From 5a007696f33b779e2de5a7000fe95836c5abbee0 Mon Sep 17 00:00:00 2001 From: MOAL Fleurian Date: Sat, 4 Jan 2020 02:00:04 +0100 Subject: [PATCH 1/4] ajout de la fonction de chargement des fixtures --- .gitignore | 2 +- api/composer.json | 1 + api/composer.lock | 134 +- api/config/bundles.php | 1 + api/src/DataFixtures/AppFixtures.php | 30 + api/symfony.lock | 15 + bookshop-api/.env | 33 + bookshop-api/.gitignore | 10 + bookshop-api/bin/console | 42 + bookshop-api/composer.json | 63 + bookshop-api/composer.lock | 4716 +++++++++++++++++ bookshop-api/config/bootstrap.php | 23 + bookshop-api/config/bundles.php | 10 + .../config/packages/api_platform.yaml | 7 + bookshop-api/config/packages/cache.yaml | 19 + bookshop-api/config/packages/doctrine.yaml | 18 + bookshop-api/config/packages/framework.yaml | 16 + bookshop-api/config/packages/nelmio_cors.yaml | 10 + .../config/packages/prod/doctrine.yaml | 20 + .../config/packages/prod/routing.yaml | 3 + bookshop-api/config/packages/routing.yaml | 3 + bookshop-api/config/packages/security.yaml | 22 + .../config/packages/test/framework.yaml | 4 + bookshop-api/config/packages/test/twig.yaml | 2 + .../config/packages/test/validator.yaml | 3 + bookshop-api/config/packages/twig.yaml | 2 + bookshop-api/config/packages/validator.yaml | 8 + bookshop-api/config/routes.yaml | 3 + bookshop-api/config/routes/annotations.yaml | 3 + bookshop-api/config/routes/api_platform.yaml | 4 + bookshop-api/config/routes/dev/framework.yaml | 3 + bookshop-api/config/services.yaml | 27 + bookshop-api/public/index.php | 27 + bookshop-api/src/Controller/.gitignore | 0 bookshop-api/src/Entity/.gitignore | 0 bookshop-api/src/Kernel.php | 54 + bookshop-api/src/Repository/.gitignore | 0 bookshop-api/symfony.lock | 333 ++ bookshop-api/templates/base.html.twig | 12 + composer.json | 5 + composer.lock | 3006 +++++++++++ vendor/autoload.php | 7 + vendor/bin/doctrine | 1 + vendor/bin/doctrine-dbal | 1 + vendor/bin/var-dump-server | 1 + vendor/composer/ClassLoader.php | 445 ++ vendor/composer/LICENSE | 21 + vendor/composer/autoload_classmap.php | 11 + vendor/composer/autoload_files.php | 15 + vendor/composer/autoload_namespaces.php | 9 + vendor/composer/autoload_psr4.php | 50 + vendor/composer/autoload_real.php | 70 + vendor/composer/autoload_static.php | 255 + vendor/composer/installed.json | 3078 +++++++++++ vendor/doctrine/annotations/CHANGELOG.md | 162 + vendor/doctrine/annotations/LICENSE | 19 + vendor/doctrine/annotations/README.md | 17 + vendor/doctrine/annotations/composer.json | 43 + .../annotations/docs/en/annotations.rst | 223 + .../doctrine/annotations/docs/en/custom.rst | 341 ++ vendor/doctrine/annotations/docs/en/index.rst | 90 + .../doctrine/annotations/docs/en/sidebar.rst | 6 + .../Common/Annotations/Annotation.php | 79 + .../Annotations/Annotation/Attribute.php | 47 + .../Annotations/Annotation/Attributes.php | 37 + .../Common/Annotations/Annotation/Enum.php | 84 + .../Annotation/IgnoreAnnotation.php | 54 + .../Annotations/Annotation/Required.php | 33 + .../Common/Annotations/Annotation/Target.php | 107 + .../Annotations/AnnotationException.php | 197 + .../Common/Annotations/AnnotationReader.php | 415 ++ .../Common/Annotations/AnnotationRegistry.php | 174 + .../Common/Annotations/CachedReader.php | 262 + .../Doctrine/Common/Annotations/DocLexer.php | 147 + .../Doctrine/Common/Annotations/DocParser.php | 1197 +++++ .../Common/Annotations/FileCacheReader.php | 290 + .../Common/Annotations/IndexedReader.php | 119 + .../Doctrine/Common/Annotations/PhpParser.php | 91 + .../Doctrine/Common/Annotations/Reader.php | 89 + .../Annotations/SimpleAnnotationReader.php | 127 + .../Common/Annotations/TokenParser.php | 194 + .../doctrine/annotations/phpbench.json.dist | 4 + vendor/doctrine/annotations/phpstan.neon | 14 + vendor/doctrine/cache/LICENSE | 19 + vendor/doctrine/cache/README.md | 10 + vendor/doctrine/cache/UPGRADE.md | 16 + vendor/doctrine/cache/composer.json | 52 + .../lib/Doctrine/Common/Cache/ApcCache.php | 105 + .../lib/Doctrine/Common/Cache/ApcuCache.php | 106 + .../lib/Doctrine/Common/Cache/ArrayCache.php | 113 + .../cache/lib/Doctrine/Common/Cache/Cache.php | 90 + .../Doctrine/Common/Cache/CacheProvider.php | 325 ++ .../lib/Doctrine/Common/Cache/ChainCache.php | 187 + .../Doctrine/Common/Cache/ClearableCache.php | 21 + .../Common/Cache/CouchbaseBucketCache.php | 197 + .../Doctrine/Common/Cache/CouchbaseCache.php | 105 + .../Doctrine/Common/Cache/ExtMongoDBCache.php | 198 + .../lib/Doctrine/Common/Cache/FileCache.php | 281 + .../Doctrine/Common/Cache/FilesystemCache.php | 102 + .../Doctrine/Common/Cache/FlushableCache.php | 18 + .../Doctrine/Common/Cache/InvalidCacheId.php | 25 + .../Common/Cache/LegacyMongoDBCache.php | 175 + .../Doctrine/Common/Cache/MemcacheCache.php | 104 + .../Doctrine/Common/Cache/MemcachedCache.php | 170 + .../Doctrine/Common/Cache/MongoDBCache.php | 112 + .../Common/Cache/MultiDeleteCache.php | 22 + .../Doctrine/Common/Cache/MultiGetCache.php | 23 + .../Common/Cache/MultiOperationCache.php | 12 + .../Doctrine/Common/Cache/MultiPutCache.php | 24 + .../Doctrine/Common/Cache/PhpFileCache.php | 118 + .../lib/Doctrine/Common/Cache/PredisCache.php | 143 + .../lib/Doctrine/Common/Cache/RedisCache.php | 181 + .../Doctrine/Common/Cache/SQLite3Cache.php | 206 + .../lib/Doctrine/Common/Cache/Version.php | 8 + .../lib/Doctrine/Common/Cache/VoidCache.php | 59 + .../Doctrine/Common/Cache/WinCacheCache.php | 106 + .../lib/Doctrine/Common/Cache/XcacheCache.php | 104 + .../Doctrine/Common/Cache/ZendDataCache.php | 69 + .../collections/.doctrine-project.json | 17 + vendor/doctrine/collections/CONTRIBUTING.md | 54 + vendor/doctrine/collections/LICENSE | 19 + vendor/doctrine/collections/README.md | 93 + vendor/doctrine/collections/composer.json | 42 + .../docs/en/derived-collections.rst | 26 + .../docs/en/expression-builder.rst | 173 + .../collections/docs/en/expressions.rst | 102 + vendor/doctrine/collections/docs/en/index.rst | 327 ++ .../collections/docs/en/lazy-collections.rst | 26 + .../doctrine/collections/docs/en/sidebar.rst | 8 + .../Collections/AbstractLazyCollection.php | 354 ++ .../Common/Collections/ArrayCollection.php | 429 ++ .../Common/Collections/Collection.php | 296 ++ .../Doctrine/Common/Collections/Criteria.php | 222 + .../Expr/ClosureExpressionVisitor.php | 257 + .../Common/Collections/Expr/Comparison.php | 80 + .../Collections/Expr/CompositeExpression.php | 68 + .../Common/Collections/Expr/Expression.php | 14 + .../Collections/Expr/ExpressionVisitor.php | 55 + .../Common/Collections/Expr/Value.php | 33 + .../Common/Collections/ExpressionBuilder.php | 180 + .../Common/Collections/Selectable.php | 31 + vendor/doctrine/collections/psalm.xml.dist | 54 + vendor/doctrine/common/.doctrine-project.json | 18 + vendor/doctrine/common/.github/FUNDING.yml | 3 + vendor/doctrine/common/LICENSE | 19 + vendor/doctrine/common/README.md | 11 + vendor/doctrine/common/UPGRADE_TO_2_1 | 39 + vendor/doctrine/common/UPGRADE_TO_2_2 | 61 + vendor/doctrine/common/composer.json | 54 + vendor/doctrine/common/composer.lock | 3433 ++++++++++++ vendor/doctrine/common/docs/en/index.rst | 10 + .../docs/en/reference/class-loading.rst | 242 + vendor/doctrine/common/humbug.json.dist | 11 + .../lib/Doctrine/Common/ClassLoader.php | 267 + .../lib/Doctrine/Common/CommonException.php | 13 + .../common/lib/Doctrine/Common/Comparable.php | 28 + .../common/lib/Doctrine/Common/Lexer.php | 25 + .../Common/Proxy/AbstractProxyFactory.php | 245 + .../lib/Doctrine/Common/Proxy/Autoloader.php | 82 + .../Exception/InvalidArgumentException.php | 106 + .../Proxy/Exception/OutOfBoundsException.php | 26 + .../Common/Proxy/Exception/ProxyException.php | 15 + .../Exception/UnexpectedValueException.php | 72 + .../lib/Doctrine/Common/Proxy/Proxy.php | 74 + .../Doctrine/Common/Proxy/ProxyDefinition.php | 53 + .../Doctrine/Common/Proxy/ProxyGenerator.php | 1062 ++++ .../lib/Doctrine/Common/Util/ClassUtils.php | 93 + .../common/lib/Doctrine/Common/Util/Debug.php | 167 + .../lib/Doctrine/Common/Util/Inflector.php | 19 + .../common/lib/Doctrine/Common/Version.php | 37 + vendor/doctrine/common/phpstan.neon.dist | 34 + .../data-fixtures/.doctrine-project.json | 24 + .../data-fixtures/.github/FUNDING.yml | 3 + vendor/doctrine/data-fixtures/CHANGELOG.md | 170 + vendor/doctrine/data-fixtures/LICENSE | 20 + vendor/doctrine/data-fixtures/README.md | 201 + vendor/doctrine/data-fixtures/UPGRADE | 17 + vendor/doctrine/data-fixtures/composer.json | 58 + .../Common/DataFixtures/AbstractFixture.php | 97 + .../DependentFixtureInterface.php | 19 + .../Listener/MongoDBReferenceListener.php | 56 + .../Event/Listener/ORMReferenceListener.php | 57 + .../Exception/CircularReferenceException.php | 11 + .../Executor/AbstractExecutor.php | 141 + .../DataFixtures/Executor/MongoDBExecutor.php | 67 + .../DataFixtures/Executor/ORMExecutor.php | 73 + .../DataFixtures/Executor/PHPCRExecutor.php | 62 + .../Common/DataFixtures/FixtureInterface.php | 18 + .../Doctrine/Common/DataFixtures/Loader.php | 438 ++ .../DataFixtures/OrderedFixtureInterface.php | 20 + .../DataFixtures/ProxyReferenceRepository.php | 131 + .../DataFixtures/Purger/MongoDBPurger.php | 58 + .../Common/DataFixtures/Purger/ORMPurger.php | 271 + .../DataFixtures/Purger/PHPCRPurger.php | 43 + .../DataFixtures/Purger/PurgerInterface.php | 18 + .../DataFixtures/ReferenceRepository.php | 255 + .../DataFixtures/SharedFixtureInterface.php | 16 + .../DataFixtures/Sorter/TopologicalSorter.php | 179 + .../Common/DataFixtures/Sorter/Vertex.php | 34 + vendor/doctrine/data-fixtures/phpcs.xml.dist | 50 + vendor/doctrine/dbal/.doctrine-project.json | 55 + vendor/doctrine/dbal/LICENSE | 19 + vendor/doctrine/dbal/README.md | 46 + vendor/doctrine/dbal/SECURITY.md | 14 + vendor/doctrine/dbal/UPGRADE.md | 452 ++ vendor/doctrine/dbal/bin/doctrine-dbal | 4 + vendor/doctrine/dbal/bin/doctrine-dbal.php | 57 + vendor/doctrine/dbal/composer.json | 66 + .../Doctrine/DBAL/Cache/ArrayStatement.php | 137 + .../Doctrine/DBAL/Cache/CacheException.php | 24 + .../Doctrine/DBAL/Cache/QueryCacheProfile.php | 121 + .../DBAL/Cache/ResultCacheStatement.php | 212 + .../dbal/lib/Doctrine/DBAL/ColumnCase.php | 32 + .../dbal/lib/Doctrine/DBAL/Configuration.php | 160 + .../dbal/lib/Doctrine/DBAL/Connection.php | 1685 ++++++ .../lib/Doctrine/DBAL/ConnectionException.php | 38 + .../Connections/MasterSlaveConnection.php | 377 ++ .../dbal/lib/Doctrine/DBAL/DBALException.php | 294 + .../dbal/lib/Doctrine/DBAL/Driver.php | 59 + .../DBAL/Driver/AbstractDB2Driver.php | 40 + .../DBAL/Driver/AbstractDriverException.php | 54 + .../DBAL/Driver/AbstractMySQLDriver.php | 218 + .../DBAL/Driver/AbstractOracleDriver.php | 97 + .../EasyConnectString.php | 121 + .../DBAL/Driver/AbstractPostgreSQLDriver.php | 138 + .../DBAL/Driver/AbstractSQLAnywhereDriver.php | 127 + .../DBAL/Driver/AbstractSQLServerDriver.php | 81 + .../DBAL/Driver/AbstractSQLiteDriver.php | 98 + .../lib/Doctrine/DBAL/Driver/Connection.php | 93 + .../Doctrine/DBAL/Driver/DriverException.php | 40 + .../Driver/DrizzlePDOMySql/Connection.php | 21 + .../DBAL/Driver/DrizzlePDOMySql/Driver.php | 59 + .../DBAL/Driver/ExceptionConverterDriver.php | 22 + .../DBAL/Driver/IBMDB2/DB2Connection.php | 186 + .../Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php | 49 + .../DBAL/Driver/IBMDB2/DB2Exception.php | 9 + .../DBAL/Driver/IBMDB2/DB2Statement.php | 454 ++ .../Doctrine/DBAL/Driver/Mysqli/Driver.php | 29 + .../DBAL/Driver/Mysqli/MysqliConnection.php | 303 ++ .../DBAL/Driver/Mysqli/MysqliException.php | 12 + .../DBAL/Driver/Mysqli/MysqliStatement.php | 453 ++ .../lib/Doctrine/DBAL/Driver/OCI8/Driver.php | 54 + .../DBAL/Driver/OCI8/OCI8Connection.php | 241 + .../DBAL/Driver/OCI8/OCI8Exception.php | 22 + .../DBAL/Driver/OCI8/OCI8Statement.php | 531 ++ .../Doctrine/DBAL/Driver/PDOConnection.php | 115 + .../lib/Doctrine/DBAL/Driver/PDOException.php | 52 + .../Doctrine/DBAL/Driver/PDOIbm/Driver.php | 59 + .../Doctrine/DBAL/Driver/PDOMySql/Driver.php | 72 + .../Doctrine/DBAL/Driver/PDOOracle/Driver.php | 62 + .../Doctrine/DBAL/Driver/PDOPgSql/Driver.php | 118 + .../Doctrine/DBAL/Driver/PDOSqlite/Driver.php | 83 + .../DBAL/Driver/PDOSqlsrv/Connection.php | 54 + .../Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php | 93 + .../DBAL/Driver/PDOSqlsrv/Statement.php | 35 + .../lib/Doctrine/DBAL/Driver/PDOStatement.php | 228 + .../DBAL/Driver/PingableConnection.php | 17 + .../Doctrine/DBAL/Driver/ResultStatement.php | 98 + .../DBAL/Driver/SQLAnywhere/Driver.php | 87 + .../SQLAnywhere/SQLAnywhereConnection.php | 215 + .../SQLAnywhere/SQLAnywhereException.php | 71 + .../SQLAnywhere/SQLAnywhereStatement.php | 364 ++ .../Doctrine/DBAL/Driver/SQLSrv/Driver.php | 58 + .../DBAL/Driver/SQLSrv/LastInsertId.php | 28 + .../DBAL/Driver/SQLSrv/SQLSrvConnection.php | 197 + .../DBAL/Driver/SQLSrv/SQLSrvException.php | 43 + .../DBAL/Driver/SQLSrv/SQLSrvStatement.php | 426 ++ .../DBAL/Driver/ServerInfoAwareConnection.php | 23 + .../lib/Doctrine/DBAL/Driver/Statement.php | 105 + .../DBAL/Driver/StatementIterator.php | 26 + .../dbal/lib/Doctrine/DBAL/DriverManager.php | 442 ++ .../DBAL/Event/ConnectionEventArgs.php | 61 + .../DBAL/Event/Listeners/MysqlSessionInit.php | 58 + .../Event/Listeners/OracleSessionInit.php | 72 + .../DBAL/Event/Listeners/SQLSessionInit.php | 41 + .../SchemaAlterTableAddColumnEventArgs.php | 81 + .../SchemaAlterTableChangeColumnEventArgs.php | 81 + .../DBAL/Event/SchemaAlterTableEventArgs.php | 68 + .../SchemaAlterTableRemoveColumnEventArgs.php | 81 + .../SchemaAlterTableRenameColumnEventArgs.php | 96 + .../Event/SchemaColumnDefinitionEventArgs.php | 108 + .../SchemaCreateTableColumnEventArgs.php | 81 + .../DBAL/Event/SchemaCreateTableEventArgs.php | 96 + .../DBAL/Event/SchemaDropTableEventArgs.php | 69 + .../Doctrine/DBAL/Event/SchemaEventArgs.php | 32 + .../Event/SchemaIndexDefinitionEventArgs.php | 92 + .../dbal/lib/Doctrine/DBAL/Events.php | 31 + .../DBAL/Exception/ConnectionException.php | 10 + .../ConstraintViolationException.php | 10 + .../DatabaseObjectExistsException.php | 14 + .../DatabaseObjectNotFoundException.php | 14 + .../DBAL/Exception/DeadlockException.php | 10 + .../DBAL/Exception/DriverException.php | 60 + ...ForeignKeyConstraintViolationException.php | 10 + .../Exception/InvalidArgumentException.php | 19 + .../Exception/InvalidFieldNameException.php | 10 + .../Exception/LockWaitTimeoutException.php | 10 + .../Exception/NonUniqueFieldNameException.php | 10 + .../NotNullConstraintViolationException.php | 10 + .../DBAL/Exception/ReadOnlyException.php | 10 + .../DBAL/Exception/RetryableException.php | 10 + .../DBAL/Exception/ServerException.php | 10 + .../DBAL/Exception/SyntaxErrorException.php | 10 + .../DBAL/Exception/TableExistsException.php | 10 + .../DBAL/Exception/TableNotFoundException.php | 10 + .../UniqueConstraintViolationException.php | 10 + .../dbal/lib/Doctrine/DBAL/FetchMode.php | 71 + .../lib/Doctrine/DBAL/Id/TableGenerator.php | 145 + .../DBAL/Id/TableGeneratorSchemaVisitor.php | 71 + .../dbal/lib/Doctrine/DBAL/LockMode.php | 21 + .../lib/Doctrine/DBAL/Logging/DebugStack.php | 56 + .../Doctrine/DBAL/Logging/EchoSQLLogger.php | 37 + .../lib/Doctrine/DBAL/Logging/LoggerChain.php | 52 + .../lib/Doctrine/DBAL/Logging/SQLLogger.php | 27 + .../dbal/lib/Doctrine/DBAL/ParameterType.php | 58 + .../DBAL/Platforms/AbstractPlatform.php | 3633 +++++++++++++ .../Doctrine/DBAL/Platforms/DB2Platform.php | 916 ++++ .../DBAL/Platforms/DateIntervalUnit.php | 28 + .../DBAL/Platforms/DrizzlePlatform.php | 621 +++ .../DBAL/Platforms/Keywords/DB2Keywords.php | 420 ++ .../Platforms/Keywords/DrizzleKeywords.php | 326 ++ .../DBAL/Platforms/Keywords/KeywordList.php | 54 + .../Platforms/Keywords/MariaDb102Keywords.php | 274 + .../DBAL/Platforms/Keywords/MsSQLKeywords.php | 21 + .../Platforms/Keywords/MySQL57Keywords.php | 263 + .../Platforms/Keywords/MySQL80Keywords.php | 65 + .../DBAL/Platforms/Keywords/MySQLKeywords.php | 265 + .../Platforms/Keywords/OracleKeywords.php | 139 + .../Keywords/PostgreSQL100Keywords.php | 19 + .../Keywords/PostgreSQL91Keywords.php | 126 + .../Keywords/PostgreSQL92Keywords.php | 29 + .../Keywords/PostgreSQL94Keywords.php | 32 + .../Platforms/Keywords/PostgreSQLKeywords.php | 113 + .../Keywords/ReservedKeywordsValidator.php | 126 + .../Keywords/SQLAnywhere11Keywords.php | 39 + .../Keywords/SQLAnywhere12Keywords.php | 48 + .../Keywords/SQLAnywhere16Keywords.php | 39 + .../Keywords/SQLAnywhereKeywords.php | 262 + .../Keywords/SQLServer2005Keywords.php | 39 + .../Keywords/SQLServer2008Keywords.php | 31 + .../Keywords/SQLServer2012Keywords.php | 37 + .../Platforms/Keywords/SQLServerKeywords.php | 209 + .../Platforms/Keywords/SQLiteKeywords.php | 147 + .../DBAL/Platforms/MariaDb1027Platform.php | 41 + .../DBAL/Platforms/MySQL57Platform.php | 71 + .../DBAL/Platforms/MySQL80Platform.php | 17 + .../Doctrine/DBAL/Platforms/MySqlPlatform.php | 1187 +++++ .../DBAL/Platforms/OraclePlatform.php | 1206 +++++ .../DBAL/Platforms/PostgreSQL100Platform.php | 33 + .../DBAL/Platforms/PostgreSQL91Platform.php | 46 + .../DBAL/Platforms/PostgreSQL92Platform.php | 69 + .../DBAL/Platforms/PostgreSQL94Platform.php | 41 + .../DBAL/Platforms/PostgreSqlPlatform.php | 1270 +++++ .../DBAL/Platforms/SQLAnywhere11Platform.php | 26 + .../DBAL/Platforms/SQLAnywhere12Platform.php | 114 + .../DBAL/Platforms/SQLAnywhere16Platform.php | 39 + .../DBAL/Platforms/SQLAnywherePlatform.php | 1512 ++++++ .../DBAL/Platforms/SQLAzurePlatform.php | 33 + .../DBAL/Platforms/SQLServer2005Platform.php | 46 + .../DBAL/Platforms/SQLServer2008Platform.php | 117 + .../DBAL/Platforms/SQLServer2012Platform.php | 143 + .../DBAL/Platforms/SQLServerPlatform.php | 1695 ++++++ .../DBAL/Platforms/SqlitePlatform.php | 1199 +++++ .../lib/Doctrine/DBAL/Platforms/TrimMode.php | 20 + .../Doctrine/DBAL/Portability/Connection.php | 132 + .../Doctrine/DBAL/Portability/Statement.php | 247 + .../Query/Expression/CompositeExpression.php | 120 + .../Query/Expression/ExpressionBuilder.php | 298 ++ .../lib/Doctrine/DBAL/Query/QueryBuilder.php | 1373 +++++ .../Doctrine/DBAL/Query/QueryException.php | 35 + .../dbal/lib/Doctrine/DBAL/SQLParserUtils.php | 291 + .../Doctrine/DBAL/SQLParserUtilsException.php | 31 + .../Doctrine/DBAL/Schema/AbstractAsset.php | 210 + .../DBAL/Schema/AbstractSchemaManager.php | 1135 ++++ .../dbal/lib/Doctrine/DBAL/Schema/Column.php | 451 ++ .../lib/Doctrine/DBAL/Schema/ColumnDiff.php | 55 + .../lib/Doctrine/DBAL/Schema/Comparator.php | 533 ++ .../lib/Doctrine/DBAL/Schema/Constraint.php | 43 + .../Doctrine/DBAL/Schema/DB2SchemaManager.php | 227 + .../DBAL/Schema/DrizzleSchemaManager.php | 103 + .../DBAL/Schema/ForeignKeyConstraint.php | 393 ++ .../lib/Doctrine/DBAL/Schema/Identifier.php | 27 + .../dbal/lib/Doctrine/DBAL/Schema/Index.php | 359 ++ .../DBAL/Schema/MySqlSchemaManager.php | 351 ++ .../DBAL/Schema/OracleSchemaManager.php | 406 ++ .../DBAL/Schema/PostgreSqlSchemaManager.php | 507 ++ .../DBAL/Schema/SQLAnywhereSchemaManager.php | 231 + .../DBAL/Schema/SQLServerSchemaManager.php | 349 ++ .../dbal/lib/Doctrine/DBAL/Schema/Schema.php | 475 ++ .../lib/Doctrine/DBAL/Schema/SchemaConfig.php | 100 + .../lib/Doctrine/DBAL/Schema/SchemaDiff.php | 168 + .../Doctrine/DBAL/Schema/SchemaException.php | 183 + .../lib/Doctrine/DBAL/Schema/Sequence.php | 139 + .../DBAL/Schema/SqliteSchemaManager.php | 545 ++ .../AbstractSchemaSynchronizer.php | 43 + .../Synchronizer/SchemaSynchronizer.php | 72 + .../SingleDatabaseSynchronizer.php | 157 + .../dbal/lib/Doctrine/DBAL/Schema/Table.php | 856 +++ .../lib/Doctrine/DBAL/Schema/TableDiff.php | 152 + .../dbal/lib/Doctrine/DBAL/Schema/View.php | 30 + .../DBAL/Schema/Visitor/AbstractVisitor.php | 47 + .../Visitor/CreateSchemaSqlCollector.php | 98 + .../Schema/Visitor/DropSchemaSqlCollector.php | 99 + .../Doctrine/DBAL/Schema/Visitor/Graphviz.php | 160 + .../DBAL/Schema/Visitor/NamespaceVisitor.php | 16 + .../Schema/Visitor/RemoveNamespacedAssets.php | 79 + .../DBAL/Schema/Visitor/SchemaDiffVisitor.php | 39 + .../Doctrine/DBAL/Schema/Visitor/Visitor.php | 46 + .../DBAL/Sharding/PoolingShardConnection.php | 249 + .../DBAL/Sharding/PoolingShardManager.php | 101 + .../SQLAzureFederationsSynchronizer.php | 271 + .../SQLAzure/SQLAzureShardManager.php | 208 + .../SQLAzure/Schema/MultiTenantVisitor.php | 148 + .../ShardChoser/MultiTenantShardChoser.php | 20 + .../DBAL/Sharding/ShardChoser/ShardChoser.php | 21 + .../Doctrine/DBAL/Sharding/ShardManager.php | 74 + .../DBAL/Sharding/ShardingException.php | 59 + .../dbal/lib/Doctrine/DBAL/Statement.php | 286 + .../Tools/Console/Command/ImportCommand.php | 138 + .../Console/Command/ReservedWordsCommand.php | 181 + .../Tools/Console/Command/RunSqlCommand.php | 74 + .../DBAL/Tools/Console/ConsoleRunner.php | 86 + .../Tools/Console/Helper/ConnectionHelper.php | 45 + .../dbal/lib/Doctrine/DBAL/Tools/Dumper.php | 182 + .../DBAL/TransactionIsolationLevel.php | 32 + .../lib/Doctrine/DBAL/Types/ArrayType.php | 72 + .../lib/Doctrine/DBAL/Types/BigIntType.php | 44 + .../lib/Doctrine/DBAL/Types/BinaryType.php | 66 + .../dbal/lib/Doctrine/DBAL/Types/BlobType.php | 66 + .../lib/Doctrine/DBAL/Types/BooleanType.php | 52 + .../DBAL/Types/ConversionException.php | 109 + .../Doctrine/DBAL/Types/DateImmutableType.php | 70 + .../Doctrine/DBAL/Types/DateIntervalType.php | 87 + .../DBAL/Types/DateTimeImmutableType.php | 75 + .../lib/Doctrine/DBAL/Types/DateTimeType.php | 68 + .../DBAL/Types/DateTimeTzImmutableType.php | 70 + .../Doctrine/DBAL/Types/DateTimeTzType.php | 75 + .../dbal/lib/Doctrine/DBAL/Types/DateType.php | 62 + .../lib/Doctrine/DBAL/Types/DecimalType.php | 35 + .../lib/Doctrine/DBAL/Types/FloatType.php | 32 + .../dbal/lib/Doctrine/DBAL/Types/GuidType.php | 35 + .../lib/Doctrine/DBAL/Types/IntegerType.php | 44 + .../lib/Doctrine/DBAL/Types/JsonArrayType.php | 46 + .../dbal/lib/Doctrine/DBAL/Types/JsonType.php | 82 + .../lib/Doctrine/DBAL/Types/ObjectType.php | 71 + .../DBAL/Types/PhpDateTimeMappingType.php | 12 + .../DBAL/Types/PhpIntegerMappingType.php | 12 + .../Doctrine/DBAL/Types/SimpleArrayType.php | 67 + .../lib/Doctrine/DBAL/Types/SmallIntType.php | 44 + .../lib/Doctrine/DBAL/Types/StringType.php | 35 + .../dbal/lib/Doctrine/DBAL/Types/TextType.php | 37 + .../Doctrine/DBAL/Types/TimeImmutableType.php | 70 + .../dbal/lib/Doctrine/DBAL/Types/TimeType.php | 62 + .../dbal/lib/Doctrine/DBAL/Types/Type.php | 384 ++ .../lib/Doctrine/DBAL/Types/TypeRegistry.php | 118 + .../dbal/lib/Doctrine/DBAL/Types/Types.php | 43 + .../DBAL/Types/VarDateTimeImmutableType.php | 67 + .../Doctrine/DBAL/Types/VarDateTimeType.php | 34 + .../dbal/lib/Doctrine/DBAL/Version.php | 33 + .../DBAL/VersionAwarePlatformDriver.php | 28 + .../doctrine-bundle/.github/FUNDING.yml | 3 + .../Command/CreateDatabaseDoctrineCommand.php | 114 + .../Command/DoctrineCommand.php | 90 + .../Command/DropDatabaseDoctrineCommand.php | 128 + .../Command/ImportMappingDoctrineCommand.php | 161 + .../ClearMetadataCacheDoctrineCommand.php | 37 + .../Proxy/ClearQueryCacheDoctrineCommand.php | 37 + .../Proxy/ClearResultCacheDoctrineCommand.php | 37 + .../Proxy/CollectionRegionDoctrineCommand.php | 33 + .../Proxy/ConvertMappingDoctrineCommand.php | 58 + .../Proxy/CreateSchemaDoctrineCommand.php | 38 + .../Command/Proxy/DelegateCommand.php | 96 + .../Command/Proxy/DoctrineCommandHelper.php | 41 + .../Proxy/DropSchemaDoctrineCommand.php | 37 + ...nsureProductionSettingsDoctrineCommand.php | 36 + .../EntityRegionCacheDoctrineCommand.php | 33 + .../Command/Proxy/ImportDoctrineCommand.php | 36 + .../Command/Proxy/InfoDoctrineCommand.php | 34 + .../Proxy/QueryRegionCacheDoctrineCommand.php | 33 + .../Command/Proxy/RunDqlDoctrineCommand.php | 53 + .../Command/Proxy/RunSqlDoctrineCommand.php | 43 + .../Proxy/UpdateSchemaDoctrineCommand.php | 37 + .../Command/Proxy/ValidateSchemaCommand.php | 36 + .../doctrine-bundle/ConnectionFactory.php | 134 + .../Controller/ProfilerController.php | 120 + .../DataCollector/DoctrineDataCollector.php | 260 + .../Dbal/BlacklistSchemaAssetFilter.php | 29 + .../Dbal/Logging/BacktraceLogger.php | 23 + .../Dbal/RegexSchemaAssetFilter.php | 25 + .../Dbal/SchemaAssetsFilterManager.php | 31 + .../Compiler/DbalSchemaFilterPass.php | 51 + .../Compiler/DoctrineOrmMappingsPass.php | 152 + .../Compiler/EntityListenerPass.php | 144 + .../ServiceRepositoryCompilerPass.php | 32 + .../Compiler/WellKnownSchemaFilterPass.php | 59 + .../DependencyInjection/Configuration.php | 702 +++ .../DependencyInjection/DoctrineExtension.php | 870 +++ .../doctrine-bundle/DoctrineBundle.php | 137 + vendor/doctrine/doctrine-bundle/LICENSE | 13 + .../doctrine-bundle/ManagerConfigurator.php | 74 + .../Mapping/ClassMetadataCollection.php | 65 + .../ContainerEntityListenerResolver.php | 103 + .../Mapping/DisconnectedMetadataFactory.php | 204 + .../Mapping/EntityListenerServiceResolver.php | 14 + vendor/doctrine/doctrine-bundle/README.md | 24 + vendor/doctrine/doctrine-bundle/Registry.php | 75 + .../Repository/ContainerRepositoryFactory.php | 86 + .../Repository/ServiceEntityRepository.php | 41 + .../ServiceEntityRepositoryInterface.php | 10 + .../doctrine-bundle/Resources/config/dbal.xml | 105 + .../Resources/config/messenger.xml | 44 + .../doctrine-bundle/Resources/config/orm.xml | 213 + .../Resources/config/schema/doctrine-1.0.xsd | 271 + .../Resources/views/Collector/db.html.twig | 528 ++ .../views/Collector/explain.html.twig | 28 + .../Resources/views/Collector/icon.svg | 4 + .../Twig/DoctrineExtension.php | 203 + .../doctrine/doctrine-bundle/UPGRADE-1.11.md | 35 + .../doctrine/doctrine-bundle/UPGRADE-1.12.md | 17 + .../doctrine/doctrine-bundle/UPGRADE-2.0.md | 63 + .../doctrine/doctrine-bundle/UPGRADE-3.0.md | 8 + vendor/doctrine/doctrine-bundle/composer.json | 75 + .../doctrine/doctrine-bundle/phpcs.xml.dist | 53 + .../.github/FUNDING.yml | 3 + .../doctrine-fixtures-bundle/.gitignore | 3 + .../doctrine-fixtures-bundle/.travis.yml | 45 + .../doctrine-fixtures-bundle/CHANGELOG-3.1.md | 14 + .../LoadDataFixturesDoctrineCommand.php | 131 + .../CompilerPass/FixturesCompilerPass.php | 39 + .../DoctrineFixturesExtension.php | 29 + .../DoctrineFixturesBundle.php | 21 + .../doctrine-fixtures-bundle/Fixture.php | 15 + .../FixtureGroupInterface.php | 19 + .../doctrine/doctrine-fixtures-bundle/LICENSE | 13 + .../Loader/SymfonyFixturesLoader.php | 150 + .../ORMFixtureInterface.php | 14 + .../doctrine-fixtures-bundle/README.markdown | 7 + .../Resources/config/services.xml | 18 + .../Resources/doc/index.rst | 293 + .../LoadDataFixturesDoctrineCommandTest.php | 43 + ...ndentOnRequiredConstructorArgsFixtures.php | 22 + .../FooBundle/DataFixtures/OtherFixtures.php | 22 + .../RequiredConstructorArgsFixtures.php | 20 + .../DataFixtures/WithDependenciesFixtures.php | 28 + .../Tests/Fixtures/FooBundle/FooBundle.php | 11 + .../Tests/IntegrationTest.php | 366 ++ .../doctrine-fixtures-bundle/UPGRADE.md | 56 + .../doctrine-fixtures-bundle/composer.json | 49 + .../doctrine-fixtures-bundle/phpcs.xml.dist | 35 + .../doctrine-fixtures-bundle/phpunit.xml.dist | 24 + .../event-manager/.doctrine-project.json | 18 + vendor/doctrine/event-manager/LICENSE | 19 + vendor/doctrine/event-manager/README.md | 13 + vendor/doctrine/event-manager/composer.json | 50 + .../lib/Doctrine/Common/EventArgs.php | 45 + .../lib/Doctrine/Common/EventManager.php | 132 + .../lib/Doctrine/Common/EventSubscriber.php | 21 + vendor/doctrine/inflector/LICENSE | 19 + vendor/doctrine/inflector/README.md | 6 + vendor/doctrine/inflector/composer.json | 32 + vendor/doctrine/inflector/docs/en/index.rst | 125 + .../Doctrine/Common/Inflector/Inflector.php | 492 ++ .../instantiator/.doctrine-project.json | 26 + .../doctrine/instantiator/.github/FUNDING.yml | 3 + vendor/doctrine/instantiator/CONTRIBUTING.md | 35 + vendor/doctrine/instantiator/LICENSE | 19 + vendor/doctrine/instantiator/README.md | 39 + vendor/doctrine/instantiator/composer.json | 47 + .../doctrine/instantiator/docs/en/index.rst | 68 + .../doctrine/instantiator/docs/en/sidebar.rst | 4 + vendor/doctrine/instantiator/phpbench.json | 4 + vendor/doctrine/instantiator/phpcs.xml.dist | 35 + .../doctrine/instantiator/phpstan.neon.dist | 19 + .../Exception/ExceptionInterface.php | 12 + .../Exception/InvalidArgumentException.php | 37 + .../Exception/UnexpectedValueException.php | 48 + .../Doctrine/Instantiator/Instantiator.php | 203 + .../Instantiator/InstantiatorInterface.php | 20 + vendor/doctrine/lexer/LICENSE | 19 + vendor/doctrine/lexer/README.md | 9 + vendor/doctrine/lexer/composer.json | 41 + .../Doctrine/Common/Lexer/AbstractLexer.php | 328 ++ vendor/doctrine/orm/.scrutinizer.yml | 34 + vendor/doctrine/orm/LICENSE | 19 + vendor/doctrine/orm/README.md | 26 + vendor/doctrine/orm/SECURITY.md | 18 + vendor/doctrine/orm/UPGRADE.md | 865 +++ vendor/doctrine/orm/bin/doctrine | 4 + vendor/doctrine/orm/bin/doctrine-pear.php | 50 + vendor/doctrine/orm/bin/doctrine.bat | 9 + vendor/doctrine/orm/bin/doctrine.php | 69 + vendor/doctrine/orm/composer.json | 57 + vendor/doctrine/orm/composer.lock | 2744 ++++++++++ vendor/doctrine/orm/docs/LICENSE.md | 363 ++ vendor/doctrine/orm/docs/README.md | 18 + vendor/doctrine/orm/docs/bin/generate-docs.sh | 10 + .../orm/docs/bin/install-dependencies.sh | 2 + vendor/doctrine/orm/docs/en/Makefile | 89 + .../orm/docs/en/_exts/configurationblock.py | 93 + vendor/doctrine/orm/docs/en/conf.py | 201 + ...-conversion-using-custom-mapping-types.rst | 256 + .../orm/docs/en/cookbook/aggregate-fields.rst | 376 ++ .../docs/en/cookbook/custom-mapping-types.rst | 101 + .../docs/en/cookbook/decorator-pattern.rst | 273 + .../docs/en/cookbook/dql-custom-walkers.rst | 217 + .../cookbook/dql-user-defined-functions.rst | 251 + .../docs/en/cookbook/entities-in-session.rst | 68 + ...menting-arrayaccess-for-domain-objects.rst | 112 + ...nting-the-notify-changetracking-policy.rst | 72 + .../cookbook/implementing-wakeup-or-clone.rst | 78 + .../orm/docs/en/cookbook/mysql-enums.rst | 199 + .../resolve-target-entity-listener.rst | 142 + .../docs/en/cookbook/sql-table-prefixes.rst | 86 + .../strategy-cookbook-introduction.rst | 254 + .../en/cookbook/validation-of-entities.rst | 137 + .../en/cookbook/working-with-datetime.rst | 197 + vendor/doctrine/orm/docs/en/index.rst | 128 + vendor/doctrine/orm/docs/en/make.bat | 113 + .../en/reference/advanced-configuration.rst | 470 ++ .../en/reference/annotations-reference.rst | 1327 +++++ .../orm/docs/en/reference/architecture.rst | 197 + .../docs/en/reference/association-mapping.rst | 1130 ++++ .../orm/docs/en/reference/basic-mapping.rst | 504 ++ .../docs/en/reference/batch-processing.rst | 196 + .../orm/docs/en/reference/best-practices.rst | 111 + .../orm/docs/en/reference/caching.rst | 477 ++ .../en/reference/change-tracking-policies.rst | 151 + .../orm/docs/en/reference/configuration.rst | 144 + .../reference/dql-doctrine-query-language.rst | 1775 +++++++ .../doctrine/orm/docs/en/reference/events.rst | 989 ++++ vendor/doctrine/orm/docs/en/reference/faq.rst | 233 + .../orm/docs/en/reference/filters.rst | 93 + .../en/reference/improving-performance.rst | 73 + .../docs/en/reference/inheritance-mapping.rst | 606 +++ .../orm/docs/en/reference/installation.rst | 4 + .../limitations-and-known-issues.rst | 203 + .../docs/en/reference/metadata-drivers.rst | 194 + .../orm/docs/en/reference/namingstrategy.rst | 137 + .../orm/docs/en/reference/native-sql.rst | 905 ++++ .../orm/docs/en/reference/partial-objects.rst | 90 + .../orm/docs/en/reference/php-mapping.rst | 325 ++ .../orm/docs/en/reference/query-builder.rst | 584 ++ .../docs/en/reference/second-level-cache.rst | 731 +++ .../orm/docs/en/reference/security.rst | 151 + .../doctrine/orm/docs/en/reference/tools.rst | 520 ++ .../transactions-and-concurrency.rst | 409 ++ .../en/reference/unitofwork-associations.rst | 60 + .../orm/docs/en/reference/unitofwork.rst | 201 + .../reference/working-with-associations.rst | 728 +++ .../en/reference/working-with-objects.rst | 865 +++ .../orm/docs/en/reference/xml-mapping.rst | 782 +++ .../orm/docs/en/reference/yaml-mapping.rst | 158 + vendor/doctrine/orm/docs/en/sidebar.rst | 83 + vendor/doctrine/orm/docs/en/toc.rst | 86 + .../en/tutorials/composite-primary-keys.rst | 375 ++ .../orm/docs/en/tutorials/embeddables.rst | 179 + .../en/tutorials/extra-lazy-associations.rst | 86 + .../en/tutorials/getting-started-database.rst | 27 + .../en/tutorials/getting-started-models.rst | 24 + .../orm/docs/en/tutorials/getting-started.rst | 1618 ++++++ .../en/tutorials/ordered-associations.rst | 110 + ...eld-association-mappings-in-subclasses.rst | 92 + .../orm/docs/en/tutorials/pagination.rst | 43 + .../working-with-indexed-associations.rst | 296 ++ vendor/doctrine/orm/doctrine-mapping.xsd | 622 +++ .../orm/lib/Doctrine/ORM/AbstractQuery.php | 1165 ++++ .../doctrine/orm/lib/Doctrine/ORM/Cache.php | 178 + .../ORM/Cache/AssociationCacheEntry.php | 68 + .../Doctrine/ORM/Cache/CacheConfiguration.php | 128 + .../orm/lib/Doctrine/ORM/Cache/CacheEntry.php | 36 + .../lib/Doctrine/ORM/Cache/CacheException.php | 73 + .../lib/Doctrine/ORM/Cache/CacheFactory.php | 112 + .../orm/lib/Doctrine/ORM/Cache/CacheKey.php | 38 + .../ORM/Cache/CollectionCacheEntry.php | 59 + .../Doctrine/ORM/Cache/CollectionCacheKey.php | 66 + .../Doctrine/ORM/Cache/CollectionHydrator.php | 52 + .../Doctrine/ORM/Cache/ConcurrentRegion.php | 57 + .../lib/Doctrine/ORM/Cache/DefaultCache.php | 342 ++ .../ORM/Cache/DefaultCacheFactory.php | 275 + .../ORM/Cache/DefaultCollectionHydrator.php | 104 + .../ORM/Cache/DefaultEntityHydrator.php | 205 + .../Doctrine/ORM/Cache/DefaultQueryCache.php | 478 ++ .../Doctrine/ORM/Cache/EntityCacheEntry.php | 88 + .../lib/Doctrine/ORM/Cache/EntityCacheKey.php | 57 + .../lib/Doctrine/ORM/Cache/EntityHydrator.php | 49 + .../orm/lib/Doctrine/ORM/Cache/Lock.php | 58 + .../lib/Doctrine/ORM/Cache/LockException.php | 32 + .../ORM/Cache/Logging/CacheLogger.php | 106 + .../ORM/Cache/Logging/CacheLoggerChain.php | 156 + .../Cache/Logging/StatisticsCacheLogger.php | 251 + .../lib/Doctrine/ORM/Cache/MultiGetRegion.php | 42 + .../ORM/Cache/Persister/CachedPersister.php | 46 + .../AbstractCollectionPersister.php | 313 ++ .../Collection/CachedCollectionPersister.php | 65 + ...rictReadWriteCachedCollectionPersister.php | 104 + .../ReadOnlyCachedCollectionPersister.php | 44 + .../ReadWriteCachedCollectionPersister.php | 134 + .../Entity/AbstractEntityPersister.php | 652 +++ .../Entity/CachedEntityPersister.php | 47 + ...onStrictReadWriteCachedEntityPersister.php | 117 + .../Entity/ReadOnlyCachedEntityPersister.php | 41 + .../Entity/ReadWriteCachedEntityPersister.php | 143 + .../orm/lib/Doctrine/ORM/Cache/QueryCache.php | 62 + .../Doctrine/ORM/Cache/QueryCacheEntry.php | 64 + .../lib/Doctrine/ORM/Cache/QueryCacheKey.php | 71 + .../ORM/Cache/QueryCacheValidator.php | 40 + .../orm/lib/Doctrine/ORM/Cache/Region.php | 84 + .../Cache/Region/DefaultMultiGetRegion.php | 82 + .../ORM/Cache/Region/DefaultRegion.php | 166 + .../ORM/Cache/Region/FileLockRegion.php | 265 + .../ORM/Cache/Region/UpdateTimestampCache.php | 42 + .../ORM/Cache/RegionsConfiguration.php | 134 + .../ORM/Cache/TimestampCacheEntry.php | 59 + .../Doctrine/ORM/Cache/TimestampCacheKey.php | 38 + .../Cache/TimestampQueryCacheValidator.php | 74 + .../Doctrine/ORM/Cache/TimestampRegion.php | 39 + .../orm/lib/Doctrine/ORM/Configuration.php | 920 ++++ .../ORM/Decorator/EntityManagerDecorator.php | 278 + .../orm/lib/Doctrine/ORM/EntityManager.php | 960 ++++ .../Doctrine/ORM/EntityManagerInterface.php | 298 ++ .../Doctrine/ORM/EntityNotFoundException.php | 51 + .../orm/lib/Doctrine/ORM/EntityRepository.php | 313 ++ .../Doctrine/ORM/Event/LifecycleEventArgs.php | 54 + .../Doctrine/ORM/Event/ListenersInvoker.php | 120 + .../ORM/Event/LoadClassMetadataEventArgs.php | 46 + .../OnClassMetadataNotFoundEventArgs.php | 86 + .../Doctrine/ORM/Event/OnClearEventArgs.php | 86 + .../Doctrine/ORM/Event/OnFlushEventArgs.php | 61 + .../Doctrine/ORM/Event/PostFlushEventArgs.php | 58 + .../Doctrine/ORM/Event/PreFlushEventArgs.php | 58 + .../Doctrine/ORM/Event/PreUpdateEventArgs.php | 137 + .../doctrine/orm/lib/Doctrine/ORM/Events.php | 167 + .../Doctrine/ORM/Id/AbstractIdGenerator.php | 49 + .../lib/Doctrine/ORM/Id/AssignedGenerator.php | 66 + .../ORM/Id/BigIntegerIdentityGenerator.php | 66 + .../lib/Doctrine/ORM/Id/IdentityGenerator.php | 65 + .../lib/Doctrine/ORM/Id/SequenceGenerator.php | 132 + .../lib/Doctrine/ORM/Id/TableGenerator.php | 109 + .../orm/lib/Doctrine/ORM/Id/UuidGenerator.php | 42 + .../ORM/Internal/CommitOrderCalculator.php | 195 + .../Internal/Hydration/AbstractHydrator.php | 527 ++ .../ORM/Internal/Hydration/ArrayHydrator.php | 307 ++ .../Internal/Hydration/HydrationException.php | 105 + .../ORM/Internal/Hydration/IterableResult.php | 110 + .../ORM/Internal/Hydration/ObjectHydrator.php | 593 +++ .../ORM/Internal/Hydration/ScalarHydrator.php | 54 + .../Hydration/SimpleObjectHydrator.php | 154 + .../Hydration/SingleScalarHydrator.php | 58 + .../ORM/Internal/HydrationCompleteHandler.php | 103 + .../Doctrine/ORM/LazyCriteriaCollection.php | 133 + .../lib/Doctrine/ORM/Mapping/Annotation.php | 24 + .../ORM/Mapping/AnsiQuoteStrategy.php | 96 + .../ORM/Mapping/AssociationOverride.php | 69 + .../ORM/Mapping/AssociationOverrides.php | 39 + .../ORM/Mapping/AttributeOverride.php | 46 + .../ORM/Mapping/AttributeOverrides.php | 39 + .../Mapping/Builder/AssociationBuilder.php | 244 + .../Mapping/Builder/ClassMetadataBuilder.php | 553 ++ .../ORM/Mapping/Builder/EmbeddedBuilder.php | 80 + .../Mapping/Builder/EntityListenerBuilder.php | 72 + .../ORM/Mapping/Builder/FieldBuilder.php | 296 ++ .../Builder/ManyToManyAssociationBuilder.php | 101 + .../Builder/OneToManyAssociationBuilder.php | 70 + .../orm/lib/Doctrine/ORM/Mapping/Cache.php | 44 + .../ORM/Mapping/ChangeTrackingPolicy.php | 36 + .../Doctrine/ORM/Mapping/ClassMetadata.php | 29 + .../ORM/Mapping/ClassMetadataFactory.php | 797 +++ .../ORM/Mapping/ClassMetadataInfo.php | 3402 ++++++++++++ .../orm/lib/Doctrine/ORM/Mapping/Column.php | 76 + .../lib/Doctrine/ORM/Mapping/ColumnResult.php | 40 + .../ORM/Mapping/CustomIdGenerator.php | 32 + .../Mapping/DefaultEntityListenerResolver.php | 75 + .../ORM/Mapping/DefaultNamingStrategy.php | 94 + .../ORM/Mapping/DefaultQuoteStrategy.php | 164 + .../ORM/Mapping/DiscriminatorColumn.php | 54 + .../Doctrine/ORM/Mapping/DiscriminatorMap.php | 32 + .../ORM/Mapping/Driver/AnnotationDriver.php | 673 +++ .../ORM/Mapping/Driver/DatabaseDriver.php | 557 ++ .../Mapping/Driver/DoctrineAnnotations.php | 69 + .../ORM/Mapping/Driver/DriverChain.php | 31 + .../Doctrine/ORM/Mapping/Driver/PHPDriver.php | 31 + .../Mapping/Driver/SimplifiedXmlDriver.php | 43 + .../Mapping/Driver/SimplifiedYamlDriver.php | 43 + .../ORM/Mapping/Driver/StaticPHPDriver.php | 31 + .../Doctrine/ORM/Mapping/Driver/XmlDriver.php | 881 +++ .../ORM/Mapping/Driver/YamlDriver.php | 819 +++ .../lib/Doctrine/ORM/Mapping/Embeddable.php | 28 + .../orm/lib/Doctrine/ORM/Mapping/Embedded.php | 38 + .../orm/lib/Doctrine/ORM/Mapping/Entity.php | 37 + .../ORM/Mapping/EntityListenerResolver.php | 55 + .../Doctrine/ORM/Mapping/EntityListeners.php | 41 + .../lib/Doctrine/ORM/Mapping/EntityResult.php | 56 + .../lib/Doctrine/ORM/Mapping/FieldResult.php | 46 + .../Doctrine/ORM/Mapping/GeneratedValue.php | 36 + .../ORM/Mapping/HasLifecycleCallbacks.php | 28 + .../orm/lib/Doctrine/ORM/Mapping/Id.php | 28 + .../orm/lib/Doctrine/ORM/Mapping/Index.php | 47 + .../Doctrine/ORM/Mapping/InheritanceType.php | 36 + .../lib/Doctrine/ORM/Mapping/JoinColumn.php | 64 + .../lib/Doctrine/ORM/Mapping/JoinColumns.php | 32 + .../lib/Doctrine/ORM/Mapping/JoinTable.php | 47 + .../lib/Doctrine/ORM/Mapping/ManyToMany.php | 66 + .../lib/Doctrine/ORM/Mapping/ManyToOne.php | 51 + .../Doctrine/ORM/Mapping/MappedSuperclass.php | 32 + .../Doctrine/ORM/Mapping/MappingException.php | 823 +++ .../ORM/Mapping/NamedNativeQueries.php | 40 + .../Doctrine/ORM/Mapping/NamedNativeQuery.php | 61 + .../lib/Doctrine/ORM/Mapping/NamedQueries.php | 32 + .../lib/Doctrine/ORM/Mapping/NamedQuery.php | 37 + .../Doctrine/ORM/Mapping/NamingStrategy.php | 100 + .../lib/Doctrine/ORM/Mapping/OneToMany.php | 61 + .../orm/lib/Doctrine/ORM/Mapping/OneToOne.php | 61 + .../orm/lib/Doctrine/ORM/Mapping/OrderBy.php | 32 + .../orm/lib/Doctrine/ORM/Mapping/PostLoad.php | 28 + .../lib/Doctrine/ORM/Mapping/PostPersist.php | 28 + .../lib/Doctrine/ORM/Mapping/PostRemove.php | 28 + .../lib/Doctrine/ORM/Mapping/PostUpdate.php | 28 + .../orm/lib/Doctrine/ORM/Mapping/PreFlush.php | 28 + .../lib/Doctrine/ORM/Mapping/PrePersist.php | 28 + .../lib/Doctrine/ORM/Mapping/PreRemove.php | 28 + .../lib/Doctrine/ORM/Mapping/PreUpdate.php | 28 + .../Doctrine/ORM/Mapping/QuoteStrategy.php | 119 + .../Reflection/ReflectionPropertiesGetter.php | 163 + .../Mapping/ReflectionEmbeddedProperty.php | 101 + .../ORM/Mapping/SequenceGenerator.php | 42 + .../ORM/Mapping/SqlResultSetMapping.php | 54 + .../ORM/Mapping/SqlResultSetMappings.php | 40 + .../orm/lib/Doctrine/ORM/Mapping/Table.php | 52 + .../ORM/Mapping/UnderscoreNamingStrategy.php | 166 + .../Doctrine/ORM/Mapping/UniqueConstraint.php | 42 + .../orm/lib/Doctrine/ORM/Mapping/Version.php | 28 + .../orm/lib/Doctrine/ORM/NativeQuery.php | 92 + .../lib/Doctrine/ORM/NoResultException.php | 37 + .../Doctrine/ORM/NonUniqueResultException.php | 36 + .../orm/lib/Doctrine/ORM/ORMException.php | 333 ++ .../ORM/ORMInvalidArgumentException.php | 272 + .../Doctrine/ORM/OptimisticLockException.php | 91 + .../lib/Doctrine/ORM/PersistentCollection.php | 734 +++ .../AbstractCollectionPersister.php | 95 + .../Collection/CollectionPersister.php | 122 + .../Collection/ManyToManyPersister.php | 787 +++ .../Collection/OneToManyPersister.php | 291 + .../AbstractEntityInheritancePersister.php | 99 + .../Entity/BasicEntityPersister.php | 2095 ++++++++ .../Entity/CachedPersisterContext.php | 102 + .../ORM/Persisters/Entity/EntityPersister.php | 330 ++ .../Entity/JoinedSubclassPersister.php | 616 +++ .../Entity/SingleTablePersister.php | 192 + .../ORM/Persisters/PersisterException.php | 40 + .../ORM/Persisters/SqlExpressionVisitor.php | 122 + .../ORM/Persisters/SqlValueVisitor.php | 128 + .../Doctrine/ORM/PessimisticLockException.php | 40 + .../orm/lib/Doctrine/ORM/Proxy/Autoloader.php | 29 + .../orm/lib/Doctrine/ORM/Proxy/Proxy.php | 34 + .../lib/Doctrine/ORM/Proxy/ProxyFactory.php | 213 + .../doctrine/orm/lib/Doctrine/ORM/Query.php | 794 +++ .../Doctrine/ORM/Query/AST/ASTException.php | 38 + .../ORM/Query/AST/AggregateExpression.php | 69 + .../ORM/Query/AST/ArithmeticExpression.php | 66 + .../ORM/Query/AST/ArithmeticFactor.php | 78 + .../Doctrine/ORM/Query/AST/ArithmeticTerm.php | 53 + .../ORM/Query/AST/BetweenExpression.php | 72 + .../ORM/Query/AST/CoalesceExpression.php | 55 + .../Query/AST/CollectionMemberExpression.php | 63 + .../ORM/Query/AST/ComparisonExpression.php | 72 + .../ORM/Query/AST/ConditionalExpression.php | 53 + .../ORM/Query/AST/ConditionalFactor.php | 58 + .../ORM/Query/AST/ConditionalPrimary.php | 66 + .../ORM/Query/AST/ConditionalTerm.php | 52 + .../Doctrine/ORM/Query/AST/DeleteClause.php | 58 + .../ORM/Query/AST/DeleteStatement.php | 58 + .../EmptyCollectionComparisonExpression.php | 58 + .../ORM/Query/AST/ExistsExpression.php | 58 + .../lib/Doctrine/ORM/Query/AST/FromClause.php | 54 + .../ORM/Query/AST/Functions/AbsFunction.php | 66 + .../ORM/Query/AST/Functions/AvgFunction.php | 54 + .../Query/AST/Functions/BitAndFunction.php | 66 + .../ORM/Query/AST/Functions/BitOrFunction.php | 66 + .../Query/AST/Functions/ConcatFunction.php | 85 + .../ORM/Query/AST/Functions/CountFunction.php | 54 + .../AST/Functions/CurrentDateFunction.php | 56 + .../AST/Functions/CurrentTimeFunction.php | 56 + .../Functions/CurrentTimestampFunction.php | 56 + .../Query/AST/Functions/DateAddFunction.php | 109 + .../Query/AST/Functions/DateDiffFunction.php | 66 + .../Query/AST/Functions/DateSubFunction.php | 85 + .../ORM/Query/AST/Functions/FunctionNode.php | 73 + .../Query/AST/Functions/IdentityFunction.php | 113 + .../Query/AST/Functions/LengthFunction.php | 63 + .../Query/AST/Functions/LocateFunction.php | 86 + .../ORM/Query/AST/Functions/LowerFunction.php | 63 + .../ORM/Query/AST/Functions/MaxFunction.php | 54 + .../ORM/Query/AST/Functions/MinFunction.php | 54 + .../ORM/Query/AST/Functions/ModFunction.php | 76 + .../ORM/Query/AST/Functions/SizeFunction.php | 125 + .../ORM/Query/AST/Functions/SqrtFunction.php | 66 + .../Query/AST/Functions/SubstringFunction.php | 91 + .../ORM/Query/AST/Functions/SumFunction.php | 54 + .../ORM/Query/AST/Functions/TrimFunction.php | 161 + .../ORM/Query/AST/Functions/UpperFunction.php | 63 + .../ORM/Query/AST/GeneralCaseExpression.php | 62 + .../Doctrine/ORM/Query/AST/GroupByClause.php | 53 + .../Doctrine/ORM/Query/AST/HavingClause.php | 53 + .../AST/IdentificationVariableDeclaration.php | 67 + .../Doctrine/ORM/Query/AST/InExpression.php | 67 + .../lib/Doctrine/ORM/Query/AST/IndexBy.php | 53 + .../Doctrine/ORM/Query/AST/InputParameter.php | 66 + .../ORM/Query/AST/InstanceOfExpression.php | 64 + .../orm/lib/Doctrine/ORM/Query/AST/Join.php | 70 + .../Query/AST/JoinAssociationDeclaration.php | 65 + .../AST/JoinAssociationPathExpression.php | 60 + .../ORM/Query/AST/JoinClassPathExpression.php | 59 + .../ORM/Query/AST/JoinVariableDeclaration.php | 61 + .../Doctrine/ORM/Query/AST/LikeExpression.php | 71 + .../lib/Doctrine/ORM/Query/AST/Literal.php | 55 + .../ORM/Query/AST/NewObjectExpression.php | 58 + .../orm/lib/Doctrine/ORM/Query/AST/Node.php | 103 + .../Query/AST/NullComparisonExpression.php | 58 + .../ORM/Query/AST/NullIfExpression.php | 62 + .../Doctrine/ORM/Query/AST/OrderByClause.php | 53 + .../Doctrine/ORM/Query/AST/OrderByItem.php | 75 + .../ORM/Query/AST/ParenthesisExpression.php | 51 + .../ORM/Query/AST/PartialObjectExpression.php | 43 + .../Doctrine/ORM/Query/AST/PathExpression.php | 81 + .../ORM/Query/AST/QuantifiedExpression.php | 81 + .../Query/AST/RangeVariableDeclaration.php | 67 + .../Doctrine/ORM/Query/AST/SelectClause.php | 60 + .../ORM/Query/AST/SelectExpression.php | 68 + .../ORM/Query/AST/SelectStatement.php | 80 + .../Query/AST/SimpleArithmeticExpression.php | 53 + .../ORM/Query/AST/SimpleCaseExpression.php | 69 + .../ORM/Query/AST/SimpleSelectClause.php | 60 + .../ORM/Query/AST/SimpleSelectExpression.php | 59 + .../ORM/Query/AST/SimpleWhenClause.php | 62 + .../lib/Doctrine/ORM/Query/AST/Subselect.php | 80 + .../ORM/Query/AST/SubselectFromClause.php | 53 + ...electIdentificationVariableDeclaration.php | 52 + .../Doctrine/ORM/Query/AST/UpdateClause.php | 65 + .../lib/Doctrine/ORM/Query/AST/UpdateItem.php | 62 + .../ORM/Query/AST/UpdateStatement.php | 58 + .../lib/Doctrine/ORM/Query/AST/WhenClause.php | 62 + .../Doctrine/ORM/Query/AST/WhereClause.php | 53 + .../ORM/Query/Exec/AbstractSqlExecutor.php | 86 + .../Query/Exec/MultiTableDeleteExecutor.php | 146 + .../Query/Exec/MultiTableUpdateExecutor.php | 205 + .../ORM/Query/Exec/SingleSelectExecutor.php | 52 + .../Exec/SingleTableDeleteUpdateExecutor.php | 57 + .../orm/lib/Doctrine/ORM/Query/Expr.php | 674 +++ .../orm/lib/Doctrine/ORM/Query/Expr/Andx.php | 55 + .../orm/lib/Doctrine/ORM/Query/Expr/Base.php | 124 + .../Doctrine/ORM/Query/Expr/Comparison.php | 100 + .../lib/Doctrine/ORM/Query/Expr/Composite.php | 71 + .../orm/lib/Doctrine/ORM/Query/Expr/From.php | 92 + .../orm/lib/Doctrine/ORM/Query/Expr/Func.php | 78 + .../lib/Doctrine/ORM/Query/Expr/GroupBy.php | 50 + .../orm/lib/Doctrine/ORM/Query/Expr/Join.php | 145 + .../lib/Doctrine/ORM/Query/Expr/Literal.php | 50 + .../orm/lib/Doctrine/ORM/Query/Expr/Math.php | 107 + .../lib/Doctrine/ORM/Query/Expr/OrderBy.php | 104 + .../orm/lib/Doctrine/ORM/Query/Expr/Orx.php | 55 + .../lib/Doctrine/ORM/Query/Expr/Select.php | 55 + .../Doctrine/ORM/Query/Filter/SQLFilter.php | 155 + .../Doctrine/ORM/Query/FilterCollection.php | 225 + .../orm/lib/Doctrine/ORM/Query/Lexer.php | 222 + .../orm/lib/Doctrine/ORM/Query/Parameter.php | 122 + .../ORM/Query/ParameterTypeInferer.php | 72 + .../orm/lib/Doctrine/ORM/Query/Parser.php | 3539 +++++++++++++ .../lib/Doctrine/ORM/Query/ParserResult.php | 145 + .../orm/lib/Doctrine/ORM/Query/Printer.php | 98 + .../lib/Doctrine/ORM/Query/QueryException.php | 270 + .../ORM/Query/QueryExpressionVisitor.php | 224 + .../Doctrine/ORM/Query/ResultSetMapping.php | 586 ++ .../ORM/Query/ResultSetMappingBuilder.php | 473 ++ .../orm/lib/Doctrine/ORM/Query/SqlWalker.php | 2324 ++++++++ .../orm/lib/Doctrine/ORM/Query/TreeWalker.php | 479 ++ .../Doctrine/ORM/Query/TreeWalkerAdapter.php | 440 ++ .../Doctrine/ORM/Query/TreeWalkerChain.php | 575 ++ .../ORM/Query/TreeWalkerChainIterator.php | 138 + .../orm/lib/Doctrine/ORM/QueryBuilder.php | 1513 ++++++ .../Repository/DefaultRepositoryFactory.php | 70 + .../ORM/Repository/RepositoryFactory.php | 41 + .../Tools/AttachEntityListenersListener.php | 79 + .../ClearCache/CollectionRegionCommand.php | 149 + .../ClearCache/EntityRegionCommand.php | 140 + .../Command/ClearCache/MetadataCommand.php | 112 + .../Command/ClearCache/QueryCommand.php | 111 + .../Command/ClearCache/QueryRegionCommand.php | 131 + .../Command/ClearCache/ResultCommand.php | 112 + .../Command/ConvertDoctrine1SchemaCommand.php | 214 + .../Console/Command/ConvertMappingCommand.php | 186 + .../EnsureProductionSettingsCommand.php | 78 + .../Command/GenerateEntitiesCommand.php | 147 + .../Command/GenerateProxiesCommand.php | 110 + .../Command/GenerateRepositoriesCommand.php | 119 + .../ORM/Tools/Console/Command/InfoCommand.php | 101 + .../Command/MappingDescribeCommand.php | 284 + .../Tools/Console/Command/RunDqlCommand.php | 116 + .../Command/SchemaTool/AbstractCommand.php | 72 + .../Command/SchemaTool/CreateCommand.php | 90 + .../Command/SchemaTool/DropCommand.php | 130 + .../Command/SchemaTool/UpdateCommand.php | 159 + .../Console/Command/ValidateSchemaCommand.php | 100 + .../ORM/Tools/Console/ConsoleRunner.php | 143 + .../Console/Helper/EntityManagerHelper.php | 71 + .../ORM/Tools/Console/MetadataFilter.php | 102 + .../ORM/Tools/ConvertDoctrine1Schema.php | 344 ++ .../ORM/Tools/DebugUnitOfWorkListener.php | 185 + .../DisconnectedClassMetadataFactory.php | 48 + .../Doctrine/ORM/Tools/EntityGenerator.php | 1906 +++++++ .../ORM/Tools/EntityRepositoryGenerator.php | 182 + .../Tools/Event/GenerateSchemaEventArgs.php | 71 + .../Event/GenerateSchemaTableEventArgs.php | 86 + .../Tools/Export/ClassMetadataExporter.php | 86 + .../Tools/Export/Driver/AbstractExporter.php | 275 + .../Export/Driver/AnnotationExporter.php | 82 + .../ORM/Tools/Export/Driver/PhpExporter.php | 202 + .../ORM/Tools/Export/Driver/XmlExporter.php | 496 ++ .../ORM/Tools/Export/Driver/YamlExporter.php | 268 + .../ORM/Tools/Export/ExportException.php | 58 + .../Tools/Pagination/CountOutputWalker.php | 154 + .../ORM/Tools/Pagination/CountWalker.php | 94 + .../Pagination/LimitSubqueryOutputWalker.php | 605 +++ .../Tools/Pagination/LimitSubqueryWalker.php | 177 + .../ORM/Tools/Pagination/Paginator.php | 289 + .../Pagination/RowNumberOverFunction.php | 62 + .../ORM/Tools/Pagination/WhereInWalker.php | 184 + .../ORM/Tools/ResolveTargetEntityListener.php | 144 + .../orm/lib/Doctrine/ORM/Tools/SchemaTool.php | 913 ++++ .../Doctrine/ORM/Tools/SchemaValidator.php | 273 + .../orm/lib/Doctrine/ORM/Tools/Setup.php | 195 + .../orm/lib/Doctrine/ORM/Tools/ToolEvents.php | 42 + .../lib/Doctrine/ORM/Tools/ToolsException.php | 46 + .../ORM/TransactionRequiredException.php | 40 + .../ORM/UnexpectedResultException.php | 30 + .../orm/lib/Doctrine/ORM/UnitOfWork.php | 3628 +++++++++++++ .../HierarchyDiscriminatorResolver.php | 41 + .../ORM/Utility/IdentifierFlattener.php | 102 + .../Doctrine/ORM/Utility/PersisterHelper.php | 135 + .../doctrine/orm/lib/Doctrine/ORM/Version.php | 57 + vendor/doctrine/orm/phpbench.json | 15 + vendor/doctrine/orm/phpstan.neon | 4 + .../persistence/.doctrine-project.json | 24 + vendor/doctrine/persistence/LICENSE | 19 + vendor/doctrine/persistence/README.md | 13 + vendor/doctrine/persistence/UPGRADE-1.2.md | 6 + vendor/doctrine/persistence/composer.json | 54 + .../Doctrine/Common/NotifyPropertyChanged.php | 31 + .../Persistence/AbstractManagerRegistry.php | 31 + .../Common/Persistence/ConnectionRegistry.php | 31 + .../Persistence/Event/LifecycleEventArgs.php | 31 + .../Event/LoadClassMetadataEventArgs.php | 31 + .../Persistence/Event/ManagerEventArgs.php | 31 + .../Persistence/Event/OnClearEventArgs.php | 31 + .../Persistence/Event/PreUpdateEventArgs.php | 31 + .../Common/Persistence/ManagerRegistry.php | 31 + .../Mapping/AbstractClassMetadataFactory.php | 31 + .../Persistence/Mapping/ClassMetadata.php | 31 + .../Mapping/ClassMetadataFactory.php | 31 + .../Mapping/Driver/AnnotationDriver.php | 31 + .../Mapping/Driver/DefaultFileLocator.php | 31 + .../Persistence/Mapping/Driver/FileDriver.php | 31 + .../Mapping/Driver/FileLocator.php | 31 + .../Mapping/Driver/MappingDriver.php | 31 + .../Mapping/Driver/MappingDriverChain.php | 31 + .../Persistence/Mapping/Driver/PHPDriver.php | 31 + .../Mapping/Driver/StaticPHPDriver.php | 31 + .../Mapping/Driver/SymfonyFileLocator.php | 31 + .../Persistence/Mapping/MappingException.php | 31 + .../Persistence/Mapping/ReflectionService.php | 31 + .../Mapping/RuntimeReflectionService.php | 31 + .../Mapping/StaticReflectionService.php | 31 + .../Common/Persistence/ObjectManager.php | 31 + .../Common/Persistence/ObjectManagerAware.php | 31 + .../Persistence/ObjectManagerDecorator.php | 31 + .../Common/Persistence/ObjectRepository.php | 31 + .../Common/Persistence/PersistentObject.php | 235 + .../lib/Doctrine/Common/Persistence/Proxy.php | 31 + .../Common/PropertyChangedListener.php | 31 + .../Persistence/AbstractManagerRegistry.php | 251 + .../Persistence/ConnectionRegistry.php | 43 + .../Persistence/Event/LifecycleEventArgs.php | 63 + .../Event/LoadClassMetadataEventArgs.php | 48 + .../Persistence/Event/ManagerEventArgs.php | 33 + .../Persistence/Event/OnClearEventArgs.php | 61 + .../Persistence/Event/PreUpdateEventArgs.php | 116 + .../Doctrine/Persistence/ManagerRegistry.php | 92 + .../Mapping/AbstractClassMetadataFactory.php | 420 ++ .../Persistence/Mapping/ClassMetadata.php | 157 + .../Mapping/ClassMetadataFactory.php | 57 + .../Mapping/Driver/AnnotationDriver.php | 258 + .../Mapping/Driver/DefaultFileLocator.php | 164 + .../Persistence/Mapping/Driver/FileDriver.php | 199 + .../Mapping/Driver/FileLocator.php | 57 + .../Mapping/Driver/MappingDriver.php | 41 + .../Mapping/Driver/MappingDriverChain.php | 149 + .../Persistence/Mapping/Driver/PHPDriver.php | 49 + .../Mapping/Driver/StaticPHPDriver.php | 134 + .../Mapping/Driver/SymfonyFileLocator.php | 233 + .../Persistence/Mapping/MappingException.php | 98 + .../Persistence/Mapping/ReflectionService.php | 74 + .../Mapping/RuntimeReflectionService.php | 89 + .../Mapping/StaticReflectionService.php | 74 + .../Persistence/NotifyPropertyChanged.php | 25 + .../Doctrine/Persistence/ObjectManager.php | 160 + .../Persistence/ObjectManagerAware.php | 34 + .../Persistence/ObjectManagerDecorator.php | 120 + .../Doctrine/Persistence/ObjectRepository.php | 64 + .../Persistence/PropertyChangedListener.php | 26 + .../lib/Doctrine/Persistence/Proxy.php | 39 + vendor/doctrine/reflection/.scrutinizer.yml | 29 + vendor/doctrine/reflection/LICENSE | 19 + vendor/doctrine/reflection/README.md | 13 + vendor/doctrine/reflection/composer.json | 44 + vendor/doctrine/reflection/docs/en/index.rst | 22 + .../reflection/docs/en/reference/index.rst | 85 + .../doctrine/reflection/docs/en/sidebar.rst | 4 + .../Reflection/ClassFinderInterface.php | 18 + .../Common/Reflection/Psr0FindFile.php | 70 + .../ReflectionProviderInterface.php | 31 + .../RuntimePublicReflectionProperty.php | 57 + .../Reflection/StaticReflectionClass.php | 413 ++ .../Reflection/StaticReflectionMethod.php | 344 ++ .../Reflection/StaticReflectionParser.php | 328 ++ .../Reflection/StaticReflectionProperty.php | 160 + vendor/doctrine/reflection/phpstan.neon | 6 + vendor/jdorn/sql-formatter/.gitignore | 1 + vendor/jdorn/sql-formatter/.travis.yml | 5 + vendor/jdorn/sql-formatter/LICENSE.txt | 21 + vendor/jdorn/sql-formatter/README.md | 185 + vendor/jdorn/sql-formatter/composer.json | 30 + vendor/jdorn/sql-formatter/composer.lock | 422 ++ vendor/jdorn/sql-formatter/examples/cli.php | 17 + .../jdorn/sql-formatter/examples/examples.php | 270 + .../jdorn/sql-formatter/lib/SqlFormatter.php | 1080 ++++ vendor/jdorn/sql-formatter/phpunit.xml.dist | 20 + .../sql-formatter/tests/SqlFormatterTest.php | 197 + .../sql-formatter/tests/clihighlight.html | 809 +++ .../jdorn/sql-formatter/tests/compress.html | 77 + .../sql-formatter/tests/format-highlight.html | 809 +++ vendor/jdorn/sql-formatter/tests/format.html | 807 +++ .../jdorn/sql-formatter/tests/highlight.html | 262 + .../jdorn/sql-formatter/tests/performance.php | 44 + vendor/jdorn/sql-formatter/tests/sql.sql | 261 + vendor/psr/cache/CHANGELOG.md | 16 + vendor/psr/cache/LICENSE.txt | 19 + vendor/psr/cache/README.md | 9 + vendor/psr/cache/composer.json | 25 + vendor/psr/cache/src/CacheException.php | 10 + vendor/psr/cache/src/CacheItemInterface.php | 105 + .../psr/cache/src/CacheItemPoolInterface.php | 138 + .../cache/src/InvalidArgumentException.php | 13 + vendor/psr/container/.gitignore | 3 + vendor/psr/container/LICENSE | 21 + vendor/psr/container/README.md | 5 + vendor/psr/container/composer.json | 27 + .../src/ContainerExceptionInterface.php | 13 + .../psr/container/src/ContainerInterface.php | 37 + .../src/NotFoundExceptionInterface.php | 13 + vendor/psr/event-dispatcher/.editorconfig | 15 + vendor/psr/event-dispatcher/.gitignore | 2 + vendor/psr/event-dispatcher/LICENSE | 21 + vendor/psr/event-dispatcher/README.md | 6 + vendor/psr/event-dispatcher/composer.json | 26 + .../src/EventDispatcherInterface.php | 21 + .../src/ListenerProviderInterface.php | 19 + .../src/StoppableEventInterface.php | 26 + vendor/psr/log/.gitignore | 1 + vendor/psr/log/LICENSE | 19 + vendor/psr/log/Psr/Log/AbstractLogger.php | 128 + .../log/Psr/Log/InvalidArgumentException.php | 7 + vendor/psr/log/Psr/Log/LogLevel.php | 18 + .../psr/log/Psr/Log/LoggerAwareInterface.php | 18 + vendor/psr/log/Psr/Log/LoggerAwareTrait.php | 26 + vendor/psr/log/Psr/Log/LoggerInterface.php | 125 + vendor/psr/log/Psr/Log/LoggerTrait.php | 142 + vendor/psr/log/Psr/Log/NullLogger.php | 30 + .../log/Psr/Log/Test/LoggerInterfaceTest.php | 146 + vendor/psr/log/Psr/Log/Test/TestLogger.php | 147 + vendor/psr/log/README.md | 58 + vendor/psr/log/composer.json | 26 + vendor/symfony/cache-contracts/.gitignore | 3 + .../cache-contracts/CacheInterface.php | 57 + vendor/symfony/cache-contracts/CacheTrait.php | 76 + .../cache-contracts/CallbackInterface.php | 30 + .../symfony/cache-contracts/ItemInterface.php | 65 + vendor/symfony/cache-contracts/LICENSE | 19 + vendor/symfony/cache-contracts/README.md | 9 + .../TagAwareCacheInterface.php | 38 + vendor/symfony/cache-contracts/composer.json | 34 + vendor/symfony/cache/.gitattributes | 3 + .../symfony/cache/Adapter/AbstractAdapter.php | 195 + .../cache/Adapter/AbstractTagAwareAdapter.php | 323 ++ .../cache/Adapter/AdapterInterface.php | 44 + vendor/symfony/cache/Adapter/ApcuAdapter.php | 122 + vendor/symfony/cache/Adapter/ArrayAdapter.php | 324 ++ vendor/symfony/cache/Adapter/ChainAdapter.php | 329 ++ .../symfony/cache/Adapter/DoctrineAdapter.php | 105 + .../cache/Adapter/FilesystemAdapter.php | 29 + .../Adapter/FilesystemTagAwareAdapter.php | 239 + .../cache/Adapter/MemcachedAdapter.php | 335 ++ vendor/symfony/cache/Adapter/NullAdapter.php | 154 + vendor/symfony/cache/Adapter/PdoAdapter.php | 469 ++ .../symfony/cache/Adapter/PhpArrayAdapter.php | 432 ++ .../symfony/cache/Adapter/PhpFilesAdapter.php | 330 ++ vendor/symfony/cache/Adapter/ProxyAdapter.php | 265 + vendor/symfony/cache/Adapter/Psr16Adapter.php | 86 + vendor/symfony/cache/Adapter/RedisAdapter.php | 30 + .../cache/Adapter/RedisTagAwareAdapter.php | 292 + .../symfony/cache/Adapter/TagAwareAdapter.php | 425 ++ .../Adapter/TagAwareAdapterInterface.php | 33 + .../cache/Adapter/TraceableAdapter.php | 299 ++ .../Adapter/TraceableTagAwareAdapter.php | 38 + vendor/symfony/cache/CHANGELOG.md | 81 + vendor/symfony/cache/CacheItem.php | 190 + .../DataCollector/CacheDataCollector.php | 189 + .../CacheCollectorPass.php | 72 + .../CachePoolClearerPass.php | 48 + .../DependencyInjection/CachePoolPass.php | 222 + .../CachePoolPrunerPass.php | 60 + vendor/symfony/cache/DoctrineProvider.php | 114 + .../cache/Exception/CacheException.php | 25 + .../Exception/InvalidArgumentException.php | 25 + .../cache/Exception/LogicException.php | 25 + vendor/symfony/cache/LICENSE | 19 + vendor/symfony/cache/LockRegistry.php | 153 + .../cache/Marshaller/DefaultMarshaller.php | 99 + .../cache/Marshaller/DeflateMarshaller.php | 53 + .../cache/Marshaller/MarshallerInterface.php | 40 + .../cache/Marshaller/TagAwareMarshaller.php | 89 + vendor/symfony/cache/PruneableInterface.php | 23 + vendor/symfony/cache/Psr16Cache.php | 277 + vendor/symfony/cache/README.md | 18 + vendor/symfony/cache/ResettableInterface.php | 21 + .../cache/Traits/AbstractAdapterTrait.php | 392 ++ .../symfony/cache/Traits/ContractsTrait.php | 97 + .../cache/Traits/FilesystemCommonTrait.php | 183 + .../symfony/cache/Traits/FilesystemTrait.php | 124 + vendor/symfony/cache/Traits/ProxyTrait.php | 43 + .../cache/Traits/RedisClusterProxy.php | 63 + vendor/symfony/cache/Traits/RedisProxy.php | 65 + vendor/symfony/cache/Traits/RedisTrait.php | 511 ++ vendor/symfony/cache/composer.json | 59 + vendor/symfony/config/.gitattributes | 3 + vendor/symfony/config/CHANGELOG.md | 116 + vendor/symfony/config/ConfigCache.php | 62 + vendor/symfony/config/ConfigCacheFactory.php | 47 + .../config/ConfigCacheFactoryInterface.php | 32 + .../symfony/config/ConfigCacheInterface.php | 49 + .../symfony/config/Definition/ArrayNode.php | 406 ++ vendor/symfony/config/Definition/BaseNode.php | 543 ++ .../symfony/config/Definition/BooleanNode.php | 55 + .../Builder/ArrayNodeDefinition.php | 546 ++ .../Builder/BooleanNodeDefinition.php | 53 + .../Builder/BuilderAwareInterface.php | 25 + .../Definition/Builder/EnumNodeDefinition.php | 56 + .../config/Definition/Builder/ExprBuilder.php | 246 + .../Builder/FloatNodeDefinition.php | 32 + .../Builder/IntegerNodeDefinition.php | 32 + .../Definition/Builder/MergeBuilder.php | 63 + .../config/Definition/Builder/NodeBuilder.php | 219 + .../Definition/Builder/NodeDefinition.php | 362 ++ .../Builder/NodeParentInterface.php | 21 + .../Builder/NormalizationBuilder.php | 60 + .../Builder/NumericNodeDefinition.php | 73 + .../Builder/ParentNodeDefinitionInterface.php | 51 + .../Builder/ScalarNodeDefinition.php | 32 + .../config/Definition/Builder/TreeBuilder.php | 63 + .../Definition/Builder/ValidationBuilder.php | 44 + .../Builder/VariableNodeDefinition.php | 65 + .../Definition/ConfigurationInterface.php | 27 + .../Definition/Dumper/XmlReferenceDumper.php | 302 ++ .../Definition/Dumper/YamlReferenceDumper.php | 242 + vendor/symfony/config/Definition/EnumNode.php | 62 + .../Exception/DuplicateKeyException.php | 22 + .../config/Definition/Exception/Exception.php | 21 + .../Exception/ForbiddenOverwriteException.php | 22 + .../InvalidConfigurationException.php | 47 + .../Exception/InvalidDefinitionException.php | 21 + .../Exception/InvalidTypeException.php | 21 + .../Exception/UnsetKeyException.php | 22 + .../symfony/config/Definition/FloatNode.php | 51 + .../symfony/config/Definition/IntegerNode.php | 46 + .../config/Definition/NodeInterface.php | 100 + .../symfony/config/Definition/NumericNode.php | 64 + .../symfony/config/Definition/Processor.php | 95 + .../Definition/PrototypeNodeInterface.php | 25 + .../config/Definition/PrototypedArrayNode.php | 365 ++ .../symfony/config/Definition/ScalarNode.php | 67 + .../config/Definition/VariableNode.php | 142 + ...LoaderImportCircularReferenceException.php | 27 + .../FileLocatorFileNotFoundException.php | 34 + .../config/Exception/LoaderLoadException.php | 109 + vendor/symfony/config/FileLocator.php | 94 + .../symfony/config/FileLocatorInterface.php | 34 + vendor/symfony/config/LICENSE | 19 + .../config/Loader/DelegatingLoader.php | 50 + vendor/symfony/config/Loader/FileLoader.php | 179 + .../symfony/config/Loader/GlobFileLoader.php | 36 + vendor/symfony/config/Loader/Loader.php | 78 + .../symfony/config/Loader/LoaderInterface.php | 50 + .../symfony/config/Loader/LoaderResolver.php | 68 + .../config/Loader/LoaderResolverInterface.php | 30 + vendor/symfony/config/README.md | 15 + .../Resource/ClassExistenceResource.php | 231 + .../config/Resource/ComposerResource.php | 70 + .../config/Resource/DirectoryResource.php | 106 + .../config/Resource/FileExistenceResource.php | 62 + .../symfony/config/Resource/FileResource.php | 67 + .../symfony/config/Resource/GlobResource.php | 230 + .../Resource/ReflectionClassResource.php | 220 + .../config/Resource/ResourceInterface.php | 33 + .../Resource/SelfCheckingResourceChecker.php | 36 + .../SelfCheckingResourceInterface.php | 30 + .../config/ResourceCheckerConfigCache.php | 188 + .../ResourceCheckerConfigCacheFactory.php | 44 + .../config/ResourceCheckerInterface.php | 45 + .../Util/Exception/InvalidXmlException.php | 21 + .../Util/Exception/XmlParsingException.php | 21 + vendor/symfony/config/Util/XmlUtils.php | 269 + vendor/symfony/config/composer.json | 48 + vendor/symfony/console/.gitattributes | 3 + vendor/symfony/console/Application.php | 1187 +++++ vendor/symfony/console/CHANGELOG.md | 178 + vendor/symfony/console/Command/Command.php | 642 +++ .../symfony/console/Command/HelpCommand.php | 83 + .../symfony/console/Command/ListCommand.php | 89 + .../symfony/console/Command/LockableTrait.php | 69 + .../CommandLoader/CommandLoaderInterface.php | 42 + .../CommandLoader/ContainerCommandLoader.php | 63 + .../CommandLoader/FactoryCommandLoader.php | 62 + vendor/symfony/console/ConsoleEvents.php | 47 + .../AddConsoleCommandPass.php | 98 + .../Descriptor/ApplicationDescription.php | 143 + .../symfony/console/Descriptor/Descriptor.php | 104 + .../Descriptor/DescriptorInterface.php | 29 + .../console/Descriptor/JsonDescriptor.php | 156 + .../console/Descriptor/MarkdownDescriptor.php | 188 + .../console/Descriptor/TextDescriptor.php | 342 ++ .../console/Descriptor/XmlDescriptor.php | 231 + .../console/Event/ConsoleCommandEvent.php | 51 + .../console/Event/ConsoleErrorEvent.php | 58 + vendor/symfony/console/Event/ConsoleEvent.php | 67 + .../console/Event/ConsoleTerminateEvent.php | 43 + .../console/EventListener/ErrorListener.php | 95 + .../Exception/CommandNotFoundException.php | 43 + .../console/Exception/ExceptionInterface.php | 21 + .../Exception/InvalidArgumentException.php | 19 + .../Exception/InvalidOptionException.php | 21 + .../console/Exception/LogicException.php | 19 + .../Exception/NamespaceNotFoundException.php | 21 + .../console/Exception/RuntimeException.php | 19 + .../console/Formatter/OutputFormatter.php | 275 + .../Formatter/OutputFormatterInterface.php | 58 + .../Formatter/OutputFormatterStyle.php | 196 + .../OutputFormatterStyleInterface.php | 52 + .../Formatter/OutputFormatterStyleStack.php | 110 + .../WrappableOutputFormatterInterface.php | 25 + .../console/Helper/DebugFormatterHelper.php | 107 + .../console/Helper/DescriptorHelper.php | 87 + vendor/symfony/console/Helper/Dumper.php | 64 + .../console/Helper/FormatterHelper.php | 96 + vendor/symfony/console/Helper/Helper.php | 132 + .../console/Helper/HelperInterface.php | 39 + vendor/symfony/console/Helper/HelperSet.php | 98 + .../console/Helper/InputAwareHelper.php | 33 + .../symfony/console/Helper/ProcessHelper.php | 144 + vendor/symfony/console/Helper/ProgressBar.php | 592 +++ .../console/Helper/ProgressIndicator.php | 254 + .../symfony/console/Helper/QuestionHelper.php | 485 ++ .../console/Helper/SymfonyQuestionHelper.php | 96 + vendor/symfony/console/Helper/Table.php | 834 +++ vendor/symfony/console/Helper/TableCell.php | 68 + vendor/symfony/console/Helper/TableRows.php | 32 + .../symfony/console/Helper/TableSeparator.php | 25 + vendor/symfony/console/Helper/TableStyle.php | 364 ++ vendor/symfony/console/Input/ArgvInput.php | 349 ++ vendor/symfony/console/Input/ArrayInput.php | 202 + vendor/symfony/console/Input/Input.php | 201 + .../symfony/console/Input/InputArgument.php | 129 + .../console/Input/InputAwareInterface.php | 26 + .../symfony/console/Input/InputDefinition.php | 390 ++ .../symfony/console/Input/InputInterface.php | 153 + vendor/symfony/console/Input/InputOption.php | 208 + .../Input/StreamableInputInterface.php | 37 + vendor/symfony/console/Input/StringInput.php | 68 + vendor/symfony/console/LICENSE | 19 + .../symfony/console/Logger/ConsoleLogger.php | 126 + .../symfony/console/Output/BufferedOutput.php | 45 + .../symfony/console/Output/ConsoleOutput.php | 159 + .../console/Output/ConsoleOutputInterface.php | 32 + .../console/Output/ConsoleSectionOutput.php | 143 + vendor/symfony/console/Output/NullOutput.php | 123 + vendor/symfony/console/Output/Output.php | 174 + .../console/Output/OutputInterface.php | 110 + .../symfony/console/Output/StreamOutput.php | 119 + .../console/Question/ChoiceQuestion.php | 182 + .../console/Question/ConfirmationQuestion.php | 57 + vendor/symfony/console/Question/Question.php | 282 + vendor/symfony/console/README.md | 20 + .../console/Resources/bin/hiddeninput.exe | Bin 0 -> 9216 bytes vendor/symfony/console/Style/OutputStyle.php | 153 + .../symfony/console/Style/StyleInterface.php | 132 + vendor/symfony/console/Style/SymfonyStyle.php | 499 ++ vendor/symfony/console/Terminal.php | 169 + .../console/Tester/ApplicationTester.php | 74 + .../symfony/console/Tester/CommandTester.php | 78 + vendor/symfony/console/Tester/TesterTrait.php | 178 + vendor/symfony/console/composer.json | 60 + .../dependency-injection/.gitattributes | 3 + vendor/symfony/dependency-injection/Alias.php | 133 + .../Argument/ArgumentInterface.php | 27 + .../Argument/BoundArgument.php | 62 + .../Argument/IteratorArgument.php | 22 + .../Argument/ReferenceSetArgumentTrait.php | 54 + .../Argument/RewindableGenerator.php | 46 + .../Argument/ServiceClosureArgument.php | 50 + .../Argument/ServiceLocator.php | 50 + .../Argument/ServiceLocatorArgument.php | 44 + .../Argument/TaggedIteratorArgument.php | 73 + .../symfony/dependency-injection/CHANGELOG.md | 248 + .../dependency-injection/ChildDefinition.php | 124 + .../Compiler/AbstractRecursivePass.php | 223 + .../Compiler/AnalyzeServiceReferencesPass.php | 184 + .../Compiler/AutoAliasServicePass.php | 41 + .../Compiler/AutowirePass.php | 475 ++ .../Compiler/AutowireRequiredMethodsPass.php | 84 + .../Compiler/CheckArgumentsValidityPass.php | 87 + .../Compiler/CheckCircularReferencesPass.php | 78 + .../Compiler/CheckDefinitionValidityPass.php | 90 + ...xceptionOnInvalidReferenceBehaviorPass.php | 88 + .../Compiler/CheckReferenceValidityPass.php | 43 + .../Compiler/CheckTypeDeclarationsPass.php | 245 + .../Compiler/Compiler.php | 116 + .../Compiler/CompilerPassInterface.php | 27 + .../Compiler/DecoratorServicePass.php | 89 + .../Compiler/DefinitionErrorExceptionPass.php | 56 + .../Compiler/ExtensionCompilerPass.php | 37 + .../Compiler/InlineServiceDefinitionsPass.php | 217 + .../MergeExtensionConfigurationPass.php | 220 + .../Compiler/PassConfig.php | 266 + .../Compiler/PriorityTaggedServiceTrait.php | 138 + .../Compiler/RegisterEnvVarProcessorsPass.php | 75 + .../Compiler/RegisterReverseContainerPass.php | 66 + .../RegisterServiceSubscribersPass.php | 122 + .../RemoveAbstractDefinitionsPass.php | 33 + .../Compiler/RemovePrivateAliasesPass.php | 39 + .../Compiler/RemoveUnusedDefinitionsPass.php | 90 + .../ReplaceAliasByActualDefinitionPass.php | 94 + .../Compiler/ResolveBindingsPass.php | 227 + .../Compiler/ResolveChildDefinitionsPass.php | 190 + .../Compiler/ResolveClassPass.php | 40 + .../Compiler/ResolveEnvPlaceholdersPass.php | 44 + .../Compiler/ResolveFactoryClassPass.php | 38 + .../Compiler/ResolveHotPathPass.php | 71 + .../ResolveInstanceofConditionalsPass.php | 168 + .../Compiler/ResolveInvalidReferencesPass.php | 136 + .../Compiler/ResolveNamedArgumentsPass.php | 112 + .../ResolveParameterPlaceHoldersPass.php | 87 + .../Compiler/ResolvePrivatesPass.php | 40 + .../ResolveReferencesToAliasesPass.php | 80 + .../ResolveServiceSubscribersPass.php | 52 + .../ResolveTaggedIteratorArgumentPass.php | 38 + .../Compiler/ServiceLocatorTagPass.php | 135 + .../Compiler/ServiceReferenceGraph.php | 98 + .../Compiler/ServiceReferenceGraphEdge.php | 99 + .../Compiler/ServiceReferenceGraphNode.php | 118 + .../Compiler/ValidateEnvPlaceholdersPass.php | 116 + .../Config/ContainerParametersResource.php | 50 + .../ContainerParametersResourceChecker.php | 52 + .../dependency-injection/Container.php | 447 ++ .../ContainerAwareInterface.php | 25 + .../ContainerAwareTrait.php | 30 + .../dependency-injection/ContainerBuilder.php | 1611 ++++++ .../ContainerInterface.php | 96 + .../dependency-injection/Definition.php | 890 ++++ .../dependency-injection/Dumper/Dumper.php | 29 + .../Dumper/DumperInterface.php | 27 + .../Dumper/GraphvizDumper.php | 251 + .../dependency-injection/Dumper/PhpDumper.php | 2064 ++++++++ .../dependency-injection/Dumper/Preloader.php | 100 + .../dependency-injection/Dumper/XmlDumper.php | 374 ++ .../Dumper/YamlDumper.php | 349 ++ .../EnvVarLoaderInterface.php | 25 + .../dependency-injection/EnvVarProcessor.php | 280 + .../EnvVarProcessorInterface.php | 40 + .../Exception/AutowiringFailedException.php | 72 + .../Exception/BadMethodCallException.php | 19 + .../Exception/EnvNotFoundException.php | 21 + .../Exception/EnvParameterException.php | 25 + .../Exception/ExceptionInterface.php | 24 + .../Exception/InvalidArgumentException.php | 21 + .../InvalidParameterTypeException.php | 26 + .../Exception/LogicException.php | 19 + .../Exception/OutOfBoundsException.php | 19 + .../ParameterCircularReferenceException.php | 34 + .../Exception/ParameterNotFoundException.php | 100 + .../Exception/RuntimeException.php | 21 + .../ServiceCircularReferenceException.php | 41 + .../Exception/ServiceNotFoundException.php | 67 + .../ExpressionLanguage.php | 40 + .../ExpressionLanguageProvider.php | 50 + .../ConfigurationExtensionInterface.php | 30 + .../Extension/Extension.php | 139 + .../Extension/ExtensionInterface.php | 52 + .../Extension/PrependExtensionInterface.php | 22 + vendor/symfony/dependency-injection/LICENSE | 19 + .../Instantiator/InstantiatorInterface.php | 34 + .../Instantiator/RealServiceInstantiator.php | 33 + .../LazyProxy/PhpDumper/DumperInterface.php | 43 + .../LazyProxy/PhpDumper/NullDumper.php | 48 + .../LazyProxy/ProxyHelper.php | 56 + .../Loader/ClosureLoader.php | 48 + .../Configurator/AbstractConfigurator.php | 87 + .../AbstractServiceConfigurator.php | 93 + .../Loader/Configurator/AliasConfigurator.php | 30 + .../Configurator/ContainerConfigurator.php | 132 + .../Configurator/DefaultsConfigurator.php | 69 + .../InlineServiceConfigurator.php | 36 + .../Configurator/InstanceofConfigurator.php | 49 + .../Configurator/ParametersConfigurator.php | 51 + .../Configurator/PrototypeConfigurator.php | 84 + .../Configurator/ReferenceConfigurator.php | 69 + .../Configurator/ServiceConfigurator.php | 72 + .../Configurator/ServicesConfigurator.php | 147 + .../Configurator/Traits/AbstractTrait.php | 28 + .../Configurator/Traits/ArgumentTrait.php | 42 + .../Traits/AutoconfigureTrait.php | 35 + .../Configurator/Traits/AutowireTrait.php | 27 + .../Loader/Configurator/Traits/BindTrait.php | 47 + .../Loader/Configurator/Traits/CallTrait.php | 35 + .../Loader/Configurator/Traits/ClassTrait.php | 27 + .../Configurator/Traits/ConfiguratorTrait.php | 29 + .../Configurator/Traits/DecorateTrait.php | 34 + .../Configurator/Traits/DeprecateTrait.php | 33 + .../Configurator/Traits/FactoryTrait.php | 37 + .../Loader/Configurator/Traits/FileTrait.php | 27 + .../Loader/Configurator/Traits/LazyTrait.php | 32 + .../Configurator/Traits/ParentTrait.php | 50 + .../Configurator/Traits/PropertyTrait.php | 27 + .../Configurator/Traits/PublicTrait.php | 35 + .../Loader/Configurator/Traits/ShareTrait.php | 27 + .../Configurator/Traits/SyntheticTrait.php | 28 + .../Loader/Configurator/Traits/TagTrait.php | 39 + .../Loader/DirectoryLoader.php | 54 + .../Loader/FileLoader.php | 225 + .../Loader/GlobFileLoader.php | 40 + .../Loader/IniFileLoader.php | 97 + .../Loader/PhpFileLoader.php | 80 + .../Loader/XmlFileLoader.php | 728 +++ .../Loader/YamlFileLoader.php | 872 +++ .../schema/dic/services/services-1.0.xsd | 305 ++ .../dependency-injection/Parameter.php | 35 + .../ParameterBag/ContainerBag.php | 51 + .../ParameterBag/ContainerBagInterface.php | 57 + .../EnvPlaceholderParameterBag.php | 154 + .../ParameterBag/FrozenParameterBag.php | 68 + .../ParameterBag/ParameterBag.php | 286 + .../ParameterBag/ParameterBagInterface.php | 108 + vendor/symfony/dependency-injection/README.md | 14 + .../dependency-injection/Reference.php | 47 + .../dependency-injection/ReverseContainer.php | 81 + .../dependency-injection/ServiceLocator.php | 145 + .../TaggedContainerInterface.php | 29 + .../dependency-injection/TypedReference.php | 47 + .../symfony/dependency-injection/Variable.php | 43 + .../dependency-injection/composer.json | 57 + vendor/symfony/doctrine-bridge/.gitattributes | 3 + vendor/symfony/doctrine-bridge/CHANGELOG.md | 114 + .../CacheWarmer/ProxyCacheWarmer.php | 69 + .../ContainerAwareEventManager.php | 174 + .../DataCollector/DoctrineDataCollector.php | 245 + .../DataCollector/ObjectParameter.php | 54 + .../DataFixtures/ContainerAwareLoader.php | 46 + .../AbstractDoctrineExtension.php | 440 ++ .../CompilerPass/DoctrineValidationPass.php | 61 + ...gisterEventListenersAndSubscribersPass.php | 149 + .../CompilerPass/RegisterMappingsPass.php | 237 + .../Security/UserProvider/EntityFactory.php | 61 + .../Form/ChoiceList/DoctrineChoiceLoader.php | 150 + .../Form/ChoiceList/EntityLoaderInterface.php | 34 + .../Form/ChoiceList/IdReader.php | 121 + .../Form/ChoiceList/ORMQueryBuilderLoader.php | 104 + .../CollectionToArrayTransformer.php | 67 + .../Form/DoctrineOrmExtension.php | 38 + .../Form/DoctrineOrmTypeGuesser.php | 201 + .../MergeDoctrineCollectionListener.php | 52 + .../Form/Type/DoctrineType.php | 279 + .../doctrine-bridge/Form/Type/EntityType.php | 98 + vendor/symfony/doctrine-bridge/LICENSE | 19 + .../doctrine-bridge/Logger/DbalLogger.php | 99 + .../doctrine-bridge/ManagerRegistry.php | 74 + .../Messenger/AbstractDoctrineMiddleware.php | 49 + ...rineClearEntityManagerWorkerSubscriber.php | 55 + .../DoctrineCloseConnectionMiddleware.php | 38 + .../DoctrinePingConnectionMiddleware.php | 48 + .../DoctrineTransactionMiddleware.php | 48 + .../PropertyInfo/DoctrineExtractor.php | 255 + vendor/symfony/doctrine-bridge/README.md | 13 + .../RememberMe/DoctrineTokenProvider.php | 126 + .../Security/User/EntityUserProvider.php | 155 + .../Security/User/UserLoaderInterface.php | 37 + .../Test/DoctrineTestHelper.php | 99 + .../Test/TestRepositoryFactory.php | 65 + .../Validator/Constraints/UniqueEntity.php | 68 + .../Constraints/UniqueEntityValidator.php | 218 + .../Validator/DoctrineInitializer.php | 38 + .../Validator/DoctrineLoader.php | 140 + vendor/symfony/doctrine-bridge/composer.json | 80 + vendor/symfony/error-handler/.gitattributes | 3 + .../symfony/error-handler/BufferingLogger.php | 58 + vendor/symfony/error-handler/CHANGELOG.md | 8 + vendor/symfony/error-handler/Debug.php | 36 + .../error-handler/DebugClassLoader.php | 1074 ++++ .../Error/ClassNotFoundError.php | 33 + .../error-handler/Error/FatalError.php | 88 + .../error-handler/Error/OutOfMemoryError.php | 16 + .../Error/UndefinedFunctionError.php | 33 + .../Error/UndefinedMethodError.php | 33 + .../ClassNotFoundErrorEnhancer.php | 193 + .../ErrorEnhancer/ErrorEnhancerInterface.php | 20 + .../UndefinedFunctionErrorEnhancer.php | 87 + .../UndefinedMethodErrorEnhancer.php | 69 + vendor/symfony/error-handler/ErrorHandler.php | 768 +++ .../ErrorRenderer/CliErrorRenderer.php | 46 + .../ErrorRenderer/ErrorRendererInterface.php | 27 + .../ErrorRenderer/HtmlErrorRenderer.php | 350 ++ .../ErrorRenderer/SerializerErrorRenderer.php | 80 + .../Exception/FlattenException.php | 397 ++ .../Exception/SilencedErrorContext.php | 67 + vendor/symfony/error-handler/LICENSE | 19 + vendor/symfony/error-handler/README.md | 12 + .../Resources/assets/css/error.css | 4 + .../Resources/assets/css/exception.css | 209 + .../Resources/assets/css/exception_full.css | 128 + .../Resources/assets/images/chevron-right.svg | 1 + .../assets/images/favicon.png.base64 | 1 + .../Resources/assets/images/icon-book.svg | 1 + .../assets/images/icon-minus-square-o.svg | 1 + .../assets/images/icon-minus-square.svg | 1 + .../assets/images/icon-plus-square-o.svg | 1 + .../assets/images/icon-plus-square.svg | 1 + .../Resources/assets/images/icon-support.svg | 1 + .../assets/images/symfony-ghost.svg.php | 1 + .../Resources/assets/images/symfony-logo.svg | 1 + .../Resources/assets/js/exception.js | 279 + .../Resources/views/error.html.php | 20 + .../Resources/views/exception.html.php | 116 + .../Resources/views/exception_full.html.php | 43 + .../Resources/views/logs.html.php | 45 + .../Resources/views/trace.html.php | 40 + .../Resources/views/traces.html.php | 42 + .../Resources/views/traces_text.html.php | 43 + .../symfony/error-handler/ThrowableUtils.php | 35 + vendor/symfony/error-handler/composer.json | 39 + .../event-dispatcher-contracts/.gitignore | 3 + .../event-dispatcher-contracts/Event.php | 54 + .../EventDispatcherInterface.php | 31 + .../event-dispatcher-contracts/LICENSE | 19 + .../event-dispatcher-contracts/README.md | 9 + .../event-dispatcher-contracts/composer.json | 34 + .../symfony/event-dispatcher/.gitattributes | 3 + vendor/symfony/event-dispatcher/CHANGELOG.md | 75 + .../Debug/TraceableEventDispatcher.php | 363 ++ .../Debug/WrappedListener.php | 127 + .../AddEventAliasesPass.php | 42 + .../RegisterListenersPass.php | 178 + .../event-dispatcher/EventDispatcher.php | 280 + .../EventDispatcherInterface.php | 75 + .../EventSubscriberInterface.php | 46 + .../symfony/event-dispatcher/GenericEvent.php | 170 + .../ImmutableEventDispatcher.php | 91 + vendor/symfony/event-dispatcher/LICENSE | 19 + .../LegacyEventDispatcherProxy.php | 29 + vendor/symfony/event-dispatcher/README.md | 15 + vendor/symfony/event-dispatcher/composer.json | 54 + vendor/symfony/filesystem/.gitattributes | 3 + vendor/symfony/filesystem/CHANGELOG.md | 75 + .../Exception/ExceptionInterface.php | 21 + .../Exception/FileNotFoundException.php | 34 + .../filesystem/Exception/IOException.php | 39 + .../Exception/IOExceptionInterface.php | 27 + .../Exception/InvalidArgumentException.php | 19 + vendor/symfony/filesystem/Filesystem.php | 734 +++ vendor/symfony/filesystem/LICENSE | 19 + vendor/symfony/filesystem/README.md | 13 + vendor/symfony/filesystem/composer.json | 34 + vendor/symfony/finder/.gitattributes | 3 + vendor/symfony/finder/CHANGELOG.md | 79 + .../symfony/finder/Comparator/Comparator.php | 91 + .../finder/Comparator/DateComparator.php | 51 + .../finder/Comparator/NumberComparator.php | 79 + .../Exception/AccessDeniedException.php | 19 + .../Exception/DirectoryNotFoundException.php | 19 + vendor/symfony/finder/Finder.php | 793 +++ vendor/symfony/finder/Gitignore.php | 105 + vendor/symfony/finder/Glob.php | 111 + .../finder/Iterator/CustomFilterIterator.php | 61 + .../Iterator/DateRangeFilterIterator.php | 58 + .../Iterator/DepthRangeFilterIterator.php | 45 + .../ExcludeDirectoryFilterIterator.php | 87 + .../Iterator/FileTypeFilterIterator.php | 53 + .../Iterator/FilecontentFilterIterator.php | 58 + .../Iterator/FilenameFilterIterator.php | 47 + .../Iterator/MultiplePcreFilterIterator.php | 106 + .../finder/Iterator/PathFilterIterator.php | 56 + .../Iterator/RecursiveDirectoryIterator.php | 140 + .../Iterator/SizeRangeFilterIterator.php | 57 + .../finder/Iterator/SortableIterator.php | 101 + vendor/symfony/finder/LICENSE | 19 + vendor/symfony/finder/README.md | 14 + vendor/symfony/finder/SplFileInfo.php | 85 + vendor/symfony/finder/composer.json | 33 + .../symfony/framework-bundle/.gitattributes | 3 + vendor/symfony/framework-bundle/CHANGELOG.md | 413 ++ .../AbstractPhpFileCacheWarmer.php | 87 + .../CacheWarmer/AnnotationsCacheWarmer.php | 102 + .../CacheWarmer/RouterCacheWarmer.php | 72 + .../CacheWarmer/SerializerCacheWarmer.php | 87 + .../CacheWarmer/TranslationsCacheWarmer.php | 67 + .../CacheWarmer/ValidatorCacheWarmer.php | 96 + .../framework-bundle/Command/AboutCommand.php | 144 + .../Command/AbstractConfigCommand.php | 141 + .../Command/AssetsInstallCommand.php | 283 + .../Command/CacheClearCommand.php | 209 + .../Command/CachePoolClearCommand.php | 105 + .../Command/CachePoolDeleteCommand.php | 83 + .../Command/CachePoolListCommand.php | 64 + .../Command/CachePoolPruneCommand.php | 73 + .../Command/CacheWarmupCommand.php | 86 + .../Command/ConfigDebugCommand.php | 156 + .../Command/ConfigDumpReferenceCommand.php | 135 + .../Command/ContainerDebugCommand.php | 295 ++ .../Command/ContainerLintCommand.php | 119 + .../Command/DebugAutowiringCommand.php | 161 + .../Command/EventDispatcherDebugCommand.php | 95 + .../Command/RouterDebugCommand.php | 123 + .../Command/RouterMatchCommand.php | 119 + .../Command/SecretsDecryptToLocalCommand.php | 90 + .../SecretsEncryptFromLocalCommand.php | 78 + .../Command/SecretsGenerateKeysCommand.php | 125 + .../Command/SecretsListCommand.php | 108 + .../Command/SecretsRemoveCommand.php | 82 + .../Command/SecretsSetCommand.php | 140 + .../Command/TranslationDebugCommand.php | 342 ++ .../Command/TranslationUpdateCommand.php | 316 ++ .../Command/WorkflowDumpCommand.php | 103 + .../Command/XliffLintCommand.php | 62 + .../Command/YamlLintCommand.php | 61 + .../framework-bundle/Console/Application.php | 221 + .../Console/Descriptor/Descriptor.php | 384 ++ .../Console/Descriptor/JsonDescriptor.php | 420 ++ .../Console/Descriptor/MarkdownDescriptor.php | 413 ++ .../Console/Descriptor/TextDescriptor.php | 608 +++ .../Console/Descriptor/XmlDescriptor.php | 570 ++ .../Console/Helper/DescriptorHelper.php | 37 + .../Controller/AbstractController.php | 427 ++ .../Controller/ControllerResolver.php | 47 + .../Controller/RedirectController.php | 179 + .../Controller/TemplateController.php | 70 + .../DataCollector/RouterDataCollector.php | 39 + .../AddAnnotationsCachedReaderPass.php | 42 + .../Compiler/AddDebugLogProcessorPass.php | 43 + .../AddExpressionLanguageProvidersPass.php | 38 + .../ContainerBuilderDebugDumpPass.php | 35 + .../Compiler/DataCollectorTranslatorPass.php | 35 + .../Compiler/LoggingTranslatorPass.php | 54 + .../Compiler/ProfilerPass.php | 58 + .../TestServiceContainerRealRefPass.php | 43 + .../TestServiceContainerWeakRefPass.php | 60 + .../Compiler/UnusedTagsPass.php | 100 + .../Compiler/WorkflowGuardListenerPass.php | 48 + .../DependencyInjection/Configuration.php | 1558 ++++++ .../FrameworkExtension.php | 1989 +++++++ .../SuggestMissingPackageSubscriber.php | 83 + .../framework-bundle/FrameworkBundle.php | 150 + .../framework-bundle/HttpCache/HttpCache.php | 72 + .../Kernel/MicroKernelTrait.php | 97 + .../framework-bundle/KernelBrowser.php | 206 + vendor/symfony/framework-bundle/LICENSE | 19 + vendor/symfony/framework-bundle/README.md | 10 + .../Resources/config/annotations.xml | 56 + .../Resources/config/assets.xml | 54 + .../Resources/config/cache.xml | 157 + .../Resources/config/cache_debug.xml | 15 + .../Resources/config/collectors.xml | 57 + .../Resources/config/console.xml | 232 + .../Resources/config/debug.xml | 34 + .../Resources/config/debug_prod.xml | 31 + .../Resources/config/error_renderer.xml | 31 + .../framework-bundle/Resources/config/esi.xml | 17 + .../Resources/config/form.xml | 115 + .../Resources/config/form_csrf.xml | 20 + .../Resources/config/form_debug.xml | 31 + .../Resources/config/fragment_listener.xml | 16 + .../Resources/config/fragment_renderer.xml | 51 + .../Resources/config/http_client.xml | 33 + .../Resources/config/http_client_debug.xml | 12 + .../Resources/config/identity_translator.xml | 14 + .../Resources/config/lock.xml | 26 + .../Resources/config/mailer.xml | 46 + .../Resources/config/mailer_debug.xml | 13 + .../Resources/config/mailer_transports.xml | 50 + .../Resources/config/messenger.xml | 138 + .../Resources/config/messenger_debug.xml | 14 + .../Resources/config/mime_type.xml | 16 + .../Resources/config/notifier.xml | 93 + .../Resources/config/notifier_transports.xml | 33 + .../Resources/config/profiling.xml | 29 + .../Resources/config/property_access.xml | 18 + .../Resources/config/property_info.xml | 37 + .../Resources/config/request.xml | 15 + .../Resources/config/routing.xml | 118 + .../Resources/config/routing/errors.xml | 12 + .../Resources/config/schema/symfony-1.0.xsd | 560 ++ .../Resources/config/secrets.xml | 18 + .../Resources/config/security_csrf.xml | 34 + .../Resources/config/serializer.xml | 175 + .../Resources/config/services.xml | 132 + .../Resources/config/session.xml | 75 + .../framework-bundle/Resources/config/ssi.xml | 17 + .../Resources/config/test.xml | 41 + .../Resources/config/translation.xml | 144 + .../Resources/config/translation_debug.xml | 21 + .../Resources/config/validator.xml | 75 + .../Resources/config/validator_debug.xml | 21 + .../framework-bundle/Resources/config/web.xml | 86 + .../Resources/config/web_link.xml | 14 + .../Resources/config/workflow.xml | 30 + .../Resources/views/Form/week_widget.html.php | 14 + .../AnnotatedRouteControllerLoader.php | 56 + .../Routing/DelegatingLoader.php | 89 + .../RedirectableCompiledUrlMatcher.php | 39 + .../Routing/RouteLoaderInterface.php | 19 + .../framework-bundle/Routing/Router.php | 189 + .../Secrets/AbstractVault.php | 49 + .../framework-bundle/Secrets/DotenvVault.php | 107 + .../framework-bundle/Secrets/SodiumVault.php | 220 + .../Test/BrowserKitAssertionsTrait.php | 159 + .../Test/DomCrawlerAssertionsTrait.php | 94 + .../framework-bundle/Test/KernelTestCase.php | 141 + .../Test/MailerAssertionsTrait.php | 131 + .../framework-bundle/Test/TestContainer.php | 152 + .../Test/WebTestAssertionsTrait.php | 18 + .../framework-bundle/Test/WebTestCase.php | 62 + .../Translation/Translator.php | 175 + vendor/symfony/framework-bundle/composer.json | 114 + vendor/symfony/http-foundation/.gitattributes | 3 + .../symfony/http-foundation/AcceptHeader.php | 165 + .../http-foundation/AcceptHeaderItem.php | 177 + .../http-foundation/BinaryFileResponse.php | 354 ++ vendor/symfony/http-foundation/CHANGELOG.md | 247 + vendor/symfony/http-foundation/Cookie.php | 302 ++ .../Exception/ConflictingHeadersException.php | 21 + .../Exception/RequestExceptionInterface.php | 21 + .../SuspiciousOperationException.php | 20 + .../ExpressionRequestMatcher.php | 47 + .../File/Exception/AccessDeniedException.php | 25 + .../Exception/CannotWriteFileException.php | 21 + .../File/Exception/ExtensionFileException.php | 21 + .../File/Exception/FileException.php | 21 + .../File/Exception/FileNotFoundException.php | 25 + .../File/Exception/FormSizeFileException.php | 21 + .../File/Exception/IniSizeFileException.php | 21 + .../File/Exception/NoFileException.php | 21 + .../File/Exception/NoTmpDirFileException.php | 21 + .../File/Exception/PartialFileException.php | 21 + .../Exception/UnexpectedTypeException.php | 20 + .../File/Exception/UploadException.php | 21 + vendor/symfony/http-foundation/File/File.php | 130 + .../symfony/http-foundation/File/Stream.php | 28 + .../http-foundation/File/UploadedFile.php | 281 + vendor/symfony/http-foundation/FileBag.php | 142 + vendor/symfony/http-foundation/HeaderBag.php | 288 + .../symfony/http-foundation/HeaderUtils.php | 224 + vendor/symfony/http-foundation/IpUtils.php | 185 + .../symfony/http-foundation/JsonResponse.php | 215 + vendor/symfony/http-foundation/LICENSE | 19 + .../symfony/http-foundation/ParameterBag.php | 205 + vendor/symfony/http-foundation/README.md | 14 + .../http-foundation/RedirectResponse.php | 105 + vendor/symfony/http-foundation/Request.php | 2057 +++++++ .../http-foundation/RequestMatcher.php | 188 + .../RequestMatcherInterface.php | 27 + .../symfony/http-foundation/RequestStack.php | 103 + vendor/symfony/http-foundation/Response.php | 1224 +++++ .../http-foundation/ResponseHeaderBag.php | 293 + vendor/symfony/http-foundation/ServerBag.php | 99 + .../Session/Attribute/AttributeBag.php | 148 + .../Attribute/AttributeBagInterface.php | 61 + .../Attribute/NamespacedAttributeBag.php | 157 + .../Session/Flash/AutoExpireFlashBag.php | 161 + .../Session/Flash/FlashBag.php | 152 + .../Session/Flash/FlashBagInterface.php | 88 + .../http-foundation/Session/Session.php | 268 + .../Session/SessionBagInterface.php | 46 + .../Session/SessionBagProxy.php | 83 + .../Session/SessionInterface.php | 166 + .../http-foundation/Session/SessionUtils.php | 59 + .../Handler/AbstractSessionHandler.php | 141 + .../Handler/MemcachedSessionHandler.php | 119 + .../Handler/MigratingSessionHandler.php | 124 + .../Storage/Handler/MongoDbSessionHandler.php | 187 + .../Handler/NativeFileSessionHandler.php | 55 + .../Storage/Handler/NullSessionHandler.php | 76 + .../Storage/Handler/PdoSessionHandler.php | 899 ++++ .../Storage/Handler/RedisSessionHandler.php | 120 + .../Storage/Handler/SessionHandlerFactory.php | 85 + .../Storage/Handler/StrictSessionHandler.php | 103 + .../Session/Storage/MetadataBag.php | 166 + .../Storage/MockArraySessionStorage.php | 252 + .../Storage/MockFileSessionStorage.php | 148 + .../Session/Storage/NativeSessionStorage.php | 464 ++ .../Storage/PhpBridgeSessionStorage.php | 64 + .../Session/Storage/Proxy/AbstractProxy.php | 118 + .../Storage/Proxy/SessionHandlerProxy.php | 101 + .../Storage/SessionStorageInterface.php | 131 + .../http-foundation/StreamedResponse.php | 135 + .../Constraint/RequestAttributeValueSame.php | 55 + .../Constraint/ResponseCookieValueSame.php | 85 + .../Test/Constraint/ResponseHasCookie.php | 77 + .../Test/Constraint/ResponseHasHeader.php | 53 + .../Test/Constraint/ResponseHeaderSame.php | 55 + .../Test/Constraint/ResponseIsRedirected.php | 56 + .../Test/Constraint/ResponseIsSuccessful.php | 56 + .../Constraint/ResponseStatusCodeSame.php | 63 + vendor/symfony/http-foundation/UrlHelper.php | 102 + vendor/symfony/http-foundation/composer.json | 39 + vendor/symfony/http-kernel/.gitattributes | 3 + vendor/symfony/http-kernel/Bundle/Bundle.php | 163 + .../http-kernel/Bundle/BundleInterface.php | 71 + vendor/symfony/http-kernel/CHANGELOG.md | 269 + .../CacheClearer/CacheClearerInterface.php | 25 + .../CacheClearer/ChainCacheClearer.php | 39 + .../CacheClearer/Psr6CacheClearer.php | 58 + .../http-kernel/CacheWarmer/CacheWarmer.php | 32 + .../CacheWarmer/CacheWarmerAggregate.php | 120 + .../CacheWarmer/CacheWarmerInterface.php | 32 + .../CacheWarmer/WarmableInterface.php | 25 + .../http-kernel/Config/FileLocator.php | 46 + .../Controller/ArgumentResolver.php | 96 + .../ArgumentResolver/DefaultValueResolver.php | 40 + .../NotTaggedControllerValueResolver.php | 81 + .../RequestAttributeValueResolver.php | 40 + .../ArgumentResolver/RequestValueResolver.php | 40 + .../ArgumentResolver/ServiceValueResolver.php | 93 + .../ArgumentResolver/SessionValueResolver.php | 50 + .../TraceableValueResolver.php | 62 + .../VariadicValueResolver.php | 46 + .../Controller/ArgumentResolverInterface.php | 32 + .../ArgumentValueResolverInterface.php | 37 + .../ContainerControllerResolver.php | 76 + .../Controller/ControllerReference.php | 44 + .../Controller/ControllerResolver.php | 220 + .../ControllerResolverInterface.php | 41 + .../Controller/ErrorController.php | 62 + .../Controller/TraceableArgumentResolver.php | 44 + .../TraceableControllerResolver.php | 44 + .../ControllerMetadata/ArgumentMetadata.php | 107 + .../ArgumentMetadataFactory.php | 65 + .../ArgumentMetadataFactoryInterface.php | 27 + .../DataCollector/AjaxDataCollector.php | 40 + .../DataCollector/ConfigDataCollector.php | 306 ++ .../DataCollector/DataCollector.php | 112 + .../DataCollector/DataCollectorInterface.php | 36 + .../DataCollector/DumpDataCollector.php | 290 + .../DataCollector/EventDataCollector.php | 150 + .../DataCollector/ExceptionDataCollector.php | 114 + .../LateDataCollectorInterface.php | 25 + .../DataCollector/LoggerDataCollector.php | 282 + .../DataCollector/MemoryDataCollector.php | 125 + .../DataCollector/RequestDataCollector.php | 458 ++ .../DataCollector/RouterDataCollector.php | 108 + .../DataCollector/TimeDataCollector.php | 159 + .../http-kernel/Debug/FileLinkFormatter.php | 106 + .../Debug/TraceableEventDispatcher.php | 90 + .../AddAnnotatedClassesToCachePass.php | 144 + .../ConfigurableExtension.php | 42 + .../ControllerArgumentValueResolverPass.php | 64 + .../DependencyInjection/Extension.php | 44 + .../FragmentRendererPass.php | 63 + .../LazyLoadingFragmentHandler.php | 47 + .../DependencyInjection/LoggerPass.php | 41 + .../MergeExtensionConfigurationPass.php | 41 + ...RegisterControllerArgumentLocatorsPass.php | 200 + .../RegisterLocaleAwareServicesPass.php | 58 + ...oveEmptyControllerArgumentLocatorsPass.php | 70 + .../ResettableServicePass.php | 71 + .../DependencyInjection/ServicesResetter.php | 43 + .../Event/ControllerArgumentsEvent.php | 61 + .../http-kernel/Event/ControllerEvent.php | 48 + .../http-kernel/Event/ExceptionEvent.php | 76 + .../http-kernel/Event/FinishRequestEvent.php | 21 + .../symfony/http-kernel/Event/KernelEvent.php | 80 + .../http-kernel/Event/RequestEvent.php | 58 + .../http-kernel/Event/ResponseEvent.php | 47 + .../http-kernel/Event/TerminateEvent.php | 41 + .../symfony/http-kernel/Event/ViewEvent.php | 61 + .../EventListener/AbstractSessionListener.php | 148 + .../AbstractTestSessionListener.php | 114 + .../AddRequestFormatsListener.php | 52 + .../EventListener/DebugHandlersListener.php | 153 + .../DisallowRobotsIndexingListener.php | 43 + .../EventListener/DumpListener.php | 63 + .../EventListener/ErrorListener.php | 149 + .../EventListener/FragmentListener.php | 100 + .../EventListener/LocaleAwareListener.php | 77 + .../EventListener/LocaleListener.php | 88 + .../EventListener/ProfilerListener.php | 127 + .../EventListener/ResponseListener.php | 58 + .../EventListener/RouterListener.php | 175 + .../EventListener/SessionListener.php | 52 + .../StreamedResponseListener.php | 51 + .../EventListener/SurrogateListener.php | 67 + .../EventListener/TestSessionListener.php | 42 + .../EventListener/ValidateRequestListener.php | 55 + .../Exception/AccessDeniedHttpException.php | 29 + .../Exception/BadRequestHttpException.php | 28 + .../Exception/ConflictHttpException.php | 28 + ...ntrollerDoesNotReturnResponseException.php | 84 + .../Exception/GoneHttpException.php | 28 + .../http-kernel/Exception/HttpException.php | 51 + .../Exception/HttpExceptionInterface.php | 34 + .../Exception/LengthRequiredHttpException.php | 28 + .../MethodNotAllowedHttpException.php | 31 + .../Exception/NotAcceptableHttpException.php | 28 + .../Exception/NotFoundHttpException.php | 28 + .../PreconditionFailedHttpException.php | 28 + .../PreconditionRequiredHttpException.php | 30 + .../ServiceUnavailableHttpException.php | 33 + .../TooManyRequestsHttpException.php | 35 + .../Exception/UnauthorizedHttpException.php | 31 + .../UnprocessableEntityHttpException.php | 28 + .../UnsupportedMediaTypeHttpException.php | 28 + .../AbstractSurrogateFragmentRenderer.php | 108 + .../Fragment/EsiFragmentRenderer.php | 28 + .../http-kernel/Fragment/FragmentHandler.php | 111 + .../Fragment/FragmentRendererInterface.php | 40 + .../Fragment/HIncludeFragmentRenderer.php | 112 + .../Fragment/InlineFragmentRenderer.php | 145 + .../Fragment/RoutableFragmentRenderer.php | 86 + .../Fragment/SsiFragmentRenderer.php | 28 + .../HttpCache/AbstractSurrogate.php | 136 + vendor/symfony/http-kernel/HttpCache/Esi.php | 117 + .../http-kernel/HttpCache/HttpCache.php | 707 +++ .../HttpCache/ResponseCacheStrategy.php | 213 + .../ResponseCacheStrategyInterface.php | 37 + vendor/symfony/http-kernel/HttpCache/Ssi.php | 100 + .../symfony/http-kernel/HttpCache/Store.php | 460 ++ .../http-kernel/HttpCache/StoreInterface.php | 81 + .../HttpCache/SubRequestHandler.php | 91 + .../HttpCache/SurrogateInterface.php | 87 + .../symfony/http-kernel/HttpClientKernel.php | 106 + vendor/symfony/http-kernel/HttpKernel.php | 282 + .../symfony/http-kernel/HttpKernelBrowser.php | 199 + .../http-kernel/HttpKernelInterface.php | 42 + vendor/symfony/http-kernel/Kernel.php | 825 +++ vendor/symfony/http-kernel/KernelEvents.php | 103 + .../symfony/http-kernel/KernelInterface.php | 141 + vendor/symfony/http-kernel/LICENSE | 19 + .../http-kernel/Log/DebugLoggerInterface.php | 45 + vendor/symfony/http-kernel/Log/Logger.php | 106 + .../Profiler/FileProfilerStorage.php | 303 ++ .../symfony/http-kernel/Profiler/Profile.php | 274 + .../symfony/http-kernel/Profiler/Profiler.php | 253 + .../Profiler/ProfilerStorageInterface.php | 60 + vendor/symfony/http-kernel/README.md | 16 + .../http-kernel/RebootableInterface.php | 30 + .../http-kernel/Resources/welcome.html.php | 119 + .../http-kernel/TerminableInterface.php | 32 + vendor/symfony/http-kernel/UriSigner.php | 103 + vendor/symfony/http-kernel/composer.json | 80 + vendor/symfony/mime/.gitattributes | 3 + vendor/symfony/mime/Address.php | 125 + vendor/symfony/mime/BodyRendererInterface.php | 20 + vendor/symfony/mime/CHANGELOG.md | 20 + vendor/symfony/mime/CharacterStream.php | 221 + vendor/symfony/mime/Crypto/SMime.php | 111 + vendor/symfony/mime/Crypto/SMimeEncrypter.php | 63 + vendor/symfony/mime/Crypto/SMimeSigner.php | 71 + .../AddMimeTypeGuesserPass.php | 46 + vendor/symfony/mime/Email.php | 599 +++ .../mime/Encoder/AddressEncoderInterface.php | 28 + .../mime/Encoder/Base64ContentEncoder.php | 48 + vendor/symfony/mime/Encoder/Base64Encoder.php | 41 + .../mime/Encoder/Base64MimeHeaderEncoder.php | 43 + .../mime/Encoder/ContentEncoderInterface.php | 30 + .../mime/Encoder/EightBitContentEncoder.php | 35 + .../symfony/mime/Encoder/EncoderInterface.php | 26 + .../mime/Encoder/IdnAddressEncoder.php | 54 + .../Encoder/MimeHeaderEncoderInterface.php | 23 + .../symfony/mime/Encoder/QpContentEncoder.php | 64 + vendor/symfony/mime/Encoder/QpEncoder.php | 195 + .../mime/Encoder/QpMimeHeaderEncoder.php | 40 + .../symfony/mime/Encoder/Rfc2231Encoder.php | 50 + .../Exception/AddressEncoderException.php | 19 + .../mime/Exception/ExceptionInterface.php | 19 + .../Exception/InvalidArgumentException.php | 19 + .../symfony/mime/Exception/LogicException.php | 19 + .../mime/Exception/RfcComplianceException.php | 19 + .../mime/Exception/RuntimeException.php | 19 + .../mime/FileBinaryMimeTypeGuesser.php | 93 + .../symfony/mime/FileinfoMimeTypeGuesser.php | 63 + vendor/symfony/mime/Header/AbstractHeader.php | 279 + vendor/symfony/mime/Header/DateHeader.php | 66 + .../symfony/mime/Header/HeaderInterface.php | 65 + vendor/symfony/mime/Header/Headers.php | 282 + .../mime/Header/IdentificationHeader.php | 110 + vendor/symfony/mime/Header/MailboxHeader.php | 85 + .../symfony/mime/Header/MailboxListHeader.php | 136 + .../mime/Header/ParameterizedHeader.php | 174 + vendor/symfony/mime/Header/PathHeader.php | 62 + .../mime/Header/UnstructuredHeader.php | 69 + vendor/symfony/mime/LICENSE | 19 + vendor/symfony/mime/Message.php | 151 + vendor/symfony/mime/MessageConverter.php | 125 + .../symfony/mime/MimeTypeGuesserInterface.php | 37 + vendor/symfony/mime/MimeTypes.php | 3153 +++++++++++ vendor/symfony/mime/MimeTypesInterface.php | 32 + .../mime/Part/AbstractMultipartPart.php | 99 + vendor/symfony/mime/Part/AbstractPart.php | 65 + vendor/symfony/mime/Part/DataPart.php | 161 + vendor/symfony/mime/Part/MessagePart.php | 62 + .../mime/Part/Multipart/AlternativePart.php | 25 + .../mime/Part/Multipart/DigestPart.php | 31 + .../mime/Part/Multipart/FormDataPart.php | 103 + .../symfony/mime/Part/Multipart/MixedPart.php | 25 + .../mime/Part/Multipart/RelatedPart.php | 55 + vendor/symfony/mime/Part/SMimePart.php | 116 + vendor/symfony/mime/Part/TextPart.php | 204 + vendor/symfony/mime/README.md | 13 + vendor/symfony/mime/RawMessage.php | 88 + .../mime/Resources/bin/update_mime_types.php | 166 + .../Test/Constraint/EmailAddressContains.php | 74 + .../Test/Constraint/EmailAttachmentCount.php | 59 + .../mime/Test/Constraint/EmailHasHeader.php | 57 + .../mime/Test/Constraint/EmailHeaderSame.php | 59 + .../Test/Constraint/EmailHtmlBodyContains.php | 56 + .../Test/Constraint/EmailTextBodyContains.php | 56 + vendor/symfony/mime/composer.json | 42 + vendor/symfony/polyfill-ctype/Ctype.php | 227 + vendor/symfony/polyfill-ctype/LICENSE | 19 + vendor/symfony/polyfill-ctype/README.md | 12 + vendor/symfony/polyfill-ctype/bootstrap.php | 26 + vendor/symfony/polyfill-ctype/composer.json | 34 + vendor/symfony/polyfill-intl-idn/Idn.php | 283 + vendor/symfony/polyfill-intl-idn/LICENSE | 19 + vendor/symfony/polyfill-intl-idn/README.md | 12 + .../symfony/polyfill-intl-idn/bootstrap.php | 59 + .../symfony/polyfill-intl-idn/composer.json | 36 + vendor/symfony/polyfill-mbstring/LICENSE | 19 + vendor/symfony/polyfill-mbstring/Mbstring.php | 840 +++ vendor/symfony/polyfill-mbstring/README.md | 13 + .../Resources/unidata/lowerCase.php | 1096 ++++ .../Resources/unidata/titleCaseRegexp.php | 5 + .../Resources/unidata/upperCase.php | 1104 ++++ .../symfony/polyfill-mbstring/bootstrap.php | 62 + .../symfony/polyfill-mbstring/composer.json | 34 + vendor/symfony/polyfill-php72/LICENSE | 19 + vendor/symfony/polyfill-php72/Php72.php | 216 + vendor/symfony/polyfill-php72/README.md | 27 + vendor/symfony/polyfill-php72/bootstrap.php | 36 + vendor/symfony/polyfill-php72/composer.json | 31 + vendor/symfony/polyfill-php73/LICENSE | 19 + vendor/symfony/polyfill-php73/Php73.php | 43 + vendor/symfony/polyfill-php73/README.md | 18 + .../Resources/stubs/JsonException.php | 14 + vendor/symfony/polyfill-php73/bootstrap.php | 32 + vendor/symfony/polyfill-php73/composer.json | 32 + vendor/symfony/routing/.gitattributes | 3 + vendor/symfony/routing/Annotation/Route.php | 182 + vendor/symfony/routing/CHANGELOG.md | 268 + vendor/symfony/routing/CompiledRoute.php | 173 + .../RoutingResolverPass.php | 49 + .../routing/Exception/ExceptionInterface.php | 21 + .../Exception/InvalidParameterException.php | 21 + .../Exception/MethodNotAllowedException.php | 41 + .../MissingMandatoryParametersException.php | 22 + .../Exception/NoConfigurationException.php | 21 + .../Exception/ResourceNotFoundException.php | 23 + .../Exception/RouteNotFoundException.php | 21 + .../Generator/CompiledUrlGenerator.php | 58 + .../ConfigurableRequirementsInterface.php | 53 + .../Dumper/CompiledUrlGeneratorDumper.php | 73 + .../Generator/Dumper/GeneratorDumper.php | 37 + .../Dumper/GeneratorDumperInterface.php | 37 + .../routing/Generator/UrlGenerator.php | 356 ++ .../Generator/UrlGeneratorInterface.php | 82 + vendor/symfony/routing/LICENSE | 19 + .../routing/Loader/AnnotationClassLoader.php | 332 ++ .../Loader/AnnotationDirectoryLoader.php | 93 + .../routing/Loader/AnnotationFileLoader.php | 143 + .../symfony/routing/Loader/ClosureLoader.php | 46 + .../Configurator/CollectionConfigurator.php | 93 + .../Configurator/ImportConfigurator.php | 93 + .../Loader/Configurator/RouteConfigurator.php | 34 + .../Configurator/RoutingConfigurator.php | 60 + .../Loader/Configurator/Traits/AddTrait.php | 90 + .../Loader/Configurator/Traits/RouteTrait.php | 163 + .../routing/Loader/ContainerLoader.php | 45 + .../routing/Loader/DirectoryLoader.php | 58 + .../symfony/routing/Loader/GlobFileLoader.php | 47 + .../symfony/routing/Loader/ObjectLoader.php | 84 + .../symfony/routing/Loader/PhpFileLoader.php | 75 + .../symfony/routing/Loader/XmlFileLoader.php | 436 ++ .../symfony/routing/Loader/YamlFileLoader.php | 285 + .../Loader/schema/routing/routing-1.0.xsd | 170 + .../routing/Matcher/CompiledUrlMatcher.php | 31 + .../Dumper/CompiledUrlMatcherDumper.php | 501 ++ .../Dumper/CompiledUrlMatcherTrait.php | 187 + .../routing/Matcher/Dumper/MatcherDumper.php | 37 + .../Matcher/Dumper/MatcherDumperInterface.php | 37 + .../Matcher/Dumper/StaticPrefixCollection.php | 202 + .../Matcher/RedirectableUrlMatcher.php | 64 + .../RedirectableUrlMatcherInterface.php | 31 + .../Matcher/RequestMatcherInterface.php | 39 + .../routing/Matcher/TraceableUrlMatcher.php | 164 + vendor/symfony/routing/Matcher/UrlMatcher.php | 279 + .../routing/Matcher/UrlMatcherInterface.php | 41 + vendor/symfony/routing/README.md | 13 + vendor/symfony/routing/RequestContext.php | 305 ++ .../routing/RequestContextAwareInterface.php | 27 + vendor/symfony/routing/Route.php | 547 ++ vendor/symfony/routing/RouteCollection.php | 273 + .../routing/RouteCollectionBuilder.php | 359 ++ vendor/symfony/routing/RouteCompiler.php | 337 ++ .../routing/RouteCompilerInterface.php | 30 + vendor/symfony/routing/Router.php | 390 ++ vendor/symfony/routing/RouterInterface.php | 35 + vendor/symfony/routing/composer.json | 54 + vendor/symfony/service-contracts/.gitignore | 3 + vendor/symfony/service-contracts/LICENSE | 19 + vendor/symfony/service-contracts/README.md | 9 + .../service-contracts/ResetInterface.php | 30 + .../service-contracts/ServiceLocatorTrait.php | 122 + .../ServiceProviderInterface.php | 36 + .../ServiceSubscriberInterface.php | 53 + .../ServiceSubscriberTrait.php | 63 + .../Test/ServiceLocatorTest.php | 92 + .../symfony/service-contracts/composer.json | 34 + vendor/symfony/var-dumper/.gitattributes | 3 + vendor/symfony/var-dumper/CHANGELOG.md | 53 + .../symfony/var-dumper/Caster/AmqpCaster.php | 212 + vendor/symfony/var-dumper/Caster/ArgsStub.php | 80 + vendor/symfony/var-dumper/Caster/Caster.php | 170 + .../symfony/var-dumper/Caster/ClassStub.php | 106 + .../symfony/var-dumper/Caster/ConstStub.php | 36 + .../var-dumper/Caster/CutArrayStub.php | 30 + vendor/symfony/var-dumper/Caster/CutStub.php | 64 + .../symfony/var-dumper/Caster/DOMCaster.php | 304 ++ .../symfony/var-dumper/Caster/DateCaster.php | 122 + .../var-dumper/Caster/DoctrineCaster.php | 62 + vendor/symfony/var-dumper/Caster/DsCaster.php | 70 + .../symfony/var-dumper/Caster/DsPairStub.php | 28 + vendor/symfony/var-dumper/Caster/EnumStub.php | 30 + .../var-dumper/Caster/ExceptionCaster.php | 383 ++ .../symfony/var-dumper/Caster/FrameStub.php | 30 + .../symfony/var-dumper/Caster/GmpCaster.php | 32 + .../var-dumper/Caster/ImagineCaster.php | 37 + vendor/symfony/var-dumper/Caster/ImgStub.php | 26 + .../symfony/var-dumper/Caster/IntlCaster.php | 172 + vendor/symfony/var-dumper/Caster/LinkStub.php | 108 + .../var-dumper/Caster/MemcachedCaster.php | 81 + .../symfony/var-dumper/Caster/PdoCaster.php | 122 + .../symfony/var-dumper/Caster/PgSqlCaster.php | 156 + .../var-dumper/Caster/ProxyManagerCaster.php | 33 + .../symfony/var-dumper/Caster/RedisCaster.php | 152 + .../var-dumper/Caster/ReflectionCaster.php | 384 ++ .../var-dumper/Caster/ResourceCaster.php | 100 + .../symfony/var-dumper/Caster/SplCaster.php | 228 + .../symfony/var-dumper/Caster/StubCaster.php | 84 + .../var-dumper/Caster/SymfonyCaster.php | 69 + .../symfony/var-dumper/Caster/TraceStub.php | 36 + .../symfony/var-dumper/Caster/UuidCaster.php | 30 + .../var-dumper/Caster/XmlReaderCaster.php | 79 + .../var-dumper/Caster/XmlResourceCaster.php | 63 + .../var-dumper/Cloner/AbstractCloner.php | 360 ++ .../var-dumper/Cloner/ClonerInterface.php | 27 + vendor/symfony/var-dumper/Cloner/Cursor.php | 43 + vendor/symfony/var-dumper/Cloner/Data.php | 451 ++ .../var-dumper/Cloner/DumperInterface.php | 56 + vendor/symfony/var-dumper/Cloner/Stub.php | 67 + .../symfony/var-dumper/Cloner/VarCloner.php | 285 + .../Command/Descriptor/CliDescriptor.php | 88 + .../Descriptor/DumpDescriptorInterface.php | 23 + .../Command/Descriptor/HtmlDescriptor.php | 119 + .../var-dumper/Command/ServerDumpCommand.php | 99 + .../var-dumper/Dumper/AbstractDumper.php | 204 + .../symfony/var-dumper/Dumper/CliDumper.php | 636 +++ .../ContextProvider/CliContextProvider.php | 32 + .../ContextProviderInterface.php | 25 + .../RequestContextProvider.php | 51 + .../ContextProvider/SourceContextProvider.php | 126 + .../Dumper/ContextualizedDumper.php | 43 + .../var-dumper/Dumper/DataDumperInterface.php | 24 + .../symfony/var-dumper/Dumper/HtmlDumper.php | 1004 ++++ .../var-dumper/Dumper/ServerDumper.php | 53 + .../Exception/ThrowingCasterException.php | 26 + vendor/symfony/var-dumper/LICENSE | 19 + vendor/symfony/var-dumper/README.md | 15 + .../var-dumper/Resources/bin/var-dump-server | 63 + .../Resources/css/htmlDescriptor.css | 130 + .../var-dumper/Resources/functions/dump.php | 43 + .../var-dumper/Resources/js/htmlDescriptor.js | 10 + .../symfony/var-dumper/Server/Connection.php | 95 + .../symfony/var-dumper/Server/DumpServer.php | 107 + .../var-dumper/Test/VarDumperTestTrait.php | 87 + vendor/symfony/var-dumper/VarDumper.php | 60 + vendor/symfony/var-dumper/composer.json | 53 + vendor/symfony/var-exporter/.gitattributes | 3 + vendor/symfony/var-exporter/CHANGELOG.md | 7 + .../Exception/ClassNotFoundException.php | 20 + .../Exception/ExceptionInterface.php | 16 + .../NotInstantiableTypeException.php | 20 + vendor/symfony/var-exporter/Instantiator.php | 94 + .../var-exporter/Internal/Exporter.php | 407 ++ .../var-exporter/Internal/Hydrator.php | 151 + .../var-exporter/Internal/Reference.php | 30 + .../var-exporter/Internal/Registry.php | 136 + .../symfony/var-exporter/Internal/Values.php | 27 + vendor/symfony/var-exporter/LICENSE | 19 + vendor/symfony/var-exporter/README.md | 38 + vendor/symfony/var-exporter/VarExporter.php | 114 + vendor/symfony/var-exporter/composer.json | 36 + 2323 files changed, 335648 insertions(+), 2 deletions(-) create mode 100644 api/src/DataFixtures/AppFixtures.php create mode 100644 bookshop-api/.env create mode 100644 bookshop-api/.gitignore create mode 100755 bookshop-api/bin/console create mode 100644 bookshop-api/composer.json create mode 100644 bookshop-api/composer.lock create mode 100644 bookshop-api/config/bootstrap.php create mode 100644 bookshop-api/config/bundles.php create mode 100644 bookshop-api/config/packages/api_platform.yaml create mode 100644 bookshop-api/config/packages/cache.yaml create mode 100644 bookshop-api/config/packages/doctrine.yaml create mode 100644 bookshop-api/config/packages/framework.yaml create mode 100644 bookshop-api/config/packages/nelmio_cors.yaml create mode 100644 bookshop-api/config/packages/prod/doctrine.yaml create mode 100644 bookshop-api/config/packages/prod/routing.yaml create mode 100644 bookshop-api/config/packages/routing.yaml create mode 100644 bookshop-api/config/packages/security.yaml create mode 100644 bookshop-api/config/packages/test/framework.yaml create mode 100644 bookshop-api/config/packages/test/twig.yaml create mode 100644 bookshop-api/config/packages/test/validator.yaml create mode 100644 bookshop-api/config/packages/twig.yaml create mode 100644 bookshop-api/config/packages/validator.yaml create mode 100644 bookshop-api/config/routes.yaml create mode 100644 bookshop-api/config/routes/annotations.yaml create mode 100644 bookshop-api/config/routes/api_platform.yaml create mode 100644 bookshop-api/config/routes/dev/framework.yaml create mode 100644 bookshop-api/config/services.yaml create mode 100644 bookshop-api/public/index.php create mode 100644 bookshop-api/src/Controller/.gitignore create mode 100644 bookshop-api/src/Entity/.gitignore create mode 100644 bookshop-api/src/Kernel.php create mode 100644 bookshop-api/src/Repository/.gitignore create mode 100644 bookshop-api/symfony.lock create mode 100644 bookshop-api/templates/base.html.twig create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 vendor/autoload.php create mode 120000 vendor/bin/doctrine create mode 120000 vendor/bin/doctrine-dbal create mode 120000 vendor/bin/var-dump-server create mode 100644 vendor/composer/ClassLoader.php create mode 100644 vendor/composer/LICENSE create mode 100644 vendor/composer/autoload_classmap.php create mode 100644 vendor/composer/autoload_files.php create mode 100644 vendor/composer/autoload_namespaces.php create mode 100644 vendor/composer/autoload_psr4.php create mode 100644 vendor/composer/autoload_real.php create mode 100644 vendor/composer/autoload_static.php create mode 100644 vendor/composer/installed.json create mode 100644 vendor/doctrine/annotations/CHANGELOG.md create mode 100644 vendor/doctrine/annotations/LICENSE create mode 100644 vendor/doctrine/annotations/README.md create mode 100644 vendor/doctrine/annotations/composer.json create mode 100644 vendor/doctrine/annotations/docs/en/annotations.rst create mode 100644 vendor/doctrine/annotations/docs/en/custom.rst create mode 100644 vendor/doctrine/annotations/docs/en/index.rst create mode 100644 vendor/doctrine/annotations/docs/en/sidebar.rst create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php create mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php create mode 100644 vendor/doctrine/annotations/phpbench.json.dist create mode 100644 vendor/doctrine/annotations/phpstan.neon create mode 100644 vendor/doctrine/cache/LICENSE create mode 100644 vendor/doctrine/cache/README.md create mode 100644 vendor/doctrine/cache/UPGRADE.md create mode 100644 vendor/doctrine/cache/composer.json create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcuCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ArrayCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ChainCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/CouchbaseBucketCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/CouchbaseCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ExtMongoDBCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/FilesystemCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/InvalidCacheId.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/LegacyMongoDBCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcacheCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcachedCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MongoDBCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiGetCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiOperationCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiPutCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/PhpFileCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/PredisCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/RedisCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/SQLite3Cache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/Version.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/VoidCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/WinCacheCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/XcacheCache.php create mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ZendDataCache.php create mode 100644 vendor/doctrine/collections/.doctrine-project.json create mode 100644 vendor/doctrine/collections/CONTRIBUTING.md create mode 100644 vendor/doctrine/collections/LICENSE create mode 100644 vendor/doctrine/collections/README.md create mode 100644 vendor/doctrine/collections/composer.json create mode 100644 vendor/doctrine/collections/docs/en/derived-collections.rst create mode 100644 vendor/doctrine/collections/docs/en/expression-builder.rst create mode 100644 vendor/doctrine/collections/docs/en/expressions.rst create mode 100644 vendor/doctrine/collections/docs/en/index.rst create mode 100644 vendor/doctrine/collections/docs/en/lazy-collections.rst create mode 100644 vendor/doctrine/collections/docs/en/sidebar.rst create mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/AbstractLazyCollection.php create mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php create mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php create mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php create mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php create mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php create mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php create mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php create mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ExpressionVisitor.php create mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php create mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php create mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Selectable.php create mode 100644 vendor/doctrine/collections/psalm.xml.dist create mode 100644 vendor/doctrine/common/.doctrine-project.json create mode 100644 vendor/doctrine/common/.github/FUNDING.yml create mode 100644 vendor/doctrine/common/LICENSE create mode 100644 vendor/doctrine/common/README.md create mode 100644 vendor/doctrine/common/UPGRADE_TO_2_1 create mode 100644 vendor/doctrine/common/UPGRADE_TO_2_2 create mode 100644 vendor/doctrine/common/composer.json create mode 100644 vendor/doctrine/common/composer.lock create mode 100644 vendor/doctrine/common/docs/en/index.rst create mode 100644 vendor/doctrine/common/docs/en/reference/class-loading.rst create mode 100644 vendor/doctrine/common/humbug.json.dist create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/ClassLoader.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/CommonException.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Comparable.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Lexer.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/Autoloader.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/InvalidArgumentException.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/OutOfBoundsException.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/ProxyException.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/Proxy.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyDefinition.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Util/ClassUtils.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Util/Inflector.php create mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Version.php create mode 100644 vendor/doctrine/common/phpstan.neon.dist create mode 100644 vendor/doctrine/data-fixtures/.doctrine-project.json create mode 100644 vendor/doctrine/data-fixtures/.github/FUNDING.yml create mode 100644 vendor/doctrine/data-fixtures/CHANGELOG.md create mode 100644 vendor/doctrine/data-fixtures/LICENSE create mode 100644 vendor/doctrine/data-fixtures/README.md create mode 100644 vendor/doctrine/data-fixtures/UPGRADE create mode 100644 vendor/doctrine/data-fixtures/composer.json create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/AbstractFixture.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/DependentFixtureInterface.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Event/Listener/MongoDBReferenceListener.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Event/Listener/ORMReferenceListener.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Exception/CircularReferenceException.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/AbstractExecutor.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/MongoDBExecutor.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/PHPCRExecutor.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/FixtureInterface.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Loader.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/OrderedFixtureInterface.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/ProxyReferenceRepository.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/MongoDBPurger.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/ORMPurger.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PHPCRPurger.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PurgerInterface.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/ReferenceRepository.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/SharedFixtureInterface.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Sorter/TopologicalSorter.php create mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Sorter/Vertex.php create mode 100644 vendor/doctrine/data-fixtures/phpcs.xml.dist create mode 100644 vendor/doctrine/dbal/.doctrine-project.json create mode 100644 vendor/doctrine/dbal/LICENSE create mode 100644 vendor/doctrine/dbal/README.md create mode 100644 vendor/doctrine/dbal/SECURITY.md create mode 100644 vendor/doctrine/dbal/UPGRADE.md create mode 100755 vendor/doctrine/dbal/bin/doctrine-dbal create mode 100644 vendor/doctrine/dbal/bin/doctrine-dbal.php create mode 100644 vendor/doctrine/dbal/composer.json create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ArrayStatement.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/CacheException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/QueryCacheProfile.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/ColumnCase.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Configuration.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/ConnectionException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDB2Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDriverException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver/EasyConnectString.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractPostgreSQLDriver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLAnywhereDriver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLServerDriver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Connection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DriverException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ExceptionConverterDriver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Exception.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PingableConnection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ResultStatement.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/LastInsertId.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ServerInfoAwareConnection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Statement.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/StatementIterator.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/DriverManager.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/ConnectionEventArgs.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaEventArgs.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Events.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ConnectionException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ConstraintViolationException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DatabaseObjectExistsException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DatabaseObjectNotFoundException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DeadlockException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DriverException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ForeignKeyConstraintViolationException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/InvalidArgumentException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/InvalidFieldNameException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/LockWaitTimeoutException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/NonUniqueFieldNameException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/NotNullConstraintViolationException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ReadOnlyException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/RetryableException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ServerException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/SyntaxErrorException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/TableExistsException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/TableNotFoundException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/UniqueConstraintViolationException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/FetchMode.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGenerator.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/LockMode.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/DebugStack.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/LoggerChain.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/SQLLogger.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/ParameterType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DB2Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DateIntervalUnit.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DrizzlePlatform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DrizzleKeywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/KeywordList.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MariaDb102Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MsSQLKeywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MySQL57Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MySQL80Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MySQLKeywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/OracleKeywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL100Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL91Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL92Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL94Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQLKeywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/ReservedKeywordsValidator.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere11Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere12Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere16Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhereKeywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLServer2005Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLServer2008Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLServer2012Keywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLServerKeywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLiteKeywords.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MariaDb1027Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL57Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL80Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/OraclePlatform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL100Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL94Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere12Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere16Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAzurePlatform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2012Platform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/TrimMode.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Connection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Statement.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/CompositeExpression.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryBuilder.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtils.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtilsException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractAsset.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Column.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ColumnDiff.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Comparator.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Constraint.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DB2SchemaManager.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DrizzleSchemaManager.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Identifier.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLAnywhereSchemaManager.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Schema.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaConfig.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaDiff.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Sequence.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SingleDatabaseSynchronizer.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Table.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/TableDiff.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/View.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Graphviz.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/NamespaceVisitor.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/SchemaDiffVisitor.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Visitor.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardConnection.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardChoser/ShardChoser.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardManager.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardingException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Helper/ConnectionHelper.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Dumper.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/TransactionIsolationLevel.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ArrayType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BigIntType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BinaryType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BlobType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BooleanType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ConversionException.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateImmutableType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateIntervalType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeImmutableType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzImmutableType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DecimalType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/FloatType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/GuidType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/IntegerType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonArrayType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ObjectType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/PhpDateTimeMappingType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/PhpIntegerMappingType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SimpleArrayType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SmallIntType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/StringType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TextType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeImmutableType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TypeRegistry.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeImmutableType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeType.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Version.php create mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/VersionAwarePlatformDriver.php create mode 100644 vendor/doctrine/doctrine-bundle/.github/FUNDING.yml create mode 100644 vendor/doctrine/doctrine-bundle/Command/CreateDatabaseDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/DoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/DropDatabaseDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/ImportMappingDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/ClearMetadataCacheDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/ClearQueryCacheDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/ClearResultCacheDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/CollectionRegionDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/ConvertMappingDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/CreateSchemaDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/DelegateCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/DoctrineCommandHelper.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/DropSchemaDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/EnsureProductionSettingsDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/EntityRegionCacheDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/ImportDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/InfoDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/QueryRegionCacheDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/RunDqlDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/RunSqlDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/UpdateSchemaDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/ValidateSchemaCommand.php create mode 100644 vendor/doctrine/doctrine-bundle/ConnectionFactory.php create mode 100644 vendor/doctrine/doctrine-bundle/Controller/ProfilerController.php create mode 100644 vendor/doctrine/doctrine-bundle/DataCollector/DoctrineDataCollector.php create mode 100644 vendor/doctrine/doctrine-bundle/Dbal/BlacklistSchemaAssetFilter.php create mode 100644 vendor/doctrine/doctrine-bundle/Dbal/Logging/BacktraceLogger.php create mode 100644 vendor/doctrine/doctrine-bundle/Dbal/RegexSchemaAssetFilter.php create mode 100644 vendor/doctrine/doctrine-bundle/Dbal/SchemaAssetsFilterManager.php create mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DbalSchemaFilterPass.php create mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DoctrineOrmMappingsPass.php create mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/EntityListenerPass.php create mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/ServiceRepositoryCompilerPass.php create mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/WellKnownSchemaFilterPass.php create mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/Configuration.php create mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/DoctrineExtension.php create mode 100644 vendor/doctrine/doctrine-bundle/DoctrineBundle.php create mode 100644 vendor/doctrine/doctrine-bundle/LICENSE create mode 100644 vendor/doctrine/doctrine-bundle/ManagerConfigurator.php create mode 100644 vendor/doctrine/doctrine-bundle/Mapping/ClassMetadataCollection.php create mode 100644 vendor/doctrine/doctrine-bundle/Mapping/ContainerEntityListenerResolver.php create mode 100644 vendor/doctrine/doctrine-bundle/Mapping/DisconnectedMetadataFactory.php create mode 100644 vendor/doctrine/doctrine-bundle/Mapping/EntityListenerServiceResolver.php create mode 100644 vendor/doctrine/doctrine-bundle/README.md create mode 100644 vendor/doctrine/doctrine-bundle/Registry.php create mode 100644 vendor/doctrine/doctrine-bundle/Repository/ContainerRepositoryFactory.php create mode 100644 vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepository.php create mode 100644 vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepositoryInterface.php create mode 100644 vendor/doctrine/doctrine-bundle/Resources/config/dbal.xml create mode 100644 vendor/doctrine/doctrine-bundle/Resources/config/messenger.xml create mode 100644 vendor/doctrine/doctrine-bundle/Resources/config/orm.xml create mode 100644 vendor/doctrine/doctrine-bundle/Resources/config/schema/doctrine-1.0.xsd create mode 100644 vendor/doctrine/doctrine-bundle/Resources/views/Collector/db.html.twig create mode 100644 vendor/doctrine/doctrine-bundle/Resources/views/Collector/explain.html.twig create mode 100644 vendor/doctrine/doctrine-bundle/Resources/views/Collector/icon.svg create mode 100644 vendor/doctrine/doctrine-bundle/Twig/DoctrineExtension.php create mode 100644 vendor/doctrine/doctrine-bundle/UPGRADE-1.11.md create mode 100644 vendor/doctrine/doctrine-bundle/UPGRADE-1.12.md create mode 100644 vendor/doctrine/doctrine-bundle/UPGRADE-2.0.md create mode 100644 vendor/doctrine/doctrine-bundle/UPGRADE-3.0.md create mode 100644 vendor/doctrine/doctrine-bundle/composer.json create mode 100644 vendor/doctrine/doctrine-bundle/phpcs.xml.dist create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/.github/FUNDING.yml create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/.gitignore create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/.travis.yml create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/CHANGELOG-3.1.md create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Command/LoadDataFixturesDoctrineCommand.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/CompilerPass/FixturesCompilerPass.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/DoctrineFixturesExtension.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/DoctrineFixturesBundle.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Fixture.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/FixtureGroupInterface.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/LICENSE create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Loader/SymfonyFixturesLoader.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/ORMFixtureInterface.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/README.markdown create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Resources/config/services.xml create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Resources/doc/index.rst create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/Command/LoadDataFixturesDoctrineCommandTest.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/DependentOnRequiredConstructorArgsFixtures.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/OtherFixtures.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/RequiredConstructorArgsFixtures.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/WithDependenciesFixtures.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/FooBundle.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/IntegrationTest.php create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/UPGRADE.md create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/composer.json create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/phpcs.xml.dist create mode 100644 vendor/doctrine/doctrine-fixtures-bundle/phpunit.xml.dist create mode 100644 vendor/doctrine/event-manager/.doctrine-project.json create mode 100644 vendor/doctrine/event-manager/LICENSE create mode 100644 vendor/doctrine/event-manager/README.md create mode 100644 vendor/doctrine/event-manager/composer.json create mode 100644 vendor/doctrine/event-manager/lib/Doctrine/Common/EventArgs.php create mode 100644 vendor/doctrine/event-manager/lib/Doctrine/Common/EventManager.php create mode 100644 vendor/doctrine/event-manager/lib/Doctrine/Common/EventSubscriber.php create mode 100644 vendor/doctrine/inflector/LICENSE create mode 100644 vendor/doctrine/inflector/README.md create mode 100644 vendor/doctrine/inflector/composer.json create mode 100644 vendor/doctrine/inflector/docs/en/index.rst create mode 100644 vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php create mode 100644 vendor/doctrine/instantiator/.doctrine-project.json create mode 100644 vendor/doctrine/instantiator/.github/FUNDING.yml create mode 100644 vendor/doctrine/instantiator/CONTRIBUTING.md create mode 100644 vendor/doctrine/instantiator/LICENSE create mode 100644 vendor/doctrine/instantiator/README.md create mode 100644 vendor/doctrine/instantiator/composer.json create mode 100644 vendor/doctrine/instantiator/docs/en/index.rst create mode 100644 vendor/doctrine/instantiator/docs/en/sidebar.rst create mode 100644 vendor/doctrine/instantiator/phpbench.json create mode 100644 vendor/doctrine/instantiator/phpcs.xml.dist create mode 100644 vendor/doctrine/instantiator/phpstan.neon.dist create mode 100644 vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php create mode 100644 vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php create mode 100644 vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php create mode 100644 vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php create mode 100644 vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php create mode 100644 vendor/doctrine/lexer/LICENSE create mode 100644 vendor/doctrine/lexer/README.md create mode 100644 vendor/doctrine/lexer/composer.json create mode 100644 vendor/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php create mode 100644 vendor/doctrine/orm/.scrutinizer.yml create mode 100644 vendor/doctrine/orm/LICENSE create mode 100644 vendor/doctrine/orm/README.md create mode 100644 vendor/doctrine/orm/SECURITY.md create mode 100644 vendor/doctrine/orm/UPGRADE.md create mode 100755 vendor/doctrine/orm/bin/doctrine create mode 100644 vendor/doctrine/orm/bin/doctrine-pear.php create mode 100644 vendor/doctrine/orm/bin/doctrine.bat create mode 100644 vendor/doctrine/orm/bin/doctrine.php create mode 100644 vendor/doctrine/orm/composer.json create mode 100644 vendor/doctrine/orm/composer.lock create mode 100644 vendor/doctrine/orm/docs/LICENSE.md create mode 100644 vendor/doctrine/orm/docs/README.md create mode 100755 vendor/doctrine/orm/docs/bin/generate-docs.sh create mode 100644 vendor/doctrine/orm/docs/bin/install-dependencies.sh create mode 100644 vendor/doctrine/orm/docs/en/Makefile create mode 100644 vendor/doctrine/orm/docs/en/_exts/configurationblock.py create mode 100644 vendor/doctrine/orm/docs/en/conf.py create mode 100644 vendor/doctrine/orm/docs/en/cookbook/advanced-field-value-conversion-using-custom-mapping-types.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/aggregate-fields.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/custom-mapping-types.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/decorator-pattern.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/dql-custom-walkers.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/dql-user-defined-functions.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/entities-in-session.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/implementing-arrayaccess-for-domain-objects.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/implementing-the-notify-changetracking-policy.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/implementing-wakeup-or-clone.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/mysql-enums.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/resolve-target-entity-listener.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/sql-table-prefixes.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/strategy-cookbook-introduction.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/validation-of-entities.rst create mode 100644 vendor/doctrine/orm/docs/en/cookbook/working-with-datetime.rst create mode 100644 vendor/doctrine/orm/docs/en/index.rst create mode 100644 vendor/doctrine/orm/docs/en/make.bat create mode 100644 vendor/doctrine/orm/docs/en/reference/advanced-configuration.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/annotations-reference.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/architecture.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/association-mapping.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/basic-mapping.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/batch-processing.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/best-practices.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/caching.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/change-tracking-policies.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/configuration.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/dql-doctrine-query-language.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/events.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/faq.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/filters.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/improving-performance.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/inheritance-mapping.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/installation.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/limitations-and-known-issues.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/metadata-drivers.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/namingstrategy.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/native-sql.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/partial-objects.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/php-mapping.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/query-builder.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/second-level-cache.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/security.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/tools.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/transactions-and-concurrency.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/unitofwork-associations.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/unitofwork.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/working-with-associations.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/working-with-objects.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/xml-mapping.rst create mode 100644 vendor/doctrine/orm/docs/en/reference/yaml-mapping.rst create mode 100644 vendor/doctrine/orm/docs/en/sidebar.rst create mode 100644 vendor/doctrine/orm/docs/en/toc.rst create mode 100644 vendor/doctrine/orm/docs/en/tutorials/composite-primary-keys.rst create mode 100644 vendor/doctrine/orm/docs/en/tutorials/embeddables.rst create mode 100644 vendor/doctrine/orm/docs/en/tutorials/extra-lazy-associations.rst create mode 100644 vendor/doctrine/orm/docs/en/tutorials/getting-started-database.rst create mode 100644 vendor/doctrine/orm/docs/en/tutorials/getting-started-models.rst create mode 100644 vendor/doctrine/orm/docs/en/tutorials/getting-started.rst create mode 100644 vendor/doctrine/orm/docs/en/tutorials/ordered-associations.rst create mode 100644 vendor/doctrine/orm/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst create mode 100644 vendor/doctrine/orm/docs/en/tutorials/pagination.rst create mode 100644 vendor/doctrine/orm/docs/en/tutorials/working-with-indexed-associations.rst create mode 100644 vendor/doctrine/orm/doctrine-mapping.xsd create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/AssociationCacheEntry.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheConfiguration.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheEntry.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheFactory.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheKey.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheEntry.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheKey.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionHydrator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/ConcurrentRegion.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCache.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCacheFactory.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCollectionHydrator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultEntityHydrator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultQueryCache.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheEntry.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheKey.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityHydrator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Lock.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/LockException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLogger.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLoggerChain.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/StatisticsCacheLogger.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/MultiGetRegion.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/CachedPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/AbstractCollectionPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/CachedCollectionPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/NonStrictReadWriteCachedCollectionPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/AbstractEntityPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/CachedEntityPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/NonStrictReadWriteCachedEntityPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadOnlyCachedEntityPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCache.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheEntry.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheKey.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheValidator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultMultiGetRegion.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultRegion.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/FileLockRegion.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/UpdateTimestampCache.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/RegionsConfiguration.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheEntry.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheKey.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampQueryCacheValidator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampRegion.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Configuration.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Decorator/EntityManagerDecorator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/EntityManagerInterface.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/EntityNotFoundException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/LifecycleEventArgs.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/ListenersInvoker.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClassMetadataNotFoundEventArgs.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClearEventArgs.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnFlushEventArgs.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/PostFlushEventArgs.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreFlushEventArgs.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Events.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/AbstractIdGenerator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/AssignedGenerator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/BigIntegerIdentityGenerator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/IdentityGenerator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/SequenceGenerator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/TableGenerator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/UuidGenerator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/CommitOrderCalculator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/HydrationException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/IterableResult.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ScalarHydrator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/HydrationCompleteHandler.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/LazyCriteriaCollection.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Annotation.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AnsiQuoteStrategy.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverride.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverrides.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverride.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverrides.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EmbeddedBuilder.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EntityListenerBuilder.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ManyToManyAssociationBuilder.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/OneToManyAssociationBuilder.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Cache.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ChangeTrackingPolicy.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadata.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Column.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ColumnResult.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/CustomIdGenerator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultEntityListenerResolver.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultNamingStrategy.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultQuoteStrategy.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorColumn.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorMap.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DriverChain.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/PHPDriver.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedXmlDriver.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedYamlDriver.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/StaticPHPDriver.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embeddable.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embedded.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Entity.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListenerResolver.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListeners.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityResult.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/FieldResult.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/GeneratedValue.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/HasLifecycleCallbacks.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Id.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Index.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/InheritanceType.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumn.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumns.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinTable.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToMany.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToOne.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappedSuperclass.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappingException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQueries.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQuery.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQueries.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQuery.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamingStrategy.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToMany.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToOne.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OrderBy.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostLoad.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostPersist.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostRemove.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostUpdate.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreFlush.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PrePersist.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreRemove.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreUpdate.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/QuoteStrategy.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Reflection/ReflectionPropertiesGetter.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ReflectionEmbeddedProperty.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SequenceGenerator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMapping.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMappings.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Table.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UnderscoreNamingStrategy.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UniqueConstraint.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Version.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/NativeQuery.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/NoResultException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/NonUniqueResultException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/ORMException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/ORMInvalidArgumentException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/OptimisticLockException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/PersistentCollection.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/AbstractCollectionPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/CollectionPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/OneToManyPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/CachedPersisterContext.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/EntityPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/PersisterException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlExpressionVisitor.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlValueVisitor.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/PessimisticLockException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Autoloader.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Proxy.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ASTException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/AggregateExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticFactor.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticTerm.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/BetweenExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CoalesceExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CollectionMemberExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ComparisonExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalFactor.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalPrimary.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalTerm.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteClause.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteStatement.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/EmptyCollectionComparisonExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ExistsExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/FromClause.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AbsFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AvgFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitAndFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitOrFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CountFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentDateFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimeFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimestampFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateDiffFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/FunctionNode.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/IdentityFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LengthFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LocateFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MaxFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MinFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ModFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SqrtFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SumFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GeneralCaseExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GroupByClause.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/HavingClause.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IdentificationVariableDeclaration.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IndexBy.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InputParameter.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InstanceOfExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Join.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationDeclaration.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationPathExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinClassPathExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinVariableDeclaration.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/LikeExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Literal.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NewObjectExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Node.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullComparisonExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullIfExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByClause.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByItem.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ParenthesisExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PartialObjectExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PathExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/QuantifiedExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/RangeVariableDeclaration.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectClause.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectStatement.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleArithmeticExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleCaseExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectClause.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectExpression.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleWhenClause.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Subselect.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectFromClause.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectIdentificationVariableDeclaration.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateClause.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateItem.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateStatement.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhenClause.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhereClause.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleSelectExecutor.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Andx.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Base.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Comparison.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Composite.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/From.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Func.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/GroupBy.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Join.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Literal.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Math.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/OrderBy.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Orx.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Select.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Filter/SQLFilter.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/FilterCollection.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Lexer.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parameter.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParameterTypeInferer.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParserResult.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Printer.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryExpressionVisitor.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMapping.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalker.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerAdapter.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChain.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChainIterator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/QueryBuilder.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Repository/RepositoryFactory.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/AttachEntityListenersListener.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/CollectionRegionCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/EntityRegionCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/MetadataCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryRegionCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/AbstractCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ValidateSchemaCommand.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Helper/EntityManagerHelper.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/MetadataFilter.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DebugUnitOfWorkListener.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DisconnectedClassMetadataFactory.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityGenerator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityRepositoryGenerator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaEventArgs.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaTableEventArgs.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ClassMetadataExporter.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ExportException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountWalker.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/Paginator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/RowNumberOverFunction.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ResolveTargetEntityListener.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaTool.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaValidator.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Setup.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolEvents.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolsException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/TransactionRequiredException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/UnexpectedResultException.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Utility/HierarchyDiscriminatorResolver.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Utility/IdentifierFlattener.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Utility/PersisterHelper.php create mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Version.php create mode 100644 vendor/doctrine/orm/phpbench.json create mode 100644 vendor/doctrine/orm/phpstan.neon create mode 100644 vendor/doctrine/persistence/.doctrine-project.json create mode 100644 vendor/doctrine/persistence/LICENSE create mode 100644 vendor/doctrine/persistence/README.md create mode 100644 vendor/doctrine/persistence/UPGRADE-1.2.md create mode 100644 vendor/doctrine/persistence/composer.json create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/NotifyPropertyChanged.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/AbstractManagerRegistry.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/ConnectionRegistry.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Event/LifecycleEventArgs.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Event/LoadClassMetadataEventArgs.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Event/ManagerEventArgs.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Event/OnClearEventArgs.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Event/PreUpdateEventArgs.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/ManagerRegistry.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/ClassMetadata.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/ClassMetadataFactory.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/DefaultFileLocator.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/FileDriver.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/FileLocator.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/MappingDriver.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/MappingDriverChain.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/PHPDriver.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/StaticPHPDriver.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/SymfonyFileLocator.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/MappingException.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/ReflectionService.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/StaticReflectionService.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/ObjectManager.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/ObjectManagerAware.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/ObjectManagerDecorator.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/ObjectRepository.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/PersistentObject.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Proxy.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/PropertyChangedListener.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/AbstractManagerRegistry.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/ConnectionRegistry.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/LifecycleEventArgs.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/LoadClassMetadataEventArgs.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/ManagerEventArgs.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/OnClearEventArgs.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/PreUpdateEventArgs.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/ManagerRegistry.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/AbstractClassMetadataFactory.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/ClassMetadata.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/ClassMetadataFactory.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/AnnotationDriver.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/DefaultFileLocator.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileDriver.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileLocator.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/MappingDriver.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/MappingDriverChain.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/PHPDriver.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/StaticPHPDriver.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/SymfonyFileLocator.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/MappingException.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/ReflectionService.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/RuntimeReflectionService.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/StaticReflectionService.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/NotifyPropertyChanged.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectManager.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectManagerAware.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectManagerDecorator.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectRepository.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/PropertyChangedListener.php create mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Proxy.php create mode 100644 vendor/doctrine/reflection/.scrutinizer.yml create mode 100644 vendor/doctrine/reflection/LICENSE create mode 100644 vendor/doctrine/reflection/README.md create mode 100644 vendor/doctrine/reflection/composer.json create mode 100644 vendor/doctrine/reflection/docs/en/index.rst create mode 100644 vendor/doctrine/reflection/docs/en/reference/index.rst create mode 100644 vendor/doctrine/reflection/docs/en/sidebar.rst create mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ClassFinderInterface.php create mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/Psr0FindFile.php create mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ReflectionProviderInterface.php create mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/RuntimePublicReflectionProperty.php create mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionClass.php create mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionMethod.php create mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionParser.php create mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionProperty.php create mode 100644 vendor/doctrine/reflection/phpstan.neon create mode 100644 vendor/jdorn/sql-formatter/.gitignore create mode 100644 vendor/jdorn/sql-formatter/.travis.yml create mode 100644 vendor/jdorn/sql-formatter/LICENSE.txt create mode 100644 vendor/jdorn/sql-formatter/README.md create mode 100644 vendor/jdorn/sql-formatter/composer.json create mode 100644 vendor/jdorn/sql-formatter/composer.lock create mode 100644 vendor/jdorn/sql-formatter/examples/cli.php create mode 100644 vendor/jdorn/sql-formatter/examples/examples.php create mode 100644 vendor/jdorn/sql-formatter/lib/SqlFormatter.php create mode 100644 vendor/jdorn/sql-formatter/phpunit.xml.dist create mode 100644 vendor/jdorn/sql-formatter/tests/SqlFormatterTest.php create mode 100644 vendor/jdorn/sql-formatter/tests/clihighlight.html create mode 100644 vendor/jdorn/sql-formatter/tests/compress.html create mode 100644 vendor/jdorn/sql-formatter/tests/format-highlight.html create mode 100644 vendor/jdorn/sql-formatter/tests/format.html create mode 100644 vendor/jdorn/sql-formatter/tests/highlight.html create mode 100644 vendor/jdorn/sql-formatter/tests/performance.php create mode 100644 vendor/jdorn/sql-formatter/tests/sql.sql create mode 100644 vendor/psr/cache/CHANGELOG.md create mode 100644 vendor/psr/cache/LICENSE.txt create mode 100644 vendor/psr/cache/README.md create mode 100644 vendor/psr/cache/composer.json create mode 100644 vendor/psr/cache/src/CacheException.php create mode 100644 vendor/psr/cache/src/CacheItemInterface.php create mode 100644 vendor/psr/cache/src/CacheItemPoolInterface.php create mode 100644 vendor/psr/cache/src/InvalidArgumentException.php create mode 100644 vendor/psr/container/.gitignore create mode 100644 vendor/psr/container/LICENSE create mode 100644 vendor/psr/container/README.md create mode 100644 vendor/psr/container/composer.json create mode 100644 vendor/psr/container/src/ContainerExceptionInterface.php create mode 100644 vendor/psr/container/src/ContainerInterface.php create mode 100644 vendor/psr/container/src/NotFoundExceptionInterface.php create mode 100644 vendor/psr/event-dispatcher/.editorconfig create mode 100644 vendor/psr/event-dispatcher/.gitignore create mode 100644 vendor/psr/event-dispatcher/LICENSE create mode 100644 vendor/psr/event-dispatcher/README.md create mode 100644 vendor/psr/event-dispatcher/composer.json create mode 100644 vendor/psr/event-dispatcher/src/EventDispatcherInterface.php create mode 100644 vendor/psr/event-dispatcher/src/ListenerProviderInterface.php create mode 100644 vendor/psr/event-dispatcher/src/StoppableEventInterface.php create mode 100644 vendor/psr/log/.gitignore create mode 100644 vendor/psr/log/LICENSE create mode 100644 vendor/psr/log/Psr/Log/AbstractLogger.php create mode 100644 vendor/psr/log/Psr/Log/InvalidArgumentException.php create mode 100644 vendor/psr/log/Psr/Log/LogLevel.php create mode 100644 vendor/psr/log/Psr/Log/LoggerAwareInterface.php create mode 100644 vendor/psr/log/Psr/Log/LoggerAwareTrait.php create mode 100644 vendor/psr/log/Psr/Log/LoggerInterface.php create mode 100644 vendor/psr/log/Psr/Log/LoggerTrait.php create mode 100644 vendor/psr/log/Psr/Log/NullLogger.php create mode 100644 vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php create mode 100644 vendor/psr/log/Psr/Log/Test/TestLogger.php create mode 100644 vendor/psr/log/README.md create mode 100644 vendor/psr/log/composer.json create mode 100644 vendor/symfony/cache-contracts/.gitignore create mode 100644 vendor/symfony/cache-contracts/CacheInterface.php create mode 100644 vendor/symfony/cache-contracts/CacheTrait.php create mode 100644 vendor/symfony/cache-contracts/CallbackInterface.php create mode 100644 vendor/symfony/cache-contracts/ItemInterface.php create mode 100644 vendor/symfony/cache-contracts/LICENSE create mode 100644 vendor/symfony/cache-contracts/README.md create mode 100644 vendor/symfony/cache-contracts/TagAwareCacheInterface.php create mode 100644 vendor/symfony/cache-contracts/composer.json create mode 100644 vendor/symfony/cache/.gitattributes create mode 100644 vendor/symfony/cache/Adapter/AbstractAdapter.php create mode 100644 vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php create mode 100644 vendor/symfony/cache/Adapter/AdapterInterface.php create mode 100644 vendor/symfony/cache/Adapter/ApcuAdapter.php create mode 100644 vendor/symfony/cache/Adapter/ArrayAdapter.php create mode 100644 vendor/symfony/cache/Adapter/ChainAdapter.php create mode 100644 vendor/symfony/cache/Adapter/DoctrineAdapter.php create mode 100644 vendor/symfony/cache/Adapter/FilesystemAdapter.php create mode 100644 vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php create mode 100644 vendor/symfony/cache/Adapter/MemcachedAdapter.php create mode 100644 vendor/symfony/cache/Adapter/NullAdapter.php create mode 100644 vendor/symfony/cache/Adapter/PdoAdapter.php create mode 100644 vendor/symfony/cache/Adapter/PhpArrayAdapter.php create mode 100644 vendor/symfony/cache/Adapter/PhpFilesAdapter.php create mode 100644 vendor/symfony/cache/Adapter/ProxyAdapter.php create mode 100644 vendor/symfony/cache/Adapter/Psr16Adapter.php create mode 100644 vendor/symfony/cache/Adapter/RedisAdapter.php create mode 100644 vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php create mode 100644 vendor/symfony/cache/Adapter/TagAwareAdapter.php create mode 100644 vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php create mode 100644 vendor/symfony/cache/Adapter/TraceableAdapter.php create mode 100644 vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php create mode 100644 vendor/symfony/cache/CHANGELOG.md create mode 100644 vendor/symfony/cache/CacheItem.php create mode 100644 vendor/symfony/cache/DataCollector/CacheDataCollector.php create mode 100644 vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php create mode 100644 vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php create mode 100644 vendor/symfony/cache/DependencyInjection/CachePoolPass.php create mode 100644 vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php create mode 100644 vendor/symfony/cache/DoctrineProvider.php create mode 100644 vendor/symfony/cache/Exception/CacheException.php create mode 100644 vendor/symfony/cache/Exception/InvalidArgumentException.php create mode 100644 vendor/symfony/cache/Exception/LogicException.php create mode 100644 vendor/symfony/cache/LICENSE create mode 100644 vendor/symfony/cache/LockRegistry.php create mode 100644 vendor/symfony/cache/Marshaller/DefaultMarshaller.php create mode 100644 vendor/symfony/cache/Marshaller/DeflateMarshaller.php create mode 100644 vendor/symfony/cache/Marshaller/MarshallerInterface.php create mode 100644 vendor/symfony/cache/Marshaller/TagAwareMarshaller.php create mode 100644 vendor/symfony/cache/PruneableInterface.php create mode 100644 vendor/symfony/cache/Psr16Cache.php create mode 100644 vendor/symfony/cache/README.md create mode 100644 vendor/symfony/cache/ResettableInterface.php create mode 100644 vendor/symfony/cache/Traits/AbstractAdapterTrait.php create mode 100644 vendor/symfony/cache/Traits/ContractsTrait.php create mode 100644 vendor/symfony/cache/Traits/FilesystemCommonTrait.php create mode 100644 vendor/symfony/cache/Traits/FilesystemTrait.php create mode 100644 vendor/symfony/cache/Traits/ProxyTrait.php create mode 100644 vendor/symfony/cache/Traits/RedisClusterProxy.php create mode 100644 vendor/symfony/cache/Traits/RedisProxy.php create mode 100644 vendor/symfony/cache/Traits/RedisTrait.php create mode 100644 vendor/symfony/cache/composer.json create mode 100644 vendor/symfony/config/.gitattributes create mode 100644 vendor/symfony/config/CHANGELOG.md create mode 100644 vendor/symfony/config/ConfigCache.php create mode 100644 vendor/symfony/config/ConfigCacheFactory.php create mode 100644 vendor/symfony/config/ConfigCacheFactoryInterface.php create mode 100644 vendor/symfony/config/ConfigCacheInterface.php create mode 100644 vendor/symfony/config/Definition/ArrayNode.php create mode 100644 vendor/symfony/config/Definition/BaseNode.php create mode 100644 vendor/symfony/config/Definition/BooleanNode.php create mode 100644 vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php create mode 100644 vendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php create mode 100644 vendor/symfony/config/Definition/Builder/BuilderAwareInterface.php create mode 100644 vendor/symfony/config/Definition/Builder/EnumNodeDefinition.php create mode 100644 vendor/symfony/config/Definition/Builder/ExprBuilder.php create mode 100644 vendor/symfony/config/Definition/Builder/FloatNodeDefinition.php create mode 100644 vendor/symfony/config/Definition/Builder/IntegerNodeDefinition.php create mode 100644 vendor/symfony/config/Definition/Builder/MergeBuilder.php create mode 100644 vendor/symfony/config/Definition/Builder/NodeBuilder.php create mode 100644 vendor/symfony/config/Definition/Builder/NodeDefinition.php create mode 100644 vendor/symfony/config/Definition/Builder/NodeParentInterface.php create mode 100644 vendor/symfony/config/Definition/Builder/NormalizationBuilder.php create mode 100644 vendor/symfony/config/Definition/Builder/NumericNodeDefinition.php create mode 100644 vendor/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php create mode 100644 vendor/symfony/config/Definition/Builder/ScalarNodeDefinition.php create mode 100644 vendor/symfony/config/Definition/Builder/TreeBuilder.php create mode 100644 vendor/symfony/config/Definition/Builder/ValidationBuilder.php create mode 100644 vendor/symfony/config/Definition/Builder/VariableNodeDefinition.php create mode 100644 vendor/symfony/config/Definition/ConfigurationInterface.php create mode 100644 vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.php create mode 100644 vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.php create mode 100644 vendor/symfony/config/Definition/EnumNode.php create mode 100644 vendor/symfony/config/Definition/Exception/DuplicateKeyException.php create mode 100644 vendor/symfony/config/Definition/Exception/Exception.php create mode 100644 vendor/symfony/config/Definition/Exception/ForbiddenOverwriteException.php create mode 100644 vendor/symfony/config/Definition/Exception/InvalidConfigurationException.php create mode 100644 vendor/symfony/config/Definition/Exception/InvalidDefinitionException.php create mode 100644 vendor/symfony/config/Definition/Exception/InvalidTypeException.php create mode 100644 vendor/symfony/config/Definition/Exception/UnsetKeyException.php create mode 100644 vendor/symfony/config/Definition/FloatNode.php create mode 100644 vendor/symfony/config/Definition/IntegerNode.php create mode 100644 vendor/symfony/config/Definition/NodeInterface.php create mode 100644 vendor/symfony/config/Definition/NumericNode.php create mode 100644 vendor/symfony/config/Definition/Processor.php create mode 100644 vendor/symfony/config/Definition/PrototypeNodeInterface.php create mode 100644 vendor/symfony/config/Definition/PrototypedArrayNode.php create mode 100644 vendor/symfony/config/Definition/ScalarNode.php create mode 100644 vendor/symfony/config/Definition/VariableNode.php create mode 100644 vendor/symfony/config/Exception/FileLoaderImportCircularReferenceException.php create mode 100644 vendor/symfony/config/Exception/FileLocatorFileNotFoundException.php create mode 100644 vendor/symfony/config/Exception/LoaderLoadException.php create mode 100644 vendor/symfony/config/FileLocator.php create mode 100644 vendor/symfony/config/FileLocatorInterface.php create mode 100644 vendor/symfony/config/LICENSE create mode 100644 vendor/symfony/config/Loader/DelegatingLoader.php create mode 100644 vendor/symfony/config/Loader/FileLoader.php create mode 100644 vendor/symfony/config/Loader/GlobFileLoader.php create mode 100644 vendor/symfony/config/Loader/Loader.php create mode 100644 vendor/symfony/config/Loader/LoaderInterface.php create mode 100644 vendor/symfony/config/Loader/LoaderResolver.php create mode 100644 vendor/symfony/config/Loader/LoaderResolverInterface.php create mode 100644 vendor/symfony/config/README.md create mode 100644 vendor/symfony/config/Resource/ClassExistenceResource.php create mode 100644 vendor/symfony/config/Resource/ComposerResource.php create mode 100644 vendor/symfony/config/Resource/DirectoryResource.php create mode 100644 vendor/symfony/config/Resource/FileExistenceResource.php create mode 100644 vendor/symfony/config/Resource/FileResource.php create mode 100644 vendor/symfony/config/Resource/GlobResource.php create mode 100644 vendor/symfony/config/Resource/ReflectionClassResource.php create mode 100644 vendor/symfony/config/Resource/ResourceInterface.php create mode 100644 vendor/symfony/config/Resource/SelfCheckingResourceChecker.php create mode 100644 vendor/symfony/config/Resource/SelfCheckingResourceInterface.php create mode 100644 vendor/symfony/config/ResourceCheckerConfigCache.php create mode 100644 vendor/symfony/config/ResourceCheckerConfigCacheFactory.php create mode 100644 vendor/symfony/config/ResourceCheckerInterface.php create mode 100644 vendor/symfony/config/Util/Exception/InvalidXmlException.php create mode 100644 vendor/symfony/config/Util/Exception/XmlParsingException.php create mode 100644 vendor/symfony/config/Util/XmlUtils.php create mode 100644 vendor/symfony/config/composer.json create mode 100644 vendor/symfony/console/.gitattributes create mode 100644 vendor/symfony/console/Application.php create mode 100644 vendor/symfony/console/CHANGELOG.md create mode 100644 vendor/symfony/console/Command/Command.php create mode 100644 vendor/symfony/console/Command/HelpCommand.php create mode 100644 vendor/symfony/console/Command/ListCommand.php create mode 100644 vendor/symfony/console/Command/LockableTrait.php create mode 100644 vendor/symfony/console/CommandLoader/CommandLoaderInterface.php create mode 100644 vendor/symfony/console/CommandLoader/ContainerCommandLoader.php create mode 100644 vendor/symfony/console/CommandLoader/FactoryCommandLoader.php create mode 100644 vendor/symfony/console/ConsoleEvents.php create mode 100644 vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php create mode 100644 vendor/symfony/console/Descriptor/ApplicationDescription.php create mode 100644 vendor/symfony/console/Descriptor/Descriptor.php create mode 100644 vendor/symfony/console/Descriptor/DescriptorInterface.php create mode 100644 vendor/symfony/console/Descriptor/JsonDescriptor.php create mode 100644 vendor/symfony/console/Descriptor/MarkdownDescriptor.php create mode 100644 vendor/symfony/console/Descriptor/TextDescriptor.php create mode 100644 vendor/symfony/console/Descriptor/XmlDescriptor.php create mode 100644 vendor/symfony/console/Event/ConsoleCommandEvent.php create mode 100644 vendor/symfony/console/Event/ConsoleErrorEvent.php create mode 100644 vendor/symfony/console/Event/ConsoleEvent.php create mode 100644 vendor/symfony/console/Event/ConsoleTerminateEvent.php create mode 100644 vendor/symfony/console/EventListener/ErrorListener.php create mode 100644 vendor/symfony/console/Exception/CommandNotFoundException.php create mode 100644 vendor/symfony/console/Exception/ExceptionInterface.php create mode 100644 vendor/symfony/console/Exception/InvalidArgumentException.php create mode 100644 vendor/symfony/console/Exception/InvalidOptionException.php create mode 100644 vendor/symfony/console/Exception/LogicException.php create mode 100644 vendor/symfony/console/Exception/NamespaceNotFoundException.php create mode 100644 vendor/symfony/console/Exception/RuntimeException.php create mode 100644 vendor/symfony/console/Formatter/OutputFormatter.php create mode 100644 vendor/symfony/console/Formatter/OutputFormatterInterface.php create mode 100644 vendor/symfony/console/Formatter/OutputFormatterStyle.php create mode 100644 vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php create mode 100644 vendor/symfony/console/Formatter/OutputFormatterStyleStack.php create mode 100644 vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php create mode 100644 vendor/symfony/console/Helper/DebugFormatterHelper.php create mode 100644 vendor/symfony/console/Helper/DescriptorHelper.php create mode 100644 vendor/symfony/console/Helper/Dumper.php create mode 100644 vendor/symfony/console/Helper/FormatterHelper.php create mode 100644 vendor/symfony/console/Helper/Helper.php create mode 100644 vendor/symfony/console/Helper/HelperInterface.php create mode 100644 vendor/symfony/console/Helper/HelperSet.php create mode 100644 vendor/symfony/console/Helper/InputAwareHelper.php create mode 100644 vendor/symfony/console/Helper/ProcessHelper.php create mode 100644 vendor/symfony/console/Helper/ProgressBar.php create mode 100644 vendor/symfony/console/Helper/ProgressIndicator.php create mode 100644 vendor/symfony/console/Helper/QuestionHelper.php create mode 100644 vendor/symfony/console/Helper/SymfonyQuestionHelper.php create mode 100644 vendor/symfony/console/Helper/Table.php create mode 100644 vendor/symfony/console/Helper/TableCell.php create mode 100644 vendor/symfony/console/Helper/TableRows.php create mode 100644 vendor/symfony/console/Helper/TableSeparator.php create mode 100644 vendor/symfony/console/Helper/TableStyle.php create mode 100644 vendor/symfony/console/Input/ArgvInput.php create mode 100644 vendor/symfony/console/Input/ArrayInput.php create mode 100644 vendor/symfony/console/Input/Input.php create mode 100644 vendor/symfony/console/Input/InputArgument.php create mode 100644 vendor/symfony/console/Input/InputAwareInterface.php create mode 100644 vendor/symfony/console/Input/InputDefinition.php create mode 100644 vendor/symfony/console/Input/InputInterface.php create mode 100644 vendor/symfony/console/Input/InputOption.php create mode 100644 vendor/symfony/console/Input/StreamableInputInterface.php create mode 100644 vendor/symfony/console/Input/StringInput.php create mode 100644 vendor/symfony/console/LICENSE create mode 100644 vendor/symfony/console/Logger/ConsoleLogger.php create mode 100644 vendor/symfony/console/Output/BufferedOutput.php create mode 100644 vendor/symfony/console/Output/ConsoleOutput.php create mode 100644 vendor/symfony/console/Output/ConsoleOutputInterface.php create mode 100644 vendor/symfony/console/Output/ConsoleSectionOutput.php create mode 100644 vendor/symfony/console/Output/NullOutput.php create mode 100644 vendor/symfony/console/Output/Output.php create mode 100644 vendor/symfony/console/Output/OutputInterface.php create mode 100644 vendor/symfony/console/Output/StreamOutput.php create mode 100644 vendor/symfony/console/Question/ChoiceQuestion.php create mode 100644 vendor/symfony/console/Question/ConfirmationQuestion.php create mode 100644 vendor/symfony/console/Question/Question.php create mode 100644 vendor/symfony/console/README.md create mode 100644 vendor/symfony/console/Resources/bin/hiddeninput.exe create mode 100644 vendor/symfony/console/Style/OutputStyle.php create mode 100644 vendor/symfony/console/Style/StyleInterface.php create mode 100644 vendor/symfony/console/Style/SymfonyStyle.php create mode 100644 vendor/symfony/console/Terminal.php create mode 100644 vendor/symfony/console/Tester/ApplicationTester.php create mode 100644 vendor/symfony/console/Tester/CommandTester.php create mode 100644 vendor/symfony/console/Tester/TesterTrait.php create mode 100644 vendor/symfony/console/composer.json create mode 100644 vendor/symfony/dependency-injection/.gitattributes create mode 100644 vendor/symfony/dependency-injection/Alias.php create mode 100644 vendor/symfony/dependency-injection/Argument/ArgumentInterface.php create mode 100644 vendor/symfony/dependency-injection/Argument/BoundArgument.php create mode 100644 vendor/symfony/dependency-injection/Argument/IteratorArgument.php create mode 100644 vendor/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php create mode 100644 vendor/symfony/dependency-injection/Argument/RewindableGenerator.php create mode 100644 vendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php create mode 100644 vendor/symfony/dependency-injection/Argument/ServiceLocator.php create mode 100644 vendor/symfony/dependency-injection/Argument/ServiceLocatorArgument.php create mode 100644 vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php create mode 100644 vendor/symfony/dependency-injection/CHANGELOG.md create mode 100644 vendor/symfony/dependency-injection/ChildDefinition.php create mode 100644 vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/AutowirePass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/Compiler.php create mode 100644 vendor/symfony/dependency-injection/Compiler/CompilerPassInterface.php create mode 100644 vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/PassConfig.php create mode 100644 vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php create mode 100644 vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php create mode 100644 vendor/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php create mode 100644 vendor/symfony/dependency-injection/Config/ContainerParametersResource.php create mode 100644 vendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php create mode 100644 vendor/symfony/dependency-injection/Container.php create mode 100644 vendor/symfony/dependency-injection/ContainerAwareInterface.php create mode 100644 vendor/symfony/dependency-injection/ContainerAwareTrait.php create mode 100644 vendor/symfony/dependency-injection/ContainerBuilder.php create mode 100644 vendor/symfony/dependency-injection/ContainerInterface.php create mode 100644 vendor/symfony/dependency-injection/Definition.php create mode 100644 vendor/symfony/dependency-injection/Dumper/Dumper.php create mode 100644 vendor/symfony/dependency-injection/Dumper/DumperInterface.php create mode 100644 vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php create mode 100644 vendor/symfony/dependency-injection/Dumper/PhpDumper.php create mode 100644 vendor/symfony/dependency-injection/Dumper/Preloader.php create mode 100644 vendor/symfony/dependency-injection/Dumper/XmlDumper.php create mode 100644 vendor/symfony/dependency-injection/Dumper/YamlDumper.php create mode 100644 vendor/symfony/dependency-injection/EnvVarLoaderInterface.php create mode 100644 vendor/symfony/dependency-injection/EnvVarProcessor.php create mode 100644 vendor/symfony/dependency-injection/EnvVarProcessorInterface.php create mode 100644 vendor/symfony/dependency-injection/Exception/AutowiringFailedException.php create mode 100644 vendor/symfony/dependency-injection/Exception/BadMethodCallException.php create mode 100644 vendor/symfony/dependency-injection/Exception/EnvNotFoundException.php create mode 100644 vendor/symfony/dependency-injection/Exception/EnvParameterException.php create mode 100644 vendor/symfony/dependency-injection/Exception/ExceptionInterface.php create mode 100644 vendor/symfony/dependency-injection/Exception/InvalidArgumentException.php create mode 100644 vendor/symfony/dependency-injection/Exception/InvalidParameterTypeException.php create mode 100644 vendor/symfony/dependency-injection/Exception/LogicException.php create mode 100644 vendor/symfony/dependency-injection/Exception/OutOfBoundsException.php create mode 100644 vendor/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php create mode 100644 vendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php create mode 100644 vendor/symfony/dependency-injection/Exception/RuntimeException.php create mode 100644 vendor/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php create mode 100644 vendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php create mode 100644 vendor/symfony/dependency-injection/ExpressionLanguage.php create mode 100644 vendor/symfony/dependency-injection/ExpressionLanguageProvider.php create mode 100644 vendor/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php create mode 100644 vendor/symfony/dependency-injection/Extension/Extension.php create mode 100644 vendor/symfony/dependency-injection/Extension/ExtensionInterface.php create mode 100644 vendor/symfony/dependency-injection/Extension/PrependExtensionInterface.php create mode 100644 vendor/symfony/dependency-injection/LICENSE create mode 100644 vendor/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php create mode 100644 vendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php create mode 100644 vendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php create mode 100644 vendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php create mode 100644 vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php create mode 100644 vendor/symfony/dependency-injection/Loader/ClosureLoader.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php create mode 100644 vendor/symfony/dependency-injection/Loader/DirectoryLoader.php create mode 100644 vendor/symfony/dependency-injection/Loader/FileLoader.php create mode 100644 vendor/symfony/dependency-injection/Loader/GlobFileLoader.php create mode 100644 vendor/symfony/dependency-injection/Loader/IniFileLoader.php create mode 100644 vendor/symfony/dependency-injection/Loader/PhpFileLoader.php create mode 100644 vendor/symfony/dependency-injection/Loader/XmlFileLoader.php create mode 100644 vendor/symfony/dependency-injection/Loader/YamlFileLoader.php create mode 100644 vendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd create mode 100644 vendor/symfony/dependency-injection/Parameter.php create mode 100644 vendor/symfony/dependency-injection/ParameterBag/ContainerBag.php create mode 100644 vendor/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php create mode 100644 vendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php create mode 100644 vendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php create mode 100644 vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php create mode 100644 vendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php create mode 100644 vendor/symfony/dependency-injection/README.md create mode 100644 vendor/symfony/dependency-injection/Reference.php create mode 100644 vendor/symfony/dependency-injection/ReverseContainer.php create mode 100644 vendor/symfony/dependency-injection/ServiceLocator.php create mode 100644 vendor/symfony/dependency-injection/TaggedContainerInterface.php create mode 100644 vendor/symfony/dependency-injection/TypedReference.php create mode 100644 vendor/symfony/dependency-injection/Variable.php create mode 100644 vendor/symfony/dependency-injection/composer.json create mode 100644 vendor/symfony/doctrine-bridge/.gitattributes create mode 100644 vendor/symfony/doctrine-bridge/CHANGELOG.md create mode 100644 vendor/symfony/doctrine-bridge/CacheWarmer/ProxyCacheWarmer.php create mode 100644 vendor/symfony/doctrine-bridge/ContainerAwareEventManager.php create mode 100644 vendor/symfony/doctrine-bridge/DataCollector/DoctrineDataCollector.php create mode 100644 vendor/symfony/doctrine-bridge/DataCollector/ObjectParameter.php create mode 100644 vendor/symfony/doctrine-bridge/DataFixtures/ContainerAwareLoader.php create mode 100644 vendor/symfony/doctrine-bridge/DependencyInjection/AbstractDoctrineExtension.php create mode 100644 vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/DoctrineValidationPass.php create mode 100644 vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php create mode 100644 vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterMappingsPass.php create mode 100644 vendor/symfony/doctrine-bridge/DependencyInjection/Security/UserProvider/EntityFactory.php create mode 100644 vendor/symfony/doctrine-bridge/Form/ChoiceList/DoctrineChoiceLoader.php create mode 100644 vendor/symfony/doctrine-bridge/Form/ChoiceList/EntityLoaderInterface.php create mode 100644 vendor/symfony/doctrine-bridge/Form/ChoiceList/IdReader.php create mode 100644 vendor/symfony/doctrine-bridge/Form/ChoiceList/ORMQueryBuilderLoader.php create mode 100644 vendor/symfony/doctrine-bridge/Form/DataTransformer/CollectionToArrayTransformer.php create mode 100644 vendor/symfony/doctrine-bridge/Form/DoctrineOrmExtension.php create mode 100644 vendor/symfony/doctrine-bridge/Form/DoctrineOrmTypeGuesser.php create mode 100644 vendor/symfony/doctrine-bridge/Form/EventListener/MergeDoctrineCollectionListener.php create mode 100644 vendor/symfony/doctrine-bridge/Form/Type/DoctrineType.php create mode 100644 vendor/symfony/doctrine-bridge/Form/Type/EntityType.php create mode 100644 vendor/symfony/doctrine-bridge/LICENSE create mode 100644 vendor/symfony/doctrine-bridge/Logger/DbalLogger.php create mode 100644 vendor/symfony/doctrine-bridge/ManagerRegistry.php create mode 100644 vendor/symfony/doctrine-bridge/Messenger/AbstractDoctrineMiddleware.php create mode 100644 vendor/symfony/doctrine-bridge/Messenger/DoctrineClearEntityManagerWorkerSubscriber.php create mode 100644 vendor/symfony/doctrine-bridge/Messenger/DoctrineCloseConnectionMiddleware.php create mode 100644 vendor/symfony/doctrine-bridge/Messenger/DoctrinePingConnectionMiddleware.php create mode 100644 vendor/symfony/doctrine-bridge/Messenger/DoctrineTransactionMiddleware.php create mode 100644 vendor/symfony/doctrine-bridge/PropertyInfo/DoctrineExtractor.php create mode 100644 vendor/symfony/doctrine-bridge/README.md create mode 100644 vendor/symfony/doctrine-bridge/Security/RememberMe/DoctrineTokenProvider.php create mode 100644 vendor/symfony/doctrine-bridge/Security/User/EntityUserProvider.php create mode 100644 vendor/symfony/doctrine-bridge/Security/User/UserLoaderInterface.php create mode 100644 vendor/symfony/doctrine-bridge/Test/DoctrineTestHelper.php create mode 100644 vendor/symfony/doctrine-bridge/Test/TestRepositoryFactory.php create mode 100644 vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntity.php create mode 100644 vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntityValidator.php create mode 100644 vendor/symfony/doctrine-bridge/Validator/DoctrineInitializer.php create mode 100644 vendor/symfony/doctrine-bridge/Validator/DoctrineLoader.php create mode 100644 vendor/symfony/doctrine-bridge/composer.json create mode 100644 vendor/symfony/error-handler/.gitattributes create mode 100644 vendor/symfony/error-handler/BufferingLogger.php create mode 100644 vendor/symfony/error-handler/CHANGELOG.md create mode 100644 vendor/symfony/error-handler/Debug.php create mode 100644 vendor/symfony/error-handler/DebugClassLoader.php create mode 100644 vendor/symfony/error-handler/Error/ClassNotFoundError.php create mode 100644 vendor/symfony/error-handler/Error/FatalError.php create mode 100644 vendor/symfony/error-handler/Error/OutOfMemoryError.php create mode 100644 vendor/symfony/error-handler/Error/UndefinedFunctionError.php create mode 100644 vendor/symfony/error-handler/Error/UndefinedMethodError.php create mode 100644 vendor/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php create mode 100644 vendor/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php create mode 100644 vendor/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php create mode 100644 vendor/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php create mode 100644 vendor/symfony/error-handler/ErrorHandler.php create mode 100644 vendor/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php create mode 100644 vendor/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php create mode 100644 vendor/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php create mode 100644 vendor/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php create mode 100644 vendor/symfony/error-handler/Exception/FlattenException.php create mode 100644 vendor/symfony/error-handler/Exception/SilencedErrorContext.php create mode 100644 vendor/symfony/error-handler/LICENSE create mode 100644 vendor/symfony/error-handler/README.md create mode 100644 vendor/symfony/error-handler/Resources/assets/css/error.css create mode 100644 vendor/symfony/error-handler/Resources/assets/css/exception.css create mode 100644 vendor/symfony/error-handler/Resources/assets/css/exception_full.css create mode 100644 vendor/symfony/error-handler/Resources/assets/images/chevron-right.svg create mode 100644 vendor/symfony/error-handler/Resources/assets/images/favicon.png.base64 create mode 100644 vendor/symfony/error-handler/Resources/assets/images/icon-book.svg create mode 100644 vendor/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg create mode 100644 vendor/symfony/error-handler/Resources/assets/images/icon-minus-square.svg create mode 100644 vendor/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg create mode 100644 vendor/symfony/error-handler/Resources/assets/images/icon-plus-square.svg create mode 100644 vendor/symfony/error-handler/Resources/assets/images/icon-support.svg create mode 100644 vendor/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php create mode 100644 vendor/symfony/error-handler/Resources/assets/images/symfony-logo.svg create mode 100644 vendor/symfony/error-handler/Resources/assets/js/exception.js create mode 100644 vendor/symfony/error-handler/Resources/views/error.html.php create mode 100644 vendor/symfony/error-handler/Resources/views/exception.html.php create mode 100644 vendor/symfony/error-handler/Resources/views/exception_full.html.php create mode 100644 vendor/symfony/error-handler/Resources/views/logs.html.php create mode 100644 vendor/symfony/error-handler/Resources/views/trace.html.php create mode 100644 vendor/symfony/error-handler/Resources/views/traces.html.php create mode 100644 vendor/symfony/error-handler/Resources/views/traces_text.html.php create mode 100644 vendor/symfony/error-handler/ThrowableUtils.php create mode 100644 vendor/symfony/error-handler/composer.json create mode 100644 vendor/symfony/event-dispatcher-contracts/.gitignore create mode 100644 vendor/symfony/event-dispatcher-contracts/Event.php create mode 100644 vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php create mode 100644 vendor/symfony/event-dispatcher-contracts/LICENSE create mode 100644 vendor/symfony/event-dispatcher-contracts/README.md create mode 100644 vendor/symfony/event-dispatcher-contracts/composer.json create mode 100644 vendor/symfony/event-dispatcher/.gitattributes create mode 100644 vendor/symfony/event-dispatcher/CHANGELOG.md create mode 100644 vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php create mode 100644 vendor/symfony/event-dispatcher/Debug/WrappedListener.php create mode 100644 vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php create mode 100644 vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php create mode 100644 vendor/symfony/event-dispatcher/EventDispatcher.php create mode 100644 vendor/symfony/event-dispatcher/EventDispatcherInterface.php create mode 100644 vendor/symfony/event-dispatcher/EventSubscriberInterface.php create mode 100644 vendor/symfony/event-dispatcher/GenericEvent.php create mode 100644 vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php create mode 100644 vendor/symfony/event-dispatcher/LICENSE create mode 100644 vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php create mode 100644 vendor/symfony/event-dispatcher/README.md create mode 100644 vendor/symfony/event-dispatcher/composer.json create mode 100644 vendor/symfony/filesystem/.gitattributes create mode 100644 vendor/symfony/filesystem/CHANGELOG.md create mode 100644 vendor/symfony/filesystem/Exception/ExceptionInterface.php create mode 100644 vendor/symfony/filesystem/Exception/FileNotFoundException.php create mode 100644 vendor/symfony/filesystem/Exception/IOException.php create mode 100644 vendor/symfony/filesystem/Exception/IOExceptionInterface.php create mode 100644 vendor/symfony/filesystem/Exception/InvalidArgumentException.php create mode 100644 vendor/symfony/filesystem/Filesystem.php create mode 100644 vendor/symfony/filesystem/LICENSE create mode 100644 vendor/symfony/filesystem/README.md create mode 100644 vendor/symfony/filesystem/composer.json create mode 100644 vendor/symfony/finder/.gitattributes create mode 100644 vendor/symfony/finder/CHANGELOG.md create mode 100644 vendor/symfony/finder/Comparator/Comparator.php create mode 100644 vendor/symfony/finder/Comparator/DateComparator.php create mode 100644 vendor/symfony/finder/Comparator/NumberComparator.php create mode 100644 vendor/symfony/finder/Exception/AccessDeniedException.php create mode 100644 vendor/symfony/finder/Exception/DirectoryNotFoundException.php create mode 100644 vendor/symfony/finder/Finder.php create mode 100644 vendor/symfony/finder/Gitignore.php create mode 100644 vendor/symfony/finder/Glob.php create mode 100644 vendor/symfony/finder/Iterator/CustomFilterIterator.php create mode 100644 vendor/symfony/finder/Iterator/DateRangeFilterIterator.php create mode 100644 vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php create mode 100644 vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php create mode 100644 vendor/symfony/finder/Iterator/FileTypeFilterIterator.php create mode 100644 vendor/symfony/finder/Iterator/FilecontentFilterIterator.php create mode 100644 vendor/symfony/finder/Iterator/FilenameFilterIterator.php create mode 100644 vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php create mode 100644 vendor/symfony/finder/Iterator/PathFilterIterator.php create mode 100644 vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php create mode 100644 vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php create mode 100644 vendor/symfony/finder/Iterator/SortableIterator.php create mode 100644 vendor/symfony/finder/LICENSE create mode 100644 vendor/symfony/finder/README.md create mode 100644 vendor/symfony/finder/SplFileInfo.php create mode 100644 vendor/symfony/finder/composer.json create mode 100644 vendor/symfony/framework-bundle/.gitattributes create mode 100644 vendor/symfony/framework-bundle/CHANGELOG.md create mode 100644 vendor/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php create mode 100644 vendor/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php create mode 100644 vendor/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php create mode 100644 vendor/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php create mode 100644 vendor/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php create mode 100644 vendor/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php create mode 100644 vendor/symfony/framework-bundle/Command/AboutCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/AbstractConfigCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/AssetsInstallCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/CacheClearCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/CachePoolClearCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/CachePoolDeleteCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/CachePoolListCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/CachePoolPruneCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/CacheWarmupCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/ConfigDebugCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/ContainerDebugCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/ContainerLintCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/DebugAutowiringCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/RouterDebugCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/RouterMatchCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/SecretsListCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/SecretsRemoveCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/SecretsSetCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/TranslationDebugCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/TranslationUpdateCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/WorkflowDumpCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/XliffLintCommand.php create mode 100644 vendor/symfony/framework-bundle/Command/YamlLintCommand.php create mode 100644 vendor/symfony/framework-bundle/Console/Application.php create mode 100644 vendor/symfony/framework-bundle/Console/Descriptor/Descriptor.php create mode 100644 vendor/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php create mode 100644 vendor/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php create mode 100644 vendor/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php create mode 100644 vendor/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php create mode 100644 vendor/symfony/framework-bundle/Console/Helper/DescriptorHelper.php create mode 100644 vendor/symfony/framework-bundle/Controller/AbstractController.php create mode 100644 vendor/symfony/framework-bundle/Controller/ControllerResolver.php create mode 100644 vendor/symfony/framework-bundle/Controller/RedirectController.php create mode 100644 vendor/symfony/framework-bundle/Controller/TemplateController.php create mode 100644 vendor/symfony/framework-bundle/DataCollector/RouterDataCollector.php create mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php create mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php create mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php create mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php create mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php create mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php create mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php create mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php create mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php create mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php create mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php create mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Configuration.php create mode 100644 vendor/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php create mode 100644 vendor/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php create mode 100644 vendor/symfony/framework-bundle/FrameworkBundle.php create mode 100644 vendor/symfony/framework-bundle/HttpCache/HttpCache.php create mode 100644 vendor/symfony/framework-bundle/Kernel/MicroKernelTrait.php create mode 100644 vendor/symfony/framework-bundle/KernelBrowser.php create mode 100644 vendor/symfony/framework-bundle/LICENSE create mode 100644 vendor/symfony/framework-bundle/README.md create mode 100644 vendor/symfony/framework-bundle/Resources/config/annotations.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/assets.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/cache.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/cache_debug.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/collectors.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/console.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/debug.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/debug_prod.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/error_renderer.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/esi.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/form.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/form_csrf.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/form_debug.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/fragment_listener.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/fragment_renderer.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/http_client.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/http_client_debug.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/identity_translator.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/lock.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/mailer.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/mailer_debug.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/mailer_transports.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/messenger.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/messenger_debug.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/mime_type.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/notifier.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/notifier_transports.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/profiling.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/property_access.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/property_info.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/request.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/routing.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/routing/errors.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd create mode 100644 vendor/symfony/framework-bundle/Resources/config/secrets.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/security_csrf.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/serializer.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/services.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/session.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/ssi.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/test.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/translation.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/translation_debug.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/validator.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/validator_debug.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/web.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/web_link.xml create mode 100644 vendor/symfony/framework-bundle/Resources/config/workflow.xml create mode 100644 vendor/symfony/framework-bundle/Resources/views/Form/week_widget.html.php create mode 100644 vendor/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php create mode 100644 vendor/symfony/framework-bundle/Routing/DelegatingLoader.php create mode 100644 vendor/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php create mode 100644 vendor/symfony/framework-bundle/Routing/RouteLoaderInterface.php create mode 100644 vendor/symfony/framework-bundle/Routing/Router.php create mode 100644 vendor/symfony/framework-bundle/Secrets/AbstractVault.php create mode 100644 vendor/symfony/framework-bundle/Secrets/DotenvVault.php create mode 100644 vendor/symfony/framework-bundle/Secrets/SodiumVault.php create mode 100644 vendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php create mode 100644 vendor/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php create mode 100644 vendor/symfony/framework-bundle/Test/KernelTestCase.php create mode 100644 vendor/symfony/framework-bundle/Test/MailerAssertionsTrait.php create mode 100644 vendor/symfony/framework-bundle/Test/TestContainer.php create mode 100644 vendor/symfony/framework-bundle/Test/WebTestAssertionsTrait.php create mode 100644 vendor/symfony/framework-bundle/Test/WebTestCase.php create mode 100644 vendor/symfony/framework-bundle/Translation/Translator.php create mode 100644 vendor/symfony/framework-bundle/composer.json create mode 100644 vendor/symfony/http-foundation/.gitattributes create mode 100644 vendor/symfony/http-foundation/AcceptHeader.php create mode 100644 vendor/symfony/http-foundation/AcceptHeaderItem.php create mode 100644 vendor/symfony/http-foundation/BinaryFileResponse.php create mode 100644 vendor/symfony/http-foundation/CHANGELOG.md create mode 100644 vendor/symfony/http-foundation/Cookie.php create mode 100644 vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php create mode 100644 vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php create mode 100644 vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php create mode 100644 vendor/symfony/http-foundation/ExpressionRequestMatcher.php create mode 100644 vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php create mode 100644 vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php create mode 100644 vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php create mode 100644 vendor/symfony/http-foundation/File/Exception/FileException.php create mode 100644 vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php create mode 100644 vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php create mode 100644 vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php create mode 100644 vendor/symfony/http-foundation/File/Exception/NoFileException.php create mode 100644 vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php create mode 100644 vendor/symfony/http-foundation/File/Exception/PartialFileException.php create mode 100644 vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php create mode 100644 vendor/symfony/http-foundation/File/Exception/UploadException.php create mode 100644 vendor/symfony/http-foundation/File/File.php create mode 100644 vendor/symfony/http-foundation/File/Stream.php create mode 100644 vendor/symfony/http-foundation/File/UploadedFile.php create mode 100644 vendor/symfony/http-foundation/FileBag.php create mode 100644 vendor/symfony/http-foundation/HeaderBag.php create mode 100644 vendor/symfony/http-foundation/HeaderUtils.php create mode 100644 vendor/symfony/http-foundation/IpUtils.php create mode 100644 vendor/symfony/http-foundation/JsonResponse.php create mode 100644 vendor/symfony/http-foundation/LICENSE create mode 100644 vendor/symfony/http-foundation/ParameterBag.php create mode 100644 vendor/symfony/http-foundation/README.md create mode 100644 vendor/symfony/http-foundation/RedirectResponse.php create mode 100644 vendor/symfony/http-foundation/Request.php create mode 100644 vendor/symfony/http-foundation/RequestMatcher.php create mode 100644 vendor/symfony/http-foundation/RequestMatcherInterface.php create mode 100644 vendor/symfony/http-foundation/RequestStack.php create mode 100644 vendor/symfony/http-foundation/Response.php create mode 100644 vendor/symfony/http-foundation/ResponseHeaderBag.php create mode 100644 vendor/symfony/http-foundation/ServerBag.php create mode 100644 vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php create mode 100644 vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php create mode 100644 vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php create mode 100644 vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php create mode 100644 vendor/symfony/http-foundation/Session/Flash/FlashBag.php create mode 100644 vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php create mode 100644 vendor/symfony/http-foundation/Session/Session.php create mode 100644 vendor/symfony/http-foundation/Session/SessionBagInterface.php create mode 100644 vendor/symfony/http-foundation/Session/SessionBagProxy.php create mode 100644 vendor/symfony/http-foundation/Session/SessionInterface.php create mode 100644 vendor/symfony/http-foundation/Session/SessionUtils.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/MetadataBag.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php create mode 100644 vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php create mode 100644 vendor/symfony/http-foundation/StreamedResponse.php create mode 100644 vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php create mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php create mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php create mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php create mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php create mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php create mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php create mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php create mode 100644 vendor/symfony/http-foundation/UrlHelper.php create mode 100644 vendor/symfony/http-foundation/composer.json create mode 100644 vendor/symfony/http-kernel/.gitattributes create mode 100644 vendor/symfony/http-kernel/Bundle/Bundle.php create mode 100644 vendor/symfony/http-kernel/Bundle/BundleInterface.php create mode 100644 vendor/symfony/http-kernel/CHANGELOG.md create mode 100644 vendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.php create mode 100644 vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php create mode 100644 vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php create mode 100644 vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php create mode 100644 vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php create mode 100644 vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php create mode 100644 vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.php create mode 100644 vendor/symfony/http-kernel/Config/FileLocator.php create mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver.php create mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php create mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php create mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php create mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php create mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php create mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php create mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php create mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php create mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php create mode 100644 vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php create mode 100644 vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php create mode 100644 vendor/symfony/http-kernel/Controller/ControllerReference.php create mode 100644 vendor/symfony/http-kernel/Controller/ControllerResolver.php create mode 100644 vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php create mode 100644 vendor/symfony/http-kernel/Controller/ErrorController.php create mode 100644 vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php create mode 100644 vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php create mode 100644 vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php create mode 100644 vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php create mode 100644 vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php create mode 100644 vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.php create mode 100644 vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php create mode 100644 vendor/symfony/http-kernel/DataCollector/DataCollector.php create mode 100644 vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php create mode 100644 vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php create mode 100644 vendor/symfony/http-kernel/DataCollector/EventDataCollector.php create mode 100644 vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php create mode 100644 vendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php create mode 100644 vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php create mode 100644 vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php create mode 100644 vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php create mode 100644 vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php create mode 100644 vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php create mode 100644 vendor/symfony/http-kernel/Debug/FileLinkFormatter.php create mode 100644 vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php create mode 100644 vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php create mode 100644 vendor/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php create mode 100644 vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php create mode 100644 vendor/symfony/http-kernel/DependencyInjection/Extension.php create mode 100644 vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php create mode 100644 vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php create mode 100644 vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php create mode 100644 vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php create mode 100644 vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php create mode 100644 vendor/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php create mode 100644 vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php create mode 100644 vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php create mode 100644 vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php create mode 100644 vendor/symfony/http-kernel/Event/ControllerArgumentsEvent.php create mode 100644 vendor/symfony/http-kernel/Event/ControllerEvent.php create mode 100644 vendor/symfony/http-kernel/Event/ExceptionEvent.php create mode 100644 vendor/symfony/http-kernel/Event/FinishRequestEvent.php create mode 100644 vendor/symfony/http-kernel/Event/KernelEvent.php create mode 100644 vendor/symfony/http-kernel/Event/RequestEvent.php create mode 100644 vendor/symfony/http-kernel/Event/ResponseEvent.php create mode 100644 vendor/symfony/http-kernel/Event/TerminateEvent.php create mode 100644 vendor/symfony/http-kernel/Event/ViewEvent.php create mode 100644 vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/DumpListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/ErrorListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/FragmentListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/LocaleAwareListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/LocaleListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/ProfilerListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/ResponseListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/RouterListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/SessionListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/SurrogateListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/TestSessionListener.php create mode 100644 vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php create mode 100644 vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/BadRequestHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/ConflictHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php create mode 100644 vendor/symfony/http-kernel/Exception/GoneHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/HttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/HttpExceptionInterface.php create mode 100644 vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/NotFoundHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php create mode 100644 vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php create mode 100644 vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php create mode 100644 vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.php create mode 100644 vendor/symfony/http-kernel/Fragment/FragmentHandler.php create mode 100644 vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php create mode 100644 vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php create mode 100644 vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php create mode 100644 vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php create mode 100644 vendor/symfony/http-kernel/Fragment/SsiFragmentRenderer.php create mode 100644 vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php create mode 100644 vendor/symfony/http-kernel/HttpCache/Esi.php create mode 100644 vendor/symfony/http-kernel/HttpCache/HttpCache.php create mode 100644 vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php create mode 100644 vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php create mode 100644 vendor/symfony/http-kernel/HttpCache/Ssi.php create mode 100644 vendor/symfony/http-kernel/HttpCache/Store.php create mode 100644 vendor/symfony/http-kernel/HttpCache/StoreInterface.php create mode 100644 vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php create mode 100644 vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php create mode 100644 vendor/symfony/http-kernel/HttpClientKernel.php create mode 100644 vendor/symfony/http-kernel/HttpKernel.php create mode 100644 vendor/symfony/http-kernel/HttpKernelBrowser.php create mode 100644 vendor/symfony/http-kernel/HttpKernelInterface.php create mode 100644 vendor/symfony/http-kernel/Kernel.php create mode 100644 vendor/symfony/http-kernel/KernelEvents.php create mode 100644 vendor/symfony/http-kernel/KernelInterface.php create mode 100644 vendor/symfony/http-kernel/LICENSE create mode 100644 vendor/symfony/http-kernel/Log/DebugLoggerInterface.php create mode 100644 vendor/symfony/http-kernel/Log/Logger.php create mode 100644 vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php create mode 100644 vendor/symfony/http-kernel/Profiler/Profile.php create mode 100644 vendor/symfony/http-kernel/Profiler/Profiler.php create mode 100644 vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php create mode 100644 vendor/symfony/http-kernel/README.md create mode 100644 vendor/symfony/http-kernel/RebootableInterface.php create mode 100644 vendor/symfony/http-kernel/Resources/welcome.html.php create mode 100644 vendor/symfony/http-kernel/TerminableInterface.php create mode 100644 vendor/symfony/http-kernel/UriSigner.php create mode 100644 vendor/symfony/http-kernel/composer.json create mode 100644 vendor/symfony/mime/.gitattributes create mode 100644 vendor/symfony/mime/Address.php create mode 100644 vendor/symfony/mime/BodyRendererInterface.php create mode 100644 vendor/symfony/mime/CHANGELOG.md create mode 100644 vendor/symfony/mime/CharacterStream.php create mode 100644 vendor/symfony/mime/Crypto/SMime.php create mode 100644 vendor/symfony/mime/Crypto/SMimeEncrypter.php create mode 100644 vendor/symfony/mime/Crypto/SMimeSigner.php create mode 100644 vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php create mode 100644 vendor/symfony/mime/Email.php create mode 100644 vendor/symfony/mime/Encoder/AddressEncoderInterface.php create mode 100644 vendor/symfony/mime/Encoder/Base64ContentEncoder.php create mode 100644 vendor/symfony/mime/Encoder/Base64Encoder.php create mode 100644 vendor/symfony/mime/Encoder/Base64MimeHeaderEncoder.php create mode 100644 vendor/symfony/mime/Encoder/ContentEncoderInterface.php create mode 100644 vendor/symfony/mime/Encoder/EightBitContentEncoder.php create mode 100644 vendor/symfony/mime/Encoder/EncoderInterface.php create mode 100644 vendor/symfony/mime/Encoder/IdnAddressEncoder.php create mode 100644 vendor/symfony/mime/Encoder/MimeHeaderEncoderInterface.php create mode 100644 vendor/symfony/mime/Encoder/QpContentEncoder.php create mode 100644 vendor/symfony/mime/Encoder/QpEncoder.php create mode 100644 vendor/symfony/mime/Encoder/QpMimeHeaderEncoder.php create mode 100644 vendor/symfony/mime/Encoder/Rfc2231Encoder.php create mode 100644 vendor/symfony/mime/Exception/AddressEncoderException.php create mode 100644 vendor/symfony/mime/Exception/ExceptionInterface.php create mode 100644 vendor/symfony/mime/Exception/InvalidArgumentException.php create mode 100644 vendor/symfony/mime/Exception/LogicException.php create mode 100644 vendor/symfony/mime/Exception/RfcComplianceException.php create mode 100644 vendor/symfony/mime/Exception/RuntimeException.php create mode 100644 vendor/symfony/mime/FileBinaryMimeTypeGuesser.php create mode 100644 vendor/symfony/mime/FileinfoMimeTypeGuesser.php create mode 100644 vendor/symfony/mime/Header/AbstractHeader.php create mode 100644 vendor/symfony/mime/Header/DateHeader.php create mode 100644 vendor/symfony/mime/Header/HeaderInterface.php create mode 100644 vendor/symfony/mime/Header/Headers.php create mode 100644 vendor/symfony/mime/Header/IdentificationHeader.php create mode 100644 vendor/symfony/mime/Header/MailboxHeader.php create mode 100644 vendor/symfony/mime/Header/MailboxListHeader.php create mode 100644 vendor/symfony/mime/Header/ParameterizedHeader.php create mode 100644 vendor/symfony/mime/Header/PathHeader.php create mode 100644 vendor/symfony/mime/Header/UnstructuredHeader.php create mode 100644 vendor/symfony/mime/LICENSE create mode 100644 vendor/symfony/mime/Message.php create mode 100644 vendor/symfony/mime/MessageConverter.php create mode 100644 vendor/symfony/mime/MimeTypeGuesserInterface.php create mode 100644 vendor/symfony/mime/MimeTypes.php create mode 100644 vendor/symfony/mime/MimeTypesInterface.php create mode 100644 vendor/symfony/mime/Part/AbstractMultipartPart.php create mode 100644 vendor/symfony/mime/Part/AbstractPart.php create mode 100644 vendor/symfony/mime/Part/DataPart.php create mode 100644 vendor/symfony/mime/Part/MessagePart.php create mode 100644 vendor/symfony/mime/Part/Multipart/AlternativePart.php create mode 100644 vendor/symfony/mime/Part/Multipart/DigestPart.php create mode 100644 vendor/symfony/mime/Part/Multipart/FormDataPart.php create mode 100644 vendor/symfony/mime/Part/Multipart/MixedPart.php create mode 100644 vendor/symfony/mime/Part/Multipart/RelatedPart.php create mode 100644 vendor/symfony/mime/Part/SMimePart.php create mode 100644 vendor/symfony/mime/Part/TextPart.php create mode 100644 vendor/symfony/mime/README.md create mode 100644 vendor/symfony/mime/RawMessage.php create mode 100644 vendor/symfony/mime/Resources/bin/update_mime_types.php create mode 100644 vendor/symfony/mime/Test/Constraint/EmailAddressContains.php create mode 100644 vendor/symfony/mime/Test/Constraint/EmailAttachmentCount.php create mode 100644 vendor/symfony/mime/Test/Constraint/EmailHasHeader.php create mode 100644 vendor/symfony/mime/Test/Constraint/EmailHeaderSame.php create mode 100644 vendor/symfony/mime/Test/Constraint/EmailHtmlBodyContains.php create mode 100644 vendor/symfony/mime/Test/Constraint/EmailTextBodyContains.php create mode 100644 vendor/symfony/mime/composer.json create mode 100644 vendor/symfony/polyfill-ctype/Ctype.php create mode 100644 vendor/symfony/polyfill-ctype/LICENSE create mode 100644 vendor/symfony/polyfill-ctype/README.md create mode 100644 vendor/symfony/polyfill-ctype/bootstrap.php create mode 100644 vendor/symfony/polyfill-ctype/composer.json create mode 100644 vendor/symfony/polyfill-intl-idn/Idn.php create mode 100644 vendor/symfony/polyfill-intl-idn/LICENSE create mode 100644 vendor/symfony/polyfill-intl-idn/README.md create mode 100644 vendor/symfony/polyfill-intl-idn/bootstrap.php create mode 100644 vendor/symfony/polyfill-intl-idn/composer.json create mode 100644 vendor/symfony/polyfill-mbstring/LICENSE create mode 100644 vendor/symfony/polyfill-mbstring/Mbstring.php create mode 100644 vendor/symfony/polyfill-mbstring/README.md create mode 100644 vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php create mode 100644 vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php create mode 100644 vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php create mode 100644 vendor/symfony/polyfill-mbstring/bootstrap.php create mode 100644 vendor/symfony/polyfill-mbstring/composer.json create mode 100644 vendor/symfony/polyfill-php72/LICENSE create mode 100644 vendor/symfony/polyfill-php72/Php72.php create mode 100644 vendor/symfony/polyfill-php72/README.md create mode 100644 vendor/symfony/polyfill-php72/bootstrap.php create mode 100644 vendor/symfony/polyfill-php72/composer.json create mode 100644 vendor/symfony/polyfill-php73/LICENSE create mode 100644 vendor/symfony/polyfill-php73/Php73.php create mode 100644 vendor/symfony/polyfill-php73/README.md create mode 100644 vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php create mode 100644 vendor/symfony/polyfill-php73/bootstrap.php create mode 100644 vendor/symfony/polyfill-php73/composer.json create mode 100644 vendor/symfony/routing/.gitattributes create mode 100644 vendor/symfony/routing/Annotation/Route.php create mode 100644 vendor/symfony/routing/CHANGELOG.md create mode 100644 vendor/symfony/routing/CompiledRoute.php create mode 100644 vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php create mode 100644 vendor/symfony/routing/Exception/ExceptionInterface.php create mode 100644 vendor/symfony/routing/Exception/InvalidParameterException.php create mode 100644 vendor/symfony/routing/Exception/MethodNotAllowedException.php create mode 100644 vendor/symfony/routing/Exception/MissingMandatoryParametersException.php create mode 100644 vendor/symfony/routing/Exception/NoConfigurationException.php create mode 100644 vendor/symfony/routing/Exception/ResourceNotFoundException.php create mode 100644 vendor/symfony/routing/Exception/RouteNotFoundException.php create mode 100644 vendor/symfony/routing/Generator/CompiledUrlGenerator.php create mode 100644 vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php create mode 100644 vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php create mode 100644 vendor/symfony/routing/Generator/Dumper/GeneratorDumper.php create mode 100644 vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php create mode 100644 vendor/symfony/routing/Generator/UrlGenerator.php create mode 100644 vendor/symfony/routing/Generator/UrlGeneratorInterface.php create mode 100644 vendor/symfony/routing/LICENSE create mode 100644 vendor/symfony/routing/Loader/AnnotationClassLoader.php create mode 100644 vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php create mode 100644 vendor/symfony/routing/Loader/AnnotationFileLoader.php create mode 100644 vendor/symfony/routing/Loader/ClosureLoader.php create mode 100644 vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php create mode 100644 vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php create mode 100644 vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php create mode 100644 vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php create mode 100644 vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php create mode 100644 vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php create mode 100644 vendor/symfony/routing/Loader/ContainerLoader.php create mode 100644 vendor/symfony/routing/Loader/DirectoryLoader.php create mode 100644 vendor/symfony/routing/Loader/GlobFileLoader.php create mode 100644 vendor/symfony/routing/Loader/ObjectLoader.php create mode 100644 vendor/symfony/routing/Loader/PhpFileLoader.php create mode 100644 vendor/symfony/routing/Loader/XmlFileLoader.php create mode 100644 vendor/symfony/routing/Loader/YamlFileLoader.php create mode 100644 vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd create mode 100644 vendor/symfony/routing/Matcher/CompiledUrlMatcher.php create mode 100644 vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php create mode 100644 vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php create mode 100644 vendor/symfony/routing/Matcher/Dumper/MatcherDumper.php create mode 100644 vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php create mode 100644 vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php create mode 100644 vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php create mode 100644 vendor/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php create mode 100644 vendor/symfony/routing/Matcher/RequestMatcherInterface.php create mode 100644 vendor/symfony/routing/Matcher/TraceableUrlMatcher.php create mode 100644 vendor/symfony/routing/Matcher/UrlMatcher.php create mode 100644 vendor/symfony/routing/Matcher/UrlMatcherInterface.php create mode 100644 vendor/symfony/routing/README.md create mode 100644 vendor/symfony/routing/RequestContext.php create mode 100644 vendor/symfony/routing/RequestContextAwareInterface.php create mode 100644 vendor/symfony/routing/Route.php create mode 100644 vendor/symfony/routing/RouteCollection.php create mode 100644 vendor/symfony/routing/RouteCollectionBuilder.php create mode 100644 vendor/symfony/routing/RouteCompiler.php create mode 100644 vendor/symfony/routing/RouteCompilerInterface.php create mode 100644 vendor/symfony/routing/Router.php create mode 100644 vendor/symfony/routing/RouterInterface.php create mode 100644 vendor/symfony/routing/composer.json create mode 100644 vendor/symfony/service-contracts/.gitignore create mode 100644 vendor/symfony/service-contracts/LICENSE create mode 100644 vendor/symfony/service-contracts/README.md create mode 100644 vendor/symfony/service-contracts/ResetInterface.php create mode 100644 vendor/symfony/service-contracts/ServiceLocatorTrait.php create mode 100644 vendor/symfony/service-contracts/ServiceProviderInterface.php create mode 100644 vendor/symfony/service-contracts/ServiceSubscriberInterface.php create mode 100644 vendor/symfony/service-contracts/ServiceSubscriberTrait.php create mode 100644 vendor/symfony/service-contracts/Test/ServiceLocatorTest.php create mode 100644 vendor/symfony/service-contracts/composer.json create mode 100644 vendor/symfony/var-dumper/.gitattributes create mode 100644 vendor/symfony/var-dumper/CHANGELOG.md create mode 100644 vendor/symfony/var-dumper/Caster/AmqpCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/ArgsStub.php create mode 100644 vendor/symfony/var-dumper/Caster/Caster.php create mode 100644 vendor/symfony/var-dumper/Caster/ClassStub.php create mode 100644 vendor/symfony/var-dumper/Caster/ConstStub.php create mode 100644 vendor/symfony/var-dumper/Caster/CutArrayStub.php create mode 100644 vendor/symfony/var-dumper/Caster/CutStub.php create mode 100644 vendor/symfony/var-dumper/Caster/DOMCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/DateCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/DoctrineCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/DsCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/DsPairStub.php create mode 100644 vendor/symfony/var-dumper/Caster/EnumStub.php create mode 100644 vendor/symfony/var-dumper/Caster/ExceptionCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/FrameStub.php create mode 100644 vendor/symfony/var-dumper/Caster/GmpCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/ImagineCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/ImgStub.php create mode 100644 vendor/symfony/var-dumper/Caster/IntlCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/LinkStub.php create mode 100644 vendor/symfony/var-dumper/Caster/MemcachedCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/PdoCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/PgSqlCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/RedisCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/ReflectionCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/ResourceCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/SplCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/StubCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/SymfonyCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/TraceStub.php create mode 100644 vendor/symfony/var-dumper/Caster/UuidCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/XmlReaderCaster.php create mode 100644 vendor/symfony/var-dumper/Caster/XmlResourceCaster.php create mode 100644 vendor/symfony/var-dumper/Cloner/AbstractCloner.php create mode 100644 vendor/symfony/var-dumper/Cloner/ClonerInterface.php create mode 100644 vendor/symfony/var-dumper/Cloner/Cursor.php create mode 100644 vendor/symfony/var-dumper/Cloner/Data.php create mode 100644 vendor/symfony/var-dumper/Cloner/DumperInterface.php create mode 100644 vendor/symfony/var-dumper/Cloner/Stub.php create mode 100644 vendor/symfony/var-dumper/Cloner/VarCloner.php create mode 100644 vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php create mode 100644 vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php create mode 100644 vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php create mode 100644 vendor/symfony/var-dumper/Command/ServerDumpCommand.php create mode 100644 vendor/symfony/var-dumper/Dumper/AbstractDumper.php create mode 100644 vendor/symfony/var-dumper/Dumper/CliDumper.php create mode 100644 vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php create mode 100644 vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php create mode 100644 vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php create mode 100644 vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php create mode 100644 vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php create mode 100644 vendor/symfony/var-dumper/Dumper/DataDumperInterface.php create mode 100644 vendor/symfony/var-dumper/Dumper/HtmlDumper.php create mode 100644 vendor/symfony/var-dumper/Dumper/ServerDumper.php create mode 100644 vendor/symfony/var-dumper/Exception/ThrowingCasterException.php create mode 100644 vendor/symfony/var-dumper/LICENSE create mode 100644 vendor/symfony/var-dumper/README.md create mode 100755 vendor/symfony/var-dumper/Resources/bin/var-dump-server create mode 100644 vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css create mode 100644 vendor/symfony/var-dumper/Resources/functions/dump.php create mode 100644 vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js create mode 100644 vendor/symfony/var-dumper/Server/Connection.php create mode 100644 vendor/symfony/var-dumper/Server/DumpServer.php create mode 100644 vendor/symfony/var-dumper/Test/VarDumperTestTrait.php create mode 100644 vendor/symfony/var-dumper/VarDumper.php create mode 100644 vendor/symfony/var-dumper/composer.json create mode 100644 vendor/symfony/var-exporter/.gitattributes create mode 100644 vendor/symfony/var-exporter/CHANGELOG.md create mode 100644 vendor/symfony/var-exporter/Exception/ClassNotFoundException.php create mode 100644 vendor/symfony/var-exporter/Exception/ExceptionInterface.php create mode 100644 vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php create mode 100644 vendor/symfony/var-exporter/Instantiator.php create mode 100644 vendor/symfony/var-exporter/Internal/Exporter.php create mode 100644 vendor/symfony/var-exporter/Internal/Hydrator.php create mode 100644 vendor/symfony/var-exporter/Internal/Reference.php create mode 100644 vendor/symfony/var-exporter/Internal/Registry.php create mode 100644 vendor/symfony/var-exporter/Internal/Values.php create mode 100644 vendor/symfony/var-exporter/LICENSE create mode 100644 vendor/symfony/var-exporter/README.md create mode 100644 vendor/symfony/var-exporter/VarExporter.php create mode 100644 vendor/symfony/var-exporter/composer.json diff --git a/.gitignore b/.gitignore index bed37a8..e9c9d3d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ valeursfoncieres-* -.vscode/ \ No newline at end of file +.vscode/ diff --git a/api/composer.json b/api/composer.json index 14450fc..68b8230 100644 --- a/api/composer.json +++ b/api/composer.json @@ -16,6 +16,7 @@ }, "require-dev": { "api-platform/schema-generator": "^2.1", + "doctrine/doctrine-fixtures-bundle": "^3.3", "symfony/maker-bundle": "^1.11", "symfony/profiler-pack": "^1.0" }, diff --git a/api/composer.lock b/api/composer.lock index 95f7e2d..970ed9d 100644 --- a/api/composer.lock +++ b/api/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d92d21009b99fe46500a17d5373db77a", + "content-hash": "eef8f519a5922cc8e8751172a04b0948", "packages": [ { "name": "api-platform/api-pack", @@ -5508,6 +5508,7 @@ "code", "zf" ], + "abandoned": "laminas/laminas-code", "time": "2019-10-05T23:18:22+00:00" }, { @@ -5562,6 +5563,7 @@ "events", "zf2" ], + "abandoned": "laminas/laminas-eventmanager", "time": "2018-04-25T15:33:34+00:00" } ], @@ -5740,6 +5742,136 @@ ], "time": "2019-11-06T16:40:04+00:00" }, + { + "name": "doctrine/data-fixtures", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/data-fixtures.git", + "reference": "608a35a3b5bcc4214d116603095f8b0c51091592" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/608a35a3b5bcc4214d116603095f8b0c51091592", + "reference": "608a35a3b5bcc4214d116603095f8b0c51091592", + "shasum": "" + }, + "require": { + "doctrine/common": "^2.11", + "php": "^7.2" + }, + "conflict": { + "doctrine/phpcr-odm": "<1.3.0" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^6.0", + "doctrine/dbal": "^2.5.4", + "doctrine/mongodb-odm": "^1.3.0", + "doctrine/orm": "^2.5.4", + "phpunit/phpunit": "^7.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "For using MongoDB ODM with PHP 7", + "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", + "doctrine/orm": "For loading ORM fixtures", + "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\DataFixtures\\": "lib/Doctrine/Common/DataFixtures" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Data Fixtures for all Doctrine Object Managers", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database" + ], + "time": "2019-10-30T20:03:18+00:00" + }, + { + "name": "doctrine/doctrine-fixtures-bundle", + "version": "3.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineFixturesBundle.git", + "reference": "8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70", + "reference": "8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70", + "shasum": "" + }, + "require": { + "doctrine/data-fixtures": "^1.3", + "doctrine/doctrine-bundle": "^1.11|^2.0", + "doctrine/orm": "^2.6.0", + "php": "^7.1", + "symfony/config": "^3.4|^4.3|^5.0", + "symfony/console": "^3.4|^4.3|^5.0", + "symfony/dependency-injection": "^3.4|^4.3|^5.0", + "symfony/doctrine-bridge": "^3.4|^4.1|^5.0", + "symfony/http-kernel": "^3.4|^4.3|^5.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.4", + "symfony/phpunit-bridge": "^4.1|^5.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "3.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\FixturesBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Doctrine Project", + "homepage": "http://www.doctrine-project.org" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony DoctrineFixturesBundle", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "Fixture", + "persistence" + ], + "time": "2019-11-13T15:46:58+00:00" + }, { "name": "easyrdf/easyrdf", "version": "0.9.1", diff --git a/api/config/bundles.php b/api/config/bundles.php index 0d1cb31..0815847 100644 --- a/api/config/bundles.php +++ b/api/config/bundles.php @@ -11,4 +11,5 @@ return [ Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], + Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], ]; diff --git a/api/src/DataFixtures/AppFixtures.php b/api/src/DataFixtures/AppFixtures.php new file mode 100644 index 0000000..788f73b --- /dev/null +++ b/api/src/DataFixtures/AppFixtures.php @@ -0,0 +1,30 @@ +id = $i; + $product->price = 15; + $product->surface = 15; + $product->date = new DateTime('2012/12/12');; + $product->department = 'DPT'; + $product->region = 'RGN'; + $manager->persist($product); + } + + $manager->flush(); + } +} diff --git a/api/symfony.lock b/api/symfony.lock index bea0a66..55a3eb5 100644 --- a/api/symfony.lock +++ b/api/symfony.lock @@ -46,6 +46,9 @@ "doctrine/common": { "version": "v2.11.0" }, + "doctrine/data-fixtures": { + "version": "1.4.0" + }, "doctrine/dbal": { "version": "v2.10.0" }, @@ -67,6 +70,18 @@ "doctrine/doctrine-cache-bundle": { "version": "1.3.5" }, + "doctrine/doctrine-fixtures-bundle": { + "version": "3.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "3.0", + "ref": "fc52d86631a6dfd9fdf3381d0b7e3df2069e51b3" + }, + "files": [ + "src/DataFixtures/AppFixtures.php" + ] + }, "doctrine/doctrine-migrations-bundle": { "version": "1.2", "recipe": { diff --git a/bookshop-api/.env b/bookshop-api/.env new file mode 100644 index 0000000..ea4df0a --- /dev/null +++ b/bookshop-api/.env @@ -0,0 +1,33 @@ +# In all environments, the following files are loaded if they exist, +# the latter taking precedence over the former: +# +# * .env contains default values for the environment variables needed by the app +# * .env.local uncommitted file with local overrides +# * .env.$APP_ENV committed environment-specific defaults +# * .env.$APP_ENV.local uncommitted environment-specific overrides +# +# Real environment variables win over .env files. +# +# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES. +# +# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). +# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration + +###> symfony/framework-bundle ### +APP_ENV=dev +APP_SECRET=5f66ea36e6db4d91aadbf917d0ee6cc8 +#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 +#TRUSTED_HOSTS='^localhost|example\.com$' +###< symfony/framework-bundle ### + +###> nelmio/cors-bundle ### +CORS_ALLOW_ORIGIN=^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$ +###< nelmio/cors-bundle ### + +###> doctrine/doctrine-bundle ### +# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url +# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db" +# For a PostgreSQL database, use: "postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=11&charset=utf8" +# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml +DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7 +###< doctrine/doctrine-bundle ### diff --git a/bookshop-api/.gitignore b/bookshop-api/.gitignore new file mode 100644 index 0000000..a67f91e --- /dev/null +++ b/bookshop-api/.gitignore @@ -0,0 +1,10 @@ + +###> symfony/framework-bundle ### +/.env.local +/.env.local.php +/.env.*.local +/config/secrets/prod/prod.decrypt.private.php +/public/bundles/ +/var/ +/vendor/ +###< symfony/framework-bundle ### diff --git a/bookshop-api/bin/console b/bookshop-api/bin/console new file mode 100755 index 0000000..5d5c80f --- /dev/null +++ b/bookshop-api/bin/console @@ -0,0 +1,42 @@ +#!/usr/bin/env php +getParameterOption(['--env', '-e'], null, true)) { + putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env); +} + +if ($input->hasParameterOption('--no-debug', true)) { + putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0'); +} + +require dirname(__DIR__).'/config/bootstrap.php'; + +if ($_SERVER['APP_DEBUG']) { + umask(0000); + + if (class_exists(Debug::class)) { + Debug::enable(); + } +} + +$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); +$application = new Application($kernel); +$application->run($input); diff --git a/bookshop-api/composer.json b/bookshop-api/composer.json new file mode 100644 index 0000000..ede5d0a --- /dev/null +++ b/bookshop-api/composer.json @@ -0,0 +1,63 @@ +{ + "type": "project", + "license": "proprietary", + "require": { + "php": "^7.2.5", + "ext-ctype": "*", + "ext-iconv": "*", + "api-platform/api-pack": "^1.2", + "symfony/console": "5.0.*", + "symfony/dotenv": "5.0.*", + "symfony/flex": "^1.3.1", + "symfony/framework-bundle": "5.0.*", + "symfony/yaml": "5.0.*" + }, + "require-dev": { + }, + "config": { + "preferred-install": { + "*": "dist" + }, + "sort-packages": true + }, + "autoload": { + "psr-4": { + "App\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "App\\Tests\\": "tests/" + } + }, + "replace": { + "paragonie/random_compat": "2.*", + "symfony/polyfill-ctype": "*", + "symfony/polyfill-iconv": "*", + "symfony/polyfill-php72": "*", + "symfony/polyfill-php71": "*", + "symfony/polyfill-php70": "*", + "symfony/polyfill-php56": "*" + }, + "scripts": { + "auto-scripts": { + "cache:clear": "symfony-cmd", + "assets:install %PUBLIC_DIR%": "symfony-cmd" + }, + "post-install-cmd": [ + "@auto-scripts" + ], + "post-update-cmd": [ + "@auto-scripts" + ] + }, + "conflict": { + "symfony/symfony": "*" + }, + "extra": { + "symfony": { + "allow-contrib": false, + "require": "5.0.*" + } + } +} diff --git a/bookshop-api/composer.lock b/bookshop-api/composer.lock new file mode 100644 index 0000000..787d411 --- /dev/null +++ b/bookshop-api/composer.lock @@ -0,0 +1,4716 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "cc915925b7c02df56ec27ffe49ab9fbf", + "packages": [ + { + "name": "api-platform/api-pack", + "version": "v1.2.1", + "source": { + "type": "git", + "url": "https://github.com/api-platform/api-pack.git", + "reference": "41364f8763475d7709c43f790aa77a4157d038e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/api-platform/api-pack/zipball/41364f8763475d7709c43f790aa77a4157d038e2", + "reference": "41364f8763475d7709c43f790aa77a4157d038e2", + "shasum": "" + }, + "require": { + "api-platform/core": "^2.1", + "doctrine/annotations": "^1.0", + "doctrine/doctrine-bundle": "^1.6 || ^2.0", + "doctrine/orm": "^2.4.5", + "nelmio/cors-bundle": "^1.5 || ^2.0", + "php": "^7.0", + "phpdocumentor/reflection-docblock": "^3.0 || ^4.0", + "symfony/asset": "*", + "symfony/expression-language": "*", + "symfony/security-bundle": "*", + "symfony/twig-bundle": "*", + "symfony/validator": "*" + }, + "type": "symfony-pack", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A pack for API Platform", + "time": "2019-11-12T17:43:33+00:00" + }, + { + "name": "api-platform/core", + "version": "v2.5.3", + "source": { + "type": "git", + "url": "https://github.com/api-platform/core.git", + "reference": "2d402688c485457adbc771e347e6498e70c6f232" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/api-platform/core/zipball/2d402688c485457adbc771e347e6498e70c6f232", + "reference": "2d402688c485457adbc771e347e6498e70c6f232", + "shasum": "" + }, + "require": { + "doctrine/inflector": "^1.0", + "fig/link-util": "^1.0", + "php": ">=7.1", + "psr/cache": "^1.0", + "psr/container": "^1.0", + "symfony/http-foundation": "^4.3.6 || ^5.0", + "symfony/http-kernel": "^4.3.7 || ^5.0", + "symfony/property-access": "^3.4 || ^4.0 || ^5.0", + "symfony/property-info": "^3.4 || ^4.0 || ^5.0", + "symfony/serializer": "^4.3 || ^5.0", + "symfony/web-link": "^4.1 || ^5.0", + "willdurand/negotiation": "^2.0.3" + }, + "conflict": { + "doctrine/common": "<2.7", + "doctrine/mongodb-odm": "<2.0" + }, + "require-dev": { + "behat/behat": "^3.1", + "behat/mink": "^1.7", + "behat/mink-browserkit-driver": "^1.3.1", + "behat/mink-extension": "^2.2", + "behat/symfony2-extension": "^2.1.1", + "behatch/contexts": "^3.1.0", + "doctrine/annotations": "^1.7", + "doctrine/common": "^2.11", + "doctrine/data-fixtures": "^1.2.2", + "doctrine/doctrine-bundle": "^1.8 || ^2.0", + "doctrine/doctrine-cache-bundle": "^1.3.5", + "doctrine/mongodb-odm": "^2.0", + "doctrine/mongodb-odm-bundle": "^4.0", + "doctrine/orm": "^2.6.4", + "elasticsearch/elasticsearch": "^6.0", + "friendsofsymfony/user-bundle": "^2.2@dev", + "guzzlehttp/guzzle": "^6.0", + "jangregor/phpstan-prophecy": "^0.4.2", + "justinrainbow/json-schema": "^5.2.1", + "nelmio/api-doc-bundle": "^2.13.4", + "phpdocumentor/reflection-docblock": "^3.0 || ^4.0", + "phpdocumentor/type-resolver": "^0.3 || ^0.4", + "phpspec/prophecy": "^1.8", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.11.10", + "phpstan/phpstan-doctrine": "^0.11.5", + "phpstan/phpstan-phpunit": "^0.11.2", + "phpstan/phpstan-symfony": "^0.11.6", + "phpunit/phpunit": "^7.5.2 || ^8.0", + "psr/log": "^1.0", + "ramsey/uuid": "^3.7", + "ramsey/uuid-doctrine": "^1.4", + "sebastian/object-enumerator": "^3.0.3", + "symfony/asset": "^3.4 || ^4.0 || ^5.0", + "symfony/browser-kit": "^4.3 || ^5.0", + "symfony/cache": "^3.4 || ^4.0 || ^5.0", + "symfony/config": "^3.4 || ^4.0 || ^5.0", + "symfony/console": "^3.4 || ^4.0 || ^5.0", + "symfony/css-selector": "^3.4 || ^4.0 || ^5.0", + "symfony/debug": "^3.4 || ^4.0", + "symfony/dependency-injection": "^3.4 || ^4.0 || ^5.0", + "symfony/doctrine-bridge": "^3.4 || ^4.0 || ^5.0", + "symfony/dom-crawler": "^3.4 || ^4.0 || ^5.0", + "symfony/event-dispatcher": "^3.4 || ^4.0 || ^5.0", + "symfony/expression-language": "^3.4 || ^4.0 || ^5.0", + "symfony/finder": "^3.4 || ^4.0 || ^5.0", + "symfony/form": "^3.4 || ^4.0 || ^5.0", + "symfony/framework-bundle": "^4.3.2 || ^5.0", + "symfony/http-client": "^4.3 || ^5.0", + "symfony/mercure-bundle": "*", + "symfony/messenger": "^4.3 || ^5.0", + "symfony/phpunit-bridge": "^4.3 || ^5.0", + "symfony/routing": "^3.4 || ^4.3 || ^5.0", + "symfony/security-bundle": "^3.4 || ^4.0 || ^5.0", + "symfony/security-core": "^4.3 || ^5.0", + "symfony/twig-bundle": "^3.4 || ^4.0 || ^5.0", + "symfony/validator": "^3.4 || ^4.0 || ^5.0", + "symfony/web-profiler-bundle": "^4.2 || ^5.0", + "symfony/yaml": "^3.4 || ^4.0 || ^5.0", + "twig/twig": "^1.42.3 || ^2.12", + "webonyx/graphql-php": ">=0.13.1 <1.0" + }, + "suggest": { + "doctrine/mongodb-odm-bundle": "To support MongoDB. Only versions 4.0 and later are supported.", + "elasticsearch/elasticsearch": "To support Elasticsearch.", + "friendsofsymfony/user-bundle": "To use the FOSUserBundle bridge.", + "guzzlehttp/guzzle": "To use the HTTP cache invalidation system.", + "phpdocumentor/reflection-docblock": "To support extracting metadata from PHPDoc.", + "psr/cache-implementation": "To use metadata caching.", + "ramsey/uuid": "To support Ramsey's UUID identifiers.", + "symfony/cache": "To have metadata caching when using Symfony integration.", + "symfony/config": "To load XML configuration files.", + "symfony/expression-language": "To use authorization features.", + "symfony/security": "To use authorization features.", + "symfony/twig-bundle": "To use the Swagger UI integration.", + "symfony/web-profiler-bundle": "To use the data collector.", + "webonyx/graphql-php": "To support GraphQL." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5.x-dev" + } + }, + "autoload": { + "psr-4": { + "ApiPlatform\\Core\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com", + "homepage": "https://dunglas.fr" + } + ], + "description": "Build a fully-featured hypermedia or GraphQL API in minutes", + "homepage": "https://api-platform.com", + "keywords": [ + "Hydra", + "JSON-LD", + "api", + "graphql", + "hal", + "jsonapi", + "openapi", + "rest", + "swagger" + ], + "time": "2019-11-23T11:27:39+00:00" + }, + { + "name": "doctrine/annotations", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/904dca4eb10715b92569fbcd79e201d5c349b6bc", + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "^7.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2019-10-01T18:55:10+00:00" + }, + { + "name": "doctrine/cache", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "382e7f4db9a12dc6c19431743a2b096041bcdd62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/382e7f4db9a12dc6c19431743a2b096041bcdd62", + "reference": "382e7f4db9a12dc6c19431743a2b096041bcdd62", + "shasum": "" + }, + "require": { + "php": "~7.1" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^6.0", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^7.0", + "predis/predis": "~1.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", + "homepage": "https://www.doctrine-project.org/projects/cache.html", + "keywords": [ + "abstraction", + "apcu", + "cache", + "caching", + "couchdb", + "memcached", + "php", + "redis", + "xcache" + ], + "time": "2019-11-29T15:36:20+00:00" + }, + { + "name": "doctrine/collections", + "version": "1.6.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7", + "reference": "6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan-shim": "^0.9.2", + "phpunit/phpunit": "^7.0", + "vimeo/psalm": "^3.2.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", + "homepage": "https://www.doctrine-project.org/projects/collections.html", + "keywords": [ + "array", + "collections", + "iterators", + "php" + ], + "time": "2019-11-13T13:07:11+00:00" + }, + { + "name": "doctrine/common", + "version": "v2.11.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/common.git", + "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/common/zipball/b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", + "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/inflector": "^1.0", + "doctrine/lexer": "^1.0", + "doctrine/persistence": "^1.1", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^1.0", + "phpstan/phpstan": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0", + "symfony/phpunit-bridge": "^4.0.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.11.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, persistence interfaces, proxies, event system and much more.", + "homepage": "https://www.doctrine-project.org/projects/common.html", + "keywords": [ + "common", + "doctrine", + "php" + ], + "time": "2019-09-10T10:10:14+00:00" + }, + { + "name": "doctrine/dbal", + "version": "v2.10.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/0c9a646775ef549eb0a213a4f9bd4381d9b4d934", + "reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934", + "shasum": "" + }, + "require": { + "doctrine/cache": "^1.0", + "doctrine/event-manager": "^1.0", + "ext-pdo": "*", + "php": "^7.2" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "jetbrains/phpstorm-stubs": "^2019.1", + "phpstan/phpstan": "^0.11.3", + "phpunit/phpunit": "^8.4.1", + "symfony/console": "^2.0.5|^3.0|^4.0|^5.0" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "bin": [ + "bin/doctrine-dbal" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.10.x-dev", + "dev-develop": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\DBAL\\": "lib/Doctrine/DBAL" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", + "keywords": [ + "abstraction", + "database", + "db2", + "dbal", + "mariadb", + "mssql", + "mysql", + "oci8", + "oracle", + "pdo", + "pgsql", + "postgresql", + "queryobject", + "sasql", + "sql", + "sqlanywhere", + "sqlite", + "sqlserver", + "sqlsrv" + ], + "time": "2019-11-03T16:50:43+00:00" + }, + { + "name": "doctrine/doctrine-bundle", + "version": "2.0.6", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineBundle.git", + "reference": "0ef972d3b730f975c80db9fffa4b2a0258c91442" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/0ef972d3b730f975c80db9fffa4b2a0258c91442", + "reference": "0ef972d3b730f975c80db9fffa4b2a0258c91442", + "shasum": "" + }, + "require": { + "doctrine/dbal": "^2.9.0", + "doctrine/persistence": "^1.3.3", + "jdorn/sql-formatter": "^1.2.16", + "php": "^7.1", + "symfony/cache": "^4.3.3|^5.0", + "symfony/config": "^4.3.3|^5.0", + "symfony/console": "^3.4.30|^4.3.3|^5.0", + "symfony/dependency-injection": "^4.3.3|^5.0", + "symfony/doctrine-bridge": "^4.3.7|^5.0", + "symfony/framework-bundle": "^3.4.30|^4.3.3|^5.0", + "symfony/service-contracts": "^1.1.1|^2.0" + }, + "conflict": { + "doctrine/orm": "<2.6", + "twig/twig": "<1.34|>=2.0,<2.4" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "doctrine/orm": "^2.6", + "ocramius/proxy-manager": "^2.1", + "phpunit/phpunit": "^7.5", + "symfony/phpunit-bridge": "^4.2", + "symfony/property-info": "^4.3.3|^5.0", + "symfony/twig-bridge": "^3.4.30|^4.3.3|^5.0", + "symfony/validator": "^3.4.30|^4.3.3|^5.0", + "symfony/web-profiler-bundle": "^3.4.30|^4.3.3|^5.0", + "symfony/yaml": "^3.4.30|^4.3.3|^5.0", + "twig/twig": "^1.34|^2.12" + }, + "suggest": { + "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", + "symfony/web-profiler-bundle": "To use the data collector." + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\DoctrineBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Doctrine Project", + "homepage": "http://www.doctrine-project.org/" + } + ], + "description": "Symfony DoctrineBundle", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "dbal", + "orm", + "persistence" + ], + "time": "2019-12-19T13:47:07+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "629572819973f13486371cb611386eb17851e85c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/629572819973f13486371cb611386eb17851e85c", + "reference": "629572819973f13486371cb611386eb17851e85c", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "event dispatcher", + "event manager", + "event system", + "events" + ], + "time": "2019-11-10T09:48:07+00:00" + }, + { + "name": "doctrine/inflector", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2019-10-30T19:59:35+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2019-10-21T16:45:58+00:00" + }, + { + "name": "doctrine/lexer", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "shasum": "" + }, + "require": { + "php": "^7.2" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "time": "2019-10-30T14:39:59+00:00" + }, + { + "name": "doctrine/orm", + "version": "v2.7.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/orm.git", + "reference": "4d763ca4c925f647b248b9fa01b5f47aa3685d62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/orm/zipball/4d763ca4c925f647b248b9fa01b5f47aa3685d62", + "reference": "4d763ca4c925f647b248b9fa01b5f47aa3685d62", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.8", + "doctrine/cache": "^1.9.1", + "doctrine/collections": "^1.5", + "doctrine/common": "^2.11", + "doctrine/dbal": "^2.9.3", + "doctrine/event-manager": "^1.1", + "doctrine/instantiator": "^1.3", + "doctrine/persistence": "^1.2", + "ext-pdo": "*", + "php": "^7.1", + "symfony/console": "^3.0|^4.0|^5.0" + }, + "require-dev": { + "doctrine/coding-standard": "^5.0", + "phpunit/phpunit": "^7.5", + "symfony/yaml": "^3.4|^4.0|^5.0" + }, + "suggest": { + "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" + }, + "bin": [ + "bin/doctrine" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\ORM\\": "lib/Doctrine/ORM" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Object-Relational-Mapper for PHP", + "homepage": "https://www.doctrine-project.org/projects/orm.html", + "keywords": [ + "database", + "orm" + ], + "time": "2019-11-19T08:38:05+00:00" + }, + { + "name": "doctrine/persistence", + "version": "1.3.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/persistence.git", + "reference": "99b196bbd4715a94fa100fac664a351ffa46d6a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/99b196bbd4715a94fa100fac664a351ffa46d6a5", + "reference": "99b196bbd4715a94fa100fac664a351ffa46d6a5", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.10@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common", + "Doctrine\\Persistence\\": "lib/Doctrine/Persistence" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", + "homepage": "https://doctrine-project.org/projects/persistence.html", + "keywords": [ + "mapper", + "object", + "odm", + "orm", + "persistence" + ], + "time": "2019-12-13T10:43:02+00:00" + }, + { + "name": "doctrine/reflection", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/reflection.git", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/reflection/zipball/02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "doctrine/common": "^2.8", + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Reflection component", + "homepage": "https://www.doctrine-project.org/projects/reflection.html", + "keywords": [ + "reflection" + ], + "time": "2018-06-14T14:45:07+00:00" + }, + { + "name": "fig/link-util", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/link-util.git", + "reference": "47f55860678a9e202206047bc02767556d298106" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/link-util/zipball/47f55860678a9e202206047bc02767556d298106", + "reference": "47f55860678a9e202206047bc02767556d298106", + "shasum": "" + }, + "require": { + "php": ">=5.5.0", + "psr/link": "~1.0@dev" + }, + "provide": { + "psr/link-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.1", + "squizlabs/php_codesniffer": "^2.3.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Fig\\Link\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common utility implementations for HTTP links", + "keywords": [ + "http", + "http-link", + "link", + "psr", + "psr-13", + "rest" + ], + "time": "2019-12-18T15:40:05+00:00" + }, + { + "name": "jdorn/sql-formatter", + "version": "v1.2.17", + "source": { + "type": "git", + "url": "https://github.com/jdorn/sql-formatter.git", + "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jdorn/sql-formatter/zipball/64990d96e0959dff8e059dfcdc1af130728d92bc", + "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "lib" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeremy Dorn", + "email": "jeremy@jeremydorn.com", + "homepage": "http://jeremydorn.com/" + } + ], + "description": "a PHP SQL highlighting library", + "homepage": "https://github.com/jdorn/sql-formatter/", + "keywords": [ + "highlight", + "sql" + ], + "time": "2014-01-12T16:20:24+00:00" + }, + { + "name": "nelmio/cors-bundle", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/nelmio/NelmioCorsBundle.git", + "reference": "9683e6d30d000ef998919261329d825de7c53499" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nelmio/NelmioCorsBundle/zipball/9683e6d30d000ef998919261329d825de7c53499", + "reference": "9683e6d30d000ef998919261329d825de7c53499", + "shasum": "" + }, + "require": { + "symfony/framework-bundle": "^4.3 || ^5.0" + }, + "require-dev": { + "mockery/mockery": "^1.2", + "symfony/phpunit-bridge": "^4.3 || ^5.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Nelmio\\CorsBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nelmio", + "homepage": "http://nelm.io" + }, + { + "name": "Symfony Community", + "homepage": "https://github.com/nelmio/NelmioCorsBundle/contributors" + } + ], + "description": "Adds CORS (Cross-Origin Resource Sharing) headers support in your Symfony application", + "keywords": [ + "api", + "cors", + "crossdomain" + ], + "time": "2019-11-15T08:54:08+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "~6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2018-08-07T13:53:10+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "4.3.4", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c", + "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", + "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "doctrine/instantiator": "^1.0.5", + "mockery/mockery": "^1.0", + "phpdocumentor/type-resolver": "0.4.*", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2019-12-28T18:55:12+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "shasum": "" + }, + "require": { + "php": "^7.1", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "^7.1", + "mockery/mockery": "~1", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "time": "2019-08-22T18:11:29+00:00" + }, + { + "name": "psr/cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "time": "2016-08-06T20:24:11+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/link", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/link.git", + "reference": "eea8e8662d5cd3ae4517c9b864493f59fca95562" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/link/zipball/eea8e8662d5cd3ae4517c9b864493f59fca95562", + "reference": "eea8e8662d5cd3ae4517c9b864493f59fca95562", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Link\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for HTTP links", + "keywords": [ + "http", + "http-link", + "link", + "psr", + "psr-13", + "rest" + ], + "time": "2016-10-28T16:06:13+00:00" + }, + { + "name": "psr/log", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2019-11-01T11:05:21+00:00" + }, + { + "name": "symfony/asset", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/asset.git", + "reference": "6b66969b9f5cd53c1ce69bdc651aa962f211b6b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/asset/zipball/6b66969b9f5cd53c1ce69bdc651aa962f211b6b6", + "reference": "6b66969b9f5cd53c1ce69bdc651aa962f211b6b6", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "require-dev": { + "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-kernel": "^4.4|^5.0" + }, + "suggest": { + "symfony/http-foundation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Asset\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Asset Component", + "homepage": "https://symfony.com", + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/cache", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "6e8d978878ae5de705ec9fabbb6011cc18776bc9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/6e8d978878ae5de705ec9fabbb6011cc18776bc9", + "reference": "6e8d978878ae5de705ec9fabbb6011cc18776bc9", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/cache": "~1.0", + "psr/log": "~1.0", + "symfony/cache-contracts": "^1.1.7|^2", + "symfony/service-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0" + }, + "conflict": { + "doctrine/dbal": "<2.5", + "symfony/dependency-injection": "<4.4", + "symfony/http-kernel": "<4.4", + "symfony/var-dumper": "<4.4" + }, + "provide": { + "psr/cache-implementation": "1.0", + "psr/simple-cache-implementation": "1.0", + "symfony/cache-implementation": "1.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/cache": "~1.6", + "doctrine/dbal": "~2.5", + "predis/predis": "~1.1", + "psr/simple-cache": "^1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Cache component with PSR-6, PSR-16, and tags", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "time": "2019-12-12T13:03:32+00:00" + }, + { + "name": "symfony/cache-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16", + "reference": "23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/cache": "^1.0" + }, + "suggest": { + "symfony/cache-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Cache\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to caching", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/config", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "7f930484966350906185ba0a604728f7898b7ba0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/7f930484966350906185ba0a604728f7898b7ba0", + "reference": "7f930484966350906185ba0a604728f7898b7ba0", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/filesystem": "^4.4|^5.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/finder": "<4.4" + }, + "require-dev": { + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2019-12-18T13:50:31+00:00" + }, + { + "name": "symfony/console", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "fe6e3cd889ca64172d7a742a2eb058541404ef47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/fe6e3cd889ca64172d7a742a2eb058541404ef47", + "reference": "fe6e3cd889ca64172d7a742a2eb058541404ef47", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "symfony/dependency-injection": "<4.4", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2019-12-17T13:20:22+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "f9dbfbf487d08f60b1c83220edcd16559d1e40a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f9dbfbf487d08f60b1c83220edcd16559d1e40a2", + "reference": "f9dbfbf487d08f60b1c83220edcd16559d1e40a2", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/container": "^1.0", + "symfony/service-contracts": "^1.1.6|^2" + }, + "conflict": { + "symfony/config": "<5.0", + "symfony/finder": "<4.4", + "symfony/proxy-manager-bridge": "<4.4", + "symfony/yaml": "<4.4" + }, + "provide": { + "psr/container-implementation": "1.0", + "symfony/service-implementation": "1.0" + }, + "require-dev": { + "symfony/config": "^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "https://symfony.com", + "time": "2019-12-19T16:01:11+00:00" + }, + { + "name": "symfony/doctrine-bridge", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/doctrine-bridge.git", + "reference": "0bdb2d31741cacacb95130d28fbac939c4d574f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/0bdb2d31741cacacb95130d28fbac939c4d574f2", + "reference": "0bdb2d31741cacacb95130d28fbac939c4d574f2", + "shasum": "" + }, + "require": { + "doctrine/event-manager": "~1.0", + "doctrine/persistence": "^1.3", + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/dependency-injection": "<4.4", + "symfony/form": "<5", + "symfony/http-kernel": "<5", + "symfony/messenger": "<4.4", + "symfony/property-info": "<5", + "symfony/security-bundle": "<5", + "symfony/security-core": "<5", + "symfony/validator": "<5.0.2" + }, + "require-dev": { + "doctrine/annotations": "~1.7", + "doctrine/cache": "~1.6", + "doctrine/collections": "~1.0", + "doctrine/data-fixtures": "1.0.*", + "doctrine/dbal": "~2.4", + "doctrine/orm": "^2.6.3", + "doctrine/reflection": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/form": "^5.0", + "symfony/http-kernel": "^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/property-access": "^4.4|^5.0", + "symfony/property-info": "^5.0", + "symfony/proxy-manager-bridge": "^4.4|^5.0", + "symfony/security-core": "^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/validator": "^5.0.2", + "symfony/var-dumper": "^4.4|^5.0" + }, + "suggest": { + "doctrine/data-fixtures": "", + "doctrine/dbal": "", + "doctrine/orm": "", + "symfony/form": "", + "symfony/property-info": "", + "symfony/validator": "" + }, + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Doctrine\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Doctrine Bridge", + "homepage": "https://symfony.com", + "time": "2019-12-19T12:10:29+00:00" + }, + { + "name": "symfony/dotenv", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/dotenv.git", + "reference": "7e1bc9024edd9157264e388080df2533306894d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/7e1bc9024edd9157264e388080df2533306894d3", + "reference": "7e1bc9024edd9157264e388080df2533306894d3", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "require-dev": { + "symfony/process": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Dotenv\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Registers environment variables from a .env file", + "homepage": "https://symfony.com", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "time": "2019-12-19T16:01:11+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "460863313bd3212d7c38e1b40602cbcfeeeea4a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/460863313bd3212d7c38e1b40602cbcfeeeea4a5", + "reference": "460863313bd3212d7c38e1b40602cbcfeeeea4a5", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/log": "^1.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "require-dev": { + "symfony/http-kernel": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony ErrorHandler Component", + "homepage": "https://symfony.com", + "time": "2019-12-16T14:48:47+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "7b738a51645e10f864cc25c24d232fb03f37b475" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7b738a51645e10f864cc25c24d232fb03f37b475", + "reference": "7b738a51645e10f864cc25c24d232fb03f37b475", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/event-dispatcher-contracts": "^2" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/stopwatch": "^4.4|^5.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "af23c2584d4577d54661c434446fb8fbed6025dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/af23c2584d4577d54661c434446fb8fbed6025dd", + "reference": "af23c2584d4577d54661c434446fb8fbed6025dd", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/expression-language", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/expression-language.git", + "reference": "412c7cc679805e78987a18fd5860013238f1daa2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/412c7cc679805e78987a18fd5860013238f1daa2", + "reference": "412c7cc679805e78987a18fd5860013238f1daa2", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/cache": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\ExpressionLanguage\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony ExpressionLanguage Component", + "homepage": "https://symfony.com", + "time": "2019-12-10T11:06:55+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "1d71f670bc5a07b9ccc97dc44f932177a322d4e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/1d71f670bc5a07b9ccc97dc44f932177a322d4e6", + "reference": "1d71f670bc5a07b9ccc97dc44f932177a322d4e6", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2019-11-26T23:25:11+00:00" + }, + { + "name": "symfony/finder", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "17874dd8ab9a19422028ad56172fb294287a701b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/17874dd8ab9a19422028ad56172fb294287a701b", + "reference": "17874dd8ab9a19422028ad56172fb294287a701b", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/flex", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/flex.git", + "reference": "952f45d1c5077e658cb16a61d11603bee873f968" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/flex/zipball/952f45d1c5077e658cb16a61d11603bee873f968", + "reference": "952f45d1c5077e658cb16a61d11603bee873f968", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0", + "php": "^7.0" + }, + "require-dev": { + "composer/composer": "^1.0.2", + "symfony/dotenv": "^3.4|^4.0|^5.0", + "symfony/phpunit-bridge": "^3.4.19|^4.1.8|^5.0", + "symfony/process": "^2.7|^3.0|^4.0|^5.0" + }, + "type": "composer-plugin", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + }, + "class": "Symfony\\Flex\\Flex" + }, + "autoload": { + "psr-4": { + "Symfony\\Flex\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien.potencier@gmail.com" + } + ], + "description": "Composer plugin for Symfony", + "time": "2019-12-13T18:05:11+00:00" + }, + { + "name": "symfony/framework-bundle", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/framework-bundle.git", + "reference": "36e51776b231d8e224da4ce4c60079540acd1c55" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/36e51776b231d8e224da4ce4c60079540acd1c55", + "reference": "36e51776b231d8e224da4ce4c60079540acd1c55", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": "^7.2.5", + "symfony/cache": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/dependency-injection": "^5.0.1", + "symfony/error-handler": "^4.4.1|^5.0.1", + "symfony/filesystem": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-kernel": "^5.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/routing": "^5.0" + }, + "conflict": { + "doctrine/persistence": "<1.3", + "phpdocumentor/reflection-docblock": "<3.0", + "phpdocumentor/type-resolver": "<0.2.1", + "phpunit/phpunit": "<5.4.3", + "symfony/asset": "<4.4", + "symfony/browser-kit": "<4.4", + "symfony/console": "<4.4", + "symfony/dom-crawler": "<4.4", + "symfony/dotenv": "<4.4", + "symfony/form": "<4.4", + "symfony/http-client": "<4.4", + "symfony/lock": "<4.4", + "symfony/mailer": "<4.4", + "symfony/messenger": "<4.4", + "symfony/mime": "<4.4", + "symfony/property-info": "<4.4", + "symfony/serializer": "<4.4", + "symfony/stopwatch": "<4.4", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<4.4", + "symfony/twig-bundle": "<4.4", + "symfony/validator": "<4.4", + "symfony/web-profiler-bundle": "<4.4", + "symfony/workflow": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "~1.7", + "doctrine/cache": "~1.0", + "paragonie/sodium_compat": "^1.8", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", + "symfony/asset": "^4.4|^5.0", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/dotenv": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/form": "^4.4|^5.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/mailer": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/process": "^4.4|^5.0", + "symfony/property-info": "^4.4|^5.0", + "symfony/security-csrf": "^4.4|^5.0", + "symfony/security-http": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/string": "~5.0.0", + "symfony/translation": "^5.0", + "symfony/twig-bundle": "^4.4|^5.0", + "symfony/validator": "^4.4|^5.0", + "symfony/web-link": "^4.4|^5.0", + "symfony/workflow": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0", + "twig/twig": "^2.10|^3.0" + }, + "suggest": { + "ext-apcu": "For best performance of the system caches", + "symfony/console": "For using the console commands", + "symfony/form": "For using forms", + "symfony/property-info": "For using the property_info service", + "symfony/serializer": "For using the serializer service", + "symfony/validator": "For using validation", + "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering", + "symfony/yaml": "For using the debug:config and lint:yaml commands" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\FrameworkBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony FrameworkBundle", + "homepage": "https://symfony.com", + "time": "2019-12-17T10:33:13+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "5dd7f6be6e62d86ba6f3154cf40e78936367978b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5dd7f6be6e62d86ba6f3154cf40e78936367978b", + "reference": "5dd7f6be6e62d86ba6f3154cf40e78936367978b", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/mime": "^4.4|^5.0", + "symfony/polyfill-mbstring": "~1.1" + }, + "require-dev": { + "predis/predis": "~1.0", + "symfony/expression-language": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2019-12-19T16:01:11+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "00ce30602f3f690e66a63c327743d7b26c723b2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/00ce30602f3f690e66a63c327743d7b26c723b2e", + "reference": "00ce30602f3f690e66a63c327743d7b26c723b2e", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/log": "~1.0", + "symfony/error-handler": "^4.4|^5.0", + "symfony/event-dispatcher": "^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php73": "^1.9" + }, + "conflict": { + "symfony/browser-kit": "<4.4", + "symfony/cache": "<5.0", + "symfony/config": "<5.0", + "symfony/dependency-injection": "<4.4", + "symfony/doctrine-bridge": "<5.0", + "symfony/form": "<5.0", + "symfony/http-client": "<5.0", + "symfony/mailer": "<5.0", + "symfony/messenger": "<5.0", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<5.0", + "symfony/validator": "<5.0", + "twig/twig": "<2.4" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/cache": "~1.0", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/routing": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "twig/twig": "^2.4|^3.0" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com", + "time": "2019-12-19T18:35:03+00:00" + }, + { + "name": "symfony/inflector", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/inflector.git", + "reference": "aaeb5e293294070d1b061fa3d7889bac69909320" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/inflector/zipball/aaeb5e293294070d1b061fa3d7889bac69909320", + "reference": "aaeb5e293294070d1b061fa3d7889bac69909320", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Inflector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Inflector Component", + "homepage": "https://symfony.com", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string", + "symfony", + "words" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/mime", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "0e6a4ced216e49d457eddcefb61132173a876d79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/0e6a4ced216e49d457eddcefb61132173a876d79", + "reference": "0e6a4ced216e49d457eddcefb61132173a876d79", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "symfony/mailer": "<4.4" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10", + "symfony/dependency-injection": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A library to manipulate MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "time": "2019-11-30T14:12:50+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.13.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6f9c239e61e1b0c9229a28ff89a812dc449c3d46", + "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.9" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "time": "2019-11-27T13:56:44+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.13.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f", + "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2019-11-27T14:18:11+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.13.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/4b0e2222c55a25b4541305a053013d5647d3a25f", + "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2019-11-27T16:25:15+00:00" + }, + { + "name": "symfony/property-access", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-access.git", + "reference": "b597c4f4dffc522bc4ed4bedcef9ed08d3ae3d23" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-access/zipball/b597c4f4dffc522bc4ed4bedcef9ed08d3ae3d23", + "reference": "b597c4f4dffc522bc4ed4bedcef9ed08d3ae3d23", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/inflector": "^4.4|^5.0" + }, + "require-dev": { + "symfony/cache": "^4.4|^5.0" + }, + "suggest": { + "psr/cache-implementation": "To cache access methods." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyAccess\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony PropertyAccess Component", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property path", + "reflection" + ], + "time": "2019-12-10T11:06:55+00:00" + }, + { + "name": "symfony/property-info", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-info.git", + "reference": "f0bf8d7360e47261ceec67d9338a0c6257f59878" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-info/zipball/f0bf8d7360e47261ceec67d9338a0c6257f59878", + "reference": "f0bf8d7360e47261ceec67d9338a0c6257f59878", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/inflector": "^4.4|^5.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<0.3.0", + "symfony/dependency-injection": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "~1.7", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", + "symfony/cache": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0" + }, + "suggest": { + "phpdocumentor/reflection-docblock": "To use the PHPDoc", + "psr/cache-implementation": "To cache results", + "symfony/doctrine-bridge": "To use Doctrine metadata", + "symfony/serializer": "To use Serializer metadata" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Property Info Component", + "homepage": "https://symfony.com", + "keywords": [ + "doctrine", + "phpdoc", + "property", + "symfony", + "type", + "validator" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/routing", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "120c5fa4f4ef5466cbb510ece8126e0007285301" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/120c5fa4f4ef5466cbb510ece8126e0007285301", + "reference": "120c5fa4f4ef5466cbb510ece8126e0007285301", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "conflict": { + "symfony/config": "<5.0", + "symfony/dependency-injection": "<4.4", + "symfony/yaml": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "~1.2", + "psr/log": "~1.0", + "symfony/config": "^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Routing Component", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2019-12-12T13:03:32+00:00" + }, + { + "name": "symfony/security-bundle", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-bundle.git", + "reference": "5cf83dea155ae9666dd491470d760c126e4dab98" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/5cf83dea155ae9666dd491470d760c126e4dab98", + "reference": "5cf83dea155ae9666dd491470d760c126e4dab98", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": "^7.2.5", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/http-kernel": "^5.0", + "symfony/security-core": "^4.4|^5.0", + "symfony/security-csrf": "^4.4|^5.0", + "symfony/security-guard": "^4.4|^5.0", + "symfony/security-http": "^4.4.1|^5.0.1" + }, + "conflict": { + "symfony/browser-kit": "<4.4", + "symfony/console": "<4.4", + "symfony/framework-bundle": "<4.4", + "symfony/ldap": "<4.4", + "symfony/twig-bundle": "<4.4" + }, + "require-dev": { + "doctrine/doctrine-bundle": "^1.5|^2.0", + "symfony/asset": "^4.4|^5.0", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/form": "^4.4|^5.0", + "symfony/framework-bundle": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/twig-bridge": "^4.4|^5.0", + "symfony/twig-bundle": "^4.4|^5.0", + "symfony/validator": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0", + "twig/twig": "^2.10|^3.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\SecurityBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony SecurityBundle", + "homepage": "https://symfony.com", + "time": "2019-12-16T10:47:49+00:00" + }, + { + "name": "symfony/security-core", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-core.git", + "reference": "4fa0454de2fab0f6c2e9990976d8872b16a0e0a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-core/zipball/4fa0454de2fab0f6c2e9990976d8872b16a0e0a9", + "reference": "4fa0454de2fab0f6c2e9990976d8872b16a0e0a9", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/event-dispatcher-contracts": "^1.1|^2", + "symfony/service-contracts": "^1.1.6|^2" + }, + "conflict": { + "symfony/event-dispatcher": "<4.4", + "symfony/ldap": "<4.4", + "symfony/security-guard": "<4.4" + }, + "require-dev": { + "psr/container": "^1.0", + "psr/log": "~1.0", + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/ldap": "^4.4|^5.0", + "symfony/validator": "^4.4|^5.0" + }, + "suggest": { + "psr/container-implementation": "To instantiate the Security class", + "symfony/event-dispatcher": "", + "symfony/expression-language": "For using the expression voter", + "symfony/http-foundation": "", + "symfony/ldap": "For using LDAP integration", + "symfony/validator": "For using the user password constraint" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Core\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component - Core Library", + "homepage": "https://symfony.com", + "time": "2019-12-16T11:08:25+00:00" + }, + { + "name": "symfony/security-csrf", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-csrf.git", + "reference": "df14c3ebed8ed99750e8d27a6333918f80b5a8ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/df14c3ebed8ed99750e8d27a6333918f80b5a8ea", + "reference": "df14c3ebed8ed99750e8d27a6333918f80b5a8ea", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/security-core": "^4.4|^5.0" + }, + "conflict": { + "symfony/http-foundation": "<4.4" + }, + "require-dev": { + "symfony/http-foundation": "^4.4|^5.0" + }, + "suggest": { + "symfony/http-foundation": "For using the class SessionTokenStorage." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Csrf\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component - CSRF Library", + "homepage": "https://symfony.com", + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/security-guard", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-guard.git", + "reference": "3e724cb9c186986e66ca2c1aaaba16fe4aa9abf9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-guard/zipball/3e724cb9c186986e66ca2c1aaaba16fe4aa9abf9", + "reference": "3e724cb9c186986e66ca2c1aaaba16fe4aa9abf9", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/security-core": "^5.0", + "symfony/security-http": "^4.4.1|^5.0.1" + }, + "require-dev": { + "psr/log": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Guard\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component - Guard", + "homepage": "https://symfony.com", + "time": "2019-11-30T14:12:50+00:00" + }, + { + "name": "symfony/security-http", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-http.git", + "reference": "64afb9eb9161c65f87de6fc31e3633843bddc02a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-http/zipball/64afb9eb9161c65f87de6fc31e3633843bddc02a", + "reference": "64afb9eb9161c65f87de6fc31e3633843bddc02a", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-kernel": "^4.4|^5.0", + "symfony/property-access": "^4.4|^5.0", + "symfony/security-core": "^4.4|^5.0" + }, + "conflict": { + "symfony/security-csrf": "<4.4" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/routing": "^4.4|^5.0", + "symfony/security-csrf": "^4.4|^5.0" + }, + "suggest": { + "symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs", + "symfony/security-csrf": "For using tokens to protect authentication/logout attempts" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Http\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component - HTTP Integration", + "homepage": "https://symfony.com", + "time": "2019-12-16T10:47:49+00:00" + }, + { + "name": "symfony/serializer", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/serializer.git", + "reference": "3cfc478c102f2d3bcf60edd339cd9c3cb446a576" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/serializer/zipball/3cfc478c102f2d3bcf60edd339cd9c3cb446a576", + "reference": "3cfc478c102f2d3bcf60edd339cd9c3cb446a576", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "phpdocumentor/type-resolver": "<0.2.1", + "symfony/dependency-injection": "<4.4", + "symfony/property-access": "<4.4", + "symfony/property-info": "<4.4", + "symfony/yaml": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0", + "phpdocumentor/reflection-docblock": "^3.2|^4.0", + "symfony/cache": "^4.4|^5.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/error-handler": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0", + "symfony/property-access": "^4.4|^5.0", + "symfony/property-info": "^4.4|^5.0", + "symfony/validator": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", + "doctrine/cache": "For using the default cached annotation reader and metadata cache.", + "psr/cache-implementation": "For using the metadata cache.", + "symfony/config": "For using the XML mapping loader.", + "symfony/mime": "For using a MIME type guesser within the DataUriNormalizer.", + "symfony/property-access": "For using the ObjectNormalizer.", + "symfony/property-info": "To deserialize relations.", + "symfony/yaml": "For using the default YAML mapping loader." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Serializer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Serializer Component", + "homepage": "https://symfony.com", + "time": "2019-12-16T11:08:25+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "144c5e51266b281231e947b51223ba14acf1a749" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", + "reference": "144c5e51266b281231e947b51223ba14acf1a749", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/container": "^1.0" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "8cc682ac458d75557203b2f2f14b0b92e1c744ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/8cc682ac458d75557203b2f2f14b0b92e1c744ed", + "reference": "8cc682ac458d75557203b2f2f14b0b92e1c744ed", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/twig-bridge", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/twig-bridge.git", + "reference": "abbaeee38ff39651e335c55be40752be2ddd0976" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/abbaeee38ff39651e335c55be40752be2ddd0976", + "reference": "abbaeee38ff39651e335c55be40752be2ddd0976", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/translation-contracts": "^1.1|^2", + "twig/twig": "^2.10|^3.0" + }, + "conflict": { + "symfony/console": "<4.4", + "symfony/form": "<5.0", + "symfony/http-foundation": "<4.4", + "symfony/http-kernel": "<4.4", + "symfony/translation": "<5.0", + "symfony/workflow": "<4.4" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10", + "symfony/asset": "^4.4|^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/form": "^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-kernel": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/routing": "^4.4|^5.0", + "symfony/security-acl": "^2.8|^3.0", + "symfony/security-core": "^4.4|^5.0", + "symfony/security-csrf": "^4.4|^5.0", + "symfony/security-http": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^5.0", + "symfony/web-link": "^4.4|^5.0", + "symfony/workflow": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0", + "twig/cssinliner-extra": "^2.12", + "twig/inky-extra": "^2.12", + "twig/markdown-extra": "^2.12" + }, + "suggest": { + "symfony/asset": "For using the AssetExtension", + "symfony/expression-language": "For using the ExpressionExtension", + "symfony/finder": "", + "symfony/form": "For using the FormExtension", + "symfony/http-kernel": "For using the HttpKernelExtension", + "symfony/routing": "For using the RoutingExtension", + "symfony/security-core": "For using the SecurityExtension", + "symfony/security-csrf": "For using the CsrfExtension", + "symfony/security-http": "For using the LogoutUrlExtension", + "symfony/stopwatch": "For using the StopwatchExtension", + "symfony/translation": "For using the TranslationExtension", + "symfony/var-dumper": "For using the DumpExtension", + "symfony/web-link": "For using the WebLinkExtension", + "symfony/yaml": "For using the YamlExtension" + }, + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Twig\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Twig Bridge", + "homepage": "https://symfony.com", + "time": "2019-12-18T16:23:52+00:00" + }, + { + "name": "symfony/twig-bundle", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/twig-bundle.git", + "reference": "a54f6db9d452aa06a77e9f8562974a61e15bfa42" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/a54f6db9d452aa06a77e9f8562974a61e15bfa42", + "reference": "a54f6db9d452aa06a77e9f8562974a61e15bfa42", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/config": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-kernel": "^5.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/twig-bridge": "^5.0", + "twig/twig": "^2.10|^3.0" + }, + "conflict": { + "symfony/dependency-injection": "<4.4", + "symfony/framework-bundle": "<5.0", + "symfony/translation": "<5.0" + }, + "require-dev": { + "doctrine/annotations": "~1.7", + "doctrine/cache": "~1.0", + "symfony/asset": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/form": "^4.4|^5.0", + "symfony/framework-bundle": "^5.0", + "symfony/routing": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^5.0", + "symfony/web-link": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\TwigBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony TwigBundle", + "homepage": "https://symfony.com", + "time": "2019-12-10T11:06:55+00:00" + }, + { + "name": "symfony/validator", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/validator.git", + "reference": "ff51ce51b3fc4c312039de2cb302e01c17843899" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/validator/zipball/ff51ce51b3fc4c312039de2cb302e01c17843899", + "reference": "ff51ce51b3fc4c312039de2cb302e01c17843899", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^1.1|^2" + }, + "conflict": { + "doctrine/lexer": "<1.0.2", + "phpunit/phpunit": "<5.4.3", + "symfony/dependency-injection": "<4.4", + "symfony/http-kernel": "<4.4", + "symfony/intl": "<4.4", + "symfony/translation": "<4.4", + "symfony/yaml": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "~1.7", + "doctrine/cache": "~1.0", + "egulias/email-validator": "^2.1.10", + "symfony/cache": "^4.4|^5.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-kernel": "^4.4|^5.0", + "symfony/intl": "^4.4|^5.0", + "symfony/property-access": "^4.4|^5.0", + "symfony/property-info": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", + "doctrine/cache": "For using the default cached annotation reader.", + "egulias/email-validator": "Strict (RFC compliant) email validation", + "psr/cache-implementation": "For using the mapping cache.", + "symfony/config": "", + "symfony/expression-language": "For using the Expression validator", + "symfony/http-foundation": "", + "symfony/intl": "", + "symfony/property-access": "For accessing properties within comparison constraints", + "symfony/property-info": "To automatically add NotNull and Type constraints", + "symfony/translation": "For translating validation errors.", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Validator\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Validator Component", + "homepage": "https://symfony.com", + "time": "2019-12-17T10:33:13+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a", + "reference": "d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<4.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "twig/twig": "^2.4|^3.0" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2019-12-18T13:50:31+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "1b9653e68d5b701bf6d9c91bdd3660078c9f4f28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1b9653e68d5b701bf6d9c91bdd3660078c9f4f28", + "reference": "1b9653e68d5b701bf6d9c91bdd3660078c9f4f28", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "require-dev": { + "symfony/var-dumper": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A blend of var_export() + serialize() to turn any serializable data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "serialize" + ], + "time": "2019-12-01T08:48:26+00:00" + }, + { + "name": "symfony/web-link", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/web-link.git", + "reference": "572ab541ec2ca2e0d0f76fd08da006805e4db157" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/web-link/zipball/572ab541ec2ca2e0d0f76fd08da006805e4db157", + "reference": "572ab541ec2ca2e0d0f76fd08da006805e4db157", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/link": "^1.0" + }, + "conflict": { + "symfony/http-kernel": "<4.4" + }, + "provide": { + "psr/link-implementation": "1.0" + }, + "require-dev": { + "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-kernel": "^4.4|^5.0" + }, + "suggest": { + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\WebLink\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony WebLink Component", + "homepage": "https://symfony.com", + "keywords": [ + "dns-prefetch", + "http", + "http2", + "link", + "performance", + "prefetch", + "preload", + "prerender", + "psr13", + "push" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/yaml", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "847661e77afa48d99ecfa508e8b60f0b029a19c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/847661e77afa48d99ecfa508e8b60f0b029a19c0", + "reference": "847661e77afa48d99ecfa508e8b60f0b029a19c0", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<4.4" + }, + "require-dev": { + "symfony/console": "^4.4|^5.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2019-12-10T11:06:55+00:00" + }, + { + "name": "twig/twig", + "version": "v3.0.1", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "28f856a4c57eeb24485916e8a68403f41a133616" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/28f856a4c57eeb24485916e8a68403f41a133616", + "reference": "28f856a4c57eeb24485916e8a68403f41a133616", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3" + }, + "require-dev": { + "psr/container": "^1.0", + "symfony/phpunit-bridge": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "time": "2019-12-28T07:17:28+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "573381c0a64f155a0d9a23f4b0c797194805b925" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/573381c0a64f155a0d9a23f4b0c797194805b925", + "reference": "573381c0a64f155a0d9a23f4b0c797194805b925", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "vimeo/psalm": "<3.6.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^7.5.13" + }, + "type": "library", + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2019-11-24T13:36:37+00:00" + }, + { + "name": "willdurand/negotiation", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/willdurand/Negotiation.git", + "reference": "03436ededa67c6e83b9b12defac15384cb399dc9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/willdurand/Negotiation/zipball/03436ededa67c6e83b9b12defac15384cb399dc9", + "reference": "03436ededa67c6e83b9b12defac15384cb399dc9", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + }, + "autoload": { + "psr-4": { + "Negotiation\\": "src/Negotiation" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "William Durand", + "email": "will+git@drnd.me" + } + ], + "description": "Content Negotiation tools for PHP provided as a standalone library.", + "homepage": "http://williamdurand.fr/Negotiation/", + "keywords": [ + "accept", + "content", + "format", + "header", + "negotiation" + ], + "time": "2017-05-14T17:21:12+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.2.5", + "ext-ctype": "*", + "ext-iconv": "*" + }, + "platform-dev": [] +} diff --git a/bookshop-api/config/bootstrap.php b/bookshop-api/config/bootstrap.php new file mode 100644 index 0000000..976a776 --- /dev/null +++ b/bookshop-api/config/bootstrap.php @@ -0,0 +1,23 @@ +=1.2) +if (is_array($env = @include dirname(__DIR__).'/.env.local.php') && ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV']) { + foreach ($env as $k => $v) { + $_ENV[$k] = $_ENV[$k] ?? (isset($_SERVER[$k]) && 0 !== strpos($k, 'HTTP_') ? $_SERVER[$k] : $v); + } +} elseif (!class_exists(Dotenv::class)) { + throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.'); +} else { + // load all the .env files + (new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env'); +} + +$_SERVER += $_ENV; +$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; +$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV']; +$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0'; diff --git a/bookshop-api/config/bundles.php b/bookshop-api/config/bundles.php new file mode 100644 index 0000000..a351714 --- /dev/null +++ b/bookshop-api/config/bundles.php @@ -0,0 +1,10 @@ + ['all' => true], + Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], + Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], + Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true], + Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], + ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true], +]; diff --git a/bookshop-api/config/packages/api_platform.yaml b/bookshop-api/config/packages/api_platform.yaml new file mode 100644 index 0000000..2eb7b4c --- /dev/null +++ b/bookshop-api/config/packages/api_platform.yaml @@ -0,0 +1,7 @@ +api_platform: + mapping: + paths: ['%kernel.project_dir%/src/Entity'] + patch_formats: + json: ['application/merge-patch+json'] + swagger: + versions: [3] diff --git a/bookshop-api/config/packages/cache.yaml b/bookshop-api/config/packages/cache.yaml new file mode 100644 index 0000000..6899b72 --- /dev/null +++ b/bookshop-api/config/packages/cache.yaml @@ -0,0 +1,19 @@ +framework: + cache: + # Unique name of your app: used to compute stable namespaces for cache keys. + #prefix_seed: your_vendor_name/app_name + + # The "app" cache stores to the filesystem by default. + # The data in this cache should persist between deploys. + # Other options include: + + # Redis + #app: cache.adapter.redis + #default_redis_provider: redis://localhost + + # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) + #app: cache.adapter.apcu + + # Namespaced pools use the above "app" backend by default + #pools: + #my.dedicated.cache: null diff --git a/bookshop-api/config/packages/doctrine.yaml b/bookshop-api/config/packages/doctrine.yaml new file mode 100644 index 0000000..5e80e77 --- /dev/null +++ b/bookshop-api/config/packages/doctrine.yaml @@ -0,0 +1,18 @@ +doctrine: + dbal: + url: '%env(resolve:DATABASE_URL)%' + + # IMPORTANT: You MUST configure your server version, + # either here or in the DATABASE_URL env var (see .env file) + #server_version: '5.7' + orm: + auto_generate_proxy_classes: true + naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware + auto_mapping: true + mappings: + App: + is_bundle: false + type: annotation + dir: '%kernel.project_dir%/src/Entity' + prefix: 'App\Entity' + alias: App diff --git a/bookshop-api/config/packages/framework.yaml b/bookshop-api/config/packages/framework.yaml new file mode 100644 index 0000000..6089f4b --- /dev/null +++ b/bookshop-api/config/packages/framework.yaml @@ -0,0 +1,16 @@ +framework: + secret: '%env(APP_SECRET)%' + #csrf_protection: true + #http_method_override: true + + # Enables session support. Note that the session will ONLY be started if you read or write from it. + # Remove or comment this section to explicitly disable session support. + session: + handler_id: null + cookie_secure: auto + cookie_samesite: lax + + #esi: true + #fragments: true + php_errors: + log: true diff --git a/bookshop-api/config/packages/nelmio_cors.yaml b/bookshop-api/config/packages/nelmio_cors.yaml new file mode 100644 index 0000000..c766508 --- /dev/null +++ b/bookshop-api/config/packages/nelmio_cors.yaml @@ -0,0 +1,10 @@ +nelmio_cors: + defaults: + origin_regex: true + allow_origin: ['%env(CORS_ALLOW_ORIGIN)%'] + allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE'] + allow_headers: ['Content-Type', 'Authorization'] + expose_headers: ['Link'] + max_age: 3600 + paths: + '^/': null diff --git a/bookshop-api/config/packages/prod/doctrine.yaml b/bookshop-api/config/packages/prod/doctrine.yaml new file mode 100644 index 0000000..084f59a --- /dev/null +++ b/bookshop-api/config/packages/prod/doctrine.yaml @@ -0,0 +1,20 @@ +doctrine: + orm: + auto_generate_proxy_classes: false + metadata_cache_driver: + type: pool + pool: doctrine.system_cache_pool + query_cache_driver: + type: pool + pool: doctrine.system_cache_pool + result_cache_driver: + type: pool + pool: doctrine.result_cache_pool + +framework: + cache: + pools: + doctrine.result_cache_pool: + adapter: cache.app + doctrine.system_cache_pool: + adapter: cache.system diff --git a/bookshop-api/config/packages/prod/routing.yaml b/bookshop-api/config/packages/prod/routing.yaml new file mode 100644 index 0000000..b3e6a0a --- /dev/null +++ b/bookshop-api/config/packages/prod/routing.yaml @@ -0,0 +1,3 @@ +framework: + router: + strict_requirements: null diff --git a/bookshop-api/config/packages/routing.yaml b/bookshop-api/config/packages/routing.yaml new file mode 100644 index 0000000..7e97762 --- /dev/null +++ b/bookshop-api/config/packages/routing.yaml @@ -0,0 +1,3 @@ +framework: + router: + utf8: true diff --git a/bookshop-api/config/packages/security.yaml b/bookshop-api/config/packages/security.yaml new file mode 100644 index 0000000..ce69ba7 --- /dev/null +++ b/bookshop-api/config/packages/security.yaml @@ -0,0 +1,22 @@ +security: + # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers + providers: + in_memory: { memory: null } + firewalls: + dev: + pattern: ^/(_(profiler|wdt)|css|images|js)/ + security: false + main: + anonymous: lazy + + # activate different ways to authenticate + # https://symfony.com/doc/current/security.html#firewalls-authentication + + # https://symfony.com/doc/current/security/impersonating_user.html + # switch_user: true + + # Easy way to control access for large sections of your site + # Note: Only the *first* access control that matches will be used + access_control: + # - { path: ^/admin, roles: ROLE_ADMIN } + # - { path: ^/profile, roles: ROLE_USER } diff --git a/bookshop-api/config/packages/test/framework.yaml b/bookshop-api/config/packages/test/framework.yaml new file mode 100644 index 0000000..d051c84 --- /dev/null +++ b/bookshop-api/config/packages/test/framework.yaml @@ -0,0 +1,4 @@ +framework: + test: true + session: + storage_id: session.storage.mock_file diff --git a/bookshop-api/config/packages/test/twig.yaml b/bookshop-api/config/packages/test/twig.yaml new file mode 100644 index 0000000..8c6e0b4 --- /dev/null +++ b/bookshop-api/config/packages/test/twig.yaml @@ -0,0 +1,2 @@ +twig: + strict_variables: true diff --git a/bookshop-api/config/packages/test/validator.yaml b/bookshop-api/config/packages/test/validator.yaml new file mode 100644 index 0000000..1e5ab78 --- /dev/null +++ b/bookshop-api/config/packages/test/validator.yaml @@ -0,0 +1,3 @@ +framework: + validation: + not_compromised_password: false diff --git a/bookshop-api/config/packages/twig.yaml b/bookshop-api/config/packages/twig.yaml new file mode 100644 index 0000000..b3cdf30 --- /dev/null +++ b/bookshop-api/config/packages/twig.yaml @@ -0,0 +1,2 @@ +twig: + default_path: '%kernel.project_dir%/templates' diff --git a/bookshop-api/config/packages/validator.yaml b/bookshop-api/config/packages/validator.yaml new file mode 100644 index 0000000..350786a --- /dev/null +++ b/bookshop-api/config/packages/validator.yaml @@ -0,0 +1,8 @@ +framework: + validation: + email_validation_mode: html5 + + # Enables validator auto-mapping support. + # For instance, basic validation constraints will be inferred from Doctrine's metadata. + #auto_mapping: + # App\Entity\: [] diff --git a/bookshop-api/config/routes.yaml b/bookshop-api/config/routes.yaml new file mode 100644 index 0000000..c3283aa --- /dev/null +++ b/bookshop-api/config/routes.yaml @@ -0,0 +1,3 @@ +#index: +# path: / +# controller: App\Controller\DefaultController::index diff --git a/bookshop-api/config/routes/annotations.yaml b/bookshop-api/config/routes/annotations.yaml new file mode 100644 index 0000000..d49a502 --- /dev/null +++ b/bookshop-api/config/routes/annotations.yaml @@ -0,0 +1,3 @@ +controllers: + resource: ../../src/Controller/ + type: annotation diff --git a/bookshop-api/config/routes/api_platform.yaml b/bookshop-api/config/routes/api_platform.yaml new file mode 100644 index 0000000..38f11cb --- /dev/null +++ b/bookshop-api/config/routes/api_platform.yaml @@ -0,0 +1,4 @@ +api_platform: + resource: . + type: api_platform + prefix: /api diff --git a/bookshop-api/config/routes/dev/framework.yaml b/bookshop-api/config/routes/dev/framework.yaml new file mode 100644 index 0000000..bcbbf13 --- /dev/null +++ b/bookshop-api/config/routes/dev/framework.yaml @@ -0,0 +1,3 @@ +_errors: + resource: '@FrameworkBundle/Resources/config/routing/errors.xml' + prefix: /_error diff --git a/bookshop-api/config/services.yaml b/bookshop-api/config/services.yaml new file mode 100644 index 0000000..5c4b417 --- /dev/null +++ b/bookshop-api/config/services.yaml @@ -0,0 +1,27 @@ +# This file is the entry point to configure your own services. +# Files in the packages/ subdirectory configure your dependencies. + +# Put parameters here that don't need to change on each machine where the app is deployed +# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration +parameters: + +services: + # default configuration for services in *this* file + _defaults: + autowire: true # Automatically injects dependencies in your services. + autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. + + # makes classes in src/ available to be used as services + # this creates a service per class whose id is the fully-qualified class name + App\: + resource: '../src/*' + exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}' + + # controllers are imported separately to make sure services can be injected + # as action arguments even if you don't extend any base controller class + App\Controller\: + resource: '../src/Controller' + tags: ['controller.service_arguments'] + + # add more service definitions when explicit configuration is needed + # please note that last definitions always *replace* previous ones diff --git a/bookshop-api/public/index.php b/bookshop-api/public/index.php new file mode 100644 index 0000000..f094a9b --- /dev/null +++ b/bookshop-api/public/index.php @@ -0,0 +1,27 @@ +handle($request); +$response->send(); +$kernel->terminate($request, $response); diff --git a/bookshop-api/src/Controller/.gitignore b/bookshop-api/src/Controller/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/bookshop-api/src/Entity/.gitignore b/bookshop-api/src/Entity/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/bookshop-api/src/Kernel.php b/bookshop-api/src/Kernel.php new file mode 100644 index 0000000..1cd0572 --- /dev/null +++ b/bookshop-api/src/Kernel.php @@ -0,0 +1,54 @@ +getProjectDir().'/config/bundles.php'; + foreach ($contents as $class => $envs) { + if ($envs[$this->environment] ?? $envs['all'] ?? false) { + yield new $class(); + } + } + } + + public function getProjectDir(): string + { + return \dirname(__DIR__); + } + + protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void + { + $container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php')); + $container->setParameter('container.dumper.inline_class_loader', \PHP_VERSION_ID < 70400 || $this->debug); + $container->setParameter('container.dumper.inline_factories', true); + $confDir = $this->getProjectDir().'/config'; + + $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob'); + $loader->load($confDir.'/{packages}/'.$this->environment.'/*'.self::CONFIG_EXTS, 'glob'); + $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob'); + $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob'); + } + + protected function configureRoutes(RouteCollectionBuilder $routes): void + { + $confDir = $this->getProjectDir().'/config'; + + $routes->import($confDir.'/{routes}/'.$this->environment.'/*'.self::CONFIG_EXTS, '/', 'glob'); + $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob'); + $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob'); + } +} diff --git a/bookshop-api/src/Repository/.gitignore b/bookshop-api/src/Repository/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/bookshop-api/symfony.lock b/bookshop-api/symfony.lock new file mode 100644 index 0000000..ea8ca1e --- /dev/null +++ b/bookshop-api/symfony.lock @@ -0,0 +1,333 @@ +{ + "api-platform/api-pack": { + "version": "v1.2.1" + }, + "api-platform/core": { + "version": "2.5", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "2.5", + "ref": "a93061567140e386f107be75340ac2aee3f86cbf" + }, + "files": [ + "config/packages/api_platform.yaml", + "config/routes/api_platform.yaml", + "src/Entity/.gitignore" + ] + }, + "doctrine/annotations": { + "version": "1.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "1.0", + "ref": "cb4152ebcadbe620ea2261da1a1c5a9b8cea7672" + }, + "files": [ + "config/routes/annotations.yaml" + ] + }, + "doctrine/cache": { + "version": "1.10.0" + }, + "doctrine/collections": { + "version": "1.6.4" + }, + "doctrine/common": { + "version": "v2.11.0" + }, + "doctrine/dbal": { + "version": "v2.10.0" + }, + "doctrine/doctrine-bundle": { + "version": "2.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "2.0", + "ref": "a9f2463b9f73efe74482f831f03a204a41328555" + }, + "files": [ + "config/packages/doctrine.yaml", + "config/packages/prod/doctrine.yaml", + "src/Entity/.gitignore", + "src/Repository/.gitignore" + ] + }, + "doctrine/event-manager": { + "version": "1.1.0" + }, + "doctrine/inflector": { + "version": "1.3.1" + }, + "doctrine/instantiator": { + "version": "1.3.0" + }, + "doctrine/lexer": { + "version": "1.2.0" + }, + "doctrine/orm": { + "version": "v2.7.0" + }, + "doctrine/persistence": { + "version": "1.3.3" + }, + "doctrine/reflection": { + "version": "v1.0.0" + }, + "fig/link-util": { + "version": "1.1.0" + }, + "jdorn/sql-formatter": { + "version": "v1.2.17" + }, + "nelmio/cors-bundle": { + "version": "1.5", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "1.5", + "ref": "6388de23860284db9acce0a7a5d9d13153bcb571" + }, + "files": [ + "config/packages/nelmio_cors.yaml" + ] + }, + "php": { + "version": "7.3" + }, + "phpdocumentor/reflection-common": { + "version": "2.0.0" + }, + "phpdocumentor/reflection-docblock": { + "version": "4.3.4" + }, + "phpdocumentor/type-resolver": { + "version": "1.0.1" + }, + "psr/cache": { + "version": "1.0.1" + }, + "psr/container": { + "version": "1.0.0" + }, + "psr/event-dispatcher": { + "version": "1.0.0" + }, + "psr/link": { + "version": "1.0.0" + }, + "psr/log": { + "version": "1.1.2" + }, + "symfony/asset": { + "version": "v5.0.2" + }, + "symfony/cache": { + "version": "v5.0.2" + }, + "symfony/cache-contracts": { + "version": "v2.0.1" + }, + "symfony/config": { + "version": "v5.0.2" + }, + "symfony/console": { + "version": "4.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "4.4", + "ref": "fead3ab2e80622c61d13dac0d21a3430a45efae8" + }, + "files": [ + "bin/console", + "config/bootstrap.php" + ] + }, + "symfony/dependency-injection": { + "version": "v5.0.2" + }, + "symfony/doctrine-bridge": { + "version": "v5.0.2" + }, + "symfony/dotenv": { + "version": "v5.0.2" + }, + "symfony/error-handler": { + "version": "v5.0.2" + }, + "symfony/event-dispatcher": { + "version": "v5.0.2" + }, + "symfony/event-dispatcher-contracts": { + "version": "v2.0.1" + }, + "symfony/expression-language": { + "version": "v5.0.2" + }, + "symfony/filesystem": { + "version": "v5.0.2" + }, + "symfony/finder": { + "version": "v5.0.2" + }, + "symfony/flex": { + "version": "1.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "1.0", + "ref": "c0eeb50665f0f77226616b6038a9b06c03752d8e" + }, + "files": [ + ".env" + ] + }, + "symfony/framework-bundle": { + "version": "4.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "4.4", + "ref": "23ecaccc551fe2f74baf613811ae529eb07762fa" + }, + "files": [ + "config/bootstrap.php", + "config/packages/cache.yaml", + "config/packages/framework.yaml", + "config/packages/test/framework.yaml", + "config/routes/dev/framework.yaml", + "config/services.yaml", + "public/index.php", + "src/Controller/.gitignore", + "src/Kernel.php" + ] + }, + "symfony/http-foundation": { + "version": "v5.0.2" + }, + "symfony/http-kernel": { + "version": "v5.0.2" + }, + "symfony/inflector": { + "version": "v5.0.2" + }, + "symfony/mime": { + "version": "v5.0.2" + }, + "symfony/polyfill-intl-idn": { + "version": "v1.13.1" + }, + "symfony/polyfill-mbstring": { + "version": "v1.13.1" + }, + "symfony/polyfill-php73": { + "version": "v1.13.1" + }, + "symfony/property-access": { + "version": "v5.0.2" + }, + "symfony/property-info": { + "version": "v5.0.2" + }, + "symfony/routing": { + "version": "4.2", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "4.2", + "ref": "683dcb08707ba8d41b7e34adb0344bfd68d248a7" + }, + "files": [ + "config/packages/prod/routing.yaml", + "config/packages/routing.yaml", + "config/routes.yaml" + ] + }, + "symfony/security-bundle": { + "version": "4.4", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "4.4", + "ref": "30efd98dd3b4ead6e9ad4713b1efc43bbe94bf77" + }, + "files": [ + "config/packages/security.yaml" + ] + }, + "symfony/security-core": { + "version": "v5.0.2" + }, + "symfony/security-csrf": { + "version": "v5.0.2" + }, + "symfony/security-guard": { + "version": "v5.0.2" + }, + "symfony/security-http": { + "version": "v5.0.2" + }, + "symfony/serializer": { + "version": "v5.0.2" + }, + "symfony/service-contracts": { + "version": "v2.0.1" + }, + "symfony/translation-contracts": { + "version": "v2.0.1" + }, + "symfony/twig-bridge": { + "version": "v5.0.2" + }, + "symfony/twig-bundle": { + "version": "5.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "5.0", + "ref": "fab9149bbaa4d5eca054ed93f9e1b66cc500895d" + }, + "files": [ + "config/packages/test/twig.yaml", + "config/packages/twig.yaml", + "templates/base.html.twig" + ] + }, + "symfony/validator": { + "version": "4.3", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "master", + "version": "4.3", + "ref": "d902da3e4952f18d3bf05aab29512eb61cabd869" + }, + "files": [ + "config/packages/test/validator.yaml", + "config/packages/validator.yaml" + ] + }, + "symfony/var-dumper": { + "version": "v5.0.2" + }, + "symfony/var-exporter": { + "version": "v5.0.2" + }, + "symfony/web-link": { + "version": "v5.0.2" + }, + "symfony/yaml": { + "version": "v5.0.2" + }, + "twig/twig": { + "version": "v3.0.1" + }, + "webmozart/assert": { + "version": "1.6.0" + }, + "willdurand/negotiation": { + "version": "v2.3.1" + } +} diff --git a/bookshop-api/templates/base.html.twig b/bookshop-api/templates/base.html.twig new file mode 100644 index 0000000..043f42d --- /dev/null +++ b/bookshop-api/templates/base.html.twig @@ -0,0 +1,12 @@ + + + + + {% block title %}Welcome!{% endblock %} + {% block stylesheets %}{% endblock %} + + + {% block body %}{% endblock %} + {% block javascripts %}{% endblock %} + + diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..f8213d9 --- /dev/null +++ b/composer.json @@ -0,0 +1,5 @@ +{ + "require-dev": { + "doctrine/doctrine-fixtures-bundle": "^3.3" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..b69d535 --- /dev/null +++ b/composer.lock @@ -0,0 +1,3006 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "13971765af52af53145bacae66ee934b", + "packages": [], + "packages-dev": [ + { + "name": "doctrine/annotations", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/904dca4eb10715b92569fbcd79e201d5c349b6bc", + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "^7.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2019-10-01T18:55:10+00:00" + }, + { + "name": "doctrine/cache", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "382e7f4db9a12dc6c19431743a2b096041bcdd62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/382e7f4db9a12dc6c19431743a2b096041bcdd62", + "reference": "382e7f4db9a12dc6c19431743a2b096041bcdd62", + "shasum": "" + }, + "require": { + "php": "~7.1" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^6.0", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^7.0", + "predis/predis": "~1.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", + "homepage": "https://www.doctrine-project.org/projects/cache.html", + "keywords": [ + "abstraction", + "apcu", + "cache", + "caching", + "couchdb", + "memcached", + "php", + "redis", + "xcache" + ], + "time": "2019-11-29T15:36:20+00:00" + }, + { + "name": "doctrine/collections", + "version": "1.6.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7", + "reference": "6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan-shim": "^0.9.2", + "phpunit/phpunit": "^7.0", + "vimeo/psalm": "^3.2.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", + "homepage": "https://www.doctrine-project.org/projects/collections.html", + "keywords": [ + "array", + "collections", + "iterators", + "php" + ], + "time": "2019-11-13T13:07:11+00:00" + }, + { + "name": "doctrine/common", + "version": "v2.11.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/common.git", + "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/common/zipball/b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", + "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/inflector": "^1.0", + "doctrine/lexer": "^1.0", + "doctrine/persistence": "^1.1", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^1.0", + "phpstan/phpstan": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0", + "symfony/phpunit-bridge": "^4.0.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.11.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, persistence interfaces, proxies, event system and much more.", + "homepage": "https://www.doctrine-project.org/projects/common.html", + "keywords": [ + "common", + "doctrine", + "php" + ], + "time": "2019-09-10T10:10:14+00:00" + }, + { + "name": "doctrine/data-fixtures", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/data-fixtures.git", + "reference": "608a35a3b5bcc4214d116603095f8b0c51091592" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/608a35a3b5bcc4214d116603095f8b0c51091592", + "reference": "608a35a3b5bcc4214d116603095f8b0c51091592", + "shasum": "" + }, + "require": { + "doctrine/common": "^2.11", + "php": "^7.2" + }, + "conflict": { + "doctrine/phpcr-odm": "<1.3.0" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^6.0", + "doctrine/dbal": "^2.5.4", + "doctrine/mongodb-odm": "^1.3.0", + "doctrine/orm": "^2.5.4", + "phpunit/phpunit": "^7.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "For using MongoDB ODM with PHP 7", + "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", + "doctrine/orm": "For loading ORM fixtures", + "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\DataFixtures\\": "lib/Doctrine/Common/DataFixtures" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Data Fixtures for all Doctrine Object Managers", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database" + ], + "time": "2019-10-30T20:03:18+00:00" + }, + { + "name": "doctrine/dbal", + "version": "v2.10.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/0c9a646775ef549eb0a213a4f9bd4381d9b4d934", + "reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934", + "shasum": "" + }, + "require": { + "doctrine/cache": "^1.0", + "doctrine/event-manager": "^1.0", + "ext-pdo": "*", + "php": "^7.2" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "jetbrains/phpstorm-stubs": "^2019.1", + "phpstan/phpstan": "^0.11.3", + "phpunit/phpunit": "^8.4.1", + "symfony/console": "^2.0.5|^3.0|^4.0|^5.0" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "bin": [ + "bin/doctrine-dbal" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.10.x-dev", + "dev-develop": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\DBAL\\": "lib/Doctrine/DBAL" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", + "keywords": [ + "abstraction", + "database", + "db2", + "dbal", + "mariadb", + "mssql", + "mysql", + "oci8", + "oracle", + "pdo", + "pgsql", + "postgresql", + "queryobject", + "sasql", + "sql", + "sqlanywhere", + "sqlite", + "sqlserver", + "sqlsrv" + ], + "time": "2019-11-03T16:50:43+00:00" + }, + { + "name": "doctrine/doctrine-bundle", + "version": "2.0.6", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineBundle.git", + "reference": "0ef972d3b730f975c80db9fffa4b2a0258c91442" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/0ef972d3b730f975c80db9fffa4b2a0258c91442", + "reference": "0ef972d3b730f975c80db9fffa4b2a0258c91442", + "shasum": "" + }, + "require": { + "doctrine/dbal": "^2.9.0", + "doctrine/persistence": "^1.3.3", + "jdorn/sql-formatter": "^1.2.16", + "php": "^7.1", + "symfony/cache": "^4.3.3|^5.0", + "symfony/config": "^4.3.3|^5.0", + "symfony/console": "^3.4.30|^4.3.3|^5.0", + "symfony/dependency-injection": "^4.3.3|^5.0", + "symfony/doctrine-bridge": "^4.3.7|^5.0", + "symfony/framework-bundle": "^3.4.30|^4.3.3|^5.0", + "symfony/service-contracts": "^1.1.1|^2.0" + }, + "conflict": { + "doctrine/orm": "<2.6", + "twig/twig": "<1.34|>=2.0,<2.4" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "doctrine/orm": "^2.6", + "ocramius/proxy-manager": "^2.1", + "phpunit/phpunit": "^7.5", + "symfony/phpunit-bridge": "^4.2", + "symfony/property-info": "^4.3.3|^5.0", + "symfony/twig-bridge": "^3.4.30|^4.3.3|^5.0", + "symfony/validator": "^3.4.30|^4.3.3|^5.0", + "symfony/web-profiler-bundle": "^3.4.30|^4.3.3|^5.0", + "symfony/yaml": "^3.4.30|^4.3.3|^5.0", + "twig/twig": "^1.34|^2.12" + }, + "suggest": { + "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", + "symfony/web-profiler-bundle": "To use the data collector." + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\DoctrineBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Doctrine Project", + "homepage": "http://www.doctrine-project.org/" + } + ], + "description": "Symfony DoctrineBundle", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "dbal", + "orm", + "persistence" + ], + "time": "2019-12-19T13:47:07+00:00" + }, + { + "name": "doctrine/doctrine-fixtures-bundle", + "version": "3.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineFixturesBundle.git", + "reference": "8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70", + "reference": "8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70", + "shasum": "" + }, + "require": { + "doctrine/data-fixtures": "^1.3", + "doctrine/doctrine-bundle": "^1.11|^2.0", + "doctrine/orm": "^2.6.0", + "php": "^7.1", + "symfony/config": "^3.4|^4.3|^5.0", + "symfony/console": "^3.4|^4.3|^5.0", + "symfony/dependency-injection": "^3.4|^4.3|^5.0", + "symfony/doctrine-bridge": "^3.4|^4.1|^5.0", + "symfony/http-kernel": "^3.4|^4.3|^5.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.4", + "symfony/phpunit-bridge": "^4.1|^5.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "3.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\FixturesBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Doctrine Project", + "homepage": "http://www.doctrine-project.org" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony DoctrineFixturesBundle", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "Fixture", + "persistence" + ], + "time": "2019-11-13T15:46:58+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "629572819973f13486371cb611386eb17851e85c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/629572819973f13486371cb611386eb17851e85c", + "reference": "629572819973f13486371cb611386eb17851e85c", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "event dispatcher", + "event manager", + "event system", + "events" + ], + "time": "2019-11-10T09:48:07+00:00" + }, + { + "name": "doctrine/inflector", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2019-10-30T19:59:35+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2019-10-21T16:45:58+00:00" + }, + { + "name": "doctrine/lexer", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "shasum": "" + }, + "require": { + "php": "^7.2" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "time": "2019-10-30T14:39:59+00:00" + }, + { + "name": "doctrine/orm", + "version": "v2.7.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/orm.git", + "reference": "4d763ca4c925f647b248b9fa01b5f47aa3685d62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/orm/zipball/4d763ca4c925f647b248b9fa01b5f47aa3685d62", + "reference": "4d763ca4c925f647b248b9fa01b5f47aa3685d62", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.8", + "doctrine/cache": "^1.9.1", + "doctrine/collections": "^1.5", + "doctrine/common": "^2.11", + "doctrine/dbal": "^2.9.3", + "doctrine/event-manager": "^1.1", + "doctrine/instantiator": "^1.3", + "doctrine/persistence": "^1.2", + "ext-pdo": "*", + "php": "^7.1", + "symfony/console": "^3.0|^4.0|^5.0" + }, + "require-dev": { + "doctrine/coding-standard": "^5.0", + "phpunit/phpunit": "^7.5", + "symfony/yaml": "^3.4|^4.0|^5.0" + }, + "suggest": { + "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" + }, + "bin": [ + "bin/doctrine" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\ORM\\": "lib/Doctrine/ORM" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Object-Relational-Mapper for PHP", + "homepage": "https://www.doctrine-project.org/projects/orm.html", + "keywords": [ + "database", + "orm" + ], + "time": "2019-11-19T08:38:05+00:00" + }, + { + "name": "doctrine/persistence", + "version": "1.3.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/persistence.git", + "reference": "99b196bbd4715a94fa100fac664a351ffa46d6a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/99b196bbd4715a94fa100fac664a351ffa46d6a5", + "reference": "99b196bbd4715a94fa100fac664a351ffa46d6a5", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.10@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common", + "Doctrine\\Persistence\\": "lib/Doctrine/Persistence" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", + "homepage": "https://doctrine-project.org/projects/persistence.html", + "keywords": [ + "mapper", + "object", + "odm", + "orm", + "persistence" + ], + "time": "2019-12-13T10:43:02+00:00" + }, + { + "name": "doctrine/reflection", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/reflection.git", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/reflection/zipball/02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "doctrine/common": "^2.8", + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Reflection component", + "homepage": "https://www.doctrine-project.org/projects/reflection.html", + "keywords": [ + "reflection" + ], + "time": "2018-06-14T14:45:07+00:00" + }, + { + "name": "jdorn/sql-formatter", + "version": "v1.2.17", + "source": { + "type": "git", + "url": "https://github.com/jdorn/sql-formatter.git", + "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jdorn/sql-formatter/zipball/64990d96e0959dff8e059dfcdc1af130728d92bc", + "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "lib" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeremy Dorn", + "email": "jeremy@jeremydorn.com", + "homepage": "http://jeremydorn.com/" + } + ], + "description": "a PHP SQL highlighting library", + "homepage": "https://github.com/jdorn/sql-formatter/", + "keywords": [ + "highlight", + "sql" + ], + "time": "2014-01-12T16:20:24+00:00" + }, + { + "name": "psr/cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "time": "2016-08-06T20:24:11+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2019-11-01T11:05:21+00:00" + }, + { + "name": "symfony/cache", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "6e8d978878ae5de705ec9fabbb6011cc18776bc9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/6e8d978878ae5de705ec9fabbb6011cc18776bc9", + "reference": "6e8d978878ae5de705ec9fabbb6011cc18776bc9", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/cache": "~1.0", + "psr/log": "~1.0", + "symfony/cache-contracts": "^1.1.7|^2", + "symfony/service-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0" + }, + "conflict": { + "doctrine/dbal": "<2.5", + "symfony/dependency-injection": "<4.4", + "symfony/http-kernel": "<4.4", + "symfony/var-dumper": "<4.4" + }, + "provide": { + "psr/cache-implementation": "1.0", + "psr/simple-cache-implementation": "1.0", + "symfony/cache-implementation": "1.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/cache": "~1.6", + "doctrine/dbal": "~2.5", + "predis/predis": "~1.1", + "psr/simple-cache": "^1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Cache component with PSR-6, PSR-16, and tags", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ], + "time": "2019-12-12T13:03:32+00:00" + }, + { + "name": "symfony/cache-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16", + "reference": "23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/cache": "^1.0" + }, + "suggest": { + "symfony/cache-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Cache\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to caching", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/config", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "7f930484966350906185ba0a604728f7898b7ba0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/7f930484966350906185ba0a604728f7898b7ba0", + "reference": "7f930484966350906185ba0a604728f7898b7ba0", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/filesystem": "^4.4|^5.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/finder": "<4.4" + }, + "require-dev": { + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2019-12-18T13:50:31+00:00" + }, + { + "name": "symfony/console", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "fe6e3cd889ca64172d7a742a2eb058541404ef47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/fe6e3cd889ca64172d7a742a2eb058541404ef47", + "reference": "fe6e3cd889ca64172d7a742a2eb058541404ef47", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "symfony/dependency-injection": "<4.4", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2019-12-17T13:20:22+00:00" + }, + { + "name": "symfony/dependency-injection", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "f9dbfbf487d08f60b1c83220edcd16559d1e40a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f9dbfbf487d08f60b1c83220edcd16559d1e40a2", + "reference": "f9dbfbf487d08f60b1c83220edcd16559d1e40a2", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/container": "^1.0", + "symfony/service-contracts": "^1.1.6|^2" + }, + "conflict": { + "symfony/config": "<5.0", + "symfony/finder": "<4.4", + "symfony/proxy-manager-bridge": "<4.4", + "symfony/yaml": "<4.4" + }, + "provide": { + "psr/container-implementation": "1.0", + "symfony/service-implementation": "1.0" + }, + "require-dev": { + "symfony/config": "^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "https://symfony.com", + "time": "2019-12-19T16:01:11+00:00" + }, + { + "name": "symfony/doctrine-bridge", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/doctrine-bridge.git", + "reference": "0bdb2d31741cacacb95130d28fbac939c4d574f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/0bdb2d31741cacacb95130d28fbac939c4d574f2", + "reference": "0bdb2d31741cacacb95130d28fbac939c4d574f2", + "shasum": "" + }, + "require": { + "doctrine/event-manager": "~1.0", + "doctrine/persistence": "^1.3", + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/dependency-injection": "<4.4", + "symfony/form": "<5", + "symfony/http-kernel": "<5", + "symfony/messenger": "<4.4", + "symfony/property-info": "<5", + "symfony/security-bundle": "<5", + "symfony/security-core": "<5", + "symfony/validator": "<5.0.2" + }, + "require-dev": { + "doctrine/annotations": "~1.7", + "doctrine/cache": "~1.6", + "doctrine/collections": "~1.0", + "doctrine/data-fixtures": "1.0.*", + "doctrine/dbal": "~2.4", + "doctrine/orm": "^2.6.3", + "doctrine/reflection": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/form": "^5.0", + "symfony/http-kernel": "^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/property-access": "^4.4|^5.0", + "symfony/property-info": "^5.0", + "symfony/proxy-manager-bridge": "^4.4|^5.0", + "symfony/security-core": "^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/validator": "^5.0.2", + "symfony/var-dumper": "^4.4|^5.0" + }, + "suggest": { + "doctrine/data-fixtures": "", + "doctrine/dbal": "", + "doctrine/orm": "", + "symfony/form": "", + "symfony/property-info": "", + "symfony/validator": "" + }, + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Doctrine\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Doctrine Bridge", + "homepage": "https://symfony.com", + "time": "2019-12-19T12:10:29+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "460863313bd3212d7c38e1b40602cbcfeeeea4a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/460863313bd3212d7c38e1b40602cbcfeeeea4a5", + "reference": "460863313bd3212d7c38e1b40602cbcfeeeea4a5", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/log": "^1.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "require-dev": { + "symfony/http-kernel": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony ErrorHandler Component", + "homepage": "https://symfony.com", + "time": "2019-12-16T14:48:47+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "7b738a51645e10f864cc25c24d232fb03f37b475" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7b738a51645e10f864cc25c24d232fb03f37b475", + "reference": "7b738a51645e10f864cc25c24d232fb03f37b475", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/event-dispatcher-contracts": "^2" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/stopwatch": "^4.4|^5.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "af23c2584d4577d54661c434446fb8fbed6025dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/af23c2584d4577d54661c434446fb8fbed6025dd", + "reference": "af23c2584d4577d54661c434446fb8fbed6025dd", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "1d71f670bc5a07b9ccc97dc44f932177a322d4e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/1d71f670bc5a07b9ccc97dc44f932177a322d4e6", + "reference": "1d71f670bc5a07b9ccc97dc44f932177a322d4e6", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2019-11-26T23:25:11+00:00" + }, + { + "name": "symfony/finder", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "17874dd8ab9a19422028ad56172fb294287a701b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/17874dd8ab9a19422028ad56172fb294287a701b", + "reference": "17874dd8ab9a19422028ad56172fb294287a701b", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/framework-bundle", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/framework-bundle.git", + "reference": "36e51776b231d8e224da4ce4c60079540acd1c55" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/36e51776b231d8e224da4ce4c60079540acd1c55", + "reference": "36e51776b231d8e224da4ce4c60079540acd1c55", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": "^7.2.5", + "symfony/cache": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/dependency-injection": "^5.0.1", + "symfony/error-handler": "^4.4.1|^5.0.1", + "symfony/filesystem": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-kernel": "^5.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/routing": "^5.0" + }, + "conflict": { + "doctrine/persistence": "<1.3", + "phpdocumentor/reflection-docblock": "<3.0", + "phpdocumentor/type-resolver": "<0.2.1", + "phpunit/phpunit": "<5.4.3", + "symfony/asset": "<4.4", + "symfony/browser-kit": "<4.4", + "symfony/console": "<4.4", + "symfony/dom-crawler": "<4.4", + "symfony/dotenv": "<4.4", + "symfony/form": "<4.4", + "symfony/http-client": "<4.4", + "symfony/lock": "<4.4", + "symfony/mailer": "<4.4", + "symfony/messenger": "<4.4", + "symfony/mime": "<4.4", + "symfony/property-info": "<4.4", + "symfony/serializer": "<4.4", + "symfony/stopwatch": "<4.4", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<4.4", + "symfony/twig-bundle": "<4.4", + "symfony/validator": "<4.4", + "symfony/web-profiler-bundle": "<4.4", + "symfony/workflow": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "~1.7", + "doctrine/cache": "~1.0", + "paragonie/sodium_compat": "^1.8", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", + "symfony/asset": "^4.4|^5.0", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/dotenv": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/form": "^4.4|^5.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/mailer": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/process": "^4.4|^5.0", + "symfony/property-info": "^4.4|^5.0", + "symfony/security-csrf": "^4.4|^5.0", + "symfony/security-http": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/string": "~5.0.0", + "symfony/translation": "^5.0", + "symfony/twig-bundle": "^4.4|^5.0", + "symfony/validator": "^4.4|^5.0", + "symfony/web-link": "^4.4|^5.0", + "symfony/workflow": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0", + "twig/twig": "^2.10|^3.0" + }, + "suggest": { + "ext-apcu": "For best performance of the system caches", + "symfony/console": "For using the console commands", + "symfony/form": "For using forms", + "symfony/property-info": "For using the property_info service", + "symfony/serializer": "For using the serializer service", + "symfony/validator": "For using validation", + "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering", + "symfony/yaml": "For using the debug:config and lint:yaml commands" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\FrameworkBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony FrameworkBundle", + "homepage": "https://symfony.com", + "time": "2019-12-17T10:33:13+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "5dd7f6be6e62d86ba6f3154cf40e78936367978b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5dd7f6be6e62d86ba6f3154cf40e78936367978b", + "reference": "5dd7f6be6e62d86ba6f3154cf40e78936367978b", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/mime": "^4.4|^5.0", + "symfony/polyfill-mbstring": "~1.1" + }, + "require-dev": { + "predis/predis": "~1.0", + "symfony/expression-language": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2019-12-19T16:01:11+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "00ce30602f3f690e66a63c327743d7b26c723b2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/00ce30602f3f690e66a63c327743d7b26c723b2e", + "reference": "00ce30602f3f690e66a63c327743d7b26c723b2e", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/log": "~1.0", + "symfony/error-handler": "^4.4|^5.0", + "symfony/event-dispatcher": "^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php73": "^1.9" + }, + "conflict": { + "symfony/browser-kit": "<4.4", + "symfony/cache": "<5.0", + "symfony/config": "<5.0", + "symfony/dependency-injection": "<4.4", + "symfony/doctrine-bridge": "<5.0", + "symfony/form": "<5.0", + "symfony/http-client": "<5.0", + "symfony/mailer": "<5.0", + "symfony/messenger": "<5.0", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<5.0", + "symfony/validator": "<5.0", + "twig/twig": "<2.4" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/cache": "~1.0", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/routing": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "twig/twig": "^2.4|^3.0" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com", + "time": "2019-12-19T18:35:03+00:00" + }, + { + "name": "symfony/mime", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "0e6a4ced216e49d457eddcefb61132173a876d79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/0e6a4ced216e49d457eddcefb61132173a876d79", + "reference": "0e6a4ced216e49d457eddcefb61132173a876d79", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "symfony/mailer": "<4.4" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10", + "symfony/dependency-injection": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A library to manipulate MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "time": "2019-11-30T14:12:50+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.13.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", + "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-11-27T13:56:44+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.13.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6f9c239e61e1b0c9229a28ff89a812dc449c3d46", + "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.9" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "time": "2019-11-27T13:56:44+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.13.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f", + "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2019-11-27T14:18:11+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.13.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "66fea50f6cb37a35eea048d75a7d99a45b586038" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/66fea50f6cb37a35eea048d75a7d99a45b586038", + "reference": "66fea50f6cb37a35eea048d75a7d99a45b586038", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2019-11-27T13:56:44+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.13.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/4b0e2222c55a25b4541305a053013d5647d3a25f", + "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2019-11-27T16:25:15+00:00" + }, + { + "name": "symfony/routing", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "120c5fa4f4ef5466cbb510ece8126e0007285301" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/120c5fa4f4ef5466cbb510ece8126e0007285301", + "reference": "120c5fa4f4ef5466cbb510ece8126e0007285301", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "conflict": { + "symfony/config": "<5.0", + "symfony/dependency-injection": "<4.4", + "symfony/yaml": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "~1.2", + "psr/log": "~1.0", + "symfony/config": "^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Routing Component", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "time": "2019-12-12T13:03:32+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "144c5e51266b281231e947b51223ba14acf1a749" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", + "reference": "144c5e51266b281231e947b51223ba14acf1a749", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/container": "^1.0" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a", + "reference": "d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<4.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "twig/twig": "^2.4|^3.0" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2019-12-18T13:50:31+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v5.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "1b9653e68d5b701bf6d9c91bdd3660078c9f4f28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1b9653e68d5b701bf6d9c91bdd3660078c9f4f28", + "reference": "1b9653e68d5b701bf6d9c91bdd3660078c9f4f28", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "require-dev": { + "symfony/var-dumper": "^4.4|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A blend of var_export() + serialize() to turn any serializable data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "serialize" + ], + "time": "2019-12-01T08:48:26+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/vendor/autoload.php b/vendor/autoload.php new file mode 100644 index 0000000..21cc90a --- /dev/null +++ b/vendor/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + private $classMapAuthoritative = false; + private $missingClasses = array(); + private $apcuPrefix; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..0976ce8 --- /dev/null +++ b/vendor/composer/autoload_classmap.php @@ -0,0 +1,11 @@ + $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', + 'SqlFormatter' => $vendorDir . '/jdorn/sql-formatter/lib/SqlFormatter.php', +); diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php new file mode 100644 index 0000000..6fef1ad --- /dev/null +++ b/vendor/composer/autoload_files.php @@ -0,0 +1,15 @@ + $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', + '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', + '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php', + 'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php', + '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', + '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php', +); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..b7fc012 --- /dev/null +++ b/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ + array($vendorDir . '/symfony/polyfill-php73'), + 'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'), + 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), + 'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'), + 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), + 'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'), + 'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'), + 'Symfony\\Contracts\\Cache\\' => array($vendorDir . '/symfony/cache-contracts'), + 'Symfony\\Component\\VarExporter\\' => array($vendorDir . '/symfony/var-exporter'), + 'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'), + 'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'), + 'Symfony\\Component\\Mime\\' => array($vendorDir . '/symfony/mime'), + 'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'), + 'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'), + 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), + 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'), + 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'), + 'Symfony\\Component\\ErrorHandler\\' => array($vendorDir . '/symfony/error-handler'), + 'Symfony\\Component\\DependencyInjection\\' => array($vendorDir . '/symfony/dependency-injection'), + 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), + 'Symfony\\Component\\Config\\' => array($vendorDir . '/symfony/config'), + 'Symfony\\Component\\Cache\\' => array($vendorDir . '/symfony/cache'), + 'Symfony\\Bundle\\FrameworkBundle\\' => array($vendorDir . '/symfony/framework-bundle'), + 'Symfony\\Bridge\\Doctrine\\' => array($vendorDir . '/symfony/doctrine-bridge'), + 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), + 'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'), + 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), + 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), + 'Doctrine\\Persistence\\' => array($vendorDir . '/doctrine/persistence/lib/Doctrine/Persistence'), + 'Doctrine\\ORM\\' => array($vendorDir . '/doctrine/orm/lib/Doctrine/ORM'), + 'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'), + 'Doctrine\\DBAL\\' => array($vendorDir . '/doctrine/dbal/lib/Doctrine/DBAL'), + 'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib/Doctrine/Common/Lexer'), + 'Doctrine\\Common\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Common/Inflector'), + 'Doctrine\\Common\\DataFixtures\\' => array($vendorDir . '/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures'), + 'Doctrine\\Common\\Collections\\' => array($vendorDir . '/doctrine/collections/lib/Doctrine/Common/Collections'), + 'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache'), + 'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations'), + 'Doctrine\\Common\\' => array($vendorDir . '/doctrine/common/lib/Doctrine/Common', $vendorDir . '/doctrine/event-manager/lib/Doctrine/Common', $vendorDir . '/doctrine/persistence/lib/Doctrine/Common', $vendorDir . '/doctrine/reflection/lib/Doctrine/Common'), + 'Doctrine\\Bundle\\FixturesBundle\\' => array($vendorDir . '/doctrine/doctrine-fixtures-bundle'), + 'Doctrine\\Bundle\\DoctrineBundle\\' => array($vendorDir . '/doctrine/doctrine-bundle'), +); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php new file mode 100644 index 0000000..de8583e --- /dev/null +++ b/vendor/composer/autoload_real.php @@ -0,0 +1,70 @@ += 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require_once __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInitd4f03afe1ff6c3294ecfb4f66aeebb22::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + if ($useStaticLoader) { + $includeFiles = Composer\Autoload\ComposerStaticInitd4f03afe1ff6c3294ecfb4f66aeebb22::$files; + } else { + $includeFiles = require __DIR__ . '/autoload_files.php'; + } + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequired4f03afe1ff6c3294ecfb4f66aeebb22($fileIdentifier, $file); + } + + return $loader; + } +} + +function composerRequired4f03afe1ff6c3294ecfb4f66aeebb22($fileIdentifier, $file) +{ + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + require $file; + + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + } +} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php new file mode 100644 index 0000000..2763690 --- /dev/null +++ b/vendor/composer/autoload_static.php @@ -0,0 +1,255 @@ + __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', + '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', + '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php', + 'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php', + '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', + '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php', + ); + + public static $prefixLengthsPsr4 = array ( + 'S' => + array ( + 'Symfony\\Polyfill\\Php73\\' => 23, + 'Symfony\\Polyfill\\Php72\\' => 23, + 'Symfony\\Polyfill\\Mbstring\\' => 26, + 'Symfony\\Polyfill\\Intl\\Idn\\' => 26, + 'Symfony\\Polyfill\\Ctype\\' => 23, + 'Symfony\\Contracts\\Service\\' => 26, + 'Symfony\\Contracts\\EventDispatcher\\' => 34, + 'Symfony\\Contracts\\Cache\\' => 24, + 'Symfony\\Component\\VarExporter\\' => 30, + 'Symfony\\Component\\VarDumper\\' => 28, + 'Symfony\\Component\\Routing\\' => 26, + 'Symfony\\Component\\Mime\\' => 23, + 'Symfony\\Component\\HttpKernel\\' => 29, + 'Symfony\\Component\\HttpFoundation\\' => 33, + 'Symfony\\Component\\Finder\\' => 25, + 'Symfony\\Component\\Filesystem\\' => 29, + 'Symfony\\Component\\EventDispatcher\\' => 34, + 'Symfony\\Component\\ErrorHandler\\' => 31, + 'Symfony\\Component\\DependencyInjection\\' => 38, + 'Symfony\\Component\\Console\\' => 26, + 'Symfony\\Component\\Config\\' => 25, + 'Symfony\\Component\\Cache\\' => 24, + 'Symfony\\Bundle\\FrameworkBundle\\' => 31, + 'Symfony\\Bridge\\Doctrine\\' => 24, + ), + 'P' => + array ( + 'Psr\\Log\\' => 8, + 'Psr\\EventDispatcher\\' => 20, + 'Psr\\Container\\' => 14, + 'Psr\\Cache\\' => 10, + ), + 'D' => + array ( + 'Doctrine\\Persistence\\' => 21, + 'Doctrine\\ORM\\' => 13, + 'Doctrine\\Instantiator\\' => 22, + 'Doctrine\\DBAL\\' => 14, + 'Doctrine\\Common\\Lexer\\' => 22, + 'Doctrine\\Common\\Inflector\\' => 26, + 'Doctrine\\Common\\DataFixtures\\' => 29, + 'Doctrine\\Common\\Collections\\' => 28, + 'Doctrine\\Common\\Cache\\' => 22, + 'Doctrine\\Common\\Annotations\\' => 28, + 'Doctrine\\Common\\' => 16, + 'Doctrine\\Bundle\\FixturesBundle\\' => 31, + 'Doctrine\\Bundle\\DoctrineBundle\\' => 31, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'Symfony\\Polyfill\\Php73\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php73', + ), + 'Symfony\\Polyfill\\Php72\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php72', + ), + 'Symfony\\Polyfill\\Mbstring\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', + ), + 'Symfony\\Polyfill\\Intl\\Idn\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn', + ), + 'Symfony\\Polyfill\\Ctype\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', + ), + 'Symfony\\Contracts\\Service\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/service-contracts', + ), + 'Symfony\\Contracts\\EventDispatcher\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts', + ), + 'Symfony\\Contracts\\Cache\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/cache-contracts', + ), + 'Symfony\\Component\\VarExporter\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/var-exporter', + ), + 'Symfony\\Component\\VarDumper\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/var-dumper', + ), + 'Symfony\\Component\\Routing\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/routing', + ), + 'Symfony\\Component\\Mime\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/mime', + ), + 'Symfony\\Component\\HttpKernel\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/http-kernel', + ), + 'Symfony\\Component\\HttpFoundation\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/http-foundation', + ), + 'Symfony\\Component\\Finder\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/finder', + ), + 'Symfony\\Component\\Filesystem\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/filesystem', + ), + 'Symfony\\Component\\EventDispatcher\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/event-dispatcher', + ), + 'Symfony\\Component\\ErrorHandler\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/error-handler', + ), + 'Symfony\\Component\\DependencyInjection\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/dependency-injection', + ), + 'Symfony\\Component\\Console\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/console', + ), + 'Symfony\\Component\\Config\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/config', + ), + 'Symfony\\Component\\Cache\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/cache', + ), + 'Symfony\\Bundle\\FrameworkBundle\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/framework-bundle', + ), + 'Symfony\\Bridge\\Doctrine\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/doctrine-bridge', + ), + 'Psr\\Log\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/log/Psr/Log', + ), + 'Psr\\EventDispatcher\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/event-dispatcher/src', + ), + 'Psr\\Container\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/container/src', + ), + 'Psr\\Cache\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/cache/src', + ), + 'Doctrine\\Persistence\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/persistence/lib/Doctrine/Persistence', + ), + 'Doctrine\\ORM\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/orm/lib/Doctrine/ORM', + ), + 'Doctrine\\Instantiator\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/instantiator/src/Doctrine/Instantiator', + ), + 'Doctrine\\DBAL\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/dbal/lib/Doctrine/DBAL', + ), + 'Doctrine\\Common\\Lexer\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/lexer/lib/Doctrine/Common/Lexer', + ), + 'Doctrine\\Common\\Inflector\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/inflector/lib/Doctrine/Common/Inflector', + ), + 'Doctrine\\Common\\DataFixtures\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures', + ), + 'Doctrine\\Common\\Collections\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/collections/lib/Doctrine/Common/Collections', + ), + 'Doctrine\\Common\\Cache\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache', + ), + 'Doctrine\\Common\\Annotations\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations', + ), + 'Doctrine\\Common\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/common/lib/Doctrine/Common', + 1 => __DIR__ . '/..' . '/doctrine/event-manager/lib/Doctrine/Common', + 2 => __DIR__ . '/..' . '/doctrine/persistence/lib/Doctrine/Common', + 3 => __DIR__ . '/..' . '/doctrine/reflection/lib/Doctrine/Common', + ), + 'Doctrine\\Bundle\\FixturesBundle\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/doctrine-fixtures-bundle', + ), + 'Doctrine\\Bundle\\DoctrineBundle\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/doctrine-bundle', + ), + ); + + public static $classMap = array ( + 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', + 'SqlFormatter' => __DIR__ . '/..' . '/jdorn/sql-formatter/lib/SqlFormatter.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInitd4f03afe1ff6c3294ecfb4f66aeebb22::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInitd4f03afe1ff6c3294ecfb4f66aeebb22::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInitd4f03afe1ff6c3294ecfb4f66aeebb22::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json new file mode 100644 index 0000000..78a7c4b --- /dev/null +++ b/vendor/composer/installed.json @@ -0,0 +1,3078 @@ +[ + { + "name": "doctrine/annotations", + "version": "v1.8.0", + "version_normalized": "1.8.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/904dca4eb10715b92569fbcd79e201d5c349b6bc", + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "^7.5" + }, + "time": "2019-10-01T18:55:10+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ] + }, + { + "name": "doctrine/cache", + "version": "1.10.0", + "version_normalized": "1.10.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "382e7f4db9a12dc6c19431743a2b096041bcdd62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/382e7f4db9a12dc6c19431743a2b096041bcdd62", + "reference": "382e7f4db9a12dc6c19431743a2b096041bcdd62", + "shasum": "" + }, + "require": { + "php": "~7.1" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^6.0", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^7.0", + "predis/predis": "~1.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" + }, + "time": "2019-11-29T15:36:20+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", + "homepage": "https://www.doctrine-project.org/projects/cache.html", + "keywords": [ + "abstraction", + "apcu", + "cache", + "caching", + "couchdb", + "memcached", + "php", + "redis", + "xcache" + ] + }, + { + "name": "doctrine/collections", + "version": "1.6.4", + "version_normalized": "1.6.4.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7", + "reference": "6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan-shim": "^0.9.2", + "phpunit/phpunit": "^7.0", + "vimeo/psalm": "^3.2.2" + }, + "time": "2019-11-13T13:07:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", + "homepage": "https://www.doctrine-project.org/projects/collections.html", + "keywords": [ + "array", + "collections", + "iterators", + "php" + ] + }, + { + "name": "doctrine/common", + "version": "v2.11.0", + "version_normalized": "2.11.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/common.git", + "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/common/zipball/b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", + "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/inflector": "^1.0", + "doctrine/lexer": "^1.0", + "doctrine/persistence": "^1.1", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^1.0", + "phpstan/phpstan": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0", + "symfony/phpunit-bridge": "^4.0.5" + }, + "time": "2019-09-10T10:10:14+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.11.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, persistence interfaces, proxies, event system and much more.", + "homepage": "https://www.doctrine-project.org/projects/common.html", + "keywords": [ + "common", + "doctrine", + "php" + ] + }, + { + "name": "doctrine/data-fixtures", + "version": "1.4.0", + "version_normalized": "1.4.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/data-fixtures.git", + "reference": "608a35a3b5bcc4214d116603095f8b0c51091592" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/608a35a3b5bcc4214d116603095f8b0c51091592", + "reference": "608a35a3b5bcc4214d116603095f8b0c51091592", + "shasum": "" + }, + "require": { + "doctrine/common": "^2.11", + "php": "^7.2" + }, + "conflict": { + "doctrine/phpcr-odm": "<1.3.0" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^6.0", + "doctrine/dbal": "^2.5.4", + "doctrine/mongodb-odm": "^1.3.0", + "doctrine/orm": "^2.5.4", + "phpunit/phpunit": "^7.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "For using MongoDB ODM with PHP 7", + "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", + "doctrine/orm": "For loading ORM fixtures", + "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" + }, + "time": "2019-10-30T20:03:18+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\DataFixtures\\": "lib/Doctrine/Common/DataFixtures" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Data Fixtures for all Doctrine Object Managers", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database" + ] + }, + { + "name": "doctrine/dbal", + "version": "v2.10.0", + "version_normalized": "2.10.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/0c9a646775ef549eb0a213a4f9bd4381d9b4d934", + "reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934", + "shasum": "" + }, + "require": { + "doctrine/cache": "^1.0", + "doctrine/event-manager": "^1.0", + "ext-pdo": "*", + "php": "^7.2" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "jetbrains/phpstorm-stubs": "^2019.1", + "phpstan/phpstan": "^0.11.3", + "phpunit/phpunit": "^8.4.1", + "symfony/console": "^2.0.5|^3.0|^4.0|^5.0" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "time": "2019-11-03T16:50:43+00:00", + "bin": [ + "bin/doctrine-dbal" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.10.x-dev", + "dev-develop": "3.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\DBAL\\": "lib/Doctrine/DBAL" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", + "keywords": [ + "abstraction", + "database", + "db2", + "dbal", + "mariadb", + "mssql", + "mysql", + "oci8", + "oracle", + "pdo", + "pgsql", + "postgresql", + "queryobject", + "sasql", + "sql", + "sqlanywhere", + "sqlite", + "sqlserver", + "sqlsrv" + ] + }, + { + "name": "doctrine/doctrine-bundle", + "version": "2.0.6", + "version_normalized": "2.0.6.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineBundle.git", + "reference": "0ef972d3b730f975c80db9fffa4b2a0258c91442" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/0ef972d3b730f975c80db9fffa4b2a0258c91442", + "reference": "0ef972d3b730f975c80db9fffa4b2a0258c91442", + "shasum": "" + }, + "require": { + "doctrine/dbal": "^2.9.0", + "doctrine/persistence": "^1.3.3", + "jdorn/sql-formatter": "^1.2.16", + "php": "^7.1", + "symfony/cache": "^4.3.3|^5.0", + "symfony/config": "^4.3.3|^5.0", + "symfony/console": "^3.4.30|^4.3.3|^5.0", + "symfony/dependency-injection": "^4.3.3|^5.0", + "symfony/doctrine-bridge": "^4.3.7|^5.0", + "symfony/framework-bundle": "^3.4.30|^4.3.3|^5.0", + "symfony/service-contracts": "^1.1.1|^2.0" + }, + "conflict": { + "doctrine/orm": "<2.6", + "twig/twig": "<1.34|>=2.0,<2.4" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "doctrine/orm": "^2.6", + "ocramius/proxy-manager": "^2.1", + "phpunit/phpunit": "^7.5", + "symfony/phpunit-bridge": "^4.2", + "symfony/property-info": "^4.3.3|^5.0", + "symfony/twig-bridge": "^3.4.30|^4.3.3|^5.0", + "symfony/validator": "^3.4.30|^4.3.3|^5.0", + "symfony/web-profiler-bundle": "^3.4.30|^4.3.3|^5.0", + "symfony/yaml": "^3.4.30|^4.3.3|^5.0", + "twig/twig": "^1.34|^2.12" + }, + "suggest": { + "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", + "symfony/web-profiler-bundle": "To use the data collector." + }, + "time": "2019-12-19T13:47:07+00:00", + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\DoctrineBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Doctrine Project", + "homepage": "http://www.doctrine-project.org/" + } + ], + "description": "Symfony DoctrineBundle", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "dbal", + "orm", + "persistence" + ] + }, + { + "name": "doctrine/doctrine-fixtures-bundle", + "version": "3.3.0", + "version_normalized": "3.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineFixturesBundle.git", + "reference": "8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70", + "reference": "8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70", + "shasum": "" + }, + "require": { + "doctrine/data-fixtures": "^1.3", + "doctrine/doctrine-bundle": "^1.11|^2.0", + "doctrine/orm": "^2.6.0", + "php": "^7.1", + "symfony/config": "^3.4|^4.3|^5.0", + "symfony/console": "^3.4|^4.3|^5.0", + "symfony/dependency-injection": "^3.4|^4.3|^5.0", + "symfony/doctrine-bridge": "^3.4|^4.1|^5.0", + "symfony/http-kernel": "^3.4|^4.3|^5.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.4", + "symfony/phpunit-bridge": "^4.1|^5.0" + }, + "time": "2019-11-13T15:46:58+00:00", + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "3.3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\FixturesBundle\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Doctrine Project", + "homepage": "http://www.doctrine-project.org" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony DoctrineFixturesBundle", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "Fixture", + "persistence" + ] + }, + { + "name": "doctrine/event-manager", + "version": "1.1.0", + "version_normalized": "1.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "629572819973f13486371cb611386eb17851e85c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/629572819973f13486371cb611386eb17851e85c", + "reference": "629572819973f13486371cb611386eb17851e85c", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.0" + }, + "time": "2019-11-10T09:48:07+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "event dispatcher", + "event manager", + "event system", + "events" + ] + }, + { + "name": "doctrine/inflector", + "version": "1.3.1", + "version_normalized": "1.3.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "time": "2019-10-30T19:59:35+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ] + }, + { + "name": "doctrine/instantiator", + "version": "1.3.0", + "version_normalized": "1.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "time": "2019-10-21T16:45:58+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ] + }, + { + "name": "doctrine/lexer", + "version": "1.2.0", + "version_normalized": "1.2.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "shasum": "" + }, + "require": { + "php": "^7.2" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" + }, + "time": "2019-10-30T14:39:59+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ] + }, + { + "name": "doctrine/orm", + "version": "v2.7.0", + "version_normalized": "2.7.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/orm.git", + "reference": "4d763ca4c925f647b248b9fa01b5f47aa3685d62" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/orm/zipball/4d763ca4c925f647b248b9fa01b5f47aa3685d62", + "reference": "4d763ca4c925f647b248b9fa01b5f47aa3685d62", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.8", + "doctrine/cache": "^1.9.1", + "doctrine/collections": "^1.5", + "doctrine/common": "^2.11", + "doctrine/dbal": "^2.9.3", + "doctrine/event-manager": "^1.1", + "doctrine/instantiator": "^1.3", + "doctrine/persistence": "^1.2", + "ext-pdo": "*", + "php": "^7.1", + "symfony/console": "^3.0|^4.0|^5.0" + }, + "require-dev": { + "doctrine/coding-standard": "^5.0", + "phpunit/phpunit": "^7.5", + "symfony/yaml": "^3.4|^4.0|^5.0" + }, + "suggest": { + "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" + }, + "time": "2019-11-19T08:38:05+00:00", + "bin": [ + "bin/doctrine" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\ORM\\": "lib/Doctrine/ORM" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Object-Relational-Mapper for PHP", + "homepage": "https://www.doctrine-project.org/projects/orm.html", + "keywords": [ + "database", + "orm" + ] + }, + { + "name": "doctrine/persistence", + "version": "1.3.3", + "version_normalized": "1.3.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/persistence.git", + "reference": "99b196bbd4715a94fa100fac664a351ffa46d6a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/99b196bbd4715a94fa100fac664a351ffa46d6a5", + "reference": "99b196bbd4715a94fa100fac664a351ffa46d6a5", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.10@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "time": "2019-12-13T10:43:02+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common", + "Doctrine\\Persistence\\": "lib/Doctrine/Persistence" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", + "homepage": "https://doctrine-project.org/projects/persistence.html", + "keywords": [ + "mapper", + "object", + "odm", + "orm", + "persistence" + ] + }, + { + "name": "doctrine/reflection", + "version": "v1.0.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/reflection.git", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/reflection/zipball/02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "doctrine/common": "^2.8", + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "time": "2018-06-14T14:45:07+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Reflection component", + "homepage": "https://www.doctrine-project.org/projects/reflection.html", + "keywords": [ + "reflection" + ] + }, + { + "name": "jdorn/sql-formatter", + "version": "v1.2.17", + "version_normalized": "1.2.17.0", + "source": { + "type": "git", + "url": "https://github.com/jdorn/sql-formatter.git", + "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jdorn/sql-formatter/zipball/64990d96e0959dff8e059dfcdc1af130728d92bc", + "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "time": "2014-01-12T16:20:24+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "classmap": [ + "lib" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeremy Dorn", + "email": "jeremy@jeremydorn.com", + "homepage": "http://jeremydorn.com/" + } + ], + "description": "a PHP SQL highlighting library", + "homepage": "https://github.com/jdorn/sql-formatter/", + "keywords": [ + "highlight", + "sql" + ] + }, + { + "name": "psr/cache", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2016-08-06T20:24:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ] + }, + { + "name": "psr/container", + "version": "1.0.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2017-02-14T16:28:37+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ] + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "time": "2019-01-08T18:20:26+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ] + }, + { + "name": "psr/log", + "version": "1.1.2", + "version_normalized": "1.1.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2019-11-01T11:05:21+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ] + }, + { + "name": "symfony/cache", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache.git", + "reference": "6e8d978878ae5de705ec9fabbb6011cc18776bc9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache/zipball/6e8d978878ae5de705ec9fabbb6011cc18776bc9", + "reference": "6e8d978878ae5de705ec9fabbb6011cc18776bc9", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/cache": "~1.0", + "psr/log": "~1.0", + "symfony/cache-contracts": "^1.1.7|^2", + "symfony/service-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0" + }, + "conflict": { + "doctrine/dbal": "<2.5", + "symfony/dependency-injection": "<4.4", + "symfony/http-kernel": "<4.4", + "symfony/var-dumper": "<4.4" + }, + "provide": { + "psr/cache-implementation": "1.0", + "psr/simple-cache-implementation": "1.0", + "symfony/cache-implementation": "1.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/cache": "~1.6", + "doctrine/dbal": "~2.5", + "predis/predis": "~1.1", + "psr/simple-cache": "^1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "time": "2019-12-12T13:03:32+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Cache\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Cache component with PSR-6, PSR-16, and tags", + "homepage": "https://symfony.com", + "keywords": [ + "caching", + "psr6" + ] + }, + { + "name": "symfony/cache-contracts", + "version": "v2.0.1", + "version_normalized": "2.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/cache-contracts.git", + "reference": "23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16", + "reference": "23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/cache": "^1.0" + }, + "suggest": { + "symfony/cache-implementation": "" + }, + "time": "2019-11-18T17:27:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Cache\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to caching", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ] + }, + { + "name": "symfony/config", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "7f930484966350906185ba0a604728f7898b7ba0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/7f930484966350906185ba0a604728f7898b7ba0", + "reference": "7f930484966350906185ba0a604728f7898b7ba0", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/filesystem": "^4.4|^5.0", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/finder": "<4.4" + }, + "require-dev": { + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "time": "2019-12-18T13:50:31+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Config Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/console", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "fe6e3cd889ca64172d7a742a2eb058541404ef47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/fe6e3cd889ca64172d7a742a2eb058541404ef47", + "reference": "fe6e3cd889ca64172d7a742a2eb058541404ef47", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "symfony/dependency-injection": "<4.4", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "time": "2019-12-17T13:20:22+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/dependency-injection", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "f9dbfbf487d08f60b1c83220edcd16559d1e40a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f9dbfbf487d08f60b1c83220edcd16559d1e40a2", + "reference": "f9dbfbf487d08f60b1c83220edcd16559d1e40a2", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/container": "^1.0", + "symfony/service-contracts": "^1.1.6|^2" + }, + "conflict": { + "symfony/config": "<5.0", + "symfony/finder": "<4.4", + "symfony/proxy-manager-bridge": "<4.4", + "symfony/yaml": "<4.4" + }, + "provide": { + "psr/container-implementation": "1.0", + "symfony/service-implementation": "1.0" + }, + "require-dev": { + "symfony/config": "^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "symfony/config": "", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", + "symfony/yaml": "" + }, + "time": "2019-12-19T16:01:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DependencyInjection Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/doctrine-bridge", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/doctrine-bridge.git", + "reference": "0bdb2d31741cacacb95130d28fbac939c4d574f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/0bdb2d31741cacacb95130d28fbac939c4d574f2", + "reference": "0bdb2d31741cacacb95130d28fbac939c4d574f2", + "shasum": "" + }, + "require": { + "doctrine/event-manager": "~1.0", + "doctrine/persistence": "^1.3", + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/dependency-injection": "<4.4", + "symfony/form": "<5", + "symfony/http-kernel": "<5", + "symfony/messenger": "<4.4", + "symfony/property-info": "<5", + "symfony/security-bundle": "<5", + "symfony/security-core": "<5", + "symfony/validator": "<5.0.2" + }, + "require-dev": { + "doctrine/annotations": "~1.7", + "doctrine/cache": "~1.6", + "doctrine/collections": "~1.0", + "doctrine/data-fixtures": "1.0.*", + "doctrine/dbal": "~2.4", + "doctrine/orm": "^2.6.3", + "doctrine/reflection": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/form": "^5.0", + "symfony/http-kernel": "^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/property-access": "^4.4|^5.0", + "symfony/property-info": "^5.0", + "symfony/proxy-manager-bridge": "^4.4|^5.0", + "symfony/security-core": "^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/validator": "^5.0.2", + "symfony/var-dumper": "^4.4|^5.0" + }, + "suggest": { + "doctrine/data-fixtures": "", + "doctrine/dbal": "", + "doctrine/orm": "", + "symfony/form": "", + "symfony/property-info": "", + "symfony/validator": "" + }, + "time": "2019-12-19T12:10:29+00:00", + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Doctrine\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Doctrine Bridge", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/error-handler", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "460863313bd3212d7c38e1b40602cbcfeeeea4a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/460863313bd3212d7c38e1b40602cbcfeeeea4a5", + "reference": "460863313bd3212d7c38e1b40602cbcfeeeea4a5", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/log": "^1.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "require-dev": { + "symfony/http-kernel": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0" + }, + "time": "2019-12-16T14:48:47+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony ErrorHandler Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/event-dispatcher", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "7b738a51645e10f864cc25c24d232fb03f37b475" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7b738a51645e10f864cc25c24d232fb03f37b475", + "reference": "7b738a51645e10f864cc25c24d232fb03f37b475", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/event-dispatcher-contracts": "^2" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/stopwatch": "^4.4|^5.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "time": "2019-11-18T17:27:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v2.0.1", + "version_normalized": "2.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "af23c2584d4577d54661c434446fb8fbed6025dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/af23c2584d4577d54661c434446fb8fbed6025dd", + "reference": "af23c2584d4577d54661c434446fb8fbed6025dd", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "time": "2019-11-18T17:27:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ] + }, + { + "name": "symfony/filesystem", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "1d71f670bc5a07b9ccc97dc44f932177a322d4e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/1d71f670bc5a07b9ccc97dc44f932177a322d4e6", + "reference": "1d71f670bc5a07b9ccc97dc44f932177a322d4e6", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "time": "2019-11-26T23:25:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Filesystem Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/finder", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "17874dd8ab9a19422028ad56172fb294287a701b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/17874dd8ab9a19422028ad56172fb294287a701b", + "reference": "17874dd8ab9a19422028ad56172fb294287a701b", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "time": "2019-11-18T17:27:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/framework-bundle", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/framework-bundle.git", + "reference": "36e51776b231d8e224da4ce4c60079540acd1c55" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/36e51776b231d8e224da4ce4c60079540acd1c55", + "reference": "36e51776b231d8e224da4ce4c60079540acd1c55", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": "^7.2.5", + "symfony/cache": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/dependency-injection": "^5.0.1", + "symfony/error-handler": "^4.4.1|^5.0.1", + "symfony/filesystem": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-kernel": "^5.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/routing": "^5.0" + }, + "conflict": { + "doctrine/persistence": "<1.3", + "phpdocumentor/reflection-docblock": "<3.0", + "phpdocumentor/type-resolver": "<0.2.1", + "phpunit/phpunit": "<5.4.3", + "symfony/asset": "<4.4", + "symfony/browser-kit": "<4.4", + "symfony/console": "<4.4", + "symfony/dom-crawler": "<4.4", + "symfony/dotenv": "<4.4", + "symfony/form": "<4.4", + "symfony/http-client": "<4.4", + "symfony/lock": "<4.4", + "symfony/mailer": "<4.4", + "symfony/messenger": "<4.4", + "symfony/mime": "<4.4", + "symfony/property-info": "<4.4", + "symfony/serializer": "<4.4", + "symfony/stopwatch": "<4.4", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<4.4", + "symfony/twig-bundle": "<4.4", + "symfony/validator": "<4.4", + "symfony/web-profiler-bundle": "<4.4", + "symfony/workflow": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "~1.7", + "doctrine/cache": "~1.0", + "paragonie/sodium_compat": "^1.8", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", + "symfony/asset": "^4.4|^5.0", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/dotenv": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/form": "^4.4|^5.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/mailer": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/process": "^4.4|^5.0", + "symfony/property-info": "^4.4|^5.0", + "symfony/security-csrf": "^4.4|^5.0", + "symfony/security-http": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/string": "~5.0.0", + "symfony/translation": "^5.0", + "symfony/twig-bundle": "^4.4|^5.0", + "symfony/validator": "^4.4|^5.0", + "symfony/web-link": "^4.4|^5.0", + "symfony/workflow": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0", + "twig/twig": "^2.10|^3.0" + }, + "suggest": { + "ext-apcu": "For best performance of the system caches", + "symfony/console": "For using the console commands", + "symfony/form": "For using forms", + "symfony/property-info": "For using the property_info service", + "symfony/serializer": "For using the serializer service", + "symfony/validator": "For using validation", + "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering", + "symfony/yaml": "For using the debug:config and lint:yaml commands" + }, + "time": "2019-12-17T10:33:13+00:00", + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\FrameworkBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony FrameworkBundle", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/http-foundation", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "5dd7f6be6e62d86ba6f3154cf40e78936367978b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5dd7f6be6e62d86ba6f3154cf40e78936367978b", + "reference": "5dd7f6be6e62d86ba6f3154cf40e78936367978b", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/mime": "^4.4|^5.0", + "symfony/polyfill-mbstring": "~1.1" + }, + "require-dev": { + "predis/predis": "~1.0", + "symfony/expression-language": "^4.4|^5.0" + }, + "time": "2019-12-19T16:01:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/http-kernel", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "00ce30602f3f690e66a63c327743d7b26c723b2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/00ce30602f3f690e66a63c327743d7b26c723b2e", + "reference": "00ce30602f3f690e66a63c327743d7b26c723b2e", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/log": "~1.0", + "symfony/error-handler": "^4.4|^5.0", + "symfony/event-dispatcher": "^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php73": "^1.9" + }, + "conflict": { + "symfony/browser-kit": "<4.4", + "symfony/cache": "<5.0", + "symfony/config": "<5.0", + "symfony/dependency-injection": "<4.4", + "symfony/doctrine-bridge": "<5.0", + "symfony/form": "<5.0", + "symfony/http-client": "<5.0", + "symfony/mailer": "<5.0", + "symfony/messenger": "<5.0", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<5.0", + "symfony/validator": "<5.0", + "twig/twig": "<2.4" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/cache": "~1.0", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/routing": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "twig/twig": "^2.4|^3.0" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "" + }, + "time": "2019-12-19T18:35:03+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpKernel Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/mime", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "0e6a4ced216e49d457eddcefb61132173a876d79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/0e6a4ced216e49d457eddcefb61132173a876d79", + "reference": "0e6a4ced216e49d457eddcefb61132173a876d79", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "symfony/mailer": "<4.4" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10", + "symfony/dependency-injection": "^4.4|^5.0" + }, + "time": "2019-11-30T14:12:50+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A library to manipulate MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ] + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.13.1", + "version_normalized": "1.13.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", + "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "time": "2019-11-27T13:56:44+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ] + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.13.1", + "version_normalized": "1.13.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6f9c239e61e1b0c9229a28ff89a812dc449c3d46", + "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.9" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "time": "2019-11-27T13:56:44+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.13.1", + "version_normalized": "1.13.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f", + "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "time": "2019-11-27T14:18:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.13.1", + "version_normalized": "1.13.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "66fea50f6cb37a35eea048d75a7d99a45b586038" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/66fea50f6cb37a35eea048d75a7d99a45b586038", + "reference": "66fea50f6cb37a35eea048d75a7d99a45b586038", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2019-11-27T13:56:44+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.13.1", + "version_normalized": "1.13.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/4b0e2222c55a25b4541305a053013d5647d3a25f", + "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2019-11-27T16:25:15+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/routing", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "120c5fa4f4ef5466cbb510ece8126e0007285301" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/120c5fa4f4ef5466cbb510ece8126e0007285301", + "reference": "120c5fa4f4ef5466cbb510ece8126e0007285301", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "conflict": { + "symfony/config": "<5.0", + "symfony/dependency-injection": "<4.4", + "symfony/yaml": "<4.4" + }, + "require-dev": { + "doctrine/annotations": "~1.2", + "psr/log": "~1.0", + "symfony/config": "^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "time": "2019-12-12T13:03:32+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Routing Component", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ] + }, + { + "name": "symfony/service-contracts", + "version": "v2.0.1", + "version_normalized": "2.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "144c5e51266b281231e947b51223ba14acf1a749" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", + "reference": "144c5e51266b281231e947b51223ba14acf1a749", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/container": "^1.0" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "time": "2019-11-18T17:27:11+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ] + }, + { + "name": "symfony/var-dumper", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a", + "reference": "d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<4.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "twig/twig": "^2.4|^3.0" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "time": "2019-12-18T13:50:31+00:00", + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ] + }, + { + "name": "symfony/var-exporter", + "version": "v5.0.2", + "version_normalized": "5.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "1b9653e68d5b701bf6d9c91bdd3660078c9f4f28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1b9653e68d5b701bf6d9c91bdd3660078c9f4f28", + "reference": "1b9653e68d5b701bf6d9c91bdd3660078c9f4f28", + "shasum": "" + }, + "require": { + "php": "^7.2.5" + }, + "require-dev": { + "symfony/var-dumper": "^4.4|^5.0" + }, + "time": "2019-12-01T08:48:26+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A blend of var_export() + serialize() to turn any serializable data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "serialize" + ] + } +] diff --git a/vendor/doctrine/annotations/CHANGELOG.md b/vendor/doctrine/annotations/CHANGELOG.md new file mode 100644 index 0000000..0b0ba1a --- /dev/null +++ b/vendor/doctrine/annotations/CHANGELOG.md @@ -0,0 +1,162 @@ +## Changelog + +### 1.6.1 + +This release fixes an issue in which annotations such as `@foo-bar` +and `@foo-` were incorrectly recognised as valid, and both erroneously +parsed as `@foo`. + +Any annotation with `@name-*` format will now silently be ignored, +allowing vendor-specific annotations to be prefixed with the tool +name. + +Total issues resolved: **3** + +- [165: Update the composer branch alias](https://github.com/doctrine/annotations/pull/165) thanks to @mikeSimonson +- [209: Change Annotation::value typehint to mixed](https://github.com/doctrine/annotations/pull/209) thanks to @malarzm +- [257: Skip parsing annotations containing dashes, such as `@Foo-bar`, or `@Foo-`](https://github.com/doctrine/annotations/pull/257) thanks to @Ocramius + +### 1.6.0 + +This release brings a new endpoint that make sure that you can't shoot yourself in the foot by calling ```registerLoader``` multiple times and a few tests improvements. + +Total issues resolved: **7** + +- [145: Memory leak in AnnotationRegistry::registerLoader() when called multiple times](https://github.com/doctrine/annotations/issues/145) thanks to @TriAnMan +- [146: Import error on @experimental Annotation](https://github.com/doctrine/annotations/issues/146) thanks to @aturki +- [147: Ignoring @experimental annotation used by Symfony 3.3 CacheAdapter](https://github.com/doctrine/annotations/pull/147) thanks to @aturki +- [151: Remove duplicate code in `DCOM58Test`](https://github.com/doctrine/annotations/pull/151) thanks to @tuanphpvn +- [161: Prevent loading class_exists multiple times](https://github.com/doctrine/annotations/pull/161) thanks to @jrjohnson +- [162: Add registerUniqueLoader to AnnotationRegistry](https://github.com/doctrine/annotations/pull/162) thanks to @jrjohnson +- [163: Use assertDirectoryExists and assertDirectoryNotExists](https://github.com/doctrine/annotations/pull/163) thanks to @carusogabriel + +Thanks to everyone involved in this release. + +### 1.5.0 + +This release increments the minimum supported PHP version to 7.1.0. + +Also, HHVM official support has been dropped. + +Some noticeable performance improvements to annotation autoloading +have been applied, making failed annotation autoloading less heavy +on the filesystem access. + +- [133: Add @throws annotation in AnnotationReader#__construct()](https://github.com/doctrine/annotations/issues/133) thanks to @SenseException +- [134: Require PHP 7.1, drop HHVM support](https://github.com/doctrine/annotations/issues/134) thanks to @lcobucci +- [135: Prevent the same loader from being registered twice](https://github.com/doctrine/annotations/issues/135) thanks to @jrjohnson +- [137: #135 optimise multiple class load attempts in AnnotationRegistry](https://github.com/doctrine/annotations/issues/137) thanks to @Ocramius + + +### 1.4.0 + +This release fix an issue were some annotations could be not loaded if the namespace in the use statement started with a backslash. +It also update the tests and drop the support for php 5.X + +- [115: Missing annotations with the latest composer version](https://github.com/doctrine/annotations/issues/115) thanks to @pascalporedda +- [120: Missing annotations with the latest composer version](https://github.com/doctrine/annotations/pull/120) thanks to @gnat42 +- [121: Adding a more detailed explanation of the test](https://github.com/doctrine/annotations/pull/121) thanks to @mikeSimonson +- [101: Test annotation parameters containing space](https://github.com/doctrine/annotations/pull/101) thanks to @mikeSimonson +- [111: Cleanup: move to correct phpunit assertions](https://github.com/doctrine/annotations/pull/111) thanks to @Ocramius +- [112: Removes support for PHP 5.x](https://github.com/doctrine/annotations/pull/112) thanks to @railto +- [113: bumped phpunit version to 5.7](https://github.com/doctrine/annotations/pull/113) thanks to @gabbydgab +- [114: Enhancement: Use SVG Travis build badge](https://github.com/doctrine/annotations/pull/114) thanks to @localheinz +- [118: Integrating PHPStan](https://github.com/doctrine/annotations/pull/118) thanks to @ondrejmirtes + +### 1.3.1 - 2016-12-30 + +This release fixes an issue with ignored annotations that were already +autoloaded, causing the `SimpleAnnotationReader` to pick them up +anyway. [#110](https://github.com/doctrine/annotations/pull/110) + +Additionally, an issue was fixed in the `CachedReader`, which was +not correctly checking the freshness of cached annotations when +traits were defined on a class. [#105](https://github.com/doctrine/annotations/pull/105) + +Total issues resolved: **2** + +- [105: Return single max timestamp](https://github.com/doctrine/annotations/pull/105) +- [110: setIgnoreNotImportedAnnotations(true) didn’t work for existing classes](https://github.com/doctrine/annotations/pull/110) + +### 1.3.0 + +This release introduces a PHP version bump. `doctrine/annotations` now requires PHP +5.6 or later to be installed. + +A series of additional improvements have been introduced: + + * support for PHP 7 "grouped use statements" + * support for ignoring entire namespace names + via `Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredNamespace()` and + `Doctrine\Common\Annotations\DocParser::setIgnoredAnnotationNamespaces()`. This will + allow you to ignore annotations from namespaces that you cannot autoload + * testing all parent classes and interfaces when checking if the annotation cache + in the `CachedReader` is fresh + * simplifying the cache keys used by the `CachedReader`: keys are no longer artificially + namespaced, since `Doctrine\Common\Cache` already supports that + * corrected parsing of multibyte strings when `mbstring.func_overload` is enabled + * corrected parsing of annotations when `"\t"` is put before the first annotation + in a docblock + * allow skipping non-imported annotations when a custom `DocParser` is passed to + the `AnnotationReader` constructor + +Total issues resolved: **15** + +- [45: DocParser can now ignore whole namespaces](https://github.com/doctrine/annotations/pull/45) +- [57: Switch to the docker-based infrastructure on Travis](https://github.com/doctrine/annotations/pull/57) +- [59: opcache.load_comments has been removed from PHP 7](https://github.com/doctrine/annotations/pull/59) +- [62: [CachedReader\ Test traits and parent class to see if cache is fresh](https://github.com/doctrine/annotations/pull/62) +- [65: Remove cache salt making key unnecessarily long](https://github.com/doctrine/annotations/pull/65) +- [66: Fix of incorrect parsing multibyte strings](https://github.com/doctrine/annotations/pull/66) +- [68: Annotations that are indented by tab are not processed.](https://github.com/doctrine/annotations/issues/68) +- [69: Support for Group Use Statements](https://github.com/doctrine/annotations/pull/69) +- [70: Allow tab character before first annotation in DocBlock](https://github.com/doctrine/annotations/pull/70) +- [74: Ignore not registered annotations fix](https://github.com/doctrine/annotations/pull/74) +- [92: Added tests for AnnotationRegistry class.](https://github.com/doctrine/annotations/pull/92) +- [96: Fix/#62 check trait and parent class ttl in annotations](https://github.com/doctrine/annotations/pull/96) +- [97: Feature - #45 - allow ignoring entire namespaces](https://github.com/doctrine/annotations/pull/97) +- [98: Enhancement/#65 remove cache salt from cached reader](https://github.com/doctrine/annotations/pull/98) +- [99: Fix - #70 - allow tab character before first annotation in docblock](https://github.com/doctrine/annotations/pull/99) + +### 1.2.4 + +Total issues resolved: **1** + +- [51: FileCacheReader::saveCacheFile::unlink fix](https://github.com/doctrine/annotations/pull/51) + +### 1.2.3 + +Total issues resolved: [**2**](https://github.com/doctrine/annotations/milestones/v1.2.3) + +- [49: #46 - applying correct `chmod()` to generated cache file](https://github.com/doctrine/annotations/pull/49) +- [50: Hotfix: match escaped quotes (revert #44)](https://github.com/doctrine/annotations/pull/50) + +### 1.2.2 + +Total issues resolved: **4** + +- [43: Exclude files from distribution with .gitattributes](https://github.com/doctrine/annotations/pull/43) +- [44: Update DocLexer.php](https://github.com/doctrine/annotations/pull/44) +- [46: A plain "file_put_contents" can cause havoc](https://github.com/doctrine/annotations/pull/46) +- [48: Deprecating the `FileCacheReader` in 1.2.2: will be removed in 2.0.0](https://github.com/doctrine/annotations/pull/48) + +### 1.2.1 + +Total issues resolved: **4** + +- [38: fixes doctrine/common#326](https://github.com/doctrine/annotations/pull/38) +- [39: Remove superfluous NS](https://github.com/doctrine/annotations/pull/39) +- [41: Warn if load_comments is not enabled.](https://github.com/doctrine/annotations/pull/41) +- [42: Clean up unused uses](https://github.com/doctrine/annotations/pull/42) + +### 1.2.0 + + * HHVM support + * Allowing dangling comma in annotations + * Excluded annotations are no longer autoloaded + * Importing namespaces also in traits + * Added support for `::class` 5.5-style constant, works also in 5.3 and 5.4 + +### 1.1.0 + + * Add Exception when ZendOptimizer+ or Opcache is configured to drop comments diff --git a/vendor/doctrine/annotations/LICENSE b/vendor/doctrine/annotations/LICENSE new file mode 100644 index 0000000..5e781fc --- /dev/null +++ b/vendor/doctrine/annotations/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2013 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/doctrine/annotations/README.md b/vendor/doctrine/annotations/README.md new file mode 100644 index 0000000..a53b91f --- /dev/null +++ b/vendor/doctrine/annotations/README.md @@ -0,0 +1,17 @@ +# Doctrine Annotations + +[![Build Status](https://travis-ci.org/doctrine/annotations.svg?branch=master)](https://travis-ci.org/doctrine/annotations) +[![Dependency Status](https://www.versioneye.com/package/php--doctrine--annotations/badge.png)](https://www.versioneye.com/package/php--doctrine--annotations) +[![Reference Status](https://www.versioneye.com/php/doctrine:annotations/reference_badge.svg)](https://www.versioneye.com/php/doctrine:annotations/references) +[![Total Downloads](https://poser.pugx.org/doctrine/annotations/downloads.png)](https://packagist.org/packages/doctrine/annotations) +[![Latest Stable Version](https://poser.pugx.org/doctrine/annotations/v/stable.png)](https://packagist.org/packages/doctrine/annotations) + +Docblock Annotations Parser library (extracted from [Doctrine Common](https://github.com/doctrine/common)). + +## Documentation + +See the [doctrine-project website](https://www.doctrine-project.org/projects/doctrine-annotations/en/latest/index.html). + +## Changelog + +See [CHANGELOG.md](CHANGELOG.md). diff --git a/vendor/doctrine/annotations/composer.json b/vendor/doctrine/annotations/composer.json new file mode 100644 index 0000000..36fd562 --- /dev/null +++ b/vendor/doctrine/annotations/composer.json @@ -0,0 +1,43 @@ +{ + "name": "doctrine/annotations", + "type": "library", + "description": "Docblock Annotations Parser", + "keywords": ["annotations", "docblock", "parser"], + "homepage": "http://www.doctrine-project.org", + "license": "MIT", + "authors": [ + {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, + {"name": "Roman Borschel", "email": "roman@code-factory.org"}, + {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, + {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, + {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} + ], + "require": { + "php": "^7.1", + "doctrine/lexer": "1.*" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "^7.5" + }, + "config": { + "sort-packages": true + }, + "autoload": { + "psr-4": { "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" } + }, + "autoload-dev": { + "psr-4": { + "Doctrine\\Performance\\Common\\Annotations\\": "tests/Doctrine/Performance/Common/Annotations", + "Doctrine\\Tests\\Common\\Annotations\\": "tests/Doctrine/Tests/Common/Annotations" + }, + "files": [ + "tests/Doctrine/Tests/Common/Annotations/Fixtures/SingleClassLOC1000.php" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev" + } + } +} diff --git a/vendor/doctrine/annotations/docs/en/annotations.rst b/vendor/doctrine/annotations/docs/en/annotations.rst new file mode 100644 index 0000000..99da3e2 --- /dev/null +++ b/vendor/doctrine/annotations/docs/en/annotations.rst @@ -0,0 +1,223 @@ +Handling Annotations +==================== + +There are several different approaches to handling annotations in PHP. Doctrine Annotations +maps docblock annotations to PHP classes. Because not all docblock annotations are used +for metadata purposes a filter is applied to ignore or skip classes that are not Doctrine annotations. + +Take a look at the following code snippet: + +.. code-block:: php + + namespace MyProject\Entities; + + use Doctrine\ORM\Mapping AS ORM; + use Symfony\Component\Validation\Constraints AS Assert; + + /** + * @author Benjamin Eberlei + * @ORM\Entity + * @MyProject\Annotations\Foobarable + */ + class User + { + /** + * @ORM\Id @ORM\Column @ORM\GeneratedValue + * @dummy + * @var int + */ + private $id; + + /** + * @ORM\Column(type="string") + * @Assert\NotEmpty + * @Assert\Email + * @var string + */ + private $email; + } + +In this snippet you can see a variety of different docblock annotations: + +- Documentation annotations such as ``@var`` and ``@author``. These annotations are on a blacklist and never considered for throwing an exception due to wrongly used annotations. +- Annotations imported through use statements. The statement ``use Doctrine\ORM\Mapping AS ORM`` makes all classes under that namespace available as ``@ORM\ClassName``. Same goes for the import of ``@Assert``. +- The ``@dummy`` annotation. It is not a documentation annotation and not blacklisted. For Doctrine Annotations it is not entirely clear how to handle this annotation. Depending on the configuration an exception (unknown annotation) will be thrown when parsing this annotation. +- The fully qualified annotation ``@MyProject\Annotations\Foobarable``. This is transformed directly into the given class name. + +How are these annotations loaded? From looking at the code you could guess that the ORM Mapping, Assert Validation and the fully qualified annotation can just be loaded using +the defined PHP autoloaders. This is not the case however: For error handling reasons every check for class existence inside the AnnotationReader sets the second parameter $autoload +of ``class_exists($name, $autoload)`` to false. To work flawlessly the AnnotationReader requires silent autoloaders which many autoloaders are not. Silent autoloading is NOT +part of the `PSR-0 specification `_ for autoloading. + +This is why Doctrine Annotations uses its own autoloading mechanism through a global registry. If you are wondering about the annotation registry being global, +there is no other way to solve the architectural problems of autoloading annotation classes in a straightforward fashion. Additionally if you think about PHP +autoloading then you recognize it is a global as well. + +To anticipate the configuration section, making the above PHP class work with Doctrine Annotations requires this setup: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationReader; + use Doctrine\Common\Annotations\AnnotationRegistry; + + AnnotationRegistry::registerFile("/path/to/doctrine/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php"); + AnnotationRegistry::registerAutoloadNamespace("Symfony\Component\Validator\Constraint", "/path/to/symfony/src"); + AnnotationRegistry::registerAutoloadNamespace("MyProject\Annotations", "/path/to/myproject/src"); + + $reader = new AnnotationReader(); + AnnotationReader::addGlobalIgnoredName('dummy'); + +The second block with the annotation registry calls registers all the three different annotation namespaces that are used. +Doctrine saves all its annotations in a single file, that is why ``AnnotationRegistry#registerFile`` is used in contrast to +``AnnotationRegistry#registerAutoloadNamespace`` which creates a PSR-0 compatible loading mechanism for class to file names. + +In the third block, we create the actual AnnotationReader instance. Note that we also add "dummy" to the global list of annotations +for which we do not throw exceptions. Setting this is necessary in our example case, otherwise ``@dummy`` would trigger an exception to +be thrown during the parsing of the docblock of ``MyProject\Entities\User#id``. + +Setup and Configuration +----------------------- + +To use the annotations library is simple, you just need to create a new ``AnnotationReader`` instance: + +.. code-block:: php + + $reader = new \Doctrine\Common\Annotations\AnnotationReader(); + +This creates a simple annotation reader with no caching other than in memory (in php arrays). +Since parsing docblocks can be expensive you should cache this process by using +a caching reader. + +You can use a file caching reader: + +.. code-block:: php + + use Doctrine\Common\Annotations\FileCacheReader; + use Doctrine\Common\Annotations\AnnotationReader; + + $reader = new FileCacheReader( + new AnnotationReader(), + "/path/to/cache", + $debug = true + ); + +If you set the debug flag to true the cache reader will check for changes in the original files, which +is very important during development. If you don't set it to true you have to delete the directory to clear the cache. +This gives faster performance, however should only be used in production, because of its inconvenience +during development. + +You can also use one of the ``Doctrine\Common\Cache\Cache`` cache implementations to cache the annotations: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationReader; + use Doctrine\Common\Annotations\CachedReader; + use Doctrine\Common\Cache\ApcCache; + + $reader = new CachedReader( + new AnnotationReader(), + new ApcCache(), + $debug = true + ); + +The debug flag is used here as well to invalidate the cache files when the PHP class with annotations changed +and should be used during development. + +.. warning :: + + The AnnotationReader works and caches under the + assumption that all annotations of a doc-block are processed at + once. That means that annotation classes that do not exist and + aren't loaded and cannot be autoloaded (using the AnnotationRegistry) would never be visible and not + accessible if a cache is used unless the cache is cleared and the + annotations requested again, this time with all annotations + defined. + +By default the annotation reader returns a list of annotations with numeric indexes. If you want your annotations +to be indexed by their class name you can wrap the reader in an IndexedReader: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationReader; + use Doctrine\Common\Annotations\IndexedReader; + + $reader = new IndexedReader(new AnnotationReader()); + +.. warning:: + + You should never wrap the indexed reader inside a cached reader only the other way around. This way you can re-use + the cache with indexed or numeric keys, otherwise your code may experience failures due to caching in an numerical + or indexed format. + +Registering Annotations +~~~~~~~~~~~~~~~~~~~~~~~ + +As explained in the Introduction Doctrine Annotations uses its own autoloading mechanism to determine if a +given annotation has a corresponding PHP class that can be autoloaded. For Annotation Autoloading you have +to configure the ``Doctrine\Common\Annotations\AnnotationRegistry``. There are three different mechanisms +to configure annotation autoloading: + +- Calling ``AnnotationRegistry#registerFile($file)`` to register a file that contains one or more Annotation classes. +- Calling ``AnnotationRegistry#registerNamespace($namespace, $dirs = null)`` to register that the given namespace + contains annotations and that their base directory is located at the given $dirs or in the include path if NULL is passed. + The given directories should *NOT* be the directory where classes of the namespace are in, but the base directory + of the root namespace. The AnnotationRegistry uses a namespace to directory separator approach to resolve the correct path. +- Calling ``AnnotationRegistry#registerLoader($callable)`` to register an autoloader callback. The callback accepts the + class as first and only parameter and has to return true if the corresponding file was found and included. + +.. note:: + + Loaders have to fail silently, if a class is not found even if it matches for example the namespace prefix of that loader. + Never is a loader to throw a warning or exception if the loading failed otherwise parsing doc block annotations will become + a huge pain. + +A sample loader callback could look like: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationRegistry; + use Symfony\Component\ClassLoader\UniversalClassLoader; + + AnnotationRegistry::registerLoader(function($class) { + $file = str_replace("\\", DIRECTORY_SEPARATOR, $class) . ".php"; + + if (file_exists("/my/base/path/" . $file)) { + // file exists makes sure that the loader fails silently + require "/my/base/path/" . $file; + } + }); + + $loader = new UniversalClassLoader(); + AnnotationRegistry::registerLoader(array($loader, "loadClass")); + + +Ignoring missing exceptions +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default an exception is thrown from the AnnotationReader if an annotation was found that: + +- Is not part of the blacklist of ignored "documentation annotations". +- Was not imported through a use statement +- Is not a fully qualified class that exists + +You can disable this behavior for specific names if your docblocks do not follow strict requirements: + +.. code-block:: php + + $reader = new \Doctrine\Common\Annotations\AnnotationReader(); + AnnotationReader::addGlobalIgnoredName('foo'); + +PHP Imports +~~~~~~~~~~~ + +By default the annotation reader parses the use-statement of a php file to gain access to the import rules +and register them for the annotation processing. Only if you are using PHP Imports you can validate the correct +usage of annotations and throw exceptions if you misspelled an annotation. This mechanism is enabled by default. + +To ease the upgrade path, we still allow you to disable this mechanism. Note however that we will remove this +in future versions: + +.. code-block:: php + + $reader = new \Doctrine\Common\Annotations\AnnotationReader(); + $reader->setEnabledPhpImports(false); diff --git a/vendor/doctrine/annotations/docs/en/custom.rst b/vendor/doctrine/annotations/docs/en/custom.rst new file mode 100644 index 0000000..860c6e6 --- /dev/null +++ b/vendor/doctrine/annotations/docs/en/custom.rst @@ -0,0 +1,341 @@ +Custom Annotation Classes +========================= + +If you want to define your own annotations you just have to group them in a namespace and register this namespace +in the AnnotationRegistry. Annotation classes have to contain a class-level docblock with the text ``@Annotation``: + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** @Annotation */ + class Bar + { + // some code + } + +Inject annotation values +------------------------ + +The annotation parser check if the annotation constructor has arguments, +if so then we will pass the value array, otherwise will try to inject values into public properties directly: + + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** + * @Annotation + * + * Some Annotation using a constructor + */ + class Bar + { + private $foo; + + public function __construct(array $values) + { + $this->foo = $values['foo']; + } + } + + /** + * @Annotation + * + * Some Annotation without a constructor + */ + class Foo + { + public $bar; + } + +Annotation Target +----------------- + +``@Target`` indicates the kinds of class element to which an annotation type is applicable. +Then you could define one or more targets: + +- ``CLASS`` Allowed in the class docblock +- ``PROPERTY`` Allowed in the property docblock +- ``METHOD`` Allowed in the method docblock +- ``ALL`` Allowed in the class, property and method docblock +- ``ANNOTATION`` Allowed inside other annotations + +If the annotations is not allowed in the current context you got an ``AnnotationException`` + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** + * @Annotation + * @Target({"METHOD","PROPERTY"}) + */ + class Bar + { + // some code + } + + /** + * @Annotation + * @Target("CLASS") + */ + class Foo + { + // some code + } + +Attribute types +--------------- + +Annotation parser check the given parameters using the phpdoc annotation ``@var``, +The data type could be validated using the ``@var`` annotation on the annotation properties +or using the annotations ``@Attributes`` and ``@Attribute``. + +If the data type not match you got an ``AnnotationException`` + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** + * @Annotation + * @Target({"METHOD","PROPERTY"}) + */ + class Bar + { + /** @var mixed */ + public $mixed; + + /** @var boolean */ + public $boolean; + + /** @var bool */ + public $bool; + + /** @var float */ + public $float; + + /** @var string */ + public $string; + + /** @var integer */ + public $integer; + + /** @var array */ + public $array; + + /** @var SomeAnnotationClass */ + public $annotation; + + /** @var array */ + public $arrayOfIntegers; + + /** @var array */ + public $arrayOfAnnotations; + } + + /** + * @Annotation + * @Target({"METHOD","PROPERTY"}) + * @Attributes({ + * @Attribute("stringProperty", type = "string"), + * @Attribute("annotProperty", type = "SomeAnnotationClass"), + * }) + */ + class Foo + { + public function __construct(array $values) + { + $this->stringProperty = $values['stringProperty']; + $this->annotProperty = $values['annotProperty']; + } + + // some code + } + +Annotation Required +------------------- + +``@Required`` indicates that the field must be specified when the annotation is used. +If it is not used you get an ``AnnotationException`` stating that this value can not be null. + +Declaring a required field: + +.. code-block:: php + + /** + * @Annotation + * @Target("ALL") + */ + class Foo + { + /** @Required */ + public $requiredField; + } + +Usage: + +.. code-block:: php + + /** @Foo(requiredField="value") */ + public $direction; // Valid + + /** @Foo */ + public $direction; // Required field missing, throws an AnnotationException + + +Enumerated values +----------------- + +- An annotation property marked with ``@Enum`` is a field that accept a fixed set of scalar values. +- You should use ``@Enum`` fields any time you need to represent fixed values. +- The annotation parser check the given value and throws an ``AnnotationException`` if the value not match. + + +Declaring an enumerated property: + +.. code-block:: php + + /** + * @Annotation + * @Target("ALL") + */ + class Direction + { + /** + * @Enum({"NORTH", "SOUTH", "EAST", "WEST"}) + */ + public $value; + } + +Annotation usage: + +.. code-block:: php + + /** @Direction("NORTH") */ + public $direction; // Valid value + + /** @Direction("NORTHEAST") */ + public $direction; // Invalid value, throws an AnnotationException + + +Constants +--------- + +The use of constants and class constants are available on the annotations parser. + +The following usage are allowed: + +.. code-block:: php + + namespace MyCompany\Entity; + + use MyCompany\Annotations\Foo; + use MyCompany\Annotations\Bar; + use MyCompany\Entity\SomeClass; + + /** + * @Foo(PHP_EOL) + * @Bar(Bar::FOO) + * @Foo({SomeClass::FOO, SomeClass::BAR}) + * @Bar({SomeClass::FOO_KEY = SomeClass::BAR_VALUE}) + */ + class User + { + } + + +Be careful with constants and the cache ! + +.. note:: + + The cached reader will not re-evaluate each time an annotation is loaded from cache. + When a constant is changed the cache must be cleaned. + + +Usage +----- + +Using the library API is simple. Using the annotations described in the previous section +you can now annotate other classes with your annotations: + +.. code-block:: php + + namespace MyCompany\Entity; + + use MyCompany\Annotations\Foo; + use MyCompany\Annotations\Bar; + + /** + * @Foo(bar="foo") + * @Bar(foo="bar") + */ + class User + { + } + +Now we can write a script to get the annotations above: + +.. code-block:: php + + $reflClass = new ReflectionClass('MyCompany\Entity\User'); + $classAnnotations = $reader->getClassAnnotations($reflClass); + + foreach ($classAnnotations AS $annot) { + if ($annot instanceof \MyCompany\Annotations\Foo) { + echo $annot->bar; // prints "foo"; + } else if ($annot instanceof \MyCompany\Annotations\Bar) { + echo $annot->foo; // prints "bar"; + } + } + +You have a complete API for retrieving annotation class instances +from a class, property or method docblock: + + +Reader API +~~~~~~~~~~ + +Access all annotations of a class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getClassAnnotations(\ReflectionClass $class); + +Access one annotation of a class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getClassAnnotation(\ReflectionClass $class, $annotationName); + +Access all annotations of a method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getMethodAnnotations(\ReflectionMethod $method); + +Access one annotation of a method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getMethodAnnotation(\ReflectionMethod $method, $annotationName); + +Access all annotations of a property +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getPropertyAnnotations(\ReflectionProperty $property); + +Access one annotation of a property +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName); diff --git a/vendor/doctrine/annotations/docs/en/index.rst b/vendor/doctrine/annotations/docs/en/index.rst new file mode 100644 index 0000000..3ac6703 --- /dev/null +++ b/vendor/doctrine/annotations/docs/en/index.rst @@ -0,0 +1,90 @@ +Introduction +============ + +Doctrine Annotations offers to implement custom annotation +functionality for PHP classes. + +.. code-block:: php + + class Foo + { + /** + * @MyAnnotation(myProperty="value") + */ + private $bar; + } + +Annotations aren't implemented in PHP itself which is why +this component offers a way to use the PHP doc-blocks as a +place for the well known annotation syntax using the +``@`` char. + +Annotations in Doctrine are used for the ORM +configuration to build the class mapping, but it can +be used in other projects for other purposes too. + +Installation +============ + +You can install the Annotation component with composer: + +.. code-block:: + +   $ composer require doctrine/annotations + +Create an annotation class +========================== + +An annotation class is a representation of the later +used annotation configuration in classes. The annotation +class of the previous example looks like this: + +.. code-block:: php + + /** + * @Annotation + */ + final class MyAnnotation + { + public $myProperty; + } + +The annotation class is declared as an annotation by +``@Annotation``. + +:ref:`Read more about custom annotations. ` + +Reading annotations +=================== + +The access to the annotations happens by reflection of the class +containing them. There are multiple reader-classes implementing the +``Doctrine\Common\Annotations\Reader`` interface, that can +access the annotations of a class. A common one is +``Doctrine\Common\Annotations\AnnotationReader``: + +.. code-block:: php + + $reflectionClass = new ReflectionClass(Foo::class); + $property = $reflectionClass->getProperty('bar'); + + $reader = new AnnotationReader(); + $myAnnotation = $reader->getPropertyAnnotation($property, 'bar'); + + echo $myAnnotation->myProperty; // result: "value" + +A reader has multiple methods to access the annotations +of a class. + +:ref:`Read more about handling annotations. ` + +IDE Support +----------- + +Some IDEs already provide support for annotations: + +- Eclipse via the `Symfony2 Plugin `_ +- PHPStorm via the `PHP Annotations Plugin `_ or the `Symfony2 Plugin `_ + +.. _Read more about handling annotations.: annotations +.. _Read more about custom annotations.: custom diff --git a/vendor/doctrine/annotations/docs/en/sidebar.rst b/vendor/doctrine/annotations/docs/en/sidebar.rst new file mode 100644 index 0000000..6f5d13c --- /dev/null +++ b/vendor/doctrine/annotations/docs/en/sidebar.rst @@ -0,0 +1,6 @@ +.. toctree:: + :depth: 3 + + index + annotations + custom diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php new file mode 100644 index 0000000..a79a0f8 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php @@ -0,0 +1,79 @@ +. + */ + +namespace Doctrine\Common\Annotations; + +/** + * Annotations class. + * + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +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. + * + * @throws \BadMethodCallException + */ + 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 Unknown property name. + * @param mixed $value Property value. + * + * @throws \BadMethodCallException + */ + public function __set($name, $value) + { + throw new \BadMethodCallException( + sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this)) + ); + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php new file mode 100644 index 0000000..dbef6df --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php @@ -0,0 +1,47 @@ +. + */ + +namespace Doctrine\Common\Annotations\Annotation; + +/** + * Annotation that can be used to signal to the parser + * to check the attribute type during the parsing process. + * + * @author Fabio B. Silva + * + * @Annotation + */ +final class Attribute +{ + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $type; + + /** + * @var boolean + */ + public $required = false; +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php new file mode 100644 index 0000000..53134e3 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php @@ -0,0 +1,37 @@ +. + */ + +namespace Doctrine\Common\Annotations\Annotation; + +/** + * Annotation that can be used to signal to the parser + * to check the types of all declared attributes during the parsing process. + * + * @author Fabio B. Silva + * + * @Annotation + */ +final class Attributes +{ + /** + * @var array + */ + public $value; +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php new file mode 100644 index 0000000..82f6241 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php @@ -0,0 +1,84 @@ +. + */ + +namespace Doctrine\Common\Annotations\Annotation; + +/** + * Annotation that can be used to signal to the parser + * to check the available values during the parsing process. + * + * @since 2.4 + * @author Fabio B. Silva + * + * @Annotation + * @Attributes({ + * @Attribute("value", required = true, type = "array"), + * @Attribute("literal", required = false, type = "array") + * }) + */ +final class Enum +{ + /** + * @var array + */ + public $value; + + /** + * Literal target declaration. + * + * @var array + */ + public $literal; + + /** + * Annotation constructor. + * + * @param array $values + * + * @throws \InvalidArgumentException + */ + public function __construct(array $values) + { + if ( ! isset($values['literal'])) { + $values['literal'] = []; + } + + foreach ($values['value'] as $var) { + if( ! is_scalar($var)) { + throw new \InvalidArgumentException(sprintf( + '@Enum supports only scalar values "%s" given.', + is_object($var) ? get_class($var) : gettype($var) + )); + } + } + + foreach ($values['literal'] as $key => $var) { + if( ! in_array($key, $values['value'])) { + throw new \InvalidArgumentException(sprintf( + 'Undefined enumerator value "%s" for literal "%s".', + $key , $var + )); + } + } + + $this->value = $values['value']; + $this->literal = $values['literal']; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php new file mode 100644 index 0000000..85ec3d6 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php @@ -0,0 +1,54 @@ +. + */ + +namespace Doctrine\Common\Annotations\Annotation; + +/** + * Annotation that can be used to signal to the parser to ignore specific + * annotations during the parsing process. + * + * @Annotation + * @author Johannes M. Schmitt + */ +final class IgnoreAnnotation +{ + /** + * @var array + */ + public $names; + + /** + * Constructor. + * + * @param array $values + * + * @throws \RuntimeException + */ + public function __construct(array $values) + { + if (is_string($values['value'])) { + $values['value'] = [$values['value']]; + } + if (!is_array($values['value'])) { + throw new \RuntimeException(sprintf('@IgnoreAnnotation expects either a string name, or an array of strings, but got %s.', json_encode($values['value']))); + } + + $this->names = $values['value']; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php new file mode 100644 index 0000000..d67f960 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php @@ -0,0 +1,33 @@ +. + */ + +namespace Doctrine\Common\Annotations\Annotation; + +/** + * Annotation that can be used to signal to the parser + * to check if that attribute is required during the parsing process. + * + * @author Fabio B. Silva + * + * @Annotation + */ +final class Required +{ +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php new file mode 100644 index 0000000..a52972b --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php @@ -0,0 +1,107 @@ +. + */ + +namespace Doctrine\Common\Annotations\Annotation; + +/** + * Annotation that can be used to signal to the parser + * to check the annotation target during the parsing process. + * + * @author Fabio B. Silva + * + * @Annotation + */ +final class Target +{ + const TARGET_CLASS = 1; + const TARGET_METHOD = 2; + const TARGET_PROPERTY = 4; + const TARGET_ANNOTATION = 8; + const TARGET_ALL = 15; + + /** + * @var array + */ + private static $map = [ + 'ALL' => self::TARGET_ALL, + 'CLASS' => self::TARGET_CLASS, + 'METHOD' => self::TARGET_METHOD, + 'PROPERTY' => self::TARGET_PROPERTY, + 'ANNOTATION' => self::TARGET_ANNOTATION, + ]; + + /** + * @var array + */ + public $value; + + /** + * Targets as bitmask. + * + * @var integer + */ + public $targets; + + /** + * Literal target declaration. + * + * @var integer + */ + public $literal; + + /** + * Annotation constructor. + * + * @param array $values + * + * @throws \InvalidArgumentException + */ + public function __construct(array $values) + { + if (!isset($values['value'])){ + $values['value'] = null; + } + if (is_string($values['value'])){ + $values['value'] = [$values['value']]; + } + if (!is_array($values['value'])){ + throw new \InvalidArgumentException( + sprintf('@Target expects either a string value, or an array of strings, "%s" given.', + is_object($values['value']) ? get_class($values['value']) : gettype($values['value']) + ) + ); + } + + $bitmask = 0; + foreach ($values['value'] as $literal) { + if(!isset(self::$map[$literal])){ + throw new \InvalidArgumentException( + sprintf('Invalid Target "%s". Available targets: [%s]', + $literal, implode(', ', array_keys(self::$map))) + ); + } + $bitmask |= self::$map[$literal]; + } + + $this->targets = $bitmask; + $this->value = $values['value']; + $this->literal = implode(', ', $this->value); + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php new file mode 100644 index 0000000..d06fe66 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php @@ -0,0 +1,197 @@ +. + */ + +namespace Doctrine\Common\Annotations; + +/** + * Description of AnnotationException + * + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +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); + } + + /** + * Creates a new AnnotationException describing an error which occurred during + * the creation of the annotation. + * + * @since 2.2 + * + * @param string $message + * + * @return AnnotationException + */ + public static function creationError($message) + { + return new self('[Creation Error] ' . $message); + } + + /** + * Creates a new AnnotationException describing a type error. + * + * @since 1.1 + * + * @param string $message + * + * @return AnnotationException + */ + public static function typeError($message) + { + return new self('[Type Error] ' . $message); + } + + /** + * Creates a new AnnotationException describing a constant semantical error. + * + * @since 2.3 + * + * @param string $identifier + * @param string $context + * + * @return AnnotationException + */ + public static function semanticalErrorConstants($identifier, $context = null) + { + return self::semanticalError(sprintf( + "Couldn't find constant %s%s.", + $identifier, + $context ? ', ' . $context : '' + )); + } + + /** + * Creates a new AnnotationException describing an type error of an attribute. + * + * @since 2.2 + * + * @param string $attributeName + * @param string $annotationName + * @param string $context + * @param string $expected + * @param mixed $actual + * + * @return AnnotationException + */ + public static function attributeTypeError($attributeName, $annotationName, $context, $expected, $actual) + { + return self::typeError(sprintf( + 'Attribute "%s" of @%s declared on %s expects %s, but got %s.', + $attributeName, + $annotationName, + $context, + $expected, + is_object($actual) ? 'an instance of ' . get_class($actual) : gettype($actual) + )); + } + + /** + * Creates a new AnnotationException describing an required error of an attribute. + * + * @since 2.2 + * + * @param string $attributeName + * @param string $annotationName + * @param string $context + * @param string $expected + * + * @return AnnotationException + */ + public static function requiredError($attributeName, $annotationName, $context, $expected) + { + return self::typeError(sprintf( + 'Attribute "%s" of @%s declared on %s expects %s. This value should not be null.', + $attributeName, + $annotationName, + $context, + $expected + )); + } + + /** + * Creates a new AnnotationException describing a invalid enummerator. + * + * @since 2.4 + * + * @param string $attributeName + * @param string $annotationName + * @param string $context + * @param array $available + * @param mixed $given + * + * @return AnnotationException + */ + public static function enumeratorError($attributeName, $annotationName, $context, $available, $given) + { + return new self(sprintf( + '[Enum Error] Attribute "%s" of @%s declared on %s accept only [%s], but got %s.', + $attributeName, + $annotationName, + $context, + implode(', ', $available), + is_object($given) ? get_class($given) : $given + )); + } + + /** + * @return AnnotationException + */ + public static function optimizerPlusSaveComments() + { + return new self( + "You have to enable opcache.save_comments=1 or zend_optimizerplus.save_comments=1." + ); + } + + /** + * @return AnnotationException + */ + public static function optimizerPlusLoadComments() + { + return new self( + "You have to enable opcache.load_comments=1 or zend_optimizerplus.load_comments=1." + ); + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php new file mode 100644 index 0000000..0b90429 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php @@ -0,0 +1,415 @@ +. + */ + +namespace Doctrine\Common\Annotations; + +use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation; +use Doctrine\Common\Annotations\Annotation\Target; +use ReflectionClass; +use ReflectionMethod; +use ReflectionProperty; + +/** + * A reader for docblock annotations. + * + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Johannes M. Schmitt + */ +class AnnotationReader implements Reader +{ + /** + * Global map for imports. + * + * @var array + */ + private static $globalImports = [ + 'ignoreannotation' => 'Doctrine\Common\Annotations\Annotation\IgnoreAnnotation', + ]; + + /** + * A list with annotations that are not causing exceptions when not resolved to an annotation class. + * + * The names are case sensitive. + * + * @var array + */ + private static $globalIgnoredNames = [ + // Annotation tags + 'Annotation' => true, 'Attribute' => true, 'Attributes' => true, + /* Can we enable this? 'Enum' => true, */ + 'Required' => true, + 'Target' => true, + // Widely used tags (but not existent in phpdoc) + 'fix' => true , 'fixme' => true, + 'override' => true, + // PHPDocumentor 1 tags + 'abstract'=> true, 'access'=> true, + 'code' => true, + 'deprec'=> true, + 'endcode' => true, 'exception'=> true, + 'final'=> true, + 'ingroup' => true, 'inheritdoc'=> true, 'inheritDoc'=> true, + 'magic' => true, + 'name'=> true, + 'toc' => true, 'tutorial'=> true, + 'private' => true, + 'static'=> true, 'staticvar'=> true, 'staticVar'=> true, + 'throw' => true, + // PHPDocumentor 2 tags. + 'api' => true, 'author'=> true, + 'category'=> true, 'copyright'=> true, + 'deprecated'=> true, + 'example'=> true, + 'filesource'=> true, + 'global'=> true, + 'ignore'=> true, /* Can we enable this? 'index' => true, */ 'internal'=> true, + 'license'=> true, 'link'=> true, + 'method' => true, + 'package'=> true, 'param'=> true, 'property' => true, 'property-read' => true, 'property-write' => true, + 'return'=> true, + 'see'=> true, 'since'=> true, 'source' => true, 'subpackage'=> true, + 'throws'=> true, 'todo'=> true, 'TODO'=> true, + 'usedby'=> true, 'uses' => true, + 'var'=> true, 'version'=> true, + // PHPUnit tags + 'codeCoverageIgnore' => true, 'codeCoverageIgnoreStart' => true, 'codeCoverageIgnoreEnd' => true, + // PHPCheckStyle + 'SuppressWarnings' => true, + // PHPStorm + 'noinspection' => true, + // PEAR + 'package_version' => true, + // PlantUML + 'startuml' => true, 'enduml' => true, + // Symfony 3.3 Cache Adapter + 'experimental' => true, + // Slevomat Coding Standard + 'phpcsSuppress' => true, + // PHP CodeSniffer + 'codingStandardsIgnoreStart' => true, + 'codingStandardsIgnoreEnd' => true, + ]; + + /** + * A list with annotations that are not causing exceptions when not resolved to an annotation class. + * + * The names are case sensitive. + * + * @var array + */ + private static $globalIgnoredNamespaces = []; + + /** + * Add a new annotation to the globally ignored annotation names with regard to exception handling. + * + * @param string $name + */ + static public function addGlobalIgnoredName($name) + { + self::$globalIgnoredNames[$name] = true; + } + + /** + * Add a new annotation to the globally ignored annotation namespaces with regard to exception handling. + * + * @param string $namespace + */ + static public function addGlobalIgnoredNamespace($namespace) + { + self::$globalIgnoredNamespaces[$namespace] = true; + } + + /** + * Annotations parser. + * + * @var \Doctrine\Common\Annotations\DocParser + */ + private $parser; + + /** + * Annotations parser used to collect parsing metadata. + * + * @var \Doctrine\Common\Annotations\DocParser + */ + private $preParser; + + /** + * PHP parser used to collect imports. + * + * @var \Doctrine\Common\Annotations\PhpParser + */ + private $phpParser; + + /** + * In-memory cache mechanism to store imported annotations per class. + * + * @var array + */ + private $imports = []; + + /** + * In-memory cache mechanism to store ignored annotations per class. + * + * @var array + */ + private $ignoredAnnotationNames = []; + + /** + * Constructor. + * + * Initializes a new AnnotationReader. + * + * @param DocParser $parser + * + * @throws AnnotationException + */ + public function __construct(DocParser $parser = null) + { + if (extension_loaded('Zend Optimizer+') && (ini_get('zend_optimizerplus.save_comments') === "0" || ini_get('opcache.save_comments') === "0")) { + throw AnnotationException::optimizerPlusSaveComments(); + } + + if (extension_loaded('Zend OPcache') && ini_get('opcache.save_comments') == 0) { + throw AnnotationException::optimizerPlusSaveComments(); + } + + AnnotationRegistry::registerFile(__DIR__ . '/Annotation/IgnoreAnnotation.php'); + + $this->parser = $parser ?: new DocParser(); + + $this->preParser = new DocParser; + + $this->preParser->setImports(self::$globalImports); + $this->preParser->setIgnoreNotImportedAnnotations(true); + $this->preParser->setIgnoredAnnotationNames(self::$globalIgnoredNames); + + $this->phpParser = new PhpParser; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(ReflectionClass $class) + { + $this->parser->setTarget(Target::TARGET_CLASS); + $this->parser->setImports($this->getClassImports($class)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); + $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); + + return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName()); + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName) + { + $annotations = $this->getClassAnnotations($class); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + $context = 'property ' . $class->getName() . "::\$" . $property->getName(); + + $this->parser->setTarget(Target::TARGET_PROPERTY); + $this->parser->setImports($this->getPropertyImports($property)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); + $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); + + return $this->parser->parse($property->getDocComment(), $context); + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) + { + $annotations = $this->getPropertyAnnotations($property); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + $context = 'method ' . $class->getName() . '::' . $method->getName() . '()'; + + $this->parser->setTarget(Target::TARGET_METHOD); + $this->parser->setImports($this->getMethodImports($method)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); + $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); + + return $this->parser->parse($method->getDocComment(), $context); + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName) + { + $annotations = $this->getMethodAnnotations($method); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Returns the ignored annotations for the given class. + * + * @param \ReflectionClass $class + * + * @return array + */ + private function getIgnoredAnnotationNames(ReflectionClass $class) + { + $name = $class->getName(); + if (isset($this->ignoredAnnotationNames[$name])) { + return $this->ignoredAnnotationNames[$name]; + } + + $this->collectParsingMetadata($class); + + return $this->ignoredAnnotationNames[$name]; + } + + /** + * Retrieves imports. + * + * @param \ReflectionClass $class + * + * @return array + */ + private function getClassImports(ReflectionClass $class) + { + $name = $class->getName(); + if (isset($this->imports[$name])) { + return $this->imports[$name]; + } + + $this->collectParsingMetadata($class); + + return $this->imports[$name]; + } + + /** + * Retrieves imports for methods. + * + * @param \ReflectionMethod $method + * + * @return array + */ + private function getMethodImports(ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + $classImports = $this->getClassImports($class); + + $traitImports = []; + + foreach ($class->getTraits() as $trait) { + if ($trait->hasMethod($method->getName()) + && $trait->getFileName() === $method->getFileName() + ) { + $traitImports = array_merge($traitImports, $this->phpParser->parseClass($trait)); + } + } + + return array_merge($classImports, $traitImports); + } + + /** + * Retrieves imports for properties. + * + * @param \ReflectionProperty $property + * + * @return array + */ + private function getPropertyImports(ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + $classImports = $this->getClassImports($class); + + $traitImports = []; + + foreach ($class->getTraits() as $trait) { + if ($trait->hasProperty($property->getName())) { + $traitImports = array_merge($traitImports, $this->phpParser->parseClass($trait)); + } + } + + return array_merge($classImports, $traitImports); + } + + /** + * Collects parsing metadata for a given class. + * + * @param \ReflectionClass $class + */ + private function collectParsingMetadata(ReflectionClass $class) + { + $ignoredAnnotationNames = self::$globalIgnoredNames; + $annotations = $this->preParser->parse($class->getDocComment(), 'class ' . $class->name); + + foreach ($annotations as $annotation) { + if ($annotation instanceof IgnoreAnnotation) { + foreach ($annotation->names AS $annot) { + $ignoredAnnotationNames[$annot] = true; + } + } + } + + $name = $class->getName(); + + $this->imports[$name] = array_merge( + self::$globalImports, + $this->phpParser->parseClass($class), + ['__NAMESPACE__' => $class->getNamespaceName()] + ); + + $this->ignoredAnnotationNames[$name] = $ignoredAnnotationNames; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php new file mode 100644 index 0000000..13abaf5 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php @@ -0,0 +1,174 @@ +. + */ + +namespace Doctrine\Common\Annotations; + +final class AnnotationRegistry +{ + /** + * A map of namespaces to use for autoloading purposes based on a PSR-0 convention. + * + * Contains the namespace as key and an array of directories as value. If the value is NULL + * the include path is used for checking for the corresponding file. + * + * This autoloading mechanism does not utilize the PHP autoloading but implements autoloading on its own. + * + * @var string[][]|string[]|null[] + */ + static private $autoloadNamespaces = []; + + /** + * A map of autoloader callables. + * + * @var callable[] + */ + static private $loaders = []; + + /** + * An array of classes which cannot be found + * + * @var null[] indexed by class name + */ + static private $failedToAutoload = []; + + public static function reset() : void + { + self::$autoloadNamespaces = []; + self::$loaders = []; + self::$failedToAutoload = []; + } + + /** + * Registers file. + * + * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 + * autoloading should be deferred to the globally registered autoloader by then. For now, + * use @example AnnotationRegistry::registerLoader('class_exists') + */ + public static function registerFile(string $file) : void + { + require_once $file; + } + + /** + * Adds a namespace with one or many directories to look for files or null for the include path. + * + * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm. + * + * @param string $namespace + * @param string|array|null $dirs + * + * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 + * autoloading should be deferred to the globally registered autoloader by then. For now, + * use @example AnnotationRegistry::registerLoader('class_exists') + */ + public static function registerAutoloadNamespace(string $namespace, $dirs = null) : void + { + self::$autoloadNamespaces[$namespace] = $dirs; + } + + /** + * Registers multiple namespaces. + * + * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm. + * + * @param string[][]|string[]|null[] $namespaces indexed by namespace name + * + * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 + * autoloading should be deferred to the globally registered autoloader by then. For now, + * use @example AnnotationRegistry::registerLoader('class_exists') + */ + public static function registerAutoloadNamespaces(array $namespaces) : void + { + self::$autoloadNamespaces = \array_merge(self::$autoloadNamespaces, $namespaces); + } + + /** + * Registers an autoloading callable for annotations, much like spl_autoload_register(). + * + * NOTE: These class loaders HAVE to be silent when a class was not found! + * IMPORTANT: Loaders have to return true if they loaded a class that could contain the searched annotation class. + * + * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 + * autoloading should be deferred to the globally registered autoloader by then. For now, + * use @example AnnotationRegistry::registerLoader('class_exists') + */ + public static function registerLoader(callable $callable) : void + { + // Reset our static cache now that we have a new loader to work with + self::$failedToAutoload = []; + self::$loaders[] = $callable; + } + + /** + * Registers an autoloading callable for annotations, if it is not already registered + * + * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 + */ + public static function registerUniqueLoader(callable $callable) : void + { + if ( ! in_array($callable, self::$loaders, true) ) { + self::registerLoader($callable); + } + } + + /** + * Autoloads an annotation class silently. + */ + public static function loadAnnotationClass(string $class) : bool + { + if (\class_exists($class, false)) { + return true; + } + + if (\array_key_exists($class, self::$failedToAutoload)) { + return false; + } + + foreach (self::$autoloadNamespaces AS $namespace => $dirs) { + if (\strpos($class, $namespace) === 0) { + $file = \str_replace('\\', \DIRECTORY_SEPARATOR, $class) . '.php'; + + if ($dirs === null) { + if ($path = stream_resolve_include_path($file)) { + require $path; + return true; + } + } else { + foreach((array) $dirs AS $dir) { + if (is_file($dir . \DIRECTORY_SEPARATOR . $file)) { + require $dir . \DIRECTORY_SEPARATOR . $file; + return true; + } + } + } + } + } + + foreach (self::$loaders AS $loader) { + if ($loader($class) === true) { + return true; + } + } + + self::$failedToAutoload[$class] = null; + + return false; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php new file mode 100644 index 0000000..674b66b --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php @@ -0,0 +1,262 @@ +. + */ + +namespace Doctrine\Common\Annotations; + +use Doctrine\Common\Cache\Cache; +use ReflectionClass; + +/** + * A cache aware annotation reader. + * + * @author Johannes M. Schmitt + * @author Benjamin Eberlei + */ +final class CachedReader implements Reader +{ + /** + * @var Reader + */ + private $delegate; + + /** + * @var Cache + */ + private $cache; + + /** + * @var boolean + */ + private $debug; + + /** + * @var array + */ + private $loadedAnnotations = []; + + /** + * Constructor. + * + * @param Reader $reader + * @param Cache $cache + * @param bool $debug + */ + public function __construct(Reader $reader, Cache $cache, $debug = false) + { + $this->delegate = $reader; + $this->cache = $cache; + $this->debug = (boolean) $debug; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(ReflectionClass $class) + { + $cacheKey = $class->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { + $annots = $this->delegate->getClassAnnotations($class); + $this->saveToCache($cacheKey, $annots); + } + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName) + { + foreach ($this->getClassAnnotations($class) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(\ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + $cacheKey = $class->getName().'$'.$property->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { + $annots = $this->delegate->getPropertyAnnotations($property); + $this->saveToCache($cacheKey, $annots); + } + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) + { + foreach ($this->getPropertyAnnotations($property) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(\ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + $cacheKey = $class->getName().'#'.$method->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { + $annots = $this->delegate->getMethodAnnotations($method); + $this->saveToCache($cacheKey, $annots); + } + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) + { + foreach ($this->getMethodAnnotations($method) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * Clears loaded annotations. + * + * @return void + */ + public function clearLoadedAnnotations() + { + $this->loadedAnnotations = []; + } + + /** + * Fetches a value from the cache. + * + * @param string $cacheKey The cache key. + * @param ReflectionClass $class The related class. + * + * @return mixed The cached value or false when the value is not in cache. + */ + private function fetchFromCache($cacheKey, ReflectionClass $class) + { + if (($data = $this->cache->fetch($cacheKey)) !== false) { + if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) { + return $data; + } + } + + return false; + } + + /** + * Saves a value to the cache. + * + * @param string $cacheKey The cache key. + * @param mixed $value The value. + * + * @return void + */ + private function saveToCache($cacheKey, $value) + { + $this->cache->save($cacheKey, $value); + if ($this->debug) { + $this->cache->save('[C]'.$cacheKey, time()); + } + } + + /** + * Checks if the cache is fresh. + * + * @param string $cacheKey + * @param ReflectionClass $class + * + * @return boolean + */ + private function isCacheFresh($cacheKey, ReflectionClass $class) + { + if (null === $lastModification = $this->getLastModification($class)) { + return true; + } + + return $this->cache->fetch('[C]'.$cacheKey) >= $lastModification; + } + + /** + * Returns the time the class was last modified, testing traits and parents + * + * @param ReflectionClass $class + * @return int + */ + private function getLastModification(ReflectionClass $class) + { + $filename = $class->getFileName(); + $parent = $class->getParentClass(); + + return max(array_merge( + [$filename ? filemtime($filename) : 0], + array_map([$this, 'getTraitLastModificationTime'], $class->getTraits()), + array_map([$this, 'getLastModification'], $class->getInterfaces()), + $parent ? [$this->getLastModification($parent)] : [] + )); + } + + /** + * @param ReflectionClass $reflectionTrait + * @return int + */ + private function getTraitLastModificationTime(ReflectionClass $reflectionTrait) + { + $fileName = $reflectionTrait->getFileName(); + + return max(array_merge( + [$fileName ? filemtime($fileName) : 0], + array_map([$this, 'getTraitLastModificationTime'], $reflectionTrait->getTraits()) + )); + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php new file mode 100644 index 0000000..8182f6c --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php @@ -0,0 +1,147 @@ +. + */ + +namespace Doctrine\Common\Annotations; + +use Doctrine\Common\Lexer\AbstractLexer; + +/** + * Simple lexer for docblock annotations. + * + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Johannes M. Schmitt + */ +final class DocLexer extends AbstractLexer +{ + const T_NONE = 1; + const T_INTEGER = 2; + const T_STRING = 3; + const T_FLOAT = 4; + + // All tokens that are also identifiers should be >= 100 + const T_IDENTIFIER = 100; + 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; + const T_NULL = 111; + const T_COLON = 112; + const T_MINUS = 113; + + /** + * @var array + */ + protected $noCase = [ + '@' => self::T_AT, + ',' => self::T_COMMA, + '(' => self::T_OPEN_PARENTHESIS, + ')' => self::T_CLOSE_PARENTHESIS, + '{' => self::T_OPEN_CURLY_BRACES, + '}' => self::T_CLOSE_CURLY_BRACES, + '=' => self::T_EQUALS, + ':' => self::T_COLON, + '-' => self::T_MINUS, + '\\' => self::T_NAMESPACE_SEPARATOR + ]; + + /** + * @var array + */ + protected $withCase = [ + 'true' => self::T_TRUE, + 'false' => self::T_FALSE, + 'null' => self::T_NULL + ]; + + /** + * Whether the next token starts immediately, or if there were + * non-captured symbols before that + */ + public function nextTokenIsAdjacent() : bool + { + return $this->token === null + || ($this->lookahead !== null + && ($this->lookahead['position'] - $this->token['position']) === strlen($this->token['value'])); + } + + /** + * {@inheritdoc} + */ + protected function getCatchablePatterns() + { + return [ + '[a-z_\\\][a-z0-9_\:\\\]*[a-z_][a-z0-9_]*', + '(?:[+-]?[0-9]+(?:[\.][0-9]+)*)(?:[eE][+-]?[0-9]+)?', + '"(?:""|[^"])*+"', + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNonCatchablePatterns() + { + return ['\s+', '\*+', '(.)']; + } + + /** + * {@inheritdoc} + */ + protected function getType(&$value) + { + $type = self::T_NONE; + + if ($value[0] === '"') { + $value = str_replace('""', '"', substr($value, 1, strlen($value) - 2)); + + return self::T_STRING; + } + + if (isset($this->noCase[$value])) { + return $this->noCase[$value]; + } + + if ($value[0] === '_' || $value[0] === '\\' || ctype_alpha($value[0])) { + return self::T_IDENTIFIER; + } + + $lowerValue = strtolower($value); + + if (isset($this->withCase[$lowerValue])) { + return $this->withCase[$lowerValue]; + } + + // Checking numeric value + if (is_numeric($value)) { + return (strpos($value, '.') !== false || stripos($value, 'e') !== false) + ? self::T_FLOAT : self::T_INTEGER; + } + + return $type; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php new file mode 100644 index 0000000..f076f36 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php @@ -0,0 +1,1197 @@ +. + */ + +namespace Doctrine\Common\Annotations; + +use Doctrine\Common\Annotations\Annotation\Attribute; +use ReflectionClass; +use Doctrine\Common\Annotations\Annotation\Enum; +use Doctrine\Common\Annotations\Annotation\Target; +use Doctrine\Common\Annotations\Annotation\Attributes; + +/** + * A parser for docblock annotations. + * + * It is strongly discouraged to change the default annotation parsing process. + * + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Johannes M. Schmitt + * @author Fabio B. Silva + */ +final class DocParser +{ + /** + * An array of all valid tokens for a class name. + * + * @var array + */ + private static $classIdentifiers = [ + DocLexer::T_IDENTIFIER, + DocLexer::T_TRUE, + DocLexer::T_FALSE, + DocLexer::T_NULL + ]; + + /** + * The lexer. + * + * @var \Doctrine\Common\Annotations\DocLexer + */ + private $lexer; + + /** + * Current target context. + * + * @var integer + */ + private $target; + + /** + * Doc parser used to collect annotation target. + * + * @var \Doctrine\Common\Annotations\DocParser + */ + private static $metadataParser; + + /** + * Flag to control if the current annotation is nested or not. + * + * @var boolean + */ + private $isNestedAnnotation = false; + + /** + * Hashmap containing all use-statements that are to be used when parsing + * the given doc block. + * + * @var array + */ + private $imports = []; + + /** + * This hashmap is used internally to cache results of class_exists() + * look-ups. + * + * @var array + */ + private $classExists = []; + + /** + * Whether annotations that have not been imported should be ignored. + * + * @var boolean + */ + private $ignoreNotImportedAnnotations = false; + + /** + * An array of default namespaces if operating in simple mode. + * + * @var string[] + */ + private $namespaces = []; + + /** + * A list with annotations that are not causing exceptions when not resolved to an annotation class. + * + * The names must be the raw names as used in the class, not the fully qualified + * class names. + * + * @var bool[] indexed by annotation name + */ + private $ignoredAnnotationNames = []; + + /** + * A list with annotations in namespaced format + * that are not causing exceptions when not resolved to an annotation class. + * + * @var bool[] indexed by namespace name + */ + private $ignoredAnnotationNamespaces = []; + + /** + * @var string + */ + private $context = ''; + + /** + * Hash-map for caching annotation metadata. + * + * @var array + */ + private static $annotationMetadata = [ + 'Doctrine\Common\Annotations\Annotation\Target' => [ + 'is_annotation' => true, + 'has_constructor' => true, + 'properties' => [], + 'targets_literal' => 'ANNOTATION_CLASS', + 'targets' => Target::TARGET_CLASS, + 'default_property' => 'value', + 'attribute_types' => [ + 'value' => [ + 'required' => false, + 'type' =>'array', + 'array_type'=>'string', + 'value' =>'array' + ] + ], + ], + 'Doctrine\Common\Annotations\Annotation\Attribute' => [ + 'is_annotation' => true, + 'has_constructor' => false, + 'targets_literal' => 'ANNOTATION_ANNOTATION', + 'targets' => Target::TARGET_ANNOTATION, + 'default_property' => 'name', + 'properties' => [ + 'name' => 'name', + 'type' => 'type', + 'required' => 'required' + ], + 'attribute_types' => [ + 'value' => [ + 'required' => true, + 'type' =>'string', + 'value' =>'string' + ], + 'type' => [ + 'required' =>true, + 'type' =>'string', + 'value' =>'string' + ], + 'required' => [ + 'required' =>false, + 'type' =>'boolean', + 'value' =>'boolean' + ] + ], + ], + 'Doctrine\Common\Annotations\Annotation\Attributes' => [ + 'is_annotation' => true, + 'has_constructor' => false, + 'targets_literal' => 'ANNOTATION_CLASS', + 'targets' => Target::TARGET_CLASS, + 'default_property' => 'value', + 'properties' => [ + 'value' => 'value' + ], + 'attribute_types' => [ + 'value' => [ + 'type' =>'array', + 'required' =>true, + 'array_type'=>'Doctrine\Common\Annotations\Annotation\Attribute', + 'value' =>'array' + ] + ], + ], + 'Doctrine\Common\Annotations\Annotation\Enum' => [ + 'is_annotation' => true, + 'has_constructor' => true, + 'targets_literal' => 'ANNOTATION_PROPERTY', + 'targets' => Target::TARGET_PROPERTY, + 'default_property' => 'value', + 'properties' => [ + 'value' => 'value' + ], + 'attribute_types' => [ + 'value' => [ + 'type' => 'array', + 'required' => true, + ], + 'literal' => [ + 'type' => 'array', + 'required' => false, + ], + ], + ], + ]; + + /** + * Hash-map for handle types declaration. + * + * @var array + */ + private static $typeMap = [ + 'float' => 'double', + 'bool' => 'boolean', + // allow uppercase Boolean in honor of George Boole + 'Boolean' => 'boolean', + 'int' => 'integer', + ]; + + /** + * Constructs a new DocParser. + */ + public function __construct() + { + $this->lexer = new DocLexer; + } + + /** + * Sets the annotation names that are ignored during the parsing process. + * + * The names are supposed to be the raw names as used in the class, not the + * fully qualified class names. + * + * @param bool[] $names indexed by annotation name + * + * @return void + */ + public function setIgnoredAnnotationNames(array $names) + { + $this->ignoredAnnotationNames = $names; + } + + /** + * Sets the annotation namespaces that are ignored during the parsing process. + * + * @param bool[] $ignoredAnnotationNamespaces indexed by annotation namespace name + * + * @return void + */ + public function setIgnoredAnnotationNamespaces($ignoredAnnotationNamespaces) + { + $this->ignoredAnnotationNamespaces = $ignoredAnnotationNamespaces; + } + + /** + * Sets ignore on not-imported annotations. + * + * @param boolean $bool + * + * @return void + */ + public function setIgnoreNotImportedAnnotations($bool) + { + $this->ignoreNotImportedAnnotations = (boolean) $bool; + } + + /** + * Sets the default namespaces. + * + * @param string $namespace + * + * @return void + * + * @throws \RuntimeException + */ + public function addNamespace($namespace) + { + if ($this->imports) { + throw new \RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); + } + + $this->namespaces[] = $namespace; + } + + /** + * Sets the imports. + * + * @param array $imports + * + * @return void + * + * @throws \RuntimeException + */ + public function setImports(array $imports) + { + if ($this->namespaces) { + throw new \RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); + } + + $this->imports = $imports; + } + + /** + * Sets current target context as bitmask. + * + * @param integer $target + * + * @return void + */ + public function setTarget($target) + { + $this->target = $target; + } + + /** + * Parses the given docblock string for annotations. + * + * @param string $input 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($input, $context = '') + { + $pos = $this->findInitialTokenPosition($input); + if ($pos === null) { + return []; + } + + $this->context = $context; + + $this->lexer->setInput(trim(substr($input, $pos), '* /')); + $this->lexer->moveNext(); + + return $this->Annotations(); + } + + /** + * Finds the first valid annotation + * + * @param string $input The docblock string to parse + * + * @return int|null + */ + private function findInitialTokenPosition($input) + { + $pos = 0; + + // search for first valid annotation + while (($pos = strpos($input, '@', $pos)) !== false) { + $preceding = substr($input, $pos - 1, 1); + + // if the @ is preceded by a space, a tab or * it is valid + if ($pos === 0 || $preceding === ' ' || $preceding === '*' || $preceding === "\t") { + return $pos; + } + + $pos++; + } + + return null; + } + + /** + * Attempts to match the given token with the current lookahead token. + * If they match, updates the lookahead token; otherwise raises a syntax error. + * + * @param integer $token Type of token. + * + * @return boolean True if tokens match; false otherwise. + */ + private function match($token) + { + if ( ! $this->lexer->isNextToken($token) ) { + $this->syntaxError($this->lexer->getLiteral($token)); + } + + return $this->lexer->moveNext(); + } + + /** + * Attempts to match the current lookahead token with any of the given tokens. + * + * If any of them matches, this method updates the lookahead token; otherwise + * a syntax error is raised. + * + * @param array $tokens + * + * @return boolean + */ + private function matchAny(array $tokens) + { + if ( ! $this->lexer->isNextTokenAny($tokens)) { + $this->syntaxError(implode(' or ', array_map([$this->lexer, 'getLiteral'], $tokens))); + } + + return $this->lexer->moveNext(); + } + + /** + * Generates a new syntax error. + * + * @param string $expected Expected string. + * @param array|null $token Optional token. + * + * @return void + * + * @throws AnnotationException + */ + private function syntaxError($expected, $token = null) + { + if ($token === null) { + $token = $this->lexer->lookahead; + } + + $message = sprintf('Expected %s, got ', $expected); + $message .= ($this->lexer->lookahead === null) + ? 'end of string' + : sprintf("'%s' at position %s", $token['value'], $token['position']); + + if (strlen($this->context)) { + $message .= ' in ' . $this->context; + } + + $message .= '.'; + + throw AnnotationException::syntaxError($message); + } + + /** + * Attempts to check if a class exists or not. This never goes through the PHP autoloading mechanism + * but uses the {@link AnnotationRegistry} to load classes. + * + * @param string $fqcn + * + * @return boolean + */ + private function classExists($fqcn) + { + if (isset($this->classExists[$fqcn])) { + return $this->classExists[$fqcn]; + } + + // first check if the class already exists, maybe loaded through another AnnotationReader + if (class_exists($fqcn, false)) { + return $this->classExists[$fqcn] = true; + } + + // final check, does this class exist? + return $this->classExists[$fqcn] = AnnotationRegistry::loadAnnotationClass($fqcn); + } + + /** + * Collects parsing metadata for a given annotation class + * + * @param string $name The annotation name + * + * @return void + */ + private function collectAnnotationMetadata($name) + { + if (self::$metadataParser === null) { + self::$metadataParser = new self(); + + self::$metadataParser->setIgnoreNotImportedAnnotations(true); + self::$metadataParser->setIgnoredAnnotationNames($this->ignoredAnnotationNames); + self::$metadataParser->setImports([ + 'enum' => 'Doctrine\Common\Annotations\Annotation\Enum', + 'target' => 'Doctrine\Common\Annotations\Annotation\Target', + 'attribute' => 'Doctrine\Common\Annotations\Annotation\Attribute', + 'attributes' => 'Doctrine\Common\Annotations\Annotation\Attributes' + ]); + + AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Enum.php'); + AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Target.php'); + AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attribute.php'); + AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attributes.php'); + } + + $class = new \ReflectionClass($name); + $docComment = $class->getDocComment(); + + // Sets default values for annotation metadata + $metadata = [ + 'default_property' => null, + 'has_constructor' => (null !== $constructor = $class->getConstructor()) && $constructor->getNumberOfParameters() > 0, + 'properties' => [], + 'property_types' => [], + 'attribute_types' => [], + 'targets_literal' => null, + 'targets' => Target::TARGET_ALL, + 'is_annotation' => false !== strpos($docComment, '@Annotation'), + ]; + + // verify that the class is really meant to be an annotation + if ($metadata['is_annotation']) { + self::$metadataParser->setTarget(Target::TARGET_CLASS); + + foreach (self::$metadataParser->parse($docComment, 'class @' . $name) as $annotation) { + if ($annotation instanceof Target) { + $metadata['targets'] = $annotation->targets; + $metadata['targets_literal'] = $annotation->literal; + + continue; + } + + if ($annotation instanceof Attributes) { + foreach ($annotation->value as $attribute) { + $this->collectAttributeTypeMetadata($metadata, $attribute); + } + } + } + + // if not has a constructor will inject values into public properties + if (false === $metadata['has_constructor']) { + // collect all public properties + foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { + $metadata['properties'][$property->name] = $property->name; + + if (false === ($propertyComment = $property->getDocComment())) { + continue; + } + + $attribute = new Attribute(); + + $attribute->required = (false !== strpos($propertyComment, '@Required')); + $attribute->name = $property->name; + $attribute->type = (false !== strpos($propertyComment, '@var') && preg_match('/@var\s+([^\s]+)/',$propertyComment, $matches)) + ? $matches[1] + : 'mixed'; + + $this->collectAttributeTypeMetadata($metadata, $attribute); + + // checks if the property has @Enum + if (false !== strpos($propertyComment, '@Enum')) { + $context = 'property ' . $class->name . "::\$" . $property->name; + + self::$metadataParser->setTarget(Target::TARGET_PROPERTY); + + foreach (self::$metadataParser->parse($propertyComment, $context) as $annotation) { + if ( ! $annotation instanceof Enum) { + continue; + } + + $metadata['enum'][$property->name]['value'] = $annotation->value; + $metadata['enum'][$property->name]['literal'] = ( ! empty($annotation->literal)) + ? $annotation->literal + : $annotation->value; + } + } + } + + // choose the first property as default property + $metadata['default_property'] = reset($metadata['properties']); + } + } + + self::$annotationMetadata[$name] = $metadata; + } + + /** + * Collects parsing metadata for a given attribute. + * + * @param array $metadata + * @param Attribute $attribute + * + * @return void + */ + private function collectAttributeTypeMetadata(&$metadata, Attribute $attribute) + { + // handle internal type declaration + $type = self::$typeMap[$attribute->type] ?? $attribute->type; + + // handle the case if the property type is mixed + if ('mixed' === $type) { + return; + } + + // Evaluate type + switch (true) { + // Checks if the property has array + case (false !== $pos = strpos($type, '<')): + $arrayType = substr($type, $pos + 1, -1); + $type = 'array'; + + if (isset(self::$typeMap[$arrayType])) { + $arrayType = self::$typeMap[$arrayType]; + } + + $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType; + break; + + // Checks if the property has type[] + case (false !== $pos = strrpos($type, '[')): + $arrayType = substr($type, 0, $pos); + $type = 'array'; + + if (isset(self::$typeMap[$arrayType])) { + $arrayType = self::$typeMap[$arrayType]; + } + + $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType; + break; + } + + $metadata['attribute_types'][$attribute->name]['type'] = $type; + $metadata['attribute_types'][$attribute->name]['value'] = $attribute->type; + $metadata['attribute_types'][$attribute->name]['required'] = $attribute->required; + } + + /** + * Annotations ::= Annotation {[ "*" ]* [Annotation]}* + * + * @return array + */ + private function Annotations() + { + $annotations = []; + + while (null !== $this->lexer->lookahead) { + if (DocLexer::T_AT !== $this->lexer->lookahead['type']) { + $this->lexer->moveNext(); + continue; + } + + // make sure the @ is preceded by non-catchable pattern + if (null !== $this->lexer->token && $this->lexer->lookahead['position'] === $this->lexer->token['position'] + strlen($this->lexer->token['value'])) { + $this->lexer->moveNext(); + continue; + } + + // make sure the @ is followed by either a namespace separator, or + // an identifier token + if ((null === $peek = $this->lexer->glimpse()) + || (DocLexer::T_NAMESPACE_SEPARATOR !== $peek['type'] && !in_array($peek['type'], self::$classIdentifiers, true)) + || $peek['position'] !== $this->lexer->lookahead['position'] + 1) { + $this->lexer->moveNext(); + continue; + } + + $this->isNestedAnnotation = false; + if (false !== $annot = $this->Annotation()) { + $annotations[] = $annot; + } + } + + return $annotations; + } + + /** + * Annotation ::= "@" AnnotationName MethodCall + * AnnotationName ::= QualifiedName | SimpleName + * QualifiedName ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleName + * NameSpacePart ::= identifier | null | false | true + * SimpleName ::= identifier | null | false | true + * + * @return mixed False if it is not a valid annotation. + * + * @throws AnnotationException + */ + private function Annotation() + { + $this->match(DocLexer::T_AT); + + // check if we have an annotation + $name = $this->Identifier(); + + if ($this->lexer->isNextToken(DocLexer::T_MINUS) + && $this->lexer->nextTokenIsAdjacent() + ) { + // Annotations with dashes, such as "@foo-" or "@foo-bar", are to be discarded + return false; + } + + // only process names which are not fully qualified, yet + // fully qualified names must start with a \ + $originalName = $name; + + if ('\\' !== $name[0]) { + $pos = strpos($name, '\\'); + $alias = (false === $pos)? $name : substr($name, 0, $pos); + $found = false; + $loweredAlias = strtolower($alias); + + if ($this->namespaces) { + foreach ($this->namespaces as $namespace) { + if ($this->classExists($namespace.'\\'.$name)) { + $name = $namespace.'\\'.$name; + $found = true; + break; + } + } + } elseif (isset($this->imports[$loweredAlias])) { + $found = true; + $name = (false !== $pos) + ? $this->imports[$loweredAlias] . substr($name, $pos) + : $this->imports[$loweredAlias]; + } elseif ( ! isset($this->ignoredAnnotationNames[$name]) + && isset($this->imports['__NAMESPACE__']) + && $this->classExists($this->imports['__NAMESPACE__'] . '\\' . $name) + ) { + $name = $this->imports['__NAMESPACE__'].'\\'.$name; + $found = true; + } elseif (! isset($this->ignoredAnnotationNames[$name]) && $this->classExists($name)) { + $found = true; + } + + if ( ! $found) { + if ($this->isIgnoredAnnotation($name)) { + return false; + } + + throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation?', $name, $this->context)); + } + } + + $name = ltrim($name,'\\'); + + if ( ! $this->classExists($name)) { + throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s does not exist, or could not be auto-loaded.', $name, $this->context)); + } + + // at this point, $name contains the fully qualified class name of the + // annotation, and it is also guaranteed that this class exists, and + // that it is loaded + + + // collects the metadata annotation only if there is not yet + if ( ! isset(self::$annotationMetadata[$name])) { + $this->collectAnnotationMetadata($name); + } + + // verify that the class is really meant to be an annotation and not just any ordinary class + if (self::$annotationMetadata[$name]['is_annotation'] === false) { + if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$originalName])) { + return false; + } + + throw AnnotationException::semanticalError(sprintf('The class "%s" is not annotated with @Annotation. Are you sure this class can be used as annotation? If so, then you need to add @Annotation to the _class_ doc comment of "%s". If it is indeed no annotation, then you need to add @IgnoreAnnotation("%s") to the _class_ doc comment of %s.', $name, $name, $originalName, $this->context)); + } + + //if target is nested annotation + $target = $this->isNestedAnnotation ? Target::TARGET_ANNOTATION : $this->target; + + // Next will be nested + $this->isNestedAnnotation = true; + + //if annotation does not support current target + if (0 === (self::$annotationMetadata[$name]['targets'] & $target) && $target) { + throw AnnotationException::semanticalError( + sprintf('Annotation @%s is not allowed to be declared on %s. You may only use this annotation on these code elements: %s.', + $originalName, $this->context, self::$annotationMetadata[$name]['targets_literal']) + ); + } + + $values = $this->MethodCall(); + + if (isset(self::$annotationMetadata[$name]['enum'])) { + // checks all declared attributes + foreach (self::$annotationMetadata[$name]['enum'] as $property => $enum) { + // checks if the attribute is a valid enumerator + if (isset($values[$property]) && ! in_array($values[$property], $enum['value'])) { + throw AnnotationException::enumeratorError($property, $name, $this->context, $enum['literal'], $values[$property]); + } + } + } + + // checks all declared attributes + foreach (self::$annotationMetadata[$name]['attribute_types'] as $property => $type) { + if ($property === self::$annotationMetadata[$name]['default_property'] + && !isset($values[$property]) && isset($values['value'])) { + $property = 'value'; + } + + // handle a not given attribute or null value + if (!isset($values[$property])) { + if ($type['required']) { + throw AnnotationException::requiredError($property, $originalName, $this->context, 'a(n) '.$type['value']); + } + + continue; + } + + if ($type['type'] === 'array') { + // handle the case of a single value + if ( ! is_array($values[$property])) { + $values[$property] = [$values[$property]]; + } + + // checks if the attribute has array type declaration, such as "array" + if (isset($type['array_type'])) { + foreach ($values[$property] as $item) { + if (gettype($item) !== $type['array_type'] && !$item instanceof $type['array_type']) { + throw AnnotationException::attributeTypeError($property, $originalName, $this->context, 'either a(n) '.$type['array_type'].', or an array of '.$type['array_type'].'s', $item); + } + } + } + } elseif (gettype($values[$property]) !== $type['type'] && !$values[$property] instanceof $type['type']) { + throw AnnotationException::attributeTypeError($property, $originalName, $this->context, 'a(n) '.$type['value'], $values[$property]); + } + } + + // check if the annotation expects values via the constructor, + // or directly injected into public properties + if (self::$annotationMetadata[$name]['has_constructor'] === true) { + return new $name($values); + } + + $instance = new $name(); + + foreach ($values as $property => $value) { + if (!isset(self::$annotationMetadata[$name]['properties'][$property])) { + if ('value' !== $property) { + throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not have a property named "%s". Available properties: %s', $originalName, $this->context, $property, implode(', ', self::$annotationMetadata[$name]['properties']))); + } + + // handle the case if the property has no annotations + if ( ! $property = self::$annotationMetadata[$name]['default_property']) { + throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not accept any values, but got %s.', $originalName, $this->context, json_encode($values))); + } + } + + $instance->{$property} = $value; + } + + return $instance; + } + + /** + * MethodCall ::= ["(" [Values] ")"] + * + * @return array + */ + private function MethodCall() + { + $values = []; + + if ( ! $this->lexer->isNextToken(DocLexer::T_OPEN_PARENTHESIS)) { + return $values; + } + + $this->match(DocLexer::T_OPEN_PARENTHESIS); + + if ( ! $this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) { + $values = $this->Values(); + } + + $this->match(DocLexer::T_CLOSE_PARENTHESIS); + + return $values; + } + + /** + * Values ::= Array | Value {"," Value}* [","] + * + * @return array + */ + private function Values() + { + $values = [$this->Value()]; + + while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { + $this->match(DocLexer::T_COMMA); + + if ($this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) { + break; + } + + $token = $this->lexer->lookahead; + $value = $this->Value(); + + if ( ! is_object($value) && ! is_array($value)) { + $this->syntaxError('Value', $token); + } + + $values[] = $value; + } + + foreach ($values as $k => $value) { + if (is_object($value) && $value instanceof \stdClass) { + $values[$value->name] = $value->value; + } else if ( ! isset($values['value'])){ + $values['value'] = $value; + } else { + if ( ! is_array($values['value'])) { + $values['value'] = [$values['value']]; + } + + $values['value'][] = $value; + } + + unset($values[$k]); + } + + return $values; + } + + /** + * Constant ::= integer | string | float | boolean + * + * @return mixed + * + * @throws AnnotationException + */ + private function Constant() + { + $identifier = $this->Identifier(); + + if ( ! defined($identifier) && false !== strpos($identifier, '::') && '\\' !== $identifier[0]) { + list($className, $const) = explode('::', $identifier); + + $pos = strpos($className, '\\'); + $alias = (false === $pos) ? $className : substr($className, 0, $pos); + $found = false; + $loweredAlias = strtolower($alias); + + switch (true) { + case !empty ($this->namespaces): + foreach ($this->namespaces as $ns) { + if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) { + $className = $ns.'\\'.$className; + $found = true; + break; + } + } + break; + + case isset($this->imports[$loweredAlias]): + $found = true; + $className = (false !== $pos) + ? $this->imports[$loweredAlias] . substr($className, $pos) + : $this->imports[$loweredAlias]; + break; + + default: + if(isset($this->imports['__NAMESPACE__'])) { + $ns = $this->imports['__NAMESPACE__']; + + if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) { + $className = $ns.'\\'.$className; + $found = true; + } + } + break; + } + + if ($found) { + $identifier = $className . '::' . $const; + } + } + + // checks if identifier ends with ::class, \strlen('::class') === 7 + $classPos = stripos($identifier, '::class'); + if ($classPos === strlen($identifier) - 7) { + return substr($identifier, 0, $classPos); + } + + if (!defined($identifier)) { + throw AnnotationException::semanticalErrorConstants($identifier, $this->context); + } + + return constant($identifier); + } + + /** + * Identifier ::= string + * + * @return string + */ + private function Identifier() + { + // check if we have an annotation + if ( ! $this->lexer->isNextTokenAny(self::$classIdentifiers)) { + $this->syntaxError('namespace separator or identifier'); + } + + $this->lexer->moveNext(); + + $className = $this->lexer->token['value']; + + while ( + null !== $this->lexer->lookahead && + $this->lexer->lookahead['position'] === ($this->lexer->token['position'] + strlen($this->lexer->token['value'])) && + $this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR) + ) { + $this->match(DocLexer::T_NAMESPACE_SEPARATOR); + $this->matchAny(self::$classIdentifiers); + + $className .= '\\' . $this->lexer->token['value']; + } + + return $className; + } + + /** + * Value ::= PlainValue | FieldAssignment + * + * @return mixed + */ + private function Value() + { + $peek = $this->lexer->glimpse(); + + if (DocLexer::T_EQUALS === $peek['type']) { + return $this->FieldAssignment(); + } + + return $this->PlainValue(); + } + + /** + * PlainValue ::= integer | string | float | boolean | Array | Annotation + * + * @return mixed + */ + private function PlainValue() + { + if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) { + return $this->Arrayx(); + } + + if ($this->lexer->isNextToken(DocLexer::T_AT)) { + return $this->Annotation(); + } + + if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { + return $this->Constant(); + } + + switch ($this->lexer->lookahead['type']) { + case DocLexer::T_STRING: + $this->match(DocLexer::T_STRING); + return $this->lexer->token['value']; + + case DocLexer::T_INTEGER: + $this->match(DocLexer::T_INTEGER); + return (int)$this->lexer->token['value']; + + case DocLexer::T_FLOAT: + $this->match(DocLexer::T_FLOAT); + return (float)$this->lexer->token['value']; + + case DocLexer::T_TRUE: + $this->match(DocLexer::T_TRUE); + return true; + + case DocLexer::T_FALSE: + $this->match(DocLexer::T_FALSE); + return false; + + case DocLexer::T_NULL: + $this->match(DocLexer::T_NULL); + return null; + + default: + $this->syntaxError('PlainValue'); + } + } + + /** + * FieldAssignment ::= FieldName "=" PlainValue + * FieldName ::= identifier + * + * @return \stdClass + */ + private function FieldAssignment() + { + $this->match(DocLexer::T_IDENTIFIER); + $fieldName = $this->lexer->token['value']; + + $this->match(DocLexer::T_EQUALS); + + $item = new \stdClass(); + $item->name = $fieldName; + $item->value = $this->PlainValue(); + + return $item; + } + + /** + * Array ::= "{" ArrayEntry {"," ArrayEntry}* [","] "}" + * + * @return array + */ + private function Arrayx() + { + $array = $values = []; + + $this->match(DocLexer::T_OPEN_CURLY_BRACES); + + // If the array is empty, stop parsing and return. + if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) { + $this->match(DocLexer::T_CLOSE_CURLY_BRACES); + + return $array; + } + + $values[] = $this->ArrayEntry(); + + while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { + $this->match(DocLexer::T_COMMA); + + // optional trailing comma + if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) { + break; + } + + $values[] = $this->ArrayEntry(); + } + + $this->match(DocLexer::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 | Constant + * Key ::= string | integer | Constant + * + * @return array + */ + private function ArrayEntry() + { + $peek = $this->lexer->glimpse(); + + if (DocLexer::T_EQUALS === $peek['type'] + || DocLexer::T_COLON === $peek['type']) { + + if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { + $key = $this->Constant(); + } else { + $this->matchAny([DocLexer::T_INTEGER, DocLexer::T_STRING]); + $key = $this->lexer->token['value']; + } + + $this->matchAny([DocLexer::T_EQUALS, DocLexer::T_COLON]); + + return [$key, $this->PlainValue()]; + } + + return [null, $this->Value()]; + } + + /** + * Checks whether the given $name matches any ignored annotation name or namespace + * + * @param string $name + * + * @return bool + */ + private function isIgnoredAnnotation($name) + { + if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) { + return true; + } + + foreach (array_keys($this->ignoredAnnotationNamespaces) as $ignoredAnnotationNamespace) { + $ignoredAnnotationNamespace = rtrim($ignoredAnnotationNamespace, '\\') . '\\'; + + if (0 === stripos(rtrim($name, '\\') . '\\', $ignoredAnnotationNamespace)) { + return true; + } + } + + return false; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php new file mode 100644 index 0000000..40141af --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php @@ -0,0 +1,290 @@ +. + */ + +namespace Doctrine\Common\Annotations; + +/** + * File cache reader for annotations. + * + * @author Johannes M. Schmitt + * @author Benjamin Eberlei + * + * @deprecated the FileCacheReader is deprecated and will be removed + * in version 2.0.0 of doctrine/annotations. Please use the + * {@see \Doctrine\Common\Annotations\CachedReader} instead. + */ +class FileCacheReader implements Reader +{ + /** + * @var Reader + */ + private $reader; + + /** + * @var string + */ + private $dir; + + /** + * @var bool + */ + private $debug; + + /** + * @var array + */ + private $loadedAnnotations = []; + + /** + * @var array + */ + private $classNameHashes = []; + + /** + * @var int + */ + private $umask; + + /** + * Constructor. + * + * @param Reader $reader + * @param string $cacheDir + * @param boolean $debug + * + * @throws \InvalidArgumentException + */ + public function __construct(Reader $reader, $cacheDir, $debug = false, $umask = 0002) + { + if ( ! is_int($umask)) { + throw new \InvalidArgumentException(sprintf( + 'The parameter umask must be an integer, was: %s', + gettype($umask) + )); + } + + $this->reader = $reader; + $this->umask = $umask; + + if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777 & (~$this->umask), true)) { + throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $cacheDir)); + } + + $this->dir = rtrim($cacheDir, '\\/'); + $this->debug = $debug; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(\ReflectionClass $class) + { + if ( ! isset($this->classNameHashes[$class->name])) { + $this->classNameHashes[$class->name] = sha1($class->name); + } + $key = $this->classNameHashes[$class->name]; + + if (isset($this->loadedAnnotations[$key])) { + return $this->loadedAnnotations[$key]; + } + + $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; + if (!is_file($path)) { + $annot = $this->reader->getClassAnnotations($class); + $this->saveCacheFile($path, $annot); + return $this->loadedAnnotations[$key] = $annot; + } + + if ($this->debug + && (false !== $filename = $class->getFileName()) + && filemtime($path) < filemtime($filename)) { + @unlink($path); + + $annot = $this->reader->getClassAnnotations($class); + $this->saveCacheFile($path, $annot); + return $this->loadedAnnotations[$key] = $annot; + } + + return $this->loadedAnnotations[$key] = include $path; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(\ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + if ( ! isset($this->classNameHashes[$class->name])) { + $this->classNameHashes[$class->name] = sha1($class->name); + } + $key = $this->classNameHashes[$class->name].'$'.$property->getName(); + + if (isset($this->loadedAnnotations[$key])) { + return $this->loadedAnnotations[$key]; + } + + $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; + if (!is_file($path)) { + $annot = $this->reader->getPropertyAnnotations($property); + $this->saveCacheFile($path, $annot); + return $this->loadedAnnotations[$key] = $annot; + } + + if ($this->debug + && (false !== $filename = $class->getFilename()) + && filemtime($path) < filemtime($filename)) { + @unlink($path); + + $annot = $this->reader->getPropertyAnnotations($property); + $this->saveCacheFile($path, $annot); + return $this->loadedAnnotations[$key] = $annot; + } + + return $this->loadedAnnotations[$key] = include $path; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(\ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + if ( ! isset($this->classNameHashes[$class->name])) { + $this->classNameHashes[$class->name] = sha1($class->name); + } + $key = $this->classNameHashes[$class->name].'#'.$method->getName(); + + if (isset($this->loadedAnnotations[$key])) { + return $this->loadedAnnotations[$key]; + } + + $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; + if (!is_file($path)) { + $annot = $this->reader->getMethodAnnotations($method); + $this->saveCacheFile($path, $annot); + return $this->loadedAnnotations[$key] = $annot; + } + + if ($this->debug + && (false !== $filename = $class->getFilename()) + && filemtime($path) < filemtime($filename)) { + @unlink($path); + + $annot = $this->reader->getMethodAnnotations($method); + $this->saveCacheFile($path, $annot); + return $this->loadedAnnotations[$key] = $annot; + } + + return $this->loadedAnnotations[$key] = include $path; + } + + /** + * Saves the cache file. + * + * @param string $path + * @param mixed $data + * + * @return void + */ + private function saveCacheFile($path, $data) + { + if (!is_writable($this->dir)) { + throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable. Both, the webserver and the console user need access. You can manage access rights for multiple users with "chmod +a". If your system does not support this, check out the acl package.', $this->dir)); + } + + $tempfile = tempnam($this->dir, uniqid('', true)); + + if (false === $tempfile) { + throw new \RuntimeException(sprintf('Unable to create tempfile in directory: %s', $this->dir)); + } + + @chmod($tempfile, 0666 & (~$this->umask)); + + $written = file_put_contents($tempfile, 'umask)); + + if (false === rename($tempfile, $path)) { + @unlink($tempfile); + throw new \RuntimeException(sprintf('Unable to rename %s to %s', $tempfile, $path)); + } + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(\ReflectionClass $class, $annotationName) + { + $annotations = $this->getClassAnnotations($class); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) + { + $annotations = $this->getMethodAnnotations($method); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) + { + $annotations = $this->getPropertyAnnotations($property); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Clears loaded annotations. + * + * @return void + */ + public function clearLoadedAnnotations() + { + $this->loadedAnnotations = []; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php new file mode 100644 index 0000000..4e8c3c8 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php @@ -0,0 +1,119 @@ +. + */ + +namespace Doctrine\Common\Annotations; + +/** + * Allows the reader to be used in-place of Doctrine's reader. + * + * @author Johannes M. Schmitt + */ +class IndexedReader implements Reader +{ + /** + * @var Reader + */ + private $delegate; + + /** + * Constructor. + * + * @param Reader $reader + */ + public function __construct(Reader $reader) + { + $this->delegate = $reader; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(\ReflectionClass $class) + { + $annotations = []; + foreach ($this->delegate->getClassAnnotations($class) as $annot) { + $annotations[get_class($annot)] = $annot; + } + + return $annotations; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(\ReflectionClass $class, $annotation) + { + return $this->delegate->getClassAnnotation($class, $annotation); + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(\ReflectionMethod $method) + { + $annotations = []; + foreach ($this->delegate->getMethodAnnotations($method) as $annot) { + $annotations[get_class($annot)] = $annot; + } + + return $annotations; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(\ReflectionMethod $method, $annotation) + { + return $this->delegate->getMethodAnnotation($method, $annotation); + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(\ReflectionProperty $property) + { + $annotations = []; + foreach ($this->delegate->getPropertyAnnotations($property) as $annot) { + $annotations[get_class($annot)] = $annot; + } + + return $annotations; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(\ReflectionProperty $property, $annotation) + { + return $this->delegate->getPropertyAnnotation($property, $annotation); + } + + /** + * Proxies all methods to the delegate. + * + * @param string $method + * @param array $args + * + * @return mixed + */ + public function __call($method, $args) + { + return call_user_func_array([$this->delegate, $method], $args); + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php new file mode 100644 index 0000000..ec87181 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php @@ -0,0 +1,91 @@ +. + */ + +namespace Doctrine\Common\Annotations; + +use SplFileObject; + +/** + * Parses a file for namespaces/use/class declarations. + * + * @author Fabien Potencier + * @author Christian Kaps + */ +final class PhpParser +{ + /** + * Parses a class. + * + * @param \ReflectionClass $class A ReflectionClass object. + * + * @return array A list with use statements in the form (Alias => FQN). + */ + public function parseClass(\ReflectionClass $class) + { + if (method_exists($class, 'getUseStatements')) { + return $class->getUseStatements(); + } + + if (false === $filename = $class->getFileName()) { + return []; + } + + $content = $this->getFileContent($filename, $class->getStartLine()); + + if (null === $content) { + return []; + } + + $namespace = preg_quote($class->getNamespaceName()); + $content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content); + $tokenizer = new TokenParser('parseUseStatements($class->getNamespaceName()); + + return $statements; + } + + /** + * Gets the content of the file right up to the given line number. + * + * @param string $filename The name of the file to load. + * @param integer $lineNumber The number of lines to read from file. + * + * @return string|null The content of the file or null if the file does not exist. + */ + private function getFileContent($filename, $lineNumber) + { + if ( ! is_file($filename)) { + return null; + } + + $content = ''; + $lineCnt = 0; + $file = new SplFileObject($filename); + while (!$file->eof()) { + if ($lineCnt++ == $lineNumber) { + break; + } + + $content .= $file->fgets(); + } + + return $content; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php new file mode 100644 index 0000000..4774f87 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php @@ -0,0 +1,89 @@ +. + */ + +namespace Doctrine\Common\Annotations; + +/** + * Interface for annotation readers. + * + * @author Johannes M. Schmitt + */ +interface Reader +{ + /** + * Gets the annotations applied to a class. + * + * @param \ReflectionClass $class The ReflectionClass of the class from which + * the class annotations should be read. + * + * @return array An array of Annotations. + */ + function getClassAnnotations(\ReflectionClass $class); + + /** + * Gets a class annotation. + * + * @param \ReflectionClass $class The ReflectionClass of the class from which + * the class annotations should be read. + * @param string $annotationName The name of the annotation. + * + * @return object|null The Annotation or NULL, if the requested annotation does not exist. + */ + function getClassAnnotation(\ReflectionClass $class, $annotationName); + + /** + * Gets the annotations applied to a method. + * + * @param \ReflectionMethod $method The ReflectionMethod of the method from which + * the annotations should be read. + * + * @return array An array of Annotations. + */ + function getMethodAnnotations(\ReflectionMethod $method); + + /** + * Gets a method annotation. + * + * @param \ReflectionMethod $method The ReflectionMethod to read the annotations from. + * @param string $annotationName The name of the annotation. + * + * @return object|null The Annotation or NULL, if the requested annotation does not exist. + */ + function getMethodAnnotation(\ReflectionMethod $method, $annotationName); + + /** + * Gets the annotations applied to a property. + * + * @param \ReflectionProperty $property The ReflectionProperty of the property + * from which the annotations should be read. + * + * @return array An array of Annotations. + */ + function getPropertyAnnotations(\ReflectionProperty $property); + + /** + * Gets a property annotation. + * + * @param \ReflectionProperty $property The ReflectionProperty to read the annotations from. + * @param string $annotationName The name of the annotation. + * + * @return object|null The Annotation or NULL, if the requested annotation does not exist. + */ + function getPropertyAnnotation(\ReflectionProperty $property, $annotationName); +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php new file mode 100644 index 0000000..d4757ee --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php @@ -0,0 +1,127 @@ +. + */ + +namespace Doctrine\Common\Annotations; + +/** + * Simple Annotation Reader. + * + * This annotation reader is intended to be used in projects where you have + * full-control over all annotations that are available. + * + * @since 2.2 + * @author Johannes M. Schmitt + * @author Fabio B. Silva + */ +class SimpleAnnotationReader implements Reader +{ + /** + * @var DocParser + */ + private $parser; + + /** + * Constructor. + * + * Initializes a new SimpleAnnotationReader. + */ + public function __construct() + { + $this->parser = new DocParser(); + $this->parser->setIgnoreNotImportedAnnotations(true); + } + + /** + * Adds a namespace in which we will look for annotations. + * + * @param string $namespace + * + * @return void + */ + public function addNamespace($namespace) + { + $this->parser->addNamespace($namespace); + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(\ReflectionClass $class) + { + return $this->parser->parse($class->getDocComment(), 'class '.$class->getName()); + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(\ReflectionMethod $method) + { + return $this->parser->parse($method->getDocComment(), 'method '.$method->getDeclaringClass()->name.'::'.$method->getName().'()'); + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(\ReflectionProperty $property) + { + return $this->parser->parse($property->getDocComment(), 'property '.$property->getDeclaringClass()->name.'::$'.$property->getName()); + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(\ReflectionClass $class, $annotationName) + { + foreach ($this->getClassAnnotations($class) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) + { + foreach ($this->getMethodAnnotations($method) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) + { + foreach ($this->getPropertyAnnotations($property) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } +} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php new file mode 100644 index 0000000..03d9320 --- /dev/null +++ b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php @@ -0,0 +1,194 @@ +. + */ + +namespace Doctrine\Common\Annotations; + +/** + * Parses a file for namespaces/use/class declarations. + * + * @author Fabien Potencier + * @author Christian Kaps + */ +class TokenParser +{ + /** + * The token list. + * + * @var array + */ + private $tokens; + + /** + * The number of tokens. + * + * @var int + */ + private $numTokens; + + /** + * The current array pointer. + * + * @var int + */ + private $pointer = 0; + + /** + * @param string $contents + */ + public function __construct($contents) + { + $this->tokens = token_get_all($contents); + + // The PHP parser sets internal compiler globals for certain things. Annoyingly, the last docblock comment it + // saw gets stored in doc_comment. When it comes to compile the next thing to be include()d this stored + // doc_comment becomes owned by the first thing the compiler sees in the file that it considers might have a + // docblock. If the first thing in the file is a class without a doc block this would cause calls to + // getDocBlock() on said class to return our long lost doc_comment. Argh. + // To workaround, cause the parser to parse an empty docblock. Sure getDocBlock() will return this, but at least + // it's harmless to us. + token_get_all("numTokens = count($this->tokens); + } + + /** + * Gets the next non whitespace and non comment token. + * + * @param boolean $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped. + * If FALSE then only whitespace and normal comments are skipped. + * + * @return array|null The token if exists, null otherwise. + */ + public function next($docCommentIsComment = TRUE) + { + for ($i = $this->pointer; $i < $this->numTokens; $i++) { + $this->pointer++; + if ($this->tokens[$i][0] === T_WHITESPACE || + $this->tokens[$i][0] === T_COMMENT || + ($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT)) { + + continue; + } + + return $this->tokens[$i]; + } + + return null; + } + + /** + * Parses a single use statement. + * + * @return array A list with all found class names for a use statement. + */ + public function parseUseStatement() + { + + $groupRoot = ''; + $class = ''; + $alias = ''; + $statements = []; + $explicitAlias = false; + while (($token = $this->next())) { + $isNameToken = $token[0] === T_STRING || $token[0] === T_NS_SEPARATOR; + if (!$explicitAlias && $isNameToken) { + $class .= $token[1]; + $alias = $token[1]; + } else if ($explicitAlias && $isNameToken) { + $alias .= $token[1]; + } else if ($token[0] === T_AS) { + $explicitAlias = true; + $alias = ''; + } else if ($token === ',') { + $statements[strtolower($alias)] = $groupRoot . $class; + $class = ''; + $alias = ''; + $explicitAlias = false; + } else if ($token === ';') { + $statements[strtolower($alias)] = $groupRoot . $class; + break; + } else if ($token === '{' ) { + $groupRoot = $class; + $class = ''; + } else if ($token === '}' ) { + continue; + } else { + break; + } + } + + return $statements; + } + + /** + * Gets all use statements. + * + * @param string $namespaceName The namespace name of the reflected class. + * + * @return array A list with all found use statements. + */ + public function parseUseStatements($namespaceName) + { + $statements = []; + while (($token = $this->next())) { + if ($token[0] === T_USE) { + $statements = array_merge($statements, $this->parseUseStatement()); + continue; + } + if ($token[0] !== T_NAMESPACE || $this->parseNamespace() != $namespaceName) { + continue; + } + + // Get fresh array for new namespace. This is to prevent the parser to collect the use statements + // for a previous namespace with the same name. This is the case if a namespace is defined twice + // or if a namespace with the same name is commented out. + $statements = []; + } + + return $statements; + } + + /** + * Gets the namespace. + * + * @return string The found namespace. + */ + public function parseNamespace() + { + $name = ''; + while (($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR)) { + $name .= $token[1]; + } + + return $name; + } + + /** + * Gets the class name. + * + * @return string The found class name. + */ + public function parseClass() + { + // Namespaces and class names are tokenized the same: T_STRINGs + // separated by T_NS_SEPARATOR so we can use one function to provide + // both. + return $this->parseNamespace(); + } +} diff --git a/vendor/doctrine/annotations/phpbench.json.dist b/vendor/doctrine/annotations/phpbench.json.dist new file mode 100644 index 0000000..35edde9 --- /dev/null +++ b/vendor/doctrine/annotations/phpbench.json.dist @@ -0,0 +1,4 @@ +{ + "bootstrap": "tests/Doctrine/Performance/Common/bootstrap.php", + "path": "tests/Doctrine/Performance/Common/Annotations" +} diff --git a/vendor/doctrine/annotations/phpstan.neon b/vendor/doctrine/annotations/phpstan.neon new file mode 100644 index 0000000..bac7f83 --- /dev/null +++ b/vendor/doctrine/annotations/phpstan.neon @@ -0,0 +1,14 @@ +parameters: + autoload_files: + - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Annotations/DocParserTest.php + excludes_analyse: + - %currentWorkingDirectory%/tests/*/Fixtures/* + - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Annotations/ReservedKeywordsClasses.php + - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM58Entity.php + - %currentWorkingDirectory%/tests/Doctrine/Tests/DoctrineTestCase.php + polluteScopeWithLoopInitialAssignments: true + ignoreErrors: + - '#Class Doctrine_Tests_Common_Annotations_Fixtures_ClassNoNamespaceNoComment not found#' + - '#Instantiated class Doctrine_Tests_Common_Annotations_Fixtures_ClassNoNamespaceNoComment not found#' + - '#Property Doctrine\\Tests\\Common\\Annotations\\DummyClassNonAnnotationProblem::\$foo has unknown class#' + - '#Call to an undefined method ReflectionClass::getUseStatements\(\)#' diff --git a/vendor/doctrine/cache/LICENSE b/vendor/doctrine/cache/LICENSE new file mode 100644 index 0000000..8c38cc1 --- /dev/null +++ b/vendor/doctrine/cache/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2015 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/doctrine/cache/README.md b/vendor/doctrine/cache/README.md new file mode 100644 index 0000000..bf9a7fe --- /dev/null +++ b/vendor/doctrine/cache/README.md @@ -0,0 +1,10 @@ +# Doctrine Cache + +[![Build Status](https://img.shields.io/travis/doctrine/cache/master.svg?style=flat-square)](http://travis-ci.org/doctrine/cache) +[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/doctrine/cache/master.svg?style=flat-square)](https://scrutinizer-ci.com/g/doctrine/cache/?branch=master) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/doctrine/cache/master.svg?style=flat-square)](https://scrutinizer-ci.com/g/doctrine/cache/?branch=master) + +[![Latest Stable Version](https://img.shields.io/packagist/v/doctrine/cache.svg?style=flat-square)](https://packagist.org/packages/doctrine/cache) +[![Total Downloads](https://img.shields.io/packagist/dt/doctrine/cache.svg?style=flat-square)](https://packagist.org/packages/doctrine/cache) + +Cache component extracted from the Doctrine Common project. [Documentation](https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/caching.html) diff --git a/vendor/doctrine/cache/UPGRADE.md b/vendor/doctrine/cache/UPGRADE.md new file mode 100644 index 0000000..e1f8a50 --- /dev/null +++ b/vendor/doctrine/cache/UPGRADE.md @@ -0,0 +1,16 @@ +# Upgrade to 1.4 + +## Minor BC Break: `Doctrine\Common\Cache\FileCache#$extension` is now `private`. + +If you need to override the value of `Doctrine\Common\Cache\FileCache#$extension`, then use the +second parameter of `Doctrine\Common\Cache\FileCache#__construct()` instead of overriding +the property in your own implementation. + +## Minor BC Break: file based caches paths changed + +`Doctrine\Common\Cache\FileCache`, `Doctrine\Common\Cache\PhpFileCache` and +`Doctrine\Common\Cache\FilesystemCache` are using a different cache paths structure. + +If you rely on warmed up caches for deployments, consider that caches generated +with `doctrine/cache` `<1.4` are not compatible with the new directory structure, +and will be ignored. diff --git a/vendor/doctrine/cache/composer.json b/vendor/doctrine/cache/composer.json new file mode 100644 index 0000000..d72c1e0 --- /dev/null +++ b/vendor/doctrine/cache/composer.json @@ -0,0 +1,52 @@ +{ + "name": "doctrine/cache", + "type": "library", + "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", + "keywords": [ + "php", + "cache", + "caching", + "abstraction", + "redis", + "memcached", + "couchdb", + "xcache", + "apcu" + ], + "homepage": "https://www.doctrine-project.org/projects/cache.html", + "license": "MIT", + "authors": [ + {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, + {"name": "Roman Borschel", "email": "roman@code-factory.org"}, + {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, + {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, + {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} + ], + "require": { + "php": "~7.1" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^7.0", + "predis/predis": "~1.0", + "doctrine/coding-standard": "^6.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "autoload": { + "psr-4": { "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" } + }, + "autoload-dev": { + "psr-4": { "Doctrine\\Tests\\": "tests/Doctrine/Tests" } + }, + "extra": { + "branch-alias": { + "dev-master": "1.9.x-dev" + } + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcCache.php new file mode 100644 index 0000000..138d49a --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcCache.php @@ -0,0 +1,105 @@ += 50500) { + $info['num_hits'] = $info['num_hits'] ?? $info['nhits']; + $info['num_misses'] = $info['num_misses'] ?? $info['nmisses']; + $info['start_time'] = $info['start_time'] ?? $info['stime']; + } + + return [ + Cache::STATS_HITS => $info['num_hits'], + Cache::STATS_MISSES => $info['num_misses'], + Cache::STATS_UPTIME => $info['start_time'], + Cache::STATS_MEMORY_USAGE => $info['mem_size'], + Cache::STATS_MEMORY_AVAILABLE => $sma['avail_mem'], + ]; + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcuCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcuCache.php new file mode 100644 index 0000000..a725213 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcuCache.php @@ -0,0 +1,106 @@ + $info['num_hits'], + Cache::STATS_MISSES => $info['num_misses'], + Cache::STATS_UPTIME => $info['start_time'], + Cache::STATS_MEMORY_USAGE => $info['mem_size'], + Cache::STATS_MEMORY_AVAILABLE => $sma['avail_mem'], + ]; + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ArrayCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ArrayCache.php new file mode 100644 index 0000000..1beb709 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ArrayCache.php @@ -0,0 +1,113 @@ +upTime = time(); + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + if (! $this->doContains($id)) { + $this->missesCount += 1; + + return false; + } + + $this->hitsCount += 1; + + return $this->data[$id][0]; + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + if (! isset($this->data[$id])) { + return false; + } + + $expiration = $this->data[$id][1]; + + if ($expiration && $expiration < time()) { + $this->doDelete($id); + + return false; + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + $this->data[$id] = [$data, $lifeTime ? time() + $lifeTime : false]; + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + unset($this->data[$id]); + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + $this->data = []; + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + return [ + Cache::STATS_HITS => $this->hitsCount, + Cache::STATS_MISSES => $this->missesCount, + Cache::STATS_UPTIME => $this->upTime, + Cache::STATS_MEMORY_USAGE => null, + Cache::STATS_MEMORY_AVAILABLE => null, + ]; + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php new file mode 100644 index 0000000..4569744 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php @@ -0,0 +1,90 @@ +hits + * Number of keys that have been requested and found present. + * + * - misses + * Number of items that have been requested and not found. + * + * - uptime + * Time that the server is running. + * + * - memory_usage + * Memory used by this server to store items. + * + * - memory_available + * Memory allowed to use for storage. + * + * @return array|null An associative array with server's statistics if available, NULL otherwise. + */ + public function getStats(); +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php new file mode 100644 index 0000000..43d414f --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php @@ -0,0 +1,325 @@ +namespace = (string) $namespace; + $this->namespaceVersion = null; + } + + /** + * Retrieves the namespace that prefixes all cache ids. + * + * @return string + */ + public function getNamespace() + { + return $this->namespace; + } + + /** + * {@inheritdoc} + */ + public function fetch($id) + { + return $this->doFetch($this->getNamespacedId($id)); + } + + /** + * {@inheritdoc} + */ + public function fetchMultiple(array $keys) + { + if (empty($keys)) { + return []; + } + + // note: the array_combine() is in place to keep an association between our $keys and the $namespacedKeys + $namespacedKeys = array_combine($keys, array_map([$this, 'getNamespacedId'], $keys)); + $items = $this->doFetchMultiple($namespacedKeys); + $foundItems = []; + + // no internal array function supports this sort of mapping: needs to be iterative + // this filters and combines keys in one pass + foreach ($namespacedKeys as $requestedKey => $namespacedKey) { + if (! isset($items[$namespacedKey]) && ! array_key_exists($namespacedKey, $items)) { + continue; + } + + $foundItems[$requestedKey] = $items[$namespacedKey]; + } + + return $foundItems; + } + + /** + * {@inheritdoc} + */ + public function saveMultiple(array $keysAndValues, $lifetime = 0) + { + $namespacedKeysAndValues = []; + foreach ($keysAndValues as $key => $value) { + $namespacedKeysAndValues[$this->getNamespacedId($key)] = $value; + } + + return $this->doSaveMultiple($namespacedKeysAndValues, $lifetime); + } + + /** + * {@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 deleteMultiple(array $keys) + { + return $this->doDeleteMultiple(array_map([$this, 'getNamespacedId'], $keys)); + } + + /** + * {@inheritdoc} + */ + public function delete($id) + { + return $this->doDelete($this->getNamespacedId($id)); + } + + /** + * {@inheritdoc} + */ + public function getStats() + { + return $this->doGetStats(); + } + + /** + * {@inheritDoc} + */ + public function flushAll() + { + return $this->doFlush(); + } + + /** + * {@inheritDoc} + */ + public function deleteAll() + { + $namespaceCacheKey = $this->getNamespaceCacheKey(); + $namespaceVersion = $this->getNamespaceVersion() + 1; + + if ($this->doSave($namespaceCacheKey, $namespaceVersion)) { + $this->namespaceVersion = $namespaceVersion; + + return true; + } + + return false; + } + + /** + * Prefixes the passed id with the configured namespace value. + * + * @param string $id The id to namespace. + * + * @return string The namespaced id. + */ + private function getNamespacedId(string $id) : string + { + $namespaceVersion = $this->getNamespaceVersion(); + + return sprintf('%s[%s][%s]', $this->namespace, $id, $namespaceVersion); + } + + /** + * Returns the namespace cache key. + */ + private function getNamespaceCacheKey() : string + { + return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace); + } + + /** + * Returns the namespace version. + */ + private function getNamespaceVersion() : int + { + if ($this->namespaceVersion !== null) { + return $this->namespaceVersion; + } + + $namespaceCacheKey = $this->getNamespaceCacheKey(); + $this->namespaceVersion = (int) $this->doFetch($namespaceCacheKey) ?: 1; + + return $this->namespaceVersion; + } + + /** + * Default implementation of doFetchMultiple. Each driver that supports multi-get should owerwrite it. + * + * @param array $keys Array of keys to retrieve from cache + * + * @return array Array of values retrieved for the given keys. + */ + protected function doFetchMultiple(array $keys) + { + $returnValues = []; + + foreach ($keys as $key) { + $item = $this->doFetch($key); + if ($item === false && ! $this->doContains($key)) { + continue; + } + + $returnValues[$key] = $item; + } + + return $returnValues; + } + + /** + * Fetches an entry from the cache. + * + * @param string $id The id of the cache entry to fetch. + * + * @return mixed|false The cached data or FALSE, if no cache entry exists for the given id. + */ + abstract protected function doFetch($id); + + /** + * Tests if an entry exists in the cache. + * + * @param string $id The cache id of the entry to check for. + * + * @return bool TRUE if a cache entry exists for the given cache id, FALSE otherwise. + */ + abstract protected function doContains($id); + + /** + * Default implementation of doSaveMultiple. Each driver that supports multi-put should override it. + * + * @param array $keysAndValues Array of keys and values to save in cache + * @param int $lifetime The lifetime. If != 0, sets a specific lifetime for these + * cache entries (0 => infinite lifeTime). + * + * @return bool TRUE if the operation was successful, FALSE if it wasn't. + */ + protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) + { + $success = true; + + foreach ($keysAndValues as $key => $value) { + if ($this->doSave($key, $value, $lifetime)) { + continue; + } + + $success = false; + } + + return $success; + } + + /** + * 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 bool TRUE if the entry was successfully stored in the cache, FALSE otherwise. + */ + abstract protected function doSave($id, $data, $lifeTime = 0); + + /** + * Default implementation of doDeleteMultiple. Each driver that supports multi-delete should override it. + * + * @param array $keys Array of keys to delete from cache + * + * @return bool TRUE if the operation was successful, FALSE if it wasn't + */ + protected function doDeleteMultiple(array $keys) + { + $success = true; + + foreach ($keys as $key) { + if ($this->doDelete($key)) { + continue; + } + + $success = false; + } + + return $success; + } + + /** + * Deletes a cache entry. + * + * @param string $id The cache id. + * + * @return bool TRUE if the cache entry was successfully deleted, FALSE otherwise. + */ + abstract protected function doDelete($id); + + /** + * Flushes all cache entries. + * + * @return bool TRUE if the cache entries were successfully flushed, FALSE otherwise. + */ + abstract protected function doFlush(); + + /** + * Retrieves cached information from the data store. + * + * @return array|null An associative array with server's statistics if available, NULL otherwise. + */ + abstract protected function doGetStats(); +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ChainCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ChainCache.php new file mode 100644 index 0000000..e9762a2 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ChainCache.php @@ -0,0 +1,187 @@ +cacheProviders = $cacheProviders instanceof Traversable + ? iterator_to_array($cacheProviders, false) + : array_values($cacheProviders); + } + + /** + * {@inheritDoc} + */ + public function setNamespace($namespace) + { + parent::setNamespace($namespace); + + foreach ($this->cacheProviders as $cacheProvider) { + $cacheProvider->setNamespace($namespace); + } + } + + /** + * {@inheritDoc} + */ + protected function doFetch($id) + { + foreach ($this->cacheProviders as $key => $cacheProvider) { + if ($cacheProvider->doContains($id)) { + $value = $cacheProvider->doFetch($id); + + // We populate all the previous cache layers (that are assumed to be faster) + for ($subKey = $key - 1; $subKey >= 0; $subKey--) { + $this->cacheProviders[$subKey]->doSave($id, $value); + } + + return $value; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + protected function doFetchMultiple(array $keys) + { + /** @var CacheProvider[] $traversedProviders */ + $traversedProviders = []; + $keysCount = count($keys); + $fetchedValues = []; + + foreach ($this->cacheProviders as $key => $cacheProvider) { + $fetchedValues = $cacheProvider->doFetchMultiple($keys); + + // We populate all the previous cache layers (that are assumed to be faster) + if (count($fetchedValues) === $keysCount) { + foreach ($traversedProviders as $previousCacheProvider) { + $previousCacheProvider->doSaveMultiple($fetchedValues); + } + + return $fetchedValues; + } + + $traversedProviders[] = $cacheProvider; + } + + return $fetchedValues; + } + + /** + * {@inheritDoc} + */ + protected function doContains($id) + { + foreach ($this->cacheProviders as $cacheProvider) { + if ($cacheProvider->doContains($id)) { + return true; + } + } + + return false; + } + + /** + * {@inheritDoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + $stored = true; + + foreach ($this->cacheProviders as $cacheProvider) { + $stored = $cacheProvider->doSave($id, $data, $lifeTime) && $stored; + } + + return $stored; + } + + /** + * {@inheritdoc} + */ + protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) + { + $stored = true; + + foreach ($this->cacheProviders as $cacheProvider) { + $stored = $cacheProvider->doSaveMultiple($keysAndValues, $lifetime) && $stored; + } + + return $stored; + } + + /** + * {@inheritDoc} + */ + protected function doDelete($id) + { + $deleted = true; + + foreach ($this->cacheProviders as $cacheProvider) { + $deleted = $cacheProvider->doDelete($id) && $deleted; + } + + return $deleted; + } + + /** + * {@inheritdoc} + */ + protected function doDeleteMultiple(array $keys) + { + $deleted = true; + + foreach ($this->cacheProviders as $cacheProvider) { + $deleted = $cacheProvider->doDeleteMultiple($keys) && $deleted; + } + + return $deleted; + } + + /** + * {@inheritDoc} + */ + protected function doFlush() + { + $flushed = true; + + foreach ($this->cacheProviders as $cacheProvider) { + $flushed = $cacheProvider->doFlush() && $flushed; + } + + return $flushed; + } + + /** + * {@inheritDoc} + */ + protected function doGetStats() + { + // We return all the stats from all adapters + $stats = []; + + foreach ($this->cacheProviders as $cacheProvider) { + $stats[] = $cacheProvider->doGetStats(); + } + + return $stats; + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php new file mode 100644 index 0000000..b94618e --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php @@ -0,0 +1,21 @@ +bucket = $bucket; + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + $id = $this->normalizeKey($id); + + try { + $document = $this->bucket->get($id); + } catch (Exception $e) { + return false; + } + + if ($document instanceof Document && $document->value !== false) { + return unserialize($document->value); + } + + return false; + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + $id = $this->normalizeKey($id); + + try { + $document = $this->bucket->get($id); + } catch (Exception $e) { + return false; + } + + if ($document instanceof Document) { + return ! $document->error; + } + + return false; + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + $id = $this->normalizeKey($id); + + $lifeTime = $this->normalizeExpiry($lifeTime); + + try { + $encoded = serialize($data); + + $document = $this->bucket->upsert($id, $encoded, [ + 'expiry' => (int) $lifeTime, + ]); + } catch (Exception $e) { + return false; + } + + if ($document instanceof Document) { + return ! $document->error; + } + + return false; + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + $id = $this->normalizeKey($id); + + try { + $document = $this->bucket->remove($id); + } catch (Exception $e) { + return $e->getCode() === self::KEY_NOT_FOUND; + } + + if ($document instanceof Document) { + return ! $document->error; + } + + return false; + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + $manager = $this->bucket->manager(); + + // Flush does not return with success or failure, and must be enabled per bucket on the server. + // Store a marker item so that we will know if it was successful. + $this->doSave(__METHOD__, true, 60); + + $manager->flush(); + + if ($this->doContains(__METHOD__)) { + $this->doDelete(__METHOD__); + + return false; + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $manager = $this->bucket->manager(); + $stats = $manager->info(); + $nodes = $stats['nodes']; + $node = $nodes[0]; + $interestingStats = $node['interestingStats']; + + return [ + Cache::STATS_HITS => $interestingStats['get_hits'], + Cache::STATS_MISSES => $interestingStats['cmd_get'] - $interestingStats['get_hits'], + Cache::STATS_UPTIME => $node['uptime'], + Cache::STATS_MEMORY_USAGE => $interestingStats['mem_used'], + Cache::STATS_MEMORY_AVAILABLE => $node['memoryFree'], + ]; + } + + private function normalizeKey(string $id) : string + { + $normalized = substr($id, 0, self::MAX_KEY_LENGTH); + + if ($normalized === false) { + return $id; + } + + return $normalized; + } + + /** + * Expiry treated as a unix timestamp instead of an offset if expiry is greater than 30 days. + * + * @src https://developer.couchbase.com/documentation/server/4.1/developer-guide/expiry.html + */ + private function normalizeExpiry(int $expiry) : int + { + if ($expiry > self::THIRTY_DAYS_IN_SECONDS) { + return time() + $expiry; + } + + return $expiry; + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CouchbaseCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CouchbaseCache.php new file mode 100644 index 0000000..2c62c2e --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CouchbaseCache.php @@ -0,0 +1,105 @@ +couchbase = $couchbase; + } + + /** + * Gets the Couchbase instance used by the cache. + * + * @return Couchbase|null + */ + public function getCouchbase() + { + return $this->couchbase; + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return $this->couchbase->get($id) ?: false; + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + return $this->couchbase->get($id) !== null; + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + if ($lifeTime > 30 * 24 * 3600) { + $lifeTime = time() + $lifeTime; + } + + return $this->couchbase->set($id, $data, (int) $lifeTime); + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return $this->couchbase->delete($id); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + return $this->couchbase->flush(); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $stats = $this->couchbase->getStats(); + $servers = $this->couchbase->getServers(); + $server = explode(':', $servers[0]); + $key = $server[0] . ':11210'; + $stats = $stats[$key]; + + return [ + Cache::STATS_HITS => $stats['get_hits'], + Cache::STATS_MISSES => $stats['get_misses'], + Cache::STATS_UPTIME => $stats['uptime'], + Cache::STATS_MEMORY_USAGE => $stats['bytes'], + Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'], + ]; + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ExtMongoDBCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ExtMongoDBCache.php new file mode 100644 index 0000000..b06f862 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ExtMongoDBCache.php @@ -0,0 +1,198 @@ +collection = $collection->withOptions(['typeMap' => null]); + $this->database = new Database($collection->getManager(), $collection->getDatabaseName()); + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + $document = $this->collection->findOne(['_id' => $id], [MongoDBCache::DATA_FIELD, MongoDBCache::EXPIRATION_FIELD]); + + if ($document === null) { + return false; + } + + if ($this->isExpired($document)) { + $this->createExpirationIndex(); + $this->doDelete($id); + + return false; + } + + return unserialize($document[MongoDBCache::DATA_FIELD]->getData()); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + $document = $this->collection->findOne(['_id' => $id], [MongoDBCache::EXPIRATION_FIELD]); + + if ($document === null) { + return false; + } + + if ($this->isExpired($document)) { + $this->createExpirationIndex(); + $this->doDelete($id); + + return false; + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + try { + $this->collection->updateOne( + ['_id' => $id], + [ + '$set' => [ + MongoDBCache::EXPIRATION_FIELD => ($lifeTime > 0 ? new UTCDateTime((time() + $lifeTime) * 1000): null), + MongoDBCache::DATA_FIELD => new Binary(serialize($data), Binary::TYPE_GENERIC), + ], + ], + ['upsert' => true] + ); + } catch (Exception $e) { + return false; + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + try { + $this->collection->deleteOne(['_id' => $id]); + } catch (Exception $e) { + return false; + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + try { + // Use remove() in lieu of drop() to maintain any collection indexes + $this->collection->deleteMany([]); + } catch (Exception $e) { + return false; + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $uptime = null; + $memoryUsage = null; + + try { + $serverStatus = $this->database->command([ + 'serverStatus' => 1, + 'locks' => 0, + 'metrics' => 0, + 'recordStats' => 0, + 'repl' => 0, + ])->toArray()[0]; + $uptime = $serverStatus['uptime'] ?? null; + } catch (Exception $e) { + } + + try { + $collStats = $this->database->command(['collStats' => $this->collection->getCollectionName()])->toArray()[0]; + $memoryUsage = $collStats['size'] ?? null; + } catch (Exception $e) { + } + + return [ + Cache::STATS_HITS => null, + Cache::STATS_MISSES => null, + Cache::STATS_UPTIME => $uptime, + Cache::STATS_MEMORY_USAGE => $memoryUsage, + Cache::STATS_MEMORY_AVAILABLE => null, + ]; + } + + /** + * Check if the document is expired. + */ + private function isExpired(BSONDocument $document) : bool + { + return isset($document[MongoDBCache::EXPIRATION_FIELD]) && + $document[MongoDBCache::EXPIRATION_FIELD] instanceof UTCDateTime && + $document[MongoDBCache::EXPIRATION_FIELD]->toDateTime() < new DateTime(); + } + + private function createExpirationIndex() : void + { + if ($this->expirationIndexCreated) { + return; + } + + $this->collection->createIndex([MongoDBCache::EXPIRATION_FIELD => 1], ['background' => true, 'expireAfterSeconds' => 0]); + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php new file mode 100644 index 0000000..4b48520 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php @@ -0,0 +1,281 @@ +umask = $umask; + + if (! $this->createPathIfNeeded($directory)) { + throw new InvalidArgumentException(sprintf( + 'The directory "%s" does not exist and could not be created.', + $directory + )); + } + + if (! is_writable($directory)) { + throw new InvalidArgumentException(sprintf( + 'The directory "%s" is not writable.', + $directory + )); + } + + // YES, this needs to be *after* createPathIfNeeded() + $this->directory = realpath($directory); + $this->extension = (string) $extension; + + $this->directoryStringLength = strlen($this->directory); + $this->extensionStringLength = strlen($this->extension); + $this->isRunningOnWindows = defined('PHP_WINDOWS_VERSION_BUILD'); + } + + /** + * Gets the cache directory. + * + * @return string + */ + public function getDirectory() + { + return $this->directory; + } + + /** + * Gets the cache file extension. + * + * @return string + */ + public function getExtension() + { + return $this->extension; + } + + /** + * @param string $id + * + * @return string + */ + protected function getFilename($id) + { + $hash = hash('sha256', $id); + + // This ensures that the filename is unique and that there are no invalid chars in it. + if ($id === '' + || ((strlen($id) * 2 + $this->extensionStringLength) > 255) + || ($this->isRunningOnWindows && ($this->directoryStringLength + 4 + strlen($id) * 2 + $this->extensionStringLength) > 258) + ) { + // Most filesystems have a limit of 255 chars for each path component. On Windows the the whole path is limited + // to 260 chars (including terminating null char). Using long UNC ("\\?\" prefix) does not work with the PHP API. + // And there is a bug in PHP (https://bugs.php.net/bug.php?id=70943) with path lengths of 259. + // So if the id in hex representation would surpass the limit, we use the hash instead. The prefix prevents + // collisions between the hash and bin2hex. + $filename = '_' . $hash; + } else { + $filename = bin2hex($id); + } + + return $this->directory + . DIRECTORY_SEPARATOR + . substr($hash, 0, 2) + . DIRECTORY_SEPARATOR + . $filename + . $this->extension; + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + $filename = $this->getFilename($id); + + return @unlink($filename) || ! file_exists($filename); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + foreach ($this->getIterator() as $name => $file) { + if ($file->isDir()) { + // Remove the intermediate directories which have been created to balance the tree. It only takes effect + // if the directory is empty. If several caches share the same directory but with different file extensions, + // the other ones are not removed. + @rmdir($name); + } elseif ($this->isFilenameEndingWithExtension($name)) { + // If an extension is set, only remove files which end with the given extension. + // If no extension is set, we have no other choice than removing everything. + @unlink($name); + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $usage = 0; + foreach ($this->getIterator() as $name => $file) { + if ($file->isDir() || ! $this->isFilenameEndingWithExtension($name)) { + continue; + } + + $usage += $file->getSize(); + } + + $free = disk_free_space($this->directory); + + return [ + Cache::STATS_HITS => null, + Cache::STATS_MISSES => null, + Cache::STATS_UPTIME => null, + Cache::STATS_MEMORY_USAGE => $usage, + Cache::STATS_MEMORY_AVAILABLE => $free, + ]; + } + + /** + * Create path if needed. + * + * @return bool TRUE on success or if path already exists, FALSE if path cannot be created. + */ + private function createPathIfNeeded(string $path) : bool + { + if (! is_dir($path)) { + if (@mkdir($path, 0777 & (~$this->umask), true) === false && ! is_dir($path)) { + return false; + } + } + + return true; + } + + /** + * Writes a string content to file in an atomic way. + * + * @param string $filename Path to the file where to write the data. + * @param string $content The content to write + * + * @return bool TRUE on success, FALSE if path cannot be created, if path is not writable or an any other error. + */ + protected function writeFile(string $filename, string $content) : bool + { + $filepath = pathinfo($filename, PATHINFO_DIRNAME); + + if (! $this->createPathIfNeeded($filepath)) { + return false; + } + + if (! is_writable($filepath)) { + return false; + } + + $tmpFile = tempnam($filepath, 'swap'); + @chmod($tmpFile, 0666 & (~$this->umask)); + + if (file_put_contents($tmpFile, $content) !== false) { + @chmod($tmpFile, 0666 & (~$this->umask)); + if (@rename($tmpFile, $filename)) { + return true; + } + + @unlink($tmpFile); + } + + return false; + } + + private function getIterator() : Iterator + { + return new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($this->directory, FilesystemIterator::SKIP_DOTS), + RecursiveIteratorIterator::CHILD_FIRST + ); + } + + /** + * @param string $name The filename + */ + private function isFilenameEndingWithExtension(string $name) : bool + { + return $this->extension === '' + || strrpos($name, $this->extension) === (strlen($name) - $this->extensionStringLength); + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FilesystemCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FilesystemCache.php new file mode 100644 index 0000000..8f34c9c --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FilesystemCache.php @@ -0,0 +1,102 @@ +getFilename($id); + + if (! is_file($filename)) { + return false; + } + + $resource = fopen($filename, 'r'); + $line = fgets($resource); + + if ($line !== false) { + $lifetime = (int) $line; + } + + if ($lifetime !== 0 && $lifetime < time()) { + fclose($resource); + + return false; + } + + while (($line = fgets($resource)) !== false) { + $data .= $line; + } + + fclose($resource); + + return unserialize($data); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + $lifetime = -1; + $filename = $this->getFilename($id); + + if (! is_file($filename)) { + return false; + } + + $resource = fopen($filename, 'r'); + $line = fgets($resource); + + if ($line !== false) { + $lifetime = (int) $line; + } + + fclose($resource); + + return $lifetime === 0 || $lifetime > time(); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + if ($lifeTime > 0) { + $lifeTime = time() + $lifeTime; + } + + $data = serialize($data); + $filename = $this->getFilename($id); + + return $this->writeFile($filename, $lifeTime . PHP_EOL . $data); + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php new file mode 100644 index 0000000..ee7ce98 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php @@ -0,0 +1,18 @@ +collection = $collection; + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + $document = $this->collection->findOne(['_id' => $id], [MongoDBCache::DATA_FIELD, MongoDBCache::EXPIRATION_FIELD]); + + if ($document === null) { + return false; + } + + if ($this->isExpired($document)) { + $this->createExpirationIndex(); + $this->doDelete($id); + + return false; + } + + return unserialize($document[MongoDBCache::DATA_FIELD]->bin); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + $document = $this->collection->findOne(['_id' => $id], [MongoDBCache::EXPIRATION_FIELD]); + + if ($document === null) { + return false; + } + + if ($this->isExpired($document)) { + $this->createExpirationIndex(); + $this->doDelete($id); + + return false; + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + try { + $result = $this->collection->update( + ['_id' => $id], + [ + '$set' => [ + MongoDBCache::EXPIRATION_FIELD => ($lifeTime > 0 ? new MongoDate(time() + $lifeTime) : null), + MongoDBCache::DATA_FIELD => new MongoBinData(serialize($data), MongoBinData::BYTE_ARRAY), + ], + ], + ['upsert' => true, 'multiple' => false] + ); + } catch (MongoCursorException $e) { + return false; + } + + return ($result['ok'] ?? 1) == 1; + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + $result = $this->collection->remove(['_id' => $id]); + + return ($result['ok'] ?? 1) == 1; + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + // Use remove() in lieu of drop() to maintain any collection indexes + $result = $this->collection->remove(); + + return ($result['ok'] ?? 1) == 1; + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $serverStatus = $this->collection->db->command([ + 'serverStatus' => 1, + 'locks' => 0, + 'metrics' => 0, + 'recordStats' => 0, + 'repl' => 0, + ]); + + $collStats = $this->collection->db->command(['collStats' => 1]); + + return [ + Cache::STATS_HITS => null, + Cache::STATS_MISSES => null, + Cache::STATS_UPTIME => $serverStatus['uptime'] ?? null, + Cache::STATS_MEMORY_USAGE => $collStats['size'] ?? null, + Cache::STATS_MEMORY_AVAILABLE => null, + ]; + } + + /** + * Check if the document is expired. + * + * @param array $document + */ + private function isExpired(array $document) : bool + { + return isset($document[MongoDBCache::EXPIRATION_FIELD]) && + $document[MongoDBCache::EXPIRATION_FIELD] instanceof MongoDate && + $document[MongoDBCache::EXPIRATION_FIELD]->sec < time(); + } + + private function createExpirationIndex() : void + { + if ($this->expirationIndexCreated) { + return; + } + + $this->expirationIndexCreated = true; + $this->collection->createIndex([MongoDBCache::EXPIRATION_FIELD => 1], ['background' => true, 'expireAfterSeconds' => 0]); + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcacheCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcacheCache.php new file mode 100644 index 0000000..42bbd2c --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcacheCache.php @@ -0,0 +1,104 @@ +memcache = $memcache; + } + + /** + * Gets the memcache instance used by the cache. + * + * @return Memcache|null + */ + public function getMemcache() + { + return $this->memcache; + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return $this->memcache->get($id); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + $flags = null; + $this->memcache->get($id, $flags); + + //if memcache has changed the value of "flags", it means the value exists + return $flags !== null; + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + if ($lifeTime > 30 * 24 * 3600) { + $lifeTime = time() + $lifeTime; + } + + return $this->memcache->set($id, $data, 0, (int) $lifeTime); + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + // Memcache::delete() returns false if entry does not exist + return $this->memcache->delete($id) || ! $this->doContains($id); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + return $this->memcache->flush(); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $stats = $this->memcache->getStats(); + + return [ + Cache::STATS_HITS => $stats['get_hits'], + Cache::STATS_MISSES => $stats['get_misses'], + Cache::STATS_UPTIME => $stats['uptime'], + Cache::STATS_MEMORY_USAGE => $stats['bytes'], + Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'], + ]; + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcachedCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcachedCache.php new file mode 100644 index 0000000..da966ae --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcachedCache.php @@ -0,0 +1,170 @@ +memcached = $memcached; + } + + /** + * Gets the memcached instance used by the cache. + * + * @return Memcached|null + */ + public function getMemcached() + { + return $this->memcached; + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return $this->memcached->get($id); + } + + /** + * {@inheritdoc} + */ + protected function doFetchMultiple(array $keys) + { + return $this->memcached->getMulti($keys) ?: []; + } + + /** + * {@inheritdoc} + */ + protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) + { + foreach (array_keys($keysAndValues) as $id) { + $this->validateCacheId($id); + } + + if ($lifetime > 30 * 24 * 3600) { + $lifetime = time() + $lifetime; + } + + return $this->memcached->setMulti($keysAndValues, $lifetime); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + $this->memcached->get($id); + + return $this->memcached->getResultCode() === Memcached::RES_SUCCESS; + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + $this->validateCacheId($id); + + if ($lifeTime > 30 * 24 * 3600) { + $lifeTime = time() + $lifeTime; + } + + return $this->memcached->set($id, $data, (int) $lifeTime); + } + + /** + * {@inheritdoc} + */ + protected function doDeleteMultiple(array $keys) + { + return $this->memcached->deleteMulti($keys) + || $this->memcached->getResultCode() === Memcached::RES_NOTFOUND; + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return $this->memcached->delete($id) + || $this->memcached->getResultCode() === Memcached::RES_NOTFOUND; + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + return $this->memcached->flush(); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $stats = $this->memcached->getStats(); + $servers = $this->memcached->getServerList(); + $key = $servers[0]['host'] . ':' . $servers[0]['port']; + $stats = $stats[$key]; + + return [ + Cache::STATS_HITS => $stats['get_hits'], + Cache::STATS_MISSES => $stats['get_misses'], + Cache::STATS_UPTIME => $stats['uptime'], + Cache::STATS_MEMORY_USAGE => $stats['bytes'], + Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'], + ]; + } + + /** + * Validate the cache id + * + * @see https://github.com/memcached/memcached/blob/1.5.12/doc/protocol.txt#L41-L49 + * + * @param string $id + * + * @return void + * + * @throws InvalidCacheId + */ + private function validateCacheId($id) + { + if (strlen($id) > self::CACHE_ID_MAX_LENGTH) { + throw InvalidCacheId::exceedsMaxLength($id, self::CACHE_ID_MAX_LENGTH); + } + + if (strpos($id, ' ') !== false) { + throw InvalidCacheId::containsUnauthorizedCharacter($id, ' '); + } + + if (preg_match('/[\t\r\n]/', $id) === 1) { + throw InvalidCacheId::containsControlCharacter($id); + } + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MongoDBCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MongoDBCache.php new file mode 100644 index 0000000..861e4dd --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MongoDBCache.php @@ -0,0 +1,112 @@ +provider = new LegacyMongoDBCache($collection); + } elseif ($collection instanceof Collection) { + $this->provider = new ExtMongoDBCache($collection); + } else { + throw new InvalidArgumentException('Invalid collection given - expected a MongoCollection or MongoDB\Collection instance'); + } + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return $this->provider->doFetch($id); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + return $this->provider->doContains($id); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + return $this->provider->doSave($id, $data, $lifeTime); + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return $this->provider->doDelete($id); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + return $this->provider->doFlush(); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + return $this->provider->doGetStats(); + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php new file mode 100644 index 0000000..d099d47 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php @@ -0,0 +1,22 @@ + infinite lifeTime). + * + * @return bool TRUE if the operation was successful, FALSE if it wasn't. + */ + public function saveMultiple(array $keysAndValues, $lifetime = 0); +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/PhpFileCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/PhpFileCache.php new file mode 100644 index 0000000..c061999 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/PhpFileCache.php @@ -0,0 +1,118 @@ +includeFileForId($id); + + if ($value === null) { + return false; + } + + if ($value['lifetime'] !== 0 && $value['lifetime'] < time()) { + return false; + } + + return $value['data']; + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + $value = $this->includeFileForId($id); + + if ($value === null) { + return false; + } + + return $value['lifetime'] === 0 || $value['lifetime'] > time(); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + if ($lifeTime > 0) { + $lifeTime = time() + $lifeTime; + } + + $filename = $this->getFilename($id); + + $value = [ + 'lifetime' => $lifeTime, + 'data' => $data, + ]; + + if (is_object($data) && method_exists($data, '__set_state')) { + $value = var_export($value, true); + $code = sprintf('writeFile($filename, $code); + } + + /** + * @return array|null + */ + private function includeFileForId(string $id) : ?array + { + $fileName = $this->getFilename($id); + + // note: error suppression is still faster than `file_exists`, `is_file` and `is_readable` + set_error_handler(self::$emptyErrorHandler); + + $value = include $fileName; + + restore_error_handler(); + + if (! isset($value['lifetime'])) { + return null; + } + + return $value; + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/PredisCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/PredisCache.php new file mode 100644 index 0000000..6430d52 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/PredisCache.php @@ -0,0 +1,143 @@ +client = $client; + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + $result = $this->client->get($id); + if ($result === null) { + return false; + } + + return unserialize($result); + } + + /** + * {@inheritdoc} + */ + protected function doFetchMultiple(array $keys) + { + $fetchedItems = call_user_func_array([$this->client, 'mget'], $keys); + + return array_map('unserialize', array_filter(array_combine($keys, $fetchedItems))); + } + + /** + * {@inheritdoc} + */ + protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) + { + if ($lifetime) { + $success = true; + + // Keys have lifetime, use SETEX for each of them + foreach ($keysAndValues as $key => $value) { + $response = (string) $this->client->setex($key, $lifetime, serialize($value)); + + if ($response == 'OK') { + continue; + } + + $success = false; + } + + return $success; + } + + // No lifetime, use MSET + $response = $this->client->mset(array_map(static function ($value) { + return serialize($value); + }, $keysAndValues)); + + return (string) $response == 'OK'; + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + return (bool) $this->client->exists($id); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + $data = serialize($data); + if ($lifeTime > 0) { + $response = $this->client->setex($id, $lifeTime, $data); + } else { + $response = $this->client->set($id, $data); + } + + return $response === true || $response == 'OK'; + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return $this->client->del($id) >= 0; + } + + /** + * {@inheritdoc} + */ + protected function doDeleteMultiple(array $keys) + { + return $this->client->del($keys) >= 0; + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + $response = $this->client->flushdb(); + + return $response === true || $response == 'OK'; + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $info = $this->client->info(); + + return [ + Cache::STATS_HITS => $info['Stats']['keyspace_hits'], + Cache::STATS_MISSES => $info['Stats']['keyspace_misses'], + Cache::STATS_UPTIME => $info['Server']['uptime_in_seconds'], + Cache::STATS_MEMORY_USAGE => $info['Memory']['used_memory'], + Cache::STATS_MEMORY_AVAILABLE => false, + ]; + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/RedisCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/RedisCache.php new file mode 100644 index 0000000..3245705 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/RedisCache.php @@ -0,0 +1,181 @@ +setOption(Redis::OPT_SERIALIZER, $this->getSerializerValue()); + $this->redis = $redis; + } + + /** + * Gets the redis instance used by the cache. + * + * @return Redis|null + */ + public function getRedis() + { + return $this->redis; + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return $this->redis->get($id); + } + + /** + * {@inheritdoc} + */ + protected function doFetchMultiple(array $keys) + { + $fetchedItems = array_combine($keys, $this->redis->mget($keys)); + + // Redis mget returns false for keys that do not exist. So we need to filter those out unless it's the real data. + $keysToFilter = array_keys(array_filter($fetchedItems, static function ($item) : bool { + return $item === false; + })); + + if ($keysToFilter) { + $multi = $this->redis->multi(Redis::PIPELINE); + foreach ($keysToFilter as $key) { + $multi->exists($key); + } + $existItems = array_filter($multi->exec()); + $missedItemKeys = array_diff_key($keysToFilter, $existItems); + $fetchedItems = array_diff_key($fetchedItems, array_fill_keys($missedItemKeys, true)); + } + + return $fetchedItems; + } + + /** + * {@inheritdoc} + */ + protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) + { + if ($lifetime) { + // Keys have lifetime, use SETEX for each of them + $multi = $this->redis->multi(Redis::PIPELINE); + foreach ($keysAndValues as $key => $value) { + $multi->setex($key, $lifetime, $value); + } + $succeeded = array_filter($multi->exec()); + + return count($succeeded) == count($keysAndValues); + } + + // No lifetime, use MSET + return (bool) $this->redis->mset($keysAndValues); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + $exists = $this->redis->exists($id); + + if (is_bool($exists)) { + return $exists; + } + + return $exists > 0; + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + if ($lifeTime > 0) { + return $this->redis->setex($id, $lifeTime, $data); + } + + return $this->redis->set($id, $data); + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return $this->redis->del($id) >= 0; + } + + /** + * {@inheritdoc} + */ + protected function doDeleteMultiple(array $keys) + { + return $this->redis->del($keys) >= 0; + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + return $this->redis->flushDB(); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $info = $this->redis->info(); + + return [ + Cache::STATS_HITS => $info['keyspace_hits'], + Cache::STATS_MISSES => $info['keyspace_misses'], + Cache::STATS_UPTIME => $info['uptime_in_seconds'], + Cache::STATS_MEMORY_USAGE => $info['used_memory'], + Cache::STATS_MEMORY_AVAILABLE => false, + ]; + } + + /** + * Returns the serializer constant to use. If Redis is compiled with + * igbinary support, that is used. Otherwise the default PHP serializer is + * used. + * + * @return int One of the Redis::SERIALIZER_* constants + */ + protected function getSerializerValue() + { + if (defined('Redis::SERIALIZER_IGBINARY') && extension_loaded('igbinary')) { + return Redis::SERIALIZER_IGBINARY; + } + + return Redis::SERIALIZER_PHP; + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/SQLite3Cache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/SQLite3Cache.php new file mode 100644 index 0000000..56deb07 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/SQLite3Cache.php @@ -0,0 +1,206 @@ +sqlite = $sqlite; + $this->table = (string) $table; + + $this->ensureTableExists(); + } + + private function ensureTableExists() : void + { + $this->sqlite->exec( + sprintf( + 'CREATE TABLE IF NOT EXISTS %s(%s TEXT PRIMARY KEY NOT NULL, %s BLOB, %s INTEGER)', + $this->table, + static::ID_FIELD, + static::DATA_FIELD, + static::EXPIRATION_FIELD + ) + ); + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + $item = $this->findById($id); + + if (! $item) { + return false; + } + + return unserialize($item[self::DATA_FIELD]); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + return $this->findById($id, false) !== null; + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + $statement = $this->sqlite->prepare(sprintf( + 'INSERT OR REPLACE INTO %s (%s) VALUES (:id, :data, :expire)', + $this->table, + implode(',', $this->getFields()) + )); + + $statement->bindValue(':id', $id); + $statement->bindValue(':data', serialize($data), SQLITE3_BLOB); + $statement->bindValue(':expire', $lifeTime > 0 ? time() + $lifeTime : null); + + return $statement->execute() instanceof SQLite3Result; + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + [$idField] = $this->getFields(); + + $statement = $this->sqlite->prepare(sprintf( + 'DELETE FROM %s WHERE %s = :id', + $this->table, + $idField + )); + + $statement->bindValue(':id', $id); + + return $statement->execute() instanceof SQLite3Result; + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + return $this->sqlite->exec(sprintf('DELETE FROM %s', $this->table)); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + // no-op. + } + + /** + * Find a single row by ID. + * + * @param mixed $id + * + * @return array|null + */ + private function findById($id, bool $includeData = true) : ?array + { + [$idField] = $fields = $this->getFields(); + + if (! $includeData) { + $key = array_search(static::DATA_FIELD, $fields); + unset($fields[$key]); + } + + $statement = $this->sqlite->prepare(sprintf( + 'SELECT %s FROM %s WHERE %s = :id LIMIT 1', + implode(',', $fields), + $this->table, + $idField + )); + + $statement->bindValue(':id', $id, SQLITE3_TEXT); + + $item = $statement->execute()->fetchArray(SQLITE3_ASSOC); + + if ($item === false) { + return null; + } + + if ($this->isExpired($item)) { + $this->doDelete($id); + + return null; + } + + return $item; + } + + /** + * Gets an array of the fields in our table. + * + * @return array + */ + private function getFields() : array + { + return [static::ID_FIELD, static::DATA_FIELD, static::EXPIRATION_FIELD]; + } + + /** + * Check if the item is expired. + * + * @param array $item + */ + private function isExpired(array $item) : bool + { + return isset($item[static::EXPIRATION_FIELD]) && + $item[self::EXPIRATION_FIELD] !== null && + $item[self::EXPIRATION_FIELD] < time(); + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Version.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Version.php new file mode 100644 index 0000000..834b5b7 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Version.php @@ -0,0 +1,8 @@ + $info['total_hit_count'], + Cache::STATS_MISSES => $info['total_miss_count'], + Cache::STATS_UPTIME => $info['total_cache_uptime'], + Cache::STATS_MEMORY_USAGE => $meminfo['memory_total'], + Cache::STATS_MEMORY_AVAILABLE => $meminfo['memory_free'], + ]; + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/XcacheCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/XcacheCache.php new file mode 100644 index 0000000..9b3a485 --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/XcacheCache.php @@ -0,0 +1,104 @@ +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); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + $this->checkAuthorization(); + + xcache_clear_cache(XC_TYPE_VAR); + + return true; + } + + /** + * Checks that xcache.admin.enable_auth is Off. + * + * @return void + * + * @throws BadMethodCallException When xcache.admin.enable_auth is On. + */ + protected function checkAuthorization() + { + 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.' + ); + } + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $this->checkAuthorization(); + + $info = xcache_info(XC_TYPE_VAR, 0); + + return [ + Cache::STATS_HITS => $info['hits'], + Cache::STATS_MISSES => $info['misses'], + Cache::STATS_UPTIME => null, + Cache::STATS_MEMORY_USAGE => $info['size'], + Cache::STATS_MEMORY_AVAILABLE => $info['avail'], + ]; + } +} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ZendDataCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ZendDataCache.php new file mode 100644 index 0000000..a6b67ef --- /dev/null +++ b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ZendDataCache.php @@ -0,0 +1,69 @@ +getNamespace(); + if (empty($namespace)) { + return zend_shm_cache_clear(); + } + + return zend_shm_cache_clear($namespace); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + return null; + } +} diff --git a/vendor/doctrine/collections/.doctrine-project.json b/vendor/doctrine/collections/.doctrine-project.json new file mode 100644 index 0000000..57d2fef --- /dev/null +++ b/vendor/doctrine/collections/.doctrine-project.json @@ -0,0 +1,17 @@ +{ + "active": true, + "name": "Collections", + "slug": "collections", + "docsSlug": "doctrine-collections", + "versions": [ + { + "name": "master", + "branchName": "master", + "slug": "latest", + "aliases": [ + "current", + "stable" + ] + } + ] +} diff --git a/vendor/doctrine/collections/CONTRIBUTING.md b/vendor/doctrine/collections/CONTRIBUTING.md new file mode 100644 index 0000000..83437da --- /dev/null +++ b/vendor/doctrine/collections/CONTRIBUTING.md @@ -0,0 +1,54 @@ +# Contribute to Doctrine + +Thank you for contributing to Doctrine! + +Before we can merge your Pull-Request here are some guidelines that you need to follow. +These guidelines exist not to annoy you, but to keep the code base clean, +unified and future proof. + +## We only accept PRs to "master" + +Our branching strategy is "everything to master first", even +bugfixes and we then merge them into the stable branches. You should only +open pull requests against the master branch. Otherwise we cannot accept the PR. + +There is one exception to the rule, when we merged a bug into some stable branches +we do occasionally accept pull requests that merge the same bug fix into earlier +branches. + +## Coding Standard + +We use the [Doctrine Coding Standard](https://github.com/doctrine/coding-standard). + +## Unit-Tests + +Please try to add a test for your pull-request. + +* If you want to contribute new functionality add unit- or functional tests + depending on the scope of the feature. + +You can run the unit-tests by calling ``vendor/bin/phpunit`` from the root of the project. +It will run all the project tests. + +In order to do that, you will need a fresh copy of doctrine/collections, and you +will have to run a composer installation in the project: + +```sh +git clone git@github.com:doctrine/collections.git +cd collections +curl -sS https://getcomposer.org/installer | php -- +./composer.phar install +``` + +## Travis + +We automatically run your pull request through [Travis CI](https://www.travis-ci.org) +against supported PHP versions. If you break the tests, we cannot merge your code, +so please make sure that your code is working before opening up a Pull-Request. + +## Getting merged + +Please allow us time to review your pull requests. We will give our best to review +everything as fast as possible, but cannot always live up to our own expectations. + +Thank you very much again for your contribution! diff --git a/vendor/doctrine/collections/LICENSE b/vendor/doctrine/collections/LICENSE new file mode 100644 index 0000000..5e781fc --- /dev/null +++ b/vendor/doctrine/collections/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2013 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/doctrine/collections/README.md b/vendor/doctrine/collections/README.md new file mode 100644 index 0000000..95fcdf8 --- /dev/null +++ b/vendor/doctrine/collections/README.md @@ -0,0 +1,93 @@ +# Doctrine Collections + +[![Build Status](https://travis-ci.org/doctrine/collections.svg?branch=master)](https://travis-ci.org/doctrine/collections) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/collections/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/collections/?branch=master) +[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/collections/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/collections/?branch=master) + +Collections Abstraction library + +## Changelog + +### v1.6.1 + +This release, combined with the release of [`doctrine/collections` `v1.6.1`](https://github.com/doctrine/collections/releases/tag/v1.6.1), +fixes an issue where parsing annotations was not possible +for classes within `doctrine/collections`. + +Specifically, `v1.6.0` introduced Psalm-specific annotations +such as (for example) `@template` and `@template-implements`, +which were both incorrectly recognized as `@template`. + +`@template` has therefore been removed, and instead we use +the prefixed `@psalm-template`, which is no longer parsed +by `doctrine/collections` `v1.6.1` + +Total issues resolved: **1** + +- [186: Use `@psalm-template` annotation to avoid clashes](https://github.com/doctrine/collections/pull/186) thanks to @muglug + +### v1.6.0 + +This release bumps the minimum required PHP version to 7.1.3. + +Following improvements were introduced: + + * `ArrayCollection#filter()` now allows filtering by key, value or both. + * When using the `ClosureExpressionVisitor` over objects with a defined + accessor and property, the accessor is prioritised. + * Updated testing tools and coding standards, autoloading, which also + led to marginal performance improvements + * Introduced generic type docblock declarations from [psalm](https://github.com/vimeo/psalm), + which should allow users to declare `/** @var Collection */` + in their code, and leverage the type propagation deriving from that. + +Total issues resolved: **16** + +- [127: Use PSR-4](https://github.com/doctrine/collections/pull/127) thanks to @Nyholm +- [129: Remove space in method declaration](https://github.com/doctrine/collections/pull/129) thanks to @bounoable +- [130: Update build to add PHPCS and PHPStan](https://github.com/doctrine/collections/pull/130) thanks to @lcobucci +- [131: ClosureExpressionVisitor > Don't duplicate the accessor when the field already starts with it](https://github.com/doctrine/collections/pull/131) thanks to @ruudk +- [139: Apply Doctrine CS 2.1](https://github.com/doctrine/collections/pull/139) thanks to @Majkl578 +- [142: CS 4.0, version composer.lock, merge stages](https://github.com/doctrine/collections/pull/142) thanks to @Majkl578 +- [144: Update to PHPUnit 7](https://github.com/doctrine/collections/pull/144) thanks to @carusogabriel +- [146: Update changelog for v1.4.0 and v1.5.0](https://github.com/doctrine/collections/pull/146) thanks to @GromNaN +- [154: Update index.rst](https://github.com/doctrine/collections/pull/154) thanks to @chraiet +- [158: Extract Selectable method into own documentation section](https://github.com/doctrine/collections/pull/158) thanks to @SenseException +- [160: Update homepage](https://github.com/doctrine/collections/pull/160) thanks to @Majkl578 +- [165: Allow `ArrayCollection#filter()` to filter by key, value or both](https://github.com/doctrine/collections/issues/165) thanks to @0x13a +- [167: Allow `ArrayCollection#filter()` to filter by key and also value](https://github.com/doctrine/collections/pull/167) thanks to @0x13a +- [175: CI: Test against PHP 7.4snapshot instead of nightly (8.0)](https://github.com/doctrine/collections/pull/175) thanks to @Majkl578 +- [177: Generify collections using Psalm](https://github.com/doctrine/collections/pull/177) thanks to @nschoellhorn +- [178: Updated doctrine/coding-standard to 6.0](https://github.com/doctrine/collections/pull/178) thanks to @patrickjahns + +### v1.5.0 + +* [Require PHP 7.1+](https://github.com/doctrine/collections/pull/105) +* [Drop HHVM support](https://github.com/doctrine/collections/pull/118) + +### v1.4.0 + +* [Require PHP 5.6+](https://github.com/doctrine/collections/pull/105) +* [Add `ArrayCollection::createFrom()`](https://github.com/doctrine/collections/pull/91) +* [Support non-camel-case naming](https://github.com/doctrine/collections/pull/57) +* [Comparison `START_WITH`, `END_WITH`](https://github.com/doctrine/collections/pull/78) +* [Comparison `MEMBER_OF`](https://github.com/doctrine/collections/pull/66) +* [Add Contributing guide](https://github.com/doctrine/collections/pull/103) + +### v1.3.0 + +* [Explicit casting of first and max results in criteria API](https://github.com/doctrine/collections/pull/26) +* [Keep keys when using `ArrayCollection#matching()` with sorting](https://github.com/doctrine/collections/pull/49) +* [Made `AbstractLazyCollection#$initialized` protected for extensibility](https://github.com/doctrine/collections/pull/52) + +### v1.2.0 + +* Add a new ``AbstractLazyCollection`` + +### v1.1.0 + +* Deprecated ``Comparison::IS``, because it's only there for SQL semantics. + These are fixed in the ORM instead. +* Add ``Comparison::CONTAINS`` to perform partial string matches: + + $criteria->andWhere($criteria->expr()->contains('property', 'Foo')); diff --git a/vendor/doctrine/collections/composer.json b/vendor/doctrine/collections/composer.json new file mode 100644 index 0000000..828a7d2 --- /dev/null +++ b/vendor/doctrine/collections/composer.json @@ -0,0 +1,42 @@ +{ + "name": "doctrine/collections", + "type": "library", + "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", + "keywords": [ + "php", + "collections", + "array", + "iterators" + ], + "homepage": "https://www.doctrine-project.org/projects/collections.html", + "license": "MIT", + "authors": [ + {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, + {"name": "Roman Borschel", "email": "roman@code-factory.org"}, + {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, + {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, + {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} + ], + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "phpunit/phpunit": "^7.0", + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan-shim": "^0.9.2", + "vimeo/psalm": "^3.2.2" + }, + "autoload": { + "psr-4": { "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" } + }, + "autoload-dev": { + "psr-4": { + "Doctrine\\Tests\\": "tests/Doctrine/Tests" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + } +} diff --git a/vendor/doctrine/collections/docs/en/derived-collections.rst b/vendor/doctrine/collections/docs/en/derived-collections.rst new file mode 100644 index 0000000..03d9da5 --- /dev/null +++ b/vendor/doctrine/collections/docs/en/derived-collections.rst @@ -0,0 +1,26 @@ +Derived Collections +=================== + +You can create custom collection classes by extending the +``Doctrine\Common\Collections\ArrayCollection`` class. If the +``__construct`` semantics are different from the default ``ArrayCollection`` +you can override the ``createFrom`` method: + +.. code-block:: php + final class DerivedArrayCollection extends ArrayCollection + { + /** @var \stdClass */ + private $foo; + + public function __construct(\stdClass $foo, array $elements = []) + { + $this->foo = $foo; + + parent::__construct($elements); + } + + protected function createFrom(array $elements) : self + { + return new static($this->foo, $elements); + } + } diff --git a/vendor/doctrine/collections/docs/en/expression-builder.rst b/vendor/doctrine/collections/docs/en/expression-builder.rst new file mode 100644 index 0000000..ad4055b --- /dev/null +++ b/vendor/doctrine/collections/docs/en/expression-builder.rst @@ -0,0 +1,173 @@ +Expression Builder +================== + +The Expression Builder is a convenient fluent interface for +building expressions to be used with the ``Doctrine\Common\Collections\Criteria`` +class: + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $criteria = new Criteria(); + $criteria->where($expressionBuilder->eq('name', 'jwage')); + $criteria->orWhere($expressionBuilder->eq('name', 'romanb')); + + $collection->matching($criteria); + +The ``ExpressionBuilder`` has the following API: + +andX +---- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->andX( + $expressionBuilder->eq('foo', 1), + $expressionBuilder->eq('bar', 1) + ); + + $collection->matching(new Criteria($expression)); + +orX +--- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->orX( + $expressionBuilder->eq('foo', 1), + $expressionBuilder->eq('bar', 1) + ); + + $collection->matching(new Criteria($expression)); + +eq +--- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->eq('foo', 1); + + $collection->matching(new Criteria($expression)); + +gt +--- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->gt('foo', 1); + + $collection->matching(new Criteria($expression)); + +lt +--- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->lt('foo', 1); + + $collection->matching(new Criteria($expression)); + +gte +--- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->gte('foo', 1); + + $collection->matching(new Criteria($expression)); + +lte +--- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->lte('foo', 1); + + $collection->matching(new Criteria($expression)); + +neq +--- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->neq('foo', 1); + + $collection->matching(new Criteria($expression)); + +isNull +------ + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->isNull('foo'); + + $collection->matching(new Criteria($expression)); + +in +--- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->in('foo', ['value1', 'value2']); + + $collection->matching(new Criteria($expression)); + +notIn +----- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->notIn('foo', ['value1', 'value2']); + + $collection->matching(new Criteria($expression)); + +contains +-------- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->contains('foo', 'value1'); + + $collection->matching(new Criteria($expression)); + +memberOf +-------- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->memberOf('foo', ['value1', 'value2']); + + $collection->matching(new Criteria($expression)); + +startsWith +---------- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->startsWith('foo', 'hello'); + + $collection->matching(new Criteria($expression)); + +endsWith +-------- + +.. code-block:: php + $expressionBuilder = Criteria::expr(); + + $expression = $expressionBuilder->endsWith('foo', 'world'); + + $collection->matching(new Criteria($expression)); diff --git a/vendor/doctrine/collections/docs/en/expressions.rst b/vendor/doctrine/collections/docs/en/expressions.rst new file mode 100644 index 0000000..db943b2 --- /dev/null +++ b/vendor/doctrine/collections/docs/en/expressions.rst @@ -0,0 +1,102 @@ +Expressions +=========== + +The ``Doctrine\Common\Collections\Expr\Comparison`` class +can be used to create expressions to be used with the +``Doctrine\Common\Collections\Criteria`` class. It has the +following operator constants: + +- ``Comparison::EQ`` +- ``Comparison::NEQ`` +- ``Comparison::LT`` +- ``Comparison::LTE`` +- ``Comparison::GT`` +- ``Comparison::GTE`` +- ``Comparison::IS`` +- ``Comparison::IN`` +- ``Comparison::NIN`` +- ``Comparison::CONTAINS`` +- ``Comparison::MEMBER_OF`` +- ``Comparison::STARTS_WITH`` +- ``Comparison::ENDS_WITH`` + +The ``Doctrine\Common\Collections\Criteria`` class has the following +API to be used with expressions: + +where +----- + +Sets the where expression to evaluate when this Criteria is searched for. + +.. code-block:: php + $expr = new Comparison('key', Comparison::EQ, 'value'); + + $criteria->where($expr); + +andWhere +-------- + +Appends the where expression to evaluate when this Criteria is searched for +using an AND with previous expression. + +.. code-block:: php + $expr = new Comparison('key', Comparison::EQ, 'value'); + + $criteria->andWhere($expr); + +orWhere +------- + +Appends the where expression to evaluate when this Criteria is searched for +using an OR with previous expression. + +.. code-block:: php + $expr1 = new Comparison('key', Comparison::EQ, 'value1'); + $expr2 = new Comparison('key', Comparison::EQ, 'value2'); + + $criteria->where($expr1); + $criteria->orWhere($expr2); + +orderBy +------- + +Sets the ordering of the result of this Criteria. + +.. code-block:: php + $criteria->orderBy(['name' => Criteria::ASC]); + +setFirstResult +-------------- + +Set the number of first result that this Criteria should return. + +.. code-block:: php + $criteria->setFirstResult(0); + +getFirstResult +-------------- + +Gets the current first result option of this Criteria. + +.. code-block:: php + $criteria->setFirstResult(10); + + echo $criteria->getFirstResult(); // 10 + +setMaxResults +------------- + +Sets the max results that this Criteria should return. + +.. code-block:: php + $criteria->setMaxResults(20); + +getMaxResults +------------- + +Gets the current max results option of this Criteria. + +.. code-block:: php + $criteria->setMaxResults(20); + + echo $criteria->getMaxResults(); // 20 diff --git a/vendor/doctrine/collections/docs/en/index.rst b/vendor/doctrine/collections/docs/en/index.rst new file mode 100644 index 0000000..447f76e --- /dev/null +++ b/vendor/doctrine/collections/docs/en/index.rst @@ -0,0 +1,327 @@ +Introduction +============ + +Doctrine Collections is a library that contains classes for working with +arrays of data. Here is an example using the simple +``Doctrine\Common\Collections\ArrayCollection`` class: + +.. code-block:: php + filter(function($count) { + return $count > 1; + }); // [2, 3] + +Collection Methods +================== + +Doctrine Collections provides an interface named ``Doctrine\Common\Collections\Collection`` +that resembles the nature of a regular PHP array. That is, +it is essentially an **ordered map** 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 preferable. +To use an external iterator simply use the foreach language construct to +iterate over the collection, which calls ``getIterator()`` internally, or +explicitly retrieve an iterator though ``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. + +The methods available on the interface are: + +add +--- + +Adds an element at the end of the collection. + +.. code-block:: php + $collection->add('test'); + +clear +----- + +Clears the collection, removing all elements. + +.. code-block:: php + $collection->clear(); + +contains +-------- + +Checks whether an element is contained in the collection. This is an O(n) operation, where n is the size of the collection. + +.. code-block:: php + $collection = new Collection(['test']); + + $contains = $collection->contains('test'); // true + +containsKey +----------- + +Checks whether the collection contains an element with the specified key/index. + +.. code-block:: php + $collection = new Collection(['test' => true]); + + $contains = $collection->containsKey('test'); // true + +current +------- + +Gets the element of the collection at the current iterator position. + +.. code-block:: php + $collection = new Collection(['first', 'second', 'third']); + + $current = $collection->current(); // first + +get +--- + +Gets the element at the specified key/index. + +.. code-block:: php + $collection = new Collection([ + 'key' => 'value', + ]); + + $value = $collection->get('key'); // value + +getKeys +------- + +Gets all keys/indices of the collection. + +.. code-block:: php + $collection = new Collection(['a', 'b', 'c']); + + $keys = $collection->getKeys(); // [0, 1, 2] + +getValues +--------- + +Gets all values of the collection. + +.. code-block:: php + $collection = new Collection([ + 'key1' => 'value1', + 'key2' => 'value2', + 'key3' => 'value3', + ]); + + $values = $collection->getValues(); // ['value1', 'value2', 'value3'] + +isEmpty +------- + +Checks whether the collection is empty (contains no elements). + +.. code-block:: php + $collection = new Collection(['a', 'b', 'c']); + + $isEmpty = $collection->isEmpty(); // false + +first +----- + +Sets the internal iterator to the first element in the collection and returns this element. + +.. code-block:: php + $collection = new Collection(['first', 'second', 'third']); + + $first = $collection->first(); // first + +exists +------ + +Tests for the existence of an element that satisfies the given predicate. + +.. code-block:: php + $collection = new Collection(['first', 'second', 'third']); + + $exists = $collection->exists(function($key, $value) { + return $value === 'first'; + }); // true + +filter +------ + +Returns all the elements of this collection that satisfy the predicate. The order of the elements is preserved. + +.. code-block:: php + $collection = new ArrayCollection([1, 2, 3]); + + $filteredCollection = $collection->filter(function($count) { + return $count > 1; + }); // [2, 3] + +forAll +------ + +Tests whether the given predicate holds for all elements of this collection. + +.. code-block:: php + $collection = new ArrayCollection([1, 2, 3]); + + $forAll = $collection->forAll(function($key, $value) { + return $value > 1; + }); // false + +indexOf +------- + +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. + +.. code-block:: php + $collection = new ArrayCollection([1, 2, 3]); + + $indexOf = $collection->indexOf(3); // 2 + +key +--- + +Gets the key/index of the element at the current iterator position. + +.. code-block:: php + $collection = new ArrayCollection([1, 2, 3]); + + $collection->next(); + + $key = $collection->key(); // 1 + +last +---- + +Sets the internal iterator to the last element in the collection and returns this element. + +.. code-block:: php + $collection = new ArrayCollection([1, 2, 3]); + + $last = $collection->last(); // 3 + +map +--- + +Applies the given function to each element in the collection and returns a new collection with the elements returned by the function. + +.. code-block:: php + $collection = new ArrayCollection([1, 2, 3]); + + $mappedCollection = $collection->map(function($value) { + return $value + 1; + }); // [2, 3, 4] + +next +---- + +Moves the internal iterator position to the next element and returns this element. + +.. code-block:: php + $collection = new ArrayCollection([1, 2, 3]); + + $next = $collection->next(); // 2 + +partition +--------- + +Partitions this collection in two collections according to a predicate. Keys are preserved in the resulting collections. + +.. code-block:: php + $collection = new ArrayCollection([1, 2, 3]); + + $mappedCollection = $collection->partition(function($key, $value) { + return $value > 1 + }); // [[2, 3], [1]] + +remove +------ + +Removes the element at the specified index from the collection. + +.. code-block:: php + $collection = new ArrayCollection([1, 2, 3]); + + $collection->remove(0); // [2, 3] + +removeElement +------------- + +Removes the specified element from the collection, if it is found. + +.. code-block:: php + $collection = new ArrayCollection([1, 2, 3]); + + $collection->removeElement(3); // [1, 2] + +set +--- + +Sets an element in the collection at the specified key/index. + +.. code-block:: php + $collection = new ArrayCollection(); + + $collection->set('name', 'jwage'); + +slice +----- + +Extracts 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. + +.. code-block:: php + $collection = new ArrayCollection([0, 1, 2, 3, 4, 5]); + + $slice = $collection->slice(1, 2); // [1, 2] + +toArray +------- + +Gets a native PHP array representation of the collection. + +.. code-block:: php + $collection = new ArrayCollection([0, 1, 2, 3, 4, 5]); + + $array = $collection->toArray(); // [0, 1, 2, 3, 4, 5] + +Selectable Methods +================== + +Some Doctrine Collections, like ``Doctrine\Common\Collections\ArrayCollection``, +implement an interface named ``Doctrine\Common\Collections\Selectable`` +that offers the usage of a powerful expressions API, where conditions +can be applied to a collection to get a result with matching elements +only. + +matching +-------- + +Selects all elements from a selectable that match the expression and +returns a new collection containing these elements. + +.. code-block:: php + use Doctrine\Common\Collections\Criteria; + use Doctrine\Common\Collections\Expr\Comparison; + + $collection = new ArrayCollection([ + [ + 'name' => 'jwage', + ], + [ + 'name' => 'romanb', + ], + ]); + + $expr = new Comparison('name', '=', 'jwage'); + + $criteria = new Criteria(); + + $criteria->where($expr); + + $matched = $collection->matching($criteria); // ['jwage'] + +You can read more about expressions :ref:`here `. diff --git a/vendor/doctrine/collections/docs/en/lazy-collections.rst b/vendor/doctrine/collections/docs/en/lazy-collections.rst new file mode 100644 index 0000000..b9cafb6 --- /dev/null +++ b/vendor/doctrine/collections/docs/en/lazy-collections.rst @@ -0,0 +1,26 @@ +Lazy Collections +================ + +To create a lazy collection you can extend the +``Doctrine\Common\Collections\AbstractLazyCollection`` class +and define the ``doInitialize`` method. Here is an example where +we lazily query the database for a collection of user records: + +.. code-block:: php + use Doctrine\DBAL\Connection; + + class UsersLazyCollection extends AbstractLazyCollection + { + /** @var Connection */ + private $connection; + + public function __construct(Connection $connection) + { + $this->connection = $connection; + } + + protected function doInitialize() : void + { + $this->collection = $this->connection->fetchAll('SELECT * FROM users'); + } + } diff --git a/vendor/doctrine/collections/docs/en/sidebar.rst b/vendor/doctrine/collections/docs/en/sidebar.rst new file mode 100644 index 0000000..69279a0 --- /dev/null +++ b/vendor/doctrine/collections/docs/en/sidebar.rst @@ -0,0 +1,8 @@ +.. toctree:: + :depth: 3 + + index + expressions + expression-builder + derived-collections + lazy-collections diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/AbstractLazyCollection.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/AbstractLazyCollection.php new file mode 100644 index 0000000..cfdd144 --- /dev/null +++ b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/AbstractLazyCollection.php @@ -0,0 +1,354 @@ + + */ +abstract class AbstractLazyCollection implements Collection +{ + /** + * The backed collection to use + * + * @psalm-var Collection + * @var Collection + */ + protected $collection; + + /** @var bool */ + protected $initialized = false; + + /** + * {@inheritDoc} + */ + public function count() + { + $this->initialize(); + + return $this->collection->count(); + } + + /** + * {@inheritDoc} + */ + public function add($element) + { + $this->initialize(); + + return $this->collection->add($element); + } + + /** + * {@inheritDoc} + */ + public function clear() + { + $this->initialize(); + $this->collection->clear(); + } + + /** + * {@inheritDoc} + */ + public function contains($element) + { + $this->initialize(); + + return $this->collection->contains($element); + } + + /** + * {@inheritDoc} + */ + public function isEmpty() + { + $this->initialize(); + + return $this->collection->isEmpty(); + } + + /** + * {@inheritDoc} + */ + public function remove($key) + { + $this->initialize(); + + return $this->collection->remove($key); + } + + /** + * {@inheritDoc} + */ + public function removeElement($element) + { + $this->initialize(); + + return $this->collection->removeElement($element); + } + + /** + * {@inheritDoc} + */ + public function containsKey($key) + { + $this->initialize(); + + return $this->collection->containsKey($key); + } + + /** + * {@inheritDoc} + */ + public function get($key) + { + $this->initialize(); + + return $this->collection->get($key); + } + + /** + * {@inheritDoc} + */ + public function getKeys() + { + $this->initialize(); + + return $this->collection->getKeys(); + } + + /** + * {@inheritDoc} + */ + public function getValues() + { + $this->initialize(); + + return $this->collection->getValues(); + } + + /** + * {@inheritDoc} + */ + public function set($key, $value) + { + $this->initialize(); + $this->collection->set($key, $value); + } + + /** + * {@inheritDoc} + */ + public function toArray() + { + $this->initialize(); + + return $this->collection->toArray(); + } + + /** + * {@inheritDoc} + */ + public function first() + { + $this->initialize(); + + return $this->collection->first(); + } + + /** + * {@inheritDoc} + */ + public function last() + { + $this->initialize(); + + return $this->collection->last(); + } + + /** + * {@inheritDoc} + */ + public function key() + { + $this->initialize(); + + return $this->collection->key(); + } + + /** + * {@inheritDoc} + */ + public function current() + { + $this->initialize(); + + return $this->collection->current(); + } + + /** + * {@inheritDoc} + */ + public function next() + { + $this->initialize(); + + return $this->collection->next(); + } + + /** + * {@inheritDoc} + */ + public function exists(Closure $p) + { + $this->initialize(); + + return $this->collection->exists($p); + } + + /** + * {@inheritDoc} + */ + public function filter(Closure $p) + { + $this->initialize(); + + return $this->collection->filter($p); + } + + /** + * {@inheritDoc} + */ + public function forAll(Closure $p) + { + $this->initialize(); + + return $this->collection->forAll($p); + } + + /** + * {@inheritDoc} + */ + public function map(Closure $func) + { + $this->initialize(); + + return $this->collection->map($func); + } + + /** + * {@inheritDoc} + */ + public function partition(Closure $p) + { + $this->initialize(); + + return $this->collection->partition($p); + } + + /** + * {@inheritDoc} + */ + public function indexOf($element) + { + $this->initialize(); + + return $this->collection->indexOf($element); + } + + /** + * {@inheritDoc} + */ + public function slice($offset, $length = null) + { + $this->initialize(); + + return $this->collection->slice($offset, $length); + } + + /** + * {@inheritDoc} + */ + public function getIterator() + { + $this->initialize(); + + return $this->collection->getIterator(); + } + + /** + * {@inheritDoc} + */ + public function offsetExists($offset) + { + $this->initialize(); + + return $this->collection->offsetExists($offset); + } + + /** + * {@inheritDoc} + */ + public function offsetGet($offset) + { + $this->initialize(); + + return $this->collection->offsetGet($offset); + } + + /** + * {@inheritDoc} + */ + public function offsetSet($offset, $value) + { + $this->initialize(); + $this->collection->offsetSet($offset, $value); + } + + /** + * {@inheritDoc} + */ + public function offsetUnset($offset) + { + $this->initialize(); + $this->collection->offsetUnset($offset); + } + + /** + * Is the lazy collection already initialized? + * + * @return bool + */ + public function isInitialized() + { + return $this->initialized; + } + + /** + * Initialize the collection + * + * @return void + */ + protected function initialize() + { + if ($this->initialized) { + return; + } + + $this->doInitialize(); + $this->initialized = true; + } + + /** + * Do the initialization logic + * + * @return void + */ + abstract protected function doInitialize(); +} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php new file mode 100644 index 0000000..46f68d4 --- /dev/null +++ b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php @@ -0,0 +1,429 @@ + + * @template-implements Selectable + */ +class ArrayCollection implements Collection, Selectable +{ + /** + * An array containing the entries of this collection. + * + * @psalm-var array + * @var array + */ + private $elements; + + /** + * Initializes a new ArrayCollection. + * + * @param array $elements + * + * @psalm-param array $elements + */ + public function __construct(array $elements = []) + { + $this->elements = $elements; + } + + /** + * {@inheritDoc} + */ + public function toArray() + { + return $this->elements; + } + + /** + * {@inheritDoc} + */ + public function first() + { + return reset($this->elements); + } + + /** + * Creates a new instance from the specified elements. + * + * This method is provided for derived classes to specify how a new + * instance should be created when constructor semantics have changed. + * + * @param array $elements Elements. + * + * @return static + * + * @psalm-param array $elements + * @psalm-return static + */ + protected function createFrom(array $elements) + { + return new static($elements); + } + + /** + * {@inheritDoc} + */ + public function last() + { + return end($this->elements); + } + + /** + * {@inheritDoc} + */ + public function key() + { + return key($this->elements); + } + + /** + * {@inheritDoc} + */ + public function next() + { + return next($this->elements); + } + + /** + * {@inheritDoc} + */ + public function current() + { + return current($this->elements); + } + + /** + * {@inheritDoc} + */ + public function remove($key) + { + if (! isset($this->elements[$key]) && ! array_key_exists($key, $this->elements)) { + return null; + } + + $removed = $this->elements[$key]; + unset($this->elements[$key]); + + return $removed; + } + + /** + * {@inheritDoc} + */ + public function removeElement($element) + { + $key = array_search($element, $this->elements, true); + + if ($key === false) { + return false; + } + + unset($this->elements[$key]); + + return true; + } + + /** + * Required by interface ArrayAccess. + * + * {@inheritDoc} + */ + public function offsetExists($offset) + { + return $this->containsKey($offset); + } + + /** + * Required by interface ArrayAccess. + * + * {@inheritDoc} + */ + public function offsetGet($offset) + { + return $this->get($offset); + } + + /** + * Required by interface ArrayAccess. + * + * {@inheritDoc} + */ + public function offsetSet($offset, $value) + { + if (! isset($offset)) { + $this->add($value); + + return; + } + + $this->set($offset, $value); + } + + /** + * Required by interface ArrayAccess. + * + * {@inheritDoc} + */ + public function offsetUnset($offset) + { + $this->remove($offset); + } + + /** + * {@inheritDoc} + */ + public function containsKey($key) + { + return isset($this->elements[$key]) || array_key_exists($key, $this->elements); + } + + /** + * {@inheritDoc} + */ + public function contains($element) + { + return in_array($element, $this->elements, true); + } + + /** + * {@inheritDoc} + */ + public function exists(Closure $p) + { + foreach ($this->elements as $key => $element) { + if ($p($key, $element)) { + return true; + } + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function indexOf($element) + { + return array_search($element, $this->elements, true); + } + + /** + * {@inheritDoc} + */ + public function get($key) + { + return $this->elements[$key] ?? null; + } + + /** + * {@inheritDoc} + */ + public function getKeys() + { + return array_keys($this->elements); + } + + /** + * {@inheritDoc} + */ + public function getValues() + { + return array_values($this->elements); + } + + /** + * {@inheritDoc} + */ + public function count() + { + return count($this->elements); + } + + /** + * {@inheritDoc} + */ + public function set($key, $value) + { + $this->elements[$key] = $value; + } + + /** + * {@inheritDoc} + */ + public function add($element) + { + $this->elements[] = $element; + + return true; + } + + /** + * {@inheritDoc} + */ + public function isEmpty() + { + return empty($this->elements); + } + + /** + * Required by interface IteratorAggregate. + * + * {@inheritDoc} + */ + public function getIterator() + { + return new ArrayIterator($this->elements); + } + + /** + * {@inheritDoc} + * + * @return static + * + * @psalm-template U + * @psalm-param Closure(T=):U $func + * @psalm-return static + */ + public function map(Closure $func) + { + return $this->createFrom(array_map($func, $this->elements)); + } + + /** + * {@inheritDoc} + * + * @return static + * + * @psalm-return static + */ + public function filter(Closure $p) + { + return $this->createFrom(array_filter($this->elements, $p, ARRAY_FILTER_USE_BOTH)); + } + + /** + * {@inheritDoc} + */ + public function forAll(Closure $p) + { + foreach ($this->elements as $key => $element) { + if (! $p($key, $element)) { + return false; + } + } + + return true; + } + + /** + * {@inheritDoc} + */ + public function partition(Closure $p) + { + $matches = $noMatches = []; + + foreach ($this->elements as $key => $element) { + if ($p($key, $element)) { + $matches[$key] = $element; + } else { + $noMatches[$key] = $element; + } + } + + return [$this->createFrom($matches), $this->createFrom($noMatches)]; + } + + /** + * Returns a string representation of this object. + * + * @return string + */ + public function __toString() + { + return self::class . '@' . spl_object_hash($this); + } + + /** + * {@inheritDoc} + */ + public function clear() + { + $this->elements = []; + } + + /** + * {@inheritDoc} + */ + public function slice($offset, $length = null) + { + return array_slice($this->elements, $offset, $length, true); + } + + /** + * {@inheritDoc} + */ + public function matching(Criteria $criteria) + { + $expr = $criteria->getWhereExpression(); + $filtered = $this->elements; + + if ($expr) { + $visitor = new ClosureExpressionVisitor(); + $filter = $visitor->dispatch($expr); + $filtered = array_filter($filtered, $filter); + } + + $orderings = $criteria->getOrderings(); + + if ($orderings) { + $next = null; + foreach (array_reverse($orderings) as $field => $ordering) { + $next = ClosureExpressionVisitor::sortByField($field, $ordering === Criteria::DESC ? -1 : 1, $next); + } + + uasort($filtered, $next); + } + + $offset = $criteria->getFirstResult(); + $length = $criteria->getMaxResults(); + + if ($offset || $length) { + $filtered = array_slice($filtered, (int) $offset, $length); + } + + return $this->createFrom($filtered); + } +} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php new file mode 100644 index 0000000..adf4a3b --- /dev/null +++ b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php @@ -0,0 +1,296 @@ +ordered map 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 preferable. + * 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. + * + * @psalm-template TKey of array-key + * @psalm-template T + * @template-extends IteratorAggregate + * @template-extends ArrayAccess + */ +interface Collection extends Countable, IteratorAggregate, ArrayAccess +{ + /** + * Adds an element at the end of the collection. + * + * @param mixed $element The element to add. + * + * @return true Always TRUE. + * + * @psalm-param T $element + */ + public function add($element); + + /** + * Clears the collection, removing all elements. + * + * @return void + */ + public 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 bool TRUE if the collection contains the element, FALSE otherwise. + * + * @psalm-param T $element + */ + public function contains($element); + + /** + * Checks whether the collection is empty (contains no elements). + * + * @return bool TRUE if the collection is empty, FALSE otherwise. + */ + public function isEmpty(); + + /** + * Removes the element at the specified index from the collection. + * + * @param string|int $key The key/index of the element to remove. + * + * @return mixed The removed element or NULL, if the collection did not contain the element. + * + * @psalm-param TKey $key + * @psalm-return T|null + */ + public function remove($key); + + /** + * Removes the specified element from the collection, if it is found. + * + * @param mixed $element The element to remove. + * + * @return bool TRUE if this collection contained the specified element, FALSE otherwise. + * + * @psalm-param T $element + */ + public function removeElement($element); + + /** + * Checks whether the collection contains an element with the specified key/index. + * + * @param string|int $key The key/index to check for. + * + * @return bool TRUE if the collection contains an element with the specified key/index, + * FALSE otherwise. + * + * @psalm-param TKey $key + */ + public function containsKey($key); + + /** + * Gets the element at the specified key/index. + * + * @param string|int $key The key/index of the element to retrieve. + * + * @return mixed + * + * @psalm-param TKey $key + * @psalm-return T|null + */ + public function get($key); + + /** + * Gets all keys/indices of the collection. + * + * @return int[]|string[] The keys/indices of the collection, in the order of the corresponding + * elements in the collection. + * + * @psalm-return TKey[] + */ + public 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. + * + * @psalm-return T[] + */ + public function getValues(); + + /** + * Sets an element in the collection at the specified key/index. + * + * @param string|int $key The key/index of the element to set. + * @param mixed $value The element to set. + * + * @return void + * + * @psalm-param TKey $key + * @psalm-param T $value + */ + public function set($key, $value); + + /** + * Gets a native PHP array representation of the collection. + * + * @return array + * + * @psalm-return array + */ + public function toArray(); + + /** + * Sets the internal iterator to the first element in the collection and returns this element. + * + * @return mixed + * + * @psalm-return T|false + */ + public function first(); + + /** + * Sets the internal iterator to the last element in the collection and returns this element. + * + * @return mixed + * + * @psalm-return T|false + */ + public function last(); + + /** + * Gets the key/index of the element at the current iterator position. + * + * @return int|string + * + * @psalm-return TKey + */ + public function key(); + + /** + * Gets the element of the collection at the current iterator position. + * + * @return mixed + * + * @psalm-return T|false + */ + public function current(); + + /** + * Moves the internal iterator position to the next element and returns this element. + * + * @return mixed + * + * @psalm-return T|false + */ + public function next(); + + /** + * Tests for the existence of an element that satisfies the given predicate. + * + * @param Closure $p The predicate. + * + * @return bool TRUE if the predicate is TRUE for at least one element, FALSE otherwise. + * + * @psalm-param Closure(TKey=, T=):bool $p + */ + public 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. + * + * @psalm-param Closure(T=):bool $p + * @psalm-return Collection + */ + public function filter(Closure $p); + + /** + * Tests whether the given predicate p holds for all elements of this collection. + * + * @param Closure $p The predicate. + * + * @return bool TRUE, if the predicate yields TRUE for all elements, FALSE otherwise. + * + * @psalm-param Closure(TKey=, T=):bool $p + */ + public 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. + * + * @return Collection + * + * @psalm-template U + * @psalm-param Closure(T=):U $func + * @psalm-return Collection + */ + public 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 Collection[] 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. + * + * @psalm-param Closure(TKey=, T=):bool $p + * @psalm-return array{0: Collection, 1: Collection} + */ + public 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 int|string|bool The key/index of the element or FALSE if the element was not found. + * + * @psalm-param T $element + * @psalm-return TKey|false + */ + public function indexOf($element); + + /** + * Extracts 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 The offset to start from. + * @param int|null $length The maximum number of elements to return, or null for no limit. + * + * @return array + * + * @psalm-return array + */ + public function slice($offset, $length = null); +} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php new file mode 100644 index 0000000..6ddaf5e --- /dev/null +++ b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php @@ -0,0 +1,222 @@ +expression = $expression; + + $this->setFirstResult($firstResult); + $this->setMaxResults($maxResults); + + if ($orderings === null) { + return; + } + + $this->orderBy($orderings); + } + + /** + * Sets the where expression to evaluate when this Criteria is searched for. + * + * @return Criteria + */ + public function where(Expression $expression) + { + $this->expression = $expression; + + return $this; + } + + /** + * Appends the where expression to evaluate when this Criteria is searched for + * using an AND with previous expression. + * + * @return Criteria + */ + public function andWhere(Expression $expression) + { + if ($this->expression === null) { + return $this->where($expression); + } + + $this->expression = new CompositeExpression( + CompositeExpression::TYPE_AND, + [$this->expression, $expression] + ); + + return $this; + } + + /** + * Appends the where expression to evaluate when this Criteria is searched for + * using an OR with previous expression. + * + * @return Criteria + */ + public function orWhere(Expression $expression) + { + if ($this->expression === null) { + return $this->where($expression); + } + + $this->expression = new CompositeExpression( + CompositeExpression::TYPE_OR, + [$this->expression, $expression] + ); + + return $this; + } + + /** + * Gets the expression attached to this Criteria. + * + * @return Expression|null + */ + public function getWhereExpression() + { + return $this->expression; + } + + /** + * Gets the current orderings of this Criteria. + * + * @return string[] + */ + public function getOrderings() + { + return $this->orderings; + } + + /** + * Sets the ordering of the result of this Criteria. + * + * Keys are field and values are the order, being either ASC or DESC. + * + * @see Criteria::ASC + * @see Criteria::DESC + * + * @param string[] $orderings + * + * @return Criteria + */ + public function orderBy(array $orderings) + { + $this->orderings = array_map( + static function (string $ordering) : string { + return strtoupper($ordering) === Criteria::ASC ? Criteria::ASC : Criteria::DESC; + }, + $orderings + ); + + return $this; + } + + /** + * Gets the current first result option of this Criteria. + * + * @return int|null + */ + public function getFirstResult() + { + return $this->firstResult; + } + + /** + * Set the number of first result that this Criteria should return. + * + * @param int|null $firstResult The value to set. + * + * @return Criteria + */ + public function setFirstResult($firstResult) + { + $this->firstResult = $firstResult === null ? null : (int) $firstResult; + + return $this; + } + + /** + * Gets maxResults. + * + * @return int|null + */ + public function getMaxResults() + { + return $this->maxResults; + } + + /** + * Sets maxResults. + * + * @param int|null $maxResults The value to set. + * + * @return Criteria + */ + public function setMaxResults($maxResults) + { + $this->maxResults = $maxResults === null ? null : (int) $maxResults; + + return $this; + } +} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php new file mode 100644 index 0000000..43e5cf1 --- /dev/null +++ b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php @@ -0,0 +1,257 @@ +$accessor(); + } + } + + if (preg_match('/^is[A-Z]+/', $field) === 1 && method_exists($object, $field)) { + return $object->$field(); + } + + // __call should be triggered for get. + $accessor = $accessors[0] . $field; + + if (method_exists($object, '__call')) { + return $object->$accessor(); + } + + if ($object instanceof ArrayAccess) { + return $object[$field]; + } + + if (isset($object->$field)) { + return $object->$field; + } + + // camelcase field name to support different variable naming conventions + $ccField = preg_replace_callback('/_(.?)/', static function ($matches) { + return strtoupper($matches[1]); + }, $field); + + foreach ($accessors as $accessor) { + $accessor .= $ccField; + + if (method_exists($object, $accessor)) { + return $object->$accessor(); + } + } + + return $object->$field; + } + + /** + * Helper for sorting arrays of objects based on multiple fields + orientations. + * + * @param string $name + * @param int $orientation + * + * @return Closure + */ + public static function sortByField($name, $orientation = 1, ?Closure $next = null) + { + if (! $next) { + $next = static function () : int { + return 0; + }; + } + + return static function ($a, $b) use ($name, $next, $orientation) : int { + $aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name); + + $bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name); + + if ($aValue === $bValue) { + return $next($a, $b); + } + + return ($aValue > $bValue ? 1 : -1) * $orientation; + }; + } + + /** + * {@inheritDoc} + */ + public function walkComparison(Comparison $comparison) + { + $field = $comparison->getField(); + $value = $comparison->getValue()->getValue(); // shortcut for walkValue() + + switch ($comparison->getOperator()) { + case Comparison::EQ: + return static function ($object) use ($field, $value) : bool { + return ClosureExpressionVisitor::getObjectFieldValue($object, $field) === $value; + }; + + case Comparison::NEQ: + return static function ($object) use ($field, $value) : bool { + return ClosureExpressionVisitor::getObjectFieldValue($object, $field) !== $value; + }; + + case Comparison::LT: + return static function ($object) use ($field, $value) : bool { + return ClosureExpressionVisitor::getObjectFieldValue($object, $field) < $value; + }; + + case Comparison::LTE: + return static function ($object) use ($field, $value) : bool { + return ClosureExpressionVisitor::getObjectFieldValue($object, $field) <= $value; + }; + + case Comparison::GT: + return static function ($object) use ($field, $value) : bool { + return ClosureExpressionVisitor::getObjectFieldValue($object, $field) > $value; + }; + + case Comparison::GTE: + return static function ($object) use ($field, $value) : bool { + return ClosureExpressionVisitor::getObjectFieldValue($object, $field) >= $value; + }; + + case Comparison::IN: + return static function ($object) use ($field, $value) : bool { + return in_array(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value, true); + }; + + case Comparison::NIN: + return static function ($object) use ($field, $value) : bool { + return ! in_array(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value, true); + }; + + case Comparison::CONTAINS: + return static function ($object) use ($field, $value) { + return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) !== false; + }; + + case Comparison::MEMBER_OF: + return static function ($object) use ($field, $value) : bool { + $fieldValues = ClosureExpressionVisitor::getObjectFieldValue($object, $field); + + if (! is_array($fieldValues)) { + $fieldValues = iterator_to_array($fieldValues); + } + + return in_array($value, $fieldValues, true); + }; + + case Comparison::STARTS_WITH: + return static function ($object) use ($field, $value) : bool { + return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) === 0; + }; + + case Comparison::ENDS_WITH: + return static function ($object) use ($field, $value) : bool { + return $value === substr(ClosureExpressionVisitor::getObjectFieldValue($object, $field), -strlen($value)); + }; + + default: + throw new RuntimeException('Unknown comparison operator: ' . $comparison->getOperator()); + } + } + + /** + * {@inheritDoc} + */ + public function walkValue(Value $value) + { + return $value->getValue(); + } + + /** + * {@inheritDoc} + */ + public function walkCompositeExpression(CompositeExpression $expr) + { + $expressionList = []; + + foreach ($expr->getExpressionList() as $child) { + $expressionList[] = $this->dispatch($child); + } + + switch ($expr->getType()) { + case CompositeExpression::TYPE_AND: + return $this->andExpressions($expressionList); + case CompositeExpression::TYPE_OR: + return $this->orExpressions($expressionList); + default: + throw new RuntimeException('Unknown composite ' . $expr->getType()); + } + } + + /** + * @param array $expressions + */ + private function andExpressions(array $expressions) : callable + { + return static function ($object) use ($expressions) : bool { + foreach ($expressions as $expression) { + if (! $expression($object)) { + return false; + } + } + + return true; + }; + } + + /** + * @param array $expressions + */ + private function orExpressions(array $expressions) : callable + { + return static function ($object) use ($expressions) : bool { + foreach ($expressions as $expression) { + if ($expression($object)) { + return true; + } + } + + return false; + }; + } +} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php new file mode 100644 index 0000000..13e193c --- /dev/null +++ b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php @@ -0,0 +1,80 @@ +'; + public const LT = '<'; + public const LTE = '<='; + public const GT = '>'; + public const GTE = '>='; + public const IS = '='; // no difference with EQ + public const IN = 'IN'; + public const NIN = 'NIN'; + public const CONTAINS = 'CONTAINS'; + public const MEMBER_OF = 'MEMBER_OF'; + public const STARTS_WITH = 'STARTS_WITH'; + public const ENDS_WITH = 'ENDS_WITH'; + + /** @var string */ + private $field; + + /** @var string */ + private $op; + + /** @var Value */ + private $value; + + /** + * @param string $field + * @param string $operator + * @param mixed $value + */ + public function __construct($field, $operator, $value) + { + if (! ($value instanceof Value)) { + $value = new Value($value); + } + + $this->field = $field; + $this->op = $operator; + $this->value = $value; + } + + /** + * @return string + */ + public function getField() + { + return $this->field; + } + + /** + * @return Value + */ + public function getValue() + { + return $this->value; + } + + /** + * @return string + */ + public function getOperator() + { + return $this->op; + } + + /** + * {@inheritDoc} + */ + public function visit(ExpressionVisitor $visitor) + { + return $visitor->walkComparison($this); + } +} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php new file mode 100644 index 0000000..e1f7114 --- /dev/null +++ b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php @@ -0,0 +1,68 @@ +type = $type; + + foreach ($expressions as $expr) { + if ($expr instanceof Value) { + throw new RuntimeException('Values are not supported expressions as children of and/or expressions.'); + } + if (! ($expr instanceof Expression)) { + throw new RuntimeException('No expression given to CompositeExpression.'); + } + + $this->expressions[] = $expr; + } + } + + /** + * Returns the list of expressions nested in this composite. + * + * @return Expression[] + */ + public function getExpressionList() + { + return $this->expressions; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * {@inheritDoc} + */ + public function visit(ExpressionVisitor $visitor) + { + return $visitor->walkCompositeExpression($this); + } +} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php new file mode 100644 index 0000000..f40d529 --- /dev/null +++ b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php @@ -0,0 +1,14 @@ +walkComparison($expr); + case $expr instanceof Value: + return $this->walkValue($expr); + case $expr instanceof CompositeExpression: + return $this->walkCompositeExpression($expr); + default: + throw new RuntimeException('Unknown Expression ' . get_class($expr)); + } + } +} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php new file mode 100644 index 0000000..0830286 --- /dev/null +++ b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php @@ -0,0 +1,33 @@ +value = $value; + } + + /** + * @return mixed + */ + public function getValue() + { + return $this->value; + } + + /** + * {@inheritDoc} + */ + public function visit(ExpressionVisitor $visitor) + { + return $visitor->walkValue($this); + } +} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php new file mode 100644 index 0000000..4c0f5fd --- /dev/null +++ b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php @@ -0,0 +1,180 @@ + + */ + public function matching(Criteria $criteria); +} diff --git a/vendor/doctrine/collections/psalm.xml.dist b/vendor/doctrine/collections/psalm.xml.dist new file mode 100644 index 0000000..8c5b066 --- /dev/null +++ b/vendor/doctrine/collections/psalm.xml.dist @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/doctrine/common/.doctrine-project.json b/vendor/doctrine/common/.doctrine-project.json new file mode 100644 index 0000000..d29ce6d --- /dev/null +++ b/vendor/doctrine/common/.doctrine-project.json @@ -0,0 +1,18 @@ +{ + "active": true, + "name": "Common", + "slug": "common", + "docsSlug": "doctrine-common", + "versions": [ + { + "name": "master", + "branchName": "master", + "slug": "latest" + }, + { + "name": "2.11", + "branchName": "2.11", + "current": true + } + ] +} diff --git a/vendor/doctrine/common/.github/FUNDING.yml b/vendor/doctrine/common/.github/FUNDING.yml new file mode 100644 index 0000000..af1c7e7 --- /dev/null +++ b/vendor/doctrine/common/.github/FUNDING.yml @@ -0,0 +1,3 @@ +patreon: phpdoctrine +tidelift: packagist/doctrine%2Fcommon +custom: https://www.doctrine-project.org/sponsorship.html diff --git a/vendor/doctrine/common/LICENSE b/vendor/doctrine/common/LICENSE new file mode 100644 index 0000000..8c38cc1 --- /dev/null +++ b/vendor/doctrine/common/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2015 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/doctrine/common/README.md b/vendor/doctrine/common/README.md new file mode 100644 index 0000000..5cffb1a --- /dev/null +++ b/vendor/doctrine/common/README.md @@ -0,0 +1,11 @@ +# Doctrine Common + +[![Build Status](https://secure.travis-ci.org/doctrine/common.png)](https://travis-ci.org/doctrine/common) + +The Doctrine Common project is a library that provides extensions to core PHP functionality. + +## More resources: + +* [Website](https://www.doctrine-project.org/) +* [Documentation](https://www.doctrine-project.org/projects/doctrine-common/en/latest/) +* [Downloads](https://github.com/doctrine/common/releases) diff --git a/vendor/doctrine/common/UPGRADE_TO_2_1 b/vendor/doctrine/common/UPGRADE_TO_2_1 new file mode 100644 index 0000000..891a2e5 --- /dev/null +++ b/vendor/doctrine/common/UPGRADE_TO_2_1 @@ -0,0 +1,39 @@ +This document details all the possible changes that you should investigate when updating +your project from Doctrine Common 2.0.x to 2.1 + +## AnnotationReader changes + +The annotation reader was heavily refactored between 2.0 and 2.1-RC1. In theory the operation of the new reader should be backwards compatible, but it has to be setup differently to work that way: + + $reader = new \Doctrine\Common\Annotations\AnnotationReader(); + $reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\'); + // new code necessary starting here + $reader->setIgnoreNotImportedAnnotations(true); + $reader->setEnableParsePhpImports(false); + $reader = new \Doctrine\Common\Annotations\CachedReader( + new \Doctrine\Common\Annotations\IndexedReader($reader), new ArrayCache() + ); + +## Annotation Base class or @Annotation + +Beginning after 2.1-RC2 you have to either extend ``Doctrine\Common\Annotations\Annotation`` or add @Annotation to your annotations class-level docblock, otherwise the class will simply be ignored. + +## Removed methods on AnnotationReader + +* AnnotationReader::setAutoloadAnnotations() +* AnnotationReader::getAutoloadAnnotations() +* AnnotationReader::isAutoloadAnnotations() + +## AnnotationRegistry + +Autoloading through the PHP autoloader is removed from the 2.1 AnnotationReader. Instead you have to use the global AnnotationRegistry for loading purposes: + + \Doctrine\Common\Annotations\AnnotationRegistry::registerFile($fileWithAnnotations); + \Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespace($namespace, $dirs = null); + \Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespaces($namespaces); + \Doctrine\Common\Annotations\AnnotationRegistry::registerLoader($callable); + +The $callable for registering a loader accepts a class as first and only parameter and must try to silently autoload it. On success true has to be returned. +The registerAutoloadNamespace function registers a PSR-0 compatible silent autoloader for all classes with the given namespace in the given directories. +If null is passed as directory the include path will be used. + diff --git a/vendor/doctrine/common/UPGRADE_TO_2_2 b/vendor/doctrine/common/UPGRADE_TO_2_2 new file mode 100644 index 0000000..1d93a13 --- /dev/null +++ b/vendor/doctrine/common/UPGRADE_TO_2_2 @@ -0,0 +1,61 @@ +This document details all the possible changes that you should investigate when +updating your project from Doctrine Common 2.1 to 2.2: + +## Annotation Changes + +- AnnotationReader::setIgnoreNotImportedAnnotations has been removed, you need to + add ignore annotation names which are supposed to be ignored via + AnnotationReader::addGlobalIgnoredName + +- AnnotationReader::setAutoloadAnnotations was deprecated by the AnnotationRegistry + in 2.1 and has been removed in 2.2 + +- AnnotationReader::setEnableParsePhpImports was added to ease transition to the new + annotation mechanism in 2.1 and is removed in 2.2 + +- AnnotationReader::isParsePhpImportsEnabled is removed (see above) + +- AnnotationReader::setDefaultAnnotationNamespace was deprecated in favor of explicit + configuration in 2.1 and will be removed in 2.2 (for isolated projects where you + have full-control over _all_ available annotations, we offer a dedicated reader + class ``SimpleAnnotationReader``) + +- AnnotationReader::setAnnotationCreationFunction was deprecated in 2.1 and will be + removed in 2.2. We only offer two creation mechanisms which cannot be changed + anymore to allow the same reader instance to work with all annotations regardless + of which library they are coming from. + +- AnnotationReader::setAnnotationNamespaceAlias was deprecated in 2.1 and will be + removed in 2.2 (see setDefaultAnnotationNamespace) + +- If you use a class as annotation which has not the @Annotation marker in it's + class block, we will now throw an exception instead of silently ignoring it. You + can however still achieve the previous behavior using the @IgnoreAnnotation, or + AnnotationReader::addGlobalIgnoredName (the exception message will contain detailed + instructions when you run into this problem). + +## Cache Changes + +- Renamed old AbstractCache to CacheProvider + +- Dropped the support to the following functions of all cache providers: + + - CacheProvider::deleteByWildcard + + - CacheProvider::deleteByRegEx + + - CacheProvider::deleteByPrefix + + - CacheProvider::deleteBySuffix + +- CacheProvider::deleteAll will not remove ALL entries, it will only mark them as invalid + +- CacheProvider::flushAll will remove ALL entries, namespaced or not + +- Added support to MemcachedCache + +- Added support to WincacheCache + +## ClassLoader Changes + +- ClassLoader::fileExistsInIncludePath() no longer exists. Use the native stream_resolve_include_path() PHP function \ No newline at end of file diff --git a/vendor/doctrine/common/composer.json b/vendor/doctrine/common/composer.json new file mode 100644 index 0000000..ea158a2 --- /dev/null +++ b/vendor/doctrine/common/composer.json @@ -0,0 +1,54 @@ +{ + "name": "doctrine/common", + "type": "library", + "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, persistence interfaces, proxies, event system and much more.", + "keywords": [ + "php", + "common", + "doctrine" + ], + "homepage": "https://www.doctrine-project.org/projects/common.html", + "license": "MIT", + "authors": [ + {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, + {"name": "Roman Borschel", "email": "roman@code-factory.org"}, + {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, + {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, + {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}, + {"name": "Marco Pivetta", "email": "ocramius@gmail.com"} + ], + "require": { + "php": "^7.1", + "doctrine/inflector": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/lexer": "^1.0", + "doctrine/annotations": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/reflection": "^1.0", + "doctrine/persistence": "^1.1" + }, + "require-dev": { + "phpstan/phpstan": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpunit/phpunit": "^7.0", + "doctrine/coding-standard": "^1.0", + "squizlabs/php_codesniffer": "^3.0", + "symfony/phpunit-bridge": "^4.0.5" + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "autoload-dev": { + "psr-4": { + "Doctrine\\Tests\\": "tests/Doctrine/Tests" + } + }, + "extra": { + "branch-alias": { + "dev-master": "2.11.x-dev" + } + } +} diff --git a/vendor/doctrine/common/composer.lock b/vendor/doctrine/common/composer.lock new file mode 100644 index 0000000..a5bb7ef --- /dev/null +++ b/vendor/doctrine/common/composer.lock @@ -0,0 +1,3433 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "40bcfe4c5277cdfa06868ad21fd26d85", + "packages": [ + { + "name": "doctrine/annotations", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2017-12-06T07:11:42+00:00" + }, + { + "name": "doctrine/cache", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/d768d58baee9a4862ca783840eca1b9add7a7f57", + "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57", + "shasum": "" + }, + "require": { + "php": "~7.1" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^4.0", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^7.0", + "predis/predis": "~1.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Caching library offering an object-oriented API for many cache backends", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "cache", + "caching" + ], + "time": "2018-08-21T18:01:43+00:00" + }, + { + "name": "doctrine/collections", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/a01ee38fcd999f34d9bfbcee59dbda5105449cbf", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "~0.1@dev", + "phpunit/phpunit": "^5.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Collections\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Collections Abstraction library", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "array", + "collections", + "iterator" + ], + "time": "2017-07-22T10:37:32+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/a520bc093a0170feeb6b14e9d83f3a14452e64b3", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Event Manager component", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "eventdispatcher", + "eventmanager" + ], + "time": "2018-06-11T11:59:03+00:00" + }, + { + "name": "doctrine/inflector", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2018-01-09T20:05:19+00:00" + }, + { + "name": "doctrine/lexer", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Lexer\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "lexer", + "parser" + ], + "time": "2014-09-09T13:34:57+00:00" + }, + { + "name": "doctrine/persistence", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/persistence.git", + "reference": "c0f1c17602afc18b4cbd8e1c8125f264c9cf7d38" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/c0f1c17602afc18b4cbd8e1c8125f264c9cf7d38", + "reference": "c0f1c17602afc18b4cbd8e1c8125f264c9cf7d38", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.10@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^5.0", + "phpstan/phpstan": "^0.8", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", + "homepage": "https://doctrine-project.org/projects/persistence.html", + "keywords": [ + "mapper", + "object", + "odm", + "orm", + "persistence" + ], + "time": "2018-11-21T00:33:13+00:00" + }, + { + "name": "doctrine/reflection", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/reflection.git", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/reflection/zipball/02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "doctrine/common": "^2.8", + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Reflection component", + "homepage": "https://www.doctrine-project.org/projects/reflection.html", + "keywords": [ + "reflection" + ], + "time": "2018-06-14T14:45:07+00:00" + } + ], + "packages-dev": [ + { + "name": "composer/xdebug-handler", + "version": "1.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "d17708133b6c276d6e42ef887a877866b909d892" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/d17708133b6c276d6e42ef887a877866b909d892", + "reference": "d17708133b6c276d6e42ef887a877866b909d892", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0", + "psr/log": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "time": "2019-01-28T20:25:53+00:00" + }, + { + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v0.4.4", + "source": { + "type": "git", + "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", + "reference": "2e41850d5f7797cbb1af7b030d245b3b24e63a08" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/2e41850d5f7797cbb1af7b030d245b3b24e63a08", + "reference": "2e41850d5f7797cbb1af7b030d245b3b24e63a08", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0", + "php": "^5.3|^7", + "squizlabs/php_codesniffer": "*" + }, + "require-dev": { + "composer/composer": "*", + "wimg/php-compatibility": "^8.0" + }, + "suggest": { + "dealerdirect/qa-tools": "All the PHP QA tools you'll need" + }, + "type": "composer-plugin", + "extra": { + "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "autoload": { + "psr-4": { + "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "f.nijhof@dealerdirect.nl", + "homepage": "http://workingatdealerdirect.eu", + "role": "Developer" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://workingatdealerdirect.eu", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "time": "2017-12-06T16:27:17+00:00" + }, + { + "name": "doctrine/coding-standard", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/coding-standard.git", + "reference": "d0af8acc36d69f315d550eef78a9607bba24a6da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/coding-standard/zipball/d0af8acc36d69f315d550eef78a9607bba24a6da", + "reference": "d0af8acc36d69f315d550eef78a9607bba24a6da", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.2", + "php": "^7.1", + "squizlabs/php_codesniffer": "~3.0" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "0.1-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Sniffs\\": "lib/Doctrine/Sniffs" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Steve Müller", + "email": "st.mueller@dzh-online.de" + } + ], + "description": "Doctrine Coding Standard", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "code", + "coding", + "cs", + "doctrine", + "sniffer", + "standard", + "style" + ], + "time": "2017-08-20T01:30:16+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "a2c590166b2133a4633738648b6b064edae0814a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a", + "reference": "a2c590166b2133a4633738648b6b064edae0814a", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2019-03-17T17:37:11+00:00" + }, + { + "name": "jean85/pretty-package-versions", + "version": "1.2", + "source": { + "type": "git", + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/75c7effcf3f77501d0e0caa75111aff4daa0dd48", + "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48", + "shasum": "" + }, + "require": { + "ocramius/package-versions": "^1.2.0", + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jean85\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" + } + ], + "description": "A wrapper for ocramius/package-versions to get pretty versions strings", + "keywords": [ + "composer", + "package", + "release", + "versions" + ], + "time": "2018-06-13T13:22:40+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.9.3", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea", + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2019-08-09T12:45:53+00:00" + }, + { + "name": "nette/bootstrap", + "version": "v2.4.6", + "source": { + "type": "git", + "url": "https://github.com/nette/bootstrap.git", + "reference": "268816e3f1bb7426c3a4ceec2bd38a036b532543" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/bootstrap/zipball/268816e3f1bb7426c3a4ceec2bd38a036b532543", + "reference": "268816e3f1bb7426c3a4ceec2bd38a036b532543", + "shasum": "" + }, + "require": { + "nette/di": "~2.4.7", + "nette/utils": "~2.4", + "php": ">=5.6.0" + }, + "conflict": { + "nette/nette": "<2.2" + }, + "require-dev": { + "latte/latte": "~2.2", + "nette/application": "~2.3", + "nette/caching": "~2.3", + "nette/database": "~2.3", + "nette/forms": "~2.3", + "nette/http": "~2.4.0", + "nette/mail": "~2.3", + "nette/robot-loader": "^2.4.2 || ^3.0", + "nette/safe-stream": "~2.2", + "nette/security": "~2.3", + "nette/tester": "~2.0", + "tracy/tracy": "^2.4.1" + }, + "suggest": { + "nette/robot-loader": "to use Configurator::createRobotLoader()", + "tracy/tracy": "to use Configurator::enableTracy()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "? Nette Bootstrap: the simple way to configure and bootstrap your Nette application.", + "homepage": "https://nette.org", + "keywords": [ + "bootstrapping", + "configurator", + "nette" + ], + "time": "2018-05-17T12:52:20+00:00" + }, + { + "name": "nette/di", + "version": "v2.4.15", + "source": { + "type": "git", + "url": "https://github.com/nette/di.git", + "reference": "d0561b8f77e8ef2ed6d83328860e16c81a5a8649" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/di/zipball/d0561b8f77e8ef2ed6d83328860e16c81a5a8649", + "reference": "d0561b8f77e8ef2ed6d83328860e16c81a5a8649", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "nette/neon": "^2.3.3 || ~3.0.0", + "nette/php-generator": "^2.6.1 || ^3.0.0", + "nette/utils": "^2.5.0 || ~3.0.0", + "php": ">=5.6.0" + }, + "conflict": { + "nette/bootstrap": "<2.4", + "nette/nette": "<2.2" + }, + "require-dev": { + "nette/tester": "^2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "? Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP 7.1 features.", + "homepage": "https://nette.org", + "keywords": [ + "compiled", + "di", + "dic", + "factory", + "ioc", + "nette", + "static" + ], + "time": "2019-01-30T13:26:05+00:00" + }, + { + "name": "nette/finder", + "version": "v2.5.0", + "source": { + "type": "git", + "url": "https://github.com/nette/finder.git", + "reference": "6be1b83ea68ac558aff189d640abe242e0306fe2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/finder/zipball/6be1b83ea68ac558aff189d640abe242e0306fe2", + "reference": "6be1b83ea68ac558aff189d640abe242e0306fe2", + "shasum": "" + }, + "require": { + "nette/utils": "^2.4 || ~3.0.0", + "php": ">=7.1" + }, + "conflict": { + "nette/nette": "<2.2" + }, + "require-dev": { + "nette/tester": "^2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🔍 Nette Finder: find files and directories with an intuitive API.", + "homepage": "https://nette.org", + "keywords": [ + "filesystem", + "glob", + "iterator", + "nette" + ], + "time": "2019-02-28T18:13:25+00:00" + }, + { + "name": "nette/neon", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/neon.git", + "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/neon/zipball/cbff32059cbdd8720deccf9e9eace6ee516f02eb", + "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "ext-json": "*", + "php": ">=7.0" + }, + "require-dev": { + "nette/tester": "^2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🍸 Nette NEON: encodes and decodes NEON file format.", + "homepage": "http://ne-on.org", + "keywords": [ + "export", + "import", + "neon", + "nette", + "yaml" + ], + "time": "2019-02-05T21:30:40+00:00" + }, + { + "name": "nette/php-generator", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/nette/php-generator.git", + "reference": "9de4e093a130f7a1bd175198799ebc0efbac6924" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/php-generator/zipball/9de4e093a130f7a1bd175198799ebc0efbac6924", + "reference": "9de4e093a130f7a1bd175198799ebc0efbac6924", + "shasum": "" + }, + "require": { + "nette/utils": "^2.4.2 || ~3.0.0", + "php": ">=7.1" + }, + "conflict": { + "nette/nette": "<2.2" + }, + "require-dev": { + "nette/tester": "^2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "? Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.3 features.", + "homepage": "https://nette.org", + "keywords": [ + "code", + "nette", + "php", + "scaffolding" + ], + "time": "2018-11-27T19:00:14+00:00" + }, + { + "name": "nette/robot-loader", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/nette/robot-loader.git", + "reference": "3e8d75d6d976e191bdf46752ca40a286671219d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/robot-loader/zipball/3e8d75d6d976e191bdf46752ca40a286671219d2", + "reference": "3e8d75d6d976e191bdf46752ca40a286671219d2", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "nette/finder": "^2.3 || ^3.0", + "nette/utils": "^2.4 || ^3.0", + "php": ">=5.6.0" + }, + "conflict": { + "nette/nette": "<2.2" + }, + "require-dev": { + "nette/tester": "^2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "? Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.", + "homepage": "https://nette.org", + "keywords": [ + "autoload", + "class", + "interface", + "nette", + "trait" + ], + "time": "2019-03-01T20:23:02+00:00" + }, + { + "name": "nette/utils", + "version": "v2.5.3", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "17b9f76f2abd0c943adfb556e56f2165460b15ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/17b9f76f2abd0c943adfb556e56f2165460b15ce", + "reference": "17b9f76f2abd0c943adfb556e56f2165460b15ce", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "conflict": { + "nette/nette": "<2.2" + }, + "require-dev": { + "nette/tester": "~2.0", + "tracy/tracy": "^2.3" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize() and toAscii()", + "ext-intl": "for script transliteration in Strings::webalize() and toAscii()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-xml": "to use Strings::length() etc. when mbstring is not available" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ], + "files": [ + "src/loader.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "? Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "time": "2018-09-18T10:22:16+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.2.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "5221f49a608808c1e4d436df32884cbc1b821ac0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/5221f49a608808c1e4d436df32884cbc1b821ac0", + "reference": "5221f49a608808c1e4d436df32884cbc1b821ac0", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.5 || ^7.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "time": "2019-02-16T20:54:15+00:00" + }, + { + "name": "ocramius/package-versions", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/Ocramius/PackageVersions.git", + "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", + "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0.0", + "php": "^7.1.0" + }, + "require-dev": { + "composer/composer": "^1.6.3", + "doctrine/coding-standard": "^5.0.1", + "ext-zip": "*", + "infection/infection": "^0.7.1", + "phpunit/phpunit": "^7.0.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PackageVersions\\Installer", + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "time": "2019-02-21T12:16:21+00:00" + }, + { + "name": "phar-io/manifest", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^2.0", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2018-07-08T19:23:20+00:00" + }, + { + "name": "phar-io/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2018-07-08T19:19:57+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2017-09-11T18:02:19+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "4.3.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", + "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2019-04-30T17:48:53+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2017-07-14T14:27:02+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "1.8.1", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76", + "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2019-06-13T12:50:23+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "0.3.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "2cc49f47c69b023eaf05b48e6529389893b13d74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/2cc49f47c69b023eaf05b48e6529389893b13d74", + "reference": "2cc49f47c69b023eaf05b48e6529389893b13d74", + "shasum": "" + }, + "require": { + "php": "~7.1" + }, + "require-dev": { + "consistence/coding-standard": "^2.0.0", + "jakub-onderka/php-parallel-lint": "^0.9.2", + "phing/phing": "^2.16.0", + "phpstan/phpstan": "^0.10", + "phpunit/phpunit": "^6.3", + "slevomat/coding-standard": "^3.3.0", + "symfony/process": "^3.4 || ^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.3-dev" + } + }, + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "time": "2019-01-14T12:26:23+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "0.11.3", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "e4644b4a8fd393c346f1137305fb2f76a7dc20a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e4644b4a8fd393c346f1137305fb2f76a7dc20a7", + "reference": "e4644b4a8fd393c346f1137305fb2f76a7dc20a7", + "shasum": "" + }, + "require": { + "composer/xdebug-handler": "^1.3.0", + "jean85/pretty-package-versions": "^1.0.3", + "nette/bootstrap": "^2.4 || ^3.0", + "nette/di": "^2.4.7 || ^3.0", + "nette/robot-loader": "^3.0.1", + "nette/utils": "^2.4.5 || ^3.0", + "nikic/php-parser": "^4.0.2", + "php": "~7.1", + "phpstan/phpdoc-parser": "^0.3", + "symfony/console": "~3.2 || ~4.0", + "symfony/finder": "~3.2 || ~4.0" + }, + "conflict": { + "symfony/console": "3.4.16 || 4.1.5" + }, + "require-dev": { + "brianium/paratest": "^2.0", + "consistence/coding-standard": "^3.5", + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4", + "ext-intl": "*", + "ext-mysqli": "*", + "ext-soap": "*", + "ext-zip": "*", + "jakub-onderka/php-parallel-lint": "^1.0", + "localheinz/composer-normalize": "^1.1.0", + "phing/phing": "^2.16.0", + "phpstan/phpstan-deprecation-rules": "^0.11", + "phpstan/phpstan-php-parser": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-strict-rules": "^0.11", + "phpunit/phpunit": "^7.0", + "slevomat/coding-standard": "^4.7.2", + "squizlabs/php_codesniffer": "^3.3.2" + }, + "bin": [ + "bin/phpstan" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.11-dev" + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": [ + "src/", + "build/PHPStan" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "time": "2019-03-10T16:25:30+00:00" + }, + { + "name": "phpstan/phpstan-phpunit", + "version": "0.11", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-phpunit.git", + "reference": "70c22d44b96a21a4952fc13021a5a63cc83f5c81" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/70c22d44b96a21a4952fc13021a5a63cc83f5c81", + "reference": "70c22d44b96a21a4952fc13021a5a63cc83f5c81", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.0", + "php": "~7.1", + "phpstan/phpdoc-parser": "^0.3", + "phpstan/phpstan": "^0.11" + }, + "conflict": { + "phpunit/phpunit": "<7.0" + }, + "require-dev": { + "consistence/coding-standard": "^3.0.1", + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4", + "jakub-onderka/php-parallel-lint": "^1.0", + "phing/phing": "^2.16.0", + "phpstan/phpstan-strict-rules": "^0.11", + "phpunit/phpunit": "^7.0", + "satooshi/php-coveralls": "^1.0", + "slevomat/coding-standard": "^4.5.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.11-dev" + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPUnit extensions and rules for PHPStan", + "time": "2018-12-22T14:05:04+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "6.1.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.1", + "phpunit/php-file-iterator": "^2.0", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^3.0", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.1 || ^4.0", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "suggest": { + "ext-xdebug": "^2.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2018-10-31T16:06:48+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "050bedf145a257b1ff02746c31894800e5122946" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", + "reference": "050bedf145a257b1ff02746c31894800e5122946", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2018-09-13T20:33:42+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "2.1.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "1038454804406b0b5f5f520358e78c1c2f71501e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e", + "reference": "1038454804406b0b5f5f520358e78c1c2f71501e", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2019-06-07T04:22:29+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e899757bb3df5ff6e95089132f32cd59aac2220a", + "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2019-07-25T05:29:42+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "7.5.15", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "d79c053d972856b8b941bb233e39dc521a5093f0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d79c053d972856b8b941bb233e39dc521a5093f0", + "reference": "d79c053d972856b8b941bb233e39dc521a5093f0", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "^1.7", + "phar-io/manifest": "^1.0.2", + "phar-io/version": "^2.0", + "php": "^7.1", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^6.0.7", + "phpunit/php-file-iterator": "^2.0.1", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^2.1", + "sebastian/comparator": "^3.0", + "sebastian/diff": "^3.0", + "sebastian/environment": "^4.0", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^2.0", + "sebastian/version": "^2.0.1" + }, + "conflict": { + "phpunit/phpunit-mock-objects": "*" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*", + "phpunit/php-invoker": "^2.0" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2019-08-21T07:05:16+00:00" + }, + { + "name": "psr/log", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2018-11-20T15:27:04+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2017-03-04T06:30:41+00:00" + }, + { + "name": "sebastian/comparator", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "shasum": "" + }, + "require": { + "php": "^7.1", + "sebastian/diff": "^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2018-07-12T15:12:46+00:00" + }, + { + "name": "sebastian/diff", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.0", + "symfony/process": "^2 || ^3.3 || ^4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "time": "2019-02-04T06:01:07+00:00" + }, + { + "name": "sebastian/environment", + "version": "4.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404", + "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2019-05-05T09:05:15+00:00" + }, + { + "name": "sebastian/exporter", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "06a9a5947f47b3029d76118eb5c22802e5869687" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/06a9a5947f47b3029d76118eb5c22802e5869687", + "reference": "06a9a5947f47b3029d76118eb5c22802e5869687", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2019-08-11T12:43:14+00:00" + }, + { + "name": "sebastian/global-state", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2017-04-27T15:39:26+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-08-03T12:35:26+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "773f97c67f28de00d397be301821b06708fca0be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", + "reference": "773f97c67f28de00d397be301821b06708fca0be", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2017-03-29T09:07:27+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2017-03-03T06:23:57+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", + "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2018-10-04T04:07:39+00:00" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-10-03T07:35:21+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "379deb987e26c7cd103a7b387aea178baec96e48" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/379deb987e26c7cd103a7b387aea178baec96e48", + "reference": "379deb987e26c7cd103a7b387aea178baec96e48", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "http://www.squizlabs.com/php-codesniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2018-12-19T23:57:18+00:00" + }, + { + "name": "symfony/console", + "version": "v4.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "9dc2299a016497f9ee620be94524e6c0af0280a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/9dc2299a016497f9ee620be94524e6c0af0280a9", + "reference": "9dc2299a016497f9ee620be94524e6c0af0280a9", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/contracts": "^1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2019-02-23T15:17:42+00:00" + }, + { + "name": "symfony/contracts", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/contracts.git", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/contracts/zipball/1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "psr/cache": "^1.0", + "psr/container": "^1.0" + }, + "suggest": { + "psr/cache": "When using the Cache contracts", + "psr/container": "When using the Service contracts", + "symfony/cache-contracts-implementation": "", + "symfony/service-contracts-implementation": "", + "symfony/translation-contracts-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\": "" + }, + "exclude-from-classmap": [ + "**/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A set of abstractions extracted out of the Symfony components", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2018-12-05T08:06:11+00:00" + }, + { + "name": "symfony/finder", + "version": "v4.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "267b7002c1b70ea80db0833c3afe05f0fbde580a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/267b7002c1b70ea80db0833c3afe05f0fbde580a", + "reference": "267b7002c1b70ea80db0833c3afe05f0fbde580a", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2019-02-23T15:42:05+00:00" + }, + { + "name": "symfony/phpunit-bridge", + "version": "v4.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/phpunit-bridge.git", + "reference": "2cc651a38fcb831a405c14fcb76fcb00320e7ee8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/2cc651a38fcb831a405c14fcb76fcb00320e7ee8", + "reference": "2cc651a38fcb831a405c14fcb76fcb00320e7ee8", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" + }, + "suggest": { + "symfony/debug": "For tracking deprecated interfaces usages at runtime with DebugClassLoader" + }, + "bin": [ + "bin/simple-phpunit" + ], + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + }, + "thanks": { + "name": "phpunit/phpunit", + "url": "https://github.com/sebastianbergmann/phpunit" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Bridge\\PhpUnit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony PHPUnit Bridge", + "homepage": "https://symfony.com", + "time": "2019-02-18T06:49:49+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2018-09-21T13:07:52+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "role": "Developer", + "email": "arne@blankerts.de" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2019-06-13T22:48:21+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4", + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^7.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2019-08-24T08:43:50+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.1" + }, + "platform-dev": [] +} diff --git a/vendor/doctrine/common/docs/en/index.rst b/vendor/doctrine/common/docs/en/index.rst new file mode 100644 index 0000000..7550d8b --- /dev/null +++ b/vendor/doctrine/common/docs/en/index.rst @@ -0,0 +1,10 @@ +Common Documentation +==================== + +Welcome to the Doctrine Common Library documentation. + +.. toctree:: + :depth: 2 + :glob: + + * diff --git a/vendor/doctrine/common/docs/en/reference/class-loading.rst b/vendor/doctrine/common/docs/en/reference/class-loading.rst new file mode 100644 index 0000000..e193b46 --- /dev/null +++ b/vendor/doctrine/common/docs/en/reference/class-loading.rst @@ -0,0 +1,242 @@ +Class Loading +============= + +Class loading is an essential part of any PHP application that +makes heavy use of classes and interfaces. Unfortunately, a lot of +people and projects spend a lot of time and effort on custom and +specialized class loading strategies. It can quickly become a pain +to understand what is going on when using multiple libraries and/or +frameworks, each with its own way to do class loading. Class +loading should be simple and it is an ideal candidate for +convention over configuration. + +Overview +-------- + +The Doctrine Common ClassLoader implements a simple and efficient +approach to class loading that is easy to understand and use. The +implementation is based on the widely used and accepted convention +of mapping namespace and class names to a directory structure. This +approach is used for example by Symfony2, the Zend Framework and of +course, Doctrine. + +For example, the following class: + +.. code-block:: php + + register(); + $dbalLoader->register(); + $ormLoader->register(); + +Do not be afraid of using multiple class loaders. Due to the +efficient class loading design you will not incur much overhead +from using many class loaders. Take a look at the implementation of +``ClassLoader#loadClass`` to see how simple and efficient the class +loading is. The iteration over the installed class loaders happens +in C (with the exception of using ``ClassLoader::classExists``). + +A ClassLoader can be used in the following other variations, +however, these are rarely used/needed: + + +- If only the second argument is not supplied, the class loader + will be responsible for the namespace prefix given in the first + argument and it will rely on the PHP include_path. + +- If only the first argument is not supplied, the class loader + will be responsible for *all* classes and it will try to look up + *all* classes starting at the directory given as the second + argument. + +- If both arguments are not supplied, the class loader will be + responsible for *all* classes and it will rely on the PHP + include_path. + + +File Extension +-------------- + +By default, a ClassLoader uses the ``.php`` file extension for all +class files. You can change this behavior, for example to use a +ClassLoader to load classes from a library that uses the +".class.php" convention (but it must nevertheless adhere to the +directory structure convention!): + +.. code-block:: php + + setFileExtension('.class.php'); + $customLoader->register(); + +Namespace Separator +------------------- + +By default, a ClassLoader uses the ``\`` namespace separator. You +can change this behavior, for example to use a ClassLoader to load +legacy Zend Framework classes that still use the underscore "_" +separator: + +.. code-block:: php + + setNamespaceSeparator('_'); + $zend1Loader->register(); + +Failing Silently and class_exists +---------------------------------- + +A lot of class/autoloaders these days try to fail silently when a +class file is not found. For the most part this is necessary in +order to support using ``class_exists('ClassName', true)`` which is +supposed to return a boolean value but triggers autoloading. This +is a bad thing as it basically forces class loaders to fail +silently, which in turn requires costly file_exists or fopen calls +for each class being loaded, even though in at least 99% of the +cases this is not necessary (compare the number of +class_exists(..., true) invocations to the total number of classes +being loaded in a request). + +The Doctrine Common ClassLoader does not fail silently, by design. +It therefore does not need any costly checks for file existence. A +ClassLoader is always responsible for all classes with a certain +namespace prefix and if a class is requested to be loaded and can +not be found this is considered to be a fatal error. This also +means that using class_exists(..., true) to check for class +existence when using a Doctrine Common ClassLoader is not possible +but this is not a bad thing. What class\_exists(..., true) actually +means is two things: 1) Check whether the class is already +defined/exists (i.e. class_exists(..., false)) and if not 2) check +whether a class file can be loaded for that class. In the Doctrine +Common ClassLoader the two responsibilities of loading a class and +checking for its existence are separated, which can be observed by +the existence of the two methods ``loadClass`` and +``canLoadClass``. Thereby ``loadClass`` does not invoke +``canLoadClass`` internally, by design. However, you are free to +use it yourself to check whether a class can be loaded and the +following code snippet is thus equivalent to class\_exists(..., +true): + +.. code-block:: php + + canLoadClass('Foo')) { + // ... + } + +The only problem with this is that it is inconvenient as you need +to have a reference to the class loaders around (and there are +often multiple class loaders in use). Therefore, a simpler +alternative exists for the cases in which you really want to ask +all installed class loaders whether they can load the class: +``ClassLoader::classExists($className)``: + +.. code-block:: php + + ClassLoader 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 include_path. + * + * @author Roman Borschel + * @since 2.0 + * + * @deprecated The ClassLoader is deprecated and will be removed in version 3.0 of doctrine/common. + */ +class ClassLoader +{ + /** + * PHP file extension. + * + * @var string + */ + protected $fileExtension = '.php'; + + /** + * Current namespace. + * + * @var string|null + */ + protected $namespace; + + /** + * Current include path. + * + * @var string|null + */ + protected $includePath; + + /** + * PHP namespace separator. + * + * @var string + */ + protected $namespaceSeparator = '\\'; + + /** + * Creates a new ClassLoader 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|null $ns The namespace of the classes to load. + * @param string|null $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. + * + * @return void + */ + 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|null $includePath + * + * @return void + */ + public function setIncludePath($includePath) + { + $this->includePath = $includePath; + } + + /** + * Gets the base include path for all class files in the namespace of this ClassLoader. + * + * @return string|null + */ + public function getIncludePath() + { + return $this->includePath; + } + + /** + * Sets the file extension of class files in the namespace of this ClassLoader. + * + * @param string $fileExtension + * + * @return void + */ + 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. + * + * @return void + */ + public function register() + { + spl_autoload_register([$this, 'loadClass']); + } + + /** + * Removes this ClassLoader from the SPL autoload stack. + * + * @return void + */ + public function unregister() + { + spl_autoload_unregister([$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 (self::typeExists($className)) { + return true; + } + + if ( ! $this->canLoadClass($className)) { + return false; + } + + require($this->includePath !== null ? $this->includePath . DIRECTORY_SEPARATOR : '') + . str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className) + . $this->fileExtension; + + return self::typeExists($className); + } + + /** + * 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; + } + + $file = str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className) . $this->fileExtension; + + if ($this->includePath !== null) { + return is_file($this->includePath . DIRECTORY_SEPARATOR . $file); + } + + return (false !== stream_resolve_include_path($file)); + } + + /** + * 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 ClassLoader, {@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 ClassLoader, 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) + { + return self::typeExists($className, true); + } + + /** + * Gets the ClassLoader 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 ClassLoader|null The ClassLoader for the class or NULL if no such ClassLoader exists. + */ + public static function getClassLoader($className) + { + foreach (spl_autoload_functions() as $loader) { + if (is_array($loader) + && ($classLoader = reset($loader)) + && $classLoader instanceof ClassLoader + && $classLoader->canLoadClass($className) + ) { + return $classLoader; + } + } + + return null; + } + + /** + * Checks whether a given type exists + * + * @param string $type + * @param bool $autoload + * + * @return bool + */ + private static function typeExists($type, $autoload = false) + { + return class_exists($type, $autoload) + || interface_exists($type, $autoload) + || trait_exists($type, $autoload); + } +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/CommonException.php b/vendor/doctrine/common/lib/Doctrine/Common/CommonException.php new file mode 100644 index 0000000..bf60621 --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/CommonException.php @@ -0,0 +1,13 @@ + + * @author Guilherme Blanco + */ +interface Comparable +{ + /** + * Compares the current object to the passed $other. + * + * Returns 0 if they are semantically equal, 1 if the other object + * is less than the current one, or -1 if its more than the current one. + * + * This method should not check for identity using ===, only for semantical equality for example + * when two different DateTime instances point to the exact same Date + TZ. + * + * @param mixed $other + * + * @return int + */ + public function compareTo($other); +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Lexer.php b/vendor/doctrine/common/lib/Doctrine/Common/Lexer.php new file mode 100644 index 0000000..8f92c26 --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/Lexer.php @@ -0,0 +1,25 @@ + + * @author Jonathan Wage + * @author Roman Borschel + * + * @deprecated Use Doctrine\Common\Lexer\AbstractLexer from doctrine/lexer package instead. + */ +abstract class Lexer extends AbstractLexer +{ +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php new file mode 100644 index 0000000..00879fc --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php @@ -0,0 +1,245 @@ + + * + * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. + */ +abstract class AbstractProxyFactory +{ + /** + * Never autogenerate a proxy and rely that it was generated by some + * process before deployment. + * + * @var integer + */ + const AUTOGENERATE_NEVER = 0; + + /** + * Always generates a new proxy in every request. + * + * This is only sane during development. + * + * @var integer + */ + const AUTOGENERATE_ALWAYS = 1; + + /** + * Autogenerate the proxy class when the proxy file does not exist. + * + * This strategy causes a file exists call whenever any proxy is used the + * first time in a request. + * + * @var integer + */ + const AUTOGENERATE_FILE_NOT_EXISTS = 2; + + /** + * Generate the proxy classes using eval(). + * + * This strategy is only sane for development, and even then it gives me + * the creeps a little. + * + * @var integer + */ + const AUTOGENERATE_EVAL = 3; + + private const AUTOGENERATE_MODES = [ + self::AUTOGENERATE_NEVER, + self::AUTOGENERATE_ALWAYS, + self::AUTOGENERATE_FILE_NOT_EXISTS, + self::AUTOGENERATE_EVAL, + ]; + + /** + * @var \Doctrine\Common\Persistence\Mapping\ClassMetadataFactory + */ + private $metadataFactory; + + /** + * @var \Doctrine\Common\Proxy\ProxyGenerator the proxy generator responsible for creating the proxy classes/files. + */ + private $proxyGenerator; + + /** + * @var int Whether to automatically (re)generate proxy classes. + */ + private $autoGenerate; + + /** + * @var \Doctrine\Common\Proxy\ProxyDefinition[] + */ + private $definitions = []; + + /** + * @param \Doctrine\Common\Proxy\ProxyGenerator $proxyGenerator + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadataFactory $metadataFactory + * @param bool|int $autoGenerate + * + * @throws \Doctrine\Common\Proxy\Exception\InvalidArgumentException When auto generate mode is not valid. + */ + public function __construct(ProxyGenerator $proxyGenerator, ClassMetadataFactory $metadataFactory, $autoGenerate) + { + $this->proxyGenerator = $proxyGenerator; + $this->metadataFactory = $metadataFactory; + $this->autoGenerate = (int) $autoGenerate; + + if ( ! in_array($this->autoGenerate, self::AUTOGENERATE_MODES, true)) { + throw InvalidArgumentException::invalidAutoGenerateMode($autoGenerate); + } + } + + /** + * Gets a reference proxy instance for the entity of the given type and identified by + * the given identifier. + * + * @param string $className + * @param array $identifier + * + * @return \Doctrine\Common\Proxy\Proxy + * + * @throws \Doctrine\Common\Proxy\Exception\OutOfBoundsException + */ + public function getProxy($className, array $identifier) + { + $definition = isset($this->definitions[$className]) + ? $this->definitions[$className] + : $this->getProxyDefinition($className); + $fqcn = $definition->proxyClassName; + $proxy = new $fqcn($definition->initializer, $definition->cloner); + + foreach ($definition->identifierFields as $idField) { + if ( ! isset($identifier[$idField])) { + throw OutOfBoundsException::missingPrimaryKeyValue($className, $idField); + } + + $definition->reflectionFields[$idField]->setValue($proxy, $identifier[$idField]); + } + + return $proxy; + } + + /** + * Generates proxy classes for all given classes. + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata[] $classes The classes (ClassMetadata instances) + * for which to generate proxies. + * @param string $proxyDir The target directory of the proxy classes. If not specified, the + * directory configured on the Configuration of the EntityManager used + * by this factory is used. + * @return int Number of generated proxies. + */ + public function generateProxyClasses(array $classes, $proxyDir = null) + { + $generated = 0; + + foreach ($classes as $class) { + if ($this->skipClass($class)) { + continue; + } + + $proxyFileName = $this->proxyGenerator->getProxyFileName($class->getName(), $proxyDir); + + $this->proxyGenerator->generateProxyClass($class, $proxyFileName); + + $generated += 1; + } + + return $generated; + } + + /** + * Reset initialization/cloning logic for an un-initialized proxy + * + * @param \Doctrine\Common\Proxy\Proxy $proxy + * + * @return \Doctrine\Common\Proxy\Proxy + * + * @throws \Doctrine\Common\Proxy\Exception\InvalidArgumentException + */ + public function resetUninitializedProxy(Proxy $proxy) + { + if ($proxy->__isInitialized()) { + throw InvalidArgumentException::unitializedProxyExpected($proxy); + } + + $className = ClassUtils::getClass($proxy); + $definition = isset($this->definitions[$className]) + ? $this->definitions[$className] + : $this->getProxyDefinition($className); + + $proxy->__setInitializer($definition->initializer); + $proxy->__setCloner($definition->cloner); + + return $proxy; + } + + /** + * Get a proxy definition for the given class name. + * + * @param string $className + * + * @return ProxyDefinition + */ + private function getProxyDefinition($className) + { + $classMetadata = $this->metadataFactory->getMetadataFor($className); + $className = $classMetadata->getName(); // aliases and case sensitivity + + $this->definitions[$className] = $this->createProxyDefinition($className); + $proxyClassName = $this->definitions[$className]->proxyClassName; + + if ( ! class_exists($proxyClassName, false)) { + $fileName = $this->proxyGenerator->getProxyFileName($className); + + switch ($this->autoGenerate) { + case self::AUTOGENERATE_NEVER: + require $fileName; + break; + + case self::AUTOGENERATE_FILE_NOT_EXISTS: + if ( ! file_exists($fileName)) { + $this->proxyGenerator->generateProxyClass($classMetadata, $fileName); + } + require $fileName; + break; + + case self::AUTOGENERATE_ALWAYS: + $this->proxyGenerator->generateProxyClass($classMetadata, $fileName); + require $fileName; + break; + + case self::AUTOGENERATE_EVAL: + $this->proxyGenerator->generateProxyClass($classMetadata, false); + break; + } + } + + return $this->definitions[$className]; + } + + /** + * Determine if this class should be skipped during proxy generation. + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $metadata + * + * @return bool + */ + abstract protected function skipClass(ClassMetadata $metadata); + + /** + * @param string $className + * + * @return ProxyDefinition + */ + abstract protected function createProxyDefinition($className); +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Autoloader.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Autoloader.php new file mode 100644 index 0000000..f5a08d7 --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Autoloader.php @@ -0,0 +1,82 @@ + + * + * @internal + * + * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. + */ +class Autoloader +{ + /** + * Resolves proxy class name to a filename based on the following pattern. + * + * 1. Remove Proxy namespace from class name. + * 2. Remove namespace separators from remaining class name. + * 3. Return PHP filename from proxy-dir with the result from 2. + * + * @param string $proxyDir + * @param string $proxyNamespace + * @param string $className + * + * @return string + * + * @throws InvalidArgumentException + */ + public static function resolveFile($proxyDir, $proxyNamespace, $className) + { + if (0 !== strpos($className, $proxyNamespace)) { + throw InvalidArgumentException::notProxyClass($className, $proxyNamespace); + } + + // remove proxy namespace from class name + $classNameRelativeToProxyNamespace = substr($className, strlen($proxyNamespace)); + + // remove namespace separators from remaining class name + $fileName = str_replace('\\', '', $classNameRelativeToProxyNamespace); + + return $proxyDir . DIRECTORY_SEPARATOR . $fileName . '.php'; + } + + /** + * Registers and returns autoloader callback for the given proxy dir and namespace. + * + * @param string $proxyDir + * @param string $proxyNamespace + * @param callable|null $notFoundCallback Invoked when the proxy file is not found. + * + * @return \Closure + * + * @throws InvalidArgumentException + */ + public static function register($proxyDir, $proxyNamespace, $notFoundCallback = null) + { + $proxyNamespace = ltrim($proxyNamespace, '\\'); + + if ( ! (null === $notFoundCallback || is_callable($notFoundCallback))) { + throw InvalidArgumentException::invalidClassNotFoundCallback($notFoundCallback); + } + + $autoloader = function ($className) use ($proxyDir, $proxyNamespace, $notFoundCallback) { + if (0 === strpos($className, $proxyNamespace)) { + $file = Autoloader::resolveFile($proxyDir, $proxyNamespace, $className); + + if ($notFoundCallback && ! file_exists($file)) { + call_user_func($notFoundCallback, $proxyDir, $proxyNamespace, $className); + } + + require $file; + } + }; + + spl_autoload_register($autoloader); + + return $autoloader; + } +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/InvalidArgumentException.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..bab3d70 --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/InvalidArgumentException.php @@ -0,0 +1,106 @@ + + * + * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. + */ +class InvalidArgumentException extends BaseInvalidArgumentException implements ProxyException +{ + /** + * @return self + */ + public static function proxyDirectoryRequired() + { + return new self('You must configure a proxy directory. See docs for details'); + } + + /** + * @param string $className + * @param string $proxyNamespace + * + * @return self + */ + public static function notProxyClass($className, $proxyNamespace) + { + return new self(sprintf('The class "%s" is not part of the proxy namespace "%s"', $className, $proxyNamespace)); + } + + /** + * @param string $name + * + * @return self + */ + public static function invalidPlaceholder($name) + { + return new self(sprintf('Provided placeholder for "%s" must be either a string or a valid callable', $name)); + } + + /** + * @return self + */ + public static function proxyNamespaceRequired() + { + return new self('You must configure a proxy namespace'); + } + + /** + * @param Proxy $proxy + * + * @return self + */ + public static function unitializedProxyExpected(Proxy $proxy) + { + return new self(sprintf('Provided proxy of type "%s" must not be initialized.', get_class($proxy))); + } + + /** + * @param mixed $callback + * + * @return self + */ + public static function invalidClassNotFoundCallback($callback) + { + $type = is_object($callback) ? get_class($callback) : gettype($callback); + + return new self(sprintf('Invalid \$notFoundCallback given: must be a callable, "%s" given', $type)); + } + + /** + * @param string $className + * + * @return self + */ + public static function classMustNotBeAbstract($className) + { + return new self(sprintf('Unable to create a proxy for an abstract class "%s".', $className)); + } + + /** + * @param string $className + * + * @return self + */ + public static function classMustNotBeFinal($className) + { + return new self(sprintf('Unable to create a proxy for a final class "%s".', $className)); + } + + /** + * @param mixed $value + * + * @return self + */ + public static function invalidAutoGenerateMode($value) : self + { + return new self(sprintf('Invalid auto generate mode "%s" given.', $value)); + } +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/OutOfBoundsException.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/OutOfBoundsException.php new file mode 100644 index 0000000..df40268 --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/OutOfBoundsException.php @@ -0,0 +1,26 @@ + + * + * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. + */ +class OutOfBoundsException extends BaseOutOfBoundsException implements ProxyException +{ + /** + * @param string $className + * @param string $idField + * + * @return self + */ + public static function missingPrimaryKeyValue($className, $idField) + { + return new self(sprintf("Missing value for primary key %s on %s", $idField, $className)); + } +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/ProxyException.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/ProxyException.php new file mode 100644 index 0000000..751f9a9 --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/ProxyException.php @@ -0,0 +1,15 @@ + + * + * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. + */ +interface ProxyException +{ +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php new file mode 100644 index 0000000..f3e7c18 --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php @@ -0,0 +1,72 @@ + + * + * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. + */ +class UnexpectedValueException extends BaseUnexpectedValueException implements ProxyException +{ + /** + * @param string $proxyDirectory + * + * @return self + */ + public static function proxyDirectoryNotWritable($proxyDirectory) + { + return new self(sprintf('Your proxy directory "%s" must be writable', $proxyDirectory)); + } + + /** + * @param string $className + * @param string $methodName + * @param string $parameterName + * @param \Exception|null $previous + * + * @return self + */ + public static function invalidParameterTypeHint( + $className, + $methodName, + $parameterName, + \Exception $previous = null + ) { + return new self( + sprintf( + 'The type hint of parameter "%s" in method "%s" in class "%s" is invalid.', + $parameterName, + $methodName, + $className + ), + 0, + $previous + ); + } + + /** + * @param string $className + * @param string $methodName + * @param \Exception|null $previous + * + * @return self + */ + public static function invalidReturnTypeHint($className, $methodName, \Exception $previous = null) + { + return new self( + sprintf( + 'The return type of method "%s" in class "%s" is invalid.', + $methodName, + $className + ), + 0, + $previous + ); + } +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Proxy.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Proxy.php new file mode 100644 index 0000000..1e76b71 --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Proxy.php @@ -0,0 +1,74 @@ + + * @author Marco Pivetta + * @since 2.4 + * + * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. + */ +interface Proxy extends BaseProxy +{ + /** + * Marks the proxy as initialized or not. + * + * @param boolean $initialized + * + * @return void + */ + public function __setInitialized($initialized); + + /** + * Sets the initializer callback to be used when initializing the proxy. That + * initializer should accept 3 parameters: $proxy, $method and $params. Those + * are respectively the proxy object that is being initialized, the method name + * that triggered initialization and the parameters passed to that method. + * + * @param Closure|null $initializer + * + * @return void + */ + public function __setInitializer(Closure $initializer = null); + + /** + * Retrieves the initializer callback used to initialize the proxy. + * + * @see __setInitializer + * + * @return Closure|null + */ + public function __getInitializer(); + + /** + * Sets the callback to be used when cloning the proxy. That initializer should accept + * a single parameter, which is the cloned proxy instance itself. + * + * @param Closure|null $cloner + * + * @return void + */ + public function __setCloner(Closure $cloner = null); + + /** + * Retrieves the callback to be used when cloning the proxy. + * + * @see __setCloner + * + * @return Closure|null + */ + public function __getCloner(); + + /** + * Retrieves the list of lazy loaded properties for a given proxy + * + * @return array Keys are the property names, and values are the default values + * for those properties. + */ + public function __getLazyProperties(); +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyDefinition.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyDefinition.php new file mode 100644 index 0000000..cb13cec --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyDefinition.php @@ -0,0 +1,53 @@ + + * + * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. + */ +class ProxyDefinition +{ + /** + * @var string + */ + public $proxyClassName; + + /** + * @var array + */ + public $identifierFields; + + /** + * @var \ReflectionProperty[] + */ + public $reflectionFields; + + /** + * @var callable + */ + public $initializer; + + /** + * @var callable + */ + public $cloner; + + /** + * @param string $proxyClassName + * @param array $identifierFields + * @param array $reflectionFields + * @param callable $initializer + * @param callable $cloner + */ + public function __construct($proxyClassName, array $identifierFields, array $reflectionFields, $initializer, $cloner) + { + $this->proxyClassName = $proxyClassName; + $this->identifierFields = $identifierFields; + $this->reflectionFields = $reflectionFields; + $this->initializer = $initializer; + $this->cloner = $cloner; + } +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php new file mode 100644 index 0000000..c8da39b --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php @@ -0,0 +1,1062 @@ + + * @since 2.4 + * + * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. + */ +class ProxyGenerator +{ + /** + * Used to match very simple id methods that don't need + * to be decorated since the identifier is known. + */ + const PATTERN_MATCH_ID_METHOD = '((public\s+)?(function\s+%s\s*\(\)\s*)\s*(?::\s*\??\s*\\\\?[a-z_\x7f-\xff][\w\x7f-\xff]*(?:\\\\[a-z_\x7f-\xff][\w\x7f-\xff]*)*\s*)?{\s*return\s*\$this->%s;\s*})i'; + + /** + * The namespace that contains all proxy classes. + * + * @var string + */ + private $proxyNamespace; + + /** + * The directory that contains all proxy classes. + * + * @var string + */ + private $proxyDirectory; + + /** + * Map of callables used to fill in placeholders set in the template. + * + * @var string[]|callable[] + */ + protected $placeholders = [ + 'baseProxyInterface' => Proxy::class, + 'additionalProperties' => '', + ]; + + /** + * Template used as a blueprint to generate proxies. + * + * @var string + */ + protected $proxyClassTemplate = '; + +/** + * DO NOT EDIT THIS FILE - IT WAS CREATED BY DOCTRINE\'S PROXY GENERATOR + */ +class extends \ implements \ +{ + /** + * @var \Closure the callback responsible for loading properties in the proxy object. This callback is called with + * three parameters, being respectively the proxy object to be initialized, the method that triggered the + * initialization process and an array of ordered parameters that were passed to that method. + * + * @see \Doctrine\Common\Proxy\Proxy::__setInitializer + */ + public $__initializer__; + + /** + * @var \Closure the callback responsible of loading properties that need to be copied in the cloned object + * + * @see \Doctrine\Common\Proxy\Proxy::__setCloner + */ + public $__cloner__; + + /** + * @var boolean flag indicating if this object was already initialized + * + * @see \Doctrine\Common\Persistence\Proxy::__isInitialized + */ + public $__isInitialized__ = false; + + /** + * @var array properties to be lazy loaded, with keys being the property + * names and values being their default values + * + * @see \Doctrine\Common\Proxy\Proxy::__getLazyProperties + */ + public static $lazyPropertiesDefaults = []; + + + + + + + + + + + + + + + + + + /** + * Forces initialization of the proxy + */ + public function __load() + { + $this->__initializer__ && $this->__initializer__->__invoke($this, \'__load\', []); + } + + /** + * {@inheritDoc} + * @internal generated method: use only when explicitly handling proxy specific loading logic + */ + public function __isInitialized() + { + return $this->__isInitialized__; + } + + /** + * {@inheritDoc} + * @internal generated method: use only when explicitly handling proxy specific loading logic + */ + public function __setInitialized($initialized) + { + $this->__isInitialized__ = $initialized; + } + + /** + * {@inheritDoc} + * @internal generated method: use only when explicitly handling proxy specific loading logic + */ + public function __setInitializer(\Closure $initializer = null) + { + $this->__initializer__ = $initializer; + } + + /** + * {@inheritDoc} + * @internal generated method: use only when explicitly handling proxy specific loading logic + */ + public function __getInitializer() + { + return $this->__initializer__; + } + + /** + * {@inheritDoc} + * @internal generated method: use only when explicitly handling proxy specific loading logic + */ + public function __setCloner(\Closure $cloner = null) + { + $this->__cloner__ = $cloner; + } + + /** + * {@inheritDoc} + * @internal generated method: use only when explicitly handling proxy specific cloning logic + */ + public function __getCloner() + { + return $this->__cloner__; + } + + /** + * {@inheritDoc} + * @internal generated method: use only when explicitly handling proxy specific loading logic + * @static + */ + public function __getLazyProperties() + { + return self::$lazyPropertiesDefaults; + } + + +} +'; + + /** + * Initializes a new instance of the ProxyFactory class that is + * connected to the given EntityManager. + * + * @param string $proxyDirectory The directory to use for the proxy classes. It must exist. + * @param string $proxyNamespace The namespace to use for the proxy classes. + * + * @throws InvalidArgumentException + */ + public function __construct($proxyDirectory, $proxyNamespace) + { + if ( ! $proxyDirectory) { + throw InvalidArgumentException::proxyDirectoryRequired(); + } + + if ( ! $proxyNamespace) { + throw InvalidArgumentException::proxyNamespaceRequired(); + } + + $this->proxyDirectory = $proxyDirectory; + $this->proxyNamespace = $proxyNamespace; + } + + /** + * Sets a placeholder to be replaced in the template. + * + * @param string $name + * @param string|callable $placeholder + * + * @throws InvalidArgumentException + */ + public function setPlaceholder($name, $placeholder) + { + if ( ! is_string($placeholder) && ! is_callable($placeholder)) { + throw InvalidArgumentException::invalidPlaceholder($name); + } + + $this->placeholders[$name] = $placeholder; + } + + /** + * Sets the base template used to create proxy classes. + * + * @param string $proxyClassTemplate + */ + public function setProxyClassTemplate($proxyClassTemplate) + { + $this->proxyClassTemplate = (string) $proxyClassTemplate; + } + + /** + * Generates a proxy class file. + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class Metadata for the original class. + * @param string|bool $fileName Filename (full path) for the generated class. If none is given, eval() is used. + * + * @throws InvalidArgumentException + * @throws UnexpectedValueException + */ + public function generateProxyClass(ClassMetadata $class, $fileName = false) + { + $this->verifyClassCanBeProxied($class); + + preg_match_all('(<([a-zA-Z]+)>)', $this->proxyClassTemplate, $placeholderMatches); + + $placeholderMatches = array_combine($placeholderMatches[0], $placeholderMatches[1]); + $placeholders = []; + + foreach ($placeholderMatches as $placeholder => $name) { + $placeholders[$placeholder] = isset($this->placeholders[$name]) + ? $this->placeholders[$name] + : [$this, 'generate' . $name]; + } + + foreach ($placeholders as & $placeholder) { + if (is_callable($placeholder)) { + $placeholder = call_user_func($placeholder, $class); + } + } + + $proxyCode = strtr($this->proxyClassTemplate, $placeholders); + + if ( ! $fileName) { + $proxyClassName = $this->generateNamespace($class) . '\\' . $this->generateProxyShortClassName($class); + + if ( ! class_exists($proxyClassName)) { + eval(substr($proxyCode, 5)); + } + + return; + } + + $parentDirectory = dirname($fileName); + + if ( ! is_dir($parentDirectory) && (false === @mkdir($parentDirectory, 0775, true))) { + throw UnexpectedValueException::proxyDirectoryNotWritable($this->proxyDirectory); + } + + if ( ! is_writable($parentDirectory)) { + throw UnexpectedValueException::proxyDirectoryNotWritable($this->proxyDirectory); + } + + $tmpFileName = $fileName . '.' . uniqid('', true); + + file_put_contents($tmpFileName, $proxyCode); + @chmod($tmpFileName, 0664); + rename($tmpFileName, $fileName); + } + + /** + * @param ClassMetadata $class + * + * @throws InvalidArgumentException + */ + private function verifyClassCanBeProxied(ClassMetadata $class) + { + if ($class->getReflectionClass()->isFinal()) { + throw InvalidArgumentException::classMustNotBeFinal($class->getName()); + } + + if ($class->getReflectionClass()->isAbstract()) { + throw InvalidArgumentException::classMustNotBeAbstract($class->getName()); + } + } + + /** + * Generates the proxy short class name to be used in the template. + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return string + */ + private function generateProxyShortClassName(ClassMetadata $class) + { + $proxyClassName = ClassUtils::generateProxyClassName($class->getName(), $this->proxyNamespace); + $parts = explode('\\', strrev($proxyClassName), 2); + + return strrev($parts[0]); + } + + /** + * Generates the proxy namespace. + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return string + */ + private function generateNamespace(ClassMetadata $class) + { + $proxyClassName = ClassUtils::generateProxyClassName($class->getName(), $this->proxyNamespace); + $parts = explode('\\', strrev($proxyClassName), 2); + + return strrev($parts[1]); + } + + /** + * Generates the original class name. + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return string + */ + private function generateClassName(ClassMetadata $class) + { + return ltrim($class->getName(), '\\'); + } + + /** + * Generates the array representation of lazy loaded public properties and their default values. + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return string + */ + private function generateLazyPropertiesDefaults(ClassMetadata $class) + { + $lazyPublicProperties = $this->getLazyLoadedPublicProperties($class); + $values = []; + + foreach ($lazyPublicProperties as $key => $value) { + $values[] = var_export($key, true) . ' => ' . var_export($value, true); + } + + return implode(', ', $values); + } + + /** + * Generates the constructor code (un-setting public lazy loaded properties, setting identifier field values). + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return string + */ + private function generateConstructorImpl(ClassMetadata $class) + { + $constructorImpl = <<<'EOT' + /** + * @param \Closure $initializer + * @param \Closure $cloner + */ + public function __construct($initializer = null, $cloner = null) + { + +EOT; + $toUnset = []; + + foreach ($this->getLazyLoadedPublicProperties($class) as $lazyPublicProperty => $unused) { + $toUnset[] = '$this->' . $lazyPublicProperty; + } + + $constructorImpl .= (empty($toUnset) ? '' : ' unset(' . implode(', ', $toUnset) . ");\n") + . <<<'EOT' + + $this->__initializer__ = $initializer; + $this->__cloner__ = $cloner; + } +EOT; + + return $constructorImpl; + } + + /** + * Generates the magic getter invoked when lazy loaded public properties are requested. + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return string + */ + private function generateMagicGet(ClassMetadata $class) + { + $lazyPublicProperties = array_keys($this->getLazyLoadedPublicProperties($class)); + $reflectionClass = $class->getReflectionClass(); + $hasParentGet = false; + $returnReference = ''; + $inheritDoc = ''; + + if ($reflectionClass->hasMethod('__get')) { + $hasParentGet = true; + $inheritDoc = '{@inheritDoc}'; + + if ($reflectionClass->getMethod('__get')->returnsReference()) { + $returnReference = '& '; + } + } + + if (empty($lazyPublicProperties) && ! $hasParentGet) { + return ''; + } + + $magicGet = <<__getLazyProperties())) { + $this->__initializer__ && $this->__initializer__->__invoke($this, '__get', [$name]); + + return $this->$name; + } + + +EOT; + } + + if ($hasParentGet) { + $magicGet .= <<<'EOT' + $this->__initializer__ && $this->__initializer__->__invoke($this, '__get', [$name]); + + return parent::__get($name); + +EOT; + } else { + $magicGet .= <<<'EOT' + trigger_error(sprintf('Undefined property: %s::$%s', __CLASS__, $name), E_USER_NOTICE); + +EOT; + } + + $magicGet .= " }"; + + return $magicGet; + } + + /** + * Generates the magic setter (currently unused). + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return string + */ + private function generateMagicSet(ClassMetadata $class) + { + $lazyPublicProperties = $this->getLazyLoadedPublicProperties($class); + $hasParentSet = $class->getReflectionClass()->hasMethod('__set'); + + if (empty($lazyPublicProperties) && ! $hasParentSet) { + return ''; + } + + $inheritDoc = $hasParentSet ? '{@inheritDoc}' : ''; + $magicSet = <<__getLazyProperties())) { + $this->__initializer__ && $this->__initializer__->__invoke($this, '__set', [$name, $value]); + + $this->$name = $value; + + return; + } + + +EOT; + } + + if ($hasParentSet) { + $magicSet .= <<<'EOT' + $this->__initializer__ && $this->__initializer__->__invoke($this, '__set', [$name, $value]); + + return parent::__set($name, $value); +EOT; + } else { + $magicSet .= " \$this->\$name = \$value;"; + } + + $magicSet .= "\n }"; + + return $magicSet; + } + + /** + * Generates the magic issetter invoked when lazy loaded public properties are checked against isset(). + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return string + */ + private function generateMagicIsset(ClassMetadata $class) + { + $lazyPublicProperties = array_keys($this->getLazyLoadedPublicProperties($class)); + $hasParentIsset = $class->getReflectionClass()->hasMethod('__isset'); + + if (empty($lazyPublicProperties) && ! $hasParentIsset) { + return ''; + } + + $inheritDoc = $hasParentIsset ? '{@inheritDoc}' : ''; + $magicIsset = <<__getLazyProperties())) { + $this->__initializer__ && $this->__initializer__->__invoke($this, '__isset', [$name]); + + return isset($this->$name); + } + + +EOT; + } + + if ($hasParentIsset) { + $magicIsset .= <<<'EOT' + $this->__initializer__ && $this->__initializer__->__invoke($this, '__isset', [$name]); + + return parent::__isset($name); + +EOT; + } else { + $magicIsset .= " return false;"; + } + + return $magicIsset . "\n }"; + } + + /** + * Generates implementation for the `__sleep` method of proxies. + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return string + */ + private function generateSleepImpl(ClassMetadata $class) + { + $hasParentSleep = $class->getReflectionClass()->hasMethod('__sleep'); + $inheritDoc = $hasParentSleep ? '{@inheritDoc}' : ''; + $sleepImpl = <<__isInitialized__) { + $properties = array_diff($properties, array_keys($this->__getLazyProperties())); + } + + return $properties; + } +EOT; + } + + $allProperties = ['__isInitialized__']; + + /* @var $prop \ReflectionProperty */ + foreach ($class->getReflectionClass()->getProperties() as $prop) { + if ($prop->isStatic()) { + continue; + } + + $allProperties[] = $prop->isPrivate() + ? "\0" . $prop->getDeclaringClass()->getName() . "\0" . $prop->getName() + : $prop->getName(); + } + + $lazyPublicProperties = array_keys($this->getLazyLoadedPublicProperties($class)); + $protectedProperties = array_diff($allProperties, $lazyPublicProperties); + + foreach ($allProperties as &$property) { + $property = var_export($property, true); + } + + foreach ($protectedProperties as &$property) { + $property = var_export($property, true); + } + + $allProperties = implode(', ', $allProperties); + $protectedProperties = implode(', ', $protectedProperties); + + return $sleepImpl . <<__isInitialized__) { + return [$allProperties]; + } + + return [$protectedProperties]; + } +EOT; + } + + /** + * Generates implementation for the `__wakeup` method of proxies. + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return string + */ + private function generateWakeupImpl(ClassMetadata $class) + { + $unsetPublicProperties = []; + $hasWakeup = $class->getReflectionClass()->hasMethod('__wakeup'); + + foreach (array_keys($this->getLazyLoadedPublicProperties($class)) as $lazyPublicProperty) { + $unsetPublicProperties[] = '$this->' . $lazyPublicProperty; + } + + $shortName = $this->generateProxyShortClassName($class); + $inheritDoc = $hasWakeup ? '{@inheritDoc}' : ''; + $wakeupImpl = <<__isInitialized__) { + \$this->__initializer__ = function ($shortName \$proxy) { + \$proxy->__setInitializer(null); + \$proxy->__setCloner(null); + + \$existingProperties = get_object_vars(\$proxy); + + foreach (\$proxy->__getLazyProperties() as \$property => \$defaultValue) { + if ( ! array_key_exists(\$property, \$existingProperties)) { + \$proxy->\$property = \$defaultValue; + } + } + }; + +EOT; + + if ( ! empty($unsetPublicProperties)) { + $wakeupImpl .= "\n unset(" . implode(', ', $unsetPublicProperties) . ");"; + } + + $wakeupImpl .= "\n }"; + + if ($hasWakeup) { + $wakeupImpl .= "\n parent::__wakeup();"; + } + + $wakeupImpl .= "\n }"; + + return $wakeupImpl; + } + + /** + * Generates implementation for the `__clone` method of proxies. + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return string + */ + private function generateCloneImpl(ClassMetadata $class) + { + $hasParentClone = $class->getReflectionClass()->hasMethod('__clone'); + $inheritDoc = $hasParentClone ? '{@inheritDoc}' : ''; + $callParentClone = $hasParentClone ? "\n parent::__clone();\n" : ''; + + return <<__cloner__ && \$this->__cloner__->__invoke(\$this, '__clone', []); +$callParentClone } +EOT; + } + + /** + * Generates decorated methods by picking those available in the parent class. + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return string + */ + private function generateMethods(ClassMetadata $class) + { + $methods = ''; + $methodNames = []; + $reflectionMethods = $class->getReflectionClass()->getMethods(\ReflectionMethod::IS_PUBLIC); + $skippedMethods = [ + '__sleep' => true, + '__clone' => true, + '__wakeup' => true, + '__get' => true, + '__set' => true, + '__isset' => true, + ]; + + foreach ($reflectionMethods as $method) { + $name = $method->getName(); + + if ($method->isConstructor() || + isset($skippedMethods[strtolower($name)]) || + isset($methodNames[$name]) || + $method->isFinal() || + $method->isStatic() || + ( ! $method->isPublic()) + ) { + continue; + } + + $methodNames[$name] = true; + $methods .= "\n /**\n" + . " * {@inheritDoc}\n" + . " */\n" + . ' public function '; + + if ($method->returnsReference()) { + $methods .= '&'; + } + + $methods .= $name . '(' . $this->buildParametersString($method->getParameters()) . ')'; + $methods .= $this->getMethodReturnType($method); + $methods .= "\n" . ' {' . "\n"; + + if ($this->isShortIdentifierGetter($method, $class)) { + $identifier = lcfirst(substr($name, 3)); + $fieldType = $class->getTypeOfField($identifier); + $cast = in_array($fieldType, ['integer', 'smallint']) ? '(int) ' : ''; + + $methods .= ' if ($this->__isInitialized__ === false) {' . "\n"; + $methods .= ' '; + $methods .= $this->shouldProxiedMethodReturn($method) ? 'return ' : ''; + $methods .= $cast . ' parent::' . $method->getName() . "();\n"; + $methods .= ' }' . "\n\n"; + } + + $invokeParamsString = implode(', ', $this->getParameterNamesForInvoke($method->getParameters())); + $callParamsString = implode(', ', $this->getParameterNamesForParentCall($method->getParameters())); + + $methods .= "\n \$this->__initializer__ " + . "&& \$this->__initializer__->__invoke(\$this, " . var_export($name, true) + . ", [" . $invokeParamsString . "]);" + . "\n\n " + . ($this->shouldProxiedMethodReturn($method) ? 'return ' : '') + . "parent::" . $name . '(' . $callParamsString . ');' + . "\n" . ' }' . "\n"; + } + + return $methods; + } + + /** + * Generates the Proxy file name. + * + * @param string $className + * @param string $baseDirectory Optional base directory for proxy file name generation. + * If not specified, the directory configured on the Configuration of the + * EntityManager will be used by this factory. + * + * @return string + */ + public function getProxyFileName($className, $baseDirectory = null) + { + $baseDirectory = $baseDirectory ?: $this->proxyDirectory; + + return rtrim($baseDirectory, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . Proxy::MARKER + . str_replace('\\', '', $className) . '.php'; + } + + /** + * Checks if the method is a short identifier getter. + * + * What does this mean? For proxy objects the identifier is already known, + * however accessing the getter for this identifier usually triggers the + * lazy loading, leading to a query that may not be necessary if only the + * ID is interesting for the userland code (for example in views that + * generate links to the entity, but do not display anything else). + * + * @param \ReflectionMethod $method + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return boolean + */ + private function isShortIdentifierGetter($method, ClassMetadata $class) + { + $identifier = lcfirst(substr($method->getName(), 3)); + $startLine = $method->getStartLine(); + $endLine = $method->getEndLine(); + $cheapCheck = ( + $method->getNumberOfParameters() == 0 + && substr($method->getName(), 0, 3) == 'get' + && in_array($identifier, $class->getIdentifier(), true) + && $class->hasField($identifier) + && (($endLine - $startLine) <= 4) + ); + + if ($cheapCheck) { + $code = file($method->getFileName()); + $code = trim(implode(' ', array_slice($code, $startLine - 1, $endLine - $startLine + 1))); + + $pattern = sprintf(self::PATTERN_MATCH_ID_METHOD, $method->getName(), $identifier); + + if (preg_match($pattern, $code)) { + return true; + } + } + + return false; + } + + /** + * Generates the list of public properties to be lazy loaded, with their default values. + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class + * + * @return mixed[] + */ + private function getLazyLoadedPublicProperties(ClassMetadata $class) + { + $defaultProperties = $class->getReflectionClass()->getDefaultProperties(); + $properties = []; + + foreach ($class->getReflectionClass()->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { + $name = $property->getName(); + + if (($class->hasField($name) || $class->hasAssociation($name)) && ! $class->isIdentifier($name)) { + $properties[$name] = $defaultProperties[$name]; + } + } + + return $properties; + } + + /** + * @param \ReflectionParameter[] $parameters + * + * @return string + */ + private function buildParametersString(array $parameters) + { + $parameterDefinitions = []; + + /* @var $param \ReflectionParameter */ + foreach ($parameters as $param) { + $parameterDefinition = ''; + + if ($parameterType = $this->getParameterType($param)) { + $parameterDefinition .= $parameterType . ' '; + } + + if ($param->isPassedByReference()) { + $parameterDefinition .= '&'; + } + + if ($param->isVariadic()) { + $parameterDefinition .= '...'; + } + + $parameterDefinition .= '$' . $param->getName(); + + if ($param->isDefaultValueAvailable()) { + $parameterDefinition .= ' = ' . var_export($param->getDefaultValue(), true); + } + + $parameterDefinitions[] = $parameterDefinition; + } + + return implode(', ', $parameterDefinitions); + } + + /** + * @param \ReflectionParameter $parameter + * + * @return string|null + */ + private function getParameterType(\ReflectionParameter $parameter) + { + if ( ! $parameter->hasType()) { + return null; + } + + return $this->formatType($parameter->getType(), $parameter->getDeclaringFunction(), $parameter); + } + + /** + * @param \ReflectionParameter[] $parameters + * + * @return string[] + */ + private function getParameterNamesForInvoke(array $parameters) + { + return array_map( + function (\ReflectionParameter $parameter) { + return '$' . $parameter->getName(); + }, + $parameters + ); + } + + /** + * @param \ReflectionParameter[] $parameters + * + * @return string[] + */ + private function getParameterNamesForParentCall(array $parameters) + { + return array_map( + function (\ReflectionParameter $parameter) { + $name = ''; + + if ($parameter->isVariadic()) { + $name .= '...'; + } + + $name .= '$' . $parameter->getName(); + + return $name; + }, + $parameters + ); + } + + /** + * @param \ReflectionMethod $method + * + * @return string + */ + private function getMethodReturnType(\ReflectionMethod $method) + { + if ( ! $method->hasReturnType()) { + return ''; + } + + return ': ' . $this->formatType($method->getReturnType(), $method); + } + + /** + * @param \ReflectionMethod $method + * + * @return bool + */ + private function shouldProxiedMethodReturn(\ReflectionMethod $method) + { + if ( ! $method->hasReturnType()) { + return true; + } + + return 'void' !== strtolower($this->formatType($method->getReturnType(), $method)); + } + + /** + * @param \ReflectionType $type + * @param \ReflectionMethod $method + * @param \ReflectionParameter|null $parameter + * + * @return string + */ + private function formatType( + \ReflectionType $type, + \ReflectionMethod $method, + \ReflectionParameter $parameter = null + ) { + $name = $type->getName(); + $nameLower = strtolower($name); + + if ('self' === $nameLower) { + $name = $method->getDeclaringClass()->getName(); + } + + if ('parent' === $nameLower) { + $name = $method->getDeclaringClass()->getParentClass()->getName(); + } + + if ( ! $type->isBuiltin() && ! class_exists($name) && ! interface_exists($name)) { + if (null !== $parameter) { + throw UnexpectedValueException::invalidParameterTypeHint( + $method->getDeclaringClass()->getName(), + $method->getName(), + $parameter->getName() + ); + } + + throw UnexpectedValueException::invalidReturnTypeHint( + $method->getDeclaringClass()->getName(), + $method->getName() + ); + } + + if ( ! $type->isBuiltin()) { + $name = '\\' . $name; + } + + if ($type->allowsNull() + && (null === $parameter || ! $parameter->isDefaultValueAvailable() || null !== $parameter->getDefaultValue()) + ) { + $name = '?' . $name; + } + + return $name; + } +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Util/ClassUtils.php b/vendor/doctrine/common/lib/Doctrine/Common/Util/ClassUtils.php new file mode 100644 index 0000000..e3d24cf --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/Util/ClassUtils.php @@ -0,0 +1,93 @@ + + * @author Johannes Schmitt + * + * @deprecated The ClassUtils class is deprecated. + */ +class ClassUtils +{ + /** + * Gets the real class name of a class name that could be a proxy. + * + * @param string $class + * + * @return string + */ + public static function getRealClass($class) + { + if (false === $pos = strrpos($class, '\\' . Proxy::MARKER . '\\')) { + return $class; + } + + return substr($class, $pos + Proxy::MARKER_LENGTH + 2); + } + + /** + * Gets the real class name of an object (even if its a proxy). + * + * @param object $object + * + * @return string + */ + public static function getClass($object) + { + return self::getRealClass(get_class($object)); + } + + /** + * Gets the real parent class name of a class or object. + * + * @param string $className + * + * @return string + */ + public static function getParentClass($className) + { + return get_parent_class(self::getRealClass($className)); + } + + /** + * Creates a new reflection class. + * + * @param string $class + * + * @return \ReflectionClass + */ + public static function newReflectionClass($class) + { + return new \ReflectionClass(self::getRealClass($class)); + } + + /** + * Creates a new reflection object. + * + * @param object $object + * + * @return \ReflectionClass + */ + public static function newReflectionObject($object) + { + return self::newReflectionClass(self::getClass($object)); + } + + /** + * Given a class name and a proxy namespace returns the proxy name. + * + * @param string $className + * @param string $proxyNamespace + * + * @return string + */ + public static function generateProxyClassName($className, $proxyNamespace) + { + return rtrim($proxyNamespace, '\\') . '\\' . Proxy::MARKER . '\\' . ltrim($className, '\\'); + } +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php b/vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php new file mode 100644 index 0000000..a37282a --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php @@ -0,0 +1,167 @@ + + * @author Jonathan Wage + * @author Roman Borschel + * @author Giorgio Sironi + * + * @deprecated The Debug class is deprecated, please use symfony/var-dumper instead. + */ +final class Debug +{ + /** + * Private constructor (prevents instantiation). + */ + private function __construct() + { + } + + /** + * Prints a dump of the public, protected and private properties of $var. + * + * @link https://xdebug.org/ + * + * @param mixed $var The variable to dump. + * @param integer $maxDepth The maximum nesting level for object properties. + * @param boolean $stripTags Whether output should strip HTML tags. + * @param boolean $echo Send the dumped value to the output buffer + * + * @return string + */ + public static function dump($var, $maxDepth = 2, $stripTags = true, $echo = true) + { + $html = ini_get('html_errors'); + + if ($html !== true) { + ini_set('html_errors', true); + } + + 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(); + + $dumpText = ($stripTags ? strip_tags(html_entity_decode($dump)) : $dump); + + ini_set('html_errors', $html); + + if ($echo) { + echo $dumpText; + } + + return $dumpText; + } + + /** + * @param mixed $var + * @param int $maxDepth + * + * @return mixed + */ + public static function export($var, $maxDepth) + { + $return = null; + $isObj = is_object($var); + + if ($var instanceof Collection) { + $var = $var->toArray(); + } + + if ( ! $maxDepth) { + return is_object($var) ? get_class($var) + : (is_array($var) ? 'Array(' . count($var) . ')' : $var); + } + + if (is_array($var)) { + $return = []; + + foreach ($var as $k => $v) { + $return[$k] = self::export($v, $maxDepth - 1); + } + + return $return; + } + + if ( ! $isObj) { + return $var; + } + + $return = new \stdClass(); + if ($var instanceof \DateTimeInterface) { + $return->__CLASS__ = get_class($var); + $return->date = $var->format('c'); + $return->timezone = $var->getTimezone()->getName(); + + return $return; + } + + $return->__CLASS__ = ClassUtils::getClass($var); + + if ($var instanceof Proxy) { + $return->__IS_PROXY__ = true; + $return->__PROXY_INITIALIZED__ = $var->__isInitialized(); + } + + if ($var instanceof \ArrayObject || $var instanceof \ArrayIterator) { + $return->__STORAGE__ = self::export($var->getArrayCopy(), $maxDepth - 1); + } + + return self::fillReturnWithClassAttributes($var, $return, $maxDepth); + } + + /** + * Fill the $return variable with class attributes + * Based on obj2array function from {@see https://secure.php.net/manual/en/function.get-object-vars.php#47075} + * + * @param object $var + * @param \stdClass $return + * @param int $maxDepth + * + * @return mixed + */ + private static function fillReturnWithClassAttributes($var, \stdClass $return, $maxDepth) + { + $clone = (array) $var; + + foreach (array_keys($clone) as $key) { + $aux = explode("\0", $key); + $name = end($aux); + if ($aux[0] === '') { + $name .= ':' . ($aux[1] === '*' ? 'protected' : $aux[1] . ':private'); + } + $return->$name = self::export($clone[$key], $maxDepth - 1); + ; + } + + return $return; + } + + /** + * Returns a string representation of an object. + * + * @param object $obj + * + * @return string + */ + public static function toString($obj) + { + return method_exists($obj, '__toString') ? (string) $obj : get_class($obj) . '@' . spl_object_hash($obj); + } +} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Util/Inflector.php b/vendor/doctrine/common/lib/Doctrine/Common/Util/Inflector.php new file mode 100644 index 0000000..f41c54a --- /dev/null +++ b/vendor/doctrine/common/lib/Doctrine/Common/Util/Inflector.php @@ -0,0 +1,19 @@ + + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * + * @deprecated The Version class is deprecated, please refrain from checking the version of doctrine/common. + */ +class Version +{ + /** + * Current Doctrine Version. + */ + const VERSION = '2.11.0'; + + /** + * Compares a Doctrine version with the current one. + * + * @param string $version Doctrine version to compare. + * + * @return int -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); + } +} diff --git a/vendor/doctrine/common/phpstan.neon.dist b/vendor/doctrine/common/phpstan.neon.dist new file mode 100644 index 0000000..47a8c2e --- /dev/null +++ b/vendor/doctrine/common/phpstan.neon.dist @@ -0,0 +1,34 @@ +parameters: + level: 3 + paths: + - %currentWorkingDirectory%/lib + - %currentWorkingDirectory%/tests + autoload_directories: + - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/ClassLoaderTest + excludes_analyse: + - %currentWorkingDirectory%/lib/vendor/doctrine-build-common + - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/InvalidReturnTypeClass.php + - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/InvalidTypeHintClass.php + - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/SerializedClass.php + - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/VariadicTypeHintClass.php + ignoreErrors: + - '#Access to an undefined property Doctrine\\Common\\Proxy\\Proxy::\$publicField#' + - + message: '#^Result of method Doctrine\\Tests\\Common\\Proxy\\LazyLoadableObjectWithVoid::(adding|incrementing)AndReturningVoid\(\) \(void\) is used\.$#' + path: '%currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/ProxyLogicVoidReturnTypeTest.php' + - + message: '#^Property Doctrine\\Tests\\Common\\Proxy\\ProxyLogicTest::\$initializerCallbackMock \(callable&PHPUnit\\Framework\\MockObject\\MockObject\) does not accept PHPUnit\\Framework\\MockObject\\MockObject&stdClass\.$#' + path: '%currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/ProxyLogicTest.php' + - + message: '#^Call to an undefined method PHPUnit\\Framework\\MockObject\\MockObject(&stdClass)?::(load|getName)\(\)\.$#' + path: '%currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/ProxyLogicTest.php' + - + message: '#^Access to an undefined property Doctrine\\Common\\Proxy\\Proxy&Doctrine\\Tests\\Common\\Proxy\\LazyLoadableObject::\$non_existing_property\.$#' + path: '%currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/ProxyLogicTest.php' + - + message: '#^Property Doctrine\\Tests\\Common\\Proxy\\ProxyLogicVoidReturnTypeTest::\$initializerCallbackMock \(callable&PHPUnit\\Framework\\MockObject\\MockObject\) does not accept PHPUnit\\Framework\\MockObject\\MockObject&stdClass\.$#' + path: '%currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/ProxyLogicVoidReturnTypeTest.php' + +includes: + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-phpunit/rules.neon diff --git a/vendor/doctrine/data-fixtures/.doctrine-project.json b/vendor/doctrine/data-fixtures/.doctrine-project.json new file mode 100644 index 0000000..06747ff --- /dev/null +++ b/vendor/doctrine/data-fixtures/.doctrine-project.json @@ -0,0 +1,24 @@ +{ + "active": true, + "name": "Data fixtures", + "slug": "data-fixtures", + "docsSlug": "doctrine-data-fixtures", + "versions": [ + { + "name": "1.4", + "branchName": "master", + "slug": "latest", + "upcoming": true + }, + { + "name": "1.3", + "branchName": "1.3", + "slug": "1.3", + "current": true, + "aliases": [ + "current", + "stable" + ] + } + ] +} diff --git a/vendor/doctrine/data-fixtures/.github/FUNDING.yml b/vendor/doctrine/data-fixtures/.github/FUNDING.yml new file mode 100644 index 0000000..43c81de --- /dev/null +++ b/vendor/doctrine/data-fixtures/.github/FUNDING.yml @@ -0,0 +1,3 @@ +patreon: phpdoctrine +tidelift: packagist/doctrine%2Fdata-fixtures +custom: https://www.doctrine-project.org/sponsorship.html diff --git a/vendor/doctrine/data-fixtures/CHANGELOG.md b/vendor/doctrine/data-fixtures/CHANGELOG.md new file mode 100644 index 0000000..8bae0c9 --- /dev/null +++ b/vendor/doctrine/data-fixtures/CHANGELOG.md @@ -0,0 +1,170 @@ +# Change Log +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## [1.3.0] - 2017-11-27 + +### Fixed + - [248: Rename example classes names for consistency](https://github.com/doctrine/data-fixtures/pull/248) - @Kwadz + - [253: Fix syntax highlighting on README](https://github.com/doctrine/data-fixtures/pull/253) - @fefas + - [269: Remove tabs](https://github.com/doctrine/data-fixtures/pull/269) - @garak + +### Changed + - [266: Bump PHP requirement to 7.1](https://github.com/doctrine/data-fixtures/pull/266) - @alcaeus + +### Added + - [255: Added handling of PHPCR documents on method `getIdentifier()`](https://github.com/doctrine/data-fixtures/pull/255) - @aemaething + - [274: Hook point to control creating fixtures objects](https://github.com/doctrine/data-fixtures/pull/274) - @weaverryan + +### Fixed + - [572: Only show generated migration in verbose mode](https://github.com/doctrine/migrations/pull/572) - @alcaeus + +## [1.6.0] - 2017-11-09 + +### Fixed + - [536: Fix typo in exception message](https://github.com/doctrine/migrations/pull/536) - @mantiz + - [545: Allow nullable custom template](https://github.com/doctrine/migrations/pull/545) - @PapsOu + - [560: Fix `--dry-run` and `--write-sql` with `addSql`](https://github.com/doctrine/migrations/pull/560) - @mikeSimonson + - [569: Allow using absolute paths for custom template](https://github.com/doctrine/migrations/pull/569) - @alcaeus + +### Changed + - [537: Require PHP 7.1](https://github.com/doctrine/migrations/pull/537) - @lcobucci + - [563: Remove copyright headers](https://github.com/doctrine/migrations/pull/563) - @mikeSimonson + - [534: Change RecursiveRegexFinder to follow Symlinks](https://github.com/doctrine/migrations/pull/534) - @burci + +### Added + - [506: Add migration events](https://github.com/doctrine/migrations/pull/506) - @chrisguitarguy + - [509: Add delta in migrate command](https://github.com/doctrine/migrations/pull/509) - @Safranil + - [535: Allow changing migration class template in generate command](https://github.com/doctrine/migrations/pull/535) - @PapsOu + - [542: Enable phpcs to ensure coding style](https://github.com/doctrine/migrations/pull/542) - @lcobucci + - [562: Allow providing a path for file dump](https://github.com/doctrine/migrations/pull/562) - @mikeSimonson + - [565: Allow Symfony 4](https://github.com/doctrine/migrations/565) - @weaverryan + - [568: Add `ConfigurationHelperInterface` to allow overriding internal class](https://github.com/doctrine/migrations/pull/568) - @alcaeus + - [571: Allow changing migration class template in diff command](https://github.com/doctrine/migrations/pull/571) - @alcaeus + +## [1.5.0] - 2016-12-25 + +### Fixed + - [447: Fix typo in error code](https://github.com/doctrine/migrations/pull/447) thanks to @funivan + - [448: Removed unused import](https://github.com/doctrine/migrations/pull/448) thanks to @localheinz + - [451: Case insensitive method calls and types](https://github.com/doctrine/migrations/pull/451) thanks to @localheinz + - [449: Use the class keyword](https://github.com/doctrine/migrations/pull/449) thanks to @localheinz + - [453: Use better assertions](https://github.com/doctrine/migrations/pull/453) thanks to @localheinz + - [452: Fix the visibility of the AbstractTest](https://github.com/doctrine/migrations/pull/452) thanks to @localheinz + - [450: Use the short array syntax](https://github.com/doctrine/migrations/pull/450) thanks to @localheinz + - [464: Clean the github autogenerated zip archive](https://github.com/doctrine/migrations/pull/464) thanks to @mlocati + - [457: Fix an issue where the migration wheren't sorted propely](https://github.com/doctrine/migrations/pull/457) thanks to @JHGitty, @Charles68 + - [451: Case insensitive method calls and types](https://github.com/doctrine/migrations/pull/451) thanks to @localheinz + - [471: Fix loading the configuration from a php file](https://github.com/doctrine/migrations/pull/471) thanks to @aaa2000 + - [451: Case insensitive method calls and types](https://github.com/doctrine/migrations/pull/451) thanks to @localheinz + - [472: Change comment marker a cross platform one ](https://github.com/doctrine/migrations/pull/472) thanks to @aaa2000 + - [476: Add test for the execute command](https://github.com/doctrine/migrations/pull/476) thanks to @chrisguitarguy + - [470: Case insensitive method calls and types](https://github.com/doctrine/migrations/pull/470) thanks to @abacaphiliac + - [489: Better help message in the execute command](https://github.com/doctrine/migrations/pull/489) thanks to @eko + - [500: Updating the dev dependencies](https://github.com/doctrine/migrations/pull/500) thanks to @mikeSimonson + - [501: Fix a bug in a rarely used message call](https://github.com/doctrine/migrations/pull/501) thanks to @Seldaek + +### Changed + - [478: Changed the default generated version number to UTC](https://github.com/doctrine/migrations/pull/446) thanks to @c960657 + - [479: Explicitly connecting to support master slave connections](https://github.com/doctrine/migrations/pull/479) thanks to @chrisguitarguy + - [482: Use strict comparaison in the generated migrations](https://github.com/doctrine/migrations/pull/482) thanks to @tifabien + +### Added + - [470: Add uptodate command](https://github.com/doctrine/migrations/pull/470) thanks to @abacaphiliac + - [477: Add parameters to the output of the dry run migrations](https://github.com/doctrine/migrations/pull/477) thanks to @chrisguitarguy + - [497: Show the content of the generated file on the console](https://github.com/doctrine/migrations/pull/497) thanks to @ErikTrapman + - [480: Don't prompt the user for confirmation when there is nothing to do](https://github.com/doctrine/migrations/pull/480) thanks to @chrisguitarguy + + +## [1.4.1] - 2016-03-14 +### Fixed + - [439: Add missing dependency in the phar build](https://github.com/doctrine/migrations/pull/439) + + +## [1.4.0] - 2016-02-23 +### Added + - [431: Formatted diffs](https://github.com/doctrine/migrations/pull/431) + - [437: Allowing to set the column name from config too](https://github.com/doctrine/migrations/pull/437) + +## [1.3.1] - 2016-02-23 +### Fixed + - [433: Fix: ExecuteCommand by making sure that it autoload the versions](https://github.com/doctrine/migrations/pull/433) + - [434: Fixing an issue in the order at which some configuration key are loaded](https://github.com/doctrine/migrations/pull/434) + +### Changed + - [429: code refactoring for clarity](https://github.com/doctrine/migrations/pull/429) + - [428: code refactoring for clarity](https://github.com/doctrine/migrations/pull/428) + +### Added + - [425: ProxyManager ~2.0 is also compatible with migrations](https://github.com/doctrine/migrations/pull/425) + + +## [1.3.0] - 2016-01-23 +### Fixed + - [421: Fix issue with some method when the migrations were not loaded](https://github.com/doctrine/migrations/pull/421) + - [405: Correcting composer constraints: allowing PHP 7, dropping 5.4 support](https://github.com/doctrine/migrations/pull/405) + - [406: putting the composer.json back in the archive](https://github.com/doctrine/migrations/pull/406) + +### Changed + - [233: Separate Configuration Objects from Configuration File Loading](https://github.com/doctrine/migrations/issues/233) + - [407: Replacing the Schema by a proxy](https://github.com/doctrine/migrations/pull/407) + - [422: Refactor the getConnection into a chainloader](https://github.com/doctrine/migrations/pull/422) + - [Dropped the support for php 5.4](https://github.com/doctrine/migrations/pull/393) + - [Again make the phar more than 3 times smaller](https://github.com/doctrine/migrations/pull/396) + +### Added + - [404: add possibility to read doctrine's config/cli-config.php](https://github.com/doctrine/migrations/pull/404) + - [409: Add a failing test case for an edge case with the write-sql option](https://github.com/doctrine/migrations/pull/409) + - [424: Adding a regression test for the configuration](https://github.com/doctrine/migrations/pull/424) + - [391: Give the possibility to override the Migration template](https://github.com/doctrine/migrations/pull/391) + +## [1.2.2] - 2016-01-07 +### Fixed + - [Fix the write-sql option in the version class too](https://github.com/doctrine/migrations/commit/91043f742da8506ab7115a1d14247ce26375f6f5) + +## [1.2.1] - 2015-12-23 +### Fixed + - [Fix the write-sql option](https://github.com/doctrine/migrations/pull/400) + +## [1.2.0] - 2015-12-15 +### Fixed + - [fix "all migrated versions shown as unavailable executed" ](https://github.com/doctrine/migrations/commit/875849e2a80d37dc8bf5dd0663e464b6789e3b56) + - [Prevent the use of 0 as migration name as it is used internally and conflict](http://github.com/doctrine/migrations/commit/5df49c5ad5dc2265401a54a3b9e6ecb3e7cda8d0) + - [composer: drop symfony/console from suggested packages, since it's required package](http://github.com/doctrine/migrations/commit/d263c7bfac7188009ab0717ed5aa6577e80) + - [fix spaces and complete missing file-docblocks](http://github.com/doctrine/migrations/commit/4b68a69c3e35492b36ec140ebb216cdb80ffe655) + - [RecursiveDirectoryIterator don't obtain some order of the file list.](http://github.com/doctrine/migrations/commit/ed95c05c14381e64404f1135763fcc9b65317b96) + - [Fix the yml parser issue with unescaped backslash in double quoted string](http://github.com/doctrine/migrations/commit/af3cce7d2e490ead821fcbdb54b4772b4913ee1d) + +### Changed + - [Adding compression to the generation of the phar](http://github.com/doctrine/migrations/commit/70730ff8655f0be89ce0f06d1e279930d7eb2550) + - [tests: move autoload of tests to composer](http://github.com/doctrine/migrations/commit/3a4f8368e4b7b95d2e6c51c26f6dc41bb05a5ce5) + - [travis: drop PHP 7.0 from allowed failures, it passes well](http://github.com/doctrine/migrations/commit/57ec2f071a7a840c554058b77f2089893d06ba23) + - [Revert the use of exec to run sql queries](http://github.com/doctrine/migrations/commit/0af6e6e705b905a56cbed26cb5c17faad4c2c04f) + +### Added + - [Adding a little script to prepare and generate the phar](http://github.com/doctrine/migrations/commit/3a8ef413e7f8a42d4e0f3d32d30601b26fb27e60) + - [Configuration: check if migration class exists added](http://github.com/doctrine/migrations/commit/a53d7c83b319341c985d2a21950e260fa55b0b8d) + - [Made composer.json compatible with SF 3.0](http://github.com/doctrine/migrations/commit/4e909f2e661a8414a3e04ce987a09c9e849cd13f) + - [Added configurable version column name](http://github.com/doctrine/migrations/commit/02ddf4318b84a20bb0e3486acfc6e6f41cc63426) + +## [1.1.0] - 2015-09-29 +### Fixed + - [Switch unexisting tag to ](http://github.com/doctrine/migrations/commit/93a81ff0dcc858de4df5c17d97f2f24b3bfa3c36) + - [Ensure that Yaml::parse return an array as it can apparently return a string](http://github.com/doctrine/migrations/commit/1499f0cc3e5f5b20a510ba8f0779d5c68a9e5084) + - [Avoid uploading code coverage to Scrutinizer for HHVM and PHP 7](http://github.com/doctrine/migrations/commit/d47d65021dcb711480bf27f6d0bbba138e220f12) + - [Improve the Travis configuration by persisting the composer cache](http://github.com/doctrine/migrations/commit/bda0509b479ae6605b8fa749b0999b4ce2ff8c04) + - [Keep the license file in the downloadable archives](https://github.com/doctrine/migrations/commit/dfbee38e004899bc078d5d47b13bea53799fca1e#diff-fc723d30b02a4cca7a534518111c1a66) + +### Changed + - [Use short array syntax](http://github.com/doctrine/migrations/commit/50a6e18c95ff617325229a4a649d65c1a11445bc) + - [composer: use PSR-4 autoload](http://github.com/doctrine/migrations/commit/7fb8d301b2f4d4a564433165e0604b7d34013844) + - [refactoring the configuration loading](http://github.com/doctrine/migrations/commit/e95b277111c74cfe65eb959d4471f45a815e1ece) + - [Drop support for php 5.3](https://github.com/doctrine/migrations/commit/0e60856a10e8b510daa612fe25f6245aece77e68) + - [compressing the phar so that it's half the size now](https://github.com/doctrine/migrations/commit/70730ff8655f0be89ce0f06d1e279930d7eb2550) + +### Added + - [Added the ability to auto create migrations in a folder by month and year](http://github.com/doctrine/migrations/commit/0b8e40868e12a36de7f689add61857b9ba29c4bc) + - [Set default name for configuration helper](http://github.com/doctrine/migrations/commit/1f3592f2f126a022db275192f17b8d5c01f19822) + - [Added ability to load config from php array or json files.](http://github.com/doctrine/migrations/commit/8cf01d623f9eb3728ba86c22970347107a8f0be7) + - [Added the possibility to inject the OutputWriter after instantiation](https://github.com/doctrine/migrations/pull/342) + - [Added the --allow-no-migration option to avoid throwing an exception if no migrations are found](https://github.com/doctrine/migrations/commit/a9ec86faa3a3f7f592a633af43b6ef6c9f358239#diff-0a4648a19ba565cda76b349e89552a9b) diff --git a/vendor/doctrine/data-fixtures/LICENSE b/vendor/doctrine/data-fixtures/LICENSE new file mode 100644 index 0000000..2336c7f --- /dev/null +++ b/vendor/doctrine/data-fixtures/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2006-2015 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/doctrine/data-fixtures/README.md b/vendor/doctrine/data-fixtures/README.md new file mode 100644 index 0000000..cabb7e2 --- /dev/null +++ b/vendor/doctrine/data-fixtures/README.md @@ -0,0 +1,201 @@ +# Doctrine Data Fixtures Extension + +[![Build Status](https://travis-ci.org/doctrine/data-fixtures.svg?branch=master)](https://travis-ci.org/doctrine/data-fixtures) + +This extension aims to provide a simple way to manage and execute the loading of data fixtures +for the [Doctrine ORM or ODM](http://www.doctrine-project.org/). You can write fixture classes +by implementing the [`Doctrine\Common\DataFixtures\FixtureInterface`](lib/Doctrine/Common/DataFixtures/FixtureInterface.php) interface: + +```php +namespace MyDataFixtures; + +use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\Common\DataFixtures\FixtureInterface; + +class UserFixtureLoader implements FixtureInterface +{ + public function load(ObjectManager $manager) + { + $user = new User(); + $user->setUsername('jwage'); + $user->setPassword('test'); + + $manager->persist($user); + $manager->flush(); + } +} +``` + +Now you can begin adding the fixtures to a loader instance: + +```php +use Doctrine\Common\DataFixtures\Loader; +use MyDataFixtures\UserDataLoader; + +$loader = new Loader(); +$loader->addFixture(new UserDataLoader()); +``` + +You can load a set of fixtures from a directory as well: + +```php +$loader->loadFromDirectory('/path/to/MyDataFixtures'); +``` + +Or you can load a set of fixtures from a file: + +```php +$loader->loadFromFile('/path/to/MyDataFixtures/MyFixture1.php'); +``` + +You can get the added fixtures using the getFixtures() method: + +```php +$fixtures = $loader->getFixtures(); +``` + +Now you can easily execute the fixtures: + +```php +use Doctrine\Common\DataFixtures\Executor\ORMExecutor; +use Doctrine\Common\DataFixtures\Purger\ORMPurger; + +$purger = new ORMPurger(); +$executor = new ORMExecutor($em, $purger); +$executor->execute($loader->getFixtures()); +``` + +If you want to append the fixtures instead of purging before loading then pass true +to the 2nd argument of execute: + +```php +$executor->execute($loader->getFixtures(), true); +``` + +## Sharing objects between fixtures + +In case if fixture objects have relations to other fixtures, it is now possible +to easily add a reference to that object by name and later reference it to form +a relation. Here is an example fixtures for **Role** and **User** relation + +```php +namespace MyDataFixtures; + +use Doctrine\Common\DataFixtures\AbstractFixture; +use Doctrine\Common\Persistence\ObjectManager; + +class UserRoleDataLoader extends AbstractFixture +{ + public function load(ObjectManager $manager) + { + $adminRole = new Role(); + $adminRole->setName('admin'); + + $anonymousRole = new Role(); + $anonymousRole->setName('anonymous'); + + $manager->persist($adminRole); + $manager->persist($anonymousRole); + $manager->flush(); + + // store reference to admin role for User relation to Role + $this->addReference('admin-role', $adminRole); + } +} +``` + +And the **User** data loading fixture: + +```php +namespace MyDataFixtures; + +use Doctrine\Common\DataFixtures\AbstractFixture; +use Doctrine\Common\Persistence\ObjectManager; + +class UserDataLoader extends AbstractFixture +{ + public function load(ObjectManager $manager) + { + $user = new User(); + $user->setUsername('jwage'); + $user->setPassword('test'); + $user->setRole( + $this->getReference('admin-role') // load the stored reference + ); + + $manager->persist($user); + $manager->flush(); + + // store reference of admin-user for other Fixtures + $this->addReference('admin-user', $user); + } +} +``` + +## Fixture ordering +**Notice** that the fixture loading order is important! To handle it manually +implement one of the following interfaces: + +### OrderedFixtureInterface + +Set the order manually: + +```php +namespace MyDataFixtures; + +use Doctrine\Common\DataFixtures\AbstractFixture; +use Doctrine\Common\DataFixtures\OrderedFixtureInterface; +use Doctrine\Common\Persistence\ObjectManager; + +class MyFixture extends AbstractFixture implements OrderedFixtureInterface +{ + public function load(ObjectManager $manager) + {} + + public function getOrder() + { + return 10; // number in which order to load fixtures + } +} +``` + +### DependentFixtureInterface + +Provide an array of fixture class names: + +```php +namespace MyDataFixtures; + +use Doctrine\Common\DataFixtures\AbstractFixture; +use Doctrine\Common\DataFixtures\DependentFixtureInterface; +use Doctrine\Common\Persistence\ObjectManager; + +class MyFixture extends AbstractFixture implements DependentFixtureInterface +{ + public function load(ObjectManager $manager) + {} + + public function getDependencies() + { + return array('MyDataFixtures\MyOtherFixture'); // fixture classes fixture is dependent on + } +} + +class MyOtherFixture extends AbstractFixture +{ + public function load(ObjectManager $manager) + {} +} +``` + +**Notice** the ordering is relevant to Loader class. + +## Running the tests: + +Phpunit is included in the dev requirements of this package. + +To setup and run tests follow these steps: + +- go to the root directory of data-fixtures +- run: **composer install --dev** +- run: **vendor/bin/phpunit** diff --git a/vendor/doctrine/data-fixtures/UPGRADE b/vendor/doctrine/data-fixtures/UPGRADE new file mode 100644 index 0000000..dba81ad --- /dev/null +++ b/vendor/doctrine/data-fixtures/UPGRADE @@ -0,0 +1,17 @@ +# Between v1.0.0-ALPHA1 and v1.0.0-ALPHA2 + +The FixtureInterface was changed from + + interface FixtureInterface + { + load($manager); + } + +to + + use Doctrine\Common\Persistence\ObjectManager; + + interface FixtureInterface + { + load(ObjectManager $manager); + } diff --git a/vendor/doctrine/data-fixtures/composer.json b/vendor/doctrine/data-fixtures/composer.json new file mode 100644 index 0000000..cebc0a9 --- /dev/null +++ b/vendor/doctrine/data-fixtures/composer.json @@ -0,0 +1,58 @@ +{ + "name": "doctrine/data-fixtures", + "type": "library", + "description": "Data Fixtures for all Doctrine Object Managers", + "keywords": [ + "database" + ], + "homepage": "http://www.doctrine-project.org", + "license": "MIT", + "authors": [ + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "require": { + "php": "^7.2", + "doctrine/common": "^2.11" + }, + "conflict": { + "doctrine/phpcr-odm": "<1.3.0" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^6.0", + "doctrine/dbal": "^2.5.4", + "doctrine/mongodb-odm": "^1.3.0", + "doctrine/orm": "^2.5.4", + "phpunit/phpunit": "^7.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "For using MongoDB ODM with PHP 7", + "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", + "doctrine/orm": "For loading ORM fixtures", + "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" + }, + "config": { + "platform": { + "ext-mongo": "1.6.16" + }, + "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\DataFixtures\\": "lib/Doctrine/Common/DataFixtures" + } + }, + "autoload-dev": { + "psr-4": { + "Doctrine\\Tests\\": "tests/Doctrine/Tests" + } + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/AbstractFixture.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/AbstractFixture.php new file mode 100644 index 0000000..732c4ca --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/AbstractFixture.php @@ -0,0 +1,97 @@ +referenceRepository = $referenceRepository; + } + + /** + * Set the reference entry identified by $name + * and referenced to managed $object. If $name + * already is set, it overrides it + * + * @see Doctrine\Common\DataFixtures\ReferenceRepository::setReference + * + * @param string $name + * @param object $object - managed object + * + * @return void + */ + public function setReference($name, $object) + { + $this->referenceRepository->setReference($name, $object); + } + + /** + * Set the reference entry identified by $name + * and referenced to managed $object. If $name + * already is set, it throws a + * BadMethodCallException exception + * + * @see Doctrine\Common\DataFixtures\ReferenceRepository::addReference + * + * @param string $name + * @param object $object - managed object + * + * @return void + * + * @throws BadMethodCallException - if repository already has a reference by $name. + */ + public function addReference($name, $object) + { + $this->referenceRepository->addReference($name, $object); + } + + /** + * Loads an object using stored reference + * named by $name + * + * @see Doctrine\Common\DataFixtures\ReferenceRepository::getReference + * + * @param string $name + * + * @return object + */ + public function getReference($name) + { + return $this->referenceRepository->getReference($name); + } + + /** + * Check if an object is stored using reference + * named by $name + * + * @see Doctrine\Common\DataFixtures\ReferenceRepository::hasReference + * + * @param string $name + * + * @return bool + */ + public function hasReference($name) + { + return $this->referenceRepository->hasReference($name); + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/DependentFixtureInterface.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/DependentFixtureInterface.php new file mode 100644 index 0000000..5cac450 --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/DependentFixtureInterface.php @@ -0,0 +1,19 @@ +referenceRepository = $referenceRepository; + } + + /** + * {@inheritdoc} + */ + public function getSubscribedEvents() + { + return ['postPersist']; + } + + /** + * Populates identities for stored references + */ + public function postPersist(LifecycleEventArgs $args) + { + $object = $args->getDocument(); + + $names = $this->referenceRepository->getReferenceNames($object); + if ($names === false) { + return; + } + + foreach ($names as $name) { + $identity = $args->getDocumentManager() + ->getUnitOfWork() + ->getDocumentIdentifier($object); + + $this->referenceRepository->setReferenceIdentity($name, $identity); + } + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Event/Listener/ORMReferenceListener.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Event/Listener/ORMReferenceListener.php new file mode 100644 index 0000000..ba43e37 --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Event/Listener/ORMReferenceListener.php @@ -0,0 +1,57 @@ +referenceRepository = $referenceRepository; + } + + /** + * {@inheritdoc} + */ + public function getSubscribedEvents() + { + // would be better to use onClear, but it is supported only in 2.1 + return ['postPersist']; + } + + /** + * Populates identities for stored references + */ + public function postPersist(LifecycleEventArgs $args) + { + $object = $args->getEntity(); + + $names = $this->referenceRepository->getReferenceNames($object); + if ($names === false) { + return; + } + + foreach ($names as $name) { + $identity = $args->getEntityManager() + ->getUnitOfWork() + ->getEntityIdentifier($object); + + $this->referenceRepository->setReferenceIdentity($name, $identity); + } + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Exception/CircularReferenceException.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Exception/CircularReferenceException.php new file mode 100644 index 0000000..005df34 --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Exception/CircularReferenceException.php @@ -0,0 +1,11 @@ +referenceRepository = new ReferenceRepository($manager); + } + + /** + * @return ReferenceRepository + */ + public function getReferenceRepository() + { + return $this->referenceRepository; + } + + public function setReferenceRepository(ReferenceRepository $referenceRepository) + { + $this->referenceRepository = $referenceRepository; + } + + /** + * Sets the Purger instance to use for this executor instance. + */ + public function setPurger(PurgerInterface $purger) + { + $this->purger = $purger; + } + + /** + * @return PurgerInterface + */ + public function getPurger() + { + return $this->purger; + } + + /** + * Set the logger callable to execute with the log() method. + * + * @param callable $logger + */ + public function setLogger($logger) + { + $this->logger = $logger; + } + + /** + * Logs a message using the logger. + * + * @param string $message + */ + public function log($message) + { + $logger = $this->logger; + $logger($message); + } + + /** + * Load a fixture with the given persistence manager. + */ + public function load(ObjectManager $manager, FixtureInterface $fixture) + { + if ($this->logger) { + $prefix = ''; + if ($fixture instanceof OrderedFixtureInterface) { + $prefix = sprintf('[%d] ', $fixture->getOrder()); + } + $this->log('loading ' . $prefix . get_class($fixture)); + } + // additionally pass the instance of reference repository to shared fixtures + if ($fixture instanceof SharedFixtureInterface) { + $fixture->setReferenceRepository($this->referenceRepository); + } + $fixture->load($manager); + $manager->clear(); + } + + /** + * Purges the database before loading. + * + * @throws Exception if the purger is not defined. + */ + public function purge() + { + if ($this->purger === null) { + throw new Exception('Doctrine\Common\DataFixtures\Purger\PurgerInterface instance is required if you want to purge the database before loading your data fixtures.'); + } + if ($this->logger) { + $this->log('purging database'); + } + $this->purger->purge(); + } + + /** + * Executes the given array of data fixtures. + * + * @param array $fixtures Array of fixtures to execute. + * @param bool $append Whether to append the data fixtures or purge the database before loading. + */ + abstract public function execute(array $fixtures, $append = false); +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/MongoDBExecutor.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/MongoDBExecutor.php new file mode 100644 index 0000000..b0fe707 --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/MongoDBExecutor.php @@ -0,0 +1,67 @@ +dm = $dm; + if ($purger !== null) { + $this->purger = $purger; + $this->purger->setDocumentManager($dm); + } + parent::__construct($dm); + $this->listener = new MongoDBReferenceListener($this->referenceRepository); + $dm->getEventManager()->addEventSubscriber($this->listener); + } + + /** + * Retrieve the DocumentManager instance this executor instance is using. + * + * @return DocumentManager + */ + public function getObjectManager() + { + return $this->dm; + } + + /** @inheritDoc */ + public function setReferenceRepository(ReferenceRepository $referenceRepository) + { + $this->dm->getEventManager()->removeEventListener( + $this->listener->getSubscribedEvents(), + $this->listener + ); + + $this->referenceRepository = $referenceRepository; + $this->listener = new MongoDBReferenceListener($this->referenceRepository); + $this->dm->getEventManager()->addEventSubscriber($this->listener); + } + + /** @inheritDoc */ + public function execute(array $fixtures, $append = false) + { + if ($append === false) { + $this->purge(); + } + foreach ($fixtures as $fixture) { + $this->load($this->dm, $fixture); + } + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php new file mode 100644 index 0000000..246c0ef --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php @@ -0,0 +1,73 @@ +em = $em; + if ($purger !== null) { + $this->purger = $purger; + $this->purger->setEntityManager($em); + } + parent::__construct($em); + $this->listener = new ORMReferenceListener($this->referenceRepository); + $em->getEventManager()->addEventSubscriber($this->listener); + } + + /** + * Retrieve the EntityManagerInterface instance this executor instance is using. + * + * @return EntityManagerInterface + */ + public function getObjectManager() + { + return $this->em; + } + + /** @inheritDoc */ + public function setReferenceRepository(ReferenceRepository $referenceRepository) + { + $this->em->getEventManager()->removeEventListener( + $this->listener->getSubscribedEvents(), + $this->listener + ); + + $this->referenceRepository = $referenceRepository; + $this->listener = new ORMReferenceListener($this->referenceRepository); + $this->em->getEventManager()->addEventSubscriber($this->listener); + } + + /** @inheritDoc */ + public function execute(array $fixtures, $append = false) + { + $executor = $this; + $this->em->transactional(static function (EntityManagerInterface $em) use ($executor, $fixtures, $append) { + if ($append === false) { + $executor->purge(); + } + foreach ($fixtures as $fixture) { + $executor->load($em, $fixture); + } + }); + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/PHPCRExecutor.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/PHPCRExecutor.php new file mode 100644 index 0000000..e30b365 --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/PHPCRExecutor.php @@ -0,0 +1,62 @@ +dm = $dm; + if ($purger === null) { + return; + } + + $purger->setDocumentManager($dm); + $this->setPurger($purger); + } + + public function getObjectManager() + { + return $this->dm; + } + + /** @inheritDoc */ + public function execute(array $fixtures, $append = false) + { + $that = $this; + + $function = static function ($dm) use ($append, $that, $fixtures) { + if ($append === false) { + $that->purge(); + } + + foreach ($fixtures as $fixture) { + $that->load($dm, $fixture); + } + }; + + if (method_exists($this->dm, 'transactional')) { + $this->dm->transactional($function); + } else { + $function($this->dm); + } + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/FixtureInterface.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/FixtureInterface.php new file mode 100644 index 0000000..3cc3fc7 --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/FixtureInterface.php @@ -0,0 +1,18 @@ +loadFromIterator($iterator); + } + + /** + * Find fixtures classes in a given file and load them. + * + * @param string $fileName File to find fixture classes in. + * + * @return array $fixtures Array of loaded fixture object instances. + */ + public function loadFromFile($fileName) + { + if (! is_readable($fileName)) { + throw new InvalidArgumentException(sprintf('"%s" does not exist or is not readable', $fileName)); + } + + $iterator = new ArrayIterator([new SplFileInfo($fileName)]); + + return $this->loadFromIterator($iterator); + } + + /** + * Has fixture? + * + * @param FixtureInterface $fixture + * + * @return bool + */ + public function hasFixture($fixture) + { + return isset($this->fixtures[get_class($fixture)]); + } + + /** + * Get a specific fixture instance + * + * @param string $className + * + * @return FixtureInterface + */ + public function getFixture($className) + { + if (! isset($this->fixtures[$className])) { + throw new InvalidArgumentException(sprintf( + '"%s" is not a registered fixture', + $className + )); + } + + return $this->fixtures[$className]; + } + + /** + * Add a fixture object instance to the loader. + */ + public function addFixture(FixtureInterface $fixture) + { + $fixtureClass = get_class($fixture); + + if (isset($this->fixtures[$fixtureClass])) { + return; + } + + if ($fixture instanceof OrderedFixtureInterface && $fixture instanceof DependentFixtureInterface) { + throw new InvalidArgumentException(sprintf( + 'Class "%s" can\'t implement "%s" and "%s" at the same time.', + get_class($fixture), + 'OrderedFixtureInterface', + 'DependentFixtureInterface' + )); + } + + $this->fixtures[$fixtureClass] = $fixture; + + if ($fixture instanceof OrderedFixtureInterface) { + $this->orderFixturesByNumber = true; + } elseif ($fixture instanceof DependentFixtureInterface) { + $this->orderFixturesByDependencies = true; + foreach ($fixture->getDependencies() as $class) { + if (! class_exists($class)) { + continue; + } + + $this->addFixture($this->createFixture($class)); + } + } + } + + /** + * Returns the array of data fixtures to execute. + * + * @return array $fixtures + */ + public function getFixtures() + { + $this->orderedFixtures = []; + + if ($this->orderFixturesByNumber) { + $this->orderFixturesByNumber(); + } + + if ($this->orderFixturesByDependencies) { + $this->orderFixturesByDependencies(); + } + + if (! $this->orderFixturesByNumber && ! $this->orderFixturesByDependencies) { + $this->orderedFixtures = $this->fixtures; + } + + return $this->orderedFixtures; + } + + /** + * Check if a given fixture is transient and should not be considered a data fixtures + * class. + * + * @return bool + */ + public function isTransient($className) + { + $rc = new ReflectionClass($className); + if ($rc->isAbstract()) { + return true; + } + + $interfaces = class_implements($className); + + return ! in_array(FixtureInterface::class, $interfaces); + } + + /** + * Creates the fixture object from the class. + * + * @param string $class + * + * @return FixtureInterface + */ + protected function createFixture($class) + { + return new $class(); + } + + /** + * Orders fixtures by number + * + * @return void + * + * @todo maybe there is a better way to handle reordering + */ + private function orderFixturesByNumber() + { + $this->orderedFixtures = $this->fixtures; + usort($this->orderedFixtures, static function ($a, $b) { + if ($a instanceof OrderedFixtureInterface && $b instanceof OrderedFixtureInterface) { + if ($a->getOrder() === $b->getOrder()) { + return 0; + } + + return $a->getOrder() < $b->getOrder() ? -1 : 1; + } + + if ($a instanceof OrderedFixtureInterface) { + return $a->getOrder() === 0 ? 0 : 1; + } + + if ($b instanceof OrderedFixtureInterface) { + return $b->getOrder() === 0 ? 0 : -1; + } + + return 0; + }); + } + + /** + * Orders fixtures by dependencies + * + * @return void + */ + private function orderFixturesByDependencies() + { + $sequenceForClasses = []; + + // If fixtures were already ordered by number then we need + // to remove classes which are not instances of OrderedFixtureInterface + // in case fixtures implementing DependentFixtureInterface exist. + // This is because, in that case, the method orderFixturesByDependencies + // will handle all fixtures which are not instances of + // OrderedFixtureInterface + if ($this->orderFixturesByNumber) { + $count = count($this->orderedFixtures); + + for ($i = 0; $i < $count; ++$i) { + if ($this->orderedFixtures[$i] instanceof OrderedFixtureInterface) { + continue; + } + + unset($this->orderedFixtures[$i]); + } + } + + // First we determine which classes has dependencies and which don't + foreach ($this->fixtures as $fixture) { + $fixtureClass = get_class($fixture); + + if ($fixture instanceof OrderedFixtureInterface) { + continue; + } + + if ($fixture instanceof DependentFixtureInterface) { + $dependenciesClasses = $fixture->getDependencies(); + + $this->validateDependencies($dependenciesClasses); + + if (! is_array($dependenciesClasses) || empty($dependenciesClasses)) { + throw new InvalidArgumentException(sprintf('Method "%s" in class "%s" must return an array of classes which are dependencies for the fixture, and it must be NOT empty.', 'getDependencies', $fixtureClass)); + } + + if (in_array($fixtureClass, $dependenciesClasses)) { + throw new InvalidArgumentException(sprintf('Class "%s" can\'t have itself as a dependency', $fixtureClass)); + } + + // We mark this class as unsequenced + $sequenceForClasses[$fixtureClass] = -1; + } else { + // This class has no dependencies, so we assign 0 + $sequenceForClasses[$fixtureClass] = 0; + } + } + + // Now we order fixtures by sequence + $sequence = 1; + $lastCount = -1; + + while (($count = count($unsequencedClasses = $this->getUnsequencedClasses($sequenceForClasses))) > 0 && $count !== $lastCount) { + foreach ($unsequencedClasses as $key => $class) { + $fixture = $this->fixtures[$class]; + $dependencies = $fixture->getDependencies(); + $unsequencedDependencies = $this->getUnsequencedClasses($sequenceForClasses, $dependencies); + + if (count($unsequencedDependencies) !== 0) { + continue; + } + + $sequenceForClasses[$class] = $sequence++; + } + + $lastCount = $count; + } + + $orderedFixtures = []; + + // If there're fixtures unsequenced left and they couldn't be sequenced, + // it means we have a circular reference + if ($count > 0) { + $msg = 'Classes "%s" have produced a CircularReferenceException. '; + $msg .= 'An example of this problem would be the following: Class C has class B as its dependency. '; + $msg .= 'Then, class B has class A has its dependency. Finally, class A has class C as its dependency. '; + $msg .= 'This case would produce a CircularReferenceException.'; + + throw new CircularReferenceException(sprintf($msg, implode(',', $unsequencedClasses))); + } else { + // We order the classes by sequence + asort($sequenceForClasses); + + foreach ($sequenceForClasses as $class => $sequence) { + // If fixtures were ordered + $orderedFixtures[] = $this->fixtures[$class]; + } + } + + $this->orderedFixtures = array_merge($this->orderedFixtures, $orderedFixtures); + } + + private function validateDependencies($dependenciesClasses) + { + $loadedFixtureClasses = array_keys($this->fixtures); + + foreach ($dependenciesClasses as $class) { + if (! in_array($class, $loadedFixtureClasses)) { + throw new RuntimeException(sprintf('Fixture "%s" was declared as a dependency, but it should be added in fixture loader first.', $class)); + } + } + + return true; + } + + private function getUnsequencedClasses($sequences, $classes = null) + { + $unsequencedClasses = []; + + if ($classes === null) { + $classes = array_keys($sequences); + } + + foreach ($classes as $class) { + if ($sequences[$class] !== -1) { + continue; + } + + $unsequencedClasses[] = $class; + } + + return $unsequencedClasses; + } + + /** + * Load fixtures from files contained in iterator. + * + * @param Iterator $iterator Iterator over files from which fixtures should be loaded. + * + * @return array $fixtures Array of loaded fixture object instances. + */ + private function loadFromIterator(Iterator $iterator) + { + $includedFiles = []; + foreach ($iterator as $file) { + $fileName = $file->getBasename($this->fileExtension); + if ($fileName === $file->getBasename()) { + continue; + } + + $sourceFile = realpath($file->getPathName()); + require_once $sourceFile; + $includedFiles[] = $sourceFile; + } + + $fixtures = []; + $declared = get_declared_classes(); + // Make the declared classes order deterministic + sort($declared); + + foreach ($declared as $className) { + $reflClass = new ReflectionClass($className); + $sourceFile = $reflClass->getFileName(); + + if (! in_array($sourceFile, $includedFiles) || $this->isTransient($className)) { + continue; + } + + $fixture = $this->createFixture($className); + $fixtures[] = $fixture; + $this->addFixture($fixture); + } + + return $fixtures; + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/OrderedFixtureInterface.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/OrderedFixtureInterface.php new file mode 100644 index 0000000..e595926 --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/OrderedFixtureInterface.php @@ -0,0 +1,20 @@ +getManager()->getUnitOfWork(); + $simpleReferences = []; + + foreach ($this->getReferences() as $name => $reference) { + $className = $this->getRealClass(get_class($reference)); + + $simpleReferences[$name] = [$className, $this->getIdentifier($reference, $unitOfWork)]; + } + + return json_encode([ + 'references' => $simpleReferences, + 'identities' => $this->getIdentities(), + ]); + } + + /** + * Unserialize reference repository + * + * @param string $serializedData Serialized data + */ + public function unserialize($serializedData) + { + $repositoryData = json_decode($serializedData, true); + $references = $repositoryData['references']; + + foreach ($references as $name => $proxyReference) { + $this->setReference( + $name, + $this->getManager()->getReference( + $proxyReference[0], // entity class name + $proxyReference[1] // identifiers + ) + ); + } + + $identities = $repositoryData['identities']; + + foreach ($identities as $name => $identity) { + $this->setReferenceIdentity($name, $identity); + } + } + + /** + * Load data fixture reference repository + * + * @param string $baseCacheName Base cache name + * + * @return bool + */ + public function load($baseCacheName) + { + $filename = $baseCacheName . '.ser'; + + if (! file_exists($filename)) { + return false; + } + + $serializedData = file_get_contents($filename); + + if ($serializedData === false) { + return false; + } + + $this->unserialize($serializedData); + + return true; + } + + /** + * Save data fixture reference repository + * + * @param string $baseCacheName Base cache name + */ + public function save($baseCacheName) + { + $serializedData = $this->serialize(); + + file_put_contents($baseCacheName . '.ser', $serializedData); + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/MongoDBPurger.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/MongoDBPurger.php new file mode 100644 index 0000000..d7d2bfe --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/MongoDBPurger.php @@ -0,0 +1,58 @@ +dm = $dm; + } + + /** + * Set the DocumentManager instance this purger instance should use. + */ + public function setDocumentManager(DocumentManager $dm) + { + $this->dm = $dm; + } + + /** + * Retrieve the DocumentManager instance this purger instance is using. + * + * @return DocumentManager + */ + public function getObjectManager() + { + return $this->dm; + } + + /** @inheritDoc */ + public function purge() + { + $metadatas = $this->dm->getMetadataFactory()->getAllMetadata(); + foreach ($metadatas as $metadata) { + if ($metadata->isMappedSuperclass) { + continue; + } + + $this->dm->getDocumentCollection($metadata->name)->drop(); + } + $this->dm->getSchemaManager()->ensureIndexes(); + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/ORMPurger.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/ORMPurger.php new file mode 100644 index 0000000..6aa2410 --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/ORMPurger.php @@ -0,0 +1,271 @@ +em = $em; + $this->excluded = $excluded; + } + + /** + * Set the purge mode + * + * @param int $mode + * + * @return void + */ + public function setPurgeMode($mode) + { + $this->purgeMode = $mode; + } + + /** + * Get the purge mode + * + * @return int + */ + public function getPurgeMode() + { + return $this->purgeMode; + } + + /** + * Set the EntityManagerInterface instance this purger instance should use. + */ + public function setEntityManager(EntityManagerInterface $em) + { + $this->em = $em; + } + + /** + * Retrieve the EntityManagerInterface instance this purger instance is using. + * + * @return EntityManagerInterface + */ + public function getObjectManager() + { + return $this->em; + } + + /** @inheritDoc */ + public function purge() + { + $classes = []; + + foreach ($this->em->getMetadataFactory()->getAllMetadata() as $metadata) { + if ($metadata->isMappedSuperclass || (isset($metadata->isEmbeddedClass) && $metadata->isEmbeddedClass)) { + continue; + } + + $classes[] = $metadata; + } + + $commitOrder = $this->getCommitOrder($this->em, $classes); + + // Get platform parameters + $platform = $this->em->getConnection()->getDatabasePlatform(); + + // Drop association tables first + $orderedTables = $this->getAssociationTables($commitOrder, $platform); + + // Drop tables in reverse commit order + for ($i = count($commitOrder) - 1; $i >= 0; --$i) { + $class = $commitOrder[$i]; + + if ((isset($class->isEmbeddedClass) && $class->isEmbeddedClass) || + $class->isMappedSuperclass || + ($class->isInheritanceTypeSingleTable() && $class->name !== $class->rootEntityName) + ) { + continue; + } + + $orderedTables[] = $this->getTableName($class, $platform); + } + + $connection = $this->em->getConnection(); + $filterExpr = $connection->getConfiguration()->getFilterSchemaAssetsExpression(); + $emptyFilterExpression = empty($filterExpr); + + $schemaAssetsFilter = method_exists($connection->getConfiguration(), 'getSchemaAssetsFilter') ? $connection->getConfiguration()->getSchemaAssetsFilter() : null; + + foreach ($orderedTables as $tbl) { + // If we have a filter expression, check it and skip if necessary + if (! $emptyFilterExpression && ! preg_match($filterExpr, $tbl)) { + continue; + } + + // If the table is excluded, skip it as well + if (array_search($tbl, $this->excluded) !== false) { + continue; + } + + // Support schema asset filters as presented in + if (is_callable($schemaAssetsFilter) && ! $schemaAssetsFilter($tbl)) { + continue; + } + + if ($this->purgeMode === self::PURGE_MODE_DELETE) { + $connection->executeUpdate('DELETE FROM ' . $tbl); + } else { + $connection->executeUpdate($platform->getTruncateTableSQL($tbl, true)); + } + } + } + + /** + * @param ClassMetadata[] $classes + * + * @return ClassMetadata[] + */ + private function getCommitOrder(EntityManagerInterface $em, array $classes) + { + $sorter = new TopologicalSorter(); + + foreach ($classes as $class) { + if (! $sorter->hasNode($class->name)) { + $sorter->addNode($class->name, $class); + } + + // $class before its parents + foreach ($class->parentClasses as $parentClass) { + $parentClass = $em->getClassMetadata($parentClass); + $parentClassName = $parentClass->getName(); + + if (! $sorter->hasNode($parentClassName)) { + $sorter->addNode($parentClassName, $parentClass); + } + + $sorter->addDependency($class->name, $parentClassName); + } + + foreach ($class->associationMappings as $assoc) { + if (! $assoc['isOwningSide']) { + continue; + } + + /** @var ClassMetadata $targetClass */ + $targetClass = $em->getClassMetadata($assoc['targetEntity']); + $targetClassName = $targetClass->getName(); + + if (! $sorter->hasNode($targetClassName)) { + $sorter->addNode($targetClassName, $targetClass); + } + + // add dependency ($targetClass before $class) + $sorter->addDependency($targetClassName, $class->name); + + // parents of $targetClass before $class, too + foreach ($targetClass->parentClasses as $parentClass) { + $parentClass = $em->getClassMetadata($parentClass); + $parentClassName = $parentClass->getName(); + + if (! $sorter->hasNode($parentClassName)) { + $sorter->addNode($parentClassName, $parentClass); + } + + $sorter->addDependency($parentClassName, $class->name); + } + } + } + + return array_reverse($sorter->sort()); + } + + /** + * @param array $classes + * + * @return array + */ + private function getAssociationTables(array $classes, AbstractPlatform $platform) + { + $associationTables = []; + + foreach ($classes as $class) { + foreach ($class->associationMappings as $assoc) { + if (! $assoc['isOwningSide'] || $assoc['type'] !== ClassMetadata::MANY_TO_MANY) { + continue; + } + + $associationTables[] = $this->getJoinTableName($assoc, $class, $platform); + } + } + + return $associationTables; + } + + /** + * @param ClassMetadata $class + * @param AbstractPlatform $platform + * + * @return string + */ + private function getTableName($class, $platform) + { + if (isset($class->table['schema']) && ! method_exists($class, 'getSchemaName')) { + return $class->table['schema'] . '.' . $this->em->getConfiguration()->getQuoteStrategy()->getTableName($class, $platform); + } + + return $this->em->getConfiguration()->getQuoteStrategy()->getTableName($class, $platform); + } + + /** + * @param array $association + * @param ClassMetadata $class + * @param AbstractPlatform $platform + * + * @return string + */ + private function getJoinTableName($assoc, $class, $platform) + { + if (isset($assoc['joinTable']['schema']) && ! method_exists($class, 'getSchemaName')) { + return $assoc['joinTable']['schema'] . '.' . $this->em->getConfiguration()->getQuoteStrategy()->getJoinTableName($assoc, $class, $platform); + } + + return $this->em->getConfiguration()->getQuoteStrategy()->getJoinTableName($assoc, $class, $platform); + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PHPCRPurger.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PHPCRPurger.php new file mode 100644 index 0000000..800f519 --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PHPCRPurger.php @@ -0,0 +1,43 @@ +dm = $dm; + } + + public function setDocumentManager(DocumentManager $dm) + { + $this->dm = $dm; + } + + public function getObjectManager() + { + return $this->dm; + } + + /** + * @inheritDoc + */ + public function purge() + { + $session = $this->dm->getPhpcrSession(); + NodeHelper::purgeWorkspace($session); + $session->save(); + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PurgerInterface.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PurgerInterface.php new file mode 100644 index 0000000..c41ea50 --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PurgerInterface.php @@ -0,0 +1,18 @@ +manager = $manager; + } + + /** + * Get identifier for a unit of work + * + * @param object $reference Reference object + * @param object $uow Unit of work + * + * @return array + */ + protected function getIdentifier($reference, $uow) + { + // In case Reference is not yet managed in UnitOfWork + if (! $this->hasIdentifier($reference)) { + $class = $this->manager->getClassMetadata(get_class($reference)); + + return $class->getIdentifierValues($reference); + } + + // Dealing with ORM UnitOfWork + if (method_exists($uow, 'getEntityIdentifier')) { + return $uow->getEntityIdentifier($reference); + } + + // PHPCR ODM UnitOfWork + if ($this->manager instanceof PhpcrDocumentManager) { + return $uow->getDocumentId($reference); + } + + // ODM UnitOfWork + return $uow->getDocumentIdentifier($reference); + } + + /** + * Set the reference entry identified by $name + * and referenced to $reference. If $name + * already is set, it overrides it + * + * @param string $name + * @param object $reference + */ + public function setReference($name, $reference) + { + $this->references[$name] = $reference; + + if (! $this->hasIdentifier($reference)) { + return; + } + + // in case if reference is set after flush, store its identity + $uow = $this->manager->getUnitOfWork(); + $this->identities[$name] = $this->getIdentifier($reference, $uow); + } + + /** + * Store the identifier of a reference + * + * @param string $name + * @param mixed $identity + */ + public function setReferenceIdentity($name, $identity) + { + $this->identities[$name] = $identity; + } + + /** + * Set the reference entry identified by $name + * and referenced to managed $object. $name must + * not be set yet + * + * Notice: in case if identifier is generated after + * the record is inserted, be sure tu use this method + * after $object is flushed + * + * @param string $name + * @param object $object - managed object + * + * @return void + * + * @throws BadMethodCallException - if repository already has a reference by $name. + */ + public function addReference($name, $object) + { + if (isset($this->references[$name])) { + throw new BadMethodCallException(sprintf('Reference to "%s" already exists, use method setReference in order to override it', $name)); + } + + $this->setReference($name, $object); + } + + /** + * Loads an object using stored reference + * named by $name + * + * @param string $name + * + * @return object + * + * @throws OutOfBoundsException - if repository does not exist. + */ + public function getReference($name) + { + if (! $this->hasReference($name)) { + throw new OutOfBoundsException(sprintf('Reference to "%s" does not exist', $name)); + } + + $reference = $this->references[$name]; + $meta = $this->manager->getClassMetadata(get_class($reference)); + + if (! $this->manager->contains($reference) && isset($this->identities[$name])) { + $reference = $this->manager->getReference( + $meta->name, + $this->identities[$name] + ); + $this->references[$name] = $reference; // already in identity map + } + + return $reference; + } + + /** + * Check if an object is stored using reference + * named by $name + * + * @param string $name + * + * @return bool + */ + public function hasReference($name) + { + return isset($this->references[$name]); + } + + /** + * Searches for reference names in the + * list of stored references + * + * @param object $reference + * + * @return array + */ + public function getReferenceNames($reference) + { + return array_keys($this->references, $reference, true); + } + + /** + * Checks if reference has identity stored + * + * @param string $name + */ + public function hasIdentity($name) + { + return array_key_exists($name, $this->identities); + } + + /** + * Get all stored identities + * + * @return array + */ + public function getIdentities() + { + return $this->identities; + } + + /** + * Get all stored references + * + * @return array + */ + public function getReferences() + { + return $this->references; + } + + /** + * Get object manager + * + * @return ObjectManager + */ + public function getManager() + { + return $this->manager; + } + + /** + * Checks if object has identifier already in unit of work. + * + * @param string $reference + * + * @return bool + */ + private function hasIdentifier($reference) + { + // in case if reference is set after flush, store its identity + $uow = $this->manager->getUnitOfWork(); + + if ($this->manager instanceof PhpcrDocumentManager) { + return $uow->contains($reference); + } + + return $uow->isInIdentityMap($reference); + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/SharedFixtureInterface.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/SharedFixtureInterface.php new file mode 100644 index 0000000..f58b4c3 --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/SharedFixtureInterface.php @@ -0,0 +1,16 @@ +allowCyclicDependencies = $allowCyclicDependencies; + } + + /** + * Adds a new node (vertex) to the graph, assigning its hash and value. + * + * @param string $hash + * + * @return void + */ + public function addNode($hash, ClassMetadata $node) + { + $this->nodeList[$hash] = new Vertex($node); + } + + /** + * Checks the existence of a node in the graph. + * + * @param string $hash + * + * @return bool + */ + public function hasNode($hash) + { + return isset($this->nodeList[$hash]); + } + + /** + * Adds a new dependency (edge) to the graph using their hashes. + * + * @param string $fromHash + * @param string $toHash + * + * @return void + */ + public function addDependency($fromHash, $toHash) + { + $definition = $this->nodeList[$fromHash]; + + $definition->dependencyList[] = $toHash; + } + + /** + * Return a valid order list of all current nodes. + * The desired topological sorting is the postorder of these searches. + * + * Note: Highly performance-sensitive method. + * + * @return array + * + * @throws RuntimeException + * @throws CircularReferenceException + */ + public function sort() + { + foreach ($this->nodeList as $definition) { + if ($definition->state !== Vertex::NOT_VISITED) { + continue; + } + + $this->visit($definition); + } + + $sortedList = $this->sortedNodeList; + + $this->nodeList = []; + $this->sortedNodeList = []; + + return $sortedList; + } + + /** + * Visit a given node definition for reordering. + * + * Note: Highly performance-sensitive method. + * + * @throws RuntimeException + * @throws CircularReferenceException + */ + private function visit(Vertex $definition) + { + $definition->state = Vertex::IN_PROGRESS; + + foreach ($definition->dependencyList as $dependency) { + if (! isset($this->nodeList[$dependency])) { + throw new RuntimeException(sprintf( + 'Fixture "%s" has a dependency of fixture "%s", but it not listed to be loaded.', + get_class($definition->value), + $dependency + )); + } + + $childDefinition = $this->nodeList[$dependency]; + + // allow self referencing classes + if ($definition === $childDefinition) { + continue; + } + + switch ($childDefinition->state) { + case Vertex::VISITED: + break; + case Vertex::IN_PROGRESS: + if (! $this->allowCyclicDependencies) { + throw new CircularReferenceException( + sprintf( + 'Graph contains cyclic dependency between the classes "%s" and' + . ' "%s". An example of this problem would be the following: ' + . 'Class C has class B as its dependency. Then, class B has class A has its dependency. ' + . 'Finally, class A has class C as its dependency.', + $definition->value->getName(), + $childDefinition->value->getName() + ) + ); + } + break; + case Vertex::NOT_VISITED: + $this->visit($childDefinition); + } + } + + $definition->state = Vertex::VISITED; + + $this->sortedNodeList[] = $definition->value; + } +} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Sorter/Vertex.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Sorter/Vertex.php new file mode 100644 index 0000000..feee46c --- /dev/null +++ b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Sorter/Vertex.php @@ -0,0 +1,34 @@ +value = $value; + } +} diff --git a/vendor/doctrine/data-fixtures/phpcs.xml.dist b/vendor/doctrine/data-fixtures/phpcs.xml.dist new file mode 100644 index 0000000..1a5fe7e --- /dev/null +++ b/vendor/doctrine/data-fixtures/phpcs.xml.dist @@ -0,0 +1,50 @@ + + + + + + + + + + + + lib + tests + + + + + + + + + + + + + + tests/* + + + + lib/Doctrine/Common/DataFixtures/AbstractFixture.php + lib/Doctrine/Common/DataFixtures/Executor/AbstractExecutor.php + + + + lib/Doctrine/Common/DataFixtures/Exception/CircularReferenceException.php + + + + lib/Doctrine/Common/DataFixtures/DependentFixtureInterface.php + lib/Doctrine/Common/DataFixtures/FixtureInterface.php + lib/Doctrine/Common/DataFixtures/Purger/PurgerInterface.php + lib/Doctrine/Common/DataFixtures/OrderedFixtureInterface.php + lib/Doctrine/Common/DataFixtures/SharedFixtureInterface.php + + + + tests/* + + diff --git a/vendor/doctrine/dbal/.doctrine-project.json b/vendor/doctrine/dbal/.doctrine-project.json new file mode 100644 index 0000000..7b97cb4 --- /dev/null +++ b/vendor/doctrine/dbal/.doctrine-project.json @@ -0,0 +1,55 @@ +{ + "active": true, + "name": "Database Abstraction Layer", + "shortName": "DBAL", + "slug": "dbal", + "docsSlug": "doctrine-dbal", + "versions": [ + { + "name": "3.0", + "branchName": "develop", + "slug": "latest", + "upcoming": true + }, + { + "name": "2.10", + "branchName": "master", + "slug": "2.10", + "upcoming": true + }, + { + "name": "2.9", + "branchName": "2.9", + "slug": "2.9", + "current": true, + "aliases": [ + "current", + "stable" + ] + }, + { + "name": "2.8", + "branchName": "2.8", + "slug": "2.8", + "maintained": false + }, + { + "name": "2.7", + "branchName": "2.7", + "slug": "2.7", + "maintained": false + }, + { + "name": "2.6", + "branchName": "2.6", + "slug": "2.6", + "maintained": false + }, + { + "name": "2.5", + "branchName": "2.5", + "slug": "2.5", + "maintained": false + } + ] +} diff --git a/vendor/doctrine/dbal/LICENSE b/vendor/doctrine/dbal/LICENSE new file mode 100644 index 0000000..e8fdec4 --- /dev/null +++ b/vendor/doctrine/dbal/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2018 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/doctrine/dbal/README.md b/vendor/doctrine/dbal/README.md new file mode 100644 index 0000000..7495d20 --- /dev/null +++ b/vendor/doctrine/dbal/README.md @@ -0,0 +1,46 @@ +# Doctrine DBAL + +| [Master][Master] | [2.9][2.9] | [Develop][develop] | +|:----------------:|:----------:|:------------------:| +| [![Build status][Master image]][Master] | [![Build status][2.9 image]][2.9] | [![Build status][develop image]][develop] | +| [![Build Status][ContinuousPHP image]][ContinuousPHP] | [![Build Status][ContinuousPHP 2.9 image]][ContinuousPHP] | [![Build Status][ContinuousPHP develop image]][ContinuousPHP] | +| [![Code Coverage][Coverage image]][Scrutinizer Master] | [![Code Coverage][Coverage 2.9 image]][Scrutinizer 2.9] | [![Code Coverage][Coverage develop image]][Scrutinizer develop] | +| [![Code Quality][Quality image]][Scrutinizer Master] | [![Code Quality][Quality 2.9 image]][Scrutinizer 2.9] | [![Code Quality][Quality develop image]][Scrutinizer develop] | +| [![AppVeyor][AppVeyor master image]][AppVeyor master] | [![AppVeyor][AppVeyor 2.9 image]][AppVeyor 2.9] | [![AppVeyor][AppVeyor develop image]][AppVeyor develop] | + +Powerful database abstraction layer with many features for database schema introspection, schema management and PDO abstraction. + +## More resources: + +* [Website](http://www.doctrine-project.org/projects/dbal.html) +* [Documentation](http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/) +* [Issue Tracker](https://github.com/doctrine/dbal/issues) + + [Master image]: https://img.shields.io/travis/doctrine/dbal/master.svg?style=flat-square + [Coverage image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/dbal/master.svg?style=flat-square + [Quality image]: https://img.shields.io/scrutinizer/g/doctrine/dbal/master.svg?style=flat-square + [ContinuousPHP image]: https://img.shields.io/continuousphp/git-hub/doctrine/dbal/master.svg?style=flat-square + [Master]: https://travis-ci.org/doctrine/dbal + [Scrutinizer Master]: https://scrutinizer-ci.com/g/doctrine/dbal/ + [AppVeyor master]: https://ci.appveyor.com/project/doctrine/dbal/branch/master + [AppVeyor master image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/master?svg=true + [ContinuousPHP]: https://continuousphp.com/git-hub/doctrine/dbal + + [2.9 image]: https://img.shields.io/travis/doctrine/dbal/2.9.svg?style=flat-square + [Coverage 2.9 image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/dbal/2.9.svg?style=flat-square + [Quality 2.9 image]: https://img.shields.io/scrutinizer/g/doctrine/dbal/2.9.svg?style=flat-square + [ContinuousPHP 2.9 image]: https://img.shields.io/continuousphp/git-hub/doctrine/dbal/2.9.svg?style=flat-square + [2.9]: https://github.com/doctrine/dbal/tree/2.9 + [Scrutinizer 2.9]: https://scrutinizer-ci.com/g/doctrine/dbal/?branch=2.9 + [AppVeyor 2.9]: https://ci.appveyor.com/project/doctrine/dbal/branch/2.9 + [AppVeyor 2.9 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/2.9?svg=true + + [develop]: https://github.com/doctrine/dbal/tree/develop + [develop image]: https://img.shields.io/travis/doctrine/dbal/develop.svg?style=flat-square + [Coverage develop image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/dbal/develop.svg?style=flat-square + [Quality develop image]: https://img.shields.io/scrutinizer/g/doctrine/dbal/develop.svg?style=flat-square + [ContinuousPHP develop image]: https://img.shields.io/continuousphp/git-hub/doctrine/dbal/develop.svg?style=flat-square + [develop]: https://github.com/doctrine/dbal/tree/develop + [Scrutinizer develop]: https://scrutinizer-ci.com/g/doctrine/dbal/?branch=develop + [AppVeyor develop]: https://ci.appveyor.com/project/doctrine/dbal/branch/develop + [AppVeyor develop image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/develop?svg=true diff --git a/vendor/doctrine/dbal/SECURITY.md b/vendor/doctrine/dbal/SECURITY.md new file mode 100644 index 0000000..e18f0dd --- /dev/null +++ b/vendor/doctrine/dbal/SECURITY.md @@ -0,0 +1,14 @@ +Security +======== + +The Doctrine library is operating very close to your database and as such needs +to handle and make assumptions about SQL injection vulnerabilities. + +It is vital that you understand how Doctrine approaches security, because +we cannot protect you from SQL injection. + +Please read the documentation chapter on Security in Doctrine DBAL to +understand the assumptions we make. + +- [Latest security.rst page on Github](https://github.com/doctrine/dbal/blob/master/docs/en/reference/security.rst) +- [Security Page in rendered documentation](http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/security.html) diff --git a/vendor/doctrine/dbal/UPGRADE.md b/vendor/doctrine/dbal/UPGRADE.md new file mode 100644 index 0000000..205bf99 --- /dev/null +++ b/vendor/doctrine/dbal/UPGRADE.md @@ -0,0 +1,452 @@ +# Upgrade to 2.10 + +## Deprecated `Doctrine\DBAL\Event\ConnectionEventArgs` methods + +The usage of the `getDriver()`, `getDatabasePlatform()` and `getSchemaManager()` methods of the `ConnectionEventArgs` class has been deprecated. Obtain the underlying connection via `getConnection()` and call the corresponding methods on the connection instance. + +## Deprecated `Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs` methods + +The usage of the `getDatabasePlatform()` method of the `SchemaColumnDefinitionEventArgs` class has been deprecated. Obtain the underlying connection via `getConnection()` and call the corresponding method on the connection instance. + +## Deprecated `Doctrine\DBAL\Connection` methods + +The usage of the `getHost()`, `getPort()`, `getUsername()` and `getPassword()` methods of the `Connection` class has been deprecated as they leak implementation details. + +## Deprecated array of statements in `addSql()` of `SchemaEventArgs`-based classes. + +Passing multiple SQL statements as an array to `SchemaAlterTableAddColumnEventArgs::addSql()` and the same method in other `SchemaEventArgs`-based classes is deprecated. Pass each statement as an individual argument instead. + +## Deprecated calling `AbstractSchemaManager::tablesExist()` with a string argument. + +Instead of passing a string, pass a one-element array. + +## Deprecated calling `OracleSchemaManager::createDatabase()` without an argument or by passing NULL. + +In order to create a database, always pass the database name. + +## Deprecated unused schema manager methods. + +The following methods have been deprecated as unused: + +- `AbstractSchemaManager::_getPortableFunctionsList()`, +- `AbstractSchemaManager::_getPortableFunctionDefinition()`, +- `OracleSchemaManager::_getPortableFunctionDefinition()`, +- `SqliteSchemaManager::_getPortableTableIndexDefinition()`. + +# Deprecations in `Doctrine\DBAL\Driver` + +- The usage of NULL to indicate empty `$username` or `$password` when calling `connect()` is deprecated. Use an empty string instead. + +## Deprecated `Doctrine\DBAL\Platforms::_getAlterTableIndexForeignKeySQL()` + +Method `Doctrine\DBAL\Platforms::_getAlterTableIndexForeignKeySQL()` has been deprecated as no longer used. + +## Deprecated `Doctrine\DBAL\Driver\OCI8\OCI8Statement::$_PARAM` + +Property `Doctrine\DBAL\Driver\OCI8\OCI8Statement::$_PARAM` has been deprecated as not used. + +## Deprecated `Doctrine\DBAL\Driver::getName()` + +Relying on the name of the driver is discouraged. For referencing the driver, use its class name. + +## Deprecated usage of user-provided `PDO` instance + +The usage of user-provided `PDO` instance is deprecated. The known use cases are: + +1. **Persistent PDO connections.** DBAL 3.0 will supported establishing persistent connections, therefore, providing a pre-created persistent PDO connection will be no longer needed. +2. **Sharing `PDO` instance between DBAL and legacy components.** In order to share a PDO instance, initialize the connection in DBAL and access it using `Connection::getWrappedConnection()->getWrappedConnection()`. + +## MINOR BC BREAK: Default values are no longer handled as SQL expressions + +They are converted to SQL literals (e.g. escaped). Clients must now specify default values in their initial form, not in the form of an SQL literal (e.g. escaped). + +Before: + + $column->setDefault('Foo\\\\Bar\\\\Baz'); + +After: + + $column->setDefault('Foo\\Bar\\Baz'); + +## Deprecated `Type::*` constants + +The constants for built-in types have been moved from `Doctrine\DBAL\Types\Type` to a separate class `Doctrine\DBAL\Types\Types`. + +Some of the constants were renamed in the process: +* `TARRAY`-> `ARRAY` +* `DATE` -> `DATE_MUTABLE` +* `DATETIME` -> `DATETIME_MUTABLE` +* `DATETIMETZ` -> `DATETIMETZ_MUTABLE` +* `TIME` -> `TIME_MUTABLE` + +## Deprecated `SQLSrvStatement::LAST_INSERT_ID_SQL` constant + +The `Doctrine\DBAL\Driver\SQLSrv\SQLSrvStatement::LAST_INSERT_ID_SQL` constant has been deprecated and will be made private in 3.0. + +## Deprecated `SQLParserUtils` constants + +The constants in `Doctrine\DBAL\SQLParserUtils` have been deprecated and will be made private in 3.0. + +## Deprecated `LoggerChain::addLogger` method + +The `Doctrine\DBAL\Logging\LoggerChain::addLogger` method has been deprecated. Inject list of loggers via constructor instead. + +# Upgrade to 2.9 + +## Deprecated `Statement::fetchColumn()` with an invalid index + +Calls to `Statement::fetchColumn()` with an invalid column index currently return `NULL`. In the future, such calls will result in a exception. + +## Deprecated `Configuration::getFilterSchemaAssetsExpression()`, `::setFilterSchemaAssetsExpression()` and `AbstractSchemaManager::getFilterSchemaAssetsExpression()`. + +Regular expression-based filters are hard to extend by combining together. Instead, you may use callback-based filers via `::getSchemaAssetsFilter()` and `::getSchemaAssetsFilter()`. Callbacks can use regular expressions internally. + +## Deprecated `Doctrine\DBAL\Types\Type::getDefaultLength()` + +This method was never used by DBAL internally. It is now deprecated and will be removed in DBAL 3.0. + +## Deprecated `Doctrine\DBAL\Types\Type::__toString()` + +Relying on string representation is discouraged and will be removed in DBAL 3.0. + +## Deprecated `NULL` value of `$offset` in LIMIT queries + +The `NULL` value of the `$offset` argument in `AbstractPlatform::(do)?ModifyLimitQuery()` methods is deprecated. If explicitly used in the method call, the absence of the offset should be indicated with a `0`. + +## Deprecated dbal:import CLI command + +The `dbal:import` CLI command has been deprecated since it only works with PDO-based drivers by relying on a non-documented behavior of the extension, and it's impossible to make it work with other drivers. +Please use other database client applications for import, e.g.: + + * For MySQL and MariaDB: `mysql [dbname] < data.sql`. + * For PostgreSQL: `psql [dbname] < data.sql`. + * For SQLite: `sqlite3 /path/to/file.db < data.sql`. + +# Upgrade to 2.8 + +## Deprecated usage of DB-generated UUIDs + +The format of DB-generated UUIDs is inconsistent across supported platforms and therefore is not portable. Some of the platforms produce UUIDv1, some produce UUIDv4, some produce the values which are not even UUID. + +Unless UUIDs are used in stored procedures which DBAL doesn't support, there's no real benefit of DB-generated UUIDs comparing to the application-generated ones. + +Use a PHP library (e.g. [ramsey/uuid](https://packagist.org/packages/ramsey/uuid)) to generate UUIDs on the application side. + +## Deprecated usage of binary fields whose length exceeds the platform maximum + +- The usage of binary fields whose length exceeds the maximum field size on a given platform is deprecated. + Use binary fields of a size which fits all target platforms, or use blob explicitly instead. + +## Removed dependency on doctrine/common + +The dependency on doctrine/common package has been removed. +DBAL now depends on doctrine/cache and doctrine/event-manager instead. +If you are using any other component from doctrine/common package, +you will have to add an explicit dependency to your composer.json. + +## Corrected exception thrown by ``Doctrine\DBAL\Platforms\SQLAnywhere16Platform::getAdvancedIndexOptionsSQL()`` + +This method now throws SPL ``UnexpectedValueException`` instead of accidentally throwing ``Doctrine\Common\Proxy\Exception\UnexpectedValueException``. + +# Upgrade to 2.7 + +## Doctrine\DBAL\Platforms\AbstractPlatform::DATE_INTERVAL_UNIT_* constants deprecated + +``Doctrine\DBAL\Platforms\AbstractPlatform::DATE_INTERVAL_UNIT_*`` constants were moved into ``Doctrine\DBAL\Platforms\DateIntervalUnit`` class without the ``DATE_INTERVAL_UNIT_`` prefix. + +## Doctrine\DBAL\Platforms\AbstractPlatform::TRIM_* constants deprecated + +``Doctrine\DBAL\Platforms\AbstractPlatform::TRIM_*`` constants were moved into ``Doctrine\DBAL\Platforms\TrimMode`` class without the ``TRIM_`` prefix. + +## Doctrine\DBAL\Connection::TRANSACTION_* constants deprecated + +``Doctrine\DBAL\Connection::TRANSACTION_*`` were moved into ``Doctrine\DBAL\TransactionIsolationLevel`` class without the ``TRANSACTION_`` prefix. + +## DEPRECATION: direct usage of the PDO APIs in the DBAL API + +1. When calling `Doctrine\DBAL\Driver\Statement` methods, instead of `PDO::PARAM_*` constants, `Doctrine\DBAL\ParameterType` constants should be used. +2. When calling `Doctrine\DBAL\Driver\ResultStatement` methods, instead of `PDO::FETCH_*` constants, `Doctrine\DBAL\FetchMode` constants should be used. +3. When configuring `Doctrine\DBAL\Portability\Connection`, instead of `PDO::CASE_*` constants, `Doctrine\DBAL\ColumnCase` constants should be used. +4. Usage of `PDO::PARAM_INPUT_OUTPUT` in `Doctrine\DBAL\Driver\Statement::bindValue()` is deprecated. +5. Usage of `PDO::FETCH_FUNC` in `Doctrine\DBAL\Driver\ResultStatement::fetch()` is deprecated. +6. Calls to `\PDOStatement` methods on a `\Doctrine\DBAL\Driver\PDOStatement` instance (e.g. `fetchObject()`) are deprecated. + +# Upgrade to 2.6 + +## MINOR BC BREAK: `fetch()` and `fetchAll()` method signatures in `Doctrine\DBAL\Driver\ResultStatement` + +1. ``Doctrine\DBAL\Driver\ResultStatement::fetch()`` now has 3 arguments instead of 1, respecting +``PDO::fetch()`` signature. + +Before: + + Doctrine\DBAL\Driver\ResultStatement::fetch($fetchMode); + +After: + + Doctrine\DBAL\Driver\ResultStatement::fetch($fetchMode, $cursorOrientation, $cursorOffset); + +2. ``Doctrine\DBAL\Driver\ResultStatement::fetchAll()`` now has 3 arguments instead of 1, respecting +``PDO::fetchAll()`` signature. + +Before: + + Doctrine\DBAL\Driver\ResultStatement::fetchAll($fetchMode); + +After: + + Doctrine\DBAL\Driver\ResultStatement::fetch($fetchMode, $fetchArgument, $ctorArgs); + + +## MINOR BC BREAK: URL-style DSN with percentage sign in password + +URL-style DSNs (e.g. ``mysql://foo@bar:localhost/db``) are now assumed to be percent-encoded +in order to allow certain special characters in usernames, paswords and database names. If +you are using a URL-style DSN and have a username, password or database name containing a +percentage sign, you need to update your DSN. If your password is, say, ``foo%foo``, it +should be encoded as ``foo%25foo``. + +# Upgrade to 2.5.1 + +## MINOR BC BREAK: Doctrine\DBAL\Schema\Table + +When adding indexes to ``Doctrine\DBAL\Schema\Table`` via ``addIndex()`` or ``addUniqueIndex()``, +duplicate indexes are not silently ignored/dropped anymore (based on semantics, not naming!). +Duplicate indexes are considered indexes that pass ``isFullfilledBy()`` or ``overrules()`` +in ``Doctrine\DBAL\Schema\Index``. +This is required to make the index renaming feature introduced in 2.5.0 work properly and avoid +issues in the ORM schema tool / DBAL schema manager which pretends users from updating +their schemas and migrate to DBAL 2.5.*. +Additionally it offers more flexibility in declaring indexes for the user and potentially fixes +related issues in the ORM. +With this change, the responsibility to decide which index is a "duplicate" is completely deferred +to the user. +Please also note that adding foreign key constraints to a table via ``addForeignKeyConstraint()``, +``addUnnamedForeignKeyConstraint()`` or ``addNamedForeignKeyConstraint()`` now first checks if an +appropriate index is already present and avoids adding an additional auto-generated one eventually. + +# Upgrade to 2.5 + +## BC BREAK: time type resets date fields to UNIX epoch + +When mapping `time` type field to PHP's `DateTime` instance all unused date fields are +reset to UNIX epoch (i.e. 1970-01-01). This might break any logic which relies on comparing +`DateTime` instances with date fields set to the current date. + +Use `!` format prefix (see http://php.net/manual/en/datetime.createfromformat.php) for parsing +time strings to prevent having different date fields when comparing user input and `DateTime` +instances as mapped by Doctrine. + +## BC BREAK: Doctrine\DBAL\Schema\Table + +The methods ``addIndex()`` and ``addUniqueIndex()`` in ``Doctrine\DBAL\Schema\Table`` +have an additional, optional parameter. If you override these methods, you should +add this new parameter to the declaration of your overridden methods. + +## BC BREAK: Doctrine\DBAL\Connection + +The visibility of the property ``$_platform`` in ``Doctrine\DBAL\Connection`` +was changed from protected to private. If you have subclassed ``Doctrine\DBAL\Connection`` +in your application and accessed ``$_platform`` directly, you have to change the code +portions to use ``getDatabasePlatform()`` instead to retrieve the underlying database +platform. +The reason for this change is the new automatic platform version detection feature, +which lazily evaluates the appropriate platform class to use for the underlying database +server version at runtime. +Please also note, that calling ``getDatabasePlatform()`` now needs to establish a connection +in order to evaluate the appropriate platform class if ``Doctrine\DBAL\Connection`` is not +already connected. Under the following circumstances, it is not possible anymore to retrieve +the platform instance from the connection object without having to do a real connect: + +1. ``Doctrine\DBAL\Connection`` was instantiated without the ``platform`` connection parameter. +2. ``Doctrine\DBAL\Connection`` was instantiated without the ``serverVersion`` connection parameter. +3. The underlying driver is "version aware" and can provide different platform instances + for different versions. +4. The underlying driver connection is "version aware" and can provide the database server + version without having to query for it. + +If one of the above conditions is NOT met, there is no need for ``Doctrine\DBAL\Connection`` +to do a connect when calling ``getDatabasePlatform()``. + +## datetime Type uses date_create() as fallback + +Before 2.5 the DateTime type always required a specific format, defined in +`$platform->getDateTimeFormatString()`, which could cause quite some troubles +on platforms that had various microtime precision formats. Starting with 2.5 +whenever the parsing of a date fails with the predefined platform format, +the `date_create()` function will be used to parse the date. + +This could cause some troubles when your date format is weird and not parsed +correctly by `date_create`, however since databases are rather strict on dates +there should be no problem. + +## Support for pdo_ibm driver removed + +The ``pdo_ibm`` driver is buggy and does not work well with Doctrine. Therefore it will no +longer be supported and has been removed from the ``Doctrine\DBAL\DriverManager`` drivers +map. It is highly encouraged to to use `ibm_db2` driver instead if you want to connect +to an IBM DB2 database as it is much more stable and secure. + +If for some reason you have to utilize the ``pdo_ibm`` driver you can still use the `driverClass` +connection parameter to explicitly specify the ``Doctrine\DBAL\Driver\PDOIbm\Driver`` class. +However be aware that you are doing this at your own risk and it will not be guaranteed that +Doctrine will work as expected. + +# Upgrade to 2.4 + +## Doctrine\DBAL\Schema\Constraint + +If you have custom classes that implement the constraint interface, you have to implement +an additional method ``getQuotedColumns`` now. This method is used to build proper constraint +SQL for columns that need to be quoted, like keywords reserved by the specific platform used. +The method has to return the same values as ``getColumns`` only that those column names that +need quotation have to be returned quoted for the given platform. + +# Upgrade to 2.3 + +## Oracle Session Init now sets Numeric Character + +Before 2.3 the Oracle Session Init did not care about the numeric character of the Session. +This could lead to problems on non english locale systems that required a comma as a floating +point seperator in Oracle. Since 2.3, using the Oracle Session Init on connection start the +client session will be altered to set the numeric character to ".,": + + ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,' + +See [DBAL-345](http://www.doctrine-project.org/jira/browse/DBAL-345) for more details. + +## Doctrine\DBAL\Connection and Doctrine\DBAL\Statement + +The query related methods including but not limited to executeQuery, exec, query, and executeUpdate +now wrap the driver exceptions such as PDOException with DBALException to add more debugging +information such as the executed SQL statement, and any bound parameters. + +If you want to retrieve the driver specific exception, you can retrieve it by calling the +``getPrevious()`` method on DBALException. + +Before: + + catch(\PDOException $ex) { + // ... + } + +After: + + catch(\Doctrine\DBAL\DBALException $ex) { + $pdoException = $ex->getPrevious(); + // ... + } + +## Doctrine\DBAL\Connection#setCharsetSQL() removed + +This method only worked on MySQL and it is considered unsafe on MySQL to use SET NAMES UTF-8 instead +of setting the charset directly on connection already. Replace this behavior with the +connection charset option: + +Before: + + $conn = DriverManager::getConnection(array(..)); + $conn->setCharset('UTF8'); + +After: + + $conn = DriverManager::getConnection(array('charset' => 'UTF8', ..)); + +## Doctrine\DBAL\Schema\Table#renameColumn() removed + +Doctrine\DBAL\Schema\Table#renameColumn() was removed, because it drops and recreates +the column instead. There is no fix available, because a schema diff +cannot reliably detect if a column was renamed or one column was created +and another one dropped. + +You should use explicit SQL ALTER TABLE statements to change columns names. + +## Schema Filter paths + +The Filter Schema assets expression is not wrapped in () anymore for the regexp automatically. + +Before: + + $config->setFilterSchemaAssetsExpression('foo'); + +After: + + $config->setFilterSchemaAssetsExpression('(foo)'); + +## Creating MySQL Tables now defaults to UTF-8 + +If you are creating a new MySQL Table through the Doctrine API, charset/collate are +now set to 'utf8'/'utf8_unicode_ci' by default. Previously the MySQL server defaults were used. + +# Upgrade to 2.2 + +## Doctrine\DBAL\Connection#insert and Doctrine\DBAL\Connection#update + +Both methods now accept an optional last parameter $types with binding types of the values passed. +This can potentially break child classes that have overwritten one of these methods. + +## Doctrine\DBAL\Connection#executeQuery + +Doctrine\DBAL\Connection#executeQuery() got a new last parameter "QueryCacheProfile $qcp" + +## Doctrine\DBAL\Driver\Statement split + +The Driver statement was split into a ResultStatement and the normal statement extending from it. +This separates the configuration and the retrieval API from a statement. + +## MsSql Platform/SchemaManager renamed + +The MsSqlPlatform was renamed to SQLServerPlatform, the MsSqlSchemaManager was renamed +to SQLServerSchemaManager. + +## Cleanup SQLServer Platform version mess + +DBAL 2.1 and before were actually only compatible to SQL Server 2008, not earlier versions. +Still other parts of the platform did use old features instead of newly introduced datatypes +in SQL Server 2005. Starting with DBAL 2.2 you can pick the Doctrine abstraction exactly +matching your SQL Server version. + +The PDO SqlSrv driver now uses the new `SQLServer2008Platform` as default platform. +This platform uses new features of SQL Server as of version 2008. This also includes a switch +in the used fields for "text" and "blob" field types to: + + "text" => "VARCHAR(MAX)" + "blob" => "VARBINARY(MAX)" + +Additionally `SQLServerPlatform` in DBAL 2.1 and before used "DATE", "TIME" and "DATETIME2" for dates. +This types are only available since version 2008 and the introduction of an explicit +SQLServer 2008 platform makes this dependency explicit. + +An `SQLServer2005Platform` was also introduced to differentiate the features between +versions 2003, earlier and 2005. + +With this change the `SQLServerPlatform` now throws an exception for using limit queries +with an offset, since SQLServer 2003 and lower do not support this feature. + +To use the old SQL Server Platform, because you are using SQL Server 2003 and below use +the following configuration code: + + use Doctrine\DBAL\DriverManager; + use Doctrine\DBAL\Platforms\SQLServerPlatform; + use Doctrine\DBAL\Platforms\SQLServer2005Platform; + + // You are using SQL Server 2003 or earlier + $conn = DriverManager::getConnection(array( + 'driver' => 'pdo_sqlsrv', + 'platform' => new SQLServerPlatform() + // .. additional parameters + )); + + // You are using SQL Server 2005 + $conn = DriverManager::getConnection(array( + 'driver' => 'pdo_sqlsrv', + 'platform' => new SQLServer2005Platform() + // .. additional parameters + )); + + // You are using SQL Server 2008 + $conn = DriverManager::getConnection(array( + 'driver' => 'pdo_sqlsrv', + // 2008 is default platform + // .. additional parameters + )); diff --git a/vendor/doctrine/dbal/bin/doctrine-dbal b/vendor/doctrine/dbal/bin/doctrine-dbal new file mode 100755 index 0000000..0531527 --- /dev/null +++ b/vendor/doctrine/dbal/bin/doctrine-dbal @@ -0,0 +1,4 @@ +#!/usr/bin/env php +data = $data; + if (! count($data)) { + return; + } + + $this->columnCount = count($data[0]); + } + + /** + * {@inheritdoc} + */ + public function closeCursor() + { + unset($this->data); + } + + /** + * {@inheritdoc} + */ + public function columnCount() + { + return $this->columnCount; + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + if ($arg2 !== null || $arg3 !== null) { + throw new InvalidArgumentException('Caching layer does not support 2nd/3rd argument to setFetchMode()'); + } + + $this->defaultFetchMode = $fetchMode; + + return true; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + $data = $this->fetchAll(); + + return new ArrayIterator($data); + } + + /** + * {@inheritdoc} + */ + public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + { + if (! isset($this->data[$this->num])) { + return false; + } + + $row = $this->data[$this->num++]; + $fetchMode = $fetchMode ?: $this->defaultFetchMode; + + if ($fetchMode === FetchMode::ASSOCIATIVE) { + return $row; + } + + if ($fetchMode === FetchMode::NUMERIC) { + return array_values($row); + } + + if ($fetchMode === FetchMode::MIXED) { + return array_merge($row, array_values($row)); + } + + if ($fetchMode === FetchMode::COLUMN) { + return reset($row); + } + + throw new InvalidArgumentException('Invalid fetch-style given for fetching result.'); + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + { + $rows = []; + while ($row = $this->fetch($fetchMode)) { + $rows[] = $row; + } + + return $rows; + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + $row = $this->fetch(FetchMode::NUMERIC); + + // TODO: verify that return false is the correct behavior + return $row[$columnIndex] ?? false; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/CacheException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/CacheException.php new file mode 100644 index 0000000..636c948 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/CacheException.php @@ -0,0 +1,24 @@ +lifetime = $lifetime; + $this->cacheKey = $cacheKey; + $this->resultCacheDriver = $resultCache; + } + + /** + * @return Cache|null + */ + public function getResultCacheDriver() + { + return $this->resultCacheDriver; + } + + /** + * @return int + */ + public function getLifetime() + { + return $this->lifetime; + } + + /** + * @return string + * + * @throws CacheException + */ + public function getCacheKey() + { + if ($this->cacheKey === null) { + throw CacheException::noCacheKey(); + } + + return $this->cacheKey; + } + + /** + * Generates the real cache key from query, params, types and connection parameters. + * + * @param string $query + * @param mixed[] $params + * @param int[]|string[] $types + * @param mixed[] $connectionParams + * + * @return string[] + */ + public function generateCacheKeys($query, $params, $types, array $connectionParams = []) + { + $realCacheKey = 'query=' . $query . + '¶ms=' . serialize($params) . + '&types=' . serialize($types) . + '&connectionParams=' . hash('sha256', serialize($connectionParams)); + + // should the key be automatically generated using the inputs or is the cache key set? + if ($this->cacheKey === null) { + $cacheKey = sha1($realCacheKey); + } else { + $cacheKey = $this->cacheKey; + } + + return [$cacheKey, $realCacheKey]; + } + + /** + * @return \Doctrine\DBAL\Cache\QueryCacheProfile + */ + public function setResultCacheDriver(Cache $cache) + { + return new QueryCacheProfile($this->lifetime, $this->cacheKey, $cache); + } + + /** + * @param string|null $cacheKey + * + * @return \Doctrine\DBAL\Cache\QueryCacheProfile + */ + public function setCacheKey($cacheKey) + { + return new QueryCacheProfile($this->lifetime, $cacheKey, $this->resultCacheDriver); + } + + /** + * @param int $lifetime + * + * @return \Doctrine\DBAL\Cache\QueryCacheProfile + */ + public function setLifetime($lifetime) + { + return new QueryCacheProfile($lifetime, $this->cacheKey, $this->resultCacheDriver); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php new file mode 100644 index 0000000..f04c852 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php @@ -0,0 +1,212 @@ +statement = $stmt; + $this->resultCache = $resultCache; + $this->cacheKey = $cacheKey; + $this->realKey = $realKey; + $this->lifetime = $lifetime; + } + + /** + * {@inheritdoc} + */ + public function closeCursor() + { + $this->statement->closeCursor(); + if (! $this->emptied || $this->data === null) { + return true; + } + + $data = $this->resultCache->fetch($this->cacheKey); + if (! $data) { + $data = []; + } + $data[$this->realKey] = $this->data; + + $this->resultCache->save($this->cacheKey, $data, $this->lifetime); + unset($this->data); + + return true; + } + + /** + * {@inheritdoc} + */ + public function columnCount() + { + return $this->statement->columnCount(); + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $this->defaultFetchMode = $fetchMode; + + return true; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + $data = $this->fetchAll(); + + return new ArrayIterator($data); + } + + /** + * {@inheritdoc} + */ + public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + { + if ($this->data === null) { + $this->data = []; + } + + $row = $this->statement->fetch(FetchMode::ASSOCIATIVE); + + if ($row) { + $this->data[] = $row; + + $fetchMode = $fetchMode ?: $this->defaultFetchMode; + + if ($fetchMode === FetchMode::ASSOCIATIVE) { + return $row; + } + + if ($fetchMode === FetchMode::NUMERIC) { + return array_values($row); + } + + if ($fetchMode === FetchMode::MIXED) { + return array_merge($row, array_values($row)); + } + + if ($fetchMode === FetchMode::COLUMN) { + return reset($row); + } + + throw new InvalidArgumentException('Invalid fetch-style given for caching result.'); + } + + $this->emptied = true; + + return false; + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + { + $data = $this->statement->fetchAll($fetchMode, $fetchArgument, $ctorArgs); + + if ($fetchMode === FetchMode::COLUMN) { + foreach ($data as $key => $value) { + $data[$key] = [$value]; + } + } + + $this->data = $data; + $this->emptied = true; + + return $this->data; + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + $row = $this->fetch(FetchMode::NUMERIC); + + // TODO: verify that return false is the correct behavior + return $row[$columnIndex] ?? false; + } + + /** + * 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 int The number of rows. + */ + public function rowCount() + { + assert($this->statement instanceof Statement); + + return $this->statement->rowCount(); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/ColumnCase.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/ColumnCase.php new file mode 100644 index 0000000..872d3ed --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/ColumnCase.php @@ -0,0 +1,32 @@ +_attributes['sqlLogger'] = $logger; + } + + /** + * Gets the SQL logger that is used. + * + * @return SQLLogger|null + */ + public function getSQLLogger() + { + return $this->_attributes['sqlLogger'] ?? null; + } + + /** + * Gets the cache driver implementation that is used for query result caching. + * + * @return Cache|null + */ + public function getResultCacheImpl() + { + return $this->_attributes['resultCacheImpl'] ?? null; + } + + /** + * Sets the cache driver implementation that is used for query result caching. + * + * @return void + */ + public function setResultCacheImpl(Cache $cacheImpl) + { + $this->_attributes['resultCacheImpl'] = $cacheImpl; + } + + /** + * Sets the filter schema assets expression. + * + * Only include tables/sequences matching the filter expression regexp in + * schema instances generated for the active connection when calling + * {AbstractSchemaManager#createSchema()}. + * + * @deprecated Use Configuration::setSchemaAssetsFilter() instead + * + * @param string $filterExpression + * + * @return void + */ + public function setFilterSchemaAssetsExpression($filterExpression) + { + $this->_attributes['filterSchemaAssetsExpression'] = $filterExpression; + if ($filterExpression) { + $this->_attributes['filterSchemaAssetsExpressionCallable'] = $this->buildSchemaAssetsFilterFromExpression($filterExpression); + } else { + $this->_attributes['filterSchemaAssetsExpressionCallable'] = null; + } + } + + /** + * Returns filter schema assets expression. + * + * @deprecated Use Configuration::getSchemaAssetsFilter() instead + * + * @return string|null + */ + public function getFilterSchemaAssetsExpression() + { + return $this->_attributes['filterSchemaAssetsExpression'] ?? null; + } + + /** + * @param string $filterExpression + */ + private function buildSchemaAssetsFilterFromExpression($filterExpression) : callable + { + return static function ($assetName) use ($filterExpression) { + if ($assetName instanceof AbstractAsset) { + $assetName = $assetName->getName(); + } + + return preg_match($filterExpression, $assetName); + }; + } + + /** + * Sets the callable to use to filter schema assets. + */ + public function setSchemaAssetsFilter(?callable $callable = null) : ?callable + { + $this->_attributes['filterSchemaAssetsExpression'] = null; + + return $this->_attributes['filterSchemaAssetsExpressionCallable'] = $callable; + } + + /** + * Returns the callable to use to filter schema assets. + */ + public function getSchemaAssetsFilter() : ?callable + { + return $this->_attributes['filterSchemaAssetsExpressionCallable'] ?? null; + } + + /** + * Sets the default auto-commit mode for connections. + * + * If a connection is in auto-commit mode, then all its SQL statements will be executed and committed as individual + * transactions. Otherwise, its SQL statements are grouped into transactions that are terminated by a call to either + * the method commit or the method rollback. By default, new connections are in auto-commit mode. + * + * @see getAutoCommit + * + * @param bool $autoCommit True to enable auto-commit mode; false to disable it. + */ + public function setAutoCommit($autoCommit) + { + $this->_attributes['autoCommit'] = (bool) $autoCommit; + } + + /** + * Returns the default auto-commit mode for connections. + * + * @see setAutoCommit + * + * @return bool True if auto-commit mode is enabled by default for connections, false otherwise. + */ + public function getAutoCommit() + { + return $this->_attributes['autoCommit'] ?? true; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php new file mode 100644 index 0000000..ee6c086 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php @@ -0,0 +1,1685 @@ +_driver = $driver; + $this->params = $params; + + if (isset($params['pdo'])) { + $this->_conn = $params['pdo']; + $this->isConnected = true; + unset($this->params['pdo']); + } + + if (isset($params['platform'])) { + if (! $params['platform'] instanceof Platforms\AbstractPlatform) { + throw DBALException::invalidPlatformType($params['platform']); + } + + $this->platform = $params['platform']; + } + + // 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; + + $this->_expr = new Query\Expression\ExpressionBuilder($this); + + $this->autoCommit = $config->getAutoCommit(); + } + + /** + * Gets the parameters used during instantiation. + * + * @return mixed[] + */ + public function getParams() + { + return $this->params; + } + + /** + * Gets the name of the database this Connection is connected to. + * + * @return string + */ + public function getDatabase() + { + return $this->_driver->getDatabase($this); + } + + /** + * Gets the hostname of the currently connected database. + * + * @deprecated + * + * @return string|null + */ + public function getHost() + { + return $this->params['host'] ?? null; + } + + /** + * Gets the port of the currently connected database. + * + * @deprecated + * + * @return mixed + */ + public function getPort() + { + return $this->params['port'] ?? null; + } + + /** + * Gets the username used by this connection. + * + * @deprecated + * + * @return string|null + */ + public function getUsername() + { + return $this->params['user'] ?? null; + } + + /** + * Gets the password used by this connection. + * + * @deprecated + * + * @return string|null + */ + public function getPassword() + { + return $this->params['password'] ?? null; + } + + /** + * Gets the DBAL driver instance. + * + * @return Driver + */ + public function getDriver() + { + return $this->_driver; + } + + /** + * Gets the Configuration used by the Connection. + * + * @return Configuration + */ + public function getConfiguration() + { + return $this->_config; + } + + /** + * Gets the EventManager used by the Connection. + * + * @return EventManager + */ + public function getEventManager() + { + return $this->_eventManager; + } + + /** + * Gets the DatabasePlatform for the connection. + * + * @return AbstractPlatform + * + * @throws DBALException + */ + public function getDatabasePlatform() + { + if ($this->platform === null) { + $this->detectDatabasePlatform(); + } + + return $this->platform; + } + + /** + * Gets the ExpressionBuilder for the connection. + * + * @return ExpressionBuilder + */ + public function getExpressionBuilder() + { + return $this->_expr; + } + + /** + * Establishes the connection with the database. + * + * @return bool TRUE if the connection was successfully established, FALSE if + * the connection is already open. + */ + public function connect() + { + if ($this->isConnected) { + return false; + } + + $driverOptions = $this->params['driverOptions'] ?? []; + $user = $this->params['user'] ?? null; + $password = $this->params['password'] ?? null; + + $this->_conn = $this->_driver->connect($this->params, $user, $password, $driverOptions); + $this->isConnected = true; + + $this->transactionNestingLevel = 0; + + if ($this->autoCommit === false) { + $this->beginTransaction(); + } + + if ($this->_eventManager->hasListeners(Events::postConnect)) { + $eventArgs = new Event\ConnectionEventArgs($this); + $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); + } + + return true; + } + + /** + * Detects and sets the database platform. + * + * Evaluates custom platform class and version in order to set the correct platform. + * + * @throws DBALException If an invalid platform was specified for this connection. + */ + private function detectDatabasePlatform() + { + $version = $this->getDatabasePlatformVersion(); + + if ($version !== null) { + assert($this->_driver instanceof VersionAwarePlatformDriver); + + $this->platform = $this->_driver->createDatabasePlatformForVersion($version); + } else { + $this->platform = $this->_driver->getDatabasePlatform(); + } + + $this->platform->setEventManager($this->_eventManager); + } + + /** + * Returns the version of the related platform if applicable. + * + * Returns null if either the driver is not capable to create version + * specific platform instances, no explicit server version was specified + * or the underlying driver connection cannot determine the platform + * version without having to query it (performance reasons). + * + * @return string|null + * + * @throws Exception + */ + private function getDatabasePlatformVersion() + { + // Driver does not support version specific platforms. + if (! $this->_driver instanceof VersionAwarePlatformDriver) { + return null; + } + + // Explicit platform version requested (supersedes auto-detection). + if (isset($this->params['serverVersion'])) { + return $this->params['serverVersion']; + } + + // If not connected, we need to connect now to determine the platform version. + if ($this->_conn === null) { + try { + $this->connect(); + } catch (Throwable $originalException) { + if (empty($this->params['dbname'])) { + throw $originalException; + } + + // The database to connect to might not yet exist. + // Retry detection without database name connection parameter. + $databaseName = $this->params['dbname']; + $this->params['dbname'] = null; + + try { + $this->connect(); + } catch (Throwable $fallbackException) { + // Either the platform does not support database-less connections + // or something else went wrong. + // Reset connection parameters and rethrow the original exception. + $this->params['dbname'] = $databaseName; + + throw $originalException; + } + + // Reset connection parameters. + $this->params['dbname'] = $databaseName; + $serverVersion = $this->getServerVersion(); + + // Close "temporary" connection to allow connecting to the real database again. + $this->close(); + + return $serverVersion; + } + } + + return $this->getServerVersion(); + } + + /** + * Returns the database server version if the underlying driver supports it. + * + * @return string|null + */ + private function getServerVersion() + { + $connection = $this->getWrappedConnection(); + + // Automatic platform version detection. + if ($connection instanceof ServerInfoAwareConnection && ! $connection->requiresQueryForServerVersion()) { + return $connection->getServerVersion(); + } + + // Unable to detect platform version. + return null; + } + + /** + * Returns the current auto-commit mode for this connection. + * + * @see setAutoCommit + * + * @return bool True if auto-commit mode is currently enabled for this connection, false otherwise. + */ + public function isAutoCommit() + { + return $this->autoCommit === true; + } + + /** + * Sets auto-commit mode for this connection. + * + * If a connection is in auto-commit mode, then all its SQL statements will be executed and committed as individual + * transactions. Otherwise, its SQL statements are grouped into transactions that are terminated by a call to either + * the method commit or the method rollback. By default, new connections are in auto-commit mode. + * + * NOTE: If this method is called during a transaction and the auto-commit mode is changed, the transaction is + * committed. If this method is called and the auto-commit mode is not changed, the call is a no-op. + * + * @see isAutoCommit + * + * @param bool $autoCommit True to enable auto-commit mode; false to disable it. + */ + public function setAutoCommit($autoCommit) + { + $autoCommit = (bool) $autoCommit; + + // Mode not changed, no-op. + if ($autoCommit === $this->autoCommit) { + return; + } + + $this->autoCommit = $autoCommit; + + // Commit all currently active transactions if any when switching auto-commit mode. + if ($this->isConnected !== true || $this->transactionNestingLevel === 0) { + return; + } + + $this->commitAll(); + } + + /** + * Sets the fetch mode. + * + * @param int $fetchMode + * + * @return void + */ + public function setFetchMode($fetchMode) + { + $this->defaultFetchMode = $fetchMode; + } + + /** + * 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 mixed[] $params The query parameters. + * @param int[]|string[] $types The query parameter types. + * + * @return mixed[]|false False is returned if no rows are found. + * + * @throws DBALException + */ + public function fetchAssoc($statement, array $params = [], array $types = []) + { + return $this->executeQuery($statement, $params, $types)->fetch(FetchMode::ASSOCIATIVE); + } + + /** + * Prepares and executes an SQL query and returns the first row of the result + * as a numerically indexed array. + * + * @param string $statement The SQL query to be executed. + * @param mixed[] $params The prepared statement params. + * @param int[]|string[] $types The query parameter types. + * + * @return mixed[]|false False is returned if no rows are found. + */ + public function fetchArray($statement, array $params = [], array $types = []) + { + return $this->executeQuery($statement, $params, $types)->fetch(FetchMode::NUMERIC); + } + + /** + * Prepares and executes an SQL query and returns the value of a single column + * of the first row of the result. + * + * @param string $statement The SQL query to be executed. + * @param mixed[] $params The prepared statement params. + * @param int $column The 0-indexed column number to retrieve. + * @param int[]|string[] $types The query parameter types. + * + * @return mixed|false False is returned if no rows are found. + * + * @throws DBALException + */ + public function fetchColumn($statement, array $params = [], $column = 0, array $types = []) + { + return $this->executeQuery($statement, $params, $types)->fetchColumn($column); + } + + /** + * Whether an actual connection to the database is established. + * + * @return bool + */ + public function isConnected() + { + return $this->isConnected; + } + + /** + * Checks whether a transaction is currently active. + * + * @return bool TRUE if a transaction is currently active, FALSE otherwise. + */ + public function isTransactionActive() + { + return $this->transactionNestingLevel > 0; + } + + /** + * Adds identifier condition to the query components + * + * @param mixed[] $identifier Map of key columns to their values + * @param string[] $columns Column names + * @param mixed[] $values Column values + * @param string[] $conditions Key conditions + * + * @throws DBALException + */ + private function addIdentifierCondition( + array $identifier, + array &$columns, + array &$values, + array &$conditions + ) : void { + $platform = $this->getDatabasePlatform(); + + foreach ($identifier as $columnName => $value) { + if ($value === null) { + $conditions[] = $platform->getIsNullExpression($columnName); + continue; + } + + $columns[] = $columnName; + $values[] = $value; + $conditions[] = $columnName . ' = ?'; + } + } + + /** + * Executes an SQL DELETE statement on a table. + * + * Table expression and columns are not escaped and are not safe for user-input. + * + * @param string $tableExpression The expression of the table on which to delete. + * @param mixed[] $identifier The deletion criteria. An associative array containing column-value pairs. + * @param int[]|string[] $types The types of identifiers. + * + * @return int The number of affected rows. + * + * @throws DBALException + * @throws InvalidArgumentException + */ + public function delete($tableExpression, array $identifier, array $types = []) + { + if (empty($identifier)) { + throw InvalidArgumentException::fromEmptyCriteria(); + } + + $columns = $values = $conditions = []; + + $this->addIdentifierCondition($identifier, $columns, $values, $conditions); + + return $this->executeUpdate( + 'DELETE FROM ' . $tableExpression . ' WHERE ' . implode(' AND ', $conditions), + $values, + is_string(key($types)) ? $this->extractTypeValues($columns, $types) : $types + ); + } + + /** + * Closes the connection. + * + * @return void + */ + public function close() + { + $this->_conn = null; + + $this->isConnected = false; + } + + /** + * Sets the transaction isolation level. + * + * @param int $level The level to set. + * + * @return int + */ + public function setTransactionIsolation($level) + { + $this->transactionIsolationLevel = $level; + + return $this->executeUpdate($this->getDatabasePlatform()->getSetTransactionIsolationSQL($level)); + } + + /** + * Gets the currently active transaction isolation level. + * + * @return int The current transaction isolation level. + */ + public function getTransactionIsolation() + { + if ($this->transactionIsolationLevel === null) { + $this->transactionIsolationLevel = $this->getDatabasePlatform()->getDefaultTransactionIsolationLevel(); + } + + return $this->transactionIsolationLevel; + } + + /** + * Executes an SQL UPDATE statement on a table. + * + * Table expression and columns are not escaped and are not safe for user-input. + * + * @param string $tableExpression The expression of the table to update quoted or unquoted. + * @param mixed[] $data An associative array containing column-value pairs. + * @param mixed[] $identifier The update criteria. An associative array containing column-value pairs. + * @param int[]|string[] $types Types of the merged $data and $identifier arrays in that order. + * + * @return int The number of affected rows. + * + * @throws DBALException + */ + public function update($tableExpression, array $data, array $identifier, array $types = []) + { + $columns = $values = $conditions = $set = []; + + foreach ($data as $columnName => $value) { + $columns[] = $columnName; + $values[] = $value; + $set[] = $columnName . ' = ?'; + } + + $this->addIdentifierCondition($identifier, $columns, $values, $conditions); + + if (is_string(key($types))) { + $types = $this->extractTypeValues($columns, $types); + } + + $sql = 'UPDATE ' . $tableExpression . ' SET ' . implode(', ', $set) + . ' WHERE ' . implode(' AND ', $conditions); + + return $this->executeUpdate($sql, $values, $types); + } + + /** + * Inserts a table row with specified data. + * + * Table expression and columns are not escaped and are not safe for user-input. + * + * @param string $tableExpression The expression of the table to insert data into, quoted or unquoted. + * @param mixed[] $data An associative array containing column-value pairs. + * @param int[]|string[] $types Types of the inserted data. + * + * @return int The number of affected rows. + * + * @throws DBALException + */ + public function insert($tableExpression, array $data, array $types = []) + { + if (empty($data)) { + return $this->executeUpdate('INSERT INTO ' . $tableExpression . ' () VALUES ()'); + } + + $columns = []; + $values = []; + $set = []; + + foreach ($data as $columnName => $value) { + $columns[] = $columnName; + $values[] = $value; + $set[] = '?'; + } + + return $this->executeUpdate( + 'INSERT INTO ' . $tableExpression . ' (' . implode(', ', $columns) . ')' . + ' VALUES (' . implode(', ', $set) . ')', + $values, + is_string(key($types)) ? $this->extractTypeValues($columns, $types) : $types + ); + } + + /** + * Extract ordered type list from an ordered column list and type map. + * + * @param int[]|string[] $columnList + * @param int[]|string[] $types + * + * @return int[]|string[] + */ + private function extractTypeValues(array $columnList, array $types) + { + $typeValues = []; + + foreach ($columnList as $columnIndex => $columnName) { + $typeValues[] = $types[$columnName] ?? ParameterType::STRING; + } + + return $typeValues; + } + + /** + * Quotes 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->getDatabasePlatform()->quoteIdentifier($str); + } + + /** + * {@inheritDoc} + */ + public function quote($input, $type = null) + { + $connection = $this->getWrappedConnection(); + + [$value, $bindingType] = $this->getBindingInfo($input, $type); + + return $connection->quote($value, $bindingType); + } + + /** + * Prepares and executes an SQL query and returns the result as an associative array. + * + * @param string $sql The SQL query. + * @param mixed[] $params The query parameters. + * @param int[]|string[] $types The query parameter types. + * + * @return mixed[] + */ + public function fetchAll($sql, array $params = [], $types = []) + { + return $this->executeQuery($sql, $params, $types)->fetchAll(); + } + + /** + * Prepares an SQL statement. + * + * @param string $statement The SQL statement to prepare. + * + * @return DriverStatement The prepared statement. + * + * @throws DBALException + */ + public function prepare($statement) + { + try { + $stmt = new Statement($statement, $this); + } catch (Throwable $ex) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $statement); + } + + $stmt->setFetchMode($this->defaultFetchMode); + + return $stmt; + } + + /** + * Executes an, optionally parametrized, SQL query. + * + * If the query is parametrized, a prepared statement is used. + * If an SQLLogger is configured, the execution is logged. + * + * @param string $query The SQL query to execute. + * @param mixed[] $params The parameters to bind to the query, if any. + * @param int[]|string[] $types The types the previous parameters are in. + * @param QueryCacheProfile|null $qcp The query cache profile, optional. + * + * @return ResultStatement The executed statement. + * + * @throws DBALException + */ + public function executeQuery($query, array $params = [], $types = [], ?QueryCacheProfile $qcp = null) + { + if ($qcp !== null) { + return $this->executeCacheQuery($query, $params, $types, $qcp); + } + + $connection = $this->getWrappedConnection(); + + $logger = $this->_config->getSQLLogger(); + if ($logger) { + $logger->startQuery($query, $params, $types); + } + + try { + if ($params) { + [$query, $params, $types] = SQLParserUtils::expandListParameters($query, $params, $types); + + $stmt = $connection->prepare($query); + if ($types) { + $this->_bindTypedValues($stmt, $params, $types); + $stmt->execute(); + } else { + $stmt->execute($params); + } + } else { + $stmt = $connection->query($query); + } + } catch (Throwable $ex) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $query, $this->resolveParams($params, $types)); + } + + $stmt->setFetchMode($this->defaultFetchMode); + + if ($logger) { + $logger->stopQuery(); + } + + return $stmt; + } + + /** + * Executes a caching query. + * + * @param string $query The SQL query to execute. + * @param mixed[] $params The parameters to bind to the query, if any. + * @param int[]|string[] $types The types the previous parameters are in. + * @param QueryCacheProfile $qcp The query cache profile. + * + * @return ResultStatement + * + * @throws CacheException + */ + public function executeCacheQuery($query, $params, $types, QueryCacheProfile $qcp) + { + $resultCache = $qcp->getResultCacheDriver() ?? $this->_config->getResultCacheImpl(); + + if ($resultCache === null) { + throw CacheException::noResultDriverConfigured(); + } + + $connectionParams = $this->getParams(); + unset($connectionParams['platform']); + + [$cacheKey, $realKey] = $qcp->generateCacheKeys($query, $params, $types, $connectionParams); + + // fetch the row pointers entry + $data = $resultCache->fetch($cacheKey); + + if ($data !== false) { + // is the real key part of this row pointers map or is the cache only pointing to other cache keys? + if (isset($data[$realKey])) { + $stmt = new ArrayStatement($data[$realKey]); + } elseif (array_key_exists($realKey, $data)) { + $stmt = new ArrayStatement([]); + } + } + + if (! isset($stmt)) { + $stmt = new ResultCacheStatement($this->executeQuery($query, $params, $types), $resultCache, $cacheKey, $realKey, $qcp->getLifetime()); + } + + $stmt->setFetchMode($this->defaultFetchMode); + + return $stmt; + } + + /** + * Executes an, optionally parametrized, 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 mixed[] $params The parameters, if any. + * @param Closure $function The transformation function that is applied on each row. + * The function receives a single parameter, 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 = []; + $stmt = $this->executeQuery($query, $params); + + while ($row = $stmt->fetch()) { + $result[] = $function($row); + } + + $stmt->closeCursor(); + + return $result; + } + + /** + * Executes an SQL statement, returning a result set as a Statement object. + * + * @return \Doctrine\DBAL\Driver\Statement + * + * @throws DBALException + */ + public function query() + { + $connection = $this->getWrappedConnection(); + + $args = func_get_args(); + + $logger = $this->_config->getSQLLogger(); + if ($logger) { + $logger->startQuery($args[0]); + } + + try { + $statement = $connection->query(...$args); + } catch (Throwable $ex) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $args[0]); + } + + $statement->setFetchMode($this->defaultFetchMode); + + if ($logger) { + $logger->stopQuery(); + } + + return $statement; + } + + /** + * 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 mixed[] $params The query parameters. + * @param int[]|string[] $types The parameter types. + * + * @return int The number of affected rows. + * + * @throws DBALException + */ + public function executeUpdate($query, array $params = [], array $types = []) + { + $connection = $this->getWrappedConnection(); + + $logger = $this->_config->getSQLLogger(); + if ($logger) { + $logger->startQuery($query, $params, $types); + } + + try { + if ($params) { + [$query, $params, $types] = SQLParserUtils::expandListParameters($query, $params, $types); + + $stmt = $connection->prepare($query); + + if ($types) { + $this->_bindTypedValues($stmt, $params, $types); + $stmt->execute(); + } else { + $stmt->execute($params); + } + $result = $stmt->rowCount(); + } else { + $result = $connection->exec($query); + } + } catch (Throwable $ex) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $query, $this->resolveParams($params, $types)); + } + + if ($logger) { + $logger->stopQuery(); + } + + return $result; + } + + /** + * Executes an SQL statement and return the number of affected rows. + * + * @param string $statement + * + * @return int The number of affected rows. + * + * @throws DBALException + */ + public function exec($statement) + { + $connection = $this->getWrappedConnection(); + + $logger = $this->_config->getSQLLogger(); + if ($logger) { + $logger->startQuery($statement); + } + + try { + $result = $connection->exec($statement); + } catch (Throwable $ex) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $statement); + } + + if ($logger) { + $logger->stopQuery(); + } + + return $result; + } + + /** + * Returns the current transaction nesting level. + * + * @return int The nesting level. A value of 0 means there's no active transaction. + */ + public function getTransactionNestingLevel() + { + return $this->transactionNestingLevel; + } + + /** + * Fetches the SQLSTATE associated with the last database operation. + * + * @return string|null The last error code. + */ + public function errorCode() + { + return $this->getWrappedConnection()->errorCode(); + } + + /** + * {@inheritDoc} + */ + public function errorInfo() + { + return $this->getWrappedConnection()->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|null $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) + { + return $this->getWrappedConnection()->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. + * + * @return mixed The value returned by $func + * + * @throws Exception + * @throws Throwable + */ + public function transactional(Closure $func) + { + $this->beginTransaction(); + try { + $res = $func($this); + $this->commit(); + + return $res; + } catch (Exception $e) { + $this->rollBack(); + throw $e; + } catch (Throwable $e) { + $this->rollBack(); + throw $e; + } + } + + /** + * Sets if nested transactions should use savepoints. + * + * @param bool $nestTransactionsWithSavepoints + * + * @return void + * + * @throws ConnectionException + */ + public function setNestTransactionsWithSavepoints($nestTransactionsWithSavepoints) + { + if ($this->transactionNestingLevel > 0) { + throw ConnectionException::mayNotAlterNestedTransactionWithSavepointsInTransaction(); + } + + if (! $this->getDatabasePlatform()->supportsSavepoints()) { + throw ConnectionException::savepointsNotSupported(); + } + + $this->nestTransactionsWithSavepoints = (bool) $nestTransactionsWithSavepoints; + } + + /** + * Gets if nested transactions should use savepoints. + * + * @return bool + */ + 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; + } + + /** + * {@inheritDoc} + */ + public function beginTransaction() + { + $connection = $this->getWrappedConnection(); + + ++$this->transactionNestingLevel; + + $logger = $this->_config->getSQLLogger(); + + if ($this->transactionNestingLevel === 1) { + if ($logger) { + $logger->startQuery('"START TRANSACTION"'); + } + + $connection->beginTransaction(); + + if ($logger) { + $logger->stopQuery(); + } + } elseif ($this->nestTransactionsWithSavepoints) { + if ($logger) { + $logger->startQuery('"SAVEPOINT"'); + } + $this->createSavepoint($this->_getNestedTransactionSavePointName()); + if ($logger) { + $logger->stopQuery(); + } + } + + return true; + } + + /** + * {@inheritDoc} + * + * @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(); + } + + $result = true; + + $connection = $this->getWrappedConnection(); + + $logger = $this->_config->getSQLLogger(); + + if ($this->transactionNestingLevel === 1) { + if ($logger) { + $logger->startQuery('"COMMIT"'); + } + + $result = $connection->commit(); + + if ($logger) { + $logger->stopQuery(); + } + } elseif ($this->nestTransactionsWithSavepoints) { + if ($logger) { + $logger->startQuery('"RELEASE SAVEPOINT"'); + } + $this->releaseSavepoint($this->_getNestedTransactionSavePointName()); + if ($logger) { + $logger->stopQuery(); + } + } + + --$this->transactionNestingLevel; + + if ($this->autoCommit !== false || $this->transactionNestingLevel !== 0) { + return $result; + } + + $this->beginTransaction(); + + return $result; + } + + /** + * Commits all current nesting transactions. + */ + private function commitAll() + { + while ($this->transactionNestingLevel !== 0) { + if ($this->autoCommit === false && $this->transactionNestingLevel === 1) { + // When in no auto-commit mode, the last nesting commit immediately starts a new transaction. + // Therefore we need to do the final commit here and then leave to avoid an infinite loop. + $this->commit(); + + return; + } + + $this->commit(); + } + } + + /** + * Cancels any database changes done during the current transaction. + * + * @throws ConnectionException If the rollback operation failed. + */ + public function rollBack() + { + if ($this->transactionNestingLevel === 0) { + throw ConnectionException::noActiveTransaction(); + } + + $connection = $this->getWrappedConnection(); + + $logger = $this->_config->getSQLLogger(); + + if ($this->transactionNestingLevel === 1) { + if ($logger) { + $logger->startQuery('"ROLLBACK"'); + } + $this->transactionNestingLevel = 0; + $connection->rollBack(); + $this->isRollbackOnly = false; + if ($logger) { + $logger->stopQuery(); + } + + if ($this->autoCommit === false) { + $this->beginTransaction(); + } + } elseif ($this->nestTransactionsWithSavepoints) { + if ($logger) { + $logger->startQuery('"ROLLBACK TO SAVEPOINT"'); + } + $this->rollbackSavepoint($this->_getNestedTransactionSavePointName()); + --$this->transactionNestingLevel; + if ($logger) { + $logger->stopQuery(); + } + } else { + $this->isRollbackOnly = true; + --$this->transactionNestingLevel; + } + } + + /** + * Creates a new savepoint. + * + * @param string $savepoint The name of the savepoint to create. + * + * @return void + * + * @throws ConnectionException + */ + public function createSavepoint($savepoint) + { + if (! $this->getDatabasePlatform()->supportsSavepoints()) { + throw ConnectionException::savepointsNotSupported(); + } + + $this->getWrappedConnection()->exec($this->platform->createSavePoint($savepoint)); + } + + /** + * Releases the given savepoint. + * + * @param string $savepoint The name of the savepoint to release. + * + * @return void + * + * @throws ConnectionException + */ + public function releaseSavepoint($savepoint) + { + if (! $this->getDatabasePlatform()->supportsSavepoints()) { + throw ConnectionException::savepointsNotSupported(); + } + + if (! $this->platform->supportsReleaseSavepoints()) { + return; + } + + $this->getWrappedConnection()->exec($this->platform->releaseSavePoint($savepoint)); + } + + /** + * Rolls back to the given savepoint. + * + * @param string $savepoint The name of the savepoint to rollback to. + * + * @return void + * + * @throws ConnectionException + */ + public function rollbackSavepoint($savepoint) + { + if (! $this->getDatabasePlatform()->supportsSavepoints()) { + throw ConnectionException::savepointsNotSupported(); + } + + $this->getWrappedConnection()->exec($this->platform->rollbackSavePoint($savepoint)); + } + + /** + * Gets the wrapped driver connection. + * + * @return DriverConnection + */ + 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 AbstractSchemaManager + */ + public function getSchemaManager() + { + if ($this->_schemaManager === null) { + $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. + * + * @return void + * + * @throws ConnectionException If no transaction is active. + */ + public function setRollbackOnly() + { + if ($this->transactionNestingLevel === 0) { + throw ConnectionException::noActiveTransaction(); + } + $this->isRollbackOnly = true; + } + + /** + * Checks whether the current transaction is marked for rollback only. + * + * @return bool + * + * @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->getDatabasePlatform()); + } + + /** + * 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->getDatabasePlatform()); + } + + /** + * 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. + * + * @internal Duck-typing used on the $stmt parameter to support driver statements as well as + * raw PDOStatement instances. + * + * @param \Doctrine\DBAL\Driver\Statement $stmt The statement to bind the values to. + * @param mixed[] $params The map/list of named/positional parameters. + * @param int[]|string[] $types The parameter types (PDO binding types or DBAL mapping types). + * + * @return void + */ + 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 = array_key_exists(0, $types) ? -1 : 0; + $bindIndex = 1; + foreach ($params as $value) { + $typeIndex = $bindIndex + $typeOffset; + if (isset($types[$typeIndex])) { + $type = $types[$typeIndex]; + [$value, $bindingType] = $this->getBindingInfo($value, $type); + $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]; + [$value, $bindingType] = $this->getBindingInfo($value, $type); + $stmt->bindValue($name, $value, $bindingType); + } else { + $stmt->bindValue($name, $value); + } + } + } + } + + /** + * Gets the binding type of a given type. The given type can be a PDO or DBAL mapping type. + * + * @param mixed $value The value to bind. + * @param int|string|null $type The type to bind (PDO or DBAL). + * + * @return mixed[] [0] => the (escaped) value, [1] => the binding type. + */ + private function getBindingInfo($value, $type) + { + if (is_string($type)) { + $type = Type::getType($type); + } + if ($type instanceof Type) { + $value = $type->convertToDatabaseValue($value, $this->getDatabasePlatform()); + $bindingType = $type->getBindingType(); + } else { + $bindingType = $type; + } + + return [$value, $bindingType]; + } + + /** + * Resolves the parameters to a format which can be displayed. + * + * @internal This is a purely internal method. If you rely on this method, you are advised to + * copy/paste the code as this method may change, or be removed without prior notice. + * + * @param mixed[] $params + * @param int[]|string[] $types + * + * @return mixed[] + */ + public function resolveParams(array $params, array $types) + { + $resolvedParams = []; + + // Check whether parameters are positional or named. Mixing is not allowed, just like in PDO. + if (is_int(key($params))) { + // Positional parameters + $typeOffset = array_key_exists(0, $types) ? -1 : 0; + $bindIndex = 1; + foreach ($params as $value) { + $typeIndex = $bindIndex + $typeOffset; + if (isset($types[$typeIndex])) { + $type = $types[$typeIndex]; + [$value] = $this->getBindingInfo($value, $type); + $resolvedParams[$bindIndex] = $value; + } else { + $resolvedParams[$bindIndex] = $value; + } + ++$bindIndex; + } + } else { + // Named parameters + foreach ($params as $name => $value) { + if (isset($types[$name])) { + $type = $types[$name]; + [$value] = $this->getBindingInfo($value, $type); + $resolvedParams[$name] = $value; + } else { + $resolvedParams[$name] = $value; + } + } + } + + return $resolvedParams; + } + + /** + * Creates a new instance of a SQL query builder. + * + * @return QueryBuilder + */ + public function createQueryBuilder() + { + return new Query\QueryBuilder($this); + } + + /** + * Ping the server + * + * When the server is not available the method returns FALSE. + * It is responsibility of the developer to handle this case + * and abort the request or reconnect manually: + * + * @return bool + * + * @example + * + * if ($conn->ping() === false) { + * $conn->close(); + * $conn->connect(); + * } + * + * It is undefined if the underlying driver attempts to reconnect + * or disconnect when the connection is not available anymore + * as long it returns TRUE when a reconnect succeeded and + * FALSE when the connection was dropped. + */ + public function ping() + { + $connection = $this->getWrappedConnection(); + + if ($connection instanceof PingableConnection) { + return $connection->ping(); + } + + try { + $this->query($this->getDatabasePlatform()->getDummySelectSQL()); + + return true; + } catch (DBALException $e) { + return false; + } + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/ConnectionException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/ConnectionException.php new file mode 100644 index 0000000..d3d11bc --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/ConnectionException.php @@ -0,0 +1,38 @@ +executeQuery("DELETE FROM table"); + * + * Be aware that Connection#executeQuery is a method specifically for READ + * operations only. + * + * This connection is limited to slave operations using the + * Connection#executeQuery operation only, because it wouldn't be compatible + * with the ORM or SchemaManager code otherwise. Both use all the other + * operations in a context where writes could happen to a slave, which makes + * this restricted approach necessary. + * + * You can manually connect to the master at any time by calling: + * + * $conn->connect('master'); + * + * Instantiation through the DriverManager looks like: + * + * @example + * + * $conn = DriverManager::getConnection(array( + * 'wrapperClass' => 'Doctrine\DBAL\Connections\MasterSlaveConnection', + * 'driver' => 'pdo_mysql', + * 'master' => array('user' => '', 'password' => '', 'host' => '', 'dbname' => ''), + * 'slaves' => array( + * array('user' => 'slave1', 'password', 'host' => '', 'dbname' => ''), + * array('user' => 'slave2', 'password', 'host' => '', 'dbname' => ''), + * ) + * )); + * + * You can also pass 'driverOptions' and any other documented option to each of this drivers to pass additional information. + */ +class MasterSlaveConnection extends Connection +{ + /** + * Master and slave connection (one of the randomly picked slaves). + * + * @var DriverConnection[]|null[] + */ + protected $connections = ['master' => null, 'slave' => null]; + + /** + * You can keep the slave connection and then switch back to it + * during the request if you know what you are doing. + * + * @var bool + */ + protected $keepSlave = false; + + /** + * Creates Master Slave Connection. + * + * @param mixed[] $params + * + * @throws InvalidArgumentException + */ + public function __construct(array $params, Driver $driver, ?Configuration $config = null, ?EventManager $eventManager = null) + { + if (! isset($params['slaves'], $params['master'])) { + throw new InvalidArgumentException('master or slaves configuration missing'); + } + if (count($params['slaves']) === 0) { + throw new InvalidArgumentException('You have to configure at least one slaves.'); + } + + $params['master']['driver'] = $params['driver']; + foreach ($params['slaves'] as $slaveKey => $slave) { + $params['slaves'][$slaveKey]['driver'] = $params['driver']; + } + + $this->keepSlave = (bool) ($params['keepSlave'] ?? false); + + parent::__construct($params, $driver, $config, $eventManager); + } + + /** + * Checks if the connection is currently towards the master or not. + * + * @return bool + */ + public function isConnectedToMaster() + { + return $this->_conn !== null && $this->_conn === $this->connections['master']; + } + + /** + * {@inheritDoc} + */ + public function connect($connectionName = null) + { + $requestedConnectionChange = ($connectionName !== null); + $connectionName = $connectionName ?: 'slave'; + + if ($connectionName !== 'slave' && $connectionName !== 'master') { + throw new InvalidArgumentException('Invalid option to connect(), only master or slave allowed.'); + } + + // If we have a connection open, and this is not an explicit connection + // change request, then abort right here, because we are already done. + // This prevents writes to the slave in case of "keepSlave" option enabled. + if ($this->_conn !== null && ! $requestedConnectionChange) { + return false; + } + + $forceMasterAsSlave = false; + + if ($this->getTransactionNestingLevel() > 0) { + $connectionName = 'master'; + $forceMasterAsSlave = true; + } + + if (isset($this->connections[$connectionName])) { + $this->_conn = $this->connections[$connectionName]; + + if ($forceMasterAsSlave && ! $this->keepSlave) { + $this->connections['slave'] = $this->_conn; + } + + return false; + } + + if ($connectionName === 'master') { + $this->connections['master'] = $this->_conn = $this->connectTo($connectionName); + + // Set slave connection to master to avoid invalid reads + if (! $this->keepSlave) { + $this->connections['slave'] = $this->connections['master']; + } + } else { + $this->connections['slave'] = $this->_conn = $this->connectTo($connectionName); + } + + if ($this->_eventManager->hasListeners(Events::postConnect)) { + $eventArgs = new ConnectionEventArgs($this); + $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); + } + + return true; + } + + /** + * Connects to a specific connection. + * + * @param string $connectionName + * + * @return DriverConnection + */ + protected function connectTo($connectionName) + { + $params = $this->getParams(); + + $driverOptions = $params['driverOptions'] ?? []; + + $connectionParams = $this->chooseConnectionConfiguration($connectionName, $params); + + $user = $connectionParams['user'] ?? null; + $password = $connectionParams['password'] ?? null; + + return $this->_driver->connect($connectionParams, $user, $password, $driverOptions); + } + + /** + * @param string $connectionName + * @param mixed[] $params + * + * @return mixed + */ + protected function chooseConnectionConfiguration($connectionName, $params) + { + if ($connectionName === 'master') { + return $params['master']; + } + + $config = $params['slaves'][array_rand($params['slaves'])]; + + if (! isset($config['charset']) && isset($params['master']['charset'])) { + $config['charset'] = $params['master']['charset']; + } + + return $config; + } + + /** + * {@inheritDoc} + */ + public function executeUpdate($query, array $params = [], array $types = []) + { + $this->connect('master'); + + return parent::executeUpdate($query, $params, $types); + } + + /** + * {@inheritDoc} + */ + public function beginTransaction() + { + $this->connect('master'); + + return parent::beginTransaction(); + } + + /** + * {@inheritDoc} + */ + public function commit() + { + $this->connect('master'); + + return parent::commit(); + } + + /** + * {@inheritDoc} + */ + public function rollBack() + { + $this->connect('master'); + + return parent::rollBack(); + } + + /** + * {@inheritDoc} + */ + public function delete($tableName, array $identifier, array $types = []) + { + $this->connect('master'); + + return parent::delete($tableName, $identifier, $types); + } + + /** + * {@inheritDoc} + */ + public function close() + { + unset($this->connections['master'], $this->connections['slave']); + + parent::close(); + + $this->_conn = null; + $this->connections = ['master' => null, 'slave' => null]; + } + + /** + * {@inheritDoc} + */ + public function update($tableName, array $data, array $identifier, array $types = []) + { + $this->connect('master'); + + return parent::update($tableName, $data, $identifier, $types); + } + + /** + * {@inheritDoc} + */ + public function insert($tableName, array $data, array $types = []) + { + $this->connect('master'); + + return parent::insert($tableName, $data, $types); + } + + /** + * {@inheritDoc} + */ + public function exec($statement) + { + $this->connect('master'); + + return parent::exec($statement); + } + + /** + * {@inheritDoc} + */ + public function createSavepoint($savepoint) + { + $this->connect('master'); + + parent::createSavepoint($savepoint); + } + + /** + * {@inheritDoc} + */ + public function releaseSavepoint($savepoint) + { + $this->connect('master'); + + parent::releaseSavepoint($savepoint); + } + + /** + * {@inheritDoc} + */ + public function rollbackSavepoint($savepoint) + { + $this->connect('master'); + + parent::rollbackSavepoint($savepoint); + } + + /** + * {@inheritDoc} + */ + public function query() + { + $this->connect('master'); + assert($this->_conn instanceof DriverConnection); + + $args = func_get_args(); + + $logger = $this->getConfiguration()->getSQLLogger(); + if ($logger) { + $logger->startQuery($args[0]); + } + + $statement = $this->_conn->query(...$args); + + $statement->setFetchMode($this->defaultFetchMode); + + if ($logger) { + $logger->stopQuery(); + } + + return $statement; + } + + /** + * {@inheritDoc} + */ + public function prepare($statement) + { + $this->connect('master'); + + return parent::prepare($statement); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php new file mode 100644 index 0000000..4961af2 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php @@ -0,0 +1,294 @@ +getMessage(); + + return static::wrapException($driver, $driverEx, $msg); + } + + /** + * @return self + */ + public static function driverException(Driver $driver, Throwable $driverEx) + { + return static::wrapException($driver, $driverEx, 'An exception occurred in driver: ' . $driverEx->getMessage()); + } + + /** + * @return self + */ + private static function wrapException(Driver $driver, Throwable $driverEx, $msg) + { + if ($driverEx instanceof DriverException) { + return $driverEx; + } + if ($driver instanceof ExceptionConverterDriver && $driverEx instanceof DriverExceptionInterface) { + return $driver->convertException($msg, $driverEx); + } + + return new self($msg, 0, $driverEx); + } + + /** + * Returns a human-readable representation of an array of parameters. + * This properly handles binary data by returning a hex representation. + * + * @param mixed[] $params + * + * @return string + */ + private static function formatParameters(array $params) + { + return '[' . implode(', ', array_map(static function ($param) { + if (is_resource($param)) { + return (string) $param; + } + + $json = @json_encode($param); + + if (! is_string($json) || $json === 'null' && is_string($param)) { + // JSON encoding failed, this is not a UTF-8 string. + return sprintf('"%s"', preg_replace('/.{2}/', '\\x$0', bin2hex($param))); + } + + return $json; + }, $params)) . ']'; + } + + /** + * @param string $wrapperClass + * + * @return \Doctrine\DBAL\DBALException + */ + public static function invalidWrapperClass($wrapperClass) + { + return new self("The given 'wrapperClass' " . $wrapperClass . ' has to be a ' . + 'subtype of \Doctrine\DBAL\Connection.'); + } + + /** + * @param string $driverClass + * + * @return \Doctrine\DBAL\DBALException + */ + public static function invalidDriverClass($driverClass) + { + return new self("The given 'driverClass' " . $driverClass . ' has to implement the ' . Driver::class . ' interface.'); + } + + /** + * @param string $tableName + * + * @return \Doctrine\DBAL\DBALException + */ + public static function invalidTableName($tableName) + { + return new self('Invalid table name specified: ' . $tableName); + } + + /** + * @param string $tableName + * + * @return \Doctrine\DBAL\DBALException + */ + public static function noColumnsSpecifiedForTable($tableName) + { + return new self('No columns specified for table ' . $tableName); + } + + /** + * @return \Doctrine\DBAL\DBALException + */ + public static function limitOffsetInvalid() + { + return new self('Invalid Offset in Limit Query, it has to be larger than or equal to 0.'); + } + + /** + * @param string $name + * + * @return \Doctrine\DBAL\DBALException + */ + public static function typeExists($name) + { + return new self('Type ' . $name . ' already exists.'); + } + + /** + * @param string $name + * + * @return \Doctrine\DBAL\DBALException + */ + public static function unknownColumnType($name) + { + return new self('Unknown column type "' . $name . '" requested. Any Doctrine type that you use has ' . + 'to be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list of all the ' . + 'known types with \Doctrine\DBAL\Types\Type::getTypesMap(). If this error occurs during database ' . + 'introspection then you might have forgotten to register all database types for a Doctrine Type. Use ' . + 'AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement ' . + 'Type#getMappedDatabaseTypes(). If the type name is empty you might ' . + 'have a problem with the cache or forgot some mapping information.'); + } + + /** + * @param string $name + * + * @return \Doctrine\DBAL\DBALException + */ + public static function typeNotFound($name) + { + return new self('Type to be overwritten ' . $name . ' does not exist.'); + } + + public static function typeNotRegistered(Type $type) : self + { + return new self(sprintf('Type of the class %s@%s is not registered.', get_class($type), spl_object_hash($type))); + } + + public static function typeAlreadyRegistered(Type $type) : self + { + return new self( + sprintf('Type of the class %s@%s is already registered.', get_class($type), spl_object_hash($type)) + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver.php new file mode 100644 index 0000000..57493e6 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver.php @@ -0,0 +1,59 @@ +getParams(); + + return $params['dbname']; + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new DB2Platform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(Connection $conn) + { + return new DB2SchemaManager($conn); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDriverException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDriverException.php new file mode 100644 index 0000000..d9af92d --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDriverException.php @@ -0,0 +1,54 @@ +errorCode = $errorCode; + $this->sqlState = $sqlState; + } + + /** + * {@inheritdoc} + */ + public function getErrorCode() + { + return $this->errorCode; + } + + /** + * {@inheritdoc} + */ + public function getSQLState() + { + return $this->sqlState; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php new file mode 100644 index 0000000..c46ddc6 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php @@ -0,0 +1,218 @@ +getErrorCode()) { + case '1213': + return new Exception\DeadlockException($message, $exception); + case '1205': + return new Exception\LockWaitTimeoutException($message, $exception); + case '1050': + return new Exception\TableExistsException($message, $exception); + + case '1051': + case '1146': + return new Exception\TableNotFoundException($message, $exception); + + case '1216': + case '1217': + case '1451': + case '1452': + case '1701': + return new Exception\ForeignKeyConstraintViolationException($message, $exception); + + case '1062': + case '1557': + case '1569': + case '1586': + return new Exception\UniqueConstraintViolationException($message, $exception); + + case '1054': + case '1166': + case '1611': + return new Exception\InvalidFieldNameException($message, $exception); + + case '1052': + case '1060': + case '1110': + return new Exception\NonUniqueFieldNameException($message, $exception); + + case '1064': + case '1149': + case '1287': + case '1341': + case '1342': + case '1343': + case '1344': + case '1382': + case '1479': + case '1541': + case '1554': + case '1626': + return new Exception\SyntaxErrorException($message, $exception); + + case '1044': + case '1045': + case '1046': + case '1049': + case '1095': + case '1142': + case '1143': + case '1227': + case '1370': + case '1429': + case '2002': + case '2005': + return new Exception\ConnectionException($message, $exception); + + case '1048': + case '1121': + case '1138': + case '1171': + case '1252': + case '1263': + case '1364': + case '1566': + return new Exception\NotNullConstraintViolationException($message, $exception); + } + + return new Exception\DriverException($message, $exception); + } + + /** + * {@inheritdoc} + * + * @throws DBALException + */ + public function createDatabasePlatformForVersion($version) + { + $mariadb = stripos($version, 'mariadb') !== false; + if ($mariadb && version_compare($this->getMariaDbMysqlVersionNumber($version), '10.2.7', '>=')) { + return new MariaDb1027Platform(); + } + + if (! $mariadb) { + $oracleMysqlVersion = $this->getOracleMysqlVersionNumber($version); + if (version_compare($oracleMysqlVersion, '8', '>=')) { + return new MySQL80Platform(); + } + if (version_compare($oracleMysqlVersion, '5.7.9', '>=')) { + return new MySQL57Platform(); + } + } + + return $this->getDatabasePlatform(); + } + + /** + * Get a normalized 'version number' from the server string + * returned by Oracle MySQL servers. + * + * @param string $versionString Version string returned by the driver, i.e. '5.7.10' + * + * @throws DBALException + */ + private function getOracleMysqlVersionNumber(string $versionString) : string + { + if (! preg_match( + '/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?/', + $versionString, + $versionParts + )) { + throw DBALException::invalidPlatformVersionSpecified( + $versionString, + '..' + ); + } + $majorVersion = $versionParts['major']; + $minorVersion = $versionParts['minor'] ?? 0; + $patchVersion = $versionParts['patch'] ?? null; + + if ($majorVersion === '5' && $minorVersion === '7' && $patchVersion === null) { + $patchVersion = '9'; + } + + return $majorVersion . '.' . $minorVersion . '.' . $patchVersion; + } + + /** + * Detect MariaDB server version, including hack for some mariadb distributions + * that starts with the prefix '5.5.5-' + * + * @param string $versionString Version string as returned by mariadb server, i.e. '5.5.5-Mariadb-10.0.8-xenial' + * + * @throws DBALException + */ + private function getMariaDbMysqlVersionNumber(string $versionString) : string + { + if (! preg_match( + '/^(?:5\.5\.5-)?(mariadb-)?(?P\d+)\.(?P\d+)\.(?P\d+)/i', + $versionString, + $versionParts + )) { + throw DBALException::invalidPlatformVersionSpecified( + $versionString, + '^(?:5\.5\.5-)?(mariadb-)?..' + ); + } + + return $versionParts['major'] . '.' . $versionParts['minor'] . '.' . $versionParts['patch']; + } + + /** + * {@inheritdoc} + */ + public function getDatabase(Connection $conn) + { + $params = $conn->getParams(); + + return $params['dbname'] ?? $conn->query('SELECT DATABASE()')->fetchColumn(); + } + + /** + * {@inheritdoc} + * + * @return MySqlPlatform + */ + public function getDatabasePlatform() + { + return new MySqlPlatform(); + } + + /** + * {@inheritdoc} + * + * @return MySqlSchemaManager + */ + public function getSchemaManager(Connection $conn) + { + return new MySqlSchemaManager($conn); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php new file mode 100644 index 0000000..dcbaaf0 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php @@ -0,0 +1,97 @@ +getErrorCode()) { + case '1': + case '2299': + case '38911': + return new Exception\UniqueConstraintViolationException($message, $exception); + + case '904': + return new Exception\InvalidFieldNameException($message, $exception); + + case '918': + case '960': + return new Exception\NonUniqueFieldNameException($message, $exception); + + case '923': + return new Exception\SyntaxErrorException($message, $exception); + + case '942': + return new Exception\TableNotFoundException($message, $exception); + + case '955': + return new Exception\TableExistsException($message, $exception); + + case '1017': + case '12545': + return new Exception\ConnectionException($message, $exception); + + case '1400': + return new Exception\NotNullConstraintViolationException($message, $exception); + + case '2266': + case '2291': + case '2292': + return new Exception\ForeignKeyConstraintViolationException($message, $exception); + } + + return new Exception\DriverException($message, $exception); + } + + /** + * {@inheritdoc} + */ + public function getDatabase(Connection $conn) + { + $params = $conn->getParams(); + + return $params['user']; + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new OraclePlatform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(Connection $conn) + { + return new OracleSchemaManager($conn); + } + + /** + * Returns an appropriate Easy Connect String for the given parameters. + * + * @param mixed[] $params The connection parameters to return the Easy Connect String for. + * + * @return string + */ + protected function getEasyConnectString(array $params) + { + return (string) EasyConnectString::fromConnectionParameters($params); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver/EasyConnectString.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver/EasyConnectString.php new file mode 100644 index 0000000..01f648b --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver/EasyConnectString.php @@ -0,0 +1,121 @@ +string = $string; + } + + public function __toString() : string + { + return $this->string; + } + + /** + * Creates the object from an array representation + * + * @param mixed[] $params + */ + public static function fromArray(array $params) : self + { + return new self(self::renderParams($params)); + } + + /** + * Creates the object from the given DBAL connection parameters. + * + * @param mixed[] $params + */ + public static function fromConnectionParameters(array $params) : self + { + if (! empty($params['connectstring'])) { + return new self($params['connectstring']); + } + + if (empty($params['host'])) { + return new self($params['dbname'] ?? ''); + } + + $connectData = []; + + if (isset($params['servicename']) || isset($params['dbname'])) { + $serviceKey = 'SID'; + + if (! empty($params['service'])) { + $serviceKey = 'SERVICE_NAME'; + } + + $serviceName = $params['servicename'] ?? $params['dbname']; + + $connectData[$serviceKey] = $serviceName; + } + + if (! empty($params['instancename'])) { + $connectData['INSTANCE_NAME'] = $params['instancename']; + } + + if (! empty($params['pooled'])) { + $connectData['SERVER'] = 'POOLED'; + } + + return self::fromArray([ + 'DESCRIPTION' => [ + 'ADDRESS' => [ + 'PROTOCOL' => 'TCP', + 'HOST' => $params['host'], + 'PORT' => $params['port'] ?? 1521, + ], + 'CONNECT_DATA' => $connectData, + ], + ]); + } + + /** + * @param mixed[] $params + */ + private static function renderParams(array $params) : string + { + $chunks = []; + + foreach ($params as $key => $value) { + $string = self::renderValue($value); + + if ($string === '') { + continue; + } + + $chunks[] = sprintf('(%s=%s)', $key, $string); + } + + return implode('', $chunks); + } + + /** + * @param mixed $value + */ + private static function renderValue($value) : string + { + if (is_array($value)) { + return self::renderParams($value); + } + + return (string) $value; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractPostgreSQLDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractPostgreSQLDriver.php new file mode 100644 index 0000000..916d924 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractPostgreSQLDriver.php @@ -0,0 +1,138 @@ +getSQLState()) { + case '40001': + case '40P01': + return new Exception\DeadlockException($message, $exception); + case '0A000': + // Foreign key constraint violations during a TRUNCATE operation + // are considered "feature not supported" in PostgreSQL. + if (strpos($exception->getMessage(), 'truncate') !== false) { + return new Exception\ForeignKeyConstraintViolationException($message, $exception); + } + + break; + case '23502': + return new Exception\NotNullConstraintViolationException($message, $exception); + + case '23503': + return new Exception\ForeignKeyConstraintViolationException($message, $exception); + + case '23505': + return new Exception\UniqueConstraintViolationException($message, $exception); + + case '42601': + return new Exception\SyntaxErrorException($message, $exception); + + case '42702': + return new Exception\NonUniqueFieldNameException($message, $exception); + + case '42703': + return new Exception\InvalidFieldNameException($message, $exception); + + case '42P01': + return new Exception\TableNotFoundException($message, $exception); + + case '42P07': + return new Exception\TableExistsException($message, $exception); + + case '7': + // In some case (mainly connection errors) the PDO exception does not provide a SQLSTATE via its code. + // The exception code is always set to 7 here. + // We have to match against the SQLSTATE in the error message in these cases. + if (strpos($exception->getMessage(), 'SQLSTATE[08006]') !== false) { + return new Exception\ConnectionException($message, $exception); + } + + break; + } + + return new Exception\DriverException($message, $exception); + } + + /** + * {@inheritdoc} + */ + public function createDatabasePlatformForVersion($version) + { + if (! preg_match('/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?/', $version, $versionParts)) { + throw DBALException::invalidPlatformVersionSpecified( + $version, + '..' + ); + } + + $majorVersion = $versionParts['major']; + $minorVersion = $versionParts['minor'] ?? 0; + $patchVersion = $versionParts['patch'] ?? 0; + $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion; + + switch (true) { + case version_compare($version, '10.0', '>='): + return new PostgreSQL100Platform(); + case version_compare($version, '9.4', '>='): + return new PostgreSQL94Platform(); + case version_compare($version, '9.2', '>='): + return new PostgreSQL92Platform(); + case version_compare($version, '9.1', '>='): + return new PostgreSQL91Platform(); + default: + return new PostgreSqlPlatform(); + } + } + + /** + * {@inheritdoc} + */ + public function getDatabase(Connection $conn) + { + $params = $conn->getParams(); + + return $params['dbname'] ?? $conn->query('SELECT CURRENT_DATABASE()')->fetchColumn(); + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new PostgreSqlPlatform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(Connection $conn) + { + return new PostgreSqlSchemaManager($conn); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLAnywhereDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLAnywhereDriver.php new file mode 100644 index 0000000..88f26ce --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLAnywhereDriver.php @@ -0,0 +1,127 @@ +getErrorCode()) { + case '-306': + case '-307': + case '-684': + return new Exception\DeadlockException($message, $exception); + case '-210': + case '-1175': + case '-1281': + return new Exception\LockWaitTimeoutException($message, $exception); + case '-100': + case '-103': + case '-832': + return new Exception\ConnectionException($message, $exception); + case '-143': + return new Exception\InvalidFieldNameException($message, $exception); + case '-193': + case '-196': + return new Exception\UniqueConstraintViolationException($message, $exception); + case '-194': + case '-198': + return new Exception\ForeignKeyConstraintViolationException($message, $exception); + case '-144': + return new Exception\NonUniqueFieldNameException($message, $exception); + case '-184': + case '-195': + return new Exception\NotNullConstraintViolationException($message, $exception); + case '-131': + return new Exception\SyntaxErrorException($message, $exception); + case '-110': + return new Exception\TableExistsException($message, $exception); + case '-141': + case '-1041': + return new Exception\TableNotFoundException($message, $exception); + } + + return new Exception\DriverException($message, $exception); + } + + /** + * {@inheritdoc} + */ + public function createDatabasePlatformForVersion($version) + { + if (! preg_match( + '/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?)?/', + $version, + $versionParts + )) { + throw DBALException::invalidPlatformVersionSpecified( + $version, + '...' + ); + } + + $majorVersion = $versionParts['major']; + $minorVersion = $versionParts['minor'] ?? 0; + $patchVersion = $versionParts['patch'] ?? 0; + $buildVersion = $versionParts['build'] ?? 0; + $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion . '.' . $buildVersion; + + switch (true) { + case version_compare($version, '16', '>='): + return new SQLAnywhere16Platform(); + case version_compare($version, '12', '>='): + return new SQLAnywhere12Platform(); + case version_compare($version, '11', '>='): + return new SQLAnywhere11Platform(); + default: + return new SQLAnywherePlatform(); + } + } + + /** + * {@inheritdoc} + */ + public function getDatabase(Connection $conn) + { + $params = $conn->getParams(); + + return $params['dbname'] ?? $conn->query('SELECT DB_NAME()')->fetchColumn(); + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new SQLAnywhere12Platform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(Connection $conn) + { + return new SQLAnywhereSchemaManager($conn); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLServerDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLServerDriver.php new file mode 100644 index 0000000..421d82b --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLServerDriver.php @@ -0,0 +1,81 @@ +\d+)(?:\.(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?)?/', + $version, + $versionParts + )) { + throw DBALException::invalidPlatformVersionSpecified( + $version, + '...' + ); + } + + $majorVersion = $versionParts['major']; + $minorVersion = $versionParts['minor'] ?? 0; + $patchVersion = $versionParts['patch'] ?? 0; + $buildVersion = $versionParts['build'] ?? 0; + $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion . '.' . $buildVersion; + + switch (true) { + case version_compare($version, '11.00.2100', '>='): + return new SQLServer2012Platform(); + case version_compare($version, '10.00.1600', '>='): + return new SQLServer2008Platform(); + case version_compare($version, '9.00.1399', '>='): + return new SQLServer2005Platform(); + default: + return new SQLServerPlatform(); + } + } + + /** + * {@inheritdoc} + */ + public function getDatabase(Connection $conn) + { + $params = $conn->getParams(); + + return $params['dbname'] ?? $conn->query('SELECT DB_NAME()')->fetchColumn(); + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new SQLServer2008Platform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(Connection $conn) + { + return new SQLServerSchemaManager($conn); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php new file mode 100644 index 0000000..582f7ca --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php @@ -0,0 +1,98 @@ +getMessage(), 'database is locked') !== false) { + return new Exception\LockWaitTimeoutException($message, $exception); + } + + if (strpos($exception->getMessage(), 'must be unique') !== false || + strpos($exception->getMessage(), 'is not unique') !== false || + strpos($exception->getMessage(), 'are not unique') !== false || + strpos($exception->getMessage(), 'UNIQUE constraint failed') !== false + ) { + return new Exception\UniqueConstraintViolationException($message, $exception); + } + + if (strpos($exception->getMessage(), 'may not be NULL') !== false || + strpos($exception->getMessage(), 'NOT NULL constraint failed') !== false + ) { + return new Exception\NotNullConstraintViolationException($message, $exception); + } + + if (strpos($exception->getMessage(), 'no such table:') !== false) { + return new Exception\TableNotFoundException($message, $exception); + } + + if (strpos($exception->getMessage(), 'already exists') !== false) { + return new Exception\TableExistsException($message, $exception); + } + + if (strpos($exception->getMessage(), 'has no column named') !== false) { + return new Exception\InvalidFieldNameException($message, $exception); + } + + if (strpos($exception->getMessage(), 'ambiguous column name') !== false) { + return new Exception\NonUniqueFieldNameException($message, $exception); + } + + if (strpos($exception->getMessage(), 'syntax error') !== false) { + return new Exception\SyntaxErrorException($message, $exception); + } + + if (strpos($exception->getMessage(), 'attempt to write a readonly database') !== false) { + return new Exception\ReadOnlyException($message, $exception); + } + + if (strpos($exception->getMessage(), 'unable to open database file') !== false) { + return new Exception\ConnectionException($message, $exception); + } + + return new Exception\DriverException($message, $exception); + } + + /** + * {@inheritdoc} + */ + public function getDatabase(Connection $conn) + { + $params = $conn->getParams(); + + return $params['path'] ?? null; + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new SqlitePlatform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(Connection $conn) + { + return new SqliteSchemaManager($conn); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Connection.php new file mode 100644 index 0000000..1574581 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Connection.php @@ -0,0 +1,93 @@ +constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + } + + /** + * {@inheritdoc} + */ + public function createDatabasePlatformForVersion($version) + { + return $this->getDatabasePlatform(); + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new DrizzlePlatform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new DrizzleSchemaManager($conn); + } + + /** + * {@inheritdoc} + * + * @deprecated + */ + public function getName() + { + return 'drizzle_pdo_mysql'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ExceptionConverterDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ExceptionConverterDriver.php new file mode 100644 index 0000000..9b79e24 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ExceptionConverterDriver.php @@ -0,0 +1,22 @@ +conn = $conn; + } + + /** + * {@inheritdoc} + */ + public function getServerVersion() + { + /** @var stdClass $serverInfo */ + $serverInfo = db2_server_info($this->conn); + + return $serverInfo->DBMS_VER; + } + + /** + * {@inheritdoc} + */ + public function requiresQueryForServerVersion() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function prepare($sql) + { + $stmt = @db2_prepare($this->conn, $sql); + if (! $stmt) { + throw new DB2Exception(db2_stmt_errormsg()); + } + + return new DB2Statement($stmt); + } + + /** + * {@inheritdoc} + */ + public function query() + { + $args = func_get_args(); + $sql = $args[0]; + $stmt = $this->prepare($sql); + $stmt->execute(); + + return $stmt; + } + + /** + * {@inheritdoc} + */ + public function quote($input, $type = ParameterType::STRING) + { + $input = db2_escape_string($input); + + if ($type === ParameterType::INTEGER) { + return $input; + } + + return "'" . $input . "'"; + } + + /** + * {@inheritdoc} + */ + public function exec($statement) + { + $stmt = @db2_exec($this->conn, $statement); + + if ($stmt === false) { + throw new DB2Exception(db2_stmt_errormsg()); + } + + return db2_num_rows($stmt); + } + + /** + * {@inheritdoc} + */ + public function lastInsertId($name = null) + { + return db2_last_insert_id($this->conn); + } + + /** + * {@inheritdoc} + */ + public function beginTransaction() + { + db2_autocommit($this->conn, DB2_AUTOCOMMIT_OFF); + } + + /** + * {@inheritdoc} + */ + public function commit() + { + if (! db2_commit($this->conn)) { + throw new DB2Exception(db2_conn_errormsg($this->conn)); + } + db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON); + } + + /** + * {@inheritdoc} + */ + public function rollBack() + { + if (! db2_rollback($this->conn)) { + throw new DB2Exception(db2_conn_errormsg($this->conn)); + } + db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON); + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + return db2_conn_error($this->conn); + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + return [ + 0 => db2_conn_errormsg($this->conn), + 1 => $this->errorCode(), + ]; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php new file mode 100644 index 0000000..fe79fe6 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php @@ -0,0 +1,49 @@ +stmt = $stmt; + } + + /** + * {@inheritdoc} + */ + public function bindValue($param, $value, $type = ParameterType::STRING) + { + return $this->bindParam($param, $value, $type); + } + + /** + * {@inheritdoc} + */ + public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null) + { + switch ($type) { + case ParameterType::INTEGER: + $this->bind($column, $variable, DB2_PARAM_IN, DB2_LONG); + break; + + case ParameterType::LARGE_OBJECT: + if (isset($this->lobs[$column])) { + [, $handle] = $this->lobs[$column]; + fclose($handle); + } + + $handle = $this->createTemporaryFile(); + $path = stream_get_meta_data($handle)['uri']; + + $this->bind($column, $path, DB2_PARAM_FILE, DB2_BINARY); + + $this->lobs[$column] = [&$variable, $handle]; + break; + + default: + $this->bind($column, $variable, DB2_PARAM_IN, DB2_CHAR); + break; + } + + return true; + } + + /** + * @param int $position Parameter position + * @param mixed $variable + * + * @throws DB2Exception + */ + private function bind($position, &$variable, int $parameterType, int $dataType) : void + { + $this->bindParam[$position] =& $variable; + + if (! db2_bind_param($this->stmt, $position, 'variable', $parameterType, $dataType)) { + throw new DB2Exception(db2_stmt_errormsg()); + } + } + + /** + * {@inheritdoc} + */ + public function closeCursor() + { + $this->bindParam = []; + + if (! db2_free_result($this->stmt)) { + return false; + } + + $this->result = false; + + return true; + } + + /** + * {@inheritdoc} + */ + public function columnCount() + { + return db2_num_fields($this->stmt) ?: 0; + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + return db2_stmt_error(); + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + return [ + db2_stmt_errormsg(), + db2_stmt_error(), + ]; + } + + /** + * {@inheritdoc} + */ + public function execute($params = null) + { + if ($params === null) { + ksort($this->bindParam); + + $params = []; + + foreach ($this->bindParam as $column => $value) { + $params[] = $value; + } + } + + foreach ($this->lobs as [$source, $target]) { + if (is_resource($source)) { + $this->copyStreamToStream($source, $target); + + continue; + } + + $this->writeStringToStream($source, $target); + } + + $retval = db2_execute($this->stmt, $params); + + foreach ($this->lobs as [, $handle]) { + fclose($handle); + } + + $this->lobs = []; + + if ($retval === false) { + throw new DB2Exception(db2_stmt_errormsg()); + } + + $this->result = true; + + return $retval; + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $this->defaultFetchMode = $fetchMode; + $this->defaultFetchClass = $arg2 ?: $this->defaultFetchClass; + $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; + + return true; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + return new StatementIterator($this); + } + + /** + * {@inheritdoc} + */ + public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + { + // do not try fetching from the statement if it's not expected to contain result + // in order to prevent exceptional situation + if (! $this->result) { + return false; + } + + $fetchMode = $fetchMode ?: $this->defaultFetchMode; + switch ($fetchMode) { + case FetchMode::COLUMN: + return $this->fetchColumn(); + + case FetchMode::MIXED: + return db2_fetch_both($this->stmt); + + case FetchMode::ASSOCIATIVE: + return db2_fetch_assoc($this->stmt); + + case FetchMode::CUSTOM_OBJECT: + $className = $this->defaultFetchClass; + $ctorArgs = $this->defaultFetchClassCtorArgs; + + if (func_num_args() >= 2) { + $args = func_get_args(); + $className = $args[1]; + $ctorArgs = $args[2] ?? []; + } + + $result = db2_fetch_object($this->stmt); + + if ($result instanceof stdClass) { + $result = $this->castObject($result, $className, $ctorArgs); + } + + return $result; + + case FetchMode::NUMERIC: + return db2_fetch_array($this->stmt); + + case FetchMode::STANDARD_OBJECT: + return db2_fetch_object($this->stmt); + + default: + throw new DB2Exception('Given Fetch-Style ' . $fetchMode . ' is not supported.'); + } + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + { + $rows = []; + + switch ($fetchMode) { + case FetchMode::CUSTOM_OBJECT: + while (($row = $this->fetch(...func_get_args())) !== false) { + $rows[] = $row; + } + break; + case FetchMode::COLUMN: + while (($row = $this->fetchColumn()) !== false) { + $rows[] = $row; + } + break; + default: + while (($row = $this->fetch($fetchMode)) !== false) { + $rows[] = $row; + } + } + + return $rows; + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + $row = $this->fetch(FetchMode::NUMERIC); + + if ($row === false) { + return false; + } + + return $row[$columnIndex] ?? null; + } + + /** + * {@inheritdoc} + */ + public function rowCount() + { + return @db2_num_rows($this->stmt) ? : 0; + } + + /** + * Casts a stdClass object to the given class name mapping its' properties. + * + * @param stdClass $sourceObject Object to cast from. + * @param string|object $destinationClass Name of the class or class instance to cast to. + * @param mixed[] $ctorArgs Arguments to use for constructing the destination class instance. + * + * @return object + * + * @throws DB2Exception + */ + private function castObject(stdClass $sourceObject, $destinationClass, array $ctorArgs = []) + { + if (! is_string($destinationClass)) { + if (! is_object($destinationClass)) { + throw new DB2Exception(sprintf( + 'Destination class has to be of type string or object, %s given.', + gettype($destinationClass) + )); + } + } else { + $destinationClass = new ReflectionClass($destinationClass); + $destinationClass = $destinationClass->newInstanceArgs($ctorArgs); + } + + $sourceReflection = new ReflectionObject($sourceObject); + $destinationClassReflection = new ReflectionObject($destinationClass); + /** @var ReflectionProperty[] $destinationProperties */ + $destinationProperties = array_change_key_case($destinationClassReflection->getProperties(), CASE_LOWER); + + foreach ($sourceReflection->getProperties() as $sourceProperty) { + $sourceProperty->setAccessible(true); + + $name = $sourceProperty->getName(); + $value = $sourceProperty->getValue($sourceObject); + + // Try to find a case-matching property. + if ($destinationClassReflection->hasProperty($name)) { + $destinationProperty = $destinationClassReflection->getProperty($name); + + $destinationProperty->setAccessible(true); + $destinationProperty->setValue($destinationClass, $value); + + continue; + } + + $name = strtolower($name); + + // Try to find a property without matching case. + // Fallback for the driver returning either all uppercase or all lowercase column names. + if (isset($destinationProperties[$name])) { + $destinationProperty = $destinationProperties[$name]; + + $destinationProperty->setAccessible(true); + $destinationProperty->setValue($destinationClass, $value); + + continue; + } + + $destinationClass->$name = $value; + } + + return $destinationClass; + } + + /** + * @return resource + * + * @throws DB2Exception + */ + private function createTemporaryFile() + { + $handle = @tmpfile(); + + if ($handle === false) { + throw new DB2Exception('Could not create temporary file: ' . error_get_last()['message']); + } + + return $handle; + } + + /** + * @param resource $source + * @param resource $target + * + * @throws DB2Exception + */ + private function copyStreamToStream($source, $target) : void + { + if (@stream_copy_to_stream($source, $target) === false) { + throw new DB2Exception('Could not copy source stream to temporary file: ' . error_get_last()['message']); + } + } + + /** + * @param resource $target + * + * @throws DB2Exception + */ + private function writeStringToStream(string $string, $target) : void + { + if (@fwrite($target, $string) === false) { + throw new DB2Exception('Could not write string to temporary file: ' . error_get_last()['message']); + } + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/Driver.php new file mode 100644 index 0000000..1166e8d --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/Driver.php @@ -0,0 +1,29 @@ +conn = mysqli_init(); + + $this->setSecureConnection($params); + $this->setDriverOptions($driverOptions); + + set_error_handler(static function () { + }); + try { + if (! $this->conn->real_connect($params['host'], $username, $password, $dbname, $port, $socket, $flags)) { + throw new MysqliException($this->conn->connect_error, $this->conn->sqlstate ?? 'HY000', $this->conn->connect_errno); + } + } finally { + restore_error_handler(); + } + + if (! isset($params['charset'])) { + return; + } + + $this->conn->set_charset($params['charset']); + } + + /** + * Retrieves mysqli native resource handle. + * + * Could be used if part of your application is not using DBAL. + * + * @return mysqli + */ + public function getWrappedResourceHandle() + { + return $this->conn; + } + + /** + * {@inheritdoc} + * + * The server version detection includes a special case for MariaDB + * to support '5.5.5-' prefixed versions introduced in Maria 10+ + * + * @link https://jira.mariadb.org/browse/MDEV-4088 + */ + public function getServerVersion() + { + $serverInfos = $this->conn->get_server_info(); + if (stripos($serverInfos, 'mariadb') !== false) { + return $serverInfos; + } + + $majorVersion = floor($this->conn->server_version / 10000); + $minorVersion = floor(($this->conn->server_version - $majorVersion * 10000) / 100); + $patchVersion = floor($this->conn->server_version - $majorVersion * 10000 - $minorVersion * 100); + + return $majorVersion . '.' . $minorVersion . '.' . $patchVersion; + } + + /** + * {@inheritdoc} + */ + public function requiresQueryForServerVersion() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function prepare($prepareString) + { + return new MysqliStatement($this->conn, $prepareString); + } + + /** + * {@inheritdoc} + */ + public function query() + { + $args = func_get_args(); + $sql = $args[0]; + $stmt = $this->prepare($sql); + $stmt->execute(); + + return $stmt; + } + + /** + * {@inheritdoc} + */ + public function quote($input, $type = ParameterType::STRING) + { + return "'" . $this->conn->escape_string($input) . "'"; + } + + /** + * {@inheritdoc} + */ + public function exec($statement) + { + if ($this->conn->query($statement) === false) { + throw new MysqliException($this->conn->error, $this->conn->sqlstate, $this->conn->errno); + } + + return $this->conn->affected_rows; + } + + /** + * {@inheritdoc} + */ + public function lastInsertId($name = null) + { + return $this->conn->insert_id; + } + + /** + * {@inheritdoc} + */ + public function beginTransaction() + { + $this->conn->query('START TRANSACTION'); + + return true; + } + + /** + * {@inheritdoc} + */ + public function commit() + { + return $this->conn->commit(); + } + + /** + * {@inheritdoc}non-PHPdoc) + */ + public function rollBack() + { + return $this->conn->rollback(); + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + return $this->conn->errno; + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + return $this->conn->error; + } + + /** + * Apply the driver options to the connection. + * + * @param mixed[] $driverOptions + * + * @throws MysqliException When one of of the options is not supported. + * @throws MysqliException When applying doesn't work - e.g. due to incorrect value. + */ + private function setDriverOptions(array $driverOptions = []) + { + $supportedDriverOptions = [ + MYSQLI_OPT_CONNECT_TIMEOUT, + MYSQLI_OPT_LOCAL_INFILE, + MYSQLI_INIT_COMMAND, + MYSQLI_READ_DEFAULT_FILE, + MYSQLI_READ_DEFAULT_GROUP, + ]; + + if (defined('MYSQLI_SERVER_PUBLIC_KEY')) { + $supportedDriverOptions[] = MYSQLI_SERVER_PUBLIC_KEY; + } + + $exceptionMsg = "%s option '%s' with value '%s'"; + + foreach ($driverOptions as $option => $value) { + if ($option === static::OPTION_FLAGS) { + continue; + } + + if (! in_array($option, $supportedDriverOptions, true)) { + throw new MysqliException( + sprintf($exceptionMsg, 'Unsupported', $option, $value) + ); + } + + if (@mysqli_options($this->conn, $option, $value)) { + continue; + } + + $msg = sprintf($exceptionMsg, 'Failed to set', $option, $value); + $msg .= sprintf(', error: %s (%d)', mysqli_error($this->conn), mysqli_errno($this->conn)); + + throw new MysqliException( + $msg, + $this->conn->sqlstate, + $this->conn->errno + ); + } + } + + /** + * Pings the server and re-connects when `mysqli.reconnect = 1` + * + * @return bool + */ + public function ping() + { + return $this->conn->ping(); + } + + /** + * Establish a secure connection + * + * @param mixed[] $params + * + * @throws MysqliException + */ + private function setSecureConnection(array $params) + { + if (! isset($params['ssl_key']) && + ! isset($params['ssl_cert']) && + ! isset($params['ssl_ca']) && + ! isset($params['ssl_capath']) && + ! isset($params['ssl_cipher']) + ) { + return; + } + + $this->conn->ssl_set( + $params['ssl_key'] ?? null, + $params['ssl_cert'] ?? null, + $params['ssl_ca'] ?? null, + $params['ssl_capath'] ?? null, + $params['ssl_cipher'] ?? null + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliException.php new file mode 100644 index 0000000..1fa0c90 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliException.php @@ -0,0 +1,12 @@ + 's', + ParameterType::BINARY => 's', + ParameterType::BOOLEAN => 'i', + ParameterType::NULL => 's', + ParameterType::INTEGER => 'i', + ParameterType::LARGE_OBJECT => 'b', + ]; + + /** @var mysqli */ + protected $_conn; + + /** @var mysqli_stmt */ + protected $_stmt; + + /** @var string[]|false|null */ + protected $_columnNames; + + /** @var mixed[] */ + protected $_rowBindedValues = []; + + /** @var mixed[] */ + protected $_bindedValues; + + /** @var string */ + protected $types; + + /** + * Contains ref values for bindValue(). + * + * @var mixed[] + */ + protected $_values = []; + + /** @var int */ + protected $_defaultFetchMode = FetchMode::MIXED; + + /** + * Indicates whether the statement is in the state when fetching results is possible + * + * @var bool + */ + private $result = false; + + /** + * @param string $prepareString + * + * @throws MysqliException + */ + public function __construct(mysqli $conn, $prepareString) + { + $this->_conn = $conn; + + $stmt = $conn->prepare($prepareString); + + if ($stmt === false) { + throw new MysqliException($this->_conn->error, $this->_conn->sqlstate, $this->_conn->errno); + } + + $this->_stmt = $stmt; + + $paramCount = $this->_stmt->param_count; + if (0 >= $paramCount) { + return; + } + + $this->types = str_repeat('s', $paramCount); + $this->_bindedValues = array_fill(1, $paramCount, null); + } + + /** + * {@inheritdoc} + */ + public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null) + { + assert(is_int($column)); + + if (! isset(self::$_paramTypeMap[$type])) { + throw new MysqliException(sprintf("Unknown type: '%s'", $type)); + } + + $this->_bindedValues[$column] =& $variable; + $this->types[$column - 1] = self::$_paramTypeMap[$type]; + + return true; + } + + /** + * {@inheritdoc} + */ + public function bindValue($param, $value, $type = ParameterType::STRING) + { + assert(is_int($param)); + + if (! isset(self::$_paramTypeMap[$type])) { + throw new MysqliException(sprintf("Unknown type: '%s'", $type)); + } + + $this->_values[$param] = $value; + $this->_bindedValues[$param] =& $this->_values[$param]; + $this->types[$param - 1] = self::$_paramTypeMap[$type]; + + return true; + } + + /** + * {@inheritdoc} + */ + public function execute($params = null) + { + if ($this->_bindedValues !== null) { + if ($params !== null) { + if (! $this->bindUntypedValues($params)) { + throw new MysqliException($this->_stmt->error, $this->_stmt->errno); + } + } else { + $this->bindTypedParameters(); + } + } + + if (! $this->_stmt->execute()) { + throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); + } + + if ($this->_columnNames === null) { + $meta = $this->_stmt->result_metadata(); + if ($meta !== false) { + $fields = $meta->fetch_fields(); + assert(is_array($fields)); + + $columnNames = []; + foreach ($fields as $col) { + $columnNames[] = $col->name; + } + + $meta->free(); + + $this->_columnNames = $columnNames; + } else { + $this->_columnNames = false; + } + } + + if ($this->_columnNames !== false) { + // Store result of every execution which has it. Otherwise it will be impossible + // to execute a new statement in case if the previous one has non-fetched rows + // @link http://dev.mysql.com/doc/refman/5.7/en/commands-out-of-sync.html + $this->_stmt->store_result(); + + // Bind row values _after_ storing the result. Otherwise, if mysqli is compiled with libmysql, + // it will have to allocate as much memory as it may be needed for the given column type + // (e.g. for a LONGBLOB field it's 4 gigabytes) + // @link https://bugs.php.net/bug.php?id=51386#1270673122 + // + // Make sure that the values are bound after each execution. Otherwise, if closeCursor() has been + // previously called on the statement, the values are unbound making the statement unusable. + // + // It's also important that row values are bound after _each_ call to store_result(). Otherwise, + // if mysqli is compiled with libmysql, subsequently fetched string values will get truncated + // to the length of the ones fetched during the previous execution. + $this->_rowBindedValues = array_fill(0, count($this->_columnNames), null); + + $refs = []; + foreach ($this->_rowBindedValues as $key => &$value) { + $refs[$key] =& $value; + } + + if (! $this->_stmt->bind_result(...$refs)) { + throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); + } + } + + $this->result = true; + + return true; + } + + /** + * Binds parameters with known types previously bound to the statement + */ + private function bindTypedParameters() + { + $streams = $values = []; + $types = $this->types; + + foreach ($this->_bindedValues as $parameter => $value) { + if (! isset($types[$parameter - 1])) { + $types[$parameter - 1] = static::$_paramTypeMap[ParameterType::STRING]; + } + + if ($types[$parameter - 1] === static::$_paramTypeMap[ParameterType::LARGE_OBJECT]) { + if (is_resource($value)) { + if (get_resource_type($value) !== 'stream') { + throw new InvalidArgumentException('Resources passed with the LARGE_OBJECT parameter type must be stream resources.'); + } + $streams[$parameter] = $value; + $values[$parameter] = null; + continue; + } + + $types[$parameter - 1] = static::$_paramTypeMap[ParameterType::STRING]; + } + + $values[$parameter] = $value; + } + + if (! $this->_stmt->bind_param($types, ...$values)) { + throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); + } + + $this->sendLongData($streams); + } + + /** + * Handle $this->_longData after regular query parameters have been bound + * + * @throws MysqliException + */ + private function sendLongData($streams) + { + foreach ($streams as $paramNr => $stream) { + while (! feof($stream)) { + $chunk = fread($stream, 8192); + + if ($chunk === false) { + throw new MysqliException("Failed reading the stream resource for parameter offset ${paramNr}."); + } + + if (! $this->_stmt->send_long_data($paramNr - 1, $chunk)) { + throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); + } + } + } + } + + /** + * Binds a array of values to bound parameters. + * + * @param mixed[] $values + * + * @return bool + */ + private function bindUntypedValues(array $values) + { + $params = []; + $types = str_repeat('s', count($values)); + + foreach ($values as &$v) { + $params[] =& $v; + } + + return $this->_stmt->bind_param($types, ...$params); + } + + /** + * @return mixed[]|false|null + */ + private function _fetch() + { + $ret = $this->_stmt->fetch(); + + if ($ret === true) { + $values = []; + foreach ($this->_rowBindedValues as $v) { + $values[] = $v; + } + + return $values; + } + + return $ret; + } + + /** + * {@inheritdoc} + */ + public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + { + // do not try fetching from the statement if it's not expected to contain result + // in order to prevent exceptional situation + if (! $this->result) { + return false; + } + + $fetchMode = $fetchMode ?: $this->_defaultFetchMode; + + if ($fetchMode === FetchMode::COLUMN) { + return $this->fetchColumn(); + } + + $values = $this->_fetch(); + + if ($values === null) { + return false; + } + + if ($values === false) { + throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); + } + + if ($fetchMode === FetchMode::NUMERIC) { + return $values; + } + + assert(is_array($this->_columnNames)); + $assoc = array_combine($this->_columnNames, $values); + assert(is_array($assoc)); + + switch ($fetchMode) { + case FetchMode::ASSOCIATIVE: + return $assoc; + + case FetchMode::MIXED: + return $assoc + $values; + + case FetchMode::STANDARD_OBJECT: + return (object) $assoc; + + default: + throw new MysqliException(sprintf("Unknown fetch type '%s'", $fetchMode)); + } + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + { + $fetchMode = $fetchMode ?: $this->_defaultFetchMode; + + $rows = []; + + if ($fetchMode === FetchMode::COLUMN) { + while (($row = $this->fetchColumn()) !== false) { + $rows[] = $row; + } + } else { + while (($row = $this->fetch($fetchMode)) !== false) { + $rows[] = $row; + } + } + + return $rows; + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + $row = $this->fetch(FetchMode::NUMERIC); + + if ($row === false) { + return false; + } + + return $row[$columnIndex] ?? null; + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + return $this->_stmt->errno; + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + return $this->_stmt->error; + } + + /** + * {@inheritdoc} + */ + public function closeCursor() + { + $this->_stmt->free_result(); + $this->result = false; + + return true; + } + + /** + * {@inheritdoc} + */ + public function rowCount() + { + if ($this->_columnNames === false) { + return $this->_stmt->affected_rows; + } + + return $this->_stmt->num_rows; + } + + /** + * {@inheritdoc} + */ + public function columnCount() + { + return $this->_stmt->field_count; + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $this->_defaultFetchMode = $fetchMode; + + return true; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + return new StatementIterator($this); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/Driver.php new file mode 100644 index 0000000..edda32d --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/Driver.php @@ -0,0 +1,54 @@ +_constructDsn($params), + $params['charset'] ?? '', + $params['sessionMode'] ?? OCI_DEFAULT, + $params['persistent'] ?? false + ); + } catch (OCI8Exception $e) { + throw DBALException::driverException($this, $e); + } + } + + /** + * Constructs the Oracle DSN. + * + * @param mixed[] $params + * + * @return string The DSN. + */ + protected function _constructDsn(array $params) + { + return $this->getEasyConnectString($params); + } + + /** + * {@inheritdoc} + * + * @deprecated + */ + public function getName() + { + return 'oci8'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php new file mode 100644 index 0000000..c185793 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php @@ -0,0 +1,241 @@ +dbh = $dbh; + } + + /** + * {@inheritdoc} + * + * @throws UnexpectedValueException If the version string returned by the database server + * does not contain a parsable version number. + */ + public function getServerVersion() + { + $version = oci_server_version($this->dbh); + + if ($version === false) { + throw OCI8Exception::fromErrorInfo(oci_error($this->dbh)); + } + + if (! preg_match('/\s+(\d+\.\d+\.\d+\.\d+\.\d+)\s+/', $version, $matches)) { + throw new UnexpectedValueException( + sprintf( + 'Unexpected database version string "%s". Cannot parse an appropriate version number from it. ' . + 'Please report this database version string to the Doctrine team.', + $version + ) + ); + } + + return $matches[1]; + } + + /** + * {@inheritdoc} + */ + public function requiresQueryForServerVersion() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function prepare($prepareString) + { + return new OCI8Statement($this->dbh, $prepareString, $this); + } + + /** + * {@inheritdoc} + */ + public function query() + { + $args = func_get_args(); + $sql = $args[0]; + //$fetchMode = $args[1]; + $stmt = $this->prepare($sql); + $stmt->execute(); + + return $stmt; + } + + /** + * {@inheritdoc} + */ + public function quote($value, $type = ParameterType::STRING) + { + if (is_int($value) || is_float($value)) { + return $value; + } + $value = str_replace("'", "''", $value); + + return "'" . addcslashes($value, "\000\n\r\\\032") . "'"; + } + + /** + * {@inheritdoc} + */ + public function exec($statement) + { + $stmt = $this->prepare($statement); + $stmt->execute(); + + return $stmt->rowCount(); + } + + /** + * {@inheritdoc} + */ + public function lastInsertId($name = null) + { + if ($name === null) { + return false; + } + + $sql = 'SELECT ' . $name . '.CURRVAL FROM DUAL'; + $stmt = $this->query($sql); + $result = $stmt->fetchColumn(); + + if ($result === false) { + throw new OCI8Exception('lastInsertId failed: Query was executed but no result was returned.'); + } + + return (int) $result; + } + + /** + * Returns the current execution mode. + * + * @return int + */ + public function getExecuteMode() + { + return $this->executeMode; + } + + /** + * {@inheritdoc} + */ + public function beginTransaction() + { + $this->executeMode = OCI_NO_AUTO_COMMIT; + + return true; + } + + /** + * {@inheritdoc} + */ + public function commit() + { + if (! oci_commit($this->dbh)) { + throw OCI8Exception::fromErrorInfo($this->errorInfo()); + } + $this->executeMode = OCI_COMMIT_ON_SUCCESS; + + return true; + } + + /** + * {@inheritdoc} + */ + public function rollBack() + { + if (! oci_rollback($this->dbh)) { + throw OCI8Exception::fromErrorInfo($this->errorInfo()); + } + $this->executeMode = OCI_COMMIT_ON_SUCCESS; + + return true; + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + $error = oci_error($this->dbh); + if ($error !== false) { + $error = $error['code']; + } + + return $error; + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + $error = oci_error($this->dbh); + + if ($error === false) { + return []; + } + + return $error; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php new file mode 100644 index 0000000..af3a9d1 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php @@ -0,0 +1,22 @@ + OCI_BOTH, + FetchMode::ASSOCIATIVE => OCI_ASSOC, + FetchMode::NUMERIC => OCI_NUM, + FetchMode::COLUMN => OCI_NUM, + ]; + + /** @var int */ + protected $_defaultFetchMode = FetchMode::MIXED; + + /** @var string[] */ + protected $_paramMap = []; + + /** + * Holds references to bound parameter values. + * + * This is a new requirement for PHP7's oci8 extension that prevents bound values from being garbage collected. + * + * @var mixed[] + */ + private $boundValues = []; + + /** + * Indicates whether the statement is in the state when fetching results is possible + * + * @var bool + */ + private $result = false; + + /** + * Creates a new OCI8Statement that uses the given connection handle and SQL statement. + * + * @param resource $dbh The connection handle. + * @param string $query The SQL query. + */ + public function __construct($dbh, $query, OCI8Connection $conn) + { + [$query, $paramMap] = self::convertPositionalToNamedPlaceholders($query); + + $stmt = oci_parse($dbh, $query); + assert(is_resource($stmt)); + + $this->_sth = $stmt; + $this->_dbh = $dbh; + $this->_paramMap = $paramMap; + $this->_conn = $conn; + } + + /** + * Converts positional (?) into named placeholders (:param). + * + * 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. + * + * @param string $statement The SQL statement to convert. + * + * @return mixed[] [0] => the statement value (string), [1] => the paramMap value (array). + * + * @throws OCI8Exception + * + * @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. + */ + public static function convertPositionalToNamedPlaceholders($statement) + { + $fragmentOffset = $tokenOffset = 0; + $fragments = $paramMap = []; + $currentLiteralDelimiter = null; + + do { + if (! $currentLiteralDelimiter) { + $result = self::findPlaceholderOrOpeningQuote( + $statement, + $tokenOffset, + $fragmentOffset, + $fragments, + $currentLiteralDelimiter, + $paramMap + ); + } else { + $result = self::findClosingQuote($statement, $tokenOffset, $currentLiteralDelimiter); + } + } while ($result); + + if ($currentLiteralDelimiter) { + throw new OCI8Exception(sprintf( + 'The statement contains non-terminated string literal starting at offset %d', + $tokenOffset - 1 + )); + } + + $fragments[] = substr($statement, $fragmentOffset); + $statement = implode('', $fragments); + + return [$statement, $paramMap]; + } + + /** + * Finds next placeholder or opening quote. + * + * @param string $statement The SQL statement to parse + * @param string $tokenOffset The offset to start searching from + * @param int $fragmentOffset The offset to build the next fragment from + * @param string[] $fragments Fragments of the original statement not containing placeholders + * @param string|null $currentLiteralDelimiter The delimiter of the current string literal + * or NULL if not currently in a literal + * @param array $paramMap Mapping of the original parameter positions to their named replacements + * + * @return bool Whether the token was found + */ + private static function findPlaceholderOrOpeningQuote( + $statement, + &$tokenOffset, + &$fragmentOffset, + &$fragments, + &$currentLiteralDelimiter, + &$paramMap + ) { + $token = self::findToken($statement, $tokenOffset, '/[?\'"]/'); + + if (! $token) { + return false; + } + + if ($token === '?') { + $position = count($paramMap) + 1; + $param = ':param' . $position; + $fragments[] = substr($statement, $fragmentOffset, $tokenOffset - $fragmentOffset); + $fragments[] = $param; + $paramMap[$position] = $param; + $tokenOffset += 1; + $fragmentOffset = $tokenOffset; + + return true; + } + + $currentLiteralDelimiter = $token; + ++$tokenOffset; + + return true; + } + + /** + * Finds closing quote + * + * @param string $statement The SQL statement to parse + * @param string $tokenOffset The offset to start searching from + * @param string $currentLiteralDelimiter The delimiter of the current string literal + * + * @return bool Whether the token was found + */ + private static function findClosingQuote( + $statement, + &$tokenOffset, + &$currentLiteralDelimiter + ) { + $token = self::findToken( + $statement, + $tokenOffset, + '/' . preg_quote($currentLiteralDelimiter, '/') . '/' + ); + + if (! $token) { + return false; + } + + $currentLiteralDelimiter = false; + ++$tokenOffset; + + return true; + } + + /** + * Finds the token described by regex starting from the given offset. Updates the offset with the position + * where the token was found. + * + * @param string $statement The SQL statement to parse + * @param int $offset The offset to start searching from + * @param string $regex The regex containing token pattern + * + * @return string|null Token or NULL if not found + */ + private static function findToken($statement, &$offset, $regex) + { + if (preg_match($regex, $statement, $matches, PREG_OFFSET_CAPTURE, $offset)) { + $offset = $matches[0][1]; + + return $matches[0][0]; + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function bindValue($param, $value, $type = ParameterType::STRING) + { + return $this->bindParam($param, $value, $type, null); + } + + /** + * {@inheritdoc} + */ + public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null) + { + $column = $this->_paramMap[$column]; + + if ($type === ParameterType::LARGE_OBJECT) { + $lob = oci_new_descriptor($this->_dbh, OCI_D_LOB); + + $class = 'OCI-Lob'; + assert($lob instanceof $class); + + $lob->writeTemporary($variable, OCI_TEMP_BLOB); + + $variable =& $lob; + } + + $this->boundValues[$column] =& $variable; + + return oci_bind_by_name( + $this->_sth, + $column, + $variable, + $length ?? -1, + $this->convertParameterType($type) + ); + } + + /** + * Converts DBAL parameter type to oci8 parameter type + */ + private function convertParameterType(int $type) : int + { + switch ($type) { + case ParameterType::BINARY: + return OCI_B_BIN; + + case ParameterType::LARGE_OBJECT: + return OCI_B_BLOB; + + default: + return SQLT_CHR; + } + } + + /** + * {@inheritdoc} + */ + public function closeCursor() + { + // not having the result means there's nothing to close + if (! $this->result) { + return true; + } + + oci_cancel($this->_sth); + + $this->result = false; + + return true; + } + + /** + * {@inheritdoc} + */ + public function columnCount() + { + return oci_num_fields($this->_sth) ?: 0; + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + $error = oci_error($this->_sth); + if ($error !== false) { + $error = $error['code']; + } + + return $error; + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + $error = oci_error($this->_sth); + + if ($error === false) { + return []; + } + + return $error; + } + + /** + * {@inheritdoc} + */ + public function execute($params = null) + { + if ($params) { + $hasZeroIndex = array_key_exists(0, $params); + + foreach ($params as $key => $val) { + if ($hasZeroIndex && is_int($key)) { + $this->bindValue($key + 1, $val); + } else { + $this->bindValue($key, $val); + } + } + } + + $ret = @oci_execute($this->_sth, $this->_conn->getExecuteMode()); + if (! $ret) { + throw OCI8Exception::fromErrorInfo($this->errorInfo()); + } + + $this->result = true; + + return $ret; + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $this->_defaultFetchMode = $fetchMode; + + return true; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + return new StatementIterator($this); + } + + /** + * {@inheritdoc} + */ + public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + { + // do not try fetching from the statement if it's not expected to contain result + // in order to prevent exceptional situation + if (! $this->result) { + return false; + } + + $fetchMode = $fetchMode ?: $this->_defaultFetchMode; + + if ($fetchMode === FetchMode::COLUMN) { + return $this->fetchColumn(); + } + + if ($fetchMode === FetchMode::STANDARD_OBJECT) { + return oci_fetch_object($this->_sth); + } + + if (! isset(self::$fetchModeMap[$fetchMode])) { + throw new InvalidArgumentException('Invalid fetch style: ' . $fetchMode); + } + + return oci_fetch_array( + $this->_sth, + self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | OCI_RETURN_LOBS + ); + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + { + $fetchMode = $fetchMode ?: $this->_defaultFetchMode; + + $result = []; + + if ($fetchMode === FetchMode::STANDARD_OBJECT) { + while ($row = $this->fetch($fetchMode)) { + $result[] = $row; + } + + return $result; + } + + if (! isset(self::$fetchModeMap[$fetchMode])) { + throw new InvalidArgumentException('Invalid fetch style: ' . $fetchMode); + } + + if (self::$fetchModeMap[$fetchMode] === OCI_BOTH) { + while ($row = $this->fetch($fetchMode)) { + $result[] = $row; + } + } else { + $fetchStructure = OCI_FETCHSTATEMENT_BY_ROW; + + if ($fetchMode === FetchMode::COLUMN) { + $fetchStructure = OCI_FETCHSTATEMENT_BY_COLUMN; + } + + // do not try fetching from the statement if it's not expected to contain result + // in order to prevent exceptional situation + if (! $this->result) { + return []; + } + + oci_fetch_all( + $this->_sth, + $result, + 0, + -1, + self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | $fetchStructure | OCI_RETURN_LOBS + ); + + if ($fetchMode === FetchMode::COLUMN) { + $result = $result[0]; + } + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + // do not try fetching from the statement if it's not expected to contain result + // in order to prevent exceptional situation + if (! $this->result) { + return false; + } + + $row = oci_fetch_array($this->_sth, OCI_NUM | OCI_RETURN_NULLS | OCI_RETURN_LOBS); + + if ($row === false) { + return false; + } + + return $row[$columnIndex] ?? null; + } + + /** + * {@inheritdoc} + */ + public function rowCount() + { + return oci_num_rows($this->_sth) ?: 0; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php new file mode 100644 index 0000000..336542e --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php @@ -0,0 +1,115 @@ +setAttribute(PDO::ATTR_STATEMENT_CLASS, [PDOStatement::class, []]); + $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function exec($statement) + { + try { + return parent::exec($statement); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function getServerVersion() + { + return PDO::getAttribute(PDO::ATTR_SERVER_VERSION); + } + + /** + * {@inheritdoc} + */ + public function prepare($prepareString, $driverOptions = []) + { + try { + return parent::prepare($prepareString, $driverOptions); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function query() + { + $args = func_get_args(); + + try { + $stmt = parent::query(...$args); + assert($stmt instanceof \PDOStatement); + + return $stmt; + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function quote($input, $type = ParameterType::STRING) + { + return parent::quote($input, $type); + } + + /** + * {@inheritdoc} + */ + public function lastInsertId($name = null) + { + try { + if ($name === null) { + return parent::lastInsertId(); + } + + return parent::lastInsertId($name); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function requiresQueryForServerVersion() + { + return false; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOException.php new file mode 100644 index 0000000..277d7a6 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOException.php @@ -0,0 +1,52 @@ +getMessage(), 0, $exception); + + $this->code = $exception->getCode(); + $this->errorInfo = $exception->errorInfo; + $this->errorCode = $exception->errorInfo[1] ?? $exception->getCode(); + $this->sqlState = $exception->errorInfo[0] ?? $exception->getCode(); + } + + /** + * {@inheritdoc} + */ + public function getErrorCode() + { + return $this->errorCode; + } + + /** + * {@inheritdoc} + */ + public function getSQLState() + { + return $this->sqlState; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php new file mode 100644 index 0000000..12fb14e --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php @@ -0,0 +1,59 @@ +_constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + } + + /** + * Constructs the IBM PDO DSN. + * + * @param mixed[] $params + * + * @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; + } + + /** + * {@inheritdoc} + * + * @deprecated + */ + public function getName() + { + return 'pdo_ibm'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php new file mode 100644 index 0000000..dcd4ff5 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php @@ -0,0 +1,72 @@ +constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + } catch (PDOException $e) { + throw DBALException::driverException($this, $e); + } + + return $conn; + } + + /** + * Constructs the MySql PDO DSN. + * + * @param mixed[] $params + * + * @return string The DSN. + */ + protected function constructPdoDsn(array $params) + { + $dsn = 'mysql:'; + if (isset($params['host']) && $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'] . ';'; + } + if (isset($params['charset'])) { + $dsn .= 'charset=' . $params['charset'] . ';'; + } + + return $dsn; + } + + /** + * {@inheritdoc} + * + * @deprecated + */ + public function getName() + { + return 'pdo_mysql'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php new file mode 100644 index 0000000..f1239ea --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php @@ -0,0 +1,62 @@ +constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + } catch (PDOException $e) { + throw DBALException::driverException($this, $e); + } + } + + /** + * Constructs the Oracle PDO DSN. + * + * @param mixed[] $params + * + * @return string The DSN. + */ + private function constructPdoDsn(array $params) + { + $dsn = 'oci:dbname=' . $this->getEasyConnectString($params); + + if (isset($params['charset'])) { + $dsn .= ';charset=' . $params['charset']; + } + + return $dsn; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'pdo_oracle'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php new file mode 100644 index 0000000..f25cd5c --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php @@ -0,0 +1,118 @@ +_constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + + if (defined('PDO::PGSQL_ATTR_DISABLE_PREPARES') + && (! isset($driverOptions[PDO::PGSQL_ATTR_DISABLE_PREPARES]) + || $driverOptions[PDO::PGSQL_ATTR_DISABLE_PREPARES] === true + ) + ) { + $pdo->setAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES, true); + } + + /* defining client_encoding via SET NAMES to avoid inconsistent DSN support + * - the 'client_encoding' connection param only works with postgres >= 9.1 + * - passing client_encoding via the 'options' param breaks pgbouncer support + */ + if (isset($params['charset'])) { + $pdo->exec('SET NAMES \'' . $params['charset'] . '\''); + } + + return $pdo; + } catch (PDOException $e) { + throw DBALException::driverException($this, $e); + } + } + + /** + * Constructs the Postgres PDO DSN. + * + * @param mixed[] $params + * + * @return string The DSN. + */ + private function _constructPdoDsn(array $params) + { + $dsn = 'pgsql:'; + + if (isset($params['host']) && $params['host'] !== '') { + $dsn .= 'host=' . $params['host'] . ';'; + } + + if (isset($params['port']) && $params['port'] !== '') { + $dsn .= 'port=' . $params['port'] . ';'; + } + + if (isset($params['dbname'])) { + $dsn .= 'dbname=' . $params['dbname'] . ';'; + } elseif (isset($params['default_dbname'])) { + $dsn .= 'dbname=' . $params['default_dbname'] . ';'; + } else { + // Used for temporary connections to allow operations like dropping the database currently connected to. + // Connecting without an explicit database does not work, therefore "postgres" database is used + // as it is mostly present in every server setup. + $dsn .= 'dbname=postgres;'; + } + + if (isset($params['sslmode'])) { + $dsn .= 'sslmode=' . $params['sslmode'] . ';'; + } + + if (isset($params['sslrootcert'])) { + $dsn .= 'sslrootcert=' . $params['sslrootcert'] . ';'; + } + + if (isset($params['sslcert'])) { + $dsn .= 'sslcert=' . $params['sslcert'] . ';'; + } + + if (isset($params['sslkey'])) { + $dsn .= 'sslkey=' . $params['sslkey'] . ';'; + } + + if (isset($params['sslcrl'])) { + $dsn .= 'sslcrl=' . $params['sslcrl'] . ';'; + } + + if (isset($params['application_name'])) { + $dsn .= 'application_name=' . $params['application_name'] . ';'; + } + + return $dsn; + } + + /** + * {@inheritdoc} + * + * @deprecated + */ + public function getName() + { + return 'pdo_pgsql'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php new file mode 100644 index 0000000..d08c6a2 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php @@ -0,0 +1,83 @@ + ['callback' => [SqlitePlatform::class, 'udfSqrt'], 'numArgs' => 1], + 'mod' => ['callback' => [SqlitePlatform::class, 'udfMod'], 'numArgs' => 2], + 'locate' => ['callback' => [SqlitePlatform::class, 'udfLocate'], 'numArgs' => -1], + ]; + + /** + * {@inheritdoc} + */ + public function connect(array $params, $username = null, $password = null, array $driverOptions = []) + { + if (isset($driverOptions['userDefinedFunctions'])) { + $this->_userDefinedFunctions = array_merge( + $this->_userDefinedFunctions, + $driverOptions['userDefinedFunctions'] + ); + unset($driverOptions['userDefinedFunctions']); + } + + try { + $pdo = new PDOConnection( + $this->_constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + } catch (PDOException $ex) { + throw DBALException::driverException($this, $ex); + } + + foreach ($this->_userDefinedFunctions as $fn => $data) { + $pdo->sqliteCreateFunction($fn, $data['callback'], $data['numArgs']); + } + + return $pdo; + } + + /** + * Constructs the Sqlite PDO DSN. + * + * @param mixed[] $params + * + * @return string The DSN. + */ + protected function _constructPdoDsn(array $params) + { + $dsn = 'sqlite:'; + if (isset($params['path'])) { + $dsn .= $params['path']; + } elseif (isset($params['memory'])) { + $dsn .= ':memory:'; + } + + return $dsn; + } + + /** + * {@inheritdoc} + * + * @deprecated + */ + public function getName() + { + return 'pdo_sqlite'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php new file mode 100644 index 0000000..bd38944 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php @@ -0,0 +1,54 @@ +setAttribute(PDO::ATTR_STATEMENT_CLASS, [Statement::class, []]); + } + + /** + * {@inheritDoc} + */ + public function lastInsertId($name = null) + { + if ($name === null) { + return parent::lastInsertId($name); + } + + $stmt = $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?'); + $stmt->execute([$name]); + + return $stmt->fetchColumn(); + } + + /** + * {@inheritDoc} + */ + public function quote($value, $type = ParameterType::STRING) + { + $val = parent::quote($value, $type); + + // Fix for a driver version terminating all values with null byte + if (strpos($val, "\0") !== false) { + $val = substr($val, 0, -1); + } + + return $val; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php new file mode 100644 index 0000000..6d6c484 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php @@ -0,0 +1,93 @@ + $value) { + if (is_int($option)) { + $pdoOptions[$option] = $value; + } else { + $dsnOptions[$option] = $value; + } + } + + return new Connection( + $this->_constructPdoDsn($params, $dsnOptions), + $username, + $password, + $pdoOptions + ); + } + + /** + * Constructs the Sqlsrv PDO DSN. + * + * @param mixed[] $params + * @param string[] $connectionOptions + * + * @return string The DSN. + */ + private function _constructPdoDsn(array $params, array $connectionOptions) + { + $dsn = 'sqlsrv:server='; + + if (isset($params['host'])) { + $dsn .= $params['host']; + } + + if (isset($params['port']) && ! empty($params['port'])) { + $dsn .= ',' . $params['port']; + } + + if (isset($params['dbname'])) { + $connectionOptions['Database'] = $params['dbname']; + } + + if (isset($params['MultipleActiveResultSets'])) { + $connectionOptions['MultipleActiveResultSets'] = $params['MultipleActiveResultSets'] ? 'true' : 'false'; + } + + return $dsn . $this->getConnectionOptionsDsn($connectionOptions); + } + + /** + * Converts a connection options array to the DSN + * + * @param string[] $connectionOptions + */ + private function getConnectionOptionsDsn(array $connectionOptions) : string + { + $connectionOptionsDsn = ''; + + foreach ($connectionOptions as $paramName => $paramValue) { + $connectionOptionsDsn .= sprintf(';%s=%s', $paramName, $paramValue); + } + + return $connectionOptionsDsn; + } + + /** + * {@inheritdoc} + * + * @deprecated + */ + public function getName() + { + return 'pdo_sqlsrv'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php new file mode 100644 index 0000000..6803bb1 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php @@ -0,0 +1,35 @@ +bindParam($param, $value, $type); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php new file mode 100644 index 0000000..5be4f2c --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php @@ -0,0 +1,228 @@ + PDO::PARAM_NULL, + ParameterType::INTEGER => PDO::PARAM_INT, + ParameterType::STRING => PDO::PARAM_STR, + ParameterType::BINARY => PDO::PARAM_LOB, + ParameterType::LARGE_OBJECT => PDO::PARAM_LOB, + ParameterType::BOOLEAN => PDO::PARAM_BOOL, + ]; + + private const FETCH_MODE_MAP = [ + FetchMode::ASSOCIATIVE => PDO::FETCH_ASSOC, + FetchMode::NUMERIC => PDO::FETCH_NUM, + FetchMode::MIXED => PDO::FETCH_BOTH, + FetchMode::STANDARD_OBJECT => PDO::FETCH_OBJ, + FetchMode::COLUMN => PDO::FETCH_COLUMN, + FetchMode::CUSTOM_OBJECT => PDO::FETCH_CLASS, + ]; + + /** + * Protected constructor. + */ + protected function __construct() + { + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $fetchMode = $this->convertFetchMode($fetchMode); + + // This thin wrapper is necessary to shield against the weird signature + // of PDOStatement::setFetchMode(): even if the second and third + // parameters are optional, PHP will not let us remove it from this + // declaration. + try { + if ($arg2 === null && $arg3 === null) { + return parent::setFetchMode($fetchMode); + } + + if ($arg3 === null) { + return parent::setFetchMode($fetchMode, $arg2); + } + + return parent::setFetchMode($fetchMode, $arg2, $arg3); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function bindValue($param, $value, $type = ParameterType::STRING) + { + $type = $this->convertParamType($type); + + try { + return parent::bindValue($param, $value, $type); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null, $driverOptions = null) + { + $type = $this->convertParamType($type); + + try { + return parent::bindParam($column, $variable, $type, ...array_slice(func_get_args(), 3)); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function closeCursor() + { + try { + return parent::closeCursor(); + } catch (\PDOException $exception) { + // Exceptions not allowed by the interface. + // In case driver implementations do not adhere to the interface, silence exceptions here. + return true; + } + } + + /** + * {@inheritdoc} + */ + public function execute($params = null) + { + try { + return parent::execute($params); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + { + $args = func_get_args(); + + if (isset($args[0])) { + $args[0] = $this->convertFetchMode($args[0]); + } + + try { + return parent::fetch(...$args); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + { + $args = func_get_args(); + + if (isset($args[0])) { + $args[0] = $this->convertFetchMode($args[0]); + } + + if ($fetchMode === null && $fetchArgument === null && $ctorArgs === null) { + $args = []; + } elseif ($fetchArgument === null && $ctorArgs === null) { + $args = [$fetchMode]; + } elseif ($ctorArgs === null) { + $args = [$fetchMode, $fetchArgument]; + } else { + $args = [$fetchMode, $fetchArgument, $ctorArgs]; + } + + try { + $data = parent::fetchAll(...$args); + assert(is_array($data)); + + return $data; + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + try { + return parent::fetchColumn($columnIndex); + } catch (\PDOException $exception) { + throw new PDOException($exception); + } + } + + /** + * Converts DBAL parameter type to PDO parameter type + * + * @param int $type Parameter type + */ + private function convertParamType(int $type) : int + { + if (! isset(self::PARAM_TYPE_MAP[$type])) { + // TODO: next major: throw an exception + @trigger_error(sprintf( + 'Using a PDO parameter type (%d given) is deprecated and will cause an error in Doctrine 3.0', + $type + ), E_USER_DEPRECATED); + + return $type; + } + + return self::PARAM_TYPE_MAP[$type]; + } + + /** + * Converts DBAL fetch mode to PDO fetch mode + * + * @param int $fetchMode Fetch mode + */ + private function convertFetchMode(int $fetchMode) : int + { + if (! isset(self::FETCH_MODE_MAP[$fetchMode])) { + // TODO: next major: throw an exception + @trigger_error(sprintf( + 'Using a PDO fetch mode or their combination (%d given)' . + ' is deprecated and will cause an error in Doctrine 3.0', + $fetchMode + ), E_USER_DEPRECATED); + + return $fetchMode; + } + + return self::FETCH_MODE_MAP[$fetchMode]; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PingableConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PingableConnection.php new file mode 100644 index 0000000..06bfb9a --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PingableConnection.php @@ -0,0 +1,17 @@ +buildDsn( + $params['host'] ?? null, + $params['port'] ?? null, + $params['server'] ?? null, + $params['dbname'] ?? null, + $username, + $password, + $driverOptions + ), + $params['persistent'] ?? false + ); + } catch (SQLAnywhereException $e) { + throw DBALException::driverException($this, $e); + } + } + + /** + * {@inheritdoc} + * + * @deprecated + */ + public function getName() + { + return 'sqlanywhere'; + } + + /** + * Build the connection string for given connection parameters and driver options. + * + * @param string $host Host address to connect to. + * @param int $port Port to use for the connection (default to SQL Anywhere standard port 2638). + * @param string $server Database server name on the host to connect to. + * SQL Anywhere allows multiple database server instances on the same host, + * therefore specifying the server instance name to use is mandatory. + * @param string $dbname Name of the database on the server instance to connect to. + * @param string $username User name to use for connection authentication. + * @param string $password Password to use for connection authentication. + * @param mixed[] $driverOptions Additional parameters to use for the connection. + * + * @return string + */ + private function buildDsn($host, $port, $server, $dbname, $username = null, $password = null, array $driverOptions = []) + { + $host = $host ?: 'localhost'; + $port = $port ?: 2638; + + if (! empty($server)) { + $server = ';ServerName=' . $server; + } + + return 'HOST=' . $host . ':' . $port . + $server . + ';DBN=' . $dbname . + ';UID=' . $username . + ';PWD=' . $password . + ';' . implode( + ';', + array_map(static function ($key, $value) { + return $key . '=' . $value; + }, array_keys($driverOptions), $driverOptions) + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php new file mode 100644 index 0000000..d477820 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php @@ -0,0 +1,215 @@ +connection = $persistent ? @sasql_pconnect($dsn) : @sasql_connect($dsn); + + if (! is_resource($this->connection)) { + throw SQLAnywhereException::fromSQLAnywhereError(); + } + + // Disable PHP warnings on error. + if (! sasql_set_option($this->connection, 'verbose_errors', false)) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + + // Enable auto committing by default. + if (! sasql_set_option($this->connection, 'auto_commit', 'on')) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function beginTransaction() + { + if (! sasql_set_option($this->connection, 'auto_commit', 'off')) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + + return true; + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function commit() + { + if (! sasql_commit($this->connection)) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + + $this->endTransaction(); + + return true; + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + return sasql_errorcode($this->connection); + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + return sasql_error($this->connection); + } + + /** + * {@inheritdoc} + */ + public function exec($statement) + { + if (sasql_real_query($this->connection, $statement) === false) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + + return sasql_affected_rows($this->connection); + } + + /** + * {@inheritdoc} + */ + public function getServerVersion() + { + $version = $this->query("SELECT PROPERTY('ProductVersion')")->fetchColumn(); + + assert(is_string($version)); + + return $version; + } + + /** + * {@inheritdoc} + */ + public function lastInsertId($name = null) + { + if ($name === null) { + return sasql_insert_id($this->connection); + } + + return $this->query('SELECT ' . $name . '.CURRVAL')->fetchColumn(); + } + + /** + * {@inheritdoc} + */ + public function prepare($prepareString) + { + return new SQLAnywhereStatement($this->connection, $prepareString); + } + + /** + * {@inheritdoc} + */ + public function query() + { + $args = func_get_args(); + $stmt = $this->prepare($args[0]); + + $stmt->execute(); + + return $stmt; + } + + /** + * {@inheritdoc} + */ + public function quote($input, $type = ParameterType::STRING) + { + if (is_int($input) || is_float($input)) { + return $input; + } + + return "'" . sasql_escape_string($this->connection, $input) . "'"; + } + + /** + * {@inheritdoc} + */ + public function requiresQueryForServerVersion() + { + return true; + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function rollBack() + { + if (! sasql_rollback($this->connection)) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + + $this->endTransaction(); + + return true; + } + + /** + * Ends transactional mode and enables auto commit again. + * + * @return bool Whether or not ending transactional mode succeeded. + * + * @throws SQLAnywhereException + */ + private function endTransaction() + { + if (! sasql_set_option($this->connection, 'auto_commit', 'on')) { + throw SQLAnywhereException::fromSQLAnywhereError($this->connection); + } + + return true; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereException.php new file mode 100644 index 0000000..0f8bc3e --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereException.php @@ -0,0 +1,71 @@ +conn = $conn; + $this->stmt = sasql_prepare($conn, $sql); + + if (! is_resource($this->stmt)) { + throw SQLAnywhereException::fromSQLAnywhereError($conn); + } + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null) + { + switch ($type) { + case ParameterType::INTEGER: + case ParameterType::BOOLEAN: + $type = 'i'; + break; + + case ParameterType::LARGE_OBJECT: + $type = 'b'; + break; + + case ParameterType::NULL: + case ParameterType::STRING: + case ParameterType::BINARY: + $type = 's'; + break; + + default: + throw new SQLAnywhereException('Unknown type: ' . $type); + } + + $this->boundValues[$column] =& $variable; + + if (! sasql_stmt_bind_param_ex($this->stmt, $column - 1, $variable, $type, $variable === null)) { + throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt); + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function bindValue($param, $value, $type = ParameterType::STRING) + { + return $this->bindParam($param, $value, $type); + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function closeCursor() + { + if (! sasql_stmt_reset($this->stmt)) { + throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt); + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function columnCount() + { + return sasql_stmt_field_count($this->stmt); + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + return sasql_stmt_errno($this->stmt); + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + return sasql_stmt_error($this->stmt); + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function execute($params = null) + { + if (is_array($params)) { + $hasZeroIndex = array_key_exists(0, $params); + + foreach ($params as $key => $val) { + if ($hasZeroIndex && is_int($key)) { + $this->bindValue($key + 1, $val); + } else { + $this->bindValue($key, $val); + } + } + } + + if (! sasql_stmt_execute($this->stmt)) { + throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt); + } + + $this->result = sasql_stmt_result_metadata($this->stmt); + + return true; + } + + /** + * {@inheritdoc} + * + * @throws SQLAnywhereException + */ + public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + { + if (! is_resource($this->result)) { + return false; + } + + $fetchMode = $fetchMode ?: $this->defaultFetchMode; + + switch ($fetchMode) { + case FetchMode::COLUMN: + return $this->fetchColumn(); + + case FetchMode::ASSOCIATIVE: + return sasql_fetch_assoc($this->result); + + case FetchMode::MIXED: + return sasql_fetch_array($this->result, SASQL_BOTH); + + case FetchMode::CUSTOM_OBJECT: + $className = $this->defaultFetchClass; + $ctorArgs = $this->defaultFetchClassCtorArgs; + + if (func_num_args() >= 2) { + $args = func_get_args(); + $className = $args[1]; + $ctorArgs = $args[2] ?? []; + } + + $result = sasql_fetch_object($this->result); + + if ($result instanceof stdClass) { + $result = $this->castObject($result, $className, $ctorArgs); + } + + return $result; + + case FetchMode::NUMERIC: + return sasql_fetch_row($this->result); + + case FetchMode::STANDARD_OBJECT: + return sasql_fetch_object($this->result); + + default: + throw new SQLAnywhereException('Fetch mode is not supported: ' . $fetchMode); + } + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + { + $rows = []; + + switch ($fetchMode) { + case FetchMode::CUSTOM_OBJECT: + while (($row = $this->fetch(...func_get_args())) !== false) { + $rows[] = $row; + } + break; + + case FetchMode::COLUMN: + while (($row = $this->fetchColumn()) !== false) { + $rows[] = $row; + } + break; + + default: + while (($row = $this->fetch($fetchMode)) !== false) { + $rows[] = $row; + } + } + + return $rows; + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + $row = $this->fetch(FetchMode::NUMERIC); + + if ($row === false) { + return false; + } + + return $row[$columnIndex] ?? null; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + return new StatementIterator($this); + } + + /** + * {@inheritdoc} + */ + public function rowCount() + { + return sasql_stmt_affected_rows($this->stmt); + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $this->defaultFetchMode = $fetchMode; + $this->defaultFetchClass = $arg2 ?: $this->defaultFetchClass; + $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; + } + + /** + * Casts a stdClass object to the given class name mapping its' properties. + * + * @param stdClass $sourceObject Object to cast from. + * @param string|object $destinationClass Name of the class or class instance to cast to. + * @param mixed[] $ctorArgs Arguments to use for constructing the destination class instance. + * + * @return object + * + * @throws SQLAnywhereException + */ + private function castObject(stdClass $sourceObject, $destinationClass, array $ctorArgs = []) + { + if (! is_string($destinationClass)) { + if (! is_object($destinationClass)) { + throw new SQLAnywhereException(sprintf( + 'Destination class has to be of type string or object, %s given.', + gettype($destinationClass) + )); + } + } else { + $destinationClass = new ReflectionClass($destinationClass); + $destinationClass = $destinationClass->newInstanceArgs($ctorArgs); + } + + $sourceReflection = new ReflectionObject($sourceObject); + $destinationClassReflection = new ReflectionObject($destinationClass); + + foreach ($sourceReflection->getProperties() as $sourceProperty) { + $sourceProperty->setAccessible(true); + + $name = $sourceProperty->getName(); + $value = $sourceProperty->getValue($sourceObject); + + if ($destinationClassReflection->hasProperty($name)) { + $destinationProperty = $destinationClassReflection->getProperty($name); + + $destinationProperty->setAccessible(true); + $destinationProperty->setValue($destinationClass, $value); + } else { + $destinationClass->$name = $value; + } + } + + return $destinationClass; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php new file mode 100644 index 0000000..848ab5e --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php @@ -0,0 +1,58 @@ +id = $id; + } + + /** + * @return int + */ + public function getId() + { + return $this->id; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php new file mode 100644 index 0000000..35ad913 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php @@ -0,0 +1,197 @@ +conn = $conn; + $this->lastInsertId = new LastInsertId(); + } + + /** + * {@inheritdoc} + */ + public function getServerVersion() + { + $serverInfo = sqlsrv_server_info($this->conn); + + return $serverInfo['SQLServerVersion']; + } + + /** + * {@inheritdoc} + */ + public function requiresQueryForServerVersion() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function prepare($sql) + { + return new SQLSrvStatement($this->conn, $sql, $this->lastInsertId); + } + + /** + * {@inheritDoc} + */ + public function query() + { + $args = func_get_args(); + $sql = $args[0]; + $stmt = $this->prepare($sql); + $stmt->execute(); + + return $stmt; + } + + /** + * {@inheritDoc} + */ + public function quote($value, $type = ParameterType::STRING) + { + if (is_int($value)) { + return $value; + } + + if (is_float($value)) { + return sprintf('%F', $value); + } + + return "'" . str_replace("'", "''", $value) . "'"; + } + + /** + * {@inheritDoc} + */ + public function exec($statement) + { + $stmt = sqlsrv_query($this->conn, $statement); + + if ($stmt === false) { + throw SQLSrvException::fromSqlSrvErrors(); + } + + $rowsAffected = sqlsrv_rows_affected($stmt); + + if ($rowsAffected === false) { + throw SQLSrvException::fromSqlSrvErrors(); + } + + return $rowsAffected; + } + + /** + * {@inheritDoc} + */ + public function lastInsertId($name = null) + { + if ($name !== null) { + $stmt = $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?'); + $stmt->execute([$name]); + } else { + $stmt = $this->query('SELECT @@IDENTITY'); + } + + return $stmt->fetchColumn(); + } + + /** + * {@inheritDoc} + */ + public function beginTransaction() + { + if (! sqlsrv_begin_transaction($this->conn)) { + throw SQLSrvException::fromSqlSrvErrors(); + } + } + + /** + * {@inheritDoc} + */ + public function commit() + { + if (! sqlsrv_commit($this->conn)) { + throw SQLSrvException::fromSqlSrvErrors(); + } + } + + /** + * {@inheritDoc} + */ + public function rollBack() + { + if (! sqlsrv_rollback($this->conn)) { + throw SQLSrvException::fromSqlSrvErrors(); + } + } + + /** + * {@inheritDoc} + */ + public function errorCode() + { + $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); + if ($errors) { + return $errors[0]['code']; + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function errorInfo() + { + return (array) sqlsrv_errors(SQLSRV_ERR_ERRORS); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php new file mode 100644 index 0000000..1c1e8c4 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php @@ -0,0 +1,43 @@ + SQLSRV_FETCH_BOTH, + FetchMode::ASSOCIATIVE => SQLSRV_FETCH_ASSOC, + FetchMode::NUMERIC => SQLSRV_FETCH_NUMERIC, + ]; + + /** + * The name of the default class to instantiate when fetching class instances. + * + * @var string + */ + private $defaultFetchClass = '\stdClass'; + + /** + * The constructor arguments for the default class to instantiate when fetching class instances. + * + * @var mixed[] + */ + private $defaultFetchClassCtorArgs = []; + + /** + * The fetch style. + * + * @var int + */ + private $defaultFetchMode = FetchMode::MIXED; + + /** + * The last insert ID. + * + * @var LastInsertId|null + */ + private $lastInsertId; + + /** + * Indicates whether the statement is in the state when fetching results is possible + * + * @var bool + */ + private $result = false; + + /** + * Append to any INSERT query to retrieve the last insert id. + * + * @deprecated This constant has been deprecated and will be made private in 3.0 + */ + public const LAST_INSERT_ID_SQL = ';SELECT SCOPE_IDENTITY() AS LastInsertId;'; + + /** + * @param resource $conn + * @param string $sql + */ + public function __construct($conn, $sql, ?LastInsertId $lastInsertId = null) + { + $this->conn = $conn; + $this->sql = $sql; + + if (stripos($sql, 'INSERT INTO ') !== 0) { + return; + } + + $this->sql .= self::LAST_INSERT_ID_SQL; + $this->lastInsertId = $lastInsertId; + } + + /** + * {@inheritdoc} + */ + public function bindValue($param, $value, $type = ParameterType::STRING) + { + if (! is_numeric($param)) { + throw new SQLSrvException( + 'sqlsrv does not support named parameters to queries, use question mark (?) placeholders instead.' + ); + } + + $this->variables[$param] = $value; + $this->types[$param] = $type; + } + + /** + * {@inheritdoc} + */ + public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null) + { + if (! is_numeric($column)) { + throw new SQLSrvException('sqlsrv does not support named parameters to queries, use question mark (?) placeholders instead.'); + } + + $this->variables[$column] =& $variable; + $this->types[$column] = $type; + + // unset the statement resource if it exists as the new one will need to be bound to the new variable + $this->stmt = null; + } + + /** + * {@inheritdoc} + */ + public function closeCursor() + { + // not having the result means there's nothing to close + if ($this->stmt === null || ! $this->result) { + return true; + } + + // emulate it by fetching and discarding rows, similarly to what PDO does in this case + // @link http://php.net/manual/en/pdostatement.closecursor.php + // @link https://github.com/php/php-src/blob/php-7.0.11/ext/pdo/pdo_stmt.c#L2075 + // deliberately do not consider multiple result sets, since doctrine/dbal doesn't support them + while (sqlsrv_fetch($this->stmt)) { + } + + $this->result = false; + + return true; + } + + /** + * {@inheritdoc} + */ + public function columnCount() + { + if ($this->stmt === null) { + return 0; + } + + return sqlsrv_num_fields($this->stmt) ?: 0; + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); + if ($errors) { + return $errors[0]['code']; + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + return (array) sqlsrv_errors(SQLSRV_ERR_ERRORS); + } + + /** + * {@inheritdoc} + */ + public function execute($params = null) + { + if ($params) { + $hasZeroIndex = array_key_exists(0, $params); + + foreach ($params as $key => $val) { + if ($hasZeroIndex && is_int($key)) { + $this->bindValue($key + 1, $val); + } else { + $this->bindValue($key, $val); + } + } + } + + if (! $this->stmt) { + $this->stmt = $this->prepare(); + } + + if (! sqlsrv_execute($this->stmt)) { + throw SQLSrvException::fromSqlSrvErrors(); + } + + if ($this->lastInsertId) { + sqlsrv_next_result($this->stmt); + sqlsrv_fetch($this->stmt); + $this->lastInsertId->setId(sqlsrv_get_field($this->stmt, 0)); + } + + $this->result = true; + } + + /** + * Prepares SQL Server statement resource + * + * @return resource + * + * @throws SQLSrvException + */ + private function prepare() + { + $params = []; + + foreach ($this->variables as $column => &$variable) { + switch ($this->types[$column]) { + case ParameterType::LARGE_OBJECT: + $params[$column - 1] = [ + &$variable, + SQLSRV_PARAM_IN, + SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY), + SQLSRV_SQLTYPE_VARBINARY('max'), + ]; + break; + + case ParameterType::BINARY: + $params[$column - 1] = [ + &$variable, + SQLSRV_PARAM_IN, + SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY), + ]; + break; + + default: + $params[$column - 1] =& $variable; + break; + } + } + + $stmt = sqlsrv_prepare($this->conn, $this->sql, $params); + + if (! $stmt) { + throw SQLSrvException::fromSqlSrvErrors(); + } + + return $stmt; + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $this->defaultFetchMode = $fetchMode; + $this->defaultFetchClass = $arg2 ?: $this->defaultFetchClass; + $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; + + return true; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + return new StatementIterator($this); + } + + /** + * {@inheritdoc} + * + * @throws SQLSrvException + */ + public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + { + // do not try fetching from the statement if it's not expected to contain result + // in order to prevent exceptional situation + if ($this->stmt === null || ! $this->result) { + return false; + } + + $args = func_get_args(); + $fetchMode = $fetchMode ?: $this->defaultFetchMode; + + if ($fetchMode === FetchMode::COLUMN) { + return $this->fetchColumn(); + } + + if (isset(self::$fetchMap[$fetchMode])) { + return sqlsrv_fetch_array($this->stmt, self::$fetchMap[$fetchMode]) ?: false; + } + + if (in_array($fetchMode, [FetchMode::STANDARD_OBJECT, FetchMode::CUSTOM_OBJECT], true)) { + $className = $this->defaultFetchClass; + $ctorArgs = $this->defaultFetchClassCtorArgs; + + if (count($args) >= 2) { + $className = $args[1]; + $ctorArgs = $args[2] ?? []; + } + + return sqlsrv_fetch_object($this->stmt, $className, $ctorArgs) ?: false; + } + + throw new SQLSrvException('Fetch mode is not supported!'); + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + { + $rows = []; + + switch ($fetchMode) { + case FetchMode::CUSTOM_OBJECT: + while (($row = $this->fetch(...func_get_args())) !== false) { + $rows[] = $row; + } + break; + + case FetchMode::COLUMN: + while (($row = $this->fetchColumn()) !== false) { + $rows[] = $row; + } + break; + + default: + while (($row = $this->fetch($fetchMode)) !== false) { + $rows[] = $row; + } + } + + return $rows; + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + $row = $this->fetch(FetchMode::NUMERIC); + + if ($row === false) { + return false; + } + + return $row[$columnIndex] ?? null; + } + + /** + * {@inheritdoc} + */ + public function rowCount() + { + if ($this->stmt === null) { + return 0; + } + + return sqlsrv_rows_affected($this->stmt) ?: 0; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ServerInfoAwareConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ServerInfoAwareConnection.php new file mode 100644 index 0000000..c97a60f --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ServerInfoAwareConnection.php @@ -0,0 +1,23 @@ +bindValue(), + * the variable is bound as a reference and will only be evaluated at the time + * that PDOStatement->execute() is called. + * + * As mentioned above, the named parameters are not natively supported by the mysqli driver, use executeQuery(), + * fetchAll(), fetchArray(), fetchColumn(), fetchAssoc() methods to have the named parameter emulated by doctrine. + * + * 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 $column 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 int $type Explicit data type for the parameter using the {@link \Doctrine\DBAL\ParameterType} + * 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. + * @param int|null $length You must specify maxlength when using an OUT bind + * so that PHP allocates enough memory to hold the returned value. + * + * @return bool TRUE on success or FALSE on failure. + */ + public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null); + + /** + * Fetches the SQLSTATE associated with the last operation on the statement handle. + * + * @see Doctrine_Adapter_Interface::errorCode() + * + * @return string|int|bool The error code string. + */ + public function errorCode(); + + /** + * Fetches extended error information associated with the last operation on the statement handle. + * + * @return mixed[] The error info array. + */ + public 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 mixed[]|null $params An array of values with as many elements as there are + * bound parameters in the SQL statement being executed. + * + * @return bool TRUE on success or FALSE on failure. + */ + public function execute($params = null); + + /** + * 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 int The number of rows. + */ + public function rowCount(); +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/StatementIterator.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/StatementIterator.php new file mode 100644 index 0000000..6b3307d --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/StatementIterator.php @@ -0,0 +1,26 @@ +statement = $statement; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + while (($result = $this->statement->fetch()) !== false) { + yield $result; + } + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/DriverManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/DriverManager.php new file mode 100644 index 0000000..6888d73 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/DriverManager.php @@ -0,0 +1,442 @@ + PDOMySQLDriver::class, + 'pdo_sqlite' => PDOSQLiteDriver::class, + 'pdo_pgsql' => PDOPgSQLDriver::class, + 'pdo_oci' => PDOOCIDriver::class, + 'oci8' => OCI8Driver::class, + 'ibm_db2' => DB2Driver::class, + 'pdo_sqlsrv' => PDOSQLSrvDriver::class, + 'mysqli' => MySQLiDriver::class, + 'drizzle_pdo_mysql' => DrizzlePDOMySQLDriver::class, + 'sqlanywhere' => SQLAnywhereDriver::class, + 'sqlsrv' => SQLSrvDriver::class, + ]; + + /** + * List of URL schemes from a database URL and their mappings to driver. + * + * @var string[] + */ + private static $driverSchemeAliases = [ + 'db2' => 'ibm_db2', + 'mssql' => 'pdo_sqlsrv', + 'mysql' => 'pdo_mysql', + 'mysql2' => 'pdo_mysql', // Amazon RDS, for some weird reason + 'postgres' => 'pdo_pgsql', + 'postgresql' => 'pdo_pgsql', + 'pgsql' => 'pdo_pgsql', + 'sqlite' => 'pdo_sqlite', + 'sqlite3' => 'pdo_sqlite', + ]; + + /** + * 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_oci (unstable) + * pdo_sqlsrv + * pdo_sqlsrv + * mysqli + * sqlanywhere + * sqlsrv + * ibm_db2 (unstable) + * drizzle_pdo_mysql + * + * OR 'driverClass' that contains the full class name (with namespace) of the + * driver class to instantiate. + * + * Other (optional) parameters: + * + * user (string): + * The username to use when connecting. + * + * password (string): + * The password to use when connecting. + * + * driverOptions (array): + * Any additional driver-specific options for the driver. These are just passed + * through to the driver. + * + * pdo: + * You can pass an existing PDO instance through this parameter. The PDO + * instance will be wrapped in a Doctrine\DBAL\Connection. + * + * wrapperClass: + * You may specify a custom wrapper class through the 'wrapperClass' + * parameter but this class MUST inherit from Doctrine\DBAL\Connection. + * + * driverClass: + * The driver class to use. + * + * @param mixed[] $params The parameters. + * @param Configuration|null $config The configuration to use. + * @param EventManager|null $eventManager The event manager to use. + * + * @throws DBALException + */ + public static function getConnection( + array $params, + ?Configuration $config = null, + ?EventManager $eventManager = null + ) : Connection { + // create default config and event manager, if not set + if (! $config) { + $config = new Configuration(); + } + if (! $eventManager) { + $eventManager = new EventManager(); + } + + $params = self::parseDatabaseUrl($params); + + // URL support for MasterSlaveConnection + if (isset($params['master'])) { + $params['master'] = self::parseDatabaseUrl($params['master']); + } + + if (isset($params['slaves'])) { + foreach ($params['slaves'] as $key => $slaveParams) { + $params['slaves'][$key] = self::parseDatabaseUrl($slaveParams); + } + } + + // URL support for PoolingShardConnection + if (isset($params['global'])) { + $params['global'] = self::parseDatabaseUrl($params['global']); + } + + if (isset($params['shards'])) { + foreach ($params['shards'] as $key => $shardParams) { + $params['shards'][$key] = self::parseDatabaseUrl($shardParams); + } + } + + // check for existing pdo object + if (isset($params['pdo']) && ! $params['pdo'] instanceof PDO) { + throw DBALException::invalidPdoInstance(); + } + + 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); + } + + $className = $params['driverClass'] ?? self::$_driverMap[$params['driver']]; + + $driver = new $className(); + + $wrapperClass = Connection::class; + if (isset($params['wrapperClass'])) { + if (! is_subclass_of($params['wrapperClass'], $wrapperClass)) { + throw DBALException::invalidWrapperClass($params['wrapperClass']); + } + + $wrapperClass = $params['wrapperClass']; + } + + return new $wrapperClass($params, $driver, $config, $eventManager); + } + + /** + * Returns the list of supported drivers. + * + * @return string[] + */ + public static function getAvailableDrivers() : array + { + return array_keys(self::$_driverMap); + } + + /** + * Checks the list of parameters. + * + * @param mixed[] $params The list of parameters. + * + * @throws DBALException + */ + private static function _checkParams(array $params) : void + { + // check existence 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(Driver::class, class_implements($params['driverClass'], true))) { + throw DBALException::invalidDriverClass($params['driverClass']); + } + } + + /** + * Normalizes the given connection URL path. + * + * @return string The normalized connection URL path + */ + private static function normalizeDatabaseUrlPath(string $urlPath) : string + { + // Trim leading slash from URL path. + return substr($urlPath, 1); + } + + /** + * Extracts parts from a database URL, if present, and returns an + * updated list of parameters. + * + * @param mixed[] $params The list of parameters. + * + * @return mixed[] A modified list of parameters with info from a database + * URL extracted into indidivual parameter parts. + * + * @throws DBALException + */ + private static function parseDatabaseUrl(array $params) : array + { + if (! isset($params['url'])) { + return $params; + } + + // (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid + $url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $params['url']); + assert(is_string($url)); + + $url = parse_url($url); + + if ($url === false) { + throw new DBALException('Malformed parameter "url".'); + } + + $url = array_map('rawurldecode', $url); + + // If we have a connection URL, we have to unset the default PDO instance connection parameter (if any) + // as we cannot merge connection details from the URL into the PDO instance (URL takes precedence). + unset($params['pdo']); + + $params = self::parseDatabaseUrlScheme($url, $params); + + if (isset($url['host'])) { + $params['host'] = $url['host']; + } + if (isset($url['port'])) { + $params['port'] = $url['port']; + } + if (isset($url['user'])) { + $params['user'] = $url['user']; + } + if (isset($url['pass'])) { + $params['password'] = $url['pass']; + } + + $params = self::parseDatabaseUrlPath($url, $params); + $params = self::parseDatabaseUrlQuery($url, $params); + + return $params; + } + + /** + * Parses the given connection URL and resolves the given connection parameters. + * + * Assumes that the connection URL scheme is already parsed and resolved into the given connection parameters + * via {@link parseDatabaseUrlScheme}. + * + * @see parseDatabaseUrlScheme + * + * @param mixed[] $url The URL parts to evaluate. + * @param mixed[] $params The connection parameters to resolve. + * + * @return mixed[] The resolved connection parameters. + */ + private static function parseDatabaseUrlPath(array $url, array $params) : array + { + if (! isset($url['path'])) { + return $params; + } + + $url['path'] = self::normalizeDatabaseUrlPath($url['path']); + + // If we do not have a known DBAL driver, we do not know any connection URL path semantics to evaluate + // and therefore treat the path as regular DBAL connection URL path. + if (! isset($params['driver'])) { + return self::parseRegularDatabaseUrlPath($url, $params); + } + + if (strpos($params['driver'], 'sqlite') !== false) { + return self::parseSqliteDatabaseUrlPath($url, $params); + } + + return self::parseRegularDatabaseUrlPath($url, $params); + } + + /** + * Parses the query part of the given connection URL and resolves the given connection parameters. + * + * @param mixed[] $url The connection URL parts to evaluate. + * @param mixed[] $params The connection parameters to resolve. + * + * @return mixed[] The resolved connection parameters. + */ + private static function parseDatabaseUrlQuery(array $url, array $params) : array + { + if (! isset($url['query'])) { + return $params; + } + + $query = []; + + parse_str($url['query'], $query); // simply ingest query as extra params, e.g. charset or sslmode + + return array_merge($params, $query); // parse_str wipes existing array elements + } + + /** + * Parses the given regular connection URL and resolves the given connection parameters. + * + * Assumes that the "path" URL part is already normalized via {@link normalizeDatabaseUrlPath}. + * + * @see normalizeDatabaseUrlPath + * + * @param mixed[] $url The regular connection URL parts to evaluate. + * @param mixed[] $params The connection parameters to resolve. + * + * @return mixed[] The resolved connection parameters. + */ + private static function parseRegularDatabaseUrlPath(array $url, array $params) : array + { + $params['dbname'] = $url['path']; + + return $params; + } + + /** + * Parses the given SQLite connection URL and resolves the given connection parameters. + * + * Assumes that the "path" URL part is already normalized via {@link normalizeDatabaseUrlPath}. + * + * @see normalizeDatabaseUrlPath + * + * @param mixed[] $url The SQLite connection URL parts to evaluate. + * @param mixed[] $params The connection parameters to resolve. + * + * @return mixed[] The resolved connection parameters. + */ + private static function parseSqliteDatabaseUrlPath(array $url, array $params) : array + { + if ($url['path'] === ':memory:') { + $params['memory'] = true; + + return $params; + } + + $params['path'] = $url['path']; // pdo_sqlite driver uses 'path' instead of 'dbname' key + + return $params; + } + + /** + * Parses the scheme part from given connection URL and resolves the given connection parameters. + * + * @param mixed[] $url The connection URL parts to evaluate. + * @param mixed[] $params The connection parameters to resolve. + * + * @return mixed[] The resolved connection parameters. + * + * @throws DBALException If parsing failed or resolution is not possible. + */ + private static function parseDatabaseUrlScheme(array $url, array $params) : array + { + if (isset($url['scheme'])) { + // The requested driver from the URL scheme takes precedence + // over the default custom driver from the connection parameters (if any). + unset($params['driverClass']); + + // URL schemes must not contain underscores, but dashes are ok + $driver = str_replace('-', '_', $url['scheme']); + assert(is_string($driver)); + + // The requested driver from the URL scheme takes precedence over the + // default driver from the connection parameters. If the driver is + // an alias (e.g. "postgres"), map it to the actual name ("pdo-pgsql"). + // Otherwise, let checkParams decide later if the driver exists. + $params['driver'] = self::$driverSchemeAliases[$driver] ?? $driver; + + return $params; + } + + // If a schemeless connection URL is given, we require a default driver or default custom driver + // as connection parameter. + if (! isset($params['driverClass']) && ! isset($params['driver'])) { + throw DBALException::driverRequired($params['url']); + } + + return $params; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/ConnectionEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/ConnectionEventArgs.php new file mode 100644 index 0000000..5c71992 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/ConnectionEventArgs.php @@ -0,0 +1,61 @@ +connection = $connection; + } + + /** + * @return Connection + */ + public function getConnection() + { + return $this->connection; + } + + /** + * @deprecated Use ConnectionEventArgs::getConnection() and Connection::getDriver() instead. + * + * @return Driver + */ + public function getDriver() + { + return $this->connection->getDriver(); + } + + /** + * @deprecated Use ConnectionEventArgs::getConnection() and Connection::getDatabasePlatform() instead. + * + * @return AbstractPlatform + */ + public function getDatabasePlatform() + { + return $this->connection->getDatabasePlatform(); + } + + /** + * @deprecated Use ConnectionEventArgs::getConnection() and Connection::getSchemaManager() instead. + * + * @return AbstractSchemaManager + */ + public function getSchemaManager() + { + return $this->connection->getSchemaManager(); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php new file mode 100644 index 0000000..9e72290 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php @@ -0,0 +1,58 @@ +charset = $charset; + $this->collation = $collation; + } + + /** + * @return void + */ + public function postConnect(ConnectionEventArgs $args) + { + $collation = $this->collation ? ' COLLATE ' . $this->collation : ''; + $args->getConnection()->executeUpdate('SET NAMES ' . $this->charset . $collation); + } + + /** + * {@inheritdoc} + */ + public function getSubscribedEvents() + { + return [Events::postConnect]; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php new file mode 100644 index 0000000..19f2b3f --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php @@ -0,0 +1,72 @@ + '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', + 'NLS_NUMERIC_CHARACTERS' => '.,', + ]; + + /** + * @param string[] $oracleSessionVars + */ + public function __construct(array $oracleSessionVars = []) + { + $this->_defaultSessionVars = array_merge($this->_defaultSessionVars, $oracleSessionVars); + } + + /** + * @return void + */ + public function postConnect(ConnectionEventArgs $args) + { + if (! count($this->_defaultSessionVars)) { + return; + } + + array_change_key_case($this->_defaultSessionVars, CASE_UPPER); + $vars = []; + foreach ($this->_defaultSessionVars as $option => $value) { + if ($option === 'CURRENT_SCHEMA') { + $vars[] = $option . ' = ' . $value; + } else { + $vars[] = $option . " = '" . $value . "'"; + } + } + $sql = 'ALTER SESSION SET ' . implode(' ', $vars); + $args->getConnection()->executeUpdate($sql); + } + + /** + * {@inheritdoc} + */ + public function getSubscribedEvents() + { + return [Events::postConnect]; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php new file mode 100644 index 0000000..ea63cab --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php @@ -0,0 +1,41 @@ +sql = $sql; + } + + /** + * @return void + */ + public function postConnect(ConnectionEventArgs $args) + { + $conn = $args->getConnection(); + $conn->exec($this->sql); + } + + /** + * {@inheritdoc} + */ + public function getSubscribedEvents() + { + return [Events::postConnect]; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php new file mode 100644 index 0000000..ff86a93 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php @@ -0,0 +1,81 @@ +column = $column; + $this->tableDiff = $tableDiff; + $this->platform = $platform; + } + + /** + * @return Column + */ + public function getColumn() + { + return $this->column; + } + + /** + * @return TableDiff + */ + public function getTableDiff() + { + return $this->tableDiff; + } + + /** + * @return AbstractPlatform + */ + public function getPlatform() + { + return $this->platform; + } + + /** + * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. + * + * @param string|string[] $sql + * + * @return \Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs + */ + public function addSql($sql) + { + $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); + + return $this; + } + + /** + * @return string[] + */ + public function getSql() + { + return $this->sql; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php new file mode 100644 index 0000000..354eb68 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php @@ -0,0 +1,81 @@ +columnDiff = $columnDiff; + $this->tableDiff = $tableDiff; + $this->platform = $platform; + } + + /** + * @return ColumnDiff + */ + public function getColumnDiff() + { + return $this->columnDiff; + } + + /** + * @return TableDiff + */ + public function getTableDiff() + { + return $this->tableDiff; + } + + /** + * @return AbstractPlatform + */ + public function getPlatform() + { + return $this->platform; + } + + /** + * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. + * + * @param string|string[] $sql + * + * @return \Doctrine\DBAL\Event\SchemaAlterTableChangeColumnEventArgs + */ + public function addSql($sql) + { + $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); + + return $this; + } + + /** + * @return string[] + */ + public function getSql() + { + return $this->sql; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php new file mode 100644 index 0000000..b10bc7a --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php @@ -0,0 +1,68 @@ +tableDiff = $tableDiff; + $this->platform = $platform; + } + + /** + * @return TableDiff + */ + public function getTableDiff() + { + return $this->tableDiff; + } + + /** + * @return AbstractPlatform + */ + public function getPlatform() + { + return $this->platform; + } + + /** + * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. + * + * @param string|string[] $sql + * + * @return \Doctrine\DBAL\Event\SchemaAlterTableEventArgs + */ + public function addSql($sql) + { + $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); + + return $this; + } + + /** + * @return string[] + */ + public function getSql() + { + return $this->sql; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php new file mode 100644 index 0000000..6e3d6a7 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php @@ -0,0 +1,81 @@ +column = $column; + $this->tableDiff = $tableDiff; + $this->platform = $platform; + } + + /** + * @return Column + */ + public function getColumn() + { + return $this->column; + } + + /** + * @return TableDiff + */ + public function getTableDiff() + { + return $this->tableDiff; + } + + /** + * @return AbstractPlatform + */ + public function getPlatform() + { + return $this->platform; + } + + /** + * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. + * + * @param string|string[] $sql + * + * @return \Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs + */ + public function addSql($sql) + { + $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); + + return $this; + } + + /** + * @return string[] + */ + public function getSql() + { + return $this->sql; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php new file mode 100644 index 0000000..27e2825 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php @@ -0,0 +1,96 @@ +oldColumnName = $oldColumnName; + $this->column = $column; + $this->tableDiff = $tableDiff; + $this->platform = $platform; + } + + /** + * @return string + */ + public function getOldColumnName() + { + return $this->oldColumnName; + } + + /** + * @return Column + */ + public function getColumn() + { + return $this->column; + } + + /** + * @return TableDiff + */ + public function getTableDiff() + { + return $this->tableDiff; + } + + /** + * @return AbstractPlatform + */ + public function getPlatform() + { + return $this->platform; + } + + /** + * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. + * + * @param string|string[] $sql + * + * @return \Doctrine\DBAL\Event\SchemaAlterTableRenameColumnEventArgs + */ + public function addSql($sql) + { + $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); + + return $this; + } + + /** + * @return string[] + */ + public function getSql() + { + return $this->sql; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php new file mode 100644 index 0000000..80d9abe --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php @@ -0,0 +1,108 @@ +tableColumn = $tableColumn; + $this->table = $table; + $this->database = $database; + $this->connection = $connection; + } + + /** + * Allows to clear the column which means the column will be excluded from + * tables column list. + * + * @return \Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs + */ + public function setColumn(?Column $column = null) + { + $this->column = $column; + + return $this; + } + + /** + * @return Column|null + */ + public function getColumn() + { + return $this->column; + } + + /** + * @return mixed[] + */ + public function getTableColumn() + { + return $this->tableColumn; + } + + /** + * @return string + */ + public function getTable() + { + return $this->table; + } + + /** + * @return string + */ + public function getDatabase() + { + return $this->database; + } + + /** + * @return Connection + */ + public function getConnection() + { + return $this->connection; + } + + /** + * @deprecated Use SchemaColumnDefinitionEventArgs::getConnection() and Connection::getDatabasePlatform() instead. + * + * @return AbstractPlatform + */ + public function getDatabasePlatform() + { + return $this->connection->getDatabasePlatform(); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php new file mode 100644 index 0000000..6d78aae --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php @@ -0,0 +1,81 @@ +column = $column; + $this->table = $table; + $this->platform = $platform; + } + + /** + * @return Column + */ + public function getColumn() + { + return $this->column; + } + + /** + * @return Table + */ + public function getTable() + { + return $this->table; + } + + /** + * @return AbstractPlatform + */ + public function getPlatform() + { + return $this->platform; + } + + /** + * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. + * + * @param string|string[] $sql + * + * @return \Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs + */ + public function addSql($sql) + { + $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); + + return $this; + } + + /** + * @return string[] + */ + public function getSql() + { + return $this->sql; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php new file mode 100644 index 0000000..927a4e4 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php @@ -0,0 +1,96 @@ +table = $table; + $this->columns = $columns; + $this->options = $options; + $this->platform = $platform; + } + + /** + * @return Table + */ + public function getTable() + { + return $this->table; + } + + /** + * @return mixed[][] + */ + public function getColumns() + { + return $this->columns; + } + + /** + * @return mixed[] + */ + public function getOptions() + { + return $this->options; + } + + /** + * @return AbstractPlatform + */ + public function getPlatform() + { + return $this->platform; + } + + /** + * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. + * + * @param string|string[] $sql + * + * @return \Doctrine\DBAL\Event\SchemaCreateTableEventArgs + */ + public function addSql($sql) + { + $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); + + return $this; + } + + /** + * @return string[] + */ + public function getSql() + { + return $this->sql; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php new file mode 100644 index 0000000..3870497 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php @@ -0,0 +1,69 @@ +table = $table; + $this->platform = $platform; + } + + /** + * @return string|Table + */ + public function getTable() + { + return $this->table; + } + + /** + * @return AbstractPlatform + */ + public function getPlatform() + { + return $this->platform; + } + + /** + * @param string $sql + * + * @return \Doctrine\DBAL\Event\SchemaDropTableEventArgs + */ + public function setSql($sql) + { + $this->sql = $sql; + + return $this; + } + + /** + * @return string|null + */ + public function getSql() + { + return $this->sql; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaEventArgs.php new file mode 100644 index 0000000..0db0689 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaEventArgs.php @@ -0,0 +1,32 @@ +preventDefault = true; + + return $this; + } + + /** + * @return bool + */ + public function isDefaultPrevented() + { + return $this->preventDefault; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php new file mode 100644 index 0000000..317f352 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php @@ -0,0 +1,92 @@ +tableIndex = $tableIndex; + $this->table = $table; + $this->connection = $connection; + } + + /** + * Allows to clear the index which means the index will be excluded from tables index list. + * + * @return SchemaIndexDefinitionEventArgs + */ + public function setIndex(?Index $index = null) + { + $this->index = $index; + + return $this; + } + + /** + * @return Index|null + */ + public function getIndex() + { + return $this->index; + } + + /** + * @return mixed[] + */ + public function getTableIndex() + { + return $this->tableIndex; + } + + /** + * @return string + */ + public function getTable() + { + return $this->table; + } + + /** + * @return Connection + */ + public function getConnection() + { + return $this->connection; + } + + /** + * @return AbstractPlatform + */ + public function getDatabasePlatform() + { + return $this->connection->getDatabasePlatform(); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Events.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Events.php new file mode 100644 index 0000000..5398d0f --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Events.php @@ -0,0 +1,31 @@ +driverException = $driverException; + } + + /** + * Returns the driver specific error code if given. + * + * Returns null if no error code was given by the driver. + * + * @return int|string|null + */ + public function getErrorCode() + { + return $this->driverException->getErrorCode(); + } + + /** + * Returns the SQLSTATE the driver was in at the time the error occurred, if given. + * + * Returns null if no SQLSTATE was given by the driver. + * + * @return string|null + */ + public function getSQLState() + { + return $this->driverException->getSQLState(); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ForeignKeyConstraintViolationException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ForeignKeyConstraintViolationException.php new file mode 100644 index 0000000..48d736f --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ForeignKeyConstraintViolationException.php @@ -0,0 +1,10 @@ +getParams(); + if ($params['driver'] === 'pdo_sqlite') { + throw new DBALException('Cannot use TableGenerator with SQLite.'); + } + $this->conn = DriverManager::getConnection($params, $conn->getConfiguration(), $conn->getEventManager()); + $this->generatorTableName = $generatorTableName; + } + + /** + * Generates the next unused value for the given sequence name. + * + * @param string $sequenceName + * + * @return int + * + * @throws DBALException + */ + public function nextValue($sequenceName) + { + if (isset($this->sequences[$sequenceName])) { + $value = $this->sequences[$sequenceName]['value']; + $this->sequences[$sequenceName]['value']++; + if ($this->sequences[$sequenceName]['value'] >= $this->sequences[$sequenceName]['max']) { + unset($this->sequences[$sequenceName]); + } + + return $value; + } + + $this->conn->beginTransaction(); + + try { + $platform = $this->conn->getDatabasePlatform(); + $sql = 'SELECT sequence_value, sequence_increment_by' + . ' FROM ' . $platform->appendLockHint($this->generatorTableName, LockMode::PESSIMISTIC_WRITE) + . ' WHERE sequence_name = ? ' . $platform->getWriteLockSQL(); + $stmt = $this->conn->executeQuery($sql, [$sequenceName]); + $row = $stmt->fetch(FetchMode::ASSOCIATIVE); + + if ($row !== false) { + $row = array_change_key_case($row, CASE_LOWER); + + $value = $row['sequence_value']; + $value++; + + if ($row['sequence_increment_by'] > 1) { + $this->sequences[$sequenceName] = [ + 'value' => $value, + 'max' => $row['sequence_value'] + $row['sequence_increment_by'], + ]; + } + + $sql = 'UPDATE ' . $this->generatorTableName . ' ' . + 'SET sequence_value = sequence_value + sequence_increment_by ' . + 'WHERE sequence_name = ? AND sequence_value = ?'; + $rows = $this->conn->executeUpdate($sql, [$sequenceName, $row['sequence_value']]); + + if ($rows !== 1) { + throw new DBALException('Race-condition detected while updating sequence. Aborting generation'); + } + } else { + $this->conn->insert( + $this->generatorTableName, + ['sequence_name' => $sequenceName, 'sequence_value' => 1, 'sequence_increment_by' => 1] + ); + $value = 1; + } + + $this->conn->commit(); + } catch (Throwable $e) { + $this->conn->rollBack(); + throw new DBALException('Error occurred while generating ID with TableGenerator, aborted generation: ' . $e->getMessage(), 0, $e); + } + + return $value; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php new file mode 100644 index 0000000..3ec22f3 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php @@ -0,0 +1,71 @@ +generatorTableName = $generatorTableName; + } + + /** + * {@inheritdoc} + */ + public function acceptSchema(Schema $schema) + { + $table = $schema->createTable($this->generatorTableName); + $table->addColumn('sequence_name', 'string'); + $table->addColumn('sequence_value', 'integer', ['default' => 1]); + $table->addColumn('sequence_increment_by', 'integer', ['default' => 1]); + } + + /** + * {@inheritdoc} + */ + public function acceptTable(Table $table) + { + } + + /** + * {@inheritdoc} + */ + public function acceptColumn(Table $table, Column $column) + { + } + + /** + * {@inheritdoc} + */ + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) + { + } + + /** + * {@inheritdoc} + */ + public function acceptIndex(Table $table, Index $index) + { + } + + /** + * {@inheritdoc} + */ + public function acceptSequence(Sequence $sequence) + { + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/LockMode.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/LockMode.php new file mode 100644 index 0000000..14e8143 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/LockMode.php @@ -0,0 +1,21 @@ +enabled) { + return; + } + + $this->start = microtime(true); + $this->queries[++$this->currentQuery] = ['sql' => $sql, 'params' => $params, 'types' => $types, 'executionMS' => 0]; + } + + /** + * {@inheritdoc} + */ + public function stopQuery() + { + if (! $this->enabled) { + return; + } + + $this->queries[$this->currentQuery]['executionMS'] = microtime(true) - $this->start; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php new file mode 100644 index 0000000..657abb4 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php @@ -0,0 +1,37 @@ +loggers = $loggers; + } + + /** + * Adds a logger in the chain. + * + * @deprecated Inject list of loggers via constructor instead + * + * @return void + */ + public function addLogger(SQLLogger $logger) + { + $this->loggers[] = $logger; + } + + /** + * {@inheritdoc} + */ + public function startQuery($sql, ?array $params = null, ?array $types = null) + { + foreach ($this->loggers as $logger) { + $logger->startQuery($sql, $params, $types); + } + } + + /** + * {@inheritdoc} + */ + public function stopQuery() + { + foreach ($this->loggers as $logger) { + $logger->stopQuery(); + } + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/SQLLogger.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/SQLLogger.php new file mode 100644 index 0000000..2e94611 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/SQLLogger.php @@ -0,0 +1,27 @@ +_eventManager = $eventManager; + } + + /** + * Gets the EventManager used by the Platform. + * + * @return EventManager + */ + public function getEventManager() + { + return $this->_eventManager; + } + + /** + * Returns the SQL snippet that declares a boolean column. + * + * @param mixed[] $columnDef + * + * @return string + */ + abstract public function getBooleanTypeDeclarationSQL(array $columnDef); + + /** + * Returns the SQL snippet that declares a 4 byte integer column. + * + * @param mixed[] $columnDef + * + * @return string + */ + abstract public function getIntegerTypeDeclarationSQL(array $columnDef); + + /** + * Returns the SQL snippet that declares an 8 byte integer column. + * + * @param mixed[] $columnDef + * + * @return string + */ + abstract public function getBigIntTypeDeclarationSQL(array $columnDef); + + /** + * Returns the SQL snippet that declares a 2 byte integer column. + * + * @param mixed[] $columnDef + * + * @return string + */ + abstract public function getSmallIntTypeDeclarationSQL(array $columnDef); + + /** + * Returns the SQL snippet that declares common properties of an integer column. + * + * @param mixed[] $columnDef + * + * @return string + */ + abstract protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef); + + /** + * Lazy load Doctrine Type Mappings. + * + * @return void + */ + abstract protected function initializeDoctrineTypeMappings(); + + /** + * Initializes Doctrine Type Mappings with the platform defaults + * and with all additional type mappings. + * + * @return void + */ + private function initializeAllDoctrineTypeMappings() + { + $this->initializeDoctrineTypeMappings(); + + foreach (Type::getTypesMap() as $typeName => $className) { + foreach (Type::getType($typeName)->getMappedDatabaseTypes($this) as $dbType) { + $this->doctrineTypeMapping[$dbType] = $typeName; + } + } + } + + /** + * Returns the SQL snippet used to declare a VARCHAR column type. + * + * @param mixed[] $field + * + * @return string + */ + public function getVarcharTypeDeclarationSQL(array $field) + { + if (! isset($field['length'])) { + $field['length'] = $this->getVarcharDefaultLength(); + } + + $fixed = $field['fixed'] ?? false; + + $maxLength = $fixed + ? $this->getCharMaxLength() + : $this->getVarcharMaxLength(); + + if ($field['length'] > $maxLength) { + return $this->getClobTypeDeclarationSQL($field); + } + + return $this->getVarcharTypeDeclarationSQLSnippet($field['length'], $fixed); + } + + /** + * Returns the SQL snippet used to declare a BINARY/VARBINARY column type. + * + * @param mixed[] $field The column definition. + * + * @return string + */ + public function getBinaryTypeDeclarationSQL(array $field) + { + if (! isset($field['length'])) { + $field['length'] = $this->getBinaryDefaultLength(); + } + + $fixed = $field['fixed'] ?? false; + + $maxLength = $this->getBinaryMaxLength(); + + if ($field['length'] > $maxLength) { + if ($maxLength > 0) { + @trigger_error(sprintf( + 'Binary field length %d is greater than supported by the platform (%d). Reduce the field length or use a BLOB field instead.', + $field['length'], + $maxLength + ), E_USER_DEPRECATED); + } + + return $this->getBlobTypeDeclarationSQL($field); + } + + return $this->getBinaryTypeDeclarationSQLSnippet($field['length'], $fixed); + } + + /** + * Returns the SQL snippet to declare a GUID/UUID field. + * + * By default this maps directly to a CHAR(36) and only maps to more + * special datatypes when the underlying databases support this datatype. + * + * @param mixed[] $field + * + * @return string + */ + public function getGuidTypeDeclarationSQL(array $field) + { + $field['length'] = 36; + $field['fixed'] = true; + + return $this->getVarcharTypeDeclarationSQL($field); + } + + /** + * Returns the SQL snippet to declare a JSON field. + * + * By default this maps directly to a CLOB and only maps to more + * special datatypes when the underlying databases support this datatype. + * + * @param mixed[] $field + * + * @return string + */ + public function getJsonTypeDeclarationSQL(array $field) + { + return $this->getClobTypeDeclarationSQL($field); + } + + /** + * @param int $length + * @param bool $fixed + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + throw DBALException::notSupported('VARCHARs not supported by Platform.'); + } + + /** + * Returns the SQL snippet used to declare a BINARY/VARBINARY column type. + * + * @param int $length The length of the column. + * @param bool $fixed Whether the column length is fixed. + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + throw DBALException::notSupported('BINARY/VARBINARY column types are not supported by this platform.'); + } + + /** + * Returns the SQL snippet used to declare a CLOB column type. + * + * @param mixed[] $field + * + * @return string + */ + abstract public function getClobTypeDeclarationSQL(array $field); + + /** + * Returns the SQL Snippet used to declare a BLOB column type. + * + * @param mixed[] $field + * + * @return string + */ + abstract public function getBlobTypeDeclarationSQL(array $field); + + /** + * Gets the name of the platform. + * + * @return string + */ + abstract public function getName(); + + /** + * Registers a doctrine type to be used in conjunction with a column type of this platform. + * + * @param string $dbType + * @param string $doctrineType + * + * @throws DBALException If the type is not found. + */ + public function registerDoctrineTypeMapping($dbType, $doctrineType) + { + if ($this->doctrineTypeMapping === null) { + $this->initializeAllDoctrineTypeMappings(); + } + + if (! Types\Type::hasType($doctrineType)) { + throw DBALException::typeNotFound($doctrineType); + } + + $dbType = strtolower($dbType); + $this->doctrineTypeMapping[$dbType] = $doctrineType; + + $doctrineType = Type::getType($doctrineType); + + if (! $doctrineType->requiresSQLCommentHint($this)) { + return; + } + + $this->markDoctrineTypeCommented($doctrineType); + } + + /** + * Gets the Doctrine type that is mapped for the given database column type. + * + * @param string $dbType + * + * @return string + * + * @throws DBALException + */ + public function getDoctrineTypeMapping($dbType) + { + if ($this->doctrineTypeMapping === null) { + $this->initializeAllDoctrineTypeMappings(); + } + + $dbType = strtolower($dbType); + + if (! isset($this->doctrineTypeMapping[$dbType])) { + throw new DBALException('Unknown database type ' . $dbType . ' requested, ' . static::class . ' may not support it.'); + } + + return $this->doctrineTypeMapping[$dbType]; + } + + /** + * Checks if a database type is currently supported by this platform. + * + * @param string $dbType + * + * @return bool + */ + public function hasDoctrineTypeMappingFor($dbType) + { + if ($this->doctrineTypeMapping === null) { + $this->initializeAllDoctrineTypeMappings(); + } + + $dbType = strtolower($dbType); + + return isset($this->doctrineTypeMapping[$dbType]); + } + + /** + * Initializes the Doctrine Type comments instance variable for in_array() checks. + * + * @return void + */ + protected function initializeCommentedDoctrineTypes() + { + $this->doctrineTypeComments = []; + + foreach (Type::getTypesMap() as $typeName => $className) { + $type = Type::getType($typeName); + + if (! $type->requiresSQLCommentHint($this)) { + continue; + } + + $this->doctrineTypeComments[] = $typeName; + } + } + + /** + * Is it necessary for the platform to add a parsable type comment to allow reverse engineering the given type? + * + * @return bool + */ + public function isCommentedDoctrineType(Type $doctrineType) + { + if ($this->doctrineTypeComments === null) { + $this->initializeCommentedDoctrineTypes(); + } + + assert(is_array($this->doctrineTypeComments)); + + return in_array($doctrineType->getName(), $this->doctrineTypeComments); + } + + /** + * Marks this type as to be commented in ALTER TABLE and CREATE TABLE statements. + * + * @param string|Type $doctrineType + * + * @return void + */ + public function markDoctrineTypeCommented($doctrineType) + { + if ($this->doctrineTypeComments === null) { + $this->initializeCommentedDoctrineTypes(); + } + + assert(is_array($this->doctrineTypeComments)); + + $this->doctrineTypeComments[] = $doctrineType instanceof Type ? $doctrineType->getName() : $doctrineType; + } + + /** + * Gets the comment to append to a column comment that helps parsing this type in reverse engineering. + * + * @return string + */ + public function getDoctrineTypeComment(Type $doctrineType) + { + return '(DC2Type:' . $doctrineType->getName() . ')'; + } + + /** + * Gets the comment of a passed column modified by potential doctrine type comment hints. + * + * @return string|null + */ + protected function getColumnComment(Column $column) + { + $comment = $column->getComment(); + + if ($this->isCommentedDoctrineType($column->getType())) { + $comment .= $this->getDoctrineTypeComment($column->getType()); + } + + return $comment; + } + + /** + * 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 char field. + */ + public function getCharMaxLength() : int + { + return $this->getVarcharMaxLength(); + } + + /** + * Gets the maximum length of a varchar field. + * + * @return int + */ + public function getVarcharMaxLength() + { + return 4000; + } + + /** + * Gets the default length of a varchar field. + * + * @return int + */ + public function getVarcharDefaultLength() + { + return 255; + } + + /** + * Gets the maximum length of a binary field. + * + * @return int + */ + public function getBinaryMaxLength() + { + return 4000; + } + + /** + * Gets the default length of a binary field. + * + * @return int + */ + public function getBinaryDefaultLength() + { + return 255; + } + + /** + * Gets all SQL wildcard characters of the platform. + * + * @return string[] + */ + public function getWildcards() + { + return ['%', '_']; + } + + /** + * Returns the regular expression operator. + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getRegexpExpression() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the global unique identifier expression. + * + * @deprecated Use application-generated UUIDs instead + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getGuidExpression() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the SQL snippet to get 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 SQL snippet to get 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|int $column The column to use. + * + * @return string Generated SQL including a COUNT aggregate function. + */ + public function getCountExpression($column) + { + return 'COUNT(' . $column . ')'; + } + + /** + * Returns the SQL snippet to get 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 SQL snippet to get the lowest value of a column. + * + * @param string $column The column to use. + * + * @return string Generated SQL including a MIN aggregate function. + */ + public function getMinExpression($column) + { + return 'MIN(' . $column . ')'; + } + + /** + * Returns the SQL snippet to get the total sum of a column. + * + * @param string $column The column to use. + * + * @return string Generated SQL including a SUM aggregate function. + */ + public function getSumExpression($column) + { + return 'SUM(' . $column . ')'; + } + + // scalar functions + + /** + * Returns the SQL snippet to get the md5 sum of a field. + * + * Note: Not SQL92, but common functionality. + * + * @param string $column + * + * @return string + */ + public function getMd5Expression($column) + { + return 'MD5(' . $column . ')'; + } + + /** + * Returns the SQL snippet to get the length of a text field. + * + * @param string $column + * + * @return string + */ + public function getLengthExpression($column) + { + return 'LENGTH(' . $column . ')'; + } + + /** + * Returns the SQL snippet to get the squared value of a column. + * + * @param string $column The column to use. + * + * @return string Generated SQL including an SQRT aggregate function. + */ + public function getSqrtExpression($column) + { + return 'SQRT(' . $column . ')'; + } + + /** + * Returns the SQL snippet to round a numeric field to the number of decimals specified. + * + * @param string $column + * @param int $decimals + * + * @return string + */ + public function getRoundExpression($column, $decimals = 0) + { + return 'ROUND(' . $column . ', ' . $decimals . ')'; + } + + /** + * Returns the SQL snippet to get 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 . ')'; + } + + /** + * Returns the SQL snippet to trim a string. + * + * @param string $str The expression to apply the trim to. + * @param int $mode The position of the trim (leading/trailing/both). + * @param string|bool $char The char to trim, has to be quoted already. Defaults to space. + * + * @return string + */ + public function getTrimExpression($str, $mode = TrimMode::UNSPECIFIED, $char = false) + { + $expression = ''; + + switch ($mode) { + case TrimMode::LEADING: + $expression = 'LEADING '; + break; + + case TrimMode::TRAILING: + $expression = 'TRAILING '; + break; + + case TrimMode::BOTH: + $expression = 'BOTH '; + break; + } + + if ($char !== false) { + $expression .= $char . ' '; + } + + if ($mode || $char !== false) { + $expression .= 'FROM '; + } + + return 'TRIM(' . $expression . $str . ')'; + } + + /** + * Returns the SQL snippet to trim trailing space characters from the expression. + * + * @param string $str Literal string or column name. + * + * @return string + */ + public function getRtrimExpression($str) + { + return 'RTRIM(' . $str . ')'; + } + + /** + * Returns the SQL snippet to trim leading space characters from the expression. + * + * @param string $str Literal string or column name. + * + * @return string + */ + public function getLtrimExpression($str) + { + return 'LTRIM(' . $str . ')'; + } + + /** + * Returns the SQL snippet to change all characters from the expression 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 . ')'; + } + + /** + * Returns the SQL snippet to change all characters from the expression 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 SQL snippet to get the position of the first occurrence of substring $substr in string $str. + * + * @param string $str Literal string. + * @param string $substr Literal string to find. + * @param int|false $startPos Position to start at, beginning of string by default. + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the SQL snippet to get the current system date. + * + * @return string + */ + public function getNowExpression() + { + return 'NOW()'; + } + + /** + * Returns a SQL snippet 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 int $from Where to start the substring portion. + * @param int|null $length The substring portion length. + * + * @return string + */ + public function getSubstringExpression($value, $from, $length = null) + { + if ($length === null) { + return 'SUBSTRING(' . $value . ' FROM ' . $from . ')'; + } + + return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $length . ')'; + } + + /** + * Returns a SQL snippet to concatenate the given expressions. + * + * Accepts an arbitrary number of string parameters. Each parameter must contain an expression. + * + * @return string + */ + public function getConcatExpression() + { + return implode(' || ', func_get_args()); + } + + /** + * Returns the SQL for a logical not. + * + * Example: + * + * $q = new Doctrine_Query(); + * $e = $q->expr; + * $q->select('*')->from('table') + * ->where($e->eq('id', $e->not('null')); + * + * + * @param string $expression + * + * @return string The logical expression. + */ + public function getNotExpression($expression) + { + return 'NOT(' . $expression . ')'; + } + + /** + * Returns the SQL that checks if an expression is null. + * + * @param string $expression The expression that should be compared to null. + * + * @return string The logical expression. + */ + public function getIsNullExpression($expression) + { + return $expression . ' IS NULL'; + } + + /** + * Returns the SQL that checks if an expression is not null. + * + * @param string $expression The expression that should be compared to null. + * + * @return string The logical expression. + */ + public function getIsNotNullExpression($expression) + { + return $expression . ' IS NOT NULL'; + } + + /** + * Returns the 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 The logical expression. + */ + public function getBetweenExpression($expression, $value1, $value2) + { + return $expression . ' BETWEEN ' . $value1 . ' AND ' . $value2; + } + + /** + * Returns the SQL to get the arccosine of a value. + * + * @param string $value + * + * @return string + */ + public function getAcosExpression($value) + { + return 'ACOS(' . $value . ')'; + } + + /** + * Returns the SQL to get the sine of a value. + * + * @param string $value + * + * @return string + */ + public function getSinExpression($value) + { + return 'SIN(' . $value . ')'; + } + + /** + * Returns the SQL to get the PI value. + * + * @return string + */ + public function getPiExpression() + { + return 'PI()'; + } + + /** + * Returns the SQL to get the cosine of a value. + * + * @param string $value + * + * @return string + */ + public function getCosExpression($value) + { + return 'COS(' . $value . ')'; + } + + /** + * Returns the SQL to calculate the difference in days between the two passed dates. + * + * Computes diff = date1 - date2. + * + * @param string $date1 + * @param string $date2 + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateDiffExpression($date1, $date2) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the SQL to add the number of given seconds to a date. + * + * @param string $date + * @param int $seconds + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateAddSecondsExpression($date, $seconds) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $seconds, DateIntervalUnit::SECOND); + } + + /** + * Returns the SQL to subtract the number of given seconds from a date. + * + * @param string $date + * @param int $seconds + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateSubSecondsExpression($date, $seconds) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $seconds, DateIntervalUnit::SECOND); + } + + /** + * Returns the SQL to add the number of given minutes to a date. + * + * @param string $date + * @param int $minutes + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateAddMinutesExpression($date, $minutes) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $minutes, DateIntervalUnit::MINUTE); + } + + /** + * Returns the SQL to subtract the number of given minutes from a date. + * + * @param string $date + * @param int $minutes + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateSubMinutesExpression($date, $minutes) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $minutes, DateIntervalUnit::MINUTE); + } + + /** + * Returns the SQL to add the number of given hours to a date. + * + * @param string $date + * @param int $hours + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateAddHourExpression($date, $hours) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $hours, DateIntervalUnit::HOUR); + } + + /** + * Returns the SQL to subtract the number of given hours to a date. + * + * @param string $date + * @param int $hours + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateSubHourExpression($date, $hours) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $hours, DateIntervalUnit::HOUR); + } + + /** + * Returns the SQL to add the number of given days to a date. + * + * @param string $date + * @param int $days + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateAddDaysExpression($date, $days) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $days, DateIntervalUnit::DAY); + } + + /** + * Returns the SQL to subtract the number of given days to a date. + * + * @param string $date + * @param int $days + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateSubDaysExpression($date, $days) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $days, DateIntervalUnit::DAY); + } + + /** + * Returns the SQL to add the number of given weeks to a date. + * + * @param string $date + * @param int $weeks + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateAddWeeksExpression($date, $weeks) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $weeks, DateIntervalUnit::WEEK); + } + + /** + * Returns the SQL to subtract the number of given weeks from a date. + * + * @param string $date + * @param int $weeks + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateSubWeeksExpression($date, $weeks) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $weeks, DateIntervalUnit::WEEK); + } + + /** + * Returns the SQL to add the number of given months to a date. + * + * @param string $date + * @param int $months + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateAddMonthExpression($date, $months) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $months, DateIntervalUnit::MONTH); + } + + /** + * Returns the SQL to subtract the number of given months to a date. + * + * @param string $date + * @param int $months + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateSubMonthExpression($date, $months) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $months, DateIntervalUnit::MONTH); + } + + /** + * Returns the SQL to add the number of given quarters to a date. + * + * @param string $date + * @param int $quarters + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateAddQuartersExpression($date, $quarters) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $quarters, DateIntervalUnit::QUARTER); + } + + /** + * Returns the SQL to subtract the number of given quarters from a date. + * + * @param string $date + * @param int $quarters + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateSubQuartersExpression($date, $quarters) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $quarters, DateIntervalUnit::QUARTER); + } + + /** + * Returns the SQL to add the number of given years to a date. + * + * @param string $date + * @param int $years + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateAddYearsExpression($date, $years) + { + return $this->getDateArithmeticIntervalExpression($date, '+', $years, DateIntervalUnit::YEAR); + } + + /** + * Returns the SQL to subtract the number of given years from a date. + * + * @param string $date + * @param int $years + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateSubYearsExpression($date, $years) + { + return $this->getDateArithmeticIntervalExpression($date, '-', $years, DateIntervalUnit::YEAR); + } + + /** + * Returns the SQL for a date arithmetic expression. + * + * @param string $date The column or literal representing a date to perform the arithmetic operation on. + * @param string $operator The arithmetic operator (+ or -). + * @param int $interval The interval that shall be calculated into the date. + * @param string $unit The unit of the interval that shall be calculated into the date. + * One of the DATE_INTERVAL_UNIT_* constants. + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the SQL bit AND comparison expression. + * + * @param string $value1 + * @param string $value2 + * + * @return string + */ + public function getBitAndComparisonExpression($value1, $value2) + { + return '(' . $value1 . ' & ' . $value2 . ')'; + } + + /** + * Returns the SQL bit OR comparison expression. + * + * @param string $value1 + * @param string $value2 + * + * @return string + */ + public function getBitOrComparisonExpression($value1, $value2) + { + return '(' . $value1 . ' | ' . $value2 . ')'; + } + + /** + * Returns the FOR UPDATE expression. + * + * @return string + */ + 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 The FROM clause to append the hint for the given lock mode to. + * @param int|null $lockMode One of the Doctrine\DBAL\LockMode::* constants. If null is given, nothing will + * be appended to the FROM clause. + * + * @return string + */ + public function appendLockHint($fromClause, $lockMode) + { + return $fromClause; + } + + /** + * Returns the SQL snippet to append to any SELECT statement which locks rows in shared read lock. + * + * This defaults to the ANSI 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(); + } + + /** + * Returns 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 ANSI SQL standard. + * + * @return string + */ + public function getWriteLockSQL() + { + return $this->getForUpdateSQL(); + } + + /** + * Returns the SQL snippet to drop an existing database. + * + * @param string $database The name of the database that should be dropped. + * + * @return string + */ + public function getDropDatabaseSQL($database) + { + return 'DROP DATABASE ' . $database; + } + + /** + * Returns the SQL snippet to drop an existing table. + * + * @param Table|string $table + * + * @return string + * + * @throws InvalidArgumentException + */ + public function getDropTableSQL($table) + { + $tableArg = $table; + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + if (! is_string($table)) { + throw new InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); + } + + if ($this->_eventManager !== null && $this->_eventManager->hasListeners(Events::onSchemaDropTable)) { + $eventArgs = new SchemaDropTableEventArgs($tableArg, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaDropTable, $eventArgs); + + if ($eventArgs->isDefaultPrevented()) { + $sql = $eventArgs->getSql(); + + if ($sql === null) { + throw new UnexpectedValueException('Default implementation of DROP TABLE was overridden with NULL'); + } + + return $sql; + } + } + + return 'DROP TABLE ' . $table; + } + + /** + * Returns the SQL to safely drop a temporary table WITHOUT implicitly committing an open transaction. + * + * @param Table|string $table + * + * @return string + */ + public function getDropTemporaryTableSQL($table) + { + return $this->getDropTableSQL($table); + } + + /** + * Returns the SQL to drop an index from a table. + * + * @param Index|string $index + * @param Table|string $table + * + * @return string + * + * @throws InvalidArgumentException + */ + public function getDropIndexSQL($index, $table = null) + { + if ($index instanceof Index) { + $index = $index->getQuotedName($this); + } elseif (! is_string($index)) { + throw new InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); + } + + return 'DROP INDEX ' . $index; + } + + /** + * Returns the SQL to drop a constraint. + * + * @param Constraint|string $constraint + * @param Table|string $table + * + * @return string + */ + public function getDropConstraintSQL($constraint, $table) + { + if (! $constraint instanceof Constraint) { + $constraint = new Identifier($constraint); + } + + if (! $table instanceof Table) { + $table = new Identifier($table); + } + + $constraint = $constraint->getQuotedName($this); + $table = $table->getQuotedName($this); + + return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $constraint; + } + + /** + * Returns the SQL to drop a foreign key. + * + * @param ForeignKeyConstraint|string $foreignKey + * @param Table|string $table + * + * @return string + */ + public function getDropForeignKeySQL($foreignKey, $table) + { + if (! $foreignKey instanceof ForeignKeyConstraint) { + $foreignKey = new Identifier($foreignKey); + } + + if (! $table instanceof Table) { + $table = new Identifier($table); + } + + $foreignKey = $foreignKey->getQuotedName($this); + $table = $table->getQuotedName($this); + + return 'ALTER TABLE ' . $table . ' DROP FOREIGN KEY ' . $foreignKey; + } + + /** + * Returns the SQL statement(s) to create a table with the specified name, columns and constraints + * on this platform. + * + * @param int $createFlags + * + * @return string[] The sequence of SQL statements. + * + * @throws DBALException + * @throws InvalidArgumentException + */ + 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->getQuotedName($this); + $options = $table->getOptions(); + $options['uniqueConstraints'] = []; + $options['indexes'] = []; + $options['primary'] = []; + + if (($createFlags&self::CREATE_INDEXES) > 0) { + foreach ($table->getIndexes() as $index) { + /** @var $index Index */ + if ($index->isPrimary()) { + $options['primary'] = $index->getQuotedColumns($this); + $options['primary_index'] = $index; + } else { + $options['indexes'][$index->getQuotedName($this)] = $index; + } + } + } + + $columnSql = []; + $columns = []; + + foreach ($table->getColumns() as $column) { + if ($this->_eventManager !== null && $this->_eventManager->hasListeners(Events::onSchemaCreateTableColumn)) { + $eventArgs = new SchemaCreateTableColumnEventArgs($column, $table, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaCreateTableColumn, $eventArgs); + + $columnSql = array_merge($columnSql, $eventArgs->getSql()); + + if ($eventArgs->isDefaultPrevented()) { + continue; + } + } + + $columnData = $column->toArray(); + $columnData['name'] = $column->getQuotedName($this); + $columnData['version'] = $column->hasPlatformOption('version') ? $column->getPlatformOption('version') : false; + $columnData['comment'] = $this->getColumnComment($column); + + if ($columnData['type'] instanceof Types\StringType && $columnData['length'] === null) { + $columnData['length'] = 255; + } + + if (in_array($column->getName(), $options['primary'])) { + $columnData['primary'] = true; + } + + $columns[$columnData['name']] = $columnData; + } + + if (($createFlags&self::CREATE_FOREIGNKEYS) > 0) { + $options['foreignKeys'] = []; + foreach ($table->getForeignKeys() as $fkConstraint) { + $options['foreignKeys'][] = $fkConstraint; + } + } + + if ($this->_eventManager !== null && $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) { + $eventArgs = new SchemaCreateTableEventArgs($table, $columns, $options, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs); + + if ($eventArgs->isDefaultPrevented()) { + return array_merge($eventArgs->getSql(), $columnSql); + } + } + + $sql = $this->_getCreateTableSQL($tableName, $columns, $options); + if ($this->supportsCommentOnStatement()) { + if ($table->hasOption('comment')) { + $sql[] = $this->getCommentOnTableSQL($tableName, $table->getOption('comment')); + } + foreach ($table->getColumns() as $column) { + $comment = $this->getColumnComment($column); + + if ($comment === null || $comment === '') { + continue; + } + + $sql[] = $this->getCommentOnColumnSQL($tableName, $column->getQuotedName($this), $comment); + } + } + + return array_merge($sql, $columnSql); + } + + protected function getCommentOnTableSQL(string $tableName, ?string $comment) : string + { + $tableName = new Identifier($tableName); + + return sprintf( + 'COMMENT ON TABLE %s IS %s', + $tableName->getQuotedName($this), + $this->quoteStringLiteral((string) $comment) + ); + } + + /** + * @param string $tableName + * @param string $columnName + * @param string|null $comment + * + * @return string + */ + public function getCommentOnColumnSQL($tableName, $columnName, $comment) + { + $tableName = new Identifier($tableName); + $columnName = new Identifier($columnName); + + return sprintf( + 'COMMENT ON COLUMN %s.%s IS %s', + $tableName->getQuotedName($this), + $columnName->getQuotedName($this), + $this->quoteStringLiteral((string) $comment) + ); + } + + /** + * Returns the SQL to create inline comment on a column. + * + * @param string $comment + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getInlineColumnCommentSQL($comment) + { + if (! $this->supportsInlineColumnComments()) { + throw DBALException::notSupported(__METHOD__); + } + + return 'COMMENT ' . $this->quoteStringLiteral($comment); + } + + /** + * Returns the SQL used to create a table. + * + * @param string $tableName + * @param mixed[][] $columns + * @param mixed[] $options + * + * @return string[] + */ + protected function _getCreateTableSQL($tableName, array $columns, array $options = []) + { + $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; + } + + /** + * @return string + */ + public function getCreateTemporaryTableSnippetSQL() + { + return 'CREATE TEMPORARY TABLE'; + } + + /** + * Returns the SQL to create a sequence on this platform. + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getCreateSequenceSQL(Sequence $sequence) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the SQL to change a sequence on this platform. + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getAlterSequenceSQL(Sequence $sequence) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the SQL to create a constraint on a table on this platform. + * + * @param Table|string $table + * + * @return string + * + * @throws InvalidArgumentException + */ + public function getCreateConstraintSQL(Constraint $constraint, $table) + { + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + $query = 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $constraint->getQuotedName($this); + + $columnList = '(' . implode(', ', $constraint->getQuotedColumns($this)) . ')'; + + $referencesClause = ''; + if ($constraint instanceof 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().' + ); + } + } elseif ($constraint instanceof ForeignKeyConstraint) { + $query .= ' FOREIGN KEY'; + + $referencesClause = ' REFERENCES ' . $constraint->getQuotedForeignTableName($this) . + ' (' . implode(', ', $constraint->getQuotedForeignColumns($this)) . ')'; + } + $query .= ' ' . $columnList . $referencesClause; + + return $query; + } + + /** + * Returns the SQL to create an index on a table on this platform. + * + * @param Table|string $table The name of the table on which the index is to be created. + * + * @return string + * + * @throws InvalidArgumentException + */ + public function getCreateIndexSQL(Index $index, $table) + { + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + $name = $index->getQuotedName($this); + $columns = $index->getColumns(); + + if (count($columns) === 0) { + throw new InvalidArgumentException("Incomplete definition. 'columns' required."); + } + + if ($index->isPrimary()) { + return $this->getCreatePrimaryKeySQL($index, $table); + } + + $query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $table; + $query .= ' (' . $this->getIndexFieldDeclarationListSQL($index) . ')' . $this->getPartialIndexSQL($index); + + return $query; + } + + /** + * Adds condition for partial index. + * + * @return string + */ + protected function getPartialIndexSQL(Index $index) + { + if ($this->supportsPartialIndexes() && $index->hasOption('where')) { + return ' WHERE ' . $index->getOption('where'); + } + + return ''; + } + + /** + * Adds additional flags for index generation. + * + * @return string + */ + protected function getCreateIndexSQLFlags(Index $index) + { + return $index->isUnique() ? 'UNIQUE ' : ''; + } + + /** + * Returns the SQL to create an unnamed primary key constraint. + * + * @param Table|string $table + * + * @return string + */ + public function getCreatePrimaryKeySQL(Index $index, $table) + { + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index) . ')'; + } + + /** + * Returns the SQL to create a named schema. + * + * @param string $schemaName + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getCreateSchemaSQL($schemaName) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * 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. This also detects identifier + * chains separated by dot and quotes them independently. + * + * 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 The identifier name to be quoted. + * + * @return string The quoted identifier string. + */ + public function quoteIdentifier($str) + { + if (strpos($str, '.') !== false) { + $parts = array_map([$this, 'quoteSingleIdentifier'], explode('.', $str)); + + return implode('.', $parts); + } + + return $this->quoteSingleIdentifier($str); + } + + /** + * Quotes a single identifier (no dot chain separation). + * + * @param string $str The identifier name to be quoted. + * + * @return string The quoted identifier string. + */ + public function quoteSingleIdentifier($str) + { + $c = $this->getIdentifierQuoteCharacter(); + + return $c . str_replace($c, $c . $c, $str) . $c; + } + + /** + * Returns the SQL to create a new foreign key. + * + * @param ForeignKeyConstraint $foreignKey The foreign key constraint. + * @param Table|string $table The name of the table on which the foreign key is to be created. + * + * @return string + */ + public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table) + { + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + return 'ALTER TABLE ' . $table . ' ADD ' . $this->getForeignKeyDeclarationSQL($foreignKey); + } + + /** + * Gets the SQL statements for altering an existing table. + * + * This method returns an array of SQL statements, since some platforms need several statements. + * + * @return string[] + * + * @throws DBALException If not supported on this platform. + */ + public function getAlterTableSQL(TableDiff $diff) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * @param mixed[] $columnSql + * + * @return bool + */ + protected function onSchemaAlterTableAddColumn(Column $column, TableDiff $diff, &$columnSql) + { + if ($this->_eventManager === null) { + return false; + } + + if (! $this->_eventManager->hasListeners(Events::onSchemaAlterTableAddColumn)) { + return false; + } + + $eventArgs = new SchemaAlterTableAddColumnEventArgs($column, $diff, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableAddColumn, $eventArgs); + + $columnSql = array_merge($columnSql, $eventArgs->getSql()); + + return $eventArgs->isDefaultPrevented(); + } + + /** + * @param string[] $columnSql + * + * @return bool + */ + protected function onSchemaAlterTableRemoveColumn(Column $column, TableDiff $diff, &$columnSql) + { + if ($this->_eventManager === null) { + return false; + } + + if (! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRemoveColumn)) { + return false; + } + + $eventArgs = new SchemaAlterTableRemoveColumnEventArgs($column, $diff, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableRemoveColumn, $eventArgs); + + $columnSql = array_merge($columnSql, $eventArgs->getSql()); + + return $eventArgs->isDefaultPrevented(); + } + + /** + * @param string[] $columnSql + * + * @return bool + */ + protected function onSchemaAlterTableChangeColumn(ColumnDiff $columnDiff, TableDiff $diff, &$columnSql) + { + if ($this->_eventManager === null) { + return false; + } + + if (! $this->_eventManager->hasListeners(Events::onSchemaAlterTableChangeColumn)) { + return false; + } + + $eventArgs = new SchemaAlterTableChangeColumnEventArgs($columnDiff, $diff, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableChangeColumn, $eventArgs); + + $columnSql = array_merge($columnSql, $eventArgs->getSql()); + + return $eventArgs->isDefaultPrevented(); + } + + /** + * @param string $oldColumnName + * @param string[] $columnSql + * + * @return bool + */ + protected function onSchemaAlterTableRenameColumn($oldColumnName, Column $column, TableDiff $diff, &$columnSql) + { + if ($this->_eventManager === null) { + return false; + } + + if (! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRenameColumn)) { + return false; + } + + $eventArgs = new SchemaAlterTableRenameColumnEventArgs($oldColumnName, $column, $diff, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableRenameColumn, $eventArgs); + + $columnSql = array_merge($columnSql, $eventArgs->getSql()); + + return $eventArgs->isDefaultPrevented(); + } + + /** + * @param string[] $sql + * + * @return bool + */ + protected function onSchemaAlterTable(TableDiff $diff, &$sql) + { + if ($this->_eventManager === null) { + return false; + } + + if (! $this->_eventManager->hasListeners(Events::onSchemaAlterTable)) { + return false; + } + + $eventArgs = new SchemaAlterTableEventArgs($diff, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaAlterTable, $eventArgs); + + $sql = array_merge($sql, $eventArgs->getSql()); + + return $eventArgs->isDefaultPrevented(); + } + + /** + * @return string[] + */ + protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) + { + $tableName = $diff->getName($this)->getQuotedName($this); + + $sql = []; + if ($this->supportsForeignKeyConstraints()) { + foreach ($diff->removedForeignKeys as $foreignKey) { + $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName); + } + foreach ($diff->changedForeignKeys as $foreignKey) { + $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName); + } + } + + foreach ($diff->removedIndexes as $index) { + $sql[] = $this->getDropIndexSQL($index, $tableName); + } + foreach ($diff->changedIndexes as $index) { + $sql[] = $this->getDropIndexSQL($index, $tableName); + } + + return $sql; + } + + /** + * @return string[] + */ + protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) + { + $sql = []; + $newName = $diff->getNewName(); + + if ($newName !== false) { + $tableName = $newName->getQuotedName($this); + } else { + $tableName = $diff->getName($this)->getQuotedName($this); + } + + if ($this->supportsForeignKeyConstraints()) { + foreach ($diff->addedForeignKeys as $foreignKey) { + $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); + } + + foreach ($diff->changedForeignKeys as $foreignKey) { + $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); + } + } + + foreach ($diff->addedIndexes as $index) { + $sql[] = $this->getCreateIndexSQL($index, $tableName); + } + + foreach ($diff->changedIndexes as $index) { + $sql[] = $this->getCreateIndexSQL($index, $tableName); + } + + foreach ($diff->renamedIndexes as $oldIndexName => $index) { + $oldIndexName = new Identifier($oldIndexName); + $sql = array_merge( + $sql, + $this->getRenameIndexSQL($oldIndexName->getQuotedName($this), $index, $tableName) + ); + } + + return $sql; + } + + /** + * Returns the SQL for renaming an index on a table. + * + * @param string $oldIndexName The name of the index to rename from. + * @param Index $index The definition of the index to rename to. + * @param string $tableName The table to rename the given index on. + * + * @return string[] The sequence of SQL statements for renaming the given index. + */ + protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) + { + return [ + $this->getDropIndexSQL($oldIndexName, $tableName), + $this->getCreateIndexSQL($index, $tableName), + ]; + } + + /** + * Common code for alter table statement generation that updates the changed Index and Foreign Key definitions. + * + * @deprecated + * + * @return string[] + */ + protected function _getAlterTableIndexForeignKeySQL(TableDiff $diff) + { + return array_merge($this->getPreAlterTableIndexForeignKeySQL($diff), $this->getPostAlterTableIndexForeignKeySQL($diff)); + } + + /** + * Gets declaration of a number of fields in bulk. + * + * @param mixed[][] $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 = []; + + foreach ($fields as $fieldName => $field) { + $queryFields[] = $this->getColumnDeclarationSQL($fieldName, $field); + } + + return implode(', ', $queryFields); + } + + /** + * Obtains DBMS specific SQL code portion needed to declare a generic type + * field to be used in statements like CREATE TABLE. + * + * @param string $name The name the field to be declared. + * @param mixed[] $field An 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; + + if ($this->supportsInlineColumnComments() && isset($field['comment']) && $field['comment'] !== '') { + $columnDef .= ' ' . $this->getInlineColumnCommentSQL($field['comment']); + } + } + + return $name . ' ' . $columnDef; + } + + /** + * Returns the SQL snippet that declares a floating point column of arbitrary precision. + * + * @param mixed[] $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'] . ')'; + } + + /** + * Obtains DBMS specific SQL code portion needed to set a default value + * declaration to be used in statements like CREATE TABLE. + * + * @param mixed[] $field The field definition array. + * + * @return string DBMS specific SQL code portion needed to set a default value. + */ + public function getDefaultValueDeclarationSQL($field) + { + if (! isset($field['default'])) { + return empty($field['notnull']) ? ' DEFAULT NULL' : ''; + } + + $default = $field['default']; + + if (! isset($field['type'])) { + return " DEFAULT '" . $default . "'"; + } + + $type = $field['type']; + + if ($type instanceof Types\PhpIntegerMappingType) { + return ' DEFAULT ' . $default; + } + + if ($type instanceof Types\PhpDateTimeMappingType && $default === $this->getCurrentTimestampSQL()) { + return ' DEFAULT ' . $this->getCurrentTimestampSQL(); + } + + if ($type instanceof Types\TimeType && $default === $this->getCurrentTimeSQL()) { + return ' DEFAULT ' . $this->getCurrentTimeSQL(); + } + + if ($type instanceof Types\DateType && $default === $this->getCurrentDateSQL()) { + return ' DEFAULT ' . $this->getCurrentDateSQL(); + } + + if ($type instanceof Types\BooleanType) { + return " DEFAULT '" . $this->convertBooleans($default) . "'"; + } + + return ' DEFAULT ' . $this->quoteStringLiteral($default); + } + + /** + * Obtains DBMS specific SQL code portion needed to set a CHECK constraint + * declaration to be used in statements like CREATE TABLE. + * + * @param string[]|mixed[][] $definition The check definition. + * + * @return string DBMS specific SQL code portion needed to set a CHECK constraint. + */ + public function getCheckDeclarationSQL(array $definition) + { + $constraints = []; + 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); + } + + /** + * Obtains DBMS specific SQL code portion needed to set a unique + * constraint declaration to be used in statements like CREATE TABLE. + * + * @param string $name The name of the unique constraint. + * @param Index $index The index definition. + * + * @return string DBMS specific SQL code portion needed to set a constraint. + * + * @throws InvalidArgumentException + */ + public function getUniqueConstraintDeclarationSQL($name, Index $index) + { + $columns = $index->getColumns(); + $name = new Identifier($name); + + if (count($columns) === 0) { + throw new InvalidArgumentException("Incomplete definition. 'columns' required."); + } + + return 'CONSTRAINT ' . $name->getQuotedName($this) . ' UNIQUE (' + . $this->getIndexFieldDeclarationListSQL($index) + . ')' . $this->getPartialIndexSQL($index); + } + + /** + * Obtains DBMS specific SQL code portion needed to set an index + * declaration to be used in statements like CREATE TABLE. + * + * @param string $name The name of the index. + * @param Index $index The index definition. + * + * @return string DBMS specific SQL code portion needed to set an index. + * + * @throws InvalidArgumentException + */ + public function getIndexDeclarationSQL($name, Index $index) + { + $columns = $index->getColumns(); + $name = new Identifier($name); + + if (count($columns) === 0) { + throw new InvalidArgumentException("Incomplete definition. 'columns' required."); + } + + return $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name->getQuotedName($this) . ' (' + . $this->getIndexFieldDeclarationListSQL($index) + . ')' . $this->getPartialIndexSQL($index); + } + + /** + * Obtains 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. + * + * @param mixed[] $columnDef + * + * @return string + */ + public function getCustomTypeDeclarationSQL(array $columnDef) + { + return $columnDef['columnDefinition']; + } + + /** + * Obtains DBMS specific SQL code portion needed to set an index + * declaration to be used in statements like CREATE TABLE. + * + * @param mixed[]|Index $columnsOrIndex array declaration is deprecated, prefer passing Index to this method + */ + public function getIndexFieldDeclarationListSQL($columnsOrIndex) : string + { + if ($columnsOrIndex instanceof Index) { + return implode(', ', $columnsOrIndex->getQuotedColumns($this)); + } + + if (! is_array($columnsOrIndex)) { + throw new InvalidArgumentException('Fields argument should be an Index or array.'); + } + + $ret = []; + + foreach ($columnsOrIndex as $column => $definition) { + if (is_array($definition)) { + $ret[] = $column; + } else { + $ret[] = $definition; + } + } + + return implode(', ', $ret); + } + + /** + * Returns 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; + } + + /** + * 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. + * + * @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; + } + + /** + * Returns the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param ForeignKeyConstraint $foreignKey The 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 the given referential action in uppercase if valid, otherwise throws an exception. + * + * @param string $action The foreign key referential action. + * + * @return string + * + * @throws InvalidArgumentException If unknown referential action given. + */ + public function getForeignKeyReferentialActionSQL($action) + { + $upper = strtoupper($action); + switch ($upper) { + case 'CASCADE': + case 'SET NULL': + case 'NO ACTION': + case 'RESTRICT': + case 'SET DEFAULT': + return $upper; + default: + throw new InvalidArgumentException('Invalid foreign key action: ' . $upper); + } + } + + /** + * Obtains DBMS specific SQL code portion needed to set the FOREIGN KEY constraint + * of a field declaration to be used in statements like CREATE TABLE. + * + * @return string + * + * @throws InvalidArgumentException + */ + public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint $foreignKey) + { + $sql = ''; + if (strlen($foreignKey->getName())) { + $sql .= 'CONSTRAINT ' . $foreignKey->getQuotedName($this) . ' '; + } + $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."); + } + + return $sql . implode(', ', $foreignKey->getQuotedLocalColumns($this)) + . ') REFERENCES ' + . $foreignKey->getQuotedForeignTableName($this) . ' (' + . implode(', ', $foreignKey->getQuotedForeignColumns($this)) . ')'; + } + + /** + * Obtains 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'; + } + + /** + * Obtains 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 The 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 ''; + } + + /** + * Obtains 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 The 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 $this->supportsColumnCollation() ? 'COLLATE ' . $collation : ''; + } + + /** + * Whether the platform prefers sequences for ID generation. + * Subclasses should override this method to return TRUE if they prefer sequences. + * + * @return bool + */ + 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 bool + */ + 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). + * + * Note: if the input is not a boolean the original input might be returned. + * + * There are two contexts when converting booleans: Literals and Prepared Statements. + * This method should handle the literal case + * + * @param mixed $item A boolean or an array of them. + * + * @return mixed A boolean database value or an array of them. + */ + public function convertBooleans($item) + { + if (is_array($item)) { + foreach ($item as $k => $value) { + if (! is_bool($value)) { + continue; + } + + $item[$k] = (int) $value; + } + } elseif (is_bool($item)) { + $item = (int) $item; + } + + return $item; + } + + /** + * Some platforms have boolean literals that needs to be correctly converted + * + * The default conversion tries to convert value into bool "(bool)$item" + * + * @param mixed $item + * + * @return bool|null + */ + public function convertFromBoolean($item) + { + return $item === null ? null: (bool) $item; + } + + /** + * This method should handle the prepared statements case. When there is no + * distinction, it's OK to use the same method. + * + * Note: if the input is not a boolean the original input might be returned. + * + * @param mixed $item A boolean or an array of them. + * + * @return mixed A boolean database value or an array of them. + */ + public function convertBooleansToDatabaseValue($item) + { + return $this->convertBooleans($item); + } + + /** + * Returns the SQL specific for the platform to get the current date. + * + * @return string + */ + public function getCurrentDateSQL() + { + return 'CURRENT_DATE'; + } + + /** + * Returns the SQL specific for the platform to get the current time. + * + * @return string + */ + public function getCurrentTimeSQL() + { + return 'CURRENT_TIME'; + } + + /** + * Returns the SQL specific for the platform to get the current timestamp + * + * @return string + */ + public function getCurrentTimestampSQL() + { + return 'CURRENT_TIMESTAMP'; + } + + /** + * Returns the SQL for a given transaction isolation level Connection constant. + * + * @param int $level + * + * @return string + * + * @throws InvalidArgumentException + */ + protected function _getTransactionIsolationLevelSQL($level) + { + switch ($level) { + case TransactionIsolationLevel::READ_UNCOMMITTED: + return 'READ UNCOMMITTED'; + case TransactionIsolationLevel::READ_COMMITTED: + return 'READ COMMITTED'; + case TransactionIsolationLevel::REPEATABLE_READ: + return 'REPEATABLE READ'; + case TransactionIsolationLevel::SERIALIZABLE: + return 'SERIALIZABLE'; + default: + throw new InvalidArgumentException('Invalid isolation level:' . $level); + } + } + + /** + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getListDatabasesSQL() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the SQL statement for retrieving the namespaces defined in the database. + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getListNamespacesSQL() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * @param string $database + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getListSequencesSQL($database) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * @param string $table + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getListTableConstraintsSQL($table) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * @param string $table + * @param string|null $database + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getListTableColumnsSQL($table, $database = null) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getListTablesSQL() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getListUsersSQL() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the SQL to list all views of a database or user. + * + * @param string $database + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getListViewsSQL($database) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the list of indexes for the current database. + * + * The current database parameter is optional but will always be passed + * when using the SchemaManager API and is the database the given table is in. + * + * Attention: Some platforms only support currentDatabase when they + * are connected with that database. Cross-database information schema + * requests may be impossible. + * + * @param string $table + * @param string $currentDatabase + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * @param string $table + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getListTableForeignKeysSQL($table) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * @param string $name + * @param string $sql + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getCreateViewSQL($name, $sql) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * @param string $name + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDropViewSQL($name) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the SQL snippet to drop an existing sequence. + * + * @param Sequence|string $sequence + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDropSequenceSQL($sequence) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * @param string $sequenceName + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getSequenceNextValSQL($sequenceName) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the SQL to create a new database. + * + * @param string $database The name of the database that should be created. + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getCreateDatabaseSQL($database) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the SQL to set the transaction isolation level. + * + * @param int $level + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getSetTransactionIsolationSQL($level) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Obtains DBMS specific SQL to be used to create datetime fields in + * statements like CREATE TABLE. + * + * @param mixed[] $fieldDeclaration + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Obtains DBMS specific SQL to be used to create datetime with timezone offset fields. + * + * @param mixed[] $fieldDeclaration + * + * @return string + */ + public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) + { + return $this->getDateTimeTypeDeclarationSQL($fieldDeclaration); + } + + /** + * Obtains DBMS specific SQL to be used to create date fields in statements + * like CREATE TABLE. + * + * @param mixed[] $fieldDeclaration + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Obtains DBMS specific SQL to be used to create time fields in statements + * like CREATE TABLE. + * + * @param mixed[] $fieldDeclaration + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * @param mixed[] $fieldDeclaration + * + * @return string + */ + public function getFloatDeclarationSQL(array $fieldDeclaration) + { + return 'DOUBLE PRECISION'; + } + + /** + * Gets the default transaction isolation level of the platform. + * + * @see TransactionIsolationLevel + * + * @return int The default isolation level. + */ + public function getDefaultTransactionIsolationLevel() + { + return TransactionIsolationLevel::READ_COMMITTED; + } + + /* supports*() methods */ + + /** + * Whether the platform supports sequences. + * + * @return bool + */ + public function supportsSequences() + { + return false; + } + + /** + * Whether the platform supports identity columns. + * + * Identity columns are columns that receive an auto-generated value from the + * database on insert of a row. + * + * @return bool + */ + public function supportsIdentityColumns() + { + return false; + } + + /** + * Whether the platform emulates identity columns through sequences. + * + * Some platforms that do not support identity columns natively + * but support sequences can emulate identity columns by using + * sequences. + * + * @return bool + */ + public function usesSequenceEmulatedIdentityColumns() + { + return false; + } + + /** + * Returns the name of the sequence for a particular identity column in a particular table. + * + * @see usesSequenceEmulatedIdentityColumns + * + * @param string $tableName The name of the table to return the sequence name for. + * @param string $columnName The name of the identity column in the table to return the sequence name for. + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getIdentitySequenceName($tableName, $columnName) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Whether the platform supports indexes. + * + * @return bool + */ + public function supportsIndexes() + { + return true; + } + + /** + * Whether the platform supports partial indexes. + * + * @return bool + */ + public function supportsPartialIndexes() + { + return false; + } + + /** + * Whether the platform supports indexes with column length definitions. + */ + public function supportsColumnLengthIndexes() : bool + { + return false; + } + + /** + * Whether the platform supports altering tables. + * + * @return bool + */ + public function supportsAlterTable() + { + return true; + } + + /** + * Whether the platform supports transactions. + * + * @return bool + */ + public function supportsTransactions() + { + return true; + } + + /** + * Whether the platform supports savepoints. + * + * @return bool + */ + public function supportsSavepoints() + { + return true; + } + + /** + * Whether the platform supports releasing savepoints. + * + * @return bool + */ + public function supportsReleaseSavepoints() + { + return $this->supportsSavepoints(); + } + + /** + * Whether the platform supports primary key constraints. + * + * @return bool + */ + public function supportsPrimaryConstraints() + { + return true; + } + + /** + * Whether the platform supports foreign key constraints. + * + * @return bool + */ + public function supportsForeignKeyConstraints() + { + return true; + } + + /** + * Whether this platform supports onUpdate in foreign key constraints. + * + * @return bool + */ + public function supportsForeignKeyOnUpdate() + { + return $this->supportsForeignKeyConstraints(); + } + + /** + * Whether the platform supports database schemas. + * + * @return bool + */ + public function supportsSchemas() + { + return false; + } + + /** + * Whether this platform can emulate schemas. + * + * Platforms that either support or emulate schemas don't automatically + * filter a schema for the namespaced elements in {@link + * AbstractManager#createSchema}. + * + * @return bool + */ + public function canEmulateSchemas() + { + return false; + } + + /** + * Returns the default schema name. + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + public function getDefaultSchemaName() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Whether this platform supports create database. + * + * 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 bool + */ + public function supportsGettingAffectedRows() + { + return true; + } + + /** + * Whether this platform support to add inline column comments as postfix. + * + * @return bool + */ + public function supportsInlineColumnComments() + { + return false; + } + + /** + * Whether this platform support the proprietary syntax "COMMENT ON asset". + * + * @return bool + */ + public function supportsCommentOnStatement() + { + return false; + } + + /** + * Does this platform have native guid type. + * + * @return bool + */ + public function hasNativeGuidType() + { + return false; + } + + /** + * Does this platform have native JSON type. + * + * @return bool + */ + public function hasNativeJsonType() + { + return false; + } + + /** + * @deprecated + * + * @todo Remove in 3.0 + */ + public function getIdentityColumnNullInsertSQL() + { + return ''; + } + + /** + * Whether this platform supports views. + * + * @return bool + */ + public function supportsViews() + { + return true; + } + + /** + * Does this platform support column collation? + * + * @return bool + */ + public function supportsColumnCollation() + { + return false; + } + + /** + * 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'; + } + + /** + * Adds an driver-specific LIMIT clause to the query. + * + * @param string $query + * @param int|null $limit + * @param int|null $offset + * + * @return string + * + * @throws DBALException + */ + final public function modifyLimitQuery($query, $limit, $offset = null) + { + if ($limit !== null) { + $limit = (int) $limit; + } + + $offset = (int) $offset; + + if ($offset < 0) { + throw new DBALException(sprintf( + 'Offset must be a positive integer or zero, %d given', + $offset + )); + } + + if ($offset > 0 && ! $this->supportsLimitOffset()) { + throw new DBALException(sprintf( + 'Platform %s does not support offset values in limit queries.', + $this->getName() + )); + } + + return $this->doModifyLimitQuery($query, $limit, $offset); + } + + /** + * Adds an platform-specific LIMIT clause to the query. + * + * @param string $query + * @param int|null $limit + * @param int|null $offset + * + * @return string + */ + protected function doModifyLimitQuery($query, $limit, $offset) + { + if ($limit !== null) { + $query .= ' LIMIT ' . $limit; + } + + if ($offset > 0) { + $query .= ' OFFSET ' . $offset; + } + + return $query; + } + + /** + * Whether the database platform support offsets in modify limit clauses. + * + * @return bool + */ + public function supportsLimitOffset() + { + return true; + } + + /** + * 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 $schemaElementName + * + * @return string + */ + public function fixSchemaElementName($schemaElementName) + { + return $schemaElementName; + } + + /** + * Maximum length of any given database identifier, like tables or column names. + * + * @return int + */ + public function getMaxIdentifierLength() + { + return 63; + } + + /** + * Returns the insert SQL for an empty insert statement. + * + * @param string $tableName + * @param string $identifierColumnName + * + * @return string + */ + public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName) + { + return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (null)'; + } + + /** + * Generates 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) + { + $tableIdentifier = new Identifier($tableName); + + return 'TRUNCATE ' . $tableIdentifier->getQuotedName($this); + } + + /** + * This is for test reasons, many vendors have special requirements for dummy statements. + * + * @return string + */ + public function getDummySelectSQL() + { + $expression = func_num_args() > 0 ? func_get_arg(0) : '1'; + + return sprintf('SELECT %s', $expression); + } + + /** + * Returns the SQL to create a new savepoint. + * + * @param string $savepoint + * + * @return string + */ + public function createSavePoint($savepoint) + { + return 'SAVEPOINT ' . $savepoint; + } + + /** + * Returns the SQL to release a savepoint. + * + * @param string $savepoint + * + * @return string + */ + public function releaseSavePoint($savepoint) + { + return 'RELEASE SAVEPOINT ' . $savepoint; + } + + /** + * Returns the SQL to rollback a savepoint. + * + * @param string $savepoint + * + * @return string + */ + public function rollbackSavePoint($savepoint) + { + return 'ROLLBACK TO SAVEPOINT ' . $savepoint; + } + + /** + * Returns the keyword list instance of this platform. + * + * @return KeywordList + * + * @throws DBALException If no keyword list is specified. + */ + final public function getReservedKeywordsList() + { + // Check for an existing instantiation of the keywords class. + if ($this->_keywords) { + return $this->_keywords; + } + + $class = $this->getReservedKeywordsClass(); + $keywords = new $class(); + if (! $keywords instanceof KeywordList) { + throw DBALException::notSupported(__METHOD__); + } + + // Store the instance so it doesn't need to be generated on every request. + $this->_keywords = $keywords; + + return $keywords; + } + + /** + * Returns the class name of the reserved keywords list. + * + * @return string + * + * @throws DBALException If not supported on this platform. + */ + protected function getReservedKeywordsClass() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Quotes a literal string. + * This method is NOT meant to fix SQL injections! + * It is only meant to escape this platform's string literal + * quote character inside the given literal string. + * + * @param string $str The literal string to be quoted. + * + * @return string The quoted literal string. + */ + public function quoteStringLiteral($str) + { + $c = $this->getStringLiteralQuoteCharacter(); + + return $c . str_replace($c, $c . $c, $str) . $c; + } + + /** + * Gets the character used for string literal quoting. + * + * @return string + */ + public function getStringLiteralQuoteCharacter() + { + return "'"; + } + + /** + * Escapes metacharacters in a string intended to be used with a LIKE + * operator. + * + * @param string $inputString a literal, unquoted string + * @param string $escapeChar should be reused by the caller in the LIKE + * expression. + */ + final public function escapeStringForLike(string $inputString, string $escapeChar) : string + { + return preg_replace( + '~([' . preg_quote($this->getLikeWildcardCharacters() . $escapeChar, '~') . '])~u', + addcslashes($escapeChar, '\\') . '$1', + $inputString + ); + } + + protected function getLikeWildcardCharacters() : string + { + return '%_'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DB2Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DB2Platform.php new file mode 100644 index 0000000..25d4163 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DB2Platform.php @@ -0,0 +1,916 @@ +getCharMaxLength(); + } + + return parent::getVarcharTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + // todo blob(n) with $field['length']; + return 'BLOB(1M)'; + } + + /** + * {@inheritDoc} + */ + public function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = [ + 'smallint' => 'smallint', + 'bigint' => 'bigint', + 'integer' => 'integer', + 'time' => 'time', + 'date' => 'date', + 'varchar' => 'string', + 'character' => 'string', + 'varbinary' => 'binary', + 'binary' => 'binary', + 'clob' => 'text', + 'blob' => 'blob', + 'decimal' => 'decimal', + 'double' => 'float', + 'real' => 'float', + 'timestamp' => 'datetime', + ]; + } + + /** + * {@inheritdoc} + */ + public function isCommentedDoctrineType(Type $doctrineType) + { + if ($doctrineType->getName() === Types::BOOLEAN) { + // We require a commented boolean type in order to distinguish between boolean and smallint + // as both (have to) map to the same native type. + return true; + } + + return parent::isCommentedDoctrineType($doctrineType); + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(254)') + : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); + } + + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return $this->getVarcharTypeDeclarationSQLSnippet($length, $fixed) . ' FOR BIT DATA'; + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + // todo clob(n) with $field['length']; + return 'CLOB(1M)'; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'db2'; + } + + /** + * {@inheritDoc} + */ + public function getBooleanTypeDeclarationSQL(array $columnDef) + { + return 'SMALLINT'; + } + + /** + * {@inheritDoc} + */ + public function getIntegerTypeDeclarationSQL(array $columnDef) + { + return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $columnDef) + { + return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $columnDef) + { + return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + $autoinc = ''; + if (! empty($columnDef['autoincrement'])) { + $autoinc = ' GENERATED BY DEFAULT AS IDENTITY'; + } + + return $autoinc; + } + + /** + * {@inheritdoc} + */ + public function getBitAndComparisonExpression($value1, $value2) + { + return 'BITAND(' . $value1 . ', ' . $value2 . ')'; + } + + /** + * {@inheritdoc} + */ + public function getBitOrComparisonExpression($value1, $value2) + { + return 'BITOR(' . $value1 . ', ' . $value2 . ')'; + } + + /** + * {@inheritdoc} + */ + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + { + switch ($unit) { + case DateIntervalUnit::WEEK: + $interval *= 7; + $unit = DateIntervalUnit::DAY; + break; + + case DateIntervalUnit::QUARTER: + $interval *= 3; + $unit = DateIntervalUnit::MONTH; + break; + } + + return $date . ' ' . $operator . ' ' . $interval . ' ' . $unit; + } + + /** + * {@inheritdoc} + */ + public function getDateDiffExpression($date1, $date2) + { + return 'DAYS(' . $date1 . ') - DAYS(' . $date2 . ')'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] === true) { + return 'TIMESTAMP(0) WITH DEFAULT'; + } + + return 'TIMESTAMP(0)'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME'; + } + + /** + * {@inheritdoc} + */ + public function getTruncateTableSQL($tableName, $cascade = false) + { + $tableIdentifier = new Identifier($tableName); + + return 'TRUNCATE ' . $tableIdentifier->getQuotedName($this) . ' IMMEDIATE'; + } + + /** + * This code fragment is originally from the Zend_Db_Adapter_Db2 class, but has been edited. + * + * @param string $table + * @param string $database + * + * @return string + */ + public function getListTableColumnsSQL($table, $database = null) + { + $table = $this->quoteStringLiteral($table); + + // We do the funky subquery and join syscat.columns.default this crazy way because + // as of db2 v10, the column is CLOB(64k) and the distinct operator won't allow a CLOB, + // it wants shorter stuff like a varchar. + return " + SELECT + cols.default, + subq.* + FROM ( + SELECT DISTINCT + c.tabschema, + c.tabname, + c.colname, + c.colno, + c.typename, + c.nulls, + c.length, + c.scale, + c.identity, + tc.type AS tabconsttype, + c.remarks AS comment, + k.colseq, + CASE + WHEN c.generated = 'D' THEN 1 + ELSE 0 + END AS autoincrement + 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 + ) subq + JOIN syscat.columns cols + ON subq.tabschema = cols.tabschema + AND subq.tabname = cols.tabname + AND subq.colno = cols.colno + ORDER BY subq.colno + '; + } + + /** + * {@inheritDoc} + */ + public function getListTablesSQL() + { + return "SELECT NAME FROM SYSIBM.SYSTABLES WHERE TYPE = 'T'"; + } + + /** + * {@inheritDoc} + */ + public function getListViewsSQL($database) + { + return 'SELECT NAME, TEXT FROM SYSIBM.SYSVIEWS'; + } + + /** + * {@inheritDoc} + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + $table = $this->quoteStringLiteral($table); + + return "SELECT idx.INDNAME AS key_name, + idxcol.COLNAME AS column_name, + CASE + WHEN idx.UNIQUERULE = 'P' THEN 1 + ELSE 0 + END AS primary, + CASE + WHEN idx.UNIQUERULE = 'D' THEN 1 + ELSE 0 + END AS non_unique + FROM SYSCAT.INDEXES AS idx + JOIN SYSCAT.INDEXCOLUSE AS idxcol + ON idx.INDSCHEMA = idxcol.INDSCHEMA AND idx.INDNAME = idxcol.INDNAME + WHERE idx.TABNAME = UPPER(" . $table . ') + ORDER BY idxcol.COLSEQ ASC'; + } + + /** + * {@inheritDoc} + */ + public function getListTableForeignKeysSQL($table) + { + $table = $this->quoteStringLiteral($table); + + return "SELECT fkcol.COLNAME AS local_column, + fk.REFTABNAME AS foreign_table, + pkcol.COLNAME AS foreign_column, + fk.CONSTNAME AS index_name, + CASE + WHEN fk.UPDATERULE = 'R' THEN 'RESTRICT' + ELSE NULL + END AS on_update, + CASE + WHEN fk.DELETERULE = 'C' THEN 'CASCADE' + WHEN fk.DELETERULE = 'N' THEN 'SET NULL' + WHEN fk.DELETERULE = 'R' THEN 'RESTRICT' + ELSE NULL + END AS on_delete + FROM SYSCAT.REFERENCES AS fk + JOIN SYSCAT.KEYCOLUSE AS fkcol + ON fk.CONSTNAME = fkcol.CONSTNAME + AND fk.TABSCHEMA = fkcol.TABSCHEMA + AND fk.TABNAME = fkcol.TABNAME + JOIN SYSCAT.KEYCOLUSE AS pkcol + ON fk.REFKEYNAME = pkcol.CONSTNAME + AND fk.REFTABSCHEMA = pkcol.TABSCHEMA + AND fk.REFTABNAME = pkcol.TABNAME + WHERE fk.TABNAME = UPPER(" . $table . ') + ORDER BY fkcol.COLSEQ ASC'; + } + + /** + * {@inheritDoc} + */ + public function getCreateViewSQL($name, $sql) + { + return 'CREATE VIEW ' . $name . ' AS ' . $sql; + } + + /** + * {@inheritDoc} + */ + public function getDropViewSQL($name) + { + return 'DROP VIEW ' . $name; + } + + /** + * {@inheritDoc} + */ + public function getCreateDatabaseSQL($database) + { + return 'CREATE DATABASE ' . $database; + } + + /** + * {@inheritDoc} + */ + public function getDropDatabaseSQL($database) + { + return 'DROP DATABASE ' . $database; + } + + /** + * {@inheritDoc} + */ + public function supportsCreateDropDatabase() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function supportsReleaseSavepoints() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function supportsCommentOnStatement() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getCurrentDateSQL() + { + return 'CURRENT DATE'; + } + + /** + * {@inheritDoc} + */ + public function getCurrentTimeSQL() + { + return 'CURRENT TIME'; + } + + /** + * {@inheritDoc} + */ + public function getCurrentTimestampSQL() + { + return 'CURRENT TIMESTAMP'; + } + + /** + * {@inheritDoc} + */ + public function getIndexDeclarationSQL($name, Index $index) + { + // Index declaration in statements like CREATE TABLE is not supported. + throw DBALException::notSupported(__METHOD__); + } + + /** + * {@inheritDoc} + */ + protected function _getCreateTableSQL($tableName, array $columns, array $options = []) + { + $indexes = []; + if (isset($options['indexes'])) { + $indexes = $options['indexes']; + } + $options['indexes'] = []; + + $sqls = parent::_getCreateTableSQL($tableName, $columns, $options); + + foreach ($indexes as $definition) { + $sqls[] = $this->getCreateIndexSQL($definition, $tableName); + } + + return $sqls; + } + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $sql = []; + $columnSql = []; + $commentsSQL = []; + + $queryParts = []; + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $columnDef = $column->toArray(); + $queryPart = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); + + // Adding non-nullable columns to a table requires a default value to be specified. + if (! empty($columnDef['notnull']) && + ! isset($columnDef['default']) && + empty($columnDef['autoincrement']) + ) { + $queryPart .= ' WITH DEFAULT'; + } + + $queryParts[] = $queryPart; + + $comment = $this->getColumnComment($column); + + if ($comment === null || $comment === '') { + continue; + } + + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), + $comment + ); + } + + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $queryParts[] = 'DROP COLUMN ' . $column->getQuotedName($this); + } + + foreach ($diff->changedColumns as $columnDiff) { + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + if ($columnDiff->hasChanged('comment')) { + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $columnDiff->column->getQuotedName($this), + $this->getColumnComment($columnDiff->column) + ); + + if (count($columnDiff->changedProperties) === 1) { + continue; + } + } + + $this->gatherAlterColumnSQL($diff->getName($this), $columnDiff, $sql, $queryParts); + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $oldColumnName = new Identifier($oldColumnName); + + $queryParts[] = 'RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . + ' TO ' . $column->getQuotedName($this); + } + + $tableSql = []; + + if (! $this->onSchemaAlterTable($diff, $tableSql)) { + if (count($queryParts) > 0) { + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(' ', $queryParts); + } + + // Some table alteration operations require a table reorganization. + if (! empty($diff->removedColumns) || ! empty($diff->changedColumns)) { + $sql[] = "CALL SYSPROC.ADMIN_CMD ('REORG TABLE " . $diff->getName($this)->getQuotedName($this) . "')"; + } + + $sql = array_merge($sql, $commentsSQL); + + $newName = $diff->getNewName(); + + if ($newName !== false) { + $sql[] = sprintf( + 'RENAME TABLE %s TO %s', + $diff->getName($this)->getQuotedName($this), + $newName->getQuotedName($this) + ); + } + + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * Gathers the table alteration SQL for a given column diff. + * + * @param Identifier $table The table to gather the SQL for. + * @param ColumnDiff $columnDiff The column diff to evaluate. + * @param string[] $sql The sequence of table alteration statements to fill. + * @param mixed[] $queryParts The sequence of column alteration clauses to fill. + */ + private function gatherAlterColumnSQL(Identifier $table, ColumnDiff $columnDiff, array &$sql, array &$queryParts) + { + $alterColumnClauses = $this->getAlterColumnClausesSQL($columnDiff); + + if (empty($alterColumnClauses)) { + return; + } + + // If we have a single column alteration, we can append the clause to the main query. + if (count($alterColumnClauses) === 1) { + $queryParts[] = current($alterColumnClauses); + + return; + } + + // We have multiple alterations for the same column, + // so we need to trigger a complete ALTER TABLE statement + // for each ALTER COLUMN clause. + foreach ($alterColumnClauses as $alterColumnClause) { + $sql[] = 'ALTER TABLE ' . $table->getQuotedName($this) . ' ' . $alterColumnClause; + } + } + + /** + * Returns the ALTER COLUMN SQL clauses for altering a column described by the given column diff. + * + * @param ColumnDiff $columnDiff The column diff to evaluate. + * + * @return string[] + */ + private function getAlterColumnClausesSQL(ColumnDiff $columnDiff) + { + $column = $columnDiff->column->toArray(); + + $alterClause = 'ALTER COLUMN ' . $columnDiff->column->getQuotedName($this); + + if ($column['columnDefinition']) { + return [$alterClause . ' ' . $column['columnDefinition']]; + } + + $clauses = []; + + if ($columnDiff->hasChanged('type') || + $columnDiff->hasChanged('length') || + $columnDiff->hasChanged('precision') || + $columnDiff->hasChanged('scale') || + $columnDiff->hasChanged('fixed') + ) { + $clauses[] = $alterClause . ' SET DATA TYPE ' . $column['type']->getSQLDeclaration($column, $this); + } + + if ($columnDiff->hasChanged('notnull')) { + $clauses[] = $column['notnull'] ? $alterClause . ' SET NOT NULL' : $alterClause . ' DROP NOT NULL'; + } + + if ($columnDiff->hasChanged('default')) { + if (isset($column['default'])) { + $defaultClause = $this->getDefaultValueDeclarationSQL($column); + + if ($defaultClause) { + $clauses[] = $alterClause . ' SET' . $defaultClause; + } + } else { + $clauses[] = $alterClause . ' DROP DEFAULT'; + } + } + + return $clauses; + } + + /** + * {@inheritDoc} + */ + protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) + { + $sql = []; + $table = $diff->getName($this)->getQuotedName($this); + + foreach ($diff->removedIndexes as $remKey => $remIndex) { + foreach ($diff->addedIndexes as $addKey => $addIndex) { + if ($remIndex->getColumns() === $addIndex->getColumns()) { + if ($remIndex->isPrimary()) { + $sql[] = 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; + } elseif ($remIndex->isUnique()) { + $sql[] = 'ALTER TABLE ' . $table . ' DROP UNIQUE ' . $remIndex->getQuotedName($this); + } else { + $sql[] = $this->getDropIndexSQL($remIndex, $table); + } + + $sql[] = $this->getCreateIndexSQL($addIndex, $table); + + unset($diff->removedIndexes[$remKey], $diff->addedIndexes[$addKey]); + + break; + } + } + } + + $sql = array_merge($sql, parent::getPreAlterTableIndexForeignKeySQL($diff)); + + return $sql; + } + + /** + * {@inheritdoc} + */ + protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) + { + if (strpos($tableName, '.') !== false) { + [$schema] = explode('.', $tableName); + $oldIndexName = $schema . '.' . $oldIndexName; + } + + return ['RENAME INDEX ' . $oldIndexName . ' TO ' . $index->getQuotedName($this)]; + } + + /** + * {@inheritDoc} + */ + public function getDefaultValueDeclarationSQL($field) + { + if (! empty($field['autoincrement'])) { + return ''; + } + + if (isset($field['version']) && $field['version']) { + if ((string) $field['type'] !== 'DateTime') { + $field['default'] = '1'; + } + } + + return parent::getDefaultValueDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName) + { + return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (DEFAULT)'; + } + + /** + * {@inheritDoc} + */ + public function getCreateTemporaryTableSnippetSQL() + { + return 'DECLARE GLOBAL TEMPORARY TABLE'; + } + + /** + * {@inheritDoc} + */ + public function getTemporaryTableName($tableName) + { + return 'SESSION.' . $tableName; + } + + /** + * {@inheritDoc} + */ + protected function doModifyLimitQuery($query, $limit, $offset = null) + { + $where = []; + + if ($offset > 0) { + $where[] = sprintf('db22.DC_ROWNUM >= %d', $offset + 1); + } + + if ($limit !== null) { + $where[] = sprintf('db22.DC_ROWNUM <= %d', $offset + $limit); + } + + if (empty($where)) { + return $query; + } + + // Todo OVER() needs ORDER BY data! + return sprintf( + 'SELECT db22.* FROM (SELECT db21.*, ROW_NUMBER() OVER() AS DC_ROWNUM FROM (%s) db21) db22 WHERE %s', + $query, + implode(' AND ', $where) + ); + } + + /** + * {@inheritDoc} + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + if ($startPos === false) { + return 'LOCATE(' . $substr . ', ' . $str . ')'; + } + + return 'LOCATE(' . $substr . ', ' . $str . ', ' . $startPos . ')'; + } + + /** + * {@inheritDoc} + */ + public function getSubstringExpression($value, $from, $length = null) + { + if ($length === null) { + return 'SUBSTR(' . $value . ', ' . $from . ')'; + } + + return 'SUBSTR(' . $value . ', ' . $from . ', ' . $length . ')'; + } + + /** + * {@inheritDoc} + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function prefersIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + * + * DB2 returns all column names in SQL result sets in uppercase. + */ + public function getSQLResultCasing($column) + { + return strtoupper($column); + } + + /** + * {@inheritDoc} + */ + public function getForUpdateSQL() + { + return ' WITH RR USE AND KEEP UPDATE LOCKS'; + } + + /** + * {@inheritDoc} + */ + public function getDummySelectSQL() + { + $expression = func_num_args() > 0 ? func_get_arg(0) : '1'; + + return sprintf('SELECT %s FROM sysibm.sysdummy1', $expression); + } + + /** + * {@inheritDoc} + * + * 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. + */ + public function supportsSavepoints() + { + return false; + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return Keywords\DB2Keywords::class; + } + + public function getListTableCommentsSQL(string $table) : string + { + return sprintf( + <<<'SQL' +SELECT REMARKS + FROM SYSIBM.SYSTABLES + WHERE NAME = UPPER( %s ) +SQL + , + $this->quoteStringLiteral($table) + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DateIntervalUnit.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DateIntervalUnit.php new file mode 100644 index 0000000..ec97d0e --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DateIntervalUnit.php @@ -0,0 +1,28 @@ +_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + $autoinc = ''; + if (! empty($columnDef['autoincrement'])) { + $autoinc = ' AUTO_INCREMENT'; + } + + return $autoinc; + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $field) + { + return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $field) + { + return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'; + } + + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return 'VARBINARY(' . ($length ?: 255) . ')'; + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = [ + 'boolean' => 'boolean', + 'varchar' => 'string', + 'varbinary' => 'binary', + 'integer' => 'integer', + 'blob' => 'blob', + 'decimal' => 'decimal', + 'datetime' => 'datetime', + 'date' => 'date', + 'time' => 'time', + 'text' => 'text', + 'timestamp' => 'datetime', + 'double' => 'float', + 'bigint' => 'bigint', + ]; + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + return 'TEXT'; + } + + /** + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + return 'BLOB'; + } + + /** + * {@inheritDoc} + */ + public function getCreateDatabaseSQL($name) + { + return 'CREATE DATABASE ' . $name; + } + + /** + * {@inheritDoc} + */ + public function getDropDatabaseSQL($name) + { + return 'DROP DATABASE ' . $name; + } + + /** + * {@inheritDoc} + */ + protected function _getCreateTableSQL($tableName, array $columns, array $options = []) + { + $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 . ') '; + $query .= $this->buildTableOptions($options); + $query .= $this->buildPartitionOptions($options); + + $sql = [$query]; + + if (isset($options['foreignKeys'])) { + foreach ((array) $options['foreignKeys'] as $definition) { + $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); + } + } + + return $sql; + } + + /** + * Build SQL for table options + * + * @param mixed[] $options + * + * @return string + */ + private function buildTableOptions(array $options) + { + if (isset($options['table_options'])) { + return $options['table_options']; + } + + $tableOptions = []; + + // Collate + if (! isset($options['collate'])) { + $options['collate'] = 'utf8_unicode_ci'; + } + + $tableOptions[] = sprintf('COLLATE %s', $options['collate']); + + // Engine + if (! isset($options['engine'])) { + $options['engine'] = 'InnoDB'; + } + + $tableOptions[] = sprintf('ENGINE = %s', $options['engine']); + + // Auto increment + if (isset($options['auto_increment'])) { + $tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']); + } + + // Comment + if (isset($options['comment'])) { + $comment = trim($options['comment'], " '"); + + $tableOptions[] = sprintf('COMMENT = %s ', $this->quoteStringLiteral($comment)); + } + + // Row format + if (isset($options['row_format'])) { + $tableOptions[] = sprintf('ROW_FORMAT = %s', $options['row_format']); + } + + return implode(' ', $tableOptions); + } + + /** + * Build SQL for partition options. + * + * @param mixed[] $options + * + * @return string + */ + private function buildPartitionOptions(array $options) + { + return isset($options['partition_options']) + ? ' ' . $options['partition_options'] + : ''; + } + + /** + * {@inheritDoc} + */ + public function getListDatabasesSQL() + { + return "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE CATALOG_NAME='LOCAL'"; + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return Keywords\DrizzleKeywords::class; + } + + /** + * {@inheritDoc} + */ + public function getListTablesSQL() + { + return "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE' AND TABLE_SCHEMA=DATABASE()"; + } + + /** + * {@inheritDoc} + */ + public function getListTableColumnsSQL($table, $database = null) + { + if ($database) { + $databaseSQL = $this->quoteStringLiteral($database); + } else { + $databaseSQL = 'DATABASE()'; + } + + return 'SELECT COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT, IS_NULLABLE, IS_AUTO_INCREMENT, CHARACTER_MAXIMUM_LENGTH, COLUMN_DEFAULT,' . + ' NUMERIC_PRECISION, NUMERIC_SCALE, COLLATION_NAME' . + ' FROM DATA_DICTIONARY.COLUMNS' . + ' WHERE TABLE_SCHEMA=' . $databaseSQL . ' AND TABLE_NAME = ' . $this->quoteStringLiteral($table); + } + + /** + * {@inheritDoc} + */ + public function getListTableForeignKeysSQL($table, $database = null) + { + if ($database) { + $databaseSQL = $this->quoteStringLiteral($database); + } else { + $databaseSQL = 'DATABASE()'; + } + + return 'SELECT CONSTRAINT_NAME, CONSTRAINT_COLUMNS, REFERENCED_TABLE_NAME, REFERENCED_TABLE_COLUMNS, UPDATE_RULE, DELETE_RULE' . + ' FROM DATA_DICTIONARY.FOREIGN_KEYS' . + ' WHERE CONSTRAINT_SCHEMA=' . $databaseSQL . ' AND CONSTRAINT_TABLE=' . $this->quoteStringLiteral($table); + } + + /** + * {@inheritDoc} + */ + public function getListTableIndexesSQL($table, $database = null) + { + if ($database) { + $databaseSQL = $this->quoteStringLiteral($database); + } else { + $databaseSQL = 'DATABASE()'; + } + + return "SELECT INDEX_NAME AS 'key_name', COLUMN_NAME AS 'column_name', IS_USED_IN_PRIMARY AS 'primary', IS_UNIQUE=0 AS 'non_unique'" . + ' FROM DATA_DICTIONARY.INDEX_PARTS' . + ' WHERE TABLE_SCHEMA=' . $databaseSQL . ' AND TABLE_NAME=' . $this->quoteStringLiteral($table); + } + + /** + * {@inheritDoc} + */ + public function prefersIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsInlineColumnComments() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsViews() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function supportsColumnCollation() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getDropIndexSQL($index, $table = null) + { + if ($index instanceof Index) { + $indexName = $index->getQuotedName($this); + } elseif (is_string($index)) { + $indexName = $index; + } else { + throw new InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } elseif (! is_string($table)) { + throw new InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); + } + + if ($index instanceof Index && $index->isPrimary()) { + // drizzle primary keys are always named "PRIMARY", + // so we cannot use them in statements because of them being keyword. + return $this->getDropPrimaryKeySQL($table); + } + + return 'DROP INDEX ' . $indexName . ' ON ' . $table; + } + + /** + * {@inheritDoc} + */ + protected function getDropPrimaryKeySQL($table) + { + return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] === true) { + return 'TIMESTAMP'; + } + + return 'DATETIME'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $columnSql = []; + $queryParts = []; + + $newName = $diff->getNewName(); + + if ($newName !== false) { + $queryParts[] = 'RENAME TO ' . $newName->getQuotedName($this); + } + + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $columnArray = $column->toArray(); + $columnArray['comment'] = $this->getColumnComment($column); + $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); + } + + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $queryParts[] = 'DROP ' . $column->getQuotedName($this); + } + + foreach ($diff->changedColumns as $columnDiff) { + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + $column = $columnDiff->column; + $columnArray = $column->toArray(); + + // Do not generate column alteration clause if type is binary and only fixed property has changed. + // Drizzle only supports binary type columns with variable length. + // Avoids unnecessary table alteration statements. + if ($columnArray['type'] instanceof BinaryType && + $columnDiff->hasChanged('fixed') && + count($columnDiff->changedProperties) === 1 + ) { + continue; + } + + $columnArray['comment'] = $this->getColumnComment($column); + $queryParts[] = 'CHANGE ' . ($columnDiff->getOldColumnName()->getQuotedName($this)) . ' ' + . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $oldColumnName = new Identifier($oldColumnName); + + $columnArray = $column->toArray(); + $columnArray['comment'] = $this->getColumnComment($column); + $queryParts[] = 'CHANGE ' . $oldColumnName->getQuotedName($this) . ' ' + . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); + } + + $sql = []; + $tableSql = []; + + if (! $this->onSchemaAlterTable($diff, $tableSql)) { + if (count($queryParts) > 0) { + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(', ', $queryParts); + } + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * {@inheritDoc} + */ + public function getDropTemporaryTableSQL($table) + { + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } elseif (! is_string($table)) { + throw new InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); + } + + return 'DROP TEMPORARY TABLE ' . $table; + } + + /** + * {@inheritDoc} + */ + public function convertBooleans($item) + { + if (is_array($item)) { + foreach ($item as $key => $value) { + if (! is_bool($value) && ! is_numeric($value)) { + continue; + } + + $item[$key] = $value ? 'true' : 'false'; + } + } elseif (is_bool($item) || is_numeric($item)) { + $item = $item ? 'true' : 'false'; + } + + return $item; + } + + /** + * {@inheritDoc} + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + if ($startPos === false) { + return 'LOCATE(' . $substr . ', ' . $str . ')'; + } + + return 'LOCATE(' . $substr . ', ' . $str . ', ' . $startPos . ')'; + } + + /** + * {@inheritDoc} + * + * @deprecated Use application-generated UUIDs instead + */ + public function getGuidExpression() + { + return 'UUID()'; + } + + /** + * {@inheritDoc} + */ + public function getRegexpExpression() + { + return 'RLIKE'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php new file mode 100644 index 0000000..8533f57 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php @@ -0,0 +1,420 @@ +keywords === null) { + $this->initializeKeywords(); + } + + return isset($this->keywords[strtoupper($word)]); + } + + /** + * @return void + */ + protected function initializeKeywords() + { + $this->keywords = array_flip(array_map('strtoupper', $this->getKeywords())); + } + + /** + * Returns the list of keywords. + * + * @return string[] + */ + abstract protected function getKeywords(); + + /** + * Returns the name of this keyword list. + * + * @return string + */ + abstract public function getName(); +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MariaDb102Keywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MariaDb102Keywords.php new file mode 100644 index 0000000..1b31c76 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MariaDb102Keywords.php @@ -0,0 +1,274 @@ +keywordLists = $keywordLists; + } + + /** + * @return string[] + */ + public function getViolations() + { + return $this->violations; + } + + /** + * @param string $word + * + * @return string[] + */ + private function isReservedWord($word) + { + if ($word[0] === '`') { + $word = str_replace('`', '', $word); + } + + $keywordLists = []; + foreach ($this->keywordLists as $keywordList) { + if (! $keywordList->isKeyword($word)) { + continue; + } + + $keywordLists[] = $keywordList->getName(); + } + + return $keywordLists; + } + + /** + * @param string $asset + * @param string[] $violatedPlatforms + * + * @return void + */ + private function addViolation($asset, $violatedPlatforms) + { + if (! $violatedPlatforms) { + return; + } + + $this->violations[] = $asset . ' keyword violations: ' . implode(', ', $violatedPlatforms); + } + + /** + * {@inheritdoc} + */ + public function acceptColumn(Table $table, Column $column) + { + $this->addViolation( + 'Table ' . $table->getName() . ' column ' . $column->getName(), + $this->isReservedWord($column->getName()) + ); + } + + /** + * {@inheritdoc} + */ + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) + { + } + + /** + * {@inheritdoc} + */ + public function acceptIndex(Table $table, Index $index) + { + } + + /** + * {@inheritdoc} + */ + public function acceptSchema(Schema $schema) + { + } + + /** + * {@inheritdoc} + */ + public function acceptSequence(Sequence $sequence) + { + } + + /** + * {@inheritdoc} + */ + public function acceptTable(Table $table) + { + $this->addViolation( + 'Table ' . $table->getName(), + $this->isReservedWord($table->getName()) + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere11Keywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere11Keywords.php new file mode 100644 index 0000000..09513c5 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere11Keywords.php @@ -0,0 +1,39 @@ +doctrineTypeMapping['json'] = Types::JSON; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL57Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL57Platform.php new file mode 100644 index 0000000..1db7d66 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL57Platform.php @@ -0,0 +1,71 @@ +getQuotedName($this)]; + } + + /** + * {@inheritdoc} + */ + protected function getReservedKeywordsClass() + { + return Keywords\MySQL57Keywords::class; + } + + /** + * {@inheritdoc} + */ + protected function initializeDoctrineTypeMappings() + { + parent::initializeDoctrineTypeMappings(); + + $this->doctrineTypeMapping['json'] = Types::JSON; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL80Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL80Platform.php new file mode 100644 index 0000000..f6d4be9 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL80Platform.php @@ -0,0 +1,17 @@ + 0) { + $query .= ' OFFSET ' . $offset; + } + } elseif ($offset > 0) { + // 2^64-1 is the maximum of unsigned BIGINT, the biggest limit possible + $query .= ' LIMIT 18446744073709551615 OFFSET ' . $offset; + } + + return $query; + } + + /** + * {@inheritDoc} + */ + public function getIdentifierQuoteCharacter() + { + return '`'; + } + + /** + * {@inheritDoc} + */ + public function getRegexpExpression() + { + return 'RLIKE'; + } + + /** + * {@inheritDoc} + * + * @deprecated Use application-generated UUIDs instead + */ + public function getGuidExpression() + { + return 'UUID()'; + } + + /** + * {@inheritDoc} + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + if ($startPos === false) { + return 'LOCATE(' . $substr . ', ' . $str . ')'; + } + + return 'LOCATE(' . $substr . ', ' . $str . ', ' . $startPos . ')'; + } + + /** + * {@inheritDoc} + */ + public function getConcatExpression() + { + return sprintf('CONCAT(%s)', implode(', ', func_get_args())); + } + + /** + * {@inheritdoc} + */ + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + { + $function = $operator === '+' ? 'DATE_ADD' : 'DATE_SUB'; + + return $function . '(' . $date . ', INTERVAL ' . $interval . ' ' . $unit . ')'; + } + + /** + * {@inheritDoc} + */ + public function getDateDiffExpression($date1, $date2) + { + return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; + } + + /** + * {@inheritDoc} + */ + public function getListDatabasesSQL() + { + return 'SHOW DATABASES'; + } + + /** + * {@inheritDoc} + */ + public function getListTableConstraintsSQL($table) + { + return 'SHOW INDEX FROM ' . $table; + } + + /** + * {@inheritDoc} + * + * Two approaches to listing the table indexes. The information_schema is + * preferred, because it doesn't cause problems with SQL keywords such as "order" or "table". + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + if ($currentDatabase) { + $currentDatabase = $this->quoteStringLiteral($currentDatabase); + $table = $this->quoteStringLiteral($table); + + return 'SELECT NON_UNIQUE AS Non_Unique, INDEX_NAME AS Key_name, COLUMN_NAME AS Column_Name,' . + ' SUB_PART AS Sub_Part, INDEX_TYPE AS Index_Type' . + ' FROM information_schema.STATISTICS WHERE TABLE_NAME = ' . $table . + ' AND TABLE_SCHEMA = ' . $currentDatabase . + ' ORDER BY SEQ_IN_INDEX ASC'; + } + + return 'SHOW INDEX FROM ' . $table; + } + + /** + * {@inheritDoc} + */ + public function getListViewsSQL($database) + { + $database = $this->quoteStringLiteral($database); + + return 'SELECT * FROM information_schema.VIEWS WHERE TABLE_SCHEMA = ' . $database; + } + + /** + * {@inheritDoc} + */ + public function getListTableForeignKeysSQL($table, $database = null) + { + $table = $this->quoteStringLiteral($table); + + if ($database !== null) { + $database = $this->quoteStringLiteral($database); + } + + $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; + + $databaseNameSql = $database ?? 'DATABASE()'; + + $sql .= ' AND k.table_schema = ' . $databaseNameSql . ' /*!50116 AND c.constraint_schema = ' . $databaseNameSql . ' */'; + $sql .= ' AND k.`REFERENCED_COLUMN_NAME` is not NULL'; + + return $sql; + } + + /** + * {@inheritDoc} + */ + public function getCreateViewSQL($name, $sql) + { + return 'CREATE VIEW ' . $name . ' AS ' . $sql; + } + + /** + * {@inheritDoc} + */ + public function getDropViewSQL($name) + { + return 'DROP VIEW ' . $name; + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') + : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); + } + + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? 'BINARY(' . ($length ?: 255) . ')' : 'VARBINARY(' . ($length ?: 255) . ')'; + } + + /** + * Gets the SQL snippet used to declare a CLOB column type. + * TINYTEXT : 2 ^ 8 - 1 = 255 + * TEXT : 2 ^ 16 - 1 = 65535 + * MEDIUMTEXT : 2 ^ 24 - 1 = 16777215 + * LONGTEXT : 2 ^ 32 - 1 = 4294967295 + * + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + if (! empty($field['length']) && is_numeric($field['length'])) { + $length = $field['length']; + + if ($length <= static::LENGTH_LIMIT_TINYTEXT) { + return 'TINYTEXT'; + } + + if ($length <= static::LENGTH_LIMIT_TEXT) { + return 'TEXT'; + } + + if ($length <= static::LENGTH_LIMIT_MEDIUMTEXT) { + return 'MEDIUMTEXT'; + } + } + + return 'LONGTEXT'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] === true) { + return 'TIMESTAMP'; + } + + return 'DATETIME'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME'; + } + + /** + * {@inheritDoc} + */ + 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. + * + * @deprecated Deprecated since version 2.5, Use {@link self::getColumnCollationDeclarationSQL()} instead. + * + * @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 $this->getColumnCollationDeclarationSQL($collation); + } + + /** + * {@inheritDoc} + * + * MySql prefers "autoincrement" identity columns since sequences can only + * be emulated with a table. + */ + public function prefersIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + * + * MySql supports this through AUTO_INCREMENT columns. + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsInlineColumnComments() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsColumnCollation() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getListTablesSQL() + { + return "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"; + } + + /** + * {@inheritDoc} + */ + public function getListTableColumnsSQL($table, $database = null) + { + $table = $this->quoteStringLiteral($table); + + if ($database) { + $database = $this->quoteStringLiteral($database); + } else { + $database = 'DATABASE()'; + } + + return 'SELECT COLUMN_NAME AS Field, COLUMN_TYPE AS Type, IS_NULLABLE AS `Null`, ' . + 'COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS Extra, COLUMN_COMMENT AS Comment, ' . + 'CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS Collation ' . + 'FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ' . $database . ' AND TABLE_NAME = ' . $table . + ' ORDER BY ORDINAL_POSITION ASC'; + } + + public function getListTableMetadataSQL(string $table, ?string $database = null) : string + { + return sprintf( + <<<'SQL' +SELECT ENGINE, AUTO_INCREMENT, TABLE_COLLATION, TABLE_COMMENT, CREATE_OPTIONS +FROM information_schema.TABLES +WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = %s AND TABLE_NAME = %s +SQL + , + $database ? $this->quoteStringLiteral($database) : 'DATABASE()', + $this->quoteStringLiteral($table) + ); + } + + /** + * {@inheritDoc} + */ + public function getCreateDatabaseSQL($name) + { + return 'CREATE DATABASE ' . $name; + } + + /** + * {@inheritDoc} + */ + public function getDropDatabaseSQL($name) + { + return 'DROP DATABASE ' . $name; + } + + /** + * {@inheritDoc} + */ + protected function _getCreateTableSQL($tableName, array $columns, array $options = []) + { + $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 . ') '; + $query .= $this->buildTableOptions($options); + $query .= $this->buildPartitionOptions($options); + + $sql = [$query]; + $engine = 'INNODB'; + + if (isset($options['engine'])) { + $engine = strtoupper(trim($options['engine'])); + } + + // Propagate foreign key constraints only for InnoDB. + if (isset($options['foreignKeys']) && $engine === 'INNODB') { + foreach ((array) $options['foreignKeys'] as $definition) { + $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); + } + } + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function getDefaultValueDeclarationSQL($field) + { + // Unset the default value if the given field definition does not allow default values. + if ($field['type'] instanceof TextType || $field['type'] instanceof BlobType) { + $field['default'] = null; + } + + return parent::getDefaultValueDeclarationSQL($field); + } + + /** + * Build SQL for table options + * + * @param mixed[] $options + * + * @return string + */ + private function buildTableOptions(array $options) + { + if (isset($options['table_options'])) { + return $options['table_options']; + } + + $tableOptions = []; + + // Charset + if (! isset($options['charset'])) { + $options['charset'] = 'utf8'; + } + + $tableOptions[] = sprintf('DEFAULT CHARACTER SET %s', $options['charset']); + + // Collate + if (! isset($options['collate'])) { + $options['collate'] = $options['charset'] . '_unicode_ci'; + } + + $tableOptions[] = $this->getColumnCollationDeclarationSQL($options['collate']); + + // Engine + if (! isset($options['engine'])) { + $options['engine'] = 'InnoDB'; + } + + $tableOptions[] = sprintf('ENGINE = %s', $options['engine']); + + // Auto increment + if (isset($options['auto_increment'])) { + $tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']); + } + + // Comment + if (isset($options['comment'])) { + $tableOptions[] = sprintf('COMMENT = %s ', $this->quoteStringLiteral($options['comment'])); + } + + // Row format + if (isset($options['row_format'])) { + $tableOptions[] = sprintf('ROW_FORMAT = %s', $options['row_format']); + } + + return implode(' ', $tableOptions); + } + + /** + * Build SQL for partition options. + * + * @param mixed[] $options + * + * @return string + */ + private function buildPartitionOptions(array $options) + { + return isset($options['partition_options']) + ? ' ' . $options['partition_options'] + : ''; + } + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $columnSql = []; + $queryParts = []; + $newName = $diff->getNewName(); + + if ($newName !== false) { + $queryParts[] = 'RENAME TO ' . $newName->getQuotedName($this); + } + + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $columnArray = $column->toArray(); + $columnArray['comment'] = $this->getColumnComment($column); + $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); + } + + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $queryParts[] = 'DROP ' . $column->getQuotedName($this); + } + + foreach ($diff->changedColumns as $columnDiff) { + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + $column = $columnDiff->column; + $columnArray = $column->toArray(); + + // Don't propagate default value changes for unsupported column types. + if ($columnDiff->hasChanged('default') && + count($columnDiff->changedProperties) === 1 && + ($columnArray['type'] instanceof TextType || $columnArray['type'] instanceof BlobType) + ) { + continue; + } + + $columnArray['comment'] = $this->getColumnComment($column); + $queryParts[] = 'CHANGE ' . ($columnDiff->getOldColumnName()->getQuotedName($this)) . ' ' + . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $oldColumnName = new Identifier($oldColumnName); + $columnArray = $column->toArray(); + $columnArray['comment'] = $this->getColumnComment($column); + $queryParts[] = 'CHANGE ' . $oldColumnName->getQuotedName($this) . ' ' + . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); + } + + if (isset($diff->addedIndexes['primary'])) { + $keyColumns = array_unique(array_values($diff->addedIndexes['primary']->getColumns())); + $queryParts[] = 'ADD PRIMARY KEY (' . implode(', ', $keyColumns) . ')'; + unset($diff->addedIndexes['primary']); + } elseif (isset($diff->changedIndexes['primary'])) { + // Necessary in case the new primary key includes a new auto_increment column + foreach ($diff->changedIndexes['primary']->getColumns() as $columnName) { + if (isset($diff->addedColumns[$columnName]) && $diff->addedColumns[$columnName]->getAutoincrement()) { + $keyColumns = array_unique(array_values($diff->changedIndexes['primary']->getColumns())); + $queryParts[] = 'DROP PRIMARY KEY'; + $queryParts[] = 'ADD PRIMARY KEY (' . implode(', ', $keyColumns) . ')'; + unset($diff->changedIndexes['primary']); + break; + } + } + } + + $sql = []; + $tableSql = []; + + if (! $this->onSchemaAlterTable($diff, $tableSql)) { + if (count($queryParts) > 0) { + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(', ', $queryParts); + } + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * {@inheritDoc} + */ + protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) + { + $sql = []; + $table = $diff->getName($this)->getQuotedName($this); + + foreach ($diff->changedIndexes as $changedIndex) { + $sql = array_merge($sql, $this->getPreAlterTableAlterPrimaryKeySQL($diff, $changedIndex)); + } + + foreach ($diff->removedIndexes as $remKey => $remIndex) { + $sql = array_merge($sql, $this->getPreAlterTableAlterPrimaryKeySQL($diff, $remIndex)); + + foreach ($diff->addedIndexes as $addKey => $addIndex) { + if ($remIndex->getColumns() === $addIndex->getColumns()) { + $indexClause = 'INDEX ' . $addIndex->getName(); + + if ($addIndex->isPrimary()) { + $indexClause = 'PRIMARY KEY'; + } elseif ($addIndex->isUnique()) { + $indexClause = 'UNIQUE INDEX ' . $addIndex->getName(); + } + + $query = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $remIndex->getName() . ', '; + $query .= 'ADD ' . $indexClause; + $query .= ' (' . $this->getIndexFieldDeclarationListSQL($addIndex) . ')'; + + $sql[] = $query; + + unset($diff->removedIndexes[$remKey], $diff->addedIndexes[$addKey]); + + break; + } + } + } + + $engine = 'INNODB'; + + if ($diff->fromTable instanceof Table && $diff->fromTable->hasOption('engine')) { + $engine = strtoupper(trim($diff->fromTable->getOption('engine'))); + } + + // Suppress foreign key constraint propagation on non-supporting engines. + if ($engine !== 'INNODB') { + $diff->addedForeignKeys = []; + $diff->changedForeignKeys = []; + $diff->removedForeignKeys = []; + } + + $sql = array_merge( + $sql, + $this->getPreAlterTableAlterIndexForeignKeySQL($diff), + parent::getPreAlterTableIndexForeignKeySQL($diff), + $this->getPreAlterTableRenameIndexForeignKeySQL($diff) + ); + + return $sql; + } + + /** + * @return string[] + */ + private function getPreAlterTableAlterPrimaryKeySQL(TableDiff $diff, Index $index) + { + $sql = []; + + if (! $index->isPrimary() || ! $diff->fromTable instanceof Table) { + return $sql; + } + + $tableName = $diff->getName($this)->getQuotedName($this); + + // Dropping primary keys requires to unset autoincrement attribute on the particular column first. + foreach ($index->getColumns() as $columnName) { + if (! $diff->fromTable->hasColumn($columnName)) { + continue; + } + + $column = $diff->fromTable->getColumn($columnName); + + if ($column->getAutoincrement() !== true) { + continue; + } + + $column->setAutoincrement(false); + + $sql[] = 'ALTER TABLE ' . $tableName . ' MODIFY ' . + $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + + // original autoincrement information might be needed later on by other parts of the table alteration + $column->setAutoincrement(true); + } + + return $sql; + } + + /** + * @param TableDiff $diff The table diff to gather the SQL for. + * + * @return string[] + */ + private function getPreAlterTableAlterIndexForeignKeySQL(TableDiff $diff) + { + $sql = []; + $table = $diff->getName($this)->getQuotedName($this); + + foreach ($diff->changedIndexes as $changedIndex) { + // Changed primary key + if (! $changedIndex->isPrimary() || ! ($diff->fromTable instanceof Table)) { + continue; + } + + foreach ($diff->fromTable->getPrimaryKeyColumns() as $columnName) { + $column = $diff->fromTable->getColumn($columnName); + + // Check if an autoincrement column was dropped from the primary key. + if (! $column->getAutoincrement() || in_array($columnName, $changedIndex->getColumns())) { + continue; + } + + // The autoincrement attribute needs to be removed from the dropped column + // before we can drop and recreate the primary key. + $column->setAutoincrement(false); + + $sql[] = 'ALTER TABLE ' . $table . ' MODIFY ' . + $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + + // Restore the autoincrement attribute as it might be needed later on + // by other parts of the table alteration. + $column->setAutoincrement(true); + } + } + + return $sql; + } + + /** + * @param TableDiff $diff The table diff to gather the SQL for. + * + * @return string[] + */ + protected function getPreAlterTableRenameIndexForeignKeySQL(TableDiff $diff) + { + $sql = []; + $tableName = $diff->getName($this)->getQuotedName($this); + + foreach ($this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) as $foreignKey) { + if (in_array($foreignKey, $diff->changedForeignKeys, true)) { + continue; + } + + $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName); + } + + return $sql; + } + + /** + * Returns the remaining foreign key constraints that require one of the renamed indexes. + * + * "Remaining" here refers to the diff between the foreign keys currently defined in the associated + * table and the foreign keys to be removed. + * + * @param TableDiff $diff The table diff to evaluate. + * + * @return ForeignKeyConstraint[] + */ + private function getRemainingForeignKeyConstraintsRequiringRenamedIndexes(TableDiff $diff) + { + if (empty($diff->renamedIndexes) || ! $diff->fromTable instanceof Table) { + return []; + } + + $foreignKeys = []; + /** @var ForeignKeyConstraint[] $remainingForeignKeys */ + $remainingForeignKeys = array_diff_key( + $diff->fromTable->getForeignKeys(), + $diff->removedForeignKeys + ); + + foreach ($remainingForeignKeys as $foreignKey) { + foreach ($diff->renamedIndexes as $index) { + if ($foreignKey->intersectsIndexColumns($index)) { + $foreignKeys[] = $foreignKey; + + break; + } + } + } + + return $foreignKeys; + } + + /** + * {@inheritdoc} + */ + protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) + { + return array_merge( + parent::getPostAlterTableIndexForeignKeySQL($diff), + $this->getPostAlterTableRenameIndexForeignKeySQL($diff) + ); + } + + /** + * @param TableDiff $diff The table diff to gather the SQL for. + * + * @return string[] + */ + protected function getPostAlterTableRenameIndexForeignKeySQL(TableDiff $diff) + { + $sql = []; + $newName = $diff->getNewName(); + + if ($newName !== false) { + $tableName = $newName->getQuotedName($this); + } else { + $tableName = $diff->getName($this)->getQuotedName($this); + } + + foreach ($this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) as $foreignKey) { + if (in_array($foreignKey, $diff->changedForeignKeys, true)) { + continue; + } + + $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); + } + + return $sql; + } + + /** + * {@inheritDoc} + */ + protected function getCreateIndexSQLFlags(Index $index) + { + $type = ''; + if ($index->isUnique()) { + $type .= 'UNIQUE '; + } elseif ($index->hasFlag('fulltext')) { + $type .= 'FULLTEXT '; + } elseif ($index->hasFlag('spatial')) { + $type .= 'SPATIAL '; + } + + return $type; + } + + /** + * {@inheritDoc} + */ + public function getIntegerTypeDeclarationSQL(array $field) + { + return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $field) + { + return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $field) + { + return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritdoc} + */ + public function getFloatDeclarationSQL(array $field) + { + return 'DOUBLE PRECISION' . $this->getUnsignedDeclaration($field); + } + + /** + * {@inheritdoc} + */ + public function getDecimalTypeDeclarationSQL(array $columnDef) + { + return parent::getDecimalTypeDeclarationSQL($columnDef) . $this->getUnsignedDeclaration($columnDef); + } + + /** + * Get unsigned declaration for a column. + * + * @param mixed[] $columnDef + * + * @return string + */ + private function getUnsignedDeclaration(array $columnDef) + { + return ! empty($columnDef['unsigned']) ? ' UNSIGNED' : ''; + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + $autoinc = ''; + if (! empty($columnDef['autoincrement'])) { + $autoinc = ' AUTO_INCREMENT'; + } + + return $this->getUnsignedDeclaration($columnDef) . $autoinc; + } + + /** + * {@inheritDoc} + */ + public function getColumnCharsetDeclarationSQL($charset) + { + return 'CHARACTER SET ' . $charset; + } + + /** + * {@inheritDoc} + */ + public function getColumnCollationDeclarationSQL($collation) + { + return 'COLLATE ' . $this->quoteSingleIdentifier($collation); + } + + /** + * {@inheritDoc} + */ + public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) + { + $query = ''; + if ($foreignKey->hasOption('match')) { + $query .= ' MATCH ' . $foreignKey->getOption('match'); + } + $query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey); + + return $query; + } + + /** + * {@inheritDoc} + */ + public function getDropIndexSQL($index, $table = null) + { + if ($index instanceof Index) { + $indexName = $index->getQuotedName($this); + } elseif (is_string($index)) { + $indexName = $index; + } else { + throw new InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } elseif (! is_string($table)) { + throw new InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); + } + + if ($index instanceof Index && $index->isPrimary()) { + // mysql primary keys are always named "PRIMARY", + // so we cannot use them in statements because of them being keyword. + return $this->getDropPrimaryKeySQL($table); + } + + return 'DROP INDEX ' . $indexName . ' ON ' . $table; + } + + /** + * @param string $table + * + * @return string + */ + protected function getDropPrimaryKeySQL($table) + { + return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; + } + + /** + * {@inheritDoc} + */ + public function getSetTransactionIsolationSQL($level) + { + return 'SET SESSION TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level); + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'mysql'; + } + + /** + * {@inheritDoc} + */ + public function getReadLockSQL() + { + return 'LOCK IN SHARE MODE'; + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = [ + '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' => 'float', + 'double' => 'float', + 'real' => 'float', + 'decimal' => 'decimal', + 'numeric' => 'decimal', + 'year' => 'date', + 'longblob' => 'blob', + 'blob' => 'blob', + 'mediumblob' => 'blob', + 'tinyblob' => 'blob', + 'binary' => 'binary', + 'varbinary' => 'binary', + 'set' => 'simple_array', + ]; + } + + /** + * {@inheritDoc} + */ + public function getVarcharMaxLength() + { + return 65535; + } + + /** + * {@inheritdoc} + */ + public function getBinaryMaxLength() + { + return 65535; + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return Keywords\MySQLKeywords::class; + } + + /** + * {@inheritDoc} + * + * MySQL commits a transaction implicitly when DROP TABLE is executed, however not + * if DROP TEMPORARY TABLE is executed. + */ + public function getDropTemporaryTableSQL($table) + { + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } elseif (! is_string($table)) { + throw new InvalidArgumentException('getDropTemporaryTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); + } + + return 'DROP TEMPORARY TABLE ' . $table; + } + + /** + * Gets the SQL Snippet used to declare a BLOB column type. + * TINYBLOB : 2 ^ 8 - 1 = 255 + * BLOB : 2 ^ 16 - 1 = 65535 + * MEDIUMBLOB : 2 ^ 24 - 1 = 16777215 + * LONGBLOB : 2 ^ 32 - 1 = 4294967295 + * + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + if (! empty($field['length']) && is_numeric($field['length'])) { + $length = $field['length']; + + if ($length <= static::LENGTH_LIMIT_TINYBLOB) { + return 'TINYBLOB'; + } + + if ($length <= static::LENGTH_LIMIT_BLOB) { + return 'BLOB'; + } + + if ($length <= static::LENGTH_LIMIT_MEDIUMBLOB) { + return 'MEDIUMBLOB'; + } + } + + return 'LONGBLOB'; + } + + /** + * {@inheritdoc} + */ + public function quoteStringLiteral($str) + { + $str = str_replace('\\', '\\\\', $str); // MySQL requires backslashes to be escaped aswell. + + return parent::quoteStringLiteral($str); + } + + /** + * {@inheritdoc} + */ + public function getDefaultTransactionIsolationLevel() + { + return TransactionIsolationLevel::REPEATABLE_READ; + } + + /** + * {@inheritdoc} + */ + public function supportsColumnLengthIndexes() : bool + { + return true; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/OraclePlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/OraclePlatform.php new file mode 100644 index 0000000..21b13a2 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/OraclePlatform.php @@ -0,0 +1,1206 @@ +getBitAndComparisonExpression($value1, $value2) + . '+' . $value2 . ')'; + } + + /** + * {@inheritDoc} + * + * 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()} + */ + public function getCreateSequenceSQL(Sequence $sequence) + { + return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . + ' START WITH ' . $sequence->getInitialValue() . + ' MINVALUE ' . $sequence->getInitialValue() . + ' INCREMENT BY ' . $sequence->getAllocationSize() . + $this->getSequenceCacheSQL($sequence); + } + + /** + * {@inheritDoc} + */ + public function getAlterSequenceSQL(Sequence $sequence) + { + return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . + ' INCREMENT BY ' . $sequence->getAllocationSize() + . $this->getSequenceCacheSQL($sequence); + } + + /** + * Cache definition for sequences + * + * @return string + */ + private function getSequenceCacheSQL(Sequence $sequence) + { + if ($sequence->getCache() === 0) { + return ' NOCACHE'; + } + + if ($sequence->getCache() === 1) { + return ' NOCACHE'; + } + + if ($sequence->getCache() > 1) { + return ' CACHE ' . $sequence->getCache(); + } + + return ''; + } + + /** + * {@inheritDoc} + */ + public function getSequenceNextValSQL($sequenceName) + { + return 'SELECT ' . $sequenceName . '.nextval FROM DUAL'; + } + + /** + * {@inheritDoc} + */ + public function getSetTransactionIsolationSQL($level) + { + return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level); + } + + /** + * {@inheritDoc} + */ + protected function _getTransactionIsolationLevelSQL($level) + { + switch ($level) { + case TransactionIsolationLevel::READ_UNCOMMITTED: + return 'READ UNCOMMITTED'; + case TransactionIsolationLevel::READ_COMMITTED: + return 'READ COMMITTED'; + case TransactionIsolationLevel::REPEATABLE_READ: + case TransactionIsolationLevel::SERIALIZABLE: + return 'SERIALIZABLE'; + default: + return parent::_getTransactionIsolationLevelSQL($level); + } + } + + /** + * {@inheritDoc} + */ + public function getBooleanTypeDeclarationSQL(array $field) + { + return 'NUMBER(1)'; + } + + /** + * {@inheritDoc} + */ + public function getIntegerTypeDeclarationSQL(array $field) + { + return 'NUMBER(10)'; + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $field) + { + return 'NUMBER(20)'; + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $field) + { + return 'NUMBER(5)'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIMESTAMP(0)'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIMESTAMP(0) WITH TIME ZONE'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + return ''; + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(2000)') + : ($length ? 'VARCHAR2(' . $length . ')' : 'VARCHAR2(4000)'); + } + + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return 'RAW(' . ($length ?: $this->getBinaryMaxLength()) . ')'; + } + + /** + * {@inheritdoc} + */ + public function getBinaryMaxLength() + { + return 2000; + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + return 'CLOB'; + } + + /** + * {@inheritDoc} + */ + public function getListDatabasesSQL() + { + return 'SELECT username FROM all_users'; + } + + /** + * {@inheritDoc} + */ + public function getListSequencesSQL($database) + { + $database = $this->normalizeIdentifier($database); + $database = $this->quoteStringLiteral($database->getName()); + + return 'SELECT sequence_name, min_value, increment_by FROM sys.all_sequences ' . + 'WHERE SEQUENCE_OWNER = ' . $database; + } + + /** + * {@inheritDoc} + */ + protected function _getCreateTableSQL($table, array $columns, array $options = []) + { + $indexes = $options['indexes'] ?? []; + $options['indexes'] = []; + $sql = parent::_getCreateTableSQL($table, $columns, $options); + + foreach ($columns as $name => $column) { + if (isset($column['sequence'])) { + $sql[] = $this->getCreateSequenceSQL($column['sequence']); + } + + if (! isset($column['autoincrement']) || ! $column['autoincrement'] && + (! isset($column['autoinc']) || ! $column['autoinc'])) { + continue; + } + + $sql = array_merge($sql, $this->getCreateAutoincrementSql($name, $table)); + } + + if (isset($indexes) && ! empty($indexes)) { + foreach ($indexes as $index) { + $sql[] = $this->getCreateIndexSQL($index, $table); + } + } + + return $sql; + } + + /** + * {@inheritDoc} + * + * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaOracleReader.html + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + $table = $this->normalizeIdentifier($table); + $table = $this->quoteStringLiteral($table->getName()); + + return "SELECT uind_col.index_name AS name, + ( + SELECT uind.index_type + FROM user_indexes uind + WHERE uind.index_name = uind_col.index_name + ) AS type, + decode( + ( + SELECT uind.uniqueness + FROM user_indexes uind + WHERE uind.index_name = uind_col.index_name + ), + '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.index_name = uind_col.index_name + ) AS is_primary + FROM user_ind_columns uind_col + WHERE uind_col.table_name = " . $table . ' + ORDER BY uind_col.column_position ASC'; + } + + /** + * {@inheritDoc} + */ + public function getListTablesSQL() + { + return 'SELECT * FROM sys.user_tables'; + } + + /** + * {@inheritDoc} + */ + public function getListViewsSQL($database) + { + return 'SELECT view_name, text FROM sys.user_views'; + } + + /** + * {@inheritDoc} + */ + public function getCreateViewSQL($name, $sql) + { + return 'CREATE VIEW ' . $name . ' AS ' . $sql; + } + + /** + * {@inheritDoc} + */ + public function getDropViewSQL($name) + { + return 'DROP VIEW ' . $name; + } + + /** + * @param string $name + * @param string $table + * @param int $start + * + * @return string[] + */ + public function getCreateAutoincrementSql($name, $table, $start = 1) + { + $tableIdentifier = $this->normalizeIdentifier($table); + $quotedTableName = $tableIdentifier->getQuotedName($this); + $unquotedTableName = $tableIdentifier->getName(); + + $nameIdentifier = $this->normalizeIdentifier($name); + $quotedName = $nameIdentifier->getQuotedName($this); + $unquotedName = $nameIdentifier->getName(); + + $sql = []; + + $autoincrementIdentifierName = $this->getAutoincrementIdentifierName($tableIdentifier); + + $idx = new Index($autoincrementIdentifierName, [$quotedName], true, true); + + $sql[] = 'DECLARE + constraints_Count NUMBER; +BEGIN + SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = \'' . $unquotedTableName . '\' AND CONSTRAINT_TYPE = \'P\'; + IF constraints_Count = 0 OR constraints_Count = \'\' THEN + EXECUTE IMMEDIATE \'' . $this->getCreateConstraintSQL($idx, $quotedTableName) . '\'; + END IF; +END;'; + + $sequenceName = $this->getIdentitySequenceName( + $tableIdentifier->isQuoted() ? $quotedTableName : $unquotedTableName, + $nameIdentifier->isQuoted() ? $quotedName : $unquotedName + ); + $sequence = new Sequence($sequenceName, $start); + $sql[] = $this->getCreateSequenceSQL($sequence); + + $sql[] = 'CREATE TRIGGER ' . $autoincrementIdentifierName . ' + BEFORE INSERT + ON ' . $quotedTableName . ' + FOR EACH ROW +DECLARE + last_Sequence NUMBER; + last_InsertID NUMBER; +BEGIN + SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $quotedName . ' FROM DUAL; + IF (:NEW.' . $quotedName . ' IS NULL OR :NEW.' . $quotedName . ' = 0) THEN + SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $quotedName . ' FROM DUAL; + ELSE + SELECT NVL(Last_Number, 0) INTO last_Sequence + FROM User_Sequences + WHERE Sequence_Name = \'' . $sequence->getName() . '\'; + SELECT :NEW.' . $quotedName . ' 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; + } + + /** + * Returns the SQL statements to drop the autoincrement for the given table name. + * + * @param string $table The table name to drop the autoincrement for. + * + * @return string[] + */ + public function getDropAutoincrementSql($table) + { + $table = $this->normalizeIdentifier($table); + $autoincrementIdentifierName = $this->getAutoincrementIdentifierName($table); + $identitySequenceName = $this->getIdentitySequenceName( + $table->isQuoted() ? $table->getQuotedName($this) : $table->getName(), + '' + ); + + return [ + 'DROP TRIGGER ' . $autoincrementIdentifierName, + $this->getDropSequenceSQL($identitySequenceName), + $this->getDropConstraintSQL($autoincrementIdentifierName, $table->getQuotedName($this)), + ]; + } + + /** + * Normalizes the given identifier. + * + * Uppercases the given identifier if it is not quoted by intention + * to reflect Oracle's internal auto uppercasing strategy of unquoted identifiers. + * + * @param string $name The identifier to normalize. + * + * @return Identifier The normalized identifier. + */ + private function normalizeIdentifier($name) + { + $identifier = new Identifier($name); + + return $identifier->isQuoted() ? $identifier : new Identifier(strtoupper($name)); + } + + /** + * Returns the autoincrement primary key identifier name for the given table identifier. + * + * Quotes the autoincrement primary key identifier name + * if the given table name is quoted by intention. + * + * @param Identifier $table The table identifier to return the autoincrement primary key identifier name for. + * + * @return string + */ + private function getAutoincrementIdentifierName(Identifier $table) + { + $identifierName = $table->getName() . '_AI_PK'; + + return $table->isQuoted() + ? $this->quoteSingleIdentifier($identifierName) + : $identifierName; + } + + /** + * {@inheritDoc} + */ + public function getListTableForeignKeysSQL($table) + { + $table = $this->normalizeIdentifier($table); + $table = $this->quoteStringLiteral($table->getName()); + + return "SELECT alc.constraint_name, + alc.DELETE_RULE, + cols.column_name \"local_column\", + cols.position, + ( + SELECT r_cols.table_name + FROM user_cons_columns r_cols + WHERE alc.r_constraint_name = r_cols.constraint_name + AND r_cols.position = cols.position + ) AS \"references_table\", + ( + SELECT r_cols.column_name + FROM user_cons_columns r_cols + WHERE alc.r_constraint_name = r_cols.constraint_name + AND r_cols.position = cols.position + ) AS \"foreign_column\" + FROM user_cons_columns cols + JOIN user_constraints alc + ON alc.constraint_name = cols.constraint_name + AND alc.constraint_type = 'R' + AND alc.table_name = " . $table . ' + ORDER BY cols.constraint_name ASC, cols.position ASC'; + } + + /** + * {@inheritDoc} + */ + public function getListTableConstraintsSQL($table) + { + $table = $this->normalizeIdentifier($table); + $table = $this->quoteStringLiteral($table->getName()); + + return 'SELECT * FROM user_constraints WHERE table_name = ' . $table; + } + + /** + * {@inheritDoc} + */ + public function getListTableColumnsSQL($table, $database = null) + { + $table = $this->normalizeIdentifier($table); + $table = $this->quoteStringLiteral($table->getName()); + + $tabColumnsTableName = 'user_tab_columns'; + $colCommentsTableName = 'user_col_comments'; + $tabColumnsOwnerCondition = ''; + $colCommentsOwnerCondition = ''; + + if ($database !== null && $database !== '/') { + $database = $this->normalizeIdentifier($database); + $database = $this->quoteStringLiteral($database->getName()); + $tabColumnsTableName = 'all_tab_columns'; + $colCommentsTableName = 'all_col_comments'; + $tabColumnsOwnerCondition = ' AND c.owner = ' . $database; + $colCommentsOwnerCondition = ' AND d.OWNER = c.OWNER'; + } + + return sprintf( + <<<'SQL' +SELECT c.*, + ( + SELECT d.comments + FROM %s d + WHERE d.TABLE_NAME = c.TABLE_NAME%s + AND d.COLUMN_NAME = c.COLUMN_NAME + ) AS comments +FROM %s c +WHERE c.table_name = %s%s +ORDER BY c.column_id +SQL + , + $colCommentsTableName, + $colCommentsOwnerCondition, + $tabColumnsTableName, + $table, + $tabColumnsOwnerCondition + ); + } + + /** + * {@inheritDoc} + */ + public function getDropSequenceSQL($sequence) + { + if ($sequence instanceof Sequence) { + $sequence = $sequence->getQuotedName($this); + } + + return 'DROP SEQUENCE ' . $sequence; + } + + /** + * {@inheritDoc} + */ + public function getDropForeignKeySQL($foreignKey, $table) + { + if (! $foreignKey instanceof ForeignKeyConstraint) { + $foreignKey = new Identifier($foreignKey); + } + + if (! $table instanceof Table) { + $table = new Identifier($table); + } + + $foreignKey = $foreignKey->getQuotedName($this); + $table = $table->getQuotedName($this); + + return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey; + } + + /** + * {@inheritdoc} + */ + public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) + { + $referentialAction = null; + + if ($foreignKey->hasOption('onDelete')) { + $referentialAction = $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete')); + } + + return $referentialAction ? ' ON DELETE ' . $referentialAction : ''; + } + + /** + * {@inheritdoc} + */ + public function getForeignKeyReferentialActionSQL($action) + { + $action = strtoupper($action); + + switch ($action) { + case 'RESTRICT': // RESTRICT is not supported, therefore falling back to NO ACTION. + case 'NO ACTION': + // NO ACTION cannot be declared explicitly, + // therefore returning empty string to indicate to OMIT the referential clause. + return ''; + + case 'CASCADE': + case 'SET NULL': + return $action; + + default: + // SET DEFAULT is not supported, throw exception instead. + throw new InvalidArgumentException('Invalid foreign key action: ' . $action); + } + } + + /** + * {@inheritDoc} + */ + public function getDropDatabaseSQL($database) + { + return 'DROP USER ' . $database . ' CASCADE'; + } + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $sql = []; + $commentsSQL = []; + $columnSql = []; + + $fields = []; + + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $fields[] = $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + $comment = $this->getColumnComment($column); + + if (! $comment) { + continue; + } + + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), + $comment + ); + } + + if (count($fields)) { + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ADD (' . implode(', ', $fields) . ')'; + } + + $fields = []; + foreach ($diff->changedColumns as $columnDiff) { + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + $column = $columnDiff->column; + + // Do not generate column alteration clause if type is binary and only fixed property has changed. + // Oracle only supports binary type columns with variable length. + // Avoids unnecessary table alteration statements. + if ($column->getType() instanceof BinaryType && + $columnDiff->hasChanged('fixed') && + count($columnDiff->changedProperties) === 1 + ) { + continue; + } + + $columnHasChangedComment = $columnDiff->hasChanged('comment'); + + /** + * Do not add query part if only comment has changed + */ + if (! ($columnHasChangedComment && count($columnDiff->changedProperties) === 1)) { + $columnInfo = $column->toArray(); + + if (! $columnDiff->hasChanged('notnull')) { + unset($columnInfo['notnull']); + } + + $fields[] = $column->getQuotedName($this) . $this->getColumnDeclarationSQL('', $columnInfo); + } + + if (! $columnHasChangedComment) { + continue; + } + + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), + $this->getColumnComment($column) + ); + } + + if (count($fields)) { + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' MODIFY (' . implode(', ', $fields) . ')'; + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $oldColumnName = new Identifier($oldColumnName); + + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . + ' RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . ' TO ' . $column->getQuotedName($this); + } + + $fields = []; + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $fields[] = $column->getQuotedName($this); + } + + if (count($fields)) { + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' DROP (' . implode(', ', $fields) . ')'; + } + + $tableSql = []; + + if (! $this->onSchemaAlterTable($diff, $tableSql)) { + $sql = array_merge($sql, $commentsSQL); + + $newName = $diff->getNewName(); + + if ($newName !== false) { + $sql[] = sprintf( + 'ALTER TABLE %s RENAME TO %s', + $diff->getName($this)->getQuotedName($this), + $newName->getQuotedName($this) + ); + } + + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * {@inheritdoc} + */ + public function getColumnDeclarationSQL($name, array $field) + { + if (isset($field['columnDefinition'])) { + $columnDef = $this->getCustomTypeDeclarationSQL($field); + } else { + $default = $this->getDefaultValueDeclarationSQL($field); + + $notnull = ''; + + if (isset($field['notnull'])) { + $notnull = $field['notnull'] ? ' NOT NULL' : ' 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 . $default . $notnull . $unique . $check; + } + + return $name . ' ' . $columnDef; + } + + /** + * {@inheritdoc} + */ + protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) + { + if (strpos($tableName, '.') !== false) { + [$schema] = explode('.', $tableName); + $oldIndexName = $schema . '.' . $oldIndexName; + } + + return ['ALTER INDEX ' . $oldIndexName . ' RENAME TO ' . $index->getQuotedName($this)]; + } + + /** + * {@inheritDoc} + */ + public function prefersSequences() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function usesSequenceEmulatedIdentityColumns() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getIdentitySequenceName($tableName, $columnName) + { + $table = new Identifier($tableName); + + // No usage of column name to preserve BC compatibility with <2.5 + $identitySequenceName = $table->getName() . '_SEQ'; + + if ($table->isQuoted()) { + $identitySequenceName = '"' . $identitySequenceName . '"'; + } + + $identitySequenceIdentifier = $this->normalizeIdentifier($identitySequenceName); + + return $identitySequenceIdentifier->getQuotedName($this); + } + + /** + * {@inheritDoc} + */ + public function supportsCommentOnStatement() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'oracle'; + } + + /** + * {@inheritDoc} + */ + protected function doModifyLimitQuery($query, $limit, $offset = null) + { + if ($limit === null && $offset <= 0) { + return $query; + } + + if (preg_match('/^\s*SELECT/i', $query)) { + if (! preg_match('/\sFROM\s/i', $query)) { + $query .= ' FROM dual'; + } + + $columns = ['a.*']; + + if ($offset > 0) { + $columns[] = 'ROWNUM AS doctrine_rownum'; + } + + $query = sprintf('SELECT %s FROM (%s) a', implode(', ', $columns), $query); + + if ($limit !== null) { + $query .= sprintf(' WHERE ROWNUM <= %d', $offset + $limit); + } + + if ($offset > 0) { + $query = sprintf('SELECT * FROM (%s) WHERE doctrine_rownum >= %d', $query, $offset + 1); + } + } + + return $query; + } + + /** + * {@inheritDoc} + * + * Oracle returns all column names in SQL result sets in uppercase. + */ + public function getSQLResultCasing($column) + { + return strtoupper($column); + } + + /** + * {@inheritDoc} + */ + public function getCreateTemporaryTableSnippetSQL() + { + return 'CREATE GLOBAL TEMPORARY TABLE'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTzFormatString() + { + return 'Y-m-d H:i:sP'; + } + + /** + * {@inheritDoc} + */ + public function getDateFormatString() + { + return 'Y-m-d 00:00:00'; + } + + /** + * {@inheritDoc} + */ + public function getTimeFormatString() + { + return '1900-01-01 H:i:s'; + } + + /** + * {@inheritDoc} + */ + public function fixSchemaElementName($schemaElementName) + { + if (strlen($schemaElementName) > 30) { + // Trim it + return substr($schemaElementName, 0, 30); + } + + return $schemaElementName; + } + + /** + * {@inheritDoc} + */ + public function getMaxIdentifierLength() + { + return 30; + } + + /** + * {@inheritDoc} + */ + public function supportsSequences() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsForeignKeyOnUpdate() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function supportsReleaseSavepoints() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function getTruncateTableSQL($tableName, $cascade = false) + { + $tableIdentifier = new Identifier($tableName); + + return 'TRUNCATE TABLE ' . $tableIdentifier->getQuotedName($this); + } + + /** + * {@inheritDoc} + */ + public function getDummySelectSQL() + { + $expression = func_num_args() > 0 ? func_get_arg(0) : '1'; + + return sprintf('SELECT %s FROM DUAL', $expression); + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = [ + 'integer' => 'integer', + 'number' => 'integer', + 'pls_integer' => 'boolean', + 'binary_integer' => 'boolean', + 'varchar' => 'string', + 'varchar2' => 'string', + 'nvarchar2' => 'string', + 'char' => 'string', + 'nchar' => 'string', + 'date' => 'date', + 'timestamp' => 'datetime', + 'timestamptz' => 'datetimetz', + 'float' => 'float', + 'binary_float' => 'float', + 'binary_double' => 'float', + 'long' => 'string', + 'clob' => 'text', + 'nclob' => 'text', + 'raw' => 'binary', + 'long raw' => 'blob', + 'rowid' => 'string', + 'urowid' => 'string', + 'blob' => 'blob', + ]; + } + + /** + * {@inheritDoc} + */ + public function releaseSavePoint($savepoint) + { + return ''; + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return Keywords\OracleKeywords::class; + } + + /** + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + return 'BLOB'; + } + + public function getListTableCommentsSQL(string $table, ?string $database = null) : string + { + $tableCommentsName = 'user_tab_comments'; + $ownerCondition = ''; + + if ($database !== null && $database !== '/') { + $tableCommentsName = 'all_tab_comments'; + $ownerCondition = ' AND owner = ' . $this->quoteStringLiteral($this->normalizeIdentifier($database)->getName()); + } + + return sprintf( + <<<'SQL' +SELECT comments FROM %s WHERE table_name = %s%s +SQL + , + $tableCommentsName, + $this->quoteStringLiteral($this->normalizeIdentifier($table)->getName()), + $ownerCondition + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL100Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL100Platform.php new file mode 100644 index 0000000..cfb079f --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL100Platform.php @@ -0,0 +1,33 @@ +quoteStringLiteral($database) . " + AND sequence_schema NOT LIKE 'pg\_%' + AND sequence_schema != 'information_schema'"; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php new file mode 100644 index 0000000..f558409 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php @@ -0,0 +1,46 @@ +quoteSingleIdentifier($collation); + } + + /** + * {@inheritDoc} + */ + public function getListTableColumnsSQL($table, $database = null) + { + $sql = parent::getListTableColumnsSQL($table, $database); + $parts = explode('AS complete_type,', $sql, 2); + + return $parts[0] . 'AS complete_type, (SELECT tc.collcollate FROM pg_catalog.pg_collation tc WHERE tc.oid = a.attcollation) AS collation,' . $parts[1]; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php new file mode 100644 index 0000000..1703056 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php @@ -0,0 +1,69 @@ +doctrineTypeMapping['json'] = Types::JSON; + } + + /** + * {@inheritdoc} + */ + public function getCloseActiveDatabaseConnectionsSQL($database) + { + return sprintf( + 'SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = %s', + $this->quoteStringLiteral($database) + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL94Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL94Platform.php new file mode 100644 index 0000000..fb559de --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL94Platform.php @@ -0,0 +1,41 @@ +doctrineTypeMapping['jsonb'] = Types::JSON; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php new file mode 100644 index 0000000..e570dc0 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php @@ -0,0 +1,1270 @@ + [ + 't', + 'true', + 'y', + 'yes', + 'on', + '1', + ], + 'false' => [ + 'f', + 'false', + 'n', + 'no', + 'off', + '0', + ], + ]; + + /** + * PostgreSQL has different behavior with some drivers + * with regard to how booleans have to be handled. + * + * Enables use of 'true'/'false' or otherwise 1 and 0 instead. + * + * @param bool $flag + */ + public function setUseBooleanTrueFalseStrings($flag) + { + $this->useBooleanTrueFalseStrings = (bool) $flag; + } + + /** + * {@inheritDoc} + */ + public function getSubstringExpression($value, $from, $length = null) + { + if ($length === null) { + return 'SUBSTRING(' . $value . ' FROM ' . $from . ')'; + } + + return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $length . ')'; + } + + /** + * {@inheritDoc} + */ + public function getNowExpression() + { + return 'LOCALTIMESTAMP(0)'; + } + + /** + * {@inheritDoc} + */ + public function getRegexpExpression() + { + return 'SIMILAR TO'; + } + + /** + * {@inheritDoc} + */ + 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'; + } + + return 'POSITION(' . $substr . ' IN ' . $str . ')'; + } + + /** + * {@inheritdoc} + */ + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + { + if ($unit === DateIntervalUnit::QUARTER) { + $interval *= 3; + $unit = DateIntervalUnit::MONTH; + } + + return '(' . $date . ' ' . $operator . ' (' . $interval . " || ' " . $unit . "')::interval)"; + } + + /** + * {@inheritDoc} + */ + public function getDateDiffExpression($date1, $date2) + { + return '(DATE(' . $date1 . ')-DATE(' . $date2 . '))'; + } + + /** + * {@inheritDoc} + */ + public function supportsSequences() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsSchemas() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getDefaultSchemaName() + { + return 'public'; + } + + /** + * {@inheritDoc} + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function supportsPartialIndexes() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function usesSequenceEmulatedIdentityColumns() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getIdentitySequenceName($tableName, $columnName) + { + return $tableName . '_' . $columnName . '_seq'; + } + + /** + * {@inheritDoc} + */ + public function supportsCommentOnStatement() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function prefersSequences() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function hasNativeGuidType() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getListDatabasesSQL() + { + return 'SELECT datname FROM pg_database'; + } + + /** + * {@inheritDoc} + */ + public function getListNamespacesSQL() + { + return "SELECT schema_name AS nspname + FROM information_schema.schemata + WHERE schema_name NOT LIKE 'pg\_%' + AND schema_name != 'information_schema'"; + } + + /** + * {@inheritDoc} + */ + public function getListSequencesSQL($database) + { + return "SELECT sequence_name AS relname, + sequence_schema AS schemaname + FROM information_schema.sequences + WHERE sequence_schema NOT LIKE 'pg\_%' + AND sequence_schema != 'information_schema'"; + } + + /** + * {@inheritDoc} + */ + public function getListTablesSQL() + { + return "SELECT quote_ident(table_name) AS table_name, + table_schema AS schema_name + FROM information_schema.tables + WHERE table_schema NOT LIKE 'pg\_%' + AND table_schema != 'information_schema' + AND table_name != 'geometry_columns' + AND table_name != 'spatial_ref_sys' + AND table_type != 'VIEW'"; + } + + /** + * {@inheritDoc} + */ + public function getListViewsSQL($database) + { + return 'SELECT quote_ident(table_name) AS viewname, + table_schema AS schemaname, + view_definition AS definition + FROM information_schema.views + WHERE view_definition IS NOT NULL'; + } + + /** + * {@inheritDoc} + */ + public function getListTableForeignKeysSQL($table, $database = null) + { + return 'SELECT quote_ident(r.conname) as 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, pg_catalog.pg_namespace n + WHERE ' . $this->getTableWhereClause($table) . " AND n.oid = c.relnamespace + ) + AND r.contype = 'f'"; + } + + /** + * {@inheritDoc} + */ + public function getCreateViewSQL($name, $sql) + { + return 'CREATE VIEW ' . $name . ' AS ' . $sql; + } + + /** + * {@inheritDoc} + */ + public function getDropViewSQL($name) + { + return 'DROP VIEW ' . $name; + } + + /** + * {@inheritDoc} + */ + public function getListTableConstraintsSQL($table) + { + $table = new Identifier($table); + $table = $this->quoteStringLiteral($table->getName()); + + return sprintf( + <<<'SQL' +SELECT + quote_ident(relname) as relname +FROM + pg_class +WHERE oid IN ( + SELECT indexrelid + FROM pg_index, pg_class + WHERE pg_class.relname = %s + AND pg_class.oid = pg_index.indrelid + AND (indisunique = 't' OR indisprimary = 't') + ) +SQL + , + $table + ); + } + + /** + * {@inheritDoc} + * + * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + return 'SELECT quote_ident(relname) as relname, pg_index.indisunique, pg_index.indisprimary, + pg_index.indkey, pg_index.indrelid, + pg_get_expr(indpred, indrelid) AS where + FROM pg_class, pg_index + WHERE oid IN ( + SELECT indexrelid + FROM pg_index si, pg_class sc, pg_namespace sn + WHERE ' . $this->getTableWhereClause($table, 'sc', 'sn') . ' AND sc.oid=si.indrelid AND sc.relnamespace = sn.oid + ) AND pg_index.indexrelid = oid'; + } + + /** + * @param string $table + * @param string $classAlias + * @param string $namespaceAlias + * + * @return string + */ + private function getTableWhereClause($table, $classAlias = 'c', $namespaceAlias = 'n') + { + $whereClause = $namespaceAlias . ".nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast') AND "; + if (strpos($table, '.') !== false) { + [$schema, $table] = explode('.', $table); + $schema = $this->quoteStringLiteral($schema); + } else { + $schema = "ANY(string_to_array((select replace(replace(setting,'\"\$user\"',user),' ','') from pg_catalog.pg_settings where name = 'search_path'),','))"; + } + + $table = new Identifier($table); + $table = $this->quoteStringLiteral($table->getName()); + + return $whereClause . sprintf( + '%s.relname = %s AND %s.nspname = %s', + $classAlias, + $table, + $namespaceAlias, + $schema + ); + } + + /** + * {@inheritDoc} + */ + public function getListTableColumnsSQL($table, $database = null) + { + return "SELECT + a.attnum, + quote_ident(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.oid = a.atttypid) 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_get_expr(adbin, adrelid) + FROM pg_attrdef + WHERE c.oid = pg_attrdef.adrelid + AND pg_attrdef.adnum=a.attnum + ) AS default, + (SELECT pg_description.description + FROM pg_description WHERE pg_description.objoid = c.oid AND a.attnum = pg_description.objsubid + ) AS comment + FROM pg_attribute a, pg_class c, pg_type t, pg_namespace n + WHERE " . $this->getTableWhereClause($table, 'c', 'n') . ' + AND a.attnum > 0 + AND a.attrelid = c.oid + AND a.atttypid = t.oid + AND n.oid = c.relnamespace + ORDER BY a.attnum'; + } + + /** + * {@inheritDoc} + */ + public function getCreateDatabaseSQL($name) + { + return 'CREATE DATABASE ' . $name; + } + + /** + * Returns the SQL statement for disallowing new connections on the given database. + * + * This is useful to force DROP DATABASE operations which could fail because of active connections. + * + * @param string $database The name of the database to disallow new connections for. + * + * @return string + */ + public function getDisallowDatabaseConnectionsSQL($database) + { + return "UPDATE pg_database SET datallowconn = 'false' WHERE datname = " . $this->quoteStringLiteral($database); + } + + /** + * Returns the SQL statement for closing currently active connections on the given database. + * + * This is useful to force DROP DATABASE operations which could fail because of active connections. + * + * @param string $database The name of the database to close currently active connections for. + * + * @return string + */ + public function getCloseActiveDatabaseConnectionsSQL($database) + { + return 'SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE datname = ' + . $this->quoteStringLiteral($database); + } + + /** + * {@inheritDoc} + */ + public function getAdvancedForeignKeyOptionsSQL(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) + || ($foreignKey->hasOption('deferred') && $foreignKey->getOption('deferred') !== false) + ) { + $query .= ' INITIALLY DEFERRED'; + } else { + $query .= ' INITIALLY IMMEDIATE'; + } + + return $query; + } + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $sql = []; + $commentsSQL = []; + $columnSql = []; + + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $query = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; + + $comment = $this->getColumnComment($column); + + if ($comment === null || $comment === '') { + continue; + } + + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), + $comment + ); + } + + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $query = 'DROP ' . $column->getQuotedName($this); + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; + } + + foreach ($diff->changedColumns as $columnDiff) { + /** @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + if ($this->isUnchangedBinaryColumn($columnDiff)) { + continue; + } + + $oldColumnName = $columnDiff->getOldColumnName()->getQuotedName($this); + $column = $columnDiff->column; + + if ($columnDiff->hasChanged('type') || $columnDiff->hasChanged('precision') || $columnDiff->hasChanged('scale') || $columnDiff->hasChanged('fixed')) { + $type = $column->getType(); + + // SERIAL/BIGSERIAL are not "real" types and we can't alter a column to that type + $columnDefinition = $column->toArray(); + $columnDefinition['autoincrement'] = false; + + // here was a server version check before, but DBAL API does not support this anymore. + $query = 'ALTER ' . $oldColumnName . ' TYPE ' . $type->getSQLDeclaration($columnDefinition, $this); + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; + } + + if ($columnDiff->hasChanged('default') || $this->typeChangeBreaksDefaultValue($columnDiff)) { + $defaultClause = $column->getDefault() === null + ? ' DROP DEFAULT' + : ' SET' . $this->getDefaultValueDeclarationSQL($column->toArray()); + $query = 'ALTER ' . $oldColumnName . $defaultClause; + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; + } + + if ($columnDiff->hasChanged('notnull')) { + $query = 'ALTER ' . $oldColumnName . ' ' . ($column->getNotnull() ? 'SET' : 'DROP') . ' NOT NULL'; + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; + } + + if ($columnDiff->hasChanged('autoincrement')) { + if ($column->getAutoincrement()) { + // add autoincrement + $seqName = $this->getIdentitySequenceName($diff->name, $oldColumnName); + + $sql[] = 'CREATE SEQUENCE ' . $seqName; + $sql[] = "SELECT setval('" . $seqName . "', (SELECT MAX(" . $oldColumnName . ') FROM ' . $diff->getName($this)->getQuotedName($this) . '))'; + $query = 'ALTER ' . $oldColumnName . " SET DEFAULT nextval('" . $seqName . "')"; + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $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->getName($this)->getQuotedName($this) . ' ' . $query; + } + } + + $newComment = $this->getColumnComment($column); + $oldComment = $this->getOldColumnComment($columnDiff); + + if ($columnDiff->hasChanged('comment') || ($columnDiff->fromColumn !== null && $oldComment !== $newComment)) { + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), + $newComment + ); + } + + if (! $columnDiff->hasChanged('length')) { + continue; + } + + $query = 'ALTER ' . $oldColumnName . ' TYPE ' . $column->getType()->getSQLDeclaration($column->toArray(), $this); + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $oldColumnName = new Identifier($oldColumnName); + + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . + ' RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . ' TO ' . $column->getQuotedName($this); + } + + $tableSql = []; + + if (! $this->onSchemaAlterTable($diff, $tableSql)) { + $sql = array_merge($sql, $commentsSQL); + + $newName = $diff->getNewName(); + + if ($newName !== false) { + $sql[] = sprintf( + 'ALTER TABLE %s RENAME TO %s', + $diff->getName($this)->getQuotedName($this), + $newName->getQuotedName($this) + ); + } + + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * Checks whether a given column diff is a logically unchanged binary type column. + * + * Used to determine whether a column alteration for a binary type column can be skipped. + * Doctrine's {@link \Doctrine\DBAL\Types\BinaryType} and {@link \Doctrine\DBAL\Types\BlobType} + * are mapped to the same database column type on this platform as this platform + * does not have a native VARBINARY/BINARY column type. Therefore the {@link \Doctrine\DBAL\Schema\Comparator} + * might detect differences for binary type columns which do not have to be propagated + * to database as there actually is no difference at database level. + * + * @param ColumnDiff $columnDiff The column diff to check against. + * + * @return bool True if the given column diff is an unchanged binary type column, false otherwise. + */ + private function isUnchangedBinaryColumn(ColumnDiff $columnDiff) + { + $columnType = $columnDiff->column->getType(); + + if (! $columnType instanceof BinaryType && ! $columnType instanceof BlobType) { + return false; + } + + $fromColumn = $columnDiff->fromColumn instanceof Column ? $columnDiff->fromColumn : null; + + if ($fromColumn) { + $fromColumnType = $fromColumn->getType(); + + if (! $fromColumnType instanceof BinaryType && ! $fromColumnType instanceof BlobType) { + return false; + } + + return count(array_diff($columnDiff->changedProperties, ['type', 'length', 'fixed'])) === 0; + } + + if ($columnDiff->hasChanged('type')) { + return false; + } + + return count(array_diff($columnDiff->changedProperties, ['length', 'fixed'])) === 0; + } + + /** + * {@inheritdoc} + */ + protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) + { + if (strpos($tableName, '.') !== false) { + [$schema] = explode('.', $tableName); + $oldIndexName = $schema . '.' . $oldIndexName; + } + + return ['ALTER INDEX ' . $oldIndexName . ' RENAME TO ' . $index->getQuotedName($this)]; + } + + /** + * {@inheritdoc} + */ + public function getCommentOnColumnSQL($tableName, $columnName, $comment) + { + $tableName = new Identifier($tableName); + $columnName = new Identifier($columnName); + $comment = $comment === null ? 'NULL' : $this->quoteStringLiteral($comment); + + return sprintf( + 'COMMENT ON COLUMN %s.%s IS %s', + $tableName->getQuotedName($this), + $columnName->getQuotedName($this), + $comment + ); + } + + /** + * {@inheritDoc} + */ + public function getCreateSequenceSQL(Sequence $sequence) + { + return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . + ' INCREMENT BY ' . $sequence->getAllocationSize() . + ' MINVALUE ' . $sequence->getInitialValue() . + ' START ' . $sequence->getInitialValue() . + $this->getSequenceCacheSQL($sequence); + } + + /** + * {@inheritDoc} + */ + public function getAlterSequenceSQL(Sequence $sequence) + { + return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . + ' INCREMENT BY ' . $sequence->getAllocationSize() . + $this->getSequenceCacheSQL($sequence); + } + + /** + * Cache definition for sequences + * + * @return string + */ + private function getSequenceCacheSQL(Sequence $sequence) + { + if ($sequence->getCache() > 1) { + return ' CACHE ' . $sequence->getCache(); + } + + return ''; + } + + /** + * {@inheritDoc} + */ + public function getDropSequenceSQL($sequence) + { + if ($sequence instanceof Sequence) { + $sequence = $sequence->getQuotedName($this); + } + + return 'DROP SEQUENCE ' . $sequence . ' CASCADE'; + } + + /** + * {@inheritDoc} + */ + public function getCreateSchemaSQL($schemaName) + { + return 'CREATE SCHEMA ' . $schemaName; + } + + /** + * {@inheritDoc} + */ + public function getDropForeignKeySQL($foreignKey, $table) + { + return $this->getDropConstraintSQL($foreignKey, $table); + } + + /** + * {@inheritDoc} + */ + protected function _getCreateTableSQL($tableName, array $columns, array $options = []) + { + $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; + } + + /** + * Converts a single boolean value. + * + * First converts the value to its native PHP boolean type + * and passes it to the given callback function to be reconverted + * into any custom representation. + * + * @param mixed $value The value to convert. + * @param callable $callback The callback function to use for converting the real boolean value. + * + * @return mixed + * + * @throws UnexpectedValueException + */ + private function convertSingleBooleanValue($value, $callback) + { + if ($value === null) { + return $callback(null); + } + + if (is_bool($value) || is_numeric($value)) { + return $callback((bool) $value); + } + + if (! is_string($value)) { + return $callback(true); + } + + /** + * Better safe than sorry: http://php.net/in_array#106319 + */ + if (in_array(strtolower(trim($value)), $this->booleanLiterals['false'], true)) { + return $callback(false); + } + + if (in_array(strtolower(trim($value)), $this->booleanLiterals['true'], true)) { + return $callback(true); + } + + throw new UnexpectedValueException("Unrecognized boolean literal '${value}'"); + } + + /** + * Converts one or multiple boolean values. + * + * First converts the value(s) to their native PHP boolean type + * and passes them to the given callback function to be reconverted + * into any custom representation. + * + * @param mixed $item The value(s) to convert. + * @param callable $callback The callback function to use for converting the real boolean value(s). + * + * @return mixed + */ + private function doConvertBooleans($item, $callback) + { + if (is_array($item)) { + foreach ($item as $key => $value) { + $item[$key] = $this->convertSingleBooleanValue($value, $callback); + } + + return $item; + } + + return $this->convertSingleBooleanValue($item, $callback); + } + + /** + * {@inheritDoc} + * + * Postgres wants boolean values converted to the strings 'true'/'false'. + */ + public function convertBooleans($item) + { + if (! $this->useBooleanTrueFalseStrings) { + return parent::convertBooleans($item); + } + + return $this->doConvertBooleans( + $item, + static function ($boolean) { + if ($boolean === null) { + return 'NULL'; + } + + return $boolean === true ? 'true' : 'false'; + } + ); + } + + /** + * {@inheritDoc} + */ + public function convertBooleansToDatabaseValue($item) + { + if (! $this->useBooleanTrueFalseStrings) { + return parent::convertBooleansToDatabaseValue($item); + } + + return $this->doConvertBooleans( + $item, + static function ($boolean) { + return $boolean === null ? null : (int) $boolean; + } + ); + } + + /** + * {@inheritDoc} + */ + public function convertFromBoolean($item) + { + if (in_array(strtolower($item), $this->booleanLiterals['false'], true)) { + return false; + } + + return parent::convertFromBoolean($item); + } + + /** + * {@inheritDoc} + */ + public function getSequenceNextValSQL($sequenceName) + { + return "SELECT NEXTVAL('" . $sequenceName . "')"; + } + + /** + * {@inheritDoc} + */ + public function getSetTransactionIsolationSQL($level) + { + return 'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL ' + . $this->_getTransactionIsolationLevelSQL($level); + } + + /** + * {@inheritDoc} + */ + public function getBooleanTypeDeclarationSQL(array $field) + { + return 'BOOLEAN'; + } + + /** + * {@inheritDoc} + */ + public function getIntegerTypeDeclarationSQL(array $field) + { + if (! empty($field['autoincrement'])) { + return 'SERIAL'; + } + + return 'INT'; + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $field) + { + if (! empty($field['autoincrement'])) { + return 'BIGSERIAL'; + } + + return 'BIGINT'; + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $field) + { + return 'SMALLINT'; + } + + /** + * {@inheritDoc} + */ + public function getGuidTypeDeclarationSQL(array $field) + { + return 'UUID'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIMESTAMP(0) WITHOUT TIME ZONE'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIMESTAMP(0) WITH TIME ZONE'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME(0) WITHOUT TIME ZONE'; + } + + /** + * {@inheritDoc} + * + * @deprecated Use application-generated UUIDs instead + */ + public function getGuidExpression() + { + return 'UUID_GENERATE_V4()'; + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + return ''; + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') + : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); + } + + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return 'BYTEA'; + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + return 'TEXT'; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'postgresql'; + } + + /** + * {@inheritDoc} + * + * PostgreSQL returns all column names in SQL result sets in lowercase. + */ + public function getSQLResultCasing($column) + { + return strtolower($column); + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTzFormatString() + { + return 'Y-m-d H:i:sO'; + } + + /** + * {@inheritDoc} + */ + public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName) + { + return 'INSERT INTO ' . $quotedTableName . ' (' . $quotedIdentifierColumnName . ') VALUES (DEFAULT)'; + } + + /** + * {@inheritDoc} + */ + public function getTruncateTableSQL($tableName, $cascade = false) + { + $tableIdentifier = new Identifier($tableName); + $sql = 'TRUNCATE ' . $tableIdentifier->getQuotedName($this); + + if ($cascade) { + $sql .= ' CASCADE'; + } + + return $sql; + } + + /** + * {@inheritDoc} + */ + public function getReadLockSQL() + { + return 'FOR SHARE'; + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = [ + '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', + 'tsvector' => 'text', + 'varchar' => 'string', + 'interval' => 'string', + '_varchar' => 'string', + 'char' => 'string', + 'bpchar' => 'string', + 'inet' => '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', + 'uuid' => 'guid', + 'bytea' => 'blob', + ]; + } + + /** + * {@inheritDoc} + */ + public function getVarcharMaxLength() + { + return 65535; + } + + /** + * {@inheritdoc} + */ + public function getBinaryMaxLength() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function getBinaryDefaultLength() + { + return 0; + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return Keywords\PostgreSQLKeywords::class; + } + + /** + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + return 'BYTEA'; + } + + /** + * {@inheritdoc} + */ + public function getDefaultValueDeclarationSQL($field) + { + if ($this->isSerialField($field)) { + return ''; + } + + return parent::getDefaultValueDeclarationSQL($field); + } + + /** + * @param mixed[] $field + */ + private function isSerialField(array $field) : bool + { + return isset($field['type'], $field['autoincrement']) + && $field['autoincrement'] === true + && $this->isNumericType($field['type']); + } + + /** + * Check whether the type of a column is changed in a way that invalidates the default value for the column + */ + private function typeChangeBreaksDefaultValue(ColumnDiff $columnDiff) : bool + { + if (! $columnDiff->fromColumn) { + return $columnDiff->hasChanged('type'); + } + + $oldTypeIsNumeric = $this->isNumericType($columnDiff->fromColumn->getType()); + $newTypeIsNumeric = $this->isNumericType($columnDiff->column->getType()); + + // default should not be changed when switching between numeric types and the default comes from a sequence + return $columnDiff->hasChanged('type') + && ! ($oldTypeIsNumeric && $newTypeIsNumeric && $columnDiff->column->getAutoincrement()); + } + + private function isNumericType(Type $type) : bool + { + return $type instanceof IntegerType || $type instanceof BigIntType; + } + + private function getOldColumnComment(ColumnDiff $columnDiff) : ?string + { + return $columnDiff->fromColumn ? $this->getColumnComment($columnDiff->fromColumn) : null; + } + + public function getListTableMetadataSQL(string $table, ?string $schema = null) : string + { + if ($schema !== null) { + $table = $schema . '.' . $table; + } + + return sprintf( + <<<'SQL' +SELECT obj_description(%s::regclass) AS table_comment; +SQL + , + $this->quoteStringLiteral($table) + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php new file mode 100644 index 0000000..a46ae93 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php @@ -0,0 +1,26 @@ +getQuotedName($this) . + ' INCREMENT BY ' . $sequence->getAllocationSize() . + ' START WITH ' . $sequence->getInitialValue() . + ' MINVALUE ' . $sequence->getInitialValue(); + } + + /** + * {@inheritdoc} + */ + public function getAlterSequenceSQL(Sequence $sequence) + { + return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . + ' INCREMENT BY ' . $sequence->getAllocationSize(); + } + + /** + * {@inheritdoc} + */ + public function getDateTimeTzFormatString() + { + return 'Y-m-d H:i:s.uP'; + } + + /** + * {@inheritdoc} + */ + public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIMESTAMP WITH TIME ZONE'; + } + + /** + * {@inheritdoc} + */ + public function getDropSequenceSQL($sequence) + { + if ($sequence instanceof Sequence) { + $sequence = $sequence->getQuotedName($this); + } + + return 'DROP SEQUENCE ' . $sequence; + } + + /** + * {@inheritdoc} + */ + public function getListSequencesSQL($database) + { + return 'SELECT sequence_name, increment_by, start_with, min_value FROM SYS.SYSSEQUENCE'; + } + + /** + * {@inheritdoc} + */ + public function getSequenceNextValSQL($sequenceName) + { + return 'SELECT ' . $sequenceName . '.NEXTVAL'; + } + + /** + * {@inheritdoc} + */ + public function supportsSequences() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function getAdvancedIndexOptionsSQL(Index $index) + { + if (! $index->isPrimary() && $index->isUnique() && $index->hasFlag('with_nulls_not_distinct')) { + return ' WITH NULLS NOT DISTINCT' . parent::getAdvancedIndexOptionsSQL($index); + } + + return parent::getAdvancedIndexOptionsSQL($index); + } + + /** + * {@inheritdoc} + */ + protected function getReservedKeywordsClass() + { + return Keywords\SQLAnywhere12Keywords::class; + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + parent::initializeDoctrineTypeMappings(); + $this->doctrineTypeMapping['timestamp with time zone'] = 'datetime'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere16Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere16Platform.php new file mode 100644 index 0000000..35d4238 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere16Platform.php @@ -0,0 +1,39 @@ +hasFlag('with_nulls_distinct') && $index->hasFlag('with_nulls_not_distinct')) { + throw new UnexpectedValueException( + 'An Index can either have a "with_nulls_distinct" or "with_nulls_not_distinct" flag but not both.' + ); + } + + if (! $index->isPrimary() && $index->isUnique() && $index->hasFlag('with_nulls_distinct')) { + return ' WITH NULLS DISTINCT' . parent::getAdvancedIndexOptionsSQL($index); + } + + return parent::getAdvancedIndexOptionsSQL($index); + } + + /** + * {@inheritdoc} + */ + protected function getReservedKeywordsClass() + { + return Keywords\SQLAnywhere16Keywords::class; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php new file mode 100644 index 0000000..6e3b2fc --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php @@ -0,0 +1,1512 @@ +getMaxIdentifierLength(); + + if (strlen($schemaElementName) > $maxIdentifierLength) { + return substr($schemaElementName, 0, $maxIdentifierLength); + } + + return $schemaElementName; + } + + /** + * {@inheritdoc} + */ + public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) + { + $query = ''; + + if ($foreignKey->hasOption('match')) { + $query = ' MATCH ' . $this->getForeignKeyMatchClauseSQL($foreignKey->getOption('match')); + } + + $query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey); + + if ($foreignKey->hasOption('check_on_commit') && (bool) $foreignKey->getOption('check_on_commit')) { + $query .= ' CHECK ON COMMIT'; + } + + if ($foreignKey->hasOption('clustered') && (bool) $foreignKey->getOption('clustered')) { + $query .= ' CLUSTERED'; + } + + if ($foreignKey->hasOption('for_olap_workload') && (bool) $foreignKey->getOption('for_olap_workload')) { + $query .= ' FOR OLAP WORKLOAD'; + } + + return $query; + } + + /** + * {@inheritdoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $sql = []; + $columnSql = []; + $commentsSQL = []; + $tableSql = []; + $alterClauses = []; + + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $alterClauses[] = $this->getAlterTableAddColumnClause($column); + + $comment = $this->getColumnComment($column); + + if ($comment === null || $comment === '') { + continue; + } + + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), + $comment + ); + } + + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $alterClauses[] = $this->getAlterTableRemoveColumnClause($column); + } + + foreach ($diff->changedColumns as $columnDiff) { + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + $alterClause = $this->getAlterTableChangeColumnClause($columnDiff); + + if ($alterClause !== null) { + $alterClauses[] = $alterClause; + } + + if (! $columnDiff->hasChanged('comment')) { + continue; + } + + $column = $columnDiff->column; + + $commentsSQL[] = $this->getCommentOnColumnSQL( + $diff->getName($this)->getQuotedName($this), + $column->getQuotedName($this), + $this->getColumnComment($column) + ); + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' . + $this->getAlterTableRenameColumnClause($oldColumnName, $column); + } + + if (! $this->onSchemaAlterTable($diff, $tableSql)) { + if (! empty($alterClauses)) { + $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' . implode(', ', $alterClauses); + } + + $sql = array_merge($sql, $commentsSQL); + + $newName = $diff->getNewName(); + + if ($newName !== false) { + $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' . + $this->getAlterTableRenameTableClause($newName); + } + + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * Returns the SQL clause for creating a column in a table alteration. + * + * @param Column $column The column to add. + * + * @return string + */ + protected function getAlterTableAddColumnClause(Column $column) + { + return 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + } + + /** + * Returns the SQL clause for altering a table. + * + * @param Identifier $tableName The quoted name of the table to alter. + * + * @return string + */ + protected function getAlterTableClause(Identifier $tableName) + { + return 'ALTER TABLE ' . $tableName->getQuotedName($this); + } + + /** + * Returns the SQL clause for dropping a column in a table alteration. + * + * @param Column $column The column to drop. + * + * @return string + */ + protected function getAlterTableRemoveColumnClause(Column $column) + { + return 'DROP ' . $column->getQuotedName($this); + } + + /** + * Returns the SQL clause for renaming a column in a table alteration. + * + * @param string $oldColumnName The quoted name of the column to rename. + * @param Column $column The column to rename to. + * + * @return string + */ + protected function getAlterTableRenameColumnClause($oldColumnName, Column $column) + { + $oldColumnName = new Identifier($oldColumnName); + + return 'RENAME ' . $oldColumnName->getQuotedName($this) . ' TO ' . $column->getQuotedName($this); + } + + /** + * Returns the SQL clause for renaming a table in a table alteration. + * + * @param Identifier $newTableName The quoted name of the table to rename to. + * + * @return string + */ + protected function getAlterTableRenameTableClause(Identifier $newTableName) + { + return 'RENAME ' . $newTableName->getQuotedName($this); + } + + /** + * Returns the SQL clause for altering a column in a table alteration. + * + * This method returns null in case that only the column comment has changed. + * Changes in column comments have to be handled differently. + * + * @param ColumnDiff $columnDiff The diff of the column to alter. + * + * @return string|null + */ + protected function getAlterTableChangeColumnClause(ColumnDiff $columnDiff) + { + $column = $columnDiff->column; + + // Do not return alter clause if only comment has changed. + if (! ($columnDiff->hasChanged('comment') && count($columnDiff->changedProperties) === 1)) { + $columnAlterationClause = 'ALTER ' . + $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + + if ($columnDiff->hasChanged('default') && $column->getDefault() === null) { + $columnAlterationClause .= ', ALTER ' . $column->getQuotedName($this) . ' DROP DEFAULT'; + } + + return $columnAlterationClause; + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function getBigIntTypeDeclarationSQL(array $columnDef) + { + $columnDef['integer_type'] = 'BIGINT'; + + return $this->_getCommonIntegerTypeDeclarationSQL($columnDef); + } + + /** + * {@inheritdoc} + */ + public function getBinaryDefaultLength() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function getBinaryMaxLength() + { + return 32767; + } + + /** + * {@inheritdoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + return 'LONG BINARY'; + } + + /** + * {@inheritdoc} + * + * BIT type columns require an explicit NULL declaration + * in SQL Anywhere if they shall be nullable. + * Otherwise by just omitting the NOT NULL clause, + * SQL Anywhere will declare them NOT NULL nonetheless. + */ + public function getBooleanTypeDeclarationSQL(array $columnDef) + { + $nullClause = isset($columnDef['notnull']) && (bool) $columnDef['notnull'] === false ? ' NULL' : ''; + + return 'BIT' . $nullClause; + } + + /** + * {@inheritdoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + return 'TEXT'; + } + + /** + * {@inheritdoc} + */ + public function getCommentOnColumnSQL($tableName, $columnName, $comment) + { + $tableName = new Identifier($tableName); + $columnName = new Identifier($columnName); + $comment = $comment === null ? 'NULL' : $this->quoteStringLiteral($comment); + + return sprintf( + 'COMMENT ON COLUMN %s.%s IS %s', + $tableName->getQuotedName($this), + $columnName->getQuotedName($this), + $comment + ); + } + + /** + * {@inheritdoc} + */ + public function getConcatExpression() + { + return 'STRING(' . implode(', ', (array) func_get_args()) . ')'; + } + + /** + * {@inheritdoc} + */ + public function getCreateConstraintSQL(Constraint $constraint, $table) + { + if ($constraint instanceof ForeignKeyConstraint) { + return $this->getCreateForeignKeySQL($constraint, $table); + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + return 'ALTER TABLE ' . $table . + ' ADD ' . $this->getTableConstraintDeclarationSQL($constraint, $constraint->getQuotedName($this)); + } + + /** + * {@inheritdoc} + */ + public function getCreateDatabaseSQL($database) + { + $database = new Identifier($database); + + return "CREATE DATABASE '" . $database->getName() . "'"; + } + + /** + * {@inheritdoc} + * + * Appends SQL Anywhere specific flags if given. + */ + public function getCreateIndexSQL(Index $index, $table) + { + return parent::getCreateIndexSQL($index, $table) . $this->getAdvancedIndexOptionsSQL($index); + } + + /** + * {@inheritdoc} + */ + public function getCreatePrimaryKeySQL(Index $index, $table) + { + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + return 'ALTER TABLE ' . $table . ' ADD ' . $this->getPrimaryKeyDeclarationSQL($index); + } + + /** + * {@inheritdoc} + */ + public function getCreateTemporaryTableSnippetSQL() + { + return 'CREATE ' . $this->getTemporaryTableSQL() . ' TABLE'; + } + + /** + * {@inheritdoc} + */ + public function getCreateViewSQL($name, $sql) + { + return 'CREATE VIEW ' . $name . ' AS ' . $sql; + } + + /** + * {@inheritdoc} + */ + public function getCurrentDateSQL() + { + return 'CURRENT DATE'; + } + + /** + * {@inheritdoc} + */ + public function getCurrentTimeSQL() + { + return 'CURRENT TIME'; + } + + /** + * {@inheritdoc} + */ + public function getCurrentTimestampSQL() + { + return 'CURRENT TIMESTAMP'; + } + + /** + * {@inheritdoc} + */ + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + { + $factorClause = ''; + + if ($operator === '-') { + $factorClause = '-1 * '; + } + + return 'DATEADD(' . $unit . ', ' . $factorClause . $interval . ', ' . $date . ')'; + } + + /** + * {@inheritdoc} + */ + public function getDateDiffExpression($date1, $date2) + { + return 'DATEDIFF(day, ' . $date2 . ', ' . $date1 . ')'; + } + + /** + * {@inheritdoc} + */ + public function getDateTimeFormatString() + { + return 'Y-m-d H:i:s.u'; + } + + /** + * {@inheritdoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATETIME'; + } + + /** + * {@inheritdoc} + */ + public function getDateTimeTzFormatString() + { + return $this->getDateTimeFormatString(); + } + + /** + * {@inheritdoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritdoc} + */ + public function getDefaultTransactionIsolationLevel() + { + return TransactionIsolationLevel::READ_UNCOMMITTED; + } + + /** + * {@inheritdoc} + */ + public function getDropDatabaseSQL($database) + { + $database = new Identifier($database); + + return "DROP DATABASE '" . $database->getName() . "'"; + } + + /** + * {@inheritdoc} + */ + public function getDropIndexSQL($index, $table = null) + { + if ($index instanceof Index) { + $index = $index->getQuotedName($this); + } + + if (! is_string($index)) { + throw new InvalidArgumentException( + 'SQLAnywherePlatform::getDropIndexSQL() expects $index parameter to be string or ' . Index::class . '.' + ); + } + + if (! isset($table)) { + return 'DROP INDEX ' . $index; + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + if (! is_string($table)) { + throw new InvalidArgumentException( + 'SQLAnywherePlatform::getDropIndexSQL() expects $table parameter to be string or ' . Index::class . '.' + ); + } + + return 'DROP INDEX ' . $table . '.' . $index; + } + + /** + * {@inheritdoc} + */ + public function getDropViewSQL($name) + { + return 'DROP VIEW ' . $name; + } + + /** + * {@inheritdoc} + */ + public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint $foreignKey) + { + $sql = ''; + $foreignKeyName = $foreignKey->getName(); + $localColumns = $foreignKey->getQuotedLocalColumns($this); + $foreignColumns = $foreignKey->getQuotedForeignColumns($this); + $foreignTableName = $foreignKey->getQuotedForeignTableName($this); + + if (! empty($foreignKeyName)) { + $sql .= 'CONSTRAINT ' . $foreignKey->getQuotedName($this) . ' '; + } + + if (empty($localColumns)) { + throw new InvalidArgumentException("Incomplete definition. 'local' required."); + } + + if (empty($foreignColumns)) { + throw new InvalidArgumentException("Incomplete definition. 'foreign' required."); + } + + if (empty($foreignTableName)) { + throw new InvalidArgumentException("Incomplete definition. 'foreignTable' required."); + } + + if ($foreignKey->hasOption('notnull') && (bool) $foreignKey->getOption('notnull')) { + $sql .= 'NOT NULL '; + } + + return $sql . + 'FOREIGN KEY (' . $this->getIndexFieldDeclarationListSQL($localColumns) . ') ' . + 'REFERENCES ' . $foreignKey->getQuotedForeignTableName($this) . + ' (' . $this->getIndexFieldDeclarationListSQL($foreignColumns) . ')'; + } + + /** + * Returns foreign key MATCH clause for given type. + * + * @param int $type The foreign key match type + * + * @return string + * + * @throws InvalidArgumentException If unknown match type given. + */ + public function getForeignKeyMatchClauseSQL($type) + { + switch ((int) $type) { + case self::FOREIGN_KEY_MATCH_SIMPLE: + return 'SIMPLE'; + + break; + case self::FOREIGN_KEY_MATCH_FULL: + return 'FULL'; + + break; + case self::FOREIGN_KEY_MATCH_SIMPLE_UNIQUE: + return 'UNIQUE SIMPLE'; + + break; + case self::FOREIGN_KEY_MATCH_FULL_UNIQUE: + return 'UNIQUE FULL'; + default: + throw new InvalidArgumentException('Invalid foreign key match type: ' . $type); + } + } + + /** + * {@inheritdoc} + */ + public function getForeignKeyReferentialActionSQL($action) + { + // NO ACTION is not supported, therefore falling back to RESTRICT. + if (strtoupper($action) === 'NO ACTION') { + return 'RESTRICT'; + } + + return parent::getForeignKeyReferentialActionSQL($action); + } + + /** + * {@inheritdoc} + */ + public function getForUpdateSQL() + { + return ''; + } + + /** + * {@inheritdoc} + * + * @deprecated Use application-generated UUIDs instead + */ + public function getGuidExpression() + { + return 'NEWID()'; + } + + /** + * {@inheritdoc} + */ + public function getGuidTypeDeclarationSQL(array $field) + { + return 'UNIQUEIDENTIFIER'; + } + + /** + * {@inheritdoc} + */ + public function getIndexDeclarationSQL($name, Index $index) + { + // Index declaration in statements like CREATE TABLE is not supported. + throw DBALException::notSupported(__METHOD__); + } + + /** + * {@inheritdoc} + */ + public function getIntegerTypeDeclarationSQL(array $columnDef) + { + $columnDef['integer_type'] = 'INT'; + + return $this->_getCommonIntegerTypeDeclarationSQL($columnDef); + } + + /** + * {@inheritdoc} + */ + public function getListDatabasesSQL() + { + return 'SELECT db_name(number) AS name FROM sa_db_list()'; + } + + /** + * {@inheritdoc} + */ + public function getListTableColumnsSQL($table, $database = null) + { + $user = 'USER_NAME()'; + + if (strpos($table, '.') !== false) { + [$user, $table] = explode('.', $table); + $user = $this->quoteStringLiteral($user); + } + + return sprintf( + <<<'SQL' +SELECT col.column_name, + COALESCE(def.user_type_name, def.domain_name) AS 'type', + def.declared_width AS 'length', + def.scale, + CHARINDEX('unsigned', def.domain_name) AS 'unsigned', + IF col.nulls = 'Y' THEN 0 ELSE 1 ENDIF AS 'notnull', + col."default", + def.is_autoincrement AS 'autoincrement', + rem.remarks AS 'comment' +FROM sa_describe_query('SELECT * FROM "%s"') AS def +JOIN SYS.SYSTABCOL AS col +ON col.table_id = def.base_table_id AND col.column_id = def.base_column_id +LEFT JOIN SYS.SYSREMARK AS rem +ON col.object_id = rem.object_id +WHERE def.base_owner_name = %s +ORDER BY def.base_column_id ASC +SQL + , + $table, + $user + ); + } + + /** + * {@inheritdoc} + * + * @todo Where is this used? Which information should be retrieved? + */ + public function getListTableConstraintsSQL($table) + { + $user = ''; + + if (strpos($table, '.') !== false) { + [$user, $table] = explode('.', $table); + $user = $this->quoteStringLiteral($user); + $table = $this->quoteStringLiteral($table); + } else { + $table = $this->quoteStringLiteral($table); + } + + return sprintf( + <<<'SQL' +SELECT con.* +FROM SYS.SYSCONSTRAINT AS con +JOIN SYS.SYSTAB AS tab ON con.table_object_id = tab.object_id +WHERE tab.table_name = %s +AND tab.creator = USER_ID(%s) +SQL + , + $table, + $user + ); + } + + /** + * {@inheritdoc} + */ + public function getListTableForeignKeysSQL($table) + { + $user = ''; + + if (strpos($table, '.') !== false) { + [$user, $table] = explode('.', $table); + $user = $this->quoteStringLiteral($user); + $table = $this->quoteStringLiteral($table); + } else { + $table = $this->quoteStringLiteral($table); + } + + return sprintf( + <<<'SQL' +SELECT fcol.column_name AS local_column, + ptbl.table_name AS foreign_table, + pcol.column_name AS foreign_column, + idx.index_name, + IF fk.nulls = 'N' + THEN 1 + ELSE NULL + ENDIF AS notnull, + CASE ut.referential_action + WHEN 'C' THEN 'CASCADE' + WHEN 'D' THEN 'SET DEFAULT' + WHEN 'N' THEN 'SET NULL' + WHEN 'R' THEN 'RESTRICT' + ELSE NULL + END AS on_update, + CASE dt.referential_action + WHEN 'C' THEN 'CASCADE' + WHEN 'D' THEN 'SET DEFAULT' + WHEN 'N' THEN 'SET NULL' + WHEN 'R' THEN 'RESTRICT' + ELSE NULL + END AS on_delete, + IF fk.check_on_commit = 'Y' + THEN 1 + ELSE NULL + ENDIF AS check_on_commit, -- check_on_commit flag + IF ftbl.clustered_index_id = idx.index_id + THEN 1 + ELSE NULL + ENDIF AS 'clustered', -- clustered flag + IF fk.match_type = 0 + THEN NULL + ELSE fk.match_type + ENDIF AS 'match', -- match option + IF pidx.max_key_distance = 1 + THEN 1 + ELSE NULL + ENDIF AS for_olap_workload -- for_olap_workload flag +FROM SYS.SYSFKEY AS fk +JOIN SYS.SYSIDX AS idx +ON fk.foreign_table_id = idx.table_id +AND fk.foreign_index_id = idx.index_id +JOIN SYS.SYSPHYSIDX pidx +ON idx.table_id = pidx.table_id +AND idx.phys_index_id = pidx.phys_index_id +JOIN SYS.SYSTAB AS ptbl +ON fk.primary_table_id = ptbl.table_id +JOIN SYS.SYSTAB AS ftbl +ON fk.foreign_table_id = ftbl.table_id +JOIN SYS.SYSIDXCOL AS idxcol +ON idx.table_id = idxcol.table_id +AND idx.index_id = idxcol.index_id +JOIN SYS.SYSTABCOL AS pcol +ON ptbl.table_id = pcol.table_id +AND idxcol.primary_column_id = pcol.column_id +JOIN SYS.SYSTABCOL AS fcol +ON ftbl.table_id = fcol.table_id +AND idxcol.column_id = fcol.column_id +LEFT JOIN SYS.SYSTRIGGER ut +ON fk.foreign_table_id = ut.foreign_table_id +AND fk.foreign_index_id = ut.foreign_key_id +AND ut.event = 'C' +LEFT JOIN SYS.SYSTRIGGER dt +ON fk.foreign_table_id = dt.foreign_table_id +AND fk.foreign_index_id = dt.foreign_key_id +AND dt.event = 'D' +WHERE ftbl.table_name = %s +AND ftbl.creator = USER_ID(%s) +ORDER BY fk.foreign_index_id ASC, idxcol.sequence ASC +SQL + , + $table, + $user + ); + } + + /** + * {@inheritdoc} + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + $user = ''; + + if (strpos($table, '.') !== false) { + [$user, $table] = explode('.', $table); + $user = $this->quoteStringLiteral($user); + $table = $this->quoteStringLiteral($table); + } else { + $table = $this->quoteStringLiteral($table); + } + + return sprintf( + <<<'SQL' +SELECT idx.index_name AS key_name, + IF idx.index_category = 1 + THEN 1 + ELSE 0 + ENDIF AS 'primary', + col.column_name, + IF idx."unique" IN(1, 2, 5) + THEN 0 + ELSE 1 + ENDIF AS non_unique, + IF tbl.clustered_index_id = idx.index_id + THEN 1 + ELSE NULL + ENDIF AS 'clustered', -- clustered flag + IF idx."unique" = 5 + THEN 1 + ELSE NULL + ENDIF AS with_nulls_not_distinct, -- with_nulls_not_distinct flag + IF pidx.max_key_distance = 1 + THEN 1 + ELSE NULL + ENDIF AS for_olap_workload -- for_olap_workload flag +FROM SYS.SYSIDX AS idx +JOIN SYS.SYSPHYSIDX pidx +ON idx.table_id = pidx.table_id +AND idx.phys_index_id = pidx.phys_index_id +JOIN SYS.SYSIDXCOL AS idxcol +ON idx.table_id = idxcol.table_id AND idx.index_id = idxcol.index_id +JOIN SYS.SYSTABCOL AS col +ON idxcol.table_id = col.table_id AND idxcol.column_id = col.column_id +JOIN SYS.SYSTAB AS tbl +ON idx.table_id = tbl.table_id +WHERE tbl.table_name = %s +AND tbl.creator = USER_ID(%s) +AND idx.index_category != 2 -- exclude indexes implicitly created by foreign key constraints +ORDER BY idx.index_id ASC, idxcol.sequence ASC +SQL + , + $table, + $user + ); + } + + /** + * {@inheritdoc} + */ + public function getListTablesSQL() + { + return "SELECT tbl.table_name + FROM SYS.SYSTAB AS tbl + JOIN SYS.SYSUSER AS usr ON tbl.creator = usr.user_id + JOIN dbo.SYSOBJECTS AS obj ON tbl.object_id = obj.id + WHERE tbl.table_type IN(1, 3) -- 'BASE', 'GBL TEMP' + AND usr.user_name NOT IN('SYS', 'dbo', 'rs_systabgroup') -- exclude system users + AND obj.type = 'U' -- user created tables only + ORDER BY tbl.table_name ASC"; + } + + /** + * {@inheritdoc} + * + * @todo Where is this used? Which information should be retrieved? + */ + public function getListUsersSQL() + { + return 'SELECT * FROM SYS.SYSUSER ORDER BY user_name ASC'; + } + + /** + * {@inheritdoc} + */ + public function getListViewsSQL($database) + { + return "SELECT tbl.table_name, v.view_def + FROM SYS.SYSVIEW v + JOIN SYS.SYSTAB tbl ON v.view_object_id = tbl.object_id + JOIN SYS.SYSUSER usr ON tbl.creator = usr.user_id + JOIN dbo.SYSOBJECTS obj ON tbl.object_id = obj.id + WHERE usr.user_name NOT IN('SYS', 'dbo', 'rs_systabgroup') -- exclude system users + ORDER BY tbl.table_name ASC"; + } + + /** + * {@inheritdoc} + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + if ($startPos === false) { + return 'LOCATE(' . $str . ', ' . $substr . ')'; + } + + return 'LOCATE(' . $str . ', ' . $substr . ', ' . $startPos . ')'; + } + + /** + * {@inheritdoc} + */ + public function getMaxIdentifierLength() + { + return 128; + } + + /** + * {@inheritdoc} + */ + public function getMd5Expression($column) + { + return 'HASH(' . $column . ", 'MD5')"; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'sqlanywhere'; + } + + /** + * Obtain DBMS specific SQL code portion needed to set a primary key + * declaration to be used in statements like ALTER TABLE. + * + * @param Index $index Index definition + * @param string $name Name of the primary key + * + * @return string DBMS specific SQL code portion needed to set a primary key + * + * @throws InvalidArgumentException If the given index is not a primary key. + */ + public function getPrimaryKeyDeclarationSQL(Index $index, $name = null) + { + if (! $index->isPrimary()) { + throw new InvalidArgumentException( + 'Can only create primary key declarations with getPrimaryKeyDeclarationSQL()' + ); + } + + return $this->getTableConstraintDeclarationSQL($index, $name); + } + + /** + * {@inheritdoc} + */ + public function getSetTransactionIsolationSQL($level) + { + return 'SET TEMPORARY OPTION isolation_level = ' . $this->_getTransactionIsolationLevelSQL($level); + } + + /** + * {@inheritdoc} + */ + public function getSmallIntTypeDeclarationSQL(array $columnDef) + { + $columnDef['integer_type'] = 'SMALLINT'; + + return $this->_getCommonIntegerTypeDeclarationSQL($columnDef); + } + + /** + * Returns the SQL statement for starting an existing database. + * + * In SQL Anywhere you can start and stop databases on a + * database server instance. + * This is a required statement after having created a new database + * as it has to be explicitly started to be usable. + * SQL Anywhere does not automatically start a database after creation! + * + * @param string $database Name of the database to start. + * + * @return string + */ + public function getStartDatabaseSQL($database) + { + $database = new Identifier($database); + + return "START DATABASE '" . $database->getName() . "' AUTOSTOP OFF"; + } + + /** + * Returns the SQL statement for stopping a running database. + * + * In SQL Anywhere you can start and stop databases on a + * database server instance. + * This is a required statement before dropping an existing database + * as it has to be explicitly stopped before it can be dropped. + * + * @param string $database Name of the database to stop. + * + * @return string + */ + public function getStopDatabaseSQL($database) + { + $database = new Identifier($database); + + return 'STOP DATABASE "' . $database->getName() . '" UNCONDITIONALLY'; + } + + /** + * {@inheritdoc} + */ + public function getSubstringExpression($value, $from, $length = null) + { + if ($length === null) { + return 'SUBSTRING(' . $value . ', ' . $from . ')'; + } + + return 'SUBSTRING(' . $value . ', ' . $from . ', ' . $length . ')'; + } + + /** + * {@inheritdoc} + */ + public function getTemporaryTableSQL() + { + return 'GLOBAL TEMPORARY'; + } + + /** + * {@inheritdoc} + */ + public function getTimeFormatString() + { + return 'H:i:s.u'; + } + + /** + * {@inheritdoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME'; + } + + /** + * {@inheritdoc} + */ + public function getTrimExpression($str, $pos = TrimMode::UNSPECIFIED, $char = false) + { + if (! $char) { + switch ($pos) { + case TrimMode::LEADING: + return $this->getLtrimExpression($str); + case TrimMode::TRAILING: + return $this->getRtrimExpression($str); + default: + return 'TRIM(' . $str . ')'; + } + } + + $pattern = "'%[^' + " . $char . " + ']%'"; + + switch ($pos) { + case TrimMode::LEADING: + return 'SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))'; + case TrimMode::TRAILING: + return 'REVERSE(SUBSTR(REVERSE(' . $str . '), PATINDEX(' . $pattern . ', REVERSE(' . $str . '))))'; + default: + return 'REVERSE(SUBSTR(REVERSE(SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))), ' . + 'PATINDEX(' . $pattern . ', REVERSE(SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))))))'; + } + } + + /** + * {@inheritdoc} + */ + public function getTruncateTableSQL($tableName, $cascade = false) + { + $tableIdentifier = new Identifier($tableName); + + return 'TRUNCATE TABLE ' . $tableIdentifier->getQuotedName($this); + } + + /** + * {@inheritdoc} + */ + public function getUniqueConstraintDeclarationSQL($name, Index $index) + { + if ($index->isPrimary()) { + throw new InvalidArgumentException( + 'Cannot create primary key constraint declarations with getUniqueConstraintDeclarationSQL().' + ); + } + + if (! $index->isUnique()) { + throw new InvalidArgumentException( + 'Can only create unique constraint declarations, no common index declarations with ' . + 'getUniqueConstraintDeclarationSQL().' + ); + } + + return $this->getTableConstraintDeclarationSQL($index, $name); + } + + /** + * {@inheritdoc} + */ + public function getVarcharDefaultLength() + { + return 1; + } + + /** + * {@inheritdoc} + */ + public function getVarcharMaxLength() + { + return 32767; + } + + /** + * {@inheritdoc} + */ + public function hasNativeGuidType() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function prefersIdentityColumns() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function supportsCommentOnStatement() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + $unsigned = ! empty($columnDef['unsigned']) ? 'UNSIGNED ' : ''; + $autoincrement = ! empty($columnDef['autoincrement']) ? ' IDENTITY' : ''; + + return $unsigned . $columnDef['integer_type'] . $autoincrement; + } + + /** + * {@inheritdoc} + */ + protected function _getCreateTableSQL($tableName, array $columns, array $options = []) + { + $columnListSql = $this->getColumnDeclarationListSQL($columns); + $indexSql = []; + + if (! empty($options['uniqueConstraints'])) { + foreach ((array) $options['uniqueConstraints'] as $name => $definition) { + $columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition); + } + } + + if (! empty($options['indexes'])) { + /** @var Index $index */ + foreach ((array) $options['indexes'] as $index) { + $indexSql[] = $this->getCreateIndexSQL($index, $tableName); + } + } + + if (! empty($options['primary'])) { + $flags = ''; + + if (isset($options['primary_index']) && $options['primary_index']->hasFlag('clustered')) { + $flags = ' CLUSTERED '; + } + + $columnListSql .= ', PRIMARY KEY' . $flags . ' (' . implode(', ', array_unique(array_values((array) $options['primary']))) . ')'; + } + + if (! empty($options['foreignKeys'])) { + foreach ((array) $options['foreignKeys'] as $definition) { + $columnListSql .= ', ' . $this->getForeignKeyDeclarationSQL($definition); + } + } + + $query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql; + $check = $this->getCheckDeclarationSQL($columns); + + if (! empty($check)) { + $query .= ', ' . $check; + } + + $query .= ')'; + + return array_merge([$query], $indexSql); + } + + /** + * {@inheritdoc} + */ + protected function _getTransactionIsolationLevelSQL($level) + { + switch ($level) { + case TransactionIsolationLevel::READ_UNCOMMITTED: + return 0; + case TransactionIsolationLevel::READ_COMMITTED: + return 1; + case TransactionIsolationLevel::REPEATABLE_READ: + return 2; + case TransactionIsolationLevel::SERIALIZABLE: + return 3; + default: + throw new InvalidArgumentException('Invalid isolation level:' . $level); + } + } + + /** + * {@inheritdoc} + */ + protected function doModifyLimitQuery($query, $limit, $offset) + { + $limitOffsetClause = $this->getTopClauseSQL($limit, $offset); + + if ($limitOffsetClause === '') { + return $query; + } + + if (! preg_match('/^\s*(SELECT\s+(DISTINCT\s+)?)(.*)/i', $query, $matches)) { + return $query; + } + + return $matches[1] . $limitOffsetClause . ' ' . $matches[3]; + } + + private function getTopClauseSQL(?int $limit, ?int $offset) : string + { + if ($offset > 0) { + return sprintf('TOP %s START AT %d', $limit ?? 'ALL', $offset + 1); + } + + return $limit === null ? '' : 'TOP ' . $limit; + } + + /** + * Return the INDEX query section dealing with non-standard + * SQL Anywhere options. + * + * @param Index $index Index definition + * + * @return string + */ + protected function getAdvancedIndexOptionsSQL(Index $index) + { + $sql = ''; + + if (! $index->isPrimary() && $index->hasFlag('for_olap_workload')) { + $sql .= ' FOR OLAP WORKLOAD'; + } + + return $sql; + } + + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed + ? 'BINARY(' . ($length ?: $this->getBinaryDefaultLength()) . ')' + : 'VARBINARY(' . ($length ?: $this->getBinaryDefaultLength()) . ')'; + } + + /** + * Returns the SQL snippet for creating a table constraint. + * + * @param Constraint $constraint The table constraint to create the SQL snippet for. + * @param string|null $name The table constraint name to use if any. + * + * @return string + * + * @throws InvalidArgumentException If the given table constraint type is not supported by this method. + */ + protected function getTableConstraintDeclarationSQL(Constraint $constraint, $name = null) + { + if ($constraint instanceof ForeignKeyConstraint) { + return $this->getForeignKeyDeclarationSQL($constraint); + } + + if (! $constraint instanceof Index) { + throw new InvalidArgumentException('Unsupported constraint type: ' . get_class($constraint)); + } + + if (! $constraint->isPrimary() && ! $constraint->isUnique()) { + throw new InvalidArgumentException( + 'Can only create primary, unique or foreign key constraint declarations, no common index declarations ' . + 'with getTableConstraintDeclarationSQL().' + ); + } + + $constraintColumns = $constraint->getQuotedColumns($this); + + if (empty($constraintColumns)) { + throw new InvalidArgumentException("Incomplete definition. 'columns' required."); + } + + $sql = ''; + $flags = ''; + + if (! empty($name)) { + $name = new Identifier($name); + $sql .= 'CONSTRAINT ' . $name->getQuotedName($this) . ' '; + } + + if ($constraint->hasFlag('clustered')) { + $flags = 'CLUSTERED '; + } + + if ($constraint->isPrimary()) { + return $sql . 'PRIMARY KEY ' . $flags . '(' . $this->getIndexFieldDeclarationListSQL($constraintColumns) . ')'; + } + + return $sql . 'UNIQUE ' . $flags . '(' . $this->getIndexFieldDeclarationListSQL($constraintColumns) . ')'; + } + + /** + * {@inheritdoc} + */ + protected function getCreateIndexSQLFlags(Index $index) + { + $type = ''; + if ($index->hasFlag('virtual')) { + $type .= 'VIRTUAL '; + } + + if ($index->isUnique()) { + $type .= 'UNIQUE '; + } + + if ($index->hasFlag('clustered')) { + $type .= 'CLUSTERED '; + } + + return $type; + } + + /** + * {@inheritdoc} + */ + protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) + { + return ['ALTER INDEX ' . $oldIndexName . ' ON ' . $tableName . ' RENAME TO ' . $index->getQuotedName($this)]; + } + + /** + * {@inheritdoc} + */ + protected function getReservedKeywordsClass() + { + return Keywords\SQLAnywhereKeywords::class; + } + + /** + * {@inheritdoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed + ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(' . $this->getVarcharDefaultLength() . ')') + : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(' . $this->getVarcharDefaultLength() . ')'); + } + + /** + * {@inheritdoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = [ + 'char' => 'string', + 'long nvarchar' => 'text', + 'long varchar' => 'text', + 'nchar' => 'string', + 'ntext' => 'text', + 'nvarchar' => 'string', + 'text' => 'text', + 'uniqueidentifierstr' => 'guid', + 'varchar' => 'string', + 'xml' => 'text', + 'bigint' => 'bigint', + 'unsigned bigint' => 'bigint', + 'bit' => 'boolean', + 'decimal' => 'decimal', + 'double' => 'float', + 'float' => 'float', + 'int' => 'integer', + 'integer' => 'integer', + 'unsigned int' => 'integer', + 'numeric' => 'decimal', + 'smallint' => 'smallint', + 'unsigned smallint' => 'smallint', + 'tinyint' => 'smallint', + 'unsigned tinyint' => 'smallint', + 'money' => 'decimal', + 'smallmoney' => 'decimal', + 'long varbit' => 'text', + 'varbit' => 'string', + 'date' => 'date', + 'datetime' => 'datetime', + 'smalldatetime' => 'datetime', + 'time' => 'time', + 'timestamp' => 'datetime', + 'binary' => 'binary', + 'image' => 'blob', + 'long binary' => 'blob', + 'uniqueidentifier' => 'guid', + 'varbinary' => 'binary', + ]; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAzurePlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAzurePlatform.php new file mode 100644 index 0000000..a104848 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAzurePlatform.php @@ -0,0 +1,33 @@ +hasOption('azure.federatedOnColumnName')) { + $distributionName = $table->getOption('azure.federatedOnDistributionName'); + $columnName = $table->getOption('azure.federatedOnColumnName'); + $stmt = ' FEDERATED ON (' . $distributionName . ' = ' . $columnName . ')'; + + $sql[0] .= $stmt; + } + + return $sql; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php new file mode 100644 index 0000000..1026a93 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php @@ -0,0 +1,46 @@ +doctrineTypeMapping['datetime2'] = 'datetime'; + $this->doctrineTypeMapping['date'] = 'date'; + $this->doctrineTypeMapping['time'] = 'time'; + $this->doctrineTypeMapping['datetimeoffset'] = 'datetimetz'; + } + + /** + * {@inheritdoc} + * + * Returns Microsoft SQL Server 2008 specific keywords class + */ + protected function getReservedKeywordsClass() + { + return Keywords\SQLServer2008Keywords::class; + } + + protected function getLikeWildcardCharacters() : string + { + return parent::getLikeWildcardCharacters() . '[]^'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2012Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2012Platform.php new file mode 100644 index 0000000..009a37d --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2012Platform.php @@ -0,0 +1,143 @@ +getQuotedName($this) . + ' INCREMENT BY ' . $sequence->getAllocationSize(); + } + + /** + * {@inheritdoc} + */ + public function getCreateSequenceSQL(Sequence $sequence) + { + return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . + ' START WITH ' . $sequence->getInitialValue() . + ' INCREMENT BY ' . $sequence->getAllocationSize() . + ' MINVALUE ' . $sequence->getInitialValue(); + } + + /** + * {@inheritdoc} + */ + public function getDropSequenceSQL($sequence) + { + if ($sequence instanceof Sequence) { + $sequence = $sequence->getQuotedName($this); + } + + return 'DROP SEQUENCE ' . $sequence; + } + + /** + * {@inheritdoc} + */ + public function getListSequencesSQL($database) + { + return 'SELECT seq.name, + CAST( + seq.increment AS VARCHAR(MAX) + ) AS increment, -- CAST avoids driver error for sql_variant type + CAST( + seq.start_value AS VARCHAR(MAX) + ) AS start_value -- CAST avoids driver error for sql_variant type + FROM sys.sequences AS seq'; + } + + /** + * {@inheritdoc} + */ + public function getSequenceNextValSQL($sequenceName) + { + return 'SELECT NEXT VALUE FOR ' . $sequenceName; + } + + /** + * {@inheritdoc} + */ + public function supportsSequences() + { + return true; + } + + /** + * {@inheritdoc} + * + * Returns Microsoft SQL Server 2012 specific keywords class + */ + protected function getReservedKeywordsClass() + { + return Keywords\SQLServer2012Keywords::class; + } + + /** + * {@inheritdoc} + */ + protected function doModifyLimitQuery($query, $limit, $offset = null) + { + if ($limit === null && $offset <= 0) { + return $query; + } + + // Queries using OFFSET... FETCH MUST have an ORDER BY clause + // Find the position of the last instance of ORDER BY and ensure it is not within a parenthetical statement + // but can be in a newline + $matches = []; + $matchesCount = preg_match_all('/[\\s]+order\\s+by\\s/im', $query, $matches, PREG_OFFSET_CAPTURE); + $orderByPos = false; + if ($matchesCount > 0) { + $orderByPos = $matches[0][($matchesCount - 1)][1]; + } + + if ($orderByPos === false + || substr_count($query, '(', $orderByPos) - substr_count($query, ')', $orderByPos) + ) { + if (preg_match('/^SELECT\s+DISTINCT/im', $query)) { + // SQL Server won't let us order by a non-selected column in a DISTINCT query, + // so we have to do this madness. This says, order by the first column in the + // result. SQL Server's docs say that a nonordered query's result order is non- + // deterministic anyway, so this won't do anything that a bunch of update and + // deletes to the table wouldn't do anyway. + $query .= ' ORDER BY 1'; + } else { + // In another DBMS, we could do ORDER BY 0, but SQL Server gets angry if you + // use constant expressions in the order by list. + $query .= ' ORDER BY (SELECT 0)'; + } + } + + if ($offset === null) { + $offset = 0; + } + + // This looks somewhat like MYSQL, but limit/offset are in inverse positions + // Supposedly SQL:2008 core standard. + // Per TSQL spec, FETCH NEXT n ROWS ONLY is not valid without OFFSET n ROWS. + $query .= ' OFFSET ' . (int) $offset . ' ROWS'; + + if ($limit !== null) { + $query .= ' FETCH NEXT ' . (int) $limit . ' ROWS ONLY'; + } + + return $query; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php new file mode 100644 index 0000000..a37f7c9 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php @@ -0,0 +1,1695 @@ +getConvertExpression('date', 'GETDATE()'); + } + + /** + * {@inheritdoc} + */ + public function getCurrentTimeSQL() + { + return $this->getConvertExpression('time', 'GETDATE()'); + } + + /** + * Returns an expression that converts an expression of one data type to another. + * + * @param string $dataType The target native data type. Alias data types cannot be used. + * @param string $expression The SQL expression to convert. + * + * @return string + */ + private function getConvertExpression($dataType, $expression) + { + return sprintf('CONVERT(%s, %s)', $dataType, $expression); + } + + /** + * {@inheritdoc} + */ + protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + { + $factorClause = ''; + + if ($operator === '-') { + $factorClause = '-1 * '; + } + + return 'DATEADD(' . $unit . ', ' . $factorClause . $interval . ', ' . $date . ')'; + } + + /** + * {@inheritDoc} + */ + public function getDateDiffExpression($date1, $date2) + { + return 'DATEDIFF(day, ' . $date2 . ',' . $date1 . ')'; + } + + /** + * {@inheritDoc} + * + * Microsoft SQL Server prefers "autoincrement" identity columns + * since sequences can only be emulated with a table. + */ + public function prefersIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + * + * Microsoft SQL Server supports this through AUTO_INCREMENT columns. + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsReleaseSavepoints() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function supportsSchemas() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getDefaultSchemaName() + { + return 'dbo'; + } + + /** + * {@inheritDoc} + */ + public function supportsColumnCollation() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function hasNativeGuidType() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getCreateDatabaseSQL($name) + { + return 'CREATE DATABASE ' . $name; + } + + /** + * {@inheritDoc} + */ + public function getDropDatabaseSQL($name) + { + return 'DROP DATABASE ' . $name; + } + + /** + * {@inheritDoc} + */ + public function supportsCreateDropDatabase() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getCreateSchemaSQL($schemaName) + { + return 'CREATE SCHEMA ' . $schemaName; + } + + /** + * {@inheritDoc} + */ + public function getDropForeignKeySQL($foreignKey, $table) + { + if (! $foreignKey instanceof ForeignKeyConstraint) { + $foreignKey = new Identifier($foreignKey); + } + + if (! $table instanceof Table) { + $table = new Identifier($table); + } + + $foreignKey = $foreignKey->getQuotedName($this); + $table = $table->getQuotedName($this); + + return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey; + } + + /** + * {@inheritDoc} + */ + public function getDropIndexSQL($index, $table = null) + { + if ($index instanceof Index) { + $index = $index->getQuotedName($this); + } elseif (! 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; + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + return sprintf( + <<getCommentOnTableSQL($tableName, $tableComment); + } + + // @todo does other code breaks because of this? + // force primary keys to be not null + foreach ($columns as &$column) { + if (isset($column['primary']) && $column['primary']) { + $column['notnull'] = true; + } + + // Build default constraints SQL statements. + if (isset($column['default'])) { + $defaultConstraintsSql[] = 'ALTER TABLE ' . $tableName . + ' ADD' . $this->getDefaultConstraintDeclarationSQL($tableName, $column); + } + + if (empty($column['comment']) && ! is_numeric($column['comment'])) { + continue; + } + + $commentsSql[] = $this->getCreateColumnCommentSQL($tableName, $column['name'], $column['comment']); + } + + $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'])) { + $flags = ''; + if (isset($options['primary_index']) && $options['primary_index']->hasFlag('nonclustered')) { + $flags = ' NONCLUSTERED'; + } + $columnListSql .= ', PRIMARY KEY' . $flags . ' (' . 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 array_merge($sql, $commentsSql, $defaultConstraintsSql); + } + + /** + * {@inheritDoc} + */ + public function getCreatePrimaryKeySQL(Index $index, $table) + { + if ($table instanceof Table) { + $identifier = $table->getQuotedName($this); + } else { + $identifier = $table; + } + + $sql = 'ALTER TABLE ' . $identifier . ' ADD PRIMARY KEY'; + + if ($index->hasFlag('nonclustered')) { + $sql .= ' NONCLUSTERED'; + } + + return $sql . ' (' . $this->getIndexFieldDeclarationListSQL($index) . ')'; + } + + /** + * Returns the SQL statement for creating a column comment. + * + * SQL Server does not support native column comments, + * therefore the extended properties functionality is used + * as a workaround to store them. + * The property name used to store column comments is "MS_Description" + * which provides compatibility with SQL Server Management Studio, + * as column comments are stored in the same property there when + * specifying a column's "Description" attribute. + * + * @param string $tableName The quoted table name to which the column belongs. + * @param string $columnName The quoted column name to create the comment for. + * @param string|null $comment The column's comment. + * + * @return string + */ + protected function getCreateColumnCommentSQL($tableName, $columnName, $comment) + { + if (strpos($tableName, '.') !== false) { + [$schemaSQL, $tableSQL] = explode('.', $tableName); + $schemaSQL = $this->quoteStringLiteral($schemaSQL); + $tableSQL = $this->quoteStringLiteral($tableSQL); + } else { + $schemaSQL = "'dbo'"; + $tableSQL = $this->quoteStringLiteral($tableName); + } + + return $this->getAddExtendedPropertySQL( + 'MS_Description', + $comment, + 'SCHEMA', + $schemaSQL, + 'TABLE', + $tableSQL, + 'COLUMN', + $columnName + ); + } + + /** + * Returns the SQL snippet for declaring a default constraint. + * + * @param string $table Name of the table to return the default constraint declaration for. + * @param mixed[] $column Column definition. + * + * @return string + * + * @throws InvalidArgumentException + */ + public function getDefaultConstraintDeclarationSQL($table, array $column) + { + if (! isset($column['default'])) { + throw new InvalidArgumentException("Incomplete column definition. 'default' required."); + } + + $columnName = new Identifier($column['name']); + + return ' CONSTRAINT ' . + $this->generateDefaultConstraintName($table, $column['name']) . + $this->getDefaultValueDeclarationSQL($column) . + ' FOR ' . $columnName->getQuotedName($this); + } + + /** + * {@inheritDoc} + */ + public function getUniqueConstraintDeclarationSQL($name, Index $index) + { + $constraint = parent::getUniqueConstraintDeclarationSQL($name, $index); + + $constraint = $this->_appendUniqueConstraintDefinition($constraint, $index); + + return $constraint; + } + + /** + * {@inheritDoc} + */ + public function getCreateIndexSQL(Index $index, $table) + { + $constraint = parent::getCreateIndexSQL($index, $table); + + if ($index->isUnique() && ! $index->isPrimary()) { + $constraint = $this->_appendUniqueConstraintDefinition($constraint, $index); + } + + return $constraint; + } + + /** + * {@inheritDoc} + */ + protected function getCreateIndexSQLFlags(Index $index) + { + $type = ''; + if ($index->isUnique()) { + $type .= 'UNIQUE '; + } + + if ($index->hasFlag('clustered')) { + $type .= 'CLUSTERED '; + } elseif ($index->hasFlag('nonclustered')) { + $type .= 'NONCLUSTERED '; + } + + return $type; + } + + /** + * Extend unique key constraint with required filters + * + * @param string $sql + * + * @return string + */ + private function _appendUniqueConstraintDefinition($sql, Index $index) + { + $fields = []; + + foreach ($index->getQuotedColumns($this) as $field) { + $fields[] = $field . ' IS NOT NULL'; + } + + return $sql . ' WHERE ' . implode(' AND ', $fields); + } + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $queryParts = []; + $sql = []; + $columnSql = []; + $commentsSql = []; + + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $columnDef = $column->toArray(); + $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); + + if (isset($columnDef['default'])) { + $queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column); + } + + $comment = $this->getColumnComment($column); + + if (empty($comment) && ! is_numeric($comment)) { + continue; + } + + $commentsSql[] = $this->getCreateColumnCommentSQL( + $diff->name, + $column->getQuotedName($this), + $comment + ); + } + + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $queryParts[] = 'DROP COLUMN ' . $column->getQuotedName($this); + } + + foreach ($diff->changedColumns as $columnDiff) { + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + $column = $columnDiff->column; + $comment = $this->getColumnComment($column); + $hasComment = ! empty($comment) || is_numeric($comment); + + if ($columnDiff->fromColumn instanceof Column) { + $fromComment = $this->getColumnComment($columnDiff->fromColumn); + $hasFromComment = ! empty($fromComment) || is_numeric($fromComment); + + if ($hasFromComment && $hasComment && $fromComment !== $comment) { + $commentsSql[] = $this->getAlterColumnCommentSQL( + $diff->name, + $column->getQuotedName($this), + $comment + ); + } elseif ($hasFromComment && ! $hasComment) { + $commentsSql[] = $this->getDropColumnCommentSQL($diff->name, $column->getQuotedName($this)); + } elseif ($hasComment) { + $commentsSql[] = $this->getCreateColumnCommentSQL( + $diff->name, + $column->getQuotedName($this), + $comment + ); + } + } + + // Do not add query part if only comment has changed. + if ($columnDiff->hasChanged('comment') && count($columnDiff->changedProperties) === 1) { + continue; + } + + $requireDropDefaultConstraint = $this->alterColumnRequiresDropDefaultConstraint($columnDiff); + + if ($requireDropDefaultConstraint) { + $queryParts[] = $this->getAlterTableDropDefaultConstraintClause( + $diff->name, + $columnDiff->oldColumnName + ); + } + + $columnDef = $column->toArray(); + + $queryParts[] = 'ALTER COLUMN ' . + $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); + + if (! isset($columnDef['default']) || (! $requireDropDefaultConstraint && ! $columnDiff->hasChanged('default'))) { + continue; + } + + $queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column); + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $oldColumnName = new Identifier($oldColumnName); + + $sql[] = "sp_RENAME '" . + $diff->getName($this)->getQuotedName($this) . '.' . $oldColumnName->getQuotedName($this) . + "', '" . $column->getQuotedName($this) . "', 'COLUMN'"; + + // Recreate default constraint with new column name if necessary (for future reference). + if ($column->getDefault() === null) { + continue; + } + + $queryParts[] = $this->getAlterTableDropDefaultConstraintClause( + $diff->name, + $oldColumnName->getQuotedName($this) + ); + $queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column); + } + + $tableSql = []; + + if ($this->onSchemaAlterTable($diff, $tableSql)) { + return array_merge($tableSql, $columnSql); + } + + foreach ($queryParts as $query) { + $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; + } + + $sql = array_merge($sql, $commentsSql); + + $newName = $diff->getNewName(); + + if ($newName !== false) { + $sql[] = "sp_RENAME '" . $diff->getName($this)->getQuotedName($this) . "', '" . $newName->getName() . "'"; + + /** + * Rename table's default constraints names + * to match the new table name. + * This is necessary to ensure that the default + * constraints can be referenced in future table + * alterations as the table name is encoded in + * default constraints' names. + */ + $sql[] = "DECLARE @sql NVARCHAR(MAX) = N''; " . + "SELECT @sql += N'EXEC sp_rename N''' + dc.name + ''', N''' " . + "+ REPLACE(dc.name, '" . $this->generateIdentifierName($diff->name) . "', " . + "'" . $this->generateIdentifierName($newName->getName()) . "') + ''', ''OBJECT'';' " . + 'FROM sys.default_constraints dc ' . + 'JOIN sys.tables tbl ON dc.parent_object_id = tbl.object_id ' . + "WHERE tbl.name = '" . $newName->getName() . "';" . + 'EXEC sp_executesql @sql'; + } + + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * Returns the SQL clause for adding a default constraint in an ALTER TABLE statement. + * + * @param string $tableName The name of the table to generate the clause for. + * @param Column $column The column to generate the clause for. + * + * @return string + */ + private function getAlterTableAddDefaultConstraintClause($tableName, Column $column) + { + $columnDef = $column->toArray(); + $columnDef['name'] = $column->getQuotedName($this); + + return 'ADD' . $this->getDefaultConstraintDeclarationSQL($tableName, $columnDef); + } + + /** + * Returns the SQL clause for dropping an existing default constraint in an ALTER TABLE statement. + * + * @param string $tableName The name of the table to generate the clause for. + * @param string $columnName The name of the column to generate the clause for. + * + * @return string + */ + private function getAlterTableDropDefaultConstraintClause($tableName, $columnName) + { + return 'DROP CONSTRAINT ' . $this->generateDefaultConstraintName($tableName, $columnName); + } + + /** + * Checks whether a column alteration requires dropping its default constraint first. + * + * Different to other database vendors SQL Server implements column default values + * as constraints and therefore changes in a column's default value as well as changes + * in a column's type require dropping the default constraint first before being to + * alter the particular column to the new definition. + * + * @param ColumnDiff $columnDiff The column diff to evaluate. + * + * @return bool True if the column alteration requires dropping its default constraint first, false otherwise. + */ + private function alterColumnRequiresDropDefaultConstraint(ColumnDiff $columnDiff) + { + // We can only decide whether to drop an existing default constraint + // if we know the original default value. + if (! $columnDiff->fromColumn instanceof Column) { + return false; + } + + // We only need to drop an existing default constraint if we know the + // column was defined with a default value before. + if ($columnDiff->fromColumn->getDefault() === null) { + return false; + } + + // We need to drop an existing default constraint if the column was + // defined with a default value before and it has changed. + if ($columnDiff->hasChanged('default')) { + return true; + } + + // We need to drop an existing default constraint if the column was + // defined with a default value before and the native column type has changed. + return $columnDiff->hasChanged('type') || $columnDiff->hasChanged('fixed'); + } + + /** + * Returns the SQL statement for altering a column comment. + * + * SQL Server does not support native column comments, + * therefore the extended properties functionality is used + * as a workaround to store them. + * The property name used to store column comments is "MS_Description" + * which provides compatibility with SQL Server Management Studio, + * as column comments are stored in the same property there when + * specifying a column's "Description" attribute. + * + * @param string $tableName The quoted table name to which the column belongs. + * @param string $columnName The quoted column name to alter the comment for. + * @param string|null $comment The column's comment. + * + * @return string + */ + protected function getAlterColumnCommentSQL($tableName, $columnName, $comment) + { + if (strpos($tableName, '.') !== false) { + [$schemaSQL, $tableSQL] = explode('.', $tableName); + $schemaSQL = $this->quoteStringLiteral($schemaSQL); + $tableSQL = $this->quoteStringLiteral($tableSQL); + } else { + $schemaSQL = "'dbo'"; + $tableSQL = $this->quoteStringLiteral($tableName); + } + + return $this->getUpdateExtendedPropertySQL( + 'MS_Description', + $comment, + 'SCHEMA', + $schemaSQL, + 'TABLE', + $tableSQL, + 'COLUMN', + $columnName + ); + } + + /** + * Returns the SQL statement for dropping a column comment. + * + * SQL Server does not support native column comments, + * therefore the extended properties functionality is used + * as a workaround to store them. + * The property name used to store column comments is "MS_Description" + * which provides compatibility with SQL Server Management Studio, + * as column comments are stored in the same property there when + * specifying a column's "Description" attribute. + * + * @param string $tableName The quoted table name to which the column belongs. + * @param string $columnName The quoted column name to drop the comment for. + * + * @return string + */ + protected function getDropColumnCommentSQL($tableName, $columnName) + { + if (strpos($tableName, '.') !== false) { + [$schemaSQL, $tableSQL] = explode('.', $tableName); + $schemaSQL = $this->quoteStringLiteral($schemaSQL); + $tableSQL = $this->quoteStringLiteral($tableSQL); + } else { + $schemaSQL = "'dbo'"; + $tableSQL = $this->quoteStringLiteral($tableName); + } + + return $this->getDropExtendedPropertySQL( + 'MS_Description', + 'SCHEMA', + $schemaSQL, + 'TABLE', + $tableSQL, + 'COLUMN', + $columnName + ); + } + + /** + * {@inheritdoc} + */ + protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) + { + return [sprintf( + "EXEC sp_RENAME N'%s.%s', N'%s', N'INDEX'", + $tableName, + $oldIndexName, + $index->getQuotedName($this) + ), + ]; + } + + /** + * Returns the SQL statement for adding an extended property to a database object. + * + * @link http://msdn.microsoft.com/en-us/library/ms180047%28v=sql.90%29.aspx + * + * @param string $name The name of the property to add. + * @param string|null $value The value of the property to add. + * @param string|null $level0Type The type of the object at level 0 the property belongs to. + * @param string|null $level0Name The name of the object at level 0 the property belongs to. + * @param string|null $level1Type The type of the object at level 1 the property belongs to. + * @param string|null $level1Name The name of the object at level 1 the property belongs to. + * @param string|null $level2Type The type of the object at level 2 the property belongs to. + * @param string|null $level2Name The name of the object at level 2 the property belongs to. + * + * @return string + */ + public function getAddExtendedPropertySQL( + $name, + $value = null, + $level0Type = null, + $level0Name = null, + $level1Type = null, + $level1Name = null, + $level2Type = null, + $level2Name = null + ) { + return 'EXEC sp_addextendedproperty ' . + 'N' . $this->quoteStringLiteral($name) . ', N' . $this->quoteStringLiteral((string) $value) . ', ' . + 'N' . $this->quoteStringLiteral((string) $level0Type) . ', ' . $level0Name . ', ' . + 'N' . $this->quoteStringLiteral((string) $level1Type) . ', ' . $level1Name . ', ' . + 'N' . $this->quoteStringLiteral((string) $level2Type) . ', ' . $level2Name; + } + + /** + * Returns the SQL statement for dropping an extended property from a database object. + * + * @link http://technet.microsoft.com/en-gb/library/ms178595%28v=sql.90%29.aspx + * + * @param string $name The name of the property to drop. + * @param string|null $level0Type The type of the object at level 0 the property belongs to. + * @param string|null $level0Name The name of the object at level 0 the property belongs to. + * @param string|null $level1Type The type of the object at level 1 the property belongs to. + * @param string|null $level1Name The name of the object at level 1 the property belongs to. + * @param string|null $level2Type The type of the object at level 2 the property belongs to. + * @param string|null $level2Name The name of the object at level 2 the property belongs to. + * + * @return string + */ + public function getDropExtendedPropertySQL( + $name, + $level0Type = null, + $level0Name = null, + $level1Type = null, + $level1Name = null, + $level2Type = null, + $level2Name = null + ) { + return 'EXEC sp_dropextendedproperty ' . + 'N' . $this->quoteStringLiteral($name) . ', ' . + 'N' . $this->quoteStringLiteral((string) $level0Type) . ', ' . $level0Name . ', ' . + 'N' . $this->quoteStringLiteral((string) $level1Type) . ', ' . $level1Name . ', ' . + 'N' . $this->quoteStringLiteral((string) $level2Type) . ', ' . $level2Name; + } + + /** + * Returns the SQL statement for updating an extended property of a database object. + * + * @link http://msdn.microsoft.com/en-us/library/ms186885%28v=sql.90%29.aspx + * + * @param string $name The name of the property to update. + * @param string|null $value The value of the property to update. + * @param string|null $level0Type The type of the object at level 0 the property belongs to. + * @param string|null $level0Name The name of the object at level 0 the property belongs to. + * @param string|null $level1Type The type of the object at level 1 the property belongs to. + * @param string|null $level1Name The name of the object at level 1 the property belongs to. + * @param string|null $level2Type The type of the object at level 2 the property belongs to. + * @param string|null $level2Name The name of the object at level 2 the property belongs to. + * + * @return string + */ + public function getUpdateExtendedPropertySQL( + $name, + $value = null, + $level0Type = null, + $level0Name = null, + $level1Type = null, + $level1Name = null, + $level2Type = null, + $level2Name = null + ) { + return 'EXEC sp_updateextendedproperty ' . + 'N' . $this->quoteStringLiteral($name) . ', N' . $this->quoteStringLiteral((string) $value) . ', ' . + 'N' . $this->quoteStringLiteral((string) $level0Type) . ', ' . $level0Name . ', ' . + 'N' . $this->quoteStringLiteral((string) $level1Type) . ', ' . $level1Name . ', ' . + 'N' . $this->quoteStringLiteral((string) $level2Type) . ', ' . $level2Name; + } + + /** + * {@inheritDoc} + */ + public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName) + { + return 'INSERT INTO ' . $quotedTableName . ' DEFAULT VALUES'; + } + + /** + * {@inheritDoc} + */ + public function getListTablesSQL() + { + // "sysdiagrams" table must be ignored as it's internal SQL Server table for Database Diagrams + // Category 2 must be ignored as it is "MS SQL Server 'pseudo-system' object[s]" for replication + return "SELECT name FROM sysobjects WHERE type = 'U' AND name != 'sysdiagrams' AND category != 2 ORDER BY name"; + } + + /** + * {@inheritDoc} + */ + public function getListTableColumnsSQL($table, $database = null) + { + return "SELECT col.name, + type.name AS type, + col.max_length AS length, + ~col.is_nullable AS notnull, + def.definition AS [default], + col.scale, + col.precision, + col.is_identity AS autoincrement, + col.collation_name AS collation, + CAST(prop.value AS NVARCHAR(MAX)) AS comment -- CAST avoids driver error for sql_variant type + FROM sys.columns AS col + JOIN sys.types AS type + ON col.user_type_id = type.user_type_id + JOIN sys.objects AS obj + ON col.object_id = obj.object_id + JOIN sys.schemas AS scm + ON obj.schema_id = scm.schema_id + LEFT JOIN sys.default_constraints def + ON col.default_object_id = def.object_id + AND col.object_id = def.parent_object_id + LEFT JOIN sys.extended_properties AS prop + ON obj.object_id = prop.major_id + AND col.column_id = prop.minor_id + AND prop.name = 'MS_Description' + WHERE obj.type = 'U' + AND " . $this->getTableWhereClause($table, 'scm.name', 'obj.name'); + } + + /** + * {@inheritDoc} + */ + 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 ' . + $this->getTableWhereClause($table, 'SCHEMA_NAME (f.schema_id)', 'OBJECT_NAME (f.parent_object_id)'); + } + + /** + * {@inheritDoc} + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + return "SELECT idx.name AS key_name, + col.name AS column_name, + ~idx.is_unique AS non_unique, + idx.is_primary_key AS [primary], + CASE idx.type + WHEN '1' THEN 'clustered' + WHEN '2' THEN 'nonclustered' + ELSE NULL + END AS flags + FROM sys.tables AS tbl + JOIN sys.schemas AS scm ON tbl.schema_id = scm.schema_id + JOIN sys.indexes AS idx ON tbl.object_id = idx.object_id + JOIN sys.index_columns AS idxcol ON idx.object_id = idxcol.object_id AND idx.index_id = idxcol.index_id + JOIN sys.columns AS col ON idxcol.object_id = col.object_id AND idxcol.column_id = col.column_id + WHERE " . $this->getTableWhereClause($table, 'scm.name', 'tbl.name') . ' + ORDER BY idx.index_id ASC, idxcol.key_ordinal ASC'; + } + + /** + * {@inheritDoc} + */ + public function getCreateViewSQL($name, $sql) + { + return 'CREATE VIEW ' . $name . ' AS ' . $sql; + } + + /** + * {@inheritDoc} + */ + public function getListViewsSQL($database) + { + return "SELECT name FROM sysobjects WHERE type = 'V' ORDER BY name"; + } + + /** + * Returns the where clause to filter schema and table name in a query. + * + * @param string $table The full qualified name of the table. + * @param string $schemaColumn The name of the column to compare the schema to in the where clause. + * @param string $tableColumn The name of the column to compare the table to in the where clause. + * + * @return string + */ + private function getTableWhereClause($table, $schemaColumn, $tableColumn) + { + if (strpos($table, '.') !== false) { + [$schema, $table] = explode('.', $table); + $schema = $this->quoteStringLiteral($schema); + $table = $this->quoteStringLiteral($table); + } else { + $schema = 'SCHEMA_NAME()'; + $table = $this->quoteStringLiteral($table); + } + + return sprintf('(%s = %s AND %s = %s)', $tableColumn, $table, $schemaColumn, $schema); + } + + /** + * {@inheritDoc} + */ + public function getDropViewSQL($name) + { + return 'DROP VIEW ' . $name; + } + + /** + * {@inheritDoc} + * + * @deprecated Use application-generated UUIDs instead + */ + public function getGuidExpression() + { + return 'NEWID()'; + } + + /** + * {@inheritDoc} + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + if ($startPos === false) { + return 'CHARINDEX(' . $substr . ', ' . $str . ')'; + } + + return 'CHARINDEX(' . $substr . ', ' . $str . ', ' . $startPos . ')'; + } + + /** + * {@inheritDoc} + */ + public function getModExpression($expression1, $expression2) + { + return $expression1 . ' % ' . $expression2; + } + + /** + * {@inheritDoc} + */ + public function getTrimExpression($str, $pos = TrimMode::UNSPECIFIED, $char = false) + { + if (! $char) { + switch ($pos) { + case TrimMode::LEADING: + $trimFn = 'LTRIM'; + break; + + case TrimMode::TRAILING: + $trimFn = 'RTRIM'; + break; + + default: + return 'LTRIM(RTRIM(' . $str . '))'; + } + + return $trimFn . '(' . $str . ')'; + } + + /** Original query used to get those expressions + declare @c varchar(100) = 'xxxBarxxx', @trim_char char(1) = 'x'; + declare @pat varchar(10) = '%[^' + @trim_char + ']%'; + select @c as string + , @trim_char as trim_char + , stuff(@c, 1, patindex(@pat, @c) - 1, null) as trim_leading + , reverse(stuff(reverse(@c), 1, patindex(@pat, reverse(@c)) - 1, null)) as trim_trailing + , reverse(stuff(reverse(stuff(@c, 1, patindex(@pat, @c) - 1, null)), 1, patindex(@pat, reverse(stuff(@c, 1, patindex(@pat, @c) - 1, null))) - 1, null)) as trim_both; + */ + $pattern = "'%[^' + " . $char . " + ']%'"; + + if ($pos === TrimMode::LEADING) { + return 'stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null)'; + } + + if ($pos === TrimMode::TRAILING) { + return 'reverse(stuff(reverse(' . $str . '), 1, patindex(' . $pattern . ', reverse(' . $str . ')) - 1, null))'; + } + + return 'reverse(stuff(reverse(stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null)), 1, patindex(' . $pattern . ', reverse(stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null))) - 1, null))'; + } + + /** + * {@inheritDoc} + */ + public function getConcatExpression() + { + $args = func_get_args(); + + return '(' . implode(' + ', $args) . ')'; + } + + /** + * {@inheritDoc} + */ + public function getListDatabasesSQL() + { + return 'SELECT * FROM sys.databases'; + } + + /** + * {@inheritDoc} + */ + public function getListNamespacesSQL() + { + return "SELECT name FROM sys.schemas WHERE name NOT IN('guest', 'INFORMATION_SCHEMA', 'sys')"; + } + + /** + * {@inheritDoc} + */ + public function getSubstringExpression($value, $from, $length = null) + { + if ($length !== null) { + return 'SUBSTRING(' . $value . ', ' . $from . ', ' . $length . ')'; + } + + return 'SUBSTRING(' . $value . ', ' . $from . ', LEN(' . $value . ') - ' . $from . ' + 1)'; + } + + /** + * {@inheritDoc} + */ + public function getLengthExpression($column) + { + return 'LEN(' . $column . ')'; + } + + /** + * {@inheritDoc} + */ + public function getSetTransactionIsolationSQL($level) + { + return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level); + } + + /** + * {@inheritDoc} + */ + public function getIntegerTypeDeclarationSQL(array $field) + { + return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $field) + { + return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $field) + { + return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getGuidTypeDeclarationSQL(array $field) + { + return 'UNIQUEIDENTIFIER'; + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? ($length ? 'NCHAR(' . $length . ')' : 'CHAR(255)') : ($length ? 'NVARCHAR(' . $length . ')' : 'NVARCHAR(255)'); + } + + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? 'BINARY(' . ($length ?: 255) . ')' : 'VARBINARY(' . ($length ?: 255) . ')'; + } + + /** + * {@inheritdoc} + */ + public function getBinaryMaxLength() + { + return 8000; + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + return 'VARCHAR(MAX)'; + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + return ! empty($columnDef['autoincrement']) ? ' IDENTITY' : ''; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATETIME'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATETIME'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATETIME'; + } + + /** + * {@inheritDoc} + */ + public function getBooleanTypeDeclarationSQL(array $field) + { + return 'BIT'; + } + + /** + * {@inheritDoc} + */ + protected function doModifyLimitQuery($query, $limit, $offset = null) + { + $where = []; + + if ($offset > 0) { + $where[] = sprintf('doctrine_rownum >= %d', $offset + 1); + } + + if ($limit !== null) { + $where[] = sprintf('doctrine_rownum <= %d', $offset + $limit); + $top = sprintf('TOP %d', $offset + $limit); + } else { + $top = 'TOP 9223372036854775807'; + } + + if (empty($where)) { + return $query; + } + + // We'll find a SELECT or SELECT distinct and prepend TOP n to it + // Even if the TOP n is very large, the use of a CTE will + // allow the SQL Server query planner to optimize it so it doesn't + // actually scan the entire range covered by the TOP clause. + if (! preg_match('/^(\s*SELECT\s+(?:DISTINCT\s+)?)(.*)$/is', $query, $matches)) { + return $query; + } + + $query = $matches[1] . $top . ' ' . $matches[2]; + + if (stristr($query, 'ORDER BY')) { + // Inner order by is not valid in SQL Server for our purposes + // unless it's in a TOP N subquery. + $query = $this->scrubInnerOrderBy($query); + } + + // Build a new limited query around the original, using a CTE + return sprintf( + 'WITH dctrn_cte AS (%s) ' + . 'SELECT * FROM (' + . 'SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM dctrn_cte' + . ') AS doctrine_tbl ' + . 'WHERE %s ORDER BY doctrine_rownum ASC', + $query, + implode(' AND ', $where) + ); + } + + /** + * Remove ORDER BY clauses in subqueries - they're not supported by SQL Server. + * Caveat: will leave ORDER BY in TOP N subqueries. + * + * @param string $query + * + * @return string + */ + private function scrubInnerOrderBy($query) + { + $count = substr_count(strtoupper($query), 'ORDER BY'); + $offset = 0; + + while ($count-- > 0) { + $orderByPos = stripos($query, ' ORDER BY', $offset); + if ($orderByPos === false) { + break; + } + + $qLen = strlen($query); + $parenCount = 0; + $currentPosition = $orderByPos; + + while ($parenCount >= 0 && $currentPosition < $qLen) { + if ($query[$currentPosition] === '(') { + $parenCount++; + } elseif ($query[$currentPosition] === ')') { + $parenCount--; + } + + $currentPosition++; + } + + if ($this->isOrderByInTopNSubquery($query, $orderByPos)) { + // If the order by clause is in a TOP N subquery, do not remove + // it and continue iteration from the current position. + $offset = $currentPosition; + continue; + } + + if ($currentPosition >= $qLen - 1) { + continue; + } + + $query = substr($query, 0, $orderByPos) . substr($query, $currentPosition - 1); + $offset = $orderByPos; + } + + return $query; + } + + /** + * Check an ORDER BY clause to see if it is in a TOP N query or subquery. + * + * @param string $query The query + * @param int $currentPosition Start position of ORDER BY clause + * + * @return bool true if ORDER BY is in a TOP N query, false otherwise + */ + private function isOrderByInTopNSubquery($query, $currentPosition) + { + // Grab query text on the same nesting level as the ORDER BY clause we're examining. + $subQueryBuffer = ''; + $parenCount = 0; + + // If $parenCount goes negative, we've exited the subquery we're examining. + // If $currentPosition goes negative, we've reached the beginning of the query. + while ($parenCount >= 0 && $currentPosition >= 0) { + if ($query[$currentPosition] === '(') { + $parenCount--; + } elseif ($query[$currentPosition] === ')') { + $parenCount++; + } + + // Only yank query text on the same nesting level as the ORDER BY clause. + $subQueryBuffer = ($parenCount === 0 ? $query[$currentPosition] : ' ') . $subQueryBuffer; + + $currentPosition--; + } + + return (bool) preg_match('/SELECT\s+(DISTINCT\s+)?TOP\s/i', $subQueryBuffer); + } + + /** + * {@inheritDoc} + */ + public function supportsLimitOffset() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function convertBooleans($item) + { + if (is_array($item)) { + foreach ($item as $key => $value) { + if (! is_bool($value) && ! is_numeric($value)) { + continue; + } + + $item[$key] = $value ? 1 : 0; + } + } elseif (is_bool($item) || is_numeric($item)) { + $item = $item ? 1 : 0; + } + + return $item; + } + + /** + * {@inheritDoc} + */ + public function getCreateTemporaryTableSnippetSQL() + { + return 'CREATE TABLE'; + } + + /** + * {@inheritDoc} + */ + public function getTemporaryTableName($tableName) + { + return '#' . $tableName; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeFormatString() + { + return 'Y-m-d H:i:s.000'; + } + + /** + * {@inheritDoc} + */ + public function getDateFormatString() + { + return 'Y-m-d H:i:s.000'; + } + + /** + * {@inheritDoc} + */ + public function getTimeFormatString() + { + return 'Y-m-d H:i:s.000'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTzFormatString() + { + return $this->getDateTimeFormatString(); + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'mssql'; + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = [ + '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', + 'smalldatetime' => 'datetime', + 'datetime' => 'datetime', + 'char' => 'string', + 'varchar' => 'string', + 'text' => 'text', + 'nchar' => 'string', + 'nvarchar' => 'string', + 'ntext' => 'text', + 'binary' => 'binary', + 'varbinary' => 'binary', + 'image' => 'blob', + 'uniqueidentifier' => 'guid', + ]; + } + + /** + * {@inheritDoc} + */ + public function createSavePoint($savepoint) + { + return 'SAVE TRANSACTION ' . $savepoint; + } + + /** + * {@inheritDoc} + */ + public function releaseSavePoint($savepoint) + { + return ''; + } + + /** + * {@inheritDoc} + */ + public function rollbackSavePoint($savepoint) + { + return 'ROLLBACK TRANSACTION ' . $savepoint; + } + + /** + * {@inheritdoc} + */ + public function getForeignKeyReferentialActionSQL($action) + { + // RESTRICT is not supported, therefore falling back to NO ACTION. + if (strtoupper($action) === 'RESTRICT') { + return 'NO ACTION'; + } + + return parent::getForeignKeyReferentialActionSQL($action); + } + + /** + * {@inheritDoc} + */ + public function appendLockHint($fromClause, $lockMode) + { + switch (true) { + case $lockMode === LockMode::NONE: + return $fromClause . ' WITH (NOLOCK)'; + + case $lockMode === LockMode::PESSIMISTIC_READ: + return $fromClause . ' WITH (HOLDLOCK, ROWLOCK)'; + + case $lockMode === LockMode::PESSIMISTIC_WRITE: + return $fromClause . ' WITH (UPDLOCK, ROWLOCK)'; + + default: + return $fromClause; + } + } + + /** + * {@inheritDoc} + */ + public function getForUpdateSQL() + { + return ' '; + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return Keywords\SQLServerKeywords::class; + } + + /** + * {@inheritDoc} + */ + public function quoteSingleIdentifier($str) + { + return '[' . str_replace(']', '][', $str) . ']'; + } + + /** + * {@inheritDoc} + */ + public function getTruncateTableSQL($tableName, $cascade = false) + { + $tableIdentifier = new Identifier($tableName); + + return 'TRUNCATE TABLE ' . $tableIdentifier->getQuotedName($this); + } + + /** + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + return 'VARBINARY(MAX)'; + } + + /** + * {@inheritdoc} + * + * Modifies column declaration order as it differs in Microsoft SQL Server. + */ + public function getColumnDeclarationSQL($name, array $field) + { + if (isset($field['columnDefinition'])) { + $columnDef = $this->getCustomTypeDeclarationSQL($field); + } else { + $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 . $collation . $notnull . $unique . $check; + } + + return $name . ' ' . $columnDef; + } + + /** + * Returns a unique default constraint name for a table and column. + * + * @param string $table Name of the table to generate the unique default constraint name for. + * @param string $column Name of the column in the table to generate the unique default constraint name for. + * + * @return string + */ + private function generateDefaultConstraintName($table, $column) + { + return 'DF_' . $this->generateIdentifierName($table) . '_' . $this->generateIdentifierName($column); + } + + /** + * Returns a hash value for a given identifier. + * + * @param string $identifier Identifier to generate a hash value for. + * + * @return string + */ + private function generateIdentifierName($identifier) + { + // Always generate name for unquoted identifiers to ensure consistency. + $identifier = new Identifier($identifier); + + return strtoupper(dechex(crc32($identifier->getName()))); + } + + protected function getCommentOnTableSQL(string $tableName, ?string $comment) : string + { + return sprintf( + <<<'SQL' +EXEC sys.sp_addextendedproperty @name=N'MS_Description', + @value=N%s, @level0type=N'SCHEMA', @level0name=N'dbo', + @level1type=N'TABLE', @level1name=N%s +SQL + , + $this->quoteStringLiteral((string) $comment), + $this->quoteStringLiteral($tableName) + ); + } + + public function getListTableMetadataSQL(string $table) : string + { + return sprintf( + <<<'SQL' +SELECT + p.value AS [table_comment] +FROM + sys.tables AS tbl + INNER JOIN sys.extended_properties AS p ON p.major_id=tbl.object_id AND p.minor_id=0 AND p.class=1 +WHERE + (tbl.name=N%s and SCHEMA_NAME(tbl.schema_id)=N'dbo' and p.name=N'MS_Description') +SQL + , + $this->quoteStringLiteral($table) + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php new file mode 100644 index 0000000..02d2482 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php @@ -0,0 +1,1199 @@ +_getTransactionIsolationLevelSQL($level); + } + + /** + * {@inheritDoc} + */ + public function prefersIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getBooleanTypeDeclarationSQL(array $field) + { + return 'BOOLEAN'; + } + + /** + * {@inheritDoc} + */ + public function getIntegerTypeDeclarationSQL(array $field) + { + return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $field) + { + // SQLite autoincrement is implicit for INTEGER PKs, but not for BIGINT fields. + if (! empty($field['autoincrement'])) { + return $this->getIntegerTypeDeclarationSQL($field); + } + + return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getTinyIntTypeDeclarationSql(array $field) + { + // SQLite autoincrement is implicit for INTEGER PKs, but not for TINYINT fields. + if (! empty($field['autoincrement'])) { + return $this->getIntegerTypeDeclarationSQL($field); + } + + return 'TINYINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $field) + { + // SQLite autoincrement is implicit for INTEGER PKs, but not for SMALLINT fields. + if (! empty($field['autoincrement'])) { + return $this->getIntegerTypeDeclarationSQL($field); + } + + return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getMediumIntTypeDeclarationSql(array $field) + { + // SQLite autoincrement is implicit for INTEGER PKs, but not for MEDIUMINT fields. + if (! empty($field['autoincrement'])) { + return $this->getIntegerTypeDeclarationSQL($field); + } + + return 'MEDIUMINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATETIME'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME'; + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + // sqlite autoincrement is only possible for the primary key + if (! empty($columnDef['autoincrement'])) { + return ' PRIMARY KEY AUTOINCREMENT'; + } + + return ! empty($columnDef['unsigned']) ? ' UNSIGNED' : ''; + } + + /** + * {@inheritDoc} + */ + public function getForeignKeyDeclarationSQL(ForeignKeyConstraint $foreignKey) + { + return parent::getForeignKeyDeclarationSQL(new ForeignKeyConstraint( + $foreignKey->getQuotedLocalColumns($this), + str_replace('.', '__', $foreignKey->getQuotedForeignTableName($this)), + $foreignKey->getQuotedForeignColumns($this), + $foreignKey->getName(), + $foreignKey->getOptions() + )); + } + + /** + * {@inheritDoc} + */ + protected function _getCreateTableSQL($name, array $columns, array $options = []) + { + $name = str_replace('.', '__', $name); + $queryFields = $this->getColumnDeclarationListSQL($columns); + + if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) { + foreach ($options['uniqueConstraints'] as $name => $definition) { + $queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition); + } + } + + $queryFields .= $this->getNonAutoincrementPrimaryKeyDefinition($columns, $options); + + if (isset($options['foreignKeys'])) { + foreach ($options['foreignKeys'] as $foreignKey) { + $queryFields .= ', ' . $this->getForeignKeyDeclarationSQL($foreignKey); + } + } + + $tableComment = ''; + if (isset($options['comment'])) { + $comment = trim($options['comment'], " '"); + + $tableComment = $this->getInlineTableCommentSQL($comment); + } + + $query = ['CREATE TABLE ' . $name . ' ' . $tableComment . '(' . $queryFields . ')']; + + if (isset($options['alter']) && $options['alter'] === true) { + return $query; + } + + if (isset($options['indexes']) && ! empty($options['indexes'])) { + foreach ($options['indexes'] as $indexDef) { + $query[] = $this->getCreateIndexSQL($indexDef, $name); + } + } + + if (isset($options['unique']) && ! empty($options['unique'])) { + foreach ($options['unique'] as $indexDef) { + $query[] = $this->getCreateIndexSQL($indexDef, $name); + } + } + + return $query; + } + + /** + * Generate a PRIMARY KEY definition if no autoincrement value is used + * + * @param mixed[][] $columns + * @param mixed[] $options + */ + private function getNonAutoincrementPrimaryKeyDefinition(array $columns, array $options) : string + { + if (empty($options['primary'])) { + return ''; + } + + $keyColumns = array_unique(array_values($options['primary'])); + + foreach ($keyColumns as $keyColumn) { + if (! empty($columns[$keyColumn]['autoincrement'])) { + return ''; + } + } + + return ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') + : ($length ? 'VARCHAR(' . $length . ')' : 'TEXT'); + } + + /** + * {@inheritdoc} + */ + protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) + { + return 'BLOB'; + } + + /** + * {@inheritdoc} + */ + public function getBinaryMaxLength() + { + return 0; + } + + /** + * {@inheritdoc} + */ + public function getBinaryDefaultLength() + { + return 0; + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + return 'CLOB'; + } + + /** + * {@inheritDoc} + */ + public function getListTableConstraintsSQL($table) + { + $table = str_replace('.', '__', $table); + + return sprintf( + "SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name = %s AND sql NOT NULL ORDER BY name", + $this->quoteStringLiteral($table) + ); + } + + /** + * {@inheritDoc} + */ + public function getListTableColumnsSQL($table, $currentDatabase = null) + { + $table = str_replace('.', '__', $table); + + return sprintf('PRAGMA table_info(%s)', $this->quoteStringLiteral($table)); + } + + /** + * {@inheritDoc} + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + $table = str_replace('.', '__', $table); + + return sprintf('PRAGMA index_list(%s)', $this->quoteStringLiteral($table)); + } + + /** + * {@inheritDoc} + */ + public function getListTablesSQL() + { + return "SELECT name FROM sqlite_master WHERE type = 'table' AND name != 'sqlite_sequence' AND name != 'geometry_columns' AND name != 'spatial_ref_sys' " + . 'UNION ALL SELECT name FROM sqlite_temp_master ' + . "WHERE type = 'table' ORDER BY name"; + } + + /** + * {@inheritDoc} + */ + public function getListViewsSQL($database) + { + return "SELECT name, sql FROM sqlite_master WHERE type='view' AND sql NOT NULL"; + } + + /** + * {@inheritDoc} + */ + public function getCreateViewSQL($name, $sql) + { + return 'CREATE VIEW ' . $name . ' AS ' . $sql; + } + + /** + * {@inheritDoc} + */ + public function getDropViewSQL($name) + { + return 'DROP VIEW ' . $name; + } + + /** + * {@inheritDoc} + */ + public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) + { + $query = parent::getAdvancedForeignKeyOptionsSQL($foreignKey); + + $query .= ($foreignKey->hasOption('deferrable') && $foreignKey->getOption('deferrable') !== false ? ' ' : ' NOT ') . 'DEFERRABLE'; + $query .= ' INITIALLY ' . ($foreignKey->hasOption('deferred') && $foreignKey->getOption('deferred') !== false ? 'DEFERRED' : 'IMMEDIATE'); + + return $query; + } + + /** + * {@inheritDoc} + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsColumnCollation() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsInlineColumnComments() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'sqlite'; + } + + /** + * {@inheritDoc} + */ + public function getTruncateTableSQL($tableName, $cascade = false) + { + $tableIdentifier = new Identifier($tableName); + $tableName = str_replace('.', '__', $tableIdentifier->getQuotedName($this)); + + return 'DELETE FROM ' . $tableName; + } + + /** + * User-defined function for Sqlite that is used with PDO::sqliteCreateFunction(). + * + * @param int|float $value + * + * @return float + */ + public static function udfSqrt($value) + { + return sqrt($value); + } + + /** + * User-defined function for Sqlite that implements MOD(a, b). + * + * @param int $a + * @param int $b + * + * @return int + */ + public static function udfMod($a, $b) + { + return $a % $b; + } + + /** + * @param string $str + * @param string $substr + * @param int $offset + * + * @return int + */ + public static function udfLocate($str, $substr, $offset = 0) + { + // SQL's LOCATE function works on 1-based positions, while PHP's strpos works on 0-based positions. + // So we have to make them compatible if an offset is given. + if ($offset > 0) { + $offset -= 1; + } + + $pos = strpos($str, $substr, $offset); + + if ($pos !== false) { + return $pos + 1; + } + + return 0; + } + + /** + * {@inheritDoc} + */ + public function getForUpdateSql() + { + return ''; + } + + /** + * {@inheritDoc} + */ + public function getInlineColumnCommentSQL($comment) + { + return '--' . str_replace("\n", "\n--", $comment) . "\n"; + } + + private function getInlineTableCommentSQL(string $comment) : string + { + return $this->getInlineColumnCommentSQL($comment); + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = [ + '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', + 'longvarchar' => 'string', + 'varchar2' => 'string', + 'nvarchar' => 'string', + 'image' => 'string', + 'ntext' => 'string', + 'char' => 'string', + 'date' => 'date', + 'datetime' => 'datetime', + 'timestamp' => 'datetime', + 'time' => 'time', + 'float' => 'float', + 'double' => 'float', + 'double precision' => 'float', + 'real' => 'float', + 'decimal' => 'decimal', + 'numeric' => 'decimal', + 'blob' => 'blob', + ]; + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return Keywords\SQLiteKeywords::class; + } + + /** + * {@inheritDoc} + */ + protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) + { + if (! $diff->fromTable instanceof Table) { + throw new DBALException('Sqlite platform requires for alter table the table diff with reference to original table schema'); + } + + $sql = []; + foreach ($diff->fromTable->getIndexes() as $index) { + if ($index->isPrimary()) { + continue; + } + + $sql[] = $this->getDropIndexSQL($index, $diff->name); + } + + return $sql; + } + + /** + * {@inheritDoc} + */ + protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) + { + if (! $diff->fromTable instanceof Table) { + throw new DBALException('Sqlite platform requires for alter table the table diff with reference to original table schema'); + } + + $sql = []; + $tableName = $diff->getNewName(); + + if ($tableName === false) { + $tableName = $diff->getName($this); + } + + foreach ($this->getIndexesInAlteredTable($diff) as $index) { + if ($index->isPrimary()) { + continue; + } + + $sql[] = $this->getCreateIndexSQL($index, $tableName->getQuotedName($this)); + } + + return $sql; + } + + /** + * {@inheritDoc} + */ + protected function doModifyLimitQuery($query, $limit, $offset) + { + if ($limit === null && $offset > 0) { + return $query . ' LIMIT -1 OFFSET ' . $offset; + } + + return parent::doModifyLimitQuery($query, $limit, $offset); + } + + /** + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + return 'BLOB'; + } + + /** + * {@inheritDoc} + */ + public function getTemporaryTableName($tableName) + { + $tableName = str_replace('.', '__', $tableName); + + return $tableName; + } + + /** + * {@inheritDoc} + * + * Sqlite Platform emulates schema by underscoring each dot and generating tables + * into the default database. + * + * This hack is implemented to be able to use SQLite as testdriver when + * using schema supporting databases. + */ + public function canEmulateSchemas() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsForeignKeyConstraints() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function getCreatePrimaryKeySQL(Index $index, $table) + { + throw new DBALException('Sqlite platform does not support alter primary key.'); + } + + /** + * {@inheritdoc} + */ + public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table) + { + throw new DBALException('Sqlite platform does not support alter foreign key.'); + } + + /** + * {@inheritdoc} + */ + public function getDropForeignKeySQL($foreignKey, $table) + { + throw new DBALException('Sqlite platform does not support alter foreign key.'); + } + + /** + * {@inheritDoc} + */ + public function getCreateConstraintSQL(Constraint $constraint, $table) + { + throw new DBALException('Sqlite platform does not support alter constraint.'); + } + + /** + * {@inheritDoc} + */ + public function getCreateTableSQL(Table $table, $createFlags = null) + { + $createFlags = $createFlags ?? self::CREATE_INDEXES | self::CREATE_FOREIGNKEYS; + + return parent::getCreateTableSQL($table, $createFlags); + } + + /** + * {@inheritDoc} + */ + public function getListTableForeignKeysSQL($table, $database = null) + { + $table = str_replace('.', '__', $table); + + return sprintf('PRAGMA foreign_key_list(%s)', $this->quoteStringLiteral($table)); + } + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $sql = $this->getSimpleAlterTableSQL($diff); + if ($sql !== false) { + return $sql; + } + + $fromTable = $diff->fromTable; + if (! $fromTable instanceof Table) { + throw new DBALException('Sqlite platform requires for alter table the table diff with reference to original table schema'); + } + + $table = clone $fromTable; + + $columns = []; + $oldColumnNames = []; + $newColumnNames = []; + $columnSql = []; + + foreach ($table->getColumns() as $columnName => $column) { + $columnName = strtolower($columnName); + $columns[$columnName] = $column; + $oldColumnNames[$columnName] = $newColumnNames[$columnName] = $column->getQuotedName($this); + } + + foreach ($diff->removedColumns as $columnName => $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $columnName = strtolower($columnName); + if (! isset($columns[$columnName])) { + continue; + } + + unset( + $columns[$columnName], + $oldColumnNames[$columnName], + $newColumnNames[$columnName] + ); + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $oldColumnName = strtolower($oldColumnName); + if (isset($columns[$oldColumnName])) { + unset($columns[$oldColumnName]); + } + + $columns[strtolower($column->getName())] = $column; + + if (! isset($newColumnNames[$oldColumnName])) { + continue; + } + + $newColumnNames[$oldColumnName] = $column->getQuotedName($this); + } + + foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + if (isset($columns[$oldColumnName])) { + unset($columns[$oldColumnName]); + } + + $columns[strtolower($columnDiff->column->getName())] = $columnDiff->column; + + if (! isset($newColumnNames[$oldColumnName])) { + continue; + } + + $newColumnNames[$oldColumnName] = $columnDiff->column->getQuotedName($this); + } + + foreach ($diff->addedColumns as $columnName => $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $columns[strtolower($columnName)] = $column; + } + + $sql = []; + $tableSql = []; + if (! $this->onSchemaAlterTable($diff, $tableSql)) { + $dataTable = new Table('__temp__' . $table->getName()); + + $newTable = new Table($table->getQuotedName($this), $columns, $this->getPrimaryIndexInAlteredTable($diff), $this->getForeignKeysInAlteredTable($diff), 0, $table->getOptions()); + $newTable->addOption('alter', true); + + $sql = $this->getPreAlterTableIndexForeignKeySQL($diff); + //$sql = array_merge($sql, $this->getCreateTableSQL($dataTable, 0)); + $sql[] = sprintf('CREATE TEMPORARY TABLE %s AS SELECT %s FROM %s', $dataTable->getQuotedName($this), implode(', ', $oldColumnNames), $table->getQuotedName($this)); + $sql[] = $this->getDropTableSQL($fromTable); + + $sql = array_merge($sql, $this->getCreateTableSQL($newTable)); + $sql[] = sprintf('INSERT INTO %s (%s) SELECT %s FROM %s', $newTable->getQuotedName($this), implode(', ', $newColumnNames), implode(', ', $oldColumnNames), $dataTable->getQuotedName($this)); + $sql[] = $this->getDropTableSQL($dataTable); + + $newName = $diff->getNewName(); + + if ($newName !== false) { + $sql[] = sprintf( + 'ALTER TABLE %s RENAME TO %s', + $newTable->getQuotedName($this), + $newName->getQuotedName($this) + ); + } + + $sql = array_merge($sql, $this->getPostAlterTableIndexForeignKeySQL($diff)); + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * @return string[]|false + */ + private function getSimpleAlterTableSQL(TableDiff $diff) + { + // Suppress changes on integer type autoincrement columns. + foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { + if (! $columnDiff->fromColumn instanceof Column || + ! $columnDiff->column instanceof Column || + ! $columnDiff->column->getAutoincrement() || + ! $columnDiff->column->getType() instanceof Types\IntegerType + ) { + continue; + } + + if (! $columnDiff->hasChanged('type') && $columnDiff->hasChanged('unsigned')) { + unset($diff->changedColumns[$oldColumnName]); + + continue; + } + + $fromColumnType = $columnDiff->fromColumn->getType(); + + if (! ($fromColumnType instanceof Types\SmallIntType) && ! ($fromColumnType instanceof Types\BigIntType)) { + continue; + } + + unset($diff->changedColumns[$oldColumnName]); + } + + if (! empty($diff->renamedColumns) || ! empty($diff->addedForeignKeys) || ! empty($diff->addedIndexes) + || ! empty($diff->changedColumns) || ! empty($diff->changedForeignKeys) || ! empty($diff->changedIndexes) + || ! empty($diff->removedColumns) || ! empty($diff->removedForeignKeys) || ! empty($diff->removedIndexes) + || ! empty($diff->renamedIndexes) + ) { + return false; + } + + $table = new Table($diff->name); + + $sql = []; + $tableSql = []; + $columnSql = []; + + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $field = array_merge(['unique' => null, 'autoincrement' => null, 'default' => null], $column->toArray()); + $type = $field['type']; + switch (true) { + case isset($field['columnDefinition']) || $field['autoincrement'] || $field['unique']: + case $type instanceof Types\DateTimeType && $field['default'] === $this->getCurrentTimestampSQL(): + case $type instanceof Types\DateType && $field['default'] === $this->getCurrentDateSQL(): + case $type instanceof Types\TimeType && $field['default'] === $this->getCurrentTimeSQL(): + return false; + } + + $field['name'] = $column->getQuotedName($this); + if ($type instanceof Types\StringType && $field['length'] === null) { + $field['length'] = 255; + } + + $sql[] = 'ALTER TABLE ' . $table->getQuotedName($this) . ' ADD COLUMN ' . $this->getColumnDeclarationSQL($field['name'], $field); + } + + if (! $this->onSchemaAlterTable($diff, $tableSql)) { + if ($diff->newName !== false) { + $newTable = new Identifier($diff->newName); + $sql[] = 'ALTER TABLE ' . $table->getQuotedName($this) . ' RENAME TO ' . $newTable->getQuotedName($this); + } + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * @return string[] + */ + private function getColumnNamesInAlteredTable(TableDiff $diff) + { + $columns = []; + + foreach ($diff->fromTable->getColumns() as $columnName => $column) { + $columns[strtolower($columnName)] = $column->getName(); + } + + foreach ($diff->removedColumns as $columnName => $column) { + $columnName = strtolower($columnName); + if (! isset($columns[$columnName])) { + continue; + } + + unset($columns[$columnName]); + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + $columnName = $column->getName(); + $columns[strtolower($oldColumnName)] = $columnName; + $columns[strtolower($columnName)] = $columnName; + } + + foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { + $columnName = $columnDiff->column->getName(); + $columns[strtolower($oldColumnName)] = $columnName; + $columns[strtolower($columnName)] = $columnName; + } + + foreach ($diff->addedColumns as $column) { + $columnName = $column->getName(); + $columns[strtolower($columnName)] = $columnName; + } + + return $columns; + } + + /** + * @return Index[] + */ + private function getIndexesInAlteredTable(TableDiff $diff) + { + $indexes = $diff->fromTable->getIndexes(); + $columnNames = $this->getColumnNamesInAlteredTable($diff); + + foreach ($indexes as $key => $index) { + foreach ($diff->renamedIndexes as $oldIndexName => $renamedIndex) { + if (strtolower($key) !== strtolower($oldIndexName)) { + continue; + } + + unset($indexes[$key]); + } + + $changed = false; + $indexColumns = []; + foreach ($index->getColumns() as $columnName) { + $normalizedColumnName = strtolower($columnName); + if (! isset($columnNames[$normalizedColumnName])) { + unset($indexes[$key]); + continue 2; + } + + $indexColumns[] = $columnNames[$normalizedColumnName]; + if ($columnName === $columnNames[$normalizedColumnName]) { + continue; + } + + $changed = true; + } + + if (! $changed) { + continue; + } + + $indexes[$key] = new Index($index->getName(), $indexColumns, $index->isUnique(), $index->isPrimary(), $index->getFlags()); + } + + foreach ($diff->removedIndexes as $index) { + $indexName = strtolower($index->getName()); + if (! strlen($indexName) || ! isset($indexes[$indexName])) { + continue; + } + + unset($indexes[$indexName]); + } + + foreach (array_merge($diff->changedIndexes, $diff->addedIndexes, $diff->renamedIndexes) as $index) { + $indexName = strtolower($index->getName()); + if (strlen($indexName)) { + $indexes[$indexName] = $index; + } else { + $indexes[] = $index; + } + } + + return $indexes; + } + + /** + * @return ForeignKeyConstraint[] + */ + private function getForeignKeysInAlteredTable(TableDiff $diff) + { + $foreignKeys = $diff->fromTable->getForeignKeys(); + $columnNames = $this->getColumnNamesInAlteredTable($diff); + + foreach ($foreignKeys as $key => $constraint) { + $changed = false; + $localColumns = []; + foreach ($constraint->getLocalColumns() as $columnName) { + $normalizedColumnName = strtolower($columnName); + if (! isset($columnNames[$normalizedColumnName])) { + unset($foreignKeys[$key]); + continue 2; + } + + $localColumns[] = $columnNames[$normalizedColumnName]; + if ($columnName === $columnNames[$normalizedColumnName]) { + continue; + } + + $changed = true; + } + + if (! $changed) { + continue; + } + + $foreignKeys[$key] = new ForeignKeyConstraint($localColumns, $constraint->getForeignTableName(), $constraint->getForeignColumns(), $constraint->getName(), $constraint->getOptions()); + } + + foreach ($diff->removedForeignKeys as $constraint) { + if (! $constraint instanceof ForeignKeyConstraint) { + $constraint = new Identifier($constraint); + } + + $constraintName = strtolower($constraint->getName()); + if (! strlen($constraintName) || ! isset($foreignKeys[$constraintName])) { + continue; + } + + unset($foreignKeys[$constraintName]); + } + + foreach (array_merge($diff->changedForeignKeys, $diff->addedForeignKeys) as $constraint) { + $constraintName = strtolower($constraint->getName()); + if (strlen($constraintName)) { + $foreignKeys[$constraintName] = $constraint; + } else { + $foreignKeys[] = $constraint; + } + } + + return $foreignKeys; + } + + /** + * @return Index[] + */ + private function getPrimaryIndexInAlteredTable(TableDiff $diff) + { + $primaryIndex = []; + + foreach ($this->getIndexesInAlteredTable($diff) as $index) { + if (! $index->isPrimary()) { + continue; + } + + $primaryIndex = [$index->getName() => $index]; + } + + return $primaryIndex; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/TrimMode.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/TrimMode.php new file mode 100644 index 0000000..0a4b6ea --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/TrimMode.php @@ -0,0 +1,20 @@ +getParams(); + if (isset($params['portability'])) { + if ($this->getDatabasePlatform()->getName() === 'oracle') { + $params['portability'] &= self::PORTABILITY_ORACLE; + } elseif ($this->getDatabasePlatform()->getName() === 'postgresql') { + $params['portability'] &= self::PORTABILITY_POSTGRESQL; + } elseif ($this->getDatabasePlatform()->getName() === 'sqlite') { + $params['portability'] &= self::PORTABILITY_SQLITE; + } elseif ($this->getDatabasePlatform()->getName() === 'drizzle') { + $params['portability'] &= self::PORTABILITY_DRIZZLE; + } elseif ($this->getDatabasePlatform()->getName() === 'sqlanywhere') { + $params['portability'] &= self::PORTABILITY_SQLANYWHERE; + } elseif ($this->getDatabasePlatform()->getName() === 'db2') { + $params['portability'] &= self::PORTABILITY_DB2; + } elseif ($this->getDatabasePlatform()->getName() === 'mssql') { + $params['portability'] &= self::PORTABILITY_SQLSRV; + } else { + $params['portability'] &= self::PORTABILITY_OTHERVENDORS; + } + $this->portability = $params['portability']; + } + + if (isset($params['fetch_case']) && $this->portability & self::PORTABILITY_FIX_CASE) { + if ($this->_conn instanceof PDOConnection) { + // make use of c-level support for case handling + $this->_conn->setAttribute(PDO::ATTR_CASE, $params['fetch_case']); + } else { + $this->case = $params['fetch_case'] === ColumnCase::LOWER ? CASE_LOWER : CASE_UPPER; + } + } + } + + return $ret; + } + + /** + * @return int + */ + public function getPortability() + { + return $this->portability; + } + + /** + * @return int + */ + public function getFetchCase() + { + return $this->case; + } + + /** + * {@inheritdoc} + */ + public function executeQuery($query, array $params = [], $types = [], ?QueryCacheProfile $qcp = null) + { + $stmt = new Statement(parent::executeQuery($query, $params, $types, $qcp), $this); + $stmt->setFetchMode($this->defaultFetchMode); + + return $stmt; + } + + /** + * {@inheritdoc} + */ + public function prepare($statement) + { + $stmt = new Statement(parent::prepare($statement), $this); + $stmt->setFetchMode($this->defaultFetchMode); + + return $stmt; + } + + /** + * {@inheritdoc} + */ + public function query() + { + $connection = $this->getWrappedConnection(); + + $stmt = $connection->query(...func_get_args()); + $stmt = new Statement($stmt, $this); + $stmt->setFetchMode($this->defaultFetchMode); + + return $stmt; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Statement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Statement.php new file mode 100644 index 0000000..514b3be --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Statement.php @@ -0,0 +1,247 @@ +Statement and applies portability measures. + * + * @param DriverStatement|ResultStatement $stmt + */ + public function __construct($stmt, Connection $conn) + { + $this->stmt = $stmt; + $this->portability = $conn->getPortability(); + $this->case = $conn->getFetchCase(); + } + + /** + * {@inheritdoc} + */ + public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null) + { + assert($this->stmt instanceof DriverStatement); + + return $this->stmt->bindParam($column, $variable, $type, $length); + } + + /** + * {@inheritdoc} + */ + public function bindValue($param, $value, $type = ParameterType::STRING) + { + assert($this->stmt instanceof DriverStatement); + + return $this->stmt->bindValue($param, $value, $type); + } + + /** + * {@inheritdoc} + */ + public function closeCursor() + { + return $this->stmt->closeCursor(); + } + + /** + * {@inheritdoc} + */ + public function columnCount() + { + return $this->stmt->columnCount(); + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + assert($this->stmt instanceof DriverStatement); + + return $this->stmt->errorCode(); + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + assert($this->stmt instanceof DriverStatement); + + return $this->stmt->errorInfo(); + } + + /** + * {@inheritdoc} + */ + public function execute($params = null) + { + assert($this->stmt instanceof DriverStatement); + + return $this->stmt->execute($params); + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg1 = null, $arg2 = null) + { + $this->defaultFetchMode = $fetchMode; + + return $this->stmt->setFetchMode($fetchMode, $arg1, $arg2); + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + return new StatementIterator($this); + } + + /** + * {@inheritdoc} + */ + public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + { + $fetchMode = $fetchMode ?: $this->defaultFetchMode; + + $row = $this->stmt->fetch($fetchMode); + + $iterateRow = $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM); + $fixCase = $this->case !== null + && ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED) + && ($this->portability & Connection::PORTABILITY_FIX_CASE); + + $row = $this->fixRow($row, $iterateRow, $fixCase); + + return $row; + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + { + $fetchMode = $fetchMode ?: $this->defaultFetchMode; + + if ($fetchArgument) { + $rows = $this->stmt->fetchAll($fetchMode, $fetchArgument); + } else { + $rows = $this->stmt->fetchAll($fetchMode); + } + + $iterateRow = $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM); + $fixCase = $this->case !== null + && ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED) + && ($this->portability & Connection::PORTABILITY_FIX_CASE); + + if (! $iterateRow && ! $fixCase) { + return $rows; + } + + if ($fetchMode === FetchMode::COLUMN) { + foreach ($rows as $num => $row) { + $rows[$num] = [$row]; + } + } + + foreach ($rows as $num => $row) { + $rows[$num] = $this->fixRow($row, $iterateRow, $fixCase); + } + + if ($fetchMode === FetchMode::COLUMN) { + foreach ($rows as $num => $row) { + $rows[$num] = $row[0]; + } + } + + return $rows; + } + + /** + * @param mixed $row + * @param int $iterateRow + * @param bool $fixCase + * + * @return mixed + */ + protected function fixRow($row, $iterateRow, $fixCase) + { + if (! $row) { + return $row; + } + + if ($fixCase) { + $row = array_change_key_case($row, $this->case); + } + + if ($iterateRow) { + foreach ($row as $k => $v) { + if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $v === '') { + $row[$k] = null; + } elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($v)) { + $row[$k] = rtrim($v); + } + } + } + + return $row; + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + $value = $this->stmt->fetchColumn($columnIndex); + + if ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) { + if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $value === '') { + $value = null; + } elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($value)) { + $value = rtrim($value); + } + } + + return $value; + } + + /** + * {@inheritdoc} + */ + public function rowCount() + { + assert($this->stmt instanceof DriverStatement); + + return $this->stmt->rowCount(); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/CompositeExpression.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/CompositeExpression.php new file mode 100644 index 0000000..443d71b --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/CompositeExpression.php @@ -0,0 +1,120 @@ +type = $type; + + $this->addMultiple($parts); + } + + /** + * Adds multiple parts to composite expression. + * + * @param self[]|string[] $parts + * + * @return \Doctrine\DBAL\Query\Expression\CompositeExpression + */ + public function addMultiple(array $parts = []) + { + foreach ($parts as $part) { + $this->add($part); + } + + return $this; + } + + /** + * Adds an expression to composite expression. + * + * @param mixed $part + * + * @return \Doctrine\DBAL\Query\Expression\CompositeExpression + */ + public function add($part) + { + if (empty($part)) { + return $this; + } + + if ($part instanceof self && count($part) === 0) { + return $this; + } + + $this->parts[] = $part; + + return $this; + } + + /** + * Retrieves the amount of expressions on composite expression. + * + * @return int + */ + public function count() + { + return count($this->parts); + } + + /** + * Retrieves the string representation of this composite expression. + * + * @return string + */ + public function __toString() + { + if ($this->count() === 1) { + return (string) $this->parts[0]; + } + + return '(' . implode(') ' . $this->type . ' (', $this->parts) . ')'; + } + + /** + * Returns the type of this composite expression (AND/OR). + * + * @return string + */ + public function getType() + { + return $this->type; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php new file mode 100644 index 0000000..dfcc31e --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php @@ -0,0 +1,298 @@ +'; + public const LT = '<'; + public const LTE = '<='; + public const GT = '>'; + public const GTE = '>='; + + /** + * The DBAL Connection. + * + * @var Connection + */ + private $connection; + + /** + * Initializes a new ExpressionBuilder. + * + * @param Connection $connection The DBAL Connection. + */ + public function __construct(Connection $connection) + { + $this->connection = $connection; + } + + /** + * Creates a conjunction of the given boolean expressions. + * + * Example: + * + * [php] + * // (u.type = ?) AND (u.role = ?) + * $expr->andX('u.type = ?', 'u.role = ?')); + * + * @param mixed $x Optional clause. Defaults = null, but requires + * at least one defined when converting to string. + * + * @return CompositeExpression + */ + public function andX($x = null) + { + return new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); + } + + /** + * Creates a disjunction of the given boolean expressions. + * + * Example: + * + * [php] + * // (u.type = ?) OR (u.role = ?) + * $qb->where($qb->expr()->orX('u.type = ?', 'u.role = ?')); + * + * @param mixed $x Optional clause. Defaults = null, but requires + * at least one defined when converting to string. + * + * @return CompositeExpression + */ + public function orX($x = null) + { + return new CompositeExpression(CompositeExpression::TYPE_OR, func_get_args()); + } + + /** + * Creates a comparison expression. + * + * @param mixed $x The left expression. + * @param string $operator One of the ExpressionBuilder::* constants. + * @param mixed $y The right expression. + * + * @return string + */ + public function comparison($x, $operator, $y) + { + return $x . ' ' . $operator . ' ' . $y; + } + + /** + * Creates an equality comparison expression with the given arguments. + * + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a = . Example: + * + * [php] + * // u.id = ? + * $expr->eq('u.id', '?'); + * + * @param mixed $x The left expression. + * @param mixed $y The right expression. + * + * @return string + */ + public function eq($x, $y) + { + return $this->comparison($x, self::EQ, $y); + } + + /** + * Creates a non equality comparison expression with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a <> . Example: + * + * [php] + * // u.id <> 1 + * $q->where($q->expr()->neq('u.id', '1')); + * + * @param mixed $x The left expression. + * @param mixed $y The right expression. + * + * @return string + */ + public function neq($x, $y) + { + return $this->comparison($x, self::NEQ, $y); + } + + /** + * Creates a lower-than comparison expression with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a < . Example: + * + * [php] + * // u.id < ? + * $q->where($q->expr()->lt('u.id', '?')); + * + * @param mixed $x The left expression. + * @param mixed $y The right expression. + * + * @return string + */ + public function lt($x, $y) + { + return $this->comparison($x, self::LT, $y); + } + + /** + * Creates a lower-than-equal comparison expression with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a <= . Example: + * + * [php] + * // u.id <= ? + * $q->where($q->expr()->lte('u.id', '?')); + * + * @param mixed $x The left expression. + * @param mixed $y The right expression. + * + * @return string + */ + public function lte($x, $y) + { + return $this->comparison($x, self::LTE, $y); + } + + /** + * Creates a greater-than comparison expression with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a > . Example: + * + * [php] + * // u.id > ? + * $q->where($q->expr()->gt('u.id', '?')); + * + * @param mixed $x The left expression. + * @param mixed $y The right expression. + * + * @return string + */ + public function gt($x, $y) + { + return $this->comparison($x, self::GT, $y); + } + + /** + * Creates a greater-than-equal comparison expression with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a >= . Example: + * + * [php] + * // u.id >= ? + * $q->where($q->expr()->gte('u.id', '?')); + * + * @param mixed $x The left expression. + * @param mixed $y The right expression. + * + * @return string + */ + public function gte($x, $y) + { + return $this->comparison($x, self::GTE, $y); + } + + /** + * Creates an IS NULL expression with the given arguments. + * + * @param string $x The field in string format to be restricted by IS NULL. + * + * @return string + */ + public function isNull($x) + { + return $x . ' IS NULL'; + } + + /** + * Creates an IS NOT NULL expression with the given arguments. + * + * @param string $x The field in string format to be restricted by IS NOT NULL. + * + * @return string + */ + public function isNotNull($x) + { + return $x . ' IS NOT NULL'; + } + + /** + * Creates a LIKE() comparison expression with the given arguments. + * + * @param string $x Field in string format to be inspected by LIKE() comparison. + * @param mixed $y Argument to be used in LIKE() comparison. + * + * @return string + */ + public function like($x, $y/*, ?string $escapeChar = null */) + { + return $this->comparison($x, 'LIKE', $y) . + (func_num_args() >= 3 ? sprintf(' ESCAPE %s', func_get_arg(2)) : ''); + } + + /** + * Creates a NOT LIKE() comparison expression with the given arguments. + * + * @param string $x Field in string format to be inspected by NOT LIKE() comparison. + * @param mixed $y Argument to be used in NOT LIKE() comparison. + * + * @return string + */ + public function notLike($x, $y/*, ?string $escapeChar = null */) + { + return $this->comparison($x, 'NOT LIKE', $y) . + (func_num_args() >= 3 ? sprintf(' ESCAPE %s', func_get_arg(2)) : ''); + } + + /** + * Creates a IN () comparison expression with the given arguments. + * + * @param string $x The field in string format to be inspected by IN() comparison. + * @param string|string[] $y The placeholder or the array of values to be used by IN() comparison. + * + * @return string + */ + public function in($x, $y) + { + return $this->comparison($x, 'IN', '(' . implode(', ', (array) $y) . ')'); + } + + /** + * Creates a NOT IN () comparison expression with the given arguments. + * + * @param string $x The field in string format to be inspected by NOT IN() comparison. + * @param string|string[] $y The placeholder or the array of values to be used by NOT IN() comparison. + * + * @return string + */ + public function notIn($x, $y) + { + return $this->comparison($x, 'NOT IN', '(' . implode(', ', (array) $y) . ')'); + } + + /** + * Quotes a given input parameter. + * + * @param mixed $input The parameter to be quoted. + * @param int|null $type The type of the parameter. + * + * @return string + */ + public function literal($input, $type = null) + { + return $this->connection->quote($input, $type); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryBuilder.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryBuilder.php new file mode 100644 index 0000000..587e266 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryBuilder.php @@ -0,0 +1,1373 @@ + [], + 'distinct' => false, + 'from' => [], + 'join' => [], + 'set' => [], + 'where' => null, + 'groupBy' => [], + 'having' => null, + 'orderBy' => [], + 'values' => [], + ]; + + /** + * The array of SQL parts collected. + * + * @var mixed[] + */ + private $sqlParts = self::SQL_PARTS_DEFAULTS; + + /** + * The complete SQL string for this query. + * + * @var string + */ + private $sql; + + /** + * The query parameters. + * + * @var mixed[] + */ + private $params = []; + + /** + * The parameter type map of this query. + * + * @var int[]|string[] + */ + private $paramTypes = []; + + /** + * The type of query this is. Can be select, update or delete. + * + * @var int + */ + private $type = self::SELECT; + + /** + * The state of the query object. Can be dirty or clean. + * + * @var int + */ + private $state = self::STATE_CLEAN; + + /** + * The index of the first result to retrieve. + * + * @var int + */ + private $firstResult = null; + + /** + * The maximum number of results to retrieve. + * + * @var int + */ + private $maxResults = null; + + /** + * The counter of bound parameters used with {@see bindValue). + * + * @var int + */ + private $boundCounter = 0; + + /** + * Initializes a new QueryBuilder. + * + * @param Connection $connection The DBAL Connection. + */ + public function __construct(Connection $connection) + { + $this->connection = $connection; + } + + /** + * Gets an ExpressionBuilder used for object-oriented construction of query expressions. + * This producer method is intended for convenient inline usage. Example: + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u') + * ->from('users', 'u') + * ->where($qb->expr()->eq('u.id', 1)); + * + * + * For more complex expression construction, consider storing the expression + * builder object in a local variable. + * + * @return ExpressionBuilder + */ + public function expr() + { + return $this->connection->getExpressionBuilder(); + } + + /** + * Gets the type of the currently built query. + * + * @return int + */ + public function getType() + { + return $this->type; + } + + /** + * Gets the associated DBAL Connection for this query builder. + * + * @return Connection + */ + public function getConnection() + { + return $this->connection; + } + + /** + * Gets the state of this query builder instance. + * + * @return int Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN. + */ + public function getState() + { + return $this->state; + } + + /** + * Executes this query using the bound parameters and their types. + * + * Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate} + * for insert, update and delete statements. + * + * @return Statement|int + */ + public function execute() + { + if ($this->type === self::SELECT) { + return $this->connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes); + } + + return $this->connection->executeUpdate($this->getSQL(), $this->params, $this->paramTypes); + } + + /** + * Gets the complete SQL string formed by the current specifications of this QueryBuilder. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u') + * echo $qb->getSQL(); // SELECT u FROM User u + * + * + * @return string The SQL query string. + */ + public function getSQL() + { + if ($this->sql !== null && $this->state === self::STATE_CLEAN) { + return $this->sql; + } + + switch ($this->type) { + case self::INSERT: + $sql = $this->getSQLForInsert(); + break; + case self::DELETE: + $sql = $this->getSQLForDelete(); + break; + + case self::UPDATE: + $sql = $this->getSQLForUpdate(); + break; + + case self::SELECT: + default: + $sql = $this->getSQLForSelect(); + break; + } + + $this->state = self::STATE_CLEAN; + $this->sql = $sql; + + return $sql; + } + + /** + * Sets a query parameter for the query being constructed. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u') + * ->from('users', 'u') + * ->where('u.id = :user_id') + * ->setParameter(':user_id', 1); + * + * + * @param string|int $key The parameter position or name. + * @param mixed $value The parameter value. + * @param string|int|null $type One of the {@link \Doctrine\DBAL\ParameterType} constants. + * + * @return $this This QueryBuilder instance. + */ + public function setParameter($key, $value, $type = null) + { + if ($type !== null) { + $this->paramTypes[$key] = $type; + } + + $this->params[$key] = $value; + + return $this; + } + + /** + * Sets a collection of query parameters for the query being constructed. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u') + * ->from('users', 'u') + * ->where('u.id = :user_id1 OR u.id = :user_id2') + * ->setParameters(array( + * ':user_id1' => 1, + * ':user_id2' => 2 + * )); + * + * + * @param mixed[] $params The query parameters to set. + * @param int[]|string[] $types The query parameters types to set. + * + * @return $this This QueryBuilder instance. + */ + public function setParameters(array $params, array $types = []) + { + $this->paramTypes = $types; + $this->params = $params; + + return $this; + } + + /** + * Gets all defined query parameters for the query being constructed indexed by parameter index or name. + * + * @return mixed[] The currently defined query parameters indexed by parameter index or name. + */ + public function getParameters() + { + return $this->params; + } + + /** + * Gets a (previously set) query parameter of the query being constructed. + * + * @param mixed $key The key (index or name) of the bound parameter. + * + * @return mixed The value of the bound parameter. + */ + public function getParameter($key) + { + return $this->params[$key] ?? null; + } + + /** + * Gets all defined query parameter types for the query being constructed indexed by parameter index or name. + * + * @return int[]|string[] The currently defined query parameter types indexed by parameter index or name. + */ + public function getParameterTypes() + { + return $this->paramTypes; + } + + /** + * Gets a (previously set) query parameter type of the query being constructed. + * + * @param mixed $key The key (index or name) of the bound parameter type. + * + * @return mixed The value of the bound parameter type. + */ + public function getParameterType($key) + { + return $this->paramTypes[$key] ?? null; + } + + /** + * Sets the position of the first result to retrieve (the "offset"). + * + * @param int $firstResult The first result to return. + * + * @return $this This QueryBuilder instance. + */ + public function setFirstResult($firstResult) + { + $this->state = self::STATE_DIRTY; + $this->firstResult = $firstResult; + + return $this; + } + + /** + * Gets the position of the first result the query object was set to retrieve (the "offset"). + * Returns NULL if {@link setFirstResult} was not applied to this QueryBuilder. + * + * @return int The position of the first result. + */ + public function getFirstResult() + { + return $this->firstResult; + } + + /** + * Sets the maximum number of results to retrieve (the "limit"). + * + * @param int $maxResults The maximum number of results to retrieve. + * + * @return $this This QueryBuilder instance. + */ + public function setMaxResults($maxResults) + { + $this->state = self::STATE_DIRTY; + $this->maxResults = $maxResults; + + return $this; + } + + /** + * Gets the maximum number of results the query object was set to retrieve (the "limit"). + * Returns NULL if {@link setMaxResults} was not applied to this query builder. + * + * @return int The maximum number of results. + */ + public function getMaxResults() + { + return $this->maxResults; + } + + /** + * Either appends to or replaces a single, generic query part. + * + * The available parts are: 'select', 'from', 'set', 'where', + * 'groupBy', 'having' and 'orderBy'. + * + * @param string $sqlPartName + * @param mixed $sqlPart + * @param bool $append + * + * @return $this This QueryBuilder instance. + */ + public function add($sqlPartName, $sqlPart, $append = false) + { + $isArray = is_array($sqlPart); + $isMultiple = is_array($this->sqlParts[$sqlPartName]); + + if ($isMultiple && ! $isArray) { + $sqlPart = [$sqlPart]; + } + + $this->state = self::STATE_DIRTY; + + if ($append) { + if ($sqlPartName === 'orderBy' || $sqlPartName === 'groupBy' || $sqlPartName === 'select' || $sqlPartName === 'set') { + foreach ($sqlPart as $part) { + $this->sqlParts[$sqlPartName][] = $part; + } + } elseif ($isArray && is_array($sqlPart[key($sqlPart)])) { + $key = key($sqlPart); + $this->sqlParts[$sqlPartName][$key][] = $sqlPart[$key]; + } elseif ($isMultiple) { + $this->sqlParts[$sqlPartName][] = $sqlPart; + } else { + $this->sqlParts[$sqlPartName] = $sqlPart; + } + + return $this; + } + + $this->sqlParts[$sqlPartName] = $sqlPart; + + return $this; + } + + /** + * Specifies an item that is to be returned in the query result. + * Replaces any previously specified selections, if any. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u.id', 'p.id') + * ->from('users', 'u') + * ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id'); + * + * + * @param mixed $select The selection expressions. + * + * @return $this This QueryBuilder instance. + */ + public function select($select = null) + { + $this->type = self::SELECT; + + if (empty($select)) { + return $this; + } + + $selects = is_array($select) ? $select : func_get_args(); + + return $this->add('select', $selects); + } + + /** + * Adds DISTINCT to the query. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u.id') + * ->distinct() + * ->from('users', 'u') + * + * + * @return $this This QueryBuilder instance. + */ + public function distinct() : self + { + $this->sqlParts['distinct'] = true; + + return $this; + } + + /** + * Adds an item that is to be returned in the query result. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u.id') + * ->addSelect('p.id') + * ->from('users', 'u') + * ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id'); + * + * + * @param mixed $select The selection expression. + * + * @return $this This QueryBuilder instance. + */ + public function addSelect($select = null) + { + $this->type = self::SELECT; + + if (empty($select)) { + return $this; + } + + $selects = is_array($select) ? $select : func_get_args(); + + return $this->add('select', $selects, true); + } + + /** + * Turns the query being built into a bulk delete query that ranges over + * a certain table. + * + * + * $qb = $conn->createQueryBuilder() + * ->delete('users', 'u') + * ->where('u.id = :user_id') + * ->setParameter(':user_id', 1); + * + * + * @param string $delete The table whose rows are subject to the deletion. + * @param string $alias The table alias used in the constructed query. + * + * @return $this This QueryBuilder instance. + */ + public function delete($delete = null, $alias = null) + { + $this->type = self::DELETE; + + if (! $delete) { + return $this; + } + + return $this->add('from', [ + 'table' => $delete, + 'alias' => $alias, + ]); + } + + /** + * Turns the query being built into a bulk update query that ranges over + * a certain table + * + * + * $qb = $conn->createQueryBuilder() + * ->update('counters', 'c') + * ->set('c.value', 'c.value + 1') + * ->where('c.id = ?'); + * + * + * @param string $update The table whose rows are subject to the update. + * @param string $alias The table alias used in the constructed query. + * + * @return $this This QueryBuilder instance. + */ + public function update($update = null, $alias = null) + { + $this->type = self::UPDATE; + + if (! $update) { + return $this; + } + + return $this->add('from', [ + 'table' => $update, + 'alias' => $alias, + ]); + } + + /** + * Turns the query being built into an insert query that inserts into + * a certain table + * + * + * $qb = $conn->createQueryBuilder() + * ->insert('users') + * ->values( + * array( + * 'name' => '?', + * 'password' => '?' + * ) + * ); + * + * + * @param string $insert The table into which the rows should be inserted. + * + * @return $this This QueryBuilder instance. + */ + public function insert($insert = null) + { + $this->type = self::INSERT; + + if (! $insert) { + return $this; + } + + return $this->add('from', ['table' => $insert]); + } + + /** + * Creates and adds a query root corresponding to the table identified by the + * given alias, forming a cartesian product with any existing query roots. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u.id') + * ->from('users', 'u') + * + * + * @param string $from The table. + * @param string|null $alias The alias of the table. + * + * @return $this This QueryBuilder instance. + */ + public function from($from, $alias = null) + { + return $this->add('from', [ + 'table' => $from, + 'alias' => $alias, + ], true); + } + + /** + * Creates and adds a join to the query. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->join('u', 'phonenumbers', 'p', 'p.is_primary = 1'); + * + * + * @param string $fromAlias The alias that points to a from clause. + * @param string $join The table name to join. + * @param string $alias The alias of the join table. + * @param string $condition The condition for the join. + * + * @return $this This QueryBuilder instance. + */ + public function join($fromAlias, $join, $alias, $condition = null) + { + return $this->innerJoin($fromAlias, $join, $alias, $condition); + } + + /** + * Creates and adds a join to the query. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->innerJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1'); + * + * + * @param string $fromAlias The alias that points to a from clause. + * @param string $join The table name to join. + * @param string $alias The alias of the join table. + * @param string $condition The condition for the join. + * + * @return $this This QueryBuilder instance. + */ + public function innerJoin($fromAlias, $join, $alias, $condition = null) + { + return $this->add('join', [ + $fromAlias => [ + 'joinType' => 'inner', + 'joinTable' => $join, + 'joinAlias' => $alias, + 'joinCondition' => $condition, + ], + ], true); + } + + /** + * Creates and adds a left join to the query. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->leftJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1'); + * + * + * @param string $fromAlias The alias that points to a from clause. + * @param string $join The table name to join. + * @param string $alias The alias of the join table. + * @param string $condition The condition for the join. + * + * @return $this This QueryBuilder instance. + */ + public function leftJoin($fromAlias, $join, $alias, $condition = null) + { + return $this->add('join', [ + $fromAlias => [ + 'joinType' => 'left', + 'joinTable' => $join, + 'joinAlias' => $alias, + 'joinCondition' => $condition, + ], + ], true); + } + + /** + * Creates and adds a right join to the query. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->rightJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1'); + * + * + * @param string $fromAlias The alias that points to a from clause. + * @param string $join The table name to join. + * @param string $alias The alias of the join table. + * @param string $condition The condition for the join. + * + * @return $this This QueryBuilder instance. + */ + public function rightJoin($fromAlias, $join, $alias, $condition = null) + { + return $this->add('join', [ + $fromAlias => [ + 'joinType' => 'right', + 'joinTable' => $join, + 'joinAlias' => $alias, + 'joinCondition' => $condition, + ], + ], true); + } + + /** + * Sets a new value for a column in a bulk update query. + * + * + * $qb = $conn->createQueryBuilder() + * ->update('counters', 'c') + * ->set('c.value', 'c.value + 1') + * ->where('c.id = ?'); + * + * + * @param string $key The column to set. + * @param string $value The value, expression, placeholder, etc. + * + * @return $this This QueryBuilder instance. + */ + public function set($key, $value) + { + return $this->add('set', $key . ' = ' . $value, true); + } + + /** + * Specifies one or more restrictions to the query result. + * Replaces any previously specified restrictions, if any. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('c.value') + * ->from('counters', 'c') + * ->where('c.id = ?'); + * + * // You can optionally programatically build and/or expressions + * $qb = $conn->createQueryBuilder(); + * + * $or = $qb->expr()->orx(); + * $or->add($qb->expr()->eq('c.id', 1)); + * $or->add($qb->expr()->eq('c.id', 2)); + * + * $qb->update('counters', 'c') + * ->set('c.value', 'c.value + 1') + * ->where($or); + * + * + * @param mixed $predicates The restriction predicates. + * + * @return $this This QueryBuilder instance. + */ + public function where($predicates) + { + if (! (func_num_args() === 1 && $predicates instanceof CompositeExpression)) { + $predicates = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); + } + + return $this->add('where', $predicates); + } + + /** + * Adds one or more restrictions to the query results, forming a logical + * conjunction with any previously specified restrictions. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u') + * ->from('users', 'u') + * ->where('u.username LIKE ?') + * ->andWhere('u.is_active = 1'); + * + * + * @see where() + * + * @param mixed $where The query restrictions. + * + * @return $this This QueryBuilder instance. + */ + public function andWhere($where) + { + $args = func_get_args(); + $where = $this->getQueryPart('where'); + + if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_AND) { + $where->addMultiple($args); + } else { + array_unshift($args, $where); + $where = new CompositeExpression(CompositeExpression::TYPE_AND, $args); + } + + return $this->add('where', $where, true); + } + + /** + * Adds one or more restrictions to the query results, forming a logical + * disjunction with any previously specified restrictions. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->where('u.id = 1') + * ->orWhere('u.id = 2'); + * + * + * @see where() + * + * @param mixed $where The WHERE statement. + * + * @return $this This QueryBuilder instance. + */ + public function orWhere($where) + { + $args = func_get_args(); + $where = $this->getQueryPart('where'); + + if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_OR) { + $where->addMultiple($args); + } else { + array_unshift($args, $where); + $where = new CompositeExpression(CompositeExpression::TYPE_OR, $args); + } + + return $this->add('where', $where, true); + } + + /** + * Specifies a grouping over the results of the query. + * Replaces any previously specified groupings, if any. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->groupBy('u.id'); + * + * + * @param mixed $groupBy The grouping expression. + * + * @return $this This QueryBuilder instance. + */ + public function groupBy($groupBy) + { + if (empty($groupBy)) { + return $this; + } + + $groupBy = is_array($groupBy) ? $groupBy : func_get_args(); + + return $this->add('groupBy', $groupBy, false); + } + + /** + * Adds a grouping expression to the query. + * + * + * $qb = $conn->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->groupBy('u.lastLogin') + * ->addGroupBy('u.createdAt'); + * + * + * @param mixed $groupBy The grouping expression. + * + * @return $this This QueryBuilder instance. + */ + public function addGroupBy($groupBy) + { + if (empty($groupBy)) { + return $this; + } + + $groupBy = is_array($groupBy) ? $groupBy : func_get_args(); + + return $this->add('groupBy', $groupBy, true); + } + + /** + * Sets a value for a column in an insert query. + * + * + * $qb = $conn->createQueryBuilder() + * ->insert('users') + * ->values( + * array( + * 'name' => '?' + * ) + * ) + * ->setValue('password', '?'); + * + * + * @param string $column The column into which the value should be inserted. + * @param string $value The value that should be inserted into the column. + * + * @return $this This QueryBuilder instance. + */ + public function setValue($column, $value) + { + $this->sqlParts['values'][$column] = $value; + + return $this; + } + + /** + * Specifies values for an insert query indexed by column names. + * Replaces any previous values, if any. + * + * + * $qb = $conn->createQueryBuilder() + * ->insert('users') + * ->values( + * array( + * 'name' => '?', + * 'password' => '?' + * ) + * ); + * + * + * @param mixed[] $values The values to specify for the insert query indexed by column names. + * + * @return $this This QueryBuilder instance. + */ + public function values(array $values) + { + return $this->add('values', $values); + } + + /** + * Specifies a restriction over the groups of the query. + * Replaces any previous having restrictions, if any. + * + * @param mixed $having The restriction over the groups. + * + * @return $this This QueryBuilder instance. + */ + public function having($having) + { + if (! (func_num_args() === 1 && $having instanceof CompositeExpression)) { + $having = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); + } + + return $this->add('having', $having); + } + + /** + * Adds a restriction over the groups of the query, forming a logical + * conjunction with any existing having restrictions. + * + * @param mixed $having The restriction to append. + * + * @return $this This QueryBuilder instance. + */ + public function andHaving($having) + { + $args = func_get_args(); + $having = $this->getQueryPart('having'); + + if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_AND) { + $having->addMultiple($args); + } else { + array_unshift($args, $having); + $having = new CompositeExpression(CompositeExpression::TYPE_AND, $args); + } + + return $this->add('having', $having); + } + + /** + * Adds a restriction over the groups of the query, forming a logical + * disjunction with any existing having restrictions. + * + * @param mixed $having The restriction to add. + * + * @return $this This QueryBuilder instance. + */ + public function orHaving($having) + { + $args = func_get_args(); + $having = $this->getQueryPart('having'); + + if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_OR) { + $having->addMultiple($args); + } else { + array_unshift($args, $having); + $having = new CompositeExpression(CompositeExpression::TYPE_OR, $args); + } + + return $this->add('having', $having); + } + + /** + * Specifies an ordering for the query results. + * Replaces any previously specified orderings, if any. + * + * @param string $sort The ordering expression. + * @param string $order The ordering direction. + * + * @return $this This QueryBuilder instance. + */ + public function orderBy($sort, $order = null) + { + return $this->add('orderBy', $sort . ' ' . (! $order ? 'ASC' : $order), false); + } + + /** + * Adds an ordering to the query results. + * + * @param string $sort The ordering expression. + * @param string $order The ordering direction. + * + * @return $this This QueryBuilder instance. + */ + public function addOrderBy($sort, $order = null) + { + return $this->add('orderBy', $sort . ' ' . (! $order ? 'ASC' : $order), true); + } + + /** + * Gets a query part by its name. + * + * @param string $queryPartName + * + * @return mixed + */ + public function getQueryPart($queryPartName) + { + return $this->sqlParts[$queryPartName]; + } + + /** + * Gets all query parts. + * + * @return mixed[] + */ + public function getQueryParts() + { + return $this->sqlParts; + } + + /** + * Resets SQL parts. + * + * @param string[]|null $queryPartNames + * + * @return $this This QueryBuilder instance. + */ + public function resetQueryParts($queryPartNames = null) + { + if ($queryPartNames === null) { + $queryPartNames = array_keys($this->sqlParts); + } + + foreach ($queryPartNames as $queryPartName) { + $this->resetQueryPart($queryPartName); + } + + return $this; + } + + /** + * Resets a single SQL part. + * + * @param string $queryPartName + * + * @return $this This QueryBuilder instance. + */ + public function resetQueryPart($queryPartName) + { + $this->sqlParts[$queryPartName] = self::SQL_PARTS_DEFAULTS[$queryPartName]; + + $this->state = self::STATE_DIRTY; + + return $this; + } + + /** + * @return string + * + * @throws QueryException + */ + private function getSQLForSelect() + { + $query = 'SELECT ' . ($this->sqlParts['distinct'] ? 'DISTINCT ' : '') . + implode(', ', $this->sqlParts['select']); + + $query .= ($this->sqlParts['from'] ? ' FROM ' . implode(', ', $this->getFromClauses()) : '') + . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '') + . ($this->sqlParts['groupBy'] ? ' GROUP BY ' . implode(', ', $this->sqlParts['groupBy']) : '') + . ($this->sqlParts['having'] !== null ? ' HAVING ' . ((string) $this->sqlParts['having']) : '') + . ($this->sqlParts['orderBy'] ? ' ORDER BY ' . implode(', ', $this->sqlParts['orderBy']) : ''); + + if ($this->isLimitQuery()) { + return $this->connection->getDatabasePlatform()->modifyLimitQuery( + $query, + $this->maxResults, + $this->firstResult + ); + } + + return $query; + } + + /** + * @return string[] + */ + private function getFromClauses() + { + $fromClauses = []; + $knownAliases = []; + + // Loop through all FROM clauses + foreach ($this->sqlParts['from'] as $from) { + if ($from['alias'] === null) { + $tableSql = $from['table']; + $tableReference = $from['table']; + } else { + $tableSql = $from['table'] . ' ' . $from['alias']; + $tableReference = $from['alias']; + } + + $knownAliases[$tableReference] = true; + + $fromClauses[$tableReference] = $tableSql . $this->getSQLForJoins($tableReference, $knownAliases); + } + + $this->verifyAllAliasesAreKnown($knownAliases); + + return $fromClauses; + } + + /** + * @param string[] $knownAliases + * + * @throws QueryException + */ + private function verifyAllAliasesAreKnown(array $knownAliases) + { + foreach ($this->sqlParts['join'] as $fromAlias => $joins) { + if (! isset($knownAliases[$fromAlias])) { + throw QueryException::unknownAlias($fromAlias, array_keys($knownAliases)); + } + } + } + + /** + * @return bool + */ + private function isLimitQuery() + { + return $this->maxResults !== null || $this->firstResult !== null; + } + + /** + * Converts this instance into an INSERT string in SQL. + * + * @return string + */ + private function getSQLForInsert() + { + return 'INSERT INTO ' . $this->sqlParts['from']['table'] . + ' (' . implode(', ', array_keys($this->sqlParts['values'])) . ')' . + ' VALUES(' . implode(', ', $this->sqlParts['values']) . ')'; + } + + /** + * Converts this instance into an UPDATE string in SQL. + * + * @return string + */ + private function getSQLForUpdate() + { + $table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : ''); + + return 'UPDATE ' . $table + . ' SET ' . implode(', ', $this->sqlParts['set']) + . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : ''); + } + + /** + * Converts this instance into a DELETE string in SQL. + * + * @return string + */ + private function getSQLForDelete() + { + $table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : ''); + + return 'DELETE FROM ' . $table . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : ''); + } + + /** + * Gets a string representation of this QueryBuilder which corresponds to + * the final SQL query being constructed. + * + * @return string The string representation of this QueryBuilder. + */ + public function __toString() + { + return $this->getSQL(); + } + + /** + * Creates a new named parameter and bind the value $value to it. + * + * This method provides a shortcut for PDOStatement::bindValue + * when using prepared statements. + * + * The parameter $value specifies the value that you want to bind. If + * $placeholder is not provided bindValue() will automatically create a + * placeholder for you. An automatic placeholder will be of the name + * ':dcValue1', ':dcValue2' etc. + * + * For more information see {@link http://php.net/pdostatement-bindparam} + * + * Example: + * + * $value = 2; + * $q->eq( 'id', $q->bindValue( $value ) ); + * $stmt = $q->executeQuery(); // executed with 'id = 2' + * + * + * @link http://www.zetacomponents.org + * + * @param mixed $value + * @param mixed $type + * @param string $placeHolder The name to bind with. The string must start with a colon ':'. + * + * @return string the placeholder name used. + */ + public function createNamedParameter($value, $type = ParameterType::STRING, $placeHolder = null) + { + if ($placeHolder === null) { + $this->boundCounter++; + $placeHolder = ':dcValue' . $this->boundCounter; + } + $this->setParameter(substr($placeHolder, 1), $value, $type); + + return $placeHolder; + } + + /** + * Creates a new positional parameter and bind the given value to it. + * + * Attention: If you are using positional parameters with the query builder you have + * to be very careful to bind all parameters in the order they appear in the SQL + * statement , otherwise they get bound in the wrong order which can lead to serious + * bugs in your code. + * + * Example: + * + * $qb = $conn->createQueryBuilder(); + * $qb->select('u.*') + * ->from('users', 'u') + * ->where('u.username = ' . $qb->createPositionalParameter('Foo', ParameterType::STRING)) + * ->orWhere('u.username = ' . $qb->createPositionalParameter('Bar', ParameterType::STRING)) + * + * + * @param mixed $value + * @param int $type + * + * @return string + */ + public function createPositionalParameter($value, $type = ParameterType::STRING) + { + $this->boundCounter++; + $this->setParameter($this->boundCounter, $value, $type); + + return '?'; + } + + /** + * @param string $fromAlias + * @param string[] $knownAliases + * + * @return string + * + * @throws QueryException + */ + private function getSQLForJoins($fromAlias, array &$knownAliases) + { + $sql = ''; + + if (isset($this->sqlParts['join'][$fromAlias])) { + foreach ($this->sqlParts['join'][$fromAlias] as $join) { + if (array_key_exists($join['joinAlias'], $knownAliases)) { + throw QueryException::nonUniqueAlias($join['joinAlias'], array_keys($knownAliases)); + } + $sql .= ' ' . strtoupper($join['joinType']) + . ' JOIN ' . $join['joinTable'] . ' ' . $join['joinAlias'] + . ' ON ' . ((string) $join['joinCondition']); + $knownAliases[$join['joinAlias']] = true; + } + + foreach ($this->sqlParts['join'][$fromAlias] as $join) { + $sql .= $this->getSQLForJoins($join['joinAlias'], $knownAliases); + } + } + + return $sql; + } + + /** + * Deep clone of all expression objects in the SQL parts. + * + * @return void + */ + public function __clone() + { + foreach ($this->sqlParts as $part => $elements) { + if (is_array($this->sqlParts[$part])) { + foreach ($this->sqlParts[$part] as $idx => $element) { + if (! is_object($element)) { + continue; + } + + $this->sqlParts[$part][$idx] = clone $element; + } + } elseif (is_object($elements)) { + $this->sqlParts[$part] = clone $elements; + } + } + + foreach ($this->params as $name => $param) { + if (! is_object($param)) { + continue; + } + + $this->params[$name] = clone $param; + } + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryException.php new file mode 100644 index 0000000..3fcb3b4 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryException.php @@ -0,0 +1,35 @@ + $type) { + ++$bindIndex; + + if ($type !== Connection::PARAM_INT_ARRAY && $type !== Connection::PARAM_STR_ARRAY) { + continue; + } + + if ($isPositional) { + $name = $bindIndex; + } + + $arrayPositions[$name] = false; + } + + if (( ! $arrayPositions && $isPositional)) { + return [$query, $params, $types]; + } + + if ($isPositional) { + $paramOffset = 0; + $queryOffset = 0; + $params = array_values($params); + $types = array_values($types); + + $paramPos = self::getPositionalPlaceholderPositions($query); + + foreach ($paramPos as $needle => $needlePos) { + if (! isset($arrayPositions[$needle])) { + continue; + } + + $needle += $paramOffset; + $needlePos += $queryOffset; + $count = count($params[$needle]); + + $params = array_merge( + array_slice($params, 0, $needle), + $params[$needle], + array_slice($params, $needle + 1) + ); + + $types = array_merge( + array_slice($types, 0, $needle), + $count ? + // array needles are at {@link \Doctrine\DBAL\ParameterType} constants + // + {@link Doctrine\DBAL\Connection::ARRAY_PARAM_OFFSET} + array_fill(0, $count, $types[$needle] - Connection::ARRAY_PARAM_OFFSET) : + [], + array_slice($types, $needle + 1) + ); + + $expandStr = $count ? implode(', ', array_fill(0, $count, '?')) : 'NULL'; + $query = substr($query, 0, $needlePos) . $expandStr . substr($query, $needlePos + 1); + + $paramOffset += ($count - 1); // Grows larger by number of parameters minus the replaced needle. + $queryOffset += (strlen($expandStr) - 1); + } + + return [$query, $params, $types]; + } + + $queryOffset = 0; + $typesOrd = []; + $paramsOrd = []; + + $paramPos = self::getNamedPlaceholderPositions($query); + + foreach ($paramPos as $pos => $paramName) { + $paramLen = strlen($paramName) + 1; + $value = static::extractParam($paramName, $params, true); + + if (! isset($arrayPositions[$paramName]) && ! isset($arrayPositions[':' . $paramName])) { + $pos += $queryOffset; + $queryOffset -= ($paramLen - 1); + $paramsOrd[] = $value; + $typesOrd[] = static::extractParam($paramName, $types, false, ParameterType::STRING); + $query = substr($query, 0, $pos) . '?' . substr($query, ($pos + $paramLen)); + + continue; + } + + $count = count($value); + $expandStr = $count > 0 ? implode(', ', array_fill(0, $count, '?')) : 'NULL'; + + foreach ($value as $val) { + $paramsOrd[] = $val; + $typesOrd[] = static::extractParam($paramName, $types, false) - Connection::ARRAY_PARAM_OFFSET; + } + + $pos += $queryOffset; + $queryOffset += (strlen($expandStr) - $paramLen); + $query = substr($query, 0, $pos) . $expandStr . substr($query, ($pos + $paramLen)); + } + + return [$query, $paramsOrd, $typesOrd]; + } + + /** + * Slice the SQL statement around pairs of quotes and + * return string fragments of SQL outside of quoted literals. + * Each fragment is captured as a 2-element array: + * + * 0 => matched fragment string, + * 1 => offset of fragment in $statement + * + * @param string $statement + * + * @return mixed[][] + */ + private static function getUnquotedStatementFragments($statement) + { + $literal = self::ESCAPED_SINGLE_QUOTED_TEXT . '|' . + self::ESCAPED_DOUBLE_QUOTED_TEXT . '|' . + self::ESCAPED_BACKTICK_QUOTED_TEXT . '|' . + self::ESCAPED_BRACKET_QUOTED_TEXT; + $expression = sprintf('/((.+(?i:ARRAY)\\[.+\\])|([^\'"`\\[]+))(?:%s)?/s', $literal); + + preg_match_all($expression, $statement, $fragments, PREG_OFFSET_CAPTURE); + + return $fragments[1]; + } + + /** + * @param string $paramName The name of the parameter (without a colon in front) + * @param mixed $paramsOrTypes A hash of parameters or types + * @param bool $isParam + * @param mixed $defaultValue An optional default value. If omitted, an exception is thrown + * + * @return mixed + * + * @throws SQLParserUtilsException + */ + private static function extractParam($paramName, $paramsOrTypes, $isParam, $defaultValue = null) + { + if (array_key_exists($paramName, $paramsOrTypes)) { + return $paramsOrTypes[$paramName]; + } + + // Hash keys can be prefixed with a colon for compatibility + if (array_key_exists(':' . $paramName, $paramsOrTypes)) { + return $paramsOrTypes[':' . $paramName]; + } + + if ($defaultValue !== null) { + return $defaultValue; + } + + if ($isParam) { + throw SQLParserUtilsException::missingParam($paramName); + } + + throw SQLParserUtilsException::missingType($paramName); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtilsException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtilsException.php new file mode 100644 index 0000000..a500ed5 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtilsException.php @@ -0,0 +1,31 @@ + Table($tableName)); if you want to rename the table, you have to make sure + */ +abstract class AbstractAsset +{ + /** @var string */ + protected $_name; + + /** + * Namespace of the asset. If none isset the default namespace is assumed. + * + * @var string|null + */ + protected $_namespace = null; + + /** @var bool */ + protected $_quoted = false; + + /** + * Sets the name of this asset. + * + * @param string $name + * + * @return void + */ + protected function _setName($name) + { + if ($this->isIdentifierQuoted($name)) { + $this->_quoted = true; + $name = $this->trimQuotes($name); + } + if (strpos($name, '.') !== false) { + $parts = explode('.', $name); + $this->_namespace = $parts[0]; + $name = $parts[1]; + } + $this->_name = $name; + } + + /** + * Is this asset in the default namespace? + * + * @param string $defaultNamespaceName + * + * @return bool + */ + public function isInDefaultNamespace($defaultNamespaceName) + { + return $this->_namespace === $defaultNamespaceName || $this->_namespace === null; + } + + /** + * Gets the namespace name of this asset. + * + * If NULL is returned this means the default namespace is used. + * + * @return string|null + */ + public function getNamespaceName() + { + return $this->_namespace; + } + + /** + * The shortest name is stripped of the default namespace. All other + * namespaced elements are returned as full-qualified names. + * + * @param string|null $defaultNamespaceName + * + * @return string + */ + public function getShortestName($defaultNamespaceName) + { + $shortestName = $this->getName(); + if ($this->_namespace === $defaultNamespaceName) { + $shortestName = $this->_name; + } + + return strtolower($shortestName); + } + + /** + * The normalized name is full-qualified and lowerspaced. Lowerspacing is + * actually wrong, but we have to do it to keep our sanity. If you are + * using database objects that only differentiate in the casing (FOO vs + * Foo) then you will NOT be able to use Doctrine Schema abstraction. + * + * Every non-namespaced element is prefixed with the default namespace + * name which is passed as argument to this method. + * + * @param string $defaultNamespaceName + * + * @return string + */ + public function getFullQualifiedName($defaultNamespaceName) + { + $name = $this->getName(); + if (! $this->_namespace) { + $name = $defaultNamespaceName . '.' . $name; + } + + return strtolower($name); + } + + /** + * Checks if this asset's name is quoted. + * + * @return bool + */ + public function isQuoted() + { + return $this->_quoted; + } + + /** + * Checks if this identifier is quoted. + * + * @param string $identifier + * + * @return bool + */ + protected function isIdentifierQuoted($identifier) + { + return isset($identifier[0]) && ($identifier[0] === '`' || $identifier[0] === '"' || $identifier[0] === '['); + } + + /** + * Trim quotes from the identifier. + * + * @param string $identifier + * + * @return string + */ + protected function trimQuotes($identifier) + { + return str_replace(['`', '"', '[', ']'], '', $identifier); + } + + /** + * Returns the name of this schema asset. + * + * @return string + */ + public function getName() + { + if ($this->_namespace) { + return $this->_namespace . '.' . $this->_name; + } + + return $this->_name; + } + + /** + * Gets the quoted representation of this asset but only if it was defined with one. Otherwise + * return the plain unquoted value as inserted. + * + * @return string + */ + public function getQuotedName(AbstractPlatform $platform) + { + $keywords = $platform->getReservedKeywordsList(); + $parts = explode('.', $this->getName()); + foreach ($parts as $k => $v) { + $parts[$k] = $this->_quoted || $keywords->isKeyword($v) ? $platform->quoteIdentifier($v) : $v; + } + + return implode('.', $parts); + } + + /** + * Generates 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 string[] $columnNames + * @param string $prefix + * @param int $maxSize + * + * @return string + */ + protected function _generateIdentifierName($columnNames, $prefix = '', $maxSize = 30) + { + $hash = implode('', array_map(static function ($column) { + return dechex(crc32($column)); + }, $columnNames)); + + return strtoupper(substr($prefix . '_' . $hash, 0, $maxSize)); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php new file mode 100644 index 0000000..8e4ffa5 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php @@ -0,0 +1,1135 @@ +_conn = $conn; + $this->_platform = $platform ?: $this->_conn->getDatabasePlatform(); + } + + /** + * Returns the associated platform. + * + * @return AbstractPlatform + */ + public function getDatabasePlatform() + { + return $this->_platform; + } + + /** + * Tries 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. + * + * + * $result = $sm->tryMethod('dropView', 'view_name'); + * + * + * @return mixed + */ + public function tryMethod() + { + $args = func_get_args(); + $method = $args[0]; + unset($args[0]); + $args = array_values($args); + + $callback = [$this, $method]; + assert(is_callable($callback)); + + try { + return call_user_func_array($callback, $args); + } catch (Throwable $e) { + return false; + } + } + + /** + * Lists the available databases for this connection. + * + * @return string[] + */ + public function listDatabases() + { + $sql = $this->_platform->getListDatabasesSQL(); + + $databases = $this->_conn->fetchAll($sql); + + return $this->_getPortableDatabasesList($databases); + } + + /** + * Returns a list of all namespaces in the current database. + * + * @return string[] + */ + public function listNamespaceNames() + { + $sql = $this->_platform->getListNamespacesSQL(); + + $namespaces = $this->_conn->fetchAll($sql); + + return $this->getPortableNamespacesList($namespaces); + } + + /** + * Lists the available sequences for this connection. + * + * @param string|null $database + * + * @return Sequence[] + */ + public function listSequences($database = null) + { + if ($database === null) { + $database = $this->_conn->getDatabase(); + } + $sql = $this->_platform->getListSequencesSQL($database); + + $sequences = $this->_conn->fetchAll($sql); + + return $this->filterAssetNames($this->_getPortableSequencesList($sequences)); + } + + /** + * Lists 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 across different RDBMS. Use + * {@see listTableIndexes($tableName)} to retrieve the primary key + * of a table. Where a RDBMS specifies more details, these are held + * in the platformDetails array. + * + * @param string $table The name of the table. + * @param string|null $database + * + * @return Column[] + */ + public function listTableColumns($table, $database = null) + { + if (! $database) { + $database = $this->_conn->getDatabase(); + } + + $sql = $this->_platform->getListTableColumnsSQL($table, $database); + + $tableColumns = $this->_conn->fetchAll($sql); + + return $this->_getPortableTableColumnList($table, $database, $tableColumns); + } + + /** + * Lists 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[] + */ + public function listTableIndexes($table) + { + $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); + + $tableIndexes = $this->_conn->fetchAll($sql); + + return $this->_getPortableTableIndexesList($tableIndexes, $table); + } + + /** + * Returns true if all the given tables exist. + * + * The usage of a string $tableNames is deprecated. Pass a one-element array instead. + * + * @param string|string[] $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()))); + } + + /** + * Returns a list of all tables in the current database. + * + * @return string[] + */ + public function listTableNames() + { + $sql = $this->_platform->getListTablesSQL(); + + $tables = $this->_conn->fetchAll($sql); + $tableNames = $this->_getPortableTablesList($tables); + + return $this->filterAssetNames($tableNames); + } + + /** + * Filters asset names if they are configured to return only a subset of all + * the found elements. + * + * @param mixed[] $assetNames + * + * @return mixed[] + */ + protected function filterAssetNames($assetNames) + { + $filter = $this->_conn->getConfiguration()->getSchemaAssetsFilter(); + if (! $filter) { + return $assetNames; + } + + return array_values(array_filter($assetNames, $filter)); + } + + /** + * @deprecated Use Configuration::getSchemaAssetsFilter() instead + * + * @return string|null + */ + protected function getFilterSchemaAssetsExpression() + { + return $this->_conn->getConfiguration()->getFilterSchemaAssetsExpression(); + } + + /** + * Lists the tables for this connection. + * + * @return Table[] + */ + public function listTables() + { + $tableNames = $this->listTableNames(); + + $tables = []; + foreach ($tableNames as $tableName) { + $tables[] = $this->listTableDetails($tableName); + } + + return $tables; + } + + /** + * @param string $tableName + * + * @return Table + */ + public function listTableDetails($tableName) + { + $columns = $this->listTableColumns($tableName); + $foreignKeys = []; + if ($this->_platform->supportsForeignKeyConstraints()) { + $foreignKeys = $this->listTableForeignKeys($tableName); + } + $indexes = $this->listTableIndexes($tableName); + + return new Table($tableName, $columns, $indexes, $foreignKeys); + } + + /** + * Lists 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); + } + + /** + * Lists the foreign keys for the given table. + * + * @param string $table The name of the table. + * @param string|null $database + * + * @return ForeignKeyConstraint[] + */ + public function listTableForeignKeys($table, $database = null) + { + if ($database === null) { + $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. + * + * @return void + */ + public function dropDatabase($database) + { + $this->_execSql($this->_platform->getDropDatabaseSQL($database)); + } + + /** + * Drops the given table. + * + * @param string $tableName The name of the table to drop. + * + * @return void + */ + public function dropTable($tableName) + { + $this->_execSql($this->_platform->getDropTableSQL($tableName)); + } + + /** + * Drops the index from the given table. + * + * @param Index|string $index The name of the index. + * @param Table|string $table The name of the table. + * + * @return void + */ + public function dropIndex($index, $table) + { + if ($index instanceof Index) { + $index = $index->getQuotedName($this->_platform); + } + + $this->_execSql($this->_platform->getDropIndexSQL($index, $table)); + } + + /** + * Drops the constraint from the given table. + * + * @param Table|string $table The name of the table. + * + * @return void + */ + public function dropConstraint(Constraint $constraint, $table) + { + $this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table)); + } + + /** + * Drops a foreign key from a table. + * + * @param ForeignKeyConstraint|string $foreignKey The name of the foreign key. + * @param Table|string $table The name of the table with the foreign key. + * + * @return void + */ + 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. + * + * @return void + */ + public function dropSequence($name) + { + $this->_execSql($this->_platform->getDropSequenceSQL($name)); + } + + /** + * Drops a view. + * + * @param string $name The name of the view. + * + * @return void + */ + 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. + * + * @return void + */ + public function createDatabase($database) + { + $this->_execSql($this->_platform->getCreateDatabaseSQL($database)); + } + + /** + * Creates a new table. + * + * @return void + */ + public function createTable(Table $table) + { + $createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS; + $this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags)); + } + + /** + * Creates a new sequence. + * + * @param Sequence $sequence + * + * @return void + * + * @throws ConnectionException If something fails at database level. + */ + public function createSequence($sequence) + { + $this->_execSql($this->_platform->getCreateSequenceSQL($sequence)); + } + + /** + * Creates a constraint on a table. + * + * @param Table|string $table + * + * @return void + */ + public function createConstraint(Constraint $constraint, $table) + { + $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table)); + } + + /** + * Creates a new index on a table. + * + * @param Table|string $table The name of the table on which the index is to be created. + * + * @return void + */ + public function createIndex(Index $index, $table) + { + $this->_execSql($this->_platform->getCreateIndexSQL($index, $table)); + } + + /** + * Creates a new foreign key. + * + * @param ForeignKeyConstraint $foreignKey The ForeignKey instance. + * @param Table|string $table The name of the table on which the foreign key is to be created. + * + * @return void + */ + public function createForeignKey(ForeignKeyConstraint $foreignKey, $table) + { + $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table)); + } + + /** + * Creates a new view. + * + * @return void + */ + public function createView(View $view) + { + $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql())); + } + + /* dropAndCreate*() Methods */ + + /** + * Drops and creates a constraint. + * + * @see dropConstraint() + * @see createConstraint() + * + * @param Table|string $table + * + * @return void + */ + public function dropAndCreateConstraint(Constraint $constraint, $table) + { + $this->tryMethod('dropConstraint', $constraint, $table); + $this->createConstraint($constraint, $table); + } + + /** + * Drops and creates a new index on a table. + * + * @param Table|string $table The name of the table on which the index is to be created. + * + * @return void + */ + public function dropAndCreateIndex(Index $index, $table) + { + $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table); + $this->createIndex($index, $table); + } + + /** + * Drops and creates a new foreign key. + * + * @param ForeignKeyConstraint $foreignKey An associative array that defines properties of the foreign key to be created. + * @param Table|string $table The name of the table on which the foreign key is to be created. + * + * @return void + */ + public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table) + { + $this->tryMethod('dropForeignKey', $foreignKey, $table); + $this->createForeignKey($foreignKey, $table); + } + + /** + * Drops and create a new sequence. + * + * @return void + * + * @throws ConnectionException If something fails at database level. + */ + public function dropAndCreateSequence(Sequence $sequence) + { + $this->tryMethod('dropSequence', $sequence->getQuotedName($this->_platform)); + $this->createSequence($sequence); + } + + /** + * Drops and creates a new table. + * + * @return void + */ + public function dropAndCreateTable(Table $table) + { + $this->tryMethod('dropTable', $table->getQuotedName($this->_platform)); + $this->createTable($table); + } + + /** + * Drops and creates a new database. + * + * @param string $database The name of the database to create. + * + * @return void + */ + public function dropAndCreateDatabase($database) + { + $this->tryMethod('dropDatabase', $database); + $this->createDatabase($database); + } + + /** + * Drops and creates a new view. + * + * @return void + */ + public function dropAndCreateView(View $view) + { + $this->tryMethod('dropView', $view->getQuotedName($this->_platform)); + $this->createView($view); + } + + /* alterTable() Methods */ + + /** + * Alters an existing tables schema. + * + * @return void + */ + public function alterTable(TableDiff $tableDiff) + { + $queries = $this->_platform->getAlterTableSQL($tableDiff); + if (! is_array($queries) || ! count($queries)) { + return; + } + + foreach ($queries as $ddlQuery) { + $this->_execSql($ddlQuery); + } + } + + /** + * Renames a given table to another name. + * + * @param string $name The current name of the table. + * @param string $newName The new name of the table. + * + * @return void + */ + 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 + */ + + /** + * @param mixed[] $databases + * + * @return string[] + */ + protected function _getPortableDatabasesList($databases) + { + $list = []; + foreach ($databases as $value) { + $value = $this->_getPortableDatabaseDefinition($value); + + if (! $value) { + continue; + } + + $list[] = $value; + } + + return $list; + } + + /** + * Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition. + * + * @param mixed[][] $namespaces The list of namespace names in the native DBMS data definition. + * + * @return string[] + */ + protected function getPortableNamespacesList(array $namespaces) + { + $namespacesList = []; + + foreach ($namespaces as $namespace) { + $namespacesList[] = $this->getPortableNamespaceDefinition($namespace); + } + + return $namespacesList; + } + + /** + * @param mixed $database + * + * @return mixed + */ + protected function _getPortableDatabaseDefinition($database) + { + return $database; + } + + /** + * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition. + * + * @param mixed[] $namespace The native DBMS namespace definition. + * + * @return mixed + */ + protected function getPortableNamespaceDefinition(array $namespace) + { + return $namespace; + } + + /** + * @deprecated + * + * @param mixed[][] $functions + * + * @return mixed[][] + */ + protected function _getPortableFunctionsList($functions) + { + $list = []; + foreach ($functions as $value) { + $value = $this->_getPortableFunctionDefinition($value); + + if (! $value) { + continue; + } + + $list[] = $value; + } + + return $list; + } + + /** + * @deprecated + * + * @param mixed[] $function + * + * @return mixed + */ + protected function _getPortableFunctionDefinition($function) + { + return $function; + } + + /** + * @param mixed[][] $triggers + * + * @return mixed[][] + */ + protected function _getPortableTriggersList($triggers) + { + $list = []; + foreach ($triggers as $value) { + $value = $this->_getPortableTriggerDefinition($value); + + if (! $value) { + continue; + } + + $list[] = $value; + } + + return $list; + } + + /** + * @param mixed[] $trigger + * + * @return mixed + */ + protected function _getPortableTriggerDefinition($trigger) + { + return $trigger; + } + + /** + * @param mixed[][] $sequences + * + * @return Sequence[] + */ + protected function _getPortableSequencesList($sequences) + { + $list = []; + + foreach ($sequences as $value) { + $list[] = $this->_getPortableSequenceDefinition($value); + } + + return $list; + } + + /** + * @param mixed[] $sequence + * + * @return Sequence + * + * @throws DBALException + */ + 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 string $table The name of the table. + * @param string $database + * @param mixed[][] $tableColumns + * + * @return Column[] + */ + protected function _getPortableTableColumnList($table, $database, $tableColumns) + { + $eventManager = $this->_platform->getEventManager(); + + $list = []; + foreach ($tableColumns as $tableColumn) { + $column = null; + $defaultPrevented = false; + + if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) { + $eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn, $table, $database, $this->_conn); + $eventManager->dispatchEvent(Events::onSchemaColumnDefinition, $eventArgs); + + $defaultPrevented = $eventArgs->isDefaultPrevented(); + $column = $eventArgs->getColumn(); + } + + if (! $defaultPrevented) { + $column = $this->_getPortableTableColumnDefinition($tableColumn); + } + + if (! $column) { + continue; + } + + $name = strtolower($column->getQuotedName($this->_platform)); + $list[$name] = $column; + } + + return $list; + } + + /** + * Gets Table Column Definition. + * + * @param mixed[] $tableColumn + * + * @return Column + */ + abstract protected function _getPortableTableColumnDefinition($tableColumn); + + /** + * Aggregates and groups the index results according to the required data result. + * + * @param mixed[][] $tableIndexRows + * @param string|null $tableName + * + * @return Index[] + */ + protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null) + { + $result = []; + foreach ($tableIndexRows as $tableIndex) { + $indexName = $keyName = $tableIndex['key_name']; + if ($tableIndex['primary']) { + $keyName = 'primary'; + } + $keyName = strtolower($keyName); + + if (! isset($result[$keyName])) { + $options = [ + 'lengths' => [], + ]; + + if (isset($tableIndex['where'])) { + $options['where'] = $tableIndex['where']; + } + + $result[$keyName] = [ + 'name' => $indexName, + 'columns' => [], + 'unique' => ! $tableIndex['non_unique'], + 'primary' => $tableIndex['primary'], + 'flags' => $tableIndex['flags'] ?? [], + 'options' => $options, + ]; + } + + $result[$keyName]['columns'][] = $tableIndex['column_name']; + $result[$keyName]['options']['lengths'][] = $tableIndex['length'] ?? null; + } + + $eventManager = $this->_platform->getEventManager(); + + $indexes = []; + foreach ($result as $indexKey => $data) { + $index = null; + $defaultPrevented = false; + + if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) { + $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn); + $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs); + + $defaultPrevented = $eventArgs->isDefaultPrevented(); + $index = $eventArgs->getIndex(); + } + + if (! $defaultPrevented) { + $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags'], $data['options']); + } + + if (! $index) { + continue; + } + + $indexes[$indexKey] = $index; + } + + return $indexes; + } + + /** + * @param mixed[][] $tables + * + * @return string[] + */ + protected function _getPortableTablesList($tables) + { + $list = []; + foreach ($tables as $value) { + $value = $this->_getPortableTableDefinition($value); + + if (! $value) { + continue; + } + + $list[] = $value; + } + + return $list; + } + + /** + * @param mixed $table + * + * @return string + */ + protected function _getPortableTableDefinition($table) + { + return $table; + } + + /** + * @param mixed[][] $users + * + * @return string[][] + */ + protected function _getPortableUsersList($users) + { + $list = []; + foreach ($users as $value) { + $value = $this->_getPortableUserDefinition($value); + + if (! $value) { + continue; + } + + $list[] = $value; + } + + return $list; + } + + /** + * @param string[] $user + * + * @return string[] + */ + protected function _getPortableUserDefinition($user) + { + return $user; + } + + /** + * @param mixed[][] $views + * + * @return View[] + */ + protected function _getPortableViewsList($views) + { + $list = []; + foreach ($views as $value) { + $view = $this->_getPortableViewDefinition($value); + + if (! $view) { + continue; + } + + $viewName = strtolower($view->getQuotedName($this->_platform)); + $list[$viewName] = $view; + } + + return $list; + } + + /** + * @param mixed[] $view + * + * @return View|false + */ + protected function _getPortableViewDefinition($view) + { + return false; + } + + /** + * @param mixed[][] $tableForeignKeys + * + * @return ForeignKeyConstraint[] + */ + protected function _getPortableTableForeignKeysList($tableForeignKeys) + { + $list = []; + + foreach ($tableForeignKeys as $value) { + $list[] = $this->_getPortableTableForeignKeyDefinition($value); + } + + return $list; + } + + /** + * @param mixed $tableForeignKey + * + * @return ForeignKeyConstraint + */ + protected function _getPortableTableForeignKeyDefinition($tableForeignKey) + { + return $tableForeignKey; + } + + /** + * @param string[]|string $sql + * + * @return void + */ + protected function _execSql($sql) + { + foreach ((array) $sql as $query) { + $this->_conn->executeUpdate($query); + } + } + + /** + * Creates a schema instance for the current database. + * + * @return Schema + */ + public function createSchema() + { + $namespaces = []; + + if ($this->_platform->supportsSchemas()) { + $namespaces = $this->listNamespaceNames(); + } + + $sequences = []; + + if ($this->_platform->supportsSequences()) { + $sequences = $this->listSequences(); + } + + $tables = $this->listTables(); + + return new Schema($tables, $sequences, $this->createSchemaConfig(), $namespaces); + } + + /** + * Creates the configuration for this schema. + * + * @return SchemaConfig + */ + public function createSchemaConfig() + { + $schemaConfig = new SchemaConfig(); + $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength()); + + $searchPaths = $this->getSchemaSearchPaths(); + if (isset($searchPaths[0])) { + $schemaConfig->setName($searchPaths[0]); + } + + $params = $this->_conn->getParams(); + if (! isset($params['defaultTableOptions'])) { + $params['defaultTableOptions'] = []; + } + if (! isset($params['defaultTableOptions']['charset']) && isset($params['charset'])) { + $params['defaultTableOptions']['charset'] = $params['charset']; + } + $schemaConfig->setDefaultTableOptions($params['defaultTableOptions']); + + return $schemaConfig; + } + + /** + * The search path for namespaces in the currently connected database. + * + * The first entry is usually the default namespace in the Schema. All + * further namespaces contain tables/sequences which can also be addressed + * with a short, not full-qualified name. + * + * For databases that don't support subschema/namespaces this method + * returns the name of the currently connected database. + * + * @return string[] + */ + public function getSchemaSearchPaths() + { + return [$this->_conn->getDatabase()]; + } + + /** + * Given a table comment this method tries to extract a typehint for Doctrine Type, or returns + * the type given as default. + * + * @param string|null $comment + * @param string $currentType + * + * @return string + */ + public function extractDoctrineTypeFromComment($comment, $currentType) + { + if ($comment !== null && preg_match('(\(DC2Type:(((?!\)).)+)\))', $comment, $match)) { + return $match[1]; + } + + return $currentType; + } + + /** + * @param string|null $comment + * @param string|null $type + * + * @return string|null + */ + public function removeDoctrineTypeFromComment($comment, $type) + { + if ($comment === null) { + return null; + } + + return str_replace('(DC2Type:' . $type . ')', '', $comment); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Column.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Column.php new file mode 100644 index 0000000..56c39c1 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Column.php @@ -0,0 +1,451 @@ +_setName($columnName); + $this->setType($type); + $this->setOptions($options); + } + + /** + * @param mixed[] $options + * + * @return Column + */ + public function setOptions(array $options) + { + foreach ($options as $name => $value) { + $method = 'set' . $name; + if (! method_exists($this, $method)) { + // next major: throw an exception + @trigger_error(sprintf( + 'The "%s" column option is not supported,' . + ' setting it is deprecated and will cause an error in Doctrine 3.0', + $name + ), E_USER_DEPRECATED); + + continue; + } + $this->$method($value); + } + + return $this; + } + + /** + * @return Column + */ + public function setType(Type $type) + { + $this->_type = $type; + + return $this; + } + + /** + * @param int|null $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) + { + if (! is_numeric($precision)) { + $precision = 10; // defaults to 10 when no valid precision is given. + } + + $this->_precision = (int) $precision; + + return $this; + } + + /** + * @param int $scale + * + * @return Column + */ + public function setScale($scale) + { + if (! is_numeric($scale)) { + $scale = 0; + } + + $this->_scale = (int) $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 mixed[] $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 $value + * + * @return Column + */ + public function setColumnDefinition($value) + { + $this->_columnDefinition = $value; + + return $this; + } + + /** + * @return Type + */ + public function getType() + { + return $this->_type; + } + + /** + * @return int|null + */ + public function getLength() + { + return $this->_length; + } + + /** + * @return int + */ + public function getPrecision() + { + return $this->_precision; + } + + /** + * @return int + */ + public function getScale() + { + return $this->_scale; + } + + /** + * @return bool + */ + public function getUnsigned() + { + return $this->_unsigned; + } + + /** + * @return bool + */ + public function getFixed() + { + return $this->_fixed; + } + + /** + * @return bool + */ + public function getNotnull() + { + return $this->_notnull; + } + + /** + * @return string|null + */ + public function getDefault() + { + return $this->_default; + } + + /** + * @return mixed[] + */ + public function getPlatformOptions() + { + return $this->_platformOptions; + } + + /** + * @param string $name + * + * @return bool + */ + public function hasPlatformOption($name) + { + return isset($this->_platformOptions[$name]); + } + + /** + * @param string $name + * + * @return mixed + */ + public function getPlatformOption($name) + { + return $this->_platformOptions[$name]; + } + + /** + * @return string|null + */ + public function getColumnDefinition() + { + return $this->_columnDefinition; + } + + /** + * @return bool + */ + public function getAutoincrement() + { + return $this->_autoincrement; + } + + /** + * @param bool $flag + * + * @return Column + */ + public function setAutoincrement($flag) + { + $this->_autoincrement = $flag; + + return $this; + } + + /** + * @param string|null $comment + * + * @return Column + */ + public function setComment($comment) + { + $this->_comment = $comment; + + return $this; + } + + /** + * @return string|null + */ + public function getComment() + { + return $this->_comment; + } + + /** + * @param string $name + * @param mixed $value + * + * @return Column + */ + public function setCustomSchemaOption($name, $value) + { + $this->_customSchemaOptions[$name] = $value; + + return $this; + } + + /** + * @param string $name + * + * @return bool + */ + public function hasCustomSchemaOption($name) + { + return isset($this->_customSchemaOptions[$name]); + } + + /** + * @param string $name + * + * @return mixed + */ + public function getCustomSchemaOption($name) + { + return $this->_customSchemaOptions[$name]; + } + + /** + * @param mixed[] $customSchemaOptions + * + * @return Column + */ + public function setCustomSchemaOptions(array $customSchemaOptions) + { + $this->_customSchemaOptions = $customSchemaOptions; + + return $this; + } + + /** + * @return mixed[] + */ + public function getCustomSchemaOptions() + { + return $this->_customSchemaOptions; + } + + /** + * @return mixed[] + */ + public function toArray() + { + return array_merge([ + '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, + 'comment' => $this->_comment, + ], $this->_platformOptions, $this->_customSchemaOptions); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ColumnDiff.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ColumnDiff.php new file mode 100644 index 0000000..1589f98 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ColumnDiff.php @@ -0,0 +1,55 @@ +oldColumnName = $oldColumnName; + $this->column = $column; + $this->changedProperties = $changedProperties; + $this->fromColumn = $fromColumn; + } + + /** + * @param string $propertyName + * + * @return bool + */ + public function hasChanged($propertyName) + { + return in_array($propertyName, $this->changedProperties); + } + + /** + * @return Identifier + */ + public function getOldColumnName() + { + $quote = $this->fromColumn && $this->fromColumn->isQuoted(); + + return new Identifier($this->oldColumnName, $quote); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Comparator.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Comparator.php new file mode 100644 index 0000000..9ccaa9a --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Comparator.php @@ -0,0 +1,533 @@ +compare($fromSchema, $toSchema); + } + + /** + * Returns a SchemaDiff object containing the differences between the schemas $fromSchema and $toSchema. + * + * The returned differences 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. + * + * @return SchemaDiff + */ + public function compare(Schema $fromSchema, Schema $toSchema) + { + $diff = new SchemaDiff(); + $diff->fromSchema = $fromSchema; + + $foreignKeysToTable = []; + + foreach ($toSchema->getNamespaces() as $namespace) { + if ($fromSchema->hasNamespace($namespace)) { + continue; + } + + $diff->newNamespaces[$namespace] = $namespace; + } + + foreach ($fromSchema->getNamespaces() as $namespace) { + if ($toSchema->hasNamespace($namespace)) { + continue; + } + + $diff->removedNamespaces[$namespace] = $namespace; + } + + foreach ($toSchema->getTables() as $table) { + $tableName = $table->getShortestName($toSchema->getName()); + if (! $fromSchema->hasTable($tableName)) { + $diff->newTables[$tableName] = $toSchema->getTable($tableName); + } else { + $tableDifferences = $this->diffTable($fromSchema->getTable($tableName), $toSchema->getTable($tableName)); + if ($tableDifferences !== false) { + $diff->changedTables[$tableName] = $tableDifferences; + } + } + } + + /* Check if there are tables removed */ + foreach ($fromSchema->getTables() as $table) { + $tableName = $table->getShortestName($fromSchema->getName()); + + $table = $fromSchema->getTable($tableName); + 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] = []; + } + $foreignKeysToTable[$foreignTable][] = $foreignKey; + } + } + + foreach ($diff->removedTables as $tableName => $table) { + if (! isset($foreignKeysToTable[$tableName])) { + continue; + } + + $diff->orphanedForeignKeys = array_merge($diff->orphanedForeignKeys, $foreignKeysToTable[$tableName]); + + // deleting duplicated foreign keys present on both on the orphanedForeignKey + // and the removedForeignKeys from changedTables + foreach ($foreignKeysToTable[$tableName] as $foreignKey) { + // strtolower the table name to make if compatible with getShortestName + $localTableName = strtolower($foreignKey->getLocalTableName()); + if (! isset($diff->changedTables[$localTableName])) { + continue; + } + + foreach ($diff->changedTables[$localTableName]->removedForeignKeys as $key => $removedForeignKey) { + assert($removedForeignKey instanceof ForeignKeyConstraint); + + // We check if the key is from the removed table if not we skip. + if ($tableName !== strtolower($removedForeignKey->getForeignTableName())) { + continue; + } + unset($diff->changedTables[$localTableName]->removedForeignKeys[$key]); + } + } + } + + foreach ($toSchema->getSequences() as $sequence) { + $sequenceName = $sequence->getShortestName($toSchema->getName()); + if (! $fromSchema->hasSequence($sequenceName)) { + if (! $this->isAutoIncrementSequenceInSchema($fromSchema, $sequence)) { + $diff->newSequences[] = $sequence; + } + } else { + if ($this->diffSequence($sequence, $fromSchema->getSequence($sequenceName))) { + $diff->changedSequences[] = $toSchema->getSequence($sequenceName); + } + } + } + + foreach ($fromSchema->getSequences() as $sequence) { + if ($this->isAutoIncrementSequenceInSchema($toSchema, $sequence)) { + continue; + } + + $sequenceName = $sequence->getShortestName($fromSchema->getName()); + + if ($toSchema->hasSequence($sequenceName)) { + continue; + } + + $diff->removedSequences[] = $sequence; + } + + return $diff; + } + + /** + * @param Schema $schema + * @param Sequence $sequence + * + * @return bool + */ + private function isAutoIncrementSequenceInSchema($schema, $sequence) + { + foreach ($schema->getTables() as $table) { + if ($sequence->isAutoIncrementsFor($table)) { + return true; + } + } + + return false; + } + + /** + * @return bool + */ + public function diffSequence(Sequence $sequence1, Sequence $sequence2) + { + if ($sequence1->getAllocationSize() !== $sequence2->getAllocationSize()) { + return true; + } + + return $sequence1->getInitialValue() !== $sequence2->getInitialValue(); + } + + /** + * Returns the difference between the tables $table1 and $table2. + * + * If there are no differences this method returns the boolean false. + * + * @return TableDiff|false + */ + public function diffTable(Table $table1, Table $table2) + { + $changes = 0; + $tableDifferences = new TableDiff($table1->getName()); + $tableDifferences->fromTable = $table1; + + $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)) { + continue; + } + + $tableDifferences->addedColumns[$columnName] = $column; + $changes++; + } + /* See if there are any removed fields in table 2 */ + foreach ($table1Columns as $columnName => $column) { + // See if column is removed in table 2. + if (! $table2->hasColumn($columnName)) { + $tableDifferences->removedColumns[$columnName] = $column; + $changes++; + continue; + } + + // See if column has changed properties in table 2. + $changedProperties = $this->diffColumn($column, $table2->getColumn($columnName)); + + if (empty($changedProperties)) { + continue; + } + + $columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties); + $columnDiff->fromColumn = $column; + $tableDifferences->changedColumns[$column->getName()] = $columnDiff; + $changes++; + } + + $this->detectColumnRenamings($tableDifferences); + + $table1Indexes = $table1->getIndexes(); + $table2Indexes = $table2->getIndexes(); + + /* See if all the indexes in table 1 exist in table 2 */ + foreach ($table2Indexes as $indexName => $index) { + if (($index->isPrimary() && $table1->hasPrimaryKey()) || $table1->hasIndex($indexName)) { + continue; + } + + $tableDifferences->addedIndexes[$indexName] = $index; + $changes++; + } + /* See if there are any removed indexes in table 2 */ + foreach ($table1Indexes as $indexName => $index) { + // See if index is removed in table 2. + if (($index->isPrimary() && ! $table2->hasPrimaryKey()) || + ! $index->isPrimary() && ! $table2->hasIndex($indexName) + ) { + $tableDifferences->removedIndexes[$indexName] = $index; + $changes++; + continue; + } + + // See if index has changed in table 2. + $table2Index = $index->isPrimary() ? $table2->getPrimaryKey() : $table2->getIndex($indexName); + assert($table2Index instanceof Index); + + if (! $this->diffIndex($index, $table2Index)) { + continue; + } + + $tableDifferences->changedIndexes[$indexName] = $table2Index; + $changes++; + } + + $this->detectIndexRenamings($tableDifferences); + + $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], $toFkeys[$key2]); + } else { + if (strtolower($constraint1->getName()) === strtolower($constraint2->getName())) { + $tableDifferences->changedForeignKeys[] = $constraint2; + $changes++; + unset($fromFkeys[$key1], $toFkeys[$key2]); + } + } + } + } + + foreach ($fromFkeys as $constraint1) { + $tableDifferences->removedForeignKeys[] = $constraint1; + $changes++; + } + + foreach ($toFkeys as $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 ambiguities between different possibilities should not lead to renaming at all. + * + * @return void + */ + private function detectColumnRenamings(TableDiff $tableDifferences) + { + $renameCandidates = []; + foreach ($tableDifferences->addedColumns as $addedColumnName => $addedColumn) { + foreach ($tableDifferences->removedColumns as $removedColumn) { + if (count($this->diffColumn($addedColumn, $removedColumn)) !== 0) { + continue; + } + + $renameCandidates[$addedColumn->getName()][] = [$removedColumn, $addedColumn, $addedColumnName]; + } + } + + foreach ($renameCandidates as $candidateColumns) { + if (count($candidateColumns) !== 1) { + continue; + } + + [$removedColumn, $addedColumn] = $candidateColumns[0]; + $removedColumnName = strtolower($removedColumn->getName()); + $addedColumnName = strtolower($addedColumn->getName()); + + if (isset($tableDifferences->renamedColumns[$removedColumnName])) { + continue; + } + + $tableDifferences->renamedColumns[$removedColumnName] = $addedColumn; + unset( + $tableDifferences->addedColumns[$addedColumnName], + $tableDifferences->removedColumns[$removedColumnName] + ); + } + } + + /** + * Try to find indexes that only changed their name, rename operations maybe cheaper than add/drop + * however ambiguities between different possibilities should not lead to renaming at all. + * + * @return void + */ + private function detectIndexRenamings(TableDiff $tableDifferences) + { + $renameCandidates = []; + + // Gather possible rename candidates by comparing each added and removed index based on semantics. + foreach ($tableDifferences->addedIndexes as $addedIndexName => $addedIndex) { + foreach ($tableDifferences->removedIndexes as $removedIndex) { + if ($this->diffIndex($addedIndex, $removedIndex)) { + continue; + } + + $renameCandidates[$addedIndex->getName()][] = [$removedIndex, $addedIndex, $addedIndexName]; + } + } + + foreach ($renameCandidates as $candidateIndexes) { + // If the current rename candidate contains exactly one semantically equal index, + // we can safely rename it. + // Otherwise it is unclear if a rename action is really intended, + // therefore we let those ambiguous indexes be added/dropped. + if (count($candidateIndexes) !== 1) { + continue; + } + + [$removedIndex, $addedIndex] = $candidateIndexes[0]; + + $removedIndexName = strtolower($removedIndex->getName()); + $addedIndexName = strtolower($addedIndex->getName()); + + if (isset($tableDifferences->renamedIndexes[$removedIndexName])) { + continue; + } + + $tableDifferences->renamedIndexes[$removedIndexName] = $addedIndex; + unset( + $tableDifferences->addedIndexes[$addedIndexName], + $tableDifferences->removedIndexes[$removedIndexName] + ); + } + } + + /** + * @return bool + */ + public function diffForeignKey(ForeignKeyConstraint $key1, ForeignKeyConstraint $key2) + { + if (array_map('strtolower', $key1->getUnquotedLocalColumns()) !== array_map('strtolower', $key2->getUnquotedLocalColumns())) { + return true; + } + + if (array_map('strtolower', $key1->getUnquotedForeignColumns()) !== array_map('strtolower', $key2->getUnquotedForeignColumns())) { + return true; + } + + if ($key1->getUnqualifiedForeignTableName() !== $key2->getUnqualifiedForeignTableName()) { + return true; + } + + if ($key1->onUpdate() !== $key2->onUpdate()) { + return true; + } + + return $key1->onDelete() !== $key2->onDelete(); + } + + /** + * Returns the difference between the fields $field1 and $field2. + * + * If there are differences this method returns $field2, otherwise the + * boolean false. + * + * @return string[] + */ + public function diffColumn(Column $column1, Column $column2) + { + $properties1 = $column1->toArray(); + $properties2 = $column2->toArray(); + + $changedProperties = []; + + if (get_class($properties1['type']) !== get_class($properties2['type'])) { + $changedProperties[] = 'type'; + } + + foreach (['notnull', 'unsigned', 'autoincrement'] as $property) { + if ($properties1[$property] === $properties2[$property]) { + continue; + } + + $changedProperties[] = $property; + } + + // This is a very nasty hack to make comparator work with the legacy json_array type, which should be killed in v3 + if ($this->isALegacyJsonComparison($properties1['type'], $properties2['type'])) { + array_shift($changedProperties); + + $changedProperties[] = 'comment'; + } + + // Null values need to be checked additionally as they tell whether to create or drop a default value. + // null != 0, null != false, null != '' etc. This affects platform's table alteration SQL generation. + if (($properties1['default'] === null) !== ($properties2['default'] === null) + || $properties1['default'] != $properties2['default']) { + $changedProperties[] = 'default'; + } + + if (($properties1['type'] instanceof Types\StringType && ! $properties1['type'] instanceof Types\GuidType) || + $properties1['type'] instanceof Types\BinaryType + ) { + // check if value of length is set at all, default value assumed otherwise. + $length1 = $properties1['length'] ?: 255; + $length2 = $properties2['length'] ?: 255; + if ($length1 !== $length2) { + $changedProperties[] = 'length'; + } + + if ($properties1['fixed'] !== $properties2['fixed']) { + $changedProperties[] = 'fixed'; + } + } elseif ($properties1['type'] instanceof Types\DecimalType) { + if (($properties1['precision'] ?: 10) !== ($properties2['precision'] ?: 10)) { + $changedProperties[] = 'precision'; + } + if ($properties1['scale'] !== $properties2['scale']) { + $changedProperties[] = 'scale'; + } + } + + // A null value and an empty string are actually equal for a comment so they should not trigger a change. + if ($properties1['comment'] !== $properties2['comment'] && + ! ($properties1['comment'] === null && $properties2['comment'] === '') && + ! ($properties2['comment'] === null && $properties1['comment'] === '') + ) { + $changedProperties[] = 'comment'; + } + + $customOptions1 = $column1->getCustomSchemaOptions(); + $customOptions2 = $column2->getCustomSchemaOptions(); + + foreach (array_merge(array_keys($customOptions1), array_keys($customOptions2)) as $key) { + if (! array_key_exists($key, $properties1) || ! array_key_exists($key, $properties2)) { + $changedProperties[] = $key; + } elseif ($properties1[$key] !== $properties2[$key]) { + $changedProperties[] = $key; + } + } + + $platformOptions1 = $column1->getPlatformOptions(); + $platformOptions2 = $column2->getPlatformOptions(); + + foreach (array_keys(array_intersect_key($platformOptions1, $platformOptions2)) as $key) { + if ($properties1[$key] === $properties2[$key]) { + continue; + } + + $changedProperties[] = $key; + } + + return array_unique($changedProperties); + } + + /** + * TODO: kill with fire on v3.0 + * + * @deprecated + */ + private function isALegacyJsonComparison(Types\Type $one, Types\Type $other) : bool + { + if (! $one instanceof Types\JsonType || ! $other instanceof Types\JsonType) { + return false; + } + + return ( ! $one instanceof Types\JsonArrayType && $other instanceof Types\JsonArrayType) + || ( ! $other instanceof Types\JsonArrayType && $one instanceof Types\JsonArrayType); + } + + /** + * 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. + * + * @return bool + */ + public function diffIndex(Index $index1, Index $index2) + { + return ! ($index1->isFullfilledBy($index2) && $index2->isFullfilledBy($index1)); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Constraint.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Constraint.php new file mode 100644 index 0000000..65e239e --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Constraint.php @@ -0,0 +1,43 @@ +_platform->getListTablesSQL(); + $sql .= ' AND CREATOR = UPPER(' . $this->_conn->quote($this->_conn->getUsername()) . ')'; + + $tables = $this->_conn->fetchAll($sql); + + return $this->filterAssetNames($this->_getPortableTablesList($tables)); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableColumnDefinition($tableColumn) + { + $tableColumn = array_change_key_case($tableColumn, CASE_LOWER); + + $length = null; + $fixed = null; + $scale = false; + $precision = false; + + $default = null; + + if ($tableColumn['default'] !== null && $tableColumn['default'] !== 'NULL') { + $default = $tableColumn['default']; + + if (preg_match('/^\'(.*)\'$/s', $default, $matches)) { + $default = str_replace("''", "'", $matches[1]); + } + } + + $type = $this->_platform->getDoctrineTypeMapping($tableColumn['typename']); + + if (isset($tableColumn['comment'])) { + $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); + $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); + } + + 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 = [ + 'length' => $length, + 'unsigned' => false, + 'fixed' => (bool) $fixed, + 'default' => $default, + 'autoincrement' => (bool) $tableColumn['autoincrement'], + 'notnull' => (bool) ($tableColumn['nulls'] === 'N'), + 'scale' => null, + 'precision' => null, + 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== '' + ? $tableColumn['comment'] + : null, + 'platformOptions' => [], + ]; + + if ($scale !== null && $precision !== null) { + $options['scale'] = $scale; + $options['precision'] = $precision; + } + + return new Column($tableColumn['colname'], Type::getType($type), $options); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTablesList($tables) + { + $tableNames = []; + foreach ($tables as $tableRow) { + $tableRow = array_change_key_case($tableRow, CASE_LOWER); + $tableNames[] = $tableRow['name']; + } + + return $tableNames; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null) + { + foreach ($tableIndexRows as &$tableIndexRow) { + $tableIndexRow = array_change_key_case($tableIndexRow, CASE_LOWER); + $tableIndexRow['primary'] = (bool) $tableIndexRow['primary']; + } + + return parent::_getPortableTableIndexesList($tableIndexRows, $tableName); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableForeignKeyDefinition($tableForeignKey) + { + return new ForeignKeyConstraint( + $tableForeignKey['local_columns'], + $tableForeignKey['foreign_table'], + $tableForeignKey['foreign_columns'], + $tableForeignKey['name'], + $tableForeignKey['options'] + ); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableForeignKeysList($tableForeignKeys) + { + $foreignKeys = []; + + foreach ($tableForeignKeys as $tableForeignKey) { + $tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER); + + if (! isset($foreignKeys[$tableForeignKey['index_name']])) { + $foreignKeys[$tableForeignKey['index_name']] = [ + 'local_columns' => [$tableForeignKey['local_column']], + 'foreign_table' => $tableForeignKey['foreign_table'], + 'foreign_columns' => [$tableForeignKey['foreign_column']], + 'name' => $tableForeignKey['index_name'], + 'options' => [ + 'onUpdate' => $tableForeignKey['on_update'], + 'onDelete' => $tableForeignKey['on_delete'], + ], + ]; + } else { + $foreignKeys[$tableForeignKey['index_name']]['local_columns'][] = $tableForeignKey['local_column']; + $foreignKeys[$tableForeignKey['index_name']]['foreign_columns'][] = $tableForeignKey['foreign_column']; + } + } + + return parent::_getPortableTableForeignKeysList($foreignKeys); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableForeignKeyRuleDef($def) + { + if ($def === 'C') { + return 'CASCADE'; + } + + if ($def === 'N') { + return 'SET NULL'; + } + + return null; + } + + /** + * {@inheritdoc} + */ + 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); + } + + public function listTableDetails($tableName) : Table + { + $table = parent::listTableDetails($tableName); + + /** @var DB2Platform $platform */ + $platform = $this->_platform; + $sql = $platform->getListTableCommentsSQL($tableName); + + $tableOptions = $this->_conn->fetchAssoc($sql); + $table->addOption('comment', $tableOptions['REMARKS']); + + return $table; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DrizzleSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DrizzleSchemaManager.php new file mode 100644 index 0000000..c334db2 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DrizzleSchemaManager.php @@ -0,0 +1,103 @@ +_platform->getDoctrineTypeMapping($dbType); + $type = $this->extractDoctrineTypeFromComment($tableColumn['COLUMN_COMMENT'], $type); + $tableColumn['COLUMN_COMMENT'] = $this->removeDoctrineTypeFromComment($tableColumn['COLUMN_COMMENT'], $type); + + $options = [ + 'notnull' => ! (bool) $tableColumn['IS_NULLABLE'], + 'length' => (int) $tableColumn['CHARACTER_MAXIMUM_LENGTH'], + 'default' => $tableColumn['COLUMN_DEFAULT'] ?? null, + 'autoincrement' => (bool) $tableColumn['IS_AUTO_INCREMENT'], + 'scale' => (int) $tableColumn['NUMERIC_SCALE'], + 'precision' => (int) $tableColumn['NUMERIC_PRECISION'], + 'comment' => isset($tableColumn['COLUMN_COMMENT']) && $tableColumn['COLUMN_COMMENT'] !== '' + ? $tableColumn['COLUMN_COMMENT'] + : null, + ]; + + $column = new Column($tableColumn['COLUMN_NAME'], Type::getType($type), $options); + + if (! empty($tableColumn['COLLATION_NAME'])) { + $column->setPlatformOption('collation', $tableColumn['COLLATION_NAME']); + } + + return $column; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableDatabaseDefinition($database) + { + return $database['SCHEMA_NAME']; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableDefinition($table) + { + return $table['TABLE_NAME']; + } + + /** + * {@inheritdoc} + */ + public function _getPortableTableForeignKeyDefinition($tableForeignKey) + { + $columns = []; + foreach (explode(',', $tableForeignKey['CONSTRAINT_COLUMNS']) as $value) { + $columns[] = trim($value, ' `'); + } + + $refColumns = []; + foreach (explode(',', $tableForeignKey['REFERENCED_TABLE_COLUMNS']) as $value) { + $refColumns[] = trim($value, ' `'); + } + + return new ForeignKeyConstraint( + $columns, + $tableForeignKey['REFERENCED_TABLE_NAME'], + $refColumns, + $tableForeignKey['CONSTRAINT_NAME'], + [ + 'onUpdate' => $tableForeignKey['UPDATE_RULE'], + 'onDelete' => $tableForeignKey['DELETE_RULE'], + ] + ); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableIndexesList($tableIndexes, $tableName = null) + { + $indexes = []; + foreach ($tableIndexes as $k) { + $k['primary'] = (bool) $k['primary']; + $indexes[] = $k; + } + + return parent::_getPortableTableIndexesList($indexes, $tableName); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php new file mode 100644 index 0000000..3c6585e --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php @@ -0,0 +1,393 @@ + Identifier) + * + * @var Identifier[] + */ + protected $_localColumnNames; + + /** + * Table or asset identifier instance of the referenced table name the foreign key constraint is associated with. + * + * @var Table|Identifier + */ + protected $_foreignTableName; + + /** + * Asset identifier instances of the referenced table column names the foreign key constraint is associated with. + * array($columnName => Identifier) + * + * @var Identifier[] + */ + protected $_foreignColumnNames; + + /** + * Options associated with the foreign key constraint. + * + * @var mixed[] + */ + protected $_options; + + /** + * Initializes the foreign key constraint. + * + * @param string[] $localColumnNames Names of the referencing table columns. + * @param Table|string $foreignTableName Referenced table. + * @param string[] $foreignColumnNames Names of the referenced table columns. + * @param string|null $name Name of the foreign key constraint. + * @param mixed[] $options Options associated with the foreign key constraint. + */ + public function __construct(array $localColumnNames, $foreignTableName, array $foreignColumnNames, $name = null, array $options = []) + { + if ($name !== null) { + $this->_setName($name); + } + + $this->_localColumnNames = $this->createIdentifierMap($localColumnNames); + + if ($foreignTableName instanceof Table) { + $this->_foreignTableName = $foreignTableName; + } else { + $this->_foreignTableName = new Identifier($foreignTableName); + } + + $this->_foreignColumnNames = $this->createIdentifierMap($foreignColumnNames); + $this->_options = $options; + } + + /** + * @param string[] $names + * + * @return Identifier[] + */ + private function createIdentifierMap(array $names) : array + { + $identifiers = []; + + foreach ($names as $name) { + $identifiers[$name] = new Identifier($name); + } + + return $identifiers; + } + + /** + * Returns the name of the referencing table + * the foreign key constraint is associated with. + * + * @return string + */ + public function getLocalTableName() + { + return $this->_localTable->getName(); + } + + /** + * Sets the Table instance of the referencing table + * the foreign key constraint is associated with. + * + * @param Table $table Instance of the referencing table. + * + * @return void + */ + public function setLocalTable(Table $table) + { + $this->_localTable = $table; + } + + /** + * @return Table + */ + public function getLocalTable() + { + return $this->_localTable; + } + + /** + * Returns the names of the referencing table columns + * the foreign key constraint is associated with. + * + * @return string[] + */ + public function getLocalColumns() + { + return array_keys($this->_localColumnNames); + } + + /** + * Returns the quoted representation of the referencing table column names + * the foreign key constraint is associated with. + * + * But only if they were defined with one or the referencing table column name + * is a keyword reserved by the platform. + * Otherwise the plain unquoted value as inserted is returned. + * + * @param AbstractPlatform $platform The platform to use for quotation. + * + * @return string[] + */ + public function getQuotedLocalColumns(AbstractPlatform $platform) + { + $columns = []; + + foreach ($this->_localColumnNames as $column) { + $columns[] = $column->getQuotedName($platform); + } + + return $columns; + } + + /** + * Returns unquoted representation of local table column names for comparison with other FK + * + * @return string[] + */ + public function getUnquotedLocalColumns() + { + return array_map([$this, 'trimQuotes'], $this->getLocalColumns()); + } + + /** + * Returns unquoted representation of foreign table column names for comparison with other FK + * + * @return string[] + */ + public function getUnquotedForeignColumns() + { + return array_map([$this, 'trimQuotes'], $this->getForeignColumns()); + } + + /** + * {@inheritdoc} + * + * @see getLocalColumns + */ + public function getColumns() + { + return $this->getLocalColumns(); + } + + /** + * Returns the quoted representation of the referencing table column names + * the foreign key constraint is associated with. + * + * But only if they were defined with one or the referencing table column name + * is a keyword reserved by the platform. + * Otherwise the plain unquoted value as inserted is returned. + * + * @see getQuotedLocalColumns + * + * @param AbstractPlatform $platform The platform to use for quotation. + * + * @return string[] + */ + public function getQuotedColumns(AbstractPlatform $platform) + { + return $this->getQuotedLocalColumns($platform); + } + + /** + * Returns the name of the referenced table + * the foreign key constraint is associated with. + * + * @return string + */ + public function getForeignTableName() + { + return $this->_foreignTableName->getName(); + } + + /** + * Returns the non-schema qualified foreign table name. + * + * @return string + */ + public function getUnqualifiedForeignTableName() + { + $name = $this->_foreignTableName->getName(); + $position = strrpos($name, '.'); + + if ($position !== false) { + $name = substr($name, $position); + } + + return strtolower($name); + } + + /** + * Returns the quoted representation of the referenced table name + * the foreign key constraint is associated with. + * + * But only if it was defined with one or the referenced table name + * is a keyword reserved by the platform. + * Otherwise the plain unquoted value as inserted is returned. + * + * @param AbstractPlatform $platform The platform to use for quotation. + * + * @return string + */ + public function getQuotedForeignTableName(AbstractPlatform $platform) + { + return $this->_foreignTableName->getQuotedName($platform); + } + + /** + * Returns the names of the referenced table columns + * the foreign key constraint is associated with. + * + * @return string[] + */ + public function getForeignColumns() + { + return array_keys($this->_foreignColumnNames); + } + + /** + * Returns the quoted representation of the referenced table column names + * the foreign key constraint is associated with. + * + * But only if they were defined with one or the referenced table column name + * is a keyword reserved by the platform. + * Otherwise the plain unquoted value as inserted is returned. + * + * @param AbstractPlatform $platform The platform to use for quotation. + * + * @return string[] + */ + public function getQuotedForeignColumns(AbstractPlatform $platform) + { + $columns = []; + + foreach ($this->_foreignColumnNames as $column) { + $columns[] = $column->getQuotedName($platform); + } + + return $columns; + } + + /** + * Returns whether or not a given option + * is associated with the foreign key constraint. + * + * @param string $name Name of the option to check. + * + * @return bool + */ + public function hasOption($name) + { + return isset($this->_options[$name]); + } + + /** + * Returns an option associated with the foreign key constraint. + * + * @param string $name Name of the option the foreign key constraint is associated with. + * + * @return mixed + */ + public function getOption($name) + { + return $this->_options[$name]; + } + + /** + * Returns the options associated with the foreign key constraint. + * + * @return mixed[] + */ + public function getOptions() + { + return $this->_options; + } + + /** + * Returns the referential action for UPDATE operations + * on the referenced table the foreign key constraint is associated with. + * + * @return string|null + */ + public function onUpdate() + { + return $this->onEvent('onUpdate'); + } + + /** + * Returns the referential action for DELETE operations + * on the referenced table the foreign key constraint is associated with. + * + * @return string|null + */ + public function onDelete() + { + return $this->onEvent('onDelete'); + } + + /** + * Returns the referential action for a given database operation + * on the referenced table the foreign key constraint is associated with. + * + * @param string $event Name of the database operation/event to return the referential action for. + * + * @return string|null + */ + private function onEvent($event) + { + if (isset($this->_options[$event])) { + $onEvent = strtoupper($this->_options[$event]); + + if (! in_array($onEvent, ['NO ACTION', 'RESTRICT'])) { + return $onEvent; + } + } + + return false; + } + + /** + * Checks whether this foreign key constraint intersects the given index columns. + * + * Returns `true` if at least one of this foreign key's local columns + * matches one of the given index's columns, `false` otherwise. + * + * @param Index $index The index to be checked against. + * + * @return bool + */ + public function intersectsIndexColumns(Index $index) + { + foreach ($index->getColumns() as $indexColumn) { + foreach ($this->_localColumnNames as $localColumn) { + if (strtolower($indexColumn) === strtolower($localColumn->getName())) { + return true; + } + } + } + + return false; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Identifier.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Identifier.php new file mode 100644 index 0000000..f34465e --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Identifier.php @@ -0,0 +1,27 @@ +_setName($identifier); + + if (! $quote || $this->_quoted) { + return; + } + + $this->_setName('"' . $this->getName() . '"'); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php new file mode 100644 index 0000000..7a31c78 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php @@ -0,0 +1,359 @@ + Identifier) + * + * @var Identifier[] + */ + protected $_columns = []; + + /** @var bool */ + protected $_isUnique = false; + + /** @var bool */ + protected $_isPrimary = false; + + /** + * Platform specific flags for indexes. + * array($flagName => true) + * + * @var true[] + */ + protected $_flags = []; + + /** + * Platform specific options + * + * @todo $_flags should eventually be refactored into options + * @var mixed[] + */ + private $options = []; + + /** + * @param string $indexName + * @param string[] $columns + * @param bool $isUnique + * @param bool $isPrimary + * @param string[] $flags + * @param mixed[] $options + */ + public function __construct($indexName, array $columns, $isUnique = false, $isPrimary = false, array $flags = [], array $options = []) + { + $isUnique = $isUnique || $isPrimary; + + $this->_setName($indexName); + $this->_isUnique = $isUnique; + $this->_isPrimary = $isPrimary; + $this->options = $options; + + foreach ($columns as $column) { + $this->_addColumn($column); + } + foreach ($flags as $flag) { + $this->addFlag($flag); + } + } + + /** + * @param string $column + * + * @return void + * + * @throws InvalidArgumentException + */ + protected function _addColumn($column) + { + if (! is_string($column)) { + throw new InvalidArgumentException('Expecting a string as Index Column'); + } + + $this->_columns[$column] = new Identifier($column); + } + + /** + * {@inheritdoc} + */ + public function getColumns() + { + return array_keys($this->_columns); + } + + /** + * {@inheritdoc} + */ + public function getQuotedColumns(AbstractPlatform $platform) + { + $subParts = $platform->supportsColumnLengthIndexes() && $this->hasOption('lengths') + ? $this->getOption('lengths') : []; + + $columns = []; + + foreach ($this->_columns as $column) { + $length = array_shift($subParts); + + $quotedColumn = $column->getQuotedName($platform); + + if ($length !== null) { + $quotedColumn .= '(' . $length . ')'; + } + + $columns[] = $quotedColumn; + } + + return $columns; + } + + /** + * @return string[] + */ + public function getUnquotedColumns() + { + return array_map([$this, 'trimQuotes'], $this->getColumns()); + } + + /** + * Is the index neither unique nor primary key? + * + * @return bool + */ + public function isSimpleIndex() + { + return ! $this->_isPrimary && ! $this->_isUnique; + } + + /** + * @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 = $this->trimQuotes(strtolower($columnName)); + $indexColumns = array_map('strtolower', $this->getUnquotedColumns()); + + return array_search($columnName, $indexColumns) === $pos; + } + + /** + * Checks if this index exactly spans the given column names in the correct order. + * + * @param string[] $columnNames + * + * @return bool + */ + public function spansColumns(array $columnNames) + { + $columns = $this->getColumns(); + $numberOfColumns = count($columns); + $sameColumns = true; + + for ($i = 0; $i < $numberOfColumns; $i++) { + if (isset($columnNames[$i]) && $this->trimQuotes(strtolower($columns[$i])) === $this->trimQuotes(strtolower($columnNames[$i]))) { + continue; + } + + $sameColumns = false; + } + + return $sameColumns; + } + + /** + * Checks if the other index already fulfills all the indexing and constraint needs of the current one. + * + * @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->samePartialIndex($other)) { + return false; + } + + if (! $this->hasSameColumnLengths($other)) { + return false; + } + + if (! $this->isUnique() && ! $this->isPrimary()) { + // this is a special case: If the current key is neither primary or unique, any unique 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 fulfill the requirements of just an + // index that has no constraints. + return true; + } + + if ($other->isPrimary() !== $this->isPrimary()) { + return false; + } + + return $other->isUnique() === $this->isUnique(); + } + + return false; + } + + /** + * Detects if the other index is a non-unique, non primary index that can be overwritten by this one. + * + * @return bool + */ + public function overrules(Index $other) + { + if ($other->isPrimary()) { + return false; + } + + if ($this->isSimpleIndex() && $other->isUnique()) { + return false; + } + + return $this->spansColumns($other->getColumns()) && ($this->isPrimary() || $this->isUnique()) && $this->samePartialIndex($other); + } + + /** + * Returns platform specific flags for indexes. + * + * @return string[] + */ + public function getFlags() + { + return array_keys($this->_flags); + } + + /** + * Adds Flag for an index that translates to platform specific handling. + * + * @param string $flag + * + * @return Index + * + * @example $index->addFlag('CLUSTERED') + */ + public function addFlag($flag) + { + $this->_flags[strtolower($flag)] = true; + + return $this; + } + + /** + * Does this index have a specific flag? + * + * @param string $flag + * + * @return bool + */ + public function hasFlag($flag) + { + return isset($this->_flags[strtolower($flag)]); + } + + /** + * Removes a flag. + * + * @param string $flag + * + * @return void + */ + public function removeFlag($flag) + { + unset($this->_flags[strtolower($flag)]); + } + + /** + * @param string $name + * + * @return bool + */ + public function hasOption($name) + { + return isset($this->options[strtolower($name)]); + } + + /** + * @param string $name + * + * @return mixed + */ + public function getOption($name) + { + return $this->options[strtolower($name)]; + } + + /** + * @return mixed[] + */ + public function getOptions() + { + return $this->options; + } + + /** + * Return whether the two indexes have the same partial index + * + * @return bool + */ + private function samePartialIndex(Index $other) + { + if ($this->hasOption('where') && $other->hasOption('where') && $this->getOption('where') === $other->getOption('where')) { + return true; + } + + return ! $this->hasOption('where') && ! $other->hasOption('where'); + } + + /** + * Returns whether the index has the same column lengths as the other + */ + private function hasSameColumnLengths(self $other) : bool + { + $filter = static function (?int $length) : bool { + return $length !== null; + }; + + return array_filter($this->options['lengths'] ?? [], $filter) + === array_filter($other->options['lengths'] ?? [], $filter); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php new file mode 100644 index 0000000..9522faf --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php @@ -0,0 +1,351 @@ + "\0", + "\\'" => "'", + '\\"' => '"', + '\\b' => "\b", + '\\n' => "\n", + '\\r' => "\r", + '\\t' => "\t", + '\\Z' => "\x1a", + '\\\\' => '\\', + '\\%' => '%', + '\\_' => '_', + + // Internally, MariaDB escapes single quotes using the standard syntax + "''" => "'", + ]; + + /** + * {@inheritdoc} + */ + protected function _getPortableViewDefinition($view) + { + return new View($view['TABLE_NAME'], $view['VIEW_DEFINITION']); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableDefinition($table) + { + return array_shift($table); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableUserDefinition($user) + { + return [ + 'user' => $user['User'], + 'password' => $user['Password'], + ]; + } + + /** + * {@inheritdoc} + */ + 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; + } + if (strpos($v['index_type'], 'FULLTEXT') !== false) { + $v['flags'] = ['FULLTEXT']; + } elseif (strpos($v['index_type'], 'SPATIAL') !== false) { + $v['flags'] = ['SPATIAL']; + } + $v['length'] = isset($v['sub_part']) ? (int) $v['sub_part'] : null; + + $tableIndexes[$k] = $v; + } + + return parent::_getPortableTableIndexesList($tableIndexes, $tableName); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableDatabaseDefinition($database) + { + return $database['Database']; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableColumnDefinition($tableColumn) + { + $tableColumn = array_change_key_case($tableColumn, CASE_LOWER); + + $dbType = strtolower($tableColumn['type']); + $dbType = strtok($dbType, '(), '); + assert(is_string($dbType)); + + $length = $tableColumn['length'] ?? strtok('(), '); + + $fixed = null; + + if (! isset($tableColumn['name'])) { + $tableColumn['name'] = ''; + } + + $scale = null; + $precision = null; + + $type = $this->_platform->getDoctrineTypeMapping($dbType); + + // In cases where not connected to a database DESCRIBE $table does not return 'Comment' + if (isset($tableColumn['comment'])) { + $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); + $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); + } + + switch ($dbType) { + case 'char': + case 'binary': + $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 'tinytext': + $length = MySqlPlatform::LENGTH_LIMIT_TINYTEXT; + break; + case 'text': + $length = MySqlPlatform::LENGTH_LIMIT_TEXT; + break; + case 'mediumtext': + $length = MySqlPlatform::LENGTH_LIMIT_MEDIUMTEXT; + break; + case 'tinyblob': + $length = MySqlPlatform::LENGTH_LIMIT_TINYBLOB; + break; + case 'blob': + $length = MySqlPlatform::LENGTH_LIMIT_BLOB; + break; + case 'mediumblob': + $length = MySqlPlatform::LENGTH_LIMIT_MEDIUMBLOB; + break; + case 'tinyint': + case 'smallint': + case 'mediumint': + case 'int': + case 'integer': + case 'bigint': + case 'year': + $length = null; + break; + } + + if ($this->_platform instanceof MariaDb1027Platform) { + $columnDefault = $this->getMariaDb1027ColumnDefault($this->_platform, $tableColumn['default']); + } else { + $columnDefault = $tableColumn['default']; + } + + $options = [ + 'length' => $length !== null ? (int) $length : null, + 'unsigned' => strpos($tableColumn['type'], 'unsigned') !== false, + 'fixed' => (bool) $fixed, + 'default' => $columnDefault, + 'notnull' => $tableColumn['null'] !== 'YES', + 'scale' => null, + 'precision' => null, + 'autoincrement' => strpos($tableColumn['extra'], 'auto_increment') !== false, + 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== '' + ? $tableColumn['comment'] + : null, + ]; + + if ($scale !== null && $precision !== null) { + $options['scale'] = (int) $scale; + $options['precision'] = (int) $precision; + } + + $column = new Column($tableColumn['field'], Type::getType($type), $options); + + if (isset($tableColumn['characterset'])) { + $column->setPlatformOption('charset', $tableColumn['characterset']); + } + if (isset($tableColumn['collation'])) { + $column->setPlatformOption('collation', $tableColumn['collation']); + } + + return $column; + } + + /** + * Return Doctrine/Mysql-compatible column default values for MariaDB 10.2.7+ servers. + * + * - Since MariaDb 10.2.7 column defaults stored in information_schema are now quoted + * to distinguish them from expressions (see MDEV-10134). + * - CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE are stored in information_schema + * as current_timestamp(), currdate(), currtime() + * - Quoted 'NULL' is not enforced by Maria, it is technically possible to have + * null in some circumstances (see https://jira.mariadb.org/browse/MDEV-14053) + * - \' is always stored as '' in information_schema (normalized) + * + * @link https://mariadb.com/kb/en/library/information-schema-columns-table/ + * @link https://jira.mariadb.org/browse/MDEV-13132 + * + * @param string|null $columnDefault default value as stored in information_schema for MariaDB >= 10.2.7 + */ + private function getMariaDb1027ColumnDefault(MariaDb1027Platform $platform, ?string $columnDefault) : ?string + { + if ($columnDefault === 'NULL' || $columnDefault === null) { + return null; + } + + if (preg_match('/^\'(.*)\'$/', $columnDefault, $matches)) { + return strtr($matches[1], self::MARIADB_ESCAPE_SEQUENCES); + } + + switch ($columnDefault) { + case 'current_timestamp()': + return $platform->getCurrentTimestampSQL(); + case 'curdate()': + return $platform->getCurrentDateSQL(); + case 'curtime()': + return $platform->getCurrentTimeSQL(); + } + + return $columnDefault; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableForeignKeysList($tableForeignKeys) + { + $list = []; + foreach ($tableForeignKeys as $value) { + $value = array_change_key_case($value, CASE_LOWER); + if (! isset($list[$value['constraint_name']])) { + if (! isset($value['delete_rule']) || $value['delete_rule'] === 'RESTRICT') { + $value['delete_rule'] = null; + } + if (! isset($value['update_rule']) || $value['update_rule'] === 'RESTRICT') { + $value['update_rule'] = null; + } + + $list[$value['constraint_name']] = [ + 'name' => $value['constraint_name'], + 'local' => [], + 'foreign' => [], + 'foreignTable' => $value['referenced_table_name'], + 'onDelete' => $value['delete_rule'], + 'onUpdate' => $value['update_rule'], + ]; + } + $list[$value['constraint_name']]['local'][] = $value['column_name']; + $list[$value['constraint_name']]['foreign'][] = $value['referenced_column_name']; + } + + $result = []; + foreach ($list as $constraint) { + $result[] = new ForeignKeyConstraint( + array_values($constraint['local']), + $constraint['foreignTable'], + array_values($constraint['foreign']), + $constraint['name'], + [ + 'onDelete' => $constraint['onDelete'], + 'onUpdate' => $constraint['onUpdate'], + ] + ); + } + + return $result; + } + + public function listTableDetails($tableName) + { + $table = parent::listTableDetails($tableName); + + /** @var MySqlPlatform $platform */ + $platform = $this->_platform; + $sql = $platform->getListTableMetadataSQL($tableName); + + $tableOptions = $this->_conn->fetchAssoc($sql); + + if ($tableOptions === false) { + return $table; + } + + $table->addOption('engine', $tableOptions['ENGINE']); + + if ($tableOptions['TABLE_COLLATION'] !== null) { + $table->addOption('collation', $tableOptions['TABLE_COLLATION']); + } + + if ($tableOptions['AUTO_INCREMENT'] !== null) { + $table->addOption('autoincrement', $tableOptions['AUTO_INCREMENT']); + } + + $table->addOption('comment', $tableOptions['TABLE_COMMENT']); + $table->addOption('create_options', $this->parseCreateOptions($tableOptions['CREATE_OPTIONS'])); + + return $table; + } + + /** + * @return string[]|true[] + */ + private function parseCreateOptions(?string $string) : array + { + $options = []; + + if ($string === null || $string === '') { + return $options; + } + + foreach (explode(' ', $string) as $pair) { + $parts = explode('=', $pair, 2); + + $options[$parts[0]] = $parts[1] ?? true; + } + + return $options; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php new file mode 100644 index 0000000..afe610d --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php @@ -0,0 +1,406 @@ +getPrevious(); + assert($exception instanceof Throwable); + + if (! $exception instanceof DriverException) { + throw $exception; + } + + // If we have a error code 1940 (ORA-01940), the drop database operation failed + // because of active connections on the database. + // To force dropping the database, we first have to close all active connections + // on that database and issue the drop database operation again. + if ($exception->getErrorCode() !== 1940) { + throw $exception; + } + + $this->killUserSessions($database); + + parent::dropDatabase($database); + } + } + + /** + * {@inheritdoc} + */ + protected function _getPortableViewDefinition($view) + { + $view = array_change_key_case($view, CASE_LOWER); + + return new View($this->getQuotedIdentifierName($view['view_name']), $view['text']); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableUserDefinition($user) + { + $user = array_change_key_case($user, CASE_LOWER); + + return [ + 'user' => $user['username'], + ]; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableDefinition($table) + { + $table = array_change_key_case($table, CASE_LOWER); + + return $this->getQuotedIdentifierName($table['table_name']); + } + + /** + * {@inheritdoc} + * + * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html + */ + protected function _getPortableTableIndexesList($tableIndexes, $tableName = null) + { + $indexBuffer = []; + foreach ($tableIndexes as $tableIndex) { + $tableIndex = array_change_key_case($tableIndex, CASE_LOWER); + + $keyName = strtolower($tableIndex['name']); + $buffer = []; + + 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']; + } + $buffer['key_name'] = $keyName; + $buffer['column_name'] = $this->getQuotedIdentifierName($tableIndex['column_name']); + $indexBuffer[] = $buffer; + } + + return parent::_getPortableTableIndexesList($indexBuffer, $tableName); + } + + /** + * {@inheritdoc} + */ + 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'; + } + } + + $unsigned = $fixed = $precision = $scale = $length = null; + + if (! isset($tableColumn['column_name'])) { + $tableColumn['column_name'] = ''; + } + + // Default values returned from database sometimes have trailing spaces. + $tableColumn['data_default'] = trim($tableColumn['data_default']); + + if ($tableColumn['data_default'] === '' || $tableColumn['data_default'] === 'NULL') { + $tableColumn['data_default'] = null; + } + + if ($tableColumn['data_default'] !== null) { + // Default values returned from database are represented as literal expressions + if (preg_match('/^\'(.*)\'$/s', $tableColumn['data_default'], $matches)) { + $tableColumn['data_default'] = str_replace("''", "'", $matches[1]); + } + } + + if ($tableColumn['data_precision'] !== null) { + $precision = (int) $tableColumn['data_precision']; + } + + if ($tableColumn['data_scale'] !== null) { + $scale = (int) $tableColumn['data_scale']; + } + + $type = $this->_platform->getDoctrineTypeMapping($dbType); + $type = $this->extractDoctrineTypeFromComment($tableColumn['comments'], $type); + $tableColumn['comments'] = $this->removeDoctrineTypeFromComment($tableColumn['comments'], $type); + + switch ($dbType) { + case 'number': + if ($precision === 20 && $scale === 0) { + $type = 'bigint'; + } elseif ($precision === 5 && $scale === 0) { + $type = 'smallint'; + } elseif ($precision === 1 && $scale === 0) { + $type = 'boolean'; + } elseif ($scale > 0) { + $type = 'decimal'; + } + + break; + case 'varchar': + case 'varchar2': + case 'nvarchar2': + $length = $tableColumn['char_length']; + $fixed = false; + break; + case 'char': + case 'nchar': + $length = $tableColumn['char_length']; + $fixed = true; + break; + } + + $options = [ + 'notnull' => (bool) ($tableColumn['nullable'] === 'N'), + 'fixed' => (bool) $fixed, + 'unsigned' => (bool) $unsigned, + 'default' => $tableColumn['data_default'], + 'length' => $length, + 'precision' => $precision, + 'scale' => $scale, + 'comment' => isset($tableColumn['comments']) && $tableColumn['comments'] !== '' + ? $tableColumn['comments'] + : null, + ]; + + return new Column($this->getQuotedIdentifierName($tableColumn['column_name']), Type::getType($type), $options); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableForeignKeysList($tableForeignKeys) + { + $list = []; + foreach ($tableForeignKeys as $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']] = [ + 'name' => $this->getQuotedIdentifierName($value['constraint_name']), + 'local' => [], + 'foreign' => [], + 'foreignTable' => $value['references_table'], + 'onDelete' => $value['delete_rule'], + ]; + } + + $localColumn = $this->getQuotedIdentifierName($value['local_column']); + $foreignColumn = $this->getQuotedIdentifierName($value['foreign_column']); + + $list[$value['constraint_name']]['local'][$value['position']] = $localColumn; + $list[$value['constraint_name']]['foreign'][$value['position']] = $foreignColumn; + } + + $result = []; + foreach ($list as $constraint) { + $result[] = new ForeignKeyConstraint( + array_values($constraint['local']), + $this->getQuotedIdentifierName($constraint['foreignTable']), + array_values($constraint['foreign']), + $this->getQuotedIdentifierName($constraint['name']), + ['onDelete' => $constraint['onDelete']] + ); + } + + return $result; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableSequenceDefinition($sequence) + { + $sequence = array_change_key_case($sequence, CASE_LOWER); + + return new Sequence( + $this->getQuotedIdentifierName($sequence['sequence_name']), + (int) $sequence['increment_by'], + (int) $sequence['min_value'] + ); + } + + /** + * {@inheritdoc} + * + * @deprecated + */ + protected function _getPortableFunctionDefinition($function) + { + $function = array_change_key_case($function, CASE_LOWER); + + return $function['name']; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableDatabaseDefinition($database) + { + $database = array_change_key_case($database, CASE_LOWER); + + return $database['username']; + } + + /** + * {@inheritdoc} + * + * Calling this method without an argument or by passing NULL is deprecated. + */ + public function createDatabase($database = null) + { + if ($database === null) { + $database = $this->_conn->getDatabase(); + } + + $params = $this->_conn->getParams(); + $username = $database; + $password = $params['password']; + + $query = 'CREATE USER ' . $username . ' IDENTIFIED BY ' . $password; + $this->_conn->executeUpdate($query); + + $query = 'GRANT DBA TO ' . $username; + $this->_conn->executeUpdate($query); + } + + /** + * @param string $table + * + * @return bool + */ + public function dropAutoincrement($table) + { + assert($this->_platform instanceof OraclePlatform); + + $sql = $this->_platform->getDropAutoincrementSql($table); + foreach ($sql as $query) { + $this->_conn->executeUpdate($query); + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function dropTable($name) + { + $this->tryMethod('dropAutoincrement', $name); + + parent::dropTable($name); + } + + /** + * Returns the quoted representation of the given identifier name. + * + * Quotes non-uppercase identifiers explicitly to preserve case + * and thus make references to the particular identifier work. + * + * @param string $identifier The identifier to quote. + * + * @return string The quoted identifier. + */ + private function getQuotedIdentifierName($identifier) + { + if (preg_match('/[a-z]/', $identifier)) { + return $this->_platform->quoteIdentifier($identifier); + } + + return $identifier; + } + + /** + * Kills sessions connected with the given user. + * + * This is useful to force DROP USER operations which could fail because of active user sessions. + * + * @param string $user The name of the user to kill sessions for. + * + * @return void + */ + private function killUserSessions($user) + { + $sql = <<_conn->fetchAll($sql, [strtoupper($user)]); + + foreach ($activeUserSessions as $activeUserSession) { + $activeUserSession = array_change_key_case($activeUserSession, CASE_LOWER); + + $this->_execSql( + sprintf( + "ALTER SYSTEM KILL SESSION '%s, %s' IMMEDIATE", + $activeUserSession['sid'], + $activeUserSession['serial#'] + ) + ); + } + } + + public function listTableDetails($tableName) : Table + { + $table = parent::listTableDetails($tableName); + + /** @var OraclePlatform $platform */ + $platform = $this->_platform; + $sql = $platform->getListTableCommentsSQL($tableName); + + $tableOptions = $this->_conn->fetchAssoc($sql); + $table->addOption('comment', $tableOptions['COMMENTS']); + + return $table; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php new file mode 100644 index 0000000..e9608e7 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php @@ -0,0 +1,507 @@ +_conn->executeQuery("SELECT nspname FROM pg_namespace WHERE nspname !~ '^pg_.*' AND nspname != 'information_schema'"); + + return $statement->fetchAll(FetchMode::COLUMN); + } + + /** + * Returns an array of schema search paths. + * + * This is a PostgreSQL only function. + * + * @return string[] + */ + public function getSchemaSearchPaths() + { + $params = $this->_conn->getParams(); + $schema = explode(',', $this->_conn->fetchColumn('SHOW search_path')); + + if (isset($params['user'])) { + $schema = str_replace('"$user"', $params['user'], $schema); + } + + return array_map('trim', $schema); + } + + /** + * Gets names of all existing schemas in the current users search path. + * + * This is a PostgreSQL only function. + * + * @return string[] + */ + public function getExistingSchemaSearchPaths() + { + if ($this->existingSchemaPaths === null) { + $this->determineExistingSchemaSearchPaths(); + } + + return $this->existingSchemaPaths; + } + + /** + * Sets or resets the order of the existing schemas in the current search path of the user. + * + * This is a PostgreSQL only function. + * + * @return void + */ + public function determineExistingSchemaSearchPaths() + { + $names = $this->getSchemaNames(); + $paths = $this->getSchemaSearchPaths(); + + $this->existingSchemaPaths = array_filter($paths, static function ($v) use ($names) { + return in_array($v, $names); + }); + } + + /** + * {@inheritdoc} + */ + public function dropDatabase($database) + { + try { + parent::dropDatabase($database); + } catch (DriverException $exception) { + // If we have a SQLSTATE 55006, the drop database operation failed + // because of active connections on the database. + // To force dropping the database, we first have to close all active connections + // on that database and issue the drop database operation again. + if ($exception->getSQLState() !== '55006') { + throw $exception; + } + + assert($this->_platform instanceof PostgreSqlPlatform); + + $this->_execSql( + [ + $this->_platform->getDisallowDatabaseConnectionsSQL($database), + $this->_platform->getCloseActiveDatabaseConnectionsSQL($database), + ] + ); + + parent::dropDatabase($database); + } + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableForeignKeyDefinition($tableForeignKey) + { + $onUpdate = null; + $onDelete = null; + $localColumns = []; + $foreignColumns = []; + $foreignTable = null; + + if (preg_match('(ON UPDATE ([a-zA-Z0-9]+( (NULL|ACTION|DEFAULT))?))', $tableForeignKey['condef'], $match)) { + $onUpdate = $match[1]; + } + if (preg_match('(ON DELETE ([a-zA-Z0-9]+( (NULL|ACTION|DEFAULT))?))', $tableForeignKey['condef'], $match)) { + $onDelete = $match[1]; + } + + if (preg_match('/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)/', $tableForeignKey['condef'], $values)) { + // PostgreSQL returns identifiers that are keywords with quotes, we need them later, don't get + // the idea to trim them here. + $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'], + ['onUpdate' => $onUpdate, 'onDelete' => $onDelete] + ); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTriggerDefinition($trigger) + { + return $trigger['trigger_name']; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableViewDefinition($view) + { + return new View($view['schemaname'] . '.' . $view['viewname'], $view['definition']); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableUserDefinition($user) + { + return [ + 'user' => $user['usename'], + 'password' => $user['passwd'], + ]; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableDefinition($table) + { + $schemas = $this->getExistingSchemaSearchPaths(); + $firstSchema = array_shift($schemas); + + if ($table['schema_name'] === $firstSchema) { + return $table['table_name']; + } + + return $table['schema_name'] . '.' . $table['table_name']; + } + + /** + * {@inheritdoc} + * + * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html + */ + protected function _getPortableTableIndexesList($tableIndexes, $tableName = null) + { + $buffer = []; + foreach ($tableIndexes as $row) { + $colNumbers = array_map('intval', explode(' ', $row['indkey'])); + $columnNameSql = sprintf( + 'SELECT attnum, attname FROM pg_attribute WHERE attrelid=%d AND attnum IN (%s) ORDER BY attnum ASC', + $row['indrelid'], + implode(' ,', $colNumbers) + ); + + $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']) { + continue; + } + + $buffer[] = [ + 'key_name' => $row['relname'], + 'column_name' => trim($colRow['attname']), + 'non_unique' => ! $row['indisunique'], + 'primary' => $row['indisprimary'], + 'where' => $row['where'], + ]; + } + } + } + + return parent::_getPortableTableIndexesList($buffer, $tableName); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableDatabaseDefinition($database) + { + return $database['datname']; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableSequencesList($sequences) + { + $sequenceDefinitions = []; + + foreach ($sequences as $sequence) { + if ($sequence['schemaname'] !== 'public') { + $sequenceName = $sequence['schemaname'] . '.' . $sequence['relname']; + } else { + $sequenceName = $sequence['relname']; + } + + $sequenceDefinitions[$sequenceName] = $sequence; + } + + $list = []; + + foreach ($this->filterAssetNames(array_keys($sequenceDefinitions)) as $sequenceName) { + $list[] = $this->_getPortableSequenceDefinition($sequenceDefinitions[$sequenceName]); + } + + return $list; + } + + /** + * {@inheritdoc} + */ + protected function getPortableNamespaceDefinition(array $namespace) + { + return $namespace['nspname']; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableSequenceDefinition($sequence) + { + if ($sequence['schemaname'] !== 'public') { + $sequenceName = $sequence['schemaname'] . '.' . $sequence['relname']; + } else { + $sequenceName = $sequence['relname']; + } + + if (! isset($sequence['increment_by'], $sequence['min_value'])) { + /** @var string[] $data */ + $data = $this->_conn->fetchAssoc('SELECT min_value, increment_by FROM ' . $this->_platform->quoteIdentifier($sequenceName)); + + $sequence += $data; + } + + return new Sequence($sequenceName, (int) $sequence['increment_by'], (int) $sequence['min_value']); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableColumnDefinition($tableColumn) + { + $tableColumn = array_change_key_case($tableColumn, CASE_LOWER); + + if (strtolower($tableColumn['type']) === 'varchar' || strtolower($tableColumn['type']) === 'bpchar') { + // get length from varchar definition + $length = preg_replace('~.*\(([0-9]*)\).*~', '$1', $tableColumn['complete_type']); + $tableColumn['length'] = $length; + } + + $matches = []; + + $autoincrement = false; + if (preg_match("/^nextval\('(.*)'(::.*)?\)$/", $tableColumn['default'], $matches)) { + $tableColumn['sequence'] = $matches[1]; + $tableColumn['default'] = null; + $autoincrement = true; + } + + if (preg_match("/^['(](.*)[')]::/", $tableColumn['default'], $matches)) { + $tableColumn['default'] = $matches[1]; + } elseif (preg_match('/^NULL::/', $tableColumn['default'])) { + $tableColumn['default'] = null; + } + + $length = $tableColumn['length'] ?? null; + if ($length === '-1' && isset($tableColumn['atttypmod'])) { + $length = $tableColumn['atttypmod'] - 4; + } + if ((int) $length <= 0) { + $length = null; + } + $fixed = null; + + if (! isset($tableColumn['name'])) { + $tableColumn['name'] = ''; + } + + $precision = null; + $scale = null; + $jsonb = null; + + $dbType = strtolower($tableColumn['type']); + if (strlen($tableColumn['domain_type']) && ! $this->_platform->hasDoctrineTypeMappingFor($tableColumn['type'])) { + $dbType = strtolower($tableColumn['domain_type']); + $tableColumn['complete_type'] = $tableColumn['domain_complete_type']; + } + + $type = $this->_platform->getDoctrineTypeMapping($dbType); + $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); + $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); + + switch ($dbType) { + case 'smallint': + case 'int2': + $tableColumn['default'] = $this->fixVersion94NegativeNumericDefaultValue($tableColumn['default']); + $length = null; + break; + case 'int': + case 'int4': + case 'integer': + $tableColumn['default'] = $this->fixVersion94NegativeNumericDefaultValue($tableColumn['default']); + $length = null; + break; + case 'bigint': + case 'int8': + $tableColumn['default'] = $this->fixVersion94NegativeNumericDefaultValue($tableColumn['default']); + $length = null; + break; + case 'bool': + case 'boolean': + if ($tableColumn['default'] === 'true') { + $tableColumn['default'] = true; + } + + if ($tableColumn['default'] === 'false') { + $tableColumn['default'] = false; + } + + $length = null; + break; + case 'text': + case '_varchar': + case 'varchar': + $tableColumn['default'] = $this->parseDefaultExpression($tableColumn['default']); + $fixed = false; + break; + case 'interval': + $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': + $tableColumn['default'] = $this->fixVersion94NegativeNumericDefaultValue($tableColumn['default']); + + 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; + + // PostgreSQL 9.4+ only + case 'jsonb': + $jsonb = true; + break; + } + + if ($tableColumn['default'] && preg_match("('([^']+)'::)", $tableColumn['default'], $match)) { + $tableColumn['default'] = $match[1]; + } + + $options = [ + 'length' => $length, + 'notnull' => (bool) $tableColumn['isnotnull'], + 'default' => $tableColumn['default'], + 'precision' => $precision, + 'scale' => $scale, + 'fixed' => $fixed, + 'unsigned' => false, + 'autoincrement' => $autoincrement, + 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== '' + ? $tableColumn['comment'] + : null, + ]; + + $column = new Column($tableColumn['field'], Type::getType($type), $options); + + if (isset($tableColumn['collation']) && ! empty($tableColumn['collation'])) { + $column->setPlatformOption('collation', $tableColumn['collation']); + } + + if (in_array($column->getType()->getName(), [Types::JSON_ARRAY, Types::JSON], true)) { + $column->setPlatformOption('jsonb', $jsonb); + } + + return $column; + } + + /** + * PostgreSQL 9.4 puts parentheses around negative numeric default values that need to be stripped eventually. + * + * @param mixed $defaultValue + * + * @return mixed + */ + private function fixVersion94NegativeNumericDefaultValue($defaultValue) + { + if (strpos($defaultValue, '(') === 0) { + return trim($defaultValue, '()'); + } + + return $defaultValue; + } + + /** + * Parses a default value expression as given by PostgreSQL + */ + private function parseDefaultExpression(?string $default) : ?string + { + if ($default === null) { + return $default; + } + + return str_replace("''", "'", $default); + } + + public function listTableDetails($tableName) : Table + { + $table = parent::listTableDetails($tableName); + + /** @var PostgreSqlPlatform $platform */ + $platform = $this->_platform; + $sql = $platform->getListTableMetadataSQL($tableName); + + $tableOptions = $this->_conn->fetchAssoc($sql); + + $table->addOption('comment', $tableOptions['table_comment']); + + return $table; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLAnywhereSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLAnywhereSchemaManager.php new file mode 100644 index 0000000..c169a6e --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLAnywhereSchemaManager.php @@ -0,0 +1,231 @@ +startDatabase($database); + } + + /** + * {@inheritdoc} + * + * Tries stopping a database before dropping + * as SQL Anywhere needs a database to be stopped + * before it can be dropped. + * + * @see stopDatabase + */ + public function dropDatabase($database) + { + $this->tryMethod('stopDatabase', $database); + parent::dropDatabase($database); + } + + /** + * Starts a database. + * + * @param string $database The name of the database to start. + */ + public function startDatabase($database) + { + assert($this->_platform instanceof SQLAnywherePlatform); + $this->_execSql($this->_platform->getStartDatabaseSQL($database)); + } + + /** + * Stops a database. + * + * @param string $database The name of the database to stop. + */ + public function stopDatabase($database) + { + assert($this->_platform instanceof SQLAnywherePlatform); + $this->_execSql($this->_platform->getStopDatabaseSQL($database)); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableDatabaseDefinition($database) + { + return $database['name']; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableSequenceDefinition($sequence) + { + return new Sequence($sequence['sequence_name'], $sequence['increment_by'], $sequence['start_with']); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableColumnDefinition($tableColumn) + { + $type = $this->_platform->getDoctrineTypeMapping($tableColumn['type']); + $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); + $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); + $precision = null; + $scale = null; + $fixed = false; + $default = null; + + if ($tableColumn['default'] !== null) { + // Strip quotes from default value. + $default = preg_replace(["/^'(.*)'$/", "/''/"], ['$1', "'"], $tableColumn['default']); + + if ($default === 'autoincrement') { + $default = null; + } + } + + switch ($tableColumn['type']) { + case 'binary': + case 'char': + case 'nchar': + $fixed = true; + } + + switch ($type) { + case 'decimal': + case 'float': + $precision = $tableColumn['length']; + $scale = $tableColumn['scale']; + } + + return new Column( + $tableColumn['column_name'], + Type::getType($type), + [ + 'length' => $type === 'string' ? $tableColumn['length'] : null, + 'precision' => $precision, + 'scale' => $scale, + 'unsigned' => (bool) $tableColumn['unsigned'], + 'fixed' => $fixed, + 'notnull' => (bool) $tableColumn['notnull'], + 'default' => $default, + 'autoincrement' => (bool) $tableColumn['autoincrement'], + 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== '' + ? $tableColumn['comment'] + : null, + ] + ); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableDefinition($table) + { + return $table['table_name']; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableForeignKeyDefinition($tableForeignKey) + { + return new ForeignKeyConstraint( + $tableForeignKey['local_columns'], + $tableForeignKey['foreign_table'], + $tableForeignKey['foreign_columns'], + $tableForeignKey['name'], + $tableForeignKey['options'] + ); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableForeignKeysList($tableForeignKeys) + { + $foreignKeys = []; + + foreach ($tableForeignKeys as $tableForeignKey) { + if (! isset($foreignKeys[$tableForeignKey['index_name']])) { + $foreignKeys[$tableForeignKey['index_name']] = [ + 'local_columns' => [$tableForeignKey['local_column']], + 'foreign_table' => $tableForeignKey['foreign_table'], + 'foreign_columns' => [$tableForeignKey['foreign_column']], + 'name' => $tableForeignKey['index_name'], + 'options' => [ + 'notnull' => $tableForeignKey['notnull'], + 'match' => $tableForeignKey['match'], + 'onUpdate' => $tableForeignKey['on_update'], + 'onDelete' => $tableForeignKey['on_delete'], + 'check_on_commit' => $tableForeignKey['check_on_commit'], + 'clustered' => $tableForeignKey['clustered'], + 'for_olap_workload' => $tableForeignKey['for_olap_workload'], + ], + ]; + } else { + $foreignKeys[$tableForeignKey['index_name']]['local_columns'][] = $tableForeignKey['local_column']; + $foreignKeys[$tableForeignKey['index_name']]['foreign_columns'][] = $tableForeignKey['foreign_column']; + } + } + + return parent::_getPortableTableForeignKeysList($foreignKeys); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null) + { + foreach ($tableIndexRows as &$tableIndex) { + $tableIndex['primary'] = (bool) $tableIndex['primary']; + $tableIndex['flags'] = []; + + if ($tableIndex['clustered']) { + $tableIndex['flags'][] = 'clustered'; + } + + if ($tableIndex['with_nulls_not_distinct']) { + $tableIndex['flags'][] = 'with_nulls_not_distinct'; + } + + if (! $tableIndex['for_olap_workload']) { + continue; + } + + $tableIndex['flags'][] = 'for_olap_workload'; + } + + return parent::_getPortableTableIndexesList($tableIndexRows, $tableName); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableViewDefinition($view) + { + $definition = preg_replace('/^.*\s+as\s+SELECT(.*)/i', 'SELECT$1', $view['view_def']); + assert(is_string($definition)); + + return new View($view['table_name'], $definition); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php new file mode 100644 index 0000000..35cdc45 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php @@ -0,0 +1,349 @@ +getPrevious(); + assert($exception instanceof Throwable); + + if (! $exception instanceof DriverException) { + throw $exception; + } + + // If we have a error code 3702, the drop database operation failed + // because of active connections on the database. + // To force dropping the database, we first have to close all active connections + // on that database and issue the drop database operation again. + if ($exception->getErrorCode() !== 3702) { + throw $exception; + } + + $this->closeActiveDatabaseConnections($database); + + parent::dropDatabase($database); + } + } + + /** + * {@inheritdoc} + */ + protected function _getPortableSequenceDefinition($sequence) + { + return new Sequence($sequence['name'], (int) $sequence['increment'], (int) $sequence['start_value']); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableColumnDefinition($tableColumn) + { + $dbType = strtok($tableColumn['type'], '(), '); + assert(is_string($dbType)); + + $fixed = null; + $length = (int) $tableColumn['length']; + $default = $tableColumn['default']; + + if (! isset($tableColumn['name'])) { + $tableColumn['name'] = ''; + } + + if ($default !== null) { + $default = $this->parseDefaultExpression($default); + } + + switch ($dbType) { + case 'nchar': + case 'nvarchar': + case 'ntext': + // Unicode data requires 2 bytes per character + $length /= 2; + break; + case 'varchar': + // TEXT type is returned as VARCHAR(MAX) with a length of -1 + if ($length === -1) { + $dbType = 'text'; + } + break; + } + + if ($dbType === 'char' || $dbType === 'nchar' || $dbType === 'binary') { + $fixed = true; + } + + $type = $this->_platform->getDoctrineTypeMapping($dbType); + $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); + $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); + + $options = [ + 'length' => $length === 0 || ! in_array($type, ['text', 'string']) ? null : $length, + 'unsigned' => false, + 'fixed' => (bool) $fixed, + 'default' => $default, + 'notnull' => (bool) $tableColumn['notnull'], + 'scale' => $tableColumn['scale'], + 'precision' => $tableColumn['precision'], + 'autoincrement' => (bool) $tableColumn['autoincrement'], + 'comment' => $tableColumn['comment'] !== '' ? $tableColumn['comment'] : null, + ]; + + $column = new Column($tableColumn['name'], Type::getType($type), $options); + + if (isset($tableColumn['collation']) && $tableColumn['collation'] !== 'NULL') { + $column->setPlatformOption('collation', $tableColumn['collation']); + } + + return $column; + } + + private function parseDefaultExpression(string $value) : ?string + { + while (preg_match('/^\((.*)\)$/s', $value, $matches)) { + $value = $matches[1]; + } + + if ($value === 'NULL') { + return null; + } + + if (preg_match('/^\'(.*)\'$/s', $value, $matches)) { + $value = str_replace("''", "'", $matches[1]); + } + + if ($value === 'getdate()') { + return $this->_platform->getCurrentTimestampSQL(); + } + + return $value; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableForeignKeysList($tableForeignKeys) + { + $foreignKeys = []; + + foreach ($tableForeignKeys as $tableForeignKey) { + if (! isset($foreignKeys[$tableForeignKey['ForeignKey']])) { + $foreignKeys[$tableForeignKey['ForeignKey']] = [ + 'local_columns' => [$tableForeignKey['ColumnName']], + 'foreign_table' => $tableForeignKey['ReferenceTableName'], + 'foreign_columns' => [$tableForeignKey['ReferenceColumnName']], + 'name' => $tableForeignKey['ForeignKey'], + 'options' => [ + 'onUpdate' => str_replace('_', ' ', $tableForeignKey['update_referential_action_desc']), + 'onDelete' => str_replace('_', ' ', $tableForeignKey['delete_referential_action_desc']), + ], + ]; + } else { + $foreignKeys[$tableForeignKey['ForeignKey']]['local_columns'][] = $tableForeignKey['ColumnName']; + $foreignKeys[$tableForeignKey['ForeignKey']]['foreign_columns'][] = $tableForeignKey['ReferenceColumnName']; + } + } + + return parent::_getPortableTableForeignKeysList($foreignKeys); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null) + { + foreach ($tableIndexRows as &$tableIndex) { + $tableIndex['non_unique'] = (bool) $tableIndex['non_unique']; + $tableIndex['primary'] = (bool) $tableIndex['primary']; + $tableIndex['flags'] = $tableIndex['flags'] ? [$tableIndex['flags']] : null; + } + + return parent::_getPortableTableIndexesList($tableIndexRows, $tableName); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableForeignKeyDefinition($tableForeignKey) + { + return new ForeignKeyConstraint( + $tableForeignKey['local_columns'], + $tableForeignKey['foreign_table'], + $tableForeignKey['foreign_columns'], + $tableForeignKey['name'], + $tableForeignKey['options'] + ); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableDefinition($table) + { + if (isset($table['schema_name']) && $table['schema_name'] !== 'dbo') { + return $table['schema_name'] . '.' . $table['name']; + } + + return $table['name']; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableDatabaseDefinition($database) + { + return $database['name']; + } + + /** + * {@inheritdoc} + */ + protected function getPortableNamespaceDefinition(array $namespace) + { + return $namespace['name']; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableViewDefinition($view) + { + // @todo + return new View($view['name'], ''); + } + + /** + * {@inheritdoc} + */ + public function listTableIndexes($table) + { + $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); + + try { + $tableIndexes = $this->_conn->fetchAll($sql); + } catch (PDOException $e) { + if ($e->getCode() === 'IMSSP') { + return []; + } + + throw $e; + } catch (DBALException $e) { + if (strpos($e->getMessage(), 'SQLSTATE [01000, 15472]') === 0) { + return []; + } + + throw $e; + } + + return $this->_getPortableTableIndexesList($tableIndexes, $table); + } + + /** + * {@inheritdoc} + */ + public function alterTable(TableDiff $tableDiff) + { + if (count($tableDiff->removedColumns) > 0) { + foreach ($tableDiff->removedColumns as $col) { + $columnConstraintSql = $this->getColumnConstraintSQL($tableDiff->name, $col->getName()); + foreach ($this->_conn->fetchAll($columnConstraintSql) as $constraint) { + $this->_conn->exec( + sprintf( + 'ALTER TABLE %s DROP CONSTRAINT %s', + $tableDiff->name, + $constraint['Name'] + ) + ); + } + } + } + + parent::alterTable($tableDiff); + } + + /** + * Returns the SQL to retrieve the constraints for a given column. + * + * @param string $table + * @param string $column + * + * @return string + */ + private function getColumnConstraintSQL($table, $column) + { + return "SELECT SysObjects.[Name] + FROM SysObjects INNER JOIN (SELECT [Name],[ID] FROM SysObjects WHERE XType = 'U') AS Tab + ON Tab.[ID] = Sysobjects.[Parent_Obj] + INNER JOIN sys.default_constraints DefCons ON DefCons.[object_id] = Sysobjects.[ID] + INNER JOIN SysColumns Col ON Col.[ColID] = DefCons.[parent_column_id] AND Col.[ID] = Tab.[ID] + WHERE Col.[Name] = " . $this->_conn->quote($column) . ' AND Tab.[Name] = ' . $this->_conn->quote($table) . ' + ORDER BY Col.[Name]'; + } + + /** + * Closes currently active connections on the given database. + * + * This is useful to force DROP DATABASE operations which could fail because of active connections. + * + * @param string $database The name of the database to close currently active connections for. + * + * @return void + */ + private function closeActiveDatabaseConnections($database) + { + $database = new Identifier($database); + + $this->_execSql( + sprintf( + 'ALTER DATABASE %s SET SINGLE_USER WITH ROLLBACK IMMEDIATE', + $database->getQuotedName($this->_platform) + ) + ); + } + + /** + * @param string $tableName + */ + public function listTableDetails($tableName) : Table + { + $table = parent::listTableDetails($tableName); + + /** @var SQLServerPlatform $platform */ + $platform = $this->_platform; + $sql = $platform->getListTableMetadataSQL($tableName); + + $tableOptions = $this->_conn->fetchAssoc($sql); + + if ($tableOptions !== false) { + $table->addOption('comment', $tableOptions['table_comment']); + } + + return $table; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Schema.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Schema.php new file mode 100644 index 0000000..5d74665 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Schema.php @@ -0,0 +1,475 @@ +_schemaConfig = $schemaConfig; + $this->_setName($schemaConfig->getName() ?: 'public'); + + foreach ($namespaces as $namespace) { + $this->createNamespace($namespace); + } + + foreach ($tables as $table) { + $this->_addTable($table); + } + + foreach ($sequences as $sequence) { + $this->_addSequence($sequence); + } + } + + /** + * @return bool + */ + public function hasExplicitForeignKeyIndexes() + { + return $this->_schemaConfig->hasExplicitForeignKeyIndexes(); + } + + /** + * @return void + * + * @throws SchemaException + */ + protected function _addTable(Table $table) + { + $namespaceName = $table->getNamespaceName(); + $tableName = $table->getFullQualifiedName($this->getName()); + + if (isset($this->_tables[$tableName])) { + throw SchemaException::tableAlreadyExists($tableName); + } + + if ($namespaceName !== null + && ! $table->isInDefaultNamespace($this->getName()) + && ! $this->hasNamespace($namespaceName)) { + $this->createNamespace($namespaceName); + } + + $this->_tables[$tableName] = $table; + $table->setSchemaConfig($this->_schemaConfig); + } + + /** + * @return void + * + * @throws SchemaException + */ + protected function _addSequence(Sequence $sequence) + { + $namespaceName = $sequence->getNamespaceName(); + $seqName = $sequence->getFullQualifiedName($this->getName()); + + if (isset($this->_sequences[$seqName])) { + throw SchemaException::sequenceAlreadyExists($seqName); + } + + if ($namespaceName !== null + && ! $sequence->isInDefaultNamespace($this->getName()) + && ! $this->hasNamespace($namespaceName)) { + $this->createNamespace($namespaceName); + } + + $this->_sequences[$seqName] = $sequence; + } + + /** + * Returns the namespaces of this schema. + * + * @return string[] A list of namespace names. + */ + public function getNamespaces() + { + return $this->namespaces; + } + + /** + * Gets all tables of this schema. + * + * @return Table[] + */ + public function getTables() + { + return $this->_tables; + } + + /** + * @param string $tableName + * + * @return Table + * + * @throws SchemaException + */ + public function getTable($tableName) + { + $tableName = $this->getFullQualifiedAssetName($tableName); + if (! isset($this->_tables[$tableName])) { + throw SchemaException::tableDoesNotExist($tableName); + } + + return $this->_tables[$tableName]; + } + + /** + * @param string $name + * + * @return string + */ + private function getFullQualifiedAssetName($name) + { + $name = $this->getUnquotedAssetName($name); + + if (strpos($name, '.') === false) { + $name = $this->getName() . '.' . $name; + } + + return strtolower($name); + } + + /** + * Returns the unquoted representation of a given asset name. + * + * @param string $assetName Quoted or unquoted representation of an asset name. + * + * @return string + */ + private function getUnquotedAssetName($assetName) + { + if ($this->isIdentifierQuoted($assetName)) { + return $this->trimQuotes($assetName); + } + + return $assetName; + } + + /** + * Does this schema have a namespace with the given name? + * + * @param string $namespaceName + * + * @return bool + */ + public function hasNamespace($namespaceName) + { + $namespaceName = strtolower($this->getUnquotedAssetName($namespaceName)); + + return isset($this->namespaces[$namespaceName]); + } + + /** + * Does this schema have a table with the given name? + * + * @param string $tableName + * + * @return bool + */ + public function hasTable($tableName) + { + $tableName = $this->getFullQualifiedAssetName($tableName); + + return isset($this->_tables[$tableName]); + } + + /** + * Gets all table names, prefixed with a schema name, even the default one if present. + * + * @return string[] + */ + public function getTableNames() + { + return array_keys($this->_tables); + } + + /** + * @param string $sequenceName + * + * @return bool + */ + public function hasSequence($sequenceName) + { + $sequenceName = $this->getFullQualifiedAssetName($sequenceName); + + return isset($this->_sequences[$sequenceName]); + } + + /** + * @param string $sequenceName + * + * @return Sequence + * + * @throws SchemaException + */ + public function getSequence($sequenceName) + { + $sequenceName = $this->getFullQualifiedAssetName($sequenceName); + if (! $this->hasSequence($sequenceName)) { + throw SchemaException::sequenceDoesNotExist($sequenceName); + } + + return $this->_sequences[$sequenceName]; + } + + /** + * @return Sequence[] + */ + public function getSequences() + { + return $this->_sequences; + } + + /** + * Creates a new namespace. + * + * @param string $namespaceName The name of the namespace to create. + * + * @return \Doctrine\DBAL\Schema\Schema This schema instance. + * + * @throws SchemaException + */ + public function createNamespace($namespaceName) + { + $unquotedNamespaceName = strtolower($this->getUnquotedAssetName($namespaceName)); + + if (isset($this->namespaces[$unquotedNamespaceName])) { + throw SchemaException::namespaceAlreadyExists($unquotedNamespaceName); + } + + $this->namespaces[$unquotedNamespaceName] = $namespaceName; + + return $this; + } + + /** + * Creates a new table. + * + * @param string $tableName + * + * @return Table + */ + public function createTable($tableName) + { + $table = new Table($tableName); + $this->_addTable($table); + + foreach ($this->_schemaConfig->getDefaultTableOptions() as $name => $value) { + $table->addOption($name, $value); + } + + return $table; + } + + /** + * Renames a table. + * + * @param string $oldTableName + * @param string $newTableName + * + * @return \Doctrine\DBAL\Schema\Schema + */ + public function renameTable($oldTableName, $newTableName) + { + $table = $this->getTable($oldTableName); + $table->_setName($newTableName); + + $this->dropTable($oldTableName); + $this->_addTable($table); + + return $this; + } + + /** + * Drops a table from the schema. + * + * @param string $tableName + * + * @return \Doctrine\DBAL\Schema\Schema + */ + public function dropTable($tableName) + { + $tableName = $this->getFullQualifiedAssetName($tableName); + $this->getTable($tableName); + unset($this->_tables[$tableName]); + + return $this; + } + + /** + * Creates 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 \Doctrine\DBAL\Schema\Schema + */ + public function dropSequence($sequenceName) + { + $sequenceName = $this->getFullQualifiedAssetName($sequenceName); + unset($this->_sequences[$sequenceName]); + + return $this; + } + + /** + * Returns an array of necessary SQL queries to create the schema on the given platform. + * + * @return string[] + */ + public function toSql(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. + * + * @return string[] + */ + public function toDropSql(AbstractPlatform $platform) + { + $dropSqlCollector = new DropSchemaSqlCollector($platform); + $this->visit($dropSqlCollector); + + return $dropSqlCollector->getQueries(); + } + + /** + * @return string[] + */ + public function getMigrateToSql(Schema $toSchema, AbstractPlatform $platform) + { + $comparator = new Comparator(); + $schemaDiff = $comparator->compare($this, $toSchema); + + return $schemaDiff->toSql($platform); + } + + /** + * @return string[] + */ + public function getMigrateFromSql(Schema $fromSchema, AbstractPlatform $platform) + { + $comparator = new Comparator(); + $schemaDiff = $comparator->compare($fromSchema, $this); + + return $schemaDiff->toSql($platform); + } + + /** + * @return void + */ + public function visit(Visitor $visitor) + { + $visitor->acceptSchema($this); + + if ($visitor instanceof NamespaceVisitor) { + foreach ($this->namespaces as $namespace) { + $visitor->acceptNamespace($namespace); + } + } + + 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; + } + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaConfig.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaConfig.php new file mode 100644 index 0000000..b8c3502 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaConfig.php @@ -0,0 +1,100 @@ +hasExplicitForeignKeyIndexes; + } + + /** + * @param bool $flag + * + * @return void + */ + public function setExplicitForeignKeyIndexes($flag) + { + $this->hasExplicitForeignKeyIndexes = (bool) $flag; + } + + /** + * @param int $length + * + * @return void + */ + public function setMaxIdentifierLength($length) + { + $this->maxIdentifierLength = (int) $length; + } + + /** + * @return int + */ + public function getMaxIdentifierLength() + { + return $this->maxIdentifierLength; + } + + /** + * Gets the default namespace of schema objects. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Sets the default namespace name of schema objects. + * + * @param string $name The value to set. + * + * @return void + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * Gets the default options that are passed to Table instances created with + * Schema#createTable(). + * + * @return mixed[] + */ + public function getDefaultTableOptions() + { + return $this->defaultTableOptions; + } + + /** + * @param mixed[] $defaultTableOptions + * + * @return void + */ + public function setDefaultTableOptions(array $defaultTableOptions) + { + $this->defaultTableOptions = $defaultTableOptions; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaDiff.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaDiff.php new file mode 100644 index 0000000..69bf125 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaDiff.php @@ -0,0 +1,168 @@ +newTables = $newTables; + $this->changedTables = $changedTables; + $this->removedTables = $removedTables; + $this->fromSchema = $fromSchema; + } + + /** + * 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. + * + * @return string[] + */ + public function toSaveSql(AbstractPlatform $platform) + { + return $this->_toSql($platform, true); + } + + /** + * @return string[] + */ + public function toSql(AbstractPlatform $platform) + { + return $this->_toSql($platform, false); + } + + /** + * @param bool $saveMode + * + * @return string[] + */ + protected function _toSql(AbstractPlatform $platform, $saveMode = false) + { + $sql = []; + + if ($platform->supportsSchemas()) { + foreach ($this->newNamespaces as $newNamespace) { + $sql[] = $platform->getCreateSchemaSQL($newNamespace); + } + } + + if ($platform->supportsForeignKeyConstraints() && $saveMode === false) { + foreach ($this->orphanedForeignKeys as $orphanedForeignKey) { + $sql[] = $platform->getDropForeignKeySQL($orphanedForeignKey, $orphanedForeignKey->getLocalTable()); + } + } + + if ($platform->supportsSequences() === true) { + foreach ($this->changedSequences as $sequence) { + $sql[] = $platform->getAlterSequenceSQL($sequence); + } + + if ($saveMode === false) { + foreach ($this->removedSequences as $sequence) { + $sql[] = $platform->getDropSequenceSQL($sequence); + } + } + + foreach ($this->newSequences as $sequence) { + $sql[] = $platform->getCreateSequenceSQL($sequence); + } + } + + $foreignKeySql = []; + foreach ($this->newTables as $table) { + $sql = array_merge( + $sql, + $platform->getCreateTableSQL($table, AbstractPlatform::CREATE_INDEXES) + ); + + if (! $platform->supportsForeignKeyConstraints()) { + continue; + } + + 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; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaException.php new file mode 100644 index 0000000..213d218 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaException.php @@ -0,0 +1,183 @@ +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.' + ); + } + + /** + * @param string $changeName + * + * @return \Doctrine\DBAL\Schema\SchemaException + */ + public static function alterTableChangeNotSupported($changeName) + { + return new self( + sprintf("Alter table change not supported, given '%s'", $changeName) + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Sequence.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Sequence.php new file mode 100644 index 0000000..8889101 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Sequence.php @@ -0,0 +1,139 @@ +_setName($name); + $this->setAllocationSize($allocationSize); + $this->setInitialValue($initialValue); + $this->cache = $cache; + } + + /** + * @return int + */ + public function getAllocationSize() + { + return $this->allocationSize; + } + + /** + * @return int + */ + public function getInitialValue() + { + return $this->initialValue; + } + + /** + * @return int|null + */ + public function getCache() + { + return $this->cache; + } + + /** + * @param int $allocationSize + * + * @return \Doctrine\DBAL\Schema\Sequence + */ + public function setAllocationSize($allocationSize) + { + $this->allocationSize = (int) $allocationSize ?: 1; + + return $this; + } + + /** + * @param int $initialValue + * + * @return \Doctrine\DBAL\Schema\Sequence + */ + public function setInitialValue($initialValue) + { + $this->initialValue = (int) $initialValue ?: 1; + + return $this; + } + + /** + * @param int $cache + * + * @return \Doctrine\DBAL\Schema\Sequence + */ + public function setCache($cache) + { + $this->cache = $cache; + + return $this; + } + + /** + * Checks if this sequence is an autoincrement sequence for a given table. + * + * This is used inside the comparator to not report sequences as missing, + * when the "from" schema implicitly creates the sequences. + * + * @return bool + */ + public function isAutoIncrementsFor(Table $table) + { + $primaryKey = $table->getPrimaryKey(); + + if ($primaryKey === null) { + return false; + } + + $pkColumns = $primaryKey->getColumns(); + + if (count($pkColumns) !== 1) { + return false; + } + + $column = $table->getColumn($pkColumns[0]); + + if (! $column->getAutoincrement()) { + return false; + } + + $sequenceName = $this->getShortestName($table->getNamespaceName()); + $tableName = $table->getShortestName($table->getNamespaceName()); + $tableSequenceName = sprintf('%s_%s_seq', $tableName, $column->getShortestName($table->getNamespaceName())); + + return $tableSequenceName === $sequenceName; + } + + /** + * @return void + */ + public function visit(Visitor $visitor) + { + $visitor->acceptSequence($this); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php new file mode 100644 index 0000000..ac75801 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php @@ -0,0 +1,545 @@ +_conn->getParams(); + $driver = $params['driver']; + $options = [ + 'driver' => $driver, + 'path' => $database, + ]; + $conn = DriverManager::getConnection($options); + $conn->connect(); + $conn->close(); + } + + /** + * {@inheritdoc} + */ + public function renameTable($name, $newName) + { + $tableDiff = new TableDiff($name); + $tableDiff->fromTable = $this->listTableDetails($name); + $tableDiff->newName = $newName; + $this->alterTable($tableDiff); + } + + /** + * {@inheritdoc} + */ + public function createForeignKey(ForeignKeyConstraint $foreignKey, $table) + { + $tableDiff = $this->getTableDiffForAlterForeignKey($table); + $tableDiff->addedForeignKeys[] = $foreignKey; + + $this->alterTable($tableDiff); + } + + /** + * {@inheritdoc} + */ + public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table) + { + $tableDiff = $this->getTableDiffForAlterForeignKey($table); + $tableDiff->changedForeignKeys[] = $foreignKey; + + $this->alterTable($tableDiff); + } + + /** + * {@inheritdoc} + */ + public function dropForeignKey($foreignKey, $table) + { + $tableDiff = $this->getTableDiffForAlterForeignKey($table); + $tableDiff->removedForeignKeys[] = $foreignKey; + + $this->alterTable($tableDiff); + } + + /** + * {@inheritdoc} + */ + public function listTableForeignKeys($table, $database = null) + { + if ($database === null) { + $database = $this->_conn->getDatabase(); + } + $sql = $this->_platform->getListTableForeignKeysSQL($table, $database); + $tableForeignKeys = $this->_conn->fetchAll($sql); + + if (! empty($tableForeignKeys)) { + $createSql = $this->getCreateTableSQL($table); + + if ($createSql !== null && preg_match_all( + '# + (?:CONSTRAINT\s+([^\s]+)\s+)? + (?:FOREIGN\s+KEY[^\)]+\)\s*)? + REFERENCES\s+[^\s]+\s+(?:\([^\)]+\))? + (?: + [^,]*? + (NOT\s+DEFERRABLE|DEFERRABLE) + (?:\s+INITIALLY\s+(DEFERRED|IMMEDIATE))? + )?#isx', + $createSql, + $match + )) { + $names = array_reverse($match[1]); + $deferrable = array_reverse($match[2]); + $deferred = array_reverse($match[3]); + } else { + $names = $deferrable = $deferred = []; + } + + foreach ($tableForeignKeys as $key => $value) { + $id = $value['id']; + $tableForeignKeys[$key]['constraint_name'] = isset($names[$id]) && $names[$id] !== '' ? $names[$id] : $id; + $tableForeignKeys[$key]['deferrable'] = isset($deferrable[$id]) && strtolower($deferrable[$id]) === 'deferrable'; + $tableForeignKeys[$key]['deferred'] = isset($deferred[$id]) && strtolower($deferred[$id]) === 'deferred'; + } + } + + return $this->_getPortableTableForeignKeysList($tableForeignKeys); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableDefinition($table) + { + return $table['name']; + } + + /** + * {@inheritdoc} + * + * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html + */ + protected function _getPortableTableIndexesList($tableIndexes, $tableName = null) + { + $indexBuffer = []; + + // fetch primary + $stmt = $this->_conn->executeQuery(sprintf( + 'PRAGMA TABLE_INFO (%s)', + $this->_conn->quote($tableName) + )); + $indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE); + + usort($indexArray, static function ($a, $b) { + if ($a['pk'] === $b['pk']) { + return $a['cid'] - $b['cid']; + } + + return $a['pk'] - $b['pk']; + }); + foreach ($indexArray as $indexColumnRow) { + if ($indexColumnRow['pk'] === '0') { + continue; + } + + $indexBuffer[] = [ + 'key_name' => 'primary', + 'primary' => true, + 'non_unique' => false, + 'column_name' => $indexColumnRow['name'], + ]; + } + + // fetch regular indexes + foreach ($tableIndexes as $tableIndex) { + // Ignore indexes with reserved names, e.g. autoindexes + if (strpos($tableIndex['name'], 'sqlite_') === 0) { + continue; + } + + $keyName = $tableIndex['name']; + $idx = []; + $idx['key_name'] = $keyName; + $idx['primary'] = false; + $idx['non_unique'] = ! $tableIndex['unique']; + + $stmt = $this->_conn->executeQuery(sprintf( + 'PRAGMA INDEX_INFO (%s)', + $this->_conn->quote($keyName) + )); + $indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE); + + foreach ($indexArray as $indexColumnRow) { + $idx['column_name'] = $indexColumnRow['name']; + $indexBuffer[] = $idx; + } + } + + return parent::_getPortableTableIndexesList($indexBuffer, $tableName); + } + + /** + * {@inheritdoc} + * + * @deprecated + */ + protected function _getPortableTableIndexDefinition($tableIndex) + { + return [ + 'name' => $tableIndex['name'], + 'unique' => (bool) $tableIndex['unique'], + ]; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableColumnList($table, $database, $tableColumns) + { + $list = parent::_getPortableTableColumnList($table, $database, $tableColumns); + + // find column with autoincrement + $autoincrementColumn = null; + $autoincrementCount = 0; + + foreach ($tableColumns as $tableColumn) { + if ($tableColumn['pk'] === '0') { + continue; + } + + $autoincrementCount++; + if ($autoincrementColumn !== null || strtolower($tableColumn['type']) !== 'integer') { + continue; + } + + $autoincrementColumn = $tableColumn['name']; + } + + if ($autoincrementCount === 1 && $autoincrementColumn !== null) { + foreach ($list as $column) { + if ($autoincrementColumn !== $column->getName()) { + continue; + } + + $column->setAutoincrement(true); + } + } + + // inspect column collation and comments + $createSql = $this->getCreateTableSQL($table) ?? ''; + + foreach ($list as $columnName => $column) { + $type = $column->getType(); + + if ($type instanceof StringType || $type instanceof TextType) { + $column->setPlatformOption('collation', $this->parseColumnCollationFromSQL($columnName, $createSql) ?: 'BINARY'); + } + + $comment = $this->parseColumnCommentFromSQL($columnName, $createSql); + + if ($comment === null) { + continue; + } + + $type = $this->extractDoctrineTypeFromComment($comment, ''); + + if ($type !== '') { + $column->setType(Type::getType($type)); + + $comment = $this->removeDoctrineTypeFromComment($comment, $type); + } + + $column->setComment($comment); + } + + return $list; + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableColumnDefinition($tableColumn) + { + $parts = explode('(', $tableColumn['type']); + $tableColumn['type'] = trim($parts[0]); + if (isset($parts[1])) { + $length = trim($parts[1], ')'); + $tableColumn['length'] = $length; + } + + $dbType = strtolower($tableColumn['type']); + $length = $tableColumn['length'] ?? null; + $unsigned = false; + + if (strpos($dbType, ' unsigned') !== false) { + $dbType = str_replace(' unsigned', '', $dbType); + $unsigned = true; + } + + $fixed = false; + $type = $this->_platform->getDoctrineTypeMapping($dbType); + $default = $tableColumn['dflt_value']; + if ($default === 'NULL') { + $default = null; + } + + if ($default !== null) { + // SQLite returns the default value as a literal expression, so we need to parse it + if (preg_match('/^\'(.*)\'$/s', $default, $matches)) { + $default = str_replace("''", "'", $matches[1]); + } + } + + $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': + if (isset($tableColumn['length'])) { + if (strpos($tableColumn['length'], ',') === false) { + $tableColumn['length'] .= ',0'; + } + [$precision, $scale] = array_map('trim', explode(',', $tableColumn['length'])); + } + $length = null; + break; + } + + $options = [ + 'length' => $length, + 'unsigned' => (bool) $unsigned, + 'fixed' => $fixed, + 'notnull' => $notnull, + 'default' => $default, + 'precision' => $precision, + 'scale' => $scale, + 'autoincrement' => false, + ]; + + return new Column($tableColumn['name'], Type::getType($type), $options); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableViewDefinition($view) + { + return new View($view['name'], $view['sql']); + } + + /** + * {@inheritdoc} + */ + protected function _getPortableTableForeignKeysList($tableForeignKeys) + { + $list = []; + foreach ($tableForeignKeys as $value) { + $value = array_change_key_case($value, CASE_LOWER); + $name = $value['constraint_name']; + if (! isset($list[$name])) { + if (! isset($value['on_delete']) || $value['on_delete'] === 'RESTRICT') { + $value['on_delete'] = null; + } + if (! isset($value['on_update']) || $value['on_update'] === 'RESTRICT') { + $value['on_update'] = null; + } + + $list[$name] = [ + 'name' => $name, + 'local' => [], + 'foreign' => [], + 'foreignTable' => $value['table'], + 'onDelete' => $value['on_delete'], + 'onUpdate' => $value['on_update'], + 'deferrable' => $value['deferrable'], + 'deferred'=> $value['deferred'], + ]; + } + $list[$name]['local'][] = $value['from']; + $list[$name]['foreign'][] = $value['to']; + } + + $result = []; + foreach ($list as $constraint) { + $result[] = new ForeignKeyConstraint( + array_values($constraint['local']), + $constraint['foreignTable'], + array_values($constraint['foreign']), + $constraint['name'], + [ + 'onDelete' => $constraint['onDelete'], + 'onUpdate' => $constraint['onUpdate'], + 'deferrable' => $constraint['deferrable'], + 'deferred'=> $constraint['deferred'], + ] + ); + } + + return $result; + } + + /** + * @param Table|string $table + * + * @return TableDiff + * + * @throws DBALException + */ + private function getTableDiffForAlterForeignKey($table) + { + if (! $table instanceof Table) { + $tableDetails = $this->tryMethod('listTableDetails', $table); + + if ($tableDetails === false) { + throw new DBALException(sprintf('Sqlite schema manager requires to modify foreign keys table definition "%s".', $table)); + } + + $table = $tableDetails; + } + + $tableDiff = new TableDiff($table->getName()); + $tableDiff->fromTable = $table; + + return $tableDiff; + } + + private function parseColumnCollationFromSQL(string $column, string $sql) : ?string + { + $pattern = '{(?:\W' . preg_quote($column) . '\W|\W' . preg_quote($this->_platform->quoteSingleIdentifier($column)) + . '\W)[^,(]+(?:\([^()]+\)[^,]*)?(?:(?:DEFAULT|CHECK)\s*(?:\(.*?\))?[^,]*)*COLLATE\s+["\']?([^\s,"\')]+)}is'; + + if (preg_match($pattern, $sql, $match) !== 1) { + return null; + } + + return $match[1]; + } + + private function parseTableCommentFromSQL(string $table, string $sql) : ?string + { + $pattern = '/\s* # Allow whitespace characters at start of line +CREATE\sTABLE # Match "CREATE TABLE" +(?:\W"' . preg_quote($this->_platform->quoteSingleIdentifier($table), '/') . '"\W|\W' . preg_quote($table, '/') + . '\W) # Match table name (quoted and unquoted) +( # Start capture + (?:\s*--[^\n]*\n?)+ # Capture anything that starts with whitespaces followed by -- until the end of the line(s) +)/ix'; + + if (preg_match($pattern, $sql, $match) !== 1) { + return null; + } + + $comment = preg_replace('{^\s*--}m', '', rtrim($match[1], "\n")); + + return $comment === '' ? null : $comment; + } + + private function parseColumnCommentFromSQL(string $column, string $sql) : ?string + { + $pattern = '{[\s(,](?:\W' . preg_quote($this->_platform->quoteSingleIdentifier($column)) . '\W|\W' . preg_quote($column) + . '\W)(?:\(.*?\)|[^,(])*?,?((?:(?!\n))(?:\s*--[^\n]*\n?)+)}i'; + + if (preg_match($pattern, $sql, $match) !== 1) { + return null; + } + + $comment = preg_replace('{^\s*--}m', '', rtrim($match[1], "\n")); + + return $comment === '' ? null : $comment; + } + + private function getCreateTableSQL(string $table) : ?string + { + return $this->_conn->fetchColumn( + <<<'SQL' +SELECT sql + FROM ( + SELECT * + FROM sqlite_master + UNION ALL + SELECT * + FROM sqlite_temp_master + ) +WHERE type = 'table' +AND name = ? +SQL + , + [$table] + ) ?: null; + } + + /** + * @param string $tableName + */ + public function listTableDetails($tableName) : Table + { + $table = parent::listTableDetails($tableName); + + $tableCreateSql = $this->getCreateTableSQL($tableName) ?? ''; + + $comment = $this->parseTableCommentFromSQL($tableName, $tableCreateSql); + + if ($comment !== null) { + $table->addOption('comment', $comment); + } + + return $table; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php new file mode 100644 index 0000000..b597b8d --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php @@ -0,0 +1,43 @@ +conn = $conn; + } + + /** + * @param string[] $sql + */ + protected function processSqlSafely(array $sql) + { + foreach ($sql as $s) { + try { + $this->conn->exec($s); + } catch (Throwable $e) { + } + } + } + + /** + * @param string[] $sql + */ + protected function processSql(array $sql) + { + foreach ($sql as $s) { + $this->conn->exec($s); + } + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php new file mode 100644 index 0000000..3e7beea --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php @@ -0,0 +1,72 @@ +platform = $conn->getDatabasePlatform(); + } + + /** + * {@inheritdoc} + */ + public function getCreateSchema(Schema $createSchema) + { + return $createSchema->toSql($this->platform); + } + + /** + * {@inheritdoc} + */ + public function getUpdateSchema(Schema $toSchema, $noDrops = false) + { + $comparator = new Comparator(); + $sm = $this->conn->getSchemaManager(); + + $fromSchema = $sm->createSchema(); + $schemaDiff = $comparator->compare($fromSchema, $toSchema); + + if ($noDrops) { + return $schemaDiff->toSaveSql($this->platform); + } + + return $schemaDiff->toSql($this->platform); + } + + /** + * {@inheritdoc} + */ + public function getDropSchema(Schema $dropSchema) + { + $visitor = new DropSchemaSqlCollector($this->platform); + $sm = $this->conn->getSchemaManager(); + + $fullSchema = $sm->createSchema(); + + foreach ($fullSchema->getTables() as $table) { + if ($dropSchema->hasTable($table->getName())) { + $visitor->acceptTable($table); + } + + foreach ($table->getForeignKeys() as $foreignKey) { + if (! $dropSchema->hasTable($table->getName())) { + continue; + } + + if (! $dropSchema->hasTable($foreignKey->getForeignTableName())) { + continue; + } + + $visitor->acceptForeignKey($table, $foreignKey); + } + } + + if (! $this->platform->supportsSequences()) { + return $visitor->getQueries(); + } + + foreach ($dropSchema->getSequences() as $sequence) { + $visitor->acceptSequence($sequence); + } + + foreach ($dropSchema->getTables() as $table) { + $primaryKey = $table->getPrimaryKey(); + + if ($primaryKey === null) { + continue; + } + + $columns = $primaryKey->getColumns(); + + if (count($columns) > 1) { + continue; + } + + $checkSequence = $table->getName() . '_' . $columns[0] . '_seq'; + if (! $fullSchema->hasSequence($checkSequence)) { + continue; + } + + $visitor->acceptSequence($fullSchema->getSequence($checkSequence)); + } + + return $visitor->getQueries(); + } + + /** + * {@inheritdoc} + */ + public function getDropAllSchema() + { + $sm = $this->conn->getSchemaManager(); + $visitor = new DropSchemaSqlCollector($this->platform); + + $schema = $sm->createSchema(); + $schema->visit($visitor); + + return $visitor->getQueries(); + } + + /** + * {@inheritdoc} + */ + public function createSchema(Schema $createSchema) + { + $this->processSql($this->getCreateSchema($createSchema)); + } + + /** + * {@inheritdoc} + */ + public function updateSchema(Schema $toSchema, $noDrops = false) + { + $this->processSql($this->getUpdateSchema($toSchema, $noDrops)); + } + + /** + * {@inheritdoc} + */ + public function dropSchema(Schema $dropSchema) + { + $this->processSqlSafely($this->getDropSchema($dropSchema)); + } + + /** + * {@inheritdoc} + */ + public function dropAllSchema() + { + $this->processSql($this->getDropAllSchema()); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Table.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Table.php new file mode 100644 index 0000000..8e61332 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Table.php @@ -0,0 +1,856 @@ + [], + ]; + + /** @var SchemaConfig|null */ + protected $_schemaConfig = null; + + /** + * @param string $tableName + * @param Column[] $columns + * @param Index[] $indexes + * @param ForeignKeyConstraint[] $fkConstraints + * @param int $idGeneratorType + * @param mixed[] $options + * + * @throws DBALException + */ + public function __construct($tableName, array $columns = [], array $indexes = [], array $fkConstraints = [], $idGeneratorType = 0, array $options = []) + { + if (strlen($tableName) === 0) { + throw DBALException::invalidTableName($tableName); + } + + $this->_setName($tableName); + + foreach ($columns as $column) { + $this->_addColumn($column); + } + + foreach ($indexes as $idx) { + $this->_addIndex($idx); + } + + foreach ($fkConstraints as $constraint) { + $this->_addForeignKeyConstraint($constraint); + } + + $this->_options = array_merge($this->_options, $options); + } + + /** + * @return void + */ + public function setSchemaConfig(SchemaConfig $schemaConfig) + { + $this->_schemaConfig = $schemaConfig; + } + + /** + * @return int + */ + protected function _getMaxIdentifierLength() + { + if ($this->_schemaConfig instanceof SchemaConfig) { + return $this->_schemaConfig->getMaxIdentifierLength(); + } + + return 63; + } + + /** + * Sets the Primary Key. + * + * @param string[] $columnNames + * @param string|false $indexName + * + * @return self + */ + public function setPrimaryKey(array $columnNames, $indexName = false) + { + $this->_addIndex($this->_createIndex($columnNames, $indexName ?: 'primary', true, true)); + + foreach ($columnNames as $columnName) { + $column = $this->getColumn($columnName); + $column->setNotnull(true); + } + + return $this; + } + + /** + * @param string[] $columnNames + * @param string|null $indexName + * @param string[] $flags + * @param mixed[] $options + * + * @return self + */ + public function addIndex(array $columnNames, $indexName = null, array $flags = [], array $options = []) + { + if ($indexName === null) { + $indexName = $this->_generateIdentifierName( + array_merge([$this->getName()], $columnNames), + 'idx', + $this->_getMaxIdentifierLength() + ); + } + + return $this->_addIndex($this->_createIndex($columnNames, $indexName, false, false, $flags, $options)); + } + + /** + * Drops the primary key from this table. + * + * @return void + */ + public function dropPrimaryKey() + { + $this->dropIndex($this->_primaryKeyName); + $this->_primaryKeyName = false; + } + + /** + * Drops an index from this table. + * + * @param string $indexName The index name. + * + * @return void + * + * @throws SchemaException If the index does not exist. + */ + public function dropIndex($indexName) + { + $indexName = $this->normalizeIdentifier($indexName); + if (! $this->hasIndex($indexName)) { + throw SchemaException::indexDoesNotExist($indexName, $this->_name); + } + unset($this->_indexes[$indexName]); + } + + /** + * @param string[] $columnNames + * @param string|null $indexName + * @param mixed[] $options + * + * @return self + */ + public function addUniqueIndex(array $columnNames, $indexName = null, array $options = []) + { + if ($indexName === null) { + $indexName = $this->_generateIdentifierName( + array_merge([$this->getName()], $columnNames), + 'uniq', + $this->_getMaxIdentifierLength() + ); + } + + return $this->_addIndex($this->_createIndex($columnNames, $indexName, true, false, [], $options)); + } + + /** + * Renames an index. + * + * @param string $oldIndexName The name of the index to rename from. + * @param string|null $newIndexName The name of the index to rename to. + * If null is given, the index name will be auto-generated. + * + * @return self This table instance. + * + * @throws SchemaException If no index exists for the given current name + * or if an index with the given new name already exists on this table. + */ + public function renameIndex($oldIndexName, $newIndexName = null) + { + $oldIndexName = $this->normalizeIdentifier($oldIndexName); + $normalizedNewIndexName = $this->normalizeIdentifier($newIndexName); + + if ($oldIndexName === $normalizedNewIndexName) { + return $this; + } + + if (! $this->hasIndex($oldIndexName)) { + throw SchemaException::indexDoesNotExist($oldIndexName, $this->_name); + } + + if ($this->hasIndex($normalizedNewIndexName)) { + throw SchemaException::indexAlreadyExists($normalizedNewIndexName, $this->_name); + } + + $oldIndex = $this->_indexes[$oldIndexName]; + + if ($oldIndex->isPrimary()) { + $this->dropPrimaryKey(); + + return $this->setPrimaryKey($oldIndex->getColumns(), $newIndexName ?? false); + } + + unset($this->_indexes[$oldIndexName]); + + if ($oldIndex->isUnique()) { + return $this->addUniqueIndex($oldIndex->getColumns(), $newIndexName, $oldIndex->getOptions()); + } + + return $this->addIndex($oldIndex->getColumns(), $newIndexName, $oldIndex->getFlags(), $oldIndex->getOptions()); + } + + /** + * Checks if an index begins in the order of the given columns. + * + * @param string[] $columnNames + * + * @return bool + */ + public function columnsAreIndexed(array $columnNames) + { + foreach ($this->getIndexes() as $index) { + /** @var $index Index */ + if ($index->spansColumns($columnNames)) { + return true; + } + } + + return false; + } + + /** + * @param string[] $columnNames + * @param string $indexName + * @param bool $isUnique + * @param bool $isPrimary + * @param string[] $flags + * @param mixed[] $options + * + * @return Index + * + * @throws SchemaException + */ + private function _createIndex(array $columnNames, $indexName, $isUnique, $isPrimary, array $flags = [], array $options = []) + { + if (preg_match('(([^a-zA-Z0-9_]+))', $this->normalizeIdentifier($indexName))) { + throw SchemaException::indexNameInvalid($indexName); + } + + foreach ($columnNames as $columnName) { + if (! $this->hasColumn($columnName)) { + throw SchemaException::columnDoesNotExist($columnName, $this->_name); + } + } + + return new Index($indexName, $columnNames, $isUnique, $isPrimary, $flags, $options); + } + + /** + * @param string $columnName + * @param string $typeName + * @param mixed[] $options + * + * @return Column + */ + public function addColumn($columnName, $typeName, array $options = []) + { + $column = new Column($columnName, Type::getType($typeName), $options); + + $this->_addColumn($column); + + return $column; + } + + /** + * Renames a Column. + * + * @deprecated + * + * @param string $oldColumnName + * @param string $newColumnName + * + * @throws DBALException + */ + public function renameColumn($oldColumnName, $newColumnName) + { + throw new DBALException('Table#renameColumn() was removed, because it drops and recreates ' . + 'the column instead. There is no fix available, because a schema diff cannot reliably detect if a ' . + 'column was renamed or one column was created and another one dropped.'); + } + + /** + * Change Column Details. + * + * @param string $columnName + * @param mixed[] $options + * + * @return self + */ + public function changeColumn($columnName, array $options) + { + $column = $this->getColumn($columnName); + $column->setOptions($options); + + return $this; + } + + /** + * Drops a Column from the Table. + * + * @param string $columnName + * + * @return self + */ + public function dropColumn($columnName) + { + $columnName = $this->normalizeIdentifier($columnName); + unset($this->_columns[$columnName]); + + return $this; + } + + /** + * Adds a foreign key constraint. + * + * Name is inferred from the local columns. + * + * @param Table|string $foreignTable Table schema instance or table name + * @param string[] $localColumnNames + * @param string[] $foreignColumnNames + * @param mixed[] $options + * @param string|null $constraintName + * + * @return self + */ + public function addForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options = [], $constraintName = null) + { + $constraintName = $constraintName ?: $this->_generateIdentifierName(array_merge((array) $this->getName(), $localColumnNames), 'fk', $this->_getMaxIdentifierLength()); + + return $this->addNamedForeignKeyConstraint($constraintName, $foreignTable, $localColumnNames, $foreignColumnNames, $options); + } + + /** + * Adds a foreign key constraint. + * + * Name is to be generated by the database itself. + * + * @deprecated Use {@link addForeignKeyConstraint} + * + * @param Table|string $foreignTable Table schema instance or table name + * @param string[] $localColumnNames + * @param string[] $foreignColumnNames + * @param mixed[] $options + * + * @return self + */ + public function addUnnamedForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options = []) + { + return $this->addForeignKeyConstraint($foreignTable, $localColumnNames, $foreignColumnNames, $options); + } + + /** + * Adds a foreign key constraint with a given name. + * + * @deprecated Use {@link addForeignKeyConstraint} + * + * @param string $name + * @param Table|string $foreignTable Table schema instance or table name + * @param string[] $localColumnNames + * @param string[] $foreignColumnNames + * @param mixed[] $options + * + * @return self + * + * @throws SchemaException + */ + public function addNamedForeignKeyConstraint($name, $foreignTable, array $localColumnNames, array $foreignColumnNames, array $options = []) + { + if ($foreignTable instanceof Table) { + foreach ($foreignColumnNames as $columnName) { + if (! $foreignTable->hasColumn($columnName)) { + throw SchemaException::columnDoesNotExist($columnName, $foreignTable->getName()); + } + } + } + + foreach ($localColumnNames as $columnName) { + if (! $this->hasColumn($columnName)) { + throw SchemaException::columnDoesNotExist($columnName, $this->_name); + } + } + + $constraint = new ForeignKeyConstraint( + $localColumnNames, + $foreignTable, + $foreignColumnNames, + $name, + $options + ); + $this->_addForeignKeyConstraint($constraint); + + return $this; + } + + /** + * @param string $name + * @param mixed $value + * + * @return self + */ + public function addOption($name, $value) + { + $this->_options[$name] = $value; + + return $this; + } + + /** + * @return void + * + * @throws SchemaException + */ + protected function _addColumn(Column $column) + { + $columnName = $column->getName(); + $columnName = $this->normalizeIdentifier($columnName); + + if (isset($this->_columns[$columnName])) { + throw SchemaException::columnAlreadyExists($this->getName(), $columnName); + } + + $this->_columns[$columnName] = $column; + } + + /** + * Adds an index to the table. + * + * @return self + * + * @throws SchemaException + */ + protected function _addIndex(Index $indexCandidate) + { + $indexName = $indexCandidate->getName(); + $indexName = $this->normalizeIdentifier($indexName); + $replacedImplicitIndexes = []; + + foreach ($this->implicitIndexes as $name => $implicitIndex) { + if (! $implicitIndex->isFullfilledBy($indexCandidate) || ! isset($this->_indexes[$name])) { + continue; + } + + $replacedImplicitIndexes[] = $name; + } + + if ((isset($this->_indexes[$indexName]) && ! in_array($indexName, $replacedImplicitIndexes, true)) || + ($this->_primaryKeyName !== false && $indexCandidate->isPrimary()) + ) { + throw SchemaException::indexAlreadyExists($indexName, $this->_name); + } + + foreach ($replacedImplicitIndexes as $name) { + unset($this->_indexes[$name], $this->implicitIndexes[$name]); + } + + if ($indexCandidate->isPrimary()) { + $this->_primaryKeyName = $indexName; + } + + $this->_indexes[$indexName] = $indexCandidate; + + return $this; + } + + /** + * @return void + */ + 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 = $this->normalizeIdentifier($name); + + $this->_fkConstraints[$name] = $constraint; + + // add an explicit index on the foreign key columns. If there is already an index that fulfils 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 computation overhead in this case, however no duplicate indexes are ever added (based on columns). + $indexName = $this->_generateIdentifierName( + array_merge([$this->getName()], $constraint->getColumns()), + 'idx', + $this->_getMaxIdentifierLength() + ); + $indexCandidate = $this->_createIndex($constraint->getColumns(), $indexName, false, false); + + foreach ($this->_indexes as $existingIndex) { + if ($indexCandidate->isFullfilledBy($existingIndex)) { + return; + } + } + + $this->_addIndex($indexCandidate); + $this->implicitIndexes[$this->normalizeIdentifier($indexName)] = $indexCandidate; + } + + /** + * Returns whether this table has a foreign key constraint with the given name. + * + * @param string $constraintName + * + * @return bool + */ + public function hasForeignKey($constraintName) + { + $constraintName = $this->normalizeIdentifier($constraintName); + + return isset($this->_fkConstraints[$constraintName]); + } + + /** + * Returns the foreign key constraint with the given name. + * + * @param string $constraintName The constraint name. + * + * @return ForeignKeyConstraint + * + * @throws SchemaException If the foreign key does not exist. + */ + public function getForeignKey($constraintName) + { + $constraintName = $this->normalizeIdentifier($constraintName); + if (! $this->hasForeignKey($constraintName)) { + throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name); + } + + return $this->_fkConstraints[$constraintName]; + } + + /** + * Removes the foreign key constraint with the given name. + * + * @param string $constraintName The constraint name. + * + * @return void + * + * @throws SchemaException + */ + public function removeForeignKey($constraintName) + { + $constraintName = $this->normalizeIdentifier($constraintName); + if (! $this->hasForeignKey($constraintName)) { + throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name); + } + + unset($this->_fkConstraints[$constraintName]); + } + + /** + * Returns ordered list of columns (primary keys are first, then foreign keys, then the rest) + * + * @return Column[] + */ + public function getColumns() + { + $primaryKey = $this->getPrimaryKey(); + $primaryKeyColumns = []; + + if ($primaryKey !== null) { + $primaryKeyColumns = $this->filterColumns($primaryKey->getColumns()); + } + + return array_merge($primaryKeyColumns, $this->getForeignKeyColumns(), $this->_columns); + } + + /** + * Returns foreign key columns + * + * @return Column[] + */ + private function getForeignKeyColumns() + { + $foreignKeyColumns = []; + foreach ($this->getForeignKeys() as $foreignKey) { + $foreignKeyColumns = array_merge($foreignKeyColumns, $foreignKey->getColumns()); + } + + return $this->filterColumns($foreignKeyColumns); + } + + /** + * Returns only columns that have specified names + * + * @param string[] $columnNames + * + * @return Column[] + */ + private function filterColumns(array $columnNames) + { + return array_filter($this->_columns, static function ($columnName) use ($columnNames) { + return in_array($columnName, $columnNames, true); + }, ARRAY_FILTER_USE_KEY); + } + + /** + * Returns whether this table has a Column with the given name. + * + * @param string $columnName The column name. + * + * @return bool + */ + public function hasColumn($columnName) + { + $columnName = $this->normalizeIdentifier($columnName); + + return isset($this->_columns[$columnName]); + } + + /** + * Returns the Column with the given name. + * + * @param string $columnName The column name. + * + * @return Column + * + * @throws SchemaException If the column does not exist. + */ + public function getColumn($columnName) + { + $columnName = $this->normalizeIdentifier($columnName); + if (! $this->hasColumn($columnName)) { + throw SchemaException::columnDoesNotExist($columnName, $this->_name); + } + + return $this->_columns[$columnName]; + } + + /** + * Returns the primary key. + * + * @return Index|null The primary key, or null if this Table has no primary key. + */ + public function getPrimaryKey() + { + if (! $this->hasPrimaryKey()) { + return null; + } + + return $this->getIndex($this->_primaryKeyName); + } + + /** + * Returns the primary key columns. + * + * @return string[] + * + * @throws DBALException + */ + public function getPrimaryKeyColumns() + { + $primaryKey = $this->getPrimaryKey(); + + if ($primaryKey === null) { + throw new DBALException('Table ' . $this->getName() . ' has no primary key.'); + } + + return $primaryKey->getColumns(); + } + + /** + * Returns whether this table has a primary key. + * + * @return bool + */ + public function hasPrimaryKey() + { + return $this->_primaryKeyName && $this->hasIndex($this->_primaryKeyName); + } + + /** + * Returns whether this table has an Index with the given name. + * + * @param string $indexName The index name. + * + * @return bool + */ + public function hasIndex($indexName) + { + $indexName = $this->normalizeIdentifier($indexName); + + return isset($this->_indexes[$indexName]); + } + + /** + * Returns the Index with the given name. + * + * @param string $indexName The index name. + * + * @return Index + * + * @throws SchemaException If the index does not exist. + */ + public function getIndex($indexName) + { + $indexName = $this->normalizeIdentifier($indexName); + if (! $this->hasIndex($indexName)) { + throw SchemaException::indexDoesNotExist($indexName, $this->_name); + } + + return $this->_indexes[$indexName]; + } + + /** + * @return Index[] + */ + public function getIndexes() + { + return $this->_indexes; + } + + /** + * Returns the foreign key constraints. + * + * @return ForeignKeyConstraint[] + */ + public function getForeignKeys() + { + return $this->_fkConstraints; + } + + /** + * @param string $name + * + * @return bool + */ + public function hasOption($name) + { + return isset($this->_options[$name]); + } + + /** + * @param string $name + * + * @return mixed + */ + public function getOption($name) + { + return $this->_options[$name]; + } + + /** + * @return mixed[] + */ + public function getOptions() + { + return $this->_options; + } + + /** + * @return void + */ + 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. + * + * @return void + */ + 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); + } + } + + /** + * Normalizes a given identifier. + * + * Trims quotes and lowercases the given identifier. + * + * @param string|null $identifier The identifier to normalize. + * + * @return string The normalized identifier. + */ + private function normalizeIdentifier($identifier) + { + if ($identifier === null) { + return ''; + } + + return $this->trimQuotes(strtolower($identifier)); + } + + public function setComment(?string $comment) : self + { + // For keeping backward compatibility with MySQL in previous releases, table comments are stored as options. + $this->addOption('comment', $comment); + + return $this; + } + + public function getComment() : ?string + { + return $this->_options['comment'] ?? null; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/TableDiff.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/TableDiff.php new file mode 100644 index 0000000..1ff2c0a --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/TableDiff.php @@ -0,0 +1,152 @@ +name = $tableName; + $this->addedColumns = $addedColumns; + $this->changedColumns = $changedColumns; + $this->removedColumns = $removedColumns; + $this->addedIndexes = $addedIndexes; + $this->changedIndexes = $changedIndexes; + $this->removedIndexes = $removedIndexes; + $this->fromTable = $fromTable; + } + + /** + * @param AbstractPlatform $platform The platform to use for retrieving this table diff's name. + * + * @return Identifier + */ + public function getName(AbstractPlatform $platform) + { + return new Identifier( + $this->fromTable instanceof Table ? $this->fromTable->getQuotedName($platform) : $this->name + ); + } + + /** + * @return Identifier|false + */ + public function getNewName() + { + if ($this->newName === false) { + return false; + } + + return new Identifier($this->newName); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/View.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/View.php new file mode 100644 index 0000000..ac8d6cb --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/View.php @@ -0,0 +1,30 @@ +_setName($name); + $this->sql = $sql; + } + + /** + * @return string + */ + public function getSql() + { + return $this->sql; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php new file mode 100644 index 0000000..4716904 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php @@ -0,0 +1,47 @@ +platform = $platform; + } + + /** + * {@inheritdoc} + */ + public function acceptNamespace($namespaceName) + { + if (! $this->platform->supportsSchemas()) { + return; + } + + $this->createNamespaceQueries[] = $this->platform->getCreateSchemaSQL($namespaceName); + } + + /** + * {@inheritdoc} + */ + public function acceptTable(Table $table) + { + $this->createTableQueries = array_merge($this->createTableQueries, $this->platform->getCreateTableSQL($table)); + } + + /** + * {@inheritdoc} + */ + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) + { + if (! $this->platform->supportsForeignKeyConstraints()) { + return; + } + + $this->createFkConstraintQueries[] = $this->platform->getCreateForeignKeySQL($fkConstraint, $localTable); + } + + /** + * {@inheritdoc} + */ + public function acceptSequence(Sequence $sequence) + { + $this->createSequenceQueries[] = $this->platform->getCreateSequenceSQL($sequence); + } + + /** + * @return void + */ + public function resetQueries() + { + $this->createNamespaceQueries = []; + $this->createTableQueries = []; + $this->createSequenceQueries = []; + $this->createFkConstraintQueries = []; + } + + /** + * Gets all queries collected so far. + * + * @return string[] + */ + public function getQueries() + { + return array_merge( + $this->createNamespaceQueries, + $this->createTableQueries, + $this->createSequenceQueries, + $this->createFkConstraintQueries + ); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php new file mode 100644 index 0000000..81e2023 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php @@ -0,0 +1,99 @@ +platform = $platform; + $this->clearQueries(); + } + + /** + * {@inheritdoc} + */ + public function acceptTable(Table $table) + { + $this->tables->attach($table); + } + + /** + * {@inheritdoc} + */ + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) + { + if (strlen($fkConstraint->getName()) === 0) { + throw SchemaException::namedForeignKeyRequired($localTable, $fkConstraint); + } + + $this->constraints->attach($fkConstraint, $localTable); + } + + /** + * {@inheritdoc} + */ + public function acceptSequence(Sequence $sequence) + { + $this->sequences->attach($sequence); + } + + /** + * @return void + */ + public function clearQueries() + { + $this->constraints = new SplObjectStorage(); + $this->sequences = new SplObjectStorage(); + $this->tables = new SplObjectStorage(); + } + + /** + * @return string[] + */ + public function getQueries() + { + $sql = []; + + /** @var ForeignKeyConstraint $fkConstraint */ + foreach ($this->constraints as $fkConstraint) { + $localTable = $this->constraints[$fkConstraint]; + $sql[] = $this->platform->getDropForeignKeySQL($fkConstraint, $localTable); + } + + /** @var Sequence $sequence */ + foreach ($this->sequences as $sequence) { + $sql[] = $this->platform->getDropSequenceSQL($sequence); + } + + /** @var Table $table */ + foreach ($this->tables as $table) { + $sql[] = $this->platform->getDropTableSQL($table); + } + + return $sql; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Graphviz.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Graphviz.php new file mode 100644 index 0000000..d5e94cf --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Graphviz.php @@ -0,0 +1,160 @@ +output .= $this->createNodeRelation( + $fkConstraint->getLocalTableName() . ':col' . current($fkConstraint->getLocalColumns()) . ':se', + $fkConstraint->getForeignTableName() . ':col' . current($fkConstraint->getForeignColumns()) . ':se', + [ + 'dir' => 'back', + 'arrowtail' => 'dot', + 'arrowhead' => 'normal', + ] + ); + } + + /** + * {@inheritdoc} + */ + public function acceptSchema(Schema $schema) + { + $this->output = 'digraph "' . $schema->getName() . '" {' . "\n"; + $this->output .= 'splines = true;' . "\n"; + $this->output .= 'overlap = false;' . "\n"; + $this->output .= 'outputorder=edgesfirst;' . "\n"; + $this->output .= 'mindist = 0.6;' . "\n"; + $this->output .= 'sep = .2;' . "\n"; + } + + /** + * {@inheritdoc} + */ + public function acceptTable(Table $table) + { + $this->output .= $this->createNode( + $table->getName(), + [ + 'label' => $this->createTableLabel($table), + 'shape' => 'plaintext', + ] + ); + } + + /** + * @return string + */ + private function createTableLabel(Table $table) + { + // Start the table + $label = '<'; + + // The title + $label .= ''; + + // The attributes block + foreach ($table->getColumns() as $column) { + $columnLabel = $column->getName(); + + $label .= ''; + $label .= ''; + $label .= ''; + } + + // End the table + $label .= '
' . $table->getName() . '
'; + $label .= '' . $columnLabel . ''; + $label .= '' . strtolower($column->getType()) . ''; + + $primaryKey = $table->getPrimaryKey(); + + if ($primaryKey !== null && in_array($column->getName(), $primaryKey->getColumns())) { + $label .= "\xe2\x9c\xb7"; + } + $label .= '
>'; + + return $label; + } + + /** + * @param string $name + * @param string[] $options + * + * @return string + */ + private function createNode($name, $options) + { + $node = $name . ' ['; + foreach ($options as $key => $value) { + $node .= $key . '=' . $value . ' '; + } + $node .= "]\n"; + + return $node; + } + + /** + * @param string $node1 + * @param string $node2 + * @param string[] $options + * + * @return string + */ + private function createNodeRelation($node1, $node2, $options) + { + $relation = $node1 . ' -> ' . $node2 . ' ['; + foreach ($options as $key => $value) { + $relation .= $key . '=' . $value . ' '; + } + $relation .= "]\n"; + + return $relation; + } + + /** + * Get Graphviz Output + * + * @return string + */ + public function getOutput() + { + return $this->output . '}'; + } + + /** + * Writes dot language output to a file. This should usually be a *.dot file. + * + * You have to convert the output into a viewable format. For example use "neato" on linux systems + * and execute: + * + * neato -Tpng -o er.png er.dot + * + * @param string $filename + * + * @return void + */ + public function write($filename) + { + file_put_contents($filename, $this->getOutput()); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/NamespaceVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/NamespaceVisitor.php new file mode 100644 index 0000000..186fe1b --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/NamespaceVisitor.php @@ -0,0 +1,16 @@ +schema = $schema; + } + + /** + * {@inheritdoc} + */ + public function acceptTable(Table $table) + { + if ($table->isInDefaultNamespace($this->schema->getName())) { + return; + } + + $this->schema->dropTable($table->getName()); + } + + /** + * {@inheritdoc} + */ + public function acceptSequence(Sequence $sequence) + { + if ($sequence->isInDefaultNamespace($this->schema->getName())) { + return; + } + + $this->schema->dropSequence($sequence->getName()); + } + + /** + * {@inheritdoc} + */ + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) + { + // The table may already be deleted in a previous + // RemoveNamespacedAssets#acceptTable call. Removing Foreign keys that + // point to nowhere. + if (! $this->schema->hasTable($fkConstraint->getForeignTableName())) { + $localTable->removeForeignKey($fkConstraint->getName()); + + return; + } + + $foreignTable = $this->schema->getTable($fkConstraint->getForeignTableName()); + if ($foreignTable->isInDefaultNamespace($this->schema->getName())) { + return; + } + + $localTable->removeForeignKey($fkConstraint->getName()); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/SchemaDiffVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/SchemaDiffVisitor.php new file mode 100644 index 0000000..5ec843d --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/SchemaDiffVisitor.php @@ -0,0 +1,39 @@ + "client" to the ShardChoser interface. + * - An exception is thrown if trying to switch shards during an open + * transaction. + * + * Instantiation through the DriverManager looks like: + * + * @example + * + * $conn = DriverManager::getConnection(array( + * 'wrapperClass' => 'Doctrine\DBAL\Sharding\PoolingShardConnection', + * 'driver' => 'pdo_mysql', + * 'global' => array('user' => '', 'password' => '', 'host' => '', 'dbname' => ''), + * 'shards' => array( + * array('id' => 1, 'user' => 'slave1', 'password', 'host' => '', 'dbname' => ''), + * array('id' => 2, 'user' => 'slave2', 'password', 'host' => '', 'dbname' => ''), + * ), + * 'shardChoser' => 'Doctrine\DBAL\Sharding\ShardChoser\MultiTenantShardChoser', + * )); + * $shardManager = $conn->getShardManager(); + * $shardManager->selectGlobal(); + * $shardManager->selectShard($value); + */ +class PoolingShardConnection extends Connection +{ + /** @var DriverConnection[] */ + private $activeConnections = []; + + /** @var string|int|null */ + private $activeShardId; + + /** @var mixed[] */ + private $connectionParameters = []; + + /** + * {@inheritDoc} + * + * @throws InvalidArgumentException + */ + public function __construct(array $params, Driver $driver, ?Configuration $config = null, ?EventManager $eventManager = null) + { + if (! isset($params['global'], $params['shards'])) { + throw new InvalidArgumentException("Connection Parameters require 'global' and 'shards' configurations."); + } + + if (! isset($params['shardChoser'])) { + throw new InvalidArgumentException("Missing Shard Choser configuration 'shardChoser'"); + } + + if (is_string($params['shardChoser'])) { + $params['shardChoser'] = new $params['shardChoser'](); + } + + if (! ($params['shardChoser'] instanceof ShardChoser)) { + throw new InvalidArgumentException("The 'shardChoser' configuration is not a valid instance of Doctrine\DBAL\Sharding\ShardChoser\ShardChoser"); + } + + $this->connectionParameters[0] = array_merge($params, $params['global']); + + foreach ($params['shards'] as $shard) { + if (! isset($shard['id'])) { + throw new InvalidArgumentException("Missing 'id' for one configured shard. Please specify a unique shard-id."); + } + + if (! is_numeric($shard['id']) || $shard['id'] < 1) { + throw new InvalidArgumentException('Shard Id has to be a non-negative number.'); + } + + if (isset($this->connectionParameters[$shard['id']])) { + throw new InvalidArgumentException('Shard ' . $shard['id'] . ' is duplicated in the configuration.'); + } + + $this->connectionParameters[$shard['id']] = array_merge($params, $shard); + } + + parent::__construct($params, $driver, $config, $eventManager); + } + + /** + * Get active shard id. + * + * @return string|int|null + */ + public function getActiveShardId() + { + return $this->activeShardId; + } + + /** + * {@inheritdoc} + */ + public function getParams() + { + return $this->activeShardId ? $this->connectionParameters[$this->activeShardId] : $this->connectionParameters[0]; + } + + /** + * {@inheritdoc} + */ + public function getHost() + { + $params = $this->getParams(); + + return $params['host'] ?? parent::getHost(); + } + + /** + * {@inheritdoc} + */ + public function getPort() + { + $params = $this->getParams(); + + return $params['port'] ?? parent::getPort(); + } + + /** + * {@inheritdoc} + */ + public function getUsername() + { + $params = $this->getParams(); + + return $params['user'] ?? parent::getUsername(); + } + + /** + * {@inheritdoc} + */ + public function getPassword() + { + $params = $this->getParams(); + + return $params['password'] ?? parent::getPassword(); + } + + /** + * Connects to a given shard. + * + * @param string|int|null $shardId + * + * @return bool + * + * @throws ShardingException + */ + public function connect($shardId = null) + { + if ($shardId === null && $this->_conn) { + return false; + } + + if ($shardId !== null && $shardId === $this->activeShardId) { + return false; + } + + if ($this->getTransactionNestingLevel() > 0) { + throw new ShardingException('Cannot switch shard when transaction is active.'); + } + + $activeShardId = $this->activeShardId = (int) $shardId; + + if (isset($this->activeConnections[$activeShardId])) { + $this->_conn = $this->activeConnections[$activeShardId]; + + return false; + } + + $this->_conn = $this->activeConnections[$activeShardId] = $this->connectTo($activeShardId); + + if ($this->_eventManager->hasListeners(Events::postConnect)) { + $eventArgs = new ConnectionEventArgs($this); + $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); + } + + return true; + } + + /** + * Connects to a specific connection. + * + * @param string|int $shardId + * + * @return \Doctrine\DBAL\Driver\Connection + */ + protected function connectTo($shardId) + { + $params = $this->getParams(); + + $driverOptions = $params['driverOptions'] ?? []; + + $connectionParams = $this->connectionParameters[$shardId]; + + $user = $connectionParams['user'] ?? null; + $password = $connectionParams['password'] ?? null; + + return $this->_driver->connect($connectionParams, $user, $password, $driverOptions); + } + + /** + * @param string|int|null $shardId + * + * @return bool + */ + public function isConnected($shardId = null) + { + if ($shardId === null) { + return $this->_conn !== null; + } + + return isset($this->activeConnections[$shardId]); + } + + /** + * @return void + */ + public function close() + { + $this->_conn = null; + $this->activeConnections = []; + $this->activeShardId = null; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php new file mode 100644 index 0000000..5edc56b --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php @@ -0,0 +1,101 @@ +getParams(); + $this->conn = $conn; + $this->choser = $params['shardChoser']; + } + + /** + * {@inheritDoc} + */ + public function selectGlobal() + { + $this->conn->connect(0); + $this->currentDistributionValue = null; + } + + /** + * {@inheritDoc} + */ + public function selectShard($distributionValue) + { + $shardId = $this->choser->pickShard($distributionValue, $this->conn); + $this->conn->connect($shardId); + $this->currentDistributionValue = $distributionValue; + } + + /** + * {@inheritDoc} + */ + public function getCurrentDistributionValue() + { + return $this->currentDistributionValue; + } + + /** + * {@inheritDoc} + */ + public function getShards() + { + $params = $this->conn->getParams(); + $shards = []; + + foreach ($params['shards'] as $shard) { + $shards[] = ['id' => $shard['id']]; + } + + return $shards; + } + + /** + * {@inheritDoc} + * + * @throws RuntimeException + */ + public function queryAll($sql, array $params, array $types) + { + $shards = $this->getShards(); + if (! $shards) { + throw new RuntimeException('No shards found.'); + } + + $result = []; + $oldDistribution = $this->getCurrentDistributionValue(); + + foreach ($shards as $shard) { + $this->conn->connect($shard['id']); + foreach ($this->conn->fetchAll($sql, $params, $types) as $row) { + $result[] = $row; + } + } + + if ($oldDistribution === null) { + $this->selectGlobal(); + } else { + $this->selectShard($oldDistribution); + } + + return $result; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php new file mode 100644 index 0000000..417f674 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php @@ -0,0 +1,271 @@ +shardManager = $shardManager; + $this->synchronizer = $sync ?: new SingleDatabaseSynchronizer($conn); + } + + /** + * {@inheritdoc} + */ + public function getCreateSchema(Schema $createSchema) + { + $sql = []; + + [$global, $federation] = $this->partitionSchema($createSchema); + + $globalSql = $this->synchronizer->getCreateSchema($global); + if ($globalSql) { + $sql[] = "-- Create Root Federation\n" . + 'USE FEDERATION ROOT WITH RESET;'; + $sql = array_merge($sql, $globalSql); + } + + $federationSql = $this->synchronizer->getCreateSchema($federation); + + if ($federationSql) { + $defaultValue = $this->getFederationTypeDefaultValue(); + + $sql[] = $this->getCreateFederationStatement(); + $sql[] = 'USE FEDERATION ' . $this->shardManager->getFederationName() . ' (' . $this->shardManager->getDistributionKey() . ' = ' . $defaultValue . ') WITH RESET, FILTERING = OFF;'; + $sql = array_merge($sql, $federationSql); + } + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function getUpdateSchema(Schema $toSchema, $noDrops = false) + { + return $this->work($toSchema, static function ($synchronizer, $schema) use ($noDrops) { + return $synchronizer->getUpdateSchema($schema, $noDrops); + }); + } + + /** + * {@inheritdoc} + */ + public function getDropSchema(Schema $dropSchema) + { + return $this->work($dropSchema, static function ($synchronizer, $schema) { + return $synchronizer->getDropSchema($schema); + }); + } + + /** + * {@inheritdoc} + */ + public function createSchema(Schema $createSchema) + { + $this->processSql($this->getCreateSchema($createSchema)); + } + + /** + * {@inheritdoc} + */ + public function updateSchema(Schema $toSchema, $noDrops = false) + { + $this->processSql($this->getUpdateSchema($toSchema, $noDrops)); + } + + /** + * {@inheritdoc} + */ + public function dropSchema(Schema $dropSchema) + { + $this->processSqlSafely($this->getDropSchema($dropSchema)); + } + + /** + * {@inheritdoc} + */ + public function getDropAllSchema() + { + $this->shardManager->selectGlobal(); + $globalSql = $this->synchronizer->getDropAllSchema(); + + if ($globalSql) { + $sql[] = "-- Work on Root Federation\nUSE FEDERATION ROOT WITH RESET;"; + $sql = array_merge($sql, $globalSql); + } + + $shards = $this->shardManager->getShards(); + foreach ($shards as $shard) { + $this->shardManager->selectShard($shard['rangeLow']); + + $federationSql = $this->synchronizer->getDropAllSchema(); + if (! $federationSql) { + continue; + } + + $sql[] = '-- Work on Federation ID ' . $shard['id'] . "\n" . + 'USE FEDERATION ' . $this->shardManager->getFederationName() . ' (' . $this->shardManager->getDistributionKey() . ' = ' . $shard['rangeLow'] . ') WITH RESET, FILTERING = OFF;'; + $sql = array_merge($sql, $federationSql); + } + + $sql[] = 'USE FEDERATION ROOT WITH RESET;'; + $sql[] = 'DROP FEDERATION ' . $this->shardManager->getFederationName(); + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function dropAllSchema() + { + $this->processSqlSafely($this->getDropAllSchema()); + } + + /** + * @return Schema[] + */ + private function partitionSchema(Schema $schema) + { + return [ + $this->extractSchemaFederation($schema, false), + $this->extractSchemaFederation($schema, true), + ]; + } + + /** + * @param bool $isFederation + * + * @return Schema + * + * @throws RuntimeException + */ + private function extractSchemaFederation(Schema $schema, $isFederation) + { + $partitionedSchema = clone $schema; + + foreach ($partitionedSchema->getTables() as $table) { + if ($isFederation) { + $table->addOption(self::FEDERATION_DISTRIBUTION_NAME, $this->shardManager->getDistributionKey()); + } + + if ($table->hasOption(self::FEDERATION_TABLE_FEDERATED) !== $isFederation) { + $partitionedSchema->dropTable($table->getName()); + } else { + foreach ($table->getForeignKeys() as $fk) { + $foreignTable = $schema->getTable($fk->getForeignTableName()); + if ($foreignTable->hasOption(self::FEDERATION_TABLE_FEDERATED) !== $isFederation) { + throw new RuntimeException('Cannot have foreign key between global/federation.'); + } + } + } + } + + return $partitionedSchema; + } + + /** + * Work on the Global/Federation based on currently existing shards and + * perform the given operation on the underlying schema synchronizer given + * the different partitioned schema instances. + * + * @return string[] + */ + private function work(Schema $schema, Closure $operation) + { + [$global, $federation] = $this->partitionSchema($schema); + $sql = []; + + $this->shardManager->selectGlobal(); + $globalSql = $operation($this->synchronizer, $global); + + if ($globalSql) { + $sql[] = "-- Work on Root Federation\nUSE FEDERATION ROOT WITH RESET;"; + $sql = array_merge($sql, $globalSql); + } + + $shards = $this->shardManager->getShards(); + + foreach ($shards as $shard) { + $this->shardManager->selectShard($shard['rangeLow']); + + $federationSql = $operation($this->synchronizer, $federation); + if (! $federationSql) { + continue; + } + + $sql[] = '-- Work on Federation ID ' . $shard['id'] . "\n" . + 'USE FEDERATION ' . $this->shardManager->getFederationName() . ' (' . $this->shardManager->getDistributionKey() . ' = ' . $shard['rangeLow'] . ') WITH RESET, FILTERING = OFF;'; + $sql = array_merge($sql, $federationSql); + } + + return $sql; + } + + /** + * @return string + */ + private function getFederationTypeDefaultValue() + { + $federationType = Type::getType($this->shardManager->getDistributionType()); + + switch ($federationType->getName()) { + case Types::GUID: + $defaultValue = '00000000-0000-0000-0000-000000000000'; + break; + case Types::INTEGER: + case Types::SMALLINT: + case Types::BIGINT: + $defaultValue = '0'; + break; + default: + $defaultValue = ''; + break; + } + + return $defaultValue; + } + + /** + * @return string + */ + private function getCreateFederationStatement() + { + $federationType = Type::getType($this->shardManager->getDistributionType()); + $federationTypeSql = $federationType->getSQLDeclaration([], $this->conn->getDatabasePlatform()); + + return "--Create Federation\n" . + 'CREATE FEDERATION ' . $this->shardManager->getFederationName() . ' (' . $this->shardManager->getDistributionKey() . ' ' . $federationTypeSql . ' RANGE)'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php new file mode 100644 index 0000000..d8178ee --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php @@ -0,0 +1,208 @@ +conn = $conn; + $params = $conn->getParams(); + + if (! isset($params['sharding']['federationName'])) { + throw ShardingException::missingDefaultFederationName(); + } + + if (! isset($params['sharding']['distributionKey'])) { + throw ShardingException::missingDefaultDistributionKey(); + } + + if (! isset($params['sharding']['distributionType'])) { + throw ShardingException::missingDistributionType(); + } + + $this->federationName = $params['sharding']['federationName']; + $this->distributionKey = $params['sharding']['distributionKey']; + $this->distributionType = $params['sharding']['distributionType']; + $this->filteringEnabled = (bool) ($params['sharding']['filteringEnabled'] ?? false); + } + + /** + * Gets the name of the federation. + * + * @return string + */ + public function getFederationName() + { + return $this->federationName; + } + + /** + * Gets the distribution key. + * + * @return string + */ + public function getDistributionKey() + { + return $this->distributionKey; + } + + /** + * Gets the Doctrine Type name used for the distribution. + * + * @return string + */ + public function getDistributionType() + { + return $this->distributionType; + } + + /** + * Sets Enabled/Disable filtering on the fly. + * + * @param bool $flag + * + * @return void + */ + public function setFilteringEnabled($flag) + { + $this->filteringEnabled = (bool) $flag; + } + + /** + * {@inheritDoc} + */ + public function selectGlobal() + { + if ($this->conn->isTransactionActive()) { + throw ShardingException::activeTransaction(); + } + + $sql = 'USE FEDERATION ROOT WITH RESET'; + $this->conn->exec($sql); + $this->currentDistributionValue = null; + } + + /** + * {@inheritDoc} + */ + public function selectShard($distributionValue) + { + if ($this->conn->isTransactionActive()) { + throw ShardingException::activeTransaction(); + } + + $platform = $this->conn->getDatabasePlatform(); + $sql = sprintf( + 'USE FEDERATION %s (%s = %s) WITH RESET, FILTERING = %s;', + $platform->quoteIdentifier($this->federationName), + $platform->quoteIdentifier($this->distributionKey), + $this->conn->quote($distributionValue), + ($this->filteringEnabled ? 'ON' : 'OFF') + ); + + $this->conn->exec($sql); + $this->currentDistributionValue = $distributionValue; + } + + /** + * {@inheritDoc} + */ + public function getCurrentDistributionValue() + { + return $this->currentDistributionValue; + } + + /** + * {@inheritDoc} + */ + public function getShards() + { + $sql = 'SELECT member_id as id, + distribution_name as distribution_key, + CAST(range_low AS CHAR) AS rangeLow, + CAST(range_high AS CHAR) AS rangeHigh + FROM sys.federation_member_distributions d + INNER JOIN sys.federations f ON f.federation_id = d.federation_id + WHERE f.name = ' . $this->conn->quote($this->federationName); + + return $this->conn->fetchAll($sql); + } + + /** + * {@inheritDoc} + */ + public function queryAll($sql, array $params = [], array $types = []) + { + $shards = $this->getShards(); + if (! $shards) { + throw new RuntimeException('No shards found for ' . $this->federationName); + } + + $result = []; + $oldDistribution = $this->getCurrentDistributionValue(); + + foreach ($shards as $shard) { + $this->selectShard($shard['rangeLow']); + foreach ($this->conn->fetchAll($sql, $params, $types) as $row) { + $result[] = $row; + } + } + + if ($oldDistribution === null) { + $this->selectGlobal(); + } else { + $this->selectShard($oldDistribution); + } + + return $result; + } + + /** + * Splits Federation at a given distribution value. + * + * @param mixed $splitDistributionValue + * + * @return void + */ + public function splitFederation($splitDistributionValue) + { + $type = Type::getType($this->distributionType); + + $sql = 'ALTER FEDERATION ' . $this->getFederationName() . ' ' . + 'SPLIT AT (' . $this->getDistributionKey() . ' = ' . + $this->conn->quote($splitDistributionValue, $type->getBindingType()) . ')'; + $this->conn->exec($sql); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php new file mode 100644 index 0000000..a83b401 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php @@ -0,0 +1,148 @@ +excludedTables = $excludedTables; + $this->tenantColumnName = $tenantColumnName; + $this->distributionName = $distributionName ?: $tenantColumnName; + } + + /** + * {@inheritdoc} + */ + public function acceptTable(Table $table) + { + if (in_array($table->getName(), $this->excludedTables)) { + return; + } + + $table->addColumn($this->tenantColumnName, $this->tenantColumnType, [ + 'default' => "federation_filtering_value('" . $this->distributionName . "')", + ]); + + $clusteredIndex = $this->getClusteredIndex($table); + + $indexColumns = $clusteredIndex->getColumns(); + $indexColumns[] = $this->tenantColumnName; + + if ($clusteredIndex->isPrimary()) { + $table->dropPrimaryKey(); + $table->setPrimaryKey($indexColumns); + } else { + $table->dropIndex($clusteredIndex->getName()); + $table->addIndex($indexColumns, $clusteredIndex->getName()); + $table->getIndex($clusteredIndex->getName())->addFlag('clustered'); + } + } + + /** + * @param Table $table + * + * @return Index + * + * @throws RuntimeException + */ + private function getClusteredIndex($table) + { + foreach ($table->getIndexes() as $index) { + if ($index->isPrimary() && ! $index->hasFlag('nonclustered')) { + return $index; + } + + if ($index->hasFlag('clustered')) { + return $index; + } + } + throw new RuntimeException('No clustered index found on table ' . $table->getName()); + } + + /** + * {@inheritdoc} + */ + public function acceptSchema(Schema $schema) + { + } + + /** + * {@inheritdoc} + */ + public function acceptColumn(Table $table, Column $column) + { + } + + /** + * {@inheritdoc} + */ + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) + { + } + + /** + * {@inheritdoc} + */ + public function acceptIndex(Table $table, Index $index) + { + } + + /** + * {@inheritdoc} + */ + public function acceptSequence(Sequence $sequence) + { + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php new file mode 100644 index 0000000..584e815 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php @@ -0,0 +1,20 @@ +Statement for the given SQL and Connection. + * + * @param string $sql The SQL of the statement. + * @param Connection $conn 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 string|int $name The name or position of the parameter. + * @param mixed $value The value of the parameter. + * @param mixed $type Either a PDO binding type or a DBAL mapping type name or instance. + * + * @return bool TRUE on success, FALSE on failure. + */ + public function bindValue($name, $value, $type = ParameterType::STRING) + { + $this->params[$name] = $value; + $this->types[$name] = $type; + 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; + } + + return $this->stmt->bindValue($name, $value, $bindingType); + } + + 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|int $name The name or position of the parameter. + * @param mixed $var The reference to the variable to bind. + * @param int $type The PDO binding type. + * @param int|null $length Must be specified when using an OUT bind + * so that PHP allocates enough memory to hold the returned value. + * + * @return bool TRUE on success, FALSE on failure. + */ + public function bindParam($name, &$var, $type = ParameterType::STRING, $length = null) + { + $this->params[$name] = $var; + $this->types[$name] = $type; + + return $this->stmt->bindParam($name, $var, $type, $length); + } + + /** + * Executes the statement with the currently bound parameters. + * + * @param mixed[]|null $params + * + * @return bool TRUE on success, FALSE on failure. + * + * @throws DBALException + */ + public function execute($params = null) + { + if (is_array($params)) { + $this->params = $params; + } + + $logger = $this->conn->getConfiguration()->getSQLLogger(); + if ($logger) { + $logger->startQuery($this->sql, $this->params, $this->types); + } + + try { + $stmt = $this->stmt->execute($params); + } catch (Throwable $ex) { + if ($logger) { + $logger->stopQuery(); + } + throw DBALException::driverExceptionDuringQuery( + $this->conn->getDriver(), + $ex, + $this->sql, + $this->conn->resolveParams($this->params, $this->types) + ); + } + + if ($logger) { + $logger->stopQuery(); + } + $this->params = []; + $this->types = []; + + return $stmt; + } + + /** + * Closes the cursor, freeing the database resources used by this statement. + * + * @return bool TRUE on success, FALSE on failure. + */ + public function closeCursor() + { + return $this->stmt->closeCursor(); + } + + /** + * Returns the number of columns in the result set. + * + * @return int + */ + public function columnCount() + { + return $this->stmt->columnCount(); + } + + /** + * Fetches the SQLSTATE associated with the last operation on the statement. + * + * @return string|int|bool + */ + public function errorCode() + { + return $this->stmt->errorCode(); + } + + /** + * {@inheritDoc} + */ + public function errorInfo() + { + return $this->stmt->errorInfo(); + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + if ($arg2 === null) { + return $this->stmt->setFetchMode($fetchMode); + } + + if ($arg3 === null) { + return $this->stmt->setFetchMode($fetchMode, $arg2); + } + + return $this->stmt->setFetchMode($fetchMode, $arg2, $arg3); + } + + /** + * Required by interface IteratorAggregate. + * + * {@inheritdoc} + */ + public function getIterator() + { + return $this->stmt; + } + + /** + * {@inheritdoc} + */ + public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + { + return $this->stmt->fetch($fetchMode); + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + { + if ($fetchArgument) { + return $this->stmt->fetchAll($fetchMode, $fetchArgument); + } + + return $this->stmt->fetchAll($fetchMode); + } + + /** + * {@inheritDoc} + */ + public function fetchColumn($columnIndex = 0) + { + return $this->stmt->fetchColumn($columnIndex); + } + + /** + * Returns the number of rows affected by the last execution of this statement. + * + * @return int 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; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php new file mode 100644 index 0000000..0cd2999 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php @@ -0,0 +1,138 @@ +setName('dbal:import') + ->setDescription('Import SQL file(s) directly to Database.') + ->setDefinition([new InputArgument( + 'file', + InputArgument::REQUIRED | InputArgument::IS_ARRAY, + 'File path(s) of SQL to be executed.' + ), + ]) + ->setHelp(<<getHelper('db')->getConnection(); + + $fileNames = $input->getArgument('file'); + + if ($fileNames === null) { + return 0; + } + + foreach ((array) $fileNames as $fileName) { + $filePath = realpath($fileName); + + // Phar compatibility. + if ($filePath === false) { + $filePath = $fileName; + } + + if (! file_exists($filePath)) { + throw new InvalidArgumentException( + sprintf("SQL file '%s' does not exist.", $filePath) + ); + } + + if (! is_readable($filePath)) { + throw new InvalidArgumentException( + sprintf("SQL file '%s' does not have read permissions.", $filePath) + ); + } + + $output->write(sprintf("Processing file '%s'... ", $filePath)); + $sql = @file_get_contents($filePath); + + if ($sql === false) { + throw new RuntimeException( + sprintf("Unable to read SQL file '%s': %s", $filePath, error_get_last()['message']) + ); + } + + if ($conn instanceof PDOConnection) { + // PDO Drivers + try { + $lines = 0; + + $stmt = $conn->prepare($sql); + assert($stmt instanceof PDOStatement); + + $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) { + $error = $stmt->errorInfo(); + + $output->write('error!' . PHP_EOL); + + throw new RuntimeException($error[2], $error[0]); + } + + $output->writeln('OK!' . PHP_EOL); + + $stmt->closeCursor(); + } + } + + return 0; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php new file mode 100644 index 0000000..2e0c48a --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php @@ -0,0 +1,181 @@ + MySQLKeywords::class, + 'mysql57' => MySQL57Keywords::class, + 'mysql80' => MySQL80Keywords::class, + 'sqlserver' => SQLServerKeywords::class, + 'sqlserver2005' => SQLServer2005Keywords::class, + 'sqlserver2008' => SQLServer2008Keywords::class, + 'sqlserver2012' => SQLServer2012Keywords::class, + 'sqlite' => SQLiteKeywords::class, + 'pgsql' => PostgreSQLKeywords::class, + 'pgsql91' => PostgreSQL91Keywords::class, + 'pgsql92' => PostgreSQL92Keywords::class, + 'oracle' => OracleKeywords::class, + 'db2' => DB2Keywords::class, + 'sqlanywhere' => SQLAnywhereKeywords::class, + 'sqlanywhere11' => SQLAnywhere11Keywords::class, + 'sqlanywhere12' => SQLAnywhere12Keywords::class, + 'sqlanywhere16' => SQLAnywhere16Keywords::class, + ]; + + /** + * If you want to add or replace a keywords list use this command. + * + * @param string $name + * @param string $class + * + * @return void + */ + public function setKeywordListClass($name, $class) + { + $this->keywordListClasses[$name] = $class; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('dbal:reserved-words') + ->setDescription('Checks if the current database contains identifiers that are reserved.') + ->setDefinition([new InputOption( + 'list', + 'l', + InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, + 'Keyword-List name.' + ), + ]) + ->setHelp(<<%command.full_name% + +If you want to check against specific dialects you can +pass them to the command: + + %command.full_name% -l mysql -l pgsql + +The following keyword lists are currently shipped with Doctrine: + + * mysql + * mysql57 + * mysql80 + * pgsql + * pgsql92 + * sqlite + * oracle + * sqlserver + * sqlserver2005 + * sqlserver2008 + * sqlserver2012 + * sqlanywhere + * sqlanywhere11 + * sqlanywhere12 + * sqlanywhere16 + * db2 (Not checked by default) +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + /** @var Connection $conn */ + $conn = $this->getHelper('db')->getConnection(); + + $keywordLists = (array) $input->getOption('list'); + if (! $keywordLists) { + $keywordLists = [ + 'mysql', + 'mysql57', + 'mysql80', + 'pgsql', + 'pgsql92', + 'sqlite', + 'oracle', + 'sqlserver', + 'sqlserver2005', + 'sqlserver2008', + 'sqlserver2012', + 'sqlanywhere', + 'sqlanywhere11', + 'sqlanywhere12', + 'sqlanywhere16', + ]; + } + + $keywords = []; + foreach ($keywordLists as $keywordList) { + if (! isset($this->keywordListClasses[$keywordList])) { + throw new InvalidArgumentException( + "There exists no keyword list with name '" . $keywordList . "'. " . + 'Known lists: ' . implode(', ', array_keys($this->keywordListClasses)) + ); + } + $class = $this->keywordListClasses[$keywordList]; + $keywords[] = new $class(); + } + + $output->write('Checking keyword violations for ' . implode(', ', $keywordLists) . '...', true); + + $schema = $conn->getSchemaManager()->createSchema(); + $visitor = new ReservedKeywordsValidator($keywords); + $schema->visit($visitor); + + $violations = $visitor->getViolations(); + if (count($violations) !== 0) { + $output->write('There are ' . count($violations) . ' reserved keyword violations in your database schema:', true); + foreach ($violations as $violation) { + $output->write(' - ' . $violation, true); + } + + return 1; + } + + $output->write('No reserved keywords violations have been found!', true); + + return 0; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php new file mode 100644 index 0000000..b479bae --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php @@ -0,0 +1,74 @@ +setName('dbal:run-sql') + ->setDescription('Executes arbitrary SQL directly from the command line.') + ->setDefinition([ + new InputArgument('sql', InputArgument::REQUIRED, 'The SQL statement to execute.'), + new InputOption('depth', null, InputOption::VALUE_REQUIRED, 'Dumping depth of result set.', 7), + new InputOption('force-fetch', null, InputOption::VALUE_NONE, 'Forces fetching the result.'), + ]) + ->setHelp(<<getHelper('db')->getConnection(); + + $sql = $input->getArgument('sql'); + + if ($sql === null) { + throw new RuntimeException("Argument 'SQL' is required in order to execute this command correctly."); + } + + assert(is_string($sql)); + + $depth = $input->getOption('depth'); + + if (! is_numeric($depth)) { + throw new LogicException("Option 'depth' must contains an integer value"); + } + + if (stripos($sql, 'select') === 0 || $input->getOption('force-fetch')) { + $resultSet = $conn->fetchAll($sql); + } else { + $resultSet = $conn->executeUpdate($sql); + } + + $output->write(Dumper::dump($resultSet, (int) $depth)); + + return 0; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php new file mode 100644 index 0000000..520a9af --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php @@ -0,0 +1,86 @@ + new ConnectionHelper($connection), + ]); + } + + /** + * Runs console with the given helperset. + * + * @param Command[] $commands + * + * @return void + */ + public static function run(HelperSet $helperSet, $commands = []) + { + $cli = new Application('Doctrine Command Line Interface', Version::VERSION); + + $cli->setCatchExceptions(true); + $cli->setHelperSet($helperSet); + + self::addCommands($cli); + + $cli->addCommands($commands); + $cli->run(); + } + + /** + * @return void + */ + public static function addCommands(Application $cli) + { + $cli->addCommands([ + new RunSqlCommand(), + new ImportCommand(), + new ReservedWordsCommand(), + ]); + } + + /** + * Prints the instructions to create a configuration file + */ + public static function printCliConfigTemplate() + { + echo <<<'HELP' +You are missing a "cli-config.php" or "config/cli-config.php" file in your +project, which is required to get the Doctrine-DBAL Console working. You can use the +following sample as a template: + +_connection = $connection; + } + + /** + * Retrieves the Doctrine database Connection. + * + * @return Connection + */ + public function getConnection() + { + return $this->_connection; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'connection'; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Dumper.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Dumper.php new file mode 100644 index 0000000..3668efb --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Dumper.php @@ -0,0 +1,182 @@ +toArray(); + } + + if ($maxDepth === 0) { + return is_object($var) ? get_class($var) + : (is_array($var) ? 'Array(' . count($var) . ')' : $var); + } + + if (is_array($var)) { + $return = []; + + foreach ($var as $k => $v) { + $return[$k] = self::export($v, $maxDepth - 1); + } + + return $return; + } + + if (! $isObj) { + return $var; + } + + $return = new stdClass(); + if ($var instanceof DateTimeInterface) { + $return->__CLASS__ = get_class($var); + $return->date = $var->format('c'); + $return->timezone = $var->getTimezone()->getName(); + + return $return; + } + + $return->__CLASS__ = self::getClass($var); + + if ($var instanceof Proxy) { + $return->__IS_PROXY__ = true; + $return->__PROXY_INITIALIZED__ = $var->__isInitialized(); + } + + if ($var instanceof ArrayObject || $var instanceof ArrayIterator) { + $return->__STORAGE__ = self::export($var->getArrayCopy(), $maxDepth - 1); + } + + return self::fillReturnWithClassAttributes($var, $return, $maxDepth); + } + + /** + * Fill the $return variable with class attributes + * Based on obj2array function from {@see https://secure.php.net/manual/en/function.get-object-vars.php#47075} + * + * @param object $var + * + * @return mixed + */ + private static function fillReturnWithClassAttributes($var, stdClass $return, int $maxDepth) + { + $clone = (array) $var; + + foreach (array_keys($clone) as $key) { + $aux = explode("\0", $key); + $name = end($aux); + if ($aux[0] === '') { + $name .= ':' . ($aux[1] === '*' ? 'protected' : $aux[1] . ':private'); + } + $return->$name = self::export($clone[$key], $maxDepth - 1); + } + + return $return; + } + + /** + * @param object $object + */ + private static function getClass($object) : string + { + $class = get_class($object); + + if (! class_exists(Proxy::class)) { + return $class; + } + + $pos = strrpos($class, '\\' . Proxy::MARKER . '\\'); + + if ($pos === false) { + return $class; + } + + return substr($class, $pos + strlen(Proxy::MARKER) + 2); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/TransactionIsolationLevel.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/TransactionIsolationLevel.php new file mode 100644 index 0000000..4e35639 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/TransactionIsolationLevel.php @@ -0,0 +1,32 @@ +getClobTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + // @todo 3.0 - $value === null check to save real NULL in database + return serialize($value); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return null; + } + + $value = is_resource($value) ? stream_get_contents($value) : $value; + + set_error_handler(function (int $code, string $message) : bool { + throw ConversionException::conversionFailedUnserialization($this->getName(), $message); + }); + + try { + return unserialize($value); + } finally { + restore_error_handler(); + } + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return Types::ARRAY; + } + + /** + * {@inheritdoc} + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BigIntType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BigIntType.php new file mode 100644 index 0000000..69cd534 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BigIntType.php @@ -0,0 +1,44 @@ +getBigIntTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function getBindingType() + { + return ParameterType::STRING; + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return $value === null ? null : (string) $value; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BinaryType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BinaryType.php new file mode 100644 index 0000000..d604b3b --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BinaryType.php @@ -0,0 +1,66 @@ +getBinaryTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return null; + } + + if (is_string($value)) { + $fp = fopen('php://temp', 'rb+'); + assert(is_resource($fp)); + fwrite($fp, $value); + fseek($fp, 0); + $value = $fp; + } + + if (! is_resource($value)) { + throw ConversionException::conversionFailed($value, Types::BINARY); + } + + return $value; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return Types::BINARY; + } + + /** + * {@inheritdoc} + */ + public function getBindingType() + { + return ParameterType::BINARY; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BlobType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BlobType.php new file mode 100644 index 0000000..e4bb22f --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BlobType.php @@ -0,0 +1,66 @@ +getBlobTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return null; + } + + if (is_string($value)) { + $fp = fopen('php://temp', 'rb+'); + assert(is_resource($fp)); + fwrite($fp, $value); + fseek($fp, 0); + $value = $fp; + } + + if (! is_resource($value)) { + throw ConversionException::conversionFailed($value, Types::BLOB); + } + + return $value; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return Types::BLOB; + } + + /** + * {@inheritdoc} + */ + public function getBindingType() + { + return ParameterType::LARGE_OBJECT; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BooleanType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BooleanType.php new file mode 100644 index 0000000..bf9be9b --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BooleanType.php @@ -0,0 +1,52 @@ +getBooleanTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + return $platform->convertBooleansToDatabaseValue($value); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return $platform->convertFromBoolean($value); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return Types::BOOLEAN; + } + + /** + * {@inheritdoc} + */ + public function getBindingType() + { + return ParameterType::BOOLEAN; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ConversionException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ConversionException.php new file mode 100644 index 0000000..b9f8a82 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ConversionException.php @@ -0,0 +1,109 @@ + 32 ? substr($value, 0, 20) . '...' : $value; + + return new self('Could not convert database value "' . $value . '" to Doctrine Type ' . $toType); + } + + /** + * Thrown when a Database to Doctrine Type Conversion fails and we can make a statement + * about the expected format. + * + * @param string $value + * @param string $toType + * @param string $expectedFormat + * + * @return \Doctrine\DBAL\Types\ConversionException + */ + public static function conversionFailedFormat($value, $toType, $expectedFormat, ?Throwable $previous = null) + { + $value = strlen($value) > 32 ? substr($value, 0, 20) . '...' : $value; + + return new self( + 'Could not convert database value "' . $value . '" to Doctrine Type ' . + $toType . '. Expected format: ' . $expectedFormat, + 0, + $previous + ); + } + + /** + * Thrown when the PHP value passed to the converter was not of the expected type. + * + * @param mixed $value + * @param string $toType + * @param string[] $possibleTypes + * + * @return \Doctrine\DBAL\Types\ConversionException + */ + public static function conversionFailedInvalidType($value, $toType, array $possibleTypes) + { + $actualType = is_object($value) ? get_class($value) : gettype($value); + + if (is_scalar($value)) { + return new self(sprintf( + "Could not convert PHP value '%s' of type '%s' to type '%s'. Expected one of the following types: %s", + $value, + $actualType, + $toType, + implode(', ', $possibleTypes) + )); + } + + return new self(sprintf( + "Could not convert PHP value of type '%s' to type '%s'. Expected one of the following types: %s", + $actualType, + $toType, + implode(', ', $possibleTypes) + )); + } + + public static function conversionFailedSerialization($value, $format, $error) + { + $actualType = is_object($value) ? get_class($value) : gettype($value); + + return new self(sprintf( + "Could not convert PHP type '%s' to '%s', as an '%s' error was triggered by the serialization", + $actualType, + $format, + $error + )); + } + + public static function conversionFailedUnserialization(string $format, string $error) : self + { + return new self(sprintf( + "Could not convert database value to '%s' as an error was triggered by the unserialization: '%s'", + $format, + $error + )); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateImmutableType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateImmutableType.php new file mode 100644 index 0000000..a4c5d26 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateImmutableType.php @@ -0,0 +1,70 @@ +format($platform->getDateFormatString()); + } + + throw ConversionException::conversionFailedInvalidType( + $value, + $this->getName(), + ['null', DateTimeImmutable::class] + ); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof DateTimeImmutable) { + return $value; + } + + $dateTime = DateTimeImmutable::createFromFormat('!' . $platform->getDateFormatString(), $value); + + if (! $dateTime) { + throw ConversionException::conversionFailedFormat( + $value, + $this->getName(), + $platform->getDateFormatString() + ); + } + + return $dateTime; + } + + /** + * {@inheritdoc} + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateIntervalType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateIntervalType.php new file mode 100644 index 0000000..96a446e --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateIntervalType.php @@ -0,0 +1,87 @@ +getVarcharTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return null; + } + + if ($value instanceof DateInterval) { + return $value->format(self::FORMAT); + } + + throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateInterval']); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof DateInterval) { + return $value; + } + + $negative = false; + + if (isset($value[0]) && ($value[0] === '+' || $value[0] === '-')) { + $negative = $value[0] === '-'; + $value = substr($value, 1); + } + + try { + $interval = new DateInterval($value); + + if ($negative) { + $interval->invert = 1; + } + + return $interval; + } catch (Throwable $exception) { + throw ConversionException::conversionFailedFormat($value, $this->getName(), self::FORMAT, $exception); + } + } + + /** + * {@inheritdoc} + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeImmutableType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeImmutableType.php new file mode 100644 index 0000000..51960a8 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeImmutableType.php @@ -0,0 +1,75 @@ +format($platform->getDateTimeFormatString()); + } + + throw ConversionException::conversionFailedInvalidType( + $value, + $this->getName(), + ['null', DateTimeImmutable::class] + ); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof DateTimeImmutable) { + return $value; + } + + $dateTime = DateTimeImmutable::createFromFormat($platform->getDateTimeFormatString(), $value); + + if (! $dateTime) { + $dateTime = date_create_immutable($value); + } + + if (! $dateTime) { + throw ConversionException::conversionFailedFormat( + $value, + $this->getName(), + $platform->getDateTimeFormatString() + ); + } + + return $dateTime; + } + + /** + * {@inheritdoc} + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php new file mode 100644 index 0000000..65071a6 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php @@ -0,0 +1,68 @@ +getDateTimeTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return $value; + } + + if ($value instanceof DateTimeInterface) { + return $value->format($platform->getDateTimeFormatString()); + } + + throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateTime']); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof DateTimeInterface) { + return $value; + } + + $val = DateTime::createFromFormat($platform->getDateTimeFormatString(), $value); + + if (! $val) { + $val = date_create($value); + } + + if (! $val) { + throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateTimeFormatString()); + } + + return $val; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzImmutableType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzImmutableType.php new file mode 100644 index 0000000..b888624 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzImmutableType.php @@ -0,0 +1,70 @@ +format($platform->getDateTimeTzFormatString()); + } + + throw ConversionException::conversionFailedInvalidType( + $value, + $this->getName(), + ['null', DateTimeImmutable::class] + ); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof DateTimeImmutable) { + return $value; + } + + $dateTime = DateTimeImmutable::createFromFormat($platform->getDateTimeTzFormatString(), $value); + + if (! $dateTime) { + throw ConversionException::conversionFailedFormat( + $value, + $this->getName(), + $platform->getDateTimeTzFormatString() + ); + } + + return $dateTime; + } + + /** + * {@inheritdoc} + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzType.php new file mode 100644 index 0000000..6240da8 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzType.php @@ -0,0 +1,75 @@ +getDateTimeTzTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return $value; + } + + if ($value instanceof DateTimeInterface) { + return $value->format($platform->getDateTimeTzFormatString()); + } + + throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateTime']); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof DateTimeInterface) { + return $value; + } + + $val = DateTime::createFromFormat($platform->getDateTimeTzFormatString(), $value); + if (! $val) { + throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateTimeTzFormatString()); + } + + return $val; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateType.php new file mode 100644 index 0000000..15d9362 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateType.php @@ -0,0 +1,62 @@ +getDateTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return $value; + } + + if ($value instanceof DateTimeInterface) { + return $value->format($platform->getDateFormatString()); + } + + throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateTime']); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof DateTimeInterface) { + return $value; + } + + $val = DateTime::createFromFormat('!' . $platform->getDateFormatString(), $value); + if (! $val) { + throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateFormatString()); + } + + return $val; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DecimalType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DecimalType.php new file mode 100644 index 0000000..b2d37f0 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DecimalType.php @@ -0,0 +1,35 @@ +getDecimalTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return $value; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/FloatType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/FloatType.php new file mode 100644 index 0000000..4988d72 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/FloatType.php @@ -0,0 +1,32 @@ +getFloatDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return $value === null ? null : (float) $value; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/GuidType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/GuidType.php new file mode 100644 index 0000000..dd45165 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/GuidType.php @@ -0,0 +1,35 @@ +getGuidTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return Types::GUID; + } + + /** + * {@inheritdoc} + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return ! $platform->hasNativeGuidType(); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/IntegerType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/IntegerType.php new file mode 100644 index 0000000..d7ab8fd --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/IntegerType.php @@ -0,0 +1,44 @@ +getIntegerTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return $value === null ? null : (int) $value; + } + + /** + * {@inheritdoc} + */ + public function getBindingType() + { + return ParameterType::INTEGER; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonArrayType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonArrayType.php new file mode 100644 index 0000000..bc468fb --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonArrayType.php @@ -0,0 +1,46 @@ +getJsonTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return null; + } + + $encoded = json_encode($value); + + if (json_last_error() !== JSON_ERROR_NONE) { + throw ConversionException::conversionFailedSerialization($value, 'json', json_last_error_msg()); + } + + return $encoded; + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value === '') { + return null; + } + + if (is_resource($value)) { + $value = stream_get_contents($value); + } + + $val = json_decode($value, true); + + if (json_last_error() !== JSON_ERROR_NONE) { + throw ConversionException::conversionFailed($value, $this->getName()); + } + + return $val; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return Types::JSON; + } + + /** + * {@inheritdoc} + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return ! $platform->hasNativeJsonType(); + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ObjectType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ObjectType.php new file mode 100644 index 0000000..82b1a75 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ObjectType.php @@ -0,0 +1,71 @@ +getClobTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + return serialize($value); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return null; + } + + $value = is_resource($value) ? stream_get_contents($value) : $value; + + set_error_handler(function (int $code, string $message) : bool { + throw ConversionException::conversionFailedUnserialization($this->getName(), $message); + }); + + try { + return unserialize($value); + } finally { + restore_error_handler(); + } + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return Types::OBJECT; + } + + /** + * {@inheritdoc} + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/PhpDateTimeMappingType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/PhpDateTimeMappingType.php new file mode 100644 index 0000000..4565850 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/PhpDateTimeMappingType.php @@ -0,0 +1,12 @@ +getClobTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + if (! $value) { + return null; + } + + return implode(',', $value); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return []; + } + + $value = is_resource($value) ? stream_get_contents($value) : $value; + + return explode(',', $value); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return Types::SIMPLE_ARRAY; + } + + /** + * {@inheritdoc} + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SmallIntType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SmallIntType.php new file mode 100644 index 0000000..5fa3cb7 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SmallIntType.php @@ -0,0 +1,44 @@ +getSmallIntTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return $value === null ? null : (int) $value; + } + + /** + * {@inheritdoc} + */ + public function getBindingType() + { + return ParameterType::INTEGER; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/StringType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/StringType.php new file mode 100644 index 0000000..e0d1a55 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/StringType.php @@ -0,0 +1,35 @@ +getVarcharTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function getDefaultLength(AbstractPlatform $platform) + { + return $platform->getVarcharDefaultLength(); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return Types::STRING; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TextType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TextType.php new file mode 100644 index 0000000..76dd7c4 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TextType.php @@ -0,0 +1,37 @@ +getClobTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return is_resource($value) ? stream_get_contents($value) : $value; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return Types::TEXT; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeImmutableType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeImmutableType.php new file mode 100644 index 0000000..cc43769 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeImmutableType.php @@ -0,0 +1,70 @@ +format($platform->getTimeFormatString()); + } + + throw ConversionException::conversionFailedInvalidType( + $value, + $this->getName(), + ['null', DateTimeImmutable::class] + ); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof DateTimeImmutable) { + return $value; + } + + $dateTime = DateTimeImmutable::createFromFormat('!' . $platform->getTimeFormatString(), $value); + + if (! $dateTime) { + throw ConversionException::conversionFailedFormat( + $value, + $this->getName(), + $platform->getTimeFormatString() + ); + } + + return $dateTime; + } + + /** + * {@inheritdoc} + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeType.php new file mode 100644 index 0000000..1eeb2c0 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeType.php @@ -0,0 +1,62 @@ +getTimeTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return $value; + } + + if ($value instanceof DateTimeInterface) { + return $value->format($platform->getTimeFormatString()); + } + + throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateTime']); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof DateTimeInterface) { + return $value; + } + + $val = DateTime::createFromFormat('!' . $platform->getTimeFormatString(), $value); + if (! $val) { + throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getTimeFormatString()); + } + + return $val; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php new file mode 100644 index 0000000..ac7ab7b --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php @@ -0,0 +1,384 @@ + ArrayType::class, + Types::BIGINT => BigIntType::class, + Types::BINARY => BinaryType::class, + Types::BLOB => BlobType::class, + Types::BOOLEAN => BooleanType::class, + Types::DATE_MUTABLE => DateType::class, + Types::DATE_IMMUTABLE => DateImmutableType::class, + Types::DATEINTERVAL => DateIntervalType::class, + Types::DATETIME_MUTABLE => DateTimeType::class, + Types::DATETIME_IMMUTABLE => DateTimeImmutableType::class, + Types::DATETIMETZ_MUTABLE => DateTimeTzType::class, + Types::DATETIMETZ_IMMUTABLE => DateTimeTzImmutableType::class, + Types::DECIMAL => DecimalType::class, + Types::FLOAT => FloatType::class, + Types::GUID => GuidType::class, + Types::INTEGER => IntegerType::class, + Types::JSON => JsonType::class, + Types::JSON_ARRAY => JsonArrayType::class, + Types::OBJECT => ObjectType::class, + Types::SIMPLE_ARRAY => SimpleArrayType::class, + Types::SMALLINT => SmallIntType::class, + Types::STRING => StringType::class, + Types::TEXT => TextType::class, + Types::TIME_MUTABLE => TimeType::class, + Types::TIME_IMMUTABLE => TimeImmutableType::class, + ]; + + /** @var TypeRegistry|null */ + private static $typeRegistry; + + /** + * @internal Do not instantiate directly - use {@see Type::addType()} method instead. + */ + final public 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. + * + * @deprecated Rely on information provided by the platform instead. + * + * @return int|null + */ + public function getDefaultLength(AbstractPlatform $platform) + { + return null; + } + + /** + * Gets the SQL declaration snippet for a field of this type. + * + * @param mixed[] $fieldDeclaration The field declaration. + * @param AbstractPlatform $platform The currently used database platform. + * + * @return string + */ + abstract public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform); + + /** + * Gets the name of this type. + * + * @return string + * + * @todo Needed? + */ + abstract public function getName(); + + /** + * @internal This method is only to be used within DBAL for forward compatibility purposes. Do not use directly. + */ + final public static function getTypeRegistry() : TypeRegistry + { + if (self::$typeRegistry === null) { + self::$typeRegistry = self::createTypeRegistry(); + } + + return self::$typeRegistry; + } + + private static function createTypeRegistry() : TypeRegistry + { + $registry = new TypeRegistry(); + + foreach (self::BUILTIN_TYPES_MAP as $name => $class) { + $registry->register($name, new $class()); + } + + return $registry; + } + + /** + * Factory method to create type instances. + * Type instances are implemented as flyweights. + * + * @param string $name The name of the type (as returned by getName()). + * + * @return \Doctrine\DBAL\Types\Type + * + * @throws DBALException + */ + public static function getType($name) + { + return self::getTypeRegistry()->get($name); + } + + /** + * Adds a custom type to the type map. + * + * @param string $name The name of the type. This should correspond to what getName() returns. + * @param string $className The class name of the custom type. + * + * @return void + * + * @throws DBALException + */ + public static function addType($name, $className) + { + self::getTypeRegistry()->register($name, new $className()); + } + + /** + * Checks if exists support for a type. + * + * @param string $name The name of the type. + * + * @return bool TRUE if type is supported; FALSE otherwise. + */ + public static function hasType($name) + { + return self::getTypeRegistry()->has($name); + } + + /** + * Overrides an already defined type to use a different implementation. + * + * @param string $name + * @param string $className + * + * @return void + * + * @throws DBALException + */ + public static function overrideType($name, $className) + { + self::getTypeRegistry()->override($name, new $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 {@link \Doctrine\DBAL\ParameterType} constants. + * + * @return int + */ + public function getBindingType() + { + return ParameterType::STRING; + } + + /** + * Gets the types array map which holds all registered types and the corresponding + * type class + * + * @return string[] + */ + public static function getTypesMap() + { + return array_map( + static function (Type $type) : string { + return get_class($type); + }, + self::getTypeRegistry()->getMap() + ); + } + + /** + * @deprecated Relying on string representation is discouraged and will be removed in DBAL 3.0. + * + * @return string + */ + public function __toString() + { + $type = static::class; + $position = strrpos($type, '\\'); + + if ($position !== false) { + $type = substr($type, $position); + } + + return str_replace('Type', '', $type); + } + + /** + * Does working with this column require SQL conversion functions? + * + * This is a metadata function that is required for example in the ORM. + * Usage of {@link convertToDatabaseValueSQL} and + * {@link convertToPHPValueSQL} works for any type and mostly + * does nothing. This method can additionally be used for optimization purposes. + * + * @return bool + */ + public function canRequireSQLConversion() + { + return false; + } + + /** + * Modifies the SQL expression (identifier, parameter) to convert to a database value. + * + * @param string $sqlExpr + * + * @return string + */ + public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform) + { + return $sqlExpr; + } + + /** + * Modifies the SQL expression (identifier, parameter) to convert to a PHP value. + * + * @param string $sqlExpr + * @param AbstractPlatform $platform + * + * @return string + */ + public function convertToPHPValueSQL($sqlExpr, $platform) + { + return $sqlExpr; + } + + /** + * Gets an array of database types that map to this Doctrine type. + * + * @return string[] + */ + public function getMappedDatabaseTypes(AbstractPlatform $platform) + { + return []; + } + + /** + * If this Doctrine Type maps to an already mapped database type, + * reverse schema engineering can't tell them apart. You need to mark + * one of those types as commented, which will have Doctrine use an SQL + * comment to typehint the actual Doctrine Type. + * + * @return bool + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return false; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TypeRegistry.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TypeRegistry.php new file mode 100644 index 0000000..7e8093c --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TypeRegistry.php @@ -0,0 +1,118 @@ + Map of type names and their corresponding flyweight objects. */ + private $instances = []; + + /** + * Finds a type by the given name. + * + * @throws DBALException + */ + public function get(string $name) : Type + { + if (! isset($this->instances[$name])) { + throw DBALException::unknownColumnType($name); + } + + return $this->instances[$name]; + } + + /** + * Finds a name for the given type. + * + * @throws DBALException + */ + public function lookupName(Type $type) : string + { + $name = $this->findTypeName($type); + + if ($name === null) { + throw DBALException::typeNotRegistered($type); + } + + return $name; + } + + /** + * Checks if there is a type of the given name. + */ + public function has(string $name) : bool + { + return isset($this->instances[$name]); + } + + /** + * Registers a custom type to the type map. + * + * @throws DBALException + */ + public function register(string $name, Type $type) : void + { + if (isset($this->instances[$name])) { + throw DBALException::typeExists($name); + } + + if ($this->findTypeName($type) !== null) { + throw DBALException::typeAlreadyRegistered($type); + } + + $this->instances[$name] = $type; + } + + /** + * Overrides an already defined type to use a different implementation. + * + * @throws DBALException + */ + public function override(string $name, Type $type) : void + { + if (! isset($this->instances[$name])) { + throw DBALException::typeNotFound($name); + } + + if (! in_array($this->findTypeName($type), [$name, null], true)) { + throw DBALException::typeAlreadyRegistered($type); + } + + $this->instances[$name] = $type; + } + + /** + * Gets the map of all registered types and their corresponding type instances. + * + * @internal + * + * @return array + */ + public function getMap() : array + { + return $this->instances; + } + + private function findTypeName(Type $type) : ?string + { + $name = array_search($type, $this->instances, true); + + if ($name === false) { + return null; + } + + return $name; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php new file mode 100644 index 0000000..f8d0cf9 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php @@ -0,0 +1,43 @@ +format($platform->getDateTimeFormatString()); + } + + throw ConversionException::conversionFailedInvalidType( + $value, + $this->getName(), + ['null', DateTimeImmutable::class] + ); + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof DateTimeImmutable) { + return $value; + } + + $dateTime = date_create_immutable($value); + + if (! $dateTime) { + throw ConversionException::conversionFailed($value, $this->getName()); + } + + return $dateTime; + } + + /** + * {@inheritdoc} + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeType.php new file mode 100644 index 0000000..1d9dbd3 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeType.php @@ -0,0 +1,34 @@ + 0 it is necessary to use this type. + */ +class VarDateTimeType extends DateTimeType +{ + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof DateTime) { + return $value; + } + + $val = date_create($value); + if (! $val) { + throw ConversionException::conversionFailed($value, $this->getName()); + } + + return $val; + } +} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Version.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Version.php new file mode 100644 index 0000000..2b1c0f2 --- /dev/null +++ b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Version.php @@ -0,0 +1,33 @@ +setName('doctrine:database:create') + ->setDescription('Creates the configured database') + ->addOption('shard', null, InputOption::VALUE_REQUIRED, 'The shard connection to use for this command') + ->addOption('connection', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command') + ->addOption('if-not-exists', null, InputOption::VALUE_NONE, 'Don\'t trigger an error, when the database already exists') + ->setHelp(<<%command.name% command creates the default connections database: + + php %command.full_name% + +You can also optionally specify the name of a connection to create the database for: + + php %command.full_name% --connection=default +EOT + ); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $connectionName = $input->getOption('connection'); + if (empty($connectionName)) { + $connectionName = $this->getDoctrine()->getDefaultConnectionName(); + } + $connection = $this->getDoctrineConnection($connectionName); + + $ifNotExists = $input->getOption('if-not-exists'); + + $params = $connection->getParams(); + if (isset($params['master'])) { + $params = $params['master']; + } + + // Cannot inject `shard` option in parent::getDoctrineConnection + // cause it will try to connect to a non-existing database + if (isset($params['shards'])) { + $shards = $params['shards']; + // Default select global + $params = array_merge($params, $params['global']); + unset($params['global']['dbname'], $params['global']['path'], $params['global']['url']); + if ($input->getOption('shard')) { + foreach ($shards as $i => $shard) { + if ($shard['id'] === (int) $input->getOption('shard')) { + // Select sharded database + $params = array_merge($params, $shard); + unset($params['shards'][$i]['dbname'], $params['shards'][$i]['path'], $params['shards'][$i]['url'], $params['id']); + break; + } + } + } + } + + $hasPath = isset($params['path']); + $name = $hasPath ? $params['path'] : (isset($params['dbname']) ? $params['dbname'] : false); + if (! $name) { + throw new InvalidArgumentException("Connection does not contain a 'path' or 'dbname' parameter and cannot be created."); + } + // Need to get rid of _every_ occurrence of dbname from connection configuration and we have already extracted all relevant info from url + unset($params['dbname'], $params['path'], $params['url']); + + $tmpConnection = DriverManager::getConnection($params); + $tmpConnection->connect($input->getOption('shard')); + $shouldNotCreateDatabase = $ifNotExists && in_array($name, $tmpConnection->getSchemaManager()->listDatabases()); + + // Only quote if we don't have a path + if (! $hasPath) { + $name = $tmpConnection->getDatabasePlatform()->quoteSingleIdentifier($name); + } + + $error = false; + try { + if ($shouldNotCreateDatabase) { + $output->writeln(sprintf('Database %s for connection named %s already exists. Skipped.', $name, $connectionName)); + } else { + $tmpConnection->getSchemaManager()->createDatabase($name); + $output->writeln(sprintf('Created database %s for connection named %s', $name, $connectionName)); + } + } catch (Exception $e) { + $output->writeln(sprintf('Could not create database %s for connection named %s', $name, $connectionName)); + $output->writeln(sprintf('%s', $e->getMessage())); + $error = true; + } + + $tmpConnection->close(); + + return $error ? 1 : 0; + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/DoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/DoctrineCommand.php new file mode 100644 index 0000000..02ffc23 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/DoctrineCommand.php @@ -0,0 +1,90 @@ +doctrine = $doctrine; + } + + /** + * get a doctrine entity generator + * + * @return EntityGenerator + */ + protected function getEntityGenerator() + { + $entityGenerator = new EntityGenerator(); + $entityGenerator->setGenerateAnnotations(false); + $entityGenerator->setGenerateStubMethods(true); + $entityGenerator->setRegenerateEntityIfExists(false); + $entityGenerator->setUpdateEntityIfExists(true); + $entityGenerator->setNumSpaces(4); + $entityGenerator->setAnnotationPrefix('ORM\\'); + + return $entityGenerator; + } + + /** + * Get a doctrine entity manager by symfony name. + * + * @param string $name + * @param int|null $shardId + * + * @return EntityManager + */ + protected function getEntityManager($name, $shardId = null) + { + $manager = $this->getDoctrine()->getManager($name); + + if ($shardId) { + if (! $manager->getConnection() instanceof PoolingShardConnection) { + throw new LogicException(sprintf("Connection of EntityManager '%s' must implement shards configuration.", $name)); + } + + $manager->getConnection()->connect($shardId); + } + + return $manager; + } + + /** + * Get a doctrine dbal connection by symfony name. + * + * @param string $name + * + * @return Connection + */ + protected function getDoctrineConnection($name) + { + return $this->getDoctrine()->getConnection($name); + } + + /** + * @return ManagerRegistry + */ + protected function getDoctrine() + { + return $this->doctrine; + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/DropDatabaseDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/DropDatabaseDoctrineCommand.php new file mode 100644 index 0000000..13c0272 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/DropDatabaseDoctrineCommand.php @@ -0,0 +1,128 @@ +setName('doctrine:database:drop') + ->setDescription('Drops the configured database') + ->addOption('shard', null, InputOption::VALUE_REQUIRED, 'The shard connection to use for this command') + ->addOption('connection', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command') + ->addOption('if-exists', null, InputOption::VALUE_NONE, 'Don\'t trigger an error, when the database doesn\'t exist') + ->addOption('force', null, InputOption::VALUE_NONE, 'Set this parameter to execute this action') + ->setHelp(<<%command.name% command drops the default connections database: + + php %command.full_name% + +The --force parameter has to be used to actually drop the database. + +You can also optionally specify the name of a connection to drop the database for: + + php %command.full_name% --connection=default + +Be careful: All data in a given database will be lost when executing this command. +EOT + ); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $connectionName = $input->getOption('connection'); + if (empty($connectionName)) { + $connectionName = $this->getDoctrine()->getDefaultConnectionName(); + } + $connection = $this->getDoctrineConnection($connectionName); + + $ifExists = $input->getOption('if-exists'); + + $params = $connection->getParams(); + if (isset($params['master'])) { + $params = $params['master']; + } + + if (isset($params['shards'])) { + $shards = $params['shards']; + // Default select global + $params = array_merge($params, $params['global']); + if ($input->getOption('shard')) { + foreach ($shards as $shard) { + if ($shard['id'] === (int) $input->getOption('shard')) { + // Select sharded database + $params = $shard; + unset($params['id']); + break; + } + } + } + } + + $name = isset($params['path']) ? $params['path'] : (isset($params['dbname']) ? $params['dbname'] : false); + if (! $name) { + throw new InvalidArgumentException("Connection does not contain a 'path' or 'dbname' parameter and cannot be dropped."); + } + unset($params['dbname'], $params['url']); + + if (! $input->getOption('force')) { + $output->writeln('ATTENTION: This operation should not be executed in a production environment.'); + $output->writeln(''); + $output->writeln(sprintf('Would drop the database %s for connection named %s.', $name, $connectionName)); + $output->writeln('Please run the operation with --force to execute'); + $output->writeln('All data will be lost!'); + + return self::RETURN_CODE_NO_FORCE; + } + + // Reopen connection without database name set + // as some vendors do not allow dropping the database connected to. + $connection->close(); + $connection = DriverManager::getConnection($params); + $shouldDropDatabase = ! $ifExists || in_array($name, $connection->getSchemaManager()->listDatabases()); + + // Only quote if we don't have a path + if (! isset($params['path'])) { + $name = $connection->getDatabasePlatform()->quoteSingleIdentifier($name); + } + + try { + if ($shouldDropDatabase) { + $connection->getSchemaManager()->dropDatabase($name); + $output->writeln(sprintf('Dropped database %s for connection named %s', $name, $connectionName)); + } else { + $output->writeln(sprintf('Database %s for connection named %s doesn\'t exist. Skipped.', $name, $connectionName)); + } + + return 0; + } catch (Exception $e) { + $output->writeln(sprintf('Could not drop database %s for connection named %s', $name, $connectionName)); + $output->writeln(sprintf('%s', $e->getMessage())); + + return self::RETURN_CODE_NOT_DROP; + } + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/ImportMappingDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/ImportMappingDoctrineCommand.php new file mode 100644 index 0000000..79c326e --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/ImportMappingDoctrineCommand.php @@ -0,0 +1,161 @@ +bundles = $bundles; + } + + /** + * {@inheritDoc} + */ + protected function configure() + { + $this + ->setName('doctrine:mapping:import') + ->addArgument('name', InputArgument::REQUIRED, 'The bundle or namespace to import the mapping information to') + ->addArgument('mapping-type', InputArgument::OPTIONAL, 'The mapping type to export the imported mapping information to') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command') + ->addOption('shard', null, InputOption::VALUE_REQUIRED, 'The shard connection to use for this command') + ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be mapped.') + ->addOption('force', null, InputOption::VALUE_NONE, 'Force to overwrite existing mapping files.') + ->addOption('path', null, InputOption::VALUE_REQUIRED, 'The path where the files would be generated (not used when a bundle is passed).') + ->setDescription('Imports mapping information from an existing database') + ->setHelp(<<%command.name% command imports mapping information +from an existing database: + +Generate annotation mappings into the src/ directory using App as the namespace: +php %command.full_name% App\\\Entity annotation --path=src/Entity + +Generate xml mappings into the config/doctrine/ directory using App as the namespace: +php %command.full_name% App\\\Entity xml --path=config/doctrine + +Generate XML mappings into a bundle: +php %command.full_name% "MyCustomBundle" xml + +You can also optionally specify which entity manager to import from with the +--em option: + +php %command.full_name% "MyCustomBundle" xml --em=default + +If you don't want to map every entity that can be found in the database, use the +--filter option. It will try to match the targeted mapped entity with the +provided pattern string. + +php %command.full_name% "MyCustomBundle" xml --filter=MyMatchedEntity + +Use the --force option, if you want to override existing mapping files: + +php %command.full_name% "MyCustomBundle" xml --force +EOT + ); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $type = $input->getArgument('mapping-type') ?: 'xml'; + if ($type === 'yaml') { + $type = 'yml'; + } + + $namespaceOrBundle = $input->getArgument('name'); + if (isset($this->bundles[$namespaceOrBundle])) { + $bundle = $this->getApplication()->getKernel()->getBundle($namespaceOrBundle); + $namespace = $bundle->getNamespace() . '\Entity'; + + $destPath = $bundle->getPath(); + if ($type === 'annotation') { + $destPath .= '/Entity'; + } else { + $destPath .= '/Resources/config/doctrine'; + } + } else { + // assume a namespace has been passed + $namespace = $namespaceOrBundle; + $destPath = $input->getOption('path'); + if ($destPath === null) { + throw new InvalidArgumentException('The --path option is required when passing a namespace (e.g. --path=src). If you intended to pass a bundle name, check your spelling.'); + } + } + + $cme = new ClassMetadataExporter(); + $exporter = $cme->getExporter($type); + $exporter->setOverwriteExistingFiles($input->getOption('force')); + + if ($type === 'annotation') { + $entityGenerator = $this->getEntityGenerator(); + $exporter->setEntityGenerator($entityGenerator); + } + + $em = $this->getEntityManager($input->getOption('em'), $input->getOption('shard')); + + $databaseDriver = new DatabaseDriver($em->getConnection()->getSchemaManager()); + $em->getConfiguration()->setMetadataDriverImpl($databaseDriver); + + $emName = $input->getOption('em'); + $emName = $emName ? $emName : 'default'; + + $cmf = new DisconnectedClassMetadataFactory(); + $cmf->setEntityManager($em); + $metadata = $cmf->getAllMetadata(); + $metadata = MetadataFilter::filter($metadata, $input->getOption('filter')); + if ($metadata) { + $output->writeln(sprintf('Importing mapping information from "%s" entity manager', $emName)); + foreach ($metadata as $class) { + $className = $class->name; + $class->name = $namespace . '\\' . $className; + if ($type === 'annotation') { + $path = $destPath . '/' . str_replace('\\', '.', $className) . '.php'; + } else { + $path = $destPath . '/' . str_replace('\\', '.', $className) . '.orm.' . $type; + } + $output->writeln(sprintf(' > writing %s', $path)); + $code = $exporter->exportClassMetadata($class); + $dir = dirname($path); + if (! is_dir($dir)) { + mkdir($dir, 0775, true); + } + file_put_contents($path, $code); + chmod($path, 0664); + } + + return 0; + } + + $output->writeln('Database does not have any mapping information.'); + $output->writeln(''); + + return 1; + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearMetadataCacheDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearMetadataCacheDoctrineCommand.php new file mode 100644 index 0000000..68a213e --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearMetadataCacheDoctrineCommand.php @@ -0,0 +1,37 @@ +setName('doctrine:cache:clear-metadata') + ->setDescription('Clears all metadata cache for an entity manager') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearQueryCacheDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearQueryCacheDoctrineCommand.php new file mode 100644 index 0000000..0c9bed8 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearQueryCacheDoctrineCommand.php @@ -0,0 +1,37 @@ +setName('doctrine:cache:clear-query') + ->setDescription('Clears all query cache for an entity manager') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearResultCacheDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearResultCacheDoctrineCommand.php new file mode 100644 index 0000000..985b1b8 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearResultCacheDoctrineCommand.php @@ -0,0 +1,37 @@ +setName('doctrine:cache:clear-result') + ->setDescription('Clears result cache for an entity manager') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/CollectionRegionDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/CollectionRegionDoctrineCommand.php new file mode 100644 index 0000000..c5df015 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/CollectionRegionDoctrineCommand.php @@ -0,0 +1,33 @@ +setName('doctrine:cache:clear-collection-region') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/ConvertMappingDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/ConvertMappingDoctrineCommand.php new file mode 100644 index 0000000..7060d7f --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/ConvertMappingDoctrineCommand.php @@ -0,0 +1,58 @@ +setName('doctrine:mapping:convert') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } + + /** + * @param string $toType + * @param string $destPath + * + * @return AbstractExporter + */ + protected function getExporter($toType, $destPath) + { + /** @var AbstractExporter $exporter */ + $exporter = parent::getExporter($toType, $destPath); + if ($exporter instanceof XmlExporter) { + $exporter->setExtension('.orm.xml'); + } elseif ($exporter instanceof YamlExporter) { + $exporter->setExtension('.orm.yml'); + } + + return $exporter; + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/CreateSchemaDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/CreateSchemaDoctrineCommand.php new file mode 100644 index 0000000..937ffea --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/CreateSchemaDoctrineCommand.php @@ -0,0 +1,38 @@ +setName('doctrine:schema:create') + ->setDescription('Executes (or dumps) the SQL needed to generate the database schema') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/DelegateCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/DelegateCommand.php new file mode 100644 index 0000000..c7f8fa7 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/DelegateCommand.php @@ -0,0 +1,96 @@ +isVersionCompatible(); + } + + /** + * @param string $entityManagerName + * + * @return Command + */ + protected function wrapCommand($entityManagerName) + { + if (! $this->isVersionCompatible()) { + throw new RuntimeException(sprintf('"%s" requires doctrine-orm "%s" or newer', $this->getName(), $this->getMinimalVersion())); + } + + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $entityManagerName); + $this->command->setApplication($this->getApplication()); + + return $this->command; + } + + /** + * {@inheritDoc} + */ + protected function configure() + { + if ($this->isVersionCompatible()) { + $this->command = $this->createCommand(); + + $this->setHelp($this->command->getHelp()); + $this->setDefinition($this->command->getDefinition()); + $this->setDescription($this->command->getDescription()); + } + + $this->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + return $this->wrapCommand($input->getOption('em'))->execute($input, $output); + } + + /** + * {@inheritDoc} + */ + protected function interact(InputInterface $input, OutputInterface $output) + { + $this->wrapCommand($input->getOption('em'))->interact($input, $output); + } + + /** + * {@inheritDoc} + */ + protected function initialize(InputInterface $input, OutputInterface $output) + { + $this->wrapCommand($input->getOption('em'))->initialize($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/DoctrineCommandHelper.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/DoctrineCommandHelper.php new file mode 100644 index 0000000..fee03f9 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/DoctrineCommandHelper.php @@ -0,0 +1,41 @@ +getKernel()->getContainer()->get('doctrine')->getManager($emName); + $helperSet = $application->getHelperSet(); + $helperSet->set(new ConnectionHelper($em->getConnection()), 'db'); + $helperSet->set(new EntityManagerHelper($em), 'em'); + } + + /** + * Convenience method to push the helper sets of a given connection into the application. + * + * @param string $connName + */ + public static function setApplicationConnection(Application $application, $connName) + { + $connection = $application->getKernel()->getContainer()->get('doctrine')->getConnection($connName); + $helperSet = $application->getHelperSet(); + $helperSet->set(new ConnectionHelper($connection), 'db'); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/DropSchemaDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/DropSchemaDoctrineCommand.php new file mode 100644 index 0000000..6ef60c2 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/DropSchemaDoctrineCommand.php @@ -0,0 +1,37 @@ +setName('doctrine:schema:drop') + ->setDescription('Executes (or dumps) the SQL needed to drop the current database schema') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/EnsureProductionSettingsDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/EnsureProductionSettingsDoctrineCommand.php new file mode 100644 index 0000000..f173d01 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/EnsureProductionSettingsDoctrineCommand.php @@ -0,0 +1,36 @@ +setName('doctrine:ensure-production-settings') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/EntityRegionCacheDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/EntityRegionCacheDoctrineCommand.php new file mode 100644 index 0000000..55ea3b8 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/EntityRegionCacheDoctrineCommand.php @@ -0,0 +1,33 @@ +setName('doctrine:cache:clear-entity-region') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/ImportDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/ImportDoctrineCommand.php new file mode 100644 index 0000000..cc04abf --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/ImportDoctrineCommand.php @@ -0,0 +1,36 @@ +setName('doctrine:database:import') + ->addOption('connection', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationConnection($this->getApplication(), $input->getOption('connection')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/InfoDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/InfoDoctrineCommand.php new file mode 100644 index 0000000..efc60b8 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/InfoDoctrineCommand.php @@ -0,0 +1,34 @@ +setName('doctrine:mapping:info') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/QueryRegionCacheDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/QueryRegionCacheDoctrineCommand.php new file mode 100644 index 0000000..b7b761b --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/QueryRegionCacheDoctrineCommand.php @@ -0,0 +1,33 @@ +setName('doctrine:cache:clear-query-region') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/RunDqlDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/RunDqlDoctrineCommand.php new file mode 100644 index 0000000..dc7d71d --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/RunDqlDoctrineCommand.php @@ -0,0 +1,53 @@ +setName('doctrine:query:dql') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command') + ->setHelp(<<%command.name% command executes the given DQL query and +outputs the results: + +php %command.full_name% "SELECT u FROM UserBundle:User u" + +You can also optional specify some additional options like what type of +hydration to use when executing the query: + +php %command.full_name% "SELECT u FROM UserBundle:User u" --hydrate=array + +Additionally you can specify the first result and maximum amount of results to +show: + +php %command.full_name% "SELECT u FROM UserBundle:User u" --first-result=0 --max-result=30 +EOT + ); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/RunSqlDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/RunSqlDoctrineCommand.php new file mode 100644 index 0000000..edcc782 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/RunSqlDoctrineCommand.php @@ -0,0 +1,43 @@ +setName('doctrine:query:sql') + ->addOption('connection', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command') + ->setHelp(<<%command.name% command executes the given SQL query and +outputs the results: + +php %command.full_name% "SELECT * FROM users" +EOT + ); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationConnection($this->getApplication(), $input->getOption('connection')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/UpdateSchemaDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/UpdateSchemaDoctrineCommand.php new file mode 100644 index 0000000..98f80cd --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/UpdateSchemaDoctrineCommand.php @@ -0,0 +1,37 @@ +setName('doctrine:schema:update') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/ValidateSchemaCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/ValidateSchemaCommand.php new file mode 100644 index 0000000..801dd74 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Command/Proxy/ValidateSchemaCommand.php @@ -0,0 +1,36 @@ +setName('doctrine:schema:validate') + ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); + + return parent::execute($input, $output); + } +} diff --git a/vendor/doctrine/doctrine-bundle/ConnectionFactory.php b/vendor/doctrine/doctrine-bundle/ConnectionFactory.php new file mode 100644 index 0000000..fdceb74 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/ConnectionFactory.php @@ -0,0 +1,134 @@ +typesConfig = $typesConfig; + } + + /** + * Create a connection by name. + * + * @param mixed[] $params + * @param string[]|Type[] $mappingTypes + * + * @return Connection + */ + public function createConnection(array $params, Configuration $config = null, EventManager $eventManager = null, array $mappingTypes = []) + { + if (! $this->initialized) { + $this->initializeTypes(); + } + + if (! isset($params['pdo']) && ! isset($params['charset'])) { + $wrapperClass = null; + if (isset($params['wrapperClass'])) { + if (! is_subclass_of($params['wrapperClass'], Connection::class)) { + throw DBALException::invalidWrapperClass($params['wrapperClass']); + } + + $wrapperClass = $params['wrapperClass']; + $params['wrapperClass'] = null; + } + + $connection = DriverManager::getConnection($params, $config, $eventManager); + $params = $connection->getParams(); + $driver = $connection->getDriver(); + + if ($driver instanceof AbstractMySQLDriver) { + $params['charset'] = 'utf8mb4'; + + if (! isset($params['defaultTableOptions']['collate'])) { + $params['defaultTableOptions']['collate'] = 'utf8mb4_unicode_ci'; + } + } else { + $params['charset'] = 'utf8'; + } + + if ($wrapperClass !== null) { + $params['wrapperClass'] = $wrapperClass; + } else { + $wrapperClass = Connection::class; + } + + $connection = new $wrapperClass($params, $driver, $config, $eventManager); + } else { + $connection = DriverManager::getConnection($params, $config, $eventManager); + } + + if (! empty($mappingTypes)) { + $platform = $this->getDatabasePlatform($connection); + foreach ($mappingTypes as $dbType => $doctrineType) { + $platform->registerDoctrineTypeMapping($dbType, $doctrineType); + } + } + + return $connection; + } + + /** + * Try to get the database platform. + * + * This could fail if types should be registered to an predefined/unused connection + * and the platform version is unknown. + * For details have a look at DoctrineBundle issue #673. + * + * @return AbstractPlatform + * + * @throws DBALException + */ + private function getDatabasePlatform(Connection $connection) + { + try { + return $connection->getDatabasePlatform(); + } catch (DriverException $driverException) { + throw new DBALException( + 'An exception occured while establishing a connection to figure out your platform version.' . PHP_EOL . + "You can circumvent this by setting a 'server_version' configuration value" . PHP_EOL . PHP_EOL . + 'For further information have a look at:' . PHP_EOL . + 'https://github.com/doctrine/DoctrineBundle/issues/673', + 0, + $driverException + ); + } + } + + /** + * initialize the types + */ + private function initializeTypes() + { + foreach ($this->typesConfig as $typeName => $typeConfig) { + if (Type::hasType($typeName)) { + Type::overrideType($typeName, $typeConfig['class']); + } else { + Type::addType($typeName, $typeConfig['class']); + } + } + + $this->initialized = true; + } +} diff --git a/vendor/doctrine/doctrine-bundle/Controller/ProfilerController.php b/vendor/doctrine/doctrine-bundle/Controller/ProfilerController.php new file mode 100644 index 0000000..1549d8a --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Controller/ProfilerController.php @@ -0,0 +1,120 @@ +container = $container; + } + + /** + * Renders the profiler panel for the given token. + * + * @param string $token The profiler token + * @param string $connectionName + * @param int $query + * + * @return Response A Response instance + */ + public function explainAction($token, $connectionName, $query) + { + /** @var Profiler $profiler */ + $profiler = $this->container->get('profiler'); + $profiler->disable(); + + $profile = $profiler->loadProfile($token); + $queries = $profile->getCollector('db')->getQueries(); + + if (! isset($queries[$connectionName][$query])) { + return new Response('This query does not exist.'); + } + + $query = $queries[$connectionName][$query]; + if (! $query['explainable']) { + return new Response('This query cannot be explained.'); + } + + /** @var Connection $connection */ + $connection = $this->container->get('doctrine')->getConnection($connectionName); + try { + $platform = $connection->getDatabasePlatform(); + if ($platform instanceof SqlitePlatform) { + $results = $this->explainSQLitePlatform($connection, $query); + } elseif ($platform instanceof SQLServerPlatform) { + $results = $this->explainSQLServerPlatform($connection, $query); + } else { + $results = $this->explainOtherPlatform($connection, $query); + } + } catch (Exception $e) { + return new Response('This query cannot be explained.'); + } + + return new Response($this->container->get('twig')->render('@Doctrine/Collector/explain.html.twig', [ + 'data' => $results, + 'query' => $query, + ])); + } + + private function explainSQLitePlatform(Connection $connection, $query) + { + $params = $query['params']; + + if ($params instanceof Data) { + $params = $params->getValue(true); + } + + return $connection->executeQuery('EXPLAIN QUERY PLAN ' . $query['sql'], $params, $query['types']) + ->fetchAll(PDO::FETCH_ASSOC); + } + + private function explainSQLServerPlatform(Connection $connection, $query) + { + if (stripos($query['sql'], 'SELECT') === 0) { + $sql = 'SET STATISTICS PROFILE ON; ' . $query['sql'] . '; SET STATISTICS PROFILE OFF;'; + } else { + $sql = 'SET SHOWPLAN_TEXT ON; GO; SET NOEXEC ON; ' . $query['sql'] . '; SET NOEXEC OFF; GO; SET SHOWPLAN_TEXT OFF;'; + } + + $params = $query['params']; + + if ($params instanceof Data) { + $params = $params->getValue(true); + } + + $stmt = $connection->executeQuery($sql, $params, $query['types']); + $stmt->nextRowset(); + + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + private function explainOtherPlatform(Connection $connection, $query) + { + $params = $query['params']; + + if ($params instanceof Data) { + $params = $params->getValue(true); + } + + return $connection->executeQuery('EXPLAIN ' . $query['sql'], $params, $query['types']) + ->fetchAll(PDO::FETCH_ASSOC); + } +} diff --git a/vendor/doctrine/doctrine-bundle/DataCollector/DoctrineDataCollector.php b/vendor/doctrine/doctrine-bundle/DataCollector/DoctrineDataCollector.php new file mode 100644 index 0000000..5d332a0 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/DataCollector/DoctrineDataCollector.php @@ -0,0 +1,260 @@ +registry = $registry; + + parent::__construct($registry); + } + + /** + * {@inheritdoc} + */ + public function collect(Request $request, Response $response, Throwable $exception = null) + { + parent::collect($request, $response, $exception); + + $errors = []; + $entities = []; + $caches = [ + 'enabled' => false, + 'log_enabled' => false, + 'counts' => [ + 'puts' => 0, + 'hits' => 0, + 'misses' => 0, + ], + 'regions' => [ + 'puts' => [], + 'hits' => [], + 'misses' => [], + ], + ]; + + /** @var EntityManager $em */ + foreach ($this->registry->getManagers() as $name => $em) { + $entities[$name] = []; + /** @var ClassMetadataFactory $factory */ + $factory = $em->getMetadataFactory(); + $validator = new SchemaValidator($em); + + /** @var ClassMetadataInfo $class */ + foreach ($factory->getLoadedMetadata() as $class) { + if (isset($entities[$name][$class->getName()])) { + continue; + } + + $classErrors = $validator->validateClass($class); + $entities[$name][$class->getName()] = $class->getName(); + + if (empty($classErrors)) { + continue; + } + + $errors[$name][$class->getName()] = $classErrors; + } + + /** @var Configuration $emConfig */ + $emConfig = $em->getConfiguration(); + $slcEnabled = $emConfig->isSecondLevelCacheEnabled(); + + if (! $slcEnabled) { + continue; + } + + $caches['enabled'] = true; + + /** @var $cacheConfiguration \Doctrine\ORM\Cache\CacheConfiguration */ + /** @var CacheLoggerChain $cacheLoggerChain */ + $cacheConfiguration = $emConfig->getSecondLevelCacheConfiguration(); + $cacheLoggerChain = $cacheConfiguration->getCacheLogger(); + + if (! $cacheLoggerChain || ! $cacheLoggerChain->getLogger('statistics')) { + continue; + } + + /** @var StatisticsCacheLogger $cacheLoggerStats */ + $cacheLoggerStats = $cacheLoggerChain->getLogger('statistics'); + $caches['log_enabled'] = true; + + $caches['counts']['puts'] += $cacheLoggerStats->getPutCount(); + $caches['counts']['hits'] += $cacheLoggerStats->getHitCount(); + $caches['counts']['misses'] += $cacheLoggerStats->getMissCount(); + + foreach ($cacheLoggerStats->getRegionsPut() as $key => $value) { + if (! isset($caches['regions']['puts'][$key])) { + $caches['regions']['puts'][$key] = 0; + } + + $caches['regions']['puts'][$key] += $value; + } + + foreach ($cacheLoggerStats->getRegionsHit() as $key => $value) { + if (! isset($caches['regions']['hits'][$key])) { + $caches['regions']['hits'][$key] = 0; + } + + $caches['regions']['hits'][$key] += $value; + } + + foreach ($cacheLoggerStats->getRegionsMiss() as $key => $value) { + if (! isset($caches['regions']['misses'][$key])) { + $caches['regions']['misses'][$key] = 0; + } + + $caches['regions']['misses'][$key] += $value; + } + } + + // Might be good idea to replicate this block in doctrine bridge so we can drop this from here after some time. + // This code is compatible with such change, because cloneVar is supposed to check if input is already cloned. + foreach ($this->data['queries'] as &$queries) { + foreach ($queries as &$query) { + $query['params'] = $this->cloneVar($query['params']); + // To be removed when the required minimum version of symfony/doctrine-bridge is >= 4.4 + $query['runnable'] = $query['runnable'] ?? true; + } + } + + $this->data['entities'] = $entities; + $this->data['errors'] = $errors; + $this->data['caches'] = $caches; + $this->groupedQueries = null; + } + + public function getEntities() + { + return $this->data['entities']; + } + + public function getMappingErrors() + { + return $this->data['errors']; + } + + public function getCacheHitsCount() + { + return $this->data['caches']['counts']['hits']; + } + + public function getCachePutsCount() + { + return $this->data['caches']['counts']['puts']; + } + + public function getCacheMissesCount() + { + return $this->data['caches']['counts']['misses']; + } + + public function getCacheEnabled() + { + return $this->data['caches']['enabled']; + } + + public function getCacheRegions() + { + return $this->data['caches']['regions']; + } + + public function getCacheCounts() + { + return $this->data['caches']['counts']; + } + + public function getInvalidEntityCount() + { + if ($this->invalidEntityCount === null) { + $this->invalidEntityCount = array_sum(array_map('count', $this->data['errors'])); + } + + return $this->invalidEntityCount; + } + + public function getGroupedQueries() + { + if ($this->groupedQueries !== null) { + return $this->groupedQueries; + } + + $this->groupedQueries = []; + $totalExecutionMS = 0; + foreach ($this->data['queries'] as $connection => $queries) { + $connectionGroupedQueries = []; + foreach ($queries as $i => $query) { + $key = $query['sql']; + if (! isset($connectionGroupedQueries[$key])) { + $connectionGroupedQueries[$key] = $query; + $connectionGroupedQueries[$key]['executionMS'] = 0; + $connectionGroupedQueries[$key]['count'] = 0; + $connectionGroupedQueries[$key]['index'] = $i; // "Explain query" relies on query index in 'queries'. + } + $connectionGroupedQueries[$key]['executionMS'] += $query['executionMS']; + $connectionGroupedQueries[$key]['count']++; + $totalExecutionMS += $query['executionMS']; + } + usort($connectionGroupedQueries, static function ($a, $b) { + if ($a['executionMS'] === $b['executionMS']) { + return 0; + } + + return $a['executionMS'] < $b['executionMS'] ? 1 : -1; + }); + $this->groupedQueries[$connection] = $connectionGroupedQueries; + } + + foreach ($this->groupedQueries as $connection => $queries) { + foreach ($queries as $i => $query) { + $this->groupedQueries[$connection][$i]['executionPercent'] = + $this->executionTimePercentage($query['executionMS'], $totalExecutionMS); + } + } + + return $this->groupedQueries; + } + + private function executionTimePercentage($executionTimeMS, $totalExecutionTimeMS) + { + if ($totalExecutionTimeMS === 0.0 || $totalExecutionTimeMS === 0) { + return 0; + } + + return $executionTimeMS / $totalExecutionTimeMS * 100; + } + + public function getGroupedQueryCount() + { + $count = 0; + foreach ($this->getGroupedQueries() as $connectionGroupedQueries) { + $count += count($connectionGroupedQueries); + } + + return $count; + } +} diff --git a/vendor/doctrine/doctrine-bundle/Dbal/BlacklistSchemaAssetFilter.php b/vendor/doctrine/doctrine-bundle/Dbal/BlacklistSchemaAssetFilter.php new file mode 100644 index 0000000..493e5fb --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Dbal/BlacklistSchemaAssetFilter.php @@ -0,0 +1,29 @@ +blacklist = $blacklist; + } + + public function __invoke($assetName) : bool + { + if ($assetName instanceof AbstractAsset) { + $assetName = $assetName->getName(); + } + + return ! in_array($assetName, $this->blacklist, true); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Dbal/Logging/BacktraceLogger.php b/vendor/doctrine/doctrine-bundle/Dbal/Logging/BacktraceLogger.php new file mode 100644 index 0000000..9cd2949 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Dbal/Logging/BacktraceLogger.php @@ -0,0 +1,23 @@ +queries[$this->currentQuery]['backtrace'] = $backtrace; + } +} diff --git a/vendor/doctrine/doctrine-bundle/Dbal/RegexSchemaAssetFilter.php b/vendor/doctrine/doctrine-bundle/Dbal/RegexSchemaAssetFilter.php new file mode 100644 index 0000000..2a9cbf9 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Dbal/RegexSchemaAssetFilter.php @@ -0,0 +1,25 @@ +filterExpression = $filterExpression; + } + + public function __invoke($assetName) : bool + { + if ($assetName instanceof AbstractAsset) { + $assetName = $assetName->getName(); + } + + return preg_match($this->filterExpression, $assetName); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Dbal/SchemaAssetsFilterManager.php b/vendor/doctrine/doctrine-bundle/Dbal/SchemaAssetsFilterManager.php new file mode 100644 index 0000000..7389a4e --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Dbal/SchemaAssetsFilterManager.php @@ -0,0 +1,31 @@ +schemaAssetFilters = $schemaAssetFilters; + } + + public function __invoke($assetName) : bool + { + foreach ($this->schemaAssetFilters as $schemaAssetFilter) { + if ($schemaAssetFilter($assetName) === false) { + return false; + } + } + + return true; + } +} diff --git a/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DbalSchemaFilterPass.php b/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DbalSchemaFilterPass.php new file mode 100644 index 0000000..7b53544 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DbalSchemaFilterPass.php @@ -0,0 +1,51 @@ +findTaggedServiceIds('doctrine.dbal.schema_filter'); + + $connectionFilters = []; + foreach ($filters as $id => $tagAttributes) { + foreach ($tagAttributes as $attributes) { + $name = isset($attributes['connection']) ? $attributes['connection'] : $container->getParameter('doctrine.default_connection'); + + if (! isset($connectionFilters[$name])) { + $connectionFilters[$name] = []; + } + + $connectionFilters[$name][] = new Reference($id); + } + } + + foreach ($connectionFilters as $name => $references) { + $configurationId = sprintf('doctrine.dbal.%s_connection.configuration', $name); + + if (! $container->hasDefinition($configurationId)) { + continue; + } + + $definition = new ChildDefinition('doctrine.dbal.schema_asset_filter_manager'); + $definition->setArgument(0, $references); + + $id = sprintf('doctrine.dbal.%s_schema_asset_filter_manager', $name); + $container->setDefinition($id, $definition); + $container->findDefinition($configurationId) + ->addMethodCall('setSchemaAssetsFilter', [new Reference($id)]); + } + } +} diff --git a/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DoctrineOrmMappingsPass.php b/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DoctrineOrmMappingsPass.php new file mode 100644 index 0000000..56e5eca --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DoctrineOrmMappingsPass.php @@ -0,0 +1,152 @@ +findTaggedServiceIds('doctrine.orm.entity_listener'); + + $lazyServiceReferencesByResolver = []; + + foreach ($resolvers as $id => $tagAttributes) { + foreach ($tagAttributes as $attributes) { + $name = isset($attributes['entity_manager']) ? $attributes['entity_manager'] : $container->getParameter('doctrine.default_entity_manager'); + $entityManager = sprintf('doctrine.orm.%s_entity_manager', $name); + + if (! $container->hasDefinition($entityManager)) { + continue; + } + + $resolverId = sprintf('doctrine.orm.%s_entity_listener_resolver', $name); + + if (! $container->has($resolverId)) { + continue; + } + + $resolver = $container->findDefinition($resolverId); + $resolver->setPublic(true); + + if (isset($attributes['entity']) && isset($attributes['event'])) { + $this->attachToListener($container, $name, $this->getConcreteDefinitionClass($container->findDefinition($id), $container, $id), $attributes); + } + + $resolverClass = $this->getResolverClass($resolver, $container, $resolverId); + $resolverSupportsLazyListeners = is_a($resolverClass, EntityListenerServiceResolver::class, true); + + $lazyByAttribute = isset($attributes['lazy']) && $attributes['lazy']; + if ($lazyByAttribute && ! $resolverSupportsLazyListeners) { + throw new InvalidArgumentException(sprintf( + 'Lazy-loaded entity listeners can only be resolved by a resolver implementing %s.', + EntityListenerServiceResolver::class + )); + } + + if (! isset($attributes['lazy']) && $resolverSupportsLazyListeners || $lazyByAttribute) { + $listener = $container->findDefinition($id); + + if ($listener->isAbstract()) { + throw new InvalidArgumentException(sprintf('The service "%s" must not be abstract as this entity listener is lazy-loaded.', $id)); + } + + $resolver->addMethodCall('registerService', [$this->getConcreteDefinitionClass($listener, $container, $id), $id]); + + // if the resolver uses the default class we will use a service locator for all listeners + if ($resolverClass === ContainerEntityListenerResolver::class) { + if (! isset($lazyServiceReferencesByResolver[$resolverId])) { + $lazyServiceReferencesByResolver[$resolverId] = []; + } + $lazyServiceReferencesByResolver[$resolverId][$id] = new Reference($id); + } else { + $listener->setPublic(true); + } + } else { + $resolver->addMethodCall('register', [new Reference($id)]); + } + } + } + + foreach ($lazyServiceReferencesByResolver as $resolverId => $listenerReferences) { + $container->findDefinition($resolverId)->setArgument(0, ServiceLocatorTagPass::register($container, $listenerReferences)); + } + } + + private function attachToListener(ContainerBuilder $container, $name, string $class, array $attributes) + { + $listenerId = sprintf('doctrine.orm.%s_listeners.attach_entity_listeners', $name); + + if (! $container->has($listenerId)) { + return; + } + + $args = [ + $attributes['entity'], + $class, + $attributes['event'], + ]; + + if (isset($attributes['method'])) { + $args[] = $attributes['method']; + } elseif (! method_exists($class, $attributes['event']) && method_exists($class, '__invoke')) { + $args[] = '__invoke'; + } + + $container->findDefinition($listenerId)->addMethodCall('addEntityListener', $args); + } + + private function getResolverClass(Definition $resolver, ContainerBuilder $container, string $id) : string + { + $resolverClass = $this->getConcreteDefinitionClass($resolver, $container, $id); + + if (substr($resolverClass, 0, 1) === '%') { + // resolve container parameter first + $resolverClass = $container->getParameterBag()->resolveValue($resolverClass); + } + + return $resolverClass; + } + + private function getConcreteDefinitionClass(Definition $definition, ContainerBuilder $container, string $id) : string + { + $class = $definition->getClass(); + if ($class) { + return $class; + } + + while ($definition instanceof ChildDefinition) { + $definition = $container->findDefinition($definition->getParent()); + + $class = $definition->getClass(); + if ($class) { + return $class; + } + } + + throw new InvalidArgumentException(sprintf('The service "%s" must define its class.', $id)); + } +} diff --git a/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/ServiceRepositoryCompilerPass.php b/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/ServiceRepositoryCompilerPass.php new file mode 100644 index 0000000..9881557 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/ServiceRepositoryCompilerPass.php @@ -0,0 +1,32 @@ +hasDefinition('doctrine.orm.container_repository_factory')) { + return; + } + + $locatorDef = $container->getDefinition('doctrine.orm.container_repository_factory'); + + $repoServiceIds = array_keys($container->findTaggedServiceIds(self::REPOSITORY_SERVICE_TAG)); + + $repoReferences = array_map(static function ($id) { + return new Reference($id); + }, $repoServiceIds); + + $ref = ServiceLocatorTagPass::register($container, array_combine($repoServiceIds, $repoReferences)); + $locatorDef->replaceArgument(0, $ref); + } +} diff --git a/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/WellKnownSchemaFilterPass.php b/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/WellKnownSchemaFilterPass.php new file mode 100644 index 0000000..8680df0 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/WellKnownSchemaFilterPass.php @@ -0,0 +1,59 @@ +getDefinitions() as $definition) { + if ($definition->isAbstract() || $definition->isSynthetic()) { + continue; + } + + switch ($definition->getClass()) { + case PdoAdapter::class: + $blacklist[] = $definition->getArguments()[3]['db_table'] ?? 'cache_items'; + break; + + case PdoSessionHandler::class: + $blacklist[] = $definition->getArguments()[1]['db_table'] ?? 'sessions'; + break; + + case PdoStore::class: + $blacklist[] = $definition->getArguments()[1]['db_table'] ?? 'lock_keys'; + break; + + case Connection::class: + $blacklist[] = $definition->getArguments()[0]['table_name'] ?? 'messenger_messages'; + break; + } + } + + if (! $blacklist) { + return; + } + + $definition = $container->getDefinition('doctrine.dbal.well_known_schema_asset_filter'); + $definition->replaceArgument(0, $blacklist); + + foreach (array_keys($container->getParameter('doctrine.connections')) as $name) { + $definition->addTag('doctrine.dbal.schema_filter', ['connection' => $name]); + } + } +} diff --git a/vendor/doctrine/doctrine-bundle/DependencyInjection/Configuration.php b/vendor/doctrine/doctrine-bundle/DependencyInjection/Configuration.php new file mode 100644 index 0000000..dac5a1b --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/DependencyInjection/Configuration.php @@ -0,0 +1,702 @@ +debug = (bool) $debug; + } + + /** + * {@inheritDoc} + */ + public function getConfigTreeBuilder() : TreeBuilder + { + $treeBuilder = new TreeBuilder('doctrine'); + $rootNode = $treeBuilder->getRootNode(); + + $this->addDbalSection($rootNode); + $this->addOrmSection($rootNode); + + return $treeBuilder; + } + + /** + * Add DBAL section to configuration tree + */ + private function addDbalSection(ArrayNodeDefinition $node) + { + $node + ->children() + ->arrayNode('dbal') + ->beforeNormalization() + ->ifTrue(static function ($v) { + return is_array($v) && ! array_key_exists('connections', $v) && ! array_key_exists('connection', $v); + }) + ->then(static function ($v) { + // Key that should not be rewritten to the connection config + $excludedKeys = ['default_connection' => true, 'types' => true, 'type' => true]; + $connection = []; + foreach ($v as $key => $value) { + if (isset($excludedKeys[$key])) { + continue; + } + $connection[$key] = $v[$key]; + unset($v[$key]); + } + $v['default_connection'] = isset($v['default_connection']) ? (string) $v['default_connection'] : 'default'; + $v['connections'] = [$v['default_connection'] => $connection]; + + return $v; + }) + ->end() + ->children() + ->scalarNode('default_connection')->end() + ->end() + ->fixXmlConfig('type') + ->children() + ->arrayNode('types') + ->useAttributeAsKey('name') + ->prototype('array') + ->beforeNormalization() + ->ifString() + ->then(static function ($v) { + return ['class' => $v]; + }) + ->end() + ->children() + ->scalarNode('class')->isRequired()->end() + ->booleanNode('commented')->setDeprecated()->end() + ->end() + ->end() + ->end() + ->end() + ->fixXmlConfig('connection') + ->append($this->getDbalConnectionsNode()) + ->end(); + } + + /** + * Return the dbal connections node + * + * @return ArrayNodeDefinition + */ + private function getDbalConnectionsNode() + { + $treeBuilder = new TreeBuilder('connections'); + $node = $treeBuilder->getRootNode(); + + /** @var ArrayNodeDefinition $connectionNode */ + $connectionNode = $node + ->requiresAtLeastOneElement() + ->useAttributeAsKey('name') + ->prototype('array'); + + $this->configureDbalDriverNode($connectionNode); + + $connectionNode + ->fixXmlConfig('option') + ->fixXmlConfig('mapping_type') + ->fixXmlConfig('slave') + ->fixXmlConfig('shard') + ->fixXmlConfig('default_table_option') + ->children() + ->scalarNode('driver')->defaultValue('pdo_mysql')->end() + ->scalarNode('platform_service')->end() + ->booleanNode('auto_commit')->end() + ->scalarNode('schema_filter')->end() + ->booleanNode('logging')->defaultValue($this->debug)->end() + ->booleanNode('profiling')->defaultValue($this->debug)->end() + ->booleanNode('profiling_collect_backtrace') + ->defaultValue(false) + ->info('Enables collecting backtraces when profiling is enabled') + ->end() + ->scalarNode('server_version')->end() + ->scalarNode('driver_class')->end() + ->scalarNode('wrapper_class')->end() + ->scalarNode('shard_manager_class')->end() + ->scalarNode('shard_choser')->end() + ->scalarNode('shard_choser_service')->end() + ->booleanNode('keep_slave')->end() + ->arrayNode('options') + ->useAttributeAsKey('key') + ->prototype('variable')->end() + ->end() + ->arrayNode('mapping_types') + ->useAttributeAsKey('name') + ->prototype('scalar')->end() + ->end() + ->arrayNode('default_table_options') + ->info("This option is used by the schema-tool and affects generated SQL. Possible keys include 'charset','collate', and 'engine'.") + ->useAttributeAsKey('name') + ->prototype('scalar')->end() + ->end() + ->end(); + + $slaveNode = $connectionNode + ->children() + ->arrayNode('slaves') + ->useAttributeAsKey('name') + ->prototype('array'); + $this->configureDbalDriverNode($slaveNode); + + $shardNode = $connectionNode + ->children() + ->arrayNode('shards') + ->prototype('array') + ->children() + ->integerNode('id') + ->min(1) + ->isRequired() + ->end() + ->end(); + $this->configureDbalDriverNode($shardNode); + + return $node; + } + + /** + * Adds config keys related to params processed by the DBAL drivers + * + * These keys are available for slave configurations too. + */ + private function configureDbalDriverNode(ArrayNodeDefinition $node) + { + $node + ->children() + ->scalarNode('url')->info('A URL with connection information; any parameter value parsed from this string will override explicitly set parameters')->end() + ->scalarNode('dbname')->end() + ->scalarNode('host')->defaultValue('localhost')->end() + ->scalarNode('port')->defaultNull()->end() + ->scalarNode('user')->defaultValue('root')->end() + ->scalarNode('password')->defaultNull()->end() + ->scalarNode('application_name')->end() + ->scalarNode('charset')->end() + ->scalarNode('path')->end() + ->booleanNode('memory')->end() + ->scalarNode('unix_socket')->info('The unix socket to use for MySQL')->end() + ->booleanNode('persistent')->info('True to use as persistent connection for the ibm_db2 driver')->end() + ->scalarNode('protocol')->info('The protocol to use for the ibm_db2 driver (default to TCPIP if ommited)')->end() + ->booleanNode('service') + ->info('True to use SERVICE_NAME as connection parameter instead of SID for Oracle') + ->end() + ->scalarNode('servicename') + ->info( + 'Overrules dbname parameter if given and used as SERVICE_NAME or SID connection parameter ' . + 'for Oracle depending on the service parameter.' + ) + ->end() + ->scalarNode('sessionMode') + ->info('The session mode to use for the oci8 driver') + ->end() + ->scalarNode('server') + ->info('The name of a running database server to connect to for SQL Anywhere.') + ->end() + ->scalarNode('default_dbname') + ->info( + 'Override the default database (postgres) to connect to for PostgreSQL connexion.' + ) + ->end() + ->scalarNode('sslmode') + ->info( + 'Determines whether or with what priority a SSL TCP/IP connection will be negotiated with ' . + 'the server for PostgreSQL.' + ) + ->end() + ->scalarNode('sslrootcert') + ->info( + 'The name of a file containing SSL certificate authority (CA) certificate(s). ' . + 'If the file exists, the server\'s certificate will be verified to be signed by one of these authorities.' + ) + ->end() + ->scalarNode('sslcert') + ->info( + 'The path to the SSL client certificate file for PostgreSQL.' + ) + ->end() + ->scalarNode('sslkey') + ->info( + 'The path to the SSL client key file for PostgreSQL.' + ) + ->end() + ->scalarNode('sslcrl') + ->info( + 'The file name of the SSL certificate revocation list for PostgreSQL.' + ) + ->end() + ->booleanNode('pooled')->info('True to use a pooled server with the oci8/pdo_oracle driver')->end() + ->booleanNode('MultipleActiveResultSets')->info('Configuring MultipleActiveResultSets for the pdo_sqlsrv driver')->end() + ->booleanNode('use_savepoints')->info('Use savepoints for nested transactions')->end() + ->scalarNode('instancename') + ->info( + 'Optional parameter, complete whether to add the INSTANCE_NAME parameter in the connection.' . + ' It is generally used to connect to an Oracle RAC server to select the name' . + ' of a particular instance.' + ) + ->end() + ->scalarNode('connectstring') + ->info( + 'Complete Easy Connect connection descriptor, see https://docs.oracle.com/database/121/NETAG/naming.htm.' . + 'When using this option, you will still need to provide the user and password parameters, but the other ' . + 'parameters will no longer be used. Note that when using this parameter, the getHost and getPort methods' . + ' from Doctrine\DBAL\Connection will no longer function as expected.' + ) + ->end() + ->end() + ->beforeNormalization() + ->ifTrue(static function ($v) { + return ! isset($v['sessionMode']) && isset($v['session_mode']); + }) + ->then(static function ($v) { + $v['sessionMode'] = $v['session_mode']; + unset($v['session_mode']); + + return $v; + }) + ->end() + ->beforeNormalization() + ->ifTrue(static function ($v) { + return ! isset($v['MultipleActiveResultSets']) && isset($v['multiple_active_result_sets']); + }) + ->then(static function ($v) { + $v['MultipleActiveResultSets'] = $v['multiple_active_result_sets']; + unset($v['multiple_active_result_sets']); + + return $v; + }) + ->end(); + } + + /** + * Add the ORM section to configuration tree + */ + private function addOrmSection(ArrayNodeDefinition $node) + { + $node + ->children() + ->arrayNode('orm') + ->beforeNormalization() + ->ifTrue(static function ($v) { + if (! empty($v) && ! class_exists(EntityManager::class)) { + throw new LogicException('The doctrine/orm package is required when the doctrine.orm config is set.'); + } + + return $v === null || (is_array($v) && ! array_key_exists('entity_managers', $v) && ! array_key_exists('entity_manager', $v)); + }) + ->then(static function ($v) { + $v = (array) $v; + // Key that should not be rewritten to the connection config + $excludedKeys = [ + 'default_entity_manager' => true, + 'auto_generate_proxy_classes' => true, + 'proxy_dir' => true, + 'proxy_namespace' => true, + 'resolve_target_entities' => true, + 'resolve_target_entity' => true, + ]; + $entityManager = []; + foreach ($v as $key => $value) { + if (isset($excludedKeys[$key])) { + continue; + } + $entityManager[$key] = $v[$key]; + unset($v[$key]); + } + $v['default_entity_manager'] = isset($v['default_entity_manager']) ? (string) $v['default_entity_manager'] : 'default'; + $v['entity_managers'] = [$v['default_entity_manager'] => $entityManager]; + + return $v; + }) + ->end() + ->children() + ->scalarNode('default_entity_manager')->end() + ->scalarNode('auto_generate_proxy_classes')->defaultValue(false) + ->info('Auto generate mode possible values are: "NEVER", "ALWAYS", "FILE_NOT_EXISTS", "EVAL"') + ->validate() + ->ifTrue(function ($v) { + $generationModes = $this->getAutoGenerateModes(); + + if (is_int($v) && in_array($v, $generationModes['values']/*array(0, 1, 2, 3)*/)) { + return false; + } + if (is_bool($v)) { + return false; + } + if (is_string($v)) { + if (in_array(strtoupper($v), $generationModes['names']/*array('NEVER', 'ALWAYS', 'FILE_NOT_EXISTS', 'EVAL')*/)) { + return false; + } + } + + return true; + }) + ->thenInvalid('Invalid auto generate mode value %s') + ->end() + ->validate() + ->ifString() + ->then(static function ($v) { + return constant('Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_' . strtoupper($v)); + }) + ->end() + ->end() + ->scalarNode('proxy_dir')->defaultValue('%kernel.cache_dir%/doctrine/orm/Proxies')->end() + ->scalarNode('proxy_namespace')->defaultValue('Proxies')->end() + ->end() + ->fixXmlConfig('entity_manager') + ->append($this->getOrmEntityManagersNode()) + ->fixXmlConfig('resolve_target_entity', 'resolve_target_entities') + ->append($this->getOrmTargetEntityResolverNode()) + ->end() + ->end(); + } + + /** + * Return ORM target entity resolver node + * + * @return NodeDefinition + */ + private function getOrmTargetEntityResolverNode() + { + $treeBuilder = new TreeBuilder('resolve_target_entities'); + $node = $treeBuilder->getRootNode(); + + $node + ->useAttributeAsKey('interface') + ->prototype('scalar') + ->cannotBeEmpty() + ->end(); + + return $node; + } + + /** + * Return ORM entity listener node + * + * @return NodeDefinition + */ + private function getOrmEntityListenersNode() + { + $treeBuilder = new TreeBuilder('entity_listeners'); + $node = $treeBuilder->getRootNode(); + + $normalizer = static function ($mappings) { + $entities = []; + + foreach ($mappings as $entityClass => $mapping) { + $listeners = []; + + foreach ($mapping as $listenerClass => $listenerEvent) { + $events = []; + + foreach ($listenerEvent as $eventType => $eventMapping) { + if ($eventMapping === null) { + $eventMapping = [null]; + } + + foreach ($eventMapping as $method) { + $events[] = [ + 'type' => $eventType, + 'method' => $method, + ]; + } + } + + $listeners[] = [ + 'class' => $listenerClass, + 'event' => $events, + ]; + } + + $entities[] = [ + 'class' => $entityClass, + 'listener' => $listeners, + ]; + } + + return ['entities' => $entities]; + }; + + $node + ->beforeNormalization() + // Yaml normalization + ->ifTrue(static function ($v) { + return is_array(reset($v)) && is_string(key(reset($v))); + }) + ->then($normalizer) + ->end() + ->fixXmlConfig('entity', 'entities') + ->children() + ->arrayNode('entities') + ->useAttributeAsKey('class') + ->prototype('array') + ->fixXmlConfig('listener') + ->children() + ->arrayNode('listeners') + ->useAttributeAsKey('class') + ->prototype('array') + ->fixXmlConfig('event') + ->children() + ->arrayNode('events') + ->prototype('array') + ->children() + ->scalarNode('type')->end() + ->scalarNode('method')->defaultNull()->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end(); + + return $node; + } + + /** + * Return ORM entity manager node + * + * @return ArrayNodeDefinition + */ + private function getOrmEntityManagersNode() + { + $treeBuilder = new TreeBuilder('entity_managers'); + $node = $treeBuilder->getRootNode(); + + $node + ->requiresAtLeastOneElement() + ->useAttributeAsKey('name') + ->prototype('array') + ->addDefaultsIfNotSet() + ->append($this->getOrmCacheDriverNode('query_cache_driver')) + ->append($this->getOrmCacheDriverNode('metadata_cache_driver')) + ->append($this->getOrmCacheDriverNode('result_cache_driver')) + ->append($this->getOrmEntityListenersNode()) + ->children() + ->scalarNode('connection')->end() + ->scalarNode('class_metadata_factory_name')->defaultValue('Doctrine\ORM\Mapping\ClassMetadataFactory')->end() + ->scalarNode('default_repository_class')->defaultValue('Doctrine\ORM\EntityRepository')->end() + ->scalarNode('auto_mapping')->defaultFalse()->end() + ->scalarNode('naming_strategy')->defaultValue('doctrine.orm.naming_strategy.default')->end() + ->scalarNode('quote_strategy')->defaultValue('doctrine.orm.quote_strategy.default')->end() + ->scalarNode('entity_listener_resolver')->defaultNull()->end() + ->scalarNode('repository_factory')->defaultValue('doctrine.orm.container_repository_factory')->end() + ->end() + ->children() + ->arrayNode('second_level_cache') + ->children() + ->append($this->getOrmCacheDriverNode('region_cache_driver')) + ->scalarNode('region_lock_lifetime')->defaultValue(60)->end() + ->booleanNode('log_enabled')->defaultValue($this->debug)->end() + ->scalarNode('region_lifetime')->defaultValue(0)->end() + ->booleanNode('enabled')->defaultValue(true)->end() + ->scalarNode('factory')->end() + ->end() + ->fixXmlConfig('region') + ->children() + ->arrayNode('regions') + ->useAttributeAsKey('name') + ->prototype('array') + ->children() + ->append($this->getOrmCacheDriverNode('cache_driver')) + ->scalarNode('lock_path')->defaultValue('%kernel.cache_dir%/doctrine/orm/slc/filelock')->end() + ->scalarNode('lock_lifetime')->defaultValue(60)->end() + ->scalarNode('type')->defaultValue('default')->end() + ->scalarNode('lifetime')->defaultValue(0)->end() + ->scalarNode('service')->end() + ->scalarNode('name')->end() + ->end() + ->end() + ->end() + ->end() + ->fixXmlConfig('logger') + ->children() + ->arrayNode('loggers') + ->useAttributeAsKey('name') + ->prototype('array') + ->children() + ->scalarNode('name')->end() + ->scalarNode('service')->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->fixXmlConfig('hydrator') + ->children() + ->arrayNode('hydrators') + ->useAttributeAsKey('name') + ->prototype('scalar')->end() + ->end() + ->end() + ->fixXmlConfig('mapping') + ->children() + ->arrayNode('mappings') + ->useAttributeAsKey('name') + ->prototype('array') + ->beforeNormalization() + ->ifString() + ->then(static function ($v) { + return ['type' => $v]; + }) + ->end() + ->treatNullLike([]) + ->treatFalseLike(['mapping' => false]) + ->performNoDeepMerging() + ->children() + ->scalarNode('mapping')->defaultValue(true)->end() + ->scalarNode('type')->end() + ->scalarNode('dir')->end() + ->scalarNode('alias')->end() + ->scalarNode('prefix')->end() + ->booleanNode('is_bundle')->end() + ->end() + ->end() + ->end() + ->arrayNode('dql') + ->fixXmlConfig('string_function') + ->fixXmlConfig('numeric_function') + ->fixXmlConfig('datetime_function') + ->children() + ->arrayNode('string_functions') + ->useAttributeAsKey('name') + ->prototype('scalar')->end() + ->end() + ->arrayNode('numeric_functions') + ->useAttributeAsKey('name') + ->prototype('scalar')->end() + ->end() + ->arrayNode('datetime_functions') + ->useAttributeAsKey('name') + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() + ->fixXmlConfig('filter') + ->children() + ->arrayNode('filters') + ->info('Register SQL Filters in the entity manager') + ->useAttributeAsKey('name') + ->prototype('array') + ->beforeNormalization() + ->ifString() + ->then(static function ($v) { + return ['class' => $v]; + }) + ->end() + ->beforeNormalization() + // The content of the XML node is returned as the "value" key so we need to rename it + ->ifTrue(static function ($v) { + return is_array($v) && isset($v['value']); + }) + ->then(static function ($v) { + $v['class'] = $v['value']; + unset($v['value']); + + return $v; + }) + ->end() + ->fixXmlConfig('parameter') + ->children() + ->scalarNode('class')->isRequired()->end() + ->booleanNode('enabled')->defaultFalse()->end() + ->arrayNode('parameters') + ->useAttributeAsKey('name') + ->prototype('variable')->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end(); + + return $node; + } + + /** + * Return a ORM cache driver node for an given entity manager + * + * @param string $name + * + * @return ArrayNodeDefinition + */ + private function getOrmCacheDriverNode($name) + { + $treeBuilder = new TreeBuilder($name); + $node = $treeBuilder->getRootNode(); + + $node + ->addDefaultsIfNotSet() + ->beforeNormalization() + ->ifString() + ->then(static function ($v) : array { + return ['type' => $v]; + }) + ->end() + ->children() + ->scalarNode('type')->defaultNull()->end() + ->scalarNode('id')->end() + ->scalarNode('pool')->end() + ->end(); + + return $node; + } + + /** + * Find proxy auto generate modes for their names and int values + * + * @return array + */ + private function getAutoGenerateModes() + { + $constPrefix = 'AUTOGENERATE_'; + $prefixLen = strlen($constPrefix); + $refClass = new ReflectionClass('Doctrine\Common\Proxy\AbstractProxyFactory'); + $constsArray = $refClass->getConstants(); + $namesArray = []; + $valuesArray = []; + + foreach ($constsArray as $key => $value) { + if (strpos($key, $constPrefix) !== 0) { + continue; + } + + $namesArray[] = substr($key, $prefixLen); + $valuesArray[] = (int) $value; + } + + return [ + 'names' => $namesArray, + 'values' => $valuesArray, + ]; + } +} diff --git a/vendor/doctrine/doctrine-bundle/DependencyInjection/DoctrineExtension.php b/vendor/doctrine/doctrine-bundle/DependencyInjection/DoctrineExtension.php new file mode 100644 index 0000000..1a95a72 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/DependencyInjection/DoctrineExtension.php @@ -0,0 +1,870 @@ +getConfiguration($configs, $container); + $config = $this->processConfiguration($configuration, $configs); + + if (! empty($config['dbal'])) { + $this->dbalLoad($config['dbal'], $container); + + $this->loadMessengerServices($container); + } + + if (empty($config['orm'])) { + return; + } + + if (empty($config['dbal'])) { + throw new LogicException('Configuring the ORM layer requires to configure the DBAL layer as well.'); + } + + $this->ormLoad($config['orm'], $container); + } + + /** + * Loads the DBAL configuration. + * + * Usage example: + * + * + * + * @param array $config An array of configuration settings + * @param ContainerBuilder $container A ContainerBuilder instance + */ + protected function dbalLoad(array $config, ContainerBuilder $container) + { + $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); + $loader->load('dbal.xml'); + + if (empty($config['default_connection'])) { + $keys = array_keys($config['connections']); + $config['default_connection'] = reset($keys); + } + + $this->defaultConnection = $config['default_connection']; + + $container->setAlias('database_connection', sprintf('doctrine.dbal.%s_connection', $this->defaultConnection)); + $container->getAlias('database_connection')->setPublic(true); + $container->setAlias('doctrine.dbal.event_manager', new Alias(sprintf('doctrine.dbal.%s_connection.event_manager', $this->defaultConnection), false)); + + $container->setParameter('doctrine.dbal.connection_factory.types', $config['types']); + + $connections = []; + + foreach (array_keys($config['connections']) as $name) { + $connections[$name] = sprintf('doctrine.dbal.%s_connection', $name); + } + + $container->setParameter('doctrine.connections', $connections); + $container->setParameter('doctrine.default_connection', $this->defaultConnection); + + foreach ($config['connections'] as $name => $connection) { + $this->loadDbalConnection($name, $connection, $container); + } + } + + /** + * Loads a configured DBAL connection. + * + * @param string $name The name of the connection + * @param array $connection A dbal connection configuration. + * @param ContainerBuilder $container A ContainerBuilder instance + */ + protected function loadDbalConnection($name, array $connection, ContainerBuilder $container) + { + $configuration = $container->setDefinition(sprintf('doctrine.dbal.%s_connection.configuration', $name), new ChildDefinition('doctrine.dbal.connection.configuration')); + $logger = null; + if ($connection['logging']) { + $logger = new Reference('doctrine.dbal.logger'); + } + unset($connection['logging']); + + if ($connection['profiling']) { + $profilingAbstractId = $connection['profiling_collect_backtrace'] ? + 'doctrine.dbal.logger.backtrace' : + 'doctrine.dbal.logger.profiling'; + + $profilingLoggerId = $profilingAbstractId . '.' . $name; + $container->setDefinition($profilingLoggerId, new ChildDefinition($profilingAbstractId)); + $profilingLogger = new Reference($profilingLoggerId); + $container->getDefinition('data_collector.doctrine')->addMethodCall('addLogger', [$name, $profilingLogger]); + + if ($logger !== null) { + $chainLogger = new ChildDefinition('doctrine.dbal.logger.chain'); + $chainLogger->addMethodCall('addLogger', [$profilingLogger]); + + $loggerId = 'doctrine.dbal.logger.chain.' . $name; + $container->setDefinition($loggerId, $chainLogger); + $logger = new Reference($loggerId); + } else { + $logger = $profilingLogger; + } + } + unset($connection['profiling'], $connection['profiling_collect_backtrace']); + + if (isset($connection['auto_commit'])) { + $configuration->addMethodCall('setAutoCommit', [$connection['auto_commit']]); + } + + unset($connection['auto_commit']); + + if (isset($connection['schema_filter']) && $connection['schema_filter']) { + $definition = new Definition(RegexSchemaAssetFilter::class, [$connection['schema_filter']]); + $definition->addTag('doctrine.dbal.schema_filter', ['connection' => $name]); + $container->setDefinition(sprintf('doctrine.dbal.%s_regex_schema_filter', $name), $definition); + } + + unset($connection['schema_filter']); + + if ($logger) { + $configuration->addMethodCall('setSQLLogger', [$logger]); + } + + // event manager + $container->setDefinition(sprintf('doctrine.dbal.%s_connection.event_manager', $name), new ChildDefinition('doctrine.dbal.connection.event_manager')); + + // connection + $options = $this->getConnectionOptions($connection); + + $def = $container + ->setDefinition(sprintf('doctrine.dbal.%s_connection', $name), new ChildDefinition('doctrine.dbal.connection')) + ->setPublic(true) + ->setArguments([ + $options, + new Reference(sprintf('doctrine.dbal.%s_connection.configuration', $name)), + new Reference(sprintf('doctrine.dbal.%s_connection.event_manager', $name)), + $connection['mapping_types'], + ]); + + // Set class in case "wrapper_class" option was used to assist IDEs + if (isset($options['wrapperClass'])) { + $def->setClass($options['wrapperClass']); + } + + if (! empty($connection['use_savepoints'])) { + $def->addMethodCall('setNestTransactionsWithSavepoints', [$connection['use_savepoints']]); + } + + // Create a shard_manager for this connection + if (! isset($options['shards'])) { + return; + } + + $shardManagerDefinition = new Definition($options['shardManagerClass'], [new Reference(sprintf('doctrine.dbal.%s_connection', $name))]); + $container->setDefinition(sprintf('doctrine.dbal.%s_shard_manager', $name), $shardManagerDefinition); + } + + protected function getConnectionOptions($connection) + { + $options = $connection; + + if (isset($options['platform_service'])) { + $options['platform'] = new Reference($options['platform_service']); + unset($options['platform_service']); + } + unset($options['mapping_types']); + + if (isset($options['shard_choser_service'])) { + $options['shard_choser'] = new Reference($options['shard_choser_service']); + unset($options['shard_choser_service']); + } + + foreach ([ + 'options' => 'driverOptions', + 'driver_class' => 'driverClass', + 'wrapper_class' => 'wrapperClass', + 'keep_slave' => 'keepSlave', + 'shard_choser' => 'shardChoser', + 'shard_manager_class' => 'shardManagerClass', + 'server_version' => 'serverVersion', + 'default_table_options' => 'defaultTableOptions', + ] as $old => $new) { + if (! isset($options[$old])) { + continue; + } + + $options[$new] = $options[$old]; + unset($options[$old]); + } + + if (! empty($options['slaves']) && ! empty($options['shards'])) { + throw new InvalidArgumentException('Sharding and master-slave connection cannot be used together'); + } + + if (! empty($options['slaves'])) { + $nonRewrittenKeys = [ + 'driver' => true, + 'driverOptions' => true, + 'driverClass' => true, + 'wrapperClass' => true, + 'keepSlave' => true, + 'shardChoser' => true, + 'platform' => true, + 'slaves' => true, + 'master' => true, + 'shards' => true, + 'serverVersion' => true, + 'defaultTableOptions' => true, + // included by safety but should have been unset already + 'logging' => true, + 'profiling' => true, + 'mapping_types' => true, + 'platform_service' => true, + ]; + foreach ($options as $key => $value) { + if (isset($nonRewrittenKeys[$key])) { + continue; + } + $options['master'][$key] = $value; + unset($options[$key]); + } + if (empty($options['wrapperClass'])) { + // Change the wrapper class only if the user does not already forced using a custom one. + $options['wrapperClass'] = 'Doctrine\\DBAL\\Connections\\MasterSlaveConnection'; + } + } else { + unset($options['slaves']); + } + + if (! empty($options['shards'])) { + $nonRewrittenKeys = [ + 'driver' => true, + 'driverOptions' => true, + 'driverClass' => true, + 'wrapperClass' => true, + 'keepSlave' => true, + 'shardChoser' => true, + 'platform' => true, + 'slaves' => true, + 'global' => true, + 'shards' => true, + 'serverVersion' => true, + 'defaultTableOptions' => true, + // included by safety but should have been unset already + 'logging' => true, + 'profiling' => true, + 'mapping_types' => true, + 'platform_service' => true, + ]; + foreach ($options as $key => $value) { + if (isset($nonRewrittenKeys[$key])) { + continue; + } + $options['global'][$key] = $value; + unset($options[$key]); + } + if (empty($options['wrapperClass'])) { + // Change the wrapper class only if the user does not already forced using a custom one. + $options['wrapperClass'] = 'Doctrine\\DBAL\\Sharding\\PoolingShardConnection'; + } + if (empty($options['shardManagerClass'])) { + // Change the shard manager class only if the user does not already forced using a custom one. + $options['shardManagerClass'] = 'Doctrine\\DBAL\\Sharding\\PoolingShardManager'; + } + } else { + unset($options['shards']); + } + + return $options; + } + + /** + * Loads the Doctrine ORM configuration. + * + * Usage example: + * + * + * + * @param array $config An array of configuration settings + * @param ContainerBuilder $container A ContainerBuilder instance + */ + protected function ormLoad(array $config, ContainerBuilder $container) + { + if (! class_exists(UnitOfWork::class)) { + throw new LogicException('To configure the ORM layer, you must first install the doctrine/orm package.'); + } + + $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); + $loader->load('orm.xml'); + + if (class_exists(AbstractType::class)) { + $container->getDefinition('form.type.entity')->addTag('kernel.reset', ['method' => 'reset']); + } + + $entityManagers = []; + foreach (array_keys($config['entity_managers']) as $name) { + $entityManagers[$name] = sprintf('doctrine.orm.%s_entity_manager', $name); + } + $container->setParameter('doctrine.entity_managers', $entityManagers); + + if (empty($config['default_entity_manager'])) { + $tmp = array_keys($entityManagers); + $config['default_entity_manager'] = reset($tmp); + } + $container->setParameter('doctrine.default_entity_manager', $config['default_entity_manager']); + + $options = ['auto_generate_proxy_classes', 'proxy_dir', 'proxy_namespace']; + foreach ($options as $key) { + $container->setParameter('doctrine.orm.' . $key, $config[$key]); + } + + $container->setAlias('doctrine.orm.entity_manager', sprintf('doctrine.orm.%s_entity_manager', $config['default_entity_manager'])); + $container->getAlias('doctrine.orm.entity_manager')->setPublic(true); + + $config['entity_managers'] = $this->fixManagersAutoMappings($config['entity_managers'], $container->getParameter('kernel.bundles')); + + foreach ($config['entity_managers'] as $name => $entityManager) { + $entityManager['name'] = $name; + $this->loadOrmEntityManager($entityManager, $container); + + if (interface_exists(PropertyInfoExtractorInterface::class)) { + $this->loadPropertyInfoExtractor($name, $container); + } + + $this->loadValidatorLoader($name, $container); + } + + if ($config['resolve_target_entities']) { + $def = $container->findDefinition('doctrine.orm.listeners.resolve_target_entity'); + foreach ($config['resolve_target_entities'] as $name => $implementation) { + $def->addMethodCall('addResolveTargetEntity', [ + $name, + $implementation, + [], + ]); + } + + $def->addTag('doctrine.event_subscriber'); + } + + $container->registerForAutoconfiguration(ServiceEntityRepositoryInterface::class) + ->addTag(ServiceRepositoryCompilerPass::REPOSITORY_SERVICE_TAG); + } + + /** + * Loads a configured ORM entity manager. + * + * @param array $entityManager A configured ORM entity manager. + * @param ContainerBuilder $container A ContainerBuilder instance + */ + protected function loadOrmEntityManager(array $entityManager, ContainerBuilder $container) + { + $ormConfigDef = $container->setDefinition(sprintf('doctrine.orm.%s_configuration', $entityManager['name']), new ChildDefinition('doctrine.orm.configuration')); + + $this->loadOrmEntityManagerMappingInformation($entityManager, $ormConfigDef, $container); + $this->loadOrmCacheDrivers($entityManager, $container); + + if (isset($entityManager['entity_listener_resolver']) && $entityManager['entity_listener_resolver']) { + $container->setAlias(sprintf('doctrine.orm.%s_entity_listener_resolver', $entityManager['name']), $entityManager['entity_listener_resolver']); + } else { + $definition = new Definition('%doctrine.orm.entity_listener_resolver.class%'); + $definition->addArgument(new Reference('service_container')); + $container->setDefinition(sprintf('doctrine.orm.%s_entity_listener_resolver', $entityManager['name']), $definition); + } + + $methods = [ + 'setMetadataCacheImpl' => new Reference(sprintf('doctrine.orm.%s_metadata_cache', $entityManager['name'])), + 'setQueryCacheImpl' => new Reference(sprintf('doctrine.orm.%s_query_cache', $entityManager['name'])), + 'setResultCacheImpl' => new Reference(sprintf('doctrine.orm.%s_result_cache', $entityManager['name'])), + 'setMetadataDriverImpl' => new Reference('doctrine.orm.' . $entityManager['name'] . '_metadata_driver'), + 'setProxyDir' => '%doctrine.orm.proxy_dir%', + 'setProxyNamespace' => '%doctrine.orm.proxy_namespace%', + 'setAutoGenerateProxyClasses' => '%doctrine.orm.auto_generate_proxy_classes%', + 'setClassMetadataFactoryName' => $entityManager['class_metadata_factory_name'], + 'setDefaultRepositoryClassName' => $entityManager['default_repository_class'], + 'setNamingStrategy' => new Reference($entityManager['naming_strategy']), + 'setQuoteStrategy' => new Reference($entityManager['quote_strategy']), + 'setEntityListenerResolver' => new Reference(sprintf('doctrine.orm.%s_entity_listener_resolver', $entityManager['name'])), + ]; + + $listenerId = sprintf('doctrine.orm.%s_listeners.attach_entity_listeners', $entityManager['name']); + $listenerDef = $container->setDefinition($listenerId, new Definition('%doctrine.orm.listeners.attach_entity_listeners.class%')); + $listenerTagParams = ['event' => 'loadClassMetadata']; + if (isset($entityManager['connection'])) { + $listenerTagParams['connection'] = $entityManager['connection']; + } + $listenerDef->addTag('doctrine.event_listener', $listenerTagParams); + + if (isset($entityManager['second_level_cache'])) { + $this->loadOrmSecondLevelCache($entityManager, $ormConfigDef, $container); + } + + if ($entityManager['repository_factory']) { + $methods['setRepositoryFactory'] = new Reference($entityManager['repository_factory']); + } + + foreach ($methods as $method => $arg) { + $ormConfigDef->addMethodCall($method, [$arg]); + } + + foreach ($entityManager['hydrators'] as $name => $class) { + $ormConfigDef->addMethodCall('addCustomHydrationMode', [$name, $class]); + } + + if (! empty($entityManager['dql'])) { + foreach ($entityManager['dql']['string_functions'] as $name => $function) { + $ormConfigDef->addMethodCall('addCustomStringFunction', [$name, $function]); + } + foreach ($entityManager['dql']['numeric_functions'] as $name => $function) { + $ormConfigDef->addMethodCall('addCustomNumericFunction', [$name, $function]); + } + foreach ($entityManager['dql']['datetime_functions'] as $name => $function) { + $ormConfigDef->addMethodCall('addCustomDatetimeFunction', [$name, $function]); + } + } + + $enabledFilters = []; + $filtersParameters = []; + foreach ($entityManager['filters'] as $name => $filter) { + $ormConfigDef->addMethodCall('addFilter', [$name, $filter['class']]); + if ($filter['enabled']) { + $enabledFilters[] = $name; + } + if (! $filter['parameters']) { + continue; + } + + $filtersParameters[$name] = $filter['parameters']; + } + + $managerConfiguratorName = sprintf('doctrine.orm.%s_manager_configurator', $entityManager['name']); + $container + ->setDefinition($managerConfiguratorName, new ChildDefinition('doctrine.orm.manager_configurator.abstract')) + ->replaceArgument(0, $enabledFilters) + ->replaceArgument(1, $filtersParameters); + + if (! isset($entityManager['connection'])) { + $entityManager['connection'] = $this->defaultConnection; + } + + $container + ->setDefinition(sprintf('doctrine.orm.%s_entity_manager', $entityManager['name']), new ChildDefinition('doctrine.orm.entity_manager.abstract')) + ->setPublic(true) + ->setArguments([ + new Reference(sprintf('doctrine.dbal.%s_connection', $entityManager['connection'])), + new Reference(sprintf('doctrine.orm.%s_configuration', $entityManager['name'])), + ]) + ->setConfigurator([new Reference($managerConfiguratorName), 'configure']); + + $container->setAlias( + sprintf('doctrine.orm.%s_entity_manager.event_manager', $entityManager['name']), + new Alias(sprintf('doctrine.dbal.%s_connection.event_manager', $entityManager['connection']), false) + ); + + if (! isset($entityManager['entity_listeners'])) { + return; + } + + if (! isset($listenerDef)) { + throw new InvalidArgumentException('Entity listeners configuration requires doctrine-orm 2.5.0 or newer'); + } + + $entities = $entityManager['entity_listeners']['entities']; + + foreach ($entities as $entityListenerClass => $entity) { + foreach ($entity['listeners'] as $listenerClass => $listener) { + foreach ($listener['events'] as $listenerEvent) { + $listenerEventName = $listenerEvent['type']; + $listenerMethod = $listenerEvent['method']; + + $listenerDef->addMethodCall('addEntityListener', [ + $entityListenerClass, + $listenerClass, + $listenerEventName, + $listenerMethod, + ]); + } + } + } + } + + /** + * Loads an ORM entity managers bundle mapping information. + * + * There are two distinct configuration possibilities for mapping information: + * + * 1. Specify a bundle and optionally details where the entity and mapping information reside. + * 2. Specify an arbitrary mapping location. + * + * @param array $entityManager A configured ORM entity manager + * @param Definition $ormConfigDef A Definition instance + * @param ContainerBuilder $container A ContainerBuilder instance + * + * @example + * + * doctrine.orm: + * mappings: + * MyBundle1: ~ + * MyBundle2: yml + * MyBundle3: { type: annotation, dir: Entities/ } + * MyBundle4: { type: xml, dir: Resources/config/doctrine/mapping } + * MyBundle5: + * type: yml + * dir: bundle-mappings/ + * alias: BundleAlias + * arbitrary_key: + * type: xml + * dir: %kernel.project_dir%/src/vendor/DoctrineExtensions/lib/DoctrineExtensions/Entities + * prefix: DoctrineExtensions\Entities\ + * alias: DExt + * + * In the case of bundles everything is really optional (which leads to autodetection for this bundle) but + * in the mappings key everything except alias is a required argument. + */ + protected function loadOrmEntityManagerMappingInformation(array $entityManager, Definition $ormConfigDef, ContainerBuilder $container) + { + // reset state of drivers and alias map. They are only used by this methods and children. + $this->drivers = []; + $this->aliasMap = []; + + $this->loadMappingInformation($entityManager, $container); + $this->registerMappingDrivers($entityManager, $container); + + $ormConfigDef->addMethodCall('setEntityNamespaces', [$this->aliasMap]); + } + + /** + * Loads an ORM second level cache bundle mapping information. + * + * @param array $entityManager A configured ORM entity manager + * @param Definition $ormConfigDef A Definition instance + * @param ContainerBuilder $container A ContainerBuilder instance + * + * @example + * entity_managers: + * default: + * second_level_cache: + * region_cache_driver: apc + * log_enabled: true + * regions: + * my_service_region: + * type: service + * service : "my_service_region" + * + * my_query_region: + * lifetime: 300 + * cache_driver: array + * type: filelock + * + * my_entity_region: + * lifetime: 600 + * cache_driver: + * type: apc + */ + protected function loadOrmSecondLevelCache(array $entityManager, Definition $ormConfigDef, ContainerBuilder $container) + { + $driverId = null; + $enabled = $entityManager['second_level_cache']['enabled']; + + if (isset($entityManager['second_level_cache']['region_cache_driver'])) { + $driverName = 'second_level_cache.region_cache_driver'; + $driverMap = $entityManager['second_level_cache']['region_cache_driver']; + $driverId = $this->loadCacheDriver($driverName, $entityManager['name'], $driverMap, $container); + } + + $configId = sprintf('doctrine.orm.%s_second_level_cache.cache_configuration', $entityManager['name']); + $regionsId = sprintf('doctrine.orm.%s_second_level_cache.regions_configuration', $entityManager['name']); + $driverId = $driverId ?: sprintf('doctrine.orm.%s_second_level_cache.region_cache_driver', $entityManager['name']); + $configDef = $container->setDefinition($configId, new Definition('%doctrine.orm.second_level_cache.cache_configuration.class%')); + $regionsDef = $container->setDefinition($regionsId, new Definition('%doctrine.orm.second_level_cache.regions_configuration.class%')); + + $slcFactoryId = sprintf('doctrine.orm.%s_second_level_cache.default_cache_factory', $entityManager['name']); + $factoryClass = isset($entityManager['second_level_cache']['factory']) ? $entityManager['second_level_cache']['factory'] : '%doctrine.orm.second_level_cache.default_cache_factory.class%'; + + $definition = new Definition($factoryClass, [new Reference($regionsId), new Reference($driverId)]); + + $slcFactoryDef = $container + ->setDefinition($slcFactoryId, $definition); + + if (isset($entityManager['second_level_cache']['regions'])) { + foreach ($entityManager['second_level_cache']['regions'] as $name => $region) { + $regionRef = null; + $regionType = $region['type']; + + if ($regionType === 'service') { + $regionId = sprintf('doctrine.orm.%s_second_level_cache.region.%s', $entityManager['name'], $name); + $regionRef = new Reference($region['service']); + + $container->setAlias($regionId, new Alias($region['service'], false)); + } + + if ($regionType === 'default' || $regionType === 'filelock') { + $regionId = sprintf('doctrine.orm.%s_second_level_cache.region.%s', $entityManager['name'], $name); + $driverName = sprintf('second_level_cache.region.%s_driver', $name); + $driverMap = $region['cache_driver']; + $driverId = $this->loadCacheDriver($driverName, $entityManager['name'], $driverMap, $container); + $regionRef = new Reference($regionId); + + $container + ->setDefinition($regionId, new Definition('%doctrine.orm.second_level_cache.default_region.class%')) + ->setArguments([$name, new Reference($driverId), $region['lifetime']]); + } + + if ($regionType === 'filelock') { + $regionId = sprintf('doctrine.orm.%s_second_level_cache.region.%s_filelock', $entityManager['name'], $name); + + $container + ->setDefinition($regionId, new Definition('%doctrine.orm.second_level_cache.filelock_region.class%')) + ->setArguments([$regionRef, $region['lock_path'], $region['lock_lifetime']]); + + $regionRef = new Reference($regionId); + $regionsDef->addMethodCall('getLockLifetime', [$name, $region['lock_lifetime']]); + } + + $regionsDef->addMethodCall('setLifetime', [$name, $region['lifetime']]); + $slcFactoryDef->addMethodCall('setRegion', [$regionRef]); + } + } + + if ($entityManager['second_level_cache']['log_enabled']) { + $loggerChainId = sprintf('doctrine.orm.%s_second_level_cache.logger_chain', $entityManager['name']); + $loggerStatsId = sprintf('doctrine.orm.%s_second_level_cache.logger_statistics', $entityManager['name']); + $loggerChaingDef = $container->setDefinition($loggerChainId, new Definition('%doctrine.orm.second_level_cache.logger_chain.class%')); + $loggerStatsDef = $container->setDefinition($loggerStatsId, new Definition('%doctrine.orm.second_level_cache.logger_statistics.class%')); + + $loggerChaingDef->addMethodCall('setLogger', ['statistics', $loggerStatsDef]); + $configDef->addMethodCall('setCacheLogger', [$loggerChaingDef]); + + foreach ($entityManager['second_level_cache']['loggers'] as $name => $logger) { + $loggerId = sprintf('doctrine.orm.%s_second_level_cache.logger.%s', $entityManager['name'], $name); + $loggerRef = new Reference($logger['service']); + + $container->setAlias($loggerId, new Alias($logger['service'], false)); + $loggerChaingDef->addMethodCall('setLogger', [$name, $loggerRef]); + } + } + + $configDef->addMethodCall('setCacheFactory', [$slcFactoryDef]); + $configDef->addMethodCall('setRegionsConfiguration', [$regionsDef]); + $ormConfigDef->addMethodCall('setSecondLevelCacheEnabled', [$enabled]); + $ormConfigDef->addMethodCall('setSecondLevelCacheConfiguration', [$configDef]); + } + + /** + * {@inheritDoc} + */ + protected function getObjectManagerElementName($name) : string + { + return 'doctrine.orm.' . $name; + } + + protected function getMappingObjectDefaultName() : string + { + return 'Entity'; + } + + /** + * {@inheritDoc} + */ + protected function getMappingResourceConfigDirectory() : string + { + return 'Resources/config/doctrine'; + } + + /** + * {@inheritDoc} + */ + protected function getMappingResourceExtension() : string + { + return 'orm'; + } + + /** + * {@inheritDoc} + */ + protected function loadCacheDriver($cacheName, $objectManagerName, array $cacheDriver, ContainerBuilder $container) : string + { + $serviceId = null; + $aliasId = $this->getObjectManagerElementName(sprintf('%s_%s', $objectManagerName, $cacheName)); + + switch ($cacheDriver['type'] ?? 'pool') { + case 'service': + $serviceId = $cacheDriver['id']; + break; + + case 'pool': + $serviceId = $this->createPoolCacheDefinition($container, $cacheDriver['pool'] ?? $this->createArrayAdapterCachePool($container, $objectManagerName, $cacheName)); + break; + + case 'provider': + $serviceId = sprintf('doctrine_cache.providers.%s', $cacheDriver['cache_provider']); + break; + + default: + throw new \InvalidArgumentException(sprintf( + 'Unknown cache of type "%s" configured for cache "%s" in entity manager "%s".', + $cacheDriver['type'], + $cacheName, + $objectManagerName + )); + } + + $container->setAlias($aliasId, new Alias($serviceId, false)); + + return $aliasId; + } + + /** + * Loads a configured entity managers cache drivers. + * + * @param array $entityManager A configured ORM entity manager. + * @param ContainerBuilder $container A ContainerBuilder instance + */ + protected function loadOrmCacheDrivers(array $entityManager, ContainerBuilder $container) + { + $this->loadCacheDriver('metadata_cache', $entityManager['name'], $entityManager['metadata_cache_driver'], $container); + $this->loadCacheDriver('result_cache', $entityManager['name'], $entityManager['result_cache_driver'], $container); + $this->loadCacheDriver('query_cache', $entityManager['name'], $entityManager['query_cache_driver'], $container); + } + + /** + * Loads a property info extractor for each defined entity manager. + * + * @param string $entityManagerName + */ + private function loadPropertyInfoExtractor($entityManagerName, ContainerBuilder $container) + { + $propertyExtractorDefinition = $container->register(sprintf('doctrine.orm.%s_entity_manager.property_info_extractor', $entityManagerName), DoctrineExtractor::class); + $argumentId = sprintf('doctrine.orm.%s_entity_manager', $entityManagerName); + + $propertyExtractorDefinition->addArgument(new Reference($argumentId)); + + $propertyExtractorDefinition->addTag('property_info.list_extractor', ['priority' => -1001]); + $propertyExtractorDefinition->addTag('property_info.type_extractor', ['priority' => -999]); + $propertyExtractorDefinition->addTag('property_info.access_extractor', ['priority' => -999]); + } + + /** + * Loads a validator loader for each defined entity manager. + */ + private function loadValidatorLoader(string $entityManagerName, ContainerBuilder $container) : void + { + $validatorLoaderDefinition = $container->register(sprintf('doctrine.orm.%s_entity_manager.validator_loader', $entityManagerName), DoctrineLoader::class); + $validatorLoaderDefinition->addArgument(new Reference(sprintf('doctrine.orm.%s_entity_manager', $entityManagerName))); + + $validatorLoaderDefinition->addTag('validator.auto_mapper', ['priority' => -100]); + } + + /** + * @param array $objectManager + * @param string $cacheName + */ + public function loadObjectManagerCacheDriver(array $objectManager, ContainerBuilder $container, $cacheName) + { + $this->loadCacheDriver($cacheName, $objectManager['name'], $objectManager[$cacheName . '_driver'], $container); + } + + /** + * {@inheritDoc} + */ + public function getXsdValidationBasePath() : string + { + return __DIR__ . '/../Resources/config/schema'; + } + + /** + * {@inheritDoc} + */ + public function getNamespace() : string + { + return 'http://symfony.com/schema/dic/doctrine'; + } + + /** + * {@inheritDoc} + */ + public function getConfiguration(array $config, ContainerBuilder $container) : Configuration + { + return new Configuration($container->getParameter('kernel.debug')); + } + + protected function getMetadataDriverClass(string $driverType) : string + { + return '%' . $this->getObjectManagerElementName('metadata.' . $driverType . '.class%'); + } + + private function loadMessengerServices(ContainerBuilder $container) : void + { + // If the Messenger component is installed and the doctrine transaction middleware is available, wire it: + if (! interface_exists(MessageBusInterface::class) || ! class_exists(DoctrineTransactionMiddleware::class)) { + return; + } + + $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); + $loader->load('messenger.xml'); + + if (! class_exists(DoctrineClearEntityManagerWorkerSubscriber::class)) { + $container->removeDefinition('doctrine.orm.messenger.event_subscriber.doctrine_clear_entity_manager'); + } + + if (! class_exists(DoctrineTransportFactory::class)) { + return; + } + + $transportFactoryDefinition = $container->getDefinition('messenger.transport.doctrine.factory'); + $transportFactoryDefinition->addTag('messenger.transport_factory'); + } + + private function createPoolCacheDefinition(ContainerBuilder $container, string $poolName) : string + { + $serviceId = sprintf('doctrine.orm.cache.provider.%s', $poolName); + + $definition = $container->register($serviceId, DoctrineProvider::class); + $definition->addArgument(new Reference($poolName)); + $definition->setPrivate(true); + + return $serviceId; + } + + private function createArrayAdapterCachePool(ContainerBuilder $container, string $objectManagerName, string $cacheName) : string + { + $id = sprintf('cache.doctrine.orm.%s.%s', $objectManagerName, str_replace('_cache', '', $cacheName)); + + $poolDefinition = $container->register($id, ArrayAdapter::class); + $poolDefinition->addTag('cache.pool'); + $container->setDefinition($id, $poolDefinition); + + return $id; + } +} diff --git a/vendor/doctrine/doctrine-bundle/DoctrineBundle.php b/vendor/doctrine/doctrine-bundle/DoctrineBundle.php new file mode 100644 index 0000000..f19a1e5 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/DoctrineBundle.php @@ -0,0 +1,137 @@ +addCompilerPass(new RegisterEventListenersAndSubscribersPass('doctrine.connections', 'doctrine.dbal.%s_connection.event_manager', 'doctrine'), PassConfig::TYPE_BEFORE_OPTIMIZATION); + + if ($container->hasExtension('security')) { + $container->getExtension('security')->addUserProviderFactory(new EntityFactory('entity', 'doctrine.orm.security.user.provider')); + } + + $container->addCompilerPass(new DoctrineValidationPass('orm')); + $container->addCompilerPass(new EntityListenerPass()); + $container->addCompilerPass(new ServiceRepositoryCompilerPass()); + $container->addCompilerPass(new WellKnownSchemaFilterPass()); + $container->addCompilerPass(new DbalSchemaFilterPass()); + } + + /** + * {@inheritDoc} + */ + public function boot() + { + // Register an autoloader for proxies to avoid issues when unserializing them + // when the ORM is used. + if (! $this->container->hasParameter('doctrine.orm.proxy_namespace')) { + return; + } + + $namespace = $this->container->getParameter('doctrine.orm.proxy_namespace'); + $dir = $this->container->getParameter('doctrine.orm.proxy_dir'); + $proxyGenerator = null; + + if ($this->container->getParameter('doctrine.orm.auto_generate_proxy_classes')) { + // See https://github.com/symfony/symfony/pull/3419 for usage of references + $container = &$this->container; + + $proxyGenerator = static function ($proxyDir, $proxyNamespace, $class) use (&$container) { + $originalClassName = ClassUtils::getRealClass($class); + /** @var Registry $registry */ + $registry = $container->get('doctrine'); + + // Tries to auto-generate the proxy file + /** @var EntityManager $em */ + foreach ($registry->getManagers() as $em) { + if (! $em->getConfiguration()->getAutoGenerateProxyClasses()) { + continue; + } + + $metadataFactory = $em->getMetadataFactory(); + + if ($metadataFactory->isTransient($originalClassName)) { + continue; + } + + $classMetadata = $metadataFactory->getMetadataFor($originalClassName); + + $em->getProxyFactory()->generateProxyClasses([$classMetadata]); + + clearstatcache(true, Autoloader::resolveFile($proxyDir, $proxyNamespace, $class)); + + break; + } + }; + } + + $this->autoloader = Autoloader::register($dir, $namespace, $proxyGenerator); + } + + /** + * {@inheritDoc} + */ + public function shutdown() + { + if ($this->autoloader !== null) { + spl_autoload_unregister($this->autoloader); + $this->autoloader = null; + } + + // Clear all entity managers to clear references to entities for GC + if ($this->container->hasParameter('doctrine.entity_managers')) { + foreach ($this->container->getParameter('doctrine.entity_managers') as $id) { + if (! $this->container->initialized($id)) { + continue; + } + + $this->container->get($id)->clear(); + } + } + + // Close all connections to avoid reaching too many connections in the process when booting again later (tests) + if (! $this->container->hasParameter('doctrine.connections')) { + return; + } + + foreach ($this->container->getParameter('doctrine.connections') as $id) { + if (! $this->container->initialized($id)) { + continue; + } + + $this->container->get($id)->close(); + } + } + + /** + * {@inheritDoc} + */ + public function registerCommands(Application $application) + { + } +} diff --git a/vendor/doctrine/doctrine-bundle/LICENSE b/vendor/doctrine/doctrine-bundle/LICENSE new file mode 100644 index 0000000..655a5ce --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2011 Fabien Potencier, Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/doctrine/doctrine-bundle/ManagerConfigurator.php b/vendor/doctrine/doctrine-bundle/ManagerConfigurator.php new file mode 100644 index 0000000..6143890 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/ManagerConfigurator.php @@ -0,0 +1,74 @@ +enabledFilters = $enabledFilters; + $this->filtersParameters = $filtersParameters; + } + + /** + * Create a connection by name. + */ + public function configure(EntityManagerInterface $entityManager) + { + $this->enableFilters($entityManager); + } + + /** + * Enables filters for a given entity manager + */ + private function enableFilters(EntityManagerInterface $entityManager) + { + if (empty($this->enabledFilters)) { + return; + } + + $filterCollection = $entityManager->getFilters(); + foreach ($this->enabledFilters as $filter) { + $filterObject = $filterCollection->enable($filter); + if ($filterObject === null) { + continue; + } + + $this->setFilterParameters($filter, $filterObject); + } + } + + /** + * Sets default parameters for a given filter + * + * @param string $name Filter name + * @param SQLFilter $filter Filter object + */ + private function setFilterParameters($name, SQLFilter $filter) + { + if (empty($this->filtersParameters[$name])) { + return; + } + + $parameters = $this->filtersParameters[$name]; + foreach ($parameters as $paramName => $paramValue) { + $filter->setParameter($paramName, $paramValue); + } + } +} diff --git a/vendor/doctrine/doctrine-bundle/Mapping/ClassMetadataCollection.php b/vendor/doctrine/doctrine-bundle/Mapping/ClassMetadataCollection.php new file mode 100644 index 0000000..c65b47f --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Mapping/ClassMetadataCollection.php @@ -0,0 +1,65 @@ +metadata = $metadata; + } + + /** + * @return ClassMetadata[] + */ + public function getMetadata() + { + return $this->metadata; + } + + /** + * @param string $path + */ + public function setPath($path) + { + $this->path = $path; + } + + /** + * @return string + */ + public function getPath() + { + return $this->path; + } + + /** + * @param string $namespace + */ + public function setNamespace($namespace) + { + $this->namespace = $namespace; + } + + /** + * @return string + */ + public function getNamespace() + { + return $this->namespace; + } +} diff --git a/vendor/doctrine/doctrine-bundle/Mapping/ContainerEntityListenerResolver.php b/vendor/doctrine/doctrine-bundle/Mapping/ContainerEntityListenerResolver.php new file mode 100644 index 0000000..9645838 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Mapping/ContainerEntityListenerResolver.php @@ -0,0 +1,103 @@ +container = $container; + } + + /** + * {@inheritdoc} + */ + public function clear($className = null) + { + if ($className === null) { + $this->instances = []; + + return; + } + + $className = $this->normalizeClassName($className); + + unset($this->instances[$className]); + } + + /** + * {@inheritdoc} + */ + public function register($object) + { + if (! is_object($object)) { + throw new InvalidArgumentException(sprintf('An object was expected, but got "%s".', gettype($object))); + } + + $className = $this->normalizeClassName(get_class($object)); + + $this->instances[$className] = $object; + } + + /** + * {@inheritdoc} + */ + public function registerService($className, $serviceId) + { + $this->serviceIds[$this->normalizeClassName($className)] = $serviceId; + } + + /** + * {@inheritdoc} + */ + public function resolve($className) + { + $className = $this->normalizeClassName($className); + + if (! isset($this->instances[$className])) { + if (isset($this->serviceIds[$className])) { + $this->instances[$className] = $this->resolveService($this->serviceIds[$className]); + } else { + $this->instances[$className] = new $className(); + } + } + + return $this->instances[$className]; + } + + /** + * @return object + */ + private function resolveService(string $serviceId) + { + if (! $this->container->has($serviceId)) { + throw new RuntimeException(sprintf('There is no service named "%s"', $serviceId)); + } + + return $this->container->get($serviceId); + } + + private function normalizeClassName(string $className) : string + { + return trim($className, '\\'); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Mapping/DisconnectedMetadataFactory.php b/vendor/doctrine/doctrine-bundle/Mapping/DisconnectedMetadataFactory.php new file mode 100644 index 0000000..163259d --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Mapping/DisconnectedMetadataFactory.php @@ -0,0 +1,204 @@ +registry = $registry; + } + + /** + * Gets the metadata of all classes of a bundle. + * + * @param BundleInterface $bundle A BundleInterface instance + * + * @return ClassMetadataCollection A ClassMetadataCollection instance + * + * @throws RuntimeException When bundle does not contain mapped entities. + */ + public function getBundleMetadata(BundleInterface $bundle) + { + $namespace = $bundle->getNamespace(); + $metadata = $this->getMetadataForNamespace($namespace); + if (! $metadata->getMetadata()) { + throw new RuntimeException(sprintf('Bundle "%s" does not contain any mapped entities.', $bundle->getName())); + } + + $path = $this->getBasePathForClass($bundle->getName(), $bundle->getNamespace(), $bundle->getPath()); + + $metadata->setPath($path); + $metadata->setNamespace($bundle->getNamespace()); + + return $metadata; + } + + /** + * Gets the metadata of a class. + * + * @param string $class A class name + * @param string $path The path where the class is stored (if known) + * + * @return ClassMetadataCollection A ClassMetadataCollection instance + * + * @throws MappingException When class is not valid entity or mapped superclass. + */ + public function getClassMetadata($class, $path = null) + { + $metadata = $this->getMetadataForClass($class); + if (! $metadata->getMetadata()) { + throw MappingException::classIsNotAValidEntityOrMappedSuperClass($class); + } + + $this->findNamespaceAndPathForMetadata($metadata, $path); + + return $metadata; + } + + /** + * Gets the metadata of all classes of a namespace. + * + * @param string $namespace A namespace name + * @param string $path The path where the class is stored (if known) + * + * @return ClassMetadataCollection A ClassMetadataCollection instance + * + * @throws RuntimeException When namespace not contain mapped entities. + */ + public function getNamespaceMetadata($namespace, $path = null) + { + $metadata = $this->getMetadataForNamespace($namespace); + if (! $metadata->getMetadata()) { + throw new RuntimeException(sprintf('Namespace "%s" does not contain any mapped entities.', $namespace)); + } + + $this->findNamespaceAndPathForMetadata($metadata, $path); + + return $metadata; + } + + /** + * Find and configure path and namespace for the metadata collection. + * + * @param string|null $path + * + * @throws RuntimeException When unable to determine the path. + */ + public function findNamespaceAndPathForMetadata(ClassMetadataCollection $metadata, $path = null) + { + $all = $metadata->getMetadata(); + if (class_exists($all[0]->name)) { + $r = new ReflectionClass($all[0]->name); + $path = $this->getBasePathForClass($r->getName(), $r->getNamespaceName(), dirname($r->getFilename())); + $ns = $r->getNamespaceName(); + } elseif ($path) { + // Get namespace by removing the last component of the FQCN + $nsParts = explode('\\', $all[0]->name); + array_pop($nsParts); + $ns = implode('\\', $nsParts); + } else { + throw new RuntimeException(sprintf('Unable to determine where to save the "%s" class (use the --path option).', $all[0]->name)); + } + + $metadata->setPath($path); + $metadata->setNamespace($ns); + } + + /** + * Get a base path for a class + * + * @param string $name class name + * @param string $namespace class namespace + * @param string $path class path + * + * @return string + * + * @throws RuntimeException When base path not found. + */ + private function getBasePathForClass($name, $namespace, $path) + { + $namespace = str_replace('\\', '/', $namespace); + $search = str_replace('\\', '/', $path); + $destination = str_replace('/' . $namespace, '', $search, $c); + + if ($c !== 1) { + throw new RuntimeException(sprintf('Can\'t find base path for "%s" (path: "%s", destination: "%s").', $name, $path, $destination)); + } + + return $destination; + } + + /** + * @param string $namespace + * + * @return ClassMetadataCollection + */ + private function getMetadataForNamespace($namespace) + { + $metadata = []; + foreach ($this->getAllMetadata() as $m) { + if (strpos($m->name, $namespace) !== 0) { + continue; + } + + $metadata[] = $m; + } + + return new ClassMetadataCollection($metadata); + } + + /** + * @param string $entity + * + * @return ClassMetadataCollection + */ + private function getMetadataForClass($entity) + { + foreach ($this->registry->getManagers() as $em) { + $cmf = new DisconnectedClassMetadataFactory(); + $cmf->setEntityManager($em); + + if (! $cmf->isTransient($entity)) { + return new ClassMetadataCollection([$cmf->getMetadataFor($entity)]); + } + } + + return new ClassMetadataCollection([]); + } + + /** + * @return ClassMetadata[] + */ + private function getAllMetadata() + { + $metadata = []; + foreach ($this->registry->getManagers() as $em) { + $cmf = new DisconnectedClassMetadataFactory(); + $cmf->setEntityManager($em); + foreach ($cmf->getAllMetadata() as $m) { + $metadata[] = $m; + } + } + + return $metadata; + } +} diff --git a/vendor/doctrine/doctrine-bundle/Mapping/EntityListenerServiceResolver.php b/vendor/doctrine/doctrine-bundle/Mapping/EntityListenerServiceResolver.php new file mode 100644 index 0000000..3cb4960 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Mapping/EntityListenerServiceResolver.php @@ -0,0 +1,14 @@ +container = $container; + + parent::__construct('ORM', $connections, $entityManagers, $defaultConnection, $defaultEntityManager, 'Doctrine\ORM\Proxy\Proxy'); + } + + /** + * Resolves a registered namespace alias to the full namespace. + * + * This method looks for the alias in all registered entity managers. + * + * @see Configuration::getEntityNamespace + * + * @param string $alias The alias + * + * @return string The full namespace + */ + public function getAliasNamespace($alias) + { + foreach (array_keys($this->getManagers()) as $name) { + try { + return $this->getManager($name)->getConfiguration()->getEntityNamespace($alias); + } catch (ORMException $e) { + } + } + + throw ORMException::unknownEntityNamespace($alias); + } + + public function reset() : void + { + foreach ($this->getManagerNames() as $managerName => $serviceId) { + $this->resetOrClearManager($managerName, $serviceId); + } + } + + private function resetOrClearManager(string $managerName, string $serviceId) : void + { + if (! $this->container->initialized($serviceId)) { + return; + } + + $manager = $this->container->get($serviceId); + + if (! $manager instanceof LazyLoadingInterface) { + $manager->clear(); + + return; + } + + $this->resetManager($managerName); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Repository/ContainerRepositoryFactory.php b/vendor/doctrine/doctrine-bundle/Repository/ContainerRepositoryFactory.php new file mode 100644 index 0000000..b16427b --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Repository/ContainerRepositoryFactory.php @@ -0,0 +1,86 @@ +container = $container; + } + + /** + * {@inheritdoc} + */ + public function getRepository(EntityManagerInterface $entityManager, $entityName) + { + $metadata = $entityManager->getClassMetadata($entityName); + $repositoryServiceId = $metadata->customRepositoryClassName; + + $customRepositoryName = $metadata->customRepositoryClassName; + if ($customRepositoryName !== null) { + // fetch from the container + if ($this->container && $this->container->has($customRepositoryName)) { + $repository = $this->container->get($customRepositoryName); + + if (! $repository instanceof ObjectRepository) { + throw new RuntimeException(sprintf('The service "%s" must implement ObjectRepository (or extend a base class, like ServiceEntityRepository).', $repositoryServiceId)); + } + + return $repository; + } + + // if not in the container but the class/id implements the interface, throw an error + if (is_a($customRepositoryName, ServiceEntityRepositoryInterface::class, true)) { + throw new RuntimeException(sprintf('The "%s" entity repository implements "%s", but its service could not be found. Make sure the service exists and is tagged with "%s".', $customRepositoryName, ServiceEntityRepositoryInterface::class, ServiceRepositoryCompilerPass::REPOSITORY_SERVICE_TAG)); + } + + if (! class_exists($customRepositoryName)) { + throw new RuntimeException(sprintf('The "%s" entity has a repositoryClass set to "%s", but this is not a valid class. Check your class naming. If this is meant to be a service id, make sure this service exists and is tagged with "%s".', $metadata->name, $customRepositoryName, ServiceRepositoryCompilerPass::REPOSITORY_SERVICE_TAG)); + } + + // allow the repository to be created below + } + + return $this->getOrCreateRepository($entityManager, $metadata); + } + + private function getOrCreateRepository(EntityManagerInterface $entityManager, ClassMetadata $metadata) + { + $repositoryHash = $metadata->getName() . spl_object_hash($entityManager); + if (isset($this->managedRepositories[$repositoryHash])) { + return $this->managedRepositories[$repositoryHash]; + } + + $repositoryClassName = $metadata->customRepositoryClassName ?: $entityManager->getConfiguration()->getDefaultRepositoryClassName(); + + return $this->managedRepositories[$repositoryHash] = new $repositoryClassName($entityManager, $metadata); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepository.php b/vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepository.php new file mode 100644 index 0000000..987d0b0 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepository.php @@ -0,0 +1,41 @@ +getManagerForClass($entityClass); + + if ($manager === null) { + throw new LogicException(sprintf( + 'Could not find the entity manager for class "%s". Check your Doctrine configuration to make sure it is configured to load this entity’s metadata.', + $entityClass + )); + } + + parent::__construct($manager, $manager->getClassMetadata($entityClass)); + } +} diff --git a/vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepositoryInterface.php b/vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepositoryInterface.php new file mode 100644 index 0000000..fe9ce4d --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepositoryInterface.php @@ -0,0 +1,10 @@ + + + + + + Doctrine\DBAL\Logging\LoggerChain + Doctrine\DBAL\Logging\DebugStack + Symfony\Bridge\Doctrine\Logger\DbalLogger + Doctrine\DBAL\Configuration + Doctrine\Bundle\DoctrineBundle\DataCollector\DoctrineDataCollector + Symfony\Bridge\Doctrine\ContainerAwareEventManager + Doctrine\Bundle\DoctrineBundle\ConnectionFactory + Doctrine\DBAL\Event\Listeners\MysqlSessionInit + Doctrine\DBAL\Event\Listeners\OracleSessionInit + Doctrine\Bundle\DoctrineBundle\Registry + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %doctrine.dbal.connection_factory.types% + + + + + + + + + + + + + + + %doctrine.connections% + %doctrine.entity_managers% + %doctrine.default_connection% + %doctrine.default_entity_manager% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/doctrine/doctrine-bundle/Resources/config/messenger.xml b/vendor/doctrine/doctrine-bundle/Resources/config/messenger.xml new file mode 100644 index 0000000..f6ae1cf --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Resources/config/messenger.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/doctrine/doctrine-bundle/Resources/config/orm.xml b/vendor/doctrine/doctrine-bundle/Resources/config/orm.xml new file mode 100644 index 0000000..929fba7 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Resources/config/orm.xml @@ -0,0 +1,213 @@ + + + + + + Doctrine\ORM\Configuration + Doctrine\ORM\EntityManager + Doctrine\Bundle\DoctrineBundle\ManagerConfigurator + + + Doctrine\Common\Cache\ArrayCache + Doctrine\Common\Cache\ApcCache + Doctrine\Common\Cache\MemcacheCache + localhost + 11211 + Memcache + Doctrine\Common\Cache\MemcachedCache + localhost + 11211 + Memcached + Doctrine\Common\Cache\RedisCache + localhost + 6379 + Redis + Doctrine\Common\Cache\XcacheCache + Doctrine\Common\Cache\WinCacheCache + Doctrine\Common\Cache\ZendDataCache + + + Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain + Doctrine\ORM\Mapping\Driver\AnnotationDriver + Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver + Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver + Doctrine\ORM\Mapping\Driver\PHPDriver + Doctrine\ORM\Mapping\Driver\StaticPHPDriver + + + Symfony\Bridge\Doctrine\CacheWarmer\ProxyCacheWarmer + + + Symfony\Bridge\Doctrine\Form\DoctrineOrmTypeGuesser + + + Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator + Symfony\Bridge\Doctrine\Validator\DoctrineInitializer + + + Symfony\Bridge\Doctrine\Security\User\EntityUserProvider + + + Doctrine\ORM\Tools\ResolveTargetEntityListener + Doctrine\ORM\Tools\AttachEntityListenersListener + + + Doctrine\ORM\Mapping\DefaultNamingStrategy + Doctrine\ORM\Mapping\UnderscoreNamingStrategy + + + Doctrine\ORM\Mapping\DefaultQuoteStrategy + Doctrine\ORM\Mapping\AnsiQuoteStrategy + + + Doctrine\Bundle\DoctrineBundle\Mapping\ContainerEntityListenerResolver + + + Doctrine\ORM\Cache\DefaultCacheFactory + Doctrine\ORM\Cache\Region\DefaultRegion + Doctrine\ORM\Cache\Region\FileLockRegion + Doctrine\ORM\Cache\Logging\CacheLoggerChain + Doctrine\ORM\Cache\Logging\StatisticsCacheLogger + Doctrine\ORM\Cache\CacheConfiguration + Doctrine\ORM\Cache\RegionsConfiguration + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CASE_LOWER + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %kernel.bundles% + + + + + diff --git a/vendor/doctrine/doctrine-bundle/Resources/config/schema/doctrine-1.0.xsd b/vendor/doctrine/doctrine-bundle/Resources/config/schema/doctrine-1.0.xsd new file mode 100644 index 0000000..58bab75 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Resources/config/schema/doctrine-1.0.xsd @@ -0,0 +1,271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/doctrine/doctrine-bundle/Resources/views/Collector/db.html.twig b/vendor/doctrine/doctrine-bundle/Resources/views/Collector/db.html.twig new file mode 100644 index 0000000..9dc79f6 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Resources/views/Collector/db.html.twig @@ -0,0 +1,528 @@ +{% extends request.isXmlHttpRequest ? '@WebProfiler/Profiler/ajax_layout.html.twig' : '@WebProfiler/Profiler/layout.html.twig' %} + +{% import _self as helper %} + +{% block toolbar %} + {% if collector.querycount > 0 or collector.invalidEntityCount > 0 %} + + {% set profiler_markup_version = profiler_markup_version|default(1) %} + + {% set icon %} + {% if profiler_markup_version == 1 %} + + Database + {{ collector.querycount }} + {% if collector.querycount > 0 %} + in {{ '%0.2f'|format(collector.time * 1000) }} ms + {% endif %} + {% if collector.invalidEntityCount > 0 %} + {{ collector.invalidEntityCount }} + {% endif %} + + {% else %} + + {% set status = collector.invalidEntityCount > 0 ? 'red' : collector.querycount > 50 ? 'yellow' %} + + {{ include('@Doctrine/Collector/icon.svg') }} + + {% if collector.querycount == 0 and collector.invalidEntityCount > 0 %} + {{ collector.invalidEntityCount }} + errors + {% else %} + {{ collector.querycount }} + + in + {{ '%0.2f'|format(collector.time * 1000) }} + ms + + {% endif %} + + {% endif %} + {% endset %} + + {% set text %} +
+ Database Queries + {{ collector.querycount }} +
+
+ Query time + {{ '%0.2f'|format(collector.time * 1000) }} ms +
+
+ Invalid entities + {{ collector.invalidEntityCount }} +
+ {% if collector.cacheEnabled %} +
+ Cache hits + {{ collector.cacheHitsCount }} +
+
+ Cache misses + {{ collector.cacheMissesCount }} +
+
+ Cache puts + {{ collector.cachePutsCount }} +
+ {% else %} +
+ Second Level Cache + disabled +
+ {% endif %} + {% endset %} + + {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: status|default('') }) }} + + {% endif %} +{% endblock %} + +{% block menu %} + {% set profiler_markup_version = profiler_markup_version|default(1) %} + + {% if profiler_markup_version == 1 %} + + + + Doctrine + + {{ collector.querycount }} + {{ '%0.0f'|format(collector.time * 1000) }} ms + + + + {% else %} + + + {{ include('@Doctrine/Collector/icon.svg') }} + Doctrine + {% if collector.invalidEntityCount %} + + {{ collector.invalidEntityCount }} + + {% endif %} + + + {% endif %} +{% endblock %} + +{% block panel %} + {% set profiler_markup_version = profiler_markup_version|default(1) %} + + {% if 'explain' == page %} + {{ render(controller('DoctrineBundle:Profiler:explain', { + token: token, + panel: 'db', + connectionName: request.query.get('connection'), + query: request.query.get('query') + })) }} + {% else %} + {{ block('queries') }} + {% endif %} +{% endblock %} + +{% block queries %} + + + {% if profiler_markup_version > 1 %} +

Query Metrics

+ +
+
+ {{ collector.querycount }} + Database Queries +
+ +
+ {{ collector.groupedQueryCount }} + Different statements +
+ +
+ {{ '%0.2f'|format(collector.time * 1000) }} ms + Query time +
+ +
+ {{ collector.invalidEntityCount }} + Invalid entities +
+ + {% if collector.cacheEnabled %} +
+ {{ collector.cacheHitsCount }} + Cache hits +
+
+ {{ collector.cacheMissesCount }} + Cache misses +
+
+ {{ collector.cachePutsCount }} + Cache puts +
+ {% endif %} +
+ {% endif %} + + {% set group_queries = request.query.getBoolean('group') %} + {% if group_queries %} +

Grouped Statements

+

Show all queries

+ {% else %} +

Queries

+

Group similar statements

+ {% endif %} + + {% for connection, queries in collector.queries %} + {% if collector.connections|length > 1 %} +

{{ connection }} connection

+ {% endif %} + + {% if queries is empty %} +
+

No database queries were performed.

+
+ {% else %} + {% if group_queries %} + {% set queries = collector.groupedQueries[connection] %} + {% endif %} + + + + {% if group_queries %} + + + {% else %} + + + {% endif %} + + + + + {% for i, query in queries %} + {% set i = group_queries ? query.index : i %} + + {% if group_queries %} + + + {% else %} + + + {% endif %} + + + {% endfor %} + +
TimeCount#TimeInfo
+ + {{ '%0.2f'|format(query.executionMS * 1000) }} ms
({{ '%0.2f'|format(query.executionPercent) }}%)
+
{{ query.count }}{{ loop.index }}{{ '%0.2f'|format(query.executionMS * 1000) }} ms + {{ query.sql|doctrine_pretty_query(highlight_only = true) }} + +
+ Parameters: {{ profiler_dump(query.params, 2) }} +
+ +
+ View formatted query + + {% if query.runnable %} +    + View runnable query + {% endif %} + + {% if query.explainable %} +    + Explain query + {% endif %} + + {% if query.backtrace is defined %} +    + View query backtrace + {% endif %} +
+ + + + {% if query.runnable %} + + {% endif %} + + {% if query.explainable %} +
+ {% endif %} + + {% if query.backtrace is defined %} + + {% endif %} +
+ {% endif %} + {% endfor %} + +

Database Connections

+ + {% if not collector.connections %} +
+

There are no configured database connections.

+
+ {% else %} + {{ helper.render_simple_table('Name', 'Service', collector.connections) }} + {% endif %} + +

Entity Managers

+ + {% if not collector.managers %} +
+

There are no configured entity managers.

+
+ {% else %} + {{ helper.render_simple_table('Name', 'Service', collector.managers) }} + {% endif %} + +

Second Level Cache

+ + {% if not collector.cacheEnabled %} +
+

Second Level Cache is not enabled.

+
+ {% else %} + {% if not collector.cacheCounts %} +
+

Second level cache information is not available.

+
+ {% else %} + {% if profiler_markup_version == 1 %} + {{ helper.render_simple_table('Key', 'Value', collector.cacheCounts) }} + {% else %} +
+
+ {{ collector.cacheCounts.hits }} + Hits +
+ +
+ {{ collector.cacheCounts.misses }} + Misses +
+ +
+ {{ collector.cacheCounts.puts }} + Puts +
+
+ {% endif %} + + {% if collector.cacheRegions.hits %} +

Number of cache hits

+ {{ helper.render_simple_table('Region', 'Hits', collector.cacheRegions.hits) }} + {% endif %} + + {% if collector.cacheRegions.misses %} +

Number of cache misses

+ {{ helper.render_simple_table('Region', 'Misses', collector.cacheRegions.misses) }} + {% endif %} + + {% if collector.cacheRegions.puts %} +

Number of cache puts

+ {{ helper.render_simple_table('Region', 'Puts', collector.cacheRegions.puts) }} + {% endif %} + {% endif %} + {% endif %} + +

Entities Mapping

+ + {% for manager, classes in collector.entities %} + {% if collector.managers|length > 1 %} +

{{ manager }} entity manager

+ {% endif %} + + {% if classes is empty %} +
+

No loaded entities.

+
+ {% else %} + + + + + + + + + {% for class in classes %} + {% set contains_errors = collector.mappingErrors[manager] is defined and collector.mappingErrors[manager][class] is defined %} + + + + + {% endfor %} + +
ClassMapping errors
{{ class }} + {% if contains_errors %} +
    + {% for error in collector.mappingErrors[manager][class] %} +
  • {{ error }}
  • + {% endfor %} +
+ {% else %} + No errors. + {% endif %} +
+ {% endif %} + {% endfor %} + + +{% endblock %} + +{% macro render_simple_table(label1, label2, data) %} + + + + + + + + + {% for key, value in data %} + + + + + {% endfor %} + +
{{ label1 }}{{ label2 }}
{{ key }}{{ value }}
+{% endmacro %} diff --git a/vendor/doctrine/doctrine-bundle/Resources/views/Collector/explain.html.twig b/vendor/doctrine/doctrine-bundle/Resources/views/Collector/explain.html.twig new file mode 100644 index 0000000..3b2dd7f --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Resources/views/Collector/explain.html.twig @@ -0,0 +1,28 @@ +{% if data[0]|length > 1 %} + {# The platform returns a table for the explanation (e.g. MySQL), display all columns #} + + + + {% for label in data[0]|keys %} + + {% endfor %} + + + + {% for row in data %} + + {% for key, item in row %} + + {% endfor %} + + {% endfor %} + +
{{ label }}
{{ item|replace({',': ', '}) }}
+{% else %} + {# The Platform returns a single column for a textual explanation (e.g. PostgreSQL), display all lines #} +
+        {%- for row in data -%}
+            {{ row|first }}{{ "\n" }}
+        {%- endfor -%}
+    
+{% endif %} diff --git a/vendor/doctrine/doctrine-bundle/Resources/views/Collector/icon.svg b/vendor/doctrine/doctrine-bundle/Resources/views/Collector/icon.svg new file mode 100644 index 0000000..49fb528 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Resources/views/Collector/icon.svg @@ -0,0 +1,4 @@ + + + diff --git a/vendor/doctrine/doctrine-bundle/Twig/DoctrineExtension.php b/vendor/doctrine/doctrine-bundle/Twig/DoctrineExtension.php new file mode 100644 index 0000000..b06ac94 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/Twig/DoctrineExtension.php @@ -0,0 +1,203 @@ + ['html']]), + new TwigFilter('doctrine_replace_query_parameters', [$this, 'replaceQueryParameters']), + ]; + } + + /** + * Get the possible combinations of elements from the given array + * + * @param array $elements + * @param int $combinationsLevel + * + * @return array + */ + private function getPossibleCombinations(array $elements, $combinationsLevel) + { + $baseCount = count($elements); + $result = []; + + if ($combinationsLevel === 1) { + foreach ($elements as $element) { + $result[] = [$element]; + } + + return $result; + } + + $nextLevelElements = $this->getPossibleCombinations($elements, $combinationsLevel - 1); + + foreach ($nextLevelElements as $nextLevelElement) { + $lastElement = $nextLevelElement[$combinationsLevel - 2]; + $found = false; + + foreach ($elements as $key => $element) { + if ($element === $lastElement) { + $found = true; + continue; + } + + if ($found !== true || $key >= $baseCount) { + continue; + } + + $tmp = $nextLevelElement; + $newCombination = array_slice($tmp, 0); + $newCombination[] = $element; + $result[] = array_slice($newCombination, 0); + } + } + + return $result; + } + + /** + * Escape parameters of a SQL query + * DON'T USE THIS FUNCTION OUTSIDE ITS INTENDED SCOPE + * + * @internal + * + * @param mixed $parameter + * + * @return string + */ + public static function escapeFunction($parameter) + { + $result = $parameter; + + switch (true) { + // Check if result is non-unicode string using PCRE_UTF8 modifier + case is_string($result) && ! preg_match('//u', $result): + $result = '0x' . strtoupper(bin2hex($result)); + break; + + case is_string($result): + $result = "'" . addslashes($result) . "'"; + break; + + case is_array($result): + foreach ($result as &$value) { + $value = static::escapeFunction($value); + } + + $result = implode(', ', $result); + break; + + case is_object($result): + $result = addslashes((string) $result); + break; + + case $result === null: + $result = 'NULL'; + break; + + case is_bool($result): + $result = $result ? '1' : '0'; + break; + } + + return $result; + } + + /** + * Return a query with the parameters replaced + * + * @param string $query + * @param array|Data $parameters + * + * @return string + */ + public function replaceQueryParameters($query, $parameters) + { + if ($parameters instanceof Data) { + $parameters = $parameters->getValue(true); + } + + $i = 0; + + if (! array_key_exists(0, $parameters) && array_key_exists(1, $parameters)) { + $i = 1; + } + + return preg_replace_callback( + '/\?|((?([^"]*+)<\/pre>/Us', '\1', $html); + } else { + $html = SqlFormatter::format($sql); + $html = preg_replace('/
([^"]*+)<\/pre>/Us', '
\2
', $html); + } + + return $html; + } + + /** + * Get the name of the extension + * + * @return string + */ + public function getName() + { + return 'doctrine_extension'; + } +} diff --git a/vendor/doctrine/doctrine-bundle/UPGRADE-1.11.md b/vendor/doctrine/doctrine-bundle/UPGRADE-1.11.md new file mode 100644 index 0000000..a2fc073 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/UPGRADE-1.11.md @@ -0,0 +1,35 @@ +UPGRADE FROM 1.10 to 1.11 +========================= + +PHP and Symfony version support +------------------------------- + + * Support for PHP 5.5, 5.6 and 7.0 was dropped + * Support for unsupported Symfony versions was dropped. The bundle now supports + Symfony 3.4 LTS and 4.1 or newer. + * Support for Twig 1.34 and below as well as 2.4 and below (for 2.x) releases + was dropped. + +Commands +-------- + + * Deprecated instantiating `Doctrine\Bundle\DoctrineBundle\Command` without a + `ManagerRegistry` instance. + * Deprecated `setContainer` and `getContainer` in + `Doctrine\Bundle\DoctrineBundle\Command`. + * `Doctrine\Bundle\DoctrineBundle\Command` no longer implements + `ContainerAwareInterface`. + +Mapping +------- + + * Renamed `ContainerAwareEntityListenerResolver` to + `ContainerEntityListenerResolver`. + +Types +----- + + * Marking types as commented in the configuration is deprecated. Instead, mark + them commented using the `requiresSQLCommentHint()` method of the type. + * The `commented` configuration option for types will be dropped in a future + release. You should avoid using it. diff --git a/vendor/doctrine/doctrine-bundle/UPGRADE-1.12.md b/vendor/doctrine/doctrine-bundle/UPGRADE-1.12.md new file mode 100644 index 0000000..c180996 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/UPGRADE-1.12.md @@ -0,0 +1,17 @@ +UPGRADE FROM 1.11 to 1.12 +========================= + +Deprecation of DoctrineCacheBundle +---------------------------------- + +With DoctrineCacheBundle [being deprecated](https://github.com/doctrine/DoctrineCacheBundle/issues/156), +configuring caches through it has been deprecated. If you are using anything +other than the `pool` or `id` cache types, please update your configuration to +either use symfony/cache through the `pool` type or configure your cache +services manually and use the `service` type. + +Service aliases +--------------- + + * Deprecated the `Symfony\Bridge\Doctrine\RegistryInterface` and `Doctrine\Bundle\DoctrineBundle\Registry` service alias, use `Doctrine\Common\Persistence\ManagerRegistry` instead. + * Deprecated the `Doctrine\Common\Persistence\ObjectManager` service alias, use `Doctrine\ORM\EntityManagerInterface` instead. diff --git a/vendor/doctrine/doctrine-bundle/UPGRADE-2.0.md b/vendor/doctrine/doctrine-bundle/UPGRADE-2.0.md new file mode 100644 index 0000000..82aee80 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/UPGRADE-2.0.md @@ -0,0 +1,63 @@ +UPGRADE FROM 1.x to 2.0 +======================= + +PHP and Symfony version support +------------------------------- + + * Support for PHP 5.5, 5.6 and 7.0 was dropped + * Support for unsupported Symfony versions was dropped. The bundle now supports + Symfony 3.4 LTS and 4.1 or newer. + * Support for Twig 1.34 and below as well as 2.4 and below (for 2.x) releases + was dropped. + * When no charset parameter is defined, it now defaults to `utf8mb4` on the + MySQL platform and to `utf8` on all other platforms. + +Commands +-------- + + * `Doctrine\Bundle\DoctrineBundle\Command` requires a `ManagerRegistry` + instance when instantiating. + * Dropped `setContainer` and `getContainer` in + `Doctrine\Bundle\DoctrineBundle\Command`. + * `Doctrine\Bundle\DoctrineBundle\Command` no longer implements + `ContainerAwareInterface`. + * `Doctrine\Bundle\DoctrineBundle\Command\GenerateEntitiesDoctrineCommand` was + dropped in favour of the MakerBundle. + +Deprecation of DoctrineCacheBundle +---------------------------------- + +Configuring caches through DoctrineCacheBundle is no longer possible. Please use +symfony/cache through the `pool` type or configure your cache services manually +and use the `service` type. + +Mapping +------- + + * Dropped `ContainerAwareEntityListenerResolver`, use + `ContainerEntityListenerResolver` instead. + +Registry +-------- + + * `Registry` no longer implements `Symfony\Bridge\Doctrine\RegistryInterface`. + * Removed all deprecated entity manager specific methods from the registry. + +Service aliases +--------------- + + * The `Symfony\Bridge\Doctrine\RegistryInterface` interface is no longer aliased + to the `doctrine` service, use `Doctrine\Common\Persistence\ManagerRegistry` + instead. + * The `Doctrine\Common\Persistence\ObjectManager` interface is no longer + aliased to the `doctrine.orm.entity_manager` service, use + `Doctrine\ORM\EntityManagerInterface` instead. + +Types +----- + + * Marking types as commented in the configuration is no longer supported. + Instead, mark them commented using the `requiresSQLCommentHint()` method of + the type. + * The `commented` configuration option for types will be dropped in a future + release. You should not use it. diff --git a/vendor/doctrine/doctrine-bundle/UPGRADE-3.0.md b/vendor/doctrine/doctrine-bundle/UPGRADE-3.0.md new file mode 100644 index 0000000..03ee914 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/UPGRADE-3.0.md @@ -0,0 +1,8 @@ +UPGRADE FROM 2.x to 3.0 +======================= + +Types +----- + + * The `commented` configuration option for types is no longer supported and + deprecated. diff --git a/vendor/doctrine/doctrine-bundle/composer.json b/vendor/doctrine/doctrine-bundle/composer.json new file mode 100644 index 0000000..bed6ef9 --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/composer.json @@ -0,0 +1,75 @@ +{ + "name": "doctrine/doctrine-bundle", + "type": "symfony-bundle", + "description": "Symfony DoctrineBundle", + "keywords": ["DBAL", "ORM", "Database", "Persistence"], + "homepage": "http://www.doctrine-project.org", + "license": "MIT", + "minimum-stability": "dev", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Doctrine Project", + "homepage": "http://www.doctrine-project.org/" + } + ], + "require": { + "php": "^7.1", + "doctrine/dbal": "^2.9.0", + "doctrine/persistence": "^1.3.3", + "jdorn/sql-formatter": "^1.2.16", + "symfony/cache": "^4.3.3|^5.0", + "symfony/config": "^4.3.3|^5.0", + "symfony/console": "^3.4.30|^4.3.3|^5.0", + "symfony/dependency-injection": "^4.3.3|^5.0", + "symfony/doctrine-bridge": "^4.3.7|^5.0", + "symfony/framework-bundle": "^3.4.30|^4.3.3|^5.0", + "symfony/service-contracts": "^1.1.1|^2.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "doctrine/orm": "^2.6", + "ocramius/proxy-manager": "^2.1", + "phpunit/phpunit": "^7.5", + "symfony/phpunit-bridge": "^4.2", + "symfony/property-info": "^4.3.3|^5.0", + "symfony/twig-bridge": "^3.4.30|^4.3.3|^5.0", + "symfony/validator": "^3.4.30|^4.3.3|^5.0", + "symfony/yaml": "^3.4.30|^4.3.3|^5.0", + "twig/twig": "^1.34|^2.12", + "symfony/web-profiler-bundle": "^3.4.30|^4.3.3|^5.0" + }, + "config": { + "sort-packages": true + }, + "conflict": { + "doctrine/orm": "<2.6", + "twig/twig": "<1.34|>=2.0,<2.4" + }, + "suggest": { + "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", + "symfony/web-profiler-bundle": "To use the data collector." + }, + "autoload": { + "psr-4": { "Doctrine\\Bundle\\DoctrineBundle\\": "" } + }, + "autoload-dev": { + "psr-4": { "": "Tests/DependencyInjection" } + }, + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + } +} diff --git a/vendor/doctrine/doctrine-bundle/phpcs.xml.dist b/vendor/doctrine/doctrine-bundle/phpcs.xml.dist new file mode 100644 index 0000000..c91a02d --- /dev/null +++ b/vendor/doctrine/doctrine-bundle/phpcs.xml.dist @@ -0,0 +1,53 @@ + + + + + + + + + + + + . + vendor/* + + + + + + + + + + + + + + + + + Tests/* + + + Tests/* + + + Tests/DependencyInjection/Fixtures/* + + + DependencyInjection/* + Twig/DoctrineExtension.php + Tests/* + + + DependencyInjection/* + Twig/DoctrineExtension.php + Tests/* + + + DependencyInjection/* + Twig/DoctrineExtension.php + Tests/* + + diff --git a/vendor/doctrine/doctrine-fixtures-bundle/.github/FUNDING.yml b/vendor/doctrine/doctrine-fixtures-bundle/.github/FUNDING.yml new file mode 100644 index 0000000..3c0102b --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/.github/FUNDING.yml @@ -0,0 +1,3 @@ +patreon: phpdoctrine +tidelift: packagist/doctrine%2Fdoctrine-fixtures-bundle +custom: https://www.doctrine-project.org/sponsorship.html diff --git a/vendor/doctrine/doctrine-fixtures-bundle/.gitignore b/vendor/doctrine/doctrine-fixtures-bundle/.gitignore new file mode 100644 index 0000000..2b1bf5a --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +.phpcs-cache diff --git a/vendor/doctrine/doctrine-fixtures-bundle/.travis.yml b/vendor/doctrine/doctrine-fixtures-bundle/.travis.yml new file mode 100644 index 0000000..284ebee --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/.travis.yml @@ -0,0 +1,45 @@ +language: php +sudo: false +cache: + directories: + - $HOME/.composer/cache/files + +php: + - 7.1 + - 7.2 + - 7.3 + - 7.4snapshot + +jobs: + include: + # Minimum supported PHP and Symfony version + - stage: test + php: 7.1 + env: DEPENDENCIES="minimum" + + # Test LTS version we support + - stage: test + php: 7.3 + env: DEPENDENCIES="symfony/lts:v3" + + - stage: test + php: 7.3 + env: DEPENDENCIES="dev" + + # Run phpcs + - stage: Code Quality + php: 7.2 + env: CODING_STANDARDS + script: + - vendor/bin/phpcs + +before_install: + - if [ "$DEPENDENCIES" = "minimum" ]; then COMPOSER_FLAGS="--prefer-stable --prefer-lowest"; fi; + - if [ "$DEPENDENCIES" = "dev" ]; then composer config minimum-stability dev; fi; + - if [[ $DEPENDENCIES == *"/"* ]]; then composer require --no-update $DEPENDENCIES; fi; + +install: + - travis_retry composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction + +script: + - vendor/bin/phpunit diff --git a/vendor/doctrine/doctrine-fixtures-bundle/CHANGELOG-3.1.md b/vendor/doctrine/doctrine-fixtures-bundle/CHANGELOG-3.1.md new file mode 100644 index 0000000..7f8d2fc --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/CHANGELOG-3.1.md @@ -0,0 +1,14 @@ +CHANGELOG for 3.1.x +=================== + +This changelog references the relevant changes (bug and security fixes) done in +3.1 minor versions. + +3.1.0 (2018-12-21) +------------------ + + - [270: Show the name of the database being purged when loading fixtures](https://github.com/doctrine/DoctrineFixturesBundle/pull/270) thanks to @alcaeus + - [265: Drop support for PHP < 7.1 and older versions of data-fixtures](https://github.com/doctrine/DoctrineFixturesBundle/pull/265) thanks to @alcaeus + - [260: Add fixture groups via a static method interface or service tags](https://github.com/doctrine/DoctrineFixturesBundle/pull/260) thanks to @weaverryan + - [269: Apply Doctrine Coding Standard](https://github.com/doctrine/DoctrineFixturesBundle/pull/269) thanks to @carusogabriel + - [219: Dynamic namespace](https://github.com/doctrine/DoctrineFixturesBundle/issues/219) thanks to @MassiveHiggsField diff --git a/vendor/doctrine/doctrine-fixtures-bundle/Command/LoadDataFixturesDoctrineCommand.php b/vendor/doctrine/doctrine-fixtures-bundle/Command/LoadDataFixturesDoctrineCommand.php new file mode 100644 index 0000000..87f7604 --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/Command/LoadDataFixturesDoctrineCommand.php @@ -0,0 +1,131 @@ +fixturesLoader = $fixturesLoader; + } + + // phpcs:ignore SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingReturnTypeHint + protected function configure() + { + $this + ->setName('doctrine:fixtures:load') + ->setDescription('Load data fixtures to your database') + ->addOption('append', null, InputOption::VALUE_NONE, 'Append the data fixtures instead of deleting all data from the database first.') + ->addOption('group', null, InputOption::VALUE_IS_ARRAY|InputOption::VALUE_REQUIRED, 'Only load fixtures that belong to this group') + ->addOption('em', null, InputOption::VALUE_REQUIRED, 'The entity manager to use for this command.') + ->addOption('shard', null, InputOption::VALUE_REQUIRED, 'The shard connection to use for this command.') + ->addOption('purge-with-truncate', null, InputOption::VALUE_NONE, 'Purge data by using a database-level TRUNCATE statement') + ->setHelp(<<%command.name% command loads data fixtures from your application: + + php %command.full_name% + +Fixtures are services that are tagged with doctrine.fixture.orm. + +If you want to append the fixtures instead of flushing the database first you can use the --append option: + + php %command.full_name% --append + +By default Doctrine Data Fixtures uses DELETE statements to drop the existing rows from the database. +If you want to use a TRUNCATE statement instead you can use the --purge-with-truncate flag: + + php %command.full_name% --purge-with-truncate + +To execute only fixtures that live in a certain group, use: + + php %command.full_name% --group=group1 + +EOT + ); + } + + /** + * @return int + */ + // phpcs:ignore SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingReturnTypeHint + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + $em = $this->getDoctrine()->getManager($input->getOption('em')); + + if (! $input->getOption('append')) { + if (! $ui->confirm(sprintf('Careful, database "%s" will be purged. Do you want to continue?', $em->getConnection()->getDatabase()), ! $input->isInteractive())) { + return 0; + } + } + + if ($input->getOption('shard')) { + if (! $em->getConnection() instanceof PoolingShardConnection) { + throw new LogicException(sprintf( + 'Connection of EntityManager "%s" must implement shards configuration.', + $input->getOption('em') + )); + } + + $em->getConnection()->connect($input->getOption('shard')); + } + + $groups = $input->getOption('group'); + $fixtures = $this->fixturesLoader->getFixtures($groups); + if (! $fixtures) { + $message = 'Could not find any fixture services to load'; + + if (! empty($groups)) { + $message .= sprintf(' in the groups (%s)', implode(', ', $groups)); + } + + $ui->error($message . '.'); + + return 1; + } + $purger = new ORMPurger($em); + $purger->setPurgeMode($input->getOption('purge-with-truncate') ? ORMPurger::PURGE_MODE_TRUNCATE : ORMPurger::PURGE_MODE_DELETE); + $executor = new ORMExecutor($em, $purger); + $executor->setLogger(static function ($message) use ($ui) : void { + $ui->text(sprintf(' > %s', $message)); + }); + $executor->execute($fixtures, $input->getOption('append')); + + return 0; + } +} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/CompilerPass/FixturesCompilerPass.php b/vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/CompilerPass/FixturesCompilerPass.php new file mode 100644 index 0000000..5fc5b4a --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/CompilerPass/FixturesCompilerPass.php @@ -0,0 +1,39 @@ +getDefinition('doctrine.fixtures.loader'); + $taggedServices = $container->findTaggedServiceIds(self::FIXTURE_TAG); + + $fixtures = []; + foreach ($taggedServices as $serviceId => $tags) { + $groups = []; + foreach ($tags as $tagData) { + if (! isset($tagData['group'])) { + continue; + } + + $groups[] = $tagData['group']; + } + + $fixtures[] = [ + 'fixture' => new Reference($serviceId), + 'groups' => $groups, + ]; + } + + $definition->addMethodCall('addFixtures', [$fixtures]); + } +} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/DoctrineFixturesExtension.php b/vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/DoctrineFixturesExtension.php new file mode 100644 index 0000000..0dd4beb --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/DoctrineFixturesExtension.php @@ -0,0 +1,29 @@ +load('services.xml'); + + $container->registerForAutoconfiguration(ORMFixtureInterface::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + } +} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/DoctrineFixturesBundle.php b/vendor/doctrine/doctrine-fixtures-bundle/DoctrineFixturesBundle.php new file mode 100644 index 0000000..256fc74 --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/DoctrineFixturesBundle.php @@ -0,0 +1,21 @@ +addCompilerPass(new FixturesCompilerPass()); + } +} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/Fixture.php b/vendor/doctrine/doctrine-fixtures-bundle/Fixture.php new file mode 100644 index 0000000..3fb0cee --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/Fixture.php @@ -0,0 +1,15 @@ +> */ + private $groupsFixtureMapping = []; + + /** + * @internal + */ + public function addFixtures(array $fixtures) : void + { + // Because parent::addFixture may call $this->createFixture + // we cannot call $this->addFixture in this loop + foreach ($fixtures as $fixture) { + $class = get_class($fixture['fixture']); + $this->loadedFixtures[$class] = $fixture['fixture']; + $this->addGroupsFixtureMapping($class, $fixture['groups']); + } + + // Now that all fixtures are in the $this->loadedFixtures array, + // it is safe to call $this->addFixture in this loop + foreach ($this->loadedFixtures as $fixture) { + $this->addFixture($fixture); + } + } + + public function addFixture(FixtureInterface $fixture) : void + { + $class = get_class($fixture); + $this->loadedFixtures[$class] = $fixture; + + $reflection = new ReflectionClass($fixture); + $this->addGroupsFixtureMapping($class, [$reflection->getShortName()]); + + if ($fixture instanceof FixtureGroupInterface) { + $this->addGroupsFixtureMapping($class, $fixture::getGroups()); + } + + parent::addFixture($fixture); + } + + /** + * Overridden to not allow new fixture classes to be instantiated. + * + * @param string $class + */ + protected function createFixture($class) : FixtureInterface + { + /* + * We don't actually need to create the fixture. We just + * return the one that already exists. + */ + + if (! isset($this->loadedFixtures[$class])) { + throw new LogicException(sprintf( + 'The "%s" fixture class is trying to be loaded, but is not available. Make sure this class is defined as a service and tagged with "%s".', + $class, + FixturesCompilerPass::FIXTURE_TAG + )); + } + + return $this->loadedFixtures[$class]; + } + + /** + * Returns the array of data fixtures to execute. + * + * @param string[] $groups + * + * @return FixtureInterface[] + */ + public function getFixtures(array $groups = []) : array + { + $fixtures = parent::getFixtures(); + + if (empty($groups)) { + return $fixtures; + } + + $filteredFixtures = []; + foreach ($fixtures as $fixture) { + foreach ($groups as $group) { + $fixtureClass = get_class($fixture); + if (isset($this->groupsFixtureMapping[$group][$fixtureClass])) { + $filteredFixtures[$fixtureClass] = $fixture; + continue 2; + } + } + } + + foreach ($filteredFixtures as $fixture) { + $this->validateDependencies($filteredFixtures, $fixture); + } + + return array_values($filteredFixtures); + } + + /** + * Generates an array of the groups and their fixtures + * + * @param string[] $groups + */ + private function addGroupsFixtureMapping(string $className, array $groups) : void + { + foreach ($groups as $group) { + $this->groupsFixtureMapping[$group][$className] = true; + } + } + + /** + * @param string[] $fixtures An array of fixtures with class names as keys + * + * @throws RuntimeException + */ + private function validateDependencies(array $fixtures, FixtureInterface $fixture) : void + { + if (! $fixture instanceof DependentFixtureInterface) { + return; + } + + $dependenciesClasses = $fixture->getDependencies(); + + foreach ($dependenciesClasses as $class) { + if (! array_key_exists($class, $fixtures)) { + throw new RuntimeException(sprintf('Fixture "%s" was declared as a dependency for fixture "%s", but it was not included in any of the loaded fixture groups.', $class, get_class($fixture))); + } + } + } +} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/ORMFixtureInterface.php b/vendor/doctrine/doctrine-fixtures-bundle/ORMFixtureInterface.php new file mode 100644 index 0000000..59260d9 --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/ORMFixtureInterface.php @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + + + diff --git a/vendor/doctrine/doctrine-fixtures-bundle/Resources/doc/index.rst b/vendor/doctrine/doctrine-fixtures-bundle/Resources/doc/index.rst new file mode 100644 index 0000000..06bcb90 --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/Resources/doc/index.rst @@ -0,0 +1,293 @@ +DoctrineFixturesBundle +====================== + +Fixtures are used to load a "fake" set of data into a database that can then +be used for testing or to help give you some interesting data while you're +developing your application. This bundle makes creating fixtures *easy*, and +supports the `ORM`_ (MySQL, PostgreSQL, SQLite, etc.). + +Installation +------------ + +In Symfony 4 or higher applications that use `Symfony Flex`_, open a command +console, enter your project directory and run the following command: + +.. code-block:: terminal + + $ composer require --dev orm-fixtures + +Starting from Symfony 4.0, Flex should be used by default and register the +bundle for you, and in that case you can skip to the next section and start +writing fixtures. + +In Symfony 3 applications (or when not using Symfony Flex), run this other +command instead: + +.. code-block:: terminal + + $ composer require --dev doctrine/doctrine-fixtures-bundle + +You will also need to enable the bundle. In Symfony 3 and earlier applications, +update the ``AppKernel`` class:: + + // app/AppKernel.php + + // ... + // registerBundles() + if (in_array($this->getEnvironment(), ['dev', 'test'], true)) { + // ... + $bundles[] = new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(); + } + +Writing Fixtures +---------------- + +Data fixtures are PHP classes where you create objects and persist them to the +database. + +Imagine that you want to add some ``Product`` objects to your database. No problem! +Create a fixtures class and start adding products:: + + // src/DataFixtures/AppFixtures.php + namespace App\DataFixtures; + + use App\Entity\Product; + use Doctrine\Bundle\FixturesBundle\Fixture; + use Doctrine\Common\Persistence\ObjectManager; + + class AppFixtures extends Fixture + { + public function load(ObjectManager $manager) + { + // create 20 products! Bam! + for ($i = 0; $i < 20; $i++) { + $product = new Product(); + $product->setName('product '.$i); + $product->setPrice(mt_rand(10, 100)); + $manager->persist($product); + } + + $manager->flush(); + } + } + +.. tip:: + + You can also create multiple fixtures classes. See :ref:`multiple-files`. + +Loading Fixtures +---------------- + +Once your fixtures have been written, load them by executing this command: + +.. code-block:: terminal + + # when using the ORM + $ php bin/console doctrine:fixtures:load + +.. caution:: + + By default the ``load`` command **purges the database**, removing all data + from every table. To append your fixtures' data add the ``--append`` option. + +This command looks for all services tagged with ``doctrine.fixture.orm``. If you're +using the `default service configuration`_, any class that implements ``ORMFixtureInterface`` +(for example, those extending from ``Fixture``) will automatically be registered +with this tag. + +To see other options for the command, run: + +.. code-block:: terminal + + $ php bin/console doctrine:fixtures:load --help + +Accessing Services from the Fixtures +------------------------------------ + +In some cases you may need to access your application's services inside a fixtures +class. No problem! Your fixtures class is a service, so you can use normal dependency +injection:: + + // src/DataFixtures/AppFixtures.php + use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; + + // ... + private $encoder; + + public function __construct(UserPasswordEncoderInterface $encoder) + { + $this->encoder = $encoder; + } + + // ... + public function load(ObjectManager $manager) + { + $user = new User(); + $user->setUsername('admin'); + + $password = $this->encoder->encodePassword($user, 'pass_1234'); + $user->setPassword($password); + + $manager->persist($user); + $manager->flush(); + } + +You can also access the container via the ``$this->container`` property. +But remember that not *all* services (i.e. private services) can be accessed +directly via the container. + +.. _multiple-files: + +Splitting Fixtures into Separate Files +-------------------------------------- + +In most applications, creating all your fixtures in just one class is fine. +This class may end up being a bit long, but it's worth it because having one +file helps keeping things simple. + +If you do decide to split your fixtures into separate files, Symfony helps you +solve the two most common issues: sharing objects between fixtures and loading +the fixtures in order. + +Sharing Objects between Fixtures +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When using multiple fixtures files, you can reuse PHP objects across different +files thanks to the **object references**. Use the ``addReference()`` method to +give a name to any object and then, use the ``getReference()`` method to get the +exact same object via its name:: + + // src/DataFixtures/UserFixtures.php + // ... + class UserFixtures extends Fixture + { + public const ADMIN_USER_REFERENCE = 'admin-user'; + + public function load(ObjectManager $manager) + { + $userAdmin = new User('admin', 'pass_1234'); + $manager->persist($userAdmin); + $manager->flush(); + + // other fixtures can get this object using the UserFixtures::ADMIN_USER_REFERENCE constant + $this->addReference(self::ADMIN_USER_REFERENCE, $userAdmin); + } + } + + // src/DataFixtures/GroupFixtures.php + // ... + class GroupFixtures extends Fixture + { + public function load(ObjectManager $manager) + { + $userGroup = new Group('administrators'); + // this reference returns the User object created in UserFixtures + $userGroup->addUser($this->getReference(UserFixtures::ADMIN_USER_REFERENCE)); + + $manager->persist($userGroup); + $manager->flush(); + } + } + +The only caveat of using references is that fixtures need to be loaded in a +certain order (in this example, if the ``Group`` fixtures are load before the +``User`` fixtures, you'll see an error). By default Doctrine loads the fixture +files in alphabetical order, but you can control their order as explained in the +next section. + +Loading the Fixture Files in Order +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Instead of defining the exact order in which all fixture files must be loaded, +Doctrine uses a smarter approach to ensure that some fixtures are loaded before +others. Implement the ``DependentFixtureInterface`` and add a new +``getDependencies()`` method to your fixtures class. This will return +an array of the fixture classes that must be loaded before this one:: + + // src/DataFixtures/UserFixtures.php + namespace App\DataFixtures; + + // ... + class UserFixtures extends Fixture + { + public function load(ObjectManager $manager) + { + // ... + } + } + + // src/DataFixtures/GroupFixtures.php + namespace App\DataFixtures; + // ... + use App\DataFixtures\UserFixtures; + use Doctrine\Common\DataFixtures\DependentFixtureInterface; + + class GroupFixtures extends Fixture implements DependentFixtureInterface + { + public function load(ObjectManager $manager) + { + // ... + } + + public function getDependencies() + { + return array( + UserFixtures::class, + ); + } + } + +Fixture Groups: Only Executing Some Fixtures +-------------------------------------------- + +By default, *all* of your fixture classes are executed. If you only want +to execute *some* of your fixture classes, you can organize them into +groups. + +The simplest way to organize a fixture class into a group is to +make your fixture implement ``FixtureGroupInterface``: + +.. code-block:: diff + + // src/DataFixtures/UserFixtures.php + + + use Doctrine\Bundle\FixturesBundle\FixtureGroupInterface; + + - class UserFixtures extends Fixture + + class UserFixtures extends Fixture implements FixtureGroupInterface + { + // ... + + + public static function getGroups(): array + + { + + return ['group1', 'group2']; + + } + } + +To execute all of your fixtures for a given group, pass the ``--group`` +option: + +.. code-block:: terminal + + $ php bin/console doctrine:fixtures:load --group=group1 + + # or to execute multiple groups + $ php bin/console doctrine:fixtures:load --group=group1 --group=group2 + +Alternatively, instead of implementing the ``FixtureGroupInterface``, +you can also tag your service with ``doctrine.fixture.orm`` and add +an extra ``group`` option set to a group your fixture should belong to. + +Regardless of groups defined in the fixture or the service definition, the +fixture loader always adds the short name of the class as a separate group so +you can load a single fixture at a time. In the example above, you can load the +fixture using the ``UserFixtures`` group: + +.. code-block:: terminal + + $ php bin/console doctrine:fixtures:load --group=UserFixtures + +.. _`ORM`: https://symfony.com/doc/current/doctrine.html +.. _`installation chapter`: https://getcomposer.org/doc/00-intro.md +.. _`Symfony Flex`: https://symfony.com/doc/current/setup/flex.html +.. _`default service configuration`: https://symfony.com/doc/current/service_container.html#service-container-services-load-example diff --git a/vendor/doctrine/doctrine-fixtures-bundle/Tests/Command/LoadDataFixturesDoctrineCommandTest.php b/vendor/doctrine/doctrine-fixtures-bundle/Tests/Command/LoadDataFixturesDoctrineCommandTest.php new file mode 100644 index 0000000..39b53a5 --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/Tests/Command/LoadDataFixturesDoctrineCommandTest.php @@ -0,0 +1,43 @@ +expectExceptionMessage('Argument 1 passed to Doctrine\Bundle\DoctrineBundle\Command\DoctrineCommand::__construct() must be an instance of Doctrine\Common\Persistence\ManagerRegistry, null given'); + + throw $e; + } + } + + /** + * @doesNotPerformAssertions + */ + public function testInstantiatingWithManagerRegistry() : void + { + $registry = $this->createMock(ManagerRegistry::class); + $loader = new SymfonyFixturesLoader(new Container()); + + new LoadDataFixturesDoctrineCommand($loader, $registry); + } +} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/DependentOnRequiredConstructorArgsFixtures.php b/vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/DependentOnRequiredConstructorArgsFixtures.php new file mode 100644 index 0000000..7fc6b2b --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/DependentOnRequiredConstructorArgsFixtures.php @@ -0,0 +1,22 @@ +addServices(static function (ContainerBuilder $c) : void { + $c->autowire(OtherFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + $c->autowire(WithDependenciesFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); + }); + $kernel->boot(); + $container = $kernel->getContainer(); + + /** @var ContainerAwareLoader $loader */ + $loader = $container->get('test.doctrine.fixtures.loader'); + + $actualFixtures = $loader->getFixtures(); + $this->assertCount(2, $actualFixtures); + $actualFixtureClasses = array_map(static function ($fixture) { + return get_class($fixture); + }, $actualFixtures); + + $this->assertSame([ + OtherFixtures::class, + WithDependenciesFixtures::class, + ], $actualFixtureClasses); + $this->assertInstanceOf(WithDependenciesFixtures::class, $actualFixtures[1]); + } + + public function testFixturesLoaderWhenFixtureHasDepdencenyThatIsNotYetLoaded() : void + { + // See https://github.com/doctrine/DoctrineFixturesBundle/issues/215 + + $kernel = new IntegrationTestKernel('dev', true); + $kernel->addServices(static function (ContainerBuilder $c) : void { + $c->autowire(WithDependenciesFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + $c->autowire(OtherFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); + }); + $kernel->boot(); + $container = $kernel->getContainer(); + + /** @var ContainerAwareLoader $loader */ + $loader = $container->get('test.doctrine.fixtures.loader'); + + $actualFixtures = $loader->getFixtures(); + $this->assertCount(2, $actualFixtures); + $actualFixtureClasses = array_map(static function ($fixture) { + return get_class($fixture); + }, $actualFixtures); + + $this->assertSame([ + OtherFixtures::class, + WithDependenciesFixtures::class, + ], $actualFixtureClasses); + $this->assertInstanceOf(WithDependenciesFixtures::class, $actualFixtures[1]); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage The getDependencies() method returned a class (Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\RequiredConstructorArgsFixtures) that has required constructor arguments. Upgrade to "doctrine/data-fixtures" version 1.3 or higher to support this. + */ + public function testExceptionWithDependenciesWithRequiredArguments() : void + { + // see https://github.com/doctrine/data-fixtures/pull/274 + // When that is merged, this test will only run when using + // an older version of that library. + if (method_exists(Loader::class, 'createFixture')) { + $this->markTestSkipped(); + } + + $kernel = new IntegrationTestKernel('dev', true); + $kernel->addServices(static function (ContainerBuilder $c) : void { + $c->autowire(DependentOnRequiredConstructorArgsFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + $c->autowire(RequiredConstructorArgsFixtures::class) + ->setArgument(0, 'foo') + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); + }); + $kernel->boot(); + $container = $kernel->getContainer(); + + /** @var ContainerAwareLoader $loader */ + $loader = $container->get('test.doctrine.fixtures.loader'); + + $loader->getFixtures(); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage The "Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\RequiredConstructorArgsFixtures" fixture class is trying to be loaded, but is not available. Make sure this class is defined as a service and tagged with "doctrine.fixture.orm". + */ + public function testExceptionIfDependentFixtureNotWired() : void + { + // only runs on newer versions of doctrine/data-fixtures + if (! method_exists(Loader::class, 'createFixture')) { + $this->markTestSkipped(); + } + + $kernel = new IntegrationTestKernel('dev', true); + $kernel->addServices(static function (ContainerBuilder $c) : void { + $c->autowire(DependentOnRequiredConstructorArgsFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); + }); + $kernel->boot(); + $container = $kernel->getContainer(); + + /** @var ContainerAwareLoader $loader */ + $loader = $container->get('test.doctrine.fixtures.loader'); + + $loader->getFixtures(); + } + + public function testFixturesLoaderWithGroupsOptionViaInterface() : void + { + $kernel = new IntegrationTestKernel('dev', true); + $kernel->addServices(static function (ContainerBuilder $c) : void { + // has a "staging" group via the getGroups() method + $c->autowire(OtherFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + // no getGroups() method + $c->autowire(WithDependenciesFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); + }); + $kernel->boot(); + $container = $kernel->getContainer(); + + /** @var ContainerAwareLoader $loader */ + $loader = $container->get('test.doctrine.fixtures.loader'); + + $actualFixtures = $loader->getFixtures(['staging']); + $this->assertCount(1, $actualFixtures); + $actualFixtureClasses = array_map(static function ($fixture) { + return get_class($fixture); + }, $actualFixtures); + + $this->assertSame([ + OtherFixtures::class, + ], $actualFixtureClasses); + $this->assertInstanceOf(OtherFixtures::class, $actualFixtures[0]); + } + + public function testFixturesLoaderWithGroupsOptionViaTag() : void + { + $kernel = new IntegrationTestKernel('dev', true); + $kernel->addServices(static function (ContainerBuilder $c) : void { + // has a "staging" group via the getGroups() method + $c->autowire(OtherFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG, ['group' => 'group1']) + ->addTag(FixturesCompilerPass::FIXTURE_TAG, ['group' => 'group2']); + + // no getGroups() method + $c->autowire(WithDependenciesFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG, ['group' => 'group2']); + + $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); + }); + $kernel->boot(); + $container = $kernel->getContainer(); + + /** @var ContainerAwareLoader $loader */ + $loader = $container->get('test.doctrine.fixtures.loader'); + + $this->assertCount(1, $loader->getFixtures(['staging'])); + $this->assertCount(1, $loader->getFixtures(['group1'])); + $this->assertCount(2, $loader->getFixtures(['group2'])); + $this->assertCount(0, $loader->getFixtures(['group3'])); + } + + public function testLoadFixturesViaGroupWithMissingDependency() : void + { + $kernel = new IntegrationTestKernel('dev', true); + $kernel->addServices(static function (ContainerBuilder $c) : void { + // has a "staging" group via the getGroups() method + $c->autowire(OtherFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + // no getGroups() method + $c->autowire(WithDependenciesFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); + }); + $kernel->boot(); + $container = $kernel->getContainer(); + + /** @var ContainerAwareLoader $loader */ + $loader = $container->get('test.doctrine.fixtures.loader'); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Fixture "Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\OtherFixtures" was declared as a dependency for fixture "Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\WithDependenciesFixtures", but it was not included in any of the loaded fixture groups.'); + + $loader->getFixtures(['missingDependencyGroup']); + } + + public function testLoadFixturesViaGroupWithFulfilledDependency() : void + { + $kernel = new IntegrationTestKernel('dev', true); + $kernel->addServices(static function (ContainerBuilder $c) : void { + // has a "staging" group via the getGroups() method + $c->autowire(OtherFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + // no getGroups() method + $c->autowire(WithDependenciesFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); + }); + $kernel->boot(); + $container = $kernel->getContainer(); + + /** @var ContainerAwareLoader $loader */ + $loader = $container->get('test.doctrine.fixtures.loader'); + + $actualFixtures = $loader->getFixtures(['fulfilledDependencyGroup']); + + $this->assertCount(2, $actualFixtures); + $actualFixtureClasses = array_map(static function ($fixture) { + return get_class($fixture); + }, $actualFixtures); + + $this->assertSame([ + OtherFixtures::class, + WithDependenciesFixtures::class, + ], $actualFixtureClasses); + } + + public function testLoadFixturesByShortName() : void + { + $kernel = new IntegrationTestKernel('dev', true); + $kernel->addServices(static function (ContainerBuilder $c) : void { + // has a "staging" group via the getGroups() method + $c->autowire(OtherFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + // no getGroups() method + $c->autowire(WithDependenciesFixtures::class) + ->addTag(FixturesCompilerPass::FIXTURE_TAG); + + $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); + }); + $kernel->boot(); + $container = $kernel->getContainer(); + + /** @var ContainerAwareLoader $loader */ + $loader = $container->get('test.doctrine.fixtures.loader'); + + $actualFixtures = $loader->getFixtures(['OtherFixtures']); + + $this->assertCount(1, $actualFixtures); + $actualFixtureClasses = array_map(static function ($fixture) { + return get_class($fixture); + }, $actualFixtures); + + $this->assertSame([ + OtherFixtures::class, + ], $actualFixtureClasses); + } +} + +class IntegrationTestKernel extends Kernel +{ + /** @var callable */ + private $servicesCallback; + + /** @var int */ + private $randomKey; + + public function __construct(string $environment, bool $debug) + { + $this->randomKey = rand(100, 999); + + parent::__construct($environment, $debug); + } + + protected function getContainerClass() : string + { + return 'test' . $this->randomKey . parent::getContainerClass(); + } + + public function registerBundles() : array + { + return [ + new DoctrineFixturesBundle(), + new FooBundle(), + ]; + } + + public function addServices(callable $callback) : void + { + $this->servicesCallback = $callback; + } + + public function registerContainerConfiguration(LoaderInterface $loader) : void + { + $loader->load(function (ContainerBuilder $c) : void { + if (! $c->hasDefinition('kernel')) { + $c->register('kernel', static::class) + ->setSynthetic(true) + ->setPublic(true); + } + + $c->register('doctrine', ManagerRegistry::class); + + $callback = $this->servicesCallback; + $callback($c); + + $c->addObjectResource($this); + }); + } + + public function getCacheDir() : string + { + return sys_get_temp_dir() . '/doctrine_fixtures_bundle' . $this->randomKey; + } + + public function getLogDir() : string + { + return sys_get_temp_dir(); + } +} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/UPGRADE.md b/vendor/doctrine/doctrine-fixtures-bundle/UPGRADE.md new file mode 100644 index 0000000..f602be1 --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/UPGRADE.md @@ -0,0 +1,56 @@ +UPGRADE to 3.0 +============== + +* The automatic loading of fixtures in a directory (e.g. + AppBundle\DataFixtures\ORM) was removed. Instead, register + your fixture classes as services and tag them with `doctrine.fixture.orm`, + like this: +```yaml +# src/AppBundle/Resources/config/dataFixture.yml +services: + _defaults: + tags: ['doctrine.fixture.orm'] + autowire: true # if you need dependency injection, see next bullet point + + AppBundle\DataFixtures\ORM\: + resource: '../../DataFixtures/ORM/*' +``` + + This will happen automatically if you're using the Symfony 3.3 + or higher **default service configuration** and your fixture classes + extend the normal ``Doctrine\Bundle\FixturesBundle\Fixture`` class, + or implement the new ``Doctrine\Bundle\FixturesBundle\ORMFixtureInterface``. + +* The base ``Fixture`` class no longer implements ``ContainerAwareInterface`` + and so no longer have a ``$this->container`` property. You *can* manually + implement this interface. Or, a better idea is to update your fixtures + to use dependency injection: + +```diff +class MyFixture extends Fixture +{ ++ private $someService; + ++ public function __construct(SomeService $someService) ++ { ++ $this->someService = $someService; ++ } + + public function load(ObjectManager $manager) + { +- $this->container->get('some_service')->someMethod(); ++ $this->someService->someMethod(); + } +} +``` + +* The base ``Fixture`` class no longer implements ``DependentFixtureInterface``. + If you want to have a ``getDependencies()`` method, be sure to implement + this interface explicitly: + +```diff ++ use Doctrine\Common\DataFixtures\DependentFixtureInterface; + +- class MyFixture extends Fixture ++ class MyFixture extends Fixture implements DependentFixtureInterface +``` diff --git a/vendor/doctrine/doctrine-fixtures-bundle/composer.json b/vendor/doctrine/doctrine-fixtures-bundle/composer.json new file mode 100644 index 0000000..65d3385 --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/composer.json @@ -0,0 +1,49 @@ +{ + "name": "doctrine/doctrine-fixtures-bundle", + "type": "symfony-bundle", + "description": "Symfony DoctrineFixturesBundle", + "keywords": ["Persistence", "Fixture"], + "homepage": "http://www.doctrine-project.org", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Doctrine Project", + "homepage": "http://www.doctrine-project.org" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "require": { + "php": "^7.1", + "doctrine/data-fixtures": "^1.3", + "doctrine/doctrine-bundle": "^1.11|^2.0", + "doctrine/orm": "^2.6.0", + "symfony/doctrine-bridge": "^3.4|^4.1|^5.0", + "symfony/config": "^3.4|^4.3|^5.0", + "symfony/console": "^3.4|^4.3|^5.0", + "symfony/dependency-injection": "^3.4|^4.3|^5.0", + "symfony/http-kernel": "^3.4|^4.3|^5.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.4", + "symfony/phpunit-bridge": "^4.1|^5.0" + }, + "autoload": { + "psr-4": { "Doctrine\\Bundle\\FixturesBundle\\": "" } + }, + "config": { + "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-master": "3.3.x-dev" + } + } +} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/phpcs.xml.dist b/vendor/doctrine/doctrine-fixtures-bundle/phpcs.xml.dist new file mode 100644 index 0000000..6c6a537 --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/phpcs.xml.dist @@ -0,0 +1,35 @@ + + + + + + + + + + + + . + /vendor + + + + + + + + + + FixtureGroupInterface.php + ORMFixtureInterface.php + + + Loader/SymfonyFixturesLoader.php + + + Tests/IntegrationTest.php + + + Tests/IntegrationTest.php + + diff --git a/vendor/doctrine/doctrine-fixtures-bundle/phpunit.xml.dist b/vendor/doctrine/doctrine-fixtures-bundle/phpunit.xml.dist new file mode 100644 index 0000000..716bd48 --- /dev/null +++ b/vendor/doctrine/doctrine-fixtures-bundle/phpunit.xml.dist @@ -0,0 +1,24 @@ + + + + + + ./Tests + + + + + + . + + ./Resources + ./Tests + ./vendor + + + + + + + + diff --git a/vendor/doctrine/event-manager/.doctrine-project.json b/vendor/doctrine/event-manager/.doctrine-project.json new file mode 100644 index 0000000..f6feb43 --- /dev/null +++ b/vendor/doctrine/event-manager/.doctrine-project.json @@ -0,0 +1,18 @@ +{ + "active": true, + "name": "Event Manager", + "slug": "event-manager", + "docsSlug": "doctrine-event-manager", + "versions": [ + { + "name": "1.0", + "branchName": "master", + "slug": "latest", + "current": true, + "aliases": [ + "current", + "stable" + ] + } + ] +} diff --git a/vendor/doctrine/event-manager/LICENSE b/vendor/doctrine/event-manager/LICENSE new file mode 100644 index 0000000..8c38cc1 --- /dev/null +++ b/vendor/doctrine/event-manager/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2015 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/doctrine/event-manager/README.md b/vendor/doctrine/event-manager/README.md new file mode 100644 index 0000000..3aee6b6 --- /dev/null +++ b/vendor/doctrine/event-manager/README.md @@ -0,0 +1,13 @@ +# Doctrine Event Manager + +[![Build Status](https://travis-ci.org/doctrine/event-manager.svg)](https://travis-ci.org/doctrine/event-manager) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/event-manager/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/event-manager/?branch=master) +[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/event-manager/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/event-manager/?branch=master) + +The Doctrine Event Manager is a library that provides a simple event system. + +## More resources: + +* [Website](https://www.doctrine-project.org/) +* [Documentation](https://www.doctrine-project.org/projects/doctrine-event-manager/en/latest/) +* [Downloads](https://github.com/doctrine/event-manager/releases) diff --git a/vendor/doctrine/event-manager/composer.json b/vendor/doctrine/event-manager/composer.json new file mode 100644 index 0000000..c0d3a84 --- /dev/null +++ b/vendor/doctrine/event-manager/composer.json @@ -0,0 +1,50 @@ +{ + "name": "doctrine/event-manager", + "type": "library", + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "keywords": [ + "events", + "event", + "event dispatcher", + "event manager", + "event system" + ], + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "license": "MIT", + "authors": [ + {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, + {"name": "Roman Borschel", "email": "roman@code-factory.org"}, + {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, + {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, + {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}, + {"name": "Marco Pivetta", "email": "ocramius@gmail.com"} + ], + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.0" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "config": { + "sort-packages": true + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "autoload-dev": { + "psr-4": { + "Doctrine\\Tests\\": "tests/Doctrine/Tests" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/vendor/doctrine/event-manager/lib/Doctrine/Common/EventArgs.php b/vendor/doctrine/event-manager/lib/Doctrine/Common/EventArgs.php new file mode 100644 index 0000000..9b9cc05 --- /dev/null +++ b/vendor/doctrine/event-manager/lib/Doctrine/Common/EventArgs.php @@ -0,0 +1,45 @@ + => + * + * @var object[][] + */ + private $_listeners = []; + + /** + * 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|null $eventArgs The event arguments to pass to the event handlers/listeners. + * If not supplied, the single empty EventArgs instance is used. + * + * @return void + */ + public function dispatchEvent($eventName, ?EventArgs $eventArgs = null) + { + if (! isset($this->_listeners[$eventName])) { + return; + } + + $eventArgs = $eventArgs ?? EventArgs::getEmptyInstance(); + + foreach ($this->_listeners[$eventName] as $listener) { + $listener->$eventName($eventArgs); + } + } + + /** + * Gets the listeners of a specific event or all listeners. + * + * @param string|null $event The name of the event. + * + * @return object[]|object[][] 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 bool TRUE if the specified event has any listeners, FALSE otherwise. + */ + public function hasListeners($event) + { + return ! empty($this->_listeners[$event]); + } + + /** + * Adds an event listener that listens on the specified events. + * + * @param string|string[] $events The event(s) to listen on. + * @param object $listener The listener object. + * + * @return void + */ + 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|string[] $events + * @param object $listener + * + * @return void + */ + public function removeEventListener($events, $listener) + { + // Picks the hash code related to that listener + $hash = spl_object_hash($listener); + + foreach ((array) $events as $event) { + unset($this->_listeners[$event][$hash]); + } + } + + /** + * Adds an EventSubscriber. The subscriber is asked for all the events it is + * interested in and added as a listener for these events. + * + * @param EventSubscriber $subscriber The subscriber. + * + * @return void + */ + public function addEventSubscriber(EventSubscriber $subscriber) + { + $this->addEventListener($subscriber->getSubscribedEvents(), $subscriber); + } + + /** + * Removes an EventSubscriber. The subscriber is asked for all the events it is + * interested in and removed as a listener for these events. + * + * @param EventSubscriber $subscriber The subscriber. + * + * @return void + */ + public function removeEventSubscriber(EventSubscriber $subscriber) + { + $this->removeEventListener($subscriber->getSubscribedEvents(), $subscriber); + } +} diff --git a/vendor/doctrine/event-manager/lib/Doctrine/Common/EventSubscriber.php b/vendor/doctrine/event-manager/lib/Doctrine/Common/EventSubscriber.php new file mode 100644 index 0000000..7d5e2ea --- /dev/null +++ b/vendor/doctrine/event-manager/lib/Doctrine/Common/EventSubscriber.php @@ -0,0 +1,21 @@ + '\1ables']); + Inflector::rules('plural', [ + 'rules' => ['/^(inflect)ors$/i' => '\1ables'], + 'uninflected' => ['dontinflectme'], + 'irregular' => ['red' => 'redlings'] + ]); + +The arguments for the ``rules`` method are: + +- ``$type`` - The type of inflection, either ``plural`` or ``singular`` +- ``$rules`` - An array of rules to be added. +- ``$reset`` - If true, will unset default inflections for all new rules that are being defined in $rules. + +Reset +===== + +Clears Inflectors inflected value caches, and resets the inflection +rules to the initial values. + +.. code-block:: php + + Inflector::reset(); + +Slugify +======= + +You can easily use the Inflector to create a slug from a string of text +by using the `tableize`_ method and replacing underscores with hyphens: + +.. code-block:: php + + public static function slugify(string $text) : string + { + return str_replace('_', '-', Inflector::tableize($text)); + } diff --git a/vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php b/vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php new file mode 100644 index 0000000..35b5c68 --- /dev/null +++ b/vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php @@ -0,0 +1,492 @@ +. + */ + +namespace Doctrine\Common\Inflector; + +/** + * 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. + * + * Pluralize & Singularize implementation are borrowed from CakePHP with some modifications. + * + * @link www.doctrine-project.org + * @since 1.0 + * @author Konsta Vesterinen + * @author Jonathan H. Wage + */ +class Inflector +{ + /** + * Plural inflector rules. + * + * @var string[][] + */ + private static $plural = array( + 'rules' => array( + '/(s)tatus$/i' => '\1\2tatuses', + '/(quiz)$/i' => '\1zes', + '/^(ox)$/i' => '\1\2en', + '/([m|l])ouse$/i' => '\1ice', + '/(matr|vert|ind)(ix|ex)$/i' => '\1ices', + '/(x|ch|ss|sh)$/i' => '\1es', + '/([^aeiouy]|qu)y$/i' => '\1ies', + '/(hive|gulf)$/i' => '\1s', + '/(?:([^f])fe|([lr])f)$/i' => '\1\2ves', + '/sis$/i' => 'ses', + '/([ti])um$/i' => '\1a', + '/(c)riterion$/i' => '\1riteria', + '/(p)erson$/i' => '\1eople', + '/(m)an$/i' => '\1en', + '/(c)hild$/i' => '\1hildren', + '/(f)oot$/i' => '\1eet', + '/(buffal|her|potat|tomat|volcan)o$/i' => '\1\2oes', + '/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us$/i' => '\1i', + '/us$/i' => 'uses', + '/(alias)$/i' => '\1es', + '/(analys|ax|cris|test|thes)is$/i' => '\1es', + '/s$/' => 's', + '/^$/' => '', + '/$/' => 's', + ), + 'uninflected' => array( + '.*[nrlm]ese', + '.*deer', + '.*fish', + '.*measles', + '.*ois', + '.*pox', + '.*sheep', + 'people', + 'cookie', + 'police', + ), + 'irregular' => array( + 'atlas' => 'atlases', + 'axe' => 'axes', + 'beef' => 'beefs', + 'brother' => 'brothers', + 'cafe' => 'cafes', + 'canvas' => 'canvases', + 'chateau' => 'chateaux', + 'niveau' => 'niveaux', + 'child' => 'children', + 'cookie' => 'cookies', + 'corpus' => 'corpuses', + 'cow' => 'cows', + 'criterion' => 'criteria', + 'curriculum' => 'curricula', + 'demo' => 'demos', + 'domino' => 'dominoes', + 'echo' => 'echoes', + 'foot' => 'feet', + 'fungus' => 'fungi', + 'ganglion' => 'ganglions', + 'gas' => 'gases', + 'genie' => 'genies', + 'genus' => 'genera', + 'goose' => 'geese', + 'graffito' => 'graffiti', + 'hippopotamus' => 'hippopotami', + 'hoof' => 'hoofs', + 'human' => 'humans', + 'iris' => 'irises', + 'larva' => 'larvae', + 'leaf' => 'leaves', + 'loaf' => 'loaves', + 'man' => 'men', + 'medium' => 'media', + 'memorandum' => 'memoranda', + 'money' => 'monies', + 'mongoose' => 'mongooses', + 'motto' => 'mottoes', + 'move' => 'moves', + 'mythos' => 'mythoi', + 'niche' => 'niches', + 'nucleus' => 'nuclei', + 'numen' => 'numina', + 'occiput' => 'occiputs', + 'octopus' => 'octopuses', + 'opus' => 'opuses', + 'ox' => 'oxen', + 'passerby' => 'passersby', + 'penis' => 'penises', + 'person' => 'people', + 'plateau' => 'plateaux', + 'runner-up' => 'runners-up', + 'sex' => 'sexes', + 'soliloquy' => 'soliloquies', + 'son-in-law' => 'sons-in-law', + 'syllabus' => 'syllabi', + 'testis' => 'testes', + 'thief' => 'thieves', + 'tooth' => 'teeth', + 'tornado' => 'tornadoes', + 'trilby' => 'trilbys', + 'turf' => 'turfs', + 'valve' => 'valves', + 'volcano' => 'volcanoes', + ) + ); + + /** + * Singular inflector rules. + * + * @var string[][] + */ + private static $singular = array( + 'rules' => array( + '/(s)tatuses$/i' => '\1\2tatus', + '/^(.*)(menu)s$/i' => '\1\2', + '/(quiz)zes$/i' => '\\1', + '/(matr)ices$/i' => '\1ix', + '/(vert|ind)ices$/i' => '\1ex', + '/^(ox)en/i' => '\1', + '/(alias)(es)*$/i' => '\1', + '/(buffal|her|potat|tomat|volcan)oes$/i' => '\1o', + '/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$/i' => '\1us', + '/([ftw]ax)es/i' => '\1', + '/(analys|ax|cris|test|thes)es$/i' => '\1is', + '/(shoe|slave)s$/i' => '\1', + '/(o)es$/i' => '\1', + '/ouses$/' => 'ouse', + '/([^a])uses$/' => '\1us', + '/([m|l])ice$/i' => '\1ouse', + '/(x|ch|ss|sh)es$/i' => '\1', + '/(m)ovies$/i' => '\1\2ovie', + '/(s)eries$/i' => '\1\2eries', + '/([^aeiouy]|qu)ies$/i' => '\1y', + '/([lr])ves$/i' => '\1f', + '/(tive)s$/i' => '\1', + '/(hive)s$/i' => '\1', + '/(drive)s$/i' => '\1', + '/(dive)s$/i' => '\1', + '/(olive)s$/i' => '\1', + '/([^fo])ves$/i' => '\1fe', + '/(^analy)ses$/i' => '\1sis', + '/(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis', + '/(c)riteria$/i' => '\1riterion', + '/([ti])a$/i' => '\1um', + '/(p)eople$/i' => '\1\2erson', + '/(m)en$/i' => '\1an', + '/(c)hildren$/i' => '\1\2hild', + '/(f)eet$/i' => '\1oot', + '/(n)ews$/i' => '\1\2ews', + '/eaus$/' => 'eau', + '/^(.*us)$/' => '\\1', + '/s$/i' => '', + ), + 'uninflected' => array( + '.*[nrlm]ese', + '.*deer', + '.*fish', + '.*measles', + '.*ois', + '.*pox', + '.*sheep', + '.*ss', + 'data', + 'police', + 'pants', + 'clothes', + ), + 'irregular' => array( + 'abuses' => 'abuse', + 'avalanches' => 'avalanche', + 'caches' => 'cache', + 'criteria' => 'criterion', + 'curves' => 'curve', + 'emphases' => 'emphasis', + 'foes' => 'foe', + 'geese' => 'goose', + 'graves' => 'grave', + 'hoaxes' => 'hoax', + 'media' => 'medium', + 'neuroses' => 'neurosis', + 'waves' => 'wave', + 'oases' => 'oasis', + 'valves' => 'valve', + ) + ); + + /** + * Words that should not be inflected. + * + * @var array + */ + private static $uninflected = array( + '.*?media', 'Amoyese', 'audio', 'bison', 'Borghese', 'bream', 'breeches', + 'britches', 'buffalo', 'cantus', 'carp', 'chassis', 'clippers', 'cod', 'coitus', 'compensation', 'Congoese', + 'contretemps', 'coreopsis', 'corps', 'data', 'debris', 'deer', 'diabetes', 'djinn', 'education', 'eland', + 'elk', 'emoji', 'equipment', 'evidence', 'Faroese', 'feedback', 'fish', 'flounder', 'Foochowese', + 'Furniture', 'furniture', 'gallows', 'Genevese', 'Genoese', 'Gilbertese', 'gold', + 'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings', 'jackanapes', 'jedi', + 'Kiplingese', 'knowledge', 'Kongoese', 'love', 'Lucchese', 'Luggage', 'mackerel', 'Maltese', 'metadata', + 'mews', 'moose', 'mumps', 'Nankingese', 'news', 'nexus', 'Niasese', 'nutrition', 'offspring', + 'Pekingese', 'Piedmontese', 'pincers', 'Pistoiese', 'plankton', 'pliers', 'pokemon', 'police', 'Portuguese', + 'proceedings', 'rabies', 'rain', 'rhinoceros', 'rice', 'salmon', 'Sarawakese', 'scissors', 'sea[- ]bass', + 'series', 'Shavese', 'shears', 'sheep', 'siemens', 'species', 'staff', 'swine', 'traffic', + 'trousers', 'trout', 'tuna', 'us', 'Vermontese', 'Wenchowese', 'wheat', 'whiting', 'wildebeest', 'Yengeese' + ); + + /** + * Method cache array. + * + * @var array + */ + private static $cache = array(); + + /** + * The initial state of Inflector so reset() works. + * + * @var array + */ + private static $initialState = array(); + + /** + * Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'. + */ + public static function tableize(string $word) : string + { + return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $word)); + } + + /** + * Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'. + */ + public static function classify(string $word) : string + { + return str_replace([' ', '_', '-'], '', ucwords($word, ' _-')); + } + + /** + * Camelizes a word. This uses the classify() method and turns the first character to lowercase. + */ + public static function camelize(string $word) : string + { + return lcfirst(self::classify($word)); + } + + /** + * Uppercases words with configurable delimeters between words. + * + * Takes a string and capitalizes all of the words, like PHP's built-in + * ucwords function. This extends that behavior, however, by allowing the + * word delimeters to be configured, rather than only separating on + * whitespace. + * + * Here is an example: + * + * + * + * + * @param string $string The string to operate on. + * @param string $delimiters A list of word separators. + * + * @return string The string with all delimeter-separated words capitalized. + */ + public static function ucwords(string $string, string $delimiters = " \n\t\r\0\x0B-") : string + { + return ucwords($string, $delimiters); + } + + /** + * Clears Inflectors inflected value caches, and resets the inflection + * rules to the initial values. + */ + public static function reset() : void + { + if (empty(self::$initialState)) { + self::$initialState = get_class_vars('Inflector'); + + return; + } + + foreach (self::$initialState as $key => $val) { + if ($key !== 'initialState') { + self::${$key} = $val; + } + } + } + + /** + * Adds custom inflection $rules, of either 'plural' or 'singular' $type. + * + * ### Usage: + * + * {{{ + * Inflector::rules('plural', array('/^(inflect)or$/i' => '\1ables')); + * Inflector::rules('plural', array( + * 'rules' => array('/^(inflect)ors$/i' => '\1ables'), + * 'uninflected' => array('dontinflectme'), + * 'irregular' => array('red' => 'redlings') + * )); + * }}} + * + * @param string $type The type of inflection, either 'plural' or 'singular' + * @param array|iterable $rules An array of rules to be added. + * @param boolean $reset If true, will unset default inflections for all + * new rules that are being defined in $rules. + * + * @return void + */ + public static function rules(string $type, iterable $rules, bool $reset = false) : void + { + foreach ($rules as $rule => $pattern) { + if ( ! is_array($pattern)) { + continue; + } + + if ($reset) { + self::${$type}[$rule] = $pattern; + } else { + self::${$type}[$rule] = ($rule === 'uninflected') + ? array_merge($pattern, self::${$type}[$rule]) + : $pattern + self::${$type}[$rule]; + } + + unset($rules[$rule], self::${$type}['cache' . ucfirst($rule)]); + + if (isset(self::${$type}['merged'][$rule])) { + unset(self::${$type}['merged'][$rule]); + } + + if ($type === 'plural') { + self::$cache['pluralize'] = self::$cache['tableize'] = array(); + } elseif ($type === 'singular') { + self::$cache['singularize'] = array(); + } + } + + self::${$type}['rules'] = $rules + self::${$type}['rules']; + } + + /** + * Returns a word in plural form. + * + * @param string $word The word in singular form. + * + * @return string The word in plural form. + */ + public static function pluralize(string $word) : string + { + if (isset(self::$cache['pluralize'][$word])) { + return self::$cache['pluralize'][$word]; + } + + if (!isset(self::$plural['merged']['irregular'])) { + self::$plural['merged']['irregular'] = self::$plural['irregular']; + } + + if (!isset(self::$plural['merged']['uninflected'])) { + self::$plural['merged']['uninflected'] = array_merge(self::$plural['uninflected'], self::$uninflected); + } + + if (!isset(self::$plural['cacheUninflected']) || !isset(self::$plural['cacheIrregular'])) { + self::$plural['cacheUninflected'] = '(?:' . implode('|', self::$plural['merged']['uninflected']) . ')'; + self::$plural['cacheIrregular'] = '(?:' . implode('|', array_keys(self::$plural['merged']['irregular'])) . ')'; + } + + if (preg_match('/(.*)\\b(' . self::$plural['cacheIrregular'] . ')$/i', $word, $regs)) { + self::$cache['pluralize'][$word] = $regs[1] . $word[0] . substr(self::$plural['merged']['irregular'][strtolower($regs[2])], 1); + + return self::$cache['pluralize'][$word]; + } + + if (preg_match('/^(' . self::$plural['cacheUninflected'] . ')$/i', $word, $regs)) { + self::$cache['pluralize'][$word] = $word; + + return $word; + } + + foreach (self::$plural['rules'] as $rule => $replacement) { + if (preg_match($rule, $word)) { + self::$cache['pluralize'][$word] = preg_replace($rule, $replacement, $word); + + return self::$cache['pluralize'][$word]; + } + } + } + + /** + * Returns a word in singular form. + * + * @param string $word The word in plural form. + * + * @return string The word in singular form. + */ + public static function singularize(string $word) : string + { + if (isset(self::$cache['singularize'][$word])) { + return self::$cache['singularize'][$word]; + } + + if (!isset(self::$singular['merged']['uninflected'])) { + self::$singular['merged']['uninflected'] = array_merge( + self::$singular['uninflected'], + self::$uninflected + ); + } + + if (!isset(self::$singular['merged']['irregular'])) { + self::$singular['merged']['irregular'] = array_merge( + self::$singular['irregular'], + array_flip(self::$plural['irregular']) + ); + } + + if (!isset(self::$singular['cacheUninflected']) || !isset(self::$singular['cacheIrregular'])) { + self::$singular['cacheUninflected'] = '(?:' . implode('|', self::$singular['merged']['uninflected']) . ')'; + self::$singular['cacheIrregular'] = '(?:' . implode('|', array_keys(self::$singular['merged']['irregular'])) . ')'; + } + + if (preg_match('/(.*)\\b(' . self::$singular['cacheIrregular'] . ')$/i', $word, $regs)) { + self::$cache['singularize'][$word] = $regs[1] . $word[0] . substr(self::$singular['merged']['irregular'][strtolower($regs[2])], 1); + + return self::$cache['singularize'][$word]; + } + + if (preg_match('/^(' . self::$singular['cacheUninflected'] . ')$/i', $word, $regs)) { + self::$cache['singularize'][$word] = $word; + + return $word; + } + + foreach (self::$singular['rules'] as $rule => $replacement) { + if (preg_match($rule, $word)) { + self::$cache['singularize'][$word] = preg_replace($rule, $replacement, $word); + + return self::$cache['singularize'][$word]; + } + } + + self::$cache['singularize'][$word] = $word; + + return $word; + } +} diff --git a/vendor/doctrine/instantiator/.doctrine-project.json b/vendor/doctrine/instantiator/.doctrine-project.json new file mode 100644 index 0000000..4fe86ee --- /dev/null +++ b/vendor/doctrine/instantiator/.doctrine-project.json @@ -0,0 +1,26 @@ +{ + "active": true, + "name": "Instantiator", + "slug": "instantiator", + "docsSlug": "doctrine-instantiator", + "codePath": "/src", + "versions": [ + { + "name": "1.1", + "branchName": "master", + "slug": "latest", + "aliases": [ + "current", + "stable" + ], + "maintained": true, + "current": true + }, + { + "name": "1.0", + "branchName": "1.0.x", + "slug": "1.0" + } + ] +} + diff --git a/vendor/doctrine/instantiator/.github/FUNDING.yml b/vendor/doctrine/instantiator/.github/FUNDING.yml new file mode 100644 index 0000000..9a35064 --- /dev/null +++ b/vendor/doctrine/instantiator/.github/FUNDING.yml @@ -0,0 +1,3 @@ +patreon: phpdoctrine +tidelift: packagist/doctrine%2Finstantiator +custom: https://www.doctrine-project.org/sponsorship.html diff --git a/vendor/doctrine/instantiator/CONTRIBUTING.md b/vendor/doctrine/instantiator/CONTRIBUTING.md new file mode 100644 index 0000000..c1a2c42 --- /dev/null +++ b/vendor/doctrine/instantiator/CONTRIBUTING.md @@ -0,0 +1,35 @@ +# Contributing + + * Follow the [Doctrine Coding Standard](https://github.com/doctrine/coding-standard) + * The project will follow strict [object calisthenics](http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php) + * Any contribution must provide tests for additional introduced conditions + * Any un-confirmed issue needs a failing test case before being accepted + * Pull requests must be sent from a new hotfix/feature branch, not from `master`. + +## Installation + +To install the project and run the tests, you need to clone it first: + +```sh +$ git clone git://github.com/doctrine/instantiator.git +``` + +You will then need to run a composer installation: + +```sh +$ cd Instantiator +$ curl -s https://getcomposer.org/installer | php +$ php composer.phar update +``` + +## Testing + +The PHPUnit version to be used is the one installed as a dev- dependency via composer: + +```sh +$ ./vendor/bin/phpunit +``` + +Accepted coverage for new contributions is 80%. Any contribution not satisfying this requirement +won't be merged. + diff --git a/vendor/doctrine/instantiator/LICENSE b/vendor/doctrine/instantiator/LICENSE new file mode 100644 index 0000000..4d983d1 --- /dev/null +++ b/vendor/doctrine/instantiator/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/doctrine/instantiator/README.md b/vendor/doctrine/instantiator/README.md new file mode 100644 index 0000000..eff5a0c --- /dev/null +++ b/vendor/doctrine/instantiator/README.md @@ -0,0 +1,39 @@ +# Instantiator + +This library provides a way of avoiding usage of constructors when instantiating PHP classes. + +[![Build Status](https://travis-ci.org/doctrine/instantiator.svg?branch=master)](https://travis-ci.org/doctrine/instantiator) +[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/instantiator/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/instantiator/?branch=master) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/instantiator/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/instantiator/?branch=master) +[![Dependency Status](https://www.versioneye.com/package/php--doctrine--instantiator/badge.svg)](https://www.versioneye.com/package/php--doctrine--instantiator) + +[![Latest Stable Version](https://poser.pugx.org/doctrine/instantiator/v/stable.png)](https://packagist.org/packages/doctrine/instantiator) +[![Latest Unstable Version](https://poser.pugx.org/doctrine/instantiator/v/unstable.png)](https://packagist.org/packages/doctrine/instantiator) + +## Installation + +The suggested installation method is via [composer](https://getcomposer.org/): + +```sh +php composer.phar require "doctrine/instantiator:~1.0.3" +``` + +## Usage + +The instantiator is able to create new instances of any class without using the constructor or any API of the class +itself: + +```php +$instantiator = new \Doctrine\Instantiator\Instantiator(); + +$instance = $instantiator->instantiate(\My\ClassName\Here::class); +``` + +## Contributing + +Please read the [CONTRIBUTING.md](CONTRIBUTING.md) contents if you wish to help out! + +## Credits + +This library was migrated from [ocramius/instantiator](https://github.com/Ocramius/Instantiator), which +has been donated to the doctrine organization, and which is now deprecated in favour of this package. diff --git a/vendor/doctrine/instantiator/composer.json b/vendor/doctrine/instantiator/composer.json new file mode 100644 index 0000000..9002a91 --- /dev/null +++ b/vendor/doctrine/instantiator/composer.json @@ -0,0 +1,47 @@ +{ + "name": "doctrine/instantiator", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "type": "library", + "license": "MIT", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "instantiate", + "constructor" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "require": { + "php": "^7.1" + }, + "require-dev": { + "ext-phar": "*", + "ext-pdo": "*", + "doctrine/coding-standard": "^6.0", + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "autoload-dev": { + "psr-0": { + "DoctrineTest\\InstantiatorPerformance\\": "tests", + "DoctrineTest\\InstantiatorTest\\": "tests", + "DoctrineTest\\InstantiatorTestAsset\\": "tests" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + } +} diff --git a/vendor/doctrine/instantiator/docs/en/index.rst b/vendor/doctrine/instantiator/docs/en/index.rst new file mode 100644 index 0000000..0c85da0 --- /dev/null +++ b/vendor/doctrine/instantiator/docs/en/index.rst @@ -0,0 +1,68 @@ +Introduction +============ + +This library provides a way of avoiding usage of constructors when instantiating PHP classes. + +Installation +============ + +The suggested installation method is via `composer`_: + +.. code-block:: console + + $ composer require doctrine/instantiator + +Usage +===== + +The instantiator is able to create new instances of any class without +using the constructor or any API of the class itself: + +.. code-block:: php + + instantiate(User::class); + +Contributing +============ + +- Follow the `Doctrine Coding Standard`_ +- The project will follow strict `object calisthenics`_ +- Any contribution must provide tests for additional introduced + conditions +- Any un-confirmed issue needs a failing test case before being + accepted +- Pull requests must be sent from a new hotfix/feature branch, not from + ``master``. + +Testing +======= + +The PHPUnit version to be used is the one installed as a dev- dependency +via composer: + +.. code-block:: console + + $ ./vendor/bin/phpunit + +Accepted coverage for new contributions is 80%. Any contribution not +satisfying this requirement won’t be merged. + +Credits +======= + +This library was migrated from `ocramius/instantiator`_, which has been +donated to the doctrine organization, and which is now deprecated in +favour of this package. + +.. _composer: https://getcomposer.org/ +.. _CONTRIBUTING.md: CONTRIBUTING.md +.. _ocramius/instantiator: https://github.com/Ocramius/Instantiator +.. _Doctrine Coding Standard: https://github.com/doctrine/coding-standard +.. _object calisthenics: http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php diff --git a/vendor/doctrine/instantiator/docs/en/sidebar.rst b/vendor/doctrine/instantiator/docs/en/sidebar.rst new file mode 100644 index 0000000..0c36479 --- /dev/null +++ b/vendor/doctrine/instantiator/docs/en/sidebar.rst @@ -0,0 +1,4 @@ +.. toctree:: + :depth: 3 + + index diff --git a/vendor/doctrine/instantiator/phpbench.json b/vendor/doctrine/instantiator/phpbench.json new file mode 100644 index 0000000..fce5dd6 --- /dev/null +++ b/vendor/doctrine/instantiator/phpbench.json @@ -0,0 +1,4 @@ +{ + "bootstrap": "vendor/autoload.php", + "path": "tests/DoctrineTest/InstantiatorPerformance" +} diff --git a/vendor/doctrine/instantiator/phpcs.xml.dist b/vendor/doctrine/instantiator/phpcs.xml.dist new file mode 100644 index 0000000..1fcac4a --- /dev/null +++ b/vendor/doctrine/instantiator/phpcs.xml.dist @@ -0,0 +1,35 @@ + + + + + + + + + + + + src + tests + + + + + + + + + + tests/DoctrineTest/InstantiatorTestAsset/AbstractClassAsset.php + + + + src/Doctrine/Instantiator/Exception/UnexpectedValueException.php + src/Doctrine/Instantiator/Exception/InvalidArgumentException.php + + + + src/Doctrine/Instantiator/Exception/ExceptionInterface.php + src/Doctrine/Instantiator/InstantiatorInterface.php + + diff --git a/vendor/doctrine/instantiator/phpstan.neon.dist b/vendor/doctrine/instantiator/phpstan.neon.dist new file mode 100644 index 0000000..ecc38ef --- /dev/null +++ b/vendor/doctrine/instantiator/phpstan.neon.dist @@ -0,0 +1,19 @@ +includes: + - vendor/phpstan/phpstan-phpunit/extension.neon + - vendor/phpstan/phpstan-phpunit/rules.neon + +parameters: + level: max + paths: + - src + - tests + + ignoreErrors: + - + message: '#::__construct\(\) does not call parent constructor from#' + path: '*/tests/DoctrineTest/InstantiatorTestAsset/*.php' + + # dynamic properties confuse static analysis + - + message: '#Access to an undefined property object::\$foo\.#' + path: '*/tests/DoctrineTest/InstantiatorTest/InstantiatorTest.php' diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php new file mode 100644 index 0000000..e6a5195 --- /dev/null +++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php @@ -0,0 +1,12 @@ += 50400 && trait_exists($className)) { + return new self(sprintf('The provided type "%s" is a trait, and can not be instantiated', $className)); + } + + return new self(sprintf('The provided class "%s" does not exist', $className)); + } + + public static function fromAbstractClass(ReflectionClass $reflectionClass) : self + { + return new self(sprintf( + 'The provided class "%s" is abstract, and can not be instantiated', + $reflectionClass->getName() + )); + } +} diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php new file mode 100644 index 0000000..d946731 --- /dev/null +++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php @@ -0,0 +1,48 @@ +getName() + ), + 0, + $exception + ); + } + + public static function fromUncleanUnSerialization( + ReflectionClass $reflectionClass, + string $errorString, + int $errorCode, + string $errorFile, + int $errorLine + ) : self { + return new self( + sprintf( + 'Could not produce an instance of "%s" via un-serialization, since an error was triggered ' + . 'in file "%s" at line "%d"', + $reflectionClass->getName(), + $errorFile, + $errorLine + ), + 0, + new Exception($errorString, $errorCode) + ); + } +} diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php new file mode 100644 index 0000000..9c67862 --- /dev/null +++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php @@ -0,0 +1,203 @@ +buildAndCacheFromFactory($className); + } + + /** + * Builds the requested object and caches it in static properties for performance + * + * @return object + */ + private function buildAndCacheFromFactory(string $className) + { + $factory = self::$cachedInstantiators[$className] = $this->buildFactory($className); + $instance = $factory(); + + if ($this->isSafeToClone(new ReflectionClass($instance))) { + self::$cachedCloneables[$className] = clone $instance; + } + + return $instance; + } + + /** + * Builds a callable capable of instantiating the given $className without + * invoking its constructor. + * + * @throws InvalidArgumentException + * @throws UnexpectedValueException + * @throws ReflectionException + */ + private function buildFactory(string $className) : callable + { + $reflectionClass = $this->getReflectionClass($className); + + if ($this->isInstantiableViaReflection($reflectionClass)) { + return [$reflectionClass, 'newInstanceWithoutConstructor']; + } + + $serializedString = sprintf( + '%s:%d:"%s":0:{}', + is_subclass_of($className, Serializable::class) ? self::SERIALIZATION_FORMAT_USE_UNSERIALIZER : self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER, + strlen($className), + $className + ); + + $this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString); + + return static function () use ($serializedString) { + return unserialize($serializedString); + }; + } + + /** + * @throws InvalidArgumentException + * @throws ReflectionException + */ + private function getReflectionClass(string $className) : ReflectionClass + { + if (! class_exists($className)) { + throw InvalidArgumentException::fromNonExistingClass($className); + } + + $reflection = new ReflectionClass($className); + + if ($reflection->isAbstract()) { + throw InvalidArgumentException::fromAbstractClass($reflection); + } + + return $reflection; + } + + /** + * @throws UnexpectedValueException + */ + private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, string $serializedString) : void + { + set_error_handler(static function (int $code, string $message, string $file, int $line) use ($reflectionClass, &$error) : bool { + $error = UnexpectedValueException::fromUncleanUnSerialization( + $reflectionClass, + $message, + $code, + $file, + $line + ); + + return true; + }); + + try { + $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString); + } finally { + restore_error_handler(); + } + + if ($error) { + throw $error; + } + } + + /** + * @throws UnexpectedValueException + */ + private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, string $serializedString) : void + { + try { + unserialize($serializedString); + } catch (Exception $exception) { + throw UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception); + } + } + + private function isInstantiableViaReflection(ReflectionClass $reflectionClass) : bool + { + return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal()); + } + + /** + * Verifies whether the given class is to be considered internal + */ + private function hasInternalAncestors(ReflectionClass $reflectionClass) : bool + { + do { + if ($reflectionClass->isInternal()) { + return true; + } + + $reflectionClass = $reflectionClass->getParentClass(); + } while ($reflectionClass); + + return false; + } + + /** + * Checks if a class is cloneable + * + * Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects. + */ + private function isSafeToClone(ReflectionClass $reflection) : bool + { + return $reflection->isCloneable() + && ! $reflection->hasMethod('__clone') + && ! $reflection->isSubclassOf(ArrayIterator::class); + } +} diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php new file mode 100644 index 0000000..95299f4 --- /dev/null +++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php @@ -0,0 +1,20 @@ +input = $input; + $this->tokens = []; + + $this->reset(); + $this->scan($input); + } + + /** + * Resets the lexer. + * + * @return void + */ + public function reset() + { + $this->lookahead = null; + $this->token = null; + $this->peek = 0; + $this->position = 0; + } + + /** + * Resets the peek pointer to 0. + * + * @return void + */ + public function resetPeek() + { + $this->peek = 0; + } + + /** + * Resets the lexer position on the input to the given position. + * + * @param int $position Position to place the lexical scanner. + * + * @return void + */ + public function resetPosition($position = 0) + { + $this->position = $position; + } + + /** + * Retrieve the original lexer's input until a given position. + * + * @param int $position + * + * @return string + */ + public function getInputUntilPosition($position) + { + return substr($this->input, 0, $position); + } + + /** + * Checks whether a given token matches the current lookahead. + * + * @param int|string $token + * + * @return bool + */ + public function isNextToken($token) + { + return $this->lookahead !== null && $this->lookahead['type'] === $token; + } + + /** + * Checks whether any of the given tokens matches the current lookahead. + * + * @param array $tokens + * + * @return bool + */ + public function isNextTokenAny(array $tokens) + { + return $this->lookahead !== null && in_array($this->lookahead['type'], $tokens, true); + } + + /** + * Moves to the next token in the input string. + * + * @return bool + */ + 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 string $type The token type to skip until. + * + * @return void + */ + 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 int|string $token + * + * @return bool + */ + 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++]; + } + + 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. + * + * @return void + */ + protected function scan($input) + { + if (! isset($this->regex)) { + $this->regex = sprintf( + '/(%s)|%s/%s', + implode(')|(', $this->getCatchablePatterns()), + implode('|', $this->getNonCatchablePatterns()), + $this->getModifiers() + ); + } + + $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; + $matches = preg_split($this->regex, $input, -1, $flags); + + if ($matches === false) { + // Work around https://bugs.php.net/78122 + $matches = [[$input, 0]]; + } + + foreach ($matches as $match) { + // Must remain before 'value' assignment since it can change content + $type = $this->getType($match[0]); + + $this->tokens[] = [ + 'value' => $match[0], + 'type' => $type, + 'position' => $match[1], + ]; + } + } + + /** + * Gets the literal for a given token. + * + * @param int|string $token + * + * @return int|string + */ + public function getLiteral($token) + { + $className = static::class; + $reflClass = new ReflectionClass($className); + $constants = $reflClass->getConstants(); + + foreach ($constants as $name => $value) { + if ($value === $token) { + return $className . '::' . $name; + } + } + + return $token; + } + + /** + * Regex modifiers + * + * @return string + */ + protected function getModifiers() + { + return 'iu'; + } + + /** + * 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 int|string|null + */ + abstract protected function getType(&$value); +} diff --git a/vendor/doctrine/orm/.scrutinizer.yml b/vendor/doctrine/orm/.scrutinizer.yml new file mode 100644 index 0000000..d05c72c --- /dev/null +++ b/vendor/doctrine/orm/.scrutinizer.yml @@ -0,0 +1,34 @@ +build: + nodes: + analysis: + environment: + php: + version: 7.1 + cache: + disabled: false + directories: + - ~/.composer/cache + + project_setup: + override: true + tests: + override: + - php-scrutinizer-run + +before_commands: + - "composer install --no-dev --prefer-source" + +tools: + external_code_coverage: + timeout: 3600 + +filter: + excluded_paths: + - docs + - tools + +build_failure_conditions: + - 'elements.rating(<= C).new.exists' # No new classes/methods with a rating of C or worse allowed + - 'issues.severity(>= MAJOR).new.exists' # New issues of major or higher severity + - 'project.metric_change("scrutinizer.test_coverage", < 0)' # Code Coverage decreased from previous inspection + - 'patches.label("Unused Use Statements").new.exists' # No new unused imports patches allowed diff --git a/vendor/doctrine/orm/LICENSE b/vendor/doctrine/orm/LICENSE new file mode 100644 index 0000000..8c38cc1 --- /dev/null +++ b/vendor/doctrine/orm/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2015 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/doctrine/orm/README.md b/vendor/doctrine/orm/README.md new file mode 100644 index 0000000..7f935fc --- /dev/null +++ b/vendor/doctrine/orm/README.md @@ -0,0 +1,26 @@ +| [Master][Master] | [2.5][2.5] | +|:----------------:|:----------:| +| [![Build status][Master image]][Master] | [![Build status][2.5 image]][2.5] | +| [![Coverage Status][Master coverage image]][Master coverage] | [![Coverage Status][2.5 coverage image]][2.5 coverage] | + +Doctrine 2 is an object-relational mapper (ORM) for PHP 7.1+ that provides transparent persistence +for PHP objects. It sits on top of a powerful database abstraction layer (DBAL). One of its key features +is the option to write database queries in a proprietary object oriented SQL dialect called Doctrine Query Language (DQL), +inspired by Hibernate's HQL. This provides developers with a powerful alternative to SQL that maintains flexibility +without requiring unnecessary code duplication. + + +## More resources: + +* [Website](http://www.doctrine-project.org) +* [Documentation](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/index.html) + + + [Master image]: https://img.shields.io/travis/doctrine/orm/master.svg?style=flat-square + [Master]: https://travis-ci.org/doctrine/orm + [Master coverage image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/orm/master.svg?style=flat-square + [Master coverage]: https://scrutinizer-ci.com/g/doctrine/orm/?branch=master + [2.5 image]: https://img.shields.io/travis/doctrine/orm/2.5.svg?style=flat-square + [2.5]: https://github.com/doctrine/orm/tree/2.5 + [2.5 coverage image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/orm/2.5.svg?style=flat-square + [2.5 coverage]: https://scrutinizer-ci.com/g/doctrine/orm/?branch=2.5 diff --git a/vendor/doctrine/orm/SECURITY.md b/vendor/doctrine/orm/SECURITY.md new file mode 100644 index 0000000..0789963 --- /dev/null +++ b/vendor/doctrine/orm/SECURITY.md @@ -0,0 +1,18 @@ +Security +======== + +The Doctrine library is operating very close to your database and as such needs +to handle and make assumptions about SQL injection vulnerabilities. + +It is vital that you understand how Doctrine approaches security, because +we cannot protect you from SQL injection. + +Please read the documentation chapter on Security in Doctrine DBAL and ORM to +understand the assumptions we make. + +- [DBAL Security Page](https://github.com/doctrine/dbal/blob/master/docs/en/reference/security.rst) +- [ORM Security Page](https://github.com/doctrine/orm/blob/master/docs/en/reference/security.rst) + +If you find a Security bug in Doctrine, please report it on Jira and change the +Security Level to "Security Issues". It will be visible to Doctrine Core +developers and you only. diff --git a/vendor/doctrine/orm/UPGRADE.md b/vendor/doctrine/orm/UPGRADE.md new file mode 100644 index 0000000..c6c6eaa --- /dev/null +++ b/vendor/doctrine/orm/UPGRADE.md @@ -0,0 +1,865 @@ +# Upgrade to 2.7 + +## Added `Doctrine\ORM\AbstractQuery#enableResultCache()` and `Doctrine\ORM\AbstractQuery#disableResultCache()` methods + +Method `Doctrine\ORM\AbstractQuery#useResultCache()` which could be used for both enabling and disabling the cache +(depending on passed flag) was split into two. + +## Minor BC BREAK: paginator output walkers aren't be called anymore on sub-queries for queries without max results + +To optimize DB interaction, `Doctrine\ORM\Tools\Pagination\Paginator` no longer fetches identifiers to be able to +perform the pagination with join collections when max results isn't set in the query. + +## Deprecated number unaware `Doctrine\ORM\Mapping\UnderscoreNamingStrategy` + +In the last patch of the `v2.6.x` series, we fixed a bug that was not converting names properly when they had numbers +(e.g.: `base64Encoded` was wrongly converted to `base64encoded` instead of `base64_encoded`). + +In order to not break BC we've introduced a way to enable the fixed behavior using a boolean constructor argument. This +argument will be removed in 3.0 and the default behavior will be the fixed one. + +## Deprecated: `Doctrine\ORM\AbstractQuery#useResultCache()` + +Method `Doctrine\ORM\AbstractQuery#useResultCache()` is deprecated because it is split into `enableResultCache()` +and `disableResultCache()`. It will be removed in 3.0. + +## Deprecated code generators and related console commands + +These console commands have been deprecated: + + * `orm:convert-mapping` + * `orm:generate:entities` + * `orm:generate-repositories` + +These classes have been deprecated: + + * `Doctrine\ORM\Tools\EntityGenerator` + * `Doctrine\ORM\Tools\EntityRepositoryGenerator` + +Whole Doctrine\ORM\Tools\Export namespace with all its members have been deprecated as well. + +## Deprecated `Doctrine\ORM\Proxy\Proxy` marker interface + +Proxy objects in Doctrine ORM 3.0 will no longer implement `Doctrine\ORM\Proxy\Proxy` nor +`Doctrine\Common\Persistence\Proxy`: instead, they implement +`ProxyManager\Proxy\GhostObjectInterface`. + +These related classes have been deprecated: + + * `Doctrine\ORM\Proxy\ProxyFactory` + * `Doctrine\ORM\Proxy\Autoloader` - we suggest using the composer autoloader instead + +These methods have been deprecated: + + * `Doctrine\ORM\Configuration#getAutoGenerateProxyClasses()` + * `Doctrine\ORM\Configuration#getProxyDir()` + * `Doctrine\ORM\Configuration#getProxyNamespace()` + +## Deprecated `Doctrine\ORM\Version` + +The `Doctrine\ORM\Version` class is now deprecated and will be removed in Doctrine ORM 3.0: +please refrain from checking the ORM version at runtime or use +[ocramius/package-versions](https://github.com/Ocramius/PackageVersions/). + +## Deprecated `EntityManager#merge()` and `EntityManager#detach()` methods + +Merge and detach semantics were a poor fit for the PHP "share-nothing" architecture. +In addition to that, merging/detaching caused multiple issues with data integrity +in the managed entity graph, which was constantly spawning more edge-case bugs/scenarios. + +The following API methods were therefore deprecated: + +* `EntityManager#merge()` +* `EntityManager#detach()` +* `UnitOfWork#merge()` +* `UnitOfWork#detach()` + +Users are encouraged to migrate `EntityManager#detach()` calls to `EntityManager#clear()`. + +In order to maintain performance on batch processing jobs, it is endorsed to enable +the second level cache (http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/second-level-cache.html) +on entities that are frequently reused across multiple `EntityManager#clear()` calls. + +An alternative to `EntityManager#merge()` will not be provided by ORM 3.0, since the merging +semantics should be part of the business domain rather than the persistence domain of an +application. If your application relies heavily on CRUD-alike interactions and/or `PATCH` +restful operations, you should look at alternatives such as [JMSSerializer](https://github.com/schmittjoh/serializer). + +## Extending `EntityManager` is deprecated + +Final keyword will be added to the `EntityManager::class` in Doctrine ORM 3.0 in order to ensure that EntityManager + is not used as valid extension point. Valid extension point should be EntityManagerInterface. + +## Deprecated `EntityManager#clear($entityName)` + +If your code relies on clearing a single entity type via `EntityManager#clear($entityName)`, +the signature has been changed to `EntityManager#clear()`. + +The main reason is that partial clears caused multiple issues with data integrity +in the managed entity graph, which was constantly spawning more edge-case bugs/scenarios. + +## Deprecated `EntityManager#flush($entity)` and `EntityManager#flush($entities)` + +If your code relies on single entity flushing optimisations via +`EntityManager#flush($entity)`, the signature has been changed to +`EntityManager#flush()`. + +Said API was affected by multiple data integrity bugs due to the fact +that change tracking was being restricted upon a subset of the managed +entities. The ORM cannot support committing subsets of the managed +entities while also guaranteeing data integrity, therefore this +utility was removed. + +The `flush()` semantics will remain the same, but the change tracking will be performed +on all entities managed by the unit of work, and not just on the provided +`$entity` or `$entities`, as the parameter is now completely ignored. + +The same applies to `UnitOfWork#commit($entity)`, which will simply be +`UnitOfWork#commit()`. + +If you would still like to perform batching operations over small `UnitOfWork` +instances, it is suggested to follow these paths instead: + + * eagerly use `EntityManager#clear()` in conjunction with a specific second level + cache configuration (see http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/second-level-cache.html) + * use an explicit change tracking policy (see http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/change-tracking-policies.html) + +## Deprecated `YAML` mapping drivers. + +If your code relies on `YamlDriver` or `SimpleYamlDriver`, you **MUST** change to +annotation or XML drivers instead. + +## Deprecated: `Doctrine\ORM\EntityManagerInterface#copy()` + +Method `Doctrine\ORM\EntityManagerInterface#copy()` never got its implementation and is deprecated. +It will be removed in 3.0. + +# Upgrade to 2.6 + +## Added `Doctrine\ORM\EntityRepository::count()` method + +`Doctrine\ORM\EntityRepository::count()` has been added. This new method has different +signature than `Countable::count()` (required parameter) and therefore are not compatible. +If your repository implemented the `Countable` interface, you will have to use +`$repository->count([])` instead and not implement `Countable` interface anymore. + +## Minor BC BREAK: `Doctrine\ORM\Tools\Console\ConsoleRunner` is now final + +Since it's just an utilitarian class and should not be inherited. + +## Minor BC BREAK: removed `Doctrine\ORM\Query\QueryException::associationPathInverseSideNotSupported()` + +Method `Doctrine\ORM\Query\QueryException::associationPathInverseSideNotSupported()` +now has a required parameter `$pathExpr`. + +## Minor BC BREAK: removed `Doctrine\ORM\Query\Parser#isInternalFunction()` + +Method `Doctrine\ORM\Query\Parser#isInternalFunction()` was removed because +the distinction between internal function and user defined DQL was removed. +[#6500](https://github.com/doctrine/orm/pull/6500) + +## Minor BC BREAK: removed `Doctrine\ORM\ORMException#overwriteInternalDQLFunctionNotAllowed()` + +Method `Doctrine\ORM\Query\Parser#overwriteInternalDQLFunctionNotAllowed()` was +removed because of the choice to allow users to overwrite internal functions, ie +`AVG`, `SUM`, `COUNT`, `MIN` and `MAX`. [#6500](https://github.com/doctrine/orm/pull/6500) + +## PHP 7.1 is now required + +Doctrine 2.6 now requires PHP 7.1 or newer. + +As a consequence, automatic cache setup in Doctrine\ORM\Tools\Setup::create*Configuration() was changed: +- APCu extension (ext-apcu) will now be used instead of abandoned APC (ext-apc). +- Memcached extension (ext-memcached) will be used instead of obsolete Memcache (ext-memcache). +- XCache support was dropped as it doesn't work with PHP 7. + +# Upgrade to 2.5 + +## Minor BC BREAK: removed `Doctrine\ORM\Query\SqlWalker#walkCaseExpression()` + +Method `Doctrine\ORM\Query\SqlWalker#walkCaseExpression()` was unused and part +of the internal API of the ORM, so it was removed. [#5600](https://github.com/doctrine/orm/pull/5600). + +## Minor BC BREAK: removed $className parameter on `AbstractEntityInheritancePersister#getSelectJoinColumnSQL()` + +As `$className` parameter was not used in the method, it was safely removed. + +## Minor BC BREAK: query cache key time is now a float + +As of 2.5.5, the `QueryCacheEntry#time` property will contain a float value +instead of an integer in order to have more precision and also to be consistent +with the `TimestampCacheEntry#time`. + +## Minor BC BREAK: discriminator map must now include all non-transient classes + +It is now required that you declare the root of an inheritance in the +discriminator map. + +When declaring an inheritance map, it was previously possible to skip the root +of the inheritance in the discriminator map. This was actually a validation +mistake by Doctrine2 and led to problems when trying to persist instances of +that class. + +If you don't plan to persist instances some classes in your inheritance, then +either: + + - make those classes `abstract` + - map those classes as `MappedSuperclass` + +## Minor BC BREAK: ``EntityManagerInterface`` instead of ``EntityManager`` in type-hints + +As of 2.5, classes requiring the ``EntityManager`` in any method signature will now require +an ``EntityManagerInterface`` instead. +If you are extending any of the following classes, then you need to check following +signatures: + +- ``Doctrine\ORM\Tools\DebugUnitOfWorkListener#dumpIdentityMap(EntityManagerInterface $em)`` +- ``Doctrine\ORM\Mapping\ClassMetadataFactory#setEntityManager(EntityManagerInterface $em)`` + +## Minor BC BREAK: Custom Hydrators API change + +As of 2.5, `AbstractHydrator` does not enforce the usage of cache as part of +API, and now provides you a clean API for column information through the method +`hydrateColumnInfo($column)`. +Cache variable being passed around by reference is no longer needed since +Hydrators are per query instantiated since Doctrine 2.4. + +## Minor BC BREAK: Entity based ``EntityManager#clear()`` calls follow cascade detach + +Whenever ``EntityManager#clear()`` method gets called with a given entity class +name, until 2.4, it was only detaching the specific requested entity. +As of 2.5, ``EntityManager`` will follow configured cascades, providing a better +memory management since associations will be garbage collected, optimizing +resources consumption on long running jobs. + +## BC BREAK: NamingStrategy interface changes + +1. A new method ``embeddedFieldToColumnName($propertyName, $embeddedColumnName)`` + +This method generates the column name for fields of embedded objects. If you implement your custom NamingStrategy, you +now also need to implement this new method. + +2. A change to method ``joinColumnName()`` to include the $className + +## Updates on entities scheduled for deletion are no longer processed + +In Doctrine 2.4, if you modified properties of an entity scheduled for deletion, UnitOfWork would +produce an UPDATE statement to be executed right before the DELETE statement. The entity in question +was therefore present in ``UnitOfWork#entityUpdates``, which means that ``preUpdate`` and ``postUpdate`` +listeners were (quite pointlessly) called. In ``preFlush`` listeners, it used to be possible to undo +the scheduled deletion for updated entities (by calling ``persist()`` if the entity was found in both +``entityUpdates`` and ``entityDeletions``). This does not work any longer, because the entire changeset +calculation logic is optimized away. + +## Minor BC BREAK: Default lock mode changed from LockMode::NONE to null in method signatures + +A misconception concerning default lock mode values in method signatures lead to unexpected behaviour +in SQL statements on SQL Server. With a default lock mode of ``LockMode::NONE`` throughout the +method signatures in ORM, the table lock hint ``WITH (NOLOCK)`` was appended to all locking related +queries by default. This could result in unpredictable results because an explicit ``WITH (NOLOCK)`` +table hint tells SQL Server to run a specific query in transaction isolation level READ UNCOMMITTED +instead of the default READ COMMITTED transaction isolation level. +Therefore there now is a distinction between ``LockMode::NONE`` and ``null`` to be able to tell +Doctrine whether to add table lock hints to queries by intention or not. To achieve this, the following +method signatures have been changed to declare ``$lockMode = null`` instead of ``$lockMode = LockMode::NONE``: + +- ``Doctrine\ORM\Cache\Persister\AbstractEntityPersister#getSelectSQL()`` +- ``Doctrine\ORM\Cache\Persister\AbstractEntityPersister#load()`` +- ``Doctrine\ORM\Cache\Persister\AbstractEntityPersister#refresh()`` +- ``Doctrine\ORM\Decorator\EntityManagerDecorator#find()`` +- ``Doctrine\ORM\EntityManager#find()`` +- ``Doctrine\ORM\EntityRepository#find()`` +- ``Doctrine\ORM\Persisters\BasicEntityPersister#getSelectSQL()`` +- ``Doctrine\ORM\Persisters\BasicEntityPersister#load()`` +- ``Doctrine\ORM\Persisters\BasicEntityPersister#refresh()`` +- ``Doctrine\ORM\Persisters\EntityPersister#getSelectSQL()`` +- ``Doctrine\ORM\Persisters\EntityPersister#load()`` +- ``Doctrine\ORM\Persisters\EntityPersister#refresh()`` +- ``Doctrine\ORM\Persisters\JoinedSubclassPersister#getSelectSQL()`` + +You should update signatures for these methods if you have subclassed one of the above classes. +Please also check the calling code of these methods in your application and update if necessary. + +**Note:** +This in fact is really a minor BC BREAK and should not have any affect on database vendors +other than SQL Server because it is the only one that supports and therefore cares about +``LockMode::NONE``. It's really just a FIX for SQL Server environments using ORM. + +## Minor BC BREAK: `__clone` method not called anymore when entities are instantiated via metadata API + +As of PHP 5.6, instantiation of new entities is deferred to the +[`doctrine/instantiator`](https://github.com/doctrine/instantiator) library, which will avoid calling `__clone` +or any public API on instantiated objects. + +## BC BREAK: `Doctrine\ORM\Repository\DefaultRepositoryFactory` is now `final` + +Please implement the `Doctrine\ORM\Repository\RepositoryFactory` interface instead of extending +the `Doctrine\ORM\Repository\DefaultRepositoryFactory`. + +## BC BREAK: New object expression DQL queries now respects user provided aliasing and not return consumed fields + +When executing DQL queries with new object expressions, instead of returning DTOs numerically indexes, it will now respect user provided aliases. Consider the following query: + + SELECT new UserDTO(u.id,u.name) as user,new AddressDTO(a.street,a.postalCode) as address, a.id as addressId FROM User u INNER JOIN u.addresses a WITH a.isPrimary = true + +Previously, your result would be similar to this: + + array( + 0=>array( + 0=>{UserDTO object}, + 1=>{AddressDTO object}, + 2=>{u.id scalar}, + 3=>{u.name scalar}, + 4=>{a.street scalar}, + 5=>{a.postalCode scalar}, + 'addressId'=>{a.id scalar}, + ), + ... + ) + +From now on, the resultset will look like this: + + array( + 0=>array( + 'user'=>{UserDTO object}, + 'address'=>{AddressDTO object}, + 'addressId'=>{a.id scalar} + ), + ... + ) + +## Minor BC BREAK: added second parameter $indexBy in EntityRepository#createQueryBuilder method signature + +Added way to access the underlying QueryBuilder#from() method's 'indexBy' parameter when using EntityRepository#createQueryBuilder() + +# Upgrade to 2.4 + +## BC BREAK: Compatibility Bugfix in PersistentCollection#matching() + +In Doctrine 2.3 it was possible to use the new ``matching($criteria)`` +functionality by adding constraints for assocations based on ID: + + Criteria::expr()->eq('association', $assocation->getId()); + +This functionality does not work on InMemory collections however, because +in memory criteria compares object values based on reference. +As of 2.4 the above code will throw an exception. You need to change +offending code to pass the ``$assocation`` reference directly: + + Criteria::expr()->eq('association', $assocation); + +## Composer is now the default autoloader + +The test suite now runs with composer autoloading. Support for PEAR, and tarball autoloading is deprecated. +Support for GIT submodules is removed. + +## OnFlush and PostFlush event always called + +Before 2.4 the postFlush and onFlush events were only called when there were +actually entities that changed. Now these events are called no matter if there +are entities in the UoW or changes are found. + +## Parenthesis are now considered in arithmetic expression + +Before 2.4 parenthesis are not considered in arithmetic primary expression. +That's conceptually wrong, since it might result in wrong values. For example: + +The DQL: + + SELECT 100 / ( 2 * 2 ) FROM MyEntity + +Before 2.4 it generates the SQL: + + SELECT 100 / 2 * 2 FROM my_entity + +Now parenthesis are considered, the previous DQL will generate: + + SELECT 100 / (2 * 2) FROM my_entity + +# Upgrade to 2.3 + +## Auto Discriminator Map breaks userland implementations with Listener + +The new feature to detect discriminator maps automatically when none +are provided breaks userland implementations doing this with a +listener in ``loadClassMetadata`` event. + +## EntityManager#find() not calls EntityRepository#find() anymore + +Previous to 2.3, calling ``EntityManager#find()`` would be delegated to +``EntityRepository#find()``. This has lead to some unexpected behavior in the +core of Doctrine when people have overwritten the find method in their +repositories. That is why this behavior has been reversed in 2.3, and +``EntityRepository#find()`` calls ``EntityManager#find()`` instead. + +## EntityGenerator add*() method generation + +When generating an add*() method for a collection the EntityGenerator will now not +use the Type-Hint to get the singular for the collection name, but use the field-name +and strip a trailing "s" character if there is one. + +## Merge copies non persisted properties too + +When merging an entity in UoW not only mapped properties are copied, but also others. + +## Query, QueryBuilder and NativeQuery parameters *BC break* + +From now on, parameters in queries is an ArrayCollection instead of a simple array. +This affects heavily the usage of setParameters(), because it will not append anymore +parameters to query, but will actually override the already defined ones. +Whenever you are retrieving a parameter (ie. $query->getParameter(1)), you will +receive an instance of Query\Parameter, which contains the methods "getName", +"getValue" and "getType". Parameters are also only converted to when necessary, and +not when they are set. + +Also, related functions were affected: + +* execute($parameters, $hydrationMode) the argument $parameters can be either an key=>value array or an ArrayCollection instance +* iterate($parameters, $hydrationMode) the argument $parameters can be either an key=>value array or an ArrayCollection instance +* setParameters($parameters) the argument $parameters can be either an key=>value array or an ArrayCollection instance +* getParameters() now returns ArrayCollection instead of array +* getParameter($key) now returns Parameter instance instead of parameter value + +## Query TreeWalker method renamed + +Internal changes were made to DQL and SQL generation. If you have implemented your own TreeWalker, +you probably need to update it. The method walkJoinVariableDeclaration is now named walkJoin. + +## New methods in TreeWalker interface *BC break* + +Two methods getQueryComponents() and setQueryComponent() were added to the TreeWalker interface and all its implementations +including TreeWalkerAdapter, TreeWalkerChain and SqlWalker. If you have your own implementation not inheriting from one of the +above you must implement these new methods. + +## Metadata Drivers + +Metadata drivers have been rewritten to reuse code from Doctrine\Common. Anyone who is using the +`Doctrine\ORM\Mapping\Driver\Driver` interface should instead refer to +`Doctrine\Common\Persistence\Mapping\Driver\MappingDriver`. Same applies to +`Doctrine\ORM\Mapping\Driver\AbstractFileDriver`: you should now refer to +`Doctrine\Common\Persistence\Mapping\Driver\FileDriver`. + +Also, following mapping drivers have been deprecated, please use their replacements in Doctrine\Common as listed: + + * `Doctrine\ORM\Mapping\Driver\DriverChain` => `Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain` + * `Doctrine\ORM\Mapping\Driver\PHPDriver` => `Doctrine\Common\Persistence\Mapping\Driver\PHPDriver` + * `Doctrine\ORM\Mapping\Driver\StaticPHPDriver` => `Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver` + +# Upgrade to 2.2 + +## ResultCache implementation rewritten + +The result cache is completely rewritten and now works on the database result level, not inside the ORM AbstractQuery +anymore. This means that for result cached queries the hydration will now always be performed again, regardless of +the hydration mode. Affected areas are: + +1. Fixes the problem that entities coming from the result cache were not registered in the UnitOfWork + leading to problems during EntityManager#flush. Calls to EntityManager#merge are not necessary anymore. +2. Affects the array hydrator which now includes the overhead of hydration compared to caching the final result. + +The API is backwards compatible however most of the getter methods on the `AbstractQuery` object are now +deprecated in favor of calling AbstractQuery#getQueryCacheProfile(). This method returns a `Doctrine\DBAL\Cache\QueryCacheProfile` +instance with access to result cache driver, lifetime and cache key. + + +## EntityManager#getPartialReference() creates read-only entity + +Entities returned from EntityManager#getPartialReference() are now marked as read-only if they +haven't been in the identity map before. This means objects of this kind never lead to changes +in the UnitOfWork. + + +## Fields omitted in a partial DQL query or a native query are never updated + +Fields of an entity that are not returned from a partial DQL Query or native SQL query +will never be updated through an UPDATE statement. + + +## Removed support for onUpdate in @JoinColumn + +The onUpdate foreign key handling makes absolutely no sense in an ORM. Additionally Oracle doesn't even support it. Support for it is removed. + + +## Changes in Annotation Handling + +There have been some changes to the annotation handling in Common 2.2 again, that affect how people with old configurations +from 2.0 have to configure the annotation driver if they don't use `Configuration::newDefaultAnnotationDriver()`: + + // Register the ORM Annotations in the AnnotationRegistry + AnnotationRegistry::registerFile('path/to/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php'); + + $reader = new \Doctrine\Common\Annotations\SimpleAnnotationReader(); + $reader->addNamespace('Doctrine\ORM\Mapping'); + $reader = new \Doctrine\Common\Annotations\CachedReader($reader, new ArrayCache()); + + $driver = new AnnotationDriver($reader, (array)$paths); + + $config->setMetadataDriverImpl($driver); + + +## Scalar mappings can now be omitted from DQL result + +You are now allowed to mark scalar SELECT expressions as HIDDEN an they are not hydrated anymore. +Example: + +SELECT u, SUM(a.id) AS HIDDEN numArticles FROM User u LEFT JOIN u.Articles a ORDER BY numArticles DESC HAVING numArticles > 10 + +Your result will be a collection of Users, and not an array with key 0 as User object instance and "numArticles" as the number of articles per user + + +## Map entities as scalars in DQL result + +When hydrating to array or even a mixed result in object hydrator, previously you had the 0 index holding you entity instance. +You are now allowed to alias this, providing more flexibility for you code. +Example: + +SELECT u AS user FROM User u + +Will now return a collection of arrays with index "user" pointing to the User object instance. + + +## Performance optimizations + +Thousands of lines were completely reviewed and optimized for best performance. +Removed redundancy and improved code readability made now internal Doctrine code easier to understand. +Also, Doctrine 2.2 now is around 10-15% faster than 2.1. + +## EntityManager#find(null) + +Previously EntityManager#find(null) returned null. It now throws an exception. + +# Upgrade to 2.1 + +## Interface for EntityRepository + +The EntityRepository now has an interface Doctrine\Common\Persistence\ObjectRepository. This means that your classes that override EntityRepository and extend find(), findOneBy() or findBy() must be adjusted to follow this interface. + +## AnnotationReader changes + +The annotation reader was heavily refactored between 2.0 and 2.1-RC1. In theory the operation of the new reader should be backwards compatible, but it has to be setup differently to work that way: + + // new call to the AnnotationRegistry + \Doctrine\Common\Annotations\AnnotationRegistry::registerFile('/doctrine-src/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php'); + + $reader = new \Doctrine\Common\Annotations\AnnotationReader(); + $reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\'); + // new code necessary starting here + $reader->setIgnoreNotImportedAnnotations(true); + $reader->setEnableParsePhpImports(false); + $reader = new \Doctrine\Common\Annotations\CachedReader( + new \Doctrine\Common\Annotations\IndexedReader($reader), new ArrayCache() + ); + +This is already done inside the ``$config->newDefaultAnnotationDriver``, so everything should automatically work if you are using this method. You can verify if everything still works by executing a console command such as schema-validate that loads all metadata into memory. + +# Update from 2.0-BETA3 to 2.0-BETA4 + +## XML Driver element demoted to attribute + +We changed how the XML Driver allows to define the change-tracking-policy. The working case is now: + + + +# Update from 2.0-BETA2 to 2.0-BETA3 + +## Serialization of Uninitialized Proxies + +As of Beta3 you can now serialize uninitialized proxies, an exception will only be thrown when +trying to access methods on the unserialized proxy as long as it has not been re-attached to the +EntityManager using `EntityManager#merge()`. See this example: + + $proxy = $em->getReference('User', 1); + + $serializedProxy = serialize($proxy); + $detachedProxy = unserialized($serializedProxy); + + echo $em->contains($detachedProxy); // FALSE + + try { + $detachedProxy->getId(); // uninitialized detached proxy + } catch(Exception $e) { + + } + $attachedProxy = $em->merge($detachedProxy); + echo $attackedProxy->getId(); // works! + +## Changed SQL implementation of Postgres and Oracle DateTime types + +The DBAL Type "datetime" included the Timezone Offset in both Postgres and Oracle. As of this version they are now +generated without Timezone (TIMESTAMP WITHOUT TIME ZONE instead of TIMESTAMP WITH TIME ZONE). +See [this comment to Ticket DBAL-22](http://www.doctrine-project.org/jira/browse/DBAL-22?focusedCommentId=13396&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_13396) +for more details as well as migration issues for PostgreSQL and Oracle. + +Both Postgres and Oracle will throw Exceptions during hydration of Objects with "DateTime" fields unless migration steps are taken! + +## Removed multi-dot/deep-path expressions in DQL + +The support for implicit joins in DQL through the multi-dot/Deep Path Expressions +was dropped. For example: + + SELECT u FROM User u WHERE u.group.name = ?1 + +See the "u.group.id" here is using multi dots (deep expression) to walk +through the graph of objects and properties. Internally the DQL parser +would rewrite these queries to: + + SELECT u FROM User u JOIN u.group g WHERE g.name = ?1 + +This explicit notation will be the only supported notation as of now. The internal +handling of multi-dots in the DQL Parser was very complex, error prone in edge cases +and required special treatment for several features we added. Additionally +it had edge cases that could not be solved without making the DQL Parser +even much more complex. For this reason we will drop the support for the +deep path expressions to increase maintainability and overall performance +of the DQL parsing process. This will benefit any DQL query being parsed, +even those not using deep path expressions. + +Note that the generated SQL of both notations is exactly the same! You +don't loose anything through this. + +## Default Allocation Size for Sequences + +The default allocation size for sequences has been changed from 10 to 1. This step was made +to not cause confusion with users and also because it is partly some kind of premature optimization. + +# Update from 2.0-BETA1 to 2.0-BETA2 + +There are no backwards incompatible changes in this release. + +# Upgrade from 2.0-ALPHA4 to 2.0-BETA1 + +## EntityRepository deprecates access to protected variables + +Instead of accessing protected variables for the EntityManager in +a custom EntityRepository it is now required to use the getter methods +for all the three instance variables: + +* `$this->_em` now accessible through `$this->getEntityManager()` +* `$this->_class` now accessible through `$this->getClassMetadata()` +* `$this->_entityName` now accessible through `$this->getEntityName()` + +Important: For Beta 2 the protected visibility of these three properties will be +changed to private! + +## Console migrated to Symfony Console + +The Doctrine CLI has been replaced by Symfony Console Configuration + +Instead of having to specify: + + [php] + $cliConfig = new CliConfiguration(); + $cliConfig->setAttribute('em', $entityManager); + +You now have to configure the script like: + + [php] + $helperSet = new \Symfony\Components\Console\Helper\HelperSet(array( + 'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()), + 'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) + )); + +## Console: No need for Mapping Paths anymore + +In previous versions you had to specify the --from and --from-path options +to show where your mapping paths are from the console. However this information +is already known from the Mapping Driver configuration, so the requirement +for this options were dropped. + +Instead for each console command all the entities are loaded and to +restrict the operation to one or more sub-groups you can use the --filter flag. + +## AnnotationDriver is not a default mapping driver anymore + +In conjunction with the recent changes to Console we realized that the +annotations driver being a default metadata driver lead to lots of glue +code in the console components to detect where entities lie and how to load +them for batch updates like SchemaTool and other commands. However the +annotations driver being a default driver does not really help that much +anyways. + +Therefore we decided to break backwards compatibility in this issue and drop +the support for Annotations as Default Driver and require our users to +specify the driver explicitly (which allows us to ask for the path to all +entities). + +If you are using the annotations metadata driver as default driver, you +have to add the following lines to your bootstrap code: + + $driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Entities")); + $config->setMetadataDriverImpl($driverImpl); + +You have to specify the path to your entities as either string of a single +path or array of multiple paths +to your entities. This information will be used by all console commands to +access all entities. + +Xml and Yaml Drivers work as before! + + +## New inversedBy attribute + +It is now *mandatory* that the owning side of a bidirectional association specifies the +'inversedBy' attribute that points to the name of the field on the inverse side that completes +the association. Example: + + [php] + // BEFORE (ALPHA4 AND EARLIER) + class User + { + //... + /** @OneToOne(targetEntity="Address", mappedBy="user") */ + private $address; + //... + } + class Address + { + //... + /** @OneToOne(targetEntity="User") */ + private $user; + //... + } + + // SINCE BETA1 + // User class DOES NOT CHANGE + class Address + { + //... + /** @OneToOne(targetEntity="User", inversedBy="address") */ + private $user; + //... + } + +Thus, the inversedBy attribute is the counterpart to the mappedBy attribute. This change +was necessary to enable some simplifications and further performance improvements. We +apologize for the inconvenience. + +## Default Property for Field Mappings + +The "default" option for database column defaults has been removed. If desired, database column defaults can +be implemented by using the columnDefinition attribute of the @Column annotation (or the appropriate XML and YAML equivalents). +Prefer PHP default values, if possible. + +## Selecting Partial Objects + +Querying for partial objects now has a new syntax. The old syntax to query for partial objects +now has a different meaning. This is best illustrated by an example. If you previously +had a DQL query like this: + + [sql] + SELECT u.id, u.name FROM User u + +Since BETA1, simple state field path expressions in the select clause are used to select +object fields as plain scalar values (something that was not possible before). +To achieve the same result as previously (that is, a partial object with only id and name populated) +you need to use the following, explicit syntax: + + [sql] + SELECT PARTIAL u.{id,name} FROM User u + +## XML Mapping Driver + +The 'inheritance-type' attribute changed to take last bit of ClassMetadata constant names, i.e. +NONE, SINGLE_TABLE, INHERITANCE_TYPE_JOINED + +## YAML Mapping Driver + +The way to specify lifecycle callbacks in YAML Mapping driver was changed to allow for multiple callbacks +per event. The Old syntax ways: + + [yaml] + lifecycleCallbacks: + doStuffOnPrePersist: prePersist + doStuffOnPostPersist: postPersist + +The new syntax is: + + [yaml] + lifecycleCallbacks: + prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ] + postPersist: [ doStuffOnPostPersist ] + +## PreUpdate Event Listeners + +Event Listeners listening to the 'preUpdate' event can only affect the primitive values of entity changesets +by using the API on the `PreUpdateEventArgs` instance passed to the preUpdate listener method. Any changes +to the state of the entitys properties won't affect the database UPDATE statement anymore. This gives drastic +performance benefits for the preUpdate event. + +## Collection API + +The Collection interface in the Common package has been updated with some missing methods +that were present only on the default implementation, ArrayCollection. Custom collection +implementations need to be updated to adhere to the updated interface. + +# Upgrade from 2.0-ALPHA3 to 2.0-ALPHA4 + +## CLI Controller changes + +CLI main object changed its name and namespace. Renamed from Doctrine\ORM\Tools\Cli to Doctrine\Common\Cli\CliController. +Doctrine\Common\Cli\CliController now only deals with namespaces. Ready to go, Core, Dbal and Orm are available and you can subscribe new tasks by retrieving the namespace and including new task. Example: + + [php] + $cli->getNamespace('Core')->addTask('my-example', '\MyProject\Tools\Cli\Tasks\MyExampleTask'); + + +## CLI Tasks documentation + +Tasks have implemented a new way to build documentation. Although it is still possible to define the help manually by extending the basicHelp and extendedHelp, they are now optional. +With new required method AbstractTask::buildDocumentation, its implementation defines the TaskDocumentation instance (accessible through AbstractTask::getDocumentation()), basicHelp and extendedHelp are now not necessary to be implemented. + +## Changes in Method Signatures + + * A bunch of Methods on both Doctrine\DBAL\Platforms\AbstractPlatform and Doctrine\DBAL\Schema\AbstractSchemaManager + have changed quite significantly by adopting the new Schema instance objects. + +## Renamed Methods + + * Doctrine\ORM\AbstractQuery::setExpireResultCache() -> expireResultCache() + * Doctrine\ORM\Query::setExpireQueryCache() -> expireQueryCache() + +## SchemaTool Changes + + * "doctrine schema-tool --drop" now always drops the complete database instead of + only those tables defined by the current database model. The previous method had + problems when foreign keys of orphaned tables pointed to tables that were scheduled + for deletion. + * Use "doctrine schema-tool --update" to get a save incremental update for your + database schema without deleting any unused tables, sequences or foreign keys. + * Use "doctrine schema-tool --complete-update" to do a full incremental update of + your schema. +# Upgrade from 2.0-ALPHA2 to 2.0-ALPHA3 + +This section details the changes made to Doctrine 2.0-ALPHA3 to make it easier for you +to upgrade your projects to use this version. + +## CLI Changes + +The $args variable used in the cli-config.php for configuring the Doctrine CLI has been renamed to $globalArguments. + +## Proxy class changes + +You are now required to make supply some minimalist configuration with regards to proxy objects. That involves 2 new configuration options. First, the directory where generated proxy classes should be placed needs to be specified. Secondly, you need to configure the namespace used for proxy classes. The following snippet shows an example: + + [php] + // step 1: configure directory for proxy classes + // $config instanceof Doctrine\ORM\Configuration + $config->setProxyDir('/path/to/myproject/lib/MyProject/Generated/Proxies'); + $config->setProxyNamespace('MyProject\Generated\Proxies'); + +Note that proxy classes behave exactly like any other classes when it comes to class loading. Therefore you need to make sure the proxy classes can be loaded by some class loader. If you place the generated proxy classes in a namespace and directory under your projects class files, like in the example above, it would be sufficient to register the MyProject namespace on a class loader. Since the proxy classes are contained in that namespace and adhere to the standards for class loading, no additional work is required. +Generating the proxy classes into a namespace within your class library is the recommended setup. + +Entities with initialized proxy objects can now be serialized and unserialized properly from within the same application. + +For more details refer to the Configuration section of the manual. + +## Removed allowPartialObjects configuration option + +The allowPartialObjects configuration option together with the `Configuration#getAllowPartialObjects` and `Configuration#setAllowPartialObjects` methods have been removed. +The new behavior is as if the option were set to FALSE all the time, basically disallowing partial objects globally. However, you can still use the `Query::HINT_FORCE_PARTIAL_LOAD` query hint to force a query to return partial objects for optimization purposes. + +## Renamed Methods + +* Doctrine\ORM\Configuration#getCacheDir() to getProxyDir() +* Doctrine\ORM\Configuration#setCacheDir($dir) to setProxyDir($dir) diff --git a/vendor/doctrine/orm/bin/doctrine b/vendor/doctrine/orm/bin/doctrine new file mode 100755 index 0000000..c359ca7 --- /dev/null +++ b/vendor/doctrine/orm/bin/doctrine @@ -0,0 +1,4 @@ +#!/usr/bin/env php +. + */ + +require_once 'Doctrine/Common/ClassLoader.php'; + +$classLoader = new \Doctrine\Common\ClassLoader('Doctrine'); +$classLoader->register(); + +$classLoader = new \Doctrine\Common\ClassLoader('Symfony'); +$classLoader->register(); + +$configFile = getcwd() . DIRECTORY_SEPARATOR . 'cli-config.php'; + +$helperSet = null; +if (file_exists($configFile)) { + if ( ! is_readable($configFile)) { + trigger_error( + 'Configuration file [' . $configFile . '] does not have read permission.', E_USER_ERROR + ); + } + + require $configFile; + + foreach ($GLOBALS as $helperSetCandidate) { + if ($helperSetCandidate instanceof \Symfony\Component\Console\Helper\HelperSet) { + $helperSet = $helperSetCandidate; + break; + } + } +} + +$helperSet = ($helperSet) ?: new \Symfony\Component\Console\Helper\HelperSet(); + +\Doctrine\ORM\Tools\Console\ConsoleRunner::run($helperSet); diff --git a/vendor/doctrine/orm/bin/doctrine.bat b/vendor/doctrine/orm/bin/doctrine.bat new file mode 100644 index 0000000..a9e8cee --- /dev/null +++ b/vendor/doctrine/orm/bin/doctrine.bat @@ -0,0 +1,9 @@ +@echo off + +if "%PHPBIN%" == "" set PHPBIN=@php_bin@ +if not exist "%PHPBIN%" if "%PHP_PEAR_PHP_BIN%" neq "" goto USE_PEAR_PATH +GOTO RUN +:USE_PEAR_PATH +set PHPBIN=%PHP_PEAR_PHP_BIN% +:RUN +"%PHPBIN%" "@bin_dir@\doctrine" %* diff --git a/vendor/doctrine/orm/bin/doctrine.php b/vendor/doctrine/orm/bin/doctrine.php new file mode 100644 index 0000000..81d4e7b --- /dev/null +++ b/vendor/doctrine/orm/bin/doctrine.php @@ -0,0 +1,69 @@ +. + */ + +use Symfony\Component\Console\Helper\HelperSet; +use Doctrine\ORM\Tools\Console\ConsoleRunner; + +$autoloadFiles = [ + __DIR__ . '/../vendor/autoload.php', + __DIR__ . '/../../../autoload.php' +]; + +foreach ($autoloadFiles as $autoloadFile) { + if (file_exists($autoloadFile)) { + require_once $autoloadFile; + break; + } +} + +$directories = [getcwd(), getcwd() . DIRECTORY_SEPARATOR . 'config']; + +$configFile = null; +foreach ($directories as $directory) { + $configFile = $directory . DIRECTORY_SEPARATOR . 'cli-config.php'; + + if (file_exists($configFile)) { + break; + } +} + +if ( ! file_exists($configFile)) { + ConsoleRunner::printCliConfigTemplate(); + exit(1); +} + +if ( ! is_readable($configFile)) { + echo 'Configuration file [' . $configFile . '] does not have read permission.' . "\n"; + exit(1); +} + +$commands = []; + +$helperSet = require $configFile; + +if ( ! ($helperSet instanceof HelperSet)) { + foreach ($GLOBALS as $helperSetCandidate) { + if ($helperSetCandidate instanceof HelperSet) { + $helperSet = $helperSetCandidate; + break; + } + } +} + +ConsoleRunner::run($helperSet, $commands); diff --git a/vendor/doctrine/orm/composer.json b/vendor/doctrine/orm/composer.json new file mode 100644 index 0000000..c74e9cf --- /dev/null +++ b/vendor/doctrine/orm/composer.json @@ -0,0 +1,57 @@ +{ + "name": "doctrine/orm", + "type": "library", + "description": "Object-Relational-Mapper for PHP", + "keywords": ["orm", "database"], + "homepage": "https://www.doctrine-project.org/projects/orm.html", + "license": "MIT", + "authors": [ + {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, + {"name": "Roman Borschel", "email": "roman@code-factory.org"}, + {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, + {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, + {"name": "Marco Pivetta", "email": "ocramius@gmail.com"} + ], + "config": { + "sort-packages": true + }, + "require": { + "php": "^7.1", + "ext-pdo": "*", + "doctrine/annotations": "^1.8", + "doctrine/cache": "^1.9.1", + "doctrine/collections": "^1.5", + "doctrine/common": "^2.11", + "doctrine/dbal": "^2.9.3", + "doctrine/event-manager": "^1.1", + "doctrine/instantiator": "^1.3", + "doctrine/persistence": "^1.2", + "symfony/console": "^3.0|^4.0|^5.0" + }, + "require-dev": { + "doctrine/coding-standard": "^5.0", + "phpunit/phpunit": "^7.5", + "symfony/yaml": "^3.4|^4.0|^5.0" + }, + "suggest": { + "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" + }, + "autoload": { + "psr-4": { "Doctrine\\ORM\\": "lib/Doctrine/ORM" } + }, + "autoload-dev": { + "psr-4": { + "Doctrine\\Tests\\": "tests/Doctrine/Tests", + "Doctrine\\Performance\\": "tests/Doctrine/Performance" + } + }, + "bin": ["bin/doctrine"], + "extra": { + "branch-alias": { + "dev-master": "2.7.x-dev" + } + }, + "archive": { + "exclude": ["!vendor", "tests", "*phpunit.xml", ".travis.yml", "build.xml", "build.properties", "composer.phar", "vendor/satooshi", "lib/vendor", "*.swp"] + } +} diff --git a/vendor/doctrine/orm/composer.lock b/vendor/doctrine/orm/composer.lock new file mode 100644 index 0000000..fc220d2 --- /dev/null +++ b/vendor/doctrine/orm/composer.lock @@ -0,0 +1,2744 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "4e24e01f599825550170acce0dda0b49", + "packages": [ + { + "name": "doctrine/annotations", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/904dca4eb10715b92569fbcd79e201d5c349b6bc", + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "^7.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2019-10-01T18:55:10+00:00" + }, + { + "name": "doctrine/cache", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "89a5c76c39c292f7798f964ab3c836c3f8192a55" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/89a5c76c39c292f7798f964ab3c836c3f8192a55", + "reference": "89a5c76c39c292f7798f964ab3c836c3f8192a55", + "shasum": "" + }, + "require": { + "php": "~7.1" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^6.0", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^7.0", + "predis/predis": "~1.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", + "homepage": "https://www.doctrine-project.org/projects/cache.html", + "keywords": [ + "abstraction", + "apcu", + "cache", + "caching", + "couchdb", + "memcached", + "php", + "redis", + "riak", + "xcache" + ], + "time": "2019-11-15T14:31:57+00:00" + }, + { + "name": "doctrine/collections", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/a01ee38fcd999f34d9bfbcee59dbda5105449cbf", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "~0.1@dev", + "phpunit/phpunit": "^5.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Collections\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Collections Abstraction library", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "array", + "collections", + "iterator" + ], + "time": "2017-07-22T10:37:32+00:00" + }, + { + "name": "doctrine/common", + "version": "v2.11.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/common.git", + "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/common/zipball/b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", + "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/inflector": "^1.0", + "doctrine/lexer": "^1.0", + "doctrine/persistence": "^1.1", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^1.0", + "phpstan/phpstan": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0", + "symfony/phpunit-bridge": "^4.0.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.11.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, persistence interfaces, proxies, event system and much more.", + "homepage": "https://www.doctrine-project.org/projects/common.html", + "keywords": [ + "common", + "doctrine", + "php" + ], + "time": "2019-09-10T10:10:14+00:00" + }, + { + "name": "doctrine/dbal", + "version": "v2.9.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "7345cd59edfa2036eb0fa4264b77ae2576842035" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/7345cd59edfa2036eb0fa4264b77ae2576842035", + "reference": "7345cd59edfa2036eb0fa4264b77ae2576842035", + "shasum": "" + }, + "require": { + "doctrine/cache": "^1.0", + "doctrine/event-manager": "^1.0", + "ext-pdo": "*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^5.0", + "jetbrains/phpstorm-stubs": "^2018.1.2", + "phpstan/phpstan": "^0.10.1", + "phpunit/phpunit": "^7.4", + "symfony/console": "^2.0.5|^3.0|^4.0", + "symfony/phpunit-bridge": "^3.4.5|^4.0.5" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "bin": [ + "bin/doctrine-dbal" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.9.x-dev", + "dev-develop": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\DBAL\\": "lib/Doctrine/DBAL" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", + "keywords": [ + "abstraction", + "database", + "dbal", + "mysql", + "persistence", + "pgsql", + "php", + "queryobject" + ], + "time": "2019-11-02T22:19:34+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "629572819973f13486371cb611386eb17851e85c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/629572819973f13486371cb611386eb17851e85c", + "reference": "629572819973f13486371cb611386eb17851e85c", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "event dispatcher", + "event manager", + "event system", + "events" + ], + "time": "2019-11-10T09:48:07+00:00" + }, + { + "name": "doctrine/inflector", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2019-10-30T19:59:35+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2019-10-21T16:45:58+00:00" + }, + { + "name": "doctrine/lexer", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "^4.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "time": "2019-06-08T11:03:04+00:00" + }, + { + "name": "doctrine/persistence", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/persistence.git", + "reference": "43526ae63312942e5316100bb3ed589ba1aba491" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/43526ae63312942e5316100bb3ed589ba1aba491", + "reference": "43526ae63312942e5316100bb3ed589ba1aba491", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.10@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^5.0", + "phpstan/phpstan": "^0.8", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", + "homepage": "https://doctrine-project.org/projects/persistence.html", + "keywords": [ + "mapper", + "object", + "odm", + "orm", + "persistence" + ], + "time": "2019-04-23T12:39:21+00:00" + }, + { + "name": "doctrine/reflection", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/reflection.git", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/reflection/zipball/02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "doctrine/common": "^2.8", + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Reflection component", + "homepage": "https://www.doctrine-project.org/projects/reflection.html", + "keywords": [ + "reflection" + ], + "time": "2018-06-14T14:45:07+00:00" + }, + { + "name": "psr/log", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2019-11-01T11:05:21+00:00" + }, + { + "name": "symfony/console", + "version": "v3.4.35", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "17b154f932c5874cdbda6d05796b6490eec9f9f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/17b154f932c5874cdbda6d05796b6490eec9f9f7", + "reference": "17b154f932c5874cdbda6d05796b6490eec9f9f7", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/debug": "~2.8|~3.0|~4.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.3|~4.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2019-11-13T07:12:39+00:00" + }, + { + "name": "symfony/debug", + "version": "v3.4.35", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "f72e33fdb1170b326e72c3157f0cd456351dd086" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/f72e33fdb1170b326e72c3157f0cd456351dd086", + "reference": "f72e33fdb1170b326e72c3157f0cd456351dd086", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/http-kernel": "~2.8|~3.0|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2019-10-24T15:33:53+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2019-08-06T08:03:45+00:00" + } + ], + "packages-dev": [ + { + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v0.5.0", + "source": { + "type": "git", + "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", + "reference": "e749410375ff6fb7a040a68878c656c2e610b132" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/e749410375ff6fb7a040a68878c656c2e610b132", + "reference": "e749410375ff6fb7a040a68878c656c2e610b132", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0", + "php": "^5.3|^7", + "squizlabs/php_codesniffer": "^2|^3" + }, + "require-dev": { + "composer/composer": "*", + "phpcompatibility/php-compatibility": "^9.0", + "sensiolabs/security-checker": "^4.1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "autoload": { + "psr-4": { + "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://www.dealerdirect.com", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "time": "2018-10-26T13:21:45+00:00" + }, + { + "name": "doctrine/coding-standard", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/coding-standard.git", + "reference": "9017efe98b47329cbd895d43f596747c8ef27307" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/coding-standard/zipball/9017efe98b47329cbd895d43f596747c8ef27307", + "reference": "9017efe98b47329cbd895d43f596747c8ef27307", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5.0", + "php": "^7.1", + "slevomat/coding-standard": "^4.8.0", + "squizlabs/php_codesniffer": "^3.3.2" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "5.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Sniffs\\": "lib/Doctrine/Sniffs" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Steve Müller", + "email": "st.mueller@dzh-online.de" + } + ], + "description": "The Doctrine Coding Standard is a set of PHPCS rules applied to all Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/coding-standard.html", + "keywords": [ + "checks", + "code", + "coding", + "cs", + "doctrine", + "rules", + "sniffer", + "sniffs", + "standard", + "style" + ], + "time": "2019-01-31T13:22:30+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.9.3", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea", + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" + }, + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2019-08-09T12:45:53+00:00" + }, + { + "name": "phar-io/manifest", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^2.0", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2018-07-08T19:23:20+00:00" + }, + { + "name": "phar-io/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2018-07-08T19:19:57+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "~6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2018-08-07T13:53:10+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "4.3.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/b83ff7cfcfee7827e1e78b637a5904fe6a96698e", + "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e", + "shasum": "" + }, + "require": { + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", + "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "doctrine/instantiator": "^1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2019-09-12T14:27:41+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "shasum": "" + }, + "require": { + "php": "^7.1", + "phpdocumentor/reflection-common": "^2.0" + }, + "require-dev": { + "ext-tokenizer": "^7.1", + "mockery/mockery": "~1", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "time": "2019-08-22T18:11:29+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "1.9.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203", + "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "psr-4": { + "Prophecy\\": "src/Prophecy" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2019-10-03T11:07:50+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "6.1.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.1", + "phpunit/php-file-iterator": "^2.0", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^3.0", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.1 || ^4.0", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "suggest": { + "ext-xdebug": "^2.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2018-10-31T16:06:48+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "050bedf145a257b1ff02746c31894800e5122946" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", + "reference": "050bedf145a257b1ff02746c31894800e5122946", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2018-09-13T20:33:42+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2015-06-21T13:50:34+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "2.1.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "1038454804406b0b5f5f520358e78c1c2f71501e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e", + "reference": "1038454804406b0b5f5f520358e78c1c2f71501e", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2019-06-07T04:22:29+00:00" + }, + { + "name": "phpunit/php-token-stream", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff", + "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2019-09-17T06:23:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "7.5.17", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "4c92a15296e58191a4cd74cff3b34fc8e374174a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4c92a15296e58191a4cd74cff3b34fc8e374174a", + "reference": "4c92a15296e58191a4cd74cff3b34fc8e374174a", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "^1.7", + "phar-io/manifest": "^1.0.2", + "phar-io/version": "^2.0", + "php": "^7.1", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^6.0.7", + "phpunit/php-file-iterator": "^2.0.1", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^2.1", + "sebastian/comparator": "^3.0", + "sebastian/diff": "^3.0", + "sebastian/environment": "^4.0", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^2.0", + "sebastian/version": "^2.0.1" + }, + "conflict": { + "phpunit/phpunit-mock-objects": "*" + }, + "require-dev": { + "ext-pdo": "*" + }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*", + "phpunit/php-invoker": "^2.0" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2019-10-28T10:37:36+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2017-03-04T06:30:41+00:00" + }, + { + "name": "sebastian/comparator", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "shasum": "" + }, + "require": { + "php": "^7.1", + "sebastian/diff": "^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2018-07-12T15:12:46+00:00" + }, + { + "name": "sebastian/diff", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.0", + "symfony/process": "^2 || ^3.3 || ^4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "time": "2019-02-04T06:01:07+00:00" + }, + { + "name": "sebastian/environment", + "version": "4.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404", + "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.5" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2019-05-05T09:05:15+00:00" + }, + { + "name": "sebastian/exporter", + "version": "3.1.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2019-09-14T09:02:43+00:00" + }, + { + "name": "sebastian/global-state", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2017-04-27T15:39:26+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2017-08-03T12:35:26+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "773f97c67f28de00d397be301821b06708fca0be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", + "reference": "773f97c67f28de00d397be301821b06708fca0be", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2017-03-29T09:07:27+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2017-03-03T06:23:57+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", + "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2018-10-04T04:07:39+00:00" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-10-03T07:35:21+00:00" + }, + { + "name": "slevomat/coding-standard", + "version": "4.8.7", + "source": { + "type": "git", + "url": "https://github.com/slevomat/coding-standard.git", + "reference": "bff96313d8c7c2ba57a4edb13c1c141df8988c58" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/bff96313d8c7c2ba57a4edb13c1c141df8988c58", + "reference": "bff96313d8c7c2ba57a4edb13c1c141df8988c58", + "shasum": "" + }, + "require": { + "php": "^7.1", + "squizlabs/php_codesniffer": "^3.4.0" + }, + "require-dev": { + "jakub-onderka/php-parallel-lint": "1.0.0", + "phing/phing": "2.16.1", + "phpstan/phpstan": "0.9.2", + "phpstan/phpstan-phpunit": "0.9.4", + "phpstan/phpstan-strict-rules": "0.9", + "phpunit/phpunit": "7.5.1" + }, + "type": "phpcodesniffer-standard", + "autoload": { + "psr-4": { + "SlevomatCodingStandard\\": "SlevomatCodingStandard" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", + "time": "2019-01-03T13:15:50+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.5.2", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "65b12cdeaaa6cd276d4c3033a95b9b88b12701e7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/65b12cdeaaa6cd276d4c3033a95b9b88b12701e7", + "reference": "65b12cdeaaa6cd276d4c3033a95b9b88b12701e7", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2019-10-28T04:36:32+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/yaml", + "version": "v3.4.35", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "dab657db15207879217fc81df4f875947bf68804" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/dab657db15207879217fc81df4f875947bf68804", + "reference": "dab657db15207879217fc81df4f875947bf68804", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2019-10-24T15:33:53+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "role": "Developer", + "email": "arne@blankerts.de" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2019-06-13T22:48:21+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4", + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^7.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2019-08-24T08:43:50+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.1", + "ext-pdo": "*" + }, + "platform-dev": [] +} diff --git a/vendor/doctrine/orm/docs/LICENSE.md b/vendor/doctrine/orm/docs/LICENSE.md new file mode 100644 index 0000000..1bf8659 --- /dev/null +++ b/vendor/doctrine/orm/docs/LICENSE.md @@ -0,0 +1,363 @@ +The Doctrine2 documentation is licensed under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_US) + +Creative Commons Legal Code + +Attribution-NonCommercial-ShareAlike 3.0 Unported + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR + DAMAGES RESULTING FROM ITS USE. + +License + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE +COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY +COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS +AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE +TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY +BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS +CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND +CONDITIONS. + +1. Definitions + + a. "Adaptation" means a work based upon the Work, or upon the Work and + other pre-existing works, such as a translation, adaptation, + derivative work, arrangement of music or other alterations of a + literary or artistic work, or phonogram or performance and includes + cinematographic adaptations or any other form in which the Work may be + recast, transformed, or adapted including in any form recognizably + derived from the original, except that a work that constitutes a + Collection will not be considered an Adaptation for the purpose of + this License. For the avoidance of doubt, where the Work is a musical + work, performance or phonogram, the synchronization of the Work in + timed-relation with a moving image ("synching") will be considered an + Adaptation for the purpose of this License. + b. "Collection" means a collection of literary or artistic works, such as + encyclopedias and anthologies, or performances, phonograms or + broadcasts, or other works or subject matter other than works listed + in Section 1(g) below, which, by reason of the selection and + arrangement of their contents, constitute intellectual creations, in + which the Work is included in its entirety in unmodified form along + with one or more other contributions, each constituting separate and + independent works in themselves, which together are assembled into a + collective whole. A work that constitutes a Collection will not be + considered an Adaptation (as defined above) for the purposes of this + License. + c. "Distribute" means to make available to the public the original and + copies of the Work or Adaptation, as appropriate, through sale or + other transfer of ownership. + d. "License Elements" means the following high-level license attributes + as selected by Licensor and indicated in the title of this License: + Attribution, Noncommercial, ShareAlike. + e. "Licensor" means the individual, individuals, entity or entities that + offer(s) the Work under the terms of this License. + f. "Original Author" means, in the case of a literary or artistic work, + the individual, individuals, entity or entities who created the Work + or if no individual or entity can be identified, the publisher; and in + addition (i) in the case of a performance the actors, singers, + musicians, dancers, and other persons who act, sing, deliver, declaim, + play in, interpret or otherwise perform literary or artistic works or + expressions of folklore; (ii) in the case of a phonogram the producer + being the person or legal entity who first fixes the sounds of a + performance or other sounds; and, (iii) in the case of broadcasts, the + organization that transmits the broadcast. + g. "Work" means the literary and/or artistic work offered under the terms + of this License including without limitation any production in the + literary, scientific and artistic domain, whatever may be the mode or + form of its expression including digital form, such as a book, + pamphlet and other writing; a lecture, address, sermon or other work + of the same nature; a dramatic or dramatico-musical work; a + choreographic work or entertainment in dumb show; a musical + composition with or without words; a cinematographic work to which are + assimilated works expressed by a process analogous to cinematography; + a work of drawing, painting, architecture, sculpture, engraving or + lithography; a photographic work to which are assimilated works + expressed by a process analogous to photography; a work of applied + art; an illustration, map, plan, sketch or three-dimensional work + relative to geography, topography, architecture or science; a + performance; a broadcast; a phonogram; a compilation of data to the + extent it is protected as a copyrightable work; or a work performed by + a variety or circus performer to the extent it is not otherwise + considered a literary or artistic work. + h. "You" means an individual or entity exercising rights under this + License who has not previously violated the terms of this License with + respect to the Work, or who has received express permission from the + Licensor to exercise rights under this License despite a previous + violation. + i. "Publicly Perform" means to perform public recitations of the Work and + to communicate to the public those public recitations, by any means or + process, including by wire or wireless means or public digital + performances; to make available to the public Works in such a way that + members of the public may access these Works from a place and at a + place individually chosen by them; to perform the Work to the public + by any means or process and the communication to the public of the + performances of the Work, including by public digital performance; to + broadcast and rebroadcast the Work by any means including signs, + sounds or images. + j. "Reproduce" means to make copies of the Work by any means including + without limitation by sound or visual recordings and the right of + fixation and reproducing fixations of the Work, including storage of a + protected performance or phonogram in digital form or other electronic + medium. + +2. Fair Dealing Rights. Nothing in this License is intended to reduce, +limit, or restrict any uses free from copyright or rights arising from +limitations or exceptions that are provided for in connection with the +copyright protection under copyright law or other applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, +Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +perpetual (for the duration of the applicable copyright) license to +exercise the rights in the Work as stated below: + + a. to Reproduce the Work, to incorporate the Work into one or more + Collections, and to Reproduce the Work as incorporated in the + Collections; + b. to create and Reproduce Adaptations provided that any such Adaptation, + including any translation in any medium, takes reasonable steps to + clearly label, demarcate or otherwise identify that changes were made + to the original Work. For example, a translation could be marked "The + original work was translated from English to Spanish," or a + modification could indicate "The original work has been modified."; + c. to Distribute and Publicly Perform the Work including as incorporated + in Collections; and, + d. to Distribute and Publicly Perform Adaptations. + +The above rights may be exercised in all media and formats whether now +known or hereafter devised. The above rights include the right to make +such modifications as are technically necessary to exercise the rights in +other media and formats. Subject to Section 8(f), all rights not expressly +granted by Licensor are hereby reserved, including but not limited to the +rights described in Section 4(e). + +4. Restrictions. The license granted in Section 3 above is expressly made +subject to and limited by the following restrictions: + + a. You may Distribute or Publicly Perform the Work only under the terms + of this License. You must include a copy of, or the Uniform Resource + Identifier (URI) for, this License with every copy of the Work You + Distribute or Publicly Perform. You may not offer or impose any terms + on the Work that restrict the terms of this License or the ability of + the recipient of the Work to exercise the rights granted to that + recipient under the terms of the License. You may not sublicense the + Work. You must keep intact all notices that refer to this License and + to the disclaimer of warranties with every copy of the Work You + Distribute or Publicly Perform. When You Distribute or Publicly + Perform the Work, You may not impose any effective technological + measures on the Work that restrict the ability of a recipient of the + Work from You to exercise the rights granted to that recipient under + the terms of the License. This Section 4(a) applies to the Work as + incorporated in a Collection, but this does not require the Collection + apart from the Work itself to be made subject to the terms of this + License. If You create a Collection, upon notice from any Licensor You + must, to the extent practicable, remove from the Collection any credit + as required by Section 4(d), as requested. If You create an + Adaptation, upon notice from any Licensor You must, to the extent + practicable, remove from the Adaptation any credit as required by + Section 4(d), as requested. + b. You may Distribute or Publicly Perform an Adaptation only under: (i) + the terms of this License; (ii) a later version of this License with + the same License Elements as this License; (iii) a Creative Commons + jurisdiction license (either this or a later license version) that + contains the same License Elements as this License (e.g., + Attribution-NonCommercial-ShareAlike 3.0 US) ("Applicable License"). + You must include a copy of, or the URI, for Applicable License with + every copy of each Adaptation You Distribute or Publicly Perform. You + may not offer or impose any terms on the Adaptation that restrict the + terms of the Applicable License or the ability of the recipient of the + Adaptation to exercise the rights granted to that recipient under the + terms of the Applicable License. You must keep intact all notices that + refer to the Applicable License and to the disclaimer of warranties + with every copy of the Work as included in the Adaptation You + Distribute or Publicly Perform. When You Distribute or Publicly + Perform the Adaptation, You may not impose any effective technological + measures on the Adaptation that restrict the ability of a recipient of + the Adaptation from You to exercise the rights granted to that + recipient under the terms of the Applicable License. This Section 4(b) + applies to the Adaptation as incorporated in a Collection, but this + does not require the Collection apart from the Adaptation itself to be + made subject to the terms of the Applicable License. + c. You may not exercise any of the rights granted to You in Section 3 + above in any manner that is primarily intended for or directed toward + commercial advantage or private monetary compensation. The exchange of + the Work for other copyrighted works by means of digital file-sharing + or otherwise shall not be considered to be intended for or directed + toward commercial advantage or private monetary compensation, provided + there is no payment of any monetary compensation in con-nection with + the exchange of copyrighted works. + d. If You Distribute, or Publicly Perform the Work or any Adaptations or + Collections, You must, unless a request has been made pursuant to + Section 4(a), keep intact all copyright notices for the Work and + provide, reasonable to the medium or means You are utilizing: (i) the + name of the Original Author (or pseudonym, if applicable) if supplied, + and/or if the Original Author and/or Licensor designate another party + or parties (e.g., a sponsor institute, publishing entity, journal) for + attribution ("Attribution Parties") in Licensor's copyright notice, + terms of service or by other reasonable means, the name of such party + or parties; (ii) the title of the Work if supplied; (iii) to the + extent reasonably practicable, the URI, if any, that Licensor + specifies to be associated with the Work, unless such URI does not + refer to the copyright notice or licensing information for the Work; + and, (iv) consistent with Section 3(b), in the case of an Adaptation, + a credit identifying the use of the Work in the Adaptation (e.g., + "French translation of the Work by Original Author," or "Screenplay + based on original Work by Original Author"). The credit required by + this Section 4(d) may be implemented in any reasonable manner; + provided, however, that in the case of a Adaptation or Collection, at + a minimum such credit will appear, if a credit for all contributing + authors of the Adaptation or Collection appears, then as part of these + credits and in a manner at least as prominent as the credits for the + other contributing authors. For the avoidance of doubt, You may only + use the credit required by this Section for the purpose of attribution + in the manner set out above and, by exercising Your rights under this + License, You may not implicitly or explicitly assert or imply any + connection with, sponsorship or endorsement by the Original Author, + Licensor and/or Attribution Parties, as appropriate, of You or Your + use of the Work, without the separate, express prior written + permission of the Original Author, Licensor and/or Attribution + Parties. + e. For the avoidance of doubt: + + i. Non-waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme cannot be waived, the Licensor + reserves the exclusive right to collect such royalties for any + exercise by You of the rights granted under this License; + ii. Waivable Compulsory License Schemes. In those jurisdictions in + which the right to collect royalties through any statutory or + compulsory licensing scheme can be waived, the Licensor reserves + the exclusive right to collect such royalties for any exercise by + You of the rights granted under this License if Your exercise of + such rights is for a purpose or use which is otherwise than + noncommercial as permitted under Section 4(c) and otherwise waives + the right to collect royalties through any statutory or compulsory + licensing scheme; and, + iii. Voluntary License Schemes. The Licensor reserves the right to + collect royalties, whether individually or, in the event that the + Licensor is a member of a collecting society that administers + voluntary licensing schemes, via that society, from any exercise + by You of the rights granted under this License that is for a + purpose or use which is otherwise than noncommercial as permitted + under Section 4(c). + f. Except as otherwise agreed in writing by the Licensor or as may be + otherwise permitted by applicable law, if You Reproduce, Distribute or + Publicly Perform the Work either by itself or as part of any + Adaptations or Collections, You must not distort, mutilate, modify or + take other derogatory action in relation to the Work which would be + prejudicial to the Original Author's honor or reputation. Licensor + agrees that in those jurisdictions (e.g. Japan), in which any exercise + of the right granted in Section 3(b) of this License (the right to + make Adaptations) would be deemed to be a distortion, mutilation, + modification or other derogatory action prejudicial to the Original + Author's honor and reputation, the Licensor will waive or not assert, + as appropriate, this Section, to the fullest extent permitted by the + applicable national law, to enable You to reasonably exercise Your + right under Section 3(b) of this License (right to make Adaptations) + but not otherwise. + +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING AND TO THE +FULLEST EXTENT PERMITTED BY APPLICABLE LAW, LICENSOR OFFERS THE WORK AS-IS +AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE +WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT +LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, +ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT +DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED +WARRANTIES, SO THIS EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE +LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR +ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES +ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. Termination + + a. This License and the rights granted hereunder will terminate + automatically upon any breach by You of the terms of this License. + Individuals or entities who have received Adaptations or Collections + from You under this License, however, will not have their licenses + terminated provided such individuals or entities remain in full + compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will + survive any termination of this License. + b. Subject to the above terms and conditions, the license granted here is + perpetual (for the duration of the applicable copyright in the Work). + Notwithstanding the above, Licensor reserves the right to release the + Work under different license terms or to stop distributing the Work at + any time; provided, however that any such election will not serve to + withdraw this License (or any other license that has been, or is + required to be, granted under the terms of this License), and this + License will continue in full force and effect unless terminated as + stated above. + +8. Miscellaneous + + a. Each time You Distribute or Publicly Perform the Work or a Collection, + the Licensor offers to the recipient a license to the Work on the same + terms and conditions as the license granted to You under this License. + b. Each time You Distribute or Publicly Perform an Adaptation, Licensor + offers to the recipient a license to the original Work on the same + terms and conditions as the license granted to You under this License. + c. If any provision of this License is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability of + the remainder of the terms of this License, and without further action + by the parties to this agreement, such provision shall be reformed to + the minimum extent necessary to make such provision valid and + enforceable. + d. No term or provision of this License shall be deemed waived and no + breach consented to unless such waiver or consent shall be in writing + and signed by the party to be charged with such waiver or consent. + e. This License constitutes the entire agreement between the parties with + respect to the Work licensed here. There are no understandings, + agreements or representations with respect to the Work not specified + here. Licensor shall not be bound by any additional provisions that + may appear in any communication from You. This License may not be + modified without the mutual written agreement of the Licensor and You. + f. The rights granted under, and the subject matter referenced, in this + License were drafted utilizing the terminology of the Berne Convention + for the Protection of Literary and Artistic Works (as amended on + September 28, 1979), the Rome Convention of 1961, the WIPO Copyright + Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 + and the Universal Copyright Convention (as revised on July 24, 1971). + These rights and subject matter take effect in the relevant + jurisdiction in which the License terms are sought to be enforced + according to the corresponding provisions of the implementation of + those treaty provisions in the applicable national law. If the + standard suite of rights granted under applicable copyright law + includes additional rights not granted under this License, such + additional rights are deemed to be included in the License; this + License is not intended to restrict the license of any rights under + applicable law. + + +Creative Commons Notice + + Creative Commons is not a party to this License, and makes no warranty + whatsoever in connection with the Work. Creative Commons will not be + liable to You or any party on any legal theory for any damages + whatsoever, including without limitation any general, special, + incidental or consequential damages arising in connection to this + license. Notwithstanding the foregoing two (2) sentences, if Creative + Commons has expressly identified itself as the Licensor hereunder, it + shall have all rights and obligations of Licensor. + + Except for the limited purpose of indicating to the public that the + Work is licensed under the CCPL, Creative Commons does not authorize + the use by either party of the trademark "Creative Commons" or any + related trademark or logo of Creative Commons without the prior + written consent of Creative Commons. Any permitted use will be in + compliance with Creative Commons' then-current trademark usage + guidelines, as may be published on its website or otherwise made + available upon request from time to time. For the avoidance of doubt, + this trademark restriction does not form part of this License. + + Creative Commons may be contacted at http://creativecommons.org/. + diff --git a/vendor/doctrine/orm/docs/README.md b/vendor/doctrine/orm/docs/README.md new file mode 100644 index 0000000..4a7ca34 --- /dev/null +++ b/vendor/doctrine/orm/docs/README.md @@ -0,0 +1,18 @@ +# Doctrine ORM Documentation + +## How to Generate: +Using Ubuntu 14.04 LTS: + +1. Run ./bin/install-dependencies.sh +2. Run ./bin/generate-docs.sh + +It will generate the documentation into the build directory of the checkout. + + +## Theme issues + +If you get a "Theme error", check if the `en/_theme` subdirectory is empty, +in which case you will need to run: + +1. git submodule init +2. git submodule update diff --git a/vendor/doctrine/orm/docs/bin/generate-docs.sh b/vendor/doctrine/orm/docs/bin/generate-docs.sh new file mode 100755 index 0000000..7d06d2a --- /dev/null +++ b/vendor/doctrine/orm/docs/bin/generate-docs.sh @@ -0,0 +1,10 @@ +#!/bin/bash +EXECPATH=`dirname $0` +cd $EXECPATH +cd .. + +rm build -Rf +sphinx-build en build + +sphinx-build -b latex en build/pdf +rubber --into build/pdf --pdf build/pdf/Doctrine2ORM.tex \ No newline at end of file diff --git a/vendor/doctrine/orm/docs/bin/install-dependencies.sh b/vendor/doctrine/orm/docs/bin/install-dependencies.sh new file mode 100644 index 0000000..9ee43bd --- /dev/null +++ b/vendor/doctrine/orm/docs/bin/install-dependencies.sh @@ -0,0 +1,2 @@ +#!/bin/bash +sudo apt-get update && sudo apt-get install -y python2.7 python-sphinx python-pygments \ No newline at end of file diff --git a/vendor/doctrine/orm/docs/en/Makefile b/vendor/doctrine/orm/docs/en/Makefile new file mode 100644 index 0000000..a6f6fce --- /dev/null +++ b/vendor/doctrine/orm/docs/en/Makefile @@ -0,0 +1,89 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Doctrine2ORM.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Doctrine2ORM.qhc" + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/vendor/doctrine/orm/docs/en/_exts/configurationblock.py b/vendor/doctrine/orm/docs/en/_exts/configurationblock.py new file mode 100644 index 0000000..36ca61f --- /dev/null +++ b/vendor/doctrine/orm/docs/en/_exts/configurationblock.py @@ -0,0 +1,93 @@ +#Copyright (c) 2010 Fabien Potencier +# +#Permission is hereby granted, free of charge, to any person obtaining a copy +#of this software and associated documentation files (the "Software"), to deal +#in the Software without restriction, including without limitation the rights +#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +#copies of the Software, and to permit persons to whom the Software is furnished +#to do so, subject to the following conditions: +# +#The above copyright notice and this permission notice shall be included in all +#copies or substantial portions of the Software. +# +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +#THE SOFTWARE. + +from docutils.parsers.rst import Directive, directives +from docutils import nodes +from string import upper + +class configurationblock(nodes.General, nodes.Element): + pass + +class ConfigurationBlock(Directive): + has_content = True + required_arguments = 0 + optional_arguments = 0 + final_argument_whitespace = True + option_spec = {} + formats = { + 'html': 'HTML', + 'xml': 'XML', + 'php': 'PHP', + 'yaml': 'YAML', + 'jinja': 'Twig', + 'html+jinja': 'Twig', + 'jinja+html': 'Twig', + 'php+html': 'PHP', + 'html+php': 'PHP', + 'ini': 'INI', + 'php-annotations': 'Annotations', + } + + def run(self): + env = self.state.document.settings.env + + node = nodes.Element() + node.document = self.state.document + self.state.nested_parse(self.content, self.content_offset, node) + + entries = [] + for i, child in enumerate(node): + if isinstance(child, nodes.literal_block): + # add a title (the language name) before each block + #targetid = "configuration-block-%d" % env.new_serialno('configuration-block') + #targetnode = nodes.target('', '', ids=[targetid]) + #targetnode.append(child) + + innernode = nodes.emphasis(self.formats[child['language']], self.formats[child['language']]) + + para = nodes.paragraph() + para += [innernode, child] + + entry = nodes.list_item('') + entry.append(para) + entries.append(entry) + + resultnode = configurationblock() + resultnode.append(nodes.bullet_list('', *entries)) + + return [resultnode] + +def visit_configurationblock_html(self, node): + self.body.append(self.starttag(node, 'div', CLASS='configuration-block')) + +def depart_configurationblock_html(self, node): + self.body.append('\n') + +def visit_configurationblock_latex(self, node): + pass + +def depart_configurationblock_latex(self, node): + pass + +def setup(app): + app.add_node(configurationblock, + html=(visit_configurationblock_html, depart_configurationblock_html), + latex=(visit_configurationblock_latex, depart_configurationblock_latex)) + app.add_directive('configuration-block', ConfigurationBlock) diff --git a/vendor/doctrine/orm/docs/en/conf.py b/vendor/doctrine/orm/docs/en/conf.py new file mode 100644 index 0000000..deafa6e --- /dev/null +++ b/vendor/doctrine/orm/docs/en/conf.py @@ -0,0 +1,201 @@ +# -*- coding: utf-8 -*- +# +# Doctrine 2 ORM documentation build configuration file, created by +# sphinx-quickstart on Fri Dec 3 18:10:24 2010. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os, datetime + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.append(os.path.abspath('_exts')) + +# -- General configuration ----------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['configurationblock'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Doctrine 2 ORM' +copyright = u'2010-%y, Doctrine Project Team'.format(datetime.date.today) + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '2' +# The full version, including alpha/beta/rc tags. +release = '2' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +language = 'en' + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +show_authors = True + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. Major themes that come with +# Sphinx are currently 'default' and 'sphinxdoc'. +html_theme = 'doctrine' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +html_theme_path = ['_theme'] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Doctrine2ORMdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'Doctrine2ORM.tex', u'Doctrine 2 ORM Documentation', + u'Doctrine Project Team', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True + +primary_domain = "dcorm" + +def linkcode_resolve(domain, info): + if domain == 'dcorm': + return 'http://' + return None diff --git a/vendor/doctrine/orm/docs/en/cookbook/advanced-field-value-conversion-using-custom-mapping-types.rst b/vendor/doctrine/orm/docs/en/cookbook/advanced-field-value-conversion-using-custom-mapping-types.rst new file mode 100644 index 0000000..f735d99 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/cookbook/advanced-field-value-conversion-using-custom-mapping-types.rst @@ -0,0 +1,256 @@ +Advanced field value conversion using custom mapping types +========================================================== + +.. sectionauthor:: Jan Sorgalla + +When creating entities, you sometimes have the need to transform field values +before they are saved to the database. In Doctrine you can use Custom Mapping +Types to solve this (see: :ref:`reference-basic-mapping-custom-mapping-types`). + +There are several ways to achieve this: converting the value inside the Type +class, converting the value on the database-level or a combination of both. + +This article describes the third way by implementing the MySQL specific column +type `Point `_. + +The ``Point`` type is part of the `Spatial extension `_ +of MySQL and enables you to store a single location in a coordinate space by +using x and y coordinates. You can use the Point type to store a +longitude/latitude pair to represent a geographic location. + +The entity +---------- + +We create a simple entity with a field ``$point`` which holds a value object +``Point`` representing the latitude and longitude of the position. + +The entity class: + +.. code-block:: php + + point = $point; + } + + /** + * @return \Geo\ValueObject\Point + */ + public function getPoint() + { + return $this->point; + } + + /** + * @param string $address + */ + public function setAddress($address) + { + $this->address = $address; + } + + /** + * @return string + */ + public function getAddress() + { + return $this->address; + } + } + +We use the custom type ``point`` in the ``@Column`` docblock annotation of the +``$point`` field. We will create this custom mapping type in the next chapter. + +The point class: + +.. code-block:: php + + latitude = $latitude; + $this->longitude = $longitude; + } + + /** + * @return float + */ + public function getLatitude() + { + return $this->latitude; + } + + /** + * @return float + */ + public function getLongitude() + { + return $this->longitude; + } + } + +The mapping type +---------------- + +Now we're going to create the ``point`` type and implement all required methods. + +.. code-block:: php + + getLongitude(), $value->getLatitude()); + } + + return $value; + } + + public function canRequireSQLConversion() + { + return true; + } + + public function convertToPHPValueSQL($sqlExpr, AbstractPlatform $platform) + { + return sprintf('AsText(%s)', $sqlExpr); + } + + public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform) + { + return sprintf('PointFromText(%s)', $sqlExpr); + } + } + +We do a 2-step conversion here. In the first step, we convert the ``Point`` +object into a string representation before saving to the database (in the +``convertToDatabaseValue`` method) and back into an object after fetching the +value from the database (in the ``convertToPHPValue`` method). + +The format of the string representation format is called +`Well-known text (WKT) `_. +The advantage of this format is, that it is both human readable and parsable by MySQL. + +Internally, MySQL stores geometry values in a binary format that is not +identical to the WKT format. So, we need to let MySQL transform the WKT +representation into its internal format. + +This is where the ``convertToPHPValueSQL`` and ``convertToDatabaseValueSQL`` +methods come into play. + +This methods wrap a sql expression (the WKT representation of the Point) into +MySQL functions `ST_PointFromText `_ +and `ST_AsText `_ +which convert WKT strings to and from the internal format of MySQL. + +.. note:: + + When using DQL queries, the ``convertToPHPValueSQL`` and + ``convertToDatabaseValueSQL`` methods only apply to identification variables + and path expressions in SELECT clauses. Expressions in WHERE clauses are + **not** wrapped! + + If you want to use Point values in WHERE clauses, you have to implement a + :doc:`user defined function ` for + ``PointFromText``. + +Example usage +------------- + +.. code-block:: php + + getConnection()->getDatabasePlatform()->registerDoctrineTypeMapping('point', 'point'); + + // Store a Location object + use Geo\Entity\Location; + use Geo\ValueObject\Point; + + $location = new Location(); + + $location->setAddress('1600 Amphitheatre Parkway, Mountain View, CA'); + $location->setPoint(new Point(37.4220761, -122.0845187)); + + $em->persist($location); + $em->flush(); + $em->clear(); + + // Fetch the Location object + $query = $em->createQuery("SELECT l FROM Geo\Entity\Location l WHERE l.address = '1600 Amphitheatre Parkway, Mountain View, CA'"); + $location = $query->getSingleResult(); + + /* @var Geo\ValueObject\Point */ + $point = $location->getPoint(); diff --git a/vendor/doctrine/orm/docs/en/cookbook/aggregate-fields.rst b/vendor/doctrine/orm/docs/en/cookbook/aggregate-fields.rst new file mode 100644 index 0000000..7e5a89d --- /dev/null +++ b/vendor/doctrine/orm/docs/en/cookbook/aggregate-fields.rst @@ -0,0 +1,376 @@ +Aggregate Fields +================ + +.. sectionauthor:: Benjamin Eberlei + +You will often come across the requirement to display aggregate +values of data that can be computed by using the MIN, MAX, COUNT or +SUM SQL functions. For any ORM this is a tricky issue +traditionally. Doctrine 2 offers several ways to get access to +these values and this article will describe all of them from +different perspectives. + +You will see that aggregate fields can become very explicit +features in your domain model and how this potentially complex +business rules can be easily tested. + +An example model +---------------- + +Say you want to model a bank account and all their entries. Entries +into the account can either be of positive or negative money +values. Each account has a credit limit and the account is never +allowed to have a balance below that value. + +For simplicity we live in a world were money is composed of +integers only. Also we omit the receiver/sender name, stated reason +for transfer and the execution date. These all would have to be +added on the ``Entry`` object. + +Our entities look like: + +.. code-block:: php + + no = $no; + $this->maxCredit = $maxCredit; + $this->entries = new \Doctrine\Common\Collections\ArrayCollection(); + } + } + + /** + * @Entity + */ + class Entry + { + /** @Id @GeneratedValue @Column(type="integer") */ + private $id; + + /** + * @ManyToOne(targetEntity="Account", inversedBy="entries") + */ + private $account; + + /** + * @Column(type="integer") + */ + private $amount; + + public function __construct($account, $amount) + { + $this->account = $account; + $this->amount = $amount; + // more stuff here, from/to whom, stated reason, execution date and such + } + + public function getAmount() + { + return $this->amount; + } + } + +Using DQL +--------- + +The Doctrine Query Language allows you to select for aggregate +values computed from fields of your Domain Model. You can select +the current balance of your account by calling: + +.. code-block:: php + + createQuery($dql) + ->setParameter(1, $myAccountId) + ->getSingleScalarResult(); + +The ``$em`` variable in this (and forthcoming) example holds the +Doctrine ``EntityManager``. We create a query for the SUM of all +amounts (negative amounts are withdraws) and retrieve them as a +single scalar result, essentially return only the first column of +the first row. + +This approach is simple and powerful, however it has a serious +drawback. We have to execute a specific query for the balance +whenever we need it. + +To implement a powerful domain model we would rather have access to +the balance from our ``Account`` entity during all times (even if +the Account was not persisted in the database before!). + +Also an additional requirement is the max credit per ``Account`` +rule. + +We cannot reliably enforce this rule in our ``Account`` entity with +the DQL retrieval of the balance. There are many different ways to +retrieve accounts. We cannot guarantee that we can execute the +aggregation query for all these use-cases, let alone that a +userland programmer checks this balance against newly added +entries. + +Using your Domain Model +----------------------- + +``Account`` and all the ``Entry`` instances are connected through a +collection, which means we can compute this value at runtime: + +.. code-block:: php + + entries as $entry) { + $balance += $entry->getAmount(); + } + return $balance; + } + } + +Now we can always call ``Account::getBalance()`` to access the +current account balance. + +To enforce the max credit rule we have to implement the "Aggregate +Root" pattern as described in Eric Evans book on Domain Driven +Design. Described with one sentence, an aggregate root controls the +instance creation, access and manipulation of its children. + +In our case we want to enforce that new entries can only added to +the ``Account`` by using a designated method. The ``Account`` is +the aggregate root of this relation. We can also enforce the +correctness of the bi-directional ``Account`` <-> ``Entry`` +relation with this method: + +.. code-block:: php + + assertAcceptEntryAllowed($amount); + + $e = new Entry($this, $amount); + $this->entries[] = $e; + return $e; + } + } + +Now look at the following test-code for our entities: + +.. code-block:: php + + assertEquals(0, $account->getBalance()); + + $account->addEntry(500); + $this->assertEquals(500, $account->getBalance()); + + $account->addEntry(-700); + $this->assertEquals(-200, $account->getBalance()); + } + + public function testExceedMaxLimit() + { + $account = new Account("123456", $maxCredit = 200); + + $this->setExpectedException("Exception"); + $account->addEntry(-1000); + } + } + +To enforce our rule we can now implement the assertion in +``Account::addEntry``: + +.. code-block:: php + + getBalance() + $amount; + $allowedMinimalBalance = ($this->maxCredit * -1); + if ($futureBalance < $allowedMinimalBalance) { + throw new Exception("Credit Limit exceeded, entry is not allowed!"); + } + } + } + +We haven't talked to the entity manager for persistence of our +account example before. You can call +``EntityManager::persist($account)`` and then +``EntityManager::flush()`` at any point to save the account to the +database. All the nested ``Entry`` objects are automatically +flushed to the database also. + +.. code-block:: php + + addEntry(500); + $account->addEntry(-200); + $em->persist($account); + $em->flush(); + +The current implementation has a considerable drawback. To get the +balance, we have to initialize the complete ``Account::$entries`` +collection, possibly a very large one. This can considerably hurt +the performance of your application. + +Using an Aggregate Field +------------------------ + +To overcome the previously mentioned issue (initializing the whole +entries collection) we want to add an aggregate field called +"balance" on the Account and adjust the code in +``Account::getBalance()`` and ``Account:addEntry()``: + +.. code-block:: php + + balance; + } + + public function addEntry($amount) + { + $this->assertAcceptEntryAllowed($amount); + + $e = new Entry($this, $amount); + $this->entries[] = $e; + $this->balance += $amount; + return $e; + } + } + +This is a very simple change, but all the tests still pass. Our +account entities return the correct balance. Now calling the +``Account::getBalance()`` method will not occur the overhead of +loading all entries anymore. Adding a new Entry to the +``Account::$entities`` will also not initialize the collection +internally. + +Adding a new entry is therefore very performant and explicitly +hooked into the domain model. It will only update the account with +the current balance and insert the new entry into the database. + +Tackling Race Conditions with Aggregate Fields +---------------------------------------------- + +Whenever you denormalize your database schema race-conditions can +potentially lead to inconsistent state. See this example: + +.. code-block:: php + + find('Bank\Entities\Account', $accId); + + // request 2 account + $account2 = $em->find('Bank\Entities\Account', $accId); + + $account1->addEntry(-200); + $account2->addEntry(-200); + + // now request 1 and 2 both flush the changes. + +The aggregate field ``Account::$balance`` is now -200, however the +SUM over all entries amounts yields -400. A violation of our max +credit rule. + +You can use both optimistic or pessimistic locking to safe-guard +your aggregate fields against this kind of race-conditions. Reading +Eric Evans DDD carefully he mentions that the "Aggregate Root" +(Account in our example) needs a locking mechanism. + +Optimistic locking is as easy as adding a version column: + +.. code-block:: php + + find('Bank\Entities\Account', $accId, LockMode::PESSIMISTIC_READ); + +Keeping Updates and Deletes in Sync +----------------------------------- + +The example shown in this article does not allow changes to the +value in ``Entry``, which considerably simplifies the effort to +keep ``Account::$balance`` in sync. If your use-case allows fields +to be updated or related entities to be removed you have to +encapsulate this logic in your "Aggregate Root" entity and adjust +the aggregate field accordingly. + +Conclusion +---------- + +This article described how to obtain aggregate values using DQL or +your domain model. It showed how you can easily add an aggregate +field that offers serious performance benefits over iterating all +the related objects that make up an aggregate value. Finally I +showed how you can ensure that your aggregate fields do not get out +of sync due to race-conditions and concurrent access. + + diff --git a/vendor/doctrine/orm/docs/en/cookbook/custom-mapping-types.rst b/vendor/doctrine/orm/docs/en/cookbook/custom-mapping-types.rst new file mode 100644 index 0000000..d9e3856 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/cookbook/custom-mapping-types.rst @@ -0,0 +1,101 @@ +Custom Mapping Types +==================== + +Doctrine allows you to create new mapping types. This can come in +handy when you're missing a specific mapping type or when you want +to replace the existing implementation of a mapping type. + +In order to create a new mapping type you need to subclass +``Doctrine\DBAL\Types\Type`` and implement/override the methods as +you wish. Here is an example skeleton of such a custom type class: + +.. code-block:: php + + getConnection(); + $conn->getDatabasePlatform()->registerDoctrineTypeMapping('db_mytype', 'mytype'); + +When registering the custom types in the configuration you specify a unique +name for the mapping type and map that to the corresponding fully qualified +class name. Now the new type can be used when mapping columns: + +.. code-block:: php + + + +This recipe will show you a simple example of how you can use +Doctrine 2 to persist an implementation of the +`Decorator Pattern `_ + +Component +--------- + +The ``Component`` class needs to be persisted, so it's going to +be an ``Entity``. As the top of the inheritance hierarchy, it's going +to have to define the persistent inheritance. For this example, we +will use Single Table Inheritance, but Class Table Inheritance +would work as well. In the discriminator map, we will define two +concrete subclasses, ``ConcreteComponent`` and ``ConcreteDecorator``. + +.. code-block:: php + + id; + } + + /** + * Set name + * @param string $name + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * Get name + * @return string $name + */ + public function getName() + { + return $this->name; + } + + } + +ConcreteComponent +----------------- + +The ``ConcreteComponent`` class is pretty simple and doesn't do much +more than extend the abstract ``Component`` class (only for the +purpose of keeping this example simple). + +.. code-block:: php + + setDecorates($c); + } + + /** + * (non-PHPdoc) + * @see Test.Component::getName() + */ + public function getName() + { + return 'Decorated ' . $this->getDecorates()->getName(); + } + + /** + * the component being decorated + * @return Component + */ + protected function getDecorates() + { + return $this->decorates; + } + + /** + * sets the component being decorated + * @param Component $c + */ + protected function setDecorates(Component $c) + { + $this->decorates = $c; + } + + } + +All operations on the ``Decorator`` (i.e. persist, remove, etc) will +cascade from the ``Decorator`` to the ``Component``. This means that +when we persist a ``Decorator``, Doctrine will take care of +persisting the chain of decorated objects for us. A ``Decorator`` can +be treated exactly as a ``Component`` when it comes time to +persisting it. + +The ``Decorator's`` constructor accepts an instance of a +``Component``, as defined by the ``Decorator`` pattern. The +setDecorates/getDecorates methods have been defined as protected to +hide the fact that a ``Decorator`` is decorating a ``Component`` and +keeps the ``Component`` interface and the ``Decorator`` interface +identical. + +To illustrate the intended result of the ``Decorator`` pattern, the +getName() method has been overridden to append a string to the +``Component's`` getName() method. + +ConcreteDecorator +----------------- + +The final class required to complete a simple implementation of the +Decorator pattern is the ``ConcreteDecorator``. In order to further +illustrate how the ``Decorator`` can alter data as it moves through +the chain of decoration, a new field, "special", has been added to +this class. The getName() has been overridden and appends the value +of the getSpecial() method to its return value. + +.. code-block:: php + + special = $special; + } + + /** + * Get special + * @return string $special + */ + public function getSpecial() + { + return $this->special; + } + + /** + * (non-PHPdoc) + * @see Test.Component::getName() + */ + public function getName() + { + return '[' . $this->getSpecial() + . '] ' . parent::getName(); + } + + } + +Examples +-------- + +Here is an example of how to persist and retrieve your decorated +objects + +.. code-block:: php + + setName('Test Component 1'); + $em->persist($c); // assigned unique ID = 1 + + // create a new concrete decorator + $c = new ConcreteComponent(); + $c->setName('Test Component 2'); + + $d = new ConcreteDecorator($c); + $d->setSpecial('Really'); + $em->persist($d); + // assigns c as unique ID = 2, and d as unique ID = 3 + + $em->flush(); + + $c = $em->find('Test\Component', 1); + $d = $em->find('Test\Component', 3); + + echo get_class($c); + // prints: Test\Component\ConcreteComponent + + echo $c->getName(); + // prints: Test Component 1 + + echo get_class($d) + // prints: Test\Component\ConcreteDecorator + + echo $d->getName(); + // prints: [Really] Decorated Test Component 2 + diff --git a/vendor/doctrine/orm/docs/en/cookbook/dql-custom-walkers.rst b/vendor/doctrine/orm/docs/en/cookbook/dql-custom-walkers.rst new file mode 100644 index 0000000..e840126 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/cookbook/dql-custom-walkers.rst @@ -0,0 +1,217 @@ +Extending DQL in Doctrine 2: Custom AST Walkers +=============================================== + +.. sectionauthor:: Benjamin Eberlei + +The Doctrine Query Language (DQL) is a proprietary sql-dialect that +substitutes tables and columns for Entity names and their fields. +Using DQL you write a query against the database using your +entities. With the help of the metadata you can write very concise, +compact and powerful queries that are then translated into SQL by +the Doctrine ORM. + +In Doctrine 1 the DQL language was not implemented using a real +parser. This made modifications of the DQL by the user impossible. +Doctrine 2 in contrast has a real parser for the DQL language, +which transforms the DQL statement into an +`Abstract Syntax Tree `_ +and generates the appropriate SQL statement for it. Since this +process is deterministic Doctrine heavily caches the SQL that is +generated from any given DQL query, which reduces the performance +overhead of the parsing process to zero. + +You can modify the Abstract syntax tree by hooking into DQL parsing +process by adding a Custom Tree Walker. A walker is an interface +that walks each node of the Abstract syntax tree, thereby +generating the SQL statement. + +There are two types of custom tree walkers that you can hook into +the DQL parser: + + +- An output walker. This one actually generates the SQL, and there + is only ever one of them. We implemented the default SqlWalker + implementation for it. +- A tree walker. There can be many tree walkers, they cannot + generate the sql, however they can modify the AST before its + rendered to sql. + +Now this is all awfully technical, so let me come to some use-cases +fast to keep you motivated. Using walker implementation you can for +example: + + +- Modify the AST to generate a Count Query to be used with a + paginator for any given DQL query. +- Modify the Output Walker to generate vendor-specific SQL + (instead of ANSI). +- Modify the AST to add additional where clauses for specific + entities (example ACL, country-specific content...) +- Modify the Output walker to pretty print the SQL for debugging + purposes. + +In this cookbook-entry I will show examples on the first two +points. There are probably much more use-cases. + +Generic count query for pagination +---------------------------------- + +Say you have a blog and posts all with one category and one author. +A query for the front-page or any archive page might look something +like: + +.. code-block:: sql + + SELECT p, c, a FROM BlogPost p JOIN p.category c JOIN p.author a WHERE ... + +Now in this query the blog post is the root entity, meaning its the +one that is hydrated directly from the query and returned as an +array of blog posts. In contrast the comment and author are loaded +for deeper use in the object tree. + +A pagination for this query would want to approximate the number of +posts that match the WHERE clause of this query to be able to +predict the number of pages to show to the user. A draft of the DQL +query for pagination would look like: + +.. code-block:: sql + + SELECT count(DISTINCT p.id) FROM BlogPost p JOIN p.category c JOIN p.author a WHERE ... + +Now you could go and write each of these queries by hand, or you +can use a tree walker to modify the AST for you. Lets see how the +API would look for this use-case: + +.. code-block:: php + + createQuery($dql); + $query->setFirstResult( ($pageNum-1) * 20)->setMaxResults(20); + + $totalResults = Paginate::count($query); + $results = $query->getResult(); + +The ``Paginate::count(Query $query)`` looks like: + +.. code-block:: php + + setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('DoctrineExtensions\Paginate\CountSqlWalker')); + $countQuery->setFirstResult(null)->setMaxResults(null); + + return $countQuery->getSingleScalarResult(); + } + } + +It clones the query, resets the limit clause first and max results +and registers the ``CountSqlWalker`` custom tree walker which +will modify the AST to execute a count query. The walkers +implementation is: + +.. code-block:: php + + _getQueryComponents() as $dqlAlias => $qComp) { + if ($qComp['parent'] === null && $qComp['nestingLevel'] == 0) { + $parent = $qComp; + $parentName = $dqlAlias; + break; + } + } + + $pathExpression = new PathExpression( + PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $parentName, + $parent['metadata']->getSingleIdentifierFieldName() + ); + $pathExpression->type = PathExpression::TYPE_STATE_FIELD; + + $AST->selectClause->selectExpressions = array( + new SelectExpression( + new AggregateExpression('count', $pathExpression, true), null + ) + ); + } + } + +This will delete any given select expressions and replace them with +a distinct count query for the root entities primary key. This will +only work if your entity has only one identifier field (composite +keys won't work). + +Modify the Output Walker to generate Vendor specific SQL +-------------------------------------------------------- + +Most RMDBS have vendor-specific features for optimizing select +query execution plans. You can write your own output walker to +introduce certain keywords using the Query Hint API. A query hint +can be set via ``Query::setHint($name, $value)`` as shown in the +previous example with the ``HINT_CUSTOM_TREE_WALKERS`` query hint. + +We will implement a custom Output Walker that allows to specify the +SQL\_NO\_CACHE query hint. + +.. code-block:: php + + createQuery($dql); + $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'DoctrineExtensions\Query\MysqlWalker'); + $query->setHint("mysqlWalker.sqlNoCache", true); + $results = $query->getResult(); + +Our ``MysqlWalker`` will extend the default ``SqlWalker``. We will +modify the generation of the SELECT clause, adding the +SQL\_NO\_CACHE on those queries that need it: + +.. code-block:: php + + getQuery()->getHint('mysqlWalker.sqlNoCache') === true) { + if ($selectClause->isDistinct) { + $sql = str_replace('SELECT DISTINCT', 'SELECT DISTINCT SQL_NO_CACHE', $sql); + } else { + $sql = str_replace('SELECT', 'SELECT SQL_NO_CACHE', $sql); + } + } + + return $sql; + } + } + +Writing extensions to the Output Walker requires a very deep +understanding of the DQL Parser and Walkers, but may offer your +huge benefits with using vendor specific features. This would still +allow you write DQL queries instead of NativeQueries to make use of +vendor specific features. + diff --git a/vendor/doctrine/orm/docs/en/cookbook/dql-user-defined-functions.rst b/vendor/doctrine/orm/docs/en/cookbook/dql-user-defined-functions.rst new file mode 100644 index 0000000..5c9b3e5 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/cookbook/dql-user-defined-functions.rst @@ -0,0 +1,251 @@ +DQL User Defined Functions +========================== + +.. sectionauthor:: Benjamin Eberlei + +By default DQL supports a limited subset of all the vendor-specific +SQL functions common between all the vendors. However in many cases +once you have decided on a specific database vendor, you will never +change it during the life of your project. This decision for a +specific vendor potentially allows you to make use of powerful SQL +features that are unique to the vendor. + +It is worth to mention that Doctrine 2 also allows you to handwrite +your SQL instead of extending the DQL parser. Extending DQL is sort of an +advanced extension point. You can map arbitrary SQL to your objects +and gain access to vendor specific functionalities using the +``EntityManager#createNativeQuery()`` API as described in +the :doc:`Native Query <../reference/native-sql>` chapter. + + +The DQL Parser has hooks to register functions that can then be +used in your DQL queries and transformed into SQL, allowing to +extend Doctrines Query capabilities to the vendors strength. This +post explains the User-Defined Functions API (UDF) of the Dql +Parser and shows some examples to give you some hints how you would +extend DQL. + +There are three types of functions in DQL, those that return a +numerical value, those that return a string and those that return a +Date. Your custom method has to be registered as either one of +those. The return type information is used by the DQL parser to +check possible syntax errors during the parsing process, for +example using a string function return value in a math expression. + +Registering your own DQL functions +---------------------------------- + +You can register your functions adding them to the ORM +configuration: + +.. code-block:: php + + addCustomStringFunction($name, $class); + $config->addCustomNumericFunction($name, $class); + $config->addCustomDatetimeFunction($name, $class); + + $em = EntityManager::create($dbParams, $config); + +The ``$name`` is the name the function will be referred to in the +DQL query. ``$class`` is a string of a class-name which has to +extend ``Doctrine\ORM\Query\Node\FunctionNode``. This is a class +that offers all the necessary API and methods to implement a UDF. + +Instead of providing the function class name, you can also provide +a callable that returns the function object: + +.. code-block:: php + + addCustomStringFunction($name, function () { + return new MyCustomFunction(); + }); + +In this post we will implement some MySql specific Date calculation +methods, which are quite handy in my opinion: + +Date Diff +--------- + +`Mysql's DateDiff function `_ +takes two dates as argument and calculates the difference in days +with ``date1-date2``. + +The DQL parser is a top-down recursive descent parser to generate +the Abstract-Syntax Tree (AST) and uses a TreeWalker approach to +generate the appropriate SQL from the AST. This makes reading the +Parser/TreeWalker code manageable in a finite amount of time. + +The ``FunctionNode`` class I referred to earlier requires you to +implement two methods, one for the parsing process (obviously) +called ``parse`` and one for the TreeWalker process called +``getSql()``. I show you the code for the DateDiff method and +discuss it step by step: + +.. code-block:: php + + match(Lexer::T_IDENTIFIER); // (2) + $parser->match(Lexer::T_OPEN_PARENTHESIS); // (3) + $this->firstDateExpression = $parser->ArithmeticPrimary(); // (4) + $parser->match(Lexer::T_COMMA); // (5) + $this->secondDateExpression = $parser->ArithmeticPrimary(); // (6) + $parser->match(Lexer::T_CLOSE_PARENTHESIS); // (3) + } + + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + return 'DATEDIFF(' . + $this->firstDateExpression->dispatch($sqlWalker) . ', ' . + $this->secondDateExpression->dispatch($sqlWalker) . + ')'; // (7) + } + } + +The Parsing process of the DATEDIFF function is going to find two +expressions the date1 and the date2 values, whose AST Node +representations will be saved in the variables of the DateDiff +FunctionNode instance at (1). + +The parse() method has to cut the function call "DATEDIFF" and its +argument into pieces. Since the parser detects the function using a +lookahead the T\_IDENTIFIER of the function name has to be taken +from the stack (2), followed by a detection of the arguments in +(4)-(6). The opening and closing parenthesis have to be detected +also. This happens during the Parsing process and leads to the +generation of a DateDiff FunctionNode somewhere in the AST of the +dql statement. + +The ``ArithmeticPrimary`` method call is the most common +denominator of valid EBNF tokens taken from the +`DQL EBNF grammar `_ +that matches our requirements for valid input into the DateDiff Dql +function. Picking the right tokens for your methods is a tricky +business, but the EBNF grammar is pretty helpful finding it, as is +looking at the Parser source code. + +Now in the TreeWalker process we have to pick up this node and +generate SQL from it, which apparently is quite easy looking at the +code in (7). Since we don't know which type of AST Node the first +and second Date expression are we are just dispatching them back to +the SQL Walker to generate SQL from and then wrap our DATEDIFF +function call around this output. + +Now registering this DateDiff FunctionNode with the ORM using: + +.. code-block:: php + + addCustomStringFunction('DATEDIFF', 'DoctrineExtensions\Query\MySql\DateDiff'); + +We can do fancy stuff like: + +.. code-block:: sql + + SELECT p FROM DoctrineExtensions\Query\BlogPost p WHERE DATEDIFF(CURRENT_TIME(), p.created) < 7 + +Date Add +-------- + +Often useful it the ability to do some simple date calculations in +your DQL query using +`MySql's DATE_ADD function `_. + +I'll skip the blah and show the code for this function: + +.. code-block:: php + + match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->firstDateExpression = $parser->ArithmeticPrimary(); + + $parser->match(Lexer::T_COMMA); + $parser->match(Lexer::T_IDENTIFIER); + + $this->intervalExpression = $parser->ArithmeticPrimary(); + + $parser->match(Lexer::T_IDENTIFIER); + + /* @var $lexer Lexer */ + $lexer = $parser->getLexer(); + $this->unit = $lexer->token['value']; + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } + + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + return 'DATE_ADD(' . + $this->firstDateExpression->dispatch($sqlWalker) . ', INTERVAL ' . + $this->intervalExpression->dispatch($sqlWalker) . ' ' . $this->unit . + ')'; + } + } + +The only difference compared to the DATEDIFF here is, we +additionally need the ``Lexer`` to access the value of the +``T_IDENTIFIER`` token for the Date Interval unit, for example the +MONTH in: + +.. code-block:: sql + + SELECT p FROM DoctrineExtensions\Query\BlogPost p WHERE DATE_ADD(CURRENT_TIME(), INTERVAL 4 MONTH) > p.created + +The above method now only supports the specification using +``INTERVAL``, to also allow a real date in DATE\_ADD we need to add +some decision logic to the parsing process (makes up for a nice +exercise). + +Now as you see, the Parsing process doesn't catch all the possible +SQL errors, here we don't match for all the valid inputs for the +interval unit. However where necessary we rely on the database +vendors SQL parser to show us further errors in the parsing +process, for example if the Unit would not be one of the supported +values by MySql. + +Conclusion +---------- + +Now that you all know how you can implement vendor specific SQL +functionalities in DQL, we would be excited to see user extensions +that add vendor specific function packages, for example more math +functions, XML + GIS Support, Hashing functions and so on. + +For 2.0 we will come with the current set of functions, however for +a future version we will re-evaluate if we can abstract even more +vendor sql functions and extend the DQL languages scope. + +Code for this Extension to DQL and other Doctrine Extensions can be +found +`in the GitHub DoctrineExtensions repository `_. + + diff --git a/vendor/doctrine/orm/docs/en/cookbook/entities-in-session.rst b/vendor/doctrine/orm/docs/en/cookbook/entities-in-session.rst new file mode 100644 index 0000000..664cff5 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/cookbook/entities-in-session.rst @@ -0,0 +1,68 @@ +Entities in the Session +======================= + +There are several use-cases to save entities in the session, for example: + +1. User object +2. Multi-step forms + +To achieve this with Doctrine you have to pay attention to some details to get +this working. + +Merging entity into an EntityManager +------------------------------------ + +In Doctrine an entity objects has to be "managed" by an EntityManager to be +updateable. Entities saved into the session are not managed in the next request +anymore. This means that you have to register these entities with an +EntityManager again if you want to change them or use them as part of +references between other entities. You can achieve this by calling +``EntityManager#merge()``. + +For a representative User object the code to get turn an instance from +the session into a managed Doctrine object looks like this: + +.. code-block:: php + + merge($user); + } + +.. note:: + + A frequent mistake is not to get the merged user object from the return + value of ``EntityManager#merge()``. The entity object passed to merge is + not necessarily the same object that is returned from the method. + +Serializing entity into the session +----------------------------------- + +Entities that are serialized into the session normally contain references to +other entities as well. Think of the user entity has a reference to his +articles, groups, photos or many other different entities. If you serialize +this object into the session then you don't want to serialize the related +entities as well. This is why you should call ``EntityManager#detach()`` on this +object or implement the __sleep() magic method on your entity. + +.. code-block:: php + + find("User", 1); + $em->detach($user); + $_SESSION['user'] = $user; + +.. note:: + + When you called detach on your objects they get "unmanaged" with that + entity manager. This means you cannot use them as part of write operations + during ``EntityManager#flush()`` anymore in this request. + diff --git a/vendor/doctrine/orm/docs/en/cookbook/implementing-arrayaccess-for-domain-objects.rst b/vendor/doctrine/orm/docs/en/cookbook/implementing-arrayaccess-for-domain-objects.rst new file mode 100644 index 0000000..4eb2b71 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/cookbook/implementing-arrayaccess-for-domain-objects.rst @@ -0,0 +1,112 @@ +Implementing ArrayAccess for Domain Objects +=========================================== + +.. sectionauthor:: Roman Borschel (roman@code-factory.org) + +This recipe will show you how to implement ArrayAccess for your +domain objects in order to allow more uniform access, for example +in templates. In these examples we will implement ArrayAccess on a +`Layer Supertype `_ +for all our domain objects. + +Option 1 +-------- + +In this implementation we will make use of PHPs highly dynamic +nature to dynamically access properties of a subtype in a supertype +at runtime. Note that this implementation has 2 main caveats: + + +- It will not work with private fields +- It will not go through any getters/setters + +.. code-block:: php + + $offset); + } + + public function offsetSet($offset, $value) { + $this->$offset = $value; + } + + public function offsetGet($offset) { + return $this->$offset; + } + + public function offsetUnset($offset) { + $this->$offset = null; + } + } + +Option 2 +-------- + +In this implementation we will dynamically invoke getters/setters. +Again we use PHPs dynamic nature to invoke methods on a subtype +from a supertype at runtime. This implementation has the following +caveats: + + +- It relies on a naming convention +- The semantics of offsetExists can differ +- offsetUnset will not work with typehinted setters + +.. code-block:: php + + {"get$offset"}(); + return $value !== null; + } + + public function offsetSet($offset, $value) { + $this->{"set$offset"}($value); + } + + public function offsetGet($offset) { + return $this->{"get$offset"}(); + } + + public function offsetUnset($offset) { + $this->{"set$offset"}(null); + } + } + +Read-only +--------- + +You can slightly tweak option 1 or option 2 in order to make array +access read-only. This will also circumvent some of the caveats of +each option. Simply make offsetSet and offsetUnset throw an +exception (i.e. BadMethodCallException). + +.. code-block:: php + + `_ +for all our domain objects. + +Implementing NotifyPropertyChanged +---------------------------------- + +The NOTIFY policy is based on the assumption that the entities +notify interested listeners of changes to their properties. For +that purpose, a class that wants to use this policy needs to +implement the ``NotifyPropertyChanged`` interface from the +``Doctrine\Common`` namespace. + +.. code-block:: php + + listeners[] = $listener; + } + + /** Notifies listeners of a change. */ + protected function onPropertyChanged($propName, $oldValue, $newValue) { + if ($this->listeners) { + foreach ($this->listeners as $listener) { + $listener->propertyChanged($this, $propName, $oldValue, $newValue); + } + } + } + } + +Then, in each property setter of concrete, derived domain classes, +you need to invoke onPropertyChanged as follows to notify +listeners: + +.. code-block:: php + + data) { // check: is it actually modified? + $this->onPropertyChanged('data', $this->data, $data); + $this->data = $data; + } + } + } + +The check whether the new value is different from the old one is +not mandatory but recommended. That way you can avoid unnecessary +updates and also have full control over when you consider a +property changed. + + diff --git a/vendor/doctrine/orm/docs/en/cookbook/implementing-wakeup-or-clone.rst b/vendor/doctrine/orm/docs/en/cookbook/implementing-wakeup-or-clone.rst new file mode 100644 index 0000000..1ae1775 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/cookbook/implementing-wakeup-or-clone.rst @@ -0,0 +1,78 @@ +Implementing Wakeup or Clone +============================ + +.. sectionauthor:: Roman Borschel (roman@code-factory.org) + +As explained in the +`restrictions for entity classes in the manual `_, +it is usually not allowed for an entity to implement ``__wakeup`` +or ``__clone``, because Doctrine makes special use of them. +However, it is quite easy to make use of these methods in a safe +way by guarding the custom wakeup or clone code with an entity +identity check, as demonstrated in the following sections. + +Safely implementing __wakeup +---------------------------- + +To safely implement ``__wakeup``, simply enclose your +implementation code in an identity check as follows: + +.. code-block:: php + + id) { + // ... Your code here as normal ... + } + // otherwise do nothing, do NOT throw an exception! + } + + //... + } + +Safely implementing __clone +--------------------------- + +Safely implementing ``__clone`` is pretty much the same: + +.. code-block:: php + + id) { + // ... Your code here as normal ... + } + // otherwise do nothing, do NOT throw an exception! + } + + //... + } + +Summary +------- + +As you have seen, it is quite easy to safely make use of +``__wakeup`` and ``__clone`` in your entities without adding any +really Doctrine-specific or Doctrine-dependant code. + +These implementations are possible and safe because when Doctrine +invokes these methods, the entities never have an identity (yet). +Furthermore, it is possibly a good idea to check for the identity +in your code anyway, since it's rarely the case that you want to +unserialize or clone an entity with no identity. + + diff --git a/vendor/doctrine/orm/docs/en/cookbook/mysql-enums.rst b/vendor/doctrine/orm/docs/en/cookbook/mysql-enums.rst new file mode 100644 index 0000000..1765ecc --- /dev/null +++ b/vendor/doctrine/orm/docs/en/cookbook/mysql-enums.rst @@ -0,0 +1,199 @@ +Mysql Enums +=========== + +The type system of Doctrine 2 consists of flyweights, which means there is only +one instance of any given type. Additionally types do not contain state. Both +assumptions make it rather complicated to work with the Enum Type of MySQL that +is used quite a lot by developers. + +When using Enums with a non-tweaked Doctrine 2 application you will get +errors from the Schema-Tool commands due to the unknown database type "enum". +By default Doctrine does not map the MySQL enum type to a Doctrine type. +This is because Enums contain state (their allowed values) and Doctrine +types don't. + +This cookbook entry shows two possible solutions to work with MySQL enums. +But first a word of warning. The MySQL Enum type has considerable downsides: + +- Adding new values requires to rebuild the whole table, which can take hours + depending on the size. +- Enums are ordered in the way the values are specified, not in their "natural" order. +- Enums validation mechanism for allowed values is not necessarily good, + specifying invalid values leads to an empty enum for the default MySQL error + settings. You can easily replicate the "allow only some values" requirement + in your Doctrine entities. + +Solution 1: Mapping to Varchars +------------------------------- + +You can map ENUMs to varchars. You can register MySQL ENUMs to map to Doctrine +varchars. This way Doctrine always resolves ENUMs to Doctrine varchars. It +will even detect this match correctly when using SchemaTool update commands. + +.. code-block:: php + + getConnection(); + $conn->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string'); + +In this case you have to ensure that each varchar field that is an enum in the +database only gets passed the allowed values. You can easily enforce this in your +entities: + +.. code-block:: php + + status = $status; + } + } + +If you want to actively create enums through the Doctrine Schema-Tool by using +the **columnDefinition** attribute. + +.. code-block:: php + + values); + + return "ENUM(".implode(", ", $values).")"; + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return $value; + } + + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + if (!in_array($value, $this->values)) { + throw new \InvalidArgumentException("Invalid '".$this->name."' value."); + } + return $value; + } + + public function getName() + { + return $this->name; + } + + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } + } + +With this base class you can define an enum as easily as: + +.. code-block:: php + + addResolveTargetEntity('Acme\\InvoiceModule\\Model\\InvoiceSubjectInterface', 'Acme\\CustomerModule\\Entity\\Customer', array()); + + // Add the ResolveTargetEntityListener + $evm->addEventListener(Doctrine\ORM\Events::loadClassMetadata, $rtel); + + $em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config, $evm); + +Final Thoughts +-------------- + +With the ``ResolveTargetEntityListener``, we are able to decouple our +bundles, keeping them usable by themselves, but still being able to +define relationships between different objects. By using this method, +I've found my bundles end up being easier to maintain independently. + + diff --git a/vendor/doctrine/orm/docs/en/cookbook/sql-table-prefixes.rst b/vendor/doctrine/orm/docs/en/cookbook/sql-table-prefixes.rst new file mode 100644 index 0000000..5ea5879 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/cookbook/sql-table-prefixes.rst @@ -0,0 +1,86 @@ +SQL-Table Prefixes +================== + +This recipe is intended as an example of implementing a +loadClassMetadata listener to provide a Table Prefix option for +your application. The method used below is not a hack, but fully +integrates into the Doctrine system, all SQL generated will include +the appropriate table prefix. + +In most circumstances it is desirable to separate different +applications into individual databases, but in certain cases, it +may be beneficial to have a table prefix for your Entities to +separate them from other vendor products in the same database. + +Implementing the listener +------------------------- + +The listener in this example has been set up with the +DoctrineExtensions namespace. You create this file in your +library/DoctrineExtensions directory, but will need to set up +appropriate autoloaders. + +.. code-block:: php + + prefix = (string) $prefix; + } + + public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) + { + $classMetadata = $eventArgs->getClassMetadata(); + + if (!$classMetadata->isInheritanceTypeSingleTable() || $classMetadata->getName() === $classMetadata->rootEntityName) { + $classMetadata->setPrimaryTable([ + 'name' => $this->prefix . $classMetadata->getTableName() + ]); + } + + foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) { + if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY && $mapping['isOwningSide']) { + $mappedTableName = $mapping['joinTable']['name']; + $classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName; + } + } + } + + } + +Telling the EntityManager about our listener +-------------------------------------------- + +A listener of this type must be set up before the EntityManager has +been initialised, otherwise an Entity might be created or cached +before the prefix has been set. + +.. note:: + + If you set this listener up, be aware that you will need + to clear your caches and drop then recreate your database schema. + + +.. code-block:: php + + addEventListener(\Doctrine\ORM\Events::loadClassMetadata, $tablePrefix); + + $em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config, $evm); + + diff --git a/vendor/doctrine/orm/docs/en/cookbook/strategy-cookbook-introduction.rst b/vendor/doctrine/orm/docs/en/cookbook/strategy-cookbook-introduction.rst new file mode 100644 index 0000000..b434a9d --- /dev/null +++ b/vendor/doctrine/orm/docs/en/cookbook/strategy-cookbook-introduction.rst @@ -0,0 +1,254 @@ +Strategy-Pattern +================ + +This recipe will give you a short introduction on how to design +similar entities without using expensive (i.e. slow) inheritance +but with not more than *the well-known strategy pattern* event +listeners + +Scenario / Problem +------------------ + +Given a Content-Management-System, we probably want to add / edit +some so-called "blocks" and "panels". What are they for? + + +- A block might be a registration form, some text content, a table + with information. A good example might also be a small calendar. +- A panel is by definition a block that can itself contain blocks. + A good example for a panel might be a sidebar box: You could easily + add a small calendar into it. + +So, in this scenario, when building your CMS, you will surely add +lots of blocks and panels to your pages and you will find yourself +highly uncomfortable because of the following: + + +- Every existing page needs to know about the panels it contains - + therefore, you'll have an association to your panels. But if you've + got several types of panels - what do you do? Add an association to + every panel-type? This wouldn't be flexible. You might be tempted + to add an AbstractPanelEntity and an AbstractBlockEntity that use + class inheritance. Your page could then only confer to the + AbstractPanelType and Doctrine 2 would do the rest for you, i.e. + load the right entities. But - you'll for sure have lots of panels + and blocks, and even worse, you'd have to edit the discriminator + map *manually* every time you or another developer implements a new + block / entity. This would tear down any effort of modular + programming. + +Therefore, we need something that's far more flexible. + +Solution +-------- + +The solution itself is pretty easy. We will have one base class +that will be loaded via the page and that has specific behaviour - +a Block class might render the front-end and even the backend, for +example. Now, every block that you'll write might look different or +need different data - therefore, we'll offer an API to these +methods but internally, we use a strategy that exactly knows what +to do. + +First of all, we need to make sure that we have an interface that +contains every needed action. Such actions would be rendering the +front-end or the backend, solving dependencies (blocks that are +supposed to be placed in the sidebar could refuse to be placed in +the middle of your page, for example). + +Such an interface could look like this: + + +.. code-block:: php + + blockStrategy. Will not be persisted by Doctrine 2. + * + * @var BlockStrategyInterface + */ + protected $strategyInstance; + + /** + * Returns the strategy that is used for this blockitem. + * + * The strategy itself defines how this block can be rendered etc. + * + * @return string + */ + public function getStrategyClassName() { + return $this->strategyClassName; + } + + /** + * Returns the instantiated strategy + * + * @return BlockStrategyInterface + */ + public function getStrategyInstance() { + return $this->strategyInstance; + } + + /** + * Sets the strategy this block / panel should work as. Make sure that you've used + * this method before persisting the block! + * + * @param BlockStrategyInterface $strategy + */ + public function setStrategy(BlockStrategyInterface $strategy) { + $this->strategyInstance = $strategy; + $this->strategyClassName = get_class($strategy); + $strategy->setBlockEntity($this); + } + +Now, the important point is that $strategyClassName is a Doctrine 2 +field, i.e. Doctrine will persist this value. This is only the +class name of your strategy and not an instance! + +Finishing your strategy pattern, we hook into the Doctrine postLoad +event and check whether a block has been loaded. If so, you will +initialize it - i.e. get the strategies classname, create an +instance of it and set it via setStrategyBlock(). + +This might look like this: + +.. code-block:: php + + view = $view; + } + + public function getSubscribedEvents() { + return array(ORM\Events::postLoad); + } + + public function postLoad(ORM\Event\LifecycleEventArgs $args) { + $blockItem = $args->getEntity(); + + // Both blocks and panels are instances of Block\AbstractBlock + if ($blockItem instanceof Block\AbstractBlock) { + $strategy = $blockItem->getStrategyClassName(); + $strategyInstance = new $strategy(); + if (null !== $blockItem->getConfig()) { + $strategyInstance->setConfig($blockItem->getConfig()); + } + $strategyInstance->setView($this->view); + $blockItem->setStrategy($strategyInstance); + } + } + } + +In this example, even some variables are set - like a view object +or a specific configuration object. + + diff --git a/vendor/doctrine/orm/docs/en/cookbook/validation-of-entities.rst b/vendor/doctrine/orm/docs/en/cookbook/validation-of-entities.rst new file mode 100644 index 0000000..dd10b8b --- /dev/null +++ b/vendor/doctrine/orm/docs/en/cookbook/validation-of-entities.rst @@ -0,0 +1,137 @@ +Validation of Entities +====================== + +.. sectionauthor:: Benjamin Eberlei + +Doctrine 2 does not ship with any internal validators, the reason +being that we think all the frameworks out there already ship with +quite decent ones that can be integrated into your Domain easily. +What we offer are hooks to execute any kind of validation. + +.. note:: + + You don't need to validate your entities in the lifecycle + events. Its only one of many options. Of course you can also + perform validations in value setters or any other method of your + entities that are used in your code. + + +Entities can register lifecycle event methods with Doctrine that +are called on different occasions. For validation we would need to +hook into the events called before persisting and updating. Even +though we don't support validation out of the box, the +implementation is even simpler than in Doctrine 1 and you will get +the additional benefit of being able to re-use your validation in +any other part of your domain. + +Say we have an ``Order`` with several ``OrderLine`` instances. We +never want to allow any customer to order for a larger sum than he +is allowed to: + +.. code-block:: php + + customer->getOrderLimit(); + + $amount = 0; + foreach ($this->orderLines as $line) { + $amount += $line->getAmount(); + } + + if ($amount > $orderLimit) { + throw new CustomerOrderLimitExceededException(); + } + } + } + +Now this is some pretty important piece of business logic in your +code, enforcing it at any time is important so that customers with +a unknown reputation don't owe your business too much money. + +We can enforce this constraint in any of the metadata drivers. +First Annotations: + +.. code-block:: php + + + + + + + + + + +YAML needs some little change yet, to allow multiple lifecycle +events for one method, this will happen before Beta 1 though. + +Now validation is performed whenever you call +``EntityManager#persist($order)`` or when you call +``EntityManager#flush()`` and an order is about to be updated. Any +Exception that happens in the lifecycle callbacks will be caught by +the EntityManager and the current transaction is rolled back. + +Of course you can do any type of primitive checks, not null, +email-validation, string size, integer and date ranges in your +validation callbacks. + +.. code-block:: php + + plannedShipDate instanceof DateTime)) { + throw new ValidateException(); + } + + if ($this->plannedShipDate->format('U') < time()) { + throw new ValidateException(); + } + + if ($this->customer == null) { + throw new OrderRequiresCustomerException(); + } + } + } + +What is nice about lifecycle events is, you can also re-use the +methods at other places in your domain, for example in combination +with your form library. Additionally there is no limitation in the +number of methods you register on one particular event, i.e. you +can register multiple methods for validation in "PrePersist" or +"PreUpdate" or mix and share them in any combinations between those +two events. + +There is no limit to what you can and can't validate in +"PrePersist" and "PreUpdate" as long as you don't create new entity +instances. This was already discussed in the previous blog post on +the Versionable extension, which requires another type of event +called "onFlush". + +Further readings: :ref:`reference-events-lifecycle-events` diff --git a/vendor/doctrine/orm/docs/en/cookbook/working-with-datetime.rst b/vendor/doctrine/orm/docs/en/cookbook/working-with-datetime.rst new file mode 100644 index 0000000..f599b83 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/cookbook/working-with-datetime.rst @@ -0,0 +1,197 @@ +Working with DateTime Instances +=============================== + +There are many nitty gritty details when working with PHPs DateTime instances. You have to know their inner +workings pretty well not to make mistakes with date handling. This cookbook entry holds several +interesting pieces of information on how to work with PHP DateTime instances in Doctrine 2. + +DateTime changes are detected by Reference +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When calling ``EntityManager#flush()`` Doctrine computes the changesets of all the currently managed entities +and saves the differences to the database. In case of object properties (@Column(type="datetime") or @Column(type="object")) +these comparisons are always made **BY REFERENCE**. That means the following change will **NOT** be saved into the database: + +.. code-block:: php + + updated->modify("now"); + } + } + +The way to go would be: + +.. code-block:: php + + updated = new \DateTime("now"); + } + } + +Default Timezone Gotcha +~~~~~~~~~~~~~~~~~~~~~~~ + +By default Doctrine assumes that you are working with a default timezone. Each DateTime instance that +is created by Doctrine will be assigned the timezone that is currently the default, either through +the ``date.timezone`` ini setting or by calling ``date_default_timezone_set()``. + +This is very important to handle correctly if your application runs on different servers or is moved from one to another server +(with different timezone settings). You have to make sure that the timezone is the correct one +on all this systems. + +Handling different Timezones with the DateTime Type +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you first come across the requirement to save different timezones you may be still optimistic about how +to manage this mess, +however let me crush your expectations fast. There is not a single database out there (supported by Doctrine 2) +that supports timezones correctly. Correctly here means that you can cover all the use-cases that +can come up with timezones. If you don't believe me you should read up on `Storing DateTime +in Databases `_. + +The problem is simple. Not a single database vendor saves the timezone, only the differences to UTC. +However with frequent daylight saving and political timezone changes you can have a UTC offset that moves +in different offset directions depending on the real location. + +The solution for this dilemma is simple. Don't use timezones with DateTime and Doctrine 2. However there is a workaround +that even allows correct date-time handling with timezones: + +1. Always convert any DateTime instance to UTC. +2. Only set Timezones for displaying purposes +3. Save the Timezone in the Entity for persistence. + +Say we have an application for an international postal company and employees insert events regarding postal-package +around the world, in their current timezones. To determine the exact time an event occurred means to save both +the UTC time at the time of the booking and the timezone the event happened in. + +.. code-block:: php + + setTimezone(self::getUtc()); + } + + return parent::convertToDatabaseValue($value, $platform); + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if (null === $value || $value instanceof \DateTime) { + return $value; + } + + $converted = \DateTime::createFromFormat( + $platform->getDateTimeFormatString(), + $value, + self::getUtc() + ); + + if (! $converted) { + throw ConversionException::conversionFailedFormat( + $value, + $this->getName(), + $platform->getDateTimeFormatString() + ); + } + + return $converted; + } + + private static function getUtc(): \DateTimeZone + { + return self::$utc ?: self::$utc = new \DateTimeZone('UTC'); + } + } + +This database type makes sure that every DateTime instance is always saved in UTC, relative +to the current timezone that the passed DateTime instance has. + +To actually use this new type instead of the default ``datetime`` type, you need to run following +code before bootstrapping the ORM: + +.. code-block:: php + + localized = true; + $this->created = $createDate; + $this->timezone = $createDate->getTimeZone()->getName(); + } + + public function getCreated() + { + if (!$this->localized) { + $this->created->setTimeZone(new \DateTimeZone($this->timezone)); + } + return $this->created; + } + } + +This snippet makes use of the previously discussed "changeset by reference only" property of +objects. That means a new DateTime will only be used during updating if the reference +changes between retrieval and flush operation. This means we can easily go and modify +the instance by setting the previous local timezone. diff --git a/vendor/doctrine/orm/docs/en/index.rst b/vendor/doctrine/orm/docs/en/index.rst new file mode 100644 index 0000000..0cea054 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/index.rst @@ -0,0 +1,128 @@ +Welcome to Doctrine 2 ORM's documentation! +========================================== + +The Doctrine documentation is comprised of tutorials, a reference section and +cookbook articles that explain different parts of the Object Relational mapper. + +Doctrine DBAL and Doctrine Common both have their own documentation. + +Getting Help +------------ + +If this documentation is not helping to answer questions you have about +Doctrine ORM don't panic. You can get help from different sources: + +- There is a :doc:`FAQ ` with answers to frequent questions. +- The `Doctrine Mailing List `_ +- Slack chat room `#orm `_ +- Report a bug on `GitHub `_. +- On `Twitter `_ with ``#doctrine2`` +- On `StackOverflow `_ + +If you need more structure over the different topics you can browse the :doc:`table +of contents `. + +Getting Started +--------------- + +* **Tutorial**: + :doc:`Getting Started with Doctrine ` + +* **Setup**: + :doc:`Installation & Configuration ` + +Mapping Objects onto a Database +------------------------------- + +* **Mapping**: + :doc:`Objects ` | + :doc:`Associations ` | + :doc:`Inheritance ` + +* **Drivers**: + :doc:`Docblock Annotations ` | + :doc:`XML ` | + :doc:`YAML ` | + :doc:`PHP ` + +Working with Objects +-------------------- + +* **Basic Reference**: + :doc:`Entities ` | + :doc:`Associations ` | + :doc:`Events ` + +* **Query Reference**: + :doc:`DQL ` | + :doc:`QueryBuilder ` | + :doc:`Native SQL ` + +* **Internals**: + :doc:`Internals explained ` | + :doc:`Associations ` + +Advanced Topics +--------------- + +* :doc:`Architecture ` +* :doc:`Advanced Configuration ` +* :doc:`Limitations and known issues ` +* :doc:`Commandline Tools ` +* :doc:`Transactions and Concurrency ` +* :doc:`Filters ` +* :doc:`NamingStrategy ` +* :doc:`Improving Performance ` +* :doc:`Caching ` +* :doc:`Partial Objects ` +* :doc:`Change Tracking Policies ` +* :doc:`Best Practices ` +* :doc:`Metadata Drivers ` +* :doc:`Batch Processing ` +* :doc:`Second Level Cache ` + +Tutorials +--------- + +* :doc:`Indexed associations ` +* :doc:`Extra Lazy Associations ` +* :doc:`Composite Primary Keys ` +* :doc:`Ordered associations ` +* :doc:`Pagination ` +* :doc:`Override Field/Association Mappings In Subclasses ` +* :doc:`Embeddables ` + +Changelogs +---------- + +* `Upgrade `_ + +Cookbook +-------- + +* **Patterns**: + :doc:`Aggregate Fields ` | + :doc:`Decorator Pattern ` | + :doc:`Strategy Pattern ` + +* **DQL Extension Points**: + :doc:`DQL Custom Walkers ` | + :doc:`DQL User-Defined-Functions ` + +* **Implementation**: + :doc:`Array Access ` | + :doc:`Notify ChangeTracking Example ` | + :doc:`Using Wakeup Or Clone ` | + :doc:`Working with DateTime ` | + :doc:`Validation ` | + :doc:`Entities in the Session ` | + :doc:`Keeping your Modules independent ` + +* **Hidden Gems** + :doc:`Prefixing Table Name ` + +* **Custom Datatypes** + :doc:`MySQL Enums ` + :doc:`Advanced Field Value Conversion ` + +.. include:: toc.rst diff --git a/vendor/doctrine/orm/docs/en/make.bat b/vendor/doctrine/orm/docs/en/make.bat new file mode 100644 index 0000000..53c40c9 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/make.bat @@ -0,0 +1,113 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +set SPHINXBUILD=sphinx-build +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Doctrine2ORM.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Doctrine2ORM.ghc + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end diff --git a/vendor/doctrine/orm/docs/en/reference/advanced-configuration.rst b/vendor/doctrine/orm/docs/en/reference/advanced-configuration.rst new file mode 100644 index 0000000..0ddb6ef --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/advanced-configuration.rst @@ -0,0 +1,470 @@ +Advanced Configuration +====================== + +The configuration of the EntityManager requires a +``Doctrine\ORM\Configuration`` instance as well as some database +connection parameters. This example shows all the potential +steps of configuration. + +.. code-block:: php + + setMetadataCacheImpl($cache); + $driverImpl = $config->newDefaultAnnotationDriver('/path/to/lib/MyProject/Entities'); + $config->setMetadataDriverImpl($driverImpl); + $config->setQueryCacheImpl($cache); + $config->setProxyDir('/path/to/myproject/lib/MyProject/Proxies'); + $config->setProxyNamespace('MyProject\Proxies'); + + if ($applicationMode == "development") { + $config->setAutoGenerateProxyClasses(true); + } else { + $config->setAutoGenerateProxyClasses(false); + } + + $connectionOptions = array( + 'driver' => 'pdo_sqlite', + 'path' => 'database.sqlite' + ); + + $em = EntityManager::create($connectionOptions, $config); + +.. note:: + + Do not use Doctrine without a metadata and query cache! + Doctrine is optimized for working with caches. The main + parts in Doctrine that are optimized for caching are the metadata + mapping information with the metadata cache and the DQL to SQL + conversions with the query cache. These 2 caches require only an + absolute minimum of memory yet they heavily improve the runtime + performance of Doctrine. The recommended cache driver to use with + Doctrine is `APC `_. APC provides you with + an opcode-cache (which is highly recommended anyway) and a very + fast in-memory cache storage that you can use for the metadata and + query caches as seen in the previous code snippet. + +Configuration Options +--------------------- + +The following sections describe all the configuration options +available on a ``Doctrine\ORM\Configuration`` instance. + +Proxy Directory (***REQUIRED***) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: php + + setProxyDir($dir); + $config->getProxyDir(); + +Gets or sets the directory where Doctrine generates any proxy +classes. For a detailed explanation on proxy classes and how they +are used in Doctrine, refer to the "Proxy Objects" section further +down. + +Proxy Namespace (***REQUIRED***) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: php + + setProxyNamespace($namespace); + $config->getProxyNamespace(); + +Gets or sets the namespace to use for generated proxy classes. For +a detailed explanation on proxy classes and how they are used in +Doctrine, refer to the "Proxy Objects" section further down. + +Metadata Driver (***REQUIRED***) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: php + + setMetadataDriverImpl($driver); + $config->getMetadataDriverImpl(); + +Gets or sets the metadata driver implementation that is used by +Doctrine to acquire the object-relational metadata for your +classes. + +There are currently 4 available implementations: + + +- ``Doctrine\ORM\Mapping\Driver\AnnotationDriver`` +- ``Doctrine\ORM\Mapping\Driver\XmlDriver`` +- ``Doctrine\ORM\Mapping\Driver\YamlDriver`` +- ``Doctrine\ORM\Mapping\Driver\DriverChain`` + +Throughout the most part of this manual the AnnotationDriver is +used in the examples. For information on the usage of the XmlDriver +or YamlDriver please refer to the dedicated chapters +``XML Mapping`` and ``YAML Mapping``. + +The annotation driver can be configured with a factory method on +the ``Doctrine\ORM\Configuration``: + +.. code-block:: php + + newDefaultAnnotationDriver('/path/to/lib/MyProject/Entities'); + $config->setMetadataDriverImpl($driverImpl); + +The path information to the entities is required for the annotation +driver, because otherwise mass-operations on all entities through +the console could not work correctly. All of metadata drivers +accept either a single directory as a string or an array of +directories. With this feature a single driver can support multiple +directories of Entities. + +Metadata Cache (***RECOMMENDED***) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: php + + setMetadataCacheImpl($cache); + $config->getMetadataCacheImpl(); + +Gets or sets the cache implementation to use for caching metadata +information, that is, all the information you supply via +annotations, xml or yaml, so that they do not need to be parsed and +loaded from scratch on every single request which is a waste of +resources. The cache implementation must implement the +``Doctrine\Common\Cache\Cache`` interface. + +Usage of a metadata cache is highly recommended. + +The recommended implementations for production are: + + +- ``Doctrine\Common\Cache\ApcCache`` +- ``Doctrine\Common\Cache\ApcuCache`` +- ``Doctrine\Common\Cache\MemcacheCache`` +- ``Doctrine\Common\Cache\XcacheCache`` +- ``Doctrine\Common\Cache\RedisCache`` + +For development you should use the +``Doctrine\Common\Cache\ArrayCache`` which only caches data on a +per-request basis. + +Query Cache (***RECOMMENDED***) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: php + + setQueryCacheImpl($cache); + $config->getQueryCacheImpl(); + +Gets or sets the cache implementation to use for caching DQL +queries, that is, the result of a DQL parsing process that includes +the final SQL as well as meta information about how to process the +SQL result set of a query. Note that the query cache does not +affect query results. You do not get stale data. This is a pure +optimization cache without any negative side-effects (except some +minimal memory usage in your cache). + +Usage of a query cache is highly recommended. + +The recommended implementations for production are: + + +- ``Doctrine\Common\Cache\ApcCache`` +- ``Doctrine\Common\Cache\ApcuCache`` +- ``Doctrine\Common\Cache\MemcacheCache`` +- ``Doctrine\Common\Cache\XcacheCache`` +- ``Doctrine\Common\Cache\RedisCache`` + +For development you should use the +``Doctrine\Common\Cache\ArrayCache`` which only caches data on a +per-request basis. + +SQL Logger (***Optional***) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: php + + setSQLLogger($logger); + $config->getSQLLogger(); + +Gets or sets the logger to use for logging all SQL statements +executed by Doctrine. The logger class must implement the +``Doctrine\DBAL\Logging\SQLLogger`` interface. A simple default +implementation that logs to the standard output using ``echo`` and +``var_dump`` can be found at +``Doctrine\DBAL\Logging\EchoSQLLogger``. + +Auto-generating Proxy Classes (***OPTIONAL***) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Proxy classes can either be generated manually through the Doctrine +Console or automatically at runtime by Doctrine. The configuration +option that controls this behavior is: + +.. code-block:: php + + setAutoGenerateProxyClasses($mode); + +Possible values for ``$mode`` are: + +- ``Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_NEVER`` + +Never autogenerate a proxy. You will need to generate the proxies +manually, for this use the Doctrine Console like so: + +.. code-block:: php + + $ ./doctrine orm:generate-proxies + +When you do this in a development environment, +be aware that you may get class/file not found errors if certain proxies +are not yet generated. You may also get failing lazy-loads if new +methods were added to the entity class that are not yet in the proxy class. +In such a case, simply use the Doctrine Console to (re)generate the +proxy classes. + +- ``Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_ALWAYS`` + +Always generates a new proxy in every request and writes it to disk. + +- ``Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS`` + +Generate the proxy class when the proxy file does not exist. +This strategy causes a file exists call whenever any proxy is +used the first time in a request. + +- ``Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_EVAL`` + +Generate the proxy classes and evaluate them on the fly via eval(), +avoiding writing the proxies to disk. +This strategy is only sane for development. + +In a production environment, it is highly recommended to use +AUTOGENERATE_NEVER to allow for optimal performances. The other +options are interesting in development environment. + +Before v2.4, ``setAutoGenerateProxyClasses`` would accept a boolean +value. This is still possible, ``FALSE`` being equivalent to +AUTOGENERATE_NEVER and ``TRUE`` to AUTOGENERATE_ALWAYS. + +Development vs Production Configuration +--------------------------------------- + +You should code your Doctrine2 bootstrapping with two different +runtime models in mind. There are some serious benefits of using +APC or Memcache in production. In development however this will +frequently give you fatal errors, when you change your entities and +the cache still keeps the outdated metadata. That is why we +recommend the ``ArrayCache`` for development. + +Furthermore you should have the Auto-generating Proxy Classes +option to true in development and to false in production. If this +option is set to ``TRUE`` it can seriously hurt your script +performance if several proxy classes are re-generated during script +execution. Filesystem calls of that magnitude can even slower than +all the database queries Doctrine issues. Additionally writing a +proxy sets an exclusive file lock which can cause serious +performance bottlenecks in systems with regular concurrent +requests. + +Connection Options +------------------ + +The ``$connectionOptions`` passed as the first argument to +``EntityManager::create()`` has to be either an array or an +instance of ``Doctrine\DBAL\Connection``. If an array is passed it +is directly passed along to the DBAL Factory +``Doctrine\DBAL\DriverManager::getConnection()``. The DBAL +configuration is explained in the +`DBAL section `_. + +Proxy Objects +------------- + +A proxy object is an object that is put in place or used instead of +the "real" object. A proxy object can add behavior to the object +being proxied without that object being aware of it. In Doctrine 2, +proxy objects are used to realize several features but mainly for +transparent lazy-loading. + +Proxy objects with their lazy-loading facilities help to keep the +subset of objects that are already in memory connected to the rest +of the objects. This is an essential property as without it there +would always be fragile partial objects at the outer edges of your +object graph. + +Doctrine 2 implements a variant of the proxy pattern where it +generates classes that extend your entity classes and adds +lazy-loading capabilities to them. Doctrine can then give you an +instance of such a proxy class whenever you request an object of +the class being proxied. This happens in two situations: + +Reference Proxies +~~~~~~~~~~~~~~~~~ + +The method ``EntityManager#getReference($entityName, $identifier)`` +lets you obtain a reference to an entity for which the identifier +is known, without loading that entity from the database. This is +useful, for example, as a performance enhancement, when you want to +establish an association to an entity for which you have the +identifier. You could simply do this: + +.. code-block:: php + + getReference('MyProject\Model\Item', $itemId); + $cart->addItem($item); + +Here, we added an Item to a Cart without loading the Item from the +database. If you invoke any method on the Item instance, it would +fully initialize its state transparently from the database. Here +$item is actually an instance of the proxy class that was generated +for the Item class but your code does not need to care. In fact it +**should not care**. Proxy objects should be transparent to your +code. + +Association proxies +~~~~~~~~~~~~~~~~~~~ + +The second most important situation where Doctrine uses proxy +objects is when querying for objects. Whenever you query for an +object that has a single-valued association to another object that +is configured LAZY, without joining that association in the same +query, Doctrine puts proxy objects in place where normally the +associated object would be. Just like other proxies it will +transparently initialize itself on first access. + +.. note:: + + Joining an association in a DQL or native query + essentially means eager loading of that association in that query. + This will override the 'fetch' option specified in the mapping for + that association, but only for that query. + + +Generating Proxy classes +~~~~~~~~~~~~~~~~~~~~~~~~ + +In a production environment, it is highly recommended to use +``AUTOGENERATE_NEVER`` to allow for optimal performances. +However you will be required to generate the proxies manually +using the Doctrine Console: + +.. code-block:: php + + $ ./doctrine orm:generate-proxies + +The other options are interesting in development environment: + +- ``AUTOGENERATE_ALWAYS`` will require you to create and configure + a proxy directory. Proxies will be generated and written to file + on each request, so any modification to your code will be acknowledged. + +- ``AUTOGENERATE_FILE_NOT_EXISTS`` will not overwrite an existing + proxy file. If your code changes, you will need to regenerate the + proxies manually. + +- ``AUTOGENERATE_EVAL`` will regenerate each proxy on each request, + but without writing them to disk. + +Autoloading Proxies +------------------- + +When you deserialize proxy objects from the session or any other storage +it is necessary to have an autoloading mechanism in place for these classes. +For implementation reasons Proxy class names are not PSR-0 compliant. This +means that you have to register a special autoloader for these classes: + +.. code-block:: php + + addDriver($xmlDriver, 'Doctrine\Tests\Models\Company'); + $chain->addDriver($yamlDriver, 'Doctrine\Tests\ORM\Mapping'); + +Based on the namespace of the entity the loading of entities is +delegated to the appropriate driver. The chain semantics come from +the fact that the driver loops through all namespaces and matches +the entity class name against the namespace using a +``strpos() === 0`` call. This means you need to order the drivers +correctly if sub-namespaces use different metadata driver +implementations. + + +Default Repository (***OPTIONAL***) +----------------------------------- + +Specifies the FQCN of a subclass of the EntityRepository. +That will be available for all entities without a custom repository class. + +.. code-block:: php + + setDefaultRepositoryClassName($fqcn); + $config->getDefaultRepositoryClassName(); + +The default value is ``Doctrine\ORM\EntityRepository``. +Any repository class must be a subclass of EntityRepository otherwise you got an ORMException + +Setting up the Console +---------------------- + +Doctrine uses the Symfony Console component for generating the command +line interface. You can take a look at the ``vendor/bin/doctrine.php`` +script and the ``Doctrine\ORM\Tools\Console\ConsoleRunner`` command +for inspiration how to setup the cli. + +In general the required code looks like this: + +.. code-block:: php + + setCatchExceptions(true); + $cli->setHelperSet($helperSet); + Doctrine\ORM\Tools\Console\ConsoleRunner::addCommands($cli); + $cli->run(); + diff --git a/vendor/doctrine/orm/docs/en/reference/annotations-reference.rst b/vendor/doctrine/orm/docs/en/reference/annotations-reference.rst new file mode 100644 index 0000000..20381da --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/annotations-reference.rst @@ -0,0 +1,1327 @@ +Annotations Reference +===================== + +You've probably used docblock annotations in some form already, +most likely to provide documentation metadata for a tool like +``PHPDocumentor`` (@author, @link, ...). Docblock annotations are a +tool to embed metadata inside the documentation section which can +then be processed by some tool. Doctrine 2 generalizes the concept +of docblock annotations so that they can be used for any kind of +metadata and so that it is easy to define new docblock annotations. +In order to allow more involved annotation values and to reduce the +chances of clashes with other docblock annotations, the Doctrine 2 +docblock annotations feature an alternative syntax that is heavily +inspired by the Annotation syntax introduced in Java 5. + +The implementation of these enhanced docblock annotations is +located in the ``Doctrine\Common\Annotations`` namespace and +therefore part of the Common package. Doctrine 2 docblock +annotations support namespaces and nested annotations among other +things. The Doctrine 2 ORM defines its own set of docblock +annotations for supplying object-relational mapping metadata. + +.. note:: + + If you're not comfortable with the concept of docblock + annotations, don't worry, as mentioned earlier Doctrine 2 provides + XML and YAML alternatives and you could easily implement your own + favourite mechanism for defining ORM metadata. + +In this chapter a reference of every Doctrine 2 Annotation is given +with short explanations on their context and usage. + +Index +----- + +- :ref:`@Column ` +- :ref:`@ColumnResult ` +- :ref:`@Cache ` +- :ref:`@ChangeTrackingPolicy ` +- :ref:`@CustomIdGenerator ` +- :ref:`@DiscriminatorColumn ` +- :ref:`@DiscriminatorMap ` +- :ref:`@Embeddable ` +- :ref:`@Embedded ` +- :ref:`@Entity ` +- :ref:`@EntityResult ` +- :ref:`@FieldResult ` +- :ref:`@GeneratedValue ` +- :ref:`@HasLifecycleCallbacks ` +- :ref:`@Index ` +- :ref:`@Id ` +- :ref:`@InheritanceType ` +- :ref:`@JoinColumn ` +- :ref:`@JoinColumns ` +- :ref:`@JoinTable ` +- :ref:`@ManyToOne ` +- :ref:`@ManyToMany ` +- :ref:`@MappedSuperclass ` +- :ref:`@NamedNativeQuery ` +- :ref:`@OneToOne ` +- :ref:`@OneToMany ` +- :ref:`@OrderBy ` +- :ref:`@PostLoad ` +- :ref:`@PostPersist ` +- :ref:`@PostRemove ` +- :ref:`@PostUpdate ` +- :ref:`@PrePersist ` +- :ref:`@PreRemove ` +- :ref:`@PreUpdate ` +- :ref:`@SequenceGenerator ` +- :ref:`@SqlResultSetMapping ` +- :ref:`@Table ` +- :ref:`@UniqueConstraint ` +- :ref:`@Version ` + +Reference +--------- + +.. _annref_column: + +@Column +~~~~~~~ + +Marks an annotated instance variable as "persistent". It has to be +inside the instance variables PHP DocBlock comment. Any value hold +inside this variable will be saved to and loaded from the database +as part of the lifecycle of the instance variables entity-class. + +Required attributes: + +- **type**: Name of the Doctrine Type which is converted between PHP + and Database representation. + +Optional attributes: + +- **name**: By default the property name is used for the database + column name also, however the 'name' attribute allows you to + determine the column name. + +- **length**: Used by the "string" type to determine its maximum + length in the database. Doctrine does not validate the length of a + string values for you. + +- **precision**: The precision for a decimal (exact numeric) column + (applies only for decimal column), which is the maximum number of + digits that are stored for the values. + +- **scale**: The scale for a decimal (exact numeric) column (applies + only for decimal column), which represents the number of digits + to the right of the decimal point and must not be greater than + *precision*. + +- **unique**: Boolean value to determine if the value of the column + should be unique across all rows of the underlying entities table. + +- **nullable**: Determines if NULL values allowed for this column. If not specified, default value is false. + +- **options**: Array of additional options: + + - ``default``: The default value to set for the column if no value + is supplied. + + - ``unsigned``: Boolean value to determine if the column should + be capable of representing only non-negative integers + (applies only for integer column and might not be supported by + all vendors). + + - ``fixed``: Boolean value to determine if the specified length of + a string column should be fixed or varying (applies only for + string/binary column and might not be supported by all vendors). + + - ``comment``: The comment of the column in the schema (might not + be supported by all vendors). + + - ``collation``: The collation of the column (only supported by Drizzle, Mysql, PostgreSQL>=9.1, Sqlite and SQLServer). + + - ``check``: Adds a check constraint type to the column (might not + be supported by all vendors). + +- **columnDefinition**: DDL SQL snippet that starts after the column + name and specifies the complete (non-portable!) column definition. + This attribute allows to make use of advanced RMDBS features. + However you should make careful use of this feature and the + consequences. SchemaTool will not detect changes on the column correctly + anymore if you use "columnDefinition". + + Additionally you should remember that the "type" + attribute still handles the conversion between PHP and Database + values. If you use this attribute on a column that is used for + joins between tables you should also take a look at + :ref:`@JoinColumn `. + +.. note:: + + For more detailed information on each attribute, please refer to + the DBAL ``Schema-Representation`` documentation. + +Examples: + +.. code-block:: php + + ` +can be found in the configuration section. + +Example: + +.. code-block:: php + + ` and :ref:`@GeneratedValue(strategy="CUSTOM") ` are specified. + +Required attributes: + +- **class**: name of the class which should extend Doctrine\ORM\Id\AbstractIdGenerator + +Example: + +.. code-block:: php + + ` +annotation to establish the relationship between the two classes. + +.. code-block:: php + + = 2.1) Specifies that this entity is marked as read only and not + considered for change-tracking. Entities of this type can be persisted + and removed though. + +Example: + +.. code-block:: php + + `. This +annotation is optional and only has meaning when used in +conjunction with @Id. + +If this annotation is not specified with @Id the NONE strategy is +used as default. + +Optional attributes: + + +- **strategy**: Set the name of the identifier generation strategy. + Valid values are AUTO, SEQUENCE, TABLE, IDENTITY, UUID, CUSTOM and NONE. + If not specified, default value is AUTO. + +Example: + +.. code-block:: php + + ` annotation on +the entity-class level. It provides a hint to the SchemaTool to +generate a database index on the specified table columns. It only +has meaning in the SchemaTool schema generation context. + +Required attributes: + + +- **name**: Name of the Index +- **columns**: Array of columns. + +Optional attributes: + +- **options**: Array of platform specific options: + + - ``where``: SQL WHERE condition to be used for partial indexes. It will + only have effect on supported platforms. + +Basic example: + +.. code-block:: php + + ` and +:ref:`@DiscriminatorColumn ` annotations. + +Examples: + +.. code-block:: php + + `, :ref:`@OneToOne ` fields +and in the Context of :ref:`@JoinTable ` nested inside +a @ManyToMany. This annotation is not required. If it is not +specified the attributes *name* and *referencedColumnName* are +inferred from the table and primary key names. + +Required attributes: + + +- **name**: Column name that holds the foreign key identifier for + this relation. In the context of @JoinTable it specifies the column + name in the join table. +- **referencedColumnName**: Name of the primary key identifier that + is used for joining of this relation. + +Optional attributes: + + +- **unique**: Determines whether this relation is exclusive between the + affected entities and should be enforced as such on the database + constraint level. Defaults to false. +- **nullable**: Determine whether the related entity is required, or if + null is an allowed state for the relation. Defaults to true. +- **onDelete**: Cascade Action (Database-level) +- **columnDefinition**: DDL SQL snippet that starts after the column + name and specifies the complete (non-portable!) column definition. + This attribute enables the use of advanced RMDBS features. Using + this attribute on @JoinColumn is necessary if you need slightly + different column definitions for joining columns, for example + regarding NULL/NOT NULL defaults. However by default a + "columnDefinition" attribute on :ref:`@Column ` also sets + the related @JoinColumn's columnDefinition. This is necessary to + make foreign keys work. + +Example: + +.. code-block:: php + + ` or :ref:`@OneToOne ` +relation with an entity that has multiple identifiers. + +.. _annref_jointable: + +@JoinTable +~~~~~~~~~~~~~~ + +Using :ref:`@OneToMany ` or +:ref:`@ManyToMany ` on the owning side of the relation +requires to specify the @JoinTable annotation which describes the +details of the database join table. If you do not specify +@JoinTable on these relations reasonable mapping defaults apply +using the affected table and the column names. + +Optional attributes: + + +- **name**: Database name of the join-table +- **joinColumns**: An array of @JoinColumn annotations describing the + join-relation between the owning entities table and the join table. +- **inverseJoinColumns**: An array of @JoinColumn annotations + describing the join-relation between the inverse entities table and + the join table. + +Example: + +.. code-block:: php + + ` is an +additional, optional annotation that has reasonable default +configuration values using the table and names of the two related +entities. + +Required attributes: + + +- **targetEntity**: FQCN of the referenced target entity. Can be the + unqualified class name if both classes are in the same namespace. + *IMPORTANT:* No leading backslash! + +Optional attributes: + + +- **mappedBy**: This option specifies the property name on the + targetEntity that is the owning side of this relation. It is a + required attribute for the inverse side of a relationship. +- **inversedBy**: The inversedBy attribute designates the field in the + entity that is the inverse side of the relationship. +- **cascade**: Cascade Option +- **fetch**: One of LAZY, EXTRA_LAZY or EAGER +- **indexBy**: Index the collection by a field on the target entity. + +.. note:: + + For ManyToMany bidirectional relationships either side may + be the owning side (the side that defines the @JoinTable and/or + does not make use of the mappedBy attribute, thus using a default + join table). + +Example: + +.. code-block:: php + + `. + +Optional attributes: + + +- **repositoryClass**: (>= 2.2) Specifies the FQCN of a subclass of the EntityRepository. + That will be inherited for all subclasses of that Mapped Superclass. + +Example: + +.. code-block:: php + + ` with one additional option which can +be specified. The configuration defaults for +:ref:`@JoinColumn ` using the target entity table and +primary key column names apply here too. + +Required attributes: + + +- **targetEntity**: FQCN of the referenced target entity. Can be the + unqualified class name if both classes are in the same namespace. + *IMPORTANT:* No leading backslash! + +Optional attributes: + + +- **cascade**: Cascade Option +- **fetch**: One of LAZY or EAGER +- **orphanRemoval**: Boolean that specifies if orphans, inverse + OneToOne entities that are not connected to any owning instance, + should be removed by Doctrine. Defaults to false. +- **inversedBy**: The inversedBy attribute designates the field in the + entity that is the inverse side of the relationship. + +Example: + +.. code-block:: php + + ` or :ref:`@OneToMany ` +annotation to specify by which criteria the collection should be +retrieved from the database by using an ORDER BY clause. + +This annotation requires a single non-attributed value with an DQL +snippet: + +Example: + +.. code-block:: php + + = 2.5) Name of the schema the table lies in. + +Example: + +.. code-block:: php + + ` annotation on +the entity-class level. It allows to hint the SchemaTool to +generate a database unique constraint on the specified table +columns. It only has meaning in the SchemaTool schema generation +context. + +Required attributes: + + +- **name**: Name of the Index +- **columns**: Array of columns. + +Optional attributes: + +- **options**: Array of platform specific options: + + - ``where``: SQL WHERE condition to be used for partial indexes. It will + only have effect on supported platforms. + +Basic example: + +.. code-block:: php + + ` +scenario. It only works on :ref:`@Column ` annotations that have +the type ``integer`` or ``datetime``. Combining ``@Version`` with +:ref:`@Id ` is not supported. + +Example: + +.. code-block:: php + + `. +- An entity class must not implement ``__wakeup`` or + :doc:`do so safely <../cookbook/implementing-wakeup-or-clone>`. + Also consider implementing + `Serializable `_ + instead. +- Any two entity classes in a class hierarchy that inherit + directly or indirectly from one another must not have a mapped + property with the same name. That is, if B inherits from A then B + must not have a mapped field with the same name as an already + mapped field that is inherited from A. +- An entity cannot make use of func_get_args() to implement variable parameters. + Generated proxies do not support this for performance reasons and your code might + actually fail to work when violating this restriction. + +Entities support inheritance, polymorphic associations, and +polymorphic queries. Both abstract and concrete classes can be +entities. Entities may extend non-entity classes as well as entity +classes, and non-entity classes may extend entity classes. + +.. note:: + + The constructor of an entity is only ever invoked when + *you* construct a new instance with the *new* keyword. Doctrine + never calls entity constructors, thus you are free to use them as + you wish and even have it require arguments of any type. + + +Entity states +~~~~~~~~~~~~~ + +An entity instance can be characterized as being NEW, MANAGED, +DETACHED or REMOVED. + + +- A NEW entity instance has no persistent identity, and is not yet + associated with an EntityManager and a UnitOfWork (i.e. those just + created with the "new" operator). +- A MANAGED entity instance is an instance with a persistent + identity that is associated with an EntityManager and whose + persistence is thus managed. +- A DETACHED entity instance is an instance with a persistent + identity that is not (or no longer) associated with an + EntityManager and a UnitOfWork. +- A REMOVED entity instance is an instance with a persistent + identity, associated with an EntityManager, that will be removed + from the database upon transaction commit. + +.. _architecture_persistent_fields: + +Persistent fields +~~~~~~~~~~~~~~~~~ + +The persistent state of an entity is represented by instance +variables. An instance variable must be directly accessed only from +within the methods of the entity by the entity instance itself. +Instance variables must not be accessed by clients of the entity. +The state of the entity is available to clients only through the +entity’s methods, i.e. accessor methods (getter/setter methods) or +other business methods. + +Collection-valued persistent fields and properties must be defined +in terms of the ``Doctrine\Common\Collections\Collection`` +interface. The collection implementation type may be used by the +application to initialize fields or properties before the entity is +made persistent. Once the entity becomes managed (or detached), +subsequent access must be through the interface type. + +Serializing entities +~~~~~~~~~~~~~~~~~~~~ + +Serializing entities can be problematic and is not really +recommended, at least not as long as an entity instance still holds +references to proxy objects or is still managed by an +EntityManager. If you intend to serialize (and unserialize) entity +instances that still hold references to proxy objects you may run +into problems with private properties because of technical +limitations. Proxy objects implement ``__sleep`` and it is not +possible for ``__sleep`` to return names of private properties in +parent classes. On the other hand it is not a solution for proxy +objects to implement ``Serializable`` because Serializable does not +work well with any potential cyclic object references (at least we +did not find a way yet, if you did, please contact us). + +The EntityManager +~~~~~~~~~~~~~~~~~ + +The ``EntityManager`` class is a central access point to the ORM +functionality provided by Doctrine 2. The ``EntityManager`` API is +used to manage the persistence of your objects and to query for +persistent objects. + +Transactional write-behind +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An ``EntityManager`` and the underlying ``UnitOfWork`` employ a +strategy called "transactional write-behind" that delays the +execution of SQL statements in order to execute them in the most +efficient way and to execute them at the end of a transaction so +that all write locks are quickly released. You should see Doctrine +as a tool to synchronize your in-memory objects with the database +in well defined units of work. Work with your objects and modify +them as usual and when you're done call ``EntityManager#flush()`` +to make your changes persistent. + +The Unit of Work +~~~~~~~~~~~~~~~~ + +Internally an ``EntityManager`` uses a ``UnitOfWork``, which is a +typical implementation of the +`Unit of Work pattern `_, +to keep track of all the things that need to be done the next time +``flush`` is invoked. You usually do not directly interact with a +``UnitOfWork`` but with the ``EntityManager`` instead. + + diff --git a/vendor/doctrine/orm/docs/en/reference/association-mapping.rst b/vendor/doctrine/orm/docs/en/reference/association-mapping.rst new file mode 100644 index 0000000..6347d89 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/association-mapping.rst @@ -0,0 +1,1130 @@ +Association Mapping +=================== + +This chapter explains mapping associations between objects. + +Instead of working with foreign keys in your code, you will always work with +references to objects instead and Doctrine will convert those references +to foreign keys internally. + +- A reference to a single object is represented by a foreign key. +- A collection of objects is represented by many foreign keys pointing to the object holding the collection + +This chapter is split into three different sections. + +- A list of all the possible association mapping use-cases is given. +- :ref:`association_mapping_defaults` are explained that simplify the use-case examples. +- :ref:`collections` are introduced that contain entities in associations. + +One tip for working with relations is to read the relation from left to right, where the left word refers to the current Entity. For example: + +- OneToMany - One instance of the current Entity has Many instances (references) to the refered Entity. +- ManyToOne - Many instances of the current Entity refer to One instance of the refered Entity. +- OneToOne - One instance of the current Entity refers to One instance of the refered Entity. + +See below for all the possible relations. + +An association is considered to be unidirectional if only one side of the association has +a property referring to the other side. + +To gain a full understanding of associations you should also read about :doc:`owning and +inverse sides of associations ` + +Many-To-One, Unidirectional +--------------------------- + +A many-to-one association is the most common association between objects. Example: Many Users have One Address: + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + .. code-block:: yaml + + User: + type: entity + manyToOne: + address: + targetEntity: Address + joinColumn: + name: address_id + referencedColumnName: id + + +.. note:: + + The above ``@JoinColumn`` is optional as it would default + to ``address_id`` and ``id`` anyways. You can omit it and let it + use the defaults. + +Generated MySQL Schema: + +.. code-block:: sql + + CREATE TABLE User ( + id INT AUTO_INCREMENT NOT NULL, + address_id INT DEFAULT NULL, + PRIMARY KEY(id) + ) ENGINE = InnoDB; + + CREATE TABLE Address ( + id INT AUTO_INCREMENT NOT NULL, + PRIMARY KEY(id) + ) ENGINE = InnoDB; + + ALTER TABLE User ADD FOREIGN KEY (address_id) REFERENCES Address(id); + +One-To-One, Unidirectional +-------------------------- + +Here is an example of a one-to-one association with a ``Product`` entity that +references one ``Shipment`` entity. + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + .. code-block:: yaml + + Product: + type: entity + oneToOne: + shipment: + targetEntity: Shipment + joinColumn: + name: shipment_id + referencedColumnName: id + +Note that the @JoinColumn is not really necessary in this example, +as the defaults would be the same. + +Generated MySQL Schema: + +.. code-block:: sql + + CREATE TABLE Product ( + id INT AUTO_INCREMENT NOT NULL, + shipment_id INT DEFAULT NULL, + UNIQUE INDEX UNIQ_6FBC94267FE4B2B (shipment_id), + PRIMARY KEY(id) + ) ENGINE = InnoDB; + CREATE TABLE Shipment ( + id INT AUTO_INCREMENT NOT NULL, + PRIMARY KEY(id) + ) ENGINE = InnoDB; + ALTER TABLE Product ADD FOREIGN KEY (shipment_id) REFERENCES Shipment(id); + +One-To-One, Bidirectional +------------------------- + +Here is a one-to-one relationship between a ``Customer`` and a +``Cart``. The ``Cart`` has a reference back to the ``Customer`` so +it is bidirectional. + +Here we see the ``mappedBy`` and ``inversedBy`` annotations for the first time. +They are used to tell Doctrine which property on the other side refers to the +object. + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + + + + .. code-block:: yaml + + Customer: + oneToOne: + cart: + targetEntity: Cart + mappedBy: customer + Cart: + oneToOne: + customer: + targetEntity: Customer + inversedBy: cart + joinColumn: + name: customer_id + referencedColumnName: id + +Note that the @JoinColumn is not really necessary in this example, +as the defaults would be the same. + +Generated MySQL Schema: + +.. code-block:: sql + + CREATE TABLE Cart ( + id INT AUTO_INCREMENT NOT NULL, + customer_id INT DEFAULT NULL, + PRIMARY KEY(id) + ) ENGINE = InnoDB; + CREATE TABLE Customer ( + id INT AUTO_INCREMENT NOT NULL, + PRIMARY KEY(id) + ) ENGINE = InnoDB; + ALTER TABLE Cart ADD FOREIGN KEY (customer_id) REFERENCES Customer(id); + +We had a choice of sides on which to place the ``inversedBy`` attribute. Because it +is on the ``Cart``, that is the owning side of the relation, and thus holds the +foreign key. + +One-To-One, Self-referencing +---------------------------- + +You can define a self-referencing one-to-one relationships like +below. + +.. code-block:: php + + features = new ArrayCollection(); + } + } + + /** @Entity */ + class Feature + { + // ... + /** + * Many features have one product. This is the owning side. + * @ManyToOne(targetEntity="Product", inversedBy="features") + * @JoinColumn(name="product_id", referencedColumnName="id") + */ + private $product; + // ... + } + + .. code-block:: xml + + + + + + + + + + + + + .. code-block:: yaml + + Product: + type: entity + oneToMany: + features: + targetEntity: Feature + mappedBy: product + Feature: + type: entity + manyToOne: + product: + targetEntity: Product + inversedBy: features + joinColumn: + name: product_id + referencedColumnName: id + +Note that the @JoinColumn is not really necessary in this example, +as the defaults would be the same. + +Generated MySQL Schema: + +.. code-block:: sql + + CREATE TABLE Product ( + id INT AUTO_INCREMENT NOT NULL, + PRIMARY KEY(id) + ) ENGINE = InnoDB; + CREATE TABLE Feature ( + id INT AUTO_INCREMENT NOT NULL, + product_id INT DEFAULT NULL, + PRIMARY KEY(id) + ) ENGINE = InnoDB; + ALTER TABLE Feature ADD FOREIGN KEY (product_id) REFERENCES Product(id); + +One-To-Many, Unidirectional with Join Table +------------------------------------------- + +A unidirectional one-to-many association can be mapped through a +join table. From Doctrine's point of view, it is simply mapped as a +unidirectional many-to-many whereby a unique constraint on one of +the join columns enforces the one-to-many cardinality. + +The following example sets up such a unidirectional one-to-many association: + +.. configuration-block:: + + .. code-block:: php + + phonenumbers = new \Doctrine\Common\Collections\ArrayCollection(); + } + + // ... + } + + /** @Entity */ + class Phonenumber + { + // ... + } + + .. code-block:: xml + + + + + + + + + + + + + + + + + .. code-block:: yaml + + User: + type: entity + manyToMany: + phonenumbers: + targetEntity: Phonenumber + joinTable: + name: users_phonenumbers + joinColumns: + user_id: + referencedColumnName: id + inverseJoinColumns: + phonenumber_id: + referencedColumnName: id + unique: true + + +Generates the following MySQL Schema: + +.. code-block:: sql + + CREATE TABLE User ( + id INT AUTO_INCREMENT NOT NULL, + PRIMARY KEY(id) + ) ENGINE = InnoDB; + + CREATE TABLE users_phonenumbers ( + user_id INT NOT NULL, + phonenumber_id INT NOT NULL, + UNIQUE INDEX users_phonenumbers_phonenumber_id_uniq (phonenumber_id), + PRIMARY KEY(user_id, phonenumber_id) + ) ENGINE = InnoDB; + + CREATE TABLE Phonenumber ( + id INT AUTO_INCREMENT NOT NULL, + PRIMARY KEY(id) + ) ENGINE = InnoDB; + + ALTER TABLE users_phonenumbers ADD FOREIGN KEY (user_id) REFERENCES User(id); + ALTER TABLE users_phonenumbers ADD FOREIGN KEY (phonenumber_id) REFERENCES Phonenumber(id); + +One-To-Many, Self-referencing +----------------------------- + +You can also setup a one-to-many association that is +self-referencing. In this example we setup a hierarchy of +``Category`` objects by creating a self referencing relationship. +This effectively models a hierarchy of categories and from the +database perspective is known as an adjacency list approach. + +.. configuration-block:: + + .. code-block:: php + + children = new \Doctrine\Common\Collections\ArrayCollection(); + } + } + + .. code-block:: xml + + + + + + + + + .. code-block:: yaml + + Category: + type: entity + oneToMany: + children: + targetEntity: Category + mappedBy: parent + manyToOne: + parent: + targetEntity: Category + inversedBy: children + +Note that the @JoinColumn is not really necessary in this example, +as the defaults would be the same. + +Generated MySQL Schema: + +.. code-block:: sql + + CREATE TABLE Category ( + id INT AUTO_INCREMENT NOT NULL, + parent_id INT DEFAULT NULL, + PRIMARY KEY(id) + ) ENGINE = InnoDB; + ALTER TABLE Category ADD FOREIGN KEY (parent_id) REFERENCES Category(id); + +Many-To-Many, Unidirectional +---------------------------- + +Real many-to-many associations are less common. The following +example shows a unidirectional association between User and Group +entities: + +.. configuration-block:: + + .. code-block:: php + + groups = new \Doctrine\Common\Collections\ArrayCollection(); + } + } + + /** @Entity */ + class Group + { + // ... + } + + .. code-block:: xml + + + + + + + + + + + + + + + + + .. code-block:: yaml + + User: + type: entity + manyToMany: + groups: + targetEntity: Group + joinTable: + name: users_groups + joinColumns: + user_id: + referencedColumnName: id + inverseJoinColumns: + group_id: + referencedColumnName: id + +Generated MySQL Schema: + +.. code-block:: sql + + CREATE TABLE User ( + id INT AUTO_INCREMENT NOT NULL, + PRIMARY KEY(id) + ) ENGINE = InnoDB; + CREATE TABLE users_groups ( + user_id INT NOT NULL, + group_id INT NOT NULL, + PRIMARY KEY(user_id, group_id) + ) ENGINE = InnoDB; + CREATE TABLE Group ( + id INT AUTO_INCREMENT NOT NULL, + PRIMARY KEY(id) + ) ENGINE = InnoDB; + ALTER TABLE users_groups ADD FOREIGN KEY (user_id) REFERENCES User(id); + ALTER TABLE users_groups ADD FOREIGN KEY (group_id) REFERENCES Group(id); + +.. note:: + + Why are many-to-many associations less common? Because + frequently you want to associate additional attributes with an + association, in which case you introduce an association class. + Consequently, the direct many-to-many association disappears and is + replaced by one-to-many/many-to-one associations between the 3 + participating classes. + +Many-To-Many, Bidirectional +--------------------------- + +Here is a similar many-to-many relationship as above except this +one is bidirectional. + +.. configuration-block:: + + .. code-block:: php + + groups = new \Doctrine\Common\Collections\ArrayCollection(); + } + + // ... + } + + /** @Entity */ + class Group + { + // ... + /** + * Many Groups have Many Users. + * @ManyToMany(targetEntity="User", mappedBy="groups") + */ + private $users; + + public function __construct() { + $this->users = new \Doctrine\Common\Collections\ArrayCollection(); + } + + // ... + } + + .. code-block:: xml + + + + + + + + + + + + + + + + + + + + + .. code-block:: yaml + + User: + type: entity + manyToMany: + groups: + targetEntity: Group + inversedBy: users + joinTable: + name: users_groups + joinColumns: + user_id: + referencedColumnName: id + inverseJoinColumns: + group_id: + referencedColumnName: id + + Group: + type: entity + manyToMany: + users: + targetEntity: User + mappedBy: groups + +The MySQL schema is exactly the same as for the Many-To-Many +uni-directional case above. + +Owning and Inverse Side on a ManyToMany Association +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For Many-To-Many associations you can chose which entity is the +owning and which the inverse side. There is a very simple semantic +rule to decide which side is more suitable to be the owning side +from a developers perspective. You only have to ask yourself which +entity is responsible for the connection management, and pick that +as the owning side. + +Take an example of two entities ``Article`` and ``Tag``. Whenever +you want to connect an Article to a Tag and vice-versa, it is +mostly the Article that is responsible for this relation. Whenever +you add a new article, you want to connect it with existing or new +tags. Your "Create Article" form will probably support this notion +and allow specifying the tags directly. This is why you should pick +the Article as owning side, as it makes the code more +understandable: + +.. code-block:: php + + addArticle($this); // synchronously updating inverse side + $this->tags[] = $tag; + } + } + + class Tag + { + private $articles; + + public function addArticle(Article $article) + { + $this->articles[] = $article; + } + } + +This allows to group the tag adding on the ``Article`` side of the +association: + +.. code-block:: php + + addTag($tagA); + $article->addTag($tagB); + +Many-To-Many, Self-referencing +------------------------------ + +You can even have a self-referencing many-to-many association. A +common scenario is where a ``User`` has friends and the target +entity of that relationship is a ``User`` so it is self +referencing. In this example it is bidirectional so ``User`` has a +field named ``$friendsWithMe`` and ``$myFriends``. + +.. code-block:: php + + friendsWithMe = new \Doctrine\Common\Collections\ArrayCollection(); + $this->myFriends = new \Doctrine\Common\Collections\ArrayCollection(); + } + + // ... + } + +Generated MySQL Schema: + +.. code-block:: sql + + CREATE TABLE User ( + id INT AUTO_INCREMENT NOT NULL, + PRIMARY KEY(id) + ) ENGINE = InnoDB; + CREATE TABLE friends ( + user_id INT NOT NULL, + friend_user_id INT NOT NULL, + PRIMARY KEY(user_id, friend_user_id) + ) ENGINE = InnoDB; + ALTER TABLE friends ADD FOREIGN KEY (user_id) REFERENCES User(id); + ALTER TABLE friends ADD FOREIGN KEY (friend_user_id) REFERENCES User(id); + +.. _association_mapping_defaults: + +Mapping Defaults +---------------- + +The ``@JoinColumn`` and ``@JoinTable`` definitions are usually optional and have +sensible default values. The defaults for a join column in a +one-to-one/many-to-one association is as follows: + +:: + + name: "_id" + referencedColumnName: "id" + +As an example, consider this mapping: + +.. configuration-block:: + + .. code-block:: php + + + + + + + + .. code-block:: yaml + + Product: + type: entity + oneToOne: + shipment: + targetEntity: Shipment + +This is essentially the same as the following, more verbose, +mapping: + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + .. code-block:: yaml + + Product: + type: entity + oneToOne: + shipment: + targetEntity: Shipment + joinColumn: + name: shipment_id + referencedColumnName: id + +The @JoinTable definition used for many-to-many mappings has +similar defaults. As an example, consider this mapping: + +.. configuration-block:: + + .. code-block:: php + + + + + + + + .. code-block:: yaml + + User: + type: entity + manyToMany: + groups: + targetEntity: Group + +This is essentially the same as the following, more verbose, mapping: + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + + + + + + + + .. code-block:: yaml + + User: + type: entity + manyToMany: + groups: + targetEntity: Group + joinTable: + name: User_Group + joinColumns: + User_id: + referencedColumnName: id + inverseJoinColumns: + Group_id: + referencedColumnName: id + +In that case, the name of the join table defaults to a combination +of the simple, unqualified class names of the participating +classes, separated by an underscore character. The names of the +join columns default to the simple, unqualified class name of the +targeted class followed by "\_id". The referencedColumnName always +defaults to "id", just as in one-to-one or many-to-one mappings. + +If you accept these defaults, you can reduce the mapping code to a +minimum. + +.. _collections: + +Collections +----------- + +Unfortunately, PHP arrays, while being great for many things, are missing +features that make them suitable for lazy loading in the context of an ORM. +This is why in all the examples of many-valued associations in this manual we +will make use of a ``Collection`` interface and its +default implementation ``ArrayCollection`` that are both defined in the +``Doctrine\Common\Collections`` namespace. A collection implements +the PHP interfaces ``ArrayAccess``, ``Traversable`` and ``Countable``. + +.. note:: + + The Collection interface and ArrayCollection class, + like everything else in the Doctrine namespace, are neither part of + the ORM, nor the DBAL, it is a plain PHP class that has no outside + dependencies apart from dependencies on PHP itself (and the SPL). + Therefore using this class in your model and elsewhere + does not introduce a coupling to the ORM. + +Initializing Collections +------------------------ + +You should always initialize the collections of your ``@OneToMany`` +and ``@ManyToMany`` associations in the constructor of your entities: + +.. code-block:: php + + groups = new ArrayCollection(); + } + + public function getGroups() + { + return $this->groups; + } + } + +The following code will then work even if the Entity hasn't +been associated with an EntityManager yet: + +.. code-block:: php + + getGroups()->add($group); diff --git a/vendor/doctrine/orm/docs/en/reference/basic-mapping.rst b/vendor/doctrine/orm/docs/en/reference/basic-mapping.rst new file mode 100644 index 0000000..91a8fef --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/basic-mapping.rst @@ -0,0 +1,504 @@ +Basic Mapping +============= + +This guide explains the basic mapping of entities and properties. +After working through this guide you should know: + +- How to create PHP objects that can be saved to the database with Doctrine; +- How to configure the mapping between columns on tables and properties on + entities; +- What Doctrine mapping types are; +- Defining primary keys and how identifiers are generated by Doctrine; +- How quoting of reserved symbols works in Doctrine. + +Mapping of associations will be covered in the next chapter on +:doc:`Association Mapping `. + +Guide Assumptions +----------------- + +You should have already :doc:`installed and configure ` +Doctrine. + +Creating Classes for the Database +--------------------------------- + +Every PHP object that you want to save in the database using Doctrine +is called an "Entity". The term "Entity" describes objects +that have an identity over many independent requests. This identity is +usually achieved by assigning a unique identifier to an entity. +In this tutorial the following ``Message`` PHP class will serve as the +example Entity: + +.. code-block:: php + + ` +- :doc:`XML ` +- :doc:`YAML ` +- :doc:`PHP code ` + +This manual will usually show mapping metadata via docblock annotations, though +many examples also show the equivalent configuration in YAML and XML. + +.. note:: + + All metadata drivers perform equally. Once the metadata of a class has been + read from the source (annotations, xml or yaml) it is stored in an instance + of the ``Doctrine\ORM\Mapping\ClassMetadata`` class and these instances are + stored in the metadata cache. If you're not using a metadata cache (not + recommended!) then the XML driver is the fastest. + +Marking our ``Message`` class as an entity for Doctrine is straightforward: + +.. configuration-block:: + + .. code-block:: php + + + + + + + + .. code-block:: yaml + + Message: + type: entity + # ... + +With no additional information, Doctrine expects the entity to be saved +into a table with the same name as the class in our case ``Message``. +You can change this by configuring information about the table: + +.. configuration-block:: + + .. code-block:: php + + + + + + + + .. code-block:: yaml + + Message: + type: entity + table: message + # ... + +Now the class ``Message`` will be saved and fetched from the table ``message``. + +Property Mapping +---------------- + +The next step after marking a PHP class as an entity is mapping its properties +to columns in a table. + +To configure a property use the ``@Column`` docblock annotation. The ``type`` +attribute specifies the :ref:`Doctrine Mapping Type ` +to use for the field. If the type is not specified, ``string`` is used as the +default. + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + .. code-block:: yaml + + Message: + type: entity + fields: + id: + type: integer + text: + length: 140 + postedAt: + type: datetime + column: posted_at + +When we don't explicitly specify a column name via the ``name`` option, Doctrine +assumes the field name is also the column name. This means that: + +* the ``id`` property will map to the column ``id`` using the type ``integer``; +* the ``text`` property will map to the column ``text`` with the default mapping type ``string``; +* the ``postedAt`` property will map to the ``posted_at`` column with the ``datetime`` type. + +The Column annotation has some more attributes. Here is a complete +list: + +- ``type``: (optional, defaults to 'string') The mapping type to + use for the column. +- ``name``: (optional, defaults to field name) The name of the + column in the database. +- ``length``: (optional, default 255) The length of the column in + the database. (Applies only if a string-valued column is used). +- ``unique``: (optional, default FALSE) Whether the column is a + unique key. +- ``nullable``: (optional, default FALSE) Whether the database + column is nullable. +- ``precision``: (optional, default 0) The precision for a decimal + (exact numeric) column (applies only for decimal column), + which is the maximum number of digits that are stored for the values. +- ``scale``: (optional, default 0) The scale for a decimal (exact + numeric) column (applies only for decimal column), which represents + the number of digits to the right of the decimal point and must + not be greater than *precision*. +- ``columnDefinition``: (optional) Allows to define a custom + DDL snippet that is used to create the column. Warning: This normally + confuses the SchemaTool to always detect the column as changed. +- ``options``: (optional) Key-value pairs of options that get passed + to the underlying database platform when generating DDL statements. + +.. _reference-mapping-types: + +Doctrine Mapping Types +---------------------- + +The ``type`` option used in the ``@Column`` accepts any of the existing +Doctrine types or even your own custom types. A Doctrine type defines +the conversion between PHP and SQL types, independent from the database vendor +you are using. All Mapping Types that ship with Doctrine are fully portable +between the supported database systems. + +As an example, the Doctrine Mapping Type ``string`` defines the +mapping from a PHP string to a SQL VARCHAR (or VARCHAR2 etc. +depending on the RDBMS brand). Here is a quick overview of the +built-in mapping types: + +- ``string``: Type that maps a SQL VARCHAR to a PHP string. +- ``integer``: Type that maps a SQL INT to a PHP integer. +- ``smallint``: Type that maps a database SMALLINT to a PHP + integer. +- ``bigint``: Type that maps a database BIGINT to a PHP string. +- ``boolean``: Type that maps a SQL boolean or equivalent (TINYINT) to a PHP boolean. +- ``decimal``: Type that maps a SQL DECIMAL to a PHP string. +- ``date``: Type that maps a SQL DATETIME to a PHP DateTime + object. +- ``time``: Type that maps a SQL TIME to a PHP DateTime object. +- ``datetime``: Type that maps a SQL DATETIME/TIMESTAMP to a PHP + DateTime object. +- ``datetimetz``: Type that maps a SQL DATETIME/TIMESTAMP to a PHP + DateTime object with timezone. +- ``text``: Type that maps a SQL CLOB to a PHP string. +- ``object``: Type that maps a SQL CLOB to a PHP object using + ``serialize()`` and ``unserialize()`` +- ``array``: Type that maps a SQL CLOB to a PHP array using + ``serialize()`` and ``unserialize()`` +- ``simple_array``: Type that maps a SQL CLOB to a PHP array using + ``implode()`` and ``explode()``, with a comma as delimiter. *IMPORTANT* + Only use this type if you are sure that your values cannot contain a ",". +- ``json_array``: Type that maps a SQL CLOB to a PHP array using + ``json_encode()`` and ``json_decode()`` +- ``float``: Type that maps a SQL Float (Double Precision) to a + PHP double. *IMPORTANT*: Works only with locale settings that use + decimal points as separator. +- ``guid``: Type that maps a database GUID/UUID to a PHP string. Defaults to + varchar but uses a specific type if the platform supports it. +- ``blob``: Type that maps a SQL BLOB to a PHP resource stream + +A cookbook article shows how to define :doc:`your own custom mapping types +<../cookbook/custom-mapping-types>`. + +.. note:: + + DateTime and Object types are compared by reference, not by value. Doctrine + updates this values if the reference changes and therefore behaves as if + these objects are immutable value objects. + +.. warning:: + + All Date types assume that you are exclusively using the default timezone + set by `date_default_timezone_set() `_ + or by the php.ini configuration ``date.timezone``. Working with + different timezones will cause troubles and unexpected behavior. + + If you need specific timezone handling you have to handle this + in your domain, converting all the values back and forth from UTC. + There is also a :doc:`cookbook entry <../cookbook/working-with-datetime>` + on working with datetimes that gives hints for implementing + multi timezone applications. + +Identifiers / Primary Keys +-------------------------- + +Every entity class must have an identifier/primary key. You can select +the field that serves as the identifier with the ``@Id`` +annotation. + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + + .. code-block:: yaml + + Message: + type: entity + id: + id: + type: integer + generator: + strategy: AUTO + fields: + # fields here + +In most cases using the automatic generator strategy (``@GeneratedValue``) is +what you want. It defaults to the identifier generation mechanism your current +database vendor prefers: AUTO_INCREMENT with MySQL, SERIAL with PostgreSQL, +Sequences with Oracle and so on. + +Identifier Generation Strategies +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The previous example showed how to use the default identifier +generation strategy without knowing the underlying database with +the AUTO-detection strategy. It is also possible to specify the +identifier generation strategy more explicitly, which allows you to +make use of some additional features. + +Here is the list of possible generation strategies: + +- ``AUTO`` (default): Tells Doctrine to pick the strategy that is + preferred by the used database platform. The preferred strategies + are IDENTITY for MySQL, SQLite, MsSQL and SQL Anywhere and SEQUENCE + for Oracle and PostgreSQL. This strategy provides full portability. +- ``SEQUENCE``: Tells Doctrine to use a database sequence for ID + generation. This strategy does currently not provide full + portability. Sequences are supported by Oracle, PostgreSql and + SQL Anywhere. +- ``IDENTITY``: Tells Doctrine to use special identity columns in + the database that generate a value on insertion of a row. This + strategy does currently not provide full portability and is + supported by the following platforms: MySQL/SQLite/SQL Anywhere + (AUTO\_INCREMENT), MSSQL (IDENTITY) and PostgreSQL (SERIAL). +- ``UUID``: Tells Doctrine to use the built-in Universally Unique Identifier + generator. This strategy provides full portability. +- ``TABLE``: Tells Doctrine to use a separate table for ID + generation. This strategy provides full portability. + ***This strategy is not yet implemented!*** +- ``NONE``: Tells Doctrine that the identifiers are assigned (and + thus generated) by your code. The assignment must take place before + a new entity is passed to ``EntityManager#persist``. NONE is the + same as leaving off the @GeneratedValue entirely. +- ``CUSTOM``: With this option, you can use the ``@CustomIdGenerator`` annotation. + It will allow you to pass a :doc:`class of your own to generate the identifiers.<_annref_customidgenerator>` + +Sequence Generator +^^^^^^^^^^^^^^^^^^ + +The Sequence Generator can currently be used in conjunction with +Oracle or Postgres and allows some additional configuration options +besides specifying the sequence's name: + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + + .. code-block:: yaml + + Message: + type: entity + id: + id: + type: integer + generator: + strategy: SEQUENCE + sequenceGenerator: + sequenceName: message_seq + allocationSize: 100 + initialValue: 1 + +The initial value specifies at which value the sequence should +start. + +The allocationSize is a powerful feature to optimize INSERT +performance of Doctrine. The allocationSize specifies by how much +values the sequence is incremented whenever the next value is +retrieved. If this is larger than 1 (one) Doctrine can generate +identifier values for the allocationSizes amount of entities. In +the above example with ``allocationSize=100`` Doctrine 2 would only +need to access the sequence once to generate the identifiers for +100 new entities. + +*The default allocationSize for a @SequenceGenerator is currently 10.* + +.. caution:: + + The allocationSize is detected by SchemaTool and + transformed into an "INCREMENT BY " clause in the CREATE SEQUENCE + statement. For a database schema created manually (and not + SchemaTool) you have to make sure that the allocationSize + configuration option is never larger than the actual sequences + INCREMENT BY value, otherwise you may get duplicate keys. + + +.. note:: + + It is possible to use strategy="AUTO" and at the same time + specifying a @SequenceGenerator. In such a case, your custom + sequence settings are used in the case where the preferred strategy + of the underlying platform is SEQUENCE, such as for Oracle and + PostgreSQL. + + +Composite Keys +~~~~~~~~~~~~~~ + +With Doctrine 2 you can use composite primary keys, using ``@Id`` on more then +one column. Some restrictions exist opposed to using a single identifier in +this case: The use of the ``@GeneratedValue`` annotation is not supported, +which means you can only use composite keys if you generate the primary key +values yourself before calling ``EntityManager#persist()`` on the entity. + +More details on composite primary keys are discussed in a :doc:`dedicated tutorial +<../tutorials/composite-primary-keys>`. + +Quoting Reserved Words +---------------------- + +Sometimes it is necessary to quote a column or table name because of reserved +word conflicts. Doctrine does not quote identifiers automatically, because it +leads to more problems than it would solve. Quoting tables and column names +needs to be done explicitly using ticks in the definition. + +.. code-block:: php + + setQuoteStrategy(new AnsiQuoteStrategy()); diff --git a/vendor/doctrine/orm/docs/en/reference/batch-processing.rst b/vendor/doctrine/orm/docs/en/reference/batch-processing.rst new file mode 100644 index 0000000..e238516 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/batch-processing.rst @@ -0,0 +1,196 @@ +Batch Processing +================ + +This chapter shows you how to accomplish bulk inserts, updates and +deletes with Doctrine in an efficient way. The main problem with +bulk operations is usually not to run out of memory and this is +especially what the strategies presented here provide help with. + +.. warning:: + + An ORM tool is not primarily well-suited for mass + inserts, updates or deletions. Every RDBMS has its own, most + effective way of dealing with such operations and if the options + outlined below are not sufficient for your purposes we recommend + you use the tools for your particular RDBMS for these bulk + operations. + + +.. note:: + + Having an SQL logger enabled when processing batches can have a serious impact on performance and resource usage. + To avoid that you should disable it in the DBAL configuration: +.. code-block:: php + + getConnection()->getConfiguration()->setSQLLogger(null); + +Bulk Inserts +------------ + +Bulk inserts in Doctrine are best performed in batches, taking +advantage of the transactional write-behind behavior of an +``EntityManager``. The following code shows an example for +inserting 10000 objects with a batch size of 20. You may need to +experiment with the batch size to find the size that works best for +you. Larger batch sizes mean more prepared statement reuse +internally but also mean more work during ``flush``. + +.. code-block:: php + + setStatus('user'); + $user->setUsername('user' . $i); + $user->setName('Mr.Smith-' . $i); + $em->persist($user); + if (($i % $batchSize) === 0) { + $em->flush(); + $em->clear(); // Detaches all objects from Doctrine! + } + } + $em->flush(); //Persist objects that did not make up an entire batch + $em->clear(); + +Bulk Updates +------------ + +There are 2 possibilities for bulk updates with Doctrine. + +DQL UPDATE +~~~~~~~~~~ + +The by far most efficient way for bulk updates is to use a DQL +UPDATE query. Example: + +.. code-block:: php + + createQuery('update MyProject\Model\Manager m set m.salary = m.salary * 0.9'); + $numUpdated = $q->execute(); + +Iterating results +~~~~~~~~~~~~~~~~~ + +An alternative solution for bulk updates is to use the +``Query#iterate()`` facility to iterate over the query results step +by step instead of loading the whole result into memory at once. +The following example shows how to do this, combining the iteration +with the batching strategy that was already used for bulk inserts: + +.. code-block:: php + + createQuery('select u from MyProject\Model\User u'); + $iterableResult = $q->iterate(); + foreach ($iterableResult as $row) { + $user = $row[0]; + $user->increaseCredit(); + $user->calculateNewBonuses(); + if (($i % $batchSize) === 0) { + $em->flush(); // Executes all updates. + $em->clear(); // Detaches all objects from Doctrine! + } + ++$i; + } + $em->flush(); + +.. note:: + + Iterating results is not possible with queries that + fetch-join a collection-valued association. The nature of such SQL + result sets is not suitable for incremental hydration. + +.. note:: + + Results may be fully buffered by the database client/ connection allocating + additional memory not visible to the PHP process. For large sets this + may easily kill the process for no apparent reason. + + +Bulk Deletes +------------ + +There are two possibilities for bulk deletes with Doctrine. You can +either issue a single DQL DELETE query or you can iterate over +results removing them one at a time. + +DQL DELETE +~~~~~~~~~~ + +The by far most efficient way for bulk deletes is to use a DQL +DELETE query. + +Example: + +.. code-block:: php + + createQuery('delete from MyProject\Model\Manager m where m.salary > 100000'); + $numDeleted = $q->execute(); + +Iterating results +~~~~~~~~~~~~~~~~~ + +An alternative solution for bulk deletes is to use the +``Query#iterate()`` facility to iterate over the query results step +by step instead of loading the whole result into memory at once. +The following example shows how to do this: + +.. code-block:: php + + createQuery('select u from MyProject\Model\User u'); + $iterableResult = $q->iterate(); + while (($row = $iterableResult->next()) !== false) { + $em->remove($row[0]); + if (($i % $batchSize) === 0) { + $em->flush(); // Executes all deletions. + $em->clear(); // Detaches all objects from Doctrine! + } + ++$i; + } + $em->flush(); + +.. note:: + + Iterating results is not possible with queries that + fetch-join a collection-valued association. The nature of such SQL + result sets is not suitable for incremental hydration. + + +Iterating Large Results for Data-Processing +------------------------------------------- + +You can use the ``iterate()`` method just to iterate over a large +result and no UPDATE or DELETE intention. The ``IterableResult`` +instance returned from ``$query->iterate()`` implements the +Iterator interface so you can process a large result without memory +problems using the following approach: + +.. code-block:: php + + _em->createQuery('select u from MyProject\Model\User u'); + $iterableResult = $q->iterate(); + foreach ($iterableResult as $row) { + // do stuff with the data in the row, $row[0] is always the object + + // detach from Doctrine, so that it can be Garbage-Collected immediately + $this->_em->detach($row[0]); + } + +.. note:: + + Iterating results is not possible with queries that + fetch-join a collection-valued association. The nature of such SQL + result sets is not suitable for incremental hydration. + + + diff --git a/vendor/doctrine/orm/docs/en/reference/best-practices.rst b/vendor/doctrine/orm/docs/en/reference/best-practices.rst new file mode 100644 index 0000000..256ee53 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/best-practices.rst @@ -0,0 +1,111 @@ +Best Practices +============== + +The best practices mentioned here that affect database +design generally refer to best practices when working with Doctrine +and do not necessarily reflect best practices for database design +in general. + +Constrain relationships as much as possible +------------------------------------------- + +It is important to constrain relationships as much as possible. +This means: + + +- Impose a traversal direction (avoid bidirectional associations + if possible) +- Eliminate nonessential associations + +This has several benefits: + + +- Reduced coupling in your domain model +- Simpler code in your domain model (no need to maintain + bidirectionality properly) +- Less work for Doctrine + +Avoid composite keys +-------------------- + +Even though Doctrine fully supports composite keys it is best not +to use them if possible. Composite keys require additional work by +Doctrine and thus have a higher probability of errors. + +Use events judiciously +---------------------- + +The event system of Doctrine is great and fast. Even though making +heavy use of events, especially lifecycle events, can have a +negative impact on the performance of your application. Thus you +should use events judiciously. + +Use cascades judiciously +------------------------ + +Automatic cascades of the persist/remove/merge/etc. operations are +very handy but should be used wisely. Do NOT simply add all +cascades to all associations. Think about which cascades actually +do make sense for you for a particular association, given the +scenarios it is most likely used in. + +Don't use special characters +---------------------------- + +Avoid using any non-ASCII characters in class, field, table or +column names. Doctrine itself is not unicode-safe in many places +and will not be until PHP itself is fully unicode-aware. + +Don't use identifier quoting +---------------------------- + +Identifier quoting is a workaround for using reserved words that +often causes problems in edge cases. Do not use identifier quoting +and avoid using reserved words as table or column names. + +Initialize collections in the constructor +----------------------------------------- + +It is recommended best practice to initialize any business +collections in entities in the constructor. Example: + +.. code-block:: php + + addresses = new ArrayCollection; + $this->articles = new ArrayCollection; + } + } + +Don't map foreign keys to fields in an entity +--------------------------------------------- + +Foreign keys have no meaning whatsoever in an object model. Foreign +keys are how a relational database establishes relationships. Your +object model establishes relationships through object references. +Thus mapping foreign keys to object fields heavily leaks details of +the relational model into the object model, something you really +should not do. + +Use explicit transaction demarcation +------------------------------------ + +While Doctrine will automatically wrap all DML operations in a +transaction on flush(), it is considered best practice to +explicitly set the transaction boundaries yourself. Otherwise every +single query is wrapped in a small transaction (Yes, SELECT +queries, too) since you can not talk to your database outside of a +transaction. While such short transactions for read-only (SELECT) +queries generally don't have any noticeable performance impact, it +is still preferable to use fewer, well-defined transactions that +are established through explicit transaction boundaries. + + diff --git a/vendor/doctrine/orm/docs/en/reference/caching.rst b/vendor/doctrine/orm/docs/en/reference/caching.rst new file mode 100644 index 0000000..4c07e16 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/caching.rst @@ -0,0 +1,477 @@ +Caching +======= + +Doctrine provides cache drivers in the ``Common`` package for some +of the most popular caching implementations such as APC, Memcache +and Xcache. We also provide an ``ArrayCache`` driver which stores +the data in a PHP array. Obviously, when using ``ArrayCache``, the +cache does not persist between requests, but this is useful for +testing in a development environment. + +Cache Drivers +------------- + +The cache drivers follow a simple interface that is defined in +``Doctrine\Common\Cache\Cache``. All the cache drivers extend a +base class ``Doctrine\Common\Cache\CacheProvider`` which implements +this interface. + +The interface defines the following public methods for you to implement: + + +- fetch($id) - Fetches an entry from the cache +- contains($id) - Test if an entry exists in the cache +- save($id, $data, $lifeTime = false) - Puts data into the cache for x seconds. 0 = infinite time +- delete($id) - Deletes a cache entry + +Each driver extends the ``CacheProvider`` class which defines a few +abstract protected methods that each of the drivers must +implement: + + +- doFetch($id) +- doContains($id) +- doSave($id, $data, $lifeTime = false) +- doDelete($id) + +The public methods ``fetch()``, ``contains()`` etc. use the +above protected methods which are implemented by the drivers. The +code is organized this way so that the protected methods in the +drivers do the raw interaction with the cache implementation and +the ``CacheProvider`` can build custom functionality on top of +these methods. + +This documentation does not cover every single cache driver included +with Doctrine. For an up-to-date-list, see the +`cache directory on GitHub `_. + +APC +~~~ + +In order to use the APC cache driver you must have it compiled and +enabled in your php.ini. You can read about APC +`in the PHP Documentation `_. It will give +you a little background information about what it is and how you +can use it as well as how to install it. + +Below is a simple example of how you could use the APC cache driver +by itself. + +.. code-block:: php + + save('cache_id', 'my_data'); + +APCu +~~~~ + +In order to use the APCu cache driver you must have it compiled and +enabled in your php.ini. You can read about APCu +`in the PHP Documentation `_. It will give +you a little background information about what it is and how you +can use it as well as how to install it. + +Below is a simple example of how you could use the APCu cache driver +by itself. + +.. code-block:: php + + save('cache_id', 'my_data'); + +Memcache +~~~~~~~~ + +In order to use the Memcache cache driver you must have it compiled +and enabled in your php.ini. You can read about Memcache +`on the PHP website `_. It will +give you a little background information about what it is and how +you can use it as well as how to install it. + +Below is a simple example of how you could use the Memcache cache +driver by itself. + +.. code-block:: php + + connect('memcache_host', 11211); + + $cacheDriver = new \Doctrine\Common\Cache\MemcacheCache(); + $cacheDriver->setMemcache($memcache); + $cacheDriver->save('cache_id', 'my_data'); + +Memcached +~~~~~~~~~ + +Memcached is a more recent and complete alternative extension to +Memcache. + +In order to use the Memcached cache driver you must have it compiled +and enabled in your php.ini. You can read about Memcached +`on the PHP website `_. It will +give you a little background information about what it is and how +you can use it as well as how to install it. + +Below is a simple example of how you could use the Memcached cache +driver by itself. + +.. code-block:: php + + addServer('memcache_host', 11211); + + $cacheDriver = new \Doctrine\Common\Cache\MemcachedCache(); + $cacheDriver->setMemcached($memcached); + $cacheDriver->save('cache_id', 'my_data'); + +Xcache +~~~~~~ + +In order to use the Xcache cache driver you must have it compiled +and enabled in your php.ini. You can read about Xcache +`here `_. It will give you a little +background information about what it is and how you can use it as +well as how to install it. + +Below is a simple example of how you could use the Xcache cache +driver by itself. + +.. code-block:: php + + save('cache_id', 'my_data'); + +Redis +~~~~~ + +In order to use the Redis cache driver you must have it compiled +and enabled in your php.ini. You can read about what Redis is +`from here `_. Also check +`A PHP extension for Redis `_ for how you can use +and install the Redis PHP extension. + +Below is a simple example of how you could use the Redis cache +driver by itself. + +.. code-block:: php + + connect('redis_host', 6379); + + $cacheDriver = new \Doctrine\Common\Cache\RedisCache(); + $cacheDriver->setRedis($redis); + $cacheDriver->save('cache_id', 'my_data'); + +Using Cache Drivers +------------------- + +In this section we'll describe how you can fully utilize the API of +the cache drivers to save data to a cache, check if some cached data +exists, fetch the cached data and delete the cached data. We'll use the +``ArrayCache`` implementation as our example here. + +.. code-block:: php + + save('cache_id', 'my_data'); + +The ``save()`` method accepts three arguments which are described +below: + + +- ``$id`` - The cache id +- ``$data`` - The cache entry/data. +- ``$lifeTime`` - The lifetime. If != false, sets a specific + lifetime for this cache entry (null => infinite lifeTime). + +You can save any type of data whether it be a string, array, +object, etc. + +.. code-block:: php + + 'value1', + 'key2' => 'value2' + ); + $cacheDriver->save('my_array', $array); + +Checking +~~~~~~~~ + +Checking whether cached data exists is very simple: just use the +``contains()`` method. It accepts a single argument which is the ID +of the cache entry. + +.. code-block:: php + + contains('cache_id')) { + echo 'cache exists'; + } else { + echo 'cache does not exist'; + } + +Fetching +~~~~~~~~ + +Now if you want to retrieve some cache entry you can use the +``fetch()`` method. It also accepts a single argument just like +``contains()`` which is again the ID of the cache entry. + +.. code-block:: php + + fetch('my_array'); + +Deleting +~~~~~~~~ + +As you might guess, deleting is just as easy as saving, checking +and fetching. You can delete by an individual ID, or you can +delete all entries. + +By Cache ID +^^^^^^^^^^^ + +.. code-block:: php + + delete('my_array'); + +All +^^^ + +If you simply want to delete all cache entries you can do so with +the ``deleteAll()`` method. + +.. code-block:: php + + deleteAll(); + +Namespaces +~~~~~~~~~~ + +If you heavily use caching in your application and use it in +multiple parts of your application, or use it in different +applications on the same server you may have issues with cache +naming collisions. This can be worked around by using namespaces. +You can set the namespace a cache driver should use by using the +``setNamespace()`` method. + +.. code-block:: php + + setNamespace('my_namespace_'); + +.. _integrating-with-the-orm: + +Integrating with the ORM +------------------------ + +The Doctrine ORM package is tightly integrated with the cache +drivers to allow you to improve the performance of various aspects of +Doctrine by simply making some additional configurations and +method calls. + +Query Cache +~~~~~~~~~~~ + +It is highly recommended that in a production environment you cache +the transformation of a DQL query to its SQL counterpart. It +doesn't make sense to do this parsing multiple times as it doesn't +change unless you alter the DQL query. + +This can be done by configuring the query cache implementation to +use on your ORM configuration. + +.. code-block:: php + + setQueryCacheImpl(new \Doctrine\Common\Cache\ApcuCache()); + +Result Cache +~~~~~~~~~~~~ + +The result cache can be used to cache the results of your queries +so that we don't have to query the database or hydrate the data +again after the first time. You just need to configure the result +cache implementation. + +.. code-block:: php + + setResultCacheImpl(new \Doctrine\Common\Cache\ApcuCache()); + +Now when you're executing DQL queries you can configure them to use +the result cache. + +.. code-block:: php + + createQuery('select u from \Entities\User u'); + $query->useResultCache(true); + +You can also configure an individual query to use a different +result cache driver. + +.. code-block:: php + + setResultCacheDriver(new \Doctrine\Common\Cache\ApcuCache()); + +.. note:: + + Setting the result cache driver on the query will + automatically enable the result cache for the query. If you want to + disable it pass false to ``useResultCache()``. + + :: + + useResultCache(false); + + +If you want to set the time the cache has to live you can use the +``setResultCacheLifetime()`` method. + +.. code-block:: php + + setResultCacheLifetime(3600); + +The ID used to store the result set cache is a hash which is +automatically generated for you if you don't set a custom ID +yourself with the ``setResultCacheId()`` method. + +.. code-block:: php + + setResultCacheId('my_custom_id'); + +You can also set the lifetime and cache ID by passing the values as +the second and third argument to ``useResultCache()``. + +.. code-block:: php + + useResultCache(true, 3600, 'my_custom_id'); + +Metadata Cache +~~~~~~~~~~~~~~ + +Your class metadata can be parsed from a few different sources like +YAML, XML, Annotations, etc. Instead of parsing this information on +each request we should cache it using one of the cache drivers. + +Just like the query and result cache we need to configure it +first. + +.. code-block:: php + + setMetadataCacheImpl(new \Doctrine\Common\Cache\ApcuCache()); + +Now the metadata information will only be parsed once and stored in +the cache driver. + +Clearing the Cache +------------------ + +We've already shown you how you can use the API of the +cache drivers to manually delete cache entries. For your +convenience we offer command line tasks to help you with +clearing the query, result and metadata cache. + +From the Doctrine command line you can run the following commands: + +To clear the query cache use the ``orm:clear-cache:query`` task. + +.. code-block:: php + + $ ./doctrine orm:clear-cache:query + +To clear the metadata cache use the ``orm:clear-cache:metadata`` task. + +.. code-block:: php + + $ ./doctrine orm:clear-cache:metadata + +To clear the result cache use the ``orm:clear-cache:result`` task. + +.. code-block:: php + + $ ./doctrine orm:clear-cache:result + +All these tasks accept a ``--flush`` option to flush the entire +contents of the cache instead of invalidating the entries. + +Cache Chaining +-------------- + +A common pattern is to use a static cache to store data that is +requested many times in a single PHP request. Even though this data +may be stored in a fast memory cache, often that cache is over a +network link leading to sizable network traffic. + +The ChainCache class allows multiple caches to be registered at once. +For example, a per-request ArrayCache can be used first, followed by +a (relatively) slower MemcacheCache if the ArrayCache misses. +ChainCache automatically handles pushing data up to faster caches in +the chain and clearing data in the entire stack when it is deleted. + +A ChainCache takes a simple array of CacheProviders in the order that +they should be used. + +.. code-block:: php + + $arrayCache = new \Doctrine\Common\Cache\ArrayCache(); + $memcache = new Memcache(); + $memcache->connect('memcache_host', 11211); + $chainCache = new \Doctrine\Common\Cache\ChainCache([ + $arrayCache, + $memcache, + ]); + +ChainCache itself extends the CacheProvider interface, so it is +possible to create chains of chains. While this may seem like an easy +way to build a simple high-availability cache, ChainCache does not +implement any exception handling so using it as a high-availability +mechanism is not recommended. + +Cache Slams +----------- + +Something to be careful of when using the cache drivers is +"cache slams". Imagine you have a heavily trafficked website with some +code that checks for the existence of a cache record and if it does +not exist it generates the information and saves it to the cache. +Now, if 100 requests were issued all at the same time and each one +sees the cache does not exist and they all try to insert the same +cache entry it could lock up APC, Xcache, etc. and cause problems. +Ways exist to work around this, like pre-populating your cache and +not letting your users' requests populate the cache. + +You can read more about cache slams +`in this blog post `_. + + diff --git a/vendor/doctrine/orm/docs/en/reference/change-tracking-policies.rst b/vendor/doctrine/orm/docs/en/reference/change-tracking-policies.rst new file mode 100644 index 0000000..d0f0998 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/change-tracking-policies.rst @@ -0,0 +1,151 @@ +Change Tracking Policies +======================== + +Change tracking is the process of determining what has changed in +managed entities since the last time they were synchronized with +the database. + +Doctrine provides 3 different change tracking policies, each having +its particular advantages and disadvantages. The change tracking +policy can be defined on a per-class basis (or more precisely, +per-hierarchy). + +Deferred Implicit +~~~~~~~~~~~~~~~~~ + +The deferred implicit policy is the default change tracking policy +and the most convenient one. With this policy, Doctrine detects the +changes by a property-by-property comparison at commit time and +also detects changes to entities or new entities that are +referenced by other managed entities ("persistence by +reachability"). Although the most convenient policy, it can have +negative effects on performance if you are dealing with large units +of work (see "Understanding the Unit of Work"). Since Doctrine +can't know what has changed, it needs to check all managed entities +for changes every time you invoke EntityManager#flush(), making +this operation rather costly. + +Deferred Explicit +~~~~~~~~~~~~~~~~~ + +The deferred explicit policy is similar to the deferred implicit +policy in that it detects changes through a property-by-property +comparison at commit time. The difference is that Doctrine 2 only +considers entities that have been explicitly marked for change detection +through a call to EntityManager#persist(entity) or through a save +cascade. All other entities are skipped. This policy therefore +gives improved performance for larger units of work while +sacrificing the behavior of "automatic dirty checking". + +Therefore, flush() operations are potentially cheaper with this +policy. The negative aspect this has is that if you have a rather +large application and you pass your objects through several layers +for processing purposes and business tasks you may need to track +yourself which entities have changed on the way so you can pass +them to EntityManager#persist(). + +This policy can be configured as follows: + +.. code-block:: php + + _listeners[] = $listener; + } + } + +Then, in each property setter of this class or derived classes, you +need to notify all the ``PropertyChangedListener`` instances. As an +example we add a convenience method on ``MyEntity`` that shows this +behaviour: + +.. code-block:: php + + _listeners) { + foreach ($this->_listeners as $listener) { + $listener->propertyChanged($this, $propName, $oldValue, $newValue); + } + } + } + + public function setData($data) + { + if ($data != $this->data) { + $this->_onPropertyChanged('data', $this->data, $data); + $this->data = $data; + } + } + } + +You have to invoke ``_onPropertyChanged`` inside every method that +changes the persistent state of ``MyEntity``. + +The check whether the new value is different from the old one is +not mandatory but recommended. That way you also have full control +over when you consider a property changed. + +The negative point of this policy is obvious: You need implement an +interface and write some plumbing code. But also note that we tried +hard to keep this notification functionality abstract. Strictly +speaking, it has nothing to do with the persistence layer and the +Doctrine ORM or DBAL. You may find that property notification +events come in handy in many other scenarios as well. As mentioned +earlier, the ``Doctrine\Common`` namespace is not that evil and +consists solely of very small classes and interfaces that have +almost no external dependencies (none to the DBAL and none to the +ORM) and that you can easily take with you should you want to swap +out the persistence layer. This change tracking policy does not +introduce a dependency on the Doctrine DBAL/ORM or the persistence +layer. + +The positive point and main advantage of this policy is its +effectiveness. It has the best performance characteristics of the 3 +policies with larger units of work and a flush() operation is very +cheap when nothing has changed. + + diff --git a/vendor/doctrine/orm/docs/en/reference/configuration.rst b/vendor/doctrine/orm/docs/en/reference/configuration.rst new file mode 100644 index 0000000..38775af --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/configuration.rst @@ -0,0 +1,144 @@ +Installation and Configuration +============================== + +Doctrine can be installed with `Composer `_. + +Define the following requirement in your ``composer.json`` file: + +:: + + { + "require": { + "doctrine/orm": "*" + } + } + +Then call ``composer install`` from your command line. If you don't know +how Composer works, check out their `Getting Started `_ to set up. + +Class loading +------------- + +Autoloading is taken care of by Composer. You just have to include the composer autoload file in your project: + +.. code-block:: php + + 'pdo_mysql', + 'user' => 'root', + 'password' => '', + 'dbname' => 'foo', + ); + + $config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode); + $entityManager = EntityManager::create($dbParams, $config); + +Or if you prefer XML: + +.. code-block:: php + + ` section. + +.. note:: + + You can learn more about the database connection configuration in the + `Doctrine DBAL connection configuration reference `_. + +Setting up the Commandline Tool +------------------------------- + +Doctrine ships with a number of command line tools that are very helpful +during development. You can call this command from the Composer binary +directory: + +.. code-block:: sh + + $ php vendor/bin/doctrine + +You need to register your applications EntityManager to the console tool +to make use of the tasks by creating a ``cli-config.php`` file with the +following content: + +On Doctrine 2.4 and above: + +.. code-block:: php + + new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()), + 'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) + )); diff --git a/vendor/doctrine/orm/docs/en/reference/dql-doctrine-query-language.rst b/vendor/doctrine/orm/docs/en/reference/dql-doctrine-query-language.rst new file mode 100644 index 0000000..5a38101 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/dql-doctrine-query-language.rst @@ -0,0 +1,1775 @@ +Doctrine Query Language +=========================== + +DQL stands for Doctrine Query Language and is an Object +Query Language derivative that is very similar to the Hibernate +Query Language (HQL) or the Java Persistence Query Language (JPQL). + +In essence, DQL provides powerful querying capabilities over your +object model. Imagine all your objects lying around in some storage +(like an object database). When writing DQL queries, think about +querying that storage to pick a certain subset of your objects. + +.. note:: + + A common mistake for beginners is to mistake DQL for + being just some form of SQL and therefore trying to use table names + and column names or join arbitrary tables together in a query. You + need to think about DQL as a query language for your object model, + not for your relational schema. + + +DQL is case in-sensitive, except for namespace, class and field +names, which are case sensitive. + +Types of DQL queries +-------------------- + +DQL as a query language has SELECT, UPDATE and DELETE constructs +that map to their corresponding SQL statement types. INSERT +statements are not allowed in DQL, because entities and their +relations have to be introduced into the persistence context +through ``EntityManager#persist()`` to ensure consistency of your +object model. + +DQL SELECT statements are a very powerful way of retrieving parts +of your domain model that are not accessible via associations. +Additionally they allow you to retrieve entities and their associations +in one single SQL select statement which can make a huge difference +in performance compared to using several queries. + +DQL UPDATE and DELETE statements offer a way to execute bulk +changes on the entities of your domain model. This is often +necessary when you cannot load all the affected entities of a bulk +update into memory. + +SELECT queries +-------------- + +DQL SELECT clause +~~~~~~~~~~~~~~~~~ + +Here is an example that selects all users with an age > 20: + +.. code-block:: php + + createQuery('SELECT u FROM MyProject\Model\User u WHERE u.age > 20'); + $users = $query->getResult(); + +Lets examine the query: + + +- ``u`` is a so called identification variable or alias that + refers to the ``MyProject\Model\User`` class. By placing this alias + in the SELECT clause we specify that we want all instances of the + User class that are matched by this query to appear in the query + result. +- The FROM keyword is always followed by a fully-qualified class + name which in turn is followed by an identification variable or + alias for that class name. This class designates a root of our + query from which we can navigate further via joins (explained + later) and path expressions. +- The expression ``u.age`` in the WHERE clause is a path + expression. Path expressions in DQL are easily identified by the + use of the '.' operator that is used for constructing paths. The + path expression ``u.age`` refers to the ``age`` field on the User + class. + +The result of this query would be a list of User objects where all +users are older than 20. + +Result format +~~~~~~~~~~~~~ +The composition of the expressions in the SELECT clause also +influences the nature of the query result. There are three +cases: + +**All objects** + +.. code-block:: sql + + SELECT u, p, n FROM Users u... + +In this case, the result will be an array of User objects because of +the FROM clause, with children ``p`` and ``n`` hydrated because of +their inclusion in the SELECT clause. + +**All scalars** + +.. code-block:: sql + + SELECT u.name, u.address FROM Users u... + +In this case, the result will be an array of arrays. In the example +above, each element of the result array would be an array of the +scalar name and address values. + +You can select scalars from any entity in the query. + +**Mixed** + +.. code-block:: sql + + SELECT u, p.quantity FROM Users u... + +Here, the result will again be an array of arrays, with each element +being an array made up of a User object and the scalar value +``p.quantity``. + +Multiple FROM clauses are allowed, which would cause the result +array elements to cycle through the classes included in the +multiple FROM clauses. + +.. note:: + + You cannot select other entities unless you also select the + root of the selection (which is the first entity in FROM). + + For example, ``SELECT p,n FROM Users u...`` would be wrong because + ``u`` is not part of the SELECT + + Doctrine throws an exception if you violate this constraint. + + +Joins +~~~~~ + +A SELECT query can contain joins. There are 2 types of JOINs: +"Regular" Joins and "Fetch" Joins. + +**Regular Joins**: Used to limit the results and/or compute +aggregate values. + +**Fetch Joins**: In addition to the uses of regular joins: Used to +fetch related entities and include them in the hydrated result of a +query. + +There is no special DQL keyword that distinguishes a regular join +from a fetch join. A join (be it an inner or outer join) becomes a +"fetch join" as soon as fields of the joined entity appear in the +SELECT part of the DQL query outside of an aggregate function. +Otherwise its a "regular join". + +Example: + +Regular join of the address: + +.. code-block:: php + + createQuery("SELECT u FROM User u JOIN u.address a WHERE a.city = 'Berlin'"); + $users = $query->getResult(); + +Fetch join of the address: + +.. code-block:: php + + createQuery("SELECT u, a FROM User u JOIN u.address a WHERE a.city = 'Berlin'"); + $users = $query->getResult(); + +When Doctrine hydrates a query with fetch-join it returns the class +in the FROM clause on the root level of the result array. In the +previous example an array of User instances is returned and the +address of each user is fetched and hydrated into the +``User#address`` variable. If you access the address Doctrine does +not need to lazy load the association with another query. + +.. note:: + + Doctrine allows you to walk all the associations between + all the objects in your domain model. Objects that were not already + loaded from the database are replaced with lazy load proxy + instances. Non-loaded Collections are also replaced by lazy-load + instances that fetch all the contained objects upon first access. + However relying on the lazy-load mechanism leads to many small + queries executed against the database, which can significantly + affect the performance of your application. **Fetch Joins** are the + solution to hydrate most or all of the entities that you need in a + single SELECT query. + + +Named and Positional Parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +DQL supports both named and positional parameters, however in +contrast to many SQL dialects positional parameters are specified +with numbers, for example "?1", "?2" and so on. Named parameters +are specified with ":name1", ":name2" and so on. + +When referencing the parameters in ``Query#setParameter($param, $value)`` +both named and positional parameters are used **without** their prefixes. + +DQL SELECT Examples +~~~~~~~~~~~~~~~~~~~ + +This section contains a large set of DQL queries and some +explanations of what is happening. The actual result also depends +on the hydration mode. + +Hydrate all User entities: + +.. code-block:: php + + createQuery('SELECT u FROM MyProject\Model\User u'); + $users = $query->getResult(); // array of User objects + +Retrieve the IDs of all CmsUsers: + +.. code-block:: php + + createQuery('SELECT u.id FROM CmsUser u'); + $ids = $query->getResult(); // array of CmsUser ids + +Retrieve the IDs of all users that have written an article: + +.. code-block:: php + + createQuery('SELECT DISTINCT u.id FROM CmsArticle a JOIN a.user u'); + $ids = $query->getResult(); // array of CmsUser ids + +Retrieve all articles and sort them by the name of the articles +users instance: + +.. code-block:: php + + createQuery('SELECT a FROM CmsArticle a JOIN a.user u ORDER BY u.name ASC'); + $articles = $query->getResult(); // array of CmsArticle objects + +Retrieve the Username and Name of a CmsUser: + +.. code-block:: php + + createQuery('SELECT u.username, u.name FROM CmsUser u'); + $users = $query->getResult(); // array of CmsUser username and name values + echo $users[0]['username']; + +Retrieve a ForumUser and his single associated entity: + +.. code-block:: php + + createQuery('SELECT u, a FROM ForumUser u JOIN u.avatar a'); + $users = $query->getResult(); // array of ForumUser objects with the avatar association loaded + echo get_class($users[0]->getAvatar()); + +Retrieve a CmsUser and fetch join all the phonenumbers he has: + +.. code-block:: php + + createQuery('SELECT u, p FROM CmsUser u JOIN u.phonenumbers p'); + $users = $query->getResult(); // array of CmsUser objects with the phonenumbers association loaded + $phonenumbers = $users[0]->getPhonenumbers(); + +Hydrate a result in Ascending: + +.. code-block:: php + + createQuery('SELECT u FROM ForumUser u ORDER BY u.id ASC'); + $users = $query->getResult(); // array of ForumUser objects + +Or in Descending Order: + +.. code-block:: php + + createQuery('SELECT u FROM ForumUser u ORDER BY u.id DESC'); + $users = $query->getResult(); // array of ForumUser objects + +Using Aggregate Functions: + +.. code-block:: php + + createQuery('SELECT COUNT(u.id) FROM Entities\User u'); + $count = $query->getSingleScalarResult(); + + $query = $em->createQuery('SELECT u, count(g.id) FROM Entities\User u JOIN u.groups g GROUP BY u.id'); + $result = $query->getResult(); + +With WHERE Clause and Positional Parameter: + +.. code-block:: php + + createQuery('SELECT u FROM ForumUser u WHERE u.id = ?1'); + $query->setParameter(1, 321); + $users = $query->getResult(); // array of ForumUser objects + +With WHERE Clause and Named Parameter: + +.. code-block:: php + + createQuery('SELECT u FROM ForumUser u WHERE u.username = :name'); + $query->setParameter('name', 'Bob'); + $users = $query->getResult(); // array of ForumUser objects + +With Nested Conditions in WHERE Clause: + +.. code-block:: php + + createQuery('SELECT u FROM ForumUser u WHERE (u.username = :name OR u.username = :name2) AND u.id = :id'); + $query->setParameters(array( + 'name' => 'Bob', + 'name2' => 'Alice', + 'id' => 321, + )); + $users = $query->getResult(); // array of ForumUser objects + +With COUNT DISTINCT: + +.. code-block:: php + + createQuery('SELECT COUNT(DISTINCT u.name) FROM CmsUser'); + $users = $query->getResult(); // array of ForumUser objects + +With Arithmetic Expression in WHERE clause: + +.. code-block:: php + + createQuery('SELECT u FROM CmsUser u WHERE ((u.id + 5000) * u.id + 3) < 10000000'); + $users = $query->getResult(); // array of ForumUser objects + +Retrieve user entities with Arithmetic Expression in ORDER clause, using the ``HIDDEN`` keyword: + +.. code-block:: php + + createQuery('SELECT u, u.posts_count + u.likes_count AS HIDDEN score FROM CmsUser u ORDER BY score'); + $users = $query->getResult(); // array of User objects + +Using a LEFT JOIN to hydrate all user-ids and optionally associated +article-ids: + +.. code-block:: php + + createQuery('SELECT u.id, a.id as article_id FROM CmsUser u LEFT JOIN u.articles a'); + $results = $query->getResult(); // array of user ids and every article_id for each user + +Restricting a JOIN clause by additional conditions specified by +WITH: + +.. code-block:: php + + createQuery("SELECT u FROM CmsUser u LEFT JOIN u.articles a WITH a.topic LIKE :foo"); + $query->setParameter('foo', '%foo%'); + $users = $query->getResult(); + +Using several Fetch JOINs: + +.. code-block:: php + + createQuery('SELECT u, a, p, c FROM CmsUser u JOIN u.articles a JOIN u.phonenumbers p JOIN a.comments c'); + $users = $query->getResult(); + +BETWEEN in WHERE clause: + +.. code-block:: php + + createQuery('SELECT u.name FROM CmsUser u WHERE u.id BETWEEN ?1 AND ?2'); + $query->setParameter(1, 123); + $query->setParameter(2, 321); + $usernames = $query->getResult(); + +DQL Functions in WHERE clause: + +.. code-block:: php + + createQuery("SELECT u.name FROM CmsUser u WHERE TRIM(u.name) = 'someone'"); + $usernames = $query->getResult(); + +IN() Expression: + +.. code-block:: php + + createQuery('SELECT u.name FROM CmsUser u WHERE u.id IN(46)'); + $usernames = $query->getResult(); + + $query = $em->createQuery('SELECT u FROM CmsUser u WHERE u.id IN (1, 2)'); + $users = $query->getResult(); + + $query = $em->createQuery('SELECT u FROM CmsUser u WHERE u.id NOT IN (1)'); + $users = $query->getResult(); + +CONCAT() DQL Function: + +.. code-block:: php + + createQuery("SELECT u.id FROM CmsUser u WHERE CONCAT(u.name, 's') = ?1"); + $query->setParameter(1, 'Jess'); + $ids = $query->getResult(); + + $query = $em->createQuery('SELECT CONCAT(u.id, u.name) FROM CmsUser u WHERE u.id = ?1'); + $query->setParameter(1, 321); + $idUsernames = $query->getResult(); + +EXISTS in WHERE clause with correlated Subquery + +.. code-block:: php + + createQuery('SELECT u.id FROM CmsUser u WHERE EXISTS (SELECT p.phonenumber FROM CmsPhonenumber p WHERE p.user = u.id)'); + $ids = $query->getResult(); + +Get all users who are members of $group. + +.. code-block:: php + + createQuery('SELECT u.id FROM CmsUser u WHERE :groupId MEMBER OF u.groups'); + $query->setParameter('groupId', $group); + $ids = $query->getResult(); + +Get all users that have more than 1 phonenumber + +.. code-block:: php + + createQuery('SELECT u FROM CmsUser u WHERE SIZE(u.phonenumbers) > 1'); + $users = $query->getResult(); + +Get all users that have no phonenumber + +.. code-block:: php + + createQuery('SELECT u FROM CmsUser u WHERE u.phonenumbers IS EMPTY'); + $users = $query->getResult(); + +Get all instances of a specific type, for use with inheritance +hierarchies: + +.. versionadded:: 2.1 + +.. code-block:: php + + createQuery('SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF Doctrine\Tests\Models\Company\CompanyEmployee'); + $query = $em->createQuery('SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF ?1'); + $query = $em->createQuery('SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u NOT INSTANCE OF ?1'); + +Get all users visible on a given website that have chosen certain gender: + +.. versionadded:: 2.2 + +.. code-block:: php + + createQuery('SELECT u FROM User u WHERE u.gender IN (SELECT IDENTITY(agl.gender) FROM Site s JOIN s.activeGenderList agl WHERE s.id = ?1)'); + +.. versionadded:: 2.4 + +Starting with 2.4, the IDENTITY() DQL function also works for composite primary keys: + +.. code-block:: php + + createQuery("SELECT IDENTITY(c.location, 'latitude') AS latitude, IDENTITY(c.location, 'longitude') AS longitude FROM Checkpoint c WHERE c.user = ?1"); + +Joins between entities without associations were not possible until version +2.4, where you can generate an arbitrary join with the following syntax: + +.. code-block:: php + + createQuery('SELECT u FROM User u JOIN Blacklist b WITH u.email = b.email'); + +.. note:: + The differences between WHERE, WITH and HAVING clauses may be + confusing. + + - WHERE is applied to the results of an entire query + - WITH is applied to a join as an additional condition. For + arbitrary joins (SELECT f, b FROM Foo f, Bar b WITH f.id = b.id) + the WITH is required, even if it is 1 = 1 + - HAVING is applied to the results of a query after + aggregation (GROUP BY) + + +Partial Object Syntax +^^^^^^^^^^^^^^^^^^^^^ + +By default when you run a DQL query in Doctrine and select only a +subset of the fields for a given entity, you do not receive objects +back. Instead, you receive only arrays as a flat rectangular result +set, similar to how you would if you were just using SQL directly +and joining some data. + +If you want to select partial objects you can use the ``partial`` +DQL keyword: + +.. code-block:: php + + createQuery('SELECT partial u.{id, username} FROM CmsUser u'); + $users = $query->getResult(); // array of partially loaded CmsUser objects + +You use the partial syntax when joining as well: + +.. code-block:: php + + createQuery('SELECT partial u.{id, username}, partial a.{id, name} FROM CmsUser u JOIN u.articles a'); + $users = $query->getResult(); // array of partially loaded CmsUser objects + +"NEW" Operator Syntax +^^^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: 2.4 + +Using the ``NEW`` operator you can construct Data Transfer Objects (DTOs) directly from DQL queries. + +- When using ``SELECT NEW`` you don't need to specify a mapped entity. +- You can specify any PHP class, it only requires that the constructor of this class matches the ``NEW`` statement. +- This approach involves determining exactly which columns you really need, + and instantiating a data-transfer object that contains a constructor with those arguments. + +If you want to select data-transfer objects you should create a class: + +.. code-block:: php + + createQuery('SELECT NEW CustomerDTO(c.name, e.email, a.city) FROM Customer c JOIN c.email e JOIN c.address a'); + $users = $query->getResult(); // array of CustomerDTO + +.. code-block:: php + + createQuery('SELECT NEW CustomerDTO(c.name, e.email, a.city, SUM(o.value)) FROM Customer c JOIN c.email e JOIN c.address a JOIN c.orders o GROUP BY c'); + $users = $query->getResult(); // array of CustomerDTO + +Note that you can only pass scalar expressions to the constructor. + +Using INDEX BY +~~~~~~~~~~~~~~ + +The INDEX BY construct is nothing that directly translates into SQL +but that affects object and array hydration. After each FROM and +JOIN clause you specify by which field this class should be indexed +in the result. By default a result is incremented by numerical keys +starting with 0. However with INDEX BY you can specify any other +column to be the key of your result, it really only makes sense +with primary or unique fields though: + +.. code-block:: sql + + SELECT u.id, u.status, upper(u.name) nameUpper FROM User u INDEX BY u.id + JOIN u.phonenumbers p INDEX BY p.phonenumber + +Returns an array of the following kind, indexed by both user-id +then phonenumber-id: + +.. code-block:: php + + array + 0 => + array + 1 => + object(stdClass)[299] + public '__CLASS__' => string 'Doctrine\Tests\Models\CMS\CmsUser' (length=33) + public 'id' => int 1 + .. + 'nameUpper' => string 'ROMANB' (length=6) + 1 => + array + 2 => + object(stdClass)[298] + public '__CLASS__' => string 'Doctrine\Tests\Models\CMS\CmsUser' (length=33) + public 'id' => int 2 + ... + 'nameUpper' => string 'JWAGE' (length=5) + +UPDATE queries +-------------- + +DQL not only allows to select your Entities using field names, you +can also execute bulk updates on a set of entities using an +DQL-UPDATE query. The Syntax of an UPDATE query works as expected, +as the following example shows: + +.. code-block:: sql + + UPDATE MyProject\Model\User u SET u.password = 'new' WHERE u.id IN (1, 2, 3) + +References to related entities are only possible in the WHERE +clause and using sub-selects. + +.. warning:: + + DQL UPDATE statements are ported directly into a + Database UPDATE statement and therefore bypass any locking scheme, events + and do not increment the version column. Entities that are already + loaded into the persistence context will *NOT* be synced with the + updated database state. It is recommended to call + ``EntityManager#clear()`` and retrieve new instances of any + affected entity. + + +DELETE queries +-------------- + +DELETE queries can also be specified using DQL and their syntax is +as simple as the UPDATE syntax: + +.. code-block:: sql + + DELETE MyProject\Model\User u WHERE u.id = 4 + +The same restrictions apply for the reference of related entities. + +.. warning:: + + DQL DELETE statements are ported directly into a + Database DELETE statement and therefore bypass any events and checks for the + version column if they are not explicitly added to the WHERE clause + of the query. Additionally Deletes of specified entities are *NOT* + cascaded to related entities even if specified in the metadata. + + +Functions, Operators, Aggregates +-------------------------------- +It is possible to wrap both fields and identification values into +aggregation and DQL functions. Numerical fields can be part of +computations using mathematical operations. + +DQL Functions +~~~~~~~~~~~~~ + +The following functions are supported in SELECT, WHERE and HAVING +clauses: + + +- IDENTITY(single\_association\_path\_expression [, fieldMapping]) - Retrieve the foreign key column of association of the owning side +- ABS(arithmetic\_expression) +- CONCAT(str1, str2) +- CURRENT\_DATE() - Return the current date +- CURRENT\_TIME() - Returns the current time +- CURRENT\_TIMESTAMP() - Returns a timestamp of the current date + and time. +- LENGTH(str) - Returns the length of the given string +- LOCATE(needle, haystack [, offset]) - Locate the first + occurrence of the substring in the string. +- LOWER(str) - returns the string lowercased. +- MOD(a, b) - Return a MOD b. +- SIZE(collection) - Return the number of elements in the + specified collection +- SQRT(q) - Return the square-root of q. +- SUBSTRING(str, start [, length]) - Return substring of given + string. +- TRIM([LEADING \| TRAILING \| BOTH] ['trchar' FROM] str) - Trim + the string by the given trim char, defaults to whitespaces. +- UPPER(str) - Return the upper-case of the given string. +- DATE_ADD(date, value, unit) - Add the given time to a given date. (Supported units are SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR) +- DATE_SUB(date, value, unit) - Subtract the given time from a given date. (Supported units are SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR) +- DATE_DIFF(date1, date2) - Calculate the difference in days between date1-date2. + +Arithmetic operators +~~~~~~~~~~~~~~~~~~~~ + +You can do math in DQL using numeric values, for example: + +.. code-block:: sql + + SELECT person.salary * 1.5 FROM CompanyPerson person WHERE person.salary < 100000 + +Aggregate Functions +~~~~~~~~~~~~~~~~~~~ + +The following aggregate functions are allowed in SELECT and GROUP +BY clauses: AVG, COUNT, MIN, MAX, SUM + +Other Expressions +~~~~~~~~~~~~~~~~~ + +DQL offers a wide-range of additional expressions that are known +from SQL, here is a list of all the supported constructs: + + +- ``ALL/ANY/SOME`` - Used in a WHERE clause followed by a + sub-select this works like the equivalent constructs in SQL. +- ``BETWEEN a AND b`` and ``NOT BETWEEN a AND b`` can be used to + match ranges of arithmetic values. +- ``IN (x1, x2, ...)`` and ``NOT IN (x1, x2, ..)`` can be used to + match a set of given values. +- ``LIKE ..`` and ``NOT LIKE ..`` match parts of a string or text + using % as a wildcard. +- ``IS NULL`` and ``IS NOT NULL`` to check for null values +- ``EXISTS`` and ``NOT EXISTS`` in combination with a sub-select + +Adding your own functions to the DQL language +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default DQL comes with functions that are part of a large basis +of underlying databases. However you will most likely choose a +database platform at the beginning of your project and most likely +never change it. For this cases you can easily extend the DQL +parser with own specialized platform functions. + +You can register custom DQL functions in your ORM Configuration: + +.. code-block:: php + + addCustomStringFunction($name, $class); + $config->addCustomNumericFunction($name, $class); + $config->addCustomDatetimeFunction($name, $class); + + $em = EntityManager::create($dbParams, $config); + +The functions have to return either a string, numeric or datetime +value depending on the registered function type. As an example we +will add a MySQL specific FLOOR() functionality. All the given +classes have to implement the base class : + +.. code-block:: php + + walkSimpleArithmeticExpression( + $this->simpleArithmeticExpression + ) . ')'; + } + + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } + } + +We will register the function by calling and can then use it: + +.. code-block:: php + + getConfiguration(); + $config->registerNumericFunction('FLOOR', 'MyProject\Query\MysqlFloor'); + + $dql = "SELECT FLOOR(person.salary * 1.75) FROM CompanyPerson person"; + +Querying Inherited Classes +-------------------------- + +This section demonstrates how you can query inherited classes and +what type of results to expect. + +Single Table +~~~~~~~~~~~~ + +`Single Table Inheritance `_ +is an inheritance mapping strategy where all classes of a hierarchy +are mapped to a single database table. In order to distinguish +which row represents which type in the hierarchy a so-called +discriminator column is used. + +First we need to setup an example set of entities to use. In this +scenario it is a generic Person and Employee example: + +.. code-block:: php + + setName('test'); + $employee->setDepartment('testing'); + $em->persist($employee); + $em->flush(); + +Now lets run a simple query to retrieve the ``Employee`` we just +created: + +.. code-block:: sql + + SELECT e FROM Entities\Employee e WHERE e.name = 'test' + +If we check the generated SQL you will notice it has some special +conditions added to ensure that we will only get back ``Employee`` +entities: + +.. code-block:: sql + + SELECT p0_.id AS id0, p0_.name AS name1, p0_.department AS department2, + p0_.discr AS discr3 FROM Person p0_ + WHERE (p0_.name = ?) AND p0_.discr IN ('employee') + +Class Table Inheritance +~~~~~~~~~~~~~~~~~~~~~~~ + +`Class Table Inheritance `_ +is an inheritance mapping strategy where each class in a hierarchy +is mapped to several tables: its own table and the tables of all +parent classes. The table of a child class is linked to the table +of a parent class through a foreign key constraint. Doctrine 2 +implements this strategy through the use of a discriminator column +in the topmost table of the hierarchy because this is the easiest +way to achieve polymorphic queries with Class Table Inheritance. + +The example for class table inheritance is the same as single +table, you just need to change the inheritance type from +``SINGLE_TABLE`` to ``JOINED``: + +.. code-block:: php + + createQuery('select u from MyProject\Model\User u'); + + // example2: using setDQL + $q = $em->createQuery(); + $q->setDQL('select u from MyProject\Model\User u'); + +Query Result Formats +~~~~~~~~~~~~~~~~~~~~ + +The format in which the result of a DQL SELECT query is returned +can be influenced by a so-called ``hydration mode``. A hydration +mode specifies a particular way in which a SQL result set is +transformed. Each hydration mode has its own dedicated method on +the Query class. Here they are: + + +- ``Query#getResult()``: Retrieves a collection of objects. The + result is either a plain collection of objects (pure) or an array + where the objects are nested in the result rows (mixed). +- ``Query#getSingleResult()``: Retrieves a single object. If the + result contains more than one object, an ``NonUniqueResultException`` + is thrown. If the result contains no objects, an ``NoResultException`` + is thrown. The pure/mixed distinction does not apply. +- ``Query#getOneOrNullResult()``: Retrieve a single object. If the + result contains more than one object, a ``NonUniqueResultException`` + is thrown. If no object is found null will be returned. +- ``Query#getArrayResult()``: Retrieves an array graph (a nested + array) that is largely interchangeable with the object graph + generated by ``Query#getResult()`` for read-only purposes. + + .. note:: + + An array graph can differ from the corresponding object + graph in certain scenarios due to the difference of the identity + semantics between arrays and objects. + + + +- ``Query#getScalarResult()``: Retrieves a flat/rectangular result + set of scalar values that can contain duplicate data. The + pure/mixed distinction does not apply. +- ``Query#getSingleScalarResult()``: Retrieves a single scalar + value from the result returned by the dbms. If the result contains + more than a single scalar value, an exception is thrown. The + pure/mixed distinction does not apply. + +Instead of using these methods, you can alternatively use the +general-purpose method +``Query#execute(array $params = array(), $hydrationMode = Query::HYDRATE_OBJECT)``. +Using this method you can directly supply the hydration mode as the +second parameter via one of the Query constants. In fact, the +methods mentioned earlier are just convenient shortcuts for the +execute method. For example, the method ``Query#getResult()`` +internally invokes execute, passing in ``Query::HYDRATE_OBJECT`` as +the hydration mode. + +The use of the methods mentioned earlier is generally preferred as +it leads to more concise code. + +Pure and Mixed Results +~~~~~~~~~~~~~~~~~~~~~~ + +The nature of a result returned by a DQL SELECT query retrieved +through ``Query#getResult()`` or ``Query#getArrayResult()`` can be +of 2 forms: **pure** and **mixed**. In the previous simple +examples, you already saw a "pure" query result, with only objects. +By default, the result type is **pure** but +**as soon as scalar values, such as aggregate values or other scalar values that do not belong to an entity, appear in the SELECT part of the DQL query, the result becomes mixed**. +A mixed result has a different structure than a pure result in +order to accommodate for the scalar values. + +A pure result usually looks like this: + +.. code-block:: php + + $dql = "SELECT u FROM User u"; + + array + [0] => Object + [1] => Object + [2] => Object + ... + +A mixed result on the other hand has the following general +structure: + +.. code-block:: php + + $dql = "SELECT u, 'some scalar string', count(g.id) AS num FROM User u JOIN u.groups g GROUP BY u.id"; + + array + [0] + [0] => Object + [1] => "some scalar string" + ['num'] => 42 + // ... more scalar values, either indexed numerically or with a name + [1] + [0] => Object + [1] => "some scalar string" + ['num'] => 42 + // ... more scalar values, either indexed numerically or with a name + +To better understand mixed results, consider the following DQL +query: + +.. code-block:: sql + + SELECT u, UPPER(u.name) nameUpper FROM MyProject\Model\User u + +This query makes use of the ``UPPER`` DQL function that returns a +scalar value and because there is now a scalar value in the SELECT +clause, we get a mixed result. + +Conventions for mixed results are as follows: + + +- The object fetched in the FROM clause is always positioned with the key '0'. +- Every scalar without a name is numbered in the order given in the query, starting with 1. +- Every aliased scalar is given with its alias-name as the key. The case of the name is kept. +- If several objects are fetched from the FROM clause they alternate every row. + + +Here is how the result could look like: + +.. code-block:: php + + array + array + [0] => User (Object) + ['nameUpper'] => "ROMAN" + array + [0] => User (Object) + ['nameUpper'] => "JONATHAN" + ... + +And here is how you would access it in PHP code: + +.. code-block:: php + + getName(); + echo "Name UPPER: " . $row['nameUpper']; + } + +Fetching Multiple FROM Entities +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you fetch multiple entities that are listed in the FROM clause then the hydration +will return the rows iterating the different top-level entities. + +.. code-block:: php + + $dql = "SELECT u, g FROM User u, Group g"; + + array + [0] => Object (User) + [1] => Object (Group) + [2] => Object (User) + [3] => Object (Group) + + +Hydration Modes +~~~~~~~~~~~~~~~ + +Each of the Hydration Modes makes assumptions about how the result +is returned to user land. You should know about all the details to +make best use of the different result formats: + +The constants for the different hydration modes are: + + +- Query::HYDRATE\_OBJECT +- Query::HYDRATE\_ARRAY +- Query::HYDRATE\_SCALAR +- Query::HYDRATE\_SINGLE\_SCALAR + +Object Hydration +^^^^^^^^^^^^^^^^ + +Object hydration hydrates the result set into the object graph: + +.. code-block:: php + + createQuery('SELECT u FROM CmsUser u'); + $users = $query->getResult(Query::HYDRATE_OBJECT); + +Sometimes the behavior in the object hydrator can be confusing, which is +why we are listing as many of the assumptions here for reference: + +- Objects fetched in a FROM clause are returned as a Set, that means every + object is only ever included in the resulting array once. This is the case + even when using JOIN or GROUP BY in ways that return the same row for an + object multiple times. If the hydrator sees the same object multiple times, + then it makes sure it is only returned once. + +- If an object is already in memory from a previous query of any kind, then + then the previous object is used, even if the database may contain more + recent data. Data from the database is discarded. This even happens if the + previous object is still an unloaded proxy. + +This list might be incomplete. + +Array Hydration +^^^^^^^^^^^^^^^ + +You can run the same query with array hydration and the result set +is hydrated into an array that represents the object graph: + +.. code-block:: php + + createQuery('SELECT u FROM CmsUser u'); + $users = $query->getResult(Query::HYDRATE_ARRAY); + +You can use the ``getArrayResult()`` shortcut as well: + +.. code-block:: php + + getArrayResult(); + +Scalar Hydration +^^^^^^^^^^^^^^^^ + +If you want to return a flat rectangular result set instead of an +object graph you can use scalar hydration: + +.. code-block:: php + + createQuery('SELECT u FROM CmsUser u'); + $users = $query->getResult(Query::HYDRATE_SCALAR); + echo $users[0]['u_id']; + +The following assumptions are made about selected fields using +Scalar Hydration: + + +1. Fields from classes are prefixed by the DQL alias in the result. + A query of the kind 'SELECT u.name ..' returns a key 'u\_name' in + the result rows. + +Single Scalar Hydration +^^^^^^^^^^^^^^^^^^^^^^^ + +If you have a query which returns just a single scalar value you can use +single scalar hydration: + +.. code-block:: php + + createQuery('SELECT COUNT(a.id) FROM CmsUser u LEFT JOIN u.articles a WHERE u.username = ?1 GROUP BY u.id'); + $query->setParameter(1, 'jwage'); + $numArticles = $query->getResult(Query::HYDRATE_SINGLE_SCALAR); + +You can use the ``getSingleScalarResult()`` shortcut as well: + +.. code-block:: php + + getSingleScalarResult(); + +Custom Hydration Modes +^^^^^^^^^^^^^^^^^^^^^^ + +You can easily add your own custom hydration modes by first +creating a class which extends ``AbstractHydrator``: + +.. code-block:: php + + _stmt->fetchAll(PDO::FETCH_ASSOC); + } + } + +Next you just need to add the class to the ORM configuration: + +.. code-block:: php + + getConfiguration()->addCustomHydrationMode('CustomHydrator', 'MyProject\Hydrators\CustomHydrator'); + +Now the hydrator is ready to be used in your queries: + +.. code-block:: php + + createQuery('SELECT u FROM CmsUser u'); + $results = $query->getResult('CustomHydrator'); + +Iterating Large Result Sets +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are situations when a query you want to execute returns a +very large result-set that needs to be processed. All the +previously described hydration modes completely load a result-set +into memory which might not be feasible with large result sets. See +the `Batch Processing `_ section on details how +to iterate large result sets. + +Functions +~~~~~~~~~ + +The following methods exist on the ``AbstractQuery`` which both +``Query`` and ``NativeQuery`` extend from. + +Parameters +^^^^^^^^^^ + +Prepared Statements that use numerical or named wildcards require +additional parameters to be executable against the database. To +pass parameters to the query the following methods can be used: + + +- ``AbstractQuery::setParameter($param, $value)`` - Set the + numerical or named wildcard to the given value. +- ``AbstractQuery::setParameters(array $params)`` - Set an array + of parameter key-value pairs. +- ``AbstractQuery::getParameter($param)`` +- ``AbstractQuery::getParameters()`` + +Both named and positional parameters are passed to these methods without their ? or : prefix. + +Cache related API +^^^^^^^^^^^^^^^^^ + +You can cache query results based either on all variables that +define the result (SQL, Hydration Mode, Parameters and Hints) or on +user-defined cache keys. However by default query results are not +cached at all. You have to enable the result cache on a per query +basis. The following example shows a complete workflow using the +Result Cache API: + +.. code-block:: php + + createQuery('SELECT u FROM MyProject\Model\User u WHERE u.id = ?1'); + $query->setParameter(1, 12); + + $query->setResultCacheDriver(new ApcCache()); + + $query->useResultCache(true) + ->setResultCacheLifeTime($seconds = 3600); + + $result = $query->getResult(); // cache miss + + $query->expireResultCache(true); + $result = $query->getResult(); // forced expire, cache miss + + $query->setResultCacheId('my_query_result'); + $result = $query->getResult(); // saved in given result cache id. + + // or call useResultCache() with all parameters: + $query->useResultCache(true, $seconds = 3600, 'my_query_result'); + $result = $query->getResult(); // cache hit! + + // Introspection + $queryCacheProfile = $query->getQueryCacheProfile(); + $cacheDriver = $query->getResultCacheDriver(); + $lifetime = $query->getLifetime(); + $key = $query->getCacheKey(); + +.. note:: + + You can set the Result Cache Driver globally on the + ``Doctrine\ORM\Configuration`` instance so that it is passed to + every ``Query`` and ``NativeQuery`` instance. + + +Query Hints +^^^^^^^^^^^ + +You can pass hints to the query parser and hydrators by using the +``AbstractQuery::setHint($name, $value)`` method. Currently there +exist mostly internal query hints that are not be consumed in +userland. However the following few hints are to be used in +userland: + + +- Query::HINT\_FORCE\_PARTIAL\_LOAD - Allows to hydrate objects + although not all their columns are fetched. This query hint can be + used to handle memory consumption problems with large result-sets + that contain char or binary data. Doctrine has no way of implicitly + reloading this data. Partially loaded objects have to be passed to + ``EntityManager::refresh()`` if they are to be reloaded fully from + the database. +- Query::HINT\_REFRESH - This query is used internally by + ``EntityManager::refresh()`` and can be used in userland as well. + If you specify this hint and a query returns the data for an entity + that is already managed by the UnitOfWork, the fields of the + existing entity will be refreshed. In normal operation a result-set + that loads data of an already existing entity is discarded in favor + of the already existing entity. +- Query::HINT\_CUSTOM\_TREE\_WALKERS - An array of additional + ``Doctrine\ORM\Query\TreeWalker`` instances that are attached to + the DQL query parsing process. + +Query Cache (DQL Query Only) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Parsing a DQL query and converting it into a SQL query against the +underlying database platform obviously has some overhead in +contrast to directly executing Native SQL queries. That is why +there is a dedicated Query Cache for caching the DQL parser +results. In combination with the use of wildcards you can reduce +the number of parsed queries in production to zero. + +The Query Cache Driver is passed from the +``Doctrine\ORM\Configuration`` instance to each +``Doctrine\ORM\Query`` instance by default and is also enabled by +default. This also means you don't regularly need to fiddle with +the parameters of the Query Cache, however if you do there are +several methods to interact with it: + + +- ``Query::setQueryCacheDriver($driver)`` - Allows to set a Cache + instance +- ``Query::setQueryCacheLifeTime($seconds = 3600)`` - Set lifetime + of the query caching. +- ``Query::expireQueryCache($bool)`` - Enforce the expiring of the + query cache if set to true. +- ``Query::getExpireQueryCache()`` +- ``Query::getQueryCacheDriver()`` +- ``Query::getQueryCacheLifeTime()`` + +First and Max Result Items (DQL Query Only) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can limit the number of results returned from a DQL query as +well as specify the starting offset, Doctrine then uses a strategy +of manipulating the select query to return only the requested +number of results: + + +- ``Query::setMaxResults($maxResults)`` +- ``Query::setFirstResult($offset)`` + +.. note:: + + If your query contains a fetch-joined collection + specifying the result limit methods are not working as you would + expect. Set Max Results restricts the number of database result + rows, however in the case of fetch-joined collections one root + entity might appear in many rows, effectively hydrating less than + the specified number of results. + +.. _dql-temporarily-change-fetch-mode: + +Temporarily change fetch mode in DQL +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +While normally all your associations are marked as lazy or extra lazy you will have cases where you are using DQL and don't want to +fetch join a second, third or fourth level of entities into your result, because of the increased cost of the SQL JOIN. You +can mark a many-to-one or one-to-one association as fetched temporarily to batch fetch these entities using a WHERE .. IN query. + +.. code-block:: php + + createQuery("SELECT u FROM MyProject\User u"); + $query->setFetchMode("MyProject\User", "address", \Doctrine\ORM\Mapping\ClassMetadata::FETCH_EAGER); + $query->execute(); + +Given that there are 10 users and corresponding addresses in the database the executed queries will look something like: + +.. code-block:: sql + + SELECT * FROM users; + SELECT * FROM address WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + +.. note:: + Changing the fetch mode during a query mostly makes sense for one-to-one and many-to-one relations. In that case, + all the necessary IDs are available after the root entity (``user`` in the above example) has been loaded. So, one + query per association can be executed to fetch all the referred-to entities (``address``). + + For one-to-many relations, changing the fetch mode to eager will cause to execute one query **for every root entity + loaded**. This gives no improvement over the ``lazy`` fetch mode which will also initialize the associations on + a one-by-one basis once they are accessed. + + +EBNF +---- + +The following context-free grammar, written in an EBNF variant, +describes the Doctrine Query Language. You can consult this grammar +whenever you are unsure about what is possible with DQL or what the +correct syntax for a particular query should be. + +Document syntax: +~~~~~~~~~~~~~~~~ + + +- non-terminals begin with an upper case character +- terminals begin with a lower case character +- parentheses (...) are used for grouping +- square brackets [...] are used for defining an optional part, + e.g. zero or one time +- curly brackets {...} are used for repetition, e.g. zero or more + times +- double quotation marks "..." define a terminal string +- a vertical bar \| represents an alternative + +Terminals +~~~~~~~~~ + + +- identifier (name, email, ...) must match ``[a-z_][a-z0-9_]*`` +- fully_qualified_name (Doctrine\Tests\Models\CMS\CmsUser) matches PHP's fully qualified class names +- aliased_name (CMS:CmsUser) uses two identifiers, one for the namespace alias and one for the class inside it +- string ('foo', 'bar''s house', '%ninja%', ...) +- char ('/', '\\', ' ', ...) +- integer (-1, 0, 1, 34, ...) +- float (-0.23, 0.007, 1.245342E+8, ...) +- boolean (false, true) + +Query Language +~~~~~~~~~~~~~~ + +.. code-block:: php + + QueryLanguage ::= SelectStatement | UpdateStatement | DeleteStatement + +Statements +~~~~~~~~~~ + +.. code-block:: php + + SelectStatement ::= SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] + UpdateStatement ::= UpdateClause [WhereClause] + DeleteStatement ::= DeleteClause [WhereClause] + +Identifiers +~~~~~~~~~~~ + +.. code-block:: php + + /* Alias Identification usage (the "u" of "u.name") */ + IdentificationVariable ::= identifier + + /* Alias Identification declaration (the "u" of "FROM User u") */ + AliasIdentificationVariable :: = identifier + + /* identifier that must be a class name (the "User" of "FROM User u"), possibly as a fully qualified class name or namespace-aliased */ + AbstractSchemaName ::= fully_qualified_name | aliased_name | identifier + + /* Alias ResultVariable declaration (the "total" of "COUNT(*) AS total") */ + AliasResultVariable = identifier + + /* ResultVariable identifier usage of mapped field aliases (the "total" of "COUNT(*) AS total") */ + ResultVariable = identifier + + /* identifier that must be a field (the "name" of "u.name") */ + /* This is responsible to know if the field exists in Object, no matter if it's a relation or a simple field */ + FieldIdentificationVariable ::= identifier + + /* identifier that must be a collection-valued association field (to-many) (the "Phonenumbers" of "u.Phonenumbers") */ + CollectionValuedAssociationField ::= FieldIdentificationVariable + + /* identifier that must be a single-valued association field (to-one) (the "Group" of "u.Group") */ + SingleValuedAssociationField ::= FieldIdentificationVariable + + /* identifier that must be an embedded class state field */ + EmbeddedClassStateField ::= FieldIdentificationVariable + + /* identifier that must be a simple state field (name, email, ...) (the "name" of "u.name") */ + /* The difference between this and FieldIdentificationVariable is only semantical, because it points to a single field (not mapping to a relation) */ + SimpleStateField ::= FieldIdentificationVariable + +Path Expressions +~~~~~~~~~~~~~~~~ + +.. code-block:: php + + /* "u.Group" or "u.Phonenumbers" declarations */ + JoinAssociationPathExpression ::= IdentificationVariable "." (CollectionValuedAssociationField | SingleValuedAssociationField) + + /* "u.Group" or "u.Phonenumbers" usages */ + AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression + + /* "u.name" or "u.Group" */ + SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression + + /* "u.name" or "u.Group.name" */ + StateFieldPathExpression ::= IdentificationVariable "." StateField + + /* "u.Group" */ + SingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField + + /* "u.Group.Permissions" */ + CollectionValuedPathExpression ::= IdentificationVariable "." CollectionValuedAssociationField + + /* "name" */ + StateField ::= {EmbeddedClassStateField "."}* SimpleStateField + +Clauses +~~~~~~~ + +.. code-block:: php + + SelectClause ::= "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression}* + SimpleSelectClause ::= "SELECT" ["DISTINCT"] SimpleSelectExpression + UpdateClause ::= "UPDATE" AbstractSchemaName ["AS"] AliasIdentificationVariable "SET" UpdateItem {"," UpdateItem}* + DeleteClause ::= "DELETE" ["FROM"] AbstractSchemaName ["AS"] AliasIdentificationVariable + FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}* + SubselectFromClause ::= "FROM" SubselectIdentificationVariableDeclaration {"," SubselectIdentificationVariableDeclaration}* + WhereClause ::= "WHERE" ConditionalExpression + HavingClause ::= "HAVING" ConditionalExpression + GroupByClause ::= "GROUP" "BY" GroupByItem {"," GroupByItem}* + OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}* + Subselect ::= SimpleSelectClause SubselectFromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] + +Items +~~~~~ + +.. code-block:: php + + UpdateItem ::= SingleValuedPathExpression "=" NewValue + OrderByItem ::= (SimpleArithmeticExpression | SingleValuedPathExpression | ScalarExpression | ResultVariable | FunctionDeclaration) ["ASC" | "DESC"] + GroupByItem ::= IdentificationVariable | ResultVariable | SingleValuedPathExpression + NewValue ::= SimpleArithmeticExpression | "NULL" + +From, Join and Index by +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: php + + IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {Join}* + SubselectIdentificationVariableDeclaration ::= IdentificationVariableDeclaration + RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable + JoinAssociationDeclaration ::= JoinAssociationPathExpression ["AS"] AliasIdentificationVariable [IndexBy] + Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" (JoinAssociationDeclaration | RangeVariableDeclaration) ["WITH" ConditionalExpression] + IndexBy ::= "INDEX" "BY" StateFieldPathExpression + +Select Expressions +~~~~~~~~~~~~~~~~~~ + +.. code-block:: php + + SelectExpression ::= (IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | PartialObjectExpression | "(" Subselect ")" | CaseExpression | NewObjectExpression) [["AS"] ["HIDDEN"] AliasResultVariable] + SimpleSelectExpression ::= (StateFieldPathExpression | IdentificationVariable | FunctionDeclaration | AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] AliasResultVariable] + PartialObjectExpression ::= "PARTIAL" IdentificationVariable "." PartialFieldSet + PartialFieldSet ::= "{" SimpleStateField {"," SimpleStateField}* "}" + NewObjectExpression ::= "NEW" AbstractSchemaName "(" NewObjectArg {"," NewObjectArg}* ")" + NewObjectArg ::= ScalarExpression | "(" Subselect ")" + +Conditional Expressions +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: php + + ConditionalExpression ::= ConditionalTerm {"OR" ConditionalTerm}* + ConditionalTerm ::= ConditionalFactor {"AND" ConditionalFactor}* + ConditionalFactor ::= ["NOT"] ConditionalPrimary + ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")" + SimpleConditionalExpression ::= ComparisonExpression | BetweenExpression | LikeExpression | + InExpression | NullComparisonExpression | ExistsExpression | + EmptyCollectionComparisonExpression | CollectionMemberExpression | + InstanceOfExpression + + +Collection Expressions +~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: php + + EmptyCollectionComparisonExpression ::= CollectionValuedPathExpression "IS" ["NOT"] "EMPTY" + CollectionMemberExpression ::= EntityExpression ["NOT"] "MEMBER" ["OF"] CollectionValuedPathExpression + +Literal Values +~~~~~~~~~~~~~~ + +.. code-block:: php + + Literal ::= string | char | integer | float | boolean + InParameter ::= Literal | InputParameter + +Input Parameter +~~~~~~~~~~~~~~~ + +.. code-block:: php + + InputParameter ::= PositionalParameter | NamedParameter + PositionalParameter ::= "?" integer + NamedParameter ::= ":" string + +Arithmetic Expressions +~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: php + + ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")" + SimpleArithmeticExpression ::= ArithmeticTerm {("+" | "-") ArithmeticTerm}* + ArithmeticTerm ::= ArithmeticFactor {("*" | "/") ArithmeticFactor}* + ArithmeticFactor ::= [("+" | "-")] ArithmeticPrimary + ArithmeticPrimary ::= SingleValuedPathExpression | Literal | "(" SimpleArithmeticExpression ")" + | FunctionsReturningNumerics | AggregateExpression | FunctionsReturningStrings + | FunctionsReturningDatetime | IdentificationVariable | ResultVariable + | InputParameter | CaseExpression + +Scalar and Type Expressions +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: php + + ScalarExpression ::= SimpleArithmeticExpression | StringPrimary | DateTimePrimary | StateFieldPathExpression | BooleanPrimary | CaseExpression | InstanceOfExpression + StringExpression ::= StringPrimary | ResultVariable | "(" Subselect ")" + StringPrimary ::= StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression | CaseExpression + BooleanExpression ::= BooleanPrimary | "(" Subselect ")" + BooleanPrimary ::= StateFieldPathExpression | boolean | InputParameter + EntityExpression ::= SingleValuedAssociationPathExpression | SimpleEntityExpression + SimpleEntityExpression ::= IdentificationVariable | InputParameter + DatetimeExpression ::= DatetimePrimary | "(" Subselect ")" + DatetimePrimary ::= StateFieldPathExpression | InputParameter | FunctionsReturningDatetime | AggregateExpression + +.. note:: + + Parts of CASE expressions are not yet implemented. + +Aggregate Expressions +~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: php + + AggregateExpression ::= ("AVG" | "MAX" | "MIN" | "SUM" | "COUNT") "(" ["DISTINCT"] SimpleArithmeticExpression ")" + +Case Expressions +~~~~~~~~~~~~~~~~ + +.. code-block:: php + + CaseExpression ::= GeneralCaseExpression | SimpleCaseExpression | CoalesceExpression | NullifExpression + GeneralCaseExpression ::= "CASE" WhenClause {WhenClause}* "ELSE" ScalarExpression "END" + WhenClause ::= "WHEN" ConditionalExpression "THEN" ScalarExpression + SimpleCaseExpression ::= "CASE" CaseOperand SimpleWhenClause {SimpleWhenClause}* "ELSE" ScalarExpression "END" + CaseOperand ::= StateFieldPathExpression | TypeDiscriminator + SimpleWhenClause ::= "WHEN" ScalarExpression "THEN" ScalarExpression + CoalesceExpression ::= "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")" + NullifExpression ::= "NULLIF" "(" ScalarExpression "," ScalarExpression ")" + +Other Expressions +~~~~~~~~~~~~~~~~~ + +QUANTIFIED/BETWEEN/COMPARISON/LIKE/NULL/EXISTS + +.. code-block:: php + + QuantifiedExpression ::= ("ALL" | "ANY" | "SOME") "(" Subselect ")" + BetweenExpression ::= ArithmeticExpression ["NOT"] "BETWEEN" ArithmeticExpression "AND" ArithmeticExpression + ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression ) + InExpression ::= SingleValuedPathExpression ["NOT"] "IN" "(" (InParameter {"," InParameter}* | Subselect) ")" + InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (InstanceOfParameter | "(" InstanceOfParameter {"," InstanceOfParameter}* ")") + InstanceOfParameter ::= AbstractSchemaName | InputParameter + LikeExpression ::= StringExpression ["NOT"] "LIKE" StringPrimary ["ESCAPE" char] + NullComparisonExpression ::= (InputParameter | NullIfExpression | CoalesceExpression | AggregateExpression | FunctionDeclaration | IdentificationVariable | SingleValuedPathExpression | ResultVariable) "IS" ["NOT"] "NULL" + ExistsExpression ::= ["NOT"] "EXISTS" "(" Subselect ")" + ComparisonOperator ::= "=" | "<" | "<=" | "<>" | ">" | ">=" | "!=" + +Functions +~~~~~~~~~ + +.. code-block:: php + + FunctionDeclaration ::= FunctionsReturningStrings | FunctionsReturningNumerics | FunctionsReturningDateTime + + FunctionsReturningNumerics ::= + "LENGTH" "(" StringPrimary ")" | + "LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" | + "ABS" "(" SimpleArithmeticExpression ")" | + "SQRT" "(" SimpleArithmeticExpression ")" | + "MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" | + "SIZE" "(" CollectionValuedPathExpression ")" | + "DATE_DIFF" "(" ArithmeticPrimary "," ArithmeticPrimary ")" | + "BIT_AND" "(" ArithmeticPrimary "," ArithmeticPrimary ")" | + "BIT_OR" "(" ArithmeticPrimary "," ArithmeticPrimary ")" + + FunctionsReturningDateTime ::= + "CURRENT_DATE" | + "CURRENT_TIME" | + "CURRENT_TIMESTAMP" | + "DATE_ADD" "(" ArithmeticPrimary "," ArithmeticPrimary "," StringPrimary ")" | + "DATE_SUB" "(" ArithmeticPrimary "," ArithmeticPrimary "," StringPrimary ")" + + FunctionsReturningStrings ::= + "CONCAT" "(" StringPrimary "," StringPrimary ")" | + "SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")" | + "TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")" | + "LOWER" "(" StringPrimary ")" | + "UPPER" "(" StringPrimary ")" | + "IDENTITY" "(" SingleValuedAssociationPathExpression {"," string} ")" + + diff --git a/vendor/doctrine/orm/docs/en/reference/events.rst b/vendor/doctrine/orm/docs/en/reference/events.rst new file mode 100644 index 0000000..9bcafe4 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/events.rst @@ -0,0 +1,989 @@ +Events +====== + +Doctrine 2 features a lightweight event system that is part of the +Common package. Doctrine uses it to dispatch system events, mainly +:ref:`lifecycle events `. +You can also use it for your own custom events. + +The Event System +---------------- + +The event system is controlled by the ``EventManager``. It is the +central point of Doctrine's event listener system. Listeners are +registered on the manager and events are dispatched through the +manager. + +.. code-block:: php + + addEventListener(array(self::preFoo, self::postFoo), $this); + } + + public function preFoo(EventArgs $e) + { + $this->preFooInvoked = true; + } + + public function postFoo(EventArgs $e) + { + $this->postFooInvoked = true; + } + } + + // Create a new instance + $test = new TestEvent($evm); + +Events can be dispatched by using the ``dispatchEvent()`` method. + +.. code-block:: php + + dispatchEvent(TestEvent::preFoo); + $evm->dispatchEvent(TestEvent::postFoo); + +You can easily remove a listener with the ``removeEventListener()`` +method. + +.. code-block:: php + + removeEventListener(array(self::preFoo, self::postFoo), $this); + +The Doctrine 2 event system also has a simple concept of event +subscribers. We can define a simple ``TestEventSubscriber`` class +which implements the ``\Doctrine\Common\EventSubscriber`` interface +and implements a ``getSubscribedEvents()`` method which returns an +array of events it should be subscribed to. + +.. code-block:: php + + preFooInvoked = true; + } + + public function getSubscribedEvents() + { + return array(TestEvent::preFoo); + } + } + + $eventSubscriber = new TestEventSubscriber(); + $evm->addEventSubscriber($eventSubscriber); + +.. note:: + + The array to return in the ``getSubscribedEvents`` method is a simple array + with the values being the event names. The subscriber must have a method + that is named exactly like the event. + +Now when you dispatch an event, any event subscribers will be +notified for that event. + +.. code-block:: php + + dispatchEvent(TestEvent::preFoo); + +Now you can test the ``$eventSubscriber`` instance to see if the +``preFoo()`` method was invoked. + +.. code-block:: php + + preFooInvoked) { + echo 'pre foo invoked!'; + } + +Naming convention +~~~~~~~~~~~~~~~~~ + +Events being used with the Doctrine 2 EventManager are best named +with camelcase and the value of the corresponding constant should +be the name of the constant itself, even with spelling. This has +several reasons: + + +- It is easy to read. +- Simplicity. +- Each method within an EventSubscriber is named after the + corresponding constant's value. If the constant's name and value differ + it contradicts the intention of using the constant and makes your code + harder to maintain. + +An example for a correct notation can be found in the example +``TestEvent`` above. + +.. _reference-events-lifecycle-events: + +Lifecycle Events +---------------- + +The EntityManager and UnitOfWork trigger a bunch of events during +the life-time of their registered entities. + + +- preRemove - The preRemove event occurs for a given entity before + the respective EntityManager remove operation for that entity is + executed. It is not called for a DQL DELETE statement. +- postRemove - The postRemove event occurs for an entity after the + entity has been deleted. It will be invoked after the database + delete operations. It is not called for a DQL DELETE statement. +- prePersist - The prePersist event occurs for a given entity + before the respective EntityManager persist operation for that + entity is executed. It should be noted that this event is only triggered on + *initial* persist of an entity (i.e. it does not trigger on future updates). +- postPersist - The postPersist event occurs for an entity after + the entity has been made persistent. It will be invoked after the + database insert operations. Generated primary key values are + available in the postPersist event. +- preUpdate - The preUpdate event occurs before the database + update operations to entity data. It is not called for a DQL UPDATE statement + nor when the computed changeset is empty. +- postUpdate - The postUpdate event occurs after the database + update operations to entity data. It is not called for a DQL UPDATE statement. +- postLoad - The postLoad event occurs for an entity after the + entity has been loaded into the current EntityManager from the + database or after the refresh operation has been applied to it. +- loadClassMetadata - The loadClassMetadata event occurs after the + mapping metadata for a class has been loaded from a mapping source + (annotations/xml/yaml). This event is not a lifecycle callback. +- onClassMetadataNotFound - Loading class metadata for a particular + requested class name failed. Manipulating the given event args instance + allows providing fallback metadata even when no actual metadata exists + or could be found. This event is not a lifecycle callback. +- preFlush - The preFlush event occurs at the very beginning of a flush + operation. +- onFlush - The onFlush event occurs after the change-sets of all + managed entities are computed. This event is not a lifecycle + callback. +- postFlush - The postFlush event occurs at the end of a flush operation. This + event is not a lifecycle callback. +- onClear - The onClear event occurs when the EntityManager#clear() operation is + invoked, after all references to entities have been removed from the unit of + work. This event is not a lifecycle callback. + +.. warning:: + + Note that, when using ``Doctrine\ORM\AbstractQuery#iterate()``, ``postLoad`` + events will be executed immediately after objects are being hydrated, and therefore + associations are not guaranteed to be initialized. It is not safe to combine + usage of ``Doctrine\ORM\AbstractQuery#iterate()`` and ``postLoad`` event + handlers. + +.. warning:: + + Note that the postRemove event or any events triggered after an entity removal + can receive an uninitializable proxy in case you have configured an entity to + cascade remove relations. In this case, you should load yourself the proxy in + the associated pre event. + +You can access the Event constants from the ``Events`` class in the +ORM package. + +.. code-block:: php + + createdAt = date('Y-m-d H:i:s'); + } + + /** @PrePersist */ + public function doOtherStuffOnPrePersist() + { + $this->value = 'changed from prePersist callback!'; + } + + /** @PostPersist */ + public function doStuffOnPostPersist() + { + $this->value = 'changed from postPersist callback!'; + } + + /** @PostLoad */ + public function doStuffOnPostLoad() + { + $this->value = 'changed from postLoad callback!'; + } + + /** @PreUpdate */ + public function doStuffOnPreUpdate() + { + $this->value = 'changed from preUpdate callback!'; + } + } + +Note that the methods set as lifecycle callbacks need to be public and, +when using these annotations, you have to apply the +``@HasLifecycleCallbacks`` marker annotation on the entity class. + +If you want to register lifecycle callbacks from YAML or XML you +can do it with the following. + +.. code-block:: yaml + + User: + type: entity + fields: + # ... + name: + type: string(50) + lifecycleCallbacks: + prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersist ] + postPersist: [ doStuffOnPostPersist ] + +In YAML the ``key`` of the lifecycleCallbacks entry is the event that you +are triggering on and the value is the method (or methods) to call. The allowed +event types are the ones listed in the previous Lifecycle Events section. + +XML would look something like this: + +.. code-block:: xml + + + + + + + + + + + + + + + + +In XML the ``type`` of the lifecycle-callback entry is the event that you +are triggering on and the ``method`` is the method to call. The allowed event +types are the ones listed in the previous Lifecycle Events section. + +When using YAML or XML you need to remember to create public methods to match the +callback names you defined. E.g. in these examples ``doStuffOnPrePersist()``, +``doOtherStuffOnPrePersist()`` and ``doStuffOnPostPersist()`` methods need to be +defined on your ``User`` model. + +.. code-block:: php + + hasChangedField('username')) { + // Do something when the username is changed. + } + } + } + +Listening and subscribing to Lifecycle Events +--------------------------------------------- + +Lifecycle event listeners are much more powerful than the simple +lifecycle callbacks that are defined on the entity classes. They +sit at a level above the entities and allow you to implement re-usable +behaviors across different entity classes. + +Note that they require much more detailed knowledge about the inner +workings of the EntityManager and UnitOfWork. Please read the +:ref:`reference-events-implementing-listeners` section carefully if you +are trying to write your own listener. + +For event subscribers, there are no surprises. They declare the +lifecycle events in their ``getSubscribedEvents`` method and provide +public methods that expect the relevant arguments. + +A lifecycle event listener looks like the following: + +.. code-block:: php + + getObject(); + $entityManager = $args->getObjectManager(); + + // perhaps you only want to act on some "Product" entity + if ($entity instanceof Product) { + // do something with the Product + } + } + } + +A lifecycle event subscriber may look like this: + +.. code-block:: php + + getObject(); + $entityManager = $args->getObjectManager(); + + // perhaps you only want to act on some "Product" entity + if ($entity instanceof Product) { + // do something with the Product + } + } + +.. note:: + + Lifecycle events are triggered for all entities. It is the responsibility + of the listeners and subscribers to check if the entity is of a type + it wants to handle. + +To register an event listener or subscriber, you have to hook it into the +EventManager that is passed to the EntityManager factory: + +.. code-block:: php + + addEventListener(array(Events::preUpdate), new MyEventListener()); + $eventManager->addEventSubscriber(new MyEventSubscriber()); + + $entityManager = EntityManager::create($dbOpts, $config, $eventManager); + +You can also retrieve the event manager instance after the +EntityManager was created: + +.. code-block:: php + + getEventManager()->addEventListener(array(Events::preUpdate), new MyEventListener()); + $entityManager->getEventManager()->addEventSubscriber(new MyEventSubscriber()); + +.. _reference-events-implementing-listeners: + +Implementing Event Listeners +---------------------------- + +This section explains what is and what is not allowed during +specific lifecycle events of the UnitOfWork. Although you get +passed the EntityManager in all of these events, you have to follow +these restrictions very carefully since operations in the wrong +event may produce lots of different errors, such as inconsistent +data and lost updates/persists/removes. + +For the described events that are also lifecycle callback events +the restrictions apply as well, with the additional restriction +that (prior to version 2.4) you do not have access to the +EntityManager or UnitOfWork APIs inside these events. + +prePersist +~~~~~~~~~~ + +There are two ways for the ``prePersist`` event to be triggered. +One is obviously when you call ``EntityManager#persist()``. The +event is also called for all cascaded associations. + +There is another way for ``prePersist`` to be called, inside the +``flush()`` method when changes to associations are computed and +this association is marked as cascade persist. Any new entity found +during this operation is also persisted and ``prePersist`` called +on it. This is called "persistence by reachability". + +In both cases you get passed a ``LifecycleEventArgs`` instance +which has access to the entity and the entity manager. + +The following restrictions apply to ``prePersist``: + + +- If you are using a PrePersist Identity Generator such as + sequences the ID value will *NOT* be available within any + PrePersist events. +- Doctrine will not recognize changes made to relations in a prePersist + event. This includes modifications to + collections such as additions, removals or replacement. + +preRemove +~~~~~~~~~ + +The ``preRemove`` event is called on every entity when its passed +to the ``EntityManager#remove()`` method. It is cascaded for all +associations that are marked as cascade delete. + +There are no restrictions to what methods can be called inside the +``preRemove`` event, except when the remove method itself was +called during a flush operation. + +preFlush +~~~~~~~~ + +``preFlush`` is called at ``EntityManager#flush()`` before +anything else. ``EntityManager#flush()`` should not be called inside +its listeners, since `preFlush` event is dispatched in it, which would +result in infinite loop. + +.. code-block:: php + + getEntityManager(); + $uow = $em->getUnitOfWork(); + + foreach ($uow->getScheduledEntityInsertions() as $entity) { + + } + + foreach ($uow->getScheduledEntityUpdates() as $entity) { + + } + + foreach ($uow->getScheduledEntityDeletions() as $entity) { + + } + + foreach ($uow->getScheduledCollectionDeletions() as $col) { + + } + + foreach ($uow->getScheduledCollectionUpdates() as $col) { + + } + } + } + +The following restrictions apply to the onFlush event: + + +- If you create and persist a new entity in ``onFlush``, then + calling ``EntityManager#persist()`` is not enough. + You have to execute an additional call to + ``$unitOfWork->computeChangeSet($classMetadata, $entity)``. +- Changing primitive fields or associations requires you to + explicitly trigger a re-computation of the changeset of the + affected entity. This can be done by calling + ``$unitOfWork->recomputeSingleEntityChangeSet($classMetadata, $entity)``. + +postFlush +~~~~~~~~~ + +``postFlush`` is called at the end of ``EntityManager#flush()``. +``EntityManager#flush()`` can **NOT** be called safely inside its listeners. + +.. code-block:: php + + getEntity() instanceof User) { + if ($eventArgs->hasChangedField('name') && $eventArgs->getNewValue('name') == 'Alice') { + $eventArgs->setNewValue('name', 'Bob'); + } + } + } + } + +You could also use this listener to implement validation of all the +fields that have changed. This is more efficient than using a +lifecycle callback when there are expensive validations to call: + +.. code-block:: php + + getEntity() instanceof Account) { + if ($eventArgs->hasChangedField('creditCard')) { + $this->validateCreditCard($eventArgs->getNewValue('creditCard')); + } + } + } + + private function validateCreditCard($no) + { + // throw an exception to interrupt flush event. Transaction will be rolled back. + } + } + +Restrictions for this event: + + +- Changes to associations of the passed entities are not + recognized by the flush operation anymore. +- Changes to fields of the passed entities are not recognized by + the flush operation anymore, use the computed change-set passed to + the event to modify primitive field values, e.g. use + ``$eventArgs->setNewValue($field, $value);`` as in the Alice to Bob example above. +- Any calls to ``EntityManager#persist()`` or + ``EntityManager#remove()``, even in combination with the UnitOfWork + API are strongly discouraged and don't work as expected outside the + flush operation. + +postUpdate, postRemove, postPersist +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The three post events are called inside ``EntityManager#flush()``. +Changes in here are not relevant to the persistence in the +database, but you can use these events to alter non-persistable items, +like non-mapped fields, logging or even associated classes that are +not directly mapped by Doctrine. + +postLoad +~~~~~~~~ + +This event is called after an entity is constructed by the +EntityManager. + +Entity listeners +---------------- + +.. versionadded:: 2.4 + +An entity listener is a lifecycle listener class used for an entity. + +- The entity listener's mapping may be applied to an entity class or mapped superclass. +- An entity listener is defined by mapping the entity class with the corresponding mapping. + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + .. code-block:: yaml + + MyProject\Entity\User: + type: entity + entityListeners: + UserListener: + # .... + +.. _reference-entity-listeners: + +Entity listeners class +~~~~~~~~~~~~~~~~~~~~~~ + +An ``Entity Listener`` could be any class, by default it should be a class with a no-arg constructor. + +- Different from :ref:`reference-events-implementing-listeners` an ``Entity Listener`` is invoked just to the specified entity +- An entity listener method receives two arguments, the entity instance and the lifecycle event. +- The callback method can be defined by naming convention or specifying a method mapping. +- When a listener mapping is not given the parser will use the naming convention to look for a matching method, + e.g. it will look for a public ``preUpdate()`` method if you are listening to the ``preUpdate`` event. +- When a listener mapping is given the parser will not look for any methods using the naming convention. + +.. code-block:: php + + + + + + + + + + + + + + + + + + + + + + .. code-block:: yaml + + MyProject\Entity\User: + type: entity + entityListeners: + UserListener: + preFlush: [preFlushHandler] + postLoad: [postLoadHandler] + + postPersist: [postPersistHandler] + prePersist: [prePersistHandler] + + postUpdate: [postUpdateHandler] + preUpdate: [preUpdateHandler] + + postRemove: [postRemoveHandler] + preRemove: [preRemoveHandler] + # .... + +.. note:: + + The order of execution of multiple methods for the same event (e.g. multiple @PrePersist) is not guaranteed. + + +Entity listeners resolver +~~~~~~~~~~~~~~~~~~~~~~~~~~ +Doctrine invokes the listener resolver to get the listener instance. + +- A resolver allows you register a specific entity listener instance. +- You can also implement your own resolver by extending ``Doctrine\ORM\Mapping\DefaultEntityListenerResolver`` or implementing ``Doctrine\ORM\Mapping\EntityListenerResolver`` + +Specifying an entity listener instance : + +.. code-block:: php + + service = $service; + } + + public function preUpdate(User $user, PreUpdateEventArgs $event) + { + $this->service->doSomething($user); + } + } + + // register a entity listener. + $listener = $container->get('user_listener'); + $em->getConfiguration()->getEntityListenerResolver()->register($listener); + +Implementing your own resolver : + +.. code-block:: php + + container = $container; + } + + public function resolve($className) + { + // resolve the service id by the given class name; + $id = 'user_listener'; + + return $this->container->get($id); + } + } + + // Configure the listener resolver only before instantiating the EntityManager + $configurations->setEntityListenerResolver(new MyEntityListenerResolver); + EntityManager::create(.., $configurations, ..); + +Load ClassMetadata Event +------------------------ + +When the mapping information for an entity is read, it is populated +in to a ``ClassMetadataInfo`` instance. You can hook in to this +process and manipulate the instance. + +.. code-block:: php + + getMetadataFactory(); + $evm = $em->getEventManager(); + $evm->addEventListener(Events::loadClassMetadata, $test); + + class TestEvent + { + public function loadClassMetadata(\Doctrine\ORM\Event\LoadClassMetadataEventArgs $eventArgs) + { + $classMetadata = $eventArgs->getClassMetadata(); + $fieldMapping = array( + 'fieldName' => 'about', + 'type' => 'string', + 'length' => 255 + ); + $classMetadata->mapField($fieldMapping); + } + } + + diff --git a/vendor/doctrine/orm/docs/en/reference/faq.rst b/vendor/doctrine/orm/docs/en/reference/faq.rst new file mode 100644 index 0000000..ca7784e --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/faq.rst @@ -0,0 +1,233 @@ +Frequently Asked Questions +========================== + +.. note:: + + This FAQ is a work in progress. We will add lots of questions and not answer them right away just to remember + what is often asked. If you stumble across an unanswered question please write a mail to the mailing-list or + join the #doctrine channel on Freenode IRC. + +Database Schema +--------------- + +How do I set the charset and collation for MySQL tables? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can't set these values inside the annotations, yml or xml mapping files. To make a database +work with the default charset and collation you should configure MySQL to use it as default charset, +or create the database with charset and collation details. This way they get inherited to all newly +created database tables and columns. + +Entity Classes +-------------- + +How can I add default values to a column? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Doctrine does not support to set the default values in columns through the "DEFAULT" keyword in SQL. +This is not necessary however, you can just use your class properties as default values. These are then used +upon insert: + +.. code-block:: php + + class User + { + const STATUS_DISABLED = 0; + const STATUS_ENABLED = 1; + + private $algorithm = "sha1"; + private $status = self:STATUS_DISABLED; + } + +. + +Mapping +------- + +Why do I get exceptions about unique constraint failures during ``$em->flush()``? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Doctrine does not check if you are re-adding entities with a primary key that already exists +or adding entities to a collection twice. You have to check for both conditions yourself +in the code before calling ``$em->flush()`` if you know that unique constraint failures +can occur. + +In `Symfony2 `_ for example there is a Unique Entity Validator +to achieve this task. + +For collections you can check with ``$collection->contains($entity)`` if an entity is already +part of this collection. For a FETCH=LAZY collection this will initialize the collection, +however for FETCH=EXTRA_LAZY this method will use SQL to determine if this entity is already +part of the collection. + +Associations +------------ + +What is wrong when I get an InvalidArgumentException "A new entity was found through the relationship.."? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This exception is thrown during ``EntityManager#flush()`` when there exists an object in the identity map +that contains a reference to an object that Doctrine does not know about. Say for example you grab +a "User"-entity from the database with a specific id and set a completely new object into one of the associations +of the User object. If you then call ``EntityManager#flush()`` without letting Doctrine know about +this new object using ``EntityManager#persist($newObject)`` you will see this exception. + +You can solve this exception by: + +* Calling ``EntityManager#persist($newObject)`` on the new object +* Using cascade=persist on the association that contains the new object + +How can I filter an association? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Natively you can't filter associations in 2.0 and 2.1. You should use DQL queries to query for the filtered set of entities. + +I call clear() on a One-To-Many collection but the entities are not deleted +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is an expected behavior that has to do with the inverse/owning side handling of Doctrine. +By definition a One-To-Many association is on the inverse side, that means changes to it +will not be recognized by Doctrine. + +If you want to perform the equivalent of the clear operation you have to iterate the +collection and set the owning side many-to-one reference to NULL as well to detach all entities +from the collection. This will trigger the appropriate UPDATE statements on the database. + +How can I add columns to a many-to-many table? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The many-to-many association is only supporting foreign keys in the table definition +To work with many-to-many tables containing extra columns you have to use the +foreign keys as primary keys feature of Doctrine introduced in version 2.1. + +See :doc:`the tutorial on composite primary keys for more information<../tutorials/composite-primary-keys>`. + + +How can i paginate fetch-joined collections? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are issuing a DQL statement that fetches a collection as well you cannot easily iterate +over this collection using a LIMIT statement (or vendor equivalent). + +Doctrine does not offer a solution for this out of the box but there are several extensions +that do: + +* `DoctrineExtensions `_ +* `Pagerfanta `_ + +Why does pagination not work correctly with fetch joins? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Pagination in Doctrine uses a LIMIT clause (or vendor equivalent) to restrict the results. +However when fetch-joining this is not returning the correct number of results since joining +with a one-to-many or many-to-many association multiplies the number of rows by the number +of associated entities. + +See the previous question for a solution to this task. + +Inheritance +----------- + +Can I use Inheritance with Doctrine 2? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Yes, you can use Single- or Joined-Table Inheritance in Doctrine 2. + +See the documentation chapter on :doc:`inheritance mapping ` for +the details. + +Why does Doctrine not create proxy objects for my inheritance hierarchy? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you set a many-to-one or one-to-one association target-entity to any parent class of +an inheritance hierarchy Doctrine does not know what PHP class the foreign is actually of. +To find this out it has to execute a SQL query to look this information up in the database. + +EntityGenerator +--------------- + +Why does the EntityGenerator not do X? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The EntityGenerator is not a full fledged code-generator that solves all tasks. Code-Generation +is not a first-class priority in Doctrine 2 anymore (compared to Doctrine 1). The EntityGenerator +is supposed to kick-start you, but not towards 100%. + +Why does the EntityGenerator not generate inheritance correctly? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Just from the details of the discriminator map the EntityGenerator cannot guess the inheritance hierarchy. +This is why the generation of inherited entities does not fully work. You have to adjust some additional +code to get this one working correctly. + +Performance +----------- + +Why is an extra SQL query executed every time I fetch an entity with a one-to-one relation? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If Doctrine detects that you are fetching an inverse side one-to-one association +it has to execute an additional query to load this object, because it cannot know +if there is no such object (setting null) or if it should set a proxy and which id this proxy has. + +To solve this problem currently a query has to be executed to find out this information. + +Doctrine Query Language +----------------------- + +What is DQL? +~~~~~~~~~~~~ + +DQL stands for Doctrine Query Language, a query language that very much looks like SQL +but has some important benefits when using Doctrine: + +- It uses class names and fields instead of tables and columns, separating concerns between backend and your object model. +- It utilizes the metadata defined to offer a range of shortcuts when writing. For example you do not have to specify the ON clause of joins, since Doctrine already knows about them. +- It adds some functionality that is related to object management and transforms them into SQL. + +It also has some drawbacks of course: + +- The syntax is slightly different to SQL so you have to learn and remember the differences. +- To be vendor independent it can only implement a subset of all the existing SQL dialects. Vendor specific functionality and optimizations cannot be used through DQL unless implemented by you explicitly. +- For some DQL constructs subselects are used which are known to be slow in MySQL. + +Can I sort by a function (for example ORDER BY RAND()) in DQL? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +No, it is not supported to sort by function in DQL. If you need this functionality you should either +use a native-query or come up with another solution. As a side note: Sorting with ORDER BY RAND() is painfully slow +starting with 1000 rows. + +Is it better to write DQL or to generate it with the query builder? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The purpose of the ``QueryBuilder`` is to generate DQL dynamically, +which is useful when you have optional filters, conditional joins, etc. + +But the ``QueryBuilder`` is not an alternative to DQL, it actually generates DQL +queries at runtime, which are then interpreted by Doctrine. This means that +using the ``QueryBuilder`` to build and run a query is actually always slower +than only running the corresponding DQL query. + +So if you only need to generate a query and bind parameters to it, +you should use plain DQL, as this is a simpler and much more readable solution. +You should only use the ``QueryBuilder`` when you can't achieve what you want to do with a DQL query. + +A Query fails, how can I debug it? +---------------------------------- + +First, if you are using the QueryBuilder you can use +``$queryBuilder->getDQL()`` to get the DQL string of this query. The +corresponding SQL you can get from the Query instance by calling +``$query->getSQL()``. + +.. code-block:: php + + createQuery($dql); + var_dump($query->getSQL()); + + $qb = $entityManager->createQueryBuilder(); + $qb->select('u')->from('User', 'u'); + var_dump($qb->getDQL()); diff --git a/vendor/doctrine/orm/docs/en/reference/filters.rst b/vendor/doctrine/orm/docs/en/reference/filters.rst new file mode 100644 index 0000000..8783526 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/filters.rst @@ -0,0 +1,93 @@ +Filters +======= + +.. versionadded:: 2.2 + +Doctrine 2.2 features a filter system that allows the developer to add SQL to +the conditional clauses of queries, regardless the place where the SQL is +generated (e.g. from a DQL query, or by loading associated entities). + +The filter functionality works on SQL level. Whether a SQL query is generated +in a Persister, during lazy loading, in extra lazy collections or from DQL. +Each time the system iterates over all the enabled filters, adding a new SQL +part as a filter returns. + +By adding SQL to the conditional clauses of queries, the filter system filters +out rows belonging to the entities at the level of the SQL result set. This +means that the filtered entities are never hydrated (which can be expensive). + + +Example filter class +-------------------- +Throughout this document the example ``MyLocaleFilter`` class will be used to +illustrate how the filter feature works. A filter class must extend the base +``Doctrine\ORM\Query\Filter\SQLFilter`` class and implement the ``addFilterConstraint`` +method. The method receives the ``ClassMetadata`` of the filtered entity and the +table alias of the SQL table of the entity. + +.. note:: + + In the case of joined or single table inheritance, you always get passed the ClassMetadata of the + inheritance root. This is necessary to avoid edge cases that would break the SQL when applying the filters. + +Parameters for the query should be set on the filter object by +``SQLFilter#setParameter()``. Only parameters set via this function can be used +in filters. The ``SQLFilter#getParameter()`` function takes care of the +proper quoting of parameters. + +.. code-block:: php + + reflClass->implementsInterface('LocaleAware')) { + return ""; + } + + return $targetTableAlias.'.locale = ' . $this->getParameter('locale'); // getParameter applies quoting automatically + } + } + + +Configuration +------------- +Filter classes are added to the configuration as following: + +.. code-block:: php + + addFilter("locale", "\Doctrine\Tests\ORM\Functional\MyLocaleFilter"); + + +The ``Configuration#addFilter()`` method takes a name for the filter and the name of the +class responsible for the actual filtering. + + +Disabling/Enabling Filters and Setting Parameters +--------------------------------------------------- +Filters can be disabled and enabled via the ``FilterCollection`` which is +stored in the ``EntityManager``. The ``FilterCollection#enable($name)`` method +will retrieve the filter object. You can set the filter parameters on that +object. + +.. code-block:: php + + getFilters()->enable("locale"); + $filter->setParameter('locale', 'en'); + + // Disable it + $filter = $em->getFilters()->disable("locale"); + +.. warning:: + Disabling and enabling filters has no effect on managed entities. If you + want to refresh or reload an object after having modified a filter or the + FilterCollection, then you should clear the EntityManager and re-fetch your + entities, having the new rules for filtering applied. diff --git a/vendor/doctrine/orm/docs/en/reference/improving-performance.rst b/vendor/doctrine/orm/docs/en/reference/improving-performance.rst new file mode 100644 index 0000000..d7ed74f --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/improving-performance.rst @@ -0,0 +1,73 @@ +Improving Performance +===================== + +Bytecode Cache +-------------- + +It is highly recommended to make use of a bytecode cache like OPcache. +A bytecode cache removes the need for parsing PHP code on every +request and can greatly improve performance. + + "If you care about performance and don't use a bytecode + cache then you don't really care about performance. Please get one + and start using it." + + *Stas Malyshev, Core Contributor to PHP and Zend Employee* + + +Metadata and Query caches +------------------------- + +As already mentioned earlier in the chapter about configuring +Doctrine, it is strongly discouraged to use Doctrine without a +Metadata and Query cache (preferably with APC or Memcache as the +cache driver). Operating Doctrine without these caches means +Doctrine will need to load your mapping information on every single +request and has to parse each DQL query on every single request. +This is a waste of resources. + +See :ref:`integrating-with-the-orm` + +Alternative Query Result Formats +-------------------------------- + +Make effective use of the available alternative query result +formats like nested array graphs or pure scalar results, especially +in scenarios where data is loaded for read-only purposes. + +Read-Only Entities +------------------ + +Starting with Doctrine 2.1 you can mark entities as read only (See metadata mapping +references for details). This means that the entity marked as read only is never considered +for updates, which means when you call flush on the EntityManager these entities are skipped +even if properties changed. Read-Only allows to persist new entities of a kind and remove existing +ones, they are just not considered for updates. + +See :ref:`annref_entity` + +Extra-Lazy Collections +---------------------- + +If entities hold references to large collections you will get performance and memory problems initializing them. +To solve this issue you can use the EXTRA_LAZY fetch-mode feature for collections. See the :doc:`tutorial <../tutorials/extra-lazy-associations>` +for more information on how this fetch mode works. + +Temporarily change fetch mode in DQL +------------------------------------ + +See :ref:`dql-temporarily-change-fetch-mode` + + +Apply Best Practices +-------------------- + +A lot of the points mentioned in the Best Practices chapter will +also positively affect the performance of Doctrine. + +See :doc:`Best Practices ` + +Change Tracking policies +------------------------ + +See: :doc:`Change Tracking Policies ` diff --git a/vendor/doctrine/orm/docs/en/reference/inheritance-mapping.rst b/vendor/doctrine/orm/docs/en/reference/inheritance-mapping.rst new file mode 100644 index 0000000..4d21ac7 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/inheritance-mapping.rst @@ -0,0 +1,606 @@ +Inheritance Mapping +=================== + +Mapped Superclasses +------------------- + +A mapped superclass is an abstract or concrete class that provides +persistent entity state and mapping information for its subclasses, +but which is not itself an entity. Typically, the purpose of such a +mapped superclass is to define state and mapping information that +is common to multiple entity classes. + +Mapped superclasses, just as regular, non-mapped classes, can +appear in the middle of an otherwise mapped inheritance hierarchy +(through Single Table Inheritance or Class Table Inheritance). + +.. note:: + + A mapped superclass cannot be an entity, it is not query-able and + persistent relationships defined by a mapped superclass must be + unidirectional (with an owning side only). This means that One-To-Many + associations are not possible on a mapped superclass at all. + Furthermore Many-To-Many associations are only possible if the + mapped superclass is only used in exactly one entity at the moment. + For further support of inheritance, the single or + joined table inheritance features have to be used. + + +Example: + +.. code-block:: php + + `_ +is an inheritance mapping strategy where all classes of a hierarchy +are mapped to a single database table. In order to distinguish +which row represents which type in the hierarchy a so-called +discriminator column is used. + +Example: + +.. configuration-block:: + + .. code-block:: php + + `_ +is an inheritance mapping strategy where each class in a hierarchy +is mapped to several tables: its own table and the tables of all +parent classes. The table of a child class is linked to the table +of a parent class through a foreign key constraint. Doctrine 2 +implements this strategy through the use of a discriminator column +in the topmost table of the hierarchy because this is the easiest +way to achieve polymorphic queries with Class Table Inheritance. + +Example: + +.. code-block:: php + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + .. code-block:: yaml + + # user mapping + MyProject\Model\User: + type: mappedSuperclass + # other fields mapping + manyToOne: + address: + targetEntity: Address + joinColumn: + name: address_id + referencedColumnName: id + cascade: [ persist, merge ] + manyToMany: + groups: + targetEntity: Group + joinTable: + name: users_groups + joinColumns: + user_id: + referencedColumnName: id + inverseJoinColumns: + group_id: + referencedColumnName: id + cascade: [ persist, merge, detach ] + + # admin mapping + MyProject\Model\Admin: + type: entity + associationOverride: + address: + joinColumn: + adminaddress_id: + name: adminaddress_id + referencedColumnName: id + groups: + joinTable: + name: users_admingroups + joinColumns: + adminuser_id: + referencedColumnName: id + inverseJoinColumns: + admingroup_id: + referencedColumnName: id + + +Things to note: + +- The "association override" specifies the overrides base on the property name. +- This feature is available for all kind of associations. (OneToOne, OneToMany, ManyToOne, ManyToMany) +- The association type *CANNOT* be changed. +- The override could redefine the joinTables or joinColumns depending on the association type. +- The override could redefine inversedBy to reference more than one extended entity. +- The override could redefine fetch to modify the fetch strategy of the extended entity. + +Attribute Override +~~~~~~~~~~~~~~~~~~~~ +Override the mapping of a field. + +Could be used by an entity that extends a mapped superclass to override a field mapping defined by the mapped superclass. + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + .. code-block:: yaml + + # user mapping + MyProject\Model\User: + type: mappedSuperclass + id: + id: + type: integer + column: user_id + length: 150 + generator: + strategy: AUTO + fields: + name: + type: string + column: user_name + length: 250 + nullable: true + unique: false + #other fields mapping + + + # guest mapping + MyProject\Model\Guest: + type: entity + attributeOverride: + id: + column: guest_id + type: integer + length: 140 + name: + column: guest_name + type: string + length: 240 + nullable: false + unique: true + +Things to note: + +- The "attribute override" specifies the overrides base on the property name. +- The column type *CANNOT* be changed. If the column type is not equal you get a ``MappingException`` +- The override can redefine all the columns except the type. + +Query the Type +-------------- + +It may happen that the entities of a special type should be queried. Because there +is no direct access to the discriminator column, Doctrine provides the +``INSTANCE OF`` construct. + +The following example shows how to use ``INSTANCE OF``. There is a three level hierarchy +with a base entity ``NaturalPerson`` which is extended by ``Staff`` which in turn +is extended by ``Technician``. + +Querying for the staffs without getting any technicians can be achieved by this DQL: + +.. code-block:: php + + createQuery("SELECT staff FROM MyProject\Model\Staff staff WHERE staff NOT INSTANCE OF MyProject\Model\Technician"); + $staffs = $query->getResult(); diff --git a/vendor/doctrine/orm/docs/en/reference/installation.rst b/vendor/doctrine/orm/docs/en/reference/installation.rst new file mode 100644 index 0000000..fec8378 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/installation.rst @@ -0,0 +1,4 @@ +Installation +============ + +The installation chapter has moved to :doc:`Installation and Configuration `_. diff --git a/vendor/doctrine/orm/docs/en/reference/limitations-and-known-issues.rst b/vendor/doctrine/orm/docs/en/reference/limitations-and-known-issues.rst new file mode 100644 index 0000000..143d53b --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/limitations-and-known-issues.rst @@ -0,0 +1,203 @@ +Limitations and Known Issues +============================ + +We try to make using Doctrine2 a very pleasant experience. +Therefore we think it is very important to be honest about the +current limitations to our users. Much like every other piece of +software Doctrine2 is not perfect and far from feature complete. +This section should give you an overview of current limitations of +Doctrine 2 as well as critical known issues that you should know +about. + +Current Limitations +------------------- + +There is a set of limitations that exist currently which might be +solved in the future. Any of this limitations now stated has at +least one ticket in the Tracker and is discussed for future +releases. + +Join-Columns with non-primary keys +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is not possible to use join columns pointing to non-primary keys. Doctrine will think these are the primary +keys and create lazy-loading proxies with the data, which can lead to unexpected results. Doctrine can for performance +reasons not validate the correctness of this settings at runtime but only through the Validate Schema command. + +Mapping Arrays to a Join Table +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Related to the previous limitation with "Foreign Keys as +Identifier" you might be interested in mapping the same table +structure as given above to an array. However this is not yet +possible either. See the following example: + +.. code-block:: sql + + CREATE TABLE product ( + id INTEGER, + name VARCHAR, + PRIMARY KEY(id) + ); + + CREATE TABLE product_attributes ( + product_id INTEGER, + attribute_name VARCHAR, + attribute_value VARCHAR, + PRIMARY KEY (product_id, attribute_name) + ); + +This schema should be mapped to a Product Entity as follows: + +.. code-block:: php + + class Product + { + private $id; + private $name; + private $attributes = array(); + } + +Where the ``attribute_name`` column contains the key and +``attribute_value`` contains the value of each array element in +``$attributes``. + +The feature request for persistence of primitive value arrays +`is described in the DDC-298 ticket `_. + +Cascade Merge with Bi-directional Associations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are two bugs now that concern the use of cascade merge in combination with bi-directional associations. +Make sure to study the behavior of cascade merge if you are using it: + +- `DDC-875 `_ Merge can sometimes add the same entity twice into a collection +- `DDC-763 `_ Cascade merge on associated entities can insert too many rows through "Persistence by Reachability" + +Custom Persisters +~~~~~~~~~~~~~~~~~ + +A Persister in Doctrine is an object that is responsible for the +hydration and write operations of an entity against the database. +Currently there is no way to overwrite the persister implementation +for a given entity, however there are several use-cases that can +benefit from custom persister implementations: + +- `Add Upsert Support `_ +- `Evaluate possible ways in which stored-procedures can be used `_ + +Persist Keys of Collections +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +PHP Arrays are ordered hash-maps and so should be the +``Doctrine\Common\Collections\Collection`` interface. We plan to +evaluate a feature that optionally persists and hydrates the keys +of a Collection instance. + +`Ticket DDC-213 `_ + +Mapping many tables to one entity +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is not possible to map several equally looking tables onto one +entity. For example if you have a production and an archive table +of a certain business concept then you cannot have both tables map +to the same entity. + +Behaviors +~~~~~~~~~ + +Doctrine 2 will **never** include a behavior system like Doctrine 1 +in the core library. We don't think behaviors add more value than +they cost pain and debugging hell. Please see the many different +blog posts we have written on this topics: + +- `Doctrine2 "Behaviors" in a Nutshell `_ +- `A re-usable Versionable behavior for Doctrine2 `_ +- `Write your own ORM on top of Doctrine2 `_ +- `Doctrine 2 Behavioral Extensions `_ + +Doctrine 2 has enough hooks and extension points so that **you** can +add whatever you want on top of it. None of this will ever become +core functionality of Doctrine2 however, you will have to rely on +third party extensions for magical behaviors. + +Nested Set +~~~~~~~~~~ + +NestedSet was offered as a behavior in Doctrine 1 and will not be +included in the core of Doctrine 2. However there are already two +extensions out there that offer support for Nested Set with +Doctrine 2: + + +- `Doctrine2 Hierarchical-Structural Behavior `_ +- `Doctrine2 NestedSet `_ + +Known Issues +------------ + +The Known Issues section describes critical/blocker bugs and other +issues that are either complicated to fix, not fixable due to +backwards compatibility issues or where no simple fix exists (yet). +We don't plan to add every bug in the tracker there, just those +issues that can potentially cause nightmares or pain of any sort. + +See bugs, improvement and feature requests on `Github issues `_. + +Identifier Quoting and Legacy Databases +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For compatibility reasons between all the supported vendors and +edge case problems Doctrine 2 does **NOT** do automatic identifier +quoting. This can lead to problems when trying to get +legacy-databases to work with Doctrine 2. + + +- You can quote column-names as described in the + :doc:`Basic-Mapping ` section. +- You cannot quote join column names. +- You cannot use non [a-zA-Z0-9\_]+ characters, they will break + several SQL statements. + +Having problems with these kind of column names? Many databases +support all CRUD operations on views that semantically map to +certain tables. You can create views for all your problematic +tables and column names to avoid the legacy quoting nightmare. + +Microsoft SQL Server and Doctrine "datetime" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Doctrine assumes that you use ``DateTime2`` data-types. If your legacy database contains DateTime +datatypes then you have to add your own data-type (see Basic Mapping for an example). + +MySQL with MyISAM tables +~~~~~~~~~~~~~~~~~~~~~~~~ + +Doctrine cannot provide atomic operations when calling ``EntityManager#flush()`` if one +of the tables involved uses the storage engine MyISAM. You must use InnoDB or +other storage engines that support transactions if you need integrity. + +Entities, Proxies and Reflection +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Using methods for Reflection on entities can be prone to error, when the entity +is actually a proxy the following methods will not work correctly: + +- ``new ReflectionClass`` +- ``new ReflectionObject`` +- ``get_class()`` +- ``get_parent_class()`` + +This is why ``Doctrine\Common\Util\ClassUtils`` class exists that has similar +methods, which resolve the proxy problem beforehand. + +.. code-block:: php + + getReference('Acme\Book'); + + $reflection = ClassUtils::newReflectionClass($bookProxy); + $class = ClassUtils::getClass($bookProxy)¸ diff --git a/vendor/doctrine/orm/docs/en/reference/metadata-drivers.rst b/vendor/doctrine/orm/docs/en/reference/metadata-drivers.rst new file mode 100644 index 0000000..5162dee --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/metadata-drivers.rst @@ -0,0 +1,194 @@ +Metadata Drivers +================ + +The heart of an object relational mapper is the mapping information +that glues everything together. It instructs the EntityManager how +it should behave when dealing with the different entities. + +Core Metadata Drivers +--------------------- + +Doctrine provides a few different ways for you to specify your +metadata: + + +- **XML files** (XmlDriver) +- **Class DocBlock Annotations** (AnnotationDriver) +- **YAML files** (YamlDriver) +- **PHP Code in files or static functions** (PhpDriver) + +Something important to note about the above drivers is they are all +an intermediate step to the same end result. The mapping +information is populated to ``Doctrine\ORM\Mapping\ClassMetadata`` +instances. So in the end, Doctrine only ever has to work with the +API of the ``ClassMetadata`` class to get mapping information for +an entity. + +.. note:: + + The populated ``ClassMetadata`` instances are also cached + so in a production environment the parsing and populating only ever + happens once. You can configure the metadata cache implementation + using the ``setMetadataCacheImpl()`` method on the + ``Doctrine\ORM\Configuration`` class: + + .. code-block:: php + + getConfiguration()->setMetadataCacheImpl(new ApcuCache()); + + +If you want to use one of the included core metadata drivers you +just need to configure it. All the drivers are in the +``Doctrine\ORM\Mapping\Driver`` namespace: + +.. code-block:: php + + getConfiguration()->setMetadataDriverImpl($driver); + +Implementing Metadata Drivers +----------------------------- + +In addition to the included metadata drivers you can very easily +implement your own. All you need to do is define a class which +implements the ``Driver`` interface: + +.. code-block:: php + + _loadMappingFile($file); + + // populate ClassMetadataInfo instance from $data + } + + /** + * {@inheritdoc} + */ + protected function _loadMappingFile($file) + { + // parse contents of $file and return php data structure + } + } + +.. note:: + + When using the ``AbstractFileDriver`` it requires that you + only have one entity defined per file and the file named after the + class described inside where namespace separators are replaced by + periods. So if you have an entity named ``Entities\User`` and you + wanted to write a mapping file for your driver above you would need + to name the file ``Entities.User.dcm.ext`` for it to be + recognized. + + +Now you can use your ``MyMetadataDriver`` implementation by setting +it with the ``setMetadataDriverImpl()`` method: + +.. code-block:: php + + getConfiguration()->setMetadataDriverImpl($driver); + +ClassMetadata +------------- + +The last piece you need to know and understand about metadata in +Doctrine 2 is the API of the ``ClassMetadata`` classes. You need to +be familiar with them in order to implement your own drivers but +more importantly to retrieve mapping information for a certain +entity when needed. + +You have all the methods you need to manually specify the mapping +information instead of using some mapping file to populate it from. +The base ``ClassMetadataInfo`` class is responsible for only data +storage and is not meant for runtime use. It does not require that +the class actually exists yet so it is useful for describing some +entity before it exists and using that information to generate for +example the entities themselves. The class ``ClassMetadata`` +extends ``ClassMetadataInfo`` and adds some functionality required +for runtime usage and requires that the PHP class is present and +can be autoloaded. + +You can read more about the API of the ``ClassMetadata`` classes in +the PHP Mapping chapter. + +Getting ClassMetadata Instances +------------------------------- + +If you want to get the ``ClassMetadata`` instance for an entity in +your project to programmatically use some mapping information to +generate some HTML or something similar you can retrieve it through +the ``ClassMetadataFactory``: + +.. code-block:: php + + getMetadataFactory(); + $class = $cmf->getMetadataFor('MyEntityName'); + +Now you can learn about the entity and use the data stored in the +``ClassMetadata`` instance to get all mapped fields for example and +iterate over them: + +.. code-block:: php + + fieldMappings as $fieldMapping) { + echo $fieldMapping['fieldName'] . "\n"; + } + + diff --git a/vendor/doctrine/orm/docs/en/reference/namingstrategy.rst b/vendor/doctrine/orm/docs/en/reference/namingstrategy.rst new file mode 100644 index 0000000..23aa573 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/namingstrategy.rst @@ -0,0 +1,137 @@ +Implementing a NamingStrategy +============================== + +.. versionadded:: 2.3 + +Using a naming strategy you can provide rules for generating database identifiers, +column or table names when the column or table name is not given. This feature helps +reduce the verbosity of the mapping document, eliminating repetitive noise (eg: ``TABLE_``). + +Configuring a naming strategy +----------------------------- +The default strategy used by Doctrine is quite minimal. + +By default the ``Doctrine\ORM\Mapping\DefaultNamingStrategy`` +uses the simple class name and the attribute names to generate tables and columns. + +You can specify a different strategy by calling ``Doctrine\ORM\Configuration#setNamingStrategy()``: + +.. code-block:: php + + setNamingStrategy($namingStrategy); + +Underscore naming strategy +--------------------------- + +``\Doctrine\ORM\Mapping\UnderscoreNamingStrategy`` is a built-in strategy. + +.. code-block:: php + + setNamingStrategy($namingStrategy); + +For SomeEntityName the strategy will generate the table SOME_ENTITY_NAME with the +``CASE_UPPER`` option, or some_entity_name with the ``CASE_LOWER`` option. + +Naming strategy interface +------------------------- +The interface ``Doctrine\ORM\Mapping\NamingStrategy`` allows you to specify +a naming strategy for database tables and columns. + +.. code-block:: php + + referenceColumnName(); + } + public function joinTableName($sourceEntity, $targetEntity, $propertyName = null) + { + return strtolower($this->classToTableName($sourceEntity) . '_' . + $this->classToTableName($targetEntity)); + } + public function joinKeyColumnName($entityName, $referencedColumnName = null) + { + return strtolower($this->classToTableName($entityName) . '_' . + ($referencedColumnName ?: $this->referenceColumnName())); + } + } diff --git a/vendor/doctrine/orm/docs/en/reference/native-sql.rst b/vendor/doctrine/orm/docs/en/reference/native-sql.rst new file mode 100644 index 0000000..1676a8f --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/native-sql.rst @@ -0,0 +1,905 @@ +Native SQL +========== + +With ``NativeQuery`` you can execute native SELECT SQL statements +and map the results to Doctrine entities or any other result format +supported by Doctrine. + +In order to make this mapping possible, you need to describe +to Doctrine what columns in the result map to which entity property. +This description is represented by a ``ResultSetMapping`` object. + +With this feature you can map arbitrary SQL code to objects, such as highly +vendor-optimized SQL or stored-procedures. + +Writing ``ResultSetMapping`` from scratch is complex, but there is a convenience +wrapper around it called a ``ResultSetMappingBuilder``. It can generate +the mappings for you based on Entities and even generates the ``SELECT`` +clause based on this information for you. + +.. note:: + + If you want to execute DELETE, UPDATE or INSERT statements + the Native SQL API cannot be used and will probably throw errors. + Use ``EntityManager#getConnection()`` to access the native database + connection and call the ``executeUpdate()`` method for these + queries. + +The NativeQuery class +--------------------- + +To create a ``NativeQuery`` you use the method +``EntityManager#createNativeQuery($sql, $resultSetMapping)``. As you can see in +the signature of this method, it expects 2 ingredients: The SQL you want to +execute and the ``ResultSetMapping`` that describes how the results will be +mapped. + +Once you obtained an instance of a ``NativeQuery``, you can bind parameters to +it with the same API that ``Query`` has and execute it. + +.. code-block:: php + + createNativeQuery('SELECT id, name, discr FROM users WHERE name = ?', $rsm); + $query->setParameter(1, 'romanb'); + + $users = $query->getResult(); + +ResultSetMappingBuilder +----------------------- + +An easy start into ResultSet mapping is the ``ResultSetMappingBuilder`` object. +This has several benefits: + +- The builder takes care of automatically updating your ``ResultSetMapping`` + when the fields or associations change on the metadata of an entity. +- You can generate the required ``SELECT`` expression for a builder + by converting it to a string. +- The API is much simpler than the usual ``ResultSetMapping`` API. + +One downside is that the builder API does not yet support entities +with inheritance hierarchies. + +.. code-block:: php + + addRootEntityFromClassMetadata('MyProject\User', 'u'); + $rsm->addJoinedEntityFromClassMetadata('MyProject\Address', 'a', 'u', 'address', array('id' => 'address_id')); + +The builder extends the ``ResultSetMapping`` class and as such has all the functionality of it as well. + +.. versionadded:: 2.4 + +Starting with Doctrine ORM 2.4 you can generate the ``SELECT`` clause +from a ``ResultSetMappingBuilder``. You can either cast the builder +object to ``(string)`` and the DQL aliases are used as SQL table aliases +or use the ``generateSelectClause($tableAliases)`` method and pass +a mapping from DQL alias (key) to SQL alias (value) + +.. code-block:: php + + generateSelectClause(array( + 'u' => 't1', + 'g' => 't2' + )); + $sql = "SELECT " . $selectClause . " FROM users t1 JOIN groups t2 ON t1.group_id = t2.id"; + + +The ResultSetMapping +-------------------- + +Understanding the ``ResultSetMapping`` is the key to using a +``NativeQuery``. A Doctrine result can contain the following +components: + + +- Entity results. These represent root result elements. +- Joined entity results. These represent joined entities in + associations of root entity results. +- Field results. These represent a column in the result set that + maps to a field of an entity. A field result always belongs to an + entity result or joined entity result. +- Scalar results. These represent scalar values in the result set + that will appear in each result row. Adding scalar results to a + ResultSetMapping can also cause the overall result to become + **mixed** (see DQL - Doctrine Query Language) if the same + ResultSetMapping also contains entity results. +- Meta results. These represent columns that contain + meta-information, such as foreign keys and discriminator columns. + When querying for objects (``getResult()``), all meta columns of + root entities or joined entities must be present in the SQL query + and mapped accordingly using ``ResultSetMapping#addMetaResult``. + +.. note:: + + It might not surprise you that Doctrine uses + ``ResultSetMapping`` internally when you create DQL queries. As + the query gets parsed and transformed to SQL, Doctrine fills a + ``ResultSetMapping`` that describes how the results should be + processed by the hydration routines. + + +We will now look at each of the result types that can appear in a +ResultSetMapping in detail. + +Entity results +~~~~~~~~~~~~~~ + +An entity result describes an entity type that appears as a root +element in the transformed result. You add an entity result through +``ResultSetMapping#addEntityResult()``. Let's take a look at the +method signature in detail: + +.. code-block:: php + + addEntityResult('User', 'u'); + $rsm->addFieldResult('u', 'id', 'id'); + $rsm->addFieldResult('u', 'name', 'name'); + + $query = $this->_em->createNativeQuery('SELECT id, name FROM users WHERE name = ?', $rsm); + $query->setParameter(1, 'romanb'); + + $users = $query->getResult(); + +The result would look like this: + +.. code-block:: php + + array( + [0] => User (Object) + ) + +Note that this would be a partial object if the entity has more +fields than just id and name. In the example above the column and +field names are identical but that is not necessary, of course. +Also note that the query string passed to createNativeQuery is +**real native SQL**. Doctrine does not touch this SQL in any way. + +In the previous basic example, a User had no relations and the +table the class is mapped to owns no foreign keys. The next example +assumes User has a unidirectional or bidirectional one-to-one +association to a CmsAddress, where the User is the owning side and +thus owns the foreign key. + +.. code-block:: php + + addEntityResult('User', 'u'); + $rsm->addFieldResult('u', 'id', 'id'); + $rsm->addFieldResult('u', 'name', 'name'); + $rsm->addMetaResult('u', 'address_id', 'address_id'); + + $query = $this->_em->createNativeQuery('SELECT id, name, address_id FROM users WHERE name = ?', $rsm); + $query->setParameter(1, 'romanb'); + + $users = $query->getResult(); + +Foreign keys are used by Doctrine for lazy-loading purposes when +querying for objects. In the previous example, each user object in +the result will have a proxy (a "ghost") in place of the address +that contains the address\_id. When the ghost proxy is accessed, it +loads itself based on this key. + +Consequently, associations that are *fetch-joined* do not require +the foreign keys to be present in the SQL result set, only +associations that are lazy. + +.. code-block:: php + + addEntityResult('User', 'u'); + $rsm->addFieldResult('u', 'id', 'id'); + $rsm->addFieldResult('u', 'name', 'name'); + $rsm->addJoinedEntityResult('Address' , 'a', 'u', 'address'); + $rsm->addFieldResult('a', 'address_id', 'id'); + $rsm->addFieldResult('a', 'street', 'street'); + $rsm->addFieldResult('a', 'city', 'city'); + + $sql = 'SELECT u.id, u.name, a.id AS address_id, a.street, a.city FROM users u ' . + 'INNER JOIN address a ON u.address_id = a.id WHERE u.name = ?'; + $query = $this->_em->createNativeQuery($sql, $rsm); + $query->setParameter(1, 'romanb'); + + $users = $query->getResult(); + +In this case the nested entity ``Address`` is registered with the +``ResultSetMapping#addJoinedEntityResult`` method, which notifies +Doctrine that this entity is not hydrated at the root level, but as +a joined entity somewhere inside the object graph. In this case we +specify the alias 'u' as third parameter and ``address`` as fourth +parameter, which means the ``Address`` is hydrated into the +``User::$address`` property. + +If a fetched entity is part of a mapped hierarchy that requires a +discriminator column, this column must be present in the result set +as a meta column so that Doctrine can create the appropriate +concrete type. This is shown in the following example where we +assume that there are one or more subclasses that extend User and +either Class Table Inheritance or Single Table Inheritance is used +to map the hierarchy (both use a discriminator column). + +.. code-block:: php + + addEntityResult('User', 'u'); + $rsm->addFieldResult('u', 'id', 'id'); + $rsm->addFieldResult('u', 'name', 'name'); + $rsm->addMetaResult('u', 'discr', 'discr'); // discriminator column + $rsm->setDiscriminatorColumn('u', 'discr'); + + $query = $this->_em->createNativeQuery('SELECT id, name, discr FROM users WHERE name = ?', $rsm); + $query->setParameter(1, 'romanb'); + + $users = $query->getResult(); + +Note that in the case of Class Table Inheritance, an example as +above would result in partial objects if any objects in the result +are actually a subtype of User. When using DQL, Doctrine +automatically includes the necessary joins for this mapping +strategy but with native SQL it is your responsibility. + +Named Native Query +------------------ + +You can also map a native query using a named native query mapping. + +To achieve that, you must describe the SQL resultset structure +using named native query (and sql resultset mappings if is a several resultset mappings). + +Like named query, a named native query can be defined at class level or in a XML or YAML file. + + +A resultSetMapping parameter is defined in @NamedNativeQuery, +it represents the name of a defined @SqlResultSetMapping. + +.. configuration-block:: + + .. code-block:: php + + + + + + SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM users u INNER JOIN addresses a ON u.id = a.user_id INNER JOIN phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username + + + + + + + + + + + + + + + + + + + + .. code-block:: yaml + + MyProject\Model\User: + type: entity + namedNativeQueries: + fetchMultipleJoinsEntityResults: + name: fetchMultipleJoinsEntityResults + resultSetMapping: mappingMultipleJoinsEntityResults + query: SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM users u INNER JOIN addresses a ON u.id = a.user_id INNER JOIN phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username + sqlResultSetMappings: + mappingMultipleJoinsEntityResults: + name: mappingMultipleJoinsEntityResults + columnResult: + 0: + name: numphones + entityResult: + 0: + entityClass: __CLASS__ + fieldResult: + 0: + name: id + column: u_id + 1: + name: name + column: u_name + 2: + name: status + column: u_status + 1: + entityClass: Address + fieldResult: + 0: + name: id + column: a_id + 1: + name: zip + column: a_zip + 2: + name: country + column: a_country + + +Things to note: + - The resultset mapping declares the entities retrieved by this native query. + - Each field of the entity is bound to a SQL alias (or column name). + - All fields of the entity including the ones of subclasses + and the foreign key columns of related entities have to be present in the SQL query. + - Field definitions are optional provided that they map to the same + column name as the one declared on the class property. + - ``__CLASS__`` is an alias for the mapped class + + +In the above example, +the ``fetchJoinedAddress`` named query use the joinMapping result set mapping. +This mapping returns 2 entities, User and Address, each property is declared and associated to a column name, +actually the column name retrieved by the query. + +Let's now see an implicit declaration of the property / column. + +.. configuration-block:: + + .. code-block:: php + + + + + + SELECT * FROM addresses + + + + + + + + + + .. code-block:: yaml + + MyProject\Model\Address: + type: entity + namedNativeQueries: + findAll: + resultSetMapping: mappingFindAll + query: SELECT * FROM addresses + sqlResultSetMappings: + mappingFindAll: + name: mappingFindAll + entityResult: + address: + entityClass: Address + + +In this example, we only describe the entity member of the result set mapping. +The property / column mappings is done using the entity mapping values. +In this case the model property is bound to the model_txt column. +If the association to a related entity involve a composite primary key, +a @FieldResult element should be used for each foreign key column. +The @FieldResult name is composed of the property name for the relationship, +followed by a dot ("."), followed by the name or the field or property of the primary key. + + +.. configuration-block:: + + .. code-block:: php + + + + + + SELECT u.id, u.name, u.status, a.id AS a_id, a.country AS a_country, a.zip AS a_zip, a.city AS a_city FROM users u INNER JOIN addresses a ON u.id = a.user_id WHERE u.username = ? + + + + + + + + + + + + + + + + + + .. code-block:: yaml + + MyProject\Model\User: + type: entity + namedNativeQueries: + fetchJoinedAddress: + name: fetchJoinedAddress + resultSetMapping: mappingJoinedAddress + query: SELECT u.id, u.name, u.status, a.id AS a_id, a.country AS a_country, a.zip AS a_zip, a.city AS a_city FROM users u INNER JOIN addresses a ON u.id = a.user_id WHERE u.username = ? + sqlResultSetMappings: + mappingJoinedAddress: + entityResult: + 0: + entityClass: __CLASS__ + fieldResult: + 0: + name: id + 1: + name: name + 2: + name: status + 3: + name: address.id + column: a_id + 4: + name: address.zip + column: a_zip + 5: + name: address.city + column: a_city + 6: + name: address.country + column: a_country + + + +If you retrieve a single entity and if you use the default mapping, +you can use the resultClass attribute instead of resultSetMapping: + +.. configuration-block:: + + .. code-block:: php + + + + + + SELECT * FROM addresses WHERE id = ? + + + + + .. code-block:: yaml + + MyProject\Model\Address: + type: entity + namedNativeQueries: + findAll: + name: findAll + resultClass: Address + query: SELECT * FROM addresses + + +In some of your native queries, you'll have to return scalar values, +for example when building report queries. +You can map them in the @SqlResultsetMapping through @ColumnResult. +You actually can even mix, entities and scalar returns in the same native query (this is probably not that common though). + +.. configuration-block:: + + .. code-block:: php + + + + + SELECT COUNT(*) AS count FROM addresses + + + + + + + + + .. code-block:: yaml + + MyProject\Model\Address: + type: entity + namedNativeQueries: + count: + name: count + resultSetMapping: mappingCount + query: SELECT COUNT(*) AS count FROM addresses + sqlResultSetMappings: + mappingCount: + name: mappingCount + columnResult: + count: + name: count diff --git a/vendor/doctrine/orm/docs/en/reference/partial-objects.rst b/vendor/doctrine/orm/docs/en/reference/partial-objects.rst new file mode 100644 index 0000000..396eecc --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/partial-objects.rst @@ -0,0 +1,90 @@ +Partial Objects +=============== + +A partial object is an object whose state is not fully initialized +after being reconstituted from the database and that is +disconnected from the rest of its data. The following section will +describe why partial objects are problematic and what the approach +of Doctrine2 to this problem is. + +.. note:: + + The partial object problem in general does not apply to + methods or queries where you do not retrieve the query result as + objects. Examples are: ``Query#getArrayResult()``, + ``Query#getScalarResult()``, ``Query#getSingleScalarResult()``, + etc. + +.. warning:: + + Use of partial objects is tricky. Fields that are not retrieved + from the database will not be updated by the UnitOfWork even if they + get changed in your objects. You can only promote a partial object + to a fully-loaded object by calling ``EntityManager#refresh()`` + or a DQL query with the refresh flag. + + +What is the problem? +-------------------- + +In short, partial objects are problematic because they are usually +objects with broken invariants. As such, code that uses these +partial objects tends to be very fragile and either needs to "know" +which fields or methods can be safely accessed or add checks around +every field access or method invocation. The same holds true for +the internals, i.e. the method implementations, of such objects. +You usually simply assume the state you need in the method is +available, after all you properly constructed this object before +you pushed it into the database, right? These blind assumptions can +quickly lead to null reference errors when working with such +partial objects. + +It gets worse with the scenario of an optional association (0..1 to +1). When the associated field is NULL, you don't know whether this +object does not have an associated object or whether it was simply +not loaded when the owning object was loaded from the database. + +These are reasons why many ORMs do not allow partial objects at all +and instead you always have to load an object with all its fields +(associations being proxied). One secure way to allow partial +objects is if the programming language/platform allows the ORM tool +to hook deeply into the object and instrument it in such a way that +individual fields (not only associations) can be loaded lazily on +first access. This is possible in Java, for example, through +bytecode instrumentation. In PHP though this is not possible, so +there is no way to have "secure" partial objects in an ORM with +transparent persistence. + +Doctrine, by default, does not allow partial objects. That means, +any query that only selects partial object data and wants to +retrieve the result as objects (i.e. ``Query#getResult()``) will +raise an exception telling you that partial objects are dangerous. +If you want to force a query to return you partial objects, +possibly as a performance tweak, you can use the ``partial`` +keyword as follows: + +.. code-block:: php + + createQuery("select partial u.{id,name} from MyApp\Domain\User u"); + +You can also get a partial reference instead of a proxy reference by +calling: + +.. code-block:: php + + getPartialReference('MyApp\Domain\User', 1); + +Partial references are objects with only the identifiers set as they +are passed to the second argument of the ``getPartialReference()`` method. +All other fields are null. + +When should I force partial objects? +------------------------------------ + +Mainly for optimization purposes, but be careful of premature +optimization as partial objects lead to potentially more fragile +code. + + diff --git a/vendor/doctrine/orm/docs/en/reference/php-mapping.rst b/vendor/doctrine/orm/docs/en/reference/php-mapping.rst new file mode 100644 index 0000000..78a7214 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/php-mapping.rst @@ -0,0 +1,325 @@ +PHP Mapping +=========== + +Doctrine 2 also allows you to provide the ORM metadata in the form +of plain PHP code using the ``ClassMetadata`` API. You can write +the code in PHP files or inside of a static function named +``loadMetadata($class)`` on the entity class itself. + +PHP Files +--------- + +If you wish to write your mapping information inside PHP files that +are named after the entity and included to populate the metadata +for an entity you can do so by using the ``PHPDriver``: + +.. code-block:: php + + getConfiguration()->setMetadataDriverImpl($driver); + +Now imagine we had an entity named ``Entities\User`` and we wanted +to write a mapping file for it using the above configured +``PHPDriver`` instance: + +.. code-block:: php + + mapField(array( + 'id' => true, + 'fieldName' => 'id', + 'type' => 'integer' + )); + + $metadata->mapField(array( + 'fieldName' => 'username', + 'type' => 'string', + 'options' => array( + 'fixed' => true, + 'comment' => "User's login name" + ) + )); + + $metadata->mapField(array( + 'fieldName' => 'login_count', + 'type' => 'integer', + 'nullable' => false, + 'options' => array( + 'unsigned' => true, + 'default' => 0 + ) + )); + +Now we can easily retrieve the populated ``ClassMetadata`` instance +where the ``PHPDriver`` includes the file and the +``ClassMetadataFactory`` caches it for later retrieval: + +.. code-block:: php + + getClassMetadata('Entities\User'); + // or + $class = $em->getMetadataFactory()->getMetadataFor('Entities\User'); + +Static Function +--------------- + +In addition to the PHP files you can also specify your mapping +information inside of a static function defined on the entity class +itself. This is useful for cases where you want to keep your entity +and mapping information together but don't want to use annotations. +For this you just need to use the ``StaticPHPDriver``: + +.. code-block:: php + + getConfiguration()->setMetadataDriverImpl($driver); + +Now you just need to define a static function named +``loadMetadata($metadata)`` on your entity: + +.. code-block:: php + + mapField(array( + 'id' => true, + 'fieldName' => 'id', + 'type' => 'integer' + )); + + $metadata->mapField(array( + 'fieldName' => 'username', + 'type' => 'string' + )); + } + } + +ClassMetadataBuilder +-------------------- + +To ease the use of the ClassMetadata API (which is very raw) there is a ``ClassMetadataBuilder`` that you can use. + +.. code-block:: php + + createField('id', 'integer')->isPrimaryKey()->generatedValue()->build(); + $builder->addField('username', 'string'); + } + } + +The API of the ClassMetadataBuilder has the following methods with a fluent interface: + +- ``addField($name, $type, array $mapping)`` +- ``setMappedSuperclass()`` +- ``setReadOnly()`` +- ``setCustomRepositoryClass($className)`` +- ``setTable($name)`` +- ``addIndex(array $columns, $indexName)`` +- ``addUniqueConstraint(array $columns, $constraintName)`` +- ``addNamedQuery($name, $dqlQuery)`` +- ``setJoinedTableInheritance()`` +- ``setSingleTableInheritance()`` +- ``setDiscriminatorColumn($name, $type = 'string', $length = 255)`` +- ``addDiscriminatorMapClass($name, $class)`` +- ``setChangeTrackingPolicyDeferredExplicit()`` +- ``setChangeTrackingPolicyNotify()`` +- ``addLifecycleEvent($methodName, $event)`` +- ``addManyToOne($name, $targetEntity, $inversedBy = null)`` +- ``addInverseOneToOne($name, $targetEntity, $mappedBy)`` +- ``addOwningOneToOne($name, $targetEntity, $inversedBy = null)`` +- ``addOwningManyToMany($name, $targetEntity, $inversedBy = null)`` +- ``addInverseManyToMany($name, $targetEntity, $mappedBy)`` +- ``addOneToMany($name, $targetEntity, $mappedBy)`` + +It also has several methods that create builders (which are necessary for advanced mappings): + +- ``createField($name, $type)`` returns a ``FieldBuilder`` instance +- ``createManyToOne($name, $targetEntity)`` returns an ``AssociationBuilder`` instance +- ``createOneToOne($name, $targetEntity)`` returns an ``AssociationBuilder`` instance +- ``createManyToMany($name, $targetEntity)`` returns an ``ManyToManyAssociationBuilder`` instance +- ``createOneToMany($name, $targetEntity)`` returns an ``OneToManyAssociationBuilder`` instance + +ClassMetadataInfo API +--------------------- + +The ``ClassMetadataInfo`` class is the base data object for storing +the mapping metadata for a single entity. It contains all the +getters and setters you need populate and retrieve information for +an entity. + +General Setters +~~~~~~~~~~~~~~~ + + +- ``setTableName($tableName)`` +- ``setPrimaryTable(array $primaryTableDefinition)`` +- ``setCustomRepositoryClass($repositoryClassName)`` +- ``setIdGeneratorType($generatorType)`` +- ``setIdGenerator($generator)`` +- ``setSequenceGeneratorDefinition(array $definition)`` +- ``setChangeTrackingPolicy($policy)`` +- ``setIdentifier(array $identifier)`` + +Inheritance Setters +~~~~~~~~~~~~~~~~~~~ + + +- ``setInheritanceType($type)`` +- ``setSubclasses(array $subclasses)`` +- ``setParentClasses(array $classNames)`` +- ``setDiscriminatorColumn($columnDef)`` +- ``setDiscriminatorMap(array $map)`` + +Field Mapping Setters +~~~~~~~~~~~~~~~~~~~~~ + + +- ``mapField(array $mapping)`` +- ``mapOneToOne(array $mapping)`` +- ``mapOneToMany(array $mapping)`` +- ``mapManyToOne(array $mapping)`` +- ``mapManyToMany(array $mapping)`` + +Lifecycle Callback Setters +~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +- ``addLifecycleCallback($callback, $event)`` +- ``setLifecycleCallbacks(array $callbacks)`` + +Versioning Setters +~~~~~~~~~~~~~~~~~~ + + +- ``setVersionMapping(array &$mapping)`` +- ``setVersioned($bool)`` +- ``setVersionField()`` + +General Getters +~~~~~~~~~~~~~~~ + + +- ``getTableName()`` +- ``getSchemaName()`` +- ``getTemporaryIdTableName()`` + +Identifier Getters +~~~~~~~~~~~~~~~~~~ + + +- ``getIdentifierColumnNames()`` +- ``usesIdGenerator()`` +- ``isIdentifier($fieldName)`` +- ``isIdGeneratorIdentity()`` +- ``isIdGeneratorSequence()`` +- ``isIdGeneratorTable()`` +- ``isIdentifierNatural()`` +- ``getIdentifierFieldNames()`` +- ``getSingleIdentifierFieldName()`` +- ``getSingleIdentifierColumnName()`` + +Inheritance Getters +~~~~~~~~~~~~~~~~~~~ + + +- ``isInheritanceTypeNone()`` +- ``isInheritanceTypeJoined()`` +- ``isInheritanceTypeSingleTable()`` +- ``isInheritanceTypeTablePerClass()`` +- ``isInheritedField($fieldName)`` +- ``isInheritedAssociation($fieldName)`` + +Change Tracking Getters +~~~~~~~~~~~~~~~~~~~~~~~ + + +- ``isChangeTrackingDeferredExplicit()`` +- ``isChangeTrackingDeferredImplicit()`` +- ``isChangeTrackingNotify()`` + +Field & Association Getters +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +- ``isUniqueField($fieldName)`` +- ``isNullable($fieldName)`` +- ``getColumnName($fieldName)`` +- ``getFieldMapping($fieldName)`` +- ``getAssociationMapping($fieldName)`` +- ``getAssociationMappings()`` +- ``getFieldName($columnName)`` +- ``hasField($fieldName)`` +- ``getColumnNames(array $fieldNames = null)`` +- ``getTypeOfField($fieldName)`` +- ``getTypeOfColumn($columnName)`` +- ``hasAssociation($fieldName)`` +- ``isSingleValuedAssociation($fieldName)`` +- ``isCollectionValuedAssociation($fieldName)`` + +Lifecycle Callback Getters +~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +- ``hasLifecycleCallbacks($lifecycleEvent)`` +- ``getLifecycleCallbacks($event)`` + +ClassMetadata API +----------------- + +The ``ClassMetadata`` class extends ``ClassMetadataInfo`` and adds +the runtime functionality required by Doctrine. It adds a few extra +methods related to runtime reflection for working with the entities +themselves. + + +- ``getReflectionClass()`` +- ``getReflectionProperties()`` +- ``getReflectionProperty($name)`` +- ``getSingleIdReflectionProperty()`` +- ``getIdentifierValues($entity)`` +- ``setIdentifierValues($entity, $id)`` +- ``setFieldValue($entity, $field, $value)`` +- ``getFieldValue($entity, $field)`` + + diff --git a/vendor/doctrine/orm/docs/en/reference/query-builder.rst b/vendor/doctrine/orm/docs/en/reference/query-builder.rst new file mode 100644 index 0000000..91833ae --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/query-builder.rst @@ -0,0 +1,584 @@ +The QueryBuilder +================ + +A ``QueryBuilder`` provides an API that is designed for +conditionally constructing a DQL query in several steps. + +It provides a set of classes and methods that is able to +programmatically build queries, and also provides a fluent API. +This means that you can change between one methodology to the other +as you want, or just pick a preferred one. + +.. note:: + + The ``QueryBuilder`` is not an abstraction of DQL, but merely a tool to dynamically build it. + You should still use plain DQL when you can, as it is simpler and more readable. + More about this in the :doc:`FAQ `_. + +Constructing a new QueryBuilder object +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The same way you build a normal Query, you build a ``QueryBuilder`` +object. Here is an example of how to build a ``QueryBuilder`` +object: + +.. code-block:: php + + createQueryBuilder(); + +An instance of QueryBuilder has several informative methods. One +good example is to inspect what type of object the +``QueryBuilder`` is. + +.. code-block:: php + + getType(); // Prints: 0 + +There're currently 3 possible return values for ``getType()``: + + +- ``QueryBuilder::SELECT``, which returns value 0 +- ``QueryBuilder::DELETE``, returning value 1 +- ``QueryBuilder::UPDATE``, which returns value 2 + +It is possible to retrieve the associated ``EntityManager`` of the +current ``QueryBuilder``, its DQL and also a ``Query`` object when +you finish building your DQL. + +.. code-block:: php + + getEntityManager(); + + // example4: retrieve the DQL string of what was defined in QueryBuilder + $dql = $qb->getDql(); + + // example5: retrieve the associated Query object with the processed DQL + $q = $qb->getQuery(); + +Internally, ``QueryBuilder`` works with a DQL cache to increase +performance. Any changes that may affect the generated DQL actually +modifies the state of ``QueryBuilder`` to a stage we call +STATE\_DIRTY. One ``QueryBuilder`` can be in two different states: + + +- ``QueryBuilder::STATE_CLEAN``, which means DQL haven't been + altered since last retrieval or nothing were added since its + instantiation +- ``QueryBuilder::STATE_DIRTY``, means DQL query must (and will) + be processed on next retrieval + +Working with QueryBuilder +~~~~~~~~~~~~~~~~~~~~~~~~~ + + +High level API methods +^^^^^^^^^^^^^^^^^^^^^^ + +The most straightforward way to build a dynamic query with the ``QueryBuilder`` is by taking +advantage of Helper methods. For all base code, there is a set of +useful methods to simplify a programmer's life. To illustrate how +to work with them, here is the same example 6 re-written using +``QueryBuilder`` helper methods: + +.. code-block:: php + + select('u') + ->from('User', 'u') + ->where('u.id = ?1') + ->orderBy('u.name', 'ASC'); + +``QueryBuilder`` helper methods are considered the standard way to +use the ``QueryBuilder``. The ``$qb->expr()->*`` methods can help you +build conditional expressions dynamically. Here is a converted example 8 to +suggested way to build queries with dynamic conditions: + +.. code-block:: php + + select(array('u')) // string 'u' is converted to array internally + ->from('User', 'u') + ->where($qb->expr()->orX( + $qb->expr()->eq('u.id', '?1'), + $qb->expr()->like('u.nickname', '?2') + )) + ->orderBy('u.surname', 'ASC'); + +Here is a complete list of helper methods available in ``QueryBuilder``: + +.. code-block:: php + + select('u') + // Example - $qb->select(array('u', 'p')) + // Example - $qb->select($qb->expr()->select('u', 'p')) + public function select($select = null); + + // addSelect does not override previous calls to select + // + // Example - $qb->select('u'); + // ->addSelect('p.area_code'); + public function addSelect($select = null); + + // Example - $qb->delete('User', 'u') + public function delete($delete = null, $alias = null); + + // Example - $qb->update('Group', 'g') + public function update($update = null, $alias = null); + + // Example - $qb->set('u.firstName', $qb->expr()->literal('Arnold')) + // Example - $qb->set('u.numChilds', 'u.numChilds + ?1') + // Example - $qb->set('u.numChilds', $qb->expr()->sum('u.numChilds', '?1')) + public function set($key, $value); + + // Example - $qb->from('Phonenumber', 'p') + // Example - $qb->from('Phonenumber', 'p', 'p.id') + public function from($from, $alias, $indexBy = null); + + // Example - $qb->join('u.Group', 'g', Expr\Join::WITH, $qb->expr()->eq('u.status_id', '?1')) + // Example - $qb->join('u.Group', 'g', 'WITH', 'u.status = ?1') + // Example - $qb->join('u.Group', 'g', 'WITH', 'u.status = ?1', 'g.id') + public function join($join, $alias, $conditionType = null, $condition = null, $indexBy = null); + + // Example - $qb->innerJoin('u.Group', 'g', Expr\Join::WITH, $qb->expr()->eq('u.status_id', '?1')) + // Example - $qb->innerJoin('u.Group', 'g', 'WITH', 'u.status = ?1') + // Example - $qb->innerJoin('u.Group', 'g', 'WITH', 'u.status = ?1', 'g.id') + public function innerJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null); + + // Example - $qb->leftJoin('u.Phonenumbers', 'p', Expr\Join::WITH, $qb->expr()->eq('p.area_code', 55)) + // Example - $qb->leftJoin('u.Phonenumbers', 'p', 'WITH', 'p.area_code = 55') + // Example - $qb->leftJoin('u.Phonenumbers', 'p', 'WITH', 'p.area_code = 55', 'p.id') + public function leftJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null); + + // NOTE: ->where() overrides all previously set conditions + // + // Example - $qb->where('u.firstName = ?1', $qb->expr()->eq('u.surname', '?2')) + // Example - $qb->where($qb->expr()->andX($qb->expr()->eq('u.firstName', '?1'), $qb->expr()->eq('u.surname', '?2'))) + // Example - $qb->where('u.firstName = ?1 AND u.surname = ?2') + public function where($where); + + // NOTE: ->andWhere() can be used directly, without any ->where() before + // + // Example - $qb->andWhere($qb->expr()->orX($qb->expr()->lte('u.age', 40), 'u.numChild = 0')) + public function andWhere($where); + + // Example - $qb->orWhere($qb->expr()->between('u.id', 1, 10)); + public function orWhere($where); + + // NOTE: -> groupBy() overrides all previously set grouping conditions + // + // Example - $qb->groupBy('u.id') + public function groupBy($groupBy); + + // Example - $qb->addGroupBy('g.name') + public function addGroupBy($groupBy); + + // NOTE: -> having() overrides all previously set having conditions + // + // Example - $qb->having('u.salary >= ?1') + // Example - $qb->having($qb->expr()->gte('u.salary', '?1')) + public function having($having); + + // Example - $qb->andHaving($qb->expr()->gt($qb->expr()->count('u.numChild'), 0)) + public function andHaving($having); + + // Example - $qb->orHaving($qb->expr()->lte('g.managerLevel', '100')) + public function orHaving($having); + + // NOTE: -> orderBy() overrides all previously set ordering conditions + // + // Example - $qb->orderBy('u.surname', 'DESC') + public function orderBy($sort, $order = null); + + // Example - $qb->addOrderBy('u.firstName') + public function addOrderBy($sort, $order = null); // Default $order = 'ASC' + } + +Binding parameters to your query +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Doctrine supports dynamic binding of parameters to your query, +similar to preparing queries. You can use both strings and numbers +as placeholders, although both have a slightly different syntax. +Additionally, you must make your choice: Mixing both styles is not +allowed. Binding parameters can simply be achieved as follows: + +.. code-block:: php + + select('u') + ->from('User', 'u') + ->where('u.id = ?1') + ->orderBy('u.name', 'ASC') + ->setParameter(1, 100); // Sets ?1 to 100, and thus we will fetch a user with u.id = 100 + +You are not forced to enumerate your placeholders as the +alternative syntax is available: + +.. code-block:: php + + select('u') + ->from('User', 'u') + ->where('u.id = :identifier') + ->orderBy('u.name', 'ASC') + ->setParameter('identifier', 100); // Sets :identifier to 100, and thus we will fetch a user with u.id = 100 + +Note that numeric placeholders start with a ? followed by a number +while the named placeholders start with a : followed by a string. + +Calling ``setParameter()`` automatically infers which type you are setting as +value. This works for integers, arrays of strings/integers, DateTime instances +and for managed entities. If you want to set a type explicitly you can call +the third argument to ``setParameter()`` explicitly. It accepts either a PDO +type or a DBAL Type name for conversion. + +If you've got several parameters to bind to your query, you can +also use setParameters() instead of setParameter() with the +following syntax: + +.. code-block:: php + + setParameters(array(1 => 'value for ?1', 2 => 'value for ?2')); + +Getting already bound parameters is easy - simply use the above +mentioned syntax with "getParameter()" or "getParameters()": + +.. code-block:: php + + getParameters(); + // $params instanceof \Doctrine\Common\Collections\ArrayCollection + + // Equivalent to + $param = $qb->getParameter(1); + // $param instanceof \Doctrine\ORM\Query\Parameter + +Note: If you try to get a parameter that was not bound yet, +getParameter() simply returns NULL. + +The API of a Query Parameter is: + +.. code-block:: php + + namespace Doctrine\ORM\Query; + + class Parameter + { + public function getName(); + public function getValue(); + public function getType(); + public function setValue($value, $type = null); + } + +Limiting the Result +^^^^^^^^^^^^^^^^^^^ + +To limit a result the query builder has some methods in common with +the Query object which can be retrieved from ``EntityManager#createQuery()``. + +.. code-block:: php + + add('select', 'u') + ->add('from', 'User u') + ->add('orderBy', 'u.name ASC') + ->setFirstResult( $offset ) + ->setMaxResults( $limit ); + +Executing a Query +^^^^^^^^^^^^^^^^^ + +The QueryBuilder is a builder object only - it has no means of actually +executing the Query. Additionally a set of parameters such as query hints +cannot be set on the QueryBuilder itself. This is why you always have to convert +a querybuilder instance into a Query object: + +.. code-block:: php + + getQuery(); + + // Set additional Query options + $query->setQueryHint('foo', 'bar'); + $query->useResultCache('my_cache_id'); + + // Execute Query + $result = $query->getResult(); + $single = $query->getSingleResult(); + $array = $query->getArrayResult(); + $scalar = $query->getScalarResult(); + $singleScalar = $query->getSingleScalarResult(); + +The Expr class +^^^^^^^^^^^^^^ + +To workaround some of the issues that ``add()`` method may cause, +Doctrine created a class that can be considered as a helper for +building expressions. This class is called ``Expr``, which provides a +set of useful methods to help build expressions: + +.. code-block:: php + + add('select', new Expr\Select(array('u'))) + ->add('from', new Expr\From('User', 'u')) + ->add('where', $qb->expr()->orX( + $qb->expr()->eq('u.id', '?1'), + $qb->expr()->like('u.nickname', '?2') + )) + ->add('orderBy', new Expr\OrderBy('u.name', 'ASC')); + +Although it still sounds complex, the ability to programmatically +create conditions are the main feature of ``Expr``. Here it is a +complete list of supported helper methods available: + +.. code-block:: php + + expr()->andX($cond1 [, $condN])->add(...)->... + public function andX($x = null); // Returns Expr\AndX instance + + // Example - $qb->expr()->orX($cond1 [, $condN])->add(...)->... + public function orX($x = null); // Returns Expr\OrX instance + + + /** Comparison objects **/ + + // Example - $qb->expr()->eq('u.id', '?1') => u.id = ?1 + public function eq($x, $y); // Returns Expr\Comparison instance + + // Example - $qb->expr()->neq('u.id', '?1') => u.id <> ?1 + public function neq($x, $y); // Returns Expr\Comparison instance + + // Example - $qb->expr()->lt('u.id', '?1') => u.id < ?1 + public function lt($x, $y); // Returns Expr\Comparison instance + + // Example - $qb->expr()->lte('u.id', '?1') => u.id <= ?1 + public function lte($x, $y); // Returns Expr\Comparison instance + + // Example - $qb->expr()->gt('u.id', '?1') => u.id > ?1 + public function gt($x, $y); // Returns Expr\Comparison instance + + // Example - $qb->expr()->gte('u.id', '?1') => u.id >= ?1 + public function gte($x, $y); // Returns Expr\Comparison instance + + // Example - $qb->expr()->isNull('u.id') => u.id IS NULL + public function isNull($x); // Returns string + + // Example - $qb->expr()->isNotNull('u.id') => u.id IS NOT NULL + public function isNotNull($x); // Returns string + + + /** Arithmetic objects **/ + + // Example - $qb->expr()->prod('u.id', '2') => u.id * 2 + public function prod($x, $y); // Returns Expr\Math instance + + // Example - $qb->expr()->diff('u.id', '2') => u.id - 2 + public function diff($x, $y); // Returns Expr\Math instance + + // Example - $qb->expr()->sum('u.id', '2') => u.id + 2 + public function sum($x, $y); // Returns Expr\Math instance + + // Example - $qb->expr()->quot('u.id', '2') => u.id / 2 + public function quot($x, $y); // Returns Expr\Math instance + + + /** Pseudo-function objects **/ + + // Example - $qb->expr()->exists($qb2->getDql()) + public function exists($subquery); // Returns Expr\Func instance + + // Example - $qb->expr()->all($qb2->getDql()) + public function all($subquery); // Returns Expr\Func instance + + // Example - $qb->expr()->some($qb2->getDql()) + public function some($subquery); // Returns Expr\Func instance + + // Example - $qb->expr()->any($qb2->getDql()) + public function any($subquery); // Returns Expr\Func instance + + // Example - $qb->expr()->not($qb->expr()->eq('u.id', '?1')) + public function not($restriction); // Returns Expr\Func instance + + // Example - $qb->expr()->in('u.id', array(1, 2, 3)) + // Make sure that you do NOT use something similar to $qb->expr()->in('value', array('stringvalue')) as this will cause Doctrine to throw an Exception. + // Instead, use $qb->expr()->in('value', array('?1')) and bind your parameter to ?1 (see section above) + public function in($x, $y); // Returns Expr\Func instance + + // Example - $qb->expr()->notIn('u.id', '2') + public function notIn($x, $y); // Returns Expr\Func instance + + // Example - $qb->expr()->like('u.firstname', $qb->expr()->literal('Gui%')) + public function like($x, $y); // Returns Expr\Comparison instance + + // Example - $qb->expr()->notLike('u.firstname', $qb->expr()->literal('Gui%')) + public function notLike($x, $y); // Returns Expr\Comparison instance + + // Example - $qb->expr()->between('u.id', '1', '10') + public function between($val, $x, $y); // Returns Expr\Func + + + /** Function objects **/ + + // Example - $qb->expr()->trim('u.firstname') + public function trim($x); // Returns Expr\Func + + // Example - $qb->expr()->concat('u.firstname', $qb->expr()->concat($qb->expr()->literal(' '), 'u.lastname')) + public function concat($x, $y); // Returns Expr\Func + + // Example - $qb->expr()->substring('u.firstname', 0, 1) + public function substring($x, $from, $len); // Returns Expr\Func + + // Example - $qb->expr()->lower('u.firstname') + public function lower($x); // Returns Expr\Func + + // Example - $qb->expr()->upper('u.firstname') + public function upper($x); // Returns Expr\Func + + // Example - $qb->expr()->length('u.firstname') + public function length($x); // Returns Expr\Func + + // Example - $qb->expr()->avg('u.age') + public function avg($x); // Returns Expr\Func + + // Example - $qb->expr()->max('u.age') + public function max($x); // Returns Expr\Func + + // Example - $qb->expr()->min('u.age') + public function min($x); // Returns Expr\Func + + // Example - $qb->expr()->abs('u.currentBalance') + public function abs($x); // Returns Expr\Func + + // Example - $qb->expr()->sqrt('u.currentBalance') + public function sqrt($x); // Returns Expr\Func + + // Example - $qb->expr()->count('u.firstname') + public function count($x); // Returns Expr\Func + + // Example - $qb->expr()->countDistinct('u.surname') + public function countDistinct($x); // Returns Expr\Func + } + +Adding a Criteria to a Query +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can also add a :ref:`filtering-collections` to a QueryBuilder by +using ``addCriteria``: + +.. code-block:: php + + orderBy(['firstName', 'ASC']); + + // $qb instanceof QueryBuilder + $qb->addCriteria($criteria); + // then execute your query like normal + +Low Level API +^^^^^^^^^^^^^ + +Now we will describe the low level method of creating queries. +It may be useful to work at this level for optimization purposes, +but most of the time it is preferred to work at a higher level of +abstraction. + +All helper methods in ``QueryBuilder`` actually rely on a single +one: ``add()``. This method is responsible of building every piece +of DQL. It takes 3 parameters: ``$dqlPartName``, ``$dqlPart`` and +``$append`` (default=false) + + +- ``$dqlPartName``: Where the ``$dqlPart`` should be placed. + Possible values: select, from, where, groupBy, having, orderBy +- ``$dqlPart``: What should be placed in ``$dqlPartName``. Accepts + a string or any instance of ``Doctrine\ORM\Query\Expr\*`` +- ``$append``: Optional flag (default=false) if the ``$dqlPart`` + should override all previously defined items in ``$dqlPartName`` or + not (no effect on the ``where`` and ``having`` DQL query parts, + which always override all previously defined items) + +- + +.. code-block:: php + + add('select', 'u') + ->add('from', 'User u') + ->add('where', 'u.id = ?1') + ->add('orderBy', 'u.name ASC'); + +Expr\* classes +^^^^^^^^^^^^^^ + +When you call ``add()`` with string, it internally evaluates to an +instance of ``Doctrine\ORM\Query\Expr\Expr\*`` class. Here is the +same query of example 6 written using +``Doctrine\ORM\Query\Expr\Expr\*`` classes: + +.. code-block:: php + + add('select', new Expr\Select(array('u'))) + ->add('from', new Expr\From('User', 'u')) + ->add('where', new Expr\Comparison('u.id', '=', '?1')) + ->add('orderBy', new Expr\OrderBy('u.name', 'ASC')); + diff --git a/vendor/doctrine/orm/docs/en/reference/second-level-cache.rst b/vendor/doctrine/orm/docs/en/reference/second-level-cache.rst new file mode 100644 index 0000000..8a0b4c2 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/second-level-cache.rst @@ -0,0 +1,731 @@ +The Second Level Cache +====================== + +.. note:: + + The second level cache functionality is marked as experimental for now. It + is a very complex feature and we cannot guarantee yet that it works stable + in all cases. + +The Second Level Cache is designed to reduce the amount of necessary database access. +It sits between your application and the database to avoid the number of database hits as much as possible. + +When turned on, entities will be first searched in cache and if they are not found, +a database query will be fired and then the entity result will be stored in a cache provider. + +There are some flavors of caching available, but is better to cache read-only data. + +Be aware that caches are not aware of changes made to the persistent store by another application. +They can, however, be configured to regularly expire cached data. + + +Caching Regions +--------------- + +Second level cache does not store instances of an entity, instead it caches only entity identifier and values. +Each entity class, collection association and query has its region, where values of each instance are stored. + +Caching Regions are specific region into the cache provider that might store entities, collection or queries. +Each cache region resides in a specific cache namespace and has its own lifetime configuration. + +Notice that when caching collection and queries only identifiers are stored. +The entity values will be stored in its own region + +Something like below for an entity region : + +.. code-block:: php + + ['id'=> 1, 'name' => 'FooBar', 'associationName'=>null], + 'region_name:entity_2_hash' => ['id'=> 2, 'name' => 'Foo', 'associationName'=>['id'=>11]], + 'region_name:entity_3_hash' => ['id'=> 3, 'name' => 'Bar', 'associationName'=>['id'=>22]] + ]; + + +If the entity holds a collection that also needs to be cached. +An collection region could look something like : + +.. code-block:: php + + ['ownerId'=> 1, 'list' => [1, 2, 3]], + 'region_name:entity_2_coll_assoc_name_hash' => ['ownerId'=> 2, 'list' => [2, 3]], + 'region_name:entity_3_coll_assoc_name_hash' => ['ownerId'=> 3, 'list' => [2, 4]] + ]; + +A query region might be something like : + +.. code-block:: php + + ['list' => [1, 2, 3]], + 'region_name:query_2_hash' => ['list' => [2, 3]], + 'region_name:query_3_hash' => ['list' => [2, 4]] + ]; + + +.. note:: + + The following data structures represents now the cache will looks like, this is not actual cached data. + + +.. _reference-second-level-cache-regions: + +Cache Regions +------------- + +``Doctrine\ORM\Cache\Region\DefaultRegion`` It's the default implementation. + A simplest cache region compatible with all doctrine-cache drivers but does not support locking. + +``Doctrine\ORM\Cache\Region`` and ``Doctrine\ORM\Cache\ConcurrentRegion`` +Defines contracts that should be implemented by a cache provider. + +It allows you to provide your own cache implementation that might take advantage of specific cache driver. + +If you want to support locking for ``READ_WRITE`` strategies you should implement ``ConcurrentRegion``; ``CacheRegion`` otherwise. + + +Cache region +~~~~~~~~~~~~ + +Defines a contract for accessing a particular region. + +``Doctrine\ORM\Cache\Region`` + +Defines a contract for accessing a particular cache region. + +`See API Doc `_. + +Concurrent cache region +~~~~~~~~~~~~~~~~~~~~~~~ + +A ``Doctrine\ORM\Cache\ConcurrentRegion`` is designed to store concurrently managed data region. +By default, Doctrine provides a very simple implementation based on file locks ``Doctrine\ORM\Cache\Region\FileLockRegion``. + +If you want to use an ``READ_WRITE`` cache, you should consider providing your own cache region. + +``Doctrine\ORM\Cache\ConcurrentRegion`` + +Defines contract for concurrently managed data region. + +`See API Doc `_. + +Timestamp region +~~~~~~~~~~~~~~~~ + +``Doctrine\ORM\Cache\TimestampRegion`` + +Tracks the timestamps of the most recent updates to particular entity. + +`See API Doc `_. + +.. _reference-second-level-cache-mode: + +Caching mode +------------ + +* ``READ_ONLY`` (DEFAULT) + + * Can do reads, inserts and deletes, cannot perform updates or employ any locks. + * Useful for data that is read frequently but never updated. + * Best performer. + * It is Simple. + +* ``NONSTRICT_READ_WRITE`` + + * Read Write Cache doesn’t employ any locks but can do reads, inserts, updates and deletes. + * Good if the application needs to update data rarely. + + +* ``READ_WRITE`` + + * Read Write cache employs locks before update/delete. + * Use if data needs to be updated. + * Slowest strategy. + * To use it a the cache region implementation must support locking. + + +Built-in cached persisters +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Cached persisters are responsible to access cache regions. + + +-----------------------+-------------------------------------------------------------------------------------------+ + | Cache Usage | Persister | + +=======================+===========================================================================================+ + | READ_ONLY | Doctrine\\ORM\\Cache\\Persister\\Entity\\ReadOnlyCachedEntityPersister | + +-----------------------+-------------------------------------------------------------------------------------------+ + | READ_WRITE | Doctrine\\ORM\\Cache\\Persister\\Entity\\ReadWriteCachedEntityPersister | + +-----------------------+-------------------------------------------------------------------------------------------+ + | NONSTRICT_READ_WRITE | Doctrine\\ORM\\Cache\\Persister\\Entity\\NonStrictReadWriteCachedEntityPersister | + +-----------------------+-------------------------------------------------------------------------------------------+ + | READ_ONLY | Doctrine\\ORM\\Cache\\Persister\\Collection\\ReadOnlyCachedCollectionPersister | + +-----------------------+-------------------------------------------------------------------------------------------+ + | READ_WRITE | Doctrine\\ORM\\Cache\\Persister\\Collection\\ReadWriteCachedCollectionPersister | + +-----------------------+-------------------------------------------------------------------------------------------+ + | NONSTRICT_READ_WRITE | Doctrine\\ORM\\Cache\\Persister\\Collection\\NonStrictReadWriteCachedCollectionPersister | + +-----------------------+-------------------------------------------------------------------------------------------+ + +Configuration +------------- +Doctrine allows you to specify configurations and some points of extension for the second-level-cache + + +Enable Second Level Cache +~~~~~~~~~~~~~~~~~~~~~~~~~ + +To enable the second-level-cache, you should provide a cache factory +``\Doctrine\ORM\Cache\DefaultCacheFactory`` is the default implementation. + +.. code-block:: php + + setSecondLevelCacheEnabled(); + + // Cache factory + $config->getSecondLevelCacheConfiguration() + ->setCacheFactory($factory); + + +Cache Factory +~~~~~~~~~~~~~ + +Cache Factory is the main point of extension. + +It allows you to provide a specific implementation of the following components : + +* ``QueryCache`` Store and retrieve query cache results. +* ``CachedEntityPersister`` Store and retrieve entity results. +* ``CachedCollectionPersister`` Store and retrieve query results. +* ``EntityHydrator`` Transform an entity into a cache entry and cache entry into entities +* ``CollectionHydrator`` Transform a collection into a cache entry and cache entry into collection + +`See API Doc `_. + +Region Lifetime +~~~~~~~~~~~~~~~ + +To specify a default lifetime for all regions or specify a different lifetime for a specific region. + +.. code-block:: php + + getSecondLevelCacheConfiguration(); + $regionConfig = $cacheConfig->getRegionsConfiguration(); + + // Cache Region lifetime + $regionConfig->setLifetime('my_entity_region', 3600); // Time to live for a specific region; In seconds + $regionConfig->setDefaultLifetime(7200); // Default time to live; In seconds + + +Cache Log +~~~~~~~~~ +By providing a cache logger you should be able to get information about all cache operations such as hits, misses and puts. + +``\Doctrine\ORM\Cache\Logging\StatisticsCacheLogger`` is a built-in implementation that provides basic statistics. + + .. code-block:: php + + setSecondLevelCacheEnabled(true); + $config->getSecondLevelCacheConfiguration() + ->setCacheLogger($logger); + + + // Collect cache statistics + + // Get the number of entries successfully retrieved from a specific region. + $logger->getRegionHitCount('my_entity_region'); + + // Get the number of cached entries *not* found in a specific region. + $logger->getRegionMissCount('my_entity_region'); + + // Get the number of cacheable entries put in cache. + $logger->getRegionPutCount('my_entity_region'); + + // Get the total number of put in all regions. + $logger->getPutCount(); + + // Get the total number of entries successfully retrieved from all regions. + $logger->getHitCount(); + + // Get the total number of cached entries *not* found in all regions. + $logger->getMissCount(); + +If you want to get more information you should implement ``\Doctrine\ORM\Cache\Logging\CacheLogger``. +and collect all information you want. + +`See API Doc `_. + + +Entity cache definition +----------------------- +* Entity cache configuration allows you to define the caching strategy and region for an entity. + + * ``usage`` Specifies the caching strategy: ``READ_ONLY``, ``NONSTRICT_READ_WRITE``, ``READ_WRITE``. see :ref:`reference-second-level-cache-mode` + * ``region`` Optional value that specifies the name of the second level cache region. + + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + + + + .. code-block:: yaml + + Country: + type: entity + cache: + usage : READ_ONLY + region : my_entity_region + id: + id: + type: integer + id: true + generator: + strategy: IDENTITY + fields: + name: + type: string + + +Association cache definition +---------------------------- +The most common use case is to cache entities. But we can also cache relationships. +It caches the primary keys of association and cache each element will be cached into its region. + + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + + + + + + + + + + + + + + + + + + + .. code-block:: yaml + + State: + type: entity + cache: + usage : NONSTRICT_READ_WRITE + id: + id: + type: integer + id: true + generator: + strategy: IDENTITY + fields: + name: + type: string + + manyToOne: + state: + targetEntity: Country + joinColumns: + country_id: + referencedColumnName: id + cache: + usage : NONSTRICT_READ_WRITE + + oneToMany: + cities: + targetEntity:City + mappedBy: state + cache: + usage : NONSTRICT_READ_WRITE + + +> Note: for this to work, the target entity must also be marked as cacheable. + +Cache usage +~~~~~~~~~~~ + +Basic entity cache + +.. code-block:: php + + persist(new Country($name)); + $em->flush(); // Hit database to insert the row and put into cache + + $em->clear(); // Clear entity manager + + $country1 = $em->find('Country', 1); // Retrieve item from cache + + $country->setName("New Name"); + $em->persist($country); + $em->flush(); // Hit database to update the row and update cache + + $em->clear(); // Clear entity manager + + $country2 = $em->find('Country', 1); // Retrieve item from cache + // Notice that $country1 and $country2 are not the same instance. + + +Association cache + +.. code-block:: php + + persist(new State($name, $country)); + $em->flush(); + + // Clear entity manager + $em->clear(); + + // Retrieve item from cache + $state = $em->find('State', 1); + + // Hit database to update the row and update cache entry + $state->setName("New Name"); + $em->persist($state); + $em->flush(); + + // Create a new collection item + $city = new City($name, $state); + $state->addCity($city); + + // Hit database to insert new collection item, + // put entity and collection cache into cache. + $em->persist($city); + $em->persist($state); + $em->flush(); + + // Clear entity manager + $em->clear(); + + // Retrieve item from cache + $state = $em->find('State', 1); + + // Retrieve association from cache + $country = $state->getCountry(); + + // Retrieve collection from cache + $cities = $state->getCities(); + + echo $country->getName(); + echo $state->getName(); + + // Retrieve each collection item from cache + foreach ($cities as $city) { + echo $city->getName(); + } + +.. note:: + + Notice that all entities should be marked as cacheable. + +Using the query cache +--------------------- + +The second level cache stores the entities, associations and collections. +The query cache stores the results of the query but as identifiers, entity values are actually stored in the 2nd level cache. + +.. note:: + + Query cache should always be used in conjunction with the second-level-cache for those entities which should be cached. + +.. code-block:: php + + createQuery('SELECT c FROM Country c ORDER BY c.name') + ->setCacheable(true) + ->getResult(); + + $em->clear() + + // Check if query result is valid and load entities from cache + $result2 = $em->createQuery('SELECT c FROM Country c ORDER BY c.name') + ->setCacheable(true) + ->getResult(); + +Cache mode +~~~~~~~~~~ + +The Cache Mode controls how a particular query interacts with the second-level cache: + +* ``Cache::MODE_GET`` - May read items from the cache, but will not add items. +* ``Cache::MODE_PUT`` - Will never read items from the cache, but will add items to the cache as it reads them from the database. +* ``Cache::MODE_NORMAL`` - May read items from the cache, and add items to the cache. +* ``Cache::MODE_REFRESH`` - The query will never read items from the cache, but will refresh items to the cache as it reads them from the database. + +.. code-block:: php + + createQuery('SELECT c FROM Country c ORDER BY c.name') + ->setCacheMode(Cache::MODE_GET) + ->setCacheable(true) + ->getResult(); + +.. note:: + + The the default query cache mode is ```Cache::MODE_NORMAL``` + +DELETE / UPDATE queries +~~~~~~~~~~~~~~~~~~~~~~~ + +DQL UPDATE / DELETE statements are ported directly into a database and bypass the second-level cache, +Entities that are already cached will NOT be invalidated. +However the cached data could be evicted using the cache API or an special query hint. + + +Execute the ``UPDATE`` and invalidate ``all cache entries`` using ``Query::HINT_CACHE_EVICT`` + +.. code-block:: php + + _em->createQuery("UPDATE Entity\Country u SET u.name = 'unknown' WHERE u.id = 1") + ->setHint(Query::HINT_CACHE_EVICT, true) + ->execute(); + + +Execute the ``UPDATE`` and invalidate ``all cache entries`` using the cache API + +.. code-block:: php + + _em->createQuery("UPDATE Entity\Country u SET u.name = 'unknown' WHERE u.id = 1") + ->execute(); + // Invoke Cache API + $em->getCache()->evictEntityRegion('Entity\Country'); + + +Execute the ``UPDATE`` and invalidate ``a specific cache entry`` using the cache API + +.. code-block:: php + + _em->createQuery("UPDATE Entity\Country u SET u.name = 'unknown' WHERE u.id = 1") + ->execute(); + // Invoke Cache API + $em->getCache()->evictEntity('Entity\Country', 1); + +Using the repository query cache +-------------------------------- + +As well as ``Query Cache`` all persister queries store only identifier values for an individual query. +All persister use a single timestamps cache region keeps track of the last update for each persister, +When a query is loaded from cache, the timestamp region is checked for the last update for that persister. +Using the last update timestamps as part of the query key invalidate the cache key when an update occurs. + +.. code-block:: php + + getRepository('Entity\Country')->findAll(); + + // load from query and entities from cache.. + $entities = $em->getRepository('Entity\Country')->findAll(); + + // update the timestamp cache region for Country + $em->persist(new Country('zombieland')); + $em->flush(); + $em->clear(); + + // Reload from database. + // At this point the query cache key if not logger valid, the select goes straight + $entities = $em->getRepository('Entity\Country')->findAll(); + +Cache API +--------- + +Caches are not aware of changes made by another application. +However, you can use the cache API to check / invalidate cache entries. + +.. code-block:: php + + getCache(); + + $cache->containsEntity('Entity\State', 1) // Check if the cache exists + $cache->evictEntity('Entity\State', 1); // Remove an entity from cache + $cache->evictEntityRegion('Entity\State'); // Remove all entities from cache + + $cache->containsCollection('Entity\State', 'cities', 1); // Check if the cache exists + $cache->evictCollection('Entity\State', 'cities', 1); // Remove an entity collection from cache + $cache->evictCollectionRegion('Entity\State', 'cities'); // Remove all collections from cache + +Limitations +----------- + +Composite primary key +~~~~~~~~~~~~~~~~~~~~~ + +Composite primary key are supported by second level cache, +however when one of the keys is an association the cached entity should always be retrieved using the association identifier. +For performance reasons the cache API does not extract from composite primary key. + +.. code-block:: php + + find('Article', 1); + + // Supported + /* @var $article Article */ + $article = $em->find('Article', $article); + + // Supported + $id = array('source' => 1, 'target' => 2); + $reference = $em->find('Reference', $id); + + // NOT Supported + $id = array('source' => new Article(1), 'target' => new Article(2)); + $reference = $em->find('Reference', $id); + +Distributed environments +~~~~~~~~~~~~~~~~~~~~~~~~ + +Some cache driver are not meant to be used in a distributed environment. +Load-balancer for distributing workloads across multiple computing resources +should be used in conjunction with distributed caching system such as memcached, redis, riak ... + +Caches should be used with care when using a load-balancer if you don't share the cache. +While using APC or any file based cache update occurred in a specific machine would not reflect to the cache in other machines. + + +Paginator +~~~~~~~~~ + +Count queries generated by ``Doctrine\ORM\Tools\Pagination\Paginator`` are not cached by second-level cache. +Although entities and query result are cached count queries will hit the database every time. diff --git a/vendor/doctrine/orm/docs/en/reference/security.rst b/vendor/doctrine/orm/docs/en/reference/security.rst new file mode 100644 index 0000000..0101e86 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/security.rst @@ -0,0 +1,151 @@ +Security +======== + +The Doctrine library is operating very close to your database and as such needs +to handle and make assumptions about SQL injection vulnerabilities. + +It is vital that you understand how Doctrine approaches security, because +we cannot protect you from SQL injection. + +Please also read the documentation chapter on Security in Doctrine DBAL. This +page only handles Security issues in the ORM. + +- `DBAL Security Page ` + +If you find a Security bug in Doctrine, please report it on Jira and change the +Security Level to "Security Issues". It will be visible to Doctrine Core +developers and you only. + +User input and Doctrine ORM +--------------------------- + +The ORM is much better at protecting against SQL injection than the DBAL alone. +You can consider the following APIs to be safe from SQL injection: + +- ``\Doctrine\ORM\EntityManager#find()`` and ``getReference()``. +- All values on Objects inserted and updated through ``Doctrine\ORM\EntityManager#persist()`` +- All find methods on ``Doctrine\ORM\EntityRepository``. +- User Input set to DQL Queries or QueryBuilder methods through + - ``setParameter()`` or variants + - ``setMaxResults()`` + - ``setFirstResult()`` +- Queries through the Criteria API on ``Doctrine\ORM\PersistentCollection`` and + ``Doctrine\ORM\EntityRepository``. + +You are **NOT** safe from SQL injection when using user input with: + +- Expression API of ``Doctrine\ORM\QueryBuilder`` +- Concatenating user input into DQL SELECT, UPDATE or DELETE statements or + Native SQL. + +This means SQL injections can only occur with Doctrine ORM when working with +Query Objects of any kind. The safe rule is to always use prepared statement +parameters for user objects when using a Query object. + +.. warning:: + + Insecure code follows, don't copy paste this. + +The following example shows insecure DQL usage: + +.. code-block:: php + + createQuery($dql); + $query->setParameter(1, $_GET['status']); + + +Preventing Mass Assignment Vulnerabilities +------------------------------------------ + +ORMs are very convenient for CRUD applications and Doctrine is no exception. +However CRUD apps are often vulnerable to mass assignment security problems +when implemented naively. + +Doctrine is not vulnerable to this problem out of the box, but you can easily +make your entities vulnerable to mass assignment when you add methods of +the kind ``updateFromArray()`` or ``updateFromJson()`` to them. A vulnerable +entity might look like this: + +.. code-block:: php + + $value) { + $this->$key = $value; + } + } + } + +Now the possiblity of mass-asignment exists on this entity and can +be exploited by attackers to set the "isAdmin" flag to true on any +object when you pass the whole request data to this method like: + +.. code-block:: php + + fromArray($_POST); + + $entityManager->persist($entity); + $entityManager->flush(); + +You can spot this problem in this very simple example easily. However +in combination with frameworks and form libraries it might not be +so obvious when this issue arises. Be careful to avoid this +kind of mistake. + +How to fix this problem? You should always have a whitelist +of allowed key to set via mass assignment functions. + +.. code-block:: php + + public function fromArray(array $userInput, $allowedFields = array()) + { + foreach ($userInput as $key => $value) { + if (in_array($key, $allowedFields)) { + $this->$key = $value; + } + } + } diff --git a/vendor/doctrine/orm/docs/en/reference/tools.rst b/vendor/doctrine/orm/docs/en/reference/tools.rst new file mode 100644 index 0000000..3b6cf33 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/tools.rst @@ -0,0 +1,520 @@ +Tools +===== + +Doctrine Console +---------------- + +The Doctrine Console is a Command Line Interface tool for simplifying common +administration tasks during the development of a project that uses Doctrine 2. + +Take a look at the :doc:`Installation and Configuration ` +chapter for more information how to setup the console command. + +Display Help Information +~~~~~~~~~~~~~~~~~~~~~~~~ + +Type ``php vendor/bin/doctrine`` on the command line and you should see an +overview of the available commands or use the --help flag to get +information on the available commands. If you want to know more +about the use of generate entities for example, you can call: + +.. code-block:: php + + $> php vendor/bin/doctrine orm:generate-entities --help + + +Configuration +~~~~~~~~~~~~~ + +Whenever the ``doctrine`` command line tool is invoked, it can +access all Commands that were registered by developer. There is no +auto-detection mechanism at work. The Doctrine binary +already registers all the commands that currently ship with +Doctrine DBAL and ORM. If you want to use additional commands you +have to register them yourself. + +All the commands of the Doctrine Console require access to the ``EntityManager`` +or ``DBAL`` Connection. You have to inject them into the console application +using so called Helper-Sets. This requires either the ``db`` +or the ``em`` helpers to be defined in order to work correctly. + +Whenever you invoke the Doctrine binary the current folder is searched for a +``cli-config.php`` file. This file contains the project specific configuration: + +.. code-block:: php + + new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($conn) + )); + $cli->setHelperSet($helperSet); + +When dealing with the ORM package, the EntityManagerHelper is +required: + +.. code-block:: php + + new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) + )); + $cli->setHelperSet($helperSet); + +The HelperSet instance has to be generated in a separate file (i.e. +``cli-config.php``) that contains typical Doctrine bootstrap code +and predefines the needed HelperSet attributes mentioned above. A +sample ``cli-config.php`` file looks as follows: + +.. code-block:: php + + new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()), + 'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) + )); + +It is important to define a correct HelperSet that Doctrine binary +script will ultimately use. The Doctrine Binary will automatically +find the first instance of HelperSet in the global variable +namespace and use this. + +.. note:: + + You have to adjust this snippet for your specific application or framework + and use their facilities to access the Doctrine EntityManager and + Connection Resources. + +Command Overview +~~~~~~~~~~~~~~~~ + +The following Commands are currently available: + + +- ``help`` Displays help for a command (?) +- ``list`` Lists commands +- ``dbal:import`` Import SQL file(s) directly to Database. +- ``dbal:run-sql`` Executes arbitrary SQL directly from the + command line. +- ``orm:clear-cache:metadata`` Clear all metadata cache of the + various cache drivers. +- ``orm:clear-cache:query`` Clear all query cache of the various + cache drivers. +- ``orm:clear-cache:result`` Clear result cache of the various + cache drivers. +- ``orm:convert-d1-schema`` Converts Doctrine 1.X schema into a + Doctrine 2.X schema. +- ``orm:convert-mapping`` Convert mapping information between + supported formats. +- ``orm:ensure-production-settings`` Verify that Doctrine is + properly configured for a production environment. +- ``orm:generate-entities`` Generate entity classes and method + stubs from your mapping information. +- ``orm:generate-proxies`` Generates proxy classes for entity + classes. +- ``orm:generate-repositories`` Generate repository classes from + your mapping information. +- ``orm:run-dql`` Executes arbitrary DQL directly from the command + line. +- ``orm:schema-tool:create`` Processes the schema and either + create it directly on EntityManager Storage Connection or generate + the SQL output. +- ``orm:schema-tool:drop`` Processes the schema and either drop + the database schema of EntityManager Storage Connection or generate + the SQL output. +- ``orm:schema-tool:update`` Processes the schema and either + update the database schema of EntityManager Storage Connection or + generate the SQL output. + +For these commands are also available aliases: + + +- ``orm:convert:d1-schema`` is alias for ``orm:convert-d1-schema``. +- ``orm:convert:mapping`` is alias for ``orm:convert-mapping``. +- ``orm:generate:entities`` is alias for ``orm:generate-entities``. +- ``orm:generate:proxies`` is alias for ``orm:generate-proxies``. +- ``orm:generate:repositories`` is alias for ``orm:generate-repositories``. + +.. note:: + + Console also supports auto completion, for example, instead of + ``orm:clear-cache:query`` you can use just ``o:c:q``. + +Database Schema Generation +-------------------------- + +.. note:: + + SchemaTool can do harm to your database. It will drop or alter + tables, indexes, sequences and such. Please use this tool with + caution in development and not on a production server. It is meant + for helping you develop your Database Schema, but NOT with + migrating schema from A to B in production. A safe approach would + be generating the SQL on development server and saving it into SQL + Migration files that are executed manually on the production + server. + + SchemaTool assumes your Doctrine Project uses the given database on + its own. Update and Drop commands will mess with other tables if + they are not related to the current project that is using Doctrine. + Please be careful! + + +To generate your database schema from your Doctrine mapping files +you can use the ``SchemaTool`` class or the ``schema-tool`` Console +Command. + +When using the SchemaTool class directly, create your schema using +the ``createSchema()`` method. First create an instance of the +``SchemaTool`` and pass it an instance of the ``EntityManager`` +that you want to use to create the schema. This method receives an +array of ``ClassMetadataInfo`` instances. + +.. code-block:: php + + getClassMetadata('Entities\User'), + $em->getClassMetadata('Entities\Profile') + ); + $tool->createSchema($classes); + +To drop the schema you can use the ``dropSchema()`` method. + +.. code-block:: php + + dropSchema($classes); + +This drops all the tables that are currently used by your metadata +model. When you are changing your metadata a lot during development +you might want to drop the complete database instead of only the +tables of the current model to clean up with orphaned tables. + +.. code-block:: php + + dropSchema($classes, \Doctrine\ORM\Tools\SchemaTool::DROP_DATABASE); + +You can also use database introspection to update your schema +easily with the ``updateSchema()`` method. It will compare your +existing database schema to the passed array of +``ClassMetadataInfo`` instances. + +.. code-block:: php + + updateSchema($classes); + +If you want to use this functionality from the command line you can +use the ``schema-tool`` command. + +To create the schema use the ``create`` command: + +.. code-block:: php + + $ php doctrine orm:schema-tool:create + +To drop the schema use the ``drop`` command: + +.. code-block:: php + + $ php doctrine orm:schema-tool:drop + +If you want to drop and then recreate the schema then use both +options: + +.. code-block:: php + + $ php doctrine orm:schema-tool:drop + $ php doctrine orm:schema-tool:create + +As you would think, if you want to update your schema use the +``update`` command: + +.. code-block:: php + + $ php doctrine orm:schema-tool:update + +All of the above commands also accept a ``--dump-sql`` option that +will output the SQL for the ran operation. + +.. code-block:: php + + $ php doctrine orm:schema-tool:create --dump-sql + +Before using the orm:schema-tool commands, remember to configure +your cli-config.php properly. + +Entity Generation +----------------- + +Generate entity classes and method stubs from your mapping information. + +.. code-block:: php + + $ php doctrine orm:generate-entities + $ php doctrine orm:generate-entities --update-entities + $ php doctrine orm:generate-entities --regenerate-entities + +This command is not suited for constant usage. It is a little helper and does +not support all the mapping edge cases very well. You still have to put work +in your entities after using this command. + +It is possible to use the EntityGenerator on code that you have already written. It will +not be lost. The EntityGenerator will only append new code to your +file and will not delete the old code. However this approach may still be prone +to error and we suggest you use code repositories such as GIT or SVN to make +backups of your code. + +It makes sense to generate the entity code if you are using entities as Data +Access Objects only and don't put much additional logic on them. If you are +however putting much more logic on the entities you should refrain from using +the entity-generator and code your entities manually. + +.. note:: + + Even if you specified Inheritance options in your + XML or YAML Mapping files the generator cannot generate the base and + child classes for you correctly, because it doesn't know which + class is supposed to extend which. You have to adjust the entity + code manually for inheritance to work! + + +Convert Mapping Information +--------------------------- + +Convert mapping information between supported formats. + +This is an **execute one-time** command. It should not be necessary for +you to call this method multiple times, especially when using the ``--from-database`` +flag. + +Converting an existing database schema into mapping files only solves about 70-80% +of the necessary mapping information. Additionally the detection from an existing +database cannot detect inverse associations, inheritance types, +entities with foreign keys as primary keys and many of the +semantical operations on associations such as cascade. + +.. note:: + + There is no need to convert YAML or XML mapping files to annotations + every time you make changes. All mapping drivers are first class citizens + in Doctrine 2 and can be used as runtime mapping for the ORM. See the + docs on XML and YAML Mapping for an example how to register this metadata + drivers as primary mapping source. + +To convert some mapping information between the various supported +formats you can use the ``ClassMetadataExporter`` to get exporter +instances for the different formats: + +.. code-block:: php + + getExporter('yml', '/path/to/export/yml'); + +Now you can export some ``ClassMetadata`` instances: + +.. code-block:: php + + getClassMetadata('Entities\User'), + $em->getClassMetadata('Entities\Profile') + ); + $exporter->setMetadata($classes); + $exporter->export(); + +This functionality is also available from the command line to +convert your loaded mapping information to another format. The +``orm:convert-mapping`` command accepts two arguments, the type to +convert to and the path to generate it: + +.. code-block:: php + + $ php doctrine orm:convert-mapping xml /path/to/mapping-path-converted-to-xml + +Reverse Engineering +------------------- + +You can use the ``DatabaseDriver`` to reverse engineer a database +to an array of ``ClassMetadataInfo`` instances and generate YAML, +XML, etc. from them. + +.. note:: + + Reverse Engineering is a **one-time** process that can get you started with a project. + Converting an existing database schema into mapping files only detects about 70-80% + of the necessary mapping information. Additionally the detection from an existing + database cannot detect inverse associations, inheritance types, + entities with foreign keys as primary keys and many of the + semantical operations on associations such as cascade. + +First you need to retrieve the metadata instances with the +``DatabaseDriver``: + +.. code-block:: php + + getConfiguration()->setMetadataDriverImpl( + new \Doctrine\ORM\Mapping\Driver\DatabaseDriver( + $em->getConnection()->getSchemaManager() + ) + ); + + $cmf = new \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory(); + $cmf->setEntityManager($em); + $metadata = $cmf->getAllMetadata(); + +Now you can get an exporter instance and export the loaded metadata +to yml: + +.. code-block:: php + + getExporter('yml', '/path/to/export/yml'); + $exporter->setMetadata($metadata); + $exporter->export(); + +You can also reverse engineer a database using the +``orm:convert-mapping`` command: + +.. code-block:: php + + $ php doctrine orm:convert-mapping --from-database yml /path/to/mapping-path-converted-to-yml + +.. note:: + + Reverse Engineering is not always working perfectly + depending on special cases. It will only detect Many-To-One + relations (even if they are One-To-One) and will try to create + entities from Many-To-Many tables. It also has problems with naming + of foreign keys that have multiple column names. Any Reverse + Engineered Database-Schema needs considerable manual work to become + a useful domain model. + + +Runtime vs Development Mapping Validation +----------------------------------------- + +For performance reasons Doctrine 2 has to skip some of the +necessary validation of metadata mappings. You have to execute +this validation in your development workflow to verify the +associations are correctly defined. + +You can either use the Doctrine Command Line Tool: + +.. code-block:: php + + doctrine orm:validate-schema + +Or you can trigger the validation manually: + +.. code-block:: php + + validateMapping(); + + if (count($errors) > 0) { + // Lots of errors! + echo implode("\n\n", $errors); + } + +If the mapping is invalid the errors array contains a positive +number of elements with error messages. + +.. warning:: + + One mapping option that is not validated is the use of the referenced column name. + It has to point to the equivalent primary key otherwise Doctrine will not work. + +.. note:: + + One common error is to use a backlash in front of the + fully-qualified class-name. Whenever a FQCN is represented inside a + string (such as in your mapping definitions) you have to drop the + prefix backslash. PHP does this with ``get_class()`` or Reflection + methods for backwards compatibility reasons. + + +Adding own commands +------------------- + +You can also add your own commands on-top of the Doctrine supported +tools if you are using a manually built console script. + +To include a new command on Doctrine Console, you need to do modify the +``doctrine.php`` file a little: + +.. code-block:: php + + setCatchExceptions(true); + $cli->setHelperSet($helperSet); + + // Register All Doctrine Commands + ConsoleRunner::addCommands($cli); + + // Register your own command + $cli->addCommand(new \MyProject\Tools\Console\Commands\MyCustomCommand); + + // Runs console application + $cli->run(); + +Additionally, include multiple commands (and overriding previously +defined ones) is possible through the command: + +.. code-block:: php + + addCommands(array( + new \MyProject\Tools\Console\Commands\MyCustomCommand(), + new \MyProject\Tools\Console\Commands\SomethingCommand(), + new \MyProject\Tools\Console\Commands\AnotherCommand(), + new \MyProject\Tools\Console\Commands\OneMoreCommand(), + )); + + +Re-use console application +-------------------------- + +You are also able to retrieve and re-use the default console application. +Just call ``ConsoleRunner::createApplication(...)`` with an appropriate +HelperSet, like it is described in the configuration section. + +.. code-block:: php + + run(); + diff --git a/vendor/doctrine/orm/docs/en/reference/transactions-and-concurrency.rst b/vendor/doctrine/orm/docs/en/reference/transactions-and-concurrency.rst new file mode 100644 index 0000000..5ce0852 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/transactions-and-concurrency.rst @@ -0,0 +1,409 @@ +Transactions and Concurrency +============================ + +.. _transactions-and-concurrency_transaction-demarcation: + +Transaction Demarcation +----------------------- + +Transaction demarcation is the task of defining your transaction +boundaries. Proper transaction demarcation is very important +because if not done properly it can negatively affect the +performance of your application. Many databases and database +abstraction layers like PDO by default operate in auto-commit mode, +which means that every single SQL statement is wrapped in a small +transaction. Without any explicit transaction demarcation from your +side, this quickly results in poor performance because transactions +are not cheap. + +For the most part, Doctrine 2 already takes care of proper +transaction demarcation for you: All the write operations +(INSERT/UPDATE/DELETE) are queued until ``EntityManager#flush()`` +is invoked which wraps all of these changes in a single +transaction. + +However, Doctrine 2 also allows (and encourages) you to take over +and control transaction demarcation yourself. + +These are two ways to deal with transactions when using the +Doctrine ORM and are now described in more detail. + +.. _transactions-and-concurrency_approach-implicitly: + +Approach 1: Implicitly +~~~~~~~~~~~~~~~~~~~~~~ + +The first approach is to use the implicit transaction handling +provided by the Doctrine ORM EntityManager. Given the following +code snippet, without any explicit transaction demarcation: + +.. code-block:: php + + setName('George'); + $em->persist($user); + $em->flush(); + +Since we do not do any custom transaction demarcation in the above +code, ``EntityManager#flush()`` will begin and commit/rollback a +transaction. This behavior is made possible by the aggregation of +the DML operations by the Doctrine ORM and is sufficient if all the +data manipulation that is part of a unit of work happens through +the domain model and thus the ORM. + +.. _transactions-and-concurrency_approach-explicitly: + +Approach 2: Explicitly +~~~~~~~~~~~~~~~~~~~~~~ + +The explicit alternative is to use the ``Doctrine\DBAL\Connection`` +API directly to control the transaction boundaries. The code then +looks like this: + +.. code-block:: php + + getConnection()->beginTransaction(); // suspend auto-commit + try { + //... do some work + $user = new User; + $user->setName('George'); + $em->persist($user); + $em->flush(); + $em->getConnection()->commit(); + } catch (Exception $e) { + $em->getConnection()->rollBack(); + throw $e; + } + +Explicit transaction demarcation is required when you want to +include custom DBAL operations in a unit of work or when you want +to make use of some methods of the ``EntityManager`` API that +require an active transaction. Such methods will throw a +``TransactionRequiredException`` to inform you of that +requirement. + +A more convenient alternative for explicit transaction demarcation is the use +of provided control abstractions in the form of +``Connection#transactional($func)`` and ``EntityManager#transactional($func)``. +When used, these control abstractions ensure that you never forget to rollback +the transaction, in addition to the obvious code reduction. An example that is +functionally equivalent to the previously shown code looks as follows: + +.. code-block:: php + + transactional(function($em) { + //... do some work + $user = new User; + $user->setName('George'); + $em->persist($user); + }); + +.. warning:: + + For historical reasons, ``EntityManager#transactional($func)`` will return + ``true`` whenever the return value of ``$func`` is loosely false. + Some examples of this include ``array()``, ``"0"``, ``""``, ``0``, and + ``null``. + +The difference between ``Connection#transactional($func)`` and +``EntityManager#transactional($func)`` is that the latter +abstraction flushes the ``EntityManager`` prior to transaction +commit and rolls back the transaction when an +exception occurs. + +.. _transactions-and-concurrency_exception-handling: + +Exception Handling +~~~~~~~~~~~~~~~~~~ + +When using implicit transaction demarcation and an exception occurs +during ``EntityManager#flush()``, the transaction is automatically +rolled back and the ``EntityManager`` closed. + +When using explicit transaction demarcation and an exception +occurs, the transaction should be rolled back immediately and the +``EntityManager`` closed by invoking ``EntityManager#close()`` and +subsequently discarded, as demonstrated in the example above. This +can be handled elegantly by the control abstractions shown earlier. +Note that when catching ``Exception`` you should generally re-throw +the exception. If you intend to recover from some exceptions, catch +them explicitly in earlier catch blocks (but do not forget to +rollback the transaction and close the ``EntityManager`` there as +well). All other best practices of exception handling apply +similarly (i.e. either log or re-throw, not both, etc.). + +As a result of this procedure, all previously managed or removed +instances of the ``EntityManager`` become detached. The state of +the detached objects will be the state at the point at which the +transaction was rolled back. The state of the objects is in no way +rolled back and thus the objects are now out of synch with the +database. The application can continue to use the detached objects, +knowing that their state is potentially no longer accurate. + +If you intend to start another unit of work after an exception has +occurred you should do that with a new ``EntityManager``. + +.. _transactions-and-concurrency_locking-support: + +Locking Support +--------------- + +Doctrine 2 offers support for Pessimistic- and Optimistic-locking +strategies natively. This allows to take very fine-grained control +over what kind of locking is required for your Entities in your +application. + +.. _transactions-and-concurrency_optimistic-locking: + +Optimistic Locking +~~~~~~~~~~~~~~~~~~ + +Database transactions are fine for concurrency control during a +single request. However, a database transaction should not span +across requests, the so-called "user think time". Therefore a +long-running "business transaction" that spans multiple requests +needs to involve several database transactions. Thus, database +transactions alone can no longer control concurrency during such a +long-running business transaction. Concurrency control becomes the +partial responsibility of the application itself. + +Doctrine has integrated support for automatic optimistic locking +via a version field. In this approach any entity that should be +protected against concurrent modifications during long-running +business transactions gets a version field that is either a simple +number (mapping type: integer) or a timestamp (mapping type: +datetime). When changes to such an entity are persisted at the end +of a long-running conversation the version of the entity is +compared to the version in the database and if they don't match, an +``OptimisticLockException`` is thrown, indicating that the entity +has been modified by someone else already. + +You designate a version field in an entity as follows. In this +example we'll use an integer. + +.. configuration-block:: + + .. code-block:: php + + + + + + + + .. code-block:: yaml + + User: + type: entity + fields: + version: + type: integer + version: true + +Alternatively a datetime type can be used (which maps to a SQL +timestamp or datetime): + +.. configuration-block:: + + .. code-block:: php + + + + + + + + .. code-block:: yaml + + User: + type: entity + fields: + version: + type: datetime + version: true + +Version numbers (not timestamps) should however be preferred as +they can not potentially conflict in a highly concurrent +environment, unlike timestamps where this is a possibility, +depending on the resolution of the timestamp on the particular +database platform. + +When a version conflict is encountered during +``EntityManager#flush()``, an ``OptimisticLockException`` is thrown +and the active transaction rolled back (or marked for rollback). +This exception can be caught and handled. Potential responses to an +OptimisticLockException are to present the conflict to the user or +to refresh or reload objects in a new transaction and then retrying +the transaction. + +With PHP promoting a share-nothing architecture, the time between +showing an update form and actually modifying the entity can in the +worst scenario be as long as your applications session timeout. If +changes happen to the entity in that time frame you want to know +directly when retrieving the entity that you will hit an optimistic +locking exception: + +You can always verify the version of an entity during a request +either when calling ``EntityManager#find()``: + +.. code-block:: php + + find('User', $theEntityId, LockMode::OPTIMISTIC, $expectedVersion); + + // do the work + + $em->flush(); + } catch(OptimisticLockException $e) { + echo "Sorry, but someone else has already changed this entity. Please apply the changes again!"; + } + +Or you can use ``EntityManager#lock()`` to find out: + +.. code-block:: php + + find('User', $theEntityId); + + try { + // assert version + $em->lock($entity, LockMode::OPTIMISTIC, $expectedVersion); + + } catch(OptimisticLockException $e) { + echo "Sorry, but someone else has already changed this entity. Please apply the changes again!"; + } + +Important Implementation Notes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can easily get the optimistic locking workflow wrong if you +compare the wrong versions. Say you have Alice and Bob editing a +hypothetical blog post: + +- Alice reads the headline of the blog post being "Foo", at + optimistic lock version 1 (GET Request) +- Bob reads the headline of the blog post being "Foo", at + optimistic lock version 1 (GET Request) +- Bob updates the headline to "Bar", upgrading the optimistic lock + version to 2 (POST Request of a Form) +- Alice updates the headline to "Baz", ... (POST Request of a + Form) + +Now at the last stage of this scenario the blog post has to be read +again from the database before Alice's headline can be applied. At +this point you will want to check if the blog post is still at +version 1 (which it is not in this scenario). + +Using optimistic locking correctly, you *have* to add the version +as an additional hidden field (or into the SESSION for more +safety). Otherwise you cannot verify the version is still the one +being originally read from the database when Alice performed her +GET request for the blog post. If this happens you might see lost +updates you wanted to prevent with Optimistic Locking. + +See the example code, The form (GET Request): + +.. code-block:: php + + find('BlogPost', 123456); + + echo ''; + echo ''; + +And the change headline action (POST Request): + +.. code-block:: php + + find('BlogPost', $postId, \Doctrine\DBAL\LockMode::OPTIMISTIC, $postVersion); + +.. _transactions-and-concurrency_pessimistic-locking: + +Pessimistic Locking +~~~~~~~~~~~~~~~~~~~ + +Doctrine 2 supports Pessimistic Locking at the database level. No +attempt is being made to implement pessimistic locking inside +Doctrine, rather vendor-specific and ANSI-SQL commands are used to +acquire row-level locks. Every Entity can be part of a pessimistic +lock, there is no special metadata required to use this feature. + +However for Pessimistic Locking to work you have to disable the +Auto-Commit Mode of your Database and start a transaction around +your pessimistic lock use-case using the "Approach 2: Explicit +Transaction Demarcation" described above. Doctrine 2 will throw an +Exception if you attempt to acquire an pessimistic lock and no +transaction is running. + +Doctrine 2 currently supports two pessimistic lock modes: + + +- Pessimistic Write + (``Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE``), locks the + underlying database rows for concurrent Read and Write Operations. +- Pessimistic Read (``Doctrine\DBAL\LockMode::PESSIMISTIC_READ``), + locks other concurrent requests that attempt to update or lock rows + in write mode. + +You can use pessimistic locks in three different scenarios: + + +1. Using + ``EntityManager#find($className, $id, \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE)`` + or + ``EntityManager#find($className, $id, \Doctrine\DBAL\LockMode::PESSIMISTIC_READ)`` +2. Using + ``EntityManager#lock($entity, \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE)`` + or + ``EntityManager#lock($entity, \Doctrine\DBAL\LockMode::PESSIMISTIC_READ)`` +3. Using + ``Query#setLockMode(\Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE)`` + or + ``Query#setLockMode(\Doctrine\DBAL\LockMode::PESSIMISTIC_READ)`` + + diff --git a/vendor/doctrine/orm/docs/en/reference/unitofwork-associations.rst b/vendor/doctrine/orm/docs/en/reference/unitofwork-associations.rst new file mode 100644 index 0000000..c9ccf73 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/unitofwork-associations.rst @@ -0,0 +1,60 @@ +Association Updates: Owning Side and Inverse Side +================================================= + +When mapping bidirectional associations it is important to +understand the concept of the owning and inverse sides. The +following general rules apply: + +- Relationships may be bidirectional or unidirectional. +- A bidirectional relationship has both an owning side and an inverse side +- A unidirectional relationship only has an owning side. +- Doctrine will **only** check the owning side of an association for changes. + +Bidirectional Associations +-------------------------- + +The following rules apply to **bidirectional** associations: + +- The inverse side has to have the ``mappedBy`` attribute of the OneToOne, + OneToMany, or ManyToMany mapping declaration. The mappedBy + attribute contains the name of the association-field on the owning side. +- The owning side has to have the ``inversedBy`` attribute of the + OneToOne, ManyToOne, or ManyToMany mapping declaration. + The inversedBy attribute contains the name of the association-field + on the inverse-side. +- ManyToOne is always the owning side of a bidirectional association. +- OneToMany is always the inverse side of a bidirectional association. +- The owning side of a OneToOne association is the entity with the table + containing the foreign key. +- You can pick the owning side of a many-to-many association yourself. + +Important concepts +------------------ + +**Doctrine will only check the owning side of an association for changes.** + +To fully understand this, remember how bidirectional associations +are maintained in the object world. There are 2 references on each +side of the association and these 2 references both represent the +same association but can change independently of one another. Of +course, in a correct application the semantics of the bidirectional +association are properly maintained by the application developer +(that's his responsibility). Doctrine needs to know which of these +two in-memory references is the one that should be persisted and +which not. This is what the owning/inverse concept is mainly used +for. + +**Changes made only to the inverse side of an association are ignored. Make sure to update both sides of a bidirectional association (or at least the owning side, from Doctrine's point of view)** + +The owning side of a bidirectional association is the side Doctrine +"looks at" when determining the state of the association, and +consequently whether there is anything to do to update the +association in the database. + +.. note:: + + "Owning side" and "inverse side" are technical concepts of + the ORM technology, not concepts of your domain model. What you + consider as the owning side in your domain model can be different + from what the owning side is for Doctrine. These are unrelated. + diff --git a/vendor/doctrine/orm/docs/en/reference/unitofwork.rst b/vendor/doctrine/orm/docs/en/reference/unitofwork.rst new file mode 100644 index 0000000..b060c46 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/unitofwork.rst @@ -0,0 +1,201 @@ +Doctrine Internals explained +============================ + +Object relational mapping is a complex topic and sufficiently understanding how Doctrine works internally helps you use its full power. + +How Doctrine keeps track of Objects +----------------------------------- + +Doctrine uses the Identity Map pattern to track objects. Whenever you fetch an +object from the database, Doctrine will keep a reference to this object inside +its UnitOfWork. The array holding all the entity references is two-levels deep +and has the keys "root entity name" and "id". Since Doctrine allows composite +keys the id is a sorted, serialized version of all the key columns. + +This allows Doctrine room for optimizations. If you call the EntityManager and +ask for an entity with a specific ID twice, it will return the same instance: + +.. code-block:: php + + public function testIdentityMap() + { + $objectA = $this->entityManager->find('EntityName', 1); + $objectB = $this->entityManager->find('EntityName', 1); + + $this->assertSame($objectA, $objectB) + } + +Only one SELECT query will be fired against the database here. In the second +``EntityManager#find()`` call Doctrine will check the identity map first and +doesn't need to make that database roundtrip. + +Even if you get a proxy object first then fetch the object by the same id you +will still end up with the same reference: + +.. code-block:: php + + public function testIdentityMapReference() + { + $objectA = $this->entityManager->getReference('EntityName', 1); + // check for proxyinterface + $this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $objectA); + + $objectB = $this->entityManager->find('EntityName', 1); + + $this->assertSame($objectA, $objectB) + } + +The identity map being indexed by primary keys only allows shortcuts when you +ask for objects by primary key. Assume you have the following ``persons`` +table: + +:: + + id | name + ------------- + 1 | Benjamin + 2 | Bud + +Take the following example where two +consecutive calls are made against a repository to fetch an entity by a set of +criteria: + +.. code-block:: php + + public function testIdentityMapRepositoryFindBy() + { + $repository = $this->entityManager->getRepository('Person'); + $objectA = $repository->findOneBy(array('name' => 'Benjamin')); + $objectB = $repository->findOneBy(array('name' => 'Benjamin')); + + $this->assertSame($objectA, $objectB); + } + +This query will still return the same references and `$objectA` and `$objectB` +are indeed referencing the same object. However when checking your SQL logs you +will realize that two queries have been executed against the database. Doctrine +only knows objects by id, so a query for different criteria has to go to the +database, even if it was executed just before. + +But instead of creating a second Person object Doctrine first gets the primary +key from the row and check if it already has an object inside the UnitOfWork +with that primary key. In our example it finds an object and decides to return +this instead of creating a new one. + +The identity map has a second use-case. When you call ``EntityManager#flush`` +Doctrine will ask the identity map for all objects that are currently managed. +This means you don't have to call ``EntityManager#persist`` over and over again +to pass known objects to the EntityManager. This is a NO-OP for known entities, +but leads to much code written that is confusing to other developers. + +The following code WILL update your database with the changes made to the +``Person`` object, even if you did not call ``EntityManager#persist``: + +.. code-block:: php + + find("Person", 1); + $user->setName("Guilherme"); + $entityManager->flush(); + +How Doctrine Detects Changes +---------------------------- + +Doctrine is a data-mapper that tries to achieve persistence-ignorance (PI). +This means you map php objects into a relational database that don't +necessarily know about the database at all. A natural question would now be, +"how does Doctrine even detect objects have changed?". + +For this Doctrine keeps a second map inside the UnitOfWork. Whenever you fetch +an object from the database Doctrine will keep a copy of all the properties and +associations inside the UnitOfWork. Because variables in the PHP language are +subject to "copy-on-write" the memory usage of a PHP request that only reads +objects from the database is the same as if Doctrine did not keep this variable +copy. Only if you start changing variables PHP will create new variables internally +that consume new memory. + +Now whenever you call ``EntityManager#flush`` Doctrine will iterate over the +Identity Map and for each object compares the original property and association +values with the values that are currently set on the object. If changes are +detected then the object is queued for a SQL UPDATE operation. Only the fields +that actually changed are updated. + +This process has an obvious performance impact. The larger the size of the +UnitOfWork is, the longer this computation takes. There are several ways to +optimize the performance of the Flush Operation: + +- Mark entities as read only. These entities can only be inserted or removed, + but are never updated. They are omitted in the changeset calculation. +- Temporarily mark entities as read only. If you have a very large UnitOfWork + but know that a large set of entities has not changed, just mark them as read + only with ``$entityManager->getUnitOfWork()->markReadOnly($entity)``. +- Flush only a single entity with ``$entityManager->flush($entity)``. +- Use :doc:`Change Tracking Policies ` to use more + explicit strategies of notifying the UnitOfWork what objects/properties + changed. + + +Query Internals +--------------- + +The different ORM Layers +------------------------ + +Doctrine ships with a set of layers with different responsibilities. This +section gives a short explanation of each layer. + +Hydration +~~~~~~~~~ + +Responsible for creating a final result from a raw database statement and a +result-set mapping object. The developer can choose which kind of result he +wishes to be hydrated. Default result-types include: + +- SQL to Entities +- SQL to structured Arrays +- SQL to simple scalar result arrays +- SQL to a single result variable + +Hydration to entities and arrays is one of the most complex parts of Doctrine +algorithm-wise. It can build results with for example: + +- Single table selects +- Joins with n:1 or 1:n cardinality, grouping belonging to the same parent. +- Mixed results of objects and scalar values +- Hydration of results by a given scalar value as key. + +Persisters +~~~~~~~~~~ + +tbr + +UnitOfWork +~~~~~~~~~~ + +tbr + +ResultSetMapping +~~~~~~~~~~~~~~~~ + +tbr + +DQL Parser +~~~~~~~~~~ + +tbr + +SQLWalker +~~~~~~~~~ + +tbr + +EntityManager +~~~~~~~~~~~~~ + +tbr + +ClassMetadataFactory +~~~~~~~~~~~~~~~~~~~~ + +tbr + diff --git a/vendor/doctrine/orm/docs/en/reference/working-with-associations.rst b/vendor/doctrine/orm/docs/en/reference/working-with-associations.rst new file mode 100644 index 0000000..ab588e4 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/working-with-associations.rst @@ -0,0 +1,728 @@ +Working with Associations +========================= + +Associations between entities are represented just like in regular +object-oriented PHP code using references to other objects or +collections of objects. + +Changes to associations in your code are not synchronized to the +database directly, only when calling ``EntityManager#flush()``. + +There are other concepts you should know about when working +with associations in Doctrine: + +- If an entity is removed from a collection, the association is + removed, not the entity itself. A collection of entities always + only represents the association to the containing entities, not the + entity itself. +- When a bidirectional association is updated, Doctrine only checks + on one of both sides for these changes. This is called the :doc:`owning side ` + of the association. +- A property with a reference to many entities has to be instances of the + ``Doctrine\Common\Collections\Collection`` interface. + +Association Example Entities +---------------------------- + +We will use a simple comment system with Users and Comments as +entities to show examples of association management. See the PHP +docblocks of each association in the following example for +information about its type and if it's the owning or inverse side. + +.. code-block:: php + + commentsRead; + } + + public function setFirstComment(Comment $c) { + $this->firstComment = $c; + } + } + +The interaction code would then look like in the following snippet +(``$em`` here is an instance of the EntityManager): + +.. code-block:: php + + find('User', $userId); + + // unidirectional many to many + $comment = $em->find('Comment', $readCommentId); + $user->getReadComments()->add($comment); + + $em->flush(); + + // unidirectional many to one + $myFirstComment = new Comment(); + $user->setFirstComment($myFirstComment); + + $em->persist($myFirstComment); + $em->flush(); + +In the case of bi-directional associations you have to update the +fields on both sides: + +.. code-block:: php + + commentsAuthored; + } + + public function getFavoriteComments() { + return $this->favorites; + } + } + + class Comment + { + // ... + + public function getUserFavorites() { + return $this->userFavorites; + } + + public function setAuthor(User $author = null) { + $this->author = $author; + } + } + + // Many-to-Many + $user->getFavorites()->add($favoriteComment); + $favoriteComment->getUserFavorites()->add($user); + + $em->flush(); + + // Many-To-One / One-To-Many Bidirectional + $newComment = new Comment(); + $user->getAuthoredComments()->add($newComment); + $newComment->setAuthor($user); + + $em->persist($newComment); + $em->flush(); + +Notice how always both sides of the bidirectional association are +updated. The previous unidirectional associations were simpler to +handle. + +Removing Associations +--------------------- + +Removing an association between two entities is similarly +straight-forward. There are two strategies to do so, by key and by +element. Here are some examples: + +.. code-block:: php + + getComments()->removeElement($comment); + $comment->setAuthor(null); + + $user->getFavorites()->removeElement($comment); + $comment->getUserFavorites()->removeElement($user); + + // Remove by Key + $user->getComments()->remove($ithComment); + $comment->setAuthor(null); + +You need to call ``$em->flush()`` to make persist these changes in +the database permanently. + +Notice how both sides of the bidirectional association are always +updated. Unidirectional associations are consequently simpler to +handle. + +Also note that if you use type-hinting in your methods, you will +have to specify a nullable type, i.e. ``setAddress(?Address $address)``, +otherwise ``setAddress(null)`` will fail to remove the association. +Another way to deal with this is to provide a special method, like +``removeAddress()``. This can also provide better encapsulation as +it hides the internal meaning of not having an address. + +When working with collections, keep in mind that a Collection is +essentially an ordered map (just like a PHP array). That is why the +``remove`` operation accepts an index/key. ``removeElement`` is a +separate method that has O(n) complexity using ``array_search``, +where n is the size of the map. + +.. note:: + + Since Doctrine always only looks at the owning side of a + bidirectional association for updates, it is not necessary for + write operations that an inverse collection of a bidirectional + one-to-many or many-to-many association is updated. This knowledge + can often be used to improve performance by avoiding the loading of + the inverse collection. + + +You can also clear the contents of a whole collection using the +``Collections::clear()`` method. You should be aware that using +this method can lead to a straight and optimized database delete or +update call during the flush operation that is not aware of +entities that have been re-added to the collection. + +Say you clear a collection of tags by calling +``$post->getTags()->clear();`` and then call +``$post->getTags()->add($tag)``. This will not recognize the tag having +already been added previously and will consequently issue two separate database +calls. + +Association Management Methods +------------------------------ + +It is generally a good idea to encapsulate proper association +management inside the entity classes. This makes it easier to use +the class correctly and can encapsulate details about how the +association is maintained. + +The following code shows updates to the previous User and Comment +example that encapsulate much of the association management code: + +.. code-block:: php + + commentsRead[] = $comment; + } + + public function addComment(Comment $comment) { + if (count($this->commentsAuthored) == 0) { + $this->setFirstComment($comment); + } + $this->comments[] = $comment; + $comment->setAuthor($this); + } + + private function setFirstComment(Comment $c) { + $this->firstComment = $c; + } + + public function addFavorite(Comment $comment) { + $this->favorites->add($comment); + $comment->addUserFavorite($this); + } + + public function removeFavorite(Comment $comment) { + $this->favorites->removeElement($comment); + $comment->removeUserFavorite($this); + } + } + + class Comment + { + // .. + + public function addUserFavorite(User $user) { + $this->userFavorites[] = $user; + } + + public function removeUserFavorite(User $user) { + $this->userFavorites->removeElement($user); + } + } + +You will notice that ``addUserFavorite`` and ``removeUserFavorite`` +do not call ``addFavorite`` and ``removeFavorite``, thus the +bidirectional association is strictly-speaking still incomplete. +However if you would naively add the ``addFavorite`` in +``addUserFavorite``, you end up with an infinite loop, so more work +is needed. As you can see, proper bidirectional association +management in plain OOP is a non-trivial task and encapsulating all +the details inside the classes can be challenging. + +.. note:: + + If you want to make sure that your collections are perfectly + encapsulated you should not return them from a + ``getCollectionName()`` method directly, but call + ``$collection->toArray()``. This way a client programmer for the + entity cannot circumvent the logic you implement on your entity for + association management. For example: + + +.. code-block:: php + + commentsRead->toArray(); + } + } + +This will however always initialize the collection, with all the +performance penalties given the size. In some scenarios of large +collections it might even be a good idea to completely hide the +read access behind methods on the EntityRepository. + +There is no single, best way for association management. It greatly +depends on the requirements of your concrete domain model as well +as your preferences. + +Synchronizing Bidirectional Collections +--------------------------------------- + +In the case of Many-To-Many associations you as the developer have the +responsibility of keeping the collections on the owning and inverse side +in sync when you apply changes to them. Doctrine can only +guarantee a consistent state for the hydration, not for your client +code. + +Using the User-Comment entities from above, a very simple example +can show the possible caveats you can encounter: + +.. code-block:: php + + getFavorites()->add($favoriteComment); + // not calling $favoriteComment->getUserFavorites()->add($user); + + $user->getFavorites()->contains($favoriteComment); // TRUE + $favoriteComment->getUserFavorites()->contains($user); // FALSE + +There are two approaches to handle this problem in your code: + + +1. Ignore updating the inverse side of bidirectional collections, + BUT never read from them in requests that changed their state. In + the next request Doctrine hydrates the consistent collection state + again. +2. Always keep the bidirectional collections in sync through + association management methods. Reads of the Collections directly + after changes are consistent then. + +.. _transitive-persistence: + +Transitive persistence / Cascade Operations +------------------------------------------- + +Doctrine 2 provides a mechanism for transitive persistence through cascading of certain operations. +Each association to another entity or a collection of +entities can be configured to automatically cascade the following operations to the associated entities: +``persist``, ``remove``, ``merge``, ``detach``, ``refresh`` or ``all``. + +The main use case for ``cascade: persist`` is to avoid "exposing" associated entities to your PHP application. +Continuing with the User-Comment example of this chapter, this is how the creation of a new user and a new +comment might look like in your controller (without ``cascade: persist``): + +.. code-block:: php + + addComment($myFirstComment); + + $em->persist($user); + $em->persist($myFirstComment); // required, if `cascade: persist` is not set + $em->flush(); + +Note that the Comment entity is instantiated right here in the controller. +To avoid this, ``cascade: persist`` allows you to "hide" the Comment entity from the controller, +only accessing it through the User entity: + +.. code-block:: php + + id = User::new(); + $this->comments = new ArrayCollection(); + } + + public function comment(string $text, DateTimeInterface $time) : void + { + $newComment = Comment::create($text, $time); + $newComment->setUser($this); + $this->comments->add($newComment); + } + + // ... + } + +If you then set up the cascading to the ``User#commentsAuthored`` property... + +.. code-block:: php + + comment('Lorem ipsum', new DateTime()); + + $em->persist($user); + $em->flush(); + +.. note:: + + The idea of ``cascade: persist`` is not to save you any lines of code in the controller. + If you instantiate the comment object in the controller (i.e. don't set up the user entity as shown above), + even with ``cascade: persist`` you still have to call ``$myFirstComment->setUser($user);``. + +Thanks to ``cascade: remove``, you can easily delete a user and all linked comments without having to loop through them: + +.. code-block:: php + + find('User', $deleteUserId); + + $em->remove($user); + $em->flush(); + +.. note:: + + Cascade operations are performed in memory. That means collections and related entities + are fetched into memory (even if they are marked as lazy) when + the cascade operation is about to be performed. This approach allows + entity lifecycle events to be performed for each of these operations. + + However, pulling object graphs into memory on cascade can cause considerable performance + overhead, especially when the cascaded collections are large. Make sure + to weigh the benefits and downsides of each cascade operation that you define. + + To rely on the database level cascade operations for the delete operation instead, you can + configure each join column with :doc:`the onDelete option `. + +Even though automatic cascading is convenient, it should be used +with care. Do not blindly apply ``cascade=all`` to all associations as +it will unnecessarily degrade the performance of your application. +For each cascade operation that gets activated, Doctrine also +applies that operation to the association, be it single or +collection valued. + +Persistence by Reachability: Cascade Persist +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are additional semantics that apply to the Cascade Persist +operation. During each ``flush()`` operation Doctrine detects if there +are new entities in any collection and three possible cases can +happen: + + +1. New entities in a collection marked as ``cascade: persist`` will be + directly persisted by Doctrine. +2. New entities in a collection not marked as ``cascade: persist`` will + produce an Exception and rollback the ``flush()`` operation. +3. Collections without new entities are skipped. + +This concept is called Persistence by Reachability: New entities +that are found on already managed entities are automatically +persisted as long as the association is defined as ``cascade: persist``. + +Orphan Removal +-------------- + +There is another concept of cascading that is relevant only when removing entities +from collections. If an Entity of type ``A`` contains references to privately +owned Entities ``B`` then if the reference from ``A`` to ``B`` is removed the +entity ``B`` should also be removed, because it is not used anymore. + +OrphanRemoval works with one-to-one, one-to-many and many-to-many associations. + +.. note:: + + When using the ``orphanRemoval=true`` option Doctrine makes the assumption + that the entities are privately owned and will **NOT** be reused by other entities. + If you neglect this assumption your entities will get deleted by Doctrine even if + you assigned the orphaned entity to another one. + +As a better example consider an Addressbook application where you have Contacts, Addresses +and StandingData: + +.. code-block:: php + + addresses = new ArrayCollection(); + } + + public function newStandingData(StandingData $sd) + { + $this->standingData = $sd; + } + + public function removeAddress($pos) + { + unset($this->addresses[$pos]); + } + } + +Now two examples of what happens when you remove the references: + +.. code-block:: php + + find("Addressbook\Contact", $contactId); + $contact->newStandingData(new StandingData("Firstname", "Lastname", "Street")); + $contact->removeAddress(1); + + $em->flush(); + +In this case you have not only changed the ``Contact`` entity itself but +you have also removed the references for standing data and as well as one +address reference. When flush is called not only are the references removed +but both the old standing data and the one address entity are also deleted +from the database. + +.. _filtering-collections: + +Filtering Collections +--------------------- + +Collections have a filtering API that allows to slice parts of data from +a collection. If the collection has not been loaded from the database yet, +the filtering API can work on the SQL level to make optimized access to +large collections. + +.. code-block:: php + + find('Group', $groupId); + $userCollection = $group->getUsers(); + + $criteria = Criteria::create() + ->where(Criteria::expr()->eq("birthday", "1982-02-17")) + ->orderBy(array("username" => Criteria::ASC)) + ->setFirstResult(0) + ->setMaxResults(20) + ; + + $birthdayUsers = $userCollection->matching($criteria); + +.. tip:: + + You can move the access of slices of collections into dedicated methods of + an entity. For example ``Group#getTodaysBirthdayUsers()``. + +The Criteria has a limited matching language that works both on the +SQL and on the PHP collection level. This means you can use collection matching +interchangeably, independent of in-memory or sql-backed collections. + +.. code-block:: php + + find('CMS\Article', 1234); + $article->setHeadline('Hello World dude!'); + + $article2 = $entityManager->find('CMS\Article', 1234); + echo $article2->getHeadline(); + +In this case the Article is accessed from the entity manager twice, +but modified in between. Doctrine 2 realizes this and will only +ever give you access to one instance of the Article with ID 1234, +no matter how often do you retrieve it from the EntityManager and +even no matter what kind of Query method you are using (find, +Repository Finder or DQL). This is called "Identity Map" pattern, +which means Doctrine keeps a map of each entity and ids that have +been retrieved per PHP request and keeps returning you the same +instances. + +In the previous example the echo prints "Hello World dude!" to the +screen. You can even verify that ``$article`` and ``$article2`` are +indeed pointing to the same instance by running the following +code: + +.. code-block:: php + + comments = new ArrayCollection(); + } + + public function getAuthor() { return $this->author; } + public function getComments() { return $this->comments; } + } + + $article = $em->find('Article', 1); + +This code only retrieves the ``Article`` instance with id 1 executing +a single SELECT statement against the articles table in the database. +You can still access the associated properties author and comments +and the associated objects they contain. + +This works by utilizing the lazy loading pattern. Instead of +passing you back a real Author instance and a collection of +comments Doctrine will create proxy instances for you. Only if you +access these proxies for the first time they will go through the +EntityManager and load their state from the database. + +This lazy-loading process happens behind the scenes, hidden from +your code. See the following code: + +.. code-block:: php + + find('Article', 1); + + // accessing a method of the user instance triggers the lazy-load + echo "Author: " . $article->getAuthor()->getName() . "\n"; + + // Lazy Loading Proxies pass instanceof tests: + if ($article->getAuthor() instanceof User) { + // a User Proxy is a generated "UserProxy" class + } + + // accessing the comments as an iterator triggers the lazy-load + // retrieving ALL the comments of this article from the database + // using a single SELECT statement + foreach ($article->getComments() as $comment) { + echo $comment->getText() . "\n\n"; + } + + // Article::$comments passes instanceof tests for the Collection interface + // But it will NOT pass for the ArrayCollection interface + if ($article->getComments() instanceof \Doctrine\Common\Collections\Collection) { + echo "This will always be true!"; + } + +A slice of the generated proxy classes code looks like the +following piece of code. A real proxy class override ALL public +methods along the lines of the ``getName()`` method shown below: + +.. code-block:: php + + _load(); + return parent::getName(); + } + // .. other public methods of User + } + +.. warning:: + + Traversing the object graph for parts that are lazy-loaded will + easily trigger lots of SQL queries and will perform badly if used + to heavily. Make sure to use DQL to fetch-join all the parts of the + object-graph that you need as efficiently as possible. + + +Persisting entities +------------------- + +An entity can be made persistent by passing it to the +``EntityManager#persist($entity)`` method. By applying the persist +operation on some entity, that entity becomes MANAGED, which means +that its persistence is from now on managed by an EntityManager. As +a result the persistent state of such an entity will subsequently +be properly synchronized with the database when +``EntityManager#flush()`` is invoked. + +.. note:: + + Invoking the ``persist`` method on an entity does NOT + cause an immediate SQL INSERT to be issued on the database. + Doctrine applies a strategy called "transactional write-behind", + which means that it will delay most SQL commands until + ``EntityManager#flush()`` is invoked which will then issue all + necessary SQL statements to synchronize your objects with the + database in the most efficient way and a single, short transaction, + taking care of maintaining referential integrity. + + +Example: + +.. code-block:: php + + setName('Mr.Right'); + $em->persist($user); + $em->flush(); + +.. note:: + + Generated entity identifiers / primary keys are + guaranteed to be available after the next successful flush + operation that involves the entity in question. You can not rely on + a generated identifier to be available directly after invoking + ``persist``. The inverse is also true. You can not rely on a + generated identifier being not available after a failed flush + operation. + + +The semantics of the persist operation, applied on an entity X, are +as follows: + + +- If X is a new entity, it becomes managed. The entity X will be + entered into the database as a result of the flush operation. +- If X is a preexisting managed entity, it is ignored by the + persist operation. However, the persist operation is cascaded to + entities referenced by X, if the relationships from X to these + other entities are mapped with cascade=PERSIST or cascade=ALL (see + ":ref:`transitive-persistence`"). +- If X is a removed entity, it becomes managed. +- If X is a detached entity, an exception will be thrown on + flush. + +Removing entities +----------------- + +An entity can be removed from persistent storage by passing it to +the ``EntityManager#remove($entity)`` method. By applying the +``remove`` operation on some entity, that entity becomes REMOVED, +which means that its persistent state will be deleted once +``EntityManager#flush()`` is invoked. + +.. note:: + + Just like ``persist``, invoking ``remove`` on an entity + does NOT cause an immediate SQL DELETE to be issued on the + database. The entity will be deleted on the next invocation of + ``EntityManager#flush()`` that involves that entity. This + means that entities scheduled for removal can still be queried + for and appear in query and collection results. See + the section on :ref:`Database and UnitOfWork Out-Of-Sync ` + for more information. + + +Example: + +.. code-block:: php + + remove($user); + $em->flush(); + +The semantics of the remove operation, applied to an entity X are +as follows: + + +- If X is a new entity, it is ignored by the remove operation. + However, the remove operation is cascaded to entities referenced by + X, if the relationship from X to these other entities is mapped + with cascade=REMOVE or cascade=ALL (see ":ref:`transitive-persistence`"). +- If X is a managed entity, the remove operation causes it to + become removed. The remove operation is cascaded to entities + referenced by X, if the relationships from X to these other + entities is mapped with cascade=REMOVE or cascade=ALL (see + ":ref:`transitive-persistence`"). +- If X is a detached entity, an InvalidArgumentException will be + thrown. +- If X is a removed entity, it is ignored by the remove operation. +- A removed entity X will be removed from the database as a result + of the flush operation. + +After an entity has been removed its in-memory state is the same as +before the removal, except for generated identifiers. + +Removing an entity will also automatically delete any existing +records in many-to-many join tables that link this entity. The +action taken depends on the value of the ``@joinColumn`` mapping +attribute "onDelete". Either Doctrine issues a dedicated ``DELETE`` +statement for records of each join table or it depends on the +foreign key semantics of onDelete="CASCADE". + +Deleting an object with all its associated objects can be achieved +in multiple ways with very different performance impacts. + + +1. If an association is marked as ``CASCADE=REMOVE`` Doctrine 2 + will fetch this association. If its a Single association it will + pass this entity to + ´EntityManager#remove()``. If the association is a collection, Doctrine will loop over all its elements and pass them to``EntityManager#remove()\`. + In both cases the cascade remove semantics are applied recursively. + For large object graphs this removal strategy can be very costly. +2. Using a DQL ``DELETE`` statement allows you to delete multiple + entities of a type with a single command and without hydrating + these entities. This can be very efficient to delete large object + graphs from the database. +3. Using foreign key semantics ``onDelete="CASCADE"`` can force the + database to remove all associated objects internally. This strategy + is a bit tricky to get right but can be very powerful and fast. You + should be aware however that using strategy 1 (``CASCADE=REMOVE``) + completely by-passes any foreign key ``onDelete=CASCADE`` option, + because Doctrine will fetch and remove all associated entities + explicitly nevertheless. + +Detaching entities +------------------ + +An entity is detached from an EntityManager and thus no longer +managed by invoking the ``EntityManager#detach($entity)`` method on +it or by cascading the detach operation to it. Changes made to the +detached entity, if any (including removal of the entity), will not +be synchronized to the database after the entity has been +detached. + +Doctrine will not hold on to any references to a detached entity. + +Example: + +.. code-block:: php + + detach($entity); + +The semantics of the detach operation, applied to an entity X are +as follows: + + +- If X is a managed entity, the detach operation causes it to + become detached. The detach operation is cascaded to entities + referenced by X, if the relationships from X to these other + entities is mapped with cascade=DETACH or cascade=ALL (see + ":ref:`transitive-persistence`"). Entities which previously referenced X + will continue to reference X. +- If X is a new or detached entity, it is ignored by the detach + operation. +- If X is a removed entity, the detach operation is cascaded to + entities referenced by X, if the relationships from X to these + other entities is mapped with cascade=DETACH or cascade=ALL (see + ":ref:`transitive-persistence`"). Entities which previously referenced X + will continue to reference X. + +There are several situations in which an entity is detached +automatically without invoking the ``detach`` method: + + +- When ``EntityManager#clear()`` is invoked, all entities that are + currently managed by the EntityManager instance become detached. +- When serializing an entity. The entity retrieved upon subsequent + unserialization will be detached (This is the case for all entities + that are serialized and stored in some cache, i.e. when using the + Query Result Cache). + +The ``detach`` operation is usually not as frequently needed and +used as ``persist`` and ``remove``. + +Merging entities +---------------- + +Merging entities refers to the merging of (usually detached) +entities into the context of an EntityManager so that they become +managed again. To merge the state of an entity into an +EntityManager use the ``EntityManager#merge($entity)`` method. The +state of the passed entity will be merged into a managed copy of +this entity and this copy will subsequently be returned. + +Example: + +.. code-block:: php + + merge($detachedEntity); + // $entity now refers to the fully managed copy returned by the merge operation. + // The EntityManager $em now manages the persistence of $entity as usual. + +.. note:: + + When you want to serialize/unserialize entities you + have to make all entity properties protected, never private. The + reason for this is, if you serialize a class that was a proxy + instance before, the private variables won't be serialized and a + PHP Notice is thrown. + + +The semantics of the merge operation, applied to an entity X, are +as follows: + + +- If X is a detached entity, the state of X is copied onto a + pre-existing managed entity instance X' of the same identity. +- If X is a new entity instance, a new managed copy X' will be + created and the state of X is copied onto this managed instance. +- If X is a removed entity instance, an InvalidArgumentException + will be thrown. +- If X is a managed entity, it is ignored by the merge operation, + however, the merge operation is cascaded to entities referenced by + relationships from X if these relationships have been mapped with + the cascade element value MERGE or ALL (see ":ref:`transitive-persistence`"). +- For all entities Y referenced by relationships from X having the + cascade element value MERGE or ALL, Y is merged recursively as Y'. + For all such Y referenced by X, X' is set to reference Y'. (Note + that if X is managed then X is the same object as X'.) +- If X is an entity merged to X', with a reference to another + entity Y, where cascade=MERGE or cascade=ALL is not specified, then + navigation of the same association from X' yields a reference to a + managed object Y' with the same persistent identity as Y. + +The ``merge`` operation will throw an ``OptimisticLockException`` +if the entity being merged uses optimistic locking through a +version field and the versions of the entity being merged and the +managed copy don't match. This usually means that the entity has +been modified while being detached. + +The ``merge`` operation is usually not as frequently needed and +used as ``persist`` and ``remove``. The most common scenario for +the ``merge`` operation is to reattach entities to an EntityManager +that come from some cache (and are therefore detached) and you want +to modify and persist such an entity. + +.. warning:: + + If you need to perform multiple merges of entities that share certain subparts + of their object-graphs and cascade merge, then you have to call ``EntityManager#clear()`` between the + successive calls to ``EntityManager#merge()``. Otherwise you might end up with + multiple copies of the "same" object in the database, however with different ids. + +.. note:: + + If you load some detached entities from a cache and you do + not need to persist or delete them or otherwise make use of them + without the need for persistence services there is no need to use + ``merge``. I.e. you can simply pass detached objects from a cache + directly to the view. + + +Synchronization with the Database +--------------------------------- + +The state of persistent entities is synchronized with the database +on flush of an ``EntityManager`` which commits the underlying +``UnitOfWork``. The synchronization involves writing any updates to +persistent entities and their relationships to the database. +Thereby bidirectional relationships are persisted based on the +references held by the owning side of the relationship as explained +in the Association Mapping chapter. + +When ``EntityManager#flush()`` is called, Doctrine inspects all +managed, new and removed entities and will perform the following +operations. + +.. _workingobjects_database_uow_outofsync: + +Effects of Database and UnitOfWork being Out-Of-Sync +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As soon as you begin to change the state of entities, call persist or remove the +contents of the UnitOfWork and the database will drive out of sync. They can +only be synchronized by calling ``EntityManager#flush()``. This section +describes the effects of database and UnitOfWork being out of sync. + +- Entities that are scheduled for removal can still be queried from the database. + They are returned from DQL and Repository queries and are visible in collections. +- Entities that are passed to ``EntityManager#persist`` do not turn up in query + results. +- Entities that have changed will not be overwritten with the state from the database. + This is because the identity map will detect the construction of an already existing + entity and assumes its the most up to date version. + +``EntityManager#flush()`` is never called implicitly by Doctrine. You always have to trigger it manually. + +Synchronizing New and Managed Entities +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The flush operation applies to a managed entity with the following +semantics: + + +- The entity itself is synchronized to the database using a SQL + UPDATE statement, only if at least one persistent field has + changed. +- No SQL updates are executed if the entity did not change. + +The flush operation applies to a new entity with the following +semantics: + + +- The entity itself is synchronized to the database using a SQL + INSERT statement. + +For all (initialized) relationships of the new or managed entity +the following semantics apply to each associated entity X: + + +- If X is new and persist operations are configured to cascade on + the relationship, X will be persisted. +- If X is new and no persist operations are configured to cascade + on the relationship, an exception will be thrown as this indicates + a programming error. +- If X is removed and persist operations are configured to cascade + on the relationship, an exception will be thrown as this indicates + a programming error (X would be re-persisted by the cascade). +- If X is detached and persist operations are configured to + cascade on the relationship, an exception will be thrown (This is + semantically the same as passing X to persist()). + +Synchronizing Removed Entities +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The flush operation applies to a removed entity by deleting its +persistent state from the database. No cascade options are relevant +for removed entities on flush, the cascade remove option is already +executed during ``EntityManager#remove($entity)``. + +The size of a Unit of Work +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The size of a Unit of Work mainly refers to the number of managed +entities at a particular point in time. + +The cost of flushing +~~~~~~~~~~~~~~~~~~~~ + +How costly a flush operation is, mainly depends on two factors: + + +- The size of the EntityManager's current UnitOfWork. +- The configured change tracking policies + +You can get the size of a UnitOfWork as follows: + +.. code-block:: php + + getUnitOfWork()->size(); + +The size represents the number of managed entities in the Unit of +Work. This size affects the performance of flush() operations due +to change tracking (see "Change Tracking Policies") and, of course, +memory consumption, so you may want to check it from time to time +during development. + +.. note:: + + Do not invoke ``flush`` after every change to an entity + or every single invocation of persist/remove/merge/... This is an + anti-pattern and unnecessarily reduces the performance of your + application. Instead, form units of work that operate on your + objects and call ``flush`` when you are done. While serving a + single HTTP request there should be usually no need for invoking + ``flush`` more than 0-2 times. + + +Direct access to a Unit of Work +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can get direct access to the Unit of Work by calling +``EntityManager#getUnitOfWork()``. This will return the UnitOfWork +instance the EntityManager is currently using. + +.. code-block:: php + + getUnitOfWork(); + +.. note:: + + Directly manipulating a UnitOfWork is not recommended. + When working directly with the UnitOfWork API, respect methods + marked as INTERNAL by not using them and carefully read the API + documentation. + + +Entity State +~~~~~~~~~~~~ + +As outlined in the architecture overview an entity can be in one of +four possible states: NEW, MANAGED, REMOVED, DETACHED. If you +explicitly need to find out what the current state of an entity is +in the context of a certain ``EntityManager`` you can ask the +underlying ``UnitOfWork``: + +.. code-block:: php + + getUnitOfWork()->getEntityState($entity)) { + case UnitOfWork::STATE_MANAGED: + ... + case UnitOfWork::STATE_REMOVED: + ... + case UnitOfWork::STATE_DETACHED: + ... + case UnitOfWork::STATE_NEW: + ... + } + +An entity is in MANAGED state if it is associated with an +``EntityManager`` and it is not REMOVED. + +An entity is in REMOVED state after it has been passed to +``EntityManager#remove()`` until the next flush operation of the +same EntityManager. A REMOVED entity is still associated with an +``EntityManager`` until the next flush operation. + +An entity is in DETACHED state if it has persistent state and +identity but is currently not associated with an +``EntityManager``. + +An entity is in NEW state if has no persistent state and identity +and is not associated with an ``EntityManager`` (for example those +just created via the "new" operator). + +Querying +-------- + +Doctrine 2 provides the following ways, in increasing level of +power and flexibility, to query for persistent objects. You should +always start with the simplest one that suits your needs. + +By Primary Key +~~~~~~~~~~~~~~ + +The most basic way to query for a persistent object is by its +identifier / primary key using the +``EntityManager#find($entityName, $id)`` method. Here is an +example: + +.. code-block:: php + + find('MyProject\Domain\User', $id); + +The return value is either the found entity instance or null if no +instance could be found with the given identifier. + +Essentially, ``EntityManager#find()`` is just a shortcut for the +following: + +.. code-block:: php + + getRepository('MyProject\Domain\User')->find($id); + +``EntityManager#getRepository($entityName)`` returns a repository +object which provides many ways to retrieve entities of the +specified type. By default, the repository instance is of type +``Doctrine\ORM\EntityRepository``. You can also use custom +repository classes as shown later. + +By Simple Conditions +~~~~~~~~~~~~~~~~~~~~ + +To query for one or more entities based on several conditions that +form a logical conjunction, use the ``findBy`` and ``findOneBy`` +methods on a repository as follows: + +.. code-block:: php + + getRepository('MyProject\Domain\User')->findBy(array('age' => 20)); + + // All users that are 20 years old and have a surname of 'Miller' + $users = $em->getRepository('MyProject\Domain\User')->findBy(array('age' => 20, 'surname' => 'Miller')); + + // A single user by its nickname + $user = $em->getRepository('MyProject\Domain\User')->findOneBy(array('nickname' => 'romanb')); + +You can also load by owning side associations through the repository: + +.. code-block:: php + + find('MyProject\Domain\Phonenumber', 1234); + $user = $em->getRepository('MyProject\Domain\User')->findOneBy(array('phone' => $number->getId())); + +The ``EntityRepository#findBy()`` method additionally accepts orderings, limit and offset as second to fourth parameters: + +.. code-block:: php + + getRepository('MyProject\Domain\User')->findBy(array('age' => 20), array('name' => 'ASC'), 10, 0); + +If you pass an array of values Doctrine will convert the query into a WHERE field IN (..) query automatically: + +.. code-block:: php + + getRepository('MyProject\Domain\User')->findBy(array('age' => array(20, 30, 40))); + // translates roughly to: SELECT * FROM users WHERE age IN (20, 30, 40) + +An EntityRepository also provides a mechanism for more concise +calls through its use of ``__call``. Thus, the following two +examples are equivalent: + +.. code-block:: php + + getRepository('MyProject\Domain\User')->findOneBy(array('nickname' => 'romanb')); + + // A single user by its nickname (__call magic) + $user = $em->getRepository('MyProject\Domain\User')->findOneByNickname('romanb'); + +Additionally, you can just count the result of the provided conditions when you don't really need the data: + +.. code-block:: php + + getRepository('MyProject\Domain\User')->count(['nickname' => 'nonexistent']); + +By Criteria +~~~~~~~~~~~ + +.. versionadded:: 2.3 + +The Repository implement the ``Doctrine\Common\Collections\Selectable`` +interface. That means you can build ``Doctrine\Common\Collections\Criteria`` +and pass them to the ``matching($criteria)`` method. + +See section `Filtering collections` of chapter :doc:`Working with Associations ` + +By Eager Loading +~~~~~~~~~~~~~~~~ + +Whenever you query for an entity that has persistent associations +and these associations are mapped as EAGER, they will automatically +be loaded together with the entity being queried and is thus +immediately available to your application. + +By Lazy Loading +~~~~~~~~~~~~~~~ + +Whenever you have a managed entity instance at hand, you can +traverse and use any associations of that entity that are +configured LAZY as if they were in-memory already. Doctrine will +automatically load the associated objects on demand through the +concept of lazy-loading. + +By DQL +~~~~~~ + +The most powerful and flexible method to query for persistent +objects is the Doctrine Query Language, an object query language. +DQL enables you to query for persistent objects in the language of +objects. DQL understands classes, fields, inheritance and +associations. DQL is syntactically very similar to the familiar SQL +but *it is not SQL*. + +A DQL query is represented by an instance of the +``Doctrine\ORM\Query`` class. You create a query using +``EntityManager#createQuery($dql)``. Here is a simple example: + +.. code-block:: php + + createQuery("select u from MyDomain\Model\User u where u.age >= 20 and u.age <= 30"); + $users = $q->getResult(); + +Note that this query contains no knowledge about the relational +schema, only about the object model. DQL supports positional as +well as named parameters, many functions, (fetch) joins, +aggregates, subqueries and much more. Detailed information about +DQL and its syntax as well as the Doctrine class can be found in +:doc:`the dedicated chapter `. +For programmatically building up queries based on conditions that +are only known at runtime, Doctrine provides the special +``Doctrine\ORM\QueryBuilder`` class. While this a powerful tool, +it also brings more complexity to your code compared to plain DQL, +so you should only use it when you need it. More information on +constructing queries with a QueryBuilder can be found +:doc:`in Query Builder chapter `. + +By Native Queries +~~~~~~~~~~~~~~~~~ + +As an alternative to DQL or as a fallback for special SQL +statements native queries can be used. Native queries are built by +using a hand-crafted SQL query and a ResultSetMapping that +describes how the SQL result set should be transformed by Doctrine. +More information about native queries can be found in +:doc:`the dedicated chapter `. + +Custom Repositories +~~~~~~~~~~~~~~~~~~~ + +By default the EntityManager returns a default implementation of +``Doctrine\ORM\EntityRepository`` when you call +``EntityManager#getRepository($entityClass)``. You can overwrite +this behaviour by specifying the class name of your own Entity +Repository in the Annotation, XML or YAML metadata. In large +applications that require lots of specialized DQL queries using a +custom repository is one recommended way of grouping these queries +in a central location. + +.. code-block:: php + + _em->createQuery('SELECT u FROM MyDomain\Model\User u WHERE u.status = "admin"') + ->getResult(); + } + } + +You can access your repository now by calling: + +.. code-block:: php + + getRepository('MyDomain\Model\User')->getAllAdminUsers(); + + diff --git a/vendor/doctrine/orm/docs/en/reference/xml-mapping.rst b/vendor/doctrine/orm/docs/en/reference/xml-mapping.rst new file mode 100644 index 0000000..f57ee46 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/xml-mapping.rst @@ -0,0 +1,782 @@ +XML Mapping +=========== + +The XML mapping driver enables you to provide the ORM metadata in +form of XML documents. + +The XML driver is backed by an XML Schema document that describes +the structure of a mapping document. The most recent version of the +XML Schema document is available online at +`https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd `_. +In order to point to the latest version of the document of a +particular stable release branch, just append the release number, +i.e.: doctrine-mapping-2.0.xsd The most convenient way to work with +XML mapping files is to use an IDE/editor that can provide +code-completion based on such an XML Schema document. The following +is an outline of a XML mapping document with the proper xmlns/xsi +setup for the latest code in trunk. + +.. code-block:: xml + + + + ... + + + +The XML mapping document of a class is loaded on-demand the first +time it is requested and subsequently stored in the metadata cache. +In order to work, this requires certain conventions: + + +- Each entity/mapped superclass must get its own dedicated XML + mapping document. +- The name of the mapping document must consist of the fully + qualified name of the class, where namespace separators are + replaced by dots (.). For example an Entity with the fully + qualified class-name "MyProject" would require a mapping file + "MyProject.Entities.User.dcm.xml" unless the extension is changed. +- All mapping documents should get the extension ".dcm.xml" to + identify it as a Doctrine mapping file. This is more of a + convention and you are not forced to do this. You can change the + file extension easily enough. + +.. code-block:: php + + setFileExtension('.xml'); + +It is recommended to put all XML mapping documents in a single +folder but you can spread the documents over several folders if you +want to. In order to tell the XmlDriver where to look for your +mapping documents, supply an array of paths as the first argument +of the constructor, like this: + +.. code-block:: php + + setMetadataDriverImpl($driver); + +.. warning:: + + Note that Doctrine ORM does not modify any settings for ``libxml``, + therefore, external XML entities may or may not be enabled or + configured correctly. + XML mappings are not XXE/XEE attack vectors since they are not + related with user input, but it is recommended that you do not + use external XML entities in your mapping files to avoid running + into unexpected behaviour. + +Simplified XML Driver +~~~~~~~~~~~~~~~~~~~~~ + +The Symfony project sponsored a driver that simplifies usage of the XML Driver. +The changes between the original driver are: + +1. File Extension is .orm.xml +2. Filenames are shortened, "MyProject\Entities\User" will become User.orm.xml +3. You can add a global file and add multiple entities in this file. + +Configuration of this client works a little bit different: + +.. code-block:: php + + 'MyProject\Entities', + '/path/to/files2' => 'OtherProject\Entities' + ); + $driver = new \Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver($namespaces); + $driver->setGlobalBasename('global'); // global.orm.xml + +Example +------- + +As a quick start, here is a small example document that makes use +of several common elements: + +.. code-block:: xml + + // Doctrine.Tests.ORM.Mapping.User.dcm.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Be aware that class-names specified in the XML files should be +fully qualified. + +XML-Element Reference +--------------------- + +The XML-Element reference explains all the tags and attributes that +the Doctrine Mapping XSD Schema defines. You should read the +Basic-, Association- and Inheritance Mapping chapters to understand +what each of this definitions means in detail. + +Defining an Entity +~~~~~~~~~~~~~~~~~~ + +Each XML Mapping File contains the definition of one entity, +specified as the ```` element as a direct child of the +```` element: + +.. code-block:: xml + + + + + + + +Required attributes: + + +- name - The fully qualified class-name of the entity. + +Optional attributes: + + +- **table** - The Table-Name to be used for this entity. Otherwise the + Unqualified Class-Name is used by default. +- **repository-class** - The fully qualified class-name of an + alternative ``Doctrine\ORM\EntityRepository`` implementation to be + used with this entity. +- **inheritance-type** - The type of inheritance, defaults to none. A + more detailed description follows in the + *Defining Inheritance Mappings* section. +- **read-only** - (>= 2.1) Specifies that this entity is marked as read only and not + considered for change-tracking. Entities of this type can be persisted + and removed though. +- **schema** - (>= 2.5) The schema the table lies in, for platforms that support schemas + +Defining Fields +~~~~~~~~~~~~~~~ + +Each entity class can contain zero to infinite fields that are +managed by Doctrine. You can define them using the ```` +element as a children to the ```` element. The field +element is only used for primitive types that are not the ID of the +entity. For the ID mapping you have to use the ```` element. + +.. code-block:: xml + + + + + + + + + + + + + + + + +Required attributes: + + +- name - The name of the Property/Field on the given Entity PHP + class. + +Optional attributes: + + +- type - The ``Doctrine\DBAL\Types\Type`` name, defaults to + "string" +- column - Name of the column in the database, defaults to the + field name. +- length - The length of the given type, for use with strings + only. +- unique - Should this field contain a unique value across the + table? Defaults to false. +- nullable - Should this field allow NULL as a value? Defaults to + false. +- version - Should this field be used for optimistic locking? Only + works on fields with type integer or datetime. +- scale - Scale of a decimal type. +- precision - Precision of a decimal type. +- options - Array of additional options: + + - default - The default value to set for the column if no value + is supplied. + - unsigned - Boolean value to determine if the column should + be capable of representing only non-negative integers + (applies only for integer column and might not be supported by + all vendors). + - fixed - Boolean value to determine if the specified length of + a string column should be fixed or varying (applies only for + string/binary column and might not be supported by all vendors). + - comment - The comment of the column in the schema (might not + be supported by all vendors). + - customSchemaOptions - Array of additional schema options + which are mostly vendor specific. +- column-definition - Optional alternative SQL representation for + this column. This definition begin after the field-name and has to + specify the complete column definition. Using this feature will + turn this field dirty for Schema-Tool update commands at all + times. + +.. note:: + + For more detailed information on each attribute, please refer to + the DBAL ``Schema-Representation`` documentation. + +Defining Identity and Generator Strategies +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An entity has to have at least one ```` element. For +composite keys you can specify more than one id-element, however +surrogate keys are recommended for use with Doctrine 2. The Id +field allows to define properties of the identifier and allows a +subset of the ```` element attributes: + +.. code-block:: xml + + + + + +Required attributes: + + +- name - The name of the Property/Field on the given Entity PHP + class. +- type - The ``Doctrine\DBAL\Types\Type`` name, preferably + "string" or "integer". + +Optional attributes: + + +- column - Name of the column in the database, defaults to the + field name. + +Using the simplified definition above Doctrine will use no +identifier strategy for this entity. That means you have to +manually set the identifier before calling +``EntityManager#persist($entity)``. This is the so called +``NONE`` strategy. + +If you want to switch the identifier generation strategy you have +to nest a ```` element inside the id-element. This of +course only works for surrogate keys. For composite keys you always +have to use the ``NONE`` strategy. + +.. code-block:: xml + + + + + + + +The following values are allowed for the ```` strategy +attribute: + + +- AUTO - Automatic detection of the identifier strategy based on + the preferred solution of the database vendor. +- IDENTITY - Use of a IDENTIFY strategy such as Auto-Increment IDs + available to Doctrine AFTER the INSERT statement has been executed. +- SEQUENCE - Use of a database sequence to retrieve the + entity-ids. This is possible before the INSERT statement is + executed. + +If you are using the SEQUENCE strategy you can define an additional +element to describe the sequence: + +.. code-block:: xml + + + + + + + + +Required attributes for ````: + + +- sequence-name - The name of the sequence + +Optional attributes for ````: + + +- allocation-size - By how much steps should the sequence be + incremented when a value is retrieved. Defaults to 1 +- initial-value - What should the initial value of the sequence + be. + + **NOTE** + + If you want to implement a cross-vendor compatible application you + have to specify and additionally define the + element, if Doctrine chooses the sequence strategy for a + platform. + + +Defining a Mapped Superclass +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sometimes you want to define a class that multiple entities inherit +from, which itself is not an entity however. The chapter on +*Inheritance Mapping* describes a Mapped Superclass in detail. You +can define it in XML using the ```` tag. + +.. code-block:: xml + + + + + + + + +Required attributes: + + +- name - Class name of the mapped superclass. + +You can nest any number of ```` and unidirectional +```` or ```` associations inside a +mapped superclass. + +Defining Inheritance Mappings +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are currently two inheritance persistence strategies that you +can choose from when defining entities that inherit from each +other. Single Table inheritance saves the fields of the complete +inheritance hierarchy in a single table, joined table inheritance +creates a table for each entity combining the fields using join +conditions. + +You can specify the inheritance type in the ```` element +and then use the ```` and +```` attributes. + +.. code-block:: xml + + + + + + + + + + +The allowed values for inheritance-type attribute are ``JOINED`` or +``SINGLE_TABLE``. + +.. note:: + + All inheritance related definitions have to be defined on the root + entity of the hierarchy. + + +Defining Lifecycle Callbacks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can define the lifecycle callback methods on your entities +using the ```` element: + +.. code-block:: xml + + + + + + + + +Defining One-To-One Relations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can define One-To-One Relations/Associations using the +```` element. The required and optional attributes +depend on the associations being on the inverse or owning side. + +For the inverse side the mapping is as simple as: + +.. code-block:: xml + + + + + +Required attributes for inverse One-To-One: + + +- field - Name of the property/field on the entity's PHP class. +- target-entity - Name of the entity associated entity class. If + this is not qualified the namespace of the current class is + prepended. *IMPORTANT:* No leading backslash! +- mapped-by - Name of the field on the owning side (here Address + entity) that contains the owning side association. + +For the owning side this mapping would look like: + +.. code-block:: xml + + + + + +Required attributes for owning One-to-One: + + +- field - Name of the property/field on the entity's PHP class. +- target-entity - Name of the entity associated entity class. If + this is not qualified the namespace of the current class is + prepended. *IMPORTANT:* No leading backslash! + +Optional attributes for owning One-to-One: + + +- inversed-by - If the association is bidirectional the + inversed-by attribute has to be specified with the name of the + field on the inverse entity that contains the back-reference. +- orphan-removal - If true, the inverse side entity is always + deleted when the owning side entity is. Defaults to false. +- fetch - Either LAZY or EAGER, defaults to LAZY. This attribute + makes only sense on the owning side, the inverse side *ALWAYS* has + to use the ``FETCH`` strategy. + +The definition for the owning side relies on a bunch of mapping +defaults for the join column names. Without the nested +```` element Doctrine assumes to foreign key to be +called ``user_id`` on the Address Entities table. This is because +the ``MyProject\Address`` entity is the owning side of this +association, which means it contains the foreign key. + +The completed explicitly defined mapping is: + +.. code-block:: xml + + + + + + + +Defining Many-To-One Associations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The many-to-one association is *ALWAYS* the owning side of any +bidirectional association. This simplifies the mapping compared to +the one-to-one case. The minimal mapping for this association looks +like: + +.. code-block:: xml + + + + + +Required attributes: + + +- field - Name of the property/field on the entity's PHP class. +- target-entity - Name of the entity associated entity class. If + this is not qualified the namespace of the current class is + prepended. *IMPORTANT:* No leading backslash! + +Optional attributes: + + +- inversed-by - If the association is bidirectional the + inversed-by attribute has to be specified with the name of the + field on the inverse entity that contains the back-reference. +- orphan-removal - If true the entity on the inverse side is + always deleted when the owning side entity is and it is not + connected to any other owning side entity anymore. Defaults to + false. +- fetch - Either LAZY or EAGER, defaults to LAZY. + +This definition relies on a bunch of mapping defaults with regards +to the naming of the join-column/foreign key. The explicitly +defined mapping includes a ```` tag nested inside +the many-to-one association tag: + +.. code-block:: xml + + + + + + + +The join-column attribute ``name`` specifies the column name of the +foreign key and the ``referenced-column-name`` attribute specifies +the name of the primary key column on the User entity. + +Defining One-To-Many Associations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The one-to-many association is *ALWAYS* the inverse side of any +association. There exists no such thing as a uni-directional +one-to-many association, which means this association only ever +exists for bi-directional associations. + +.. code-block:: xml + + + + + +Required attributes: + + +- field - Name of the property/field on the entity's PHP class. +- target-entity - Name of the entity associated entity class. If + this is not qualified the namespace of the current class is + prepended. *IMPORTANT:* No leading backslash! +- mapped-by - Name of the field on the owning side (here + Phonenumber entity) that contains the owning side association. + +Optional attributes: + + +- fetch - Either LAZY, EXTRA_LAZY or EAGER, defaults to LAZY. +- index-by: Index the collection by a field on the target entity. + +Defining Many-To-Many Associations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +From all the associations the many-to-many has the most complex +definition. When you rely on the mapping defaults you can omit many +definitions and rely on their implicit values. + +.. code-block:: xml + + + + + +Required attributes: + + +- field - Name of the property/field on the entity's PHP class. +- target-entity - Name of the entity associated entity class. If + this is not qualified the namespace of the current class is + prepended. *IMPORTANT:* No leading backslash! + +Optional attributes: + + +- mapped-by - Name of the field on the owning side that contains + the owning side association if the defined many-to-many association + is on the inverse side. +- inversed-by - If the association is bidirectional the + inversed-by attribute has to be specified with the name of the + field on the inverse entity that contains the back-reference. +- fetch - Either LAZY, EXTRA_LAZY or EAGER, defaults to LAZY. +- index-by: Index the collection by a field on the target entity. + +The mapping defaults would lead to a join-table with the name +"User\_Group" being created that contains two columns "user\_id" +and "group\_id". The explicit definition of this mapping would be: + +.. code-block:: xml + + + + + + + + + + + + + + +Here both the ```` and ```` +tags are necessary to tell Doctrine for which side the specified +join-columns apply. These are nested inside a ```` +attribute which allows to specify the table name of the +many-to-many join-table. + +Cascade Element +~~~~~~~~~~~~~~~ + +Doctrine allows cascading of several UnitOfWork operations to +related entities. You can specify the cascade operations in the +```` element inside any of the association mapping +tags. + +.. code-block:: xml + + + + + + + + + +Besides ```` the following operations can be +specified by their respective tags: + + +- ```` +- ```` +- ```` +- ```` + +Join Column Element +~~~~~~~~~~~~~~~~~~~ + +In any explicitly defined association mapping you will need the +```` tag. It defines how the foreign key and primary +key names are called that are used for joining two entities. + +Required attributes: + + +- name - The column name of the foreign key. +- referenced-column-name - The column name of the associated + entities primary key + +Optional attributes: + + +- unique - If the join column should contain a UNIQUE constraint. + This makes sense for Many-To-Many join-columns only to simulate a + one-to-many unidirectional using a join-table. +- nullable - should the join column be nullable, defaults to true. +- on-delete - Foreign Key Cascade action to perform when entity is + deleted, defaults to NO ACTION/RESTRICT but can be set to + "CASCADE". + +Defining Order of To-Many Associations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can require one-to-many or many-to-many associations to be +retrieved using an additional ``ORDER BY``. + +.. code-block:: xml + + + + + + + + + +Defining Indexes or Unique Constraints +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To define additional indexes or unique constraints on the entities +table you can use the ```` and +```` elements: + +.. code-block:: xml + + + + + + + + + + + + + +You have to specify the column and not the entity-class field names +in the index and unique-constraint definitions. + +Derived Entities ID syntax +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If the primary key of an entity contains a foreign key to another entity we speak of a derived +entity relationship. You can define this in XML with the "association-key" attribute in the ```` tag. + +.. code-block:: xml + + + + + + + + + + + + + diff --git a/vendor/doctrine/orm/docs/en/reference/yaml-mapping.rst b/vendor/doctrine/orm/docs/en/reference/yaml-mapping.rst new file mode 100644 index 0000000..8199406 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/reference/yaml-mapping.rst @@ -0,0 +1,158 @@ +YAML Mapping +============ + +.. note:: + The YAML driver is deprecated and will be removed in version 3.0. + It is strongly recommended to switch to one of the other mappings. + +The YAML mapping driver enables you to provide the ORM metadata in +form of YAML documents. + +The YAML mapping document of a class is loaded on-demand the first +time it is requested and subsequently stored in the metadata cache. +In order to work, this requires certain conventions: + + +- Each entity/mapped superclass must get its own dedicated YAML + mapping document. +- The name of the mapping document must consist of the fully + qualified name of the class, where namespace separators are + replaced by dots (.). +- All mapping documents should get the extension ".dcm.yml" to + identify it as a Doctrine mapping file. This is more of a + convention and you are not forced to do this. You can change the + file extension easily enough. + +.. code-block:: php + + setFileExtension('.yml'); + +It is recommended to put all YAML mapping documents in a single +folder but you can spread the documents over several folders if you +want to. In order to tell the YamlDriver where to look for your +mapping documents, supply an array of paths as the first argument +of the constructor, like this: + +.. code-block:: php + + setMetadataDriverImpl($driver); + +Simplified YAML Driver +~~~~~~~~~~~~~~~~~~~~~~ + +The Symfony project sponsored a driver that simplifies usage of the YAML Driver. +The changes between the original driver are: + +- File Extension is .orm.yml +- Filenames are shortened, "MyProject\\Entities\\User" will become User.orm.yml +- You can add a global file and add multiple entities in this file. + +Configuration of this client works a little bit different: + +.. code-block:: php + + 'MyProject\Entities', + '/path/to/files2' => 'OtherProject\Entities' + ); + $driver = new \Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver($namespaces); + $driver->setGlobalBasename('global'); // global.orm.yml + +Example +------- + +As a quick start, here is a small example document that makes use +of several common elements: + +.. code-block:: yaml + + # Doctrine.Tests.ORM.Mapping.User.dcm.yml + Doctrine\Tests\ORM\Mapping\User: + type: entity + repositoryClass: Doctrine\Tests\ORM\Mapping\UserRepository + table: cms_users + schema: schema_name # The schema the table lies in, for platforms that support schemas (Optional, >= 2.5) + readOnly: true + indexes: + name_index: + columns: [ name ] + id: + id: + type: integer + generator: + strategy: AUTO + fields: + name: + type: string + length: 50 + email: + type: string + length: 32 + column: user_email + unique: true + options: + fixed: true + comment: User's email address + loginCount: + type: integer + column: login_count + nullable: false + options: + unsigned: true + default: 0 + oneToOne: + address: + targetEntity: Address + joinColumn: + name: address_id + referencedColumnName: id + onDelete: CASCADE + oneToMany: + phonenumbers: + targetEntity: Phonenumber + mappedBy: user + cascade: ["persist", "merge"] + manyToMany: + groups: + targetEntity: Group + joinTable: + name: cms_users_groups + joinColumns: + user_id: + referencedColumnName: id + inverseJoinColumns: + group_id: + referencedColumnName: id + lifecycleCallbacks: + prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ] + postPersist: [ doStuffOnPostPersist ] + +Be aware that class-names specified in the YAML files should be +fully qualified. + +Reference +~~~~~~~~~~~~~~~~~~~~~~ + +Unique Constraints +------------------ + +It is possible to define unique constraints by the following declaration: + +.. code-block:: yaml + + # ECommerceProduct.orm.yml + ECommerceProduct: + type: entity + fields: + # definition of some fields + uniqueConstraints: + search_idx: + columns: [ name, email ] + diff --git a/vendor/doctrine/orm/docs/en/sidebar.rst b/vendor/doctrine/orm/docs/en/sidebar.rst new file mode 100644 index 0000000..03d130c --- /dev/null +++ b/vendor/doctrine/orm/docs/en/sidebar.rst @@ -0,0 +1,83 @@ +.. toc:: + + .. tocheader:: Tutorials + + .. toctree:: + :depth: 3 + + tutorials/getting-started + tutorials/getting-started-database + tutorials/getting-started-models + tutorials/working-with-indexed-associations + tutorials/extra-lazy-associations + tutorials/composite-primary-keys + tutorials/ordered-associations + tutorials/override-field-association-mappings-in-subclasses + tutorials/pagination + tutorials/embeddables + +.. toc:: + + .. tocheader:: Reference + + .. toctree:: + :depth: 3 + + reference/architecture + reference/configuration + reference/faq + reference/basic-mapping + reference/association-mapping + reference/inheritance-mapping + reference/working-with-objects + reference/working-with-associations + reference/events + reference/unitofwork + reference/unitofwork-associations + reference/transactions-and-concurrency + reference/batch-processing + reference/dql-doctrine-query-language + reference/query-builder + reference/native-sql + reference/change-tracking-policies + reference/partial-objects + reference/xml-mapping + reference/yaml-mapping + reference/annotations-reference + reference/php-mapping + reference/caching + reference/improving-performance + reference/tools + reference/metadata-drivers + reference/best-practices + reference/limitations-and-known-issues + tutorials/pagination + reference/filters + reference/namingstrategy + reference/advanced-configuration + reference/second-level-cache + reference/security + +.. toc:: + + .. tocheader:: Cookbook + + .. toctree:: + :depth: 3 + + cookbook/aggregate-fields + cookbook/custom-mapping-types + cookbook/decorator-pattern + cookbook/dql-custom-walkers + cookbook/dql-user-defined-functions + cookbook/implementing-arrayaccess-for-domain-objects + cookbook/implementing-the-notify-changetracking-policy + cookbook/implementing-wakeup-or-clone + cookbook/resolve-target-entity-listener + cookbook/sql-table-prefixes + cookbook/strategy-cookbook-introduction + cookbook/validation-of-entities + cookbook/working-with-datetime + cookbook/mysql-enums + cookbook/advanced-field-value-conversion-using-custom-mapping-types + cookbook/entities-in-session diff --git a/vendor/doctrine/orm/docs/en/toc.rst b/vendor/doctrine/orm/docs/en/toc.rst new file mode 100644 index 0000000..2309d56 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/toc.rst @@ -0,0 +1,86 @@ +Welcome to Doctrine 2 ORM's documentation! +========================================== + +Tutorials +--------- + +.. toctree:: + :maxdepth: 1 + + tutorials/getting-started + tutorials/getting-started-database + tutorials/getting-started-models + tutorials/working-with-indexed-associations + tutorials/extra-lazy-associations + tutorials/composite-primary-keys + tutorials/ordered-associations + tutorials/override-field-association-mappings-in-subclasses + tutorials/pagination.rst + tutorials/embeddables.rst + +Reference Guide +--------------- + +.. toctree:: + :maxdepth: 1 + :numbered: + + reference/architecture + reference/configuration.rst + reference/faq + reference/basic-mapping + reference/association-mapping + reference/inheritance-mapping + reference/working-with-objects + reference/working-with-associations + reference/events + reference/unitofwork + reference/unitofwork-associations + reference/transactions-and-concurrency + reference/batch-processing + reference/dql-doctrine-query-language + reference/query-builder + reference/native-sql + reference/change-tracking-policies + reference/partial-objects + reference/xml-mapping + reference/yaml-mapping + reference/annotations-reference + reference/php-mapping + reference/caching + reference/improving-performance + reference/tools + reference/metadata-drivers + reference/best-practices + reference/limitations-and-known-issues + tutorials/pagination + reference/filters + reference/namingstrategy + reference/advanced-configuration + reference/second-level-cache + reference/security + + +Cookbook +-------- + +.. toctree:: + :maxdepth: 1 + + cookbook/aggregate-fields + cookbook/custom-mapping-types + cookbook/decorator-pattern + cookbook/dql-custom-walkers + cookbook/dql-user-defined-functions + cookbook/implementing-arrayaccess-for-domain-objects + cookbook/implementing-the-notify-changetracking-policy + cookbook/implementing-wakeup-or-clone + cookbook/resolve-target-entity-listener + cookbook/sql-table-prefixes + cookbook/strategy-cookbook-introduction + cookbook/validation-of-entities + cookbook/working-with-datetime + cookbook/mysql-enums + cookbook/advanced-field-value-conversion-using-custom-mapping-types + cookbook/entities-in-session + diff --git a/vendor/doctrine/orm/docs/en/tutorials/composite-primary-keys.rst b/vendor/doctrine/orm/docs/en/tutorials/composite-primary-keys.rst new file mode 100644 index 0000000..ef164c9 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/tutorials/composite-primary-keys.rst @@ -0,0 +1,375 @@ +Composite and Foreign Keys as Primary Key +========================================= + +.. versionadded:: 2.1 + +Doctrine 2 supports composite primary keys natively. Composite keys are a very powerful relational database concept +and we took good care to make sure Doctrine 2 supports as many of the composite primary key use-cases. +For Doctrine 2.0 composite keys of primitive data-types are supported, for Doctrine 2.1 even foreign keys as +primary keys are supported. + +This tutorial shows how the semantics of composite primary keys work and how they map to the database. + +General Considerations +~~~~~~~~~~~~~~~~~~~~~~ + +Every entity with a composite key cannot use an id generator other than "NONE". That means +the ID fields have to have their values set before you call ``EntityManager#persist($entity)``. + +Primitive Types only +~~~~~~~~~~~~~~~~~~~~ + +Even in version 2.0 you can have composite keys as long as they only consist of the primitive types +``integer`` and ``string``. Suppose you want to create a database of cars and use the model-name +and year of production as primary keys: + +.. configuration-block:: + + .. code-block:: php + + name = $name; + $this->year = $year; + } + + public function getModelName() + { + return $this->name; + } + + public function getYearOfProduction() + { + return $this->year; + } + } + + .. code-block:: xml + + + + + + + + + + + .. code-block:: yaml + + VehicleCatalogue\Model\Car: + type: entity + id: + name: + type: string + year: + type: integer + +Now you can use this entity: + +.. code-block:: php + + persist($car); + $em->flush(); + +And for querying you can use arrays to both DQL and EntityRepositories: + +.. code-block:: php + + find("VehicleCatalogue\Model\Car", array("name" => "Audi A8", "year" => 2010)); + + $dql = "SELECT c FROM VehicleCatalogue\Model\Car c WHERE c.id = ?1"; + $audi = $em->createQuery($dql) + ->setParameter(1, array("name" => "Audi A8", "year" => 2010)) + ->getSingleResult(); + +You can also use this entity in associations. Doctrine will then generate two foreign keys one for ``name`` +and to ``year`` to the related entities. + +.. note:: + + This example shows how you can nicely solve the requirement for existing + values before ``EntityManager#persist()``: By adding them as mandatory values for the constructor. + +Identity through foreign Entities +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. note:: + + Identity through foreign entities is only supported with Doctrine 2.1 + +There are tons of use-cases where the identity of an Entity should be determined by the entity +of one or many parent entities. + +- Dynamic Attributes of an Entity (for example Article). Each Article has many + attributes with primary key "article_id" and "attribute_name". +- Address object of a Person, the primary key of the address is "user_id". This is not a case of a composite primary + key, but the identity is derived through a foreign entity and a foreign key. +- Join Tables with metadata can be modelled as Entity, for example connections between two articles + with a little description and a score. + +The semantics of mapping identity through foreign entities are easy: + +- Only allowed on Many-To-One or One-To-One associations. +- Plug an ``@Id`` annotation onto every association. +- Set an attribute ``association-key`` with the field name of the association in XML. +- Set a key ``associationKey:`` with the field name of the association in YAML. + +Use-Case 1: Dynamic Attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We keep up the example of an Article with arbitrary attributes, the mapping looks like this: + +.. configuration-block:: + + .. code-block:: php + + attributes[$name] = new ArticleAttribute($name, $value, $this); + } + } + + /** + * @Entity + */ + class ArticleAttribute + { + /** @Id @ManyToOne(targetEntity="Article", inversedBy="attributes") */ + private $article; + + /** @Id @Column(type="string") */ + private $attribute; + + /** @Column(type="string") */ + private $value; + + public function __construct($name, $value, $article) + { + $this->attribute = $name; + $this->value = $value; + $this->article = $article; + } + } + + .. code-block:: xml + + + + + + + + + + + + + + + .. code-block:: yaml + + Application\Model\ArticleAttribute: + type: entity + id: + article: + associationKey: true + attribute: + type: string + fields: + value: + type: string + manyToOne: + article: + targetEntity: Article + inversedBy: attributes + + +Use-Case 2: Simple Derived Identity +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sometimes you have the requirement that two objects are related by a One-To-One association +and that the dependent class should re-use the primary key of the class it depends on. +One good example for this is a user-address relationship: + +.. configuration-block:: + + .. code-block:: php + + customer = $customer; + $this->items = new ArrayCollection(); + $this->created = new \DateTime("now"); + } + } + + /** @Entity */ + class Product + { + /** @Id @Column(type="integer") @GeneratedValue */ + private $id; + + /** @Column(type="string") */ + private $name; + + /** @Column(type="decimal") */ + private $currentPrice; + + public function getCurrentPrice() + { + return $this->currentPrice; + } + } + + /** @Entity */ + class OrderItem + { + /** @Id @ManyToOne(targetEntity="Order") */ + private $order; + + /** @Id @ManyToOne(targetEntity="Product") */ + private $product; + + /** @Column(type="integer") */ + private $amount = 1; + + /** @Column(type="decimal") */ + private $offeredPrice; + + public function __construct(Order $order, Product $product, $amount = 1) + { + $this->order = $order; + $this->product = $product; + $this->offeredPrice = $product->getCurrentPrice(); + } + } + + +Performance Considerations +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Using composite keys always comes with a performance hit compared to using entities with +a simple surrogate key. This performance impact is mostly due to additional PHP code that is +necessary to handle this kind of keys, most notably when using derived identifiers. + +On the SQL side there is not much overhead as no additional or unexpected queries have to be +executed to manage entities with derived foreign keys. diff --git a/vendor/doctrine/orm/docs/en/tutorials/embeddables.rst b/vendor/doctrine/orm/docs/en/tutorials/embeddables.rst new file mode 100644 index 0000000..483e58d --- /dev/null +++ b/vendor/doctrine/orm/docs/en/tutorials/embeddables.rst @@ -0,0 +1,179 @@ +Separating Concerns using Embeddables +------------------------------------- + +Embeddables are classes which are not entities themselves, but are embedded +in entities and can also be queried in DQL. You'll mostly want to use them +to reduce duplication or separating concerns. Value objects such as date range +or address are the primary use case for this feature. + +.. note:: + + Embeddables can only contain properties with basic ``@Column`` mapping. + +For the purposes of this tutorial, we will assume that you have a ``User`` +class in your application and you would like to store an address in +the ``User`` class. We will model the ``Address`` class as an embeddable +instead of simply adding the respective columns to the ``User`` class. + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + + + + + + .. code-block:: yaml + + User: + type: entity + embedded: + address: + class: Address + + Address: + type: embeddable + fields: + street: { type: string } + postalCode: { type: string } + city: { type: string } + country: { type: string } + +In terms of your database schema, Doctrine will automatically inline all +columns from the ``Address`` class into the table of the ``User`` class, +just as if you had declared them directly there. + +Initializing embeddables +------------------------ + +In case all fields in the embeddable are ``nullable``, you might want +to initialize the embeddable, to avoid getting a null value instead of +the embedded object. + +.. code-block:: php + + public function __construct() + { + $this->address = new Address(); + } + +Column Prefixing +---------------- + +By default, Doctrine names your columns by prefixing them, using the value +object name. + +Following the example above, your columns would be named as ``address_street``, +``address_postalCode``... + +You can change this behaviour to meet your needs by changing the +``columnPrefix`` attribute in the ``@Embedded`` notation. + +The following example shows you how to set your prefix to ``myPrefix_``: + +.. configuration-block:: + + .. code-block:: php + + + + + + .. code-block:: yaml + + User: + type: entity + embedded: + address: + class: Address + columnPrefix: myPrefix_ + +To have Doctrine drop the prefix and use the value object's property name +directly, set ``columnPrefix=false`` (``use-column-prefix="false"`` for XML): + +.. configuration-block:: + + .. code-block:: php + + + + + + +DQL +--- + +You can also use mapped fields of embedded classes in DQL queries, just +as if they were declared in the ``User`` class: + +.. code-block:: sql + + SELECT u FROM User u WHERE u.address.city = :myCity + diff --git a/vendor/doctrine/orm/docs/en/tutorials/extra-lazy-associations.rst b/vendor/doctrine/orm/docs/en/tutorials/extra-lazy-associations.rst new file mode 100644 index 0000000..4452d68 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/tutorials/extra-lazy-associations.rst @@ -0,0 +1,86 @@ +Extra Lazy Associations +======================= + +.. versionadded:: 2.1 + +In many cases associations between entities can get pretty large. Even in a simple scenario like a blog. +where posts can be commented, you always have to assume that a post draws hundreds of comments. +In Doctrine 2.0 if you accessed an association it would always get loaded completely into memory. This +can lead to pretty serious performance problems, if your associations contain several hundreds or thousands +of entities. + +With Doctrine 2.1 a feature called **Extra Lazy** is introduced for associations. Associations +are marked as **Lazy** by default, which means the whole collection object for an association is populated +the first time its accessed. If you mark an association as extra lazy the following methods on collections +can be called without triggering a full load of the collection: + +- ``Collection#contains($entity)`` +- ``Collection#containsKey($key)`` (available with Doctrine 2.5) +- ``Collection#count()`` +- ``Collection#get($key)`` (available with Doctrine 2.4) +- ``Collection#slice($offset, $length = null)`` + +For each of the above methods the following semantics apply: + +- For each call, if the Collection is not yet loaded, issue a straight SELECT statement against the database. +- For each call, if the collection is already loaded, fallback to the default functionality for lazy collections. No additional SELECT statements are executed. + +Additionally even with Doctrine 2.0 the following methods do not trigger the collection load: + +- ``Collection#add($entity)`` +- ``Collection#offsetSet($key, $entity)`` - ArrayAccess with no specific key ``$coll[] = $entity``, it does + not work when setting specific keys like ``$coll[0] = $entity``. + +With extra lazy collections you can now not only add entities to large collections but also paginate them +easily using a combination of ``count`` and ``slice``. + + +Enabling Extra-Lazy Associations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The mapping configuration is simple. Instead of using the default value of ``fetch="LAZY"`` you have to +switch to extra lazy as shown in these examples: + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + + .. code-block:: yaml + + Doctrine\Tests\Models\CMS\CmsGroup: + type: entity + # ... + manyToMany: + users: + targetEntity: CmsUser + mappedBy: groups + fetch: EXTRA_LAZY + diff --git a/vendor/doctrine/orm/docs/en/tutorials/getting-started-database.rst b/vendor/doctrine/orm/docs/en/tutorials/getting-started-database.rst new file mode 100644 index 0000000..5a4883f --- /dev/null +++ b/vendor/doctrine/orm/docs/en/tutorials/getting-started-database.rst @@ -0,0 +1,27 @@ +Getting Started: Database First +=============================== + +.. note:: *Development Workflows* + + When you :doc:`Code First `, you + start with developing Objects and then map them onto your database. When + you :doc:`Model First `, you are modelling your application using tools (for + example UML) and generate database schema and PHP code from this model. + When you have a Database First, you already have a database schema + and generate the corresponding PHP code from it. + +.. note:: + + This getting started guide is in development. + +Development of new applications often starts with an existing database schema. +When the database schema is the starting point for your application, then +development is said to use the *Database First* approach to Doctrine. + +In this workflow you would modify the database schema first and then +regenerate the PHP code to use with this schema. You need a flexible +code-generator for this task and up to Doctrine 2.2, the code generator hasn't +been flexible enough to achieve this. + +We spinned off a subproject, Doctrine CodeGenerator, that will fill this gap and +allow you to do *Database First* development. diff --git a/vendor/doctrine/orm/docs/en/tutorials/getting-started-models.rst b/vendor/doctrine/orm/docs/en/tutorials/getting-started-models.rst new file mode 100644 index 0000000..01b7187 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/tutorials/getting-started-models.rst @@ -0,0 +1,24 @@ +Getting Started: Model First +============================ + +.. note:: *Development Workflows* + + When you :doc:`Code First `, you + start with developing Objects and then map them onto your database. When + you Model First, you are modelling your application using tools (for + example UML) and generate database schema and PHP code from this model. + When you have a :doc:`Database First `, then you already have a database schema + and generate the corresponding PHP code from it. + +.. note:: + + This getting started guide is in development. + +There are applications when you start with a high-level description of the +model using modelling tools such as UML. Modelling tools could also be Excel, +XML or CSV files that describe the model in some structured way. If your +application is using a modelling tool, then the development workflow is said to +be a *Model First* approach to Doctrine2. + +In this workflow you always change the model description and then regenerate +both PHP code and database schema from this model. diff --git a/vendor/doctrine/orm/docs/en/tutorials/getting-started.rst b/vendor/doctrine/orm/docs/en/tutorials/getting-started.rst new file mode 100644 index 0000000..52190e5 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/tutorials/getting-started.rst @@ -0,0 +1,1618 @@ +Getting Started with Doctrine +============================= + +This guide covers getting started with the Doctrine ORM. After working +through the guide you should know: + +- How to install and configure Doctrine by connecting it to a database +- Mapping PHP objects to database tables +- Generating a database schema from PHP objects +- Using the ``EntityManager`` to insert, update, delete and find + objects in the database. + +Guide Assumptions +----------------- + +This guide is designed for beginners that haven't worked with Doctrine ORM +before. There are some prerequisites for the tutorial that have to be +installed: + +- PHP (latest stable version) +- Composer Package Manager (`Install Composer + `_) + +The code of this tutorial is `available on Github `_. + +.. note:: + + This tutorial assumes you work with **Doctrine 2.6** and above. + Some of the code will not work with lower versions. + +What is Doctrine? +----------------- + +Doctrine 2 is an `object-relational mapper (ORM) `_ +for PHP 7.1+ that provides transparent persistence for PHP objects. It uses the Data Mapper +pattern at the heart, aiming for a complete separation of your domain/business +logic from the persistence in a relational database management system. + +The benefit of Doctrine for the programmer is the ability to focus +on the object-oriented business logic and worry about persistence only +as a secondary problem. This doesn't mean persistence is downplayed by Doctrine +2, however it is our belief that there are considerable benefits for +object-oriented programming if persistence and entities are kept +separated. + +What are Entities? +~~~~~~~~~~~~~~~~~~ + +Entities are PHP Objects that can be identified over many requests +by a unique identifier or primary key. These classes don't need to extend any +abstract base class or interface. An entity class must not be final +or contain final methods. Additionally it must not implement +**clone** nor **wakeup**, unless it :doc:`does so safely <../cookbook/implementing-wakeup-or-clone>`. + +An entity contains persistable properties. A persistable property +is an instance variable of the entity that is saved into and retrieved from the database +by Doctrine's data mapping capabilities. + +An Example Model: Bug Tracker +----------------------------- + +For this Getting Started Guide for Doctrine we will implement the +Bug Tracker domain model from the +`Zend_Db_Table `_ +documentation. Reading their documentation we can extract the +requirements: + +- A Bug has a description, creation date, status, reporter and + engineer +- A Bug can occur on different Products (platforms) +- A Product has a name. +- Bug reporters and engineers are both Users of the system. +- A User can create new Bugs. +- The assigned engineer can close a Bug. +- A User can see all his reported or assigned Bugs. +- Bugs can be paginated through a list-view. + +Project Setup +------------- + +Create a new empty folder for this tutorial project, for example +``doctrine2-tutorial`` and create a new file ``composer.json`` inside +that directory with the following contents: + +:: + + { + "require": { + "doctrine/orm": "^2.6.2", + "symfony/yaml": "2.*" + }, + "autoload": { + "psr-0": {"": "src/"} + } + } + + +Install Doctrine using the Composer Dependency Management tool, by calling: + +:: + + $ composer install + +This will install the packages Doctrine Common, Doctrine DBAL, Doctrine ORM, +into the ``vendor`` directory. + +Add the following directories: +:: + + doctrine2-tutorial + |-- config + | `-- xml + | `-- yaml + `-- src + +.. note:: + The YAML driver is deprecated and will be removed in version 3.0. + It is strongly recommended to switch to one of the other mappings. + +Obtaining the EntityManager +--------------------------- + +Doctrine's public interface is through the ``EntityManager``. This class +provides access points to the complete lifecycle management for your entities, +and transforms entities from and back to persistence. You have to +configure and create it to use your entities with Doctrine 2. I +will show the configuration steps and then discuss them step by +step: + +.. code-block:: php + + 'pdo_sqlite', + 'path' => __DIR__ . '/db.sqlite', + ); + + // obtaining the entity manager + $entityManager = EntityManager::create($conn, $config); + +.. note:: + The YAML driver is deprecated and will be removed in version 3.0. + It is strongly recommended to switch to one of the other mappings. + +.. note:: + It is recommended not to use the SimpleAnnotationReader because its + usage will be removed for version 3.0. + +The ``require_once`` statement sets up the class autoloading for Doctrine and +its dependencies using Composer's autoloader. + +The second block consists of the instantiation of the ORM +``Configuration`` object using the Setup helper. It assumes a bunch +of defaults that you don't have to bother about for now. You can +read up on the configuration details in the +:doc:`reference chapter on configuration <../reference/configuration>`. + +The third block shows the configuration options required to connect to +a database. In this case, we'll use a file-based SQLite database. All the +configuration options for all the shipped drivers are given in the +`DBAL Configuration section of the manual `_. + +The last block shows how the ``EntityManager`` is obtained from a +factory method. + +Generating the Database Schema +------------------------------ + +Doctrine has a command-line interface that allows you to access the SchemaTool, +a component that can generate a relational database schema based entirely on the +defined entity classes and their metadata. For this tool to work, a +``cli-config.php`` file must exist in the project root directory: + +.. code-block:: php + + id; + } + + public function getName() + { + return $this->name; + } + + public function setName($name) + { + $this->name = $name; + } + } + +When creating entity classes, all of the fields should be ``protected`` or ``private`` +(not ``public``), with getter and setter methods for each one (except ``$id``). +The use of mutators allows Doctrine to hook into calls which +manipulate the entities in ways that it could not if you just +directly set the values with ``entity#field = foo;`` + +The id field has no setter since, generally speaking, your code +should not set this value since it represents a database id value. +(Note that Doctrine itself can still set the value using the +Reflection API instead of a defined setter function.) + +The next step for persistence with Doctrine is to describe the +structure of the ``Product`` entity to Doctrine using a metadata +language. The metadata language describes how entities, their +properties and references should be persisted and what constraints +should be applied to them. + +Metadata for an Entity can be configured using DocBlock annotations directly +in the Entity class itself, or in an external XML or YAML file. This Getting +Started guide will demonstrate metadata mappings using all three methods, +but you only need to choose one. + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + + + + +.. note:: + The YAML driver is deprecated and will be removed in version 3.0. + It is strongly recommended to switch to one of the other mappings. + + .. code-block:: yaml + + # config/yaml/Product.dcm.yml + Product: + type: entity + table: products + id: + id: + type: integer + generator: + strategy: AUTO + fields: + name: + type: string + +The top-level ``entity`` definition specifies information about +the class and table name. The primitive type ``Product#name`` is +defined as a ``field`` attribute. The ``id`` property is defined with +the ``id`` tag. It has a ``generator`` tag nested inside, which +specifies that the primary key generation mechanism should automatically +use the database platform's native id generation strategy (for +example, AUTO INCREMENT in the case of MySql, or Sequences in the +case of PostgreSql and Oracle). + +Now that we have defined our first entity and its metadata, +let's update the database schema: + +:: + + $ vendor/bin/doctrine orm:schema-tool:update --force --dump-sql + +Specifying both flags ``--force`` and ``--dump-sql`` will cause the DDL +statements to be executed and then printed to the screen. + +Now, we'll create a new script to insert products into the database: + +.. code-block:: php + + + require_once "bootstrap.php"; + + $newProductName = $argv[1]; + + $product = new Product(); + $product->setName($newProductName); + + $entityManager->persist($product); + $entityManager->flush(); + + echo "Created Product with ID " . $product->getId() . "\n"; + +Call this script from the command-line to see how new products are created: + +:: + + $ php create_product.php ORM + $ php create_product.php DBAL + +What is happening here? Using the ``Product`` class is pretty standard OOP. +The interesting bits are the use of the ``EntityManager`` service. To +notify the EntityManager that a new entity should be inserted into the database, +you have to call ``persist()``. To initiate a transaction to actually *perform* +the insertion, you have to explicitly call ``flush()`` on the ``EntityManager``. + +This distinction between persist and flush is what allows the aggregation of +all database writes (INSERT, UPDATE, DELETE) into one single transaction, which +is executed when ``flush()`` is called. Using this approach, the write-performance +is significantly better than in a scenario in which writes are performed on +each entity in isolation. + +Next, we'll fetch a list of all the Products in the database. Let's create a +new script for this: + +.. code-block:: php + + getRepository('Product'); + $products = $productRepository->findAll(); + + foreach ($products as $product) { + echo sprintf("-%s\n", $product->getName()); + } + +The ``EntityManager#getRepository()`` method can create a finder object (called +a repository) for every type of entity. It is provided by Doctrine and contains +some finder methods like ``findAll()``. + +Let's continue by creating a script to display the name of a product based on its ID: + +.. code-block:: php + + + require_once "bootstrap.php"; + + $id = $argv[1]; + $product = $entityManager->find('Product', $id); + + if ($product === null) { + echo "No product found.\n"; + exit(1); + } + + echo sprintf("-%s\n", $product->getName()); + +Next we'll update a product's name, given its id. This simple example will +help demonstrate Doctrine's implementation of the UnitOfWork pattern. Doctrine +keeps track of all the entities that were retrieved from the Entity Manager, +and can detect when any of those entities' properties have been modified. +As a result, rather than needing to call ``persist($entity)`` for each individual +entity whose properties were changed, a single call to ``flush()`` at the end of a +request is sufficient to update the database for all of the modified entities. + +.. code-block:: php + + + require_once "bootstrap.php"; + + $id = $argv[1]; + $newName = $argv[2]; + + $product = $entityManager->find('Product', $id); + + if ($product === null) { + echo "Product $id does not exist.\n"; + exit(1); + } + + $product->setName($newName); + + $entityManager->flush(); + +After calling this script on one of the existing products, you can verify the +product name changed by calling the ``show_product.php`` script. + +Adding Bug and User Entities +---------------------------- + +We continue with the bug tracker example by creating the ``Bug`` and ``User`` +classes. We'll store them in ``src/Bug.php`` and ``src/User.php``, respectively. + +.. code-block:: php + + id; + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($description) + { + $this->description = $description; + } + + public function setCreated(DateTime $created) + { + $this->created = $created; + } + + public function getCreated() + { + return $this->created; + } + + public function setStatus($status) + { + $this->status = $status; + } + + public function getStatus() + { + return $this->status; + } + } + +.. code-block:: php + + id; + } + + public function getName() + { + return $this->name; + } + + public function setName($name) + { + $this->name = $name; + } + } + +All of the properties we've seen so far are of simple types (integer, string, +and datetime). But now, we'll add properties that will store objects of +specific *entity types* in order to model the relationships between different +entities. + +At the database level, relationships between entities are represented by foreign +keys. But with Doctrine, you'll never have to (and never should) work with +the foreign keys directly. You should only work with objects that represent +foreign keys through their own identities. + +For every foreign key you either have a Doctrine ManyToOne or OneToOne +association. On the inverse sides of these foreign keys you can have +OneToMany associations. Obviously you can have ManyToMany associations +that connect two tables with each other through a join table with +two foreign keys. + +Now that you know the basics about references in Doctrine, we can extend the +domain model to match the requirements: + +.. code-block:: php + + products = new ArrayCollection(); + } + } + +.. code-block:: php + + reportedBugs = new ArrayCollection(); + $this->assignedBugs = new ArrayCollection(); + } + } + +.. note:: + + Whenever an entity is created from the database, a ``Collection`` + implementation of the type ``PersistentCollection`` will be injected into + your entity instead of an ``ArrayCollection``. This helps Doctrine ORM + understand the changes that have happened to the collection that are + noteworthy for persistence. + +.. warning:: + + Lazy load proxies always contain an instance of + Doctrine's EntityManager and all its dependencies. Therefore a + var\_dump() will possibly dump a very large recursive structure + which is impossible to render and read. You have to use + ``Doctrine\Common\Util\Debug::dump()`` to restrict the dumping to a + human readable level. Additionally you should be aware that dumping + the EntityManager to a Browser may take several minutes, and the + Debug::dump() method just ignores any occurrences of it in Proxy + instances. + +Because we only work with collections for the references we must be +careful to implement a bidirectional reference in the domain model. +The concept of owning or inverse side of a relation is central to +this notion and should always be kept in mind. The following +assumptions are made about relations and have to be followed to be +able to work with Doctrine 2. These assumptions are not unique to +Doctrine 2 but are best practices in handling database relations +and Object-Relational Mapping. + +- In a one-to-one relation, the entity holding the foreign key of + the related entity on its own database table is *always* the owning + side of the relation. +- In a many-to-one relation, the Many-side is the owning side by + default because it holds the foreign key. Accordingly, the One-side + is the inverse side by default. +- In a many-to-one relation, the One-side can only be the owning side if + the relation is implemented as a ManyToMany with a join table, and the + One-side is restricted to allow only UNIQUE values per database constraint. +- In a many-to-many relation, both sides can be the owning side of + the relation. However, in a bi-directional many-to-many relation, + only one side is allowed to be the owning side. +- Changes to Collections are saved or updated, when the entity on + the *owning* side of the collection is saved or updated. +- Saving an Entity at the inverse side of a relation never + triggers a persist operation to changes to the collection. + +.. note:: + + Consistency of bi-directional references on the inverse side of a + relation have to be managed in userland application code. Doctrine + cannot magically update your collections to be consistent. + + +In the case of Users and Bugs we have references back and forth to +the assigned and reported bugs from a user, making this relation +bi-directional. We have to change the code to ensure consistency of +the bi-directional reference: + +.. code-block:: php + + assignedToBug($this); + $this->engineer = $engineer; + } + + public function setReporter(User $reporter) + { + $reporter->addReportedBug($this); + $this->reporter = $reporter; + } + + public function getEngineer() + { + return $this->engineer; + } + + public function getReporter() + { + return $this->reporter; + } + } + +.. code-block:: php + + reportedBugs[] = $bug; + } + + public function assignedToBug(Bug $bug) + { + $this->assignedBugs[] = $bug; + } + } + +I chose to name the inverse methods in past-tense, which should +indicate that the actual assigning has already taken place and the +methods are only used for ensuring consistency of the references. +This approach is my personal preference, you can choose whatever +method to make this work. + +You can see from ``User#addReportedBug()`` and +``User#assignedToBug()`` that using this method in userland alone +would not add the Bug to the collection of the owning side in +``Bug#reporter`` or ``Bug#engineer``. Using these methods and +calling Doctrine for persistence would not update the Collections' +representation in the database. + +Only using ``Bug#setEngineer()`` or ``Bug#setReporter()`` +correctly saves the relation information. + +The ``Bug#reporter`` and ``Bug#engineer`` properties are +Many-To-One relations, which point to a User. In a normalized +relational model, the foreign key is saved on the Bug's table, hence +in our object-relation model the Bug is at the owning side of the +relation. You should always make sure that the use-cases of your +domain model should drive which side is an inverse or owning one in +your Doctrine mapping. In our example, whenever a new bug is saved +or an engineer is assigned to the bug, we don't want to update the +User to persist the reference, but the Bug. This is the case with +the Bug being at the owning side of the relation. + +Bugs reference Products by a uni-directional ManyToMany relation in +the database that points from Bugs to Products. + +.. code-block:: php + + products[] = $product; + } + + public function getProducts() + { + return $this->products; + } + } + +We are now finished with the domain model given the requirements. +Lets add metadata mappings for the ``Bug`` entity, as we did for +the ``Product`` before: + +.. configuration-block:: + .. code-block:: php + + + + + + + + + + + + + + + + + + + + +.. note:: + The YAML driver is deprecated and will be removed in version 3.0. + It is strongly recommended to switch to one of the other mappings. + + .. code-block:: yaml + + # config/yaml/Bug.dcm.yml + Bug: + type: entity + table: bugs + id: + id: + type: integer + generator: + strategy: AUTO + fields: + description: + type: text + created: + type: datetime + status: + type: string + manyToOne: + reporter: + targetEntity: User + inversedBy: reportedBugs + engineer: + targetEntity: User + inversedBy: assignedBugs + manyToMany: + products: + targetEntity: Product + + +Here we have the entity, id and primitive type definitions. +For the "created" field we have used the ``datetime`` type, +which translates the YYYY-mm-dd HH:mm:ss database format +into a PHP DateTime instance and back. + +After the field definitions, the two qualified references to the +user entity are defined. They are created by the ``many-to-one`` +tag. The class name of the related entity has to be specified with +the ``target-entity`` attribute, which is enough information for +the database mapper to access the foreign-table. Since +``reporter`` and ``engineer`` are on the owning side of a +bi-directional relation, we also have to specify the ``inversed-by`` +attribute. They have to point to the field names on the inverse +side of the relationship. We will see in the next example that the ``inversed-by`` +attribute has a counterpart ``mapped-by`` which makes that +the inverse side. + +The last definition is for the ``Bug#products`` collection. It +holds all products where the specific bug occurs. Again +you have to define the ``target-entity`` and ``field`` attributes +on the ``many-to-many`` tag. + +Finally, we'll add metadata mappings for the ``User`` entity. + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + + + + + + + +.. note:: + The YAML driver is deprecated and will be removed in version 3.0. + It is strongly recommended to switch to one of the other mappings. + + .. code-block:: yaml + + # config/yaml/User.dcm.yml + User: + type: entity + table: users + id: + id: + type: integer + generator: + strategy: AUTO + fields: + name: + type: string + oneToMany: + reportedBugs: + targetEntity: Bug + mappedBy: reporter + assignedBugs: + targetEntity: Bug + mappedBy: engineer + +Here are some new things to mention about the ``one-to-many`` tags. +Remember that we discussed about the inverse and owning side. Now +both reportedBugs and assignedBugs are inverse relations, which +means the join details have already been defined on the owning +side. Therefore we only have to specify the property on the Bug +class that holds the owning sides. + +Update your database schema by running: +:: + + $ vendor/bin/doctrine orm:schema-tool:update --force + + +Implementing more Requirements +------------------------------ + +So far, we've seen the most basic features of the metadata definition language. +To explore additional functionality, let's first create new ``User`` entities: + +.. code-block:: php + + setName($newUsername); + + $entityManager->persist($user); + $entityManager->flush(); + + echo "Created User with ID " . $user->getId() . "\n"; + +Now call: + +:: + + $ php create_user.php beberlei + +We now have the necessary data to create a new Bug entity: + +.. code-block:: php + + + require_once "bootstrap.php"; + + $reporterId = $argv[1]; + $engineerId = $argv[2]; + $productIds = explode(",", $argv[3]); + + $reporter = $entityManager->find("User", $reporterId); + $engineer = $entityManager->find("User", $engineerId); + if (!$reporter || !$engineer) { + echo "No reporter and/or engineer found for the given id(s).\n"; + exit(1); + } + + $bug = new Bug(); + $bug->setDescription("Something does not work!"); + $bug->setCreated(new DateTime("now")); + $bug->setStatus("OPEN"); + + foreach ($productIds as $productId) { + $product = $entityManager->find("Product", $productId); + $bug->assignToProduct($product); + } + + $bug->setReporter($reporter); + $bug->setEngineer($engineer); + + $entityManager->persist($bug); + $entityManager->flush(); + + echo "Your new Bug Id: ".$bug->getId()."\n"; + +Since we only have one user and product, probably with the ID of 1, we can +call this script as follows: + +:: + + php create_bug.php 1 1 1 + +See how simple it is to relate a Bug, Reporter, Engineer and Products? +Also recall that thanks to the UnitOfWork pattern, Doctrine will detect +these relations and update all of the modified entities in the database +automatically when ``flush()`` is called. + +Queries for Application Use-Cases +--------------------------------- + +List of Bugs +~~~~~~~~~~~~ + +Using the previous examples we can fill up the database quite a +bit. However, we now need to discuss how to query the underlying +mapper for the required view representations. When opening the +application, bugs can be paginated through a list-view, which is +the first read-only use-case: + +.. code-block:: php + + createQuery($dql); + $query->setMaxResults(30); + $bugs = $query->getResult(); + + foreach ($bugs as $bug) { + echo $bug->getDescription()." - ".$bug->getCreated()->format('d.m.Y')."\n"; + echo " Reported by: ".$bug->getReporter()->getName()."\n"; + echo " Assigned to: ".$bug->getEngineer()->getName()."\n"; + foreach ($bug->getProducts() as $product) { + echo " Platform: ".$product->getName()."\n"; + } + echo "\n"; + } + +The DQL Query in this example fetches the 30 most recent bugs with +their respective engineer and reporter in one single SQL statement. +The console output of this script is then: + +:: + + Something does not work! - 02.04.2010 + Reported by: beberlei + Assigned to: beberlei + Platform: My Product + +.. note:: + + **DQL is not SQL** + + You may wonder why we start writing SQL at the beginning of this + use-case. Don't we use an ORM to get rid of all the endless + hand-writing of SQL? Doctrine introduces DQL which is best + described as **object-query-language** and is a dialect of + `OQL `_ and + similar to `HQL `_ or + `JPQL `_. + It does not know the concept of columns and tables, but only those + of Entity-Class and property. Using the Metadata we defined before + it allows for very short distinctive and powerful queries. + + + An important reason why DQL is favourable to the Query API of most + ORMs is its similarity to SQL. The DQL language allows query + constructs that most ORMs don't: GROUP BY even with HAVING, + Sub-selects, Fetch-Joins of nested classes, mixed results with + entities and scalar data such as COUNT() results and much more. + Using DQL you should seldom come to the point where you want to + throw your ORM into the dumpster, because it doesn't support some + the more powerful SQL concepts. + + If you need to build your query dynamically, you can use the ``QueryBuilder`` retrieved + by calling ``$entityManager->createQueryBuilder()``. There are more + details about this in the relevant part of the documentation. + + + As a last resort you can still use Native SQL and a description of the + result set to retrieve entities from the database. DQL boils down to a + Native SQL statement and a ``ResultSetMapping`` instance itself. Using + Native SQL you could even use stored procedures for data retrieval, or + make use of advanced non-portable database queries like PostgreSql's + recursive queries. + + +Array Hydration of the Bug List +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In the previous use-case we retrieved the results as their +respective object instances. We are not limited to retrieving +objects only from Doctrine however. For a simple list view like the +previous one we only need read access to our entities and can +switch the hydration from objects to simple PHP arrays instead. + +Hydration can be an expensive process so only retrieving what you need can +yield considerable performance benefits for read-only requests. + +Implementing the same list view as before using array hydration we +can rewrite our code: + +.. code-block:: php + + createQuery($dql); + $bugs = $query->getArrayResult(); + + foreach ($bugs as $bug) { + echo $bug['description'] . " - " . $bug['created']->format('d.m.Y')."\n"; + echo " Reported by: ".$bug['reporter']['name']."\n"; + echo " Assigned to: ".$bug['engineer']['name']."\n"; + foreach ($bug['products'] as $product) { + echo " Platform: ".$product['name']."\n"; + } + echo "\n"; + } + +There is one significant difference in the DQL query however, we +have to add an additional fetch-join for the products connected to +a bug. The resulting SQL query for this single select statement is +pretty large, however still more efficient to retrieve compared to +hydrating objects. + +Find by Primary Key +~~~~~~~~~~~~~~~~~~~ + +The next Use-Case is displaying a Bug by primary key. This could be +done using DQL as in the previous example with a where clause, +however there is a convenience method on the ``EntityManager`` that +handles loading by primary key, which we have already seen in the +write scenarios: + +.. code-block:: php + + + require_once "bootstrap.php"; + + $theBugId = $argv[1]; + + $bug = $entityManager->find("Bug", (int)$theBugId); + + echo "Bug: ".$bug->getDescription()."\n"; + echo "Engineer: ".$bug->getEngineer()->getName()."\n"; + +The output of the engineer’s name is fetched from the database! What is happening? + +Since we only retrieved the bug by primary key both the engineer and reporter +are not immediately loaded from the database but are replaced by LazyLoading +proxies. These proxies will load behind the scenes, when the first method +is called on them. + +Sample code of this proxy generated code can be found in the specified Proxy +Directory, it looks like: + +.. code-block:: php + + _load(); + return parent::addReportedBug($bug); + } + + public function assignedToBug($bug) + { + $this->_load(); + return parent::assignedToBug($bug); + } + } + +See how upon each method call the proxy is lazily loaded from the +database? + +The call prints: + +:: + + $ php show_bug.php 1 + Bug: Something does not work! + Engineer: beberlei + +.. warning:: + + Lazy loading additional data can be very convenient but the additional + queries create an overhead. If you know that certain fields will always + (or usually) be required by the query then you will get better performance + by explicitly retrieving them all in the first query. + + +Dashboard of the User +--------------------- + +For the next use-case we want to retrieve the dashboard view, a +list of all open bugs the user reported or was assigned to. This +will be achieved using DQL again, this time with some WHERE clauses +and usage of bound parameters: + +.. code-block:: php + + + require_once "bootstrap.php"; + + $theUserId = $argv[1]; + + $dql = "SELECT b, e, r FROM Bug b JOIN b.engineer e JOIN b.reporter r ". + "WHERE b.status = 'OPEN' AND (e.id = ?1 OR r.id = ?1) ORDER BY b.created DESC"; + + $myBugs = $entityManager->createQuery($dql) + ->setParameter(1, $theUserId) + ->setMaxResults(15) + ->getResult(); + + echo "You have created or assigned to " . count($myBugs) . " open bugs:\n\n"; + + foreach ($myBugs as $bug) { + echo $bug->getId() . " - " . $bug->getDescription()."\n"; + } + +Number of Bugs +-------------- + +Until now we only retrieved entities or their array representation. +Doctrine also supports the retrieval of non-entities through DQL. +These values are called "scalar result values" and may even be +aggregate values using COUNT, SUM, MIN, MAX or AVG functions. + +We will need this knowledge to retrieve the number of open bugs +grouped by product: + +.. code-block:: php + + createQuery($dql)->getScalarResult(); + + foreach ($productBugs as $productBug) { + echo $productBug['name']." has " . $productBug['openBugs'] . " open bugs!\n"; + } + +Updating Entities +----------------- + +There is a single use-case missing from the requirements, Engineers +should be able to close a bug. This looks like: + +.. code-block:: php + + status = "CLOSE"; + } + } + +.. code-block:: php + + + require_once "bootstrap.php"; + + $theBugId = $argv[1]; + + $bug = $entityManager->find("Bug", (int)$theBugId); + $bug->close(); + + $entityManager->flush(); + +When retrieving the Bug from the database it is inserted into the +IdentityMap inside the UnitOfWork of Doctrine. This means your Bug +with exactly this id can only exist once during the whole request +no matter how often you call ``EntityManager#find()``. It even +detects entities that are hydrated using DQL and are already +present in the Identity Map. + +When flush is called the EntityManager loops over all the entities +in the identity map and performs a comparison between the values +originally retrieved from the database and those values the entity +currently has. If at least one of these properties is different the +entity is scheduled for an UPDATE against the database. Only the +changed columns are updated, which offers a pretty good performance +improvement compared to updating all the properties. + +Entity Repositories +------------------- + +For now we have not discussed how to separate the Doctrine query logic from your model. +In Doctrine 1 there was the concept of ``Doctrine_Table`` instances for this +separation. The similar concept in Doctrine2 is called Entity Repositories, integrating +the `repository pattern `_ at the heart of Doctrine. + +Every Entity uses a default repository by default and offers a bunch of convenience +methods that you can use to query for instances of that Entity. Take for example +our Product entity. If we wanted to Query by name, we can use: + +.. code-block:: php + + getRepository('Product') + ->findOneBy(array('name' => $productName)); + +The method ``findOneBy()`` takes an array of fields or association keys and the values to match against. + +If you want to find all entities matching a condition you can use ``findBy()``, for +example querying for all closed bugs: + +.. code-block:: php + + getRepository('Bug') + ->findBy(array('status' => 'CLOSED')); + + foreach ($bugs as $bug) { + // do stuff + } + +Compared to DQL these query methods are falling short of functionality very fast. +Doctrine offers you a convenient way to extend the functionalities of the default ``EntityRepository`` +and put all the specialized DQL query logic on it. For this you have to create a subclass +of ``Doctrine\ORM\EntityRepository``, in our case a ``BugRepository`` and group all +the previously discussed query functionality in it: + +.. code-block:: php + + getEntityManager()->createQuery($dql); + $query->setMaxResults($number); + return $query->getResult(); + } + + public function getRecentBugsArray($number = 30) + { + $dql = "SELECT b, e, r, p FROM Bug b JOIN b.engineer e ". + "JOIN b.reporter r JOIN b.products p ORDER BY b.created DESC"; + $query = $this->getEntityManager()->createQuery($dql); + $query->setMaxResults($number); + return $query->getArrayResult(); + } + + public function getUsersBugs($userId, $number = 15) + { + $dql = "SELECT b, e, r FROM Bug b JOIN b.engineer e JOIN b.reporter r ". + "WHERE b.status = 'OPEN' AND e.id = ?1 OR r.id = ?1 ORDER BY b.created DESC"; + + return $this->getEntityManager()->createQuery($dql) + ->setParameter(1, $userId) + ->setMaxResults($number) + ->getResult(); + } + + public function getOpenBugsByProduct() + { + $dql = "SELECT p.id, p.name, count(b.id) AS openBugs FROM Bug b ". + "JOIN b.products p WHERE b.status = 'OPEN' GROUP BY p.id"; + return $this->getEntityManager()->createQuery($dql)->getScalarResult(); + } + } + +To be able to use this query logic through ``$this->getEntityManager()->getRepository('Bug')`` +we have to adjust the metadata slightly. + +.. configuration-block:: + + .. code-block:: php + + + + + + + + +.. note:: + The YAML driver is deprecated and will be removed in version 3.0. + It is strongly recommended to switch to one of the other mappings. + + .. code-block:: yaml + + Bug: + type: entity + repositoryClass: BugRepository + +Now we can remove our query logic in all the places and instead use them through the EntityRepository. +As an example here is the code of the first use case "List of Bugs": + +.. code-block:: php + + getRepository('Bug')->getRecentBugs(); + + foreach ($bugs as $bug) { + echo $bug->getDescription()." - ".$bug->getCreated()->format('d.m.Y')."\n"; + echo " Reported by: ".$bug->getReporter()->getName()."\n"; + echo " Assigned to: ".$bug->getEngineer()->getName()."\n"; + foreach ($bug->getProducts() as $product) { + echo " Platform: ".$product->getName()."\n"; + } + echo "\n"; + } + +Using EntityRepositories you can avoid coupling your model with specific query logic. +You can also re-use query logic easily throughout your application. + +The method ``count()`` takes an array of fields or association keys and the values to match against. +This provides you with a convenient and lightweight way to count a resultset when you don't need to +deal with it: + +.. code-block:: php + + getRepository(Product::class) + ->count(['name' => $productName]); + +Conclusion +---------- + +This tutorial is over here, I hope you had fun. Additional content +will be added to this tutorial incrementally, topics will include: + +- More on Association Mappings +- Lifecycle Events triggered in the UnitOfWork +- Ordering of Collections + +Additional details on all the topics discussed here can be found in +the respective manual chapters. diff --git a/vendor/doctrine/orm/docs/en/tutorials/ordered-associations.rst b/vendor/doctrine/orm/docs/en/tutorials/ordered-associations.rst new file mode 100644 index 0000000..cb0e64a --- /dev/null +++ b/vendor/doctrine/orm/docs/en/tutorials/ordered-associations.rst @@ -0,0 +1,110 @@ +Ordering To-Many Associations +----------------------------- + +There are use-cases when you'll want to sort collections when they are +retrieved from the database. In userland you do this as long as you +haven't initially saved an entity with its associations into the +database. To retrieve a sorted collection from the database you can +use the ``@OrderBy`` annotation with a collection that specifies +a DQL snippet that is appended to all queries with this +collection. + +Additional to any ``@OneToMany`` or ``@ManyToMany`` annotation you +can specify the ``@OrderBy`` in the following way: + +.. configuration-block:: + + .. code-block:: php + + + + + + + + + + + + .. code-block:: yaml + + User: + type: entity + manyToMany: + groups: + orderBy: { 'name': 'ASC' } + targetEntity: Group + joinTable: + name: users_groups + joinColumns: + user_id: + referencedColumnName: id + inverseJoinColumns: + group_id: + referencedColumnName: id + +The DQL Snippet in OrderBy is only allowed to consist of +unqualified, unquoted field names and of an optional ASC/DESC +positional statement. Multiple Fields are separated by a comma (,). +The referenced field names have to exist on the ``targetEntity`` +class of the ``@ManyToMany`` or ``@OneToMany`` annotation. + +The semantics of this feature can be described as follows: + + +- ``@OrderBy`` acts as an implicit ORDER BY clause for the given + fields, that is appended to all the explicitly given ORDER BY + items. +- All collections of the ordered type are always retrieved in an + ordered fashion. +- To keep the database impact low, these implicit ORDER BY items + are only added to a DQL Query if the collection is fetch joined in + the DQL query. + +Given our previously defined example, the following would not add +ORDER BY, since g is not fetch joined: + +.. code-block:: sql + + SELECT u FROM User u JOIN u.groups g WHERE SIZE(g) > 10 + +However the following: + +.. code-block:: sql + + SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 + +...would internally be rewritten to: + +.. code-block:: sql + + SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 ORDER BY g.name ASC + +You can reverse the order with an explicit DQL ORDER BY: + +.. code-block:: sql + + SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 ORDER BY g.name DESC + +...is internally rewritten to: + +.. code-block:: sql + + SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 ORDER BY g.name DESC, g.name ASC + + diff --git a/vendor/doctrine/orm/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst b/vendor/doctrine/orm/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst new file mode 100644 index 0000000..de9f0d9 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst @@ -0,0 +1,92 @@ +Override Field Association Mappings In Subclasses +------------------------------------------------- + +Sometimes there is a need to persist entities but override all or part of the +mapping metadata. Sometimes also the mapping to override comes from entities +using traits where the traits have mapping metadata. +This tutorial explains how to override mapping metadata, +i.e. attributes and associations metadata in particular. The example here shows +the overriding of a class that uses a trait but is similar when extending a base +class as shown at the end of this tutorial. + +Suppose we have a class ExampleEntityWithOverride. This class uses trait ExampleTrait: + +.. code-block:: php + + `). diff --git a/vendor/doctrine/orm/docs/en/tutorials/pagination.rst b/vendor/doctrine/orm/docs/en/tutorials/pagination.rst new file mode 100644 index 0000000..3971383 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/tutorials/pagination.rst @@ -0,0 +1,43 @@ +Pagination +========== + +.. versionadded:: 2.2 + +Starting with version 2.2 Doctrine ships with a Paginator for DQL queries. It +has a very simple API and implements the SPL interfaces ``Countable`` and +``IteratorAggregate``. + +.. code-block:: php + + createQuery($dql) + ->setFirstResult(0) + ->setMaxResults(100); + + $paginator = new Paginator($query, $fetchJoinCollection = true); + + $c = count($paginator); + foreach ($paginator as $post) { + echo $post->getHeadline() . "\n"; + } + +Paginating Doctrine queries is not as simple as you might think in the +beginning. If you have complex fetch-join scenarios with one-to-many or +many-to-many associations using the "default" LIMIT functionality of database +vendors is not sufficient to get the correct results. + +By default the pagination extension does the following steps to compute the +correct result: + +- Perform a Count query using `DISTINCT` keyword. +- Perform a Limit Subquery with `DISTINCT` to find all ids of the entity in from on the current page. +- Perform a WHERE IN query to get all results for the current page. + +This behavior is only necessary if you actually fetch join a to-many +collection. You can disable this behavior by setting the +``$fetchJoinCollection`` flag to ``false``; in that case only 2 instead of the 3 queries +described are executed. We hope to automate the detection for this in +the future. diff --git a/vendor/doctrine/orm/docs/en/tutorials/working-with-indexed-associations.rst b/vendor/doctrine/orm/docs/en/tutorials/working-with-indexed-associations.rst new file mode 100644 index 0000000..0381764 --- /dev/null +++ b/vendor/doctrine/orm/docs/en/tutorials/working-with-indexed-associations.rst @@ -0,0 +1,296 @@ +Working with Indexed Associations +================================= + +.. note:: + + This feature is available from version 2.1 of Doctrine. + +Doctrine 2 collections are modelled after PHPs native arrays. PHP arrays are an ordered hashmap, but in +the first version of Doctrine keys retrieved from the database were always numerical unless ``INDEX BY`` +was used. Starting with Doctrine 2.1 you can index your collections by a value in the related entity. +This is a first step towards full ordered hashmap support through the Doctrine ORM. +The feature works like an implicit ``INDEX BY`` for the selected association but has several +downsides also: + +- You have to manage both the key and field if you want to change the index by field value. +- On each request the keys are regenerated from the field value, and not from the previous collection key. +- Values of the Index-By keys are never considered during persistence. They only exist for accessing purposes. +- Fields that are used for the index by feature **HAVE** to be unique in the database. The behavior for multiple entities + with the same index-by field value is undefined. + +As an example we will design a simple stock exchange list view. The domain consists of the entity ``Stock`` +and ``Market`` where each Stock has a symbol and is traded on a single market. Instead of having a numerical +list of stocks traded on a market they will be indexed by their symbol, which is unique across all markets. + +Mapping Indexed Associations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can map indexed associations by adding: + + * ``indexBy`` attribute to any ``@OneToMany`` or ``@ManyToMany`` annotation. + * ``index-by`` attribute to any ```` or ```` xml element. + * ``indexBy:`` key-value pair to any association defined in ``manyToMany:`` or ``oneToMany:`` YAML mapping files. + +The code and mappings for the Market entity looks like this: + +.. configuration-block:: + .. code-block:: php + + name = $name; + $this->stocks = new ArrayCollection(); + } + + public function getId() + { + return $this->id; + } + + public function getName() + { + return $this->name; + } + + public function addStock(Stock $stock) + { + $this->stocks[$stock->getSymbol()] = $stock; + } + + public function getStock($symbol) + { + if (!isset($this->stocks[$symbol])) { + throw new \InvalidArgumentException("Symbol is not traded on this market."); + } + + return $this->stocks[$symbol]; + } + + public function getStocks() + { + return $this->stocks->toArray(); + } + } + + .. code-block:: xml + + + + + + + + + + + + + + + + .. code-block:: yaml + + Doctrine\Tests\Models\StockExchange\Market: + type: entity + id: + id: + type: integer + generator: + strategy: AUTO + fields: + name: + type:string + oneToMany: + stocks: + targetEntity: Stock + mappedBy: market + indexBy: symbol + +Inside the ``addStock()`` method you can see how we directly set the key of the association to the symbol, +so that we can work with the indexed association directly after invoking ``addStock()``. Inside ``getStock($symbol)`` +we pick a stock traded on the particular market by symbol. If this stock doesn't exist an exception is thrown. + +The ``Stock`` entity doesn't contain any special instructions that are new, but for completeness +here are the code and mappings for it: + +.. configuration-block:: + .. code-block:: php + + symbol = $symbol; + $this->market = $market; + $market->addStock($this); + } + + public function getSymbol() + { + return $this->symbol; + } + } + + .. code-block:: xml + + + + + + + + + + + + + + + .. code-block:: yaml + + Doctrine\Tests\Models\StockExchange\Stock: + type: entity + id: + id: + type: integer + generator: + strategy: AUTO + fields: + symbol: + type: string + manyToOne: + market: + targetEntity: Market + inversedBy: stocks + +Querying indexed associations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now that we defined the stocks collection to be indexed by symbol, we can take a look at some code +that makes use of the indexing. + +First we will populate our database with two example stocks traded on a single market: + +.. code-block:: php + + persist($market); + $em->persist($stock1); + $em->persist($stock2); + $em->flush(); + +This code is not particular interesting since the indexing feature is not yet used. In a new request we could +now query for the market: + +.. code-block:: php + + find("Doctrine\Tests\Models\StockExchange\Market", $marketId); + + // Access the stocks by symbol now: + $stock = $market->getStock($symbol); + + echo $stock->getSymbol(); // will print "AAPL" + +The implementation of ``Market::addStock()``, in combination with ``indexBy``, allows us to access the collection +consistently by the Stock symbol. It does not matter if Stock is managed by Doctrine or not. + +The same applies to DQL queries: The ``indexBy`` configuration acts as implicit "INDEX BY" to a join association. + +.. code-block:: php + + createQuery($dql) + ->setParameter(1, $marketId) + ->getSingleResult(); + + // Access the stocks by symbol now: + $stock = $market->getStock($symbol); + + echo $stock->getSymbol(); // will print "AAPL" + +If you want to use ``INDEX BY`` explicitly on an indexed association you are free to do so. Additionally, +indexed associations also work with the ``Collection::slice()`` functionality, even if the association's fetch mode is +LAZY or EXTRA_LAZY. + +Outlook into the Future +~~~~~~~~~~~~~~~~~~~~~~~ + +For the inverse side of a many-to-many associations there will be a way to persist the keys and the order +as a third and fourth parameter into the join table. This feature is discussed in `DDC-213 `_ +This feature cannot be implemented for one-to-many associations, because they are never the owning side. + diff --git a/vendor/doctrine/orm/doctrine-mapping.xsd b/vendor/doctrine/orm/doctrine-mapping.xsd new file mode 100644 index 0000000..561b062 --- /dev/null +++ b/vendor/doctrine/orm/doctrine-mapping.xsd @@ -0,0 +1,622 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php b/vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php new file mode 100644 index 0000000..2240366 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php @@ -0,0 +1,1165 @@ +. + */ + +namespace Doctrine\ORM; + +use Doctrine\Common\Persistence\Mapping\MappingException; +use Doctrine\Common\Util\ClassUtils; +use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Collections\ArrayCollection; + +use Doctrine\ORM\Mapping\MappingException as ORMMappingException; +use Doctrine\ORM\Query\Parameter; +use Doctrine\ORM\Cache\QueryCacheKey; +use Doctrine\DBAL\Cache\QueryCacheProfile; + +/** + * Base contract for ORM queries. Base class for Query and NativeQuery. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Konsta Vesterinen + */ +abstract class AbstractQuery +{ + /* Hydration mode constants */ + + /** + * Hydrates an object graph. This is the default behavior. + */ + const HYDRATE_OBJECT = 1; + + /** + * Hydrates an array graph. + */ + const HYDRATE_ARRAY = 2; + + /** + * Hydrates a flat, rectangular result set with scalar values. + */ + const HYDRATE_SCALAR = 3; + + /** + * Hydrates a single scalar value. + */ + const HYDRATE_SINGLE_SCALAR = 4; + + /** + * Very simple object hydrator (optimized for performance). + */ + const HYDRATE_SIMPLEOBJECT = 5; + + /** + * The parameter map of this query. + * + * @var ArrayCollection|Parameter[] + */ + protected $parameters; + + /** + * The user-specified ResultSetMapping to use. + * + * @var \Doctrine\ORM\Query\ResultSetMapping + */ + protected $_resultSetMapping; + + /** + * The entity manager used by this query object. + * + * @var EntityManagerInterface + */ + protected $_em; + + /** + * The map of query hints. + * + * @var array + */ + protected $_hints = []; + + /** + * The hydration mode. + * + * @var string|int + */ + protected $_hydrationMode = self::HYDRATE_OBJECT; + + /** + * @var \Doctrine\DBAL\Cache\QueryCacheProfile + */ + protected $_queryCacheProfile; + + /** + * Whether or not expire the result cache. + * + * @var boolean + */ + protected $_expireResultCache = false; + + /** + * @var \Doctrine\DBAL\Cache\QueryCacheProfile + */ + protected $_hydrationCacheProfile; + + /** + * Whether to use second level cache, if available. + * + * @var boolean + */ + protected $cacheable = false; + + /** + * @var boolean + */ + protected $hasCache = false; + + /** + * Second level cache region name. + * + * @var string|null + */ + protected $cacheRegion; + + /** + * Second level query cache mode. + * + * @var integer|null + */ + protected $cacheMode; + + /** + * @var \Doctrine\ORM\Cache\Logging\CacheLogger|null + */ + protected $cacheLogger; + + /** + * @var integer + */ + protected $lifetime = 0; + + /** + * Initializes a new instance of a class derived from AbstractQuery. + * + * @param \Doctrine\ORM\EntityManagerInterface $em + */ + public function __construct(EntityManagerInterface $em) + { + $this->_em = $em; + $this->parameters = new ArrayCollection(); + $this->_hints = $em->getConfiguration()->getDefaultQueryHints(); + $this->hasCache = $this->_em->getConfiguration()->isSecondLevelCacheEnabled(); + + if ($this->hasCache) { + $this->cacheLogger = $em->getConfiguration() + ->getSecondLevelCacheConfiguration() + ->getCacheLogger(); + } + } + + /** + * Enable/disable second level query (result) caching for this query. + * + * @param boolean $cacheable + * + * @return static This query instance. + */ + public function setCacheable($cacheable) + { + $this->cacheable = (boolean) $cacheable; + + return $this; + } + + /** + * @return boolean TRUE if the query results are enable for second level cache, FALSE otherwise. + */ + public function isCacheable() + { + return $this->cacheable; + } + + /** + * @param string $cacheRegion + * + * @return static This query instance. + */ + public function setCacheRegion($cacheRegion) + { + $this->cacheRegion = (string) $cacheRegion; + + return $this; + } + + /** + * Obtain the name of the second level query cache region in which query results will be stored + * + * @return string|null The cache region name; NULL indicates the default region. + */ + public function getCacheRegion() + { + return $this->cacheRegion; + } + + /** + * @return boolean TRUE if the query cache and second level cache are enabled, FALSE otherwise. + */ + protected function isCacheEnabled() + { + return $this->cacheable && $this->hasCache; + } + + /** + * @return integer + */ + public function getLifetime() + { + return $this->lifetime; + } + + /** + * Sets the life-time for this query into second level cache. + * + * @param integer $lifetime + * + * @return \Doctrine\ORM\AbstractQuery This query instance. + */ + public function setLifetime($lifetime) + { + $this->lifetime = (integer) $lifetime; + + return $this; + } + + /** + * @return integer + */ + public function getCacheMode() + { + return $this->cacheMode; + } + + /** + * @param integer $cacheMode + * + * @return \Doctrine\ORM\AbstractQuery This query instance. + */ + public function setCacheMode($cacheMode) + { + $this->cacheMode = (integer) $cacheMode; + + return $this; + } + + /** + * Gets the SQL query that corresponds to this query object. + * The returned SQL syntax depends on the connection driver that is used + * by this query object at the time of this method call. + * + * @return string SQL query + */ + abstract public function getSQL(); + + /** + * Retrieves the associated EntityManager of this Query instance. + * + * @return \Doctrine\ORM\EntityManager + */ + public function getEntityManager() + { + return $this->_em; + } + + /** + * Frees the resources used by the query object. + * + * Resets Parameters, Parameter Types and Query Hints. + * + * @return void + */ + public function free() + { + $this->parameters = new ArrayCollection(); + + $this->_hints = $this->_em->getConfiguration()->getDefaultQueryHints(); + } + + /** + * Get all defined parameters. + * + * @return ArrayCollection The defined query parameters. + */ + public function getParameters() + { + return $this->parameters; + } + + /** + * Gets a query parameter. + * + * @param mixed $key The key (index or name) of the bound parameter. + * + * @return Query\Parameter|null The value of the bound parameter, or NULL if not available. + */ + public function getParameter($key) + { + $filteredParameters = $this->parameters->filter( + function (Query\Parameter $parameter) use ($key) : bool { + $parameterName = $parameter->getName(); + + return $key === $parameterName || (string) $key === (string) $parameterName; + } + ); + + return ! $filteredParameters->isEmpty() ? $filteredParameters->first() : null; + } + + /** + * Sets a collection of query parameters. + * + * @param ArrayCollection|mixed[] $parameters + * + * @return static This query instance. + */ + public function setParameters($parameters) + { + // BC compatibility with 2.3- + if (is_array($parameters)) { + $parameterCollection = new ArrayCollection(); + + foreach ($parameters as $key => $value) { + $parameterCollection->add(new Parameter($key, $value)); + } + + $parameters = $parameterCollection; + } + + $this->parameters = $parameters; + + return $this; + } + + /** + * Sets a query parameter. + * + * @param string|int $key The parameter position or name. + * @param mixed $value The parameter value. + * @param string|null $type The parameter type. If specified, the given value will be run through + * the type conversion of this type. This is usually not needed for + * strings and numeric types. + * + * @return static This query instance. + */ + public function setParameter($key, $value, $type = null) + { + $existingParameter = $this->getParameter($key); + + if ($existingParameter !== null) { + $existingParameter->setValue($value, $type); + + return $this; + } + + $this->parameters->add(new Parameter($key, $value, $type)); + + return $this; + } + + /** + * Processes an individual parameter value. + * + * @param mixed $value + * + * @return array|string + * + * @throws \Doctrine\ORM\ORMInvalidArgumentException + */ + public function processParameterValue($value) + { + if (is_scalar($value)) { + return $value; + } + + if ($value instanceof Collection) { + $value = $value->toArray(); + } + + if (is_array($value)) { + foreach ($value as $key => $paramValue) { + $paramValue = $this->processParameterValue($paramValue); + $value[$key] = is_array($paramValue) ? reset($paramValue) : $paramValue; + } + + return $value; + } + + if ($value instanceof Mapping\ClassMetadata) { + return $value->name; + } + + if (! is_object($value)) { + return $value; + } + + try { + $value = $this->_em->getUnitOfWork()->getSingleIdentifierValue($value); + + if ($value === null) { + throw ORMInvalidArgumentException::invalidIdentifierBindingEntity(); + } + } catch (MappingException | ORMMappingException $e) { + // Silence any mapping exceptions. These can occur if the object in + // question is not a mapped entity, in which case we just don't do + // any preparation on the value. + } + + return $value; + } + + /** + * Sets the ResultSetMapping that should be used for hydration. + * + * @param \Doctrine\ORM\Query\ResultSetMapping $rsm + * + * @return static This query instance. + */ + public function setResultSetMapping(Query\ResultSetMapping $rsm) + { + $this->translateNamespaces($rsm); + $this->_resultSetMapping = $rsm; + + return $this; + } + + /** + * Gets the ResultSetMapping used for hydration. + * + * @return \Doctrine\ORM\Query\ResultSetMapping + */ + protected function getResultSetMapping() + { + return $this->_resultSetMapping; + } + + /** + * Allows to translate entity namespaces to full qualified names. + * + * @param Query\ResultSetMapping $rsm + * + * @return void + */ + private function translateNamespaces(Query\ResultSetMapping $rsm) + { + $translate = function ($alias) { + return $this->_em->getClassMetadata($alias)->getName(); + }; + + $rsm->aliasMap = array_map($translate, $rsm->aliasMap); + $rsm->declaringClasses = array_map($translate, $rsm->declaringClasses); + } + + /** + * Set a cache profile for hydration caching. + * + * If no result cache driver is set in the QueryCacheProfile, the default + * result cache driver is used from the configuration. + * + * Important: Hydration caching does NOT register entities in the + * UnitOfWork when retrieved from the cache. Never use result cached + * entities for requests that also flush the EntityManager. If you want + * some form of caching with UnitOfWork registration you should use + * {@see AbstractQuery::setResultCacheProfile()}. + * + * @example + * $lifetime = 100; + * $resultKey = "abc"; + * $query->setHydrationCacheProfile(new QueryCacheProfile()); + * $query->setHydrationCacheProfile(new QueryCacheProfile($lifetime, $resultKey)); + * + * @param \Doctrine\DBAL\Cache\QueryCacheProfile $profile + * + * @return static This query instance. + */ + public function setHydrationCacheProfile(QueryCacheProfile $profile = null) + { + if ($profile !== null && ! $profile->getResultCacheDriver()) { + $resultCacheDriver = $this->_em->getConfiguration()->getHydrationCacheImpl(); + $profile = $profile->setResultCacheDriver($resultCacheDriver); + } + + $this->_hydrationCacheProfile = $profile; + + return $this; + } + + /** + * @return \Doctrine\DBAL\Cache\QueryCacheProfile + */ + public function getHydrationCacheProfile() + { + return $this->_hydrationCacheProfile; + } + + /** + * Set a cache profile for the result cache. + * + * If no result cache driver is set in the QueryCacheProfile, the default + * result cache driver is used from the configuration. + * + * @param \Doctrine\DBAL\Cache\QueryCacheProfile $profile + * + * @return static This query instance. + */ + public function setResultCacheProfile(QueryCacheProfile $profile = null) + { + if ($profile !== null && ! $profile->getResultCacheDriver()) { + $resultCacheDriver = $this->_em->getConfiguration()->getResultCacheImpl(); + $profile = $profile->setResultCacheDriver($resultCacheDriver); + } + + $this->_queryCacheProfile = $profile; + + return $this; + } + + /** + * Defines a cache driver to be used for caching result sets and implicitly enables caching. + * + * @param \Doctrine\Common\Cache\Cache|null $resultCacheDriver Cache driver + * + * @return static This query instance. + * + * @throws ORMException + */ + public function setResultCacheDriver($resultCacheDriver = null) + { + if ($resultCacheDriver !== null && ! ($resultCacheDriver instanceof \Doctrine\Common\Cache\Cache)) { + throw ORMException::invalidResultCacheDriver(); + } + + $this->_queryCacheProfile = $this->_queryCacheProfile + ? $this->_queryCacheProfile->setResultCacheDriver($resultCacheDriver) + : new QueryCacheProfile(0, null, $resultCacheDriver); + + return $this; + } + + /** + * Returns the cache driver used for caching result sets. + * + * @deprecated + * + * @return \Doctrine\Common\Cache\Cache Cache driver + */ + public function getResultCacheDriver() + { + if ($this->_queryCacheProfile && $this->_queryCacheProfile->getResultCacheDriver()) { + return $this->_queryCacheProfile->getResultCacheDriver(); + } + + return $this->_em->getConfiguration()->getResultCacheImpl(); + } + + /** + * Set whether or not to cache the results of this query and if so, for + * how long and which ID to use for the cache entry. + * + * @deprecated 2.7 Use {@see enableResultCache} and {@see disableResultCache} instead. + * + * @param bool $useCache + * @param int $lifetime + * @param string $resultCacheId + * + * @return static This query instance. + */ + public function useResultCache($useCache, $lifetime = null, $resultCacheId = null) + { + return $useCache + ? $this->enableResultCache($lifetime, $resultCacheId) + : $this->disableResultCache(); + } + + /** + * Enables caching of the results of this query, for given or default amount of seconds + * and optionally specifies which ID to use for the cache entry. + * + * @param int|null $lifetime How long the cache entry is valid, in seconds. + * @param string|null $resultCacheId ID to use for the cache entry. + * + * @return static This query instance. + */ + public function enableResultCache(?int $lifetime = null, ?string $resultCacheId = null) : self + { + $this->setResultCacheLifetime($lifetime); + $this->setResultCacheId($resultCacheId); + + return $this; + } + + /** + * Disables caching of the results of this query. + * + * @return static This query instance. + */ + public function disableResultCache() : self + { + $this->_queryCacheProfile = null; + + return $this; + } + + /** + * Defines how long the result cache will be active before expire. + * + * @param integer $lifetime How long the cache entry is valid. + * + * @return static This query instance. + */ + public function setResultCacheLifetime($lifetime) + { + $lifetime = ($lifetime !== null) ? (int) $lifetime : 0; + + $this->_queryCacheProfile = $this->_queryCacheProfile + ? $this->_queryCacheProfile->setLifetime($lifetime) + : new QueryCacheProfile($lifetime, null, $this->_em->getConfiguration()->getResultCacheImpl()); + + return $this; + } + + /** + * Retrieves the lifetime of resultset cache. + * + * @deprecated + * + * @return integer + */ + public function getResultCacheLifetime() + { + return $this->_queryCacheProfile ? $this->_queryCacheProfile->getLifetime() : 0; + } + + /** + * Defines if the result cache is active or not. + * + * @param boolean $expire Whether or not to force resultset cache expiration. + * + * @return static This query instance. + */ + public function expireResultCache($expire = true) + { + $this->_expireResultCache = $expire; + + return $this; + } + + /** + * Retrieves if the resultset cache is active or not. + * + * @return boolean + */ + public function getExpireResultCache() + { + return $this->_expireResultCache; + } + + /** + * @return QueryCacheProfile + */ + public function getQueryCacheProfile() + { + return $this->_queryCacheProfile; + } + + /** + * Change the default fetch mode of an association for this query. + * + * $fetchMode can be one of ClassMetadata::FETCH_EAGER or ClassMetadata::FETCH_LAZY + * + * @param string $class + * @param string $assocName + * @param int $fetchMode + * + * @return static This query instance. + */ + public function setFetchMode($class, $assocName, $fetchMode) + { + if ($fetchMode !== Mapping\ClassMetadata::FETCH_EAGER) { + $fetchMode = Mapping\ClassMetadata::FETCH_LAZY; + } + + $this->_hints['fetchMode'][$class][$assocName] = $fetchMode; + + return $this; + } + + /** + * Defines the processing mode to be used during hydration / result set transformation. + * + * @param string|int $hydrationMode Doctrine processing mode to be used during hydration process. + * One of the Query::HYDRATE_* constants. + * + * @return static This query instance. + */ + public function setHydrationMode($hydrationMode) + { + $this->_hydrationMode = $hydrationMode; + + return $this; + } + + /** + * Gets the hydration mode currently used by the query. + * + * @return string|int + */ + public function getHydrationMode() + { + return $this->_hydrationMode; + } + + /** + * Gets the list of results for the query. + * + * Alias for execute(null, $hydrationMode = HYDRATE_OBJECT). + * + * @param string|int $hydrationMode + * + * @return mixed + */ + public function getResult($hydrationMode = self::HYDRATE_OBJECT) + { + return $this->execute(null, $hydrationMode); + } + + /** + * Gets the array of results for the query. + * + * Alias for execute(null, HYDRATE_ARRAY). + * + * @return array + */ + public function getArrayResult() + { + return $this->execute(null, self::HYDRATE_ARRAY); + } + + /** + * Gets the scalar results for the query. + * + * Alias for execute(null, HYDRATE_SCALAR). + * + * @return array + */ + public function getScalarResult() + { + return $this->execute(null, self::HYDRATE_SCALAR); + } + + /** + * Get exactly one result or null. + * + * @param string|int $hydrationMode + * + * @return mixed + * + * @throws NonUniqueResultException + */ + public function getOneOrNullResult($hydrationMode = null) + { + try { + $result = $this->execute(null, $hydrationMode); + } catch (NoResultException $e) { + return null; + } + + + if ($this->_hydrationMode !== self::HYDRATE_SINGLE_SCALAR && ! $result) { + return null; + } + + if ( ! is_array($result)) { + return $result; + } + + if (count($result) > 1) { + throw new NonUniqueResultException; + } + + return array_shift($result); + } + + /** + * Gets the single result of the query. + * + * Enforces the presence as well as the uniqueness of the result. + * + * If the result is not unique, a NonUniqueResultException is thrown. + * If there is no result, a NoResultException is thrown. + * + * @param string|int $hydrationMode + * + * @return mixed + * + * @throws NonUniqueResultException If the query result is not unique. + * @throws NoResultException If the query returned no result and hydration mode is not HYDRATE_SINGLE_SCALAR. + */ + public function getSingleResult($hydrationMode = null) + { + $result = $this->execute(null, $hydrationMode); + + if ($this->_hydrationMode !== self::HYDRATE_SINGLE_SCALAR && ! $result) { + throw new NoResultException; + } + + if ( ! is_array($result)) { + return $result; + } + + if (count($result) > 1) { + throw new NonUniqueResultException; + } + + return array_shift($result); + } + + /** + * Gets the single scalar result of the query. + * + * Alias for getSingleResult(HYDRATE_SINGLE_SCALAR). + * + * @return mixed The scalar result. + * + * @throws NoResultException If the query returned no result. + * @throws NonUniqueResultException If the query result is not unique. + */ + public function getSingleScalarResult() + { + return $this->getSingleResult(self::HYDRATE_SINGLE_SCALAR); + } + + /** + * Sets a query hint. If the hint name is not recognized, it is silently ignored. + * + * @param string $name The name of the hint. + * @param mixed $value The value of the hint. + * + * @return static This query instance. + */ + public function setHint($name, $value) + { + $this->_hints[$name] = $value; + + return $this; + } + + /** + * Gets the value of a query hint. If the hint name is not recognized, FALSE is returned. + * + * @param string $name The name of the hint. + * + * @return mixed The value of the hint or FALSE, if the hint name is not recognized. + */ + public function getHint($name) + { + return isset($this->_hints[$name]) ? $this->_hints[$name] : false; + } + + /** + * Check if the query has a hint + * + * @param string $name The name of the hint + * + * @return bool False if the query does not have any hint + */ + public function hasHint($name) + { + return isset($this->_hints[$name]); + } + + /** + * Return the key value map of query hints that are currently set. + * + * @return array + */ + public function getHints() + { + return $this->_hints; + } + + /** + * Executes the query and returns an IterableResult that can be used to incrementally + * iterate over the result. + * + * @param ArrayCollection|array|null $parameters The query parameters. + * @param string|int|null $hydrationMode The hydration mode to use. + * + * @return \Doctrine\ORM\Internal\Hydration\IterableResult + */ + public function iterate($parameters = null, $hydrationMode = null) + { + if ($hydrationMode !== null) { + $this->setHydrationMode($hydrationMode); + } + + if ( ! empty($parameters)) { + $this->setParameters($parameters); + } + + $rsm = $this->getResultSetMapping(); + $stmt = $this->_doExecute(); + + return $this->_em->newHydrator($this->_hydrationMode)->iterate($stmt, $rsm, $this->_hints); + } + + /** + * Executes the query. + * + * @param ArrayCollection|array|null $parameters Query parameters. + * @param string|int|null $hydrationMode Processing mode to be used during the hydration process. + * + * @return mixed + */ + public function execute($parameters = null, $hydrationMode = null) + { + if ($this->cacheable && $this->isCacheEnabled()) { + return $this->executeUsingQueryCache($parameters, $hydrationMode); + } + + return $this->executeIgnoreQueryCache($parameters, $hydrationMode); + } + + /** + * Execute query ignoring second level cache. + * + * @param ArrayCollection|array|null $parameters + * @param string|int|null $hydrationMode + * + * @return mixed + */ + private function executeIgnoreQueryCache($parameters = null, $hydrationMode = null) + { + if ($hydrationMode !== null) { + $this->setHydrationMode($hydrationMode); + } + + if ( ! empty($parameters)) { + $this->setParameters($parameters); + } + + $setCacheEntry = function() {}; + + if ($this->_hydrationCacheProfile !== null) { + list($cacheKey, $realCacheKey) = $this->getHydrationCacheId(); + + $queryCacheProfile = $this->getHydrationCacheProfile(); + $cache = $queryCacheProfile->getResultCacheDriver(); + $result = $cache->fetch($cacheKey); + + if (isset($result[$realCacheKey])) { + return $result[$realCacheKey]; + } + + if ( ! $result) { + $result = []; + } + + $setCacheEntry = function($data) use ($cache, $result, $cacheKey, $realCacheKey, $queryCacheProfile) { + $result[$realCacheKey] = $data; + + $cache->save($cacheKey, $result, $queryCacheProfile->getLifetime()); + }; + } + + $stmt = $this->_doExecute(); + + if (is_numeric($stmt)) { + $setCacheEntry($stmt); + + return $stmt; + } + + $rsm = $this->getResultSetMapping(); + $data = $this->_em->newHydrator($this->_hydrationMode)->hydrateAll($stmt, $rsm, $this->_hints); + + $setCacheEntry($data); + + return $data; + } + + /** + * Load from second level cache or executes the query and put into cache. + * + * @param ArrayCollection|array|null $parameters + * @param string|int|null $hydrationMode + * + * @return mixed + */ + private function executeUsingQueryCache($parameters = null, $hydrationMode = null) + { + $rsm = $this->getResultSetMapping(); + $queryCache = $this->_em->getCache()->getQueryCache($this->cacheRegion); + $queryKey = new QueryCacheKey( + $this->getHash(), + $this->lifetime, + $this->cacheMode ?: Cache::MODE_NORMAL, + $this->getTimestampKey() + ); + + $result = $queryCache->get($queryKey, $rsm, $this->_hints); + + if ($result !== null) { + if ($this->cacheLogger) { + $this->cacheLogger->queryCacheHit($queryCache->getRegion()->getName(), $queryKey); + } + + return $result; + } + + $result = $this->executeIgnoreQueryCache($parameters, $hydrationMode); + $cached = $queryCache->put($queryKey, $rsm, $result, $this->_hints); + + if ($this->cacheLogger) { + $this->cacheLogger->queryCacheMiss($queryCache->getRegion()->getName(), $queryKey); + + if ($cached) { + $this->cacheLogger->queryCachePut($queryCache->getRegion()->getName(), $queryKey); + } + } + + return $result; + } + + /** + * @return \Doctrine\ORM\Cache\TimestampCacheKey|null + */ + private function getTimestampKey() + { + $entityName = reset($this->_resultSetMapping->aliasMap); + + if (empty($entityName)) { + return null; + } + + $metadata = $this->_em->getClassMetadata($entityName); + + return new Cache\TimestampCacheKey($metadata->rootEntityName); + } + + /** + * Get the result cache id to use to store the result set cache entry. + * Will return the configured id if it exists otherwise a hash will be + * automatically generated for you. + * + * @return array ($key, $hash) + */ + protected function getHydrationCacheId() + { + $parameters = []; + + foreach ($this->getParameters() as $parameter) { + $parameters[$parameter->getName()] = $this->processParameterValue($parameter->getValue()); + } + + $sql = $this->getSQL(); + $queryCacheProfile = $this->getHydrationCacheProfile(); + $hints = $this->getHints(); + $hints['hydrationMode'] = $this->getHydrationMode(); + + ksort($hints); + + return $queryCacheProfile->generateCacheKeys($sql, $parameters, $hints); + } + + /** + * Set the result cache id to use to store the result set cache entry. + * If this is not explicitly set by the developer then a hash is automatically + * generated for you. + * + * @param string $id + * + * @return static This query instance. + */ + public function setResultCacheId($id) + { + $this->_queryCacheProfile = $this->_queryCacheProfile + ? $this->_queryCacheProfile->setCacheKey($id) + : new QueryCacheProfile(0, $id, $this->_em->getConfiguration()->getResultCacheImpl()); + + return $this; + } + + /** + * Get the result cache id to use to store the result set cache entry if set. + * + * @deprecated + * + * @return string + */ + public function getResultCacheId() + { + return $this->_queryCacheProfile ? $this->_queryCacheProfile->getCacheKey() : null; + } + + /** + * Executes the query and returns a the resulting Statement object. + * + * @return \Doctrine\DBAL\Driver\Statement The executed database statement that holds the results. + */ + abstract protected function _doExecute(); + + /** + * Cleanup Query resource when clone is called. + * + * @return void + */ + public function __clone() + { + $this->parameters = new ArrayCollection(); + + $this->_hints = []; + $this->_hints = $this->_em->getConfiguration()->getDefaultQueryHints(); + } + + /** + * Generates a string of currently query to use for the cache second level cache. + * + * @return string + */ + protected function getHash() + { + $query = $this->getSQL(); + $hints = $this->getHints(); + $params = array_map(function(Parameter $parameter) { + // Small optimization + // Does not invoke processParameterValue for scalar values + if (is_scalar($value = $parameter->getValue())) { + return $value; + } + + return $this->processParameterValue($value); + }, $this->parameters->getValues()); + + ksort($hints); + + return sha1($query . '-' . serialize($params) . '-' . serialize($hints)); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache.php new file mode 100644 index 0000000..3da7c05 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache.php @@ -0,0 +1,178 @@ +. + */ + +namespace Doctrine\ORM; + +/** + * Provides an API for querying/managing the second level cache regions. + * + * @since 2.5 + * @author Fabio B. Silva + */ +interface Cache +{ + const DEFAULT_QUERY_REGION_NAME = 'query_cache_region'; + + const DEFAULT_TIMESTAMP_REGION_NAME = 'timestamp_cache_region'; + + /** + * May read items from the cache, but will not add items. + */ + const MODE_GET = 1; + + /** + * Will never read items from the cache, + * but will add items to the cache as it reads them from the database. + */ + const MODE_PUT = 2; + + /** + * May read items from the cache, and add items to the cache. + */ + const MODE_NORMAL = 3; + + /** + * The query will never read items from the cache, + * but will refresh items to the cache as it reads them from the database. + */ + const MODE_REFRESH = 4; + + /** + * @param string $className The entity class. + * + * @return \Doctrine\ORM\Cache\Region|null + */ + public function getEntityCacheRegion($className); + + /** + * @param string $className The entity class. + * @param string $association The field name that represents the association. + * + * @return \Doctrine\ORM\Cache\Region|null + */ + public function getCollectionCacheRegion($className, $association); + + /** + * Determine whether the cache contains data for the given entity "instance". + * + * @param string $className The entity class. + * @param mixed $identifier The entity identifier + * + * @return boolean true if the underlying cache contains corresponding data; false otherwise. + */ + public function containsEntity($className, $identifier); + + /** + * Evicts the entity data for a particular entity "instance". + * + * @param string $className The entity class. + * @param mixed $identifier The entity identifier. + * + * @return void + */ + public function evictEntity($className, $identifier); + + /** + * Evicts all entity data from the given region. + * + * @param string $className The entity metadata. + * + * @return void + */ + public function evictEntityRegion($className); + + /** + * Evict data from all entity regions. + * + * @return void + */ + public function evictEntityRegions(); + + /** + * Determine whether the cache contains data for the given collection. + * + * @param string $className The entity class. + * @param string $association The field name that represents the association. + * @param mixed $ownerIdentifier The identifier of the owning entity. + * + * @return boolean true if the underlying cache contains corresponding data; false otherwise. + */ + public function containsCollection($className, $association, $ownerIdentifier); + + /** + * Evicts the cache data for the given identified collection instance. + * + * @param string $className The entity class. + * @param string $association The field name that represents the association. + * @param mixed $ownerIdentifier The identifier of the owning entity. + * + * @return void + */ + public function evictCollection($className, $association, $ownerIdentifier); + + /** + * Evicts all entity data from the given region. + * + * @param string $className The entity class. + * @param string $association The field name that represents the association. + * + * @return void + */ + public function evictCollectionRegion($className, $association); + + /** + * Evict data from all collection regions. + * + * @return void + */ + public function evictCollectionRegions(); + + /** + * Determine whether the cache contains data for the given query. + * + * @param string $regionName The cache name given to the query. + * + * @return boolean true if the underlying cache contains corresponding data; false otherwise. + */ + public function containsQuery($regionName); + + /** + * Evicts all cached query results under the given name, or default query cache if the region name is NULL. + * + * @param string|null $regionName The cache name associated to the queries being cached. + */ + public function evictQueryRegion($regionName = null); + + /** + * Evict data from all query regions. + * + * @return void + */ + public function evictQueryRegions(); + + /** + * Get query cache by region name or create a new one if none exist. + * + * @param string|null $regionName Query cache region name, or default query cache if the region name is NULL. + * + * @return \Doctrine\ORM\Cache\QueryCache The Query Cache associated with the region name. + */ + public function getQueryCache($regionName = null); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/AssociationCacheEntry.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/AssociationCacheEntry.php new file mode 100644 index 0000000..dae5e60 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/AssociationCacheEntry.php @@ -0,0 +1,68 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Association cache entry + * + * @since 2.5 + * @author Fabio B. Silva + */ +class AssociationCacheEntry implements CacheEntry +{ + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var array The entity identifier + */ + public $identifier; + + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var string The entity class name + */ + public $class; + + /** + * @param string $class The entity class. + * @param array $identifier The entity identifier. + */ + public function __construct($class, array $identifier) + { + $this->class = $class; + $this->identifier = $identifier; + } + + /** + * Creates a new AssociationCacheEntry + * + * This method allow Doctrine\Common\Cache\PhpFileCache compatibility + * + * @param array $values array containing property values + * + * @return AssociationCacheEntry + */ + public static function __set_state(array $values) + { + return new self($values['class'], $values['identifier']); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheConfiguration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheConfiguration.php new file mode 100644 index 0000000..eb3ec42 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheConfiguration.php @@ -0,0 +1,128 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +use Doctrine\ORM\Cache\Logging\CacheLogger; + +/** + * Configuration container for second-level cache. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class CacheConfiguration +{ + /** + * @var \Doctrine\ORM\Cache\CacheFactory|null + */ + private $cacheFactory; + + /** + * @var \Doctrine\ORM\Cache\RegionsConfiguration|null + */ + private $regionsConfig; + + /** + * @var \Doctrine\ORM\Cache\Logging\CacheLogger|null + */ + private $cacheLogger; + + /** + * @var \Doctrine\ORM\Cache\QueryCacheValidator|null + */ + private $queryValidator; + + /** + * @return \Doctrine\ORM\Cache\CacheFactory|null + */ + public function getCacheFactory() + { + return $this->cacheFactory; + } + + /** + * @param \Doctrine\ORM\Cache\CacheFactory $factory + * + * @return void + */ + public function setCacheFactory(CacheFactory $factory) + { + $this->cacheFactory = $factory; + } + + /** + * @return \Doctrine\ORM\Cache\Logging\CacheLogger|null + */ + public function getCacheLogger() + { + return $this->cacheLogger; + } + + /** + * @param \Doctrine\ORM\Cache\Logging\CacheLogger $logger + */ + public function setCacheLogger(CacheLogger $logger) + { + $this->cacheLogger = $logger; + } + + /** + * @return \Doctrine\ORM\Cache\RegionsConfiguration + */ + public function getRegionsConfiguration() + { + if ($this->regionsConfig === null) { + $this->regionsConfig = new RegionsConfiguration(); + } + + return $this->regionsConfig; + } + + /** + * @param \Doctrine\ORM\Cache\RegionsConfiguration $regionsConfig + */ + public function setRegionsConfiguration(RegionsConfiguration $regionsConfig) + { + $this->regionsConfig = $regionsConfig; + } + + /** + * @return \Doctrine\ORM\Cache\QueryCacheValidator + */ + public function getQueryValidator() + { + if ($this->queryValidator === null) { + $this->queryValidator = new TimestampQueryCacheValidator( + $this->cacheFactory->getTimestampRegion() + ); + } + + return $this->queryValidator; + } + + /** + * @param \Doctrine\ORM\Cache\QueryCacheValidator $validator + */ + public function setQueryValidator(QueryCacheValidator $validator) + { + $this->queryValidator = $validator; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheEntry.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheEntry.php new file mode 100644 index 0000000..c34b0ff --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheEntry.php @@ -0,0 +1,36 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Cache entry interface + * + * IMPORTANT NOTE: + * + * Fields of classes that implement CacheEntry are public for performance reason. + * + * @since 2.5 + * @author Fabio B. Silva + */ +interface CacheEntry +{ + +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheException.php new file mode 100644 index 0000000..315a8aa --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheException.php @@ -0,0 +1,73 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +use Doctrine\ORM\ORMException; + +/** + * Exception for cache. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class CacheException extends ORMException +{ + /** + * @param string $sourceEntity + * @param string $fieldName + * + * @return \Doctrine\ORM\Cache\CacheException + */ + public static function updateReadOnlyCollection($sourceEntity, $fieldName) + { + return new self(sprintf('Cannot update a readonly collection "%s#%s"', $sourceEntity, $fieldName)); + } + + /** + * @param string $entityName + * + * @return \Doctrine\ORM\Cache\CacheException + */ + public static function updateReadOnlyEntity($entityName) + { + return new self(sprintf('Cannot update a readonly entity "%s"', $entityName)); + } + + /** + * @param string $entityName + * + * @return \Doctrine\ORM\Cache\CacheException + */ + public static function nonCacheableEntity($entityName) + { + return new self(sprintf('Entity "%s" not configured as part of the second-level cache.', $entityName)); + } + + /** + * @param string $entityName + * @param string $field + * + * @return CacheException + */ + public static function nonCacheableEntityAssociation($entityName, $field) + { + return new self(sprintf('Entity association field "%s#%s" not configured as part of the second-level cache.', $entityName, $field)); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheFactory.php new file mode 100644 index 0000000..b915100 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheFactory.php @@ -0,0 +1,112 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Persisters\Collection\CollectionPersister; +use Doctrine\ORM\Persisters\Entity\EntityPersister; + +/** + * Contract for building second level cache regions components. + * + * @since 2.5 + * @author Fabio B. Silva + */ +interface CacheFactory +{ + /** + * Build an entity persister for the given entity metadata. + * + * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. + * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $persister The entity persister that will be cached. + * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. + * + * @return \Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister + */ + public function buildCachedEntityPersister(EntityManagerInterface $em, EntityPersister $persister, ClassMetadata $metadata); + + /** + * Build a collection persister for the given relation mapping. + * + * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. + * @param \Doctrine\ORM\Persisters\Collection\CollectionPersister $persister The collection persister that will be cached. + * @param array $mapping The association mapping. + * + * @return \Doctrine\ORM\Cache\Persister\Collection\CachedCollectionPersister + */ + public function buildCachedCollectionPersister(EntityManagerInterface $em, CollectionPersister $persister, array $mapping); + + /** + * Build a query cache based on the given region name + * + * @param \Doctrine\ORM\EntityManagerInterface $em The Entity manager. + * @param string $regionName The region name. + * + * @return \Doctrine\ORM\Cache\QueryCache The built query cache. + */ + public function buildQueryCache(EntityManagerInterface $em, $regionName = null); + + /** + * Build an entity hydrator + * + * @param \Doctrine\ORM\EntityManagerInterface $em The Entity manager. + * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. + * + * @return \Doctrine\ORM\Cache\EntityHydrator The built entity hydrator. + */ + public function buildEntityHydrator(EntityManagerInterface $em, ClassMetadata $metadata); + + /** + * Build a collection hydrator + * + * @param \Doctrine\ORM\EntityManagerInterface $em The Entity manager. + * @param array $mapping The association mapping. + * + * @return \Doctrine\ORM\Cache\CollectionHydrator The built collection hydrator. + */ + public function buildCollectionHydrator(EntityManagerInterface $em, array $mapping); + + /** + * Build a cache region + * + * @param array $cache The cache configuration. + * + * @return \Doctrine\ORM\Cache\Region The cache region. + */ + public function getRegion(array $cache); + + /** + * Build timestamp cache region + * + * @return \Doctrine\ORM\Cache\TimestampRegion The timestamp region. + */ + public function getTimestampRegion(); + + /** + * Build \Doctrine\ORM\Cache + * + * @param EntityManagerInterface $entityManager + * + * @return \Doctrine\ORM\Cache + */ + public function createCache(EntityManagerInterface $entityManager); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheKey.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheKey.php new file mode 100644 index 0000000..1641c99 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheKey.php @@ -0,0 +1,38 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Defines entity / collection / query key to be stored in the cache region. + * Allows multiple roles to be stored in the same cache region. + * + * @since 2.5 + * @author Fabio B. Silva + */ +abstract class CacheKey +{ + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var string Unique identifier + */ + public $hash; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheEntry.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheEntry.php new file mode 100644 index 0000000..b3a1def --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheEntry.php @@ -0,0 +1,59 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Collection cache entry + * + * @since 2.5 + * @author Fabio B. Silva + */ +class CollectionCacheEntry implements CacheEntry +{ + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var CacheKey[] The list of entity identifiers hold by the collection + */ + public $identifiers; + + /** + * @param CacheKey[] $identifiers List of entity identifiers hold by the collection + */ + public function __construct(array $identifiers) + { + $this->identifiers = $identifiers; + } + + /** + * Creates a new CollectionCacheEntry + * + * This method allows for Doctrine\Common\Cache\PhpFileCache compatibility + * + * @param array $values array containing property values + * + * @return CollectionCacheEntry + */ + public static function __set_state(array $values) + { + return new self($values['identifiers']); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheKey.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheKey.php new file mode 100644 index 0000000..6b63145 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheKey.php @@ -0,0 +1,66 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Defines entity collection roles to be stored in the cache region. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class CollectionCacheKey extends CacheKey +{ + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var array The owner entity identifier + */ + public $ownerIdentifier; + + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var string The owner entity class + */ + public $entityClass; + + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var string The association name + */ + public $association; + + /** + * @param string $entityClass The entity class. + * @param string $association The field name that represents the association. + * @param array $ownerIdentifier The identifier of the owning entity. + */ + public function __construct($entityClass, $association, array $ownerIdentifier) + { + ksort($ownerIdentifier); + + $this->ownerIdentifier = $ownerIdentifier; + $this->entityClass = (string) $entityClass; + $this->association = (string) $association; + $this->hash = str_replace('\\', '.', strtolower($entityClass)) . '_' . implode(' ', $ownerIdentifier) . '__' . $association; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionHydrator.php new file mode 100644 index 0000000..04cdde1 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionHydrator.php @@ -0,0 +1,52 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +use Doctrine\ORM\PersistentCollection; +use Doctrine\ORM\Mapping\ClassMetadata; + +/** + * Hydrator cache entry for collections + * + * @since 2.5 + * @author Fabio B. Silva + */ +interface CollectionHydrator +{ + /** + * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. + * @param \Doctrine\ORM\Cache\CollectionCacheKey $key The cached collection key. + * @param array|\Doctrine\Common\Collections\Collection $collection The collection. + * + * @return \Doctrine\ORM\Cache\CollectionCacheEntry + */ + public function buildCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, $collection); + + /** + * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The owning entity metadata. + * @param \Doctrine\ORM\Cache\CollectionCacheKey $key The cached collection key. + * @param \Doctrine\ORM\Cache\CollectionCacheEntry $entry The cached collection entry. + * @param \Doctrine\ORM\PersistentCollection $collection The collection to load the cache into. + * + * @return array + */ + public function loadCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, CollectionCacheEntry $entry, PersistentCollection $collection); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/ConcurrentRegion.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/ConcurrentRegion.php new file mode 100644 index 0000000..12da6d6 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/ConcurrentRegion.php @@ -0,0 +1,57 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Defines contract for concurrently managed data region. + * It should be able to lock an specific cache entry in an atomic operation. + * + * When a entry is locked another process should not be able to read or write the entry. + * All evict operation should not consider locks, even though an entry is locked evict should be able to delete the entry and its lock. + * + * @since 2.5 + * @author Fabio B. Silva + */ +interface ConcurrentRegion extends Region +{ + /** + * Attempts to read lock the mapping for the given key. + * + * @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to lock. + * + * @return \Doctrine\ORM\Cache\Lock A lock instance or NULL if the lock already exists. + * + * @throws \Doctrine\ORM\Cache\LockException Indicates a problem accessing the region. + */ + public function lock(CacheKey $key); + + /** + * Attempts to read unlock the mapping for the given key. + * + * @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to unlock. + * @param \Doctrine\ORM\Cache\Lock $lock The lock previously obtained from {@link readLock} + * + * @return void + * + * @throws \Doctrine\ORM\Cache\LockException Indicates a problem accessing the region. + */ + public function unlock(CacheKey $key, Lock $lock); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCache.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCache.php new file mode 100644 index 0000000..80fbd81 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCache.php @@ -0,0 +1,342 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +use Doctrine\ORM\Cache; +use Doctrine\Common\Util\ClassUtils; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Cache\Persister\CachedPersister; +use Doctrine\ORM\ORMInvalidArgumentException; + +/** + * Provides an API for querying/managing the second level cache regions. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class DefaultCache implements Cache +{ + /** + * @var \Doctrine\ORM\EntityManagerInterface + */ + private $em; + + /** + * @var \Doctrine\ORM\UnitOfWork + */ + private $uow; + + /** + * @var \Doctrine\ORM\Cache\CacheFactory + */ + private $cacheFactory; + + /** + * @var \Doctrine\ORM\Cache\QueryCache[] + */ + private $queryCaches = []; + + /** + * @var \Doctrine\ORM\Cache\QueryCache + */ + private $defaultQueryCache; + + /** + * {@inheritdoc} + */ + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + $this->uow = $em->getUnitOfWork(); + $this->cacheFactory = $em->getConfiguration() + ->getSecondLevelCacheConfiguration() + ->getCacheFactory(); + } + + /** + * {@inheritdoc} + */ + public function getEntityCacheRegion($className) + { + $metadata = $this->em->getClassMetadata($className); + $persister = $this->uow->getEntityPersister($metadata->rootEntityName); + + if ( ! ($persister instanceof CachedPersister)) { + return null; + } + + return $persister->getCacheRegion(); + } + + /** + * {@inheritdoc} + */ + public function getCollectionCacheRegion($className, $association) + { + $metadata = $this->em->getClassMetadata($className); + $persister = $this->uow->getCollectionPersister($metadata->getAssociationMapping($association)); + + if ( ! ($persister instanceof CachedPersister)) { + return null; + } + + return $persister->getCacheRegion(); + } + + /** + * {@inheritdoc} + */ + public function containsEntity($className, $identifier) + { + $metadata = $this->em->getClassMetadata($className); + $persister = $this->uow->getEntityPersister($metadata->rootEntityName); + + if ( ! ($persister instanceof CachedPersister)) { + return false; + } + + return $persister->getCacheRegion()->contains($this->buildEntityCacheKey($metadata, $identifier)); + } + + /** + * {@inheritdoc} + */ + public function evictEntity($className, $identifier) + { + $metadata = $this->em->getClassMetadata($className); + $persister = $this->uow->getEntityPersister($metadata->rootEntityName); + + if ( ! ($persister instanceof CachedPersister)) { + return; + } + + $persister->getCacheRegion()->evict($this->buildEntityCacheKey($metadata, $identifier)); + } + + /** + * {@inheritdoc} + */ + public function evictEntityRegion($className) + { + $metadata = $this->em->getClassMetadata($className); + $persister = $this->uow->getEntityPersister($metadata->rootEntityName); + + if ( ! ($persister instanceof CachedPersister)) { + return; + } + + $persister->getCacheRegion()->evictAll(); + } + + /** + * {@inheritdoc} + */ + public function evictEntityRegions() + { + $metadatas = $this->em->getMetadataFactory()->getAllMetadata(); + + foreach ($metadatas as $metadata) { + $persister = $this->uow->getEntityPersister($metadata->rootEntityName); + + if ( ! ($persister instanceof CachedPersister)) { + continue; + } + + $persister->getCacheRegion()->evictAll(); + } + } + + /** + * {@inheritdoc} + */ + public function containsCollection($className, $association, $ownerIdentifier) + { + $metadata = $this->em->getClassMetadata($className); + $persister = $this->uow->getCollectionPersister($metadata->getAssociationMapping($association)); + + if ( ! ($persister instanceof CachedPersister)) { + return false; + } + + return $persister->getCacheRegion()->contains($this->buildCollectionCacheKey($metadata, $association, $ownerIdentifier)); + } + + /** + * {@inheritdoc} + */ + public function evictCollection($className, $association, $ownerIdentifier) + { + $metadata = $this->em->getClassMetadata($className); + $persister = $this->uow->getCollectionPersister($metadata->getAssociationMapping($association)); + + if ( ! ($persister instanceof CachedPersister)) { + return; + } + + $persister->getCacheRegion()->evict($this->buildCollectionCacheKey($metadata, $association, $ownerIdentifier)); + } + + /** + * {@inheritdoc} + */ + public function evictCollectionRegion($className, $association) + { + $metadata = $this->em->getClassMetadata($className); + $persister = $this->uow->getCollectionPersister($metadata->getAssociationMapping($association)); + + if ( ! ($persister instanceof CachedPersister)) { + return; + } + + $persister->getCacheRegion()->evictAll(); + } + + /** + * {@inheritdoc} + */ + public function evictCollectionRegions() + { + $metadatas = $this->em->getMetadataFactory()->getAllMetadata(); + + foreach ($metadatas as $metadata) { + + foreach ($metadata->associationMappings as $association) { + + if ( ! $association['type'] & ClassMetadata::TO_MANY) { + continue; + } + + $persister = $this->uow->getCollectionPersister($association); + + if ( ! ($persister instanceof CachedPersister)) { + continue; + } + + $persister->getCacheRegion()->evictAll(); + } + } + } + + /** + * {@inheritdoc} + */ + public function containsQuery($regionName) + { + return isset($this->queryCaches[$regionName]); + } + + /** + * {@inheritdoc} + */ + public function evictQueryRegion($regionName = null) + { + if ($regionName === null && $this->defaultQueryCache !== null) { + $this->defaultQueryCache->clear(); + + return; + } + + if (isset($this->queryCaches[$regionName])) { + $this->queryCaches[$regionName]->clear(); + } + } + + /** + * {@inheritdoc} + */ + public function evictQueryRegions() + { + $this->getQueryCache()->clear(); + + foreach ($this->queryCaches as $queryCache) { + $queryCache->clear(); + } + } + + /** + * {@inheritdoc} + */ + public function getQueryCache($regionName = null) + { + if ($regionName === null) { + return $this->defaultQueryCache ?: + $this->defaultQueryCache = $this->cacheFactory->buildQueryCache($this->em); + } + + if ( ! isset($this->queryCaches[$regionName])) { + $this->queryCaches[$regionName] = $this->cacheFactory->buildQueryCache($this->em, $regionName); + } + + return $this->queryCaches[$regionName]; + } + + /** + * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. + * @param mixed $identifier The entity identifier. + * + * @return \Doctrine\ORM\Cache\EntityCacheKey + */ + private function buildEntityCacheKey(ClassMetadata $metadata, $identifier) + { + if ( ! is_array($identifier)) { + $identifier = $this->toIdentifierArray($metadata, $identifier); + } + + return new EntityCacheKey($metadata->rootEntityName, $identifier); + } + + /** + * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. + * @param string $association The field name that represents the association. + * @param mixed $ownerIdentifier The identifier of the owning entity. + * + * @return \Doctrine\ORM\Cache\CollectionCacheKey + */ + private function buildCollectionCacheKey(ClassMetadata $metadata, $association, $ownerIdentifier) + { + if ( ! is_array($ownerIdentifier)) { + $ownerIdentifier = $this->toIdentifierArray($metadata, $ownerIdentifier); + } + + return new CollectionCacheKey($metadata->rootEntityName, $association, $ownerIdentifier); + } + + /** + * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. + * @param mixed $identifier The entity identifier. + * + * @return array + */ + private function toIdentifierArray(ClassMetadata $metadata, $identifier) + { + if (is_object($identifier) && $this->em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($identifier))) { + $identifier = $this->uow->getSingleIdentifierValue($identifier); + + if ($identifier === null) { + throw ORMInvalidArgumentException::invalidIdentifierBindingEntity(); + } + } + + return [$metadata->identifier[0] => $identifier]; + } + +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCacheFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCacheFactory.php new file mode 100644 index 0000000..bfc6aa2 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCacheFactory.php @@ -0,0 +1,275 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +use Doctrine\Common\Cache\Cache as CacheAdapter; +use Doctrine\Common\Cache\CacheProvider; +use Doctrine\Common\Cache\MultiGetCache; +use Doctrine\ORM\Cache; +use Doctrine\ORM\Cache\Persister\Collection\NonStrictReadWriteCachedCollectionPersister; +use Doctrine\ORM\Cache\Persister\Collection\ReadOnlyCachedCollectionPersister; +use Doctrine\ORM\Cache\Persister\Collection\ReadWriteCachedCollectionPersister; +use Doctrine\ORM\Cache\Persister\Entity\NonStrictReadWriteCachedEntityPersister; +use Doctrine\ORM\Cache\Persister\Entity\ReadOnlyCachedEntityPersister; +use Doctrine\ORM\Cache\Persister\Entity\ReadWriteCachedEntityPersister; +use Doctrine\ORM\Cache\Region\DefaultMultiGetRegion; +use Doctrine\ORM\Cache\Region\DefaultRegion; +use Doctrine\ORM\Cache\Region\FileLockRegion; +use Doctrine\ORM\Cache\Region\UpdateTimestampCache; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Persisters\Collection\CollectionPersister; +use Doctrine\ORM\Persisters\Entity\EntityPersister; + +/** + * @since 2.5 + * @author Fabio B. Silva + */ +class DefaultCacheFactory implements CacheFactory +{ + /** + * @var CacheAdapter + */ + private $cache; + + /** + * @var \Doctrine\ORM\Cache\RegionsConfiguration + */ + private $regionsConfig; + + /** + * @var \Doctrine\ORM\Cache\TimestampRegion|null + */ + private $timestampRegion; + + /** + * @var \Doctrine\ORM\Cache\Region[] + */ + private $regions = []; + + /** + * @var string|null + */ + private $fileLockRegionDirectory; + + /** + * @param RegionsConfiguration $cacheConfig + * @param CacheAdapter $cache + */ + public function __construct(RegionsConfiguration $cacheConfig, CacheAdapter $cache) + { + $this->cache = $cache; + $this->regionsConfig = $cacheConfig; + } + + /** + * @param string $fileLockRegionDirectory + */ + public function setFileLockRegionDirectory($fileLockRegionDirectory) + { + $this->fileLockRegionDirectory = (string) $fileLockRegionDirectory; + } + + /** + * @return string + */ + public function getFileLockRegionDirectory() + { + return $this->fileLockRegionDirectory; + } + + /** + * @param \Doctrine\ORM\Cache\Region $region + */ + public function setRegion(Region $region) + { + $this->regions[$region->getName()] = $region; + } + + /** + * @param \Doctrine\ORM\Cache\TimestampRegion $region + */ + public function setTimestampRegion(TimestampRegion $region) + { + $this->timestampRegion = $region; + } + + /** + * {@inheritdoc} + */ + public function buildCachedEntityPersister(EntityManagerInterface $em, EntityPersister $persister, ClassMetadata $metadata) + { + $region = $this->getRegion($metadata->cache); + $usage = $metadata->cache['usage']; + + if ($usage === ClassMetadata::CACHE_USAGE_READ_ONLY) { + return new ReadOnlyCachedEntityPersister($persister, $region, $em, $metadata); + } + + if ($usage === ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE) { + return new NonStrictReadWriteCachedEntityPersister($persister, $region, $em, $metadata); + } + + if ($usage === ClassMetadata::CACHE_USAGE_READ_WRITE) { + return new ReadWriteCachedEntityPersister($persister, $region, $em, $metadata); + } + + throw new \InvalidArgumentException(sprintf("Unrecognized access strategy type [%s]", $usage)); + } + + /** + * {@inheritdoc} + */ + public function buildCachedCollectionPersister(EntityManagerInterface $em, CollectionPersister $persister, array $mapping) + { + $usage = $mapping['cache']['usage']; + $region = $this->getRegion($mapping['cache']); + + if ($usage === ClassMetadata::CACHE_USAGE_READ_ONLY) { + return new ReadOnlyCachedCollectionPersister($persister, $region, $em, $mapping); + } + + if ($usage === ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE) { + return new NonStrictReadWriteCachedCollectionPersister($persister, $region, $em, $mapping); + } + + if ($usage === ClassMetadata::CACHE_USAGE_READ_WRITE) { + return new ReadWriteCachedCollectionPersister($persister, $region, $em, $mapping); + } + + throw new \InvalidArgumentException(sprintf("Unrecognized access strategy type [%s]", $usage)); + } + + /** + * {@inheritdoc} + */ + public function buildQueryCache(EntityManagerInterface $em, $regionName = null) + { + return new DefaultQueryCache( + $em, + $this->getRegion( + [ + 'region' => $regionName ?: Cache::DEFAULT_QUERY_REGION_NAME, + 'usage' => ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE + ] + ) + ); + } + + /** + * {@inheritdoc} + */ + public function buildCollectionHydrator(EntityManagerInterface $em, array $mapping) + { + return new DefaultCollectionHydrator($em); + } + + /** + * {@inheritdoc} + */ + public function buildEntityHydrator(EntityManagerInterface $em, ClassMetadata $metadata) + { + return new DefaultEntityHydrator($em); + } + + /** + * {@inheritdoc} + */ + public function getRegion(array $cache) + { + if (isset($this->regions[$cache['region']])) { + return $this->regions[$cache['region']]; + } + + $name = $cache['region']; + $cacheAdapter = $this->createRegionCache($name); + $lifetime = $this->regionsConfig->getLifetime($cache['region']); + + $region = ($cacheAdapter instanceof MultiGetCache) + ? new DefaultMultiGetRegion($name, $cacheAdapter, $lifetime) + : new DefaultRegion($name, $cacheAdapter, $lifetime); + + if ($cache['usage'] === ClassMetadata::CACHE_USAGE_READ_WRITE) { + + if ( + '' === $this->fileLockRegionDirectory || + null === $this->fileLockRegionDirectory + ) { + throw new \LogicException( + 'If you want to use a "READ_WRITE" cache an implementation of "Doctrine\ORM\Cache\ConcurrentRegion" is required, ' . + 'The default implementation provided by doctrine is "Doctrine\ORM\Cache\Region\FileLockRegion" if you want to use it please provide a valid directory, DefaultCacheFactory#setFileLockRegionDirectory(). ' + ); + } + + $directory = $this->fileLockRegionDirectory . DIRECTORY_SEPARATOR . $cache['region']; + $region = new FileLockRegion($region, $directory, $this->regionsConfig->getLockLifetime($cache['region'])); + } + + return $this->regions[$cache['region']] = $region; + } + + /** + * @param string $name + * + * @return CacheAdapter + */ + private function createRegionCache($name) + { + $cacheAdapter = clone $this->cache; + + if (!$cacheAdapter instanceof CacheProvider) { + return $cacheAdapter; + } + + $namespace = $cacheAdapter->getNamespace(); + + if ('' !== $namespace) { + $namespace .= ':'; + } + + $cacheAdapter->setNamespace($namespace . $name); + + return $cacheAdapter; + } + + /** + * {@inheritdoc} + */ + public function getTimestampRegion() + { + if ($this->timestampRegion === null) { + $name = Cache::DEFAULT_TIMESTAMP_REGION_NAME; + $lifetime = $this->regionsConfig->getLifetime($name); + + $this->timestampRegion = new UpdateTimestampCache($name, clone $this->cache, $lifetime); + } + + return $this->timestampRegion; + } + + /** + * {@inheritdoc} + */ + public function createCache(EntityManagerInterface $em) + { + return new DefaultCache($em); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCollectionHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCollectionHydrator.php new file mode 100644 index 0000000..f12ccf5 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCollectionHydrator.php @@ -0,0 +1,104 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +use Doctrine\ORM\Query; +use Doctrine\ORM\PersistentCollection; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\EntityManagerInterface; + +/** + * Default hydrator cache for collections + * + * @since 2.5 + * @author Fabio B. Silva + */ +class DefaultCollectionHydrator implements CollectionHydrator +{ + /** + * @var \Doctrine\ORM\EntityManagerInterface + */ + private $em; + + /** + * @var \Doctrine\ORM\UnitOfWork + */ + private $uow; + + /** + * @var array + */ + private static $hints = [Query::HINT_CACHE_ENABLED => true]; + + /** + * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. + */ + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + $this->uow = $em->getUnitOfWork(); + } + + /** + * {@inheritdoc} + */ + public function buildCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, $collection) + { + $data = []; + + foreach ($collection as $index => $entity) { + $data[$index] = new EntityCacheKey($metadata->rootEntityName, $this->uow->getEntityIdentifier($entity)); + } + + return new CollectionCacheEntry($data); + } + + /** + * {@inheritdoc} + */ + public function loadCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, CollectionCacheEntry $entry, PersistentCollection $collection) + { + $assoc = $metadata->associationMappings[$key->association]; + /* @var $targetPersister \Doctrine\ORM\Cache\Persister\CachedPersister */ + $targetPersister = $this->uow->getEntityPersister($assoc['targetEntity']); + $targetRegion = $targetPersister->getCacheRegion(); + $list = []; + + $entityEntries = $targetRegion->getMultiple($entry); + + if ($entityEntries === null) { + return null; + } + + /* @var $entityEntries \Doctrine\ORM\Cache\EntityCacheEntry[] */ + foreach ($entityEntries as $index => $entityEntry) { + $list[$index] = $this->uow->createEntity($entityEntry->class, $entityEntry->resolveAssociationEntries($this->em), self::$hints); + } + + array_walk($list, function($entity, $index) use ($collection) { + $collection->hydrateSet($index, $entity); + }); + + $this->uow->hydrationComplete(); + + return $list; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultEntityHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultEntityHydrator.php new file mode 100644 index 0000000..62f7620 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultEntityHydrator.php @@ -0,0 +1,205 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +use Doctrine\Common\Util\ClassUtils; + +use Doctrine\ORM\Query; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Utility\IdentifierFlattener; + +/** + * Default hydrator cache for entities + * + * @since 2.5 + * @author Fabio B. Silva + */ +class DefaultEntityHydrator implements EntityHydrator +{ + /** + * @var \Doctrine\ORM\EntityManagerInterface + */ + private $em; + + /** + * @var \Doctrine\ORM\UnitOfWork + */ + private $uow; + + /** + * The IdentifierFlattener used for manipulating identifiers + * + * @var \Doctrine\ORM\Utility\IdentifierFlattener + */ + private $identifierFlattener; + + /** + * @var array + */ + private static $hints = [Query::HINT_CACHE_ENABLED => true]; + + /** + * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. + */ + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + $this->uow = $em->getUnitOfWork(); + $this->identifierFlattener = new IdentifierFlattener($em->getUnitOfWork(), $em->getMetadataFactory()); + } + + /** + * {@inheritdoc} + */ + public function buildCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, $entity) + { + $data = $this->uow->getOriginalEntityData($entity); + $data = array_merge($data, $metadata->getIdentifierValues($entity)); // why update has no identifier values ? + + if ($metadata->isVersioned) { + $data[$metadata->versionField] = $metadata->getFieldValue($entity, $metadata->versionField); + } + + foreach ($metadata->associationMappings as $name => $assoc) { + if ( ! isset($data[$name])) { + continue; + } + + if ( ! ($assoc['type'] & ClassMetadata::TO_ONE)) { + unset($data[$name]); + + continue; + } + + if ( ! isset($assoc['cache'])) { + $targetClassMetadata = $this->em->getClassMetadata($assoc['targetEntity']); + $owningAssociation = ( ! $assoc['isOwningSide']) + ? $targetClassMetadata->associationMappings[$assoc['mappedBy']] + : $assoc; + $associationIds = $this->identifierFlattener->flattenIdentifier( + $targetClassMetadata, + $targetClassMetadata->getIdentifierValues($data[$name]) + ); + + unset($data[$name]); + + foreach ($associationIds as $fieldName => $fieldValue) { + if (isset($targetClassMetadata->fieldMappings[$fieldName])) { + $fieldMapping = $targetClassMetadata->fieldMappings[$fieldName]; + + $data[$owningAssociation['targetToSourceKeyColumns'][$fieldMapping['columnName']]] = $fieldValue; + + continue; + } + + $targetAssoc = $targetClassMetadata->associationMappings[$fieldName]; + + foreach($assoc['targetToSourceKeyColumns'] as $referencedColumn => $localColumn) { + if (isset($targetAssoc['sourceToTargetKeyColumns'][$referencedColumn])) { + $data[$localColumn] = $fieldValue; + } + } + } + + continue; + } + + if ( ! isset($assoc['id'])) { + $targetClass = ClassUtils::getClass($data[$name]); + $targetId = $this->uow->getEntityIdentifier($data[$name]); + $data[$name] = new AssociationCacheEntry($targetClass, $targetId); + + continue; + } + + // handle association identifier + $targetId = is_object($data[$name]) && $this->uow->isInIdentityMap($data[$name]) + ? $this->uow->getEntityIdentifier($data[$name]) + : $data[$name]; + + // @TODO - fix it ! + // handle UnitOfWork#createEntity hash generation + if ( ! is_array($targetId)) { + $data[reset($assoc['joinColumnFieldNames'])] = $targetId; + + $targetEntity = $this->em->getClassMetadata($assoc['targetEntity']); + $targetId = [$targetEntity->identifier[0] => $targetId]; + } + + $data[$name] = new AssociationCacheEntry($assoc['targetEntity'], $targetId); + } + + return new EntityCacheEntry($metadata->name, $data); + } + + /** + * {@inheritdoc} + */ + public function loadCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, EntityCacheEntry $entry, $entity = null) + { + $data = $entry->data; + $hints = self::$hints; + + if ($entity !== null) { + $hints[Query::HINT_REFRESH] = true; + $hints[Query::HINT_REFRESH_ENTITY] = $entity; + } + + foreach ($metadata->associationMappings as $name => $assoc) { + if ( ! isset($assoc['cache']) || ! isset($data[$name])) { + continue; + } + + $assocClass = $data[$name]->class; + $assocId = $data[$name]->identifier; + $isEagerLoad = ($assoc['fetch'] === ClassMetadata::FETCH_EAGER || ($assoc['type'] === ClassMetadata::ONE_TO_ONE && ! $assoc['isOwningSide'])); + + if ( ! $isEagerLoad) { + $data[$name] = $this->em->getReference($assocClass, $assocId); + + continue; + } + + $assocMetadata = $this->em->getClassMetadata($assoc['targetEntity']); + $assocKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocId); + $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']); + $assocRegion = $assocPersister->getCacheRegion(); + $assocEntry = $assocRegion->get($assocKey); + + if ($assocEntry === null) { + return null; + } + + $data[$name] = $this->uow->createEntity($assocEntry->class, $assocEntry->resolveAssociationEntries($this->em), $hints); + } + + if ($entity !== null) { + $this->uow->registerManaged($entity, $key->identifier, $data); + } + + $result = $this->uow->createEntity($entry->class, $data, $hints); + + $this->uow->hydrationComplete(); + + return $result; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultQueryCache.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultQueryCache.php new file mode 100644 index 0000000..866ea0d --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultQueryCache.php @@ -0,0 +1,478 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\ORM\Cache\Persister\CachedPersister; +use Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Query\ResultSetMapping; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\PersistentCollection; +use Doctrine\Common\Proxy\Proxy; +use Doctrine\ORM\Cache; +use Doctrine\ORM\Query; +use function assert; + +/** + * Default query cache implementation. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class DefaultQueryCache implements QueryCache +{ + /** + * @var \Doctrine\ORM\EntityManagerInterface + */ + private $em; + + /** + * @var \Doctrine\ORM\UnitOfWork + */ + private $uow; + + /** + * @var \Doctrine\ORM\Cache\Region + */ + private $region; + + /** + * @var \Doctrine\ORM\Cache\QueryCacheValidator + */ + private $validator; + + /** + * @var \Doctrine\ORM\Cache\Logging\CacheLogger + */ + protected $cacheLogger; + + /** + * @var array + */ + private static $hints = [Query::HINT_CACHE_ENABLED => true]; + + /** + * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. + * @param \Doctrine\ORM\Cache\Region $region The query region. + */ + public function __construct(EntityManagerInterface $em, Region $region) + { + $cacheConfig = $em->getConfiguration()->getSecondLevelCacheConfiguration(); + + $this->em = $em; + $this->region = $region; + $this->uow = $em->getUnitOfWork(); + $this->cacheLogger = $cacheConfig->getCacheLogger(); + $this->validator = $cacheConfig->getQueryValidator(); + } + + /** + * {@inheritdoc} + */ + public function get(QueryCacheKey $key, ResultSetMapping $rsm, array $hints = []) + { + if ( ! ($key->cacheMode & Cache::MODE_GET)) { + return null; + } + + $cacheEntry = $this->region->get($key); + + if ( ! $cacheEntry instanceof QueryCacheEntry) { + return null; + } + + if ( ! $this->validator->isValid($key, $cacheEntry)) { + $this->region->evict($key); + + return null; + } + + $result = []; + $entityName = reset($rsm->aliasMap); + $hasRelation = ! empty($rsm->relationMap); + $persister = $this->uow->getEntityPersister($entityName); + assert($persister instanceof CachedEntityPersister); + + $region = $persister->getCacheRegion(); + $regionName = $region->getName(); + + $cm = $this->em->getClassMetadata($entityName); + + $generateKeys = static function (array $entry) use ($cm) : EntityCacheKey { + return new EntityCacheKey($cm->rootEntityName, $entry['identifier']); + }; + + $cacheKeys = new CollectionCacheEntry(array_map($generateKeys, $cacheEntry->result)); + $entries = $region->getMultiple($cacheKeys) ?? []; + + // @TODO - move to cache hydration component + foreach ($cacheEntry->result as $index => $entry) { + $entityEntry = $entries[$index] ?? null; + + if (! $entityEntry instanceof EntityCacheEntry) { + if ($this->cacheLogger !== null) { + $this->cacheLogger->entityCacheMiss($regionName, $cacheKeys->identifiers[$index]); + } + + return null; + } + + if ($this->cacheLogger !== null) { + $this->cacheLogger->entityCacheHit($regionName, $cacheKeys->identifiers[$index]); + } + + if ( ! $hasRelation) { + $result[$index] = $this->uow->createEntity($entityEntry->class, $entityEntry->resolveAssociationEntries($this->em), self::$hints); + + continue; + } + + $data = $entityEntry->data; + + foreach ($entry['associations'] as $name => $assoc) { + $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']); + assert($assocPersister instanceof CachedEntityPersister); + + $assocRegion = $assocPersister->getCacheRegion(); + $assocMetadata = $this->em->getClassMetadata($assoc['targetEntity']); + + if ($assoc['type'] & ClassMetadata::TO_ONE) { + + if (($assocEntry = $assocRegion->get($assocKey = new EntityCacheKey($assocMetadata->rootEntityName, $assoc['identifier']))) === null) { + + if ($this->cacheLogger !== null) { + $this->cacheLogger->entityCacheMiss($assocRegion->getName(), $assocKey); + } + + $this->uow->hydrationComplete(); + + return null; + } + + $data[$name] = $this->uow->createEntity($assocEntry->class, $assocEntry->resolveAssociationEntries($this->em), self::$hints); + + if ($this->cacheLogger !== null) { + $this->cacheLogger->entityCacheHit($assocRegion->getName(), $assocKey); + } + + continue; + } + + if ( ! isset($assoc['list']) || empty($assoc['list'])) { + continue; + } + + $generateKeys = function ($id) use ($assocMetadata): EntityCacheKey { + return new EntityCacheKey($assocMetadata->rootEntityName, $id); + }; + + $collection = new PersistentCollection($this->em, $assocMetadata, new ArrayCollection()); + $assocKeys = new CollectionCacheEntry(array_map($generateKeys, $assoc['list'])); + $assocEntries = $assocRegion->getMultiple($assocKeys); + + foreach ($assoc['list'] as $assocIndex => $assocId) { + $assocEntry = is_array($assocEntries) && array_key_exists($assocIndex, $assocEntries) ? $assocEntries[$assocIndex] : null; + + if ($assocEntry === null) { + if ($this->cacheLogger !== null) { + $this->cacheLogger->entityCacheMiss($assocRegion->getName(), $assocKeys->identifiers[$assocIndex]); + } + + $this->uow->hydrationComplete(); + + return null; + } + + $element = $this->uow->createEntity($assocEntry->class, $assocEntry->resolveAssociationEntries($this->em), self::$hints); + + $collection->hydrateSet($assocIndex, $element); + + if ($this->cacheLogger !== null) { + $this->cacheLogger->entityCacheHit($assocRegion->getName(), $assocKeys->identifiers[$assocIndex]); + } + } + + $data[$name] = $collection; + + $collection->setInitialized(true); + } + + foreach ($data as $fieldName => $unCachedAssociationData) { + // In some scenarios, such as EAGER+ASSOCIATION+ID+CACHE, the + // cache key information in `$cacheEntry` will not contain details + // for fields that are associations. + // + // This means that `$data` keys for some associations that may + // actually not be cached will not be converted to actual association + // data, yet they contain L2 cache AssociationCacheEntry objects. + // + // We need to unwrap those associations into proxy references, + // since we don't have actual data for them except for identifiers. + if ($unCachedAssociationData instanceof AssociationCacheEntry) { + $data[$fieldName] = $this->em->getReference( + $unCachedAssociationData->class, + $unCachedAssociationData->identifier + ); + } + } + + $result[$index] = $this->uow->createEntity($entityEntry->class, $data, self::$hints); + } + + $this->uow->hydrationComplete(); + + return $result; + } + + /** + * {@inheritdoc} + */ + public function put(QueryCacheKey $key, ResultSetMapping $rsm, $result, array $hints = []) + { + if ($rsm->scalarMappings) { + throw new CacheException("Second level cache does not support scalar results."); + } + + if (count($rsm->entityMappings) > 1) { + throw new CacheException("Second level cache does not support multiple root entities."); + } + + if ( ! $rsm->isSelect) { + throw new CacheException("Second-level cache query supports only select statements."); + } + + if (isset($hints[Query::HINT_FORCE_PARTIAL_LOAD]) && $hints[Query::HINT_FORCE_PARTIAL_LOAD]) { + throw new CacheException("Second level cache does not support partial entities."); + } + + if ( ! ($key->cacheMode & Cache::MODE_PUT)) { + return false; + } + + $data = []; + $entityName = reset($rsm->aliasMap); + $rootAlias = key($rsm->aliasMap); + $persister = $this->uow->getEntityPersister($entityName); + + if (! $persister instanceof CachedEntityPersister) { + throw CacheException::nonCacheableEntity($entityName); + } + + $region = $persister->getCacheRegion(); + + foreach ($result as $index => $entity) { + $identifier = $this->uow->getEntityIdentifier($entity); + $entityKey = new EntityCacheKey($entityName, $identifier); + + if (($key->cacheMode & Cache::MODE_REFRESH) || ! $region->contains($entityKey)) { + // Cancel put result if entity put fail + if ( ! $persister->storeEntityCache($entity, $entityKey)) { + return false; + } + } + + $data[$index]['identifier'] = $identifier; + $data[$index]['associations'] = []; + + // @TODO - move to cache hydration components + foreach ($rsm->relationMap as $alias => $name) { + $parentAlias = $rsm->parentAliasMap[$alias]; + $parentClass = $rsm->aliasMap[$parentAlias]; + $metadata = $this->em->getClassMetadata($parentClass); + $assoc = $metadata->associationMappings[$name]; + $assocValue = $this->getAssociationValue($rsm, $alias, $entity); + + if ($assocValue === null) { + continue; + } + + // root entity association + if ($rootAlias === $parentAlias) { + // Cancel put result if association put fail + if ( ($assocInfo = $this->storeAssociationCache($key, $assoc, $assocValue)) === null) { + return false; + } + + $data[$index]['associations'][$name] = $assocInfo; + + continue; + } + + // store single nested association + if ( ! is_array($assocValue)) { + // Cancel put result if association put fail + if ($this->storeAssociationCache($key, $assoc, $assocValue) === null) { + return false; + } + + continue; + } + + // store array of nested association + foreach ($assocValue as $aVal) { + // Cancel put result if association put fail + if ($this->storeAssociationCache($key, $assoc, $aVal) === null) { + return false; + } + } + } + } + + return $this->region->put($key, new QueryCacheEntry($data)); + } + + /** + * @param \Doctrine\ORM\Cache\QueryCacheKey $key + * @param array $assoc + * @param mixed $assocValue + * + * @return array|null + */ + private function storeAssociationCache(QueryCacheKey $key, array $assoc, $assocValue) + { + $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']); + $assocMetadata = $assocPersister->getClassMetadata(); + $assocRegion = $assocPersister->getCacheRegion(); + + // Handle *-to-one associations + if ($assoc['type'] & ClassMetadata::TO_ONE) { + $assocIdentifier = $this->uow->getEntityIdentifier($assocValue); + $entityKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocIdentifier); + + if ( ! $assocValue instanceof Proxy && ($key->cacheMode & Cache::MODE_REFRESH) || ! $assocRegion->contains($entityKey)) { + // Entity put fail + if ( ! $assocPersister->storeEntityCache($assocValue, $entityKey)) { + return null; + } + } + + return [ + 'targetEntity' => $assocMetadata->rootEntityName, + 'identifier' => $assocIdentifier, + 'type' => $assoc['type'] + ]; + } + + // Handle *-to-many associations + $list = []; + + foreach ($assocValue as $assocItemIndex => $assocItem) { + $assocIdentifier = $this->uow->getEntityIdentifier($assocItem); + $entityKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocIdentifier); + + if (($key->cacheMode & Cache::MODE_REFRESH) || ! $assocRegion->contains($entityKey)) { + // Entity put fail + if ( ! $assocPersister->storeEntityCache($assocItem, $entityKey)) { + return null; + } + } + + $list[$assocItemIndex] = $assocIdentifier; + } + + return [ + 'targetEntity' => $assocMetadata->rootEntityName, + 'type' => $assoc['type'], + 'list' => $list, + ]; + } + + /** + * @param \Doctrine\ORM\Query\ResultSetMapping $rsm + * @param string $assocAlias + * @param object $entity + * + * @return array|object + */ + private function getAssociationValue(ResultSetMapping $rsm, $assocAlias, $entity) + { + $path = []; + $alias = $assocAlias; + + while (isset($rsm->parentAliasMap[$alias])) { + $parent = $rsm->parentAliasMap[$alias]; + $field = $rsm->relationMap[$alias]; + $class = $rsm->aliasMap[$parent]; + + array_unshift($path, [ + 'field' => $field, + 'class' => $class + ] + ); + + $alias = $parent; + } + + return $this->getAssociationPathValue($entity, $path); + } + + /** + * @param mixed $value + * @param array $path + * + * @return array|object|null + */ + private function getAssociationPathValue($value, array $path) + { + $mapping = array_shift($path); + $metadata = $this->em->getClassMetadata($mapping['class']); + $assoc = $metadata->associationMappings[$mapping['field']]; + $value = $metadata->getFieldValue($value, $mapping['field']); + + if ($value === null) { + return null; + } + + if (empty($path)) { + return $value; + } + + // Handle *-to-one associations + if ($assoc['type'] & ClassMetadata::TO_ONE) { + return $this->getAssociationPathValue($value, $path); + } + + $values = []; + + foreach ($value as $item) { + $values[] = $this->getAssociationPathValue($item, $path); + } + + return $values; + } + + /** + * {@inheritdoc} + */ + public function clear() + { + return $this->region->evictAll(); + } + + /** + * {@inheritdoc} + */ + public function getRegion() + { + return $this->region; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheEntry.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheEntry.php new file mode 100644 index 0000000..155618b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheEntry.php @@ -0,0 +1,88 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +use Doctrine\ORM\EntityManagerInterface; + +/** + * Entity cache entry + * + * @since 2.5 + * @author Fabio B. Silva + */ +class EntityCacheEntry implements CacheEntry +{ + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var array The entity map data + */ + public $data; + + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var string The entity class name + */ + public $class; + + /** + * @param string $class The entity class. + * @param array $data The entity data. + */ + public function __construct($class, array $data) + { + $this->class = $class; + $this->data = $data; + } + + /** + * Creates a new EntityCacheEntry + * + * This method allow Doctrine\Common\Cache\PhpFileCache compatibility + * + * @param array $values array containing property values + * + * @return EntityCacheEntry + */ + public static function __set_state(array $values) + { + return new self($values['class'], $values['data']); + } + + /** + * Retrieves the entity data resolving cache entries + * + * @param \Doctrine\ORM\EntityManagerInterface $em + * + * @return array + */ + public function resolveAssociationEntries(EntityManagerInterface $em) + { + return array_map(function($value) use ($em) { + if ( ! ($value instanceof AssociationCacheEntry)) { + return $value; + } + + return $em->getReference($value->class, $value->identifier); + }, $this->data); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheKey.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheKey.php new file mode 100644 index 0000000..281e610 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheKey.php @@ -0,0 +1,57 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Defines entity classes roles to be stored in the cache region. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class EntityCacheKey extends CacheKey +{ + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var array The entity identifier + */ + public $identifier; + + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var string The entity class name + */ + public $entityClass; + + /** + * @param string $entityClass The entity class name. In a inheritance hierarchy it should always be the root entity class. + * @param array $identifier The entity identifier + */ + public function __construct($entityClass, array $identifier) + { + ksort($identifier); + + $this->identifier = $identifier; + $this->entityClass = $entityClass; + $this->hash = str_replace('\\', '.', strtolower($entityClass) . '_' . implode(' ', $identifier)); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityHydrator.php new file mode 100644 index 0000000..05a394d --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityHydrator.php @@ -0,0 +1,49 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +use Doctrine\ORM\Mapping\ClassMetadata; + +/** + * Hydrator cache entry for entities + * + * @since 2.5 + * @author Fabio B. Silva + */ +interface EntityHydrator +{ + /** + * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. + * @param \Doctrine\ORM\Cache\EntityCacheKey $key The entity cache key. + * @param object $entity The entity. + * + * @return \Doctrine\ORM\Cache\EntityCacheEntry + */ + public function buildCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, $entity); + + /** + * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. + * @param \Doctrine\ORM\Cache\EntityCacheKey $key The entity cache key. + * @param \Doctrine\ORM\Cache\EntityCacheEntry $entry The entity cache entry. + * @param object $entity The entity to load the cache into. If not specified, a new entity is created. + */ + public function loadCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, EntityCacheEntry $entry, $entity = null); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Lock.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Lock.php new file mode 100644 index 0000000..60f7d6c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Lock.php @@ -0,0 +1,58 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Cache Lock + * + * @since 2.5 + * @author Fabio B. Silva + */ +class Lock +{ + /** + * @var string + */ + public $value; + + /** + * @var integer + */ + public $time; + + /** + * @param string $value + * @param integer $time + */ + public function __construct($value, $time = null) + { + $this->value = $value; + $this->time = $time ? : time(); + } + + /** + * @return \Doctrine\ORM\Cache\Lock + */ + public static function createLockRead() + { + return new self(uniqid(time(), true)); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/LockException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/LockException.php new file mode 100644 index 0000000..d4c7624 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/LockException.php @@ -0,0 +1,32 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Lock exception for cache. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class LockException extends CacheException +{ + +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLogger.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLogger.php new file mode 100644 index 0000000..bdae4ee --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLogger.php @@ -0,0 +1,106 @@ +. + */ + +namespace Doctrine\ORM\Cache\Logging; + +use Doctrine\ORM\Cache\CollectionCacheKey; +use Doctrine\ORM\Cache\EntityCacheKey; +use Doctrine\ORM\Cache\QueryCacheKey; + +/** + * Interface for logging. + * + * @since 2.5 + * @author Fabio B. Silva + */ +interface CacheLogger +{ + /** + * Log an entity put into second level cache. + * + * @param string $regionName The name of the cache region. + * @param \Doctrine\ORM\Cache\EntityCacheKey $key The cache key of the entity. + */ + public function entityCachePut($regionName, EntityCacheKey $key); + + /** + * Log an entity get from second level cache resulted in a hit. + * + * @param string $regionName The name of the cache region. + * @param \Doctrine\ORM\Cache\EntityCacheKey $key The cache key of the entity. + */ + public function entityCacheHit($regionName, EntityCacheKey $key); + + /** + * Log an entity get from second level cache resulted in a miss. + * + * @param string $regionName The name of the cache region. + * @param \Doctrine\ORM\Cache\EntityCacheKey $key The cache key of the entity. + */ + public function entityCacheMiss($regionName, EntityCacheKey $key); + + /** + * Log an entity put into second level cache. + * + * @param string $regionName The name of the cache region. + * @param \Doctrine\ORM\Cache\CollectionCacheKey $key The cache key of the collection. + */ + public function collectionCachePut($regionName, CollectionCacheKey $key); + + /** + * Log an entity get from second level cache resulted in a hit. + * + * @param string $regionName The name of the cache region. + * @param \Doctrine\ORM\Cache\CollectionCacheKey $key The cache key of the collection. + */ + public function collectionCacheHit($regionName, CollectionCacheKey $key); + + /** + * Log an entity get from second level cache resulted in a miss. + * + * @param string $regionName The name of the cache region. + * @param \Doctrine\ORM\Cache\CollectionCacheKey $key The cache key of the collection. + */ + public function collectionCacheMiss($regionName, CollectionCacheKey $key); + + /** + * Log a query put into the query cache. + * + * @param string $regionName The name of the cache region. + * @param \Doctrine\ORM\Cache\QueryCacheKey $key The cache key of the query. + */ + public function queryCachePut($regionName, QueryCacheKey $key); + + /** + * Log a query get from the query cache resulted in a hit. + * + * @param string $regionName The name of the cache region. + * @param \Doctrine\ORM\Cache\QueryCacheKey $key The cache key of the query. + */ + public function queryCacheHit($regionName, QueryCacheKey $key); + + /** + * Log a query get from the query cache resulted in a miss. + * + * @param string $regionName The name of the cache region. + * @param \Doctrine\ORM\Cache\QueryCacheKey $key The cache key of the query. + */ + public function queryCacheMiss($regionName, QueryCacheKey $key); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLoggerChain.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLoggerChain.php new file mode 100644 index 0000000..28a8125 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLoggerChain.php @@ -0,0 +1,156 @@ +. + */ + +namespace Doctrine\ORM\Cache\Logging; + +use Doctrine\ORM\Cache\CollectionCacheKey; +use Doctrine\ORM\Cache\EntityCacheKey; +use Doctrine\ORM\Cache\QueryCacheKey; + +/** + * Cache logger chain + * + * @since 2.5 + * @author Fabio B. Silva + */ +class CacheLoggerChain implements CacheLogger +{ + /** + * @var array<\Doctrine\ORM\Cache\Logging\CacheLogger> + */ + private $loggers = []; + + /** + * @param string $name + * @param \Doctrine\ORM\Cache\Logging\CacheLogger $logger + */ + public function setLogger($name, CacheLogger $logger) + { + $this->loggers[$name] = $logger; + } + + /** + * @param string $name + * + * @return \Doctrine\ORM\Cache\Logging\CacheLogger|null + */ + public function getLogger($name) + { + return isset($this->loggers[$name]) ? $this->loggers[$name] : null; + } + + /** + * @return array<\Doctrine\ORM\Cache\Logging\CacheLogger> + */ + public function getLoggers() + { + return $this->loggers; + } + + /** + * {@inheritdoc} + */ + public function collectionCacheHit($regionName, CollectionCacheKey $key) + { + foreach ($this->loggers as $logger) { + $logger->collectionCacheHit($regionName, $key); + } + } + + /** + * {@inheritdoc} + */ + public function collectionCacheMiss($regionName, CollectionCacheKey $key) + { + foreach ($this->loggers as $logger) { + $logger->collectionCacheMiss($regionName, $key); + } + } + + /** + * {@inheritdoc} + */ + public function collectionCachePut($regionName, CollectionCacheKey $key) + { + foreach ($this->loggers as $logger) { + $logger->collectionCachePut($regionName, $key); + } + } + + /** + * {@inheritdoc} + */ + public function entityCacheHit($regionName, EntityCacheKey $key) + { + foreach ($this->loggers as $logger) { + $logger->entityCacheHit($regionName, $key); + } + } + + /** + * {@inheritdoc} + */ + public function entityCacheMiss($regionName, EntityCacheKey $key) + { + foreach ($this->loggers as $logger) { + $logger->entityCacheMiss($regionName, $key); + } + } + + /** + * {@inheritdoc} + */ + public function entityCachePut($regionName, EntityCacheKey $key) + { + foreach ($this->loggers as $logger) { + $logger->entityCachePut($regionName, $key); + } + } + + /** + * {@inheritdoc} + */ + public function queryCacheHit($regionName, QueryCacheKey $key) + { + foreach ($this->loggers as $logger) { + $logger->queryCacheHit($regionName, $key); + } + } + + /** + * {@inheritdoc} + */ + public function queryCacheMiss($regionName, QueryCacheKey $key) + { + foreach ($this->loggers as $logger) { + $logger->queryCacheMiss($regionName, $key); + } + } + + /** + * {@inheritdoc} + */ + public function queryCachePut($regionName, QueryCacheKey $key) + { + foreach ($this->loggers as $logger) { + $logger->queryCachePut($regionName, $key); + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/StatisticsCacheLogger.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/StatisticsCacheLogger.php new file mode 100644 index 0000000..122e353 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/StatisticsCacheLogger.php @@ -0,0 +1,251 @@ +. + */ + +namespace Doctrine\ORM\Cache\Logging; + +use Doctrine\ORM\Cache\CollectionCacheKey; +use Doctrine\ORM\Cache\EntityCacheKey; +use Doctrine\ORM\Cache\QueryCacheKey; + +/** + * Provide basic second level cache statistics. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class StatisticsCacheLogger implements CacheLogger +{ + /** + * @var array + */ + private $cacheMissCountMap = []; + + /** + * @var array + */ + private $cacheHitCountMap = []; + + /** + * @var array + */ + private $cachePutCountMap = []; + + /** + * {@inheritdoc} + */ + public function collectionCacheMiss($regionName, CollectionCacheKey $key) + { + $this->cacheMissCountMap[$regionName] = isset($this->cacheMissCountMap[$regionName]) + ? $this->cacheMissCountMap[$regionName] + 1 + : 1; + } + + /** + * {@inheritdoc} + */ + public function collectionCacheHit($regionName, CollectionCacheKey $key) + { + $this->cacheHitCountMap[$regionName] = isset($this->cacheHitCountMap[$regionName]) + ? $this->cacheHitCountMap[$regionName] + 1 + : 1; + } + + /** + * {@inheritdoc} + */ + public function collectionCachePut($regionName, CollectionCacheKey $key) + { + $this->cachePutCountMap[$regionName] = isset($this->cachePutCountMap[$regionName]) + ? $this->cachePutCountMap[$regionName] + 1 + : 1; + } + + /** + * {@inheritdoc} + */ + public function entityCacheMiss($regionName, EntityCacheKey $key) + { + $this->cacheMissCountMap[$regionName] = isset($this->cacheMissCountMap[$regionName]) + ? $this->cacheMissCountMap[$regionName] + 1 + : 1; + } + + /** + * {@inheritdoc} + */ + public function entityCacheHit($regionName, EntityCacheKey $key) + { + $this->cacheHitCountMap[$regionName] = isset($this->cacheHitCountMap[$regionName]) + ? $this->cacheHitCountMap[$regionName] + 1 + : 1; + } + + /** + * {@inheritdoc} + */ + public function entityCachePut($regionName, EntityCacheKey $key) + { + $this->cachePutCountMap[$regionName] = isset($this->cachePutCountMap[$regionName]) + ? $this->cachePutCountMap[$regionName] + 1 + : 1; + } + + /** + * {@inheritdoc} + */ + public function queryCacheHit($regionName, QueryCacheKey $key) + { + $this->cacheHitCountMap[$regionName] = isset($this->cacheHitCountMap[$regionName]) + ? $this->cacheHitCountMap[$regionName] + 1 + : 1; + } + + /** + * {@inheritdoc} + */ + public function queryCacheMiss($regionName, QueryCacheKey $key) + { + $this->cacheMissCountMap[$regionName] = isset($this->cacheMissCountMap[$regionName]) + ? $this->cacheMissCountMap[$regionName] + 1 + : 1; + } + + /** + * {@inheritdoc} + */ + public function queryCachePut($regionName, QueryCacheKey $key) + { + $this->cachePutCountMap[$regionName] = isset($this->cachePutCountMap[$regionName]) + ? $this->cachePutCountMap[$regionName] + 1 + : 1; + } + + /** + * Get the number of entries successfully retrieved from cache. + * + * @param string $regionName The name of the cache region. + * + * @return integer + */ + public function getRegionHitCount($regionName) + { + return isset($this->cacheHitCountMap[$regionName]) ? $this->cacheHitCountMap[$regionName] : 0; + } + + /** + * Get the number of cached entries *not* found in cache. + * + * @param string $regionName The name of the cache region. + * + * @return integer + */ + public function getRegionMissCount($regionName) + { + return isset($this->cacheMissCountMap[$regionName]) ? $this->cacheMissCountMap[$regionName] : 0; + } + + /** + * Get the number of cacheable entries put in cache. + * + * @param string $regionName The name of the cache region. + * + * @return integer + */ + public function getRegionPutCount($regionName) + { + return isset($this->cachePutCountMap[$regionName]) ? $this->cachePutCountMap[$regionName] : 0; + } + + /** + * @return array + */ + public function getRegionsMiss() + { + return $this->cacheMissCountMap; + } + + /** + * @return array + */ + public function getRegionsHit() + { + return $this->cacheHitCountMap; + } + + /** + * @return array + */ + public function getRegionsPut() + { + return $this->cachePutCountMap; + } + + /** + * Clear region statistics + * + * @param string $regionName The name of the cache region. + */ + public function clearRegionStats($regionName) + { + $this->cachePutCountMap[$regionName] = 0; + $this->cacheHitCountMap[$regionName] = 0; + $this->cacheMissCountMap[$regionName] = 0; + } + + /** + * Clear all statistics + */ + public function clearStats() + { + $this->cachePutCountMap = []; + $this->cacheHitCountMap = []; + $this->cacheMissCountMap = []; + } + + /** + * Get the total number of put in cache. + * + * @return integer + */ + public function getPutCount() + { + return array_sum($this->cachePutCountMap); + } + + /** + * Get the total number of entries successfully retrieved from cache. + * + * @return integer + */ + public function getHitCount() + { + return array_sum($this->cacheHitCountMap); + } + + /** + * Get the total number of cached entries *not* found in cache. + * + * @return integer + */ + public function getMissCount() + { + return array_sum($this->cacheMissCountMap); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/MultiGetRegion.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/MultiGetRegion.php new file mode 100644 index 0000000..be32b08 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/MultiGetRegion.php @@ -0,0 +1,42 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Defines a region that supports multi-get reading. + * + * With one method call we can get multiple items. + * + * @since 2.5 + * @author Asmir Mustafic + */ +interface MultiGetRegion +{ + /** + * Get all items from the cache identified by $keys. + * It returns NULL if some elements can not be found. + * + * @param CollectionCacheEntry $collection The collection of the items to be retrieved. + * + * @return CacheEntry[]|null The cached entries or NULL if one or more entries can not be found + */ + public function getMultiple(CollectionCacheEntry $collection); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/CachedPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/CachedPersister.php new file mode 100644 index 0000000..89afd32 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/CachedPersister.php @@ -0,0 +1,46 @@ +. + */ + +namespace Doctrine\ORM\Cache\Persister; + +/** + * Interface for persister that support second level cache. + * + * @since 2.5 + * @author Fabio B. Silva + */ +interface CachedPersister +{ + /** + * Perform whatever processing is encapsulated here after completion of the transaction. + */ + public function afterTransactionComplete(); + + /** + * Perform whatever processing is encapsulated here after completion of the rolled-back. + */ + public function afterTransactionRolledBack(); + + /** + * Gets the The region access. + * + * @return \Doctrine\ORM\Cache\Region + */ + public function getCacheRegion(); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/AbstractCollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/AbstractCollectionPersister.php new file mode 100644 index 0000000..7a10d17 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/AbstractCollectionPersister.php @@ -0,0 +1,313 @@ +. + */ + +namespace Doctrine\ORM\Cache\Persister\Collection; + +use Doctrine\Common\Collections\Criteria; +use Doctrine\ORM\Cache\EntityCacheKey; +use Doctrine\ORM\Cache\CollectionCacheKey; +use Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister; +use Doctrine\ORM\Persisters\Collection\CollectionPersister; +use Doctrine\ORM\PersistentCollection; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Cache\Region; +use Doctrine\Common\Util\ClassUtils; + +/** + * @author Fabio B. Silva + * @author Guilherme Blanco + * @since 2.5 + */ +abstract class AbstractCollectionPersister implements CachedCollectionPersister +{ + /** + * @var \Doctrine\ORM\UnitOfWork + */ + protected $uow; + + /** + * @var \Doctrine\ORM\Mapping\ClassMetadataFactory + */ + protected $metadataFactory; + + /** + * @var \Doctrine\ORM\Persisters\Collection\CollectionPersister + */ + protected $persister; + + /** + * @var \Doctrine\ORM\Mapping\ClassMetadata + */ + protected $sourceEntity; + + /** + * @var \Doctrine\ORM\Mapping\ClassMetadata + */ + protected $targetEntity; + + /** + * @var array + */ + protected $association; + + /** + * @var array + */ + protected $queuedCache = []; + + /** + * @var \Doctrine\ORM\Cache\Region + */ + protected $region; + + /** + * @var string + */ + protected $regionName; + + /** + * @var \Doctrine\ORM\Cache\CollectionHydrator + */ + protected $hydrator; + + /** + * @var \Doctrine\ORM\Cache\Logging\CacheLogger + */ + protected $cacheLogger; + + /** + * @param \Doctrine\ORM\Persisters\Collection\CollectionPersister $persister The collection persister that will be cached. + * @param \Doctrine\ORM\Cache\Region $region The collection region. + * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. + * @param array $association The association mapping. + */ + public function __construct(CollectionPersister $persister, Region $region, EntityManagerInterface $em, array $association) + { + $configuration = $em->getConfiguration(); + $cacheConfig = $configuration->getSecondLevelCacheConfiguration(); + $cacheFactory = $cacheConfig->getCacheFactory(); + + $this->region = $region; + $this->persister = $persister; + $this->association = $association; + $this->regionName = $region->getName(); + $this->uow = $em->getUnitOfWork(); + $this->metadataFactory = $em->getMetadataFactory(); + $this->cacheLogger = $cacheConfig->getCacheLogger(); + $this->hydrator = $cacheFactory->buildCollectionHydrator($em, $association); + $this->sourceEntity = $em->getClassMetadata($association['sourceEntity']); + $this->targetEntity = $em->getClassMetadata($association['targetEntity']); + } + + /** + * {@inheritdoc} + */ + public function getCacheRegion() + { + return $this->region; + } + + /** + * {@inheritdoc} + */ + public function getSourceEntityMetadata() + { + return $this->sourceEntity; + } + + /** + * {@inheritdoc} + */ + public function getTargetEntityMetadata() + { + return $this->targetEntity; + } + + /** + * @param \Doctrine\ORM\PersistentCollection $collection + * @param \Doctrine\ORM\Cache\CollectionCacheKey $key + * + * @return \Doctrine\ORM\PersistentCollection|null + */ + public function loadCollectionCache(PersistentCollection $collection, CollectionCacheKey $key) + { + if (($cache = $this->region->get($key)) === null) { + return null; + } + + if (($cache = $this->hydrator->loadCacheEntry($this->sourceEntity, $key, $cache, $collection)) === null) { + return null; + } + + return $cache; + } + + /** + * {@inheritdoc} + */ + public function storeCollectionCache(CollectionCacheKey $key, $elements) + { + /* @var $targetPersister CachedEntityPersister */ + $associationMapping = $this->sourceEntity->associationMappings[$key->association]; + $targetPersister = $this->uow->getEntityPersister($this->targetEntity->rootEntityName); + $targetRegion = $targetPersister->getCacheRegion(); + $targetHydrator = $targetPersister->getEntityHydrator(); + + // Only preserve ordering if association configured it + if ( ! (isset($associationMapping['indexBy']) && $associationMapping['indexBy'])) { + // Elements may be an array or a Collection + $elements = array_values(is_array($elements) ? $elements : $elements->getValues()); + } + + $entry = $this->hydrator->buildCacheEntry($this->targetEntity, $key, $elements); + + foreach ($entry->identifiers as $index => $entityKey) { + if ($targetRegion->contains($entityKey)) { + continue; + } + + $class = $this->targetEntity; + $className = ClassUtils::getClass($elements[$index]); + + if ($className !== $this->targetEntity->name) { + $class = $this->metadataFactory->getMetadataFor($className); + } + + $entity = $elements[$index]; + $entityEntry = $targetHydrator->buildCacheEntry($class, $entityKey, $entity); + + $targetRegion->put($entityKey, $entityEntry); + } + + $cached = $this->region->put($key, $entry); + + if ($this->cacheLogger && $cached) { + $this->cacheLogger->collectionCachePut($this->regionName, $key); + } + } + + /** + * {@inheritdoc} + */ + public function contains(PersistentCollection $collection, $element) + { + return $this->persister->contains($collection, $element); + } + + /** + * {@inheritdoc} + */ + public function containsKey(PersistentCollection $collection, $key) + { + return $this->persister->containsKey($collection, $key); + } + + /** + * {@inheritdoc} + */ + public function count(PersistentCollection $collection) + { + $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); + $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId); + $entry = $this->region->get($key); + + if ($entry !== null) { + return count($entry->identifiers); + } + + return $this->persister->count($collection); + } + + /** + * {@inheritdoc} + */ + public function get(PersistentCollection $collection, $index) + { + return $this->persister->get($collection, $index); + } + + /** + * {@inheritdoc} + */ + public function removeElement(PersistentCollection $collection, $element) + { + if ($persisterResult = $this->persister->removeElement($collection, $element)) { + $this->evictCollectionCache($collection); + $this->evictElementCache($this->sourceEntity->rootEntityName, $collection->getOwner()); + $this->evictElementCache($this->targetEntity->rootEntityName, $element); + } + + return $persisterResult; + } + + /** + * {@inheritdoc} + */ + public function slice(PersistentCollection $collection, $offset, $length = null) + { + return $this->persister->slice($collection, $offset, $length); + } + + /** + * {@inheritDoc} + */ + public function loadCriteria(PersistentCollection $collection, Criteria $criteria) + { + return $this->persister->loadCriteria($collection, $criteria); + } + + /** + * Clears cache entries related to the current collection + * + * @param PersistentCollection $collection + */ + protected function evictCollectionCache(PersistentCollection $collection) + { + $key = new CollectionCacheKey( + $this->sourceEntity->rootEntityName, + $this->association['fieldName'], + $this->uow->getEntityIdentifier($collection->getOwner()) + ); + + $this->region->evict($key); + + if ($this->cacheLogger) { + $this->cacheLogger->collectionCachePut($this->regionName, $key); + } + } + + /** + * @param string $targetEntity + * @param object $element + */ + protected function evictElementCache($targetEntity, $element) + { + /* @var $targetPersister CachedEntityPersister */ + $targetPersister = $this->uow->getEntityPersister($targetEntity); + $targetRegion = $targetPersister->getCacheRegion(); + $key = new EntityCacheKey($targetEntity, $this->uow->getEntityIdentifier($element)); + + $targetRegion->evict($key); + + if ($this->cacheLogger) { + $this->cacheLogger->entityCachePut($targetRegion->getName(), $key); + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/CachedCollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/CachedCollectionPersister.php new file mode 100644 index 0000000..5722027 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/CachedCollectionPersister.php @@ -0,0 +1,65 @@ +. + */ + +namespace Doctrine\ORM\Cache\Persister\Collection; + +use Doctrine\ORM\Cache\CollectionCacheKey; +use Doctrine\ORM\Cache\Persister\CachedPersister; +use Doctrine\ORM\Persisters\Collection\CollectionPersister; +use Doctrine\ORM\PersistentCollection; + +/** + * Interface for second level cache collection persisters. + * + * @author Fabio B. Silva + * @since 2.5 + */ +interface CachedCollectionPersister extends CachedPersister, CollectionPersister +{ + /** + * @return \Doctrine\ORM\Mapping\ClassMetadata + */ + public function getSourceEntityMetadata(); + + /** + * @return \Doctrine\ORM\Mapping\ClassMetadata + */ + public function getTargetEntityMetadata(); + + /** + * Loads a collection from cache + * + * @param \Doctrine\ORM\PersistentCollection $collection + * @param \Doctrine\ORM\Cache\CollectionCacheKey $key + * + * @return \Doctrine\ORM\PersistentCollection|null + */ + public function loadCollectionCache(PersistentCollection $collection, CollectionCacheKey $key); + + /** + * Stores a collection into cache + * + * @param \Doctrine\ORM\Cache\CollectionCacheKey $key + * @param array|\Doctrine\Common\Collections\Collection $elements + * + * @return void + */ + public function storeCollectionCache(CollectionCacheKey $key, $elements); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/NonStrictReadWriteCachedCollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/NonStrictReadWriteCachedCollectionPersister.php new file mode 100644 index 0000000..fbd46f6 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/NonStrictReadWriteCachedCollectionPersister.php @@ -0,0 +1,104 @@ +. + */ + +namespace Doctrine\ORM\Cache\Persister\Collection; + +use Doctrine\ORM\Cache\CollectionCacheKey; +use Doctrine\ORM\PersistentCollection; + +/** + * @author Fabio B. Silva + * @since 2.5 + */ +class NonStrictReadWriteCachedCollectionPersister extends AbstractCollectionPersister +{ + /** + * {@inheritdoc} + */ + public function afterTransactionComplete() + { + if (isset($this->queuedCache['update'])) { + foreach ($this->queuedCache['update'] as $item) { + $this->storeCollectionCache($item['key'], $item['list']); + } + } + + if (isset($this->queuedCache['delete'])) { + foreach ($this->queuedCache['delete'] as $key) { + $this->region->evict($key); + } + } + + $this->queuedCache = []; + } + + /** + * {@inheritdoc} + */ + public function afterTransactionRolledBack() + { + $this->queuedCache = []; + } + + /** + * {@inheritdoc} + */ + public function delete(PersistentCollection $collection) + { + $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); + $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId); + + $this->persister->delete($collection); + + $this->queuedCache['delete'][spl_object_hash($collection)] = $key; + } + + /** + * {@inheritdoc} + */ + public function update(PersistentCollection $collection) + { + $isInitialized = $collection->isInitialized(); + $isDirty = $collection->isDirty(); + + if ( ! $isInitialized && ! $isDirty) { + return; + } + + $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); + $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId); + + // Invalidate non initialized collections OR ordered collection + if ($isDirty && ! $isInitialized || isset($this->association['orderBy'])) { + $this->persister->update($collection); + + $this->queuedCache['delete'][spl_object_hash($collection)] = $key; + + return; + } + + $this->persister->update($collection); + + $this->queuedCache['update'][spl_object_hash($collection)] = [ + 'key' => $key, + 'list' => $collection + ]; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php new file mode 100644 index 0000000..dfc816c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php @@ -0,0 +1,44 @@ +. + */ + +namespace Doctrine\ORM\Cache\Persister\Collection; + +use Doctrine\ORM\PersistentCollection; +use Doctrine\ORM\Cache\CacheException; +use Doctrine\Common\Util\ClassUtils; + +/** + * @author Fabio B. Silva + * @since 2.5 + */ +class ReadOnlyCachedCollectionPersister extends NonStrictReadWriteCachedCollectionPersister +{ + /** + * {@inheritdoc} + */ + public function update(PersistentCollection $collection) + { + if ($collection->isDirty() && $collection->getSnapshot()) { + throw CacheException::updateReadOnlyCollection(ClassUtils::getClass($collection->getOwner()), $this->association['fieldName']); + } + + parent::update($collection); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php new file mode 100644 index 0000000..74bb044 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php @@ -0,0 +1,134 @@ +. + */ + +namespace Doctrine\ORM\Cache\Persister\Collection; + +use Doctrine\ORM\Persisters\Collection\CollectionPersister; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Cache\CollectionCacheKey; +use Doctrine\ORM\Cache\ConcurrentRegion; +use Doctrine\ORM\PersistentCollection; + +/** + * @author Fabio B. Silva + * @since 2.5 + */ +class ReadWriteCachedCollectionPersister extends AbstractCollectionPersister +{ + /** + * @param \Doctrine\ORM\Persisters\Collection\CollectionPersister $persister The collection persister that will be cached. + * @param \Doctrine\ORM\Cache\ConcurrentRegion $region The collection region. + * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. + * @param array $association The association mapping. + */ + public function __construct(CollectionPersister $persister, ConcurrentRegion $region, EntityManagerInterface $em, array $association) + { + parent::__construct($persister, $region, $em, $association); + } + + /** + * {@inheritdoc} + */ + public function afterTransactionComplete() + { + if (isset($this->queuedCache['update'])) { + foreach ($this->queuedCache['update'] as $item) { + $this->region->evict($item['key']); + } + } + + if (isset($this->queuedCache['delete'])) { + foreach ($this->queuedCache['delete'] as $item) { + $this->region->evict($item['key']); + } + } + + $this->queuedCache = []; + } + + /** + * {@inheritdoc} + */ + public function afterTransactionRolledBack() + { + if (isset($this->queuedCache['update'])) { + foreach ($this->queuedCache['update'] as $item) { + $this->region->evict($item['key']); + } + } + + if (isset($this->queuedCache['delete'])) { + foreach ($this->queuedCache['delete'] as $item) { + $this->region->evict($item['key']); + } + } + + $this->queuedCache = []; + } + + /** + * {@inheritdoc} + */ + public function delete(PersistentCollection $collection) + { + $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); + $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId); + $lock = $this->region->lock($key); + + $this->persister->delete($collection); + + if ($lock === null) { + return; + } + + $this->queuedCache['delete'][spl_object_hash($collection)] = [ + 'key' => $key, + 'lock' => $lock + ]; + } + + /** + * {@inheritdoc} + */ + public function update(PersistentCollection $collection) + { + $isInitialized = $collection->isInitialized(); + $isDirty = $collection->isDirty(); + + if ( ! $isInitialized && ! $isDirty) { + return; + } + + $this->persister->update($collection); + + $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); + $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId); + $lock = $this->region->lock($key); + + if ($lock === null) { + return; + } + + $this->queuedCache['update'][spl_object_hash($collection)] = [ + 'key' => $key, + 'lock' => $lock + ]; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/AbstractEntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/AbstractEntityPersister.php new file mode 100644 index 0000000..0548412 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/AbstractEntityPersister.php @@ -0,0 +1,652 @@ +. + */ + +namespace Doctrine\ORM\Cache\Persister\Entity; + +use Doctrine\ORM\Cache; +use Doctrine\ORM\Cache\Region; +use Doctrine\ORM\Cache\EntityCacheKey; +use Doctrine\ORM\Cache\CollectionCacheKey; +use Doctrine\ORM\Cache\TimestampCacheKey; +use Doctrine\ORM\Cache\QueryCacheKey; +use Doctrine\ORM\Cache\Persister\CachedPersister; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\PersistentCollection; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Persisters\Entity\EntityPersister; + +use Doctrine\Common\Util\ClassUtils; +use Doctrine\Common\Collections\Criteria; + +/** + * @author Fabio B. Silva + * @since 2.5 + */ +abstract class AbstractEntityPersister implements CachedEntityPersister +{ + /** + * @var \Doctrine\ORM\UnitOfWork + */ + protected $uow; + + /** + * @var \Doctrine\ORM\Mapping\ClassMetadataFactory + */ + protected $metadataFactory; + + /** + * @var \Doctrine\ORM\Persisters\Entity\EntityPersister + */ + protected $persister; + + /** + * @var \Doctrine\ORM\Mapping\ClassMetadata + */ + protected $class; + + /** + * @var array + */ + protected $queuedCache = []; + + /** + * @var \Doctrine\ORM\Cache\Region + */ + protected $region; + + /** + * @var \Doctrine\ORM\Cache\TimestampRegion + */ + protected $timestampRegion; + + /** + * @var \Doctrine\ORM\Cache\TimestampCacheKey + */ + protected $timestampKey; + + /** + * @var \Doctrine\ORM\Cache\EntityHydrator + */ + protected $hydrator; + + /** + * @var \Doctrine\ORM\Cache + */ + protected $cache; + + /** + * @var \Doctrine\ORM\Cache\Logging\CacheLogger + */ + protected $cacheLogger; + + /** + * @var string + */ + protected $regionName; + + /** + * Associations configured as FETCH_EAGER, as well as all inverse one-to-one associations. + * + * @var array|null + */ + protected $joinedAssociations; + + /** + * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $persister The entity persister to cache. + * @param \Doctrine\ORM\Cache\Region $region The entity cache region. + * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. + * @param \Doctrine\ORM\Mapping\ClassMetadata $class The entity metadata. + */ + public function __construct(EntityPersister $persister, Region $region, EntityManagerInterface $em, ClassMetadata $class) + { + $configuration = $em->getConfiguration(); + $cacheConfig = $configuration->getSecondLevelCacheConfiguration(); + $cacheFactory = $cacheConfig->getCacheFactory(); + + $this->class = $class; + $this->region = $region; + $this->persister = $persister; + $this->cache = $em->getCache(); + $this->regionName = $region->getName(); + $this->uow = $em->getUnitOfWork(); + $this->metadataFactory = $em->getMetadataFactory(); + $this->cacheLogger = $cacheConfig->getCacheLogger(); + $this->timestampRegion = $cacheFactory->getTimestampRegion(); + $this->hydrator = $cacheFactory->buildEntityHydrator($em, $class); + $this->timestampKey = new TimestampCacheKey($this->class->rootEntityName); + } + + /** + * {@inheritdoc} + */ + public function addInsert($entity) + { + $this->persister->addInsert($entity); + } + + /** + * {@inheritdoc} + */ + public function getInserts() + { + return $this->persister->getInserts(); + } + + /** + * {@inheritdoc} + */ + public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, array $orderBy = null) + { + return $this->persister->getSelectSQL($criteria, $assoc, $lockMode, $limit, $offset, $orderBy); + } + + /** + * {@inheritDoc} + */ + public function getCountSQL($criteria = []) + { + return $this->persister->getCountSQL($criteria); + } + + /** + * {@inheritdoc} + */ + public function getInsertSQL() + { + return $this->persister->getInsertSQL(); + } + + /** + * {@inheritdoc} + */ + public function getResultSetMapping() + { + return $this->persister->getResultSetMapping(); + } + + /** + * {@inheritdoc} + */ + public function getSelectConditionStatementSQL($field, $value, $assoc = null, $comparison = null) + { + return $this->persister->getSelectConditionStatementSQL($field, $value, $assoc, $comparison); + } + + /** + * {@inheritdoc} + */ + public function exists($entity, Criteria $extraConditions = null) + { + if (null === $extraConditions) { + $key = new EntityCacheKey($this->class->rootEntityName, $this->class->getIdentifierValues($entity)); + + if ($this->region->contains($key)) { + return true; + } + } + + return $this->persister->exists($entity, $extraConditions); + } + + /** + * {@inheritdoc} + */ + public function getCacheRegion() + { + return $this->region; + } + + /** + * @return \Doctrine\ORM\Cache\EntityHydrator + */ + public function getEntityHydrator() + { + return $this->hydrator; + } + + /** + * {@inheritdoc} + */ + public function storeEntityCache($entity, EntityCacheKey $key) + { + $class = $this->class; + $className = ClassUtils::getClass($entity); + + if ($className !== $this->class->name) { + $class = $this->metadataFactory->getMetadataFor($className); + } + + $entry = $this->hydrator->buildCacheEntry($class, $key, $entity); + $cached = $this->region->put($key, $entry); + + if ($this->cacheLogger && $cached) { + $this->cacheLogger->entityCachePut($this->regionName, $key); + } + + return $cached; + } + + /** + * @param object $entity + */ + private function storeJoinedAssociations($entity) + { + if ($this->joinedAssociations === null) { + $associations = []; + + foreach ($this->class->associationMappings as $name => $assoc) { + if (isset($assoc['cache']) && + ($assoc['type'] & ClassMetadata::TO_ONE) && + ($assoc['fetch'] === ClassMetadata::FETCH_EAGER || ! $assoc['isOwningSide'])) { + + $associations[] = $name; + } + } + + $this->joinedAssociations = $associations; + } + + foreach ($this->joinedAssociations as $name) { + $assoc = $this->class->associationMappings[$name]; + $assocEntity = $this->class->getFieldValue($entity, $name); + + if ($assocEntity === null) { + continue; + } + + $assocId = $this->uow->getEntityIdentifier($assocEntity); + $assocMetadata = $this->metadataFactory->getMetadataFor($assoc['targetEntity']); + $assocKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocId); + $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']); + + $assocPersister->storeEntityCache($assocEntity, $assocKey); + } + } + + /** + * Generates a string of currently query + * + * @param array $query + * @param string $criteria + * @param array $orderBy + * @param integer $limit + * @param integer $offset + * + * @return string + */ + protected function getHash($query, $criteria, array $orderBy = null, $limit = null, $offset = null) + { + list($params) = ($criteria instanceof Criteria) + ? $this->persister->expandCriteriaParameters($criteria) + : $this->persister->expandParameters($criteria); + + return sha1($query . serialize($params) . serialize($orderBy) . $limit . $offset); + } + + /** + * {@inheritdoc} + */ + public function expandParameters($criteria) + { + return $this->persister->expandParameters($criteria); + } + + /** + * {@inheritdoc} + */ + public function expandCriteriaParameters(Criteria $criteria) + { + return $this->persister->expandCriteriaParameters($criteria); + } + + /** + * {@inheritdoc} + */ + public function getClassMetadata() + { + return $this->persister->getClassMetadata(); + } + + /** + * {@inheritdoc} + */ + public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null) + { + return $this->persister->getManyToManyCollection($assoc, $sourceEntity, $offset, $limit); + } + + /** + * {@inheritdoc} + */ + public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null) + { + return $this->persister->getOneToManyCollection($assoc, $sourceEntity, $offset, $limit); + } + + /** + * {@inheritdoc} + */ + public function getOwningTable($fieldName) + { + return $this->persister->getOwningTable($fieldName); + } + + /** + * {@inheritdoc} + */ + public function executeInserts() + { + $this->queuedCache['insert'] = $this->persister->getInserts(); + + return $this->persister->executeInserts(); + } + + /** + * {@inheritdoc} + */ + public function load(array $criteria, $entity = null, $assoc = null, array $hints = [], $lockMode = null, $limit = null, array $orderBy = null) + { + if ($entity !== null || $assoc !== null || ! empty($hints) || $lockMode !== null) { + return $this->persister->load($criteria, $entity, $assoc, $hints, $lockMode, $limit, $orderBy); + } + + //handle only EntityRepository#findOneBy + $query = $this->persister->getSelectSQL($criteria, null, null, $limit, null, $orderBy); + $hash = $this->getHash($query, $criteria, null, null, null); + $rsm = $this->getResultSetMapping(); + $queryKey = new QueryCacheKey($hash, 0, Cache::MODE_NORMAL, $this->timestampKey); + $queryCache = $this->cache->getQueryCache($this->regionName); + $result = $queryCache->get($queryKey, $rsm); + + if ($result !== null) { + if ($this->cacheLogger) { + $this->cacheLogger->queryCacheHit($this->regionName, $queryKey); + } + + return $result[0]; + } + + if (($result = $this->persister->load($criteria, $entity, $assoc, $hints, $lockMode, $limit, $orderBy)) === null) { + return null; + } + + $cached = $queryCache->put($queryKey, $rsm, [$result]); + + if ($this->cacheLogger) { + if ($result) { + $this->cacheLogger->queryCacheMiss($this->regionName, $queryKey); + } + + if ($cached) { + $this->cacheLogger->queryCachePut($this->regionName, $queryKey); + } + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function loadAll(array $criteria = [], array $orderBy = null, $limit = null, $offset = null) + { + $query = $this->persister->getSelectSQL($criteria, null, null, $limit, $offset, $orderBy); + $hash = $this->getHash($query, $criteria, null, null, null); + $rsm = $this->getResultSetMapping(); + $queryKey = new QueryCacheKey($hash, 0, Cache::MODE_NORMAL, $this->timestampKey); + $queryCache = $this->cache->getQueryCache($this->regionName); + $result = $queryCache->get($queryKey, $rsm); + + if ($result !== null) { + if ($this->cacheLogger) { + $this->cacheLogger->queryCacheHit($this->regionName, $queryKey); + } + + return $result; + } + + $result = $this->persister->loadAll($criteria, $orderBy, $limit, $offset); + $cached = $queryCache->put($queryKey, $rsm, $result); + + if ($this->cacheLogger) { + if ($result) { + $this->cacheLogger->queryCacheMiss($this->regionName, $queryKey); + } + + if ($cached) { + $this->cacheLogger->queryCachePut($this->regionName, $queryKey); + } + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function loadById(array $identifier, $entity = null) + { + $cacheKey = new EntityCacheKey($this->class->rootEntityName, $identifier); + $cacheEntry = $this->region->get($cacheKey); + $class = $this->class; + + if ($cacheEntry !== null) { + if ($cacheEntry->class !== $this->class->name) { + $class = $this->metadataFactory->getMetadataFor($cacheEntry->class); + } + + $cachedEntity = $this->hydrator->loadCacheEntry($class, $cacheKey, $cacheEntry, $entity); + + if ($cachedEntity !== null) { + if ($this->cacheLogger) { + $this->cacheLogger->entityCacheHit($this->regionName, $cacheKey); + } + + return $cachedEntity; + } + } + + $entity = $this->persister->loadById($identifier, $entity); + + if ($entity === null) { + return null; + } + + $class = $this->class; + $className = ClassUtils::getClass($entity); + + if ($className !== $this->class->name) { + $class = $this->metadataFactory->getMetadataFor($className); + } + + $cacheEntry = $this->hydrator->buildCacheEntry($class, $cacheKey, $entity); + $cached = $this->region->put($cacheKey, $cacheEntry); + + if ($cached && (null === $this->joinedAssociations || $this->joinedAssociations)) { + $this->storeJoinedAssociations($entity); + } + + if ($this->cacheLogger) { + if ($cached) { + $this->cacheLogger->entityCachePut($this->regionName, $cacheKey); + } + + $this->cacheLogger->entityCacheMiss($this->regionName, $cacheKey); + } + + return $entity; + } + + /** + * {@inheritDoc} + */ + public function count($criteria = []) + { + return $this->persister->count($criteria); + } + + /** + * {@inheritdoc} + */ + public function loadCriteria(Criteria $criteria) + { + $orderBy = $criteria->getOrderings(); + $limit = $criteria->getMaxResults(); + $offset = $criteria->getFirstResult(); + $query = $this->persister->getSelectSQL($criteria); + $hash = $this->getHash($query, $criteria, $orderBy, $limit, $offset); + $rsm = $this->getResultSetMapping(); + $queryKey = new QueryCacheKey($hash, 0, Cache::MODE_NORMAL, $this->timestampKey); + $queryCache = $this->cache->getQueryCache($this->regionName); + $cacheResult = $queryCache->get($queryKey, $rsm); + + if ($cacheResult !== null) { + if ($this->cacheLogger) { + $this->cacheLogger->queryCacheHit($this->regionName, $queryKey); + } + + return $cacheResult; + } + + $result = $this->persister->loadCriteria($criteria); + $cached = $queryCache->put($queryKey, $rsm, $result); + + if ($this->cacheLogger) { + if ($result) { + $this->cacheLogger->queryCacheMiss($this->regionName, $queryKey); + } + + if ($cached) { + $this->cacheLogger->queryCachePut($this->regionName, $queryKey); + } + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll) + { + $persister = $this->uow->getCollectionPersister($assoc); + $hasCache = ($persister instanceof CachedPersister); + $key = null; + + if ( ! $hasCache) { + return $this->persister->loadManyToManyCollection($assoc, $sourceEntity, $coll); + } + + $ownerId = $this->uow->getEntityIdentifier($coll->getOwner()); + $key = $this->buildCollectionCacheKey($assoc, $ownerId); + $list = $persister->loadCollectionCache($coll, $key); + + if ($list !== null) { + if ($this->cacheLogger) { + $this->cacheLogger->collectionCacheHit($persister->getCacheRegion()->getName(), $key); + } + + return $list; + } + + $list = $this->persister->loadManyToManyCollection($assoc, $sourceEntity, $coll); + + $persister->storeCollectionCache($key, $list); + + if ($this->cacheLogger) { + $this->cacheLogger->collectionCacheMiss($persister->getCacheRegion()->getName(), $key); + } + + return $list; + } + + /** + * {@inheritdoc} + */ + public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll) + { + $persister = $this->uow->getCollectionPersister($assoc); + $hasCache = ($persister instanceof CachedPersister); + + if ( ! $hasCache) { + return $this->persister->loadOneToManyCollection($assoc, $sourceEntity, $coll); + } + + $ownerId = $this->uow->getEntityIdentifier($coll->getOwner()); + $key = $this->buildCollectionCacheKey($assoc, $ownerId); + $list = $persister->loadCollectionCache($coll, $key); + + if ($list !== null) { + if ($this->cacheLogger) { + $this->cacheLogger->collectionCacheHit($persister->getCacheRegion()->getName(), $key); + } + + return $list; + } + + $list = $this->persister->loadOneToManyCollection($assoc, $sourceEntity, $coll); + + $persister->storeCollectionCache($key, $list); + + if ($this->cacheLogger) { + $this->cacheLogger->collectionCacheMiss($persister->getCacheRegion()->getName(), $key); + } + + return $list; + } + + /** + * {@inheritdoc} + */ + public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifier = []) + { + return $this->persister->loadOneToOneEntity($assoc, $sourceEntity, $identifier); + } + + /** + * {@inheritdoc} + */ + public function lock(array $criteria, $lockMode) + { + $this->persister->lock($criteria, $lockMode); + } + + /** + * {@inheritdoc} + */ + public function refresh(array $id, $entity, $lockMode = null) + { + $this->persister->refresh($id, $entity, $lockMode); + } + + /** + * @param array $association + * @param array $ownerId + * + * @return CollectionCacheKey + */ + protected function buildCollectionCacheKey(array $association, $ownerId) + { + /** @var ClassMetadata $metadata */ + $metadata = $this->metadataFactory->getMetadataFor($association['sourceEntity']); + + return new CollectionCacheKey($metadata->rootEntityName, $association['fieldName'], $ownerId); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/CachedEntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/CachedEntityPersister.php new file mode 100644 index 0000000..8958270 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/CachedEntityPersister.php @@ -0,0 +1,47 @@ +. + */ + +namespace Doctrine\ORM\Cache\Persister\Entity; + +use Doctrine\ORM\Cache\EntityCacheKey; +use Doctrine\ORM\Cache\Persister\CachedPersister; +use Doctrine\ORM\Persisters\Entity\EntityPersister; + +/** + * Interface for second level cache entity persisters. + * + * @author Fabio B. Silva + * @since 2.5 + */ +interface CachedEntityPersister extends CachedPersister, EntityPersister +{ + /** + * @return \Doctrine\ORM\Cache\EntityHydrator + */ + public function getEntityHydrator(); + + /** + * @param object $entity + * @param \Doctrine\ORM\Cache\EntityCacheKey $key + * + * @return boolean + */ + public function storeEntityCache($entity, EntityCacheKey $key); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/NonStrictReadWriteCachedEntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/NonStrictReadWriteCachedEntityPersister.php new file mode 100644 index 0000000..a284467 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/NonStrictReadWriteCachedEntityPersister.php @@ -0,0 +1,117 @@ +. + */ + +namespace Doctrine\ORM\Cache\Persister\Entity; + +use Doctrine\ORM\Cache\EntityCacheKey; + +/** + * Specific non-strict read/write cached entity persister + * + * @author Fabio B. Silva + * @author Guilherme Blanco + * @since 2.5 + */ +class NonStrictReadWriteCachedEntityPersister extends AbstractEntityPersister +{ + /** + * {@inheritdoc} + */ + public function afterTransactionComplete() + { + $isChanged = false; + + if (isset($this->queuedCache['insert'])) { + foreach ($this->queuedCache['insert'] as $entity) { + $isChanged = $this->updateCache($entity, $isChanged); + } + } + + if (isset($this->queuedCache['update'])) { + foreach ($this->queuedCache['update'] as $entity) { + $isChanged = $this->updateCache($entity, $isChanged); + } + } + + if (isset($this->queuedCache['delete'])) { + foreach ($this->queuedCache['delete'] as $key) { + $this->region->evict($key); + + $isChanged = true; + } + } + + if ($isChanged) { + $this->timestampRegion->update($this->timestampKey); + } + + $this->queuedCache = []; + } + + /** + * {@inheritdoc} + */ + public function afterTransactionRolledBack() + { + $this->queuedCache = []; + } + + /** + * {@inheritdoc} + */ + public function delete($entity) + { + $key = new EntityCacheKey($this->class->rootEntityName, $this->uow->getEntityIdentifier($entity)); + $deleted = $this->persister->delete($entity); + + if ($deleted) { + $this->region->evict($key); + } + + $this->queuedCache['delete'][] = $key; + + return $deleted; + } + + /** + * {@inheritdoc} + */ + public function update($entity) + { + $this->persister->update($entity); + + $this->queuedCache['update'][] = $entity; + } + + private function updateCache($entity, $isChanged) + { + $class = $this->metadataFactory->getMetadataFor(get_class($entity)); + $key = new EntityCacheKey($class->rootEntityName, $this->uow->getEntityIdentifier($entity)); + $entry = $this->hydrator->buildCacheEntry($class, $key, $entity); + $cached = $this->region->put($key, $entry); + $isChanged = $isChanged ?: $cached; + + if ($this->cacheLogger && $cached) { + $this->cacheLogger->entityCachePut($this->regionName, $key); + } + + return $isChanged; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadOnlyCachedEntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadOnlyCachedEntityPersister.php new file mode 100644 index 0000000..ce93d7b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadOnlyCachedEntityPersister.php @@ -0,0 +1,41 @@ +. + */ + +namespace Doctrine\ORM\Cache\Persister\Entity; + +use Doctrine\ORM\Cache\CacheException; +use Doctrine\Common\Util\ClassUtils; + +/** + * Specific read-only region entity persister + * + * @author Fabio B. Silva + * @since 2.5 + */ +class ReadOnlyCachedEntityPersister extends NonStrictReadWriteCachedEntityPersister +{ + /** + * {@inheritdoc} + */ + public function update($entity) + { + throw CacheException::updateReadOnlyEntity(ClassUtils::getClass($entity)); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php new file mode 100644 index 0000000..79a4c8c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php @@ -0,0 +1,143 @@ +. + */ + +namespace Doctrine\ORM\Cache\Persister\Entity; + +use Doctrine\ORM\Persisters\Entity\EntityPersister; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Cache\ConcurrentRegion; +use Doctrine\ORM\Cache\EntityCacheKey; + +/** + * Specific read-write entity persister + * + * @author Fabio B. Silva + * @author Guilherme Blanco + * @since 2.5 + */ +class ReadWriteCachedEntityPersister extends AbstractEntityPersister +{ + /** + * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $persister The entity persister to cache. + * @param \Doctrine\ORM\Cache\ConcurrentRegion $region The entity cache region. + * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. + * @param \Doctrine\ORM\Mapping\ClassMetadata $class The entity metadata. + */ + public function __construct(EntityPersister $persister, ConcurrentRegion $region, EntityManagerInterface $em, ClassMetadata $class) + { + parent::__construct($persister, $region, $em, $class); + } + + /** + * {@inheritdoc} + */ + public function afterTransactionComplete() + { + $isChanged = true; + + if (isset($this->queuedCache['update'])) { + foreach ($this->queuedCache['update'] as $item) { + $this->region->evict($item['key']); + + $isChanged = true; + } + } + + if (isset($this->queuedCache['delete'])) { + foreach ($this->queuedCache['delete'] as $item) { + $this->region->evict($item['key']); + + $isChanged = true; + } + } + + if ($isChanged) { + $this->timestampRegion->update($this->timestampKey); + } + + $this->queuedCache = []; + } + + /** + * {@inheritdoc} + */ + public function afterTransactionRolledBack() + { + if (isset($this->queuedCache['update'])) { + foreach ($this->queuedCache['update'] as $item) { + $this->region->evict($item['key']); + } + } + + if (isset($this->queuedCache['delete'])) { + foreach ($this->queuedCache['delete'] as $item) { + $this->region->evict($item['key']); + } + } + + $this->queuedCache = []; + } + + /** + * {@inheritdoc} + */ + public function delete($entity) + { + $key = new EntityCacheKey($this->class->rootEntityName, $this->uow->getEntityIdentifier($entity)); + $lock = $this->region->lock($key); + $deleted = $this->persister->delete($entity); + + if ($deleted) { + $this->region->evict($key); + } + + if ($lock === null) { + return $deleted; + } + + $this->queuedCache['delete'][] = [ + 'lock' => $lock, + 'key' => $key + ]; + + return $deleted; + } + + /** + * {@inheritdoc} + */ + public function update($entity) + { + $key = new EntityCacheKey($this->class->rootEntityName, $this->uow->getEntityIdentifier($entity)); + $lock = $this->region->lock($key); + + $this->persister->update($entity); + + if ($lock === null) { + return; + } + + $this->queuedCache['update'][] = [ + 'lock' => $lock, + 'key' => $key + ]; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCache.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCache.php new file mode 100644 index 0000000..de24962 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCache.php @@ -0,0 +1,62 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +use Doctrine\ORM\Query\ResultSetMapping; + +/** + * Defines the contract for caches capable of storing query results. + * These caches should only concern themselves with storing the matching result ids. + * + * @since 2.5 + * @author Fabio B. Silva + */ +interface QueryCache +{ + /** + * @return boolean + */ + public function clear(); + + /** + * @param \Doctrine\ORM\Cache\QueryCacheKey $key + * @param \Doctrine\ORM\Query\ResultSetMapping $rsm + * @param mixed $result + * @param array $hints + * + * @return boolean + */ + public function put(QueryCacheKey $key, ResultSetMapping $rsm, $result, array $hints = []); + + /** + * @param \Doctrine\ORM\Cache\QueryCacheKey $key + * @param \Doctrine\ORM\Query\ResultSetMapping $rsm + * @param array $hints + * + * @return array|null + */ + public function get(QueryCacheKey $key, ResultSetMapping $rsm, array $hints = []); + + /** + * @return \Doctrine\ORM\Cache\Region + */ + public function getRegion(); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheEntry.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheEntry.php new file mode 100644 index 0000000..b6af393 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheEntry.php @@ -0,0 +1,64 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Query cache entry + * + * @since 2.5 + * @author Fabio B. Silva + */ +class QueryCacheEntry implements CacheEntry +{ + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var array List of entity identifiers + */ + public $result; + + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var float Time creation of this cache entry + */ + public $time; + + /** + * @param array $result + * @param float $time + */ + public function __construct($result, $time = null) + { + $this->result = $result; + $this->time = $time ?: microtime(true); + } + + /** + * @param array $values + * + * @return QueryCacheEntry + */ + public static function __set_state(array $values) + { + return new self($values['result'], $values['time']); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheKey.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheKey.php new file mode 100644 index 0000000..0e072a3 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheKey.php @@ -0,0 +1,71 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +use Doctrine\ORM\Cache; + +/** + * A cache key that identifies a particular query. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class QueryCacheKey extends CacheKey +{ + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var integer Cache key lifetime + */ + public $lifetime; + + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var integer Cache mode (Doctrine\ORM\Cache::MODE_*) + */ + public $cacheMode; + + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var TimestampCacheKey|null + */ + public $timestampKey; + + /** + * @param string $hash Result cache id + * @param integer $lifetime Query lifetime + * @param int $cacheMode Query cache mode + * @param TimestampCacheKey|null $timestampKey + */ + public function __construct( + $hash, + $lifetime = 0, + $cacheMode = Cache::MODE_NORMAL, + TimestampCacheKey $timestampKey = null + ) { + $this->hash = $hash; + $this->lifetime = $lifetime; + $this->cacheMode = $cacheMode; + $this->timestampKey = $timestampKey; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheValidator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheValidator.php new file mode 100644 index 0000000..682a41e --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheValidator.php @@ -0,0 +1,40 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Cache query validator interface. + * + * @since 2.5 + * @author Fabio B. Silva + */ +interface QueryCacheValidator +{ + /** + * Checks if the query entry is valid + * + * @param \Doctrine\ORM\Cache\QueryCacheKey $key + * @param \Doctrine\ORM\Cache\QueryCacheEntry $entry + * + * @return boolean + */ + public function isValid(QueryCacheKey $key, QueryCacheEntry $entry); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region.php new file mode 100644 index 0000000..3bffbbc --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region.php @@ -0,0 +1,84 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Defines a contract for accessing a particular named region. + * + * @since 2.5 + * @author Fabio B. Silva + */ +interface Region extends MultiGetRegion +{ + /** + * Retrieve the name of this region. + * + * @return string The region name + */ + public function getName(); + + /** + * Determine whether this region contains data for the given key. + * + * @param \Doctrine\ORM\Cache\CacheKey $key The cache key + * + * @return boolean TRUE if the underlying cache contains corresponding data; FALSE otherwise. + */ + public function contains(CacheKey $key); + + /** + * Get an item from the cache. + * + * @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to be retrieved. + * + * @return \Doctrine\ORM\Cache\CacheEntry|null The cached entry or NULL + * + * @throws \Doctrine\ORM\Cache\CacheException Indicates a problem accessing the item or region. + */ + public function get(CacheKey $key); + + /** + * Put an item into the cache. + * + * @param \Doctrine\ORM\Cache\CacheKey $key The key under which to cache the item. + * @param \Doctrine\ORM\Cache\CacheEntry $entry The entry to cache. + * @param \Doctrine\ORM\Cache\Lock $lock The lock previously obtained. + * + * @throws \Doctrine\ORM\Cache\CacheException Indicates a problem accessing the region. + */ + public function put(CacheKey $key, CacheEntry $entry, Lock $lock = null); + + /** + * Remove an item from the cache. + * + * @param \Doctrine\ORM\Cache\CacheKey $key The key under which to cache the item. + * + * @throws \Doctrine\ORM\Cache\CacheException Indicates a problem accessing the region. + */ + public function evict(CacheKey $key); + + /** + * Remove all contents of this particular cache region. + * + * @throws \Doctrine\ORM\Cache\CacheException Indicates problem accessing the region. + */ + public function evictAll(); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultMultiGetRegion.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultMultiGetRegion.php new file mode 100644 index 0000000..7b5f28e --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultMultiGetRegion.php @@ -0,0 +1,82 @@ +. + */ + +namespace Doctrine\ORM\Cache\Region; + +use Doctrine\Common\Cache\MultiGetCache; +use Doctrine\ORM\Cache\CacheEntry; +use Doctrine\ORM\Cache\CollectionCacheEntry; + +/** + * A cache region that enables the retrieval of multiple elements with one call + * + * @since 2.5 + * @author Asmir Mustafic + */ +class DefaultMultiGetRegion extends DefaultRegion +{ + /** + * Note that the multiple type is due to doctrine/cache not integrating the MultiGetCache interface + * in its signature due to BC in 1.x + * + * @var MultiGetCache|\Doctrine\Common\Cache\Cache + */ + protected $cache; + + /** + * {@inheritDoc} + * + * @param MultiGetCache $cache + */ + public function __construct($name, MultiGetCache $cache, $lifetime = 0) + { + /* @var $cache \Doctrine\Common\Cache\Cache */ + parent::__construct($name, $cache, $lifetime); + } + + /** + * {@inheritdoc} + */ + public function getMultiple(CollectionCacheEntry $collection) + { + $keysToRetrieve = []; + + foreach ($collection->identifiers as $index => $key) { + $keysToRetrieve[$index] = $this->getCacheEntryKey($key); + } + + $items = $this->cache->fetchMultiple($keysToRetrieve); + if (count($items) !== count($keysToRetrieve)) { + return null; + } + + $returnableItems = []; + + foreach ($keysToRetrieve as $index => $key) { + if (! $items[$key] instanceof CacheEntry) { + return null; + } + + $returnableItems[$index] = $items[$key]; + } + + return $returnableItems; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultRegion.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultRegion.php new file mode 100644 index 0000000..ab069ce --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultRegion.php @@ -0,0 +1,166 @@ +. + */ + +namespace Doctrine\ORM\Cache\Region; + +use Doctrine\Common\Cache\Cache as CacheAdapter; +use Doctrine\Common\Cache\ClearableCache; +use Doctrine\ORM\Cache\CacheEntry; +use Doctrine\ORM\Cache\CacheKey; +use Doctrine\ORM\Cache\CollectionCacheEntry; +use Doctrine\ORM\Cache\Lock; +use Doctrine\ORM\Cache\Region; + +/** + * The simplest cache region compatible with all doctrine-cache drivers. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class DefaultRegion implements Region +{ + const REGION_KEY_SEPARATOR = '_'; + + /** + * @var CacheAdapter + */ + protected $cache; + + /** + * @var string + */ + protected $name; + + /** + * @var integer + */ + protected $lifetime = 0; + + /** + * @param string $name + * @param CacheAdapter $cache + * @param integer $lifetime + */ + public function __construct($name, CacheAdapter $cache, $lifetime = 0) + { + $this->cache = $cache; + $this->name = (string) $name; + $this->lifetime = (integer) $lifetime; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * @return \Doctrine\Common\Cache\CacheProvider + */ + public function getCache() + { + return $this->cache; + } + + /** + * {@inheritdoc} + */ + public function contains(CacheKey $key) + { + return $this->cache->contains($this->getCacheEntryKey($key)); + } + + /** + * {@inheritdoc} + */ + public function get(CacheKey $key) + { + $entry = $this->cache->fetch($this->getCacheEntryKey($key)); + + if (! $entry instanceof CacheEntry) { + return null; + } + + return $entry; + } + + /** + * {@inheritdoc} + */ + public function getMultiple(CollectionCacheEntry $collection) + { + $result = []; + + foreach ($collection->identifiers as $key) { + $entryKey = $this->getCacheEntryKey($key); + $entryValue = $this->cache->fetch($entryKey); + + if (! $entryValue instanceof CacheEntry) { + return null; + } + + $result[] = $entryValue; + } + + return $result; + } + + /** + * @param CacheKey $key + * @return string + */ + protected function getCacheEntryKey(CacheKey $key) + { + return $this->name . self::REGION_KEY_SEPARATOR . $key->hash; + } + + /** + * {@inheritdoc} + */ + public function put(CacheKey $key, CacheEntry $entry, Lock $lock = null) + { + return $this->cache->save($this->getCacheEntryKey($key), $entry, $this->lifetime); + } + + /** + * {@inheritdoc} + */ + public function evict(CacheKey $key) + { + return $this->cache->delete($this->getCacheEntryKey($key)); + } + + /** + * {@inheritdoc} + */ + public function evictAll() + { + if (! $this->cache instanceof ClearableCache) { + throw new \BadMethodCallException(sprintf( + 'Clearing all cache entries is not supported by the supplied cache adapter of type %s', + get_class($this->cache) + )); + } + + return $this->cache->deleteAll(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/FileLockRegion.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/FileLockRegion.php new file mode 100644 index 0000000..880d9da --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/FileLockRegion.php @@ -0,0 +1,265 @@ +. + */ + +namespace Doctrine\ORM\Cache\Region; + +use Doctrine\ORM\Cache\CollectionCacheEntry; +use Doctrine\ORM\Cache\Lock; +use Doctrine\ORM\Cache\Region; +use Doctrine\ORM\Cache\CacheKey; +use Doctrine\ORM\Cache\CacheEntry; +use Doctrine\ORM\Cache\ConcurrentRegion; + +/** + * Very naive concurrent region, based on file locks. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class FileLockRegion implements ConcurrentRegion +{ + const LOCK_EXTENSION = 'lock'; + + /** + * var \Doctrine\ORM\Cache\Region + */ + private $region; + + /** + * @var string + */ + private $directory; + + /** + * var integer + */ + private $lockLifetime; + + /** + * @param \Doctrine\ORM\Cache\Region $region + * @param string $directory + * @param string $lockLifetime + * + * @throws \InvalidArgumentException + */ + public function __construct(Region $region, $directory, $lockLifetime) + { + if ( ! is_dir($directory) && ! @mkdir($directory, 0775, true)) { + throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $directory)); + } + + if ( ! is_writable($directory)) { + throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable.', $directory)); + } + + $this->region = $region; + $this->directory = $directory; + $this->lockLifetime = $lockLifetime; + } + + /** + * @param \Doctrine\ORM\Cache\CacheKey $key + * @param \Doctrine\ORM\Cache\Lock $lock + * + * @return boolean + */ + private function isLocked(CacheKey $key, Lock $lock = null) + { + $filename = $this->getLockFileName($key); + + if ( ! is_file($filename)) { + return false; + } + + $time = $this->getLockTime($filename); + $content = $this->getLockContent($filename); + + if ( ! $content || ! $time) { + @unlink($filename); + + return false; + } + + if ($lock && $content === $lock->value) { + return false; + } + + // outdated lock + if (($time + $this->lockLifetime) <= time()) { + @unlink($filename); + + return false; + } + + return true; + } + + /** + * @param \Doctrine\ORM\Cache\CacheKey $key + * + * @return string + */ + private function getLockFileName(CacheKey $key) + { + return $this->directory . DIRECTORY_SEPARATOR . $key->hash . '.' . self::LOCK_EXTENSION; + } + + /** + * @param string $filename + * + * @return string + */ + private function getLockContent($filename) + { + return @file_get_contents($filename); + } + + /** + * @param string $filename + * + * @return integer + */ + private function getLockTime($filename) + { + return @fileatime($filename); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->region->getName(); + } + + /** + * {@inheritdoc} + */ + public function contains(CacheKey $key) + { + if ($this->isLocked($key)) { + return false; + } + + return $this->region->contains($key); + } + + /** + * {@inheritdoc} + */ + public function get(CacheKey $key) + { + if ($this->isLocked($key)) { + return null; + } + + return $this->region->get($key); + } + + /** + * {@inheritdoc} + */ + public function getMultiple(CollectionCacheEntry $collection) + { + if (array_filter(array_map([$this, 'isLocked'], $collection->identifiers))) { + return null; + } + + return $this->region->getMultiple($collection); + } + + /** + * {@inheritdoc} + */ + public function put(CacheKey $key, CacheEntry $entry, Lock $lock = null) + { + if ($this->isLocked($key, $lock)) { + return false; + } + + return $this->region->put($key, $entry); + } + + /** + * {@inheritdoc} + */ + public function evict(CacheKey $key) + { + if ($this->isLocked($key)) { + @unlink($this->getLockFileName($key)); + } + + return $this->region->evict($key); + } + + /** + * {@inheritdoc} + */ + public function evictAll() + { + // The check below is necessary because on some platforms glob returns false + // when nothing matched (even though no errors occurred) + $filenames = glob(sprintf("%s/*.%s" , $this->directory, self::LOCK_EXTENSION)); + + if ($filenames) { + foreach ($filenames as $filename) { + @unlink($filename); + } + } + + return $this->region->evictAll(); + } + + /** + * {@inheritdoc} + */ + public function lock(CacheKey $key) + { + if ($this->isLocked($key)) { + return null; + } + + $lock = Lock::createLockRead(); + $filename = $this->getLockFileName($key); + + if ( ! @file_put_contents($filename, $lock->value, LOCK_EX)) { + return null; + } + chmod($filename, 0664); + + return $lock; + } + + /** + * {@inheritdoc} + */ + public function unlock(CacheKey $key, Lock $lock) + { + if ($this->isLocked($key, $lock)) { + return false; + } + + if ( ! @unlink($this->getLockFileName($key))) { + return false; + } + + return true; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/UpdateTimestampCache.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/UpdateTimestampCache.php new file mode 100644 index 0000000..dfdf906 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/UpdateTimestampCache.php @@ -0,0 +1,42 @@ +. + */ + +namespace Doctrine\ORM\Cache\Region; + +use Doctrine\ORM\Cache\TimestampCacheEntry; +use Doctrine\ORM\Cache\TimestampRegion; +use Doctrine\ORM\Cache\CacheKey; + +/** + * Tracks the timestamps of the most recent updates to particular keys. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class UpdateTimestampCache extends DefaultRegion implements TimestampRegion +{ + /** + * {@inheritdoc} + */ + public function update(CacheKey $key) + { + $this->put($key, new TimestampCacheEntry); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/RegionsConfiguration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/RegionsConfiguration.php new file mode 100644 index 0000000..d79c5b1 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/RegionsConfiguration.php @@ -0,0 +1,134 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Cache regions configuration + * + * @since 2.5 + * @author Fabio B. Silva + */ +class RegionsConfiguration +{ + /** + * @var array + */ + private $lifetimes = []; + + /** + * @var array + */ + private $lockLifetimes = []; + + /** + * @var integer + */ + private $defaultLifetime; + + /** + * @var integer + */ + private $defaultLockLifetime; + + /** + * @param integer $defaultLifetime + * @param integer $defaultLockLifetime + */ + public function __construct($defaultLifetime = 3600, $defaultLockLifetime = 60) + { + $this->defaultLifetime = (integer) $defaultLifetime; + $this->defaultLockLifetime = (integer) $defaultLockLifetime; + } + + /** + * @return integer + */ + public function getDefaultLifetime() + { + return $this->defaultLifetime; + } + + /** + * @param integer $defaultLifetime + */ + public function setDefaultLifetime($defaultLifetime) + { + $this->defaultLifetime = (integer) $defaultLifetime; + } + + /** + * @return integer + */ + public function getDefaultLockLifetime() + { + return $this->defaultLockLifetime; + } + + /** + * @param integer $defaultLockLifetime + */ + public function setDefaultLockLifetime($defaultLockLifetime) + { + $this->defaultLockLifetime = (integer) $defaultLockLifetime; + } + + /** + * @param string $regionName + * + * @return integer + */ + public function getLifetime($regionName) + { + return isset($this->lifetimes[$regionName]) + ? $this->lifetimes[$regionName] + : $this->defaultLifetime; + } + + /** + * @param string $name + * @param integer $lifetime + */ + public function setLifetime($name, $lifetime) + { + $this->lifetimes[$name] = (integer) $lifetime; + } + + /** + * @param string $regionName + * + * @return integer + */ + public function getLockLifetime($regionName) + { + return isset($this->lockLifetimes[$regionName]) + ? $this->lockLifetimes[$regionName] + : $this->defaultLockLifetime; + } + + /** + * @param string $name + * @param integer $lifetime + */ + public function setLockLifetime($name, $lifetime) + { + $this->lockLifetimes[$name] = (integer) $lifetime; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheEntry.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheEntry.php new file mode 100644 index 0000000..0b7ce0b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheEntry.php @@ -0,0 +1,59 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Timestamp cache entry + * + * @since 2.5 + * @author Fabio B. Silva + */ +class TimestampCacheEntry implements CacheEntry +{ + /** + * READ-ONLY: Public only for performance reasons, it should be considered immutable. + * + * @var float + */ + public $time; + + /** + * @param float $time + */ + public function __construct($time = null) + { + $this->time = $time ? (float) $time : microtime(true); + } + + /** + * Creates a new TimestampCacheEntry + * + * This method allow Doctrine\Common\Cache\PhpFileCache compatibility + * + * @param array $values array containing property values + * + * @return TimestampCacheEntry + */ + public static function __set_state(array $values) + { + return new self($values['time']); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheKey.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheKey.php new file mode 100644 index 0000000..dfa7227 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheKey.php @@ -0,0 +1,38 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * A key that identifies a timestamped space. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class TimestampCacheKey extends CacheKey +{ + /** + * @param string $space Result cache id + */ + public function __construct($space) + { + $this->hash = (string) $space; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampQueryCacheValidator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampQueryCacheValidator.php new file mode 100644 index 0000000..c6404d3 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampQueryCacheValidator.php @@ -0,0 +1,74 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * @since 2.5 + * @author Fabio B. Silva + */ +class TimestampQueryCacheValidator implements QueryCacheValidator +{ + /** + * @var TimestampRegion + */ + private $timestampRegion; + + /** + * @param TimestampRegion $timestampRegion + */ + public function __construct(TimestampRegion $timestampRegion) + { + $this->timestampRegion = $timestampRegion; + } + + /** + * {@inheritdoc} + */ + public function isValid(QueryCacheKey $key, QueryCacheEntry $entry) + { + if ($this->regionUpdated($key, $entry)) { + return false; + } + + if ($key->lifetime == 0) { + return true; + } + + return ($entry->time + $key->lifetime) > microtime(true); + } + + /** + * @param QueryCacheKey $key + * @param QueryCacheEntry $entry + * + * @return bool + */ + private function regionUpdated(QueryCacheKey $key, QueryCacheEntry $entry) + { + if ($key->timestampKey === null) { + return false; + } + + $timestamp = $this->timestampRegion->get($key->timestampKey); + + return $timestamp && $timestamp->time > $entry->time; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampRegion.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampRegion.php new file mode 100644 index 0000000..9e0c25c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampRegion.php @@ -0,0 +1,39 @@ +. + */ + +namespace Doctrine\ORM\Cache; + +/** + * Defines the contract for a cache region which will specifically be used to store entity "update timestamps". + * + * @since 2.5 + * @author Fabio B. Silva + */ +interface TimestampRegion extends Region +{ + /** + * Update an specific key into the cache region. + * + * @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to update the timestamp. + * + * @throws \Doctrine\ORM\Cache\LockException Indicates a problem accessing the region. + */ + public function update(CacheKey $key); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Configuration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Configuration.php new file mode 100644 index 0000000..c036d67 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Configuration.php @@ -0,0 +1,920 @@ +. + */ + +namespace Doctrine\ORM; + +use Doctrine\Common\Annotations\AnnotationReader; +use Doctrine\Common\Annotations\AnnotationRegistry; +use Doctrine\Common\Annotations\CachedReader; +use Doctrine\Common\Annotations\SimpleAnnotationReader; +use Doctrine\Common\Cache\ArrayCache; +use Doctrine\Common\Cache\Cache as CacheDriver; +use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver; +use Doctrine\Common\Persistence\ObjectRepository; +use Doctrine\Common\Proxy\AbstractProxyFactory; +use Doctrine\ORM\Cache\CacheConfiguration; +use Doctrine\ORM\Mapping\ClassMetadataFactory; +use Doctrine\ORM\Mapping\DefaultEntityListenerResolver; +use Doctrine\ORM\Mapping\DefaultNamingStrategy; +use Doctrine\ORM\Mapping\DefaultQuoteStrategy; +use Doctrine\ORM\Mapping\Driver\AnnotationDriver; +use Doctrine\ORM\Mapping\EntityListenerResolver; +use Doctrine\ORM\Mapping\NamingStrategy; +use Doctrine\ORM\Mapping\QuoteStrategy; +use Doctrine\ORM\Repository\DefaultRepositoryFactory; +use Doctrine\ORM\Repository\RepositoryFactory; + +/** + * Configuration container for all configuration options of Doctrine. + * It combines all configuration options from DBAL & ORM. + * + * Internal note: When adding a new configuration option just write a getter/setter pair. + * + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class Configuration extends \Doctrine\DBAL\Configuration +{ + /** + * Sets the directory where Doctrine generates any necessary proxy class files. + * + * @param string $dir + * + * @return void + */ + public function setProxyDir($dir) + { + $this->_attributes['proxyDir'] = $dir; + } + + /** + * Gets the directory where Doctrine generates any necessary proxy class files. + * + * @return string|null + * + * @deprecated 2.7 We're switch to `ocramius/proxy-manager` and this method isn't applicable any longer + * @see https://github.com/Ocramius/ProxyManager + */ + public function getProxyDir() + { + return isset($this->_attributes['proxyDir']) + ? $this->_attributes['proxyDir'] + : null; + } + + /** + * Gets the strategy for automatically generating proxy classes. + * + * @return int Possible values are constants of Doctrine\Common\Proxy\AbstractProxyFactory. + * + * @deprecated 2.7 We're switch to `ocramius/proxy-manager` and this method isn't applicable any longer + * @see https://github.com/Ocramius/ProxyManager + */ + public function getAutoGenerateProxyClasses() + { + return isset($this->_attributes['autoGenerateProxyClasses']) + ? $this->_attributes['autoGenerateProxyClasses'] + : AbstractProxyFactory::AUTOGENERATE_ALWAYS; + } + + /** + * Sets the strategy for automatically generating proxy classes. + * + * @param boolean|int $autoGenerate Possible values are constants of Doctrine\Common\Proxy\AbstractProxyFactory. + * True is converted to AUTOGENERATE_ALWAYS, false to AUTOGENERATE_NEVER. + * + * @return void + */ + public function setAutoGenerateProxyClasses($autoGenerate) + { + $this->_attributes['autoGenerateProxyClasses'] = (int) $autoGenerate; + } + + /** + * Gets the namespace where proxy classes reside. + * + * @return string|null + * + * @deprecated 2.7 We're switch to `ocramius/proxy-manager` and this method isn't applicable any longer + * @see https://github.com/Ocramius/ProxyManager + */ + public function getProxyNamespace() + { + return isset($this->_attributes['proxyNamespace']) + ? $this->_attributes['proxyNamespace'] + : null; + } + + /** + * Sets the namespace where proxy classes reside. + * + * @param string $ns + * + * @return void + */ + public function setProxyNamespace($ns) + { + $this->_attributes['proxyNamespace'] = $ns; + } + + /** + * Sets the cache driver implementation that is used for metadata caching. + * + * @param MappingDriver $driverImpl + * + * @return void + * + * @todo Force parameter to be a Closure to ensure lazy evaluation + * (as soon as a metadata cache is in effect, the driver never needs to initialize). + */ + public function setMetadataDriverImpl(MappingDriver $driverImpl) + { + $this->_attributes['metadataDriverImpl'] = $driverImpl; + } + + /** + * Adds a new default annotation driver with a correctly configured annotation reader. If $useSimpleAnnotationReader + * is true, the notation `@Entity` will work, otherwise, the notation `@ORM\Entity` will be supported. + * + * @param array $paths + * @param bool $useSimpleAnnotationReader + * + * @return AnnotationDriver + */ + public function newDefaultAnnotationDriver($paths = [], $useSimpleAnnotationReader = true) + { + AnnotationRegistry::registerFile(__DIR__ . '/Mapping/Driver/DoctrineAnnotations.php'); + + if ($useSimpleAnnotationReader) { + // Register the ORM Annotations in the AnnotationRegistry + $reader = new SimpleAnnotationReader(); + $reader->addNamespace('Doctrine\ORM\Mapping'); + $cachedReader = new CachedReader($reader, new ArrayCache()); + + return new AnnotationDriver($cachedReader, (array) $paths); + } + + return new AnnotationDriver( + new CachedReader(new AnnotationReader(), new ArrayCache()), + (array) $paths + ); + } + + /** + * Adds a namespace under a certain alias. + * + * @param string $alias + * @param string $namespace + * + * @return void + */ + public function addEntityNamespace($alias, $namespace) + { + $this->_attributes['entityNamespaces'][$alias] = $namespace; + } + + /** + * Resolves a registered namespace alias to the full namespace. + * + * @param string $entityNamespaceAlias + * + * @return string + * + * @throws ORMException + */ + public function getEntityNamespace($entityNamespaceAlias) + { + if ( ! isset($this->_attributes['entityNamespaces'][$entityNamespaceAlias])) { + throw ORMException::unknownEntityNamespace($entityNamespaceAlias); + } + + return trim($this->_attributes['entityNamespaces'][$entityNamespaceAlias], '\\'); + } + + /** + * Sets the entity alias map. + * + * @param array $entityNamespaces + * + * @return void + */ + public function setEntityNamespaces(array $entityNamespaces) + { + $this->_attributes['entityNamespaces'] = $entityNamespaces; + } + + /** + * Retrieves the list of registered entity namespace aliases. + * + * @return array + */ + public function getEntityNamespaces() + { + return $this->_attributes['entityNamespaces']; + } + + /** + * Gets the cache driver implementation that is used for the mapping metadata. + * + * @return MappingDriver|null + * + * @throws ORMException + */ + public function getMetadataDriverImpl() + { + return isset($this->_attributes['metadataDriverImpl']) + ? $this->_attributes['metadataDriverImpl'] + : null; + } + + /** + * Gets the cache driver implementation that is used for the query cache (SQL cache). + * + * @return \Doctrine\Common\Cache\Cache|null + */ + public function getQueryCacheImpl() + { + return isset($this->_attributes['queryCacheImpl']) + ? $this->_attributes['queryCacheImpl'] + : null; + } + + /** + * Sets the cache driver implementation that is used for the query cache (SQL cache). + * + * @param \Doctrine\Common\Cache\Cache $cacheImpl + * + * @return void + */ + public function setQueryCacheImpl(CacheDriver $cacheImpl) + { + $this->_attributes['queryCacheImpl'] = $cacheImpl; + } + + /** + * Gets the cache driver implementation that is used for the hydration cache (SQL cache). + * + * @return \Doctrine\Common\Cache\Cache|null + */ + public function getHydrationCacheImpl() + { + return isset($this->_attributes['hydrationCacheImpl']) + ? $this->_attributes['hydrationCacheImpl'] + : null; + } + + /** + * Sets the cache driver implementation that is used for the hydration cache (SQL cache). + * + * @param \Doctrine\Common\Cache\Cache $cacheImpl + * + * @return void + */ + public function setHydrationCacheImpl(CacheDriver $cacheImpl) + { + $this->_attributes['hydrationCacheImpl'] = $cacheImpl; + } + + /** + * Gets the cache driver implementation that is used for metadata caching. + * + * @return \Doctrine\Common\Cache\Cache|null + */ + public function getMetadataCacheImpl() + { + return isset($this->_attributes['metadataCacheImpl']) + ? $this->_attributes['metadataCacheImpl'] + : null; + } + + /** + * Sets the cache driver implementation that is used for metadata caching. + * + * @param \Doctrine\Common\Cache\Cache $cacheImpl + * + * @return void + */ + public function setMetadataCacheImpl(CacheDriver $cacheImpl) + { + $this->_attributes['metadataCacheImpl'] = $cacheImpl; + } + + /** + * Adds a named DQL query to the configuration. + * + * @param string $name The name of the query. + * @param string $dql The DQL query string. + * + * @return void + */ + public function addNamedQuery($name, $dql) + { + $this->_attributes['namedQueries'][$name] = $dql; + } + + /** + * Gets a previously registered named DQL query. + * + * @param string $name The name of the query. + * + * @return string The DQL query. + * + * @throws ORMException + */ + public function getNamedQuery($name) + { + if ( ! isset($this->_attributes['namedQueries'][$name])) { + throw ORMException::namedQueryNotFound($name); + } + + return $this->_attributes['namedQueries'][$name]; + } + + /** + * Adds a named native query to the configuration. + * + * @param string $name The name of the query. + * @param string $sql The native SQL query string. + * @param Query\ResultSetMapping $rsm The ResultSetMapping used for the results of the SQL query. + * + * @return void + */ + public function addNamedNativeQuery($name, $sql, Query\ResultSetMapping $rsm) + { + $this->_attributes['namedNativeQueries'][$name] = [$sql, $rsm]; + } + + /** + * Gets the components of a previously registered named native query. + * + * @param string $name The name of the query. + * + * @return array A tuple with the first element being the SQL string and the second + * element being the ResultSetMapping. + * + * @throws ORMException + */ + public function getNamedNativeQuery($name) + { + if ( ! isset($this->_attributes['namedNativeQueries'][$name])) { + throw ORMException::namedNativeQueryNotFound($name); + } + + return $this->_attributes['namedNativeQueries'][$name]; + } + + /** + * Ensures that this Configuration instance contains settings that are + * suitable for a production environment. + * + * @return void + * + * @throws ORMException If a configuration setting has a value that is not + * suitable for a production environment. + */ + public function ensureProductionSettings() + { + $queryCacheImpl = $this->getQueryCacheImpl(); + + if ( ! $queryCacheImpl) { + throw ORMException::queryCacheNotConfigured(); + } + + if ($queryCacheImpl instanceof ArrayCache) { + throw ORMException::queryCacheUsesNonPersistentCache($queryCacheImpl); + } + + $metadataCacheImpl = $this->getMetadataCacheImpl(); + + if ( ! $metadataCacheImpl) { + throw ORMException::metadataCacheNotConfigured(); + } + + if ($metadataCacheImpl instanceof ArrayCache) { + throw ORMException::metadataCacheUsesNonPersistentCache($metadataCacheImpl); + } + + if ($this->getAutoGenerateProxyClasses()) { + throw ORMException::proxyClassesAlwaysRegenerating(); + } + } + + /** + * Registers a custom DQL function that produces a string value. + * Such a function can then be used in any DQL statement in any place where string + * functions are allowed. + * + * DQL function names are case-insensitive. + * + * @param string $name Function name. + * @param string|callable $className Class name or a callable that returns the function. + * + * @return void + */ + public function addCustomStringFunction($name, $className) + { + $this->_attributes['customStringFunctions'][strtolower($name)] = $className; + } + + /** + * Gets the implementation class name of a registered custom string DQL function. + * + * @param string $name + * + * @return string|null + */ + public function getCustomStringFunction($name) + { + $name = strtolower($name); + + return isset($this->_attributes['customStringFunctions'][$name]) + ? $this->_attributes['customStringFunctions'][$name] + : null; + } + + /** + * Sets a map of custom DQL string functions. + * + * Keys must be function names and values the FQCN of the implementing class. + * The function names will be case-insensitive in DQL. + * + * Any previously added string functions are discarded. + * + * @param array $functions The map of custom DQL string functions. + * + * @return void + */ + public function setCustomStringFunctions(array $functions) + { + foreach ($functions as $name => $className) { + $this->addCustomStringFunction($name, $className); + } + } + + /** + * Registers a custom DQL function that produces a numeric value. + * Such a function can then be used in any DQL statement in any place where numeric + * functions are allowed. + * + * DQL function names are case-insensitive. + * + * @param string $name Function name. + * @param string|callable $className Class name or a callable that returns the function. + * + * @return void + */ + public function addCustomNumericFunction($name, $className) + { + $this->_attributes['customNumericFunctions'][strtolower($name)] = $className; + } + + /** + * Gets the implementation class name of a registered custom numeric DQL function. + * + * @param string $name + * + * @return string|null + */ + public function getCustomNumericFunction($name) + { + $name = strtolower($name); + + return isset($this->_attributes['customNumericFunctions'][$name]) + ? $this->_attributes['customNumericFunctions'][$name] + : null; + } + + /** + * Sets a map of custom DQL numeric functions. + * + * Keys must be function names and values the FQCN of the implementing class. + * The function names will be case-insensitive in DQL. + * + * Any previously added numeric functions are discarded. + * + * @param array $functions The map of custom DQL numeric functions. + * + * @return void + */ + public function setCustomNumericFunctions(array $functions) + { + foreach ($functions as $name => $className) { + $this->addCustomNumericFunction($name, $className); + } + } + + /** + * Registers a custom DQL function that produces a date/time value. + * Such a function can then be used in any DQL statement in any place where date/time + * functions are allowed. + * + * DQL function names are case-insensitive. + * + * @param string $name Function name. + * @param string|callable $className Class name or a callable that returns the function. + * + * @return void + */ + public function addCustomDatetimeFunction($name, $className) + { + $this->_attributes['customDatetimeFunctions'][strtolower($name)] = $className; + } + + /** + * Gets the implementation class name of a registered custom date/time DQL function. + * + * @param string $name + * + * @return string|null + */ + public function getCustomDatetimeFunction($name) + { + $name = strtolower($name); + + return isset($this->_attributes['customDatetimeFunctions'][$name]) + ? $this->_attributes['customDatetimeFunctions'][$name] + : null; + } + + /** + * Sets a map of custom DQL date/time functions. + * + * Keys must be function names and values the FQCN of the implementing class. + * The function names will be case-insensitive in DQL. + * + * Any previously added date/time functions are discarded. + * + * @param array $functions The map of custom DQL date/time functions. + * + * @return void + */ + public function setCustomDatetimeFunctions(array $functions) + { + foreach ($functions as $name => $className) { + $this->addCustomDatetimeFunction($name, $className); + } + } + + /** + * Sets the custom hydrator modes in one pass. + * + * @param array $modes An array of ($modeName => $hydrator). + * + * @return void + */ + public function setCustomHydrationModes($modes) + { + $this->_attributes['customHydrationModes'] = []; + + foreach ($modes as $modeName => $hydrator) { + $this->addCustomHydrationMode($modeName, $hydrator); + } + } + + /** + * Gets the hydrator class for the given hydration mode name. + * + * @param string $modeName The hydration mode name. + * + * @return string|null The hydrator class name. + */ + public function getCustomHydrationMode($modeName) + { + return isset($this->_attributes['customHydrationModes'][$modeName]) + ? $this->_attributes['customHydrationModes'][$modeName] + : null; + } + + /** + * Adds a custom hydration mode. + * + * @param string $modeName The hydration mode name. + * @param string $hydrator The hydrator class name. + * + * @return void + */ + public function addCustomHydrationMode($modeName, $hydrator) + { + $this->_attributes['customHydrationModes'][$modeName] = $hydrator; + } + + /** + * Sets a class metadata factory. + * + * @param string $cmfName + * + * @return void + */ + public function setClassMetadataFactoryName($cmfName) + { + $this->_attributes['classMetadataFactoryName'] = $cmfName; + } + + /** + * @return string + */ + public function getClassMetadataFactoryName() + { + if ( ! isset($this->_attributes['classMetadataFactoryName'])) { + $this->_attributes['classMetadataFactoryName'] = ClassMetadataFactory::class; + } + + return $this->_attributes['classMetadataFactoryName']; + } + + /** + * Adds a filter to the list of possible filters. + * + * @param string $name The name of the filter. + * @param string $className The class name of the filter. + */ + public function addFilter($name, $className) + { + $this->_attributes['filters'][$name] = $className; + } + + /** + * Gets the class name for a given filter name. + * + * @param string $name The name of the filter. + * + * @return string The class name of the filter, or null if it is not + * defined. + */ + public function getFilterClassName($name) + { + return isset($this->_attributes['filters'][$name]) + ? $this->_attributes['filters'][$name] + : null; + } + + /** + * Sets default repository class. + * + * @since 2.2 + * + * @param string $className + * + * @return void + * + * @throws ORMException If not is a \Doctrine\Common\Persistence\ObjectRepository + */ + public function setDefaultRepositoryClassName($className) + { + $reflectionClass = new \ReflectionClass($className); + + if ( ! $reflectionClass->implementsInterface(ObjectRepository::class)) { + throw ORMException::invalidEntityRepository($className); + } + + $this->_attributes['defaultRepositoryClassName'] = $className; + } + + /** + * Get default repository class. + * + * @since 2.2 + * + * @return string + */ + public function getDefaultRepositoryClassName() + { + return isset($this->_attributes['defaultRepositoryClassName']) + ? $this->_attributes['defaultRepositoryClassName'] + : EntityRepository::class; + } + + /** + * Sets naming strategy. + * + * @since 2.3 + * + * @param NamingStrategy $namingStrategy + * + * @return void + */ + public function setNamingStrategy(NamingStrategy $namingStrategy) + { + $this->_attributes['namingStrategy'] = $namingStrategy; + } + + /** + * Gets naming strategy.. + * + * @since 2.3 + * + * @return NamingStrategy + */ + public function getNamingStrategy() + { + if ( ! isset($this->_attributes['namingStrategy'])) { + $this->_attributes['namingStrategy'] = new DefaultNamingStrategy(); + } + + return $this->_attributes['namingStrategy']; + } + + /** + * Sets quote strategy. + * + * @since 2.3 + * + * @param \Doctrine\ORM\Mapping\QuoteStrategy $quoteStrategy + * + * @return void + */ + public function setQuoteStrategy(QuoteStrategy $quoteStrategy) + { + $this->_attributes['quoteStrategy'] = $quoteStrategy; + } + + /** + * Gets quote strategy. + * + * @since 2.3 + * + * @return \Doctrine\ORM\Mapping\QuoteStrategy + */ + public function getQuoteStrategy() + { + if ( ! isset($this->_attributes['quoteStrategy'])) { + $this->_attributes['quoteStrategy'] = new DefaultQuoteStrategy(); + } + + return $this->_attributes['quoteStrategy']; + } + + /** + * Set the entity listener resolver. + * + * @since 2.4 + * @param \Doctrine\ORM\Mapping\EntityListenerResolver $resolver + */ + public function setEntityListenerResolver(EntityListenerResolver $resolver) + { + $this->_attributes['entityListenerResolver'] = $resolver; + } + + /** + * Get the entity listener resolver. + * + * @since 2.4 + * @return \Doctrine\ORM\Mapping\EntityListenerResolver + */ + public function getEntityListenerResolver() + { + if ( ! isset($this->_attributes['entityListenerResolver'])) { + $this->_attributes['entityListenerResolver'] = new DefaultEntityListenerResolver(); + } + + return $this->_attributes['entityListenerResolver']; + } + + /** + * Set the entity repository factory. + * + * @since 2.4 + * @param \Doctrine\ORM\Repository\RepositoryFactory $repositoryFactory + */ + public function setRepositoryFactory(RepositoryFactory $repositoryFactory) + { + $this->_attributes['repositoryFactory'] = $repositoryFactory; + } + + /** + * Get the entity repository factory. + * + * @since 2.4 + * @return \Doctrine\ORM\Repository\RepositoryFactory + */ + public function getRepositoryFactory() + { + return isset($this->_attributes['repositoryFactory']) + ? $this->_attributes['repositoryFactory'] + : new DefaultRepositoryFactory(); + } + + /** + * @since 2.5 + * + * @return boolean + */ + public function isSecondLevelCacheEnabled() + { + return isset($this->_attributes['isSecondLevelCacheEnabled']) + ? $this->_attributes['isSecondLevelCacheEnabled'] + : false; + } + + /** + * @since 2.5 + * + * @param boolean $flag + * + * @return void + */ + public function setSecondLevelCacheEnabled($flag = true) + { + $this->_attributes['isSecondLevelCacheEnabled'] = (boolean) $flag; + } + + /** + * @since 2.5 + * + * @param \Doctrine\ORM\Cache\CacheConfiguration $cacheConfig + * + * @return void + */ + public function setSecondLevelCacheConfiguration(CacheConfiguration $cacheConfig) + { + $this->_attributes['secondLevelCacheConfiguration'] = $cacheConfig; + } + + /** + * @since 2.5 + * + * @return \Doctrine\ORM\Cache\CacheConfiguration|null + */ + public function getSecondLevelCacheConfiguration() + { + if ( ! isset($this->_attributes['secondLevelCacheConfiguration']) && $this->isSecondLevelCacheEnabled()) { + $this->_attributes['secondLevelCacheConfiguration'] = new CacheConfiguration(); + } + + return isset($this->_attributes['secondLevelCacheConfiguration']) + ? $this->_attributes['secondLevelCacheConfiguration'] + : null; + } + + /** + * Returns query hints, which will be applied to every query in application + * + * @since 2.5 + * + * @return array + */ + public function getDefaultQueryHints() + { + return isset($this->_attributes['defaultQueryHints']) ? $this->_attributes['defaultQueryHints'] : []; + } + + /** + * Sets array of query hints, which will be applied to every query in application + * + * @since 2.5 + * + * @param array $defaultQueryHints + */ + public function setDefaultQueryHints(array $defaultQueryHints) + { + $this->_attributes['defaultQueryHints'] = $defaultQueryHints; + } + + /** + * Gets the value of a default query hint. If the hint name is not recognized, FALSE is returned. + * + * @since 2.5 + * + * @param string $name The name of the hint. + * + * @return mixed The value of the hint or FALSE, if the hint name is not recognized. + */ + public function getDefaultQueryHint($name) + { + return isset($this->_attributes['defaultQueryHints'][$name]) + ? $this->_attributes['defaultQueryHints'][$name] + : false; + } + + /** + * Sets a default query hint. If the hint name is not recognized, it is silently ignored. + * + * @since 2.5 + * + * @param string $name The name of the hint. + * @param mixed $value The value of the hint. + */ + public function setDefaultQueryHint($name, $value) + { + $this->_attributes['defaultQueryHints'][$name] = $value; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Decorator/EntityManagerDecorator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Decorator/EntityManagerDecorator.php new file mode 100644 index 0000000..69cc6f5 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Decorator/EntityManagerDecorator.php @@ -0,0 +1,278 @@ +. + */ + +namespace Doctrine\ORM\Decorator; + +use Doctrine\ORM\Query\ResultSetMapping; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\Common\Persistence\ObjectManagerDecorator; + +/** + * Base class for EntityManager decorators + * + * @since 2.4 + * @author Lars Strojny wrapped = $wrapped; + } + + /** + * {@inheritdoc} + */ + public function getConnection() + { + return $this->wrapped->getConnection(); + } + + /** + * {@inheritdoc} + */ + public function getExpressionBuilder() + { + return $this->wrapped->getExpressionBuilder(); + } + + /** + * {@inheritdoc} + */ + public function beginTransaction() + { + return $this->wrapped->beginTransaction(); + } + + /** + * {@inheritdoc} + */ + public function transactional($func) + { + return $this->wrapped->transactional($func); + } + + /** + * {@inheritdoc} + */ + public function commit() + { + return $this->wrapped->commit(); + } + + /** + * {@inheritdoc} + */ + public function rollback() + { + return $this->wrapped->rollback(); + } + + /** + * {@inheritdoc} + */ + public function createQuery($dql = '') + { + return $this->wrapped->createQuery($dql); + } + + /** + * {@inheritdoc} + */ + public function createNamedQuery($name) + { + return $this->wrapped->createNamedQuery($name); + } + + /** + * {@inheritdoc} + */ + public function createNativeQuery($sql, ResultSetMapping $rsm) + { + return $this->wrapped->createNativeQuery($sql, $rsm); + } + + /** + * {@inheritdoc} + */ + public function createNamedNativeQuery($name) + { + return $this->wrapped->createNamedNativeQuery($name); + } + + /** + * {@inheritdoc} + */ + public function createQueryBuilder() + { + return $this->wrapped->createQueryBuilder(); + } + + /** + * {@inheritdoc} + */ + public function getReference($entityName, $id) + { + return $this->wrapped->getReference($entityName, $id); + } + + /** + * {@inheritdoc} + */ + public function getPartialReference($entityName, $identifier) + { + return $this->wrapped->getPartialReference($entityName, $identifier); + } + + /** + * {@inheritdoc} + */ + public function close() + { + return $this->wrapped->close(); + } + + /** + * {@inheritdoc} + */ + public function copy($entity, $deep = false) + { + return $this->wrapped->copy($entity, $deep); + } + + /** + * {@inheritdoc} + */ + public function lock($entity, $lockMode, $lockVersion = null) + { + return $this->wrapped->lock($entity, $lockMode, $lockVersion); + } + + /** + * {@inheritdoc} + */ + public function find($entityName, $id, $lockMode = null, $lockVersion = null) + { + return $this->wrapped->find($entityName, $id, $lockMode, $lockVersion); + } + + /** + * {@inheritdoc} + */ + public function flush($entity = null) + { + return $this->wrapped->flush($entity); + } + + /** + * {@inheritdoc} + */ + public function getEventManager() + { + return $this->wrapped->getEventManager(); + } + + /** + * {@inheritdoc} + */ + public function getConfiguration() + { + return $this->wrapped->getConfiguration(); + } + + /** + * {@inheritdoc} + */ + public function isOpen() + { + return $this->wrapped->isOpen(); + } + + /** + * {@inheritdoc} + */ + public function getUnitOfWork() + { + return $this->wrapped->getUnitOfWork(); + } + + /** + * {@inheritdoc} + */ + public function getHydrator($hydrationMode) + { + return $this->wrapped->getHydrator($hydrationMode); + } + + /** + * {@inheritdoc} + */ + public function newHydrator($hydrationMode) + { + return $this->wrapped->newHydrator($hydrationMode); + } + + /** + * {@inheritdoc} + */ + public function getProxyFactory() + { + return $this->wrapped->getProxyFactory(); + } + + /** + * {@inheritdoc} + */ + public function getFilters() + { + return $this->wrapped->getFilters(); + } + + /** + * {@inheritdoc} + */ + public function isFiltersStateClean() + { + return $this->wrapped->isFiltersStateClean(); + } + + /** + * {@inheritdoc} + */ + public function hasFilters() + { + return $this->wrapped->hasFilters(); + } + + /** + * {@inheritdoc} + */ + public function getCache() + { + return $this->wrapped->getCache(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php b/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php new file mode 100644 index 0000000..0752f0e --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php @@ -0,0 +1,960 @@ +. + */ + +namespace Doctrine\ORM; + +use Doctrine\Common\EventManager; +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\DriverManager; +use Doctrine\DBAL\LockMode; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Query\ResultSetMapping; +use Doctrine\ORM\Proxy\ProxyFactory; +use Doctrine\ORM\Query\FilterCollection; +use Doctrine\Common\Util\ClassUtils; +use Throwable; +use const E_USER_DEPRECATED; +use function trigger_error; + +/** + * The EntityManager is the central access point to ORM functionality. + * + * It is a facade to all different ORM subsystems such as UnitOfWork, + * Query Language and Repository API. Instantiation is done through + * the static create() method. The quickest way to obtain a fully + * configured EntityManager is: + * + * use Doctrine\ORM\Tools\Setup; + * use Doctrine\ORM\EntityManager; + * + * $paths = array('/path/to/entity/mapping/files'); + * + * $config = Setup::createAnnotationMetadataConfiguration($paths); + * $dbParams = array('driver' => 'pdo_sqlite', 'memory' => true); + * $entityManager = EntityManager::create($dbParams, $config); + * + * For more information see + * {@link http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/configuration.html} + * + * You should never attempt to inherit from the EntityManager: Inheritance + * is not a valid extension point for the EntityManager. Instead you + * should take a look at the {@see \Doctrine\ORM\Decorator\EntityManagerDecorator} + * and wrap your entity manager in a decorator. + * + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +/* final */class EntityManager implements EntityManagerInterface +{ + /** + * The used Configuration. + * + * @var \Doctrine\ORM\Configuration + */ + private $config; + + /** + * The database connection used by the EntityManager. + * + * @var \Doctrine\DBAL\Connection + */ + private $conn; + + /** + * The metadata factory, used to retrieve the ORM metadata of entity classes. + * + * @var \Doctrine\ORM\Mapping\ClassMetadataFactory + */ + private $metadataFactory; + + /** + * The UnitOfWork used to coordinate object-level transactions. + * + * @var \Doctrine\ORM\UnitOfWork + */ + private $unitOfWork; + + /** + * The event manager that is the central point of the event system. + * + * @var \Doctrine\Common\EventManager + */ + private $eventManager; + + /** + * The proxy factory used to create dynamic proxies. + * + * @var \Doctrine\ORM\Proxy\ProxyFactory + */ + private $proxyFactory; + + /** + * The repository factory used to create dynamic repositories. + * + * @var \Doctrine\ORM\Repository\RepositoryFactory + */ + private $repositoryFactory; + + /** + * The expression builder instance used to generate query expressions. + * + * @var \Doctrine\ORM\Query\Expr + */ + private $expressionBuilder; + + /** + * Whether the EntityManager is closed or not. + * + * @var bool + */ + private $closed = false; + + /** + * Collection of query filters. + * + * @var \Doctrine\ORM\Query\FilterCollection + */ + private $filterCollection; + + /** + * @var \Doctrine\ORM\Cache The second level cache regions API. + */ + private $cache; + + /** + * Creates a new EntityManager that operates on the given database connection + * and uses the given Configuration and EventManager implementations. + * + * @param \Doctrine\DBAL\Connection $conn + * @param \Doctrine\ORM\Configuration $config + * @param \Doctrine\Common\EventManager $eventManager + */ + protected function __construct(Connection $conn, Configuration $config, EventManager $eventManager) + { + $this->conn = $conn; + $this->config = $config; + $this->eventManager = $eventManager; + + $metadataFactoryClassName = $config->getClassMetadataFactoryName(); + + $this->metadataFactory = new $metadataFactoryClassName; + $this->metadataFactory->setEntityManager($this); + $this->metadataFactory->setCacheDriver($this->config->getMetadataCacheImpl()); + + $this->repositoryFactory = $config->getRepositoryFactory(); + $this->unitOfWork = new UnitOfWork($this); + $this->proxyFactory = new ProxyFactory( + $this, + $config->getProxyDir(), + $config->getProxyNamespace(), + $config->getAutoGenerateProxyClasses() + ); + + if ($config->isSecondLevelCacheEnabled()) { + $cacheConfig = $config->getSecondLevelCacheConfiguration(); + $cacheFactory = $cacheConfig->getCacheFactory(); + $this->cache = $cacheFactory->createCache($this); + } + } + + /** + * {@inheritDoc} + */ + public function getConnection() + { + return $this->conn; + } + + /** + * Gets the metadata factory used to gather the metadata of classes. + * + * @return \Doctrine\ORM\Mapping\ClassMetadataFactory + */ + public function getMetadataFactory() + { + return $this->metadataFactory; + } + + /** + * {@inheritDoc} + */ + public function getExpressionBuilder() + { + if ($this->expressionBuilder === null) { + $this->expressionBuilder = new Query\Expr; + } + + return $this->expressionBuilder; + } + + /** + * {@inheritDoc} + */ + public function beginTransaction() + { + $this->conn->beginTransaction(); + } + + /** + * {@inheritDoc} + */ + public function getCache() + { + return $this->cache; + } + + /** + * {@inheritDoc} + */ + public function transactional($func) + { + if (!is_callable($func)) { + throw new \InvalidArgumentException('Expected argument of type "callable", got "' . gettype($func) . '"'); + } + + $this->conn->beginTransaction(); + + try { + $return = call_user_func($func, $this); + + $this->flush(); + $this->conn->commit(); + + return $return ?: true; + } catch (Throwable $e) { + $this->close(); + $this->conn->rollBack(); + + throw $e; + } + } + + /** + * {@inheritDoc} + */ + public function commit() + { + $this->conn->commit(); + } + + /** + * {@inheritDoc} + */ + public function rollback() + { + $this->conn->rollBack(); + } + + /** + * Returns the ORM metadata descriptor for a class. + * + * The class name must be the fully-qualified class name without a leading backslash + * (as it is returned by get_class($obj)) or an aliased class name. + * + * Examples: + * MyProject\Domain\User + * sales:PriceRequest + * + * Internal note: Performance-sensitive method. + * + * @param string $className + * + * @return \Doctrine\ORM\Mapping\ClassMetadata + */ + public function getClassMetadata($className) + { + return $this->metadataFactory->getMetadataFor($className); + } + + /** + * {@inheritDoc} + */ + public function createQuery($dql = '') + { + $query = new Query($this); + + if ( ! empty($dql)) { + $query->setDQL($dql); + } + + return $query; + } + + /** + * {@inheritDoc} + */ + public function createNamedQuery($name) + { + return $this->createQuery($this->config->getNamedQuery($name)); + } + + /** + * {@inheritDoc} + */ + public function createNativeQuery($sql, ResultSetMapping $rsm) + { + $query = new NativeQuery($this); + + $query->setSQL($sql); + $query->setResultSetMapping($rsm); + + return $query; + } + + /** + * {@inheritDoc} + */ + public function createNamedNativeQuery($name) + { + list($sql, $rsm) = $this->config->getNamedNativeQuery($name); + + return $this->createNativeQuery($sql, $rsm); + } + + /** + * {@inheritDoc} + */ + public function createQueryBuilder() + { + return new QueryBuilder($this); + } + + /** + * Flushes all changes to objects that have been queued up to now to the database. + * This effectively synchronizes the in-memory state of managed objects with the + * database. + * + * If an entity is explicitly passed to this method only this entity and + * the cascade-persist semantics + scheduled inserts/removals are synchronized. + * + * @param null|object|array $entity + * + * @return void + * + * @throws \Doctrine\ORM\OptimisticLockException If a version check on an entity that + * makes use of optimistic locking fails. + * @throws ORMException + */ + public function flush($entity = null) + { + if ($entity !== null) { + @trigger_error( + 'Calling ' . __METHOD__ . '() with any arguments to flush specific entities is deprecated and will not be supported in Doctrine ORM 3.0.', + E_USER_DEPRECATED + ); + } + + $this->errorIfClosed(); + + $this->unitOfWork->commit($entity); + } + + /** + * Finds an Entity by its identifier. + * + * @param string $entityName The class name of the entity to find. + * @param mixed $id The identity of the entity to find. + * @param integer|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants + * or NULL if no specific lock mode should be used + * during the search. + * @param integer|null $lockVersion The version of the entity to find when using + * optimistic locking. + * + * @return object|null The entity instance or NULL if the entity can not be found. + * + * @throws OptimisticLockException + * @throws ORMInvalidArgumentException + * @throws TransactionRequiredException + * @throws ORMException + */ + public function find($entityName, $id, $lockMode = null, $lockVersion = null) + { + $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\')); + + if ($lockMode !== null) { + $this->checkLockRequirements($lockMode, $class); + } + + if ( ! is_array($id)) { + if ($class->isIdentifierComposite) { + throw ORMInvalidArgumentException::invalidCompositeIdentifier(); + } + + $id = [$class->identifier[0] => $id]; + } + + foreach ($id as $i => $value) { + if (is_object($value) && $this->metadataFactory->hasMetadataFor(ClassUtils::getClass($value))) { + $id[$i] = $this->unitOfWork->getSingleIdentifierValue($value); + + if ($id[$i] === null) { + throw ORMInvalidArgumentException::invalidIdentifierBindingEntity(); + } + } + } + + $sortedId = []; + + foreach ($class->identifier as $identifier) { + if ( ! isset($id[$identifier])) { + throw ORMException::missingIdentifierField($class->name, $identifier); + } + + $sortedId[$identifier] = $id[$identifier]; + unset($id[$identifier]); + } + + if ($id) { + throw ORMException::unrecognizedIdentifierFields($class->name, array_keys($id)); + } + + $unitOfWork = $this->getUnitOfWork(); + + // Check identity map first + if (($entity = $unitOfWork->tryGetById($sortedId, $class->rootEntityName)) !== false) { + if ( ! ($entity instanceof $class->name)) { + return null; + } + + switch (true) { + case LockMode::OPTIMISTIC === $lockMode: + $this->lock($entity, $lockMode, $lockVersion); + break; + + case LockMode::NONE === $lockMode: + case LockMode::PESSIMISTIC_READ === $lockMode: + case LockMode::PESSIMISTIC_WRITE === $lockMode: + $persister = $unitOfWork->getEntityPersister($class->name); + $persister->refresh($sortedId, $entity, $lockMode); + break; + } + + return $entity; // Hit! + } + + $persister = $unitOfWork->getEntityPersister($class->name); + + switch (true) { + case LockMode::OPTIMISTIC === $lockMode: + $entity = $persister->load($sortedId); + + $unitOfWork->lock($entity, $lockMode, $lockVersion); + + return $entity; + + case LockMode::PESSIMISTIC_READ === $lockMode: + case LockMode::PESSIMISTIC_WRITE === $lockMode: + return $persister->load($sortedId, null, null, [], $lockMode); + + default: + return $persister->loadById($sortedId); + } + } + + /** + * {@inheritDoc} + */ + public function getReference($entityName, $id) + { + $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\')); + + if ( ! is_array($id)) { + $id = [$class->identifier[0] => $id]; + } + + $sortedId = []; + + foreach ($class->identifier as $identifier) { + if ( ! isset($id[$identifier])) { + throw ORMException::missingIdentifierField($class->name, $identifier); + } + + $sortedId[$identifier] = $id[$identifier]; + unset($id[$identifier]); + } + + if ($id) { + throw ORMException::unrecognizedIdentifierFields($class->name, array_keys($id)); + } + + // Check identity map first, if its already in there just return it. + if (($entity = $this->unitOfWork->tryGetById($sortedId, $class->rootEntityName)) !== false) { + return ($entity instanceof $class->name) ? $entity : null; + } + + if ($class->subClasses) { + return $this->find($entityName, $sortedId); + } + + $entity = $this->proxyFactory->getProxy($class->name, $sortedId); + + $this->unitOfWork->registerManaged($entity, $sortedId, []); + + return $entity; + } + + /** + * {@inheritDoc} + */ + public function getPartialReference($entityName, $identifier) + { + $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\')); + + // Check identity map first, if its already in there just return it. + if (($entity = $this->unitOfWork->tryGetById($identifier, $class->rootEntityName)) !== false) { + return ($entity instanceof $class->name) ? $entity : null; + } + + if ( ! is_array($identifier)) { + $identifier = [$class->identifier[0] => $identifier]; + } + + $entity = $class->newInstance(); + + $class->setIdentifierValues($entity, $identifier); + + $this->unitOfWork->registerManaged($entity, $identifier, []); + $this->unitOfWork->markReadOnly($entity); + + return $entity; + } + + /** + * Clears the EntityManager. All entities that are currently managed + * by this EntityManager become detached. + * + * @param string|null $entityName if given, only entities of this type will get detached + * + * @return void + * + * @throws ORMInvalidArgumentException if a non-null non-string value is given + * @throws \Doctrine\Common\Persistence\Mapping\MappingException if a $entityName is given, but that entity is not + * found in the mappings + */ + public function clear($entityName = null) + { + if (null !== $entityName && ! is_string($entityName)) { + throw ORMInvalidArgumentException::invalidEntityName($entityName); + } + + if ($entityName !== null) { + @trigger_error( + 'Calling ' . __METHOD__ . '() with any arguments to clear specific entities is deprecated and will not be supported in Doctrine ORM 3.0.', + E_USER_DEPRECATED + ); + } + + $this->unitOfWork->clear( + null === $entityName + ? null + : $this->metadataFactory->getMetadataFor($entityName)->getName() + ); + } + + /** + * {@inheritDoc} + */ + public function close() + { + $this->clear(); + + $this->closed = true; + } + + /** + * Tells the EntityManager to make an instance managed and persistent. + * + * The entity will be entered into the database at or before transaction + * commit or as a result of the flush operation. + * + * NOTE: The persist operation always considers entities that are not yet known to + * this EntityManager as NEW. Do not pass detached entities to the persist operation. + * + * @param object $entity The instance to make managed and persistent. + * + * @return void + * + * @throws ORMInvalidArgumentException + * @throws ORMException + */ + public function persist($entity) + { + if ( ! is_object($entity)) { + throw ORMInvalidArgumentException::invalidObject('EntityManager#persist()', $entity); + } + + $this->errorIfClosed(); + + $this->unitOfWork->persist($entity); + } + + /** + * Removes an entity instance. + * + * A removed entity will be removed from the database at or before transaction commit + * or as a result of the flush operation. + * + * @param object $entity The entity instance to remove. + * + * @return void + * + * @throws ORMInvalidArgumentException + * @throws ORMException + */ + public function remove($entity) + { + if ( ! is_object($entity)) { + throw ORMInvalidArgumentException::invalidObject('EntityManager#remove()', $entity); + } + + $this->errorIfClosed(); + + $this->unitOfWork->remove($entity); + } + + /** + * Refreshes the persistent state of an entity from the database, + * overriding any local changes that have not yet been persisted. + * + * @param object $entity The entity to refresh. + * + * @return void + * + * @throws ORMInvalidArgumentException + * @throws ORMException + */ + public function refresh($entity) + { + if ( ! is_object($entity)) { + throw ORMInvalidArgumentException::invalidObject('EntityManager#refresh()', $entity); + } + + $this->errorIfClosed(); + + $this->unitOfWork->refresh($entity); + } + + /** + * Detaches an entity from the EntityManager, causing a managed entity to + * become detached. Unflushed changes made to the entity if any + * (including removal of the entity), will not be synchronized to the database. + * Entities which previously referenced the detached entity will continue to + * reference it. + * + * @param object $entity The entity to detach. + * + * @return void + * + * @throws ORMInvalidArgumentException + * + * @deprecated 2.7 This method is being removed from the ORM and won't have any replacement + */ + public function detach($entity) + { + @trigger_error('Method ' . __METHOD__ . '() is deprecated and will be removed in Doctrine ORM 3.0.', E_USER_DEPRECATED); + + if ( ! is_object($entity)) { + throw ORMInvalidArgumentException::invalidObject('EntityManager#detach()', $entity); + } + + $this->unitOfWork->detach($entity); + } + + /** + * Merges the state of a detached entity into the persistence context + * of this EntityManager and returns the managed copy of the entity. + * The entity passed to merge will not become associated/managed with this EntityManager. + * + * @param object $entity The detached entity to merge into the persistence context. + * + * @return object The managed copy of the entity. + * + * @throws ORMInvalidArgumentException + * @throws ORMException + * + * @deprecated 2.7 This method is being removed from the ORM and won't have any replacement + */ + public function merge($entity) + { + @trigger_error('Method ' . __METHOD__ . '() is deprecated and will be removed in Doctrine ORM 3.0.', E_USER_DEPRECATED); + + if ( ! is_object($entity)) { + throw ORMInvalidArgumentException::invalidObject('EntityManager#merge()', $entity); + } + + $this->errorIfClosed(); + + return $this->unitOfWork->merge($entity); + } + + /** + * {@inheritDoc} + */ + public function copy($entity, $deep = false) + { + @trigger_error('Method ' . __METHOD__ . '() is deprecated and will be removed in Doctrine ORM 3.0.', E_USER_DEPRECATED); + + throw new \BadMethodCallException("Not implemented."); + } + + /** + * {@inheritDoc} + */ + public function lock($entity, $lockMode, $lockVersion = null) + { + $this->unitOfWork->lock($entity, $lockMode, $lockVersion); + } + + /** + * Gets the repository for an entity class. + * + * @param string $entityName The name of the entity. + * + * @return \Doctrine\Common\Persistence\ObjectRepository|\Doctrine\ORM\EntityRepository The repository class. + */ + public function getRepository($entityName) + { + return $this->repositoryFactory->getRepository($this, $entityName); + } + + /** + * Determines whether an entity instance is managed in this EntityManager. + * + * @param object $entity + * + * @return boolean TRUE if this EntityManager currently manages the given entity, FALSE otherwise. + */ + public function contains($entity) + { + return $this->unitOfWork->isScheduledForInsert($entity) + || $this->unitOfWork->isInIdentityMap($entity) + && ! $this->unitOfWork->isScheduledForDelete($entity); + } + + /** + * {@inheritDoc} + */ + public function getEventManager() + { + return $this->eventManager; + } + + /** + * {@inheritDoc} + */ + public function getConfiguration() + { + return $this->config; + } + + /** + * Throws an exception if the EntityManager is closed or currently not active. + * + * @return void + * + * @throws ORMException If the EntityManager is closed. + */ + private function errorIfClosed() + { + if ($this->closed) { + throw ORMException::entityManagerClosed(); + } + } + + /** + * {@inheritDoc} + */ + public function isOpen() + { + return (!$this->closed); + } + + /** + * {@inheritDoc} + */ + public function getUnitOfWork() + { + return $this->unitOfWork; + } + + /** + * {@inheritDoc} + */ + public function getHydrator($hydrationMode) + { + return $this->newHydrator($hydrationMode); + } + + /** + * {@inheritDoc} + */ + public function newHydrator($hydrationMode) + { + switch ($hydrationMode) { + case Query::HYDRATE_OBJECT: + return new Internal\Hydration\ObjectHydrator($this); + + case Query::HYDRATE_ARRAY: + return new Internal\Hydration\ArrayHydrator($this); + + case Query::HYDRATE_SCALAR: + return new Internal\Hydration\ScalarHydrator($this); + + case Query::HYDRATE_SINGLE_SCALAR: + return new Internal\Hydration\SingleScalarHydrator($this); + + case Query::HYDRATE_SIMPLEOBJECT: + return new Internal\Hydration\SimpleObjectHydrator($this); + + default: + if (($class = $this->config->getCustomHydrationMode($hydrationMode)) !== null) { + return new $class($this); + } + } + + throw ORMException::invalidHydrationMode($hydrationMode); + } + + /** + * {@inheritDoc} + */ + public function getProxyFactory() + { + return $this->proxyFactory; + } + + /** + * {@inheritDoc} + */ + public function initializeObject($obj) + { + $this->unitOfWork->initializeObject($obj); + } + + /** + * Factory method to create EntityManager instances. + * + * @param array|Connection $connection An array with the connection parameters or an existing Connection instance. + * @param Configuration $config The Configuration instance to use. + * @param EventManager $eventManager The EventManager instance to use. + * + * @return EntityManager The created EntityManager. + * + * @throws \InvalidArgumentException + * @throws ORMException + */ + public static function create($connection, Configuration $config, EventManager $eventManager = null) + { + if ( ! $config->getMetadataDriverImpl()) { + throw ORMException::missingMappingDriverImpl(); + } + + $connection = static::createConnection($connection, $config, $eventManager); + + return new EntityManager($connection, $config, $connection->getEventManager()); + } + + /** + * Factory method to create Connection instances. + * + * @param array|Connection $connection An array with the connection parameters or an existing Connection instance. + * @param Configuration $config The Configuration instance to use. + * @param EventManager $eventManager The EventManager instance to use. + * + * @return Connection + * + * @throws \InvalidArgumentException + * @throws ORMException + */ + protected static function createConnection($connection, Configuration $config, EventManager $eventManager = null) + { + if (is_array($connection)) { + return DriverManager::getConnection($connection, $config, $eventManager ?: new EventManager()); + } + + if ( ! $connection instanceof Connection) { + throw new \InvalidArgumentException( + sprintf( + 'Invalid $connection argument of type %s given%s.', + is_object($connection) ? get_class($connection) : gettype($connection), + is_object($connection) ? '' : ': "' . $connection . '"' + ) + ); + } + + if ($eventManager !== null && $connection->getEventManager() !== $eventManager) { + throw ORMException::mismatchedEventManager(); + } + + return $connection; + } + + /** + * {@inheritDoc} + */ + public function getFilters() + { + if (null === $this->filterCollection) { + $this->filterCollection = new FilterCollection($this); + } + + return $this->filterCollection; + } + + /** + * {@inheritDoc} + */ + public function isFiltersStateClean() + { + return null === $this->filterCollection || $this->filterCollection->isClean(); + } + + /** + * {@inheritDoc} + */ + public function hasFilters() + { + return null !== $this->filterCollection; + } + + /** + * @param int $lockMode + * @param ClassMetadata $class + * @throws OptimisticLockException + * @throws TransactionRequiredException + */ + private function checkLockRequirements(int $lockMode, ClassMetadata $class): void + { + switch ($lockMode) { + case LockMode::OPTIMISTIC: + if (!$class->isVersioned) { + throw OptimisticLockException::notVersioned($class->name); + } + break; + case LockMode::PESSIMISTIC_READ: + case LockMode::PESSIMISTIC_WRITE: + if (!$this->getConnection()->isTransactionActive()) { + throw TransactionRequiredException::transactionRequired(); + } + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManagerInterface.php b/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManagerInterface.php new file mode 100644 index 0000000..c96aa67 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManagerInterface.php @@ -0,0 +1,298 @@ +. + */ + +namespace Doctrine\ORM; + +use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\ORM\Query\ResultSetMapping; + +/** + * EntityManager interface + * + * @since 2.4 + * @author Lars Strojny + * + * @method Mapping\ClassMetadata getClassMetadata($className) + */ +interface EntityManagerInterface extends ObjectManager +{ + /** + * Returns the cache API for managing the second level cache regions or NULL if the cache is not enabled. + * + * @return \Doctrine\ORM\Cache|null + */ + public function getCache(); + + /** + * Gets the database connection object used by the EntityManager. + * + * @return \Doctrine\DBAL\Connection + */ + public function getConnection(); + + /** + * Gets an ExpressionBuilder used for object-oriented construction of query expressions. + * + * Example: + * + * + * $qb = $em->createQueryBuilder(); + * $expr = $em->getExpressionBuilder(); + * $qb->select('u')->from('User', 'u') + * ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2))); + * + * + * @return \Doctrine\ORM\Query\Expr + */ + public function getExpressionBuilder(); + + /** + * Starts a transaction on the underlying database connection. + * + * @return void + */ + public function beginTransaction(); + + /** + * Executes a function in a transaction. + * + * The function gets passed this EntityManager instance as an (optional) parameter. + * + * {@link flush} is invoked prior to transaction commit. + * + * If an exception occurs during execution of the function or flushing or transaction commit, + * the transaction is rolled back, the EntityManager closed and the exception re-thrown. + * + * @param callable $func The function to execute transactionally. + * + * @return mixed The non-empty value returned from the closure or true instead. + */ + public function transactional($func); + + /** + * Commits a transaction on the underlying database connection. + * + * @return void + */ + public function commit(); + + /** + * Performs a rollback on the underlying database connection. + * + * @return void + */ + public function rollback(); + + /** + * Creates a new Query object. + * + * @param string $dql The DQL string. + * + * @return Query + */ + public function createQuery($dql = ''); + + /** + * Creates a Query from a named query. + * + * @param string $name + * + * @return Query + */ + public function createNamedQuery($name); + + /** + * Creates a native SQL query. + * + * @param string $sql + * @param ResultSetMapping $rsm The ResultSetMapping to use. + * + * @return NativeQuery + */ + public function createNativeQuery($sql, ResultSetMapping $rsm); + + /** + * Creates a NativeQuery from a named native query. + * + * @param string $name + * + * @return NativeQuery + */ + public function createNamedNativeQuery($name); + + /** + * Create a QueryBuilder instance + * + * @return QueryBuilder + */ + public function createQueryBuilder(); + + /** + * Gets a reference to the entity identified by the given type and identifier + * without actually loading it, if the entity is not yet loaded. + * + * @param string $entityName The name of the entity type. + * @param mixed $id The entity identifier. + * + * @return object|null The entity reference. + * + * @throws ORMException + */ + public function getReference($entityName, $id); + + /** + * Gets a partial reference to the entity identified by the given type and identifier + * without actually loading it, if the entity is not yet loaded. + * + * The returned reference may be a partial object if the entity is not yet loaded/managed. + * If it is a partial object it will not initialize the rest of the entity state on access. + * Thus you can only ever safely access the identifier of an entity obtained through + * this method. + * + * The use-cases for partial references involve maintaining bidirectional associations + * without loading one side of the association or to update an entity without loading it. + * Note, however, that in the latter case the original (persistent) entity data will + * never be visible to the application (especially not event listeners) as it will + * never be loaded in the first place. + * + * @param string $entityName The name of the entity type. + * @param mixed $identifier The entity identifier. + * + * @return object|null The (partial) entity reference. + */ + public function getPartialReference($entityName, $identifier); + + /** + * Closes the EntityManager. All entities that are currently managed + * by this EntityManager become detached. The EntityManager may no longer + * be used after it is closed. + * + * @return void + */ + public function close(); + + /** + * Creates a copy of the given entity. Can create a shallow or a deep copy. + * + * @deprecated 2.7 This method is being removed from the ORM and won't have any replacement + * + * @param object $entity The entity to copy. + * @param boolean $deep FALSE for a shallow copy, TRUE for a deep copy. + * + * @return object The new entity. + * + * @throws \BadMethodCallException + */ + public function copy($entity, $deep = false); + + /** + * Acquire a lock on the given entity. + * + * @param object $entity + * @param int $lockMode + * @param int|null $lockVersion + * + * @return void + * + * @throws OptimisticLockException + * @throws PessimisticLockException + */ + public function lock($entity, $lockMode, $lockVersion = null); + + /** + * Gets the EventManager used by the EntityManager. + * + * @return \Doctrine\Common\EventManager + */ + public function getEventManager(); + + /** + * Gets the Configuration used by the EntityManager. + * + * @return Configuration + */ + public function getConfiguration(); + + /** + * Check if the Entity manager is open or closed. + * + * @return bool + */ + public function isOpen(); + + /** + * Gets the UnitOfWork used by the EntityManager to coordinate operations. + * + * @return UnitOfWork + */ + public function getUnitOfWork(); + + /** + * Gets a hydrator for the given hydration mode. + * + * This method caches the hydrator instances which is used for all queries that don't + * selectively iterate over the result. + * + * @deprecated + * + * @param string|int $hydrationMode + * + * @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator + */ + public function getHydrator($hydrationMode); + + /** + * Create a new instance for the given hydration mode. + * + * @param string|int $hydrationMode + * + * @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator + * + * @throws ORMException + */ + public function newHydrator($hydrationMode); + + /** + * Gets the proxy factory used by the EntityManager to create entity proxies. + * + * @return \Doctrine\ORM\Proxy\ProxyFactory + */ + public function getProxyFactory(); + + /** + * Gets the enabled filters. + * + * @return \Doctrine\ORM\Query\FilterCollection The active filter collection. + */ + public function getFilters(); + + /** + * Checks whether the state of the filter collection is clean. + * + * @return boolean True, if the filter collection is clean. + */ + public function isFiltersStateClean(); + + /** + * Checks whether the Entity Manager has filters. + * + * @return boolean True, if the EM has a filter collection. + */ + public function hasFilters(); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/EntityNotFoundException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/EntityNotFoundException.php new file mode 100644 index 0000000..5b21e15 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/EntityNotFoundException.php @@ -0,0 +1,51 @@ +. + */ + +namespace Doctrine\ORM; + +/** + * Exception thrown when a Proxy fails to retrieve an Entity result. + * + * @author robo + * @since 2.0 + */ +class EntityNotFoundException extends ORMException +{ + /** + * Static constructor. + * + * @param string $className + * @param string[] $id + * + * @return self + */ + public static function fromClassNameAndIdentifier($className, array $id) + { + $ids = []; + + foreach ($id as $key => $value) { + $ids[] = $key . '(' . $value . ')'; + } + + + return new self( + 'Entity of type \'' . $className . '\'' . ($ids ? ' for IDs ' . implode(', ', $ids) : '') . ' was not found' + ); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php b/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php new file mode 100644 index 0000000..8a7c814 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php @@ -0,0 +1,313 @@ +. + */ + +namespace Doctrine\ORM; + +use Doctrine\Common\Inflector\Inflector; +use Doctrine\ORM\Query\ResultSetMappingBuilder; +use Doctrine\Common\Persistence\ObjectRepository; +use Doctrine\Common\Collections\Selectable; +use Doctrine\Common\Collections\Criteria; + +/** + * An EntityRepository serves as a repository for entities with generic as well as + * business specific methods for retrieving entities. + * + * This class is designed for inheritance and users can subclass this class to + * write their own repositories with business-specific methods to locate entities. + * + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class EntityRepository implements ObjectRepository, Selectable +{ + /** + * @var string + */ + protected $_entityName; + + /** + * @var EntityManager + */ + protected $_em; + + /** + * @var \Doctrine\ORM\Mapping\ClassMetadata + */ + protected $_class; + + /** + * Initializes a new EntityRepository. + */ + public function __construct(EntityManagerInterface $em, Mapping\ClassMetadata $class) + { + $this->_entityName = $class->name; + $this->_em = $em; + $this->_class = $class; + } + + /** + * Creates a new QueryBuilder instance that is prepopulated for this entity name. + * + * @param string $alias + * @param string $indexBy The index for the from. + * + * @return QueryBuilder + */ + public function createQueryBuilder($alias, $indexBy = null) + { + return $this->_em->createQueryBuilder() + ->select($alias) + ->from($this->_entityName, $alias, $indexBy); + } + + /** + * Creates a new result set mapping builder for this entity. + * + * The column naming strategy is "INCREMENT". + * + * @param string $alias + * + * @return ResultSetMappingBuilder + */ + public function createResultSetMappingBuilder($alias) + { + $rsm = new ResultSetMappingBuilder($this->_em, ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT); + $rsm->addRootEntityFromClassMetadata($this->_entityName, $alias); + + return $rsm; + } + + /** + * Creates a new Query instance based on a predefined metadata named query. + * + * @param string $queryName + * + * @return Query + */ + public function createNamedQuery($queryName) + { + return $this->_em->createQuery($this->_class->getNamedQuery($queryName)); + } + + /** + * Creates a native SQL query. + * + * @param string $queryName + * + * @return NativeQuery + */ + public function createNativeNamedQuery($queryName) + { + $queryMapping = $this->_class->getNamedNativeQuery($queryName); + $rsm = new Query\ResultSetMappingBuilder($this->_em); + $rsm->addNamedNativeQueryMapping($this->_class, $queryMapping); + + return $this->_em->createNativeQuery($queryMapping['query'], $rsm); + } + + /** + * Clears the repository, causing all managed entities to become detached. + * + * @return void + */ + public function clear() + { + $this->_em->clear($this->_class->rootEntityName); + } + + /** + * Finds an entity by its primary key / identifier. + * + * @param mixed $id The identifier. + * @param int|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants + * or NULL if no specific lock mode should be used + * during the search. + * @param int|null $lockVersion The lock version. + * + * @return object|null The entity instance or NULL if the entity can not be found. + */ + public function find($id, $lockMode = null, $lockVersion = null) + { + return $this->_em->find($this->_entityName, $id, $lockMode, $lockVersion); + } + + /** + * Finds all entities in the repository. + * + * @return array The entities. + */ + public function findAll() + { + return $this->findBy([]); + } + + /** + * Finds entities by a set of criteria. + * + * @param array $criteria + * @param array|null $orderBy + * @param int|null $limit + * @param int|null $offset + * + * @return array The objects. + */ + public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + { + $persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName); + + return $persister->loadAll($criteria, $orderBy, $limit, $offset); + } + + /** + * Finds a single entity by a set of criteria. + * + * @param array $criteria + * @param array|null $orderBy + * + * @return object|null The entity instance or NULL if the entity can not be found. + */ + public function findOneBy(array $criteria, array $orderBy = null) + { + $persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName); + + return $persister->load($criteria, null, null, [], null, 1, $orderBy); + } + + /** + * Counts entities by a set of criteria. + * + * @todo Add this method to `ObjectRepository` interface in the next major release + * + * @param array $criteria + * + * @return int The cardinality of the objects that match the given criteria. + */ + public function count(array $criteria) + { + return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->count($criteria); + } + + /** + * Adds support for magic method calls. + * + * @param string $method + * @param array $arguments + * + * @return mixed The returned value from the resolved method. + * + * @throws ORMException + * @throws \BadMethodCallException If the method called is invalid + */ + public function __call($method, $arguments) + { + if (0 === strpos($method, 'findBy')) { + return $this->resolveMagicCall('findBy', substr($method, 6), $arguments); + } + + if (0 === strpos($method, 'findOneBy')) { + return $this->resolveMagicCall('findOneBy', substr($method, 9), $arguments); + } + + if (0 === strpos($method, 'countBy')) { + return $this->resolveMagicCall('count', substr($method, 7), $arguments); + } + + throw new \BadMethodCallException( + "Undefined method '$method'. The method name must start with ". + "either findBy, findOneBy or countBy!" + ); + } + + /** + * @return string + */ + protected function getEntityName() + { + return $this->_entityName; + } + + /** + * @return string + */ + public function getClassName() + { + return $this->getEntityName(); + } + + /** + * @return EntityManager + */ + protected function getEntityManager() + { + return $this->_em; + } + + /** + * @return Mapping\ClassMetadata + */ + protected function getClassMetadata() + { + return $this->_class; + } + + /** + * Select all elements from a selectable that match the expression and + * return a new collection containing these elements. + * + * @param \Doctrine\Common\Collections\Criteria $criteria + * + * @return \Doctrine\Common\Collections\Collection + */ + public function matching(Criteria $criteria) + { + $persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName); + + return new LazyCriteriaCollection($persister, $criteria); + } + + /** + * Resolves a magic method call to the proper existent method at `EntityRepository`. + * + * @param string $method The method to call + * @param string $by The property name used as condition + * @param array $arguments The arguments to pass at method call + * + * @throws ORMException If the method called is invalid or the requested field/association does not exist + * + * @return mixed + */ + private function resolveMagicCall($method, $by, array $arguments) + { + if (! $arguments) { + throw ORMException::findByRequiresParameter($method . $by); + } + + $fieldName = lcfirst(Inflector::classify($by)); + + if (! ($this->_class->hasField($fieldName) || $this->_class->hasAssociation($fieldName))) { + throw ORMException::invalidMagicCall($this->_entityName, $fieldName, $method . $by); + } + + return $this->$method([$fieldName => $arguments[0]], ...array_slice($arguments, 1)); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/LifecycleEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/LifecycleEventArgs.php new file mode 100644 index 0000000..c7eb80b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/LifecycleEventArgs.php @@ -0,0 +1,54 @@ +. + */ + +namespace Doctrine\ORM\Event; + +use Doctrine\Common\Persistence\Event\LifecycleEventArgs as BaseLifecycleEventArgs; + +/** + * Lifecycle Events are triggered by the UnitOfWork during lifecycle transitions + * of entities. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class LifecycleEventArgs extends BaseLifecycleEventArgs +{ + /** + * Retrieves associated Entity. + * + * @return object + */ + public function getEntity() + { + return $this->getObject(); + } + + /** + * Retrieves associated EntityManager. + * + * @return \Doctrine\ORM\EntityManager + */ + public function getEntityManager() + { + return $this->getObjectManager(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/ListenersInvoker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/ListenersInvoker.php new file mode 100644 index 0000000..7be8d48 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/ListenersInvoker.php @@ -0,0 +1,120 @@ +. + */ + +namespace Doctrine\ORM\Event; + +use Doctrine\Common\EventArgs; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadata; + +/** + * A method invoker based on entity lifecycle. + * + * @author Fabio B. Silva + * @since 2.4 + */ +class ListenersInvoker +{ + const INVOKE_NONE = 0; + const INVOKE_LISTENERS = 1; + const INVOKE_CALLBACKS = 2; + const INVOKE_MANAGER = 4; + + /** + * @var \Doctrine\ORM\Mapping\EntityListenerResolver The Entity listener resolver. + */ + private $resolver; + + /** + * The EventManager used for dispatching events. + * + * @var \Doctrine\Common\EventManager + */ + private $eventManager; + + /** + * Initializes a new ListenersInvoker instance. + * + * @param EntityManagerInterface $em + */ + public function __construct(EntityManagerInterface $em) + { + $this->eventManager = $em->getEventManager(); + $this->resolver = $em->getConfiguration()->getEntityListenerResolver(); + } + + /** + * Get the subscribed event systems + * + * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. + * @param string $eventName The entity lifecycle event. + * + * @return integer Bitmask of subscribed event systems. + */ + public function getSubscribedSystems(ClassMetadata $metadata, $eventName) + { + $invoke = self::INVOKE_NONE; + + if (isset($metadata->lifecycleCallbacks[$eventName])) { + $invoke |= self::INVOKE_CALLBACKS; + } + + if (isset($metadata->entityListeners[$eventName])) { + $invoke |= self::INVOKE_LISTENERS; + } + + if ($this->eventManager->hasListeners($eventName)) { + $invoke |= self::INVOKE_MANAGER; + } + + return $invoke; + } + + /** + * Dispatches the lifecycle event of the given entity. + * + * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. + * @param string $eventName The entity lifecycle event. + * @param object $entity The Entity on which the event occurred. + * @param \Doctrine\Common\EventArgs $event The Event args. + * @param integer $invoke Bitmask to invoke listeners. + */ + public function invoke(ClassMetadata $metadata, $eventName, $entity, EventArgs $event, $invoke) + { + if ($invoke & self::INVOKE_CALLBACKS) { + foreach ($metadata->lifecycleCallbacks[$eventName] as $callback) { + $entity->$callback($event); + } + } + + if ($invoke & self::INVOKE_LISTENERS) { + foreach ($metadata->entityListeners[$eventName] as $listener) { + $class = $listener['class']; + $method = $listener['method']; + $instance = $this->resolver->resolve($class); + + $instance->$method($entity, $event); + } + } + + if ($invoke & self::INVOKE_MANAGER) { + $this->eventManager->dispatchEvent($eventName, $event); + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php new file mode 100644 index 0000000..5df698d --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php @@ -0,0 +1,46 @@ +. + */ + +namespace Doctrine\ORM\Event; + +use Doctrine\Common\Persistence\Event\LoadClassMetadataEventArgs as BaseLoadClassMetadataEventArgs; + +/** + * Class that holds event arguments for a loadMetadata event. + * + * @author Jonathan H. Wage + * @since 2.0 + * + * Note: method annotations are used instead of method overrides (due to BC policy) + * + * @method __construct(\Doctrine\ORM\Mapping\ClassMetadata $classMetadata, \Doctrine\ORM\EntityManager $objectManager) + * @method \Doctrine\ORM\Mapping\ClassMetadata getClassMetadata() + */ +class LoadClassMetadataEventArgs extends BaseLoadClassMetadataEventArgs +{ + /** + * Retrieve associated EntityManager. + * + * @return \Doctrine\ORM\EntityManager + */ + public function getEntityManager() + { + return $this->getObjectManager(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClassMetadataNotFoundEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClassMetadataNotFoundEventArgs.php new file mode 100644 index 0000000..a044a7e --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClassMetadataNotFoundEventArgs.php @@ -0,0 +1,86 @@ +. + */ + +namespace Doctrine\ORM\Event; + +use Doctrine\Common\Persistence\Event\ManagerEventArgs; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Doctrine\Common\Persistence\ObjectManager; + +/** + * Class that holds event arguments for a `onClassMetadataNotFound` event. + * + * This object is mutable by design, allowing callbacks having access to it to set the + * found metadata in it, and therefore "cancelling" a `onClassMetadataNotFound` event + * + * @author Marco Pivetta + * @since 2.5 + */ +class OnClassMetadataNotFoundEventArgs extends ManagerEventArgs +{ + /** + * @var string + */ + private $className; + + /** + * @var ClassMetadata|null + */ + private $foundMetadata; + + /** + * Constructor. + * + * @param string $className + * @param ObjectManager $objectManager + */ + public function __construct($className, ObjectManager $objectManager) + { + $this->className = (string) $className; + + parent::__construct($objectManager); + } + + /** + * @param ClassMetadata|null $classMetadata + */ + public function setFoundMetadata(ClassMetadata $classMetadata = null) + { + $this->foundMetadata = $classMetadata; + } + + /** + * @return ClassMetadata|null + */ + public function getFoundMetadata() + { + return $this->foundMetadata; + } + + /** + * Retrieve class name for which a failed metadata fetch attempt was executed + * + * @return string + */ + public function getClassName() + { + return $this->className; + } +} + diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClearEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClearEventArgs.php new file mode 100644 index 0000000..dd827c7 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClearEventArgs.php @@ -0,0 +1,86 @@ +. + */ + +namespace Doctrine\ORM\Event; + +use Doctrine\ORM\EntityManagerInterface; + +/** + * Provides event arguments for the onClear event. + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.org + * @since 2.0 + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class OnClearEventArgs extends \Doctrine\Common\EventArgs +{ + /** + * @var EntityManagerInterface + */ + private $em; + + /** + * @var string + */ + private $entityClass; + + /** + * Constructor. + * + * @param EntityManagerInterface $em + * @param string|null $entityClass Optional entity class. + */ + public function __construct(EntityManagerInterface $em, $entityClass = null) + { + $this->em = $em; + $this->entityClass = $entityClass; + } + + /** + * Retrieves associated EntityManager. + * + * @return \Doctrine\ORM\EntityManager + */ + public function getEntityManager() + { + return $this->em; + } + + /** + * Name of the entity class that is cleared, or empty if all are cleared. + * + * @return string|null + */ + public function getEntityClass() + { + return $this->entityClass; + } + + /** + * Checks if event clears all entities. + * + * @return bool + */ + public function clearsAllEntities() + { + return ($this->entityClass === null); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnFlushEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnFlushEventArgs.php new file mode 100644 index 0000000..6a9c7c7 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnFlushEventArgs.php @@ -0,0 +1,61 @@ +. + */ + +namespace Doctrine\ORM\Event; + +use Doctrine\Common\EventArgs; +use Doctrine\ORM\EntityManagerInterface; + +/** + * Provides event arguments for the preFlush event. + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.org + * @since 2.0 + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class OnFlushEventArgs extends EventArgs +{ + /** + * @var EntityManagerInterface + */ + private $em; + + /** + * Constructor. + * + * @param EntityManagerInterface $em + */ + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + + /** + * Retrieve associated EntityManager. + * + * @return \Doctrine\ORM\EntityManager + */ + public function getEntityManager() + { + return $this->em; + } + +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PostFlushEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PostFlushEventArgs.php new file mode 100644 index 0000000..860f2d3 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PostFlushEventArgs.php @@ -0,0 +1,58 @@ +. + */ +namespace Doctrine\ORM\Event; + +use Doctrine\Common\EventArgs; +use Doctrine\ORM\EntityManagerInterface; + +/** + * Provides event arguments for the postFlush event. + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.org + * @since 2.0 + * @author Daniel Freudenberger + */ +class PostFlushEventArgs extends EventArgs +{ + /** + * @var \Doctrine\ORM\EntityManager + */ + private $em; + + /** + * Constructor. + * + * @param EntityManagerInterface $em + */ + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + + /** + * Retrieves associated EntityManager. + * + * @return \Doctrine\ORM\EntityManager + */ + public function getEntityManager() + { + return $this->em; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreFlushEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreFlushEventArgs.php new file mode 100644 index 0000000..d01a926 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreFlushEventArgs.php @@ -0,0 +1,58 @@ +. + */ + +namespace Doctrine\ORM\Event; + +use Doctrine\Common\EventArgs; +use Doctrine\ORM\EntityManagerInterface; + +/** + * Provides event arguments for the preFlush event. + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.com + * @since 2.0 + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class PreFlushEventArgs extends EventArgs +{ + /** + * @var \Doctrine\ORM\EntityManager + */ + private $em; + + /** + * Constructor. + * + * @param EntityManagerInterface $em + */ + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + + /** + * @return \Doctrine\ORM\EntityManager + */ + public function getEntityManager() + { + return $this->em; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php new file mode 100644 index 0000000..d9a9f9d --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php @@ -0,0 +1,137 @@ +. + */ + +namespace Doctrine\ORM\Event; + +use Doctrine\ORM\EntityManagerInterface; + +/** + * Class that holds event arguments for a preInsert/preUpdate event. + * + * @author Guilherme Blanco + * @author Roman Borschel + * @author Benjamin Eberlei + * @since 2.0 + */ +class PreUpdateEventArgs extends LifecycleEventArgs +{ + /** + * @var array + */ + private $entityChangeSet; + + /** + * Constructor. + * + * @param object $entity + * @param EntityManagerInterface $em + * @param array $changeSet + */ + public function __construct($entity, EntityManagerInterface $em, array &$changeSet) + { + parent::__construct($entity, $em); + + $this->entityChangeSet = &$changeSet; + } + + /** + * Retrieves entity changeset. + * + * @return array + */ + public function getEntityChangeSet() + { + return $this->entityChangeSet; + } + + /** + * Checks if field has a changeset. + * + * @param string $field + * + * @return boolean + */ + public function hasChangedField($field) + { + return isset($this->entityChangeSet[$field]); + } + + /** + * Gets the old value of the changeset of the changed field. + * + * @param string $field + * + * @return mixed + */ + public function getOldValue($field) + { + $this->assertValidField($field); + + return $this->entityChangeSet[$field][0]; + } + + /** + * Gets the new value of the changeset of the changed field. + * + * @param string $field + * + * @return mixed + */ + public function getNewValue($field) + { + $this->assertValidField($field); + + return $this->entityChangeSet[$field][1]; + } + + /** + * Sets the new value of this field. + * + * @param string $field + * @param mixed $value + * + * @return void + */ + public function setNewValue($field, $value) + { + $this->assertValidField($field); + + $this->entityChangeSet[$field][1] = $value; + } + + /** + * Asserts the field exists in changeset. + * + * @param string $field + * + * @return void + * + * @throws \InvalidArgumentException + */ + private function assertValidField($field) + { + if ( ! isset($this->entityChangeSet[$field])) { + throw new \InvalidArgumentException(sprintf( + 'Field "%s" is not a valid field of the entity "%s" in PreUpdateEventArgs.', + $field, + get_class($this->getEntity()) + )); + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Events.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Events.php new file mode 100644 index 0000000..e16b47a --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Events.php @@ -0,0 +1,167 @@ +. + */ + +namespace Doctrine\ORM; + +/** + * Container for all ORM events. + * + * This class cannot be instantiated. + * + * @author Roman Borschel + * @since 2.0 + */ +final class Events +{ + /** + * Private constructor. This class is not meant to be instantiated. + */ + private function __construct() + { + } + + /** + * The preRemove event occurs for a given entity before the respective + * EntityManager remove operation for that entity is executed. + * + * This is an entity lifecycle event. + * + * @var string + */ + const preRemove = 'preRemove'; + + /** + * The postRemove event occurs for an entity after the entity has + * been deleted. It will be invoked after the database delete operations. + * + * This is an entity lifecycle event. + * + * @var string + */ + const postRemove = 'postRemove'; + + /** + * The prePersist event occurs for a given entity before the respective + * EntityManager persist operation for that entity is executed. + * + * This is an entity lifecycle event. + * + * @var string + */ + const prePersist = 'prePersist'; + + /** + * The postPersist event occurs for an entity after the entity has + * been made persistent. It will be invoked after the database insert operations. + * Generated primary key values are available in the postPersist event. + * + * This is an entity lifecycle event. + * + * @var string + */ + const postPersist = 'postPersist'; + + /** + * The preUpdate event occurs before the database update operations to + * entity data. + * + * This is an entity lifecycle event. + * + * @var string + */ + const preUpdate = 'preUpdate'; + + /** + * The postUpdate event occurs after the database update operations to + * entity data. + * + * This is an entity lifecycle event. + * + * @var string + */ + const postUpdate = 'postUpdate'; + + /** + * The postLoad event occurs for an entity after the entity has been loaded + * into the current EntityManager from the database or after the refresh operation + * has been applied to it. + * + * Note that the postLoad event occurs for an entity before any associations have been + * initialized. Therefore it is not safe to access associations in a postLoad callback + * or event handler. + * + * This is an entity lifecycle event. + * + * @var string + */ + const postLoad = 'postLoad'; + + /** + * The loadClassMetadata event occurs after the mapping metadata for a class + * has been loaded from a mapping source (annotations/xml/yaml). + * + * @var string + */ + const loadClassMetadata = 'loadClassMetadata'; + + /** + * The onClassMetadataNotFound event occurs whenever loading metadata for a class + * failed. + * + * @var string + */ + const onClassMetadataNotFound = 'onClassMetadataNotFound'; + + /** + * The preFlush event occurs when the EntityManager#flush() operation is invoked, + * but before any changes to managed entities have been calculated. This event is + * always raised right after EntityManager#flush() call. + */ + const preFlush = 'preFlush'; + + /** + * The onFlush event occurs when the EntityManager#flush() operation is invoked, + * after any changes to managed entities have been determined but before any + * actual database operations are executed. The event is only raised if there is + * actually something to do for the underlying UnitOfWork. If nothing needs to be done, + * the onFlush event is not raised. + * + * @var string + */ + const onFlush = 'onFlush'; + + /** + * The postFlush event occurs when the EntityManager#flush() operation is invoked and + * after all actual database operations are executed successfully. The event is only raised if there is + * actually something to do for the underlying UnitOfWork. If nothing needs to be done, + * the postFlush event is not raised. The event won't be raised if an error occurs during the + * flush operation. + * + * @var string + */ + const postFlush = 'postFlush'; + + /** + * The onClear event occurs when the EntityManager#clear() operation is invoked, + * after all references to entities have been removed from the unit of work. + * + * @var string + */ + const onClear = 'onClear'; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/AbstractIdGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/AbstractIdGenerator.php new file mode 100644 index 0000000..9e2e226 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/AbstractIdGenerator.php @@ -0,0 +1,49 @@ +. + */ + +namespace Doctrine\ORM\Id; + +use Doctrine\ORM\EntityManager; + +abstract class AbstractIdGenerator +{ + /** + * Generates an identifier for an entity. + * + * @param EntityManager $em + * @param object|null $entity + * @return mixed + */ + abstract public function generate(EntityManager $em, $entity); + + /** + * Gets whether this generator is a post-insert generator which means that + * {@link generate()} must be called after the entity has been inserted + * into the database. + * + * By default, this method returns FALSE. Generators that have this requirement + * must override this method and return TRUE. + * + * @return boolean + */ + public function isPostInsertGenerator() + { + return false; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/AssignedGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/AssignedGenerator.php new file mode 100644 index 0000000..691eaee --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/AssignedGenerator.php @@ -0,0 +1,66 @@ +. + */ + +namespace Doctrine\ORM\Id; + +use Doctrine\ORM\EntityManager; +use Doctrine\ORM\ORMException; + +/** + * Special generator for application-assigned identifiers (doesn't really generate anything). + * + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class AssignedGenerator extends AbstractIdGenerator +{ + /** + * Returns the identifier assigned to the given entity. + * + * {@inheritDoc} + * + * @throws \Doctrine\ORM\ORMException + */ + public function generate(EntityManager $em, $entity) + { + $class = $em->getClassMetadata(get_class($entity)); + $idFields = $class->getIdentifierFieldNames(); + $identifier = []; + + foreach ($idFields as $idField) { + $value = $class->getFieldValue($entity, $idField); + + if ( ! isset($value)) { + throw ORMException::entityMissingAssignedIdForField($entity, $idField); + } + + if (isset($class->associationMappings[$idField])) { + // NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced. + $value = $em->getUnitOfWork()->getSingleIdentifierValue($value); + } + + $identifier[$idField] = $value; + } + + return $identifier; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/BigIntegerIdentityGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/BigIntegerIdentityGenerator.php new file mode 100644 index 0000000..01d139f --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/BigIntegerIdentityGenerator.php @@ -0,0 +1,66 @@ +. + */ + +namespace Doctrine\ORM\Id; + +use Doctrine\ORM\EntityManager; + +/** + * Id generator that obtains IDs from special "identity" columns. These are columns + * that automatically get a database-generated, auto-incremented identifier on INSERT. + * This generator obtains the last insert id after such an insert. + */ +class BigIntegerIdentityGenerator extends AbstractIdGenerator +{ + /** + * The name of the sequence to pass to lastInsertId(), if any. + * + * @var string + */ + private $sequenceName; + + /** + * Constructor. + * + * @param string|null $sequenceName The name of the sequence to pass to lastInsertId() + * to obtain the last generated identifier within the current + * database session/connection, if any. + */ + public function __construct($sequenceName = null) + { + $this->sequenceName = $sequenceName; + } + + /** + * {@inheritDoc} + */ + public function generate(EntityManager $em, $entity) + { + return (string) $em->getConnection()->lastInsertId($this->sequenceName); + } + + /** + * {@inheritDoc} + */ + public function isPostInsertGenerator() + { + return true; + } +} + diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/IdentityGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/IdentityGenerator.php new file mode 100644 index 0000000..b9f68c6 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/IdentityGenerator.php @@ -0,0 +1,65 @@ +. + */ + +namespace Doctrine\ORM\Id; + +use Doctrine\ORM\EntityManager; + +/** + * Id generator that obtains IDs from special "identity" columns. These are columns + * that automatically get a database-generated, auto-incremented identifier on INSERT. + * This generator obtains the last insert id after such an insert. + */ +class IdentityGenerator extends AbstractIdGenerator +{ + /** + * The name of the sequence to pass to lastInsertId(), if any. + * + * @var string + */ + private $sequenceName; + + /** + * Constructor. + * + * @param string|null $sequenceName The name of the sequence to pass to lastInsertId() + * to obtain the last generated identifier within the current + * database session/connection, if any. + */ + public function __construct($sequenceName = null) + { + $this->sequenceName = $sequenceName; + } + + /** + * {@inheritDoc} + */ + public function generate(EntityManager $em, $entity) + { + return (int) $em->getConnection()->lastInsertId($this->sequenceName); + } + + /** + * {@inheritdoc} + */ + public function isPostInsertGenerator() + { + return true; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/SequenceGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/SequenceGenerator.php new file mode 100644 index 0000000..9d8e9eb --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/SequenceGenerator.php @@ -0,0 +1,132 @@ +. + */ + +namespace Doctrine\ORM\Id; + +use Doctrine\ORM\EntityManager; +use Serializable; + +/** + * Represents an ID generator that uses a database sequence. + * + * @since 2.0 + * @author Roman Borschel + */ +class SequenceGenerator extends AbstractIdGenerator implements Serializable +{ + /** + * The allocation size of the sequence. + * + * @var int + */ + private $_allocationSize; + + /** + * The name of the sequence. + * + * @var string + */ + private $_sequenceName; + + /** + * @var int + */ + private $_nextValue = 0; + + /** + * @var int|null + */ + private $_maxValue = null; + + /** + * Initializes a new sequence generator. + * + * @param string $sequenceName The name of the sequence. + * @param integer $allocationSize The allocation size of the sequence. + */ + public function __construct($sequenceName, $allocationSize) + { + $this->_sequenceName = $sequenceName; + $this->_allocationSize = $allocationSize; + } + + /** + * {@inheritDoc} + */ + public function generate(EntityManager $em, $entity) + { + if ($this->_maxValue === null || $this->_nextValue == $this->_maxValue) { + // Allocate new values + $conn = $em->getConnection(); + $sql = $conn->getDatabasePlatform()->getSequenceNextValSQL($this->_sequenceName); + + // Using `query` to force usage of the master server in MasterSlaveConnection + $this->_nextValue = (int) $conn->query($sql)->fetchColumn(); + $this->_maxValue = $this->_nextValue + $this->_allocationSize; + } + + return $this->_nextValue++; + } + + /** + * Gets the maximum value of the currently allocated bag of values. + * + * @return integer|null + */ + public function getCurrentMaxValue() + { + return $this->_maxValue; + } + + /** + * Gets the next value that will be returned by generate(). + * + * @return integer + */ + public function getNextValue() + { + return $this->_nextValue; + } + + /** + * @return string + */ + public function serialize() + { + return serialize( + [ + 'allocationSize' => $this->_allocationSize, + 'sequenceName' => $this->_sequenceName + ] + ); + } + + /** + * @param string $serialized + * + * @return void + */ + public function unserialize($serialized) + { + $array = unserialize($serialized); + + $this->_sequenceName = $array['sequenceName']; + $this->_allocationSize = $array['allocationSize']; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/TableGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/TableGenerator.php new file mode 100644 index 0000000..02385f5 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/TableGenerator.php @@ -0,0 +1,109 @@ +. + */ + +namespace Doctrine\ORM\Id; + +use Doctrine\ORM\EntityManager; + +/** + * Id generator that uses a single-row database table and a hi/lo algorithm. + * + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class TableGenerator extends AbstractIdGenerator +{ + /** + * @var string + */ + private $_tableName; + + /** + * @var string + */ + private $_sequenceName; + + /** + * @var int + */ + private $_allocationSize; + + /** + * @var int|null + */ + private $_nextValue; + + /** + * @var int|null + */ + private $_maxValue; + + /** + * @param string $tableName + * @param string $sequenceName + * @param int $allocationSize + */ + public function __construct($tableName, $sequenceName = 'default', $allocationSize = 10) + { + $this->_tableName = $tableName; + $this->_sequenceName = $sequenceName; + $this->_allocationSize = $allocationSize; + } + + /** + * {@inheritDoc} + */ + public function generate( + EntityManager $em, $entity) + { + if ($this->_maxValue === null || $this->_nextValue == $this->_maxValue) { + // Allocate new values + $conn = $em->getConnection(); + + if ($conn->getTransactionNestingLevel() === 0) { + // use select for update + $sql = $conn->getDatabasePlatform()->getTableHiLoCurrentValSql($this->_tableName, $this->_sequenceName); + $currentLevel = $conn->fetchColumn($sql); + + if ($currentLevel != null) { + $this->_nextValue = $currentLevel; + $this->_maxValue = $this->_nextValue + $this->_allocationSize; + + $updateSql = $conn->getDatabasePlatform()->getTableHiLoUpdateNextValSql( + $this->_tableName, $this->_sequenceName, $this->_allocationSize + ); + + if ($conn->executeUpdate($updateSql, [1 => $currentLevel, 2 => $currentLevel+1]) !== 1) { + // no affected rows, concurrency issue, throw exception + } + } else { + // no current level returned, TableGenerator seems to be broken, throw exception + } + } else { + // only table locks help here, implement this or throw exception? + // or do we want to work with table locks exclusively? + } + } + + return $this->_nextValue++; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/UuidGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/UuidGenerator.php new file mode 100644 index 0000000..7cac5cc --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/UuidGenerator.php @@ -0,0 +1,42 @@ +. + */ + +namespace Doctrine\ORM\Id; + +use Doctrine\ORM\EntityManager; + +/** + * Represents an ID generator that uses the database UUID expression + * + * @since 2.3 + * @author Maarten de Keizer + */ +class UuidGenerator extends AbstractIdGenerator +{ + /** + * {@inheritDoc} + */ + public function generate(EntityManager $em, $entity) + { + $conn = $em->getConnection(); + $sql = 'SELECT ' . $conn->getDatabasePlatform()->getGuidExpression(); + + return $conn->query($sql)->fetchColumn(0); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/CommitOrderCalculator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/CommitOrderCalculator.php new file mode 100644 index 0000000..30b9caa --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/CommitOrderCalculator.php @@ -0,0 +1,195 @@ +. + */ + +namespace Doctrine\ORM\Internal; + +/** + * CommitOrderCalculator implements topological sorting, which is an ordering + * algorithm for directed graphs (DG) and/or directed acyclic graphs (DAG) by + * using a depth-first searching (DFS) to traverse the graph built in memory. + * This algorithm have a linear running time based on nodes (V) and dependency + * between the nodes (E), resulting in a computational complexity of O(V + E). + * + * @since 2.0 + * @author Guilherme Blanco + * @author Roman Borschel + */ +class CommitOrderCalculator +{ + const NOT_VISITED = 0; + const IN_PROGRESS = 1; + const VISITED = 2; + + /** + * Matrix of nodes (aka. vertex). + * Keys are provided hashes and values are the node definition objects. + * + * The node state definition contains the following properties: + * + * - state (integer) + * Whether the node is NOT_VISITED or IN_PROGRESS + * + * - value (object) + * Actual node value + * + * - dependencyList (array) + * Map of node dependencies defined as hashes. + * + * @var array<\stdClass> + */ + private $nodeList = []; + + /** + * Volatile variable holding calculated nodes during sorting process. + * + * @var array + */ + private $sortedNodeList = []; + + /** + * Checks for node (vertex) existence in graph. + * + * @param string $hash + * + * @return boolean + */ + public function hasNode($hash) + { + return isset($this->nodeList[$hash]); + } + + /** + * Adds a new node (vertex) to the graph, assigning its hash and value. + * + * @param string $hash + * @param object $node + * + * @return void + */ + public function addNode($hash, $node) + { + $vertex = new \stdClass(); + + $vertex->hash = $hash; + $vertex->state = self::NOT_VISITED; + $vertex->value = $node; + $vertex->dependencyList = []; + + $this->nodeList[$hash] = $vertex; + } + + /** + * Adds a new dependency (edge) to the graph using their hashes. + * + * @param string $fromHash + * @param string $toHash + * @param integer $weight + * + * @return void + */ + public function addDependency($fromHash, $toHash, $weight) + { + $vertex = $this->nodeList[$fromHash]; + $edge = new \stdClass(); + + $edge->from = $fromHash; + $edge->to = $toHash; + $edge->weight = $weight; + + $vertex->dependencyList[$toHash] = $edge; + } + + /** + * Return a valid order list of all current nodes. + * The desired topological sorting is the reverse post order of these searches. + * + * {@internal Highly performance-sensitive method.} + * + * @return array + */ + public function sort() + { + foreach ($this->nodeList as $vertex) { + if ($vertex->state !== self::NOT_VISITED) { + continue; + } + + $this->visit($vertex); + } + + $sortedList = $this->sortedNodeList; + + $this->nodeList = []; + $this->sortedNodeList = []; + + return array_reverse($sortedList); + } + + /** + * Visit a given node definition for reordering. + * + * {@internal Highly performance-sensitive method.} + * + * @param \stdClass $vertex + */ + private function visit($vertex) + { + $vertex->state = self::IN_PROGRESS; + + foreach ($vertex->dependencyList as $edge) { + $adjacentVertex = $this->nodeList[$edge->to]; + + switch ($adjacentVertex->state) { + case self::VISITED: + // Do nothing, since node was already visited + break; + + case self::IN_PROGRESS: + if (isset($adjacentVertex->dependencyList[$vertex->hash]) && + $adjacentVertex->dependencyList[$vertex->hash]->weight < $edge->weight) { + + // If we have some non-visited dependencies in the in-progress dependency, we + // need to visit them before adding the node. + foreach ($adjacentVertex->dependencyList as $adjacentEdge) { + $adjacentEdgeVertex = $this->nodeList[$adjacentEdge->to]; + + if ($adjacentEdgeVertex->state === self::NOT_VISITED) { + $this->visit($adjacentEdgeVertex); + } + } + + $adjacentVertex->state = self::VISITED; + + $this->sortedNodeList[] = $adjacentVertex->value; + } + break; + + case self::NOT_VISITED: + $this->visit($adjacentVertex); + } + } + + if ($vertex->state !== self::VISITED) { + $vertex->state = self::VISITED; + + $this->sortedNodeList[] = $vertex->value; + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php new file mode 100644 index 0000000..8a9c0f4 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php @@ -0,0 +1,527 @@ +. + */ + +namespace Doctrine\ORM\Internal\Hydration; + +use Doctrine\DBAL\Types\Type; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Events; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Tools\Pagination\LimitSubqueryWalker; +use PDO; +use function array_map; +use function in_array; + +/** + * Base class for all hydrators. A hydrator is a class that provides some form + * of transformation of an SQL result set into another structure. + * + * @since 2.0 + * @author Konsta Vesterinen + * @author Roman Borschel + * @author Guilherme Blanco + */ +abstract class AbstractHydrator +{ + /** + * The ResultSetMapping. + * + * @var \Doctrine\ORM\Query\ResultSetMapping + */ + protected $_rsm; + + /** + * The EntityManager instance. + * + * @var EntityManagerInterface + */ + protected $_em; + + /** + * The dbms Platform instance. + * + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + protected $_platform; + + /** + * The UnitOfWork of the associated EntityManager. + * + * @var \Doctrine\ORM\UnitOfWork + */ + protected $_uow; + + /** + * Local ClassMetadata cache to avoid going to the EntityManager all the time. + * + * @var array + */ + protected $_metadataCache = []; + + /** + * The cache used during row-by-row hydration. + * + * @var array + */ + protected $_cache = []; + + /** + * The statement that provides the data to hydrate. + * + * @var \Doctrine\DBAL\Driver\Statement + */ + protected $_stmt; + + /** + * The query hints. + * + * @var array + */ + protected $_hints; + + /** + * Initializes a new instance of a class derived from AbstractHydrator. + * + * @param EntityManagerInterface $em The EntityManager to use. + */ + public function __construct(EntityManagerInterface $em) + { + $this->_em = $em; + $this->_platform = $em->getConnection()->getDatabasePlatform(); + $this->_uow = $em->getUnitOfWork(); + } + + /** + * Initiates a row-by-row hydration. + * + * @param object $stmt + * @param object $resultSetMapping + * @param array $hints + * + * @return IterableResult + */ + public function iterate($stmt, $resultSetMapping, array $hints = []) + { + $this->_stmt = $stmt; + $this->_rsm = $resultSetMapping; + $this->_hints = $hints; + + $evm = $this->_em->getEventManager(); + + $evm->addEventListener([Events::onClear], $this); + + $this->prepare(); + + return new IterableResult($this); + } + + /** + * Hydrates all rows returned by the passed statement instance at once. + * + * @param object $stmt + * @param object $resultSetMapping + * @param array $hints + * + * @return array + */ + public function hydrateAll($stmt, $resultSetMapping, array $hints = []) + { + $this->_stmt = $stmt; + $this->_rsm = $resultSetMapping; + $this->_hints = $hints; + + $this->_em->getEventManager()->addEventListener([Events::onClear], $this); + + $this->prepare(); + + $result = $this->hydrateAllData(); + + $this->cleanup(); + + return $result; + } + + /** + * Hydrates a single row returned by the current statement instance during + * row-by-row hydration with {@link iterate()}. + * + * @return mixed + */ + public function hydrateRow() + { + $row = $this->_stmt->fetch(PDO::FETCH_ASSOC); + + if ( ! $row) { + $this->cleanup(); + + return false; + } + + $result = []; + + $this->hydrateRowData($row, $result); + + return $result; + } + + /** + * When executed in a hydrate() loop we have to clear internal state to + * decrease memory consumption. + * + * @param mixed $eventArgs + * + * @return void + */ + public function onClear($eventArgs) + { + } + + /** + * Executes one-time preparation tasks, once each time hydration is started + * through {@link hydrateAll} or {@link iterate()}. + * + * @return void + */ + protected function prepare() + { + } + + /** + * Executes one-time cleanup tasks at the end of a hydration that was initiated + * through {@link hydrateAll} or {@link iterate()}. + * + * @return void + */ + protected function cleanup() + { + $this->_stmt->closeCursor(); + + $this->_stmt = null; + $this->_rsm = null; + $this->_cache = []; + $this->_metadataCache = []; + + $this + ->_em + ->getEventManager() + ->removeEventListener([Events::onClear], $this); + } + + /** + * Hydrates a single row from the current statement instance. + * + * Template method. + * + * @param array $data The row data. + * @param array $result The result to fill. + * + * @return void + * + * @throws HydrationException + */ + protected function hydrateRowData(array $data, array &$result) + { + throw new HydrationException("hydrateRowData() not implemented by this hydrator."); + } + + /** + * Hydrates all rows from the current statement instance at once. + * + * @return array + */ + abstract protected function hydrateAllData(); + + /** + * Processes a row of the result set. + * + * Used for identity-based hydration (HYDRATE_OBJECT and HYDRATE_ARRAY). + * Puts the elements of a result row into a new array, grouped by the dql alias + * they belong to. The column names in the result set are mapped to their + * field names during this procedure as well as any necessary conversions on + * the values applied. Scalar values are kept in a specific key 'scalars'. + * + * @param array $data SQL Result Row. + * @param array &$id Dql-Alias => ID-Hash. + * @param array &$nonemptyComponents Does this DQL-Alias has at least one non NULL value? + * + * @return array An array with all the fields (name => value) of the data row, + * grouped by their component alias. + */ + protected function gatherRowData(array $data, array &$id, array &$nonemptyComponents) + { + $rowData = ['data' => []]; + + foreach ($data as $key => $value) { + if (($cacheKeyInfo = $this->hydrateColumnInfo($key)) === null) { + continue; + } + + $fieldName = $cacheKeyInfo['fieldName']; + + switch (true) { + case (isset($cacheKeyInfo['isNewObjectParameter'])): + $argIndex = $cacheKeyInfo['argIndex']; + $objIndex = $cacheKeyInfo['objIndex']; + $type = $cacheKeyInfo['type']; + $value = $type->convertToPHPValue($value, $this->_platform); + + $rowData['newObjects'][$objIndex]['class'] = $cacheKeyInfo['class']; + $rowData['newObjects'][$objIndex]['args'][$argIndex] = $value; + break; + + case (isset($cacheKeyInfo['isScalar'])): + $type = $cacheKeyInfo['type']; + $value = $type->convertToPHPValue($value, $this->_platform); + + $rowData['scalars'][$fieldName] = $value; + break; + + //case (isset($cacheKeyInfo['isMetaColumn'])): + default: + $dqlAlias = $cacheKeyInfo['dqlAlias']; + $type = $cacheKeyInfo['type']; + + // If there are field name collisions in the child class, then we need + // to only hydrate if we are looking at the correct discriminator value + if (isset($cacheKeyInfo['discriminatorColumn'], $data[$cacheKeyInfo['discriminatorColumn']]) + && ! in_array((string) $data[$cacheKeyInfo['discriminatorColumn']], $cacheKeyInfo['discriminatorValues'], true) + ) { + break; + } + + // in an inheritance hierarchy the same field could be defined several times. + // We overwrite this value so long we don't have a non-null value, that value we keep. + // Per definition it cannot be that a field is defined several times and has several values. + if (isset($rowData['data'][$dqlAlias][$fieldName])) { + break; + } + + $rowData['data'][$dqlAlias][$fieldName] = $type + ? $type->convertToPHPValue($value, $this->_platform) + : $value; + + if ($cacheKeyInfo['isIdentifier'] && $value !== null) { + $id[$dqlAlias] .= '|' . $value; + $nonemptyComponents[$dqlAlias] = true; + } + break; + } + } + + return $rowData; + } + + /** + * Processes a row of the result set. + * + * Used for HYDRATE_SCALAR. This is a variant of _gatherRowData() that + * simply converts column names to field names and properly converts the + * values according to their types. The resulting row has the same number + * of elements as before. + * + * @param array $data + * + * @return array The processed row. + */ + protected function gatherScalarRowData(&$data) + { + $rowData = []; + + foreach ($data as $key => $value) { + if (($cacheKeyInfo = $this->hydrateColumnInfo($key)) === null) { + continue; + } + + $fieldName = $cacheKeyInfo['fieldName']; + + // WARNING: BC break! We know this is the desired behavior to type convert values, but this + // erroneous behavior exists since 2.0 and we're forced to keep compatibility. + if (! isset($cacheKeyInfo['isScalar'])) { + $type = $cacheKeyInfo['type']; + $value = $type ? $type->convertToPHPValue($value, $this->_platform) : $value; + + $fieldName = $cacheKeyInfo['dqlAlias'] . '_' . $fieldName; + } + + $rowData[$fieldName] = $value; + } + + return $rowData; + } + + /** + * Retrieve column information from ResultSetMapping. + * + * @param string $key Column name + * + * @return array|null + */ + protected function hydrateColumnInfo($key) + { + if (isset($this->_cache[$key])) { + return $this->_cache[$key]; + } + + switch (true) { + // NOTE: Most of the times it's a field mapping, so keep it first!!! + case (isset($this->_rsm->fieldMappings[$key])): + $classMetadata = $this->getClassMetadata($this->_rsm->declaringClasses[$key]); + $fieldName = $this->_rsm->fieldMappings[$key]; + $fieldMapping = $classMetadata->fieldMappings[$fieldName]; + $ownerMap = $this->_rsm->columnOwnerMap[$key]; + $columnInfo = [ + 'isIdentifier' => \in_array($fieldName, $classMetadata->identifier, true), + 'fieldName' => $fieldName, + 'type' => Type::getType($fieldMapping['type']), + 'dqlAlias' => $ownerMap, + ]; + + // the current discriminator value must be saved in order to disambiguate fields hydration, + // should there be field name collisions + if ($classMetadata->parentClasses && isset($this->_rsm->discriminatorColumns[$ownerMap])) { + return $this->_cache[$key] = \array_merge( + $columnInfo, + [ + 'discriminatorColumn' => $this->_rsm->discriminatorColumns[$ownerMap], + 'discriminatorValue' => $classMetadata->discriminatorValue, + 'discriminatorValues' => $this->getDiscriminatorValues($classMetadata), + ] + ); + } + + return $this->_cache[$key] = $columnInfo; + + case (isset($this->_rsm->newObjectMappings[$key])): + // WARNING: A NEW object is also a scalar, so it must be declared before! + $mapping = $this->_rsm->newObjectMappings[$key]; + + return $this->_cache[$key] = [ + 'isScalar' => true, + 'isNewObjectParameter' => true, + 'fieldName' => $this->_rsm->scalarMappings[$key], + 'type' => Type::getType($this->_rsm->typeMappings[$key]), + 'argIndex' => $mapping['argIndex'], + 'objIndex' => $mapping['objIndex'], + 'class' => new \ReflectionClass($mapping['className']), + ]; + + case isset($this->_rsm->scalarMappings[$key], $this->_hints[LimitSubqueryWalker::FORCE_DBAL_TYPE_CONVERSION]): + return $this->_cache[$key] = [ + 'fieldName' => $this->_rsm->scalarMappings[$key], + 'type' => Type::getType($this->_rsm->typeMappings[$key]), + 'dqlAlias' => '', + ]; + case (isset($this->_rsm->scalarMappings[$key])): + return $this->_cache[$key] = [ + 'isScalar' => true, + 'fieldName' => $this->_rsm->scalarMappings[$key], + 'type' => Type::getType($this->_rsm->typeMappings[$key]), + ]; + + case (isset($this->_rsm->metaMappings[$key])): + // Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns). + $fieldName = $this->_rsm->metaMappings[$key]; + $dqlAlias = $this->_rsm->columnOwnerMap[$key]; + $type = isset($this->_rsm->typeMappings[$key]) + ? Type::getType($this->_rsm->typeMappings[$key]) + : null; + + // Cache metadata fetch + $this->getClassMetadata($this->_rsm->aliasMap[$dqlAlias]); + + return $this->_cache[$key] = [ + 'isIdentifier' => isset($this->_rsm->isIdentifierColumn[$dqlAlias][$key]), + 'isMetaColumn' => true, + 'fieldName' => $fieldName, + 'type' => $type, + 'dqlAlias' => $dqlAlias, + ]; + } + + // this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2 + // maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping. + return null; + } + + /** + * @return string[] + */ + private function getDiscriminatorValues(ClassMetadata $classMetadata) : array + { + $values = array_map( + function (string $subClass) : string { + return (string) $this->getClassMetadata($subClass)->discriminatorValue; + }, + $classMetadata->subClasses + ); + + $values[] = (string) $classMetadata->discriminatorValue; + + return $values; + } + + /** + * Retrieve ClassMetadata associated to entity class name. + * + * @param string $className + * + * @return \Doctrine\ORM\Mapping\ClassMetadata + */ + protected function getClassMetadata($className) + { + if ( ! isset($this->_metadataCache[$className])) { + $this->_metadataCache[$className] = $this->_em->getClassMetadata($className); + } + + return $this->_metadataCache[$className]; + } + + /** + * Register entity as managed in UnitOfWork. + * + * @param ClassMetadata $class + * @param object $entity + * @param array $data + * + * @return void + * + * @todo The "$id" generation is the same of UnitOfWork#createEntity. Remove this duplication somehow + */ + protected function registerManaged(ClassMetadata $class, $entity, array $data) + { + if ($class->isIdentifierComposite) { + $id = []; + + foreach ($class->identifier as $fieldName) { + $id[$fieldName] = isset($class->associationMappings[$fieldName]) + ? $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']] + : $data[$fieldName]; + } + } else { + $fieldName = $class->identifier[0]; + $id = [ + $fieldName => isset($class->associationMappings[$fieldName]) + ? $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']] + : $data[$fieldName] + ]; + } + + $this->_em->getUnitOfWork()->registerManaged($entity, $id, $data); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php new file mode 100644 index 0000000..c26b99b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php @@ -0,0 +1,307 @@ +. + */ + +namespace Doctrine\ORM\Internal\Hydration; + +use PDO; +use Doctrine\ORM\Mapping\ClassMetadata; + +/** + * The ArrayHydrator produces a nested array "graph" that is often (not always) + * interchangeable with the corresponding object graph for read-only access. + * + * @since 2.0 + * @author Roman Borschel + * @author Guilherme Blanco + */ +class ArrayHydrator extends AbstractHydrator +{ + /** + * @var array + */ + private $_rootAliases = []; + + /** + * @var bool + */ + private $_isSimpleQuery = false; + + /** + * @var array + */ + private $_identifierMap = []; + + /** + * @var array + */ + private $_resultPointers = []; + + /** + * @var array + */ + private $_idTemplate = []; + + /** + * @var int + */ + private $_resultCounter = 0; + + /** + * {@inheritdoc} + */ + protected function prepare() + { + $this->_isSimpleQuery = count($this->_rsm->aliasMap) <= 1; + + foreach ($this->_rsm->aliasMap as $dqlAlias => $className) { + $this->_identifierMap[$dqlAlias] = []; + $this->_resultPointers[$dqlAlias] = []; + $this->_idTemplate[$dqlAlias] = ''; + } + } + + /** + * {@inheritdoc} + */ + protected function hydrateAllData() + { + $result = []; + + while ($data = $this->_stmt->fetch(PDO::FETCH_ASSOC)) { + $this->hydrateRowData($data, $result); + } + + return $result; + } + + /** + * {@inheritdoc} + */ + protected function hydrateRowData(array $row, array &$result) + { + // 1) Initialize + $id = $this->_idTemplate; // initialize the id-memory + $nonemptyComponents = []; + $rowData = $this->gatherRowData($row, $id, $nonemptyComponents); + + // 2) Now hydrate the data found in the current row. + foreach ($rowData['data'] as $dqlAlias => $data) { + $index = false; + + if (isset($this->_rsm->parentAliasMap[$dqlAlias])) { + // It's a joined result + + $parent = $this->_rsm->parentAliasMap[$dqlAlias]; + $path = $parent . '.' . $dqlAlias; + + // missing parent data, skipping as RIGHT JOIN hydration is not supported. + if ( ! isset($nonemptyComponents[$parent]) ) { + continue; + } + + // Get a reference to the right element in the result tree. + // This element will get the associated element attached. + if ($this->_rsm->isMixed && isset($this->_rootAliases[$parent])) { + $first = reset($this->_resultPointers); + // TODO: Exception if $key === null ? + $baseElement =& $this->_resultPointers[$parent][key($first)]; + } else if (isset($this->_resultPointers[$parent])) { + $baseElement =& $this->_resultPointers[$parent]; + } else { + unset($this->_resultPointers[$dqlAlias]); // Ticket #1228 + + continue; + } + + $relationAlias = $this->_rsm->relationMap[$dqlAlias]; + $parentClass = $this->_metadataCache[$this->_rsm->aliasMap[$parent]]; + $relation = $parentClass->associationMappings[$relationAlias]; + + // Check the type of the relation (many or single-valued) + if ( ! ($relation['type'] & ClassMetadata::TO_ONE)) { + $oneToOne = false; + + if ( ! isset($baseElement[$relationAlias])) { + $baseElement[$relationAlias] = []; + } + + if (isset($nonemptyComponents[$dqlAlias])) { + $indexExists = isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]); + $index = $indexExists ? $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false; + $indexIsValid = $index !== false ? isset($baseElement[$relationAlias][$index]) : false; + + if ( ! $indexExists || ! $indexIsValid) { + $element = $data; + + if (isset($this->_rsm->indexByMap[$dqlAlias])) { + $baseElement[$relationAlias][$row[$this->_rsm->indexByMap[$dqlAlias]]] = $element; + } else { + $baseElement[$relationAlias][] = $element; + } + + end($baseElement[$relationAlias]); + + $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = key($baseElement[$relationAlias]); + } + } + } else { + $oneToOne = true; + + if ( + ( ! isset($nonemptyComponents[$dqlAlias])) && + ( ! isset($baseElement[$relationAlias])) + ) { + $baseElement[$relationAlias] = null; + } else if ( ! isset($baseElement[$relationAlias])) { + $baseElement[$relationAlias] = $data; + } + } + + $coll =& $baseElement[$relationAlias]; + + if (is_array($coll)) { + $this->updateResultPointer($coll, $index, $dqlAlias, $oneToOne); + } + } else { + // It's a root result element + + $this->_rootAliases[$dqlAlias] = true; // Mark as root + $entityKey = $this->_rsm->entityMappings[$dqlAlias] ?: 0; + + // if this row has a NULL value for the root result id then make it a null result. + if ( ! isset($nonemptyComponents[$dqlAlias]) ) { + $result[] = $this->_rsm->isMixed + ? [$entityKey => null] + : null; + + $resultKey = $this->_resultCounter; + ++$this->_resultCounter; + + continue; + } + + // Check for an existing element + if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) { + $element = $this->_rsm->isMixed + ? [$entityKey => $data] + : $data; + + if (isset($this->_rsm->indexByMap[$dqlAlias])) { + $resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]]; + $result[$resultKey] = $element; + } else { + $resultKey = $this->_resultCounter; + $result[] = $element; + + ++$this->_resultCounter; + } + + $this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $resultKey; + } else { + $index = $this->_identifierMap[$dqlAlias][$id[$dqlAlias]]; + $resultKey = $index; + } + + $this->updateResultPointer($result, $index, $dqlAlias, false); + } + } + + if ( ! isset($resultKey)) { + $this->_resultCounter++; + } + + // Append scalar values to mixed result sets + if (isset($rowData['scalars'])) { + if ( ! isset($resultKey)) { + // this only ever happens when no object is fetched (scalar result only) + $resultKey = isset($this->_rsm->indexByMap['scalars']) + ? $row[$this->_rsm->indexByMap['scalars']] + : $this->_resultCounter - 1; + } + + foreach ($rowData['scalars'] as $name => $value) { + $result[$resultKey][$name] = $value; + } + } + + // Append new object to mixed result sets + if (isset($rowData['newObjects'])) { + if ( ! isset($resultKey)) { + $resultKey = $this->_resultCounter - 1; + } + + $scalarCount = (isset($rowData['scalars'])? count($rowData['scalars']): 0); + + foreach ($rowData['newObjects'] as $objIndex => $newObject) { + $class = $newObject['class']; + $args = $newObject['args']; + $obj = $class->newInstanceArgs($args); + + if (count($args) == $scalarCount || ($scalarCount == 0 && count($rowData['newObjects']) == 1)) { + $result[$resultKey] = $obj; + + continue; + } + + $result[$resultKey][$objIndex] = $obj; + } + } + } + + /** + * Updates the result pointer for an Entity. The result pointers point to the + * last seen instance of each Entity type. This is used for graph construction. + * + * @param array $coll The element. + * @param boolean|integer $index Index of the element in the collection. + * @param string $dqlAlias + * @param boolean $oneToOne Whether it is a single-valued association or not. + * + * @return void + */ + private function updateResultPointer(array &$coll, $index, $dqlAlias, $oneToOne) + { + if ($coll === null) { + unset($this->_resultPointers[$dqlAlias]); // Ticket #1228 + + return; + } + + if ($oneToOne) { + $this->_resultPointers[$dqlAlias] =& $coll; + + return; + } + + if ($index !== false) { + $this->_resultPointers[$dqlAlias] =& $coll[$index]; + + return; + } + + if ( ! $coll) { + return; + } + + end($coll); + $this->_resultPointers[$dqlAlias] =& $coll[key($coll)]; + + return; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/HydrationException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/HydrationException.php new file mode 100644 index 0000000..9caf03d --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/HydrationException.php @@ -0,0 +1,105 @@ +. + */ + +namespace Doctrine\ORM\Internal\Hydration; + +class HydrationException extends \Doctrine\ORM\ORMException +{ + /** + * @return HydrationException + */ + public static function nonUniqueResult() + { + return new self("The result returned by the query was not unique."); + } + + /** + * @param string $alias + * @param string $parentAlias + * + * @return HydrationException + */ + public static function parentObjectOfRelationNotFound($alias, $parentAlias) + { + return new self("The parent object of entity result with alias '$alias' was not found." + . " The parent alias is '$parentAlias'."); + } + + /** + * @param string $dqlAlias + * + * @return HydrationException + */ + public static function emptyDiscriminatorValue($dqlAlias) + { + return new self("The DQL alias '" . $dqlAlias . "' contains an entity ". + "of an inheritance hierarchy with an empty discriminator value. This means " . + "that the database contains inconsistent data with an empty " . + "discriminator value in a table row." + ); + } + + /** + * @since 2.3 + * + * @param string $entityName + * @param string $discrColumnName + * @param string $dqlAlias + * + * @return HydrationException + */ + public static function missingDiscriminatorColumn($entityName, $discrColumnName, $dqlAlias) + { + return new self(sprintf( + 'The discriminator column "%s" is missing for "%s" using the DQL alias "%s".', + $discrColumnName, $entityName, $dqlAlias + )); + } + + /** + * @since 2.3 + * + * @param string $entityName + * @param string $discrColumnName + * @param string $dqlAlias + * + * @return HydrationException + */ + public static function missingDiscriminatorMetaMappingColumn($entityName, $discrColumnName, $dqlAlias) + { + return new self(sprintf( + 'The meta mapping for the discriminator column "%s" is missing for "%s" using the DQL alias "%s".', + $discrColumnName, $entityName, $dqlAlias + )); + } + + /** + * @param string $discrValue + * @param array $discrMap + * + * @return HydrationException + */ + public static function invalidDiscriminatorValue($discrValue, $discrMap) + { + return new self(sprintf( + 'The discriminator value "%s" is invalid. It must be one of "%s".', + $discrValue, implode('", "', $discrMap) + )); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/IterableResult.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/IterableResult.php new file mode 100644 index 0000000..1774ca0 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/IterableResult.php @@ -0,0 +1,110 @@ +. + */ + +namespace Doctrine\ORM\Internal\Hydration; + +/** + * Represents a result structure that can be iterated over, hydrating row-by-row + * during the iteration. An IterableResult is obtained by AbstractHydrator#iterate(). + * + * @author robo + * @since 2.0 + */ +class IterableResult implements \Iterator +{ + /** + * @var \Doctrine\ORM\Internal\Hydration\AbstractHydrator + */ + private $_hydrator; + + /** + * @var boolean + */ + private $_rewinded = false; + + /** + * @var integer + */ + private $_key = -1; + + /** + * @var object|null + */ + private $_current = null; + + /** + * @param \Doctrine\ORM\Internal\Hydration\AbstractHydrator $hydrator + */ + public function __construct($hydrator) + { + $this->_hydrator = $hydrator; + } + + /** + * @return void + * + * @throws HydrationException + */ + public function rewind() + { + if ($this->_rewinded == true) { + throw new HydrationException("Can only iterate a Result once."); + } else { + $this->_current = $this->next(); + $this->_rewinded = true; + } + } + + /** + * Gets the next set of results. + * + * @return array|false + */ + public function next() + { + $this->_current = $this->_hydrator->hydrateRow(); + $this->_key++; + + return $this->_current; + } + + /** + * @return mixed + */ + public function current() + { + return $this->_current; + } + + /** + * @return int + */ + public function key() + { + return $this->_key; + } + + /** + * @return bool + */ + public function valid() + { + return ($this->_current!=false); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php new file mode 100644 index 0000000..5048216 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php @@ -0,0 +1,593 @@ +. + */ + +namespace Doctrine\ORM\Internal\Hydration; + +use Doctrine\ORM\UnitOfWork; +use PDO; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\PersistentCollection; +use Doctrine\ORM\Query; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\ORM\Proxy\Proxy; + +/** + * The ObjectHydrator constructs an object graph out of an SQL result set. + * + * Internal note: Highly performance-sensitive code. + * + * @since 2.0 + * @author Roman Borschel + * @author Guilherme Blanco + * @author Fabio B. Silva + */ +class ObjectHydrator extends AbstractHydrator +{ + /** + * @var array + */ + private $identifierMap = []; + + /** + * @var array + */ + private $resultPointers = []; + + /** + * @var array + */ + private $idTemplate = []; + + /** + * @var integer + */ + private $resultCounter = 0; + + /** + * @var array + */ + private $rootAliases = []; + + /** + * @var array + */ + private $initializedCollections = []; + + /** + * @var array + */ + private $existingCollections = []; + + /** + * {@inheritdoc} + */ + protected function prepare() + { + if ( ! isset($this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD])) { + $this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD] = true; + } + + foreach ($this->_rsm->aliasMap as $dqlAlias => $className) { + $this->identifierMap[$dqlAlias] = []; + $this->idTemplate[$dqlAlias] = ''; + + // Remember which associations are "fetch joined", so that we know where to inject + // collection stubs or proxies and where not. + if ( ! isset($this->_rsm->relationMap[$dqlAlias])) { + continue; + } + + $parent = $this->_rsm->parentAliasMap[$dqlAlias]; + + if ( ! isset($this->_rsm->aliasMap[$parent])) { + throw HydrationException::parentObjectOfRelationNotFound($dqlAlias, $parent); + } + + $sourceClassName = $this->_rsm->aliasMap[$parent]; + $sourceClass = $this->getClassMetadata($sourceClassName); + $assoc = $sourceClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]]; + + $this->_hints['fetched'][$parent][$assoc['fieldName']] = true; + + if ($assoc['type'] === ClassMetadata::MANY_TO_MANY) { + continue; + } + + // Mark any non-collection opposite sides as fetched, too. + if ($assoc['mappedBy']) { + $this->_hints['fetched'][$dqlAlias][$assoc['mappedBy']] = true; + + continue; + } + + // handle fetch-joined owning side bi-directional one-to-one associations + if ($assoc['inversedBy']) { + $class = $this->getClassMetadata($className); + $inverseAssoc = $class->associationMappings[$assoc['inversedBy']]; + + if ( ! ($inverseAssoc['type'] & ClassMetadata::TO_ONE)) { + continue; + } + + $this->_hints['fetched'][$dqlAlias][$inverseAssoc['fieldName']] = true; + } + } + } + + /** + * {@inheritdoc} + */ + protected function cleanup() + { + $eagerLoad = (isset($this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD])) && $this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD] == true; + + parent::cleanup(); + + $this->identifierMap = + $this->initializedCollections = + $this->existingCollections = + $this->resultPointers = []; + + if ($eagerLoad) { + $this->_uow->triggerEagerLoads(); + } + + $this->_uow->hydrationComplete(); + } + + /** + * {@inheritdoc} + */ + protected function hydrateAllData() + { + $result = []; + + while ($row = $this->_stmt->fetch(PDO::FETCH_ASSOC)) { + $this->hydrateRowData($row, $result); + } + + // Take snapshots from all newly initialized collections + foreach ($this->initializedCollections as $coll) { + $coll->takeSnapshot(); + } + + return $result; + } + + /** + * Initializes a related collection. + * + * @param object $entity The entity to which the collection belongs. + * @param ClassMetadata $class + * @param string $fieldName The name of the field on the entity that holds the collection. + * @param string $parentDqlAlias Alias of the parent fetch joining this collection. + * + * @return \Doctrine\ORM\PersistentCollection + */ + private function initRelatedCollection($entity, $class, $fieldName, $parentDqlAlias) + { + $oid = spl_object_hash($entity); + $relation = $class->associationMappings[$fieldName]; + $value = $class->reflFields[$fieldName]->getValue($entity); + + if ($value === null || is_array($value)) { + $value = new ArrayCollection((array) $value); + } + + if ( ! $value instanceof PersistentCollection) { + $value = new PersistentCollection( + $this->_em, $this->_metadataCache[$relation['targetEntity']], $value + ); + $value->setOwner($entity, $relation); + + $class->reflFields[$fieldName]->setValue($entity, $value); + $this->_uow->setOriginalEntityProperty($oid, $fieldName, $value); + + $this->initializedCollections[$oid . $fieldName] = $value; + } else if ( + isset($this->_hints[Query::HINT_REFRESH]) || + isset($this->_hints['fetched'][$parentDqlAlias][$fieldName]) && + ! $value->isInitialized() + ) { + // Is already PersistentCollection, but either REFRESH or FETCH-JOIN and UNINITIALIZED! + $value->setDirty(false); + $value->setInitialized(true); + $value->unwrap()->clear(); + + $this->initializedCollections[$oid . $fieldName] = $value; + } else { + // Is already PersistentCollection, and DON'T REFRESH or FETCH-JOIN! + $this->existingCollections[$oid . $fieldName] = $value; + } + + return $value; + } + + /** + * Gets an entity instance. + * + * @param array $data The instance data. + * @param string $dqlAlias The DQL alias of the entity's class. + * + * @return object The entity. + * + * @throws HydrationException + */ + private function getEntity(array $data, $dqlAlias) + { + $className = $this->_rsm->aliasMap[$dqlAlias]; + + if (isset($this->_rsm->discriminatorColumns[$dqlAlias])) { + $fieldName = $this->_rsm->discriminatorColumns[$dqlAlias]; + + if ( ! isset($this->_rsm->metaMappings[$fieldName])) { + throw HydrationException::missingDiscriminatorMetaMappingColumn($className, $fieldName, $dqlAlias); + } + + $discrColumn = $this->_rsm->metaMappings[$fieldName]; + + if ( ! isset($data[$discrColumn])) { + throw HydrationException::missingDiscriminatorColumn($className, $discrColumn, $dqlAlias); + } + + if ($data[$discrColumn] === "") { + throw HydrationException::emptyDiscriminatorValue($dqlAlias); + } + + $discrMap = $this->_metadataCache[$className]->discriminatorMap; + $discriminatorValue = (string) $data[$discrColumn]; + + if ( ! isset($discrMap[$discriminatorValue])) { + throw HydrationException::invalidDiscriminatorValue($discriminatorValue, array_keys($discrMap)); + } + + $className = $discrMap[$discriminatorValue]; + + unset($data[$discrColumn]); + } + + if (isset($this->_hints[Query::HINT_REFRESH_ENTITY]) && isset($this->rootAliases[$dqlAlias])) { + $this->registerManaged($this->_metadataCache[$className], $this->_hints[Query::HINT_REFRESH_ENTITY], $data); + } + + $this->_hints['fetchAlias'] = $dqlAlias; + + return $this->_uow->createEntity($className, $data, $this->_hints); + } + + /** + * @param string $className + * @param array $data + * + * @return mixed + */ + private function getEntityFromIdentityMap($className, array $data) + { + // TODO: Abstract this code and UnitOfWork::createEntity() equivalent? + $class = $this->_metadataCache[$className]; + + /* @var $class ClassMetadata */ + if ($class->isIdentifierComposite) { + $idHash = ''; + + foreach ($class->identifier as $fieldName) { + $idHash .= ' ' . (isset($class->associationMappings[$fieldName]) + ? $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']] + : $data[$fieldName]); + } + + return $this->_uow->tryGetByIdHash(ltrim($idHash), $class->rootEntityName); + } else if (isset($class->associationMappings[$class->identifier[0]])) { + return $this->_uow->tryGetByIdHash($data[$class->associationMappings[$class->identifier[0]]['joinColumns'][0]['name']], $class->rootEntityName); + } + + return $this->_uow->tryGetByIdHash($data[$class->identifier[0]], $class->rootEntityName); + } + + /** + * Hydrates a single row in an SQL result set. + * + * @internal + * First, the data of the row is split into chunks where each chunk contains data + * that belongs to a particular component/class. Afterwards, all these chunks + * are processed, one after the other. For each chunk of class data only one of the + * following code paths is executed: + * + * Path A: The data chunk belongs to a joined/associated object and the association + * is collection-valued. + * Path B: The data chunk belongs to a joined/associated object and the association + * is single-valued. + * Path C: The data chunk belongs to a root result element/object that appears in the topmost + * level of the hydrated result. A typical example are the objects of the type + * specified by the FROM clause in a DQL query. + * + * @param array $row The data of the row to process. + * @param array $result The result array to fill. + * + * @return void + */ + protected function hydrateRowData(array $row, array &$result) + { + // Initialize + $id = $this->idTemplate; // initialize the id-memory + $nonemptyComponents = []; + // Split the row data into chunks of class data. + $rowData = $this->gatherRowData($row, $id, $nonemptyComponents); + + // reset result pointers for each data row + $this->resultPointers = []; + + // Hydrate the data chunks + foreach ($rowData['data'] as $dqlAlias => $data) { + $entityName = $this->_rsm->aliasMap[$dqlAlias]; + + if (isset($this->_rsm->parentAliasMap[$dqlAlias])) { + // It's a joined result + + $parentAlias = $this->_rsm->parentAliasMap[$dqlAlias]; + // we need the $path to save into the identifier map which entities were already + // seen for this parent-child relationship + $path = $parentAlias . '.' . $dqlAlias; + + // We have a RIGHT JOIN result here. Doctrine cannot hydrate RIGHT JOIN Object-Graphs + if ( ! isset($nonemptyComponents[$parentAlias])) { + // TODO: Add special case code where we hydrate the right join objects into identity map at least + continue; + } + + $parentClass = $this->_metadataCache[$this->_rsm->aliasMap[$parentAlias]]; + $relationField = $this->_rsm->relationMap[$dqlAlias]; + $relation = $parentClass->associationMappings[$relationField]; + $reflField = $parentClass->reflFields[$relationField]; + + // Get a reference to the parent object to which the joined element belongs. + if ($this->_rsm->isMixed && isset($this->rootAliases[$parentAlias])) { + $objectClass = $this->resultPointers[$parentAlias]; + $parentObject = $objectClass[key($objectClass)]; + } else if (isset($this->resultPointers[$parentAlias])) { + $parentObject = $this->resultPointers[$parentAlias]; + } else { + // Parent object of relation not found, mark as not-fetched again + $element = $this->getEntity($data, $dqlAlias); + + // Update result pointer and provide initial fetch data for parent + $this->resultPointers[$dqlAlias] = $element; + $rowData['data'][$parentAlias][$relationField] = $element; + + // Mark as not-fetched again + unset($this->_hints['fetched'][$parentAlias][$relationField]); + continue; + } + + $oid = spl_object_hash($parentObject); + + // Check the type of the relation (many or single-valued) + if ( ! ($relation['type'] & ClassMetadata::TO_ONE)) { + // PATH A: Collection-valued association + $reflFieldValue = $reflField->getValue($parentObject); + + if (isset($nonemptyComponents[$dqlAlias])) { + $collKey = $oid . $relationField; + if (isset($this->initializedCollections[$collKey])) { + $reflFieldValue = $this->initializedCollections[$collKey]; + } else if ( ! isset($this->existingCollections[$collKey])) { + $reflFieldValue = $this->initRelatedCollection($parentObject, $parentClass, $relationField, $parentAlias); + } + + $indexExists = isset($this->identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]]); + $index = $indexExists ? $this->identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] : false; + $indexIsValid = $index !== false ? isset($reflFieldValue[$index]) : false; + + if ( ! $indexExists || ! $indexIsValid) { + if (isset($this->existingCollections[$collKey])) { + // Collection exists, only look for the element in the identity map. + if ($element = $this->getEntityFromIdentityMap($entityName, $data)) { + $this->resultPointers[$dqlAlias] = $element; + } else { + unset($this->resultPointers[$dqlAlias]); + } + } else { + $element = $this->getEntity($data, $dqlAlias); + + if (isset($this->_rsm->indexByMap[$dqlAlias])) { + $indexValue = $row[$this->_rsm->indexByMap[$dqlAlias]]; + $reflFieldValue->hydrateSet($indexValue, $element); + $this->identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] = $indexValue; + } else { + $reflFieldValue->hydrateAdd($element); + $reflFieldValue->last(); + $this->identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] = $reflFieldValue->key(); + } + // Update result pointer + $this->resultPointers[$dqlAlias] = $element; + } + } else { + // Update result pointer + $this->resultPointers[$dqlAlias] = $reflFieldValue[$index]; + } + } else if ( ! $reflFieldValue) { + $this->initRelatedCollection($parentObject, $parentClass, $relationField, $parentAlias); + } else if ($reflFieldValue instanceof PersistentCollection && $reflFieldValue->isInitialized() === false) { + $reflFieldValue->setInitialized(true); + } + + } else { + // PATH B: Single-valued association + $reflFieldValue = $reflField->getValue($parentObject); + + if ( ! $reflFieldValue || isset($this->_hints[Query::HINT_REFRESH]) || ($reflFieldValue instanceof Proxy && !$reflFieldValue->__isInitialized__)) { + // we only need to take action if this value is null, + // we refresh the entity or its an uninitialized proxy. + if (isset($nonemptyComponents[$dqlAlias])) { + $element = $this->getEntity($data, $dqlAlias); + $reflField->setValue($parentObject, $element); + $this->_uow->setOriginalEntityProperty($oid, $relationField, $element); + $targetClass = $this->_metadataCache[$relation['targetEntity']]; + + if ($relation['isOwningSide']) { + // TODO: Just check hints['fetched'] here? + // If there is an inverse mapping on the target class its bidirectional + if ($relation['inversedBy']) { + $inverseAssoc = $targetClass->associationMappings[$relation['inversedBy']]; + if ($inverseAssoc['type'] & ClassMetadata::TO_ONE) { + $targetClass->reflFields[$inverseAssoc['fieldName']]->setValue($element, $parentObject); + $this->_uow->setOriginalEntityProperty(spl_object_hash($element), $inverseAssoc['fieldName'], $parentObject); + } + } else if ($parentClass === $targetClass && $relation['mappedBy']) { + // Special case: bi-directional self-referencing one-one on the same class + $targetClass->reflFields[$relationField]->setValue($element, $parentObject); + } + } else { + // For sure bidirectional, as there is no inverse side in unidirectional mappings + $targetClass->reflFields[$relation['mappedBy']]->setValue($element, $parentObject); + $this->_uow->setOriginalEntityProperty(spl_object_hash($element), $relation['mappedBy'], $parentObject); + } + // Update result pointer + $this->resultPointers[$dqlAlias] = $element; + } else { + $this->_uow->setOriginalEntityProperty($oid, $relationField, null); + $reflField->setValue($parentObject, null); + } + // else leave $reflFieldValue null for single-valued associations + } else { + // Update result pointer + $this->resultPointers[$dqlAlias] = $reflFieldValue; + } + } + } else { + // PATH C: Its a root result element + $this->rootAliases[$dqlAlias] = true; // Mark as root alias + $entityKey = $this->_rsm->entityMappings[$dqlAlias] ?: 0; + + // if this row has a NULL value for the root result id then make it a null result. + if ( ! isset($nonemptyComponents[$dqlAlias]) ) { + if ($this->_rsm->isMixed) { + $result[] = [$entityKey => null]; + } else { + $result[] = null; + } + $resultKey = $this->resultCounter; + ++$this->resultCounter; + continue; + } + + // check for existing result from the iterations before + if ( ! isset($this->identifierMap[$dqlAlias][$id[$dqlAlias]])) { + $element = $this->getEntity($data, $dqlAlias); + + if ($this->_rsm->isMixed) { + $element = [$entityKey => $element]; + } + + if (isset($this->_rsm->indexByMap[$dqlAlias])) { + $resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]]; + + if (isset($this->_hints['collection'])) { + $this->_hints['collection']->hydrateSet($resultKey, $element); + } + + $result[$resultKey] = $element; + } else { + $resultKey = $this->resultCounter; + ++$this->resultCounter; + + if (isset($this->_hints['collection'])) { + $this->_hints['collection']->hydrateAdd($element); + } + + $result[] = $element; + } + + $this->identifierMap[$dqlAlias][$id[$dqlAlias]] = $resultKey; + + // Update result pointer + $this->resultPointers[$dqlAlias] = $element; + + } else { + // Update result pointer + $index = $this->identifierMap[$dqlAlias][$id[$dqlAlias]]; + $this->resultPointers[$dqlAlias] = $result[$index]; + $resultKey = $index; + } + } + + if (isset($this->_hints[Query::HINT_INTERNAL_ITERATION]) && $this->_hints[Query::HINT_INTERNAL_ITERATION]) { + $this->_uow->hydrationComplete(); + } + } + + if ( ! isset($resultKey) ) { + $this->resultCounter++; + } + + // Append scalar values to mixed result sets + if (isset($rowData['scalars'])) { + if ( ! isset($resultKey) ) { + $resultKey = (isset($this->_rsm->indexByMap['scalars'])) + ? $row[$this->_rsm->indexByMap['scalars']] + : $this->resultCounter - 1; + } + + foreach ($rowData['scalars'] as $name => $value) { + $result[$resultKey][$name] = $value; + } + } + + // Append new object to mixed result sets + if (isset($rowData['newObjects'])) { + if ( ! isset($resultKey) ) { + $resultKey = $this->resultCounter - 1; + } + + + $scalarCount = (isset($rowData['scalars'])? count($rowData['scalars']): 0); + + foreach ($rowData['newObjects'] as $objIndex => $newObject) { + $class = $newObject['class']; + $args = $newObject['args']; + $obj = $class->newInstanceArgs($args); + + if ($scalarCount == 0 && count($rowData['newObjects']) == 1 ) { + $result[$resultKey] = $obj; + + continue; + } + + $result[$resultKey][$objIndex] = $obj; + } + } + } + + /** + * When executed in a hydrate() loop we may have to clear internal state to + * decrease memory consumption. + * + * @param mixed $eventArgs + * + * @return void + */ + public function onClear($eventArgs) + { + parent::onClear($eventArgs); + + $aliases = array_keys($this->identifierMap); + + $this->identifierMap = array_fill_keys($aliases, []); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ScalarHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ScalarHydrator.php new file mode 100644 index 0000000..093e89c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ScalarHydrator.php @@ -0,0 +1,54 @@ +. + */ + +namespace Doctrine\ORM\Internal\Hydration; + +/** + * Hydrator that produces flat, rectangular results of scalar data. + * The created result is almost the same as a regular SQL result set, except + * that column names are mapped to field names and data type conversions take place. + * + * @since 2.0 + * @author Roman Borschel + * @author Guilherme Blanco + */ +class ScalarHydrator extends AbstractHydrator +{ + /** + * {@inheritdoc} + */ + protected function hydrateAllData() + { + $result = []; + + while ($data = $this->_stmt->fetch(\PDO::FETCH_ASSOC)) { + $this->hydrateRowData($data, $result); + } + + return $result; + } + + /** + * {@inheritdoc} + */ + protected function hydrateRowData(array $data, array &$result) + { + $result[] = $this->gatherScalarRowData($data); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php new file mode 100644 index 0000000..bf2beab --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php @@ -0,0 +1,154 @@ +. + */ + +namespace Doctrine\ORM\Internal\Hydration; + +use PDO; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Query; + +class SimpleObjectHydrator extends AbstractHydrator +{ + /** + * @var ClassMetadata + */ + private $class; + + /** + * {@inheritdoc} + */ + protected function prepare() + { + if (count($this->_rsm->aliasMap) !== 1) { + throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping that contains more than one object result."); + } + + if ($this->_rsm->scalarMappings) { + throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping that contains scalar mappings."); + } + + $this->class = $this->getClassMetadata(reset($this->_rsm->aliasMap)); + } + + /** + * {@inheritdoc} + */ + protected function cleanup() + { + parent::cleanup(); + + $this->_uow->triggerEagerLoads(); + $this->_uow->hydrationComplete(); + } + + /** + * {@inheritdoc} + */ + protected function hydrateAllData() + { + $result = []; + + while ($row = $this->_stmt->fetch(PDO::FETCH_ASSOC)) { + $this->hydrateRowData($row, $result); + } + + $this->_em->getUnitOfWork()->triggerEagerLoads(); + + return $result; + } + + /** + * {@inheritdoc} + */ + protected function hydrateRowData(array $sqlResult, array &$result) + { + $entityName = $this->class->name; + $data = []; + + // We need to find the correct entity class name if we have inheritance in resultset + if ($this->class->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) { + $discrColumnName = $this->_platform->getSQLResultCasing($this->class->discriminatorColumn['name']); + + // Find mapped discriminator column from the result set. + if ($metaMappingDiscrColumnName = array_search($discrColumnName, $this->_rsm->metaMappings)) { + $discrColumnName = $metaMappingDiscrColumnName; + } + + if ( ! isset($sqlResult[$discrColumnName])) { + throw HydrationException::missingDiscriminatorColumn($entityName, $discrColumnName, key($this->_rsm->aliasMap)); + } + + if ($sqlResult[$discrColumnName] === '') { + throw HydrationException::emptyDiscriminatorValue(key($this->_rsm->aliasMap)); + } + + $discrMap = $this->class->discriminatorMap; + + if ( ! isset($discrMap[$sqlResult[$discrColumnName]])) { + throw HydrationException::invalidDiscriminatorValue($sqlResult[$discrColumnName], array_keys($discrMap)); + } + + $entityName = $discrMap[$sqlResult[$discrColumnName]]; + + unset($sqlResult[$discrColumnName]); + } + + foreach ($sqlResult as $column => $value) { + // An ObjectHydrator should be used instead of SimpleObjectHydrator + if (isset($this->_rsm->relationMap[$column])) { + throw new \Exception(sprintf('Unable to retrieve association information for column "%s"', $column)); + } + + $cacheKeyInfo = $this->hydrateColumnInfo($column); + + if ( ! $cacheKeyInfo) { + continue; + } + + // Check if value is null before conversion (because some types convert null to something else) + $valueIsNull = null === $value; + + // Convert field to a valid PHP value + if (isset($cacheKeyInfo['type'])) { + $type = $cacheKeyInfo['type']; + $value = $type->convertToPHPValue($value, $this->_platform); + } + + $fieldName = $cacheKeyInfo['fieldName']; + + // Prevent overwrite in case of inherit classes using same property name (See AbstractHydrator) + if ( ! isset($data[$fieldName]) || ! $valueIsNull) { + $data[$fieldName] = $value; + } + } + + if (isset($this->_hints[Query::HINT_REFRESH_ENTITY])) { + $this->registerManaged($this->class, $this->_hints[Query::HINT_REFRESH_ENTITY], $data); + } + + $uow = $this->_em->getUnitOfWork(); + $entity = $uow->createEntity($entityName, $data, $this->_hints); + + $result[] = $entity; + + if (isset($this->_hints[Query::HINT_INTERNAL_ITERATION]) && $this->_hints[Query::HINT_INTERNAL_ITERATION]) { + $this->_uow->hydrationComplete(); + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php new file mode 100644 index 0000000..b9caeb1 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php @@ -0,0 +1,58 @@ +. + */ + +namespace Doctrine\ORM\Internal\Hydration; + +use Doctrine\ORM\NoResultException; +use Doctrine\ORM\NonUniqueResultException; + +/** + * Hydrator that hydrates a single scalar value from the result set. + * + * @since 2.0 + * @author Roman Borschel + * @author Guilherme Blanco + */ +class SingleScalarHydrator extends AbstractHydrator +{ + /** + * {@inheritdoc} + */ + protected function hydrateAllData() + { + $data = $this->_stmt->fetchAll(\PDO::FETCH_ASSOC); + $numRows = count($data); + + if ($numRows === 0) { + throw new NoResultException(); + } + + if ($numRows > 1) { + throw new NonUniqueResultException('The query returned multiple rows. Change the query or use a different result function like getScalarResult().'); + } + + if (count($data[key($data)]) > 1) { + throw new NonUniqueResultException('The query returned a row containing multiple columns. Change the query or use a different result function like getScalarResult().'); + } + + $result = $this->gatherScalarRowData($data[key($data)]); + + return array_shift($result); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/HydrationCompleteHandler.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/HydrationCompleteHandler.php new file mode 100644 index 0000000..72a0c70 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/HydrationCompleteHandler.php @@ -0,0 +1,103 @@ +. + */ + +namespace Doctrine\ORM\Internal; + +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Event\LifecycleEventArgs; +use Doctrine\ORM\Event\ListenersInvoker; +use Doctrine\ORM\Events; +use Doctrine\ORM\Mapping\ClassMetadata; + +/** + * Class, which can handle completion of hydration cycle and produce some of tasks. + * In current implementation triggers deferred postLoad event. + * + * @author Artur Eshenbrener + * @since 2.5 + */ +final class HydrationCompleteHandler +{ + /** + * @var ListenersInvoker + */ + private $listenersInvoker; + + /** + * @var EntityManagerInterface + */ + private $em; + + /** + * @var array[] + */ + private $deferredPostLoadInvocations = []; + + /** + * Constructor for this object + * + * @param ListenersInvoker $listenersInvoker + * @param EntityManagerInterface $em + */ + public function __construct(ListenersInvoker $listenersInvoker, EntityManagerInterface $em) + { + $this->listenersInvoker = $listenersInvoker; + $this->em = $em; + } + + /** + * Method schedules invoking of postLoad entity to the very end of current hydration cycle. + * + * @param ClassMetadata $class + * @param object $entity + */ + public function deferPostLoadInvoking(ClassMetadata $class, $entity) + { + $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postLoad); + + if ($invoke === ListenersInvoker::INVOKE_NONE) { + return; + } + + $this->deferredPostLoadInvocations[] = [$class, $invoke, $entity]; + } + + /** + * This method should me called after any hydration cycle completed. + * + * Method fires all deferred invocations of postLoad events + */ + public function hydrationComplete() + { + $toInvoke = $this->deferredPostLoadInvocations; + $this->deferredPostLoadInvocations = []; + + foreach ($toInvoke as $classAndEntity) { + list($class, $invoke, $entity) = $classAndEntity; + + $this->listenersInvoker->invoke( + $class, + Events::postLoad, + $entity, + new LifecycleEventArgs($entity, $this->em), + $invoke + ); + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/LazyCriteriaCollection.php b/vendor/doctrine/orm/lib/Doctrine/ORM/LazyCriteriaCollection.php new file mode 100644 index 0000000..ad0238f --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/LazyCriteriaCollection.php @@ -0,0 +1,133 @@ +. + */ + +namespace Doctrine\ORM; + +use Doctrine\Common\Collections\AbstractLazyCollection; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Criteria; +use Doctrine\Common\Collections\Selectable; +use Doctrine\ORM\Persisters\Entity\BasicEntityPersister; +use Doctrine\ORM\Persisters\Entity\EntityPersister; + +/** + * A lazy collection that allow a fast count when using criteria object + * Once count gets executed once without collection being initialized, result + * is cached and returned on subsequent calls until collection gets loaded, + * then returning the number of loaded results. + * + * @since 2.5 + * @author Guilherme Blanco + * @author Michaël Gallego + */ +class LazyCriteriaCollection extends AbstractLazyCollection implements Selectable +{ + /** + * @var BasicEntityPersister + */ + protected $entityPersister; + + /** + * @var Criteria + */ + protected $criteria; + + /** + * @var integer|null + */ + private $count; + + /** + * @param EntityPersister $entityPersister + * @param Criteria $criteria + */ + public function __construct(EntityPersister $entityPersister, Criteria $criteria) + { + $this->entityPersister = $entityPersister; + $this->criteria = $criteria; + } + + /** + * Do an efficient count on the collection + * + * @return integer + */ + public function count() + { + if ($this->isInitialized()) { + return $this->collection->count(); + } + + // Return cached result in case count query was already executed + if ($this->count !== null) { + return $this->count; + } + + return $this->count = $this->entityPersister->count($this->criteria); + } + + /** + * check if collection is empty without loading it + * + * @return boolean TRUE if the collection is empty, FALSE otherwise. + */ + public function isEmpty() + { + if ($this->isInitialized()) { + return $this->collection->isEmpty(); + } + + return !$this->count(); + } + + /** + * Do an optimized search of an element + * + * @param object $element + * + * @return bool + */ + public function contains($element) + { + if ($this->isInitialized()) { + return $this->collection->contains($element); + } + + return $this->entityPersister->exists($element, $this->criteria); + } + + /** + * {@inheritDoc} + */ + public function matching(Criteria $criteria) + { + $this->initialize(); + + return $this->collection->matching($criteria); + } + + /** + * {@inheritDoc} + */ + protected function doInitialize() + { + $elements = $this->entityPersister->loadCriteria($this->criteria); + $this->collection = new ArrayCollection($elements); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Annotation.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Annotation.php new file mode 100644 index 0000000..19374ff --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Annotation.php @@ -0,0 +1,24 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +interface Annotation +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AnsiQuoteStrategy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AnsiQuoteStrategy.php new file mode 100644 index 0000000..d18c8be --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AnsiQuoteStrategy.php @@ -0,0 +1,96 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * ANSI compliant quote strategy, this strategy does not apply any quote. + * To use this strategy all mapped tables and columns should be ANSI compliant. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class AnsiQuoteStrategy implements QuoteStrategy +{ + /** + * {@inheritdoc} + */ + public function getColumnName($fieldName, ClassMetadata $class, AbstractPlatform $platform) + { + return $class->fieldMappings[$fieldName]['columnName']; + } + + /** + * {@inheritdoc} + */ + public function getTableName(ClassMetadata $class, AbstractPlatform $platform) + { + return $class->table['name']; + } + + /** + * {@inheritdoc} + */ + public function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform) + { + return $definition['sequenceName']; + } + + /** + * {@inheritdoc} + */ + public function getJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform) + { + return $joinColumn['name']; + } + + /** + * {@inheritdoc} + */ + public function getReferencedJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform) + { + return $joinColumn['referencedColumnName']; + } + + /** + * {@inheritdoc} + */ + public function getJoinTableName(array $association, ClassMetadata $class, AbstractPlatform $platform) + { + return $association['joinTable']['name']; + } + + /** + * {@inheritdoc} + */ + public function getIdentifierColumnNames(ClassMetadata $class, AbstractPlatform $platform) + { + return $class->identifier; + } + + /** + * {@inheritdoc} + */ + public function getColumnAlias($columnName, $counter, AbstractPlatform $platform, ClassMetadata $class = null) + { + return $platform->getSQLResultCasing($columnName . '_' . $counter); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverride.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverride.php new file mode 100644 index 0000000..e208b16 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverride.php @@ -0,0 +1,69 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * This annotation is used to override association mapping of property for an entity relationship. + * + * @author Fabio B. Silva + * @since 2.3 + * + * @Annotation + * @Target("ANNOTATION") + */ +final class AssociationOverride implements Annotation +{ + /** + * The name of the relationship property whose mapping is being overridden. + * + * @var string + */ + public $name; + + /** + * The join column that is being mapped to the persistent attribute. + * + * @var array<\Doctrine\ORM\Mapping\JoinColumn> + */ + public $joinColumns; + + /** + * The join table that maps the relationship. + * + * @var \Doctrine\ORM\Mapping\JoinTable + */ + public $joinTable; + + /** + * The name of the association-field on the inverse-side. + * + * @var string + */ + public $inversedBy; + + /** + * The fetching strategy to use for the association. + * + * @var string + * + * @Enum({"LAZY", "EAGER", "EXTRA_LAZY"}) + */ + public $fetch; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverrides.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverrides.php new file mode 100644 index 0000000..217c9e4 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverrides.php @@ -0,0 +1,39 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * This annotation is used to override association mappings of relationship properties. + * + * @author Fabio B. Silva + * @since 2.3 + * + * @Annotation + * @Target("CLASS") + */ +final class AssociationOverrides implements Annotation +{ + /** + * Mapping overrides of relationship properties. + * + * @var array<\Doctrine\ORM\Mapping\AssociationOverride> + */ + public $value; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverride.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverride.php new file mode 100644 index 0000000..f86d3a1 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverride.php @@ -0,0 +1,46 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * This annotation is used to override the mapping of a entity property. + * + * @author Fabio B. Silva + * @since 2.3 + * + * @Annotation + * @Target("ANNOTATION") + */ +final class AttributeOverride implements Annotation +{ + /** + * The name of the property whose mapping is being overridden. + * + * @var string + */ + public $name; + + /** + * The column definition. + * + * @var \Doctrine\ORM\Mapping\Column + */ + public $column; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverrides.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverrides.php new file mode 100644 index 0000000..63b2cc6 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverrides.php @@ -0,0 +1,39 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * This annotation is used to override the mapping of a entity property. + * + * @author Fabio B. Silva + * @since 2.3 + * + * @Annotation + * @Target("CLASS") + */ +final class AttributeOverrides implements Annotation +{ + /** + * One or more field or property mapping overrides. + * + * @var array<\Doctrine\ORM\Mapping\AttributeOverride> + */ + public $value; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php new file mode 100644 index 0000000..7f4fddc --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php @@ -0,0 +1,244 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Builder; + +use Doctrine\ORM\Mapping\ClassMetadata; + +class AssociationBuilder +{ + /** + * @var ClassMetadataBuilder + */ + protected $builder; + + /** + * @var array + */ + protected $mapping; + + /** + * @var array|null + */ + protected $joinColumns; + + /** + * @var int + */ + protected $type; + + /** + * @param ClassMetadataBuilder $builder + * @param array $mapping + * @param int $type + */ + public function __construct(ClassMetadataBuilder $builder, array $mapping, $type) + { + $this->builder = $builder; + $this->mapping = $mapping; + $this->type = $type; + } + + /** + * @param string $fieldName + * + * @return AssociationBuilder + */ + public function mappedBy($fieldName) + { + $this->mapping['mappedBy'] = $fieldName; + + return $this; + } + + /** + * @param string $fieldName + * + * @return AssociationBuilder + */ + public function inversedBy($fieldName) + { + $this->mapping['inversedBy'] = $fieldName; + + return $this; + } + + /** + * @return AssociationBuilder + */ + public function cascadeAll() + { + $this->mapping['cascade'] = ["ALL"]; + + return $this; + } + + /** + * @return AssociationBuilder + */ + public function cascadePersist() + { + $this->mapping['cascade'][] = "persist"; + + return $this; + } + + /** + * @return AssociationBuilder + */ + public function cascadeRemove() + { + $this->mapping['cascade'][] = "remove"; + + return $this; + } + + /** + * @return AssociationBuilder + */ + public function cascadeMerge() + { + $this->mapping['cascade'][] = "merge"; + + return $this; + } + + /** + * @return AssociationBuilder + */ + public function cascadeDetach() + { + $this->mapping['cascade'][] = "detach"; + + return $this; + } + + /** + * @return AssociationBuilder + */ + public function cascadeRefresh() + { + $this->mapping['cascade'][] = "refresh"; + + return $this; + } + + /** + * @return AssociationBuilder + */ + public function fetchExtraLazy() + { + $this->mapping['fetch'] = ClassMetadata::FETCH_EXTRA_LAZY; + + return $this; + } + + /** + * @return AssociationBuilder + */ + public function fetchEager() + { + $this->mapping['fetch'] = ClassMetadata::FETCH_EAGER; + + return $this; + } + + /** + * @return AssociationBuilder + */ + public function fetchLazy() + { + $this->mapping['fetch'] = ClassMetadata::FETCH_LAZY; + + return $this; + } + + /** + * Add Join Columns. + * + * @param string $columnName + * @param string $referencedColumnName + * @param bool $nullable + * @param bool $unique + * @param string|null $onDelete + * @param string|null $columnDef + * + * @return AssociationBuilder + */ + public function addJoinColumn($columnName, $referencedColumnName, $nullable = true, $unique = false, $onDelete = null, $columnDef = null) + { + $this->joinColumns[] = [ + 'name' => $columnName, + 'referencedColumnName' => $referencedColumnName, + 'nullable' => $nullable, + 'unique' => $unique, + 'onDelete' => $onDelete, + 'columnDefinition' => $columnDef, + ]; + + return $this; + } + + /** + * Sets field as primary key. + * + * @return self + */ + public function makePrimaryKey() + { + $this->mapping['id'] = true; + + return $this; + } + + /** + * Removes orphan entities when detached from their parent. + * + * @return self + */ + public function orphanRemoval() + { + $this->mapping['orphanRemoval'] = true; + + return $this; + } + + /** + * @return ClassMetadataBuilder + * + * @throws \InvalidArgumentException + */ + public function build() + { + $mapping = $this->mapping; + if ($this->joinColumns) { + $mapping['joinColumns'] = $this->joinColumns; + } + $cm = $this->builder->getClassMetadata(); + if ($this->type == ClassMetadata::MANY_TO_ONE) { + $cm->mapManyToOne($mapping); + } else if ($this->type == ClassMetadata::ONE_TO_ONE) { + $cm->mapOneToOne($mapping); + } else { + throw new \InvalidArgumentException("Type should be a ToOne Association here"); + } + + return $this->builder; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php new file mode 100644 index 0000000..c08b374 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php @@ -0,0 +1,553 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Builder; + +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Mapping\ClassMetadataInfo; + +/** + * Builder Object for ClassMetadata + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.com + * @since 2.2 + * @author Benjamin Eberlei + * @author Guilherme Blanco + */ +class ClassMetadataBuilder +{ + /** + * @var \Doctrine\ORM\Mapping\ClassMetadataInfo + */ + private $cm; + + /** + * @param \Doctrine\ORM\Mapping\ClassMetadataInfo $cm + */ + public function __construct(ClassMetadataInfo $cm) + { + $this->cm = $cm; + } + + /** + * @return ClassMetadata + */ + public function getClassMetadata() + { + return $this->cm; + } + + /** + * Marks the class as mapped superclass. + * + * @return ClassMetadataBuilder + */ + public function setMappedSuperClass() + { + $this->cm->isMappedSuperclass = true; + $this->cm->isEmbeddedClass = false; + + return $this; + } + + /** + * Marks the class as embeddable. + * + * @return ClassMetadataBuilder + */ + public function setEmbeddable() + { + $this->cm->isEmbeddedClass = true; + $this->cm->isMappedSuperclass = false; + + return $this; + } + + /** + * Adds and embedded class + * + * @param string $fieldName + * @param string $class + * @param string|null $columnPrefix + * + * @return $this + */ + public function addEmbedded($fieldName, $class, $columnPrefix = null) + { + $this->cm->mapEmbedded( + [ + 'fieldName' => $fieldName, + 'class' => $class, + 'columnPrefix' => $columnPrefix + ] + ); + + return $this; + } + + /** + * Sets custom Repository class name. + * + * @param string $repositoryClassName + * + * @return ClassMetadataBuilder + */ + public function setCustomRepositoryClass($repositoryClassName) + { + $this->cm->setCustomRepositoryClass($repositoryClassName); + + return $this; + } + + /** + * Marks class read only. + * + * @return ClassMetadataBuilder + */ + public function setReadOnly() + { + $this->cm->markReadOnly(); + + return $this; + } + + /** + * Sets the table name. + * + * @param string $name + * + * @return ClassMetadataBuilder + */ + public function setTable($name) + { + $this->cm->setPrimaryTable(['name' => $name]); + + return $this; + } + + /** + * Adds Index. + * + * @param array $columns + * @param string $name + * + * @return ClassMetadataBuilder + */ + public function addIndex(array $columns, $name) + { + if (!isset($this->cm->table['indexes'])) { + $this->cm->table['indexes'] = []; + } + + $this->cm->table['indexes'][$name] = ['columns' => $columns]; + + return $this; + } + + /** + * Adds Unique Constraint. + * + * @param array $columns + * @param string $name + * + * @return ClassMetadataBuilder + */ + public function addUniqueConstraint(array $columns, $name) + { + if ( ! isset($this->cm->table['uniqueConstraints'])) { + $this->cm->table['uniqueConstraints'] = []; + } + + $this->cm->table['uniqueConstraints'][$name] = ['columns' => $columns]; + + return $this; + } + + /** + * Adds named query. + * + * @param string $name + * @param string $dqlQuery + * + * @return ClassMetadataBuilder + */ + public function addNamedQuery($name, $dqlQuery) + { + $this->cm->addNamedQuery( + [ + 'name' => $name, + 'query' => $dqlQuery, + ] + ); + + return $this; + } + + /** + * Sets class as root of a joined table inheritance hierarchy. + * + * @return ClassMetadataBuilder + */ + public function setJoinedTableInheritance() + { + $this->cm->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_JOINED); + + return $this; + } + + /** + * Sets class as root of a single table inheritance hierarchy. + * + * @return ClassMetadataBuilder + */ + public function setSingleTableInheritance() + { + $this->cm->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE); + + return $this; + } + + /** + * Sets the discriminator column details. + * + * @param string $name + * @param string $type + * @param int $length + * + * @return ClassMetadataBuilder + */ + public function setDiscriminatorColumn($name, $type = 'string', $length = 255) + { + $this->cm->setDiscriminatorColumn( + [ + 'name' => $name, + 'type' => $type, + 'length' => $length, + ] + ); + + return $this; + } + + /** + * Adds a subclass to this inheritance hierarchy. + * + * @param string $name + * @param string $class + * + * @return ClassMetadataBuilder + */ + public function addDiscriminatorMapClass($name, $class) + { + $this->cm->addDiscriminatorMapClass($name, $class); + + return $this; + } + + /** + * Sets deferred explicit change tracking policy. + * + * @return ClassMetadataBuilder + */ + public function setChangeTrackingPolicyDeferredExplicit() + { + $this->cm->setChangeTrackingPolicy(ClassMetadata::CHANGETRACKING_DEFERRED_EXPLICIT); + + return $this; + } + + /** + * Sets notify change tracking policy. + * + * @return ClassMetadataBuilder + */ + public function setChangeTrackingPolicyNotify() + { + $this->cm->setChangeTrackingPolicy(ClassMetadata::CHANGETRACKING_NOTIFY); + + return $this; + } + + /** + * Adds lifecycle event. + * + * @param string $methodName + * @param string $event + * + * @return ClassMetadataBuilder + */ + public function addLifecycleEvent($methodName, $event) + { + $this->cm->addLifecycleCallback($methodName, $event); + + return $this; + } + + /** + * Adds Field. + * + * @param string $name + * @param string $type + * @param array $mapping + * + * @return ClassMetadataBuilder + */ + public function addField($name, $type, array $mapping = []) + { + $mapping['fieldName'] = $name; + $mapping['type'] = $type; + + $this->cm->mapField($mapping); + + return $this; + } + + /** + * Creates a field builder. + * + * @param string $name + * @param string $type + * + * @return FieldBuilder + */ + public function createField($name, $type) + { + return new FieldBuilder( + $this, + [ + 'fieldName' => $name, + 'type' => $type + ] + ); + } + + /** + * Creates an embedded builder. + * + * @param string $fieldName + * @param string $class + * + * @return EmbeddedBuilder + */ + public function createEmbedded($fieldName, $class) + { + return new EmbeddedBuilder( + $this, + [ + 'fieldName' => $fieldName, + 'class' => $class, + 'columnPrefix' => null + ] + ); + } + + /** + * Adds a simple many to one association, optionally with the inversed by field. + * + * @param string $name + * @param string $targetEntity + * @param string|null $inversedBy + * + * @return ClassMetadataBuilder + */ + public function addManyToOne($name, $targetEntity, $inversedBy = null) + { + $builder = $this->createManyToOne($name, $targetEntity); + + if ($inversedBy) { + $builder->inversedBy($inversedBy); + } + + return $builder->build(); + } + + /** + * Creates a ManyToOne Association Builder. + * + * Note: This method does not add the association, you have to call build() on the AssociationBuilder. + * + * @param string $name + * @param string $targetEntity + * + * @return AssociationBuilder + */ + public function createManyToOne($name, $targetEntity) + { + return new AssociationBuilder( + $this, + [ + 'fieldName' => $name, + 'targetEntity' => $targetEntity + ], + ClassMetadata::MANY_TO_ONE + ); + } + + /** + * Creates a OneToOne Association Builder. + * + * @param string $name + * @param string $targetEntity + * + * @return AssociationBuilder + */ + public function createOneToOne($name, $targetEntity) + { + return new AssociationBuilder( + $this, + [ + 'fieldName' => $name, + 'targetEntity' => $targetEntity + ], + ClassMetadata::ONE_TO_ONE + ); + } + + /** + * Adds simple inverse one-to-one association. + * + * @param string $name + * @param string $targetEntity + * @param string $mappedBy + * + * @return ClassMetadataBuilder + */ + public function addInverseOneToOne($name, $targetEntity, $mappedBy) + { + $builder = $this->createOneToOne($name, $targetEntity); + $builder->mappedBy($mappedBy); + + return $builder->build(); + } + + /** + * Adds simple owning one-to-one association. + * + * @param string $name + * @param string $targetEntity + * @param string|null $inversedBy + * + * @return ClassMetadataBuilder + */ + public function addOwningOneToOne($name, $targetEntity, $inversedBy = null) + { + $builder = $this->createOneToOne($name, $targetEntity); + + if ($inversedBy) { + $builder->inversedBy($inversedBy); + } + + return $builder->build(); + } + + /** + * Creates a ManyToMany Association Builder. + * + * @param string $name + * @param string $targetEntity + * + * @return ManyToManyAssociationBuilder + */ + public function createManyToMany($name, $targetEntity) + { + return new ManyToManyAssociationBuilder( + $this, + [ + 'fieldName' => $name, + 'targetEntity' => $targetEntity + ], + ClassMetadata::MANY_TO_MANY + ); + } + + /** + * Adds a simple owning many to many association. + * + * @param string $name + * @param string $targetEntity + * @param string|null $inversedBy + * + * @return ClassMetadataBuilder + */ + public function addOwningManyToMany($name, $targetEntity, $inversedBy = null) + { + $builder = $this->createManyToMany($name, $targetEntity); + + if ($inversedBy) { + $builder->inversedBy($inversedBy); + } + + return $builder->build(); + } + + /** + * Adds a simple inverse many to many association. + * + * @param string $name + * @param string $targetEntity + * @param string $mappedBy + * + * @return ClassMetadataBuilder + */ + public function addInverseManyToMany($name, $targetEntity, $mappedBy) + { + $builder = $this->createManyToMany($name, $targetEntity); + $builder->mappedBy($mappedBy); + + return $builder->build(); + } + + /** + * Creates a one to many association builder. + * + * @param string $name + * @param string $targetEntity + * + * @return OneToManyAssociationBuilder + */ + public function createOneToMany($name, $targetEntity) + { + return new OneToManyAssociationBuilder( + $this, + [ + 'fieldName' => $name, + 'targetEntity' => $targetEntity + ], + ClassMetadata::ONE_TO_MANY + ); + } + + /** + * Adds simple OneToMany association. + * + * @param string $name + * @param string $targetEntity + * @param string $mappedBy + * + * @return ClassMetadataBuilder + */ + public function addOneToMany($name, $targetEntity, $mappedBy) + { + $builder = $this->createOneToMany($name, $targetEntity); + $builder->mappedBy($mappedBy); + + return $builder->build(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EmbeddedBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EmbeddedBuilder.php new file mode 100644 index 0000000..de8383c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EmbeddedBuilder.php @@ -0,0 +1,80 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Builder; + +/** + * Embedded Builder + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.com + * @since 2.5 + * @author Guido Contreras Woda + */ +class EmbeddedBuilder +{ + /** + * @var ClassMetadataBuilder + */ + private $builder; + + /** + * @var array + */ + private $mapping; + + /** + * @param ClassMetadataBuilder $builder + * @param array $mapping + */ + public function __construct(ClassMetadataBuilder $builder, array $mapping) + { + $this->builder = $builder; + $this->mapping = $mapping; + } + + /** + * Sets the column prefix for all of the embedded columns. + * + * @param string $columnPrefix + * @return $this + */ + public function setColumnPrefix($columnPrefix) + { + $this->mapping['columnPrefix'] = $columnPrefix; + + return $this; + } + + /** + * Finalizes this embeddable and attach it to the ClassMetadata. + * + * Without this call an EmbeddedBuilder has no effect on the ClassMetadata. + * + * @return ClassMetadataBuilder + */ + public function build() + { + $cm = $this->builder->getClassMetadata(); + + $cm->mapEmbedded($this->mapping); + + return $this->builder; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EntityListenerBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EntityListenerBuilder.php new file mode 100644 index 0000000..e962726 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EntityListenerBuilder.php @@ -0,0 +1,72 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Builder; + +use Doctrine\ORM\Mapping\MappingException; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Events; + +/** + * Builder for entity listeners. + * + * @since 2.4 + * @author Fabio B. Silva + */ +class EntityListenerBuilder +{ + /** + * @var array Hash-map to handle event names. + */ + static private $events = [ + Events::preRemove => true, + Events::postRemove => true, + Events::prePersist => true, + Events::postPersist => true, + Events::preUpdate => true, + Events::postUpdate => true, + Events::postLoad => true, + Events::preFlush => true + ]; + + /** + * Lookup the entity class to find methods that match to event lifecycle names + * + * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. + * @param string $className The listener class name. + * + * @throws \Doctrine\ORM\Mapping\MappingException When the listener class not found. + */ + static public function bindEntityListener(ClassMetadata $metadata, $className) + { + $class = $metadata->fullyQualifiedClassName($className); + + if ( ! class_exists($class)) { + throw MappingException::entityListenerClassNotFound($class, $className); + } + + foreach (get_class_methods($class) as $method) { + if ( ! isset(self::$events[$method])) { + continue; + } + + $metadata->addEntityListener($method, $class, $method); + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php new file mode 100644 index 0000000..d0128d4 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php @@ -0,0 +1,296 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Builder; + +/** + * Field Builder + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.com + * @since 2.2 + * @author Benjamin Eberlei + */ +class FieldBuilder +{ + /** + * @var ClassMetadataBuilder + */ + private $builder; + + /** + * @var array + */ + private $mapping; + + /** + * @var bool + */ + private $version; + + /** + * @var string + */ + private $generatedValue; + + /** + * @var array + */ + private $sequenceDef; + + /** + * @var string|null + */ + private $customIdGenerator; + + /** + * @param ClassMetadataBuilder $builder + * @param array $mapping + */ + public function __construct(ClassMetadataBuilder $builder, array $mapping) + { + $this->builder = $builder; + $this->mapping = $mapping; + } + + /** + * Sets length. + * + * @param int $length + * + * @return FieldBuilder + */ + public function length($length) + { + $this->mapping['length'] = $length; + + return $this; + } + + /** + * Sets nullable. + * + * @param bool $flag + * + * @return FieldBuilder + */ + public function nullable($flag = true) + { + $this->mapping['nullable'] = (bool) $flag; + + return $this; + } + + /** + * Sets Unique. + * + * @param bool $flag + * + * @return FieldBuilder + */ + public function unique($flag = true) + { + $this->mapping['unique'] = (bool) $flag; + + return $this; + } + + /** + * Sets column name. + * + * @param string $name + * + * @return FieldBuilder + */ + public function columnName($name) + { + $this->mapping['columnName'] = $name; + + return $this; + } + + /** + * Sets Precision. + * + * @param int $p + * + * @return FieldBuilder + */ + public function precision($p) + { + $this->mapping['precision'] = $p; + + return $this; + } + + /** + * Sets scale. + * + * @param int $s + * + * @return FieldBuilder + */ + public function scale($s) + { + $this->mapping['scale'] = $s; + + return $this; + } + + /** + * Sets field as primary key. + * + * @deprecated Use makePrimaryKey() instead + * @return FieldBuilder + */ + public function isPrimaryKey() + { + return $this->makePrimaryKey(); + } + + /** + * Sets field as primary key. + * + * @return FieldBuilder + */ + public function makePrimaryKey() + { + $this->mapping['id'] = true; + + return $this; + } + + /** + * Sets an option. + * + * @param string $name + * @param mixed $value + * + * @return FieldBuilder + */ + public function option($name, $value) + { + $this->mapping['options'][$name] = $value; + + return $this; + } + + /** + * @param string $strategy + * + * @return FieldBuilder + */ + public function generatedValue($strategy = 'AUTO') + { + $this->generatedValue = $strategy; + + return $this; + } + + /** + * Sets field versioned. + * + * @return FieldBuilder + */ + public function isVersionField() + { + $this->version = true; + + return $this; + } + + /** + * Sets Sequence Generator. + * + * @param string $sequenceName + * @param int $allocationSize + * @param int $initialValue + * + * @return FieldBuilder + */ + public function setSequenceGenerator($sequenceName, $allocationSize = 1, $initialValue = 1) + { + $this->sequenceDef = [ + 'sequenceName' => $sequenceName, + 'allocationSize' => $allocationSize, + 'initialValue' => $initialValue, + ]; + + return $this; + } + + /** + * Sets column definition. + * + * @param string $def + * + * @return FieldBuilder + */ + public function columnDefinition($def) + { + $this->mapping['columnDefinition'] = $def; + + return $this; + } + + /** + * Set the FQCN of the custom ID generator. + * This class must extend \Doctrine\ORM\Id\AbstractIdGenerator. + * + * @param string $customIdGenerator + * + * @return $this + */ + public function setCustomIdGenerator($customIdGenerator) + { + $this->customIdGenerator = (string) $customIdGenerator; + + return $this; + } + + /** + * Finalizes this field and attach it to the ClassMetadata. + * + * Without this call a FieldBuilder has no effect on the ClassMetadata. + * + * @return ClassMetadataBuilder + */ + public function build() + { + $cm = $this->builder->getClassMetadata(); + if ($this->generatedValue) { + $cm->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $this->generatedValue)); + } + + if ($this->version) { + $cm->setVersionMapping($this->mapping); + } + + $cm->mapField($this->mapping); + if ($this->sequenceDef) { + $cm->setSequenceGeneratorDefinition($this->sequenceDef); + } + + if ($this->customIdGenerator) { + $cm->setCustomGeneratorDefinition(['class' => $this->customIdGenerator]); + } + + return $this->builder; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ManyToManyAssociationBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ManyToManyAssociationBuilder.php new file mode 100644 index 0000000..a71859d --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ManyToManyAssociationBuilder.php @@ -0,0 +1,101 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Builder; + +/** + * ManyToMany Association Builder + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei + */ +class ManyToManyAssociationBuilder extends OneToManyAssociationBuilder +{ + /** + * @var string|null + */ + private $joinTableName; + + /** + * @var array + */ + private $inverseJoinColumns = []; + + /** + * @param string $name + * + * @return ManyToManyAssociationBuilder + */ + public function setJoinTable($name) + { + $this->joinTableName = $name; + + return $this; + } + + /** + * Adds Inverse Join Columns. + * + * @param string $columnName + * @param string $referencedColumnName + * @param bool $nullable + * @param bool $unique + * @param string|null $onDelete + * @param string|null $columnDef + * + * @return ManyToManyAssociationBuilder + */ + public function addInverseJoinColumn($columnName, $referencedColumnName, $nullable = true, $unique = false, $onDelete = null, $columnDef = null) + { + $this->inverseJoinColumns[] = [ + 'name' => $columnName, + 'referencedColumnName' => $referencedColumnName, + 'nullable' => $nullable, + 'unique' => $unique, + 'onDelete' => $onDelete, + 'columnDefinition' => $columnDef, + ]; + + return $this; + } + + /** + * @return ClassMetadataBuilder + */ + public function build() + { + $mapping = $this->mapping; + $mapping['joinTable'] = []; + if ($this->joinColumns) { + $mapping['joinTable']['joinColumns'] = $this->joinColumns; + } + if ($this->inverseJoinColumns) { + $mapping['joinTable']['inverseJoinColumns'] = $this->inverseJoinColumns; + } + if ($this->joinTableName) { + $mapping['joinTable']['name'] = $this->joinTableName; + } + $cm = $this->builder->getClassMetadata(); + $cm->mapManyToMany($mapping); + + return $this->builder; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/OneToManyAssociationBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/OneToManyAssociationBuilder.php new file mode 100644 index 0000000..347dfd0 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/OneToManyAssociationBuilder.php @@ -0,0 +1,70 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Builder; + +/** + * OneToMany Association Builder + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei + */ +class OneToManyAssociationBuilder extends AssociationBuilder +{ + /** + * @param array $fieldNames + * + * @return OneToManyAssociationBuilder + */ + public function setOrderBy(array $fieldNames) + { + $this->mapping['orderBy'] = $fieldNames; + + return $this; + } + + /** + * @param string $fieldName + * + * @return OneToManyAssociationBuilder + */ + public function setIndexBy($fieldName) + { + $this->mapping['indexBy'] = $fieldName; + + return $this; + } + + /** + * @return ClassMetadataBuilder + */ + public function build() + { + $mapping = $this->mapping; + if ($this->joinColumns) { + $mapping['joinColumns'] = $this->joinColumns; + } + $cm = $this->builder->getClassMetadata(); + $cm->mapOneToMany($mapping); + + return $this->builder; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Cache.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Cache.php new file mode 100644 index 0000000..3226b60 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Cache.php @@ -0,0 +1,44 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * Caching to an entity or a collection. + * + * @author Fabio B. Silva + * @since 2.5 + * + * @Annotation + * @Target({"CLASS","PROPERTY"}) + */ +final class Cache implements Annotation +{ + /** + * @Enum({"READ_ONLY", "NONSTRICT_READ_WRITE", "READ_WRITE"}) + * + * @var string The concurrency strategy. + */ + public $usage = 'READ_ONLY'; + + /** + * @var string Cache region name. + */ + public $region; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ChangeTrackingPolicy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ChangeTrackingPolicy.php new file mode 100644 index 0000000..3657b76 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ChangeTrackingPolicy.php @@ -0,0 +1,36 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("CLASS") + */ +final class ChangeTrackingPolicy implements Annotation +{ + /** + * The change tracking policy. + * + * @var string + * + * @Enum({"DEFERRED_IMPLICIT", "DEFERRED_EXPLICIT", "NOTIFY"}) + */ + public $value; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadata.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadata.php new file mode 100644 index 0000000..a57f1e1 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadata.php @@ -0,0 +1,29 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * {@inheritDoc} + * + * @todo remove or rename ClassMetadataInfo to ClassMetadata + */ +class ClassMetadata extends ClassMetadataInfo +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php new file mode 100644 index 0000000..8410ce5 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php @@ -0,0 +1,797 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +use Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory; +use Doctrine\Common\Persistence\Mapping\ClassMetadata as ClassMetadataInterface; +use Doctrine\Common\Persistence\Mapping\ReflectionService; +use Doctrine\DBAL\Platforms; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Event\LoadClassMetadataEventArgs; +use Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs; +use Doctrine\ORM\Events; +use Doctrine\ORM\Id\BigIntegerIdentityGenerator; +use Doctrine\ORM\Id\IdentityGenerator; +use Doctrine\ORM\ORMException; +use ReflectionException; + +/** + * The ClassMetadataFactory is used to create ClassMetadata objects that contain all the + * metadata mapping information of a class which describes how a class should be mapped + * to a relational database. + * + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ClassMetadataFactory extends AbstractClassMetadataFactory +{ + /** + * @var EntityManagerInterface|null + */ + private $em; + + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $targetPlatform; + + /** + * @var \Doctrine\Common\Persistence\Mapping\Driver\MappingDriver + */ + private $driver; + + /** + * @var \Doctrine\Common\EventManager + */ + private $evm; + + /** + * @var array + */ + private $embeddablesActiveNesting = []; + + /** + * {@inheritDoc} + */ + protected function loadMetadata($name) + { + $loaded = parent::loadMetadata($name); + + array_map([$this, 'resolveDiscriminatorValue'], array_map([$this, 'getMetadataFor'], $loaded)); + + return $loaded; + } + + /** + * @param EntityManagerInterface $em + */ + public function setEntityManager(EntityManagerInterface $em) + { + $this->em = $em; + } + + /** + * {@inheritDoc} + */ + protected function initialize() + { + $this->driver = $this->em->getConfiguration()->getMetadataDriverImpl(); + $this->evm = $this->em->getEventManager(); + $this->initialized = true; + } + + /** + * {@inheritDoc} + */ + protected function onNotFoundMetadata($className) + { + if (! $this->evm->hasListeners(Events::onClassMetadataNotFound)) { + return; + } + + $eventArgs = new OnClassMetadataNotFoundEventArgs($className, $this->em); + + $this->evm->dispatchEvent(Events::onClassMetadataNotFound, $eventArgs); + + return $eventArgs->getFoundMetadata(); + } + + /** + * {@inheritDoc} + */ + protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonSuperclassParents) + { + /* @var $class ClassMetadata */ + /* @var $parent ClassMetadata */ + if ($parent) { + $class->setInheritanceType($parent->inheritanceType); + $class->setDiscriminatorColumn($parent->discriminatorColumn); + $class->setIdGeneratorType($parent->generatorType); + $this->addInheritedFields($class, $parent); + $this->addInheritedRelations($class, $parent); + $this->addInheritedEmbeddedClasses($class, $parent); + $class->setIdentifier($parent->identifier); + $class->setVersioned($parent->isVersioned); + $class->setVersionField($parent->versionField); + $class->setDiscriminatorMap($parent->discriminatorMap); + $class->setLifecycleCallbacks($parent->lifecycleCallbacks); + $class->setChangeTrackingPolicy($parent->changeTrackingPolicy); + + if ( ! empty($parent->customGeneratorDefinition)) { + $class->setCustomGeneratorDefinition($parent->customGeneratorDefinition); + } + + if ($parent->isMappedSuperclass) { + $class->setCustomRepositoryClass($parent->customRepositoryClassName); + } + } + + // Invoke driver + try { + $this->driver->loadMetadataForClass($class->getName(), $class); + } catch (ReflectionException $e) { + throw MappingException::reflectionFailure($class->getName(), $e); + } + + // If this class has a parent the id generator strategy is inherited. + // However this is only true if the hierarchy of parents contains the root entity, + // if it consists of mapped superclasses these don't necessarily include the id field. + if ($parent && $rootEntityFound) { + $this->inheritIdGeneratorMapping($class, $parent); + } else { + $this->completeIdGeneratorMapping($class); + } + + if (!$class->isMappedSuperclass) { + foreach ($class->embeddedClasses as $property => $embeddableClass) { + + if (isset($embeddableClass['inherited'])) { + continue; + } + + if ( ! (isset($embeddableClass['class']) && $embeddableClass['class'])) { + throw MappingException::missingEmbeddedClass($property); + } + + if (isset($this->embeddablesActiveNesting[$embeddableClass['class']])) { + throw MappingException::infiniteEmbeddableNesting($class->name, $property); + } + + $this->embeddablesActiveNesting[$class->name] = true; + + $embeddableMetadata = $this->getMetadataFor($embeddableClass['class']); + + if ($embeddableMetadata->isEmbeddedClass) { + $this->addNestedEmbeddedClasses($embeddableMetadata, $class, $property); + } + + $identifier = $embeddableMetadata->getIdentifier(); + + if (! empty($identifier)) { + $this->inheritIdGeneratorMapping($class, $embeddableMetadata); + } + + $class->inlineEmbeddable($property, $embeddableMetadata); + + unset($this->embeddablesActiveNesting[$class->name]); + } + } + + if ($parent) { + if ($parent->isInheritanceTypeSingleTable()) { + $class->setPrimaryTable($parent->table); + } + + if ($parent) { + $this->addInheritedIndexes($class, $parent); + } + + if ($parent->cache) { + $class->cache = $parent->cache; + } + + if ($parent->containsForeignIdentifier) { + $class->containsForeignIdentifier = true; + } + + if ( ! empty($parent->namedQueries)) { + $this->addInheritedNamedQueries($class, $parent); + } + + if ( ! empty($parent->namedNativeQueries)) { + $this->addInheritedNamedNativeQueries($class, $parent); + } + + if ( ! empty($parent->sqlResultSetMappings)) { + $this->addInheritedSqlResultSetMappings($class, $parent); + } + + if ( ! empty($parent->entityListeners) && empty($class->entityListeners)) { + $class->entityListeners = $parent->entityListeners; + } + } + + $class->setParentClasses($nonSuperclassParents); + + if ($class->isRootEntity() && ! $class->isInheritanceTypeNone() && ! $class->discriminatorMap) { + $this->addDefaultDiscriminatorMap($class); + } + + if ($this->evm->hasListeners(Events::loadClassMetadata)) { + $eventArgs = new LoadClassMetadataEventArgs($class, $this->em); + $this->evm->dispatchEvent(Events::loadClassMetadata, $eventArgs); + } + + $this->validateRuntimeMetadata($class, $parent); + } + + /** + * Validate runtime metadata is correctly defined. + * + * @param ClassMetadata $class + * @param ClassMetadataInterface|null $parent + * + * @return void + * + * @throws MappingException + */ + protected function validateRuntimeMetadata($class, $parent) + { + if ( ! $class->reflClass ) { + // only validate if there is a reflection class instance + return; + } + + $class->validateIdentifier(); + $class->validateAssociations(); + $class->validateLifecycleCallbacks($this->getReflectionService()); + + // verify inheritance + if ( ! $class->isMappedSuperclass && !$class->isInheritanceTypeNone()) { + if ( ! $parent) { + if (count($class->discriminatorMap) == 0) { + throw MappingException::missingDiscriminatorMap($class->name); + } + if ( ! $class->discriminatorColumn) { + throw MappingException::missingDiscriminatorColumn($class->name); + } + } + } else if ($class->isMappedSuperclass && $class->name == $class->rootEntityName && (count($class->discriminatorMap) || $class->discriminatorColumn)) { + // second condition is necessary for mapped superclasses in the middle of an inheritance hierarchy + throw MappingException::noInheritanceOnMappedSuperClass($class->name); + } + } + + /** + * {@inheritDoc} + */ + protected function newClassMetadataInstance($className) + { + return new ClassMetadata($className, $this->em->getConfiguration()->getNamingStrategy()); + } + + /** + * Populates the discriminator value of the given metadata (if not set) by iterating over discriminator + * map classes and looking for a fitting one. + * + * @param ClassMetadata $metadata + * + * @return void + * + * @throws MappingException + */ + private function resolveDiscriminatorValue(ClassMetadata $metadata) + { + if ($metadata->discriminatorValue + || ! $metadata->discriminatorMap + || $metadata->isMappedSuperclass + || ! $metadata->reflClass + || $metadata->reflClass->isAbstract() + ) { + return; + } + + // minor optimization: avoid loading related metadata when not needed + foreach ($metadata->discriminatorMap as $discriminatorValue => $discriminatorClass) { + if ($discriminatorClass === $metadata->name) { + $metadata->discriminatorValue = $discriminatorValue; + + return; + } + } + + // iterate over discriminator mappings and resolve actual referenced classes according to existing metadata + foreach ($metadata->discriminatorMap as $discriminatorValue => $discriminatorClass) { + if ($metadata->name === $this->getMetadataFor($discriminatorClass)->getName()) { + $metadata->discriminatorValue = $discriminatorValue; + + return; + } + } + + throw MappingException::mappedClassNotPartOfDiscriminatorMap($metadata->name, $metadata->rootEntityName); + } + + /** + * Adds a default discriminator map if no one is given + * + * If an entity is of any inheritance type and does not contain a + * discriminator map, then the map is generated automatically. This process + * is expensive computation wise. + * + * The automatically generated discriminator map contains the lowercase short name of + * each class as key. + * + * @param \Doctrine\ORM\Mapping\ClassMetadata $class + * + * @throws MappingException + */ + private function addDefaultDiscriminatorMap(ClassMetadata $class) + { + $allClasses = $this->driver->getAllClassNames(); + $fqcn = $class->getName(); + $map = [$this->getShortName($class->name) => $fqcn]; + + $duplicates = []; + foreach ($allClasses as $subClassCandidate) { + if (is_subclass_of($subClassCandidate, $fqcn)) { + $shortName = $this->getShortName($subClassCandidate); + + if (isset($map[$shortName])) { + $duplicates[] = $shortName; + } + + $map[$shortName] = $subClassCandidate; + } + } + + if ($duplicates) { + throw MappingException::duplicateDiscriminatorEntry($class->name, $duplicates, $map); + } + + $class->setDiscriminatorMap($map); + } + + /** + * Gets the lower-case short name of a class. + * + * @param string $className + * + * @return string + */ + private function getShortName($className) + { + if (strpos($className, "\\") === false) { + return strtolower($className); + } + + $parts = explode("\\", $className); + + return strtolower(end($parts)); + } + + /** + * Adds inherited fields to the subclass mapping. + * + * @param \Doctrine\ORM\Mapping\ClassMetadata $subClass + * @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass + * + * @return void + */ + private function addInheritedFields(ClassMetadata $subClass, ClassMetadata $parentClass) + { + foreach ($parentClass->fieldMappings as $mapping) { + if ( ! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) { + $mapping['inherited'] = $parentClass->name; + } + if ( ! isset($mapping['declared'])) { + $mapping['declared'] = $parentClass->name; + } + $subClass->addInheritedFieldMapping($mapping); + } + foreach ($parentClass->reflFields as $name => $field) { + $subClass->reflFields[$name] = $field; + } + } + + /** + * Adds inherited association mappings to the subclass mapping. + * + * @param \Doctrine\ORM\Mapping\ClassMetadata $subClass + * @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass + * + * @return void + * + * @throws MappingException + */ + private function addInheritedRelations(ClassMetadata $subClass, ClassMetadata $parentClass) + { + foreach ($parentClass->associationMappings as $field => $mapping) { + if ($parentClass->isMappedSuperclass) { + if ($mapping['type'] & ClassMetadata::TO_MANY && !$mapping['isOwningSide']) { + throw MappingException::illegalToManyAssociationOnMappedSuperclass($parentClass->name, $field); + } + $mapping['sourceEntity'] = $subClass->name; + } + + //$subclassMapping = $mapping; + if ( ! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) { + $mapping['inherited'] = $parentClass->name; + } + if ( ! isset($mapping['declared'])) { + $mapping['declared'] = $parentClass->name; + } + $subClass->addInheritedAssociationMapping($mapping); + } + } + + private function addInheritedEmbeddedClasses(ClassMetadata $subClass, ClassMetadata $parentClass) + { + foreach ($parentClass->embeddedClasses as $field => $embeddedClass) { + if ( ! isset($embeddedClass['inherited']) && ! $parentClass->isMappedSuperclass) { + $embeddedClass['inherited'] = $parentClass->name; + } + if ( ! isset($embeddedClass['declared'])) { + $embeddedClass['declared'] = $parentClass->name; + } + + $subClass->embeddedClasses[$field] = $embeddedClass; + } + } + + /** + * Adds nested embedded classes metadata to a parent class. + * + * @param ClassMetadata $subClass Sub embedded class metadata to add nested embedded classes metadata from. + * @param ClassMetadata $parentClass Parent class to add nested embedded classes metadata to. + * @param string $prefix Embedded classes' prefix to use for nested embedded classes field names. + */ + private function addNestedEmbeddedClasses(ClassMetadata $subClass, ClassMetadata $parentClass, $prefix) + { + foreach ($subClass->embeddedClasses as $property => $embeddableClass) { + if (isset($embeddableClass['inherited'])) { + continue; + } + + $embeddableMetadata = $this->getMetadataFor($embeddableClass['class']); + + $parentClass->mapEmbedded( + [ + 'fieldName' => $prefix . '.' . $property, + 'class' => $embeddableMetadata->name, + 'columnPrefix' => $embeddableClass['columnPrefix'], + 'declaredField' => $embeddableClass['declaredField'] + ? $prefix . '.' . $embeddableClass['declaredField'] + : $prefix, + 'originalField' => $embeddableClass['originalField'] ?: $property, + ] + ); + } + } + + /** + * Copy the table indices from the parent class superclass to the child class + * + * @param ClassMetadata $subClass + * @param ClassMetadata $parentClass + * + * @return void + */ + private function addInheritedIndexes(ClassMetadata $subClass, ClassMetadata $parentClass) + { + if (! $parentClass->isMappedSuperclass) { + return; + } + + foreach (['uniqueConstraints', 'indexes'] as $indexType) { + if (isset($parentClass->table[$indexType])) { + foreach ($parentClass->table[$indexType] as $indexName => $index) { + if (isset($subClass->table[$indexType][$indexName])) { + continue; // Let the inheriting table override indices + } + + $subClass->table[$indexType][$indexName] = $index; + } + } + } + } + + /** + * Adds inherited named queries to the subclass mapping. + * + * @since 2.2 + * + * @param \Doctrine\ORM\Mapping\ClassMetadata $subClass + * @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass + * + * @return void + */ + private function addInheritedNamedQueries(ClassMetadata $subClass, ClassMetadata $parentClass) + { + foreach ($parentClass->namedQueries as $name => $query) { + if ( ! isset ($subClass->namedQueries[$name])) { + $subClass->addNamedQuery( + [ + 'name' => $query['name'], + 'query' => $query['query'] + ] + ); + } + } + } + + /** + * Adds inherited named native queries to the subclass mapping. + * + * @since 2.3 + * + * @param \Doctrine\ORM\Mapping\ClassMetadata $subClass + * @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass + * + * @return void + */ + private function addInheritedNamedNativeQueries(ClassMetadata $subClass, ClassMetadata $parentClass) + { + foreach ($parentClass->namedNativeQueries as $name => $query) { + if ( ! isset ($subClass->namedNativeQueries[$name])) { + $subClass->addNamedNativeQuery( + [ + 'name' => $query['name'], + 'query' => $query['query'], + 'isSelfClass' => $query['isSelfClass'], + 'resultSetMapping' => $query['resultSetMapping'], + 'resultClass' => $query['isSelfClass'] ? $subClass->name : $query['resultClass'], + ] + ); + } + } + } + + /** + * Adds inherited sql result set mappings to the subclass mapping. + * + * @since 2.3 + * + * @param \Doctrine\ORM\Mapping\ClassMetadata $subClass + * @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass + * + * @return void + */ + private function addInheritedSqlResultSetMappings(ClassMetadata $subClass, ClassMetadata $parentClass) + { + foreach ($parentClass->sqlResultSetMappings as $name => $mapping) { + if ( ! isset ($subClass->sqlResultSetMappings[$name])) { + $entities = []; + foreach ($mapping['entities'] as $entity) { + $entities[] = [ + 'fields' => $entity['fields'], + 'isSelfClass' => $entity['isSelfClass'], + 'discriminatorColumn' => $entity['discriminatorColumn'], + 'entityClass' => $entity['isSelfClass'] ? $subClass->name : $entity['entityClass'], + ]; + } + + $subClass->addSqlResultSetMapping( + [ + 'name' => $mapping['name'], + 'columns' => $mapping['columns'], + 'entities' => $entities, + ] + ); + } + } + } + + /** + * Completes the ID generator mapping. If "auto" is specified we choose the generator + * most appropriate for the targeted database platform. + * + * @param ClassMetadataInfo $class + * + * @return void + * + * @throws ORMException + */ + private function completeIdGeneratorMapping(ClassMetadataInfo $class) + { + $idGenType = $class->generatorType; + if ($idGenType == ClassMetadata::GENERATOR_TYPE_AUTO) { + if ($this->getTargetPlatform()->prefersSequences()) { + $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_SEQUENCE); + } else if ($this->getTargetPlatform()->prefersIdentityColumns()) { + $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_IDENTITY); + } else { + $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_TABLE); + } + } + + // Create & assign an appropriate ID generator instance + switch ($class->generatorType) { + case ClassMetadata::GENERATOR_TYPE_IDENTITY: + $sequenceName = null; + $fieldName = $class->identifier ? $class->getSingleIdentifierFieldName() : null; + + // Platforms that do not have native IDENTITY support need a sequence to emulate this behaviour. + if ($this->getTargetPlatform()->usesSequenceEmulatedIdentityColumns()) { + $columnName = $class->getSingleIdentifierColumnName(); + $quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']); + $sequencePrefix = $class->getSequencePrefix($this->getTargetPlatform()); + $sequenceName = $this->getTargetPlatform()->getIdentitySequenceName($sequencePrefix, $columnName); + $definition = [ + 'sequenceName' => $this->getTargetPlatform()->fixSchemaElementName($sequenceName) + ]; + + if ($quoted) { + $definition['quoted'] = true; + } + + $sequenceName = $this + ->em + ->getConfiguration() + ->getQuoteStrategy() + ->getSequenceName($definition, $class, $this->getTargetPlatform()); + } + + $generator = ($fieldName && $class->fieldMappings[$fieldName]['type'] === 'bigint') + ? new BigIntegerIdentityGenerator($sequenceName) + : new IdentityGenerator($sequenceName); + + $class->setIdGenerator($generator); + + break; + + case ClassMetadata::GENERATOR_TYPE_SEQUENCE: + // If there is no sequence definition yet, create a default definition + $definition = $class->sequenceGeneratorDefinition; + + if ( ! $definition) { + $fieldName = $class->getSingleIdentifierFieldName(); + $sequenceName = $class->getSequenceName($this->getTargetPlatform()); + $quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']); + + $definition = [ + 'sequenceName' => $this->getTargetPlatform()->fixSchemaElementName($sequenceName), + 'allocationSize' => 1, + 'initialValue' => 1, + ]; + + if ($quoted) { + $definition['quoted'] = true; + } + + $class->setSequenceGeneratorDefinition($definition); + } + + $sequenceGenerator = new \Doctrine\ORM\Id\SequenceGenerator( + $this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->getTargetPlatform()), + $definition['allocationSize'] + ); + $class->setIdGenerator($sequenceGenerator); + break; + + case ClassMetadata::GENERATOR_TYPE_NONE: + $class->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator()); + break; + + case ClassMetadata::GENERATOR_TYPE_UUID: + $class->setIdGenerator(new \Doctrine\ORM\Id\UuidGenerator()); + break; + + case ClassMetadata::GENERATOR_TYPE_TABLE: + throw new ORMException("TableGenerator not yet implemented."); + break; + + case ClassMetadata::GENERATOR_TYPE_CUSTOM: + $definition = $class->customGeneratorDefinition; + if ($definition === null) { + throw new ORMException("Can't instantiate custom generator : no custom generator definition"); + } + if ( ! class_exists($definition['class'])) { + throw new ORMException("Can't instantiate custom generator : " . + $definition['class']); + } + $class->setIdGenerator(new $definition['class']); + break; + + default: + throw new ORMException("Unknown generator type: " . $class->generatorType); + } + } + + /** + * Inherits the ID generator mapping from a parent class. + * + * @param ClassMetadataInfo $class + * @param ClassMetadataInfo $parent + */ + private function inheritIdGeneratorMapping(ClassMetadataInfo $class, ClassMetadataInfo $parent) + { + if ($parent->isIdGeneratorSequence()) { + $class->setSequenceGeneratorDefinition($parent->sequenceGeneratorDefinition); + } elseif ($parent->isIdGeneratorTable()) { + $class->tableGeneratorDefinition = $parent->tableGeneratorDefinition; + } + + if ($parent->generatorType) { + $class->setIdGeneratorType($parent->generatorType); + } + + if ($parent->idGenerator) { + $class->setIdGenerator($parent->idGenerator); + } + } + + /** + * {@inheritDoc} + */ + protected function wakeupReflection(ClassMetadataInterface $class, ReflectionService $reflService) + { + /* @var $class ClassMetadata */ + $class->wakeupReflection($reflService); + } + + /** + * {@inheritDoc} + */ + protected function initializeReflection(ClassMetadataInterface $class, ReflectionService $reflService) + { + /* @var $class ClassMetadata */ + $class->initializeReflection($reflService); + } + + /** + * {@inheritDoc} + */ + protected function getFqcnFromAlias($namespaceAlias, $simpleClassName) + { + return $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName; + } + + /** + * {@inheritDoc} + */ + protected function getDriver() + { + return $this->driver; + } + + /** + * {@inheritDoc} + */ + protected function isEntity(ClassMetadataInterface $class) + { + return isset($class->isMappedSuperclass) && $class->isMappedSuperclass === false; + } + + /** + * @return Platforms\AbstractPlatform + */ + private function getTargetPlatform() + { + if (!$this->targetPlatform) { + $this->targetPlatform = $this->em->getConnection()->getDatabasePlatform(); + } + + return $this->targetPlatform; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php new file mode 100644 index 0000000..8584a78 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php @@ -0,0 +1,3402 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +use BadMethodCallException; +use Doctrine\Instantiator\Instantiator; +use InvalidArgumentException; +use RuntimeException; +use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Platforms\AbstractPlatform; +use ReflectionClass; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Doctrine\ORM\Cache\CacheException; + +/** + * A ClassMetadata instance holds all the object-relational mapping metadata + * of an entity and its associations. + * + * Once populated, ClassMetadata instances are usually cached in a serialized form. + * + * IMPORTANT NOTE: + * + * The fields of this class are only public for 2 reasons: + * 1) To allow fast READ access. + * 2) To drastically reduce the size of a serialized instance (private/protected members + * get the whole class name, namespace inclusive, prepended to every property in + * the serialized representation). + * + * @author Roman Borschel + * @author Jonathan H. Wage + * @since 2.0 + */ +class ClassMetadataInfo implements ClassMetadata +{ + /* The inheritance mapping types */ + /** + * NONE means the class does not participate in an inheritance hierarchy + * and therefore does not need an inheritance mapping type. + */ + const INHERITANCE_TYPE_NONE = 1; + + /** + * JOINED means the class will be persisted according to the rules of + * Class Table Inheritance. + */ + const INHERITANCE_TYPE_JOINED = 2; + + /** + * SINGLE_TABLE means the class will be persisted according to the rules of + * Single Table Inheritance. + */ + const INHERITANCE_TYPE_SINGLE_TABLE = 3; + + /** + * TABLE_PER_CLASS means the class will be persisted according to the rules + * of Concrete Table Inheritance. + */ + const INHERITANCE_TYPE_TABLE_PER_CLASS = 4; + + /* The Id generator types. */ + /** + * AUTO means the generator type will depend on what the used platform prefers. + * Offers full portability. + */ + const GENERATOR_TYPE_AUTO = 1; + + /** + * SEQUENCE means a separate sequence object will be used. Platforms that do + * not have native sequence support may emulate it. Full portability is currently + * not guaranteed. + */ + const GENERATOR_TYPE_SEQUENCE = 2; + + /** + * TABLE means a separate table is used for id generation. + * Offers full portability. + */ + const GENERATOR_TYPE_TABLE = 3; + + /** + * IDENTITY means an identity column is used for id generation. The database + * will fill in the id column on insertion. Platforms that do not support + * native identity columns may emulate them. Full portability is currently + * not guaranteed. + */ + const GENERATOR_TYPE_IDENTITY = 4; + + /** + * NONE means the class does not have a generated id. That means the class + * must have a natural, manually assigned id. + */ + const GENERATOR_TYPE_NONE = 5; + + /** + * UUID means that a UUID/GUID expression is used for id generation. Full + * portability is currently not guaranteed. + */ + const GENERATOR_TYPE_UUID = 6; + + /** + * CUSTOM means that customer will use own ID generator that supposedly work + */ + const GENERATOR_TYPE_CUSTOM = 7; + + /** + * DEFERRED_IMPLICIT means that changes of entities are calculated at commit-time + * by doing a property-by-property comparison with the original data. This will + * be done for all entities that are in MANAGED state at commit-time. + * + * This is the default change tracking policy. + */ + const CHANGETRACKING_DEFERRED_IMPLICIT = 1; + + /** + * DEFERRED_EXPLICIT means that changes of entities are calculated at commit-time + * by doing a property-by-property comparison with the original data. This will + * be done only for entities that were explicitly saved (through persist() or a cascade). + */ + const CHANGETRACKING_DEFERRED_EXPLICIT = 2; + + /** + * NOTIFY means that Doctrine relies on the entities sending out notifications + * when their properties change. Such entity classes must implement + * the NotifyPropertyChanged interface. + */ + const CHANGETRACKING_NOTIFY = 3; + + /** + * Specifies that an association is to be fetched when it is first accessed. + */ + const FETCH_LAZY = 2; + + /** + * Specifies that an association is to be fetched when the owner of the + * association is fetched. + */ + const FETCH_EAGER = 3; + + /** + * Specifies that an association is to be fetched lazy (on first access) and that + * commands such as Collection#count, Collection#slice are issued directly against + * the database if the collection is not yet initialized. + */ + const FETCH_EXTRA_LAZY = 4; + + /** + * Identifies a one-to-one association. + */ + const ONE_TO_ONE = 1; + + /** + * Identifies a many-to-one association. + */ + const MANY_TO_ONE = 2; + + /** + * Identifies a one-to-many association. + */ + const ONE_TO_MANY = 4; + + /** + * Identifies a many-to-many association. + */ + const MANY_TO_MANY = 8; + + /** + * Combined bitmask for to-one (single-valued) associations. + */ + const TO_ONE = 3; + + /** + * Combined bitmask for to-many (collection-valued) associations. + */ + const TO_MANY = 12; + + /** + * ReadOnly cache can do reads, inserts and deletes, cannot perform updates or employ any locks, + */ + const CACHE_USAGE_READ_ONLY = 1; + + /** + * Nonstrict Read Write Cache doesn’t employ any locks but can do inserts, update and deletes. + */ + const CACHE_USAGE_NONSTRICT_READ_WRITE = 2; + + /** + * Read Write Attempts to lock the entity before update/delete. + */ + const CACHE_USAGE_READ_WRITE = 3; + + /** + * READ-ONLY: The name of the entity class. + * + * @var string + */ + public $name; + + /** + * READ-ONLY: The namespace the entity class is contained in. + * + * @var string + * + * @todo Not really needed. Usage could be localized. + */ + public $namespace; + + /** + * READ-ONLY: The name of the entity class that is at the root of the mapped entity inheritance + * hierarchy. If the entity is not part of a mapped inheritance hierarchy this is the same + * as {@link $name}. + * + * @var string + */ + public $rootEntityName; + + /** + * READ-ONLY: The definition of custom generator. Only used for CUSTOM + * generator type + * + * The definition has the following structure: + * + * array( + * 'class' => 'ClassName', + * ) + * + * + * @todo Merge with tableGeneratorDefinition into generic generatorDefinition + * + * @var array|null + */ + public $customGeneratorDefinition; + + /** + * The name of the custom repository class used for the entity class. + * (Optional). + * + * @var string + */ + public $customRepositoryClassName; + + /** + * READ-ONLY: Whether this class describes the mapping of a mapped superclass. + * + * @var boolean + */ + public $isMappedSuperclass = false; + + /** + * READ-ONLY: Whether this class describes the mapping of an embeddable class. + * + * @var boolean + */ + public $isEmbeddedClass = false; + + /** + * READ-ONLY: The names of the parent classes (ancestors). + * + * @var array + */ + public $parentClasses = []; + + /** + * READ-ONLY: The names of all subclasses (descendants). + * + * @var array + */ + public $subClasses = []; + + /** + * READ-ONLY: The names of all embedded classes based on properties. + * + * @var array + */ + public $embeddedClasses = []; + + /** + * READ-ONLY: The named queries allowed to be called directly from Repository. + * + * @var array + */ + public $namedQueries = []; + + /** + * READ-ONLY: The named native queries allowed to be called directly from Repository. + * + * A native SQL named query definition has the following structure: + *
+     * array(
+     *     'name'               => ,
+     *     'query'              => ,
+     *     'resultClass'        => ,
+     *     'resultSetMapping'   => 
+     * )
+     * 
+ * + * @var array + */ + public $namedNativeQueries = []; + + /** + * READ-ONLY: The mappings of the results of native SQL queries. + * + * A native result mapping definition has the following structure: + *
+     * array(
+     *     'name'               => ,
+     *     'entities'           => array(),
+     *     'columns'            => array()
+     * )
+     * 
+ * + * @var array + */ + public $sqlResultSetMappings = []; + + /** + * READ-ONLY: The field names of all fields that are part of the identifier/primary key + * of the mapped entity class. + * + * @var array + */ + public $identifier = []; + + /** + * READ-ONLY: The inheritance mapping type used by the class. + * + * @var integer + */ + public $inheritanceType = self::INHERITANCE_TYPE_NONE; + + /** + * READ-ONLY: The Id generator type used by the class. + * + * @var int + */ + public $generatorType = self::GENERATOR_TYPE_NONE; + + /** + * READ-ONLY: The field mappings of the class. + * Keys are field names and values are mapping definitions. + * + * The mapping definition array has the following values: + * + * - fieldName (string) + * The name of the field in the Entity. + * + * - type (string) + * The type name of the mapped field. Can be one of Doctrine's mapping types + * or a custom mapping type. + * + * - columnName (string, optional) + * The column name. Optional. Defaults to the field name. + * + * - length (integer, optional) + * The database length of the column. Optional. Default value taken from + * the type. + * + * - id (boolean, optional) + * Marks the field as the primary key of the entity. Multiple fields of an + * entity can have the id attribute, forming a composite key. + * + * - nullable (boolean, optional) + * Whether the column is nullable. Defaults to FALSE. + * + * - columnDefinition (string, optional, schema-only) + * The SQL fragment that is used when generating the DDL for the column. + * + * - precision (integer, optional, schema-only) + * The precision of a decimal column. Only valid if the column type is decimal. + * + * - scale (integer, optional, schema-only) + * The scale of a decimal column. Only valid if the column type is decimal. + * + * - 'unique' (string, optional, schema-only) + * Whether a unique constraint should be generated for the column. + * + * @var array + */ + public $fieldMappings = []; + + /** + * READ-ONLY: An array of field names. Used to look up field names from column names. + * Keys are column names and values are field names. + * + * @var array + */ + public $fieldNames = []; + + /** + * READ-ONLY: A map of field names to column names. Keys are field names and values column names. + * Used to look up column names from field names. + * This is the reverse lookup map of $_fieldNames. + * + * @var array + * + * @deprecated 3.0 Remove this. + */ + public $columnNames = []; + + /** + * READ-ONLY: The discriminator value of this class. + * + * This does only apply to the JOINED and SINGLE_TABLE inheritance mapping strategies + * where a discriminator column is used. + * + * @var mixed + * + * @see discriminatorColumn + */ + public $discriminatorValue; + + /** + * READ-ONLY: The discriminator map of all mapped classes in the hierarchy. + * + * This does only apply to the JOINED and SINGLE_TABLE inheritance mapping strategies + * where a discriminator column is used. + * + * @var mixed + * + * @see discriminatorColumn + */ + public $discriminatorMap = []; + + /** + * READ-ONLY: The definition of the discriminator column used in JOINED and SINGLE_TABLE + * inheritance mappings. + * + * @var array + */ + public $discriminatorColumn; + + /** + * READ-ONLY: The primary table definition. The definition is an array with the + * following entries: + * + * name => + * schema => + * indexes => array + * uniqueConstraints => array + * + * @var array + */ + public $table; + + /** + * READ-ONLY: The registered lifecycle callbacks for entities of this class. + * + * @var array[] + */ + public $lifecycleCallbacks = []; + + /** + * READ-ONLY: The registered entity listeners. + * + * @var array + */ + public $entityListeners = []; + + /** + * READ-ONLY: The association mappings of this class. + * + * The mapping definition array supports the following keys: + * + * - fieldName (string) + * The name of the field in the entity the association is mapped to. + * + * - targetEntity (string) + * The class name of the target entity. If it is fully-qualified it is used as is. + * If it is a simple, unqualified class name the namespace is assumed to be the same + * as the namespace of the source entity. + * + * - mappedBy (string, required for bidirectional associations) + * The name of the field that completes the bidirectional association on the owning side. + * This key must be specified on the inverse side of a bidirectional association. + * + * - inversedBy (string, required for bidirectional associations) + * The name of the field that completes the bidirectional association on the inverse side. + * This key must be specified on the owning side of a bidirectional association. + * + * - cascade (array, optional) + * The names of persistence operations to cascade on the association. The set of possible + * values are: "persist", "remove", "detach", "merge", "refresh", "all" (implies all others). + * + * - orderBy (array, one-to-many/many-to-many only) + * A map of field names (of the target entity) to sorting directions (ASC/DESC). + * Example: array('priority' => 'desc') + * + * - fetch (integer, optional) + * The fetching strategy to use for the association, usually defaults to FETCH_LAZY. + * Possible values are: ClassMetadata::FETCH_EAGER, ClassMetadata::FETCH_LAZY. + * + * - joinTable (array, optional, many-to-many only) + * Specification of the join table and its join columns (foreign keys). + * Only valid for many-to-many mappings. Note that one-to-many associations can be mapped + * through a join table by simply mapping the association as many-to-many with a unique + * constraint on the join table. + * + * - indexBy (string, optional, to-many only) + * Specification of a field on target-entity that is used to index the collection by. + * This field HAS to be either the primary key or a unique column. Otherwise the collection + * does not contain all the entities that are actually related. + * + * A join table definition has the following structure: + *
+     * array(
+     *     'name' => ,
+     *      'joinColumns' => array(),
+     *      'inverseJoinColumns' => array()
+     * )
+     * 
+ * + * @var array + */ + public $associationMappings = []; + + /** + * READ-ONLY: Flag indicating whether the identifier/primary key of the class is composite. + * + * @var boolean + */ + public $isIdentifierComposite = false; + + /** + * READ-ONLY: Flag indicating whether the identifier/primary key contains at least one foreign key association. + * + * This flag is necessary because some code blocks require special treatment of this cases. + * + * @var boolean + */ + public $containsForeignIdentifier = false; + + /** + * READ-ONLY: The ID generator used for generating IDs for this class. + * + * @var \Doctrine\ORM\Id\AbstractIdGenerator + * + * @todo Remove! + */ + public $idGenerator; + + /** + * READ-ONLY: The definition of the sequence generator of this class. Only used for the + * SEQUENCE generation strategy. + * + * The definition has the following structure: + * + * array( + * 'sequenceName' => 'name', + * 'allocationSize' => 20, + * 'initialValue' => 1 + * ) + * + * + * @var array + * + * @todo Merge with tableGeneratorDefinition into generic generatorDefinition + */ + public $sequenceGeneratorDefinition; + + /** + * READ-ONLY: The definition of the table generator of this class. Only used for the + * TABLE generation strategy. + * + * @var array + * + * @todo Merge with tableGeneratorDefinition into generic generatorDefinition + */ + public $tableGeneratorDefinition; + + /** + * READ-ONLY: The policy used for change-tracking on entities of this class. + * + * @var integer + */ + public $changeTrackingPolicy = self::CHANGETRACKING_DEFERRED_IMPLICIT; + + /** + * READ-ONLY: A flag for whether or not instances of this class are to be versioned + * with optimistic locking. + * + * @var boolean + */ + public $isVersioned; + + /** + * READ-ONLY: The name of the field which is used for versioning in optimistic locking (if any). + * + * @var mixed + */ + public $versionField; + + /** + * @var array + */ + public $cache = null; + + /** + * The ReflectionClass instance of the mapped class. + * + * @var ReflectionClass + */ + public $reflClass; + + /** + * Is this entity marked as "read-only"? + * + * That means it is never considered for change-tracking in the UnitOfWork. It is a very helpful performance + * optimization for entities that are immutable, either in your domain or through the relation database + * (coming from a view, or a history table for example). + * + * @var bool + */ + public $isReadOnly = false; + + /** + * NamingStrategy determining the default column and table names. + * + * @var \Doctrine\ORM\Mapping\NamingStrategy + */ + protected $namingStrategy; + + /** + * The ReflectionProperty instances of the mapped class. + * + * @var \ReflectionProperty[] + */ + public $reflFields = []; + + /** + * @var \Doctrine\Instantiator\InstantiatorInterface|null + */ + private $instantiator; + + /** + * Initializes a new ClassMetadata instance that will hold the object-relational mapping + * metadata of the class with the given name. + * + * @param string $entityName The name of the entity class the new instance is used for. + * @param NamingStrategy|null $namingStrategy + */ + public function __construct($entityName, NamingStrategy $namingStrategy = null) + { + $this->name = $entityName; + $this->rootEntityName = $entityName; + $this->namingStrategy = $namingStrategy ?: new DefaultNamingStrategy(); + $this->instantiator = new Instantiator(); + } + + /** + * Gets the ReflectionProperties of the mapped class. + * + * @return array An array of ReflectionProperty instances. + */ + public function getReflectionProperties() + { + return $this->reflFields; + } + + /** + * Gets a ReflectionProperty for a specific field of the mapped class. + * + * @param string $name + * + * @return \ReflectionProperty + */ + public function getReflectionProperty($name) + { + return $this->reflFields[$name]; + } + + /** + * Gets the ReflectionProperty for the single identifier field. + * + * @return \ReflectionProperty + * + * @throws BadMethodCallException If the class has a composite identifier. + */ + public function getSingleIdReflectionProperty() + { + if ($this->isIdentifierComposite) { + throw new BadMethodCallException("Class " . $this->name . " has a composite identifier."); + } + + return $this->reflFields[$this->identifier[0]]; + } + + /** + * Extracts the identifier values of an entity of this class. + * + * For composite identifiers, the identifier values are returned as an array + * with the same order as the field order in {@link identifier}. + * + * @param object $entity + * + * @return array + */ + public function getIdentifierValues($entity) + { + if ($this->isIdentifierComposite) { + $id = []; + + foreach ($this->identifier as $idField) { + $value = $this->reflFields[$idField]->getValue($entity); + + if (null !== $value) { + $id[$idField] = $value; + } + } + + return $id; + } + + $id = $this->identifier[0]; + $value = $this->reflFields[$id]->getValue($entity); + + if (null === $value) { + return []; + } + + return [$id => $value]; + } + + /** + * Populates the entity identifier of an entity. + * + * @param object $entity + * @param array $id + * + * @return void + * + * @todo Rename to assignIdentifier() + */ + public function setIdentifierValues($entity, array $id) + { + foreach ($id as $idField => $idValue) { + $this->reflFields[$idField]->setValue($entity, $idValue); + } + } + + /** + * Sets the specified field to the specified value on the given entity. + * + * @param object $entity + * @param string $field + * @param mixed $value + * + * @return void + */ + public function setFieldValue($entity, $field, $value) + { + $this->reflFields[$field]->setValue($entity, $value); + } + + /** + * Gets the specified field's value off the given entity. + * + * @param object $entity + * @param string $field + * + * @return mixed + */ + public function getFieldValue($entity, $field) + { + return $this->reflFields[$field]->getValue($entity); + } + + /** + * Creates a string representation of this instance. + * + * @return string The string representation of this instance. + * + * @todo Construct meaningful string representation. + */ + public function __toString() + { + return __CLASS__ . '@' . spl_object_hash($this); + } + + /** + * Determines which fields get serialized. + * + * It is only serialized what is necessary for best unserialization performance. + * That means any metadata properties that are not set or empty or simply have + * their default value are NOT serialized. + * + * Parts that are also NOT serialized because they can not be properly unserialized: + * - reflClass (ReflectionClass) + * - reflFields (ReflectionProperty array) + * + * @return array The names of all the fields that should be serialized. + */ + public function __sleep() + { + // This metadata is always serialized/cached. + $serialized = [ + 'associationMappings', + 'columnNames', //TODO: 3.0 Remove this. Can use fieldMappings[$fieldName]['columnName'] + 'fieldMappings', + 'fieldNames', + 'embeddedClasses', + 'identifier', + 'isIdentifierComposite', // TODO: REMOVE + 'name', + 'namespace', // TODO: REMOVE + 'table', + 'rootEntityName', + 'idGenerator', //TODO: Does not really need to be serialized. Could be moved to runtime. + ]; + + // The rest of the metadata is only serialized if necessary. + if ($this->changeTrackingPolicy != self::CHANGETRACKING_DEFERRED_IMPLICIT) { + $serialized[] = 'changeTrackingPolicy'; + } + + if ($this->customRepositoryClassName) { + $serialized[] = 'customRepositoryClassName'; + } + + if ($this->inheritanceType != self::INHERITANCE_TYPE_NONE) { + $serialized[] = 'inheritanceType'; + $serialized[] = 'discriminatorColumn'; + $serialized[] = 'discriminatorValue'; + $serialized[] = 'discriminatorMap'; + $serialized[] = 'parentClasses'; + $serialized[] = 'subClasses'; + } + + if ($this->generatorType != self::GENERATOR_TYPE_NONE) { + $serialized[] = 'generatorType'; + if ($this->generatorType == self::GENERATOR_TYPE_SEQUENCE) { + $serialized[] = 'sequenceGeneratorDefinition'; + } + } + + if ($this->isMappedSuperclass) { + $serialized[] = 'isMappedSuperclass'; + } + + if ($this->isEmbeddedClass) { + $serialized[] = 'isEmbeddedClass'; + } + + if ($this->containsForeignIdentifier) { + $serialized[] = 'containsForeignIdentifier'; + } + + if ($this->isVersioned) { + $serialized[] = 'isVersioned'; + $serialized[] = 'versionField'; + } + + if ($this->lifecycleCallbacks) { + $serialized[] = 'lifecycleCallbacks'; + } + + if ($this->entityListeners) { + $serialized[] = 'entityListeners'; + } + + if ($this->namedQueries) { + $serialized[] = 'namedQueries'; + } + + if ($this->namedNativeQueries) { + $serialized[] = 'namedNativeQueries'; + } + + if ($this->sqlResultSetMappings) { + $serialized[] = 'sqlResultSetMappings'; + } + + if ($this->isReadOnly) { + $serialized[] = 'isReadOnly'; + } + + if ($this->customGeneratorDefinition) { + $serialized[] = "customGeneratorDefinition"; + } + + if ($this->cache) { + $serialized[] = 'cache'; + } + + return $serialized; + } + + /** + * Creates a new instance of the mapped class, without invoking the constructor. + * + * @return object + */ + public function newInstance() + { + return $this->instantiator->instantiate($this->name); + } + + /** + * Restores some state that can not be serialized/unserialized. + * + * @param \Doctrine\Common\Persistence\Mapping\ReflectionService $reflService + * + * @return void + */ + public function wakeupReflection($reflService) + { + // Restore ReflectionClass and properties + $this->reflClass = $reflService->getClass($this->name); + $this->instantiator = $this->instantiator ?: new Instantiator(); + + $parentReflFields = []; + + foreach ($this->embeddedClasses as $property => $embeddedClass) { + if (isset($embeddedClass['declaredField'])) { + $parentReflFields[$property] = new ReflectionEmbeddedProperty( + $parentReflFields[$embeddedClass['declaredField']], + $reflService->getAccessibleProperty( + $this->embeddedClasses[$embeddedClass['declaredField']]['class'], + $embeddedClass['originalField'] + ), + $this->embeddedClasses[$embeddedClass['declaredField']]['class'] + ); + + continue; + } + + $fieldRefl = $reflService->getAccessibleProperty( + $embeddedClass['declared'] ?? $this->name, + $property + ); + + $parentReflFields[$property] = $fieldRefl; + $this->reflFields[$property] = $fieldRefl; + } + + foreach ($this->fieldMappings as $field => $mapping) { + if (isset($mapping['declaredField']) && isset($parentReflFields[$mapping['declaredField']])) { + $this->reflFields[$field] = new ReflectionEmbeddedProperty( + $parentReflFields[$mapping['declaredField']], + $reflService->getAccessibleProperty($mapping['originalClass'], $mapping['originalField']), + $mapping['originalClass'] + ); + continue; + } + + $this->reflFields[$field] = isset($mapping['declared']) + ? $reflService->getAccessibleProperty($mapping['declared'], $field) + : $reflService->getAccessibleProperty($this->name, $field); + } + + foreach ($this->associationMappings as $field => $mapping) { + $this->reflFields[$field] = isset($mapping['declared']) + ? $reflService->getAccessibleProperty($mapping['declared'], $field) + : $reflService->getAccessibleProperty($this->name, $field); + } + } + + /** + * Initializes a new ClassMetadata instance that will hold the object-relational mapping + * metadata of the class with the given name. + * + * @param \Doctrine\Common\Persistence\Mapping\ReflectionService $reflService The reflection service. + * + * @return void + */ + public function initializeReflection($reflService) + { + $this->reflClass = $reflService->getClass($this->name); + $this->namespace = $reflService->getClassNamespace($this->name); + + if ($this->reflClass) { + $this->name = $this->rootEntityName = $this->reflClass->getName(); + } + + $this->table['name'] = $this->namingStrategy->classToTableName($this->name); + } + + /** + * Validates Identifier. + * + * @return void + * + * @throws MappingException + */ + public function validateIdentifier() + { + if ($this->isMappedSuperclass || $this->isEmbeddedClass) { + return; + } + + // Verify & complete identifier mapping + if ( ! $this->identifier) { + throw MappingException::identifierRequired($this->name); + } + + if ($this->usesIdGenerator() && $this->isIdentifierComposite) { + throw MappingException::compositeKeyAssignedIdGeneratorRequired($this->name); + } + } + + /** + * Validates association targets actually exist. + * + * @return void + * + * @throws MappingException + */ + public function validateAssociations() + { + foreach ($this->associationMappings as $mapping) { + if ( + ! class_exists($mapping['targetEntity']) + && ! interface_exists($mapping['targetEntity']) + && ! trait_exists($mapping['targetEntity']) + ) { + throw MappingException::invalidTargetEntityClass($mapping['targetEntity'], $this->name, $mapping['fieldName']); + } + } + } + + /** + * Validates lifecycle callbacks. + * + * @param \Doctrine\Common\Persistence\Mapping\ReflectionService $reflService + * + * @return void + * + * @throws MappingException + */ + public function validateLifecycleCallbacks($reflService) + { + foreach ($this->lifecycleCallbacks as $callbacks) { + foreach ($callbacks as $callbackFuncName) { + if ( ! $reflService->hasPublicMethod($this->name, $callbackFuncName)) { + throw MappingException::lifecycleCallbackMethodNotFound($this->name, $callbackFuncName); + } + } + } + } + + /** + * {@inheritDoc} + */ + public function getReflectionClass() + { + return $this->reflClass; + } + + /** + * @param array $cache + * + * @return void + */ + public function enableCache(array $cache) + { + if ( ! isset($cache['usage'])) { + $cache['usage'] = self::CACHE_USAGE_READ_ONLY; + } + + if ( ! isset($cache['region'])) { + $cache['region'] = strtolower(str_replace('\\', '_', $this->rootEntityName)); + } + + $this->cache = $cache; + } + + /** + * @param string $fieldName + * @param array $cache + * + * @return void + */ + public function enableAssociationCache($fieldName, array $cache) + { + $this->associationMappings[$fieldName]['cache'] = $this->getAssociationCacheDefaults($fieldName, $cache); + } + + /** + * @param string $fieldName + * @param array $cache + * + * @return array + */ + public function getAssociationCacheDefaults($fieldName, array $cache) + { + if ( ! isset($cache['usage'])) { + $cache['usage'] = isset($this->cache['usage']) + ? $this->cache['usage'] + : self::CACHE_USAGE_READ_ONLY; + } + + if ( ! isset($cache['region'])) { + $cache['region'] = strtolower(str_replace('\\', '_', $this->rootEntityName)) . '__' . $fieldName; + } + + return $cache; + } + + /** + * Sets the change tracking policy used by this class. + * + * @param integer $policy + * + * @return void + */ + public function setChangeTrackingPolicy($policy) + { + $this->changeTrackingPolicy = $policy; + } + + /** + * Whether the change tracking policy of this class is "deferred explicit". + * + * @return boolean + */ + public function isChangeTrackingDeferredExplicit() + { + return self::CHANGETRACKING_DEFERRED_EXPLICIT === $this->changeTrackingPolicy; + } + + /** + * Whether the change tracking policy of this class is "deferred implicit". + * + * @return boolean + */ + public function isChangeTrackingDeferredImplicit() + { + return self::CHANGETRACKING_DEFERRED_IMPLICIT === $this->changeTrackingPolicy; + } + + /** + * Whether the change tracking policy of this class is "notify". + * + * @return boolean + */ + public function isChangeTrackingNotify() + { + return self::CHANGETRACKING_NOTIFY === $this->changeTrackingPolicy; + } + + /** + * Checks whether a field is part of the identifier/primary key field(s). + * + * @param string $fieldName The field name. + * + * @return boolean TRUE if the field is part of the table identifier/primary key field(s), + * FALSE otherwise. + */ + public function isIdentifier($fieldName) + { + if ( ! $this->identifier) { + return false; + } + + if ( ! $this->isIdentifierComposite) { + return $fieldName === $this->identifier[0]; + } + + return in_array($fieldName, $this->identifier, true); + } + + /** + * Checks if the field is unique. + * + * @param string $fieldName The field name. + * + * @return boolean TRUE if the field is unique, FALSE otherwise. + */ + public function isUniqueField($fieldName) + { + $mapping = $this->getFieldMapping($fieldName); + + return false !== $mapping && isset($mapping['unique']) && $mapping['unique']; + } + + /** + * Checks if the field is not null. + * + * @param string $fieldName The field name. + * + * @return boolean TRUE if the field is not null, FALSE otherwise. + */ + public function isNullable($fieldName) + { + $mapping = $this->getFieldMapping($fieldName); + + return false !== $mapping && isset($mapping['nullable']) && $mapping['nullable']; + } + + /** + * Gets a column name for a field name. + * If the column name for the field cannot be found, the given field name + * is returned. + * + * @param string $fieldName The field name. + * + * @return string The column name. + */ + public function getColumnName($fieldName) + { + return isset($this->columnNames[$fieldName]) + ? $this->columnNames[$fieldName] + : $fieldName; + } + + /** + * Gets the mapping of a (regular) field that holds some data but not a + * reference to another object. + * + * @param string $fieldName The field name. + * + * @return array The field mapping. + * + * @throws MappingException + */ + public function getFieldMapping($fieldName) + { + if ( ! isset($this->fieldMappings[$fieldName])) { + throw MappingException::mappingNotFound($this->name, $fieldName); + } + + return $this->fieldMappings[$fieldName]; + } + + /** + * Gets the mapping of an association. + * + * @see ClassMetadataInfo::$associationMappings + * + * @param string $fieldName The field name that represents the association in + * the object model. + * + * @return array The mapping. + * + * @throws MappingException + */ + public function getAssociationMapping($fieldName) + { + if ( ! isset($this->associationMappings[$fieldName])) { + throw MappingException::mappingNotFound($this->name, $fieldName); + } + + return $this->associationMappings[$fieldName]; + } + + /** + * Gets all association mappings of the class. + * + * @return array + */ + public function getAssociationMappings() + { + return $this->associationMappings; + } + + /** + * Gets the field name for a column name. + * If no field name can be found the column name is returned. + * + * @param string $columnName The column name. + * + * @return string The column alias. + */ + public function getFieldName($columnName) + { + return isset($this->fieldNames[$columnName]) + ? $this->fieldNames[$columnName] + : $columnName; + } + + /** + * Gets the named query. + * + * @see ClassMetadataInfo::$namedQueries + * + * @param string $queryName The query name. + * + * @return string + * + * @throws MappingException + */ + public function getNamedQuery($queryName) + { + if ( ! isset($this->namedQueries[$queryName])) { + throw MappingException::queryNotFound($this->name, $queryName); + } + + return $this->namedQueries[$queryName]['dql']; + } + + /** + * Gets all named queries of the class. + * + * @return array + */ + public function getNamedQueries() + { + return $this->namedQueries; + } + + /** + * Gets the named native query. + * + * @see ClassMetadataInfo::$namedNativeQueries + * + * @param string $queryName The query name. + * + * @return array + * + * @throws MappingException + */ + public function getNamedNativeQuery($queryName) + { + if ( ! isset($this->namedNativeQueries[$queryName])) { + throw MappingException::queryNotFound($this->name, $queryName); + } + + return $this->namedNativeQueries[$queryName]; + } + + /** + * Gets all named native queries of the class. + * + * @return array + */ + public function getNamedNativeQueries() + { + return $this->namedNativeQueries; + } + + /** + * Gets the result set mapping. + * + * @see ClassMetadataInfo::$sqlResultSetMappings + * + * @param string $name The result set mapping name. + * + * @return array + * + * @throws MappingException + */ + public function getSqlResultSetMapping($name) + { + if ( ! isset($this->sqlResultSetMappings[$name])) { + throw MappingException::resultMappingNotFound($this->name, $name); + } + + return $this->sqlResultSetMappings[$name]; + } + + /** + * Gets all sql result set mappings of the class. + * + * @return array + */ + public function getSqlResultSetMappings() + { + return $this->sqlResultSetMappings; + } + + /** + * Validates & completes the given field mapping. + * + * @param array $mapping The field mapping to validate & complete. + * + * @return void + * + * @throws MappingException + */ + protected function _validateAndCompleteFieldMapping(array &$mapping) + { + // Check mandatory fields + if ( ! isset($mapping['fieldName']) || !$mapping['fieldName']) { + throw MappingException::missingFieldName($this->name); + } + + if ( ! isset($mapping['type'])) { + // Default to string + $mapping['type'] = 'string'; + } + + // Complete fieldName and columnName mapping + if ( ! isset($mapping['columnName'])) { + $mapping['columnName'] = $this->namingStrategy->propertyToColumnName($mapping['fieldName'], $this->name); + } + + if ('`' === $mapping['columnName'][0]) { + $mapping['columnName'] = trim($mapping['columnName'], '`'); + $mapping['quoted'] = true; + } + + $this->columnNames[$mapping['fieldName']] = $mapping['columnName']; + + if (isset($this->fieldNames[$mapping['columnName']]) || ($this->discriminatorColumn && $this->discriminatorColumn['name'] === $mapping['columnName'])) { + throw MappingException::duplicateColumnName($this->name, $mapping['columnName']); + } + + $this->fieldNames[$mapping['columnName']] = $mapping['fieldName']; + + // Complete id mapping + if (isset($mapping['id']) && true === $mapping['id']) { + if ($this->versionField == $mapping['fieldName']) { + throw MappingException::cannotVersionIdField($this->name, $mapping['fieldName']); + } + + if ( ! in_array($mapping['fieldName'], $this->identifier)) { + $this->identifier[] = $mapping['fieldName']; + } + + // Check for composite key + if ( ! $this->isIdentifierComposite && count($this->identifier) > 1) { + $this->isIdentifierComposite = true; + } + } + + if (Type::hasType($mapping['type']) && Type::getType($mapping['type'])->canRequireSQLConversion()) { + if (isset($mapping['id']) && true === $mapping['id']) { + throw MappingException::sqlConversionNotAllowedForIdentifiers($this->name, $mapping['fieldName'], $mapping['type']); + } + + $mapping['requireSQLConversion'] = true; + } + } + + /** + * Validates & completes the basic mapping information that is common to all + * association mappings (one-to-one, many-ot-one, one-to-many, many-to-many). + * + * @param array $mapping The mapping. + * + * @return array The updated mapping. + * + * @throws MappingException If something is wrong with the mapping. + */ + protected function _validateAndCompleteAssociationMapping(array $mapping) + { + if ( ! isset($mapping['mappedBy'])) { + $mapping['mappedBy'] = null; + } + + if ( ! isset($mapping['inversedBy'])) { + $mapping['inversedBy'] = null; + } + + $mapping['isOwningSide'] = true; // assume owning side until we hit mappedBy + + if (empty($mapping['indexBy'])) { + unset($mapping['indexBy']); + } + + // If targetEntity is unqualified, assume it is in the same namespace as + // the sourceEntity. + $mapping['sourceEntity'] = $this->name; + + if (isset($mapping['targetEntity'])) { + $mapping['targetEntity'] = $this->fullyQualifiedClassName($mapping['targetEntity']); + $mapping['targetEntity'] = ltrim($mapping['targetEntity'], '\\'); + } + + if (($mapping['type'] & self::MANY_TO_ONE) > 0 && isset($mapping['orphanRemoval']) && $mapping['orphanRemoval']) { + throw MappingException::illegalOrphanRemoval($this->name, $mapping['fieldName']); + } + + // Complete id mapping + if (isset($mapping['id']) && true === $mapping['id']) { + if (isset($mapping['orphanRemoval']) && $mapping['orphanRemoval']) { + throw MappingException::illegalOrphanRemovalOnIdentifierAssociation($this->name, $mapping['fieldName']); + } + + if ( ! in_array($mapping['fieldName'], $this->identifier)) { + if (isset($mapping['joinColumns']) && count($mapping['joinColumns']) >= 2) { + throw MappingException::cannotMapCompositePrimaryKeyEntitiesAsForeignId( + $mapping['targetEntity'], $this->name, $mapping['fieldName'] + ); + } + + $this->identifier[] = $mapping['fieldName']; + $this->containsForeignIdentifier = true; + } + + // Check for composite key + if ( ! $this->isIdentifierComposite && count($this->identifier) > 1) { + $this->isIdentifierComposite = true; + } + + if ($this->cache && !isset($mapping['cache'])) { + throw CacheException::nonCacheableEntityAssociation($this->name, $mapping['fieldName']); + } + } + + // Mandatory attributes for both sides + // Mandatory: fieldName, targetEntity + if ( ! isset($mapping['fieldName']) || !$mapping['fieldName']) { + throw MappingException::missingFieldName($this->name); + } + + if ( ! isset($mapping['targetEntity'])) { + throw MappingException::missingTargetEntity($mapping['fieldName']); + } + + // Mandatory and optional attributes for either side + if ( ! $mapping['mappedBy']) { + if (isset($mapping['joinTable']) && $mapping['joinTable']) { + if (isset($mapping['joinTable']['name']) && $mapping['joinTable']['name'][0] === '`') { + $mapping['joinTable']['name'] = trim($mapping['joinTable']['name'], '`'); + $mapping['joinTable']['quoted'] = true; + } + } + } else { + $mapping['isOwningSide'] = false; + } + + if (isset($mapping['id']) && true === $mapping['id'] && $mapping['type'] & self::TO_MANY) { + throw MappingException::illegalToManyIdentifierAssociation($this->name, $mapping['fieldName']); + } + + // Fetch mode. Default fetch mode to LAZY, if not set. + if ( ! isset($mapping['fetch'])) { + $mapping['fetch'] = self::FETCH_LAZY; + } + + // Cascades + $cascades = isset($mapping['cascade']) ? array_map('strtolower', $mapping['cascade']) : []; + + $allCascades = ['remove', 'persist', 'refresh', 'merge', 'detach']; + if (in_array('all', $cascades)) { + $cascades = $allCascades; + } elseif (count($cascades) !== count(array_intersect($cascades, $allCascades))) { + throw MappingException::invalidCascadeOption( + array_diff($cascades, $allCascades), + $this->name, + $mapping['fieldName'] + ); + } + + $mapping['cascade'] = $cascades; + $mapping['isCascadeRemove'] = in_array('remove', $cascades); + $mapping['isCascadePersist'] = in_array('persist', $cascades); + $mapping['isCascadeRefresh'] = in_array('refresh', $cascades); + $mapping['isCascadeMerge'] = in_array('merge', $cascades); + $mapping['isCascadeDetach'] = in_array('detach', $cascades); + + return $mapping; + } + + /** + * Validates & completes a one-to-one association mapping. + * + * @param array $mapping The mapping to validate & complete. + * + * @return array The validated & completed mapping. + * + * @throws RuntimeException + * @throws MappingException + */ + protected function _validateAndCompleteOneToOneMapping(array $mapping) + { + $mapping = $this->_validateAndCompleteAssociationMapping($mapping); + + if (isset($mapping['joinColumns']) && $mapping['joinColumns']) { + $mapping['isOwningSide'] = true; + } + + if ($mapping['isOwningSide']) { + if (empty($mapping['joinColumns'])) { + // Apply default join column + $mapping['joinColumns'] = [ + [ + 'name' => $this->namingStrategy->joinColumnName($mapping['fieldName'], $this->name), + 'referencedColumnName' => $this->namingStrategy->referenceColumnName() + ] + ]; + } + + $uniqueConstraintColumns = []; + + foreach ($mapping['joinColumns'] as &$joinColumn) { + if ($mapping['type'] === self::ONE_TO_ONE && ! $this->isInheritanceTypeSingleTable()) { + if (count($mapping['joinColumns']) === 1) { + if (empty($mapping['id'])) { + $joinColumn['unique'] = true; + } + } else { + $uniqueConstraintColumns[] = $joinColumn['name']; + } + } + + if (empty($joinColumn['name'])) { + $joinColumn['name'] = $this->namingStrategy->joinColumnName($mapping['fieldName'], $this->name); + } + + if (empty($joinColumn['referencedColumnName'])) { + $joinColumn['referencedColumnName'] = $this->namingStrategy->referenceColumnName(); + } + + if ($joinColumn['name'][0] === '`') { + $joinColumn['name'] = trim($joinColumn['name'], '`'); + $joinColumn['quoted'] = true; + } + + if ($joinColumn['referencedColumnName'][0] === '`') { + $joinColumn['referencedColumnName'] = trim($joinColumn['referencedColumnName'], '`'); + $joinColumn['quoted'] = true; + } + + $mapping['sourceToTargetKeyColumns'][$joinColumn['name']] = $joinColumn['referencedColumnName']; + $mapping['joinColumnFieldNames'][$joinColumn['name']] = $joinColumn['fieldName'] ?? $joinColumn['name']; + } + + if ($uniqueConstraintColumns) { + if ( ! $this->table) { + throw new RuntimeException("ClassMetadataInfo::setTable() has to be called before defining a one to one relationship."); + } + + $this->table['uniqueConstraints'][$mapping['fieldName'] . "_uniq"] = [ + 'columns' => $uniqueConstraintColumns + ]; + } + + $mapping['targetToSourceKeyColumns'] = array_flip($mapping['sourceToTargetKeyColumns']); + } + + $mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) && $mapping['orphanRemoval']; + $mapping['isCascadeRemove'] = $mapping['orphanRemoval'] || $mapping['isCascadeRemove']; + + if ($mapping['orphanRemoval']) { + unset($mapping['unique']); + } + + if (isset($mapping['id']) && $mapping['id'] === true && !$mapping['isOwningSide']) { + throw MappingException::illegalInverseIdentifierAssociation($this->name, $mapping['fieldName']); + } + + return $mapping; + } + + /** + * Validates & completes a one-to-many association mapping. + * + * @param array $mapping The mapping to validate and complete. + * + * @return array The validated and completed mapping. + * + * @throws MappingException + * @throws InvalidArgumentException + */ + protected function _validateAndCompleteOneToManyMapping(array $mapping) + { + $mapping = $this->_validateAndCompleteAssociationMapping($mapping); + + // OneToMany-side MUST be inverse (must have mappedBy) + if ( ! isset($mapping['mappedBy'])) { + throw MappingException::oneToManyRequiresMappedBy($mapping['fieldName']); + } + + $mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) && $mapping['orphanRemoval']; + $mapping['isCascadeRemove'] = $mapping['orphanRemoval'] || $mapping['isCascadeRemove']; + + $this->assertMappingOrderBy($mapping); + + return $mapping; + } + + /** + * Validates & completes a many-to-many association mapping. + * + * @param array $mapping The mapping to validate & complete. + * + * @return array The validated & completed mapping. + * + * @throws \InvalidArgumentException + */ + protected function _validateAndCompleteManyToManyMapping(array $mapping) + { + $mapping = $this->_validateAndCompleteAssociationMapping($mapping); + + if ($mapping['isOwningSide']) { + // owning side MUST have a join table + if ( ! isset($mapping['joinTable']['name'])) { + $mapping['joinTable']['name'] = $this->namingStrategy->joinTableName($mapping['sourceEntity'], $mapping['targetEntity'], $mapping['fieldName']); + } + + $selfReferencingEntityWithoutJoinColumns = $mapping['sourceEntity'] == $mapping['targetEntity'] + && (! (isset($mapping['joinTable']['joinColumns']) || isset($mapping['joinTable']['inverseJoinColumns']))); + + if ( ! isset($mapping['joinTable']['joinColumns'])) { + $mapping['joinTable']['joinColumns'] = [ + [ + 'name' => $this->namingStrategy->joinKeyColumnName($mapping['sourceEntity'], $selfReferencingEntityWithoutJoinColumns ? 'source' : null), + 'referencedColumnName' => $this->namingStrategy->referenceColumnName(), + 'onDelete' => 'CASCADE' + ] + ]; + } + + if ( ! isset($mapping['joinTable']['inverseJoinColumns'])) { + $mapping['joinTable']['inverseJoinColumns'] = [ + [ + 'name' => $this->namingStrategy->joinKeyColumnName($mapping['targetEntity'], $selfReferencingEntityWithoutJoinColumns ? 'target' : null), + 'referencedColumnName' => $this->namingStrategy->referenceColumnName(), + 'onDelete' => 'CASCADE' + ] + ]; + } + + $mapping['joinTableColumns'] = []; + + foreach ($mapping['joinTable']['joinColumns'] as &$joinColumn) { + if (empty($joinColumn['name'])) { + $joinColumn['name'] = $this->namingStrategy->joinKeyColumnName($mapping['sourceEntity'], $joinColumn['referencedColumnName']); + } + + if (empty($joinColumn['referencedColumnName'])) { + $joinColumn['referencedColumnName'] = $this->namingStrategy->referenceColumnName(); + } + + if ($joinColumn['name'][0] === '`') { + $joinColumn['name'] = trim($joinColumn['name'], '`'); + $joinColumn['quoted'] = true; + } + + if ($joinColumn['referencedColumnName'][0] === '`') { + $joinColumn['referencedColumnName'] = trim($joinColumn['referencedColumnName'], '`'); + $joinColumn['quoted'] = true; + } + + if (isset($joinColumn['onDelete']) && strtolower($joinColumn['onDelete']) == 'cascade') { + $mapping['isOnDeleteCascade'] = true; + } + + $mapping['relationToSourceKeyColumns'][$joinColumn['name']] = $joinColumn['referencedColumnName']; + $mapping['joinTableColumns'][] = $joinColumn['name']; + } + + foreach ($mapping['joinTable']['inverseJoinColumns'] as &$inverseJoinColumn) { + if (empty($inverseJoinColumn['name'])) { + $inverseJoinColumn['name'] = $this->namingStrategy->joinKeyColumnName($mapping['targetEntity'], $inverseJoinColumn['referencedColumnName']); + } + + if (empty($inverseJoinColumn['referencedColumnName'])) { + $inverseJoinColumn['referencedColumnName'] = $this->namingStrategy->referenceColumnName(); + } + + if ($inverseJoinColumn['name'][0] === '`') { + $inverseJoinColumn['name'] = trim($inverseJoinColumn['name'], '`'); + $inverseJoinColumn['quoted'] = true; + } + + if ($inverseJoinColumn['referencedColumnName'][0] === '`') { + $inverseJoinColumn['referencedColumnName'] = trim($inverseJoinColumn['referencedColumnName'], '`'); + $inverseJoinColumn['quoted'] = true; + } + + if (isset($inverseJoinColumn['onDelete']) && strtolower($inverseJoinColumn['onDelete']) == 'cascade') { + $mapping['isOnDeleteCascade'] = true; + } + + $mapping['relationToTargetKeyColumns'][$inverseJoinColumn['name']] = $inverseJoinColumn['referencedColumnName']; + $mapping['joinTableColumns'][] = $inverseJoinColumn['name']; + } + } + + $mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) && $mapping['orphanRemoval']; + + $this->assertMappingOrderBy($mapping); + + return $mapping; + } + + /** + * {@inheritDoc} + */ + public function getIdentifierFieldNames() + { + return $this->identifier; + } + + /** + * Gets the name of the single id field. Note that this only works on + * entity classes that have a single-field pk. + * + * @return string + * + * @throws MappingException If the class doesn't have an identifier or it has a composite primary key. + */ + public function getSingleIdentifierFieldName() + { + if ($this->isIdentifierComposite) { + throw MappingException::singleIdNotAllowedOnCompositePrimaryKey($this->name); + } + + if ( ! isset($this->identifier[0])) { + throw MappingException::noIdDefined($this->name); + } + + return $this->identifier[0]; + } + + /** + * Gets the column name of the single id column. Note that this only works on + * entity classes that have a single-field pk. + * + * @return string + * + * @throws MappingException If the class doesn't have an identifier or it has a composite primary key. + */ + public function getSingleIdentifierColumnName() + { + return $this->getColumnName($this->getSingleIdentifierFieldName()); + } + + /** + * INTERNAL: + * Sets the mapped identifier/primary key fields of this class. + * Mainly used by the ClassMetadataFactory to assign inherited identifiers. + * + * @param array $identifier + * + * @return void + */ + public function setIdentifier(array $identifier) + { + $this->identifier = $identifier; + $this->isIdentifierComposite = (count($this->identifier) > 1); + } + + /** + * {@inheritDoc} + */ + public function getIdentifier() + { + return $this->identifier; + } + + /** + * {@inheritDoc} + */ + public function hasField($fieldName) + { + return isset($this->fieldMappings[$fieldName]) || isset($this->embeddedClasses[$fieldName]); + } + + /** + * Gets an array containing all the column names. + * + * @param array|null $fieldNames + * + * @return array + */ + public function getColumnNames(array $fieldNames = null) + { + if (null === $fieldNames) { + return array_keys($this->fieldNames); + } + + return array_values(array_map([$this, 'getColumnName'], $fieldNames)); + } + + /** + * Returns an array with all the identifier column names. + * + * @return array + */ + public function getIdentifierColumnNames() + { + $columnNames = []; + + foreach ($this->identifier as $idProperty) { + if (isset($this->fieldMappings[$idProperty])) { + $columnNames[] = $this->fieldMappings[$idProperty]['columnName']; + + continue; + } + + // Association defined as Id field + $joinColumns = $this->associationMappings[$idProperty]['joinColumns']; + $assocColumnNames = array_map(function ($joinColumn) { return $joinColumn['name']; }, $joinColumns); + + $columnNames = array_merge($columnNames, $assocColumnNames); + } + + return $columnNames; + } + + /** + * Sets the type of Id generator to use for the mapped class. + * + * @param int $generatorType + * + * @return void + */ + public function setIdGeneratorType($generatorType) + { + $this->generatorType = $generatorType; + } + + /** + * Checks whether the mapped class uses an Id generator. + * + * @return boolean TRUE if the mapped class uses an Id generator, FALSE otherwise. + */ + public function usesIdGenerator() + { + return $this->generatorType != self::GENERATOR_TYPE_NONE; + } + + /** + * @return boolean + */ + public function isInheritanceTypeNone() + { + return $this->inheritanceType == self::INHERITANCE_TYPE_NONE; + } + + /** + * Checks whether the mapped class uses the JOINED inheritance mapping strategy. + * + * @return boolean TRUE if the class participates in a JOINED inheritance mapping, + * FALSE otherwise. + */ + public function isInheritanceTypeJoined() + { + return $this->inheritanceType == self::INHERITANCE_TYPE_JOINED; + } + + /** + * Checks whether the mapped class uses the SINGLE_TABLE inheritance mapping strategy. + * + * @return boolean TRUE if the class participates in a SINGLE_TABLE inheritance mapping, + * FALSE otherwise. + */ + public function isInheritanceTypeSingleTable() + { + return $this->inheritanceType == self::INHERITANCE_TYPE_SINGLE_TABLE; + } + + /** + * Checks whether the mapped class uses the TABLE_PER_CLASS inheritance mapping strategy. + * + * @return boolean TRUE if the class participates in a TABLE_PER_CLASS inheritance mapping, + * FALSE otherwise. + */ + public function isInheritanceTypeTablePerClass() + { + return $this->inheritanceType == self::INHERITANCE_TYPE_TABLE_PER_CLASS; + } + + /** + * Checks whether the class uses an identity column for the Id generation. + * + * @return boolean TRUE if the class uses the IDENTITY generator, FALSE otherwise. + */ + public function isIdGeneratorIdentity() + { + return $this->generatorType == self::GENERATOR_TYPE_IDENTITY; + } + + /** + * Checks whether the class uses a sequence for id generation. + * + * @return boolean TRUE if the class uses the SEQUENCE generator, FALSE otherwise. + */ + public function isIdGeneratorSequence() + { + return $this->generatorType == self::GENERATOR_TYPE_SEQUENCE; + } + + /** + * Checks whether the class uses a table for id generation. + * + * @return boolean TRUE if the class uses the TABLE generator, FALSE otherwise. + */ + public function isIdGeneratorTable() + { + return $this->generatorType == self::GENERATOR_TYPE_TABLE; + } + + /** + * Checks whether the class has a natural identifier/pk (which means it does + * not use any Id generator. + * + * @return boolean + */ + public function isIdentifierNatural() + { + return $this->generatorType == self::GENERATOR_TYPE_NONE; + } + + /** + * Checks whether the class use a UUID for id generation. + * + * @return boolean + */ + public function isIdentifierUuid() + { + return $this->generatorType == self::GENERATOR_TYPE_UUID; + } + + /** + * Gets the type of a field. + * + * @param string $fieldName + * + * @return string|null + * + * @todo 3.0 Remove this. PersisterHelper should fix it somehow + */ + public function getTypeOfField($fieldName) + { + return isset($this->fieldMappings[$fieldName]) + ? $this->fieldMappings[$fieldName]['type'] + : null; + } + + /** + * Gets the type of a column. + * + * @param string $columnName + * + * @return string|null + * + * @deprecated 3.0 remove this. this method is bogus and unreliable, since it cannot resolve the type of a column + * that is derived by a referenced field on a different entity. + */ + public function getTypeOfColumn($columnName) + { + return $this->getTypeOfField($this->getFieldName($columnName)); + } + + /** + * Gets the name of the primary table. + * + * @return string + */ + public function getTableName() + { + return $this->table['name']; + } + + /** + * Gets primary table's schema name. + * + * @return string|null + */ + public function getSchemaName() + { + return isset($this->table['schema']) ? $this->table['schema'] : null; + } + + /** + * Gets the table name to use for temporary identifier tables of this class. + * + * @return string + */ + public function getTemporaryIdTableName() + { + // replace dots with underscores because PostgreSQL creates temporary tables in a special schema + return str_replace('.', '_', $this->getTableName() . '_id_tmp'); + } + + /** + * Sets the mapped subclasses of this class. + * + * @param array $subclasses The names of all mapped subclasses. + * + * @return void + */ + public function setSubclasses(array $subclasses) + { + foreach ($subclasses as $subclass) { + $this->subClasses[] = $this->fullyQualifiedClassName($subclass); + } + } + + /** + * Sets the parent class names. + * Assumes that the class names in the passed array are in the order: + * directParent -> directParentParent -> directParentParentParent ... -> root. + * + * @param array $classNames + * + * @return void + */ + public function setParentClasses(array $classNames) + { + $this->parentClasses = $classNames; + + if (count($classNames) > 0) { + $this->rootEntityName = array_pop($classNames); + } + } + + /** + * Sets the inheritance type used by the class and its subclasses. + * + * @param integer $type + * + * @return void + * + * @throws MappingException + */ + public function setInheritanceType($type) + { + if ( ! $this->_isInheritanceType($type)) { + throw MappingException::invalidInheritanceType($this->name, $type); + } + + $this->inheritanceType = $type; + } + + /** + * Sets the association to override association mapping of property for an entity relationship. + * + * @param string $fieldName + * @param array $overrideMapping + * + * @return void + * + * @throws MappingException + */ + public function setAssociationOverride($fieldName, array $overrideMapping) + { + if ( ! isset($this->associationMappings[$fieldName])) { + throw MappingException::invalidOverrideFieldName($this->name, $fieldName); + } + + $mapping = $this->associationMappings[$fieldName]; + + if (isset($overrideMapping['joinColumns'])) { + $mapping['joinColumns'] = $overrideMapping['joinColumns']; + } + + if (isset($overrideMapping['inversedBy'])) { + $mapping['inversedBy'] = $overrideMapping['inversedBy']; + } + + if (isset($overrideMapping['joinTable'])) { + $mapping['joinTable'] = $overrideMapping['joinTable']; + } + + if (isset($overrideMapping['fetch'])) { + $mapping['fetch'] = $overrideMapping['fetch']; + } + + $mapping['joinColumnFieldNames'] = null; + $mapping['joinTableColumns'] = null; + $mapping['sourceToTargetKeyColumns'] = null; + $mapping['relationToSourceKeyColumns'] = null; + $mapping['relationToTargetKeyColumns'] = null; + + switch ($mapping['type']) { + case self::ONE_TO_ONE: + $mapping = $this->_validateAndCompleteOneToOneMapping($mapping); + break; + case self::ONE_TO_MANY: + $mapping = $this->_validateAndCompleteOneToManyMapping($mapping); + break; + case self::MANY_TO_ONE: + $mapping = $this->_validateAndCompleteOneToOneMapping($mapping); + break; + case self::MANY_TO_MANY: + $mapping = $this->_validateAndCompleteManyToManyMapping($mapping); + break; + } + + $this->associationMappings[$fieldName] = $mapping; + } + + /** + * Sets the override for a mapped field. + * + * @param string $fieldName + * @param array $overrideMapping + * + * @return void + * + * @throws MappingException + */ + public function setAttributeOverride($fieldName, array $overrideMapping) + { + if ( ! isset($this->fieldMappings[$fieldName])) { + throw MappingException::invalidOverrideFieldName($this->name, $fieldName); + } + + $mapping = $this->fieldMappings[$fieldName]; + + if (isset($mapping['id'])) { + $overrideMapping['id'] = $mapping['id']; + } + + if ( ! isset($overrideMapping['type'])) { + $overrideMapping['type'] = $mapping['type']; + } + + if ( ! isset($overrideMapping['fieldName'])) { + $overrideMapping['fieldName'] = $mapping['fieldName']; + } + + if ($overrideMapping['type'] !== $mapping['type']) { + throw MappingException::invalidOverrideFieldType($this->name, $fieldName); + } + + unset($this->fieldMappings[$fieldName]); + unset($this->fieldNames[$mapping['columnName']]); + unset($this->columnNames[$mapping['fieldName']]); + + $this->_validateAndCompleteFieldMapping($overrideMapping); + + $this->fieldMappings[$fieldName] = $overrideMapping; + } + + /** + * Checks whether a mapped field is inherited from an entity superclass. + * + * @param string $fieldName + * + * @return bool TRUE if the field is inherited, FALSE otherwise. + */ + public function isInheritedField($fieldName) + { + return isset($this->fieldMappings[$fieldName]['inherited']); + } + + /** + * Checks if this entity is the root in any entity-inheritance-hierarchy. + * + * @return bool + */ + public function isRootEntity() + { + return $this->name == $this->rootEntityName; + } + + /** + * Checks whether a mapped association field is inherited from a superclass. + * + * @param string $fieldName + * + * @return boolean TRUE if the field is inherited, FALSE otherwise. + */ + public function isInheritedAssociation($fieldName) + { + return isset($this->associationMappings[$fieldName]['inherited']); + } + + public function isInheritedEmbeddedClass($fieldName) + { + return isset($this->embeddedClasses[$fieldName]['inherited']); + } + + /** + * Sets the name of the primary table the class is mapped to. + * + * @param string $tableName The table name. + * + * @return void + * + * @deprecated Use {@link setPrimaryTable}. + */ + public function setTableName($tableName) + { + $this->table['name'] = $tableName; + } + + /** + * Sets the primary table definition. The provided array supports the + * following structure: + * + * name => (optional, defaults to class name) + * indexes => array of indexes (optional) + * uniqueConstraints => array of constraints (optional) + * + * If a key is omitted, the current value is kept. + * + * @param array $table The table description. + * + * @return void + */ + public function setPrimaryTable(array $table) + { + if (isset($table['name'])) { + // Split schema and table name from a table name like "myschema.mytable" + if (strpos($table['name'], '.') !== false) { + list($this->table['schema'], $table['name']) = explode('.', $table['name'], 2); + } + + if ($table['name'][0] === '`') { + $table['name'] = trim($table['name'], '`'); + $this->table['quoted'] = true; + } + + $this->table['name'] = $table['name']; + } + + if (isset($table['quoted'])) { + $this->table['quoted'] = $table['quoted']; + } + + if (isset($table['schema'])) { + $this->table['schema'] = $table['schema']; + } + + if (isset($table['indexes'])) { + $this->table['indexes'] = $table['indexes']; + } + + if (isset($table['uniqueConstraints'])) { + $this->table['uniqueConstraints'] = $table['uniqueConstraints']; + } + + if (isset($table['options'])) { + $this->table['options'] = $table['options']; + } + } + + /** + * Checks whether the given type identifies an inheritance type. + * + * @param integer $type + * + * @return boolean TRUE if the given type identifies an inheritance type, FALSe otherwise. + */ + private function _isInheritanceType($type) + { + return $type == self::INHERITANCE_TYPE_NONE || + $type == self::INHERITANCE_TYPE_SINGLE_TABLE || + $type == self::INHERITANCE_TYPE_JOINED || + $type == self::INHERITANCE_TYPE_TABLE_PER_CLASS; + } + + /** + * Adds a mapped field to the class. + * + * @param array $mapping The field mapping. + * + * @return void + * + * @throws MappingException + */ + public function mapField(array $mapping) + { + $this->_validateAndCompleteFieldMapping($mapping); + $this->assertFieldNotMapped($mapping['fieldName']); + + $this->fieldMappings[$mapping['fieldName']] = $mapping; + } + + /** + * INTERNAL: + * Adds an association mapping without completing/validating it. + * This is mainly used to add inherited association mappings to derived classes. + * + * @param array $mapping + * + * @return void + * + * @throws MappingException + */ + public function addInheritedAssociationMapping(array $mapping/*, $owningClassName = null*/) + { + if (isset($this->associationMappings[$mapping['fieldName']])) { + throw MappingException::duplicateAssociationMapping($this->name, $mapping['fieldName']); + } + $this->associationMappings[$mapping['fieldName']] = $mapping; + } + + /** + * INTERNAL: + * Adds a field mapping without completing/validating it. + * This is mainly used to add inherited field mappings to derived classes. + * + * @param array $fieldMapping + * + * @return void + */ + public function addInheritedFieldMapping(array $fieldMapping) + { + $this->fieldMappings[$fieldMapping['fieldName']] = $fieldMapping; + $this->columnNames[$fieldMapping['fieldName']] = $fieldMapping['columnName']; + $this->fieldNames[$fieldMapping['columnName']] = $fieldMapping['fieldName']; + } + + /** + * INTERNAL: + * Adds a named query to this class. + * + * @param array $queryMapping + * + * @return void + * + * @throws MappingException + */ + public function addNamedQuery(array $queryMapping) + { + if (!isset($queryMapping['name'])) { + throw MappingException::nameIsMandatoryForQueryMapping($this->name); + } + + if (isset($this->namedQueries[$queryMapping['name']])) { + throw MappingException::duplicateQueryMapping($this->name, $queryMapping['name']); + } + + if (!isset($queryMapping['query'])) { + throw MappingException::emptyQueryMapping($this->name, $queryMapping['name']); + } + + $name = $queryMapping['name']; + $query = $queryMapping['query']; + $dql = str_replace('__CLASS__', $this->name, $query); + + $this->namedQueries[$name] = [ + 'name' => $name, + 'query' => $query, + 'dql' => $dql, + ]; + } + + /** + * INTERNAL: + * Adds a named native query to this class. + * + * @param array $queryMapping + * + * @return void + * + * @throws MappingException + */ + public function addNamedNativeQuery(array $queryMapping) + { + if (!isset($queryMapping['name'])) { + throw MappingException::nameIsMandatoryForQueryMapping($this->name); + } + + if (isset($this->namedNativeQueries[$queryMapping['name']])) { + throw MappingException::duplicateQueryMapping($this->name, $queryMapping['name']); + } + + if (!isset($queryMapping['query'])) { + throw MappingException::emptyQueryMapping($this->name, $queryMapping['name']); + } + + if (!isset($queryMapping['resultClass']) && !isset($queryMapping['resultSetMapping'])) { + throw MappingException::missingQueryMapping($this->name, $queryMapping['name']); + } + + $queryMapping['isSelfClass'] = false; + + if (isset($queryMapping['resultClass'])) { + if ($queryMapping['resultClass'] === '__CLASS__') { + + $queryMapping['isSelfClass'] = true; + $queryMapping['resultClass'] = $this->name; + } + + $queryMapping['resultClass'] = $this->fullyQualifiedClassName($queryMapping['resultClass']); + $queryMapping['resultClass'] = ltrim($queryMapping['resultClass'], '\\'); + } + + $this->namedNativeQueries[$queryMapping['name']] = $queryMapping; + } + + /** + * INTERNAL: + * Adds a sql result set mapping to this class. + * + * @param array $resultMapping + * + * @return void + * + * @throws MappingException + */ + public function addSqlResultSetMapping(array $resultMapping) + { + if (!isset($resultMapping['name'])) { + throw MappingException::nameIsMandatoryForSqlResultSetMapping($this->name); + } + + if (isset($this->sqlResultSetMappings[$resultMapping['name']])) { + throw MappingException::duplicateResultSetMapping($this->name, $resultMapping['name']); + } + + if (isset($resultMapping['entities'])) { + foreach ($resultMapping['entities'] as $key => $entityResult) { + if (!isset($entityResult['entityClass'])) { + throw MappingException::missingResultSetMappingEntity($this->name, $resultMapping['name']); + } + + $entityResult['isSelfClass'] = false; + if ($entityResult['entityClass'] === '__CLASS__') { + + $entityResult['isSelfClass'] = true; + $entityResult['entityClass'] = $this->name; + + } + + $entityResult['entityClass'] = $this->fullyQualifiedClassName($entityResult['entityClass']); + + $resultMapping['entities'][$key]['entityClass'] = ltrim($entityResult['entityClass'], '\\'); + $resultMapping['entities'][$key]['isSelfClass'] = $entityResult['isSelfClass']; + + if (isset($entityResult['fields'])) { + foreach ($entityResult['fields'] as $k => $field) { + if (!isset($field['name'])) { + throw MappingException::missingResultSetMappingFieldName($this->name, $resultMapping['name']); + } + + if (!isset($field['column'])) { + $fieldName = $field['name']; + if (strpos($fieldName, '.')) { + list(, $fieldName) = explode('.', $fieldName); + } + + $resultMapping['entities'][$key]['fields'][$k]['column'] = $fieldName; + } + } + } + } + } + + $this->sqlResultSetMappings[$resultMapping['name']] = $resultMapping; + } + + /** + * Adds a one-to-one mapping. + * + * @param array $mapping The mapping. + * + * @return void + */ + public function mapOneToOne(array $mapping) + { + $mapping['type'] = self::ONE_TO_ONE; + + $mapping = $this->_validateAndCompleteOneToOneMapping($mapping); + + $this->_storeAssociationMapping($mapping); + } + + /** + * Adds a one-to-many mapping. + * + * @param array $mapping The mapping. + * + * @return void + */ + public function mapOneToMany(array $mapping) + { + $mapping['type'] = self::ONE_TO_MANY; + + $mapping = $this->_validateAndCompleteOneToManyMapping($mapping); + + $this->_storeAssociationMapping($mapping); + } + + /** + * Adds a many-to-one mapping. + * + * @param array $mapping The mapping. + * + * @return void + */ + public function mapManyToOne(array $mapping) + { + $mapping['type'] = self::MANY_TO_ONE; + + // A many-to-one mapping is essentially a one-one backreference + $mapping = $this->_validateAndCompleteOneToOneMapping($mapping); + + $this->_storeAssociationMapping($mapping); + } + + /** + * Adds a many-to-many mapping. + * + * @param array $mapping The mapping. + * + * @return void + */ + public function mapManyToMany(array $mapping) + { + $mapping['type'] = self::MANY_TO_MANY; + + $mapping = $this->_validateAndCompleteManyToManyMapping($mapping); + + $this->_storeAssociationMapping($mapping); + } + + /** + * Stores the association mapping. + * + * @param array $assocMapping + * + * @return void + * + * @throws MappingException + */ + protected function _storeAssociationMapping(array $assocMapping) + { + $sourceFieldName = $assocMapping['fieldName']; + + $this->assertFieldNotMapped($sourceFieldName); + + $this->associationMappings[$sourceFieldName] = $assocMapping; + } + + /** + * Registers a custom repository class for the entity class. + * + * @param string $repositoryClassName The class name of the custom mapper. + * + * @return void + */ + public function setCustomRepositoryClass($repositoryClassName) + { + $this->customRepositoryClassName = $this->fullyQualifiedClassName($repositoryClassName); + } + + /** + * Dispatches the lifecycle event of the given entity to the registered + * lifecycle callbacks and lifecycle listeners. + * + * @deprecated Deprecated since version 2.4 in favor of \Doctrine\ORM\Event\ListenersInvoker + * + * @param string $lifecycleEvent The lifecycle event. + * @param object $entity The Entity on which the event occurred. + * + * @return void + */ + public function invokeLifecycleCallbacks($lifecycleEvent, $entity) + { + foreach ($this->lifecycleCallbacks[$lifecycleEvent] as $callback) { + $entity->$callback(); + } + } + + /** + * Whether the class has any attached lifecycle listeners or callbacks for a lifecycle event. + * + * @param string $lifecycleEvent + * + * @return boolean + */ + public function hasLifecycleCallbacks($lifecycleEvent) + { + return isset($this->lifecycleCallbacks[$lifecycleEvent]); + } + + /** + * Gets the registered lifecycle callbacks for an event. + * + * @param string $event + * + * @return array + */ + public function getLifecycleCallbacks($event) + { + return isset($this->lifecycleCallbacks[$event]) ? $this->lifecycleCallbacks[$event] : []; + } + + /** + * Adds a lifecycle callback for entities of this class. + * + * @param string $callback + * @param string $event + * + * @return void + */ + public function addLifecycleCallback($callback, $event) + { + if (isset($this->lifecycleCallbacks[$event]) && in_array($callback, $this->lifecycleCallbacks[$event])) { + return; + } + + $this->lifecycleCallbacks[$event][] = $callback; + } + + /** + * Sets the lifecycle callbacks for entities of this class. + * Any previously registered callbacks are overwritten. + * + * @param array $callbacks + * + * @return void + */ + public function setLifecycleCallbacks(array $callbacks) + { + $this->lifecycleCallbacks = $callbacks; + } + + /** + * Adds a entity listener for entities of this class. + * + * @param string $eventName The entity lifecycle event. + * @param string $class The listener class. + * @param string $method The listener callback method. + * + * @throws \Doctrine\ORM\Mapping\MappingException + */ + public function addEntityListener($eventName, $class, $method) + { + $class = $this->fullyQualifiedClassName($class); + + $listener = [ + 'class' => $class, + 'method' => $method, + ]; + + if ( ! class_exists($class)) { + throw MappingException::entityListenerClassNotFound($class, $this->name); + } + + if ( ! method_exists($class, $method)) { + throw MappingException::entityListenerMethodNotFound($class, $method, $this->name); + } + + if (isset($this->entityListeners[$eventName]) && in_array($listener, $this->entityListeners[$eventName])) { + throw MappingException::duplicateEntityListener($class, $method, $this->name); + } + + $this->entityListeners[$eventName][] = $listener; + } + + /** + * Sets the discriminator column definition. + * + * @param array $columnDef + * + * @return void + * + * @throws MappingException + * + * @see getDiscriminatorColumn() + */ + public function setDiscriminatorColumn($columnDef) + { + if ($columnDef !== null) { + if ( ! isset($columnDef['name'])) { + throw MappingException::nameIsMandatoryForDiscriminatorColumns($this->name); + } + + if (isset($this->fieldNames[$columnDef['name']])) { + throw MappingException::duplicateColumnName($this->name, $columnDef['name']); + } + + if ( ! isset($columnDef['fieldName'])) { + $columnDef['fieldName'] = $columnDef['name']; + } + + if ( ! isset($columnDef['type'])) { + $columnDef['type'] = "string"; + } + + if (in_array($columnDef['type'], ["boolean", "array", "object", "datetime", "time", "date"])) { + throw MappingException::invalidDiscriminatorColumnType($this->name, $columnDef['type']); + } + + $this->discriminatorColumn = $columnDef; + } + } + + /** + * Sets the discriminator values used by this class. + * Used for JOINED and SINGLE_TABLE inheritance mapping strategies. + * + * @param array $map + * + * @return void + */ + public function setDiscriminatorMap(array $map) + { + foreach ($map as $value => $className) { + $this->addDiscriminatorMapClass($value, $className); + } + } + + /** + * Adds one entry of the discriminator map with a new class and corresponding name. + * + * @param string $name + * @param string $className + * + * @return void + * + * @throws MappingException + */ + public function addDiscriminatorMapClass($name, $className) + { + $className = $this->fullyQualifiedClassName($className); + $className = ltrim($className, '\\'); + + $this->discriminatorMap[$name] = $className; + + if ($this->name === $className) { + $this->discriminatorValue = $name; + + return; + } + + if ( ! (class_exists($className) || interface_exists($className))) { + throw MappingException::invalidClassInDiscriminatorMap($className, $this->name); + } + + if (is_subclass_of($className, $this->name) && ! in_array($className, $this->subClasses)) { + $this->subClasses[] = $className; + } + } + + /** + * Checks whether the class has a named query with the given query name. + * + * @param string $queryName + * + * @return boolean + */ + public function hasNamedQuery($queryName) + { + return isset($this->namedQueries[$queryName]); + } + + /** + * Checks whether the class has a named native query with the given query name. + * + * @param string $queryName + * + * @return boolean + */ + public function hasNamedNativeQuery($queryName) + { + return isset($this->namedNativeQueries[$queryName]); + } + + /** + * Checks whether the class has a named native query with the given query name. + * + * @param string $name + * + * @return boolean + */ + public function hasSqlResultSetMapping($name) + { + return isset($this->sqlResultSetMappings[$name]); + } + + /** + * {@inheritDoc} + */ + public function hasAssociation($fieldName) + { + return isset($this->associationMappings[$fieldName]); + } + + /** + * {@inheritDoc} + */ + public function isSingleValuedAssociation($fieldName) + { + return isset($this->associationMappings[$fieldName]) + && ($this->associationMappings[$fieldName]['type'] & self::TO_ONE); + } + + /** + * {@inheritDoc} + */ + public function isCollectionValuedAssociation($fieldName) + { + return isset($this->associationMappings[$fieldName]) + && ! ($this->associationMappings[$fieldName]['type'] & self::TO_ONE); + } + + /** + * Is this an association that only has a single join column? + * + * @param string $fieldName + * + * @return bool + */ + public function isAssociationWithSingleJoinColumn($fieldName) + { + return isset($this->associationMappings[$fieldName]) + && isset($this->associationMappings[$fieldName]['joinColumns'][0]) + && ! isset($this->associationMappings[$fieldName]['joinColumns'][1]); + } + + /** + * Returns the single association join column (if any). + * + * @param string $fieldName + * + * @return string + * + * @throws MappingException + */ + public function getSingleAssociationJoinColumnName($fieldName) + { + if ( ! $this->isAssociationWithSingleJoinColumn($fieldName)) { + throw MappingException::noSingleAssociationJoinColumnFound($this->name, $fieldName); + } + + return $this->associationMappings[$fieldName]['joinColumns'][0]['name']; + } + + /** + * Returns the single association referenced join column name (if any). + * + * @param string $fieldName + * + * @return string + * + * @throws MappingException + */ + public function getSingleAssociationReferencedJoinColumnName($fieldName) + { + if ( ! $this->isAssociationWithSingleJoinColumn($fieldName)) { + throw MappingException::noSingleAssociationJoinColumnFound($this->name, $fieldName); + } + + return $this->associationMappings[$fieldName]['joinColumns'][0]['referencedColumnName']; + } + + /** + * Used to retrieve a fieldname for either field or association from a given column. + * + * This method is used in foreign-key as primary-key contexts. + * + * @param string $columnName + * + * @return string + * + * @throws MappingException + */ + public function getFieldForColumn($columnName) + { + if (isset($this->fieldNames[$columnName])) { + return $this->fieldNames[$columnName]; + } + + foreach ($this->associationMappings as $assocName => $mapping) { + if ($this->isAssociationWithSingleJoinColumn($assocName) && + $this->associationMappings[$assocName]['joinColumns'][0]['name'] == $columnName) { + + return $assocName; + } + } + + throw MappingException::noFieldNameFoundForColumn($this->name, $columnName); + } + + /** + * Sets the ID generator used to generate IDs for instances of this class. + * + * @param \Doctrine\ORM\Id\AbstractIdGenerator $generator + * + * @return void + */ + public function setIdGenerator($generator) + { + $this->idGenerator = $generator; + } + + /** + * Sets definition. + * + * @param array $definition + * + * @return void + */ + public function setCustomGeneratorDefinition(array $definition) + { + $this->customGeneratorDefinition = $definition; + } + + /** + * Sets the definition of the sequence ID generator for this class. + * + * The definition must have the following structure: + * + * array( + * 'sequenceName' => 'name', + * 'allocationSize' => 20, + * 'initialValue' => 1 + * 'quoted' => 1 + * ) + * + * + * @param array $definition + * + * @return void + * + * @throws MappingException + */ + public function setSequenceGeneratorDefinition(array $definition) + { + if ( ! isset($definition['sequenceName']) || trim($definition['sequenceName']) === '') { + throw MappingException::missingSequenceName($this->name); + } + + if ($definition['sequenceName'][0] == '`') { + $definition['sequenceName'] = trim($definition['sequenceName'], '`'); + $definition['quoted'] = true; + } + + if ( ! isset($definition['allocationSize']) || trim($definition['allocationSize']) === '') { + $definition['allocationSize'] = '1'; + } + + if ( ! isset($definition['initialValue']) || trim($definition['initialValue']) === '') { + $definition['initialValue'] = '1'; + } + + $this->sequenceGeneratorDefinition = $definition; + } + + /** + * Sets the version field mapping used for versioning. Sets the default + * value to use depending on the column type. + * + * @param array $mapping The version field mapping array. + * + * @return void + * + * @throws MappingException + */ + public function setVersionMapping(array &$mapping) + { + $this->isVersioned = true; + $this->versionField = $mapping['fieldName']; + + if ( ! isset($mapping['default'])) { + if (in_array($mapping['type'], ['integer', 'bigint', 'smallint'])) { + $mapping['default'] = 1; + } else if ($mapping['type'] == 'datetime') { + $mapping['default'] = 'CURRENT_TIMESTAMP'; + } else { + throw MappingException::unsupportedOptimisticLockingType($this->name, $mapping['fieldName'], $mapping['type']); + } + } + } + + /** + * Sets whether this class is to be versioned for optimistic locking. + * + * @param boolean $bool + * + * @return void + */ + public function setVersioned($bool) + { + $this->isVersioned = $bool; + } + + /** + * Sets the name of the field that is to be used for versioning if this class is + * versioned for optimistic locking. + * + * @param string $versionField + * + * @return void + */ + public function setVersionField($versionField) + { + $this->versionField = $versionField; + } + + /** + * Marks this class as read only, no change tracking is applied to it. + * + * @return void + */ + public function markReadOnly() + { + $this->isReadOnly = true; + } + + /** + * {@inheritDoc} + */ + public function getFieldNames() + { + return array_keys($this->fieldMappings); + } + + /** + * {@inheritDoc} + */ + public function getAssociationNames() + { + return array_keys($this->associationMappings); + } + + /** + * {@inheritDoc} + * + * @throws InvalidArgumentException + */ + public function getAssociationTargetClass($assocName) + { + if ( ! isset($this->associationMappings[$assocName])) { + throw new InvalidArgumentException("Association name expected, '" . $assocName ."' is not an association."); + } + + return $this->associationMappings[$assocName]['targetEntity']; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return $this->name; + } + + /** + * Gets the (possibly quoted) identifier column names for safe use in an SQL statement. + * + * @deprecated Deprecated since version 2.3 in favor of \Doctrine\ORM\Mapping\QuoteStrategy + * + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + * + * @return array + */ + public function getQuotedIdentifierColumnNames($platform) + { + $quotedColumnNames = []; + + foreach ($this->identifier as $idProperty) { + if (isset($this->fieldMappings[$idProperty])) { + $quotedColumnNames[] = isset($this->fieldMappings[$idProperty]['quoted']) + ? $platform->quoteIdentifier($this->fieldMappings[$idProperty]['columnName']) + : $this->fieldMappings[$idProperty]['columnName']; + + continue; + } + + // Association defined as Id field + $joinColumns = $this->associationMappings[$idProperty]['joinColumns']; + $assocQuotedColumnNames = array_map( + function ($joinColumn) use ($platform) { + return isset($joinColumn['quoted']) + ? $platform->quoteIdentifier($joinColumn['name']) + : $joinColumn['name']; + }, + $joinColumns + ); + + $quotedColumnNames = array_merge($quotedColumnNames, $assocQuotedColumnNames); + } + + return $quotedColumnNames; + } + + /** + * Gets the (possibly quoted) column name of a mapped field for safe use in an SQL statement. + * + * @deprecated Deprecated since version 2.3 in favor of \Doctrine\ORM\Mapping\QuoteStrategy + * + * @param string $field + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + * + * @return string + */ + public function getQuotedColumnName($field, $platform) + { + return isset($this->fieldMappings[$field]['quoted']) + ? $platform->quoteIdentifier($this->fieldMappings[$field]['columnName']) + : $this->fieldMappings[$field]['columnName']; + } + + /** + * Gets the (possibly quoted) primary table name of this class for safe use in an SQL statement. + * + * @deprecated Deprecated since version 2.3 in favor of \Doctrine\ORM\Mapping\QuoteStrategy + * + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + * + * @return string + */ + public function getQuotedTableName($platform) + { + return isset($this->table['quoted']) + ? $platform->quoteIdentifier($this->table['name']) + : $this->table['name']; + } + + /** + * Gets the (possibly quoted) name of the join table. + * + * @deprecated Deprecated since version 2.3 in favor of \Doctrine\ORM\Mapping\QuoteStrategy + * + * @param array $assoc + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + * + * @return string + */ + public function getQuotedJoinTableName(array $assoc, $platform) + { + return isset($assoc['joinTable']['quoted']) + ? $platform->quoteIdentifier($assoc['joinTable']['name']) + : $assoc['joinTable']['name']; + } + + /** + * {@inheritDoc} + */ + public function isAssociationInverseSide($fieldName) + { + return isset($this->associationMappings[$fieldName]) + && ! $this->associationMappings[$fieldName]['isOwningSide']; + } + + /** + * {@inheritDoc} + */ + public function getAssociationMappedByTargetField($fieldName) + { + return $this->associationMappings[$fieldName]['mappedBy']; + } + + /** + * @param string $targetClass + * + * @return array + */ + public function getAssociationsByTargetClass($targetClass) + { + $relations = []; + + foreach ($this->associationMappings as $mapping) { + if ($mapping['targetEntity'] == $targetClass) { + $relations[$mapping['fieldName']] = $mapping; + } + } + + return $relations; + } + + /** + * @param string|null $className + * + * @return string|null null if the input value is null + */ + public function fullyQualifiedClassName($className) + { + if (empty($className)) { + return $className; + } + + if ($className !== null && strpos($className, '\\') === false && $this->namespace) { + return $this->namespace . '\\' . $className; + } + + return $className; + } + + /** + * @param string $name + * + * @return mixed + */ + public function getMetadataValue($name) + { + + if (isset($this->$name)) { + return $this->$name; + } + + return null; + } + + /** + * Map Embedded Class + * + * @param array $mapping + * + * @throws MappingException + * @return void + */ + public function mapEmbedded(array $mapping) + { + $this->assertFieldNotMapped($mapping['fieldName']); + + $this->embeddedClasses[$mapping['fieldName']] = [ + 'class' => $this->fullyQualifiedClassName($mapping['class']), + 'columnPrefix' => $mapping['columnPrefix'], + 'declaredField' => $mapping['declaredField'] ?? null, + 'originalField' => $mapping['originalField'] ?? null, + ]; + } + + /** + * Inline the embeddable class + * + * @param string $property + * @param ClassMetadataInfo $embeddable + */ + public function inlineEmbeddable($property, ClassMetadataInfo $embeddable) + { + foreach ($embeddable->fieldMappings as $fieldMapping) { + $fieldMapping['originalClass'] = $fieldMapping['originalClass'] ?? $embeddable->name; + $fieldMapping['declaredField'] = isset($fieldMapping['declaredField']) + ? $property . '.' . $fieldMapping['declaredField'] + : $property; + $fieldMapping['originalField'] = $fieldMapping['originalField'] ?? $fieldMapping['fieldName']; + $fieldMapping['fieldName'] = $property . "." . $fieldMapping['fieldName']; + + if (! empty($this->embeddedClasses[$property]['columnPrefix'])) { + $fieldMapping['columnName'] = $this->embeddedClasses[$property]['columnPrefix'] . $fieldMapping['columnName']; + } elseif ($this->embeddedClasses[$property]['columnPrefix'] !== false) { + $fieldMapping['columnName'] = $this->namingStrategy + ->embeddedFieldToColumnName( + $property, + $fieldMapping['columnName'], + $this->reflClass->name, + $embeddable->reflClass->name + ); + } + + $this->mapField($fieldMapping); + } + } + + /** + * @param string $fieldName + * @throws MappingException + */ + private function assertFieldNotMapped($fieldName) + { + if (isset($this->fieldMappings[$fieldName]) || + isset($this->associationMappings[$fieldName]) || + isset($this->embeddedClasses[$fieldName])) { + + throw MappingException::duplicateFieldMapping($this->name, $fieldName); + } + } + + /** + * Gets the sequence name based on class metadata. + * + * @param AbstractPlatform $platform + * @return string + * + * @todo Sequence names should be computed in DBAL depending on the platform + */ + public function getSequenceName(AbstractPlatform $platform) + { + $sequencePrefix = $this->getSequencePrefix($platform); + $columnName = $this->getSingleIdentifierColumnName(); + $sequenceName = $sequencePrefix . '_' . $columnName . '_seq'; + + return $sequenceName; + } + + /** + * Gets the sequence name prefix based on class metadata. + * + * @param AbstractPlatform $platform + * @return string + * + * @todo Sequence names should be computed in DBAL depending on the platform + */ + public function getSequencePrefix(AbstractPlatform $platform) + { + $tableName = $this->getTableName(); + $sequencePrefix = $tableName; + + // Prepend the schema name to the table name if there is one + if ($schemaName = $this->getSchemaName()) { + $sequencePrefix = $schemaName . '.' . $tableName; + + if ( ! $platform->supportsSchemas() && $platform->canEmulateSchemas()) { + $sequencePrefix = $schemaName . '__' . $tableName; + } + } + + return $sequencePrefix; + } + + /** + * @param array $mapping + */ + private function assertMappingOrderBy(array $mapping) + { + if (isset($mapping['orderBy']) && !is_array($mapping['orderBy'])) { + throw new InvalidArgumentException("'orderBy' is expected to be an array, not " . gettype($mapping['orderBy'])); + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Column.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Column.php new file mode 100644 index 0000000..711590b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Column.php @@ -0,0 +1,76 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target({"PROPERTY","ANNOTATION"}) + */ +final class Column implements Annotation +{ + /** + * @var string + */ + public $name; + + /** + * @var mixed + */ + public $type = 'string'; + + /** + * @var integer + */ + public $length; + + /** + * The precision for a decimal (exact numeric) column (Applies only for decimal column). + * + * @var integer + */ + public $precision = 0; + + /** + * The scale for a decimal (exact numeric) column (Applies only for decimal column). + * + * @var integer + */ + public $scale = 0; + + /** + * @var boolean + */ + public $unique = false; + + /** + * @var boolean + */ + public $nullable = false; + + /** + * @var array + */ + public $options = []; + + /** + * @var string + */ + public $columnDefinition; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ColumnResult.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ColumnResult.php new file mode 100644 index 0000000..a164c85 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ColumnResult.php @@ -0,0 +1,40 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * References name of a column in the SELECT clause of a SQL query. + * Scalar result types can be included in the query result by specifying this annotation in the metadata. + * + * @author Fabio B. Silva + * @since 2.3 + * + * @Annotation + * @Target("ANNOTATION") + */ +final class ColumnResult implements Annotation +{ + /** + * The name of a column in the SELECT clause of a SQL query. + * + * @var string + */ + public $name; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/CustomIdGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/CustomIdGenerator.php new file mode 100644 index 0000000..41e200e --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/CustomIdGenerator.php @@ -0,0 +1,32 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("PROPERTY") + */ +final class CustomIdGenerator implements Annotation +{ + /** + * @var string + */ + public $class; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultEntityListenerResolver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultEntityListenerResolver.php new file mode 100644 index 0000000..a8ee2dc --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultEntityListenerResolver.php @@ -0,0 +1,75 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * The default DefaultEntityListener + * + * @since 2.4 + * @author Fabio B. Silva + */ +class DefaultEntityListenerResolver implements EntityListenerResolver +{ + /** + * @var array Map to store entity listener instances. + */ + private $instances = []; + + /** + * {@inheritdoc} + */ + public function clear($className = null) + { + if ($className === null) { + $this->instances = []; + + return; + } + + if (isset($this->instances[$className = trim($className, '\\')])) { + unset($this->instances[$className]); + } + } + + /** + * {@inheritdoc} + */ + public function register($object) + { + if ( ! is_object($object)) { + throw new \InvalidArgumentException(sprintf('An object was expected, but got "%s".', gettype($object))); + } + + $this->instances[get_class($object)] = $object; + } + + /** + * {@inheritdoc} + */ + public function resolve($className) + { + if (isset($this->instances[$className = trim($className, '\\')])) { + return $this->instances[$className]; + } + + return $this->instances[$className] = new $className(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultNamingStrategy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultNamingStrategy.php new file mode 100644 index 0000000..ef7f76b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultNamingStrategy.php @@ -0,0 +1,94 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * The default NamingStrategy + * + * + * @link www.doctrine-project.org + * @since 2.3 + * @author Fabio B. Silva + */ +class DefaultNamingStrategy implements NamingStrategy +{ + /** + * {@inheritdoc} + */ + public function classToTableName($className) + { + if (strpos($className, '\\') !== false) { + return substr($className, strrpos($className, '\\') + 1); + } + + return $className; + } + + /** + * {@inheritdoc} + */ + public function propertyToColumnName($propertyName, $className = null) + { + return $propertyName; + } + + /** + * {@inheritdoc} + */ + public function embeddedFieldToColumnName($propertyName, $embeddedColumnName, $className = null, $embeddedClassName = null) + { + return $propertyName.'_'.$embeddedColumnName; + } + + /** + * {@inheritdoc} + */ + public function referenceColumnName() + { + return 'id'; + } + + /** + * {@inheritdoc} + */ + public function joinColumnName($propertyName, $className = null) + { + return $propertyName . '_' . $this->referenceColumnName(); + } + + /** + * {@inheritdoc} + */ + public function joinTableName($sourceEntity, $targetEntity, $propertyName = null) + { + return strtolower($this->classToTableName($sourceEntity) . '_' . + $this->classToTableName($targetEntity)); + } + + /** + * {@inheritdoc} + */ + public function joinKeyColumnName($entityName, $referencedColumnName = null) + { + return strtolower($this->classToTableName($entityName) . '_' . + ($referencedColumnName ?: $this->referenceColumnName())); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultQuoteStrategy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultQuoteStrategy.php new file mode 100644 index 0000000..ade44a0 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultQuoteStrategy.php @@ -0,0 +1,164 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * A set of rules for determining the physical column, alias and table quotes + * + * @since 2.3 + * @author Fabio B. Silva + */ +class DefaultQuoteStrategy implements QuoteStrategy +{ + /** + * {@inheritdoc} + */ + public function getColumnName($fieldName, ClassMetadata $class, AbstractPlatform $platform) + { + return isset($class->fieldMappings[$fieldName]['quoted']) + ? $platform->quoteIdentifier($class->fieldMappings[$fieldName]['columnName']) + : $class->fieldMappings[$fieldName]['columnName']; + } + + /** + * {@inheritdoc} + * + * @todo Table names should be computed in DBAL depending on the platform + */ + public function getTableName(ClassMetadata $class, AbstractPlatform $platform) + { + $tableName = $class->table['name']; + + if ( ! empty($class->table['schema'])) { + $tableName = $class->table['schema'] . '.' . $class->table['name']; + + if ( ! $platform->supportsSchemas() && $platform->canEmulateSchemas()) { + $tableName = $class->table['schema'] . '__' . $class->table['name']; + } + } + + return isset($class->table['quoted']) + ? $platform->quoteIdentifier($tableName) + : $tableName; + } + + /** + * {@inheritdoc} + */ + public function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform) + { + return isset($definition['quoted']) + ? $platform->quoteIdentifier($definition['sequenceName']) + : $definition['sequenceName']; + } + + /** + * {@inheritdoc} + */ + public function getJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform) + { + return isset($joinColumn['quoted']) + ? $platform->quoteIdentifier($joinColumn['name']) + : $joinColumn['name']; + } + + /** + * {@inheritdoc} + */ + public function getReferencedJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform) + { + return isset($joinColumn['quoted']) + ? $platform->quoteIdentifier($joinColumn['referencedColumnName']) + : $joinColumn['referencedColumnName']; + } + + /** + * {@inheritdoc} + */ + public function getJoinTableName(array $association, ClassMetadata $class, AbstractPlatform $platform) + { + $schema = ''; + + if (isset($association['joinTable']['schema'])) { + $schema = $association['joinTable']['schema']; + $schema .= ! $platform->supportsSchemas() && $platform->canEmulateSchemas() ? '__' : '.'; + } + + $tableName = $association['joinTable']['name']; + + if (isset($association['joinTable']['quoted'])) { + $tableName = $platform->quoteIdentifier($tableName); + } + + return $schema . $tableName; + } + + /** + * {@inheritdoc} + */ + public function getIdentifierColumnNames(ClassMetadata $class, AbstractPlatform $platform) + { + $quotedColumnNames = []; + + foreach ($class->identifier as $fieldName) { + if (isset($class->fieldMappings[$fieldName])) { + $quotedColumnNames[] = $this->getColumnName($fieldName, $class, $platform); + + continue; + } + + // Association defined as Id field + $joinColumns = $class->associationMappings[$fieldName]['joinColumns']; + $assocQuotedColumnNames = array_map( + function ($joinColumn) use ($platform) + { + return isset($joinColumn['quoted']) + ? $platform->quoteIdentifier($joinColumn['name']) + : $joinColumn['name']; + }, + $joinColumns + ); + + $quotedColumnNames = array_merge($quotedColumnNames, $assocQuotedColumnNames); + } + + return $quotedColumnNames; + } + + /** + * {@inheritdoc} + */ + public function getColumnAlias($columnName, $counter, AbstractPlatform $platform, ClassMetadata $class = null) + { + // 1 ) Concatenate column name and counter + // 2 ) Trim the column alias to the maximum identifier length of the platform. + // If the alias is to long, characters are cut off from the beginning. + // 3 ) Strip non alphanumeric characters + // 4 ) Prefix with "_" if the result its numeric + $columnName = $columnName . '_' . $counter; + $columnName = substr($columnName, -$platform->getMaxIdentifierLength()); + $columnName = preg_replace('/[^A-Za-z0-9_]/', '', $columnName); + $columnName = is_numeric($columnName) ? '_' . $columnName : $columnName; + + return $platform->getSQLResultCasing($columnName); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorColumn.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorColumn.php new file mode 100644 index 0000000..97ca7e9 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorColumn.php @@ -0,0 +1,54 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("CLASS") + */ +final class DiscriminatorColumn implements Annotation +{ + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $type; + + /** + * @var integer + */ + public $length; + + /** + * Field name used in non-object hydration (array/scalar). + * + * @var mixed + */ + public $fieldName; + + /** + * @var string + */ + public $columnDefinition; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorMap.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorMap.php new file mode 100644 index 0000000..09d6194 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorMap.php @@ -0,0 +1,32 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("CLASS") + */ +final class DiscriminatorMap implements Annotation +{ + /** + * @var array + */ + public $value; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php new file mode 100644 index 0000000..d59fd3b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php @@ -0,0 +1,673 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Driver; + +use Doctrine\Common\Annotations\AnnotationReader; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver as AbstractAnnotationDriver; +use Doctrine\ORM\Events; +use Doctrine\ORM\Mapping; +use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder; +use Doctrine\ORM\Mapping\MappingException; + +/** + * The AnnotationDriver reads the mapping metadata from docblock annotations. + * + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan H. Wage + * @author Roman Borschel + */ +class AnnotationDriver extends AbstractAnnotationDriver +{ + /** + * {@inheritDoc} + */ + protected $entityAnnotationClasses = [ + Mapping\Entity::class => 1, + Mapping\MappedSuperclass::class => 2, + ]; + + /** + * {@inheritDoc} + */ + public function loadMetadataForClass($className, ClassMetadata $metadata) + { + /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */ + $class = $metadata->getReflectionClass(); + + if ( ! $class) { + // this happens when running annotation driver in combination with + // static reflection services. This is not the nicest fix + $class = new \ReflectionClass($metadata->name); + } + + $classAnnotations = $this->reader->getClassAnnotations($class); + + if ($classAnnotations) { + foreach ($classAnnotations as $key => $annot) { + if ( ! is_numeric($key)) { + continue; + } + + $classAnnotations[get_class($annot)] = $annot; + } + } + + // Evaluate Entity annotation + if (isset($classAnnotations[Mapping\Entity::class])) { + $entityAnnot = $classAnnotations[Mapping\Entity::class]; + if ($entityAnnot->repositoryClass !== null) { + $metadata->setCustomRepositoryClass($entityAnnot->repositoryClass); + } + + if ($entityAnnot->readOnly) { + $metadata->markReadOnly(); + } + } else if (isset($classAnnotations[Mapping\MappedSuperclass::class])) { + $mappedSuperclassAnnot = $classAnnotations[Mapping\MappedSuperclass::class]; + + $metadata->setCustomRepositoryClass($mappedSuperclassAnnot->repositoryClass); + $metadata->isMappedSuperclass = true; + } else if (isset($classAnnotations[Mapping\Embeddable::class])) { + $metadata->isEmbeddedClass = true; + } else { + throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className); + } + + // Evaluate Table annotation + if (isset($classAnnotations[Mapping\Table::class])) { + $tableAnnot = $classAnnotations[Mapping\Table::class]; + $primaryTable = [ + 'name' => $tableAnnot->name, + 'schema' => $tableAnnot->schema + ]; + + if ($tableAnnot->indexes !== null) { + foreach ($tableAnnot->indexes as $indexAnnot) { + $index = ['columns' => $indexAnnot->columns]; + + if ( ! empty($indexAnnot->flags)) { + $index['flags'] = $indexAnnot->flags; + } + + if ( ! empty($indexAnnot->options)) { + $index['options'] = $indexAnnot->options; + } + + if ( ! empty($indexAnnot->name)) { + $primaryTable['indexes'][$indexAnnot->name] = $index; + } else { + $primaryTable['indexes'][] = $index; + } + } + } + + if ($tableAnnot->uniqueConstraints !== null) { + foreach ($tableAnnot->uniqueConstraints as $uniqueConstraintAnnot) { + $uniqueConstraint = ['columns' => $uniqueConstraintAnnot->columns]; + + if ( ! empty($uniqueConstraintAnnot->options)) { + $uniqueConstraint['options'] = $uniqueConstraintAnnot->options; + } + + if ( ! empty($uniqueConstraintAnnot->name)) { + $primaryTable['uniqueConstraints'][$uniqueConstraintAnnot->name] = $uniqueConstraint; + } else { + $primaryTable['uniqueConstraints'][] = $uniqueConstraint; + } + } + } + + if ($tableAnnot->options) { + $primaryTable['options'] = $tableAnnot->options; + } + + $metadata->setPrimaryTable($primaryTable); + } + + // Evaluate @Cache annotation + if (isset($classAnnotations[Mapping\Cache::class])) { + $cacheAnnot = $classAnnotations[Mapping\Cache::class]; + $cacheMap = [ + 'region' => $cacheAnnot->region, + 'usage' => constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $cacheAnnot->usage), + ]; + + $metadata->enableCache($cacheMap); + } + + // Evaluate NamedNativeQueries annotation + if (isset($classAnnotations[Mapping\NamedNativeQueries::class])) { + $namedNativeQueriesAnnot = $classAnnotations[Mapping\NamedNativeQueries::class]; + + foreach ($namedNativeQueriesAnnot->value as $namedNativeQuery) { + $metadata->addNamedNativeQuery( + [ + 'name' => $namedNativeQuery->name, + 'query' => $namedNativeQuery->query, + 'resultClass' => $namedNativeQuery->resultClass, + 'resultSetMapping' => $namedNativeQuery->resultSetMapping, + ] + ); + } + } + + // Evaluate SqlResultSetMappings annotation + if (isset($classAnnotations[Mapping\SqlResultSetMappings::class])) { + $sqlResultSetMappingsAnnot = $classAnnotations[Mapping\SqlResultSetMappings::class]; + + foreach ($sqlResultSetMappingsAnnot->value as $resultSetMapping) { + $entities = []; + $columns = []; + foreach ($resultSetMapping->entities as $entityResultAnnot) { + $entityResult = [ + 'fields' => [], + 'entityClass' => $entityResultAnnot->entityClass, + 'discriminatorColumn' => $entityResultAnnot->discriminatorColumn, + ]; + + foreach ($entityResultAnnot->fields as $fieldResultAnnot) { + $entityResult['fields'][] = [ + 'name' => $fieldResultAnnot->name, + 'column' => $fieldResultAnnot->column + ]; + } + + $entities[] = $entityResult; + } + + foreach ($resultSetMapping->columns as $columnResultAnnot) { + $columns[] = [ + 'name' => $columnResultAnnot->name, + ]; + } + + $metadata->addSqlResultSetMapping( + [ + 'name' => $resultSetMapping->name, + 'entities' => $entities, + 'columns' => $columns + ] + ); + } + } + + // Evaluate NamedQueries annotation + if (isset($classAnnotations[Mapping\NamedQueries::class])) { + $namedQueriesAnnot = $classAnnotations[Mapping\NamedQueries::class]; + + if ( ! is_array($namedQueriesAnnot->value)) { + throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations."); + } + + foreach ($namedQueriesAnnot->value as $namedQuery) { + if ( ! ($namedQuery instanceof Mapping\NamedQuery)) { + throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations."); + } + $metadata->addNamedQuery( + [ + 'name' => $namedQuery->name, + 'query' => $namedQuery->query + ] + ); + } + } + + // Evaluate InheritanceType annotation + if (isset($classAnnotations[Mapping\InheritanceType::class])) { + $inheritanceTypeAnnot = $classAnnotations[Mapping\InheritanceType::class]; + + $metadata->setInheritanceType( + constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceTypeAnnot->value) + ); + + if ($metadata->inheritanceType != Mapping\ClassMetadata::INHERITANCE_TYPE_NONE) { + // Evaluate DiscriminatorColumn annotation + if (isset($classAnnotations[Mapping\DiscriminatorColumn::class])) { + $discrColumnAnnot = $classAnnotations[Mapping\DiscriminatorColumn::class]; + + $metadata->setDiscriminatorColumn( + [ + 'name' => $discrColumnAnnot->name, + 'type' => $discrColumnAnnot->type ?: 'string', + 'length' => $discrColumnAnnot->length ?: 255, + 'columnDefinition' => $discrColumnAnnot->columnDefinition, + ] + ); + } else { + $metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]); + } + + // Evaluate DiscriminatorMap annotation + if (isset($classAnnotations[Mapping\DiscriminatorMap::class])) { + $discrMapAnnot = $classAnnotations[Mapping\DiscriminatorMap::class]; + $metadata->setDiscriminatorMap($discrMapAnnot->value); + } + } + } + + + // Evaluate DoctrineChangeTrackingPolicy annotation + if (isset($classAnnotations[Mapping\ChangeTrackingPolicy::class])) { + $changeTrackingAnnot = $classAnnotations[Mapping\ChangeTrackingPolicy::class]; + $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_' . $changeTrackingAnnot->value)); + } + + // Evaluate annotations on properties/fields + /* @var $property \ReflectionProperty */ + foreach ($class->getProperties() as $property) { + if ($metadata->isMappedSuperclass && ! $property->isPrivate() + || + $metadata->isInheritedField($property->name) + || + $metadata->isInheritedAssociation($property->name) + || + $metadata->isInheritedEmbeddedClass($property->name)) { + continue; + } + + $mapping = []; + $mapping['fieldName'] = $property->getName(); + + // Evaluate @Cache annotation + if (($cacheAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Cache::class)) !== null) { + $mapping['cache'] = $metadata->getAssociationCacheDefaults( + $mapping['fieldName'], + [ + 'usage' => constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $cacheAnnot->usage), + 'region' => $cacheAnnot->region, + ] + ); + } + // Check for JoinColumn/JoinColumns annotations + $joinColumns = []; + + if ($joinColumnAnnot = $this->reader->getPropertyAnnotation($property, Mapping\JoinColumn::class)) { + $joinColumns[] = $this->joinColumnToArray($joinColumnAnnot); + } else if ($joinColumnsAnnot = $this->reader->getPropertyAnnotation($property, Mapping\JoinColumns::class)) { + foreach ($joinColumnsAnnot->value as $joinColumn) { + $joinColumns[] = $this->joinColumnToArray($joinColumn); + } + } + + // Field can only be annotated with one of: + // @Column, @OneToOne, @OneToMany, @ManyToOne, @ManyToMany + if ($columnAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Column::class)) { + if ($columnAnnot->type == null) { + throw MappingException::propertyTypeIsRequired($className, $property->getName()); + } + + $mapping = $this->columnToArray($property->getName(), $columnAnnot); + + if ($idAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Id::class)) { + $mapping['id'] = true; + } + + if ($generatedValueAnnot = $this->reader->getPropertyAnnotation($property, Mapping\GeneratedValue::class)) { + $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $generatedValueAnnot->strategy)); + } + + if ($this->reader->getPropertyAnnotation($property, Mapping\Version::class)) { + $metadata->setVersionMapping($mapping); + } + + $metadata->mapField($mapping); + + // Check for SequenceGenerator/TableGenerator definition + if ($seqGeneratorAnnot = $this->reader->getPropertyAnnotation($property, Mapping\SequenceGenerator::class)) { + $metadata->setSequenceGeneratorDefinition( + [ + 'sequenceName' => $seqGeneratorAnnot->sequenceName, + 'allocationSize' => $seqGeneratorAnnot->allocationSize, + 'initialValue' => $seqGeneratorAnnot->initialValue + ] + ); + } else if ($this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\TableGenerator')) { + throw MappingException::tableIdGeneratorNotImplemented($className); + } else if ($customGeneratorAnnot = $this->reader->getPropertyAnnotation($property, Mapping\CustomIdGenerator::class)) { + $metadata->setCustomGeneratorDefinition( + [ + 'class' => $customGeneratorAnnot->class + ] + ); + } + } else if ($oneToOneAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OneToOne::class)) { + if ($idAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Id::class)) { + $mapping['id'] = true; + } + + $mapping['targetEntity'] = $oneToOneAnnot->targetEntity; + $mapping['joinColumns'] = $joinColumns; + $mapping['mappedBy'] = $oneToOneAnnot->mappedBy; + $mapping['inversedBy'] = $oneToOneAnnot->inversedBy; + $mapping['cascade'] = $oneToOneAnnot->cascade; + $mapping['orphanRemoval'] = $oneToOneAnnot->orphanRemoval; + $mapping['fetch'] = $this->getFetchMode($className, $oneToOneAnnot->fetch); + $metadata->mapOneToOne($mapping); + } else if ($oneToManyAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OneToMany::class)) { + $mapping['mappedBy'] = $oneToManyAnnot->mappedBy; + $mapping['targetEntity'] = $oneToManyAnnot->targetEntity; + $mapping['cascade'] = $oneToManyAnnot->cascade; + $mapping['indexBy'] = $oneToManyAnnot->indexBy; + $mapping['orphanRemoval'] = $oneToManyAnnot->orphanRemoval; + $mapping['fetch'] = $this->getFetchMode($className, $oneToManyAnnot->fetch); + + if ($orderByAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OrderBy::class)) { + $mapping['orderBy'] = $orderByAnnot->value; + } + + $metadata->mapOneToMany($mapping); + } else if ($manyToOneAnnot = $this->reader->getPropertyAnnotation($property, Mapping\ManyToOne::class)) { + if ($idAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Id::class)) { + $mapping['id'] = true; + } + + $mapping['joinColumns'] = $joinColumns; + $mapping['cascade'] = $manyToOneAnnot->cascade; + $mapping['inversedBy'] = $manyToOneAnnot->inversedBy; + $mapping['targetEntity'] = $manyToOneAnnot->targetEntity; + $mapping['fetch'] = $this->getFetchMode($className, $manyToOneAnnot->fetch); + $metadata->mapManyToOne($mapping); + } else if ($manyToManyAnnot = $this->reader->getPropertyAnnotation($property, Mapping\ManyToMany::class)) { + $joinTable = []; + + if ($joinTableAnnot = $this->reader->getPropertyAnnotation($property, Mapping\JoinTable::class)) { + $joinTable = [ + 'name' => $joinTableAnnot->name, + 'schema' => $joinTableAnnot->schema + ]; + + foreach ($joinTableAnnot->joinColumns as $joinColumn) { + $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn); + } + + foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) { + $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn); + } + } + + $mapping['joinTable'] = $joinTable; + $mapping['targetEntity'] = $manyToManyAnnot->targetEntity; + $mapping['mappedBy'] = $manyToManyAnnot->mappedBy; + $mapping['inversedBy'] = $manyToManyAnnot->inversedBy; + $mapping['cascade'] = $manyToManyAnnot->cascade; + $mapping['indexBy'] = $manyToManyAnnot->indexBy; + $mapping['orphanRemoval'] = $manyToManyAnnot->orphanRemoval; + $mapping['fetch'] = $this->getFetchMode($className, $manyToManyAnnot->fetch); + + if ($orderByAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OrderBy::class)) { + $mapping['orderBy'] = $orderByAnnot->value; + } + + $metadata->mapManyToMany($mapping); + } else if ($embeddedAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Embedded::class)) { + $mapping['class'] = $embeddedAnnot->class; + $mapping['columnPrefix'] = $embeddedAnnot->columnPrefix; + + $metadata->mapEmbedded($mapping); + } + } + + // Evaluate AssociationOverrides annotation + if (isset($classAnnotations[Mapping\AssociationOverrides::class])) { + $associationOverridesAnnot = $classAnnotations[Mapping\AssociationOverrides::class]; + + foreach ($associationOverridesAnnot->value as $associationOverride) { + $override = []; + $fieldName = $associationOverride->name; + + // Check for JoinColumn/JoinColumns annotations + if ($associationOverride->joinColumns) { + $joinColumns = []; + + foreach ($associationOverride->joinColumns as $joinColumn) { + $joinColumns[] = $this->joinColumnToArray($joinColumn); + } + + $override['joinColumns'] = $joinColumns; + } + + // Check for JoinTable annotations + if ($associationOverride->joinTable) { + $joinTableAnnot = $associationOverride->joinTable; + $joinTable = [ + 'name' => $joinTableAnnot->name, + 'schema' => $joinTableAnnot->schema + ]; + + foreach ($joinTableAnnot->joinColumns as $joinColumn) { + $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn); + } + + foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) { + $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn); + } + + $override['joinTable'] = $joinTable; + } + + // Check for inversedBy + if ($associationOverride->inversedBy) { + $override['inversedBy'] = $associationOverride->inversedBy; + } + + // Check for `fetch` + if ($associationOverride->fetch) { + $override['fetch'] = constant(Mapping\ClassMetadata::class . '::FETCH_' . $associationOverride->fetch); + } + + $metadata->setAssociationOverride($fieldName, $override); + } + } + + // Evaluate AttributeOverrides annotation + if (isset($classAnnotations[Mapping\AttributeOverrides::class])) { + $attributeOverridesAnnot = $classAnnotations[Mapping\AttributeOverrides::class]; + + foreach ($attributeOverridesAnnot->value as $attributeOverrideAnnot) { + $attributeOverride = $this->columnToArray($attributeOverrideAnnot->name, $attributeOverrideAnnot->column); + + $metadata->setAttributeOverride($attributeOverrideAnnot->name, $attributeOverride); + } + } + + // Evaluate EntityListeners annotation + if (isset($classAnnotations[Mapping\EntityListeners::class])) { + $entityListenersAnnot = $classAnnotations[Mapping\EntityListeners::class]; + + foreach ($entityListenersAnnot->value as $item) { + $listenerClassName = $metadata->fullyQualifiedClassName($item); + + if ( ! class_exists($listenerClassName)) { + throw MappingException::entityListenerClassNotFound($listenerClassName, $className); + } + + $hasMapping = false; + $listenerClass = new \ReflectionClass($listenerClassName); + + /* @var $method \ReflectionMethod */ + foreach ($listenerClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { + // find method callbacks. + $callbacks = $this->getMethodCallbacks($method); + $hasMapping = $hasMapping ?: ( ! empty($callbacks)); + + foreach ($callbacks as $value) { + $metadata->addEntityListener($value[1], $listenerClassName, $value[0]); + } + } + + // Evaluate the listener using naming convention. + if ( ! $hasMapping ) { + EntityListenerBuilder::bindEntityListener($metadata, $listenerClassName); + } + } + } + + // Evaluate @HasLifecycleCallbacks annotation + if (isset($classAnnotations[Mapping\HasLifecycleCallbacks::class])) { + /* @var $method \ReflectionMethod */ + foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { + foreach ($this->getMethodCallbacks($method) as $value) { + $metadata->addLifecycleCallback($value[0], $value[1]); + } + } + } + } + + /** + * Attempts to resolve the fetch mode. + * + * @param string $className The class name. + * @param string $fetchMode The fetch mode. + * + * @return integer The fetch mode as defined in ClassMetadata. + * + * @throws MappingException If the fetch mode is not valid. + */ + private function getFetchMode($className, $fetchMode) + { + if ( ! defined('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode)) { + throw MappingException::invalidFetchMode($className, $fetchMode); + } + + return constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode); + } + + /** + * Parses the given method. + * + * @param \ReflectionMethod $method + * + * @return array + */ + private function getMethodCallbacks(\ReflectionMethod $method) + { + $callbacks = []; + $annotations = $this->reader->getMethodAnnotations($method); + + foreach ($annotations as $annot) { + if ($annot instanceof Mapping\PrePersist) { + $callbacks[] = [$method->name, Events::prePersist]; + } + + if ($annot instanceof Mapping\PostPersist) { + $callbacks[] = [$method->name, Events::postPersist]; + } + + if ($annot instanceof Mapping\PreUpdate) { + $callbacks[] = [$method->name, Events::preUpdate]; + } + + if ($annot instanceof Mapping\PostUpdate) { + $callbacks[] = [$method->name, Events::postUpdate]; + } + + if ($annot instanceof Mapping\PreRemove) { + $callbacks[] = [$method->name, Events::preRemove]; + } + + if ($annot instanceof Mapping\PostRemove) { + $callbacks[] = [$method->name, Events::postRemove]; + } + + if ($annot instanceof Mapping\PostLoad) { + $callbacks[] = [$method->name, Events::postLoad]; + } + + if ($annot instanceof Mapping\PreFlush) { + $callbacks[] = [$method->name, Events::preFlush]; + } + } + + return $callbacks; + } + + /** + * Parse the given JoinColumn as array + * + * @param Mapping\JoinColumn $joinColumn + * @return array + */ + private function joinColumnToArray(Mapping\JoinColumn $joinColumn) + { + return [ + 'name' => $joinColumn->name, + 'unique' => $joinColumn->unique, + 'nullable' => $joinColumn->nullable, + 'onDelete' => $joinColumn->onDelete, + 'columnDefinition' => $joinColumn->columnDefinition, + 'referencedColumnName' => $joinColumn->referencedColumnName, + ]; + } + + /** + * Parse the given Column as array + * + * @param string $fieldName + * @param Mapping\Column $column + * + * @return array + */ + private function columnToArray($fieldName, Mapping\Column $column) + { + $mapping = [ + 'fieldName' => $fieldName, + 'type' => $column->type, + 'scale' => $column->scale, + 'length' => $column->length, + 'unique' => $column->unique, + 'nullable' => $column->nullable, + 'precision' => $column->precision + ]; + + if ($column->options) { + $mapping['options'] = $column->options; + } + + if (isset($column->name)) { + $mapping['columnName'] = $column->name; + } + + if (isset($column->columnDefinition)) { + $mapping['columnDefinition'] = $column->columnDefinition; + } + + return $mapping; + } + + /** + * Factory method for the Annotation Driver. + * + * @param array|string $paths + * @param AnnotationReader|null $reader + * + * @return AnnotationDriver + */ + static public function create($paths = [], AnnotationReader $reader = null) + { + if ($reader == null) { + $reader = new AnnotationReader(); + } + + return new self($reader, $paths); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php new file mode 100644 index 0000000..83798e1 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php @@ -0,0 +1,557 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Driver; + +use Doctrine\Common\Inflector\Inflector; +use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Doctrine\DBAL\Schema\AbstractSchemaManager; +use Doctrine\DBAL\Schema\SchemaException; +use Doctrine\DBAL\Schema\Table; +use Doctrine\DBAL\Schema\Column; +use Doctrine\DBAL\Types\Type; +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Doctrine\ORM\Mapping\MappingException; +use function preg_replace; + +/** + * The DatabaseDriver reverse engineers the mapping metadata from a database. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Benjamin Eberlei + */ +class DatabaseDriver implements MappingDriver +{ + /** + * @var AbstractSchemaManager + */ + private $_sm; + + /** + * @var array|null + */ + private $tables = null; + + /** + * @var array + */ + private $classToTableNames = []; + + /** + * @var array + */ + private $manyToManyTables = []; + + /** + * @var array + */ + private $classNamesForTables = []; + + /** + * @var array + */ + private $fieldNamesForColumns = []; + + /** + * The namespace for the generated entities. + * + * @var string|null + */ + private $namespace; + + /** + * @param AbstractSchemaManager $schemaManager + */ + public function __construct(AbstractSchemaManager $schemaManager) + { + $this->_sm = $schemaManager; + } + + /** + * Set the namespace for the generated entities. + * + * @param string $namespace + * + * @return void + */ + public function setNamespace($namespace) + { + $this->namespace = $namespace; + } + + /** + * {@inheritDoc} + */ + public function isTransient($className) + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getAllClassNames() + { + $this->reverseEngineerMappingFromDatabase(); + + return array_keys($this->classToTableNames); + } + + /** + * Sets class name for a table. + * + * @param string $tableName + * @param string $className + * + * @return void + */ + public function setClassNameForTable($tableName, $className) + { + $this->classNamesForTables[$tableName] = $className; + } + + /** + * Sets field name for a column on a specific table. + * + * @param string $tableName + * @param string $columnName + * @param string $fieldName + * + * @return void + */ + public function setFieldNameForColumn($tableName, $columnName, $fieldName) + { + $this->fieldNamesForColumns[$tableName][$columnName] = $fieldName; + } + + /** + * Sets tables manually instead of relying on the reverse engineering capabilities of SchemaManager. + * + * @param array $entityTables + * @param array $manyToManyTables + * + * @return void + */ + public function setTables($entityTables, $manyToManyTables) + { + $this->tables = $this->manyToManyTables = $this->classToTableNames = []; + + foreach ($entityTables as $table) { + $className = $this->getClassNameForTable($table->getName()); + + $this->classToTableNames[$className] = $table->getName(); + $this->tables[$table->getName()] = $table; + } + + foreach ($manyToManyTables as $table) { + $this->manyToManyTables[$table->getName()] = $table; + } + } + + /** + * {@inheritDoc} + */ + public function loadMetadataForClass($className, ClassMetadata $metadata) + { + $this->reverseEngineerMappingFromDatabase(); + + if ( ! isset($this->classToTableNames[$className])) { + throw new \InvalidArgumentException("Unknown class " . $className); + } + + $tableName = $this->classToTableNames[$className]; + + $metadata->name = $className; + $metadata->table['name'] = $tableName; + + $this->buildIndexes($metadata); + $this->buildFieldMappings($metadata); + $this->buildToOneAssociationMappings($metadata); + + foreach ($this->manyToManyTables as $manyTable) { + foreach ($manyTable->getForeignKeys() as $foreignKey) { + // foreign key maps to the table of the current entity, many to many association probably exists + if ( ! (strtolower($tableName) === strtolower($foreignKey->getForeignTableName()))) { + continue; + } + + $myFk = $foreignKey; + $otherFk = null; + + foreach ($manyTable->getForeignKeys() as $foreignKey) { + if ($foreignKey != $myFk) { + $otherFk = $foreignKey; + break; + } + } + + if ( ! $otherFk) { + // the definition of this many to many table does not contain + // enough foreign key information to continue reverse engineering. + continue; + } + + $localColumn = current($myFk->getColumns()); + + $associationMapping = []; + $associationMapping['fieldName'] = $this->getFieldNameForColumn($manyTable->getName(), current($otherFk->getColumns()), true); + $associationMapping['targetEntity'] = $this->getClassNameForTable($otherFk->getForeignTableName()); + + if (current($manyTable->getColumns())->getName() == $localColumn) { + $associationMapping['inversedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getColumns()), true); + $associationMapping['joinTable'] = [ + 'name' => strtolower($manyTable->getName()), + 'joinColumns' => [], + 'inverseJoinColumns' => [], + ]; + + $fkCols = $myFk->getForeignColumns(); + $cols = $myFk->getColumns(); + + for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) { + $associationMapping['joinTable']['joinColumns'][] = [ + 'name' => $cols[$i], + 'referencedColumnName' => $fkCols[$i], + ]; + } + + $fkCols = $otherFk->getForeignColumns(); + $cols = $otherFk->getColumns(); + + for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) { + $associationMapping['joinTable']['inverseJoinColumns'][] = [ + 'name' => $cols[$i], + 'referencedColumnName' => $fkCols[$i], + ]; + } + } else { + $associationMapping['mappedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getColumns()), true); + } + + $metadata->mapManyToMany($associationMapping); + + break; + } + } + } + + /** + * @return void + * + * @throws \Doctrine\ORM\Mapping\MappingException + */ + private function reverseEngineerMappingFromDatabase() + { + if ($this->tables !== null) { + return; + } + + $tables = []; + + foreach ($this->_sm->listTableNames() as $tableName) { + $tables[$tableName] = $this->_sm->listTableDetails($tableName); + } + + $this->tables = $this->manyToManyTables = $this->classToTableNames = []; + + foreach ($tables as $tableName => $table) { + $foreignKeys = ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) + ? $table->getForeignKeys() + : []; + + $allForeignKeyColumns = []; + + foreach ($foreignKeys as $foreignKey) { + $allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns()); + } + + if ( ! $table->hasPrimaryKey()) { + throw new MappingException( + "Table " . $table->getName() . " has no primary key. Doctrine does not ". + "support reverse engineering from tables that don't have a primary key." + ); + } + + $pkColumns = $table->getPrimaryKey()->getColumns(); + + sort($pkColumns); + sort($allForeignKeyColumns); + + if ($pkColumns == $allForeignKeyColumns && count($foreignKeys) == 2) { + $this->manyToManyTables[$tableName] = $table; + } else { + // lower-casing is necessary because of Oracle Uppercase Tablenames, + // assumption is lower-case + underscore separated. + $className = $this->getClassNameForTable($tableName); + + $this->tables[$tableName] = $table; + $this->classToTableNames[$className] = $tableName; + } + } + } + + /** + * Build indexes from a class metadata. + * + * @param \Doctrine\ORM\Mapping\ClassMetadataInfo $metadata + */ + private function buildIndexes(ClassMetadataInfo $metadata) + { + $tableName = $metadata->table['name']; + $indexes = $this->tables[$tableName]->getIndexes(); + + foreach ($indexes as $index) { + if ($index->isPrimary()) { + continue; + } + + $indexName = $index->getName(); + $indexColumns = $index->getColumns(); + $constraintType = $index->isUnique() + ? 'uniqueConstraints' + : 'indexes'; + + $metadata->table[$constraintType][$indexName]['columns'] = $indexColumns; + } + } + + /** + * Build field mapping from class metadata. + * + * @param \Doctrine\ORM\Mapping\ClassMetadataInfo $metadata + */ + private function buildFieldMappings(ClassMetadataInfo $metadata) + { + $tableName = $metadata->table['name']; + $columns = $this->tables[$tableName]->getColumns(); + $primaryKeys = $this->getTablePrimaryKeys($this->tables[$tableName]); + $foreignKeys = $this->getTableForeignKeys($this->tables[$tableName]); + $allForeignKeys = []; + + foreach ($foreignKeys as $foreignKey) { + $allForeignKeys = array_merge($allForeignKeys, $foreignKey->getLocalColumns()); + } + + $ids = []; + $fieldMappings = []; + + foreach ($columns as $column) { + if (in_array($column->getName(), $allForeignKeys)) { + continue; + } + + $fieldMapping = $this->buildFieldMapping($tableName, $column); + + if ($primaryKeys && in_array($column->getName(), $primaryKeys)) { + $fieldMapping['id'] = true; + $ids[] = $fieldMapping; + } + + $fieldMappings[] = $fieldMapping; + } + + // We need to check for the columns here, because we might have associations as id as well. + if ($ids && count($primaryKeys) == 1) { + $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); + } + + foreach ($fieldMappings as $fieldMapping) { + $metadata->mapField($fieldMapping); + } + } + + /** + * Build field mapping from a schema column definition + * + * @param string $tableName + * @param \Doctrine\DBAL\Schema\Column $column + * + * @return array + */ + private function buildFieldMapping($tableName, Column $column) + { + $fieldMapping = [ + 'fieldName' => $this->getFieldNameForColumn($tableName, $column->getName(), false), + 'columnName' => $column->getName(), + 'type' => $column->getType()->getName(), + 'nullable' => ( ! $column->getNotnull()), + ]; + + // Type specific elements + switch ($fieldMapping['type']) { + case Type::TARRAY: + case Type::BLOB: + case Type::GUID: + case Type::JSON_ARRAY: + case Type::OBJECT: + case Type::SIMPLE_ARRAY: + case Type::STRING: + case Type::TEXT: + $fieldMapping['length'] = $column->getLength(); + $fieldMapping['options']['fixed'] = $column->getFixed(); + break; + + case Type::DECIMAL: + case Type::FLOAT: + $fieldMapping['precision'] = $column->getPrecision(); + $fieldMapping['scale'] = $column->getScale(); + break; + + case Type::INTEGER: + case Type::BIGINT: + case Type::SMALLINT: + $fieldMapping['options']['unsigned'] = $column->getUnsigned(); + break; + } + + // Comment + if (($comment = $column->getComment()) !== null) { + $fieldMapping['options']['comment'] = $comment; + } + + // Default + if (($default = $column->getDefault()) !== null) { + $fieldMapping['options']['default'] = $default; + } + + return $fieldMapping; + } + + /** + * Build to one (one to one, many to one) association mapping from class metadata. + * + * @param \Doctrine\ORM\Mapping\ClassMetadataInfo $metadata + */ + private function buildToOneAssociationMappings(ClassMetadataInfo $metadata) + { + $tableName = $metadata->table['name']; + $primaryKeys = $this->getTablePrimaryKeys($this->tables[$tableName]); + $foreignKeys = $this->getTableForeignKeys($this->tables[$tableName]); + + foreach ($foreignKeys as $foreignKey) { + $foreignTableName = $foreignKey->getForeignTableName(); + $fkColumns = $foreignKey->getColumns(); + $fkForeignColumns = $foreignKey->getForeignColumns(); + $localColumn = current($fkColumns); + $associationMapping = [ + 'fieldName' => $this->getFieldNameForColumn($tableName, $localColumn, true), + 'targetEntity' => $this->getClassNameForTable($foreignTableName), + ]; + + if (isset($metadata->fieldMappings[$associationMapping['fieldName']])) { + $associationMapping['fieldName'] .= '2'; // "foo" => "foo2" + } + + if ($primaryKeys && in_array($localColumn, $primaryKeys)) { + $associationMapping['id'] = true; + } + + for ($i = 0, $fkColumnsCount = count($fkColumns); $i < $fkColumnsCount; $i++) { + $associationMapping['joinColumns'][] = [ + 'name' => $fkColumns[$i], + 'referencedColumnName' => $fkForeignColumns[$i], + ]; + } + + // Here we need to check if $fkColumns are the same as $primaryKeys + if ( ! array_diff($fkColumns, $primaryKeys)) { + $metadata->mapOneToOne($associationMapping); + } else { + $metadata->mapManyToOne($associationMapping); + } + } + } + + /** + * Retrieve schema table definition foreign keys. + * + * @param \Doctrine\DBAL\Schema\Table $table + * + * @return array + */ + private function getTableForeignKeys(Table $table) + { + return ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) + ? $table->getForeignKeys() + : []; + } + + /** + * Retrieve schema table definition primary keys. + * + * @param \Doctrine\DBAL\Schema\Table $table + * + * @return array + */ + private function getTablePrimaryKeys(Table $table) + { + try { + return $table->getPrimaryKey()->getColumns(); + } catch (SchemaException $e) { + // Do nothing + } + + return []; + } + + /** + * Returns the mapped class name for a table if it exists. Otherwise return "classified" version. + * + * @param string $tableName + * + * @return string + */ + private function getClassNameForTable($tableName) + { + if (isset($this->classNamesForTables[$tableName])) { + return $this->namespace . $this->classNamesForTables[$tableName]; + } + + return $this->namespace . Inflector::classify(strtolower($tableName)); + } + + /** + * Return the mapped field name for a column, if it exists. Otherwise return camelized version. + * + * @param string $tableName + * @param string $columnName + * @param boolean $fk Whether the column is a foreignkey or not. + * + * @return string + */ + private function getFieldNameForColumn($tableName, $columnName, $fk = false) + { + if (isset($this->fieldNamesForColumns[$tableName]) && isset($this->fieldNamesForColumns[$tableName][$columnName])) { + return $this->fieldNamesForColumns[$tableName][$columnName]; + } + + $columnName = strtolower($columnName); + + // Replace _id if it is a foreignkey column + if ($fk) { + $columnName = preg_replace('/_id$/', '', $columnName); + } + + return Inflector::camelize($columnName); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php new file mode 100644 index 0000000..8f4a34c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php @@ -0,0 +1,69 @@ +. + */ + +require_once __DIR__.'/../Annotation.php'; +require_once __DIR__.'/../Entity.php'; +require_once __DIR__.'/../Embeddable.php'; +require_once __DIR__.'/../Embedded.php'; +require_once __DIR__.'/../MappedSuperclass.php'; +require_once __DIR__.'/../InheritanceType.php'; +require_once __DIR__.'/../DiscriminatorColumn.php'; +require_once __DIR__.'/../DiscriminatorMap.php'; +require_once __DIR__.'/../Id.php'; +require_once __DIR__.'/../GeneratedValue.php'; +require_once __DIR__.'/../Version.php'; +require_once __DIR__.'/../JoinColumn.php'; +require_once __DIR__.'/../JoinColumns.php'; +require_once __DIR__.'/../Column.php'; +require_once __DIR__.'/../OneToOne.php'; +require_once __DIR__.'/../OneToMany.php'; +require_once __DIR__.'/../ManyToOne.php'; +require_once __DIR__.'/../ManyToMany.php'; +require_once __DIR__.'/../Table.php'; +require_once __DIR__.'/../UniqueConstraint.php'; +require_once __DIR__.'/../Index.php'; +require_once __DIR__.'/../JoinTable.php'; +require_once __DIR__.'/../SequenceGenerator.php'; +require_once __DIR__.'/../CustomIdGenerator.php'; +require_once __DIR__.'/../ChangeTrackingPolicy.php'; +require_once __DIR__.'/../OrderBy.php'; +require_once __DIR__.'/../NamedQueries.php'; +require_once __DIR__.'/../NamedQuery.php'; +require_once __DIR__.'/../HasLifecycleCallbacks.php'; +require_once __DIR__.'/../PrePersist.php'; +require_once __DIR__.'/../PostPersist.php'; +require_once __DIR__.'/../PreUpdate.php'; +require_once __DIR__.'/../PostUpdate.php'; +require_once __DIR__.'/../PreRemove.php'; +require_once __DIR__.'/../PostRemove.php'; +require_once __DIR__.'/../PostLoad.php'; +require_once __DIR__.'/../PreFlush.php'; +require_once __DIR__.'/../FieldResult.php'; +require_once __DIR__.'/../ColumnResult.php'; +require_once __DIR__.'/../EntityResult.php'; +require_once __DIR__.'/../NamedNativeQuery.php'; +require_once __DIR__.'/../NamedNativeQueries.php'; +require_once __DIR__.'/../SqlResultSetMapping.php'; +require_once __DIR__.'/../SqlResultSetMappings.php'; +require_once __DIR__.'/../AssociationOverride.php'; +require_once __DIR__.'/../AssociationOverrides.php'; +require_once __DIR__.'/../AttributeOverride.php'; +require_once __DIR__.'/../AttributeOverrides.php'; +require_once __DIR__.'/../EntityListeners.php'; +require_once __DIR__.'/../Cache.php'; diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DriverChain.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DriverChain.php new file mode 100644 index 0000000..f4cd8cd --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DriverChain.php @@ -0,0 +1,31 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Driver; + +use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain; + +/** + * {@inheritDoc} + * + * @deprecated this driver will be removed. Use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain instead + */ +class DriverChain extends MappingDriverChain +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/PHPDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/PHPDriver.php new file mode 100644 index 0000000..28e2dbe --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/PHPDriver.php @@ -0,0 +1,31 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Driver; + +use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver as CommonPHPDriver; + +/** + * {@inheritDoc} + * + * @deprecated this driver will be removed. Use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver instead + */ +class PHPDriver extends CommonPHPDriver +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedXmlDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedXmlDriver.php new file mode 100644 index 0000000..9bfd84c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedXmlDriver.php @@ -0,0 +1,43 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Driver; + +use Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator; + +/** + * XmlDriver that additionally looks for mapping information in a global file. + * + * @author Fabien Potencier + * @author Benjamin Eberlei + * @license MIT + */ +class SimplifiedXmlDriver extends XmlDriver +{ + const DEFAULT_FILE_EXTENSION = '.orm.xml'; + + /** + * {@inheritDoc} + */ + public function __construct($prefixes, $fileExtension = self::DEFAULT_FILE_EXTENSION) + { + $locator = new SymfonyFileLocator((array) $prefixes, $fileExtension); + parent::__construct($locator, $fileExtension); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedYamlDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedYamlDriver.php new file mode 100644 index 0000000..8f38784 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedYamlDriver.php @@ -0,0 +1,43 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Driver; + +use Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator; + +/** + * YamlDriver that additionally looks for mapping information in a global file. + * + * @author Fabien Potencier + * @author Benjamin Eberlei + * @license MIT + */ +class SimplifiedYamlDriver extends YamlDriver +{ + const DEFAULT_FILE_EXTENSION = '.orm.yml'; + + /** + * {@inheritDoc} + */ + public function __construct($prefixes, $fileExtension = self::DEFAULT_FILE_EXTENSION) + { + $locator = new SymfonyFileLocator((array) $prefixes, $fileExtension); + parent::__construct($locator, $fileExtension); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/StaticPHPDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/StaticPHPDriver.php new file mode 100644 index 0000000..d6c6ead --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/StaticPHPDriver.php @@ -0,0 +1,31 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Driver; + +use Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver as CommonStaticPHPDriver; + +/** + * {@inheritDoc} + * + * @deprecated this driver will be removed. Use Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver instead + */ +class StaticPHPDriver extends CommonStaticPHPDriver +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php new file mode 100644 index 0000000..93b697c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php @@ -0,0 +1,881 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Driver; + +use Doctrine\Common\Collections\Criteria; +use SimpleXMLElement; +use Doctrine\Common\Persistence\Mapping\Driver\FileDriver; +use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Doctrine\ORM\Mapping\MappingException; +use Doctrine\ORM\Mapping\ClassMetadata as Metadata; + +/** + * XmlDriver is a metadata driver that enables mapping through XML files. + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan H. Wage + * @author Roman Borschel + */ +class XmlDriver extends FileDriver +{ + const DEFAULT_FILE_EXTENSION = '.dcm.xml'; + + /** + * {@inheritDoc} + */ + public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION) + { + parent::__construct($locator, $fileExtension); + } + + /** + * {@inheritDoc} + */ + public function loadMetadataForClass($className, ClassMetadata $metadata) + { + /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */ + /* @var $xmlRoot SimpleXMLElement */ + $xmlRoot = $this->getElement($className); + + if ($xmlRoot->getName() == 'entity') { + if (isset($xmlRoot['repository-class'])) { + $metadata->setCustomRepositoryClass((string) $xmlRoot['repository-class']); + } + if (isset($xmlRoot['read-only']) && $this->evaluateBoolean($xmlRoot['read-only'])) { + $metadata->markReadOnly(); + } + } else if ($xmlRoot->getName() == 'mapped-superclass') { + $metadata->setCustomRepositoryClass( + isset($xmlRoot['repository-class']) ? (string) $xmlRoot['repository-class'] : null + ); + $metadata->isMappedSuperclass = true; + } else if ($xmlRoot->getName() == 'embeddable') { + $metadata->isEmbeddedClass = true; + } else { + throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className); + } + + // Evaluate attributes + $primaryTable = []; + + if (isset($xmlRoot['table'])) { + $primaryTable['name'] = (string) $xmlRoot['table']; + } + + if (isset($xmlRoot['schema'])) { + $primaryTable['schema'] = (string) $xmlRoot['schema']; + } + + $metadata->setPrimaryTable($primaryTable); + + // Evaluate second level cache + if (isset($xmlRoot->cache)) { + $metadata->enableCache($this->cacheToArray($xmlRoot->cache)); + } + + // Evaluate named queries + if (isset($xmlRoot->{'named-queries'})) { + foreach ($xmlRoot->{'named-queries'}->{'named-query'} as $namedQueryElement) { + $metadata->addNamedQuery( + [ + 'name' => (string) $namedQueryElement['name'], + 'query' => (string) $namedQueryElement['query'] + ] + ); + } + } + + // Evaluate native named queries + if (isset($xmlRoot->{'named-native-queries'})) { + foreach ($xmlRoot->{'named-native-queries'}->{'named-native-query'} as $nativeQueryElement) { + $metadata->addNamedNativeQuery( + [ + 'name' => isset($nativeQueryElement['name']) ? (string) $nativeQueryElement['name'] : null, + 'query' => isset($nativeQueryElement->query) ? (string) $nativeQueryElement->query : null, + 'resultClass' => isset($nativeQueryElement['result-class']) ? (string) $nativeQueryElement['result-class'] : null, + 'resultSetMapping' => isset($nativeQueryElement['result-set-mapping']) ? (string) $nativeQueryElement['result-set-mapping'] : null, + ] + ); + } + } + + // Evaluate sql result set mapping + if (isset($xmlRoot->{'sql-result-set-mappings'})) { + foreach ($xmlRoot->{'sql-result-set-mappings'}->{'sql-result-set-mapping'} as $rsmElement) { + $entities = []; + $columns = []; + foreach ($rsmElement as $entityElement) { + // + if (isset($entityElement['entity-class'])) { + $entityResult = [ + 'fields' => [], + 'entityClass' => (string) $entityElement['entity-class'], + 'discriminatorColumn' => isset($entityElement['discriminator-column']) ? (string) $entityElement['discriminator-column'] : null, + ]; + + foreach ($entityElement as $fieldElement) { + $entityResult['fields'][] = [ + 'name' => isset($fieldElement['name']) ? (string) $fieldElement['name'] : null, + 'column' => isset($fieldElement['column']) ? (string) $fieldElement['column'] : null, + ]; + } + + $entities[] = $entityResult; + } + + // + if (isset($entityElement['name'])) { + $columns[] = [ + 'name' => (string) $entityElement['name'], + ]; + } + } + + $metadata->addSqlResultSetMapping( + [ + 'name' => (string) $rsmElement['name'], + 'entities' => $entities, + 'columns' => $columns + ] + ); + } + } + + if (isset($xmlRoot['inheritance-type'])) { + $inheritanceType = (string) $xmlRoot['inheritance-type']; + $metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceType)); + + if ($metadata->inheritanceType != Metadata::INHERITANCE_TYPE_NONE) { + // Evaluate + if (isset($xmlRoot->{'discriminator-column'})) { + $discrColumn = $xmlRoot->{'discriminator-column'}; + $metadata->setDiscriminatorColumn( + [ + 'name' => isset($discrColumn['name']) ? (string) $discrColumn['name'] : null, + 'type' => isset($discrColumn['type']) ? (string) $discrColumn['type'] : 'string', + 'length' => isset($discrColumn['length']) ? (string) $discrColumn['length'] : 255, + 'columnDefinition' => isset($discrColumn['column-definition']) ? (string) $discrColumn['column-definition'] : null + ] + ); + } else { + $metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]); + } + + // Evaluate + if (isset($xmlRoot->{'discriminator-map'})) { + $map = []; + foreach ($xmlRoot->{'discriminator-map'}->{'discriminator-mapping'} as $discrMapElement) { + $map[(string) $discrMapElement['value']] = (string) $discrMapElement['class']; + } + $metadata->setDiscriminatorMap($map); + } + } + } + + + // Evaluate + if (isset($xmlRoot['change-tracking-policy'])) { + $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_' + . strtoupper((string) $xmlRoot['change-tracking-policy']))); + } + + // Evaluate + if (isset($xmlRoot->indexes)) { + $metadata->table['indexes'] = []; + foreach ($xmlRoot->indexes->index as $indexXml) { + $index = ['columns' => explode(',', (string) $indexXml['columns'])]; + + if (isset($indexXml['flags'])) { + $index['flags'] = explode(',', (string) $indexXml['flags']); + } + + if (isset($indexXml->options)) { + $index['options'] = $this->_parseOptions($indexXml->options->children()); + } + + if (isset($indexXml['name'])) { + $metadata->table['indexes'][(string) $indexXml['name']] = $index; + } else { + $metadata->table['indexes'][] = $index; + } + } + } + + // Evaluate + if (isset($xmlRoot->{'unique-constraints'})) { + $metadata->table['uniqueConstraints'] = []; + foreach ($xmlRoot->{'unique-constraints'}->{'unique-constraint'} as $uniqueXml) { + $unique = ['columns' => explode(',', (string) $uniqueXml['columns'])]; + + if (isset($uniqueXml->options)) { + $unique['options'] = $this->_parseOptions($uniqueXml->options->children()); + } + + if (isset($uniqueXml['name'])) { + $metadata->table['uniqueConstraints'][(string) $uniqueXml['name']] = $unique; + } else { + $metadata->table['uniqueConstraints'][] = $unique; + } + } + } + + if (isset($xmlRoot->options)) { + $metadata->table['options'] = $this->_parseOptions($xmlRoot->options->children()); + } + + // The mapping assignment is done in 2 times as a bug might occurs on some php/xml lib versions + // The internal SimpleXmlIterator get resetted, to this generate a duplicate field exception + $mappings = []; + // Evaluate mappings + if (isset($xmlRoot->field)) { + foreach ($xmlRoot->field as $fieldMapping) { + $mapping = $this->columnToArray($fieldMapping); + + if (isset($mapping['version'])) { + $metadata->setVersionMapping($mapping); + unset($mapping['version']); + } + + $metadata->mapField($mapping); + } + } + + if (isset($xmlRoot->embedded)) { + foreach ($xmlRoot->embedded as $embeddedMapping) { + $columnPrefix = isset($embeddedMapping['column-prefix']) + ? (string) $embeddedMapping['column-prefix'] + : null; + + $useColumnPrefix = isset($embeddedMapping['use-column-prefix']) + ? $this->evaluateBoolean($embeddedMapping['use-column-prefix']) + : true; + + $mapping = [ + 'fieldName' => (string) $embeddedMapping['name'], + 'class' => (string) $embeddedMapping['class'], + 'columnPrefix' => $useColumnPrefix ? $columnPrefix : false + ]; + + $metadata->mapEmbedded($mapping); + } + } + + foreach ($mappings as $mapping) { + if (isset($mapping['version'])) { + $metadata->setVersionMapping($mapping); + } + + $metadata->mapField($mapping); + } + + // Evaluate mappings + $associationIds = []; + foreach ($xmlRoot->id as $idElement) { + if (isset($idElement['association-key']) && $this->evaluateBoolean($idElement['association-key'])) { + $associationIds[(string) $idElement['name']] = true; + continue; + } + + $mapping = [ + 'id' => true, + 'fieldName' => (string) $idElement['name'] + ]; + + if (isset($idElement['type'])) { + $mapping['type'] = (string) $idElement['type']; + } + + if (isset($idElement['length'])) { + $mapping['length'] = (string) $idElement['length']; + } + + if (isset($idElement['column'])) { + $mapping['columnName'] = (string) $idElement['column']; + } + + if (isset($idElement['column-definition'])) { + $mapping['columnDefinition'] = (string) $idElement['column-definition']; + } + + if (isset($idElement->options)) { + $mapping['options'] = $this->_parseOptions($idElement->options->children()); + } + + $metadata->mapField($mapping); + + if (isset($idElement->generator)) { + $strategy = isset($idElement->generator['strategy']) ? + (string) $idElement->generator['strategy'] : 'AUTO'; + $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' + . $strategy)); + } + + // Check for SequenceGenerator/TableGenerator definition + if (isset($idElement->{'sequence-generator'})) { + $seqGenerator = $idElement->{'sequence-generator'}; + $metadata->setSequenceGeneratorDefinition( + [ + 'sequenceName' => (string) $seqGenerator['sequence-name'], + 'allocationSize' => (string) $seqGenerator['allocation-size'], + 'initialValue' => (string) $seqGenerator['initial-value'] + ] + ); + } else if (isset($idElement->{'custom-id-generator'})) { + $customGenerator = $idElement->{'custom-id-generator'}; + $metadata->setCustomGeneratorDefinition( + [ + 'class' => (string) $customGenerator['class'] + ] + ); + } else if (isset($idElement->{'table-generator'})) { + throw MappingException::tableIdGeneratorNotImplemented($className); + } + } + + // Evaluate mappings + if (isset($xmlRoot->{'one-to-one'})) { + foreach ($xmlRoot->{'one-to-one'} as $oneToOneElement) { + $mapping = [ + 'fieldName' => (string) $oneToOneElement['field'], + 'targetEntity' => (string) $oneToOneElement['target-entity'] + ]; + + if (isset($associationIds[$mapping['fieldName']])) { + $mapping['id'] = true; + } + + if (isset($oneToOneElement['fetch'])) { + $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string) $oneToOneElement['fetch']); + } + + if (isset($oneToOneElement['mapped-by'])) { + $mapping['mappedBy'] = (string) $oneToOneElement['mapped-by']; + } else { + if (isset($oneToOneElement['inversed-by'])) { + $mapping['inversedBy'] = (string) $oneToOneElement['inversed-by']; + } + $joinColumns = []; + + if (isset($oneToOneElement->{'join-column'})) { + $joinColumns[] = $this->joinColumnToArray($oneToOneElement->{'join-column'}); + } else if (isset($oneToOneElement->{'join-columns'})) { + foreach ($oneToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { + $joinColumns[] = $this->joinColumnToArray($joinColumnElement); + } + } + + $mapping['joinColumns'] = $joinColumns; + } + + if (isset($oneToOneElement->cascade)) { + $mapping['cascade'] = $this->_getCascadeMappings($oneToOneElement->cascade); + } + + if (isset($oneToOneElement['orphan-removal'])) { + $mapping['orphanRemoval'] = $this->evaluateBoolean($oneToOneElement['orphan-removal']); + } + + // Evaluate second level cache + if (isset($oneToOneElement->cache)) { + $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToOneElement->cache)); + } + + $metadata->mapOneToOne($mapping); + } + } + + // Evaluate mappings + if (isset($xmlRoot->{'one-to-many'})) { + foreach ($xmlRoot->{'one-to-many'} as $oneToManyElement) { + $mapping = [ + 'fieldName' => (string) $oneToManyElement['field'], + 'targetEntity' => (string) $oneToManyElement['target-entity'], + 'mappedBy' => (string) $oneToManyElement['mapped-by'] + ]; + + if (isset($oneToManyElement['fetch'])) { + $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string) $oneToManyElement['fetch']); + } + + if (isset($oneToManyElement->cascade)) { + $mapping['cascade'] = $this->_getCascadeMappings($oneToManyElement->cascade); + } + + if (isset($oneToManyElement['orphan-removal'])) { + $mapping['orphanRemoval'] = $this->evaluateBoolean($oneToManyElement['orphan-removal']); + } + + if (isset($oneToManyElement->{'order-by'})) { + $orderBy = []; + foreach ($oneToManyElement->{'order-by'}->{'order-by-field'} as $orderByField) { + $orderBy[(string) $orderByField['name']] = isset($orderByField['direction']) + ? (string) $orderByField['direction'] + : Criteria::ASC + ; + } + $mapping['orderBy'] = $orderBy; + } + + if (isset($oneToManyElement['index-by'])) { + $mapping['indexBy'] = (string) $oneToManyElement['index-by']; + } else if (isset($oneToManyElement->{'index-by'})) { + throw new \InvalidArgumentException(" is not a valid tag"); + } + + // Evaluate second level cache + if (isset($oneToManyElement->cache)) { + $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToManyElement->cache)); + } + + $metadata->mapOneToMany($mapping); + } + } + + // Evaluate mappings + if (isset($xmlRoot->{'many-to-one'})) { + foreach ($xmlRoot->{'many-to-one'} as $manyToOneElement) { + $mapping = [ + 'fieldName' => (string) $manyToOneElement['field'], + 'targetEntity' => (string) $manyToOneElement['target-entity'] + ]; + + if (isset($associationIds[$mapping['fieldName']])) { + $mapping['id'] = true; + } + + if (isset($manyToOneElement['fetch'])) { + $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string) $manyToOneElement['fetch']); + } + + if (isset($manyToOneElement['inversed-by'])) { + $mapping['inversedBy'] = (string) $manyToOneElement['inversed-by']; + } + + $joinColumns = []; + + if (isset($manyToOneElement->{'join-column'})) { + $joinColumns[] = $this->joinColumnToArray($manyToOneElement->{'join-column'}); + } else if (isset($manyToOneElement->{'join-columns'})) { + foreach ($manyToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { + $joinColumns[] = $this->joinColumnToArray($joinColumnElement); + } + } + + $mapping['joinColumns'] = $joinColumns; + + if (isset($manyToOneElement->cascade)) { + $mapping['cascade'] = $this->_getCascadeMappings($manyToOneElement->cascade); + } + + // Evaluate second level cache + if (isset($manyToOneElement->cache)) { + $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToOneElement->cache)); + } + + $metadata->mapManyToOne($mapping); + + } + } + + // Evaluate mappings + if (isset($xmlRoot->{'many-to-many'})) { + foreach ($xmlRoot->{'many-to-many'} as $manyToManyElement) { + $mapping = [ + 'fieldName' => (string) $manyToManyElement['field'], + 'targetEntity' => (string) $manyToManyElement['target-entity'] + ]; + + if (isset($manyToManyElement['fetch'])) { + $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string) $manyToManyElement['fetch']); + } + + if (isset($manyToManyElement['orphan-removal'])) { + $mapping['orphanRemoval'] = $this->evaluateBoolean($manyToManyElement['orphan-removal']); + } + + if (isset($manyToManyElement['mapped-by'])) { + $mapping['mappedBy'] = (string) $manyToManyElement['mapped-by']; + } else if (isset($manyToManyElement->{'join-table'})) { + if (isset($manyToManyElement['inversed-by'])) { + $mapping['inversedBy'] = (string) $manyToManyElement['inversed-by']; + } + + $joinTableElement = $manyToManyElement->{'join-table'}; + $joinTable = [ + 'name' => (string) $joinTableElement['name'] + ]; + + if (isset($joinTableElement['schema'])) { + $joinTable['schema'] = (string) $joinTableElement['schema']; + } + + foreach ($joinTableElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { + $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); + } + + foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} as $joinColumnElement) { + $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); + } + + $mapping['joinTable'] = $joinTable; + } + + if (isset($manyToManyElement->cascade)) { + $mapping['cascade'] = $this->_getCascadeMappings($manyToManyElement->cascade); + } + + if (isset($manyToManyElement->{'order-by'})) { + $orderBy = []; + foreach ($manyToManyElement->{'order-by'}->{'order-by-field'} as $orderByField) { + $orderBy[(string) $orderByField['name']] = isset($orderByField['direction']) + ? (string) $orderByField['direction'] + : Criteria::ASC; + } + $mapping['orderBy'] = $orderBy; + } + + if (isset($manyToManyElement['index-by'])) { + $mapping['indexBy'] = (string) $manyToManyElement['index-by']; + } else if (isset($manyToManyElement->{'index-by'})) { + throw new \InvalidArgumentException(" is not a valid tag"); + } + + // Evaluate second level cache + if (isset($manyToManyElement->cache)) { + $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToManyElement->cache)); + } + + $metadata->mapManyToMany($mapping); + } + } + + // Evaluate association-overrides + if (isset($xmlRoot->{'attribute-overrides'})) { + foreach ($xmlRoot->{'attribute-overrides'}->{'attribute-override'} as $overrideElement) { + $fieldName = (string) $overrideElement['name']; + foreach ($overrideElement->field as $field) { + $mapping = $this->columnToArray($field); + $mapping['fieldName'] = $fieldName; + $metadata->setAttributeOverride($fieldName, $mapping); + } + } + } + + // Evaluate association-overrides + if (isset($xmlRoot->{'association-overrides'})) { + foreach ($xmlRoot->{'association-overrides'}->{'association-override'} as $overrideElement) { + $fieldName = (string) $overrideElement['name']; + $override = []; + + // Check for join-columns + if (isset($overrideElement->{'join-columns'})) { + $joinColumns = []; + foreach ($overrideElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { + $joinColumns[] = $this->joinColumnToArray($joinColumnElement); + } + $override['joinColumns'] = $joinColumns; + } + + // Check for join-table + if ($overrideElement->{'join-table'}) { + $joinTable = null; + $joinTableElement = $overrideElement->{'join-table'}; + + $joinTable = [ + 'name' => (string) $joinTableElement['name'], + 'schema' => (string) $joinTableElement['schema'] + ]; + + if (isset($joinTableElement->{'join-columns'})) { + foreach ($joinTableElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { + $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); + } + } + + if (isset($joinTableElement->{'inverse-join-columns'})) { + foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} as $joinColumnElement) { + $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); + } + } + + $override['joinTable'] = $joinTable; + } + + // Check for inversed-by + if (isset($overrideElement->{'inversed-by'})) { + $override['inversedBy'] = (string) $overrideElement->{'inversed-by'}['name']; + } + + // Check for `fetch` + if (isset($overrideElement['fetch'])) { + $override['fetch'] = constant(Metadata::class . '::FETCH_' . (string) $overrideElement['fetch']); + } + + $metadata->setAssociationOverride($fieldName, $override); + } + } + + // Evaluate + if (isset($xmlRoot->{'lifecycle-callbacks'})) { + foreach ($xmlRoot->{'lifecycle-callbacks'}->{'lifecycle-callback'} as $lifecycleCallback) { + $metadata->addLifecycleCallback((string) $lifecycleCallback['method'], constant('Doctrine\ORM\Events::' . (string) $lifecycleCallback['type'])); + } + } + + // Evaluate entity listener + if (isset($xmlRoot->{'entity-listeners'})) { + foreach ($xmlRoot->{'entity-listeners'}->{'entity-listener'} as $listenerElement) { + $className = (string) $listenerElement['class']; + // Evaluate the listener using naming convention. + if ($listenerElement->count() === 0) { + EntityListenerBuilder::bindEntityListener($metadata, $className); + + continue; + } + + foreach ($listenerElement as $callbackElement) { + $eventName = (string) $callbackElement['type']; + $methodName = (string) $callbackElement['method']; + + $metadata->addEntityListener($eventName, $className, $methodName); + } + } + } + } + + /** + * Parses (nested) option elements. + * + * @param SimpleXMLElement $options The XML element. + * + * @return array The options array. + */ + private function _parseOptions(SimpleXMLElement $options) + { + $array = []; + + /* @var $option SimpleXMLElement */ + foreach ($options as $option) { + if ($option->count()) { + $value = $this->_parseOptions($option->children()); + } else { + $value = (string) $option; + } + + $attributes = $option->attributes(); + + if (isset($attributes->name)) { + $nameAttribute = (string) $attributes->name; + $array[$nameAttribute] = in_array($nameAttribute, ['unsigned', 'fixed']) + ? $this->evaluateBoolean($value) + : $value; + } else { + $array[] = $value; + } + } + + return $array; + } + + /** + * Constructs a joinColumn mapping array based on the information + * found in the given SimpleXMLElement. + * + * @param SimpleXMLElement $joinColumnElement The XML element. + * + * @return array The mapping array. + */ + private function joinColumnToArray(SimpleXMLElement $joinColumnElement) + { + $joinColumn = [ + 'name' => (string) $joinColumnElement['name'], + 'referencedColumnName' => (string) $joinColumnElement['referenced-column-name'] + ]; + + if (isset($joinColumnElement['unique'])) { + $joinColumn['unique'] = $this->evaluateBoolean($joinColumnElement['unique']); + } + + if (isset($joinColumnElement['nullable'])) { + $joinColumn['nullable'] = $this->evaluateBoolean($joinColumnElement['nullable']); + } + + if (isset($joinColumnElement['on-delete'])) { + $joinColumn['onDelete'] = (string) $joinColumnElement['on-delete']; + } + + if (isset($joinColumnElement['column-definition'])) { + $joinColumn['columnDefinition'] = (string) $joinColumnElement['column-definition']; + } + + return $joinColumn; + } + + /** + * Parses the given field as array. + * + * @param SimpleXMLElement $fieldMapping + * + * @return array + */ + private function columnToArray(SimpleXMLElement $fieldMapping) + { + $mapping = [ + 'fieldName' => (string) $fieldMapping['name'], + ]; + + if (isset($fieldMapping['type'])) { + $mapping['type'] = (string) $fieldMapping['type']; + } + + if (isset($fieldMapping['column'])) { + $mapping['columnName'] = (string) $fieldMapping['column']; + } + + if (isset($fieldMapping['length'])) { + $mapping['length'] = (int) $fieldMapping['length']; + } + + if (isset($fieldMapping['precision'])) { + $mapping['precision'] = (int) $fieldMapping['precision']; + } + + if (isset($fieldMapping['scale'])) { + $mapping['scale'] = (int) $fieldMapping['scale']; + } + + if (isset($fieldMapping['unique'])) { + $mapping['unique'] = $this->evaluateBoolean($fieldMapping['unique']); + } + + if (isset($fieldMapping['nullable'])) { + $mapping['nullable'] = $this->evaluateBoolean($fieldMapping['nullable']); + } + + if (isset($fieldMapping['version']) && $fieldMapping['version']) { + $mapping['version'] = $this->evaluateBoolean($fieldMapping['version']); + } + + if (isset($fieldMapping['column-definition'])) { + $mapping['columnDefinition'] = (string) $fieldMapping['column-definition']; + } + + if (isset($fieldMapping->options)) { + $mapping['options'] = $this->_parseOptions($fieldMapping->options->children()); + } + + return $mapping; + } + + /** + * Parse / Normalize the cache configuration + * + * @param SimpleXMLElement $cacheMapping + * + * @return array + */ + private function cacheToArray(SimpleXMLElement $cacheMapping) + { + $region = isset($cacheMapping['region']) ? (string) $cacheMapping['region'] : null; + $usage = isset($cacheMapping['usage']) ? strtoupper($cacheMapping['usage']) : null; + + if ($usage && ! defined('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage)) { + throw new \InvalidArgumentException(sprintf('Invalid cache usage "%s"', $usage)); + } + + if ($usage) { + $usage = constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage); + } + + return [ + 'usage' => $usage, + 'region' => $region, + ]; + } + + /** + * Gathers a list of cascade options found in the given cascade element. + * + * @param SimpleXMLElement $cascadeElement The cascade element. + * + * @return array The list of cascade options. + */ + private function _getCascadeMappings(SimpleXMLElement $cascadeElement) + { + $cascades = []; + /* @var $action SimpleXmlElement */ + foreach ($cascadeElement->children() as $action) { + // According to the JPA specifications, XML uses "cascade-persist" + // instead of "persist". Here, both variations + // are supported because both YAML and Annotation use "persist" + // and we want to make sure that this driver doesn't need to know + // anything about the supported cascading actions + $cascades[] = str_replace('cascade-', '', $action->getName()); + } + + return $cascades; + } + + /** + * {@inheritDoc} + */ + protected function loadMappingFile($file) + { + $result = []; + // Note: we do not use `simplexml_load_file()` because of https://bugs.php.net/bug.php?id=62577 + $xmlElement = simplexml_load_string(file_get_contents($file)); + + if (isset($xmlElement->entity)) { + foreach ($xmlElement->entity as $entityElement) { + $entityName = (string) $entityElement['name']; + $result[$entityName] = $entityElement; + } + } else if (isset($xmlElement->{'mapped-superclass'})) { + foreach ($xmlElement->{'mapped-superclass'} as $mappedSuperClass) { + $className = (string) $mappedSuperClass['name']; + $result[$className] = $mappedSuperClass; + } + } else if (isset($xmlElement->embeddable)) { + foreach ($xmlElement->embeddable as $embeddableElement) { + $embeddableName = (string) $embeddableElement['name']; + $result[$embeddableName] = $embeddableElement; + } + } + + return $result; + } + + /** + * @param mixed $element + * + * @return bool + */ + protected function evaluateBoolean($element) + { + $flag = (string) $element; + + return ($flag == "true" || $flag == "1"); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php new file mode 100644 index 0000000..05339ec --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php @@ -0,0 +1,819 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Driver; + +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder; +use Doctrine\Common\Persistence\Mapping\Driver\FileDriver; +use Doctrine\ORM\Mapping\ClassMetadata as Metadata; +use Doctrine\ORM\Mapping\MappingException; +use Symfony\Component\Yaml\Yaml; +use function trigger_error; + +/** + * The YamlDriver reads the mapping metadata from yaml schema files. + * + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan H. Wage + * @author Roman Borschel + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class YamlDriver extends FileDriver +{ + const DEFAULT_FILE_EXTENSION = '.dcm.yml'; + + /** + * {@inheritDoc} + */ + public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION) + { + @trigger_error( + 'YAML mapping driver is deprecated and will be removed in Doctrine ORM 3.0, please migrate to annotation or XML driver.', + E_USER_DEPRECATED + ); + + parent::__construct($locator, $fileExtension); + } + + /** + * {@inheritDoc} + */ + public function loadMetadataForClass($className, ClassMetadata $metadata) + { + /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */ + $element = $this->getElement($className); + + if ($element['type'] == 'entity') { + if (isset($element['repositoryClass'])) { + $metadata->setCustomRepositoryClass($element['repositoryClass']); + } + if (isset($element['readOnly']) && $element['readOnly'] == true) { + $metadata->markReadOnly(); + } + } else if ($element['type'] == 'mappedSuperclass') { + $metadata->setCustomRepositoryClass( + $element['repositoryClass'] ?? null + ); + $metadata->isMappedSuperclass = true; + } else if ($element['type'] == 'embeddable') { + $metadata->isEmbeddedClass = true; + } else { + throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className); + } + + // Evaluate root level properties + $primaryTable = []; + + if (isset($element['table'])) { + $primaryTable['name'] = $element['table']; + } + + if (isset($element['schema'])) { + $primaryTable['schema'] = $element['schema']; + } + + // Evaluate second level cache + if (isset($element['cache'])) { + $metadata->enableCache($this->cacheToArray($element['cache'])); + } + + $metadata->setPrimaryTable($primaryTable); + + // Evaluate named queries + if (isset($element['namedQueries'])) { + foreach ($element['namedQueries'] as $name => $queryMapping) { + if (is_string($queryMapping)) { + $queryMapping = ['query' => $queryMapping]; + } + + if ( ! isset($queryMapping['name'])) { + $queryMapping['name'] = $name; + } + + $metadata->addNamedQuery($queryMapping); + } + } + + // Evaluate named native queries + if (isset($element['namedNativeQueries'])) { + foreach ($element['namedNativeQueries'] as $name => $mappingElement) { + if (!isset($mappingElement['name'])) { + $mappingElement['name'] = $name; + } + $metadata->addNamedNativeQuery( + [ + 'name' => $mappingElement['name'], + 'query' => $mappingElement['query'] ?? null, + 'resultClass' => $mappingElement['resultClass'] ?? null, + 'resultSetMapping' => $mappingElement['resultSetMapping'] ?? null, + ] + ); + } + } + + // Evaluate sql result set mappings + if (isset($element['sqlResultSetMappings'])) { + foreach ($element['sqlResultSetMappings'] as $name => $resultSetMapping) { + if (!isset($resultSetMapping['name'])) { + $resultSetMapping['name'] = $name; + } + + $entities = []; + $columns = []; + if (isset($resultSetMapping['entityResult'])) { + foreach ($resultSetMapping['entityResult'] as $entityResultElement) { + $entityResult = [ + 'fields' => [], + 'entityClass' => $entityResultElement['entityClass'] ?? null, + 'discriminatorColumn' => $entityResultElement['discriminatorColumn'] ?? null, + ]; + + if (isset($entityResultElement['fieldResult'])) { + foreach ($entityResultElement['fieldResult'] as $fieldResultElement) { + $entityResult['fields'][] = [ + 'name' => $fieldResultElement['name'] ?? null, + 'column' => $fieldResultElement['column'] ?? null, + ]; + } + } + + $entities[] = $entityResult; + } + } + + + if (isset($resultSetMapping['columnResult'])) { + foreach ($resultSetMapping['columnResult'] as $columnResultAnnot) { + $columns[] = [ + 'name' => $columnResultAnnot['name'] ?? null, + ]; + } + } + + $metadata->addSqlResultSetMapping( + [ + 'name' => $resultSetMapping['name'], + 'entities' => $entities, + 'columns' => $columns + ] + ); + } + } + + if (isset($element['inheritanceType'])) { + $metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . strtoupper($element['inheritanceType']))); + + if ($metadata->inheritanceType != Metadata::INHERITANCE_TYPE_NONE) { + // Evaluate discriminatorColumn + if (isset($element['discriminatorColumn'])) { + $discrColumn = $element['discriminatorColumn']; + $metadata->setDiscriminatorColumn( + [ + 'name' => isset($discrColumn['name']) ? (string) $discrColumn['name'] : null, + 'type' => isset($discrColumn['type']) ? (string) $discrColumn['type'] : 'string', + 'length' => isset($discrColumn['length']) ? (string) $discrColumn['length'] : 255, + 'columnDefinition' => isset($discrColumn['columnDefinition']) ? (string) $discrColumn['columnDefinition'] : null + ] + ); + } else { + $metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]); + } + + // Evaluate discriminatorMap + if (isset($element['discriminatorMap'])) { + $metadata->setDiscriminatorMap($element['discriminatorMap']); + } + } + } + + + // Evaluate changeTrackingPolicy + if (isset($element['changeTrackingPolicy'])) { + $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_' + . strtoupper($element['changeTrackingPolicy']))); + } + + // Evaluate indexes + if (isset($element['indexes'])) { + foreach ($element['indexes'] as $name => $indexYml) { + if ( ! isset($indexYml['name'])) { + $indexYml['name'] = $name; + } + + if (is_string($indexYml['columns'])) { + $index = ['columns' => array_map('trim', explode(',', $indexYml['columns']))]; + } else { + $index = ['columns' => $indexYml['columns']]; + } + + if (isset($indexYml['flags'])) { + if (is_string($indexYml['flags'])) { + $index['flags'] = array_map('trim', explode(',', $indexYml['flags'])); + } else { + $index['flags'] = $indexYml['flags']; + } + } + + if (isset($indexYml['options'])) { + $index['options'] = $indexYml['options']; + } + + $metadata->table['indexes'][$indexYml['name']] = $index; + } + } + + // Evaluate uniqueConstraints + if (isset($element['uniqueConstraints'])) { + foreach ($element['uniqueConstraints'] as $name => $uniqueYml) { + if ( ! isset($uniqueYml['name'])) { + $uniqueYml['name'] = $name; + } + + if (is_string($uniqueYml['columns'])) { + $unique = ['columns' => array_map('trim', explode(',', $uniqueYml['columns']))]; + } else { + $unique = ['columns' => $uniqueYml['columns']]; + } + + if (isset($uniqueYml['options'])) { + $unique['options'] = $uniqueYml['options']; + } + + $metadata->table['uniqueConstraints'][$uniqueYml['name']] = $unique; + } + } + + if (isset($element['options'])) { + $metadata->table['options'] = $element['options']; + } + + $associationIds = []; + if (isset($element['id'])) { + // Evaluate identifier settings + foreach ($element['id'] as $name => $idElement) { + if (isset($idElement['associationKey']) && $idElement['associationKey'] == true) { + $associationIds[$name] = true; + continue; + } + + $mapping = [ + 'id' => true, + 'fieldName' => $name + ]; + + if (isset($idElement['type'])) { + $mapping['type'] = $idElement['type']; + } + + if (isset($idElement['column'])) { + $mapping['columnName'] = $idElement['column']; + } + + if (isset($idElement['length'])) { + $mapping['length'] = $idElement['length']; + } + + if (isset($idElement['columnDefinition'])) { + $mapping['columnDefinition'] = $idElement['columnDefinition']; + } + + if (isset($idElement['options'])) { + $mapping['options'] = $idElement['options']; + } + + $metadata->mapField($mapping); + + if (isset($idElement['generator'])) { + $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' + . strtoupper($idElement['generator']['strategy']))); + } + // Check for SequenceGenerator/TableGenerator definition + if (isset($idElement['sequenceGenerator'])) { + $metadata->setSequenceGeneratorDefinition($idElement['sequenceGenerator']); + } else if (isset($idElement['customIdGenerator'])) { + $customGenerator = $idElement['customIdGenerator']; + $metadata->setCustomGeneratorDefinition( + [ + 'class' => (string) $customGenerator['class'] + ] + ); + } else if (isset($idElement['tableGenerator'])) { + throw MappingException::tableIdGeneratorNotImplemented($className); + } + } + } + + // Evaluate fields + if (isset($element['fields'])) { + foreach ($element['fields'] as $name => $fieldMapping) { + + $mapping = $this->columnToArray($name, $fieldMapping); + + if (isset($fieldMapping['id'])) { + $mapping['id'] = true; + if (isset($fieldMapping['generator']['strategy'])) { + $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' + . strtoupper($fieldMapping['generator']['strategy']))); + } + } + + if (isset($mapping['version'])) { + $metadata->setVersionMapping($mapping); + unset($mapping['version']); + } + + $metadata->mapField($mapping); + } + } + + if (isset($element['embedded'])) { + foreach ($element['embedded'] as $name => $embeddedMapping) { + $mapping = [ + 'fieldName' => $name, + 'class' => $embeddedMapping['class'], + 'columnPrefix' => $embeddedMapping['columnPrefix'] ?? null, + ]; + $metadata->mapEmbedded($mapping); + } + } + + // Evaluate oneToOne relationships + if (isset($element['oneToOne'])) { + foreach ($element['oneToOne'] as $name => $oneToOneElement) { + $mapping = [ + 'fieldName' => $name, + 'targetEntity' => $oneToOneElement['targetEntity'] + ]; + + if (isset($associationIds[$mapping['fieldName']])) { + $mapping['id'] = true; + } + + if (isset($oneToOneElement['fetch'])) { + $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToOneElement['fetch']); + } + + if (isset($oneToOneElement['mappedBy'])) { + $mapping['mappedBy'] = $oneToOneElement['mappedBy']; + } else { + if (isset($oneToOneElement['inversedBy'])) { + $mapping['inversedBy'] = $oneToOneElement['inversedBy']; + } + + $joinColumns = []; + + if (isset($oneToOneElement['joinColumn'])) { + $joinColumns[] = $this->joinColumnToArray($oneToOneElement['joinColumn']); + } else if (isset($oneToOneElement['joinColumns'])) { + foreach ($oneToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) { + if ( ! isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $joinColumnName; + } + + $joinColumns[] = $this->joinColumnToArray($joinColumnElement); + } + } + + $mapping['joinColumns'] = $joinColumns; + } + + if (isset($oneToOneElement['cascade'])) { + $mapping['cascade'] = $oneToOneElement['cascade']; + } + + if (isset($oneToOneElement['orphanRemoval'])) { + $mapping['orphanRemoval'] = (bool) $oneToOneElement['orphanRemoval']; + } + + // Evaluate second level cache + if (isset($oneToOneElement['cache'])) { + $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToOneElement['cache'])); + } + + $metadata->mapOneToOne($mapping); + } + } + + // Evaluate oneToMany relationships + if (isset($element['oneToMany'])) { + foreach ($element['oneToMany'] as $name => $oneToManyElement) { + $mapping = [ + 'fieldName' => $name, + 'targetEntity' => $oneToManyElement['targetEntity'], + 'mappedBy' => $oneToManyElement['mappedBy'] + ]; + + if (isset($oneToManyElement['fetch'])) { + $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToManyElement['fetch']); + } + + if (isset($oneToManyElement['cascade'])) { + $mapping['cascade'] = $oneToManyElement['cascade']; + } + + if (isset($oneToManyElement['orphanRemoval'])) { + $mapping['orphanRemoval'] = (bool) $oneToManyElement['orphanRemoval']; + } + + if (isset($oneToManyElement['orderBy'])) { + $mapping['orderBy'] = $oneToManyElement['orderBy']; + } + + if (isset($oneToManyElement['indexBy'])) { + $mapping['indexBy'] = $oneToManyElement['indexBy']; + } + + + // Evaluate second level cache + if (isset($oneToManyElement['cache'])) { + $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToManyElement['cache'])); + } + + $metadata->mapOneToMany($mapping); + } + } + + // Evaluate manyToOne relationships + if (isset($element['manyToOne'])) { + foreach ($element['manyToOne'] as $name => $manyToOneElement) { + $mapping = [ + 'fieldName' => $name, + 'targetEntity' => $manyToOneElement['targetEntity'] + ]; + + if (isset($associationIds[$mapping['fieldName']])) { + $mapping['id'] = true; + } + + if (isset($manyToOneElement['fetch'])) { + $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToOneElement['fetch']); + } + + if (isset($manyToOneElement['inversedBy'])) { + $mapping['inversedBy'] = $manyToOneElement['inversedBy']; + } + + $joinColumns = []; + + if (isset($manyToOneElement['joinColumn'])) { + $joinColumns[] = $this->joinColumnToArray($manyToOneElement['joinColumn']); + } else if (isset($manyToOneElement['joinColumns'])) { + foreach ($manyToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) { + if ( ! isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $joinColumnName; + } + + $joinColumns[] = $this->joinColumnToArray($joinColumnElement); + } + } + + $mapping['joinColumns'] = $joinColumns; + + if (isset($manyToOneElement['cascade'])) { + $mapping['cascade'] = $manyToOneElement['cascade']; + } + + // Evaluate second level cache + if (isset($manyToOneElement['cache'])) { + $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToOneElement['cache'])); + } + + $metadata->mapManyToOne($mapping); + } + } + + // Evaluate manyToMany relationships + if (isset($element['manyToMany'])) { + foreach ($element['manyToMany'] as $name => $manyToManyElement) { + $mapping = [ + 'fieldName' => $name, + 'targetEntity' => $manyToManyElement['targetEntity'] + ]; + + if (isset($manyToManyElement['fetch'])) { + $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToManyElement['fetch']); + } + + if (isset($manyToManyElement['mappedBy'])) { + $mapping['mappedBy'] = $manyToManyElement['mappedBy']; + } else if (isset($manyToManyElement['joinTable'])) { + + $joinTableElement = $manyToManyElement['joinTable']; + $joinTable = [ + 'name' => $joinTableElement['name'] + ]; + + if (isset($joinTableElement['schema'])) { + $joinTable['schema'] = $joinTableElement['schema']; + } + + if (isset($joinTableElement['joinColumns'])) { + foreach ($joinTableElement['joinColumns'] as $joinColumnName => $joinColumnElement) { + if ( ! isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $joinColumnName; + } + $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); + } + } + + if (isset($joinTableElement['inverseJoinColumns'])) { + foreach ($joinTableElement['inverseJoinColumns'] as $joinColumnName => $joinColumnElement) { + if ( ! isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $joinColumnName; + } + $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); + } + } + + $mapping['joinTable'] = $joinTable; + } + + if (isset($manyToManyElement['inversedBy'])) { + $mapping['inversedBy'] = $manyToManyElement['inversedBy']; + } + + if (isset($manyToManyElement['cascade'])) { + $mapping['cascade'] = $manyToManyElement['cascade']; + } + + if (isset($manyToManyElement['orderBy'])) { + $mapping['orderBy'] = $manyToManyElement['orderBy']; + } + + if (isset($manyToManyElement['indexBy'])) { + $mapping['indexBy'] = $manyToManyElement['indexBy']; + } + + if (isset($manyToManyElement['orphanRemoval'])) { + $mapping['orphanRemoval'] = (bool) $manyToManyElement['orphanRemoval']; + } + + // Evaluate second level cache + if (isset($manyToManyElement['cache'])) { + $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToManyElement['cache'])); + } + + $metadata->mapManyToMany($mapping); + } + } + + // Evaluate associationOverride + if (isset($element['associationOverride']) && is_array($element['associationOverride'])) { + + foreach ($element['associationOverride'] as $fieldName => $associationOverrideElement) { + $override = []; + + // Check for joinColumn + if (isset($associationOverrideElement['joinColumn'])) { + $joinColumns = []; + foreach ($associationOverrideElement['joinColumn'] as $name => $joinColumnElement) { + if ( ! isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $name; + } + $joinColumns[] = $this->joinColumnToArray($joinColumnElement); + } + $override['joinColumns'] = $joinColumns; + } + + // Check for joinTable + if (isset($associationOverrideElement['joinTable'])) { + + $joinTableElement = $associationOverrideElement['joinTable']; + $joinTable = [ + 'name' => $joinTableElement['name'] + ]; + + if (isset($joinTableElement['schema'])) { + $joinTable['schema'] = $joinTableElement['schema']; + } + + foreach ($joinTableElement['joinColumns'] as $name => $joinColumnElement) { + if ( ! isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $name; + } + + $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); + } + + foreach ($joinTableElement['inverseJoinColumns'] as $name => $joinColumnElement) { + if ( ! isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $name; + } + + $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); + } + + $override['joinTable'] = $joinTable; + } + + // Check for inversedBy + if (isset($associationOverrideElement['inversedBy'])) { + $override['inversedBy'] = (string) $associationOverrideElement['inversedBy']; + } + + // Check for `fetch` + if (isset($associationOverrideElement['fetch'])) { + $override['fetch'] = constant(Metadata::class . '::FETCH_' . $associationOverrideElement['fetch']); + } + + $metadata->setAssociationOverride($fieldName, $override); + } + } + + // Evaluate associationOverride + if (isset($element['attributeOverride']) && is_array($element['attributeOverride'])) { + + foreach ($element['attributeOverride'] as $fieldName => $attributeOverrideElement) { + $mapping = $this->columnToArray($fieldName, $attributeOverrideElement); + $metadata->setAttributeOverride($fieldName, $mapping); + } + } + + // Evaluate lifeCycleCallbacks + if (isset($element['lifecycleCallbacks'])) { + foreach ($element['lifecycleCallbacks'] as $type => $methods) { + foreach ($methods as $method) { + $metadata->addLifecycleCallback($method, constant('Doctrine\ORM\Events::' . $type)); + } + } + } + + // Evaluate entityListeners + if (isset($element['entityListeners'])) { + foreach ($element['entityListeners'] as $className => $entityListener) { + // Evaluate the listener using naming convention. + if (empty($entityListener)) { + EntityListenerBuilder::bindEntityListener($metadata, $className); + + continue; + } + + foreach ($entityListener as $eventName => $callbackElement) { + foreach ($callbackElement as $methodName) { + $metadata->addEntityListener($eventName, $className, $methodName); + } + } + } + } + } + + /** + * Constructs a joinColumn mapping array based on the information + * found in the given join column element. + * + * @param array $joinColumnElement The array join column element. + * + * @return array The mapping array. + */ + private function joinColumnToArray($joinColumnElement) + { + $joinColumn = []; + if (isset($joinColumnElement['referencedColumnName'])) { + $joinColumn['referencedColumnName'] = (string) $joinColumnElement['referencedColumnName']; + } + + if (isset($joinColumnElement['name'])) { + $joinColumn['name'] = (string) $joinColumnElement['name']; + } + + if (isset($joinColumnElement['fieldName'])) { + $joinColumn['fieldName'] = (string) $joinColumnElement['fieldName']; + } + + if (isset($joinColumnElement['unique'])) { + $joinColumn['unique'] = (bool) $joinColumnElement['unique']; + } + + if (isset($joinColumnElement['nullable'])) { + $joinColumn['nullable'] = (bool) $joinColumnElement['nullable']; + } + + if (isset($joinColumnElement['onDelete'])) { + $joinColumn['onDelete'] = $joinColumnElement['onDelete']; + } + + if (isset($joinColumnElement['columnDefinition'])) { + $joinColumn['columnDefinition'] = $joinColumnElement['columnDefinition']; + } + + return $joinColumn; + } + + /** + * Parses the given column as array. + * + * @param string $fieldName + * @param array $column + * + * @return array + */ + private function columnToArray($fieldName, $column) + { + $mapping = [ + 'fieldName' => $fieldName + ]; + + if (isset($column['type'])) { + $params = explode('(', $column['type']); + + $column['type'] = $params[0]; + $mapping['type'] = $column['type']; + + if (isset($params[1])) { + $column['length'] = (integer) substr($params[1], 0, strlen($params[1]) - 1); + } + } + + if (isset($column['column'])) { + $mapping['columnName'] = $column['column']; + } + + if (isset($column['length'])) { + $mapping['length'] = $column['length']; + } + + if (isset($column['precision'])) { + $mapping['precision'] = $column['precision']; + } + + if (isset($column['scale'])) { + $mapping['scale'] = $column['scale']; + } + + if (isset($column['unique'])) { + $mapping['unique'] = (bool) $column['unique']; + } + + if (isset($column['options'])) { + $mapping['options'] = $column['options']; + } + + if (isset($column['nullable'])) { + $mapping['nullable'] = $column['nullable']; + } + + if (isset($column['version']) && $column['version']) { + $mapping['version'] = $column['version']; + } + + if (isset($column['columnDefinition'])) { + $mapping['columnDefinition'] = $column['columnDefinition']; + } + + return $mapping; + } + + /** + * Parse / Normalize the cache configuration + * + * @param array $cacheMapping + * + * @return array + */ + private function cacheToArray($cacheMapping) + { + $region = isset($cacheMapping['region']) ? (string) $cacheMapping['region'] : null; + $usage = isset($cacheMapping['usage']) ? strtoupper($cacheMapping['usage']) : null; + + if ($usage && ! defined('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage)) { + throw new \InvalidArgumentException(sprintf('Invalid cache usage "%s"', $usage)); + } + + if ($usage) { + $usage = constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage); + } + + return [ + 'usage' => $usage, + 'region' => $region, + ]; + } + + /** + * {@inheritDoc} + */ + protected function loadMappingFile($file) + { + return Yaml::parse(file_get_contents($file)); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embeddable.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embeddable.php new file mode 100644 index 0000000..f14bfac --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embeddable.php @@ -0,0 +1,28 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("CLASS") + */ +final class Embeddable implements Annotation +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embedded.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embedded.php new file mode 100644 index 0000000..3733910 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embedded.php @@ -0,0 +1,38 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("PROPERTY") + */ +final class Embedded implements Annotation +{ + /** + * @Required + * @var string + */ + public $class; + + /** + * @var mixed + */ + public $columnPrefix; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Entity.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Entity.php new file mode 100644 index 0000000..edf6ad5 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Entity.php @@ -0,0 +1,37 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("CLASS") + */ +final class Entity implements Annotation +{ + /** + * @var string + */ + public $repositoryClass; + + /** + * @var boolean + */ + public $readOnly = false; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListenerResolver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListenerResolver.php new file mode 100644 index 0000000..b0c62c8 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListenerResolver.php @@ -0,0 +1,55 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * A resolver is used to instantiate an entity listener. + * + * @since 2.4 + * @author Fabio B. Silva + */ +interface EntityListenerResolver +{ + /** + * Clear all instances from the set, or a specific class when given. + * + * @param string $className The fully-qualified class name + * + * @return void + */ + function clear($className = null); + + /** + * Returns a entity listener instance for the given class name. + * + * @param string $className The fully-qualified class name + * + * @return object An entity listener + */ + function resolve($className); + + /** + * Register a entity listener instance. + * + * @param object $object An entity listener + */ + function register($object); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListeners.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListeners.php new file mode 100644 index 0000000..ae6c912 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListeners.php @@ -0,0 +1,41 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * The EntityListeners annotation specifies the callback listener classes to be used for an entity or mapped superclass. + * The EntityListeners annotation may be applied to an entity class or mapped superclass. + * + * @author Fabio B. Silva + * @since 2.4 + * + * @Annotation + * @Target("CLASS") + */ +final class EntityListeners implements Annotation +{ + /** + * Specifies the names of the entity listeners. + * + * @var array + */ + public $value = []; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityResult.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityResult.php new file mode 100644 index 0000000..d8b0573 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityResult.php @@ -0,0 +1,56 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * References an entity in the SELECT clause of a SQL query. + * If this annotation is used, the SQL statement should select all of the columns that are mapped to the entity object. + * This should include foreign key columns to related entities. + * The results obtained when insufficient data is available are undefined. + * + * @author Fabio B. Silva + * @since 2.3 + * + * @Annotation + * @Target("ANNOTATION") + */ +final class EntityResult implements Annotation +{ + /** + * The class of the result. + * + * @var string + */ + public $entityClass; + + /** + * Maps the columns specified in the SELECT list of the query to the properties or fields of the entity class. + * + * @var array<\Doctrine\ORM\Mapping\FieldResult> + */ + public $fields = []; + + /** + * Specifies the column name of the column in the SELECT list that is used to determine the type of the entity instance. + * + * @var string + */ + public $discriminatorColumn; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/FieldResult.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/FieldResult.php new file mode 100644 index 0000000..5e8aa0c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/FieldResult.php @@ -0,0 +1,46 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * Is used to map the columns specified in the SELECT list of the query to the properties or fields of the entity class. + * + * @author Fabio B. Silva + * @since 2.3 + * + * @Annotation + * @Target("ANNOTATION") + */ +final class FieldResult implements Annotation +{ + /** + * Name of the column in the SELECT clause. + * + * @var string + */ + public $name; + + /** + * Name of the persistent field or property of the class. + * + * @var string + */ + public $column; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/GeneratedValue.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/GeneratedValue.php new file mode 100644 index 0000000..27c03d4 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/GeneratedValue.php @@ -0,0 +1,36 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("PROPERTY") + */ +final class GeneratedValue implements Annotation +{ + /** + * The type of Id generator. + * + * @var string + * + * @Enum({"AUTO", "SEQUENCE", "TABLE", "IDENTITY", "NONE", "UUID", "CUSTOM"}) + */ + public $strategy = 'AUTO'; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/HasLifecycleCallbacks.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/HasLifecycleCallbacks.php new file mode 100644 index 0000000..313ece3 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/HasLifecycleCallbacks.php @@ -0,0 +1,28 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("CLASS") + */ +final class HasLifecycleCallbacks implements Annotation +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Id.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Id.php new file mode 100644 index 0000000..6c9bcef --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Id.php @@ -0,0 +1,28 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("PROPERTY") + */ +final class Id implements Annotation +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Index.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Index.php new file mode 100644 index 0000000..45953a8 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Index.php @@ -0,0 +1,47 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("ANNOTATION") + */ +final class Index implements Annotation +{ + /** + * @var string + */ + public $name; + + /** + * @var array + */ + public $columns; + + /** + * @var array + */ + public $flags; + + /** + * @var array + */ + public $options; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/InheritanceType.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/InheritanceType.php new file mode 100644 index 0000000..de80336 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/InheritanceType.php @@ -0,0 +1,36 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("CLASS") + */ +final class InheritanceType implements Annotation +{ + /** + * The inheritance type used by the class and its subclasses. + * + * @var string + * + * @Enum({"NONE", "JOINED", "SINGLE_TABLE", "TABLE_PER_CLASS"}) + */ + public $value; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumn.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumn.php new file mode 100644 index 0000000..febce91 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumn.php @@ -0,0 +1,64 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target({"PROPERTY","ANNOTATION"}) + */ +final class JoinColumn implements Annotation +{ + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $referencedColumnName = 'id'; + + /** + * @var boolean + */ + public $unique = false; + + /** + * @var boolean + */ + public $nullable = true; + + /** + * @var mixed + */ + public $onDelete; + + /** + * @var string + */ + public $columnDefinition; + + /** + * Field name used in non-object hydration (array/scalar). + * + * @var string + */ + public $fieldName; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumns.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumns.php new file mode 100644 index 0000000..ae096c2 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumns.php @@ -0,0 +1,32 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("PROPERTY") + */ +final class JoinColumns implements Annotation +{ + /** + * @var array<\Doctrine\ORM\Mapping\JoinColumn> + */ + public $value; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinTable.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinTable.php new file mode 100644 index 0000000..879316a --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinTable.php @@ -0,0 +1,47 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target({"PROPERTY","ANNOTATION"}) + */ +final class JoinTable implements Annotation +{ + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $schema; + + /** + * @var array<\Doctrine\ORM\Mapping\JoinColumn> + */ + public $joinColumns = []; + + /** + * @var array<\Doctrine\ORM\Mapping\JoinColumn> + */ + public $inverseJoinColumns = []; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToMany.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToMany.php new file mode 100644 index 0000000..ca2f53c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToMany.php @@ -0,0 +1,66 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("PROPERTY") + */ +final class ManyToMany implements Annotation +{ + /** + * @var string + */ + public $targetEntity; + + /** + * @var string + */ + public $mappedBy; + + /** + * @var string + */ + public $inversedBy; + + /** + * @var array + */ + public $cascade; + + /** + * The fetching strategy to use for the association. + * + * @var string + * + * @Enum({"LAZY", "EAGER", "EXTRA_LAZY"}) + */ + public $fetch = 'LAZY'; + + /** + * @var boolean + */ + public $orphanRemoval = false; + + /** + * @var string + */ + public $indexBy; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToOne.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToOne.php new file mode 100644 index 0000000..d3414e6 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToOne.php @@ -0,0 +1,51 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("PROPERTY") + */ +final class ManyToOne implements Annotation +{ + /** + * @var string + */ + public $targetEntity; + + /** + * @var array + */ + public $cascade; + + /** + * The fetching strategy to use for the association. + * + * @var string + * + * @Enum({"LAZY", "EAGER", "EXTRA_LAZY"}) + */ + public $fetch = 'LAZY'; + + /** + * @var string + */ + public $inversedBy; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappedSuperclass.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappedSuperclass.php new file mode 100644 index 0000000..7458810 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappedSuperclass.php @@ -0,0 +1,32 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("CLASS") + */ +final class MappedSuperclass implements Annotation +{ + /** + * @var string + */ + public $repositoryClass; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappingException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappingException.php new file mode 100644 index 0000000..7dc4405 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappingException.php @@ -0,0 +1,823 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * A MappingException indicates that something is wrong with the mapping setup. + * + * @since 2.0 + */ +class MappingException extends \Doctrine\ORM\ORMException +{ + /** + * @return MappingException + */ + public static function pathRequired() + { + return new self("Specifying the paths to your entities is required ". + "in the AnnotationDriver to retrieve all class names."); + } + + /** + * @param string $entityName + * + * @return MappingException + */ + public static function identifierRequired($entityName) + { + if (false !== ($parent = get_parent_class($entityName))) { + return new self(sprintf( + 'No identifier/primary key specified for Entity "%s" sub class of "%s". Every Entity must have an identifier/primary key.', + $entityName, $parent + )); + } + + return new self(sprintf( + 'No identifier/primary key specified for Entity "%s". Every Entity must have an identifier/primary key.', + $entityName + )); + + } + + /** + * @param string $entityName + * @param string $type + * + * @return MappingException + */ + public static function invalidInheritanceType($entityName, $type) + { + return new self("The inheritance type '$type' specified for '$entityName' does not exist."); + } + + /** + * @return MappingException + */ + public static function generatorNotAllowedWithCompositeId() + { + return new self("Id generators can't be used with a composite id."); + } + + /** + * @param string $entity + * + * @return MappingException + */ + public static function missingFieldName($entity) + { + return new self("The field or association mapping misses the 'fieldName' attribute in entity '$entity'."); + } + + /** + * @param string $fieldName + * + * @return MappingException + */ + public static function missingTargetEntity($fieldName) + { + return new self("The association mapping '$fieldName' misses the 'targetEntity' attribute."); + } + + /** + * @param string $fieldName + * + * @return MappingException + */ + public static function missingSourceEntity($fieldName) + { + return new self("The association mapping '$fieldName' misses the 'sourceEntity' attribute."); + } + + /** + * @param string $fieldName + * + * @return MappingException + */ + public static function missingEmbeddedClass($fieldName) + { + return new self("The embed mapping '$fieldName' misses the 'class' attribute."); + } + + /** + * @param string $entityName + * @param string $fileName + * + * @return MappingException + */ + public static function mappingFileNotFound($entityName, $fileName) + { + return new self("No mapping file found named '$fileName' for class '$entityName'."); + } + + /** + * Exception for invalid property name override. + * + * @param string $className The entity's name. + * @param string $fieldName + * + * @return MappingException + */ + public static function invalidOverrideFieldName($className, $fieldName) + { + return new self("Invalid field override named '$fieldName' for class '$className'."); + } + + /** + * Exception for invalid property type override. + * + * @param string $className The entity's name. + * @param string $fieldName + * + * @return MappingException + */ + public static function invalidOverrideFieldType($className, $fieldName) + { + return new self("The column type of attribute '$fieldName' on class '$className' could not be changed."); + } + + /** + * @param string $className + * @param string $fieldName + * + * @return MappingException + */ + public static function mappingNotFound($className, $fieldName) + { + return new self("No mapping found for field '$fieldName' on class '$className'."); + } + + /** + * @param string $className + * @param string $queryName + * + * @return MappingException + */ + public static function queryNotFound($className, $queryName) + { + return new self("No query found named '$queryName' on class '$className'."); + } + + /** + * @param string $className + * @param string $resultName + * + * @return MappingException + */ + public static function resultMappingNotFound($className, $resultName) + { + return new self("No result set mapping found named '$resultName' on class '$className'."); + } + + /** + * @param string $entity + * @param string $queryName + * + * @return MappingException + */ + public static function emptyQueryMapping($entity, $queryName) + { + return new self('Query named "'.$queryName.'" in "'.$entity.'" could not be empty.'); + } + + /** + * @param string $className + * + * @return MappingException + */ + public static function nameIsMandatoryForQueryMapping($className) + { + return new self("Query name on entity class '$className' is not defined."); + } + + /** + * @param string $entity + * @param string $queryName + * + * @return MappingException + */ + public static function missingQueryMapping($entity, $queryName) + { + return new self('Query named "'.$queryName.'" in "'.$entity.' requires a result class or result set mapping.'); + } + + /** + * @param string $entity + * @param string $resultName + * + * @return MappingException + */ + public static function missingResultSetMappingEntity($entity, $resultName) + { + return new self('Result set mapping named "'.$resultName.'" in "'.$entity.' requires a entity class name.'); + } + + /** + * @param string $entity + * @param string $resultName + * + * @return MappingException + */ + public static function missingResultSetMappingFieldName($entity, $resultName) + { + return new self('Result set mapping named "'.$resultName.'" in "'.$entity.' requires a field name.'); + } + + /** + * @param string $className + * + * @return MappingException + */ + public static function nameIsMandatoryForSqlResultSetMapping($className) + { + return new self("Result set mapping name on entity class '$className' is not defined."); + } + + /** + * @param string $fieldName + * + * @return MappingException + */ + public static function oneToManyRequiresMappedBy($fieldName) + { + return new self("OneToMany mapping on field '$fieldName' requires the 'mappedBy' attribute."); + } + + /** + * @param string $fieldName + * + * @return MappingException + */ + public static function joinTableRequired($fieldName) + { + return new self("The mapping of field '$fieldName' requires an the 'joinTable' attribute."); + } + + /** + * Called if a required option was not found but is required + * + * @param string $field Which field cannot be processed? + * @param string $expectedOption Which option is required + * @param string $hint Can optionally be used to supply a tip for common mistakes, + * e.g. "Did you think of the plural s?" + * + * @return MappingException + */ + static function missingRequiredOption($field, $expectedOption, $hint = '') + { + $message = "The mapping of field '{$field}' is invalid: The option '{$expectedOption}' is required."; + + if ( ! empty($hint)) { + $message .= ' (Hint: ' . $hint . ')'; + } + + return new self($message); + } + + /** + * Generic exception for invalid mappings. + * + * @param string $fieldName + * + * @return MappingException + */ + public static function invalidMapping($fieldName) + { + return new self("The mapping of field '$fieldName' is invalid."); + } + + /** + * Exception for reflection exceptions - adds the entity name, + * because there might be long classnames that will be shortened + * within the stacktrace + * + * @param string $entity The entity's name + * @param \ReflectionException $previousException + * + * @return MappingException + */ + public static function reflectionFailure($entity, \ReflectionException $previousException) + { + return new self('An error occurred in ' . $entity, 0, $previousException); + } + + /** + * @param string $className + * @param string $joinColumn + * + * @return MappingException + */ + public static function joinColumnMustPointToMappedField($className, $joinColumn) + { + return new self('The column ' . $joinColumn . ' must be mapped to a field in class ' + . $className . ' since it is referenced by a join column of another class.'); + } + + /** + * @param string $className + * + * @return MappingException + */ + public static function classIsNotAValidEntityOrMappedSuperClass($className) + { + if (false !== ($parent = get_parent_class($className))) { + return new self(sprintf( + 'Class "%s" sub class of "%s" is not a valid entity or mapped super class.', + $className, $parent + )); + } + + return new self(sprintf( + 'Class "%s" is not a valid entity or mapped super class.', + $className + )); + } + + /** + * @param string $className + * @param string $propertyName + * + * @return MappingException + */ + public static function propertyTypeIsRequired($className, $propertyName) + { + return new self("The attribute 'type' is required for the column description of property ".$className."::\$".$propertyName."."); + } + + /** + * @param string $className + * + * @return MappingException + */ + public static function tableIdGeneratorNotImplemented($className) + { + return new self("TableIdGenerator is not yet implemented for use with class ".$className); + } + + /** + * @param string $entity The entity's name. + * @param string $fieldName The name of the field that was already declared. + * + * @return MappingException + */ + public static function duplicateFieldMapping($entity, $fieldName) + { + return new self('Property "'.$fieldName.'" in "'.$entity.'" was already declared, but it must be declared only once'); + } + + /** + * @param string $entity + * @param string $fieldName + * + * @return MappingException + */ + public static function duplicateAssociationMapping($entity, $fieldName) + { + return new self('Property "'.$fieldName.'" in "'.$entity.'" was already declared, but it must be declared only once'); + } + + /** + * @param string $entity + * @param string $queryName + * + * @return MappingException + */ + public static function duplicateQueryMapping($entity, $queryName) + { + return new self('Query named "'.$queryName.'" in "'.$entity.'" was already declared, but it must be declared only once'); + } + + /** + * @param string $entity + * @param string $resultName + * + * @return MappingException + */ + public static function duplicateResultSetMapping($entity, $resultName) + { + return new self('Result set mapping named "'.$resultName.'" in "'.$entity.'" was already declared, but it must be declared only once'); + } + + /** + * @param string $entity + * + * @return MappingException + */ + public static function singleIdNotAllowedOnCompositePrimaryKey($entity) + { + return new self('Single id is not allowed on composite primary key in entity '.$entity); + } + + /** + * @param string $entity + * + * @return MappingException + */ + public static function noIdDefined($entity) + { + return new self('No ID defined for entity ' . $entity); + } + + /** + * @param string $entity + * @param string $fieldName + * @param string $unsupportedType + * + * @return MappingException + */ + public static function unsupportedOptimisticLockingType($entity, $fieldName, $unsupportedType) + { + return new self('Locking type "'.$unsupportedType.'" (specified in "'.$entity.'", field "'.$fieldName.'") ' + .'is not supported by Doctrine.' + ); + } + + /** + * @param string|null $path + * + * @return MappingException + */ + public static function fileMappingDriversRequireConfiguredDirectoryPath($path = null) + { + if ( ! empty($path)) { + $path = '[' . $path . ']'; + } + + return new self( + 'File mapping drivers must have a valid directory path, ' . + 'however the given path ' . $path . ' seems to be incorrect!' + ); + } + + /** + * Returns an exception that indicates that a class used in a discriminator map does not exist. + * An example would be an outdated (maybe renamed) classname. + * + * @param string $className The class that could not be found + * @param string $owningClass The class that declares the discriminator map. + * + * @return MappingException + */ + public static function invalidClassInDiscriminatorMap($className, $owningClass) + { + return new self( + "Entity class '$className' used in the discriminator map of class '$owningClass' ". + "does not exist." + ); + } + + /** + * @param string $className + * @param array $entries + * @param array $map + * + * @return MappingException + */ + public static function duplicateDiscriminatorEntry($className, array $entries, array $map) + { + return new self( + "The entries " . implode(', ', $entries) . " in discriminator map of class '" . $className . "' is duplicated. " . + "If the discriminator map is automatically generated you have to convert it to an explicit discriminator map now. " . + "The entries of the current map are: @DiscriminatorMap({" . implode(', ', array_map( + function($a, $b) { return "'$a': '$b'"; }, array_keys($map), array_values($map) + )) . "})" + ); + } + + /** + * @param string $className + * + * @return MappingException + */ + public static function missingDiscriminatorMap($className) + { + return new self("Entity class '$className' is using inheritance but no discriminator map was defined."); + } + + /** + * @param string $className + * + * @return MappingException + */ + public static function missingDiscriminatorColumn($className) + { + return new self("Entity class '$className' is using inheritance but no discriminator column was defined."); + } + + /** + * @param string $className + * @param string $type + * + * @return MappingException + */ + public static function invalidDiscriminatorColumnType($className, $type) + { + return new self("Discriminator column type on entity class '$className' is not allowed to be '$type'. 'string' or 'integer' type variables are suggested!"); + } + + /** + * @param string $className + * + * @return MappingException + */ + public static function nameIsMandatoryForDiscriminatorColumns($className) + { + return new self("Discriminator column name on entity class '$className' is not defined."); + } + + /** + * @param string $className + * @param string $fieldName + * + * @return MappingException + */ + public static function cannotVersionIdField($className, $fieldName) + { + return new self("Setting Id field '$fieldName' as versionable in entity class '$className' is not supported."); + } + + /** + * @param string $className + * @param string $fieldName + * @param string $type + * + * @return MappingException + */ + public static function sqlConversionNotAllowedForIdentifiers($className, $fieldName, $type) + { + return new self("It is not possible to set id field '$fieldName' to type '$type' in entity class '$className'. The type '$type' requires conversion SQL which is not allowed for identifiers."); + } + + /** + * @param string $className + * @param string $columnName + * + * @return MappingException + */ + public static function duplicateColumnName($className, $columnName) + { + return new self("Duplicate definition of column '".$columnName."' on entity '".$className."' in a field or discriminator column mapping."); + } + + /** + * @param string $className + * @param string $field + * + * @return MappingException + */ + public static function illegalToManyAssociationOnMappedSuperclass($className, $field) + { + return new self("It is illegal to put an inverse side one-to-many or many-to-many association on mapped superclass '".$className."#".$field."'."); + } + + /** + * @param string $className + * @param string $targetEntity + * @param string $targetField + * + * @return MappingException + */ + public static function cannotMapCompositePrimaryKeyEntitiesAsForeignId($className, $targetEntity, $targetField) + { + return new self("It is not possible to map entity '".$className."' with a composite primary key ". + "as part of the primary key of another entity '".$targetEntity."#".$targetField."'."); + } + + /** + * @param string $className + * @param string $field + * + * @return MappingException + */ + public static function noSingleAssociationJoinColumnFound($className, $field) + { + return new self("'$className#$field' is not an association with a single join column."); + } + + /** + * @param string $className + * @param string $column + * + * @return MappingException + */ + public static function noFieldNameFoundForColumn($className, $column) + { + return new self("Cannot find a field on '$className' that is mapped to column '$column'. Either the ". + "field does not exist or an association exists but it has multiple join columns."); + } + + /** + * @param string $className + * @param string $field + * + * @return MappingException + */ + public static function illegalOrphanRemovalOnIdentifierAssociation($className, $field) + { + return new self("The orphan removal option is not allowed on an association that is ". + "part of the identifier in '$className#$field'."); + } + + /** + * @param string $className + * @param string $field + * + * @return MappingException + */ + public static function illegalOrphanRemoval($className, $field) + { + return new self("Orphan removal is only allowed on one-to-one and one-to-many ". + "associations, but " . $className."#" .$field . " is not."); + } + + /** + * @param string $className + * @param string $field + * + * @return MappingException + */ + public static function illegalInverseIdentifierAssociation($className, $field) + { + return new self("An inverse association is not allowed to be identifier in '$className#$field'."); + } + + /** + * @param string $className + * @param string $field + * + * @return MappingException + */ + public static function illegalToManyIdentifierAssociation($className, $field) + { + return new self("Many-to-many or one-to-many associations are not allowed to be identifier in '$className#$field'."); + } + + /** + * @param string $className + * + * @return MappingException + */ + public static function noInheritanceOnMappedSuperClass($className) + { + return new self("It is not supported to define inheritance information on a mapped superclass '" . $className . "'."); + } + + /** + * @param string $className + * @param string $rootClassName + * + * @return MappingException + */ + public static function mappedClassNotPartOfDiscriminatorMap($className, $rootClassName) + { + return new self( + "Entity '" . $className . "' has to be part of the discriminator map of '" . $rootClassName . "' " . + "to be properly mapped in the inheritance hierarchy. Alternatively you can make '".$className."' an abstract class " . + "to avoid this exception from occurring." + ); + } + + /** + * @param string $className + * @param string $methodName + * + * @return MappingException + */ + public static function lifecycleCallbackMethodNotFound($className, $methodName) + { + return new self("Entity '" . $className . "' has no method '" . $methodName . "' to be registered as lifecycle callback."); + } + + /** + * @param string $listenerName + * @param string $className + * + * @return \Doctrine\ORM\Mapping\MappingException + */ + public static function entityListenerClassNotFound($listenerName, $className) + { + return new self(sprintf('Entity Listener "%s" declared on "%s" not found.', $listenerName, $className)); + } + + /** + * @param string $listenerName + * @param string $methodName + * @param string $className + * + * @return \Doctrine\ORM\Mapping\MappingException + */ + public static function entityListenerMethodNotFound($listenerName, $methodName, $className) + { + return new self(sprintf('Entity Listener "%s" declared on "%s" has no method "%s".', $listenerName, $className, $methodName)); + } + + /** + * @param string $listenerName + * @param string $methodName + * @param string $className + * + * @return \Doctrine\ORM\Mapping\MappingException + */ + public static function duplicateEntityListener($listenerName, $methodName, $className) + { + return new self(sprintf('Entity Listener "%s#%s()" in "%s" was already declared, but it must be declared only once.', $listenerName, $methodName, $className)); + } + + /** + * @param string $className + * @param string $annotation + * + * @return MappingException + */ + public static function invalidFetchMode($className, $annotation) + { + return new self("Entity '" . $className . "' has a mapping with invalid fetch mode '" . $annotation . "'"); + } + + /** + * @param string $className + * + * @return MappingException + */ + public static function compositeKeyAssignedIdGeneratorRequired($className) + { + return new self("Entity '". $className . "' has a composite identifier but uses an ID generator other than manually assigning (Identity, Sequence). This is not supported."); + } + + /** + * @param string $targetEntity + * @param string $sourceEntity + * @param string $associationName + * + * @return MappingException + */ + public static function invalidTargetEntityClass($targetEntity, $sourceEntity, $associationName) + { + return new self("The target-entity " . $targetEntity . " cannot be found in '" . $sourceEntity."#".$associationName."'."); + } + + /** + * @param array $cascades + * @param string $className + * @param string $propertyName + * + * @return MappingException + */ + public static function invalidCascadeOption(array $cascades, $className, $propertyName) + { + $cascades = implode(", ", array_map(function ($e) { return "'" . $e . "'"; }, $cascades)); + + return new self(sprintf( + "You have specified invalid cascade options for %s::$%s: %s; available options: 'remove', 'persist', 'refresh', 'merge', and 'detach'", + $className, + $propertyName, + $cascades + )); + } + + /** + * @param string $className + * + * @return MappingException + */ + public static function missingSequenceName($className) + { + return new self( + sprintf('Missing "sequenceName" attribute for sequence id generator definition on class "%s".', $className) + ); + } + + /** + * @param string $className + * @param string $propertyName + * + * @return MappingException + */ + public static function infiniteEmbeddableNesting($className, $propertyName) + { + return new self( + sprintf( + 'Infinite nesting detected for embedded property %s::%s. ' . + 'You cannot embed an embeddable from the same type inside an embeddable.', + $className, + $propertyName + ) + ); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQueries.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQueries.php new file mode 100644 index 0000000..2539107 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQueries.php @@ -0,0 +1,40 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * Is used to specify an array of native SQL named queries. + * The NamedNativeQueries annotation can be applied to an entity or mapped superclass. + * + * @author Fabio B. Silva + * @since 2.3 + * + * @Annotation + * @Target("CLASS") + */ +final class NamedNativeQueries implements Annotation +{ + /** + * One or more NamedNativeQuery annotations. + * + * @var array<\Doctrine\ORM\Mapping\NamedNativeQuery> + */ + public $value = []; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQuery.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQuery.php new file mode 100644 index 0000000..f336c99 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQuery.php @@ -0,0 +1,61 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * Is used to specify a native SQL named query. + * The NamedNativeQuery annotation can be applied to an entity or mapped superclass. + * + * @author Fabio B. Silva + * @since 2.3 + * + * @Annotation + * @Target("ANNOTATION") + */ +final class NamedNativeQuery implements Annotation +{ + /** + * The name used to refer to the query with the EntityManager methods that create query objects. + * + * @var string + */ + public $name; + + /** + * The SQL query string. + * + * @var string + */ + public $query; + + /** + * The class of the result. + * + * @var string + */ + public $resultClass; + + /** + * The name of a SqlResultSetMapping, as defined in metadata. + * + * @var string + */ + public $resultSetMapping; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQueries.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQueries.php new file mode 100644 index 0000000..5fce072 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQueries.php @@ -0,0 +1,32 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("CLASS") + */ +final class NamedQueries implements Annotation +{ + /** + * @var array<\Doctrine\ORM\Mapping\NamedQuery> + */ + public $value; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQuery.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQuery.php new file mode 100644 index 0000000..c4e6cd5 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQuery.php @@ -0,0 +1,37 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("ANNOTATION") + */ +final class NamedQuery implements Annotation +{ + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $query; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamingStrategy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamingStrategy.php new file mode 100644 index 0000000..9960f94 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamingStrategy.php @@ -0,0 +1,100 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * A set of rules for determining the physical column and table names + * + * + * @link www.doctrine-project.org + * @since 2.3 + * @author Fabio B. Silva + */ +interface NamingStrategy +{ + /** + * Returns a table name for an entity class. + * + * @param string $className The fully-qualified class name. + * + * @return string A table name. + */ + function classToTableName($className); + + /** + * Returns a column name for a property. + * + * @param string $propertyName A property name. + * @param string|null $className The fully-qualified class name. + * + * @return string A column name. + */ + function propertyToColumnName($propertyName, $className = null); + + /** + * Returns a column name for an embedded property. + * + * @param string $propertyName + * @param string $embeddedColumnName + * @param string $className + * @param string $embeddedClassName + * + * @return string + */ + function embeddedFieldToColumnName($propertyName, $embeddedColumnName, $className = null, $embeddedClassName = null); + + /** + * Returns the default reference column name. + * + * @return string A column name. + */ + function referenceColumnName(); + + /** + * Returns a join column name for a property. + * + * @param string $propertyName A property name. + * + * @return string A join column name. + */ + function joinColumnName($propertyName); + + /** + * Returns a join table name. + * + * @param string $sourceEntity The source entity. + * @param string $targetEntity The target entity. + * @param string|null $propertyName A property name. + * + * @return string A join table name. + */ + function joinTableName($sourceEntity, $targetEntity, $propertyName = null); + + /** + * Returns the foreign key column name for the given parameters. + * + * @param string $entityName An entity. + * @param string|null $referencedColumnName A property. + * + * @return string A join column name. + */ + function joinKeyColumnName($entityName, $referencedColumnName = null); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToMany.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToMany.php new file mode 100644 index 0000000..4b24657 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToMany.php @@ -0,0 +1,61 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("PROPERTY") + */ +final class OneToMany implements Annotation +{ + /** + * @var string + */ + public $mappedBy; + + /** + * @var string + */ + public $targetEntity; + + /** + * @var array + */ + public $cascade; + + /** + * The fetching strategy to use for the association. + * + * @var string + * + * @Enum({"LAZY", "EAGER", "EXTRA_LAZY"}) + */ + public $fetch = 'LAZY'; + + /** + * @var boolean + */ + public $orphanRemoval = false; + + /** + * @var string + */ + public $indexBy; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToOne.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToOne.php new file mode 100644 index 0000000..b2ab81f --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToOne.php @@ -0,0 +1,61 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("PROPERTY") + */ +final class OneToOne implements Annotation +{ + /** + * @var string + */ + public $targetEntity; + + /** + * @var string + */ + public $mappedBy; + + /** + * @var string + */ + public $inversedBy; + + /** + * @var array + */ + public $cascade; + + /** + * The fetching strategy to use for the association. + * + * @var string + * + * @Enum({"LAZY", "EAGER", "EXTRA_LAZY"}) + */ + public $fetch = 'LAZY'; + + /** + * @var boolean + */ + public $orphanRemoval = false; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OrderBy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OrderBy.php new file mode 100644 index 0000000..ad1b7a8 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OrderBy.php @@ -0,0 +1,32 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("PROPERTY") + */ +final class OrderBy implements Annotation +{ + /** + * @var array + */ + public $value; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostLoad.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostLoad.php new file mode 100644 index 0000000..2f8e993 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostLoad.php @@ -0,0 +1,28 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("METHOD") + */ +final class PostLoad implements Annotation +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostPersist.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostPersist.php new file mode 100644 index 0000000..2aea719 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostPersist.php @@ -0,0 +1,28 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("METHOD") + */ +final class PostPersist implements Annotation +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostRemove.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostRemove.php new file mode 100644 index 0000000..321c4bd --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostRemove.php @@ -0,0 +1,28 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("METHOD") + */ +final class PostRemove implements Annotation +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostUpdate.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostUpdate.php new file mode 100644 index 0000000..a55f707 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostUpdate.php @@ -0,0 +1,28 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("METHOD") + */ +final class PostUpdate implements Annotation +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreFlush.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreFlush.php new file mode 100644 index 0000000..6697d37 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreFlush.php @@ -0,0 +1,28 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("METHOD") + */ +final class PreFlush implements Annotation +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PrePersist.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PrePersist.php new file mode 100644 index 0000000..fea05be --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PrePersist.php @@ -0,0 +1,28 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("METHOD") + */ +final class PrePersist implements Annotation +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreRemove.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreRemove.php new file mode 100644 index 0000000..29822ed --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreRemove.php @@ -0,0 +1,28 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("METHOD") + */ +final class PreRemove implements Annotation +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreUpdate.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreUpdate.php new file mode 100644 index 0000000..290df72 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreUpdate.php @@ -0,0 +1,28 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("METHOD") + */ +final class PreUpdate implements Annotation +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/QuoteStrategy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/QuoteStrategy.php new file mode 100644 index 0000000..1a21ff1 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/QuoteStrategy.php @@ -0,0 +1,119 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * A set of rules for determining the column, alias and table quotes. + * + * @since 2.3 + * @author Fabio B. Silva + */ +interface QuoteStrategy +{ + /** + * Gets the (possibly quoted) column name for safe use in an SQL statement. + * + * @param string $fieldName + * @param ClassMetadata $class + * @param AbstractPlatform $platform + * + * @return string + */ + function getColumnName($fieldName, ClassMetadata $class, AbstractPlatform $platform); + + /** + * Gets the (possibly quoted) primary table name for safe use in an SQL statement. + * + * @param ClassMetadata $class + * @param AbstractPlatform $platform + * + * @return string + */ + function getTableName(ClassMetadata $class, AbstractPlatform $platform); + + /** + * Gets the (possibly quoted) sequence name for safe use in an SQL statement. + * + * @param array $definition + * @param ClassMetadata $class + * @param AbstractPlatform $platform + * + * @return string + */ + function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform); + + /** + * Gets the (possibly quoted) name of the join table. + * + * @param array $association + * @param ClassMetadata $class + * @param AbstractPlatform $platform + * + * @return string + */ + function getJoinTableName(array $association, ClassMetadata $class, AbstractPlatform $platform); + + /** + * Gets the (possibly quoted) join column name. + * + * @param array $joinColumn + * @param ClassMetadata $class + * @param AbstractPlatform $platform + * + * @return string + */ + function getJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform); + + /** + * Gets the (possibly quoted) join column name. + * + * @param array $joinColumn + * @param ClassMetadata $class + * @param AbstractPlatform $platform + * + * @return string + */ + function getReferencedJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform); + + /** + * Gets the (possibly quoted) identifier column names for safe use in an SQL statement. + * + * @param ClassMetadata $class + * @param AbstractPlatform $platform + * + * @return array + */ + function getIdentifierColumnNames(ClassMetadata $class, AbstractPlatform $platform); + + /** + * Gets the column alias. + * + * @param string $columnName + * @param integer $counter + * @param AbstractPlatform $platform + * @param ClassMetadata|null $class + * + * @return string + */ + function getColumnAlias($columnName, $counter, AbstractPlatform $platform, ClassMetadata $class = null); + +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Reflection/ReflectionPropertiesGetter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Reflection/ReflectionPropertiesGetter.php new file mode 100644 index 0000000..6ac7f11 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Reflection/ReflectionPropertiesGetter.php @@ -0,0 +1,163 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Reflection; + +use Doctrine\Common\Persistence\Mapping\ReflectionService; +use ReflectionClass; +use ReflectionProperty; + +/** + * Utility class to retrieve all reflection instance properties of a given class, including + * private inherited properties and transient properties. + * + * @private This API is for internal use only + * + * @author Marco Pivetta + */ +final class ReflectionPropertiesGetter +{ + /** + * @var ReflectionProperty[][] indexed by class name and property internal name + */ + private $properties = []; + + /** + * @var ReflectionService + */ + private $reflectionService; + + /** + * @param ReflectionService $reflectionService + */ + public function __construct(ReflectionService $reflectionService) + { + $this->reflectionService = $reflectionService; + } + + /** + * @param $className + * + * @return ReflectionProperty[] indexed by property internal name + */ + public function getProperties($className) + { + if (isset($this->properties[$className])) { + return $this->properties[$className]; + } + + return $this->properties[$className] = call_user_func_array( + 'array_merge', + // first merge because `array_merge` expects >= 1 params + array_merge( + [[]], + array_map( + [$this, 'getClassProperties'], + $this->getHierarchyClasses($className) + ) + ) + ); + } + + /** + * @param string $className + * + * @return ReflectionClass[] + */ + private function getHierarchyClasses($className) + { + $classes = []; + $parentClassName = $className; + + while ($parentClassName && $currentClass = $this->reflectionService->getClass($parentClassName)) { + $classes[] = $currentClass; + $parentClassName = null; + + if ($parentClass = $currentClass->getParentClass()) { + $parentClassName = $parentClass->getName(); + } + } + + return $classes; + } + + /** + * @param ReflectionClass $reflectionClass + * + * @return ReflectionProperty[] + */ + private function getClassProperties(ReflectionClass $reflectionClass) + { + $properties = $reflectionClass->getProperties(); + + return array_filter( + array_filter(array_map( + [$this, 'getAccessibleProperty'], + array_combine( + array_map([$this, 'getLogicalName'], $properties), + $properties + ) + )), + [$this, 'isInstanceProperty'] + ); + } + + /** + * @param ReflectionProperty $reflectionProperty + * + * @return bool + */ + private function isInstanceProperty(ReflectionProperty $reflectionProperty) + { + return ! $reflectionProperty->isStatic(); + } + + /** + * @param ReflectionProperty $property + * + * @return null|ReflectionProperty + */ + private function getAccessibleProperty(ReflectionProperty $property) + { + return $this->reflectionService->getAccessibleProperty( + $property->getDeclaringClass()->getName(), + $property->getName() + ); + } + + /** + * @param ReflectionProperty $property + * + * @return string + */ + private function getLogicalName(ReflectionProperty $property) + { + $propertyName = $property->getName(); + + if ($property->isPublic()) { + return $propertyName; + } + + if ($property->isProtected()) { + return "\0*\0" . $propertyName; + } + + return "\0" . $property->getDeclaringClass()->getName() . "\0" . $propertyName; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ReflectionEmbeddedProperty.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ReflectionEmbeddedProperty.php new file mode 100644 index 0000000..b224fff --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ReflectionEmbeddedProperty.php @@ -0,0 +1,101 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +use Doctrine\Instantiator\Instantiator; +use ReflectionProperty; + +/** + * Acts as a proxy to a nested Property structure, making it look like + * just a single scalar property. + * + * This way value objects "just work" without UnitOfWork, Persisters or Hydrators + * needing any changes. + * + * TODO: Move this class into Common\Reflection + */ +class ReflectionEmbeddedProperty extends ReflectionProperty +{ + /** + * @var ReflectionProperty reflection property of the class where the embedded object has to be put + */ + private $parentProperty; + + /** + * @var ReflectionProperty reflection property of the embedded object + */ + private $childProperty; + + /** + * @var string name of the embedded class to be eventually instantiated + */ + private $embeddedClass; + + /** + * @var Instantiator|null + */ + private $instantiator; + + /** + * @param ReflectionProperty $parentProperty + * @param ReflectionProperty $childProperty + * @param string $embeddedClass + */ + public function __construct(ReflectionProperty $parentProperty, ReflectionProperty $childProperty, $embeddedClass) + { + $this->parentProperty = $parentProperty; + $this->childProperty = $childProperty; + $this->embeddedClass = (string) $embeddedClass; + + parent::__construct($childProperty->getDeclaringClass()->getName(), $childProperty->getName()); + } + + /** + * {@inheritDoc} + */ + public function getValue($object = null) + { + $embeddedObject = $this->parentProperty->getValue($object); + + if (null === $embeddedObject) { + return null; + } + + return $this->childProperty->getValue($embeddedObject); + } + + /** + * {@inheritDoc} + */ + public function setValue($object, $value = null) + { + $embeddedObject = $this->parentProperty->getValue($object); + + if (null === $embeddedObject) { + $this->instantiator = $this->instantiator ?: new Instantiator(); + + $embeddedObject = $this->instantiator->instantiate($this->embeddedClass); + + $this->parentProperty->setValue($object, $embeddedObject); + } + + $this->childProperty->setValue($embeddedObject, $value); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SequenceGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SequenceGenerator.php new file mode 100644 index 0000000..ba1c45b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SequenceGenerator.php @@ -0,0 +1,42 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("PROPERTY") + */ +final class SequenceGenerator implements Annotation +{ + /** + * @var string + */ + public $sequenceName; + + /** + * @var integer + */ + public $allocationSize = 1; + + /** + * @var integer + */ + public $initialValue = 1; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMapping.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMapping.php new file mode 100644 index 0000000..cb78c9a --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMapping.php @@ -0,0 +1,54 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * The SqlResultSetMapping annotation is used to specify the mapping of the result of a native SQL query. + * The SqlResultSetMapping annotation can be applied to an entity or mapped superclass. + * + * @author Fabio B. Silva + * @since 2.3 + * + * @Annotation + * @Target("ANNOTATION") + */ +final class SqlResultSetMapping implements Annotation +{ + /** + * The name given to the result set mapping, and used to refer to it in the methods of the Query API. + * + * @var string + */ + public $name; + + /** + * Specifies the result set mapping to entities. + * + * @var array<\Doctrine\ORM\Mapping\EntityResult> + */ + public $entities = []; + + /** + * Specifies the result set mapping to scalar values. + * + * @var array<\Doctrine\ORM\Mapping\ColumnResult> + */ + public $columns = []; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMappings.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMappings.php new file mode 100644 index 0000000..0b74f2d --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMappings.php @@ -0,0 +1,40 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * Is used to specify an array of mappings. + * The SqlResultSetMappings annotation can be applied to an entity or mapped superclass. + * + * @author Fabio B. Silva + * @since 2.3 + * + * @Annotation + * @Target("CLASS") + */ +final class SqlResultSetMappings implements Annotation +{ + /** + * One or more SqlResultSetMapping annotations. + * + * @var array<\Doctrine\ORM\Mapping\SqlResultSetMapping> + */ + public $value = []; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Table.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Table.php new file mode 100644 index 0000000..6ed7037 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Table.php @@ -0,0 +1,52 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("CLASS") + */ +final class Table implements Annotation +{ + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $schema; + + /** + * @var array<\Doctrine\ORM\Mapping\Index> + */ + public $indexes; + + /** + * @var array<\Doctrine\ORM\Mapping\UniqueConstraint> + */ + public $uniqueConstraints; + + /** + * @var array + */ + public $options = []; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UnderscoreNamingStrategy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UnderscoreNamingStrategy.php new file mode 100644 index 0000000..177b390 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UnderscoreNamingStrategy.php @@ -0,0 +1,166 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +use const CASE_LOWER; +use const CASE_UPPER; +use const E_USER_DEPRECATED; +use function preg_replace; +use function strpos; +use function strrpos; +use function strtolower; +use function strtoupper; +use function substr; +use function trigger_error; + +/** + * Naming strategy implementing the underscore naming convention. + * Converts 'MyEntity' to 'my_entity' or 'MY_ENTITY'. + * + * + * @link www.doctrine-project.org + * @since 2.3 + * @author Fabio B. Silva + */ +class UnderscoreNamingStrategy implements NamingStrategy +{ + private const DEFAULT_PATTERN = '/(?<=[a-z])([A-Z])/'; + private const NUMBER_AWARE_PATTERN = '/(?<=[a-z0-9])([A-Z])/'; + + /** + * @var integer + */ + private $case; + + /** @var string */ + private $pattern; + + /** + * Underscore naming strategy construct. + * + * @param int $case CASE_LOWER | CASE_UPPER + */ + public function __construct($case = CASE_LOWER, bool $numberAware = false) + { + if (! $numberAware) { + @trigger_error( + 'Creating ' . self::class . ' without making it number aware is deprecated and will be removed in Doctrine ORM 3.0.', + E_USER_DEPRECATED + ); + } + + $this->case = $case; + $this->pattern = $numberAware ? self::NUMBER_AWARE_PATTERN : self::DEFAULT_PATTERN; + } + + /** + * @return integer CASE_LOWER | CASE_UPPER + */ + public function getCase() + { + return $this->case; + } + + /** + * Sets string case CASE_LOWER | CASE_UPPER. + * Alphabetic characters converted to lowercase or uppercase. + * + * @param integer $case + * + * @return void + */ + public function setCase($case) + { + $this->case = $case; + } + + /** + * {@inheritdoc} + */ + public function classToTableName($className) + { + if (strpos($className, '\\') !== false) { + $className = substr($className, strrpos($className, '\\') + 1); + } + + return $this->underscore($className); + } + + /** + * {@inheritdoc} + */ + public function propertyToColumnName($propertyName, $className = null) + { + return $this->underscore($propertyName); + } + + /** + * {@inheritdoc} + */ + public function embeddedFieldToColumnName($propertyName, $embeddedColumnName, $className = null, $embeddedClassName = null) + { + return $this->underscore($propertyName).'_'.$embeddedColumnName; + } + + /** + * {@inheritdoc} + */ + public function referenceColumnName() + { + return $this->case === CASE_UPPER ? 'ID' : 'id'; + } + + /** + * {@inheritdoc} + */ + public function joinColumnName($propertyName, $className = null) + { + return $this->underscore($propertyName) . '_' . $this->referenceColumnName(); + } + + /** + * {@inheritdoc} + */ + public function joinTableName($sourceEntity, $targetEntity, $propertyName = null) + { + return $this->classToTableName($sourceEntity) . '_' . $this->classToTableName($targetEntity); + } + + /** + * {@inheritdoc} + */ + public function joinKeyColumnName($entityName, $referencedColumnName = null) + { + return $this->classToTableName($entityName) . '_' . + ($referencedColumnName ?: $this->referenceColumnName()); + } + + private function underscore(string $string) : string + { + $string = preg_replace($this->pattern, '_$1', $string); + + if ($this->case === CASE_UPPER) { + return strtoupper($string); + } + + return strtolower($string); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UniqueConstraint.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UniqueConstraint.php new file mode 100644 index 0000000..f117d18 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UniqueConstraint.php @@ -0,0 +1,42 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("ANNOTATION") + */ +final class UniqueConstraint implements Annotation +{ + /** + * @var string + */ + public $name; + + /** + * @var array + */ + public $columns; + + /** + * @var array + */ + public $options; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Version.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Version.php new file mode 100644 index 0000000..a237702 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Version.php @@ -0,0 +1,28 @@ +. + */ + +namespace Doctrine\ORM\Mapping; + +/** + * @Annotation + * @Target("PROPERTY") + */ +final class Version implements Annotation +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/NativeQuery.php b/vendor/doctrine/orm/lib/Doctrine/ORM/NativeQuery.php new file mode 100644 index 0000000..ddc5418 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/NativeQuery.php @@ -0,0 +1,92 @@ +. + */ + +namespace Doctrine\ORM; + +/** + * Represents a native SQL query. + * + * @author Roman Borschel + * @since 2.0 + */ +final class NativeQuery extends AbstractQuery +{ + /** + * @var string + */ + private $_sql; + + /** + * Sets the SQL of the query. + * + * @param string $sql + * + * @return NativeQuery This query instance. + */ + public function setSQL($sql) + { + $this->_sql = $sql; + + return $this; + } + + /** + * Gets the SQL query. + * + * @return mixed The built SQL query or an array of all SQL queries. + * + * @override + */ + public function getSQL() + { + return $this->_sql; + } + + /** + * {@inheritdoc} + */ + protected function _doExecute() + { + $parameters = []; + $types = []; + + foreach ($this->getParameters() as $parameter) { + $name = $parameter->getName(); + $value = $this->processParameterValue($parameter->getValue()); + $type = ($parameter->getValue() === $value) + ? $parameter->getType() + : Query\ParameterTypeInferer::inferType($value); + + $parameters[$name] = $value; + $types[$name] = $type; + } + + if ($parameters && is_int(key($parameters))) { + ksort($parameters); + ksort($types); + + $parameters = array_values($parameters); + $types = array_values($types); + } + + return $this->_em->getConnection()->executeQuery( + $this->_sql, $parameters, $types, $this->_queryCacheProfile + ); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/NoResultException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/NoResultException.php new file mode 100644 index 0000000..2cbac8e --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/NoResultException.php @@ -0,0 +1,37 @@ +. + */ + +namespace Doctrine\ORM; + +/** + * Exception thrown when an ORM query unexpectedly does not return any results. + * + * @author robo + * @since 2.0 + */ +class NoResultException extends UnexpectedResultException +{ + /** + * Constructor. + */ + public function __construct() + { + parent::__construct('No result was found for query although at least one row was expected.'); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/NonUniqueResultException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/NonUniqueResultException.php new file mode 100644 index 0000000..78a58dd --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/NonUniqueResultException.php @@ -0,0 +1,36 @@ +. + */ + +namespace Doctrine\ORM; + +/** + * Exception thrown when an ORM query unexpectedly returns more than one result. + * + * @author robo + * @since 2.0 + */ +class NonUniqueResultException extends UnexpectedResultException +{ + const DEFAULT_MESSAGE = 'More than one result was found for query although one row or none was expected.'; + + public function __construct(string $message = null) + { + parent::__construct($message ?? self::DEFAULT_MESSAGE); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/ORMException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/ORMException.php new file mode 100644 index 0000000..3ce9ce9 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/ORMException.php @@ -0,0 +1,333 @@ +. + */ + +namespace Doctrine\ORM; + +use Doctrine\Common\Cache\Cache as CacheDriver; +use Exception; + +/** + * Base exception class for all ORM exceptions. + * + * @author Roman Borschel + * @since 2.0 + */ +class ORMException extends Exception +{ + /** + * @return ORMException + */ + public static function missingMappingDriverImpl() + { + return new self("It's a requirement to specify a Metadata Driver and pass it ". + "to Doctrine\\ORM\\Configuration::setMetadataDriverImpl()."); + } + + /** + * @param string $queryName + * + * @return ORMException + */ + public static function namedQueryNotFound($queryName) + { + return new self('Could not find a named query by the name "' . $queryName . '"'); + } + + /** + * @param string $nativeQueryName + * + * @return ORMException + */ + public static function namedNativeQueryNotFound($nativeQueryName) + { + return new self('Could not find a named native query by the name "' . $nativeQueryName . '"'); + } + + /** + * @param object $entity + * @param object $relatedEntity + * + * @return ORMException + */ + public static function entityMissingForeignAssignedId($entity, $relatedEntity) + { + return new self( + "Entity of type " . get_class($entity) . " has identity through a foreign entity " . get_class($relatedEntity) . ", " . + "however this entity has no identity itself. You have to call EntityManager#persist() on the related entity " . + "and make sure that an identifier was generated before trying to persist '" . get_class($entity) . "'. In case " . + "of Post Insert ID Generation (such as MySQL Auto-Increment) this means you have to call " . + "EntityManager#flush() between both persist operations." + ); + } + + /** + * @param object $entity + * @param string $field + * + * @return ORMException + */ + public static function entityMissingAssignedIdForField($entity, $field) + { + return new self("Entity of type " . get_class($entity) . " is missing an assigned ID for field '" . $field . "'. " . + "The identifier generation strategy for this entity requires the ID field to be populated before ". + "EntityManager#persist() is called. If you want automatically generated identifiers instead " . + "you need to adjust the metadata mapping accordingly." + ); + } + + /** + * @param string $field + * + * @return ORMException + */ + public static function unrecognizedField($field) + { + return new self("Unrecognized field: $field"); + } + + /** + * + * @param string $class + * @param string $association + * @param string $given + * @param string $expected + * + * @return \Doctrine\ORM\ORMInvalidArgumentException + */ + public static function unexpectedAssociationValue($class, $association, $given, $expected) + { + return new self(sprintf('Found entity of type %s on association %s#%s, but expecting %s', $given, $class, $association, $expected)); + } + + /** + * @param string $className + * @param string $field + * + * @return ORMException + */ + public static function invalidOrientation($className, $field) + { + return new self("Invalid order by orientation specified for " . $className . "#" . $field); + } + + /** + * @param string $mode + * + * @return ORMException + */ + public static function invalidFlushMode($mode) + { + return new self("'$mode' is an invalid flush mode."); + } + + /** + * @return ORMException + */ + public static function entityManagerClosed() + { + return new self("The EntityManager is closed."); + } + + /** + * @param string $mode + * + * @return ORMException + */ + public static function invalidHydrationMode($mode) + { + return new self("'$mode' is an invalid hydration mode."); + } + + /** + * @return ORMException + */ + public static function mismatchedEventManager() + { + return new self("Cannot use different EventManager instances for EntityManager and Connection."); + } + + /** + * @param string $methodName + * + * @return ORMException + */ + public static function findByRequiresParameter($methodName) + { + return new self("You need to pass a parameter to '".$methodName."'"); + } + + /** + * @param string $entityName + * @param string $fieldName + * @param string $method + * + * @return ORMException + */ + public static function invalidFindByCall($entityName, $fieldName, $method) + { + return new self( + "Entity '".$entityName."' has no field '".$fieldName."'. ". + "You can therefore not call '".$method."' on the entities' repository" + ); + } + + /** + * @param string $entityName + * @param string $fieldName + * @param string $method + * + * @return ORMException + */ + public static function invalidMagicCall($entityName, $fieldName, $method) + { + return new self( + "Entity '".$entityName."' has no field '".$fieldName."'. ". + "You can therefore not call '".$method."' on the entities' repository" + ); + } + + /** + * @param string $entityName + * @param string $associationFieldName + * + * @return ORMException + */ + public static function invalidFindByInverseAssociation($entityName, $associationFieldName) + { + return new self( + "You cannot search for the association field '".$entityName."#".$associationFieldName."', ". + "because it is the inverse side of an association. Find methods only work on owning side associations." + ); + } + + /** + * @return ORMException + */ + public static function invalidResultCacheDriver() + { + return new self("Invalid result cache driver; it must implement Doctrine\\Common\\Cache\\Cache."); + } + + /** + * @return ORMException + */ + public static function notSupported() + { + return new self("This behaviour is (currently) not supported by Doctrine 2"); + } + + /** + * @return ORMException + */ + public static function queryCacheNotConfigured() + { + return new self('Query Cache is not configured.'); + } + + /** + * @return ORMException + */ + public static function metadataCacheNotConfigured() + { + return new self('Class Metadata Cache is not configured.'); + } + + /** + * @param \Doctrine\Common\Cache\Cache $cache + * + * @return ORMException + */ + public static function queryCacheUsesNonPersistentCache(CacheDriver $cache) + { + return new self('Query Cache uses a non-persistent cache driver, ' . get_class($cache) . '.'); + } + + /** + * @param \Doctrine\Common\Cache\Cache $cache + * + * @return ORMException + */ + public static function metadataCacheUsesNonPersistentCache(CacheDriver $cache) + { + return new self('Metadata Cache uses a non-persistent cache driver, ' . get_class($cache) . '.'); + } + + /** + * @return ORMException + */ + public static function proxyClassesAlwaysRegenerating() + { + return new self('Proxy Classes are always regenerating.'); + } + + /** + * @param string $entityNamespaceAlias + * + * @return ORMException + */ + public static function unknownEntityNamespace($entityNamespaceAlias) + { + return new self( + "Unknown Entity namespace alias '$entityNamespaceAlias'." + ); + } + + /** + * @param string $className + * + * @return ORMException + */ + public static function invalidEntityRepository($className) + { + return new self("Invalid repository class '".$className."'. It must be a Doctrine\Common\Persistence\ObjectRepository."); + } + + /** + * @param string $className + * @param string $fieldName + * + * @return ORMException + */ + public static function missingIdentifierField($className, $fieldName) + { + return new self("The identifier $fieldName is missing for a query of " . $className); + } + + /** + * @param string $className + * @param string[] $fieldNames + * + * @return ORMException + */ + public static function unrecognizedIdentifierFields($className, $fieldNames) + { + return new self( + "Unrecognized identifier fields: '" . implode("', '", $fieldNames) . "' " . + "are not present on class '" . $className . "'." + ); + } + + /** + * @return ORMException + */ + public static function cantUseInOperatorOnCompositeKeys() + { + return new self("Can't use IN operator on entities that have composite keys."); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/ORMInvalidArgumentException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/ORMInvalidArgumentException.php new file mode 100644 index 0000000..68bb6f9 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/ORMInvalidArgumentException.php @@ -0,0 +1,272 @@ +. + */ + +namespace Doctrine\ORM; +use Doctrine\ORM\Mapping\ClassMetadata; + +/** + * Contains exception messages for all invalid lifecycle state exceptions inside UnitOfWork + * + * @author Benjamin Eberlei + */ +class ORMInvalidArgumentException extends \InvalidArgumentException +{ + /** + * @param object $entity + * + * @return ORMInvalidArgumentException + */ + static public function scheduleInsertForManagedEntity($entity) + { + return new self("A managed+dirty entity " . self::objToStr($entity) . " can not be scheduled for insertion."); + } + + /** + * @param object $entity + * + * @return ORMInvalidArgumentException + */ + static public function scheduleInsertForRemovedEntity($entity) + { + return new self("Removed entity " . self::objToStr($entity) . " can not be scheduled for insertion."); + } + + /** + * @param object $entity + * + * @return ORMInvalidArgumentException + */ + static public function scheduleInsertTwice($entity) + { + return new self("Entity " . self::objToStr($entity) . " can not be scheduled for insertion twice."); + } + + /** + * @param string $className + * @param object $entity + * + * @return ORMInvalidArgumentException + */ + static public function entityWithoutIdentity($className, $entity) + { + return new self( + "The given entity of type '" . $className . "' (".self::objToStr($entity).") has no identity/no " . + "id values set. It cannot be added to the identity map." + ); + } + + /** + * @param object $entity + * + * @return ORMInvalidArgumentException + */ + static public function readOnlyRequiresManagedEntity($entity) + { + return new self("Only managed entities can be marked or checked as read only. But " . self::objToStr($entity) . " is not"); + } + + /** + * @param array[][]|object[][] $newEntitiesWithAssociations non-empty an array + * of [array $associationMapping, object $entity] pairs + * + * @return ORMInvalidArgumentException + */ + static public function newEntitiesFoundThroughRelationships($newEntitiesWithAssociations) + { + $errorMessages = array_map( + function (array $newEntityWithAssociation) : string { + [$associationMapping, $entity] = $newEntityWithAssociation; + + return self::newEntityFoundThroughRelationshipMessage($associationMapping, $entity); + }, + $newEntitiesWithAssociations + ); + + if (1 === count($errorMessages)) { + return new self(reset($errorMessages)); + } + + return new self( + 'Multiple non-persisted new entities were found through the given association graph:' + . "\n\n * " + . implode("\n * ", $errorMessages) + ); + } + + /** + * @param array $associationMapping + * @param object $entry + * + * @return ORMInvalidArgumentException + */ + static public function newEntityFoundThroughRelationship(array $associationMapping, $entry) + { + return new self(self::newEntityFoundThroughRelationshipMessage($associationMapping, $entry)); + } + + /** + * @param array $assoc + * @param object $entry + * + * @return ORMInvalidArgumentException + */ + static public function detachedEntityFoundThroughRelationship(array $assoc, $entry) + { + return new self("A detached entity of type " . $assoc['targetEntity'] . " (" . self::objToStr($entry) . ") " + . " was found through the relationship '" . $assoc['sourceEntity'] . "#" . $assoc['fieldName'] . "' " + . "during cascading a persist operation."); + } + + /** + * @param object $entity + * + * @return ORMInvalidArgumentException + */ + static public function entityNotManaged($entity) + { + return new self("Entity " . self::objToStr($entity) . " is not managed. An entity is managed if its fetched " . + "from the database or registered as new through EntityManager#persist"); + } + + /** + * @param object $entity + * @param string $operation + * + * @return ORMInvalidArgumentException + */ + static public function entityHasNoIdentity($entity, $operation) + { + return new self("Entity has no identity, therefore " . $operation ." cannot be performed. " . self::objToStr($entity)); + } + + /** + * @param object $entity + * @param string $operation + * + * @return ORMInvalidArgumentException + */ + static public function entityIsRemoved($entity, $operation) + { + return new self("Entity is removed, therefore " . $operation ." cannot be performed. " . self::objToStr($entity)); + } + + /** + * @param object $entity + * @param string $operation + * + * @return ORMInvalidArgumentException + */ + static public function detachedEntityCannot($entity, $operation) + { + return new self("Detached entity " . self::objToStr($entity) . " cannot be " . $operation); + } + + /** + * @param string $context + * @param mixed $given + * @param int $parameterIndex + * + * @return ORMInvalidArgumentException + */ + public static function invalidObject($context, $given, $parameterIndex = 1) + { + return new self($context . ' expects parameter ' . $parameterIndex . + ' to be an entity object, '. gettype($given) . ' given.'); + } + + /** + * @return ORMInvalidArgumentException + */ + public static function invalidCompositeIdentifier() + { + return new self("Binding an entity with a composite primary key to a query is not supported. " . + "You should split the parameter into the explicit fields and bind them separately."); + } + + /** + * @return ORMInvalidArgumentException + */ + public static function invalidIdentifierBindingEntity() + { + return new self("Binding entities to query parameters only allowed for entities that have an identifier."); + } + + /** + * @param ClassMetadata $targetClass + * @param array $assoc + * @param mixed $actualValue + * + * @return self + */ + public static function invalidAssociation(ClassMetadata $targetClass, $assoc, $actualValue) + { + $expectedType = $targetClass->getName(); + + return new self(sprintf( + 'Expected value of type "%s" for association field "%s#$%s", got "%s" instead.', + $expectedType, + $assoc['sourceEntity'], + $assoc['fieldName'], + is_object($actualValue) ? get_class($actualValue) : gettype($actualValue) + )); + } + + /** + * Used when a given entityName hasn't the good type + * + * @param mixed $entityName The given entity (which shouldn't be a string) + * + * @return self + */ + public static function invalidEntityName($entityName) + { + return new self(sprintf('Entity name must be a string, %s given', gettype($entityName))); + } + + /** + * Helper method to show an object as string. + * + * @param object $obj + * + * @return string + */ + private static function objToStr($obj) : string + { + return method_exists($obj, '__toString') ? (string) $obj : get_class($obj).'@'.spl_object_hash($obj); + } + + /** + * @param array $associationMapping + * @param object $entity + */ + private static function newEntityFoundThroughRelationshipMessage(array $associationMapping, $entity) : string + { + return 'A new entity was found through the relationship \'' + . $associationMapping['sourceEntity'] . '#' . $associationMapping['fieldName'] . '\' that was not' + . ' configured to cascade persist operations for entity: ' . self::objToStr($entity) . '.' + . ' To solve this issue: Either explicitly call EntityManager#persist()' + . ' on this unknown entity or configure cascade persist' + . ' this association in the mapping for example @ManyToOne(..,cascade={"persist"}).' + . (method_exists($entity, '__toString') + ? '' + : ' If you cannot find out which entity causes the problem implement \'' + . $associationMapping['targetEntity'] . '#__toString()\' to get a clue.' + ); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/OptimisticLockException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/OptimisticLockException.php new file mode 100644 index 0000000..2fbd9ce --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/OptimisticLockException.php @@ -0,0 +1,91 @@ +. + */ + +namespace Doctrine\ORM; + +/** + * An OptimisticLockException is thrown when a version check on an object + * that uses optimistic locking through a version field fails. + * + * @author Roman Borschel + * @author Benjamin Eberlei + * @since 2.0 + */ +class OptimisticLockException extends ORMException +{ + /** + * @var object|null + */ + private $entity; + + /** + * @param string $msg + * @param object $entity + */ + public function __construct($msg, $entity) + { + parent::__construct($msg); + $this->entity = $entity; + } + + /** + * Gets the entity that caused the exception. + * + * @return object|null + */ + public function getEntity() + { + return $this->entity; + } + + /** + * @param object $entity + * + * @return OptimisticLockException + */ + public static function lockFailed($entity) + { + return new self("The optimistic lock on an entity failed.", $entity); + } + + /** + * @param object $entity + * @param int $expectedLockVersion + * @param int $actualLockVersion + * + * @return OptimisticLockException + */ + public static function lockFailedVersionMismatch($entity, $expectedLockVersion, $actualLockVersion) + { + $expectedLockVersion = ($expectedLockVersion instanceof \DateTime) ? $expectedLockVersion->getTimestamp() : $expectedLockVersion; + $actualLockVersion = ($actualLockVersion instanceof \DateTime) ? $actualLockVersion->getTimestamp() : $actualLockVersion; + + return new self("The optimistic lock failed, version " . $expectedLockVersion . " was expected, but is actually ".$actualLockVersion, $entity); + } + + /** + * @param string $entityName + * + * @return OptimisticLockException + */ + public static function notVersioned($entityName) + { + return new self("Cannot obtain optimistic lock on unversioned entity " . $entityName, null); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/PersistentCollection.php b/vendor/doctrine/orm/lib/Doctrine/ORM/PersistentCollection.php new file mode 100644 index 0000000..7d52d53 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/PersistentCollection.php @@ -0,0 +1,734 @@ +. + */ + +namespace Doctrine\ORM; + +use Doctrine\Common\Collections\AbstractLazyCollection; +use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Selectable; +use Doctrine\Common\Collections\Criteria; +use Doctrine\ORM\Mapping\ClassMetadata; +use function get_class; + +/** + * A PersistentCollection represents a collection of elements that have persistent state. + * + * Collections of entities represent only the associations (links) to those entities. + * That means, if the collection is part of a many-many mapping and you remove + * entities from the collection, only the links in the relation table are removed (on flush). + * Similarly, if you remove entities from a collection that is part of a one-many + * mapping this will only result in the nulling out of the foreign keys on flush. + * + * @since 2.0 + * @author Konsta Vesterinen + * @author Roman Borschel + * @author Giorgio Sironi + * @author Stefano Rodriguez + */ +final class PersistentCollection extends AbstractLazyCollection implements Selectable +{ + /** + * A snapshot of the collection at the moment it was fetched from the database. + * This is used to create a diff of the collection at commit time. + * + * @var array + */ + private $snapshot = []; + + /** + * The entity that owns this collection. + * + * @var object + */ + private $owner; + + /** + * The association mapping the collection belongs to. + * This is currently either a OneToManyMapping or a ManyToManyMapping. + * + * @var array + */ + private $association; + + /** + * The EntityManager that manages the persistence of the collection. + * + * @var \Doctrine\ORM\EntityManagerInterface + */ + private $em; + + /** + * The name of the field on the target entities that points to the owner + * of the collection. This is only set if the association is bi-directional. + * + * @var string + */ + private $backRefFieldName; + + /** + * The class descriptor of the collection's entity type. + * + * @var ClassMetadata + */ + private $typeClass; + + /** + * Whether the collection is dirty and needs to be synchronized with the database + * when the UnitOfWork that manages its persistent state commits. + * + * @var boolean + */ + private $isDirty = false; + + /** + * Creates a new persistent collection. + * + * @param EntityManagerInterface $em The EntityManager the collection will be associated with. + * @param ClassMetadata $class The class descriptor of the entity type of this collection. + * @param Collection $collection The collection elements. + */ + public function __construct(EntityManagerInterface $em, $class, Collection $collection) + { + $this->collection = $collection; + $this->em = $em; + $this->typeClass = $class; + $this->initialized = true; + } + + /** + * INTERNAL: + * Sets the collection's owning entity together with the AssociationMapping that + * describes the association between the owner and the elements of the collection. + * + * @param object $entity + * @param array $assoc + * + * @return void + */ + public function setOwner($entity, array $assoc) + { + $this->owner = $entity; + $this->association = $assoc; + $this->backRefFieldName = $assoc['inversedBy'] ?: $assoc['mappedBy']; + } + + /** + * INTERNAL: + * Gets the collection owner. + * + * @return object + */ + public function getOwner() + { + return $this->owner; + } + + /** + * @return Mapping\ClassMetadata + */ + public function getTypeClass() + { + return $this->typeClass; + } + + /** + * INTERNAL: + * Adds an element to a collection during hydration. This will automatically + * complete bidirectional associations in the case of a one-to-many association. + * + * @param mixed $element The element to add. + * + * @return void + */ + public function hydrateAdd($element) + { + $this->collection->add($element); + + // If _backRefFieldName is set and its a one-to-many association, + // we need to set the back reference. + if ($this->backRefFieldName && $this->association['type'] === ClassMetadata::ONE_TO_MANY) { + // Set back reference to owner + $this->typeClass->reflFields[$this->backRefFieldName]->setValue( + $element, $this->owner + ); + + $this->em->getUnitOfWork()->setOriginalEntityProperty( + spl_object_hash($element), $this->backRefFieldName, $this->owner + ); + } + } + + /** + * INTERNAL: + * Sets a keyed element in the collection during hydration. + * + * @param mixed $key The key to set. + * @param mixed $element The element to set. + * + * @return void + */ + public function hydrateSet($key, $element) + { + $this->collection->set($key, $element); + + // If _backRefFieldName is set, then the association is bidirectional + // and we need to set the back reference. + if ($this->backRefFieldName && $this->association['type'] === ClassMetadata::ONE_TO_MANY) { + // Set back reference to owner + $this->typeClass->reflFields[$this->backRefFieldName]->setValue( + $element, $this->owner + ); + } + } + + /** + * Initializes the collection by loading its contents from the database + * if the collection is not yet initialized. + * + * @return void + */ + public function initialize() + { + if ($this->initialized || ! $this->association) { + return; + } + + $this->doInitialize(); + + $this->initialized = true; + } + + /** + * INTERNAL: + * Tells this collection to take a snapshot of its current state. + * + * @return void + */ + public function takeSnapshot() + { + $this->snapshot = $this->collection->toArray(); + $this->isDirty = false; + } + + /** + * INTERNAL: + * Returns the last snapshot of the elements in the collection. + * + * @return array The last snapshot of the elements. + */ + public function getSnapshot() + { + return $this->snapshot; + } + + /** + * INTERNAL: + * getDeleteDiff + * + * @return array + */ + public function getDeleteDiff() + { + return array_udiff_assoc( + $this->snapshot, + $this->collection->toArray(), + function($a, $b) { return $a === $b ? 0 : 1; } + ); + } + + /** + * INTERNAL: + * getInsertDiff + * + * @return array + */ + public function getInsertDiff() + { + return array_udiff_assoc( + $this->collection->toArray(), + $this->snapshot, + function($a, $b) { return $a === $b ? 0 : 1; } + ); + } + + /** + * INTERNAL: Gets the association mapping of the collection. + * + * @return array + */ + public function getMapping() + { + return $this->association; + } + + /** + * Marks this collection as changed/dirty. + * + * @return void + */ + private function changed() + { + if ($this->isDirty) { + return; + } + + $this->isDirty = true; + + if ($this->association !== null && + $this->association['isOwningSide'] && + $this->association['type'] === ClassMetadata::MANY_TO_MANY && + $this->owner && + $this->em->getClassMetadata(get_class($this->owner))->isChangeTrackingNotify()) { + $this->em->getUnitOfWork()->scheduleForDirtyCheck($this->owner); + } + } + + /** + * Gets a boolean flag indicating whether this collection is dirty which means + * its state needs to be synchronized with the database. + * + * @return boolean TRUE if the collection is dirty, FALSE otherwise. + */ + public function isDirty() + { + return $this->isDirty; + } + + /** + * Sets a boolean flag, indicating whether this collection is dirty. + * + * @param boolean $dirty Whether the collection should be marked dirty or not. + * + * @return void + */ + public function setDirty($dirty) + { + $this->isDirty = $dirty; + } + + /** + * Sets the initialized flag of the collection, forcing it into that state. + * + * @param boolean $bool + * + * @return void + */ + public function setInitialized($bool) + { + $this->initialized = $bool; + } + + /** + * {@inheritdoc} + */ + public function remove($key) + { + // TODO: If the keys are persistent as well (not yet implemented) + // and the collection is not initialized and orphanRemoval is + // not used we can issue a straight SQL delete/update on the + // association (table). Without initializing the collection. + $removed = parent::remove($key); + + if ( ! $removed) { + return $removed; + } + + $this->changed(); + + if ($this->association !== null && + $this->association['type'] & ClassMetadata::TO_MANY && + $this->owner && + $this->association['orphanRemoval']) { + $this->em->getUnitOfWork()->scheduleOrphanRemoval($removed); + } + + return $removed; + } + + /** + * {@inheritdoc} + */ + public function removeElement($element) + { + if ( ! $this->initialized && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) { + if ($this->collection->contains($element)) { + return $this->collection->removeElement($element); + } + + $persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association); + + return $persister->removeElement($this, $element); + } + + $removed = parent::removeElement($element); + + if ( ! $removed) { + return $removed; + } + + $this->changed(); + + if ($this->association !== null && + $this->association['type'] & ClassMetadata::TO_MANY && + $this->owner && + $this->association['orphanRemoval']) { + $this->em->getUnitOfWork()->scheduleOrphanRemoval($element); + } + + return $removed; + } + + /** + * {@inheritdoc} + */ + public function containsKey($key) + { + if (! $this->initialized && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY + && isset($this->association['indexBy'])) { + $persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association); + + return $this->collection->containsKey($key) || $persister->containsKey($this, $key); + } + + return parent::containsKey($key); + } + + /** + * {@inheritdoc} + */ + public function contains($element) + { + if ( ! $this->initialized && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) { + $persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association); + + return $this->collection->contains($element) || $persister->contains($this, $element); + } + + return parent::contains($element); + } + + /** + * {@inheritdoc} + */ + public function get($key) + { + if ( ! $this->initialized + && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY + && isset($this->association['indexBy']) + ) { + if (!$this->typeClass->isIdentifierComposite && $this->typeClass->isIdentifier($this->association['indexBy'])) { + return $this->em->find($this->typeClass->name, $key); + } + + return $this->em->getUnitOfWork()->getCollectionPersister($this->association)->get($this, $key); + } + + return parent::get($key); + } + + /** + * {@inheritdoc} + */ + public function count() + { + if (! $this->initialized && $this->association !== null && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) { + $persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association); + + return $persister->count($this) + ($this->isDirty ? $this->collection->count() : 0); + } + + return parent::count(); + } + + /** + * {@inheritdoc} + */ + public function set($key, $value) + { + parent::set($key, $value); + + $this->changed(); + + if (is_object($value) && $this->em) { + $this->em->getUnitOfWork()->cancelOrphanRemoval($value); + } + } + + /** + * {@inheritdoc} + */ + public function add($value) + { + $this->collection->add($value); + + $this->changed(); + + if (is_object($value) && $this->em) { + $this->em->getUnitOfWork()->cancelOrphanRemoval($value); + } + + return true; + } + + /* ArrayAccess implementation */ + + /** + * {@inheritdoc} + */ + public function offsetExists($offset) + { + return $this->containsKey($offset); + } + + /** + * {@inheritdoc} + */ + public function offsetGet($offset) + { + return $this->get($offset); + } + + /** + * {@inheritdoc} + */ + public function offsetSet($offset, $value) + { + if ( ! isset($offset)) { + $this->add($value); + return; + } + + $this->set($offset, $value); + } + + /** + * {@inheritdoc} + */ + public function offsetUnset($offset) + { + return $this->remove($offset); + } + + /** + * {@inheritdoc} + */ + public function isEmpty() + { + return $this->collection->isEmpty() && $this->count() === 0; + } + + /** + * {@inheritdoc} + */ + public function clear() + { + if ($this->initialized && $this->isEmpty()) { + $this->collection->clear(); + + return; + } + + $uow = $this->em->getUnitOfWork(); + + if ($this->association['type'] & ClassMetadata::TO_MANY && + $this->association['orphanRemoval'] && + $this->owner) { + // we need to initialize here, as orphan removal acts like implicit cascadeRemove, + // hence for event listeners we need the objects in memory. + $this->initialize(); + + foreach ($this->collection as $element) { + $uow->scheduleOrphanRemoval($element); + } + } + + $this->collection->clear(); + + $this->initialized = true; // direct call, {@link initialize()} is too expensive + + if ($this->association['isOwningSide'] && $this->owner) { + $this->changed(); + + $uow->scheduleCollectionDeletion($this); + + $this->takeSnapshot(); + } + } + + /** + * Called by PHP when this collection is serialized. Ensures that only the + * elements are properly serialized. + * + * Internal note: Tried to implement Serializable first but that did not work well + * with circular references. This solution seems simpler and works well. + * + * @return array + */ + public function __sleep() + { + return ['collection', 'initialized']; + } + + /** + * Extracts 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|null $length + * + * @return array + */ + public function slice($offset, $length = null) + { + if ( ! $this->initialized && ! $this->isDirty && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) { + $persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association); + + return $persister->slice($this, $offset, $length); + } + + return parent::slice($offset, $length); + } + + /** + * Cleans up internal state of cloned persistent collection. + * + * The following problems have to be prevented: + * 1. Added entities are added to old PC + * 2. New collection is not dirty, if reused on other entity nothing + * changes. + * 3. Snapshot leads to invalid diffs being generated. + * 4. Lazy loading grabs entities from old owner object. + * 5. New collection is connected to old owner and leads to duplicate keys. + * + * @return void + */ + public function __clone() + { + if (is_object($this->collection)) { + $this->collection = clone $this->collection; + } + + $this->initialize(); + + $this->owner = null; + $this->snapshot = []; + + $this->changed(); + } + + /** + * Selects all elements from a selectable that match the expression and + * return a new collection containing these elements. + * + * @param \Doctrine\Common\Collections\Criteria $criteria + * + * @return Collection + * + * @throws \RuntimeException + */ + public function matching(Criteria $criteria) + { + if ($this->isDirty) { + $this->initialize(); + } + + if ($this->initialized) { + return $this->collection->matching($criteria); + } + + if ($this->association['type'] === ClassMetadata::MANY_TO_MANY) { + $persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association); + + return new ArrayCollection($persister->loadCriteria($this, $criteria)); + } + + $builder = Criteria::expr(); + $ownerExpression = $builder->eq($this->backRefFieldName, $this->owner); + $expression = $criteria->getWhereExpression(); + $expression = $expression ? $builder->andX($expression, $ownerExpression) : $ownerExpression; + + $criteria = clone $criteria; + $criteria->where($expression); + $criteria->orderBy($criteria->getOrderings() ?: $this->association['orderBy'] ?? []); + + $persister = $this->em->getUnitOfWork()->getEntityPersister($this->association['targetEntity']); + + return ($this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) + ? new LazyCriteriaCollection($persister, $criteria) + : new ArrayCollection($persister->loadCriteria($criteria)); + } + + /** + * Retrieves the wrapped Collection instance. + * + * @return \Doctrine\Common\Collections\Collection + */ + public function unwrap() + { + return $this->collection; + } + + /** + * {@inheritdoc} + */ + protected function doInitialize() + { + // Has NEW objects added through add(). Remember them. + $newlyAddedDirtyObjects = []; + + if ($this->isDirty) { + $newlyAddedDirtyObjects = $this->collection->toArray(); + } + + $this->collection->clear(); + $this->em->getUnitOfWork()->loadCollection($this); + $this->takeSnapshot(); + + if ($newlyAddedDirtyObjects) { + $this->restoreNewObjectsInDirtyCollection($newlyAddedDirtyObjects); + } + } + + /** + * @param object[] $newObjects + * + * Note: the only reason why this entire looping/complexity is performed via `spl_object_hash` + * is because we want to prevent using `array_udiff()`, which is likely to cause very + * high overhead (complexity of O(n^2)). `array_diff_key()` performs the operation in + * core, which is faster than using a callback for comparisons + */ + private function restoreNewObjectsInDirtyCollection(array $newObjects) : void + { + $loadedObjects = $this->collection->toArray(); + $newObjectsByOid = \array_combine(\array_map('spl_object_hash', $newObjects), $newObjects); + $loadedObjectsByOid = \array_combine(\array_map('spl_object_hash', $loadedObjects), $loadedObjects); + $newObjectsThatWereNotLoaded = \array_diff_key($newObjectsByOid, $loadedObjectsByOid); + + if ($newObjectsThatWereNotLoaded) { + // Reattach NEW objects added through add(), if any. + \array_walk($newObjectsThatWereNotLoaded, [$this->collection, 'add']); + + $this->isDirty = true; + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/AbstractCollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/AbstractCollectionPersister.php new file mode 100644 index 0000000..2e85b67 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/AbstractCollectionPersister.php @@ -0,0 +1,95 @@ +. + */ + +namespace Doctrine\ORM\Persisters\Collection; + +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\UnitOfWork; + +/** + * Base class for all collection persisters. + * + * @since 2.0 + * @author Roman Borschel + */ +abstract class AbstractCollectionPersister implements CollectionPersister +{ + /** + * @var EntityManagerInterface + */ + protected $em; + + /** + * @var \Doctrine\DBAL\Connection + */ + protected $conn; + + /** + * @var UnitOfWork + */ + protected $uow; + + /** + * The database platform. + * + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + protected $platform; + + /** + * The quote strategy. + * + * @var \Doctrine\ORM\Mapping\QuoteStrategy + */ + protected $quoteStrategy; + + /** + * Initializes a new instance of a class derived from AbstractCollectionPersister. + * + * @param EntityManagerInterface $em + */ + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + $this->uow = $em->getUnitOfWork(); + $this->conn = $em->getConnection(); + $this->platform = $this->conn->getDatabasePlatform(); + $this->quoteStrategy = $em->getConfiguration()->getQuoteStrategy(); + } + + /** + * Check if entity is in a valid state for operations. + * + * @param object $entity + * + * @return bool + */ + protected function isValidEntityState($entity) + { + $entityState = $this->uow->getEntityState($entity, UnitOfWork::STATE_NEW); + + if ($entityState === UnitOfWork::STATE_NEW) { + return false; + } + + // If Entity is scheduled for inclusion, it is not in this collection. + // We can assure that because it would have return true before on array check + return ! ($entityState === UnitOfWork::STATE_MANAGED && $this->uow->isScheduledForInsert($entity)); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/CollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/CollectionPersister.php new file mode 100644 index 0000000..36b5706 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/CollectionPersister.php @@ -0,0 +1,122 @@ +. + */ + +namespace Doctrine\ORM\Persisters\Collection; + +use Doctrine\Common\Collections\Criteria; +use Doctrine\ORM\PersistentCollection; + +/** + * Collection persister interface + * Define the behavior that should be implemented by all collection persisters. + * + * @author Fabio B. Silva + * @since 2.5 + */ +interface CollectionPersister +{ + /** + * Deletes the persistent state represented by the given collection. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * + * @return void + */ + public function delete(PersistentCollection $collection); + + /** + * Updates the given collection, synchronizing its state with the database + * by inserting, updating and deleting individual elements. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * + * @return void + */ + public function update(PersistentCollection $collection); + + /** + * Counts the size of this persistent collection. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * + * @return integer + */ + public function count(PersistentCollection $collection); + + /** + * Slices elements. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * @param integer $offset + * @param integer $length + * + * @return array + */ + public function slice(PersistentCollection $collection, $offset, $length = null); + + /** + * Checks for existence of an element. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * @param object $element + * + * @return boolean + */ + public function contains(PersistentCollection $collection, $element); + + /** + * Checks for existence of a key. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * @param mixed $key + * + * @return boolean + */ + public function containsKey(PersistentCollection $collection, $key); + + /** + * Removes an element. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * @param object $element + * + * @return mixed + */ + public function removeElement(PersistentCollection $collection, $element); + + /** + * Gets an element by key. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * @param mixed $index + * + * @return mixed + */ + public function get(PersistentCollection $collection, $index); + + /** + * Loads association entities matching the given Criteria object. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * @param \Doctrine\Common\Collections\Criteria $criteria + * + * @return array + */ + public function loadCriteria(PersistentCollection $collection, Criteria $criteria); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php new file mode 100644 index 0000000..c817f60 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php @@ -0,0 +1,787 @@ +. + */ + +namespace Doctrine\ORM\Persisters\Collection; + +use Doctrine\Common\Collections\Criteria; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Persisters\SqlValueVisitor; +use Doctrine\ORM\PersistentCollection; +use Doctrine\ORM\Query; +use Doctrine\ORM\Utility\PersisterHelper; + +/** + * Persister for many-to-many collections. + * + * @author Roman Borschel + * @author Guilherme Blanco + * @author Alexander + * @since 2.0 + */ +class ManyToManyPersister extends AbstractCollectionPersister +{ + /** + * {@inheritdoc} + */ + public function delete(PersistentCollection $collection) + { + $mapping = $collection->getMapping(); + + if ( ! $mapping['isOwningSide']) { + return; // ignore inverse side + } + + $types = []; + $class = $this->em->getClassMetadata($mapping['sourceEntity']); + + foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) { + $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $class, $this->em); + } + + $this->conn->executeUpdate($this->getDeleteSQL($collection), $this->getDeleteSQLParameters($collection), $types); + } + + /** + * {@inheritdoc} + */ + public function update(PersistentCollection $collection) + { + $mapping = $collection->getMapping(); + + if ( ! $mapping['isOwningSide']) { + return; // ignore inverse side + } + + list($deleteSql, $deleteTypes) = $this->getDeleteRowSQL($collection); + list($insertSql, $insertTypes) = $this->getInsertRowSQL($collection); + + foreach ($collection->getDeleteDiff() as $element) { + $this->conn->executeUpdate( + $deleteSql, + $this->getDeleteRowSQLParameters($collection, $element), + $deleteTypes + ); + } + + foreach ($collection->getInsertDiff() as $element) { + $this->conn->executeUpdate( + $insertSql, + $this->getInsertRowSQLParameters($collection, $element), + $insertTypes + ); + } + } + + /** + * {@inheritdoc} + */ + public function get(PersistentCollection $collection, $index) + { + $mapping = $collection->getMapping(); + + if ( ! isset($mapping['indexBy'])) { + throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections."); + } + + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); + $mappedKey = $mapping['isOwningSide'] + ? $mapping['inversedBy'] + : $mapping['mappedBy']; + + return $persister->load([$mappedKey => $collection->getOwner(), $mapping['indexBy'] => $index], null, $mapping, [], 0, 1); + } + + /** + * {@inheritdoc} + */ + public function count(PersistentCollection $collection) + { + $conditions = []; + $params = []; + $types = []; + $mapping = $collection->getMapping(); + $id = $this->uow->getEntityIdentifier($collection->getOwner()); + $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + $association = ( ! $mapping['isOwningSide']) + ? $targetClass->associationMappings[$mapping['mappedBy']] + : $mapping; + + $joinTableName = $this->quoteStrategy->getJoinTableName($association, $sourceClass, $this->platform); + $joinColumns = ( ! $mapping['isOwningSide']) + ? $association['joinTable']['inverseJoinColumns'] + : $association['joinTable']['joinColumns']; + + foreach ($joinColumns as $joinColumn) { + $columnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $sourceClass, $this->platform); + $referencedName = $joinColumn['referencedColumnName']; + $conditions[] = 't.' . $columnName . ' = ?'; + $params[] = $id[$sourceClass->getFieldForColumn($referencedName)]; + $types[] = PersisterHelper::getTypeOfColumn($referencedName, $sourceClass, $this->em); + } + + list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($mapping); + + if ($filterSql) { + $conditions[] = $filterSql; + } + + // If there is a provided criteria, make part of conditions + // @todo Fix this. Current SQL returns something like: + // + /*if ($criteria && ($expression = $criteria->getWhereExpression()) !== null) { + // A join is needed on the target entity + $targetTableName = $this->quoteStrategy->getTableName($targetClass, $this->platform); + $targetJoinSql = ' JOIN ' . $targetTableName . ' te' + . ' ON' . implode(' AND ', $this->getOnConditionSQL($association)); + + // And criteria conditions needs to be added + $persister = $this->uow->getEntityPersister($targetClass->name); + $visitor = new SqlExpressionVisitor($persister, $targetClass); + $conditions[] = $visitor->dispatch($expression); + + $joinTargetEntitySQL = $targetJoinSql . $joinTargetEntitySQL; + }*/ + + $sql = 'SELECT COUNT(*)' + . ' FROM ' . $joinTableName . ' t' + . $joinTargetEntitySQL + . ' WHERE ' . implode(' AND ', $conditions); + + return $this->conn->fetchColumn($sql, $params, 0, $types); + } + + /** + * {@inheritDoc} + */ + public function slice(PersistentCollection $collection, $offset, $length = null) + { + $mapping = $collection->getMapping(); + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); + + return $persister->getManyToManyCollection($mapping, $collection->getOwner(), $offset, $length); + } + /** + * {@inheritdoc} + */ + public function containsKey(PersistentCollection $collection, $key) + { + $mapping = $collection->getMapping(); + + if ( ! isset($mapping['indexBy'])) { + throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections."); + } + + list($quotedJoinTable, $whereClauses, $params, $types) = $this->getJoinTableRestrictionsWithKey($collection, $key, true); + + $sql = 'SELECT 1 FROM ' . $quotedJoinTable . ' WHERE ' . implode(' AND ', $whereClauses); + + return (bool) $this->conn->fetchColumn($sql, $params, 0, $types); + } + + /** + * {@inheritDoc} + */ + public function contains(PersistentCollection $collection, $element) + { + if ( ! $this->isValidEntityState($element)) { + return false; + } + + list($quotedJoinTable, $whereClauses, $params, $types) = $this->getJoinTableRestrictions($collection, $element, true); + + $sql = 'SELECT 1 FROM ' . $quotedJoinTable . ' WHERE ' . implode(' AND ', $whereClauses); + + return (bool) $this->conn->fetchColumn($sql, $params, 0, $types); + } + + /** + * {@inheritDoc} + */ + public function removeElement(PersistentCollection $collection, $element) + { + if ( ! $this->isValidEntityState($element)) { + return false; + } + + list($quotedJoinTable, $whereClauses, $params, $types) = $this->getJoinTableRestrictions($collection, $element, false); + + $sql = 'DELETE FROM ' . $quotedJoinTable . ' WHERE ' . implode(' AND ', $whereClauses); + + return (bool) $this->conn->executeUpdate($sql, $params, $types); + } + + /** + * {@inheritDoc} + */ + public function loadCriteria(PersistentCollection $collection, Criteria $criteria) + { + $mapping = $collection->getMapping(); + $owner = $collection->getOwner(); + $ownerMetadata = $this->em->getClassMetadata(get_class($owner)); + $id = $this->uow->getEntityIdentifier($owner); + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + $onConditions = $this->getOnConditionSQL($mapping); + $whereClauses = $params = []; + + if ( ! $mapping['isOwningSide']) { + $associationSourceClass = $targetClass; + $mapping = $targetClass->associationMappings[$mapping['mappedBy']]; + $sourceRelationMode = 'relationToTargetKeyColumns'; + } else { + $associationSourceClass = $ownerMetadata; + $sourceRelationMode = 'relationToSourceKeyColumns'; + } + + foreach ($mapping[$sourceRelationMode] as $key => $value) { + $whereClauses[] = sprintf('t.%s = ?', $key); + $params[] = $ownerMetadata->containsForeignIdentifier + ? $id[$ownerMetadata->getFieldForColumn($value)] + : $id[$ownerMetadata->fieldNames[$value]]; + } + + $parameters = $this->expandCriteriaParameters($criteria); + + foreach ($parameters as $parameter) { + [$name, $value, $operator] = $parameter; + + $field = $this->quoteStrategy->getColumnName($name, $targetClass, $this->platform); + $whereClauses[] = sprintf('te.%s %s ?', $field, $operator); + $params[] = $value; + } + + $tableName = $this->quoteStrategy->getTableName($targetClass, $this->platform); + $joinTable = $this->quoteStrategy->getJoinTableName($mapping, $associationSourceClass, $this->platform); + + $rsm = new Query\ResultSetMappingBuilder($this->em); + $rsm->addRootEntityFromClassMetadata($targetClass->name, 'te'); + + $sql = 'SELECT ' . $rsm->generateSelectClause() + . ' FROM ' . $tableName . ' te' + . ' JOIN ' . $joinTable . ' t ON' + . implode(' AND ', $onConditions) + . ' WHERE ' . implode(' AND ', $whereClauses); + + $sql .= $this->getOrderingSql($criteria, $targetClass); + + $sql .= $this->getLimitSql($criteria); + + $stmt = $this->conn->executeQuery($sql, $params); + + return $this + ->em + ->newHydrator(Query::HYDRATE_OBJECT) + ->hydrateAll($stmt, $rsm); + } + + /** + * Generates the filter SQL for a given mapping. + * + * This method is not used for actually grabbing the related entities + * but when the extra-lazy collection methods are called on a filtered + * association. This is why besides the many to many table we also + * have to join in the actual entities table leading to additional + * JOIN. + * + * @param array $mapping Array containing mapping information. + * + * @return string[] ordered tuple: + * - JOIN condition to add to the SQL + * - WHERE condition to add to the SQL + */ + public function getFilterSql($mapping) + { + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + $rootClass = $this->em->getClassMetadata($targetClass->rootEntityName); + $filterSql = $this->generateFilterConditionSQL($rootClass, 'te'); + + if ('' === $filterSql) { + return ['', '']; + } + + // A join is needed if there is filtering on the target entity + $tableName = $this->quoteStrategy->getTableName($rootClass, $this->platform); + $joinSql = ' JOIN ' . $tableName . ' te' + . ' ON' . implode(' AND ', $this->getOnConditionSQL($mapping)); + + return [$joinSql, $filterSql]; + } + + /** + * Generates the filter SQL for a given entity and table alias. + * + * @param ClassMetadata $targetEntity Metadata of the target entity. + * @param string $targetTableAlias The table alias of the joined/selected table. + * + * @return string The SQL query part to add to a query. + */ + protected function generateFilterConditionSQL(ClassMetadata $targetEntity, $targetTableAlias) + { + $filterClauses = []; + + foreach ($this->em->getFilters()->getEnabledFilters() as $filter) { + if ($filterExpr = $filter->addFilterConstraint($targetEntity, $targetTableAlias)) { + $filterClauses[] = '(' . $filterExpr . ')'; + } + } + + return $filterClauses + ? '(' . implode(' AND ', $filterClauses) . ')' + : ''; + } + + /** + * Generate ON condition + * + * @param array $mapping + * + * @return array + */ + protected function getOnConditionSQL($mapping) + { + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + $association = ( ! $mapping['isOwningSide']) + ? $targetClass->associationMappings[$mapping['mappedBy']] + : $mapping; + + $joinColumns = $mapping['isOwningSide'] + ? $association['joinTable']['inverseJoinColumns'] + : $association['joinTable']['joinColumns']; + + $conditions = []; + + foreach ($joinColumns as $joinColumn) { + $joinColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); + $refColumnName = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform); + + $conditions[] = ' t.' . $joinColumnName . ' = ' . 'te.' . $refColumnName; + } + + return $conditions; + } + + /** + * {@inheritdoc} + * + * @override + */ + protected function getDeleteSQL(PersistentCollection $collection) + { + $columns = []; + $mapping = $collection->getMapping(); + $class = $this->em->getClassMetadata(get_class($collection->getOwner())); + $joinTable = $this->quoteStrategy->getJoinTableName($mapping, $class, $this->platform); + + foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) { + $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); + } + + return 'DELETE FROM ' . $joinTable + . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?'; + } + + /** + * {@inheritdoc} + * + * Internal note: Order of the parameters must be the same as the order of the columns in getDeleteSql. + * @override + */ + protected function getDeleteSQLParameters(PersistentCollection $collection) + { + $mapping = $collection->getMapping(); + $identifier = $this->uow->getEntityIdentifier($collection->getOwner()); + + // Optimization for single column identifier + if (count($mapping['relationToSourceKeyColumns']) === 1) { + return [reset($identifier)]; + } + + // Composite identifier + $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); + $params = []; + + foreach ($mapping['relationToSourceKeyColumns'] as $columnName => $refColumnName) { + $params[] = isset($sourceClass->fieldNames[$refColumnName]) + ? $identifier[$sourceClass->fieldNames[$refColumnName]] + : $identifier[$sourceClass->getFieldForColumn($refColumnName)]; + } + + return $params; + } + + /** + * Gets the SQL statement used for deleting a row from the collection. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * + * @return string[]|string[][] ordered tuple containing the SQL to be executed and an array + * of types for bound parameters + */ + protected function getDeleteRowSQL(PersistentCollection $collection) + { + $mapping = $collection->getMapping(); + $class = $this->em->getClassMetadata($mapping['sourceEntity']); + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + $columns = []; + $types = []; + + foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) { + $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); + $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $class, $this->em); + } + + foreach ($mapping['joinTable']['inverseJoinColumns'] as $joinColumn) { + $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); + $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); + } + + return [ + 'DELETE FROM ' . $this->quoteStrategy->getJoinTableName($mapping, $class, $this->platform) + . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?', + $types, + ]; + } + + /** + * Gets the SQL parameters for the corresponding SQL statement to delete the given + * element from the given collection. + * + * Internal note: Order of the parameters must be the same as the order of the columns in getDeleteRowSql. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * @param mixed $element + * + * @return array + */ + protected function getDeleteRowSQLParameters(PersistentCollection $collection, $element) + { + return $this->collectJoinTableColumnParameters($collection, $element); + } + + /** + * Gets the SQL statement used for inserting a row in the collection. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * + * @return string[]|string[][] ordered tuple containing the SQL to be executed and an array + * of types for bound parameters + */ + protected function getInsertRowSQL(PersistentCollection $collection) + { + $columns = []; + $types = []; + $mapping = $collection->getMapping(); + $class = $this->em->getClassMetadata($mapping['sourceEntity']); + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + + foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) { + $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); + $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $class, $this->em); + } + + foreach ($mapping['joinTable']['inverseJoinColumns'] as $joinColumn) { + $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); + $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); + } + + return [ + 'INSERT INTO ' . $this->quoteStrategy->getJoinTableName($mapping, $class, $this->platform) + . ' (' . implode(', ', $columns) . ')' + . ' VALUES' + . ' (' . implode(', ', array_fill(0, count($columns), '?')) . ')', + $types, + ]; + } + + /** + * Gets the SQL parameters for the corresponding SQL statement to insert the given + * element of the given collection into the database. + * + * Internal note: Order of the parameters must be the same as the order of the columns in getInsertRowSql. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * @param mixed $element + * + * @return array + */ + protected function getInsertRowSQLParameters(PersistentCollection $collection, $element) + { + return $this->collectJoinTableColumnParameters($collection, $element); + } + + /** + * Collects the parameters for inserting/deleting on the join table in the order + * of the join table columns as specified in ManyToManyMapping#joinTableColumns. + * + * @param \Doctrine\ORM\PersistentCollection $collection + * @param object $element + * + * @return array + */ + private function collectJoinTableColumnParameters(PersistentCollection $collection, $element) + { + $params = []; + $mapping = $collection->getMapping(); + $isComposite = count($mapping['joinTableColumns']) > 2; + + $identifier1 = $this->uow->getEntityIdentifier($collection->getOwner()); + $identifier2 = $this->uow->getEntityIdentifier($element); + + $class1 = $class2 = null; + if ($isComposite) { + $class1 = $this->em->getClassMetadata(get_class($collection->getOwner())); + $class2 = $collection->getTypeClass(); + } + + foreach ($mapping['joinTableColumns'] as $joinTableColumn) { + $isRelationToSource = isset($mapping['relationToSourceKeyColumns'][$joinTableColumn]); + + if ( ! $isComposite) { + $params[] = $isRelationToSource ? array_pop($identifier1) : array_pop($identifier2); + + continue; + } + + if ($isRelationToSource) { + $params[] = $identifier1[$class1->getFieldForColumn($mapping['relationToSourceKeyColumns'][$joinTableColumn])]; + + continue; + } + + $params[] = $identifier2[$class2->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])]; + } + + return $params; + } + + /** + * @param \Doctrine\ORM\PersistentCollection $collection + * @param string $key + * @param boolean $addFilters Whether the filter SQL should be included or not. + * + * @return array ordered vector: + * - quoted join table name + * - where clauses to be added for filtering + * - parameters to be bound for filtering + * - types of the parameters to be bound for filtering + */ + private function getJoinTableRestrictionsWithKey(PersistentCollection $collection, $key, $addFilters) + { + $filterMapping = $collection->getMapping(); + $mapping = $filterMapping; + $indexBy = $mapping['indexBy']; + $id = $this->uow->getEntityIdentifier($collection->getOwner()); + $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + + if (! $mapping['isOwningSide']) { + $associationSourceClass = $this->em->getClassMetadata($mapping['targetEntity']); + $mapping = $associationSourceClass->associationMappings[$mapping['mappedBy']]; + $joinColumns = $mapping['joinTable']['joinColumns']; + $sourceRelationMode = 'relationToTargetKeyColumns'; + $targetRelationMode = 'relationToSourceKeyColumns'; + } else { + $associationSourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); + $joinColumns = $mapping['joinTable']['inverseJoinColumns']; + $sourceRelationMode = 'relationToSourceKeyColumns'; + $targetRelationMode = 'relationToTargetKeyColumns'; + } + + $quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $associationSourceClass, $this->platform). ' t'; + $whereClauses = []; + $params = []; + $types = []; + + $joinNeeded = ! in_array($indexBy, $targetClass->identifier); + + if ($joinNeeded) { // extra join needed if indexBy is not a @id + $joinConditions = []; + + foreach ($joinColumns as $joinTableColumn) { + $joinConditions[] = 't.' . $joinTableColumn['name'] . ' = tr.' . $joinTableColumn['referencedColumnName']; + } + + $tableName = $this->quoteStrategy->getTableName($targetClass, $this->platform); + $quotedJoinTable .= ' JOIN ' . $tableName . ' tr ON ' . implode(' AND ', $joinConditions); + $columnName = $targetClass->getColumnName($indexBy); + + $whereClauses[] = 'tr.' . $columnName . ' = ?'; + $params[] = $key; + $types[] = PersisterHelper::getTypeOfColumn($columnName, $targetClass, $this->em); + } + + foreach ($mapping['joinTableColumns'] as $joinTableColumn) { + if (isset($mapping[$sourceRelationMode][$joinTableColumn])) { + $column = $mapping[$sourceRelationMode][$joinTableColumn]; + $whereClauses[] = 't.' . $joinTableColumn . ' = ?'; + $params[] = $sourceClass->containsForeignIdentifier + ? $id[$sourceClass->getFieldForColumn($column)] + : $id[$sourceClass->fieldNames[$column]]; + $types[] = PersisterHelper::getTypeOfColumn($column, $sourceClass, $this->em); + } elseif ( ! $joinNeeded) { + $column = $mapping[$targetRelationMode][$joinTableColumn]; + + $whereClauses[] = 't.' . $joinTableColumn . ' = ?'; + $params[] = $key; + $types[] = PersisterHelper::getTypeOfColumn($column, $targetClass, $this->em); + } + } + + if ($addFilters) { + list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($filterMapping); + + if ($filterSql) { + $quotedJoinTable .= ' ' . $joinTargetEntitySQL; + $whereClauses[] = $filterSql; + } + } + + return [$quotedJoinTable, $whereClauses, $params, $types]; + } + + /** + * @param \Doctrine\ORM\PersistentCollection $collection + * @param object $element + * @param boolean $addFilters Whether the filter SQL should be included or not. + * + * @return array ordered vector: + * - quoted join table name + * - where clauses to be added for filtering + * - parameters to be bound for filtering + * - types of the parameters to be bound for filtering + */ + private function getJoinTableRestrictions(PersistentCollection $collection, $element, $addFilters) + { + $filterMapping = $collection->getMapping(); + $mapping = $filterMapping; + + if ( ! $mapping['isOwningSide']) { + $sourceClass = $this->em->getClassMetadata($mapping['targetEntity']); + $targetClass = $this->em->getClassMetadata($mapping['sourceEntity']); + $sourceId = $this->uow->getEntityIdentifier($element); + $targetId = $this->uow->getEntityIdentifier($collection->getOwner()); + + $mapping = $sourceClass->associationMappings[$mapping['mappedBy']]; + } else { + $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + $sourceId = $this->uow->getEntityIdentifier($collection->getOwner()); + $targetId = $this->uow->getEntityIdentifier($element); + } + + $quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $sourceClass, $this->platform); + $whereClauses = []; + $params = []; + $types = []; + + foreach ($mapping['joinTableColumns'] as $joinTableColumn) { + $whereClauses[] = ($addFilters ? 't.' : '') . $joinTableColumn . ' = ?'; + + if (isset($mapping['relationToTargetKeyColumns'][$joinTableColumn])) { + $targetColumn = $mapping['relationToTargetKeyColumns'][$joinTableColumn]; + $params[] = $targetId[$targetClass->getFieldForColumn($targetColumn)]; + $types[] = PersisterHelper::getTypeOfColumn($targetColumn, $targetClass, $this->em); + + continue; + } + + // relationToSourceKeyColumns + $targetColumn = $mapping['relationToSourceKeyColumns'][$joinTableColumn]; + $params[] = $sourceId[$sourceClass->getFieldForColumn($targetColumn)]; + $types[] = PersisterHelper::getTypeOfColumn($targetColumn, $sourceClass, $this->em); + } + + if ($addFilters) { + $quotedJoinTable .= ' t'; + + list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($filterMapping); + + if ($filterSql) { + $quotedJoinTable .= ' ' . $joinTargetEntitySQL; + $whereClauses[] = $filterSql; + } + } + + return [$quotedJoinTable, $whereClauses, $params, $types]; + } + + /** + * Expands Criteria Parameters by walking the expressions and grabbing all + * parameters and types from it. + * + * @param \Doctrine\Common\Collections\Criteria $criteria + * + * @return array + */ + private function expandCriteriaParameters(Criteria $criteria) + { + $expression = $criteria->getWhereExpression(); + + if ($expression === null) { + return []; + } + + $valueVisitor = new SqlValueVisitor(); + + $valueVisitor->dispatch($expression); + + list(, $types) = $valueVisitor->getParamsAndTypes(); + + return $types; + } + + /** + * @param Criteria $criteria + * @param ClassMetadata $targetClass + * @return string + */ + private function getOrderingSql(Criteria $criteria, ClassMetadata $targetClass) + { + $orderings = $criteria->getOrderings(); + if ($orderings) { + $orderBy = []; + foreach ($orderings as $name => $direction) { + $field = $this->quoteStrategy->getColumnName( + $name, + $targetClass, + $this->platform + ); + $orderBy[] = $field . ' ' . $direction; + } + + return ' ORDER BY ' . implode(', ', $orderBy); + } + return ''; + } + + /** + * @param Criteria $criteria + * @return string + * @throws \Doctrine\DBAL\DBALException + */ + private function getLimitSql(Criteria $criteria) + { + $limit = $criteria->getMaxResults(); + $offset = $criteria->getFirstResult(); + if ($limit !== null || $offset !== null) { + return $this->platform->modifyLimitQuery('', $limit, $offset); + } + return ''; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/OneToManyPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/OneToManyPersister.php new file mode 100644 index 0000000..8211507 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/OneToManyPersister.php @@ -0,0 +1,291 @@ +. + */ + +namespace Doctrine\ORM\Persisters\Collection; + +use Doctrine\Common\Collections\Criteria; +use Doctrine\DBAL\Types\Type; +use Doctrine\ORM\PersistentCollection; +use Doctrine\ORM\Utility\PersisterHelper; + +/** + * Persister for one-to-many collections. + * + * @author Roman Borschel + * @author Guilherme Blanco + * @author Alexander + * @since 2.0 + */ +class OneToManyPersister extends AbstractCollectionPersister +{ + /** + * {@inheritdoc} + */ + public function delete(PersistentCollection $collection) + { + // The only valid case here is when you have weak entities. In this + // scenario, you have @OneToMany with orphanRemoval=true, and replacing + // the entire collection with a new would trigger this operation. + $mapping = $collection->getMapping(); + + if ( ! $mapping['orphanRemoval']) { + // Handling non-orphan removal should never happen, as @OneToMany + // can only be inverse side. For owning side one to many, it is + // required to have a join table, which would classify as a ManyToManyPersister. + return; + } + + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + + return $targetClass->isInheritanceTypeJoined() + ? $this->deleteJoinedEntityCollection($collection) + : $this->deleteEntityCollection($collection); + } + + /** + * {@inheritdoc} + */ + public function update(PersistentCollection $collection) + { + // This can never happen. One to many can only be inverse side. + // For owning side one to many, it is required to have a join table, + // then classifying it as a ManyToManyPersister. + return; + } + + /** + * {@inheritdoc} + */ + public function get(PersistentCollection $collection, $index) + { + $mapping = $collection->getMapping(); + + if ( ! isset($mapping['indexBy'])) { + throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections."); + } + + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); + + return $persister->load( + [ + $mapping['mappedBy'] => $collection->getOwner(), + $mapping['indexBy'] => $index + ], + null, + $mapping, + [], + null, + 1 + ); + } + + /** + * {@inheritdoc} + */ + public function count(PersistentCollection $collection) + { + $mapping = $collection->getMapping(); + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); + + // only works with single id identifier entities. Will throw an + // exception in Entity Persisters if that is not the case for the + // 'mappedBy' field. + $criteria = new Criteria(Criteria::expr()->eq($mapping['mappedBy'], $collection->getOwner())); + + return $persister->count($criteria); + } + + /** + * {@inheritdoc} + */ + public function slice(PersistentCollection $collection, $offset, $length = null) + { + $mapping = $collection->getMapping(); + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); + + return $persister->getOneToManyCollection($mapping, $collection->getOwner(), $offset, $length); + } + + /** + * {@inheritdoc} + */ + public function containsKey(PersistentCollection $collection, $key) + { + $mapping = $collection->getMapping(); + + if ( ! isset($mapping['indexBy'])) { + throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections."); + } + + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); + + // only works with single id identifier entities. Will throw an + // exception in Entity Persisters if that is not the case for the + // 'mappedBy' field. + $criteria = new Criteria(); + + $criteria->andWhere(Criteria::expr()->eq($mapping['mappedBy'], $collection->getOwner())); + $criteria->andWhere(Criteria::expr()->eq($mapping['indexBy'], $key)); + + return (bool) $persister->count($criteria); + } + + /** + * {@inheritdoc} + */ + public function contains(PersistentCollection $collection, $element) + { + if ( ! $this->isValidEntityState($element)) { + return false; + } + + $mapping = $collection->getMapping(); + $persister = $this->uow->getEntityPersister($mapping['targetEntity']); + + // only works with single id identifier entities. Will throw an + // exception in Entity Persisters if that is not the case for the + // 'mappedBy' field. + $criteria = new Criteria(Criteria::expr()->eq($mapping['mappedBy'], $collection->getOwner())); + + return $persister->exists($element, $criteria); + } + + /** + * {@inheritdoc} + */ + public function removeElement(PersistentCollection $collection, $element) + { + $mapping = $collection->getMapping(); + + if ( ! $mapping['orphanRemoval']) { + // no-op: this is not the owning side, therefore no operations should be applied + return false; + } + + if ( ! $this->isValidEntityState($element)) { + return false; + } + + return $this + ->uow + ->getEntityPersister($mapping['targetEntity']) + ->delete($element); + } + + /** + * {@inheritdoc} + */ + public function loadCriteria(PersistentCollection $collection, Criteria $criteria) + { + throw new \BadMethodCallException("Filtering a collection by Criteria is not supported by this CollectionPersister."); + } + + /** + * @param PersistentCollection $collection + * + * @return int + * + * @throws \Doctrine\DBAL\DBALException + */ + private function deleteEntityCollection(PersistentCollection $collection) + { + $mapping = $collection->getMapping(); + $identifier = $this->uow->getEntityIdentifier($collection->getOwner()); + $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + $columns = []; + $parameters = []; + + foreach ($targetClass->associationMappings[$mapping['mappedBy']]['joinColumns'] as $joinColumn) { + $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); + $parameters[] = $identifier[$sourceClass->getFieldForColumn($joinColumn['referencedColumnName'])]; + } + + $statement = 'DELETE FROM ' . $this->quoteStrategy->getTableName($targetClass, $this->platform) + . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?'; + + return $this->conn->executeUpdate($statement, $parameters); + } + + /** + * Delete Class Table Inheritance entities. + * A temporary table is needed to keep IDs to be deleted in both parent and child class' tables. + * + * Thanks Steve Ebersole (Hibernate) for idea on how to tackle reliably this scenario, we owe him a beer! =) + * + * @param PersistentCollection $collection + * + * @return int + * + * @throws \Doctrine\DBAL\DBALException + */ + private function deleteJoinedEntityCollection(PersistentCollection $collection) + { + $mapping = $collection->getMapping(); + $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + $rootClass = $this->em->getClassMetadata($targetClass->rootEntityName); + + // 1) Build temporary table DDL + $tempTable = $this->platform->getTemporaryTableName($rootClass->getTemporaryIdTableName()); + $idColumnNames = $rootClass->getIdentifierColumnNames(); + $idColumnList = implode(', ', $idColumnNames); + $columnDefinitions = []; + + foreach ($idColumnNames as $idColumnName) { + $columnDefinitions[$idColumnName] = [ + 'notnull' => true, + 'type' => Type::getType(PersisterHelper::getTypeOfColumn($idColumnName, $rootClass, $this->em)), + ]; + } + + $statement = $this->platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable + . ' (' . $this->platform->getColumnDeclarationListSQL($columnDefinitions) . ')'; + + $this->conn->executeUpdate($statement); + + // 2) Build insert table records into temporary table + $query = $this->em->createQuery( + ' SELECT t0.' . implode(', t0.', $rootClass->getIdentifierFieldNames()) + . ' FROM ' . $targetClass->name . ' t0 WHERE t0.' . $mapping['mappedBy'] . ' = :owner' + )->setParameter('owner', $collection->getOwner()); + + $statement = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ') ' . $query->getSQL(); + $parameters = array_values($sourceClass->getIdentifierValues($collection->getOwner())); + $numDeleted = $this->conn->executeUpdate($statement, $parameters); + + // 3) Delete records on each table in the hierarchy + $classNames = array_merge($targetClass->parentClasses, [$targetClass->name], $targetClass->subClasses); + + foreach (array_reverse($classNames) as $className) { + $tableName = $this->quoteStrategy->getTableName($this->em->getClassMetadata($className), $this->platform); + $statement = 'DELETE FROM ' . $tableName . ' WHERE (' . $idColumnList . ')' + . ' IN (SELECT ' . $idColumnList . ' FROM ' . $tempTable . ')'; + + $this->conn->executeUpdate($statement); + } + + // 4) Drop temporary table + $statement = $this->platform->getDropTemporaryTableSQL($tempTable); + + $this->conn->executeUpdate($statement); + + return $numDeleted; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php new file mode 100644 index 0000000..79472b5 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php @@ -0,0 +1,99 @@ +. + */ + +namespace Doctrine\ORM\Persisters\Entity; + +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\DBAL\Types\Type; + +/** + * Base class for entity persisters that implement a certain inheritance mapping strategy. + * All these persisters are assumed to use a discriminator column to discriminate entity + * types in the hierarchy. + * + * @author Roman Borschel + * @author Benjamin Eberlei + * @since 2.0 + */ +abstract class AbstractEntityInheritancePersister extends BasicEntityPersister +{ + /** + * {@inheritdoc} + */ + protected function prepareInsertData($entity) + { + $data = parent::prepareInsertData($entity); + + // Populate the discriminator column + $discColumn = $this->class->discriminatorColumn; + $this->columnTypes[$discColumn['name']] = $discColumn['type']; + $data[$this->getDiscriminatorColumnTableName()][$discColumn['name']] = $this->class->discriminatorValue; + + return $data; + } + + /** + * Gets the name of the table that contains the discriminator column. + * + * @return string The table name. + */ + abstract protected function getDiscriminatorColumnTableName(); + + /** + * {@inheritdoc} + */ + protected function getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r') + { + $tableAlias = $alias == 'r' ? '' : $alias; + $fieldMapping = $class->fieldMappings[$field]; + $columnAlias = $this->getSQLColumnAlias($fieldMapping['columnName']); + $sql = sprintf( + '%s.%s', + $this->getSQLTableAlias($class->name, $tableAlias), + $this->quoteStrategy->getColumnName($field, $class, $this->platform) + ); + + $this->currentPersisterContext->rsm->addFieldResult($alias, $columnAlias, $field, $class->name); + + if (isset($fieldMapping['requireSQLConversion'])) { + $type = Type::getType($fieldMapping['type']); + $sql = $type->convertToPHPValueSQL($sql, $this->platform); + } + + return $sql . ' AS ' . $columnAlias; + } + + /** + * @param string $tableAlias + * @param string $joinColumnName + * @param string $quotedColumnName + * + * @param string $type + * + * @return string + */ + protected function getSelectJoinColumnSQL($tableAlias, $joinColumnName, $quotedColumnName, $type) + { + $columnAlias = $this->getSQLColumnAlias($joinColumnName); + + $this->currentPersisterContext->rsm->addMetaResult('r', $columnAlias, $joinColumnName, false, $type); + + return $tableAlias . '.' . $quotedColumnName . ' AS ' . $columnAlias; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php new file mode 100644 index 0000000..ea1f2ef --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php @@ -0,0 +1,2095 @@ +. + */ + +namespace Doctrine\ORM\Persisters\Entity; + +use Doctrine\Common\Collections\Criteria; +use Doctrine\Common\Collections\Expr\Comparison; +use Doctrine\Common\Util\ClassUtils; +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\LockMode; +use Doctrine\DBAL\Types\Type; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Mapping\MappingException; +use Doctrine\ORM\OptimisticLockException; +use Doctrine\ORM\ORMException; +use Doctrine\ORM\PersistentCollection; +use Doctrine\ORM\Persisters\SqlExpressionVisitor; +use Doctrine\ORM\Persisters\SqlValueVisitor; +use Doctrine\ORM\Query; +use Doctrine\ORM\UnitOfWork; +use Doctrine\ORM\Utility\IdentifierFlattener; +use Doctrine\ORM\Utility\PersisterHelper; +use function array_map; +use function array_merge; +use function assert; +use function reset; + +/** + * A BasicEntityPersister maps an entity to a single table in a relational database. + * + * A persister is always responsible for a single entity type. + * + * EntityPersisters are used during a UnitOfWork to apply any changes to the persistent + * state of entities onto a relational database when the UnitOfWork is committed, + * as well as for basic querying of entities and their associations (not DQL). + * + * The persisting operations that are invoked during a commit of a UnitOfWork to + * persist the persistent entity state are: + * + * - {@link addInsert} : To schedule an entity for insertion. + * - {@link executeInserts} : To execute all scheduled insertions. + * - {@link update} : To update the persistent state of an entity. + * - {@link delete} : To delete the persistent state of an entity. + * + * As can be seen from the above list, insertions are batched and executed all at once + * for increased efficiency. + * + * The querying operations invoked during a UnitOfWork, either through direct find + * requests or lazy-loading, are the following: + * + * - {@link load} : Loads (the state of) a single, managed entity. + * - {@link loadAll} : Loads multiple, managed entities. + * - {@link loadOneToOneEntity} : Loads a one/many-to-one entity association (lazy-loading). + * - {@link loadOneToManyCollection} : Loads a one-to-many entity association (lazy-loading). + * - {@link loadManyToManyCollection} : Loads a many-to-many entity association (lazy-loading). + * + * The BasicEntityPersister implementation provides the default behavior for + * persisting and querying entities that are mapped to a single database table. + * + * Subclasses can be created to provide custom persisting and querying strategies, + * i.e. spanning multiple tables. + * + * @author Roman Borschel + * @author Giorgio Sironi + * @author Benjamin Eberlei + * @author Alexander + * @author Fabio B. Silva + * @author Rob Caiger + * @since 2.0 + */ +class BasicEntityPersister implements EntityPersister +{ + /** + * @var array + */ + static private $comparisonMap = [ + Comparison::EQ => '= %s', + Comparison::IS => '= %s', + Comparison::NEQ => '!= %s', + Comparison::GT => '> %s', + Comparison::GTE => '>= %s', + Comparison::LT => '< %s', + Comparison::LTE => '<= %s', + Comparison::IN => 'IN (%s)', + Comparison::NIN => 'NOT IN (%s)', + Comparison::CONTAINS => 'LIKE %s', + Comparison::STARTS_WITH => 'LIKE %s', + Comparison::ENDS_WITH => 'LIKE %s', + ]; + + /** + * Metadata object that describes the mapping of the mapped entity class. + * + * @var \Doctrine\ORM\Mapping\ClassMetadata + */ + protected $class; + + /** + * The underlying DBAL Connection of the used EntityManager. + * + * @var \Doctrine\DBAL\Connection $conn + */ + protected $conn; + + /** + * The database platform. + * + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + protected $platform; + + /** + * The EntityManager instance. + * + * @var EntityManagerInterface + */ + protected $em; + + /** + * Queued inserts. + * + * @var array + */ + protected $queuedInserts = []; + + /** + * The map of column names to DBAL mapping types of all prepared columns used + * when INSERTing or UPDATEing an entity. + * + * @var array + * + * @see prepareInsertData($entity) + * @see prepareUpdateData($entity) + */ + protected $columnTypes = []; + + /** + * The map of quoted column names. + * + * @var array + * + * @see prepareInsertData($entity) + * @see prepareUpdateData($entity) + */ + protected $quotedColumns = []; + + /** + * The INSERT SQL statement used for entities handled by this persister. + * This SQL is only generated once per request, if at all. + * + * @var string + */ + private $insertSql; + + /** + * The quote strategy. + * + * @var \Doctrine\ORM\Mapping\QuoteStrategy + */ + protected $quoteStrategy; + + /** + * The IdentifierFlattener used for manipulating identifiers + * + * @var \Doctrine\ORM\Utility\IdentifierFlattener + */ + private $identifierFlattener; + + /** + * @var CachedPersisterContext + */ + protected $currentPersisterContext; + + /** + * @var CachedPersisterContext + */ + private $limitsHandlingContext; + + /** + * @var CachedPersisterContext + */ + private $noLimitsContext; + + /** + * Initializes a new BasicEntityPersister that uses the given EntityManager + * and persists instances of the class described by the given ClassMetadata descriptor. + * + * @param EntityManagerInterface $em + * @param ClassMetadata $class + */ + public function __construct(EntityManagerInterface $em, ClassMetadata $class) + { + $this->em = $em; + $this->class = $class; + $this->conn = $em->getConnection(); + $this->platform = $this->conn->getDatabasePlatform(); + $this->quoteStrategy = $em->getConfiguration()->getQuoteStrategy(); + $this->identifierFlattener = new IdentifierFlattener($em->getUnitOfWork(), $em->getMetadataFactory()); + $this->noLimitsContext = $this->currentPersisterContext = new CachedPersisterContext( + $class, + new Query\ResultSetMapping(), + false + ); + $this->limitsHandlingContext = new CachedPersisterContext( + $class, + new Query\ResultSetMapping(), + true + ); + } + + /** + * {@inheritdoc} + */ + public function getClassMetadata() + { + return $this->class; + } + + /** + * {@inheritdoc} + */ + public function getResultSetMapping() + { + return $this->currentPersisterContext->rsm; + } + + /** + * {@inheritdoc} + */ + public function addInsert($entity) + { + $this->queuedInserts[spl_object_hash($entity)] = $entity; + } + + /** + * {@inheritdoc} + */ + public function getInserts() + { + return $this->queuedInserts; + } + + /** + * {@inheritdoc} + */ + public function executeInserts() + { + if ( ! $this->queuedInserts) { + return []; + } + + $postInsertIds = []; + $idGenerator = $this->class->idGenerator; + $isPostInsertId = $idGenerator->isPostInsertGenerator(); + + $stmt = $this->conn->prepare($this->getInsertSQL()); + $tableName = $this->class->getTableName(); + + foreach ($this->queuedInserts as $entity) { + $insertData = $this->prepareInsertData($entity); + + if (isset($insertData[$tableName])) { + $paramIndex = 1; + + foreach ($insertData[$tableName] as $column => $value) { + $stmt->bindValue($paramIndex++, $value, $this->columnTypes[$column]); + } + } + + $stmt->execute(); + + if ($isPostInsertId) { + $generatedId = $idGenerator->generate($this->em, $entity); + $id = [ + $this->class->identifier[0] => $generatedId + ]; + $postInsertIds[] = [ + 'generatedId' => $generatedId, + 'entity' => $entity, + ]; + } else { + $id = $this->class->getIdentifierValues($entity); + } + + if ($this->class->isVersioned) { + $this->assignDefaultVersionValue($entity, $id); + } + } + + $stmt->closeCursor(); + $this->queuedInserts = []; + + return $postInsertIds; + } + + /** + * Retrieves the default version value which was created + * by the preceding INSERT statement and assigns it back in to the + * entities version field. + * + * @param object $entity + * @param array $id + * + * @return void + */ + protected function assignDefaultVersionValue($entity, array $id) + { + $value = $this->fetchVersionValue($this->class, $id); + + $this->class->setFieldValue($entity, $this->class->versionField, $value); + } + + /** + * Fetches the current version value of a versioned entity. + * + * @param \Doctrine\ORM\Mapping\ClassMetadata $versionedClass + * @param array $id + * + * @return mixed + */ + protected function fetchVersionValue($versionedClass, array $id) + { + $versionField = $versionedClass->versionField; + $fieldMapping = $versionedClass->fieldMappings[$versionField]; + $tableName = $this->quoteStrategy->getTableName($versionedClass, $this->platform); + $identifier = $this->quoteStrategy->getIdentifierColumnNames($versionedClass, $this->platform); + $columnName = $this->quoteStrategy->getColumnName($versionField, $versionedClass, $this->platform); + + // FIXME: Order with composite keys might not be correct + $sql = 'SELECT ' . $columnName + . ' FROM ' . $tableName + . ' WHERE ' . implode(' = ? AND ', $identifier) . ' = ?'; + + + $flatId = $this->identifierFlattener->flattenIdentifier($versionedClass, $id); + + $value = $this->conn->fetchColumn( + $sql, + array_values($flatId), + 0, + $this->extractIdentifierTypes($id, $versionedClass) + ); + + return Type::getType($fieldMapping['type'])->convertToPHPValue($value, $this->platform); + } + + private function extractIdentifierTypes(array $id, ClassMetadata $versionedClass) : array + { + $types = []; + + foreach ($id as $field => $value) { + $types = array_merge($types, $this->getTypes($field, $value, $versionedClass)); + } + + return $types; + } + + /** + * {@inheritdoc} + */ + public function update($entity) + { + $tableName = $this->class->getTableName(); + $updateData = $this->prepareUpdateData($entity); + + if ( ! isset($updateData[$tableName]) || ! ($data = $updateData[$tableName])) { + return; + } + + $isVersioned = $this->class->isVersioned; + $quotedTableName = $this->quoteStrategy->getTableName($this->class, $this->platform); + + $this->updateTable($entity, $quotedTableName, $data, $isVersioned); + + if ($isVersioned) { + $id = $this->em->getUnitOfWork()->getEntityIdentifier($entity); + + $this->assignDefaultVersionValue($entity, $id); + } + } + + /** + * Performs an UPDATE statement for an entity on a specific table. + * The UPDATE can optionally be versioned, which requires the entity to have a version field. + * + * @param object $entity The entity object being updated. + * @param string $quotedTableName The quoted name of the table to apply the UPDATE on. + * @param array $updateData The map of columns to update (column => value). + * @param boolean $versioned Whether the UPDATE should be versioned. + * + * @return void + * + * @throws \Doctrine\ORM\ORMException + * @throws \Doctrine\ORM\OptimisticLockException + */ + protected final function updateTable($entity, $quotedTableName, array $updateData, $versioned = false) + { + $set = []; + $types = []; + $params = []; + + foreach ($updateData as $columnName => $value) { + $placeholder = '?'; + $column = $columnName; + + switch (true) { + case isset($this->class->fieldNames[$columnName]): + $fieldName = $this->class->fieldNames[$columnName]; + $column = $this->quoteStrategy->getColumnName($fieldName, $this->class, $this->platform); + + if (isset($this->class->fieldMappings[$fieldName]['requireSQLConversion'])) { + $type = Type::getType($this->columnTypes[$columnName]); + $placeholder = $type->convertToDatabaseValueSQL('?', $this->platform); + } + + break; + + case isset($this->quotedColumns[$columnName]): + $column = $this->quotedColumns[$columnName]; + + break; + } + + $params[] = $value; + $set[] = $column . ' = ' . $placeholder; + $types[] = $this->columnTypes[$columnName]; + } + + $where = []; + $identifier = $this->em->getUnitOfWork()->getEntityIdentifier($entity); + + foreach ($this->class->identifier as $idField) { + if ( ! isset($this->class->associationMappings[$idField])) { + $params[] = $identifier[$idField]; + $types[] = $this->class->fieldMappings[$idField]['type']; + $where[] = $this->quoteStrategy->getColumnName($idField, $this->class, $this->platform); + + continue; + } + + $params[] = $identifier[$idField]; + $where[] = $this->quoteStrategy->getJoinColumnName( + $this->class->associationMappings[$idField]['joinColumns'][0], + $this->class, + $this->platform + ); + + $targetMapping = $this->em->getClassMetadata($this->class->associationMappings[$idField]['targetEntity']); + $targetType = PersisterHelper::getTypeOfField($targetMapping->identifier[0], $targetMapping, $this->em); + + if ($targetType === []) { + throw ORMException::unrecognizedField($targetMapping->identifier[0]); + } + + $types[] = reset($targetType); + } + + if ($versioned) { + $versionField = $this->class->versionField; + $versionFieldType = $this->class->fieldMappings[$versionField]['type']; + $versionColumn = $this->quoteStrategy->getColumnName($versionField, $this->class, $this->platform); + + $where[] = $versionColumn; + $types[] = $this->class->fieldMappings[$versionField]['type']; + $params[] = $this->class->reflFields[$versionField]->getValue($entity); + + switch ($versionFieldType) { + case Type::SMALLINT: + case Type::INTEGER: + case Type::BIGINT: + $set[] = $versionColumn . ' = ' . $versionColumn . ' + 1'; + break; + + case Type::DATETIME: + $set[] = $versionColumn . ' = CURRENT_TIMESTAMP'; + break; + } + } + + $sql = 'UPDATE ' . $quotedTableName + . ' SET ' . implode(', ', $set) + . ' WHERE ' . implode(' = ? AND ', $where) . ' = ?'; + + $result = $this->conn->executeUpdate($sql, $params, $types); + + if ($versioned && ! $result) { + throw OptimisticLockException::lockFailed($entity); + } + } + + /** + * @todo Add check for platform if it supports foreign keys/cascading. + * + * @param array $identifier + * + * @return void + */ + protected function deleteJoinTableRecords($identifier) + { + foreach ($this->class->associationMappings as $mapping) { + if ($mapping['type'] !== ClassMetadata::MANY_TO_MANY) { + continue; + } + + // @Todo this only covers scenarios with no inheritance or of the same level. Is there something + // like self-referential relationship between different levels of an inheritance hierarchy? I hope not! + $selfReferential = ($mapping['targetEntity'] == $mapping['sourceEntity']); + $class = $this->class; + $association = $mapping; + $otherColumns = []; + $otherKeys = []; + $keys = []; + + if ( ! $mapping['isOwningSide']) { + $class = $this->em->getClassMetadata($mapping['targetEntity']); + $association = $class->associationMappings[$mapping['mappedBy']]; + } + + $joinColumns = $mapping['isOwningSide'] + ? $association['joinTable']['joinColumns'] + : $association['joinTable']['inverseJoinColumns']; + + + if ($selfReferential) { + $otherColumns = (! $mapping['isOwningSide']) + ? $association['joinTable']['joinColumns'] + : $association['joinTable']['inverseJoinColumns']; + } + + foreach ($joinColumns as $joinColumn) { + $keys[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); + } + + foreach ($otherColumns as $joinColumn) { + $otherKeys[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); + } + + if (isset($mapping['isOnDeleteCascade'])) { + continue; + } + + $joinTableName = $this->quoteStrategy->getJoinTableName($association, $this->class, $this->platform); + + $this->conn->delete($joinTableName, array_combine($keys, $identifier)); + + if ($selfReferential) { + $this->conn->delete($joinTableName, array_combine($otherKeys, $identifier)); + } + } + } + + /** + * {@inheritdoc} + */ + public function delete($entity) + { + $class = $this->class; + $identifier = $this->em->getUnitOfWork()->getEntityIdentifier($entity); + $tableName = $this->quoteStrategy->getTableName($class, $this->platform); + $idColumns = $this->quoteStrategy->getIdentifierColumnNames($class, $this->platform); + $id = array_combine($idColumns, $identifier); + $types = $this->getClassIdentifiersTypes($class); + + $this->deleteJoinTableRecords($identifier); + + return (bool) $this->conn->delete($tableName, $id, $types); + } + + /** + * Prepares the changeset of an entity for database insertion (UPDATE). + * + * The changeset is obtained from the currently running UnitOfWork. + * + * During this preparation the array that is passed as the second parameter is filled with + * => pairs, grouped by table name. + * + * Example: + * + * array( + * 'foo_table' => array('column1' => 'value1', 'column2' => 'value2', ...), + * 'bar_table' => array('columnX' => 'valueX', 'columnY' => 'valueY', ...), + * ... + * ) + * + * + * @param object $entity The entity for which to prepare the data. + * + * @return array The prepared data. + */ + protected function prepareUpdateData($entity) + { + $versionField = null; + $result = []; + $uow = $this->em->getUnitOfWork(); + + if (($versioned = $this->class->isVersioned) != false) { + $versionField = $this->class->versionField; + } + + foreach ($uow->getEntityChangeSet($entity) as $field => $change) { + if (isset($versionField) && $versionField == $field) { + continue; + } + + if (isset($this->class->embeddedClasses[$field])) { + continue; + } + + $newVal = $change[1]; + + if ( ! isset($this->class->associationMappings[$field])) { + $fieldMapping = $this->class->fieldMappings[$field]; + $columnName = $fieldMapping['columnName']; + + $this->columnTypes[$columnName] = $fieldMapping['type']; + + $result[$this->getOwningTable($field)][$columnName] = $newVal; + + continue; + } + + $assoc = $this->class->associationMappings[$field]; + + // Only owning side of x-1 associations can have a FK column. + if ( ! $assoc['isOwningSide'] || ! ($assoc['type'] & ClassMetadata::TO_ONE)) { + continue; + } + + if ($newVal !== null) { + $oid = spl_object_hash($newVal); + + if (isset($this->queuedInserts[$oid]) || $uow->isScheduledForInsert($newVal)) { + // The associated entity $newVal is not yet persisted, so we must + // set $newVal = null, in order to insert a null value and schedule an + // extra update on the UnitOfWork. + $uow->scheduleExtraUpdate($entity, [$field => [null, $newVal]]); + + $newVal = null; + } + } + + $newValId = null; + + if ($newVal !== null) { + $newValId = $uow->getEntityIdentifier($newVal); + } + + $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); + $owningTable = $this->getOwningTable($field); + + foreach ($assoc['joinColumns'] as $joinColumn) { + $sourceColumn = $joinColumn['name']; + $targetColumn = $joinColumn['referencedColumnName']; + $quotedColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); + + $this->quotedColumns[$sourceColumn] = $quotedColumn; + $this->columnTypes[$sourceColumn] = PersisterHelper::getTypeOfColumn($targetColumn, $targetClass, $this->em); + $result[$owningTable][$sourceColumn] = $newValId + ? $newValId[$targetClass->getFieldForColumn($targetColumn)] + : null; + } + } + + return $result; + } + + /** + * Prepares the data changeset of a managed entity for database insertion (initial INSERT). + * The changeset of the entity is obtained from the currently running UnitOfWork. + * + * The default insert data preparation is the same as for updates. + * + * @param object $entity The entity for which to prepare the data. + * + * @return array The prepared data for the tables to update. + * + * @see prepareUpdateData + */ + protected function prepareInsertData($entity) + { + return $this->prepareUpdateData($entity); + } + + /** + * {@inheritdoc} + */ + public function getOwningTable($fieldName) + { + return $this->class->getTableName(); + } + + /** + * {@inheritdoc} + */ + public function load(array $criteria, $entity = null, $assoc = null, array $hints = [], $lockMode = null, $limit = null, array $orderBy = null) + { + $this->switchPersisterContext(null, $limit); + + $sql = $this->getSelectSQL($criteria, $assoc, $lockMode, $limit, null, $orderBy); + list($params, $types) = $this->expandParameters($criteria); + $stmt = $this->conn->executeQuery($sql, $params, $types); + + if ($entity !== null) { + $hints[Query::HINT_REFRESH] = true; + $hints[Query::HINT_REFRESH_ENTITY] = $entity; + } + + $hydrator = $this->em->newHydrator($this->currentPersisterContext->selectJoinSql ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT); + $entities = $hydrator->hydrateAll($stmt, $this->currentPersisterContext->rsm, $hints); + + return $entities ? $entities[0] : null; + } + + /** + * {@inheritdoc} + */ + public function loadById(array $identifier, $entity = null) + { + return $this->load($identifier, $entity); + } + + /** + * {@inheritdoc} + */ + public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifier = []) + { + if (($foundEntity = $this->em->getUnitOfWork()->tryGetById($identifier, $assoc['targetEntity'])) != false) { + return $foundEntity; + } + + $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); + + if ($assoc['isOwningSide']) { + $isInverseSingleValued = $assoc['inversedBy'] && ! $targetClass->isCollectionValuedAssociation($assoc['inversedBy']); + + // Mark inverse side as fetched in the hints, otherwise the UoW would + // try to load it in a separate query (remember: to-one inverse sides can not be lazy). + $hints = []; + + if ($isInverseSingleValued) { + $hints['fetched']["r"][$assoc['inversedBy']] = true; + } + + /* cascade read-only status + if ($this->em->getUnitOfWork()->isReadOnly($sourceEntity)) { + $hints[Query::HINT_READ_ONLY] = true; + } + */ + + $targetEntity = $this->load($identifier, null, $assoc, $hints); + + // Complete bidirectional association, if necessary + if ($targetEntity !== null && $isInverseSingleValued) { + $targetClass->reflFields[$assoc['inversedBy']]->setValue($targetEntity, $sourceEntity); + } + + return $targetEntity; + } + + $sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']); + $owningAssoc = $targetClass->getAssociationMapping($assoc['mappedBy']); + + $computedIdentifier = []; + + // TRICKY: since the association is specular source and target are flipped + foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) { + if ( ! isset($sourceClass->fieldNames[$sourceKeyColumn])) { + throw MappingException::joinColumnMustPointToMappedField( + $sourceClass->name, $sourceKeyColumn + ); + } + + $computedIdentifier[$targetClass->getFieldForColumn($targetKeyColumn)] = + $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity); + } + + $targetEntity = $this->load($computedIdentifier, null, $assoc); + + if ($targetEntity !== null) { + $targetClass->setFieldValue($targetEntity, $assoc['mappedBy'], $sourceEntity); + } + + return $targetEntity; + } + + /** + * {@inheritdoc} + */ + public function refresh(array $id, $entity, $lockMode = null) + { + $sql = $this->getSelectSQL($id, null, $lockMode); + list($params, $types) = $this->expandParameters($id); + $stmt = $this->conn->executeQuery($sql, $params, $types); + + $hydrator = $this->em->newHydrator(Query::HYDRATE_OBJECT); + $hydrator->hydrateAll($stmt, $this->currentPersisterContext->rsm, [Query::HINT_REFRESH => true]); + } + + /** + * {@inheritDoc} + */ + public function count($criteria = []) + { + $sql = $this->getCountSQL($criteria); + + list($params, $types) = ($criteria instanceof Criteria) + ? $this->expandCriteriaParameters($criteria) + : $this->expandParameters($criteria); + + return (int) $this->conn->executeQuery($sql, $params, $types)->fetchColumn(); + } + + /** + * {@inheritdoc} + */ + public function loadCriteria(Criteria $criteria) + { + $orderBy = $criteria->getOrderings(); + $limit = $criteria->getMaxResults(); + $offset = $criteria->getFirstResult(); + $query = $this->getSelectSQL($criteria, null, null, $limit, $offset, $orderBy); + + list($params, $types) = $this->expandCriteriaParameters($criteria); + + $stmt = $this->conn->executeQuery($query, $params, $types); + $hydrator = $this->em->newHydrator(($this->currentPersisterContext->selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT); + + return $hydrator->hydrateAll($stmt, $this->currentPersisterContext->rsm, [UnitOfWork::HINT_DEFEREAGERLOAD => true] + ); + } + + /** + * {@inheritdoc} + */ + public function expandCriteriaParameters(Criteria $criteria) + { + $expression = $criteria->getWhereExpression(); + $sqlParams = []; + $sqlTypes = []; + + if ($expression === null) { + return [$sqlParams, $sqlTypes]; + } + + $valueVisitor = new SqlValueVisitor(); + + $valueVisitor->dispatch($expression); + + list($params, $types) = $valueVisitor->getParamsAndTypes(); + + foreach ($params as $param) { + $sqlParams = array_merge($sqlParams, $this->getValues($param)); + } + + foreach ($types as $type) { + list ($field, $value) = $type; + $sqlTypes = array_merge($sqlTypes, $this->getTypes($field, $value, $this->class)); + } + + return [$sqlParams, $sqlTypes]; + } + + /** + * {@inheritdoc} + */ + public function loadAll(array $criteria = [], array $orderBy = null, $limit = null, $offset = null) + { + $this->switchPersisterContext($offset, $limit); + + $sql = $this->getSelectSQL($criteria, null, null, $limit, $offset, $orderBy); + list($params, $types) = $this->expandParameters($criteria); + $stmt = $this->conn->executeQuery($sql, $params, $types); + + $hydrator = $this->em->newHydrator(($this->currentPersisterContext->selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT); + + return $hydrator->hydrateAll($stmt, $this->currentPersisterContext->rsm, [UnitOfWork::HINT_DEFEREAGERLOAD => true] + ); + } + + /** + * {@inheritdoc} + */ + public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null) + { + $this->switchPersisterContext($offset, $limit); + + $stmt = $this->getManyToManyStatement($assoc, $sourceEntity, $offset, $limit); + + return $this->loadArrayFromStatement($assoc, $stmt); + } + + /** + * Loads an array of entities from a given DBAL statement. + * + * @param array $assoc + * @param \Doctrine\DBAL\Statement $stmt + * + * @return array + */ + private function loadArrayFromStatement($assoc, $stmt) + { + $rsm = $this->currentPersisterContext->rsm; + $hints = [UnitOfWork::HINT_DEFEREAGERLOAD => true]; + + if (isset($assoc['indexBy'])) { + $rsm = clone ($this->currentPersisterContext->rsm); // this is necessary because the "default rsm" should be changed. + $rsm->addIndexBy('r', $assoc['indexBy']); + } + + return $this->em->newHydrator(Query::HYDRATE_OBJECT)->hydrateAll($stmt, $rsm, $hints); + } + + /** + * Hydrates a collection from a given DBAL statement. + * + * @param array $assoc + * @param \Doctrine\DBAL\Statement $stmt + * @param PersistentCollection $coll + * + * @return array + */ + private function loadCollectionFromStatement($assoc, $stmt, $coll) + { + $rsm = $this->currentPersisterContext->rsm; + $hints = [ + UnitOfWork::HINT_DEFEREAGERLOAD => true, + 'collection' => $coll + ]; + + if (isset($assoc['indexBy'])) { + $rsm = clone ($this->currentPersisterContext->rsm); // this is necessary because the "default rsm" should be changed. + $rsm->addIndexBy('r', $assoc['indexBy']); + } + + return $this->em->newHydrator(Query::HYDRATE_OBJECT)->hydrateAll($stmt, $rsm, $hints); + } + + /** + * {@inheritdoc} + */ + public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll) + { + $stmt = $this->getManyToManyStatement($assoc, $sourceEntity); + + return $this->loadCollectionFromStatement($assoc, $stmt, $coll); + } + + /** + * @param array $assoc + * @param object $sourceEntity + * @param int|null $offset + * @param int|null $limit + * + * @return \Doctrine\DBAL\Driver\Statement + * + * @throws \Doctrine\ORM\Mapping\MappingException + */ + private function getManyToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null) + { + $this->switchPersisterContext($offset, $limit); + + $sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']); + $class = $sourceClass; + $association = $assoc; + $criteria = []; + $parameters = []; + + if ( ! $assoc['isOwningSide']) { + $class = $this->em->getClassMetadata($assoc['targetEntity']); + $association = $class->associationMappings[$assoc['mappedBy']]; + } + + $joinColumns = $assoc['isOwningSide'] + ? $association['joinTable']['joinColumns'] + : $association['joinTable']['inverseJoinColumns']; + + $quotedJoinTable = $this->quoteStrategy->getJoinTableName($association, $class, $this->platform); + + foreach ($joinColumns as $joinColumn) { + $sourceKeyColumn = $joinColumn['referencedColumnName']; + $quotedKeyColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); + + switch (true) { + case $sourceClass->containsForeignIdentifier: + $field = $sourceClass->getFieldForColumn($sourceKeyColumn); + $value = $sourceClass->reflFields[$field]->getValue($sourceEntity); + + if (isset($sourceClass->associationMappings[$field])) { + $value = $this->em->getUnitOfWork()->getEntityIdentifier($value); + $value = $value[$this->em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]]; + } + + break; + + case isset($sourceClass->fieldNames[$sourceKeyColumn]): + $field = $sourceClass->fieldNames[$sourceKeyColumn]; + $value = $sourceClass->reflFields[$field]->getValue($sourceEntity); + + break; + + default: + throw MappingException::joinColumnMustPointToMappedField( + $sourceClass->name, $sourceKeyColumn + ); + } + + $criteria[$quotedJoinTable . '.' . $quotedKeyColumn] = $value; + $parameters[] = [ + 'value' => $value, + 'field' => $field, + 'class' => $sourceClass, + ]; + } + + $sql = $this->getSelectSQL($criteria, $assoc, null, $limit, $offset); + list($params, $types) = $this->expandToManyParameters($parameters); + + return $this->conn->executeQuery($sql, $params, $types); + } + + /** + * {@inheritdoc} + */ + public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, array $orderBy = null) + { + $this->switchPersisterContext($offset, $limit); + + $lockSql = ''; + $joinSql = ''; + $orderBySql = ''; + + if ($assoc != null && $assoc['type'] == ClassMetadata::MANY_TO_MANY) { + $joinSql = $this->getSelectManyToManyJoinSQL($assoc); + } + + if (isset($assoc['orderBy'])) { + $orderBy = $assoc['orderBy']; + } + + if ($orderBy) { + $orderBySql = $this->getOrderBySQL($orderBy, $this->getSQLTableAlias($this->class->name)); + } + + $conditionSql = ($criteria instanceof Criteria) + ? $this->getSelectConditionCriteriaSQL($criteria) + : $this->getSelectConditionSQL($criteria, $assoc); + + switch ($lockMode) { + case LockMode::PESSIMISTIC_READ: + $lockSql = ' ' . $this->platform->getReadLockSQL(); + break; + + case LockMode::PESSIMISTIC_WRITE: + $lockSql = ' ' . $this->platform->getWriteLockSQL(); + break; + } + + $columnList = $this->getSelectColumnsSQL(); + $tableAlias = $this->getSQLTableAlias($this->class->name); + $filterSql = $this->generateFilterConditionSQL($this->class, $tableAlias); + $tableName = $this->quoteStrategy->getTableName($this->class, $this->platform); + + if ('' !== $filterSql) { + $conditionSql = $conditionSql + ? $conditionSql . ' AND ' . $filterSql + : $filterSql; + } + + $select = 'SELECT ' . $columnList; + $from = ' FROM ' . $tableName . ' '. $tableAlias; + $join = $this->currentPersisterContext->selectJoinSql . $joinSql; + $where = ($conditionSql ? ' WHERE ' . $conditionSql : ''); + $lock = $this->platform->appendLockHint($from, $lockMode); + $query = $select + . $lock + . $join + . $where + . $orderBySql; + + return $this->platform->modifyLimitQuery($query, $limit, $offset) . $lockSql; + } + + /** + * {@inheritDoc} + */ + public function getCountSQL($criteria = []) + { + $tableName = $this->quoteStrategy->getTableName($this->class, $this->platform); + $tableAlias = $this->getSQLTableAlias($this->class->name); + + $conditionSql = ($criteria instanceof Criteria) + ? $this->getSelectConditionCriteriaSQL($criteria) + : $this->getSelectConditionSQL($criteria); + + $filterSql = $this->generateFilterConditionSQL($this->class, $tableAlias); + + if ('' !== $filterSql) { + $conditionSql = $conditionSql + ? $conditionSql . ' AND ' . $filterSql + : $filterSql; + } + + $sql = 'SELECT COUNT(*) ' + . 'FROM ' . $tableName . ' ' . $tableAlias + . (empty($conditionSql) ? '' : ' WHERE ' . $conditionSql); + + return $sql; + } + + /** + * Gets the ORDER BY SQL snippet for ordered collections. + * + * @param array $orderBy + * @param string $baseTableAlias + * + * @return string + * + * @throws \Doctrine\ORM\ORMException + */ + protected final function getOrderBySQL(array $orderBy, $baseTableAlias) + { + $orderByList = []; + + foreach ($orderBy as $fieldName => $orientation) { + + $orientation = strtoupper(trim($orientation)); + + if ($orientation != 'ASC' && $orientation != 'DESC') { + throw ORMException::invalidOrientation($this->class->name, $fieldName); + } + + if (isset($this->class->fieldMappings[$fieldName])) { + $tableAlias = isset($this->class->fieldMappings[$fieldName]['inherited']) + ? $this->getSQLTableAlias($this->class->fieldMappings[$fieldName]['inherited']) + : $baseTableAlias; + + $columnName = $this->quoteStrategy->getColumnName($fieldName, $this->class, $this->platform); + $orderByList[] = $tableAlias . '.' . $columnName . ' ' . $orientation; + + continue; + } + + if (isset($this->class->associationMappings[$fieldName])) { + + if ( ! $this->class->associationMappings[$fieldName]['isOwningSide']) { + throw ORMException::invalidFindByInverseAssociation($this->class->name, $fieldName); + } + + $tableAlias = isset($this->class->associationMappings[$fieldName]['inherited']) + ? $this->getSQLTableAlias($this->class->associationMappings[$fieldName]['inherited']) + : $baseTableAlias; + + foreach ($this->class->associationMappings[$fieldName]['joinColumns'] as $joinColumn) { + $columnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); + $orderByList[] = $tableAlias . '.' . $columnName . ' ' . $orientation; + } + + continue; + } + + throw ORMException::unrecognizedField($fieldName); + } + + return ' ORDER BY ' . implode(', ', $orderByList); + } + + /** + * Gets the SQL fragment with the list of columns to select when querying for + * an entity in this persister. + * + * Subclasses should override this method to alter or change the select column + * list SQL fragment. Note that in the implementation of BasicEntityPersister + * the resulting SQL fragment is generated only once and cached in {@link selectColumnListSql}. + * Subclasses may or may not do the same. + * + * @return string The SQL fragment. + */ + protected function getSelectColumnsSQL() + { + if ($this->currentPersisterContext->selectColumnListSql !== null) { + return $this->currentPersisterContext->selectColumnListSql; + } + + $columnList = []; + $this->currentPersisterContext->rsm->addEntityResult($this->class->name, 'r'); // r for root + + // Add regular columns to select list + foreach ($this->class->fieldNames as $field) { + $columnList[] = $this->getSelectColumnSQL($field, $this->class); + } + + $this->currentPersisterContext->selectJoinSql = ''; + $eagerAliasCounter = 0; + + foreach ($this->class->associationMappings as $assocField => $assoc) { + $assocColumnSQL = $this->getSelectColumnAssociationSQL($assocField, $assoc, $this->class); + + if ($assocColumnSQL) { + $columnList[] = $assocColumnSQL; + } + + $isAssocToOneInverseSide = $assoc['type'] & ClassMetadata::TO_ONE && ! $assoc['isOwningSide']; + $isAssocFromOneEager = $assoc['type'] !== ClassMetadata::MANY_TO_MANY && $assoc['fetch'] === ClassMetadata::FETCH_EAGER; + + if ( ! ($isAssocFromOneEager || $isAssocToOneInverseSide)) { + continue; + } + + if ((($assoc['type'] & ClassMetadata::TO_MANY) > 0) && $this->currentPersisterContext->handlesLimits) { + continue; + } + + $eagerEntity = $this->em->getClassMetadata($assoc['targetEntity']); + + if ($eagerEntity->inheritanceType != ClassMetadata::INHERITANCE_TYPE_NONE) { + continue; // now this is why you shouldn't use inheritance + } + + $assocAlias = 'e' . ($eagerAliasCounter++); + $this->currentPersisterContext->rsm->addJoinedEntityResult($assoc['targetEntity'], $assocAlias, 'r', $assocField); + + foreach ($eagerEntity->fieldNames as $field) { + $columnList[] = $this->getSelectColumnSQL($field, $eagerEntity, $assocAlias); + } + + foreach ($eagerEntity->associationMappings as $eagerAssocField => $eagerAssoc) { + $eagerAssocColumnSQL = $this->getSelectColumnAssociationSQL( + $eagerAssocField, $eagerAssoc, $eagerEntity, $assocAlias + ); + + if ($eagerAssocColumnSQL) { + $columnList[] = $eagerAssocColumnSQL; + } + } + + $association = $assoc; + $joinCondition = []; + + if (isset($assoc['indexBy'])) { + $this->currentPersisterContext->rsm->addIndexBy($assocAlias, $assoc['indexBy']); + } + + if ( ! $assoc['isOwningSide']) { + $eagerEntity = $this->em->getClassMetadata($assoc['targetEntity']); + $association = $eagerEntity->getAssociationMapping($assoc['mappedBy']); + } + + $joinTableAlias = $this->getSQLTableAlias($eagerEntity->name, $assocAlias); + $joinTableName = $this->quoteStrategy->getTableName($eagerEntity, $this->platform); + + if ($assoc['isOwningSide']) { + $tableAlias = $this->getSQLTableAlias($association['targetEntity'], $assocAlias); + $this->currentPersisterContext->selectJoinSql .= ' ' . $this->getJoinSQLForJoinColumns($association['joinColumns']); + + foreach ($association['joinColumns'] as $joinColumn) { + $sourceCol = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); + $targetCol = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $this->class, $this->platform); + $joinCondition[] = $this->getSQLTableAlias($association['sourceEntity']) + . '.' . $sourceCol . ' = ' . $tableAlias . '.' . $targetCol; + } + + // Add filter SQL + if ($filterSql = $this->generateFilterConditionSQL($eagerEntity, $tableAlias)) { + $joinCondition[] = $filterSql; + } + + } else { + + $this->currentPersisterContext->selectJoinSql .= ' LEFT JOIN'; + + foreach ($association['joinColumns'] as $joinColumn) { + $sourceCol = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); + $targetCol = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $this->class, $this->platform); + + $joinCondition[] = $this->getSQLTableAlias($association['sourceEntity'], $assocAlias) . '.' . $sourceCol . ' = ' + . $this->getSQLTableAlias($association['targetEntity']) . '.' . $targetCol; + } + } + + $this->currentPersisterContext->selectJoinSql .= ' ' . $joinTableName . ' ' . $joinTableAlias . ' ON '; + $this->currentPersisterContext->selectJoinSql .= implode(' AND ', $joinCondition); + } + + $this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList); + + return $this->currentPersisterContext->selectColumnListSql; + } + + /** + * Gets the SQL join fragment used when selecting entities from an association. + * + * @param string $field + * @param array $assoc + * @param ClassMetadata $class + * @param string $alias + * + * @return string + */ + protected function getSelectColumnAssociationSQL($field, $assoc, ClassMetadata $class, $alias = 'r') + { + if ( ! ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) ) { + return ''; + } + + $columnList = []; + $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); + $isIdentifier = isset($assoc['id']) && $assoc['id'] === true; + $sqlTableAlias = $this->getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias)); + + foreach ($assoc['joinColumns'] as $joinColumn) { + $quotedColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); + $resultColumnName = $this->getSQLColumnAlias($joinColumn['name']); + $type = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); + + $this->currentPersisterContext->rsm->addMetaResult($alias, $resultColumnName, $joinColumn['name'], $isIdentifier, $type); + + $columnList[] = sprintf('%s.%s AS %s', $sqlTableAlias, $quotedColumn, $resultColumnName); + } + + return implode(', ', $columnList); + } + + /** + * Gets the SQL join fragment used when selecting entities from a + * many-to-many association. + * + * @param array $manyToMany + * + * @return string + */ + protected function getSelectManyToManyJoinSQL(array $manyToMany) + { + $conditions = []; + $association = $manyToMany; + $sourceTableAlias = $this->getSQLTableAlias($this->class->name); + + if ( ! $manyToMany['isOwningSide']) { + $targetEntity = $this->em->getClassMetadata($manyToMany['targetEntity']); + $association = $targetEntity->associationMappings[$manyToMany['mappedBy']]; + } + + $joinTableName = $this->quoteStrategy->getJoinTableName($association, $this->class, $this->platform); + $joinColumns = ($manyToMany['isOwningSide']) + ? $association['joinTable']['inverseJoinColumns'] + : $association['joinTable']['joinColumns']; + + foreach ($joinColumns as $joinColumn) { + $quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); + $quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $this->class, $this->platform); + $conditions[] = $sourceTableAlias . '.' . $quotedTargetColumn . ' = ' . $joinTableName . '.' . $quotedSourceColumn; + } + + return ' INNER JOIN ' . $joinTableName . ' ON ' . implode(' AND ', $conditions); + } + + /** + * {@inheritdoc} + */ + public function getInsertSQL() + { + if ($this->insertSql !== null) { + return $this->insertSql; + } + + $columns = $this->getInsertColumnList(); + $tableName = $this->quoteStrategy->getTableName($this->class, $this->platform); + + if (empty($columns)) { + $identityColumn = $this->quoteStrategy->getColumnName($this->class->identifier[0], $this->class, $this->platform); + $this->insertSql = $this->platform->getEmptyIdentityInsertSQL($tableName, $identityColumn); + + return $this->insertSql; + } + + $values = []; + $columns = array_unique($columns); + + foreach ($columns as $column) { + $placeholder = '?'; + + if (isset($this->class->fieldNames[$column]) + && isset($this->columnTypes[$this->class->fieldNames[$column]]) + && isset($this->class->fieldMappings[$this->class->fieldNames[$column]]['requireSQLConversion'])) { + $type = Type::getType($this->columnTypes[$this->class->fieldNames[$column]]); + $placeholder = $type->convertToDatabaseValueSQL('?', $this->platform); + } + + $values[] = $placeholder; + } + + $columns = implode(', ', $columns); + $values = implode(', ', $values); + + $this->insertSql = sprintf('INSERT INTO %s (%s) VALUES (%s)', $tableName, $columns, $values); + + return $this->insertSql; + } + + /** + * Gets the list of columns to put in the INSERT SQL statement. + * + * Subclasses should override this method to alter or change the list of + * columns placed in the INSERT statements used by the persister. + * + * @return array The list of columns. + */ + protected function getInsertColumnList() + { + $columns = []; + + foreach ($this->class->reflFields as $name => $field) { + if ($this->class->isVersioned && $this->class->versionField == $name) { + continue; + } + + if (isset($this->class->embeddedClasses[$name])) { + continue; + } + + if (isset($this->class->associationMappings[$name])) { + $assoc = $this->class->associationMappings[$name]; + + if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) { + foreach ($assoc['joinColumns'] as $joinColumn) { + $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); + } + } + + continue; + } + + if (! $this->class->isIdGeneratorIdentity() || $this->class->identifier[0] != $name) { + $columns[] = $this->quoteStrategy->getColumnName($name, $this->class, $this->platform); + $this->columnTypes[$name] = $this->class->fieldMappings[$name]['type']; + } + } + + return $columns; + } + + /** + * Gets the SQL snippet of a qualified column name for the given field name. + * + * @param string $field The field name. + * @param ClassMetadata $class The class that declares this field. The table this class is + * mapped to must own the column for the given field. + * @param string $alias + * + * @return string + */ + protected function getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r') + { + $root = $alias == 'r' ? '' : $alias ; + $tableAlias = $this->getSQLTableAlias($class->name, $root); + $fieldMapping = $class->fieldMappings[$field]; + $sql = sprintf('%s.%s', $tableAlias, $this->quoteStrategy->getColumnName($field, $class, $this->platform)); + $columnAlias = $this->getSQLColumnAlias($fieldMapping['columnName']); + + $this->currentPersisterContext->rsm->addFieldResult($alias, $columnAlias, $field); + + if (isset($fieldMapping['requireSQLConversion'])) { + $type = Type::getType($fieldMapping['type']); + $sql = $type->convertToPHPValueSQL($sql, $this->platform); + } + + return $sql . ' AS ' . $columnAlias; + } + + /** + * Gets the SQL table alias for the given class name. + * + * @param string $className + * @param string $assocName + * + * @return string The SQL table alias. + * + * @todo Reconsider. Binding table aliases to class names is not such a good idea. + */ + protected function getSQLTableAlias($className, $assocName = '') + { + if ($assocName) { + $className .= '#' . $assocName; + } + + if (isset($this->currentPersisterContext->sqlTableAliases[$className])) { + return $this->currentPersisterContext->sqlTableAliases[$className]; + } + + $tableAlias = 't' . $this->currentPersisterContext->sqlAliasCounter++; + + $this->currentPersisterContext->sqlTableAliases[$className] = $tableAlias; + + return $tableAlias; + } + + /** + * {@inheritdoc} + */ + public function lock(array $criteria, $lockMode) + { + $lockSql = ''; + $conditionSql = $this->getSelectConditionSQL($criteria); + + switch ($lockMode) { + case LockMode::PESSIMISTIC_READ: + $lockSql = $this->platform->getReadLockSQL(); + + break; + case LockMode::PESSIMISTIC_WRITE: + + $lockSql = $this->platform->getWriteLockSQL(); + break; + } + + $lock = $this->getLockTablesSql($lockMode); + $where = ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' '; + $sql = 'SELECT 1 ' + . $lock + . $where + . $lockSql; + + list($params, $types) = $this->expandParameters($criteria); + + $this->conn->executeQuery($sql, $params, $types); + } + + /** + * Gets the FROM and optionally JOIN conditions to lock the entity managed by this persister. + * + * @param integer $lockMode One of the Doctrine\DBAL\LockMode::* constants. + * + * @return string + */ + protected function getLockTablesSql($lockMode) + { + return $this->platform->appendLockHint( + 'FROM ' + . $this->quoteStrategy->getTableName($this->class, $this->platform) . ' ' + . $this->getSQLTableAlias($this->class->name), + $lockMode + ); + } + + /** + * Gets the Select Where Condition from a Criteria object. + * + * @param \Doctrine\Common\Collections\Criteria $criteria + * + * @return string + */ + protected function getSelectConditionCriteriaSQL(Criteria $criteria) + { + $expression = $criteria->getWhereExpression(); + + if ($expression === null) { + return ''; + } + + $visitor = new SqlExpressionVisitor($this, $this->class); + + return $visitor->dispatch($expression); + } + + /** + * {@inheritdoc} + */ + public function getSelectConditionStatementSQL($field, $value, $assoc = null, $comparison = null) + { + $selectedColumns = []; + $columns = $this->getSelectConditionStatementColumnSQL($field, $assoc); + + if (count($columns) > 1 && $comparison === Comparison::IN) { + /* + * @todo try to support multi-column IN expressions. + * Example: (col1, col2) IN (('val1A', 'val2A'), ('val1B', 'val2B')) + */ + throw ORMException::cantUseInOperatorOnCompositeKeys(); + } + + foreach ($columns as $column) { + $placeholder = '?'; + + if (isset($this->class->fieldMappings[$field]['requireSQLConversion'])) { + $type = Type::getType($this->class->fieldMappings[$field]['type']); + $placeholder = $type->convertToDatabaseValueSQL($placeholder, $this->platform); + } + + if (null !== $comparison) { + // special case null value handling + if (($comparison === Comparison::EQ || $comparison === Comparison::IS) && null ===$value) { + $selectedColumns[] = $column . ' IS NULL'; + + continue; + } + + if ($comparison === Comparison::NEQ && null === $value) { + $selectedColumns[] = $column . ' IS NOT NULL'; + + continue; + } + + $selectedColumns[] = $column . ' ' . sprintf(self::$comparisonMap[$comparison], $placeholder); + + continue; + } + + if (is_array($value)) { + $in = sprintf('%s IN (%s)', $column, $placeholder); + + if (false !== array_search(null, $value, true)) { + $selectedColumns[] = sprintf('(%s OR %s IS NULL)', $in, $column); + + continue; + } + + $selectedColumns[] = $in; + + continue; + } + + if (null === $value) { + $selectedColumns[] = sprintf('%s IS NULL', $column); + + continue; + } + + $selectedColumns[] = sprintf('%s = %s', $column, $placeholder); + } + + return implode(' AND ', $selectedColumns); + } + + /** + * Builds the left-hand-side of a where condition statement. + * + * @param string $field + * @param array|null $assoc + * + * @return string[] + * + * @throws \Doctrine\ORM\ORMException + */ + private function getSelectConditionStatementColumnSQL($field, $assoc = null) + { + if (isset($this->class->fieldMappings[$field])) { + $className = (isset($this->class->fieldMappings[$field]['inherited'])) + ? $this->class->fieldMappings[$field]['inherited'] + : $this->class->name; + + return [$this->getSQLTableAlias($className) . '.' . $this->quoteStrategy->getColumnName($field, $this->class, $this->platform)]; + } + + if (isset($this->class->associationMappings[$field])) { + $association = $this->class->associationMappings[$field]; + // Many-To-Many requires join table check for joinColumn + $columns = []; + $class = $this->class; + + if ($association['type'] === ClassMetadata::MANY_TO_MANY) { + if ( ! $association['isOwningSide']) { + $association = $assoc; + } + + $joinTableName = $this->quoteStrategy->getJoinTableName($association, $class, $this->platform); + $joinColumns = $assoc['isOwningSide'] + ? $association['joinTable']['joinColumns'] + : $association['joinTable']['inverseJoinColumns']; + + + foreach ($joinColumns as $joinColumn) { + $columns[] = $joinTableName . '.' . $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); + } + + } else { + if ( ! $association['isOwningSide']) { + throw ORMException::invalidFindByInverseAssociation($this->class->name, $field); + } + + $className = (isset($association['inherited'])) + ? $association['inherited'] + : $this->class->name; + + foreach ($association['joinColumns'] as $joinColumn) { + $columns[] = $this->getSQLTableAlias($className) . '.' . $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); + } + } + return $columns; + } + + if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) { + // very careless developers could potentially open up this normally hidden api for userland attacks, + // therefore checking for spaces and function calls which are not allowed. + + // found a join column condition, not really a "field" + return [$field]; + } + + throw ORMException::unrecognizedField($field); + } + + /** + * Gets the conditional SQL fragment used in the WHERE clause when selecting + * entities in this persister. + * + * Subclasses are supposed to override this method if they intend to change + * or alter the criteria by which entities are selected. + * + * @param array $criteria + * @param array|null $assoc + * + * @return string + */ + protected function getSelectConditionSQL(array $criteria, $assoc = null) + { + $conditions = []; + + foreach ($criteria as $field => $value) { + $conditions[] = $this->getSelectConditionStatementSQL($field, $value, $assoc); + } + + return implode(' AND ', $conditions); + } + + /** + * {@inheritdoc} + */ + public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null) + { + $this->switchPersisterContext($offset, $limit); + + $stmt = $this->getOneToManyStatement($assoc, $sourceEntity, $offset, $limit); + + return $this->loadArrayFromStatement($assoc, $stmt); + } + + /** + * {@inheritdoc} + */ + public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll) + { + $stmt = $this->getOneToManyStatement($assoc, $sourceEntity); + + return $this->loadCollectionFromStatement($assoc, $stmt, $coll); + } + + /** + * Builds criteria and execute SQL statement to fetch the one to many entities from. + * + * @param array $assoc + * @param object $sourceEntity + * @param int|null $offset + * @param int|null $limit + * + * @return \Doctrine\DBAL\Statement + */ + private function getOneToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null) + { + $this->switchPersisterContext($offset, $limit); + + $criteria = []; + $parameters = []; + $owningAssoc = $this->class->associationMappings[$assoc['mappedBy']]; + $sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']); + $tableAlias = $this->getSQLTableAlias($owningAssoc['inherited'] ?? $this->class->name); + + foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) { + if ($sourceClass->containsForeignIdentifier) { + $field = $sourceClass->getFieldForColumn($sourceKeyColumn); + $value = $sourceClass->reflFields[$field]->getValue($sourceEntity); + + if (isset($sourceClass->associationMappings[$field])) { + $value = $this->em->getUnitOfWork()->getEntityIdentifier($value); + $value = $value[$this->em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]]; + } + + $criteria[$tableAlias . "." . $targetKeyColumn] = $value; + $parameters[] = [ + 'value' => $value, + 'field' => $field, + 'class' => $sourceClass, + ]; + + continue; + } + + $field = $sourceClass->fieldNames[$sourceKeyColumn]; + $value = $sourceClass->reflFields[$field]->getValue($sourceEntity); + + $criteria[$tableAlias . "." . $targetKeyColumn] = $value; + $parameters[] = [ + 'value' => $value, + 'field' => $field, + 'class' => $sourceClass, + ]; + + } + + $sql = $this->getSelectSQL($criteria, $assoc, null, $limit, $offset); + list($params, $types) = $this->expandToManyParameters($parameters); + + return $this->conn->executeQuery($sql, $params, $types); + } + + /** + * {@inheritdoc} + */ + public function expandParameters($criteria) + { + $params = []; + $types = []; + + foreach ($criteria as $field => $value) { + if ($value === null) { + continue; // skip null values. + } + + $types = array_merge($types, $this->getTypes($field, $value, $this->class)); + $params = array_merge($params, $this->getValues($value)); + } + + return [$params, $types]; + } + + /** + * Expands the parameters from the given criteria and use the correct binding types if found, + * specialized for OneToMany or ManyToMany associations. + * + * @param mixed[][] $criteria an array of arrays containing following: + * - field to which each criterion will be bound + * - value to be bound + * - class to which the field belongs to + * + * + * @return array + */ + private function expandToManyParameters($criteria) + { + $params = []; + $types = []; + + foreach ($criteria as $criterion) { + if ($criterion['value'] === null) { + continue; // skip null values. + } + + $types = array_merge($types, $this->getTypes($criterion['field'], $criterion['value'], $criterion['class'])); + $params = array_merge($params, $this->getValues($criterion['value'])); + } + + return [$params, $types]; + } + + /** + * Infers field types to be used by parameter type casting. + * + * @param string $field + * @param mixed $value + * @param ClassMetadata $class + * + * @return array + * + * @throws \Doctrine\ORM\Query\QueryException + */ + private function getTypes($field, $value, ClassMetadata $class) + { + $types = []; + + switch (true) { + case (isset($class->fieldMappings[$field])): + $types = array_merge($types, [$class->fieldMappings[$field]['type']]); + break; + + case (isset($class->associationMappings[$field])): + $assoc = $class->associationMappings[$field]; + $class = $this->em->getClassMetadata($assoc['targetEntity']); + + if (! $assoc['isOwningSide']) { + $assoc = $class->associationMappings[$assoc['mappedBy']]; + $class = $this->em->getClassMetadata($assoc['targetEntity']); + } + + $columns = $assoc['type'] === ClassMetadata::MANY_TO_MANY + ? $assoc['relationToTargetKeyColumns'] + : $assoc['sourceToTargetKeyColumns']; + + foreach ($columns as $column){ + $types[] = PersisterHelper::getTypeOfColumn($column, $class, $this->em); + } + break; + + default: + $types[] = null; + break; + } + + if (is_array($value)) { + return array_map(function ($type) { + $type = Type::getType($type); + + return $type->getBindingType() + Connection::ARRAY_PARAM_OFFSET; + }, $types); + } + + return $types; + } + + /** + * Retrieves the parameters that identifies a value. + * + * @param mixed $value + * + * @return array + */ + private function getValues($value) + { + if (is_array($value)) { + $newValue = []; + + foreach ($value as $itemValue) { + $newValue = array_merge($newValue, $this->getValues($itemValue)); + } + + return [$newValue]; + } + + if (is_object($value) && $this->em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value))) { + $class = $this->em->getClassMetadata(get_class($value)); + if ($class->isIdentifierComposite) { + $newValue = []; + + foreach ($class->getIdentifierValues($value) as $innerValue) { + $newValue = array_merge($newValue, $this->getValues($innerValue)); + } + + return $newValue; + } + } + + return [$this->getIndividualValue($value)]; + } + + /** + * Retrieves an individual parameter value. + * + * @param mixed $value + * + * @return mixed + */ + private function getIndividualValue($value) + { + if ( ! is_object($value) || ! $this->em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value))) { + return $value; + } + + return $this->em->getUnitOfWork()->getSingleIdentifierValue($value); + } + + /** + * {@inheritdoc} + */ + public function exists($entity, Criteria $extraConditions = null) + { + $criteria = $this->class->getIdentifierValues($entity); + + if ( ! $criteria) { + return false; + } + + $alias = $this->getSQLTableAlias($this->class->name); + + $sql = 'SELECT 1 ' + . $this->getLockTablesSql(null) + . ' WHERE ' . $this->getSelectConditionSQL($criteria); + + list($params, $types) = $this->expandParameters($criteria); + + if (null !== $extraConditions) { + $sql .= ' AND ' . $this->getSelectConditionCriteriaSQL($extraConditions); + list($criteriaParams, $criteriaTypes) = $this->expandCriteriaParameters($extraConditions); + + $params = array_merge($params, $criteriaParams); + $types = array_merge($types, $criteriaTypes); + } + + if ($filterSql = $this->generateFilterConditionSQL($this->class, $alias)) { + $sql .= ' AND ' . $filterSql; + } + + return (bool) $this->conn->fetchColumn($sql, $params, 0, $types); + } + + /** + * Generates the appropriate join SQL for the given join column. + * + * @param array $joinColumns The join columns definition of an association. + * + * @return string LEFT JOIN if one of the columns is nullable, INNER JOIN otherwise. + */ + protected function getJoinSQLForJoinColumns($joinColumns) + { + // if one of the join columns is nullable, return left join + foreach ($joinColumns as $joinColumn) { + if ( ! isset($joinColumn['nullable']) || $joinColumn['nullable']) { + return 'LEFT JOIN'; + } + } + + return 'INNER JOIN'; + } + + /** + * {@inheritdoc} + */ + public function getSQLColumnAlias($columnName) + { + return $this->quoteStrategy->getColumnAlias($columnName, $this->currentPersisterContext->sqlAliasCounter++, $this->platform); + } + + /** + * Generates the filter SQL for a given entity and table alias. + * + * @param ClassMetadata $targetEntity Metadata of the target entity. + * @param string $targetTableAlias The table alias of the joined/selected table. + * + * @return string The SQL query part to add to a query. + */ + protected function generateFilterConditionSQL(ClassMetadata $targetEntity, $targetTableAlias) + { + $filterClauses = []; + + foreach ($this->em->getFilters()->getEnabledFilters() as $filter) { + if ('' !== $filterExpr = $filter->addFilterConstraint($targetEntity, $targetTableAlias)) { + $filterClauses[] = '(' . $filterExpr . ')'; + } + } + + $sql = implode(' AND ', $filterClauses); + + return $sql ? "(" . $sql . ")" : ""; // Wrap again to avoid "X or Y and FilterConditionSQL" + } + + /** + * Switches persister context according to current query offset/limits + * + * This is due to the fact that to-many associations cannot be fetch-joined when a limit is involved + * + * @param null|int $offset + * @param null|int $limit + */ + protected function switchPersisterContext($offset, $limit) + { + if (null === $offset && null === $limit) { + $this->currentPersisterContext = $this->noLimitsContext; + + return; + } + + $this->currentPersisterContext = $this->limitsHandlingContext; + } + + /** + * @return string[] + */ + protected function getClassIdentifiersTypes(ClassMetadata $class) : array + { + $entityManager = $this->em; + + return array_map( + static function ($fieldName) use ($class, $entityManager) : string { + $types = PersisterHelper::getTypeOfField($fieldName, $class, $entityManager); + assert(isset($types[0])); + + return $types[0]; + }, + $class->identifier + ); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/CachedPersisterContext.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/CachedPersisterContext.php new file mode 100644 index 0000000..132dac7 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/CachedPersisterContext.php @@ -0,0 +1,102 @@ +. + */ + +namespace Doctrine\ORM\Persisters\Entity; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Doctrine\ORM\Query\ResultSetMapping; + +/** + * A swappable persister context to use as a container for the current + * generated query/resultSetMapping/type binding information. + * + * This class is a utility class to be used only by the persister API + * + * This object is highly mutable due to performance reasons. Same reasoning + * behind its properties being public. + * + * @author Marco Pivetta + */ +class CachedPersisterContext +{ + /** + * Metadata object that describes the mapping of the mapped entity class. + * + * @var \Doctrine\ORM\Mapping\ClassMetadata + */ + public $class; + + /** + * ResultSetMapping that is used for all queries. Is generated lazily once per request. + * + * @var \Doctrine\ORM\Query\ResultSetMapping + */ + public $rsm; + + /** + * The SELECT column list SQL fragment used for querying entities by this persister. + * This SQL fragment is only generated once per request, if at all. + * + * @var string|null + */ + public $selectColumnListSql; + + /** + * The JOIN SQL fragment used to eagerly load all many-to-one and one-to-one + * associations configured as FETCH_EAGER, as well as all inverse one-to-one associations. + * + * @var string + */ + public $selectJoinSql; + + /** + * Counter for creating unique SQL table and column aliases. + * + * @var integer + */ + public $sqlAliasCounter = 0; + + /** + * Map from class names (FQCN) to the corresponding generated SQL table aliases. + * + * @var array + */ + public $sqlTableAliases = []; + + /** + * Whether this persistent context is considering limit operations applied to the selection queries + * + * @var bool + */ + public $handlesLimits; + + /** + * @param ClassMetadata $class + * @param ResultSetMapping $rsm + * @param bool $handlesLimits + */ + public function __construct( + ClassMetadata $class, + ResultSetMapping $rsm, + $handlesLimits + ) { + $this->class = $class; + $this->rsm = $rsm; + $this->handlesLimits = (bool) $handlesLimits; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/EntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/EntityPersister.php new file mode 100644 index 0000000..9ac6316 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/EntityPersister.php @@ -0,0 +1,330 @@ +. + */ + +namespace Doctrine\ORM\Persisters\Entity; + +use Doctrine\ORM\PersistentCollection; +use Doctrine\Common\Collections\Criteria; + +/** + * Entity persister interface + * Define the behavior that should be implemented by all entity persisters. + * + * @author Fabio B. Silva + * @since 2.5 + */ +interface EntityPersister +{ + /** + * @return \Doctrine\ORM\Mapping\ClassMetadata + */ + public function getClassMetadata(); + + /** + * Gets the ResultSetMapping used for hydration. + * + * @return \Doctrine\ORM\Query\ResultSetMapping + */ + public function getResultSetMapping(); + + /** + * Get all queued inserts. + * + * @return array + */ + public function getInserts(); + + /** + * @TODO - It should not be here. + * But its necessary since JoinedSubclassPersister#executeInserts invoke the root persister. + * + * Gets the INSERT SQL used by the persister to persist a new entity. + * + * @return string + */ + public function getInsertSQL(); + + /** + * Gets the SELECT SQL to select one or more entities by a set of field criteria. + * + * @param array|\Doctrine\Common\Collections\Criteria $criteria + * @param array|null $assoc + * @param int|null $lockMode + * @param int|null $limit + * @param int|null $offset + * @param array|null $orderBy + * + * @return string + */ + public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, array $orderBy = null); + + /** + * Get the COUNT SQL to count entities (optionally based on a criteria) + * + * @param array|\Doctrine\Common\Collections\Criteria $criteria + * + * @return string + */ + public function getCountSQL($criteria = []); + + /** + * Expands the parameters from the given criteria and use the correct binding types if found. + * + * @param $criteria + * + * @return array + */ + public function expandParameters($criteria); + + /** + * Expands Criteria Parameters by walking the expressions and grabbing all parameters and types from it. + * + * @param \Doctrine\Common\Collections\Criteria $criteria + * + * @return array + */ + public function expandCriteriaParameters(Criteria $criteria); + + /** + * Gets the SQL WHERE condition for matching a field with a given value. + * + * @param string $field + * @param mixed $value + * @param array|null $assoc + * @param string|null $comparison + * + * @return string + */ + public function getSelectConditionStatementSQL($field, $value, $assoc = null, $comparison = null); + + /** + * Adds an entity to the queued insertions. + * The entity remains queued until {@link executeInserts} is invoked. + * + * @param object $entity The entity to queue for insertion. + * + * @return void + */ + public function addInsert($entity); + + /** + * Executes all queued entity insertions and returns any generated post-insert + * identifiers that were created as a result of the insertions. + * + * If no inserts are queued, invoking this method is a NOOP. + * + * @return array An array of any generated post-insert IDs. This will be an empty array + * if the entity class does not use the IDENTITY generation strategy. + */ + public function executeInserts(); + + /** + * Updates a managed entity. The entity is updated according to its current changeset + * in the running UnitOfWork. If there is no changeset, nothing is updated. + * + * @param object $entity The entity to update. + * + * @return void + */ + public function update($entity); + + /** + * Deletes a managed entity. + * + * The entity to delete must be managed and have a persistent identifier. + * The deletion happens instantaneously. + * + * Subclasses may override this method to customize the semantics of entity deletion. + * + * @param object $entity The entity to delete. + * + * @return bool TRUE if the entity got deleted in the database, FALSE otherwise. + */ + public function delete($entity); + + /** + * Count entities (optionally filtered by a criteria) + * + * @param array|\Doctrine\Common\Collections\Criteria $criteria + * + * @return int + */ + public function count($criteria = []); + + /** + * Gets the name of the table that owns the column the given field is mapped to. + * + * The default implementation in BasicEntityPersister always returns the name + * of the table the entity type of this persister is mapped to, since an entity + * is always persisted to a single table with a BasicEntityPersister. + * + * @param string $fieldName The field name. + * + * @return string The table name. + */ + public function getOwningTable($fieldName); + + /** + * Loads an entity by a list of field criteria. + * + * @param array $criteria The criteria by which to load the entity. + * @param object|null $entity The entity to load the data into. If not specified, a new entity is created. + * @param array|null $assoc The association that connects the entity to load to another entity, if any. + * @param array $hints Hints for entity creation. + * @param int|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants + * or NULL if no specific lock mode should be used + * for loading the entity. + * @param int|null $limit Limit number of results. + * @param array|null $orderBy Criteria to order by. + * + * @return object|null The loaded and managed entity instance or NULL if the entity can not be found. + * + * @todo Check identity map? loadById method? Try to guess whether $criteria is the id? + */ + public function load(array $criteria, $entity = null, $assoc = null, array $hints = [], $lockMode = null, $limit = null, array $orderBy = null); + + /** + * Loads an entity by identifier. + * + * @param array $identifier The entity identifier. + * @param object|null $entity The entity to load the data into. If not specified, a new entity is created. + * + * @return object The loaded and managed entity instance or NULL if the entity can not be found. + * + * @todo Check parameters + */ + public function loadById(array $identifier, $entity = null); + + /** + * Loads an entity of this persister's mapped class as part of a single-valued + * association from another entity. + * + * @param array $assoc The association to load. + * @param object $sourceEntity The entity that owns the association (not necessarily the "owning side"). + * @param array $identifier The identifier of the entity to load. Must be provided if + * the association to load represents the owning side, otherwise + * the identifier is derived from the $sourceEntity. + * + * @return object The loaded and managed entity instance or NULL if the entity can not be found. + * + * @throws \Doctrine\ORM\Mapping\MappingException + */ + public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifier = []); + + /** + * Refreshes a managed entity. + * + * @param array $id The identifier of the entity as an associative array from + * column or field names to values. + * @param object $entity The entity to refresh. + * @param int|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants + * or NULL if no specific lock mode should be used + * for refreshing the managed entity. + * + * @return void + */ + public function refresh(array $id, $entity, $lockMode = null); + + /** + * Loads Entities matching the given Criteria object. + * + * @param \Doctrine\Common\Collections\Criteria $criteria + * + * @return array + */ + public function loadCriteria(Criteria $criteria); + + /** + * Loads a list of entities by a list of field criteria. + * + * @param array $criteria + * @param array|null $orderBy + * @param int|null $limit + * @param int|null $offset + * + * @return array + */ + public function loadAll(array $criteria = [], array $orderBy = null, $limit = null, $offset = null); + + /** + * Gets (sliced or full) elements of the given collection. + * + * @param array $assoc + * @param object $sourceEntity + * @param int|null $offset + * @param int|null $limit + * + * @return array + */ + public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null); + + /** + * Loads a collection of entities of a many-to-many association. + * + * @param array $assoc The association mapping of the association being loaded. + * @param object $sourceEntity The entity that owns the collection. + * @param PersistentCollection $collection The collection to fill. + * + * @return array + */ + public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $collection); + + /** + * Loads a collection of entities in a one-to-many association. + * + * @param array $assoc + * @param object $sourceEntity + * @param PersistentCollection $collection The collection to load/fill. + * + * @return array + */ + public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $collection); + + /** + * Locks all rows of this entity matching the given criteria with the specified pessimistic lock mode. + * + * @param array $criteria + * @param int $lockMode One of the Doctrine\DBAL\LockMode::* constants. + * + * @return void + */ + public function lock(array $criteria, $lockMode); + + /** + * Returns an array with (sliced or full list) of elements in the specified collection. + * + * @param array $assoc + * @param object $sourceEntity + * @param int|null $offset + * @param int|null $limit + * + * @return array + */ + public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null); + + /** + * Checks whether the given managed entity exists in the database. + * + * @param object $entity + * @param Criteria|null $extraConditions + * + * @return boolean TRUE if the entity exists in the database, FALSE otherwise. + */ + public function exists($entity, Criteria $extraConditions = null); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php new file mode 100644 index 0000000..1f6d401 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php @@ -0,0 +1,616 @@ +. + */ + +namespace Doctrine\ORM\Persisters\Entity; + +use Doctrine\ORM\Mapping\ClassMetadata; + +use Doctrine\DBAL\LockMode; +use Doctrine\DBAL\Types\Type; + +use Doctrine\Common\Collections\Criteria; +use Doctrine\ORM\Utility\PersisterHelper; + +/** + * The joined subclass persister maps a single entity instance to several tables in the + * database as it is defined by the Class Table Inheritance strategy. + * + * @author Roman Borschel + * @author Benjamin Eberlei + * @author Alexander + * @since 2.0 + * @see http://martinfowler.com/eaaCatalog/classTableInheritance.html + */ +class JoinedSubclassPersister extends AbstractEntityInheritancePersister +{ + /** + * Map that maps column names to the table names that own them. + * This is mainly a temporary cache, used during a single request. + * + * @var array + */ + private $owningTableMap = []; + + /** + * Map of table to quoted table names. + * + * @var array + */ + private $quotedTableMap = []; + + /** + * {@inheritdoc} + */ + protected function getDiscriminatorColumnTableName() + { + $class = ($this->class->name !== $this->class->rootEntityName) + ? $this->em->getClassMetadata($this->class->rootEntityName) + : $this->class; + + return $class->getTableName(); + } + + /** + * This function finds the ClassMetadata instance in an inheritance hierarchy + * that is responsible for enabling versioning. + * + * @return \Doctrine\ORM\Mapping\ClassMetadata + */ + private function getVersionedClassMetadata() + { + if (isset($this->class->fieldMappings[$this->class->versionField]['inherited'])) { + $definingClassName = $this->class->fieldMappings[$this->class->versionField]['inherited']; + + return $this->em->getClassMetadata($definingClassName); + } + + return $this->class; + } + + /** + * Gets the name of the table that owns the column the given field is mapped to. + * + * @param string $fieldName + * + * @return string + * + * @override + */ + public function getOwningTable($fieldName) + { + if (isset($this->owningTableMap[$fieldName])) { + return $this->owningTableMap[$fieldName]; + } + + switch (true) { + case isset($this->class->associationMappings[$fieldName]['inherited']): + $cm = $this->em->getClassMetadata($this->class->associationMappings[$fieldName]['inherited']); + break; + + case isset($this->class->fieldMappings[$fieldName]['inherited']): + $cm = $this->em->getClassMetadata($this->class->fieldMappings[$fieldName]['inherited']); + break; + + default: + $cm = $this->class; + break; + } + + $tableName = $cm->getTableName(); + $quotedTableName = $this->quoteStrategy->getTableName($cm, $this->platform); + + $this->owningTableMap[$fieldName] = $tableName; + $this->quotedTableMap[$tableName] = $quotedTableName; + + return $tableName; + } + + /** + * {@inheritdoc} + */ + public function executeInserts() + { + if ( ! $this->queuedInserts) { + return []; + } + + $postInsertIds = []; + $idGenerator = $this->class->idGenerator; + $isPostInsertId = $idGenerator->isPostInsertGenerator(); + $rootClass = ($this->class->name !== $this->class->rootEntityName) + ? $this->em->getClassMetadata($this->class->rootEntityName) + : $this->class; + + // Prepare statement for the root table + $rootPersister = $this->em->getUnitOfWork()->getEntityPersister($rootClass->name); + $rootTableName = $rootClass->getTableName(); + $rootTableStmt = $this->conn->prepare($rootPersister->getInsertSQL()); + + // Prepare statements for sub tables. + $subTableStmts = []; + + if ($rootClass !== $this->class) { + $subTableStmts[$this->class->getTableName()] = $this->conn->prepare($this->getInsertSQL()); + } + + foreach ($this->class->parentClasses as $parentClassName) { + $parentClass = $this->em->getClassMetadata($parentClassName); + $parentTableName = $parentClass->getTableName(); + + if ($parentClass !== $rootClass) { + $parentPersister = $this->em->getUnitOfWork()->getEntityPersister($parentClassName); + $subTableStmts[$parentTableName] = $this->conn->prepare($parentPersister->getInsertSQL()); + } + } + + // Execute all inserts. For each entity: + // 1) Insert on root table + // 2) Insert on sub tables + foreach ($this->queuedInserts as $entity) { + $insertData = $this->prepareInsertData($entity); + + // Execute insert on root table + $paramIndex = 1; + + foreach ($insertData[$rootTableName] as $columnName => $value) { + $rootTableStmt->bindValue($paramIndex++, $value, $this->columnTypes[$columnName]); + } + + $rootTableStmt->execute(); + + if ($isPostInsertId) { + $generatedId = $idGenerator->generate($this->em, $entity); + $id = [ + $this->class->identifier[0] => $generatedId + ]; + $postInsertIds[] = [ + 'generatedId' => $generatedId, + 'entity' => $entity, + ]; + } else { + $id = $this->em->getUnitOfWork()->getEntityIdentifier($entity); + } + + if ($this->class->isVersioned) { + $this->assignDefaultVersionValue($entity, $id); + } + + // Execute inserts on subtables. + // The order doesn't matter because all child tables link to the root table via FK. + foreach ($subTableStmts as $tableName => $stmt) { + /** @var \Doctrine\DBAL\Statement $stmt */ + $paramIndex = 1; + $data = $insertData[$tableName] ?? []; + + foreach ((array) $id as $idName => $idVal) { + $type = isset($this->columnTypes[$idName]) ? $this->columnTypes[$idName] : Type::STRING; + + $stmt->bindValue($paramIndex++, $idVal, $type); + } + + foreach ($data as $columnName => $value) { + if (!is_array($id) || !isset($id[$columnName])) { + $stmt->bindValue($paramIndex++, $value, $this->columnTypes[$columnName]); + } + } + + $stmt->execute(); + } + } + + $rootTableStmt->closeCursor(); + + foreach ($subTableStmts as $stmt) { + $stmt->closeCursor(); + } + + $this->queuedInserts = []; + + return $postInsertIds; + } + + /** + * {@inheritdoc} + */ + public function update($entity) + { + $updateData = $this->prepareUpdateData($entity); + + if ( ! $updateData) { + return; + } + + if (($isVersioned = $this->class->isVersioned) === false) { + return; + } + + $versionedClass = $this->getVersionedClassMetadata(); + $versionedTable = $versionedClass->getTableName(); + + foreach ($updateData as $tableName => $data) { + $tableName = $this->quotedTableMap[$tableName]; + $versioned = $isVersioned && $versionedTable === $tableName; + + $this->updateTable($entity, $tableName, $data, $versioned); + } + + // Make sure the table with the version column is updated even if no columns on that + // table were affected. + if ($isVersioned) { + if ( ! isset($updateData[$versionedTable])) { + $tableName = $this->quoteStrategy->getTableName($versionedClass, $this->platform); + + $this->updateTable($entity, $tableName, [], true); + } + + $identifiers = $this->em->getUnitOfWork()->getEntityIdentifier($entity); + + $this->assignDefaultVersionValue($entity, $identifiers); + } + } + + /** + * {@inheritdoc} + */ + public function delete($entity) + { + $identifier = $this->em->getUnitOfWork()->getEntityIdentifier($entity); + $id = array_combine($this->class->getIdentifierColumnNames(), $identifier); + + $this->deleteJoinTableRecords($identifier); + + // If the database platform supports FKs, just + // delete the row from the root table. Cascades do the rest. + if ($this->platform->supportsForeignKeyConstraints()) { + $rootClass = $this->em->getClassMetadata($this->class->rootEntityName); + $rootTable = $this->quoteStrategy->getTableName($rootClass, $this->platform); + $rootTypes = $this->getClassIdentifiersTypes($rootClass); + + return (bool) $this->conn->delete($rootTable, $id, $rootTypes); + } + + // Delete from all tables individually, starting from this class' table up to the root table. + $rootTable = $this->quoteStrategy->getTableName($this->class, $this->platform); + $rootTypes = $this->getClassIdentifiersTypes($this->class); + + $affectedRows = $this->conn->delete($rootTable, $id, $rootTypes); + + foreach ($this->class->parentClasses as $parentClass) { + $parentMetadata = $this->em->getClassMetadata($parentClass); + $parentTable = $this->quoteStrategy->getTableName($parentMetadata, $this->platform); + $parentTypes = $this->getClassIdentifiersTypes($parentMetadata); + + $this->conn->delete($parentTable, $id, $parentTypes); + } + + return (bool) $affectedRows; + } + + /** + * {@inheritdoc} + */ + public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, array $orderBy = null) + { + $this->switchPersisterContext($offset, $limit); + + $baseTableAlias = $this->getSQLTableAlias($this->class->name); + $joinSql = $this->getJoinSql($baseTableAlias); + + if ($assoc != null && $assoc['type'] == ClassMetadata::MANY_TO_MANY) { + $joinSql .= $this->getSelectManyToManyJoinSQL($assoc); + } + + $conditionSql = ($criteria instanceof Criteria) + ? $this->getSelectConditionCriteriaSQL($criteria) + : $this->getSelectConditionSQL($criteria, $assoc); + + // If the current class in the root entity, add the filters + if ($filterSql = $this->generateFilterConditionSQL($this->em->getClassMetadata($this->class->rootEntityName), $this->getSQLTableAlias($this->class->rootEntityName))) { + $conditionSql .= $conditionSql + ? ' AND ' . $filterSql + : $filterSql; + } + + $orderBySql = ''; + + if ($assoc !== null && isset($assoc['orderBy'])) { + $orderBy = $assoc['orderBy']; + } + + if ($orderBy) { + $orderBySql = $this->getOrderBySQL($orderBy, $baseTableAlias); + } + + $lockSql = ''; + + switch ($lockMode) { + case LockMode::PESSIMISTIC_READ: + + $lockSql = ' ' . $this->platform->getReadLockSQL(); + + break; + + case LockMode::PESSIMISTIC_WRITE: + + $lockSql = ' ' . $this->platform->getWriteLockSQL(); + + break; + } + + $tableName = $this->quoteStrategy->getTableName($this->class, $this->platform); + $from = ' FROM ' . $tableName . ' ' . $baseTableAlias; + $where = $conditionSql != '' ? ' WHERE ' . $conditionSql : ''; + $lock = $this->platform->appendLockHint($from, $lockMode); + $columnList = $this->getSelectColumnsSQL(); + $query = 'SELECT ' . $columnList + . $lock + . $joinSql + . $where + . $orderBySql; + + return $this->platform->modifyLimitQuery($query, $limit, $offset) . $lockSql; + } + + /** + * {@inheritDoc} + */ + public function getCountSQL($criteria = []) + { + $tableName = $this->quoteStrategy->getTableName($this->class, $this->platform); + $baseTableAlias = $this->getSQLTableAlias($this->class->name); + $joinSql = $this->getJoinSql($baseTableAlias); + + $conditionSql = ($criteria instanceof Criteria) + ? $this->getSelectConditionCriteriaSQL($criteria) + : $this->getSelectConditionSQL($criteria); + + $filterSql = $this->generateFilterConditionSQL($this->em->getClassMetadata($this->class->rootEntityName), $this->getSQLTableAlias($this->class->rootEntityName)); + + if ('' !== $filterSql) { + $conditionSql = $conditionSql + ? $conditionSql . ' AND ' . $filterSql + : $filterSql; + } + + $sql = 'SELECT COUNT(*) ' + . 'FROM ' . $tableName . ' ' . $baseTableAlias + . $joinSql + . (empty($conditionSql) ? '' : ' WHERE ' . $conditionSql); + + return $sql; + } + + /** + * {@inheritdoc} + */ + protected function getLockTablesSql($lockMode) + { + $joinSql = ''; + $identifierColumns = $this->class->getIdentifierColumnNames(); + $baseTableAlias = $this->getSQLTableAlias($this->class->name); + + // INNER JOIN parent tables + foreach ($this->class->parentClasses as $parentClassName) { + $conditions = []; + $tableAlias = $this->getSQLTableAlias($parentClassName); + $parentClass = $this->em->getClassMetadata($parentClassName); + $joinSql .= ' INNER JOIN ' . $this->quoteStrategy->getTableName($parentClass, $this->platform) . ' ' . $tableAlias . ' ON '; + + foreach ($identifierColumns as $idColumn) { + $conditions[] = $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn; + } + + $joinSql .= implode(' AND ', $conditions); + } + + return parent::getLockTablesSql($lockMode) . $joinSql; + } + + /** + * Ensure this method is never called. This persister overrides getSelectEntitiesSQL directly. + * + * @return string + */ + protected function getSelectColumnsSQL() + { + // Create the column list fragment only once + if ($this->currentPersisterContext->selectColumnListSql !== null) { + return $this->currentPersisterContext->selectColumnListSql; + } + + $columnList = []; + $discrColumn = $this->class->discriminatorColumn['name']; + $discrColumnType = $this->class->discriminatorColumn['type']; + $baseTableAlias = $this->getSQLTableAlias($this->class->name); + $resultColumnName = $this->platform->getSQLResultCasing($discrColumn); + + $this->currentPersisterContext->rsm->addEntityResult($this->class->name, 'r'); + $this->currentPersisterContext->rsm->setDiscriminatorColumn('r', $resultColumnName); + $this->currentPersisterContext->rsm->addMetaResult('r', $resultColumnName, $discrColumn, false, $discrColumnType); + + // Add regular columns + foreach ($this->class->fieldMappings as $fieldName => $mapping) { + $class = isset($mapping['inherited']) + ? $this->em->getClassMetadata($mapping['inherited']) + : $this->class; + + $columnList[] = $this->getSelectColumnSQL($fieldName, $class); + } + + // Add foreign key columns + foreach ($this->class->associationMappings as $mapping) { + if ( ! $mapping['isOwningSide'] || ! ($mapping['type'] & ClassMetadata::TO_ONE)) { + continue; + } + + $tableAlias = isset($mapping['inherited']) + ? $this->getSQLTableAlias($mapping['inherited']) + : $baseTableAlias; + + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + + foreach ($mapping['joinColumns'] as $joinColumn) { + $columnList[] = $this->getSelectJoinColumnSQL( + $tableAlias, + $joinColumn['name'], + $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform), + PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em) + ); + } + } + + // Add discriminator column (DO NOT ALIAS, see AbstractEntityInheritancePersister#processSQLResult). + $tableAlias = ($this->class->rootEntityName == $this->class->name) + ? $baseTableAlias + : $this->getSQLTableAlias($this->class->rootEntityName); + + $columnList[] = $tableAlias . '.' . $discrColumn; + + // sub tables + foreach ($this->class->subClasses as $subClassName) { + $subClass = $this->em->getClassMetadata($subClassName); + $tableAlias = $this->getSQLTableAlias($subClassName); + + // Add subclass columns + foreach ($subClass->fieldMappings as $fieldName => $mapping) { + if (isset($mapping['inherited'])) { + continue; + } + + $columnList[] = $this->getSelectColumnSQL($fieldName, $subClass); + } + + // Add join columns (foreign keys) + foreach ($subClass->associationMappings as $mapping) { + if ( ! $mapping['isOwningSide'] + || ! ($mapping['type'] & ClassMetadata::TO_ONE) + || isset($mapping['inherited'])) { + continue; + } + + $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); + + foreach ($mapping['joinColumns'] as $joinColumn) { + $columnList[] = $this->getSelectJoinColumnSQL( + $tableAlias, + $joinColumn['name'], + $this->quoteStrategy->getJoinColumnName($joinColumn, $subClass, $this->platform), + PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em) + ); + } + } + } + + $this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList); + + return $this->currentPersisterContext->selectColumnListSql; + } + + /** + * {@inheritdoc} + */ + protected function getInsertColumnList() + { + // Identifier columns must always come first in the column list of subclasses. + $columns = $this->class->parentClasses + ? $this->class->getIdentifierColumnNames() + : []; + + foreach ($this->class->reflFields as $name => $field) { + if (isset($this->class->fieldMappings[$name]['inherited']) + && ! isset($this->class->fieldMappings[$name]['id']) + || isset($this->class->associationMappings[$name]['inherited']) + || ($this->class->isVersioned && $this->class->versionField == $name) + || isset($this->class->embeddedClasses[$name])) { + continue; + } + + if (isset($this->class->associationMappings[$name])) { + $assoc = $this->class->associationMappings[$name]; + if ($assoc['type'] & ClassMetadata::TO_ONE && $assoc['isOwningSide']) { + foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) { + $columns[] = $sourceCol; + } + } + } else if ($this->class->name != $this->class->rootEntityName || + ! $this->class->isIdGeneratorIdentity() || $this->class->identifier[0] != $name) { + $columns[] = $this->quoteStrategy->getColumnName($name, $this->class, $this->platform); + $this->columnTypes[$name] = $this->class->fieldMappings[$name]['type']; + } + } + + // Add discriminator column if it is the topmost class. + if ($this->class->name == $this->class->rootEntityName) { + $columns[] = $this->class->discriminatorColumn['name']; + } + + return $columns; + } + + /** + * {@inheritdoc} + */ + protected function assignDefaultVersionValue($entity, array $id) + { + $value = $this->fetchVersionValue($this->getVersionedClassMetadata(), $id); + $this->class->setFieldValue($entity, $this->class->versionField, $value); + } + + /** + * @param string $baseTableAlias + * + * @return string + */ + private function getJoinSql($baseTableAlias) + { + $joinSql = ''; + $identifierColumn = $this->class->getIdentifierColumnNames(); + + // INNER JOIN parent tables + foreach ($this->class->parentClasses as $parentClassName) { + $conditions = []; + $parentClass = $this->em->getClassMetadata($parentClassName); + $tableAlias = $this->getSQLTableAlias($parentClassName); + $joinSql .= ' INNER JOIN ' . $this->quoteStrategy->getTableName($parentClass, $this->platform) . ' ' . $tableAlias . ' ON '; + + + foreach ($identifierColumn as $idColumn) { + $conditions[] = $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn; + } + + $joinSql .= implode(' AND ', $conditions); + } + + // OUTER JOIN sub tables + foreach ($this->class->subClasses as $subClassName) { + $conditions = []; + $subClass = $this->em->getClassMetadata($subClassName); + $tableAlias = $this->getSQLTableAlias($subClassName); + $joinSql .= ' LEFT JOIN ' . $this->quoteStrategy->getTableName($subClass, $this->platform) . ' ' . $tableAlias . ' ON '; + + foreach ($identifierColumn as $idColumn) { + $conditions[] = $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn; + } + + $joinSql .= implode(' AND ', $conditions); + } + + return $joinSql; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php new file mode 100644 index 0000000..4b8352b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php @@ -0,0 +1,192 @@ +. + */ + +namespace Doctrine\ORM\Persisters\Entity; + +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\Common\Collections\Criteria; +use Doctrine\ORM\Utility\PersisterHelper; + +/** + * Persister for entities that participate in a hierarchy mapped with the + * SINGLE_TABLE strategy. + * + * @author Roman Borschel + * @author Benjamin Eberlei + * @author Alexander + * @since 2.0 + * @link http://martinfowler.com/eaaCatalog/singleTableInheritance.html + */ +class SingleTablePersister extends AbstractEntityInheritancePersister +{ + /** + * {@inheritdoc} + */ + protected function getDiscriminatorColumnTableName() + { + return $this->class->getTableName(); + } + + /** + * {@inheritdoc} + */ + protected function getSelectColumnsSQL() + { + if ($this->currentPersisterContext->selectColumnListSql !== null) { + return $this->currentPersisterContext->selectColumnListSql; + } + + $columnList[] = parent::getSelectColumnsSQL(); + + $rootClass = $this->em->getClassMetadata($this->class->rootEntityName); + $tableAlias = $this->getSQLTableAlias($rootClass->name); + + // Append discriminator column + $discrColumn = $this->class->discriminatorColumn['name']; + $discrColumnType = $this->class->discriminatorColumn['type']; + + $columnList[] = $tableAlias . '.' . $discrColumn; + + $resultColumnName = $this->platform->getSQLResultCasing($discrColumn); + + $this->currentPersisterContext->rsm->setDiscriminatorColumn('r', $resultColumnName); + $this->currentPersisterContext->rsm->addMetaResult('r', $resultColumnName, $discrColumn, false, $discrColumnType); + + // Append subclass columns + foreach ($this->class->subClasses as $subClassName) { + $subClass = $this->em->getClassMetadata($subClassName); + + // Regular columns + foreach ($subClass->fieldMappings as $fieldName => $mapping) { + if (isset($mapping['inherited'])) { + continue; + } + + $columnList[] = $this->getSelectColumnSQL($fieldName, $subClass); + } + + // Foreign key columns + foreach ($subClass->associationMappings as $assoc) { + if ( ! $assoc['isOwningSide'] || ! ($assoc['type'] & ClassMetadata::TO_ONE) || isset($assoc['inherited'])) { + continue; + } + + $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); + + foreach ($assoc['joinColumns'] as $joinColumn) { + $columnList[] = $this->getSelectJoinColumnSQL( + $tableAlias, + $joinColumn['name'], + $this->quoteStrategy->getJoinColumnName($joinColumn, $subClass, $this->platform), + PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em) + ); + } + } + } + + $this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList); + + return $this->currentPersisterContext->selectColumnListSql; + } + + /** + * {@inheritdoc} + */ + protected function getInsertColumnList() + { + $columns = parent::getInsertColumnList(); + + // Add discriminator column to the INSERT SQL + $columns[] = $this->class->discriminatorColumn['name']; + + return $columns; + } + + /** + * {@inheritdoc} + */ + protected function getSQLTableAlias($className, $assocName = '') + { + return parent::getSQLTableAlias($this->class->rootEntityName, $assocName); + } + + /** + * {@inheritdoc} + */ + protected function getSelectConditionSQL(array $criteria, $assoc = null) + { + $conditionSql = parent::getSelectConditionSQL($criteria, $assoc); + + if ($conditionSql) { + $conditionSql .= ' AND '; + } + + return $conditionSql . $this->getSelectConditionDiscriminatorValueSQL(); + } + + /** + * {@inheritdoc} + */ + protected function getSelectConditionCriteriaSQL(Criteria $criteria) + { + $conditionSql = parent::getSelectConditionCriteriaSQL($criteria); + + if ($conditionSql) { + $conditionSql .= ' AND '; + } + + return $conditionSql . $this->getSelectConditionDiscriminatorValueSQL(); + } + + /** + * @return string + */ + protected function getSelectConditionDiscriminatorValueSQL() + { + $values = []; + + if ($this->class->discriminatorValue !== null) { // discriminators can be 0 + $values[] = $this->conn->quote($this->class->discriminatorValue); + } + + $discrValues = array_flip($this->class->discriminatorMap); + + foreach ($this->class->subClasses as $subclassName) { + $values[] = $this->conn->quote($discrValues[$subclassName]); + } + + $values = implode(', ', $values); + $discColumn = $this->class->discriminatorColumn['name']; + $tableAlias = $this->getSQLTableAlias($this->class->name); + + return $tableAlias . '.' . $discColumn . ' IN (' . $values . ')'; + } + + /** + * {@inheritdoc} + */ + protected function generateFilterConditionSQL(ClassMetadata $targetEntity, $targetTableAlias) + { + // Ensure that the filters are applied to the root entity of the inheritance tree + $targetEntity = $this->em->getClassMetadata($targetEntity->rootEntityName); + // we don't care about the $targetTableAlias, in a STI there is only one table. + + return parent::generateFilterConditionSQL($targetEntity, $targetTableAlias); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/PersisterException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/PersisterException.php new file mode 100644 index 0000000..09f73b2 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/PersisterException.php @@ -0,0 +1,40 @@ +. + */ + +namespace Doctrine\ORM\Persisters; + +use Doctrine\ORM\ORMException; + +class PersisterException extends ORMException +{ + /** + * @param string $class + * @param string $associationName + * + * @return PersisterException + */ + static public function matchingAssocationFieldRequiresObject($class, $associationName) + { + return new self(sprintf( + "Cannot match on %s::%s with a non-object value. Matching objects by id is " . + "not compatible with matching on an in-memory collection, which compares objects by reference.", + $class, $associationName + )); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlExpressionVisitor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlExpressionVisitor.php new file mode 100644 index 0000000..476ecab --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlExpressionVisitor.php @@ -0,0 +1,122 @@ +. + */ + +namespace Doctrine\ORM\Persisters; + +use Doctrine\ORM\Mapping\ClassMetadata; + +use Doctrine\Common\Collections\Expr\ExpressionVisitor; +use Doctrine\Common\Collections\Expr\Comparison; +use Doctrine\Common\Collections\Expr\Value; +use Doctrine\Common\Collections\Expr\CompositeExpression; +use Doctrine\ORM\Persisters\Entity\BasicEntityPersister; + +/** + * Visit Expressions and generate SQL WHERE conditions from them. + * + * @author Benjamin Eberlei + * @since 2.3 + */ +class SqlExpressionVisitor extends ExpressionVisitor +{ + /** + * @var \Doctrine\ORM\Persisters\Entity\BasicEntityPersister + */ + private $persister; + + /** + * @var \Doctrine\ORM\Mapping\ClassMetadata + */ + private $classMetadata; + + /** + * @param \Doctrine\ORM\Persisters\Entity\BasicEntityPersister $persister + * @param \Doctrine\ORM\Mapping\ClassMetadata $classMetadata + */ + public function __construct(BasicEntityPersister $persister, ClassMetadata $classMetadata) + { + $this->persister = $persister; + $this->classMetadata = $classMetadata; + } + + /** + * Converts a comparison expression into the target query language output. + * + * @param \Doctrine\Common\Collections\Expr\Comparison $comparison + * + * @return mixed + */ + public function walkComparison(Comparison $comparison) + { + $field = $comparison->getField(); + $value = $comparison->getValue()->getValue(); // shortcut for walkValue() + + if (isset($this->classMetadata->associationMappings[$field]) && + $value !== null && + ! is_object($value) && + ! in_array($comparison->getOperator(), [Comparison::IN, Comparison::NIN])) { + + throw PersisterException::matchingAssocationFieldRequiresObject($this->classMetadata->name, $field); + } + + return $this->persister->getSelectConditionStatementSQL($field, $value, null, $comparison->getOperator()); + } + + /** + * Converts a composite expression into the target query language output. + * + * @param \Doctrine\Common\Collections\Expr\CompositeExpression $expr + * + * @return mixed + * + * @throws \RuntimeException + */ + public function walkCompositeExpression(CompositeExpression $expr) + { + $expressionList = []; + + foreach ($expr->getExpressionList() as $child) { + $expressionList[] = $this->dispatch($child); + } + + switch($expr->getType()) { + case CompositeExpression::TYPE_AND: + return '(' . implode(' AND ', $expressionList) . ')'; + + case CompositeExpression::TYPE_OR: + return '(' . implode(' OR ', $expressionList) . ')'; + + default: + throw new \RuntimeException("Unknown composite " . $expr->getType()); + } + } + + /** + * Converts a value expression into the target query language part. + * + * @param \Doctrine\Common\Collections\Expr\Value $value + * + * @return mixed + */ + public function walkValue(Value $value) + { + return '?'; + } +} + diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlValueVisitor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlValueVisitor.php new file mode 100644 index 0000000..a5df126 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlValueVisitor.php @@ -0,0 +1,128 @@ +. + */ + +namespace Doctrine\ORM\Persisters; + +use Doctrine\Common\Collections\Expr\ExpressionVisitor; +use Doctrine\Common\Collections\Expr\Comparison; +use Doctrine\Common\Collections\Expr\Value; +use Doctrine\Common\Collections\Expr\CompositeExpression; + +/** + * Extract the values from a criteria/expression + * + * @author Benjamin Eberlei + */ +class SqlValueVisitor extends ExpressionVisitor +{ + /** + * @var array + */ + private $values = []; + + /** + * @var array + */ + private $types = []; + + /** + * Converts a comparison expression into the target query language output. + * + * @param \Doctrine\Common\Collections\Expr\Comparison $comparison + * + * @return void + */ + public function walkComparison(Comparison $comparison) + { + $value = $this->getValueFromComparison($comparison); + $field = $comparison->getField(); + $operator = $comparison->getOperator(); + + if (($operator === Comparison::EQ || $operator === Comparison::IS) && $value === null) { + return; + } else if ($operator === Comparison::NEQ && $value === null) { + return; + } + + $this->values[] = $value; + $this->types[] = [$field, $value, $operator]; + } + + /** + * Converts a composite expression into the target query language output. + * + * @param \Doctrine\Common\Collections\Expr\CompositeExpression $expr + * + * @return void + */ + public function walkCompositeExpression(CompositeExpression $expr) + { + foreach ($expr->getExpressionList() as $child) { + $this->dispatch($child); + } + } + + /** + * Converts a value expression into the target query language part. + * + * @param \Doctrine\Common\Collections\Expr\Value $value + * + * @return mixed + */ + public function walkValue(Value $value) + { + return; + } + + /** + * Returns the Parameters and Types necessary for matching the last visited expression. + * + * @return array + */ + public function getParamsAndTypes() + { + return [$this->values, $this->types]; + } + + /** + * Returns the value from a Comparison. In case of a CONTAINS comparison, + * the value is wrapped in %-signs, because it will be used in a LIKE clause. + * + * @param \Doctrine\Common\Collections\Expr\Comparison $comparison + * @return mixed + */ + protected function getValueFromComparison(Comparison $comparison) + { + $value = $comparison->getValue()->getValue(); + + switch ($comparison->getOperator()) { + case Comparison::CONTAINS: + return "%{$value}%"; + + case Comparison::STARTS_WITH: + return "{$value}%"; + + case Comparison::ENDS_WITH: + return "%{$value}"; + + default: + return $value; + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/PessimisticLockException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/PessimisticLockException.php new file mode 100644 index 0000000..d60f7a8 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/PessimisticLockException.php @@ -0,0 +1,40 @@ +. + */ + +namespace Doctrine\ORM; + +/** + * Pessimistic Lock Exception + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.com + * @since 1.0 + * @author Benjamin Eberlei + * @author Roman Borschel + */ +class PessimisticLockException extends ORMException +{ + /** + * @return PessimisticLockException + */ + public static function lockFailed() + { + return new self("The pessimistic lock failed."); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Autoloader.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Autoloader.php new file mode 100644 index 0000000..9b2e2cd --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Autoloader.php @@ -0,0 +1,29 @@ +. + */ + +namespace Doctrine\ORM\Proxy; + +use Doctrine\Common\Proxy\Autoloader as BaseAutoloader; + +/** + * @deprecated use \Doctrine\Common\Proxy\Autoloader instead + */ +class Autoloader extends BaseAutoloader +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Proxy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Proxy.php new file mode 100644 index 0000000..75a61a7 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Proxy.php @@ -0,0 +1,34 @@ +. + */ + +namespace Doctrine\ORM\Proxy; + +use Doctrine\Common\Proxy\Proxy as BaseProxy; + +/** + * Interface for proxy classes. + * + * @author Roman Borschel + * @since 2.0 + * + * @deprecated 2.7 This interface is being removed from the ORM and won't have any replacement, proxies will no longer implement it. + */ +interface Proxy extends BaseProxy +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php new file mode 100644 index 0000000..31fac18 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php @@ -0,0 +1,213 @@ +. + */ + +namespace Doctrine\ORM\Proxy; + +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Doctrine\Common\Proxy\AbstractProxyFactory; +use Doctrine\Common\Proxy\Proxy as BaseProxy; +use Doctrine\Common\Proxy\ProxyDefinition; +use Doctrine\Common\Proxy\ProxyGenerator; +use Doctrine\Common\Util\ClassUtils; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Persisters\Entity\EntityPersister; +use Doctrine\ORM\EntityNotFoundException; +use Doctrine\ORM\Utility\IdentifierFlattener; + +/** + * This factory is used to create proxy objects for entities at runtime. + * + * @author Roman Borschel + * @author Giorgio Sironi + * @author Marco Pivetta + * @since 2.0 + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class ProxyFactory extends AbstractProxyFactory +{ + /** + * @var EntityManagerInterface The EntityManager this factory is bound to. + */ + private $em; + + /** + * @var \Doctrine\ORM\UnitOfWork The UnitOfWork this factory uses to retrieve persisters + */ + private $uow; + + /** + * @var string + */ + private $proxyNs; + + /** + * The IdentifierFlattener used for manipulating identifiers + * + * @var \Doctrine\ORM\Utility\IdentifierFlattener + */ + private $identifierFlattener; + + /** + * Initializes a new instance of the ProxyFactory class that is + * connected to the given EntityManager. + * + * @param EntityManagerInterface $em The EntityManager the new factory works for. + * @param string $proxyDir The directory to use for the proxy classes. It must exist. + * @param string $proxyNs The namespace to use for the proxy classes. + * @param boolean|int $autoGenerate The strategy for automatically generating proxy classes. Possible + * values are constants of Doctrine\Common\Proxy\AbstractProxyFactory. + */ + public function __construct(EntityManagerInterface $em, $proxyDir, $proxyNs, $autoGenerate = AbstractProxyFactory::AUTOGENERATE_NEVER) + { + $proxyGenerator = new ProxyGenerator($proxyDir, $proxyNs); + + $proxyGenerator->setPlaceholder('baseProxyInterface', Proxy::class); + parent::__construct($proxyGenerator, $em->getMetadataFactory(), $autoGenerate); + + $this->em = $em; + $this->uow = $em->getUnitOfWork(); + $this->proxyNs = $proxyNs; + $this->identifierFlattener = new IdentifierFlattener($this->uow, $em->getMetadataFactory()); + } + + /** + * {@inheritDoc} + */ + protected function skipClass(ClassMetadata $metadata) + { + /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */ + return $metadata->isMappedSuperclass + || $metadata->isEmbeddedClass + || $metadata->getReflectionClass()->isAbstract(); + } + + /** + * {@inheritDoc} + */ + protected function createProxyDefinition($className) + { + $classMetadata = $this->em->getClassMetadata($className); + $entityPersister = $this->uow->getEntityPersister($className); + + return new ProxyDefinition( + ClassUtils::generateProxyClassName($className, $this->proxyNs), + $classMetadata->getIdentifierFieldNames(), + $classMetadata->getReflectionProperties(), + $this->createInitializer($classMetadata, $entityPersister), + $this->createCloner($classMetadata, $entityPersister) + ); + } + + /** + * Creates a closure capable of initializing a proxy + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $classMetadata + * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $entityPersister + * + * @return \Closure + * + * @throws \Doctrine\ORM\EntityNotFoundException + */ + private function createInitializer(ClassMetadata $classMetadata, EntityPersister $entityPersister) + { + $wakeupProxy = $classMetadata->getReflectionClass()->hasMethod('__wakeup'); + + return function (BaseProxy $proxy) use ($entityPersister, $classMetadata, $wakeupProxy) { + $initializer = $proxy->__getInitializer(); + $cloner = $proxy->__getCloner(); + + $proxy->__setInitializer(null); + $proxy->__setCloner(null); + + if ($proxy->__isInitialized()) { + return; + } + + $properties = $proxy->__getLazyProperties(); + + foreach ($properties as $propertyName => $property) { + if ( ! isset($proxy->$propertyName)) { + $proxy->$propertyName = $properties[$propertyName]; + } + } + + $proxy->__setInitialized(true); + + if ($wakeupProxy) { + $proxy->__wakeup(); + } + + $identifier = $classMetadata->getIdentifierValues($proxy); + + if (null === $entityPersister->loadById($identifier, $proxy)) { + $proxy->__setInitializer($initializer); + $proxy->__setCloner($cloner); + $proxy->__setInitialized(false); + + throw EntityNotFoundException::fromClassNameAndIdentifier( + $classMetadata->getName(), + $this->identifierFlattener->flattenIdentifier($classMetadata, $identifier) + ); + } + }; + } + + /** + * Creates a closure capable of finalizing state a cloned proxy + * + * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $classMetadata + * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $entityPersister + * + * @return \Closure + * + * @throws \Doctrine\ORM\EntityNotFoundException + */ + private function createCloner(ClassMetadata $classMetadata, EntityPersister $entityPersister) + { + return function (BaseProxy $proxy) use ($entityPersister, $classMetadata) { + if ($proxy->__isInitialized()) { + return; + } + + $proxy->__setInitialized(true); + $proxy->__setInitializer(null); + + $class = $entityPersister->getClassMetadata(); + $identifier = $classMetadata->getIdentifierValues($proxy); + $original = $entityPersister->loadById($identifier); + + if (null === $original) { + throw EntityNotFoundException::fromClassNameAndIdentifier( + $classMetadata->getName(), + $this->identifierFlattener->flattenIdentifier($classMetadata, $identifier) + ); + } + + foreach ($class->getReflectionProperties() as $property) { + if ( ! $class->hasField($property->name) && ! $class->hasAssociation($property->name)) { + continue; + } + + $property->setAccessible(true); + $property->setValue($proxy, $property->getValue($original)); + } + }; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query.php new file mode 100644 index 0000000..c9d8fb6 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query.php @@ -0,0 +1,794 @@ +. + */ + +namespace Doctrine\ORM; + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\DBAL\LockMode; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Query\Exec\AbstractSqlExecutor; +use Doctrine\ORM\Query\Parameter; +use Doctrine\ORM\Query\ParameterTypeInferer; +use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\ParserResult; +use Doctrine\ORM\Query\QueryException; +use Doctrine\ORM\Utility\HierarchyDiscriminatorResolver; +use function array_keys; +use function assert; + +/** + * A Query object represents a DQL query. + * + * @since 1.0 + * @author Guilherme Blanco + * @author Konsta Vesterinen + * @author Roman Borschel + */ +final class Query extends AbstractQuery +{ + /** + * A query object is in CLEAN state when it has NO unparsed/unprocessed DQL parts. + */ + const STATE_CLEAN = 1; + + /** + * A query object is in state DIRTY when it has DQL parts that have not yet been + * parsed/processed. This is automatically defined as DIRTY when addDqlQueryPart + * is called. + */ + const STATE_DIRTY = 2; + + /* Query HINTS */ + + /** + * The refresh hint turns any query into a refresh query with the result that + * any local changes in entities are overridden with the fetched values. + * + * @var string + */ + const HINT_REFRESH = 'doctrine.refresh'; + + /** + * @var string + */ + const HINT_CACHE_ENABLED = 'doctrine.cache.enabled'; + + /** + * @var string + */ + const HINT_CACHE_EVICT = 'doctrine.cache.evict'; + + /** + * Internal hint: is set to the proxy entity that is currently triggered for loading + * + * @var string + */ + const HINT_REFRESH_ENTITY = 'doctrine.refresh.entity'; + + /** + * The forcePartialLoad query hint forces a particular query to return + * partial objects. + * + * @var string + * @todo Rename: HINT_OPTIMIZE + */ + const HINT_FORCE_PARTIAL_LOAD = 'doctrine.forcePartialLoad'; + + /** + * The includeMetaColumns query hint causes meta columns like foreign keys and + * discriminator columns to be selected and returned as part of the query result. + * + * This hint does only apply to non-object queries. + * + * @var string + */ + const HINT_INCLUDE_META_COLUMNS = 'doctrine.includeMetaColumns'; + + /** + * An array of class names that implement \Doctrine\ORM\Query\TreeWalker and + * are iterated and executed after the DQL has been parsed into an AST. + * + * @var string + */ + const HINT_CUSTOM_TREE_WALKERS = 'doctrine.customTreeWalkers'; + + /** + * A string with a class name that implements \Doctrine\ORM\Query\TreeWalker + * and is used for generating the target SQL from any DQL AST tree. + * + * @var string + */ + const HINT_CUSTOM_OUTPUT_WALKER = 'doctrine.customOutputWalker'; + + //const HINT_READ_ONLY = 'doctrine.readOnly'; + + /** + * @var string + */ + const HINT_INTERNAL_ITERATION = 'doctrine.internal.iteration'; + + /** + * @var string + */ + const HINT_LOCK_MODE = 'doctrine.lockMode'; + + /** + * The current state of this query. + * + * @var integer + */ + private $_state = self::STATE_CLEAN; + + /** + * A snapshot of the parameter types the query was parsed with. + * + * @var array + */ + private $_parsedTypes = []; + + /** + * Cached DQL query. + * + * @var string|null + */ + private $_dql = null; + + /** + * The parser result that holds DQL => SQL information. + * + * @var \Doctrine\ORM\Query\ParserResult + */ + private $_parserResult; + + /** + * The first result to return (the "offset"). + * + * @var int|null + */ + private $_firstResult = null; + + /** + * The maximum number of results to return (the "limit"). + * + * @var integer|null + */ + private $_maxResults = null; + + /** + * The cache driver used for caching queries. + * + * @var \Doctrine\Common\Cache\Cache|null + */ + private $_queryCache; + + /** + * Whether or not expire the query cache. + * + * @var boolean + */ + private $_expireQueryCache = false; + + /** + * The query cache lifetime. + * + * @var int + */ + private $_queryCacheTTL; + + /** + * Whether to use a query cache, if available. Defaults to TRUE. + * + * @var boolean + */ + private $_useQueryCache = true; + + /** + * Gets the SQL query/queries that correspond to this DQL query. + * + * @return mixed The built sql query or an array of all sql queries. + * + * @override + */ + public function getSQL() + { + return $this->_parse()->getSqlExecutor()->getSqlStatements(); + } + + /** + * Returns the corresponding AST for this DQL query. + * + * @return \Doctrine\ORM\Query\AST\SelectStatement | + * \Doctrine\ORM\Query\AST\UpdateStatement | + * \Doctrine\ORM\Query\AST\DeleteStatement + */ + public function getAST() + { + $parser = new Parser($this); + + return $parser->getAST(); + } + + /** + * {@inheritdoc} + */ + protected function getResultSetMapping() + { + // parse query or load from cache + if ($this->_resultSetMapping === null) { + $this->_resultSetMapping = $this->_parse()->getResultSetMapping(); + } + + return $this->_resultSetMapping; + } + + /** + * Parses the DQL query, if necessary, and stores the parser result. + * + * Note: Populates $this->_parserResult as a side-effect. + * + * @return \Doctrine\ORM\Query\ParserResult + */ + private function _parse() + { + $types = []; + + foreach ($this->parameters as $parameter) { + /** @var Query\Parameter $parameter */ + $types[$parameter->getName()] = $parameter->getType(); + } + + // Return previous parser result if the query and the filter collection are both clean + if ($this->_state === self::STATE_CLEAN && $this->_parsedTypes === $types && $this->_em->isFiltersStateClean()) { + return $this->_parserResult; + } + + $this->_state = self::STATE_CLEAN; + $this->_parsedTypes = $types; + + // Check query cache. + if ( ! ($this->_useQueryCache && ($queryCache = $this->getQueryCacheDriver()))) { + $parser = new Parser($this); + + $this->_parserResult = $parser->parse(); + + return $this->_parserResult; + } + + $hash = $this->_getQueryCacheId(); + $cached = $this->_expireQueryCache ? false : $queryCache->fetch($hash); + + if ($cached instanceof ParserResult) { + // Cache hit. + $this->_parserResult = $cached; + + return $this->_parserResult; + } + + // Cache miss. + $parser = new Parser($this); + + $this->_parserResult = $parser->parse(); + + $queryCache->save($hash, $this->_parserResult, $this->_queryCacheTTL); + + return $this->_parserResult; + } + + /** + * {@inheritdoc} + */ + protected function _doExecute() + { + $executor = $this->_parse()->getSqlExecutor(); + + if ($this->_queryCacheProfile) { + $executor->setQueryCacheProfile($this->_queryCacheProfile); + } else { + $executor->removeQueryCacheProfile(); + } + + if ($this->_resultSetMapping === null) { + $this->_resultSetMapping = $this->_parserResult->getResultSetMapping(); + } + + // Prepare parameters + $paramMappings = $this->_parserResult->getParameterMappings(); + $paramCount = count($this->parameters); + $mappingCount = count($paramMappings); + + if ($paramCount > $mappingCount) { + throw QueryException::tooManyParameters($mappingCount, $paramCount); + } + + if ($paramCount < $mappingCount) { + throw QueryException::tooFewParameters($mappingCount, $paramCount); + } + + // evict all cache for the entity region + if ($this->hasCache && isset($this->_hints[self::HINT_CACHE_EVICT]) && $this->_hints[self::HINT_CACHE_EVICT]) { + $this->evictEntityCacheRegion(); + } + + list($sqlParams, $types) = $this->processParameterMappings($paramMappings); + + $this->evictResultSetCache( + $executor, + $sqlParams, + $types, + $this->_em->getConnection()->getParams() + ); + + return $executor->execute($this->_em->getConnection(), $sqlParams, $types); + } + + private function evictResultSetCache( + AbstractSqlExecutor $executor, + array $sqlParams, + array $types, + array $connectionParams + ) { + if (null === $this->_queryCacheProfile || ! $this->getExpireResultCache()) { + return; + } + + $cacheDriver = $this->_queryCacheProfile->getResultCacheDriver(); + $statements = (array) $executor->getSqlStatements(); // Type casted since it can either be a string or an array + + foreach ($statements as $statement) { + $cacheKeys = $this->_queryCacheProfile->generateCacheKeys($statement, $sqlParams, $types, $connectionParams); + + $cacheDriver->delete(reset($cacheKeys)); + } + } + + /** + * Evict entity cache region + */ + private function evictEntityCacheRegion() + { + $AST = $this->getAST(); + + if ($AST instanceof \Doctrine\ORM\Query\AST\SelectStatement) { + throw new QueryException('The hint "HINT_CACHE_EVICT" is not valid for select statements.'); + } + + $className = ($AST instanceof \Doctrine\ORM\Query\AST\DeleteStatement) + ? $AST->deleteClause->abstractSchemaName + : $AST->updateClause->abstractSchemaName; + + $this->_em->getCache()->evictEntityRegion($className); + } + + /** + * Processes query parameter mappings. + * + * @param array $paramMappings + * + * @return array + * + * @throws Query\QueryException + */ + private function processParameterMappings($paramMappings) + { + $sqlParams = []; + $types = []; + + foreach ($this->parameters as $parameter) { + $key = $parameter->getName(); + + if ( ! isset($paramMappings[$key])) { + throw QueryException::unknownParameter($key); + } + + [$value, $type] = $this->resolveParameterValue($parameter); + + foreach ($paramMappings[$key] as $position) { + $types[$position] = $type; + } + + $sqlPositions = $paramMappings[$key]; + + // optimized multi value sql positions away for now, + // they are not allowed in DQL anyways. + $value = [$value]; + $countValue = count($value); + + for ($i = 0, $l = count($sqlPositions); $i < $l; $i++) { + $sqlParams[$sqlPositions[$i]] = $value[($i % $countValue)]; + } + } + + if (count($sqlParams) != count($types)) { + throw QueryException::parameterTypeMismatch(); + } + + if ($sqlParams) { + ksort($sqlParams); + $sqlParams = array_values($sqlParams); + + ksort($types); + $types = array_values($types); + } + + return [$sqlParams, $types]; + } + + /** @return mixed[] tuple of (value, type) */ + private function resolveParameterValue(Parameter $parameter) : array + { + if ($parameter->typeWasSpecified()) { + return [$parameter->getValue(), $parameter->getType()]; + } + + $key = $parameter->getName(); + $originalValue = $parameter->getValue(); + $value = $originalValue; + $rsm = $this->getResultSetMapping(); + + assert($rsm !== null); + + if ($value instanceof ClassMetadata && isset($rsm->metadataParameterMapping[$key])) { + $value = $value->getMetadataValue($rsm->metadataParameterMapping[$key]); + } + + if ($value instanceof ClassMetadata && isset($rsm->discriminatorParameters[$key])) { + $value = array_keys(HierarchyDiscriminatorResolver::resolveDiscriminatorsForClass($value, $this->_em)); + } + + $processedValue = $this->processParameterValue($value); + + return [ + $processedValue, + $originalValue === $processedValue + ? $parameter->getType() + : ParameterTypeInferer::inferType($processedValue), + ]; + } + + /** + * Defines a cache driver to be used for caching queries. + * + * @param \Doctrine\Common\Cache\Cache|null $queryCache Cache driver. + * + * @return Query This query instance. + */ + public function setQueryCacheDriver($queryCache) + { + $this->_queryCache = $queryCache; + + return $this; + } + + /** + * Defines whether the query should make use of a query cache, if available. + * + * @param boolean $bool + * + * @return Query This query instance. + */ + public function useQueryCache($bool) + { + $this->_useQueryCache = $bool; + + return $this; + } + + /** + * Returns the cache driver used for query caching. + * + * @return \Doctrine\Common\Cache\Cache|null The cache driver used for query caching or NULL, if + * this Query does not use query caching. + */ + public function getQueryCacheDriver() + { + if ($this->_queryCache) { + return $this->_queryCache; + } + + return $this->_em->getConfiguration()->getQueryCacheImpl(); + } + + /** + * Defines how long the query cache will be active before expire. + * + * @param integer $timeToLive How long the cache entry is valid. + * + * @return Query This query instance. + */ + public function setQueryCacheLifetime($timeToLive) + { + if ($timeToLive !== null) { + $timeToLive = (int) $timeToLive; + } + + $this->_queryCacheTTL = $timeToLive; + + return $this; + } + + /** + * Retrieves the lifetime of resultset cache. + * + * @return int + */ + public function getQueryCacheLifetime() + { + return $this->_queryCacheTTL; + } + + /** + * Defines if the query cache is active or not. + * + * @param boolean $expire Whether or not to force query cache expiration. + * + * @return Query This query instance. + */ + public function expireQueryCache($expire = true) + { + $this->_expireQueryCache = $expire; + + return $this; + } + + /** + * Retrieves if the query cache is active or not. + * + * @return bool + */ + public function getExpireQueryCache() + { + return $this->_expireQueryCache; + } + + /** + * @override + */ + public function free() + { + parent::free(); + + $this->_dql = null; + $this->_state = self::STATE_CLEAN; + } + + /** + * Sets a DQL query string. + * + * @param string $dqlQuery DQL Query. + * + * @return \Doctrine\ORM\AbstractQuery + */ + public function setDQL($dqlQuery) + { + if ($dqlQuery !== null) { + $this->_dql = $dqlQuery; + $this->_state = self::STATE_DIRTY; + } + + return $this; + } + + /** + * Returns the DQL query that is represented by this query object. + * + * @return string|null + */ + public function getDQL() + { + return $this->_dql; + } + + /** + * Returns the state of this query object + * By default the type is Doctrine_ORM_Query_Abstract::STATE_CLEAN but if it appears any unprocessed DQL + * part, it is switched to Doctrine_ORM_Query_Abstract::STATE_DIRTY. + * + * @see AbstractQuery::STATE_CLEAN + * @see AbstractQuery::STATE_DIRTY + * + * @return integer The query state. + */ + public function getState() + { + return $this->_state; + } + + /** + * Method to check if an arbitrary piece of DQL exists + * + * @param string $dql Arbitrary piece of DQL to check for. + * + * @return boolean + */ + public function contains($dql) + { + return stripos($this->getDQL(), $dql) !== false; + } + + /** + * Sets the position of the first result to retrieve (the "offset"). + * + * @param integer $firstResult The first result to return. + * + * @return Query This query object. + */ + public function setFirstResult($firstResult) + { + $this->_firstResult = $firstResult; + $this->_state = self::STATE_DIRTY; + + return $this; + } + + /** + * Gets the position of the first result the query object was set to retrieve (the "offset"). + * Returns NULL if {@link setFirstResult} was not applied to this query. + * + * @return int|null The position of the first result. + */ + public function getFirstResult() + { + return $this->_firstResult; + } + + /** + * Sets the maximum number of results to retrieve (the "limit"). + * + * @param integer|null $maxResults + * + * @return Query This query object. + */ + public function setMaxResults($maxResults) + { + $this->_maxResults = $maxResults; + $this->_state = self::STATE_DIRTY; + + return $this; + } + + /** + * Gets the maximum number of results the query object was set to retrieve (the "limit"). + * Returns NULL if {@link setMaxResults} was not applied to this query. + * + * @return integer|null Maximum number of results. + */ + public function getMaxResults() + { + return $this->_maxResults; + } + + /** + * Executes the query and returns an IterableResult that can be used to incrementally + * iterated over the result. + * + * @param ArrayCollection|array|null $parameters The query parameters. + * @param string|int $hydrationMode The hydration mode to use. + * + * @return \Doctrine\ORM\Internal\Hydration\IterableResult + */ + public function iterate($parameters = null, $hydrationMode = self::HYDRATE_OBJECT) + { + $this->setHint(self::HINT_INTERNAL_ITERATION, true); + + return parent::iterate($parameters, $hydrationMode); + } + + /** + * {@inheritdoc} + */ + public function setHint($name, $value) + { + $this->_state = self::STATE_DIRTY; + + return parent::setHint($name, $value); + } + + /** + * {@inheritdoc} + */ + public function setHydrationMode($hydrationMode) + { + $this->_state = self::STATE_DIRTY; + + return parent::setHydrationMode($hydrationMode); + } + + /** + * Set the lock mode for this Query. + * + * @see \Doctrine\DBAL\LockMode + * + * @param int $lockMode + * + * @return Query + * + * @throws TransactionRequiredException + */ + public function setLockMode($lockMode) + { + if (in_array($lockMode, [LockMode::NONE, LockMode::PESSIMISTIC_READ, LockMode::PESSIMISTIC_WRITE], true)) { + if ( ! $this->_em->getConnection()->isTransactionActive()) { + throw TransactionRequiredException::transactionRequired(); + } + } + + $this->setHint(self::HINT_LOCK_MODE, $lockMode); + + return $this; + } + + /** + * Get the current lock mode for this query. + * + * @return int|null The current lock mode of this query or NULL if no specific lock mode is set. + */ + public function getLockMode() + { + $lockMode = $this->getHint(self::HINT_LOCK_MODE); + + if (false === $lockMode) { + return null; + } + + return $lockMode; + } + + /** + * Generate a cache id for the query cache - reusing the Result-Cache-Id generator. + * + * @return string + */ + protected function _getQueryCacheId() + { + ksort($this->_hints); + + $platform = $this->getEntityManager() + ->getConnection() + ->getDatabasePlatform() + ->getName(); + + return md5( + $this->getDQL() . serialize($this->_hints) . + '&platform=' . $platform . + ($this->_em->hasFilters() ? $this->_em->getFilters()->getHash() : '') . + '&firstResult=' . $this->_firstResult . '&maxResult=' . $this->_maxResults . + '&hydrationMode=' . $this->_hydrationMode . '&types=' . serialize($this->_parsedTypes) . 'DOCTRINE_QUERY_CACHE_SALT' + ); + } + + /** + * {@inheritdoc} + */ + protected function getHash() + { + return sha1(parent::getHash(). '-'. $this->_firstResult . '-' . $this->_maxResults); + } + + /** + * Cleanup Query resource when clone is called. + * + * @return void + */ + public function __clone() + { + parent::__clone(); + + $this->_state = self::STATE_DIRTY; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ASTException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ASTException.php new file mode 100644 index 0000000..b8f931b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ASTException.php @@ -0,0 +1,38 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +use Doctrine\ORM\Query\QueryException; + +/** + * Base exception class for AST exceptions. + */ +class ASTException extends QueryException +{ + /** + * @param Node $node + * + * @return ASTException + */ + public static function noDispatchForNode($node) + { + return new self("Double-dispatch for node " . get_class($node) . " is not supported."); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/AggregateExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/AggregateExpression.php new file mode 100644 index 0000000..0966d90 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/AggregateExpression.php @@ -0,0 +1,69 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * Description of AggregateExpression. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class AggregateExpression extends Node +{ + /** + * @var string + */ + public $functionName; + + /** + * @var PathExpression|SimpleArithmeticExpression + */ + public $pathExpression; + + /** + * Some aggregate expressions support distinct, eg COUNT. + * + * @var bool + */ + public $isDistinct = false; + + /** + * @param string $functionName + * @param PathExpression|SimpleArithmeticExpression $pathExpression + * @param bool $isDistinct + */ + public function __construct($functionName, $pathExpression, $isDistinct) + { + $this->functionName = $functionName; + $this->pathExpression = $pathExpression; + $this->isDistinct = $isDistinct; + } + + /** + * {@inheritdoc} + */ + public function dispatch($walker) + { + return $walker->walkAggregateExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticExpression.php new file mode 100644 index 0000000..b586cba --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticExpression.php @@ -0,0 +1,66 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")" + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ArithmeticExpression extends Node +{ + /** + * @var SimpleArithmeticExpression|null + */ + public $simpleArithmeticExpression; + + /** + * @var Subselect|null + */ + public $subselect; + + /** + * @return bool + */ + public function isSimpleArithmeticExpression() + { + return (bool) $this->simpleArithmeticExpression; + } + + /** + * @return bool + */ + public function isSubselect() + { + return (bool) $this->subselect; + } + + /** + * {@inheritdoc} + */ + public function dispatch($walker) + { + return $walker->walkArithmeticExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticFactor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticFactor.php new file mode 100644 index 0000000..3120466 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticFactor.php @@ -0,0 +1,78 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * ArithmeticFactor ::= [("+" | "-")] ArithmeticPrimary + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ArithmeticFactor extends Node +{ + /** + * @var mixed + */ + public $arithmeticPrimary; + + /** + * NULL represents no sign, TRUE means positive and FALSE means negative sign. + * + * @var null|boolean + */ + public $sign; + + /** + * @param mixed $arithmeticPrimary + * @param null|bool $sign + */ + public function __construct($arithmeticPrimary, $sign = null) + { + $this->arithmeticPrimary = $arithmeticPrimary; + $this->sign = $sign; + } + + /** + * @return bool + */ + public function isPositiveSigned() + { + return $this->sign === true; + } + + /** + * @return bool + */ + public function isNegativeSigned() + { + return $this->sign === false; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkArithmeticFactor($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticTerm.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticTerm.php new file mode 100644 index 0000000..e08ae7f --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticTerm.php @@ -0,0 +1,53 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * ArithmeticTerm ::= ArithmeticFactor {("*" | "/") ArithmeticFactor}* + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ArithmeticTerm extends Node +{ + /** + * @var array + */ + public $arithmeticFactors; + + /** + * @param array $arithmeticFactors + */ + public function __construct(array $arithmeticFactors) + { + $this->arithmeticFactors = $arithmeticFactors; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkArithmeticTerm($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/BetweenExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/BetweenExpression.php new file mode 100644 index 0000000..1e31fd1 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/BetweenExpression.php @@ -0,0 +1,72 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * Description of BetweenExpression. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class BetweenExpression extends Node +{ + /** + * @var ArithmeticExpression + */ + public $expression; + + /** + * @var ArithmeticExpression + */ + public $leftBetweenExpression; + + /** + * @var ArithmeticExpression + */ + public $rightBetweenExpression; + + /** + * @var bool + */ + public $not; + + /** + * @param ArithmeticExpression $expr + * @param ArithmeticExpression $leftExpr + * @param ArithmeticExpression $rightExpr + */ + public function __construct($expr, $leftExpr, $rightExpr) + { + $this->expression = $expr; + $this->leftBetweenExpression = $leftExpr; + $this->rightBetweenExpression = $rightExpr; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkBetweenExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CoalesceExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CoalesceExpression.php new file mode 100644 index 0000000..9e3b4c5 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CoalesceExpression.php @@ -0,0 +1,55 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * CoalesceExpression ::= "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")" + * + * @since 2.1 + * + * @link www.doctrine-project.org + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class CoalesceExpression extends Node +{ + /** + * @var array + */ + public $scalarExpressions = []; + + /** + * @param array $scalarExpressions + */ + public function __construct(array $scalarExpressions) + { + $this->scalarExpressions = $scalarExpressions; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkCoalesceExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CollectionMemberExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CollectionMemberExpression.php new file mode 100644 index 0000000..70989a2 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CollectionMemberExpression.php @@ -0,0 +1,63 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * CollectionMemberExpression ::= EntityExpression ["NOT"] "MEMBER" ["OF"] CollectionValuedPathExpression + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class CollectionMemberExpression extends Node +{ + public $entityExpression; + + /** + * @var PathExpression + */ + public $collectionValuedPathExpression; + + /** + * @var bool + */ + public $not; + + /** + * @param mixed $entityExpr + * @param PathExpression $collValuedPathExpr + */ + public function __construct($entityExpr, $collValuedPathExpr) + { + $this->entityExpression = $entityExpr; + $this->collectionValuedPathExpression = $collValuedPathExpr; + } + + /** + * {@inheritdoc} + */ + public function dispatch($walker) + { + return $walker->walkCollectionMemberExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ComparisonExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ComparisonExpression.php new file mode 100644 index 0000000..ad4d222 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ComparisonExpression.php @@ -0,0 +1,72 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression ) | + * StringExpression ComparisonOperator (StringExpression | QuantifiedExpression) | + * BooleanExpression ("=" | "<>" | "!=") (BooleanExpression | QuantifiedExpression) | + * EnumExpression ("=" | "<>" | "!=") (EnumExpression | QuantifiedExpression) | + * DatetimeExpression ComparisonOperator (DatetimeExpression | QuantifiedExpression) | + * EntityExpression ("=" | "<>") (EntityExpression | QuantifiedExpression) + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ComparisonExpression extends Node +{ + /** + * @var Node + */ + public $leftExpression; + + /** + * @var Node + */ + public $rightExpression; + + /** + * @var string + */ + public $operator; + + /** + * @param Node $leftExpr + * @param string $operator + * @param Node $rightExpr + */ + public function __construct($leftExpr, $operator, $rightExpr) + { + $this->leftExpression = $leftExpr; + $this->rightExpression = $rightExpr; + $this->operator = $operator; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkComparisonExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalExpression.php new file mode 100644 index 0000000..bf82362 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalExpression.php @@ -0,0 +1,53 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * ConditionalExpression ::= ConditionalTerm {"OR" ConditionalTerm}* + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ConditionalExpression extends Node +{ + /** + * @var array + */ + public $conditionalTerms = []; + + /** + * @param array $conditionalTerms + */ + public function __construct(array $conditionalTerms) + { + $this->conditionalTerms = $conditionalTerms; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkConditionalExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalFactor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalFactor.php new file mode 100644 index 0000000..7c89faa --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalFactor.php @@ -0,0 +1,58 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * ConditionalFactor ::= ["NOT"] ConditionalPrimary + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ConditionalFactor extends Node +{ + /** + * @var bool + */ + public $not = false; + + /** + * @var ConditionalPrimary + */ + public $conditionalPrimary; + + /** + * @param ConditionalPrimary $conditionalPrimary + */ + public function __construct($conditionalPrimary) + { + $this->conditionalPrimary = $conditionalPrimary; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkConditionalFactor($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalPrimary.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalPrimary.php new file mode 100644 index 0000000..1eed41d --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalPrimary.php @@ -0,0 +1,66 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")" + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ConditionalPrimary extends Node +{ + /** + * @var Node|null + */ + public $simpleConditionalExpression; + + /** + * @var ConditionalExpression|null + */ + public $conditionalExpression; + + /** + * @return bool + */ + public function isSimpleConditionalExpression() + { + return (bool) $this->simpleConditionalExpression; + } + + /** + * @return bool + */ + public function isConditionalExpression() + { + return (bool) $this->conditionalExpression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkConditionalPrimary($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalTerm.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalTerm.php new file mode 100644 index 0000000..7122c9c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalTerm.php @@ -0,0 +1,52 @@ +. + */ +namespace Doctrine\ORM\Query\AST; + +/** + * ConditionalTerm ::= ConditionalFactor {"AND" ConditionalFactor}* + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ConditionalTerm extends Node +{ + /** + * @var array + */ + public $conditionalFactors = []; + + /** + * @param array $conditionalFactors + */ + public function __construct(array $conditionalFactors) + { + $this->conditionalFactors = $conditionalFactors; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkConditionalTerm($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteClause.php new file mode 100644 index 0000000..8ca35c6 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteClause.php @@ -0,0 +1,58 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * DeleteClause ::= "DELETE" ["FROM"] AbstractSchemaName [["AS"] AliasIdentificationVariable] + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class DeleteClause extends Node +{ + /** + * @var string + */ + public $abstractSchemaName; + + /** + * @var string + */ + public $aliasIdentificationVariable; + + /** + * @param string $abstractSchemaName + */ + public function __construct($abstractSchemaName) + { + $this->abstractSchemaName = $abstractSchemaName; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkDeleteClause($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteStatement.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteStatement.php new file mode 100644 index 0000000..da6859b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteStatement.php @@ -0,0 +1,58 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * DeleteStatement = DeleteClause [WhereClause] + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class DeleteStatement extends Node +{ + /** + * @var DeleteClause + */ + public $deleteClause; + + /** + * @var WhereClause|null + */ + public $whereClause; + + /** + * @param DeleteClause $deleteClause + */ + public function __construct($deleteClause) + { + $this->deleteClause = $deleteClause; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkDeleteStatement($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/EmptyCollectionComparisonExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/EmptyCollectionComparisonExpression.php new file mode 100644 index 0000000..bd978af --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/EmptyCollectionComparisonExpression.php @@ -0,0 +1,58 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * EmptyCollectionComparisonExpression ::= CollectionValuedPathExpression "IS" ["NOT"] "EMPTY" + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class EmptyCollectionComparisonExpression extends Node +{ + /** + * @var PathExpression + */ + public $expression; + + /** + * @var bool + */ + public $not; + + /** + * @param PathExpression $expression + */ + public function __construct($expression) + { + $this->expression = $expression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkEmptyCollectionComparisonExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ExistsExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ExistsExpression.php new file mode 100644 index 0000000..c53a107 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ExistsExpression.php @@ -0,0 +1,58 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * ExistsExpression ::= ["NOT"] "EXISTS" "(" Subselect ")" + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ExistsExpression extends Node +{ + /** + * @var bool + */ + public $not; + + /** + * @var Subselect + */ + public $subselect; + + /** + * @param Subselect $subselect + */ + public function __construct($subselect) + { + $this->subselect = $subselect; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkExistsExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/FromClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/FromClause.php new file mode 100644 index 0000000..fdb61ca --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/FromClause.php @@ -0,0 +1,54 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration} + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class FromClause extends Node +{ + /** + * @var array + */ + public $identificationVariableDeclarations = []; + + /** + * @param array $identificationVariableDeclarations + */ + public function __construct(array $identificationVariableDeclarations) + { + $this->identificationVariableDeclarations = $identificationVariableDeclarations; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkFromClause($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AbsFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AbsFunction.php new file mode 100644 index 0000000..4c61435 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AbsFunction.php @@ -0,0 +1,66 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "ABS" "(" SimpleArithmeticExpression ")" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class AbsFunction extends FunctionNode +{ + /** + * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression + */ + public $simpleArithmeticExpression; + + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + return 'ABS(' . $sqlWalker->walkSimpleArithmeticExpression( + $this->simpleArithmeticExpression + ) . ')'; + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AvgFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AvgFunction.php new file mode 100644 index 0000000..6cb8d92 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AvgFunction.php @@ -0,0 +1,54 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\AST\AggregateExpression; + +/** + * "AVG" "(" ["DISTINCT"] StringPrimary ")" + * + * @since 2.6 + * @author Mathew Davies + */ +final class AvgFunction extends FunctionNode +{ + /** + * @var AggregateExpression + */ + private $aggregateExpression; + + /** + * @inheritDoc + */ + public function getSql(SqlWalker $sqlWalker): string + { + return $this->aggregateExpression->dispatch($sqlWalker); + } + + /** + * @inheritDoc + */ + public function parse(Parser $parser): void + { + $this->aggregateExpression = $parser->AggregateExpression(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitAndFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitAndFunction.php new file mode 100644 index 0000000..469a4b0 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitAndFunction.php @@ -0,0 +1,66 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "BIT_AND" "(" ArithmeticPrimary "," ArithmeticPrimary ")" + * + * + * @link www.doctrine-project.org + * @since 2.2 + * @author Fabio B. Silva + */ +class BitAndFunction extends FunctionNode +{ + public $firstArithmetic; + public $secondArithmetic; + + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + $platform = $sqlWalker->getConnection()->getDatabasePlatform(); + + return $platform->getBitAndComparisonExpression( + $this->firstArithmetic->dispatch($sqlWalker), + $this->secondArithmetic->dispatch($sqlWalker) + ); + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->firstArithmetic = $parser->ArithmeticPrimary(); + $parser->match(Lexer::T_COMMA); + $this->secondArithmetic = $parser->ArithmeticPrimary(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitOrFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitOrFunction.php new file mode 100644 index 0000000..d3a3efc --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitOrFunction.php @@ -0,0 +1,66 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "BIT_OR" "(" ArithmeticPrimary "," ArithmeticPrimary ")" + * + * + * @link www.doctrine-project.org + * @since 2.2 + * @author Fabio B. Silva + */ +class BitOrFunction extends FunctionNode +{ + public $firstArithmetic; + public $secondArithmetic; + + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + $platform = $sqlWalker->getConnection()->getDatabasePlatform(); + + return $platform->getBitOrComparisonExpression( + $this->firstArithmetic->dispatch($sqlWalker), + $this->secondArithmetic->dispatch($sqlWalker) + ); + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->firstArithmetic = $parser->ArithmeticPrimary(); + $parser->match(Lexer::T_COMMA); + $this->secondArithmetic = $parser->ArithmeticPrimary(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php new file mode 100644 index 0000000..b7c5ae1 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php @@ -0,0 +1,85 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "CONCAT" "(" StringPrimary "," StringPrimary {"," StringPrimary }* ")" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class ConcatFunction extends FunctionNode +{ + public $firstStringPrimary; + + public $secondStringPrimary; + + public $concatExpressions = []; + + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + $platform = $sqlWalker->getConnection()->getDatabasePlatform(); + + $args = []; + + foreach ($this->concatExpressions as $expression) { + $args[] = $sqlWalker->walkStringPrimary($expression); + } + + return call_user_func_array([$platform,'getConcatExpression'], $args); + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->firstStringPrimary = $parser->StringPrimary(); + $this->concatExpressions[] = $this->firstStringPrimary; + + $parser->match(Lexer::T_COMMA); + + $this->secondStringPrimary = $parser->StringPrimary(); + $this->concatExpressions[] = $this->secondStringPrimary; + + while ($parser->getLexer()->isNextToken(Lexer::T_COMMA)) { + $parser->match(Lexer::T_COMMA); + $this->concatExpressions[] = $parser->StringPrimary(); + } + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} + diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CountFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CountFunction.php new file mode 100644 index 0000000..f232cf4 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CountFunction.php @@ -0,0 +1,54 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\AST\AggregateExpression; + +/** + * "COUNT" "(" ["DISTINCT"] StringPrimary ")" + * + * @since 2.6 + * @author Mathew Davies + */ +final class CountFunction extends FunctionNode +{ + /** + * @var AggregateExpression + */ + private $aggregateExpression; + + /** + * @inheritDoc + */ + public function getSql(SqlWalker $sqlWalker): string + { + return $this->aggregateExpression->dispatch($sqlWalker); + } + + /** + * @inheritDoc + */ + public function parse(Parser $parser): void + { + $this->aggregateExpression = $parser->AggregateExpression(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentDateFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentDateFunction.php new file mode 100644 index 0000000..565b875 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentDateFunction.php @@ -0,0 +1,56 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "CURRENT_DATE" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class CurrentDateFunction extends FunctionNode +{ + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + return $sqlWalker->getConnection()->getDatabasePlatform()->getCurrentDateSQL(); + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimeFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimeFunction.php new file mode 100644 index 0000000..ec9ceb7 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimeFunction.php @@ -0,0 +1,56 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "CURRENT_TIME" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class CurrentTimeFunction extends FunctionNode +{ + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + return $sqlWalker->getConnection()->getDatabasePlatform()->getCurrentTimeSQL(); + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimestampFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimestampFunction.php new file mode 100644 index 0000000..4203072 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimestampFunction.php @@ -0,0 +1,56 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "CURRENT_TIMESTAMP" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class CurrentTimestampFunction extends FunctionNode +{ + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + return $sqlWalker->getConnection()->getDatabasePlatform()->getCurrentTimestampSQL(); + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php new file mode 100644 index 0000000..edec7f9 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php @@ -0,0 +1,109 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; +use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\QueryException; + +/** + * "DATE_ADD" "(" ArithmeticPrimary "," ArithmeticPrimary "," StringPrimary ")" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Benjamin Eberlei + */ +class DateAddFunction extends FunctionNode +{ + public $firstDateExpression = null; + public $intervalExpression = null; + public $unit = null; + + /** + * @override + * @inheritdoc + */ + public function getSql(SqlWalker $sqlWalker) + { + switch (strtolower($this->unit->value)) { + case 'second': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddSecondsExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + case 'minute': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddMinutesExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + case 'hour': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddHourExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + case 'day': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddDaysExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + case 'week': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddWeeksExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + case 'month': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddMonthExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + case 'year': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddYearsExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + + default: + throw QueryException::semanticalError( + 'DATE_ADD() only supports units of type second, minute, hour, day, week, month and year.' + ); + } + } + + /** + * @override + * @inheritdoc + */ + public function parse(Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->firstDateExpression = $parser->ArithmeticPrimary(); + $parser->match(Lexer::T_COMMA); + $this->intervalExpression = $parser->ArithmeticPrimary(); + $parser->match(Lexer::T_COMMA); + $this->unit = $parser->StringPrimary(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateDiffFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateDiffFunction.php new file mode 100644 index 0000000..5372482 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateDiffFunction.php @@ -0,0 +1,66 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; +use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\Parser; + +/** + * "DATE_DIFF" "(" ArithmeticPrimary "," ArithmeticPrimary ")" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + */ +class DateDiffFunction extends FunctionNode +{ + public $date1; + public $date2; + + /** + * @override + * @inheritdoc + */ + public function getSql(SqlWalker $sqlWalker) + { + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateDiffExpression( + $this->date1->dispatch($sqlWalker), + $this->date2->dispatch($sqlWalker) + ); + } + + /** + * @override + * @inheritdoc + */ + public function parse(Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->date1 = $parser->ArithmeticPrimary(); + $parser->match(Lexer::T_COMMA); + $this->date2 = $parser->ArithmeticPrimary(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php new file mode 100644 index 0000000..8dcc135 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php @@ -0,0 +1,85 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\QueryException; + +/** + * "DATE_ADD(date1, interval, unit)" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Benjamin Eberlei + */ +class DateSubFunction extends DateAddFunction +{ + /** + * @override + * @inheritdoc + */ + public function getSql(SqlWalker $sqlWalker) + { + switch (strtolower($this->unit->value)) { + case 'second': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubSecondsExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + case 'minute': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubMinutesExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + case 'hour': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubHourExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + case 'day': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubDaysExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + case 'week': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubWeeksExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + case 'month': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubMonthExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + case 'year': + return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubYearsExpression( + $this->firstDateExpression->dispatch($sqlWalker), + $this->intervalExpression->dispatch($sqlWalker) + ); + + default: + throw QueryException::semanticalError( + 'DATE_SUB() only supports units of type second, minute, hour, day, week, month and year.' + ); + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/FunctionNode.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/FunctionNode.php new file mode 100644 index 0000000..2f33c9d --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/FunctionNode.php @@ -0,0 +1,73 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\AST\Node; + +/** + * Abstract Function Node. + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +abstract class FunctionNode extends Node +{ + /** + * @var string + */ + public $name; + + /** + * @param string $name + */ + public function __construct($name) + { + $this->name = $name; + } + + /** + * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker + * + * @return string + */ + abstract public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker); + + /** + * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker + * + * @return string + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkFunction($this); + } + + /** + * @param \Doctrine\ORM\Query\Parser $parser + * + * @return void + */ + abstract public function parse(\Doctrine\ORM\Query\Parser $parser); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/IdentityFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/IdentityFunction.php new file mode 100644 index 0000000..6f69d53 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/IdentityFunction.php @@ -0,0 +1,113 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; +use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\QueryException; + +/** + * "IDENTITY" "(" SingleValuedAssociationPathExpression {"," string} ")" + * + * + * @link www.doctrine-project.org + * @since 2.2 + * @author Guilherme Blanco + * @author Benjamin Eberlei + */ +class IdentityFunction extends FunctionNode +{ + /** + * @var \Doctrine\ORM\Query\AST\PathExpression + */ + public $pathExpression; + + /** + * @var string + */ + public $fieldMapping; + + /** + * {@inheritdoc} + */ + public function getSql(SqlWalker $sqlWalker) + { + $platform = $sqlWalker->getEntityManager()->getConnection()->getDatabasePlatform(); + $quoteStrategy = $sqlWalker->getEntityManager()->getConfiguration()->getQuoteStrategy(); + $dqlAlias = $this->pathExpression->identificationVariable; + $assocField = $this->pathExpression->field; + $qComp = $sqlWalker->getQueryComponent($dqlAlias); + $class = $qComp['metadata']; + $assoc = $class->associationMappings[$assocField]; + $targetEntity = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']); + $joinColumn = reset($assoc['joinColumns']); + + if ($this->fieldMapping !== null) { + if ( ! isset($targetEntity->fieldMappings[$this->fieldMapping])) { + throw new QueryException(sprintf('Undefined reference field mapping "%s"', $this->fieldMapping)); + } + + $field = $targetEntity->fieldMappings[$this->fieldMapping]; + $joinColumn = null; + + foreach ($assoc['joinColumns'] as $mapping) { + + if ($mapping['referencedColumnName'] === $field['columnName']) { + $joinColumn = $mapping; + + break; + } + } + + if ($joinColumn === null) { + throw new QueryException(sprintf('Unable to resolve the reference field mapping "%s"', $this->fieldMapping)); + } + } + + // The table with the relation may be a subclass, so get the table name from the association definition + $tableName = $sqlWalker->getEntityManager()->getClassMetadata($assoc['sourceEntity'])->getTableName(); + + $tableAlias = $sqlWalker->getSQLTableAlias($tableName, $dqlAlias); + $columnName = $quoteStrategy->getJoinColumnName($joinColumn, $targetEntity, $platform); + + return $tableAlias . '.' . $columnName; + } + + /** + * {@inheritdoc} + */ + public function parse(Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->pathExpression = $parser->SingleValuedAssociationPathExpression(); + + if ($parser->getLexer()->isNextToken(Lexer::T_COMMA)) { + $parser->match(Lexer::T_COMMA); + $parser->match(Lexer::T_STRING); + + $this->fieldMapping = $parser->getLexer()->token['value']; + } + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LengthFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LengthFunction.php new file mode 100644 index 0000000..3d2b1a6 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LengthFunction.php @@ -0,0 +1,63 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "LENGTH" "(" StringPrimary ")" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class LengthFunction extends FunctionNode +{ + public $stringPrimary; + + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + return $sqlWalker->getConnection()->getDatabasePlatform()->getLengthExpression( + $sqlWalker->walkSimpleArithmeticExpression($this->stringPrimary) + ); + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->stringPrimary = $parser->StringPrimary(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LocateFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LocateFunction.php new file mode 100644 index 0000000..473aa34 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LocateFunction.php @@ -0,0 +1,86 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class LocateFunction extends FunctionNode +{ + public $firstStringPrimary; + public $secondStringPrimary; + + /** + * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression|bool + */ + public $simpleArithmeticExpression = false; + + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + + return $sqlWalker->getConnection()->getDatabasePlatform()->getLocateExpression( + $sqlWalker->walkStringPrimary($this->secondStringPrimary), // its the other way around in platform + $sqlWalker->walkStringPrimary($this->firstStringPrimary), + (($this->simpleArithmeticExpression) + ? $sqlWalker->walkSimpleArithmeticExpression($this->simpleArithmeticExpression) + : false + ) + ); + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->firstStringPrimary = $parser->StringPrimary(); + + $parser->match(Lexer::T_COMMA); + + $this->secondStringPrimary = $parser->StringPrimary(); + + $lexer = $parser->getLexer(); + if ($lexer->isNextToken(Lexer::T_COMMA)) { + $parser->match(Lexer::T_COMMA); + + $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression(); + } + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php new file mode 100644 index 0000000..5f0fb95 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php @@ -0,0 +1,63 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "LOWER" "(" StringPrimary ")" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class LowerFunction extends FunctionNode +{ + public $stringPrimary; + + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + return $sqlWalker->getConnection()->getDatabasePlatform()->getLowerExpression( + $sqlWalker->walkSimpleArithmeticExpression($this->stringPrimary) + ); + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->stringPrimary = $parser->StringPrimary(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MaxFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MaxFunction.php new file mode 100644 index 0000000..eba9b86 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MaxFunction.php @@ -0,0 +1,54 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\AST\AggregateExpression; + +/** + * "MAX" "(" ["DISTINCT"] StringPrimary ")" + * + * @since 2.6 + * @author Mathew Davies + */ +final class MaxFunction extends FunctionNode +{ + /** + * @var AggregateExpression + */ + private $aggregateExpression; + + /** + * @inheritDoc + */ + public function getSql(SqlWalker $sqlWalker): string + { + return $this->aggregateExpression->dispatch($sqlWalker); + } + + /** + * @inheritDoc + */ + public function parse(Parser $parser): void + { + $this->aggregateExpression = $parser->AggregateExpression(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MinFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MinFunction.php new file mode 100644 index 0000000..e1c0869 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MinFunction.php @@ -0,0 +1,54 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\AST\AggregateExpression; + +/** + * "MIN" "(" ["DISTINCT"] StringPrimary ")" + * + * @since 2.6 + * @author Mathew Davies + */ +final class MinFunction extends FunctionNode +{ + /** + * @var AggregateExpression + */ + private $aggregateExpression; + + /** + * @inheritDoc + */ + public function getSql(SqlWalker $sqlWalker): string + { + return $this->aggregateExpression->dispatch($sqlWalker); + } + + /** + * @inheritDoc + */ + public function parse(Parser $parser): void + { + $this->aggregateExpression = $parser->AggregateExpression(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ModFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ModFunction.php new file mode 100644 index 0000000..61bc9a7 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ModFunction.php @@ -0,0 +1,76 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class ModFunction extends FunctionNode +{ + /** + * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression + */ + public $firstSimpleArithmeticExpression; + + /** + * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression + */ + public $secondSimpleArithmeticExpression; + + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + return $sqlWalker->getConnection()->getDatabasePlatform()->getModExpression( + $sqlWalker->walkSimpleArithmeticExpression($this->firstSimpleArithmeticExpression), + $sqlWalker->walkSimpleArithmeticExpression($this->secondSimpleArithmeticExpression) + ); + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->firstSimpleArithmeticExpression = $parser->SimpleArithmeticExpression(); + + $parser->match(Lexer::T_COMMA); + + $this->secondSimpleArithmeticExpression = $parser->SimpleArithmeticExpression(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php new file mode 100644 index 0000000..bf0f7a4 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php @@ -0,0 +1,125 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "SIZE" "(" CollectionValuedPathExpression ")" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class SizeFunction extends FunctionNode +{ + /** + * @var \Doctrine\ORM\Query\AST\PathExpression + */ + public $collectionPathExpression; + + /** + * @override + * @inheritdoc + * @todo If the collection being counted is already joined, the SQL can be simpler (more efficient). + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + $platform = $sqlWalker->getEntityManager()->getConnection()->getDatabasePlatform(); + $quoteStrategy = $sqlWalker->getEntityManager()->getConfiguration()->getQuoteStrategy(); + $dqlAlias = $this->collectionPathExpression->identificationVariable; + $assocField = $this->collectionPathExpression->field; + + $qComp = $sqlWalker->getQueryComponent($dqlAlias); + $class = $qComp['metadata']; + $assoc = $class->associationMappings[$assocField]; + $sql = 'SELECT COUNT(*) FROM '; + + if ($assoc['type'] == \Doctrine\ORM\Mapping\ClassMetadata::ONE_TO_MANY) { + $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']); + $targetTableAlias = $sqlWalker->getSQLTableAlias($targetClass->getTableName()); + $sourceTableAlias = $sqlWalker->getSQLTableAlias($class->getTableName(), $dqlAlias); + + $sql .= $quoteStrategy->getTableName($targetClass, $platform) . ' ' . $targetTableAlias . ' WHERE '; + + $owningAssoc = $targetClass->associationMappings[$assoc['mappedBy']]; + + $first = true; + + foreach ($owningAssoc['targetToSourceKeyColumns'] as $targetColumn => $sourceColumn) { + if ($first) $first = false; else $sql .= ' AND '; + + $sql .= $targetTableAlias . '.' . $sourceColumn + . ' = ' + . $sourceTableAlias . '.' . $quoteStrategy->getColumnName($class->fieldNames[$targetColumn], $class, $platform); + } + } else { // many-to-many + $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']); + + $owningAssoc = $assoc['isOwningSide'] ? $assoc : $targetClass->associationMappings[$assoc['mappedBy']]; + $joinTable = $owningAssoc['joinTable']; + + // SQL table aliases + $joinTableAlias = $sqlWalker->getSQLTableAlias($joinTable['name']); + $sourceTableAlias = $sqlWalker->getSQLTableAlias($class->getTableName(), $dqlAlias); + + // join to target table + $sql .= $quoteStrategy->getJoinTableName($owningAssoc, $targetClass, $platform) . ' ' . $joinTableAlias . ' WHERE '; + + $joinColumns = $assoc['isOwningSide'] + ? $joinTable['joinColumns'] + : $joinTable['inverseJoinColumns']; + + $first = true; + + foreach ($joinColumns as $joinColumn) { + if ($first) $first = false; else $sql .= ' AND '; + + $sourceColumnName = $quoteStrategy->getColumnName( + $class->fieldNames[$joinColumn['referencedColumnName']], $class, $platform + ); + + $sql .= $joinTableAlias . '.' . $joinColumn['name'] + . ' = ' + . $sourceTableAlias . '.' . $sourceColumnName; + } + } + + return '(' . $sql . ')'; + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->collectionPathExpression = $parser->CollectionValuedPathExpression(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SqrtFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SqrtFunction.php new file mode 100644 index 0000000..08155d2 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SqrtFunction.php @@ -0,0 +1,66 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "SQRT" "(" SimpleArithmeticExpression ")" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class SqrtFunction extends FunctionNode +{ + /** + * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression + */ + public $simpleArithmeticExpression; + + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + return $sqlWalker->getConnection()->getDatabasePlatform()->getSqrtExpression( + $sqlWalker->walkSimpleArithmeticExpression($this->simpleArithmeticExpression) + ); + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php new file mode 100644 index 0000000..a6a80f8 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php @@ -0,0 +1,91 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class SubstringFunction extends FunctionNode +{ + public $stringPrimary; + + /** + * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression + */ + public $firstSimpleArithmeticExpression; + + /** + * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression|null + */ + public $secondSimpleArithmeticExpression = null; + + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + $optionalSecondSimpleArithmeticExpression = null; + if ($this->secondSimpleArithmeticExpression !== null) { + $optionalSecondSimpleArithmeticExpression = $sqlWalker->walkSimpleArithmeticExpression($this->secondSimpleArithmeticExpression); + } + + return $sqlWalker->getConnection()->getDatabasePlatform()->getSubstringExpression( + $sqlWalker->walkStringPrimary($this->stringPrimary), + $sqlWalker->walkSimpleArithmeticExpression($this->firstSimpleArithmeticExpression), + $optionalSecondSimpleArithmeticExpression + ); + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->stringPrimary = $parser->StringPrimary(); + + $parser->match(Lexer::T_COMMA); + + $this->firstSimpleArithmeticExpression = $parser->SimpleArithmeticExpression(); + + $lexer = $parser->getLexer(); + if ($lexer->isNextToken(Lexer::T_COMMA)) { + $parser->match(Lexer::T_COMMA); + + $this->secondSimpleArithmeticExpression = $parser->SimpleArithmeticExpression(); + } + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SumFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SumFunction.php new file mode 100644 index 0000000..c9fcf7b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SumFunction.php @@ -0,0 +1,54 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\AST\AggregateExpression; + +/** + * "SUM" "(" ["DISTINCT"] StringPrimary ")" + * + * @since 2.6 + * @author Mathew Davies + */ +final class SumFunction extends FunctionNode +{ + /** + * @var AggregateExpression + */ + private $aggregateExpression; + + /** + * @inheritDoc + */ + public function getSql(SqlWalker $sqlWalker): string + { + return $this->aggregateExpression->dispatch($sqlWalker); + } + + /** + * @inheritDoc + */ + public function parse(Parser $parser): void + { + $this->aggregateExpression = $parser->AggregateExpression(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php new file mode 100644 index 0000000..9e748c3 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php @@ -0,0 +1,161 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; +use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\SqlWalker; +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * "TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class TrimFunction extends FunctionNode +{ + /** + * @var boolean + */ + public $leading; + + /** + * @var boolean + */ + public $trailing; + + /** + * @var boolean + */ + public $both; + + /** + * @var boolean + */ + public $trimChar = false; + + /** + * @var \Doctrine\ORM\Query\AST\Node + */ + public $stringPrimary; + + /** + * {@inheritdoc} + */ + public function getSql(SqlWalker $sqlWalker) + { + $stringPrimary = $sqlWalker->walkStringPrimary($this->stringPrimary); + $platform = $sqlWalker->getConnection()->getDatabasePlatform(); + $trimMode = $this->getTrimMode(); + $trimChar = ($this->trimChar !== false) + ? $sqlWalker->getConnection()->quote($this->trimChar) + : false; + + return $platform->getTrimExpression($stringPrimary, $trimMode, $trimChar); + } + + /** + * {@inheritdoc} + */ + public function parse(Parser $parser) + { + $lexer = $parser->getLexer(); + + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->parseTrimMode($parser); + + if ($lexer->isNextToken(Lexer::T_STRING)) { + $parser->match(Lexer::T_STRING); + + $this->trimChar = $lexer->token['value']; + } + + if ($this->leading || $this->trailing || $this->both || $this->trimChar) { + $parser->match(Lexer::T_FROM); + } + + $this->stringPrimary = $parser->StringPrimary(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } + + /** + * @return integer + */ + private function getTrimMode() + { + if ($this->leading) { + return AbstractPlatform::TRIM_LEADING; + } + + if ($this->trailing) { + return AbstractPlatform::TRIM_TRAILING; + } + + if ($this->both) { + return AbstractPlatform::TRIM_BOTH; + } + + return AbstractPlatform::TRIM_UNSPECIFIED; + } + + /** + * @param \Doctrine\ORM\Query\Parser $parser + * + * @return void + */ + private function parseTrimMode(Parser $parser) + { + $lexer = $parser->getLexer(); + $value = $lexer->lookahead['value']; + + if (strcasecmp('leading', $value) === 0) { + $parser->match(Lexer::T_LEADING); + + $this->leading = true; + + return; + } + + if (strcasecmp('trailing', $value) === 0) { + $parser->match(Lexer::T_TRAILING); + + $this->trailing = true; + + return; + } + + if (strcasecmp('both', $value) === 0) { + $parser->match(Lexer::T_BOTH); + + $this->both = true; + + return; + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php new file mode 100644 index 0000000..28e0f16 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php @@ -0,0 +1,63 @@ +. + */ + +namespace Doctrine\ORM\Query\AST\Functions; + +use Doctrine\ORM\Query\Lexer; + +/** + * "UPPER" "(" StringPrimary ")" + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class UpperFunction extends FunctionNode +{ + public $stringPrimary; + + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + return $sqlWalker->getConnection()->getDatabasePlatform()->getUpperExpression( + $sqlWalker->walkSimpleArithmeticExpression($this->stringPrimary) + ); + } + + /** + * @override + * @inheritdoc + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + $parser->match(Lexer::T_IDENTIFIER); + $parser->match(Lexer::T_OPEN_PARENTHESIS); + + $this->stringPrimary = $parser->StringPrimary(); + + $parser->match(Lexer::T_CLOSE_PARENTHESIS); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GeneralCaseExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GeneralCaseExpression.php new file mode 100644 index 0000000..e7937d6 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GeneralCaseExpression.php @@ -0,0 +1,62 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * GeneralCaseExpression ::= "CASE" WhenClause {WhenClause}* "ELSE" ScalarExpression "END" + * + * @since 2.2 + * + * @link www.doctrine-project.org + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class GeneralCaseExpression extends Node +{ + /** + * @var array + */ + public $whenClauses = []; + + /** + * @var mixed + */ + public $elseScalarExpression = null; + + /** + * @param array $whenClauses + * @param mixed $elseScalarExpression + */ + public function __construct(array $whenClauses, $elseScalarExpression) + { + $this->whenClauses = $whenClauses; + $this->elseScalarExpression = $elseScalarExpression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkGeneralCaseExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GroupByClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GroupByClause.php new file mode 100644 index 0000000..687512a --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GroupByClause.php @@ -0,0 +1,53 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * Description of GroupByClause. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class GroupByClause extends Node +{ + /** + * @var array + */ + public $groupByItems = []; + + /** + * @param array $groupByItems + */ + public function __construct(array $groupByItems) + { + $this->groupByItems = $groupByItems; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkGroupByClause($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/HavingClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/HavingClause.php new file mode 100644 index 0000000..1d369ff --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/HavingClause.php @@ -0,0 +1,53 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * Description of HavingClause. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class HavingClause extends Node +{ + /** + * @var ConditionalExpression + */ + public $conditionalExpression; + + /** + * @param ConditionalExpression $conditionalExpression + */ + public function __construct($conditionalExpression) + { + $this->conditionalExpression = $conditionalExpression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkHavingClause($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IdentificationVariableDeclaration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IdentificationVariableDeclaration.php new file mode 100644 index 0000000..2e2032c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IdentificationVariableDeclaration.php @@ -0,0 +1,67 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {JoinVariableDeclaration}* + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class IdentificationVariableDeclaration extends Node +{ + /** + * @var RangeVariableDeclaration|null + */ + public $rangeVariableDeclaration = null; + + /** + * @var IndexBy|null + */ + public $indexBy = null; + + /** + * @var array + */ + public $joins = []; + + /** + * @param RangeVariableDeclaration|null $rangeVariableDecl + * @param IndexBy|null $indexBy + * @param array $joins + */ + public function __construct($rangeVariableDecl, $indexBy, array $joins) + { + $this->rangeVariableDeclaration = $rangeVariableDecl; + $this->indexBy = $indexBy; + $this->joins = $joins; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkIdentificationVariableDeclaration($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InExpression.php new file mode 100644 index 0000000..64ef134 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InExpression.php @@ -0,0 +1,67 @@ +. + */ +namespace Doctrine\ORM\Query\AST; + +/** + * InExpression ::= StateFieldPathExpression ["NOT"] "IN" "(" (Literal {"," Literal}* | Subselect) ")" + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class InExpression extends Node +{ + /** + * @var bool + */ + public $not; + + /** + * @var ArithmeticExpression + */ + public $expression; + + /** + * @var array + */ + public $literals = []; + + /** + * @var Subselect|null + */ + public $subselect; + + /** + * @param ArithmeticExpression $expression + */ + public function __construct($expression) + { + $this->expression = $expression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkInExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IndexBy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IndexBy.php new file mode 100644 index 0000000..c7874b7 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IndexBy.php @@ -0,0 +1,53 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * IndexBy ::= "INDEX" "BY" SimpleStateFieldPathExpression + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class IndexBy extends Node +{ + /** + * @var PathExpression + */ + public $simpleStateFieldPathExpression = null; + + /** + * @param PathExpression $simpleStateFieldPathExpression + */ + public function __construct($simpleStateFieldPathExpression) + { + $this->simpleStateFieldPathExpression = $simpleStateFieldPathExpression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkIndexBy($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InputParameter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InputParameter.php new file mode 100644 index 0000000..4da550f --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InputParameter.php @@ -0,0 +1,66 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * Description of InputParameter. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class InputParameter extends Node +{ + /** + * @var bool + */ + public $isNamed; + + /** + * @var string + */ + public $name; + + /** + * @param string $value + * + * @throws \Doctrine\ORM\Query\QueryException + */ + public function __construct($value) + { + if (strlen($value) === 1) { + throw \Doctrine\ORM\Query\QueryException::invalidParameterFormat($value); + } + + $param = substr($value, 1); + $this->isNamed = ! is_numeric($param); + $this->name = $param; + } + + /** + * {@inheritdoc} + */ + public function dispatch($walker) + { + return $walker->walkInputParameter($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InstanceOfExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InstanceOfExpression.php new file mode 100644 index 0000000..c1fd65b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InstanceOfExpression.php @@ -0,0 +1,64 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (InstanceOfParameter | "(" InstanceOfParameter {"," InstanceOfParameter}* ")") + * InstanceOfParameter ::= AbstractSchemaName | InputParameter + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class InstanceOfExpression extends Node +{ + /** + * @var bool + */ + public $not; + + /** + * @var string + */ + public $identificationVariable; + + /** + * @var array + */ + public $value; + + /** + * @param string $identVariable + */ + public function __construct($identVariable) + { + $this->identificationVariable = $identVariable; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkInstanceOfExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Join.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Join.php new file mode 100644 index 0000000..5c203aa --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Join.php @@ -0,0 +1,70 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" JoinAssociationPathExpression + * ["AS"] AliasIdentificationVariable [("ON" | "WITH") ConditionalExpression] + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class Join extends Node +{ + const JOIN_TYPE_LEFT = 1; + const JOIN_TYPE_LEFTOUTER = 2; + const JOIN_TYPE_INNER = 3; + + /** + * @var int + */ + public $joinType = self::JOIN_TYPE_INNER; + + /** + * @var Node|null + */ + public $joinAssociationDeclaration = null; + + /** + * @var ConditionalExpression|null + */ + public $conditionalExpression = null; + + /** + * @param int $joinType + * @param Node $joinAssociationDeclaration + */ + public function __construct($joinType, $joinAssociationDeclaration) + { + $this->joinType = $joinType; + $this->joinAssociationDeclaration = $joinAssociationDeclaration; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkJoin($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationDeclaration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationDeclaration.php new file mode 100644 index 0000000..a33900a --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationDeclaration.php @@ -0,0 +1,65 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * JoinAssociationDeclaration ::= JoinAssociationPathExpression ["AS"] AliasIdentificationVariable + * + * @link www.doctrine-project.org + * @since 2.3 + * @author Guilherme Blanco + */ +class JoinAssociationDeclaration extends Node +{ + /** + * @var JoinAssociationPathExpression + */ + public $joinAssociationPathExpression; + + /** + * @var string + */ + public $aliasIdentificationVariable; + + /** + * @var IndexBy|null + */ + public $indexBy; + + /** + * @param JoinAssociationPathExpression $joinAssociationPathExpression + * @param string $aliasIdentificationVariable + * @param IndexBy|null $indexBy + */ + public function __construct($joinAssociationPathExpression, $aliasIdentificationVariable, $indexBy) + { + $this->joinAssociationPathExpression = $joinAssociationPathExpression; + $this->aliasIdentificationVariable = $aliasIdentificationVariable; + $this->indexBy = $indexBy; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkJoinAssociationDeclaration($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationPathExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationPathExpression.php new file mode 100644 index 0000000..946bbb1 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationPathExpression.php @@ -0,0 +1,60 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * JoinAssociationPathExpression ::= IdentificationVariable "." (SingleValuedAssociationField | CollectionValuedAssociationField) + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class JoinAssociationPathExpression extends Node +{ + /** + * @var string + */ + public $identificationVariable; + + /** + * @var string + */ + public $associationField; + + /** + * @param string $identificationVariable + * @param string $associationField + */ + public function __construct($identificationVariable, $associationField) + { + $this->identificationVariable = $identificationVariable; + $this->associationField = $associationField; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkPathExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinClassPathExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinClassPathExpression.php new file mode 100644 index 0000000..7e37414 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinClassPathExpression.php @@ -0,0 +1,59 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * JoinClassPathExpression ::= AbstractSchemaName ["AS"] AliasIdentificationVariable + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.org + * @since 2.3 + * @author Alexander + */ +class JoinClassPathExpression extends Node +{ + /** + * @var mixed + */ + public $abstractSchemaName; + + /** + * @var mixed + */ + public $aliasIdentificationVariable; + + /** + * @param mixed $abstractSchemaName + * @param mixed $aliasIdentificationVar + */ + public function __construct($abstractSchemaName, $aliasIdentificationVar) + { + $this->abstractSchemaName = $abstractSchemaName; + $this->aliasIdentificationVariable = $aliasIdentificationVar; + } + + /** + * {@inheritdoc} + */ + public function dispatch($walker) + { + return $walker->walkJoinPathExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinVariableDeclaration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinVariableDeclaration.php new file mode 100644 index 0000000..89aa83a --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinVariableDeclaration.php @@ -0,0 +1,61 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * JoinVariableDeclaration ::= Join [IndexBy] + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.org + * @since 2.5 + * @author Guilherme Blanco + */ +class JoinVariableDeclaration extends Node +{ + /** + * @var Join + */ + public $join; + + /** + * @var IndexBy|null + */ + public $indexBy; + + /** + * Constructor. + * + * @param Join $join + * @param IndexBy|null $indexBy + */ + public function __construct($join, $indexBy) + { + $this->join = $join; + $this->indexBy = $indexBy; + } + + /** + * {@inheritdoc} + */ + public function dispatch($walker) + { + return $walker->walkJoinVariableDeclaration($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/LikeExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/LikeExpression.php new file mode 100644 index 0000000..e320c51 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/LikeExpression.php @@ -0,0 +1,71 @@ +. + */ +namespace Doctrine\ORM\Query\AST; + +/** + * LikeExpression ::= StringExpression ["NOT"] "LIKE" string ["ESCAPE" char] + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class LikeExpression extends Node +{ + /** + * @var bool + */ + public $not; + + /** + * @var Node + */ + public $stringExpression; + + /** + * @var InputParameter + */ + public $stringPattern; + + /** + * @var Literal|null + */ + public $escapeChar; + + /** + * @param Node $stringExpression + * @param InputParameter $stringPattern + * @param Literal|null $escapeChar + */ + public function __construct($stringExpression, $stringPattern, $escapeChar = null) + { + $this->stringExpression = $stringExpression; + $this->stringPattern = $stringPattern; + $this->escapeChar = $escapeChar; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkLikeExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Literal.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Literal.php new file mode 100644 index 0000000..43d71ad --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Literal.php @@ -0,0 +1,55 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +class Literal extends Node +{ + const STRING = 1; + const BOOLEAN = 2; + const NUMERIC = 3; + + /** + * @var int + */ + public $type; + + /** + * @var mixed + */ + public $value; + + /** + * @param int $type + * @param mixed $value + */ + public function __construct($type, $value) + { + $this->type = $type; + $this->value = $value; + } + + /** + * {@inheritdoc} + */ + public function dispatch($walker) + { + return $walker->walkLiteral($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NewObjectExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NewObjectExpression.php new file mode 100644 index 0000000..ec011ce --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NewObjectExpression.php @@ -0,0 +1,58 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * NewObjectExpression ::= "NEW" IdentificationVariable "(" NewObjectArg {"," NewObjectArg}* ")" + * + * @link www.doctrine-project.org + * @since 2.4 + * @author Fabio B. Silva + */ +class NewObjectExpression extends Node +{ + /** + * @var string + */ + public $className; + + /** + * @var array + */ + public $args; + + /** + * @param string $className + * @param array $args + */ + public function __construct($className, array $args) + { + $this->className = $className; + $this->args = $args; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkNewObject($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Node.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Node.php new file mode 100644 index 0000000..a257dc2 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Node.php @@ -0,0 +1,103 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * Abstract class of an AST node. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +abstract class Node +{ + /** + * Double-dispatch method, supposed to dispatch back to the walker. + * + * Implementation is not mandatory for all nodes. + * + * @param \Doctrine\ORM\Query\SqlWalker $walker + * + * @return string + * + * @throws ASTException + */ + public function dispatch($walker) + { + throw ASTException::noDispatchForNode($this); + } + + /** + * Dumps the AST Node into a string representation for information purpose only. + * + * @return string + */ + public function __toString() + { + return $this->dump($this); + } + + /** + * @param object $obj + * + * @return string + */ + public function dump($obj) + { + static $ident = 0; + + $str = ''; + + if ($obj instanceof Node) { + $str .= get_class($obj) . '(' . PHP_EOL; + $props = get_object_vars($obj); + + foreach ($props as $name => $prop) { + $ident += 4; + $str .= str_repeat(' ', $ident) . '"' . $name . '": ' + . $this->dump($prop) . ',' . PHP_EOL; + $ident -= 4; + } + + $str .= str_repeat(' ', $ident) . ')'; + } else if (is_array($obj)) { + $ident += 4; + $str .= 'array('; + $some = false; + + foreach ($obj as $k => $v) { + $str .= PHP_EOL . str_repeat(' ', $ident) . '"' + . $k . '" => ' . $this->dump($v) . ','; + $some = true; + } + + $ident -= 4; + $str .= ($some ? PHP_EOL . str_repeat(' ', $ident) : '') . ')'; + } else if (is_object($obj)) { + $str .= 'instanceof(' . get_class($obj) . ')'; + } else { + $str .= var_export($obj, true); + } + + return $str; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullComparisonExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullComparisonExpression.php new file mode 100644 index 0000000..84a1997 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullComparisonExpression.php @@ -0,0 +1,58 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * NullComparisonExpression ::= (SingleValuedPathExpression | InputParameter) "IS" ["NOT"] "NULL" + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class NullComparisonExpression extends Node +{ + /** + * @var bool + */ + public $not; + + /** + * @var Node + */ + public $expression; + + /** + * @param Node $expression + */ + public function __construct($expression) + { + $this->expression = $expression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkNullComparisonExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullIfExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullIfExpression.php new file mode 100644 index 0000000..e33bc72 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullIfExpression.php @@ -0,0 +1,62 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * NullIfExpression ::= "NULLIF" "(" ScalarExpression "," ScalarExpression ")" + * + * @since 2.1 + * + * @link www.doctrine-project.org + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class NullIfExpression extends Node +{ + /** + * @var mixed + */ + public $firstExpression; + + /** + * @var mixed + */ + public $secondExpression; + + /** + * @param mixed $firstExpression + * @param mixed $secondExpression + */ + public function __construct($firstExpression, $secondExpression) + { + $this->firstExpression = $firstExpression; + $this->secondExpression = $secondExpression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkNullIfExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByClause.php new file mode 100644 index 0000000..e0e30e9 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByClause.php @@ -0,0 +1,53 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}* + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class OrderByClause extends Node +{ + /** + * @var array + */ + public $orderByItems = []; + + /** + * @param array $orderByItems + */ + public function __construct(array $orderByItems) + { + $this->orderByItems = $orderByItems; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkOrderByClause($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByItem.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByItem.php new file mode 100644 index 0000000..bf3288a --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByItem.php @@ -0,0 +1,75 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * OrderByItem ::= (ResultVariable | StateFieldPathExpression) ["ASC" | "DESC"] + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class OrderByItem extends Node +{ + /** + * @var mixed + */ + public $expression; + + /** + * @var string + */ + public $type; + + /** + * @param mixed $expression + */ + public function __construct($expression) + { + $this->expression = $expression; + } + + /** + * @return bool + */ + public function isAsc() + { + return strtoupper($this->type) == 'ASC'; + } + + /** + * @return bool + */ + public function isDesc() + { + return strtoupper($this->type) == 'DESC'; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkOrderByItem($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ParenthesisExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ParenthesisExpression.php new file mode 100644 index 0000000..f16db0e --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ParenthesisExpression.php @@ -0,0 +1,51 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * ParenthesisExpression ::= "(" ArithmeticPrimary ")" + * + * @author Fabio B. Silva + * @since 2.4 + */ +class ParenthesisExpression extends Node +{ + /** + * @var \Doctrine\ORM\Query\AST\Node + */ + public $expression; + + /** + * @param \Doctrine\ORM\Query\AST\Node $expression + */ + public function __construct(Node $expression) + { + $this->expression = $expression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($walker) + { + return $walker->walkParenthesisExpression($this); + } +} \ No newline at end of file diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PartialObjectExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PartialObjectExpression.php new file mode 100644 index 0000000..e4ffe79 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PartialObjectExpression.php @@ -0,0 +1,43 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +class PartialObjectExpression extends Node +{ + /** + * @var string + */ + public $identificationVariable; + + /** + * @var array + */ + public $partialFieldSet; + + /** + * @param string $identificationVariable + * @param array $partialFieldSet + */ + public function __construct($identificationVariable, array $partialFieldSet) + { + $this->identificationVariable = $identificationVariable; + $this->partialFieldSet = $partialFieldSet; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PathExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PathExpression.php new file mode 100644 index 0000000..37674b6 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PathExpression.php @@ -0,0 +1,81 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression + * SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression + * StateFieldPathExpression ::= SimpleStateFieldPathExpression | SimpleStateFieldAssociationPathExpression + * SingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField + * CollectionValuedPathExpression ::= IdentificationVariable "." CollectionValuedAssociationField + * StateField ::= {EmbeddedClassStateField "."}* SimpleStateField + * SimpleStateFieldPathExpression ::= IdentificationVariable "." StateField + * + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class PathExpression extends Node +{ + const TYPE_COLLECTION_VALUED_ASSOCIATION = 2; + const TYPE_SINGLE_VALUED_ASSOCIATION = 4; + const TYPE_STATE_FIELD = 8; + + /** + * @var int + */ + public $type; + + /** + * @var int + */ + public $expectedType; + + /** + * @var string + */ + public $identificationVariable; + + /** + * @var string|null + */ + public $field; + + /** + * @param int $expectedType + * @param string $identificationVariable + * @param string|null $field + */ + public function __construct($expectedType, $identificationVariable, $field = null) + { + $this->expectedType = $expectedType; + $this->identificationVariable = $identificationVariable; + $this->field = $field; + } + + /** + * {@inheritdoc} + */ + public function dispatch($walker) + { + return $walker->walkPathExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/QuantifiedExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/QuantifiedExpression.php new file mode 100644 index 0000000..15be952 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/QuantifiedExpression.php @@ -0,0 +1,81 @@ +. + */ +namespace Doctrine\ORM\Query\AST; + +/** + * QuantifiedExpression ::= ("ALL" | "ANY" | "SOME") "(" Subselect ")" + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class QuantifiedExpression extends Node +{ + /** + * @var string + */ + public $type; + + /** + * @var Subselect + */ + public $subselect; + + /** + * @param Subselect $subselect + */ + public function __construct($subselect) + { + $this->subselect = $subselect; + } + + /** + * @return bool + */ + public function isAll() + { + return strtoupper($this->type) == 'ALL'; + } + + /** + * @return bool + */ + public function isAny() + { + return strtoupper($this->type) == 'ANY'; + } + + /** + * @return bool + */ + public function isSome() + { + return strtoupper($this->type) == 'SOME'; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkQuantifiedExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/RangeVariableDeclaration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/RangeVariableDeclaration.php new file mode 100644 index 0000000..0ca5274 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/RangeVariableDeclaration.php @@ -0,0 +1,67 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class RangeVariableDeclaration extends Node +{ + /** + * @var string + */ + public $abstractSchemaName; + + /** + * @var string + */ + public $aliasIdentificationVariable; + + /** + * @var boolean + */ + public $isRoot; + + /** + * @param string $abstractSchemaName + * @param string $aliasIdentificationVar + * @param boolean $isRoot + */ + public function __construct($abstractSchemaName, $aliasIdentificationVar, $isRoot = true) + { + $this->abstractSchemaName = $abstractSchemaName; + $this->aliasIdentificationVariable = $aliasIdentificationVar; + $this->isRoot = $isRoot; + } + + /** + * {@inheritdoc} + */ + public function dispatch($walker) + { + return $walker->walkRangeVariableDeclaration($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectClause.php new file mode 100644 index 0000000..f8e6f47 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectClause.php @@ -0,0 +1,60 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * SelectClause = "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression} + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class SelectClause extends Node +{ + /** + * @var bool + */ + public $isDistinct; + + /** + * @var array + */ + public $selectExpressions = []; + + /** + * @param array $selectExpressions + * @param bool $isDistinct + */ + public function __construct(array $selectExpressions, $isDistinct) + { + $this->isDistinct = $isDistinct; + $this->selectExpressions = $selectExpressions; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkSelectClause($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectExpression.php new file mode 100644 index 0000000..4187013 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectExpression.php @@ -0,0 +1,68 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * SelectExpression ::= IdentificationVariable ["." "*"] | StateFieldPathExpression | + * (AggregateExpression | "(" Subselect ")") [["AS"] ["HIDDEN"] FieldAliasIdentificationVariable] + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class SelectExpression extends Node +{ + /** + * @var mixed + */ + public $expression; + + /** + * @var string|null + */ + public $fieldIdentificationVariable; + + /** + * @var bool + */ + public $hiddenAliasResultVariable; + + /** + * @param mixed $expression + * @param string|null $fieldIdentificationVariable + * @param bool $hiddenAliasResultVariable + */ + public function __construct($expression, $fieldIdentificationVariable, $hiddenAliasResultVariable = false) + { + $this->expression = $expression; + $this->fieldIdentificationVariable = $fieldIdentificationVariable; + $this->hiddenAliasResultVariable = $hiddenAliasResultVariable; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkSelectExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectStatement.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectStatement.php new file mode 100644 index 0000000..d84f725 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectStatement.php @@ -0,0 +1,80 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * SelectStatement = SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class SelectStatement extends Node +{ + /** + * @var SelectClause + */ + public $selectClause; + + /** + * @var FromClause + */ + public $fromClause; + + /** + * @var WhereClause|null + */ + public $whereClause; + + /** + * @var GroupByClause|null + */ + public $groupByClause; + + /** + * @var HavingClause|null + */ + public $havingClause; + + /** + * @var OrderByClause|null + */ + public $orderByClause; + + /** + * @param SelectClause $selectClause + * @param FromClause $fromClause + */ + public function __construct($selectClause, $fromClause) + { + $this->selectClause = $selectClause; + $this->fromClause = $fromClause; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkSelectStatement($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleArithmeticExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleArithmeticExpression.php new file mode 100644 index 0000000..80ecd15 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleArithmeticExpression.php @@ -0,0 +1,53 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * SimpleArithmeticExpression ::= ArithmeticTerm {("+" | "-") ArithmeticTerm}* + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class SimpleArithmeticExpression extends Node +{ + /** + * @var array + */ + public $arithmeticTerms = []; + + /** + * @param array $arithmeticTerms + */ + public function __construct(array $arithmeticTerms) + { + $this->arithmeticTerms = $arithmeticTerms; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkSimpleArithmeticExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleCaseExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleCaseExpression.php new file mode 100644 index 0000000..67e354e --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleCaseExpression.php @@ -0,0 +1,69 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * SimpleCaseExpression ::= "CASE" CaseOperand SimpleWhenClause {SimpleWhenClause}* "ELSE" ScalarExpression "END" + * + * @since 2.2 + * + * @link www.doctrine-project.org + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class SimpleCaseExpression extends Node +{ + /** + * @var PathExpression + */ + public $caseOperand = null; + + /** + * @var array + */ + public $simpleWhenClauses = []; + + /** + * @var mixed + */ + public $elseScalarExpression = null; + + /** + * @param PathExpression $caseOperand + * @param array $simpleWhenClauses + * @param mixed $elseScalarExpression + */ + public function __construct($caseOperand, array $simpleWhenClauses, $elseScalarExpression) + { + $this->caseOperand = $caseOperand; + $this->simpleWhenClauses = $simpleWhenClauses; + $this->elseScalarExpression = $elseScalarExpression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkSimpleCaseExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectClause.php new file mode 100644 index 0000000..92361da --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectClause.php @@ -0,0 +1,60 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * SimpleSelectClause ::= "SELECT" ["DISTINCT"] SimpleSelectExpression + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class SimpleSelectClause extends Node +{ + /** + * @var bool + */ + public $isDistinct = false; + + /** + * @var SimpleSelectExpression + */ + public $simpleSelectExpression; + + /** + * @param SimpleSelectExpression $simpleSelectExpression + * @param bool $isDistinct + */ + public function __construct($simpleSelectExpression, $isDistinct) + { + $this->simpleSelectExpression = $simpleSelectExpression; + $this->isDistinct = $isDistinct; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkSimpleSelectClause($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectExpression.php new file mode 100644 index 0000000..e556835 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectExpression.php @@ -0,0 +1,59 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * SimpleSelectExpression ::= StateFieldPathExpression | IdentificationVariable + * | (AggregateExpression [["AS"] FieldAliasIdentificationVariable]) + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class SimpleSelectExpression extends Node +{ + /** + * @var Node + */ + public $expression; + + /** + * @var string + */ + public $fieldIdentificationVariable; + + /** + * @param Node $expression + */ + public function __construct($expression) + { + $this->expression = $expression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkSimpleSelectExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleWhenClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleWhenClause.php new file mode 100644 index 0000000..4f60881 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleWhenClause.php @@ -0,0 +1,62 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * SimpleWhenClause ::= "WHEN" ScalarExpression "THEN" ScalarExpression + * + * @since 2.2 + * + * @link www.doctrine-project.org + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class SimpleWhenClause extends Node +{ + /** + * @var mixed + */ + public $caseScalarExpression = null; + + /** + * @var mixed + */ + public $thenScalarExpression = null; + + /** + * @param mixed $caseScalarExpression + * @param mixed $thenScalarExpression + */ + public function __construct($caseScalarExpression, $thenScalarExpression) + { + $this->caseScalarExpression = $caseScalarExpression; + $this->thenScalarExpression = $thenScalarExpression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkWhenClauseExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Subselect.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Subselect.php new file mode 100644 index 0000000..ce08266 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Subselect.php @@ -0,0 +1,80 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * Subselect ::= SimpleSelectClause SubselectFromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class Subselect extends Node +{ + /** + * @var SimpleSelectClause + */ + public $simpleSelectClause; + + /** + * @var SubselectFromClause + */ + public $subselectFromClause; + + /** + * @var WhereClause|null + */ + public $whereClause; + + /** + * @var GroupByClause|null + */ + public $groupByClause; + + /** + * @var HavingClause|null + */ + public $havingClause; + + /** + * @var OrderByClause|null + */ + public $orderByClause; + + /** + * @param SimpleSelectClause $simpleSelectClause + * @param SubselectFromClause $subselectFromClause + */ + public function __construct($simpleSelectClause, $subselectFromClause) + { + $this->simpleSelectClause = $simpleSelectClause; + $this->subselectFromClause = $subselectFromClause; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkSubselect($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectFromClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectFromClause.php new file mode 100644 index 0000000..9704061 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectFromClause.php @@ -0,0 +1,53 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * SubselectFromClause ::= "FROM" SubselectIdentificationVariableDeclaration {"," SubselectIdentificationVariableDeclaration}* + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class SubselectFromClause extends Node +{ + /** + * @var array + */ + public $identificationVariableDeclarations = []; + + /** + * @param array $identificationVariableDeclarations + */ + public function __construct(array $identificationVariableDeclarations) + { + $this->identificationVariableDeclarations = $identificationVariableDeclarations; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkSubselectFromClause($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectIdentificationVariableDeclaration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectIdentificationVariableDeclaration.php new file mode 100644 index 0000000..866f112 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectIdentificationVariableDeclaration.php @@ -0,0 +1,52 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * SubselectIdentificationVariableDeclaration ::= AssociationPathExpression ["AS"] AliasIdentificationVariable + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + */ +class SubselectIdentificationVariableDeclaration +{ + /** + * @var PathExpression + */ + public $associationPathExpression; + + /** + * @var string + */ + public $aliasIdentificationVariable; + + /** + * Constructor. + * + * @param PathExpression $associationPathExpression + * @param string $aliasIdentificationVariable + */ + public function __construct($associationPathExpression, $aliasIdentificationVariable) + { + $this->associationPathExpression = $associationPathExpression; + $this->aliasIdentificationVariable = $aliasIdentificationVariable; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateClause.php new file mode 100644 index 0000000..23c722a --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateClause.php @@ -0,0 +1,65 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * UpdateClause ::= "UPDATE" AbstractSchemaName [["AS"] AliasIdentificationVariable] "SET" UpdateItem {"," UpdateItem}* + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class UpdateClause extends Node +{ + /** + * @var string + */ + public $abstractSchemaName; + + /** + * @var string + */ + public $aliasIdentificationVariable; + + /** + * @var array + */ + public $updateItems = []; + + /** + * @param string $abstractSchemaName + * @param array $updateItems + */ + public function __construct($abstractSchemaName, array $updateItems) + { + $this->abstractSchemaName = $abstractSchemaName; + $this->updateItems = $updateItems; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkUpdateClause($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateItem.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateItem.php new file mode 100644 index 0000000..f1a288c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateItem.php @@ -0,0 +1,62 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * UpdateItem ::= [IdentificationVariable "."] {StateField | SingleValuedAssociationField} "=" NewValue + * NewValue ::= SimpleArithmeticExpression | StringPrimary | DatetimePrimary | BooleanPrimary | + * EnumPrimary | SimpleEntityExpression | "NULL" + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class UpdateItem extends Node +{ + /** + * @var PathExpression + */ + public $pathExpression; + + /** + * @var InputParameter|ArithmeticExpression|null + */ + public $newValue; + + /** + * @param PathExpression $pathExpression + * @param InputParameter|ArithmeticExpression|null $newValue + */ + public function __construct($pathExpression, $newValue) + { + $this->pathExpression = $pathExpression; + $this->newValue = $newValue; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkUpdateItem($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateStatement.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateStatement.php new file mode 100644 index 0000000..c578efe --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateStatement.php @@ -0,0 +1,58 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * UpdateStatement = UpdateClause [WhereClause] + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class UpdateStatement extends Node +{ + /** + * @var UpdateClause + */ + public $updateClause; + + /** + * @var WhereClause|null + */ + public $whereClause; + + /** + * @param UpdateClause $updateClause + */ + public function __construct($updateClause) + { + $this->updateClause = $updateClause; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkUpdateStatement($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhenClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhenClause.php new file mode 100644 index 0000000..01c0330 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhenClause.php @@ -0,0 +1,62 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * WhenClause ::= "WHEN" ConditionalExpression "THEN" ScalarExpression + * + * @since 2.2 + * + * @link www.doctrine-project.org + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class WhenClause extends Node +{ + /** + * @var ConditionalExpression + */ + public $caseConditionExpression = null; + + /** + * @var mixed + */ + public $thenScalarExpression = null; + + /** + * @param ConditionalExpression $caseConditionExpression + * @param mixed $thenScalarExpression + */ + public function __construct($caseConditionExpression, $thenScalarExpression) + { + $this->caseConditionExpression = $caseConditionExpression; + $this->thenScalarExpression = $thenScalarExpression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkWhenClauseExpression($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhereClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhereClause.php new file mode 100644 index 0000000..e659775 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhereClause.php @@ -0,0 +1,53 @@ +. + */ + +namespace Doctrine\ORM\Query\AST; + +/** + * WhereClause ::= "WHERE" ConditionalExpression + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class WhereClause extends Node +{ + /** + * @var ConditionalExpression + */ + public $conditionalExpression; + + /** + * @param ConditionalExpression $conditionalExpression + */ + public function __construct($conditionalExpression) + { + $this->conditionalExpression = $conditionalExpression; + } + + /** + * {@inheritdoc} + */ + public function dispatch($sqlWalker) + { + return $sqlWalker->walkWhereClause($this); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php new file mode 100644 index 0000000..8955b92 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php @@ -0,0 +1,86 @@ +. + */ + +namespace Doctrine\ORM\Query\Exec; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Cache\QueryCacheProfile; + +/** + * Base class for SQL statement executors. + * + * @author Roman Borschel + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://www.doctrine-project.org + * @since 2.0 + * @todo Rename: AbstractSQLExecutor + */ +abstract class AbstractSqlExecutor +{ + /** + * @var array + */ + protected $_sqlStatements; + + /** + * @var QueryCacheProfile + */ + protected $queryCacheProfile; + + /** + * Gets the SQL statements that are executed by the executor. + * + * @return array All the SQL update statements. + */ + public function getSqlStatements() + { + return $this->_sqlStatements; + } + + /** + * @param \Doctrine\DBAL\Cache\QueryCacheProfile $qcp + * + * @return void + */ + public function setQueryCacheProfile(QueryCacheProfile $qcp) + { + $this->queryCacheProfile = $qcp; + } + + /** + * Do not use query cache + * + * @return void + */ + public function removeQueryCacheProfile() + { + $this->queryCacheProfile = null; + } + + /** + * Executes all sql statements. + * + * @param Connection $conn The database connection that is used to execute the queries. + * @param array $params The parameters. + * @param array $types The parameter types. + * + * @return \Doctrine\DBAL\Driver\Statement + */ + abstract public function execute(Connection $conn, array $params, array $types); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php new file mode 100644 index 0000000..2f3d5ac --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php @@ -0,0 +1,146 @@ +. + */ + +namespace Doctrine\ORM\Query\Exec; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Types\Type; +use Doctrine\ORM\Query\AST; +use Doctrine\ORM\Utility\PersisterHelper; +use Throwable; + +/** + * Executes the SQL statements for bulk DQL DELETE statements on classes in + * Class Table Inheritance (JOINED). + * + * @author Roman Borschel + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://www.doctrine-project.org + * @since 2.0 + */ +class MultiTableDeleteExecutor extends AbstractSqlExecutor +{ + /** + * @var string + */ + private $_createTempTableSql; + + /** + * @var string + */ + private $_dropTempTableSql; + + /** + * @var string + */ + private $_insertSql; + + /** + * Initializes a new MultiTableDeleteExecutor. + * + * Internal note: Any SQL construction and preparation takes place in the constructor for + * best performance. With a query cache the executor will be cached. + * + * @param \Doctrine\ORM\Query\AST\Node $AST The root AST node of the DQL query. + * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker The walker used for SQL generation from the AST. + */ + public function __construct(AST\Node $AST, $sqlWalker) + { + $em = $sqlWalker->getEntityManager(); + $conn = $em->getConnection(); + $platform = $conn->getDatabasePlatform(); + $quoteStrategy = $em->getConfiguration()->getQuoteStrategy(); + + $primaryClass = $em->getClassMetadata($AST->deleteClause->abstractSchemaName); + $primaryDqlAlias = $AST->deleteClause->aliasIdentificationVariable; + $rootClass = $em->getClassMetadata($primaryClass->rootEntityName); + + $tempTable = $platform->getTemporaryTableName($rootClass->getTemporaryIdTableName()); + $idColumnNames = $rootClass->getIdentifierColumnNames(); + $idColumnList = implode(', ', $idColumnNames); + + // 1. Create an INSERT INTO temptable ... SELECT identifiers WHERE $AST->getWhereClause() + $sqlWalker->setSQLTableAlias($primaryClass->getTableName(), 't0', $primaryDqlAlias); + + $this->_insertSql = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ')' + . ' SELECT t0.' . implode(', t0.', $idColumnNames); + + $rangeDecl = new AST\RangeVariableDeclaration($primaryClass->name, $primaryDqlAlias); + $fromClause = new AST\FromClause([new AST\IdentificationVariableDeclaration($rangeDecl, null, [])]); + $this->_insertSql .= $sqlWalker->walkFromClause($fromClause); + + // Append WHERE clause, if there is one. + if ($AST->whereClause) { + $this->_insertSql .= $sqlWalker->walkWhereClause($AST->whereClause); + } + + // 2. Create ID subselect statement used in DELETE ... WHERE ... IN (subselect) + $idSubselect = 'SELECT ' . $idColumnList . ' FROM ' . $tempTable; + + // 3. Create and store DELETE statements + $classNames = array_merge($primaryClass->parentClasses, [$primaryClass->name], $primaryClass->subClasses); + foreach (array_reverse($classNames) as $className) { + $tableName = $quoteStrategy->getTableName($em->getClassMetadata($className), $platform); + $this->_sqlStatements[] = 'DELETE FROM ' . $tableName + . ' WHERE (' . $idColumnList . ') IN (' . $idSubselect . ')'; + } + + // 4. Store DDL for temporary identifier table. + $columnDefinitions = []; + foreach ($idColumnNames as $idColumnName) { + $columnDefinitions[$idColumnName] = [ + 'notnull' => true, + 'type' => Type::getType(PersisterHelper::getTypeOfColumn($idColumnName, $rootClass, $em)), + ]; + } + $this->_createTempTableSql = $platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' (' + . $platform->getColumnDeclarationListSQL($columnDefinitions) . ')'; + $this->_dropTempTableSql = $platform->getDropTemporaryTableSQL($tempTable); + } + + /** + * {@inheritDoc} + */ + public function execute(Connection $conn, array $params, array $types) + { + // Create temporary id table + $conn->executeUpdate($this->_createTempTableSql); + + try { + // Insert identifiers + $numDeleted = $conn->executeUpdate($this->_insertSql, $params, $types); + + // Execute DELETE statements + foreach ($this->_sqlStatements as $sql) { + $conn->executeUpdate($sql); + } + } catch (Throwable $exception) { + // FAILURE! Drop temporary table to avoid possible collisions + $conn->executeUpdate($this->_dropTempTableSql); + + // Re-throw exception + throw $exception; + } + + // Drop temporary table + $conn->executeUpdate($this->_dropTempTableSql); + + return $numDeleted; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php new file mode 100644 index 0000000..47db034 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php @@ -0,0 +1,205 @@ +. + */ + +namespace Doctrine\ORM\Query\Exec; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Types\Type; +use Doctrine\ORM\Query\ParameterTypeInferer; +use Doctrine\ORM\Query\AST; +use Doctrine\ORM\Utility\PersisterHelper; +use Throwable; + +/** + * Executes the SQL statements for bulk DQL UPDATE statements on classes in + * Class Table Inheritance (JOINED). + * + * @author Roman Borschel + * @since 2.0 + */ +class MultiTableUpdateExecutor extends AbstractSqlExecutor +{ + /** + * @var string + */ + private $_createTempTableSql; + + /** + * @var string + */ + private $_dropTempTableSql; + + /** + * @var string + */ + private $_insertSql; + + /** + * @var array + */ + private $_sqlParameters = []; + + /** + * @var int + */ + private $_numParametersInUpdateClause = 0; + + /** + * Initializes a new MultiTableUpdateExecutor. + * + * Internal note: Any SQL construction and preparation takes place in the constructor for + * best performance. With a query cache the executor will be cached. + * + * @param \Doctrine\ORM\Query\AST\Node $AST The root AST node of the DQL query. + * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker The walker used for SQL generation from the AST. + */ + public function __construct(AST\Node $AST, $sqlWalker) + { + $em = $sqlWalker->getEntityManager(); + $conn = $em->getConnection(); + $platform = $conn->getDatabasePlatform(); + $quoteStrategy = $em->getConfiguration()->getQuoteStrategy(); + + $updateClause = $AST->updateClause; + $primaryClass = $sqlWalker->getEntityManager()->getClassMetadata($updateClause->abstractSchemaName); + $rootClass = $em->getClassMetadata($primaryClass->rootEntityName); + + $updateItems = $updateClause->updateItems; + + $tempTable = $platform->getTemporaryTableName($rootClass->getTemporaryIdTableName()); + $idColumnNames = $rootClass->getIdentifierColumnNames(); + $idColumnList = implode(', ', $idColumnNames); + + // 1. Create an INSERT INTO temptable ... SELECT identifiers WHERE $AST->getWhereClause() + $sqlWalker->setSQLTableAlias($primaryClass->getTableName(), 't0', $updateClause->aliasIdentificationVariable); + + $this->_insertSql = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ')' + . ' SELECT t0.' . implode(', t0.', $idColumnNames); + + $rangeDecl = new AST\RangeVariableDeclaration($primaryClass->name, $updateClause->aliasIdentificationVariable); + $fromClause = new AST\FromClause([new AST\IdentificationVariableDeclaration($rangeDecl, null, [])]); + + $this->_insertSql .= $sqlWalker->walkFromClause($fromClause); + + // 2. Create ID subselect statement used in UPDATE ... WHERE ... IN (subselect) + $idSubselect = 'SELECT ' . $idColumnList . ' FROM ' . $tempTable; + + // 3. Create and store UPDATE statements + $classNames = array_merge($primaryClass->parentClasses, [$primaryClass->name], $primaryClass->subClasses); + $i = -1; + + foreach (array_reverse($classNames) as $className) { + $affected = false; + $class = $em->getClassMetadata($className); + $updateSql = 'UPDATE ' . $quoteStrategy->getTableName($class, $platform) . ' SET '; + + foreach ($updateItems as $updateItem) { + $field = $updateItem->pathExpression->field; + + if ((isset($class->fieldMappings[$field]) && ! isset($class->fieldMappings[$field]['inherited'])) || + (isset($class->associationMappings[$field]) && ! isset($class->associationMappings[$field]['inherited']))) { + $newValue = $updateItem->newValue; + + if ( ! $affected) { + $affected = true; + ++$i; + } else { + $updateSql .= ', '; + } + + $updateSql .= $sqlWalker->walkUpdateItem($updateItem); + + if ($newValue instanceof AST\InputParameter) { + $this->_sqlParameters[$i][] = $newValue->name; + + ++$this->_numParametersInUpdateClause; + } + } + } + + if ($affected) { + $this->_sqlStatements[$i] = $updateSql . ' WHERE (' . $idColumnList . ') IN (' . $idSubselect . ')'; + } + } + + // Append WHERE clause to insertSql, if there is one. + if ($AST->whereClause) { + $this->_insertSql .= $sqlWalker->walkWhereClause($AST->whereClause); + } + + // 4. Store DDL for temporary identifier table. + $columnDefinitions = []; + + foreach ($idColumnNames as $idColumnName) { + $columnDefinitions[$idColumnName] = [ + 'notnull' => true, + 'type' => Type::getType(PersisterHelper::getTypeOfColumn($idColumnName, $rootClass, $em)), + ]; + } + + $this->_createTempTableSql = $platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' (' + . $platform->getColumnDeclarationListSQL($columnDefinitions) . ')'; + + $this->_dropTempTableSql = $platform->getDropTemporaryTableSQL($tempTable); + } + + /** + * {@inheritDoc} + */ + public function execute(Connection $conn, array $params, array $types) + { + // Create temporary id table + $conn->executeUpdate($this->_createTempTableSql); + + try { + // Insert identifiers. Parameters from the update clause are cut off. + $numUpdated = $conn->executeUpdate( + $this->_insertSql, + array_slice($params, $this->_numParametersInUpdateClause), + array_slice($types, $this->_numParametersInUpdateClause) + ); + + // Execute UPDATE statements + foreach ($this->_sqlStatements as $key => $statement) { + $paramValues = []; + $paramTypes = []; + + if (isset($this->_sqlParameters[$key])) { + foreach ($this->_sqlParameters[$key] as $parameterKey => $parameterName) { + $paramValues[] = $params[$parameterKey]; + $paramTypes[] = $types[$parameterKey] ?? ParameterTypeInferer::inferType($params[$parameterKey]); + } + } + + $conn->executeUpdate($statement, $paramValues, $paramTypes); + } + } catch (Throwable $exception) { + // FAILURE! Drop temporary table to avoid possible collisions + $conn->executeUpdate($this->_dropTempTableSql); + + // Re-throw exception + throw $exception; + } + + // Drop temporary table + $conn->executeUpdate($this->_dropTempTableSql); + + return $numUpdated; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleSelectExecutor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleSelectExecutor.php new file mode 100644 index 0000000..91827ab --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleSelectExecutor.php @@ -0,0 +1,52 @@ +. + */ + +namespace Doctrine\ORM\Query\Exec; + +use Doctrine\DBAL\Connection; +use Doctrine\ORM\Query\AST\SelectStatement; +use Doctrine\ORM\Query\SqlWalker; + +/** + * Executor that executes the SQL statement for simple DQL SELECT statements. + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @author Roman Borschel + * @link www.doctrine-project.org + * @since 2.0 + */ +class SingleSelectExecutor extends AbstractSqlExecutor +{ + /** + * @param \Doctrine\ORM\Query\AST\SelectStatement $AST + * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker + */ + public function __construct(SelectStatement $AST, SqlWalker $sqlWalker) + { + $this->_sqlStatements = $sqlWalker->walkSelectStatement($AST); + } + + /** + * {@inheritDoc} + */ + public function execute(Connection $conn, array $params, array $types) + { + return $conn->executeQuery($this->_sqlStatements, $params, $types, $this->queryCacheProfile); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php new file mode 100644 index 0000000..e0183dd --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php @@ -0,0 +1,57 @@ +. + */ + +namespace Doctrine\ORM\Query\Exec; + +use Doctrine\DBAL\Connection; +use Doctrine\ORM\Query\AST; + +/** + * Executor that executes the SQL statements for DQL DELETE/UPDATE statements on classes + * that are mapped to a single table. + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @author Roman Borschel + * @link www.doctrine-project.org + * @since 2.0 + * @todo This is exactly the same as SingleSelectExecutor. Unify in SingleStatementExecutor. + */ +class SingleTableDeleteUpdateExecutor extends AbstractSqlExecutor +{ + /** + * @param \Doctrine\ORM\Query\AST\Node $AST + * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker + */ + public function __construct(AST\Node $AST, $sqlWalker) + { + if ($AST instanceof AST\UpdateStatement) { + $this->_sqlStatements = $sqlWalker->walkUpdateStatement($AST); + } else if ($AST instanceof AST\DeleteStatement) { + $this->_sqlStatements = $sqlWalker->walkDeleteStatement($AST); + } + } + + /** + * {@inheritDoc} + */ + public function execute(Connection $conn, array $params, array $types) + { + return $conn->executeUpdate($this->_sqlStatements, $params, $types); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr.php new file mode 100644 index 0000000..2523182 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr.php @@ -0,0 +1,674 @@ +. + */ + +namespace Doctrine\ORM\Query; + +/** + * This class is used to generate DQL expressions via a set of PHP static functions. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + * @todo Rename: ExpressionBuilder + */ +class Expr +{ + /** + * Creates a conjunction of the given boolean expressions. + * + * Example: + * + * [php] + * // (u.type = ?1) AND (u.role = ?2) + * $expr->andX($expr->eq('u.type', ':1'), $expr->eq('u.role', ':2')); + * + * @param Expr\Comparison|Expr\Func|Expr\Orx|string $x Optional clause. Defaults to null, but requires at least one + * defined when converting to string. + * + * @return Expr\Andx + */ + public function andX($x = null) + { + return new Expr\Andx(func_get_args()); + } + + /** + * Creates a disjunction of the given boolean expressions. + * + * Example: + * + * [php] + * // (u.type = ?1) OR (u.role = ?2) + * $q->where($q->expr()->orX('u.type = ?1', 'u.role = ?2')); + * + * @param mixed $x Optional clause. Defaults to null, but requires + * at least one defined when converting to string. + * + * @return Expr\Orx + */ + public function orX($x = null) + { + return new Expr\Orx(func_get_args()); + } + + /** + * Creates an ASCending order expression. + * + * @param mixed $expr + * + * @return Expr\OrderBy + */ + public function asc($expr) + { + return new Expr\OrderBy($expr, 'ASC'); + } + + /** + * Creates a DESCending order expression. + * + * @param mixed $expr + * + * @return Expr\OrderBy + */ + public function desc($expr) + { + return new Expr\OrderBy($expr, 'DESC'); + } + + /** + * Creates an equality comparison expression with the given arguments. + * + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a = . Example: + * + * [php] + * // u.id = ?1 + * $expr->eq('u.id', '?1'); + * + * @param mixed $x Left expression. + * @param mixed $y Right expression. + * + * @return Expr\Comparison + */ + public function eq($x, $y) + { + return new Expr\Comparison($x, Expr\Comparison::EQ, $y); + } + + /** + * Creates an instance of Expr\Comparison, with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a <> . Example: + * + * [php] + * // u.id <> ?1 + * $q->where($q->expr()->neq('u.id', '?1')); + * + * @param mixed $x Left expression. + * @param mixed $y Right expression. + * + * @return Expr\Comparison + */ + public function neq($x, $y) + { + return new Expr\Comparison($x, Expr\Comparison::NEQ, $y); + } + + /** + * Creates an instance of Expr\Comparison, with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a < . Example: + * + * [php] + * // u.id < ?1 + * $q->where($q->expr()->lt('u.id', '?1')); + * + * @param mixed $x Left expression. + * @param mixed $y Right expression. + * + * @return Expr\Comparison + */ + public function lt($x, $y) + { + return new Expr\Comparison($x, Expr\Comparison::LT, $y); + } + + /** + * Creates an instance of Expr\Comparison, with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a <= . Example: + * + * [php] + * // u.id <= ?1 + * $q->where($q->expr()->lte('u.id', '?1')); + * + * @param mixed $x Left expression. + * @param mixed $y Right expression. + * + * @return Expr\Comparison + */ + public function lte($x, $y) + { + return new Expr\Comparison($x, Expr\Comparison::LTE, $y); + } + + /** + * Creates an instance of Expr\Comparison, with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a > . Example: + * + * [php] + * // u.id > ?1 + * $q->where($q->expr()->gt('u.id', '?1')); + * + * @param mixed $x Left expression. + * @param mixed $y Right expression. + * + * @return Expr\Comparison + */ + public function gt($x, $y) + { + return new Expr\Comparison($x, Expr\Comparison::GT, $y); + } + + /** + * Creates an instance of Expr\Comparison, with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a >= . Example: + * + * [php] + * // u.id >= ?1 + * $q->where($q->expr()->gte('u.id', '?1')); + * + * @param mixed $x Left expression. + * @param mixed $y Right expression. + * + * @return Expr\Comparison + */ + public function gte($x, $y) + { + return new Expr\Comparison($x, Expr\Comparison::GTE, $y); + } + + /** + * Creates an instance of AVG() function, with the given argument. + * + * @param mixed $x Argument to be used in AVG() function. + * + * @return Expr\Func + */ + public function avg($x) + { + return new Expr\Func('AVG', [$x]); + } + + /** + * Creates an instance of MAX() function, with the given argument. + * + * @param mixed $x Argument to be used in MAX() function. + * + * @return Expr\Func + */ + public function max($x) + { + return new Expr\Func('MAX', [$x]); + } + + /** + * Creates an instance of MIN() function, with the given argument. + * + * @param mixed $x Argument to be used in MIN() function. + * + * @return Expr\Func + */ + public function min($x) + { + return new Expr\Func('MIN', [$x]); + } + + /** + * Creates an instance of COUNT() function, with the given argument. + * + * @param mixed $x Argument to be used in COUNT() function. + * + * @return Expr\Func + */ + public function count($x) + { + return new Expr\Func('COUNT', [$x]); + } + + /** + * Creates an instance of COUNT(DISTINCT) function, with the given argument. + * + * @param mixed $x Argument to be used in COUNT(DISTINCT) function. + * + * @return string + */ + public function countDistinct($x) + { + return 'COUNT(DISTINCT ' . implode(', ', func_get_args()) . ')'; + } + + /** + * Creates an instance of EXISTS() function, with the given DQL Subquery. + * + * @param mixed $subquery DQL Subquery to be used in EXISTS() function. + * + * @return Expr\Func + */ + public function exists($subquery) + { + return new Expr\Func('EXISTS', [$subquery]); + } + + /** + * Creates an instance of ALL() function, with the given DQL Subquery. + * + * @param mixed $subquery DQL Subquery to be used in ALL() function. + * + * @return Expr\Func + */ + public function all($subquery) + { + return new Expr\Func('ALL', [$subquery]); + } + + /** + * Creates a SOME() function expression with the given DQL subquery. + * + * @param mixed $subquery DQL Subquery to be used in SOME() function. + * + * @return Expr\Func + */ + public function some($subquery) + { + return new Expr\Func('SOME', [$subquery]); + } + + /** + * Creates an ANY() function expression with the given DQL subquery. + * + * @param mixed $subquery DQL Subquery to be used in ANY() function. + * + * @return Expr\Func + */ + public function any($subquery) + { + return new Expr\Func('ANY', [$subquery]); + } + + /** + * Creates a negation expression of the given restriction. + * + * @param mixed $restriction Restriction to be used in NOT() function. + * + * @return Expr\Func + */ + public function not($restriction) + { + return new Expr\Func('NOT', [$restriction]); + } + + /** + * Creates an ABS() function expression with the given argument. + * + * @param mixed $x Argument to be used in ABS() function. + * + * @return Expr\Func + */ + public function abs($x) + { + return new Expr\Func('ABS', [$x]); + } + + /** + * Creates a product mathematical expression with the given arguments. + * + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a * . Example: + * + * [php] + * // u.salary * u.percentAnnualSalaryIncrease + * $q->expr()->prod('u.salary', 'u.percentAnnualSalaryIncrease') + * + * @param mixed $x Left expression. + * @param mixed $y Right expression. + * + * @return Expr\Math + */ + public function prod($x, $y) + { + return new Expr\Math($x, '*', $y); + } + + /** + * Creates a difference mathematical expression with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a - . Example: + * + * [php] + * // u.monthlySubscriptionCount - 1 + * $q->expr()->diff('u.monthlySubscriptionCount', '1') + * + * @param mixed $x Left expression. + * @param mixed $y Right expression. + * + * @return Expr\Math + */ + public function diff($x, $y) + { + return new Expr\Math($x, '-', $y); + } + + /** + * Creates a sum mathematical expression with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a + . Example: + * + * [php] + * // u.numChildren + 1 + * $q->expr()->sum('u.numChildren', '1') + * + * @param mixed $x Left expression. + * @param mixed $y Right expression. + * + * @return Expr\Math + */ + public function sum($x, $y) + { + return new Expr\Math($x, '+', $y); + } + + /** + * Creates a quotient mathematical expression with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a / . Example: + * + * [php] + * // u.total / u.period + * $expr->quot('u.total', 'u.period') + * + * @param mixed $x Left expression. + * @param mixed $y Right expression. + * + * @return Expr\Math + */ + public function quot($x, $y) + { + return new Expr\Math($x, '/', $y); + } + + /** + * Creates a SQRT() function expression with the given argument. + * + * @param mixed $x Argument to be used in SQRT() function. + * + * @return Expr\Func + */ + public function sqrt($x) + { + return new Expr\Func('SQRT', [$x]); + } + + /** + * Creates an IN() expression with the given arguments. + * + * @param string $x Field in string format to be restricted by IN() function. + * @param mixed $y Argument to be used in IN() function. + * + * @return Expr\Func + */ + public function in($x, $y) + { + if (is_array($y)) { + foreach ($y as &$literal) { + if ( ! ($literal instanceof Expr\Literal)) { + $literal = $this->_quoteLiteral($literal); + } + } + } + + return new Expr\Func($x . ' IN', (array) $y); + } + + /** + * Creates a NOT IN() expression with the given arguments. + * + * @param string $x Field in string format to be restricted by NOT IN() function. + * @param mixed $y Argument to be used in NOT IN() function. + * + * @return Expr\Func + */ + public function notIn($x, $y) + { + if (is_array($y)) { + foreach ($y as &$literal) { + if ( ! ($literal instanceof Expr\Literal)) { + $literal = $this->_quoteLiteral($literal); + } + } + } + + return new Expr\Func($x . ' NOT IN', (array) $y); + } + + /** + * Creates an IS NULL expression with the given arguments. + * + * @param string $x Field in string format to be restricted by IS NULL. + * + * @return string + */ + public function isNull($x) + { + return $x . ' IS NULL'; + } + + /** + * Creates an IS NOT NULL expression with the given arguments. + * + * @param string $x Field in string format to be restricted by IS NOT NULL. + * + * @return string + */ + public function isNotNull($x) + { + return $x . ' IS NOT NULL'; + } + + /** + * Creates a LIKE() comparison expression with the given arguments. + * + * @param string $x Field in string format to be inspected by LIKE() comparison. + * @param mixed $y Argument to be used in LIKE() comparison. + * + * @return Expr\Comparison + */ + public function like($x, $y) + { + return new Expr\Comparison($x, 'LIKE', $y); + } + + /** + * Creates a NOT LIKE() comparison expression with the given arguments. + * + * @param string $x Field in string format to be inspected by LIKE() comparison. + * @param mixed $y Argument to be used in LIKE() comparison. + * + * @return Expr\Comparison + */ + public function notLike($x, $y) + { + return new Expr\Comparison($x, 'NOT LIKE', $y); + } + + /** + * Creates a CONCAT() function expression with the given arguments. + * + * @param mixed $x First argument to be used in CONCAT() function. + * @param mixed $y,... Other arguments to be used in CONCAT() function. + * + * @return Expr\Func + */ + public function concat($x, $y) + { + return new Expr\Func('CONCAT', func_get_args()); + } + + /** + * Creates a SUBSTRING() function expression with the given arguments. + * + * @param mixed $x Argument to be used as string to be cropped by SUBSTRING() function. + * @param int $from Initial offset to start cropping string. May accept negative values. + * @param int|null $len Length of crop. May accept negative values. + * + * @return Expr\Func + */ + public function substring($x, $from, $len = null) + { + $args = [$x, $from]; + if (null !== $len) { + $args[] = $len; + } + + return new Expr\Func('SUBSTRING', $args); + } + + /** + * Creates a LOWER() function expression with the given argument. + * + * @param mixed $x Argument to be used in LOWER() function. + * + * @return Expr\Func A LOWER function expression. + */ + public function lower($x) + { + return new Expr\Func('LOWER', [$x]); + } + + /** + * Creates an UPPER() function expression with the given argument. + * + * @param mixed $x Argument to be used in UPPER() function. + * + * @return Expr\Func An UPPER function expression. + */ + public function upper($x) + { + return new Expr\Func('UPPER', [$x]); + } + + /** + * Creates a LENGTH() function expression with the given argument. + * + * @param mixed $x Argument to be used as argument of LENGTH() function. + * + * @return Expr\Func A LENGTH function expression. + */ + public function length($x) + { + return new Expr\Func('LENGTH', [$x]); + } + + /** + * Creates a literal expression of the given argument. + * + * @param mixed $literal Argument to be converted to literal. + * + * @return Expr\Literal + */ + public function literal($literal) + { + return new Expr\Literal($this->_quoteLiteral($literal)); + } + + /** + * Quotes a literal value, if necessary, according to the DQL syntax. + * + * @param mixed $literal The literal value. + * + * @return string + */ + private function _quoteLiteral($literal) + { + if (is_numeric($literal) && !is_string($literal)) { + return (string) $literal; + } else if (is_bool($literal)) { + return $literal ? "true" : "false"; + } + + return "'" . str_replace("'", "''", $literal) . "'"; + } + + /** + * Creates an instance of BETWEEN() function, with the given argument. + * + * @param mixed $val Valued to be inspected by range values. + * @param integer|string $x Starting range value to be used in BETWEEN() function. + * @param integer|string $y End point value to be used in BETWEEN() function. + * + * @return Expr\Func A BETWEEN expression. + */ + public function between($val, $x, $y) + { + return $val . ' BETWEEN ' . $x . ' AND ' . $y; + } + + /** + * Creates an instance of TRIM() function, with the given argument. + * + * @param mixed $x Argument to be used as argument of TRIM() function. + * + * @return Expr\Func a TRIM expression. + */ + public function trim($x) + { + return new Expr\Func('TRIM', $x); + } + + /** + * Creates an instance of MEMBER OF function, with the given arguments. + * + * @param string $x Value to be checked + * @param string $y Value to be checked against + * + * @return Expr\Comparison + */ + public function isMemberOf($x, $y) + { + return new Expr\Comparison($x, 'MEMBER OF', $y); + } + + /** + * Creates an instance of INSTANCE OF function, with the given arguments. + * + * @param string $x Value to be checked + * @param string $y Value to be checked against + * + * @return Expr\Comparison + */ + public function isInstanceOf($x, $y) + { + return new Expr\Comparison($x, 'INSTANCE OF', $y); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Andx.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Andx.php new file mode 100644 index 0000000..dd91916 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Andx.php @@ -0,0 +1,55 @@ +. + */ + +namespace Doctrine\ORM\Query\Expr; + +/** + * Expression class for building DQL and parts. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class Andx extends Composite +{ + /** + * @var string + */ + protected $separator = ' AND '; + + /** + * @var array + */ + protected $allowedClasses = [ + Comparison::class, + Func::class, + Orx::class, + Andx::class, + ]; + + /** + * @return array + */ + public function getParts() + { + return $this->parts; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Base.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Base.php new file mode 100644 index 0000000..d4b8d38 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Base.php @@ -0,0 +1,124 @@ +. + */ + +namespace Doctrine\ORM\Query\Expr; + +/** + * Abstract base Expr class for building DQL parts. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +abstract class Base +{ + /** + * @var string + */ + protected $preSeparator = '('; + + /** + * @var string + */ + protected $separator = ', '; + + /** + * @var string + */ + protected $postSeparator = ')'; + + /** + * @var array + */ + protected $allowedClasses = []; + + /** + * @var array + */ + protected $parts = []; + + /** + * @param mixed $args + */ + public function __construct($args = []) + { + $this->addMultiple($args); + } + + /** + * @param array $args + * + * @return Base + */ + public function addMultiple($args = []) + { + foreach ((array) $args as $arg) { + $this->add($arg); + } + + return $this; + } + + /** + * @param mixed $arg + * + * @return Base + * + * @throws \InvalidArgumentException + */ + public function add($arg) + { + if ( $arg !== null && (!$arg instanceof self || $arg->count() > 0) ) { + // If we decide to keep Expr\Base instances, we can use this check + if ( ! is_string($arg)) { + $class = get_class($arg); + + if ( ! in_array($class, $this->allowedClasses)) { + throw new \InvalidArgumentException("Expression of type '$class' not allowed in this context."); + } + } + + $this->parts[] = $arg; + } + + return $this; + } + + /** + * @return integer + */ + public function count() + { + return count($this->parts); + } + + /** + * @return string + */ + public function __toString() + { + if ($this->count() == 1) { + return (string) $this->parts[0]; + } + + return $this->preSeparator . implode($this->separator, $this->parts) . $this->postSeparator; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Comparison.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Comparison.php new file mode 100644 index 0000000..4103dce --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Comparison.php @@ -0,0 +1,100 @@ +. + */ + +namespace Doctrine\ORM\Query\Expr; + +/** + * Expression class for DQL comparison expressions. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class Comparison +{ + const EQ = '='; + const NEQ = '<>'; + const LT = '<'; + const LTE = '<='; + const GT = '>'; + const GTE = '>='; + + /** + * @var mixed + */ + protected $leftExpr; + + /** + * @var string + */ + protected $operator; + + /** + * @var mixed + */ + protected $rightExpr; + + /** + * Creates a comparison expression with the given arguments. + * + * @param mixed $leftExpr + * @param string $operator + * @param mixed $rightExpr + */ + public function __construct($leftExpr, $operator, $rightExpr) + { + $this->leftExpr = $leftExpr; + $this->operator = $operator; + $this->rightExpr = $rightExpr; + } + + /** + * @return mixed + */ + public function getLeftExpr() + { + return $this->leftExpr; + } + + /** + * @return string + */ + public function getOperator() + { + return $this->operator; + } + + /** + * @return mixed + */ + public function getRightExpr() + { + return $this->rightExpr; + } + + /** + * @return string + */ + public function __toString() + { + return $this->leftExpr . ' ' . $this->operator . ' ' . $this->rightExpr; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Composite.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Composite.php new file mode 100644 index 0000000..6b8a04f --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Composite.php @@ -0,0 +1,71 @@ +. + */ + +namespace Doctrine\ORM\Query\Expr; + +/** + * Expression class for building DQL and parts. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class Composite extends Base +{ + /** + * @return string + */ + public function __toString() + { + if ($this->count() === 1) { + return (string) $this->parts[0]; + } + + $components = []; + + foreach ($this->parts as $part) { + $components[] = $this->processQueryPart($part); + } + + return implode($this->separator, $components); + } + + /** + * @param string $part + * + * @return string + */ + private function processQueryPart($part) + { + $queryPart = (string) $part; + + if (is_object($part) && $part instanceof self && $part->count() > 1) { + return $this->preSeparator . $queryPart . $this->postSeparator; + } + + // Fixes DDC-1237: User may have added a where item containing nested expression (with "OR" or "AND") + if (stripos($queryPart, ' OR ') !== false || stripos($queryPart, ' AND ') !== false) { + return $this->preSeparator . $queryPart . $this->postSeparator; + } + + return $queryPart; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/From.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/From.php new file mode 100644 index 0000000..9dcce9b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/From.php @@ -0,0 +1,92 @@ +. + */ + +namespace Doctrine\ORM\Query\Expr; + +/** + * Expression class for DQL from. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class From +{ + /** + * @var string + */ + protected $from; + + /** + * @var string + */ + protected $alias; + + /** + * @var string + */ + protected $indexBy; + + /** + * @param string $from The class name. + * @param string $alias The alias of the class. + * @param string $indexBy The index for the from. + */ + public function __construct($from, $alias, $indexBy = null) + { + $this->from = $from; + $this->alias = $alias; + $this->indexBy = $indexBy; + } + + /** + * @return string + */ + public function getFrom() + { + return $this->from; + } + + /** + * @return string + */ + public function getAlias() + { + return $this->alias; + } + + /** + * @return string + */ + public function getIndexBy() + { + return $this->indexBy; + } + + /** + * @return string + */ + public function __toString() + { + return $this->from . ' ' . $this->alias . + ($this->indexBy ? ' INDEX BY ' . $this->indexBy : ''); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Func.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Func.php new file mode 100644 index 0000000..b4ed07c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Func.php @@ -0,0 +1,78 @@ +. + */ + +namespace Doctrine\ORM\Query\Expr; + +/** + * Expression class for generating DQL functions. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class Func +{ + /** + * @var string + */ + protected $name; + + /** + * @var array + */ + protected $arguments; + + /** + * Creates a function, with the given argument. + * + * @param string $name + * @param array $arguments + */ + public function __construct($name, $arguments) + { + $this->name = $name; + $this->arguments = (array) $arguments; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return array + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * @return string + */ + public function __toString() + { + return $this->name . '(' . implode(', ', $this->arguments) . ')'; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/GroupBy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/GroupBy.php new file mode 100644 index 0000000..efa3582 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/GroupBy.php @@ -0,0 +1,50 @@ +. + */ + +namespace Doctrine\ORM\Query\Expr; + +/** + * Expression class for building DQL Group By parts. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class GroupBy extends Base +{ + /** + * @var string + */ + protected $preSeparator = ''; + + /** + * @var string + */ + protected $postSeparator = ''; + + /** + * @return array + */ + public function getParts() + { + return $this->parts; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Join.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Join.php new file mode 100644 index 0000000..7a59e24 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Join.php @@ -0,0 +1,145 @@ +. + */ + +namespace Doctrine\ORM\Query\Expr; + +/** + * Expression class for DQL join. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class Join +{ + const INNER_JOIN = 'INNER'; + const LEFT_JOIN = 'LEFT'; + + const ON = 'ON'; + const WITH = 'WITH'; + + /** + * @var string + */ + protected $joinType; + + /** + * @var string + */ + protected $join; + + /** + * @var string + */ + protected $alias; + + /** + * @var string + */ + protected $conditionType; + + /** + * @var string + */ + protected $condition; + + /** + * @var string + */ + protected $indexBy; + + /** + * @param string $joinType The condition type constant. Either INNER_JOIN or LEFT_JOIN. + * @param string $join The relationship to join. + * @param string|null $alias The alias of the join. + * @param string|null $conditionType The condition type constant. Either ON or WITH. + * @param string|null $condition The condition for the join. + * @param string|null $indexBy The index for the join. + */ + public function __construct($joinType, $join, $alias = null, $conditionType = null, $condition = null, $indexBy = null) + { + $this->joinType = $joinType; + $this->join = $join; + $this->alias = $alias; + $this->conditionType = $conditionType; + $this->condition = $condition; + $this->indexBy = $indexBy; + } + + /** + * @return string + */ + public function getJoinType() + { + return $this->joinType; + } + + /** + * @return string + */ + public function getJoin() + { + return $this->join; + } + + /** + * @return string + */ + public function getAlias() + { + return $this->alias; + } + + /** + * @return string + */ + public function getConditionType() + { + return $this->conditionType; + } + + /** + * @return string + */ + public function getCondition() + { + return $this->condition; + } + + /** + * @return string + */ + public function getIndexBy() + { + return $this->indexBy; + } + + /** + * @return string + */ + public function __toString() + { + return strtoupper($this->joinType) . ' JOIN ' . $this->join + . ($this->alias ? ' ' . $this->alias : '') + . ($this->indexBy ? ' INDEX BY ' . $this->indexBy : '') + . ($this->condition ? ' ' . strtoupper($this->conditionType) . ' ' . $this->condition : ''); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Literal.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Literal.php new file mode 100644 index 0000000..98cee79 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Literal.php @@ -0,0 +1,50 @@ +. + */ + +namespace Doctrine\ORM\Query\Expr; + +/** + * Expression class for generating DQL functions. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class Literal extends Base +{ + /** + * @var string + */ + protected $preSeparator = ''; + + /** + * @var string + */ + protected $postSeparator = ''; + + /** + * @return array + */ + public function getParts() + { + return $this->parts; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Math.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Math.php new file mode 100644 index 0000000..9bf800d --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Math.php @@ -0,0 +1,107 @@ +. + */ + +namespace Doctrine\ORM\Query\Expr; + +/** + * Expression class for DQL math statements. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class Math +{ + /** + * @var mixed + */ + protected $leftExpr; + + /** + * @var string + */ + protected $operator; + + /** + * @var mixed + */ + protected $rightExpr; + + /** + * Creates a mathematical expression with the given arguments. + * + * @param mixed $leftExpr + * @param string $operator + * @param mixed $rightExpr + */ + public function __construct($leftExpr, $operator, $rightExpr) + { + $this->leftExpr = $leftExpr; + $this->operator = $operator; + $this->rightExpr = $rightExpr; + } + + /** + * @return mixed + */ + public function getLeftExpr() + { + return $this->leftExpr; + } + + /** + * @return string + */ + public function getOperator() + { + return $this->operator; + } + + /** + * @return mixed + */ + public function getRightExpr() + { + return $this->rightExpr; + } + + /** + * @return string + */ + public function __toString() + { + // Adjusting Left Expression + $leftExpr = (string) $this->leftExpr; + + if ($this->leftExpr instanceof Math) { + $leftExpr = '(' . $leftExpr . ')'; + } + + // Adjusting Right Expression + $rightExpr = (string) $this->rightExpr; + + if ($this->rightExpr instanceof Math) { + $rightExpr = '(' . $rightExpr . ')'; + } + + return $leftExpr . ' ' . $this->operator . ' ' . $rightExpr; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/OrderBy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/OrderBy.php new file mode 100644 index 0000000..a5f8ef9 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/OrderBy.php @@ -0,0 +1,104 @@ +. + */ + +namespace Doctrine\ORM\Query\Expr; + +/** + * Expression class for building DQL Order By parts. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class OrderBy +{ + /** + * @var string + */ + protected $preSeparator = ''; + + /** + * @var string + */ + protected $separator = ', '; + + /** + * @var string + */ + protected $postSeparator = ''; + + /** + * @var array + */ + protected $allowedClasses = []; + + /** + * @var array + */ + protected $parts = []; + + /** + * @param string|null $sort + * @param string|null $order + */ + public function __construct($sort = null, $order = null) + { + if ($sort) { + $this->add($sort, $order); + } + } + + /** + * @param string $sort + * @param string|null $order + * + * @return void + */ + public function add($sort, $order = null) + { + $order = ! $order ? 'ASC' : $order; + $this->parts[] = $sort . ' '. $order; + } + + /** + * @return integer + */ + public function count() + { + return count($this->parts); + } + + /** + * @return array + */ + public function getParts() + { + return $this->parts; + } + + /** + * @return string + */ + public function __toString() + { + return $this->preSeparator . implode($this->separator, $this->parts) . $this->postSeparator; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Orx.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Orx.php new file mode 100644 index 0000000..d36abfa --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Orx.php @@ -0,0 +1,55 @@ +. + */ + +namespace Doctrine\ORM\Query\Expr; + +/** + * Expression class for building DQL OR clauses. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class Orx extends Composite +{ + /** + * @var string + */ + protected $separator = ' OR '; + + /** + * @var array + */ + protected $allowedClasses = [ + Comparison::class, + Func::class, + Andx::class, + Orx::class, + ]; + + /** + * @return array + */ + public function getParts() + { + return $this->parts; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Select.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Select.php new file mode 100644 index 0000000..8ab5153 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Select.php @@ -0,0 +1,55 @@ +. + */ + +namespace Doctrine\ORM\Query\Expr; + +/** + * Expression class for building DQL select statements. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class Select extends Base +{ + /** + * @var string + */ + protected $preSeparator = ''; + + /** + * @var string + */ + protected $postSeparator = ''; + + /** + * @var array + */ + protected $allowedClasses = [Func::class]; + + /** + * @return array + */ + public function getParts() + { + return $this->parts; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Filter/SQLFilter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Filter/SQLFilter.php new file mode 100644 index 0000000..c48edd4 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Filter/SQLFilter.php @@ -0,0 +1,155 @@ +. + */ + +namespace Doctrine\ORM\Query\Filter; + +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Query\ParameterTypeInferer; + +/** + * The base class that user defined filters should extend. + * + * Handles the setting and escaping of parameters. + * + * @author Alexander + * @author Benjamin Eberlei + * @abstract + */ +abstract class SQLFilter +{ + /** + * The entity manager. + * + * @var EntityManagerInterface + */ + private $em; + + /** + * Parameters for the filter. + * + * @var array + */ + private $parameters = []; + + /** + * Constructs the SQLFilter object. + * + * @param EntityManagerInterface $em The entity manager. + */ + final public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + + /** + * Sets a parameter that can be used by the filter. + * + * @param string $name Name of the parameter. + * @param string $value Value of the parameter. + * @param string|null $type The parameter type. If specified, the given value will be run through + * the type conversion of this type. This is usually not needed for + * strings and numeric types. + * + * @return SQLFilter The current SQL filter. + */ + final public function setParameter($name, $value, $type = null) + { + if (null === $type) { + $type = ParameterTypeInferer::inferType($value); + } + + $this->parameters[$name] = ['value' => $value, 'type' => $type]; + + // Keep the parameters sorted for the hash + ksort($this->parameters); + + // The filter collection of the EM is now dirty + $this->em->getFilters()->setFiltersStateDirty(); + + return $this; + } + + /** + * Gets a parameter to use in a query. + * + * The function is responsible for the right output escaping to use the + * value in a query. + * + * @param string $name Name of the parameter. + * + * @return string The SQL escaped parameter to use in a query. + * + * @throws \InvalidArgumentException + */ + final public function getParameter($name) + { + if (!isset($this->parameters[$name])) { + throw new \InvalidArgumentException("Parameter '" . $name . "' does not exist."); + } + + return $this->em->getConnection()->quote($this->parameters[$name]['value'], $this->parameters[$name]['type']); + } + + /** + * Checks if a parameter was set for the filter. + * + * @param string $name Name of the parameter. + * + * @return boolean + */ + final public function hasParameter($name) + { + if (!isset($this->parameters[$name])) { + return false; + } + + return true; + } + + /** + * Returns as string representation of the SQLFilter parameters (the state). + * + * @return string String representation of the SQLFilter. + */ + final public function __toString() + { + return serialize($this->parameters); + } + + /** + * Returns the database connection used by the entity manager + * + * @return \Doctrine\DBAL\Connection + */ + final protected function getConnection() + { + return $this->em->getConnection(); + } + + /** + * Gets the SQL query part to add to a query. + * + * @param ClassMetaData $targetEntity + * @param string $targetTableAlias + * + * @return string The constraint SQL if there is available, empty string otherwise. + */ + abstract public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/FilterCollection.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/FilterCollection.php new file mode 100644 index 0000000..ca7f1ac --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/FilterCollection.php @@ -0,0 +1,225 @@ +. + */ + +namespace Doctrine\ORM\Query; + +use Doctrine\ORM\EntityManagerInterface; + +/** + * Collection class for all the query filters. + * + * @author Alexander + */ +class FilterCollection +{ + /* Filter STATES */ + + /** + * A filter object is in CLEAN state when it has no changed parameters. + */ + const FILTERS_STATE_CLEAN = 1; + + /** + * A filter object is in DIRTY state when it has changed parameters. + */ + const FILTERS_STATE_DIRTY = 2; + + /** + * The used Configuration. + * + * @var \Doctrine\ORM\Configuration + */ + private $config; + + /** + * The EntityManager that "owns" this FilterCollection instance. + * + * @var \Doctrine\ORM\EntityManager + */ + private $em; + + /** + * Instances of enabled filters. + * + * @var \Doctrine\ORM\Query\Filter\SQLFilter[] + */ + private $enabledFilters = []; + + /** + * @var string The filter hash from the last time the query was parsed. + */ + private $filterHash; + + /** + * @var integer The current state of this filter. + */ + private $filtersState = self::FILTERS_STATE_CLEAN; + + /** + * Constructor. + * + * @param EntityManagerInterface $em + */ + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + $this->config = $em->getConfiguration(); + } + + /** + * Gets all the enabled filters. + * + * @return \Doctrine\ORM\Query\Filter\SQLFilter[] The enabled filters. + */ + public function getEnabledFilters() + { + return $this->enabledFilters; + } + + /** + * Enables a filter from the collection. + * + * @param string $name Name of the filter. + * + * @return \Doctrine\ORM\Query\Filter\SQLFilter The enabled filter. + * + * @throws \InvalidArgumentException If the filter does not exist. + */ + public function enable($name) + { + if ( ! $this->has($name)) { + throw new \InvalidArgumentException("Filter '" . $name . "' does not exist."); + } + + if ( ! $this->isEnabled($name)) { + $filterClass = $this->config->getFilterClassName($name); + + $this->enabledFilters[$name] = new $filterClass($this->em); + + // Keep the enabled filters sorted for the hash + ksort($this->enabledFilters); + + // Now the filter collection is dirty + $this->filtersState = self::FILTERS_STATE_DIRTY; + } + + return $this->enabledFilters[$name]; + } + + /** + * Disables a filter. + * + * @param string $name Name of the filter. + * + * @return \Doctrine\ORM\Query\Filter\SQLFilter The disabled filter. + * + * @throws \InvalidArgumentException If the filter does not exist. + */ + public function disable($name) + { + // Get the filter to return it + $filter = $this->getFilter($name); + + unset($this->enabledFilters[$name]); + + // Now the filter collection is dirty + $this->filtersState = self::FILTERS_STATE_DIRTY; + + return $filter; + } + + /** + * Gets an enabled filter from the collection. + * + * @param string $name Name of the filter. + * + * @return \Doctrine\ORM\Query\Filter\SQLFilter The filter. + * + * @throws \InvalidArgumentException If the filter is not enabled. + */ + public function getFilter($name) + { + if ( ! $this->isEnabled($name)) { + throw new \InvalidArgumentException("Filter '" . $name . "' is not enabled."); + } + + return $this->enabledFilters[$name]; + } + + /** + * Checks whether filter with given name is defined. + * + * @param string $name Name of the filter. + * + * @return bool true if the filter exists, false if not. + */ + public function has($name) + { + return null !== $this->config->getFilterClassName($name); + } + + /** + * Checks if a filter is enabled. + * + * @param string $name Name of the filter. + * + * @return boolean True if the filter is enabled, false otherwise. + */ + public function isEnabled($name) + { + return isset($this->enabledFilters[$name]); + } + + /** + * @return boolean True, if the filter collection is clean. + */ + public function isClean() + { + return self::FILTERS_STATE_CLEAN === $this->filtersState; + } + + /** + * Generates a string of currently enabled filters to use for the cache id. + * + * @return string + */ + public function getHash() + { + // If there are only clean filters, the previous hash can be returned + if (self::FILTERS_STATE_CLEAN === $this->filtersState) { + return $this->filterHash; + } + + $filterHash = ''; + + foreach ($this->enabledFilters as $name => $filter) { + $filterHash .= $name . $filter; + } + + return $filterHash; + } + + /** + * Sets the filter state to dirty. + */ + public function setFiltersStateDirty() + { + $this->filtersState = self::FILTERS_STATE_DIRTY; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Lexer.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Lexer.php new file mode 100644 index 0000000..573e433 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Lexer.php @@ -0,0 +1,222 @@ +. + */ + +namespace Doctrine\ORM\Query; + +use Doctrine\Common\Lexer\AbstractLexer; + +/** + * Scans a DQL query for tokens. + * + * @author Guilherme Blanco + * @author Janne Vanhala + * @author Roman Borschel + * @since 2.0 + */ +class Lexer extends AbstractLexer +{ + // All tokens that are not valid identifiers must be < 100 + const T_NONE = 1; + const T_INTEGER = 2; + const T_STRING = 3; + const T_INPUT_PARAMETER = 4; + const T_FLOAT = 5; + const T_CLOSE_PARENTHESIS = 6; + const T_OPEN_PARENTHESIS = 7; + const T_COMMA = 8; + const T_DIVIDE = 9; + const T_DOT = 10; + const T_EQUALS = 11; + const T_GREATER_THAN = 12; + const T_LOWER_THAN = 13; + const T_MINUS = 14; + const T_MULTIPLY = 15; + const T_NEGATE = 16; + const T_PLUS = 17; + const T_OPEN_CURLY_BRACE = 18; + const T_CLOSE_CURLY_BRACE = 19; + + // All tokens that are identifiers or keywords that could be considered as identifiers should be >= 100 + const T_ALIASED_NAME = 100; + const T_FULLY_QUALIFIED_NAME = 101; + const T_IDENTIFIER = 102; + + // All keyword tokens should be >= 200 + const T_ALL = 200; + const T_AND = 201; + const T_ANY = 202; + const T_AS = 203; + const T_ASC = 204; + const T_AVG = 205; + const T_BETWEEN = 206; + const T_BOTH = 207; + const T_BY = 208; + const T_CASE = 209; + const T_COALESCE = 210; + const T_COUNT = 211; + const T_DELETE = 212; + const T_DESC = 213; + const T_DISTINCT = 214; + const T_ELSE = 215; + const T_EMPTY = 216; + const T_END = 217; + const T_ESCAPE = 218; + const T_EXISTS = 219; + const T_FALSE = 220; + const T_FROM = 221; + const T_GROUP = 222; + const T_HAVING = 223; + const T_HIDDEN = 224; + const T_IN = 225; + const T_INDEX = 226; + const T_INNER = 227; + const T_INSTANCE = 228; + const T_IS = 229; + const T_JOIN = 230; + const T_LEADING = 231; + const T_LEFT = 232; + const T_LIKE = 233; + const T_MAX = 234; + const T_MEMBER = 235; + const T_MIN = 236; + const T_NEW = 237; + const T_NOT = 238; + const T_NULL = 239; + const T_NULLIF = 240; + const T_OF = 241; + const T_OR = 242; + const T_ORDER = 243; + const T_OUTER = 244; + const T_PARTIAL = 245; + const T_SELECT = 246; + const T_SET = 247; + const T_SOME = 248; + const T_SUM = 249; + const T_THEN = 250; + const T_TRAILING = 251; + const T_TRUE = 252; + const T_UPDATE = 253; + const T_WHEN = 254; + const T_WHERE = 255; + const T_WITH = 256; + + /** + * Creates a new query scanner object. + * + * @param string $input A query string. + */ + public function __construct($input) + { + $this->setInput($input); + } + + /** + * {@inheritdoc} + */ + protected function getCatchablePatterns() + { + return [ + '[a-z_][a-z0-9_]*\:[a-z_][a-z0-9_]*(?:\\\[a-z_][a-z0-9_]*)*', // aliased name + '[a-z_\\\][a-z0-9_]*(?:\\\[a-z_][a-z0-9_]*)*', // identifier or qualified name + '(?:[0-9]+(?:[\.][0-9]+)*)(?:e[+-]?[0-9]+)?', // numbers + "'(?:[^']|'')*'", // quoted strings + '\?[0-9]*|:[a-z_][a-z0-9_]*' // parameters + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNonCatchablePatterns() + { + return ['\s+', '(.)']; + } + + /** + * {@inheritdoc} + */ + protected function getType(&$value) + { + $type = self::T_NONE; + + switch (true) { + // Recognize numeric values + case (is_numeric($value)): + if (strpos($value, '.') !== false || stripos($value, 'e') !== false) { + return self::T_FLOAT; + } + + return self::T_INTEGER; + + // Recognize quoted strings + case ($value[0] === "'"): + $value = str_replace("''", "'", substr($value, 1, strlen($value) - 2)); + + return self::T_STRING; + + // Recognize identifiers, aliased or qualified names + case (ctype_alpha($value[0]) || $value[0] === '_' || $value[0] === '\\'): + $name = 'Doctrine\ORM\Query\Lexer::T_' . strtoupper($value); + + if (defined($name)) { + $type = constant($name); + + if ($type > 100) { + return $type; + } + } + + if (strpos($value, ':') !== false) { + return self::T_ALIASED_NAME; + } + + if (strpos($value, '\\') !== false) { + return self::T_FULLY_QUALIFIED_NAME; + } + + return self::T_IDENTIFIER; + + // Recognize input parameters + case ($value[0] === '?' || $value[0] === ':'): + return self::T_INPUT_PARAMETER; + + // Recognize symbols + case ($value === '.'): return self::T_DOT; + case ($value === ','): return self::T_COMMA; + case ($value === '('): return self::T_OPEN_PARENTHESIS; + case ($value === ')'): return self::T_CLOSE_PARENTHESIS; + case ($value === '='): return self::T_EQUALS; + case ($value === '>'): return self::T_GREATER_THAN; + case ($value === '<'): return self::T_LOWER_THAN; + case ($value === '+'): return self::T_PLUS; + case ($value === '-'): return self::T_MINUS; + case ($value === '*'): return self::T_MULTIPLY; + case ($value === '/'): return self::T_DIVIDE; + case ($value === '!'): return self::T_NEGATE; + case ($value === '{'): return self::T_OPEN_CURLY_BRACE; + case ($value === '}'): return self::T_CLOSE_CURLY_BRACE; + + // Default + default: + // Do nothing + } + + return $type; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parameter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parameter.php new file mode 100644 index 0000000..6e968a1 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parameter.php @@ -0,0 +1,122 @@ +. + */ + +namespace Doctrine\ORM\Query; + +use function trim; + +/** + * Defines a Query Parameter. + * + * @link www.doctrine-project.org + * @since 2.3 + * @author Guilherme Blanco + */ +class Parameter +{ + /** + * The parameter name. + * + * @var string + */ + private $name; + + /** + * The parameter value. + * + * @var mixed + */ + private $value; + + /** + * The parameter type. + * + * @var mixed + */ + private $type; + + /** + * Whether the parameter type was explicitly specified or not + * + * @var bool + */ + private $typeSpecified; + + /** + * Constructor. + * + * @param string $name Parameter name + * @param mixed $value Parameter value + * @param mixed $type Parameter type + */ + public function __construct($name, $value, $type = null) + { + $this->name = trim($name, ':'); + $this->typeSpecified = $type !== null; + + $this->setValue($value, $type); + } + + /** + * Retrieves the Parameter name. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Retrieves the Parameter value. + * + * @return mixed + */ + public function getValue() + { + return $this->value; + } + + /** + * Retrieves the Parameter type. + * + * @return mixed + */ + public function getType() + { + return $this->type; + } + + /** + * Defines the Parameter value. + * + * @param mixed $value Parameter value. + * @param mixed $type Parameter type. + */ + public function setValue($value, $type = null) + { + $this->value = $value; + $this->type = $type ?: ParameterTypeInferer::inferType($value); + } + + public function typeWasSpecified() : bool + { + return $this->typeSpecified; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParameterTypeInferer.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParameterTypeInferer.php new file mode 100644 index 0000000..07b78f0 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParameterTypeInferer.php @@ -0,0 +1,72 @@ +. + */ + +namespace Doctrine\ORM\Query; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Types\Type; + +/** + * Provides an enclosed support for parameter inferring. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ParameterTypeInferer +{ + /** + * Infers type of a given value, returning a compatible constant: + * - Type (\Doctrine\DBAL\Types\Type::*) + * - Connection (\Doctrine\DBAL\Connection::PARAM_*) + * + * @param mixed $value Parameter value. + * + * @return mixed Parameter type constant. + */ + public static function inferType($value) + { + if (is_int($value)) { + return Type::INTEGER; + } + + if (is_bool($value)) { + return Type::BOOLEAN; + } + + if ($value instanceof \DateTime || $value instanceof \DateTimeInterface) { + return Type::DATETIME; + } + + if ($value instanceof \DateInterval) { + return Type::DATEINTERVAL; + } + + if (is_array($value)) { + return is_int(current($value)) + ? Connection::PARAM_INT_ARRAY + : Connection::PARAM_STR_ARRAY; + } + + return \PDO::PARAM_STR; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php new file mode 100644 index 0000000..7b3e8ff --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php @@ -0,0 +1,3539 @@ +. + */ + +namespace Doctrine\ORM\Query; + +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Query; +use Doctrine\ORM\Query\AST\Functions; +use function in_array; +use function strpos; + +/** + * An LL(*) recursive-descent parser for the context-free grammar of the Doctrine Query Language. + * Parses a DQL query, reports any errors in it, and generates an AST. + * + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Janne Vanhala + * @author Fabio B. Silva + */ +class Parser +{ + /** + * READ-ONLY: Maps BUILT-IN string function names to AST class names. + * + * @var array + */ + private static $_STRING_FUNCTIONS = [ + 'concat' => Functions\ConcatFunction::class, + 'substring' => Functions\SubstringFunction::class, + 'trim' => Functions\TrimFunction::class, + 'lower' => Functions\LowerFunction::class, + 'upper' => Functions\UpperFunction::class, + 'identity' => Functions\IdentityFunction::class, + ]; + + /** + * READ-ONLY: Maps BUILT-IN numeric function names to AST class names. + * + * @var array + */ + private static $_NUMERIC_FUNCTIONS = [ + 'length' => Functions\LengthFunction::class, + 'locate' => Functions\LocateFunction::class, + 'abs' => Functions\AbsFunction::class, + 'sqrt' => Functions\SqrtFunction::class, + 'mod' => Functions\ModFunction::class, + 'size' => Functions\SizeFunction::class, + 'date_diff' => Functions\DateDiffFunction::class, + 'bit_and' => Functions\BitAndFunction::class, + 'bit_or' => Functions\BitOrFunction::class, + + // Aggregate functions + 'min' => Functions\MinFunction::class, + 'max' => Functions\MaxFunction::class, + 'avg' => Functions\AvgFunction::class, + 'sum' => Functions\SumFunction::class, + 'count' => Functions\CountFunction::class, + ]; + + /** + * READ-ONLY: Maps BUILT-IN datetime function names to AST class names. + * + * @var array + */ + private static $_DATETIME_FUNCTIONS = [ + 'current_date' => Functions\CurrentDateFunction::class, + 'current_time' => Functions\CurrentTimeFunction::class, + 'current_timestamp' => Functions\CurrentTimestampFunction::class, + 'date_add' => Functions\DateAddFunction::class, + 'date_sub' => Functions\DateSubFunction::class, + ]; + + /* + * Expressions that were encountered during parsing of identifiers and expressions + * and still need to be validated. + */ + + /** + * @var array + */ + private $deferredIdentificationVariables = []; + + /** + * @var array + */ + private $deferredPartialObjectExpressions = []; + + /** + * @var array + */ + private $deferredPathExpressions = []; + + /** + * @var array + */ + private $deferredResultVariables = []; + + /** + * @var array + */ + private $deferredNewObjectExpressions = []; + + /** + * The lexer. + * + * @var \Doctrine\ORM\Query\Lexer + */ + private $lexer; + + /** + * The parser result. + * + * @var \Doctrine\ORM\Query\ParserResult + */ + private $parserResult; + + /** + * The EntityManager. + * + * @var \Doctrine\ORM\EntityManager + */ + private $em; + + /** + * The Query to parse. + * + * @var Query + */ + private $query; + + /** + * Map of declared query components in the parsed query. + * + * @var array + */ + private $queryComponents = []; + + /** + * Keeps the nesting level of defined ResultVariables. + * + * @var integer + */ + private $nestingLevel = 0; + + /** + * Any additional custom tree walkers that modify the AST. + * + * @var array + */ + private $customTreeWalkers = []; + + /** + * The custom last tree walker, if any, that is responsible for producing the output. + * + * @var TreeWalker + */ + private $customOutputWalker; + + /** + * @var array + */ + private $identVariableExpressions = []; + + /** + * Creates a new query parser object. + * + * @param Query $query The Query to parse. + */ + public function __construct(Query $query) + { + $this->query = $query; + $this->em = $query->getEntityManager(); + $this->lexer = new Lexer($query->getDQL()); + $this->parserResult = new ParserResult(); + } + + /** + * Sets a custom tree walker that produces output. + * This tree walker will be run last over the AST, after any other walkers. + * + * @param string $className + * + * @return void + */ + public function setCustomOutputTreeWalker($className) + { + $this->customOutputWalker = $className; + } + + /** + * Adds a custom tree walker for modifying the AST. + * + * @param string $className + * + * @return void + */ + public function addCustomTreeWalker($className) + { + $this->customTreeWalkers[] = $className; + } + + /** + * Gets the lexer used by the parser. + * + * @return \Doctrine\ORM\Query\Lexer + */ + public function getLexer() + { + return $this->lexer; + } + + /** + * Gets the ParserResult that is being filled with information during parsing. + * + * @return \Doctrine\ORM\Query\ParserResult + */ + public function getParserResult() + { + return $this->parserResult; + } + + /** + * Gets the EntityManager used by the parser. + * + * @return \Doctrine\ORM\EntityManager + */ + public function getEntityManager() + { + return $this->em; + } + + /** + * Parses and builds AST for the given Query. + * + * @return \Doctrine\ORM\Query\AST\SelectStatement | + * \Doctrine\ORM\Query\AST\UpdateStatement | + * \Doctrine\ORM\Query\AST\DeleteStatement + */ + public function getAST() + { + // Parse & build AST + $AST = $this->QueryLanguage(); + + // Process any deferred validations of some nodes in the AST. + // This also allows post-processing of the AST for modification purposes. + $this->processDeferredIdentificationVariables(); + + if ($this->deferredPartialObjectExpressions) { + $this->processDeferredPartialObjectExpressions(); + } + + if ($this->deferredPathExpressions) { + $this->processDeferredPathExpressions(); + } + + if ($this->deferredResultVariables) { + $this->processDeferredResultVariables(); + } + + if ($this->deferredNewObjectExpressions) { + $this->processDeferredNewObjectExpressions($AST); + } + + $this->processRootEntityAliasSelected(); + + // TODO: Is there a way to remove this? It may impact the mixed hydration resultset a lot! + $this->fixIdentificationVariableOrder($AST); + + return $AST; + } + + /** + * 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 The token type. + * + * @return void + * + * @throws QueryException If the tokens don't match. + */ + public function match($token) + { + $lookaheadType = $this->lexer->lookahead['type']; + + // Short-circuit on first condition, usually types match + if ($lookaheadType === $token) { + $this->lexer->moveNext(); + return; + } + + // If parameter is not identifier (1-99) must be exact match + if ($token < Lexer::T_IDENTIFIER) { + $this->syntaxError($this->lexer->getLiteral($token)); + } + + // If parameter is keyword (200+) must be exact match + if ($token > Lexer::T_IDENTIFIER) { + $this->syntaxError($this->lexer->getLiteral($token)); + } + + // If parameter is T_IDENTIFIER, then matches T_IDENTIFIER (100) and keywords (200+) + if ($token === Lexer::T_IDENTIFIER && $lookaheadType < Lexer::T_IDENTIFIER) { + $this->syntaxError($this->lexer->getLiteral($token)); + } + + $this->lexer->moveNext(); + } + + /** + * Frees this parser, enabling it to be reused. + * + * @param boolean $deep Whether to clean peek and reset errors. + * @param integer $position Position to reset. + * + * @return void + */ + public function free($deep = false, $position = 0) + { + // WARNING! Use this method with care. It resets the scanner! + $this->lexer->resetPosition($position); + + // Deep = true cleans peek and also any previously defined errors + if ($deep) { + $this->lexer->resetPeek(); + } + + $this->lexer->token = null; + $this->lexer->lookahead = null; + } + + /** + * Parses a query string. + * + * @return ParserResult + */ + public function parse() + { + $AST = $this->getAST(); + + if (($customWalkers = $this->query->getHint(Query::HINT_CUSTOM_TREE_WALKERS)) !== false) { + $this->customTreeWalkers = $customWalkers; + } + + if (($customOutputWalker = $this->query->getHint(Query::HINT_CUSTOM_OUTPUT_WALKER)) !== false) { + $this->customOutputWalker = $customOutputWalker; + } + + // Run any custom tree walkers over the AST + if ($this->customTreeWalkers) { + $treeWalkerChain = new TreeWalkerChain($this->query, $this->parserResult, $this->queryComponents); + + foreach ($this->customTreeWalkers as $walker) { + $treeWalkerChain->addTreeWalker($walker); + } + + switch (true) { + case ($AST instanceof AST\UpdateStatement): + $treeWalkerChain->walkUpdateStatement($AST); + break; + + case ($AST instanceof AST\DeleteStatement): + $treeWalkerChain->walkDeleteStatement($AST); + break; + + case ($AST instanceof AST\SelectStatement): + default: + $treeWalkerChain->walkSelectStatement($AST); + } + + $this->queryComponents = $treeWalkerChain->getQueryComponents(); + } + + $outputWalkerClass = $this->customOutputWalker ?: SqlWalker::class; + $outputWalker = new $outputWalkerClass($this->query, $this->parserResult, $this->queryComponents); + + // Assign an SQL executor to the parser result + $this->parserResult->setSqlExecutor($outputWalker->getExecutor($AST)); + + return $this->parserResult; + } + + /** + * Fixes order of identification variables. + * + * They have to appear in the select clause in the same order as the + * declarations (from ... x join ... y join ... z ...) appear in the query + * as the hydration process relies on that order for proper operation. + * + * @param AST\SelectStatement|AST\DeleteStatement|AST\UpdateStatement $AST + * + * @return void + */ + private function fixIdentificationVariableOrder($AST) + { + if (count($this->identVariableExpressions) <= 1) { + return; + } + + foreach ($this->queryComponents as $dqlAlias => $qComp) { + if ( ! isset($this->identVariableExpressions[$dqlAlias])) { + continue; + } + + $expr = $this->identVariableExpressions[$dqlAlias]; + $key = array_search($expr, $AST->selectClause->selectExpressions); + + unset($AST->selectClause->selectExpressions[$key]); + + $AST->selectClause->selectExpressions[] = $expr; + } + } + + /** + * Generates a new syntax error. + * + * @param string $expected Expected string. + * @param array|null $token Got token. + * + * @return void + * + * @throws \Doctrine\ORM\Query\QueryException + */ + public function syntaxError($expected = '', $token = null) + { + if ($token === null) { + $token = $this->lexer->lookahead; + } + + $tokenPos = (isset($token['position'])) ? $token['position'] : '-1'; + + $message = "line 0, col {$tokenPos}: Error: "; + $message .= ($expected !== '') ? "Expected {$expected}, got " : 'Unexpected '; + $message .= ($this->lexer->lookahead === null) ? 'end of string.' : "'{$token['value']}'"; + + throw QueryException::syntaxError($message, QueryException::dqlError($this->query->getDQL())); + } + + /** + * Generates a new semantical error. + * + * @param string $message Optional message. + * @param array|null $token Optional token. + * + * @return void + * + * @throws \Doctrine\ORM\Query\QueryException + */ + public function semanticalError($message = '', $token = null) + { + if ($token === null) { + $token = $this->lexer->lookahead ?? ['position' => null]; + } + + // Minimum exposed chars ahead of token + $distance = 12; + + // Find a position of a final word to display in error string + $dql = $this->query->getDQL(); + $length = strlen($dql); + $pos = $token['position'] + $distance; + $pos = strpos($dql, ' ', ($length > $pos) ? $pos : $length); + $length = ($pos !== false) ? $pos - $token['position'] : $distance; + + $tokenPos = (isset($token['position']) && $token['position'] > 0) ? $token['position'] : '-1'; + $tokenStr = substr($dql, $token['position'], $length); + + // Building informative message + $message = 'line 0, col ' . $tokenPos . " near '" . $tokenStr . "': Error: " . $message; + + throw QueryException::semanticalError($message, QueryException::dqlError($this->query->getDQL())); + } + + /** + * Peeks beyond the matched closing parenthesis and returns the first token after that one. + * + * @param boolean $resetPeek Reset peek after finding the closing parenthesis. + * + * @return array + */ + private function peekBeyondClosingParenthesis($resetPeek = true) + { + $token = $this->lexer->peek(); + $numUnmatched = 1; + + while ($numUnmatched > 0 && $token !== null) { + switch ($token['type']) { + case Lexer::T_OPEN_PARENTHESIS: + ++$numUnmatched; + break; + + case Lexer::T_CLOSE_PARENTHESIS: + --$numUnmatched; + break; + + default: + // Do nothing + } + + $token = $this->lexer->peek(); + } + + if ($resetPeek) { + $this->lexer->resetPeek(); + } + + return $token; + } + + /** + * Checks if the given token indicates a mathematical operator. + * + * @param array $token + * + * @return boolean TRUE if the token is a mathematical operator, FALSE otherwise. + */ + private function isMathOperator($token) + { + return $token !== null && in_array($token['type'], [Lexer::T_PLUS, Lexer::T_MINUS, Lexer::T_DIVIDE, Lexer::T_MULTIPLY]); + } + + /** + * Checks if the next-next (after lookahead) token starts a function. + * + * @return boolean TRUE if the next-next tokens start a function, FALSE otherwise. + */ + private function isFunction() + { + $lookaheadType = $this->lexer->lookahead['type']; + $peek = $this->lexer->peek(); + + $this->lexer->resetPeek(); + + return $lookaheadType >= Lexer::T_IDENTIFIER && $peek !== null && $peek['type'] === Lexer::T_OPEN_PARENTHESIS; + } + + /** + * Checks whether the given token type indicates an aggregate function. + * + * @param int $tokenType + * + * @return boolean TRUE if the token type is an aggregate function, FALSE otherwise. + */ + private function isAggregateFunction($tokenType) + { + return in_array($tokenType, [Lexer::T_AVG, Lexer::T_MIN, Lexer::T_MAX, Lexer::T_SUM, Lexer::T_COUNT]); + } + + /** + * Checks whether the current lookahead token of the lexer has the type T_ALL, T_ANY or T_SOME. + * + * @return boolean + */ + private function isNextAllAnySome() + { + return in_array($this->lexer->lookahead['type'], [Lexer::T_ALL, Lexer::T_ANY, Lexer::T_SOME]); + } + + /** + * Validates that the given IdentificationVariable is semantically correct. + * It must exist in query components list. + * + * @return void + */ + private function processDeferredIdentificationVariables() + { + foreach ($this->deferredIdentificationVariables as $deferredItem) { + $identVariable = $deferredItem['expression']; + + // Check if IdentificationVariable exists in queryComponents + if ( ! isset($this->queryComponents[$identVariable])) { + $this->semanticalError( + "'$identVariable' is not defined.", $deferredItem['token'] + ); + } + + $qComp = $this->queryComponents[$identVariable]; + + // Check if queryComponent points to an AbstractSchemaName or a ResultVariable + if ( ! isset($qComp['metadata'])) { + $this->semanticalError( + "'$identVariable' does not point to a Class.", $deferredItem['token'] + ); + } + + // Validate if identification variable nesting level is lower or equal than the current one + if ($qComp['nestingLevel'] > $deferredItem['nestingLevel']) { + $this->semanticalError( + "'$identVariable' is used outside the scope of its declaration.", $deferredItem['token'] + ); + } + } + } + + /** + * Validates that the given NewObjectExpression. + * + * @param \Doctrine\ORM\Query\AST\SelectClause $AST + * + * @return void + */ + private function processDeferredNewObjectExpressions($AST) + { + foreach ($this->deferredNewObjectExpressions as $deferredItem) { + $expression = $deferredItem['expression']; + $token = $deferredItem['token']; + $className = $expression->className; + $args = $expression->args; + $fromClassName = isset($AST->fromClause->identificationVariableDeclarations[0]->rangeVariableDeclaration->abstractSchemaName) + ? $AST->fromClause->identificationVariableDeclarations[0]->rangeVariableDeclaration->abstractSchemaName + : null; + + // If the namespace is not given then assumes the first FROM entity namespace + if (strpos($className, '\\') === false && ! class_exists($className) && strpos($fromClassName, '\\') !== false) { + $namespace = substr($fromClassName, 0, strrpos($fromClassName, '\\')); + $fqcn = $namespace . '\\' . $className; + + if (class_exists($fqcn)) { + $expression->className = $fqcn; + $className = $fqcn; + } + } + + if ( ! class_exists($className)) { + $this->semanticalError(sprintf('Class "%s" is not defined.', $className), $token); + } + + $class = new \ReflectionClass($className); + + if ( ! $class->isInstantiable()) { + $this->semanticalError(sprintf('Class "%s" can not be instantiated.', $className), $token); + } + + if ($class->getConstructor() === null) { + $this->semanticalError(sprintf('Class "%s" has not a valid constructor.', $className), $token); + } + + if ($class->getConstructor()->getNumberOfRequiredParameters() > count($args)) { + $this->semanticalError(sprintf('Number of arguments does not match with "%s" constructor declaration.', $className), $token); + } + } + } + + /** + * Validates that the given PartialObjectExpression is semantically correct. + * It must exist in query components list. + * + * @return void + */ + private function processDeferredPartialObjectExpressions() + { + foreach ($this->deferredPartialObjectExpressions as $deferredItem) { + $expr = $deferredItem['expression']; + $class = $this->queryComponents[$expr->identificationVariable]['metadata']; + + foreach ($expr->partialFieldSet as $field) { + if (isset($class->fieldMappings[$field])) { + continue; + } + + if (isset($class->associationMappings[$field]) && + $class->associationMappings[$field]['isOwningSide'] && + $class->associationMappings[$field]['type'] & ClassMetadata::TO_ONE) { + continue; + } + + $this->semanticalError( + "There is no mapped field named '$field' on class " . $class->name . ".", $deferredItem['token'] + ); + } + + if (array_intersect($class->identifier, $expr->partialFieldSet) != $class->identifier) { + $this->semanticalError( + "The partial field selection of class " . $class->name . " must contain the identifier.", + $deferredItem['token'] + ); + } + } + } + + /** + * Validates that the given ResultVariable is semantically correct. + * It must exist in query components list. + * + * @return void + */ + private function processDeferredResultVariables() + { + foreach ($this->deferredResultVariables as $deferredItem) { + $resultVariable = $deferredItem['expression']; + + // Check if ResultVariable exists in queryComponents + if ( ! isset($this->queryComponents[$resultVariable])) { + $this->semanticalError( + "'$resultVariable' is not defined.", $deferredItem['token'] + ); + } + + $qComp = $this->queryComponents[$resultVariable]; + + // Check if queryComponent points to an AbstractSchemaName or a ResultVariable + if ( ! isset($qComp['resultVariable'])) { + $this->semanticalError( + "'$resultVariable' does not point to a ResultVariable.", $deferredItem['token'] + ); + } + + // Validate if identification variable nesting level is lower or equal than the current one + if ($qComp['nestingLevel'] > $deferredItem['nestingLevel']) { + $this->semanticalError( + "'$resultVariable' is used outside the scope of its declaration.", $deferredItem['token'] + ); + } + } + } + + /** + * Validates that the given PathExpression is semantically correct for grammar rules: + * + * AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression + * SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression + * StateFieldPathExpression ::= IdentificationVariable "." StateField + * SingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField + * CollectionValuedPathExpression ::= IdentificationVariable "." CollectionValuedAssociationField + * + * @return void + */ + private function processDeferredPathExpressions() + { + foreach ($this->deferredPathExpressions as $deferredItem) { + $pathExpression = $deferredItem['expression']; + + $qComp = $this->queryComponents[$pathExpression->identificationVariable]; + $class = $qComp['metadata']; + + if (($field = $pathExpression->field) === null) { + $field = $pathExpression->field = $class->identifier[0]; + } + + // Check if field or association exists + if ( ! isset($class->associationMappings[$field]) && ! isset($class->fieldMappings[$field])) { + $this->semanticalError( + 'Class ' . $class->name . ' has no field or association named ' . $field, + $deferredItem['token'] + ); + } + + $fieldType = AST\PathExpression::TYPE_STATE_FIELD; + + if (isset($class->associationMappings[$field])) { + $assoc = $class->associationMappings[$field]; + + $fieldType = ($assoc['type'] & ClassMetadata::TO_ONE) + ? AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION + : AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION; + } + + // Validate if PathExpression is one of the expected types + $expectedType = $pathExpression->expectedType; + + if ( ! ($expectedType & $fieldType)) { + // We need to recognize which was expected type(s) + $expectedStringTypes = []; + + // Validate state field type + if ($expectedType & AST\PathExpression::TYPE_STATE_FIELD) { + $expectedStringTypes[] = 'StateFieldPathExpression'; + } + + // Validate single valued association (*-to-one) + if ($expectedType & AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION) { + $expectedStringTypes[] = 'SingleValuedAssociationField'; + } + + // Validate single valued association (*-to-many) + if ($expectedType & AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION) { + $expectedStringTypes[] = 'CollectionValuedAssociationField'; + } + + // Build the error message + $semanticalError = 'Invalid PathExpression. '; + $semanticalError .= (count($expectedStringTypes) == 1) + ? 'Must be a ' . $expectedStringTypes[0] . '.' + : implode(' or ', $expectedStringTypes) . ' expected.'; + + $this->semanticalError($semanticalError, $deferredItem['token']); + } + + // We need to force the type in PathExpression + $pathExpression->type = $fieldType; + } + } + + /** + * @return void + */ + private function processRootEntityAliasSelected() + { + if ( ! count($this->identVariableExpressions)) { + return; + } + + foreach ($this->identVariableExpressions as $dqlAlias => $expr) { + if (isset($this->queryComponents[$dqlAlias]) && $this->queryComponents[$dqlAlias]['parent'] === null) { + return; + } + } + + $this->semanticalError('Cannot select entity through identification variables without choosing at least one root entity alias.'); + } + + /** + * QueryLanguage ::= SelectStatement | UpdateStatement | DeleteStatement + * + * @return \Doctrine\ORM\Query\AST\SelectStatement | + * \Doctrine\ORM\Query\AST\UpdateStatement | + * \Doctrine\ORM\Query\AST\DeleteStatement + */ + public function QueryLanguage() + { + $statement = null; + + $this->lexer->moveNext(); + + switch ($this->lexer->lookahead['type'] ?? null) { + case Lexer::T_SELECT: + $statement = $this->SelectStatement(); + break; + + case Lexer::T_UPDATE: + $statement = $this->UpdateStatement(); + break; + + case Lexer::T_DELETE: + $statement = $this->DeleteStatement(); + break; + + default: + $this->syntaxError('SELECT, UPDATE or DELETE'); + break; + } + + // Check for end of string + if ($this->lexer->lookahead !== null) { + $this->syntaxError('end of string'); + } + + return $statement; + } + + /** + * SelectStatement ::= SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] + * + * @return \Doctrine\ORM\Query\AST\SelectStatement + */ + public function SelectStatement() + { + $selectStatement = new AST\SelectStatement($this->SelectClause(), $this->FromClause()); + + $selectStatement->whereClause = $this->lexer->isNextToken(Lexer::T_WHERE) ? $this->WhereClause() : null; + $selectStatement->groupByClause = $this->lexer->isNextToken(Lexer::T_GROUP) ? $this->GroupByClause() : null; + $selectStatement->havingClause = $this->lexer->isNextToken(Lexer::T_HAVING) ? $this->HavingClause() : null; + $selectStatement->orderByClause = $this->lexer->isNextToken(Lexer::T_ORDER) ? $this->OrderByClause() : null; + + return $selectStatement; + } + + /** + * UpdateStatement ::= UpdateClause [WhereClause] + * + * @return \Doctrine\ORM\Query\AST\UpdateStatement + */ + public function UpdateStatement() + { + $updateStatement = new AST\UpdateStatement($this->UpdateClause()); + + $updateStatement->whereClause = $this->lexer->isNextToken(Lexer::T_WHERE) ? $this->WhereClause() : null; + + return $updateStatement; + } + + /** + * DeleteStatement ::= DeleteClause [WhereClause] + * + * @return \Doctrine\ORM\Query\AST\DeleteStatement + */ + public function DeleteStatement() + { + $deleteStatement = new AST\DeleteStatement($this->DeleteClause()); + + $deleteStatement->whereClause = $this->lexer->isNextToken(Lexer::T_WHERE) ? $this->WhereClause() : null; + + return $deleteStatement; + } + + /** + * IdentificationVariable ::= identifier + * + * @return string + */ + public function IdentificationVariable() + { + $this->match(Lexer::T_IDENTIFIER); + + $identVariable = $this->lexer->token['value']; + + $this->deferredIdentificationVariables[] = [ + 'expression' => $identVariable, + 'nestingLevel' => $this->nestingLevel, + 'token' => $this->lexer->token, + ]; + + return $identVariable; + } + + /** + * AliasIdentificationVariable = identifier + * + * @return string + */ + public function AliasIdentificationVariable() + { + $this->match(Lexer::T_IDENTIFIER); + + $aliasIdentVariable = $this->lexer->token['value']; + $exists = isset($this->queryComponents[$aliasIdentVariable]); + + if ($exists) { + $this->semanticalError("'$aliasIdentVariable' is already defined.", $this->lexer->token); + } + + return $aliasIdentVariable; + } + + /** + * AbstractSchemaName ::= fully_qualified_name | aliased_name | identifier + * + * @return string + */ + public function AbstractSchemaName() + { + if ($this->lexer->isNextToken(Lexer::T_FULLY_QUALIFIED_NAME)) { + $this->match(Lexer::T_FULLY_QUALIFIED_NAME); + + return $this->lexer->token['value']; + } + + if ($this->lexer->isNextToken(Lexer::T_IDENTIFIER)) { + $this->match(Lexer::T_IDENTIFIER); + + return $this->lexer->token['value']; + } + + $this->match(Lexer::T_ALIASED_NAME); + + [$namespaceAlias, $simpleClassName] = explode(':', $this->lexer->token['value']); + + return $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName; + } + + /** + * Validates an AbstractSchemaName, making sure the class exists. + * + * @param string $schemaName The name to validate. + * + * @throws QueryException if the name does not exist. + */ + private function validateAbstractSchemaName($schemaName) + { + if (! (class_exists($schemaName, true) || interface_exists($schemaName, true))) { + $this->semanticalError("Class '$schemaName' is not defined.", $this->lexer->token); + } + } + + /** + * AliasResultVariable ::= identifier + * + * @return string + */ + public function AliasResultVariable() + { + $this->match(Lexer::T_IDENTIFIER); + + $resultVariable = $this->lexer->token['value']; + $exists = isset($this->queryComponents[$resultVariable]); + + if ($exists) { + $this->semanticalError("'$resultVariable' is already defined.", $this->lexer->token); + } + + return $resultVariable; + } + + /** + * ResultVariable ::= identifier + * + * @return string + */ + public function ResultVariable() + { + $this->match(Lexer::T_IDENTIFIER); + + $resultVariable = $this->lexer->token['value']; + + // Defer ResultVariable validation + $this->deferredResultVariables[] = [ + 'expression' => $resultVariable, + 'nestingLevel' => $this->nestingLevel, + 'token' => $this->lexer->token, + ]; + + return $resultVariable; + } + + /** + * JoinAssociationPathExpression ::= IdentificationVariable "." (CollectionValuedAssociationField | SingleValuedAssociationField) + * + * @return \Doctrine\ORM\Query\AST\JoinAssociationPathExpression + */ + public function JoinAssociationPathExpression() + { + $identVariable = $this->IdentificationVariable(); + + if ( ! isset($this->queryComponents[$identVariable])) { + $this->semanticalError( + 'Identification Variable ' . $identVariable .' used in join path expression but was not defined before.' + ); + } + + $this->match(Lexer::T_DOT); + $this->match(Lexer::T_IDENTIFIER); + + $field = $this->lexer->token['value']; + + // Validate association field + $qComp = $this->queryComponents[$identVariable]; + $class = $qComp['metadata']; + + if ( ! $class->hasAssociation($field)) { + $this->semanticalError('Class ' . $class->name . ' has no association named ' . $field); + } + + return new AST\JoinAssociationPathExpression($identVariable, $field); + } + + /** + * Parses an arbitrary path expression and defers semantical validation + * based on expected types. + * + * PathExpression ::= IdentificationVariable {"." identifier}* + * + * @param integer $expectedTypes + * + * @return \Doctrine\ORM\Query\AST\PathExpression + */ + public function PathExpression($expectedTypes) + { + $identVariable = $this->IdentificationVariable(); + $field = null; + + if ($this->lexer->isNextToken(Lexer::T_DOT)) { + $this->match(Lexer::T_DOT); + $this->match(Lexer::T_IDENTIFIER); + + $field = $this->lexer->token['value']; + + while ($this->lexer->isNextToken(Lexer::T_DOT)) { + $this->match(Lexer::T_DOT); + $this->match(Lexer::T_IDENTIFIER); + $field .= '.'.$this->lexer->token['value']; + } + } + + // Creating AST node + $pathExpr = new AST\PathExpression($expectedTypes, $identVariable, $field); + + // Defer PathExpression validation if requested to be deferred + $this->deferredPathExpressions[] = [ + 'expression' => $pathExpr, + 'nestingLevel' => $this->nestingLevel, + 'token' => $this->lexer->token, + ]; + + return $pathExpr; + } + + /** + * AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression + * + * @return \Doctrine\ORM\Query\AST\PathExpression + */ + public function AssociationPathExpression() + { + return $this->PathExpression( + AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION | + AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION + ); + } + + /** + * SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression + * + * @return \Doctrine\ORM\Query\AST\PathExpression + */ + public function SingleValuedPathExpression() + { + return $this->PathExpression( + AST\PathExpression::TYPE_STATE_FIELD | + AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION + ); + } + + /** + * StateFieldPathExpression ::= IdentificationVariable "." StateField + * + * @return \Doctrine\ORM\Query\AST\PathExpression + */ + public function StateFieldPathExpression() + { + return $this->PathExpression(AST\PathExpression::TYPE_STATE_FIELD); + } + + /** + * SingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField + * + * @return \Doctrine\ORM\Query\AST\PathExpression + */ + public function SingleValuedAssociationPathExpression() + { + return $this->PathExpression(AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION); + } + + /** + * CollectionValuedPathExpression ::= IdentificationVariable "." CollectionValuedAssociationField + * + * @return \Doctrine\ORM\Query\AST\PathExpression + */ + public function CollectionValuedPathExpression() + { + return $this->PathExpression(AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION); + } + + /** + * SelectClause ::= "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression} + * + * @return \Doctrine\ORM\Query\AST\SelectClause + */ + public function SelectClause() + { + $isDistinct = false; + $this->match(Lexer::T_SELECT); + + // Check for DISTINCT + if ($this->lexer->isNextToken(Lexer::T_DISTINCT)) { + $this->match(Lexer::T_DISTINCT); + + $isDistinct = true; + } + + // Process SelectExpressions (1..N) + $selectExpressions = []; + $selectExpressions[] = $this->SelectExpression(); + + while ($this->lexer->isNextToken(Lexer::T_COMMA)) { + $this->match(Lexer::T_COMMA); + + $selectExpressions[] = $this->SelectExpression(); + } + + return new AST\SelectClause($selectExpressions, $isDistinct); + } + + /** + * SimpleSelectClause ::= "SELECT" ["DISTINCT"] SimpleSelectExpression + * + * @return \Doctrine\ORM\Query\AST\SimpleSelectClause + */ + public function SimpleSelectClause() + { + $isDistinct = false; + $this->match(Lexer::T_SELECT); + + if ($this->lexer->isNextToken(Lexer::T_DISTINCT)) { + $this->match(Lexer::T_DISTINCT); + + $isDistinct = true; + } + + return new AST\SimpleSelectClause($this->SimpleSelectExpression(), $isDistinct); + } + + /** + * UpdateClause ::= "UPDATE" AbstractSchemaName ["AS"] AliasIdentificationVariable "SET" UpdateItem {"," UpdateItem}* + * + * @return \Doctrine\ORM\Query\AST\UpdateClause + */ + public function UpdateClause() + { + $this->match(Lexer::T_UPDATE); + + $token = $this->lexer->lookahead; + $abstractSchemaName = $this->AbstractSchemaName(); + + $this->validateAbstractSchemaName($abstractSchemaName); + + if ($this->lexer->isNextToken(Lexer::T_AS)) { + $this->match(Lexer::T_AS); + } + + $aliasIdentificationVariable = $this->AliasIdentificationVariable(); + + $class = $this->em->getClassMetadata($abstractSchemaName); + + // Building queryComponent + $queryComponent = [ + 'metadata' => $class, + 'parent' => null, + 'relation' => null, + 'map' => null, + 'nestingLevel' => $this->nestingLevel, + 'token' => $token, + ]; + + $this->queryComponents[$aliasIdentificationVariable] = $queryComponent; + + $this->match(Lexer::T_SET); + + $updateItems = []; + $updateItems[] = $this->UpdateItem(); + + while ($this->lexer->isNextToken(Lexer::T_COMMA)) { + $this->match(Lexer::T_COMMA); + + $updateItems[] = $this->UpdateItem(); + } + + $updateClause = new AST\UpdateClause($abstractSchemaName, $updateItems); + $updateClause->aliasIdentificationVariable = $aliasIdentificationVariable; + + return $updateClause; + } + + /** + * DeleteClause ::= "DELETE" ["FROM"] AbstractSchemaName ["AS"] AliasIdentificationVariable + * + * @return \Doctrine\ORM\Query\AST\DeleteClause + */ + public function DeleteClause() + { + $this->match(Lexer::T_DELETE); + + if ($this->lexer->isNextToken(Lexer::T_FROM)) { + $this->match(Lexer::T_FROM); + } + + $token = $this->lexer->lookahead; + $abstractSchemaName = $this->AbstractSchemaName(); + + $this->validateAbstractSchemaName($abstractSchemaName); + + $deleteClause = new AST\DeleteClause($abstractSchemaName); + + if ($this->lexer->isNextToken(Lexer::T_AS)) { + $this->match(Lexer::T_AS); + } + + $aliasIdentificationVariable = $this->lexer->isNextToken(Lexer::T_IDENTIFIER) + ? $this->AliasIdentificationVariable() + : 'alias_should_have_been_set'; + + $deleteClause->aliasIdentificationVariable = $aliasIdentificationVariable; + $class = $this->em->getClassMetadata($deleteClause->abstractSchemaName); + + // Building queryComponent + $queryComponent = [ + 'metadata' => $class, + 'parent' => null, + 'relation' => null, + 'map' => null, + 'nestingLevel' => $this->nestingLevel, + 'token' => $token, + ]; + + $this->queryComponents[$aliasIdentificationVariable] = $queryComponent; + + return $deleteClause; + } + + /** + * FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}* + * + * @return \Doctrine\ORM\Query\AST\FromClause + */ + public function FromClause() + { + $this->match(Lexer::T_FROM); + + $identificationVariableDeclarations = []; + $identificationVariableDeclarations[] = $this->IdentificationVariableDeclaration(); + + while ($this->lexer->isNextToken(Lexer::T_COMMA)) { + $this->match(Lexer::T_COMMA); + + $identificationVariableDeclarations[] = $this->IdentificationVariableDeclaration(); + } + + return new AST\FromClause($identificationVariableDeclarations); + } + + /** + * SubselectFromClause ::= "FROM" SubselectIdentificationVariableDeclaration {"," SubselectIdentificationVariableDeclaration}* + * + * @return \Doctrine\ORM\Query\AST\SubselectFromClause + */ + public function SubselectFromClause() + { + $this->match(Lexer::T_FROM); + + $identificationVariables = []; + $identificationVariables[] = $this->SubselectIdentificationVariableDeclaration(); + + while ($this->lexer->isNextToken(Lexer::T_COMMA)) { + $this->match(Lexer::T_COMMA); + + $identificationVariables[] = $this->SubselectIdentificationVariableDeclaration(); + } + + return new AST\SubselectFromClause($identificationVariables); + } + + /** + * WhereClause ::= "WHERE" ConditionalExpression + * + * @return \Doctrine\ORM\Query\AST\WhereClause + */ + public function WhereClause() + { + $this->match(Lexer::T_WHERE); + + return new AST\WhereClause($this->ConditionalExpression()); + } + + /** + * HavingClause ::= "HAVING" ConditionalExpression + * + * @return \Doctrine\ORM\Query\AST\HavingClause + */ + public function HavingClause() + { + $this->match(Lexer::T_HAVING); + + return new AST\HavingClause($this->ConditionalExpression()); + } + + /** + * GroupByClause ::= "GROUP" "BY" GroupByItem {"," GroupByItem}* + * + * @return \Doctrine\ORM\Query\AST\GroupByClause + */ + public function GroupByClause() + { + $this->match(Lexer::T_GROUP); + $this->match(Lexer::T_BY); + + $groupByItems = [$this->GroupByItem()]; + + while ($this->lexer->isNextToken(Lexer::T_COMMA)) { + $this->match(Lexer::T_COMMA); + + $groupByItems[] = $this->GroupByItem(); + } + + return new AST\GroupByClause($groupByItems); + } + + /** + * OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}* + * + * @return \Doctrine\ORM\Query\AST\OrderByClause + */ + public function OrderByClause() + { + $this->match(Lexer::T_ORDER); + $this->match(Lexer::T_BY); + + $orderByItems = []; + $orderByItems[] = $this->OrderByItem(); + + while ($this->lexer->isNextToken(Lexer::T_COMMA)) { + $this->match(Lexer::T_COMMA); + + $orderByItems[] = $this->OrderByItem(); + } + + return new AST\OrderByClause($orderByItems); + } + + /** + * Subselect ::= SimpleSelectClause SubselectFromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] + * + * @return \Doctrine\ORM\Query\AST\Subselect + */ + public function Subselect() + { + // Increase query nesting level + $this->nestingLevel++; + + $subselect = new AST\Subselect($this->SimpleSelectClause(), $this->SubselectFromClause()); + + $subselect->whereClause = $this->lexer->isNextToken(Lexer::T_WHERE) ? $this->WhereClause() : null; + $subselect->groupByClause = $this->lexer->isNextToken(Lexer::T_GROUP) ? $this->GroupByClause() : null; + $subselect->havingClause = $this->lexer->isNextToken(Lexer::T_HAVING) ? $this->HavingClause() : null; + $subselect->orderByClause = $this->lexer->isNextToken(Lexer::T_ORDER) ? $this->OrderByClause() : null; + + // Decrease query nesting level + $this->nestingLevel--; + + return $subselect; + } + + /** + * UpdateItem ::= SingleValuedPathExpression "=" NewValue + * + * @return \Doctrine\ORM\Query\AST\UpdateItem + */ + public function UpdateItem() + { + $pathExpr = $this->SingleValuedPathExpression(); + + $this->match(Lexer::T_EQUALS); + + $updateItem = new AST\UpdateItem($pathExpr, $this->NewValue()); + + return $updateItem; + } + + /** + * GroupByItem ::= IdentificationVariable | ResultVariable | SingleValuedPathExpression + * + * @return string | \Doctrine\ORM\Query\AST\PathExpression + */ + public function GroupByItem() + { + // We need to check if we are in a IdentificationVariable or SingleValuedPathExpression + $glimpse = $this->lexer->glimpse(); + + if ($glimpse !== null && $glimpse['type'] === Lexer::T_DOT) { + return $this->SingleValuedPathExpression(); + } + + // Still need to decide between IdentificationVariable or ResultVariable + $lookaheadValue = $this->lexer->lookahead['value']; + + if ( ! isset($this->queryComponents[$lookaheadValue])) { + $this->semanticalError('Cannot group by undefined identification or result variable.'); + } + + return (isset($this->queryComponents[$lookaheadValue]['metadata'])) + ? $this->IdentificationVariable() + : $this->ResultVariable(); + } + + /** + * OrderByItem ::= ( + * SimpleArithmeticExpression | SingleValuedPathExpression | + * ScalarExpression | ResultVariable | FunctionDeclaration + * ) ["ASC" | "DESC"] + * + * @return \Doctrine\ORM\Query\AST\OrderByItem + */ + public function OrderByItem() + { + $this->lexer->peek(); // lookahead => '.' + $this->lexer->peek(); // lookahead => token after '.' + + $peek = $this->lexer->peek(); // lookahead => token after the token after the '.' + + $this->lexer->resetPeek(); + + $glimpse = $this->lexer->glimpse(); + + switch (true) { + case ($this->isFunction()): + $expr = $this->FunctionDeclaration(); + break; + + case ($this->isMathOperator($peek)): + $expr = $this->SimpleArithmeticExpression(); + break; + + case $glimpse !== null && $glimpse['type'] === Lexer::T_DOT: + $expr = $this->SingleValuedPathExpression(); + break; + + case ($this->lexer->peek() && $this->isMathOperator($this->peekBeyondClosingParenthesis())): + $expr = $this->ScalarExpression(); + break; + + default: + $expr = $this->ResultVariable(); + break; + } + + $type = 'ASC'; + $item = new AST\OrderByItem($expr); + + switch (true) { + case ($this->lexer->isNextToken(Lexer::T_DESC)): + $this->match(Lexer::T_DESC); + $type = 'DESC'; + break; + + case ($this->lexer->isNextToken(Lexer::T_ASC)): + $this->match(Lexer::T_ASC); + break; + + default: + // Do nothing + } + + $item->type = $type; + + return $item; + } + + /** + * NewValue ::= SimpleArithmeticExpression | StringPrimary | DatetimePrimary | BooleanPrimary | + * EnumPrimary | SimpleEntityExpression | "NULL" + * + * NOTE: Since it is not possible to correctly recognize individual types, here is the full + * grammar that needs to be supported: + * + * NewValue ::= SimpleArithmeticExpression | "NULL" + * + * SimpleArithmeticExpression covers all *Primary grammar rules and also SimpleEntityExpression + * + * @return AST\ArithmeticExpression + */ + public function NewValue() + { + if ($this->lexer->isNextToken(Lexer::T_NULL)) { + $this->match(Lexer::T_NULL); + + return null; + } + + if ($this->lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) { + $this->match(Lexer::T_INPUT_PARAMETER); + + return new AST\InputParameter($this->lexer->token['value']); + } + + return $this->ArithmeticExpression(); + } + + /** + * IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {Join}* + * + * @return \Doctrine\ORM\Query\AST\IdentificationVariableDeclaration + */ + public function IdentificationVariableDeclaration() + { + $joins = []; + $rangeVariableDeclaration = $this->RangeVariableDeclaration(); + $indexBy = $this->lexer->isNextToken(Lexer::T_INDEX) + ? $this->IndexBy() + : null; + + $rangeVariableDeclaration->isRoot = true; + + while ( + $this->lexer->isNextToken(Lexer::T_LEFT) || + $this->lexer->isNextToken(Lexer::T_INNER) || + $this->lexer->isNextToken(Lexer::T_JOIN) + ) { + $joins[] = $this->Join(); + } + + return new AST\IdentificationVariableDeclaration( + $rangeVariableDeclaration, $indexBy, $joins + ); + } + + /** + * SubselectIdentificationVariableDeclaration ::= IdentificationVariableDeclaration + * + * {Internal note: WARNING: Solution is harder than a bare implementation. + * Desired EBNF support: + * + * SubselectIdentificationVariableDeclaration ::= IdentificationVariableDeclaration | (AssociationPathExpression ["AS"] AliasIdentificationVariable) + * + * It demands that entire SQL generation to become programmatical. This is + * needed because association based subselect requires "WHERE" conditional + * expressions to be injected, but there is no scope to do that. Only scope + * accessible is "FROM", prohibiting an easy implementation without larger + * changes.} + * + * @return \Doctrine\ORM\Query\AST\SubselectIdentificationVariableDeclaration | + * \Doctrine\ORM\Query\AST\IdentificationVariableDeclaration + */ + public function SubselectIdentificationVariableDeclaration() + { + /* + NOT YET IMPLEMENTED! + + $glimpse = $this->lexer->glimpse(); + + if ($glimpse['type'] == Lexer::T_DOT) { + $associationPathExpression = $this->AssociationPathExpression(); + + if ($this->lexer->isNextToken(Lexer::T_AS)) { + $this->match(Lexer::T_AS); + } + + $aliasIdentificationVariable = $this->AliasIdentificationVariable(); + $identificationVariable = $associationPathExpression->identificationVariable; + $field = $associationPathExpression->associationField; + + $class = $this->queryComponents[$identificationVariable]['metadata']; + $targetClass = $this->em->getClassMetadata($class->associationMappings[$field]['targetEntity']); + + // Building queryComponent + $joinQueryComponent = array( + 'metadata' => $targetClass, + 'parent' => $identificationVariable, + 'relation' => $class->getAssociationMapping($field), + 'map' => null, + 'nestingLevel' => $this->nestingLevel, + 'token' => $this->lexer->lookahead + ); + + $this->queryComponents[$aliasIdentificationVariable] = $joinQueryComponent; + + return new AST\SubselectIdentificationVariableDeclaration( + $associationPathExpression, $aliasIdentificationVariable + ); + } + */ + + return $this->IdentificationVariableDeclaration(); + } + + /** + * Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" + * (JoinAssociationDeclaration | RangeVariableDeclaration) + * ["WITH" ConditionalExpression] + * + * @return \Doctrine\ORM\Query\AST\Join + */ + public function Join() + { + // Check Join type + $joinType = AST\Join::JOIN_TYPE_INNER; + + switch (true) { + case ($this->lexer->isNextToken(Lexer::T_LEFT)): + $this->match(Lexer::T_LEFT); + + $joinType = AST\Join::JOIN_TYPE_LEFT; + + // Possible LEFT OUTER join + if ($this->lexer->isNextToken(Lexer::T_OUTER)) { + $this->match(Lexer::T_OUTER); + + $joinType = AST\Join::JOIN_TYPE_LEFTOUTER; + } + break; + + case ($this->lexer->isNextToken(Lexer::T_INNER)): + $this->match(Lexer::T_INNER); + break; + + default: + // Do nothing + } + + $this->match(Lexer::T_JOIN); + + $next = $this->lexer->glimpse(); + $joinDeclaration = ($next['type'] === Lexer::T_DOT) ? $this->JoinAssociationDeclaration() : $this->RangeVariableDeclaration(); + $adhocConditions = $this->lexer->isNextToken(Lexer::T_WITH); + $join = new AST\Join($joinType, $joinDeclaration); + + // Describe non-root join declaration + if ($joinDeclaration instanceof AST\RangeVariableDeclaration) { + $joinDeclaration->isRoot = false; + } + + // Check for ad-hoc Join conditions + if ($adhocConditions) { + $this->match(Lexer::T_WITH); + + $join->conditionalExpression = $this->ConditionalExpression(); + } + + return $join; + } + + /** + * RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable + * + * @return \Doctrine\ORM\Query\AST\RangeVariableDeclaration + * + * @throws QueryException + */ + public function RangeVariableDeclaration() + { + if ($this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS) && $this->lexer->glimpse()['type'] === Lexer::T_SELECT) { + $this->semanticalError('Subquery is not supported here', $this->lexer->token); + } + + $abstractSchemaName = $this->AbstractSchemaName(); + + $this->validateAbstractSchemaName($abstractSchemaName); + + if ($this->lexer->isNextToken(Lexer::T_AS)) { + $this->match(Lexer::T_AS); + } + + $token = $this->lexer->lookahead; + $aliasIdentificationVariable = $this->AliasIdentificationVariable(); + $classMetadata = $this->em->getClassMetadata($abstractSchemaName); + + // Building queryComponent + $queryComponent = [ + 'metadata' => $classMetadata, + 'parent' => null, + 'relation' => null, + 'map' => null, + 'nestingLevel' => $this->nestingLevel, + 'token' => $token + ]; + + $this->queryComponents[$aliasIdentificationVariable] = $queryComponent; + + return new AST\RangeVariableDeclaration($abstractSchemaName, $aliasIdentificationVariable); + } + + /** + * JoinAssociationDeclaration ::= JoinAssociationPathExpression ["AS"] AliasIdentificationVariable [IndexBy] + * + * @return \Doctrine\ORM\Query\AST\JoinAssociationPathExpression + */ + public function JoinAssociationDeclaration() + { + $joinAssociationPathExpression = $this->JoinAssociationPathExpression(); + + if ($this->lexer->isNextToken(Lexer::T_AS)) { + $this->match(Lexer::T_AS); + } + + $aliasIdentificationVariable = $this->AliasIdentificationVariable(); + $indexBy = $this->lexer->isNextToken(Lexer::T_INDEX) ? $this->IndexBy() : null; + + $identificationVariable = $joinAssociationPathExpression->identificationVariable; + $field = $joinAssociationPathExpression->associationField; + + $class = $this->queryComponents[$identificationVariable]['metadata']; + $targetClass = $this->em->getClassMetadata($class->associationMappings[$field]['targetEntity']); + + // Building queryComponent + $joinQueryComponent = [ + 'metadata' => $targetClass, + 'parent' => $joinAssociationPathExpression->identificationVariable, + 'relation' => $class->getAssociationMapping($field), + 'map' => null, + 'nestingLevel' => $this->nestingLevel, + 'token' => $this->lexer->lookahead + ]; + + $this->queryComponents[$aliasIdentificationVariable] = $joinQueryComponent; + + return new AST\JoinAssociationDeclaration($joinAssociationPathExpression, $aliasIdentificationVariable, $indexBy); + } + + /** + * PartialObjectExpression ::= "PARTIAL" IdentificationVariable "." PartialFieldSet + * PartialFieldSet ::= "{" SimpleStateField {"," SimpleStateField}* "}" + * + * @return \Doctrine\ORM\Query\AST\PartialObjectExpression + */ + public function PartialObjectExpression() + { + $this->match(Lexer::T_PARTIAL); + + $partialFieldSet = []; + + $identificationVariable = $this->IdentificationVariable(); + + $this->match(Lexer::T_DOT); + $this->match(Lexer::T_OPEN_CURLY_BRACE); + $this->match(Lexer::T_IDENTIFIER); + + $field = $this->lexer->token['value']; + + // First field in partial expression might be embeddable property + while ($this->lexer->isNextToken(Lexer::T_DOT)) { + $this->match(Lexer::T_DOT); + $this->match(Lexer::T_IDENTIFIER); + $field .= '.'.$this->lexer->token['value']; + } + + $partialFieldSet[] = $field; + + while ($this->lexer->isNextToken(Lexer::T_COMMA)) { + $this->match(Lexer::T_COMMA); + $this->match(Lexer::T_IDENTIFIER); + + $field = $this->lexer->token['value']; + + while ($this->lexer->isNextToken(Lexer::T_DOT)) { + $this->match(Lexer::T_DOT); + $this->match(Lexer::T_IDENTIFIER); + $field .= '.'.$this->lexer->token['value']; + } + + $partialFieldSet[] = $field; + } + + $this->match(Lexer::T_CLOSE_CURLY_BRACE); + + $partialObjectExpression = new AST\PartialObjectExpression($identificationVariable, $partialFieldSet); + + // Defer PartialObjectExpression validation + $this->deferredPartialObjectExpressions[] = [ + 'expression' => $partialObjectExpression, + 'nestingLevel' => $this->nestingLevel, + 'token' => $this->lexer->token, + ]; + + return $partialObjectExpression; + } + + /** + * NewObjectExpression ::= "NEW" AbstractSchemaName "(" NewObjectArg {"," NewObjectArg}* ")" + * + * @return \Doctrine\ORM\Query\AST\NewObjectExpression + */ + public function NewObjectExpression() + { + $this->match(Lexer::T_NEW); + + $className = $this->AbstractSchemaName(); // note that this is not yet validated + $token = $this->lexer->token; + + $this->match(Lexer::T_OPEN_PARENTHESIS); + + $args[] = $this->NewObjectArg(); + + while ($this->lexer->isNextToken(Lexer::T_COMMA)) { + $this->match(Lexer::T_COMMA); + + $args[] = $this->NewObjectArg(); + } + + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + $expression = new AST\NewObjectExpression($className, $args); + + // Defer NewObjectExpression validation + $this->deferredNewObjectExpressions[] = [ + 'token' => $token, + 'expression' => $expression, + 'nestingLevel' => $this->nestingLevel, + ]; + + return $expression; + } + + /** + * NewObjectArg ::= ScalarExpression | "(" Subselect ")" + * + * @return mixed + */ + public function NewObjectArg() + { + $token = $this->lexer->lookahead; + $peek = $this->lexer->glimpse(); + + if ($token['type'] === Lexer::T_OPEN_PARENTHESIS && $peek['type'] === Lexer::T_SELECT) { + $this->match(Lexer::T_OPEN_PARENTHESIS); + $expression = $this->Subselect(); + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + return $expression; + } + + return $this->ScalarExpression(); + } + + /** + * IndexBy ::= "INDEX" "BY" StateFieldPathExpression + * + * @return \Doctrine\ORM\Query\AST\IndexBy + */ + public function IndexBy() + { + $this->match(Lexer::T_INDEX); + $this->match(Lexer::T_BY); + $pathExpr = $this->StateFieldPathExpression(); + + // Add the INDEX BY info to the query component + $this->queryComponents[$pathExpr->identificationVariable]['map'] = $pathExpr->field; + + return new AST\IndexBy($pathExpr); + } + + /** + * ScalarExpression ::= SimpleArithmeticExpression | StringPrimary | DateTimePrimary | + * StateFieldPathExpression | BooleanPrimary | CaseExpression | + * InstanceOfExpression + * + * @return mixed One of the possible expressions or subexpressions. + */ + public function ScalarExpression() + { + $lookahead = $this->lexer->lookahead['type']; + $peek = $this->lexer->glimpse(); + + switch (true) { + case ($lookahead === Lexer::T_INTEGER): + case ($lookahead === Lexer::T_FLOAT): + // SimpleArithmeticExpression : (- u.value ) or ( + u.value ) or ( - 1 ) or ( + 1 ) + case ($lookahead === Lexer::T_MINUS): + case ($lookahead === Lexer::T_PLUS): + return $this->SimpleArithmeticExpression(); + + case ($lookahead === Lexer::T_STRING): + return $this->StringPrimary(); + + case ($lookahead === Lexer::T_TRUE): + case ($lookahead === Lexer::T_FALSE): + $this->match($lookahead); + + return new AST\Literal(AST\Literal::BOOLEAN, $this->lexer->token['value']); + + case ($lookahead === Lexer::T_INPUT_PARAMETER): + switch (true) { + case $this->isMathOperator($peek): + // :param + u.value + return $this->SimpleArithmeticExpression(); + default: + return $this->InputParameter(); + } + + case ($lookahead === Lexer::T_CASE): + case ($lookahead === Lexer::T_COALESCE): + case ($lookahead === Lexer::T_NULLIF): + // Since NULLIF and COALESCE can be identified as a function, + // we need to check these before checking for FunctionDeclaration + return $this->CaseExpression(); + + case ($lookahead === Lexer::T_OPEN_PARENTHESIS): + return $this->SimpleArithmeticExpression(); + + // this check must be done before checking for a filed path expression + case ($this->isFunction()): + $this->lexer->peek(); // "(" + + switch (true) { + case ($this->isMathOperator($this->peekBeyondClosingParenthesis())): + // SUM(u.id) + COUNT(u.id) + return $this->SimpleArithmeticExpression(); + + default: + // IDENTITY(u) + return $this->FunctionDeclaration(); + } + + break; + // it is no function, so it must be a field path + case ($lookahead === Lexer::T_IDENTIFIER): + $this->lexer->peek(); // lookahead => '.' + $this->lexer->peek(); // lookahead => token after '.' + $peek = $this->lexer->peek(); // lookahead => token after the token after the '.' + $this->lexer->resetPeek(); + + if ($this->isMathOperator($peek)) { + return $this->SimpleArithmeticExpression(); + } + + return $this->StateFieldPathExpression(); + + default: + $this->syntaxError(); + } + } + + /** + * CaseExpression ::= GeneralCaseExpression | SimpleCaseExpression | CoalesceExpression | NullifExpression + * GeneralCaseExpression ::= "CASE" WhenClause {WhenClause}* "ELSE" ScalarExpression "END" + * WhenClause ::= "WHEN" ConditionalExpression "THEN" ScalarExpression + * SimpleCaseExpression ::= "CASE" CaseOperand SimpleWhenClause {SimpleWhenClause}* "ELSE" ScalarExpression "END" + * CaseOperand ::= StateFieldPathExpression | TypeDiscriminator + * SimpleWhenClause ::= "WHEN" ScalarExpression "THEN" ScalarExpression + * CoalesceExpression ::= "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")" + * NullifExpression ::= "NULLIF" "(" ScalarExpression "," ScalarExpression ")" + * + * @return mixed One of the possible expressions or subexpressions. + */ + public function CaseExpression() + { + $lookahead = $this->lexer->lookahead['type']; + + switch ($lookahead) { + case Lexer::T_NULLIF: + return $this->NullIfExpression(); + + case Lexer::T_COALESCE: + return $this->CoalesceExpression(); + + case Lexer::T_CASE: + $this->lexer->resetPeek(); + $peek = $this->lexer->peek(); + + if ($peek['type'] === Lexer::T_WHEN) { + return $this->GeneralCaseExpression(); + } + + return $this->SimpleCaseExpression(); + + default: + // Do nothing + break; + } + + $this->syntaxError(); + } + + /** + * CoalesceExpression ::= "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")" + * + * @return \Doctrine\ORM\Query\AST\CoalesceExpression + */ + public function CoalesceExpression() + { + $this->match(Lexer::T_COALESCE); + $this->match(Lexer::T_OPEN_PARENTHESIS); + + // Process ScalarExpressions (1..N) + $scalarExpressions = []; + $scalarExpressions[] = $this->ScalarExpression(); + + while ($this->lexer->isNextToken(Lexer::T_COMMA)) { + $this->match(Lexer::T_COMMA); + + $scalarExpressions[] = $this->ScalarExpression(); + } + + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + return new AST\CoalesceExpression($scalarExpressions); + } + + /** + * NullIfExpression ::= "NULLIF" "(" ScalarExpression "," ScalarExpression ")" + * + * @return \Doctrine\ORM\Query\AST\NullIfExpression + */ + public function NullIfExpression() + { + $this->match(Lexer::T_NULLIF); + $this->match(Lexer::T_OPEN_PARENTHESIS); + + $firstExpression = $this->ScalarExpression(); + $this->match(Lexer::T_COMMA); + $secondExpression = $this->ScalarExpression(); + + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + return new AST\NullIfExpression($firstExpression, $secondExpression); + } + + /** + * GeneralCaseExpression ::= "CASE" WhenClause {WhenClause}* "ELSE" ScalarExpression "END" + * + * @return \Doctrine\ORM\Query\AST\GeneralCaseExpression + */ + public function GeneralCaseExpression() + { + $this->match(Lexer::T_CASE); + + // Process WhenClause (1..N) + $whenClauses = []; + + do { + $whenClauses[] = $this->WhenClause(); + } while ($this->lexer->isNextToken(Lexer::T_WHEN)); + + $this->match(Lexer::T_ELSE); + $scalarExpression = $this->ScalarExpression(); + $this->match(Lexer::T_END); + + return new AST\GeneralCaseExpression($whenClauses, $scalarExpression); + } + + /** + * SimpleCaseExpression ::= "CASE" CaseOperand SimpleWhenClause {SimpleWhenClause}* "ELSE" ScalarExpression "END" + * CaseOperand ::= StateFieldPathExpression | TypeDiscriminator + * + * @return AST\SimpleCaseExpression + */ + public function SimpleCaseExpression() + { + $this->match(Lexer::T_CASE); + $caseOperand = $this->StateFieldPathExpression(); + + // Process SimpleWhenClause (1..N) + $simpleWhenClauses = []; + + do { + $simpleWhenClauses[] = $this->SimpleWhenClause(); + } while ($this->lexer->isNextToken(Lexer::T_WHEN)); + + $this->match(Lexer::T_ELSE); + $scalarExpression = $this->ScalarExpression(); + $this->match(Lexer::T_END); + + return new AST\SimpleCaseExpression($caseOperand, $simpleWhenClauses, $scalarExpression); + } + + /** + * WhenClause ::= "WHEN" ConditionalExpression "THEN" ScalarExpression + * + * @return \Doctrine\ORM\Query\AST\WhenClause + */ + public function WhenClause() + { + $this->match(Lexer::T_WHEN); + $conditionalExpression = $this->ConditionalExpression(); + $this->match(Lexer::T_THEN); + + return new AST\WhenClause($conditionalExpression, $this->ScalarExpression()); + } + + /** + * SimpleWhenClause ::= "WHEN" ScalarExpression "THEN" ScalarExpression + * + * @return \Doctrine\ORM\Query\AST\SimpleWhenClause + */ + public function SimpleWhenClause() + { + $this->match(Lexer::T_WHEN); + $conditionalExpression = $this->ScalarExpression(); + $this->match(Lexer::T_THEN); + + return new AST\SimpleWhenClause($conditionalExpression, $this->ScalarExpression()); + } + + /** + * SelectExpression ::= ( + * IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | + * PartialObjectExpression | "(" Subselect ")" | CaseExpression | NewObjectExpression + * ) [["AS"] ["HIDDEN"] AliasResultVariable] + * + * @return \Doctrine\ORM\Query\AST\SelectExpression + */ + public function SelectExpression() + { + $expression = null; + $identVariable = null; + $peek = $this->lexer->glimpse(); + $lookaheadType = $this->lexer->lookahead['type']; + + switch (true) { + // ScalarExpression (u.name) + case ($lookaheadType === Lexer::T_IDENTIFIER && $peek['type'] === Lexer::T_DOT): + $expression = $this->ScalarExpression(); + break; + + // IdentificationVariable (u) + case ($lookaheadType === Lexer::T_IDENTIFIER && $peek['type'] !== Lexer::T_OPEN_PARENTHESIS): + $expression = $identVariable = $this->IdentificationVariable(); + break; + + // CaseExpression (CASE ... or NULLIF(...) or COALESCE(...)) + case ($lookaheadType === Lexer::T_CASE): + case ($lookaheadType === Lexer::T_COALESCE): + case ($lookaheadType === Lexer::T_NULLIF): + $expression = $this->CaseExpression(); + break; + + // DQL Function (SUM(u.value) or SUM(u.value) + 1) + case ($this->isFunction()): + $this->lexer->peek(); // "(" + + switch (true) { + case ($this->isMathOperator($this->peekBeyondClosingParenthesis())): + // SUM(u.id) + COUNT(u.id) + $expression = $this->ScalarExpression(); + break; + + default: + // IDENTITY(u) + $expression = $this->FunctionDeclaration(); + break; + } + + break; + + // PartialObjectExpression (PARTIAL u.{id, name}) + case ($lookaheadType === Lexer::T_PARTIAL): + $expression = $this->PartialObjectExpression(); + $identVariable = $expression->identificationVariable; + break; + + // Subselect + case ($lookaheadType === Lexer::T_OPEN_PARENTHESIS && $peek['type'] === Lexer::T_SELECT): + $this->match(Lexer::T_OPEN_PARENTHESIS); + $expression = $this->Subselect(); + $this->match(Lexer::T_CLOSE_PARENTHESIS); + break; + + // Shortcut: ScalarExpression => SimpleArithmeticExpression + case ($lookaheadType === Lexer::T_OPEN_PARENTHESIS): + case ($lookaheadType === Lexer::T_INTEGER): + case ($lookaheadType === Lexer::T_STRING): + case ($lookaheadType === Lexer::T_FLOAT): + // SimpleArithmeticExpression : (- u.value ) or ( + u.value ) + case ($lookaheadType === Lexer::T_MINUS): + case ($lookaheadType === Lexer::T_PLUS): + $expression = $this->SimpleArithmeticExpression(); + break; + + // NewObjectExpression (New ClassName(id, name)) + case ($lookaheadType === Lexer::T_NEW): + $expression = $this->NewObjectExpression(); + break; + + default: + $this->syntaxError( + 'IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | PartialObjectExpression | "(" Subselect ")" | CaseExpression', + $this->lexer->lookahead + ); + } + + // [["AS"] ["HIDDEN"] AliasResultVariable] + $mustHaveAliasResultVariable = false; + + if ($this->lexer->isNextToken(Lexer::T_AS)) { + $this->match(Lexer::T_AS); + + $mustHaveAliasResultVariable = true; + } + + $hiddenAliasResultVariable = false; + + if ($this->lexer->isNextToken(Lexer::T_HIDDEN)) { + $this->match(Lexer::T_HIDDEN); + + $hiddenAliasResultVariable = true; + } + + $aliasResultVariable = null; + + if ($mustHaveAliasResultVariable || $this->lexer->isNextToken(Lexer::T_IDENTIFIER)) { + $token = $this->lexer->lookahead; + $aliasResultVariable = $this->AliasResultVariable(); + + // Include AliasResultVariable in query components. + $this->queryComponents[$aliasResultVariable] = [ + 'resultVariable' => $expression, + 'nestingLevel' => $this->nestingLevel, + 'token' => $token, + ]; + } + + // AST + + $expr = new AST\SelectExpression($expression, $aliasResultVariable, $hiddenAliasResultVariable); + + if ($identVariable) { + $this->identVariableExpressions[$identVariable] = $expr; + } + + return $expr; + } + + /** + * SimpleSelectExpression ::= ( + * StateFieldPathExpression | IdentificationVariable | FunctionDeclaration | + * AggregateExpression | "(" Subselect ")" | ScalarExpression + * ) [["AS"] AliasResultVariable] + * + * @return \Doctrine\ORM\Query\AST\SimpleSelectExpression + */ + public function SimpleSelectExpression() + { + $peek = $this->lexer->glimpse(); + + switch ($this->lexer->lookahead['type']) { + case Lexer::T_IDENTIFIER: + switch (true) { + case ($peek['type'] === Lexer::T_DOT): + $expression = $this->StateFieldPathExpression(); + + return new AST\SimpleSelectExpression($expression); + + case ($peek['type'] !== Lexer::T_OPEN_PARENTHESIS): + $expression = $this->IdentificationVariable(); + + return new AST\SimpleSelectExpression($expression); + + case ($this->isFunction()): + // SUM(u.id) + COUNT(u.id) + if ($this->isMathOperator($this->peekBeyondClosingParenthesis())) { + return new AST\SimpleSelectExpression($this->ScalarExpression()); + } + // COUNT(u.id) + if ($this->isAggregateFunction($this->lexer->lookahead['type'])) { + return new AST\SimpleSelectExpression($this->AggregateExpression()); + } + // IDENTITY(u) + return new AST\SimpleSelectExpression($this->FunctionDeclaration()); + + default: + // Do nothing + } + break; + + case Lexer::T_OPEN_PARENTHESIS: + if ($peek['type'] !== Lexer::T_SELECT) { + // Shortcut: ScalarExpression => SimpleArithmeticExpression + $expression = $this->SimpleArithmeticExpression(); + + return new AST\SimpleSelectExpression($expression); + } + + // Subselect + $this->match(Lexer::T_OPEN_PARENTHESIS); + $expression = $this->Subselect(); + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + return new AST\SimpleSelectExpression($expression); + + default: + // Do nothing + } + + $this->lexer->peek(); + + $expression = $this->ScalarExpression(); + $expr = new AST\SimpleSelectExpression($expression); + + if ($this->lexer->isNextToken(Lexer::T_AS)) { + $this->match(Lexer::T_AS); + } + + if ($this->lexer->isNextToken(Lexer::T_IDENTIFIER)) { + $token = $this->lexer->lookahead; + $resultVariable = $this->AliasResultVariable(); + $expr->fieldIdentificationVariable = $resultVariable; + + // Include AliasResultVariable in query components. + $this->queryComponents[$resultVariable] = [ + 'resultvariable' => $expr, + 'nestingLevel' => $this->nestingLevel, + 'token' => $token, + ]; + } + + return $expr; + } + + /** + * ConditionalExpression ::= ConditionalTerm {"OR" ConditionalTerm}* + * + * @return \Doctrine\ORM\Query\AST\ConditionalExpression + */ + public function ConditionalExpression() + { + $conditionalTerms = []; + $conditionalTerms[] = $this->ConditionalTerm(); + + while ($this->lexer->isNextToken(Lexer::T_OR)) { + $this->match(Lexer::T_OR); + + $conditionalTerms[] = $this->ConditionalTerm(); + } + + // Phase 1 AST optimization: Prevent AST\ConditionalExpression + // if only one AST\ConditionalTerm is defined + if (count($conditionalTerms) == 1) { + return $conditionalTerms[0]; + } + + return new AST\ConditionalExpression($conditionalTerms); + } + + /** + * ConditionalTerm ::= ConditionalFactor {"AND" ConditionalFactor}* + * + * @return \Doctrine\ORM\Query\AST\ConditionalTerm + */ + public function ConditionalTerm() + { + $conditionalFactors = []; + $conditionalFactors[] = $this->ConditionalFactor(); + + while ($this->lexer->isNextToken(Lexer::T_AND)) { + $this->match(Lexer::T_AND); + + $conditionalFactors[] = $this->ConditionalFactor(); + } + + // Phase 1 AST optimization: Prevent AST\ConditionalTerm + // if only one AST\ConditionalFactor is defined + if (count($conditionalFactors) == 1) { + return $conditionalFactors[0]; + } + + return new AST\ConditionalTerm($conditionalFactors); + } + + /** + * ConditionalFactor ::= ["NOT"] ConditionalPrimary + * + * @return \Doctrine\ORM\Query\AST\ConditionalFactor + */ + public function ConditionalFactor() + { + $not = false; + + if ($this->lexer->isNextToken(Lexer::T_NOT)) { + $this->match(Lexer::T_NOT); + + $not = true; + } + + $conditionalPrimary = $this->ConditionalPrimary(); + + // Phase 1 AST optimization: Prevent AST\ConditionalFactor + // if only one AST\ConditionalPrimary is defined + if ( ! $not) { + return $conditionalPrimary; + } + + $conditionalFactor = new AST\ConditionalFactor($conditionalPrimary); + $conditionalFactor->not = $not; + + return $conditionalFactor; + } + + /** + * ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")" + * + * @return \Doctrine\ORM\Query\AST\ConditionalPrimary + */ + public function ConditionalPrimary() + { + $condPrimary = new AST\ConditionalPrimary; + + if ( ! $this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) { + $condPrimary->simpleConditionalExpression = $this->SimpleConditionalExpression(); + + return $condPrimary; + } + + // Peek beyond the matching closing parenthesis ')' + $peek = $this->peekBeyondClosingParenthesis(); + + if ($peek !== null && ( + in_array($peek['value'], ['=', '<', '<=', '<>', '>', '>=', '!=']) || + in_array($peek['type'], [Lexer::T_NOT, Lexer::T_BETWEEN, Lexer::T_LIKE, Lexer::T_IN, Lexer::T_IS, Lexer::T_EXISTS]) || + $this->isMathOperator($peek) + )) { + $condPrimary->simpleConditionalExpression = $this->SimpleConditionalExpression(); + + return $condPrimary; + } + + $this->match(Lexer::T_OPEN_PARENTHESIS); + $condPrimary->conditionalExpression = $this->ConditionalExpression(); + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + return $condPrimary; + } + + /** + * SimpleConditionalExpression ::= + * ComparisonExpression | BetweenExpression | LikeExpression | + * InExpression | NullComparisonExpression | ExistsExpression | + * EmptyCollectionComparisonExpression | CollectionMemberExpression | + * InstanceOfExpression + */ + public function SimpleConditionalExpression() + { + if ($this->lexer->isNextToken(Lexer::T_EXISTS)) { + return $this->ExistsExpression(); + } + + $token = $this->lexer->lookahead; + $peek = $this->lexer->glimpse(); + $lookahead = $token; + + if ($this->lexer->isNextToken(Lexer::T_NOT)) { + $token = $this->lexer->glimpse(); + } + + if ($token['type'] === Lexer::T_IDENTIFIER || $token['type'] === Lexer::T_INPUT_PARAMETER || $this->isFunction()) { + // Peek beyond the matching closing parenthesis. + $beyond = $this->lexer->peek(); + + switch ($peek['value']) { + case '(': + // Peeks beyond the matched closing parenthesis. + $token = $this->peekBeyondClosingParenthesis(false); + + if ($token['type'] === Lexer::T_NOT) { + $token = $this->lexer->peek(); + } + + if ($token['type'] === Lexer::T_IS) { + $lookahead = $this->lexer->peek(); + } + break; + + default: + // Peek beyond the PathExpression or InputParameter. + $token = $beyond; + + while ($token['value'] === '.') { + $this->lexer->peek(); + + $token = $this->lexer->peek(); + } + + // Also peek beyond a NOT if there is one. + if ($token['type'] === Lexer::T_NOT) { + $token = $this->lexer->peek(); + } + + // We need to go even further in case of IS (differentiate between NULL and EMPTY) + $lookahead = $this->lexer->peek(); + } + + // Also peek beyond a NOT if there is one. + if ($lookahead['type'] === Lexer::T_NOT) { + $lookahead = $this->lexer->peek(); + } + + $this->lexer->resetPeek(); + } + + if ($token['type'] === Lexer::T_BETWEEN) { + return $this->BetweenExpression(); + } + + if ($token['type'] === Lexer::T_LIKE) { + return $this->LikeExpression(); + } + + if ($token['type'] === Lexer::T_IN) { + return $this->InExpression(); + } + + if ($token['type'] === Lexer::T_INSTANCE) { + return $this->InstanceOfExpression(); + } + + if ($token['type'] === Lexer::T_MEMBER) { + return $this->CollectionMemberExpression(); + } + + if ($token['type'] === Lexer::T_IS && $lookahead['type'] === Lexer::T_NULL) { + return $this->NullComparisonExpression(); + } + + if ($token['type'] === Lexer::T_IS && $lookahead['type'] === Lexer::T_EMPTY) { + return $this->EmptyCollectionComparisonExpression(); + } + + return $this->ComparisonExpression(); + } + + /** + * EmptyCollectionComparisonExpression ::= CollectionValuedPathExpression "IS" ["NOT"] "EMPTY" + * + * @return \Doctrine\ORM\Query\AST\EmptyCollectionComparisonExpression + */ + public function EmptyCollectionComparisonExpression() + { + $emptyCollectionCompExpr = new AST\EmptyCollectionComparisonExpression( + $this->CollectionValuedPathExpression() + ); + $this->match(Lexer::T_IS); + + if ($this->lexer->isNextToken(Lexer::T_NOT)) { + $this->match(Lexer::T_NOT); + $emptyCollectionCompExpr->not = true; + } + + $this->match(Lexer::T_EMPTY); + + return $emptyCollectionCompExpr; + } + + /** + * CollectionMemberExpression ::= EntityExpression ["NOT"] "MEMBER" ["OF"] CollectionValuedPathExpression + * + * EntityExpression ::= SingleValuedAssociationPathExpression | SimpleEntityExpression + * SimpleEntityExpression ::= IdentificationVariable | InputParameter + * + * @return \Doctrine\ORM\Query\AST\CollectionMemberExpression + */ + public function CollectionMemberExpression() + { + $not = false; + $entityExpr = $this->EntityExpression(); + + if ($this->lexer->isNextToken(Lexer::T_NOT)) { + $this->match(Lexer::T_NOT); + + $not = true; + } + + $this->match(Lexer::T_MEMBER); + + if ($this->lexer->isNextToken(Lexer::T_OF)) { + $this->match(Lexer::T_OF); + } + + $collMemberExpr = new AST\CollectionMemberExpression( + $entityExpr, $this->CollectionValuedPathExpression() + ); + $collMemberExpr->not = $not; + + return $collMemberExpr; + } + + /** + * Literal ::= string | char | integer | float | boolean + * + * @return \Doctrine\ORM\Query\AST\Literal + */ + public function Literal() + { + switch ($this->lexer->lookahead['type']) { + case Lexer::T_STRING: + $this->match(Lexer::T_STRING); + + return new AST\Literal(AST\Literal::STRING, $this->lexer->token['value']); + case Lexer::T_INTEGER: + case Lexer::T_FLOAT: + $this->match( + $this->lexer->isNextToken(Lexer::T_INTEGER) ? Lexer::T_INTEGER : Lexer::T_FLOAT + ); + + return new AST\Literal(AST\Literal::NUMERIC, $this->lexer->token['value']); + case Lexer::T_TRUE: + case Lexer::T_FALSE: + $this->match( + $this->lexer->isNextToken(Lexer::T_TRUE) ? Lexer::T_TRUE : Lexer::T_FALSE + ); + + return new AST\Literal(AST\Literal::BOOLEAN, $this->lexer->token['value']); + default: + $this->syntaxError('Literal'); + } + } + + /** + * InParameter ::= Literal | InputParameter + * + * @return string | \Doctrine\ORM\Query\AST\InputParameter + */ + public function InParameter() + { + if ($this->lexer->lookahead['type'] == Lexer::T_INPUT_PARAMETER) { + return $this->InputParameter(); + } + + return $this->Literal(); + } + + /** + * InputParameter ::= PositionalParameter | NamedParameter + * + * @return \Doctrine\ORM\Query\AST\InputParameter + */ + public function InputParameter() + { + $this->match(Lexer::T_INPUT_PARAMETER); + + return new AST\InputParameter($this->lexer->token['value']); + } + + /** + * ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")" + * + * @return \Doctrine\ORM\Query\AST\ArithmeticExpression + */ + public function ArithmeticExpression() + { + $expr = new AST\ArithmeticExpression; + + if ($this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) { + $peek = $this->lexer->glimpse(); + + if ($peek['type'] === Lexer::T_SELECT) { + $this->match(Lexer::T_OPEN_PARENTHESIS); + $expr->subselect = $this->Subselect(); + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + return $expr; + } + } + + $expr->simpleArithmeticExpression = $this->SimpleArithmeticExpression(); + + return $expr; + } + + /** + * SimpleArithmeticExpression ::= ArithmeticTerm {("+" | "-") ArithmeticTerm}* + * + * @return \Doctrine\ORM\Query\AST\SimpleArithmeticExpression + */ + public function SimpleArithmeticExpression() + { + $terms = []; + $terms[] = $this->ArithmeticTerm(); + + while (($isPlus = $this->lexer->isNextToken(Lexer::T_PLUS)) || $this->lexer->isNextToken(Lexer::T_MINUS)) { + $this->match(($isPlus) ? Lexer::T_PLUS : Lexer::T_MINUS); + + $terms[] = $this->lexer->token['value']; + $terms[] = $this->ArithmeticTerm(); + } + + // Phase 1 AST optimization: Prevent AST\SimpleArithmeticExpression + // if only one AST\ArithmeticTerm is defined + if (count($terms) == 1) { + return $terms[0]; + } + + return new AST\SimpleArithmeticExpression($terms); + } + + /** + * ArithmeticTerm ::= ArithmeticFactor {("*" | "/") ArithmeticFactor}* + * + * @return \Doctrine\ORM\Query\AST\ArithmeticTerm + */ + public function ArithmeticTerm() + { + $factors = []; + $factors[] = $this->ArithmeticFactor(); + + while (($isMult = $this->lexer->isNextToken(Lexer::T_MULTIPLY)) || $this->lexer->isNextToken(Lexer::T_DIVIDE)) { + $this->match(($isMult) ? Lexer::T_MULTIPLY : Lexer::T_DIVIDE); + + $factors[] = $this->lexer->token['value']; + $factors[] = $this->ArithmeticFactor(); + } + + // Phase 1 AST optimization: Prevent AST\ArithmeticTerm + // if only one AST\ArithmeticFactor is defined + if (count($factors) == 1) { + return $factors[0]; + } + + return new AST\ArithmeticTerm($factors); + } + + /** + * ArithmeticFactor ::= [("+" | "-")] ArithmeticPrimary + * + * @return \Doctrine\ORM\Query\AST\ArithmeticFactor + */ + public function ArithmeticFactor() + { + $sign = null; + + if (($isPlus = $this->lexer->isNextToken(Lexer::T_PLUS)) || $this->lexer->isNextToken(Lexer::T_MINUS)) { + $this->match(($isPlus) ? Lexer::T_PLUS : Lexer::T_MINUS); + $sign = $isPlus; + } + + $primary = $this->ArithmeticPrimary(); + + // Phase 1 AST optimization: Prevent AST\ArithmeticFactor + // if only one AST\ArithmeticPrimary is defined + if ($sign === null) { + return $primary; + } + + return new AST\ArithmeticFactor($primary, $sign); + } + + /** + * ArithmeticPrimary ::= SingleValuedPathExpression | Literal | ParenthesisExpression + * | FunctionsReturningNumerics | AggregateExpression | FunctionsReturningStrings + * | FunctionsReturningDatetime | IdentificationVariable | ResultVariable + * | InputParameter | CaseExpression + */ + public function ArithmeticPrimary() + { + if ($this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) { + $this->match(Lexer::T_OPEN_PARENTHESIS); + + $expr = $this->SimpleArithmeticExpression(); + + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + return new AST\ParenthesisExpression($expr); + } + + switch ($this->lexer->lookahead['type']) { + case Lexer::T_COALESCE: + case Lexer::T_NULLIF: + case Lexer::T_CASE: + return $this->CaseExpression(); + + case Lexer::T_IDENTIFIER: + $peek = $this->lexer->glimpse(); + + if ($peek !== null && $peek['value'] === '(') { + return $this->FunctionDeclaration(); + } + + if ($peek !== null && $peek['value'] === '.') { + return $this->SingleValuedPathExpression(); + } + + if (isset($this->queryComponents[$this->lexer->lookahead['value']]['resultVariable'])) { + return $this->ResultVariable(); + } + + return $this->StateFieldPathExpression(); + + case Lexer::T_INPUT_PARAMETER: + return $this->InputParameter(); + + default: + $peek = $this->lexer->glimpse(); + + if ($peek !== null && $peek['value'] === '(') { + return $this->FunctionDeclaration(); + } + + return $this->Literal(); + } + } + + /** + * StringExpression ::= StringPrimary | ResultVariable | "(" Subselect ")" + * + * @return \Doctrine\ORM\Query\AST\Subselect | + * string + */ + public function StringExpression() + { + $peek = $this->lexer->glimpse(); + + // Subselect + if ($this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS) && $peek['type'] === Lexer::T_SELECT) { + $this->match(Lexer::T_OPEN_PARENTHESIS); + $expr = $this->Subselect(); + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + return $expr; + } + + // ResultVariable (string) + if ($this->lexer->isNextToken(Lexer::T_IDENTIFIER) && + isset($this->queryComponents[$this->lexer->lookahead['value']]['resultVariable'])) { + return $this->ResultVariable(); + } + + return $this->StringPrimary(); + } + + /** + * StringPrimary ::= StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression | CaseExpression + */ + public function StringPrimary() + { + $lookaheadType = $this->lexer->lookahead['type']; + + switch ($lookaheadType) { + case Lexer::T_IDENTIFIER: + $peek = $this->lexer->glimpse(); + + if ($peek['value'] == '.') { + return $this->StateFieldPathExpression(); + } + + if ($peek['value'] == '(') { + // do NOT directly go to FunctionsReturningString() because it doesn't check for custom functions. + return $this->FunctionDeclaration(); + } + + $this->syntaxError("'.' or '('"); + break; + + case Lexer::T_STRING: + $this->match(Lexer::T_STRING); + + return new AST\Literal(AST\Literal::STRING, $this->lexer->token['value']); + + case Lexer::T_INPUT_PARAMETER: + return $this->InputParameter(); + + case Lexer::T_CASE: + case Lexer::T_COALESCE: + case Lexer::T_NULLIF: + return $this->CaseExpression(); + default: + if ($this->isAggregateFunction($lookaheadType)) { + return $this->AggregateExpression(); + } + } + + $this->syntaxError( + 'StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression' + ); + } + + /** + * EntityExpression ::= SingleValuedAssociationPathExpression | SimpleEntityExpression + * + * @return \Doctrine\ORM\Query\AST\PathExpression | + * \Doctrine\ORM\Query\AST\SimpleEntityExpression + */ + public function EntityExpression() + { + $glimpse = $this->lexer->glimpse(); + + if ($this->lexer->isNextToken(Lexer::T_IDENTIFIER) && $glimpse['value'] === '.') { + return $this->SingleValuedAssociationPathExpression(); + } + + return $this->SimpleEntityExpression(); + } + + /** + * SimpleEntityExpression ::= IdentificationVariable | InputParameter + * + * @return string | \Doctrine\ORM\Query\AST\InputParameter + */ + public function SimpleEntityExpression() + { + if ($this->lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) { + return $this->InputParameter(); + } + + return $this->StateFieldPathExpression(); + } + + /** + * AggregateExpression ::= + * ("AVG" | "MAX" | "MIN" | "SUM" | "COUNT") "(" ["DISTINCT"] SimpleArithmeticExpression ")" + * + * @return \Doctrine\ORM\Query\AST\AggregateExpression + */ + public function AggregateExpression() + { + $lookaheadType = $this->lexer->lookahead['type']; + $isDistinct = false; + + if ( ! in_array($lookaheadType, [Lexer::T_COUNT, Lexer::T_AVG, Lexer::T_MAX, Lexer::T_MIN, Lexer::T_SUM])) { + $this->syntaxError('One of: MAX, MIN, AVG, SUM, COUNT'); + } + + $this->match($lookaheadType); + $functionName = $this->lexer->token['value']; + $this->match(Lexer::T_OPEN_PARENTHESIS); + + if ($this->lexer->isNextToken(Lexer::T_DISTINCT)) { + $this->match(Lexer::T_DISTINCT); + $isDistinct = true; + } + + $pathExp = $this->SimpleArithmeticExpression(); + + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + return new AST\AggregateExpression($functionName, $pathExp, $isDistinct); + } + + /** + * QuantifiedExpression ::= ("ALL" | "ANY" | "SOME") "(" Subselect ")" + * + * @return \Doctrine\ORM\Query\AST\QuantifiedExpression + */ + public function QuantifiedExpression() + { + $lookaheadType = $this->lexer->lookahead['type']; + $value = $this->lexer->lookahead['value']; + + if ( ! in_array($lookaheadType, [Lexer::T_ALL, Lexer::T_ANY, Lexer::T_SOME])) { + $this->syntaxError('ALL, ANY or SOME'); + } + + $this->match($lookaheadType); + $this->match(Lexer::T_OPEN_PARENTHESIS); + + $qExpr = new AST\QuantifiedExpression($this->Subselect()); + $qExpr->type = $value; + + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + return $qExpr; + } + + /** + * BetweenExpression ::= ArithmeticExpression ["NOT"] "BETWEEN" ArithmeticExpression "AND" ArithmeticExpression + * + * @return \Doctrine\ORM\Query\AST\BetweenExpression + */ + public function BetweenExpression() + { + $not = false; + $arithExpr1 = $this->ArithmeticExpression(); + + if ($this->lexer->isNextToken(Lexer::T_NOT)) { + $this->match(Lexer::T_NOT); + $not = true; + } + + $this->match(Lexer::T_BETWEEN); + $arithExpr2 = $this->ArithmeticExpression(); + $this->match(Lexer::T_AND); + $arithExpr3 = $this->ArithmeticExpression(); + + $betweenExpr = new AST\BetweenExpression($arithExpr1, $arithExpr2, $arithExpr3); + $betweenExpr->not = $not; + + return $betweenExpr; + } + + /** + * ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression ) + * + * @return \Doctrine\ORM\Query\AST\ComparisonExpression + */ + public function ComparisonExpression() + { + $this->lexer->glimpse(); + + $leftExpr = $this->ArithmeticExpression(); + $operator = $this->ComparisonOperator(); + $rightExpr = ($this->isNextAllAnySome()) + ? $this->QuantifiedExpression() + : $this->ArithmeticExpression(); + + return new AST\ComparisonExpression($leftExpr, $operator, $rightExpr); + } + + /** + * InExpression ::= SingleValuedPathExpression ["NOT"] "IN" "(" (InParameter {"," InParameter}* | Subselect) ")" + * + * @return \Doctrine\ORM\Query\AST\InExpression + */ + public function InExpression() + { + $inExpression = new AST\InExpression($this->ArithmeticExpression()); + + if ($this->lexer->isNextToken(Lexer::T_NOT)) { + $this->match(Lexer::T_NOT); + $inExpression->not = true; + } + + $this->match(Lexer::T_IN); + $this->match(Lexer::T_OPEN_PARENTHESIS); + + if ($this->lexer->isNextToken(Lexer::T_SELECT)) { + $inExpression->subselect = $this->Subselect(); + } else { + $literals = []; + $literals[] = $this->InParameter(); + + while ($this->lexer->isNextToken(Lexer::T_COMMA)) { + $this->match(Lexer::T_COMMA); + $literals[] = $this->InParameter(); + } + + $inExpression->literals = $literals; + } + + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + return $inExpression; + } + + /** + * InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (InstanceOfParameter | "(" InstanceOfParameter {"," InstanceOfParameter}* ")") + * + * @return \Doctrine\ORM\Query\AST\InstanceOfExpression + */ + public function InstanceOfExpression() + { + $instanceOfExpression = new AST\InstanceOfExpression($this->IdentificationVariable()); + + if ($this->lexer->isNextToken(Lexer::T_NOT)) { + $this->match(Lexer::T_NOT); + $instanceOfExpression->not = true; + } + + $this->match(Lexer::T_INSTANCE); + $this->match(Lexer::T_OF); + + $exprValues = []; + + if ($this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) { + $this->match(Lexer::T_OPEN_PARENTHESIS); + + $exprValues[] = $this->InstanceOfParameter(); + + while ($this->lexer->isNextToken(Lexer::T_COMMA)) { + $this->match(Lexer::T_COMMA); + + $exprValues[] = $this->InstanceOfParameter(); + } + + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + $instanceOfExpression->value = $exprValues; + + return $instanceOfExpression; + } + + $exprValues[] = $this->InstanceOfParameter(); + + $instanceOfExpression->value = $exprValues; + + return $instanceOfExpression; + } + + /** + * InstanceOfParameter ::= AbstractSchemaName | InputParameter + * + * @return mixed + */ + public function InstanceOfParameter() + { + if ($this->lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) { + $this->match(Lexer::T_INPUT_PARAMETER); + + return new AST\InputParameter($this->lexer->token['value']); + } + + $abstractSchemaName = $this->AbstractSchemaName(); + + $this->validateAbstractSchemaName($abstractSchemaName); + + return $abstractSchemaName; + } + + /** + * LikeExpression ::= StringExpression ["NOT"] "LIKE" StringPrimary ["ESCAPE" char] + * + * @return \Doctrine\ORM\Query\AST\LikeExpression + */ + public function LikeExpression() + { + $stringExpr = $this->StringExpression(); + $not = false; + + if ($this->lexer->isNextToken(Lexer::T_NOT)) { + $this->match(Lexer::T_NOT); + $not = true; + } + + $this->match(Lexer::T_LIKE); + + if ($this->lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) { + $this->match(Lexer::T_INPUT_PARAMETER); + $stringPattern = new AST\InputParameter($this->lexer->token['value']); + } else { + $stringPattern = $this->StringPrimary(); + } + + $escapeChar = null; + + if ($this->lexer->lookahead !== null && $this->lexer->lookahead['type'] === Lexer::T_ESCAPE) { + $this->match(Lexer::T_ESCAPE); + $this->match(Lexer::T_STRING); + + $escapeChar = new AST\Literal(AST\Literal::STRING, $this->lexer->token['value']); + } + + $likeExpr = new AST\LikeExpression($stringExpr, $stringPattern, $escapeChar); + $likeExpr->not = $not; + + return $likeExpr; + } + + /** + * NullComparisonExpression ::= (InputParameter | NullIfExpression | CoalesceExpression | AggregateExpression | FunctionDeclaration | IdentificationVariable | SingleValuedPathExpression | ResultVariable) "IS" ["NOT"] "NULL" + * + * @return \Doctrine\ORM\Query\AST\NullComparisonExpression + */ + public function NullComparisonExpression() + { + switch (true) { + case $this->lexer->isNextToken(Lexer::T_INPUT_PARAMETER): + $this->match(Lexer::T_INPUT_PARAMETER); + + $expr = new AST\InputParameter($this->lexer->token['value']); + break; + + case $this->lexer->isNextToken(Lexer::T_NULLIF): + $expr = $this->NullIfExpression(); + break; + + case $this->lexer->isNextToken(Lexer::T_COALESCE): + $expr = $this->CoalesceExpression(); + break; + + case $this->isFunction(): + $expr = $this->FunctionDeclaration(); + break; + + default: + // We need to check if we are in a IdentificationVariable or SingleValuedPathExpression + $glimpse = $this->lexer->glimpse(); + + if ($glimpse['type'] === Lexer::T_DOT) { + $expr = $this->SingleValuedPathExpression(); + + // Leave switch statement + break; + } + + $lookaheadValue = $this->lexer->lookahead['value']; + + // Validate existing component + if ( ! isset($this->queryComponents[$lookaheadValue])) { + $this->semanticalError('Cannot add having condition on undefined result variable.'); + } + + // Validate SingleValuedPathExpression (ie.: "product") + if (isset($this->queryComponents[$lookaheadValue]['metadata'])) { + $expr = $this->SingleValuedPathExpression(); + break; + } + + // Validating ResultVariable + if ( ! isset($this->queryComponents[$lookaheadValue]['resultVariable'])) { + $this->semanticalError('Cannot add having condition on a non result variable.'); + } + + $expr = $this->ResultVariable(); + break; + } + + $nullCompExpr = new AST\NullComparisonExpression($expr); + + $this->match(Lexer::T_IS); + + if ($this->lexer->isNextToken(Lexer::T_NOT)) { + $this->match(Lexer::T_NOT); + + $nullCompExpr->not = true; + } + + $this->match(Lexer::T_NULL); + + return $nullCompExpr; + } + + /** + * ExistsExpression ::= ["NOT"] "EXISTS" "(" Subselect ")" + * + * @return \Doctrine\ORM\Query\AST\ExistsExpression + */ + public function ExistsExpression() + { + $not = false; + + if ($this->lexer->isNextToken(Lexer::T_NOT)) { + $this->match(Lexer::T_NOT); + $not = true; + } + + $this->match(Lexer::T_EXISTS); + $this->match(Lexer::T_OPEN_PARENTHESIS); + + $existsExpression = new AST\ExistsExpression($this->Subselect()); + $existsExpression->not = $not; + + $this->match(Lexer::T_CLOSE_PARENTHESIS); + + return $existsExpression; + } + + /** + * ComparisonOperator ::= "=" | "<" | "<=" | "<>" | ">" | ">=" | "!=" + * + * @return string + */ + public function ComparisonOperator() + { + switch ($this->lexer->lookahead['value']) { + case '=': + $this->match(Lexer::T_EQUALS); + + return '='; + + case '<': + $this->match(Lexer::T_LOWER_THAN); + $operator = '<'; + + if ($this->lexer->isNextToken(Lexer::T_EQUALS)) { + $this->match(Lexer::T_EQUALS); + $operator .= '='; + } else if ($this->lexer->isNextToken(Lexer::T_GREATER_THAN)) { + $this->match(Lexer::T_GREATER_THAN); + $operator .= '>'; + } + + return $operator; + + case '>': + $this->match(Lexer::T_GREATER_THAN); + $operator = '>'; + + if ($this->lexer->isNextToken(Lexer::T_EQUALS)) { + $this->match(Lexer::T_EQUALS); + $operator .= '='; + } + + return $operator; + + case '!': + $this->match(Lexer::T_NEGATE); + $this->match(Lexer::T_EQUALS); + + return '<>'; + + default: + $this->syntaxError('=, <, <=, <>, >, >=, !='); + } + } + + /** + * FunctionDeclaration ::= FunctionsReturningStrings | FunctionsReturningNumerics | FunctionsReturningDatetime + * + * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode + */ + public function FunctionDeclaration() + { + $token = $this->lexer->lookahead; + $funcName = strtolower($token['value']); + + $customFunctionDeclaration = $this->CustomFunctionDeclaration(); + + // Check for custom functions functions first! + switch (true) { + case $customFunctionDeclaration !== null: + return $customFunctionDeclaration; + + case (isset(self::$_STRING_FUNCTIONS[$funcName])): + return $this->FunctionsReturningStrings(); + + case (isset(self::$_NUMERIC_FUNCTIONS[$funcName])): + return $this->FunctionsReturningNumerics(); + + case (isset(self::$_DATETIME_FUNCTIONS[$funcName])): + return $this->FunctionsReturningDatetime(); + + default: + $this->syntaxError('known function', $token); + } + } + + /** + * Helper function for FunctionDeclaration grammar rule. + * + * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode + */ + private function CustomFunctionDeclaration() + { + $token = $this->lexer->lookahead; + $funcName = strtolower($token['value']); + + // Check for custom functions afterwards + $config = $this->em->getConfiguration(); + + switch (true) { + case ($config->getCustomStringFunction($funcName) !== null): + return $this->CustomFunctionsReturningStrings(); + + case ($config->getCustomNumericFunction($funcName) !== null): + return $this->CustomFunctionsReturningNumerics(); + + case ($config->getCustomDatetimeFunction($funcName) !== null): + return $this->CustomFunctionsReturningDatetime(); + + default: + return null; + } + } + + /** + * FunctionsReturningNumerics ::= + * "LENGTH" "(" StringPrimary ")" | + * "LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" | + * "ABS" "(" SimpleArithmeticExpression ")" | + * "SQRT" "(" SimpleArithmeticExpression ")" | + * "MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" | + * "SIZE" "(" CollectionValuedPathExpression ")" | + * "DATE_DIFF" "(" ArithmeticPrimary "," ArithmeticPrimary ")" | + * "BIT_AND" "(" ArithmeticPrimary "," ArithmeticPrimary ")" | + * "BIT_OR" "(" ArithmeticPrimary "," ArithmeticPrimary ")" + * + * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode + */ + public function FunctionsReturningNumerics() + { + $funcNameLower = strtolower($this->lexer->lookahead['value']); + $funcClass = self::$_NUMERIC_FUNCTIONS[$funcNameLower]; + + $function = new $funcClass($funcNameLower); + $function->parse($this); + + return $function; + } + + /** + * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode + */ + public function CustomFunctionsReturningNumerics() + { + // getCustomNumericFunction is case-insensitive + $functionName = strtolower($this->lexer->lookahead['value']); + $functionClass = $this->em->getConfiguration()->getCustomNumericFunction($functionName); + + $function = is_string($functionClass) + ? new $functionClass($functionName) + : call_user_func($functionClass, $functionName); + + $function->parse($this); + + return $function; + } + + /** + * FunctionsReturningDateTime ::= + * "CURRENT_DATE" | + * "CURRENT_TIME" | + * "CURRENT_TIMESTAMP" | + * "DATE_ADD" "(" ArithmeticPrimary "," ArithmeticPrimary "," StringPrimary ")" | + * "DATE_SUB" "(" ArithmeticPrimary "," ArithmeticPrimary "," StringPrimary ")" + * + * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode + */ + public function FunctionsReturningDatetime() + { + $funcNameLower = strtolower($this->lexer->lookahead['value']); + $funcClass = self::$_DATETIME_FUNCTIONS[$funcNameLower]; + + $function = new $funcClass($funcNameLower); + $function->parse($this); + + return $function; + } + + /** + * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode + */ + public function CustomFunctionsReturningDatetime() + { + // getCustomDatetimeFunction is case-insensitive + $functionName = $this->lexer->lookahead['value']; + $functionClass = $this->em->getConfiguration()->getCustomDatetimeFunction($functionName); + + $function = is_string($functionClass) + ? new $functionClass($functionName) + : call_user_func($functionClass, $functionName); + + $function->parse($this); + + return $function; + } + + /** + * FunctionsReturningStrings ::= + * "CONCAT" "(" StringPrimary "," StringPrimary {"," StringPrimary}* ")" | + * "SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")" | + * "TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")" | + * "LOWER" "(" StringPrimary ")" | + * "UPPER" "(" StringPrimary ")" | + * "IDENTITY" "(" SingleValuedAssociationPathExpression {"," string} ")" + * + * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode + */ + public function FunctionsReturningStrings() + { + $funcNameLower = strtolower($this->lexer->lookahead['value']); + $funcClass = self::$_STRING_FUNCTIONS[$funcNameLower]; + + $function = new $funcClass($funcNameLower); + $function->parse($this); + + return $function; + } + + /** + * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode + */ + public function CustomFunctionsReturningStrings() + { + // getCustomStringFunction is case-insensitive + $functionName = $this->lexer->lookahead['value']; + $functionClass = $this->em->getConfiguration()->getCustomStringFunction($functionName); + + $function = is_string($functionClass) + ? new $functionClass($functionName) + : call_user_func($functionClass, $functionName); + + $function->parse($this); + + return $function; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParserResult.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParserResult.php new file mode 100644 index 0000000..84ad178 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParserResult.php @@ -0,0 +1,145 @@ +. + */ + +namespace Doctrine\ORM\Query; + +/** + * Encapsulates the resulting components from a DQL query parsing process that + * can be serialized. + * + * @author Guilherme Blanco + * @author Janne Vanhala + * @author Roman Borschel + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://www.doctrine-project.org + * @since 2.0 + */ +class ParserResult +{ + /** + * The SQL executor used for executing the SQL. + * + * @var \Doctrine\ORM\Query\Exec\AbstractSqlExecutor + */ + private $_sqlExecutor; + + /** + * The ResultSetMapping that describes how to map the SQL result set. + * + * @var \Doctrine\ORM\Query\ResultSetMapping + */ + private $_resultSetMapping; + + /** + * The mappings of DQL parameter names/positions to SQL parameter positions. + * + * @var array + */ + private $_parameterMappings = []; + + /** + * Initializes a new instance of the ParserResult class. + * The new instance is initialized with an empty ResultSetMapping. + */ + public function __construct() + { + $this->_resultSetMapping = new ResultSetMapping; + } + + /** + * Gets the ResultSetMapping for the parsed query. + * + * @return ResultSetMapping|null The result set mapping of the parsed query or NULL + * if the query is not a SELECT query. + */ + public function getResultSetMapping() + { + return $this->_resultSetMapping; + } + + /** + * Sets the ResultSetMapping of the parsed query. + * + * @param ResultSetMapping $rsm + * + * @return void + */ + public function setResultSetMapping(ResultSetMapping $rsm) + { + $this->_resultSetMapping = $rsm; + } + + /** + * Sets the SQL executor that should be used for this ParserResult. + * + * @param \Doctrine\ORM\Query\Exec\AbstractSqlExecutor $executor + * + * @return void + */ + public function setSqlExecutor($executor) + { + $this->_sqlExecutor = $executor; + } + + /** + * Gets the SQL executor used by this ParserResult. + * + * @return \Doctrine\ORM\Query\Exec\AbstractSqlExecutor + */ + public function getSqlExecutor() + { + return $this->_sqlExecutor; + } + + /** + * Adds a DQL to SQL parameter mapping. One DQL parameter name/position can map to + * several SQL parameter positions. + * + * @param string|integer $dqlPosition + * @param integer $sqlPosition + * + * @return void + */ + public function addParameterMapping($dqlPosition, $sqlPosition) + { + $this->_parameterMappings[$dqlPosition][] = $sqlPosition; + } + + /** + * Gets all DQL to SQL parameter mappings. + * + * @return array The parameter mappings. + */ + public function getParameterMappings() + { + return $this->_parameterMappings; + } + + /** + * Gets the SQL parameter positions for a DQL parameter name/position. + * + * @param string|integer $dqlPosition The name or position of the DQL parameter. + * + * @return array The positions of the corresponding SQL parameters. + */ + public function getSqlParameterPositions($dqlPosition) + { + return $this->_parameterMappings[$dqlPosition]; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Printer.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Printer.php new file mode 100644 index 0000000..d92ad85 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Printer.php @@ -0,0 +1,98 @@ +. + */ + +namespace Doctrine\ORM\Query; + +/** + * A parse tree printer for Doctrine Query Language parser. + * + * @author Janne Vanhala + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://www.phpdoctrine.org + * @since 2.0 + */ +class Printer +{ + /** + * Current indentation level + * + * @var int + */ + protected $_indent = 0; + + /** + * Defines whether parse tree is printed (default, false) or not (true). + * + * @var bool + */ + protected $_silent; + + /** + * Constructs a new parse tree printer. + * + * @param bool $silent Parse tree will not be printed if true. + */ + public function __construct($silent = false) + { + $this->_silent = $silent; + } + + /** + * Prints an opening parenthesis followed by production name and increases + * indentation level by one. + * + * This method is called before executing a production. + * + * @param string $name Production name. + * + * @return void + */ + public function startProduction($name) + { + $this->println('(' . $name); + $this->_indent++; + } + + /** + * Decreases indentation level by one and prints a closing parenthesis. + * + * This method is called after executing a production. + * + * @return void + */ + public function endProduction() + { + $this->_indent--; + $this->println(')'); + } + + /** + * Prints text indented with spaces depending on current indentation level. + * + * @param string $str The text. + * + * @return void + */ + public function println($str) + { + if ( ! $this->_silent) { + echo str_repeat(' ', $this->_indent), $str, "\n"; + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php new file mode 100644 index 0000000..b78e27b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php @@ -0,0 +1,270 @@ +. + */ + +namespace Doctrine\ORM\Query; + +use Doctrine\ORM\Query\AST\PathExpression; + +/** + * Description of QueryException. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + */ +class QueryException extends \Doctrine\ORM\ORMException +{ + /** + * @param string $dql + * + * @return QueryException + */ + public static function dqlError($dql) + { + return new self($dql); + } + + /** + * @param string $message + * @param \Exception|null $previous + * + * @return QueryException + */ + public static function syntaxError($message, $previous = null) + { + return new self('[Syntax Error] ' . $message, 0, $previous); + } + + /** + * @param string $message + * @param \Exception|null $previous + * + * @return QueryException + */ + public static function semanticalError($message, $previous = null) + { + return new self('[Semantical Error] ' . $message, 0, $previous); + } + + /** + * @return QueryException + */ + public static function invalidLockMode() + { + return new self('Invalid lock mode hint provided.'); + } + + /** + * @param string $expected + * @param string $received + * + * @return QueryException + */ + public static function invalidParameterType($expected, $received) + { + return new self('Invalid parameter type, ' . $received . ' given, but ' . $expected . ' expected.'); + } + + /** + * @param string $pos + * + * @return QueryException + */ + public static function invalidParameterPosition($pos) + { + return new self('Invalid parameter position: ' . $pos); + } + + /** + * @param integer $expected + * @param integer $received + * + * @return QueryException + */ + public static function tooManyParameters($expected, $received) + { + return new self('Too many parameters: the query defines ' . $expected . ' parameters and you bound ' . $received); + } + + /** + * @param integer $expected + * @param integer $received + * + * @return QueryException + */ + public static function tooFewParameters($expected, $received) + { + return new self('Too few parameters: the query defines ' . $expected . ' parameters but you only bound ' . $received); + } + + /** + * @param string $value + * + * @return QueryException + */ + public static function invalidParameterFormat($value) + { + return new self('Invalid parameter format, '.$value.' given, but : or ? expected.'); + } + + /** + * @param string $key + * + * @return QueryException + */ + public static function unknownParameter($key) + { + return new self("Invalid parameter: token ".$key." is not defined in the query."); + } + + /** + * @return QueryException + */ + public static function parameterTypeMismatch() + { + return new self("DQL Query parameter and type numbers mismatch, but have to be exactly equal."); + } + + /** + * @param object $pathExpr + * + * @return QueryException + */ + public static function invalidPathExpression($pathExpr) + { + return new self( + "Invalid PathExpression '" . $pathExpr->identificationVariable . "." . $pathExpr->field . "'." + ); + } + + /** + * @param string $literal + * + * @return QueryException + */ + public static function invalidLiteral($literal) + { + return new self("Invalid literal '$literal'"); + } + + /** + * @param array $assoc + * + * @return QueryException + */ + public static function iterateWithFetchJoinCollectionNotAllowed($assoc) + { + return new self( + "Invalid query operation: Not allowed to iterate over fetch join collections ". + "in class ".$assoc['sourceEntity']." association ".$assoc['fieldName'] + ); + } + + /** + * @return QueryException + */ + public static function partialObjectsAreDangerous() + { + return new self( + "Loading partial objects is dangerous. Fetch full objects or consider " . + "using a different fetch mode. If you really want partial objects, " . + "set the doctrine.forcePartialLoad query hint to TRUE." + ); + } + + /** + * @param array $assoc + * + * @return QueryException + */ + public static function overwritingJoinConditionsNotYetSupported($assoc) + { + return new self( + "Unsupported query operation: It is not yet possible to overwrite the join ". + "conditions in class ".$assoc['sourceEntityName']." association ".$assoc['fieldName'].". ". + "Use WITH to append additional join conditions to the association." + ); + } + + /** + * @param PathExpression $pathExpr + * + * @return QueryException + */ + public static function associationPathInverseSideNotSupported(PathExpression $pathExpr) + { + return new self( + 'A single-valued association path expression to an inverse side is not supported in DQL queries. ' . + 'Instead of "' . $pathExpr->identificationVariable . '.' . $pathExpr->field . '" use an explicit join.' + ); + } + + /** + * @param array $assoc + * + * @return QueryException + */ + public static function iterateWithFetchJoinNotAllowed($assoc) + { + return new self( + "Iterate with fetch join in class " . $assoc['sourceEntity'] . + " using association " . $assoc['fieldName'] . " not allowed." + ); + } + + /** + * @return QueryException + */ + public static function associationPathCompositeKeyNotSupported() + { + return new self( + "A single-valued association path expression to an entity with a composite primary ". + "key is not supported. Explicitly name the components of the composite primary key ". + "in the query." + ); + } + + /** + * @param string $className + * @param string $rootClass + * + * @return QueryException + */ + public static function instanceOfUnrelatedClass($className, $rootClass) + { + return new self("Cannot check if a child of '" . $rootClass . "' is instanceof '" . $className . "', " . + "inheritance hierarchy does not exists between these two classes."); + } + + /** + * @param string $dqlAlias + * + * @return QueryException + */ + public static function invalidQueryComponent($dqlAlias) + { + return new self( + "Invalid query component given for DQL alias '" . $dqlAlias . "', ". + "requires 'metadata', 'parent', 'relation', 'map', 'nestingLevel' and 'token' keys." + ); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryExpressionVisitor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryExpressionVisitor.php new file mode 100644 index 0000000..0381ac0 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryExpressionVisitor.php @@ -0,0 +1,224 @@ +. + */ + +namespace Doctrine\ORM\Query; + +use Doctrine\Common\Collections\ArrayCollection; + +use Doctrine\Common\Collections\Expr\ExpressionVisitor; +use Doctrine\Common\Collections\Expr\Comparison; +use Doctrine\Common\Collections\Expr\CompositeExpression; +use Doctrine\Common\Collections\Expr\Value; + +/** + * Converts Collection expressions to Query expressions. + * + * @author Kirill chEbba Chebunin + * @since 2.4 + */ +class QueryExpressionVisitor extends ExpressionVisitor +{ + /** + * @var array + */ + private static $operatorMap = [ + Comparison::GT => Expr\Comparison::GT, + Comparison::GTE => Expr\Comparison::GTE, + Comparison::LT => Expr\Comparison::LT, + Comparison::LTE => Expr\Comparison::LTE + ]; + + /** + * @var array + */ + private $queryAliases; + + /** + * @var Expr + */ + private $expr; + + /** + * @var array + */ + private $parameters = []; + + /** + * Constructor + * + * @param array $queryAliases + */ + public function __construct($queryAliases) + { + $this->queryAliases = $queryAliases; + $this->expr = new Expr(); + } + + /** + * Gets bound parameters. + * Filled after {@link dispach()}. + * + * @return \Doctrine\Common\Collections\Collection + */ + public function getParameters() + { + return new ArrayCollection($this->parameters); + } + + /** + * Clears parameters. + * + * @return void + */ + public function clearParameters() + { + $this->parameters = []; + } + + /** + * Converts Criteria expression to Query one based on static map. + * + * @param string $criteriaOperator + * + * @return string|null + */ + private static function convertComparisonOperator($criteriaOperator) + { + return isset(self::$operatorMap[$criteriaOperator]) ? self::$operatorMap[$criteriaOperator] : null; + } + + /** + * {@inheritDoc} + */ + public function walkCompositeExpression(CompositeExpression $expr) + { + $expressionList = []; + + foreach ($expr->getExpressionList() as $child) { + $expressionList[] = $this->dispatch($child); + } + + switch($expr->getType()) { + case CompositeExpression::TYPE_AND: + return new Expr\Andx($expressionList); + + case CompositeExpression::TYPE_OR: + return new Expr\Orx($expressionList); + + default: + throw new \RuntimeException("Unknown composite " . $expr->getType()); + } + } + + /** + * {@inheritDoc} + */ + public function walkComparison(Comparison $comparison) + { + + if ( ! isset($this->queryAliases[0])) { + throw new QueryException('No aliases are set before invoking walkComparison().'); + } + + $field = $this->queryAliases[0] . '.' . $comparison->getField(); + + foreach($this->queryAliases as $alias) { + if(strpos($comparison->getField() . '.', $alias . '.') === 0) { + $field = $comparison->getField(); + break; + } + } + + $parameterName = str_replace('.', '_', $comparison->getField()); + + foreach ($this->parameters as $parameter) { + if ($parameter->getName() === $parameterName) { + $parameterName .= '_' . count($this->parameters); + break; + } + } + + $parameter = new Parameter($parameterName, $this->walkValue($comparison->getValue())); + $placeholder = ':' . $parameterName; + + switch ($comparison->getOperator()) { + case Comparison::IN: + $this->parameters[] = $parameter; + + return $this->expr->in($field, $placeholder); + case Comparison::NIN: + $this->parameters[] = $parameter; + + return $this->expr->notIn($field, $placeholder); + case Comparison::EQ: + case Comparison::IS: + if ($this->walkValue($comparison->getValue()) === null) { + return $this->expr->isNull($field); + } + $this->parameters[] = $parameter; + + return $this->expr->eq($field, $placeholder); + case Comparison::NEQ: + if ($this->walkValue($comparison->getValue()) === null) { + return $this->expr->isNotNull($field); + } + $this->parameters[] = $parameter; + + return $this->expr->neq($field, $placeholder); + case Comparison::CONTAINS: + $parameter->setValue('%' . $parameter->getValue() . '%', $parameter->getType()); + $this->parameters[] = $parameter; + + return $this->expr->like($field, $placeholder); + case Comparison::MEMBER_OF: + return $this->expr->isMemberOf($comparison->getField(), $comparison->getValue()->getValue()); + case Comparison::STARTS_WITH: + $parameter->setValue($parameter->getValue() . '%', $parameter->getType()); + $this->parameters[] = $parameter; + + return $this->expr->like($field, $placeholder); + case Comparison::ENDS_WITH: + $parameter->setValue('%' . $parameter->getValue(), $parameter->getType()); + $this->parameters[] = $parameter; + + return $this->expr->like($field, $placeholder); + default: + $operator = self::convertComparisonOperator($comparison->getOperator()); + if ($operator) { + $this->parameters[] = $parameter; + + return new Expr\Comparison( + $field, + $operator, + $placeholder + ); + } + + throw new \RuntimeException("Unknown comparison operator: " . $comparison->getOperator()); + } + } + + /** + * {@inheritDoc} + */ + public function walkValue(Value $value) + { + return $value->getValue(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMapping.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMapping.php new file mode 100644 index 0000000..640b8e6 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMapping.php @@ -0,0 +1,586 @@ +. + */ + +namespace Doctrine\ORM\Query; + +/** + * A ResultSetMapping describes how a result set of an SQL query maps to a Doctrine result. + * + * IMPORTANT NOTE: + * The properties of this class are only public for fast internal READ access and to (drastically) + * reduce the size of serialized instances for more effective caching due to better (un-)serialization + * performance. + * + * Users should use the public methods. + * + * @author Roman Borschel + * @since 2.0 + * @todo Think about whether the number of lookup maps can be reduced. + */ +class ResultSetMapping +{ + /** + * Whether the result is mixed (contains scalar values together with field values). + * + * @ignore + * @var boolean + */ + public $isMixed = false; + + /** + * Whether the result is a select statement. + * + * @ignore + * @var boolean + */ + public $isSelect = true; + + /** + * Maps alias names to class names. + * + * @ignore + * @var array + */ + public $aliasMap = []; + + /** + * Maps alias names to related association field names. + * + * @ignore + * @var array + */ + public $relationMap = []; + + /** + * Maps alias names to parent alias names. + * + * @ignore + * @var array + */ + public $parentAliasMap = []; + + /** + * Maps column names in the result set to field names for each class. + * + * @ignore + * @var array + */ + public $fieldMappings = []; + + /** + * Maps column names in the result set to the alias/field name to use in the mapped result. + * + * @ignore + * @var array + */ + public $scalarMappings = []; + + /** + * Maps column names in the result set to the alias/field type to use in the mapped result. + * + * @ignore + * @var array + */ + public $typeMappings = []; + + /** + * Maps entities in the result set to the alias name to use in the mapped result. + * + * @ignore + * @var array + */ + public $entityMappings = []; + + /** + * Maps column names of meta columns (foreign keys, discriminator columns, ...) to field names. + * + * @ignore + * @var array + */ + public $metaMappings = []; + + /** + * Maps column names in the result set to the alias they belong to. + * + * @ignore + * @var array + */ + public $columnOwnerMap = []; + + /** + * List of columns in the result set that are used as discriminator columns. + * + * @ignore + * @var array + */ + public $discriminatorColumns = []; + + /** + * Maps alias names to field names that should be used for indexing. + * + * @ignore + * @var array + */ + public $indexByMap = []; + + /** + * Map from column names to class names that declare the field the column is mapped to. + * + * @ignore + * @var array + */ + public $declaringClasses = []; + + /** + * This is necessary to hydrate derivate foreign keys correctly. + * + * @var array + */ + public $isIdentifierColumn = []; + + /** + * Maps column names in the result set to field names for each new object expression. + * + * @var array + */ + public $newObjectMappings = []; + + /** + * Maps metadata parameter names to the metadata attribute. + * + * @var array + */ + public $metadataParameterMapping = []; + + /** + * Contains query parameter names to be resolved as discriminator values + * + * @var array + */ + public $discriminatorParameters = []; + + /** + * Adds an entity result to this ResultSetMapping. + * + * @param string $class The class name of the entity. + * @param string $alias The alias for the class. The alias must be unique among all entity + * results or joined entity results within this ResultSetMapping. + * @param string|null $resultAlias The result alias with which the entity result should be + * placed in the result structure. + * + * @return ResultSetMapping This ResultSetMapping instance. + * + * @todo Rename: addRootEntity + */ + public function addEntityResult($class, $alias, $resultAlias = null) + { + $this->aliasMap[$alias] = $class; + $this->entityMappings[$alias] = $resultAlias; + + if ($resultAlias !== null) { + $this->isMixed = true; + } + + return $this; + } + + /** + * Sets a discriminator column for an entity result or joined entity result. + * The discriminator column will be used to determine the concrete class name to + * instantiate. + * + * @param string $alias The alias of the entity result or joined entity result the discriminator + * column should be used for. + * @param string $discrColumn The name of the discriminator column in the SQL result set. + * + * @return ResultSetMapping This ResultSetMapping instance. + * + * @todo Rename: addDiscriminatorColumn + */ + public function setDiscriminatorColumn($alias, $discrColumn) + { + $this->discriminatorColumns[$alias] = $discrColumn; + $this->columnOwnerMap[$discrColumn] = $alias; + + return $this; + } + + /** + * Sets a field to use for indexing an entity result or joined entity result. + * + * @param string $alias The alias of an entity result or joined entity result. + * @param string $fieldName The name of the field to use for indexing. + * + * @return ResultSetMapping This ResultSetMapping instance. + */ + public function addIndexBy($alias, $fieldName) + { + $found = false; + + foreach (array_merge($this->metaMappings, $this->fieldMappings) as $columnName => $columnFieldName) { + if ( ! ($columnFieldName === $fieldName && $this->columnOwnerMap[$columnName] === $alias)) continue; + + $this->addIndexByColumn($alias, $columnName); + $found = true; + + break; + } + + /* TODO: check if this exception can be put back, for now it's gone because of assumptions made by some ORM internals + if ( ! $found) { + $message = sprintf( + 'Cannot add index by for DQL alias %s and field %s without calling addFieldResult() for them before.', + $alias, + $fieldName + ); + + throw new \LogicException($message); + } + */ + + return $this; + } + + /** + * Sets to index by a scalar result column name. + * + * @param string $resultColumnName + * + * @return ResultSetMapping This ResultSetMapping instance. + */ + public function addIndexByScalar($resultColumnName) + { + $this->indexByMap['scalars'] = $resultColumnName; + + return $this; + } + + /** + * Sets a column to use for indexing an entity or joined entity result by the given alias name. + * + * @param string $alias + * @param string $resultColumnName + * + * @return ResultSetMapping This ResultSetMapping instance. + */ + public function addIndexByColumn($alias, $resultColumnName) + { + $this->indexByMap[$alias] = $resultColumnName; + + return $this; + } + + /** + * Checks whether an entity result or joined entity result with a given alias has + * a field set for indexing. + * + * @param string $alias + * + * @return boolean + * + * @todo Rename: isIndexed($alias) + */ + public function hasIndexBy($alias) + { + return isset($this->indexByMap[$alias]); + } + + /** + * Checks whether the column with the given name is mapped as a field result + * as part of an entity result or joined entity result. + * + * @param string $columnName The name of the column in the SQL result set. + * + * @return boolean + * + * @todo Rename: isField + */ + public function isFieldResult($columnName) + { + return isset($this->fieldMappings[$columnName]); + } + + /** + * Adds a field to the result that belongs to an entity or joined entity. + * + * @param string $alias The alias of the root entity or joined entity to which the field belongs. + * @param string $columnName The name of the column in the SQL result set. + * @param string $fieldName The name of the field on the declaring class. + * @param string|null $declaringClass The name of the class that declares/owns the specified field. + * When $alias refers to a superclass in a mapped hierarchy but + * the field $fieldName is defined on a subclass, specify that here. + * If not specified, the field is assumed to belong to the class + * designated by $alias. + * + * @return ResultSetMapping This ResultSetMapping instance. + * + * @todo Rename: addField + */ + public function addFieldResult($alias, $columnName, $fieldName, $declaringClass = null) + { + // column name (in result set) => field name + $this->fieldMappings[$columnName] = $fieldName; + // column name => alias of owner + $this->columnOwnerMap[$columnName] = $alias; + // field name => class name of declaring class + $this->declaringClasses[$columnName] = $declaringClass ?: $this->aliasMap[$alias]; + + if ( ! $this->isMixed && $this->scalarMappings) { + $this->isMixed = true; + } + + return $this; + } + + /** + * Adds a joined entity result. + * + * @param string $class The class name of the joined entity. + * @param string $alias The unique alias to use for the joined entity. + * @param string $parentAlias The alias of the entity result that is the parent of this joined result. + * @param string $relation The association field that connects the parent entity result + * with the joined entity result. + * + * @return ResultSetMapping This ResultSetMapping instance. + * + * @todo Rename: addJoinedEntity + */ + public function addJoinedEntityResult($class, $alias, $parentAlias, $relation) + { + $this->aliasMap[$alias] = $class; + $this->parentAliasMap[$alias] = $parentAlias; + $this->relationMap[$alias] = $relation; + + return $this; + } + + /** + * Adds a scalar result mapping. + * + * @param string $columnName The name of the column in the SQL result set. + * @param string $alias The result alias with which the scalar result should be placed in the result structure. + * @param string $type The column type + * + * @return ResultSetMapping This ResultSetMapping instance. + * + * @todo Rename: addScalar + */ + public function addScalarResult($columnName, $alias, $type = 'string') + { + $this->scalarMappings[$columnName] = $alias; + $this->typeMappings[$columnName] = $type; + + if ( ! $this->isMixed && $this->fieldMappings) { + $this->isMixed = true; + } + + return $this; + } + + /** + * Adds a metadata parameter mappings. + * + * @param mixed $parameter The parameter name in the SQL result set. + * @param string $attribute The metadata attribute. + */ + public function addMetadataParameterMapping($parameter, $attribute) + { + $this->metadataParameterMapping[$parameter] = $attribute; + } + + /** + * Checks whether a column with a given name is mapped as a scalar result. + * + * @param string $columnName The name of the column in the SQL result set. + * + * @return boolean + * + * @todo Rename: isScalar + */ + public function isScalarResult($columnName) + { + return isset($this->scalarMappings[$columnName]); + } + + /** + * Gets the name of the class of an entity result or joined entity result, + * identified by the given unique alias. + * + * @param string $alias + * + * @return string + */ + public function getClassName($alias) + { + return $this->aliasMap[$alias]; + } + + /** + * Gets the field alias for a column that is mapped as a scalar value. + * + * @param string $columnName The name of the column in the SQL result set. + * + * @return string + */ + public function getScalarAlias($columnName) + { + return $this->scalarMappings[$columnName]; + } + + /** + * Gets the name of the class that owns a field mapping for the specified column. + * + * @param string $columnName + * + * @return string + */ + public function getDeclaringClass($columnName) + { + return $this->declaringClasses[$columnName]; + } + + /** + * @param string $alias + * + * @return string + */ + public function getRelation($alias) + { + return $this->relationMap[$alias]; + } + + /** + * @param string $alias + * + * @return boolean + */ + public function isRelation($alias) + { + return isset($this->relationMap[$alias]); + } + + /** + * Gets the alias of the class that owns a field mapping for the specified column. + * + * @param string $columnName + * + * @return string + */ + public function getEntityAlias($columnName) + { + return $this->columnOwnerMap[$columnName]; + } + + /** + * Gets the parent alias of the given alias. + * + * @param string $alias + * + * @return string + */ + public function getParentAlias($alias) + { + return $this->parentAliasMap[$alias]; + } + + /** + * Checks whether the given alias has a parent alias. + * + * @param string $alias + * + * @return boolean + */ + public function hasParentAlias($alias) + { + return isset($this->parentAliasMap[$alias]); + } + + /** + * Gets the field name for a column name. + * + * @param string $columnName + * + * @return string + */ + public function getFieldName($columnName) + { + return $this->fieldMappings[$columnName]; + } + + /** + * @return array + */ + public function getAliasMap() + { + return $this->aliasMap; + } + + /** + * Gets the number of different entities that appear in the mapped result. + * + * @return integer + */ + public function getEntityResultCount() + { + return count($this->aliasMap); + } + + /** + * Checks whether this ResultSetMapping defines a mixed result. + * + * Mixed results can only occur in object and array (graph) hydration. In such a + * case a mixed result means that scalar values are mixed with objects/array in + * the result. + * + * @return boolean + */ + public function isMixedResult() + { + return $this->isMixed; + } + + /** + * Adds a meta column (foreign key or discriminator column) to the result set. + * + * @param string $alias The result alias with which the meta result should be placed in the result structure. + * @param string $columnName The name of the column in the SQL result set. + * @param string $fieldName The name of the field on the declaring class. + * @param bool $isIdentifierColumn + * @param string $type The column type + * + * @return ResultSetMapping This ResultSetMapping instance. + * + * @todo Make all methods of this class require all parameters and not infer anything + */ + public function addMetaResult($alias, $columnName, $fieldName, $isIdentifierColumn = false, $type = null) + { + $this->metaMappings[$columnName] = $fieldName; + $this->columnOwnerMap[$columnName] = $alias; + + if ($isIdentifierColumn) { + $this->isIdentifierColumn[$alias][$columnName] = true; + } + + if ($type) { + $this->typeMappings[$columnName] = $type; + } + + return $this; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php new file mode 100644 index 0000000..0bf1181 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php @@ -0,0 +1,473 @@ +. + */ + +namespace Doctrine\ORM\Query; + +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Doctrine\ORM\Mapping\MappingException; +use Doctrine\ORM\Utility\PersisterHelper; + +/** + * A ResultSetMappingBuilder uses the EntityManager to automatically populate entity fields. + * + * @author Michael Ridgway + * @since 2.1 + */ +class ResultSetMappingBuilder extends ResultSetMapping +{ + /** + * Picking this rename mode will register entity columns as is, + * as they are in the database. This can cause clashes when multiple + * entities are fetched that have columns with the same name. + * + * @var int + */ + const COLUMN_RENAMING_NONE = 1; + + /** + * Picking custom renaming allows the user to define the renaming + * of specific columns with a rename array that contains column names as + * keys and result alias as values. + * + * @var int + */ + const COLUMN_RENAMING_CUSTOM = 2; + + /** + * Incremental renaming uses a result set mapping internal counter to add a + * number to each column result, leading to uniqueness. This only works if + * you use {@see generateSelectClause()} to generate the SELECT clause for + * you. + * + * @var int + */ + const COLUMN_RENAMING_INCREMENT = 3; + + /** + * @var int + */ + private $sqlCounter = 0; + + /** + * @var EntityManagerInterface + */ + private $em; + + /** + * Default column renaming mode. + * + * @var int + */ + private $defaultRenameMode; + + /** + * @param EntityManagerInterface $em + * @param integer $defaultRenameMode + */ + public function __construct(EntityManagerInterface $em, $defaultRenameMode = self::COLUMN_RENAMING_NONE) + { + $this->em = $em; + $this->defaultRenameMode = $defaultRenameMode; + } + + /** + * Adds a root entity and all of its fields to the result set. + * + * @param string $class The class name of the root entity. + * @param string $alias The unique alias to use for the root entity. + * @param array $renamedColumns Columns that have been renamed (tableColumnName => queryColumnName). + * @param int|null $renameMode One of the COLUMN_RENAMING_* constants or array for BC reasons (CUSTOM). + * + * @return void + */ + public function addRootEntityFromClassMetadata($class, $alias, $renamedColumns = [], $renameMode = null) + { + $renameMode = $renameMode ?: $this->defaultRenameMode; + $columnAliasMap = $this->getColumnAliasMap($class, $renameMode, $renamedColumns); + + $this->addEntityResult($class, $alias); + $this->addAllClassFields($class, $alias, $columnAliasMap); + } + + /** + * Adds a joined entity and all of its fields to the result set. + * + * @param string $class The class name of the joined entity. + * @param string $alias The unique alias to use for the joined entity. + * @param string $parentAlias The alias of the entity result that is the parent of this joined result. + * @param string $relation The association field that connects the parent entity result + * with the joined entity result. + * @param array $renamedColumns Columns that have been renamed (tableColumnName => queryColumnName). + * @param int|null $renameMode One of the COLUMN_RENAMING_* constants or array for BC reasons (CUSTOM). + * + * @return void + */ + public function addJoinedEntityFromClassMetadata($class, $alias, $parentAlias, $relation, $renamedColumns = [], $renameMode = null) + { + $renameMode = $renameMode ?: $this->defaultRenameMode; + $columnAliasMap = $this->getColumnAliasMap($class, $renameMode, $renamedColumns); + + $this->addJoinedEntityResult($class, $alias, $parentAlias, $relation); + $this->addAllClassFields($class, $alias, $columnAliasMap); + } + + /** + * Adds all fields of the given class to the result set mapping (columns and meta fields). + * + * @param string $class + * @param string $alias + * @param array $columnAliasMap + * + * @return void + * + * @throws \InvalidArgumentException + */ + protected function addAllClassFields($class, $alias, $columnAliasMap = []) + { + $classMetadata = $this->em->getClassMetadata($class); + $platform = $this->em->getConnection()->getDatabasePlatform(); + + if ( ! $this->isInheritanceSupported($classMetadata)) { + throw new \InvalidArgumentException('ResultSetMapping builder does not currently support your inheritance scheme.'); + } + + + foreach ($classMetadata->getColumnNames() as $columnName) { + $propertyName = $classMetadata->getFieldName($columnName); + $columnAlias = $platform->getSQLResultCasing($columnAliasMap[$columnName]); + + if (isset($this->fieldMappings[$columnAlias])) { + throw new \InvalidArgumentException("The column '$columnName' conflicts with another column in the mapper."); + } + + $this->addFieldResult($alias, $columnAlias, $propertyName); + } + + foreach ($classMetadata->associationMappings as $associationMapping) { + if ($associationMapping['isOwningSide'] && $associationMapping['type'] & ClassMetadataInfo::TO_ONE) { + $targetClass = $this->em->getClassMetadata($associationMapping['targetEntity']); + $isIdentifier = isset($associationMapping['id']) && $associationMapping['id'] === true; + + foreach ($associationMapping['joinColumns'] as $joinColumn) { + $columnName = $joinColumn['name']; + $columnAlias = $platform->getSQLResultCasing($columnAliasMap[$columnName]); + $columnType = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); + + if (isset($this->metaMappings[$columnAlias])) { + throw new \InvalidArgumentException("The column '$columnAlias' conflicts with another column in the mapper."); + } + + $this->addMetaResult($alias, $columnAlias, $columnName, $isIdentifier, $columnType); + } + } + } + } + + private function isInheritanceSupported(ClassMetadataInfo $classMetadata) + { + if ($classMetadata->isInheritanceTypeSingleTable() + && in_array($classMetadata->name, $classMetadata->discriminatorMap, true)) { + return true; + } + + return ! ($classMetadata->isInheritanceTypeSingleTable() || $classMetadata->isInheritanceTypeJoined()); + } + + /** + * Gets column alias for a given column. + * + * @param string $columnName + * @param int $mode + * @param array $customRenameColumns + * + * @return string + */ + private function getColumnAlias($columnName, $mode, array $customRenameColumns) + { + switch ($mode) { + case self::COLUMN_RENAMING_INCREMENT: + return $columnName . $this->sqlCounter++; + + case self::COLUMN_RENAMING_CUSTOM: + return $customRenameColumns[$columnName] ?? $columnName; + + case self::COLUMN_RENAMING_NONE: + return $columnName; + + } + } + + /** + * Retrieves a class columns and join columns aliases that are used in the SELECT clause. + * + * This depends on the renaming mode selected by the user. + * + * @param string $className + * @param int $mode + * @param array $customRenameColumns + * + * @return array + */ + private function getColumnAliasMap($className, $mode, array $customRenameColumns) + { + if ($customRenameColumns) { // for BC with 2.2-2.3 API + $mode = self::COLUMN_RENAMING_CUSTOM; + } + + $columnAlias = []; + $class = $this->em->getClassMetadata($className); + + foreach ($class->getColumnNames() as $columnName) { + $columnAlias[$columnName] = $this->getColumnAlias($columnName, $mode, $customRenameColumns); + } + + foreach ($class->associationMappings as $associationMapping) { + if ($associationMapping['isOwningSide'] && $associationMapping['type'] & ClassMetadataInfo::TO_ONE) { + foreach ($associationMapping['joinColumns'] as $joinColumn) { + $columnName = $joinColumn['name']; + $columnAlias[$columnName] = $this->getColumnAlias($columnName, $mode, $customRenameColumns); + } + } + } + + return $columnAlias; + } + + /** + * Adds the mappings of the results of native SQL queries to the result set. + * + * @param ClassMetadataInfo $class + * @param array $queryMapping + * + * @return ResultSetMappingBuilder + */ + public function addNamedNativeQueryMapping(ClassMetadataInfo $class, array $queryMapping) + { + if (isset($queryMapping['resultClass'])) { + return $this->addNamedNativeQueryResultClassMapping($class, $queryMapping['resultClass']); + } + + return $this->addNamedNativeQueryResultSetMapping($class, $queryMapping['resultSetMapping']); + } + + /** + * Adds the class mapping of the results of native SQL queries to the result set. + * + * @param ClassMetadataInfo $class + * @param string $resultClassName + * + * @return ResultSetMappingBuilder + */ + public function addNamedNativeQueryResultClassMapping(ClassMetadataInfo $class, $resultClassName) + { + $classMetadata = $this->em->getClassMetadata($resultClassName); + $shortName = $classMetadata->reflClass->getShortName(); + $alias = strtolower($shortName[0]).'0'; + + $this->addEntityResult($class->name, $alias); + + if ($classMetadata->discriminatorColumn) { + $discrColumn = $classMetadata->discriminatorColumn; + + $this->setDiscriminatorColumn($alias, $discrColumn['name']); + $this->addMetaResult($alias, $discrColumn['name'], $discrColumn['fieldName'], false, $discrColumn['type']); + } + + foreach ($classMetadata->getColumnNames() as $key => $columnName) { + $propertyName = $classMetadata->getFieldName($columnName); + + $this->addFieldResult($alias, $columnName, $propertyName); + } + + foreach ($classMetadata->associationMappings as $associationMapping) { + if ($associationMapping['isOwningSide'] && $associationMapping['type'] & ClassMetadataInfo::TO_ONE) { + $targetClass = $this->em->getClassMetadata($associationMapping['targetEntity']); + + foreach ($associationMapping['joinColumns'] as $joinColumn) { + $columnName = $joinColumn['name']; + $columnType = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); + + $this->addMetaResult($alias, $columnName, $columnName, $classMetadata->isIdentifier($columnName), $columnType); + } + } + } + + return $this; + } + + /** + * Adds the result set mapping of the results of native SQL queries to the result set. + * + * @param ClassMetadataInfo $class + * @param string $resultSetMappingName + * + * @return ResultSetMappingBuilder + */ + public function addNamedNativeQueryResultSetMapping(ClassMetadataInfo $class, $resultSetMappingName) + { + $counter = 0; + $resultMapping = $class->getSqlResultSetMapping($resultSetMappingName); + $rootShortName = $class->reflClass->getShortName(); + $rootAlias = strtolower($rootShortName[0]) . $counter; + + + if (isset($resultMapping['entities'])) { + foreach ($resultMapping['entities'] as $key => $entityMapping) { + $classMetadata = $this->em->getClassMetadata($entityMapping['entityClass']); + + if ($class->reflClass->name == $classMetadata->reflClass->name) { + $this->addEntityResult($classMetadata->name, $rootAlias); + $this->addNamedNativeQueryEntityResultMapping($classMetadata, $entityMapping, $rootAlias); + } else { + $shortName = $classMetadata->reflClass->getShortName(); + $joinAlias = strtolower($shortName[0]) . ++ $counter; + $associations = $class->getAssociationsByTargetClass($classMetadata->name); + + $this->addNamedNativeQueryEntityResultMapping($classMetadata, $entityMapping, $joinAlias); + + foreach ($associations as $relation => $mapping) { + $this->addJoinedEntityResult($mapping['targetEntity'], $joinAlias, $rootAlias, $relation); + } + } + + } + } + + if (isset($resultMapping['columns'])) { + foreach ($resultMapping['columns'] as $entityMapping) { + $type = isset($class->fieldNames[$entityMapping['name']]) + ? PersisterHelper::getTypeOfColumn($entityMapping['name'], $class, $this->em) + : 'string'; + + $this->addScalarResult($entityMapping['name'], $entityMapping['name'], $type); + } + } + + return $this; + } + + /** + * Adds the entity result mapping of the results of native SQL queries to the result set. + * + * @param ClassMetadataInfo $classMetadata + * @param array $entityMapping + * @param string $alias + * + * @return ResultSetMappingBuilder + * + * @throws MappingException + * @throws \InvalidArgumentException + */ + public function addNamedNativeQueryEntityResultMapping(ClassMetadataInfo $classMetadata, array $entityMapping, $alias) + { + if (isset($entityMapping['discriminatorColumn']) && $entityMapping['discriminatorColumn']) { + $discriminatorColumn = $entityMapping['discriminatorColumn']; + $discriminatorType = $classMetadata->discriminatorColumn['type']; + + $this->setDiscriminatorColumn($alias, $discriminatorColumn); + $this->addMetaResult($alias, $discriminatorColumn, $discriminatorColumn, false, $discriminatorType); + } + + if (isset($entityMapping['fields']) && !empty($entityMapping['fields'])) { + foreach ($entityMapping['fields'] as $field) { + $fieldName = $field['name']; + $relation = null; + + if (strpos($fieldName, '.') !== false) { + list($relation, $fieldName) = explode('.', $fieldName); + } + + if (isset($classMetadata->associationMappings[$relation])) { + if ($relation) { + $associationMapping = $classMetadata->associationMappings[$relation]; + $joinAlias = $alias.$relation; + $parentAlias = $alias; + + $this->addJoinedEntityResult($associationMapping['targetEntity'], $joinAlias, $parentAlias, $relation); + $this->addFieldResult($joinAlias, $field['column'], $fieldName); + } else { + $this->addFieldResult($alias, $field['column'], $fieldName, $classMetadata->name); + } + } else { + if ( ! isset($classMetadata->fieldMappings[$fieldName])) { + throw new \InvalidArgumentException("Entity '".$classMetadata->name."' has no field '".$fieldName."'. "); + } + + $this->addFieldResult($alias, $field['column'], $fieldName, $classMetadata->name); + } + } + + } else { + foreach ($classMetadata->getColumnNames() as $columnName) { + $propertyName = $classMetadata->getFieldName($columnName); + + $this->addFieldResult($alias, $columnName, $propertyName); + } + } + + return $this; + } + + /** + * Generates the Select clause from this ResultSetMappingBuilder. + * + * Works only for all the entity results. The select parts for scalar + * expressions have to be written manually. + * + * @param array $tableAliases + * + * @return string + */ + public function generateSelectClause($tableAliases = []) + { + $sql = ""; + + foreach ($this->columnOwnerMap as $columnName => $dqlAlias) { + $tableAlias = $tableAliases[$dqlAlias] ?? $dqlAlias; + + if ($sql) { + $sql .= ", "; + } + + $sql .= $tableAlias . "."; + + if (isset($this->fieldMappings[$columnName])) { + $class = $this->em->getClassMetadata($this->declaringClasses[$columnName]); + $sql .= $class->fieldMappings[$this->fieldMappings[$columnName]]['columnName']; + } else if (isset($this->metaMappings[$columnName])) { + $sql .= $this->metaMappings[$columnName]; + } else if (isset($this->discriminatorColumns[$dqlAlias])) { + $sql .= $this->discriminatorColumns[$dqlAlias]; + } + + $sql .= " AS " . $columnName; + } + + return $sql; + } + + /** + * @return string + */ + public function __toString() + { + return $this->generateSelectClause([]); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php new file mode 100644 index 0000000..d06d070 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php @@ -0,0 +1,2324 @@ +. + */ + +namespace Doctrine\ORM\Query; + +use Doctrine\DBAL\LockMode; +use Doctrine\DBAL\Types\Type; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Doctrine\ORM\OptimisticLockException; +use Doctrine\ORM\Query; +use Doctrine\ORM\Utility\HierarchyDiscriminatorResolver; +use Doctrine\ORM\Utility\PersisterHelper; + +/** + * The SqlWalker is a TreeWalker that walks over a DQL AST and constructs + * the corresponding SQL. + * + * @author Guilherme Blanco + * @author Roman Borschel + * @author Benjamin Eberlei + * @author Alexander + * @author Fabio B. Silva + * @since 2.0 + */ +class SqlWalker implements TreeWalker +{ + /** + * @var string + */ + const HINT_DISTINCT = 'doctrine.distinct'; + + /** + * @var ResultSetMapping + */ + private $rsm; + + /** + * Counter for generating unique column aliases. + * + * @var integer + */ + private $aliasCounter = 0; + + /** + * Counter for generating unique table aliases. + * + * @var integer + */ + private $tableAliasCounter = 0; + + /** + * Counter for generating unique scalar result. + * + * @var integer + */ + private $scalarResultCounter = 1; + + /** + * Counter for generating unique parameter indexes. + * + * @var integer + */ + private $sqlParamIndex = 0; + + /** + * Counter for generating indexes. + * + * @var integer + */ + private $newObjectCounter = 0; + + /** + * @var ParserResult + */ + private $parserResult; + + /** + * @var \Doctrine\ORM\EntityManager + */ + private $em; + + /** + * @var \Doctrine\DBAL\Connection + */ + private $conn; + + /** + * @var \Doctrine\ORM\AbstractQuery + */ + private $query; + + /** + * @var array + */ + private $tableAliasMap = []; + + /** + * Map from result variable names to their SQL column alias names. + * + * @var array + */ + private $scalarResultAliasMap = []; + + /** + * Map from Table-Alias + Column-Name to OrderBy-Direction. + * + * @var array + */ + private $orderedColumnsMap = []; + + /** + * Map from DQL-Alias + Field-Name to SQL Column Alias. + * + * @var array + */ + private $scalarFields = []; + + /** + * Map of all components/classes that appear in the DQL query. + * + * @var array + */ + private $queryComponents; + + /** + * A list of classes that appear in non-scalar SelectExpressions. + * + * @var array + */ + private $selectedClasses = []; + + /** + * The DQL alias of the root class of the currently traversed query. + * + * @var array + */ + private $rootAliases = []; + + /** + * Flag that indicates whether to generate SQL table aliases in the SQL. + * These should only be generated for SELECT queries, not for UPDATE/DELETE. + * + * @var boolean + */ + private $useSqlTableAliases = true; + + /** + * The database platform abstraction. + * + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $platform; + + /** + * The quote strategy. + * + * @var \Doctrine\ORM\Mapping\QuoteStrategy + */ + private $quoteStrategy; + + /** + * {@inheritDoc} + */ + public function __construct($query, $parserResult, array $queryComponents) + { + $this->query = $query; + $this->parserResult = $parserResult; + $this->queryComponents = $queryComponents; + $this->rsm = $parserResult->getResultSetMapping(); + $this->em = $query->getEntityManager(); + $this->conn = $this->em->getConnection(); + $this->platform = $this->conn->getDatabasePlatform(); + $this->quoteStrategy = $this->em->getConfiguration()->getQuoteStrategy(); + } + + /** + * Gets the Query instance used by the walker. + * + * @return Query. + */ + public function getQuery() + { + return $this->query; + } + + /** + * Gets the Connection used by the walker. + * + * @return \Doctrine\DBAL\Connection + */ + public function getConnection() + { + return $this->conn; + } + + /** + * Gets the EntityManager used by the walker. + * + * @return \Doctrine\ORM\EntityManager + */ + public function getEntityManager() + { + return $this->em; + } + + /** + * Gets the information about a single query component. + * + * @param string $dqlAlias The DQL alias. + * + * @return array + */ + public function getQueryComponent($dqlAlias) + { + return $this->queryComponents[$dqlAlias]; + } + + /** + * {@inheritdoc} + */ + public function getQueryComponents() + { + return $this->queryComponents; + } + + /** + * {@inheritdoc} + */ + public function setQueryComponent($dqlAlias, array $queryComponent) + { + $requiredKeys = ['metadata', 'parent', 'relation', 'map', 'nestingLevel', 'token']; + + if (array_diff($requiredKeys, array_keys($queryComponent))) { + throw QueryException::invalidQueryComponent($dqlAlias); + } + + $this->queryComponents[$dqlAlias] = $queryComponent; + } + + /** + * {@inheritdoc} + */ + public function getExecutor($AST) + { + switch (true) { + case ($AST instanceof AST\DeleteStatement): + $primaryClass = $this->em->getClassMetadata($AST->deleteClause->abstractSchemaName); + + return ($primaryClass->isInheritanceTypeJoined()) + ? new Exec\MultiTableDeleteExecutor($AST, $this) + : new Exec\SingleTableDeleteUpdateExecutor($AST, $this); + + case ($AST instanceof AST\UpdateStatement): + $primaryClass = $this->em->getClassMetadata($AST->updateClause->abstractSchemaName); + + return ($primaryClass->isInheritanceTypeJoined()) + ? new Exec\MultiTableUpdateExecutor($AST, $this) + : new Exec\SingleTableDeleteUpdateExecutor($AST, $this); + + default: + return new Exec\SingleSelectExecutor($AST, $this); + } + } + + /** + * Generates a unique, short SQL table alias. + * + * @param string $tableName Table name + * @param string $dqlAlias The DQL alias. + * + * @return string Generated table alias. + */ + public function getSQLTableAlias($tableName, $dqlAlias = '') + { + $tableName .= ($dqlAlias) ? '@[' . $dqlAlias . ']' : ''; + + if ( ! isset($this->tableAliasMap[$tableName])) { + $this->tableAliasMap[$tableName] = (preg_match('/[a-z]/i', $tableName[0]) ? strtolower($tableName[0]) : 't') + . $this->tableAliasCounter++ . '_'; + } + + return $this->tableAliasMap[$tableName]; + } + + /** + * Forces the SqlWalker to use a specific alias for a table name, rather than + * generating an alias on its own. + * + * @param string $tableName + * @param string $alias + * @param string $dqlAlias + * + * @return string + */ + public function setSQLTableAlias($tableName, $alias, $dqlAlias = '') + { + $tableName .= ($dqlAlias) ? '@[' . $dqlAlias . ']' : ''; + + $this->tableAliasMap[$tableName] = $alias; + + return $alias; + } + + /** + * Gets an SQL column alias for a column name. + * + * @param string $columnName + * + * @return string + */ + public function getSQLColumnAlias($columnName) + { + return $this->quoteStrategy->getColumnAlias($columnName, $this->aliasCounter++, $this->platform); + } + + /** + * Generates the SQL JOINs that are necessary for Class Table Inheritance + * for the given class. + * + * @param ClassMetadata $class The class for which to generate the joins. + * @param string $dqlAlias The DQL alias of the class. + * + * @return string The SQL. + */ + private function _generateClassTableInheritanceJoins($class, $dqlAlias) + { + $sql = ''; + + $baseTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias); + + // INNER JOIN parent class tables + foreach ($class->parentClasses as $parentClassName) { + $parentClass = $this->em->getClassMetadata($parentClassName); + $tableAlias = $this->getSQLTableAlias($parentClass->getTableName(), $dqlAlias); + + // If this is a joined association we must use left joins to preserve the correct result. + $sql .= isset($this->queryComponents[$dqlAlias]['relation']) ? ' LEFT ' : ' INNER '; + $sql .= 'JOIN ' . $this->quoteStrategy->getTableName($parentClass, $this->platform) . ' ' . $tableAlias . ' ON '; + + $sqlParts = []; + + foreach ($this->quoteStrategy->getIdentifierColumnNames($class, $this->platform) as $columnName) { + $sqlParts[] = $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName; + } + + // Add filters on the root class + if ($filterSql = $this->generateFilterConditionSQL($parentClass, $tableAlias)) { + $sqlParts[] = $filterSql; + } + + $sql .= implode(' AND ', $sqlParts); + } + + // Ignore subclassing inclusion if partial objects is disallowed + if ($this->query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) { + return $sql; + } + + // LEFT JOIN child class tables + foreach ($class->subClasses as $subClassName) { + $subClass = $this->em->getClassMetadata($subClassName); + $tableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias); + + $sql .= ' LEFT JOIN ' . $this->quoteStrategy->getTableName($subClass, $this->platform) . ' ' . $tableAlias . ' ON '; + + $sqlParts = []; + + foreach ($this->quoteStrategy->getIdentifierColumnNames($subClass, $this->platform) as $columnName) { + $sqlParts[] = $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName; + } + + $sql .= implode(' AND ', $sqlParts); + } + + return $sql; + } + + /** + * @return string + */ + private function _generateOrderedCollectionOrderByItems() + { + $orderedColumns = []; + + foreach ($this->selectedClasses as $selectedClass) { + $dqlAlias = $selectedClass['dqlAlias']; + $qComp = $this->queryComponents[$dqlAlias]; + + if ( ! isset($qComp['relation']['orderBy'])) { + continue; + } + + $persister = $this->em->getUnitOfWork()->getEntityPersister($qComp['metadata']->name); + + foreach ($qComp['relation']['orderBy'] as $fieldName => $orientation) { + $columnName = $this->quoteStrategy->getColumnName($fieldName, $qComp['metadata'], $this->platform); + $tableName = ($qComp['metadata']->isInheritanceTypeJoined()) + ? $persister->getOwningTable($fieldName) + : $qComp['metadata']->getTableName(); + + $orderedColumn = $this->getSQLTableAlias($tableName, $dqlAlias) . '.' . $columnName; + + // OrderByClause should replace an ordered relation. see - DDC-2475 + if (isset($this->orderedColumnsMap[$orderedColumn])) { + continue; + } + + $this->orderedColumnsMap[$orderedColumn] = $orientation; + $orderedColumns[] = $orderedColumn . ' ' . $orientation; + } + } + + return implode(', ', $orderedColumns); + } + + /** + * Generates a discriminator column SQL condition for the class with the given DQL alias. + * + * @param array $dqlAliases List of root DQL aliases to inspect for discriminator restrictions. + * + * @return string + */ + private function _generateDiscriminatorColumnConditionSQL(array $dqlAliases) + { + $sqlParts = []; + + foreach ($dqlAliases as $dqlAlias) { + $class = $this->queryComponents[$dqlAlias]['metadata']; + + if ( ! $class->isInheritanceTypeSingleTable()) continue; + + $conn = $this->em->getConnection(); + $values = []; + + if ($class->discriminatorValue !== null) { // discriminators can be 0 + $values[] = $conn->quote($class->discriminatorValue); + } + + foreach ($class->subClasses as $subclassName) { + $values[] = $conn->quote($this->em->getClassMetadata($subclassName)->discriminatorValue); + } + + $sqlTableAlias = ($this->useSqlTableAliases) + ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' + : ''; + + $sqlParts[] = $sqlTableAlias . $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')'; + } + + $sql = implode(' AND ', $sqlParts); + + return (count($sqlParts) > 1) ? '(' . $sql . ')' : $sql; + } + + /** + * Generates the filter SQL for a given entity and table alias. + * + * @param ClassMetadata $targetEntity Metadata of the target entity. + * @param string $targetTableAlias The table alias of the joined/selected table. + * + * @return string The SQL query part to add to a query. + */ + private function generateFilterConditionSQL(ClassMetadata $targetEntity, $targetTableAlias) + { + if (!$this->em->hasFilters()) { + return ''; + } + + switch($targetEntity->inheritanceType) { + case ClassMetadata::INHERITANCE_TYPE_NONE: + break; + case ClassMetadata::INHERITANCE_TYPE_JOINED: + // The classes in the inheritance will be added to the query one by one, + // but only the root node is getting filtered + if ($targetEntity->name !== $targetEntity->rootEntityName) { + return ''; + } + break; + case ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE: + // With STI the table will only be queried once, make sure that the filters + // are added to the root entity + $targetEntity = $this->em->getClassMetadata($targetEntity->rootEntityName); + break; + default: + //@todo: throw exception? + return ''; + } + + $filterClauses = []; + foreach ($this->em->getFilters()->getEnabledFilters() as $filter) { + if ('' !== $filterExpr = $filter->addFilterConstraint($targetEntity, $targetTableAlias)) { + $filterClauses[] = '(' . $filterExpr . ')'; + } + } + + return implode(' AND ', $filterClauses); + } + + /** + * {@inheritdoc} + */ + public function walkSelectStatement(AST\SelectStatement $AST) + { + $limit = $this->query->getMaxResults(); + $offset = $this->query->getFirstResult(); + $lockMode = $this->query->getHint(Query::HINT_LOCK_MODE); + $sql = $this->walkSelectClause($AST->selectClause) + . $this->walkFromClause($AST->fromClause) + . $this->walkWhereClause($AST->whereClause); + + if ($AST->groupByClause) { + $sql .= $this->walkGroupByClause($AST->groupByClause); + } + + if ($AST->havingClause) { + $sql .= $this->walkHavingClause($AST->havingClause); + } + + if ($AST->orderByClause) { + $sql .= $this->walkOrderByClause($AST->orderByClause); + } + + if ( ! $AST->orderByClause && ($orderBySql = $this->_generateOrderedCollectionOrderByItems())) { + $sql .= ' ORDER BY ' . $orderBySql; + } + + if ($limit !== null || $offset !== null) { + $sql = $this->platform->modifyLimitQuery($sql, $limit, $offset); + } + + if ($lockMode === null || $lockMode === false || $lockMode === LockMode::NONE) { + return $sql; + } + + if ($lockMode === LockMode::PESSIMISTIC_READ) { + return $sql . ' ' . $this->platform->getReadLockSQL(); + } + + if ($lockMode === LockMode::PESSIMISTIC_WRITE) { + return $sql . ' ' . $this->platform->getWriteLockSQL(); + } + + if ($lockMode !== LockMode::OPTIMISTIC) { + throw QueryException::invalidLockMode(); + } + + foreach ($this->selectedClasses as $selectedClass) { + if ( ! $selectedClass['class']->isVersioned) { + throw OptimisticLockException::lockFailed($selectedClass['class']->name); + } + } + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkUpdateStatement(AST\UpdateStatement $AST) + { + $this->useSqlTableAliases = false; + $this->rsm->isSelect = false; + + return $this->walkUpdateClause($AST->updateClause) + . $this->walkWhereClause($AST->whereClause); + } + + /** + * {@inheritdoc} + */ + public function walkDeleteStatement(AST\DeleteStatement $AST) + { + $this->useSqlTableAliases = false; + $this->rsm->isSelect = false; + + return $this->walkDeleteClause($AST->deleteClause) + . $this->walkWhereClause($AST->whereClause); + } + + /** + * Walks down an IdentificationVariable AST node, thereby generating the appropriate SQL. + * This one differs of ->walkIdentificationVariable() because it generates the entity identifiers. + * + * @param string $identVariable + * + * @return string + */ + public function walkEntityIdentificationVariable($identVariable) + { + $class = $this->queryComponents[$identVariable]['metadata']; + $tableAlias = $this->getSQLTableAlias($class->getTableName(), $identVariable); + $sqlParts = []; + + foreach ($this->quoteStrategy->getIdentifierColumnNames($class, $this->platform) as $columnName) { + $sqlParts[] = $tableAlias . '.' . $columnName; + } + + return implode(', ', $sqlParts); + } + + /** + * Walks down an IdentificationVariable (no AST node associated), thereby generating the SQL. + * + * @param string $identificationVariable + * @param string $fieldName + * + * @return string The SQL. + */ + public function walkIdentificationVariable($identificationVariable, $fieldName = null) + { + $class = $this->queryComponents[$identificationVariable]['metadata']; + + if ( + $fieldName !== null && $class->isInheritanceTypeJoined() && + isset($class->fieldMappings[$fieldName]['inherited']) + ) { + $class = $this->em->getClassMetadata($class->fieldMappings[$fieldName]['inherited']); + } + + return $this->getSQLTableAlias($class->getTableName(), $identificationVariable); + } + + /** + * {@inheritdoc} + */ + public function walkPathExpression($pathExpr) + { + $sql = ''; + + /* @var $pathExpr Query\AST\PathExpression */ + switch ($pathExpr->type) { + case AST\PathExpression::TYPE_STATE_FIELD: + $fieldName = $pathExpr->field; + $dqlAlias = $pathExpr->identificationVariable; + $class = $this->queryComponents[$dqlAlias]['metadata']; + + if ($this->useSqlTableAliases) { + $sql .= $this->walkIdentificationVariable($dqlAlias, $fieldName) . '.'; + } + + $sql .= $this->quoteStrategy->getColumnName($fieldName, $class, $this->platform); + break; + + case AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION: + // 1- the owning side: + // Just use the foreign key, i.e. u.group_id + $fieldName = $pathExpr->field; + $dqlAlias = $pathExpr->identificationVariable; + $class = $this->queryComponents[$dqlAlias]['metadata']; + + if (isset($class->associationMappings[$fieldName]['inherited'])) { + $class = $this->em->getClassMetadata($class->associationMappings[$fieldName]['inherited']); + } + + $assoc = $class->associationMappings[$fieldName]; + + if ( ! $assoc['isOwningSide']) { + throw QueryException::associationPathInverseSideNotSupported($pathExpr); + } + + // COMPOSITE KEYS NOT (YET?) SUPPORTED + if (count($assoc['sourceToTargetKeyColumns']) > 1) { + throw QueryException::associationPathCompositeKeyNotSupported(); + } + + if ($this->useSqlTableAliases) { + $sql .= $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.'; + } + + $sql .= reset($assoc['targetToSourceKeyColumns']); + break; + + default: + throw QueryException::invalidPathExpression($pathExpr); + } + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkSelectClause($selectClause) + { + $sql = 'SELECT ' . (($selectClause->isDistinct) ? 'DISTINCT ' : ''); + $sqlSelectExpressions = array_filter(array_map([$this, 'walkSelectExpression'], $selectClause->selectExpressions)); + + if ($this->query->getHint(Query::HINT_INTERNAL_ITERATION) == true && $selectClause->isDistinct) { + $this->query->setHint(self::HINT_DISTINCT, true); + } + + $addMetaColumns = ! $this->query->getHint(Query::HINT_FORCE_PARTIAL_LOAD) && + $this->query->getHydrationMode() == Query::HYDRATE_OBJECT + || + $this->query->getHydrationMode() != Query::HYDRATE_OBJECT && + $this->query->getHint(Query::HINT_INCLUDE_META_COLUMNS); + + foreach ($this->selectedClasses as $selectedClass) { + $class = $selectedClass['class']; + $dqlAlias = $selectedClass['dqlAlias']; + $resultAlias = $selectedClass['resultAlias']; + + // Register as entity or joined entity result + if ($this->queryComponents[$dqlAlias]['relation'] === null) { + $this->rsm->addEntityResult($class->name, $dqlAlias, $resultAlias); + } else { + $this->rsm->addJoinedEntityResult( + $class->name, + $dqlAlias, + $this->queryComponents[$dqlAlias]['parent'], + $this->queryComponents[$dqlAlias]['relation']['fieldName'] + ); + } + + if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()) { + // Add discriminator columns to SQL + $rootClass = $this->em->getClassMetadata($class->rootEntityName); + $tblAlias = $this->getSQLTableAlias($rootClass->getTableName(), $dqlAlias); + $discrColumn = $rootClass->discriminatorColumn; + $columnAlias = $this->getSQLColumnAlias($discrColumn['name']); + + $sqlSelectExpressions[] = $tblAlias . '.' . $discrColumn['name'] . ' AS ' . $columnAlias; + + $this->rsm->setDiscriminatorColumn($dqlAlias, $columnAlias); + $this->rsm->addMetaResult($dqlAlias, $columnAlias, $discrColumn['fieldName'], false, $discrColumn['type']); + } + + // Add foreign key columns to SQL, if necessary + if ( ! $addMetaColumns && ! $class->containsForeignIdentifier) { + continue; + } + + // Add foreign key columns of class and also parent classes + foreach ($class->associationMappings as $assoc) { + if ( ! ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) + || ( ! $addMetaColumns && !isset($assoc['id']))) { + continue; + } + + $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); + $isIdentifier = (isset($assoc['id']) && $assoc['id'] === true); + $owningClass = (isset($assoc['inherited'])) ? $this->em->getClassMetadata($assoc['inherited']) : $class; + $sqlTableAlias = $this->getSQLTableAlias($owningClass->getTableName(), $dqlAlias); + + foreach ($assoc['joinColumns'] as $joinColumn) { + $columnName = $joinColumn['name']; + $columnAlias = $this->getSQLColumnAlias($columnName); + $columnType = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); + + $quotedColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); + $sqlSelectExpressions[] = $sqlTableAlias . '.' . $quotedColumnName . ' AS ' . $columnAlias; + + $this->rsm->addMetaResult($dqlAlias, $columnAlias, $columnName, $isIdentifier, $columnType); + } + } + + // Add foreign key columns to SQL, if necessary + if ( ! $addMetaColumns) { + continue; + } + + // Add foreign key columns of subclasses + foreach ($class->subClasses as $subClassName) { + $subClass = $this->em->getClassMetadata($subClassName); + $sqlTableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias); + + foreach ($subClass->associationMappings as $assoc) { + // Skip if association is inherited + if (isset($assoc['inherited'])) continue; + + if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) { + $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); + + foreach ($assoc['joinColumns'] as $joinColumn) { + $columnName = $joinColumn['name']; + $columnAlias = $this->getSQLColumnAlias($columnName); + $columnType = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); + + $quotedColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $subClass, $this->platform); + $sqlSelectExpressions[] = $sqlTableAlias . '.' . $quotedColumnName . ' AS ' . $columnAlias; + + $this->rsm->addMetaResult($dqlAlias, $columnAlias, $columnName, $subClass->isIdentifier($columnName), $columnType); + } + } + } + } + } + + $sql .= implode(', ', $sqlSelectExpressions); + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkFromClause($fromClause) + { + $identificationVarDecls = $fromClause->identificationVariableDeclarations; + $sqlParts = []; + + foreach ($identificationVarDecls as $identificationVariableDecl) { + $sqlParts[] = $this->walkIdentificationVariableDeclaration($identificationVariableDecl); + } + + return ' FROM ' . implode(', ', $sqlParts); + } + + /** + * Walks down a IdentificationVariableDeclaration AST node, thereby generating the appropriate SQL. + * + * @param AST\IdentificationVariableDeclaration $identificationVariableDecl + * + * @return string + */ + public function walkIdentificationVariableDeclaration($identificationVariableDecl) + { + $sql = $this->walkRangeVariableDeclaration($identificationVariableDecl->rangeVariableDeclaration); + + if ($identificationVariableDecl->indexBy) { + $this->walkIndexBy($identificationVariableDecl->indexBy); + } + + foreach ($identificationVariableDecl->joins as $join) { + $sql .= $this->walkJoin($join); + } + + return $sql; + } + + /** + * Walks down a IndexBy AST node. + * + * @param AST\IndexBy $indexBy + * + * @return void + */ + public function walkIndexBy($indexBy) + { + $pathExpression = $indexBy->simpleStateFieldPathExpression; + $alias = $pathExpression->identificationVariable; + $field = $pathExpression->field; + + if (isset($this->scalarFields[$alias][$field])) { + $this->rsm->addIndexByScalar($this->scalarFields[$alias][$field]); + + return; + } + + $this->rsm->addIndexBy($alias, $field); + } + + /** + * Walks down a RangeVariableDeclaration AST node, thereby generating the appropriate SQL. + * + * @param AST\RangeVariableDeclaration $rangeVariableDeclaration + * + * @return string + */ + public function walkRangeVariableDeclaration($rangeVariableDeclaration) + { + return $this->generateRangeVariableDeclarationSQL($rangeVariableDeclaration, false); + } + + /** + * Generate appropriate SQL for RangeVariableDeclaration AST node + * + * @param AST\RangeVariableDeclaration $rangeVariableDeclaration + * @param bool $buildNestedJoins + * + * @return string + */ + private function generateRangeVariableDeclarationSQL($rangeVariableDeclaration, bool $buildNestedJoins) : string + { + $class = $this->em->getClassMetadata($rangeVariableDeclaration->abstractSchemaName); + $dqlAlias = $rangeVariableDeclaration->aliasIdentificationVariable; + + if ($rangeVariableDeclaration->isRoot) { + $this->rootAliases[] = $dqlAlias; + } + + $sql = $this->platform->appendLockHint( + $this->quoteStrategy->getTableName($class, $this->platform) . ' ' . + $this->getSQLTableAlias($class->getTableName(), $dqlAlias), + $this->query->getHint(Query::HINT_LOCK_MODE) + ); + + if ( ! $class->isInheritanceTypeJoined()) { + return $sql; + } + + $classTableInheritanceJoins = $this->_generateClassTableInheritanceJoins($class, $dqlAlias); + + if ( ! $buildNestedJoins) { + return $sql . $classTableInheritanceJoins; + } + + return $classTableInheritanceJoins === '' ? $sql : '(' . $sql . $classTableInheritanceJoins . ')'; + } + + /** + * Walks down a JoinAssociationDeclaration AST node, thereby generating the appropriate SQL. + * + * @param AST\JoinAssociationDeclaration $joinAssociationDeclaration + * @param int $joinType + * @param AST\ConditionalExpression $condExpr + * + * @return string + * + * @throws QueryException + */ + public function walkJoinAssociationDeclaration($joinAssociationDeclaration, $joinType = AST\Join::JOIN_TYPE_INNER, $condExpr = null) + { + $sql = ''; + + $associationPathExpression = $joinAssociationDeclaration->joinAssociationPathExpression; + $joinedDqlAlias = $joinAssociationDeclaration->aliasIdentificationVariable; + $indexBy = $joinAssociationDeclaration->indexBy; + + $relation = $this->queryComponents[$joinedDqlAlias]['relation']; + $targetClass = $this->em->getClassMetadata($relation['targetEntity']); + $sourceClass = $this->em->getClassMetadata($relation['sourceEntity']); + $targetTableName = $this->quoteStrategy->getTableName($targetClass, $this->platform); + + $targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName(), $joinedDqlAlias); + $sourceTableAlias = $this->getSQLTableAlias($sourceClass->getTableName(), $associationPathExpression->identificationVariable); + + // Ensure we got the owning side, since it has all mapping info + $assoc = ( ! $relation['isOwningSide']) ? $targetClass->associationMappings[$relation['mappedBy']] : $relation; + + if ($this->query->getHint(Query::HINT_INTERNAL_ITERATION) == true && (!$this->query->getHint(self::HINT_DISTINCT) || isset($this->selectedClasses[$joinedDqlAlias]))) { + if ($relation['type'] == ClassMetadata::ONE_TO_MANY || $relation['type'] == ClassMetadata::MANY_TO_MANY) { + throw QueryException::iterateWithFetchJoinNotAllowed($assoc); + } + } + + $targetTableJoin = null; + + // This condition is not checking ClassMetadata::MANY_TO_ONE, because by definition it cannot + // be the owning side and previously we ensured that $assoc is always the owning side of the associations. + // The owning side is necessary at this point because only it contains the JoinColumn information. + switch (true) { + case ($assoc['type'] & ClassMetadata::TO_ONE): + $conditions = []; + + foreach ($assoc['joinColumns'] as $joinColumn) { + $quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); + $quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform); + + if ($relation['isOwningSide']) { + $conditions[] = $sourceTableAlias . '.' . $quotedSourceColumn . ' = ' . $targetTableAlias . '.' . $quotedTargetColumn; + + continue; + } + + $conditions[] = $sourceTableAlias . '.' . $quotedTargetColumn . ' = ' . $targetTableAlias . '.' . $quotedSourceColumn; + } + + // Apply remaining inheritance restrictions + $discrSql = $this->_generateDiscriminatorColumnConditionSQL([$joinedDqlAlias]); + + if ($discrSql) { + $conditions[] = $discrSql; + } + + // Apply the filters + $filterExpr = $this->generateFilterConditionSQL($targetClass, $targetTableAlias); + + if ($filterExpr) { + $conditions[] = $filterExpr; + } + + $targetTableJoin = [ + 'table' => $targetTableName . ' ' . $targetTableAlias, + 'condition' => implode(' AND ', $conditions), + ]; + break; + + case ($assoc['type'] == ClassMetadata::MANY_TO_MANY): + // Join relation table + $joinTable = $assoc['joinTable']; + $joinTableAlias = $this->getSQLTableAlias($joinTable['name'], $joinedDqlAlias); + $joinTableName = $this->quoteStrategy->getJoinTableName($assoc, $sourceClass, $this->platform); + + $conditions = []; + $relationColumns = ($relation['isOwningSide']) + ? $assoc['joinTable']['joinColumns'] + : $assoc['joinTable']['inverseJoinColumns']; + + foreach ($relationColumns as $joinColumn) { + $quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); + $quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform); + + $conditions[] = $sourceTableAlias . '.' . $quotedTargetColumn . ' = ' . $joinTableAlias . '.' . $quotedSourceColumn; + } + + $sql .= $joinTableName . ' ' . $joinTableAlias . ' ON ' . implode(' AND ', $conditions); + + // Join target table + $sql .= ($joinType == AST\Join::JOIN_TYPE_LEFT || $joinType == AST\Join::JOIN_TYPE_LEFTOUTER) ? ' LEFT JOIN ' : ' INNER JOIN '; + + $conditions = []; + $relationColumns = ($relation['isOwningSide']) + ? $assoc['joinTable']['inverseJoinColumns'] + : $assoc['joinTable']['joinColumns']; + + foreach ($relationColumns as $joinColumn) { + $quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); + $quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform); + + $conditions[] = $targetTableAlias . '.' . $quotedTargetColumn . ' = ' . $joinTableAlias . '.' . $quotedSourceColumn; + } + + // Apply remaining inheritance restrictions + $discrSql = $this->_generateDiscriminatorColumnConditionSQL([$joinedDqlAlias]); + + if ($discrSql) { + $conditions[] = $discrSql; + } + + // Apply the filters + $filterExpr = $this->generateFilterConditionSQL($targetClass, $targetTableAlias); + + if ($filterExpr) { + $conditions[] = $filterExpr; + } + + $targetTableJoin = [ + 'table' => $targetTableName . ' ' . $targetTableAlias, + 'condition' => implode(' AND ', $conditions), + ]; + break; + + default: + throw new \BadMethodCallException('Type of association must be one of *_TO_ONE or MANY_TO_MANY'); + } + + // Handle WITH clause + $withCondition = (null === $condExpr) ? '' : ('(' . $this->walkConditionalExpression($condExpr) . ')'); + + if ($targetClass->isInheritanceTypeJoined()) { + $ctiJoins = $this->_generateClassTableInheritanceJoins($targetClass, $joinedDqlAlias); + // If we have WITH condition, we need to build nested joins for target class table and cti joins + if ($withCondition) { + $sql .= '(' . $targetTableJoin['table'] . $ctiJoins . ') ON ' . $targetTableJoin['condition']; + } else { + $sql .= $targetTableJoin['table'] . ' ON ' . $targetTableJoin['condition'] . $ctiJoins; + } + } else { + $sql .= $targetTableJoin['table'] . ' ON ' . $targetTableJoin['condition']; + } + + if ($withCondition) { + $sql .= ' AND ' . $withCondition; + } + + // Apply the indexes + if ($indexBy) { + // For Many-To-One or One-To-One associations this obviously makes no sense, but is ignored silently. + $this->walkIndexBy($indexBy); + } else if (isset($relation['indexBy'])) { + $this->rsm->addIndexBy($joinedDqlAlias, $relation['indexBy']); + } + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkFunction($function) + { + return $function->getSql($this); + } + + /** + * {@inheritdoc} + */ + public function walkOrderByClause($orderByClause) + { + $orderByItems = array_map([$this, 'walkOrderByItem'], $orderByClause->orderByItems); + + if (($collectionOrderByItems = $this->_generateOrderedCollectionOrderByItems()) !== '') { + $orderByItems = array_merge($orderByItems, (array) $collectionOrderByItems); + } + + return ' ORDER BY ' . implode(', ', $orderByItems); + } + + /** + * {@inheritdoc} + */ + public function walkOrderByItem($orderByItem) + { + $type = strtoupper($orderByItem->type); + $expr = $orderByItem->expression; + $sql = ($expr instanceof AST\Node) + ? $expr->dispatch($this) + : $this->walkResultVariable($this->queryComponents[$expr]['token']['value']); + + $this->orderedColumnsMap[$sql] = $type; + + if ($expr instanceof AST\Subselect) { + return '(' . $sql . ') ' . $type; + } + + return $sql . ' ' . $type; + } + + /** + * {@inheritdoc} + */ + public function walkHavingClause($havingClause) + { + return ' HAVING ' . $this->walkConditionalExpression($havingClause->conditionalExpression); + } + + /** + * {@inheritdoc} + */ + public function walkJoin($join) + { + $joinType = $join->joinType; + $joinDeclaration = $join->joinAssociationDeclaration; + + $sql = ($joinType == AST\Join::JOIN_TYPE_LEFT || $joinType == AST\Join::JOIN_TYPE_LEFTOUTER) + ? ' LEFT JOIN ' + : ' INNER JOIN '; + + switch (true) { + case ($joinDeclaration instanceof AST\RangeVariableDeclaration): + $class = $this->em->getClassMetadata($joinDeclaration->abstractSchemaName); + $dqlAlias = $joinDeclaration->aliasIdentificationVariable; + $tableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias); + $conditions = []; + + if ($join->conditionalExpression) { + $conditions[] = '(' . $this->walkConditionalExpression($join->conditionalExpression) . ')'; + } + + $isUnconditionalJoin = empty($conditions); + $condExprConjunction = ($class->isInheritanceTypeJoined() && $joinType != AST\Join::JOIN_TYPE_LEFT && $joinType != AST\Join::JOIN_TYPE_LEFTOUTER && $isUnconditionalJoin) + ? ' AND ' + : ' ON '; + + $sql .= $this->generateRangeVariableDeclarationSQL($joinDeclaration, !$isUnconditionalJoin); + + // Apply remaining inheritance restrictions + $discrSql = $this->_generateDiscriminatorColumnConditionSQL([$dqlAlias]); + + if ($discrSql) { + $conditions[] = $discrSql; + } + + // Apply the filters + $filterExpr = $this->generateFilterConditionSQL($class, $tableAlias); + + if ($filterExpr) { + $conditions[] = $filterExpr; + } + + if ($conditions) { + $sql .= $condExprConjunction . implode(' AND ', $conditions); + } + + break; + + case ($joinDeclaration instanceof AST\JoinAssociationDeclaration): + $sql .= $this->walkJoinAssociationDeclaration($joinDeclaration, $joinType, $join->conditionalExpression); + break; + } + + return $sql; + } + + /** + * Walks down a CoalesceExpression AST node and generates the corresponding SQL. + * + * @param AST\CoalesceExpression $coalesceExpression + * + * @return string The SQL. + */ + public function walkCoalesceExpression($coalesceExpression) + { + $sql = 'COALESCE('; + + $scalarExpressions = []; + + foreach ($coalesceExpression->scalarExpressions as $scalarExpression) { + $scalarExpressions[] = $this->walkSimpleArithmeticExpression($scalarExpression); + } + + $sql .= implode(', ', $scalarExpressions) . ')'; + + return $sql; + } + + /** + * Walks down a NullIfExpression AST node and generates the corresponding SQL. + * + * @param AST\NullIfExpression $nullIfExpression + * + * @return string The SQL. + */ + public function walkNullIfExpression($nullIfExpression) + { + $firstExpression = is_string($nullIfExpression->firstExpression) + ? $this->conn->quote($nullIfExpression->firstExpression) + : $this->walkSimpleArithmeticExpression($nullIfExpression->firstExpression); + + $secondExpression = is_string($nullIfExpression->secondExpression) + ? $this->conn->quote($nullIfExpression->secondExpression) + : $this->walkSimpleArithmeticExpression($nullIfExpression->secondExpression); + + return 'NULLIF(' . $firstExpression . ', ' . $secondExpression . ')'; + } + + /** + * Walks down a GeneralCaseExpression AST node and generates the corresponding SQL. + * + * @param AST\GeneralCaseExpression $generalCaseExpression + * + * @return string The SQL. + */ + public function walkGeneralCaseExpression(AST\GeneralCaseExpression $generalCaseExpression) + { + $sql = 'CASE'; + + foreach ($generalCaseExpression->whenClauses as $whenClause) { + $sql .= ' WHEN ' . $this->walkConditionalExpression($whenClause->caseConditionExpression); + $sql .= ' THEN ' . $this->walkSimpleArithmeticExpression($whenClause->thenScalarExpression); + } + + $sql .= ' ELSE ' . $this->walkSimpleArithmeticExpression($generalCaseExpression->elseScalarExpression) . ' END'; + + return $sql; + } + + /** + * Walks down a SimpleCaseExpression AST node and generates the corresponding SQL. + * + * @param AST\SimpleCaseExpression $simpleCaseExpression + * + * @return string The SQL. + */ + public function walkSimpleCaseExpression($simpleCaseExpression) + { + $sql = 'CASE ' . $this->walkStateFieldPathExpression($simpleCaseExpression->caseOperand); + + foreach ($simpleCaseExpression->simpleWhenClauses as $simpleWhenClause) { + $sql .= ' WHEN ' . $this->walkSimpleArithmeticExpression($simpleWhenClause->caseScalarExpression); + $sql .= ' THEN ' . $this->walkSimpleArithmeticExpression($simpleWhenClause->thenScalarExpression); + } + + $sql .= ' ELSE ' . $this->walkSimpleArithmeticExpression($simpleCaseExpression->elseScalarExpression) . ' END'; + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkSelectExpression($selectExpression) + { + $sql = ''; + $expr = $selectExpression->expression; + $hidden = $selectExpression->hiddenAliasResultVariable; + + switch (true) { + case ($expr instanceof AST\PathExpression): + if ($expr->type !== AST\PathExpression::TYPE_STATE_FIELD) { + throw QueryException::invalidPathExpression($expr); + } + + $fieldName = $expr->field; + $dqlAlias = $expr->identificationVariable; + $qComp = $this->queryComponents[$dqlAlias]; + $class = $qComp['metadata']; + + $resultAlias = $selectExpression->fieldIdentificationVariable ?: $fieldName; + $tableName = ($class->isInheritanceTypeJoined()) + ? $this->em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName) + : $class->getTableName(); + + $sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias); + $fieldMapping = $class->fieldMappings[$fieldName]; + $columnName = $this->quoteStrategy->getColumnName($fieldName, $class, $this->platform); + $columnAlias = $this->getSQLColumnAlias($fieldMapping['columnName']); + $col = $sqlTableAlias . '.' . $columnName; + + if (isset($fieldMapping['requireSQLConversion'])) { + $type = Type::getType($fieldMapping['type']); + $col = $type->convertToPHPValueSQL($col, $this->conn->getDatabasePlatform()); + } + + $sql .= $col . ' AS ' . $columnAlias; + + $this->scalarResultAliasMap[$resultAlias] = $columnAlias; + + if ( ! $hidden) { + $this->rsm->addScalarResult($columnAlias, $resultAlias, $fieldMapping['type']); + $this->scalarFields[$dqlAlias][$fieldName] = $columnAlias; + } + + break; + + case ($expr instanceof AST\AggregateExpression): + case ($expr instanceof AST\Functions\FunctionNode): + case ($expr instanceof AST\SimpleArithmeticExpression): + case ($expr instanceof AST\ArithmeticTerm): + case ($expr instanceof AST\ArithmeticFactor): + case ($expr instanceof AST\ParenthesisExpression): + case ($expr instanceof AST\Literal): + case ($expr instanceof AST\NullIfExpression): + case ($expr instanceof AST\CoalesceExpression): + case ($expr instanceof AST\GeneralCaseExpression): + case ($expr instanceof AST\SimpleCaseExpression): + $columnAlias = $this->getSQLColumnAlias('sclr'); + $resultAlias = $selectExpression->fieldIdentificationVariable ?: $this->scalarResultCounter++; + + $sql .= $expr->dispatch($this) . ' AS ' . $columnAlias; + + $this->scalarResultAliasMap[$resultAlias] = $columnAlias; + + if ( ! $hidden) { + // We cannot resolve field type here; assume 'string'. + $this->rsm->addScalarResult($columnAlias, $resultAlias, 'string'); + } + break; + + case ($expr instanceof AST\Subselect): + $columnAlias = $this->getSQLColumnAlias('sclr'); + $resultAlias = $selectExpression->fieldIdentificationVariable ?: $this->scalarResultCounter++; + + $sql .= '(' . $this->walkSubselect($expr) . ') AS ' . $columnAlias; + + $this->scalarResultAliasMap[$resultAlias] = $columnAlias; + + if ( ! $hidden) { + // We cannot resolve field type here; assume 'string'. + $this->rsm->addScalarResult($columnAlias, $resultAlias, 'string'); + } + break; + + case ($expr instanceof AST\NewObjectExpression): + $sql .= $this->walkNewObject($expr,$selectExpression->fieldIdentificationVariable); + break; + + default: + // IdentificationVariable or PartialObjectExpression + if ($expr instanceof AST\PartialObjectExpression) { + $dqlAlias = $expr->identificationVariable; + $partialFieldSet = $expr->partialFieldSet; + } else { + $dqlAlias = $expr; + $partialFieldSet = []; + } + + $queryComp = $this->queryComponents[$dqlAlias]; + $class = $queryComp['metadata']; + $resultAlias = $selectExpression->fieldIdentificationVariable ?: null; + + if ( ! isset($this->selectedClasses[$dqlAlias])) { + $this->selectedClasses[$dqlAlias] = [ + 'class' => $class, + 'dqlAlias' => $dqlAlias, + 'resultAlias' => $resultAlias + ]; + } + + $sqlParts = []; + + // Select all fields from the queried class + foreach ($class->fieldMappings as $fieldName => $mapping) { + if ($partialFieldSet && ! in_array($fieldName, $partialFieldSet)) { + continue; + } + + $tableName = (isset($mapping['inherited'])) + ? $this->em->getClassMetadata($mapping['inherited'])->getTableName() + : $class->getTableName(); + + $sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias); + $columnAlias = $this->getSQLColumnAlias($mapping['columnName']); + $quotedColumnName = $this->quoteStrategy->getColumnName($fieldName, $class, $this->platform); + + $col = $sqlTableAlias . '.' . $quotedColumnName; + + if (isset($mapping['requireSQLConversion'])) { + $type = Type::getType($mapping['type']); + $col = $type->convertToPHPValueSQL($col, $this->platform); + } + + $sqlParts[] = $col . ' AS '. $columnAlias; + + $this->scalarResultAliasMap[$resultAlias][] = $columnAlias; + + $this->rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name); + } + + // Add any additional fields of subclasses (excluding inherited fields) + // 1) on Single Table Inheritance: always, since its marginal overhead + // 2) on Class Table Inheritance only if partial objects are disallowed, + // since it requires outer joining subtables. + if ($class->isInheritanceTypeSingleTable() || ! $this->query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) { + foreach ($class->subClasses as $subClassName) { + $subClass = $this->em->getClassMetadata($subClassName); + $sqlTableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias); + + foreach ($subClass->fieldMappings as $fieldName => $mapping) { + if (isset($mapping['inherited']) || ($partialFieldSet && !in_array($fieldName, $partialFieldSet))) { + continue; + } + + $columnAlias = $this->getSQLColumnAlias($mapping['columnName']); + $quotedColumnName = $this->quoteStrategy->getColumnName($fieldName, $subClass, $this->platform); + + $col = $sqlTableAlias . '.' . $quotedColumnName; + + if (isset($mapping['requireSQLConversion'])) { + $type = Type::getType($mapping['type']); + $col = $type->convertToPHPValueSQL($col, $this->platform); + } + + $sqlParts[] = $col . ' AS ' . $columnAlias; + + $this->scalarResultAliasMap[$resultAlias][] = $columnAlias; + + $this->rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName); + } + } + } + + $sql .= implode(', ', $sqlParts); + } + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkQuantifiedExpression($qExpr) + { + return ' ' . strtoupper($qExpr->type) . '(' . $this->walkSubselect($qExpr->subselect) . ')'; + } + + /** + * {@inheritdoc} + */ + public function walkSubselect($subselect) + { + $useAliasesBefore = $this->useSqlTableAliases; + $rootAliasesBefore = $this->rootAliases; + + $this->rootAliases = []; // reset the rootAliases for the subselect + $this->useSqlTableAliases = true; + + $sql = $this->walkSimpleSelectClause($subselect->simpleSelectClause); + $sql .= $this->walkSubselectFromClause($subselect->subselectFromClause); + $sql .= $this->walkWhereClause($subselect->whereClause); + + $sql .= $subselect->groupByClause ? $this->walkGroupByClause($subselect->groupByClause) : ''; + $sql .= $subselect->havingClause ? $this->walkHavingClause($subselect->havingClause) : ''; + $sql .= $subselect->orderByClause ? $this->walkOrderByClause($subselect->orderByClause) : ''; + + $this->rootAliases = $rootAliasesBefore; // put the main aliases back + $this->useSqlTableAliases = $useAliasesBefore; + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkSubselectFromClause($subselectFromClause) + { + $identificationVarDecls = $subselectFromClause->identificationVariableDeclarations; + $sqlParts = []; + + foreach ($identificationVarDecls as $subselectIdVarDecl) { + $sqlParts[] = $this->walkIdentificationVariableDeclaration($subselectIdVarDecl); + } + + return ' FROM ' . implode(', ', $sqlParts); + } + + /** + * {@inheritdoc} + */ + public function walkSimpleSelectClause($simpleSelectClause) + { + return 'SELECT' . ($simpleSelectClause->isDistinct ? ' DISTINCT' : '') + . $this->walkSimpleSelectExpression($simpleSelectClause->simpleSelectExpression); + } + + /** + * @param \Doctrine\ORM\Query\AST\ParenthesisExpression $parenthesisExpression + * + * @return string. + */ + public function walkParenthesisExpression(AST\ParenthesisExpression $parenthesisExpression) + { + return sprintf('(%s)', $parenthesisExpression->expression->dispatch($this)); + } + + /** + * @param AST\NewObjectExpression $newObjectExpression + * @param null|string $newObjectResultAlias + * @return string The SQL. + */ + public function walkNewObject($newObjectExpression, $newObjectResultAlias=null) + { + $sqlSelectExpressions = []; + $objIndex = $newObjectResultAlias?:$this->newObjectCounter++; + + foreach ($newObjectExpression->args as $argIndex => $e) { + $resultAlias = $this->scalarResultCounter++; + $columnAlias = $this->getSQLColumnAlias('sclr'); + $fieldType = 'string'; + + switch (true) { + case ($e instanceof AST\NewObjectExpression): + $sqlSelectExpressions[] = $e->dispatch($this); + break; + + case ($e instanceof AST\Subselect): + $sqlSelectExpressions[] = '(' . $e->dispatch($this) . ') AS ' . $columnAlias; + break; + + case ($e instanceof AST\PathExpression): + $dqlAlias = $e->identificationVariable; + $qComp = $this->queryComponents[$dqlAlias]; + $class = $qComp['metadata']; + $fieldType = $class->fieldMappings[$e->field]['type']; + + $sqlSelectExpressions[] = trim($e->dispatch($this)) . ' AS ' . $columnAlias; + break; + + case ($e instanceof AST\Literal): + switch ($e->type) { + case AST\Literal::BOOLEAN: + $fieldType = 'boolean'; + break; + + case AST\Literal::NUMERIC: + $fieldType = is_float($e->value) ? 'float' : 'integer'; + break; + } + + $sqlSelectExpressions[] = trim($e->dispatch($this)) . ' AS ' . $columnAlias; + break; + + default: + $sqlSelectExpressions[] = trim($e->dispatch($this)) . ' AS ' . $columnAlias; + break; + } + + $this->scalarResultAliasMap[$resultAlias] = $columnAlias; + $this->rsm->addScalarResult($columnAlias, $resultAlias, $fieldType); + + $this->rsm->newObjectMappings[$columnAlias] = [ + 'className' => $newObjectExpression->className, + 'objIndex' => $objIndex, + 'argIndex' => $argIndex + ]; + } + + return implode(', ', $sqlSelectExpressions); + } + + /** + * {@inheritdoc} + */ + public function walkSimpleSelectExpression($simpleSelectExpression) + { + $expr = $simpleSelectExpression->expression; + $sql = ' '; + + switch (true) { + case ($expr instanceof AST\PathExpression): + $sql .= $this->walkPathExpression($expr); + break; + + case ($expr instanceof AST\Subselect): + $alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->scalarResultCounter++; + + $columnAlias = 'sclr' . $this->aliasCounter++; + $this->scalarResultAliasMap[$alias] = $columnAlias; + + $sql .= '(' . $this->walkSubselect($expr) . ') AS ' . $columnAlias; + break; + + case ($expr instanceof AST\Functions\FunctionNode): + case ($expr instanceof AST\SimpleArithmeticExpression): + case ($expr instanceof AST\ArithmeticTerm): + case ($expr instanceof AST\ArithmeticFactor): + case ($expr instanceof AST\Literal): + case ($expr instanceof AST\NullIfExpression): + case ($expr instanceof AST\CoalesceExpression): + case ($expr instanceof AST\GeneralCaseExpression): + case ($expr instanceof AST\SimpleCaseExpression): + $alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->scalarResultCounter++; + + $columnAlias = $this->getSQLColumnAlias('sclr'); + $this->scalarResultAliasMap[$alias] = $columnAlias; + + $sql .= $expr->dispatch($this) . ' AS ' . $columnAlias; + break; + + case ($expr instanceof AST\ParenthesisExpression): + $sql .= $this->walkParenthesisExpression($expr); + break; + + default: // IdentificationVariable + $sql .= $this->walkEntityIdentificationVariable($expr); + break; + } + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkAggregateExpression($aggExpression) + { + return $aggExpression->functionName . '(' . ($aggExpression->isDistinct ? 'DISTINCT ' : '') + . $this->walkSimpleArithmeticExpression($aggExpression->pathExpression) . ')'; + } + + /** + * {@inheritdoc} + */ + public function walkGroupByClause($groupByClause) + { + $sqlParts = []; + + foreach ($groupByClause->groupByItems as $groupByItem) { + $sqlParts[] = $this->walkGroupByItem($groupByItem); + } + + return ' GROUP BY ' . implode(', ', $sqlParts); + } + + /** + * {@inheritdoc} + */ + public function walkGroupByItem($groupByItem) + { + // StateFieldPathExpression + if ( ! is_string($groupByItem)) { + return $this->walkPathExpression($groupByItem); + } + + // ResultVariable + if (isset($this->queryComponents[$groupByItem]['resultVariable'])) { + $resultVariable = $this->queryComponents[$groupByItem]['resultVariable']; + + if ($resultVariable instanceof AST\PathExpression) { + return $this->walkPathExpression($resultVariable); + } + + if (isset($resultVariable->pathExpression)) { + return $this->walkPathExpression($resultVariable->pathExpression); + } + + return $this->walkResultVariable($groupByItem); + } + + // IdentificationVariable + $sqlParts = []; + + foreach ($this->queryComponents[$groupByItem]['metadata']->fieldNames as $field) { + $item = new AST\PathExpression(AST\PathExpression::TYPE_STATE_FIELD, $groupByItem, $field); + $item->type = AST\PathExpression::TYPE_STATE_FIELD; + + $sqlParts[] = $this->walkPathExpression($item); + } + + foreach ($this->queryComponents[$groupByItem]['metadata']->associationMappings as $mapping) { + if ($mapping['isOwningSide'] && $mapping['type'] & ClassMetadataInfo::TO_ONE) { + $item = new AST\PathExpression(AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $groupByItem, $mapping['fieldName']); + $item->type = AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION; + + $sqlParts[] = $this->walkPathExpression($item); + } + } + + return implode(', ', $sqlParts); + } + + /** + * {@inheritdoc} + */ + public function walkDeleteClause(AST\DeleteClause $deleteClause) + { + $class = $this->em->getClassMetadata($deleteClause->abstractSchemaName); + $tableName = $class->getTableName(); + $sql = 'DELETE FROM ' . $this->quoteStrategy->getTableName($class, $this->platform); + + $this->setSQLTableAlias($tableName, $tableName, $deleteClause->aliasIdentificationVariable); + $this->rootAliases[] = $deleteClause->aliasIdentificationVariable; + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkUpdateClause($updateClause) + { + $class = $this->em->getClassMetadata($updateClause->abstractSchemaName); + $tableName = $class->getTableName(); + $sql = 'UPDATE ' . $this->quoteStrategy->getTableName($class, $this->platform); + + $this->setSQLTableAlias($tableName, $tableName, $updateClause->aliasIdentificationVariable); + $this->rootAliases[] = $updateClause->aliasIdentificationVariable; + + $sql .= ' SET ' . implode(', ', array_map([$this, 'walkUpdateItem'], $updateClause->updateItems)); + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkUpdateItem($updateItem) + { + $useTableAliasesBefore = $this->useSqlTableAliases; + $this->useSqlTableAliases = false; + + $sql = $this->walkPathExpression($updateItem->pathExpression) . ' = '; + $newValue = $updateItem->newValue; + + switch (true) { + case ($newValue instanceof AST\Node): + $sql .= $newValue->dispatch($this); + break; + + case ($newValue === null): + $sql .= 'NULL'; + break; + + default: + $sql .= $this->conn->quote($newValue); + break; + } + + $this->useSqlTableAliases = $useTableAliasesBefore; + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkWhereClause($whereClause) + { + $condSql = null !== $whereClause ? $this->walkConditionalExpression($whereClause->conditionalExpression) : ''; + $discrSql = $this->_generateDiscriminatorColumnConditionSQL($this->rootAliases); + + if ($this->em->hasFilters()) { + $filterClauses = []; + foreach ($this->rootAliases as $dqlAlias) { + $class = $this->queryComponents[$dqlAlias]['metadata']; + $tableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias); + + if ($filterExpr = $this->generateFilterConditionSQL($class, $tableAlias)) { + $filterClauses[] = $filterExpr; + } + } + + if (count($filterClauses)) { + if ($condSql) { + $condSql = '(' . $condSql . ') AND '; + } + + $condSql .= implode(' AND ', $filterClauses); + } + } + + if ($condSql) { + return ' WHERE ' . (( ! $discrSql) ? $condSql : '(' . $condSql . ') AND ' . $discrSql); + } + + if ($discrSql) { + return ' WHERE ' . $discrSql; + } + + return ''; + } + + /** + * {@inheritdoc} + */ + public function walkConditionalExpression($condExpr) + { + // Phase 2 AST optimization: Skip processing of ConditionalExpression + // if only one ConditionalTerm is defined + if ( ! ($condExpr instanceof AST\ConditionalExpression)) { + return $this->walkConditionalTerm($condExpr); + } + + return implode(' OR ', array_map([$this, 'walkConditionalTerm'], $condExpr->conditionalTerms)); + } + + /** + * {@inheritdoc} + */ + public function walkConditionalTerm($condTerm) + { + // Phase 2 AST optimization: Skip processing of ConditionalTerm + // if only one ConditionalFactor is defined + if ( ! ($condTerm instanceof AST\ConditionalTerm)) { + return $this->walkConditionalFactor($condTerm); + } + + return implode(' AND ', array_map([$this, 'walkConditionalFactor'], $condTerm->conditionalFactors)); + } + + /** + * {@inheritdoc} + */ + public function walkConditionalFactor($factor) + { + // Phase 2 AST optimization: Skip processing of ConditionalFactor + // if only one ConditionalPrimary is defined + return ( ! ($factor instanceof AST\ConditionalFactor)) + ? $this->walkConditionalPrimary($factor) + : ($factor->not ? 'NOT ' : '') . $this->walkConditionalPrimary($factor->conditionalPrimary); + } + + /** + * {@inheritdoc} + */ + public function walkConditionalPrimary($primary) + { + if ($primary->isSimpleConditionalExpression()) { + return $primary->simpleConditionalExpression->dispatch($this); + } + + if ($primary->isConditionalExpression()) { + $condExpr = $primary->conditionalExpression; + + return '(' . $this->walkConditionalExpression($condExpr) . ')'; + } + } + + /** + * {@inheritdoc} + */ + public function walkExistsExpression($existsExpr) + { + $sql = ($existsExpr->not) ? 'NOT ' : ''; + + $sql .= 'EXISTS (' . $this->walkSubselect($existsExpr->subselect) . ')'; + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkCollectionMemberExpression($collMemberExpr) + { + $sql = $collMemberExpr->not ? 'NOT ' : ''; + $sql .= 'EXISTS (SELECT 1 FROM '; + + $entityExpr = $collMemberExpr->entityExpression; + $collPathExpr = $collMemberExpr->collectionValuedPathExpression; + + $fieldName = $collPathExpr->field; + $dqlAlias = $collPathExpr->identificationVariable; + + $class = $this->queryComponents[$dqlAlias]['metadata']; + + switch (true) { + // InputParameter + case ($entityExpr instanceof AST\InputParameter): + $dqlParamKey = $entityExpr->name; + $entitySql = '?'; + break; + + // SingleValuedAssociationPathExpression | IdentificationVariable + case ($entityExpr instanceof AST\PathExpression): + $entitySql = $this->walkPathExpression($entityExpr); + break; + + default: + throw new \BadMethodCallException("Not implemented"); + } + + $assoc = $class->associationMappings[$fieldName]; + + if ($assoc['type'] == ClassMetadata::ONE_TO_MANY) { + $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); + $targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName()); + $sourceTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias); + + $sql .= $this->quoteStrategy->getTableName($targetClass, $this->platform) . ' ' . $targetTableAlias . ' WHERE '; + + $owningAssoc = $targetClass->associationMappings[$assoc['mappedBy']]; + $sqlParts = []; + + foreach ($owningAssoc['targetToSourceKeyColumns'] as $targetColumn => $sourceColumn) { + $targetColumn = $this->quoteStrategy->getColumnName($class->fieldNames[$targetColumn], $class, $this->platform); + + $sqlParts[] = $sourceTableAlias . '.' . $targetColumn . ' = ' . $targetTableAlias . '.' . $sourceColumn; + } + + foreach ($this->quoteStrategy->getIdentifierColumnNames($targetClass, $this->platform) as $targetColumnName) { + if (isset($dqlParamKey)) { + $this->parserResult->addParameterMapping($dqlParamKey, $this->sqlParamIndex++); + } + + $sqlParts[] = $targetTableAlias . '.' . $targetColumnName . ' = ' . $entitySql; + } + + $sql .= implode(' AND ', $sqlParts); + } else { // many-to-many + $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); + + $owningAssoc = $assoc['isOwningSide'] ? $assoc : $targetClass->associationMappings[$assoc['mappedBy']]; + $joinTable = $owningAssoc['joinTable']; + + // SQL table aliases + $joinTableAlias = $this->getSQLTableAlias($joinTable['name']); + $targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName()); + $sourceTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias); + + // join to target table + $sql .= $this->quoteStrategy->getJoinTableName($owningAssoc, $targetClass, $this->platform) . ' ' . $joinTableAlias + . ' INNER JOIN ' . $this->quoteStrategy->getTableName($targetClass, $this->platform) . ' ' . $targetTableAlias . ' ON '; + + // join conditions + $joinColumns = $assoc['isOwningSide'] ? $joinTable['inverseJoinColumns'] : $joinTable['joinColumns']; + $joinSqlParts = []; + + foreach ($joinColumns as $joinColumn) { + $targetColumn = $this->quoteStrategy->getColumnName($targetClass->fieldNames[$joinColumn['referencedColumnName']], $targetClass, $this->platform); + + $joinSqlParts[] = $joinTableAlias . '.' . $joinColumn['name'] . ' = ' . $targetTableAlias . '.' . $targetColumn; + } + + $sql .= implode(' AND ', $joinSqlParts); + $sql .= ' WHERE '; + + $joinColumns = $assoc['isOwningSide'] ? $joinTable['joinColumns'] : $joinTable['inverseJoinColumns']; + $sqlParts = []; + + foreach ($joinColumns as $joinColumn) { + $targetColumn = $this->quoteStrategy->getColumnName($class->fieldNames[$joinColumn['referencedColumnName']], $class, $this->platform); + + $sqlParts[] = $joinTableAlias . '.' . $joinColumn['name'] . ' = ' . $sourceTableAlias . '.' . $targetColumn; + } + + foreach ($this->quoteStrategy->getIdentifierColumnNames($targetClass, $this->platform) as $targetColumnName) { + if (isset($dqlParamKey)) { + $this->parserResult->addParameterMapping($dqlParamKey, $this->sqlParamIndex++); + } + + $sqlParts[] = $targetTableAlias . '.' . $targetColumnName . ' IN (' . $entitySql . ')'; + } + + $sql .= implode(' AND ', $sqlParts); + } + + return $sql . ')'; + } + + /** + * {@inheritdoc} + */ + public function walkEmptyCollectionComparisonExpression($emptyCollCompExpr) + { + $sizeFunc = new AST\Functions\SizeFunction('size'); + $sizeFunc->collectionPathExpression = $emptyCollCompExpr->expression; + + return $sizeFunc->getSql($this) . ($emptyCollCompExpr->not ? ' > 0' : ' = 0'); + } + + /** + * {@inheritdoc} + */ + public function walkNullComparisonExpression($nullCompExpr) + { + $expression = $nullCompExpr->expression; + $comparison = ' IS' . ($nullCompExpr->not ? ' NOT' : '') . ' NULL'; + + // Handle ResultVariable + if (is_string($expression) && isset($this->queryComponents[$expression]['resultVariable'])) { + return $this->walkResultVariable($expression) . $comparison; + } + + // Handle InputParameter mapping inclusion to ParserResult + if ($expression instanceof AST\InputParameter) { + return $this->walkInputParameter($expression) . $comparison; + } + + return $expression->dispatch($this) . $comparison; + } + + /** + * {@inheritdoc} + */ + public function walkInExpression($inExpr) + { + $sql = $this->walkArithmeticExpression($inExpr->expression) . ($inExpr->not ? ' NOT' : '') . ' IN ('; + + $sql .= ($inExpr->subselect) + ? $this->walkSubselect($inExpr->subselect) + : implode(', ', array_map([$this, 'walkInParameter'], $inExpr->literals)); + + $sql .= ')'; + + return $sql; + } + + /** + * {@inheritdoc} + * @throws \Doctrine\ORM\Query\QueryException + */ + public function walkInstanceOfExpression($instanceOfExpr) + { + $sql = ''; + + $dqlAlias = $instanceOfExpr->identificationVariable; + $discrClass = $class = $this->queryComponents[$dqlAlias]['metadata']; + + if ($class->discriminatorColumn) { + $discrClass = $this->em->getClassMetadata($class->rootEntityName); + } + + if ($this->useSqlTableAliases) { + $sql .= $this->getSQLTableAlias($discrClass->getTableName(), $dqlAlias) . '.'; + } + + $sql .= $class->discriminatorColumn['name'] . ($instanceOfExpr->not ? ' NOT IN ' : ' IN '); + $sql .= $this->getChildDiscriminatorsFromClassMetadata($discrClass, $instanceOfExpr); + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkInParameter($inParam) + { + return $inParam instanceof AST\InputParameter + ? $this->walkInputParameter($inParam) + : $this->walkLiteral($inParam); + } + + /** + * {@inheritdoc} + */ + public function walkLiteral($literal) + { + switch ($literal->type) { + case AST\Literal::STRING: + return $this->conn->quote($literal->value); + + case AST\Literal::BOOLEAN: + return $this->conn->getDatabasePlatform()->convertBooleans('true' === strtolower($literal->value)); + + case AST\Literal::NUMERIC: + return $literal->value; + + default: + throw QueryException::invalidLiteral($literal); + } + } + + /** + * {@inheritdoc} + */ + public function walkBetweenExpression($betweenExpr) + { + $sql = $this->walkArithmeticExpression($betweenExpr->expression); + + if ($betweenExpr->not) { + $sql .= ' NOT'; + } + + $sql .= ' BETWEEN ' . $this->walkArithmeticExpression($betweenExpr->leftBetweenExpression) + . ' AND ' . $this->walkArithmeticExpression($betweenExpr->rightBetweenExpression); + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkLikeExpression($likeExpr) + { + $stringExpr = $likeExpr->stringExpression; + $leftExpr = (is_string($stringExpr) && isset($this->queryComponents[$stringExpr]['resultVariable'])) + ? $this->walkResultVariable($stringExpr) + : $stringExpr->dispatch($this); + + $sql = $leftExpr . ($likeExpr->not ? ' NOT' : '') . ' LIKE '; + + if ($likeExpr->stringPattern instanceof AST\InputParameter) { + $sql .= $this->walkInputParameter($likeExpr->stringPattern); + } elseif ($likeExpr->stringPattern instanceof AST\Functions\FunctionNode) { + $sql .= $this->walkFunction($likeExpr->stringPattern); + } elseif ($likeExpr->stringPattern instanceof AST\PathExpression) { + $sql .= $this->walkPathExpression($likeExpr->stringPattern); + } else { + $sql .= $this->walkLiteral($likeExpr->stringPattern); + } + + if ($likeExpr->escapeChar) { + $sql .= ' ESCAPE ' . $this->walkLiteral($likeExpr->escapeChar); + } + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkStateFieldPathExpression($stateFieldPathExpression) + { + return $this->walkPathExpression($stateFieldPathExpression); + } + + /** + * {@inheritdoc} + */ + public function walkComparisonExpression($compExpr) + { + $leftExpr = $compExpr->leftExpression; + $rightExpr = $compExpr->rightExpression; + $sql = ''; + + $sql .= ($leftExpr instanceof AST\Node) + ? $leftExpr->dispatch($this) + : (is_numeric($leftExpr) ? $leftExpr : $this->conn->quote($leftExpr)); + + $sql .= ' ' . $compExpr->operator . ' '; + + $sql .= ($rightExpr instanceof AST\Node) + ? $rightExpr->dispatch($this) + : (is_numeric($rightExpr) ? $rightExpr : $this->conn->quote($rightExpr)); + + return $sql; + } + + /** + * {@inheritdoc} + */ + public function walkInputParameter($inputParam) + { + $this->parserResult->addParameterMapping($inputParam->name, $this->sqlParamIndex++); + + $parameter = $this->query->getParameter($inputParam->name); + + if ($parameter && Type::hasType($type = $parameter->getType())) { + return Type::getType($type)->convertToDatabaseValueSQL('?', $this->platform); + } + + return '?'; + } + + /** + * {@inheritdoc} + */ + public function walkArithmeticExpression($arithmeticExpr) + { + return ($arithmeticExpr->isSimpleArithmeticExpression()) + ? $this->walkSimpleArithmeticExpression($arithmeticExpr->simpleArithmeticExpression) + : '(' . $this->walkSubselect($arithmeticExpr->subselect) . ')'; + } + + /** + * {@inheritdoc} + */ + public function walkSimpleArithmeticExpression($simpleArithmeticExpr) + { + if ( ! ($simpleArithmeticExpr instanceof AST\SimpleArithmeticExpression)) { + return $this->walkArithmeticTerm($simpleArithmeticExpr); + } + + return implode(' ', array_map([$this, 'walkArithmeticTerm'], $simpleArithmeticExpr->arithmeticTerms)); + } + + /** + * {@inheritdoc} + */ + public function walkArithmeticTerm($term) + { + if (is_string($term)) { + return (isset($this->queryComponents[$term])) + ? $this->walkResultVariable($this->queryComponents[$term]['token']['value']) + : $term; + } + + // Phase 2 AST optimization: Skip processing of ArithmeticTerm + // if only one ArithmeticFactor is defined + if ( ! ($term instanceof AST\ArithmeticTerm)) { + return $this->walkArithmeticFactor($term); + } + + return implode(' ', array_map([$this, 'walkArithmeticFactor'], $term->arithmeticFactors)); + } + + /** + * {@inheritdoc} + */ + public function walkArithmeticFactor($factor) + { + if (is_string($factor)) { + return (isset($this->queryComponents[$factor])) + ? $this->walkResultVariable($this->queryComponents[$factor]['token']['value']) + : $factor; + } + + // Phase 2 AST optimization: Skip processing of ArithmeticFactor + // if only one ArithmeticPrimary is defined + if ( ! ($factor instanceof AST\ArithmeticFactor)) { + return $this->walkArithmeticPrimary($factor); + } + + $sign = $factor->isNegativeSigned() ? '-' : ($factor->isPositiveSigned() ? '+' : ''); + + return $sign . $this->walkArithmeticPrimary($factor->arithmeticPrimary); + } + + /** + * Walks down an ArithmeticPrimary that represents an AST node, thereby generating the appropriate SQL. + * + * @param mixed $primary + * + * @return string The SQL. + */ + public function walkArithmeticPrimary($primary) + { + if ($primary instanceof AST\SimpleArithmeticExpression) { + return '(' . $this->walkSimpleArithmeticExpression($primary) . ')'; + } + + if ($primary instanceof AST\Node) { + return $primary->dispatch($this); + } + + return $this->walkEntityIdentificationVariable($primary); + } + + /** + * {@inheritdoc} + */ + public function walkStringPrimary($stringPrimary) + { + return (is_string($stringPrimary)) + ? $this->conn->quote($stringPrimary) + : $stringPrimary->dispatch($this); + } + + /** + * {@inheritdoc} + */ + public function walkResultVariable($resultVariable) + { + $resultAlias = $this->scalarResultAliasMap[$resultVariable]; + + if (is_array($resultAlias)) { + return implode(', ', $resultAlias); + } + + return $resultAlias; + } + + /** + * @param ClassMetadataInfo $rootClass + * @param AST\InstanceOfExpression $instanceOfExpr + * @return string The list in parentheses of valid child discriminators from the given class + * @throws QueryException + */ + private function getChildDiscriminatorsFromClassMetadata(ClassMetadataInfo $rootClass, AST\InstanceOfExpression $instanceOfExpr): string + { + $sqlParameterList = []; + $discriminators = []; + foreach ($instanceOfExpr->value as $parameter) { + if ($parameter instanceof AST\InputParameter) { + $this->rsm->discriminatorParameters[$parameter->name] = $parameter->name; + $sqlParameterList[] = $this->walkInParameter($parameter); + continue; + } + + $metadata = $this->em->getClassMetadata($parameter); + + if ($metadata->getName() !== $rootClass->name && ! $metadata->getReflectionClass()->isSubclassOf($rootClass->name)) { + throw QueryException::instanceOfUnrelatedClass($parameter, $rootClass->name); + } + + $discriminators += HierarchyDiscriminatorResolver::resolveDiscriminatorsForClass($metadata, $this->em); + } + + foreach (array_keys($discriminators) as $dis) { + $sqlParameterList[] = $this->conn->quote($dis); + } + + return '(' . implode(', ', $sqlParameterList) . ')'; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalker.php new file mode 100644 index 0000000..9ddd86b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalker.php @@ -0,0 +1,479 @@ +. + */ + +namespace Doctrine\ORM\Query; + +/** + * Interface for walkers of DQL ASTs (abstract syntax trees). + * + * @author Roman Borschel + * @since 2.0 + */ +interface TreeWalker +{ + /** + * Initializes TreeWalker with important information about the ASTs to be walked. + * + * @param \Doctrine\ORM\AbstractQuery $query The parsed Query. + * @param \Doctrine\ORM\Query\ParserResult $parserResult The result of the parsing process. + * @param array $queryComponents The query components (symbol table). + */ + public function __construct($query, $parserResult, array $queryComponents); + + /** + * Returns internal queryComponents array. + * + * @return array + */ + public function getQueryComponents(); + + /** + * Sets or overrides a query component for a given dql alias. + * + * @param string $dqlAlias The DQL alias. + * @param array $queryComponent + * + * @return void + */ + public function setQueryComponent($dqlAlias, array $queryComponent); + + /** + * Walks down a SelectStatement AST node, thereby generating the appropriate SQL. + * + * @param AST\SelectStatement $AST + * + * @return string The SQL. + */ + function walkSelectStatement(AST\SelectStatement $AST); + + /** + * Walks down a SelectClause AST node, thereby generating the appropriate SQL. + * + * @param AST\SelectClause $selectClause + * + * @return string The SQL. + */ + function walkSelectClause($selectClause); + + /** + * Walks down a FromClause AST node, thereby generating the appropriate SQL. + * + * @param AST\FromClause $fromClause + * + * @return string The SQL. + */ + function walkFromClause($fromClause); + + /** + * Walks down a FunctionNode AST node, thereby generating the appropriate SQL. + * + * @param AST\Functions\FunctionNode $function + * + * @return string The SQL. + */ + function walkFunction($function); + + /** + * Walks down an OrderByClause AST node, thereby generating the appropriate SQL. + * + * @param AST\OrderByClause $orderByClause + * + * @return string The SQL. + */ + function walkOrderByClause($orderByClause); + + /** + * Walks down an OrderByItem AST node, thereby generating the appropriate SQL. + * + * @param AST\OrderByItem $orderByItem + * + * @return string The SQL. + */ + function walkOrderByItem($orderByItem); + + /** + * Walks down a HavingClause AST node, thereby generating the appropriate SQL. + * + * @param AST\HavingClause $havingClause + * + * @return string The SQL. + */ + function walkHavingClause($havingClause); + + /** + * Walks down a Join AST node and creates the corresponding SQL. + * + * @param AST\Join $join + * + * @return string The SQL. + */ + function walkJoin($join); + + /** + * Walks down a SelectExpression AST node and generates the corresponding SQL. + * + * @param AST\SelectExpression $selectExpression + * + * @return string The SQL. + */ + function walkSelectExpression($selectExpression); + + /** + * Walks down a QuantifiedExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\QuantifiedExpression $qExpr + * + * @return string The SQL. + */ + function walkQuantifiedExpression($qExpr); + + /** + * Walks down a Subselect AST node, thereby generating the appropriate SQL. + * + * @param AST\Subselect $subselect + * + * @return string The SQL. + */ + function walkSubselect($subselect); + + /** + * Walks down a SubselectFromClause AST node, thereby generating the appropriate SQL. + * + * @param AST\SubselectFromClause $subselectFromClause + * + * @return string The SQL. + */ + function walkSubselectFromClause($subselectFromClause); + + /** + * Walks down a SimpleSelectClause AST node, thereby generating the appropriate SQL. + * + * @param AST\SimpleSelectClause $simpleSelectClause + * + * @return string The SQL. + */ + function walkSimpleSelectClause($simpleSelectClause); + + /** + * Walks down a SimpleSelectExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\SimpleSelectExpression $simpleSelectExpression + * + * @return string The SQL. + */ + function walkSimpleSelectExpression($simpleSelectExpression); + + /** + * Walks down an AggregateExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\AggregateExpression $aggExpression + * + * @return string The SQL. + */ + function walkAggregateExpression($aggExpression); + + /** + * Walks down a GroupByClause AST node, thereby generating the appropriate SQL. + * + * @param AST\GroupByClause $groupByClause + * + * @return string The SQL. + */ + function walkGroupByClause($groupByClause); + + /** + * Walks down a GroupByItem AST node, thereby generating the appropriate SQL. + * + * @param AST\PathExpression|string $groupByItem + * + * @return string The SQL. + */ + function walkGroupByItem($groupByItem); + + /** + * Walks down an UpdateStatement AST node, thereby generating the appropriate SQL. + * + * @param AST\UpdateStatement $AST + * + * @return string The SQL. + */ + function walkUpdateStatement(AST\UpdateStatement $AST); + + /** + * Walks down a DeleteStatement AST node, thereby generating the appropriate SQL. + * + * @param AST\DeleteStatement $AST + * + * @return string The SQL. + */ + function walkDeleteStatement(AST\DeleteStatement $AST); + + /** + * Walks down a DeleteClause AST node, thereby generating the appropriate SQL. + * + * @param AST\DeleteClause $deleteClause + * + * @return string The SQL. + */ + function walkDeleteClause(AST\DeleteClause $deleteClause); + + /** + * Walks down an UpdateClause AST node, thereby generating the appropriate SQL. + * + * @param AST\UpdateClause $updateClause + * + * @return string The SQL. + */ + function walkUpdateClause($updateClause); + + /** + * Walks down an UpdateItem AST node, thereby generating the appropriate SQL. + * + * @param AST\UpdateItem $updateItem + * + * @return string The SQL. + */ + function walkUpdateItem($updateItem); + + /** + * Walks down a WhereClause AST node, thereby generating the appropriate SQL. + * WhereClause or not, the appropriate discriminator sql is added. + * + * @param AST\WhereClause $whereClause + * + * @return string The SQL. + */ + function walkWhereClause($whereClause); + + /** + * Walk down a ConditionalExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\ConditionalExpression $condExpr + * + * @return string The SQL. + */ + function walkConditionalExpression($condExpr); + + /** + * Walks down a ConditionalTerm AST node, thereby generating the appropriate SQL. + * + * @param AST\ConditionalTerm $condTerm + * + * @return string The SQL. + */ + function walkConditionalTerm($condTerm); + + /** + * Walks down a ConditionalFactor AST node, thereby generating the appropriate SQL. + * + * @param AST\ConditionalFactor $factor + * + * @return string The SQL. + */ + function walkConditionalFactor($factor); + + /** + * Walks down a ConditionalPrimary AST node, thereby generating the appropriate SQL. + * + * @param AST\ConditionalPrimary $primary + * + * @return string The SQL. + */ + function walkConditionalPrimary($primary); + + /** + * Walks down an ExistsExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\ExistsExpression $existsExpr + * + * @return string The SQL. + */ + function walkExistsExpression($existsExpr); + + /** + * Walks down a CollectionMemberExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\CollectionMemberExpression $collMemberExpr + * + * @return string The SQL. + */ + function walkCollectionMemberExpression($collMemberExpr); + + /** + * Walks down an EmptyCollectionComparisonExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\EmptyCollectionComparisonExpression $emptyCollCompExpr + * + * @return string The SQL. + */ + function walkEmptyCollectionComparisonExpression($emptyCollCompExpr); + + /** + * Walks down a NullComparisonExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\NullComparisonExpression $nullCompExpr + * + * @return string The SQL. + */ + function walkNullComparisonExpression($nullCompExpr); + + /** + * Walks down an InExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\InExpression $inExpr + * + * @return string The SQL. + */ + function walkInExpression($inExpr); + + /** + * Walks down an InstanceOfExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\InstanceOfExpression $instanceOfExpr + * + * @return string The SQL. + */ + function walkInstanceOfExpression($instanceOfExpr); + + /** + * Walks down a literal that represents an AST node, thereby generating the appropriate SQL. + * + * @param mixed $literal + * + * @return string The SQL. + */ + function walkLiteral($literal); + + /** + * Walks down a BetweenExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\BetweenExpression $betweenExpr + * + * @return string The SQL. + */ + function walkBetweenExpression($betweenExpr); + + /** + * Walks down a LikeExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\LikeExpression $likeExpr + * + * @return string The SQL. + */ + function walkLikeExpression($likeExpr); + + /** + * Walks down a StateFieldPathExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\PathExpression $stateFieldPathExpression + * + * @return string The SQL. + */ + function walkStateFieldPathExpression($stateFieldPathExpression); + + /** + * Walks down a ComparisonExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\ComparisonExpression $compExpr + * + * @return string The SQL. + */ + function walkComparisonExpression($compExpr); + + /** + * Walks down an InputParameter AST node, thereby generating the appropriate SQL. + * + * @param AST\InputParameter $inputParam + * + * @return string The SQL. + */ + function walkInputParameter($inputParam); + + /** + * Walks down an ArithmeticExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\ArithmeticExpression $arithmeticExpr + * + * @return string The SQL. + */ + function walkArithmeticExpression($arithmeticExpr); + + /** + * Walks down an ArithmeticTerm AST node, thereby generating the appropriate SQL. + * + * @param mixed $term + * + * @return string The SQL. + */ + function walkArithmeticTerm($term); + + /** + * Walks down a StringPrimary that represents an AST node, thereby generating the appropriate SQL. + * + * @param mixed $stringPrimary + * + * @return string The SQL. + */ + function walkStringPrimary($stringPrimary); + + /** + * Walks down an ArithmeticFactor that represents an AST node, thereby generating the appropriate SQL. + * + * @param mixed $factor + * + * @return string The SQL. + */ + function walkArithmeticFactor($factor); + + /** + * Walks down an SimpleArithmeticExpression AST node, thereby generating the appropriate SQL. + * + * @param AST\SimpleArithmeticExpression $simpleArithmeticExpr + * + * @return string The SQL. + */ + function walkSimpleArithmeticExpression($simpleArithmeticExpr); + + /** + * Walks down a PathExpression AST node, thereby generating the appropriate SQL. + * + * @param mixed $pathExpr + * + * @return string The SQL. + */ + function walkPathExpression($pathExpr); + + /** + * Walks down a ResultVariable that represents an AST node, thereby generating the appropriate SQL. + * + * @param string $resultVariable + * + * @return string The SQL. + */ + function walkResultVariable($resultVariable); + + /** + * Gets an executor that can be used to execute the result of this walker. + * + * @param AST\DeleteStatement|AST\UpdateStatement|AST\SelectStatement $AST + * + * @return Exec\AbstractSqlExecutor + */ + function getExecutor($AST); +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerAdapter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerAdapter.php new file mode 100644 index 0000000..deee03a --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerAdapter.php @@ -0,0 +1,440 @@ +. + */ + +namespace Doctrine\ORM\Query; + +/** + * An adapter implementation of the TreeWalker interface. The methods in this class + * are empty. This class exists as convenience for creating tree walkers. + * + * @author Roman Borschel + * @since 2.0 + */ +abstract class TreeWalkerAdapter implements TreeWalker +{ + /** + * The original Query. + * + * @var \Doctrine\ORM\AbstractQuery + */ + private $_query; + + /** + * The ParserResult of the original query that was produced by the Parser. + * + * @var \Doctrine\ORM\Query\ParserResult + */ + private $_parserResult; + + /** + * The query components of the original query (the "symbol table") that was produced by the Parser. + * + * @var array + */ + private $_queryComponents; + + /** + * {@inheritdoc} + */ + public function __construct($query, $parserResult, array $queryComponents) + { + $this->_query = $query; + $this->_parserResult = $parserResult; + $this->_queryComponents = $queryComponents; + } + + /** + * {@inheritdoc} + */ + public function getQueryComponents() + { + return $this->_queryComponents; + } + + /** + * {@inheritdoc} + */ + public function setQueryComponent($dqlAlias, array $queryComponent) + { + $requiredKeys = ['metadata', 'parent', 'relation', 'map', 'nestingLevel', 'token']; + + if (array_diff($requiredKeys, array_keys($queryComponent))) { + throw QueryException::invalidQueryComponent($dqlAlias); + } + + $this->_queryComponents[$dqlAlias] = $queryComponent; + } + + /** + * @return array + */ + protected function _getQueryComponents() + { + return $this->_queryComponents; + } + + /** + * Retrieves the Query Instance responsible for the current walkers execution. + * + * @return \Doctrine\ORM\AbstractQuery + */ + protected function _getQuery() + { + return $this->_query; + } + + /** + * Retrieves the ParserResult. + * + * @return \Doctrine\ORM\Query\ParserResult + */ + protected function _getParserResult() + { + return $this->_parserResult; + } + + /** + * {@inheritdoc} + */ + public function walkSelectStatement(AST\SelectStatement $AST) + { + } + + /** + * {@inheritdoc} + */ + public function walkSelectClause($selectClause) + { + } + + /** + * {@inheritdoc} + */ + public function walkFromClause($fromClause) + { + } + + /** + * {@inheritdoc} + */ + public function walkFunction($function) + { + } + + /** + * {@inheritdoc} + */ + public function walkOrderByClause($orderByClause) + { + } + + /** + * {@inheritdoc} + */ + public function walkOrderByItem($orderByItem) + { + } + + /** + * {@inheritdoc} + */ + public function walkHavingClause($havingClause) + { + } + + /** + * {@inheritdoc} + */ + public function walkJoin($join) + { + } + + /** + * {@inheritdoc} + */ + public function walkSelectExpression($selectExpression) + { + } + + /** + * {@inheritdoc} + */ + public function walkQuantifiedExpression($qExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkSubselect($subselect) + { + } + + /** + * {@inheritdoc} + */ + public function walkSubselectFromClause($subselectFromClause) + { + } + + /** + * {@inheritdoc} + */ + public function walkSimpleSelectClause($simpleSelectClause) + { + } + + /** + * {@inheritdoc} + */ + public function walkSimpleSelectExpression($simpleSelectExpression) + { + } + + /** + * {@inheritdoc} + */ + public function walkAggregateExpression($aggExpression) + { + } + + /** + * {@inheritdoc} + */ + public function walkGroupByClause($groupByClause) + { + } + + /** + * {@inheritdoc} + */ + public function walkGroupByItem($groupByItem) + { + } + + /** + * {@inheritdoc} + */ + public function walkUpdateStatement(AST\UpdateStatement $AST) + { + } + + /** + * {@inheritdoc} + */ + public function walkDeleteStatement(AST\DeleteStatement $AST) + { + } + + /** + * {@inheritdoc} + */ + public function walkDeleteClause(AST\DeleteClause $deleteClause) + { + } + + /** + * {@inheritdoc} + */ + public function walkUpdateClause($updateClause) + { + } + + /** + * {@inheritdoc} + */ + public function walkUpdateItem($updateItem) + { + } + + /** + * {@inheritdoc} + */ + public function walkWhereClause($whereClause) + { + } + + /** + * {@inheritdoc} + */ + public function walkConditionalExpression($condExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkConditionalTerm($condTerm) + { + } + + /** + * {@inheritdoc} + */ + public function walkConditionalFactor($factor) + { + } + + /** + * {@inheritdoc} + */ + public function walkConditionalPrimary($primary) + { + } + + /** + * {@inheritdoc} + */ + public function walkExistsExpression($existsExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkCollectionMemberExpression($collMemberExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkEmptyCollectionComparisonExpression($emptyCollCompExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkNullComparisonExpression($nullCompExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkInExpression($inExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkInstanceOfExpression($instanceOfExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkLiteral($literal) + { + } + + /** + * {@inheritdoc} + */ + public function walkBetweenExpression($betweenExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkLikeExpression($likeExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkStateFieldPathExpression($stateFieldPathExpression) + { + } + + /** + * {@inheritdoc} + */ + public function walkComparisonExpression($compExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkInputParameter($inputParam) + { + } + + /** + * {@inheritdoc} + */ + public function walkArithmeticExpression($arithmeticExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkArithmeticTerm($term) + { + } + + /** + * {@inheritdoc} + */ + public function walkStringPrimary($stringPrimary) + { + } + + /** + * {@inheritdoc} + */ + public function walkArithmeticFactor($factor) + { + } + + /** + * {@inheritdoc} + */ + public function walkSimpleArithmeticExpression($simpleArithmeticExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkPathExpression($pathExpr) + { + } + + /** + * {@inheritdoc} + */ + public function walkResultVariable($resultVariable) + { + } + + /** + * {@inheritdoc} + */ + public function getExecutor($AST) + { + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChain.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChain.php new file mode 100644 index 0000000..074aa93 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChain.php @@ -0,0 +1,575 @@ +. + */ + +namespace Doctrine\ORM\Query; + +/** + * Represents a chain of tree walkers that modify an AST and finally emit output. + * Only the last walker in the chain can emit output. Any previous walkers can modify + * the AST to influence the final output produced by the last walker. + * + * @author Roman Borschel + * @since 2.0 + */ +class TreeWalkerChain implements TreeWalker +{ + /** + * The tree walkers. + * + * @var TreeWalker[] + */ + private $_walkers; + + /** + * The original Query. + * + * @var \Doctrine\ORM\AbstractQuery + */ + private $_query; + + /** + * The ParserResult of the original query that was produced by the Parser. + * + * @var \Doctrine\ORM\Query\ParserResult + */ + private $_parserResult; + + /** + * The query components of the original query (the "symbol table") that was produced by the Parser. + * + * @var array + */ + private $_queryComponents; + + /** + * Returns the internal queryComponents array. + * + * @return array + */ + public function getQueryComponents() + { + return $this->_queryComponents; + } + + /** + * {@inheritdoc} + */ + public function setQueryComponent($dqlAlias, array $queryComponent) + { + $requiredKeys = ['metadata', 'parent', 'relation', 'map', 'nestingLevel', 'token']; + + if (array_diff($requiredKeys, array_keys($queryComponent))) { + throw QueryException::invalidQueryComponent($dqlAlias); + } + + $this->_queryComponents[$dqlAlias] = $queryComponent; + } + + /** + * {@inheritdoc} + */ + public function __construct($query, $parserResult, array $queryComponents) + { + $this->_query = $query; + $this->_parserResult = $parserResult; + $this->_queryComponents = $queryComponents; + $this->_walkers = new TreeWalkerChainIterator($this, $query, $parserResult); + } + + /** + * Adds a tree walker to the chain. + * + * @param string $walkerClass The class of the walker to instantiate. + * + * @return void + */ + public function addTreeWalker($walkerClass) + { + $this->_walkers[] = $walkerClass; + } + + /** + * {@inheritdoc} + */ + public function walkSelectStatement(AST\SelectStatement $AST) + { + foreach ($this->_walkers as $walker) { + $walker->walkSelectStatement($AST); + + $this->_queryComponents = $walker->getQueryComponents(); + } + } + + /** + * {@inheritdoc} + */ + public function walkSelectClause($selectClause) + { + foreach ($this->_walkers as $walker) { + $walker->walkSelectClause($selectClause); + } + } + + /** + * {@inheritdoc} + */ + public function walkFromClause($fromClause) + { + foreach ($this->_walkers as $walker) { + $walker->walkFromClause($fromClause); + } + } + + /** + * {@inheritdoc} + */ + public function walkFunction($function) + { + foreach ($this->_walkers as $walker) { + $walker->walkFunction($function); + } + } + + /** + * {@inheritdoc} + */ + public function walkOrderByClause($orderByClause) + { + foreach ($this->_walkers as $walker) { + $walker->walkOrderByClause($orderByClause); + } + } + + /** + * {@inheritdoc} + */ + public function walkOrderByItem($orderByItem) + { + foreach ($this->_walkers as $walker) { + $walker->walkOrderByItem($orderByItem); + } + } + + /** + * {@inheritdoc} + */ + public function walkHavingClause($havingClause) + { + foreach ($this->_walkers as $walker) { + $walker->walkHavingClause($havingClause); + } + } + + /** + * {@inheritdoc} + */ + public function walkJoin($join) + { + foreach ($this->_walkers as $walker) { + $walker->walkJoin($join); + } + } + + /** + * {@inheritdoc} + */ + public function walkSelectExpression($selectExpression) + { + foreach ($this->_walkers as $walker) { + $walker->walkSelectExpression($selectExpression); + } + } + + /** + * {@inheritdoc} + */ + public function walkQuantifiedExpression($qExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkQuantifiedExpression($qExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkSubselect($subselect) + { + foreach ($this->_walkers as $walker) { + $walker->walkSubselect($subselect); + } + } + + /** + * {@inheritdoc} + */ + public function walkSubselectFromClause($subselectFromClause) + { + foreach ($this->_walkers as $walker) { + $walker->walkSubselectFromClause($subselectFromClause); + } + } + + /** + * {@inheritdoc} + */ + public function walkSimpleSelectClause($simpleSelectClause) + { + foreach ($this->_walkers as $walker) { + $walker->walkSimpleSelectClause($simpleSelectClause); + } + } + + /** + * {@inheritdoc} + */ + public function walkSimpleSelectExpression($simpleSelectExpression) + { + foreach ($this->_walkers as $walker) { + $walker->walkSimpleSelectExpression($simpleSelectExpression); + } + } + + /** + * {@inheritdoc} + */ + public function walkAggregateExpression($aggExpression) + { + foreach ($this->_walkers as $walker) { + $walker->walkAggregateExpression($aggExpression); + } + } + + /** + * {@inheritdoc} + */ + public function walkGroupByClause($groupByClause) + { + foreach ($this->_walkers as $walker) { + $walker->walkGroupByClause($groupByClause); + } + } + + /** + * {@inheritdoc} + */ + public function walkGroupByItem($groupByItem) + { + foreach ($this->_walkers as $walker) { + $walker->walkGroupByItem($groupByItem); + } + } + + /** + * {@inheritdoc} + */ + public function walkUpdateStatement(AST\UpdateStatement $AST) + { + foreach ($this->_walkers as $walker) { + $walker->walkUpdateStatement($AST); + } + } + + /** + * {@inheritdoc} + */ + public function walkDeleteStatement(AST\DeleteStatement $AST) + { + foreach ($this->_walkers as $walker) { + $walker->walkDeleteStatement($AST); + } + } + + /** + * {@inheritdoc} + */ + public function walkDeleteClause(AST\DeleteClause $deleteClause) + { + foreach ($this->_walkers as $walker) { + $walker->walkDeleteClause($deleteClause); + } + } + + /** + * {@inheritdoc} + */ + public function walkUpdateClause($updateClause) + { + foreach ($this->_walkers as $walker) { + $walker->walkUpdateClause($updateClause); + } + } + + /** + * {@inheritdoc} + */ + public function walkUpdateItem($updateItem) + { + foreach ($this->_walkers as $walker) { + $walker->walkUpdateItem($updateItem); + } + } + + /** + * {@inheritdoc} + */ + public function walkWhereClause($whereClause) + { + foreach ($this->_walkers as $walker) { + $walker->walkWhereClause($whereClause); + } + } + + /** + * {@inheritdoc} + */ + public function walkConditionalExpression($condExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkConditionalExpression($condExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkConditionalTerm($condTerm) + { + foreach ($this->_walkers as $walker) { + $walker->walkConditionalTerm($condTerm); + } + } + + /** + * {@inheritdoc} + */ + public function walkConditionalFactor($factor) + { + foreach ($this->_walkers as $walker) { + $walker->walkConditionalFactor($factor); + } + } + + /** + * {@inheritdoc} + */ + public function walkConditionalPrimary($condPrimary) + { + foreach ($this->_walkers as $walker) { + $walker->walkConditionalPrimary($condPrimary); + } + } + + /** + * {@inheritdoc} + */ + public function walkExistsExpression($existsExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkExistsExpression($existsExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkCollectionMemberExpression($collMemberExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkCollectionMemberExpression($collMemberExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkEmptyCollectionComparisonExpression($emptyCollCompExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkEmptyCollectionComparisonExpression($emptyCollCompExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkNullComparisonExpression($nullCompExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkNullComparisonExpression($nullCompExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkInExpression($inExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkInExpression($inExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkInstanceOfExpression($instanceOfExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkInstanceOfExpression($instanceOfExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkLiteral($literal) + { + foreach ($this->_walkers as $walker) { + $walker->walkLiteral($literal); + } + } + + /** + * {@inheritdoc} + */ + public function walkBetweenExpression($betweenExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkBetweenExpression($betweenExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkLikeExpression($likeExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkLikeExpression($likeExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkStateFieldPathExpression($stateFieldPathExpression) + { + foreach ($this->_walkers as $walker) { + $walker->walkStateFieldPathExpression($stateFieldPathExpression); + } + } + + /** + * {@inheritdoc} + */ + public function walkComparisonExpression($compExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkComparisonExpression($compExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkInputParameter($inputParam) + { + foreach ($this->_walkers as $walker) { + $walker->walkInputParameter($inputParam); + } + } + + /** + * {@inheritdoc} + */ + public function walkArithmeticExpression($arithmeticExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkArithmeticExpression($arithmeticExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkArithmeticTerm($term) + { + foreach ($this->_walkers as $walker) { + $walker->walkArithmeticTerm($term); + } + } + + /** + * {@inheritdoc} + */ + public function walkStringPrimary($stringPrimary) + { + foreach ($this->_walkers as $walker) { + $walker->walkStringPrimary($stringPrimary); + } + } + + /** + * {@inheritdoc} + */ + public function walkArithmeticFactor($factor) + { + foreach ($this->_walkers as $walker) { + $walker->walkArithmeticFactor($factor); + } + } + + /** + * {@inheritdoc} + */ + public function walkSimpleArithmeticExpression($simpleArithmeticExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkSimpleArithmeticExpression($simpleArithmeticExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkPathExpression($pathExpr) + { + foreach ($this->_walkers as $walker) { + $walker->walkPathExpression($pathExpr); + } + } + + /** + * {@inheritdoc} + */ + public function walkResultVariable($resultVariable) + { + foreach ($this->_walkers as $walker) { + $walker->walkResultVariable($resultVariable); + } + } + + /** + * {@inheritdoc} + */ + public function getExecutor($AST) + { + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChainIterator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChainIterator.php new file mode 100644 index 0000000..e72e1d4 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChainIterator.php @@ -0,0 +1,138 @@ +. + */ + +namespace Doctrine\ORM\Query; + +/** + * + */ +class TreeWalkerChainIterator implements \Iterator, \ArrayAccess +{ + /** + * @var TreeWalker[] + */ + private $walkers = []; + /** + * @var TreeWalkerChain + */ + private $treeWalkerChain; + /** + * @var + */ + private $query; + /** + * @var + */ + private $parserResult; + + public function __construct(TreeWalkerChain $treeWalkerChain, $query, $parserResult) + { + $this->treeWalkerChain = $treeWalkerChain; + $this->query = $query; + $this->parserResult = $parserResult; + } + + /** + * {@inheritdoc} + */ + public function rewind() + { + return reset($this->walkers); + } + + /** + * {@inheritdoc} + */ + public function current() + { + return $this->offsetGet(key($this->walkers)); + } + + /** + * {@inheritdoc} + */ + public function key() + { + return key($this->walkers); + } + + /** + * {@inheritdoc} + */ + public function next() + { + next($this->walkers); + + return $this->offsetGet(key($this->walkers)); + } + + /** + * {@inheritdoc} + */ + public function valid() + { + return key($this->walkers) !== null; + } + + /** + * {@inheritdoc} + */ + public function offsetExists($offset) + { + return isset($this->walkers[$offset]); + } + + /** + * {@inheritdoc} + */ + public function offsetGet($offset) + { + if ($this->offsetExists($offset)) { + return new $this->walkers[$offset]( + $this->query, + $this->parserResult, + $this->treeWalkerChain->getQueryComponents() + ); + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function offsetSet($offset, $value) + { + if (null === $offset) { + $this->walkers[] = $value; + } else { + $this->walkers[$offset] = $value; + } + } + + /** + * {@inheritdoc} + */ + public function offsetUnset($offset) + { + if ($this->offsetExists($offset)) { + unset($this->walkers[$offset]); + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/QueryBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/QueryBuilder.php new file mode 100644 index 0000000..af4d8cd --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/QueryBuilder.php @@ -0,0 +1,1513 @@ +. + */ + +namespace Doctrine\ORM; + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Criteria; + +use Doctrine\ORM\Query\Expr; +use Doctrine\ORM\Query\QueryExpressionVisitor; + +/** + * This class is responsible for building DQL query strings via an object oriented + * PHP interface. + * + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class QueryBuilder +{ + /* The query types. */ + const SELECT = 0; + const DELETE = 1; + const UPDATE = 2; + + /* The builder states. */ + const STATE_DIRTY = 0; + const STATE_CLEAN = 1; + + /** + * The EntityManager used by this QueryBuilder. + * + * @var EntityManagerInterface + */ + private $_em; + + /** + * The array of DQL parts collected. + * + * @var array + */ + private $_dqlParts = [ + 'distinct' => false, + 'select' => [], + 'from' => [], + 'join' => [], + 'set' => [], + 'where' => null, + 'groupBy' => [], + 'having' => null, + 'orderBy' => [] + ]; + + /** + * The type of query this is. Can be select, update or delete. + * + * @var integer + */ + private $_type = self::SELECT; + + /** + * The state of the query object. Can be dirty or clean. + * + * @var integer + */ + private $_state = self::STATE_CLEAN; + + /** + * The complete DQL string for this query. + * + * @var string + */ + private $_dql; + + /** + * The query parameters. + * + * @var \Doctrine\Common\Collections\ArrayCollection + */ + private $parameters; + + /** + * The index of the first result to retrieve. + * + * @var integer + */ + private $_firstResult = null; + + /** + * The maximum number of results to retrieve. + * + * @var integer|null + */ + private $_maxResults = null; + + /** + * Keeps root entity alias names for join entities. + * + * @var array + */ + private $joinRootAliases = []; + + /** + * Whether to use second level cache, if available. + * + * @var boolean + */ + protected $cacheable = false; + + /** + * Second level cache region name. + * + * @var string|null + */ + protected $cacheRegion; + + /** + * Second level query cache mode. + * + * @var integer|null + */ + protected $cacheMode; + + /** + * @var integer + */ + protected $lifetime = 0; + + /** + * Initializes a new QueryBuilder that uses the given EntityManager. + * + * @param EntityManagerInterface $em The EntityManager to use. + */ + public function __construct(EntityManagerInterface $em) + { + $this->_em = $em; + $this->parameters = new ArrayCollection(); + } + + /** + * Gets an ExpressionBuilder used for object-oriented construction of query expressions. + * This producer method is intended for convenient inline usage. Example: + * + * + * $qb = $em->createQueryBuilder(); + * $qb + * ->select('u') + * ->from('User', 'u') + * ->where($qb->expr()->eq('u.id', 1)); + * + * + * For more complex expression construction, consider storing the expression + * builder object in a local variable. + * + * @return Query\Expr + */ + public function expr() + { + return $this->_em->getExpressionBuilder(); + } + + /** + * + * Enable/disable second level query (result) caching for this query. + * + * @param boolean $cacheable + * + * @return self + */ + public function setCacheable($cacheable) + { + $this->cacheable = (boolean) $cacheable; + + return $this; + } + + /** + * @return boolean TRUE if the query results are enable for second level cache, FALSE otherwise. + */ + public function isCacheable() + { + return $this->cacheable; + } + + /** + * @param string $cacheRegion + * + * @return self + */ + public function setCacheRegion($cacheRegion) + { + $this->cacheRegion = (string) $cacheRegion; + + return $this; + } + + /** + * Obtain the name of the second level query cache region in which query results will be stored + * + * @return string|null The cache region name; NULL indicates the default region. + */ + public function getCacheRegion() + { + return $this->cacheRegion; + } + + /** + * @return integer + */ + public function getLifetime() + { + return $this->lifetime; + } + + /** + * Sets the life-time for this query into second level cache. + * + * @param integer $lifetime + * + * @return self + */ + public function setLifetime($lifetime) + { + $this->lifetime = (integer) $lifetime; + + return $this; + } + + /** + * @return integer + */ + public function getCacheMode() + { + return $this->cacheMode; + } + + /** + * @param integer $cacheMode + * + * @return self + */ + public function setCacheMode($cacheMode) + { + $this->cacheMode = (integer) $cacheMode; + + return $this; + } + + /** + * Gets the type of the currently built query. + * + * @return integer + */ + public function getType() + { + return $this->_type; + } + + /** + * Gets the associated EntityManager for this query builder. + * + * @return EntityManager + */ + public function getEntityManager() + { + return $this->_em; + } + + /** + * Gets the state of this query builder instance. + * + * @return integer Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN. + */ + public function getState() + { + return $this->_state; + } + + /** + * Gets the complete DQL string formed by the current specifications of this QueryBuilder. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u'); + * echo $qb->getDql(); // SELECT u FROM User u + * + * + * @return string The DQL query string. + */ + public function getDQL() + { + if ($this->_dql !== null && $this->_state === self::STATE_CLEAN) { + return $this->_dql; + } + + switch ($this->_type) { + case self::DELETE: + $dql = $this->_getDQLForDelete(); + break; + + case self::UPDATE: + $dql = $this->_getDQLForUpdate(); + break; + + case self::SELECT: + default: + $dql = $this->_getDQLForSelect(); + break; + } + + $this->_state = self::STATE_CLEAN; + $this->_dql = $dql; + + return $dql; + } + + /** + * Constructs a Query instance from the current specifications of the builder. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u'); + * $q = $qb->getQuery(); + * $results = $q->execute(); + * + * + * @return Query + */ + public function getQuery() + { + $parameters = clone $this->parameters; + $query = $this->_em->createQuery($this->getDQL()) + ->setParameters($parameters) + ->setFirstResult($this->_firstResult) + ->setMaxResults($this->_maxResults); + + if ($this->lifetime) { + $query->setLifetime($this->lifetime); + } + + if ($this->cacheMode) { + $query->setCacheMode($this->cacheMode); + } + + if ($this->cacheable) { + $query->setCacheable($this->cacheable); + } + + if ($this->cacheRegion) { + $query->setCacheRegion($this->cacheRegion); + } + + return $query; + } + + /** + * Finds the root entity alias of the joined entity. + * + * @param string $alias The alias of the new join entity + * @param string $parentAlias The parent entity alias of the join relationship + * + * @return string + */ + private function findRootAlias($alias, $parentAlias) + { + $rootAlias = null; + + if (in_array($parentAlias, $this->getRootAliases())) { + $rootAlias = $parentAlias; + } elseif (isset($this->joinRootAliases[$parentAlias])) { + $rootAlias = $this->joinRootAliases[$parentAlias]; + } else { + // Should never happen with correct joining order. Might be + // thoughtful to throw exception instead. + $rootAlias = $this->getRootAlias(); + } + + $this->joinRootAliases[$alias] = $rootAlias; + + return $rootAlias; + } + + /** + * Gets the FIRST root alias of the query. This is the first entity alias involved + * in the construction of the query. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u'); + * + * echo $qb->getRootAlias(); // u + * + * + * @deprecated Please use $qb->getRootAliases() instead. + * @throws \RuntimeException + * + * @return string + */ + public function getRootAlias() + { + $aliases = $this->getRootAliases(); + + if ( ! isset($aliases[0])) { + throw new \RuntimeException('No alias was set before invoking getRootAlias().'); + } + + return $aliases[0]; + } + + /** + * Gets the root aliases of the query. This is the entity aliases involved + * in the construction of the query. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u'); + * + * $qb->getRootAliases(); // array('u') + * + * + * @return array + */ + public function getRootAliases() + { + $aliases = []; + + foreach ($this->_dqlParts['from'] as &$fromClause) { + if (is_string($fromClause)) { + $spacePos = strrpos($fromClause, ' '); + $from = substr($fromClause, 0, $spacePos); + $alias = substr($fromClause, $spacePos + 1); + + $fromClause = new Query\Expr\From($from, $alias); + } + + $aliases[] = $fromClause->getAlias(); + } + + return $aliases; + } + + /** + * Gets all the aliases that have been used in the query. + * Including all select root aliases and join aliases + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u') + * ->join('u.articles','a'); + * + * $qb->getAllAliases(); // array('u','a') + * + * @return array + */ + public function getAllAliases() + { + return array_merge($this->getRootAliases(), array_keys($this->joinRootAliases)); + } + + /** + * Gets the root entities of the query. This is the entity aliases involved + * in the construction of the query. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u'); + * + * $qb->getRootEntities(); // array('User') + * + * + * @return array + */ + public function getRootEntities() + { + $entities = []; + + foreach ($this->_dqlParts['from'] as &$fromClause) { + if (is_string($fromClause)) { + $spacePos = strrpos($fromClause, ' '); + $from = substr($fromClause, 0, $spacePos); + $alias = substr($fromClause, $spacePos + 1); + + $fromClause = new Query\Expr\From($from, $alias); + } + + $entities[] = $fromClause->getFrom(); + } + + return $entities; + } + + /** + * Sets a query parameter for the query being constructed. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u') + * ->where('u.id = :user_id') + * ->setParameter('user_id', 1); + * + * + * @param string|integer $key The parameter position or name. + * @param mixed $value The parameter value. + * @param string|integer|null $type PDO::PARAM_* or \Doctrine\DBAL\Types\Type::* constant + * + * @return self + */ + public function setParameter($key, $value, $type = null) + { + $existingParameter = $this->getParameter($key); + + if ($existingParameter !== null) { + $existingParameter->setValue($value, $type); + + return $this; + } + + $this->parameters->add(new Query\Parameter($key, $value, $type)); + + return $this; + } + + /** + * Sets a collection of query parameters for the query being constructed. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u') + * ->where('u.id = :user_id1 OR u.id = :user_id2') + * ->setParameters(new ArrayCollection(array( + * new Parameter('user_id1', 1), + * new Parameter('user_id2', 2) + * ))); + * + * + * @param \Doctrine\Common\Collections\ArrayCollection|array $parameters The query parameters to set. + * + * @return self + */ + public function setParameters($parameters) + { + // BC compatibility with 2.3- + if (is_array($parameters)) { + $parameterCollection = new ArrayCollection(); + + foreach ($parameters as $key => $value) { + $parameter = new Query\Parameter($key, $value); + + $parameterCollection->add($parameter); + } + + $parameters = $parameterCollection; + } + + $this->parameters = $parameters; + + return $this; + } + + /** + * Gets all defined query parameters for the query being constructed. + * + * @return \Doctrine\Common\Collections\ArrayCollection The currently defined query parameters. + */ + public function getParameters() + { + return $this->parameters; + } + + /** + * Gets a (previously set) query parameter of the query being constructed. + * + * @param mixed $key The key (index or name) of the bound parameter. + * + * @return Query\Parameter|null The value of the bound parameter. + */ + public function getParameter($key) + { + $filteredParameters = $this->parameters->filter( + function (Query\Parameter $parameter) use ($key) : bool { + $parameterName = $parameter->getName(); + + return $key === $parameterName || (string) $key === (string) $parameterName; + } + ); + + return ! $filteredParameters->isEmpty() ? $filteredParameters->first() : null; + } + + /** + * Sets the position of the first result to retrieve (the "offset"). + * + * @param integer $firstResult The first result to return. + * + * @return self + */ + public function setFirstResult($firstResult) + { + $this->_firstResult = $firstResult; + + return $this; + } + + /** + * Gets the position of the first result the query object was set to retrieve (the "offset"). + * Returns NULL if {@link setFirstResult} was not applied to this QueryBuilder. + * + * @return integer The position of the first result. + */ + public function getFirstResult() + { + return $this->_firstResult; + } + + /** + * Sets the maximum number of results to retrieve (the "limit"). + * + * @param integer|null $maxResults The maximum number of results to retrieve. + * + * @return self + */ + public function setMaxResults($maxResults) + { + $this->_maxResults = $maxResults; + + return $this; + } + + /** + * Gets the maximum number of results the query object was set to retrieve (the "limit"). + * Returns NULL if {@link setMaxResults} was not applied to this query builder. + * + * @return integer|null Maximum number of results. + */ + public function getMaxResults() + { + return $this->_maxResults; + } + + /** + * Either appends to or replaces a single, generic query part. + * + * The available parts are: 'select', 'from', 'join', 'set', 'where', + * 'groupBy', 'having' and 'orderBy'. + * + * @param string $dqlPartName The DQL part name. + * @param object|array $dqlPart An Expr object. + * @param bool $append Whether to append (true) or replace (false). + * + * @return self + */ + public function add($dqlPartName, $dqlPart, $append = false) + { + if ($append && ($dqlPartName === "where" || $dqlPartName === "having")) { + throw new \InvalidArgumentException( + "Using \$append = true does not have an effect with 'where' or 'having' ". + "parts. See QueryBuilder#andWhere() for an example for correct usage." + ); + } + + $isMultiple = is_array($this->_dqlParts[$dqlPartName]) + && !($dqlPartName == 'join' && !$append); + + // Allow adding any part retrieved from self::getDQLParts(). + if (is_array($dqlPart) && $dqlPartName != 'join') { + $dqlPart = reset($dqlPart); + } + + // This is introduced for backwards compatibility reasons. + // TODO: Remove for 3.0 + if ($dqlPartName == 'join') { + $newDqlPart = []; + + foreach ($dqlPart as $k => $v) { + $k = is_numeric($k) ? $this->getRootAlias() : $k; + + $newDqlPart[$k] = $v; + } + + $dqlPart = $newDqlPart; + } + + if ($append && $isMultiple) { + if (is_array($dqlPart)) { + $key = key($dqlPart); + + $this->_dqlParts[$dqlPartName][$key][] = $dqlPart[$key]; + } else { + $this->_dqlParts[$dqlPartName][] = $dqlPart; + } + } else { + $this->_dqlParts[$dqlPartName] = ($isMultiple) ? [$dqlPart] : $dqlPart; + } + + $this->_state = self::STATE_DIRTY; + + return $this; + } + + /** + * Specifies an item that is to be returned in the query result. + * Replaces any previously specified selections, if any. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u', 'p') + * ->from('User', 'u') + * ->leftJoin('u.Phonenumbers', 'p'); + * + * + * @param mixed $select The selection expressions. + * + * @return self + */ + public function select($select = null) + { + $this->_type = self::SELECT; + + if (empty($select)) { + return $this; + } + + $selects = is_array($select) ? $select : func_get_args(); + + return $this->add('select', new Expr\Select($selects), false); + } + + /** + * Adds a DISTINCT flag to this query. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->distinct() + * ->from('User', 'u'); + * + * + * @param bool $flag + * + * @return self + */ + public function distinct($flag = true) + { + $this->_dqlParts['distinct'] = (bool) $flag; + + return $this; + } + + /** + * Adds an item that is to be returned in the query result. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->addSelect('p') + * ->from('User', 'u') + * ->leftJoin('u.Phonenumbers', 'p'); + * + * + * @param mixed $select The selection expression. + * + * @return self + */ + public function addSelect($select = null) + { + $this->_type = self::SELECT; + + if (empty($select)) { + return $this; + } + + $selects = is_array($select) ? $select : func_get_args(); + + return $this->add('select', new Expr\Select($selects), true); + } + + /** + * Turns the query being built into a bulk delete query that ranges over + * a certain entity type. + * + * + * $qb = $em->createQueryBuilder() + * ->delete('User', 'u') + * ->where('u.id = :user_id') + * ->setParameter('user_id', 1); + * + * + * @param string $delete The class/type whose instances are subject to the deletion. + * @param string $alias The class/type alias used in the constructed query. + * + * @return self + */ + public function delete($delete = null, $alias = null) + { + $this->_type = self::DELETE; + + if ( ! $delete) { + return $this; + } + + return $this->add('from', new Expr\From($delete, $alias)); + } + + /** + * Turns the query being built into a bulk update query that ranges over + * a certain entity type. + * + * + * $qb = $em->createQueryBuilder() + * ->update('User', 'u') + * ->set('u.password', '?1') + * ->where('u.id = ?2'); + * + * + * @param string $update The class/type whose instances are subject to the update. + * @param string $alias The class/type alias used in the constructed query. + * + * @return self + */ + public function update($update = null, $alias = null) + { + $this->_type = self::UPDATE; + + if ( ! $update) { + return $this; + } + + return $this->add('from', new Expr\From($update, $alias)); + } + + /** + * Creates and adds a query root corresponding to the entity identified by the given alias, + * forming a cartesian product with any existing query roots. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u'); + * + * + * @param string $from The class name. + * @param string $alias The alias of the class. + * @param string $indexBy The index for the from. + * + * @return self + */ + public function from($from, $alias, $indexBy = null) + { + return $this->add('from', new Expr\From($from, $alias, $indexBy), true); + } + + /** + * Updates a query root corresponding to an entity setting its index by. This method is intended to be used with + * EntityRepository->createQueryBuilder(), which creates the initial FROM clause and do not allow you to update it + * setting an index by. + * + * + * $qb = $userRepository->createQueryBuilder('u') + * ->indexBy('u', 'u.id'); + * + * // Is equivalent to... + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u', 'u.id'); + * + * + * @param string $alias The root alias of the class. + * @param string $indexBy The index for the from. + * + * @return self + * + * @throws Query\QueryException + */ + public function indexBy($alias, $indexBy) + { + $rootAliases = $this->getRootAliases(); + + if (!in_array($alias, $rootAliases)) { + throw new Query\QueryException( + sprintf('Specified root alias %s must be set before invoking indexBy().', $alias) + ); + } + + foreach ($this->_dqlParts['from'] as &$fromClause) { + /* @var Expr\From $fromClause */ + if ($fromClause->getAlias() !== $alias) { + continue; + } + + $fromClause = new Expr\From($fromClause->getFrom(), $fromClause->getAlias(), $indexBy); + } + + return $this; + } + + /** + * Creates and adds a join over an entity association to the query. + * + * The entities in the joined association will be fetched as part of the query + * result if the alias used for the joined association is placed in the select + * expressions. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u') + * ->join('u.Phonenumbers', 'p', Expr\Join::WITH, 'p.is_primary = 1'); + * + * + * @param string $join The relationship to join. + * @param string $alias The alias of the join. + * @param string|null $conditionType The condition type constant. Either ON or WITH. + * @param string|null $condition The condition for the join. + * @param string|null $indexBy The index for the join. + * + * @return self + */ + public function join($join, $alias, $conditionType = null, $condition = null, $indexBy = null) + { + return $this->innerJoin($join, $alias, $conditionType, $condition, $indexBy); + } + + /** + * Creates and adds a join over an entity association to the query. + * + * The entities in the joined association will be fetched as part of the query + * result if the alias used for the joined association is placed in the select + * expressions. + * + * [php] + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u') + * ->innerJoin('u.Phonenumbers', 'p', Expr\Join::WITH, 'p.is_primary = 1'); + * + * @param string $join The relationship to join. + * @param string $alias The alias of the join. + * @param string|null $conditionType The condition type constant. Either ON or WITH. + * @param string|null $condition The condition for the join. + * @param string|null $indexBy The index for the join. + * + * @return self + */ + public function innerJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null) + { + $parentAlias = substr($join, 0, strpos($join, '.')); + + $rootAlias = $this->findRootAlias($alias, $parentAlias); + + $join = new Expr\Join( + Expr\Join::INNER_JOIN, $join, $alias, $conditionType, $condition, $indexBy + ); + + return $this->add('join', [$rootAlias => $join], true); + } + + /** + * Creates and adds a left join over an entity association to the query. + * + * The entities in the joined association will be fetched as part of the query + * result if the alias used for the joined association is placed in the select + * expressions. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u') + * ->leftJoin('u.Phonenumbers', 'p', Expr\Join::WITH, 'p.is_primary = 1'); + * + * + * @param string $join The relationship to join. + * @param string $alias The alias of the join. + * @param string|null $conditionType The condition type constant. Either ON or WITH. + * @param string|null $condition The condition for the join. + * @param string|null $indexBy The index for the join. + * + * @return self + */ + public function leftJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null) + { + $parentAlias = substr($join, 0, strpos($join, '.')); + + $rootAlias = $this->findRootAlias($alias, $parentAlias); + + $join = new Expr\Join( + Expr\Join::LEFT_JOIN, $join, $alias, $conditionType, $condition, $indexBy + ); + + return $this->add('join', [$rootAlias => $join], true); + } + + /** + * Sets a new value for a field in a bulk update query. + * + * + * $qb = $em->createQueryBuilder() + * ->update('User', 'u') + * ->set('u.password', '?1') + * ->where('u.id = ?2'); + * + * + * @param string $key The key/field to set. + * @param mixed $value The value, expression, placeholder, etc. + * + * @return self + */ + public function set($key, $value) + { + return $this->add('set', new Expr\Comparison($key, Expr\Comparison::EQ, $value), true); + } + + /** + * Specifies one or more restrictions to the query result. + * Replaces any previously specified restrictions, if any. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u') + * ->where('u.id = ?'); + * + * // You can optionally programmatically build and/or expressions + * $qb = $em->createQueryBuilder(); + * + * $or = $qb->expr()->orX(); + * $or->add($qb->expr()->eq('u.id', 1)); + * $or->add($qb->expr()->eq('u.id', 2)); + * + * $qb->update('User', 'u') + * ->set('u.password', '?') + * ->where($or); + * + * + * @param mixed $predicates The restriction predicates. + * + * @return self + */ + public function where($predicates) + { + if ( ! (func_num_args() == 1 && $predicates instanceof Expr\Composite)) { + $predicates = new Expr\Andx(func_get_args()); + } + + return $this->add('where', $predicates); + } + + /** + * Adds one or more restrictions to the query results, forming a logical + * conjunction with any previously specified restrictions. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u') + * ->where('u.username LIKE ?') + * ->andWhere('u.is_active = 1'); + * + * + * @param mixed $where The query restrictions. + * + * @return self + * + * @see where() + */ + public function andWhere() + { + $args = func_get_args(); + $where = $this->getDQLPart('where'); + + if ($where instanceof Expr\Andx) { + $where->addMultiple($args); + } else { + array_unshift($args, $where); + $where = new Expr\Andx($args); + } + + return $this->add('where', $where); + } + + /** + * Adds one or more restrictions to the query results, forming a logical + * disjunction with any previously specified restrictions. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u') + * ->where('u.id = 1') + * ->orWhere('u.id = 2'); + * + * + * @param mixed $where The WHERE statement. + * + * @return self + * + * @see where() + */ + public function orWhere() + { + $args = func_get_args(); + $where = $this->getDQLPart('where'); + + if ($where instanceof Expr\Orx) { + $where->addMultiple($args); + } else { + array_unshift($args, $where); + $where = new Expr\Orx($args); + } + + return $this->add('where', $where); + } + + /** + * Specifies a grouping over the results of the query. + * Replaces any previously specified groupings, if any. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u') + * ->groupBy('u.id'); + * + * + * @param string $groupBy The grouping expression. + * + * @return self + */ + public function groupBy($groupBy) + { + return $this->add('groupBy', new Expr\GroupBy(func_get_args())); + } + + /** + * Adds a grouping expression to the query. + * + * + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u') + * ->groupBy('u.lastLogin') + * ->addGroupBy('u.createdAt'); + * + * + * @param string $groupBy The grouping expression. + * + * @return self + */ + public function addGroupBy($groupBy) + { + return $this->add('groupBy', new Expr\GroupBy(func_get_args()), true); + } + + /** + * Specifies a restriction over the groups of the query. + * Replaces any previous having restrictions, if any. + * + * @param mixed $having The restriction over the groups. + * + * @return self + */ + public function having($having) + { + if ( ! (func_num_args() == 1 && ($having instanceof Expr\Andx || $having instanceof Expr\Orx))) { + $having = new Expr\Andx(func_get_args()); + } + + return $this->add('having', $having); + } + + /** + * Adds a restriction over the groups of the query, forming a logical + * conjunction with any existing having restrictions. + * + * @param mixed $having The restriction to append. + * + * @return self + */ + public function andHaving($having) + { + $args = func_get_args(); + $having = $this->getDQLPart('having'); + + if ($having instanceof Expr\Andx) { + $having->addMultiple($args); + } else { + array_unshift($args, $having); + $having = new Expr\Andx($args); + } + + return $this->add('having', $having); + } + + /** + * Adds a restriction over the groups of the query, forming a logical + * disjunction with any existing having restrictions. + * + * @param mixed $having The restriction to add. + * + * @return self + */ + public function orHaving($having) + { + $args = func_get_args(); + $having = $this->getDQLPart('having'); + + if ($having instanceof Expr\Orx) { + $having->addMultiple($args); + } else { + array_unshift($args, $having); + $having = new Expr\Orx($args); + } + + return $this->add('having', $having); + } + + /** + * Specifies an ordering for the query results. + * Replaces any previously specified orderings, if any. + * + * @param string|Expr\OrderBy $sort The ordering expression. + * @param string $order The ordering direction. + * + * @return self + */ + public function orderBy($sort, $order = null) + { + $orderBy = ($sort instanceof Expr\OrderBy) ? $sort : new Expr\OrderBy($sort, $order); + + return $this->add('orderBy', $orderBy); + } + + /** + * Adds an ordering to the query results. + * + * @param string|Expr\OrderBy $sort The ordering expression. + * @param string $order The ordering direction. + * + * @return self + */ + public function addOrderBy($sort, $order = null) + { + $orderBy = ($sort instanceof Expr\OrderBy) ? $sort : new Expr\OrderBy($sort, $order); + + return $this->add('orderBy', $orderBy, true); + } + + /** + * Adds criteria to the query. + * + * Adds where expressions with AND operator. + * Adds orderings. + * Overrides firstResult and maxResults if they're set. + * + * @param Criteria $criteria + * + * @return self + * + * @throws Query\QueryException + */ + public function addCriteria(Criteria $criteria) + { + $allAliases = $this->getAllAliases(); + if ( ! isset($allAliases[0])) { + throw new Query\QueryException('No aliases are set before invoking addCriteria().'); + } + + $visitor = new QueryExpressionVisitor($this->getAllAliases()); + + if ($whereExpression = $criteria->getWhereExpression()) { + $this->andWhere($visitor->dispatch($whereExpression)); + foreach ($visitor->getParameters() as $parameter) { + $this->parameters->add($parameter); + } + } + + if ($criteria->getOrderings()) { + foreach ($criteria->getOrderings() as $sort => $order) { + + $hasValidAlias = false; + foreach($allAliases as $alias) { + if(strpos($sort . '.', $alias . '.') === 0) { + $hasValidAlias = true; + break; + } + } + + if(!$hasValidAlias) { + $sort = $allAliases[0] . '.' . $sort; + } + + $this->addOrderBy($sort, $order); + } + } + + // Overwrite limits only if they was set in criteria + if (($firstResult = $criteria->getFirstResult()) !== null) { + $this->setFirstResult($firstResult); + } + if (($maxResults = $criteria->getMaxResults()) !== null) { + $this->setMaxResults($maxResults); + } + + return $this; + } + + /** + * Gets a query part by its name. + * + * @param string $queryPartName + * + * @return mixed $queryPart + * + * @todo Rename: getQueryPart (or remove?) + */ + public function getDQLPart($queryPartName) + { + return $this->_dqlParts[$queryPartName]; + } + + /** + * Gets all query parts. + * + * @return array $dqlParts + * + * @todo Rename: getQueryParts (or remove?) + */ + public function getDQLParts() + { + return $this->_dqlParts; + } + + /** + * @return string + */ + private function _getDQLForDelete() + { + return 'DELETE' + . $this->_getReducedDQLQueryPart('from', ['pre' => ' ', 'separator' => ', ']) + . $this->_getReducedDQLQueryPart('where', ['pre' => ' WHERE ']) + . $this->_getReducedDQLQueryPart('orderBy', ['pre' => ' ORDER BY ', 'separator' => ', ']); + } + + /** + * @return string + */ + private function _getDQLForUpdate() + { + return 'UPDATE' + . $this->_getReducedDQLQueryPart('from', ['pre' => ' ', 'separator' => ', ']) + . $this->_getReducedDQLQueryPart('set', ['pre' => ' SET ', 'separator' => ', ']) + . $this->_getReducedDQLQueryPart('where', ['pre' => ' WHERE ']) + . $this->_getReducedDQLQueryPart('orderBy', ['pre' => ' ORDER BY ', 'separator' => ', ']); + } + + /** + * @return string + */ + private function _getDQLForSelect() + { + $dql = 'SELECT' + . ($this->_dqlParts['distinct']===true ? ' DISTINCT' : '') + . $this->_getReducedDQLQueryPart('select', ['pre' => ' ', 'separator' => ', ']); + + $fromParts = $this->getDQLPart('from'); + $joinParts = $this->getDQLPart('join'); + $fromClauses = []; + + // Loop through all FROM clauses + if ( ! empty($fromParts)) { + $dql .= ' FROM '; + + foreach ($fromParts as $from) { + $fromClause = (string) $from; + + if ($from instanceof Expr\From && isset($joinParts[$from->getAlias()])) { + foreach ($joinParts[$from->getAlias()] as $join) { + $fromClause .= ' ' . ((string) $join); + } + } + + $fromClauses[] = $fromClause; + } + } + + $dql .= implode(', ', $fromClauses) + . $this->_getReducedDQLQueryPart('where', ['pre' => ' WHERE ']) + . $this->_getReducedDQLQueryPart('groupBy', ['pre' => ' GROUP BY ', 'separator' => ', ']) + . $this->_getReducedDQLQueryPart('having', ['pre' => ' HAVING ']) + . $this->_getReducedDQLQueryPart('orderBy', ['pre' => ' ORDER BY ', 'separator' => ', ']); + + return $dql; + } + + /** + * @param string $queryPartName + * @param array $options + * + * @return string + */ + private function _getReducedDQLQueryPart($queryPartName, $options = []) + { + $queryPart = $this->getDQLPart($queryPartName); + + if (empty($queryPart)) { + return ($options['empty'] ?? ''); + } + + return ($options['pre'] ?? '') + . (is_array($queryPart) ? implode($options['separator'], $queryPart) : $queryPart) + . ($options['post'] ?? ''); + } + + /** + * Resets DQL parts. + * + * @param array|null $parts + * + * @return self + */ + public function resetDQLParts($parts = null) + { + if (null === $parts) { + $parts = array_keys($this->_dqlParts); + } + + foreach ($parts as $part) { + $this->resetDQLPart($part); + } + + return $this; + } + + /** + * Resets single DQL part. + * + * @param string $part + * + * @return self + */ + public function resetDQLPart($part) + { + $this->_dqlParts[$part] = is_array($this->_dqlParts[$part]) ? [] : null; + $this->_state = self::STATE_DIRTY; + + return $this; + } + + /** + * Gets a string representation of this QueryBuilder which corresponds to + * the final DQL query being constructed. + * + * @return string The string representation of this QueryBuilder. + */ + public function __toString() + { + return $this->getDQL(); + } + + /** + * Deep clones all expression objects in the DQL parts. + * + * @return void + */ + public function __clone() + { + foreach ($this->_dqlParts as $part => $elements) { + if (is_array($this->_dqlParts[$part])) { + foreach ($this->_dqlParts[$part] as $idx => $element) { + if (is_object($element)) { + $this->_dqlParts[$part][$idx] = clone $element; + } + } + } else if (is_object($elements)) { + $this->_dqlParts[$part] = clone $elements; + } + } + + $parameters = []; + + foreach ($this->parameters as $parameter) { + $parameters[] = clone $parameter; + } + + $this->parameters = new ArrayCollection($parameters); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php new file mode 100644 index 0000000..6809624 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php @@ -0,0 +1,70 @@ +. + */ + +namespace Doctrine\ORM\Repository; + +use Doctrine\ORM\EntityManagerInterface; + +/** + * This factory is used to create default repository objects for entities at runtime. + * + * @author Guilherme Blanco + * @since 2.4 + */ +final class DefaultRepositoryFactory implements RepositoryFactory +{ + /** + * The list of EntityRepository instances. + * + * @var \Doctrine\Common\Persistence\ObjectRepository[] + */ + private $repositoryList = []; + + /** + * {@inheritdoc} + */ + public function getRepository(EntityManagerInterface $entityManager, $entityName) + { + $repositoryHash = $entityManager->getClassMetadata($entityName)->getName() . spl_object_hash($entityManager); + + if (isset($this->repositoryList[$repositoryHash])) { + return $this->repositoryList[$repositoryHash]; + } + + return $this->repositoryList[$repositoryHash] = $this->createRepository($entityManager, $entityName); + } + + /** + * Create a new repository instance for an entity class. + * + * @param \Doctrine\ORM\EntityManagerInterface $entityManager The EntityManager instance. + * @param string $entityName The name of the entity. + * + * @return \Doctrine\Common\Persistence\ObjectRepository + */ + private function createRepository(EntityManagerInterface $entityManager, $entityName) + { + /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */ + $metadata = $entityManager->getClassMetadata($entityName); + $repositoryClassName = $metadata->customRepositoryClassName + ?: $entityManager->getConfiguration()->getDefaultRepositoryClassName(); + + return new $repositoryClassName($entityManager, $metadata); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/RepositoryFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/RepositoryFactory.php new file mode 100644 index 0000000..f3af43e --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/RepositoryFactory.php @@ -0,0 +1,41 @@ +. + */ + +namespace Doctrine\ORM\Repository; + +use Doctrine\ORM\EntityManagerInterface; + +/** + * Interface for entity repository factory. + * + * @author Guilherme Blanco + * @since 2.4 + */ +interface RepositoryFactory +{ + /** + * Gets the repository for an entity class. + * + * @param \Doctrine\ORM\EntityManagerInterface $entityManager The EntityManager instance. + * @param string $entityName The name of the entity. + * + * @return \Doctrine\Common\Persistence\ObjectRepository + */ + public function getRepository(EntityManagerInterface $entityManager, $entityName); +} \ No newline at end of file diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/AttachEntityListenersListener.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/AttachEntityListenersListener.php new file mode 100644 index 0000000..cf7cc8b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/AttachEntityListenersListener.php @@ -0,0 +1,79 @@ +. + */ + +namespace Doctrine\ORM\Tools; + +use Doctrine\ORM\Event\LoadClassMetadataEventArgs; + +/** + * Mechanism to programmatically attach entity listeners. + * + * @author Fabio B. SIlva + * + * @since 2.5 + */ +class AttachEntityListenersListener +{ + /** + * @var array[] + */ + private $entityListeners = []; + + /** + * Adds a entity listener for a specific entity. + * + * @param string $entityClass The entity to attach the listener. + * @param string $listenerClass The listener class. + * @param string $eventName The entity lifecycle event. + * @param string|null $listenerCallback The listener callback method or NULL to use $eventName. + * + * @return void + */ + public function addEntityListener($entityClass, $listenerClass, $eventName, $listenerCallback = null) + { + $this->entityListeners[ltrim($entityClass, '\\')][] = [ + 'event' => $eventName, + 'class' => $listenerClass, + 'method' => $listenerCallback ?: $eventName + ]; + } + + /** + * Processes event and attach the entity listener. + * + * @param \Doctrine\ORM\Event\LoadClassMetadataEventArgs $event + * + * @return void + */ + public function loadClassMetadata(LoadClassMetadataEventArgs $event) + { + /** @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */ + $metadata = $event->getClassMetadata(); + + if ( ! isset($this->entityListeners[$metadata->name])) { + return; + } + + foreach ($this->entityListeners[$metadata->name] as $listener) { + $metadata->addEntityListener($listener['event'], $listener['class'], $listener['method']); + } + + unset($this->entityListeners[$metadata->name]); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/CollectionRegionCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/CollectionRegionCommand.php new file mode 100644 index 0000000..1c75ccc --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/CollectionRegionCommand.php @@ -0,0 +1,149 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\ClearCache; + +use Doctrine\ORM\Cache; +use Doctrine\ORM\Cache\Region\DefaultRegion; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to clear a collection cache region. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class CollectionRegionCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:clear-cache:region:collection') + ->setDescription('Clear a second-level cache collection region') + ->addArgument('owner-class', InputArgument::OPTIONAL, 'The owner entity name.') + ->addArgument('association', InputArgument::OPTIONAL, 'The association collection name.') + ->addArgument('owner-id', InputArgument::OPTIONAL, 'The owner identifier.') + ->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all entity regions will be deleted/invalidated.') + ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, all cache entries will be flushed.') + ->setHelp(<<%command.name% command is meant to clear a second-level cache collection regions for an associated Entity Manager. +It is possible to delete/invalidate all collection region, a specific collection region or flushes the cache provider. + +The execution type differ on how you execute the command. +If you want to invalidate all entries for an collection region this command would do the work: + +%command.name% 'Entities\MyEntity' 'collectionName' + +To invalidate a specific entry you should use : + +%command.name% 'Entities\MyEntity' 'collectionName' 1 + +If you want to invalidate all entries for the all collection regions: + +%command.name% --all + +Alternatively, if you want to flush the configured cache provider for an collection region use this command: + +%command.name% 'Entities\MyEntity' 'collectionName' --flush + +Finally, be aware that if --flush option is passed, +not all cache providers are able to flush entries, because of a limitation of its execution nature. +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + $em = $this->getHelper('em')->getEntityManager(); + $ownerClass = $input->getArgument('owner-class'); + $assoc = $input->getArgument('association'); + $ownerId = $input->getArgument('owner-id'); + $cache = $em->getCache(); + + if ( ! $cache instanceof Cache) { + throw new \InvalidArgumentException('No second-level cache is configured on the given EntityManager.'); + } + + if (( ! $ownerClass || ! $assoc) && ! $input->getOption('all')) { + throw new \InvalidArgumentException('Missing arguments "--owner-class" "--association"'); + } + + if ($input->getOption('flush')) { + $collectionRegion = $cache->getCollectionCacheRegion($ownerClass, $assoc); + + if ( ! $collectionRegion instanceof DefaultRegion) { + throw new \InvalidArgumentException(sprintf( + 'The option "--flush" expects a "Doctrine\ORM\Cache\Region\DefaultRegion", but got "%s".', + is_object($collectionRegion) ? get_class($collectionRegion) : gettype($collectionRegion) + )); + } + + $collectionRegion->getCache()->flushAll(); + + $ui->comment( + sprintf( + 'Flushing cache provider configured for "%s#%s"', + $ownerClass, + $assoc + ) + ); + + return 0; + } + + if ($input->getOption('all')) { + $ui->comment('Clearing all second-level cache collection regions'); + + $cache->evictEntityRegions(); + + return 0; + } + + if ($ownerId) { + $ui->comment( + sprintf( + 'Clearing second-level cache entry for collection "%s#%s" owner entity identified by "%s"', + $ownerClass, + $assoc, + $ownerId + ) + ); + $cache->evictCollection($ownerClass, $assoc, $ownerId); + + return 0; + } + + $ui->comment(sprintf('Clearing second-level cache for collection "%s#%s"', $ownerClass, $assoc)); + $cache->evictCollectionRegion($ownerClass, $assoc); + + return 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/EntityRegionCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/EntityRegionCommand.php new file mode 100644 index 0000000..c246910 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/EntityRegionCommand.php @@ -0,0 +1,140 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\ClearCache; + +use Doctrine\ORM\Cache; +use Doctrine\ORM\Cache\Region\DefaultRegion; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to clear a entity cache region. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class EntityRegionCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:clear-cache:region:entity') + ->setDescription('Clear a second-level cache entity region') + ->addArgument('entity-class', InputArgument::OPTIONAL, 'The entity name.') + ->addArgument('entity-id', InputArgument::OPTIONAL, 'The entity identifier.') + ->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all entity regions will be deleted/invalidated.') + ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, all cache entries will be flushed.') + ->setHelp(<<%command.name% command is meant to clear a second-level cache entity region for an associated Entity Manager. +It is possible to delete/invalidate all entity region, a specific entity region or flushes the cache provider. + +The execution type differ on how you execute the command. +If you want to invalidate all entries for an entity region this command would do the work: + +%command.name% 'Entities\MyEntity' + +To invalidate a specific entry you should use : + +%command.name% 'Entities\MyEntity' 1 + +If you want to invalidate all entries for the all entity regions: + +%command.name% --all + +Alternatively, if you want to flush the configured cache provider for an entity region use this command: + +%command.name% 'Entities\MyEntity' --flush + +Finally, be aware that if --flush option is passed, +not all cache providers are able to flush entries, because of a limitation of its execution nature. +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + $em = $this->getHelper('em')->getEntityManager(); + $entityClass = $input->getArgument('entity-class'); + $entityId = $input->getArgument('entity-id'); + $cache = $em->getCache(); + + if ( ! $cache instanceof Cache) { + throw new \InvalidArgumentException('No second-level cache is configured on the given EntityManager.'); + } + + if ( ! $entityClass && ! $input->getOption('all')) { + throw new \InvalidArgumentException('Invalid argument "--entity-class"'); + } + + if ($input->getOption('flush')) { + $entityRegion = $cache->getEntityCacheRegion($entityClass); + + if ( ! $entityRegion instanceof DefaultRegion) { + throw new \InvalidArgumentException(sprintf( + 'The option "--flush" expects a "Doctrine\ORM\Cache\Region\DefaultRegion", but got "%s".', + is_object($entityRegion) ? get_class($entityRegion) : gettype($entityRegion) + )); + } + + $entityRegion->getCache()->flushAll(); + + $ui->comment(sprintf('Flushing cache provider configured for entity named "%s"', $entityClass)); + + return 0; + } + + if ($input->getOption('all')) { + $ui->comment('Clearing all second-level cache entity regions'); + + $cache->evictEntityRegions(); + + return 0; + } + + if ($entityId) { + $ui->comment( + sprintf( + 'Clearing second-level cache entry for entity "%s" identified by "%s"', + $entityClass, + $entityId + ) + ); + $cache->evictEntity($entityClass, $entityId); + + return 0; + } + + $ui->comment(sprintf('Clearing second-level cache for entity "%s"', $entityClass)); + $cache->evictEntityRegion($entityClass); + + return 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/MetadataCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/MetadataCommand.php new file mode 100644 index 0000000..e6531f2 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/MetadataCommand.php @@ -0,0 +1,112 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\ClearCache; + +use Doctrine\Common\Cache\ApcCache; +use Doctrine\Common\Cache\XcacheCache; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to clear the metadata cache of the various cache drivers. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class MetadataCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:clear-cache:metadata') + ->setDescription('Clear all metadata cache of the various cache drivers') + ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, cache entries will be flushed instead of deleted/invalidated.') + ->setHelp(<<%command.name% command is meant to clear the metadata cache of associated Entity Manager. +It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider +instance completely. + +The execution type differ on how you execute the command. +If you want to invalidate the entries (and not delete from cache instance), this command would do the work: + +%command.name% + +Alternatively, if you want to flush the cache provider using this command: + +%command.name% --flush + +Finally, be aware that if --flush option is passed, not all cache providers are able to flush entries, +because of a limitation of its execution nature. +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + $em = $this->getHelper('em')->getEntityManager(); + $cacheDriver = $em->getConfiguration()->getMetadataCacheImpl(); + + if ( ! $cacheDriver) { + throw new \InvalidArgumentException('No Metadata cache driver is configured on given EntityManager.'); + } + + if ($cacheDriver instanceof ApcCache) { + throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); + } + + if ($cacheDriver instanceof XcacheCache) { + throw new \LogicException("Cannot clear XCache Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); + } + + $ui->comment('Clearing all Metadata cache entries'); + + $result = $cacheDriver->deleteAll(); + $message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.'; + + if (true === $input->getOption('flush')) { + $result = $cacheDriver->flushAll(); + $message = ($result) ? 'Successfully flushed cache entries.' : $message; + } + + if ( ! $result) { + $ui->error($message); + + return 1; + } + + $ui->success($message); + + return 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php new file mode 100644 index 0000000..95bec91 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php @@ -0,0 +1,111 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\ClearCache; + +use Doctrine\Common\Cache\ApcCache; +use Doctrine\Common\Cache\XcacheCache; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to clear the query cache of the various cache drivers. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class QueryCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:clear-cache:query') + ->setDescription('Clear all query cache of the various cache drivers') + ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, cache entries will be flushed instead of deleted/invalidated.') + ->setHelp(<<%command.name% command is meant to clear the query cache of associated Entity Manager. +It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider +instance completely. + +The execution type differ on how you execute the command. +If you want to invalidate the entries (and not delete from cache instance), this command would do the work: + +%command.name% + +Alternatively, if you want to flush the cache provider using this command: + +%command.name% --flush + +Finally, be aware that if --flush option is passed, not all cache providers are able to flush entries, +because of a limitation of its execution nature. +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + $em = $this->getHelper('em')->getEntityManager(); + $cacheDriver = $em->getConfiguration()->getQueryCacheImpl(); + + if ( ! $cacheDriver) { + throw new \InvalidArgumentException('No Query cache driver is configured on given EntityManager.'); + } + + if ($cacheDriver instanceof ApcCache) { + throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); + } + if ($cacheDriver instanceof XcacheCache) { + throw new \LogicException("Cannot clear XCache Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); + } + + $ui->comment('Clearing all Query cache entries'); + + $result = $cacheDriver->deleteAll(); + $message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.'; + + if (true === $input->getOption('flush')) { + $result = $cacheDriver->flushAll(); + $message = ($result) ? 'Successfully flushed cache entries.' : $message; + } + + if ( ! $result) { + $ui->error($message); + + return 1; + } + + $ui->success($message); + + return 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryRegionCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryRegionCommand.php new file mode 100644 index 0000000..36ffa12 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryRegionCommand.php @@ -0,0 +1,131 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\ClearCache; + +use Doctrine\ORM\Cache; +use Doctrine\ORM\Cache\Region\DefaultRegion; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to clear a query cache region. + * + * @since 2.5 + * @author Fabio B. Silva + */ +class QueryRegionCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:clear-cache:region:query') + ->setDescription('Clear a second-level cache query region') + ->addArgument('region-name', InputArgument::OPTIONAL, 'The query region to clear.') + ->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all query regions will be deleted/invalidated.') + ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, all cache entries will be flushed.') + ->setHelp(<<%command.name% command is meant to clear a second-level cache query region for an associated Entity Manager. +It is possible to delete/invalidate all query region, a specific query region or flushes the cache provider. + +The execution type differ on how you execute the command. +If you want to invalidate all entries for the default query region this command would do the work: + +%command.name% + +To invalidate entries for a specific query region you should use : + +%command.name% my_region_name + +If you want to invalidate all entries for the all query region: + +%command.name% --all + +Alternatively, if you want to flush the configured cache provider use this command: + +%command.name% my_region_name --flush + +Finally, be aware that if --flush option is passed, +not all cache providers are able to flush entries, because of a limitation of its execution nature. +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + $em = $this->getHelper('em')->getEntityManager(); + $name = $input->getArgument('region-name'); + $cache = $em->getCache(); + + if ($name === null) { + $name = Cache::DEFAULT_QUERY_REGION_NAME; + } + + if ( ! $cache instanceof Cache) { + throw new \InvalidArgumentException('No second-level cache is configured on the given EntityManager.'); + } + + if ($input->getOption('flush')) { + $queryCache = $cache->getQueryCache($name); + $queryRegion = $queryCache->getRegion(); + + if ( ! $queryRegion instanceof DefaultRegion) { + throw new \InvalidArgumentException(sprintf( + 'The option "--flush" expects a "Doctrine\ORM\Cache\Region\DefaultRegion", but got "%s".', + is_object($queryRegion) ? get_class($queryRegion) : gettype($queryRegion) + )); + } + + $queryRegion->getCache()->flushAll(); + + $ui->comment( + sprintf( + 'Flushing cache provider configured for second-level cache query region named "%s"', + $name + ) + ); + + return 0; + } + + if ($input->getOption('all')) { + $ui->comment('Clearing all second-level cache query regions'); + + $cache->evictQueryRegions(); + + return 0; + } + + $ui->comment(sprintf('Clearing second-level cache query region named "%s"', $name)); + $cache->evictQueryRegion($name); + + return 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php new file mode 100644 index 0000000..42ad79c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php @@ -0,0 +1,112 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\ClearCache; + +use Doctrine\Common\Cache\ApcCache; +use Doctrine\Common\Cache\XcacheCache; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to clear the result cache of the various cache drivers. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ResultCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:clear-cache:result') + ->setDescription('Clear all result cache of the various cache drivers') + ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, cache entries will be flushed instead of deleted/invalidated.') + ->setHelp(<<%command.name% command is meant to clear the result cache of associated Entity Manager. +It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider +instance completely. + +The execution type differ on how you execute the command. +If you want to invalidate the entries (and not delete from cache instance), this command would do the work: + +%command.name% + +Alternatively, if you want to flush the cache provider using this command: + +%command.name% --flush + +Finally, be aware that if --flush option is passed, not all cache providers are able to flush entries, +because of a limitation of its execution nature. +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + $em = $this->getHelper('em')->getEntityManager(); + $cacheDriver = $em->getConfiguration()->getResultCacheImpl(); + + if ( ! $cacheDriver) { + throw new \InvalidArgumentException('No Result cache driver is configured on given EntityManager.'); + } + + if ($cacheDriver instanceof ApcCache) { + throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); + } + + if ($cacheDriver instanceof XcacheCache) { + throw new \LogicException("Cannot clear XCache Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); + } + + $ui->comment('Clearing all Result cache entries'); + + $result = $cacheDriver->deleteAll(); + $message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.'; + + if (true === $input->getOption('flush')) { + $result = $cacheDriver->flushAll(); + $message = ($result) ? 'Successfully flushed cache entries.' : $message; + } + + if ( ! $result) { + $ui->error($message); + + return 1; + } + + $ui->success($message); + + return 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php new file mode 100644 index 0000000..90de732 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php @@ -0,0 +1,214 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Doctrine\ORM\Tools\ConvertDoctrine1Schema; +use Doctrine\ORM\Tools\EntityGenerator; +use Doctrine\ORM\Tools\Export\ClassMetadataExporter; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to convert a Doctrine 1 schema to a Doctrine 2 mapping file. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class ConvertDoctrine1SchemaCommand extends Command +{ + /** + * @var EntityGenerator|null + */ + private $entityGenerator = null; + + /** + * @var ClassMetadataExporter|null + */ + private $metadataExporter = null; + + /** + * @return EntityGenerator + */ + public function getEntityGenerator() + { + if ($this->entityGenerator == null) { + $this->entityGenerator = new EntityGenerator(); + } + + return $this->entityGenerator; + } + + /** + * @param EntityGenerator $entityGenerator + * + * @return void + */ + public function setEntityGenerator(EntityGenerator $entityGenerator) + { + $this->entityGenerator = $entityGenerator; + } + + /** + * @return ClassMetadataExporter + */ + public function getMetadataExporter() + { + if ($this->metadataExporter == null) { + $this->metadataExporter = new ClassMetadataExporter(); + } + + return $this->metadataExporter; + } + + /** + * @param ClassMetadataExporter $metadataExporter + * + * @return void + */ + public function setMetadataExporter(ClassMetadataExporter $metadataExporter) + { + $this->metadataExporter = $metadataExporter; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:convert-d1-schema') + ->setAliases(['orm:convert:d1-schema']) + ->setDescription('Converts Doctrine 1.x schema into a Doctrine 2.x schema') + ->addArgument('from-path', InputArgument::REQUIRED, 'The path of Doctrine 1.X schema information.') + ->addArgument('to-type', InputArgument::REQUIRED, 'The destination Doctrine 2.X mapping type.') + ->addArgument('dest-path', InputArgument::REQUIRED, 'The path to generate your Doctrine 2.X mapping information.') + ->addOption('from', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Optional paths of Doctrine 1.X schema information.', []) + ->addOption('extend', null, InputOption::VALUE_OPTIONAL, 'Defines a base class to be extended by generated entity classes.') + ->addOption('num-spaces', null, InputOption::VALUE_OPTIONAL, 'Defines the number of indentation spaces', 4) + ->setHelp('Converts Doctrine 1.x schema into a Doctrine 2.x schema.'); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + $ui->warning('Command ' . $this->getName() . ' is deprecated and will be removed in Doctrine ORM 3.0.'); + + // Process source directories + $fromPaths = array_merge([$input->getArgument('from-path')], $input->getOption('from')); + + // Process destination directory + $destPath = realpath($input->getArgument('dest-path')); + + $toType = $input->getArgument('to-type'); + $extend = $input->getOption('extend'); + $numSpaces = $input->getOption('num-spaces'); + + $this->convertDoctrine1Schema($fromPaths, $destPath, $toType, $numSpaces, $extend, $output); + + return 0; + } + + /** + * @param array $fromPaths + * @param string $destPath + * @param string $toType + * @param int $numSpaces + * @param string|null $extend + * @param OutputInterface $output + * + * @throws \InvalidArgumentException + */ + public function convertDoctrine1Schema(array $fromPaths, $destPath, $toType, $numSpaces, $extend, OutputInterface $output) + { + foreach ($fromPaths as &$dirName) { + $dirName = realpath($dirName); + + if ( ! file_exists($dirName)) { + throw new \InvalidArgumentException( + sprintf("Doctrine 1.X schema directory '%s' does not exist.", $dirName) + ); + } + + if ( ! is_readable($dirName)) { + throw new \InvalidArgumentException( + sprintf("Doctrine 1.X schema directory '%s' does not have read permissions.", $dirName) + ); + } + } + + if ( ! file_exists($destPath)) { + throw new \InvalidArgumentException( + sprintf("Doctrine 2.X mapping destination directory '%s' does not exist.", $destPath) + ); + } + + if ( ! is_writable($destPath)) { + throw new \InvalidArgumentException( + sprintf("Doctrine 2.X mapping destination directory '%s' does not have write permissions.", $destPath) + ); + } + + $cme = $this->getMetadataExporter(); + $exporter = $cme->getExporter($toType, $destPath); + + if (strtolower($toType) === 'annotation') { + $entityGenerator = $this->getEntityGenerator(); + $exporter->setEntityGenerator($entityGenerator); + + $entityGenerator->setNumSpaces($numSpaces); + + if ($extend !== null) { + $entityGenerator->setClassToExtend($extend); + } + } + + $converter = new ConvertDoctrine1Schema($fromPaths); + $metadata = $converter->getMetadata(); + + if ($metadata) { + $output->writeln(''); + + foreach ($metadata as $class) { + $output->writeln(sprintf('Processing entity "%s"', $class->name)); + } + + $exporter->setMetadata($metadata); + $exporter->export(); + + $output->writeln(PHP_EOL . sprintf( + 'Converting Doctrine 1.X schema to "%s" mapping type in "%s"', $toType, $destPath + )); + } else { + $output->writeln('No Metadata Classes to process.'); + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php new file mode 100644 index 0000000..8de2b84 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php @@ -0,0 +1,186 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Doctrine\ORM\Mapping\Driver\DatabaseDriver; +use Doctrine\ORM\Tools\Console\MetadataFilter; +use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory; +use Doctrine\ORM\Tools\EntityGenerator; +use Doctrine\ORM\Tools\Export\ClassMetadataExporter; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to convert your mapping information between the various formats. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ConvertMappingCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:convert-mapping') + ->setAliases(['orm:convert:mapping']) + ->setDescription('Convert mapping information between supported formats') + ->addArgument('to-type', InputArgument::REQUIRED, 'The mapping type to be converted.') + ->addArgument('dest-path', InputArgument::REQUIRED, 'The path to generate your entities classes.') + ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be processed.') + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force to overwrite existing mapping files.') + ->addOption('from-database', null, null, 'Whether or not to convert mapping information from existing database.') + ->addOption('extend', null, InputOption::VALUE_OPTIONAL, 'Defines a base class to be extended by generated entity classes.') + ->addOption('num-spaces', null, InputOption::VALUE_OPTIONAL, 'Defines the number of indentation spaces', 4) + ->addOption('namespace', null, InputOption::VALUE_OPTIONAL, 'Defines a namespace for the generated entity classes, if converted from database.') + ->setHelp(<<one-time command. It should not be necessary for +you to call this method multiple times, especially when using the --from-database +flag. + +Converting an existing database schema into mapping files only solves about 70-80% +of the necessary mapping information. Additionally the detection from an existing +database cannot detect inverse associations, inheritance types, +entities with foreign keys as primary keys and many of the +semantical operations on associations such as cascade. + +Hint: There is no need to convert YAML or XML mapping files to annotations +every time you make changes. All mapping drivers are first class citizens +in Doctrine 2 and can be used as runtime mapping for the ORM. + +Hint: If you have a database with tables that should not be managed +by the ORM, you can use a DBAL functionality to filter the tables and sequences down +on a global level: + + \$config->setFilterSchemaAssetsExpression(\$regexp); +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + $em = $this->getHelper('em')->getEntityManager(); + + if ($input->getOption('from-database') === true) { + $databaseDriver = new DatabaseDriver( + $em->getConnection()->getSchemaManager() + ); + + $em->getConfiguration()->setMetadataDriverImpl( + $databaseDriver + ); + + if (($namespace = $input->getOption('namespace')) !== null) { + $databaseDriver->setNamespace($namespace); + } + } + + $cmf = new DisconnectedClassMetadataFactory(); + $cmf->setEntityManager($em); + $metadata = $cmf->getAllMetadata(); + $metadata = MetadataFilter::filter($metadata, $input->getOption('filter')); + + // Process destination directory + if ( ! is_dir($destPath = $input->getArgument('dest-path'))) { + mkdir($destPath, 0775, true); + } + $destPath = realpath($destPath); + + if ( ! file_exists($destPath)) { + throw new \InvalidArgumentException( + sprintf("Mapping destination directory '%s' does not exist.", $input->getArgument('dest-path')) + ); + } + + if ( ! is_writable($destPath)) { + throw new \InvalidArgumentException( + sprintf("Mapping destination directory '%s' does not have write permissions.", $destPath) + ); + } + + $toType = strtolower($input->getArgument('to-type')); + + $exporter = $this->getExporter($toType, $destPath); + $exporter->setOverwriteExistingFiles($input->getOption('force')); + + if ($toType == 'annotation') { + $entityGenerator = new EntityGenerator(); + $exporter->setEntityGenerator($entityGenerator); + + $entityGenerator->setNumSpaces($input->getOption('num-spaces')); + + if (($extend = $input->getOption('extend')) !== null) { + $entityGenerator->setClassToExtend($extend); + } + } + + if (empty($metadata)) { + $ui->success('No Metadata Classes to process.'); + return; + } + + foreach ($metadata as $class) { + $ui->text(sprintf('Processing entity "%s"', $class->name)); + } + + $exporter->setMetadata($metadata); + $exporter->export(); + + $ui->newLine(); + $ui->text( + sprintf( + 'Exporting "%s" mapping information to "%s"', + $toType, + $destPath + ) + ); + + return 0; + } + + /** + * @param string $toType + * @param string $destPath + * + * @return \Doctrine\ORM\Tools\Export\Driver\AbstractExporter + */ + protected function getExporter($toType, $destPath) + { + $cme = new ClassMetadataExporter(); + + return $cme->getExporter($toType, $destPath); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php new file mode 100644 index 0000000..eb0ff17 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php @@ -0,0 +1,78 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Throwable; + +/** + * Command to ensure that Doctrine is properly configured for a production environment. + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class EnsureProductionSettingsCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:ensure-production-settings') + ->setDescription('Verify that Doctrine is properly configured for a production environment') + ->addOption('complete', null, InputOption::VALUE_NONE, 'Flag to also inspect database connection existence.') + ->setHelp('Verify that Doctrine is properly configured for a production environment.'); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + $em = $this->getHelper('em')->getEntityManager(); + + try { + $em->getConfiguration()->ensureProductionSettings(); + + if ($input->getOption('complete') !== null) { + $em->getConnection()->connect(); + } + } catch (Throwable $e) { + $ui->error($e->getMessage()); + + return 1; + } + + $ui->success('Environment is correctly configured for production.'); + + return 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php new file mode 100644 index 0000000..f1bba22 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php @@ -0,0 +1,147 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Doctrine\ORM\Tools\Console\MetadataFilter; +use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory; +use Doctrine\ORM\Tools\EntityGenerator; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to generate entity classes and method stubs from your mapping information. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class GenerateEntitiesCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:generate-entities') + ->setAliases(['orm:generate:entities']) + ->setDescription('Generate entity classes and method stubs from your mapping information') + ->addArgument('dest-path', InputArgument::REQUIRED, 'The path to generate your entity classes.') + ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be processed.') + ->addOption('generate-annotations', null, InputOption::VALUE_OPTIONAL, 'Flag to define if generator should generate annotation metadata on entities.', false) + ->addOption('generate-methods', null, InputOption::VALUE_OPTIONAL, 'Flag to define if generator should generate stub methods on entities.', true) + ->addOption('regenerate-entities', null, InputOption::VALUE_OPTIONAL, 'Flag to define if generator should regenerate entity if it exists.', false) + ->addOption('update-entities', null, InputOption::VALUE_OPTIONAL, 'Flag to define if generator should only update entity if it exists.', true) + ->addOption('extend', null, InputOption::VALUE_REQUIRED, 'Defines a base class to be extended by generated entity classes.') + ->addOption('num-spaces', null, InputOption::VALUE_REQUIRED, 'Defines the number of indentation spaces', 4) + ->addOption('no-backup', null, InputOption::VALUE_NONE, 'Flag to define if generator should avoid backuping existing entity file if it exists.') + ->setHelp(<<--update-entities or --regenerate-entities flags your existing +code gets overwritten. The EntityGenerator will only append new code to your +file and will not delete the old code. However this approach may still be prone +to error and we suggest you use code repositories such as GIT or SVN to make +backups of your code. + +It makes sense to generate the entity code if you are using entities as Data +Access Objects only and don't put much additional logic on them. If you are +however putting much more logic on the entities you should refrain from using +the entity-generator and code your entities manually. + +Important: Even if you specified Inheritance options in your +XML or YAML Mapping files the generator cannot generate the base and +child classes for you correctly, because it doesn't know which +class is supposed to extend which. You have to adjust the entity +code manually for inheritance to work! +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + $ui->warning('Command ' . $this->getName() . ' is deprecated and will be removed in Doctrine ORM 3.0.'); + + $em = $this->getHelper('em')->getEntityManager(); + + $cmf = new DisconnectedClassMetadataFactory(); + $cmf->setEntityManager($em); + $metadatas = $cmf->getAllMetadata(); + $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter')); + + // Process destination directory + $destPath = realpath($input->getArgument('dest-path')); + + if ( ! file_exists($destPath)) { + throw new \InvalidArgumentException( + sprintf("Entities destination directory '%s' does not exist.", $input->getArgument('dest-path')) + ); + } + + if ( ! is_writable($destPath)) { + throw new \InvalidArgumentException( + sprintf("Entities destination directory '%s' does not have write permissions.", $destPath) + ); + } + + if (empty($metadatas)) { + $ui->success('No Metadata Classes to process.'); + return 0; + } + + $entityGenerator = new EntityGenerator(); + + $entityGenerator->setGenerateAnnotations($input->getOption('generate-annotations')); + $entityGenerator->setGenerateStubMethods($input->getOption('generate-methods')); + $entityGenerator->setRegenerateEntityIfExists($input->getOption('regenerate-entities')); + $entityGenerator->setUpdateEntityIfExists($input->getOption('update-entities')); + $entityGenerator->setNumSpaces($input->getOption('num-spaces')); + $entityGenerator->setBackupExisting(!$input->getOption('no-backup')); + + if (($extend = $input->getOption('extend')) !== null) { + $entityGenerator->setClassToExtend($extend); + } + + foreach ($metadatas as $metadata) { + $ui->text(sprintf('Processing entity "%s"', $metadata->name)); + } + + // Generating Entities + $entityGenerator->generate($metadatas, $destPath); + + // Outputting information message + $ui->newLine(); + $ui->success(sprintf('Entity classes generated to "%s"', $destPath)); + + return 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php new file mode 100644 index 0000000..2cace34 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php @@ -0,0 +1,110 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Tools\Console\MetadataFilter; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to (re)generate the proxy classes used by doctrine. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class GenerateProxiesCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:generate-proxies') + ->setAliases(['orm:generate:proxies']) + ->setDescription('Generates proxy classes for entity classes') + ->addArgument('dest-path', InputArgument::OPTIONAL, 'The path to generate your proxy classes. If none is provided, it will attempt to grab from configuration.') + ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be processed.') + ->setHelp('Generates proxy classes for entity classes.'); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + /** @var EntityManagerInterface $em */ + $em = $this->getHelper('em')->getEntityManager(); + + $metadatas = $em->getMetadataFactory()->getAllMetadata(); + $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter')); + + // Process destination directory + if (($destPath = $input->getArgument('dest-path')) === null) { + $destPath = $em->getConfiguration()->getProxyDir(); + } + + if ( ! is_dir($destPath)) { + mkdir($destPath, 0775, true); + } + + $destPath = realpath($destPath); + + if ( ! file_exists($destPath)) { + throw new \InvalidArgumentException( + sprintf("Proxies destination directory '%s' does not exist.", $em->getConfiguration()->getProxyDir()) + ); + } + + if ( ! is_writable($destPath)) { + throw new \InvalidArgumentException( + sprintf("Proxies destination directory '%s' does not have write permissions.", $destPath) + ); + } + + if (empty($metadatas)) { + $ui->success('No Metadata Classes to process.'); + return 0; + } + + foreach ($metadatas as $metadata) { + $ui->text(sprintf('Processing entity "%s"', $metadata->name)); + } + + // Generating Proxies + $em->getProxyFactory()->generateProxyClasses($metadatas, $destPath); + + // Outputting information message + $ui->newLine(); + $ui->text(sprintf('Proxy classes generated to "%s"', $destPath)); + + return 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php new file mode 100644 index 0000000..379c935 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php @@ -0,0 +1,119 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Doctrine\ORM\Tools\Console\MetadataFilter; +use Doctrine\ORM\Tools\EntityRepositoryGenerator; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to generate repository classes for mapping information. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class GenerateRepositoriesCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:generate-repositories') + ->setAliases(['orm:generate:repositories']) + ->setDescription('Generate repository classes from your mapping information') + ->addArgument('dest-path', InputArgument::REQUIRED, 'The path to generate your repository classes.') + ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be processed.') + ->setHelp('Generate repository classes from your mapping information.'); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + $ui->warning('Command ' . $this->getName() . ' is deprecated and will be removed in Doctrine ORM 3.0.'); + + $em = $this->getHelper('em')->getEntityManager(); + + $metadatas = $em->getMetadataFactory()->getAllMetadata(); + $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter')); + + $repositoryName = $em->getConfiguration()->getDefaultRepositoryClassName(); + + // Process destination directory + $destPath = realpath($input->getArgument('dest-path')); + + if ( ! file_exists($destPath)) { + throw new \InvalidArgumentException( + sprintf("Entities destination directory '%s' does not exist.", $input->getArgument('dest-path')) + ); + } + + if ( ! is_writable($destPath)) { + throw new \InvalidArgumentException( + sprintf("Entities destination directory '%s' does not have write permissions.", $destPath) + ); + } + + if (empty($metadatas)) { + $ui->success('No Metadata Classes to process.'); + return 0; + } + + $numRepositories = 0; + $generator = new EntityRepositoryGenerator(); + + $generator->setDefaultRepositoryName($repositoryName); + + foreach ($metadatas as $metadata) { + if ($metadata->customRepositoryClassName) { + $ui->text(sprintf('Processing repository "%s"', $metadata->customRepositoryClassName)); + + $generator->writeEntityRepositoryClass($metadata->customRepositoryClassName, $destPath); + + ++$numRepositories; + } + } + + if ($numRepositories === 0) { + $ui->text('No Repository classes were found to be processed.'); + return 0; + } + + // Outputting information message + $ui->newLine(); + $ui->text(sprintf('Repository classes generated to "%s"', $destPath)); + + return 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php new file mode 100644 index 0000000..89f6c31 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php @@ -0,0 +1,101 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Doctrine\ORM\Mapping\MappingException; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Show information about mapped entities. + * + * @link www.doctrine-project.org + * @since 2.1 + * @author Benjamin Eberlei + */ +class InfoCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:info') + ->setDescription('Show basic information about all mapped entities') + ->setHelp(<<%command.name% shows basic information about which +entities exist and possibly if their mapping information contains errors or +not. +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + /* @var $entityManager \Doctrine\ORM\EntityManager */ + $entityManager = $this->getHelper('em')->getEntityManager(); + + $entityClassNames = $entityManager->getConfiguration() + ->getMetadataDriverImpl() + ->getAllClassNames(); + + if ( ! $entityClassNames) { + $ui->caution( + [ + 'You do not have any mapped Doctrine ORM entities according to the current configuration.', + 'If you have entities or mapping files you should check your mapping configuration for errors.' + ] + ); + + return 1; + } + + $ui->text(sprintf("Found %d mapped entities:", count($entityClassNames))); + $ui->newLine(); + + $failure = false; + + foreach ($entityClassNames as $entityClassName) { + try { + $entityManager->getClassMetadata($entityClassName); + $ui->text(sprintf("[OK] %s", $entityClassName)); + } catch (MappingException $e) { + $ui->text( + [ + sprintf("[FAIL] %s", $entityClassName), + sprintf("%s", $e->getMessage()), + '' + ] + ); + + $failure = true; + } + } + + return $failure ? 1 : 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php new file mode 100644 index 0000000..0e1f505 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -0,0 +1,284 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Doctrine\Common\Persistence\Mapping\MappingException; +use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use const JSON_PRETTY_PRINT; +use const JSON_UNESCAPED_SLASHES; +use const JSON_UNESCAPED_UNICODE; +use function json_encode; + +/** + * Show information about mapped entities. + * + * @link www.doctrine-project.org + * @since 2.4 + * @author Daniel Leech + */ +final class MappingDescribeCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:mapping:describe') + ->addArgument('entityName', InputArgument::REQUIRED, 'Full or partial name of entity') + ->setDescription('Display information about mapped objects') + ->setHelp(<<%command.full_name% My\Namespace\Entity\MyEntity + +Or: + + %command.full_name% MyEntity +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + /* @var $entityManager \Doctrine\ORM\EntityManagerInterface */ + $entityManager = $this->getHelper('em')->getEntityManager(); + + $this->displayEntity($input->getArgument('entityName'), $entityManager, $ui); + + return 0; + } + + /** + * Display all the mapping information for a single Entity. + * + * @param string $entityName Full or partial entity class name + * @param EntityManagerInterface $entityManager + * @param SymfonyStyle $ui + */ + private function displayEntity($entityName, EntityManagerInterface $entityManager, SymfonyStyle $ui) + { + $metadata = $this->getClassMetadata($entityName, $entityManager); + + $ui->table( + ['Field', 'Value'], + array_merge( + [ + $this->formatField('Name', $metadata->name), + $this->formatField('Root entity name', $metadata->rootEntityName), + $this->formatField('Custom generator definition', $metadata->customGeneratorDefinition), + $this->formatField('Custom repository class', $metadata->customRepositoryClassName), + $this->formatField('Mapped super class?', $metadata->isMappedSuperclass), + $this->formatField('Embedded class?', $metadata->isEmbeddedClass), + $this->formatField('Parent classes', $metadata->parentClasses), + $this->formatField('Sub classes', $metadata->subClasses), + $this->formatField('Embedded classes', $metadata->subClasses), + $this->formatField('Named queries', $metadata->namedQueries), + $this->formatField('Named native queries', $metadata->namedNativeQueries), + $this->formatField('SQL result set mappings', $metadata->sqlResultSetMappings), + $this->formatField('Identifier', $metadata->identifier), + $this->formatField('Inheritance type', $metadata->inheritanceType), + $this->formatField('Discriminator column', $metadata->discriminatorColumn), + $this->formatField('Discriminator value', $metadata->discriminatorValue), + $this->formatField('Discriminator map', $metadata->discriminatorMap), + $this->formatField('Generator type', $metadata->generatorType), + $this->formatField('Table', $metadata->table), + $this->formatField('Composite identifier?', $metadata->isIdentifierComposite), + $this->formatField('Foreign identifier?', $metadata->containsForeignIdentifier), + $this->formatField('Sequence generator definition', $metadata->sequenceGeneratorDefinition), + $this->formatField('Table generator definition', $metadata->tableGeneratorDefinition), + $this->formatField('Change tracking policy', $metadata->changeTrackingPolicy), + $this->formatField('Versioned?', $metadata->isVersioned), + $this->formatField('Version field', $metadata->versionField), + $this->formatField('Read only?', $metadata->isReadOnly), + + $this->formatEntityListeners($metadata->entityListeners), + ], + [$this->formatField('Association mappings:', '')], + $this->formatMappings($metadata->associationMappings), + [$this->formatField('Field mappings:', '')], + $this->formatMappings($metadata->fieldMappings) + ) + ); + } + + /** + * Return all mapped entity class names + * + * @param EntityManagerInterface $entityManager + * + * @return string[] + */ + private function getMappedEntities(EntityManagerInterface $entityManager) + { + $entityClassNames = $entityManager->getConfiguration() + ->getMetadataDriverImpl() + ->getAllClassNames(); + + if ( ! $entityClassNames) { + throw new \InvalidArgumentException( + 'You do not have any mapped Doctrine ORM entities according to the current configuration. '. + 'If you have entities or mapping files you should check your mapping configuration for errors.' + ); + } + + return $entityClassNames; + } + + /** + * Return the class metadata for the given entity + * name + * + * @param string $entityName Full or partial entity name + * @param EntityManagerInterface $entityManager + * + * @return \Doctrine\ORM\Mapping\ClassMetadata + */ + private function getClassMetadata($entityName, EntityManagerInterface $entityManager) + { + try { + return $entityManager->getClassMetadata($entityName); + } catch (MappingException $e) { + } + + $matches = array_filter( + $this->getMappedEntities($entityManager), + function ($mappedEntity) use ($entityName) { + return preg_match('{' . preg_quote($entityName) . '}', $mappedEntity); + } + ); + + if ( ! $matches) { + throw new \InvalidArgumentException(sprintf( + 'Could not find any mapped Entity classes matching "%s"', + $entityName + )); + } + + if (count($matches) > 1) { + throw new \InvalidArgumentException(sprintf( + 'Entity name "%s" is ambiguous, possible matches: "%s"', + $entityName, implode(', ', $matches) + )); + } + + return $entityManager->getClassMetadata(current($matches)); + } + + /** + * Format the given value for console output + * + * @param mixed $value + * + * @return string + */ + private function formatValue($value) + { + if ('' === $value) { + return ''; + } + + if (null === $value) { + return 'Null'; + } + + if (is_bool($value)) { + return '' . ($value ? 'True' : 'False') . ''; + } + + if (empty($value)) { + return 'Empty'; + } + + if (is_array($value)) { + return json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT); + } + + if (is_object($value)) { + return sprintf('<%s>', get_class($value)); + } + + if (is_scalar($value)) { + return $value; + } + + throw new \InvalidArgumentException(sprintf('Do not know how to format value "%s"', print_r($value, true))); + } + + /** + * Add the given label and value to the two column table output + * + * @param string $label Label for the value + * @param mixed $value A Value to show + * + * @return array + */ + private function formatField($label, $value) + { + if (null === $value) { + $value = 'None'; + } + + return [sprintf('%s', $label), $this->formatValue($value)]; + } + + /** + * Format the association mappings + * + * @param array $propertyMappings + * + * @return array + */ + private function formatMappings(array $propertyMappings) + { + $output = []; + + foreach ($propertyMappings as $propertyName => $mapping) { + $output[] = $this->formatField(sprintf(' %s', $propertyName), ''); + + foreach ($mapping as $field => $value) { + $output[] = $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); + } + } + + return $output; + } + + /** + * Format the entity listeners + * + * @param array $entityListeners + * + * @return array + */ + private function formatEntityListeners(array $entityListeners) + { + return $this->formatField('Entity listeners', array_map('get_class', $entityListeners)); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php new file mode 100644 index 0000000..7f40692 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php @@ -0,0 +1,116 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Doctrine\Common\Util\Debug; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to execute DQL queries in a given EntityManager. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class RunDqlCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:run-dql') + ->setDescription('Executes arbitrary DQL directly from the command line') + ->addArgument('dql', InputArgument::REQUIRED, 'The DQL to execute.') + ->addOption('hydrate', null, InputOption::VALUE_REQUIRED, 'Hydration mode of result set. Should be either: object, array, scalar or single-scalar.', 'object') + ->addOption('first-result', null, InputOption::VALUE_REQUIRED, 'The first result in the result set.') + ->addOption('max-result', null, InputOption::VALUE_REQUIRED, 'The maximum number of results in the result set.') + ->addOption('depth', null, InputOption::VALUE_REQUIRED, 'Dumping depth of Entity graph.', 7) + ->addOption('show-sql', null, InputOption::VALUE_NONE, 'Dump generated SQL instead of executing query') + ->setHelp('Executes arbitrary DQL directly from the command line.'); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + /* @var $em \Doctrine\ORM\EntityManagerInterface */ + $em = $this->getHelper('em')->getEntityManager(); + + if (($dql = $input->getArgument('dql')) === null) { + throw new \RuntimeException("Argument 'dql' is required in order to execute this command correctly."); + } + + $depth = $input->getOption('depth'); + + if ( ! is_numeric($depth)) { + throw new \LogicException("Option 'depth' must contain an integer value"); + } + + $hydrationModeName = $input->getOption('hydrate'); + $hydrationMode = 'Doctrine\ORM\Query::HYDRATE_' . strtoupper(str_replace('-', '_', $hydrationModeName)); + + if ( ! defined($hydrationMode)) { + throw new \RuntimeException( + "Hydration mode '$hydrationModeName' does not exist. It should be either: object. array, scalar or single-scalar." + ); + } + + $query = $em->createQuery($dql); + + if (($firstResult = $input->getOption('first-result')) !== null) { + if ( ! is_numeric($firstResult)) { + throw new \LogicException("Option 'first-result' must contain an integer value"); + } + + $query->setFirstResult((int) $firstResult); + } + + if (($maxResult = $input->getOption('max-result')) !== null) { + if ( ! is_numeric($maxResult)) { + throw new \LogicException("Option 'max-result' must contain an integer value"); + } + + $query->setMaxResults((int) $maxResult); + } + + if ($input->getOption('show-sql')) { + $ui->text($query->getSQL()); + return 0; + } + + $resultSet = $query->execute([], constant($hydrationMode)); + + $ui->text(Debug::dump($resultSet, $input->getOption('depth'), true, false)); + + return 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/AbstractCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/AbstractCommand.php new file mode 100644 index 0000000..21907d0 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/AbstractCommand.php @@ -0,0 +1,72 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; + +use Doctrine\ORM\Tools\SchemaTool; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Base class for CreateCommand, DropCommand and UpdateCommand. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +abstract class AbstractCommand extends Command +{ + /** + * @param InputInterface $input + * @param OutputInterface $output + * @param SchemaTool $schemaTool + * @param array $metadatas + * + * @return null|int Null or 0 if everything went fine, or an error code. + */ + abstract protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui); + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + $emHelper = $this->getHelper('em'); + + /* @var $em \Doctrine\ORM\EntityManager */ + $em = $emHelper->getEntityManager(); + + $metadatas = $em->getMetadataFactory()->getAllMetadata(); + + if (empty($metadatas)) { + $ui->success('No Metadata Classes to process.'); + + return 0; + } + + return $this->executeSchemaCommand($input, $output, new SchemaTool($em), $metadatas, $ui); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php new file mode 100644 index 0000000..0c21374 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php @@ -0,0 +1,90 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; + +use Doctrine\ORM\Tools\SchemaTool; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to create the database schema for a set of classes based on their mappings. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class CreateCommand extends AbstractCommand +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:schema-tool:create') + ->setDescription('Processes the schema and either create it directly on EntityManager Storage Connection or generate the SQL output') + ->addOption('dump-sql', null, InputOption::VALUE_NONE, 'Instead of trying to apply generated SQLs into EntityManager Storage Connection, output them.') + ->setHelp(<<Hint: If you have a database with tables that should not be managed +by the ORM, you can use a DBAL functionality to filter the tables and sequences down +on a global level: + + \$config->setFilterSchemaAssetsExpression(\$regexp); +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui) + { + $dumpSql = true === $input->getOption('dump-sql'); + + if ($dumpSql) { + $sqls = $schemaTool->getCreateSchemaSql($metadatas); + $ui->text('The following SQL statements will be executed:'); + $ui->newLine(); + + foreach ($sqls as $sql) { + $ui->text(sprintf(' %s;', $sql)); + } + + return 0; + } + + $ui->caution('This operation should not be executed in a production environment!'); + + $ui->text('Creating database schema...'); + $ui->newLine(); + + $schemaTool->createSchema($metadatas); + + $ui->success('Database schema created successfully!'); + + return 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php new file mode 100644 index 0000000..3d77fc8 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php @@ -0,0 +1,130 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; + +use Doctrine\ORM\Tools\SchemaTool; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to drop the database schema for a set of classes based on their mappings. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class DropCommand extends AbstractCommand +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:schema-tool:drop') + ->setDescription('Drop the complete database schema of EntityManager Storage Connection or generate the corresponding SQL output') + ->addOption('dump-sql', null, InputOption::VALUE_NONE, 'Instead of trying to apply generated SQLs into EntityManager Storage Connection, output them.') + ->addOption('force', 'f', InputOption::VALUE_NONE, "Don't ask for the deletion of the database, but force the operation to run.") + ->addOption('full-database', null, InputOption::VALUE_NONE, 'Instead of using the Class Metadata to detect the database table schema, drop ALL assets that the database contains.') + ->setHelp(<<Hint: If you have a database with tables that should not be managed +by the ORM, you can use a DBAL functionality to filter the tables and sequences down +on a global level: + + \$config->setFilterSchemaAssetsExpression(\$regexp); +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui) + { + $isFullDatabaseDrop = $input->getOption('full-database'); + $dumpSql = true === $input->getOption('dump-sql'); + $force = true === $input->getOption('force'); + + if ($dumpSql) { + if ($isFullDatabaseDrop) { + $sqls = $schemaTool->getDropDatabaseSQL(); + } else { + $sqls = $schemaTool->getDropSchemaSQL($metadatas); + } + $ui->text('The following SQL statements will be executed:'); + $ui->newLine(); + + foreach ($sqls as $sql) { + $ui->text(sprintf(' %s;', $sql)); + } + + return 0; + } + + if ($force) { + $ui->text('Dropping database schema...'); + $ui->newLine(); + + if ($isFullDatabaseDrop) { + $schemaTool->dropDatabase(); + } else { + $schemaTool->dropSchema($metadatas); + } + + $ui->success('Database schema dropped successfully!'); + + return 0; + } + + $ui->caution('This operation should not be executed in a production environment!'); + + if ($isFullDatabaseDrop) { + $sqls = $schemaTool->getDropDatabaseSQL(); + } else { + $sqls = $schemaTool->getDropSchemaSQL($metadatas); + } + + if (empty($sqls)) { + $ui->success('Nothing to drop. The database is empty!'); + + return 0; + } + + $ui->text( + [ + sprintf('The Schema-Tool would execute "%s" queries to update the database.', count($sqls)), + '', + 'Please run the operation by passing one - or both - of the following options:', + '', + sprintf(' %s --force to execute the command', $this->getName()), + sprintf(' %s --dump-sql to dump the SQL statements to the screen', $this->getName()), + ] + ); + + return 1; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php new file mode 100644 index 0000000..c905977 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php @@ -0,0 +1,159 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; + +use Doctrine\ORM\Tools\SchemaTool; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to generate the SQL needed to update the database schema to match + * the current mapping information. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Ryan Weaver + */ +class UpdateCommand extends AbstractCommand +{ + /** + * @var string + */ + protected $name = 'orm:schema-tool:update'; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName($this->name) + ->setDescription('Executes (or dumps) the SQL needed to update the database schema to match the current mapping metadata') + ->addOption('complete', null, InputOption::VALUE_NONE, 'If defined, all assets of the database which are not relevant to the current metadata will be dropped.') + ->addOption('dump-sql', null, InputOption::VALUE_NONE, 'Dumps the generated SQL statements to the screen (does not execute them).') + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Causes the generated SQL statements to be physically executed against your database.') + ->setHelp(<<%command.name% command generates the SQL needed to +synchronize the database schema with the current mapping metadata of the +default entity manager. + +For example, if you add metadata for a new column to an entity, this command +would generate and output the SQL needed to add the new column to the database: + +%command.name% --dump-sql + +Alternatively, you can execute the generated queries: + +%command.name% --force + +If both options are specified, the queries are output and then executed: + +%command.name% --dump-sql --force + +Finally, be aware that if the --complete option is passed, this +task will drop all database assets (e.g. tables, etc) that are *not* described +by the current metadata. In other words, without this option, this task leaves +untouched any "extra" tables that exist in the database, but which aren't +described by any metadata. + +Hint: If you have a database with tables that should not be managed +by the ORM, you can use a DBAL functionality to filter the tables and sequences down +on a global level: + + \$config->setFilterSchemaAssetsExpression(\$regexp); +EOT + ); + } + + /** + * {@inheritdoc} + */ + protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui) + { + // Defining if update is complete or not (--complete not defined means $saveMode = true) + $saveMode = ! $input->getOption('complete'); + + $sqls = $schemaTool->getUpdateSchemaSql($metadatas, $saveMode); + + if (empty($sqls)) { + $ui->success('Nothing to update - your database is already in sync with the current entity metadata.'); + + return 0; + } + + $dumpSql = true === $input->getOption('dump-sql'); + $force = true === $input->getOption('force'); + + if ($dumpSql) { + $ui->text('The following SQL statements will be executed:'); + $ui->newLine(); + + foreach ($sqls as $sql) { + $ui->text(sprintf(' %s;', $sql)); + } + } + + if ($force) { + if ($dumpSql) { + $ui->newLine(); + } + $ui->text('Updating database schema...'); + $ui->newLine(); + + $schemaTool->updateSchema($metadatas, $saveMode); + + $pluralization = (1 === count($sqls)) ? 'query was' : 'queries were'; + + $ui->text(sprintf(' %s %s executed', count($sqls), $pluralization)); + $ui->success('Database schema updated successfully!'); + } + + if ($dumpSql || $force) { + return 0; + } + + $ui->caution( + [ + 'This operation should not be executed in a production environment!', + '', + 'Use the incremental update to detect changes during development and use', + 'the SQL DDL provided to manually update your database in production.', + ] + ); + + $ui->text( + [ + sprintf('The Schema-Tool would execute "%s" queries to update the database.', count($sqls)), + '', + 'Please run the operation by passing one - or both - of the following options:', + '', + sprintf(' %s --force to execute the command', $this->getName()), + sprintf(' %s --dump-sql to dump the SQL statements to the screen', $this->getName()), + ] + ); + + return 1; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ValidateSchemaCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ValidateSchemaCommand.php new file mode 100644 index 0000000..343d3b5 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ValidateSchemaCommand.php @@ -0,0 +1,100 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console\Command; + +use Doctrine\ORM\Tools\SchemaValidator; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Command to validate that the current mapping is valid. + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.com + * @since 1.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ValidateSchemaCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName('orm:validate-schema') + ->setDescription('Validate the mapping files') + ->addOption('skip-mapping', null, InputOption::VALUE_NONE, 'Skip the mapping validation check') + ->addOption('skip-sync', null, InputOption::VALUE_NONE, 'Skip checking if the mapping is in sync with the database') + ->setHelp('Validate that the mapping files are correct and in sync with the database.'); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $ui = new SymfonyStyle($input, $output); + + $em = $this->getHelper('em')->getEntityManager(); + $validator = new SchemaValidator($em); + $exit = 0; + + $ui->section('Mapping'); + + if ($input->getOption('skip-mapping')) { + $ui->text('[SKIPPED] The mapping was not checked.'); + } elseif ($errors = $validator->validateMapping()) { + foreach ($errors as $className => $errorMessages) { + $ui->text( + sprintf( + '[FAIL] The entity-class %s mapping is invalid:', + $className + ) + ); + + $ui->listing($errorMessages); + $ui->newLine(); + } + + ++$exit; + } else { + $ui->success('The mapping files are correct.'); + } + + $ui->section('Database'); + + if ($input->getOption('skip-sync')) { + $ui->text('[SKIPPED] The database was not checked for synchronicity.'); + } elseif ( ! $validator->schemaInSyncWithMetadata()) { + $ui->error('The database schema is not in sync with the current mapping file.'); + $exit += 2; + } else { + $ui->success('The database schema is in sync with the mapping files.'); + } + + return $exit; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php new file mode 100644 index 0000000..c6a265c --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php @@ -0,0 +1,143 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console; + +use Doctrine\DBAL\Tools\Console as DBALConsole; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper; +use Doctrine\ORM\Version; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Helper\HelperSet; + +/** + * Handles running the Console Tools inside Symfony Console context. + */ +final class ConsoleRunner +{ + /** + * Create a Symfony Console HelperSet + * + * @param EntityManagerInterface $entityManager + * + * @return HelperSet + */ + public static function createHelperSet(EntityManagerInterface $entityManager) : HelperSet + { + return new HelperSet( + [ + 'db' => new DBALConsole\Helper\ConnectionHelper($entityManager->getConnection()), + 'em' => new EntityManagerHelper($entityManager), + ] + ); + } + + /** + * Runs console with the given helper set. + * + * @param \Symfony\Component\Console\Helper\HelperSet $helperSet + * @param \Symfony\Component\Console\Command\Command[] $commands + * + * @return void + */ + public static function run(HelperSet $helperSet, array $commands = []) : void + { + $cli = self::createApplication($helperSet, $commands); + $cli->run(); + } + + /** + * Creates a console application with the given helperset and + * optional commands. + * + * @param \Symfony\Component\Console\Helper\HelperSet $helperSet + * @param array $commands + * + * @return \Symfony\Component\Console\Application + */ + public static function createApplication(HelperSet $helperSet, array $commands = []) : Application + { + $cli = new Application('Doctrine Command Line Interface', Version::VERSION); + $cli->setCatchExceptions(true); + $cli->setHelperSet($helperSet); + self::addCommands($cli); + $cli->addCommands($commands); + + return $cli; + } + + /** + * @param Application $cli + * + * @return void + */ + public static function addCommands(Application $cli) : void + { + $cli->addCommands( + [ + // DBAL Commands + new DBALConsole\Command\ImportCommand(), + new DBALConsole\Command\ReservedWordsCommand(), + new DBALConsole\Command\RunSqlCommand(), + + // ORM Commands + new Command\ClearCache\CollectionRegionCommand(), + new Command\ClearCache\EntityRegionCommand(), + new Command\ClearCache\MetadataCommand(), + new Command\ClearCache\QueryCommand(), + new Command\ClearCache\QueryRegionCommand(), + new Command\ClearCache\ResultCommand(), + new Command\SchemaTool\CreateCommand(), + new Command\SchemaTool\UpdateCommand(), + new Command\SchemaTool\DropCommand(), + new Command\EnsureProductionSettingsCommand(), + new Command\ConvertDoctrine1SchemaCommand(), + new Command\GenerateRepositoriesCommand(), + new Command\GenerateEntitiesCommand(), + new Command\GenerateProxiesCommand(), + new Command\ConvertMappingCommand(), + new Command\RunDqlCommand(), + new Command\ValidateSchemaCommand(), + new Command\InfoCommand(), + new Command\MappingDescribeCommand(), + ] + ); + } + + public static function printCliConfigTemplate() : void + { + echo <<<'HELP' +You are missing a "cli-config.php" or "config/cli-config.php" file in your +project, which is required to get the Doctrine Console working. You can use the +following sample as a template: + +. + */ + +namespace Doctrine\ORM\Tools\Console\Helper; + +use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\Console\Helper\Helper; + +/** + * Doctrine CLI Connection Helper. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class EntityManagerHelper extends Helper +{ + /** + * Doctrine ORM EntityManagerInterface. + * + * @var EntityManagerInterface + */ + protected $_em; + + /** + * Constructor. + * + * @param EntityManagerInterface $em + */ + public function __construct(EntityManagerInterface $em) + { + $this->_em = $em; + } + + /** + * Retrieves Doctrine ORM EntityManager. + * + * @return EntityManagerInterface + */ + public function getEntityManager() + { + return $this->_em; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'entityManager'; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/MetadataFilter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/MetadataFilter.php new file mode 100644 index 0000000..88357e3 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/MetadataFilter.php @@ -0,0 +1,102 @@ +. + */ + +namespace Doctrine\ORM\Tools\Console; + +/** + * Used by CLI Tools to restrict entity-based commands to given patterns. + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.com + * @since 1.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class MetadataFilter extends \FilterIterator implements \Countable +{ + /** + * @var array + */ + private $filter = []; + + /** + * Filter Metadatas by one or more filter options. + * + * @param array $metadatas + * @param array|string $filter + * + * @return array + */ + static public function filter(array $metadatas, $filter) + { + $metadatas = new MetadataFilter(new \ArrayIterator($metadatas), $filter); + + return iterator_to_array($metadatas); + } + + /** + * @param \ArrayIterator $metadata + * @param array|string $filter + */ + public function __construct(\ArrayIterator $metadata, $filter) + { + $this->filter = (array) $filter; + + parent::__construct($metadata); + } + + /** + * @return bool + */ + public function accept() + { + if (count($this->filter) == 0) { + return true; + } + + $it = $this->getInnerIterator(); + $metadata = $it->current(); + + foreach ($this->filter as $filter) { + $pregResult = preg_match("/$filter/", $metadata->name); + + if ($pregResult === false) { + throw new \RuntimeException( + sprintf("Error while evaluating regex '/%s/'.", $filter) + ); + } + + if ($pregResult) { + return true; + } + } + + return false; + } + + /** + * @return int + */ + public function count() + { + return count($this->getInnerIterator()); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php new file mode 100644 index 0000000..41a103d --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php @@ -0,0 +1,344 @@ +. + */ + +namespace Doctrine\ORM\Tools; + +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Doctrine\Common\Inflector\Inflector; +use Doctrine\DBAL\Types\Type; +use Symfony\Component\Yaml\Yaml; + +/** + * Class to help with converting Doctrine 1 schema files to Doctrine 2 mapping files + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class ConvertDoctrine1Schema +{ + /** + * @var array + */ + private $from; + + /** + * @var array + */ + private $legacyTypeMap = [ + // TODO: This list may need to be updated + 'clob' => 'text', + 'timestamp' => 'datetime', + 'enum' => 'string' + ]; + + /** + * Constructor passes the directory or array of directories + * to convert the Doctrine 1 schema files from. + * + * @param array $from + * + * @author Jonathan Wage + */ + public function __construct($from) + { + $this->from = (array) $from; + } + + /** + * Gets an array of ClassMetadataInfo instances from the passed + * Doctrine 1 schema. + * + * @return array An array of ClassMetadataInfo instances + */ + public function getMetadata() + { + $schema = []; + foreach ($this->from as $path) { + if (is_dir($path)) { + $files = glob($path . '/*.yml'); + foreach ($files as $file) { + $schema = array_merge($schema, (array) Yaml::parse(file_get_contents($file))); + } + } else { + $schema = array_merge($schema, (array) Yaml::parse(file_get_contents($path))); + } + } + + $metadatas = []; + foreach ($schema as $className => $mappingInformation) { + $metadatas[] = $this->convertToClassMetadataInfo($className, $mappingInformation); + } + + return $metadatas; + } + + /** + * @param string $className + * @param array $mappingInformation + * + * @return \Doctrine\ORM\Mapping\ClassMetadataInfo + */ + private function convertToClassMetadataInfo($className, $mappingInformation) + { + $metadata = new ClassMetadataInfo($className); + + $this->convertTableName($className, $mappingInformation, $metadata); + $this->convertColumns($className, $mappingInformation, $metadata); + $this->convertIndexes($className, $mappingInformation, $metadata); + $this->convertRelations($className, $mappingInformation, $metadata); + + return $metadata; + } + + /** + * @param string $className + * @param array $model + * @param ClassMetadataInfo $metadata + * + * @return void + */ + private function convertTableName($className, array $model, ClassMetadataInfo $metadata) + { + if (isset($model['tableName']) && $model['tableName']) { + $e = explode('.', $model['tableName']); + + if (count($e) > 1) { + $metadata->table['schema'] = $e[0]; + $metadata->table['name'] = $e[1]; + } else { + $metadata->table['name'] = $e[0]; + } + } + } + + /** + * @param string $className + * @param array $model + * @param ClassMetadataInfo $metadata + * + * @return void + */ + private function convertColumns($className, array $model, ClassMetadataInfo $metadata) + { + $id = false; + + if (isset($model['columns']) && $model['columns']) { + foreach ($model['columns'] as $name => $column) { + $fieldMapping = $this->convertColumn($className, $name, $column, $metadata); + + if (isset($fieldMapping['id']) && $fieldMapping['id']) { + $id = true; + } + } + } + + if ( ! $id) { + $fieldMapping = [ + 'fieldName' => 'id', + 'columnName' => 'id', + 'type' => 'integer', + 'id' => true + ]; + $metadata->mapField($fieldMapping); + $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); + } + } + + /** + * @param string $className + * @param string $name + * @param string|array $column + * @param ClassMetadataInfo $metadata + * + * @return array + * + * @throws ToolsException + */ + private function convertColumn($className, $name, $column, ClassMetadataInfo $metadata) + { + if (is_string($column)) { + $string = $column; + $column = []; + $column['type'] = $string; + } + + if ( ! isset($column['name'])) { + $column['name'] = $name; + } + + // check if a column alias was used (column_name as field_name) + if (preg_match("/(\w+)\sas\s(\w+)/i", $column['name'], $matches)) { + $name = $matches[1]; + $column['name'] = $name; + $column['alias'] = $matches[2]; + } + + if (preg_match("/([a-zA-Z]+)\(([0-9]+)\)/", $column['type'], $matches)) { + $column['type'] = $matches[1]; + $column['length'] = $matches[2]; + } + + $column['type'] = strtolower($column['type']); + // check if legacy column type (1.x) needs to be mapped to a 2.0 one + if (isset($this->legacyTypeMap[$column['type']])) { + $column['type'] = $this->legacyTypeMap[$column['type']]; + } + + if ( ! Type::hasType($column['type'])) { + throw ToolsException::couldNotMapDoctrine1Type($column['type']); + } + + $fieldMapping = []; + + if (isset($column['primary'])) { + $fieldMapping['id'] = true; + } + + $fieldMapping['fieldName'] = $column['alias'] ?? $name; + $fieldMapping['columnName'] = $column['name']; + $fieldMapping['type'] = $column['type']; + + if (isset($column['length'])) { + $fieldMapping['length'] = $column['length']; + } + + $allowed = ['precision', 'scale', 'unique', 'options', 'notnull', 'version']; + + foreach ($column as $key => $value) { + if (in_array($key, $allowed)) { + $fieldMapping[$key] = $value; + } + } + + $metadata->mapField($fieldMapping); + + if (isset($column['autoincrement'])) { + $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); + } elseif (isset($column['sequence'])) { + $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE); + + $definition = [ + 'sequenceName' => is_array($column['sequence']) ? $column['sequence']['name']:$column['sequence'] + ]; + + if (isset($column['sequence']['size'])) { + $definition['allocationSize'] = $column['sequence']['size']; + } + + if (isset($column['sequence']['value'])) { + $definition['initialValue'] = $column['sequence']['value']; + } + + $metadata->setSequenceGeneratorDefinition($definition); + } + + return $fieldMapping; + } + + /** + * @param string $className + * @param array $model + * @param ClassMetadataInfo $metadata + * + * @return void + */ + private function convertIndexes($className, array $model, ClassMetadataInfo $metadata) + { + if (empty($model['indexes'])) { + return; + } + + foreach ($model['indexes'] as $name => $index) { + $type = (isset($index['type']) && $index['type'] == 'unique') + ? 'uniqueConstraints' : 'indexes'; + + $metadata->table[$type][$name] = [ + 'columns' => $index['fields'] + ]; + } + } + + /** + * @param string $className + * @param array $model + * @param ClassMetadataInfo $metadata + * + * @return void + */ + private function convertRelations($className, array $model, ClassMetadataInfo $metadata) + { + if (empty($model['relations'])) { + return; + } + + foreach ($model['relations'] as $name => $relation) { + if ( ! isset($relation['alias'])) { + $relation['alias'] = $name; + } + if ( ! isset($relation['class'])) { + $relation['class'] = $name; + } + if ( ! isset($relation['local'])) { + $relation['local'] = Inflector::tableize($relation['class']); + } + if ( ! isset($relation['foreign'])) { + $relation['foreign'] = 'id'; + } + if ( ! isset($relation['foreignAlias'])) { + $relation['foreignAlias'] = $className; + } + + if (isset($relation['refClass'])) { + $type = 'many'; + $foreignType = 'many'; + $joinColumns = []; + } else { + $type = $relation['type'] ?? 'one'; + $foreignType = $relation['foreignType'] ?? 'many'; + $joinColumns = [ + [ + 'name' => $relation['local'], + 'referencedColumnName' => $relation['foreign'], + 'onDelete' => $relation['onDelete'] ?? null, + ] + ]; + } + + if ($type == 'one' && $foreignType == 'one') { + $method = 'mapOneToOne'; + } elseif ($type == 'many' && $foreignType == 'many') { + $method = 'mapManyToMany'; + } else { + $method = 'mapOneToMany'; + } + + $associationMapping = []; + $associationMapping['fieldName'] = $relation['alias']; + $associationMapping['targetEntity'] = $relation['class']; + $associationMapping['mappedBy'] = $relation['foreignAlias']; + $associationMapping['joinColumns'] = $joinColumns; + + $metadata->$method($associationMapping); + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DebugUnitOfWorkListener.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DebugUnitOfWorkListener.php new file mode 100644 index 0000000..5011382 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DebugUnitOfWorkListener.php @@ -0,0 +1,185 @@ +. + */ + +namespace Doctrine\ORM\Tools; + +use Doctrine\Common\Persistence\Proxy; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Event\OnFlushEventArgs; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\PersistentCollection; +use Doctrine\ORM\UnitOfWork; + +/** + * Use this logger to dump the identity map during the onFlush event. This is useful for debugging + * weird UnitOfWork behavior with complex operations. + */ +class DebugUnitOfWorkListener +{ + /** + * @var string + */ + private $file; + + /** + * @var string + */ + private $context; + + /** + * Pass a stream and context information for the debugging session. + * + * The stream can be php://output to print to the screen. + * + * @param string $file + * @param string $context + */ + public function __construct($file = 'php://output', $context = '') + { + $this->file = $file; + $this->context = $context; + } + + /** + * @param \Doctrine\ORM\Event\OnFlushEventArgs $args + * + * @return void + */ + public function onFlush(OnFlushEventArgs $args) + { + $this->dumpIdentityMap($args->getEntityManager()); + } + + /** + * Dumps the contents of the identity map into a stream. + * + * @param EntityManagerInterface $em + * + * @return void + */ + public function dumpIdentityMap(EntityManagerInterface $em) + { + $uow = $em->getUnitOfWork(); + $identityMap = $uow->getIdentityMap(); + + $fh = fopen($this->file, 'xb+'); + if (count($identityMap) == 0) { + fwrite($fh, "Flush Operation [".$this->context."] - Empty identity map.\n"); + + return; + } + + fwrite($fh, "Flush Operation [".$this->context."] - Dumping identity map:\n"); + foreach ($identityMap as $className => $map) { + fwrite($fh, "Class: ". $className . "\n"); + + foreach ($map as $entity) { + fwrite($fh, " Entity: " . $this->getIdString($entity, $uow) . " " . spl_object_hash($entity)."\n"); + fwrite($fh, " Associations:\n"); + + $cm = $em->getClassMetadata($className); + + foreach ($cm->associationMappings as $field => $assoc) { + fwrite($fh, " " . $field . " "); + $value = $cm->getFieldValue($entity, $field); + + if ($assoc['type'] & ClassMetadata::TO_ONE) { + if ($value === null) { + fwrite($fh, " NULL\n"); + } else { + if ($value instanceof Proxy && !$value->__isInitialized()) { + fwrite($fh, "[PROXY] "); + } + + fwrite($fh, $this->getIdString($value, $uow) . " " . spl_object_hash($value) . "\n"); + } + } else { + $initialized = !($value instanceof PersistentCollection) || $value->isInitialized(); + if ($value === null) { + fwrite($fh, " NULL\n"); + } elseif ($initialized) { + fwrite($fh, "[INITIALIZED] " . $this->getType($value). " " . count($value) . " elements\n"); + + foreach ($value as $obj) { + fwrite($fh, " " . $this->getIdString($obj, $uow) . " " . spl_object_hash($obj)."\n"); + } + } else { + fwrite($fh, "[PROXY] " . $this->getType($value) . " unknown element size\n"); + foreach ($value->unwrap() as $obj) { + fwrite($fh, " " . $this->getIdString($obj, $uow) . " " . spl_object_hash($obj)."\n"); + } + } + } + } + } + } + + fclose($fh); + } + + /** + * @param mixed $var + * + * @return string + */ + private function getType($var) + { + if (is_object($var)) { + $refl = new \ReflectionObject($var); + + return $refl->getShortName(); + } + + return gettype($var); + } + + /** + * @param object $entity + * @param UnitOfWork $uow + * + * @return string + */ + private function getIdString($entity, UnitOfWork $uow) + { + if ($uow->isInIdentityMap($entity)) { + $ids = $uow->getEntityIdentifier($entity); + $idstring = ""; + + foreach ($ids as $k => $v) { + $idstring .= $k."=".$v; + } + } else { + $idstring = "NEWOBJECT "; + } + + $state = $uow->getEntityState($entity); + + if ($state == UnitOfWork::STATE_NEW) { + $idstring .= " [NEW]"; + } elseif ($state == UnitOfWork::STATE_REMOVED) { + $idstring .= " [REMOVED]"; + } elseif ($state == UnitOfWork::STATE_MANAGED) { + $idstring .= " [MANAGED]"; + } elseif ($state == UnitOfWork::STATE_DETACHED) { + $idstring .= " [DETACHED]"; + } + + return $idstring; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DisconnectedClassMetadataFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DisconnectedClassMetadataFactory.php new file mode 100644 index 0000000..7a3ec6f --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DisconnectedClassMetadataFactory.php @@ -0,0 +1,48 @@ +. + */ + +namespace Doctrine\ORM\Tools; + +use Doctrine\Common\Persistence\Mapping\StaticReflectionService; +use Doctrine\ORM\Mapping\ClassMetadataFactory; + +/** + * The DisconnectedClassMetadataFactory is used to create ClassMetadataInfo objects + * that do not require the entity class actually exist. This allows us to + * load some mapping information and use it to do things like generate code + * from the mapping information. + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class DisconnectedClassMetadataFactory extends ClassMetadataFactory +{ + /** + * @return \Doctrine\Common\Persistence\Mapping\StaticReflectionService + */ + public function getReflectionService() + { + return new StaticReflectionService(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityGenerator.php new file mode 100644 index 0000000..5c304db --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityGenerator.php @@ -0,0 +1,1906 @@ +. + */ + +namespace Doctrine\ORM\Tools; + +use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Inflector\Inflector; +use Doctrine\DBAL\Types\Type; +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use const E_USER_DEPRECATED; +use function str_replace; +use function trigger_error; + +/** + * Generic class used to generate PHP5 entity classes from ClassMetadataInfo instances. + * + * [php] + * $classes = $em->getClassMetadataFactory()->getAllMetadata(); + * + * $generator = new \Doctrine\ORM\Tools\EntityGenerator(); + * $generator->setGenerateAnnotations(true); + * $generator->setGenerateStubMethods(true); + * $generator->setRegenerateEntityIfExists(false); + * $generator->setUpdateEntityIfExists(true); + * $generator->generate($classes, '/path/to/generate/entities'); + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class EntityGenerator +{ + /** + * Specifies class fields should be protected. + */ + const FIELD_VISIBLE_PROTECTED = 'protected'; + + /** + * Specifies class fields should be private. + */ + const FIELD_VISIBLE_PRIVATE = 'private'; + + /** + * @var bool + */ + protected $backupExisting = true; + + /** + * The extension to use for written php files. + * + * @var string + */ + protected $extension = '.php'; + + /** + * Whether or not the current ClassMetadataInfo instance is new or old. + * + * @var boolean + */ + protected $isNew = true; + + /** + * @var array + */ + protected $staticReflection = []; + + /** + * Number of spaces to use for indention in generated code. + */ + protected $numSpaces = 4; + + /** + * The actual spaces to use for indention. + * + * @var string + */ + protected $spaces = ' '; + + /** + * The class all generated entities should extend. + * + * @var string + */ + protected $classToExtend; + + /** + * Whether or not to generation annotations. + * + * @var boolean + */ + protected $generateAnnotations = false; + + /** + * @var string + */ + protected $annotationsPrefix = ''; + + /** + * Whether or not to generate sub methods. + * + * @var boolean + */ + protected $generateEntityStubMethods = false; + + /** + * Whether or not to update the entity class if it exists already. + * + * @var boolean + */ + protected $updateEntityIfExists = false; + + /** + * Whether or not to re-generate entity class if it exists already. + * + * @var boolean + */ + protected $regenerateEntityIfExists = false; + + /** + * Visibility of the field + * + * @var string + */ + protected $fieldVisibility = 'private'; + + /** + * Whether or not to make generated embeddables immutable. + * + * @var boolean. + */ + protected $embeddablesImmutable = false; + + /** + * Hash-map for handle types. + * + * @var array + */ + protected $typeAlias = [ + Type::DATETIMETZ => '\DateTime', + Type::DATETIME => '\DateTime', + Type::DATE => '\DateTime', + Type::TIME => '\DateTime', + Type::OBJECT => '\stdClass', + Type::INTEGER => 'int', + Type::BIGINT => 'int', + Type::SMALLINT => 'int', + Type::TEXT => 'string', + Type::BLOB => 'string', + Type::DECIMAL => 'string', + Type::GUID => 'string', + Type::JSON_ARRAY => 'array', + Type::SIMPLE_ARRAY => 'array', + Type::BOOLEAN => 'bool', + ]; + + /** + * Hash-map to handle generator types string. + * + * @var array + */ + protected static $generatorStrategyMap = [ + ClassMetadataInfo::GENERATOR_TYPE_AUTO => 'AUTO', + ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE => 'SEQUENCE', + ClassMetadataInfo::GENERATOR_TYPE_TABLE => 'TABLE', + ClassMetadataInfo::GENERATOR_TYPE_IDENTITY => 'IDENTITY', + ClassMetadataInfo::GENERATOR_TYPE_NONE => 'NONE', + ClassMetadataInfo::GENERATOR_TYPE_UUID => 'UUID', + ClassMetadataInfo::GENERATOR_TYPE_CUSTOM => 'CUSTOM' + ]; + + /** + * Hash-map to handle the change tracking policy string. + * + * @var array + */ + protected static $changeTrackingPolicyMap = [ + ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT => 'DEFERRED_IMPLICIT', + ClassMetadataInfo::CHANGETRACKING_DEFERRED_EXPLICIT => 'DEFERRED_EXPLICIT', + ClassMetadataInfo::CHANGETRACKING_NOTIFY => 'NOTIFY', + ]; + + /** + * Hash-map to handle the inheritance type string. + * + * @var array + */ + protected static $inheritanceTypeMap = [ + ClassMetadataInfo::INHERITANCE_TYPE_NONE => 'NONE', + ClassMetadataInfo::INHERITANCE_TYPE_JOINED => 'JOINED', + ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_TABLE => 'SINGLE_TABLE', + ClassMetadataInfo::INHERITANCE_TYPE_TABLE_PER_CLASS => 'TABLE_PER_CLASS', + ]; + + /** + * @var string + */ + protected static $classTemplate = +' + + + +{ + +} +'; + + /** + * @var string + */ + protected static $getMethodTemplate = +'/** + * + * + * @return + */ +public function () +{ +return $this->; +}'; + + /** + * @var string + */ + protected static $setMethodTemplate = +'/** + * + * + * @param $ + * + * @return + */ +public function ($) +{ +$this-> = $; + +return $this; +}'; + + /** + * @var string + */ + protected static $addMethodTemplate = +'/** + * + * + * @param $ + * + * @return + */ +public function ($) +{ +$this->[] = $; + +return $this; +}'; + + /** + * @var string + */ + protected static $removeMethodTemplate = +'/** + * + * + * @param $ + * + * @return boolean TRUE if this collection contained the specified element, FALSE otherwise. + */ +public function ($) +{ +return $this->->removeElement($); +}'; + + /** + * @var string + */ + protected static $lifecycleCallbackMethodTemplate = +'/** + * @ + */ +public function () +{ +// Add your code here +}'; + + /** + * @var string + */ + protected static $constructorMethodTemplate = +'/** + * Constructor + */ +public function __construct() +{ + +} +'; + + /** + * @var string + */ + protected static $embeddableConstructorMethodTemplate = +'/** + * Constructor + * + * + */ +public function __construct() +{ + +} +'; + + /** + * Constructor. + */ + public function __construct() + { + @trigger_error(self::class . ' is deprecated and will be removed in Doctrine ORM 3.0', E_USER_DEPRECATED); + + if (version_compare(\Doctrine\Common\Version::VERSION, '2.2.0-DEV', '>=')) { + $this->annotationsPrefix = 'ORM\\'; + } + } + + /** + * Generates and writes entity classes for the given array of ClassMetadataInfo instances. + * + * @param array $metadatas + * @param string $outputDirectory + * + * @return void + */ + public function generate(array $metadatas, $outputDirectory) + { + foreach ($metadatas as $metadata) { + $this->writeEntityClass($metadata, $outputDirectory); + } + } + + /** + * Generates and writes entity class to disk for the given ClassMetadataInfo instance. + * + * @param ClassMetadataInfo $metadata + * @param string $outputDirectory + * + * @return void + * + * @throws \RuntimeException + */ + public function writeEntityClass(ClassMetadataInfo $metadata, $outputDirectory) + { + $path = $outputDirectory . '/' . str_replace('\\', DIRECTORY_SEPARATOR, $metadata->name) . $this->extension; + $dir = dirname($path); + + if ( ! is_dir($dir)) { + mkdir($dir, 0775, true); + } + + $this->isNew = ! file_exists($path) || $this->regenerateEntityIfExists; + + if ( ! $this->isNew) { + $this->parseTokensInEntityFile(file_get_contents($path)); + } else { + $this->staticReflection[$metadata->name] = ['properties' => [], 'methods' => []]; + } + + if ($this->backupExisting && file_exists($path)) { + $backupPath = dirname($path) . DIRECTORY_SEPARATOR . basename($path) . "~"; + if (!copy($path, $backupPath)) { + throw new \RuntimeException("Attempt to backup overwritten entity file but copy operation failed."); + } + } + + // If entity doesn't exist or we're re-generating the entities entirely + if ($this->isNew) { + file_put_contents($path, $this->generateEntityClass($metadata)); + // If entity exists and we're allowed to update the entity class + } elseif ($this->updateEntityIfExists) { + file_put_contents($path, $this->generateUpdatedEntityClass($metadata, $path)); + } + chmod($path, 0664); + } + + /** + * Generates a PHP5 Doctrine 2 entity class from the given ClassMetadataInfo instance. + * + * @param ClassMetadataInfo $metadata + * + * @return string + */ + public function generateEntityClass(ClassMetadataInfo $metadata) + { + $placeHolders = [ + '', + '', + '', + '', + '' + ]; + + $replacements = [ + $this->generateEntityNamespace($metadata), + $this->generateEntityUse(), + $this->generateEntityDocBlock($metadata), + $this->generateEntityClassName($metadata), + $this->generateEntityBody($metadata) + ]; + + $code = str_replace($placeHolders, $replacements, static::$classTemplate); + + return str_replace('', $this->spaces, $code); + } + + /** + * Generates the updated code for the given ClassMetadataInfo and entity at path. + * + * @param ClassMetadataInfo $metadata + * @param string $path + * + * @return string + */ + public function generateUpdatedEntityClass(ClassMetadataInfo $metadata, $path) + { + $currentCode = file_get_contents($path); + + $body = $this->generateEntityBody($metadata); + $body = str_replace('', $this->spaces, $body); + $last = strrpos($currentCode, '}'); + + return substr($currentCode, 0, $last) . $body . ($body ? "\n" : '') . "}\n"; + } + + /** + * Sets the number of spaces the exported class should have. + * + * @param integer $numSpaces + * + * @return void + */ + public function setNumSpaces($numSpaces) + { + $this->spaces = str_repeat(' ', $numSpaces); + $this->numSpaces = $numSpaces; + } + + /** + * Sets the extension to use when writing php files to disk. + * + * @param string $extension + * + * @return void + */ + public function setExtension($extension) + { + $this->extension = $extension; + } + + /** + * Sets the name of the class the generated classes should extend from. + * + * @param string $classToExtend + * + * @return void + */ + public function setClassToExtend($classToExtend) + { + $this->classToExtend = $classToExtend; + } + + /** + * Sets whether or not to generate annotations for the entity. + * + * @param bool $bool + * + * @return void + */ + public function setGenerateAnnotations($bool) + { + $this->generateAnnotations = $bool; + } + + /** + * Sets the class fields visibility for the entity (can either be private or protected). + * + * @param bool $visibility + * + * @return void + * + * @throws \InvalidArgumentException + */ + public function setFieldVisibility($visibility) + { + if ($visibility !== static::FIELD_VISIBLE_PRIVATE && $visibility !== static::FIELD_VISIBLE_PROTECTED) { + throw new \InvalidArgumentException('Invalid provided visibility (only private and protected are allowed): ' . $visibility); + } + + $this->fieldVisibility = $visibility; + } + + /** + * Sets whether or not to generate immutable embeddables. + * + * @param boolean $embeddablesImmutable + */ + public function setEmbeddablesImmutable($embeddablesImmutable) + { + $this->embeddablesImmutable = (boolean) $embeddablesImmutable; + } + + /** + * Sets an annotation prefix. + * + * @param string $prefix + * + * @return void + */ + public function setAnnotationPrefix($prefix) + { + $this->annotationsPrefix = $prefix; + } + + /** + * Sets whether or not to try and update the entity if it already exists. + * + * @param bool $bool + * + * @return void + */ + public function setUpdateEntityIfExists($bool) + { + $this->updateEntityIfExists = $bool; + } + + /** + * Sets whether or not to regenerate the entity if it exists. + * + * @param bool $bool + * + * @return void + */ + public function setRegenerateEntityIfExists($bool) + { + $this->regenerateEntityIfExists = $bool; + } + + /** + * Sets whether or not to generate stub methods for the entity. + * + * @param bool $bool + * + * @return void + */ + public function setGenerateStubMethods($bool) + { + $this->generateEntityStubMethods = $bool; + } + + /** + * Should an existing entity be backed up if it already exists? + * + * @param bool $bool + * + * @return void + */ + public function setBackupExisting($bool) + { + $this->backupExisting = $bool; + } + + /** + * @param string $type + * + * @return string + */ + protected function getType($type) + { + if (isset($this->typeAlias[$type])) { + return $this->typeAlias[$type]; + } + + return $type; + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateEntityNamespace(ClassMetadataInfo $metadata) + { + if (! $this->hasNamespace($metadata)) { + return ''; + } + + return 'namespace ' . $this->getNamespace($metadata) .';'; + } + + /** + * @return string + */ + protected function generateEntityUse() + { + if (! $this->generateAnnotations) { + return ''; + } + + return "\n".'use Doctrine\ORM\Mapping as ORM;'."\n"; + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateEntityClassName(ClassMetadataInfo $metadata) + { + return 'class ' . $this->getClassName($metadata) . + ($this->extendsClass() ? ' extends ' . $this->getClassToExtendName() : null); + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateEntityBody(ClassMetadataInfo $metadata) + { + $fieldMappingProperties = $this->generateEntityFieldMappingProperties($metadata); + $embeddedProperties = $this->generateEntityEmbeddedProperties($metadata); + $associationMappingProperties = $this->generateEntityAssociationMappingProperties($metadata); + $stubMethods = $this->generateEntityStubMethods ? $this->generateEntityStubMethods($metadata) : null; + $lifecycleCallbackMethods = $this->generateEntityLifecycleCallbackMethods($metadata); + + $code = []; + + if ($fieldMappingProperties) { + $code[] = $fieldMappingProperties; + } + + if ($embeddedProperties) { + $code[] = $embeddedProperties; + } + + if ($associationMappingProperties) { + $code[] = $associationMappingProperties; + } + + $code[] = $this->generateEntityConstructor($metadata); + + if ($stubMethods) { + $code[] = $stubMethods; + } + + if ($lifecycleCallbackMethods) { + $code[] = $lifecycleCallbackMethods; + } + + return implode("\n", $code); + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateEntityConstructor(ClassMetadataInfo $metadata) + { + if ($this->hasMethod('__construct', $metadata)) { + return ''; + } + + if ($metadata->isEmbeddedClass && $this->embeddablesImmutable) { + return $this->generateEmbeddableConstructor($metadata); + } + + $collections = []; + + foreach ($metadata->associationMappings as $mapping) { + if ($mapping['type'] & ClassMetadataInfo::TO_MANY) { + $collections[] = '$this->'.$mapping['fieldName'].' = new \Doctrine\Common\Collections\ArrayCollection();'; + } + } + + if ($collections) { + return $this->prefixCodeWithSpaces(str_replace("", implode("\n".$this->spaces, $collections), static::$constructorMethodTemplate)); + } + + return ''; + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + private function generateEmbeddableConstructor(ClassMetadataInfo $metadata) + { + $paramTypes = []; + $paramVariables = []; + $params = []; + $fields = []; + + // Resort fields to put optional fields at the end of the method signature. + $requiredFields = []; + $optionalFields = []; + + foreach ($metadata->fieldMappings as $fieldMapping) { + if (empty($fieldMapping['nullable'])) { + $requiredFields[] = $fieldMapping; + + continue; + } + + $optionalFields[] = $fieldMapping; + } + + $fieldMappings = array_merge($requiredFields, $optionalFields); + + foreach ($metadata->embeddedClasses as $fieldName => $embeddedClass) { + $paramType = '\\' . ltrim($embeddedClass['class'], '\\'); + $paramVariable = '$' . $fieldName; + + $paramTypes[] = $paramType; + $paramVariables[] = $paramVariable; + $params[] = $paramType . ' ' . $paramVariable; + $fields[] = '$this->' . $fieldName . ' = ' . $paramVariable . ';'; + } + + foreach ($fieldMappings as $fieldMapping) { + if (isset($fieldMapping['declaredField'], $metadata->embeddedClasses[$fieldMapping['declaredField']])) { + continue; + } + + $paramTypes[] = $this->getType($fieldMapping['type']) . (!empty($fieldMapping['nullable']) ? '|null' : ''); + $param = '$' . $fieldMapping['fieldName']; + $paramVariables[] = $param; + + if ($fieldMapping['type'] === 'datetime') { + $param = $this->getType($fieldMapping['type']) . ' ' . $param; + } + + if (!empty($fieldMapping['nullable'])) { + $param .= ' = null'; + } + + $params[] = $param; + + $fields[] = '$this->' . $fieldMapping['fieldName'] . ' = $' . $fieldMapping['fieldName'] . ';'; + } + + $maxParamTypeLength = max(array_map('strlen', $paramTypes)); + $paramTags = array_map( + function ($type, $variable) use ($maxParamTypeLength) { + return '@param ' . $type . str_repeat(' ', $maxParamTypeLength - strlen($type) + 1) . $variable; + }, + $paramTypes, + $paramVariables + ); + + // Generate multi line constructor if the signature exceeds 120 characters. + if (array_sum(array_map('strlen', $params)) + count($params) * 2 + 29 > 120) { + $delimiter = "\n" . $this->spaces; + $params = $delimiter . implode(',' . $delimiter, $params) . "\n"; + } else { + $params = implode(', ', $params); + } + + $replacements = [ + '' => implode("\n * ", $paramTags), + '' => $params, + '' => implode("\n" . $this->spaces, $fields), + ]; + + $constructor = str_replace( + array_keys($replacements), + array_values($replacements), + static::$embeddableConstructorMethodTemplate + ); + + return $this->prefixCodeWithSpaces($constructor); + } + + /** + * @todo this won't work if there is a namespace in brackets and a class outside of it. + * + * @param string $src + * + * @return void + */ + protected function parseTokensInEntityFile($src) + { + $tokens = token_get_all($src); + $tokensCount = count($tokens); + $lastSeenNamespace = ''; + $lastSeenClass = false; + + $inNamespace = false; + $inClass = false; + + for ($i = 0; $i < $tokensCount; $i++) { + $token = $tokens[$i]; + if (in_array($token[0], [T_WHITESPACE, T_COMMENT, T_DOC_COMMENT], true)) { + continue; + } + + if ($inNamespace) { + if (in_array($token[0], [T_NS_SEPARATOR, T_STRING], true)) { + $lastSeenNamespace .= $token[1]; + } elseif (is_string($token) && in_array($token, [';', '{'], true)) { + $inNamespace = false; + } + } + + if ($inClass) { + $inClass = false; + $lastSeenClass = $lastSeenNamespace . ($lastSeenNamespace ? '\\' : '') . $token[1]; + $this->staticReflection[$lastSeenClass]['properties'] = []; + $this->staticReflection[$lastSeenClass]['methods'] = []; + } + + if (T_NAMESPACE === $token[0]) { + $lastSeenNamespace = ''; + $inNamespace = true; + } elseif (T_CLASS === $token[0] && T_DOUBLE_COLON !== $tokens[$i-1][0]) { + $inClass = true; + } elseif (T_FUNCTION === $token[0]) { + if (T_STRING === $tokens[$i+2][0]) { + $this->staticReflection[$lastSeenClass]['methods'][] = strtolower($tokens[$i+2][1]); + } elseif ($tokens[$i+2] == '&' && T_STRING === $tokens[$i+3][0]) { + $this->staticReflection[$lastSeenClass]['methods'][] = strtolower($tokens[$i+3][1]); + } + } elseif (in_array($token[0], [T_VAR, T_PUBLIC, T_PRIVATE, T_PROTECTED], true) && T_FUNCTION !== $tokens[$i+2][0]) { + $this->staticReflection[$lastSeenClass]['properties'][] = substr($tokens[$i+2][1], 1); + } + } + } + + /** + * @param string $property + * @param ClassMetadataInfo $metadata + * + * @return bool + */ + protected function hasProperty($property, ClassMetadataInfo $metadata) + { + if ($this->extendsClass() || (!$this->isNew && class_exists($metadata->name))) { + // don't generate property if its already on the base class. + $reflClass = new \ReflectionClass($this->getClassToExtend() ?: $metadata->name); + if ($reflClass->hasProperty($property)) { + return true; + } + } + + // check traits for existing property + foreach ($this->getTraits($metadata) as $trait) { + if ($trait->hasProperty($property)) { + return true; + } + } + + return ( + isset($this->staticReflection[$metadata->name]) && + in_array($property, $this->staticReflection[$metadata->name]['properties'], true) + ); + } + + /** + * @param string $method + * @param ClassMetadataInfo $metadata + * + * @return bool + */ + protected function hasMethod($method, ClassMetadataInfo $metadata) + { + if ($this->extendsClass() || (!$this->isNew && class_exists($metadata->name))) { + // don't generate method if its already on the base class. + $reflClass = new \ReflectionClass($this->getClassToExtend() ?: $metadata->name); + + if ($reflClass->hasMethod($method)) { + return true; + } + } + + // check traits for existing method + foreach ($this->getTraits($metadata) as $trait) { + if ($trait->hasMethod($method)) { + return true; + } + } + + return ( + isset($this->staticReflection[$metadata->name]) && + in_array(strtolower($method), $this->staticReflection[$metadata->name]['methods'], true) + ); + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return array + * + * @throws \ReflectionException + */ + protected function getTraits(ClassMetadataInfo $metadata) + { + if (! ($metadata->reflClass !== null || class_exists($metadata->name))) { + return []; + } + + $reflClass = $metadata->reflClass ?? new \ReflectionClass($metadata->name); + + $traits = []; + + while ($reflClass !== false) { + $traits = array_merge($traits, $reflClass->getTraits()); + + $reflClass = $reflClass->getParentClass(); + } + + return $traits; + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return bool + */ + protected function hasNamespace(ClassMetadataInfo $metadata) + { + return (bool) strpos($metadata->name, '\\'); + } + + /** + * @return bool + */ + protected function extendsClass() + { + return (bool) $this->classToExtend; + } + + /** + * @return string + */ + protected function getClassToExtend() + { + return $this->classToExtend; + } + + /** + * @return string + */ + protected function getClassToExtendName() + { + $refl = new \ReflectionClass($this->getClassToExtend()); + + return '\\' . $refl->getName(); + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function getClassName(ClassMetadataInfo $metadata) + { + return ($pos = strrpos($metadata->name, '\\')) + ? substr($metadata->name, $pos + 1, strlen($metadata->name)) : $metadata->name; + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function getNamespace(ClassMetadataInfo $metadata) + { + return substr($metadata->name, 0, strrpos($metadata->name, '\\')); + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateEntityDocBlock(ClassMetadataInfo $metadata) + { + $lines = []; + $lines[] = '/**'; + $lines[] = ' * ' . $this->getClassName($metadata); + + if ($this->generateAnnotations) { + $lines[] = ' *'; + + $methods = [ + 'generateTableAnnotation', + 'generateInheritanceAnnotation', + 'generateDiscriminatorColumnAnnotation', + 'generateDiscriminatorMapAnnotation', + 'generateEntityAnnotation', + 'generateEntityListenerAnnotation', + ]; + + foreach ($methods as $method) { + if ($code = $this->$method($metadata)) { + $lines[] = ' * ' . $code; + } + } + + if (isset($metadata->lifecycleCallbacks) && $metadata->lifecycleCallbacks) { + $lines[] = ' * @' . $this->annotationsPrefix . 'HasLifecycleCallbacks'; + } + } + + $lines[] = ' */'; + + return implode("\n", $lines); + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateEntityAnnotation(ClassMetadataInfo $metadata) + { + $prefix = '@' . $this->annotationsPrefix; + + if ($metadata->isEmbeddedClass) { + return $prefix . 'Embeddable'; + } + + $customRepository = $metadata->customRepositoryClassName + ? '(repositoryClass="' . $metadata->customRepositoryClassName . '")' + : ''; + + return $prefix . ($metadata->isMappedSuperclass ? 'MappedSuperclass' : 'Entity') . $customRepository; + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateTableAnnotation(ClassMetadataInfo $metadata) + { + if ($metadata->isEmbeddedClass) { + return ''; + } + + $table = []; + + if (isset($metadata->table['schema'])) { + $table[] = 'schema="' . $metadata->table['schema'] . '"'; + } + + if (isset($metadata->table['name'])) { + $table[] = 'name="' . $metadata->table['name'] . '"'; + } + + if (isset($metadata->table['options']) && $metadata->table['options']) { + $table[] = 'options={' . $this->exportTableOptions((array) $metadata->table['options']) . '}'; + } + + if (isset($metadata->table['uniqueConstraints']) && $metadata->table['uniqueConstraints']) { + $constraints = $this->generateTableConstraints('UniqueConstraint', $metadata->table['uniqueConstraints']); + $table[] = 'uniqueConstraints={' . $constraints . '}'; + } + + if (isset($metadata->table['indexes']) && $metadata->table['indexes']) { + $constraints = $this->generateTableConstraints('Index', $metadata->table['indexes']); + $table[] = 'indexes={' . $constraints . '}'; + } + + return '@' . $this->annotationsPrefix . 'Table(' . implode(', ', $table) . ')'; + } + + /** + * @param string $constraintName + * @param array $constraints + * + * @return string + */ + protected function generateTableConstraints($constraintName, array $constraints) + { + $annotations = []; + foreach ($constraints as $name => $constraint) { + $columns = []; + foreach ($constraint['columns'] as $column) { + $columns[] = '"' . $column . '"'; + } + $annotations[] = '@' . $this->annotationsPrefix . $constraintName . '(name="' . $name . '", columns={' . implode(', ', $columns) . '})'; + } + + return implode(', ', $annotations); + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateInheritanceAnnotation(ClassMetadataInfo $metadata) + { + if ($metadata->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_NONE) { + return ''; + } + + return '@' . $this->annotationsPrefix . 'InheritanceType("'.$this->getInheritanceTypeString($metadata->inheritanceType).'")'; + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateDiscriminatorColumnAnnotation(ClassMetadataInfo $metadata) + { + if ($metadata->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_NONE) { + return ''; + } + + $discrColumn = $metadata->discriminatorColumn; + $columnDefinition = 'name="' . $discrColumn['name'] + . '", type="' . $discrColumn['type'] + . '", length=' . $discrColumn['length']; + + return '@' . $this->annotationsPrefix . 'DiscriminatorColumn(' . $columnDefinition . ')'; + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateDiscriminatorMapAnnotation(ClassMetadataInfo $metadata) + { + if ($metadata->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_NONE) { + return null; + } + + $inheritanceClassMap = []; + + foreach ($metadata->discriminatorMap as $type => $class) { + $inheritanceClassMap[] .= '"' . $type . '" = "' . $class . '"'; + } + + return '@' . $this->annotationsPrefix . 'DiscriminatorMap({' . implode(', ', $inheritanceClassMap) . '})'; + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateEntityStubMethods(ClassMetadataInfo $metadata) + { + $methods = []; + + foreach ($metadata->fieldMappings as $fieldMapping) { + if (isset($fieldMapping['declaredField'], $metadata->embeddedClasses[$fieldMapping['declaredField']])) { + continue; + } + + $nullableField = $this->nullableFieldExpression($fieldMapping); + + if ((!$metadata->isEmbeddedClass || !$this->embeddablesImmutable) + && (!isset($fieldMapping['id']) || ! $fieldMapping['id'] || $metadata->generatorType === ClassMetadataInfo::GENERATOR_TYPE_NONE) + && $code = $this->generateEntityStubMethod($metadata, 'set', $fieldMapping['fieldName'], $fieldMapping['type'], $nullableField) + ) { + $methods[] = $code; + } + + if ($code = $this->generateEntityStubMethod($metadata, 'get', $fieldMapping['fieldName'], $fieldMapping['type'], $nullableField)) { + $methods[] = $code; + } + } + + foreach ($metadata->embeddedClasses as $fieldName => $embeddedClass) { + if (isset($embeddedClass['declaredField'])) { + continue; + } + + if ( ! $metadata->isEmbeddedClass || ! $this->embeddablesImmutable) { + if ($code = $this->generateEntityStubMethod($metadata, 'set', $fieldName, $embeddedClass['class'])) { + $methods[] = $code; + } + } + + if ($code = $this->generateEntityStubMethod($metadata, 'get', $fieldName, $embeddedClass['class'])) { + $methods[] = $code; + } + } + + foreach ($metadata->associationMappings as $associationMapping) { + if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) { + $nullable = $this->isAssociationIsNullable($associationMapping) ? 'null' : null; + if ($code = $this->generateEntityStubMethod($metadata, 'set', $associationMapping['fieldName'], $associationMapping['targetEntity'], $nullable)) { + $methods[] = $code; + } + if ($code = $this->generateEntityStubMethod($metadata, 'get', $associationMapping['fieldName'], $associationMapping['targetEntity'], $nullable)) { + $methods[] = $code; + } + } elseif ($associationMapping['type'] & ClassMetadataInfo::TO_MANY) { + if ($code = $this->generateEntityStubMethod($metadata, 'add', $associationMapping['fieldName'], $associationMapping['targetEntity'])) { + $methods[] = $code; + } + if ($code = $this->generateEntityStubMethod($metadata, 'remove', $associationMapping['fieldName'], $associationMapping['targetEntity'])) { + $methods[] = $code; + } + if ($code = $this->generateEntityStubMethod($metadata, 'get', $associationMapping['fieldName'], Collection::class)) { + $methods[] = $code; + } + } + } + + return implode("\n\n", $methods); + } + + /** + * @param array $associationMapping + * + * @return bool + */ + protected function isAssociationIsNullable(array $associationMapping) + { + if (isset($associationMapping['id']) && $associationMapping['id']) { + return false; + } + + if (isset($associationMapping['joinColumns'])) { + $joinColumns = $associationMapping['joinColumns']; + } else { + //@todo there is no way to retrieve targetEntity metadata + $joinColumns = []; + } + + foreach ($joinColumns as $joinColumn) { + if (isset($joinColumn['nullable']) && !$joinColumn['nullable']) { + return false; + } + } + + return true; + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateEntityLifecycleCallbackMethods(ClassMetadataInfo $metadata) + { + if (empty($metadata->lifecycleCallbacks)) { + return ''; + } + + $methods = []; + + foreach ($metadata->lifecycleCallbacks as $name => $callbacks) { + foreach ($callbacks as $callback) { + $methods[] = $this->generateLifecycleCallbackMethod($name, $callback, $metadata); + } + } + + return implode("\n\n", array_filter($methods)); + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateEntityAssociationMappingProperties(ClassMetadataInfo $metadata) + { + $lines = []; + + foreach ($metadata->associationMappings as $associationMapping) { + if ($this->hasProperty($associationMapping['fieldName'], $metadata)) { + continue; + } + + $lines[] = $this->generateAssociationMappingPropertyDocBlock($associationMapping, $metadata); + $lines[] = $this->spaces . $this->fieldVisibility . ' $' . $associationMapping['fieldName'] + . ($associationMapping['type'] == 'manyToMany' ? ' = array()' : null) . ";\n"; + } + + return implode("\n", $lines); + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateEntityFieldMappingProperties(ClassMetadataInfo $metadata) + { + $lines = []; + + foreach ($metadata->fieldMappings as $fieldMapping) { + if (isset($fieldMapping['declaredField'], $metadata->embeddedClasses[$fieldMapping['declaredField']]) || + $this->hasProperty($fieldMapping['fieldName'], $metadata) || + $metadata->isInheritedField($fieldMapping['fieldName']) + ) { + continue; + } + + $lines[] = $this->generateFieldMappingPropertyDocBlock($fieldMapping, $metadata); + $lines[] = $this->spaces . $this->fieldVisibility . ' $' . $fieldMapping['fieldName'] + . (isset($fieldMapping['options']['default']) ? ' = ' . var_export($fieldMapping['options']['default'], true) : null) . ";\n"; + } + + return implode("\n", $lines); + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateEntityEmbeddedProperties(ClassMetadataInfo $metadata) + { + $lines = []; + + foreach ($metadata->embeddedClasses as $fieldName => $embeddedClass) { + if (isset($embeddedClass['declaredField']) || $this->hasProperty($fieldName, $metadata)) { + continue; + } + + $lines[] = $this->generateEmbeddedPropertyDocBlock($embeddedClass); + $lines[] = $this->spaces . $this->fieldVisibility . ' $' . $fieldName . ";\n"; + } + + return implode("\n", $lines); + } + + /** + * @param ClassMetadataInfo $metadata + * @param string $type + * @param string $fieldName + * @param string|null $typeHint + * @param string|null $defaultValue + * + * @return string + */ + protected function generateEntityStubMethod(ClassMetadataInfo $metadata, $type, $fieldName, $typeHint = null, $defaultValue = null) + { + $methodName = $type . Inflector::classify($fieldName); + $variableName = Inflector::camelize($fieldName); + if (in_array($type, ["add", "remove"])) { + $methodName = Inflector::singularize($methodName); + $variableName = Inflector::singularize($variableName); + } + + if ($this->hasMethod($methodName, $metadata)) { + return ''; + } + $this->staticReflection[$metadata->name]['methods'][] = strtolower($methodName); + + $var = sprintf('%sMethodTemplate', $type); + $template = static::$$var; + + $methodTypeHint = null; + $types = Type::getTypesMap(); + $variableType = $typeHint ? $this->getType($typeHint) : null; + + if ($typeHint && ! isset($types[$typeHint])) { + $variableType = '\\' . ltrim($variableType, '\\'); + $methodTypeHint = '\\' . $typeHint . ' '; + } + + $replacements = [ + '' => ucfirst($type) . ' ' . $variableName . '.', + '' => $methodTypeHint, + '' => $variableType . (null !== $defaultValue ? ('|' . $defaultValue) : ''), + '' => $variableName, + '' => $methodName, + '' => $fieldName, + '' => ($defaultValue !== null ) ? (' = ' . $defaultValue) : '', + '' => $this->getClassName($metadata) + ]; + + $method = str_replace( + array_keys($replacements), + array_values($replacements), + $template + ); + + return $this->prefixCodeWithSpaces($method); + } + + /** + * @param string $name + * @param string $methodName + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateLifecycleCallbackMethod($name, $methodName, ClassMetadataInfo $metadata) + { + if ($this->hasMethod($methodName, $metadata)) { + return ''; + } + + $this->staticReflection[$metadata->name]['methods'][] = $methodName; + + $replacements = [ + '' => $this->annotationsPrefix . ucfirst($name), + '' => $methodName, + ]; + + $method = str_replace( + array_keys($replacements), + array_values($replacements), + static::$lifecycleCallbackMethodTemplate + ); + + return $this->prefixCodeWithSpaces($method); + } + + /** + * @param array $joinColumn + * + * @return string + */ + protected function generateJoinColumnAnnotation(array $joinColumn) + { + $joinColumnAnnot = []; + + if (isset($joinColumn['name'])) { + $joinColumnAnnot[] = 'name="' . $joinColumn['name'] . '"'; + } + + if (isset($joinColumn['referencedColumnName'])) { + $joinColumnAnnot[] = 'referencedColumnName="' . $joinColumn['referencedColumnName'] . '"'; + } + + if (isset($joinColumn['unique']) && $joinColumn['unique']) { + $joinColumnAnnot[] = 'unique=' . ($joinColumn['unique'] ? 'true' : 'false'); + } + + if (isset($joinColumn['nullable'])) { + $joinColumnAnnot[] = 'nullable=' . ($joinColumn['nullable'] ? 'true' : 'false'); + } + + if (isset($joinColumn['onDelete'])) { + $joinColumnAnnot[] = 'onDelete="' . ($joinColumn['onDelete'] . '"'); + } + + if (isset($joinColumn['columnDefinition'])) { + $joinColumnAnnot[] = 'columnDefinition="' . $joinColumn['columnDefinition'] . '"'; + } + + return '@' . $this->annotationsPrefix . 'JoinColumn(' . implode(', ', $joinColumnAnnot) . ')'; + } + + /** + * @param array $associationMapping + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateAssociationMappingPropertyDocBlock(array $associationMapping, ClassMetadataInfo $metadata) + { + $lines = []; + $lines[] = $this->spaces . '/**'; + + if ($associationMapping['type'] & ClassMetadataInfo::TO_MANY) { + $lines[] = $this->spaces . ' * @var \Doctrine\Common\Collections\Collection'; + } else { + $lines[] = $this->spaces . ' * @var \\' . ltrim($associationMapping['targetEntity'], '\\'); + } + + if ($this->generateAnnotations) { + $lines[] = $this->spaces . ' *'; + + if (isset($associationMapping['id']) && $associationMapping['id']) { + $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'Id'; + + if ($generatorType = $this->getIdGeneratorTypeString($metadata->generatorType)) { + $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'GeneratedValue(strategy="' . $generatorType . '")'; + } + } + + $type = null; + switch ($associationMapping['type']) { + case ClassMetadataInfo::ONE_TO_ONE: + $type = 'OneToOne'; + break; + case ClassMetadataInfo::MANY_TO_ONE: + $type = 'ManyToOne'; + break; + case ClassMetadataInfo::ONE_TO_MANY: + $type = 'OneToMany'; + break; + case ClassMetadataInfo::MANY_TO_MANY: + $type = 'ManyToMany'; + break; + } + $typeOptions = []; + + if (isset($associationMapping['targetEntity'])) { + $typeOptions[] = 'targetEntity="' . $associationMapping['targetEntity'] . '"'; + } + + if (isset($associationMapping['inversedBy'])) { + $typeOptions[] = 'inversedBy="' . $associationMapping['inversedBy'] . '"'; + } + + if (isset($associationMapping['mappedBy'])) { + $typeOptions[] = 'mappedBy="' . $associationMapping['mappedBy'] . '"'; + } + + if ($associationMapping['cascade']) { + $cascades = []; + + if ($associationMapping['isCascadePersist']) $cascades[] = '"persist"'; + if ($associationMapping['isCascadeRemove']) $cascades[] = '"remove"'; + if ($associationMapping['isCascadeDetach']) $cascades[] = '"detach"'; + if ($associationMapping['isCascadeMerge']) $cascades[] = '"merge"'; + if ($associationMapping['isCascadeRefresh']) $cascades[] = '"refresh"'; + + if (count($cascades) === 5) { + $cascades = ['"all"']; + } + + $typeOptions[] = 'cascade={' . implode(',', $cascades) . '}'; + } + + if (isset($associationMapping['orphanRemoval']) && $associationMapping['orphanRemoval']) { + $typeOptions[] = 'orphanRemoval=' . ($associationMapping['orphanRemoval'] ? 'true' : 'false'); + } + + if (isset($associationMapping['fetch']) && $associationMapping['fetch'] !== ClassMetadataInfo::FETCH_LAZY) { + $fetchMap = [ + ClassMetadataInfo::FETCH_EXTRA_LAZY => 'EXTRA_LAZY', + ClassMetadataInfo::FETCH_EAGER => 'EAGER', + ]; + + $typeOptions[] = 'fetch="' . $fetchMap[$associationMapping['fetch']] . '"'; + } + + $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . '' . $type . '(' . implode(', ', $typeOptions) . ')'; + + if (isset($associationMapping['joinColumns']) && $associationMapping['joinColumns']) { + $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'JoinColumns({'; + + $joinColumnsLines = []; + + foreach ($associationMapping['joinColumns'] as $joinColumn) { + if ($joinColumnAnnot = $this->generateJoinColumnAnnotation($joinColumn)) { + $joinColumnsLines[] = $this->spaces . ' * ' . $joinColumnAnnot; + } + } + + $lines[] = implode(",\n", $joinColumnsLines); + $lines[] = $this->spaces . ' * })'; + } + + if (isset($associationMapping['joinTable']) && $associationMapping['joinTable']) { + $joinTable = []; + $joinTable[] = 'name="' . $associationMapping['joinTable']['name'] . '"'; + + if (isset($associationMapping['joinTable']['schema'])) { + $joinTable[] = 'schema="' . $associationMapping['joinTable']['schema'] . '"'; + } + + $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'JoinTable(' . implode(', ', $joinTable) . ','; + $lines[] = $this->spaces . ' * joinColumns={'; + + $joinColumnsLines = []; + + foreach ($associationMapping['joinTable']['joinColumns'] as $joinColumn) { + $joinColumnsLines[] = $this->spaces . ' * ' . $this->generateJoinColumnAnnotation($joinColumn); + } + + $lines[] = implode(",". PHP_EOL, $joinColumnsLines); + $lines[] = $this->spaces . ' * },'; + $lines[] = $this->spaces . ' * inverseJoinColumns={'; + + $inverseJoinColumnsLines = []; + + foreach ($associationMapping['joinTable']['inverseJoinColumns'] as $joinColumn) { + $inverseJoinColumnsLines[] = $this->spaces . ' * ' . $this->generateJoinColumnAnnotation($joinColumn); + } + + $lines[] = implode(",". PHP_EOL, $inverseJoinColumnsLines); + $lines[] = $this->spaces . ' * }'; + $lines[] = $this->spaces . ' * )'; + } + + if (isset($associationMapping['orderBy'])) { + $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'OrderBy({'; + + foreach ($associationMapping['orderBy'] as $name => $direction) { + $lines[] = $this->spaces . ' * "' . $name . '"="' . $direction . '",'; + } + + $lines[count($lines) - 1] = substr($lines[count($lines) - 1], 0, strlen($lines[count($lines) - 1]) - 1); + $lines[] = $this->spaces . ' * })'; + } + } + + $lines[] = $this->spaces . ' */'; + + return implode("\n", $lines); + } + + /** + * @param array $fieldMapping + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function generateFieldMappingPropertyDocBlock(array $fieldMapping, ClassMetadataInfo $metadata) + { + $lines = []; + $lines[] = $this->spaces . '/**'; + $lines[] = $this->spaces . ' * @var ' + . $this->getType($fieldMapping['type']) + . ($this->nullableFieldExpression($fieldMapping) ? '|null' : ''); + + if ($this->generateAnnotations) { + $lines[] = $this->spaces . ' *'; + + $column = []; + if (isset($fieldMapping['columnName'])) { + $column[] = 'name="' . $fieldMapping['columnName'] . '"'; + } + + if (isset($fieldMapping['type'])) { + $column[] = 'type="' . $fieldMapping['type'] . '"'; + } + + if (isset($fieldMapping['length'])) { + $column[] = 'length=' . $fieldMapping['length']; + } + + if (isset($fieldMapping['precision'])) { + $column[] = 'precision=' . $fieldMapping['precision']; + } + + if (isset($fieldMapping['scale'])) { + $column[] = 'scale=' . $fieldMapping['scale']; + } + + if (isset($fieldMapping['nullable'])) { + $column[] = 'nullable=' . var_export($fieldMapping['nullable'], true); + } + + $options = []; + + if (isset($fieldMapping['options']['default']) && $fieldMapping['options']['default']) { + $options[] = '"default"="' . $fieldMapping['options']['default'] .'"'; + } + + if (isset($fieldMapping['options']['unsigned']) && $fieldMapping['options']['unsigned']) { + $options[] = '"unsigned"=true'; + } + + if (isset($fieldMapping['options']['fixed']) && $fieldMapping['options']['fixed']) { + $options[] = '"fixed"=true'; + } + + if (isset($fieldMapping['options']['comment']) && $fieldMapping['options']['comment']) { + $options[] = '"comment"="' . str_replace('"', '""', $fieldMapping['options']['comment']) . '"'; + } + + if (isset($fieldMapping['options']['collation']) && $fieldMapping['options']['collation']) { + $options[] = '"collation"="' . $fieldMapping['options']['collation'] .'"'; + } + + if (isset($fieldMapping['options']['check']) && $fieldMapping['options']['check']) { + $options[] = '"check"="' . $fieldMapping['options']['check'] .'"'; + } + + if ($options) { + $column[] = 'options={'.implode(',', $options).'}'; + } + + if (isset($fieldMapping['columnDefinition'])) { + $column[] = 'columnDefinition="' . $fieldMapping['columnDefinition'] . '"'; + } + + if (isset($fieldMapping['unique'])) { + $column[] = 'unique=' . var_export($fieldMapping['unique'], true); + } + + $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'Column(' . implode(', ', $column) . ')'; + + if (isset($fieldMapping['id']) && $fieldMapping['id']) { + $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'Id'; + + if ($generatorType = $this->getIdGeneratorTypeString($metadata->generatorType)) { + $lines[] = $this->spaces.' * @' . $this->annotationsPrefix . 'GeneratedValue(strategy="' . $generatorType . '")'; + } + + if ($metadata->sequenceGeneratorDefinition) { + $sequenceGenerator = []; + + if (isset($metadata->sequenceGeneratorDefinition['sequenceName'])) { + $sequenceGenerator[] = 'sequenceName="' . $metadata->sequenceGeneratorDefinition['sequenceName'] . '"'; + } + + if (isset($metadata->sequenceGeneratorDefinition['allocationSize'])) { + $sequenceGenerator[] = 'allocationSize=' . $metadata->sequenceGeneratorDefinition['allocationSize']; + } + + if (isset($metadata->sequenceGeneratorDefinition['initialValue'])) { + $sequenceGenerator[] = 'initialValue=' . $metadata->sequenceGeneratorDefinition['initialValue']; + } + + $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'SequenceGenerator(' . implode(', ', $sequenceGenerator) . ')'; + } + } + + if (isset($fieldMapping['version']) && $fieldMapping['version']) { + $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'Version'; + } + } + + $lines[] = $this->spaces . ' */'; + + return implode("\n", $lines); + } + + /** + * @param array $embeddedClass + * + * @return string + */ + protected function generateEmbeddedPropertyDocBlock(array $embeddedClass) + { + $lines = []; + $lines[] = $this->spaces . '/**'; + $lines[] = $this->spaces . ' * @var \\' . ltrim($embeddedClass['class'], '\\'); + + if ($this->generateAnnotations) { + $lines[] = $this->spaces . ' *'; + + $embedded = ['class="' . $embeddedClass['class'] . '"']; + + if (isset($embeddedClass['columnPrefix'])) { + if (is_string($embeddedClass['columnPrefix'])) { + $embedded[] = 'columnPrefix="' . $embeddedClass['columnPrefix'] . '"'; + } else { + $embedded[] = 'columnPrefix=' . var_export($embeddedClass['columnPrefix'], true); + } + } + + $lines[] = $this->spaces . ' * @' . + $this->annotationsPrefix . 'Embedded(' . implode(', ', $embedded) . ')'; + } + + $lines[] = $this->spaces . ' */'; + + return implode("\n", $lines); + } + + private function generateEntityListenerAnnotation(ClassMetadataInfo $metadata): string + { + if (0 === \count($metadata->entityListeners)) { + return ''; + } + + $processedClasses = []; + foreach ($metadata->entityListeners as $event => $eventListeners) { + foreach ($eventListeners as $eventListener) { + $processedClasses[] = '"' . $eventListener['class'] . '"'; + } + } + + return \sprintf( + '%s%s({%s})', + '@' . $this->annotationsPrefix, + 'EntityListeners', + \implode(',', \array_unique($processedClasses)) + ); + } + + /** + * @param string $code + * @param int $num + * + * @return string + */ + protected function prefixCodeWithSpaces($code, $num = 1) + { + $lines = explode("\n", $code); + + foreach ($lines as $key => $value) { + if ( ! empty($value)) { + $lines[$key] = str_repeat($this->spaces, $num) . $lines[$key]; + } + } + + return implode("\n", $lines); + } + + /** + * @param integer $type The inheritance type used by the class and its subclasses. + * + * @return string The literal string for the inheritance type. + * + * @throws \InvalidArgumentException When the inheritance type does not exist. + */ + protected function getInheritanceTypeString($type) + { + if ( ! isset(static::$inheritanceTypeMap[$type])) { + throw new \InvalidArgumentException(sprintf('Invalid provided InheritanceType: %s', $type)); + } + + return static::$inheritanceTypeMap[$type]; + } + + /** + * @param integer $type The policy used for change-tracking for the mapped class. + * + * @return string The literal string for the change-tracking type. + * + * @throws \InvalidArgumentException When the change-tracking type does not exist. + */ + protected function getChangeTrackingPolicyString($type) + { + if ( ! isset(static::$changeTrackingPolicyMap[$type])) { + throw new \InvalidArgumentException(sprintf('Invalid provided ChangeTrackingPolicy: %s', $type)); + } + + return static::$changeTrackingPolicyMap[$type]; + } + + /** + * @param integer $type The generator to use for the mapped class. + * + * @return string The literal string for the generator type. + * + * @throws \InvalidArgumentException When the generator type does not exist. + */ + protected function getIdGeneratorTypeString($type) + { + if ( ! isset(static::$generatorStrategyMap[$type])) { + throw new \InvalidArgumentException(sprintf('Invalid provided IdGeneratorType: %s', $type)); + } + + return static::$generatorStrategyMap[$type]; + } + + /** + * @param array $fieldMapping + * + * @return string|null + */ + private function nullableFieldExpression(array $fieldMapping) + { + if (isset($fieldMapping['nullable']) && true === $fieldMapping['nullable']) { + return 'null'; + } + + return null; + } + + /** + * Exports (nested) option elements. + * + * @param array $options + * + * @return string + */ + private function exportTableOptions(array $options) + { + $optionsStr = []; + + foreach ($options as $name => $option) { + if (is_array($option)) { + $optionsStr[] = '"' . $name . '"={' . $this->exportTableOptions($option) . '}'; + } else { + $optionsStr[] = '"' . $name . '"="' . (string) $option . '"'; + } + } + + return implode(',', $optionsStr); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityRepositoryGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityRepositoryGenerator.php new file mode 100644 index 0000000..9b3b290 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityRepositoryGenerator.php @@ -0,0 +1,182 @@ +. + */ + +namespace Doctrine\ORM\Tools; + +use Doctrine\ORM\EntityRepository; +use const E_USER_DEPRECATED; +use function trigger_error; + +/** + * Class to generate entity repository classes + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class EntityRepositoryGenerator +{ + private $repositoryName; + + protected static $_template = +' + +/** + * + * + * This class was generated by the Doctrine ORM. Add your own custom + * repository methods below. + */ +class extends +{ +} +'; + + public function __construct() + { + @trigger_error(self::class . ' is deprecated and will be removed in Doctrine ORM 3.0', E_USER_DEPRECATED); + } + + /** + * @param string $fullClassName + * + * @return string + */ + public function generateEntityRepositoryClass($fullClassName) + { + $variables = [ + '' => $this->generateEntityRepositoryNamespace($fullClassName), + '' => $this->generateEntityRepositoryName($fullClassName), + '' => $this->generateClassName($fullClassName) + ]; + + return str_replace(array_keys($variables), array_values($variables), self::$_template); + } + + /** + * Generates the namespace, if class do not have namespace, return empty string instead. + * + * @param string $fullClassName + * + * @return string $namespace + */ + private function getClassNamespace($fullClassName) + { + $namespace = substr($fullClassName, 0, strrpos($fullClassName, '\\')); + + return $namespace; + } + + /** + * Generates the class name + * + * @param string $fullClassName + * + * @return string + */ + private function generateClassName($fullClassName) + { + $namespace = $this->getClassNamespace($fullClassName); + + $className = $fullClassName; + + if ($namespace) { + $className = substr($fullClassName, strrpos($fullClassName, '\\') + 1, strlen($fullClassName)); + } + + return $className; + } + + /** + * Generates the namespace statement, if class do not have namespace, return empty string instead. + * + * @param string $fullClassName The full repository class name. + * + * @return string $namespace + */ + private function generateEntityRepositoryNamespace($fullClassName) + { + $namespace = $this->getClassNamespace($fullClassName); + + return $namespace ? 'namespace ' . $namespace . ';' : ''; + } + + /** + * @param string $fullClassName + * + * @return string $repositoryName + */ + private function generateEntityRepositoryName($fullClassName) + { + $namespace = $this->getClassNamespace($fullClassName); + + $repositoryName = $this->repositoryName ?: EntityRepository::class; + + if ($namespace && $repositoryName[0] !== '\\') { + $repositoryName = '\\' . $repositoryName; + } + + return $repositoryName; + } + + /** + * @param string $fullClassName + * @param string $outputDirectory + * + * @return void + */ + public function writeEntityRepositoryClass($fullClassName, $outputDirectory) + { + $code = $this->generateEntityRepositoryClass($fullClassName); + + $path = $outputDirectory . DIRECTORY_SEPARATOR + . str_replace('\\', \DIRECTORY_SEPARATOR, $fullClassName) . '.php'; + $dir = dirname($path); + + if ( ! is_dir($dir)) { + mkdir($dir, 0775, true); + } + + if ( ! file_exists($path)) { + file_put_contents($path, $code); + chmod($path, 0664); + } + } + + /** + * @param string $repositoryName + * + * @return \Doctrine\ORM\Tools\EntityRepositoryGenerator + */ + public function setDefaultRepositoryName($repositoryName) + { + $this->repositoryName = $repositoryName; + + return $this; + } + +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaEventArgs.php new file mode 100644 index 0000000..ed03e32 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaEventArgs.php @@ -0,0 +1,71 @@ +. + */ + +namespace Doctrine\ORM\Tools\Event; + +use Doctrine\Common\EventArgs; +use Doctrine\DBAL\Schema\Schema; +use Doctrine\ORM\EntityManagerInterface; + +/** + * Event Args used for the Events::postGenerateSchema event. + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.com + * @since 1.0 + * @author Benjamin Eberlei + */ +class GenerateSchemaEventArgs extends EventArgs +{ + /** + * @var \Doctrine\ORM\EntityManagerInterface + */ + private $em; + + /** + * @var \Doctrine\DBAL\Schema\Schema + */ + private $schema; + + /** + * @param EntityManagerInterface $em + * @param Schema $schema + */ + public function __construct(EntityManagerInterface $em, Schema $schema) + { + $this->em = $em; + $this->schema = $schema; + } + + /** + * @return EntityManagerInterface + */ + public function getEntityManager() + { + return $this->em; + } + + /** + * @return Schema + */ + public function getSchema() + { + return $this->schema; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaTableEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaTableEventArgs.php new file mode 100644 index 0000000..e2c38f9 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaTableEventArgs.php @@ -0,0 +1,86 @@ +. + */ +namespace Doctrine\ORM\Tools\Event; + +use Doctrine\Common\EventArgs; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Schema\Table; + +/** + * Event Args used for the Events::postGenerateSchemaTable event. + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.com + * @since 1.0 + * @author Benjamin Eberlei + */ +class GenerateSchemaTableEventArgs extends EventArgs +{ + /** + * @var \Doctrine\ORM\Mapping\ClassMetadata + */ + private $classMetadata; + + /** + * @var \Doctrine\DBAL\Schema\Schema + */ + private $schema; + + /** + * @var \Doctrine\DBAL\Schema\Table + */ + private $classTable; + + /** + * @param ClassMetadata $classMetadata + * @param Schema $schema + * @param Table $classTable + */ + public function __construct(ClassMetadata $classMetadata, Schema $schema, Table $classTable) + { + $this->classMetadata = $classMetadata; + $this->schema = $schema; + $this->classTable = $classTable; + } + + /** + * @return ClassMetadata + */ + public function getClassMetadata() + { + return $this->classMetadata; + } + + /** + * @return Schema + */ + public function getSchema() + { + return $this->schema; + } + + /** + * @return Table + */ + public function getClassTable() + { + return $this->classTable; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ClassMetadataExporter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ClassMetadataExporter.php new file mode 100644 index 0000000..15c03b5 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ClassMetadataExporter.php @@ -0,0 +1,86 @@ +. + */ + +namespace Doctrine\ORM\Tools\Export; + +use const E_USER_DEPRECATED; +use function trigger_error; + +/** + * Class used for converting your mapping information between the + * supported formats: yaml, xml, and php/annotation. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan Wage + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class ClassMetadataExporter +{ + /** + * @var array + */ + private static $_exporterDrivers = [ + 'xml' => Driver\XmlExporter::class, + 'yaml' => Driver\YamlExporter::class, + 'yml' => Driver\YamlExporter::class, + 'php' => Driver\PhpExporter::class, + 'annotation' => Driver\AnnotationExporter::class + ]; + + public function __construct() + { + @trigger_error(self::class . ' is deprecated and will be removed in Doctrine ORM 3.0', E_USER_DEPRECATED); + } + + /** + * Registers a new exporter driver class under a specified name. + * + * @param string $name + * @param string $class + * + * @return void + */ + public static function registerExportDriver($name, $class) + { + self::$_exporterDrivers[$name] = $class; + } + + /** + * Gets an exporter driver instance. + * + * @param string $type The type to get (yml, xml, etc.). + * @param string|null $dest The directory where the exporter will export to. + * + * @return Driver\AbstractExporter + * + * @throws ExportException + */ + public function getExporter($type, $dest = null) + { + if ( ! isset(self::$_exporterDrivers[$type])) { + throw ExportException::invalidExporterDriverType($type); + } + + $class = self::$_exporterDrivers[$type]; + + return new $class($dest); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php new file mode 100644 index 0000000..efe8e7b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php @@ -0,0 +1,275 @@ +. + */ + +namespace Doctrine\ORM\Tools\Export\Driver; + +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Doctrine\ORM\Tools\Export\ExportException; +use const E_USER_DEPRECATED; +use function trigger_error; + +/** + * Abstract base class which is to be used for the Exporter drivers + * which can be found in \Doctrine\ORM\Tools\Export\Driver. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan Wage + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +abstract class AbstractExporter +{ + /** + * @var array + */ + protected $_metadata = []; + + /** + * @var string|null + */ + protected $_outputDir; + + /** + * @var string|null + */ + protected $_extension; + + /** + * @var bool + */ + protected $_overwriteExistingFiles = false; + + /** + * @param string|null $dir + */ + public function __construct($dir = null) + { + @trigger_error(static::class . ' is deprecated and will be removed in Doctrine ORM 3.0', E_USER_DEPRECATED); + + $this->_outputDir = $dir; + } + + /** + * @param bool $overwrite + * + * @return void + */ + public function setOverwriteExistingFiles($overwrite) + { + $this->_overwriteExistingFiles = $overwrite; + } + + /** + * Converts a single ClassMetadata instance to the exported format + * and returns it. + * + * @param ClassMetadataInfo $metadata + * + * @return string + */ + abstract public function exportClassMetadata(ClassMetadataInfo $metadata); + + /** + * Sets the array of ClassMetadataInfo instances to export. + * + * @param array $metadata + * + * @return void + */ + public function setMetadata(array $metadata) + { + $this->_metadata = $metadata; + } + + /** + * Gets the extension used to generated the path to a class. + * + * @return string|null + */ + public function getExtension() + { + return $this->_extension; + } + + /** + * Sets the directory to output the mapping files to. + * + * [php] + * $exporter = new YamlExporter($metadata); + * $exporter->setOutputDir(__DIR__ . '/yaml'); + * $exporter->export(); + * + * @param string $dir + * + * @return void + */ + public function setOutputDir($dir) + { + $this->_outputDir = $dir; + } + + /** + * Exports each ClassMetadata instance to a single Doctrine Mapping file + * named after the entity. + * + * @return void + * + * @throws \Doctrine\ORM\Tools\Export\ExportException + */ + public function export() + { + if ( ! is_dir($this->_outputDir)) { + mkdir($this->_outputDir, 0775, true); + } + + foreach ($this->_metadata as $metadata) { + // In case output is returned, write it to a file, skip otherwise + if ($output = $this->exportClassMetadata($metadata)) { + $path = $this->_generateOutputPath($metadata); + $dir = dirname($path); + if ( ! is_dir($dir)) { + mkdir($dir, 0775, true); + } + if (file_exists($path) && !$this->_overwriteExistingFiles) { + throw ExportException::attemptOverwriteExistingFile($path); + } + file_put_contents($path, $output); + chmod($path, 0664); + } + } + } + + /** + * Generates the path to write the class for the given ClassMetadataInfo instance. + * + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function _generateOutputPath(ClassMetadataInfo $metadata) + { + return $this->_outputDir . '/' . str_replace('\\', '.', $metadata->name) . $this->_extension; + } + + /** + * Sets the directory to output the mapping files to. + * + * [php] + * $exporter = new YamlExporter($metadata, __DIR__ . '/yaml'); + * $exporter->setExtension('.yml'); + * $exporter->export(); + * + * @param string $extension + * + * @return void + */ + public function setExtension($extension) + { + $this->_extension = $extension; + } + + /** + * @param int $type + * + * @return string + */ + protected function _getInheritanceTypeString($type) + { + switch ($type) { + case ClassMetadataInfo::INHERITANCE_TYPE_NONE: + return 'NONE'; + + case ClassMetadataInfo::INHERITANCE_TYPE_JOINED: + return 'JOINED'; + + case ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_TABLE: + return 'SINGLE_TABLE'; + + case ClassMetadataInfo::INHERITANCE_TYPE_TABLE_PER_CLASS: + return 'PER_CLASS'; + } + } + + /** + * @param int $mode + * + * @return string + */ + protected function _getFetchModeString($mode) + { + switch ($mode) { + case ClassMetadataInfo::FETCH_EAGER: + return 'EAGER'; + + case ClassMetadataInfo::FETCH_EXTRA_LAZY: + return 'EXTRA_LAZY'; + + case ClassMetadataInfo::FETCH_LAZY: + return 'LAZY'; + } + } + + /** + * @param int $policy + * + * @return string + */ + protected function _getChangeTrackingPolicyString($policy) + { + switch ($policy) { + case ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT: + return 'DEFERRED_IMPLICIT'; + + case ClassMetadataInfo::CHANGETRACKING_DEFERRED_EXPLICIT: + return 'DEFERRED_EXPLICIT'; + + case ClassMetadataInfo::CHANGETRACKING_NOTIFY: + return 'NOTIFY'; + } + } + + /** + * @param int $type + * + * @return string + */ + protected function _getIdGeneratorTypeString($type) + { + switch ($type) { + case ClassMetadataInfo::GENERATOR_TYPE_AUTO: + return 'AUTO'; + + case ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE: + return 'SEQUENCE'; + + case ClassMetadataInfo::GENERATOR_TYPE_TABLE: + return 'TABLE'; + + case ClassMetadataInfo::GENERATOR_TYPE_IDENTITY: + return 'IDENTITY'; + + case ClassMetadataInfo::GENERATOR_TYPE_UUID: + return 'UUID'; + + case ClassMetadataInfo::GENERATOR_TYPE_CUSTOM: + return 'CUSTOM'; + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php new file mode 100644 index 0000000..29cb8df --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php @@ -0,0 +1,82 @@ +. + */ + +namespace Doctrine\ORM\Tools\Export\Driver; + +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Doctrine\ORM\Tools\EntityGenerator; + +/** + * ClassMetadata exporter for PHP classes with annotations. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan Wage + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class AnnotationExporter extends AbstractExporter +{ + /** + * @var string + */ + protected $_extension = '.php'; + + /** + * @var EntityGenerator|null + */ + private $_entityGenerator; + + /** + * {@inheritdoc} + */ + public function exportClassMetadata(ClassMetadataInfo $metadata) + { + if ( ! $this->_entityGenerator) { + throw new \RuntimeException('For the AnnotationExporter you must set an EntityGenerator instance with the setEntityGenerator() method.'); + } + + $this->_entityGenerator->setGenerateAnnotations(true); + $this->_entityGenerator->setGenerateStubMethods(false); + $this->_entityGenerator->setRegenerateEntityIfExists(false); + $this->_entityGenerator->setUpdateEntityIfExists(false); + + return $this->_entityGenerator->generateEntityClass($metadata); + } + + /** + * @param ClassMetadataInfo $metadata + * + * @return string + */ + protected function _generateOutputPath(ClassMetadataInfo $metadata) + { + return $this->_outputDir . '/' . str_replace('\\', '/', $metadata->name) . $this->_extension; + } + + /** + * @param EntityGenerator $entityGenerator + * + * @return void + */ + public function setEntityGenerator(EntityGenerator $entityGenerator) + { + $this->_entityGenerator = $entityGenerator; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php new file mode 100644 index 0000000..c0cd176 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php @@ -0,0 +1,202 @@ +. + */ + +namespace Doctrine\ORM\Tools\Export\Driver; + +use Doctrine\ORM\Mapping\ClassMetadataInfo; + +/** + * ClassMetadata exporter for PHP code. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan Wage + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class PhpExporter extends AbstractExporter +{ + /** + * @var string + */ + protected $_extension = '.php'; + + /** + * {@inheritdoc} + */ + public function exportClassMetadata(ClassMetadataInfo $metadata) + { + $lines = []; + $lines[] = 'isMappedSuperclass) { + $lines[] = '$metadata->isMappedSuperclass = true;'; + } + + if ($metadata->inheritanceType) { + $lines[] = '$metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_' . $this->_getInheritanceTypeString($metadata->inheritanceType) . ');'; + } + + if ($metadata->customRepositoryClassName) { + $lines[] = "\$metadata->customRepositoryClassName = '" . $metadata->customRepositoryClassName . "';"; + } + + if ($metadata->table) { + $lines[] = '$metadata->setPrimaryTable(' . $this->_varExport($metadata->table) . ');'; + } + + if ($metadata->discriminatorColumn) { + $lines[] = '$metadata->setDiscriminatorColumn(' . $this->_varExport($metadata->discriminatorColumn) . ');'; + } + + if ($metadata->discriminatorMap) { + $lines[] = '$metadata->setDiscriminatorMap(' . $this->_varExport($metadata->discriminatorMap) . ');'; + } + + if ($metadata->changeTrackingPolicy) { + $lines[] = '$metadata->setChangeTrackingPolicy(ClassMetadataInfo::CHANGETRACKING_' . $this->_getChangeTrackingPolicyString($metadata->changeTrackingPolicy) . ');'; + } + + if ($metadata->lifecycleCallbacks) { + foreach ($metadata->lifecycleCallbacks as $event => $callbacks) { + foreach ($callbacks as $callback) { + $lines[] = "\$metadata->addLifecycleCallback('$callback', '$event');"; + } + } + } + + $lines = array_merge($lines, $this->processEntityListeners($metadata)); + + foreach ($metadata->fieldMappings as $fieldMapping) { + $lines[] = '$metadata->mapField(' . $this->_varExport($fieldMapping) . ');'; + } + + if ( ! $metadata->isIdentifierComposite && $generatorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) { + $lines[] = '$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_' . $generatorType . ');'; + } + + foreach ($metadata->associationMappings as $associationMapping) { + $cascade = ['remove', 'persist', 'refresh', 'merge', 'detach']; + foreach ($cascade as $key => $value) { + if ( ! $associationMapping['isCascade'.ucfirst($value)]) { + unset($cascade[$key]); + } + } + + if (count($cascade) === 5) { + $cascade = ['all']; + } + + $method = null; + $associationMappingArray = [ + 'fieldName' => $associationMapping['fieldName'], + 'targetEntity' => $associationMapping['targetEntity'], + 'cascade' => $cascade, + ]; + + if (isset($associationMapping['fetch'])) { + $associationMappingArray['fetch'] = $associationMapping['fetch']; + } + + if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) { + $method = 'mapOneToOne'; + $oneToOneMappingArray = [ + 'mappedBy' => $associationMapping['mappedBy'], + 'inversedBy' => $associationMapping['inversedBy'], + 'joinColumns' => $associationMapping['isOwningSide'] ? $associationMapping['joinColumns'] : [], + 'orphanRemoval' => $associationMapping['orphanRemoval'], + ]; + + $associationMappingArray = array_merge($associationMappingArray, $oneToOneMappingArray); + } elseif ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) { + $method = 'mapOneToMany'; + $potentialAssociationMappingIndexes = [ + 'mappedBy', + 'orphanRemoval', + 'orderBy', + ]; + $oneToManyMappingArray = []; + foreach ($potentialAssociationMappingIndexes as $index) { + if (isset($associationMapping[$index])) { + $oneToManyMappingArray[$index] = $associationMapping[$index]; + } + } + $associationMappingArray = array_merge($associationMappingArray, $oneToManyMappingArray); + } elseif ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_MANY) { + $method = 'mapManyToMany'; + $potentialAssociationMappingIndexes = [ + 'mappedBy', + 'joinTable', + 'orderBy', + ]; + $manyToManyMappingArray = []; + foreach ($potentialAssociationMappingIndexes as $index) { + if (isset($associationMapping[$index])) { + $manyToManyMappingArray[$index] = $associationMapping[$index]; + } + } + $associationMappingArray = array_merge($associationMappingArray, $manyToManyMappingArray); + } + + $lines[] = '$metadata->' . $method . '(' . $this->_varExport($associationMappingArray) . ');'; + } + + return implode("\n", $lines); + } + + /** + * @param mixed $var + * + * @return string + */ + protected function _varExport($var) + { + $export = var_export($var, true); + $export = str_replace("\n", PHP_EOL . str_repeat(' ', 8), $export); + $export = str_replace(' ', ' ', $export); + $export = str_replace('array (', 'array(', $export); + $export = str_replace('array( ', 'array(', $export); + $export = str_replace(',)', ')', $export); + $export = str_replace(', )', ')', $export); + $export = str_replace(' ', ' ', $export); + + return $export; + } + + private function processEntityListeners(ClassMetadataInfo $metadata) : array + { + $lines = []; + + foreach ($metadata->entityListeners as $event => $entityListenerConfig) { + foreach ($entityListenerConfig as $entityListener) { + $lines[] = \sprintf( + '$metadata->addEntityListener(%s, %s, %s);', + \var_export($event, true), + \var_export($entityListener['class'], true), + \var_export($entityListener['method'], true) + ); + } + } + + return $lines; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php new file mode 100644 index 0000000..6503649 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php @@ -0,0 +1,496 @@ +. + */ + +namespace Doctrine\ORM\Tools\Export\Driver; + +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use SimpleXMLElement; + +/** + * ClassMetadata exporter for Doctrine XML mapping files. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan Wage + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class XmlExporter extends AbstractExporter +{ + /** + * @var string + */ + protected $_extension = '.dcm.xml'; + + /** + * {@inheritdoc} + */ + public function exportClassMetadata(ClassMetadataInfo $metadata) + { + $xml = new SimpleXmlElement(''); + + if ($metadata->isMappedSuperclass) { + $root = $xml->addChild('mapped-superclass'); + } else { + $root = $xml->addChild('entity'); + } + + if ($metadata->customRepositoryClassName) { + $root->addAttribute('repository-class', $metadata->customRepositoryClassName); + } + + $root->addAttribute('name', $metadata->name); + + if (isset($metadata->table['name'])) { + $root->addAttribute('table', $metadata->table['name']); + } + + if (isset($metadata->table['schema'])) { + $root->addAttribute('schema', $metadata->table['schema']); + } + + if ($metadata->inheritanceType && $metadata->inheritanceType !== ClassMetadataInfo::INHERITANCE_TYPE_NONE) { + $root->addAttribute('inheritance-type', $this->_getInheritanceTypeString($metadata->inheritanceType)); + } + + if (isset($metadata->table['options'])) { + $optionsXml = $root->addChild('options'); + + $this->exportTableOptions($optionsXml, $metadata->table['options']); + } + + if ($metadata->discriminatorColumn) { + $discriminatorColumnXml = $root->addChild('discriminator-column'); + $discriminatorColumnXml->addAttribute('name', $metadata->discriminatorColumn['name']); + $discriminatorColumnXml->addAttribute('type', $metadata->discriminatorColumn['type']); + + if (isset($metadata->discriminatorColumn['length'])) { + $discriminatorColumnXml->addAttribute('length', $metadata->discriminatorColumn['length']); + } + } + + if ($metadata->discriminatorMap) { + $discriminatorMapXml = $root->addChild('discriminator-map'); + + foreach ($metadata->discriminatorMap as $value => $className) { + $discriminatorMappingXml = $discriminatorMapXml->addChild('discriminator-mapping'); + $discriminatorMappingXml->addAttribute('value', $value); + $discriminatorMappingXml->addAttribute('class', $className); + } + } + + $trackingPolicy = $this->_getChangeTrackingPolicyString($metadata->changeTrackingPolicy); + + if ( $trackingPolicy != 'DEFERRED_IMPLICIT') { + $root->addChild('change-tracking-policy', $trackingPolicy); + } + + if (isset($metadata->table['indexes'])) { + $indexesXml = $root->addChild('indexes'); + + foreach ($metadata->table['indexes'] as $name => $index) { + $indexXml = $indexesXml->addChild('index'); + $indexXml->addAttribute('name', $name); + $indexXml->addAttribute('columns', implode(',', $index['columns'])); + if (isset($index['flags'])) { + $indexXml->addAttribute('flags', implode(',', $index['flags'])); + } + } + } + + if (isset($metadata->table['uniqueConstraints'])) { + $uniqueConstraintsXml = $root->addChild('unique-constraints'); + + foreach ($metadata->table['uniqueConstraints'] as $name => $unique) { + $uniqueConstraintXml = $uniqueConstraintsXml->addChild('unique-constraint'); + $uniqueConstraintXml->addAttribute('name', $name); + $uniqueConstraintXml->addAttribute('columns', implode(',', $unique['columns'])); + } + } + + $fields = $metadata->fieldMappings; + + $id = []; + foreach ($fields as $name => $field) { + if (isset($field['id']) && $field['id']) { + $id[$name] = $field; + unset($fields[$name]); + } + } + + foreach ($metadata->associationMappings as $name => $assoc) { + if (isset($assoc['id']) && $assoc['id']) { + $id[$name] = [ + 'fieldName' => $name, + 'associationKey' => true + ]; + } + } + + if ( ! $metadata->isIdentifierComposite && $idGeneratorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) { + $id[$metadata->getSingleIdentifierFieldName()]['generator']['strategy'] = $idGeneratorType; + } + + if ($id) { + foreach ($id as $field) { + $idXml = $root->addChild('id'); + $idXml->addAttribute('name', $field['fieldName']); + + if (isset($field['type'])) { + $idXml->addAttribute('type', $field['type']); + } + + if (isset($field['columnName'])) { + $idXml->addAttribute('column', $field['columnName']); + } + + if (isset($field['length'])) { + $idXml->addAttribute('length', $field['length']); + } + + if (isset($field['associationKey']) && $field['associationKey']) { + $idXml->addAttribute('association-key', 'true'); + } + + if ($idGeneratorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) { + $generatorXml = $idXml->addChild('generator'); + $generatorXml->addAttribute('strategy', $idGeneratorType); + + $this->exportSequenceInformation($idXml, $metadata); + } + } + } + + if ($fields) { + foreach ($fields as $field) { + $fieldXml = $root->addChild('field'); + $fieldXml->addAttribute('name', $field['fieldName']); + $fieldXml->addAttribute('type', $field['type']); + + if (isset($field['columnName'])) { + $fieldXml->addAttribute('column', $field['columnName']); + } + + if (isset($field['length'])) { + $fieldXml->addAttribute('length', $field['length']); + } + + if (isset($field['precision'])) { + $fieldXml->addAttribute('precision', $field['precision']); + } + + if (isset($field['scale'])) { + $fieldXml->addAttribute('scale', $field['scale']); + } + + if (isset($field['unique']) && $field['unique']) { + $fieldXml->addAttribute('unique', $field['unique'] ? 'true' : 'false'); + } + + if (isset($field['options'])) { + $optionsXml = $fieldXml->addChild('options'); + foreach ($field['options'] as $key => $value) { + $optionXml = $optionsXml->addChild('option', $value); + $optionXml->addAttribute('name', $key); + } + } + + if (isset($field['version'])) { + $fieldXml->addAttribute('version', $field['version']); + } + + if (isset($field['columnDefinition'])) { + $fieldXml->addAttribute('column-definition', $field['columnDefinition']); + } + + if (isset($field['nullable'])) { + $fieldXml->addAttribute('nullable', $field['nullable'] ? 'true' : 'false'); + } + } + } + + $orderMap = [ + ClassMetadataInfo::ONE_TO_ONE, + ClassMetadataInfo::ONE_TO_MANY, + ClassMetadataInfo::MANY_TO_ONE, + ClassMetadataInfo::MANY_TO_MANY, + ]; + + uasort($metadata->associationMappings, function($m1, $m2) use (&$orderMap){ + $a1 = array_search($m1['type'], $orderMap); + $a2 = array_search($m2['type'], $orderMap); + + return strcmp($a1, $a2); + }); + + foreach ($metadata->associationMappings as $associationMapping) { + $associationMappingXml = null; + if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_ONE) { + $associationMappingXml = $root->addChild('one-to-one'); + } elseif ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_ONE) { + $associationMappingXml = $root->addChild('many-to-one'); + } elseif ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) { + $associationMappingXml = $root->addChild('one-to-many'); + } elseif ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_MANY) { + $associationMappingXml = $root->addChild('many-to-many'); + } + + $associationMappingXml->addAttribute('field', $associationMapping['fieldName']); + $associationMappingXml->addAttribute('target-entity', $associationMapping['targetEntity']); + + if (isset($associationMapping['mappedBy'])) { + $associationMappingXml->addAttribute('mapped-by', $associationMapping['mappedBy']); + } + + if (isset($associationMapping['inversedBy'])) { + $associationMappingXml->addAttribute('inversed-by', $associationMapping['inversedBy']); + } + + if (isset($associationMapping['indexBy'])) { + $associationMappingXml->addAttribute('index-by', $associationMapping['indexBy']); + } + + if (isset($associationMapping['orphanRemoval']) && $associationMapping['orphanRemoval'] !== false) { + $associationMappingXml->addAttribute('orphan-removal', 'true'); + } + + if (isset($associationMapping['fetch'])) { + $associationMappingXml->addAttribute('fetch', $this->_getFetchModeString($associationMapping['fetch'])); + } + + $cascade = []; + if ($associationMapping['isCascadeRemove']) { + $cascade[] = 'cascade-remove'; + } + + if ($associationMapping['isCascadePersist']) { + $cascade[] = 'cascade-persist'; + } + + if ($associationMapping['isCascadeRefresh']) { + $cascade[] = 'cascade-refresh'; + } + + if ($associationMapping['isCascadeMerge']) { + $cascade[] = 'cascade-merge'; + } + + if ($associationMapping['isCascadeDetach']) { + $cascade[] = 'cascade-detach'; + } + + if (count($cascade) === 5) { + $cascade = ['cascade-all']; + } + + if ($cascade) { + $cascadeXml = $associationMappingXml->addChild('cascade'); + + foreach ($cascade as $type) { + $cascadeXml->addChild($type); + } + } + + if (isset($associationMapping['joinTable']) && $associationMapping['joinTable']) { + $joinTableXml = $associationMappingXml->addChild('join-table'); + $joinTableXml->addAttribute('name', $associationMapping['joinTable']['name']); + $joinColumnsXml = $joinTableXml->addChild('join-columns'); + + foreach ($associationMapping['joinTable']['joinColumns'] as $joinColumn) { + $joinColumnXml = $joinColumnsXml->addChild('join-column'); + $joinColumnXml->addAttribute('name', $joinColumn['name']); + $joinColumnXml->addAttribute('referenced-column-name', $joinColumn['referencedColumnName']); + + if (isset($joinColumn['onDelete'])) { + $joinColumnXml->addAttribute('on-delete', $joinColumn['onDelete']); + } + } + + $inverseJoinColumnsXml = $joinTableXml->addChild('inverse-join-columns'); + + foreach ($associationMapping['joinTable']['inverseJoinColumns'] as $inverseJoinColumn) { + $inverseJoinColumnXml = $inverseJoinColumnsXml->addChild('join-column'); + $inverseJoinColumnXml->addAttribute('name', $inverseJoinColumn['name']); + $inverseJoinColumnXml->addAttribute('referenced-column-name', $inverseJoinColumn['referencedColumnName']); + + if (isset($inverseJoinColumn['onDelete'])) { + $inverseJoinColumnXml->addAttribute('on-delete', $inverseJoinColumn['onDelete']); + } + + if (isset($inverseJoinColumn['columnDefinition'])) { + $inverseJoinColumnXml->addAttribute('column-definition', $inverseJoinColumn['columnDefinition']); + } + + if (isset($inverseJoinColumn['nullable'])) { + $inverseJoinColumnXml->addAttribute('nullable', $inverseJoinColumn['nullable']); + } + + if (isset($inverseJoinColumn['orderBy'])) { + $inverseJoinColumnXml->addAttribute('order-by', $inverseJoinColumn['orderBy']); + } + } + } + if (isset($associationMapping['joinColumns'])) { + $joinColumnsXml = $associationMappingXml->addChild('join-columns'); + + foreach ($associationMapping['joinColumns'] as $joinColumn) { + $joinColumnXml = $joinColumnsXml->addChild('join-column'); + $joinColumnXml->addAttribute('name', $joinColumn['name']); + $joinColumnXml->addAttribute('referenced-column-name', $joinColumn['referencedColumnName']); + + if (isset($joinColumn['onDelete'])) { + $joinColumnXml->addAttribute('on-delete', $joinColumn['onDelete']); + } + + if (isset($joinColumn['columnDefinition'])) { + $joinColumnXml->addAttribute('column-definition', $joinColumn['columnDefinition']); + } + + if (isset($joinColumn['nullable'])) { + $joinColumnXml->addAttribute('nullable', $joinColumn['nullable']); + } + } + } + if (isset($associationMapping['orderBy'])) { + $orderByXml = $associationMappingXml->addChild('order-by'); + + foreach ($associationMapping['orderBy'] as $name => $direction) { + $orderByFieldXml = $orderByXml->addChild('order-by-field'); + $orderByFieldXml->addAttribute('name', $name); + $orderByFieldXml->addAttribute('direction', $direction); + } + } + } + + if (isset($metadata->lifecycleCallbacks) && count($metadata->lifecycleCallbacks)>0) { + $lifecycleCallbacksXml = $root->addChild('lifecycle-callbacks'); + + foreach ($metadata->lifecycleCallbacks as $name => $methods) { + foreach ($methods as $method) { + $lifecycleCallbackXml = $lifecycleCallbacksXml->addChild('lifecycle-callback'); + $lifecycleCallbackXml->addAttribute('type', $name); + $lifecycleCallbackXml->addAttribute('method', $method); + } + } + } + + $this->processEntityListeners($metadata, $root); + + return $this->_asXml($xml); + } + + /** + * Exports (nested) option elements. + * + * @param SimpleXMLElement $parentXml + * @param array $options + */ + private function exportTableOptions(SimpleXMLElement $parentXml, array $options) : void + { + foreach ($options as $name => $option) { + $isArray = is_array($option); + $optionXml = $isArray + ? $parentXml->addChild('option') + : $parentXml->addChild('option', (string) $option); + + $optionXml->addAttribute('name', (string) $name); + + if ($isArray) { + $this->exportTableOptions($optionXml, $option); + } + } + } + + /** + * Export sequence information (if available/configured) into the current identifier XML node + * + * @param SimpleXMLElement $identifierXmlNode + * @param ClassMetadataInfo $metadata + * + * @return void + */ + private function exportSequenceInformation(SimpleXMLElement $identifierXmlNode, ClassMetadataInfo $metadata) : void + { + $sequenceDefinition = $metadata->sequenceGeneratorDefinition; + + if (! ($metadata->generatorType === ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE && $sequenceDefinition)) { + return; + } + + $sequenceGeneratorXml = $identifierXmlNode->addChild('sequence-generator'); + + $sequenceGeneratorXml->addAttribute('sequence-name', $sequenceDefinition['sequenceName']); + $sequenceGeneratorXml->addAttribute('allocation-size', $sequenceDefinition['allocationSize']); + $sequenceGeneratorXml->addAttribute('initial-value', $sequenceDefinition['initialValue']); + } + + private function _asXml(SimpleXMLElement $simpleXml) : string + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->loadXML($simpleXml->asXML()); + $dom->formatOutput = true; + + return $dom->saveXML(); + } + + private function processEntityListeners(ClassMetadataInfo $metadata, SimpleXMLElement $root): void + { + if (0 === \count($metadata->entityListeners)) { + return; + } + + $entityListenersXml = $root->addChild('entity-listeners'); + $entityListenersXmlMap = []; + + $this->generateEntityListenerXml($metadata, $entityListenersXmlMap, $entityListenersXml); + } + + private function generateEntityListenerXml(ClassMetadataInfo $metadata, array $entityListenersXmlMap, SimpleXMLElement $entityListenersXml): void + { + foreach ($metadata->entityListeners as $event => $entityListenerConfig) { + foreach ($entityListenerConfig as $entityListener) { + $entityListenerXml = $this->addClassToMapIfExists( + $entityListenersXmlMap, + $entityListener, + $entityListenersXml + ); + + $entityListenerCallbackXml = $entityListenerXml->addChild('lifecycle-callback'); + $entityListenerCallbackXml->addAttribute('type', $event); + $entityListenerCallbackXml->addAttribute('method', $entityListener['method']); + } + } + } + + private function addClassToMapIfExists(array $entityListenersXmlMap, array $entityListener, SimpleXMLElement $entityListenersXml): SimpleXMLElement + { + if (isset($entityListenersXmlMap[$entityListener['class']])) { + return $entityListenersXmlMap[$entityListener['class']]; + } + + $entityListenerXml = $entityListenersXml->addChild('entity-listener'); + $entityListenerXml->addAttribute('class', $entityListener['class']); + $entityListenersXmlMap[$entityListener['class']] = $entityListenerXml; + + return $entityListenerXml; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php new file mode 100644 index 0000000..1fb960b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php @@ -0,0 +1,268 @@ +. + */ + +namespace Doctrine\ORM\Tools\Export\Driver; + +use Symfony\Component\Yaml\Yaml; +use Doctrine\ORM\Mapping\ClassMetadataInfo; + +/** + * ClassMetadata exporter for Doctrine YAML mapping files. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Jonathan Wage + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class YamlExporter extends AbstractExporter +{ + /** + * @var string + */ + protected $_extension = '.dcm.yml'; + + /** + * {@inheritdoc} + */ + public function exportClassMetadata(ClassMetadataInfo $metadata) + { + $array = []; + + if ($metadata->isMappedSuperclass) { + $array['type'] = 'mappedSuperclass'; + } else { + $array['type'] = 'entity'; + } + $metadataTable = $metadata->table ?? ['name' => null]; + + $array['table'] = $metadataTable['name']; + + if (isset($metadataTable['schema'])) { + $array['schema'] = $metadataTable['schema']; + } + + $inheritanceType = $metadata->inheritanceType; + + if ($inheritanceType !== ClassMetadataInfo::INHERITANCE_TYPE_NONE) { + $array['inheritanceType'] = $this->_getInheritanceTypeString($inheritanceType); + } + + if ($column = $metadata->discriminatorColumn) { + $array['discriminatorColumn'] = $column; + } + + if ($map = $metadata->discriminatorMap) { + $array['discriminatorMap'] = $map; + } + + if ($metadata->changeTrackingPolicy !== ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT) { + $array['changeTrackingPolicy'] = $this->_getChangeTrackingPolicyString($metadata->changeTrackingPolicy); + } + + if (isset($metadataTable['indexes'])) { + $array['indexes'] = $metadataTable['indexes']; + } + + if ($metadata->customRepositoryClassName) { + $array['repositoryClass'] = $metadata->customRepositoryClassName; + } + + if (isset($metadataTable['uniqueConstraints'])) { + $array['uniqueConstraints'] = $metadataTable['uniqueConstraints']; + } + + if (isset($metadataTable['options'])) { + $array['options'] = $metadataTable['options']; + } + + $fieldMappings = $metadata->fieldMappings; + + $ids = []; + foreach ($fieldMappings as $name => $fieldMapping) { + $fieldMapping['column'] = $fieldMapping['columnName']; + + unset($fieldMapping['columnName'], $fieldMapping['fieldName']); + + if ($fieldMapping['column'] == $name) { + unset($fieldMapping['column']); + } + + if (isset($fieldMapping['id']) && $fieldMapping['id']) { + $ids[$name] = $fieldMapping; + unset($fieldMappings[$name]); + continue; + } + + $fieldMappings[$name] = $fieldMapping; + } + + if ( ! $metadata->isIdentifierComposite && $idGeneratorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) { + $ids[$metadata->getSingleIdentifierFieldName()]['generator']['strategy'] = $idGeneratorType; + } + + $array['id'] = $ids; + + if ($fieldMappings) { + if ( ! isset($array['fields'])) { + $array['fields'] = []; + } + $array['fields'] = array_merge($array['fields'], $fieldMappings); + } + + foreach ($metadata->associationMappings as $name => $associationMapping) { + $cascade = []; + + if ($associationMapping['isCascadeRemove']) { + $cascade[] = 'remove'; + } + + if ($associationMapping['isCascadePersist']) { + $cascade[] = 'persist'; + } + + if ($associationMapping['isCascadeRefresh']) { + $cascade[] = 'refresh'; + } + + if ($associationMapping['isCascadeMerge']) { + $cascade[] = 'merge'; + } + + if ($associationMapping['isCascadeDetach']) { + $cascade[] = 'detach'; + } + if (count($cascade) === 5) { + $cascade = ['all']; + } + + $associationMappingArray = [ + 'targetEntity' => $associationMapping['targetEntity'], + 'cascade' => $cascade, + ]; + + if (isset($associationMapping['fetch'])) { + $associationMappingArray['fetch'] = $this->_getFetchModeString($associationMapping['fetch']); + } + + if (isset($associationMapping['id']) && $associationMapping['id'] === true) { + $array['id'][$name]['associationKey'] = true; + } + + if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) { + $joinColumns = $associationMapping['isOwningSide'] ? $associationMapping['joinColumns'] : []; + $newJoinColumns = []; + + foreach ($joinColumns as $joinColumn) { + $newJoinColumns[$joinColumn['name']]['referencedColumnName'] = $joinColumn['referencedColumnName']; + + if (isset($joinColumn['onDelete'])) { + $newJoinColumns[$joinColumn['name']]['onDelete'] = $joinColumn['onDelete']; + } + } + + $oneToOneMappingArray = [ + 'mappedBy' => $associationMapping['mappedBy'], + 'inversedBy' => $associationMapping['inversedBy'], + 'joinColumns' => $newJoinColumns, + 'orphanRemoval' => $associationMapping['orphanRemoval'], + ]; + + $associationMappingArray = array_merge($associationMappingArray, $oneToOneMappingArray); + + if ($associationMapping['type'] & ClassMetadataInfo::ONE_TO_ONE) { + $array['oneToOne'][$name] = $associationMappingArray; + } else { + $array['manyToOne'][$name] = $associationMappingArray; + } + } elseif ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) { + $oneToManyMappingArray = [ + 'mappedBy' => $associationMapping['mappedBy'], + 'inversedBy' => $associationMapping['inversedBy'], + 'orphanRemoval' => $associationMapping['orphanRemoval'], + 'orderBy' => $associationMapping['orderBy'] ?? null + ]; + + $associationMappingArray = array_merge($associationMappingArray, $oneToManyMappingArray); + $array['oneToMany'][$name] = $associationMappingArray; + } elseif ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_MANY) { + $manyToManyMappingArray = [ + 'mappedBy' => $associationMapping['mappedBy'], + 'inversedBy' => $associationMapping['inversedBy'], + 'joinTable' => $associationMapping['joinTable'] ?? null, + 'orderBy' => $associationMapping['orderBy'] ?? null + ]; + + $associationMappingArray = array_merge($associationMappingArray, $manyToManyMappingArray); + $array['manyToMany'][$name] = $associationMappingArray; + } + } + if (isset($metadata->lifecycleCallbacks)) { + $array['lifecycleCallbacks'] = $metadata->lifecycleCallbacks; + } + + $array = $this->processEntityListeners($metadata, $array); + + return $this->yamlDump([$metadata->name => $array], 10); + } + + /** + * Dumps a PHP array to a YAML string. + * + * The yamlDump 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 [optional] The level where you switch to inline YAML + * + * @return string A YAML string representing the original PHP array + */ + protected function yamlDump($array, $inline = 2) + { + return Yaml::dump($array, $inline); + } + + private function processEntityListeners(ClassMetadataInfo $metadata, array $array) : array + { + if (0 === \count($metadata->entityListeners)) { + return $array; + } + + $array['entityListeners'] = []; + + foreach ($metadata->entityListeners as $event => $entityListenerConfig) { + $array = $this->processEntityListenerConfig($array, $entityListenerConfig, $event); + } + + return $array; + } + + private function processEntityListenerConfig(array $array, array $entityListenerConfig, string $event) : array + { + foreach ($entityListenerConfig as $entityListener) { + if (! isset($array['entityListeners'][$entityListener['class']])) { + $array['entityListeners'][$entityListener['class']] = []; + } + + $array['entityListeners'][$entityListener['class']][$event] = [$entityListener['method']]; + } + + return $array; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ExportException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ExportException.php new file mode 100644 index 0000000..725ea21 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ExportException.php @@ -0,0 +1,58 @@ +. + */ + +namespace Doctrine\ORM\Tools\Export; + +use Doctrine\ORM\ORMException; + +/** + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class ExportException extends ORMException +{ + /** + * @param string $type + * + * @return ExportException + */ + public static function invalidExporterDriverType($type) + { + return new self("The specified export driver '$type' does not exist"); + } + + /** + * @param string $type + * + * @return ExportException + */ + public static function invalidMappingDriverType($type) + { + return new self("The mapping driver '$type' does not exist"); + } + + /** + * @param string $file + * + * @return ExportException + */ + public static function attemptOverwriteExistingFile($file) + { + return new self("Attempting to overwrite an existing file '".$file."'."); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php new file mode 100644 index 0000000..f3db053 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php @@ -0,0 +1,154 @@ +. + */ + +namespace Doctrine\ORM\Tools\Pagination; + +use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\AST\SelectStatement; + +/** + * Wraps the query in order to accurately count the root objects. + * + * Given a DQL like `SELECT u FROM User u` it will generate an SQL query like: + * SELECT COUNT(*) (SELECT DISTINCT FROM ()) + * + * Works with composite keys but cannot deal with queries that have multiple + * root entities (e.g. `SELECT f, b from Foo, Bar`) + * + * @author Sander Marechal + */ +class CountOutputWalker extends SqlWalker +{ + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $platform; + + /** + * @var \Doctrine\ORM\Query\ResultSetMapping + */ + private $rsm; + + /** + * @var array + */ + private $queryComponents; + + /** + * Constructor. + * + * Stores various parameters that are otherwise unavailable + * because Doctrine\ORM\Query\SqlWalker keeps everything private without + * accessors. + * + * @param \Doctrine\ORM\Query $query + * @param \Doctrine\ORM\Query\ParserResult $parserResult + * @param array $queryComponents + */ + public function __construct($query, $parserResult, array $queryComponents) + { + $this->platform = $query->getEntityManager()->getConnection()->getDatabasePlatform(); + $this->rsm = $parserResult->getResultSetMapping(); + $this->queryComponents = $queryComponents; + + parent::__construct($query, $parserResult, $queryComponents); + } + + /** + * Walks down a SelectStatement AST node, wrapping it in a COUNT (SELECT DISTINCT). + * + * Note that the ORDER BY clause is not removed. Many SQL implementations (e.g. MySQL) + * are able to cache subqueries. By keeping the ORDER BY clause intact, the limitSubQuery + * that will most likely be executed next can be read from the native SQL cache. + * + * @param SelectStatement $AST + * + * @return string + * + * @throws \RuntimeException + */ + public function walkSelectStatement(SelectStatement $AST) + { + if ($this->platform->getName() === "mssql") { + $AST->orderByClause = null; + } + + $sql = parent::walkSelectStatement($AST); + + if ($AST->groupByClause) { + return sprintf( + 'SELECT %s AS dctrn_count FROM (%s) dctrn_table', + $this->platform->getCountExpression('*'), + $sql + ); + } + + // Find out the SQL alias of the identifier column of the root entity + // It may be possible to make this work with multiple root entities but that + // would probably require issuing multiple queries or doing a UNION SELECT + // so for now, It's not supported. + + // Get the root entity and alias from the AST fromClause + $from = $AST->fromClause->identificationVariableDeclarations; + if (count($from) > 1) { + throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); + } + + $fromRoot = reset($from); + $rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable; + $rootClass = $this->queryComponents[$rootAlias]['metadata']; + $rootIdentifier = $rootClass->identifier; + + // For every identifier, find out the SQL alias by combing through the ResultSetMapping + $sqlIdentifier = []; + foreach ($rootIdentifier as $property) { + if (isset($rootClass->fieldMappings[$property])) { + foreach (array_keys($this->rsm->fieldMappings, $property) as $alias) { + if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { + $sqlIdentifier[$property] = $alias; + } + } + } + + if (isset($rootClass->associationMappings[$property])) { + $joinColumn = $rootClass->associationMappings[$property]['joinColumns'][0]['name']; + + foreach (array_keys($this->rsm->metaMappings, $joinColumn) as $alias) { + if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { + $sqlIdentifier[$property] = $alias; + } + } + } + } + + if (count($rootIdentifier) != count($sqlIdentifier)) { + throw new \RuntimeException(sprintf( + 'Not all identifier properties can be found in the ResultSetMapping: %s', + implode(', ', array_diff($rootIdentifier, array_keys($sqlIdentifier))) + )); + } + + // Build the counter query + return sprintf('SELECT %s AS dctrn_count FROM (SELECT DISTINCT %s FROM (%s) dctrn_result) dctrn_table', + $this->platform->getCountExpression('*'), + implode(', ', $sqlIdentifier), + $sql + ); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountWalker.php new file mode 100644 index 0000000..a8f2600 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountWalker.php @@ -0,0 +1,94 @@ +. + */ + +namespace Doctrine\ORM\Tools\Pagination; + +use Doctrine\ORM\Query\TreeWalkerAdapter; +use Doctrine\ORM\Query\AST\SelectStatement; +use Doctrine\ORM\Query\AST\SelectExpression; +use Doctrine\ORM\Query\AST\PathExpression; +use Doctrine\ORM\Query\AST\AggregateExpression; + +/** + * Replaces the selectClause of the AST with a COUNT statement. + * + * @category DoctrineExtensions + * @package DoctrineExtensions\Paginate + * @author David Abdemoulaie + * @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/) + * @license http://hobodave.com/license.txt New BSD License + */ +class CountWalker extends TreeWalkerAdapter +{ + /** + * Distinct mode hint name. + */ + const HINT_DISTINCT = 'doctrine_paginator.distinct'; + + /** + * Walks down a SelectStatement AST node, modifying it to retrieve a COUNT. + * + * @param SelectStatement $AST + * + * @return void + * + * @throws \RuntimeException + */ + public function walkSelectStatement(SelectStatement $AST) + { + if ($AST->havingClause) { + throw new \RuntimeException('Cannot count query that uses a HAVING clause. Use the output walkers for pagination'); + } + + $queryComponents = $this->_getQueryComponents(); + // Get the root entity and alias from the AST fromClause + $from = $AST->fromClause->identificationVariableDeclarations; + + if (count($from) > 1) { + throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); + } + + $fromRoot = reset($from); + $rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable; + $rootClass = $queryComponents[$rootAlias]['metadata']; + $identifierFieldName = $rootClass->getSingleIdentifierFieldName(); + + $pathType = PathExpression::TYPE_STATE_FIELD; + if (isset($rootClass->associationMappings[$identifierFieldName])) { + $pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION; + } + + $pathExpression = new PathExpression( + PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $rootAlias, + $identifierFieldName + ); + $pathExpression->type = $pathType; + + $distinct = $this->_getQuery()->getHint(self::HINT_DISTINCT); + $AST->selectClause->selectExpressions = [ + new SelectExpression( + new AggregateExpression('count', $pathExpression, $distinct), null + ) + ]; + + // ORDER BY is not needed, only increases query execution through unnecessary sorting. + $AST->orderByClause = null; + } +} + diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php new file mode 100644 index 0000000..034b33b --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php @@ -0,0 +1,605 @@ +. + */ + +namespace Doctrine\ORM\Tools\Pagination; + +use Doctrine\DBAL\Platforms\DB2Platform; +use Doctrine\DBAL\Platforms\OraclePlatform; +use Doctrine\DBAL\Platforms\PostgreSqlPlatform; +use Doctrine\DBAL\Platforms\SQLAnywherePlatform; +use Doctrine\DBAL\Platforms\SQLServerPlatform; +use Doctrine\ORM\Query\AST\OrderByClause; +use Doctrine\ORM\Query\AST\PartialObjectExpression; +use Doctrine\ORM\Query\AST\SelectExpression; +use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\AST\SelectStatement; + +/** + * Wraps the query in order to select root entity IDs for pagination. + * + * Given a DQL like `SELECT u FROM User u` it will generate an SQL query like: + * SELECT DISTINCT FROM () LIMIT x OFFSET y + * + * Works with composite keys but cannot deal with queries that have multiple + * root entities (e.g. `SELECT f, b from Foo, Bar`) + * + * @author Sander Marechal + */ +class LimitSubqueryOutputWalker extends SqlWalker +{ + private const ORDER_BY_PATH_EXPRESSION = '/(?platform = $query->getEntityManager()->getConnection()->getDatabasePlatform(); + $this->rsm = $parserResult->getResultSetMapping(); + $this->queryComponents = $queryComponents; + + // Reset limit and offset + $this->firstResult = $query->getFirstResult(); + $this->maxResults = $query->getMaxResults(); + $query->setFirstResult(null)->setMaxResults(null); + + $this->em = $query->getEntityManager(); + $this->quoteStrategy = $this->em->getConfiguration()->getQuoteStrategy(); + + parent::__construct($query, $parserResult, $queryComponents); + } + + /** + * Check if the platform supports the ROW_NUMBER window function. + * + * @return bool + */ + private function platformSupportsRowNumber() + { + return $this->platform instanceof PostgreSqlPlatform + || $this->platform instanceof SQLServerPlatform + || $this->platform instanceof OraclePlatform + || $this->platform instanceof SQLAnywherePlatform + || $this->platform instanceof DB2Platform + || (method_exists($this->platform, 'supportsRowNumberFunction') + && $this->platform->supportsRowNumberFunction()); + } + + /** + * Rebuilds a select statement's order by clause for use in a + * ROW_NUMBER() OVER() expression. + * + * @param SelectStatement $AST + */ + private function rebuildOrderByForRowNumber(SelectStatement $AST) + { + $orderByClause = $AST->orderByClause; + $selectAliasToExpressionMap = []; + // Get any aliases that are available for select expressions. + foreach ($AST->selectClause->selectExpressions as $selectExpression) { + $selectAliasToExpressionMap[$selectExpression->fieldIdentificationVariable] = $selectExpression->expression; + } + + // Rebuild string orderby expressions to use the select expression they're referencing + foreach ($orderByClause->orderByItems as $orderByItem) { + if (is_string($orderByItem->expression) && isset($selectAliasToExpressionMap[$orderByItem->expression])) { + $orderByItem->expression = $selectAliasToExpressionMap[$orderByItem->expression]; + } + } + $func = new RowNumberOverFunction('dctrn_rownum'); + $func->orderByClause = $AST->orderByClause; + $AST->selectClause->selectExpressions[] = new SelectExpression($func, 'dctrn_rownum', true); + + // No need for an order by clause, we'll order by rownum in the outer query. + $AST->orderByClause = null; + } + + /** + * Walks down a SelectStatement AST node, wrapping it in a SELECT DISTINCT. + * + * @param SelectStatement $AST + * + * @return string + * + * @throws \RuntimeException + */ + public function walkSelectStatement(SelectStatement $AST) + { + if ($this->platformSupportsRowNumber()) { + return $this->walkSelectStatementWithRowNumber($AST); + } + return $this->walkSelectStatementWithoutRowNumber($AST); + } + + /** + * Walks down a SelectStatement AST node, wrapping it in a SELECT DISTINCT. + * This method is for use with platforms which support ROW_NUMBER. + * + * @param SelectStatement $AST + * + * @return string + * + * @throws \RuntimeException + */ + public function walkSelectStatementWithRowNumber(SelectStatement $AST) + { + $hasOrderBy = false; + $outerOrderBy = ' ORDER BY dctrn_minrownum ASC'; + $orderGroupBy = ''; + if ($AST->orderByClause instanceof OrderByClause) { + $hasOrderBy = true; + $this->rebuildOrderByForRowNumber($AST); + } + + $innerSql = $this->getInnerSQL($AST); + + $sqlIdentifier = $this->getSQLIdentifier($AST); + + if ($hasOrderBy) { + $orderGroupBy = ' GROUP BY ' . implode(', ', $sqlIdentifier); + $sqlIdentifier[] = 'MIN(' . $this->walkResultVariable('dctrn_rownum') . ') AS dctrn_minrownum'; + } + + // Build the counter query + $sql = sprintf( + 'SELECT DISTINCT %s FROM (%s) dctrn_result', + implode(', ', $sqlIdentifier), + $innerSql + ); + + if ($hasOrderBy) { + $sql .= $orderGroupBy . $outerOrderBy; + } + + // Apply the limit and offset. + $sql = $this->platform->modifyLimitQuery( + $sql, + $this->maxResults, + $this->firstResult + ); + + // Add the columns to the ResultSetMapping. It's not really nice but + // it works. Preferably I'd clear the RSM or simply create a new one + // but that is not possible from inside the output walker, so we dirty + // up the one we have. + foreach ($sqlIdentifier as $property => $alias) { + $this->rsm->addScalarResult($alias, $property); + } + + return $sql; + } + + /** + * Walks down a SelectStatement AST node, wrapping it in a SELECT DISTINCT. + * This method is for platforms which DO NOT support ROW_NUMBER. + * + * @param SelectStatement $AST + * @param bool $addMissingItemsFromOrderByToSelect + * + * @return string + * + * @throws \RuntimeException + */ + public function walkSelectStatementWithoutRowNumber(SelectStatement $AST, $addMissingItemsFromOrderByToSelect = true) + { + // We don't want to call this recursively! + if ($AST->orderByClause instanceof OrderByClause && $addMissingItemsFromOrderByToSelect) { + // In the case of ordering a query by columns from joined tables, we + // must add those columns to the select clause of the query BEFORE + // the SQL is generated. + $this->addMissingItemsFromOrderByToSelect($AST); + } + + // Remove order by clause from the inner query + // It will be re-appended in the outer select generated by this method + $orderByClause = $AST->orderByClause; + $AST->orderByClause = null; + + $innerSql = $this->getInnerSQL($AST); + + $sqlIdentifier = $this->getSQLIdentifier($AST); + + // Build the counter query + $sql = sprintf('SELECT DISTINCT %s FROM (%s) dctrn_result', + implode(', ', $sqlIdentifier), $innerSql); + + // http://www.doctrine-project.org/jira/browse/DDC-1958 + $sql = $this->preserveSqlOrdering($sqlIdentifier, $innerSql, $sql, $orderByClause); + + // Apply the limit and offset. + $sql = $this->platform->modifyLimitQuery( + $sql, $this->maxResults, $this->firstResult + ); + + // Add the columns to the ResultSetMapping. It's not really nice but + // it works. Preferably I'd clear the RSM or simply create a new one + // but that is not possible from inside the output walker, so we dirty + // up the one we have. + foreach ($sqlIdentifier as $property => $alias) { + $this->rsm->addScalarResult($alias, $property); + } + + // Restore orderByClause + $AST->orderByClause = $orderByClause; + + return $sql; + } + + /** + * Finds all PathExpressions in an AST's OrderByClause, and ensures that + * the referenced fields are present in the SelectClause of the passed AST. + * + * @param SelectStatement $AST + */ + private function addMissingItemsFromOrderByToSelect(SelectStatement $AST) + { + $this->orderByPathExpressions = []; + + // We need to do this in another walker because otherwise we'll end up + // polluting the state of this one. + $walker = clone $this; + + // This will populate $orderByPathExpressions via + // LimitSubqueryOutputWalker::walkPathExpression, which will be called + // as the select statement is walked. We'll end up with an array of all + // path expressions referenced in the query. + $walker->walkSelectStatementWithoutRowNumber($AST, false); + $orderByPathExpressions = $walker->getOrderByPathExpressions(); + + // Get a map of referenced identifiers to field names. + $selects = []; + foreach ($orderByPathExpressions as $pathExpression) { + $idVar = $pathExpression->identificationVariable; + $field = $pathExpression->field; + if (!isset($selects[$idVar])) { + $selects[$idVar] = []; + } + $selects[$idVar][$field] = true; + } + + // Loop the select clause of the AST and exclude items from $select + // that are already being selected in the query. + foreach ($AST->selectClause->selectExpressions as $selectExpression) { + if ($selectExpression instanceof SelectExpression) { + $idVar = $selectExpression->expression; + if (!is_string($idVar)) { + continue; + } + $field = $selectExpression->fieldIdentificationVariable; + if ($field === null) { + // No need to add this select, as we're already fetching the whole object. + unset($selects[$idVar]); + } else { + unset($selects[$idVar][$field]); + } + } + } + + // Add select items which were not excluded to the AST's select clause. + foreach ($selects as $idVar => $fields) { + $AST->selectClause->selectExpressions[] = new SelectExpression(new PartialObjectExpression($idVar, array_keys($fields)), null, true); + } + } + + /** + * Generates new SQL for statements with an order by clause + * + * @param array $sqlIdentifier + * @param string $innerSql + * @param string $sql + * @param OrderByClause|null $orderByClause + * + * @return string + */ + private function preserveSqlOrdering( + array $sqlIdentifier, + string $innerSql, + string $sql, + ?OrderByClause $orderByClause + ) : string { + // If the sql statement has an order by clause, we need to wrap it in a new select distinct statement + if (! $orderByClause) { + return $sql; + } + + // now only select distinct identifier + return \sprintf( + 'SELECT DISTINCT %s FROM (%s) dctrn_result', + \implode(', ', $sqlIdentifier), + $this->recreateInnerSql($orderByClause, $sqlIdentifier, $innerSql) + ); + } + + /** + * Generates a new SQL statement for the inner query to keep the correct sorting + * + * @param OrderByClause $orderByClause + * @param array $identifiers + * @param string $innerSql + * + * @return string + */ + private function recreateInnerSql( + OrderByClause $orderByClause, + array $identifiers, + string $innerSql + ) : string { + [$searchPatterns, $replacements] = $this->generateSqlAliasReplacements(); + + $orderByItems = []; + + foreach ($orderByClause->orderByItems as $orderByItem) { + // Walk order by item to get string representation of it and + // replace path expressions in the order by clause with their column alias + $orderByItemString = \preg_replace( + $searchPatterns, + $replacements, + $this->walkOrderByItem($orderByItem) + ); + + $orderByItems[] = $orderByItemString; + $identifier = \substr($orderByItemString, 0, \strrpos($orderByItemString, ' ')); + + if (! \in_array($identifier, $identifiers, true)) { + $identifiers[] = $identifier; + } + } + + return $sql = \sprintf( + 'SELECT DISTINCT %s FROM (%s) dctrn_result_inner ORDER BY %s', + \implode(', ', $identifiers), + $innerSql, + \implode(', ', $orderByItems) + ); + } + + /** + * @return string[][] + */ + private function generateSqlAliasReplacements() : array + { + $aliasMap = $searchPatterns = $replacements = $metadataList = []; + + // Generate DQL alias -> SQL table alias mapping + foreach (\array_keys($this->rsm->aliasMap) as $dqlAlias) { + $metadataList[$dqlAlias] = $class = $this->queryComponents[$dqlAlias]['metadata']; + $aliasMap[$dqlAlias] = $this->getSQLTableAlias($class->getTableName(), $dqlAlias); + } + + // Generate search patterns for each field's path expression in the order by clause + foreach ($this->rsm->fieldMappings as $fieldAlias => $fieldName) { + $dqlAliasForFieldAlias = $this->rsm->columnOwnerMap[$fieldAlias]; + $class = $metadataList[$dqlAliasForFieldAlias]; + + // If the field is from a joined child table, we won't be ordering on it. + if (! isset($class->fieldMappings[$fieldName])) { + continue; + } + + $fieldMapping = $class->fieldMappings[$fieldName]; + + // Get the proper column name as will appear in the select list + $columnName = $this->quoteStrategy->getColumnName( + $fieldName, + $metadataList[$dqlAliasForFieldAlias], + $this->em->getConnection()->getDatabasePlatform() + ); + + // Get the SQL table alias for the entity and field + $sqlTableAliasForFieldAlias = $aliasMap[$dqlAliasForFieldAlias]; + + if (isset($fieldMapping['declared']) && $fieldMapping['declared'] !== $class->name) { + // Field was declared in a parent class, so we need to get the proper SQL table alias + // for the joined parent table. + $otherClassMetadata = $this->em->getClassMetadata($fieldMapping['declared']); + + if (! $otherClassMetadata->isMappedSuperclass) { + $sqlTableAliasForFieldAlias = $this->getSQLTableAlias($otherClassMetadata->getTableName(), $dqlAliasForFieldAlias); + } + } + + // Compose search and replace patterns + $searchPatterns[] = \sprintf(self::ORDER_BY_PATH_EXPRESSION, $sqlTableAliasForFieldAlias, $columnName); + $replacements[] = $fieldAlias; + } + + return [$searchPatterns, $replacements]; + } + + /** + * getter for $orderByPathExpressions + * + * @return array + */ + public function getOrderByPathExpressions() + { + return $this->orderByPathExpressions; + } + + /** + * @param SelectStatement $AST + * + * @return string + * + * @throws \Doctrine\ORM\OptimisticLockException + * @throws \Doctrine\ORM\Query\QueryException + */ + private function getInnerSQL(SelectStatement $AST) + { + // Set every select expression as visible(hidden = false) to + // make $AST have scalar mappings properly - this is relevant for referencing selected + // fields from outside the subquery, for example in the ORDER BY segment + $hiddens = []; + + foreach ($AST->selectClause->selectExpressions as $idx => $expr) { + $hiddens[$idx] = $expr->hiddenAliasResultVariable; + $expr->hiddenAliasResultVariable = false; + } + + $innerSql = parent::walkSelectStatement($AST); + + // Restore hiddens + foreach ($AST->selectClause->selectExpressions as $idx => $expr) { + $expr->hiddenAliasResultVariable = $hiddens[$idx]; + } + + return $innerSql; + } + + /** + * @param SelectStatement $AST + * + * @return array + */ + private function getSQLIdentifier(SelectStatement $AST) + { + // Find out the SQL alias of the identifier column of the root entity. + // It may be possible to make this work with multiple root entities but that + // would probably require issuing multiple queries or doing a UNION SELECT. + // So for now, it's not supported. + + // Get the root entity and alias from the AST fromClause. + $from = $AST->fromClause->identificationVariableDeclarations; + if (count($from) !== 1) { + throw new \RuntimeException('Cannot count query which selects two FROM components, cannot make distinction'); + } + + $fromRoot = reset($from); + $rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable; + $rootClass = $this->queryComponents[$rootAlias]['metadata']; + $rootIdentifier = $rootClass->identifier; + + // For every identifier, find out the SQL alias by combing through the ResultSetMapping + $sqlIdentifier = []; + foreach ($rootIdentifier as $property) { + if (isset($rootClass->fieldMappings[$property])) { + foreach (array_keys($this->rsm->fieldMappings, $property) as $alias) { + if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { + $sqlIdentifier[$property] = $alias; + } + } + } + + if (isset($rootClass->associationMappings[$property])) { + $joinColumn = $rootClass->associationMappings[$property]['joinColumns'][0]['name']; + + foreach (array_keys($this->rsm->metaMappings, $joinColumn) as $alias) { + if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { + $sqlIdentifier[$property] = $alias; + } + } + } + } + + if (count($sqlIdentifier) === 0) { + throw new \RuntimeException('The Paginator does not support Queries which only yield ScalarResults.'); + } + + if (count($rootIdentifier) != count($sqlIdentifier)) { + throw new \RuntimeException(sprintf( + 'Not all identifier properties can be found in the ResultSetMapping: %s', + implode(', ', array_diff($rootIdentifier, array_keys($sqlIdentifier))) + )); + } + + return $sqlIdentifier; + } + + /** + * {@inheritdoc} + */ + public function walkPathExpression($pathExpr) + { + if (!$this->inSubSelect && !$this->platformSupportsRowNumber() && !in_array($pathExpr, $this->orderByPathExpressions)) { + $this->orderByPathExpressions[] = $pathExpr; + } + + return parent::walkPathExpression($pathExpr); + } + + /** + * {@inheritdoc} + */ + public function walkSubSelect($subselect) + { + $this->inSubSelect = true; + + $sql = parent::walkSubselect($subselect); + + $this->inSubSelect = false; + + return $sql; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php new file mode 100644 index 0000000..5614138 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php @@ -0,0 +1,177 @@ +. + */ + +namespace Doctrine\ORM\Tools\Pagination; + +use Doctrine\DBAL\Types\Type; +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Doctrine\ORM\Query; +use Doctrine\ORM\Query\TreeWalkerAdapter; +use Doctrine\ORM\Query\AST\Functions\IdentityFunction; +use Doctrine\ORM\Query\AST\PathExpression; +use Doctrine\ORM\Query\AST\SelectExpression; +use Doctrine\ORM\Query\AST\SelectStatement; + +/** + * Replaces the selectClause of the AST with a SELECT DISTINCT root.id equivalent. + * + * @category DoctrineExtensions + * @package DoctrineExtensions\Paginate + * @author David Abdemoulaie + * @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/) + * @license http://hobodave.com/license.txt New BSD License + */ +class LimitSubqueryWalker extends TreeWalkerAdapter +{ + public const IDENTIFIER_TYPE = 'doctrine_paginator.id.type'; + + public const FORCE_DBAL_TYPE_CONVERSION = 'doctrine_paginator.scalar_result.force_dbal_type_conversion'; + + /** + * Counter for generating unique order column aliases. + * + * @var int + */ + private $_aliasCounter = 0; + + /** + * Walks down a SelectStatement AST node, modifying it to retrieve DISTINCT ids + * of the root Entity. + * + * @param SelectStatement $AST + * + * @return void + * + * @throws \RuntimeException + */ + public function walkSelectStatement(SelectStatement $AST) + { + $queryComponents = $this->_getQueryComponents(); + // Get the root entity and alias from the AST fromClause + $from = $AST->fromClause->identificationVariableDeclarations; + $fromRoot = reset($from); + $rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable; + $rootClass = $queryComponents[$rootAlias]['metadata']; + + $this->validate($AST); + $identifier = $rootClass->getSingleIdentifierFieldName(); + + if (isset($rootClass->associationMappings[$identifier])) { + throw new \RuntimeException("Paginating an entity with foreign key as identifier only works when using the Output Walkers. Call Paginator#setUseOutputWalkers(true) before iterating the paginator."); + } + + $this->_getQuery()->setHint( + self::IDENTIFIER_TYPE, + Type::getType($rootClass->fieldMappings[$identifier]['type']) + ); + + $this->_getQuery()->setHint(self::FORCE_DBAL_TYPE_CONVERSION, true); + + $pathExpression = new PathExpression( + PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, + $rootAlias, + $identifier + ); + + $pathExpression->type = PathExpression::TYPE_STATE_FIELD; + + $AST->selectClause->selectExpressions = [new SelectExpression($pathExpression, '_dctrn_id')]; + $AST->selectClause->isDistinct = true; + + if ( ! isset($AST->orderByClause)) { + return; + } + + foreach ($AST->orderByClause->orderByItems as $item) { + if ($item->expression instanceof PathExpression) { + $AST->selectClause->selectExpressions[] = new SelectExpression( + $this->createSelectExpressionItem($item->expression), '_dctrn_ord' . $this->_aliasCounter++ + ); + + continue; + } + + if (is_string($item->expression) && isset($queryComponents[$item->expression])) { + $qComp = $queryComponents[$item->expression]; + + if (isset($qComp['resultVariable'])) { + $AST->selectClause->selectExpressions[] = new SelectExpression( + $qComp['resultVariable'], + $item->expression + ); + } + } + } + } + + /** + * Validate the AST to ensure that this walker is able to properly manipulate it. + * + * @param SelectStatement $AST + */ + private function validate(SelectStatement $AST) + { + // Prevent LimitSubqueryWalker from being used with queries that include + // a limit, a fetched to-many join, and an order by condition that + // references a column from the fetch joined table. + $queryComponents = $this->getQueryComponents(); + $query = $this->_getQuery(); + $from = $AST->fromClause->identificationVariableDeclarations; + $fromRoot = reset($from); + + if ($query instanceof Query + && null !== $query->getMaxResults() + && $AST->orderByClause + && count($fromRoot->joins)) { + // Check each orderby item. + // TODO: check complex orderby items too... + foreach ($AST->orderByClause->orderByItems as $orderByItem) { + $expression = $orderByItem->expression; + if ($orderByItem->expression instanceof PathExpression + && isset($queryComponents[$expression->identificationVariable])) { + $queryComponent = $queryComponents[$expression->identificationVariable]; + if (isset($queryComponent['parent']) + && $queryComponent['relation']['type'] & ClassMetadataInfo::TO_MANY) { + throw new \RuntimeException("Cannot select distinct identifiers from query with LIMIT and ORDER BY on a column from a fetch joined to-many association. Use output walkers."); + } + } + } + } + } + + /** + * Retrieve either an IdentityFunction (IDENTITY(u.assoc)) or a state field (u.name). + * + * @param \Doctrine\ORM\Query\AST\PathExpression $pathExpression + * + * @return \Doctrine\ORM\Query\AST\Functions\IdentityFunction + */ + private function createSelectExpressionItem(PathExpression $pathExpression) + { + if ($pathExpression->type === PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION) { + $identity = new IdentityFunction('identity'); + + $identity->pathExpression = clone $pathExpression; + + return $identity; + } + + return clone $pathExpression; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/Paginator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/Paginator.php new file mode 100644 index 0000000..64cd9e2 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/Paginator.php @@ -0,0 +1,289 @@ +. + */ + +namespace Doctrine\ORM\Tools\Pagination; + +use Doctrine\ORM\NoResultException; +use Doctrine\ORM\Query; +use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\ResultSetMapping; +use Doctrine\ORM\QueryBuilder; +use function array_map; + +/** + * The paginator can handle various complex scenarios with DQL. + * + * @author Pablo Díez + * @author Benjamin Eberlei + * @license New BSD + */ +class Paginator implements \Countable, \IteratorAggregate +{ + /** + * @var Query + */ + private $query; + + /** + * @var bool + */ + private $fetchJoinCollection; + + /** + * @var bool|null + */ + private $useOutputWalkers; + + /** + * @var int + */ + private $count; + + /** + * Constructor. + * + * @param Query|QueryBuilder $query A Doctrine ORM query or query builder. + * @param boolean $fetchJoinCollection Whether the query joins a collection (true by default). + */ + public function __construct($query, $fetchJoinCollection = true) + { + if ($query instanceof QueryBuilder) { + $query = $query->getQuery(); + } + + $this->query = $query; + $this->fetchJoinCollection = (bool) $fetchJoinCollection; + } + + /** + * Returns the query. + * + * @return Query + */ + public function getQuery() + { + return $this->query; + } + + /** + * Returns whether the query joins a collection. + * + * @return boolean Whether the query joins a collection. + */ + public function getFetchJoinCollection() + { + return $this->fetchJoinCollection; + } + + /** + * Returns whether the paginator will use an output walker. + * + * @return bool|null + */ + public function getUseOutputWalkers() + { + return $this->useOutputWalkers; + } + + /** + * Sets whether the paginator will use an output walker. + * + * @param bool|null $useOutputWalkers + * + * @return $this + */ + public function setUseOutputWalkers($useOutputWalkers) + { + $this->useOutputWalkers = $useOutputWalkers; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function count() + { + if ($this->count === null) { + try { + $this->count = array_sum(array_map('current', $this->getCountQuery()->getScalarResult())); + } catch (NoResultException $e) { + $this->count = 0; + } + } + + return $this->count; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + $offset = $this->query->getFirstResult(); + $length = $this->query->getMaxResults(); + + if ($this->fetchJoinCollection && $length !== null) { + $subQuery = $this->cloneQuery($this->query); + + if ($this->useOutputWalker($subQuery)) { + $subQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); + } else { + $this->appendTreeWalker($subQuery, LimitSubqueryWalker::class); + $this->unbindUnusedQueryParams($subQuery); + } + + $subQuery->setFirstResult($offset)->setMaxResults($length); + + $foundIdRows = $subQuery->getScalarResult(); + + // don't do this for an empty id array + if ($foundIdRows === []) { + return new \ArrayIterator([]); + } + + $whereInQuery = $this->cloneQuery($this->query); + $ids = array_map('current', $foundIdRows); + + $this->appendTreeWalker($whereInQuery, WhereInWalker::class); + $whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, count($ids)); + $whereInQuery->setFirstResult(null)->setMaxResults(null); + $whereInQuery->setParameter(WhereInWalker::PAGINATOR_ID_ALIAS, $ids); + $whereInQuery->setCacheable($this->query->isCacheable()); + $whereInQuery->expireQueryCache(); + + $result = $whereInQuery->getResult($this->query->getHydrationMode()); + } else { + $result = $this->cloneQuery($this->query) + ->setMaxResults($length) + ->setFirstResult($offset) + ->setCacheable($this->query->isCacheable()) + ->getResult($this->query->getHydrationMode()) + ; + } + + return new \ArrayIterator($result); + } + + /** + * Clones a query. + * + * @param Query $query The query. + * + * @return Query The cloned query. + */ + private function cloneQuery(Query $query) + { + /* @var $cloneQuery Query */ + $cloneQuery = clone $query; + + $cloneQuery->setParameters(clone $query->getParameters()); + $cloneQuery->setCacheable(false); + + foreach ($query->getHints() as $name => $value) { + $cloneQuery->setHint($name, $value); + } + + return $cloneQuery; + } + + /** + * Determines whether to use an output walker for the query. + * + * @param Query $query The query. + * + * @return bool + */ + private function useOutputWalker(Query $query) + { + if ($this->useOutputWalkers === null) { + return (bool) $query->getHint(Query::HINT_CUSTOM_OUTPUT_WALKER) === false; + } + + return $this->useOutputWalkers; + } + + /** + * Appends a custom tree walker to the tree walkers hint. + * + * @param Query $query + * @param string $walkerClass + */ + private function appendTreeWalker(Query $query, $walkerClass) + { + $hints = $query->getHint(Query::HINT_CUSTOM_TREE_WALKERS); + + if ($hints === false) { + $hints = []; + } + + $hints[] = $walkerClass; + $query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, $hints); + } + + /** + * Returns Query prepared to count. + * + * @return Query + */ + private function getCountQuery() + { + /* @var $countQuery Query */ + $countQuery = $this->cloneQuery($this->query); + + if ( ! $countQuery->hasHint(CountWalker::HINT_DISTINCT)) { + $countQuery->setHint(CountWalker::HINT_DISTINCT, true); + } + + if ($this->useOutputWalker($countQuery)) { + $platform = $countQuery->getEntityManager()->getConnection()->getDatabasePlatform(); // law of demeter win + + $rsm = new ResultSetMapping(); + $rsm->addScalarResult($platform->getSQLResultCasing('dctrn_count'), 'count'); + + $countQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, CountOutputWalker::class); + $countQuery->setResultSetMapping($rsm); + } else { + $this->appendTreeWalker($countQuery, CountWalker::class); + $this->unbindUnusedQueryParams($countQuery); + } + + $countQuery->setFirstResult(null)->setMaxResults(null); + + return $countQuery; + } + + private function unbindUnusedQueryParams(Query $query): void + { + $parser = new Parser($query); + $parameterMappings = $parser->parse()->getParameterMappings(); + /* @var $parameters \Doctrine\Common\Collections\Collection|\Doctrine\ORM\Query\Parameter[] */ + $parameters = $query->getParameters(); + + foreach ($parameters as $key => $parameter) { + $parameterName = $parameter->getName(); + + if ( ! (isset($parameterMappings[$parameterName]) || array_key_exists($parameterName, $parameterMappings))) { + unset($parameters[$key]); + } + } + + $query->setParameters($parameters); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/RowNumberOverFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/RowNumberOverFunction.php new file mode 100644 index 0000000..a9d3e5d --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/RowNumberOverFunction.php @@ -0,0 +1,62 @@ +. + */ + +namespace Doctrine\ORM\Tools\Pagination; + +use Doctrine\ORM\ORMException; +use Doctrine\ORM\Query\AST\Functions\FunctionNode; + +/** + * RowNumberOverFunction + * + * Provides ROW_NUMBER() OVER(ORDER BY...) construct for use in LimitSubqueryOutputWalker + * + * @since 2.5 + * @author Bill Schaller + */ +class RowNumberOverFunction extends FunctionNode +{ + /** + * @var \Doctrine\ORM\Query\AST\OrderByClause + */ + public $orderByClause; + + /** + * @override + * @inheritdoc + */ + public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) + { + return 'ROW_NUMBER() OVER(' . trim($sqlWalker->walkOrderByClause( + $this->orderByClause + )) . ')'; + } + + /** + * @override + * @inheritdoc + * + * @throws ORMException + */ + public function parse(\Doctrine\ORM\Query\Parser $parser) + { + throw new ORMException("The RowNumberOverFunction is not intended for, nor is it enabled for use in DQL."); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php new file mode 100644 index 0000000..de66f64 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php @@ -0,0 +1,184 @@ +. + */ + +namespace Doctrine\ORM\Tools\Pagination; + +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Query\AST\ArithmeticExpression; +use Doctrine\ORM\Query\AST\ConditionalExpression; +use Doctrine\ORM\Query\AST\ConditionalFactor; +use Doctrine\ORM\Query\AST\ConditionalPrimary; +use Doctrine\ORM\Query\AST\ConditionalTerm; +use Doctrine\ORM\Query\AST\InExpression; +use Doctrine\ORM\Query\AST\InputParameter; +use Doctrine\ORM\Query\AST\NullComparisonExpression; +use Doctrine\ORM\Query\AST\PathExpression; +use Doctrine\ORM\Query\AST\SelectStatement; +use Doctrine\ORM\Query\AST\SimpleArithmeticExpression; +use Doctrine\ORM\Query\AST\WhereClause; +use Doctrine\ORM\Query\TreeWalkerAdapter; +use Doctrine\ORM\Utility\PersisterHelper; +use function array_map; +use function assert; +use function is_array; + +/** + * Replaces the whereClause of the AST with a WHERE id IN (:foo_1, :foo_2) equivalent. + * + * @category DoctrineExtensions + * @package DoctrineExtensions\Paginate + * @author David Abdemoulaie + * @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/) + * @license http://hobodave.com/license.txt New BSD License + */ +class WhereInWalker extends TreeWalkerAdapter +{ + /** + * ID Count hint name. + */ + const HINT_PAGINATOR_ID_COUNT = 'doctrine.id.count'; + + /** + * Primary key alias for query. + */ + const PAGINATOR_ID_ALIAS = 'dpid'; + + /** + * Replaces the whereClause in the AST. + * + * Generates a clause equivalent to WHERE IN (:dpid_1, :dpid_2, ...) + * + * The parameter namespace (dpid) is defined by + * the PAGINATOR_ID_ALIAS + * + * The total number of parameters is retrieved from + * the HINT_PAGINATOR_ID_COUNT query hint. + * + * @param SelectStatement $AST + * + * @return void + * + * @throws \RuntimeException + */ + public function walkSelectStatement(SelectStatement $AST) + { + $queryComponents = $this->_getQueryComponents(); + // Get the root entity and alias from the AST fromClause + $from = $AST->fromClause->identificationVariableDeclarations; + + if (count($from) > 1) { + throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); + } + + $fromRoot = reset($from); + $rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable; + /** @var ClassMetadata $rootClass */ + $rootClass = $queryComponents[$rootAlias]['metadata']; + $identifierFieldName = $rootClass->getSingleIdentifierFieldName(); + + $pathType = PathExpression::TYPE_STATE_FIELD; + if (isset($rootClass->associationMappings[$identifierFieldName])) { + $pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION; + } + + $pathExpression = new PathExpression(PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $rootAlias, $identifierFieldName); + $pathExpression->type = $pathType; + + $count = $this->_getQuery()->getHint(self::HINT_PAGINATOR_ID_COUNT); + + if ($count > 0) { + $arithmeticExpression = new ArithmeticExpression(); + $arithmeticExpression->simpleArithmeticExpression = new SimpleArithmeticExpression( + [$pathExpression] + ); + $expression = new InExpression($arithmeticExpression); + $expression->literals[] = new InputParameter(":" . self::PAGINATOR_ID_ALIAS); + + $this->convertWhereInIdentifiersToDatabaseValue( + PersisterHelper::getTypeOfField( + $identifierFieldName, + $rootClass, + $this->_getQuery() + ->getEntityManager() + )[0] + ); + } else { + $expression = new NullComparisonExpression($pathExpression); + $expression->not = false; + } + + $conditionalPrimary = new ConditionalPrimary; + $conditionalPrimary->simpleConditionalExpression = $expression; + if ($AST->whereClause) { + if ($AST->whereClause->conditionalExpression instanceof ConditionalTerm) { + $AST->whereClause->conditionalExpression->conditionalFactors[] = $conditionalPrimary; + } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalPrimary) { + $AST->whereClause->conditionalExpression = new ConditionalExpression( + [ + new ConditionalTerm( + [ + $AST->whereClause->conditionalExpression, + $conditionalPrimary + ] + ) + ] + ); + } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalExpression + || $AST->whereClause->conditionalExpression instanceof ConditionalFactor + ) { + $tmpPrimary = new ConditionalPrimary; + $tmpPrimary->conditionalExpression = $AST->whereClause->conditionalExpression; + $AST->whereClause->conditionalExpression = new ConditionalTerm( + [ + $tmpPrimary, + $conditionalPrimary + ] + ); + } + } else { + $AST->whereClause = new WhereClause( + new ConditionalExpression( + [ + new ConditionalTerm([$conditionalPrimary]) + ] + ) + ); + } + } + + private function convertWhereInIdentifiersToDatabaseValue(string $type) : void + { + $query = $this->_getQuery(); + $identifiersParameter = $query->getParameter(self::PAGINATOR_ID_ALIAS); + + assert($identifiersParameter !== null); + + $identifiers = $identifiersParameter->getValue(); + + assert(is_array($identifiers)); + + $connection = $this->_getQuery() + ->getEntityManager() + ->getConnection(); + + $query->setParameter(self::PAGINATOR_ID_ALIAS, array_map(static function ($id) use ($connection, $type) { + return $connection->convertToDatabaseValue($id, $type); + }, $identifiers)); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ResolveTargetEntityListener.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ResolveTargetEntityListener.php new file mode 100644 index 0000000..36f1f92 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ResolveTargetEntityListener.php @@ -0,0 +1,144 @@ +. + */ + +namespace Doctrine\ORM\Tools; + +use Doctrine\ORM\Event\LoadClassMetadataEventArgs; +use Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\Common\EventSubscriber; +use Doctrine\ORM\Events; + +/** + * ResolveTargetEntityListener + * + * Mechanism to overwrite interfaces or classes specified as association + * targets. + * + * @author Benjamin Eberlei + * @since 2.2 + */ +class ResolveTargetEntityListener implements EventSubscriber +{ + /** + * @var array[] indexed by original entity name + */ + private $resolveTargetEntities = []; + + /** + * {@inheritDoc} + */ + public function getSubscribedEvents() + { + return [ + Events::loadClassMetadata, + Events::onClassMetadataNotFound + ]; + } + + /** + * Adds a target-entity class name to resolve to a new class name. + * + * @param string $originalEntity + * @param string $newEntity + * @param array $mapping + * + * @return void + */ + public function addResolveTargetEntity($originalEntity, $newEntity, array $mapping) + { + $mapping['targetEntity'] = ltrim($newEntity, "\\"); + $this->resolveTargetEntities[ltrim($originalEntity, "\\")] = $mapping; + } + + /** + * @param OnClassMetadataNotFoundEventArgs $args + * + * @internal this is an event callback, and should not be called directly + * + * @return void + */ + public function onClassMetadataNotFound(OnClassMetadataNotFoundEventArgs $args) + { + if (array_key_exists($args->getClassName(), $this->resolveTargetEntities)) { + $args->setFoundMetadata( + $args + ->getObjectManager() + ->getClassMetadata($this->resolveTargetEntities[$args->getClassName()]['targetEntity']) + ); + } + } + + /** + * Processes event and resolves new target entity names. + * + * @param LoadClassMetadataEventArgs $args + * + * @return void + * + * @internal this is an event callback, and should not be called directly + */ + public function loadClassMetadata(LoadClassMetadataEventArgs $args) + { + /* @var $cm \Doctrine\ORM\Mapping\ClassMetadata */ + $cm = $args->getClassMetadata(); + + foreach ($cm->associationMappings as $mapping) { + if (isset($this->resolveTargetEntities[$mapping['targetEntity']])) { + $this->remapAssociation($cm, $mapping); + } + } + + foreach ($this->resolveTargetEntities as $interface => $data) { + if ($data['targetEntity'] == $cm->getName()) { + $args->getEntityManager()->getMetadataFactory()->setMetadataFor($interface, $cm); + } + } + } + + /** + * @param \Doctrine\ORM\Mapping\ClassMetadataInfo $classMetadata + * @param array $mapping + * + * @return void + */ + private function remapAssociation($classMetadata, $mapping) + { + $newMapping = $this->resolveTargetEntities[$mapping['targetEntity']]; + $newMapping = array_replace_recursive($mapping, $newMapping); + $newMapping['fieldName'] = $mapping['fieldName']; + + unset($classMetadata->associationMappings[$mapping['fieldName']]); + + switch ($mapping['type']) { + case ClassMetadata::MANY_TO_MANY: + $classMetadata->mapManyToMany($newMapping); + break; + case ClassMetadata::MANY_TO_ONE: + $classMetadata->mapManyToOne($newMapping); + break; + case ClassMetadata::ONE_TO_MANY: + $classMetadata->mapOneToMany($newMapping); + break; + case ClassMetadata::ONE_TO_ONE: + $classMetadata->mapOneToOne($newMapping); + break; + } + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaTool.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaTool.php new file mode 100644 index 0000000..ba63e69 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaTool.php @@ -0,0 +1,913 @@ +. + */ + +namespace Doctrine\ORM\Tools; + +use Doctrine\ORM\ORMException; +use Doctrine\DBAL\Schema\Comparator; +use Doctrine\DBAL\Schema\Index; +use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Schema\Table; +use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector; +use Doctrine\DBAL\Schema\Visitor\RemoveNamespacedAssets; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Tools\Event\GenerateSchemaTableEventArgs; +use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs; + +/** + * The SchemaTool is a tool to create/drop/update database schemas based on + * ClassMetadata class descriptors. + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Benjamin Eberlei + * @author Stefano Rodriguez + */ +class SchemaTool +{ + private const KNOWN_COLUMN_OPTIONS = ['comment', 'unsigned', 'fixed', 'default']; + + /** + * @var \Doctrine\ORM\EntityManagerInterface + */ + private $em; + + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $platform; + + /** + * The quote strategy. + * + * @var \Doctrine\ORM\Mapping\QuoteStrategy + */ + private $quoteStrategy; + + /** + * Initializes a new SchemaTool instance that uses the connection of the + * provided EntityManager. + * + * @param \Doctrine\ORM\EntityManagerInterface $em + */ + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + $this->platform = $em->getConnection()->getDatabasePlatform(); + $this->quoteStrategy = $em->getConfiguration()->getQuoteStrategy(); + } + + /** + * Creates the database schema for the given array of ClassMetadata instances. + * + * @param array $classes + * + * @return void + * + * @throws ToolsException + */ + public function createSchema(array $classes) + { + $createSchemaSql = $this->getCreateSchemaSql($classes); + $conn = $this->em->getConnection(); + + foreach ($createSchemaSql as $sql) { + try { + $conn->executeQuery($sql); + } catch (\Throwable $e) { + throw ToolsException::schemaToolFailure($sql, $e); + } + } + } + + /** + * Gets the list of DDL statements that are required to create the database schema for + * the given list of ClassMetadata instances. + * + * @param array $classes + * + * @return array The SQL statements needed to create the schema for the classes. + */ + public function getCreateSchemaSql(array $classes) + { + $schema = $this->getSchemaFromMetadata($classes); + + return $schema->toSql($this->platform); + } + + /** + * Detects instances of ClassMetadata that don't need to be processed in the SchemaTool context. + * + * @param ClassMetadata $class + * @param array $processedClasses + * + * @return bool + */ + private function processingNotRequired($class, array $processedClasses) + { + return ( + isset($processedClasses[$class->name]) || + $class->isMappedSuperclass || + $class->isEmbeddedClass || + ($class->isInheritanceTypeSingleTable() && $class->name != $class->rootEntityName) + ); + } + + /** + * Creates a Schema instance from a given set of metadata classes. + * + * @param array $classes + * + * @return Schema + * + * @throws \Doctrine\ORM\ORMException + */ + public function getSchemaFromMetadata(array $classes) + { + // Reminder for processed classes, used for hierarchies + $processedClasses = []; + $eventManager = $this->em->getEventManager(); + $schemaManager = $this->em->getConnection()->getSchemaManager(); + $metadataSchemaConfig = $schemaManager->createSchemaConfig(); + + $metadataSchemaConfig->setExplicitForeignKeyIndexes(false); + $schema = new Schema([], [], $metadataSchemaConfig); + + $addedFks = []; + $blacklistedFks = []; + + foreach ($classes as $class) { + /** @var \Doctrine\ORM\Mapping\ClassMetadata $class */ + if ($this->processingNotRequired($class, $processedClasses)) { + continue; + } + + $table = $schema->createTable($this->quoteStrategy->getTableName($class, $this->platform)); + + if ($class->isInheritanceTypeSingleTable()) { + $this->gatherColumns($class, $table); + $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks); + + // Add the discriminator column + $this->addDiscriminatorColumnDefinition($class, $table); + + // Aggregate all the information from all classes in the hierarchy + foreach ($class->parentClasses as $parentClassName) { + // Parent class information is already contained in this class + $processedClasses[$parentClassName] = true; + } + + foreach ($class->subClasses as $subClassName) { + $subClass = $this->em->getClassMetadata($subClassName); + $this->gatherColumns($subClass, $table); + $this->gatherRelationsSql($subClass, $table, $schema, $addedFks, $blacklistedFks); + $processedClasses[$subClassName] = true; + } + } elseif ($class->isInheritanceTypeJoined()) { + // Add all non-inherited fields as columns + foreach ($class->fieldMappings as $fieldName => $mapping) { + if ( ! isset($mapping['inherited'])) { + $this->gatherColumn($class, $mapping, $table); + } + } + + $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks); + + // Add the discriminator column only to the root table + if ($class->name == $class->rootEntityName) { + $this->addDiscriminatorColumnDefinition($class, $table); + } else { + // Add an ID FK column to child tables + $pkColumns = []; + $inheritedKeyColumns = []; + + foreach ($class->identifier as $identifierField) { + if (isset($class->fieldMappings[$identifierField]['inherited'])) { + $idMapping = $class->fieldMappings[$identifierField]; + $this->gatherColumn($class, $idMapping, $table); + $columnName = $this->quoteStrategy->getColumnName( + $identifierField, + $class, + $this->platform + ); + // TODO: This seems rather hackish, can we optimize it? + $table->getColumn($columnName)->setAutoincrement(false); + + $pkColumns[] = $columnName; + $inheritedKeyColumns[] = $columnName; + + continue; + } + + if (isset($class->associationMappings[$identifierField]['inherited'])) { + $idMapping = $class->associationMappings[$identifierField]; + + $targetEntity = current( + array_filter( + $classes, + function (ClassMetadata $class) use ($idMapping) : bool { + return $class->name === $idMapping['targetEntity']; + } + ) + ); + + foreach ($idMapping['joinColumns'] as $joinColumn) { + if (isset($targetEntity->fieldMappings[$joinColumn['referencedColumnName']])) { + $columnName = $this->quoteStrategy->getJoinColumnName( + $joinColumn, + $class, + $this->platform + ); + + $pkColumns[] = $columnName; + $inheritedKeyColumns[] = $columnName; + } + } + } + } + + if ( ! empty($inheritedKeyColumns)) { + // Add a FK constraint on the ID column + $table->addForeignKeyConstraint( + $this->quoteStrategy->getTableName( + $this->em->getClassMetadata($class->rootEntityName), + $this->platform + ), + $inheritedKeyColumns, + $inheritedKeyColumns, + ['onDelete' => 'CASCADE'] + ); + } + + if ( ! empty($pkColumns)) { + $table->setPrimaryKey($pkColumns); + } + } + } elseif ($class->isInheritanceTypeTablePerClass()) { + throw ORMException::notSupported(); + } else { + $this->gatherColumns($class, $table); + $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks); + } + + $pkColumns = []; + + foreach ($class->identifier as $identifierField) { + if (isset($class->fieldMappings[$identifierField])) { + $pkColumns[] = $this->quoteStrategy->getColumnName($identifierField, $class, $this->platform); + } elseif (isset($class->associationMappings[$identifierField])) { + /* @var $assoc \Doctrine\ORM\Mapping\OneToOne */ + $assoc = $class->associationMappings[$identifierField]; + + foreach ($assoc['joinColumns'] as $joinColumn) { + $pkColumns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); + } + } + } + + if ( ! $table->hasIndex('primary')) { + $table->setPrimaryKey($pkColumns); + } + + // there can be unique indexes automatically created for join column + // if join column is also primary key we should keep only primary key on this column + // so, remove indexes overruled by primary key + $primaryKey = $table->getIndex('primary'); + + foreach ($table->getIndexes() as $idxKey => $existingIndex) { + if ($primaryKey->overrules($existingIndex)) { + $table->dropIndex($idxKey); + } + } + + if (isset($class->table['indexes'])) { + foreach ($class->table['indexes'] as $indexName => $indexData) { + if ( ! isset($indexData['flags'])) { + $indexData['flags'] = []; + } + + $table->addIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName, (array) $indexData['flags'], $indexData['options'] ?? []); + } + } + + if (isset($class->table['uniqueConstraints'])) { + foreach ($class->table['uniqueConstraints'] as $indexName => $indexData) { + $uniqIndex = new Index($indexName, $indexData['columns'], true, false, [], $indexData['options'] ?? []); + + foreach ($table->getIndexes() as $tableIndexName => $tableIndex) { + if ($tableIndex->isFullfilledBy($uniqIndex)) { + $table->dropIndex($tableIndexName); + break; + } + } + + $table->addUniqueIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName, $indexData['options'] ?? []); + } + } + + if (isset($class->table['options'])) { + foreach ($class->table['options'] as $key => $val) { + $table->addOption($key, $val); + } + } + + $processedClasses[$class->name] = true; + + if ($class->isIdGeneratorSequence() && $class->name == $class->rootEntityName) { + $seqDef = $class->sequenceGeneratorDefinition; + $quotedName = $this->quoteStrategy->getSequenceName($seqDef, $class, $this->platform); + if ( ! $schema->hasSequence($quotedName)) { + $schema->createSequence( + $quotedName, + $seqDef['allocationSize'], + $seqDef['initialValue'] + ); + } + } + + if ($eventManager->hasListeners(ToolEvents::postGenerateSchemaTable)) { + $eventManager->dispatchEvent( + ToolEvents::postGenerateSchemaTable, + new GenerateSchemaTableEventArgs($class, $schema, $table) + ); + } + } + + if ( ! $this->platform->supportsSchemas() && ! $this->platform->canEmulateSchemas()) { + $schema->visit(new RemoveNamespacedAssets()); + } + + if ($eventManager->hasListeners(ToolEvents::postGenerateSchema)) { + $eventManager->dispatchEvent( + ToolEvents::postGenerateSchema, + new GenerateSchemaEventArgs($this->em, $schema) + ); + } + + return $schema; + } + + /** + * Gets a portable column definition as required by the DBAL for the discriminator + * column of a class. + * + * @param ClassMetadata $class + * @param Table $table + * + * @return void + */ + private function addDiscriminatorColumnDefinition($class, Table $table) + { + $discrColumn = $class->discriminatorColumn; + + if ( ! isset($discrColumn['type']) || + (strtolower($discrColumn['type']) == 'string' && ! isset($discrColumn['length'])) + ) { + $discrColumn['type'] = 'string'; + $discrColumn['length'] = 255; + } + + $options = [ + 'length' => $discrColumn['length'] ?? null, + 'notnull' => true + ]; + + if (isset($discrColumn['columnDefinition'])) { + $options['columnDefinition'] = $discrColumn['columnDefinition']; + } + + $table->addColumn($discrColumn['name'], $discrColumn['type'], $options); + } + + /** + * Gathers the column definitions as required by the DBAL of all field mappings + * found in the given class. + * + * @param ClassMetadata $class + * @param Table $table + * + * @return void + */ + private function gatherColumns($class, Table $table) + { + $pkColumns = []; + + foreach ($class->fieldMappings as $mapping) { + if ($class->isInheritanceTypeSingleTable() && isset($mapping['inherited'])) { + continue; + } + + $this->gatherColumn($class, $mapping, $table); + + if ($class->isIdentifier($mapping['fieldName'])) { + $pkColumns[] = $this->quoteStrategy->getColumnName($mapping['fieldName'], $class, $this->platform); + } + } + } + + /** + * Creates a column definition as required by the DBAL from an ORM field mapping definition. + * + * @param ClassMetadata $class The class that owns the field mapping. + * @param array $mapping The field mapping. + * @param Table $table + * + * @return void + */ + private function gatherColumn($class, array $mapping, Table $table) + { + $columnName = $this->quoteStrategy->getColumnName($mapping['fieldName'], $class, $this->platform); + $columnType = $mapping['type']; + + $options = []; + $options['length'] = $mapping['length'] ?? null; + $options['notnull'] = isset($mapping['nullable']) ? ! $mapping['nullable'] : true; + if ($class->isInheritanceTypeSingleTable() && $class->parentClasses) { + $options['notnull'] = false; + } + + $options['platformOptions'] = []; + $options['platformOptions']['version'] = $class->isVersioned && $class->versionField === $mapping['fieldName']; + + if (strtolower($columnType) === 'string' && null === $options['length']) { + $options['length'] = 255; + } + + if (isset($mapping['precision'])) { + $options['precision'] = $mapping['precision']; + } + + if (isset($mapping['scale'])) { + $options['scale'] = $mapping['scale']; + } + + if (isset($mapping['default'])) { + $options['default'] = $mapping['default']; + } + + if (isset($mapping['columnDefinition'])) { + $options['columnDefinition'] = $mapping['columnDefinition']; + } + + // the 'default' option can be overwritten here + $options = $this->gatherColumnOptions($mapping) + $options; + + if ($class->isIdGeneratorIdentity() && $class->getIdentifierFieldNames() == [$mapping['fieldName']]) { + $options['autoincrement'] = true; + } + if ($class->isInheritanceTypeJoined() && $class->name !== $class->rootEntityName) { + $options['autoincrement'] = false; + } + + if ($table->hasColumn($columnName)) { + // required in some inheritance scenarios + $table->changeColumn($columnName, $options); + } else { + $table->addColumn($columnName, $columnType, $options); + } + + $isUnique = $mapping['unique'] ?? false; + if ($isUnique) { + $table->addUniqueIndex([$columnName]); + } + } + + /** + * Gathers the SQL for properly setting up the relations of the given class. + * This includes the SQL for foreign key constraints and join tables. + * + * @param ClassMetadata $class + * @param Table $table + * @param Schema $schema + * @param array $addedFks + * @param array $blacklistedFks + * + * @return void + * + * @throws \Doctrine\ORM\ORMException + */ + private function gatherRelationsSql($class, $table, $schema, &$addedFks, &$blacklistedFks) + { + foreach ($class->associationMappings as $id => $mapping) { + if (isset($mapping['inherited']) && ! \in_array($id, $class->identifier, true)) { + continue; + } + + $foreignClass = $this->em->getClassMetadata($mapping['targetEntity']); + + if ($mapping['type'] & ClassMetadata::TO_ONE && $mapping['isOwningSide']) { + $primaryKeyColumns = []; // PK is unnecessary for this relation-type + + $this->gatherRelationJoinColumns( + $mapping['joinColumns'], + $table, + $foreignClass, + $mapping, + $primaryKeyColumns, + $addedFks, + $blacklistedFks + ); + } elseif ($mapping['type'] == ClassMetadata::ONE_TO_MANY && $mapping['isOwningSide']) { + //... create join table, one-many through join table supported later + throw ORMException::notSupported(); + } elseif ($mapping['type'] == ClassMetadata::MANY_TO_MANY && $mapping['isOwningSide']) { + // create join table + $joinTable = $mapping['joinTable']; + + $theJoinTable = $schema->createTable( + $this->quoteStrategy->getJoinTableName($mapping, $foreignClass, $this->platform) + ); + + $primaryKeyColumns = []; + + // Build first FK constraint (relation table => source table) + $this->gatherRelationJoinColumns( + $joinTable['joinColumns'], + $theJoinTable, + $class, + $mapping, + $primaryKeyColumns, + $addedFks, + $blacklistedFks + ); + + // Build second FK constraint (relation table => target table) + $this->gatherRelationJoinColumns( + $joinTable['inverseJoinColumns'], + $theJoinTable, + $foreignClass, + $mapping, + $primaryKeyColumns, + $addedFks, + $blacklistedFks + ); + + $theJoinTable->setPrimaryKey($primaryKeyColumns); + } + } + } + + /** + * Gets the class metadata that is responsible for the definition of the referenced column name. + * + * Previously this was a simple task, but with DDC-117 this problem is actually recursive. If its + * not a simple field, go through all identifier field names that are associations recursively and + * find that referenced column name. + * + * TODO: Is there any way to make this code more pleasing? + * + * @param ClassMetadata $class + * @param string $referencedColumnName + * + * @return array (ClassMetadata, referencedFieldName) + */ + private function getDefiningClass($class, $referencedColumnName) + { + $referencedFieldName = $class->getFieldName($referencedColumnName); + + if ($class->hasField($referencedFieldName)) { + return [$class, $referencedFieldName]; + } + + if (in_array($referencedColumnName, $class->getIdentifierColumnNames())) { + // it seems to be an entity as foreign key + foreach ($class->getIdentifierFieldNames() as $fieldName) { + if ($class->hasAssociation($fieldName) + && $class->getSingleAssociationJoinColumnName($fieldName) == $referencedColumnName) { + return $this->getDefiningClass( + $this->em->getClassMetadata($class->associationMappings[$fieldName]['targetEntity']), + $class->getSingleAssociationReferencedJoinColumnName($fieldName) + ); + } + } + } + + return null; + } + + /** + * Gathers columns and fk constraints that are required for one part of relationship. + * + * @param array $joinColumns + * @param Table $theJoinTable + * @param ClassMetadata $class + * @param array $mapping + * @param array $primaryKeyColumns + * @param array $addedFks + * @param array $blacklistedFks + * + * @return void + * + * @throws \Doctrine\ORM\ORMException + */ + private function gatherRelationJoinColumns( + $joinColumns, + $theJoinTable, + $class, + $mapping, + &$primaryKeyColumns, + &$addedFks, + &$blacklistedFks + ) + { + $localColumns = []; + $foreignColumns = []; + $fkOptions = []; + $foreignTableName = $this->quoteStrategy->getTableName($class, $this->platform); + $uniqueConstraints = []; + + foreach ($joinColumns as $joinColumn) { + + list($definingClass, $referencedFieldName) = $this->getDefiningClass( + $class, + $joinColumn['referencedColumnName'] + ); + + if ( ! $definingClass) { + throw new \Doctrine\ORM\ORMException( + 'Column name `' . $joinColumn['referencedColumnName'] . '` referenced for relation from ' + . $mapping['sourceEntity'] . ' towards ' . $mapping['targetEntity'] . ' does not exist.' + ); + } + + $quotedColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); + $quotedRefColumnName = $this->quoteStrategy->getReferencedJoinColumnName( + $joinColumn, + $class, + $this->platform + ); + + $primaryKeyColumns[] = $quotedColumnName; + $localColumns[] = $quotedColumnName; + $foreignColumns[] = $quotedRefColumnName; + + if ( ! $theJoinTable->hasColumn($quotedColumnName)) { + // Only add the column to the table if it does not exist already. + // It might exist already if the foreign key is mapped into a regular + // property as well. + + $fieldMapping = $definingClass->getFieldMapping($referencedFieldName); + + $columnDef = null; + if (isset($joinColumn['columnDefinition'])) { + $columnDef = $joinColumn['columnDefinition']; + } elseif (isset($fieldMapping['columnDefinition'])) { + $columnDef = $fieldMapping['columnDefinition']; + } + + $columnOptions = ['notnull' => false, 'columnDefinition' => $columnDef]; + + if (isset($joinColumn['nullable'])) { + $columnOptions['notnull'] = ! $joinColumn['nullable']; + } + + $columnOptions = $columnOptions + $this->gatherColumnOptions($fieldMapping); + + if ($fieldMapping['type'] == "string" && isset($fieldMapping['length'])) { + $columnOptions['length'] = $fieldMapping['length']; + } elseif ($fieldMapping['type'] == "decimal") { + $columnOptions['scale'] = $fieldMapping['scale']; + $columnOptions['precision'] = $fieldMapping['precision']; + } + + $theJoinTable->addColumn($quotedColumnName, $fieldMapping['type'], $columnOptions); + } + + if (isset($joinColumn['unique']) && $joinColumn['unique'] == true) { + $uniqueConstraints[] = ['columns' => [$quotedColumnName]]; + } + + if (isset($joinColumn['onDelete'])) { + $fkOptions['onDelete'] = $joinColumn['onDelete']; + } + } + + // Prefer unique constraints over implicit simple indexes created for foreign keys. + // Also avoids index duplication. + foreach ($uniqueConstraints as $indexName => $unique) { + $theJoinTable->addUniqueIndex($unique['columns'], is_numeric($indexName) ? null : $indexName); + } + + $compositeName = $theJoinTable->getName().'.'.implode('', $localColumns); + + if (! $this->platform->supportsForeignKeyConstraints()) { + return; + } + + if (isset($addedFks[$compositeName]) + && ($foreignTableName != $addedFks[$compositeName]['foreignTableName'] + || 0 < count(array_diff($foreignColumns, $addedFks[$compositeName]['foreignColumns']))) + ) { + foreach ($theJoinTable->getForeignKeys() as $fkName => $key) { + if (0 === count(array_diff($key->getLocalColumns(), $localColumns)) + && (($key->getForeignTableName() != $foreignTableName) + || 0 < count(array_diff($key->getForeignColumns(), $foreignColumns))) + ) { + $theJoinTable->removeForeignKey($fkName); + break; + } + } + $blacklistedFks[$compositeName] = true; + } elseif ( ! isset($blacklistedFks[$compositeName])) { + $addedFks[$compositeName] = ['foreignTableName' => $foreignTableName, 'foreignColumns' => $foreignColumns]; + $theJoinTable->addUnnamedForeignKeyConstraint( + $foreignTableName, + $localColumns, + $foreignColumns, + $fkOptions + ); + } + } + + /** + * @param mixed[] $mapping + * + * @return mixed[] + */ + private function gatherColumnOptions(array $mapping) : array + { + if (! isset($mapping['options'])) { + return []; + } + + $options = array_intersect_key($mapping['options'], array_flip(self::KNOWN_COLUMN_OPTIONS)); + $options['customSchemaOptions'] = array_diff_key($mapping['options'], $options); + + return $options; + } + + /** + * Drops the database schema for the given classes. + * + * In any way when an exception is thrown it is suppressed since drop was + * issued for all classes of the schema and some probably just don't exist. + * + * @param array $classes + * + * @return void + */ + public function dropSchema(array $classes) + { + $dropSchemaSql = $this->getDropSchemaSQL($classes); + $conn = $this->em->getConnection(); + + foreach ($dropSchemaSql as $sql) { + try { + $conn->executeQuery($sql); + } catch (\Throwable $e) { + // ignored + } + } + } + + /** + * Drops all elements in the database of the current connection. + * + * @return void + */ + public function dropDatabase() + { + $dropSchemaSql = $this->getDropDatabaseSQL(); + $conn = $this->em->getConnection(); + + foreach ($dropSchemaSql as $sql) { + $conn->executeQuery($sql); + } + } + + /** + * Gets the SQL needed to drop the database schema for the connections database. + * + * @return array + */ + public function getDropDatabaseSQL() + { + $sm = $this->em->getConnection()->getSchemaManager(); + $schema = $sm->createSchema(); + + $visitor = new DropSchemaSqlCollector($this->platform); + $schema->visit($visitor); + + return $visitor->getQueries(); + } + + /** + * Gets SQL to drop the tables defined by the passed classes. + * + * @param array $classes + * + * @return array + */ + public function getDropSchemaSQL(array $classes) + { + $visitor = new DropSchemaSqlCollector($this->platform); + $schema = $this->getSchemaFromMetadata($classes); + + $sm = $this->em->getConnection()->getSchemaManager(); + $fullSchema = $sm->createSchema(); + + foreach ($fullSchema->getTables() as $table) { + if ( ! $schema->hasTable($table->getName())) { + foreach ($table->getForeignKeys() as $foreignKey) { + /* @var $foreignKey \Doctrine\DBAL\Schema\ForeignKeyConstraint */ + if ($schema->hasTable($foreignKey->getForeignTableName())) { + $visitor->acceptForeignKey($table, $foreignKey); + } + } + } else { + $visitor->acceptTable($table); + foreach ($table->getForeignKeys() as $foreignKey) { + $visitor->acceptForeignKey($table, $foreignKey); + } + } + } + + if ($this->platform->supportsSequences()) { + foreach ($schema->getSequences() as $sequence) { + $visitor->acceptSequence($sequence); + } + + foreach ($schema->getTables() as $table) { + /* @var $sequence Table */ + if ($table->hasPrimaryKey()) { + $columns = $table->getPrimaryKey()->getColumns(); + if (count($columns) == 1) { + $checkSequence = $table->getName() . '_' . $columns[0] . '_seq'; + if ($fullSchema->hasSequence($checkSequence)) { + $visitor->acceptSequence($fullSchema->getSequence($checkSequence)); + } + } + } + } + } + + return $visitor->getQueries(); + } + + /** + * Updates the database schema of the given classes by comparing the ClassMetadata + * instances to the current database schema that is inspected. + * + * @param array $classes + * @param boolean $saveMode If TRUE, only performs a partial update + * without dropping assets which are scheduled for deletion. + * + * @return void + */ + public function updateSchema(array $classes, $saveMode = false) + { + $updateSchemaSql = $this->getUpdateSchemaSql($classes, $saveMode); + $conn = $this->em->getConnection(); + + foreach ($updateSchemaSql as $sql) { + $conn->executeQuery($sql); + } + } + + /** + * Gets the sequence of SQL statements that need to be performed in order + * to bring the given class mappings in-synch with the relational schema. + * + * @param array $classes The classes to consider. + * @param boolean $saveMode If TRUE, only generates SQL for a partial update + * that does not include SQL for dropping assets which are scheduled for deletion. + * + * @return array The sequence of SQL statements. + */ + public function getUpdateSchemaSql(array $classes, $saveMode = false) + { + $sm = $this->em->getConnection()->getSchemaManager(); + + $fromSchema = $sm->createSchema(); + $toSchema = $this->getSchemaFromMetadata($classes); + + $comparator = new Comparator(); + $schemaDiff = $comparator->compare($fromSchema, $toSchema); + + if ($saveMode) { + return $schemaDiff->toSaveSql($this->platform); + } + + return $schemaDiff->toSql($this->platform); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaValidator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaValidator.php new file mode 100644 index 0000000..6446598 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaValidator.php @@ -0,0 +1,273 @@ +. + */ + +namespace Doctrine\ORM\Tools; + +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Doctrine\DBAL\Types\Type; + +/** + * Performs strict validation of the mapping schema + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.com + * @since 1.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + */ +class SchemaValidator +{ + /** + * @var EntityManagerInterface + */ + private $em; + + /** + * @param EntityManagerInterface $em + */ + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + } + + /** + * Checks the internal consistency of all mapping files. + * + * There are several checks that can't be done at runtime or are too expensive, which can be verified + * with this command. For example: + * + * 1. Check if a relation with "mappedBy" is actually connected to that specified field. + * 2. Check if "mappedBy" and "inversedBy" are consistent to each other. + * 3. Check if "referencedColumnName" attributes are really pointing to primary key columns. + * + * @return array + */ + public function validateMapping() + { + $errors = []; + $cmf = $this->em->getMetadataFactory(); + $classes = $cmf->getAllMetadata(); + + foreach ($classes as $class) { + if ($ce = $this->validateClass($class)) { + $errors[$class->name] = $ce; + } + } + + return $errors; + } + + /** + * Validates a single class of the current. + * + * @param ClassMetadataInfo $class + * + * @return array + */ + public function validateClass(ClassMetadataInfo $class) + { + $ce = []; + $cmf = $this->em->getMetadataFactory(); + + foreach ($class->fieldMappings as $fieldName => $mapping) { + if (!Type::hasType($mapping['type'])) { + $ce[] = "The field '" . $class->name . "#" . $fieldName."' uses a non-existent type '" . $mapping['type'] . "'."; + } + } + + foreach ($class->associationMappings as $fieldName => $assoc) { + if (!class_exists($assoc['targetEntity']) || $cmf->isTransient($assoc['targetEntity'])) { + $ce[] = "The target entity '" . $assoc['targetEntity'] . "' specified on " . $class->name . '#' . $fieldName . ' is unknown or not an entity.'; + + return $ce; + } + + if ($assoc['mappedBy'] && $assoc['inversedBy']) { + $ce[] = "The association " . $class . "#" . $fieldName . " cannot be defined as both inverse and owning."; + } + + $targetMetadata = $cmf->getMetadataFor($assoc['targetEntity']); + + if (isset($assoc['id']) && $targetMetadata->containsForeignIdentifier) { + $ce[] = "Cannot map association '" . $class->name. "#". $fieldName ." as identifier, because " . + "the target entity '". $targetMetadata->name . "' also maps an association as identifier."; + } + + if ($assoc['mappedBy']) { + if ($targetMetadata->hasField($assoc['mappedBy'])) { + $ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the owning side ". + "field " . $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " which is not defined as association, but as field."; + } + if (!$targetMetadata->hasAssociation($assoc['mappedBy'])) { + $ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the owning side ". + "field " . $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " which does not exist."; + } elseif ($targetMetadata->associationMappings[$assoc['mappedBy']]['inversedBy'] == null) { + $ce[] = "The field " . $class->name . "#" . $fieldName . " is on the inverse side of a ". + "bi-directional relationship, but the specified mappedBy association on the target-entity ". + $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " does not contain the required ". + "'inversedBy=\"" . $fieldName . "\"' attribute."; + } elseif ($targetMetadata->associationMappings[$assoc['mappedBy']]['inversedBy'] != $fieldName) { + $ce[] = "The mappings " . $class->name . "#" . $fieldName . " and " . + $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " are ". + "inconsistent with each other."; + } + } + + if ($assoc['inversedBy']) { + if ($targetMetadata->hasField($assoc['inversedBy'])) { + $ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the inverse side ". + "field " . $assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " which is not defined as association."; + } + + if (!$targetMetadata->hasAssociation($assoc['inversedBy'])) { + $ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the inverse side ". + "field " . $assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " which does not exist."; + } elseif ($targetMetadata->associationMappings[$assoc['inversedBy']]['mappedBy'] == null) { + $ce[] = "The field " . $class->name . "#" . $fieldName . " is on the owning side of a ". + "bi-directional relationship, but the specified mappedBy association on the target-entity ". + $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " does not contain the required ". + "'inversedBy' attribute."; + } elseif ($targetMetadata->associationMappings[$assoc['inversedBy']]['mappedBy'] != $fieldName) { + $ce[] = "The mappings " . $class->name . "#" . $fieldName . " and " . + $assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " are ". + "inconsistent with each other."; + } + + // Verify inverse side/owning side match each other + if (array_key_exists($assoc['inversedBy'], $targetMetadata->associationMappings)) { + $targetAssoc = $targetMetadata->associationMappings[$assoc['inversedBy']]; + if ($assoc['type'] == ClassMetadataInfo::ONE_TO_ONE && $targetAssoc['type'] !== ClassMetadataInfo::ONE_TO_ONE) { + $ce[] = "If association " . $class->name . "#" . $fieldName . " is one-to-one, then the inversed " . + "side " . $targetMetadata->name . "#" . $assoc['inversedBy'] . " has to be one-to-one as well."; + } elseif ($assoc['type'] == ClassMetadataInfo::MANY_TO_ONE && $targetAssoc['type'] !== ClassMetadataInfo::ONE_TO_MANY) { + $ce[] = "If association " . $class->name . "#" . $fieldName . " is many-to-one, then the inversed " . + "side " . $targetMetadata->name . "#" . $assoc['inversedBy'] . " has to be one-to-many."; + } elseif ($assoc['type'] == ClassMetadataInfo::MANY_TO_MANY && $targetAssoc['type'] !== ClassMetadataInfo::MANY_TO_MANY) { + $ce[] = "If association " . $class->name . "#" . $fieldName . " is many-to-many, then the inversed " . + "side " . $targetMetadata->name . "#" . $assoc['inversedBy'] . " has to be many-to-many as well."; + } + } + } + + if ($assoc['isOwningSide']) { + if ($assoc['type'] == ClassMetadataInfo::MANY_TO_MANY) { + $identifierColumns = $class->getIdentifierColumnNames(); + foreach ($assoc['joinTable']['joinColumns'] as $joinColumn) { + if (!in_array($joinColumn['referencedColumnName'], $identifierColumns)) { + $ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' " . + "has to be a primary key column on the target entity class '".$class->name."'."; + break; + } + } + + $identifierColumns = $targetMetadata->getIdentifierColumnNames(); + foreach ($assoc['joinTable']['inverseJoinColumns'] as $inverseJoinColumn) { + if (! in_array($inverseJoinColumn['referencedColumnName'], $identifierColumns)) { + $ce[] = "The referenced column name '" . $inverseJoinColumn['referencedColumnName'] . "' " . + "has to be a primary key column on the target entity class '" .$targetMetadata->name . "'."; + break; + } + } + + if (count($targetMetadata->getIdentifierColumnNames()) != count($assoc['joinTable']['inverseJoinColumns'])) { + $ce[] = "The inverse join columns of the many-to-many table '" . $assoc['joinTable']['name'] . "' " . + "have to contain to ALL identifier columns of the target entity '". $targetMetadata->name . "', " . + "however '" . implode(", ", array_diff($targetMetadata->getIdentifierColumnNames(), array_values($assoc['relationToTargetKeyColumns']))) . + "' are missing."; + } + + if (count($class->getIdentifierColumnNames()) != count($assoc['joinTable']['joinColumns'])) { + $ce[] = "The join columns of the many-to-many table '" . $assoc['joinTable']['name'] . "' " . + "have to contain to ALL identifier columns of the source entity '". $class->name . "', " . + "however '" . implode(", ", array_diff($class->getIdentifierColumnNames(), array_values($assoc['relationToSourceKeyColumns']))) . + "' are missing."; + } + + } elseif ($assoc['type'] & ClassMetadataInfo::TO_ONE) { + $identifierColumns = $targetMetadata->getIdentifierColumnNames(); + foreach ($assoc['joinColumns'] as $joinColumn) { + if (!in_array($joinColumn['referencedColumnName'], $identifierColumns)) { + $ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' " . + "has to be a primary key column on the target entity class '".$targetMetadata->name."'."; + } + } + + if (count($identifierColumns) != count($assoc['joinColumns'])) { + $ids = []; + + foreach ($assoc['joinColumns'] as $joinColumn) { + $ids[] = $joinColumn['name']; + } + + $ce[] = "The join columns of the association '" . $assoc['fieldName'] . "' " . + "have to match to ALL identifier columns of the target entity '". $targetMetadata->name . "', " . + "however '" . implode(", ", array_diff($targetMetadata->getIdentifierColumnNames(), $ids)) . + "' are missing."; + } + } + } + + if (isset($assoc['orderBy']) && $assoc['orderBy'] !== null) { + foreach ($assoc['orderBy'] as $orderField => $orientation) { + if (!$targetMetadata->hasField($orderField) && !$targetMetadata->hasAssociation($orderField)) { + $ce[] = "The association " . $class->name."#".$fieldName." is ordered by a foreign field " . + $orderField . " that is not a field on the target entity " . $targetMetadata->name . "."; + continue; + } + if ($targetMetadata->isCollectionValuedAssociation($orderField)) { + $ce[] = "The association " . $class->name."#".$fieldName." is ordered by a field " . + $orderField . " on " . $targetMetadata->name . " that is a collection-valued association."; + continue; + } + if ($targetMetadata->isAssociationInverseSide($orderField)) { + $ce[] = "The association " . $class->name."#".$fieldName." is ordered by a field " . + $orderField . " on " . $targetMetadata->name . " that is the inverse side of an association."; + continue; + } + } + } + } + + foreach ($class->subClasses as $subClass) { + if (!in_array($class->name, class_parents($subClass))) { + $ce[] = "According to the discriminator map class '" . $subClass . "' has to be a child ". + "of '" . $class->name . "' but these entities are not related through inheritance."; + } + } + + return $ce; + } + + /** + * Checks if the Database Schema is in sync with the current metadata state. + * + * @return bool + */ + public function schemaInSyncWithMetadata() + { + $schemaTool = new SchemaTool($this->em); + + $allMetadata = $this->em->getMetadataFactory()->getAllMetadata(); + + return count($schemaTool->getUpdateSchemaSql($allMetadata, true)) == 0; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Setup.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Setup.php new file mode 100644 index 0000000..302db67 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Setup.php @@ -0,0 +1,195 @@ +. + */ + +namespace Doctrine\ORM\Tools; + +use Doctrine\Common\ClassLoader; +use Doctrine\Common\Cache\Cache; +use Doctrine\Common\Cache\CacheProvider; +use Doctrine\Common\Cache\ArrayCache; +use Doctrine\ORM\Configuration; +use Doctrine\ORM\Mapping\Driver\XmlDriver; +use Doctrine\ORM\Mapping\Driver\YamlDriver; + +/** + * Convenience class for setting up Doctrine from different installations and configurations. + * + * @author Benjamin Eberlei + */ +class Setup +{ + /** + * Use this method to register all autoloads for a downloaded Doctrine library. + * Pick the directory the library was uncompressed into. + * + * @param string $directory + * + * @return void + */ + public static function registerAutoloadDirectory($directory) + { + if (!class_exists('Doctrine\Common\ClassLoader', false)) { + require_once $directory . "/Doctrine/Common/ClassLoader.php"; + } + + $loader = new ClassLoader("Doctrine", $directory); + $loader->register(); + + $loader = new ClassLoader("Symfony\Component", $directory . "/Doctrine"); + $loader->register(); + } + + /** + * Creates a configuration with an annotation metadata driver. + * + * @param array $paths + * @param boolean $isDevMode + * @param string $proxyDir + * @param Cache $cache + * @param bool $useSimpleAnnotationReader + * + * @return Configuration + */ + public static function createAnnotationMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null, $useSimpleAnnotationReader = true) + { + $config = self::createConfiguration($isDevMode, $proxyDir, $cache); + $config->setMetadataDriverImpl($config->newDefaultAnnotationDriver($paths, $useSimpleAnnotationReader)); + + return $config; + } + + /** + * Creates a configuration with a xml metadata driver. + * + * @param array $paths + * @param boolean $isDevMode + * @param string $proxyDir + * @param Cache $cache + * + * @return Configuration + */ + public static function createXMLMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null) + { + $config = self::createConfiguration($isDevMode, $proxyDir, $cache); + $config->setMetadataDriverImpl(new XmlDriver($paths)); + + return $config; + } + + /** + * Creates a configuration with a yaml metadata driver. + * + * @param array $paths + * @param boolean $isDevMode + * @param string $proxyDir + * @param Cache $cache + * + * @return Configuration + */ + public static function createYAMLMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null) + { + $config = self::createConfiguration($isDevMode, $proxyDir, $cache); + $config->setMetadataDriverImpl(new YamlDriver($paths)); + + return $config; + } + + /** + * Creates a configuration without a metadata driver. + * + * @param bool $isDevMode + * @param string $proxyDir + * @param Cache $cache + * + * @return Configuration + */ + public static function createConfiguration($isDevMode = false, $proxyDir = null, Cache $cache = null) + { + $proxyDir = $proxyDir ?: sys_get_temp_dir(); + + $cache = self::createCacheConfiguration($isDevMode, $proxyDir, $cache); + + $config = new Configuration(); + $config->setMetadataCacheImpl($cache); + $config->setQueryCacheImpl($cache); + $config->setResultCacheImpl($cache); + $config->setProxyDir($proxyDir); + $config->setProxyNamespace('DoctrineProxies'); + $config->setAutoGenerateProxyClasses($isDevMode); + + return $config; + } + + private static function createCacheConfiguration(bool $isDevMode, string $proxyDir, ?Cache $cache) : Cache + { + $cache = self::createCacheInstance($isDevMode, $cache); + + if ( ! $cache instanceof CacheProvider) { + return $cache; + } + + $namespace = $cache->getNamespace(); + + if ($namespace !== '') { + $namespace .= ':'; + } + + $cache->setNamespace($namespace . 'dc2_' . md5($proxyDir) . '_'); // to avoid collisions + + return $cache; + } + + private static function createCacheInstance(bool $isDevMode, ?Cache $cache) : Cache + { + if ($cache !== null) { + return $cache; + } + + if ($isDevMode === true) { + return new ArrayCache(); + } + + if (extension_loaded('apcu')) { + return new \Doctrine\Common\Cache\ApcuCache(); + } + + + if (extension_loaded('memcached')) { + $memcached = new \Memcached(); + $memcached->addServer('127.0.0.1', 11211); + + $cache = new \Doctrine\Common\Cache\MemcachedCache(); + $cache->setMemcached($memcached); + + return $cache; + } + + if (extension_loaded('redis')) { + $redis = new \Redis(); + $redis->connect('127.0.0.1'); + + $cache = new \Doctrine\Common\Cache\RedisCache(); + $cache->setRedis($redis); + + return $cache; + } + + return new ArrayCache(); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolEvents.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolEvents.php new file mode 100644 index 0000000..aebb5d8 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolEvents.php @@ -0,0 +1,42 @@ +. + */ + +namespace Doctrine\ORM\Tools; + +class ToolEvents +{ + /** + * The postGenerateSchemaTable event occurs in SchemaTool#getSchemaFromMetadata() + * whenever an entity class is transformed into its table representation. It receives + * the current non-complete Schema instance, the Entity Metadata Class instance and + * the Schema Table instance of this entity. + * + * @var string + */ + const postGenerateSchemaTable = 'postGenerateSchemaTable'; + + /** + * The postGenerateSchema event is triggered in SchemaTool#getSchemaFromMetadata() + * after all entity classes have been transformed into the related Schema structure. + * The EventArgs contain the EntityManager and the created Schema instance. + * + * @var string + */ + const postGenerateSchema = 'postGenerateSchema'; +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolsException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolsException.php new file mode 100644 index 0000000..95b3af0 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolsException.php @@ -0,0 +1,46 @@ +. + */ + +namespace Doctrine\ORM\Tools; + +use Doctrine\ORM\ORMException; +use Throwable; + +/** + * Tools related Exceptions. + * + * @author Benjamin Eberlei + */ +class ToolsException extends ORMException +{ + public static function schemaToolFailure(string $sql, Throwable $e) : self + { + return new self("Schema-Tool failed with Error '" . $e->getMessage() . "' while executing DDL: " . $sql, "0", $e); + } + + /** + * @param string $type + * + * @return ToolsException + */ + public static function couldNotMapDoctrine1Type($type) + { + return new self("Could not map doctrine 1 type '$type'!"); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/TransactionRequiredException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/TransactionRequiredException.php new file mode 100644 index 0000000..c3417b6 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/TransactionRequiredException.php @@ -0,0 +1,40 @@ +. + */ + +namespace Doctrine\ORM; + +/** + * Is thrown when a transaction is required for the current operation, but there is none open. + * + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link www.doctrine-project.com + * @since 1.0 + * @author Benjamin Eberlei + * @author Roman Borschel + */ +class TransactionRequiredException extends ORMException +{ + /** + * @return TransactionRequiredException + */ + static public function transactionRequired() + { + return new self('An open transaction is required for this operation.'); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/UnexpectedResultException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/UnexpectedResultException.php new file mode 100644 index 0000000..3cd561f --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/UnexpectedResultException.php @@ -0,0 +1,30 @@ +. + */ + +namespace Doctrine\ORM; + +/** + * Exception for a unexpected query result. + * + * @author Fabio B. Silva + * @since 2.3 + */ +class UnexpectedResultException extends ORMException +{ +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php b/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php new file mode 100644 index 0000000..f7b32b3 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php @@ -0,0 +1,3628 @@ +. + */ + +namespace Doctrine\ORM; + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; +use Doctrine\Common\NotifyPropertyChanged; +use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService; +use Doctrine\Common\Persistence\ObjectManagerAware; +use Doctrine\Common\PropertyChangedListener; +use Doctrine\DBAL\LockMode; +use Doctrine\ORM\Cache\Persister\CachedPersister; +use Doctrine\ORM\Event\LifecycleEventArgs; +use Doctrine\ORM\Event\ListenersInvoker; +use Doctrine\ORM\Event\OnFlushEventArgs; +use Doctrine\ORM\Event\PostFlushEventArgs; +use Doctrine\ORM\Event\PreFlushEventArgs; +use Doctrine\ORM\Event\PreUpdateEventArgs; +use Doctrine\ORM\Internal\HydrationCompleteHandler; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Mapping\Reflection\ReflectionPropertiesGetter; +use Doctrine\ORM\Persisters\Collection\ManyToManyPersister; +use Doctrine\ORM\Persisters\Collection\OneToManyPersister; +use Doctrine\ORM\Persisters\Entity\BasicEntityPersister; +use Doctrine\ORM\Persisters\Entity\JoinedSubclassPersister; +use Doctrine\ORM\Persisters\Entity\SingleTablePersister; +use Doctrine\ORM\Proxy\Proxy; +use Doctrine\ORM\Utility\IdentifierFlattener; +use InvalidArgumentException; +use Throwable; +use UnexpectedValueException; +use function get_class; + +/** + * The UnitOfWork is responsible for tracking changes to objects during an + * "object-level" transaction and for writing out changes to the database + * in the correct order. + * + * Internal note: This class contains highly performance-sensitive code. + * + * @since 2.0 + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Rob Caiger + */ +class UnitOfWork implements PropertyChangedListener +{ + /** + * An entity is in MANAGED state when its persistence is managed by an EntityManager. + */ + const STATE_MANAGED = 1; + + /** + * An entity is new if it has just been instantiated (i.e. using the "new" operator) + * and is not (yet) managed by an EntityManager. + */ + const STATE_NEW = 2; + + /** + * A detached entity is an instance with persistent state and identity that is not + * (or no longer) associated with an EntityManager (and a UnitOfWork). + */ + const STATE_DETACHED = 3; + + /** + * A removed entity instance is an instance with a persistent identity, + * associated with an EntityManager, whose persistent state will be deleted + * on commit. + */ + const STATE_REMOVED = 4; + + /** + * Hint used to collect all primary keys of associated entities during hydration + * and execute it in a dedicated query afterwards + * @see https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#temporarily-change-fetch-mode-in-dql + */ + const HINT_DEFEREAGERLOAD = 'deferEagerLoad'; + + /** + * The identity map that holds references to all managed entities that have + * an identity. The entities are grouped by their class name. + * Since all classes in a hierarchy must share the same identifier set, + * we always take the root class name of the hierarchy. + * + * @var array + */ + private $identityMap = []; + + /** + * Map of all identifiers of managed entities. + * Keys are object ids (spl_object_hash). + * + * @var array + */ + private $entityIdentifiers = []; + + /** + * Map of the original entity data of managed entities. + * Keys are object ids (spl_object_hash). This is used for calculating changesets + * at commit time. + * + * Internal note: Note that PHPs "copy-on-write" behavior helps a lot with memory usage. + * A value will only really be copied if the value in the entity is modified + * by the user. + * + * @var array + */ + private $originalEntityData = []; + + /** + * Map of entity changes. Keys are object ids (spl_object_hash). + * Filled at the beginning of a commit of the UnitOfWork and cleaned at the end. + * + * @var array + */ + private $entityChangeSets = []; + + /** + * The (cached) states of any known entities. + * Keys are object ids (spl_object_hash). + * + * @var array + */ + private $entityStates = []; + + /** + * Map of entities that are scheduled for dirty checking at commit time. + * This is only used for entities with a change tracking policy of DEFERRED_EXPLICIT. + * Keys are object ids (spl_object_hash). + * + * @var array + */ + private $scheduledForSynchronization = []; + + /** + * A list of all pending entity insertions. + * + * @var array + */ + private $entityInsertions = []; + + /** + * A list of all pending entity updates. + * + * @var array + */ + private $entityUpdates = []; + + /** + * Any pending extra updates that have been scheduled by persisters. + * + * @var array + */ + private $extraUpdates = []; + + /** + * A list of all pending entity deletions. + * + * @var array + */ + private $entityDeletions = []; + + /** + * New entities that were discovered through relationships that were not + * marked as cascade-persist. During flush, this array is populated and + * then pruned of any entities that were discovered through a valid + * cascade-persist path. (Leftovers cause an error.) + * + * Keys are OIDs, payload is a two-item array describing the association + * and the entity. + * + * @var object[][]|array[][] indexed by respective object spl_object_hash() + */ + private $nonCascadedNewDetectedEntities = []; + + /** + * All pending collection deletions. + * + * @var array + */ + private $collectionDeletions = []; + + /** + * All pending collection updates. + * + * @var array + */ + private $collectionUpdates = []; + + /** + * List of collections visited during changeset calculation on a commit-phase of a UnitOfWork. + * At the end of the UnitOfWork all these collections will make new snapshots + * of their data. + * + * @var array + */ + private $visitedCollections = []; + + /** + * The EntityManager that "owns" this UnitOfWork instance. + * + * @var EntityManagerInterface + */ + private $em; + + /** + * The entity persister instances used to persist entity instances. + * + * @var array + */ + private $persisters = []; + + /** + * The collection persister instances used to persist collections. + * + * @var array + */ + private $collectionPersisters = []; + + /** + * The EventManager used for dispatching events. + * + * @var \Doctrine\Common\EventManager + */ + private $evm; + + /** + * The ListenersInvoker used for dispatching events. + * + * @var \Doctrine\ORM\Event\ListenersInvoker + */ + private $listenersInvoker; + + /** + * The IdentifierFlattener used for manipulating identifiers + * + * @var \Doctrine\ORM\Utility\IdentifierFlattener + */ + private $identifierFlattener; + + /** + * Orphaned entities that are scheduled for removal. + * + * @var array + */ + private $orphanRemovals = []; + + /** + * Read-Only objects are never evaluated + * + * @var array + */ + private $readOnlyObjects = []; + + /** + * Map of Entity Class-Names and corresponding IDs that should eager loaded when requested. + * + * @var array + */ + private $eagerLoadingEntities = []; + + /** + * @var boolean + */ + protected $hasCache = false; + + /** + * Helper for handling completion of hydration + * + * @var HydrationCompleteHandler + */ + private $hydrationCompleteHandler; + + /** + * @var ReflectionPropertiesGetter + */ + private $reflectionPropertiesGetter; + + /** + * Initializes a new UnitOfWork instance, bound to the given EntityManager. + * + * @param EntityManagerInterface $em + */ + public function __construct(EntityManagerInterface $em) + { + $this->em = $em; + $this->evm = $em->getEventManager(); + $this->listenersInvoker = new ListenersInvoker($em); + $this->hasCache = $em->getConfiguration()->isSecondLevelCacheEnabled(); + $this->identifierFlattener = new IdentifierFlattener($this, $em->getMetadataFactory()); + $this->hydrationCompleteHandler = new HydrationCompleteHandler($this->listenersInvoker, $em); + $this->reflectionPropertiesGetter = new ReflectionPropertiesGetter(new RuntimeReflectionService()); + } + + /** + * Commits the UnitOfWork, executing all operations that have been postponed + * up to this point. The state of all managed entities will be synchronized with + * the database. + * + * The operations are executed in the following order: + * + * 1) All entity insertions + * 2) All entity updates + * 3) All collection deletions + * 4) All collection updates + * 5) All entity deletions + * + * @param null|object|array $entity + * + * @return void + * + * @throws \Exception + */ + public function commit($entity = null) + { + // Raise preFlush + if ($this->evm->hasListeners(Events::preFlush)) { + $this->evm->dispatchEvent(Events::preFlush, new PreFlushEventArgs($this->em)); + } + + // Compute changes done since last commit. + if (null === $entity) { + $this->computeChangeSets(); + } elseif (is_object($entity)) { + $this->computeSingleEntityChangeSet($entity); + } elseif (is_array($entity)) { + foreach ($entity as $object) { + $this->computeSingleEntityChangeSet($object); + } + } + + if ( ! ($this->entityInsertions || + $this->entityDeletions || + $this->entityUpdates || + $this->collectionUpdates || + $this->collectionDeletions || + $this->orphanRemovals)) { + $this->dispatchOnFlushEvent(); + $this->dispatchPostFlushEvent(); + + $this->postCommitCleanup($entity); + + return; // Nothing to do. + } + + $this->assertThatThereAreNoUnintentionallyNonPersistedAssociations(); + + if ($this->orphanRemovals) { + foreach ($this->orphanRemovals as $orphan) { + $this->remove($orphan); + } + } + + $this->dispatchOnFlushEvent(); + + // Now we need a commit order to maintain referential integrity + $commitOrder = $this->getCommitOrder(); + + $conn = $this->em->getConnection(); + $conn->beginTransaction(); + + try { + // Collection deletions (deletions of complete collections) + foreach ($this->collectionDeletions as $collectionToDelete) { + if (! $collectionToDelete instanceof PersistentCollection) { + $this->getCollectionPersister($collectionToDelete->getMapping())->delete($collectionToDelete); + + continue; + } + + // Deferred explicit tracked collections can be removed only when owning relation was persisted + $owner = $collectionToDelete->getOwner(); + + if ($this->em->getClassMetadata(get_class($owner))->isChangeTrackingDeferredImplicit() || $this->isScheduledForDirtyCheck($owner)) { + $this->getCollectionPersister($collectionToDelete->getMapping())->delete($collectionToDelete); + } + } + + if ($this->entityInsertions) { + foreach ($commitOrder as $class) { + $this->executeInserts($class); + } + } + + if ($this->entityUpdates) { + foreach ($commitOrder as $class) { + $this->executeUpdates($class); + } + } + + // Extra updates that were requested by persisters. + if ($this->extraUpdates) { + $this->executeExtraUpdates(); + } + + // Collection updates (deleteRows, updateRows, insertRows) + foreach ($this->collectionUpdates as $collectionToUpdate) { + $this->getCollectionPersister($collectionToUpdate->getMapping())->update($collectionToUpdate); + } + + // Entity deletions come last and need to be in reverse commit order + if ($this->entityDeletions) { + for ($count = count($commitOrder), $i = $count - 1; $i >= 0 && $this->entityDeletions; --$i) { + $this->executeDeletions($commitOrder[$i]); + } + } + + $conn->commit(); + } catch (Throwable $e) { + $this->em->close(); + $conn->rollBack(); + + $this->afterTransactionRolledBack(); + + throw $e; + } + + $this->afterTransactionComplete(); + + // Take new snapshots from visited collections + foreach ($this->visitedCollections as $coll) { + $coll->takeSnapshot(); + } + + $this->dispatchPostFlushEvent(); + + $this->postCommitCleanup($entity); + } + + /** + * @param null|object|object[] $entity + */ + private function postCommitCleanup($entity) : void + { + $this->entityInsertions = + $this->entityUpdates = + $this->entityDeletions = + $this->extraUpdates = + $this->collectionUpdates = + $this->nonCascadedNewDetectedEntities = + $this->collectionDeletions = + $this->visitedCollections = + $this->orphanRemovals = []; + + if (null === $entity) { + $this->entityChangeSets = $this->scheduledForSynchronization = []; + + return; + } + + $entities = \is_object($entity) + ? [$entity] + : $entity; + + foreach ($entities as $object) { + $oid = \spl_object_hash($object); + + $this->clearEntityChangeSet($oid); + + unset($this->scheduledForSynchronization[$this->em->getClassMetadata(\get_class($object))->rootEntityName][$oid]); + } + } + + /** + * Computes the changesets of all entities scheduled for insertion. + * + * @return void + */ + private function computeScheduleInsertsChangeSets() + { + foreach ($this->entityInsertions as $entity) { + $class = $this->em->getClassMetadata(get_class($entity)); + + $this->computeChangeSet($class, $entity); + } + } + + /** + * Only flushes the given entity according to a ruleset that keeps the UoW consistent. + * + * 1. All entities scheduled for insertion, (orphan) removals and changes in collections are processed as well! + * 2. Read Only entities are skipped. + * 3. Proxies are skipped. + * 4. Only if entity is properly managed. + * + * @param object $entity + * + * @return void + * + * @throws \InvalidArgumentException + */ + private function computeSingleEntityChangeSet($entity) + { + $state = $this->getEntityState($entity); + + if ($state !== self::STATE_MANAGED && $state !== self::STATE_REMOVED) { + throw new \InvalidArgumentException("Entity has to be managed or scheduled for removal for single computation " . self::objToStr($entity)); + } + + $class = $this->em->getClassMetadata(get_class($entity)); + + if ($state === self::STATE_MANAGED && $class->isChangeTrackingDeferredImplicit()) { + $this->persist($entity); + } + + // Compute changes for INSERTed entities first. This must always happen even in this case. + $this->computeScheduleInsertsChangeSets(); + + if ($class->isReadOnly) { + return; + } + + // Ignore uninitialized proxy objects + if ($entity instanceof Proxy && ! $entity->__isInitialized__) { + return; + } + + // Only MANAGED entities that are NOT SCHEDULED FOR INSERTION OR DELETION are processed here. + $oid = spl_object_hash($entity); + + if ( ! isset($this->entityInsertions[$oid]) && ! isset($this->entityDeletions[$oid]) && isset($this->entityStates[$oid])) { + $this->computeChangeSet($class, $entity); + } + } + + /** + * Executes any extra updates that have been scheduled. + */ + private function executeExtraUpdates() + { + foreach ($this->extraUpdates as $oid => $update) { + list ($entity, $changeset) = $update; + + $this->entityChangeSets[$oid] = $changeset; + $this->getEntityPersister(get_class($entity))->update($entity); + } + + $this->extraUpdates = []; + } + + /** + * Gets the changeset for an entity. + * + * @param object $entity + * + * @return array + */ + public function & getEntityChangeSet($entity) + { + $oid = spl_object_hash($entity); + $data = []; + + if (!isset($this->entityChangeSets[$oid])) { + return $data; + } + + return $this->entityChangeSets[$oid]; + } + + /** + * Computes the changes that happened to a single entity. + * + * Modifies/populates the following properties: + * + * {@link _originalEntityData} + * If the entity is NEW or MANAGED but not yet fully persisted (only has an id) + * then it was not fetched from the database and therefore we have no original + * entity data yet. All of the current entity data is stored as the original entity data. + * + * {@link _entityChangeSets} + * The changes detected on all properties of the entity are stored there. + * A change is a tuple array where the first entry is the old value and the second + * entry is the new value of the property. Changesets are used by persisters + * to INSERT/UPDATE the persistent entity state. + * + * {@link _entityUpdates} + * If the entity is already fully MANAGED (has been fetched from the database before) + * and any changes to its properties are detected, then a reference to the entity is stored + * there to mark it for an update. + * + * {@link _collectionDeletions} + * If a PersistentCollection has been de-referenced in a fully MANAGED entity, + * then this collection is marked for deletion. + * + * @ignore + * + * @internal Don't call from the outside. + * + * @param ClassMetadata $class The class descriptor of the entity. + * @param object $entity The entity for which to compute the changes. + * + * @return void + */ + public function computeChangeSet(ClassMetadata $class, $entity) + { + $oid = spl_object_hash($entity); + + if (isset($this->readOnlyObjects[$oid])) { + return; + } + + if ( ! $class->isInheritanceTypeNone()) { + $class = $this->em->getClassMetadata(get_class($entity)); + } + + $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preFlush) & ~ListenersInvoker::INVOKE_MANAGER; + + if ($invoke !== ListenersInvoker::INVOKE_NONE) { + $this->listenersInvoker->invoke($class, Events::preFlush, $entity, new PreFlushEventArgs($this->em), $invoke); + } + + $actualData = []; + + foreach ($class->reflFields as $name => $refProp) { + $value = $refProp->getValue($entity); + + if ($class->isCollectionValuedAssociation($name) && $value !== null) { + if ($value instanceof PersistentCollection) { + if ($value->getOwner() === $entity) { + continue; + } + + $value = new ArrayCollection($value->getValues()); + } + + // If $value is not a Collection then use an ArrayCollection. + if ( ! $value instanceof Collection) { + $value = new ArrayCollection($value); + } + + $assoc = $class->associationMappings[$name]; + + // Inject PersistentCollection + $value = new PersistentCollection( + $this->em, $this->em->getClassMetadata($assoc['targetEntity']), $value + ); + $value->setOwner($entity, $assoc); + $value->setDirty( ! $value->isEmpty()); + + $class->reflFields[$name]->setValue($entity, $value); + + $actualData[$name] = $value; + + continue; + } + + if (( ! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity()) && ($name !== $class->versionField)) { + $actualData[$name] = $value; + } + } + + if ( ! isset($this->originalEntityData[$oid])) { + // Entity is either NEW or MANAGED but not yet fully persisted (only has an id). + // These result in an INSERT. + $this->originalEntityData[$oid] = $actualData; + $changeSet = []; + + foreach ($actualData as $propName => $actualValue) { + if ( ! isset($class->associationMappings[$propName])) { + $changeSet[$propName] = [null, $actualValue]; + + continue; + } + + $assoc = $class->associationMappings[$propName]; + + if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) { + $changeSet[$propName] = [null, $actualValue]; + } + } + + $this->entityChangeSets[$oid] = $changeSet; + } else { + // Entity is "fully" MANAGED: it was already fully persisted before + // and we have a copy of the original data + $originalData = $this->originalEntityData[$oid]; + $isChangeTrackingNotify = $class->isChangeTrackingNotify(); + $changeSet = ($isChangeTrackingNotify && isset($this->entityChangeSets[$oid])) + ? $this->entityChangeSets[$oid] + : []; + + foreach ($actualData as $propName => $actualValue) { + // skip field, its a partially omitted one! + if ( ! (isset($originalData[$propName]) || array_key_exists($propName, $originalData))) { + continue; + } + + $orgValue = $originalData[$propName]; + + // skip if value haven't changed + if ($orgValue === $actualValue) { + continue; + } + + // if regular field + if ( ! isset($class->associationMappings[$propName])) { + if ($isChangeTrackingNotify) { + continue; + } + + $changeSet[$propName] = [$orgValue, $actualValue]; + + continue; + } + + $assoc = $class->associationMappings[$propName]; + + // Persistent collection was exchanged with the "originally" + // created one. This can only mean it was cloned and replaced + // on another entity. + if ($actualValue instanceof PersistentCollection) { + $owner = $actualValue->getOwner(); + if ($owner === null) { // cloned + $actualValue->setOwner($entity, $assoc); + } else if ($owner !== $entity) { // no clone, we have to fix + if (!$actualValue->isInitialized()) { + $actualValue->initialize(); // we have to do this otherwise the cols share state + } + $newValue = clone $actualValue; + $newValue->setOwner($entity, $assoc); + $class->reflFields[$propName]->setValue($entity, $newValue); + } + } + + if ($orgValue instanceof PersistentCollection) { + // A PersistentCollection was de-referenced, so delete it. + $coid = spl_object_hash($orgValue); + + if (isset($this->collectionDeletions[$coid])) { + continue; + } + + $this->collectionDeletions[$coid] = $orgValue; + $changeSet[$propName] = $orgValue; // Signal changeset, to-many assocs will be ignored. + + continue; + } + + if ($assoc['type'] & ClassMetadata::TO_ONE) { + if ($assoc['isOwningSide']) { + $changeSet[$propName] = [$orgValue, $actualValue]; + } + + if ($orgValue !== null && $assoc['orphanRemoval']) { + $this->scheduleOrphanRemoval($orgValue); + } + } + } + + if ($changeSet) { + $this->entityChangeSets[$oid] = $changeSet; + $this->originalEntityData[$oid] = $actualData; + $this->entityUpdates[$oid] = $entity; + } + } + + // Look for changes in associations of the entity + foreach ($class->associationMappings as $field => $assoc) { + if (($val = $class->reflFields[$field]->getValue($entity)) === null) { + continue; + } + + $this->computeAssociationChanges($assoc, $val); + + if ( ! isset($this->entityChangeSets[$oid]) && + $assoc['isOwningSide'] && + $assoc['type'] == ClassMetadata::MANY_TO_MANY && + $val instanceof PersistentCollection && + $val->isDirty()) { + + $this->entityChangeSets[$oid] = []; + $this->originalEntityData[$oid] = $actualData; + $this->entityUpdates[$oid] = $entity; + } + } + } + + /** + * Computes all the changes that have been done to entities and collections + * since the last commit and stores these changes in the _entityChangeSet map + * temporarily for access by the persisters, until the UoW commit is finished. + * + * @return void + */ + public function computeChangeSets() + { + // Compute changes for INSERTed entities first. This must always happen. + $this->computeScheduleInsertsChangeSets(); + + // Compute changes for other MANAGED entities. Change tracking policies take effect here. + foreach ($this->identityMap as $className => $entities) { + $class = $this->em->getClassMetadata($className); + + // Skip class if instances are read-only + if ($class->isReadOnly) { + continue; + } + + // If change tracking is explicit or happens through notification, then only compute + // changes on entities of that type that are explicitly marked for synchronization. + switch (true) { + case ($class->isChangeTrackingDeferredImplicit()): + $entitiesToProcess = $entities; + break; + + case (isset($this->scheduledForSynchronization[$className])): + $entitiesToProcess = $this->scheduledForSynchronization[$className]; + break; + + default: + $entitiesToProcess = []; + + } + + foreach ($entitiesToProcess as $entity) { + // Ignore uninitialized proxy objects + if ($entity instanceof Proxy && ! $entity->__isInitialized__) { + continue; + } + + // Only MANAGED entities that are NOT SCHEDULED FOR INSERTION OR DELETION are processed here. + $oid = spl_object_hash($entity); + + if ( ! isset($this->entityInsertions[$oid]) && ! isset($this->entityDeletions[$oid]) && isset($this->entityStates[$oid])) { + $this->computeChangeSet($class, $entity); + } + } + } + } + + /** + * Computes the changes of an association. + * + * @param array $assoc The association mapping. + * @param mixed $value The value of the association. + * + * @throws ORMInvalidArgumentException + * @throws ORMException + * + * @return void + */ + private function computeAssociationChanges($assoc, $value) + { + if ($value instanceof Proxy && ! $value->__isInitialized__) { + return; + } + + if ($value instanceof PersistentCollection && $value->isDirty()) { + $coid = spl_object_hash($value); + + $this->collectionUpdates[$coid] = $value; + $this->visitedCollections[$coid] = $value; + } + + // Look through the entities, and in any of their associations, + // for transient (new) entities, recursively. ("Persistence by reachability") + // Unwrap. Uninitialized collections will simply be empty. + $unwrappedValue = ($assoc['type'] & ClassMetadata::TO_ONE) ? [$value] : $value->unwrap(); + $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); + + foreach ($unwrappedValue as $key => $entry) { + if (! ($entry instanceof $targetClass->name)) { + throw ORMInvalidArgumentException::invalidAssociation($targetClass, $assoc, $entry); + } + + $state = $this->getEntityState($entry, self::STATE_NEW); + + if ( ! ($entry instanceof $assoc['targetEntity'])) { + throw ORMException::unexpectedAssociationValue($assoc['sourceEntity'], $assoc['fieldName'], get_class($entry), $assoc['targetEntity']); + } + + switch ($state) { + case self::STATE_NEW: + if ( ! $assoc['isCascadePersist']) { + /* + * For now just record the details, because this may + * not be an issue if we later discover another pathway + * through the object-graph where cascade-persistence + * is enabled for this object. + */ + $this->nonCascadedNewDetectedEntities[\spl_object_hash($entry)] = [$assoc, $entry]; + + break; + } + + $this->persistNew($targetClass, $entry); + $this->computeChangeSet($targetClass, $entry); + + break; + + case self::STATE_REMOVED: + // Consume the $value as array (it's either an array or an ArrayAccess) + // and remove the element from Collection. + if ($assoc['type'] & ClassMetadata::TO_MANY) { + unset($value[$key]); + } + break; + + case self::STATE_DETACHED: + // Can actually not happen right now as we assume STATE_NEW, + // so the exception will be raised from the DBAL layer (constraint violation). + throw ORMInvalidArgumentException::detachedEntityFoundThroughRelationship($assoc, $entry); + break; + + default: + // MANAGED associated entities are already taken into account + // during changeset calculation anyway, since they are in the identity map. + } + } + } + + /** + * @param \Doctrine\ORM\Mapping\ClassMetadata $class + * @param object $entity + * + * @return void + */ + private function persistNew($class, $entity) + { + $oid = spl_object_hash($entity); + $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::prePersist); + + if ($invoke !== ListenersInvoker::INVOKE_NONE) { + $this->listenersInvoker->invoke($class, Events::prePersist, $entity, new LifecycleEventArgs($entity, $this->em), $invoke); + } + + $idGen = $class->idGenerator; + + if ( ! $idGen->isPostInsertGenerator()) { + $idValue = $idGen->generate($this->em, $entity); + + if ( ! $idGen instanceof \Doctrine\ORM\Id\AssignedGenerator) { + $idValue = [$class->getSingleIdentifierFieldName() => $this->convertSingleFieldIdentifierToPHPValue($class, $idValue)]; + + $class->setIdentifierValues($entity, $idValue); + } + + // Some identifiers may be foreign keys to new entities. + // In this case, we don't have the value yet and should treat it as if we have a post-insert generator + if (! $this->hasMissingIdsWhichAreForeignKeys($class, $idValue)) { + $this->entityIdentifiers[$oid] = $idValue; + } + } + + $this->entityStates[$oid] = self::STATE_MANAGED; + + $this->scheduleForInsert($entity); + } + + /** + * @param mixed[] $idValue + */ + private function hasMissingIdsWhichAreForeignKeys(ClassMetadata $class, array $idValue) : bool + { + foreach ($idValue as $idField => $idFieldValue) { + if ($idFieldValue === null && isset($class->associationMappings[$idField])) { + return true; + } + } + + return false; + } + + /** + * INTERNAL: + * Computes the changeset of an individual entity, independently of the + * computeChangeSets() routine that is used at the beginning of a UnitOfWork#commit(). + * + * The passed entity must be a managed entity. If the entity already has a change set + * because this method is invoked during a commit cycle then the change sets are added. + * whereby changes detected in this method prevail. + * + * @ignore + * + * @param ClassMetadata $class The class descriptor of the entity. + * @param object $entity The entity for which to (re)calculate the change set. + * + * @return void + * + * @throws ORMInvalidArgumentException If the passed entity is not MANAGED. + */ + public function recomputeSingleEntityChangeSet(ClassMetadata $class, $entity) + { + $oid = spl_object_hash($entity); + + if ( ! isset($this->entityStates[$oid]) || $this->entityStates[$oid] != self::STATE_MANAGED) { + throw ORMInvalidArgumentException::entityNotManaged($entity); + } + + // skip if change tracking is "NOTIFY" + if ($class->isChangeTrackingNotify()) { + return; + } + + if ( ! $class->isInheritanceTypeNone()) { + $class = $this->em->getClassMetadata(get_class($entity)); + } + + $actualData = []; + + foreach ($class->reflFields as $name => $refProp) { + if (( ! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity()) + && ($name !== $class->versionField) + && ! $class->isCollectionValuedAssociation($name)) { + $actualData[$name] = $refProp->getValue($entity); + } + } + + if ( ! isset($this->originalEntityData[$oid])) { + throw new \RuntimeException('Cannot call recomputeSingleEntityChangeSet before computeChangeSet on an entity.'); + } + + $originalData = $this->originalEntityData[$oid]; + $changeSet = []; + + foreach ($actualData as $propName => $actualValue) { + $orgValue = $originalData[$propName] ?? null; + + if ($orgValue !== $actualValue) { + $changeSet[$propName] = [$orgValue, $actualValue]; + } + } + + if ($changeSet) { + if (isset($this->entityChangeSets[$oid])) { + $this->entityChangeSets[$oid] = array_merge($this->entityChangeSets[$oid], $changeSet); + } else if ( ! isset($this->entityInsertions[$oid])) { + $this->entityChangeSets[$oid] = $changeSet; + $this->entityUpdates[$oid] = $entity; + } + $this->originalEntityData[$oid] = $actualData; + } + } + + /** + * Executes all entity insertions for entities of the specified type. + * + * @param \Doctrine\ORM\Mapping\ClassMetadata $class + * + * @return void + */ + private function executeInserts($class) + { + $entities = []; + $className = $class->name; + $persister = $this->getEntityPersister($className); + $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postPersist); + + $insertionsForClass = []; + + foreach ($this->entityInsertions as $oid => $entity) { + + if ($this->em->getClassMetadata(get_class($entity))->name !== $className) { + continue; + } + + $insertionsForClass[$oid] = $entity; + + $persister->addInsert($entity); + + unset($this->entityInsertions[$oid]); + + if ($invoke !== ListenersInvoker::INVOKE_NONE) { + $entities[] = $entity; + } + } + + $postInsertIds = $persister->executeInserts(); + + if ($postInsertIds) { + // Persister returned post-insert IDs + foreach ($postInsertIds as $postInsertId) { + $idField = $class->getSingleIdentifierFieldName(); + $idValue = $this->convertSingleFieldIdentifierToPHPValue($class, $postInsertId['generatedId']); + + $entity = $postInsertId['entity']; + $oid = spl_object_hash($entity); + + $class->reflFields[$idField]->setValue($entity, $idValue); + + $this->entityIdentifiers[$oid] = [$idField => $idValue]; + $this->entityStates[$oid] = self::STATE_MANAGED; + $this->originalEntityData[$oid][$idField] = $idValue; + + $this->addToIdentityMap($entity); + } + } else { + foreach ($insertionsForClass as $oid => $entity) { + if (! isset($this->entityIdentifiers[$oid])) { + //entity was not added to identity map because some identifiers are foreign keys to new entities. + //add it now + $this->addToEntityIdentifiersAndEntityMap($class, $oid, $entity); + } + } + } + + foreach ($entities as $entity) { + $this->listenersInvoker->invoke($class, Events::postPersist, $entity, new LifecycleEventArgs($entity, $this->em), $invoke); + } + } + + /** + * @param object $entity + */ + private function addToEntityIdentifiersAndEntityMap(ClassMetadata $class, string $oid, $entity): void + { + $identifier = []; + + foreach ($class->getIdentifierFieldNames() as $idField) { + $value = $class->getFieldValue($entity, $idField); + + if (isset($class->associationMappings[$idField])) { + // NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced. + $value = $this->getSingleIdentifierValue($value); + } + + $identifier[$idField] = $this->originalEntityData[$oid][$idField] = $value; + } + + $this->entityStates[$oid] = self::STATE_MANAGED; + $this->entityIdentifiers[$oid] = $identifier; + + $this->addToIdentityMap($entity); + } + + /** + * Executes all entity updates for entities of the specified type. + * + * @param \Doctrine\ORM\Mapping\ClassMetadata $class + * + * @return void + */ + private function executeUpdates($class) + { + $className = $class->name; + $persister = $this->getEntityPersister($className); + $preUpdateInvoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preUpdate); + $postUpdateInvoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postUpdate); + + foreach ($this->entityUpdates as $oid => $entity) { + if ($this->em->getClassMetadata(get_class($entity))->name !== $className) { + continue; + } + + if ($preUpdateInvoke != ListenersInvoker::INVOKE_NONE) { + $this->listenersInvoker->invoke($class, Events::preUpdate, $entity, new PreUpdateEventArgs($entity, $this->em, $this->getEntityChangeSet($entity)), $preUpdateInvoke); + + $this->recomputeSingleEntityChangeSet($class, $entity); + } + + if ( ! empty($this->entityChangeSets[$oid])) { + $persister->update($entity); + } + + unset($this->entityUpdates[$oid]); + + if ($postUpdateInvoke != ListenersInvoker::INVOKE_NONE) { + $this->listenersInvoker->invoke($class, Events::postUpdate, $entity, new LifecycleEventArgs($entity, $this->em), $postUpdateInvoke); + } + } + } + + /** + * Executes all entity deletions for entities of the specified type. + * + * @param \Doctrine\ORM\Mapping\ClassMetadata $class + * + * @return void + */ + private function executeDeletions($class) + { + $className = $class->name; + $persister = $this->getEntityPersister($className); + $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postRemove); + + foreach ($this->entityDeletions as $oid => $entity) { + if ($this->em->getClassMetadata(get_class($entity))->name !== $className) { + continue; + } + + $persister->delete($entity); + + unset( + $this->entityDeletions[$oid], + $this->entityIdentifiers[$oid], + $this->originalEntityData[$oid], + $this->entityStates[$oid] + ); + + // Entity with this $oid after deletion treated as NEW, even if the $oid + // is obtained by a new entity because the old one went out of scope. + //$this->entityStates[$oid] = self::STATE_NEW; + if ( ! $class->isIdentifierNatural()) { + $class->reflFields[$class->identifier[0]]->setValue($entity, null); + } + + if ($invoke !== ListenersInvoker::INVOKE_NONE) { + $this->listenersInvoker->invoke($class, Events::postRemove, $entity, new LifecycleEventArgs($entity, $this->em), $invoke); + } + } + } + + /** + * Gets the commit order. + * + * @param array|null $entityChangeSet + * + * @return array + */ + private function getCommitOrder(array $entityChangeSet = null) + { + if ($entityChangeSet === null) { + $entityChangeSet = array_merge($this->entityInsertions, $this->entityUpdates, $this->entityDeletions); + } + + $calc = $this->getCommitOrderCalculator(); + + // See if there are any new classes in the changeset, that are not in the + // commit order graph yet (don't have a node). + // We have to inspect changeSet to be able to correctly build dependencies. + // It is not possible to use IdentityMap here because post inserted ids + // are not yet available. + $newNodes = []; + + foreach ($entityChangeSet as $entity) { + $class = $this->em->getClassMetadata(get_class($entity)); + + if ($calc->hasNode($class->name)) { + continue; + } + + $calc->addNode($class->name, $class); + + $newNodes[] = $class; + } + + // Calculate dependencies for new nodes + while ($class = array_pop($newNodes)) { + foreach ($class->associationMappings as $assoc) { + if ( ! ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE)) { + continue; + } + + $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); + + if ( ! $calc->hasNode($targetClass->name)) { + $calc->addNode($targetClass->name, $targetClass); + + $newNodes[] = $targetClass; + } + + $joinColumns = reset($assoc['joinColumns']); + + $calc->addDependency($targetClass->name, $class->name, (int)empty($joinColumns['nullable'])); + + // If the target class has mapped subclasses, these share the same dependency. + if ( ! $targetClass->subClasses) { + continue; + } + + foreach ($targetClass->subClasses as $subClassName) { + $targetSubClass = $this->em->getClassMetadata($subClassName); + + if ( ! $calc->hasNode($subClassName)) { + $calc->addNode($targetSubClass->name, $targetSubClass); + + $newNodes[] = $targetSubClass; + } + + $calc->addDependency($targetSubClass->name, $class->name, 1); + } + } + } + + return $calc->sort(); + } + + /** + * Schedules an entity for insertion into the database. + * If the entity already has an identifier, it will be added to the identity map. + * + * @param object $entity The entity to schedule for insertion. + * + * @return void + * + * @throws ORMInvalidArgumentException + * @throws \InvalidArgumentException + */ + public function scheduleForInsert($entity) + { + $oid = spl_object_hash($entity); + + if (isset($this->entityUpdates[$oid])) { + throw new InvalidArgumentException("Dirty entity can not be scheduled for insertion."); + } + + if (isset($this->entityDeletions[$oid])) { + throw ORMInvalidArgumentException::scheduleInsertForRemovedEntity($entity); + } + if (isset($this->originalEntityData[$oid]) && ! isset($this->entityInsertions[$oid])) { + throw ORMInvalidArgumentException::scheduleInsertForManagedEntity($entity); + } + + if (isset($this->entityInsertions[$oid])) { + throw ORMInvalidArgumentException::scheduleInsertTwice($entity); + } + + $this->entityInsertions[$oid] = $entity; + + if (isset($this->entityIdentifiers[$oid])) { + $this->addToIdentityMap($entity); + } + + if ($entity instanceof NotifyPropertyChanged) { + $entity->addPropertyChangedListener($this); + } + } + + /** + * Checks whether an entity is scheduled for insertion. + * + * @param object $entity + * + * @return boolean + */ + public function isScheduledForInsert($entity) + { + return isset($this->entityInsertions[spl_object_hash($entity)]); + } + + /** + * Schedules an entity for being updated. + * + * @param object $entity The entity to schedule for being updated. + * + * @return void + * + * @throws ORMInvalidArgumentException + */ + public function scheduleForUpdate($entity) + { + $oid = spl_object_hash($entity); + + if ( ! isset($this->entityIdentifiers[$oid])) { + throw ORMInvalidArgumentException::entityHasNoIdentity($entity, "scheduling for update"); + } + + if (isset($this->entityDeletions[$oid])) { + throw ORMInvalidArgumentException::entityIsRemoved($entity, "schedule for update"); + } + + if ( ! isset($this->entityUpdates[$oid]) && ! isset($this->entityInsertions[$oid])) { + $this->entityUpdates[$oid] = $entity; + } + } + + /** + * INTERNAL: + * Schedules an extra update that will be executed immediately after the + * regular entity updates within the currently running commit cycle. + * + * Extra updates for entities are stored as (entity, changeset) tuples. + * + * @ignore + * + * @param object $entity The entity for which to schedule an extra update. + * @param array $changeset The changeset of the entity (what to update). + * + * @return void + */ + public function scheduleExtraUpdate($entity, array $changeset) + { + $oid = spl_object_hash($entity); + $extraUpdate = [$entity, $changeset]; + + if (isset($this->extraUpdates[$oid])) { + list(, $changeset2) = $this->extraUpdates[$oid]; + + $extraUpdate = [$entity, $changeset + $changeset2]; + } + + $this->extraUpdates[$oid] = $extraUpdate; + } + + /** + * Checks whether an entity is registered as dirty in the unit of work. + * Note: Is not very useful currently as dirty entities are only registered + * at commit time. + * + * @param object $entity + * + * @return boolean + */ + public function isScheduledForUpdate($entity) + { + return isset($this->entityUpdates[spl_object_hash($entity)]); + } + + /** + * Checks whether an entity is registered to be checked in the unit of work. + * + * @param object $entity + * + * @return boolean + */ + public function isScheduledForDirtyCheck($entity) + { + $rootEntityName = $this->em->getClassMetadata(get_class($entity))->rootEntityName; + + return isset($this->scheduledForSynchronization[$rootEntityName][spl_object_hash($entity)]); + } + + /** + * INTERNAL: + * Schedules an entity for deletion. + * + * @param object $entity + * + * @return void + */ + public function scheduleForDelete($entity) + { + $oid = spl_object_hash($entity); + + if (isset($this->entityInsertions[$oid])) { + if ($this->isInIdentityMap($entity)) { + $this->removeFromIdentityMap($entity); + } + + unset($this->entityInsertions[$oid], $this->entityStates[$oid]); + + return; // entity has not been persisted yet, so nothing more to do. + } + + if ( ! $this->isInIdentityMap($entity)) { + return; + } + + $this->removeFromIdentityMap($entity); + + unset($this->entityUpdates[$oid]); + + if ( ! isset($this->entityDeletions[$oid])) { + $this->entityDeletions[$oid] = $entity; + $this->entityStates[$oid] = self::STATE_REMOVED; + } + } + + /** + * Checks whether an entity is registered as removed/deleted with the unit + * of work. + * + * @param object $entity + * + * @return boolean + */ + public function isScheduledForDelete($entity) + { + return isset($this->entityDeletions[spl_object_hash($entity)]); + } + + /** + * Checks whether an entity is scheduled for insertion, update or deletion. + * + * @param object $entity + * + * @return boolean + */ + public function isEntityScheduled($entity) + { + $oid = spl_object_hash($entity); + + return isset($this->entityInsertions[$oid]) + || isset($this->entityUpdates[$oid]) + || isset($this->entityDeletions[$oid]); + } + + /** + * INTERNAL: + * Registers an entity in the identity map. + * Note that entities in a hierarchy are registered with the class name of + * the root entity. + * + * @ignore + * + * @param object $entity The entity to register. + * + * @return boolean TRUE if the registration was successful, FALSE if the identity of + * the entity in question is already managed. + * + * @throws ORMInvalidArgumentException + */ + public function addToIdentityMap($entity) + { + $classMetadata = $this->em->getClassMetadata(get_class($entity)); + $identifier = $this->entityIdentifiers[spl_object_hash($entity)]; + + if (empty($identifier) || in_array(null, $identifier, true)) { + throw ORMInvalidArgumentException::entityWithoutIdentity($classMetadata->name, $entity); + } + + $idHash = implode(' ', $identifier); + $className = $classMetadata->rootEntityName; + + if (isset($this->identityMap[$className][$idHash])) { + return false; + } + + $this->identityMap[$className][$idHash] = $entity; + + return true; + } + + /** + * Gets the state of an entity with regard to the current unit of work. + * + * @param object $entity + * @param int|null $assume The state to assume if the state is not yet known (not MANAGED or REMOVED). + * This parameter can be set to improve performance of entity state detection + * by potentially avoiding a database lookup if the distinction between NEW and DETACHED + * is either known or does not matter for the caller of the method. + * + * @return int The entity state. + */ + public function getEntityState($entity, $assume = null) + { + $oid = spl_object_hash($entity); + + if (isset($this->entityStates[$oid])) { + return $this->entityStates[$oid]; + } + + if ($assume !== null) { + return $assume; + } + + // State can only be NEW or DETACHED, because MANAGED/REMOVED states are known. + // Note that you can not remember the NEW or DETACHED state in _entityStates since + // the UoW does not hold references to such objects and the object hash can be reused. + // More generally because the state may "change" between NEW/DETACHED without the UoW being aware of it. + $class = $this->em->getClassMetadata(get_class($entity)); + $id = $class->getIdentifierValues($entity); + + if ( ! $id) { + return self::STATE_NEW; + } + + if ($class->containsForeignIdentifier) { + $id = $this->identifierFlattener->flattenIdentifier($class, $id); + } + + switch (true) { + case ($class->isIdentifierNatural()): + // Check for a version field, if available, to avoid a db lookup. + if ($class->isVersioned) { + return ($class->getFieldValue($entity, $class->versionField)) + ? self::STATE_DETACHED + : self::STATE_NEW; + } + + // Last try before db lookup: check the identity map. + if ($this->tryGetById($id, $class->rootEntityName)) { + return self::STATE_DETACHED; + } + + // db lookup + if ($this->getEntityPersister($class->name)->exists($entity)) { + return self::STATE_DETACHED; + } + + return self::STATE_NEW; + + case ( ! $class->idGenerator->isPostInsertGenerator()): + // if we have a pre insert generator we can't be sure that having an id + // really means that the entity exists. We have to verify this through + // the last resort: a db lookup + + // Last try before db lookup: check the identity map. + if ($this->tryGetById($id, $class->rootEntityName)) { + return self::STATE_DETACHED; + } + + // db lookup + if ($this->getEntityPersister($class->name)->exists($entity)) { + return self::STATE_DETACHED; + } + + return self::STATE_NEW; + + default: + return self::STATE_DETACHED; + } + } + + /** + * INTERNAL: + * Removes an entity from the identity map. This effectively detaches the + * entity from the persistence management of Doctrine. + * + * @ignore + * + * @param object $entity + * + * @return boolean + * + * @throws ORMInvalidArgumentException + */ + public function removeFromIdentityMap($entity) + { + $oid = spl_object_hash($entity); + $classMetadata = $this->em->getClassMetadata(get_class($entity)); + $idHash = implode(' ', $this->entityIdentifiers[$oid]); + + if ($idHash === '') { + throw ORMInvalidArgumentException::entityHasNoIdentity($entity, "remove from identity map"); + } + + $className = $classMetadata->rootEntityName; + + if (isset($this->identityMap[$className][$idHash])) { + unset($this->identityMap[$className][$idHash]); + unset($this->readOnlyObjects[$oid]); + + //$this->entityStates[$oid] = self::STATE_DETACHED; + + return true; + } + + return false; + } + + /** + * INTERNAL: + * Gets an entity in the identity map by its identifier hash. + * + * @ignore + * + * @param string $idHash + * @param string $rootClassName + * + * @return object + */ + public function getByIdHash($idHash, $rootClassName) + { + return $this->identityMap[$rootClassName][$idHash]; + } + + /** + * INTERNAL: + * Tries to get an entity by its identifier hash. If no entity is found for + * the given hash, FALSE is returned. + * + * @ignore + * + * @param mixed $idHash (must be possible to cast it to string) + * @param string $rootClassName + * + * @return object|bool The found entity or FALSE. + */ + public function tryGetByIdHash($idHash, $rootClassName) + { + $stringIdHash = (string) $idHash; + + return isset($this->identityMap[$rootClassName][$stringIdHash]) + ? $this->identityMap[$rootClassName][$stringIdHash] + : false; + } + + /** + * Checks whether an entity is registered in the identity map of this UnitOfWork. + * + * @param object $entity + * + * @return boolean + */ + public function isInIdentityMap($entity) + { + $oid = spl_object_hash($entity); + + if (empty($this->entityIdentifiers[$oid])) { + return false; + } + + $classMetadata = $this->em->getClassMetadata(get_class($entity)); + $idHash = implode(' ', $this->entityIdentifiers[$oid]); + + return isset($this->identityMap[$classMetadata->rootEntityName][$idHash]); + } + + /** + * INTERNAL: + * Checks whether an identifier hash exists in the identity map. + * + * @ignore + * + * @param string $idHash + * @param string $rootClassName + * + * @return boolean + */ + public function containsIdHash($idHash, $rootClassName) + { + return isset($this->identityMap[$rootClassName][$idHash]); + } + + /** + * Persists an entity as part of the current unit of work. + * + * @param object $entity The entity to persist. + * + * @return void + */ + public function persist($entity) + { + $visited = []; + + $this->doPersist($entity, $visited); + } + + /** + * Persists an entity as part of the current unit of work. + * + * This method is internally called during persist() cascades as it tracks + * the already visited entities to prevent infinite recursions. + * + * @param object $entity The entity to persist. + * @param array $visited The already visited entities. + * + * @return void + * + * @throws ORMInvalidArgumentException + * @throws UnexpectedValueException + */ + private function doPersist($entity, array &$visited) + { + $oid = spl_object_hash($entity); + + if (isset($visited[$oid])) { + return; // Prevent infinite recursion + } + + $visited[$oid] = $entity; // Mark visited + + $class = $this->em->getClassMetadata(get_class($entity)); + + // We assume NEW, so DETACHED entities result in an exception on flush (constraint violation). + // If we would detect DETACHED here we would throw an exception anyway with the same + // consequences (not recoverable/programming error), so just assuming NEW here + // lets us avoid some database lookups for entities with natural identifiers. + $entityState = $this->getEntityState($entity, self::STATE_NEW); + + switch ($entityState) { + case self::STATE_MANAGED: + // Nothing to do, except if policy is "deferred explicit" + if ($class->isChangeTrackingDeferredExplicit()) { + $this->scheduleForDirtyCheck($entity); + } + break; + + case self::STATE_NEW: + $this->persistNew($class, $entity); + break; + + case self::STATE_REMOVED: + // Entity becomes managed again + unset($this->entityDeletions[$oid]); + $this->addToIdentityMap($entity); + + $this->entityStates[$oid] = self::STATE_MANAGED; + break; + + case self::STATE_DETACHED: + // Can actually not happen right now since we assume STATE_NEW. + throw ORMInvalidArgumentException::detachedEntityCannot($entity, "persisted"); + + default: + throw new UnexpectedValueException("Unexpected entity state: $entityState." . self::objToStr($entity)); + } + + $this->cascadePersist($entity, $visited); + } + + /** + * Deletes an entity as part of the current unit of work. + * + * @param object $entity The entity to remove. + * + * @return void + */ + public function remove($entity) + { + $visited = []; + + $this->doRemove($entity, $visited); + } + + /** + * Deletes an entity as part of the current unit of work. + * + * This method is internally called during delete() cascades as it tracks + * the already visited entities to prevent infinite recursions. + * + * @param object $entity The entity to delete. + * @param array $visited The map of the already visited entities. + * + * @return void + * + * @throws ORMInvalidArgumentException If the instance is a detached entity. + * @throws UnexpectedValueException + */ + private function doRemove($entity, array &$visited) + { + $oid = spl_object_hash($entity); + + if (isset($visited[$oid])) { + return; // Prevent infinite recursion + } + + $visited[$oid] = $entity; // mark visited + + // Cascade first, because scheduleForDelete() removes the entity from the identity map, which + // can cause problems when a lazy proxy has to be initialized for the cascade operation. + $this->cascadeRemove($entity, $visited); + + $class = $this->em->getClassMetadata(get_class($entity)); + $entityState = $this->getEntityState($entity); + + switch ($entityState) { + case self::STATE_NEW: + case self::STATE_REMOVED: + // nothing to do + break; + + case self::STATE_MANAGED: + $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preRemove); + + if ($invoke !== ListenersInvoker::INVOKE_NONE) { + $this->listenersInvoker->invoke($class, Events::preRemove, $entity, new LifecycleEventArgs($entity, $this->em), $invoke); + } + + $this->scheduleForDelete($entity); + break; + + case self::STATE_DETACHED: + throw ORMInvalidArgumentException::detachedEntityCannot($entity, "removed"); + default: + throw new UnexpectedValueException("Unexpected entity state: $entityState." . self::objToStr($entity)); + } + + } + + /** + * Merges the state of the given detached entity into this UnitOfWork. + * + * @param object $entity + * + * @return object The managed copy of the entity. + * + * @throws OptimisticLockException If the entity uses optimistic locking through a version + * attribute and the version check against the managed copy fails. + * + * @deprecated 2.7 This method is being removed from the ORM and won't have any replacement + */ + public function merge($entity) + { + $visited = []; + + return $this->doMerge($entity, $visited); + } + + /** + * Executes a merge operation on an entity. + * + * @param object $entity + * @param array $visited + * @param object|null $prevManagedCopy + * @param array|null $assoc + * + * @return object The managed copy of the entity. + * + * @throws OptimisticLockException If the entity uses optimistic locking through a version + * attribute and the version check against the managed copy fails. + * @throws ORMInvalidArgumentException If the entity instance is NEW. + * @throws EntityNotFoundException if an assigned identifier is used in the entity, but none is provided + */ + private function doMerge($entity, array &$visited, $prevManagedCopy = null, array $assoc = []) + { + $oid = spl_object_hash($entity); + + if (isset($visited[$oid])) { + $managedCopy = $visited[$oid]; + + if ($prevManagedCopy !== null) { + $this->updateAssociationWithMergedEntity($entity, $assoc, $prevManagedCopy, $managedCopy); + } + + return $managedCopy; + } + + $class = $this->em->getClassMetadata(get_class($entity)); + + // First we assume DETACHED, although it can still be NEW but we can avoid + // an extra db-roundtrip this way. If it is not MANAGED but has an identity, + // we need to fetch it from the db anyway in order to merge. + // MANAGED entities are ignored by the merge operation. + $managedCopy = $entity; + + if ($this->getEntityState($entity, self::STATE_DETACHED) !== self::STATE_MANAGED) { + // Try to look the entity up in the identity map. + $id = $class->getIdentifierValues($entity); + + // If there is no ID, it is actually NEW. + if ( ! $id) { + $managedCopy = $this->newInstance($class); + + $this->mergeEntityStateIntoManagedCopy($entity, $managedCopy); + $this->persistNew($class, $managedCopy); + } else { + $flatId = ($class->containsForeignIdentifier) + ? $this->identifierFlattener->flattenIdentifier($class, $id) + : $id; + + $managedCopy = $this->tryGetById($flatId, $class->rootEntityName); + + if ($managedCopy) { + // We have the entity in-memory already, just make sure its not removed. + if ($this->getEntityState($managedCopy) == self::STATE_REMOVED) { + throw ORMInvalidArgumentException::entityIsRemoved($managedCopy, "merge"); + } + } else { + // We need to fetch the managed copy in order to merge. + $managedCopy = $this->em->find($class->name, $flatId); + } + + if ($managedCopy === null) { + // If the identifier is ASSIGNED, it is NEW, otherwise an error + // since the managed entity was not found. + if ( ! $class->isIdentifierNatural()) { + throw EntityNotFoundException::fromClassNameAndIdentifier( + $class->getName(), + $this->identifierFlattener->flattenIdentifier($class, $id) + ); + } + + $managedCopy = $this->newInstance($class); + $class->setIdentifierValues($managedCopy, $id); + + $this->mergeEntityStateIntoManagedCopy($entity, $managedCopy); + $this->persistNew($class, $managedCopy); + } else { + $this->ensureVersionMatch($class, $entity, $managedCopy); + $this->mergeEntityStateIntoManagedCopy($entity, $managedCopy); + } + } + + $visited[$oid] = $managedCopy; // mark visited + + if ($class->isChangeTrackingDeferredExplicit()) { + $this->scheduleForDirtyCheck($entity); + } + } + + if ($prevManagedCopy !== null) { + $this->updateAssociationWithMergedEntity($entity, $assoc, $prevManagedCopy, $managedCopy); + } + + // Mark the managed copy visited as well + $visited[spl_object_hash($managedCopy)] = $managedCopy; + + $this->cascadeMerge($entity, $managedCopy, $visited); + + return $managedCopy; + } + + /** + * @param ClassMetadata $class + * @param object $entity + * @param object $managedCopy + * + * @return void + * + * @throws OptimisticLockException + */ + private function ensureVersionMatch(ClassMetadata $class, $entity, $managedCopy) + { + if (! ($class->isVersioned && $this->isLoaded($managedCopy) && $this->isLoaded($entity))) { + return; + } + + $reflField = $class->reflFields[$class->versionField]; + $managedCopyVersion = $reflField->getValue($managedCopy); + $entityVersion = $reflField->getValue($entity); + + // Throw exception if versions don't match. + if ($managedCopyVersion == $entityVersion) { + return; + } + + throw OptimisticLockException::lockFailedVersionMismatch($entity, $entityVersion, $managedCopyVersion); + } + + /** + * Tests if an entity is loaded - must either be a loaded proxy or not a proxy + * + * @param object $entity + * + * @return bool + */ + private function isLoaded($entity) + { + return !($entity instanceof Proxy) || $entity->__isInitialized(); + } + + /** + * Sets/adds associated managed copies into the previous entity's association field + * + * @param object $entity + * @param array $association + * @param object $previousManagedCopy + * @param object $managedCopy + * + * @return void + */ + private function updateAssociationWithMergedEntity($entity, array $association, $previousManagedCopy, $managedCopy) + { + $assocField = $association['fieldName']; + $prevClass = $this->em->getClassMetadata(get_class($previousManagedCopy)); + + if ($association['type'] & ClassMetadata::TO_ONE) { + $prevClass->reflFields[$assocField]->setValue($previousManagedCopy, $managedCopy); + + return; + } + + $value = $prevClass->reflFields[$assocField]->getValue($previousManagedCopy); + $value[] = $managedCopy; + + if ($association['type'] == ClassMetadata::ONE_TO_MANY) { + $class = $this->em->getClassMetadata(get_class($entity)); + + $class->reflFields[$association['mappedBy']]->setValue($managedCopy, $previousManagedCopy); + } + } + + /** + * Detaches an entity from the persistence management. It's persistence will + * no longer be managed by Doctrine. + * + * @param object $entity The entity to detach. + * + * @return void + * + * @deprecated 2.7 This method is being removed from the ORM and won't have any replacement + */ + public function detach($entity) + { + $visited = []; + + $this->doDetach($entity, $visited); + } + + /** + * Executes a detach operation on the given entity. + * + * @param object $entity + * @param array $visited + * @param boolean $noCascade if true, don't cascade detach operation. + * + * @return void + */ + private function doDetach($entity, array &$visited, $noCascade = false) + { + $oid = spl_object_hash($entity); + + if (isset($visited[$oid])) { + return; // Prevent infinite recursion + } + + $visited[$oid] = $entity; // mark visited + + switch ($this->getEntityState($entity, self::STATE_DETACHED)) { + case self::STATE_MANAGED: + if ($this->isInIdentityMap($entity)) { + $this->removeFromIdentityMap($entity); + } + + unset( + $this->entityInsertions[$oid], + $this->entityUpdates[$oid], + $this->entityDeletions[$oid], + $this->entityIdentifiers[$oid], + $this->entityStates[$oid], + $this->originalEntityData[$oid] + ); + break; + case self::STATE_NEW: + case self::STATE_DETACHED: + return; + } + + if ( ! $noCascade) { + $this->cascadeDetach($entity, $visited); + } + } + + /** + * Refreshes the state of the given entity from the database, overwriting + * any local, unpersisted changes. + * + * @param object $entity The entity to refresh. + * + * @return void + * + * @throws InvalidArgumentException If the entity is not MANAGED. + */ + public function refresh($entity) + { + $visited = []; + + $this->doRefresh($entity, $visited); + } + + /** + * Executes a refresh operation on an entity. + * + * @param object $entity The entity to refresh. + * @param array $visited The already visited entities during cascades. + * + * @return void + * + * @throws ORMInvalidArgumentException If the entity is not MANAGED. + */ + private function doRefresh($entity, array &$visited) + { + $oid = spl_object_hash($entity); + + if (isset($visited[$oid])) { + return; // Prevent infinite recursion + } + + $visited[$oid] = $entity; // mark visited + + $class = $this->em->getClassMetadata(get_class($entity)); + + if ($this->getEntityState($entity) !== self::STATE_MANAGED) { + throw ORMInvalidArgumentException::entityNotManaged($entity); + } + + $this->getEntityPersister($class->name)->refresh( + array_combine($class->getIdentifierFieldNames(), $this->entityIdentifiers[$oid]), + $entity + ); + + $this->cascadeRefresh($entity, $visited); + } + + /** + * Cascades a refresh operation to associated entities. + * + * @param object $entity + * @param array $visited + * + * @return void + */ + private function cascadeRefresh($entity, array &$visited) + { + $class = $this->em->getClassMetadata(get_class($entity)); + + $associationMappings = array_filter( + $class->associationMappings, + function ($assoc) { return $assoc['isCascadeRefresh']; } + ); + + foreach ($associationMappings as $assoc) { + $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity); + + switch (true) { + case ($relatedEntities instanceof PersistentCollection): + // Unwrap so that foreach() does not initialize + $relatedEntities = $relatedEntities->unwrap(); + // break; is commented intentionally! + + case ($relatedEntities instanceof Collection): + case (is_array($relatedEntities)): + foreach ($relatedEntities as $relatedEntity) { + $this->doRefresh($relatedEntity, $visited); + } + break; + + case ($relatedEntities !== null): + $this->doRefresh($relatedEntities, $visited); + break; + + default: + // Do nothing + } + } + } + + /** + * Cascades a detach operation to associated entities. + * + * @param object $entity + * @param array $visited + * + * @return void + */ + private function cascadeDetach($entity, array &$visited) + { + $class = $this->em->getClassMetadata(get_class($entity)); + + $associationMappings = array_filter( + $class->associationMappings, + function ($assoc) { return $assoc['isCascadeDetach']; } + ); + + foreach ($associationMappings as $assoc) { + $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity); + + switch (true) { + case ($relatedEntities instanceof PersistentCollection): + // Unwrap so that foreach() does not initialize + $relatedEntities = $relatedEntities->unwrap(); + // break; is commented intentionally! + + case ($relatedEntities instanceof Collection): + case (is_array($relatedEntities)): + foreach ($relatedEntities as $relatedEntity) { + $this->doDetach($relatedEntity, $visited); + } + break; + + case ($relatedEntities !== null): + $this->doDetach($relatedEntities, $visited); + break; + + default: + // Do nothing + } + } + } + + /** + * Cascades a merge operation to associated entities. + * + * @param object $entity + * @param object $managedCopy + * @param array $visited + * + * @return void + */ + private function cascadeMerge($entity, $managedCopy, array &$visited) + { + $class = $this->em->getClassMetadata(get_class($entity)); + + $associationMappings = array_filter( + $class->associationMappings, + function ($assoc) { return $assoc['isCascadeMerge']; } + ); + + foreach ($associationMappings as $assoc) { + $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity); + + if ($relatedEntities instanceof Collection) { + if ($relatedEntities === $class->reflFields[$assoc['fieldName']]->getValue($managedCopy)) { + continue; + } + + if ($relatedEntities instanceof PersistentCollection) { + // Unwrap so that foreach() does not initialize + $relatedEntities = $relatedEntities->unwrap(); + } + + foreach ($relatedEntities as $relatedEntity) { + $this->doMerge($relatedEntity, $visited, $managedCopy, $assoc); + } + } else if ($relatedEntities !== null) { + $this->doMerge($relatedEntities, $visited, $managedCopy, $assoc); + } + } + } + + /** + * Cascades the save operation to associated entities. + * + * @param object $entity + * @param array $visited + * + * @return void + */ + private function cascadePersist($entity, array &$visited) + { + $class = $this->em->getClassMetadata(get_class($entity)); + + $associationMappings = array_filter( + $class->associationMappings, + function ($assoc) { return $assoc['isCascadePersist']; } + ); + + foreach ($associationMappings as $assoc) { + $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity); + + switch (true) { + case ($relatedEntities instanceof PersistentCollection): + // Unwrap so that foreach() does not initialize + $relatedEntities = $relatedEntities->unwrap(); + // break; is commented intentionally! + + case ($relatedEntities instanceof Collection): + case (is_array($relatedEntities)): + if (($assoc['type'] & ClassMetadata::TO_MANY) <= 0) { + throw ORMInvalidArgumentException::invalidAssociation( + $this->em->getClassMetadata($assoc['targetEntity']), + $assoc, + $relatedEntities + ); + } + + foreach ($relatedEntities as $relatedEntity) { + $this->doPersist($relatedEntity, $visited); + } + + break; + + case ($relatedEntities !== null): + if (! $relatedEntities instanceof $assoc['targetEntity']) { + throw ORMInvalidArgumentException::invalidAssociation( + $this->em->getClassMetadata($assoc['targetEntity']), + $assoc, + $relatedEntities + ); + } + + $this->doPersist($relatedEntities, $visited); + break; + + default: + // Do nothing + } + } + } + + /** + * Cascades the delete operation to associated entities. + * + * @param object $entity + * @param array $visited + * + * @return void + */ + private function cascadeRemove($entity, array &$visited) + { + $class = $this->em->getClassMetadata(get_class($entity)); + + $associationMappings = array_filter( + $class->associationMappings, + function ($assoc) { return $assoc['isCascadeRemove']; } + ); + + $entitiesToCascade = []; + + foreach ($associationMappings as $assoc) { + if ($entity instanceof Proxy && !$entity->__isInitialized__) { + $entity->__load(); + } + + $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity); + + switch (true) { + case ($relatedEntities instanceof Collection): + case (is_array($relatedEntities)): + // If its a PersistentCollection initialization is intended! No unwrap! + foreach ($relatedEntities as $relatedEntity) { + $entitiesToCascade[] = $relatedEntity; + } + break; + + case ($relatedEntities !== null): + $entitiesToCascade[] = $relatedEntities; + break; + + default: + // Do nothing + } + } + + foreach ($entitiesToCascade as $relatedEntity) { + $this->doRemove($relatedEntity, $visited); + } + } + + /** + * Acquire a lock on the given entity. + * + * @param object $entity + * @param int $lockMode + * @param int $lockVersion + * + * @return void + * + * @throws ORMInvalidArgumentException + * @throws TransactionRequiredException + * @throws OptimisticLockException + */ + public function lock($entity, $lockMode, $lockVersion = null) + { + if ($entity === null) { + throw new \InvalidArgumentException("No entity passed to UnitOfWork#lock()."); + } + + if ($this->getEntityState($entity, self::STATE_DETACHED) != self::STATE_MANAGED) { + throw ORMInvalidArgumentException::entityNotManaged($entity); + } + + $class = $this->em->getClassMetadata(get_class($entity)); + + switch (true) { + case LockMode::OPTIMISTIC === $lockMode: + if ( ! $class->isVersioned) { + throw OptimisticLockException::notVersioned($class->name); + } + + if ($lockVersion === null) { + return; + } + + if ($entity instanceof Proxy && !$entity->__isInitialized__) { + $entity->__load(); + } + + $entityVersion = $class->reflFields[$class->versionField]->getValue($entity); + + if ($entityVersion != $lockVersion) { + throw OptimisticLockException::lockFailedVersionMismatch($entity, $lockVersion, $entityVersion); + } + + break; + + case LockMode::NONE === $lockMode: + case LockMode::PESSIMISTIC_READ === $lockMode: + case LockMode::PESSIMISTIC_WRITE === $lockMode: + if (!$this->em->getConnection()->isTransactionActive()) { + throw TransactionRequiredException::transactionRequired(); + } + + $oid = spl_object_hash($entity); + + $this->getEntityPersister($class->name)->lock( + array_combine($class->getIdentifierFieldNames(), $this->entityIdentifiers[$oid]), + $lockMode + ); + break; + + default: + // Do nothing + } + } + + /** + * Gets the CommitOrderCalculator used by the UnitOfWork to order commits. + * + * @return \Doctrine\ORM\Internal\CommitOrderCalculator + */ + public function getCommitOrderCalculator() + { + return new Internal\CommitOrderCalculator(); + } + + /** + * Clears the UnitOfWork. + * + * @param string|null $entityName if given, only entities of this type will get detached. + * + * @return void + * + * @throws ORMInvalidArgumentException if an invalid entity name is given + */ + public function clear($entityName = null) + { + if ($entityName === null) { + $this->identityMap = + $this->entityIdentifiers = + $this->originalEntityData = + $this->entityChangeSets = + $this->entityStates = + $this->scheduledForSynchronization = + $this->entityInsertions = + $this->entityUpdates = + $this->entityDeletions = + $this->nonCascadedNewDetectedEntities = + $this->collectionDeletions = + $this->collectionUpdates = + $this->extraUpdates = + $this->readOnlyObjects = + $this->visitedCollections = + $this->eagerLoadingEntities = + $this->orphanRemovals = []; + } else { + $this->clearIdentityMapForEntityName($entityName); + $this->clearEntityInsertionsForEntityName($entityName); + } + + if ($this->evm->hasListeners(Events::onClear)) { + $this->evm->dispatchEvent(Events::onClear, new Event\OnClearEventArgs($this->em, $entityName)); + } + } + + /** + * INTERNAL: + * Schedules an orphaned entity for removal. The remove() operation will be + * invoked on that entity at the beginning of the next commit of this + * UnitOfWork. + * + * @ignore + * + * @param object $entity + * + * @return void + */ + public function scheduleOrphanRemoval($entity) + { + $this->orphanRemovals[spl_object_hash($entity)] = $entity; + } + + /** + * INTERNAL: + * Cancels a previously scheduled orphan removal. + * + * @ignore + * + * @param object $entity + * + * @return void + */ + public function cancelOrphanRemoval($entity) + { + unset($this->orphanRemovals[spl_object_hash($entity)]); + } + + /** + * INTERNAL: + * Schedules a complete collection for removal when this UnitOfWork commits. + * + * @param PersistentCollection $coll + * + * @return void + */ + public function scheduleCollectionDeletion(PersistentCollection $coll) + { + $coid = spl_object_hash($coll); + + // TODO: if $coll is already scheduled for recreation ... what to do? + // Just remove $coll from the scheduled recreations? + unset($this->collectionUpdates[$coid]); + + $this->collectionDeletions[$coid] = $coll; + } + + /** + * @param PersistentCollection $coll + * + * @return bool + */ + public function isCollectionScheduledForDeletion(PersistentCollection $coll) + { + return isset($this->collectionDeletions[spl_object_hash($coll)]); + } + + /** + * @param ClassMetadata $class + * + * @return \Doctrine\Common\Persistence\ObjectManagerAware|object + */ + private function newInstance($class) + { + $entity = $class->newInstance(); + + if ($entity instanceof \Doctrine\Common\Persistence\ObjectManagerAware) { + $entity->injectObjectManager($this->em, $class); + } + + return $entity; + } + + /** + * INTERNAL: + * Creates an entity. Used for reconstitution of persistent entities. + * + * Internal note: Highly performance-sensitive method. + * + * @ignore + * + * @param string $className The name of the entity class. + * @param array $data The data for the entity. + * @param array $hints Any hints to account for during reconstitution/lookup of the entity. + * + * @return object The managed entity instance. + * + * @todo Rename: getOrCreateEntity + */ + public function createEntity($className, array $data, &$hints = []) + { + $class = $this->em->getClassMetadata($className); + + $id = $this->identifierFlattener->flattenIdentifier($class, $data); + $idHash = implode(' ', $id); + + if (isset($this->identityMap[$class->rootEntityName][$idHash])) { + $entity = $this->identityMap[$class->rootEntityName][$idHash]; + $oid = spl_object_hash($entity); + + if ( + isset($hints[Query::HINT_REFRESH]) + && isset($hints[Query::HINT_REFRESH_ENTITY]) + && ($unmanagedProxy = $hints[Query::HINT_REFRESH_ENTITY]) !== $entity + && $unmanagedProxy instanceof Proxy + && $this->isIdentifierEquals($unmanagedProxy, $entity) + ) { + // DDC-1238 - we have a managed instance, but it isn't the provided one. + // Therefore we clear its identifier. Also, we must re-fetch metadata since the + // refreshed object may be anything + + foreach ($class->identifier as $fieldName) { + $class->reflFields[$fieldName]->setValue($unmanagedProxy, null); + } + + return $unmanagedProxy; + } + + if ($entity instanceof Proxy && ! $entity->__isInitialized()) { + $entity->__setInitialized(true); + + if ($entity instanceof NotifyPropertyChanged) { + $entity->addPropertyChangedListener($this); + } + } else { + if ( ! isset($hints[Query::HINT_REFRESH]) + || (isset($hints[Query::HINT_REFRESH_ENTITY]) && $hints[Query::HINT_REFRESH_ENTITY] !== $entity)) { + return $entity; + } + } + + // inject ObjectManager upon refresh. + if ($entity instanceof ObjectManagerAware) { + $entity->injectObjectManager($this->em, $class); + } + + $this->originalEntityData[$oid] = $data; + } else { + $entity = $this->newInstance($class); + $oid = spl_object_hash($entity); + + $this->entityIdentifiers[$oid] = $id; + $this->entityStates[$oid] = self::STATE_MANAGED; + $this->originalEntityData[$oid] = $data; + + $this->identityMap[$class->rootEntityName][$idHash] = $entity; + + if ($entity instanceof NotifyPropertyChanged) { + $entity->addPropertyChangedListener($this); + } + } + + foreach ($data as $field => $value) { + if (isset($class->fieldMappings[$field])) { + $class->reflFields[$field]->setValue($entity, $value); + } + } + + // Loading the entity right here, if its in the eager loading map get rid of it there. + unset($this->eagerLoadingEntities[$class->rootEntityName][$idHash]); + + if (isset($this->eagerLoadingEntities[$class->rootEntityName]) && ! $this->eagerLoadingEntities[$class->rootEntityName]) { + unset($this->eagerLoadingEntities[$class->rootEntityName]); + } + + // Properly initialize any unfetched associations, if partial objects are not allowed. + if (isset($hints[Query::HINT_FORCE_PARTIAL_LOAD])) { + return $entity; + } + + foreach ($class->associationMappings as $field => $assoc) { + // Check if the association is not among the fetch-joined associations already. + if (isset($hints['fetchAlias']) && isset($hints['fetched'][$hints['fetchAlias']][$field])) { + continue; + } + + $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); + + switch (true) { + case ($assoc['type'] & ClassMetadata::TO_ONE): + if ( ! $assoc['isOwningSide']) { + + // use the given entity association + if (isset($data[$field]) && is_object($data[$field]) && isset($this->entityStates[spl_object_hash($data[$field])])) { + + $this->originalEntityData[$oid][$field] = $data[$field]; + + $class->reflFields[$field]->setValue($entity, $data[$field]); + $targetClass->reflFields[$assoc['mappedBy']]->setValue($data[$field], $entity); + + continue 2; + } + + // Inverse side of x-to-one can never be lazy + $class->reflFields[$field]->setValue($entity, $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity)); + + continue 2; + } + + // use the entity association + if (isset($data[$field]) && is_object($data[$field]) && isset($this->entityStates[spl_object_hash($data[$field])])) { + $class->reflFields[$field]->setValue($entity, $data[$field]); + $this->originalEntityData[$oid][$field] = $data[$field]; + + break; + } + + $associatedId = []; + + // TODO: Is this even computed right in all cases of composite keys? + foreach ($assoc['targetToSourceKeyColumns'] as $targetColumn => $srcColumn) { + $joinColumnValue = $data[$srcColumn] ?? null; + + if ($joinColumnValue !== null) { + if ($targetClass->containsForeignIdentifier) { + $associatedId[$targetClass->getFieldForColumn($targetColumn)] = $joinColumnValue; + } else { + $associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue; + } + } elseif ($targetClass->containsForeignIdentifier + && in_array($targetClass->getFieldForColumn($targetColumn), $targetClass->identifier, true) + ) { + // the missing key is part of target's entity primary key + $associatedId = []; + break; + } + } + + if ( ! $associatedId) { + // Foreign key is NULL + $class->reflFields[$field]->setValue($entity, null); + $this->originalEntityData[$oid][$field] = null; + + break; + } + + if ( ! isset($hints['fetchMode'][$class->name][$field])) { + $hints['fetchMode'][$class->name][$field] = $assoc['fetch']; + } + + // Foreign key is set + // Check identity map first + // FIXME: Can break easily with composite keys if join column values are in + // wrong order. The correct order is the one in ClassMetadata#identifier. + $relatedIdHash = implode(' ', $associatedId); + + switch (true) { + case (isset($this->identityMap[$targetClass->rootEntityName][$relatedIdHash])): + $newValue = $this->identityMap[$targetClass->rootEntityName][$relatedIdHash]; + + // If this is an uninitialized proxy, we are deferring eager loads, + // this association is marked as eager fetch, and its an uninitialized proxy (wtf!) + // then we can append this entity for eager loading! + if ($hints['fetchMode'][$class->name][$field] == ClassMetadata::FETCH_EAGER && + isset($hints[self::HINT_DEFEREAGERLOAD]) && + !$targetClass->isIdentifierComposite && + $newValue instanceof Proxy && + $newValue->__isInitialized__ === false) { + + $this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId); + } + + break; + + case ($targetClass->subClasses): + // If it might be a subtype, it can not be lazy. There isn't even + // a way to solve this with deferred eager loading, which means putting + // an entity with subclasses at a *-to-one location is really bad! (performance-wise) + $newValue = $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity, $associatedId); + break; + + default: + switch (true) { + // We are negating the condition here. Other cases will assume it is valid! + case ($hints['fetchMode'][$class->name][$field] !== ClassMetadata::FETCH_EAGER): + $newValue = $this->em->getProxyFactory()->getProxy($assoc['targetEntity'], $associatedId); + break; + + // Deferred eager load only works for single identifier classes + case (isset($hints[self::HINT_DEFEREAGERLOAD]) && ! $targetClass->isIdentifierComposite): + // TODO: Is there a faster approach? + $this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId); + + $newValue = $this->em->getProxyFactory()->getProxy($assoc['targetEntity'], $associatedId); + break; + + default: + // TODO: This is very imperformant, ignore it? + $newValue = $this->em->find($assoc['targetEntity'], $associatedId); + break; + } + + // PERF: Inlined & optimized code from UnitOfWork#registerManaged() + $newValueOid = spl_object_hash($newValue); + $this->entityIdentifiers[$newValueOid] = $associatedId; + $this->identityMap[$targetClass->rootEntityName][$relatedIdHash] = $newValue; + + if ( + $newValue instanceof NotifyPropertyChanged && + ( ! $newValue instanceof Proxy || $newValue->__isInitialized()) + ) { + $newValue->addPropertyChangedListener($this); + } + $this->entityStates[$newValueOid] = self::STATE_MANAGED; + // make sure that when an proxy is then finally loaded, $this->originalEntityData is set also! + break; + } + + $this->originalEntityData[$oid][$field] = $newValue; + $class->reflFields[$field]->setValue($entity, $newValue); + + if ($assoc['inversedBy'] && $assoc['type'] & ClassMetadata::ONE_TO_ONE) { + $inverseAssoc = $targetClass->associationMappings[$assoc['inversedBy']]; + $targetClass->reflFields[$inverseAssoc['fieldName']]->setValue($newValue, $entity); + } + + break; + + default: + // Ignore if its a cached collection + if (isset($hints[Query::HINT_CACHE_ENABLED]) && $class->getFieldValue($entity, $field) instanceof PersistentCollection) { + break; + } + + // use the given collection + if (isset($data[$field]) && $data[$field] instanceof PersistentCollection) { + + $data[$field]->setOwner($entity, $assoc); + + $class->reflFields[$field]->setValue($entity, $data[$field]); + $this->originalEntityData[$oid][$field] = $data[$field]; + + break; + } + + // Inject collection + $pColl = new PersistentCollection($this->em, $targetClass, new ArrayCollection); + $pColl->setOwner($entity, $assoc); + $pColl->setInitialized(false); + + $reflField = $class->reflFields[$field]; + $reflField->setValue($entity, $pColl); + + if ($assoc['fetch'] == ClassMetadata::FETCH_EAGER) { + $this->loadCollection($pColl); + $pColl->takeSnapshot(); + } + + $this->originalEntityData[$oid][$field] = $pColl; + break; + } + } + + // defer invoking of postLoad event to hydration complete step + $this->hydrationCompleteHandler->deferPostLoadInvoking($class, $entity); + + return $entity; + } + + /** + * @return void + */ + public function triggerEagerLoads() + { + if ( ! $this->eagerLoadingEntities) { + return; + } + + // avoid infinite recursion + $eagerLoadingEntities = $this->eagerLoadingEntities; + $this->eagerLoadingEntities = []; + + foreach ($eagerLoadingEntities as $entityName => $ids) { + if ( ! $ids) { + continue; + } + + $class = $this->em->getClassMetadata($entityName); + + $this->getEntityPersister($entityName)->loadAll( + array_combine($class->identifier, [array_values($ids)]) + ); + } + } + + /** + * Initializes (loads) an uninitialized persistent collection of an entity. + * + * @param \Doctrine\ORM\PersistentCollection $collection The collection to initialize. + * + * @return void + * + * @todo Maybe later move to EntityManager#initialize($proxyOrCollection). See DDC-733. + */ + public function loadCollection(PersistentCollection $collection) + { + $assoc = $collection->getMapping(); + $persister = $this->getEntityPersister($assoc['targetEntity']); + + switch ($assoc['type']) { + case ClassMetadata::ONE_TO_MANY: + $persister->loadOneToManyCollection($assoc, $collection->getOwner(), $collection); + break; + + case ClassMetadata::MANY_TO_MANY: + $persister->loadManyToManyCollection($assoc, $collection->getOwner(), $collection); + break; + } + + $collection->setInitialized(true); + } + + /** + * Gets the identity map of the UnitOfWork. + * + * @return array + */ + public function getIdentityMap() + { + return $this->identityMap; + } + + /** + * Gets the original data of an entity. The original data is the data that was + * present at the time the entity was reconstituted from the database. + * + * @param object $entity + * + * @return array + */ + public function getOriginalEntityData($entity) + { + $oid = spl_object_hash($entity); + + return isset($this->originalEntityData[$oid]) + ? $this->originalEntityData[$oid] + : []; + } + + /** + * @ignore + * + * @param object $entity + * @param array $data + * + * @return void + */ + public function setOriginalEntityData($entity, array $data) + { + $this->originalEntityData[spl_object_hash($entity)] = $data; + } + + /** + * INTERNAL: + * Sets a property value of the original data array of an entity. + * + * @ignore + * + * @param string $oid + * @param string $property + * @param mixed $value + * + * @return void + */ + public function setOriginalEntityProperty($oid, $property, $value) + { + $this->originalEntityData[$oid][$property] = $value; + } + + /** + * Gets the identifier of an entity. + * The returned value is always an array of identifier values. If the entity + * has a composite identifier then the identifier values are in the same + * order as the identifier field names as returned by ClassMetadata#getIdentifierFieldNames(). + * + * @param object $entity + * + * @return array The identifier values. + */ + public function getEntityIdentifier($entity) + { + return $this->entityIdentifiers[spl_object_hash($entity)]; + } + + /** + * Processes an entity instance to extract their identifier values. + * + * @param object $entity The entity instance. + * + * @return mixed A scalar value. + * + * @throws \Doctrine\ORM\ORMInvalidArgumentException + */ + public function getSingleIdentifierValue($entity) + { + $class = $this->em->getClassMetadata(get_class($entity)); + + if ($class->isIdentifierComposite) { + throw ORMInvalidArgumentException::invalidCompositeIdentifier(); + } + + $values = $this->isInIdentityMap($entity) + ? $this->getEntityIdentifier($entity) + : $class->getIdentifierValues($entity); + + return isset($values[$class->identifier[0]]) ? $values[$class->identifier[0]] : null; + } + + /** + * Tries to find an entity with the given identifier in the identity map of + * this UnitOfWork. + * + * @param mixed $id The entity identifier to look for. + * @param string $rootClassName The name of the root class of the mapped entity hierarchy. + * + * @return object|bool Returns the entity with the specified identifier if it exists in + * this UnitOfWork, FALSE otherwise. + */ + public function tryGetById($id, $rootClassName) + { + $idHash = implode(' ', (array) $id); + + return isset($this->identityMap[$rootClassName][$idHash]) + ? $this->identityMap[$rootClassName][$idHash] + : false; + } + + /** + * Schedules an entity for dirty-checking at commit-time. + * + * @param object $entity The entity to schedule for dirty-checking. + * + * @return void + * + * @todo Rename: scheduleForSynchronization + */ + public function scheduleForDirtyCheck($entity) + { + $rootClassName = $this->em->getClassMetadata(get_class($entity))->rootEntityName; + + $this->scheduledForSynchronization[$rootClassName][spl_object_hash($entity)] = $entity; + } + + /** + * Checks whether the UnitOfWork has any pending insertions. + * + * @return boolean TRUE if this UnitOfWork has pending insertions, FALSE otherwise. + */ + public function hasPendingInsertions() + { + return ! empty($this->entityInsertions); + } + + /** + * Calculates the size of the UnitOfWork. The size of the UnitOfWork is the + * number of entities in the identity map. + * + * @return integer + */ + public function size() + { + $countArray = array_map('count', $this->identityMap); + + return array_sum($countArray); + } + + /** + * Gets the EntityPersister for an Entity. + * + * @param string $entityName The name of the Entity. + * + * @return \Doctrine\ORM\Persisters\Entity\EntityPersister + */ + public function getEntityPersister($entityName) + { + if (isset($this->persisters[$entityName])) { + return $this->persisters[$entityName]; + } + + $class = $this->em->getClassMetadata($entityName); + + switch (true) { + case ($class->isInheritanceTypeNone()): + $persister = new BasicEntityPersister($this->em, $class); + break; + + case ($class->isInheritanceTypeSingleTable()): + $persister = new SingleTablePersister($this->em, $class); + break; + + case ($class->isInheritanceTypeJoined()): + $persister = new JoinedSubclassPersister($this->em, $class); + break; + + default: + throw new \RuntimeException('No persister found for entity.'); + } + + if ($this->hasCache && $class->cache !== null) { + $persister = $this->em->getConfiguration() + ->getSecondLevelCacheConfiguration() + ->getCacheFactory() + ->buildCachedEntityPersister($this->em, $persister, $class); + } + + $this->persisters[$entityName] = $persister; + + return $this->persisters[$entityName]; + } + + /** + * Gets a collection persister for a collection-valued association. + * + * @param array $association + * + * @return \Doctrine\ORM\Persisters\Collection\CollectionPersister + */ + public function getCollectionPersister(array $association) + { + $role = isset($association['cache']) + ? $association['sourceEntity'] . '::' . $association['fieldName'] + : $association['type']; + + if (isset($this->collectionPersisters[$role])) { + return $this->collectionPersisters[$role]; + } + + $persister = ClassMetadata::ONE_TO_MANY === $association['type'] + ? new OneToManyPersister($this->em) + : new ManyToManyPersister($this->em); + + if ($this->hasCache && isset($association['cache'])) { + $persister = $this->em->getConfiguration() + ->getSecondLevelCacheConfiguration() + ->getCacheFactory() + ->buildCachedCollectionPersister($this->em, $persister, $association); + } + + $this->collectionPersisters[$role] = $persister; + + return $this->collectionPersisters[$role]; + } + + /** + * INTERNAL: + * Registers an entity as managed. + * + * @param object $entity The entity. + * @param array $id The identifier values. + * @param array $data The original entity data. + * + * @return void + */ + public function registerManaged($entity, array $id, array $data) + { + $oid = spl_object_hash($entity); + + $this->entityIdentifiers[$oid] = $id; + $this->entityStates[$oid] = self::STATE_MANAGED; + $this->originalEntityData[$oid] = $data; + + $this->addToIdentityMap($entity); + + if ($entity instanceof NotifyPropertyChanged && ( ! $entity instanceof Proxy || $entity->__isInitialized())) { + $entity->addPropertyChangedListener($this); + } + } + + /** + * INTERNAL: + * Clears the property changeset of the entity with the given OID. + * + * @param string $oid The entity's OID. + * + * @return void + */ + public function clearEntityChangeSet($oid) + { + unset($this->entityChangeSets[$oid]); + } + + /* PropertyChangedListener implementation */ + + /** + * Notifies this UnitOfWork of a property change in an entity. + * + * @param object $entity The entity that owns the property. + * @param string $propertyName The name of the property that changed. + * @param mixed $oldValue The old value of the property. + * @param mixed $newValue The new value of the property. + * + * @return void + */ + public function propertyChanged($entity, $propertyName, $oldValue, $newValue) + { + $oid = spl_object_hash($entity); + $class = $this->em->getClassMetadata(get_class($entity)); + + $isAssocField = isset($class->associationMappings[$propertyName]); + + if ( ! $isAssocField && ! isset($class->fieldMappings[$propertyName])) { + return; // ignore non-persistent fields + } + + // Update changeset and mark entity for synchronization + $this->entityChangeSets[$oid][$propertyName] = [$oldValue, $newValue]; + + if ( ! isset($this->scheduledForSynchronization[$class->rootEntityName][$oid])) { + $this->scheduleForDirtyCheck($entity); + } + } + + /** + * Gets the currently scheduled entity insertions in this UnitOfWork. + * + * @return array + */ + public function getScheduledEntityInsertions() + { + return $this->entityInsertions; + } + + /** + * Gets the currently scheduled entity updates in this UnitOfWork. + * + * @return array + */ + public function getScheduledEntityUpdates() + { + return $this->entityUpdates; + } + + /** + * Gets the currently scheduled entity deletions in this UnitOfWork. + * + * @return array + */ + public function getScheduledEntityDeletions() + { + return $this->entityDeletions; + } + + /** + * Gets the currently scheduled complete collection deletions + * + * @return array + */ + public function getScheduledCollectionDeletions() + { + return $this->collectionDeletions; + } + + /** + * Gets the currently scheduled collection inserts, updates and deletes. + * + * @return array + */ + public function getScheduledCollectionUpdates() + { + return $this->collectionUpdates; + } + + /** + * Helper method to initialize a lazy loading proxy or persistent collection. + * + * @param object $obj + * + * @return void + */ + public function initializeObject($obj) + { + if ($obj instanceof Proxy) { + $obj->__load(); + + return; + } + + if ($obj instanceof PersistentCollection) { + $obj->initialize(); + } + } + + /** + * Helper method to show an object as string. + * + * @param object $obj + * + * @return string + */ + private static function objToStr($obj) + { + return method_exists($obj, '__toString') ? (string) $obj : get_class($obj).'@'.spl_object_hash($obj); + } + + /** + * Marks an entity as read-only so that it will not be considered for updates during UnitOfWork#commit(). + * + * This operation cannot be undone as some parts of the UnitOfWork now keep gathering information + * on this object that might be necessary to perform a correct update. + * + * @param object $object + * + * @return void + * + * @throws ORMInvalidArgumentException + */ + public function markReadOnly($object) + { + if ( ! is_object($object) || ! $this->isInIdentityMap($object)) { + throw ORMInvalidArgumentException::readOnlyRequiresManagedEntity($object); + } + + $this->readOnlyObjects[spl_object_hash($object)] = true; + } + + /** + * Is this entity read only? + * + * @param object $object + * + * @return bool + * + * @throws ORMInvalidArgumentException + */ + public function isReadOnly($object) + { + if ( ! is_object($object)) { + throw ORMInvalidArgumentException::readOnlyRequiresManagedEntity($object); + } + + return isset($this->readOnlyObjects[spl_object_hash($object)]); + } + + /** + * Perform whatever processing is encapsulated here after completion of the transaction. + */ + private function afterTransactionComplete() + { + $this->performCallbackOnCachedPersister(function (CachedPersister $persister) { + $persister->afterTransactionComplete(); + }); + } + + /** + * Perform whatever processing is encapsulated here after completion of the rolled-back. + */ + private function afterTransactionRolledBack() + { + $this->performCallbackOnCachedPersister(function (CachedPersister $persister) { + $persister->afterTransactionRolledBack(); + }); + } + + /** + * Performs an action after the transaction. + * + * @param callable $callback + */ + private function performCallbackOnCachedPersister(callable $callback) + { + if ( ! $this->hasCache) { + return; + } + + foreach (array_merge($this->persisters, $this->collectionPersisters) as $persister) { + if ($persister instanceof CachedPersister) { + $callback($persister); + } + } + } + + private function dispatchOnFlushEvent() + { + if ($this->evm->hasListeners(Events::onFlush)) { + $this->evm->dispatchEvent(Events::onFlush, new OnFlushEventArgs($this->em)); + } + } + + private function dispatchPostFlushEvent() + { + if ($this->evm->hasListeners(Events::postFlush)) { + $this->evm->dispatchEvent(Events::postFlush, new PostFlushEventArgs($this->em)); + } + } + + /** + * Verifies if two given entities actually are the same based on identifier comparison + * + * @param object $entity1 + * @param object $entity2 + * + * @return bool + */ + private function isIdentifierEquals($entity1, $entity2) + { + if ($entity1 === $entity2) { + return true; + } + + $class = $this->em->getClassMetadata(get_class($entity1)); + + if ($class !== $this->em->getClassMetadata(get_class($entity2))) { + return false; + } + + $oid1 = spl_object_hash($entity1); + $oid2 = spl_object_hash($entity2); + + $id1 = isset($this->entityIdentifiers[$oid1]) + ? $this->entityIdentifiers[$oid1] + : $this->identifierFlattener->flattenIdentifier($class, $class->getIdentifierValues($entity1)); + $id2 = isset($this->entityIdentifiers[$oid2]) + ? $this->entityIdentifiers[$oid2] + : $this->identifierFlattener->flattenIdentifier($class, $class->getIdentifierValues($entity2)); + + return $id1 === $id2 || implode(' ', $id1) === implode(' ', $id2); + } + + /** + * @throws ORMInvalidArgumentException + */ + private function assertThatThereAreNoUnintentionallyNonPersistedAssociations() : void + { + $entitiesNeedingCascadePersist = \array_diff_key($this->nonCascadedNewDetectedEntities, $this->entityInsertions); + + $this->nonCascadedNewDetectedEntities = []; + + if ($entitiesNeedingCascadePersist) { + throw ORMInvalidArgumentException::newEntitiesFoundThroughRelationships( + \array_values($entitiesNeedingCascadePersist) + ); + } + } + + /** + * @param object $entity + * @param object $managedCopy + * + * @throws ORMException + * @throws OptimisticLockException + * @throws TransactionRequiredException + */ + private function mergeEntityStateIntoManagedCopy($entity, $managedCopy) + { + if (! $this->isLoaded($entity)) { + return; + } + + if (! $this->isLoaded($managedCopy)) { + $managedCopy->__load(); + } + + $class = $this->em->getClassMetadata(get_class($entity)); + + foreach ($this->reflectionPropertiesGetter->getProperties($class->name) as $prop) { + $name = $prop->name; + + $prop->setAccessible(true); + + if ( ! isset($class->associationMappings[$name])) { + if ( ! $class->isIdentifier($name)) { + $prop->setValue($managedCopy, $prop->getValue($entity)); + } + } else { + $assoc2 = $class->associationMappings[$name]; + + if ($assoc2['type'] & ClassMetadata::TO_ONE) { + $other = $prop->getValue($entity); + if ($other === null) { + $prop->setValue($managedCopy, null); + } else { + if ($other instanceof Proxy && !$other->__isInitialized()) { + // do not merge fields marked lazy that have not been fetched. + continue; + } + + if ( ! $assoc2['isCascadeMerge']) { + if ($this->getEntityState($other) === self::STATE_DETACHED) { + $targetClass = $this->em->getClassMetadata($assoc2['targetEntity']); + $relatedId = $targetClass->getIdentifierValues($other); + + if ($targetClass->subClasses) { + $other = $this->em->find($targetClass->name, $relatedId); + } else { + $other = $this->em->getProxyFactory()->getProxy( + $assoc2['targetEntity'], + $relatedId + ); + $this->registerManaged($other, $relatedId, []); + } + } + + $prop->setValue($managedCopy, $other); + } + } + } else { + $mergeCol = $prop->getValue($entity); + + if ($mergeCol instanceof PersistentCollection && ! $mergeCol->isInitialized()) { + // do not merge fields marked lazy that have not been fetched. + // keep the lazy persistent collection of the managed copy. + continue; + } + + $managedCol = $prop->getValue($managedCopy); + + if ( ! $managedCol) { + $managedCol = new PersistentCollection( + $this->em, + $this->em->getClassMetadata($assoc2['targetEntity']), + new ArrayCollection + ); + $managedCol->setOwner($managedCopy, $assoc2); + $prop->setValue($managedCopy, $managedCol); + } + + if ($assoc2['isCascadeMerge']) { + $managedCol->initialize(); + + // clear and set dirty a managed collection if its not also the same collection to merge from. + if ( ! $managedCol->isEmpty() && $managedCol !== $mergeCol) { + $managedCol->unwrap()->clear(); + $managedCol->setDirty(true); + + if ($assoc2['isOwningSide'] + && $assoc2['type'] == ClassMetadata::MANY_TO_MANY + && $class->isChangeTrackingNotify() + ) { + $this->scheduleForDirtyCheck($managedCopy); + } + } + } + } + } + + if ($class->isChangeTrackingNotify()) { + // Just treat all properties as changed, there is no other choice. + $this->propertyChanged($managedCopy, $name, null, $prop->getValue($managedCopy)); + } + } + } + + /** + * This method called by hydrators, and indicates that hydrator totally completed current hydration cycle. + * Unit of work able to fire deferred events, related to loading events here. + * + * @internal should be called internally from object hydrators + */ + public function hydrationComplete() + { + $this->hydrationCompleteHandler->hydrationComplete(); + } + + /** + * @param string $entityName + */ + private function clearIdentityMapForEntityName($entityName) + { + if (! isset($this->identityMap[$entityName])) { + return; + } + + $visited = []; + + foreach ($this->identityMap[$entityName] as $entity) { + $this->doDetach($entity, $visited, false); + } + } + + /** + * @param string $entityName + */ + private function clearEntityInsertionsForEntityName($entityName) + { + foreach ($this->entityInsertions as $hash => $entity) { + // note: performance optimization - `instanceof` is much faster than a function call + if ($entity instanceof $entityName && get_class($entity) === $entityName) { + unset($this->entityInsertions[$hash]); + } + } + } + + /** + * @param ClassMetadata $class + * @param mixed $identifierValue + * + * @return mixed the identifier after type conversion + * + * @throws \Doctrine\ORM\Mapping\MappingException if the entity has more than a single identifier + */ + private function convertSingleFieldIdentifierToPHPValue(ClassMetadata $class, $identifierValue) + { + return $this->em->getConnection()->convertToPHPValue( + $identifierValue, + $class->getTypeOfField($class->getSingleIdentifierFieldName()) + ); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/HierarchyDiscriminatorResolver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/HierarchyDiscriminatorResolver.php new file mode 100644 index 0000000..9b08b7f --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/HierarchyDiscriminatorResolver.php @@ -0,0 +1,41 @@ +subClasses; + $hierarchyClasses[] = $rootClassMetadata->name; + + $discriminators = []; + + foreach ($hierarchyClasses as $class) { + $currentMetadata = $entityManager->getClassMetadata($class); + $currentDiscriminator = $currentMetadata->discriminatorValue; + + if (null !== $currentDiscriminator) { + $discriminators[$currentDiscriminator] = null; + } + } + + return $discriminators; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/IdentifierFlattener.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/IdentifierFlattener.php new file mode 100644 index 0000000..a283a68 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/IdentifierFlattener.php @@ -0,0 +1,102 @@ +. + */ + +namespace Doctrine\ORM\Utility; + +use Doctrine\ORM\UnitOfWork; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory; + +/** + * The IdentifierFlattener utility now houses some of the identifier manipulation logic from unit of work, so that it + * can be re-used elsewhere. + * + * @since 2.5 + * @author Rob Caiger + */ +final class IdentifierFlattener +{ + /** + * The UnitOfWork used to coordinate object-level transactions. + * + * @var UnitOfWork + */ + private $unitOfWork; + + /** + * The metadata factory, used to retrieve the ORM metadata of entity classes. + * + * @var ClassMetadataFactory + */ + private $metadataFactory; + + /** + * Initializes a new IdentifierFlattener instance, bound to the given EntityManager. + * + * @param UnitOfWork $unitOfWork + * @param ClassMetadataFactory $metadataFactory + */ + public function __construct(UnitOfWork $unitOfWork, ClassMetadataFactory $metadataFactory) + { + $this->unitOfWork = $unitOfWork; + $this->metadataFactory = $metadataFactory; + } + + /** + * convert foreign identifiers into scalar foreign key values to avoid object to string conversion failures. + * + * @param ClassMetadata $class + * @param array $id + * + * @return array + */ + public function flattenIdentifier(ClassMetadata $class, array $id) + { + $flatId = []; + + foreach ($class->identifier as $field) { + if (isset($class->associationMappings[$field]) && isset($id[$field]) && is_object($id[$field])) { + /* @var $targetClassMetadata ClassMetadata */ + $targetClassMetadata = $this->metadataFactory->getMetadataFor( + $class->associationMappings[$field]['targetEntity'] + ); + + if ($this->unitOfWork->isInIdentityMap($id[$field])) { + $associatedId = $this->flattenIdentifier($targetClassMetadata, $this->unitOfWork->getEntityIdentifier($id[$field])); + } else { + $associatedId = $this->flattenIdentifier($targetClassMetadata, $targetClassMetadata->getIdentifierValues($id[$field])); + } + + $flatId[$field] = implode(' ', $associatedId); + } elseif (isset($class->associationMappings[$field])) { + $associatedId = []; + + foreach ($class->associationMappings[$field]['joinColumns'] as $joinColumn) { + $associatedId[] = $id[$joinColumn['name']]; + } + + $flatId[$field] = implode(' ', $associatedId); + } else { + $flatId[$field] = $id[$field]; + } + } + + return $flatId; + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/PersisterHelper.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/PersisterHelper.php new file mode 100644 index 0000000..fc6e492 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/PersisterHelper.php @@ -0,0 +1,135 @@ +. + */ + +namespace Doctrine\ORM\Utility; + +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Query\QueryException; + +/** + * The PersisterHelper contains logic to infer binding types which is used in + * several persisters. + * + * @link www.doctrine-project.org + * @since 2.5 + * @author Jasper N. Brouwer + */ +class PersisterHelper +{ + /** + * @param string $fieldName + * @param ClassMetadata $class + * @param EntityManagerInterface $em + * + * @return array + * + * @throws QueryException + */ + public static function getTypeOfField($fieldName, ClassMetadata $class, EntityManagerInterface $em) + { + if (isset($class->fieldMappings[$fieldName])) { + return [$class->fieldMappings[$fieldName]['type']]; + } + + if ( ! isset($class->associationMappings[$fieldName])) { + return []; + } + + $assoc = $class->associationMappings[$fieldName]; + + if (! $assoc['isOwningSide']) { + return self::getTypeOfField($assoc['mappedBy'], $em->getClassMetadata($assoc['targetEntity']), $em); + } + + if ($assoc['type'] & ClassMetadata::MANY_TO_MANY) { + $joinData = $assoc['joinTable']; + } else { + $joinData = $assoc; + } + + $types = []; + $targetClass = $em->getClassMetadata($assoc['targetEntity']); + + foreach ($joinData['joinColumns'] as $joinColumn) { + $types[] = self::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $em); + } + + return $types; + } + + /** + * @param string $columnName + * @param ClassMetadata $class + * @param EntityManagerInterface $em + * + * @return string + * + * @throws \RuntimeException + */ + public static function getTypeOfColumn($columnName, ClassMetadata $class, EntityManagerInterface $em) + { + if (isset($class->fieldNames[$columnName])) { + $fieldName = $class->fieldNames[$columnName]; + + if (isset($class->fieldMappings[$fieldName])) { + return $class->fieldMappings[$fieldName]['type']; + } + } + + // iterate over to-one association mappings + foreach ($class->associationMappings as $assoc) { + if ( ! isset($assoc['joinColumns'])) { + continue; + } + + foreach ($assoc['joinColumns'] as $joinColumn) { + if ($joinColumn['name'] == $columnName) { + $targetColumnName = $joinColumn['referencedColumnName']; + $targetClass = $em->getClassMetadata($assoc['targetEntity']); + + return self::getTypeOfColumn($targetColumnName, $targetClass, $em); + } + } + } + + // iterate over to-many association mappings + foreach ($class->associationMappings as $assoc) { + if ( ! (isset($assoc['joinTable']) && isset($assoc['joinTable']['joinColumns']))) { + continue; + } + + foreach ($assoc['joinTable']['joinColumns'] as $joinColumn) { + if ($joinColumn['name'] == $columnName) { + $targetColumnName = $joinColumn['referencedColumnName']; + $targetClass = $em->getClassMetadata($assoc['targetEntity']); + + return self::getTypeOfColumn($targetColumnName, $targetClass, $em); + } + } + } + + throw new \RuntimeException(sprintf( + 'Could not resolve type of column "%s" of class "%s"', + $columnName, + $class->getName() + )); + } +} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Version.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Version.php new file mode 100644 index 0000000..1af5517 --- /dev/null +++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Version.php @@ -0,0 +1,57 @@ +. + */ + +namespace Doctrine\ORM; + +/** + * Class to store and retrieve the version of Doctrine + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * + * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement + */ +class Version +{ + /** + * Current Doctrine Version + */ + const VERSION = '2.7.0'; + + /** + * 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); + } +} diff --git a/vendor/doctrine/orm/phpbench.json b/vendor/doctrine/orm/phpbench.json new file mode 100644 index 0000000..74fdef4 --- /dev/null +++ b/vendor/doctrine/orm/phpbench.json @@ -0,0 +1,15 @@ +{ + "bootstrap": "vendor/autoload.php", + "path": "tests/Doctrine/Performance", + + "extensions": [ + "PhpBench\\Extensions\\Dbal\\DbalExtension", + "PhpBench\\Extensions\\XDebug\\XDebugExtension" + ], + + "storage": "dbal", + "storage.dbal.connection": { + "driver": "pdo_sqlite", + "path": "tests/Doctrine/Performance/history.db" + } +} diff --git a/vendor/doctrine/orm/phpstan.neon b/vendor/doctrine/orm/phpstan.neon new file mode 100644 index 0000000..4046aa1 --- /dev/null +++ b/vendor/doctrine/orm/phpstan.neon @@ -0,0 +1,4 @@ +parameters: + earlyTerminatingMethodCalls: + Doctrine\ORM\Query\Parser: + - syntaxError diff --git a/vendor/doctrine/persistence/.doctrine-project.json b/vendor/doctrine/persistence/.doctrine-project.json new file mode 100644 index 0000000..cfeefa4 --- /dev/null +++ b/vendor/doctrine/persistence/.doctrine-project.json @@ -0,0 +1,24 @@ +{ + "active": true, + "name": "Persistence", + "slug": "persistence", + "docsSlug": "doctrine-persistence", + "versions": [ + { + "name": "1.1", + "branchName": "1.1.x", + "slug": "latest", + "current": true, + "aliases": [ + "current", + "stable" + ] + }, + { + "name": "1.0", + "branchName": "1.0.x", + "slug": "1.0", + "maintained": false + } + ] +} diff --git a/vendor/doctrine/persistence/LICENSE b/vendor/doctrine/persistence/LICENSE new file mode 100644 index 0000000..8c38cc1 --- /dev/null +++ b/vendor/doctrine/persistence/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2015 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/doctrine/persistence/README.md b/vendor/doctrine/persistence/README.md new file mode 100644 index 0000000..b5d32d5 --- /dev/null +++ b/vendor/doctrine/persistence/README.md @@ -0,0 +1,13 @@ +# Doctrine Persistence + +[![Build Status](https://travis-ci.org/doctrine/persistence.svg)](https://travis-ci.org/doctrine/persistence) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/persistence/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/persistence/?branch=master) +[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/persistence/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/persistence/?branch=master) + +The Doctrine Persistence project is a library that provides common abstractions for object mapper persistence. + +## More resources: + +* [Website](https://www.doctrine-project.org/) +* [Documentation](https://www.doctrine-project.org/projects/doctrine-persistence/en/latest/index.html) +* [Downloads](https://github.com/doctrine/persistence/releases) diff --git a/vendor/doctrine/persistence/UPGRADE-1.2.md b/vendor/doctrine/persistence/UPGRADE-1.2.md new file mode 100644 index 0000000..0c0115d --- /dev/null +++ b/vendor/doctrine/persistence/UPGRADE-1.2.md @@ -0,0 +1,6 @@ +UPGRADE FROM 1.x to 1.2 +======================= + +* Deprecated `ObjectManager::merge()`. Please handle merge operations in your application instead. +* Deprecated `ObjectManager::detach()`. Please use `ObjectManager::clear()` instead. +* Deprecated `PersistentObject` class. Please implement this functionality directly in your application if you want ActiveRecord style functionality. diff --git a/vendor/doctrine/persistence/composer.json b/vendor/doctrine/persistence/composer.json new file mode 100644 index 0000000..10704f1 --- /dev/null +++ b/vendor/doctrine/persistence/composer.json @@ -0,0 +1,54 @@ +{ + "name": "doctrine/persistence", + "type": "library", + "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", + "keywords": [ + "persistence", + "object", + "mapper", + "orm", + "odm" + ], + "homepage": "https://doctrine-project.org/projects/persistence.html", + "license": "MIT", + "authors": [ + {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, + {"name": "Roman Borschel", "email": "roman@code-factory.org"}, + {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, + {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, + {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}, + {"name": "Marco Pivetta", "email": "ocramius@gmail.com"} + ], + "require": { + "php": "^7.1", + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/reflection": "^1.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.11", + "doctrine/coding-standard": "^6.0", + "phpunit/phpunit": "^7.0" + }, + "conflict": { + "doctrine/common": "<2.10@dev" + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common", + "Doctrine\\Persistence\\": "lib/Doctrine/Persistence" + } + }, + "autoload-dev": { + "psr-4": { + "Doctrine\\Tests\\": "tests/Doctrine/Tests" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + } +} diff --git a/vendor/doctrine/persistence/lib/Doctrine/Common/NotifyPropertyChanged.php b/vendor/doctrine/persistence/lib/Doctrine/Common/NotifyPropertyChanged.php new file mode 100644 index 0000000..b570bb8 --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Common/NotifyPropertyChanged.php @@ -0,0 +1,31 @@ +getId(); // method exists through __call + */ +abstract class PersistentObject implements ObjectManagerAware +{ + /** @var ObjectManager|null */ + private static $objectManager = null; + + /** @var ClassMetadata|null */ + private $cm = null; + + /** + * Sets the object manager responsible for all persistent object base classes. + * + * @return void + */ + public static function setObjectManager(?ObjectManager $objectManager = null) + { + self::$objectManager = $objectManager; + } + + /** + * @return ObjectManager|null + */ + public static function getObjectManager() + { + return self::$objectManager; + } + + /** + * Injects the Doctrine Object Manager. + * + * @return void + * + * @throws RuntimeException + */ + public function injectObjectManager(ObjectManager $objectManager, ClassMetadata $classMetadata) + { + if ($objectManager !== self::$objectManager) { + throw new RuntimeException('Trying to use PersistentObject with different ObjectManager instances. ' . + 'Was PersistentObject::setObjectManager() called?'); + } + + $this->cm = $classMetadata; + } + + /** + * Sets a persistent fields value. + * + * @param string $field + * @param mixed[] $args + * + * @return void + * + * @throws BadMethodCallException When no persistent field exists by that name. + * @throws InvalidArgumentException When the wrong target object type is passed to an association. + */ + private function set($field, $args) + { + if ($this->cm->hasField($field) && ! $this->cm->isIdentifier($field)) { + $this->$field = $args[0]; + } elseif ($this->cm->hasAssociation($field) && $this->cm->isSingleValuedAssociation($field)) { + $targetClass = $this->cm->getAssociationTargetClass($field); + if (! ($args[0] instanceof $targetClass) && $args[0] !== null) { + throw new InvalidArgumentException("Expected persistent object of type '" . $targetClass . "'"); + } + $this->$field = $args[0]; + $this->completeOwningSide($field, $targetClass, $args[0]); + } else { + throw new BadMethodCallException("no field with name '" . $field . "' exists on '" . $this->cm->getName() . "'"); + } + } + + /** + * Gets a persistent field value. + * + * @param string $field + * + * @return mixed + * + * @throws BadMethodCallException When no persistent field exists by that name. + */ + private function get($field) + { + if ($this->cm->hasField($field) || $this->cm->hasAssociation($field)) { + return $this->$field; + } + + throw new BadMethodCallException("no field with name '" . $field . "' exists on '" . $this->cm->getName() . "'"); + } + + /** + * If this is an inverse side association, completes the owning side. + * + * @param string $field + * @param ClassMetadata $targetClass + * @param object $targetObject + * + * @return void + */ + private function completeOwningSide($field, $targetClass, $targetObject) + { + // add this object on the owning side as well, for obvious infinite recursion + // reasons this is only done when called on the inverse side. + if (! $this->cm->isAssociationInverseSide($field)) { + return; + } + + $mappedByField = $this->cm->getAssociationMappedByTargetField($field); + $targetMetadata = self::$objectManager->getClassMetadata($targetClass); + + $setter = ($targetMetadata->isCollectionValuedAssociation($mappedByField) ? 'add' : 'set') . $mappedByField; + $targetObject->$setter($this); + } + + /** + * Adds an object to a collection. + * + * @param string $field + * @param mixed[] $args + * + * @return void + * + * @throws BadMethodCallException + * @throws InvalidArgumentException + */ + private function add($field, $args) + { + if (! $this->cm->hasAssociation($field) || ! $this->cm->isCollectionValuedAssociation($field)) { + throw new BadMethodCallException('There is no method add' . $field . '() on ' . $this->cm->getName()); + } + + $targetClass = $this->cm->getAssociationTargetClass($field); + if (! ($args[0] instanceof $targetClass)) { + throw new InvalidArgumentException("Expected persistent object of type '" . $targetClass . "'"); + } + if (! ($this->$field instanceof Collection)) { + $this->$field = new ArrayCollection($this->$field ?: []); + } + $this->$field->add($args[0]); + $this->completeOwningSide($field, $targetClass, $args[0]); + } + + /** + * Initializes Doctrine Metadata for this class. + * + * @return void + * + * @throws RuntimeException + */ + private function initializeDoctrine() + { + if ($this->cm !== null) { + return; + } + + if (! self::$objectManager) { + throw new RuntimeException('No runtime object manager set. Call PersistentObject#setObjectManager().'); + } + + $this->cm = self::$objectManager->getClassMetadata(static::class); + } + + /** + * Magic methods. + * + * @param string $method + * @param mixed[] $args + * + * @return mixed + * + * @throws BadMethodCallException + */ + public function __call($method, $args) + { + $this->initializeDoctrine(); + + $command = substr($method, 0, 3); + $field = lcfirst(substr($method, 3)); + if ($command === 'set') { + $this->set($field, $args); + } elseif ($command === 'get') { + return $this->get($field); + } elseif ($command === 'add') { + $this->add($field, $args); + } else { + throw new BadMethodCallException('There is no method ' . $method . ' on ' . $this->cm->getName()); + } + } +} + +class_exists(\Doctrine\Common\Persistence\PersistentObject::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Proxy.php b/vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Proxy.php new file mode 100644 index 0000000..e7a31eb --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Proxy.php @@ -0,0 +1,31 @@ +name = $name; + $this->connections = $connections; + $this->managers = $managers; + $this->defaultConnection = $defaultConnection; + $this->defaultManager = $defaultManager; + $this->proxyInterfaceName = $proxyInterfaceName; + } + + /** + * Fetches/creates the given services. + * + * A service in this context is connection or a manager instance. + * + * @param string $name The name of the service. + * + * @return ObjectManager The instance of the given service. + */ + abstract protected function getService($name); + + /** + * Resets the given services. + * + * A service in this context is connection or a manager instance. + * + * @param string $name The name of the service. + * + * @return void + */ + abstract protected function resetService($name); + + /** + * Gets the name of the registry. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function getConnection($name = null) + { + if ($name === null) { + $name = $this->defaultConnection; + } + + if (! isset($this->connections[$name])) { + throw new InvalidArgumentException(sprintf('Doctrine %s Connection named "%s" does not exist.', $this->name, $name)); + } + + return $this->getService($this->connections[$name]); + } + + /** + * {@inheritdoc} + */ + public function getConnectionNames() + { + return $this->connections; + } + + /** + * {@inheritdoc} + */ + public function getConnections() + { + $connections = []; + foreach ($this->connections as $name => $id) { + $connections[$name] = $this->getService($id); + } + + return $connections; + } + + /** + * {@inheritdoc} + */ + public function getDefaultConnectionName() + { + return $this->defaultConnection; + } + + /** + * {@inheritdoc} + */ + public function getDefaultManagerName() + { + return $this->defaultManager; + } + + /** + * {@inheritdoc} + * + * @throws InvalidArgumentException + */ + public function getManager($name = null) + { + if ($name === null) { + $name = $this->defaultManager; + } + + if (! isset($this->managers[$name])) { + throw new InvalidArgumentException(sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name)); + } + + return $this->getService($this->managers[$name]); + } + + /** + * {@inheritdoc} + */ + public function getManagerForClass($class) + { + // Check for namespace alias + if (strpos($class, ':') !== false) { + [$namespaceAlias, $simpleClassName] = explode(':', $class, 2); + $class = $this->getAliasNamespace($namespaceAlias) . '\\' . $simpleClassName; + } + + $proxyClass = new ReflectionClass($class); + + if ($proxyClass->implementsInterface($this->proxyInterfaceName)) { + $parentClass = $proxyClass->getParentClass(); + + if (! $parentClass) { + return null; + } + + $class = $parentClass->getName(); + } + + foreach ($this->managers as $id) { + $manager = $this->getService($id); + + if (! $manager->getMetadataFactory()->isTransient($class)) { + return $manager; + } + } + } + + /** + * {@inheritdoc} + */ + public function getManagerNames() + { + return $this->managers; + } + + /** + * {@inheritdoc} + */ + public function getManagers() + { + $dms = []; + foreach ($this->managers as $name => $id) { + $dms[$name] = $this->getService($id); + } + + return $dms; + } + + /** + * {@inheritdoc} + */ + public function getRepository($persistentObjectName, $persistentManagerName = null) + { + return $this + ->selectManager($persistentObjectName, $persistentManagerName) + ->getRepository($persistentObjectName); + } + + /** + * {@inheritdoc} + */ + public function resetManager($name = null) + { + if ($name === null) { + $name = $this->defaultManager; + } + + if (! isset($this->managers[$name])) { + throw new InvalidArgumentException(sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name)); + } + + // force the creation of a new document manager + // if the current one is closed + $this->resetService($this->managers[$name]); + + return $this->getManager($name); + } + + private function selectManager(string $persistentObjectName, ?string $persistentManagerName = null) : ObjectManager + { + if ($persistentManagerName !== null) { + return $this->getManager($persistentManagerName); + } + + return $this->getManagerForClass($persistentObjectName) ?? $this->getManager(); + } +} + +class_exists(\Doctrine\Common\Persistence\AbstractManagerRegistry::class); +interface_exists(ObjectManager::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/ConnectionRegistry.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/ConnectionRegistry.php new file mode 100644 index 0000000..a822c71 --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/ConnectionRegistry.php @@ -0,0 +1,43 @@ +object = $object; + $this->objectManager = $objectManager; + } + + /** + * Retrieves the associated entity. + * + * @deprecated + * + * @return object + */ + public function getEntity() + { + return $this->object; + } + + /** + * Retrieves the associated object. + * + * @return object + */ + public function getObject() + { + return $this->object; + } + + /** + * Retrieves the associated ObjectManager. + * + * @return ObjectManager + */ + public function getObjectManager() + { + return $this->objectManager; + } +} + +class_exists(\Doctrine\Common\Persistence\Event\LifecycleEventArgs::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/LoadClassMetadataEventArgs.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/LoadClassMetadataEventArgs.php new file mode 100644 index 0000000..31aae4a --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/LoadClassMetadataEventArgs.php @@ -0,0 +1,48 @@ +classMetadata = $classMetadata; + $this->objectManager = $objectManager; + } + + /** + * Retrieves the associated ClassMetadata. + * + * @return ClassMetadata + */ + public function getClassMetadata() + { + return $this->classMetadata; + } + + /** + * Retrieves the associated ObjectManager. + * + * @return ObjectManager + */ + public function getObjectManager() + { + return $this->objectManager; + } +} + +class_exists(\Doctrine\Common\Persistence\Event\LoadClassMetadataEventArgs::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/ManagerEventArgs.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/ManagerEventArgs.php new file mode 100644 index 0000000..66dd903 --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/ManagerEventArgs.php @@ -0,0 +1,33 @@ +objectManager = $objectManager; + } + + /** + * Retrieves the associated ObjectManager. + * + * @return ObjectManager + */ + public function getObjectManager() + { + return $this->objectManager; + } +} + +class_exists(\Doctrine\Common\Persistence\Event\ManagerEventArgs::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/OnClearEventArgs.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/OnClearEventArgs.php new file mode 100644 index 0000000..cc263c1 --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/OnClearEventArgs.php @@ -0,0 +1,61 @@ +objectManager = $objectManager; + $this->entityClass = $entityClass; + } + + /** + * Retrieves the associated ObjectManager. + * + * @return ObjectManager + */ + public function getObjectManager() + { + return $this->objectManager; + } + + /** + * Returns the name of the entity class that is cleared, or null if all are cleared. + * + * @return string|null + */ + public function getEntityClass() + { + return $this->entityClass; + } + + /** + * Returns whether this event clears all entities. + * + * @return bool + */ + public function clearsAllEntities() + { + return $this->entityClass === null; + } +} + +class_exists(\Doctrine\Common\Persistence\Event\OnClearEventArgs::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/PreUpdateEventArgs.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/PreUpdateEventArgs.php new file mode 100644 index 0000000..b9f8376 --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/PreUpdateEventArgs.php @@ -0,0 +1,116 @@ +entityChangeSet = &$changeSet; + } + + /** + * Retrieves the entity changeset. + * + * @return mixed[][] + */ + public function getEntityChangeSet() + { + return $this->entityChangeSet; + } + + /** + * Checks if field has a changeset. + * + * @param string $field + * + * @return bool + */ + public function hasChangedField($field) + { + return isset($this->entityChangeSet[$field]); + } + + /** + * Gets the old value of the changeset of the changed field. + * + * @param string $field + * + * @return mixed + */ + public function getOldValue($field) + { + $this->assertValidField($field); + + return $this->entityChangeSet[$field][0]; + } + + /** + * Gets the new value of the changeset of the changed field. + * + * @param string $field + * + * @return mixed + */ + public function getNewValue($field) + { + $this->assertValidField($field); + + return $this->entityChangeSet[$field][1]; + } + + /** + * Sets the new value of this field. + * + * @param string $field + * @param mixed $value + * + * @return void + */ + public function setNewValue($field, $value) + { + $this->assertValidField($field); + + $this->entityChangeSet[$field][1] = $value; + } + + /** + * Asserts the field exists in changeset. + * + * @param string $field + * + * @return void + * + * @throws InvalidArgumentException + */ + private function assertValidField($field) + { + if (! isset($this->entityChangeSet[$field])) { + throw new InvalidArgumentException(sprintf( + 'Field "%s" is not a valid field of the entity "%s" in PreUpdateEventArgs.', + $field, + get_class($this->getObject()) + )); + } + } +} + +class_exists(\Doctrine\Common\Persistence\Event\PreUpdateEventArgs::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/ManagerRegistry.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/ManagerRegistry.php new file mode 100644 index 0000000..b28664c --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/ManagerRegistry.php @@ -0,0 +1,92 @@ +cacheDriver = $cacheDriver; + } + + /** + * Gets the cache driver used by the factory to cache ClassMetadata instances. + * + * @return Cache|null + */ + public function getCacheDriver() + { + return $this->cacheDriver; + } + + /** + * Returns an array of all the loaded metadata currently in memory. + * + * @return ClassMetadata[] + */ + public function getLoadedMetadata() + { + return $this->loadedMetadata; + } + + /** + * Forces the factory to load the metadata of all classes known to the underlying + * mapping driver. + * + * @return ClassMetadata[] The ClassMetadata instances of all mapped classes. + */ + public function getAllMetadata() + { + if (! $this->initialized) { + $this->initialize(); + } + + $driver = $this->getDriver(); + $metadata = []; + foreach ($driver->getAllClassNames() as $className) { + $metadata[] = $this->getMetadataFor($className); + } + + return $metadata; + } + + /** + * Lazy initialization of this stuff, especially the metadata driver, + * since these are not needed at all when a metadata cache is active. + * + * @return void + */ + abstract protected function initialize(); + + /** + * Gets the fully qualified class-name from the namespace alias. + * + * @param string $namespaceAlias + * @param string $simpleClassName + * + * @return string + */ + abstract protected function getFqcnFromAlias($namespaceAlias, $simpleClassName); + + /** + * Returns the mapping driver implementation. + * + * @return MappingDriver + */ + abstract protected function getDriver(); + + /** + * Wakes up reflection after ClassMetadata gets unserialized from cache. + * + * @return void + */ + abstract protected function wakeupReflection(ClassMetadata $class, ReflectionService $reflService); + + /** + * Initializes Reflection after ClassMetadata was constructed. + * + * @return void + */ + abstract protected function initializeReflection(ClassMetadata $class, ReflectionService $reflService); + + /** + * Checks whether the class metadata is an entity. + * + * This method should return false for mapped superclasses or embedded classes. + * + * @return bool + */ + abstract protected function isEntity(ClassMetadata $class); + + /** + * Gets the class metadata descriptor for a class. + * + * @param string $className The name of the class. + * + * @return ClassMetadata + * + * @throws ReflectionException + * @throws MappingException + */ + public function getMetadataFor($className) + { + if (isset($this->loadedMetadata[$className])) { + return $this->loadedMetadata[$className]; + } + + // Check for namespace alias + if (strpos($className, ':') !== false) { + [$namespaceAlias, $simpleClassName] = explode(':', $className, 2); + + $realClassName = $this->getFqcnFromAlias($namespaceAlias, $simpleClassName); + } else { + $realClassName = $this->getRealClass($className); + } + + if (isset($this->loadedMetadata[$realClassName])) { + // We do not have the alias name in the map, include it + return $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName]; + } + + $loadingException = null; + + try { + if ($this->cacheDriver) { + $cached = $this->cacheDriver->fetch($realClassName . $this->cacheSalt); + if ($cached instanceof ClassMetadata) { + $this->loadedMetadata[$realClassName] = $cached; + + $this->wakeupReflection($cached, $this->getReflectionService()); + } else { + foreach ($this->loadMetadata($realClassName) as $loadedClassName) { + $this->cacheDriver->save( + $loadedClassName . $this->cacheSalt, + $this->loadedMetadata[$loadedClassName] + ); + } + } + } else { + $this->loadMetadata($realClassName); + } + } catch (MappingException $loadingException) { + $fallbackMetadataResponse = $this->onNotFoundMetadata($realClassName); + + if (! $fallbackMetadataResponse) { + throw $loadingException; + } + + $this->loadedMetadata[$realClassName] = $fallbackMetadataResponse; + } + + if ($className !== $realClassName) { + // We do not have the alias name in the map, include it + $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName]; + } + + return $this->loadedMetadata[$className]; + } + + /** + * Checks whether the factory has the metadata for a class loaded already. + * + * @param string $className + * + * @return bool TRUE if the metadata of the class in question is already loaded, FALSE otherwise. + */ + public function hasMetadataFor($className) + { + return isset($this->loadedMetadata[$className]); + } + + /** + * Sets the metadata descriptor for a specific class. + * + * NOTE: This is only useful in very special cases, like when generating proxy classes. + * + * @param string $className + * @param ClassMetadata $class + * + * @return void + */ + public function setMetadataFor($className, $class) + { + $this->loadedMetadata[$className] = $class; + } + + /** + * Gets an array of parent classes for the given entity class. + * + * @param string $name + * + * @return string[] + */ + protected function getParentClasses($name) + { + // Collect parent classes, ignoring transient (not-mapped) classes. + $parentClasses = []; + + foreach (array_reverse($this->getReflectionService()->getParentClasses($name)) as $parentClass) { + if ($this->getDriver()->isTransient($parentClass)) { + continue; + } + + $parentClasses[] = $parentClass; + } + + return $parentClasses; + } + + /** + * Loads the metadata of the class in question and all it's ancestors whose metadata + * is still not loaded. + * + * Important: The class $name does not necessarily exist at this point here. + * Scenarios in a code-generation setup might have access to XML/YAML + * Mapping files without the actual PHP code existing here. That is why the + * {@see Doctrine\Common\Persistence\Mapping\ReflectionService} interface + * should be used for reflection. + * + * @param string $name The name of the class for which the metadata should get loaded. + * + * @return string[] + */ + protected function loadMetadata($name) + { + if (! $this->initialized) { + $this->initialize(); + } + + $loaded = []; + + $parentClasses = $this->getParentClasses($name); + $parentClasses[] = $name; + + // Move down the hierarchy of parent classes, starting from the topmost class + $parent = null; + $rootEntityFound = false; + $visited = []; + $reflService = $this->getReflectionService(); + foreach ($parentClasses as $className) { + if (isset($this->loadedMetadata[$className])) { + $parent = $this->loadedMetadata[$className]; + if ($this->isEntity($parent)) { + $rootEntityFound = true; + array_unshift($visited, $className); + } + continue; + } + + $class = $this->newClassMetadataInstance($className); + $this->initializeReflection($class, $reflService); + + $this->doLoadMetadata($class, $parent, $rootEntityFound, $visited); + + $this->loadedMetadata[$className] = $class; + + $parent = $class; + + if ($this->isEntity($class)) { + $rootEntityFound = true; + array_unshift($visited, $className); + } + + $this->wakeupReflection($class, $reflService); + + $loaded[] = $className; + } + + return $loaded; + } + + /** + * Provides a fallback hook for loading metadata when loading failed due to reflection/mapping exceptions + * + * Override this method to implement a fallback strategy for failed metadata loading + * + * @param string $className + * + * @return ClassMetadata|null + */ + protected function onNotFoundMetadata($className) + { + return null; + } + + /** + * Actually loads the metadata from the underlying metadata. + * + * @param ClassMetadata $class + * @param ClassMetadata|null $parent + * @param bool $rootEntityFound + * @param string[] $nonSuperclassParents All parent class names + * that are not marked as mapped superclasses. + * + * @return void + */ + abstract protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonSuperclassParents); + + /** + * Creates a new ClassMetadata instance for the given class name. + * + * @param string $className + * + * @return ClassMetadata + */ + abstract protected function newClassMetadataInstance($className); + + /** + * {@inheritDoc} + */ + public function isTransient($class) + { + if (! $this->initialized) { + $this->initialize(); + } + + // Check for namespace alias + if (strpos($class, ':') !== false) { + [$namespaceAlias, $simpleClassName] = explode(':', $class, 2); + $class = $this->getFqcnFromAlias($namespaceAlias, $simpleClassName); + } + + return $this->getDriver()->isTransient($class); + } + + /** + * Sets the reflectionService. + * + * @return void + */ + public function setReflectionService(ReflectionService $reflectionService) + { + $this->reflectionService = $reflectionService; + } + + /** + * Gets the reflection service associated with this metadata factory. + * + * @return ReflectionService + */ + public function getReflectionService() + { + if ($this->reflectionService === null) { + $this->reflectionService = new RuntimeReflectionService(); + } + + return $this->reflectionService; + } + + /** + * Gets the real class name of a class name that could be a proxy. + */ + private function getRealClass(string $class) : string + { + $pos = strrpos($class, '\\' . Proxy::MARKER . '\\'); + + if ($pos === false) { + return $class; + } + + return substr($class, $pos + Proxy::MARKER_LENGTH + 2); + } +} + +class_exists(\Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory::class); +interface_exists(ClassMetadata::class); +interface_exists(ReflectionService::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/ClassMetadata.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/ClassMetadata.php new file mode 100644 index 0000000..7b995d5 --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/ClassMetadata.php @@ -0,0 +1,157 @@ +reader = $reader; + if (! $paths) { + return; + } + + $this->addPaths((array) $paths); + } + + /** + * Appends lookup paths to metadata driver. + * + * @param string[] $paths + * + * @return void + */ + public function addPaths(array $paths) + { + $this->paths = array_unique(array_merge($this->paths, $paths)); + } + + /** + * Retrieves the defined metadata lookup paths. + * + * @return string[] + */ + public function getPaths() + { + return $this->paths; + } + + /** + * Append exclude lookup paths to metadata driver. + * + * @param string[] $paths + */ + public function addExcludePaths(array $paths) + { + $this->excludePaths = array_unique(array_merge($this->excludePaths, $paths)); + } + + /** + * Retrieve the defined metadata lookup exclude paths. + * + * @return string[] + */ + public function getExcludePaths() + { + return $this->excludePaths; + } + + /** + * Retrieve the current annotation reader + * + * @return Reader + */ + public function getReader() + { + return $this->reader; + } + + /** + * Gets the file extension used to look for mapping files under. + * + * @return string + */ + public function getFileExtension() + { + return $this->fileExtension; + } + + /** + * Sets the file extension used to look for mapping files under. + * + * @param string $fileExtension The file extension to set. + * + * @return void + */ + public function setFileExtension($fileExtension) + { + $this->fileExtension = $fileExtension; + } + + /** + * Returns whether the class with the specified name is transient. Only non-transient + * classes, that is entities and mapped superclasses, should have their metadata loaded. + * + * A class is non-transient if it is annotated with an annotation + * from the {@see AnnotationDriver::entityAnnotationClasses}. + * + * @param string $className + * + * @return bool + */ + public function isTransient($className) + { + $classAnnotations = $this->reader->getClassAnnotations(new ReflectionClass($className)); + + foreach ($classAnnotations as $annot) { + if (isset($this->entityAnnotationClasses[get_class($annot)])) { + return false; + } + } + + return true; + } + + /** + * {@inheritDoc} + */ + public function getAllClassNames() + { + if ($this->classNames !== null) { + return $this->classNames; + } + + if (! $this->paths) { + throw MappingException::pathRequired(); + } + + $classes = []; + $includedFiles = []; + + foreach ($this->paths as $path) { + if (! is_dir($path)) { + throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); + } + + $iterator = new RegexIterator( + new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS), + RecursiveIteratorIterator::LEAVES_ONLY + ), + '/^.+' . preg_quote($this->fileExtension) . '$/i', + RecursiveRegexIterator::GET_MATCH + ); + + foreach ($iterator as $file) { + $sourceFile = $file[0]; + + if (! preg_match('(^phar:)i', $sourceFile)) { + $sourceFile = realpath($sourceFile); + } + + foreach ($this->excludePaths as $excludePath) { + $exclude = str_replace('\\', '/', realpath($excludePath)); + $current = str_replace('\\', '/', $sourceFile); + + if (strpos($current, $exclude) !== false) { + continue 2; + } + } + + require_once $sourceFile; + + $includedFiles[] = $sourceFile; + } + } + + $declared = get_declared_classes(); + + foreach ($declared as $className) { + $rc = new ReflectionClass($className); + $sourceFile = $rc->getFileName(); + if (! in_array($sourceFile, $includedFiles) || $this->isTransient($className)) { + continue; + } + + $classes[] = $className; + } + + $this->classNames = $classes; + + return $classes; + } +} + +class_exists(\Doctrine\Persistence\Mapping\Driver\AnnotationDriver::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/DefaultFileLocator.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/DefaultFileLocator.php new file mode 100644 index 0000000..4f49bc2 --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/DefaultFileLocator.php @@ -0,0 +1,164 @@ +addPaths((array) $paths); + $this->fileExtension = $fileExtension; + } + + /** + * Appends lookup paths to metadata driver. + * + * @param string[] $paths + * + * @return void + */ + public function addPaths(array $paths) + { + $this->paths = array_unique(array_merge($this->paths, $paths)); + } + + /** + * Retrieves the defined metadata lookup paths. + * + * @return string[] + */ + public function getPaths() + { + return $this->paths; + } + + /** + * Gets the file extension used to look for mapping files under. + * + * @return string|null + */ + public function getFileExtension() + { + return $this->fileExtension; + } + + /** + * Sets the file extension used to look for mapping files under. + * + * @param string|null $fileExtension The file extension to set. + * + * @return void + */ + public function setFileExtension($fileExtension) + { + $this->fileExtension = $fileExtension; + } + + /** + * {@inheritDoc} + */ + public function findMappingFile($className) + { + $fileName = str_replace('\\', '.', $className) . $this->fileExtension; + + // Check whether file exists + foreach ($this->paths as $path) { + if (is_file($path . DIRECTORY_SEPARATOR . $fileName)) { + return $path . DIRECTORY_SEPARATOR . $fileName; + } + } + + throw MappingException::mappingFileNotFound($className, $fileName); + } + + /** + * {@inheritDoc} + */ + public function getAllClassNames($globalBasename) + { + $classes = []; + + if ($this->paths) { + foreach ($this->paths as $path) { + if (! is_dir($path)) { + throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); + } + + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($path), + RecursiveIteratorIterator::LEAVES_ONLY + ); + + foreach ($iterator as $file) { + $fileName = $file->getBasename($this->fileExtension); + + if ($fileName === $file->getBasename() || $fileName === $globalBasename) { + continue; + } + + // NOTE: All files found here means classes are not transient! + $classes[] = str_replace('.', '\\', $fileName); + } + } + } + + return $classes; + } + + /** + * {@inheritDoc} + */ + public function fileExists($className) + { + $fileName = str_replace('\\', '.', $className) . $this->fileExtension; + + // Check whether file exists + foreach ((array) $this->paths as $path) { + if (is_file($path . DIRECTORY_SEPARATOR . $fileName)) { + return true; + } + } + + return false; + } +} + +class_exists(\Doctrine\Common\Persistence\Mapping\Driver\DefaultFileLocator::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileDriver.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileDriver.php new file mode 100644 index 0000000..c8c783a --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileDriver.php @@ -0,0 +1,199 @@ +locator = $locator; + } else { + $this->locator = new DefaultFileLocator((array) $locator, $fileExtension); + } + } + + /** + * Sets the global basename. + * + * @param string $file + * + * @return void + */ + public function setGlobalBasename($file) + { + $this->globalBasename = $file; + } + + /** + * Retrieves the global basename. + * + * @return string|null + */ + public function getGlobalBasename() + { + return $this->globalBasename; + } + + /** + * Gets the element of schema meta data for the class from the mapping file. + * This will lazily load the mapping file if it is not loaded yet. + * + * @param string $className + * + * @return ClassMetadata The element of schema meta data. + * + * @throws MappingException + */ + public function getElement($className) + { + if ($this->classCache === null) { + $this->initialize(); + } + + if (isset($this->classCache[$className])) { + return $this->classCache[$className]; + } + + $result = $this->loadMappingFile($this->locator->findMappingFile($className)); + if (! isset($result[$className])) { + throw MappingException::invalidMappingFile($className, str_replace('\\', '.', $className) . $this->locator->getFileExtension()); + } + + $this->classCache[$className] = $result[$className]; + + return $result[$className]; + } + + /** + * {@inheritDoc} + */ + public function isTransient($className) + { + if ($this->classCache === null) { + $this->initialize(); + } + + if (isset($this->classCache[$className])) { + return false; + } + + return ! $this->locator->fileExists($className); + } + + /** + * {@inheritDoc} + */ + public function getAllClassNames() + { + if ($this->classCache === null) { + $this->initialize(); + } + + if (! $this->classCache) { + return (array) $this->locator->getAllClassNames($this->globalBasename); + } + + return array_unique(array_merge( + array_keys($this->classCache), + (array) $this->locator->getAllClassNames($this->globalBasename) + )); + } + + /** + * Loads a mapping file with the given name and returns a map + * from class/entity names to their corresponding file driver elements. + * + * @param string $file The mapping file to load. + * + * @return ClassMetadata[] + */ + abstract protected function loadMappingFile($file); + + /** + * Initializes the class cache from all the global files. + * + * Using this feature adds a substantial performance hit to file drivers as + * more metadata has to be loaded into memory than might actually be + * necessary. This may not be relevant to scenarios where caching of + * metadata is in place, however hits very hard in scenarios where no + * caching is used. + * + * @return void + */ + protected function initialize() + { + $this->classCache = []; + if ($this->globalBasename === null) { + return; + } + + foreach ($this->locator->getPaths() as $path) { + $file = $path . '/' . $this->globalBasename . $this->locator->getFileExtension(); + if (! is_file($file)) { + continue; + } + + $this->classCache = array_merge( + $this->classCache, + $this->loadMappingFile($file) + ); + } + } + + /** + * Retrieves the locator used to discover mapping files by className. + * + * @return FileLocator + */ + public function getLocator() + { + return $this->locator; + } + + /** + * Sets the locator used to discover mapping files by className. + */ + public function setLocator(FileLocator $locator) + { + $this->locator = $locator; + } +} + +class_exists(\Doctrine\Common\Persistence\Mapping\Driver\FileDriver::class); +interface_exists(FileLocator::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileLocator.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileLocator.php new file mode 100644 index 0000000..bce3c03 --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileLocator.php @@ -0,0 +1,57 @@ +defaultDriver; + } + + /** + * Set the default driver. + * + * @return void + */ + public function setDefaultDriver(MappingDriver $driver) + { + $this->defaultDriver = $driver; + } + + /** + * Adds a nested driver. + * + * @param string $namespace + * + * @return void + */ + public function addDriver(MappingDriver $nestedDriver, $namespace) + { + $this->drivers[$namespace] = $nestedDriver; + } + + /** + * Gets the array of nested drivers. + * + * @return MappingDriver[] $drivers + */ + public function getDrivers() + { + return $this->drivers; + } + + /** + * {@inheritDoc} + */ + public function loadMetadataForClass($className, ClassMetadata $metadata) + { + /** @var MappingDriver $driver */ + foreach ($this->drivers as $namespace => $driver) { + if (strpos($className, $namespace) === 0) { + $driver->loadMetadataForClass($className, $metadata); + + return; + } + } + + if ($this->defaultDriver !== null) { + $this->defaultDriver->loadMetadataForClass($className, $metadata); + + return; + } + + throw MappingException::classNotFoundInNamespaces($className, array_keys($this->drivers)); + } + + /** + * {@inheritDoc} + */ + public function getAllClassNames() + { + $classNames = []; + $driverClasses = []; + + /** @var MappingDriver $driver */ + foreach ($this->drivers as $namespace => $driver) { + $oid = spl_object_hash($driver); + + if (! isset($driverClasses[$oid])) { + $driverClasses[$oid] = $driver->getAllClassNames(); + } + + foreach ($driverClasses[$oid] as $className) { + if (strpos($className, $namespace) !== 0) { + continue; + } + + $classNames[$className] = true; + } + } + + if ($this->defaultDriver !== null) { + foreach ($this->defaultDriver->getAllClassNames() as $className) { + $classNames[$className] = true; + } + } + + return array_keys($classNames); + } + + /** + * {@inheritDoc} + */ + public function isTransient($className) + { + /** @var MappingDriver $driver */ + foreach ($this->drivers as $namespace => $driver) { + if (strpos($className, $namespace) === 0) { + return $driver->isTransient($className); + } + } + + if ($this->defaultDriver !== null) { + return $this->defaultDriver->isTransient($className); + } + + return true; + } +} + +class_exists(\Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain::class); +interface_exists(ClassMetadata::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/PHPDriver.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/PHPDriver.php new file mode 100644 index 0000000..4f1d948 --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/PHPDriver.php @@ -0,0 +1,49 @@ +metadata = $metadata; + + $this->loadMappingFile($this->locator->findMappingFile($className)); + } + + /** + * {@inheritDoc} + */ + protected function loadMappingFile($file) + { + $metadata = $this->metadata; + include $file; + + return [$metadata->getName() => $metadata]; + } +} + +class_exists(\Doctrine\Common\Persistence\Mapping\Driver\PHPDriver::class); +interface_exists(ClassMetadata::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/StaticPHPDriver.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/StaticPHPDriver.php new file mode 100644 index 0000000..848b3bd --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/StaticPHPDriver.php @@ -0,0 +1,134 @@ +addPaths((array) $paths); + } + + /** + * Adds paths. + * + * @param string[] $paths + * + * @return void + */ + public function addPaths(array $paths) + { + $this->paths = array_unique(array_merge($this->paths, $paths)); + } + + /** + * {@inheritdoc} + */ + public function loadMetadataForClass($className, ClassMetadata $metadata) + { + $className::loadMetadata($metadata); + } + + /** + * {@inheritDoc} + * + * @todo Same code exists in AnnotationDriver, should we re-use it somehow or not worry about it? + */ + public function getAllClassNames() + { + if ($this->classNames !== null) { + return $this->classNames; + } + + if (! $this->paths) { + throw MappingException::pathRequired(); + } + + $classes = []; + $includedFiles = []; + + foreach ($this->paths as $path) { + if (! is_dir($path)) { + throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); + } + + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($path), + RecursiveIteratorIterator::LEAVES_ONLY + ); + + foreach ($iterator as $file) { + if ($file->getBasename('.php') === $file->getBasename()) { + continue; + } + + $sourceFile = realpath($file->getPathName()); + require_once $sourceFile; + $includedFiles[] = $sourceFile; + } + } + + $declared = get_declared_classes(); + + foreach ($declared as $className) { + $rc = new ReflectionClass($className); + $sourceFile = $rc->getFileName(); + if (! in_array($sourceFile, $includedFiles) || $this->isTransient($className)) { + continue; + } + + $classes[] = $className; + } + + $this->classNames = $classes; + + return $classes; + } + + /** + * {@inheritdoc} + */ + public function isTransient($className) + { + return ! method_exists($className, 'loadMetadata'); + } +} + +class_exists(\Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver::class); +interface_exists(ClassMetadata::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/SymfonyFileLocator.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/SymfonyFileLocator.php new file mode 100644 index 0000000..3124c66 --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/SymfonyFileLocator.php @@ -0,0 +1,233 @@ +addNamespacePrefixes($prefixes); + $this->fileExtension = $fileExtension; + + if (empty($nsSeparator)) { + throw new InvalidArgumentException('Namespace separator should not be empty'); + } + + $this->nsSeparator = (string) $nsSeparator; + } + + /** + * Adds Namespace Prefixes. + * + * @param string[] $prefixes + * + * @return void + */ + public function addNamespacePrefixes(array $prefixes) + { + $this->prefixes = array_merge($this->prefixes, $prefixes); + $this->paths = array_merge($this->paths, array_keys($prefixes)); + } + + /** + * Gets Namespace Prefixes. + * + * @return string[] + */ + public function getNamespacePrefixes() + { + return $this->prefixes; + } + + /** + * {@inheritDoc} + */ + public function getPaths() + { + return $this->paths; + } + + /** + * {@inheritDoc} + */ + public function getFileExtension() + { + return $this->fileExtension; + } + + /** + * Sets the file extension used to look for mapping files under. + * + * @param string $fileExtension The file extension to set. + * + * @return void + */ + public function setFileExtension($fileExtension) + { + $this->fileExtension = $fileExtension; + } + + /** + * {@inheritDoc} + */ + public function fileExists($className) + { + $defaultFileName = str_replace('\\', $this->nsSeparator, $className) . $this->fileExtension; + foreach ($this->paths as $path) { + if (! isset($this->prefixes[$path])) { + // global namespace class + if (is_file($path . DIRECTORY_SEPARATOR . $defaultFileName)) { + return true; + } + + continue; + } + + $prefix = $this->prefixes[$path]; + + if (strpos($className, $prefix . '\\') !== 0) { + continue; + } + + $filename = $path . '/' . strtr(substr($className, strlen($prefix) + 1), '\\', $this->nsSeparator) . $this->fileExtension; + if (is_file($filename)) { + return true; + } + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function getAllClassNames($globalBasename = null) + { + $classes = []; + + if ($this->paths) { + foreach ((array) $this->paths as $path) { + if (! is_dir($path)) { + throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); + } + + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($path), + RecursiveIteratorIterator::LEAVES_ONLY + ); + + foreach ($iterator as $file) { + $fileName = $file->getBasename($this->fileExtension); + + if ($fileName === $file->getBasename() || $fileName === $globalBasename) { + continue; + } + + // NOTE: All files found here means classes are not transient! + if (isset($this->prefixes[$path])) { + // Calculate namespace suffix for given prefix as a relative path from basepath to file path + $nsSuffix = strtr( + substr(realpath($file->getPath()), strlen(realpath($path))), + $this->nsSeparator, + '\\' + ); + + $classes[] = $this->prefixes[$path] . str_replace(DIRECTORY_SEPARATOR, '\\', $nsSuffix) . '\\' . str_replace($this->nsSeparator, '\\', $fileName); + } else { + $classes[] = str_replace($this->nsSeparator, '\\', $fileName); + } + } + } + } + + return $classes; + } + + /** + * {@inheritDoc} + */ + public function findMappingFile($className) + { + $defaultFileName = str_replace('\\', $this->nsSeparator, $className) . $this->fileExtension; + foreach ($this->paths as $path) { + if (! isset($this->prefixes[$path])) { + if (is_file($path . DIRECTORY_SEPARATOR . $defaultFileName)) { + return $path . DIRECTORY_SEPARATOR . $defaultFileName; + } + + continue; + } + + $prefix = $this->prefixes[$path]; + + if (strpos($className, $prefix . '\\') !== 0) { + continue; + } + + $filename = $path . '/' . strtr(substr($className, strlen($prefix) + 1), '\\', $this->nsSeparator) . $this->fileExtension; + if (is_file($filename)) { + return $filename; + } + } + + throw MappingException::mappingFileNotFound($className, substr($className, strrpos($className, '\\') + 1) . $this->fileExtension); + } +} + +class_exists(\Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/MappingException.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/MappingException.php new file mode 100644 index 0000000..9729e5f --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/MappingException.php @@ -0,0 +1,98 @@ +getShortName(); + } + + /** + * {@inheritDoc} + */ + public function getClassNamespace($class) + { + $reflectionClass = new ReflectionClass($class); + + return $reflectionClass->getNamespaceName(); + } + + /** + * {@inheritDoc} + */ + public function getClass($class) + { + return new ReflectionClass($class); + } + + /** + * {@inheritDoc} + */ + public function getAccessibleProperty($class, $property) + { + $reflectionProperty = new ReflectionProperty($class, $property); + + if ($reflectionProperty->isPublic()) { + $reflectionProperty = new RuntimePublicReflectionProperty($class, $property); + } + + $reflectionProperty->setAccessible(true); + + return $reflectionProperty; + } + + /** + * {@inheritDoc} + */ + public function hasPublicMethod($class, $method) + { + try { + $reflectionMethod = new ReflectionMethod($class, $method); + } catch (ReflectionException $e) { + return false; + } + + return $reflectionMethod->isPublic(); + } +} + +class_exists(\Doctrine\Common\Persistence\Mapping\RuntimeReflectionService::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/StaticReflectionService.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/StaticReflectionService.php new file mode 100644 index 0000000..ac24e45 --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/StaticReflectionService.php @@ -0,0 +1,74 @@ +find($id). + * + * @param string $className The class name of the object to find. + * @param mixed $id The identity of the object to find. + * + * @return object|null The found object. + */ + public function find($className, $id); + + /** + * Tells the ObjectManager to make an instance managed and persistent. + * + * The object will be entered into the database as a result of the flush operation. + * + * NOTE: The persist operation always considers objects that are not yet known to + * this ObjectManager as NEW. Do not pass detached objects to the persist operation. + * + * @param object $object The instance to make managed and persistent. + * + * @return void + */ + public function persist($object); + + /** + * Removes an object instance. + * + * A removed object will be removed from the database as a result of the flush operation. + * + * @param object $object The object instance to remove. + * + * @return void + */ + public function remove($object); + + /** + * Merges the state of a detached object into the persistence context + * of this ObjectManager and returns the managed copy of the object. + * The object passed to merge will not become associated/managed with this ObjectManager. + * + * @deprecated Merge operation is deprecated and will be removed in Persistence 2.0. + * Merging should be part of the business domain of an application rather than + * a generic operation of ObjectManager. + * + * @param object $object + * + * @return object + */ + public function merge($object); + + /** + * Clears the ObjectManager. All objects that are currently managed + * by this ObjectManager become detached. + * + * @param string|null $objectName if given, only objects of this type will get detached. + * + * @return void + */ + public function clear($objectName = null); + + /** + * Detaches an object from the ObjectManager, causing a managed object to + * become detached. Unflushed changes made to the object if any + * (including removal of the object), will not be synchronized to the database. + * Objects which previously referenced the detached object will continue to + * reference it. + * + * @deprecated Detach operation is deprecated and will be removed in Persistence 2.0. Please use + * {@see ObjectManager::clear()} instead. + * + * @param object $object The object to detach. + * + * @return void + */ + public function detach($object); + + /** + * Refreshes the persistent state of an object from the database, + * overriding any local changes that have not yet been persisted. + * + * @param object $object The object to refresh. + * + * @return void + */ + public function refresh($object); + + /** + * Flushes all changes to objects that have been queued up to now to the database. + * This effectively synchronizes the in-memory state of managed objects with the + * database. + * + * @return void + */ + public function flush(); + + /** + * Gets the repository for a class. + * + * @param string $className + * + * @return ObjectRepository + */ + public function getRepository($className); + + /** + * Returns the ClassMetadata descriptor for a class. + * + * The class name must be the fully-qualified class name without a leading backslash + * (as it is returned by get_class($obj)). + * + * @param string $className + * + * @return ClassMetadata + */ + public function getClassMetadata($className); + + /** + * Gets the metadata factory used to gather the metadata of classes. + * + * @return ClassMetadataFactory + */ + public function getMetadataFactory(); + + /** + * Helper method to initialize a lazy loading proxy or persistent collection. + * + * This method is a no-op for other objects. + * + * @param object $obj + * + * @return void + */ + public function initializeObject($obj); + + /** + * Checks if the object is part of the current UnitOfWork and therefore managed. + * + * @param object $object + * + * @return bool + */ + public function contains($object); +} + +interface_exists(\Doctrine\Common\Persistence\ObjectManager::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectManagerAware.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectManagerAware.php new file mode 100644 index 0000000..2593b7c --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectManagerAware.php @@ -0,0 +1,34 @@ +wrapped->find($className, $id); + } + + /** + * {@inheritdoc} + */ + public function persist($object) + { + $this->wrapped->persist($object); + } + + /** + * {@inheritdoc} + */ + public function remove($object) + { + $this->wrapped->remove($object); + } + + /** + * {@inheritdoc} + */ + public function merge($object) + { + return $this->wrapped->merge($object); + } + + /** + * {@inheritdoc} + */ + public function clear($objectName = null) + { + $this->wrapped->clear($objectName); + } + + /** + * {@inheritdoc} + */ + public function detach($object) + { + $this->wrapped->detach($object); + } + + /** + * {@inheritdoc} + */ + public function refresh($object) + { + $this->wrapped->refresh($object); + } + + /** + * {@inheritdoc} + */ + public function flush() + { + $this->wrapped->flush(); + } + + /** + * {@inheritdoc} + */ + public function getRepository($className) + { + return $this->wrapped->getRepository($className); + } + + /** + * {@inheritdoc} + */ + public function getClassMetadata($className) + { + return $this->wrapped->getClassMetadata($className); + } + + /** + * {@inheritdoc} + */ + public function getMetadataFactory() + { + return $this->wrapped->getMetadataFactory(); + } + + /** + * {@inheritdoc} + */ + public function initializeObject($obj) + { + $this->wrapped->initializeObject($obj); + } + + /** + * {@inheritdoc} + */ + public function contains($object) + { + return $this->wrapped->contains($object); + } +} + +class_exists(\Doctrine\Common\Persistence\ObjectManagerDecorator::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectRepository.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectRepository.php new file mode 100644 index 0000000..7661be2 --- /dev/null +++ b/vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectRepository.php @@ -0,0 +1,64 @@ += MAJOR).new.exists' # New issues of major or higher severity + - 'project.metric_change("scrutinizer.test_coverage", < 0)' # Code Coverage decreased from previous inspection diff --git a/vendor/doctrine/reflection/LICENSE b/vendor/doctrine/reflection/LICENSE new file mode 100644 index 0000000..8c38cc1 --- /dev/null +++ b/vendor/doctrine/reflection/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2015 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/doctrine/reflection/README.md b/vendor/doctrine/reflection/README.md new file mode 100644 index 0000000..756c55b --- /dev/null +++ b/vendor/doctrine/reflection/README.md @@ -0,0 +1,13 @@ +# Doctrine Reflection + +[![Build Status](https://travis-ci.org/doctrine/reflection.svg)](https://travis-ci.org/doctrine/reflection) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/reflection/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/reflection/?branch=master) +[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/reflection/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/reflection/?branch=master) + +The Doctrine Reflection project is a simple library used by the various Doctrine projects which adds some additional functionality on top of the reflection functionality that comes with PHP. It allows you to get the reflection information about classes, methods and properties statically. + +## More resources: + +* [Website](https://www.doctrine-project.org/) +* [Documentation](https://www.doctrine-project.org/projects/doctrine-reflection/en/latest/) +* [Downloads](https://github.com/doctrine/reflection/releases) diff --git a/vendor/doctrine/reflection/composer.json b/vendor/doctrine/reflection/composer.json new file mode 100644 index 0000000..ad31969 --- /dev/null +++ b/vendor/doctrine/reflection/composer.json @@ -0,0 +1,44 @@ +{ + "name": "doctrine/reflection", + "type": "library", + "description": "Doctrine Reflection component", + "keywords": ["reflection"], + "homepage": "https://www.doctrine-project.org/projects/reflection.html", + "license": "MIT", + "authors": [ + {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, + {"name": "Roman Borschel", "email": "roman@code-factory.org"}, + {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, + {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, + {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}, + {"name": "Marco Pivetta", "email": "ocramius@gmail.com"} + ], + "require": { + "php": "^7.1", + "ext-tokenizer": "*", + "doctrine/annotations": "^1.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpunit/phpunit": "^7.0", + "doctrine/coding-standard": "^4.0", + "doctrine/common": "^2.8", + "squizlabs/php_codesniffer": "^3.0" + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "autoload-dev": { + "psr-4": { + "Doctrine\\Tests\\": "tests/Doctrine/Tests" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/vendor/doctrine/reflection/docs/en/index.rst b/vendor/doctrine/reflection/docs/en/index.rst new file mode 100644 index 0000000..ae85870 --- /dev/null +++ b/vendor/doctrine/reflection/docs/en/index.rst @@ -0,0 +1,22 @@ +Reflection Documentation +================= + +The Doctrine Reflection documentation is a reference guide to everything you need +to know about the reflection project. + +Getting Help +------------ + +If this documentation is not helping to answer questions you have about +Doctrine Reflection don't panic. You can get help from different sources: + +- The `Doctrine Mailing List `_ +- Gitter chat room `#doctrine/reflection `_ +- Report a bug on `GitHub `_. +- On `StackOverflow `_ + +Getting Started +--------------- + +The best way to get started is with the :doc:`Introduction ` section. +Use the sidebar to browse other documentation for the Doctrine PHP Reflection project. diff --git a/vendor/doctrine/reflection/docs/en/reference/index.rst b/vendor/doctrine/reflection/docs/en/reference/index.rst new file mode 100644 index 0000000..e383a17 --- /dev/null +++ b/vendor/doctrine/reflection/docs/en/reference/index.rst @@ -0,0 +1,85 @@ +Introduction +============ + +The Doctrine Reflection project is a simple library used by the various Doctrine projects which adds some additional +functionality on top of the reflection functionality that comes with PHP. It allows you to get the reflection information +about classes, methods and properties statically. + +Installation +============ + +The library can easily be installed with composer. + +.. code-block:: sh + + $ composer require doctrine/reflection + +Setup +===== + +.. code-block:: php + + use Doctrine\Common\Reflection\Psr0FindFile; + use Doctrine\Common\Reflection\StaticReflectionParser; + use App\Model\User; + + $finder = new Psr0FindFile(['App' => [ + '/path/to/project/src/App' + ]]); + + $staticReflectionParser = new StaticReflectionParser(User::class, $finder); + +Usage +===== + +.. code-block:: php + + echo $staticReflectionParser->getClassName(); + echo $staticReflectionParser->getNamespaceName(); + +StaticReflectionClass +===================== + +.. code-block:: php + + $staticReflectionClass = $staticReflectionParser->getReflectionClass(); + + echo $staticReflectionClass->getName(); + + echo $staticReflectionClass->getDocComment(); + + echo $staticReflectionClass->getNamespaceName(); + + print_r($staticReflectionClass->getUseStatements()); + +StaticReflectionMethod +====================== + +.. code-block:: php + + $staticReflectionMethod = $staticReflectionParser->getReflectionMethod('getSomething'); + + echo $staticReflectionMethod->getName(); + + echo $staticReflectionMethod->getDeclaringClass(); + + echo $staticReflectionMethod->getNamespaceName(); + + echo $staticReflectionMethod->getDocComment(); + + print_r($staticReflectionMethod->getUseStatements()); + +StaticReflectionProperty +======================== + +.. code-block:: php + + $staticReflectionProperty = $staticReflectionParser->getReflectionProperty('something'); + + echo $staticReflectionProperty->getName(); + + echo $staticReflectionProperty->getDeclaringClass(); + + echo $staticReflectionProperty->getDocComment(); + + print_r($staticReflectionProperty->getUseStatements()); diff --git a/vendor/doctrine/reflection/docs/en/sidebar.rst b/vendor/doctrine/reflection/docs/en/sidebar.rst new file mode 100644 index 0000000..0672d8d --- /dev/null +++ b/vendor/doctrine/reflection/docs/en/sidebar.rst @@ -0,0 +1,4 @@ +.. toctree:: + :depth: 3 + + reference/index diff --git a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ClassFinderInterface.php b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ClassFinderInterface.php new file mode 100644 index 0000000..8f4ed00 --- /dev/null +++ b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ClassFinderInterface.php @@ -0,0 +1,18 @@ +prefixes = $prefixes; + } + + /** + * {@inheritDoc} + */ + public function findFile($class) + { + if ($class[0] === '\\') { + $class = substr($class, 1); + } + + $lastNsPos = strrpos($class, '\\'); + + if ($lastNsPos !== false) { + // namespaced class name + $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $lastNsPos)) . DIRECTORY_SEPARATOR; + $className = substr($class, $lastNsPos + 1); + } else { + // PEAR-like class name + $classPath = null; + $className = $class; + } + + $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; + + foreach ($this->prefixes as $prefix => $dirs) { + if (strpos($class, $prefix) !== 0) { + continue; + } + + foreach ($dirs as $dir) { + if (is_file($dir . DIRECTORY_SEPARATOR . $classPath)) { + return $dir . DIRECTORY_SEPARATOR . $classPath; + } + } + } + + return null; + } +} diff --git a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ReflectionProviderInterface.php b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ReflectionProviderInterface.php new file mode 100644 index 0000000..473325b --- /dev/null +++ b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ReflectionProviderInterface.php @@ -0,0 +1,31 @@ +getName(); + + if ($object instanceof Proxy && ! $object->__isInitialized()) { + $originalInitializer = $object->__getInitializer(); + $object->__setInitializer(null); + $val = $object->$name ?? null; + $object->__setInitializer($originalInitializer); + + return $val; + } + + return isset($object->$name) ? parent::getValue($object) : null; + } + + /** + * {@inheritDoc} + * + * Avoids triggering lazy loading via `__set` if the provided object + * is a {@see \Doctrine\Common\Proxy\Proxy}. + * @link https://bugs.php.net/bug.php?id=63463 + */ + public function setValue($object, $value = null) + { + if (! ($object instanceof Proxy && ! $object->__isInitialized())) { + parent::setValue($object, $value); + + return; + } + + $originalInitializer = $object->__getInitializer(); + $object->__setInitializer(null); + parent::setValue($object, $value); + $object->__setInitializer($originalInitializer); + } +} diff --git a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionClass.php b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionClass.php new file mode 100644 index 0000000..180f5a6 --- /dev/null +++ b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionClass.php @@ -0,0 +1,413 @@ +staticReflectionParser = $staticReflectionParser; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return $this->staticReflectionParser->getClassName(); + } + + /** + * {@inheritDoc} + */ + public function getDocComment() + { + return $this->staticReflectionParser->getDocComment(); + } + + /** + * {@inheritDoc} + */ + public function getNamespaceName() + { + return $this->staticReflectionParser->getNamespaceName(); + } + + /** + * @return string[] + */ + public function getUseStatements() + { + return $this->staticReflectionParser->getUseStatements(); + } + + /** + * {@inheritDoc} + */ + public function getMethod($name) + { + return $this->staticReflectionParser->getReflectionMethod($name); + } + + /** + * {@inheritDoc} + */ + public function getProperty($name) + { + return $this->staticReflectionParser->getReflectionProperty($name); + } + + /** + * {@inheritDoc} + */ + public static function export($argument, $return = false) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getConstant($name) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getConstants() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getConstructor() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getDefaultProperties() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getEndLine() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getExtension() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getExtensionName() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getFileName() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getInterfaceNames() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getInterfaces() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getMethods($filter = null) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getModifiers() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getParentClass() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getProperties($filter = null) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getShortName() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getStartLine() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getStaticProperties() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getStaticPropertyValue($name, $default = '') + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getTraitAliases() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getTraitNames() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getTraits() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function hasConstant($name) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function hasMethod($name) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function hasProperty($name) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function implementsInterface($interface) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function inNamespace() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isAbstract() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isCloneable() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isFinal() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isInstance($object) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isInstantiable() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isInterface() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isInternal() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isIterateable() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isSubclassOf($class) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isTrait() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isUserDefined() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function newInstance($args) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function newInstanceArgs(array $args = []) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function newInstanceWithoutConstructor() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function setStaticPropertyValue($name, $value) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function __toString() + { + throw new ReflectionException('Method not implemented'); + } +} diff --git a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionMethod.php b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionMethod.php new file mode 100644 index 0000000..67bd998 --- /dev/null +++ b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionMethod.php @@ -0,0 +1,344 @@ +staticReflectionParser = $staticReflectionParser; + $this->methodName = $methodName; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return $this->methodName; + } + + /** + * @return StaticReflectionParser + */ + protected function getStaticReflectionParser() + { + return $this->staticReflectionParser->getStaticReflectionParserForDeclaringClass('method', $this->methodName); + } + + /** + * {@inheritDoc} + */ + public function getDeclaringClass() + { + return $this->getStaticReflectionParser()->getReflectionClass(); + } + + /** + * {@inheritDoc} + */ + public function getNamespaceName() + { + return $this->getStaticReflectionParser()->getNamespaceName(); + } + + /** + * {@inheritDoc} + */ + public function getDocComment() + { + return $this->getStaticReflectionParser()->getDocComment('method', $this->methodName); + } + + /** + * @return string[] + */ + public function getUseStatements() + { + return $this->getStaticReflectionParser()->getUseStatements(); + } + + /** + * {@inheritDoc} + */ + public static function export($class, $name, $return = false) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getClosure($object) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getModifiers() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getPrototype() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function invoke($object, $parameter = null) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function invokeArgs($object, array $args) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isAbstract() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isConstructor() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isDestructor() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isFinal() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isPrivate() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isProtected() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isPublic() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isStatic() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function setAccessible($accessible) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function __toString() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getClosureThis() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getEndLine() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getExtension() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getExtensionName() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getFileName() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getNumberOfParameters() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getNumberOfRequiredParameters() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getParameters() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getShortName() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getStartLine() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getStaticVariables() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function inNamespace() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isClosure() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isDeprecated() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isInternal() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isUserDefined() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function returnsReference() + { + throw new ReflectionException('Method not implemented'); + } +} diff --git a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionParser.php b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionParser.php new file mode 100644 index 0000000..94e0b07 --- /dev/null +++ b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionParser.php @@ -0,0 +1,328 @@ + '', + 'property' => [], + 'method' => [], + ]; + + /** + * The name of the class this class extends, if any. + * + * @var string + */ + protected $parentClassName = ''; + + /** + * The parent PSR-0 Parser. + * + * @var \Doctrine\Common\Reflection\StaticReflectionParser + */ + protected $parentStaticReflectionParser; + + /** + * Parses a class residing in a PSR-0 hierarchy. + * + * @param string $className The full, namespaced class name. + * @param ClassFinderInterface $finder A ClassFinder object which finds the class. + * @param bool $classAnnotationOptimize Only retrieve the class docComment. + * Presumes there is only one statement per line. + */ + public function __construct($className, $finder, $classAnnotationOptimize = false) + { + $this->className = ltrim($className, '\\'); + $lastNsPos = strrpos($this->className, '\\'); + + if ($lastNsPos !== false) { + $this->namespace = substr($this->className, 0, $lastNsPos); + $this->shortClassName = substr($this->className, $lastNsPos + 1); + } else { + $this->shortClassName = $this->className; + } + + $this->finder = $finder; + $this->classAnnotationOptimize = $classAnnotationOptimize; + } + + /** + * @return void + */ + protected function parse() + { + $fileName = $this->finder->findFile($this->className); + + if ($this->parsed || ! $fileName) { + return; + } + $this->parsed = true; + $contents = file_get_contents($fileName); + if ($this->classAnnotationOptimize) { + $regex = sprintf('/\A.*^\s*((abstract|final)\s+)?class\s+%s\s+/sm', $this->shortClassName); + + if (preg_match($regex, $contents, $matches)) { + $contents = $matches[0]; + } + } + $tokenParser = new TokenParser($contents); + $docComment = ''; + $last_token = false; + + while ($token = $tokenParser->next(false)) { + switch ($token[0]) { + case T_USE: + $this->useStatements = array_merge($this->useStatements, $tokenParser->parseUseStatement()); + break; + case T_DOC_COMMENT: + $docComment = $token[1]; + break; + case T_CLASS: + if ($last_token !== T_PAAMAYIM_NEKUDOTAYIM) { + $this->docComment['class'] = $docComment; + $docComment = ''; + } + break; + case T_VAR: + case T_PRIVATE: + case T_PROTECTED: + case T_PUBLIC: + $token = $tokenParser->next(); + if ($token[0] === T_VARIABLE) { + $propertyName = substr($token[1], 1); + $this->docComment['property'][$propertyName] = $docComment; + continue 2; + } + if ($token[0] !== T_FUNCTION) { + // For example, it can be T_FINAL. + continue 2; + } + // No break. + case T_FUNCTION: + // The next string after function is the name, but + // there can be & before the function name so find the + // string. + while (($token = $tokenParser->next()) && $token[0] !== T_STRING) { + continue; + } + $methodName = $token[1]; + $this->docComment['method'][$methodName] = $docComment; + $docComment = ''; + break; + case T_EXTENDS: + $this->parentClassName = $tokenParser->parseClass(); + $nsPos = strpos($this->parentClassName, '\\'); + $fullySpecified = false; + if ($nsPos === 0) { + $fullySpecified = true; + } else { + if ($nsPos) { + $prefix = strtolower(substr($this->parentClassName, 0, $nsPos)); + $postfix = substr($this->parentClassName, $nsPos); + } else { + $prefix = strtolower($this->parentClassName); + $postfix = ''; + } + foreach ($this->useStatements as $alias => $use) { + if ($alias !== $prefix) { + continue; + } + + $this->parentClassName = '\\' . $use . $postfix; + $fullySpecified = true; + } + } + if (! $fullySpecified) { + $this->parentClassName = '\\' . $this->namespace . '\\' . $this->parentClassName; + } + break; + } + + $last_token = $token[0]; + } + } + + /** + * @return StaticReflectionParser + */ + protected function getParentStaticReflectionParser() + { + if (empty($this->parentStaticReflectionParser)) { + $this->parentStaticReflectionParser = new static($this->parentClassName, $this->finder); + } + + return $this->parentStaticReflectionParser; + } + + /** + * @return string + */ + public function getClassName() + { + return $this->className; + } + + /** + * @return string + */ + public function getNamespaceName() + { + return $this->namespace; + } + + /** + * {@inheritDoc} + */ + public function getReflectionClass() + { + return new StaticReflectionClass($this); + } + + /** + * {@inheritDoc} + */ + public function getReflectionMethod($methodName) + { + return new StaticReflectionMethod($this, $methodName); + } + + /** + * {@inheritDoc} + */ + public function getReflectionProperty($propertyName) + { + return new StaticReflectionProperty($this, $propertyName); + } + + /** + * Gets the use statements from this file. + * + * @return string[] + */ + public function getUseStatements() + { + $this->parse(); + + return $this->useStatements; + } + + /** + * Gets the doc comment. + * + * @param string $type The type: 'class', 'property' or 'method'. + * @param string $name The name of the property or method, not needed for 'class'. + * + * @return string The doc comment, empty string if none. + */ + public function getDocComment($type = 'class', $name = '') + { + $this->parse(); + + return $name ? $this->docComment[$type][$name] : $this->docComment[$type]; + } + + /** + * Gets the PSR-0 parser for the declaring class. + * + * @param string $type The type: 'property' or 'method'. + * @param string $name The name of the property or method. + * + * @return StaticReflectionParser A static reflection parser for the declaring class. + * + * @throws ReflectionException + */ + public function getStaticReflectionParserForDeclaringClass($type, $name) + { + $this->parse(); + if (isset($this->docComment[$type][$name])) { + return $this; + } + if (! empty($this->parentClassName)) { + return $this->getParentStaticReflectionParser()->getStaticReflectionParserForDeclaringClass($type, $name); + } + throw new ReflectionException('Invalid ' . $type . ' "' . $name . '"'); + } +} diff --git a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionProperty.php b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionProperty.php new file mode 100644 index 0000000..b94fda3 --- /dev/null +++ b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionProperty.php @@ -0,0 +1,160 @@ +staticReflectionParser = $staticReflectionParser; + $this->propertyName = $propertyName; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return $this->propertyName; + } + + /** + * @return StaticReflectionParser + */ + protected function getStaticReflectionParser() + { + return $this->staticReflectionParser->getStaticReflectionParserForDeclaringClass('property', $this->propertyName); + } + + /** + * {@inheritDoc} + */ + public function getDeclaringClass() + { + return $this->getStaticReflectionParser()->getReflectionClass(); + } + + /** + * {@inheritDoc} + */ + public function getDocComment() + { + return $this->getStaticReflectionParser()->getDocComment('property', $this->propertyName); + } + + /** + * @return string[] + */ + public function getUseStatements() + { + return $this->getStaticReflectionParser()->getUseStatements(); + } + + /** + * {@inheritDoc} + */ + public static function export($class, $name, $return = false) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getModifiers() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function getValue($object = null) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isDefault() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isPrivate() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isProtected() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isPublic() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function isStatic() + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function setAccessible($accessible) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function setValue($object, $value = null) + { + throw new ReflectionException('Method not implemented'); + } + + /** + * {@inheritDoc} + */ + public function __toString() + { + throw new ReflectionException('Method not implemented'); + } +} diff --git a/vendor/doctrine/reflection/phpstan.neon b/vendor/doctrine/reflection/phpstan.neon new file mode 100644 index 0000000..4c8102b --- /dev/null +++ b/vendor/doctrine/reflection/phpstan.neon @@ -0,0 +1,6 @@ +includes: + - vendor/phpstan/phpstan-phpunit/extension.neon + +parameters: + ignoreErrors: + - '#Doctrine\\Common\\Reflection\\StaticReflection[a-zA-Z0-9_]+::__construct\(\) does not call parent constructor from Reflection[a-zA-Z0-9_]+#' diff --git a/vendor/jdorn/sql-formatter/.gitignore b/vendor/jdorn/sql-formatter/.gitignore new file mode 100644 index 0000000..48b8bf9 --- /dev/null +++ b/vendor/jdorn/sql-formatter/.gitignore @@ -0,0 +1 @@ +vendor/ diff --git a/vendor/jdorn/sql-formatter/.travis.yml b/vendor/jdorn/sql-formatter/.travis.yml new file mode 100644 index 0000000..310d8e0 --- /dev/null +++ b/vendor/jdorn/sql-formatter/.travis.yml @@ -0,0 +1,5 @@ +language: php +php: + - 5.4 + - 5.3 +script: phpunit --coverage-text diff --git a/vendor/jdorn/sql-formatter/LICENSE.txt b/vendor/jdorn/sql-formatter/LICENSE.txt new file mode 100644 index 0000000..e822279 --- /dev/null +++ b/vendor/jdorn/sql-formatter/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Jeremy Dorn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/jdorn/sql-formatter/README.md b/vendor/jdorn/sql-formatter/README.md new file mode 100644 index 0000000..a144323 --- /dev/null +++ b/vendor/jdorn/sql-formatter/README.md @@ -0,0 +1,185 @@ +SqlFormatter +============= + +A lightweight php class for formatting sql statements. + +It can automatically indent and add line breaks in addition to syntax highlighting. + +History +============ + +I found myself having to debug auto-generated SQL statements all the time and +wanted some way to easily output formatted HTML without having to include a +huge library or copy and paste into online formatters. + +I was originally planning to extract the formatting code from PhpMyAdmin, +but that was 10,000+ lines of code and used global variables. + +I saw that other people had the same problem and used Stack Overflow user +losif's answer as a starting point. http://stackoverflow.com/a/3924147 + +Usage +============ + +The SqlFormatter class has a static method 'format' which takes a SQL string +as input and returns a formatted HTML block inside a pre tag. + +Sample usage: + +```php += NOW()) ) + GROUP BY Column1 ORDER BY Column3 DESC LIMIT 5,10"; + +echo SqlFormatter::format($query); +``` + +Output: + +![](http://jdorn.github.com/sql-formatter/format-highlight.png) + +Formatting Only +------------------------- +If you don't want syntax highlighting and only want the indentations and +line breaks, pass in false as the second parameter. + +This is useful for outputting to error logs or other non-html formats. + +```php +=5.2.4" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "authors": [ + { + "name": "Jeremy Dorn", + "email": "jeremy@jeremydorn.com", + "homepage": "http://jeremydorn.com/" + } + ], + "autoload": { + "classmap": ["lib"] + }, + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + } +} diff --git a/vendor/jdorn/sql-formatter/composer.lock b/vendor/jdorn/sql-formatter/composer.lock new file mode 100644 index 0000000..379ab13 --- /dev/null +++ b/vendor/jdorn/sql-formatter/composer.lock @@ -0,0 +1,422 @@ +{ + "hash": "a709b40d4a35e7077aa40fbd0f78f6c6", + "packages": [ + + ], + "packages-dev": [ + { + "name": "phpunit/php-code-coverage", + "version": "1.2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "1.2.9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1.2.9", + "reference": "1.2.9", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": ">=1.3.0@stable", + "phpunit/php-text-template": ">=1.1.1@stable", + "phpunit/php-token-stream": ">=1.1.3@stable" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.0.5" + }, + "type": "library", + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2013-02-26 18:55:56" + }, + { + "name": "phpunit/php-file-iterator", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "2deb24c65ea78e126daa8d45b2089ddc29ec1d26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2deb24c65ea78e126daa8d45b2089ddc29ec1d26", + "reference": "2deb24c65ea78e126daa8d45b2089ddc29ec1d26", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "File/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2013-01-07 10:47:05" + }, + { + "name": "phpunit/php-text-template", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "1eeef106193d2f8c539728e566bb4793071a9e18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/1eeef106193d2f8c539728e566bb4793071a9e18", + "reference": "1eeef106193d2f8c539728e566bb4793071a9e18", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "Text/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2013-01-07 10:56:17" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "ecf7920b27003a9412b07dad79dbb5ad1249e6c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/ecf7920b27003a9412b07dad79dbb5ad1249e6c3", + "reference": "ecf7920b27003a9412b07dad79dbb5ad1249e6c3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2013-01-30 06:08:51" + }, + { + "name": "phpunit/php-token-stream", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "c25dd88e1592e66dee2553c99ef244203d5a1b98" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c25dd88e1592e66dee2553c99ef244203d5a1b98", + "reference": "c25dd88e1592e66dee2553c99ef244203d5a1b98", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2013-01-07 10:56:35" + }, + { + "name": "phpunit/phpunit", + "version": "3.7.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "2c67e52445416bb7c14046b432acd7eb79e4e612" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2c67e52445416bb7c14046b432acd7eb79e4e612", + "reference": "2c67e52445416bb7c14046b432acd7eb79e4e612", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpunit/php-code-coverage": ">=1.2.1,<1.3.0", + "phpunit/php-file-iterator": ">=1.3.1", + "phpunit/php-text-template": ">=1.1.1", + "phpunit/php-timer": ">=1.0.2,<1.1.0", + "phpunit/phpunit-mock-objects": ">=1.2.0,<1.3.0", + "symfony/yaml": ">=2.2.0" + }, + "require-dev": { + "pear-pear/pear": "1.9.4" + }, + "suggest": { + "ext-json": "*", + "ext-simplexml": "*", + "ext-tokenizer": "*", + "phpunit/php-invoker": ">=1.1.0,<1.2.0" + }, + "bin": [ + "composer/bin/phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.7.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHPUnit/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "", + "../../symfony/yaml/" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "http://www.phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2013-03-11 07:06:05" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "1.2.x-dev", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "d49b5683200b5db9b1c64cb06f52f50d147891c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/d49b5683200b5db9b1c64cb06f52f50d147891c4", + "reference": "d49b5683200b5db9b1c64cb06f52f50d147891c4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-text-template": ">=1.1.1@stable" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "autoload": { + "classmap": [ + "PHPUnit/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2013-02-05 07:46:41" + }, + { + "name": "symfony/yaml", + "version": "dev-master", + "target-dir": "Symfony/Component/Yaml", + "source": { + "type": "git", + "url": "https://github.com/symfony/Yaml.git", + "reference": "f198ac28048eeceae852419c076123aaee59cd1c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/f198ac28048eeceae852419c076123aaee59cd1c", + "reference": "f198ac28048eeceae852419c076123aaee59cd1c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Yaml\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "http://symfony.com", + "time": "2013-01-31 21:39:01" + } + ], + "aliases": [ + + ], + "minimum-stability": "dev", + "stability-flags": [ + + ], + "platform": { + "php": ">=5.2.4" + }, + "platform-dev": [ + + ] +} diff --git a/vendor/jdorn/sql-formatter/examples/cli.php b/vendor/jdorn/sql-formatter/examples/cli.php new file mode 100644 index 0000000..17ee0e1 --- /dev/null +++ b/vendor/jdorn/sql-formatter/examples/cli.php @@ -0,0 +1,17 @@ +Run this php script from the command line to see CLI syntax highlighting and formatting. It support Unix pipes or command line argument style.

"; + echo "
php examples/cli.php \"SELECT * FROM MyTable WHERE (id>5 AND \\`name\\` LIKE \\"testing\\");\"
"; + echo "
echo \"SELECT * FROM MyTable WHERE (id>5 AND \\`name\\` LIKE \\"testing\\");\" | php examples/cli.php
"; +} + +if(isset($argv[1])) { + $sql = $argv[1]; +} +else { + $sql = stream_get_contents(fopen("php://stdin", "r")); +} + +require_once(__DIR__.'/../lib/SqlFormatter.php'); + +echo SqlFormatter::format($sql); diff --git a/vendor/jdorn/sql-formatter/examples/examples.php b/vendor/jdorn/sql-formatter/examples/examples.php new file mode 100644 index 0000000..f54cfb0 --- /dev/null +++ b/vendor/jdorn/sql-formatter/examples/examples.php @@ -0,0 +1,270 @@ + + + + SqlFormatter Examples + + + += + DATE_FORMAT((DATE_SUB(NOW(),INTERVAL 1 DAY)),'%Y-%c-%d') AND t_create + < DATE_FORMAT(NOW(), '%Y-%c-%d') ORDER BY d.id LIMIT 2,10) a, + orc_scheme_detail b WHERE a.id = b.id", + + "SELECT * from Table1 LEFT + OUTER JOIN Table2 on Table1.id = Table2.id", + + "SELECT * FROM MyTable WHERE id = 46", + + "SELECT count(*),`Column1` as count,`Testing`, `Testing Three` FROM `Table1` + WHERE Column1 = 'testing' AND ( (`Column2` = `Column3` OR Column4 >= NOW()) ) + GROUP BY Column1 ORDER BY Column3 DESC LIMIT 5,10", + + "select * from `Table`, (SELECT group_concat(column1) as col FROM Table2 GROUP BY category) + Table2, Table3 where Table2.col = (Table3.col2 - `Table`.id)", + + "insert ignore into Table3 (column1, column2) VALUES ('test1','test2'), ('test3','test4');", + + "UPDATE MyTable SET name='sql', category='databases' WHERE id > '65'", + + "delete from MyTable WHERE name LIKE \"test%\"", + + "SELECT * FROM UnmatchedParens WHERE ( A = B)) AND (((Test=1)", + + "-- This is a comment + SELECT + /* This is another comment + On more than one line */ + Id #This is one final comment + as temp, DateCreated as Created FROM MyTable;", +); + +// Example statements for splitting SQL strings into individual queries +$split_statements = array( + "DROP TABLE IF EXISTS MyTable; + CREATE TABLE MyTable ( id int ); + INSERT INTO MyTable (id) + VALUES + (1),(2),(3),(4); + SELECT * FROM MyTable;", + + "SELECT \";\"; SELECT \";\\\"; a;\"; + SELECT \"; + abc\"; + SELECT a,b #comment; + FROM test;", + + " + -- Drop the table first if it exists + DROP TABLE IF EXISTS MyTable; + + -- Create the table + CREATE TABLE MyTable ( id int ); + + -- Insert values + INSERT INTO MyTable (id) + VALUES + (1),(2),(3),(4); + + -- Done", +); + +// Example statements for removing comments +$comment_statements = array( + "-- This is a comment + SELECT + /* This is another comment + On more than one line */ + Id #This is one final comment + as temp, DateCreated as Created FROM MyTable;", +); +?> + + +

Formatting And Syntax Highlighting

+ +
+ Usage: +
+    '); ?>
+    
+
+ + + + + + + + + + + +
OriginalFormatted And Highlighted
+
+
+ + +

Formatting Only

+ +
+ Usage: +
+    '); ?>
+    
+
+ + + + + + + + + + + +
OriginalFormatted
+
+
+ + +

Syntax Highlighting Only

+ +
+ Usage: +
+    '); ?>
+    
+
+ + + + + + + + + + + +
OriginalHighlighted
+
+
+ + +

Compress Query

+ +
+ Usage: +
+    '); ?>
+    
+
+ + + + + + + + + + + +
OriginalCompressed
+
+
+ + +

Splitting SQL Strings Into Individual Queries

+ +
+ Usage: +
+    '); ?>
+    
+
+ + + + + + + + + + + +
OriginalSplit
+
+
"; + foreach ($queries as $query) { + echo "
  • " . SqlFormatter::highlight($query) . "
  • "; + } + echo ""; + ?>
    + + +

    Removing Comments

    + +
    + Usage: +
    +    '); ?>
    +    
    +
    + + + + + + + + + + + +
    OriginalComments Removed
    +
    +
    +
    +
    + + + diff --git a/vendor/jdorn/sql-formatter/lib/SqlFormatter.php b/vendor/jdorn/sql-formatter/lib/SqlFormatter.php new file mode 100644 index 0000000..e569682 --- /dev/null +++ b/vendor/jdorn/sql-formatter/lib/SqlFormatter.php @@ -0,0 +1,1080 @@ + + * @author Florin Patan + * @copyright 2013 Jeremy Dorn + * @license http://opensource.org/licenses/MIT + * @link http://github.com/jdorn/sql-formatter + * @version 1.2.17 + */ +class SqlFormatter +{ + // Constants for token types + const TOKEN_TYPE_WHITESPACE = 0; + const TOKEN_TYPE_WORD = 1; + const TOKEN_TYPE_QUOTE = 2; + const TOKEN_TYPE_BACKTICK_QUOTE = 3; + const TOKEN_TYPE_RESERVED = 4; + const TOKEN_TYPE_RESERVED_TOPLEVEL = 5; + const TOKEN_TYPE_RESERVED_NEWLINE = 6; + const TOKEN_TYPE_BOUNDARY = 7; + const TOKEN_TYPE_COMMENT = 8; + const TOKEN_TYPE_BLOCK_COMMENT = 9; + const TOKEN_TYPE_NUMBER = 10; + const TOKEN_TYPE_ERROR = 11; + const TOKEN_TYPE_VARIABLE = 12; + + // Constants for different components of a token + const TOKEN_TYPE = 0; + const TOKEN_VALUE = 1; + + // Reserved words (for syntax highlighting) + protected static $reserved = array( + 'ACCESSIBLE', 'ACTION', 'AGAINST', 'AGGREGATE', 'ALGORITHM', 'ALL', 'ALTER', 'ANALYSE', 'ANALYZE', 'AS', 'ASC', + 'AUTOCOMMIT', 'AUTO_INCREMENT', 'BACKUP', 'BEGIN', 'BETWEEN', 'BINLOG', 'BOTH', 'CASCADE', 'CASE', 'CHANGE', 'CHANGED', 'CHARACTER SET', + 'CHARSET', 'CHECK', 'CHECKSUM', 'COLLATE', 'COLLATION', 'COLUMN', 'COLUMNS', 'COMMENT', 'COMMIT', 'COMMITTED', 'COMPRESSED', 'CONCURRENT', + 'CONSTRAINT', 'CONTAINS', 'CONVERT', 'CREATE', 'CROSS', 'CURRENT_TIMESTAMP', 'DATABASE', 'DATABASES', 'DAY', 'DAY_HOUR', 'DAY_MINUTE', + 'DAY_SECOND', 'DEFAULT', 'DEFINER', 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 'DISTINCT', 'DISTINCTROW', 'DIV', + 'DO', 'DUMPFILE', 'DUPLICATE', 'DYNAMIC', 'ELSE', 'ENCLOSED', 'END', 'ENGINE', 'ENGINE_TYPE', 'ENGINES', 'ESCAPE', 'ESCAPED', 'EVENTS', 'EXECUTE', + 'EXISTS', 'EXPLAIN', 'EXTENDED', 'FAST', 'FIELDS', 'FILE', 'FIRST', 'FIXED', 'FLUSH', 'FOR', 'FORCE', 'FOREIGN', 'FULL', 'FULLTEXT', + 'FUNCTION', 'GLOBAL', 'GRANT', 'GRANTS', 'GROUP_CONCAT', 'HEAP', 'HIGH_PRIORITY', 'HOSTS', 'HOUR', 'HOUR_MINUTE', + 'HOUR_SECOND', 'IDENTIFIED', 'IF', 'IFNULL', 'IGNORE', 'IN', 'INDEX', 'INDEXES', 'INFILE', 'INSERT', 'INSERT_ID', 'INSERT_METHOD', 'INTERVAL', + 'INTO', 'INVOKER', 'IS', 'ISOLATION', 'KEY', 'KEYS', 'KILL', 'LAST_INSERT_ID', 'LEADING', 'LEVEL', 'LIKE', 'LINEAR', + 'LINES', 'LOAD', 'LOCAL', 'LOCK', 'LOCKS', 'LOGS', 'LOW_PRIORITY', 'MARIA', 'MASTER', 'MASTER_CONNECT_RETRY', 'MASTER_HOST', 'MASTER_LOG_FILE', + 'MATCH','MAX_CONNECTIONS_PER_HOUR', 'MAX_QUERIES_PER_HOUR', 'MAX_ROWS', 'MAX_UPDATES_PER_HOUR', 'MAX_USER_CONNECTIONS', + 'MEDIUM', 'MERGE', 'MINUTE', 'MINUTE_SECOND', 'MIN_ROWS', 'MODE', 'MODIFY', + 'MONTH', 'MRG_MYISAM', 'MYISAM', 'NAMES', 'NATURAL', 'NOT', 'NOW()','NULL', 'OFFSET', 'ON', 'OPEN', 'OPTIMIZE', 'OPTION', 'OPTIONALLY', + 'ON UPDATE', 'ON DELETE', 'OUTFILE', 'PACK_KEYS', 'PAGE', 'PARTIAL', 'PARTITION', 'PARTITIONS', 'PASSWORD', 'PRIMARY', 'PRIVILEGES', 'PROCEDURE', + 'PROCESS', 'PROCESSLIST', 'PURGE', 'QUICK', 'RANGE', 'RAID0', 'RAID_CHUNKS', 'RAID_CHUNKSIZE','RAID_TYPE', 'READ', 'READ_ONLY', + 'READ_WRITE', 'REFERENCES', 'REGEXP', 'RELOAD', 'RENAME', 'REPAIR', 'REPEATABLE', 'REPLACE', 'REPLICATION', 'RESET', 'RESTORE', 'RESTRICT', + 'RETURN', 'RETURNS', 'REVOKE', 'RLIKE', 'ROLLBACK', 'ROW', 'ROWS', 'ROW_FORMAT', 'SECOND', 'SECURITY', 'SEPARATOR', + 'SERIALIZABLE', 'SESSION', 'SHARE', 'SHOW', 'SHUTDOWN', 'SLAVE', 'SONAME', 'SOUNDS', 'SQL', 'SQL_AUTO_IS_NULL', 'SQL_BIG_RESULT', + 'SQL_BIG_SELECTS', 'SQL_BIG_TABLES', 'SQL_BUFFER_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_LOG_BIN', 'SQL_LOG_OFF', 'SQL_LOG_UPDATE', + 'SQL_LOW_PRIORITY_UPDATES', 'SQL_MAX_JOIN_SIZE', 'SQL_QUOTE_SHOW_CREATE', 'SQL_SAFE_UPDATES', 'SQL_SELECT_LIMIT', 'SQL_SLAVE_SKIP_COUNTER', + 'SQL_SMALL_RESULT', 'SQL_WARNINGS', 'SQL_CACHE', 'SQL_NO_CACHE', 'START', 'STARTING', 'STATUS', 'STOP', 'STORAGE', + 'STRAIGHT_JOIN', 'STRING', 'STRIPED', 'SUPER', 'TABLE', 'TABLES', 'TEMPORARY', 'TERMINATED', 'THEN', 'TO', 'TRAILING', 'TRANSACTIONAL', 'TRUE', + 'TRUNCATE', 'TYPE', 'TYPES', 'UNCOMMITTED', 'UNIQUE', 'UNLOCK', 'UNSIGNED', 'USAGE', 'USE', 'USING', 'VARIABLES', + 'VIEW', 'WHEN', 'WITH', 'WORK', 'WRITE', 'YEAR_MONTH' + ); + + // For SQL formatting + // These keywords will all be on their own line + protected static $reserved_toplevel = array( + 'SELECT', 'FROM', 'WHERE', 'SET', 'ORDER BY', 'GROUP BY', 'LIMIT', 'DROP', + 'VALUES', 'UPDATE', 'HAVING', 'ADD', 'AFTER', 'ALTER TABLE', 'DELETE FROM', 'UNION ALL', 'UNION', 'EXCEPT', 'INTERSECT' + ); + + protected static $reserved_newline = array( + 'LEFT OUTER JOIN', 'RIGHT OUTER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'OUTER JOIN', 'INNER JOIN', 'JOIN', 'XOR', 'OR', 'AND' + ); + + protected static $functions = array ( + 'ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_DECRYPT', 'AES_ENCRYPT', 'AREA', 'ASBINARY', 'ASCII', 'ASIN', 'ASTEXT', 'ATAN', 'ATAN2', + 'AVG', 'BDMPOLYFROMTEXT', 'BDMPOLYFROMWKB', 'BDPOLYFROMTEXT', 'BDPOLYFROMWKB', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_COUNT', 'BIT_LENGTH', + 'BIT_OR', 'BIT_XOR', 'BOUNDARY', 'BUFFER', 'CAST', 'CEIL', 'CEILING', 'CENTROID', 'CHAR', 'CHARACTER_LENGTH', 'CHARSET', 'CHAR_LENGTH', + 'COALESCE', 'COERCIBILITY', 'COLLATION', 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONNECTION_ID', 'CONTAINS', 'CONV', 'CONVERT', 'CONVERT_TZ', + 'CONVEXHULL', 'COS', 'COT', 'COUNT', 'CRC32', 'CROSSES', 'CURDATE', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER', + 'CURTIME', 'DATABASE', 'DATE', 'DATEDIFF', 'DATE_ADD', 'DATE_DIFF', 'DATE_FORMAT', 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', + 'DAYOFYEAR', 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 'DIFFERENCE', 'DIMENSION', 'DISJOINT', 'DISTANCE', 'ELT', 'ENCODE', + 'ENCRYPT', 'ENDPOINT', 'ENVELOPE', 'EQUALS', 'EXP', 'EXPORT_SET', 'EXTERIORRING', 'EXTRACT', 'EXTRACTVALUE', 'FIELD', 'FIND_IN_SET', 'FLOOR', + 'FORMAT', 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', 'GEOMCOLLFROMTEXT', 'GEOMCOLLFROMWKB', 'GEOMETRYCOLLECTION', 'GEOMETRYCOLLECTIONFROMTEXT', + 'GEOMETRYCOLLECTIONFROMWKB', 'GEOMETRYFROMTEXT', 'GEOMETRYFROMWKB', 'GEOMETRYN', 'GEOMETRYTYPE', 'GEOMFROMTEXT', 'GEOMFROMWKB', 'GET_FORMAT', + 'GET_LOCK', 'GLENGTH', 'GREATEST', 'GROUP_CONCAT', 'GROUP_UNIQUE_USERS', 'HEX', 'HOUR', 'IF', 'IFNULL', 'INET_ATON', 'INET_NTOA', 'INSERT', 'INSTR', + 'INTERIORRINGN', 'INTERSECTION', 'INTERSECTS', 'INTERVAL', 'ISCLOSED', 'ISEMPTY', 'ISNULL', 'ISRING', 'ISSIMPLE', 'IS_FREE_LOCK', 'IS_USED_LOCK', + 'LAST_DAY', 'LAST_INSERT_ID', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 'LINEFROMTEXT', 'LINEFROMWKB', 'LINESTRING', 'LINESTRINGFROMTEXT', 'LINESTRINGFROMWKB', + 'LN', 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATE', 'LOG', 'LOG10', 'LOG2', 'LOWER', 'LPAD', 'LTRIM', 'MAKEDATE', 'MAKETIME', 'MAKE_SET', + 'MASTER_POS_WAIT', 'MAX', 'MBRCONTAINS', 'MBRDISJOINT', 'MBREQUAL', 'MBRINTERSECTS', 'MBROVERLAPS', 'MBRTOUCHES', 'MBRWITHIN', 'MD5', 'MICROSECOND', + 'MID', 'MIN', 'MINUTE', 'MLINEFROMTEXT', 'MLINEFROMWKB', 'MOD', 'MONTH', 'MONTHNAME', 'MPOINTFROMTEXT', 'MPOINTFROMWKB', 'MPOLYFROMTEXT', 'MPOLYFROMWKB', + 'MULTILINESTRING', 'MULTILINESTRINGFROMTEXT', 'MULTILINESTRINGFROMWKB', 'MULTIPOINT', 'MULTIPOINTFROMTEXT', 'MULTIPOINTFROMWKB', 'MULTIPOLYGON', + 'MULTIPOLYGONFROMTEXT', 'MULTIPOLYGONFROMWKB', 'NAME_CONST', 'NULLIF', 'NUMGEOMETRIES', 'NUMINTERIORRINGS', 'NUMPOINTS', 'OCT', 'OCTET_LENGTH', + 'OLD_PASSWORD', 'ORD', 'OVERLAPS', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', 'PI', 'POINT', 'POINTFROMTEXT', 'POINTFROMWKB', 'POINTN', 'POINTONSURFACE', + 'POLYFROMTEXT', 'POLYFROMWKB', 'POLYGON', 'POLYGONFROMTEXT', 'POLYGONFROMWKB', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RAND', + 'RELATED', 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'ROW_COUNT', 'RPAD', 'RTRIM', 'SCHEMA', 'SECOND', 'SEC_TO_TIME', + 'SESSION_USER', 'SHA', 'SHA1', 'SIGN', 'SIN', 'SLEEP', 'SOUNDEX', 'SPACE', 'SQRT', 'SRID', 'STARTPOINT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', + 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTR', 'SUBSTRING', 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'SYMDIFFERENCE', 'SYSDATE', 'SYSTEM_USER', 'TAN', + 'TIME', 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TOUCHES', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', + 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UNIQUE_USERS', 'UNIX_TIMESTAMP', 'UPDATEXML', 'UPPER', 'USER', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', + 'UUID', 'VARIANCE', 'VAR_POP', 'VAR_SAMP', 'VERSION', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'WITHIN', 'X', 'Y', 'YEAR', 'YEARWEEK' + ); + + // Punctuation that can be used as a boundary between other tokens + protected static $boundaries = array(',', ';',':', ')', '(', '.', '=', '<', '>', '+', '-', '*', '/', '!', '^', '%', '|', '&', '#'); + + // For HTML syntax highlighting + // Styles applied to different token types + public static $quote_attributes = 'style="color: blue;"'; + public static $backtick_quote_attributes = 'style="color: purple;"'; + public static $reserved_attributes = 'style="font-weight:bold;"'; + public static $boundary_attributes = ''; + public static $number_attributes = 'style="color: green;"'; + public static $word_attributes = 'style="color: #333;"'; + public static $error_attributes = 'style="background-color: red;"'; + public static $comment_attributes = 'style="color: #aaa;"'; + public static $variable_attributes = 'style="color: orange;"'; + public static $pre_attributes = 'style="color: black; background-color: white;"'; + + // Boolean - whether or not the current environment is the CLI + // This affects the type of syntax highlighting + // If not defined, it will be determined automatically + public static $cli; + + // For CLI syntax highlighting + public static $cli_quote = "\x1b[34;1m"; + public static $cli_backtick_quote = "\x1b[35;1m"; + public static $cli_reserved = "\x1b[37m"; + public static $cli_boundary = ""; + public static $cli_number = "\x1b[32;1m"; + public static $cli_word = ""; + public static $cli_error = "\x1b[31;1;7m"; + public static $cli_comment = "\x1b[30;1m"; + public static $cli_functions = "\x1b[37m"; + public static $cli_variable = "\x1b[36;1m"; + + // The tab character to use when formatting SQL + public static $tab = ' '; + + // This flag tells us if queries need to be enclosed in
     tags
    +    public static $use_pre = true;
    +
    +    // This flag tells us if SqlFormatted has been initialized
    +    protected static $init;
    +
    +    // Regular expressions for tokenizing
    +    protected static $regex_boundaries;
    +    protected static $regex_reserved;
    +    protected static $regex_reserved_newline;
    +    protected static $regex_reserved_toplevel;
    +    protected static $regex_function;
    +
    +    // Cache variables
    +    // Only tokens shorter than this size will be cached.  Somewhere between 10 and 20 seems to work well for most cases.
    +    public static $max_cachekey_size = 15;
    +    protected static $token_cache = array();
    +    protected static $cache_hits = 0;
    +    protected static $cache_misses = 0;
    +
    +    /**
    +     * Get stats about the token cache
    +     * @return Array An array containing the keys 'hits', 'misses', 'entries', and 'size' in bytes
    +     */
    +    public static function getCacheStats()
    +    {
    +        return array(
    +            'hits'=>self::$cache_hits,
    +            'misses'=>self::$cache_misses,
    +            'entries'=>count(self::$token_cache),
    +            'size'=>strlen(serialize(self::$token_cache))
    +        );
    +    }
    +
    +    /**
    +     * Stuff that only needs to be done once.  Builds regular expressions and sorts the reserved words.
    +     */
    +    protected static function init()
    +    {
    +        if (self::$init) return;
    +
    +        // Sort reserved word list from longest word to shortest, 3x faster than usort
    +        $reservedMap = array_combine(self::$reserved, array_map('strlen', self::$reserved));
    +        arsort($reservedMap);
    +        self::$reserved = array_keys($reservedMap);
    +
    +        // Set up regular expressions
    +        self::$regex_boundaries = '('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$boundaries)).')';
    +        self::$regex_reserved = '('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$reserved)).')';
    +        self::$regex_reserved_toplevel = str_replace(' ','\\s+','('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$reserved_toplevel)).')');
    +        self::$regex_reserved_newline = str_replace(' ','\\s+','('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$reserved_newline)).')');
    +
    +        self::$regex_function = '('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$functions)).')';
    +
    +        self::$init = true;
    +    }
    +
    +    /**
    +     * Return the next token and token type in a SQL string.
    +     * Quoted strings, comments, reserved words, whitespace, and punctuation are all their own tokens.
    +     *
    +     * @param String $string   The SQL string
    +     * @param array  $previous The result of the previous getNextToken() call
    +     *
    +     * @return Array An associative array containing the type and value of the token.
    +     */
    +    protected static function getNextToken($string, $previous = null)
    +    {
    +        // Whitespace
    +        if (preg_match('/^\s+/',$string,$matches)) {
    +            return array(
    +                self::TOKEN_VALUE => $matches[0],
    +                self::TOKEN_TYPE=>self::TOKEN_TYPE_WHITESPACE
    +            );
    +        }
    +
    +        // Comment
    +        if ($string[0] === '#' || (isset($string[1])&&($string[0]==='-'&&$string[1]==='-') || ($string[0]==='/'&&$string[1]==='*'))) {
    +            // Comment until end of line
    +            if ($string[0] === '-' || $string[0] === '#') {
    +                $last = strpos($string, "\n");
    +                $type = self::TOKEN_TYPE_COMMENT;
    +            } else { // Comment until closing comment tag
    +                $last = strpos($string, "*/", 2) + 2;
    +                $type = self::TOKEN_TYPE_BLOCK_COMMENT;
    +            }
    +
    +            if ($last === false) {
    +                $last = strlen($string);
    +            }
    +
    +            return array(
    +                self::TOKEN_VALUE => substr($string, 0, $last),
    +                self::TOKEN_TYPE  => $type
    +            );
    +        }
    +
    +        // Quoted String
    +        if ($string[0]==='"' || $string[0]==='\'' || $string[0]==='`') {
    +            $return = array(
    +                self::TOKEN_TYPE => ($string[0]==='`'? self::TOKEN_TYPE_BACKTICK_QUOTE : self::TOKEN_TYPE_QUOTE),
    +                self::TOKEN_VALUE => self::getQuotedString($string)
    +            );
    +
    +            return $return;
    +        }
    +
    +        // User-defined Variable
    +        if ($string[0] === '@' && isset($string[1])) {
    +            $ret = array(
    +                self::TOKEN_VALUE => null,
    +                self::TOKEN_TYPE => self::TOKEN_TYPE_VARIABLE
    +            );
    +            
    +            // If the variable name is quoted
    +            if ($string[1]==='"' || $string[1]==='\'' || $string[1]==='`') {
    +                $ret[self::TOKEN_VALUE] = '@'.self::getQuotedString(substr($string,1));
    +            }
    +            // Non-quoted variable name
    +            else {
    +                preg_match('/^(@[a-zA-Z0-9\._\$]+)/',$string,$matches);
    +                if ($matches) {
    +                    $ret[self::TOKEN_VALUE] = $matches[1];
    +                }
    +            }
    +            
    +            if($ret[self::TOKEN_VALUE] !== null) return $ret;
    +        }
    +
    +        // Number (decimal, binary, or hex)
    +        if (preg_match('/^([0-9]+(\.[0-9]+)?|0x[0-9a-fA-F]+|0b[01]+)($|\s|"\'`|'.self::$regex_boundaries.')/',$string,$matches)) {
    +            return array(
    +                self::TOKEN_VALUE => $matches[1],
    +                self::TOKEN_TYPE=>self::TOKEN_TYPE_NUMBER
    +            );
    +        }
    +
    +        // Boundary Character (punctuation and symbols)
    +        if (preg_match('/^('.self::$regex_boundaries.')/',$string,$matches)) {
    +            return array(
    +                self::TOKEN_VALUE => $matches[1],
    +                self::TOKEN_TYPE  => self::TOKEN_TYPE_BOUNDARY
    +            );
    +        }
    +
    +        // A reserved word cannot be preceded by a '.'
    +        // this makes it so in "mytable.from", "from" is not considered a reserved word
    +        if (!$previous || !isset($previous[self::TOKEN_VALUE]) || $previous[self::TOKEN_VALUE] !== '.') {
    +            $upper = strtoupper($string);
    +            // Top Level Reserved Word
    +            if (preg_match('/^('.self::$regex_reserved_toplevel.')($|\s|'.self::$regex_boundaries.')/', $upper,$matches)) {
    +                return array(
    +                    self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED_TOPLEVEL,
    +                    self::TOKEN_VALUE=>substr($string,0,strlen($matches[1]))
    +                );
    +            }
    +            // Newline Reserved Word
    +            if (preg_match('/^('.self::$regex_reserved_newline.')($|\s|'.self::$regex_boundaries.')/', $upper,$matches)) {
    +                return array(
    +                    self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED_NEWLINE,
    +                    self::TOKEN_VALUE=>substr($string,0,strlen($matches[1]))
    +                );
    +            }
    +            // Other Reserved Word
    +            if (preg_match('/^('.self::$regex_reserved.')($|\s|'.self::$regex_boundaries.')/', $upper,$matches)) {
    +                return array(
    +                    self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED,
    +                    self::TOKEN_VALUE=>substr($string,0,strlen($matches[1]))
    +                );
    +            }
    +        }
    +
    +        // A function must be suceeded by '('
    +        // this makes it so "count(" is considered a function, but "count" alone is not
    +        $upper = strtoupper($string);
    +        // function
    +        if (preg_match('/^('.self::$regex_function.'[(]|\s|[)])/', $upper,$matches)) {
    +            return array(
    +                self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED,
    +                self::TOKEN_VALUE=>substr($string,0,strlen($matches[1])-1)
    +            );
    +        }
    +
    +        // Non reserved word
    +        preg_match('/^(.*?)($|\s|["\'`]|'.self::$regex_boundaries.')/',$string,$matches);
    +
    +        return array(
    +            self::TOKEN_VALUE => $matches[1],
    +            self::TOKEN_TYPE  => self::TOKEN_TYPE_WORD
    +        );
    +    }
    +
    +    protected static function getQuotedString($string)
    +    {
    +        $ret = null;
    +        
    +        // This checks for the following patterns:
    +        // 1. backtick quoted string using `` to escape
    +        // 2. double quoted string using "" or \" to escape
    +        // 3. single quoted string using '' or \' to escape
    +        if ( preg_match('/^(((`[^`]*($|`))+)|(("[^"\\\\]*(?:\\\\.[^"\\\\]*)*("|$))+)|((\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*(\'|$))+))/s', $string, $matches)) {
    +            $ret = $matches[1];
    +        }
    +        
    +        return $ret;
    +    }
    +
    +    /**
    +     * Takes a SQL string and breaks it into tokens.
    +     * Each token is an associative array with type and value.
    +     *
    +     * @param String $string The SQL string
    +     *
    +     * @return Array An array of tokens.
    +     */
    +    protected static function tokenize($string)
    +    {
    +        self::init();
    +
    +        $tokens = array();
    +
    +        // Used for debugging if there is an error while tokenizing the string
    +        $original_length = strlen($string);
    +
    +        // Used to make sure the string keeps shrinking on each iteration
    +        $old_string_len = strlen($string) + 1;
    +
    +        $token = null;
    +
    +        $current_length = strlen($string);
    +
    +        // Keep processing the string until it is empty
    +        while ($current_length) {
    +            // If the string stopped shrinking, there was a problem
    +            if ($old_string_len <= $current_length) {
    +                $tokens[] = array(
    +                    self::TOKEN_VALUE=>$string,
    +                    self::TOKEN_TYPE=>self::TOKEN_TYPE_ERROR
    +                );
    +
    +                return $tokens;
    +            }
    +            $old_string_len =  $current_length;
    +
    +            // Determine if we can use caching
    +            if ($current_length >= self::$max_cachekey_size) {
    +                $cacheKey = substr($string,0,self::$max_cachekey_size);
    +            } else {
    +                $cacheKey = false;
    +            }
    +
    +            // See if the token is already cached
    +            if ($cacheKey && isset(self::$token_cache[$cacheKey])) {
    +                // Retrieve from cache
    +                $token = self::$token_cache[$cacheKey];
    +                $token_length = strlen($token[self::TOKEN_VALUE]);
    +                self::$cache_hits++;
    +            } else {
    +                // Get the next token and the token type
    +                $token = self::getNextToken($string, $token);
    +                $token_length = strlen($token[self::TOKEN_VALUE]);
    +                self::$cache_misses++;
    +
    +                // If the token is shorter than the max length, store it in cache
    +                if ($cacheKey && $token_length < self::$max_cachekey_size) {
    +                    self::$token_cache[$cacheKey] = $token;
    +                }
    +            }
    +
    +            $tokens[] = $token;
    +
    +            // Advance the string
    +            $string = substr($string, $token_length);
    +
    +            $current_length -= $token_length;
    +        }
    +
    +        return $tokens;
    +    }
    +
    +    /**
    +     * Format the whitespace in a SQL string to make it easier to read.
    +     *
    +     * @param String  $string    The SQL string
    +     * @param boolean $highlight If true, syntax highlighting will also be performed
    +     *
    +     * @return String The SQL string with HTML styles and formatting wrapped in a 
     tag
    +     */
    +    public static function format($string, $highlight=true)
    +    {
    +        // This variable will be populated with formatted html
    +        $return = '';
    +
    +        // Use an actual tab while formatting and then switch out with self::$tab at the end
    +        $tab = "\t";
    +
    +        $indent_level = 0;
    +        $newline = false;
    +        $inline_parentheses = false;
    +        $increase_special_indent = false;
    +        $increase_block_indent = false;
    +        $indent_types = array();
    +        $added_newline = false;
    +        $inline_count = 0;
    +        $inline_indented = false;
    +        $clause_limit = false;
    +
    +        // Tokenize String
    +        $original_tokens = self::tokenize($string);
    +
    +        // Remove existing whitespace
    +        $tokens = array();
    +        foreach ($original_tokens as $i=>$token) {
    +            if ($token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) {
    +                $token['i'] = $i;
    +                $tokens[] = $token;
    +            }
    +        }
    +
    +        // Format token by token
    +        foreach ($tokens as $i=>$token) {
    +            // Get highlighted token if doing syntax highlighting
    +            if ($highlight) {
    +                $highlighted = self::highlightToken($token);
    +            } else { // If returning raw text
    +                $highlighted = $token[self::TOKEN_VALUE];
    +            }
    +
    +            // If we are increasing the special indent level now
    +            if ($increase_special_indent) {
    +                $indent_level++;
    +                $increase_special_indent = false;
    +                array_unshift($indent_types,'special');
    +            }
    +            // If we are increasing the block indent level now
    +            if ($increase_block_indent) {
    +                $indent_level++;
    +                $increase_block_indent = false;
    +                array_unshift($indent_types,'block');
    +            }
    +
    +            // If we need a new line before the token
    +            if ($newline) {
    +                $return .= "\n" . str_repeat($tab, $indent_level);
    +                $newline = false;
    +                $added_newline = true;
    +            } else {
    +                $added_newline = false;
    +            }
    +
    +            // Display comments directly where they appear in the source
    +            if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_COMMENT || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) {
    +                if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) {
    +                    $indent = str_repeat($tab,$indent_level);
    +                    $return .= "\n" . $indent;
    +                    $highlighted = str_replace("\n","\n".$indent,$highlighted);
    +                }
    +
    +                $return .= $highlighted;
    +                $newline = true;
    +                continue;
    +            }
    +
    +            if ($inline_parentheses) {
    +                // End of inline parentheses
    +                if ($token[self::TOKEN_VALUE] === ')') {
    +                    $return = rtrim($return,' ');
    +
    +                    if ($inline_indented) {
    +                        array_shift($indent_types);
    +                        $indent_level --;
    +                        $return .= "\n" . str_repeat($tab, $indent_level);
    +                    }
    +
    +                    $inline_parentheses = false;
    +
    +                    $return .= $highlighted . ' ';
    +                    continue;
    +                }
    +
    +                if ($token[self::TOKEN_VALUE] === ',') {
    +                    if ($inline_count >= 30) {
    +                        $inline_count = 0;
    +                        $newline = true;
    +                    }
    +                }
    +
    +                $inline_count += strlen($token[self::TOKEN_VALUE]);
    +            }
    +
    +            // Opening parentheses increase the block indent level and start a new line
    +            if ($token[self::TOKEN_VALUE] === '(') {
    +                // First check if this should be an inline parentheses block
    +                // Examples are "NOW()", "COUNT(*)", "int(10)", key(`somecolumn`), DECIMAL(7,2)
    +                // Allow up to 3 non-whitespace tokens inside inline parentheses
    +                $length = 0;
    +                for ($j=1;$j<=250;$j++) {
    +                    // Reached end of string
    +                    if (!isset($tokens[$i+$j])) break;
    +
    +                    $next = $tokens[$i+$j];
    +
    +                    // Reached closing parentheses, able to inline it
    +                    if ($next[self::TOKEN_VALUE] === ')') {
    +                        $inline_parentheses = true;
    +                        $inline_count = 0;
    +                        $inline_indented = false;
    +                        break;
    +                    }
    +
    +                    // Reached an invalid token for inline parentheses
    +                    if ($next[self::TOKEN_VALUE]===';' || $next[self::TOKEN_VALUE]==='(') {
    +                        break;
    +                    }
    +
    +                    // Reached an invalid token type for inline parentheses
    +                    if ($next[self::TOKEN_TYPE]===self::TOKEN_TYPE_RESERVED_TOPLEVEL || $next[self::TOKEN_TYPE]===self::TOKEN_TYPE_RESERVED_NEWLINE || $next[self::TOKEN_TYPE]===self::TOKEN_TYPE_COMMENT || $next[self::TOKEN_TYPE]===self::TOKEN_TYPE_BLOCK_COMMENT) {
    +                        break;
    +                    }
    +
    +                    $length += strlen($next[self::TOKEN_VALUE]);
    +                }
    +
    +                if ($inline_parentheses && $length > 30) {
    +                    $increase_block_indent = true;
    +                    $inline_indented = true;
    +                    $newline = true;
    +                }
    +
    +                // Take out the preceding space unless there was whitespace there in the original query
    +                if (isset($original_tokens[$token['i']-1]) && $original_tokens[$token['i']-1][self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) {
    +                    $return = rtrim($return,' ');
    +                }
    +
    +                if (!$inline_parentheses) {
    +                    $increase_block_indent = true;
    +                    // Add a newline after the parentheses
    +                    $newline = true;
    +                }
    +
    +            }
    +
    +            // Closing parentheses decrease the block indent level
    +            elseif ($token[self::TOKEN_VALUE] === ')') {
    +                // Remove whitespace before the closing parentheses
    +                $return = rtrim($return,' ');
    +
    +                $indent_level--;
    +
    +                // Reset indent level
    +                while ($j=array_shift($indent_types)) {
    +                    if ($j==='special') {
    +                        $indent_level--;
    +                    } else {
    +                        break;
    +                    }
    +                }
    +
    +                if ($indent_level < 0) {
    +                    // This is an error
    +                    $indent_level = 0;
    +
    +                    if ($highlight) {
    +                        $return .= "\n".self::highlightError($token[self::TOKEN_VALUE]);
    +                        continue;
    +                    }
    +                }
    +
    +                // Add a newline before the closing parentheses (if not already added)
    +                if (!$added_newline) {
    +                    $return .= "\n" . str_repeat($tab, $indent_level);
    +                }
    +            }
    +
    +            // Top level reserved words start a new line and increase the special indent level
    +            elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_TOPLEVEL) {
    +                $increase_special_indent = true;
    +
    +                // If the last indent type was 'special', decrease the special indent for this round
    +                reset($indent_types);
    +                if (current($indent_types)==='special') {
    +                    $indent_level--;
    +                    array_shift($indent_types);
    +                }
    +
    +                // Add a newline after the top level reserved word
    +                $newline = true;
    +                // Add a newline before the top level reserved word (if not already added)
    +                if (!$added_newline) {
    +                    $return .= "\n" . str_repeat($tab, $indent_level);
    +                }
    +                // If we already added a newline, redo the indentation since it may be different now
    +                else {
    +                    $return = rtrim($return,$tab).str_repeat($tab, $indent_level);
    +                }
    +
    +                // If the token may have extra whitespace
    +                if (strpos($token[self::TOKEN_VALUE],' ')!==false || strpos($token[self::TOKEN_VALUE],"\n")!==false || strpos($token[self::TOKEN_VALUE],"\t")!==false) {
    +                    $highlighted = preg_replace('/\s+/',' ',$highlighted);
    +                }
    +                //if SQL 'LIMIT' clause, start variable to reset newline
    +                if ($token[self::TOKEN_VALUE] === 'LIMIT' && !$inline_parentheses) {
    +                    $clause_limit = true;
    +                }
    +            }
    +
    +            // Checks if we are out of the limit clause
    +            elseif ($clause_limit && $token[self::TOKEN_VALUE] !== "," && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_NUMBER && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) {
    +                $clause_limit = false;
    +            }
    +
    +            // Commas start a new line (unless within inline parentheses or SQL 'LIMIT' clause)
    +            elseif ($token[self::TOKEN_VALUE] === ',' && !$inline_parentheses) {
    +                //If the previous TOKEN_VALUE is 'LIMIT', resets new line
    +                if ($clause_limit === true) {
    +                    $newline = false;
    +                    $clause_limit = false;
    +                }
    +                // All other cases of commas
    +                else {
    +                    $newline = true;
    +                }
    +            }
    +
    +            // Newline reserved words start a new line
    +            elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_NEWLINE) {
    +                // Add a newline before the reserved word (if not already added)
    +                if (!$added_newline) {
    +                    $return .= "\n" . str_repeat($tab, $indent_level);
    +                }
    +
    +                // If the token may have extra whitespace
    +                if (strpos($token[self::TOKEN_VALUE],' ')!==false || strpos($token[self::TOKEN_VALUE],"\n")!==false || strpos($token[self::TOKEN_VALUE],"\t")!==false) {
    +                    $highlighted = preg_replace('/\s+/',' ',$highlighted);
    +                }
    +            }
    +
    +            // Multiple boundary characters in a row should not have spaces between them (not including parentheses)
    +            elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BOUNDARY) {
    +                if (isset($tokens[$i-1]) && $tokens[$i-1][self::TOKEN_TYPE] === self::TOKEN_TYPE_BOUNDARY) {
    +                    if (isset($original_tokens[$token['i']-1]) && $original_tokens[$token['i']-1][self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) {
    +                        $return = rtrim($return,' ');
    +                    }
    +                }
    +            }
    +
    +            // If the token shouldn't have a space before it
    +            if ($token[self::TOKEN_VALUE] === '.' || $token[self::TOKEN_VALUE] === ',' || $token[self::TOKEN_VALUE] === ';') {
    +                $return = rtrim($return, ' ');
    +            }
    +
    +            $return .= $highlighted.' ';
    +
    +            // If the token shouldn't have a space after it
    +            if ($token[self::TOKEN_VALUE] === '(' || $token[self::TOKEN_VALUE] === '.') {
    +                $return = rtrim($return,' ');
    +            }
    +            
    +            // If this is the "-" of a negative number, it shouldn't have a space after it
    +            if($token[self::TOKEN_VALUE] === '-' && isset($tokens[$i+1]) && $tokens[$i+1][self::TOKEN_TYPE] === self::TOKEN_TYPE_NUMBER && isset($tokens[$i-1])) {
    +                $prev = $tokens[$i-1][self::TOKEN_TYPE];
    +                if($prev !== self::TOKEN_TYPE_QUOTE && $prev !== self::TOKEN_TYPE_BACKTICK_QUOTE && $prev !== self::TOKEN_TYPE_WORD && $prev !== self::TOKEN_TYPE_NUMBER) {
    +                    $return = rtrim($return,' ');
    +                }
    +            } 
    +        }
    +
    +        // If there are unmatched parentheses
    +        if ($highlight && array_search('block',$indent_types) !== false) {
    +            $return .= "\n".self::highlightError("WARNING: unclosed parentheses or section");
    +        }
    +
    +        // Replace tab characters with the configuration tab character
    +        $return = trim(str_replace("\t",self::$tab,$return));
    +
    +        if ($highlight) {
    +            $return = self::output($return);
    +        }
    +
    +        return $return;
    +    }
    +
    +    /**
    +     * Add syntax highlighting to a SQL string
    +     *
    +     * @param String $string The SQL string
    +     *
    +     * @return String The SQL string with HTML styles applied
    +     */
    +    public static function highlight($string)
    +    {
    +        $tokens = self::tokenize($string);
    +
    +        $return = '';
    +
    +        foreach ($tokens as $token) {
    +            $return .= self::highlightToken($token);
    +        }
    +
    +        return self::output($return);
    +    }
    +
    +    /**
    +     * Split a SQL string into multiple queries.
    +     * Uses ";" as a query delimiter.
    +     *
    +     * @param String $string The SQL string
    +     *
    +     * @return Array An array of individual query strings without trailing semicolons
    +     */
    +    public static function splitQuery($string)
    +    {
    +        $queries = array();
    +        $current_query = '';
    +        $empty = true;
    +
    +        $tokens = self::tokenize($string);
    +
    +        foreach ($tokens as $token) {
    +            // If this is a query separator
    +            if ($token[self::TOKEN_VALUE] === ';') {
    +                if (!$empty) {
    +                    $queries[] = $current_query.';';
    +                }
    +                $current_query = '';
    +                $empty = true;
    +                continue;
    +            }
    +
    +            // If this is a non-empty character
    +            if ($token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_COMMENT && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_BLOCK_COMMENT) {
    +                $empty = false;
    +            }
    +
    +            $current_query .= $token[self::TOKEN_VALUE];
    +        }
    +
    +        if (!$empty) {
    +            $queries[] = trim($current_query);
    +        }
    +
    +        return $queries;
    +    }
    +
    +    /**
    +     * Remove all comments from a SQL string
    +     *
    +     * @param String $string The SQL string
    +     *
    +     * @return String The SQL string without comments
    +     */
    +    public static function removeComments($string)
    +    {
    +        $result = '';
    +
    +        $tokens = self::tokenize($string);
    +
    +        foreach ($tokens as $token) {
    +            // Skip comment tokens
    +            if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_COMMENT || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) {
    +                continue;
    +            }
    +
    +            $result .= $token[self::TOKEN_VALUE];
    +        }
    +        $result = self::format( $result,false);
    +
    +        return $result;
    +    }
    +
    +    /**
    +     * Compress a query by collapsing white space and removing comments
    +     *
    +     * @param String $string The SQL string
    +     *
    +     * @return String The SQL string without comments
    +     */
    +    public static function compress($string)
    +    {
    +        $result = '';
    +
    +        $tokens = self::tokenize($string);
    +
    +        $whitespace = true;
    +        foreach ($tokens as $token) {
    +            // Skip comment tokens
    +            if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_COMMENT || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) {
    +                continue;
    +            }
    +            // Remove extra whitespace in reserved words (e.g "OUTER     JOIN" becomes "OUTER JOIN")
    +            elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_NEWLINE || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_TOPLEVEL) {
    +                $token[self::TOKEN_VALUE] = preg_replace('/\s+/',' ',$token[self::TOKEN_VALUE]);
    +            }
    +
    +            if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_WHITESPACE) {
    +                // If the last token was whitespace, don't add another one
    +                if ($whitespace) {
    +                    continue;
    +                } else {
    +                    $whitespace = true;
    +                    // Convert all whitespace to a single space
    +                    $token[self::TOKEN_VALUE] = ' ';
    +                }
    +            } else {
    +                $whitespace = false;
    +            }
    +
    +            $result .= $token[self::TOKEN_VALUE];
    +        }
    +
    +        return rtrim($result);
    +    }
    +
    +    /**
    +     * Highlights a token depending on its type.
    +     *
    +     * @param Array $token An associative array containing type and value.
    +     *
    +     * @return String HTML code of the highlighted token.
    +     */
    +    protected static function highlightToken($token)
    +    {
    +        $type = $token[self::TOKEN_TYPE];
    +
    +        if (self::is_cli()) {
    +            $token = $token[self::TOKEN_VALUE];
    +        } else {
    +            $token = htmlentities($token[self::TOKEN_VALUE],ENT_COMPAT,'UTF-8');
    +        }
    +
    +        if ($type===self::TOKEN_TYPE_BOUNDARY) {
    +            return self::highlightBoundary($token);
    +        } elseif ($type===self::TOKEN_TYPE_WORD) {
    +            return self::highlightWord($token);
    +        } elseif ($type===self::TOKEN_TYPE_BACKTICK_QUOTE) {
    +            return self::highlightBacktickQuote($token);
    +        } elseif ($type===self::TOKEN_TYPE_QUOTE) {
    +            return self::highlightQuote($token);
    +        } elseif ($type===self::TOKEN_TYPE_RESERVED) {
    +            return self::highlightReservedWord($token);
    +        } elseif ($type===self::TOKEN_TYPE_RESERVED_TOPLEVEL) {
    +            return self::highlightReservedWord($token);
    +        } elseif ($type===self::TOKEN_TYPE_RESERVED_NEWLINE) {
    +            return self::highlightReservedWord($token);
    +        } elseif ($type===self::TOKEN_TYPE_NUMBER) {
    +            return self::highlightNumber($token);
    +        } elseif ($type===self::TOKEN_TYPE_VARIABLE) {
    +            return self::highlightVariable($token);
    +        } elseif ($type===self::TOKEN_TYPE_COMMENT || $type===self::TOKEN_TYPE_BLOCK_COMMENT) {
    +            return self::highlightComment($token);
    +        }
    +
    +        return $token;
    +    }
    +
    +    /**
    +     * Highlights a quoted string
    +     *
    +     * @param String $value The token's value
    +     *
    +     * @return String HTML code of the highlighted token.
    +     */
    +    protected static function highlightQuote($value)
    +    {
    +        if (self::is_cli()) {
    +            return self::$cli_quote . $value . "\x1b[0m";
    +        } else {
    +            return '' . $value . '';
    +        }
    +    }
    +
    +    /**
    +     * Highlights a backtick quoted string
    +     *
    +     * @param String $value The token's value
    +     *
    +     * @return String HTML code of the highlighted token.
    +     */
    +    protected static function highlightBacktickQuote($value)
    +    {
    +        if (self::is_cli()) {
    +            return self::$cli_backtick_quote . $value . "\x1b[0m";
    +        } else {
    +            return '' . $value . '';
    +        }
    +    }
    +
    +    /**
    +     * Highlights a reserved word
    +     *
    +     * @param String $value The token's value
    +     *
    +     * @return String HTML code of the highlighted token.
    +     */
    +    protected static function highlightReservedWord($value)
    +    {
    +        if (self::is_cli()) {
    +            return self::$cli_reserved . $value . "\x1b[0m";
    +        } else {
    +            return '' . $value . '';
    +        }
    +    }
    +
    +    /**
    +     * Highlights a boundary token
    +     *
    +     * @param String $value The token's value
    +     *
    +     * @return String HTML code of the highlighted token.
    +     */
    +    protected static function highlightBoundary($value)
    +    {
    +        if ($value==='(' || $value===')') return $value;
    +
    +        if (self::is_cli()) {
    +            return self::$cli_boundary . $value . "\x1b[0m";
    +        } else {
    +            return '' . $value . '';
    +        }
    +    }
    +
    +    /**
    +     * Highlights a number
    +     *
    +     * @param String $value The token's value
    +     *
    +     * @return String HTML code of the highlighted token.
    +     */
    +    protected static function highlightNumber($value)
    +    {
    +        if (self::is_cli()) {
    +            return self::$cli_number . $value . "\x1b[0m";
    +        } else {
    +            return '' . $value . '';
    +        }
    +    }
    +
    +    /**
    +     * Highlights an error
    +     *
    +     * @param String $value The token's value
    +     *
    +     * @return String HTML code of the highlighted token.
    +     */
    +    protected static function highlightError($value)
    +    {
    +        if (self::is_cli()) {
    +            return self::$cli_error . $value . "\x1b[0m";
    +        } else {
    +            return '' . $value . '';
    +        }
    +    }
    +
    +    /**
    +     * Highlights a comment
    +     *
    +     * @param String $value The token's value
    +     *
    +     * @return String HTML code of the highlighted token.
    +     */
    +    protected static function highlightComment($value)
    +    {
    +        if (self::is_cli()) {
    +            return self::$cli_comment . $value . "\x1b[0m";
    +        } else {
    +            return '' . $value . '';
    +        }
    +    }
    +
    +    /**
    +     * Highlights a word token
    +     *
    +     * @param String $value The token's value
    +     *
    +     * @return String HTML code of the highlighted token.
    +     */
    +    protected static function highlightWord($value)
    +    {
    +        if (self::is_cli()) {
    +            return self::$cli_word . $value . "\x1b[0m";
    +        } else {
    +            return '' . $value . '';
    +        }
    +    }
    +
    +    /**
    +     * Highlights a variable token
    +     *
    +     * @param String $value The token's value
    +     *
    +     * @return String HTML code of the highlighted token.
    +     */
    +    protected static function highlightVariable($value)
    +    {
    +        if (self::is_cli()) {
    +            return self::$cli_variable . $value . "\x1b[0m";
    +        } else {
    +            return '' . $value . '';
    +        }
    +    }
    +
    +    /**
    +     * Helper function for building regular expressions for reserved words and boundary characters
    +     *
    +     * @param String $a The string to be quoted
    +     *
    +     * @return String The quoted string
    +     */
    +    private static function quote_regex($a)
    +    {
    +        return preg_quote($a,'/');
    +    }
    +
    +    /**
    +     * Helper function for building string output
    +     *
    +     * @param String $string The string to be quoted
    +     *
    +     * @return String The quoted string
    +     */
    +    private static function output($string)
    +    {
    +        if (self::is_cli()) {
    +            return $string."\n";
    +        } else {
    +            $string=trim($string);
    +            if (!self::$use_pre) {
    +                return $string;
    +            }
    +
    +            return '
    ' . $string . '
    '; + } + } + + private static function is_cli() + { + if (isset(self::$cli)) return self::$cli; + else return php_sapi_name() === 'cli'; + } + +} diff --git a/vendor/jdorn/sql-formatter/phpunit.xml.dist b/vendor/jdorn/sql-formatter/phpunit.xml.dist new file mode 100644 index 0000000..ebfda97 --- /dev/null +++ b/vendor/jdorn/sql-formatter/phpunit.xml.dist @@ -0,0 +1,20 @@ + + + + + + ./tests + + + + + + ./ + + ./tests + ./vendor + ./examples + + + + diff --git a/vendor/jdorn/sql-formatter/tests/SqlFormatterTest.php b/vendor/jdorn/sql-formatter/tests/SqlFormatterTest.php new file mode 100644 index 0000000..ca535cf --- /dev/null +++ b/vendor/jdorn/sql-formatter/tests/SqlFormatterTest.php @@ -0,0 +1,197 @@ +assertEquals(trim($html), trim(SqlFormatter::format($sql))); + } + /** + * @dataProvider formatData + */ + function testFormat($sql, $html) { + $this->assertEquals(trim($html), trim(SqlFormatter::format($sql, false))); + } + /** + * @dataProvider highlightData + */ + function testHighlight($sql, $html) { + $this->assertEquals(trim($html), trim(SqlFormatter::highlight($sql))); + } + /** + * @dataProvider highlightCliData + */ + function testCliHighlight($sql, $html) { + SqlFormatter::$cli = true; + $this->assertEquals(trim($html), trim(SqlFormatter::format($sql))); + SqlFormatter::$cli = false; + } + /** + * @dataProvider compressData + */ + function testCompress($sql, $html) { + $this->assertEquals(trim($html), trim(SqlFormatter::compress($sql))); + } + + function testUsePre() { + SqlFormatter::$use_pre = false; + $actual = SqlFormatter::highlight("test"); + $expected = 'test'; + $this->assertEquals($actual,$expected); + + SqlFormatter::$use_pre = true; + $actual = SqlFormatter::highlight("test"); + $expected = '
    test
    '; + $this->assertEquals($actual,$expected); + } + + function testSplitQuery() { + $expected = array( + "SELECT 'test' FROM MyTable;", + "SELECT Column2 FROM SomeOther Table WHERE (test = true);" + ); + + $actual = SqlFormatter::splitQuery(implode(';',$expected)); + + $this->assertEquals($expected, $actual); + } + + function testSplitQueryEmpty() { + $sql = "SELECT 1;SELECT 2;\n-- This is a comment\n;SELECT 3"; + $expected = array("SELECT 1;","SELECT 2;","SELECT 3"); + $actual = SqlFormatter::splitQuery($sql); + + $this->assertEquals($expected, $actual); + } + + function testRemoveComments() { + $expected = SqlFormatter::format("SELECT\n * FROM\n MyTable",false); + $sql = "/* this is a comment */SELECT#This is another comment\n * FROM-- One final comment\n MyTable"; + $actual = SqlFormatter::removeComments($sql); + + $this->assertEquals($expected, $actual); + } + + function testCacheStats() { + $stats = SqlFormatter::getCacheStats(); + $this->assertGreaterThan(1,$stats['hits']); + } + + function formatHighlightData() { + $formatHighlightData = explode("\n\n",file_get_contents(__DIR__."/format-highlight.html")); + $sqlData = $this->sqlData(); + + $return = array(); + foreach($formatHighlightData as $i=>$data) { + $return[] = array( + $sqlData[$i], + $data + ); + } + + return $return; + } + + function highlightCliData() { + $clidata = explode("\n\n",file_get_contents(__DIR__."/clihighlight.html")); + $sqlData = $this->sqlData(); + + $return = array(); + foreach($clidata as $i=>$data) { + $return[] = array( + $sqlData[$i], + $data + ); + } + + return $return; + } + + function formatData() { + $formatData = explode("\n\n",file_get_contents(__DIR__."/format.html")); + $sqlData = $this->sqlData(); + + $return = array(); + foreach($formatData as $i=>$data) { + $return[] = array( + $sqlData[$i], + $data + ); + } + + return $return; + } + + function compressData() { + $compressData = explode("\n\n",file_get_contents(__DIR__."/compress.html")); + $sqlData = $this->sqlData(); + + $return = array(); + foreach($compressData as $i=>$data) { + $return[] = array( + $sqlData[$i], + $data + ); + } + + return $return; + } + + function highlightData() { + $highlightData = explode("\n\n",file_get_contents(__DIR__."/highlight.html")); + $sqlData = $this->sqlData(); + + $return = array(); + foreach($highlightData as $i=>$data) { + $return[] = array( + $sqlData[$i], + $data + ); + } + + return $return; + } + + + + function sqlData() { + if(!$this->sqlData) { + $this->sqlData = explode("\n\n",file_get_contents(__DIR__."/sql.sql")); + } + + /** + $formatHighlight = array(); + $highlight = array(); + $format = array(); + $compress = array(); + $clihighlight = array(); + + foreach($this->sqlData as $sql) { + $formatHighlight[] = trim(SqlFormatter::format($sql)); + $highlight[] = trim(SqlFormatter::highlight($sql)); + $format[] = trim(SqlFormatter::format($sql, false)); + $compress[] = trim(SqlFormatter::compress($sql)); + + SqlFormatter::$cli = true; + $clihighlight[] = trim(SqlFormatter::format($sql)); + SqlFormatter::$cli = false; + } + + file_put_contents(__DIR__."/format-highlight.html", implode("\n\n",$formatHighlight)); + file_put_contents(__DIR__."/highlight.html", implode("\n\n",$highlight)); + file_put_contents(__DIR__."/format.html", implode("\n\n",$format)); + file_put_contents(__DIR__."/compress.html", implode("\n\n",$compress)); + file_put_contents(__DIR__."/clihighlight.html", implode("\n\n",$clihighlight)); + /**/ + + return $this->sqlData; + } + +} diff --git a/vendor/jdorn/sql-formatter/tests/clihighlight.html b/vendor/jdorn/sql-formatter/tests/clihighlight.html new file mode 100644 index 0000000..6ccfc12 --- /dev/null +++ b/vendor/jdorn/sql-formatter/tests/clihighlight.html @@ -0,0 +1,809 @@ +SELECT + customer_id, + customer_name, + COUNT(order_id) as total +FROM + customers + INNER JOIN orders ON customers.customer_id = orders.customer_id +GROUP BY + customer_id, + customer_name +HAVING + COUNT(order_id) > 5 +ORDER BY + COUNT(order_id) DESC; + +UPDATE + customers +SET + totalorders = ordersummary.total +FROM + ( + SELECT + customer_id, + count(order_id) As total + FROM + orders + GROUP BY + customer_id + ) As ordersummary +WHERE + customers.customer_id = ordersummary.customer_id + +SELECT + * +FROM + sometable +UNION ALL +SELECT + * +FROM + someothertable; + +SET + NAMES 'utf8'; + +CREATE TABLE `PREFIX_address` ( + `id_address` int(10) unsigned NOT NULL auto_increment, + `id_country` int(10) unsigned NOT NULL, + `id_state` int(10) unsigned default NULL, + `id_customer` int(10) unsigned NOT NULL default '0', + `id_manufacturer` int(10) unsigned NOT NULL default '0', + `id_supplier` int(10) unsigned NOT NULL default '0', + `id_warehouse` int(10) unsigned NOT NULL default '0', + `alias` varchar(32) NOT NULL, + `company` varchar(64) default NULL, + `lastname` varchar(32) NOT NULL, + `firstname` varchar(32) NOT NULL, + `address1` varchar(128) NOT NULL, + `address2` varchar(128) default NULL, + `postcode` varchar(12) default NULL, + `city` varchar(64) NOT NULL, + `other` text, + `phone` varchar(16) default NULL, + `phone_mobile` varchar(16) default NULL, + `vat_number` varchar(32) default NULL, + `dni` varchar(16) DEFAULT NULL, + `date_add` datetime NOT NULL, + `date_upd` datetime NOT NULL, + `active` tinyint(1) unsigned NOT NULL default '1', + `deleted` tinyint(1) unsigned NOT NULL default '0', + PRIMARY KEY (`id_address`), + KEY `address_customer` (`id_customer`), + KEY `id_country` (`id_country`), + KEY `id_state` (`id_state`), + KEY `id_manufacturer` (`id_manufacturer`), + KEY `id_supplier` (`id_supplier`), + KEY `id_warehouse` (`id_warehouse`) +) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 + +CREATE TABLE `PREFIX_alias` ( + `id_alias` int(10) unsigned NOT NULL auto_increment, + `alias` varchar(255) NOT NULL, + `search` varchar(255) NOT NULL, + `active` tinyint(1) NOT NULL default '1', + PRIMARY KEY (`id_alias`), + UNIQUE KEY `alias` (`alias`) +) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 + +CREATE TABLE `PREFIX_carrier` ( + `id_carrier` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id_reference` int(10) unsigned NOT NULL, + `id_tax_rules_group` int(10) unsigned DEFAULT '0', + `name` varchar(64) NOT NULL, + `url` varchar(255) DEFAULT NULL, + `active` tinyint(1) unsigned NOT NULL DEFAULT '0', + `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0', + `shipping_handling` tinyint(1) unsigned NOT NULL DEFAULT '1', + `range_behavior` tinyint(1) unsigned NOT NULL DEFAULT '0', + `is_module` tinyint(1) unsigned NOT NULL DEFAULT '0', + `is_free` tinyint(1) unsigned NOT NULL DEFAULT '0', + `shipping_external` tinyint(1) unsigned NOT NULL DEFAULT '0', + `need_range` tinyint(1) unsigned NOT NULL DEFAULT '0', + `external_module_name` varchar(64) DEFAULT NULL, + `shipping_method` int(2) NOT NULL DEFAULT '0', + `position` int(10) unsigned NOT NULL default '0', + `max_width` int(10) DEFAULT 0, + `max_height` int(10) DEFAULT 0, + `max_depth` int(10) DEFAULT 0, + `max_weight` int(10) DEFAULT 0, + `grade` int(10) DEFAULT 0, + PRIMARY KEY (`id_carrier`), + KEY `deleted` (`deleted`, `active`), + KEY `id_tax_rules_group` (`id_tax_rules_group`) +) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 + +CREATE TABLE IF NOT EXISTS `PREFIX_specific_price_rule` ( + `id_specific_price_rule` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL, + `id_shop` int(11) unsigned NOT NULL DEFAULT '1', + `id_currency` int(10) unsigned NOT NULL, + `id_country` int(10) unsigned NOT NULL, + `id_group` int(10) unsigned NOT NULL, + `from_quantity` mediumint(8) unsigned NOT NULL, + `price` DECIMAL(20, 6), + `reduction` decimal(20, 6) NOT NULL, + `reduction_type` enum('amount', 'percentage') NOT NULL, + `from` datetime NOT NULL, + `to` datetime NOT NULL, + PRIMARY KEY (`id_specific_price_rule`), + KEY `id_product` ( + `id_shop`, `id_currency`, `id_country`, + `id_group`, `from_quantity`, `from`, + `to` + ) +) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 + +UPDATE + `PREFIX_configuration` +SET + value = '6' +WHERE + name = 'PS_SEARCH_WEIGHT_PNAME' + +UPDATE + `PREFIX_hook_module` +SET + position = 1 +WHERE + id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayPayment' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'cheque' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayPaymentReturn' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'cheque' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayHome' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'homeslider' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionAuthentication' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'statsdata' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionShopDataDuplication' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'homeslider' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayTop' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blocklanguages' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionCustomerAccountAdd' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'statsdata' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayCustomerAccount' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'favoriteproducts' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayAdminStatsModules' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'statsvisits' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayAdminStatsGraphEngine' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'graphvisifire' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayAdminStatsGridEngine' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'gridhtml' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayLeftColumnProduct' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blocksharefb' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionSearch' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'statssearch' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionCategoryAdd' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blockcategories' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionCategoryUpdate' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blockcategories' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionCategoryDelete' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blockcategories' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionAdminMetaSave' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blockcategories' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayMyAccountBlock' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'favoriteproducts' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayFooter' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blockreinsurance' + ) + +ALTER TABLE + `PREFIX_employee` +ADD + `bo_color` varchar(32) default NULL +AFTER + `stats_date_to` + +INSERT INTO `PREFIX_cms_category_lang` +VALUES + ( + 1, 3, 'Inicio', '', 'home', NULL, NULL, + NULL + ) + +INSERT INTO `PREFIX_cms_category` +VALUES + (1, 0, 0, 1, NOW(), NOW(), 0) + +UPDATE + `PREFIX_cms_category` +SET + `position` = 0 + +ALTER TABLE + `PREFIX_customer` +ADD + `note` text +AFTER + `secure_key` + +ALTER TABLE + `PREFIX_contact` +ADD + `customer_service` tinyint(1) NOT NULL DEFAULT 0 +AFTER + `email` + +INSERT INTO `PREFIX_specific_price` ( + `id_product`, `id_shop`, `id_currency`, + `id_country`, `id_group`, `priority`, + `price`, `from_quantity`, `reduction`, + `reduction_type`, `from`, `to` +) ( + SELECT + dq.`id_product`, + 1, + 1, + 0, + 1, + 0, + 0.00, + dq.`quantity`, + IF( + dq.`id_discount_type` = 2, dq.`value`, + dq.`value` / 100 + ), + IF ( + dq.`id_discount_type` = 2, 'amount', + 'percentage' + ), + '0000-00-00 00:00:00', + '0000-00-00 00:00:00' + FROM + `PREFIX_discount_quantity` dq + INNER JOIN `PREFIX_product` p ON (p.`id_product` = dq.`id_product`) +) + +DROP + TABLE `PREFIX_discount_quantity` + +INSERT INTO `PREFIX_specific_price` ( + `id_product`, `id_shop`, `id_currency`, + `id_country`, `id_group`, `priority`, + `price`, `from_quantity`, `reduction`, + `reduction_type`, `from`, `to` +) ( + SELECT + p.`id_product`, + 1, + 0, + 0, + 0, + 0, + 0.00, + 1, + IF( + p.`reduction_price` > 0, p.`reduction_price`, + p.`reduction_percent` / 100 + ), + IF( + p.`reduction_price` > 0, 'amount', + 'percentage' + ), + IF ( + p.`reduction_from` = p.`reduction_to`, + '0000-00-00 00:00:00', p.`reduction_from` + ), + IF ( + p.`reduction_from` = p.`reduction_to`, + '0000-00-00 00:00:00', p.`reduction_to` + ) + FROM + `PREFIX_product` p + WHERE + p.`reduction_price` + OR p.`reduction_percent` +) + +ALTER TABLE + `PREFIX_product` +DROP + `reduction_price`, +DROP + `reduction_percent`, +DROP + `reduction_from`, +DROP + `reduction_to` + +INSERT INTO `PREFIX_configuration` ( + `name`, `value`, `date_add`, `date_upd` +) +VALUES + ( + 'PS_SPECIFIC_PRICE_PRIORITIES', + 'id_shop;id_currency;id_country;id_group', + NOW(), NOW() + ), + ('PS_TAX_DISPLAY', 0, NOW(), NOW()), + ( + 'PS_SMARTY_FORCE_COMPILE', 1, NOW(), + NOW() + ), + ( + 'PS_DISTANCE_UNIT', 'km', NOW(), NOW() + ), + ( + 'PS_STORES_DISPLAY_CMS', 0, NOW(), + NOW() + ), + ( + 'PS_STORES_DISPLAY_FOOTER', 0, NOW(), + NOW() + ), + ( + 'PS_STORES_SIMPLIFIED', 0, NOW(), + NOW() + ), + ( + 'PS_STATSDATA_CUSTOMER_PAGESVIEWS', + 1, NOW(), NOW() + ), + ( + 'PS_STATSDATA_PAGESVIEWS', 1, NOW(), + NOW() + ), + ( + 'PS_STATSDATA_PLUGINS', 1, NOW(), + NOW() + ) + +INSERT INTO `PREFIX_configuration` ( + `name`, `value`, `date_add`, `date_upd` +) +VALUES + ( + 'PS_CONDITIONS_CMS_ID', + IFNULL( + ( + SELECT + `id_cms` + FROM + `PREFIX_cms` + WHERE + `id_cms` = 3 + ), + 0 + ), + NOW(), + NOW() + ) + +CREATE TEMPORARY TABLE `PREFIX_configuration_tmp` (`value` text) + +SET + @defaultOOS = ( + SELECT + value + FROM + `PREFIX_configuration` + WHERE + name = 'PS_ORDER_OUT_OF_STOCK' + ) + +UPDATE + `PREFIX_product` p +SET + `cache_default_attribute` = 0 +WHERE + `id_product` NOT IN ( + SELECT + `id_product` + FROM + `PREFIX_product_attribute` + ) + +INSERT INTO `PREFIX_hook` ( + `name`, `title`, `description`, `position` +) +VALUES + ( + 'processCarrier', 'Carrier Process', + NULL, 0 + ) + +INSERT INTO `PREFIX_stock_mvt_reason_lang` ( + `id_stock_mvt_reason`, `id_lang`, + `name` +) +VALUES + (1, 1, 'Order'), + (1, 2, 'Commande'), + (2, 1, 'Missing Stock Movement'), + ( + 2, 2, 'Mouvement de stock manquant' + ), + (3, 1, 'Restocking'), + (3, 2, 'Réassort') + +INSERT INTO `PREFIX_meta_lang` ( + `id_lang`, `id_meta`, `title`, `url_rewrite` +) +VALUES + ( + 1, + ( + SELECT + `id_meta` + FROM + `PREFIX_meta` + WHERE + `page` = 'authentication' + ), + 'Authentication', + 'authentication' + ), + ( + 2, + ( + SELECT + `id_meta` + FROM + `PREFIX_meta` + WHERE + `page` = 'authentication' + ), + 'Authentification', + 'authentification' + ), + ( + 3, + ( + SELECT + `id_meta` + FROM + `PREFIX_meta` + WHERE + `page` = 'authentication' + ), + 'Autenticación', + 'autenticacion' + ) + +LOCK TABLES `admin_assert` WRITE + +UNLOCK TABLES + +DROP + TABLE IF EXISTS `admin_role` + +SELECT + * +FROM + -- This is another comment + MyTable # One final comment + + /* This is a block comment + */ +WHERE + 1 = 2; + +SELECT + -- This is a test + +SELECT + Test +FROM + Test +WHERE + (MyColumn = 1) +) +AND ( + ( + (SomeOtherColumn = 2); +WARNING: unclosed parentheses or section + +SELECT + * +LIMIT + 1; +SELECT + a, + b, + c, + d +FROM + e +LIMIT + 1, 2; +SELECT + 1, + 2, + 3 +WHERE + a in (1, 2, 3, 4, 5) + and b = 5; + +SELECT + count - 50 +WHERE + a - 50 = b +WHERE + 1 + and -50 +WHERE + -50 = a +WHERE + a = -50 +WHERE + 1 + /*test*/ + -50 +WHERE + 1 + and -50; + +SELECT + @ + and b; + +SELECT + @"weird variable name"; + +SELECT + "no closing quote + \ No newline at end of file diff --git a/vendor/jdorn/sql-formatter/tests/compress.html b/vendor/jdorn/sql-formatter/tests/compress.html new file mode 100644 index 0000000..bb2fcf7 --- /dev/null +++ b/vendor/jdorn/sql-formatter/tests/compress.html @@ -0,0 +1,77 @@ +SELECT customer_id, customer_name, COUNT(order_id) as total FROM customers INNER JOIN orders ON customers.customer_id = orders.customer_id GROUP BY customer_id, customer_name HAVING COUNT(order_id) > 5 ORDER BY COUNT(order_id) DESC; + +UPDATE customers SET totalorders = ordersummary.total FROM (SELECT customer_id, count(order_id) As total FROM orders GROUP BY customer_id) As ordersummary WHERE customers.customer_id = ordersummary.customer_id + +SELECT * FROM sometable UNION ALL SELECT * FROM someothertable; + +SET NAMES 'utf8'; + +CREATE TABLE `PREFIX_address` ( `id_address` int(10) unsigned NOT NULL auto_increment, `id_country` int(10) unsigned NOT NULL, `id_state` int(10) unsigned default NULL, `id_customer` int(10) unsigned NOT NULL default '0', `id_manufacturer` int(10) unsigned NOT NULL default '0', `id_supplier` int(10) unsigned NOT NULL default '0', `id_warehouse` int(10) unsigned NOT NULL default '0', `alias` varchar(32) NOT NULL, `company` varchar(64) default NULL, `lastname` varchar(32) NOT NULL, `firstname` varchar(32) NOT NULL, `address1` varchar(128) NOT NULL, `address2` varchar(128) default NULL, `postcode` varchar(12) default NULL, `city` varchar(64) NOT NULL, `other` text, `phone` varchar(16) default NULL, `phone_mobile` varchar(16) default NULL, `vat_number` varchar(32) default NULL, `dni` varchar(16) DEFAULT NULL, `date_add` datetime NOT NULL, `date_upd` datetime NOT NULL, `active` tinyint(1) unsigned NOT NULL default '1', `deleted` tinyint(1) unsigned NOT NULL default '0', PRIMARY KEY (`id_address`), KEY `address_customer` (`id_customer`), KEY `id_country` (`id_country`), KEY `id_state` (`id_state`), KEY `id_manufacturer` (`id_manufacturer`), KEY `id_supplier` (`id_supplier`), KEY `id_warehouse` (`id_warehouse`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 + +CREATE TABLE `PREFIX_alias` ( `id_alias` int(10) unsigned NOT NULL auto_increment, `alias` varchar(255) NOT NULL, `search` varchar(255) NOT NULL, `active` tinyint(1) NOT NULL default '1', PRIMARY KEY (`id_alias`), UNIQUE KEY `alias` (`alias`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 + +CREATE TABLE `PREFIX_carrier` ( `id_carrier` int(10) unsigned NOT NULL AUTO_INCREMENT, `id_reference` int(10) unsigned NOT NULL, `id_tax_rules_group` int(10) unsigned DEFAULT '0', `name` varchar(64) NOT NULL, `url` varchar(255) DEFAULT NULL, `active` tinyint(1) unsigned NOT NULL DEFAULT '0', `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0', `shipping_handling` tinyint(1) unsigned NOT NULL DEFAULT '1', `range_behavior` tinyint(1) unsigned NOT NULL DEFAULT '0', `is_module` tinyint(1) unsigned NOT NULL DEFAULT '0', `is_free` tinyint(1) unsigned NOT NULL DEFAULT '0', `shipping_external` tinyint(1) unsigned NOT NULL DEFAULT '0', `need_range` tinyint(1) unsigned NOT NULL DEFAULT '0', `external_module_name` varchar(64) DEFAULT NULL, `shipping_method` int(2) NOT NULL DEFAULT '0', `position` int(10) unsigned NOT NULL default '0', `max_width` int(10) DEFAULT 0, `max_height` int(10) DEFAULT 0, `max_depth` int(10) DEFAULT 0, `max_weight` int(10) DEFAULT 0, `grade` int(10) DEFAULT 0, PRIMARY KEY (`id_carrier`), KEY `deleted` (`deleted`,`active`), KEY `id_tax_rules_group` (`id_tax_rules_group`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 + +CREATE TABLE IF NOT EXISTS `PREFIX_specific_price_rule` ( `id_specific_price_rule` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL, `id_shop` int(11) unsigned NOT NULL DEFAULT '1', `id_currency` int(10) unsigned NOT NULL, `id_country` int(10) unsigned NOT NULL, `id_group` int(10) unsigned NOT NULL, `from_quantity` mediumint(8) unsigned NOT NULL, `price` DECIMAL(20,6), `reduction` decimal(20,6) NOT NULL, `reduction_type` enum('amount','percentage') NOT NULL, `from` datetime NOT NULL, `to` datetime NOT NULL, PRIMARY KEY (`id_specific_price_rule`), KEY `id_product` (`id_shop`,`id_currency`,`id_country`,`id_group`,`from_quantity`,`from`,`to`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 + +UPDATE `PREFIX_configuration` SET value = '6' WHERE name = 'PS_SEARCH_WEIGHT_PNAME' + +UPDATE `PREFIX_hook_module` SET position = 1 WHERE id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayPayment') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'cheque') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayPaymentReturn') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'cheque') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayHome') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'homeslider') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionAuthentication') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsdata') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionShopDataDuplication') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'homeslider') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayTop') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blocklanguages') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCustomerAccountAdd') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsdata') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayCustomerAccount') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'favoriteproducts') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsModules') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsvisits') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsGraphEngine') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'graphvisifire') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsGridEngine') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'gridhtml') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayLeftColumnProduct') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blocksharefb') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionSearch') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statssearch') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryAdd') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryUpdate') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryDelete') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionAdminMetaSave') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayMyAccountBlock') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'favoriteproducts') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayFooter') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockreinsurance') + +ALTER TABLE `PREFIX_employee` ADD `bo_color` varchar(32) default NULL AFTER `stats_date_to` + +INSERT INTO `PREFIX_cms_category_lang` VALUES(1, 3, 'Inicio', '', 'home', NULL, NULL, NULL) + +INSERT INTO `PREFIX_cms_category` VALUES(1, 0, 0, 1, NOW(), NOW(),0) + +UPDATE `PREFIX_cms_category` SET `position` = 0 + +ALTER TABLE `PREFIX_customer` ADD `note` text AFTER `secure_key` + +ALTER TABLE `PREFIX_contact` ADD `customer_service` tinyint(1) NOT NULL DEFAULT 0 AFTER `email` + +INSERT INTO `PREFIX_specific_price` (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `priority`, `price`, `from_quantity`, `reduction`, `reduction_type`, `from`, `to`) ( SELECT dq.`id_product`, 1, 1, 0, 1, 0, 0.00, dq.`quantity`, IF(dq.`id_discount_type` = 2, dq.`value`, dq.`value` / 100), IF (dq.`id_discount_type` = 2, 'amount', 'percentage'), '0000-00-00 00:00:00', '0000-00-00 00:00:00' FROM `PREFIX_discount_quantity` dq INNER JOIN `PREFIX_product` p ON (p.`id_product` = dq.`id_product`) ) + +DROP TABLE `PREFIX_discount_quantity` + +INSERT INTO `PREFIX_specific_price` (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `priority`, `price`, `from_quantity`, `reduction`, `reduction_type`, `from`, `to`) ( SELECT p.`id_product`, 1, 0, 0, 0, 0, 0.00, 1, IF(p.`reduction_price` > 0, p.`reduction_price`, p.`reduction_percent` / 100), IF(p.`reduction_price` > 0, 'amount', 'percentage'), IF (p.`reduction_from` = p.`reduction_to`, '0000-00-00 00:00:00', p.`reduction_from`), IF (p.`reduction_from` = p.`reduction_to`, '0000-00-00 00:00:00', p.`reduction_to`) FROM `PREFIX_product` p WHERE p.`reduction_price` OR p.`reduction_percent` ) + +ALTER TABLE `PREFIX_product` DROP `reduction_price`, DROP `reduction_percent`, DROP `reduction_from`, DROP `reduction_to` + +INSERT INTO `PREFIX_configuration` (`name`, `value`, `date_add`, `date_upd`) VALUES ('PS_SPECIFIC_PRICE_PRIORITIES', 'id_shop;id_currency;id_country;id_group', NOW(), NOW()), ('PS_TAX_DISPLAY', 0, NOW(), NOW()), ('PS_SMARTY_FORCE_COMPILE', 1, NOW(), NOW()), ('PS_DISTANCE_UNIT', 'km', NOW(), NOW()), ('PS_STORES_DISPLAY_CMS', 0, NOW(), NOW()), ('PS_STORES_DISPLAY_FOOTER', 0, NOW(), NOW()), ('PS_STORES_SIMPLIFIED', 0, NOW(), NOW()), ('PS_STATSDATA_CUSTOMER_PAGESVIEWS', 1, NOW(), NOW()), ('PS_STATSDATA_PAGESVIEWS', 1, NOW(), NOW()), ('PS_STATSDATA_PLUGINS', 1, NOW(), NOW()) + +INSERT INTO `PREFIX_configuration` (`name`, `value`, `date_add`, `date_upd`) VALUES ('PS_CONDITIONS_CMS_ID', IFNULL((SELECT `id_cms` FROM `PREFIX_cms` WHERE `id_cms` = 3), 0), NOW(), NOW()) + +CREATE TEMPORARY TABLE `PREFIX_configuration_tmp` ( `value` text ) + +SET @defaultOOS = (SELECT value FROM `PREFIX_configuration` WHERE name = 'PS_ORDER_OUT_OF_STOCK') + +UPDATE `PREFIX_product` p SET `cache_default_attribute` = 0 WHERE `id_product` NOT IN (SELECT `id_product` FROM `PREFIX_product_attribute`) + +INSERT INTO `PREFIX_hook` (`name`, `title`, `description`, `position`) VALUES ('processCarrier', 'Carrier Process', NULL, 0) + +INSERT INTO `PREFIX_stock_mvt_reason_lang` (`id_stock_mvt_reason`, `id_lang`, `name`) VALUES (1, 1, 'Order'), (1, 2, 'Commande'), (2, 1, 'Missing Stock Movement'), (2, 2, 'Mouvement de stock manquant'), (3, 1, 'Restocking'), (3, 2, 'Réassort') + +INSERT INTO `PREFIX_meta_lang` (`id_lang`, `id_meta`, `title`, `url_rewrite`) VALUES (1, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Authentication', 'authentication'), (2, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Authentification', 'authentification'), (3, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Autenticación', 'autenticacion') + +LOCK TABLES `admin_assert` WRITE + +UNLOCK TABLES + +DROP TABLE IF EXISTS `admin_role` + +SELECT * FROM MyTable WHERE 1 = 2; + +SELECT + +SELECT Test FROM Test WHERE ( MyColumn = 1 )) AND ((( SomeOtherColumn = 2); + +SELECT * LIMIT 1; SELECT a,b,c,d FROM e LIMIT 1, 2; SELECT 1,2,3 WHERE a in (1,2,3,4,5) and b=5; + +SELECT count - 50 WHERE a-50 = b WHERE 1 and - 50 WHERE -50 = a WHERE a = -50 WHERE 1 - 50 WHERE 1 and -50; + +SELECT @ and b; + +SELECT @"weird variable name"; + +SELECT "no closing quote \ No newline at end of file diff --git a/vendor/jdorn/sql-formatter/tests/format-highlight.html b/vendor/jdorn/sql-formatter/tests/format-highlight.html new file mode 100644 index 0000000..73af253 --- /dev/null +++ b/vendor/jdorn/sql-formatter/tests/format-highlight.html @@ -0,0 +1,809 @@ +
    SELECT 
    +  customer_id, 
    +  customer_name, 
    +  COUNT(order_id) as total 
    +FROM 
    +  customers 
    +  INNER JOIN orders ON customers.customer_id = orders.customer_id 
    +GROUP BY 
    +  customer_id, 
    +  customer_name 
    +HAVING 
    +  COUNT(order_id) > 5 
    +ORDER BY 
    +  COUNT(order_id) DESC;
    + +
    UPDATE 
    +  customers 
    +SET 
    +  totalorders = ordersummary.total 
    +FROM 
    +  (
    +    SELECT 
    +      customer_id, 
    +      count(order_id) As total 
    +    FROM 
    +      orders 
    +    GROUP BY 
    +      customer_id
    +  ) As ordersummary 
    +WHERE 
    +  customers.customer_id = ordersummary.customer_id
    + +
    SELECT 
    +  * 
    +FROM 
    +  sometable 
    +UNION ALL 
    +SELECT 
    +  * 
    +FROM 
    +  someothertable;
    + +
    SET 
    +  NAMES 'utf8';
    + +
    CREATE TABLE `PREFIX_address` (
    +  `id_address` int(10) unsigned NOT NULL auto_increment, 
    +  `id_country` int(10) unsigned NOT NULL, 
    +  `id_state` int(10) unsigned default NULL, 
    +  `id_customer` int(10) unsigned NOT NULL default '0', 
    +  `id_manufacturer` int(10) unsigned NOT NULL default '0', 
    +  `id_supplier` int(10) unsigned NOT NULL default '0', 
    +  `id_warehouse` int(10) unsigned NOT NULL default '0', 
    +  `alias` varchar(32) NOT NULL, 
    +  `company` varchar(64) default NULL, 
    +  `lastname` varchar(32) NOT NULL, 
    +  `firstname` varchar(32) NOT NULL, 
    +  `address1` varchar(128) NOT NULL, 
    +  `address2` varchar(128) default NULL, 
    +  `postcode` varchar(12) default NULL, 
    +  `city` varchar(64) NOT NULL, 
    +  `other` text, 
    +  `phone` varchar(16) default NULL, 
    +  `phone_mobile` varchar(16) default NULL, 
    +  `vat_number` varchar(32) default NULL, 
    +  `dni` varchar(16) DEFAULT NULL, 
    +  `date_add` datetime NOT NULL, 
    +  `date_upd` datetime NOT NULL, 
    +  `active` tinyint(1) unsigned NOT NULL default '1', 
    +  `deleted` tinyint(1) unsigned NOT NULL default '0', 
    +  PRIMARY KEY (`id_address`), 
    +  KEY `address_customer` (`id_customer`), 
    +  KEY `id_country` (`id_country`), 
    +  KEY `id_state` (`id_state`), 
    +  KEY `id_manufacturer` (`id_manufacturer`), 
    +  KEY `id_supplier` (`id_supplier`), 
    +  KEY `id_warehouse` (`id_warehouse`)
    +) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8
    + +
    CREATE TABLE `PREFIX_alias` (
    +  `id_alias` int(10) unsigned NOT NULL auto_increment, 
    +  `alias` varchar(255) NOT NULL, 
    +  `search` varchar(255) NOT NULL, 
    +  `active` tinyint(1) NOT NULL default '1', 
    +  PRIMARY KEY (`id_alias`), 
    +  UNIQUE KEY `alias` (`alias`)
    +) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8
    + +
    CREATE TABLE `PREFIX_carrier` (
    +  `id_carrier` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    +  `id_reference` int(10) unsigned NOT NULL, 
    +  `id_tax_rules_group` int(10) unsigned DEFAULT '0', 
    +  `name` varchar(64) NOT NULL, 
    +  `url` varchar(255) DEFAULT NULL, 
    +  `active` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    +  `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    +  `shipping_handling` tinyint(1) unsigned NOT NULL DEFAULT '1', 
    +  `range_behavior` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    +  `is_module` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    +  `is_free` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    +  `shipping_external` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    +  `need_range` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    +  `external_module_name` varchar(64) DEFAULT NULL, 
    +  `shipping_method` int(2) NOT NULL DEFAULT '0', 
    +  `position` int(10) unsigned NOT NULL default '0', 
    +  `max_width` int(10) DEFAULT 0, 
    +  `max_height` int(10) DEFAULT 0, 
    +  `max_depth` int(10) DEFAULT 0, 
    +  `max_weight` int(10) DEFAULT 0, 
    +  `grade` int(10) DEFAULT 0, 
    +  PRIMARY KEY (`id_carrier`), 
    +  KEY `deleted` (`deleted`, `active`), 
    +  KEY `id_tax_rules_group` (`id_tax_rules_group`)
    +) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8
    + +
    CREATE TABLE IF NOT EXISTS `PREFIX_specific_price_rule` (
    +  `id_specific_price_rule` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    +  `name` VARCHAR(255) NOT NULL, 
    +  `id_shop` int(11) unsigned NOT NULL DEFAULT '1', 
    +  `id_currency` int(10) unsigned NOT NULL, 
    +  `id_country` int(10) unsigned NOT NULL, 
    +  `id_group` int(10) unsigned NOT NULL, 
    +  `from_quantity` mediumint(8) unsigned NOT NULL, 
    +  `price` DECIMAL(20, 6), 
    +  `reduction` decimal(20, 6) NOT NULL, 
    +  `reduction_type` enum('amount', 'percentage') NOT NULL, 
    +  `from` datetime NOT NULL, 
    +  `to` datetime NOT NULL, 
    +  PRIMARY KEY (`id_specific_price_rule`), 
    +  KEY `id_product` (
    +    `id_shop`, `id_currency`, `id_country`, 
    +    `id_group`, `from_quantity`, `from`, 
    +    `to`
    +  )
    +) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8
    + +
    UPDATE 
    +  `PREFIX_configuration` 
    +SET 
    +  value = '6' 
    +WHERE 
    +  name = 'PS_SEARCH_WEIGHT_PNAME'
    + +
    UPDATE 
    +  `PREFIX_hook_module` 
    +SET 
    +  position = 1 
    +WHERE 
    +  id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'displayPayment'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'cheque'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'displayPaymentReturn'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'cheque'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'displayHome'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'homeslider'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'actionAuthentication'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'statsdata'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'actionShopDataDuplication'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'homeslider'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'displayTop'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'blocklanguages'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'actionCustomerAccountAdd'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'statsdata'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'displayCustomerAccount'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'favoriteproducts'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'displayAdminStatsModules'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'statsvisits'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'displayAdminStatsGraphEngine'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'graphvisifire'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'displayAdminStatsGridEngine'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'gridhtml'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'displayLeftColumnProduct'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'blocksharefb'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'actionSearch'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'statssearch'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'actionCategoryAdd'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'blockcategories'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'actionCategoryUpdate'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'blockcategories'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'actionCategoryDelete'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'blockcategories'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'actionAdminMetaSave'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'blockcategories'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'displayMyAccountBlock'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'favoriteproducts'
    +  ) 
    +  OR id_hook = (
    +    SELECT 
    +      id_hook 
    +    FROM 
    +      `PREFIX_hook` 
    +    WHERE 
    +      name = 'displayFooter'
    +  ) 
    +  AND id_module = (
    +    SELECT 
    +      id_module 
    +    FROM 
    +      `PREFIX_module` 
    +    WHERE 
    +      name = 'blockreinsurance'
    +  )
    + +
    ALTER TABLE 
    +  `PREFIX_employee` 
    +ADD 
    +  `bo_color` varchar(32) default NULL 
    +AFTER 
    +  `stats_date_to`
    + +
    INSERT INTO `PREFIX_cms_category_lang` 
    +VALUES 
    +  (
    +    1, 3, 'Inicio', '', 'home', NULL, NULL, 
    +    NULL
    +  )
    + +
    INSERT INTO `PREFIX_cms_category` 
    +VALUES 
    +  (1, 0, 0, 1, NOW(), NOW(), 0)
    + +
    UPDATE 
    +  `PREFIX_cms_category` 
    +SET 
    +  `position` = 0
    + +
    ALTER TABLE 
    +  `PREFIX_customer` 
    +ADD 
    +  `note` text 
    +AFTER 
    +  `secure_key`
    + +
    ALTER TABLE 
    +  `PREFIX_contact` 
    +ADD 
    +  `customer_service` tinyint(1) NOT NULL DEFAULT 0 
    +AFTER 
    +  `email`
    + +
    INSERT INTO `PREFIX_specific_price` (
    +  `id_product`, `id_shop`, `id_currency`, 
    +  `id_country`, `id_group`, `priority`, 
    +  `price`, `from_quantity`, `reduction`, 
    +  `reduction_type`, `from`, `to`
    +) (
    +  SELECT 
    +    dq.`id_product`, 
    +    1, 
    +    1, 
    +    0, 
    +    1, 
    +    0, 
    +    0.00, 
    +    dq.`quantity`, 
    +    IF(
    +      dq.`id_discount_type` = 2, dq.`value`, 
    +      dq.`value` / 100
    +    ), 
    +    IF (
    +      dq.`id_discount_type` = 2, 'amount', 
    +      'percentage'
    +    ), 
    +    '0000-00-00 00:00:00', 
    +    '0000-00-00 00:00:00' 
    +  FROM 
    +    `PREFIX_discount_quantity` dq 
    +    INNER JOIN `PREFIX_product` p ON (p.`id_product` = dq.`id_product`)
    +)
    + +
    DROP 
    +  TABLE `PREFIX_discount_quantity`
    + +
    INSERT INTO `PREFIX_specific_price` (
    +  `id_product`, `id_shop`, `id_currency`, 
    +  `id_country`, `id_group`, `priority`, 
    +  `price`, `from_quantity`, `reduction`, 
    +  `reduction_type`, `from`, `to`
    +) (
    +  SELECT 
    +    p.`id_product`, 
    +    1, 
    +    0, 
    +    0, 
    +    0, 
    +    0, 
    +    0.00, 
    +    1, 
    +    IF(
    +      p.`reduction_price` > 0, p.`reduction_price`, 
    +      p.`reduction_percent` / 100
    +    ), 
    +    IF(
    +      p.`reduction_price` > 0, 'amount', 
    +      'percentage'
    +    ), 
    +    IF (
    +      p.`reduction_from` = p.`reduction_to`, 
    +      '0000-00-00 00:00:00', p.`reduction_from`
    +    ), 
    +    IF (
    +      p.`reduction_from` = p.`reduction_to`, 
    +      '0000-00-00 00:00:00', p.`reduction_to`
    +    ) 
    +  FROM 
    +    `PREFIX_product` p 
    +  WHERE 
    +    p.`reduction_price` 
    +    OR p.`reduction_percent`
    +)
    + +
    ALTER TABLE 
    +  `PREFIX_product` 
    +DROP 
    +  `reduction_price`, 
    +DROP 
    +  `reduction_percent`, 
    +DROP 
    +  `reduction_from`, 
    +DROP 
    +  `reduction_to`
    + +
    INSERT INTO `PREFIX_configuration` (
    +  `name`, `value`, `date_add`, `date_upd`
    +) 
    +VALUES 
    +  (
    +    'PS_SPECIFIC_PRICE_PRIORITIES', 
    +    'id_shop;id_currency;id_country;id_group', 
    +    NOW(), NOW()
    +  ), 
    +  ('PS_TAX_DISPLAY', 0, NOW(), NOW()), 
    +  (
    +    'PS_SMARTY_FORCE_COMPILE', 1, NOW(), 
    +    NOW()
    +  ), 
    +  (
    +    'PS_DISTANCE_UNIT', 'km', NOW(), NOW()
    +  ), 
    +  (
    +    'PS_STORES_DISPLAY_CMS', 0, NOW(), 
    +    NOW()
    +  ), 
    +  (
    +    'PS_STORES_DISPLAY_FOOTER', 0, NOW(), 
    +    NOW()
    +  ), 
    +  (
    +    'PS_STORES_SIMPLIFIED', 0, NOW(), 
    +    NOW()
    +  ), 
    +  (
    +    'PS_STATSDATA_CUSTOMER_PAGESVIEWS', 
    +    1, NOW(), NOW()
    +  ), 
    +  (
    +    'PS_STATSDATA_PAGESVIEWS', 1, NOW(), 
    +    NOW()
    +  ), 
    +  (
    +    'PS_STATSDATA_PLUGINS', 1, NOW(), 
    +    NOW()
    +  )
    + +
    INSERT INTO `PREFIX_configuration` (
    +  `name`, `value`, `date_add`, `date_upd`
    +) 
    +VALUES 
    +  (
    +    'PS_CONDITIONS_CMS_ID', 
    +    IFNULL(
    +      (
    +        SELECT 
    +          `id_cms` 
    +        FROM 
    +          `PREFIX_cms` 
    +        WHERE 
    +          `id_cms` = 3
    +      ), 
    +      0
    +    ), 
    +    NOW(), 
    +    NOW()
    +  )
    + +
    CREATE TEMPORARY TABLE `PREFIX_configuration_tmp` (`value` text)
    + +
    SET 
    +  @defaultOOS = (
    +    SELECT 
    +      value 
    +    FROM 
    +      `PREFIX_configuration` 
    +    WHERE 
    +      name = 'PS_ORDER_OUT_OF_STOCK'
    +  )
    + +
    UPDATE 
    +  `PREFIX_product` p 
    +SET 
    +  `cache_default_attribute` = 0 
    +WHERE 
    +  `id_product` NOT IN (
    +    SELECT 
    +      `id_product` 
    +    FROM 
    +      `PREFIX_product_attribute`
    +  )
    + +
    INSERT INTO `PREFIX_hook` (
    +  `name`, `title`, `description`, `position`
    +) 
    +VALUES 
    +  (
    +    'processCarrier', 'Carrier Process', 
    +    NULL, 0
    +  )
    + +
    INSERT INTO `PREFIX_stock_mvt_reason_lang` (
    +  `id_stock_mvt_reason`, `id_lang`, 
    +  `name`
    +) 
    +VALUES 
    +  (1, 1, 'Order'), 
    +  (1, 2, 'Commande'), 
    +  (2, 1, 'Missing Stock Movement'), 
    +  (
    +    2, 2, 'Mouvement de stock manquant'
    +  ), 
    +  (3, 1, 'Restocking'), 
    +  (3, 2, 'Réassort')
    + +
    INSERT INTO `PREFIX_meta_lang` (
    +  `id_lang`, `id_meta`, `title`, `url_rewrite`
    +) 
    +VALUES 
    +  (
    +    1, 
    +    (
    +      SELECT 
    +        `id_meta` 
    +      FROM 
    +        `PREFIX_meta` 
    +      WHERE 
    +        `page` = 'authentication'
    +    ), 
    +    'Authentication', 
    +    'authentication'
    +  ), 
    +  (
    +    2, 
    +    (
    +      SELECT 
    +        `id_meta` 
    +      FROM 
    +        `PREFIX_meta` 
    +      WHERE 
    +        `page` = 'authentication'
    +    ), 
    +    'Authentification', 
    +    'authentification'
    +  ), 
    +  (
    +    3, 
    +    (
    +      SELECT 
    +        `id_meta` 
    +      FROM 
    +        `PREFIX_meta` 
    +      WHERE 
    +        `page` = 'authentication'
    +    ), 
    +    'Autenticación', 
    +    'autenticacion'
    +  )
    + +
    LOCK TABLES `admin_assert` WRITE
    + +
    UNLOCK TABLES
    + +
    DROP 
    +  TABLE IF EXISTS `admin_role`
    + +
    SELECT 
    +  * 
    +FROM 
    +  -- This is another comment
    +  MyTable # One final comment
    +  
    +  /* This is a block comment 
    +  */
    +WHERE 
    +  1 = 2;
    + +
    SELECT 
    +  -- This is a test
    + +
    SELECT 
    +  Test 
    +FROM 
    +  Test 
    +WHERE 
    +  (MyColumn = 1)
    +)
    +AND (
    +  (
    +    (SomeOtherColumn = 2); 
    +WARNING: unclosed parentheses or section
    + +
    SELECT 
    +  * 
    +LIMIT 
    +  1; 
    +SELECT 
    +  a, 
    +  b, 
    +  c, 
    +  d 
    +FROM 
    +  e 
    +LIMIT 
    +  1, 2; 
    +SELECT 
    +  1, 
    +  2, 
    +  3 
    +WHERE 
    +  a in (1, 2, 3, 4, 5) 
    +  and b = 5;
    + +
    SELECT 
    +  count - 50 
    +WHERE 
    +  a - 50 = b 
    +WHERE 
    +  1 
    +  and -50 
    +WHERE 
    +  -50 = a 
    +WHERE 
    +  a = -50 
    +WHERE 
    +  1 
    +  /*test*/
    +  -50 
    +WHERE 
    +  1 
    +  and -50;
    + +
    SELECT 
    +  @ 
    +  and b;
    + +
    SELECT 
    +  @"weird variable name";
    + +
    SELECT 
    +  "no closing quote
    +
    \ No newline at end of file diff --git a/vendor/jdorn/sql-formatter/tests/format.html b/vendor/jdorn/sql-formatter/tests/format.html new file mode 100644 index 0000000..dcbac03 --- /dev/null +++ b/vendor/jdorn/sql-formatter/tests/format.html @@ -0,0 +1,807 @@ +SELECT + customer_id, + customer_name, + COUNT(order_id) as total +FROM + customers + INNER JOIN orders ON customers.customer_id = orders.customer_id +GROUP BY + customer_id, + customer_name +HAVING + COUNT(order_id) > 5 +ORDER BY + COUNT(order_id) DESC; + +UPDATE + customers +SET + totalorders = ordersummary.total +FROM + ( + SELECT + customer_id, + count(order_id) As total + FROM + orders + GROUP BY + customer_id + ) As ordersummary +WHERE + customers.customer_id = ordersummary.customer_id + +SELECT + * +FROM + sometable +UNION ALL +SELECT + * +FROM + someothertable; + +SET + NAMES 'utf8'; + +CREATE TABLE `PREFIX_address` ( + `id_address` int(10) unsigned NOT NULL auto_increment, + `id_country` int(10) unsigned NOT NULL, + `id_state` int(10) unsigned default NULL, + `id_customer` int(10) unsigned NOT NULL default '0', + `id_manufacturer` int(10) unsigned NOT NULL default '0', + `id_supplier` int(10) unsigned NOT NULL default '0', + `id_warehouse` int(10) unsigned NOT NULL default '0', + `alias` varchar(32) NOT NULL, + `company` varchar(64) default NULL, + `lastname` varchar(32) NOT NULL, + `firstname` varchar(32) NOT NULL, + `address1` varchar(128) NOT NULL, + `address2` varchar(128) default NULL, + `postcode` varchar(12) default NULL, + `city` varchar(64) NOT NULL, + `other` text, + `phone` varchar(16) default NULL, + `phone_mobile` varchar(16) default NULL, + `vat_number` varchar(32) default NULL, + `dni` varchar(16) DEFAULT NULL, + `date_add` datetime NOT NULL, + `date_upd` datetime NOT NULL, + `active` tinyint(1) unsigned NOT NULL default '1', + `deleted` tinyint(1) unsigned NOT NULL default '0', + PRIMARY KEY (`id_address`), + KEY `address_customer` (`id_customer`), + KEY `id_country` (`id_country`), + KEY `id_state` (`id_state`), + KEY `id_manufacturer` (`id_manufacturer`), + KEY `id_supplier` (`id_supplier`), + KEY `id_warehouse` (`id_warehouse`) +) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 + +CREATE TABLE `PREFIX_alias` ( + `id_alias` int(10) unsigned NOT NULL auto_increment, + `alias` varchar(255) NOT NULL, + `search` varchar(255) NOT NULL, + `active` tinyint(1) NOT NULL default '1', + PRIMARY KEY (`id_alias`), + UNIQUE KEY `alias` (`alias`) +) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 + +CREATE TABLE `PREFIX_carrier` ( + `id_carrier` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id_reference` int(10) unsigned NOT NULL, + `id_tax_rules_group` int(10) unsigned DEFAULT '0', + `name` varchar(64) NOT NULL, + `url` varchar(255) DEFAULT NULL, + `active` tinyint(1) unsigned NOT NULL DEFAULT '0', + `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0', + `shipping_handling` tinyint(1) unsigned NOT NULL DEFAULT '1', + `range_behavior` tinyint(1) unsigned NOT NULL DEFAULT '0', + `is_module` tinyint(1) unsigned NOT NULL DEFAULT '0', + `is_free` tinyint(1) unsigned NOT NULL DEFAULT '0', + `shipping_external` tinyint(1) unsigned NOT NULL DEFAULT '0', + `need_range` tinyint(1) unsigned NOT NULL DEFAULT '0', + `external_module_name` varchar(64) DEFAULT NULL, + `shipping_method` int(2) NOT NULL DEFAULT '0', + `position` int(10) unsigned NOT NULL default '0', + `max_width` int(10) DEFAULT 0, + `max_height` int(10) DEFAULT 0, + `max_depth` int(10) DEFAULT 0, + `max_weight` int(10) DEFAULT 0, + `grade` int(10) DEFAULT 0, + PRIMARY KEY (`id_carrier`), + KEY `deleted` (`deleted`, `active`), + KEY `id_tax_rules_group` (`id_tax_rules_group`) +) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 + +CREATE TABLE IF NOT EXISTS `PREFIX_specific_price_rule` ( + `id_specific_price_rule` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL, + `id_shop` int(11) unsigned NOT NULL DEFAULT '1', + `id_currency` int(10) unsigned NOT NULL, + `id_country` int(10) unsigned NOT NULL, + `id_group` int(10) unsigned NOT NULL, + `from_quantity` mediumint(8) unsigned NOT NULL, + `price` DECIMAL(20, 6), + `reduction` decimal(20, 6) NOT NULL, + `reduction_type` enum('amount', 'percentage') NOT NULL, + `from` datetime NOT NULL, + `to` datetime NOT NULL, + PRIMARY KEY (`id_specific_price_rule`), + KEY `id_product` ( + `id_shop`, `id_currency`, `id_country`, + `id_group`, `from_quantity`, `from`, + `to` + ) +) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 + +UPDATE + `PREFIX_configuration` +SET + value = '6' +WHERE + name = 'PS_SEARCH_WEIGHT_PNAME' + +UPDATE + `PREFIX_hook_module` +SET + position = 1 +WHERE + id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayPayment' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'cheque' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayPaymentReturn' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'cheque' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayHome' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'homeslider' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionAuthentication' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'statsdata' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionShopDataDuplication' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'homeslider' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayTop' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blocklanguages' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionCustomerAccountAdd' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'statsdata' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayCustomerAccount' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'favoriteproducts' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayAdminStatsModules' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'statsvisits' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayAdminStatsGraphEngine' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'graphvisifire' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayAdminStatsGridEngine' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'gridhtml' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayLeftColumnProduct' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blocksharefb' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionSearch' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'statssearch' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionCategoryAdd' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blockcategories' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionCategoryUpdate' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blockcategories' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionCategoryDelete' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blockcategories' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'actionAdminMetaSave' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blockcategories' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayMyAccountBlock' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'favoriteproducts' + ) + OR id_hook = ( + SELECT + id_hook + FROM + `PREFIX_hook` + WHERE + name = 'displayFooter' + ) + AND id_module = ( + SELECT + id_module + FROM + `PREFIX_module` + WHERE + name = 'blockreinsurance' + ) + +ALTER TABLE + `PREFIX_employee` +ADD + `bo_color` varchar(32) default NULL +AFTER + `stats_date_to` + +INSERT INTO `PREFIX_cms_category_lang` +VALUES + ( + 1, 3, 'Inicio', '', 'home', NULL, NULL, + NULL + ) + +INSERT INTO `PREFIX_cms_category` +VALUES + (1, 0, 0, 1, NOW(), NOW(), 0) + +UPDATE + `PREFIX_cms_category` +SET + `position` = 0 + +ALTER TABLE + `PREFIX_customer` +ADD + `note` text +AFTER + `secure_key` + +ALTER TABLE + `PREFIX_contact` +ADD + `customer_service` tinyint(1) NOT NULL DEFAULT 0 +AFTER + `email` + +INSERT INTO `PREFIX_specific_price` ( + `id_product`, `id_shop`, `id_currency`, + `id_country`, `id_group`, `priority`, + `price`, `from_quantity`, `reduction`, + `reduction_type`, `from`, `to` +) ( + SELECT + dq.`id_product`, + 1, + 1, + 0, + 1, + 0, + 0.00, + dq.`quantity`, + IF( + dq.`id_discount_type` = 2, dq.`value`, + dq.`value` / 100 + ), + IF ( + dq.`id_discount_type` = 2, 'amount', + 'percentage' + ), + '0000-00-00 00:00:00', + '0000-00-00 00:00:00' + FROM + `PREFIX_discount_quantity` dq + INNER JOIN `PREFIX_product` p ON (p.`id_product` = dq.`id_product`) +) + +DROP + TABLE `PREFIX_discount_quantity` + +INSERT INTO `PREFIX_specific_price` ( + `id_product`, `id_shop`, `id_currency`, + `id_country`, `id_group`, `priority`, + `price`, `from_quantity`, `reduction`, + `reduction_type`, `from`, `to` +) ( + SELECT + p.`id_product`, + 1, + 0, + 0, + 0, + 0, + 0.00, + 1, + IF( + p.`reduction_price` > 0, p.`reduction_price`, + p.`reduction_percent` / 100 + ), + IF( + p.`reduction_price` > 0, 'amount', + 'percentage' + ), + IF ( + p.`reduction_from` = p.`reduction_to`, + '0000-00-00 00:00:00', p.`reduction_from` + ), + IF ( + p.`reduction_from` = p.`reduction_to`, + '0000-00-00 00:00:00', p.`reduction_to` + ) + FROM + `PREFIX_product` p + WHERE + p.`reduction_price` + OR p.`reduction_percent` +) + +ALTER TABLE + `PREFIX_product` +DROP + `reduction_price`, +DROP + `reduction_percent`, +DROP + `reduction_from`, +DROP + `reduction_to` + +INSERT INTO `PREFIX_configuration` ( + `name`, `value`, `date_add`, `date_upd` +) +VALUES + ( + 'PS_SPECIFIC_PRICE_PRIORITIES', + 'id_shop;id_currency;id_country;id_group', + NOW(), NOW() + ), + ('PS_TAX_DISPLAY', 0, NOW(), NOW()), + ( + 'PS_SMARTY_FORCE_COMPILE', 1, NOW(), + NOW() + ), + ( + 'PS_DISTANCE_UNIT', 'km', NOW(), NOW() + ), + ( + 'PS_STORES_DISPLAY_CMS', 0, NOW(), + NOW() + ), + ( + 'PS_STORES_DISPLAY_FOOTER', 0, NOW(), + NOW() + ), + ( + 'PS_STORES_SIMPLIFIED', 0, NOW(), + NOW() + ), + ( + 'PS_STATSDATA_CUSTOMER_PAGESVIEWS', + 1, NOW(), NOW() + ), + ( + 'PS_STATSDATA_PAGESVIEWS', 1, NOW(), + NOW() + ), + ( + 'PS_STATSDATA_PLUGINS', 1, NOW(), + NOW() + ) + +INSERT INTO `PREFIX_configuration` ( + `name`, `value`, `date_add`, `date_upd` +) +VALUES + ( + 'PS_CONDITIONS_CMS_ID', + IFNULL( + ( + SELECT + `id_cms` + FROM + `PREFIX_cms` + WHERE + `id_cms` = 3 + ), + 0 + ), + NOW(), + NOW() + ) + +CREATE TEMPORARY TABLE `PREFIX_configuration_tmp` (`value` text) + +SET + @defaultOOS = ( + SELECT + value + FROM + `PREFIX_configuration` + WHERE + name = 'PS_ORDER_OUT_OF_STOCK' + ) + +UPDATE + `PREFIX_product` p +SET + `cache_default_attribute` = 0 +WHERE + `id_product` NOT IN ( + SELECT + `id_product` + FROM + `PREFIX_product_attribute` + ) + +INSERT INTO `PREFIX_hook` ( + `name`, `title`, `description`, `position` +) +VALUES + ( + 'processCarrier', 'Carrier Process', + NULL, 0 + ) + +INSERT INTO `PREFIX_stock_mvt_reason_lang` ( + `id_stock_mvt_reason`, `id_lang`, + `name` +) +VALUES + (1, 1, 'Order'), + (1, 2, 'Commande'), + (2, 1, 'Missing Stock Movement'), + ( + 2, 2, 'Mouvement de stock manquant' + ), + (3, 1, 'Restocking'), + (3, 2, 'Réassort') + +INSERT INTO `PREFIX_meta_lang` ( + `id_lang`, `id_meta`, `title`, `url_rewrite` +) +VALUES + ( + 1, + ( + SELECT + `id_meta` + FROM + `PREFIX_meta` + WHERE + `page` = 'authentication' + ), + 'Authentication', + 'authentication' + ), + ( + 2, + ( + SELECT + `id_meta` + FROM + `PREFIX_meta` + WHERE + `page` = 'authentication' + ), + 'Authentification', + 'authentification' + ), + ( + 3, + ( + SELECT + `id_meta` + FROM + `PREFIX_meta` + WHERE + `page` = 'authentication' + ), + 'Autenticación', + 'autenticacion' + ) + +LOCK TABLES `admin_assert` WRITE + +UNLOCK TABLES + +DROP + TABLE IF EXISTS `admin_role` + +SELECT + * +FROM + -- This is another comment + MyTable # One final comment + + /* This is a block comment + */ +WHERE + 1 = 2; + +SELECT + -- This is a test + +SELECT + Test +FROM + Test +WHERE + (MyColumn = 1) +) +AND ( + ( + (SomeOtherColumn = 2); + +SELECT + * +LIMIT + 1; +SELECT + a, + b, + c, + d +FROM + e +LIMIT + 1, 2; +SELECT + 1, + 2, + 3 +WHERE + a in (1, 2, 3, 4, 5) + and b = 5; + +SELECT + count - 50 +WHERE + a - 50 = b +WHERE + 1 + and -50 +WHERE + -50 = a +WHERE + a = -50 +WHERE + 1 + /*test*/ + -50 +WHERE + 1 + and -50; + +SELECT + @ + and b; + +SELECT + @"weird variable name"; + +SELECT + "no closing quote \ No newline at end of file diff --git a/vendor/jdorn/sql-formatter/tests/highlight.html b/vendor/jdorn/sql-formatter/tests/highlight.html new file mode 100644 index 0000000..e26af9a --- /dev/null +++ b/vendor/jdorn/sql-formatter/tests/highlight.html @@ -0,0 +1,262 @@ +
    SELECT customer_id, customer_name, COUNT(order_id) as total
    +FROM customers INNER JOIN orders ON customers.customer_id = orders.customer_id
    +GROUP BY customer_id, customer_name
    +HAVING COUNT(order_id) > 5
    +ORDER BY COUNT(order_id) DESC;
    + +
    UPDATE customers
    +        SET totalorders = ordersummary.total
    +        FROM (SELECT customer_id, count(order_id) As total 
    +FROM orders GROUP BY customer_id) As ordersummary
    +        WHERE customers.customer_id = ordersummary.customer_id
    + +
    SELECT * FROM sometable
    +UNION ALL
    +SELECT * FROM someothertable;
    + +
    SET NAMES 'utf8';
    + +
    CREATE TABLE `PREFIX_address` (
    +  `id_address` int(10) unsigned NOT NULL auto_increment,
    +  `id_country` int(10) unsigned NOT NULL,
    +  `id_state` int(10) unsigned default NULL,
    +  `id_customer` int(10) unsigned NOT NULL default '0',
    +  `id_manufacturer` int(10) unsigned NOT NULL default '0',
    +  `id_supplier` int(10) unsigned NOT NULL default '0',
    +  `id_warehouse` int(10) unsigned NOT NULL default '0',
    +  `alias` varchar(32) NOT NULL,
    +  `company` varchar(64) default NULL,
    +  `lastname` varchar(32) NOT NULL,
    +  `firstname` varchar(32) NOT NULL,
    +  `address1` varchar(128) NOT NULL,
    +  `address2` varchar(128) default NULL,
    +  `postcode` varchar(12) default NULL,
    +  `city` varchar(64) NOT NULL,
    +  `other` text,
    +  `phone` varchar(16) default NULL,
    +  `phone_mobile` varchar(16) default NULL,
    +  `vat_number` varchar(32) default NULL,
    +  `dni` varchar(16) DEFAULT NULL,
    +  `date_add` datetime NOT NULL,
    +  `date_upd` datetime NOT NULL,
    +  `active` tinyint(1) unsigned NOT NULL default '1',
    +  `deleted` tinyint(1) unsigned NOT NULL default '0',
    +  PRIMARY KEY (`id_address`),
    +  KEY `address_customer` (`id_customer`),
    +  KEY `id_country` (`id_country`),
    +  KEY `id_state` (`id_state`),
    +  KEY `id_manufacturer` (`id_manufacturer`),
    +  KEY `id_supplier` (`id_supplier`),
    +  KEY `id_warehouse` (`id_warehouse`)
    +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8
    + +
    CREATE TABLE `PREFIX_alias` (
    +  `id_alias` int(10) unsigned NOT NULL auto_increment,
    +  `alias` varchar(255) NOT NULL,
    +  `search` varchar(255) NOT NULL,
    +  `active` tinyint(1) NOT NULL default '1',
    +  PRIMARY KEY (`id_alias`),
    +  UNIQUE KEY `alias` (`alias`)
    +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8
    + +
    CREATE TABLE `PREFIX_carrier` (
    +  `id_carrier` int(10) unsigned NOT NULL AUTO_INCREMENT,
    +  `id_reference` int(10) unsigned NOT NULL,
    +  `id_tax_rules_group` int(10) unsigned DEFAULT '0',
    +  `name` varchar(64) NOT NULL,
    +  `url` varchar(255) DEFAULT NULL,
    +  `active` tinyint(1) unsigned NOT NULL DEFAULT '0',
    +  `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0',
    +  `shipping_handling` tinyint(1) unsigned NOT NULL DEFAULT '1',
    +  `range_behavior` tinyint(1) unsigned NOT NULL DEFAULT '0',
    +  `is_module` tinyint(1) unsigned NOT NULL DEFAULT '0',
    +  `is_free` tinyint(1) unsigned NOT NULL DEFAULT '0',
    +  `shipping_external` tinyint(1) unsigned NOT NULL DEFAULT '0',
    +  `need_range` tinyint(1) unsigned NOT NULL DEFAULT '0',
    +  `external_module_name` varchar(64) DEFAULT NULL,
    +  `shipping_method` int(2) NOT NULL DEFAULT '0',
    +  `position` int(10) unsigned NOT NULL default '0',
    +  `max_width` int(10) DEFAULT 0,
    +  `max_height` int(10)  DEFAULT 0,
    +  `max_depth` int(10)  DEFAULT 0,
    +  `max_weight` int(10)  DEFAULT 0,
    +  `grade` int(10)  DEFAULT 0,
    +  PRIMARY KEY (`id_carrier`),
    +  KEY `deleted` (`deleted`,`active`),
    +  KEY `id_tax_rules_group` (`id_tax_rules_group`)
    +) ENGINE=ENGINE_TYPE  DEFAULT CHARSET=utf8
    + +
    CREATE TABLE IF NOT EXISTS `PREFIX_specific_price_rule` (
    +	`id_specific_price_rule` int(10) unsigned NOT NULL AUTO_INCREMENT,
    +	`name` VARCHAR(255) NOT NULL,
    +	`id_shop` int(11) unsigned NOT NULL DEFAULT '1',
    +	`id_currency` int(10) unsigned NOT NULL,
    +	`id_country` int(10) unsigned NOT NULL,
    +	`id_group` int(10) unsigned NOT NULL,
    +	`from_quantity` mediumint(8) unsigned NOT NULL,
    +	`price` DECIMAL(20,6),
    +	`reduction` decimal(20,6) NOT NULL,
    +	`reduction_type` enum('amount','percentage') NOT NULL,
    +	`from` datetime NOT NULL,
    +	`to` datetime NOT NULL,
    +	PRIMARY KEY (`id_specific_price_rule`),
    +	KEY `id_product` (`id_shop`,`id_currency`,`id_country`,`id_group`,`from_quantity`,`from`,`to`)
    +) ENGINE=ENGINE_TYPE  DEFAULT CHARSET=utf8
    + +
    UPDATE `PREFIX_configuration` SET value = '6' WHERE name = 'PS_SEARCH_WEIGHT_PNAME'
    + +
    UPDATE `PREFIX_hook_module` SET position = 1
    +WHERE
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayPayment') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'cheque')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayPaymentReturn') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'cheque')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayHome') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'homeslider')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionAuthentication') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsdata')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionShopDataDuplication') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'homeslider')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayTop') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blocklanguages')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCustomerAccountAdd') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsdata')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayCustomerAccount') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'favoriteproducts')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsModules') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsvisits')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsGraphEngine') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'graphvisifire')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsGridEngine') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'gridhtml')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayLeftColumnProduct') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blocksharefb')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionSearch') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statssearch')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryAdd') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryUpdate') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryDelete') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionAdminMetaSave') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayMyAccountBlock') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'favoriteproducts')
    +	OR
    +	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayFooter') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockreinsurance')
    + +
    ALTER TABLE `PREFIX_employee` ADD `bo_color` varchar(32) default NULL AFTER `stats_date_to`
    + +
    INSERT INTO `PREFIX_cms_category_lang` VALUES(1, 3, 'Inicio', '', 'home', NULL, NULL, NULL)
    + +
    INSERT INTO `PREFIX_cms_category` VALUES(1, 0, 0, 1, NOW(), NOW(),0)
    + +
    UPDATE `PREFIX_cms_category` SET `position` = 0
    + +
    ALTER TABLE `PREFIX_customer` ADD `note` text AFTER `secure_key`
    + +
    ALTER TABLE `PREFIX_contact` ADD `customer_service` tinyint(1) NOT NULL DEFAULT 0 AFTER `email`
    + +
    INSERT INTO `PREFIX_specific_price` (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `priority`, `price`, `from_quantity`, `reduction`, `reduction_type`, `from`, `to`)
    +	(	SELECT dq.`id_product`, 1, 1, 0, 1, 0, 0.00, dq.`quantity`, IF(dq.`id_discount_type` = 2, dq.`value`, dq.`value` / 100), IF (dq.`id_discount_type` = 2, 'amount', 'percentage'), '0000-00-00 00:00:00', '0000-00-00 00:00:00'
    +		FROM `PREFIX_discount_quantity` dq
    +		INNER JOIN `PREFIX_product` p ON (p.`id_product` = dq.`id_product`)
    +	)
    + +
    DROP TABLE `PREFIX_discount_quantity`
    + +
    INSERT INTO `PREFIX_specific_price` (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `priority`, `price`, `from_quantity`, `reduction`, `reduction_type`, `from`, `to`) (
    +	SELECT
    +		p.`id_product`,
    +		1,
    +		0,
    +		0,
    +		0,
    +		0,
    +		0.00,
    +		1,
    +		IF(p.`reduction_price` > 0, p.`reduction_price`, p.`reduction_percent` / 100),
    +		IF(p.`reduction_price` > 0, 'amount', 'percentage'),
    +		IF (p.`reduction_from` = p.`reduction_to`, '0000-00-00 00:00:00', p.`reduction_from`),
    +		IF (p.`reduction_from` = p.`reduction_to`, '0000-00-00 00:00:00', p.`reduction_to`)
    +	FROM `PREFIX_product` p
    +	WHERE p.`reduction_price` OR p.`reduction_percent`
    +)
    + +
    ALTER TABLE `PREFIX_product`
    +	DROP `reduction_price`,
    +	DROP `reduction_percent`,
    +	DROP `reduction_from`,
    +	DROP `reduction_to`
    + +
    INSERT INTO `PREFIX_configuration` (`name`, `value`, `date_add`, `date_upd`) VALUES
    +('PS_SPECIFIC_PRICE_PRIORITIES', 'id_shop;id_currency;id_country;id_group', NOW(), NOW()),
    +('PS_TAX_DISPLAY', 0, NOW(), NOW()),
    +('PS_SMARTY_FORCE_COMPILE', 1, NOW(), NOW()),
    +('PS_DISTANCE_UNIT', 'km', NOW(), NOW()),
    +('PS_STORES_DISPLAY_CMS', 0, NOW(), NOW()),
    +('PS_STORES_DISPLAY_FOOTER', 0, NOW(), NOW()),
    +('PS_STORES_SIMPLIFIED', 0, NOW(), NOW()),
    +('PS_STATSDATA_CUSTOMER_PAGESVIEWS', 1, NOW(), NOW()),
    +('PS_STATSDATA_PAGESVIEWS', 1, NOW(), NOW()),
    +('PS_STATSDATA_PLUGINS', 1, NOW(), NOW())
    + +
    INSERT INTO `PREFIX_configuration` (`name`, `value`, `date_add`, `date_upd`) VALUES ('PS_CONDITIONS_CMS_ID', IFNULL((SELECT `id_cms` FROM `PREFIX_cms` WHERE `id_cms` = 3), 0), NOW(), NOW())
    + +
    CREATE TEMPORARY TABLE `PREFIX_configuration_tmp` (
    +	`value` text
    +)
    + +
    SET @defaultOOS = (SELECT value FROM `PREFIX_configuration` WHERE name = 'PS_ORDER_OUT_OF_STOCK')
    + +
    UPDATE `PREFIX_product` p SET `cache_default_attribute` =  0 WHERE `id_product` NOT IN (SELECT `id_product` FROM `PREFIX_product_attribute`)
    + +
    INSERT INTO `PREFIX_hook` (`name`, `title`, `description`, `position`) VALUES ('processCarrier', 'Carrier Process', NULL, 0)
    + +
    INSERT INTO `PREFIX_stock_mvt_reason_lang` (`id_stock_mvt_reason`, `id_lang`, `name`) VALUES
    +(1, 1, 'Order'),
    +(1, 2, 'Commande'),
    +(2, 1, 'Missing Stock Movement'),
    +(2, 2, 'Mouvement de stock manquant'),
    +(3, 1, 'Restocking'),
    +(3, 2, 'Réassort')
    + +
    INSERT INTO `PREFIX_meta_lang` (`id_lang`, `id_meta`, `title`, `url_rewrite`) VALUES
    +(1, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Authentication', 'authentication'),
    +(2, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Authentification', 'authentification'),
    +(3, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Autenticación', 'autenticacion')
    + +
    LOCK TABLES `admin_assert` WRITE
    + +
    UNLOCK TABLES
    + +
    DROP TABLE IF EXISTS `admin_role`
    + +
    SELECT * FROM
    +-- This is another comment
    +MyTable # One final comment
    +/* This is a block comment 
    +*/ WHERE 1 = 2;
    + +
    SELECT -- This is a test
    + +
    SELECT Test FROM Test WHERE
    +(
    + MyColumn = 1 )) AND ((( SomeOtherColumn = 2);
    + +
    SELECT * LIMIT 1; SELECT a,b,c,d FROM e LIMIT 1, 2; SELECT 1,2,3 WHERE a in (1,2,3,4,5) and b=5;
    + +
    SELECT count - 50
    +WHERE a-50 = b
    +WHERE 1 and - 50
    +WHERE -50 = a
    +WHERE a = -50
    +WHERE 1 /*test*/ - 50
    +WHERE 1 and -50;
    + +
    SELECT @ and b;
    + +
    SELECT @"weird variable name";
    + +
    SELECT "no closing quote
    +
    \ No newline at end of file diff --git a/vendor/jdorn/sql-formatter/tests/performance.php b/vendor/jdorn/sql-formatter/tests/performance.php new file mode 100644 index 0000000..6c9eb97 --- /dev/null +++ b/vendor/jdorn/sql-formatter/tests/performance.php @@ -0,0 +1,44 @@ +Formatted ".$num." queries using a max_cachekey_size of ".SqlFormatter::$max_cachekey_size."

    "; + +echo "

    Average query length of ".number_format($chars/$num,5)." characters

    "; + +echo "

    Took ".number_format($end-$start,5)." seconds total, ".number_format(($end-$start)/$num,5)." seconds per query, ".number_format(1000*($end-$start)/$chars,5)." seconds per 1000 characters

    "; + +echo "

    Used ".number_format($uend-$ustart)." bytes of memory

    "; + +echo "

    Cache Stats

    ".print_r(SqlFormatter::getCacheStats(),true)."
    "; + diff --git a/vendor/jdorn/sql-formatter/tests/sql.sql b/vendor/jdorn/sql-formatter/tests/sql.sql new file mode 100644 index 0000000..4e2d988 --- /dev/null +++ b/vendor/jdorn/sql-formatter/tests/sql.sql @@ -0,0 +1,261 @@ +SELECT customer_id, customer_name, COUNT(order_id) as total +FROM customers INNER JOIN orders ON customers.customer_id = orders.customer_id +GROUP BY customer_id, customer_name +HAVING COUNT(order_id) > 5 +ORDER BY COUNT(order_id) DESC; + +UPDATE customers + SET totalorders = ordersummary.total + FROM (SELECT customer_id, count(order_id) As total +FROM orders GROUP BY customer_id) As ordersummary + WHERE customers.customer_id = ordersummary.customer_id + +SELECT * FROM sometable +UNION ALL +SELECT * FROM someothertable; + +SET NAMES 'utf8'; + +CREATE TABLE `PREFIX_address` ( + `id_address` int(10) unsigned NOT NULL auto_increment, + `id_country` int(10) unsigned NOT NULL, + `id_state` int(10) unsigned default NULL, + `id_customer` int(10) unsigned NOT NULL default '0', + `id_manufacturer` int(10) unsigned NOT NULL default '0', + `id_supplier` int(10) unsigned NOT NULL default '0', + `id_warehouse` int(10) unsigned NOT NULL default '0', + `alias` varchar(32) NOT NULL, + `company` varchar(64) default NULL, + `lastname` varchar(32) NOT NULL, + `firstname` varchar(32) NOT NULL, + `address1` varchar(128) NOT NULL, + `address2` varchar(128) default NULL, + `postcode` varchar(12) default NULL, + `city` varchar(64) NOT NULL, + `other` text, + `phone` varchar(16) default NULL, + `phone_mobile` varchar(16) default NULL, + `vat_number` varchar(32) default NULL, + `dni` varchar(16) DEFAULT NULL, + `date_add` datetime NOT NULL, + `date_upd` datetime NOT NULL, + `active` tinyint(1) unsigned NOT NULL default '1', + `deleted` tinyint(1) unsigned NOT NULL default '0', + PRIMARY KEY (`id_address`), + KEY `address_customer` (`id_customer`), + KEY `id_country` (`id_country`), + KEY `id_state` (`id_state`), + KEY `id_manufacturer` (`id_manufacturer`), + KEY `id_supplier` (`id_supplier`), + KEY `id_warehouse` (`id_warehouse`) +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 + +CREATE TABLE `PREFIX_alias` ( + `id_alias` int(10) unsigned NOT NULL auto_increment, + `alias` varchar(255) NOT NULL, + `search` varchar(255) NOT NULL, + `active` tinyint(1) NOT NULL default '1', + PRIMARY KEY (`id_alias`), + UNIQUE KEY `alias` (`alias`) +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 + +CREATE TABLE `PREFIX_carrier` ( + `id_carrier` int(10) unsigned NOT NULL AUTO_INCREMENT, + `id_reference` int(10) unsigned NOT NULL, + `id_tax_rules_group` int(10) unsigned DEFAULT '0', + `name` varchar(64) NOT NULL, + `url` varchar(255) DEFAULT NULL, + `active` tinyint(1) unsigned NOT NULL DEFAULT '0', + `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0', + `shipping_handling` tinyint(1) unsigned NOT NULL DEFAULT '1', + `range_behavior` tinyint(1) unsigned NOT NULL DEFAULT '0', + `is_module` tinyint(1) unsigned NOT NULL DEFAULT '0', + `is_free` tinyint(1) unsigned NOT NULL DEFAULT '0', + `shipping_external` tinyint(1) unsigned NOT NULL DEFAULT '0', + `need_range` tinyint(1) unsigned NOT NULL DEFAULT '0', + `external_module_name` varchar(64) DEFAULT NULL, + `shipping_method` int(2) NOT NULL DEFAULT '0', + `position` int(10) unsigned NOT NULL default '0', + `max_width` int(10) DEFAULT 0, + `max_height` int(10) DEFAULT 0, + `max_depth` int(10) DEFAULT 0, + `max_weight` int(10) DEFAULT 0, + `grade` int(10) DEFAULT 0, + PRIMARY KEY (`id_carrier`), + KEY `deleted` (`deleted`,`active`), + KEY `id_tax_rules_group` (`id_tax_rules_group`) +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 + +CREATE TABLE IF NOT EXISTS `PREFIX_specific_price_rule` ( + `id_specific_price_rule` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL, + `id_shop` int(11) unsigned NOT NULL DEFAULT '1', + `id_currency` int(10) unsigned NOT NULL, + `id_country` int(10) unsigned NOT NULL, + `id_group` int(10) unsigned NOT NULL, + `from_quantity` mediumint(8) unsigned NOT NULL, + `price` DECIMAL(20,6), + `reduction` decimal(20,6) NOT NULL, + `reduction_type` enum('amount','percentage') NOT NULL, + `from` datetime NOT NULL, + `to` datetime NOT NULL, + PRIMARY KEY (`id_specific_price_rule`), + KEY `id_product` (`id_shop`,`id_currency`,`id_country`,`id_group`,`from_quantity`,`from`,`to`) +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 + +UPDATE `PREFIX_configuration` SET value = '6' WHERE name = 'PS_SEARCH_WEIGHT_PNAME' + +UPDATE `PREFIX_hook_module` SET position = 1 +WHERE + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayPayment') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'cheque') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayPaymentReturn') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'cheque') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayHome') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'homeslider') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionAuthentication') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsdata') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionShopDataDuplication') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'homeslider') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayTop') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blocklanguages') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCustomerAccountAdd') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsdata') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayCustomerAccount') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'favoriteproducts') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsModules') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsvisits') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsGraphEngine') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'graphvisifire') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsGridEngine') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'gridhtml') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayLeftColumnProduct') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blocksharefb') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionSearch') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statssearch') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryAdd') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryUpdate') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryDelete') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionAdminMetaSave') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayMyAccountBlock') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'favoriteproducts') + OR + id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayFooter') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockreinsurance') + +ALTER TABLE `PREFIX_employee` ADD `bo_color` varchar(32) default NULL AFTER `stats_date_to` + +INSERT INTO `PREFIX_cms_category_lang` VALUES(1, 3, 'Inicio', '', 'home', NULL, NULL, NULL) + +INSERT INTO `PREFIX_cms_category` VALUES(1, 0, 0, 1, NOW(), NOW(),0) + +UPDATE `PREFIX_cms_category` SET `position` = 0 + +ALTER TABLE `PREFIX_customer` ADD `note` text AFTER `secure_key` + +ALTER TABLE `PREFIX_contact` ADD `customer_service` tinyint(1) NOT NULL DEFAULT 0 AFTER `email` + +INSERT INTO `PREFIX_specific_price` (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `priority`, `price`, `from_quantity`, `reduction`, `reduction_type`, `from`, `to`) + ( SELECT dq.`id_product`, 1, 1, 0, 1, 0, 0.00, dq.`quantity`, IF(dq.`id_discount_type` = 2, dq.`value`, dq.`value` / 100), IF (dq.`id_discount_type` = 2, 'amount', 'percentage'), '0000-00-00 00:00:00', '0000-00-00 00:00:00' + FROM `PREFIX_discount_quantity` dq + INNER JOIN `PREFIX_product` p ON (p.`id_product` = dq.`id_product`) + ) + +DROP TABLE `PREFIX_discount_quantity` + +INSERT INTO `PREFIX_specific_price` (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `priority`, `price`, `from_quantity`, `reduction`, `reduction_type`, `from`, `to`) ( + SELECT + p.`id_product`, + 1, + 0, + 0, + 0, + 0, + 0.00, + 1, + IF(p.`reduction_price` > 0, p.`reduction_price`, p.`reduction_percent` / 100), + IF(p.`reduction_price` > 0, 'amount', 'percentage'), + IF (p.`reduction_from` = p.`reduction_to`, '0000-00-00 00:00:00', p.`reduction_from`), + IF (p.`reduction_from` = p.`reduction_to`, '0000-00-00 00:00:00', p.`reduction_to`) + FROM `PREFIX_product` p + WHERE p.`reduction_price` OR p.`reduction_percent` +) + +ALTER TABLE `PREFIX_product` + DROP `reduction_price`, + DROP `reduction_percent`, + DROP `reduction_from`, + DROP `reduction_to` + +INSERT INTO `PREFIX_configuration` (`name`, `value`, `date_add`, `date_upd`) VALUES +('PS_SPECIFIC_PRICE_PRIORITIES', 'id_shop;id_currency;id_country;id_group', NOW(), NOW()), +('PS_TAX_DISPLAY', 0, NOW(), NOW()), +('PS_SMARTY_FORCE_COMPILE', 1, NOW(), NOW()), +('PS_DISTANCE_UNIT', 'km', NOW(), NOW()), +('PS_STORES_DISPLAY_CMS', 0, NOW(), NOW()), +('PS_STORES_DISPLAY_FOOTER', 0, NOW(), NOW()), +('PS_STORES_SIMPLIFIED', 0, NOW(), NOW()), +('PS_STATSDATA_CUSTOMER_PAGESVIEWS', 1, NOW(), NOW()), +('PS_STATSDATA_PAGESVIEWS', 1, NOW(), NOW()), +('PS_STATSDATA_PLUGINS', 1, NOW(), NOW()) + +INSERT INTO `PREFIX_configuration` (`name`, `value`, `date_add`, `date_upd`) VALUES ('PS_CONDITIONS_CMS_ID', IFNULL((SELECT `id_cms` FROM `PREFIX_cms` WHERE `id_cms` = 3), 0), NOW(), NOW()) + +CREATE TEMPORARY TABLE `PREFIX_configuration_tmp` ( + `value` text +) + +SET @defaultOOS = (SELECT value FROM `PREFIX_configuration` WHERE name = 'PS_ORDER_OUT_OF_STOCK') + +UPDATE `PREFIX_product` p SET `cache_default_attribute` = 0 WHERE `id_product` NOT IN (SELECT `id_product` FROM `PREFIX_product_attribute`) + +INSERT INTO `PREFIX_hook` (`name`, `title`, `description`, `position`) VALUES ('processCarrier', 'Carrier Process', NULL, 0) + +INSERT INTO `PREFIX_stock_mvt_reason_lang` (`id_stock_mvt_reason`, `id_lang`, `name`) VALUES +(1, 1, 'Order'), +(1, 2, 'Commande'), +(2, 1, 'Missing Stock Movement'), +(2, 2, 'Mouvement de stock manquant'), +(3, 1, 'Restocking'), +(3, 2, 'Réassort') + +INSERT INTO `PREFIX_meta_lang` (`id_lang`, `id_meta`, `title`, `url_rewrite`) VALUES +(1, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Authentication', 'authentication'), +(2, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Authentification', 'authentification'), +(3, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Autenticación', 'autenticacion') + +LOCK TABLES `admin_assert` WRITE + +UNLOCK TABLES + +DROP TABLE IF EXISTS `admin_role` + +SELECT * FROM +-- This is another comment +MyTable # One final comment +/* This is a block comment +*/ WHERE 1 = 2; + +SELECT -- This is a test + +SELECT Test FROM Test WHERE +( + MyColumn = 1 )) AND ((( SomeOtherColumn = 2); + +SELECT * LIMIT 1; SELECT a,b,c,d FROM e LIMIT 1, 2; SELECT 1,2,3 WHERE a in (1,2,3,4,5) and b=5; + +SELECT count - 50 +WHERE a-50 = b +WHERE 1 and - 50 +WHERE -50 = a +WHERE a = -50 +WHERE 1 /*test*/ - 50 +WHERE 1 and -50; + +SELECT @ and b; + +SELECT @"weird variable name"; + +SELECT "no closing quote diff --git a/vendor/psr/cache/CHANGELOG.md b/vendor/psr/cache/CHANGELOG.md new file mode 100644 index 0000000..58ddab0 --- /dev/null +++ b/vendor/psr/cache/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 1.0.1 - 2016-08-06 + +### Fixed + +- Make spacing consistent in phpdoc annotations php-fig/cache#9 - chalasr +- Fix grammar in phpdoc annotations php-fig/cache#10 - chalasr +- Be more specific in docblocks that `getItems()` and `deleteItems()` take an array of strings (`string[]`) compared to just `array` php-fig/cache#8 - GrahamCampbell +- For `expiresAt()` and `expiresAfter()` in CacheItemInterface fix docblock to specify null as a valid parameters as well as an implementation of DateTimeInterface php-fig/cache#7 - GrahamCampbell + +## 1.0.0 - 2015-12-11 + +Initial stable release; reflects accepted PSR-6 specification diff --git a/vendor/psr/cache/LICENSE.txt b/vendor/psr/cache/LICENSE.txt new file mode 100644 index 0000000..b1c2c97 --- /dev/null +++ b/vendor/psr/cache/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2015 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/psr/cache/README.md b/vendor/psr/cache/README.md new file mode 100644 index 0000000..c8706ce --- /dev/null +++ b/vendor/psr/cache/README.md @@ -0,0 +1,9 @@ +PSR Cache +========= + +This repository holds all interfaces defined by +[PSR-6](http://www.php-fig.org/psr/psr-6/). + +Note that this is not a Cache implementation of its own. It is merely an +interface that describes a Cache implementation. See the specification for more +details. diff --git a/vendor/psr/cache/composer.json b/vendor/psr/cache/composer.json new file mode 100644 index 0000000..e828fec --- /dev/null +++ b/vendor/psr/cache/composer.json @@ -0,0 +1,25 @@ +{ + "name": "psr/cache", + "description": "Common interface for caching libraries", + "keywords": ["psr", "psr-6", "cache"], + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/vendor/psr/cache/src/CacheException.php b/vendor/psr/cache/src/CacheException.php new file mode 100644 index 0000000..e27f22f --- /dev/null +++ b/vendor/psr/cache/src/CacheException.php @@ -0,0 +1,10 @@ +=5.3.0" + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/vendor/psr/container/src/ContainerExceptionInterface.php b/vendor/psr/container/src/ContainerExceptionInterface.php new file mode 100644 index 0000000..d35c6b4 --- /dev/null +++ b/vendor/psr/container/src/ContainerExceptionInterface.php @@ -0,0 +1,13 @@ +=7.2.0" + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/vendor/psr/event-dispatcher/src/EventDispatcherInterface.php b/vendor/psr/event-dispatcher/src/EventDispatcherInterface.php new file mode 100644 index 0000000..4306fa9 --- /dev/null +++ b/vendor/psr/event-dispatcher/src/EventDispatcherInterface.php @@ -0,0 +1,21 @@ +log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function alert($message, array $context = array()) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function critical($message, array $context = array()) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function error($message, array $context = array()) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function warning($message, array $context = array()) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function notice($message, array $context = array()) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function info($message, array $context = array()) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function debug($message, array $context = array()) + { + $this->log(LogLevel::DEBUG, $message, $context); + } +} diff --git a/vendor/psr/log/Psr/Log/InvalidArgumentException.php b/vendor/psr/log/Psr/Log/InvalidArgumentException.php new file mode 100644 index 0000000..67f852d --- /dev/null +++ b/vendor/psr/log/Psr/Log/InvalidArgumentException.php @@ -0,0 +1,7 @@ +logger = $logger; + } +} diff --git a/vendor/psr/log/Psr/Log/LoggerInterface.php b/vendor/psr/log/Psr/Log/LoggerInterface.php new file mode 100644 index 0000000..e695046 --- /dev/null +++ b/vendor/psr/log/Psr/Log/LoggerInterface.php @@ -0,0 +1,125 @@ +log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function alert($message, array $context = array()) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function critical($message, array $context = array()) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function error($message, array $context = array()) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function warning($message, array $context = array()) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function notice($message, array $context = array()) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function info($message, array $context = array()) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function debug($message, array $context = array()) + { + $this->log(LogLevel::DEBUG, $message, $context); + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * + * @return void + * + * @throws \Psr\Log\InvalidArgumentException + */ + abstract public function log($level, $message, array $context = array()); +} diff --git a/vendor/psr/log/Psr/Log/NullLogger.php b/vendor/psr/log/Psr/Log/NullLogger.php new file mode 100644 index 0000000..c8f7293 --- /dev/null +++ b/vendor/psr/log/Psr/Log/NullLogger.php @@ -0,0 +1,30 @@ +logger) { }` + * blocks. + */ +class NullLogger extends AbstractLogger +{ + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * + * @return void + * + * @throws \Psr\Log\InvalidArgumentException + */ + public function log($level, $message, array $context = array()) + { + // noop + } +} diff --git a/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php b/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php new file mode 100644 index 0000000..9ecb6c4 --- /dev/null +++ b/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php @@ -0,0 +1,146 @@ + ". + * + * Example ->error('Foo') would yield "error Foo". + * + * @return string[] + */ + abstract public function getLogs(); + + public function testImplements() + { + $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger()); + } + + /** + * @dataProvider provideLevelsAndMessages + */ + public function testLogsAtAllLevels($level, $message) + { + $logger = $this->getLogger(); + $logger->{$level}($message, array('user' => 'Bob')); + $logger->log($level, $message, array('user' => 'Bob')); + + $expected = array( + $level.' message of level '.$level.' with context: Bob', + $level.' message of level '.$level.' with context: Bob', + ); + $this->assertEquals($expected, $this->getLogs()); + } + + public function provideLevelsAndMessages() + { + return array( + LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), + LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), + LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), + LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), + LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), + LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), + LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), + LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'), + ); + } + + /** + * @expectedException \Psr\Log\InvalidArgumentException + */ + public function testThrowsOnInvalidLevel() + { + $logger = $this->getLogger(); + $logger->log('invalid level', 'Foo'); + } + + public function testContextReplacement() + { + $logger = $this->getLogger(); + $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); + + $expected = array('info {Message {nothing} Bob Bar a}'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testObjectCastToString() + { + if (method_exists($this, 'createPartialMock')) { + $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString')); + } else { + $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString')); + } + $dummy->expects($this->once()) + ->method('__toString') + ->will($this->returnValue('DUMMY')); + + $this->getLogger()->warning($dummy); + + $expected = array('warning DUMMY'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testContextCanContainAnything() + { + $closed = fopen('php://memory', 'r'); + fclose($closed); + + $context = array( + 'bool' => true, + 'null' => null, + 'string' => 'Foo', + 'int' => 0, + 'float' => 0.5, + 'nested' => array('with object' => new DummyTest), + 'object' => new \DateTime, + 'resource' => fopen('php://memory', 'r'), + 'closed' => $closed, + ); + + $this->getLogger()->warning('Crazy context data', $context); + + $expected = array('warning Crazy context data'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testContextExceptionKeyCanBeExceptionOrOtherValues() + { + $logger = $this->getLogger(); + $logger->warning('Random message', array('exception' => 'oops')); + $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail'))); + + $expected = array( + 'warning Random message', + 'critical Uncaught Exception!' + ); + $this->assertEquals($expected, $this->getLogs()); + } +} + +class DummyTest +{ + public function __toString() + { + return 'DummyTest'; + } +} diff --git a/vendor/psr/log/Psr/Log/Test/TestLogger.php b/vendor/psr/log/Psr/Log/Test/TestLogger.php new file mode 100644 index 0000000..1be3230 --- /dev/null +++ b/vendor/psr/log/Psr/Log/Test/TestLogger.php @@ -0,0 +1,147 @@ + $level, + 'message' => $message, + 'context' => $context, + ]; + + $this->recordsByLevel[$record['level']][] = $record; + $this->records[] = $record; + } + + public function hasRecords($level) + { + return isset($this->recordsByLevel[$level]); + } + + public function hasRecord($record, $level) + { + if (is_string($record)) { + $record = ['message' => $record]; + } + return $this->hasRecordThatPasses(function ($rec) use ($record) { + if ($rec['message'] !== $record['message']) { + return false; + } + if (isset($record['context']) && $rec['context'] !== $record['context']) { + return false; + } + return true; + }, $level); + } + + public function hasRecordThatContains($message, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($message) { + return strpos($rec['message'], $message) !== false; + }, $level); + } + + public function hasRecordThatMatches($regex, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($regex) { + return preg_match($regex, $rec['message']) > 0; + }, $level); + } + + public function hasRecordThatPasses(callable $predicate, $level) + { + if (!isset($this->recordsByLevel[$level])) { + return false; + } + foreach ($this->recordsByLevel[$level] as $i => $rec) { + if (call_user_func($predicate, $rec, $i)) { + return true; + } + } + return false; + } + + public function __call($method, $args) + { + if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { + $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; + $level = strtolower($matches[2]); + if (method_exists($this, $genericMethod)) { + $args[] = $level; + return call_user_func_array([$this, $genericMethod], $args); + } + } + throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); + } + + public function reset() + { + $this->records = []; + $this->recordsByLevel = []; + } +} diff --git a/vendor/psr/log/README.md b/vendor/psr/log/README.md new file mode 100644 index 0000000..a9f20c4 --- /dev/null +++ b/vendor/psr/log/README.md @@ -0,0 +1,58 @@ +PSR Log +======= + +This repository holds all interfaces/classes/traits related to +[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md). + +Note that this is not a logger of its own. It is merely an interface that +describes a logger. See the specification for more details. + +Installation +------------ + +```bash +composer require psr/log +``` + +Usage +----- + +If you need a logger, you can use the interface like this: + +```php +logger = $logger; + } + + public function doSomething() + { + if ($this->logger) { + $this->logger->info('Doing work'); + } + + try { + $this->doSomethingElse(); + } catch (Exception $exception) { + $this->logger->error('Oh no!', array('exception' => $exception)); + } + + // do something useful + } +} +``` + +You can then pick one of the implementations of the interface to get a logger. + +If you want to implement the interface, you can require this package and +implement `Psr\Log\LoggerInterface` in your code. Please read the +[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) +for details. diff --git a/vendor/psr/log/composer.json b/vendor/psr/log/composer.json new file mode 100644 index 0000000..3f6d4ee --- /dev/null +++ b/vendor/psr/log/composer.json @@ -0,0 +1,26 @@ +{ + "name": "psr/log", + "description": "Common interface for logging libraries", + "keywords": ["psr", "psr-3", "log"], + "homepage": "https://github.com/php-fig/log", + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + } +} diff --git a/vendor/symfony/cache-contracts/.gitignore b/vendor/symfony/cache-contracts/.gitignore new file mode 100644 index 0000000..c49a5d8 --- /dev/null +++ b/vendor/symfony/cache-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/vendor/symfony/cache-contracts/CacheInterface.php b/vendor/symfony/cache-contracts/CacheInterface.php new file mode 100644 index 0000000..4b1686b --- /dev/null +++ b/vendor/symfony/cache-contracts/CacheInterface.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Cache; + +use Psr\Cache\CacheItemInterface; +use Psr\Cache\InvalidArgumentException; + +/** + * Covers most simple to advanced caching needs. + * + * @author Nicolas Grekas + */ +interface CacheInterface +{ + /** + * Fetches a value from the pool or computes it if not found. + * + * On cache misses, a callback is called that should return the missing value. + * This callback is given a PSR-6 CacheItemInterface instance corresponding to the + * requested key, that could be used e.g. for expiration control. It could also + * be an ItemInterface instance when its additional features are needed. + * + * @param string $key The key of the item to retrieve from the cache + * @param callable|CallbackInterface $callback Should return the computed value for the given key/item + * @param float|null $beta A float that, as it grows, controls the likeliness of triggering + * early expiration. 0 disables it, INF forces immediate expiration. + * The default (or providing null) is implementation dependent but should + * typically be 1.0, which should provide optimal stampede protection. + * See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration + * @param array &$metadata The metadata of the cached item {@see ItemInterface::getMetadata()} + * + * @return mixed The value corresponding to the provided key + * + * @throws InvalidArgumentException When $key is not valid or when $beta is negative + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null); + + /** + * Removes an item from the pool. + * + * @param string $key The key to delete + * + * @throws InvalidArgumentException When $key is not valid + * + * @return bool True if the item was successfully removed, false if there was any error + */ + public function delete(string $key): bool; +} diff --git a/vendor/symfony/cache-contracts/CacheTrait.php b/vendor/symfony/cache-contracts/CacheTrait.php new file mode 100644 index 0000000..355ea29 --- /dev/null +++ b/vendor/symfony/cache-contracts/CacheTrait.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Cache; + +use Psr\Cache\CacheItemPoolInterface; +use Psr\Cache\InvalidArgumentException; +use Psr\Log\LoggerInterface; + +/** + * An implementation of CacheInterface for PSR-6 CacheItemPoolInterface classes. + * + * @author Nicolas Grekas + */ +trait CacheTrait +{ + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + return $this->doGet($this, $key, $callback, $beta, $metadata); + } + + /** + * {@inheritdoc} + */ + public function delete(string $key): bool + { + return $this->deleteItem($key); + } + + private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null, LoggerInterface $logger = null) + { + if (0 > $beta = $beta ?? 1.0) { + throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', \get_class($this), $beta)) extends \InvalidArgumentException implements InvalidArgumentException { + }; + } + + $item = $pool->getItem($key); + $recompute = !$item->isHit() || INF === $beta; + $metadata = $item instanceof ItemInterface ? $item->getMetadata() : []; + + if (!$recompute && $metadata) { + $expiry = $metadata[ItemInterface::METADATA_EXPIRY] ?? false; + $ctime = $metadata[ItemInterface::METADATA_CTIME] ?? false; + + if ($recompute = $ctime && $expiry && $expiry <= ($now = microtime(true)) - $ctime / 1000 * $beta * log(random_int(1, PHP_INT_MAX) / PHP_INT_MAX)) { + // force applying defaultLifetime to expiry + $item->expiresAt(null); + $logger && $logger->info('Item "{key}" elected for early recomputation {delta}s before its expiration', [ + 'key' => $key, + 'delta' => sprintf('%.1f', $expiry - $now), + ]); + } + } + + if ($recompute) { + $save = true; + $item->set($callback($item, $save)); + if ($save) { + $pool->save($item); + } + } + + return $item->get(); + } +} diff --git a/vendor/symfony/cache-contracts/CallbackInterface.php b/vendor/symfony/cache-contracts/CallbackInterface.php new file mode 100644 index 0000000..7dae2aa --- /dev/null +++ b/vendor/symfony/cache-contracts/CallbackInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Cache; + +use Psr\Cache\CacheItemInterface; + +/** + * Computes and returns the cached value of an item. + * + * @author Nicolas Grekas + */ +interface CallbackInterface +{ + /** + * @param CacheItemInterface|ItemInterface $item The item to compute the value for + * @param bool &$save Should be set to false when the value should not be saved in the pool + * + * @return mixed The computed value for the passed item + */ + public function __invoke(CacheItemInterface $item, bool &$save); +} diff --git a/vendor/symfony/cache-contracts/ItemInterface.php b/vendor/symfony/cache-contracts/ItemInterface.php new file mode 100644 index 0000000..cbd7226 --- /dev/null +++ b/vendor/symfony/cache-contracts/ItemInterface.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Cache; + +use Psr\Cache\CacheException; +use Psr\Cache\CacheItemInterface; +use Psr\Cache\InvalidArgumentException; + +/** + * Augments PSR-6's CacheItemInterface with support for tags and metadata. + * + * @author Nicolas Grekas + */ +interface ItemInterface extends CacheItemInterface +{ + /** + * References the Unix timestamp stating when the item will expire. + */ + const METADATA_EXPIRY = 'expiry'; + + /** + * References the time the item took to be created, in milliseconds. + */ + const METADATA_CTIME = 'ctime'; + + /** + * References the list of tags that were assigned to the item, as string[]. + */ + const METADATA_TAGS = 'tags'; + + /** + * Reserved characters that cannot be used in a key or tag. + */ + const RESERVED_CHARACTERS = '{}()/\@:'; + + /** + * Adds a tag to a cache item. + * + * Tags are strings that follow the same validation rules as keys. + * + * @param string|string[] $tags A tag or array of tags + * + * @return $this + * + * @throws InvalidArgumentException When $tag is not valid + * @throws CacheException When the item comes from a pool that is not tag-aware + */ + public function tag($tags): self; + + /** + * Returns a list of metadata info that were saved alongside with the cached value. + * + * See ItemInterface::METADATA_* consts for keys potentially found in the returned array. + */ + public function getMetadata(): array; +} diff --git a/vendor/symfony/cache-contracts/LICENSE b/vendor/symfony/cache-contracts/LICENSE new file mode 100644 index 0000000..3f853aa --- /dev/null +++ b/vendor/symfony/cache-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/cache-contracts/README.md b/vendor/symfony/cache-contracts/README.md new file mode 100644 index 0000000..58c589e --- /dev/null +++ b/vendor/symfony/cache-contracts/README.md @@ -0,0 +1,9 @@ +Symfony Cache Contracts +======================= + +A set of abstractions extracted out of the Symfony components. + +Can be used to build on semantics that the Symfony components proved useful - and +that already have battle tested implementations. + +See https://github.com/symfony/contracts/blob/master/README.md for more information. diff --git a/vendor/symfony/cache-contracts/TagAwareCacheInterface.php b/vendor/symfony/cache-contracts/TagAwareCacheInterface.php new file mode 100644 index 0000000..7c4cf11 --- /dev/null +++ b/vendor/symfony/cache-contracts/TagAwareCacheInterface.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Cache; + +use Psr\Cache\InvalidArgumentException; + +/** + * Allows invalidating cached items using tags. + * + * @author Nicolas Grekas + */ +interface TagAwareCacheInterface extends CacheInterface +{ + /** + * Invalidates cached items using tags. + * + * When implemented on a PSR-6 pool, invalidation should not apply + * to deferred items. Instead, they should be committed as usual. + * This allows replacing old tagged values by new ones without + * race conditions. + * + * @param string[] $tags An array of tags to invalidate + * + * @return bool True on success + * + * @throws InvalidArgumentException When $tags is not valid + */ + public function invalidateTags(array $tags); +} diff --git a/vendor/symfony/cache-contracts/composer.json b/vendor/symfony/cache-contracts/composer.json new file mode 100644 index 0000000..c9cf8b5 --- /dev/null +++ b/vendor/symfony/cache-contracts/composer.json @@ -0,0 +1,34 @@ +{ + "name": "symfony/cache-contracts", + "type": "library", + "description": "Generic abstractions related to caching", + "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "psr/cache": "^1.0" + }, + "suggest": { + "symfony/cache-implementation": "" + }, + "autoload": { + "psr-4": { "Symfony\\Contracts\\Cache\\": "" } + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + } +} diff --git a/vendor/symfony/cache/.gitattributes b/vendor/symfony/cache/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/cache/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/cache/Adapter/AbstractAdapter.php b/vendor/symfony/cache/Adapter/AbstractAdapter.php new file mode 100644 index 0000000..d12d8f6 --- /dev/null +++ b/vendor/symfony/cache/Adapter/AbstractAdapter.php @@ -0,0 +1,195 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\AbstractAdapterTrait; +use Symfony\Component\Cache\Traits\ContractsTrait; +use Symfony\Contracts\Cache\CacheInterface; + +/** + * @author Nicolas Grekas + */ +abstract class AbstractAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface +{ + /** + * @internal + */ + protected const NS_SEPARATOR = ':'; + + use AbstractAdapterTrait; + use ContractsTrait; + + private static $apcuSupported; + private static $phpFilesSupported; + + protected function __construct(string $namespace = '', int $defaultLifetime = 0) + { + $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).static::NS_SEPARATOR; + if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) { + throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")', $this->maxIdLength - 24, \strlen($namespace), $namespace)); + } + $this->createCacheItem = \Closure::bind( + static function ($key, $value, $isHit) use ($defaultLifetime) { + $item = new CacheItem(); + $item->key = $key; + $item->value = $v = $value; + $item->isHit = $isHit; + $item->defaultLifetime = $defaultLifetime; + // Detect wrapped values that encode for their expiry and creation duration + // For compactness, these values are packed in the key of an array using + // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F + if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = key($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) { + $item->value = $v[$k]; + $v = unpack('Ve/Nc', substr($k, 1, -1)); + $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; + $item->metadata[CacheItem::METADATA_CTIME] = $v['c']; + } + + return $item; + }, + null, + CacheItem::class + ); + $getId = \Closure::fromCallable([$this, 'getId']); + $this->mergeByLifetime = \Closure::bind( + static function ($deferred, $namespace, &$expiredIds) use ($getId) { + $byLifetime = []; + $now = microtime(true); + $expiredIds = []; + + foreach ($deferred as $key => $item) { + $key = (string) $key; + if (null === $item->expiry) { + $ttl = 0 < $item->defaultLifetime ? $item->defaultLifetime : 0; + } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) { + $expiredIds[] = $getId($key); + continue; + } + if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) { + unset($metadata[CacheItem::METADATA_TAGS]); + } + // For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators + $byLifetime[$ttl][$getId($key)] = $metadata ? ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item->value] : $item->value; + } + + return $byLifetime; + }, + null, + CacheItem::class + ); + } + + /** + * Returns the best possible adapter that your runtime supports. + * + * Using ApcuAdapter makes system caches compatible with read-only filesystems. + * + * @return AdapterInterface + */ + public static function createSystemCache(string $namespace, int $defaultLifetime, string $version, string $directory, LoggerInterface $logger = null) + { + $opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory, true); + if (null !== $logger) { + $opcache->setLogger($logger); + } + + if (!self::$apcuSupported = self::$apcuSupported ?? ApcuAdapter::isSupported()) { + return $opcache; + } + + $apcu = new ApcuAdapter($namespace, $defaultLifetime / 5, $version); + if ('cli' === \PHP_SAPI && !filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN)) { + $apcu->setLogger(new NullLogger()); + } elseif (null !== $logger) { + $apcu->setLogger($logger); + } + + return new ChainAdapter([$apcu, $opcache]); + } + + public static function createConnection(string $dsn, array $options = []) + { + if (0 === strpos($dsn, 'redis:') || 0 === strpos($dsn, 'rediss:')) { + return RedisAdapter::createConnection($dsn, $options); + } + if (0 === strpos($dsn, 'memcached:')) { + return MemcachedAdapter::createConnection($dsn, $options); + } + + throw new InvalidArgumentException(sprintf('Unsupported DSN: %s.', $dsn)); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function commit() + { + $ok = true; + $byLifetime = $this->mergeByLifetime; + $byLifetime = $byLifetime($this->deferred, $this->namespace, $expiredIds); + $retry = $this->deferred = []; + + if ($expiredIds) { + $this->doDelete($expiredIds); + } + foreach ($byLifetime as $lifetime => $values) { + try { + $e = $this->doSave($values, $lifetime); + } catch (\Exception $e) { + } + if (true === $e || [] === $e) { + continue; + } + if (\is_array($e) || 1 === \count($values)) { + foreach (\is_array($e) ? $e : array_keys($values) as $id) { + $ok = false; + $v = $values[$id]; + $type = \is_object($v) ? \get_class($v) : \gettype($v); + $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]); + } + } else { + foreach ($values as $id => $v) { + $retry[$lifetime][] = $id; + } + } + } + + // When bulk-save failed, retry each item individually + foreach ($retry as $lifetime => $ids) { + foreach ($ids as $id) { + try { + $v = $byLifetime[$lifetime][$id]; + $e = $this->doSave([$id => $v], $lifetime); + } catch (\Exception $e) { + } + if (true === $e || [] === $e) { + continue; + } + $ok = false; + $type = \is_object($v) ? \get_class($v) : \gettype($v); + $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]); + } + } + + return $ok; + } +} diff --git a/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php b/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php new file mode 100644 index 0000000..a1d2440 --- /dev/null +++ b/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php @@ -0,0 +1,323 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Log\LoggerAwareInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\AbstractAdapterTrait; +use Symfony\Component\Cache\Traits\ContractsTrait; +use Symfony\Contracts\Cache\TagAwareCacheInterface; + +/** + * Abstract for native TagAware adapters. + * + * To keep info on tags, the tags are both serialized as part of cache value and provided as tag ids + * to Adapters on operations when needed for storage to doSave(), doDelete() & doInvalidate(). + * + * @author Nicolas Grekas + * @author André Rømcke + * + * @internal + */ +abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, LoggerAwareInterface, ResettableInterface +{ + use AbstractAdapterTrait; + use ContractsTrait; + + private const TAGS_PREFIX = "\0tags\0"; + + protected function __construct(string $namespace = '', int $defaultLifetime = 0) + { + $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':'; + if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) { + throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")', $this->maxIdLength - 24, \strlen($namespace), $namespace)); + } + $this->createCacheItem = \Closure::bind( + static function ($key, $value, $isHit) use ($defaultLifetime) { + $item = new CacheItem(); + $item->key = $key; + $item->defaultLifetime = $defaultLifetime; + $item->isTaggable = true; + // If structure does not match what we expect return item as is (no value and not a hit) + if (!\is_array($value) || !\array_key_exists('value', $value)) { + return $item; + } + $item->isHit = $isHit; + // Extract value, tags and meta data from the cache value + $item->value = $value['value']; + $item->metadata[CacheItem::METADATA_TAGS] = $value['tags'] ?? []; + if (isset($value['meta'])) { + // For compactness these values are packed, & expiry is offset to reduce size + $v = unpack('Ve/Nc', $value['meta']); + $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; + $item->metadata[CacheItem::METADATA_CTIME] = $v['c']; + } + + return $item; + }, + null, + CacheItem::class + ); + $getId = \Closure::fromCallable([$this, 'getId']); + $tagPrefix = self::TAGS_PREFIX; + $this->mergeByLifetime = \Closure::bind( + static function ($deferred, &$expiredIds) use ($getId, $tagPrefix) { + $byLifetime = []; + $now = microtime(true); + $expiredIds = []; + + foreach ($deferred as $key => $item) { + $key = (string) $key; + if (null === $item->expiry) { + $ttl = 0 < $item->defaultLifetime ? $item->defaultLifetime : 0; + } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) { + $expiredIds[] = $getId($key); + continue; + } + // Store Value and Tags on the cache value + if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) { + $value = ['value' => $item->value, 'tags' => $metadata[CacheItem::METADATA_TAGS]]; + unset($metadata[CacheItem::METADATA_TAGS]); + } else { + $value = ['value' => $item->value, 'tags' => []]; + } + + if ($metadata) { + // For compactness, expiry and creation duration are packed, using magic numbers as separators + $value['meta'] = pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME]); + } + + // Extract tag changes, these should be removed from values in doSave() + $value['tag-operations'] = ['add' => [], 'remove' => []]; + $oldTags = $item->metadata[CacheItem::METADATA_TAGS] ?? []; + foreach (array_diff($value['tags'], $oldTags) as $addedTag) { + $value['tag-operations']['add'][] = $getId($tagPrefix.$addedTag); + } + foreach (array_diff($oldTags, $value['tags']) as $removedTag) { + $value['tag-operations']['remove'][] = $getId($tagPrefix.$removedTag); + } + + $byLifetime[$ttl][$getId($key)] = $value; + } + + return $byLifetime; + }, + null, + CacheItem::class + ); + } + + /** + * Persists several cache items immediately. + * + * @param array $values The values to cache, indexed by their cache identifier + * @param int $lifetime The lifetime of the cached values, 0 for persisting until manual cleaning + * @param array[] $addTagData Hash where key is tag id, and array value is list of cache id's to add to tag + * @param array[] $removeTagData Hash where key is tag id, and array value is list of cache id's to remove to tag + * + * @return array The identifiers that failed to be cached or a boolean stating if caching succeeded or not + */ + abstract protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array; + + /** + * Removes multiple items from the pool and their corresponding tags. + * + * @param array $ids An array of identifiers that should be removed from the pool + * + * @return bool True if the items were successfully removed, false otherwise + */ + abstract protected function doDelete(array $ids); + + /** + * Removes relations between tags and deleted items. + * + * @param array $tagData Array of tag => key identifiers that should be removed from the pool + */ + abstract protected function doDeleteTagRelations(array $tagData): bool; + + /** + * Invalidates cached items using tags. + * + * @param string[] $tagIds An array of tags to invalidate, key is tag and value is tag id + * + * @return bool True on success + */ + abstract protected function doInvalidate(array $tagIds): bool; + + /** + * Delete items and yields the tags they were bound to. + */ + protected function doDeleteYieldTags(array $ids): iterable + { + foreach ($this->doFetch($ids) as $id => $value) { + yield $id => \is_array($value) && \is_array($value['tags'] ?? null) ? $value['tags'] : []; + } + + $this->doDelete($ids); + } + + /** + * {@inheritdoc} + */ + public function commit(): bool + { + $ok = true; + $byLifetime = $this->mergeByLifetime; + $byLifetime = $byLifetime($this->deferred, $expiredIds); + $retry = $this->deferred = []; + + if ($expiredIds) { + // Tags are not cleaned up in this case, however that is done on invalidateTags(). + $this->doDelete($expiredIds); + } + foreach ($byLifetime as $lifetime => $values) { + try { + $values = $this->extractTagData($values, $addTagData, $removeTagData); + $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData); + } catch (\Exception $e) { + } + if (true === $e || [] === $e) { + continue; + } + if (\is_array($e) || 1 === \count($values)) { + foreach (\is_array($e) ? $e : array_keys($values) as $id) { + $ok = false; + $v = $values[$id]; + $type = \is_object($v) ? \get_class($v) : \gettype($v); + $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]); + } + } else { + foreach ($values as $id => $v) { + $retry[$lifetime][] = $id; + } + } + } + + // When bulk-save failed, retry each item individually + foreach ($retry as $lifetime => $ids) { + foreach ($ids as $id) { + try { + $v = $byLifetime[$lifetime][$id]; + $values = $this->extractTagData([$id => $v], $addTagData, $removeTagData); + $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData); + } catch (\Exception $e) { + } + if (true === $e || [] === $e) { + continue; + } + $ok = false; + $type = \is_object($v) ? \get_class($v) : \gettype($v); + $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]); + } + } + + return $ok; + } + + /** + * {@inheritdoc} + */ + public function deleteItems(array $keys): bool + { + if (!$keys) { + return true; + } + + $ok = true; + $ids = []; + $tagData = []; + + foreach ($keys as $key) { + $ids[$key] = $this->getId($key); + unset($this->deferred[$key]); + } + + try { + foreach ($this->doDeleteYieldTags(array_values($ids)) as $id => $tags) { + foreach ($tags as $tag) { + $tagData[$this->getId(self::TAGS_PREFIX.$tag)][] = $id; + } + } + } catch (\Exception $e) { + $ok = false; + } + + try { + if ((!$tagData || $this->doDeleteTagRelations($tagData)) && $ok) { + return true; + } + } catch (\Exception $e) { + } + + // When bulk-delete failed, retry each item individually + foreach ($ids as $key => $id) { + try { + $e = null; + if ($this->doDelete([$id])) { + continue; + } + } catch (\Exception $e) { + } + $message = 'Failed to delete key "{key}"'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e]); + $ok = false; + } + + return $ok; + } + + /** + * {@inheritdoc} + */ + public function invalidateTags(array $tags) + { + if (empty($tags)) { + return false; + } + + $tagIds = []; + foreach (array_unique($tags) as $tag) { + $tagIds[] = $this->getId(self::TAGS_PREFIX.$tag); + } + + if ($this->doInvalidate($tagIds)) { + return true; + } + + return false; + } + + /** + * Extracts tags operation data from $values set in mergeByLifetime, and returns values without it. + */ + private function extractTagData(array $values, ?array &$addTagData, ?array &$removeTagData): array + { + $addTagData = $removeTagData = []; + foreach ($values as $id => $value) { + foreach ($value['tag-operations']['add'] as $tag => $tagId) { + $addTagData[$tagId][] = $id; + } + + foreach ($value['tag-operations']['remove'] as $tag => $tagId) { + $removeTagData[$tagId][] = $id; + } + + unset($values[$id]['tag-operations']); + } + + return $values; + } +} diff --git a/vendor/symfony/cache/Adapter/AdapterInterface.php b/vendor/symfony/cache/Adapter/AdapterInterface.php new file mode 100644 index 0000000..99c5cd1 --- /dev/null +++ b/vendor/symfony/cache/Adapter/AdapterInterface.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Cache\CacheItem; + +/** + * Interface for adapters managing instances of Symfony's CacheItem. + * + * @author Kévin Dunglas + */ +interface AdapterInterface extends CacheItemPoolInterface +{ + /** + * {@inheritdoc} + * + * @return CacheItem + */ + public function getItem($key); + + /** + * {@inheritdoc} + * + * @return \Traversable|CacheItem[] + */ + public function getItems(array $keys = []); + + /** + * {@inheritdoc} + * + * @return bool + */ + public function clear(string $prefix = ''); +} diff --git a/vendor/symfony/cache/Adapter/ApcuAdapter.php b/vendor/symfony/cache/Adapter/ApcuAdapter.php new file mode 100644 index 0000000..62ba4d9 --- /dev/null +++ b/vendor/symfony/cache/Adapter/ApcuAdapter.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\CacheException; + +/** + * @author Nicolas Grekas + */ +class ApcuAdapter extends AbstractAdapter +{ + /** + * @throws CacheException if APCu is not enabled + */ + public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null) + { + if (!static::isSupported()) { + throw new CacheException('APCu is not enabled'); + } + if ('cli' === \PHP_SAPI) { + ini_set('apc.use_request_time', 0); + } + parent::__construct($namespace, $defaultLifetime); + + if (null !== $version) { + CacheItem::validateKey($version); + + if (!apcu_exists($version.'@'.$namespace)) { + $this->doClear($namespace); + apcu_add($version.'@'.$namespace, null); + } + } + } + + public static function isSupported() + { + return \function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN); + } + + /** + * {@inheritdoc} + */ + protected function doFetch(array $ids) + { + $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); + try { + $values = []; + foreach (apcu_fetch($ids, $ok) ?: [] as $k => $v) { + if (null !== $v || $ok) { + $values[$k] = $v; + } + } + + return $values; + } catch (\Error $e) { + throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); + } finally { + ini_set('unserialize_callback_func', $unserializeCallbackHandler); + } + } + + /** + * {@inheritdoc} + */ + protected function doHave(string $id) + { + return apcu_exists($id); + } + + /** + * {@inheritdoc} + */ + protected function doClear(string $namespace) + { + return isset($namespace[0]) && class_exists('APCuIterator', false) && ('cli' !== \PHP_SAPI || filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN)) + ? apcu_delete(new \APCuIterator(sprintf('/^%s/', preg_quote($namespace, '/')), APC_ITER_KEY)) + : apcu_clear_cache(); + } + + /** + * {@inheritdoc} + */ + protected function doDelete(array $ids) + { + foreach ($ids as $id) { + apcu_delete($id); + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doSave(array $values, int $lifetime) + { + try { + if (false === $failures = apcu_store($values, null, $lifetime)) { + $failures = $values; + } + + return array_keys($failures); + } catch (\Throwable $e) { + if (1 === \count($values)) { + // Workaround https://github.com/krakjoe/apcu/issues/170 + apcu_delete(key($values)); + } + + throw $e; + } + } +} diff --git a/vendor/symfony/cache/Adapter/ArrayAdapter.php b/vendor/symfony/cache/Adapter/ArrayAdapter.php new file mode 100644 index 0000000..05920d0 --- /dev/null +++ b/vendor/symfony/cache/Adapter/ArrayAdapter.php @@ -0,0 +1,324 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Contracts\Cache\CacheInterface; + +/** + * @author Nicolas Grekas + */ +class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface +{ + use LoggerAwareTrait; + + private $storeSerialized; + private $values = []; + private $expiries = []; + private $createCacheItem; + + /** + * @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise + */ + public function __construct(int $defaultLifetime = 0, bool $storeSerialized = true) + { + $this->storeSerialized = $storeSerialized; + $this->createCacheItem = \Closure::bind( + static function ($key, $value, $isHit) use ($defaultLifetime) { + $item = new CacheItem(); + $item->key = $key; + $item->value = $value; + $item->isHit = $isHit; + $item->defaultLifetime = $defaultLifetime; + + return $item; + }, + null, + CacheItem::class + ); + } + + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + $item = $this->getItem($key); + $metadata = $item->getMetadata(); + + // ArrayAdapter works in memory, we don't care about stampede protection + if (INF === $beta || !$item->isHit()) { + $save = true; + $this->save($item->set($callback($item, $save))); + } + + return $item->get(); + } + + /** + * {@inheritdoc} + */ + public function delete(string $key): bool + { + return $this->deleteItem($key); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function hasItem($key) + { + if (\is_string($key) && isset($this->expiries[$key]) && $this->expiries[$key] > microtime(true)) { + return true; + } + CacheItem::validateKey($key); + + return isset($this->expiries[$key]) && !$this->deleteItem($key); + } + + /** + * {@inheritdoc} + */ + public function getItem($key) + { + if (!$isHit = $this->hasItem($key)) { + $this->values[$key] = $value = null; + } else { + $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key]; + } + $f = $this->createCacheItem; + + return $f($key, $value, $isHit); + } + + /** + * {@inheritdoc} + */ + public function getItems(array $keys = []) + { + foreach ($keys as $key) { + if (!\is_string($key) || !isset($this->expiries[$key])) { + CacheItem::validateKey($key); + } + } + + return $this->generateItems($keys, microtime(true), $this->createCacheItem); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItem($key) + { + if (!\is_string($key) || !isset($this->expiries[$key])) { + CacheItem::validateKey($key); + } + unset($this->values[$key], $this->expiries[$key]); + + return true; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItems(array $keys) + { + foreach ($keys as $key) { + $this->deleteItem($key); + } + + return true; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function save(CacheItemInterface $item) + { + if (!$item instanceof CacheItem) { + return false; + } + $item = (array) $item; + $key = $item["\0*\0key"]; + $value = $item["\0*\0value"]; + $expiry = $item["\0*\0expiry"]; + + if (null !== $expiry && $expiry <= microtime(true)) { + $this->deleteItem($key); + + return true; + } + if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) { + return false; + } + if (null === $expiry && 0 < $item["\0*\0defaultLifetime"]) { + $expiry = microtime(true) + $item["\0*\0defaultLifetime"]; + } + + $this->values[$key] = $value; + $this->expiries[$key] = null !== $expiry ? $expiry : PHP_INT_MAX; + + return true; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function saveDeferred(CacheItemInterface $item) + { + return $this->save($item); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function commit() + { + return true; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function clear(string $prefix = '') + { + if ('' !== $prefix) { + foreach ($this->values as $key => $value) { + if (0 === strpos($key, $prefix)) { + unset($this->values[$key], $this->expiries[$key]); + } + } + } else { + $this->values = $this->expiries = []; + } + + return true; + } + + /** + * Returns all cached values, with cache miss as null. + * + * @return array + */ + public function getValues() + { + if (!$this->storeSerialized) { + return $this->values; + } + + $values = $this->values; + foreach ($values as $k => $v) { + if (null === $v || 'N;' === $v) { + continue; + } + if (!\is_string($v) || !isset($v[2]) || ':' !== $v[1]) { + $values[$k] = serialize($v); + } + } + + return $values; + } + + /** + * {@inheritdoc} + */ + public function reset() + { + $this->clear(); + } + + private function generateItems(array $keys, $now, $f) + { + foreach ($keys as $i => $key) { + if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) { + $this->values[$key] = $value = null; + } else { + $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key]; + } + unset($keys[$i]); + + yield $key => $f($key, $value, $isHit); + } + + foreach ($keys as $key) { + yield $key => $f($key, null, false); + } + } + + private function freeze($value, $key) + { + if (null === $value) { + return 'N;'; + } + if (\is_string($value)) { + // Serialize strings if they could be confused with serialized objects or arrays + if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) { + return serialize($value); + } + } elseif (!is_scalar($value)) { + try { + $serialized = serialize($value); + } catch (\Exception $e) { + $type = \is_object($value) ? \get_class($value) : \gettype($value); + $message = sprintf('Failed to save key "{key}" of type %s: %s', $type, $e->getMessage()); + CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e]); + + return; + } + // Keep value serialized if it contains any objects or any internal references + if ('C' === $serialized[0] || 'O' === $serialized[0] || preg_match('/;[OCRr]:[1-9]/', $serialized)) { + return $serialized; + } + } + + return $value; + } + + private function unfreeze(string $key, bool &$isHit) + { + if ('N;' === $value = $this->values[$key]) { + return null; + } + if (\is_string($value) && isset($value[2]) && ':' === $value[1]) { + try { + $value = unserialize($value); + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to unserialize key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e]); + $value = false; + } + if (false === $value) { + $this->values[$key] = $value = null; + $isHit = false; + } + } + + return $value; + } +} diff --git a/vendor/symfony/cache/Adapter/ChainAdapter.php b/vendor/symfony/cache/Adapter/ChainAdapter.php new file mode 100644 index 0000000..a2fc8e7 --- /dev/null +++ b/vendor/symfony/cache/Adapter/ChainAdapter.php @@ -0,0 +1,329 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ContractsTrait; +use Symfony\Contracts\Cache\CacheInterface; +use Symfony\Contracts\Service\ResetInterface; + +/** + * Chains several adapters together. + * + * Cached items are fetched from the first adapter having them in its data store. + * They are saved and deleted in all adapters at once. + * + * @author Kévin Dunglas + */ +class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface +{ + use ContractsTrait; + + private $adapters = []; + private $adapterCount; + private $syncItem; + + /** + * @param CacheItemPoolInterface[] $adapters The ordered list of adapters used to fetch cached items + * @param int $defaultLifetime The default lifetime of items propagated from lower adapters to upper ones + */ + public function __construct(array $adapters, int $defaultLifetime = 0) + { + if (!$adapters) { + throw new InvalidArgumentException('At least one adapter must be specified.'); + } + + foreach ($adapters as $adapter) { + if (!$adapter instanceof CacheItemPoolInterface) { + throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', \get_class($adapter), CacheItemPoolInterface::class)); + } + + if ($adapter instanceof AdapterInterface) { + $this->adapters[] = $adapter; + } else { + $this->adapters[] = new ProxyAdapter($adapter); + } + } + $this->adapterCount = \count($this->adapters); + + $this->syncItem = \Closure::bind( + static function ($sourceItem, $item, $sourceMetadata = null) use ($defaultLifetime) { + $sourceItem->isTaggable = false; + $sourceMetadata = $sourceMetadata ?? $sourceItem->metadata; + unset($sourceMetadata[CacheItem::METADATA_TAGS]); + + $item->value = $sourceItem->value; + $item->expiry = $sourceMetadata[CacheItem::METADATA_EXPIRY] ?? $sourceItem->expiry; + $item->isHit = $sourceItem->isHit; + $item->metadata = $item->newMetadata = $sourceItem->metadata = $sourceMetadata; + + if (0 < $sourceItem->defaultLifetime && $sourceItem->defaultLifetime < $defaultLifetime) { + $defaultLifetime = $sourceItem->defaultLifetime; + } + if (0 < $defaultLifetime && ($item->defaultLifetime <= 0 || $defaultLifetime < $item->defaultLifetime)) { + $item->defaultLifetime = $defaultLifetime; + } + + return $item; + }, + null, + CacheItem::class + ); + } + + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + $lastItem = null; + $i = 0; + $wrap = function (CacheItem $item = null) use ($key, $callback, $beta, &$wrap, &$i, &$lastItem, &$metadata) { + $adapter = $this->adapters[$i]; + if (isset($this->adapters[++$i])) { + $callback = $wrap; + $beta = INF === $beta ? INF : 0; + } + if ($adapter instanceof CacheInterface) { + $value = $adapter->get($key, $callback, $beta, $metadata); + } else { + $value = $this->doGet($adapter, $key, $callback, $beta, $metadata); + } + if (null !== $item) { + ($this->syncItem)($lastItem = $lastItem ?? $item, $item, $metadata); + } + + return $value; + }; + + return $wrap(); + } + + /** + * {@inheritdoc} + */ + public function getItem($key) + { + $syncItem = $this->syncItem; + $misses = []; + + foreach ($this->adapters as $i => $adapter) { + $item = $adapter->getItem($key); + + if ($item->isHit()) { + while (0 <= --$i) { + $this->adapters[$i]->save($syncItem($item, $misses[$i])); + } + + return $item; + } + + $misses[$i] = $item; + } + + return $item; + } + + /** + * {@inheritdoc} + */ + public function getItems(array $keys = []) + { + return $this->generateItems($this->adapters[0]->getItems($keys), 0); + } + + private function generateItems(iterable $items, int $adapterIndex) + { + $missing = []; + $misses = []; + $nextAdapterIndex = $adapterIndex + 1; + $nextAdapter = isset($this->adapters[$nextAdapterIndex]) ? $this->adapters[$nextAdapterIndex] : null; + + foreach ($items as $k => $item) { + if (!$nextAdapter || $item->isHit()) { + yield $k => $item; + } else { + $missing[] = $k; + $misses[$k] = $item; + } + } + + if ($missing) { + $syncItem = $this->syncItem; + $adapter = $this->adapters[$adapterIndex]; + $items = $this->generateItems($nextAdapter->getItems($missing), $nextAdapterIndex); + + foreach ($items as $k => $item) { + if ($item->isHit()) { + $adapter->save($syncItem($item, $misses[$k])); + } + + yield $k => $item; + } + } + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function hasItem($key) + { + foreach ($this->adapters as $adapter) { + if ($adapter->hasItem($key)) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function clear(string $prefix = '') + { + $cleared = true; + $i = $this->adapterCount; + + while ($i--) { + if ($this->adapters[$i] instanceof AdapterInterface) { + $cleared = $this->adapters[$i]->clear($prefix) && $cleared; + } else { + $cleared = $this->adapters[$i]->clear() && $cleared; + } + } + + return $cleared; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItem($key) + { + $deleted = true; + $i = $this->adapterCount; + + while ($i--) { + $deleted = $this->adapters[$i]->deleteItem($key) && $deleted; + } + + return $deleted; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItems(array $keys) + { + $deleted = true; + $i = $this->adapterCount; + + while ($i--) { + $deleted = $this->adapters[$i]->deleteItems($keys) && $deleted; + } + + return $deleted; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function save(CacheItemInterface $item) + { + $saved = true; + $i = $this->adapterCount; + + while ($i--) { + $saved = $this->adapters[$i]->save($item) && $saved; + } + + return $saved; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function saveDeferred(CacheItemInterface $item) + { + $saved = true; + $i = $this->adapterCount; + + while ($i--) { + $saved = $this->adapters[$i]->saveDeferred($item) && $saved; + } + + return $saved; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function commit() + { + $committed = true; + $i = $this->adapterCount; + + while ($i--) { + $committed = $this->adapters[$i]->commit() && $committed; + } + + return $committed; + } + + /** + * {@inheritdoc} + */ + public function prune() + { + $pruned = true; + + foreach ($this->adapters as $adapter) { + if ($adapter instanceof PruneableInterface) { + $pruned = $adapter->prune() && $pruned; + } + } + + return $pruned; + } + + /** + * {@inheritdoc} + */ + public function reset() + { + foreach ($this->adapters as $adapter) { + if ($adapter instanceof ResetInterface) { + $adapter->reset(); + } + } + } +} diff --git a/vendor/symfony/cache/Adapter/DoctrineAdapter.php b/vendor/symfony/cache/Adapter/DoctrineAdapter.php new file mode 100644 index 0000000..55a36e1 --- /dev/null +++ b/vendor/symfony/cache/Adapter/DoctrineAdapter.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Doctrine\Common\Cache\CacheProvider; + +/** + * @author Nicolas Grekas + */ +class DoctrineAdapter extends AbstractAdapter +{ + private $provider; + + public function __construct(CacheProvider $provider, string $namespace = '', int $defaultLifetime = 0) + { + parent::__construct('', $defaultLifetime); + $this->provider = $provider; + $provider->setNamespace($namespace); + } + + /** + * {@inheritdoc} + */ + public function reset() + { + parent::reset(); + $this->provider->setNamespace($this->provider->getNamespace()); + } + + /** + * {@inheritdoc} + */ + protected function doFetch(array $ids) + { + $unserializeCallbackHandler = ini_set('unserialize_callback_func', parent::class.'::handleUnserializeCallback'); + try { + return $this->provider->fetchMultiple($ids); + } catch (\Error $e) { + $trace = $e->getTrace(); + + if (isset($trace[0]['function']) && !isset($trace[0]['class'])) { + switch ($trace[0]['function']) { + case 'unserialize': + case 'apcu_fetch': + case 'apc_fetch': + throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); + } + } + + throw $e; + } finally { + ini_set('unserialize_callback_func', $unserializeCallbackHandler); + } + } + + /** + * {@inheritdoc} + */ + protected function doHave(string $id) + { + return $this->provider->contains($id); + } + + /** + * {@inheritdoc} + */ + protected function doClear(string $namespace) + { + $namespace = $this->provider->getNamespace(); + + return isset($namespace[0]) + ? $this->provider->deleteAll() + : $this->provider->flushAll(); + } + + /** + * {@inheritdoc} + */ + protected function doDelete(array $ids) + { + $ok = true; + foreach ($ids as $id) { + $ok = $this->provider->delete($id) && $ok; + } + + return $ok; + } + + /** + * {@inheritdoc} + */ + protected function doSave(array $values, int $lifetime) + { + return $this->provider->saveMultiple($values, $lifetime); + } +} diff --git a/vendor/symfony/cache/Adapter/FilesystemAdapter.php b/vendor/symfony/cache/Adapter/FilesystemAdapter.php new file mode 100644 index 0000000..7185dd4 --- /dev/null +++ b/vendor/symfony/cache/Adapter/FilesystemAdapter.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\Traits\FilesystemTrait; + +class FilesystemAdapter extends AbstractAdapter implements PruneableInterface +{ + use FilesystemTrait; + + public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null) + { + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + parent::__construct('', $defaultLifetime); + $this->init($namespace, $directory); + } +} diff --git a/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php b/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php new file mode 100644 index 0000000..2496bda --- /dev/null +++ b/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php @@ -0,0 +1,239 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\Marshaller\TagAwareMarshaller; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\Traits\FilesystemTrait; + +/** + * Stores tag id <> cache id relationship as a symlink, and lookup on invalidation calls. + * + * @author Nicolas Grekas + * @author André Rømcke + */ +class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements PruneableInterface +{ + use FilesystemTrait { + doClear as private doClearCache; + doSave as private doSaveCache; + } + + /** + * Folder used for tag symlinks. + */ + private const TAG_FOLDER = 'tags'; + + public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null) + { + $this->marshaller = new TagAwareMarshaller($marshaller); + parent::__construct('', $defaultLifetime); + $this->init($namespace, $directory); + } + + /** + * {@inheritdoc} + */ + protected function doClear(string $namespace) + { + $ok = $this->doClearCache($namespace); + + if ('' !== $namespace) { + return $ok; + } + + set_error_handler(static function () {}); + $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + + try { + foreach ($this->scanHashDir($this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR) as $dir) { + if (rename($dir, $renamed = substr_replace($dir, bin2hex(random_bytes(4)), -8))) { + $dir = $renamed.\DIRECTORY_SEPARATOR; + } else { + $dir .= \DIRECTORY_SEPARATOR; + $renamed = null; + } + + for ($i = 0; $i < 38; ++$i) { + if (!file_exists($dir.$chars[$i])) { + continue; + } + for ($j = 0; $j < 38; ++$j) { + if (!file_exists($d = $dir.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j])) { + continue; + } + foreach (scandir($d, SCANDIR_SORT_NONE) ?: [] as $link) { + if ('.' !== $link && '..' !== $link && (null !== $renamed || !realpath($d.\DIRECTORY_SEPARATOR.$link))) { + unlink($d.\DIRECTORY_SEPARATOR.$link); + } + } + null === $renamed ?: rmdir($d); + } + null === $renamed ?: rmdir($dir.$chars[$i]); + } + null === $renamed ?: rmdir($renamed); + } + } finally { + restore_error_handler(); + } + + return $ok; + } + + /** + * {@inheritdoc} + */ + protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array + { + $failed = $this->doSaveCache($values, $lifetime); + + // Add Tags as symlinks + foreach ($addTagData as $tagId => $ids) { + $tagFolder = $this->getTagFolder($tagId); + foreach ($ids as $id) { + if ($failed && \in_array($id, $failed, true)) { + continue; + } + + $file = $this->getFile($id); + + if (!@symlink($file, $this->getFile($id, true, $tagFolder))) { + @unlink($file); + $failed[] = $id; + } + } + } + + // Unlink removed Tags + foreach ($removeTagData as $tagId => $ids) { + $tagFolder = $this->getTagFolder($tagId); + foreach ($ids as $id) { + if ($failed && \in_array($id, $failed, true)) { + continue; + } + + @unlink($this->getFile($id, false, $tagFolder)); + } + } + + return $failed; + } + + /** + * {@inheritdoc} + */ + protected function doDeleteYieldTags(array $ids): iterable + { + foreach ($ids as $id) { + $file = $this->getFile($id); + if (!file_exists($file) || !$h = @fopen($file, 'rb')) { + continue; + } + + if ((\PHP_VERSION_ID >= 70300 || '\\' !== \DIRECTORY_SEPARATOR) && !@unlink($file)) { + fclose($h); + continue; + } + + $meta = explode("\n", fread($h, 4096), 3)[2] ?? ''; + + // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F + if (13 < \strlen($meta) && "\x9D" === $meta[0] && "\0" === $meta[5] && "\x5F" === $meta[9]) { + $meta[9] = "\0"; + $tagLen = unpack('Nlen', $meta, 9)['len']; + $meta = substr($meta, 13, $tagLen); + + if (0 < $tagLen -= \strlen($meta)) { + $meta .= fread($h, $tagLen); + } + + try { + yield $id => '' === $meta ? [] : $this->marshaller->unmarshall($meta); + } catch (\Exception $e) { + yield $id => []; + } + } + + fclose($h); + + if (\PHP_VERSION_ID < 70300 && '\\' === \DIRECTORY_SEPARATOR) { + @unlink($file); + } + } + } + + /** + * {@inheritdoc} + */ + protected function doDeleteTagRelations(array $tagData): bool + { + foreach ($tagData as $tagId => $idList) { + $tagFolder = $this->getTagFolder($tagId); + foreach ($idList as $id) { + @unlink($this->getFile($id, false, $tagFolder)); + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doInvalidate(array $tagIds): bool + { + foreach ($tagIds as $tagId) { + if (!file_exists($tagFolder = $this->getTagFolder($tagId))) { + continue; + } + + set_error_handler(static function () {}); + + try { + if (rename($tagFolder, $renamed = substr_replace($tagFolder, bin2hex(random_bytes(4)), -9))) { + $tagFolder = $renamed.\DIRECTORY_SEPARATOR; + } else { + $renamed = null; + } + + foreach ($this->scanHashDir($tagFolder) as $itemLink) { + unlink(realpath($itemLink) ?: $itemLink); + unlink($itemLink); + } + + if (null === $renamed) { + continue; + } + + $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + + for ($i = 0; $i < 38; ++$i) { + for ($j = 0; $j < 38; ++$j) { + rmdir($tagFolder.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j]); + } + rmdir($tagFolder.$chars[$i]); + } + rmdir($renamed); + } finally { + restore_error_handler(); + } + } + + return true; + } + + private function getTagFolder(string $tagId): string + { + return $this->getFile($tagId, false, $this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR; + } +} diff --git a/vendor/symfony/cache/Adapter/MemcachedAdapter.php b/vendor/symfony/cache/Adapter/MemcachedAdapter.php new file mode 100644 index 0000000..e2bc068 --- /dev/null +++ b/vendor/symfony/cache/Adapter/MemcachedAdapter.php @@ -0,0 +1,335 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; + +/** + * @author Rob Frawley 2nd + * @author Nicolas Grekas + */ +class MemcachedAdapter extends AbstractAdapter +{ + protected $maxIdLength = 250; + + private static $defaultClientOptions = [ + 'persistent_id' => null, + 'username' => null, + 'password' => null, + \Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_PHP, + ]; + + private $marshaller; + private $client; + private $lazyClient; + + /** + * Using a MemcachedAdapter with a TagAwareAdapter for storing tags is discouraged. + * Using a RedisAdapter is recommended instead. If you cannot do otherwise, be aware that: + * - the Memcached::OPT_BINARY_PROTOCOL must be enabled + * (that's the default when using MemcachedAdapter::createConnection()); + * - tags eviction by Memcached's LRU algorithm will break by-tags invalidation; + * your Memcached memory should be large enough to never trigger LRU. + * + * Using a MemcachedAdapter as a pure items store is fine. + */ + public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) + { + if (!static::isSupported()) { + throw new CacheException('Memcached >= 2.2.0 is required'); + } + if ('Memcached' === \get_class($client)) { + $opt = $client->getOption(\Memcached::OPT_SERIALIZER); + if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { + throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); + } + $this->maxIdLength -= \strlen($client->getOption(\Memcached::OPT_PREFIX_KEY)); + $this->client = $client; + } else { + $this->lazyClient = $client; + } + + parent::__construct($namespace, $defaultLifetime); + $this->enableVersioning(); + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + } + + public static function isSupported() + { + return \extension_loaded('memcached') && version_compare(phpversion('memcached'), '2.2.0', '>='); + } + + /** + * Creates a Memcached instance. + * + * By default, the binary protocol, no block, and libketama compatible options are enabled. + * + * Examples for servers: + * - 'memcached://user:pass@localhost?weight=33' + * - [['localhost', 11211, 33]] + * + * @param array[]|string|string[] $servers An array of servers, a DSN, or an array of DSNs + * @param array $options An array of options + * + * @return \Memcached + * + * @throws \ErrorException When invalid options or servers are provided + */ + public static function createConnection($servers, array $options = []) + { + if (\is_string($servers)) { + $servers = [$servers]; + } elseif (!\is_array($servers)) { + throw new InvalidArgumentException(sprintf('MemcachedAdapter::createClient() expects array or string as first argument, %s given.', \gettype($servers))); + } + if (!static::isSupported()) { + throw new CacheException('Memcached >= 2.2.0 is required'); + } + set_error_handler(function ($type, $msg, $file, $line) { throw new \ErrorException($msg, 0, $type, $file, $line); }); + try { + $options += static::$defaultClientOptions; + $client = new \Memcached($options['persistent_id']); + $username = $options['username']; + $password = $options['password']; + + // parse any DSN in $servers + foreach ($servers as $i => $dsn) { + if (\is_array($dsn)) { + continue; + } + if (0 !== strpos($dsn, 'memcached:')) { + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s does not start with "memcached:"', $dsn)); + } + $params = preg_replace_callback('#^memcached:(//)?(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { + if (!empty($m[2])) { + list($username, $password) = explode(':', $m[2], 2) + [1 => null]; + } + + return 'file:'.($m[1] ?? ''); + }, $dsn); + if (false === $params = parse_url($params)) { + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $dsn)); + } + $query = $hosts = []; + if (isset($params['query'])) { + parse_str($params['query'], $query); + + if (isset($query['host'])) { + if (!\is_array($hosts = $query['host'])) { + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $dsn)); + } + foreach ($hosts as $host => $weight) { + if (false === $port = strrpos($host, ':')) { + $hosts[$host] = [$host, 11211, (int) $weight]; + } else { + $hosts[$host] = [substr($host, 0, $port), (int) substr($host, 1 + $port), (int) $weight]; + } + } + $hosts = array_values($hosts); + unset($query['host']); + } + if ($hosts && !isset($params['host']) && !isset($params['path'])) { + unset($servers[$i]); + $servers = array_merge($servers, $hosts); + continue; + } + } + if (!isset($params['host']) && !isset($params['path'])) { + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $dsn)); + } + if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { + $params['weight'] = $m[1]; + $params['path'] = substr($params['path'], 0, -\strlen($m[0])); + } + $params += [ + 'host' => isset($params['host']) ? $params['host'] : $params['path'], + 'port' => isset($params['host']) ? 11211 : null, + 'weight' => 0, + ]; + if ($query) { + $params += $query; + $options = $query + $options; + } + + $servers[$i] = [$params['host'], $params['port'], $params['weight']]; + + if ($hosts) { + $servers = array_merge($servers, $hosts); + } + } + + // set client's options + unset($options['persistent_id'], $options['username'], $options['password'], $options['weight'], $options['lazy']); + $options = array_change_key_case($options, CASE_UPPER); + $client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); + $client->setOption(\Memcached::OPT_NO_BLOCK, true); + $client->setOption(\Memcached::OPT_TCP_NODELAY, true); + if (!\array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !\array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) { + $client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true); + } + foreach ($options as $name => $value) { + if (\is_int($name)) { + continue; + } + if ('HASH' === $name || 'SERIALIZER' === $name || 'DISTRIBUTION' === $name) { + $value = \constant('Memcached::'.$name.'_'.strtoupper($value)); + } + $opt = \constant('Memcached::OPT_'.$name); + + unset($options[$name]); + $options[$opt] = $value; + } + $client->setOptions($options); + + // set client's servers, taking care of persistent connections + if (!$client->isPristine()) { + $oldServers = []; + foreach ($client->getServerList() as $server) { + $oldServers[] = [$server['host'], $server['port']]; + } + + $newServers = []; + foreach ($servers as $server) { + if (1 < \count($server)) { + $server = array_values($server); + unset($server[2]); + $server[1] = (int) $server[1]; + } + $newServers[] = $server; + } + + if ($oldServers !== $newServers) { + $client->resetServerList(); + $client->addServers($servers); + } + } else { + $client->addServers($servers); + } + + if (null !== $username || null !== $password) { + if (!method_exists($client, 'setSaslAuthData')) { + trigger_error('Missing SASL support: the memcached extension must be compiled with --enable-memcached-sasl.'); + } + $client->setSaslAuthData($username, $password); + } + + return $client; + } finally { + restore_error_handler(); + } + } + + /** + * {@inheritdoc} + */ + protected function doSave(array $values, int $lifetime) + { + if (!$values = $this->marshaller->marshall($values, $failed)) { + return $failed; + } + + if ($lifetime && $lifetime > 30 * 86400) { + $lifetime += time(); + } + + $encodedValues = []; + foreach ($values as $key => $value) { + $encodedValues[rawurlencode($key)] = $value; + } + + return $this->checkResultCode($this->getClient()->setMulti($encodedValues, $lifetime)) ? $failed : false; + } + + /** + * {@inheritdoc} + */ + protected function doFetch(array $ids) + { + try { + $encodedIds = array_map('rawurlencode', $ids); + + $encodedResult = $this->checkResultCode($this->getClient()->getMulti($encodedIds)); + + $result = []; + foreach ($encodedResult as $key => $value) { + $result[rawurldecode($key)] = $this->marshaller->unmarshall($value); + } + + return $result; + } catch (\Error $e) { + throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); + } + } + + /** + * {@inheritdoc} + */ + protected function doHave(string $id) + { + return false !== $this->getClient()->get(rawurlencode($id)) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode()); + } + + /** + * {@inheritdoc} + */ + protected function doDelete(array $ids) + { + $ok = true; + $encodedIds = array_map('rawurlencode', $ids); + foreach ($this->checkResultCode($this->getClient()->deleteMulti($encodedIds)) as $result) { + if (\Memcached::RES_SUCCESS !== $result && \Memcached::RES_NOTFOUND !== $result) { + $ok = false; + } + } + + return $ok; + } + + /** + * {@inheritdoc} + */ + protected function doClear(string $namespace) + { + return '' === $namespace && $this->getClient()->flush(); + } + + private function checkResultCode($result) + { + $code = $this->client->getResultCode(); + + if (\Memcached::RES_SUCCESS === $code || \Memcached::RES_NOTFOUND === $code) { + return $result; + } + + throw new CacheException(sprintf('MemcachedAdapter client error: %s.', strtolower($this->client->getResultMessage()))); + } + + private function getClient(): \Memcached + { + if ($this->client) { + return $this->client; + } + + $opt = $this->lazyClient->getOption(\Memcached::OPT_SERIALIZER); + if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { + throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); + } + if ('' !== $prefix = (string) $this->lazyClient->getOption(\Memcached::OPT_PREFIX_KEY)) { + throw new CacheException(sprintf('MemcachedAdapter: "prefix_key" option must be empty when using proxified connections, "%s" given.', $prefix)); + } + + return $this->client = $this->lazyClient; + } +} diff --git a/vendor/symfony/cache/Adapter/NullAdapter.php b/vendor/symfony/cache/Adapter/NullAdapter.php new file mode 100644 index 0000000..44778d7 --- /dev/null +++ b/vendor/symfony/cache/Adapter/NullAdapter.php @@ -0,0 +1,154 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Contracts\Cache\CacheInterface; + +/** + * @author Titouan Galopin + */ +class NullAdapter implements AdapterInterface, CacheInterface +{ + private $createCacheItem; + + public function __construct() + { + $this->createCacheItem = \Closure::bind( + function ($key) { + $item = new CacheItem(); + $item->key = $key; + $item->isHit = false; + + return $item; + }, + $this, + CacheItem::class + ); + } + + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + $save = true; + + return $callback(($this->createCacheItem)($key), $save); + } + + /** + * {@inheritdoc} + */ + public function getItem($key) + { + $f = $this->createCacheItem; + + return $f($key); + } + + /** + * {@inheritdoc} + */ + public function getItems(array $keys = []) + { + return $this->generateItems($keys); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function hasItem($key) + { + return false; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function clear(string $prefix = '') + { + return true; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItem($key) + { + return true; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItems(array $keys) + { + return true; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function save(CacheItemInterface $item) + { + return false; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function saveDeferred(CacheItemInterface $item) + { + return false; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function commit() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function delete(string $key): bool + { + return $this->deleteItem($key); + } + + private function generateItems(array $keys) + { + $f = $this->createCacheItem; + + foreach ($keys as $key) { + yield $key => $f($key); + } + } +} diff --git a/vendor/symfony/cache/Adapter/PdoAdapter.php b/vendor/symfony/cache/Adapter/PdoAdapter.php new file mode 100644 index 0000000..79f9a33 --- /dev/null +++ b/vendor/symfony/cache/Adapter/PdoAdapter.php @@ -0,0 +1,469 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Driver\ServerInfoAwareConnection; +use Doctrine\DBAL\DriverManager; +use Doctrine\DBAL\Exception\TableNotFoundException; +use Doctrine\DBAL\Schema\Schema; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\PruneableInterface; + +class PdoAdapter extends AbstractAdapter implements PruneableInterface +{ + protected $maxIdLength = 255; + + private $marshaller; + private $conn; + private $dsn; + private $driver; + private $serverVersion; + private $table = 'cache_items'; + private $idCol = 'item_id'; + private $dataCol = 'item_data'; + private $lifetimeCol = 'item_lifetime'; + private $timeCol = 'item_time'; + private $username = ''; + private $password = ''; + private $connectionOptions = []; + private $namespace; + + /** + * You can either pass an existing database connection as PDO instance or + * a Doctrine DBAL Connection or a DSN string that will be used to + * lazy-connect to the database when the cache is actually used. + * + * When a Doctrine DBAL Connection is passed, the cache table is created + * automatically when possible. Otherwise, use the createTable() method. + * + * List of available options: + * * db_table: The name of the table [default: cache_items] + * * db_id_col: The column where to store the cache id [default: item_id] + * * db_data_col: The column where to store the cache data [default: item_data] + * * db_lifetime_col: The column where to store the lifetime [default: item_lifetime] + * * db_time_col: The column where to store the timestamp [default: item_time] + * * db_username: The username when lazy-connect [default: ''] + * * db_password: The password when lazy-connect [default: ''] + * * db_connection_options: An array of driver-specific connection options [default: []] + * + * @param \PDO|Connection|string $connOrDsn a \PDO or Connection instance or DSN string or null + * + * @throws InvalidArgumentException When first argument is not PDO nor Connection nor string + * @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION + * @throws InvalidArgumentException When namespace contains invalid characters + */ + public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null) + { + if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) { + throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0])); + } + + if ($connOrDsn instanceof \PDO) { + if (\PDO::ERRMODE_EXCEPTION !== $connOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { + throw new InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION))', __CLASS__)); + } + + $this->conn = $connOrDsn; + } elseif ($connOrDsn instanceof Connection) { + $this->conn = $connOrDsn; + } elseif (\is_string($connOrDsn)) { + $this->dsn = $connOrDsn; + } else { + throw new InvalidArgumentException(sprintf('"%s" requires PDO or Doctrine\DBAL\Connection instance or DSN string as first argument, "%s" given.', __CLASS__, \is_object($connOrDsn) ? \get_class($connOrDsn) : \gettype($connOrDsn))); + } + + $this->table = isset($options['db_table']) ? $options['db_table'] : $this->table; + $this->idCol = isset($options['db_id_col']) ? $options['db_id_col'] : $this->idCol; + $this->dataCol = isset($options['db_data_col']) ? $options['db_data_col'] : $this->dataCol; + $this->lifetimeCol = isset($options['db_lifetime_col']) ? $options['db_lifetime_col'] : $this->lifetimeCol; + $this->timeCol = isset($options['db_time_col']) ? $options['db_time_col'] : $this->timeCol; + $this->username = isset($options['db_username']) ? $options['db_username'] : $this->username; + $this->password = isset($options['db_password']) ? $options['db_password'] : $this->password; + $this->connectionOptions = isset($options['db_connection_options']) ? $options['db_connection_options'] : $this->connectionOptions; + $this->namespace = $namespace; + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + + parent::__construct($namespace, $defaultLifetime); + } + + /** + * Creates the table to store cache items which can be called once for setup. + * + * Cache ID are saved in a column of maximum length 255. Cache data is + * saved in a BLOB. + * + * @throws \PDOException When the table already exists + * @throws DBALException When the table already exists + * @throws \DomainException When an unsupported PDO driver is used + */ + public function createTable() + { + // connect if we are not yet + $conn = $this->getConnection(); + + if ($conn instanceof Connection) { + $types = [ + 'mysql' => 'binary', + 'sqlite' => 'text', + 'pgsql' => 'string', + 'oci' => 'string', + 'sqlsrv' => 'string', + ]; + if (!isset($types[$this->driver])) { + throw new \DomainException(sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $this->driver)); + } + + $schema = new Schema(); + $table = $schema->createTable($this->table); + $table->addColumn($this->idCol, $types[$this->driver], ['length' => 255]); + $table->addColumn($this->dataCol, 'blob', ['length' => 16777215]); + $table->addColumn($this->lifetimeCol, 'integer', ['unsigned' => true, 'notnull' => false]); + $table->addColumn($this->timeCol, 'integer', ['unsigned' => true]); + $table->setPrimaryKey([$this->idCol]); + + foreach ($schema->toSql($conn->getDatabasePlatform()) as $sql) { + $conn->exec($sql); + } + + return; + } + + switch ($this->driver) { + case 'mysql': + // We use varbinary for the ID column because it prevents unwanted conversions: + // - character set conversions between server and client + // - trailing space removal + // - case-insensitivity + // - language processing like é == e + $sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(255) NOT NULL PRIMARY KEY, $this->dataCol MEDIUMBLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8_bin, ENGINE = InnoDB"; + break; + case 'sqlite': + $sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)"; + break; + case 'pgsql': + $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)"; + break; + case 'oci': + $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR2(255) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)"; + break; + case 'sqlsrv': + $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)"; + break; + default: + throw new \DomainException(sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $this->driver)); + } + + $conn->exec($sql); + } + + /** + * {@inheritdoc} + */ + public function prune() + { + $deleteSql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= :time"; + + if ('' !== $this->namespace) { + $deleteSql .= " AND $this->idCol LIKE :namespace"; + } + + try { + $delete = $this->getConnection()->prepare($deleteSql); + } catch (TableNotFoundException $e) { + return true; + } catch (\PDOException $e) { + return true; + } + $delete->bindValue(':time', time(), \PDO::PARAM_INT); + + if ('' !== $this->namespace) { + $delete->bindValue(':namespace', sprintf('%s%%', $this->namespace), \PDO::PARAM_STR); + } + try { + return $delete->execute(); + } catch (TableNotFoundException $e) { + return true; + } catch (\PDOException $e) { + return true; + } + } + + /** + * {@inheritdoc} + */ + protected function doFetch(array $ids) + { + $now = time(); + $expired = []; + + $sql = str_pad('', (\count($ids) << 1) - 1, '?,'); + $sql = "SELECT $this->idCol, CASE WHEN $this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ? THEN $this->dataCol ELSE NULL END FROM $this->table WHERE $this->idCol IN ($sql)"; + $stmt = $this->getConnection()->prepare($sql); + $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); + foreach ($ids as $id) { + $stmt->bindValue(++$i, $id); + } + $stmt->execute(); + + while ($row = $stmt->fetch(\PDO::FETCH_NUM)) { + if (null === $row[1]) { + $expired[] = $row[0]; + } else { + yield $row[0] => $this->marshaller->unmarshall(\is_resource($row[1]) ? stream_get_contents($row[1]) : $row[1]); + } + } + + if ($expired) { + $sql = str_pad('', (\count($expired) << 1) - 1, '?,'); + $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ? AND $this->idCol IN ($sql)"; + $stmt = $this->getConnection()->prepare($sql); + $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); + foreach ($expired as $id) { + $stmt->bindValue(++$i, $id); + } + $stmt->execute(); + } + } + + /** + * {@inheritdoc} + */ + protected function doHave(string $id) + { + $sql = "SELECT 1 FROM $this->table WHERE $this->idCol = :id AND ($this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > :time)"; + $stmt = $this->getConnection()->prepare($sql); + + $stmt->bindValue(':id', $id); + $stmt->bindValue(':time', time(), \PDO::PARAM_INT); + $stmt->execute(); + + return (bool) $stmt->fetchColumn(); + } + + /** + * {@inheritdoc} + */ + protected function doClear(string $namespace) + { + $conn = $this->getConnection(); + + if ('' === $namespace) { + if ('sqlite' === $this->driver) { + $sql = "DELETE FROM $this->table"; + } else { + $sql = "TRUNCATE TABLE $this->table"; + } + } else { + $sql = "DELETE FROM $this->table WHERE $this->idCol LIKE '$namespace%'"; + } + + try { + $conn->exec($sql); + } catch (TableNotFoundException $e) { + } catch (\PDOException $e) { + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doDelete(array $ids) + { + $sql = str_pad('', (\count($ids) << 1) - 1, '?,'); + $sql = "DELETE FROM $this->table WHERE $this->idCol IN ($sql)"; + try { + $stmt = $this->getConnection()->prepare($sql); + $stmt->execute(array_values($ids)); + } catch (TableNotFoundException $e) { + } catch (\PDOException $e) { + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doSave(array $values, int $lifetime) + { + if (!$values = $this->marshaller->marshall($values, $failed)) { + return $failed; + } + + $conn = $this->getConnection(); + $driver = $this->driver; + $insertSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)"; + + switch (true) { + case 'mysql' === $driver: + $sql = $insertSql." ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)"; + break; + case 'oci' === $driver: + // DUAL is Oracle specific dummy table + $sql = "MERGE INTO $this->table USING DUAL ON ($this->idCol = ?) ". + "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". + "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?"; + break; + case 'sqlsrv' === $driver && version_compare($this->getServerVersion(), '10', '>='): + // MERGE is only available since SQL Server 2008 and must be terminated by semicolon + // It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx + $sql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ". + "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". + "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;"; + break; + case 'sqlite' === $driver: + $sql = 'INSERT OR REPLACE'.substr($insertSql, 6); + break; + case 'pgsql' === $driver && version_compare($this->getServerVersion(), '9.5', '>='): + $sql = $insertSql." ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; + break; + default: + $driver = null; + $sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id"; + break; + } + + $now = time(); + $lifetime = $lifetime ?: null; + try { + $stmt = $conn->prepare($sql); + } catch (TableNotFoundException $e) { + if (!$conn->isTransactionActive() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { + $this->createTable(); + } + $stmt = $conn->prepare($sql); + } catch (\PDOException $e) { + if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { + $this->createTable(); + } + $stmt = $conn->prepare($sql); + } + + if ('sqlsrv' === $driver || 'oci' === $driver) { + $stmt->bindParam(1, $id); + $stmt->bindParam(2, $id); + $stmt->bindParam(3, $data, \PDO::PARAM_LOB); + $stmt->bindValue(4, $lifetime, \PDO::PARAM_INT); + $stmt->bindValue(5, $now, \PDO::PARAM_INT); + $stmt->bindParam(6, $data, \PDO::PARAM_LOB); + $stmt->bindValue(7, $lifetime, \PDO::PARAM_INT); + $stmt->bindValue(8, $now, \PDO::PARAM_INT); + } else { + $stmt->bindParam(':id', $id); + $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); + $stmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT); + $stmt->bindValue(':time', $now, \PDO::PARAM_INT); + } + if (null === $driver) { + $insertStmt = $conn->prepare($insertSql); + + $insertStmt->bindParam(':id', $id); + $insertStmt->bindParam(':data', $data, \PDO::PARAM_LOB); + $insertStmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT); + $insertStmt->bindValue(':time', $now, \PDO::PARAM_INT); + } + + foreach ($values as $id => $data) { + try { + $stmt->execute(); + } catch (TableNotFoundException $e) { + if (!$conn->isTransactionActive() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { + $this->createTable(); + } + $stmt->execute(); + } catch (\PDOException $e) { + if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { + $this->createTable(); + } + $stmt->execute(); + } + if (null === $driver && !$stmt->rowCount()) { + try { + $insertStmt->execute(); + } catch (DBALException $e) { + } catch (\PDOException $e) { + // A concurrent write won, let it be + } + } + } + + return $failed; + } + + /** + * @return \PDO|Connection + */ + private function getConnection(): object + { + if (null === $this->conn) { + if (strpos($this->dsn, '://')) { + if (!class_exists(DriverManager::class)) { + throw new InvalidArgumentException(sprintf('Failed to parse the DSN "%s". Try running "composer require doctrine/dbal".', $this->dsn)); + } + $this->conn = DriverManager::getConnection(['url' => $this->dsn]); + } else { + $this->conn = new \PDO($this->dsn, $this->username, $this->password, $this->connectionOptions); + $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + } + } + if (null === $this->driver) { + if ($this->conn instanceof \PDO) { + $this->driver = $this->conn->getAttribute(\PDO::ATTR_DRIVER_NAME); + } else { + switch ($this->driver = $this->conn->getDriver()->getName()) { + case 'mysqli': + case 'pdo_mysql': + case 'drizzle_pdo_mysql': + $this->driver = 'mysql'; + break; + case 'pdo_sqlite': + $this->driver = 'sqlite'; + break; + case 'pdo_pgsql': + $this->driver = 'pgsql'; + break; + case 'oci8': + case 'pdo_oracle': + $this->driver = 'oci'; + break; + case 'pdo_sqlsrv': + $this->driver = 'sqlsrv'; + break; + } + } + } + + return $this->conn; + } + + private function getServerVersion(): string + { + if (null === $this->serverVersion) { + $conn = $this->conn instanceof \PDO ? $this->conn : $this->conn->getWrappedConnection(); + if ($conn instanceof \PDO) { + $this->serverVersion = $conn->getAttribute(\PDO::ATTR_SERVER_VERSION); + } elseif ($conn instanceof ServerInfoAwareConnection) { + $this->serverVersion = $conn->getServerVersion(); + } else { + $this->serverVersion = '0'; + } + } + + return $this->serverVersion; + } +} diff --git a/vendor/symfony/cache/Adapter/PhpArrayAdapter.php b/vendor/symfony/cache/Adapter/PhpArrayAdapter.php new file mode 100644 index 0000000..84946f6 --- /dev/null +++ b/vendor/symfony/cache/Adapter/PhpArrayAdapter.php @@ -0,0 +1,432 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ContractsTrait; +use Symfony\Component\Cache\Traits\ProxyTrait; +use Symfony\Component\VarExporter\VarExporter; +use Symfony\Contracts\Cache\CacheInterface; + +/** + * Caches items at warm up time using a PHP array that is stored in shared memory by OPCache since PHP 7.0. + * Warmed up items are read-only and run-time discovered items are cached using a fallback adapter. + * + * @author Titouan Galopin + * @author Nicolas Grekas + */ +class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface +{ + use ContractsTrait; + use ProxyTrait; + + private $file; + private $keys; + private $values; + private $createCacheItem; + + private static $valuesCache = []; + + /** + * @param string $file The PHP file were values are cached + * @param AdapterInterface $fallbackPool A pool to fallback on when an item is not hit + */ + public function __construct(string $file, AdapterInterface $fallbackPool) + { + $this->file = $file; + $this->pool = $fallbackPool; + $this->createCacheItem = \Closure::bind( + static function ($key, $value, $isHit) { + $item = new CacheItem(); + $item->key = $key; + $item->value = $value; + $item->isHit = $isHit; + + return $item; + }, + null, + CacheItem::class + ); + } + + /** + * This adapter takes advantage of how PHP stores arrays in its latest versions. + * + * @param string $file The PHP file were values are cached + * @param CacheItemPoolInterface $fallbackPool A pool to fallback on when an item is not hit + * + * @return CacheItemPoolInterface + */ + public static function create(string $file, CacheItemPoolInterface $fallbackPool) + { + if (!$fallbackPool instanceof AdapterInterface) { + $fallbackPool = new ProxyAdapter($fallbackPool); + } + + return new static($file, $fallbackPool); + } + + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + if (null === $this->values) { + $this->initialize(); + } + if (!isset($this->keys[$key])) { + get_from_pool: + if ($this->pool instanceof CacheInterface) { + return $this->pool->get($key, $callback, $beta, $metadata); + } + + return $this->doGet($this->pool, $key, $callback, $beta, $metadata); + } + $value = $this->values[$this->keys[$key]]; + + if ('N;' === $value) { + return null; + } + try { + if ($value instanceof \Closure) { + return $value(); + } + } catch (\Throwable $e) { + unset($this->keys[$key]); + goto get_from_pool; + } + + return $value; + } + + /** + * {@inheritdoc} + */ + public function getItem($key) + { + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); + } + if (null === $this->values) { + $this->initialize(); + } + if (!isset($this->keys[$key])) { + return $this->pool->getItem($key); + } + + $value = $this->values[$this->keys[$key]]; + $isHit = true; + + if ('N;' === $value) { + $value = null; + } elseif ($value instanceof \Closure) { + try { + $value = $value(); + } catch (\Throwable $e) { + $value = null; + $isHit = false; + } + } + + $f = $this->createCacheItem; + + return $f($key, $value, $isHit); + } + + /** + * {@inheritdoc} + */ + public function getItems(array $keys = []) + { + foreach ($keys as $key) { + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); + } + } + if (null === $this->values) { + $this->initialize(); + } + + return $this->generateItems($keys); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function hasItem($key) + { + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); + } + if (null === $this->values) { + $this->initialize(); + } + + return isset($this->keys[$key]) || $this->pool->hasItem($key); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItem($key) + { + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); + } + if (null === $this->values) { + $this->initialize(); + } + + return !isset($this->keys[$key]) && $this->pool->deleteItem($key); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItems(array $keys) + { + $deleted = true; + $fallbackKeys = []; + + foreach ($keys as $key) { + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); + } + + if (isset($this->keys[$key])) { + $deleted = false; + } else { + $fallbackKeys[] = $key; + } + } + if (null === $this->values) { + $this->initialize(); + } + + if ($fallbackKeys) { + $deleted = $this->pool->deleteItems($fallbackKeys) && $deleted; + } + + return $deleted; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function save(CacheItemInterface $item) + { + if (null === $this->values) { + $this->initialize(); + } + + return !isset($this->keys[$item->getKey()]) && $this->pool->save($item); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function saveDeferred(CacheItemInterface $item) + { + if (null === $this->values) { + $this->initialize(); + } + + return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function commit() + { + return $this->pool->commit(); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function clear(string $prefix = '') + { + $this->keys = $this->values = []; + + $cleared = @unlink($this->file) || !file_exists($this->file); + unset(self::$valuesCache[$this->file]); + + if ($this->pool instanceof AdapterInterface) { + return $this->pool->clear($prefix) && $cleared; + } + + return $this->pool->clear() && $cleared; + } + + /** + * Store an array of cached values. + * + * @param array $values The cached values + */ + public function warmUp(array $values) + { + if (file_exists($this->file)) { + if (!is_file($this->file)) { + throw new InvalidArgumentException(sprintf('Cache path exists and is not a file: %s.', $this->file)); + } + + if (!is_writable($this->file)) { + throw new InvalidArgumentException(sprintf('Cache file is not writable: %s.', $this->file)); + } + } else { + $directory = \dirname($this->file); + + if (!is_dir($directory) && !@mkdir($directory, 0777, true)) { + throw new InvalidArgumentException(sprintf('Cache directory does not exist and cannot be created: %s.', $directory)); + } + + if (!is_writable($directory)) { + throw new InvalidArgumentException(sprintf('Cache directory is not writable: %s.', $directory)); + } + } + + $dumpedValues = ''; + $dumpedMap = []; + $dump = <<<'EOF' + $value) { + CacheItem::validateKey(\is_int($key) ? (string) $key : $key); + $isStaticValue = true; + + if (null === $value) { + $value = "'N;'"; + } elseif (\is_object($value) || \is_array($value)) { + try { + $value = VarExporter::export($value, $isStaticValue); + } catch (\Exception $e) { + throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, \is_object($value) ? \get_class($value) : 'array'), 0, $e); + } + } elseif (\is_string($value)) { + // Wrap "N;" in a closure to not confuse it with an encoded `null` + if ('N;' === $value) { + $isStaticValue = false; + } + $value = var_export($value, true); + } elseif (!is_scalar($value)) { + throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, \gettype($value))); + } else { + $value = var_export($value, true); + } + + if (!$isStaticValue) { + $value = str_replace("\n", "\n ", $value); + $value = "static function () {\n return {$value};\n}"; + } + $hash = hash('md5', $value); + + if (null === $id = $dumpedMap[$hash] ?? null) { + $id = $dumpedMap[$hash] = \count($dumpedMap); + $dumpedValues .= "{$id} => {$value},\n"; + } + + $dump .= var_export($key, true)." => {$id},\n"; + } + + $dump .= "\n], [\n\n{$dumpedValues}\n]];\n"; + + $tmpFile = uniqid($this->file, true); + + file_put_contents($tmpFile, $dump); + @chmod($tmpFile, 0666 & ~umask()); + unset($serialized, $value, $dump); + + @rename($tmpFile, $this->file); + unset(self::$valuesCache[$this->file]); + + $this->initialize(); + } + + /** + * Load the cache file. + */ + private function initialize() + { + if (isset(self::$valuesCache[$this->file])) { + $values = self::$valuesCache[$this->file]; + } elseif (!file_exists($this->file)) { + $this->keys = $this->values = []; + + return; + } else { + $values = self::$valuesCache[$this->file] = (include $this->file) ?: [[], []]; + } + + if (2 !== \count($values) || !isset($values[0], $values[1])) { + $this->keys = $this->values = []; + } else { + list($this->keys, $this->values) = $values; + } + } + + private function generateItems(array $keys): \Generator + { + $f = $this->createCacheItem; + $fallbackKeys = []; + + foreach ($keys as $key) { + if (isset($this->keys[$key])) { + $value = $this->values[$this->keys[$key]]; + + if ('N;' === $value) { + yield $key => $f($key, null, true); + } elseif ($value instanceof \Closure) { + try { + yield $key => $f($key, $value(), true); + } catch (\Throwable $e) { + yield $key => $f($key, null, false); + } + } else { + yield $key => $f($key, $value, true); + } + } else { + $fallbackKeys[] = $key; + } + } + + if ($fallbackKeys) { + yield from $this->pool->getItems($fallbackKeys); + } + } +} diff --git a/vendor/symfony/cache/Adapter/PhpFilesAdapter.php b/vendor/symfony/cache/Adapter/PhpFilesAdapter.php new file mode 100644 index 0000000..f148a89 --- /dev/null +++ b/vendor/symfony/cache/Adapter/PhpFilesAdapter.php @@ -0,0 +1,330 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\Traits\FilesystemCommonTrait; +use Symfony\Component\VarExporter\VarExporter; + +/** + * @author Piotr Stankowski + * @author Nicolas Grekas + * @author Rob Frawley 2nd + */ +class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface +{ + use FilesystemCommonTrait { + doClear as private doCommonClear; + doDelete as private doCommonDelete; + } + + private $includeHandler; + private $appendOnly; + private $values = []; + private $files = []; + + private static $startTime; + private static $valuesCache = []; + + /** + * @param $appendOnly Set to `true` to gain extra performance when the items stored in this pool never expire. + * Doing so is encouraged because it fits perfectly OPcache's memory model. + * + * @throws CacheException if OPcache is not enabled + */ + public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, bool $appendOnly = false) + { + $this->appendOnly = $appendOnly; + self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time(); + parent::__construct('', $defaultLifetime); + $this->init($namespace, $directory); + $this->includeHandler = static function ($type, $msg, $file, $line) { + throw new \ErrorException($msg, 0, $type, $file, $line); + }; + } + + public static function isSupported() + { + self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time(); + + return \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(ini_get('opcache.enable_cli'), FILTER_VALIDATE_BOOLEAN)); + } + + /** + * @return bool + */ + public function prune() + { + $time = time(); + $pruned = true; + $getExpiry = true; + + set_error_handler($this->includeHandler); + try { + foreach ($this->scanHashDir($this->directory) as $file) { + try { + if (\is_array($expiresAt = include $file)) { + $expiresAt = $expiresAt[0]; + } + } catch (\ErrorException $e) { + $expiresAt = $time; + } + + if ($time >= $expiresAt) { + $pruned = $this->doUnlink($file) && !file_exists($file) && $pruned; + } + } + } finally { + restore_error_handler(); + } + + return $pruned; + } + + /** + * {@inheritdoc} + */ + protected function doFetch(array $ids) + { + if ($this->appendOnly) { + $now = 0; + $missingIds = []; + } else { + $now = time(); + $missingIds = $ids; + $ids = []; + } + $values = []; + + begin: + $getExpiry = false; + + foreach ($ids as $id) { + if (null === $value = $this->values[$id] ?? null) { + $missingIds[] = $id; + } elseif ('N;' === $value) { + $values[$id] = null; + } elseif (!\is_object($value)) { + $values[$id] = $value; + } elseif (!$value instanceof LazyValue) { + $values[$id] = $value(); + } elseif (false === $values[$id] = include $value->file) { + unset($values[$id], $this->values[$id]); + $missingIds[] = $id; + } + if (!$this->appendOnly) { + unset($this->values[$id]); + } + } + + if (!$missingIds) { + return $values; + } + + set_error_handler($this->includeHandler); + try { + $getExpiry = true; + + foreach ($missingIds as $k => $id) { + try { + $file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id); + + if (isset(self::$valuesCache[$file])) { + [$expiresAt, $this->values[$id]] = self::$valuesCache[$file]; + } elseif (\is_array($expiresAt = include $file)) { + if ($this->appendOnly) { + self::$valuesCache[$file] = $expiresAt; + } + + [$expiresAt, $this->values[$id]] = $expiresAt; + } elseif ($now < $expiresAt) { + $this->values[$id] = new LazyValue($file); + } + + if ($now >= $expiresAt) { + unset($this->values[$id], $missingIds[$k], self::$valuesCache[$file]); + } + } catch (\ErrorException $e) { + unset($missingIds[$k]); + } + } + } finally { + restore_error_handler(); + } + + $ids = $missingIds; + $missingIds = []; + goto begin; + } + + /** + * {@inheritdoc} + */ + protected function doHave(string $id) + { + if ($this->appendOnly && isset($this->values[$id])) { + return true; + } + + set_error_handler($this->includeHandler); + try { + $file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id); + $getExpiry = true; + + if (isset(self::$valuesCache[$file])) { + [$expiresAt, $value] = self::$valuesCache[$file]; + } elseif (\is_array($expiresAt = include $file)) { + if ($this->appendOnly) { + self::$valuesCache[$file] = $expiresAt; + } + + [$expiresAt, $value] = $expiresAt; + } elseif ($this->appendOnly) { + $value = new LazyValue($file); + } + } catch (\ErrorException $e) { + return false; + } finally { + restore_error_handler(); + } + if ($this->appendOnly) { + $now = 0; + $this->values[$id] = $value; + } else { + $now = time(); + } + + return $now < $expiresAt; + } + + /** + * {@inheritdoc} + */ + protected function doSave(array $values, int $lifetime) + { + $ok = true; + $expiry = $lifetime ? time() + $lifetime : 'PHP_INT_MAX'; + $allowCompile = self::isSupported(); + + foreach ($values as $key => $value) { + unset($this->values[$key]); + $isStaticValue = true; + if (null === $value) { + $value = "'N;'"; + } elseif (\is_object($value) || \is_array($value)) { + try { + $value = VarExporter::export($value, $isStaticValue); + } catch (\Exception $e) { + throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, \is_object($value) ? \get_class($value) : 'array'), 0, $e); + } + } elseif (\is_string($value)) { + // Wrap "N;" in a closure to not confuse it with an encoded `null` + if ('N;' === $value) { + $isStaticValue = false; + } + $value = var_export($value, true); + } elseif (!is_scalar($value)) { + throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, \gettype($value))); + } else { + $value = var_export($value, true); + } + + $encodedKey = rawurlencode($key); + + if ($isStaticValue) { + $value = "return [{$expiry}, {$value}];"; + } elseif ($this->appendOnly) { + $value = "return [{$expiry}, static function () { return {$value}; }];"; + } else { + // We cannot use a closure here because of https://bugs.php.net/76982 + $value = str_replace('\Symfony\Component\VarExporter\Internal\\', '', $value); + $value = "namespace Symfony\Component\VarExporter\Internal;\n\nreturn \$getExpiry ? {$expiry} : {$value};"; + } + + $file = $this->files[$key] = $this->getFile($key, true); + // Since OPcache only compiles files older than the script execution start, set the file's mtime in the past + $ok = $this->write($file, "directory)) { + throw new CacheException(sprintf('Cache directory is not writable (%s)', $this->directory)); + } + + return $ok; + } + + /** + * {@inheritdoc} + */ + protected function doClear(string $namespace) + { + $this->values = []; + + return $this->doCommonClear($namespace); + } + + /** + * {@inheritdoc} + */ + protected function doDelete(array $ids) + { + foreach ($ids as $id) { + unset($this->values[$id]); + } + + return $this->doCommonDelete($ids); + } + + protected function doUnlink($file) + { + unset(self::$valuesCache[$file]); + + if (self::isSupported()) { + @opcache_invalidate($file, true); + } + + return @unlink($file); + } + + private function getFileKey(string $file): string + { + if (!$h = @fopen($file, 'rb')) { + return ''; + } + + $encodedKey = substr(fgets($h), 8); + fclose($h); + + return rawurldecode(rtrim($encodedKey)); + } +} + +/** + * @internal + */ +class LazyValue +{ + public $file; + + public function __construct($file) + { + $this->file = $file; + } +} diff --git a/vendor/symfony/cache/Adapter/ProxyAdapter.php b/vendor/symfony/cache/Adapter/ProxyAdapter.php new file mode 100644 index 0000000..bd96fa8 --- /dev/null +++ b/vendor/symfony/cache/Adapter/ProxyAdapter.php @@ -0,0 +1,265 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ContractsTrait; +use Symfony\Component\Cache\Traits\ProxyTrait; +use Symfony\Contracts\Cache\CacheInterface; + +/** + * @author Nicolas Grekas + */ +class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface +{ + use ProxyTrait; + use ContractsTrait; + + private $namespace; + private $namespaceLen; + private $createCacheItem; + private $setInnerItem; + private $poolHash; + + public function __construct(CacheItemPoolInterface $pool, string $namespace = '', int $defaultLifetime = 0) + { + $this->pool = $pool; + $this->poolHash = $poolHash = spl_object_hash($pool); + $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace); + $this->namespaceLen = \strlen($namespace); + $this->createCacheItem = \Closure::bind( + static function ($key, $innerItem) use ($defaultLifetime, $poolHash) { + $item = new CacheItem(); + $item->key = $key; + + if (null === $innerItem) { + return $item; + } + + $item->value = $v = $innerItem->get(); + $item->isHit = $innerItem->isHit(); + $item->innerItem = $innerItem; + $item->defaultLifetime = $defaultLifetime; + $item->poolHash = $poolHash; + + // Detect wrapped values that encode for their expiry and creation duration + // For compactness, these values are packed in the key of an array using + // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F + if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = key($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) { + $item->value = $v[$k]; + $v = unpack('Ve/Nc', substr($k, 1, -1)); + $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; + $item->metadata[CacheItem::METADATA_CTIME] = $v['c']; + } elseif ($innerItem instanceof CacheItem) { + $item->metadata = $innerItem->metadata; + } + $innerItem->set(null); + + return $item; + }, + null, + CacheItem::class + ); + $this->setInnerItem = \Closure::bind( + /** + * @param array $item A CacheItem cast to (array); accessing protected properties requires adding the "\0*\0" PHP prefix + */ + static function (CacheItemInterface $innerItem, array $item) { + // Tags are stored separately, no need to account for them when considering this item's newly set metadata + if (isset(($metadata = $item["\0*\0newMetadata"])[CacheItem::METADATA_TAGS])) { + unset($metadata[CacheItem::METADATA_TAGS]); + } + if ($metadata) { + // For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators + $item["\0*\0value"] = ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item["\0*\0value"]]; + } + $innerItem->set($item["\0*\0value"]); + $innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6f', $item["\0*\0expiry"])) : null); + }, + null, + CacheItem::class + ); + } + + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + if (!$this->pool instanceof CacheInterface) { + return $this->doGet($this, $key, $callback, $beta, $metadata); + } + + return $this->pool->get($this->getId($key), function ($innerItem, bool &$save) use ($key, $callback) { + $item = ($this->createCacheItem)($key, $innerItem); + $item->set($value = $callback($item, $save)); + ($this->setInnerItem)($innerItem, (array) $item); + + return $value; + }, $beta, $metadata); + } + + /** + * {@inheritdoc} + */ + public function getItem($key) + { + $f = $this->createCacheItem; + $item = $this->pool->getItem($this->getId($key)); + + return $f($key, $item); + } + + /** + * {@inheritdoc} + */ + public function getItems(array $keys = []) + { + if ($this->namespaceLen) { + foreach ($keys as $i => $key) { + $keys[$i] = $this->getId($key); + } + } + + return $this->generateItems($this->pool->getItems($keys)); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function hasItem($key) + { + return $this->pool->hasItem($this->getId($key)); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function clear(string $prefix = '') + { + if ($this->pool instanceof AdapterInterface) { + return $this->pool->clear($this->namespace.$prefix); + } + + return $this->pool->clear(); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItem($key) + { + return $this->pool->deleteItem($this->getId($key)); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItems(array $keys) + { + if ($this->namespaceLen) { + foreach ($keys as $i => $key) { + $keys[$i] = $this->getId($key); + } + } + + return $this->pool->deleteItems($keys); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function save(CacheItemInterface $item) + { + return $this->doSave($item, __FUNCTION__); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function saveDeferred(CacheItemInterface $item) + { + return $this->doSave($item, __FUNCTION__); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function commit() + { + return $this->pool->commit(); + } + + private function doSave(CacheItemInterface $item, string $method) + { + if (!$item instanceof CacheItem) { + return false; + } + $item = (array) $item; + if (null === $item["\0*\0expiry"] && 0 < $item["\0*\0defaultLifetime"]) { + $item["\0*\0expiry"] = microtime(true) + $item["\0*\0defaultLifetime"]; + } + + if ($item["\0*\0poolHash"] === $this->poolHash && $item["\0*\0innerItem"]) { + $innerItem = $item["\0*\0innerItem"]; + } elseif ($this->pool instanceof AdapterInterface) { + // this is an optimization specific for AdapterInterface implementations + // so we can save a round-trip to the backend by just creating a new item + $f = $this->createCacheItem; + $innerItem = $f($this->namespace.$item["\0*\0key"], null); + } else { + $innerItem = $this->pool->getItem($this->namespace.$item["\0*\0key"]); + } + + ($this->setInnerItem)($innerItem, $item); + + return $this->pool->$method($innerItem); + } + + private function generateItems(iterable $items) + { + $f = $this->createCacheItem; + + foreach ($items as $key => $item) { + if ($this->namespaceLen) { + $key = substr($key, $this->namespaceLen); + } + + yield $key => $f($key, $item); + } + } + + private function getId($key): string + { + CacheItem::validateKey($key); + + return $this->namespace.$key; + } +} diff --git a/vendor/symfony/cache/Adapter/Psr16Adapter.php b/vendor/symfony/cache/Adapter/Psr16Adapter.php new file mode 100644 index 0000000..a13b20e --- /dev/null +++ b/vendor/symfony/cache/Adapter/Psr16Adapter.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\SimpleCache\CacheInterface; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ProxyTrait; + +/** + * Turns a PSR-16 cache into a PSR-6 one. + * + * @author Nicolas Grekas + */ +class Psr16Adapter extends AbstractAdapter implements PruneableInterface, ResettableInterface +{ + /** + * @internal + */ + protected const NS_SEPARATOR = '_'; + + use ProxyTrait; + + private $miss; + + public function __construct(CacheInterface $pool, string $namespace = '', int $defaultLifetime = 0) + { + parent::__construct($namespace, $defaultLifetime); + + $this->pool = $pool; + $this->miss = new \stdClass(); + } + + /** + * {@inheritdoc} + */ + protected function doFetch(array $ids) + { + foreach ($this->pool->getMultiple($ids, $this->miss) as $key => $value) { + if ($this->miss !== $value) { + yield $key => $value; + } + } + } + + /** + * {@inheritdoc} + */ + protected function doHave(string $id) + { + return $this->pool->has($id); + } + + /** + * {@inheritdoc} + */ + protected function doClear(string $namespace) + { + return $this->pool->clear(); + } + + /** + * {@inheritdoc} + */ + protected function doDelete(array $ids) + { + return $this->pool->deleteMultiple($ids); + } + + /** + * {@inheritdoc} + */ + protected function doSave(array $values, int $lifetime) + { + return $this->pool->setMultiple($values, 0 === $lifetime ? null : $lifetime); + } +} diff --git a/vendor/symfony/cache/Adapter/RedisAdapter.php b/vendor/symfony/cache/Adapter/RedisAdapter.php new file mode 100644 index 0000000..5c49f7a --- /dev/null +++ b/vendor/symfony/cache/Adapter/RedisAdapter.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\Traits\RedisTrait; + +class RedisAdapter extends AbstractAdapter +{ + use RedisTrait; + + /** + * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface $redisClient The redis client + * @param string $namespace The default namespace + * @param int $defaultLifetime The default lifetime + */ + public function __construct($redisClient, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) + { + $this->init($redisClient, $namespace, $defaultLifetime, $marshaller); + } +} diff --git a/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php b/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php new file mode 100644 index 0000000..acdfa88 --- /dev/null +++ b/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php @@ -0,0 +1,292 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Predis\Connection\Aggregate\ClusterInterface; +use Predis\Connection\Aggregate\PredisCluster; +use Predis\Response\Status; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Marshaller\DeflateMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\Marshaller\TagAwareMarshaller; +use Symfony\Component\Cache\Traits\RedisTrait; + +/** + * Stores tag id <> cache id relationship as a Redis Set, lookup on invalidation using RENAME+SMEMBERS. + * + * Set (tag relation info) is stored without expiry (non-volatile), while cache always gets an expiry (volatile) even + * if not set by caller. Thus if you configure redis with the right eviction policy you can be safe this tag <> cache + * relationship survives eviction (cache cleanup when Redis runs out of memory). + * + * Requirements: + * - Client: PHP Redis or Predis + * Note: Due to lack of RENAME support it is NOT recommended to use Cluster on Predis, instead use phpredis. + * - Server: Redis 2.8+ + * Configured with any `volatile-*` eviction policy, OR `noeviction` if it will NEVER fill up memory + * + * Design limitations: + * - Max 4 billion cache keys per cache tag as limited by Redis Set datatype. + * E.g. If you use a "all" items tag for expiry instead of clear(), that limits you to 4 billion cache items also. + * + * @see https://redis.io/topics/lru-cache#eviction-policies Documentation for Redis eviction policies. + * @see https://redis.io/topics/data-types#sets Documentation for Redis Set datatype. + * + * @author Nicolas Grekas + * @author André Rømcke + */ +class RedisTagAwareAdapter extends AbstractTagAwareAdapter +{ + use RedisTrait; + + /** + * Limits for how many keys are deleted in batch. + */ + private const BULK_DELETE_LIMIT = 10000; + + /** + * On cache items without a lifetime set, we set it to 100 days. This is to make sure cache items are + * preferred to be evicted over tag Sets, if eviction policy is configured according to requirements. + */ + private const DEFAULT_CACHE_TTL = 8640000; + + /** + * @var string|null detected eviction policy used on Redis server + */ + private $redisEvictionPolicy; + + /** + * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface $redisClient The redis client + * @param string $namespace The default namespace + * @param int $defaultLifetime The default lifetime + */ + public function __construct($redisClient, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) + { + if ($redisClient instanceof \Predis\ClientInterface && $redisClient->getConnection() instanceof ClusterInterface && !$redisClient->getConnection() instanceof PredisCluster) { + throw new InvalidArgumentException(sprintf('Unsupported Predis cluster connection: only "%s" is, "%s" given.', PredisCluster::class, \get_class($redisClient->getConnection()))); + } + + if (\defined('Redis::OPT_COMPRESSION') && ($redisClient instanceof \Redis || $redisClient instanceof \RedisArray || $redisClient instanceof \RedisCluster)) { + $compression = $redisClient->getOption(\Redis::OPT_COMPRESSION); + + foreach (\is_array($compression) ? $compression : [$compression] as $c) { + if (\Redis::COMPRESSION_NONE !== $c) { + throw new InvalidArgumentException(sprintf('phpredis compression must be disabled when using "%s", use "%s" instead.', \get_class($this), DeflateMarshaller::class)); + } + } + } + + $this->init($redisClient, $namespace, $defaultLifetime, new TagAwareMarshaller($marshaller)); + } + + /** + * {@inheritdoc} + */ + protected function doSave(array $values, int $lifetime, array $addTagData = [], array $delTagData = []): array + { + $eviction = $this->getRedisEvictionPolicy(); + if ('noeviction' !== $eviction && 0 !== strpos($eviction, 'volatile-')) { + CacheItem::log($this->logger, sprintf('Redis maxmemory-policy setting "%s" is *not* supported by RedisTagAwareAdapter, use "noeviction" or "volatile-*" eviction policies', $eviction)); + + return false; + } + + // serialize values + if (!$serialized = $this->marshaller->marshall($values, $failed)) { + return $failed; + } + + // While pipeline isn't supported on RedisCluster, other setups will at least benefit from doing this in one op + $results = $this->pipeline(static function () use ($serialized, $lifetime, $addTagData, $delTagData, $failed) { + // Store cache items, force a ttl if none is set, as there is no MSETEX we need to set each one + foreach ($serialized as $id => $value) { + yield 'setEx' => [ + $id, + 0 >= $lifetime ? self::DEFAULT_CACHE_TTL : $lifetime, + $value, + ]; + } + + // Add and Remove Tags + foreach ($addTagData as $tagId => $ids) { + if (!$failed || $ids = array_diff($ids, $failed)) { + yield 'sAdd' => array_merge([$tagId], $ids); + } + } + + foreach ($delTagData as $tagId => $ids) { + if (!$failed || $ids = array_diff($ids, $failed)) { + yield 'sRem' => array_merge([$tagId], $ids); + } + } + }); + + foreach ($results as $id => $result) { + // Skip results of SADD/SREM operations, they'll be 1 or 0 depending on if set value already existed or not + if (is_numeric($result)) { + continue; + } + // setEx results + if (true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) { + $failed[] = $id; + } + } + + return $failed; + } + + /** + * {@inheritdoc} + */ + protected function doDeleteYieldTags(array $ids): iterable + { + $lua = <<<'EOLUA' + local v = redis.call('GET', KEYS[1]) + redis.call('DEL', KEYS[1]) + + if not v or v:len() <= 13 or v:byte(1) ~= 0x9D or v:byte(6) ~= 0 or v:byte(10) ~= 0x5F then + return '' + end + + return v:sub(14, 13 + v:byte(13) + v:byte(12) * 256 + v:byte(11) * 65536) +EOLUA; + + if ($this->redis instanceof \Predis\ClientInterface) { + $evalArgs = [$lua, 1, &$id]; + } else { + $evalArgs = [$lua, [&$id], 1]; + } + + $results = $this->pipeline(function () use ($ids, &$id, $evalArgs) { + foreach ($ids as $id) { + yield 'eval' => $evalArgs; + } + }); + + foreach ($results as $id => $result) { + try { + yield $id => !\is_string($result) || '' === $result ? [] : $this->marshaller->unmarshall($result); + } catch (\Exception $e) { + yield $id => []; + } + } + } + + /** + * {@inheritdoc} + */ + protected function doDeleteTagRelations(array $tagData): bool + { + $this->pipeline(static function () use ($tagData) { + foreach ($tagData as $tagId => $idList) { + array_unshift($idList, $tagId); + yield 'sRem' => $idList; + } + })->rewind(); + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doInvalidate(array $tagIds): bool + { + if (!$this->redis instanceof \Predis\ClientInterface || !$this->redis->getConnection() instanceof PredisCluster) { + $movedTagSetIds = $this->renameKeys($this->redis, $tagIds); + } else { + $clusterConnection = $this->redis->getConnection(); + $tagIdsByConnection = new \SplObjectStorage(); + $movedTagSetIds = []; + + foreach ($tagIds as $id) { + $connection = $clusterConnection->getConnectionByKey($id); + $slot = $tagIdsByConnection[$connection] ?? $tagIdsByConnection[$connection] = new \ArrayObject(); + $slot[] = $id; + } + + foreach ($tagIdsByConnection as $connection) { + $slot = $tagIdsByConnection[$connection]; + $movedTagSetIds = array_merge($movedTagSetIds, $this->renameKeys(new $this->redis($connection, $this->redis->getOptions()), $slot->getArrayCopy())); + } + } + + // No Sets found + if (!$movedTagSetIds) { + return false; + } + + // Now safely take the time to read the keys in each set and collect ids we need to delete + $tagIdSets = $this->pipeline(static function () use ($movedTagSetIds) { + foreach ($movedTagSetIds as $movedTagId) { + yield 'sMembers' => [$movedTagId]; + } + }); + + // Return combination of the temporary Tag Set ids and their values (cache ids) + $ids = array_merge($movedTagSetIds, ...iterator_to_array($tagIdSets, false)); + + // Delete cache in chunks to avoid overloading the connection + foreach (array_chunk(array_unique($ids), self::BULK_DELETE_LIMIT) as $chunkIds) { + $this->doDelete($chunkIds); + } + + return true; + } + + /** + * Renames several keys in order to be able to operate on them without risk of race conditions. + * + * Filters out keys that do not exist before returning new keys. + * + * @see https://redis.io/commands/rename + * @see https://redis.io/topics/cluster-spec#keys-hash-tags + * + * @return array Filtered list of the valid moved keys (only those that existed) + */ + private function renameKeys($redis, array $ids): array + { + $newIds = []; + $uniqueToken = bin2hex(random_bytes(10)); + + $results = $this->pipeline(static function () use ($ids, $uniqueToken) { + foreach ($ids as $id) { + yield 'rename' => [$id, '{'.$id.'}'.$uniqueToken]; + } + }, $redis); + + foreach ($results as $id => $result) { + if (true === $result || ($result instanceof Status && Status::get('OK') === $result)) { + // Only take into account if ok (key existed), will be false on phpredis if it did not exist + $newIds[] = '{'.$id.'}'.$uniqueToken; + } + } + + return $newIds; + } + + private function getRedisEvictionPolicy(): string + { + if (null !== $this->redisEvictionPolicy) { + return $this->redisEvictionPolicy; + } + + foreach ($this->getHosts() as $host) { + $info = $host->info('Memory'); + $info = isset($info['Memory']) ? $info['Memory'] : $info; + + return $this->redisEvictionPolicy = $info['maxmemory_policy']; + } + + return $this->redisEvictionPolicy = ''; + } +} diff --git a/vendor/symfony/cache/Adapter/TagAwareAdapter.php b/vendor/symfony/cache/Adapter/TagAwareAdapter.php new file mode 100644 index 0000000..793df43 --- /dev/null +++ b/vendor/symfony/cache/Adapter/TagAwareAdapter.php @@ -0,0 +1,425 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Psr\Cache\InvalidArgumentException; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ContractsTrait; +use Symfony\Component\Cache\Traits\ProxyTrait; +use Symfony\Contracts\Cache\TagAwareCacheInterface; + +/** + * @author Nicolas Grekas + */ +class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, PruneableInterface, ResettableInterface +{ + const TAGS_PREFIX = "\0tags\0"; + + use ProxyTrait; + use ContractsTrait; + + private $deferred = []; + private $createCacheItem; + private $setCacheItemTags; + private $getTagsByKey; + private $invalidateTags; + private $tags; + private $knownTagVersions = []; + private $knownTagVersionsTtl; + + public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15) + { + $this->pool = $itemsPool; + $this->tags = $tagsPool ?: $itemsPool; + $this->knownTagVersionsTtl = $knownTagVersionsTtl; + $this->createCacheItem = \Closure::bind( + static function ($key, $value, CacheItem $protoItem) { + $item = new CacheItem(); + $item->key = $key; + $item->value = $value; + $item->defaultLifetime = $protoItem->defaultLifetime; + $item->expiry = $protoItem->expiry; + $item->poolHash = $protoItem->poolHash; + + return $item; + }, + null, + CacheItem::class + ); + $this->setCacheItemTags = \Closure::bind( + static function (CacheItem $item, $key, array &$itemTags) { + $item->isTaggable = true; + if (!$item->isHit) { + return $item; + } + if (isset($itemTags[$key])) { + foreach ($itemTags[$key] as $tag => $version) { + $item->metadata[CacheItem::METADATA_TAGS][$tag] = $tag; + } + unset($itemTags[$key]); + } else { + $item->value = null; + $item->isHit = false; + } + + return $item; + }, + null, + CacheItem::class + ); + $this->getTagsByKey = \Closure::bind( + static function ($deferred) { + $tagsByKey = []; + foreach ($deferred as $key => $item) { + $tagsByKey[$key] = $item->newMetadata[CacheItem::METADATA_TAGS] ?? []; + } + + return $tagsByKey; + }, + null, + CacheItem::class + ); + $this->invalidateTags = \Closure::bind( + static function (AdapterInterface $tagsAdapter, array $tags) { + foreach ($tags as $v) { + $v->defaultLifetime = 0; + $v->expiry = null; + $tagsAdapter->saveDeferred($v); + } + + return $tagsAdapter->commit(); + }, + null, + CacheItem::class + ); + } + + /** + * {@inheritdoc} + */ + public function invalidateTags(array $tags) + { + $ok = true; + $tagsByKey = []; + $invalidatedTags = []; + foreach ($tags as $tag) { + CacheItem::validateKey($tag); + $invalidatedTags[$tag] = 0; + } + + if ($this->deferred) { + $items = $this->deferred; + foreach ($items as $key => $item) { + if (!$this->pool->saveDeferred($item)) { + unset($this->deferred[$key]); + $ok = false; + } + } + + $f = $this->getTagsByKey; + $tagsByKey = $f($items); + $this->deferred = []; + } + + $tagVersions = $this->getTagVersions($tagsByKey, $invalidatedTags); + $f = $this->createCacheItem; + + foreach ($tagsByKey as $key => $tags) { + $this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key])); + } + $ok = $this->pool->commit() && $ok; + + if ($invalidatedTags) { + $f = $this->invalidateTags; + $ok = $f($this->tags, $invalidatedTags) && $ok; + } + + return $ok; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function hasItem($key) + { + if ($this->deferred) { + $this->commit(); + } + if (!$this->pool->hasItem($key)) { + return false; + } + + $itemTags = $this->pool->getItem(static::TAGS_PREFIX.$key); + + if (!$itemTags->isHit()) { + return false; + } + + if (!$itemTags = $itemTags->get()) { + return true; + } + + foreach ($this->getTagVersions([$itemTags]) as $tag => $version) { + if ($itemTags[$tag] !== $version && 1 !== $itemTags[$tag] - $version) { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function getItem($key) + { + foreach ($this->getItems([$key]) as $item) { + return $item; + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function getItems(array $keys = []) + { + if ($this->deferred) { + $this->commit(); + } + $tagKeys = []; + + foreach ($keys as $key) { + if ('' !== $key && \is_string($key)) { + $key = static::TAGS_PREFIX.$key; + $tagKeys[$key] = $key; + } + } + + try { + $items = $this->pool->getItems($tagKeys + $keys); + } catch (InvalidArgumentException $e) { + $this->pool->getItems($keys); // Should throw an exception + + throw $e; + } + + return $this->generateItems($items, $tagKeys); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function clear(string $prefix = '') + { + if ('' !== $prefix) { + foreach ($this->deferred as $key => $item) { + if (0 === strpos($key, $prefix)) { + unset($this->deferred[$key]); + } + } + } else { + $this->deferred = []; + } + + if ($this->pool instanceof AdapterInterface) { + return $this->pool->clear($prefix); + } + + return $this->pool->clear(); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItem($key) + { + return $this->deleteItems([$key]); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItems(array $keys) + { + foreach ($keys as $key) { + if ('' !== $key && \is_string($key)) { + $keys[] = static::TAGS_PREFIX.$key; + } + } + + return $this->pool->deleteItems($keys); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function save(CacheItemInterface $item) + { + if (!$item instanceof CacheItem) { + return false; + } + $this->deferred[$item->getKey()] = $item; + + return $this->commit(); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function saveDeferred(CacheItemInterface $item) + { + if (!$item instanceof CacheItem) { + return false; + } + $this->deferred[$item->getKey()] = $item; + + return true; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function commit() + { + return $this->invalidateTags([]); + } + + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + public function __destruct() + { + $this->commit(); + } + + private function generateItems(iterable $items, array $tagKeys) + { + $bufferedItems = $itemTags = []; + $f = $this->setCacheItemTags; + + foreach ($items as $key => $item) { + if (!$tagKeys) { + yield $key => $f($item, static::TAGS_PREFIX.$key, $itemTags); + continue; + } + if (!isset($tagKeys[$key])) { + $bufferedItems[$key] = $item; + continue; + } + + unset($tagKeys[$key]); + + if ($item->isHit()) { + $itemTags[$key] = $item->get() ?: []; + } + + if (!$tagKeys) { + $tagVersions = $this->getTagVersions($itemTags); + + foreach ($itemTags as $key => $tags) { + foreach ($tags as $tag => $version) { + if ($tagVersions[$tag] !== $version && 1 !== $version - $tagVersions[$tag]) { + unset($itemTags[$key]); + continue 2; + } + } + } + $tagVersions = $tagKeys = null; + + foreach ($bufferedItems as $key => $item) { + yield $key => $f($item, static::TAGS_PREFIX.$key, $itemTags); + } + $bufferedItems = null; + } + } + } + + private function getTagVersions(array $tagsByKey, array &$invalidatedTags = []) + { + $tagVersions = $invalidatedTags; + + foreach ($tagsByKey as $tags) { + $tagVersions += $tags; + } + + if (!$tagVersions) { + return []; + } + + if (!$fetchTagVersions = 1 !== \func_num_args()) { + foreach ($tagsByKey as $tags) { + foreach ($tags as $tag => $version) { + if ($tagVersions[$tag] > $version) { + $tagVersions[$tag] = $version; + } + } + } + } + + $now = microtime(true); + $tags = []; + foreach ($tagVersions as $tag => $version) { + $tags[$tag.static::TAGS_PREFIX] = $tag; + if ($fetchTagVersions || !isset($this->knownTagVersions[$tag])) { + $fetchTagVersions = true; + continue; + } + $version -= $this->knownTagVersions[$tag][1]; + if ((0 !== $version && 1 !== $version) || $now - $this->knownTagVersions[$tag][0] >= $this->knownTagVersionsTtl) { + // reuse previously fetched tag versions up to the ttl, unless we are storing items or a potential miss arises + $fetchTagVersions = true; + } else { + $this->knownTagVersions[$tag][1] += $version; + } + } + + if (!$fetchTagVersions) { + return $tagVersions; + } + + foreach ($this->tags->getItems(array_keys($tags)) as $tag => $version) { + $tagVersions[$tag = $tags[$tag]] = $version->get() ?: 0; + if (isset($invalidatedTags[$tag])) { + $invalidatedTags[$tag] = $version->set(++$tagVersions[$tag]); + } + $this->knownTagVersions[$tag] = [$now, $tagVersions[$tag]]; + } + + return $tagVersions; + } +} diff --git a/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php b/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php new file mode 100644 index 0000000..340048c --- /dev/null +++ b/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\InvalidArgumentException; + +/** + * Interface for invalidating cached items using tags. + * + * @author Nicolas Grekas + */ +interface TagAwareAdapterInterface extends AdapterInterface +{ + /** + * Invalidates cached items using tags. + * + * @param string[] $tags An array of tags to invalidate + * + * @return bool True on success + * + * @throws InvalidArgumentException When $tags is not valid + */ + public function invalidateTags(array $tags); +} diff --git a/vendor/symfony/cache/Adapter/TraceableAdapter.php b/vendor/symfony/cache/Adapter/TraceableAdapter.php new file mode 100644 index 0000000..16d819e --- /dev/null +++ b/vendor/symfony/cache/Adapter/TraceableAdapter.php @@ -0,0 +1,299 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Psr\Cache\CacheItemInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Contracts\Cache\CacheInterface; +use Symfony\Contracts\Service\ResetInterface; + +/** + * An adapter that collects data about all cache calls. + * + * @author Aaron Scherer + * @author Tobias Nyholm + * @author Nicolas Grekas + */ +class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface +{ + protected $pool; + private $calls = []; + + public function __construct(AdapterInterface $pool) + { + $this->pool = $pool; + } + + /** + * {@inheritdoc} + */ + public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) + { + if (!$this->pool instanceof CacheInterface) { + throw new \BadMethodCallException(sprintf('Cannot call "%s::get()": this class doesn\'t implement "%s".', \get_class($this->pool), CacheInterface::class)); + } + + $isHit = true; + $callback = function (CacheItem $item, bool &$save) use ($callback, &$isHit) { + $isHit = $item->isHit(); + + return $callback($item, $save); + }; + + $event = $this->start(__FUNCTION__); + try { + $value = $this->pool->get($key, $callback, $beta, $metadata); + $event->result[$key] = \is_object($value) ? \get_class($value) : \gettype($value); + } finally { + $event->end = microtime(true); + } + if ($isHit) { + ++$event->hits; + } else { + ++$event->misses; + } + + return $value; + } + + /** + * {@inheritdoc} + */ + public function getItem($key) + { + $event = $this->start(__FUNCTION__); + try { + $item = $this->pool->getItem($key); + } finally { + $event->end = microtime(true); + } + if ($event->result[$key] = $item->isHit()) { + ++$event->hits; + } else { + ++$event->misses; + } + + return $item; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function hasItem($key) + { + $event = $this->start(__FUNCTION__); + try { + return $event->result[$key] = $this->pool->hasItem($key); + } finally { + $event->end = microtime(true); + } + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItem($key) + { + $event = $this->start(__FUNCTION__); + try { + return $event->result[$key] = $this->pool->deleteItem($key); + } finally { + $event->end = microtime(true); + } + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function save(CacheItemInterface $item) + { + $event = $this->start(__FUNCTION__); + try { + return $event->result[$item->getKey()] = $this->pool->save($item); + } finally { + $event->end = microtime(true); + } + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function saveDeferred(CacheItemInterface $item) + { + $event = $this->start(__FUNCTION__); + try { + return $event->result[$item->getKey()] = $this->pool->saveDeferred($item); + } finally { + $event->end = microtime(true); + } + } + + /** + * {@inheritdoc} + */ + public function getItems(array $keys = []) + { + $event = $this->start(__FUNCTION__); + try { + $result = $this->pool->getItems($keys); + } finally { + $event->end = microtime(true); + } + $f = function () use ($result, $event) { + $event->result = []; + foreach ($result as $key => $item) { + if ($event->result[$key] = $item->isHit()) { + ++$event->hits; + } else { + ++$event->misses; + } + yield $key => $item; + } + }; + + return $f(); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function clear(string $prefix = '') + { + $event = $this->start(__FUNCTION__); + try { + if ($this->pool instanceof AdapterInterface) { + return $event->result = $this->pool->clear($prefix); + } + + return $event->result = $this->pool->clear(); + } finally { + $event->end = microtime(true); + } + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItems(array $keys) + { + $event = $this->start(__FUNCTION__); + $event->result['keys'] = $keys; + try { + return $event->result['result'] = $this->pool->deleteItems($keys); + } finally { + $event->end = microtime(true); + } + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function commit() + { + $event = $this->start(__FUNCTION__); + try { + return $event->result = $this->pool->commit(); + } finally { + $event->end = microtime(true); + } + } + + /** + * {@inheritdoc} + */ + public function prune() + { + if (!$this->pool instanceof PruneableInterface) { + return false; + } + $event = $this->start(__FUNCTION__); + try { + return $event->result = $this->pool->prune(); + } finally { + $event->end = microtime(true); + } + } + + /** + * {@inheritdoc} + */ + public function reset() + { + if (!$this->pool instanceof ResetInterface) { + return; + } + $event = $this->start(__FUNCTION__); + try { + $this->pool->reset(); + } finally { + $event->end = microtime(true); + } + } + + /** + * {@inheritdoc} + */ + public function delete(string $key): bool + { + $event = $this->start(__FUNCTION__); + try { + return $event->result[$key] = $this->pool->deleteItem($key); + } finally { + $event->end = microtime(true); + } + } + + public function getCalls() + { + return $this->calls; + } + + public function clearCalls() + { + $this->calls = []; + } + + protected function start($name) + { + $this->calls[] = $event = new TraceableAdapterEvent(); + $event->name = $name; + $event->start = microtime(true); + + return $event; + } +} + +class TraceableAdapterEvent +{ + public $name; + public $start; + public $end; + public $result; + public $hits = 0; + public $misses = 0; +} diff --git a/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php b/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php new file mode 100644 index 0000000..69461b8 --- /dev/null +++ b/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +use Symfony\Contracts\Cache\TagAwareCacheInterface; + +/** + * @author Robin Chalas + */ +class TraceableTagAwareAdapter extends TraceableAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface +{ + public function __construct(TagAwareAdapterInterface $pool) + { + parent::__construct($pool); + } + + /** + * {@inheritdoc} + */ + public function invalidateTags(array $tags) + { + $event = $this->start(__FUNCTION__); + try { + return $event->result = $this->pool->invalidateTags($tags); + } finally { + $event->end = microtime(true); + } + } +} diff --git a/vendor/symfony/cache/CHANGELOG.md b/vendor/symfony/cache/CHANGELOG.md new file mode 100644 index 0000000..2f2b249 --- /dev/null +++ b/vendor/symfony/cache/CHANGELOG.md @@ -0,0 +1,81 @@ +CHANGELOG +========= + +5.0.0 +----- + + * removed all PSR-16 implementations in the `Simple` namespace + * removed `SimpleCacheAdapter` + * removed `AbstractAdapter::unserialize()` + * removed `CacheItem::getPreviousTags()` + +4.4.0 +----- + + * added support for connecting to Redis Sentinel clusters + * added argument `$prefix` to `AdapterInterface::clear()` + * improved `RedisTagAwareAdapter` to support Redis server >= 2.8 and up to 4B items per tag + * added `TagAwareMarshaller` for optimized data storage when using `AbstractTagAwareAdapter` + * added `DeflateMarshaller` to compress serialized values + * removed support for phpredis 4 `compression` + * [BC BREAK] `RedisTagAwareAdapter` is not compatible with `RedisCluster` from `Predis` anymore, use `phpredis` instead + * Marked the `CacheDataCollector` class as `@final`. + +4.3.0 +----- + + * removed `psr/simple-cache` dependency, run `composer require psr/simple-cache` if you need it + * deprecated all PSR-16 adapters, use `Psr16Cache` or `Symfony\Contracts\Cache\CacheInterface` implementations instead + * deprecated `SimpleCacheAdapter`, use `Psr16Adapter` instead + +4.2.0 +----- + + * added support for connecting to Redis clusters via DSN + * added support for configuring multiple Memcached servers via DSN + * added `MarshallerInterface` and `DefaultMarshaller` to allow changing the serializer and provide one that automatically uses igbinary when available + * implemented `CacheInterface`, which provides stampede protection via probabilistic early expiration and should become the preferred way to use a cache + * added sub-second expiry accuracy for backends that support it + * added support for phpredis 4 `compression` and `tcp_keepalive` options + * added automatic table creation when using Doctrine DBAL with PDO-based backends + * throw `LogicException` when `CacheItem::tag()` is called on an item coming from a non tag-aware pool + * deprecated `CacheItem::getPreviousTags()`, use `CacheItem::getMetadata()` instead + * deprecated the `AbstractAdapter::unserialize()` and `AbstractCache::unserialize()` methods + * added `CacheCollectorPass` (originally in `FrameworkBundle`) + * added `CachePoolClearerPass` (originally in `FrameworkBundle`) + * added `CachePoolPass` (originally in `FrameworkBundle`) + * added `CachePoolPrunerPass` (originally in `FrameworkBundle`) + +3.4.0 +----- + + * added using options from Memcached DSN + * added PruneableInterface so PSR-6 or PSR-16 cache implementations can declare support for manual stale cache pruning + * added prune logic to FilesystemTrait, PhpFilesTrait, PdoTrait, TagAwareAdapter and ChainTrait + * now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, PhpFilesCache, PdoAdapter, PdoCache, ChainAdapter, and + ChainCache implement PruneableInterface and support manual stale cache pruning + +3.3.0 +----- + + * added CacheItem::getPreviousTags() to get bound tags coming from the pool storage if any + * added PSR-16 "Simple Cache" implementations for all existing PSR-6 adapters + * added Psr6Cache and SimpleCacheAdapter for bidirectional interoperability between PSR-6 and PSR-16 + * added MemcachedAdapter (PSR-6) and MemcachedCache (PSR-16) + * added TraceableAdapter (PSR-6) and TraceableCache (PSR-16) + +3.2.0 +----- + + * added TagAwareAdapter for tags-based invalidation + * added PdoAdapter with PDO and Doctrine DBAL support + * added PhpArrayAdapter and PhpFilesAdapter for OPcache-backed shared memory storage (PHP 7+ only) + * added NullAdapter + +3.1.0 +----- + + * added the component with strict PSR-6 implementations + * added ApcuAdapter, ArrayAdapter, FilesystemAdapter and RedisAdapter + * added AbstractAdapter, ChainAdapter and ProxyAdapter + * added DoctrineAdapter and DoctrineProvider for bidirectional interoperability with Doctrine Cache diff --git a/vendor/symfony/cache/CacheItem.php b/vendor/symfony/cache/CacheItem.php new file mode 100644 index 0000000..5880803 --- /dev/null +++ b/vendor/symfony/cache/CacheItem.php @@ -0,0 +1,190 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Exception\LogicException; +use Symfony\Contracts\Cache\ItemInterface; + +/** + * @author Nicolas Grekas + */ +final class CacheItem implements ItemInterface +{ + private const METADATA_EXPIRY_OFFSET = 1527506807; + + protected $key; + protected $value; + protected $isHit = false; + protected $expiry; + protected $defaultLifetime; + protected $metadata = []; + protected $newMetadata = []; + protected $innerItem; + protected $poolHash; + protected $isTaggable = false; + + /** + * {@inheritdoc} + */ + public function getKey(): string + { + return $this->key; + } + + /** + * {@inheritdoc} + */ + public function get() + { + return $this->value; + } + + /** + * {@inheritdoc} + */ + public function isHit(): bool + { + return $this->isHit; + } + + /** + * {@inheritdoc} + * + * @return $this + */ + public function set($value): self + { + $this->value = $value; + + return $this; + } + + /** + * {@inheritdoc} + * + * @return $this + */ + public function expiresAt($expiration): self + { + if (null === $expiration) { + $this->expiry = $this->defaultLifetime > 0 ? microtime(true) + $this->defaultLifetime : null; + } elseif ($expiration instanceof \DateTimeInterface) { + $this->expiry = (float) $expiration->format('U.u'); + } else { + throw new InvalidArgumentException(sprintf('Expiration date must implement DateTimeInterface or be null, "%s" given', \is_object($expiration) ? \get_class($expiration) : \gettype($expiration))); + } + + return $this; + } + + /** + * {@inheritdoc} + * + * @return $this + */ + public function expiresAfter($time): self + { + if (null === $time) { + $this->expiry = $this->defaultLifetime > 0 ? microtime(true) + $this->defaultLifetime : null; + } elseif ($time instanceof \DateInterval) { + $this->expiry = microtime(true) + \DateTime::createFromFormat('U', 0)->add($time)->format('U.u'); + } elseif (\is_int($time)) { + $this->expiry = $time + microtime(true); + } else { + throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given', \is_object($time) ? \get_class($time) : \gettype($time))); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function tag($tags): ItemInterface + { + if (!$this->isTaggable) { + throw new LogicException(sprintf('Cache item "%s" comes from a non tag-aware pool: you cannot tag it.', $this->key)); + } + if (!is_iterable($tags)) { + $tags = [$tags]; + } + foreach ($tags as $tag) { + if (!\is_string($tag)) { + throw new InvalidArgumentException(sprintf('Cache tag must be string, "%s" given', \is_object($tag) ? \get_class($tag) : \gettype($tag))); + } + if (isset($this->newMetadata[self::METADATA_TAGS][$tag])) { + continue; + } + if ('' === $tag) { + throw new InvalidArgumentException('Cache tag length must be greater than zero'); + } + if (false !== strpbrk($tag, self::RESERVED_CHARACTERS)) { + throw new InvalidArgumentException(sprintf('Cache tag "%s" contains reserved characters %s', $tag, self::RESERVED_CHARACTERS)); + } + $this->newMetadata[self::METADATA_TAGS][$tag] = $tag; + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getMetadata(): array + { + return $this->metadata; + } + + /** + * Validates a cache key according to PSR-6. + * + * @param string $key The key to validate + * + * @throws InvalidArgumentException When $key is not valid + */ + public static function validateKey($key): string + { + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given', \is_object($key) ? \get_class($key) : \gettype($key))); + } + if ('' === $key) { + throw new InvalidArgumentException('Cache key length must be greater than zero'); + } + if (false !== strpbrk($key, self::RESERVED_CHARACTERS)) { + throw new InvalidArgumentException(sprintf('Cache key "%s" contains reserved characters %s', $key, self::RESERVED_CHARACTERS)); + } + + return $key; + } + + /** + * Internal logging helper. + * + * @internal + */ + public static function log(?LoggerInterface $logger, string $message, array $context = []) + { + if ($logger) { + $logger->warning($message, $context); + } else { + $replace = []; + foreach ($context as $k => $v) { + if (is_scalar($v)) { + $replace['{'.$k.'}'] = $v; + } + } + @trigger_error(strtr($message, $replace), E_USER_WARNING); + } + } +} diff --git a/vendor/symfony/cache/DataCollector/CacheDataCollector.php b/vendor/symfony/cache/DataCollector/CacheDataCollector.php new file mode 100644 index 0000000..363b887 --- /dev/null +++ b/vendor/symfony/cache/DataCollector/CacheDataCollector.php @@ -0,0 +1,189 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\DataCollector; + +use Symfony\Component\Cache\Adapter\TraceableAdapter; +use Symfony\Component\Cache\Adapter\TraceableAdapterEvent; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\DataCollector; +use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; + +/** + * @author Aaron Scherer + * @author Tobias Nyholm + * + * @final + */ +class CacheDataCollector extends DataCollector implements LateDataCollectorInterface +{ + /** + * @var TraceableAdapter[] + */ + private $instances = []; + + public function addInstance(string $name, TraceableAdapter $instance) + { + $this->instances[$name] = $instance; + } + + /** + * {@inheritdoc} + */ + public function collect(Request $request, Response $response, \Throwable $exception = null) + { + $empty = ['calls' => [], 'config' => [], 'options' => [], 'statistics' => []]; + $this->data = ['instances' => $empty, 'total' => $empty]; + foreach ($this->instances as $name => $instance) { + $this->data['instances']['calls'][$name] = $instance->getCalls(); + } + + $this->data['instances']['statistics'] = $this->calculateStatistics(); + $this->data['total']['statistics'] = $this->calculateTotalStatistics(); + } + + public function reset() + { + $this->data = []; + foreach ($this->instances as $instance) { + $instance->clearCalls(); + } + } + + public function lateCollect() + { + $this->data = $this->cloneVar($this->data); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'cache'; + } + + /** + * Method returns amount of logged Cache reads: "get" calls. + * + * @return array + */ + public function getStatistics() + { + return $this->data['instances']['statistics']; + } + + /** + * Method returns the statistic totals. + * + * @return array + */ + public function getTotals() + { + return $this->data['total']['statistics']; + } + + /** + * Method returns all logged Cache call objects. + * + * @return mixed + */ + public function getCalls() + { + return $this->data['instances']['calls']; + } + + private function calculateStatistics(): array + { + $statistics = []; + foreach ($this->data['instances']['calls'] as $name => $calls) { + $statistics[$name] = [ + 'calls' => 0, + 'time' => 0, + 'reads' => 0, + 'writes' => 0, + 'deletes' => 0, + 'hits' => 0, + 'misses' => 0, + ]; + /** @var TraceableAdapterEvent $call */ + foreach ($calls as $call) { + ++$statistics[$name]['calls']; + $statistics[$name]['time'] += $call->end - $call->start; + if ('get' === $call->name) { + ++$statistics[$name]['reads']; + if ($call->hits) { + ++$statistics[$name]['hits']; + } else { + ++$statistics[$name]['misses']; + ++$statistics[$name]['writes']; + } + } elseif ('getItem' === $call->name) { + ++$statistics[$name]['reads']; + if ($call->hits) { + ++$statistics[$name]['hits']; + } else { + ++$statistics[$name]['misses']; + } + } elseif ('getItems' === $call->name) { + $statistics[$name]['reads'] += $call->hits + $call->misses; + $statistics[$name]['hits'] += $call->hits; + $statistics[$name]['misses'] += $call->misses; + } elseif ('hasItem' === $call->name) { + ++$statistics[$name]['reads']; + if (false === $call->result) { + ++$statistics[$name]['misses']; + } else { + ++$statistics[$name]['hits']; + } + } elseif ('save' === $call->name) { + ++$statistics[$name]['writes']; + } elseif ('deleteItem' === $call->name) { + ++$statistics[$name]['deletes']; + } + } + if ($statistics[$name]['reads']) { + $statistics[$name]['hit_read_ratio'] = round(100 * $statistics[$name]['hits'] / $statistics[$name]['reads'], 2); + } else { + $statistics[$name]['hit_read_ratio'] = null; + } + } + + return $statistics; + } + + private function calculateTotalStatistics(): array + { + $statistics = $this->getStatistics(); + $totals = [ + 'calls' => 0, + 'time' => 0, + 'reads' => 0, + 'writes' => 0, + 'deletes' => 0, + 'hits' => 0, + 'misses' => 0, + ]; + foreach ($statistics as $name => $values) { + foreach ($totals as $key => $value) { + $totals[$key] += $statistics[$name][$key]; + } + } + if ($totals['reads']) { + $totals['hit_read_ratio'] = round(100 * $totals['hits'] / $totals['reads'], 2); + } else { + $totals['hit_read_ratio'] = null; + } + + return $totals; + } +} diff --git a/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php b/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php new file mode 100644 index 0000000..6193d34 --- /dev/null +++ b/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\DependencyInjection; + +use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface; +use Symfony\Component\Cache\Adapter\TraceableAdapter; +use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Inject a data collector to all the cache services to be able to get detailed statistics. + * + * @author Tobias Nyholm + */ +class CacheCollectorPass implements CompilerPassInterface +{ + private $dataCollectorCacheId; + private $cachePoolTag; + private $cachePoolRecorderInnerSuffix; + + public function __construct(string $dataCollectorCacheId = 'data_collector.cache', string $cachePoolTag = 'cache.pool', string $cachePoolRecorderInnerSuffix = '.recorder_inner') + { + $this->dataCollectorCacheId = $dataCollectorCacheId; + $this->cachePoolTag = $cachePoolTag; + $this->cachePoolRecorderInnerSuffix = $cachePoolRecorderInnerSuffix; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->dataCollectorCacheId)) { + return; + } + + $collectorDefinition = $container->getDefinition($this->dataCollectorCacheId); + foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $attributes) { + $definition = $container->getDefinition($id); + if ($definition->isAbstract()) { + continue; + } + + $recorder = new Definition(is_subclass_of($definition->getClass(), TagAwareAdapterInterface::class) ? TraceableTagAwareAdapter::class : TraceableAdapter::class); + $recorder->setTags($definition->getTags()); + $recorder->setPublic($definition->isPublic()); + $recorder->setArguments([new Reference($innerId = $id.$this->cachePoolRecorderInnerSuffix)]); + + $definition->setTags([]); + $definition->setPublic(false); + + $container->setDefinition($innerId, $definition); + $container->setDefinition($id, $recorder); + + // Tell the collector to add the new instance + $collectorDefinition->addMethodCall('addInstance', [$id, new Reference($id)]); + $collectorDefinition->setPublic(false); + } + } +} diff --git a/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php b/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php new file mode 100644 index 0000000..3ca89a3 --- /dev/null +++ b/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Nicolas Grekas + */ +class CachePoolClearerPass implements CompilerPassInterface +{ + private $cachePoolClearerTag; + + public function __construct(string $cachePoolClearerTag = 'cache.pool.clearer') + { + $this->cachePoolClearerTag = $cachePoolClearerTag; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $container->getParameterBag()->remove('cache.prefix.seed'); + + foreach ($container->findTaggedServiceIds($this->cachePoolClearerTag) as $id => $attr) { + $clearer = $container->getDefinition($id); + $pools = []; + foreach ($clearer->getArgument(0) as $name => $ref) { + if ($container->hasDefinition($ref)) { + $pools[$name] = new Reference($ref); + } + } + $clearer->replaceArgument(0, $pools); + } + } +} diff --git a/vendor/symfony/cache/DependencyInjection/CachePoolPass.php b/vendor/symfony/cache/DependencyInjection/CachePoolPass.php new file mode 100644 index 0000000..35bf5e7 --- /dev/null +++ b/vendor/symfony/cache/DependencyInjection/CachePoolPass.php @@ -0,0 +1,222 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\DependencyInjection; + +use Symfony\Component\Cache\Adapter\AbstractAdapter; +use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Cache\Adapter\ChainAdapter; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Nicolas Grekas + */ +class CachePoolPass implements CompilerPassInterface +{ + private $cachePoolTag; + private $kernelResetTag; + private $cacheClearerId; + private $cachePoolClearerTag; + private $cacheSystemClearerId; + private $cacheSystemClearerTag; + + public function __construct(string $cachePoolTag = 'cache.pool', string $kernelResetTag = 'kernel.reset', string $cacheClearerId = 'cache.global_clearer', string $cachePoolClearerTag = 'cache.pool.clearer', string $cacheSystemClearerId = 'cache.system_clearer', string $cacheSystemClearerTag = 'kernel.cache_clearer') + { + $this->cachePoolTag = $cachePoolTag; + $this->kernelResetTag = $kernelResetTag; + $this->cacheClearerId = $cacheClearerId; + $this->cachePoolClearerTag = $cachePoolClearerTag; + $this->cacheSystemClearerId = $cacheSystemClearerId; + $this->cacheSystemClearerTag = $cacheSystemClearerTag; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if ($container->hasParameter('cache.prefix.seed')) { + $seed = '.'.$container->getParameterBag()->resolveValue($container->getParameter('cache.prefix.seed')); + } else { + $seed = '_'.$container->getParameter('kernel.project_dir'); + } + $seed .= '.'.$container->getParameter('kernel.container_class'); + + $pools = []; + $clearers = []; + $attributes = [ + 'provider', + 'name', + 'namespace', + 'default_lifetime', + 'reset', + ]; + foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $tags) { + $adapter = $pool = $container->getDefinition($id); + if ($pool->isAbstract()) { + continue; + } + $class = $adapter->getClass(); + while ($adapter instanceof ChildDefinition) { + $adapter = $container->findDefinition($adapter->getParent()); + $class = $class ?: $adapter->getClass(); + if ($t = $adapter->getTag($this->cachePoolTag)) { + $tags[0] += $t[0]; + } + } + $name = $tags[0]['name'] ?? $id; + if (!isset($tags[0]['namespace'])) { + $namespaceSeed = $seed; + if (null !== $class) { + $namespaceSeed .= '.'.$class; + } + + $tags[0]['namespace'] = $this->getNamespace($namespaceSeed, $name); + } + if (isset($tags[0]['clearer'])) { + $clearer = $tags[0]['clearer']; + while ($container->hasAlias($clearer)) { + $clearer = (string) $container->getAlias($clearer); + } + } else { + $clearer = null; + } + unset($tags[0]['clearer'], $tags[0]['name']); + + if (isset($tags[0]['provider'])) { + $tags[0]['provider'] = new Reference(static::getServiceProvider($container, $tags[0]['provider'])); + } + + if (ChainAdapter::class === $class) { + $adapters = []; + foreach ($adapter->getArgument(0) as $provider => $adapter) { + $chainedPool = $adapter = new ChildDefinition($adapter); + $chainedTags = [\is_int($provider) ? [] : ['provider' => $provider]]; + $chainedClass = ''; + + while ($adapter instanceof ChildDefinition) { + $adapter = $container->findDefinition($adapter->getParent()); + $chainedClass = $chainedClass ?: $adapter->getClass(); + if ($t = $adapter->getTag($this->cachePoolTag)) { + $chainedTags[0] += $t[0]; + } + } + + if (ChainAdapter::class === $chainedClass) { + throw new InvalidArgumentException(sprintf('Invalid service "%s": chain of adapters cannot reference another chain, found "%s".', $id, $chainedPool->getParent())); + } + + $i = 0; + + if (isset($chainedTags[0]['provider'])) { + $chainedPool->replaceArgument($i++, new Reference(static::getServiceProvider($container, $chainedTags[0]['provider']))); + } + + if (isset($tags[0]['namespace']) && ArrayAdapter::class !== $adapter->getClass()) { + $chainedPool->replaceArgument($i++, $tags[0]['namespace']); + } + + if (isset($tags[0]['default_lifetime'])) { + $chainedPool->replaceArgument($i++, $tags[0]['default_lifetime']); + } + + $adapters[] = $chainedPool; + } + + $pool->replaceArgument(0, $adapters); + unset($tags[0]['provider'], $tags[0]['namespace']); + $i = 1; + } else { + $i = 0; + } + + foreach ($attributes as $attr) { + if (!isset($tags[0][$attr])) { + // no-op + } elseif ('reset' === $attr) { + if ($tags[0][$attr]) { + $pool->addTag($this->kernelResetTag, ['method' => $tags[0][$attr]]); + } + } elseif ('namespace' !== $attr || ArrayAdapter::class !== $class) { + $pool->replaceArgument($i++, $tags[0][$attr]); + } + unset($tags[0][$attr]); + } + if (!empty($tags[0])) { + throw new InvalidArgumentException(sprintf('Invalid "%s" tag for service "%s": accepted attributes are "clearer", "provider", "name", "namespace", "default_lifetime" and "reset", found "%s".', $this->cachePoolTag, $id, implode('", "', array_keys($tags[0])))); + } + + if (null !== $clearer) { + $clearers[$clearer][$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE); + } + + $pools[$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE); + } + + $notAliasedCacheClearerId = $this->cacheClearerId; + while ($container->hasAlias($this->cacheClearerId)) { + $this->cacheClearerId = (string) $container->getAlias($this->cacheClearerId); + } + if ($container->hasDefinition($this->cacheClearerId)) { + $clearers[$notAliasedCacheClearerId] = $pools; + } + + foreach ($clearers as $id => $pools) { + $clearer = $container->getDefinition($id); + if ($clearer instanceof ChildDefinition) { + $clearer->replaceArgument(0, $pools); + } else { + $clearer->setArgument(0, $pools); + } + $clearer->addTag($this->cachePoolClearerTag); + + if ($this->cacheSystemClearerId === $id) { + $clearer->addTag($this->cacheSystemClearerTag); + } + } + + if ($container->hasDefinition('console.command.cache_pool_list')) { + $container->getDefinition('console.command.cache_pool_list')->replaceArgument(0, array_keys($pools)); + } + } + + private function getNamespace(string $seed, string $id) + { + return substr(str_replace('/', '-', base64_encode(hash('sha256', $id.$seed, true))), 0, 10); + } + + /** + * @internal + */ + public static function getServiceProvider(ContainerBuilder $container, $name) + { + $container->resolveEnvPlaceholders($name, null, $usedEnvs); + + if ($usedEnvs || preg_match('#^[a-z]++:#', $name)) { + $dsn = $name; + + if (!$container->hasDefinition($name = '.cache_connection.'.ContainerBuilder::hash($dsn))) { + $definition = new Definition(AbstractAdapter::class); + $definition->setPublic(false); + $definition->setFactory([AbstractAdapter::class, 'createConnection']); + $definition->setArguments([$dsn, ['lazy' => true]]); + $container->setDefinition($name, $definition); + } + } + + return $name; + } +} diff --git a/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php b/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php new file mode 100644 index 0000000..e569962 --- /dev/null +++ b/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\DependencyInjection; + +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Rob Frawley 2nd + */ +class CachePoolPrunerPass implements CompilerPassInterface +{ + private $cacheCommandServiceId; + private $cachePoolTag; + + public function __construct(string $cacheCommandServiceId = 'console.command.cache_pool_prune', string $cachePoolTag = 'cache.pool') + { + $this->cacheCommandServiceId = $cacheCommandServiceId; + $this->cachePoolTag = $cachePoolTag; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->cacheCommandServiceId)) { + return; + } + + $services = []; + + foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $tags) { + $class = $container->getParameterBag()->resolveValue($container->getDefinition($id)->getClass()); + + if (!$reflection = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + + if ($reflection->implementsInterface(PruneableInterface::class)) { + $services[$id] = new Reference($id); + } + } + + $container->getDefinition($this->cacheCommandServiceId)->replaceArgument(0, new IteratorArgument($services)); + } +} diff --git a/vendor/symfony/cache/DoctrineProvider.php b/vendor/symfony/cache/DoctrineProvider.php new file mode 100644 index 0000000..d7e0bca --- /dev/null +++ b/vendor/symfony/cache/DoctrineProvider.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache; + +use Doctrine\Common\Cache\CacheProvider; +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Contracts\Service\ResetInterface; + +/** + * @author Nicolas Grekas + */ +class DoctrineProvider extends CacheProvider implements PruneableInterface, ResettableInterface +{ + private $pool; + + public function __construct(CacheItemPoolInterface $pool) + { + $this->pool = $pool; + } + + /** + * {@inheritdoc} + */ + public function prune() + { + return $this->pool instanceof PruneableInterface && $this->pool->prune(); + } + + /** + * {@inheritdoc} + */ + public function reset() + { + if ($this->pool instanceof ResetInterface) { + $this->pool->reset(); + } + $this->setNamespace($this->getNamespace()); + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + $item = $this->pool->getItem(rawurlencode($id)); + + return $item->isHit() ? $item->get() : false; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + protected function doContains($id) + { + return $this->pool->hasItem(rawurlencode($id)); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + protected function doSave($id, $data, $lifeTime = 0) + { + $item = $this->pool->getItem(rawurlencode($id)); + + if (0 < $lifeTime) { + $item->expiresAfter($lifeTime); + } + + return $this->pool->save($item->set($data)); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + protected function doDelete($id) + { + return $this->pool->deleteItem(rawurlencode($id)); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + protected function doFlush() + { + return $this->pool->clear(); + } + + /** + * {@inheritdoc} + * + * @return array|null + */ + protected function doGetStats() + { + return null; + } +} diff --git a/vendor/symfony/cache/Exception/CacheException.php b/vendor/symfony/cache/Exception/CacheException.php new file mode 100644 index 0000000..d2e975b --- /dev/null +++ b/vendor/symfony/cache/Exception/CacheException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Exception; + +use Psr\Cache\CacheException as Psr6CacheInterface; +use Psr\SimpleCache\CacheException as SimpleCacheInterface; + +if (interface_exists(SimpleCacheInterface::class)) { + class CacheException extends \Exception implements Psr6CacheInterface, SimpleCacheInterface + { + } +} else { + class CacheException extends \Exception implements Psr6CacheInterface + { + } +} diff --git a/vendor/symfony/cache/Exception/InvalidArgumentException.php b/vendor/symfony/cache/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..7f9584a --- /dev/null +++ b/vendor/symfony/cache/Exception/InvalidArgumentException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Exception; + +use Psr\Cache\InvalidArgumentException as Psr6CacheInterface; +use Psr\SimpleCache\InvalidArgumentException as SimpleCacheInterface; + +if (interface_exists(SimpleCacheInterface::class)) { + class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface, SimpleCacheInterface + { + } +} else { + class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface + { + } +} diff --git a/vendor/symfony/cache/Exception/LogicException.php b/vendor/symfony/cache/Exception/LogicException.php new file mode 100644 index 0000000..9ffa7ed --- /dev/null +++ b/vendor/symfony/cache/Exception/LogicException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Exception; + +use Psr\Cache\CacheException as Psr6CacheInterface; +use Psr\SimpleCache\CacheException as SimpleCacheInterface; + +if (interface_exists(SimpleCacheInterface::class)) { + class LogicException extends \LogicException implements Psr6CacheInterface, SimpleCacheInterface + { + } +} else { + class LogicException extends \LogicException implements Psr6CacheInterface + { + } +} diff --git a/vendor/symfony/cache/LICENSE b/vendor/symfony/cache/LICENSE new file mode 100644 index 0000000..3c464ca --- /dev/null +++ b/vendor/symfony/cache/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/cache/LockRegistry.php b/vendor/symfony/cache/LockRegistry.php new file mode 100644 index 0000000..6c0fbff --- /dev/null +++ b/vendor/symfony/cache/LockRegistry.php @@ -0,0 +1,153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache; + +use Psr\Log\LoggerInterface; +use Symfony\Contracts\Cache\CacheInterface; +use Symfony\Contracts\Cache\ItemInterface; + +/** + * LockRegistry is used internally by existing adapters to protect against cache stampede. + * + * It does so by wrapping the computation of items in a pool of locks. + * Foreach each apps, there can be at most 20 concurrent processes that + * compute items at the same time and only one per cache-key. + * + * @author Nicolas Grekas + */ +final class LockRegistry +{ + private static $openedFiles = []; + private static $lockedFiles = []; + + /** + * The number of items in this list controls the max number of concurrent processes. + */ + private static $files = [ + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AbstractAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AbstractTagAwareAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AdapterInterface.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ApcuAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ArrayAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ChainAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'DoctrineAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'FilesystemAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'FilesystemTagAwareAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'MemcachedAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'NullAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PdoAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PhpArrayAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PhpFilesAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ProxyAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'Psr16Adapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'RedisAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'RedisTagAwareAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TagAwareAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TagAwareAdapterInterface.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TraceableAdapter.php', + __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TraceableTagAwareAdapter.php', + ]; + + /** + * Defines a set of existing files that will be used as keys to acquire locks. + * + * @return array The previously defined set of files + */ + public static function setFiles(array $files): array + { + $previousFiles = self::$files; + self::$files = $files; + + foreach (self::$openedFiles as $file) { + if ($file) { + flock($file, LOCK_UN); + fclose($file); + } + } + self::$openedFiles = self::$lockedFiles = []; + + return $previousFiles; + } + + public static function compute(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata = null, LoggerInterface $logger = null) + { + $key = self::$files ? crc32($item->getKey()) % \count(self::$files) : -1; + + if ($key < 0 || (self::$lockedFiles[$key] ?? false) || !$lock = self::open($key)) { + return $callback($item, $save); + } + + while (true) { + try { + // race to get the lock in non-blocking mode + $locked = flock($lock, LOCK_EX | LOCK_NB, $wouldBlock); + + if ($locked || !$wouldBlock) { + $logger && $logger->info(sprintf('Lock %s, now computing item "{key}"', $locked ? 'acquired' : 'not supported'), ['key' => $item->getKey()]); + self::$lockedFiles[$key] = true; + + $value = $callback($item, $save); + + if ($save) { + if ($setMetadata) { + $setMetadata($item); + } + + $pool->save($item->set($value)); + $save = false; + } + + return $value; + } + // if we failed the race, retry locking in blocking mode to wait for the winner + $logger && $logger->info('Item "{key}" is locked, waiting for it to be released', ['key' => $item->getKey()]); + flock($lock, LOCK_SH); + } finally { + flock($lock, LOCK_UN); + unset(self::$lockedFiles[$key]); + } + static $signalingException, $signalingCallback; + $signalingException = $signalingException ?? unserialize("O:9:\"Exception\":1:{s:16:\"\0Exception\0trace\";a:0:{}}"); + $signalingCallback = $signalingCallback ?? function () use ($signalingException) { throw $signalingException; }; + + try { + $value = $pool->get($item->getKey(), $signalingCallback, 0); + $logger && $logger->info('Item "{key}" retrieved after lock was released', ['key' => $item->getKey()]); + $save = false; + + return $value; + } catch (\Exception $e) { + if ($signalingException !== $e) { + throw $e; + } + $logger && $logger->info('Item "{key}" not found while lock was released, now retrying', ['key' => $item->getKey()]); + } + } + + return null; + } + + private static function open(int $key) + { + if (null !== $h = self::$openedFiles[$key] ?? null) { + return $h; + } + set_error_handler(function () {}); + try { + $h = fopen(self::$files[$key], 'r+'); + } finally { + restore_error_handler(); + } + + return self::$openedFiles[$key] = $h ?: @fopen(self::$files[$key], 'r'); + } +} diff --git a/vendor/symfony/cache/Marshaller/DefaultMarshaller.php b/vendor/symfony/cache/Marshaller/DefaultMarshaller.php new file mode 100644 index 0000000..24b67a5 --- /dev/null +++ b/vendor/symfony/cache/Marshaller/DefaultMarshaller.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Marshaller; + +use Symfony\Component\Cache\Exception\CacheException; + +/** + * Serializes/unserializes values using igbinary_serialize() if available, serialize() otherwise. + * + * @author Nicolas Grekas + */ +class DefaultMarshaller implements MarshallerInterface +{ + private $useIgbinarySerialize = true; + + public function __construct(bool $useIgbinarySerialize = null) + { + if (null === $useIgbinarySerialize) { + $useIgbinarySerialize = \extension_loaded('igbinary') && \PHP_VERSION_ID < 70400; + } elseif ($useIgbinarySerialize && (!\extension_loaded('igbinary') || \PHP_VERSION_ID >= 70400)) { + throw new CacheException('The "igbinary" PHP extension is not '.(\PHP_VERSION_ID >= 70400 ? 'compatible with PHP 7.4.' : 'loaded.')); + } + $this->useIgbinarySerialize = $useIgbinarySerialize; + } + + /** + * {@inheritdoc} + */ + public function marshall(array $values, ?array &$failed): array + { + $serialized = $failed = []; + + foreach ($values as $id => $value) { + try { + if ($this->useIgbinarySerialize) { + $serialized[$id] = igbinary_serialize($value); + } else { + $serialized[$id] = serialize($value); + } + } catch (\Exception $e) { + $failed[] = $id; + } + } + + return $serialized; + } + + /** + * {@inheritdoc} + */ + public function unmarshall(string $value) + { + if ('b:0;' === $value) { + return false; + } + if ('N;' === $value) { + return null; + } + static $igbinaryNull; + if ($value === ($igbinaryNull ?? $igbinaryNull = \extension_loaded('igbinary') && \PHP_VERSION_ID < 70400 ? igbinary_serialize(null) : false)) { + return null; + } + $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); + try { + if (':' === ($value[1] ?? ':')) { + if (false !== $value = unserialize($value)) { + return $value; + } + } elseif (false === $igbinaryNull) { + throw new \RuntimeException('Failed to unserialize values, did you forget to install the "igbinary" extension?'); + } elseif (null !== $value = igbinary_unserialize($value)) { + return $value; + } + + throw new \DomainException(error_get_last() ? error_get_last()['message'] : 'Failed to unserialize values.'); + } catch (\Error $e) { + throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); + } finally { + ini_set('unserialize_callback_func', $unserializeCallbackHandler); + } + } + + /** + * @internal + */ + public static function handleUnserializeCallback(string $class) + { + throw new \DomainException('Class not found: '.$class); + } +} diff --git a/vendor/symfony/cache/Marshaller/DeflateMarshaller.php b/vendor/symfony/cache/Marshaller/DeflateMarshaller.php new file mode 100644 index 0000000..5544806 --- /dev/null +++ b/vendor/symfony/cache/Marshaller/DeflateMarshaller.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Marshaller; + +use Symfony\Component\Cache\Exception\CacheException; + +/** + * Compresses values using gzdeflate(). + * + * @author Nicolas Grekas + */ +class DeflateMarshaller implements MarshallerInterface +{ + private $marshaller; + + public function __construct(MarshallerInterface $marshaller) + { + if (!\function_exists('gzdeflate')) { + throw new CacheException('The "zlib" PHP extension is not loaded.'); + } + + $this->marshaller = $marshaller; + } + + /** + * {@inheritdoc} + */ + public function marshall(array $values, ?array &$failed): array + { + return array_map('gzdeflate', $this->marshaller->marshall($values, $failed)); + } + + /** + * {@inheritdoc} + */ + public function unmarshall(string $value) + { + if (false !== $inflatedValue = @gzinflate($value)) { + $value = $inflatedValue; + } + + return $this->marshaller->unmarshall($value); + } +} diff --git a/vendor/symfony/cache/Marshaller/MarshallerInterface.php b/vendor/symfony/cache/Marshaller/MarshallerInterface.php new file mode 100644 index 0000000..cdd6c40 --- /dev/null +++ b/vendor/symfony/cache/Marshaller/MarshallerInterface.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Marshaller; + +/** + * Serializes/unserializes PHP values. + * + * Implementations of this interface MUST deal with errors carefully. They MUST + * also deal with forward and backward compatibility at the storage format level. + * + * @author Nicolas Grekas + */ +interface MarshallerInterface +{ + /** + * Serializes a list of values. + * + * When serialization fails for a specific value, no exception should be + * thrown. Instead, its key should be listed in $failed. + */ + public function marshall(array $values, ?array &$failed): array; + + /** + * Unserializes a single value and throws an exception if anything goes wrong. + * + * @return mixed + * + * @throws \Exception Whenever unserialization fails + */ + public function unmarshall(string $value); +} diff --git a/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php b/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php new file mode 100644 index 0000000..5d1e303 --- /dev/null +++ b/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Marshaller; + +/** + * A marshaller optimized for data structures generated by AbstractTagAwareAdapter. + * + * @author Nicolas Grekas + */ +class TagAwareMarshaller implements MarshallerInterface +{ + private $marshaller; + + public function __construct(MarshallerInterface $marshaller = null) + { + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + } + + /** + * {@inheritdoc} + */ + public function marshall(array $values, ?array &$failed): array + { + $failed = $notSerialized = $serialized = []; + + foreach ($values as $id => $value) { + if (\is_array($value) && \is_array($value['tags'] ?? null) && \array_key_exists('value', $value) && \count($value) === 2 + (\is_string($value['meta'] ?? null) && 8 === \strlen($value['meta']))) { + // if the value is an array with keys "tags", "value" and "meta", use a compact serialization format + // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F allow detecting this format quickly in unmarshall() + + $v = $this->marshaller->marshall($value, $f); + + if ($f) { + $f = []; + $failed[] = $id; + } else { + if ([] === $value['tags']) { + $v['tags'] = ''; + } + + $serialized[$id] = "\x9D".($value['meta'] ?? "\0\0\0\0\0\0\0\0").pack('N', \strlen($v['tags'])).$v['tags'].$v['value']; + $serialized[$id][9] = "\x5F"; + } + } else { + // other arbitratry values are serialized using the decorated marshaller below + $notSerialized[$id] = $value; + } + } + + if ($notSerialized) { + $serialized += $this->marshaller->marshall($notSerialized, $f); + $failed = array_merge($failed, $f); + } + + return $serialized; + } + + /** + * {@inheritdoc} + */ + public function unmarshall(string $value) + { + // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F + if (13 >= \strlen($value) || "\x9D" !== $value[0] || "\0" !== $value[5] || "\x5F" !== $value[9]) { + return $this->marshaller->unmarshall($value); + } + + // data consists of value, tags and metadata which we need to unpack + $meta = substr($value, 1, 12); + $meta[8] = "\0"; + $tagLen = unpack('Nlen', $meta, 8)['len']; + $meta = substr($meta, 0, 8); + + return [ + 'value' => $this->marshaller->unmarshall(substr($value, 13 + $tagLen)), + 'tags' => $tagLen ? $this->marshaller->unmarshall(substr($value, 13, $tagLen)) : [], + 'meta' => "\0\0\0\0\0\0\0\0" === $meta ? null : $meta, + ]; + } +} diff --git a/vendor/symfony/cache/PruneableInterface.php b/vendor/symfony/cache/PruneableInterface.php new file mode 100644 index 0000000..4261525 --- /dev/null +++ b/vendor/symfony/cache/PruneableInterface.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache; + +/** + * Interface extends psr-6 and psr-16 caches to allow for pruning (deletion) of all expired cache items. + */ +interface PruneableInterface +{ + /** + * @return bool + */ + public function prune(); +} diff --git a/vendor/symfony/cache/Psr16Cache.php b/vendor/symfony/cache/Psr16Cache.php new file mode 100644 index 0000000..6501516 --- /dev/null +++ b/vendor/symfony/cache/Psr16Cache.php @@ -0,0 +1,277 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache; + +use Psr\Cache\CacheException as Psr6CacheException; +use Psr\Cache\CacheItemPoolInterface; +use Psr\SimpleCache\CacheException as SimpleCacheException; +use Psr\SimpleCache\CacheInterface; +use Symfony\Component\Cache\Adapter\AdapterInterface; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Traits\ProxyTrait; + +/** + * Turns a PSR-6 cache into a PSR-16 one. + * + * @author Nicolas Grekas + */ +class Psr16Cache implements CacheInterface, PruneableInterface, ResettableInterface +{ + use ProxyTrait; + + private const METADATA_EXPIRY_OFFSET = 1527506807; + + private $createCacheItem; + private $cacheItemPrototype; + + public function __construct(CacheItemPoolInterface $pool) + { + $this->pool = $pool; + + if (!$pool instanceof AdapterInterface) { + return; + } + $cacheItemPrototype = &$this->cacheItemPrototype; + $createCacheItem = \Closure::bind( + static function ($key, $value, $allowInt = false) use (&$cacheItemPrototype) { + $item = clone $cacheItemPrototype; + $item->key = $allowInt && \is_int($key) ? (string) $key : CacheItem::validateKey($key); + $item->value = $value; + $item->isHit = false; + + return $item; + }, + null, + CacheItem::class + ); + $this->createCacheItem = function ($key, $value, $allowInt = false) use ($createCacheItem) { + if (null === $this->cacheItemPrototype) { + $this->get($allowInt && \is_int($key) ? (string) $key : $key); + } + $this->createCacheItem = $createCacheItem; + + return $createCacheItem($key, null, $allowInt)->set($value); + }; + } + + /** + * {@inheritdoc} + */ + public function get($key, $default = null) + { + try { + $item = $this->pool->getItem($key); + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + if (null === $this->cacheItemPrototype) { + $this->cacheItemPrototype = clone $item; + $this->cacheItemPrototype->set(null); + } + + return $item->isHit() ? $item->get() : $default; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function set($key, $value, $ttl = null) + { + try { + if (null !== $f = $this->createCacheItem) { + $item = $f($key, $value); + } else { + $item = $this->pool->getItem($key)->set($value); + } + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + if (null !== $ttl) { + $item->expiresAfter($ttl); + } + + return $this->pool->save($item); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function delete($key) + { + try { + return $this->pool->deleteItem($key); + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function clear() + { + return $this->pool->clear(); + } + + /** + * {@inheritdoc} + * + * @return iterable + */ + public function getMultiple($keys, $default = null) + { + if ($keys instanceof \Traversable) { + $keys = iterator_to_array($keys, false); + } elseif (!\is_array($keys)) { + throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', \is_object($keys) ? \get_class($keys) : \gettype($keys))); + } + + try { + $items = $this->pool->getItems($keys); + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + $values = []; + + if (!$this->pool instanceof AdapterInterface) { + foreach ($items as $key => $item) { + $values[$key] = $item->isHit() ? $item->get() : $default; + } + + return $values; + } + + foreach ($items as $key => $item) { + if (!$item->isHit()) { + $values[$key] = $default; + continue; + } + $values[$key] = $item->get(); + + if (!$metadata = $item->getMetadata()) { + continue; + } + unset($metadata[CacheItem::METADATA_TAGS]); + + if ($metadata) { + $values[$key] = ["\x9D".pack('VN', (int) (0.1 + $metadata[CacheItem::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[CacheItem::METADATA_CTIME])."\x5F" => $values[$key]]; + } + } + + return $values; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function setMultiple($values, $ttl = null) + { + $valuesIsArray = \is_array($values); + if (!$valuesIsArray && !$values instanceof \Traversable) { + throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given', \is_object($values) ? \get_class($values) : \gettype($values))); + } + $items = []; + + try { + if (null !== $f = $this->createCacheItem) { + $valuesIsArray = false; + foreach ($values as $key => $value) { + $items[$key] = $f($key, $value, true); + } + } elseif ($valuesIsArray) { + $items = []; + foreach ($values as $key => $value) { + $items[] = (string) $key; + } + $items = $this->pool->getItems($items); + } else { + foreach ($values as $key => $value) { + if (\is_int($key)) { + $key = (string) $key; + } + $items[$key] = $this->pool->getItem($key)->set($value); + } + } + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + $ok = true; + + foreach ($items as $key => $item) { + if ($valuesIsArray) { + $item->set($values[$key]); + } + if (null !== $ttl) { + $item->expiresAfter($ttl); + } + $ok = $this->pool->saveDeferred($item) && $ok; + } + + return $this->pool->commit() && $ok; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteMultiple($keys) + { + if ($keys instanceof \Traversable) { + $keys = iterator_to_array($keys, false); + } elseif (!\is_array($keys)) { + throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', \is_object($keys) ? \get_class($keys) : \gettype($keys))); + } + + try { + return $this->pool->deleteItems($keys); + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function has($key) + { + try { + return $this->pool->hasItem($key); + } catch (SimpleCacheException $e) { + throw $e; + } catch (Psr6CacheException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); + } + } +} diff --git a/vendor/symfony/cache/README.md b/vendor/symfony/cache/README.md new file mode 100644 index 0000000..c4ab752 --- /dev/null +++ b/vendor/symfony/cache/README.md @@ -0,0 +1,18 @@ +Symfony PSR-6 implementation for caching +======================================== + +This component provides an extended [PSR-6](http://www.php-fig.org/psr/psr-6/) +implementation for adding cache to your applications. It is designed to have a +low overhead so that caching is fastest. It ships with a few caching adapters +for the most widespread and suited to caching backends. It also provides a +`doctrine/cache` proxy adapter to cover more advanced caching needs and a proxy +adapter for greater interoperability between PSR-6 implementations. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/cache.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/cache/ResettableInterface.php b/vendor/symfony/cache/ResettableInterface.php new file mode 100644 index 0000000..7b0a853 --- /dev/null +++ b/vendor/symfony/cache/ResettableInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache; + +use Symfony\Contracts\Service\ResetInterface; + +/** + * Resets a pool's local state. + */ +interface ResettableInterface extends ResetInterface +{ +} diff --git a/vendor/symfony/cache/Traits/AbstractAdapterTrait.php b/vendor/symfony/cache/Traits/AbstractAdapterTrait.php new file mode 100644 index 0000000..d166c53 --- /dev/null +++ b/vendor/symfony/cache/Traits/AbstractAdapterTrait.php @@ -0,0 +1,392 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Psr\Cache\CacheItemInterface; +use Psr\Log\LoggerAwareTrait; +use Symfony\Component\Cache\CacheItem; + +/** + * @author Nicolas Grekas + * + * @internal + */ +trait AbstractAdapterTrait +{ + use LoggerAwareTrait; + + /** + * @var \Closure needs to be set by class, signature is function(string , mixed , bool ) + */ + private $createCacheItem; + + /** + * @var \Closure needs to be set by class, signature is function(array , string , array <&expiredIds>) + */ + private $mergeByLifetime; + + private $namespace; + private $namespaceVersion = ''; + private $versioningIsEnabled = false; + private $deferred = []; + private $ids = []; + + /** + * @var int|null The maximum length to enforce for identifiers or null when no limit applies + */ + protected $maxIdLength; + + /** + * Fetches several cache items. + * + * @param array $ids The cache identifiers to fetch + * + * @return array|\Traversable The corresponding values found in the cache + */ + abstract protected function doFetch(array $ids); + + /** + * Confirms if the cache contains specified cache item. + * + * @param string $id The identifier for which to check existence + * + * @return bool True if item exists in the cache, false otherwise + */ + abstract protected function doHave(string $id); + + /** + * Deletes all items in the pool. + * + * @param string $namespace The prefix used for all identifiers managed by this pool + * + * @return bool True if the pool was successfully cleared, false otherwise + */ + abstract protected function doClear(string $namespace); + + /** + * Removes multiple items from the pool. + * + * @param array $ids An array of identifiers that should be removed from the pool + * + * @return bool True if the items were successfully removed, false otherwise + */ + abstract protected function doDelete(array $ids); + + /** + * Persists several cache items immediately. + * + * @param array $values The values to cache, indexed by their cache identifier + * @param int $lifetime The lifetime of the cached values, 0 for persisting until manual cleaning + * + * @return array|bool The identifiers that failed to be cached or a boolean stating if caching succeeded or not + */ + abstract protected function doSave(array $values, int $lifetime); + + /** + * {@inheritdoc} + * + * @return bool + */ + public function hasItem($key) + { + $id = $this->getId($key); + + if (isset($this->deferred[$key])) { + $this->commit(); + } + + try { + return $this->doHave($id); + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to check if key "{key}" is cached: '.$e->getMessage(), ['key' => $key, 'exception' => $e]); + + return false; + } + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function clear(string $prefix = '') + { + $this->deferred = []; + if ($cleared = $this->versioningIsEnabled) { + $namespaceVersion = substr_replace(base64_encode(pack('V', mt_rand())), static::NS_SEPARATOR, 5); + try { + $cleared = $this->doSave([static::NS_SEPARATOR.$this->namespace => $namespaceVersion], 0); + } catch (\Exception $e) { + $cleared = false; + } + if ($cleared = true === $cleared || [] === $cleared) { + $this->namespaceVersion = $namespaceVersion; + $this->ids = []; + } + } + + try { + return $this->doClear($this->namespace.$prefix) || $cleared; + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to clear the cache: '.$e->getMessage(), ['exception' => $e]); + + return false; + } + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItem($key) + { + return $this->deleteItems([$key]); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function deleteItems(array $keys) + { + $ids = []; + + foreach ($keys as $key) { + $ids[$key] = $this->getId($key); + unset($this->deferred[$key]); + } + + try { + if ($this->doDelete($ids)) { + return true; + } + } catch (\Exception $e) { + } + + $ok = true; + + // When bulk-delete failed, retry each item individually + foreach ($ids as $key => $id) { + try { + $e = null; + if ($this->doDelete([$id])) { + continue; + } + } catch (\Exception $e) { + } + $message = 'Failed to delete key "{key}"'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); + CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e]); + $ok = false; + } + + return $ok; + } + + /** + * {@inheritdoc} + */ + public function getItem($key) + { + if ($this->deferred) { + $this->commit(); + } + $id = $this->getId($key); + + $f = $this->createCacheItem; + $isHit = false; + $value = null; + + try { + foreach ($this->doFetch([$id]) as $value) { + $isHit = true; + } + + return $f($key, $value, $isHit); + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to fetch key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e]); + } + + return $f($key, null, false); + } + + /** + * {@inheritdoc} + */ + public function getItems(array $keys = []) + { + if ($this->deferred) { + $this->commit(); + } + $ids = []; + + foreach ($keys as $key) { + $ids[] = $this->getId($key); + } + try { + $items = $this->doFetch($ids); + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to fetch items: '.$e->getMessage(), ['keys' => $keys, 'exception' => $e]); + $items = []; + } + $ids = array_combine($ids, $keys); + + return $this->generateItems($items, $ids); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function save(CacheItemInterface $item) + { + if (!$item instanceof CacheItem) { + return false; + } + $this->deferred[$item->getKey()] = $item; + + return $this->commit(); + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function saveDeferred(CacheItemInterface $item) + { + if (!$item instanceof CacheItem) { + return false; + } + $this->deferred[$item->getKey()] = $item; + + return true; + } + + /** + * Enables/disables versioning of items. + * + * When versioning is enabled, clearing the cache is atomic and doesn't require listing existing keys to proceed, + * but old keys may need garbage collection and extra round-trips to the back-end are required. + * + * Calling this method also clears the memoized namespace version and thus forces a resynchonization of it. + * + * @param bool $enable + * + * @return bool the previous state of versioning + */ + public function enableVersioning($enable = true) + { + $wasEnabled = $this->versioningIsEnabled; + $this->versioningIsEnabled = (bool) $enable; + $this->namespaceVersion = ''; + $this->ids = []; + + return $wasEnabled; + } + + /** + * {@inheritdoc} + */ + public function reset() + { + if ($this->deferred) { + $this->commit(); + } + $this->namespaceVersion = ''; + $this->ids = []; + } + + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + public function __destruct() + { + if ($this->deferred) { + $this->commit(); + } + } + + private function generateItems(iterable $items, array &$keys): iterable + { + $f = $this->createCacheItem; + + try { + foreach ($items as $id => $value) { + if (!isset($keys[$id])) { + $id = key($keys); + } + $key = $keys[$id]; + unset($keys[$id]); + yield $key => $f($key, $value, true); + } + } catch (\Exception $e) { + CacheItem::log($this->logger, 'Failed to fetch items: '.$e->getMessage(), ['keys' => array_values($keys), 'exception' => $e]); + } + + foreach ($keys as $key) { + yield $key => $f($key, null, false); + } + } + + private function getId($key) + { + if ($this->versioningIsEnabled && '' === $this->namespaceVersion) { + $this->ids = []; + $this->namespaceVersion = '1'.static::NS_SEPARATOR; + try { + foreach ($this->doFetch([static::NS_SEPARATOR.$this->namespace]) as $v) { + $this->namespaceVersion = $v; + } + if ('1'.static::NS_SEPARATOR === $this->namespaceVersion) { + $this->namespaceVersion = substr_replace(base64_encode(pack('V', time())), static::NS_SEPARATOR, 5); + $this->doSave([static::NS_SEPARATOR.$this->namespace => $this->namespaceVersion], 0); + } + } catch (\Exception $e) { + } + } + + if (\is_string($key) && isset($this->ids[$key])) { + return $this->namespace.$this->namespaceVersion.$this->ids[$key]; + } + CacheItem::validateKey($key); + $this->ids[$key] = $key; + + if (null === $this->maxIdLength) { + return $this->namespace.$this->namespaceVersion.$key; + } + if (\strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) { + // Use MD5 to favor speed over security, which is not an issue here + $this->ids[$key] = $id = substr_replace(base64_encode(hash('md5', $key, true)), static::NS_SEPARATOR, -(\strlen($this->namespaceVersion) + 2)); + $id = $this->namespace.$this->namespaceVersion.$id; + } + + return $id; + } + + /** + * @internal + */ + public static function handleUnserializeCallback($class) + { + throw new \DomainException('Class not found: '.$class); + } +} diff --git a/vendor/symfony/cache/Traits/ContractsTrait.php b/vendor/symfony/cache/Traits/ContractsTrait.php new file mode 100644 index 0000000..c5827c3 --- /dev/null +++ b/vendor/symfony/cache/Traits/ContractsTrait.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Cache\Adapter\AdapterInterface; +use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\LockRegistry; +use Symfony\Contracts\Cache\CacheInterface; +use Symfony\Contracts\Cache\CacheTrait; +use Symfony\Contracts\Cache\ItemInterface; + +/** + * @author Nicolas Grekas + * + * @internal + */ +trait ContractsTrait +{ + use CacheTrait { + doGet as private contractsGet; + } + + private $callbackWrapper = [LockRegistry::class, 'compute']; + private $computing = []; + + /** + * Wraps the callback passed to ->get() in a callable. + * + * @return callable the previous callback wrapper + */ + public function setCallbackWrapper(?callable $callbackWrapper): callable + { + $previousWrapper = $this->callbackWrapper; + $this->callbackWrapper = $callbackWrapper ?? function (callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger) { + return $callback($item, $save); + }; + + return $previousWrapper; + } + + private function doGet(AdapterInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null) + { + if (0 > $beta = $beta ?? 1.0) { + throw new InvalidArgumentException(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', \get_class($this), $beta)); + } + + static $setMetadata; + + $setMetadata = $setMetadata ?? \Closure::bind( + static function (CacheItem $item, float $startTime, ?array &$metadata) { + if ($item->expiry > $endTime = microtime(true)) { + $item->newMetadata[CacheItem::METADATA_EXPIRY] = $metadata[CacheItem::METADATA_EXPIRY] = $item->expiry; + $item->newMetadata[CacheItem::METADATA_CTIME] = $metadata[CacheItem::METADATA_CTIME] = (int) ceil(1000 * ($endTime - $startTime)); + } else { + unset($metadata[CacheItem::METADATA_EXPIRY], $metadata[CacheItem::METADATA_CTIME]); + } + }, + null, + CacheItem::class + ); + + return $this->contractsGet($pool, $key, function (CacheItem $item, bool &$save) use ($pool, $callback, $setMetadata, &$metadata, $key) { + // don't wrap nor save recursive calls + if (isset($this->computing[$key])) { + $value = $callback($item, $save); + $save = false; + + return $value; + } + + $this->computing[$key] = $key; + $startTime = microtime(true); + + try { + $value = ($this->callbackWrapper)($callback, $item, $save, $pool, function (CacheItem $item) use ($setMetadata, $startTime, &$metadata) { + $setMetadata($item, $startTime, $metadata); + }, $this->logger ?? null); + $setMetadata($item, $startTime, $metadata); + + return $value; + } finally { + unset($this->computing[$key]); + } + }, $beta, $metadata, $this->logger ?? null); + } +} diff --git a/vendor/symfony/cache/Traits/FilesystemCommonTrait.php b/vendor/symfony/cache/Traits/FilesystemCommonTrait.php new file mode 100644 index 0000000..01400c8 --- /dev/null +++ b/vendor/symfony/cache/Traits/FilesystemCommonTrait.php @@ -0,0 +1,183 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Symfony\Component\Cache\Exception\InvalidArgumentException; + +/** + * @author Nicolas Grekas + * + * @internal + */ +trait FilesystemCommonTrait +{ + private $directory; + private $tmp; + + private function init(string $namespace, ?string $directory) + { + if (!isset($directory[0])) { + $directory = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'symfony-cache'; + } else { + $directory = realpath($directory) ?: $directory; + } + if (isset($namespace[0])) { + if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) { + throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0])); + } + $directory .= \DIRECTORY_SEPARATOR.$namespace; + } + if (!file_exists($directory)) { + @mkdir($directory, 0777, true); + } + $directory .= \DIRECTORY_SEPARATOR; + // On Windows the whole path is limited to 258 chars + if ('\\' === \DIRECTORY_SEPARATOR && \strlen($directory) > 234) { + throw new InvalidArgumentException(sprintf('Cache directory too long (%s)', $directory)); + } + + $this->directory = $directory; + } + + /** + * {@inheritdoc} + */ + protected function doClear(string $namespace) + { + $ok = true; + + foreach ($this->scanHashDir($this->directory) as $file) { + if ('' !== $namespace && 0 !== strpos($this->getFileKey($file), $namespace)) { + continue; + } + + $ok = ($this->doUnlink($file) || !file_exists($file)) && $ok; + } + + return $ok; + } + + /** + * {@inheritdoc} + */ + protected function doDelete(array $ids) + { + $ok = true; + + foreach ($ids as $id) { + $file = $this->getFile($id); + $ok = (!file_exists($file) || $this->doUnlink($file) || !file_exists($file)) && $ok; + } + + return $ok; + } + + protected function doUnlink($file) + { + return @unlink($file); + } + + private function write(string $file, string $data, int $expiresAt = null) + { + set_error_handler(__CLASS__.'::throwError'); + try { + if (null === $this->tmp) { + $this->tmp = $this->directory.uniqid('', true); + } + file_put_contents($this->tmp, $data); + + if (null !== $expiresAt) { + touch($this->tmp, $expiresAt); + } + + return rename($this->tmp, $file); + } finally { + restore_error_handler(); + } + } + + private function getFile(string $id, bool $mkdir = false, string $directory = null) + { + // Use MD5 to favor speed over security, which is not an issue here + $hash = str_replace('/', '-', base64_encode(hash('md5', static::class.$id, true))); + $dir = ($directory ?? $this->directory).strtoupper($hash[0].\DIRECTORY_SEPARATOR.$hash[1].\DIRECTORY_SEPARATOR); + + if ($mkdir && !file_exists($dir)) { + @mkdir($dir, 0777, true); + } + + return $dir.substr($hash, 2, 20); + } + + private function getFileKey(string $file): string + { + return ''; + } + + private function scanHashDir(string $directory): \Generator + { + if (!file_exists($directory)) { + return; + } + + $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + + for ($i = 0; $i < 38; ++$i) { + if (!file_exists($directory.$chars[$i])) { + continue; + } + + for ($j = 0; $j < 38; ++$j) { + if (!file_exists($dir = $directory.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j])) { + continue; + } + + foreach (@scandir($dir, SCANDIR_SORT_NONE) ?: [] as $file) { + if ('.' !== $file && '..' !== $file) { + yield $dir.\DIRECTORY_SEPARATOR.$file; + } + } + } + } + } + + /** + * @internal + */ + public static function throwError($type, $message, $file, $line) + { + throw new \ErrorException($message, 0, $type, $file, $line); + } + + /** + * @return array + */ + public function __sleep() + { + throw new \BadMethodCallException('Cannot serialize '.__CLASS__); + } + + public function __wakeup() + { + throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); + } + + public function __destruct() + { + if (method_exists(parent::class, '__destruct')) { + parent::__destruct(); + } + if (null !== $this->tmp && file_exists($this->tmp)) { + unlink($this->tmp); + } + } +} diff --git a/vendor/symfony/cache/Traits/FilesystemTrait.php b/vendor/symfony/cache/Traits/FilesystemTrait.php new file mode 100644 index 0000000..d6926c7 --- /dev/null +++ b/vendor/symfony/cache/Traits/FilesystemTrait.php @@ -0,0 +1,124 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Symfony\Component\Cache\Exception\CacheException; + +/** + * @author Nicolas Grekas + * @author Rob Frawley 2nd + * + * @internal + */ +trait FilesystemTrait +{ + use FilesystemCommonTrait; + + private $marshaller; + + /** + * @return bool + */ + public function prune() + { + $time = time(); + $pruned = true; + + foreach ($this->scanHashDir($this->directory) as $file) { + if (!$h = @fopen($file, 'rb')) { + continue; + } + + if (($expiresAt = (int) fgets($h)) && $time >= $expiresAt) { + fclose($h); + $pruned = @unlink($file) && !file_exists($file) && $pruned; + } else { + fclose($h); + } + } + + return $pruned; + } + + /** + * {@inheritdoc} + */ + protected function doFetch(array $ids) + { + $values = []; + $now = time(); + + foreach ($ids as $id) { + $file = $this->getFile($id); + if (!file_exists($file) || !$h = @fopen($file, 'rb')) { + continue; + } + if (($expiresAt = (int) fgets($h)) && $now >= $expiresAt) { + fclose($h); + @unlink($file); + } else { + $i = rawurldecode(rtrim(fgets($h))); + $value = stream_get_contents($h); + fclose($h); + if ($i === $id) { + $values[$id] = $this->marshaller->unmarshall($value); + } + } + } + + return $values; + } + + /** + * {@inheritdoc} + */ + protected function doHave(string $id) + { + $file = $this->getFile($id); + + return file_exists($file) && (@filemtime($file) > time() || $this->doFetch([$id])); + } + + /** + * {@inheritdoc} + */ + protected function doSave(array $values, int $lifetime) + { + $expiresAt = $lifetime ? (time() + $lifetime) : 0; + $values = $this->marshaller->marshall($values, $failed); + + foreach ($values as $id => $value) { + if (!$this->write($this->getFile($id, true), $expiresAt."\n".rawurlencode($id)."\n".$value, $expiresAt)) { + $failed[] = $id; + } + } + + if ($failed && !is_writable($this->directory)) { + throw new CacheException(sprintf('Cache directory is not writable (%s)', $this->directory)); + } + + return $failed; + } + + private function getFileKey(string $file): string + { + if (!$h = @fopen($file, 'rb')) { + return ''; + } + + fgets($h); // expiry + $encodedKey = fgets($h); + fclose($h); + + return rawurldecode(rtrim($encodedKey)); + } +} diff --git a/vendor/symfony/cache/Traits/ProxyTrait.php b/vendor/symfony/cache/Traits/ProxyTrait.php new file mode 100644 index 0000000..c86f360 --- /dev/null +++ b/vendor/symfony/cache/Traits/ProxyTrait.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Contracts\Service\ResetInterface; + +/** + * @author Nicolas Grekas + * + * @internal + */ +trait ProxyTrait +{ + private $pool; + + /** + * {@inheritdoc} + */ + public function prune() + { + return $this->pool instanceof PruneableInterface && $this->pool->prune(); + } + + /** + * {@inheritdoc} + */ + public function reset() + { + if ($this->pool instanceof ResetInterface) { + $this->pool->reset(); + } + } +} diff --git a/vendor/symfony/cache/Traits/RedisClusterProxy.php b/vendor/symfony/cache/Traits/RedisClusterProxy.php new file mode 100644 index 0000000..73c6a4f --- /dev/null +++ b/vendor/symfony/cache/Traits/RedisClusterProxy.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +/** + * @author Alessandro Chitolina + * + * @internal + */ +class RedisClusterProxy +{ + private $redis; + private $initializer; + + public function __construct(\Closure $initializer) + { + $this->initializer = $initializer; + } + + public function __call(string $method, array $args) + { + $this->redis ?: $this->redis = $this->initializer->__invoke(); + + return $this->redis->{$method}(...$args); + } + + public function hscan($strKey, &$iIterator, $strPattern = null, $iCount = null) + { + $this->redis ?: $this->redis = $this->initializer->__invoke(); + + return $this->redis->hscan($strKey, $iIterator, $strPattern, $iCount); + } + + public function scan(&$iIterator, $strPattern = null, $iCount = null) + { + $this->redis ?: $this->redis = $this->initializer->__invoke(); + + return $this->redis->scan($iIterator, $strPattern, $iCount); + } + + public function sscan($strKey, &$iIterator, $strPattern = null, $iCount = null) + { + $this->redis ?: $this->redis = $this->initializer->__invoke(); + + return $this->redis->sscan($strKey, $iIterator, $strPattern, $iCount); + } + + public function zscan($strKey, &$iIterator, $strPattern = null, $iCount = null) + { + $this->redis ?: $this->redis = $this->initializer->__invoke(); + + return $this->redis->zscan($strKey, $iIterator, $strPattern, $iCount); + } +} diff --git a/vendor/symfony/cache/Traits/RedisProxy.php b/vendor/symfony/cache/Traits/RedisProxy.php new file mode 100644 index 0000000..ec5cfab --- /dev/null +++ b/vendor/symfony/cache/Traits/RedisProxy.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class RedisProxy +{ + private $redis; + private $initializer; + private $ready = false; + + public function __construct(\Redis $redis, \Closure $initializer) + { + $this->redis = $redis; + $this->initializer = $initializer; + } + + public function __call(string $method, array $args) + { + $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); + + return $this->redis->{$method}(...$args); + } + + public function hscan($strKey, &$iIterator, $strPattern = null, $iCount = null) + { + $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); + + return $this->redis->hscan($strKey, $iIterator, $strPattern, $iCount); + } + + public function scan(&$iIterator, $strPattern = null, $iCount = null) + { + $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); + + return $this->redis->scan($iIterator, $strPattern, $iCount); + } + + public function sscan($strKey, &$iIterator, $strPattern = null, $iCount = null) + { + $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); + + return $this->redis->sscan($strKey, $iIterator, $strPattern, $iCount); + } + + public function zscan($strKey, &$iIterator, $strPattern = null, $iCount = null) + { + $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); + + return $this->redis->zscan($strKey, $iIterator, $strPattern, $iCount); + } +} diff --git a/vendor/symfony/cache/Traits/RedisTrait.php b/vendor/symfony/cache/Traits/RedisTrait.php new file mode 100644 index 0000000..5a8460a --- /dev/null +++ b/vendor/symfony/cache/Traits/RedisTrait.php @@ -0,0 +1,511 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Predis\Connection\Aggregate\ClusterInterface; +use Predis\Connection\Aggregate\RedisCluster; +use Predis\Response\Status; +use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; + +/** + * @author Aurimas Niekis + * @author Nicolas Grekas + * + * @internal + */ +trait RedisTrait +{ + private static $defaultConnectionOptions = [ + 'class' => null, + 'persistent' => 0, + 'persistent_id' => null, + 'timeout' => 30, + 'read_timeout' => 0, + 'retry_interval' => 0, + 'tcp_keepalive' => 0, + 'lazy' => null, + 'redis_cluster' => false, + 'redis_sentinel' => null, + 'dbindex' => 0, + 'failover' => 'none', + ]; + private $redis; + private $marshaller; + + /** + * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface $redisClient + */ + private function init($redisClient, string $namespace, int $defaultLifetime, ?MarshallerInterface $marshaller) + { + parent::__construct($namespace, $defaultLifetime); + + if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) { + throw new InvalidArgumentException(sprintf('RedisAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0])); + } + + if (!$redisClient instanceof \Redis && !$redisClient instanceof \RedisArray && !$redisClient instanceof \RedisCluster && !$redisClient instanceof \Predis\ClientInterface && !$redisClient instanceof RedisProxy && !$redisClient instanceof RedisClusterProxy) { + throw new InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, %s given.', __METHOD__, \is_object($redisClient) ? \get_class($redisClient) : \gettype($redisClient))); + } + + if ($redisClient instanceof \Predis\ClientInterface && $redisClient->getOptions()->exceptions) { + $options = clone $redisClient->getOptions(); + \Closure::bind(function () { $this->options['exceptions'] = false; }, $options, $options)(); + $redisClient = new $redisClient($redisClient->getConnection(), $options); + } + + $this->redis = $redisClient; + $this->marshaller = $marshaller ?? new DefaultMarshaller(); + } + + /** + * Creates a Redis connection using a DSN configuration. + * + * Example DSN: + * - redis://localhost + * - redis://example.com:1234 + * - redis://secret@example.com/13 + * - redis:///var/run/redis.sock + * - redis://secret@/var/run/redis.sock/13 + * + * @param string $dsn + * @param array $options See self::$defaultConnectionOptions + * + * @throws InvalidArgumentException when the DSN is invalid + * + * @return \Redis|\RedisCluster|\Predis\ClientInterface According to the "class" option + */ + public static function createConnection($dsn, array $options = []) + { + if (0 === strpos($dsn, 'redis:')) { + $scheme = 'redis'; + } elseif (0 === strpos($dsn, 'rediss:')) { + $scheme = 'rediss'; + } else { + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s does not start with "redis:" or "rediss".', $dsn)); + } + + if (!\extension_loaded('redis') && !class_exists(\Predis\Client::class)) { + throw new CacheException(sprintf('Cannot find the "redis" extension nor the "predis/predis" package: %s', $dsn)); + } + + $params = preg_replace_callback('#^'.$scheme.':(//)?(?:(?:[^:@]*+:)?([^@]*+)@)?#', function ($m) use (&$auth) { + if (isset($m[2])) { + $auth = $m[2]; + } + + return 'file:'.($m[1] ?? ''); + }, $dsn); + + if (false === $params = parse_url($params)) { + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s', $dsn)); + } + + $query = $hosts = []; + + if (isset($params['query'])) { + parse_str($params['query'], $query); + + if (isset($query['host'])) { + if (!\is_array($hosts = $query['host'])) { + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s', $dsn)); + } + foreach ($hosts as $host => $parameters) { + if (\is_string($parameters)) { + parse_str($parameters, $parameters); + } + if (false === $i = strrpos($host, ':')) { + $hosts[$host] = ['scheme' => 'tcp', 'host' => $host, 'port' => 6379] + $parameters; + } elseif ($port = (int) substr($host, 1 + $i)) { + $hosts[$host] = ['scheme' => 'tcp', 'host' => substr($host, 0, $i), 'port' => $port] + $parameters; + } else { + $hosts[$host] = ['scheme' => 'unix', 'path' => substr($host, 0, $i)] + $parameters; + } + } + $hosts = array_values($hosts); + } + } + + if (isset($params['host']) || isset($params['path'])) { + if (!isset($params['dbindex']) && isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { + $params['dbindex'] = $m[1]; + $params['path'] = substr($params['path'], 0, -\strlen($m[0])); + } + + if (isset($params['host'])) { + array_unshift($hosts, ['scheme' => 'tcp', 'host' => $params['host'], 'port' => $params['port'] ?? 6379]); + } else { + array_unshift($hosts, ['scheme' => 'unix', 'path' => $params['path']]); + } + } + + if (!$hosts) { + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s', $dsn)); + } + + if (isset($params['redis_sentinel']) && !class_exists(\Predis\Client::class)) { + throw new CacheException(sprintf('Redis Sentinel support requires the "predis/predis" package: %s', $dsn)); + } + + $params += $query + $options + self::$defaultConnectionOptions; + + if (null === $params['class'] && !isset($params['redis_sentinel']) && \extension_loaded('redis')) { + $class = $params['redis_cluster'] ? \RedisCluster::class : (1 < \count($hosts) ? \RedisArray::class : \Redis::class); + } else { + $class = null === $params['class'] ? \Predis\Client::class : $params['class']; + } + + if (is_a($class, \Redis::class, true)) { + $connect = $params['persistent'] || $params['persistent_id'] ? 'pconnect' : 'connect'; + $redis = new $class(); + + $initializer = function ($redis) use ($connect, $params, $dsn, $auth, $hosts) { + try { + @$redis->{$connect}($hosts[0]['host'] ?? $hosts[0]['path'], $hosts[0]['port'] ?? null, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval']); + } catch (\RedisException $e) { + throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e->getMessage(), $dsn)); + } + + set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); + $isConnected = $redis->isConnected(); + restore_error_handler(); + if (!$isConnected) { + $error = preg_match('/^Redis::p?connect\(\): (.*)/', $error, $error) ? sprintf(' (%s)', $error[1]) : ''; + throw new InvalidArgumentException(sprintf('Redis connection failed%s: %s', $error, $dsn)); + } + + if ((null !== $auth && !$redis->auth($auth)) + || ($params['dbindex'] && !$redis->select($params['dbindex'])) + || ($params['read_timeout'] && !$redis->setOption(\Redis::OPT_READ_TIMEOUT, $params['read_timeout'])) + ) { + $e = preg_replace('/^ERR /', '', $redis->getLastError()); + throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e, $dsn)); + } + + if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { + $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); + } + + return true; + }; + + if ($params['lazy']) { + $redis = new RedisProxy($redis, $initializer); + } else { + $initializer($redis); + } + } elseif (is_a($class, \RedisArray::class, true)) { + foreach ($hosts as $i => $host) { + $hosts[$i] = 'tcp' === $host['scheme'] ? $host['host'].':'.$host['port'] : $host['path']; + } + $params['lazy_connect'] = $params['lazy'] ?? true; + $params['connect_timeout'] = $params['timeout']; + + try { + $redis = new $class($hosts, $params); + } catch (\RedisClusterException $e) { + throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e->getMessage(), $dsn)); + } + + if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { + $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); + } + } elseif (is_a($class, \RedisCluster::class, true)) { + $initializer = function () use ($class, $params, $dsn, $hosts) { + foreach ($hosts as $i => $host) { + $hosts[$i] = 'tcp' === $host['scheme'] ? $host['host'].':'.$host['port'] : $host['path']; + } + + try { + $redis = new $class(null, $hosts, $params['timeout'], $params['read_timeout'], (bool) $params['persistent']); + } catch (\RedisClusterException $e) { + throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e->getMessage(), $dsn)); + } + + if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { + $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); + } + switch ($params['failover']) { + case 'error': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_ERROR); break; + case 'distribute': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_DISTRIBUTE); break; + case 'slaves': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES); break; + } + + return $redis; + }; + + $redis = $params['lazy'] ? new RedisClusterProxy($initializer) : $initializer(); + } elseif (is_a($class, \Predis\ClientInterface::class, true)) { + if ($params['redis_cluster']) { + $params['cluster'] = 'redis'; + if (isset($params['redis_sentinel'])) { + throw new InvalidArgumentException(sprintf('Cannot use both "redis_cluster" and "redis_sentinel" at the same time: %s', $dsn)); + } + } elseif (isset($params['redis_sentinel'])) { + $params['replication'] = 'sentinel'; + $params['service'] = $params['redis_sentinel']; + } + $params += ['parameters' => []]; + $params['parameters'] += [ + 'persistent' => $params['persistent'], + 'timeout' => $params['timeout'], + 'read_write_timeout' => $params['read_timeout'], + 'tcp_nodelay' => true, + ]; + if ($params['dbindex']) { + $params['parameters']['database'] = $params['dbindex']; + } + if (null !== $auth) { + $params['parameters']['password'] = $auth; + } + if (1 === \count($hosts) && !($params['redis_cluster'] || $params['redis_sentinel'])) { + $hosts = $hosts[0]; + } elseif (\in_array($params['failover'], ['slaves', 'distribute'], true) && !isset($params['replication'])) { + $params['replication'] = true; + $hosts[0] += ['alias' => 'master']; + } + $params['exceptions'] = false; + + $redis = new $class($hosts, array_diff_key($params, self::$defaultConnectionOptions)); + if (isset($params['redis_sentinel'])) { + $redis->getConnection()->setSentinelTimeout($params['timeout']); + } + } elseif (class_exists($class, false)) { + throw new InvalidArgumentException(sprintf('"%s" is not a subclass of "Redis", "RedisArray", "RedisCluster" nor "Predis\ClientInterface".', $class)); + } else { + throw new InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); + } + + return $redis; + } + + /** + * {@inheritdoc} + */ + protected function doFetch(array $ids) + { + if (!$ids) { + return []; + } + + $result = []; + + if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) { + $values = $this->pipeline(function () use ($ids) { + foreach ($ids as $id) { + yield 'get' => [$id]; + } + }); + } else { + $values = $this->redis->mget($ids); + + if (!\is_array($values) || \count($values) !== \count($ids)) { + return []; + } + + $values = array_combine($ids, $values); + } + + foreach ($values as $id => $v) { + if ($v) { + $result[$id] = $this->marshaller->unmarshall($v); + } + } + + return $result; + } + + /** + * {@inheritdoc} + */ + protected function doHave(string $id) + { + return (bool) $this->redis->exists($id); + } + + /** + * {@inheritdoc} + */ + protected function doClear(string $namespace) + { + $cleared = true; + if ($this->redis instanceof \Predis\ClientInterface) { + $evalArgs = [0, $namespace]; + } else { + $evalArgs = [[$namespace], 0]; + } + + foreach ($this->getHosts() as $host) { + if (!isset($namespace[0])) { + $cleared = $host->flushDb() && $cleared; + continue; + } + + $info = $host->info('Server'); + $info = isset($info['Server']) ? $info['Server'] : $info; + + if (!version_compare($info['redis_version'], '2.8', '>=')) { + // As documented in Redis documentation (http://redis.io/commands/keys) using KEYS + // can hang your server when it is executed against large databases (millions of items). + // Whenever you hit this scale, you should really consider upgrading to Redis 2.8 or above. + $cleared = $host->eval("local keys=redis.call('KEYS',ARGV[1]..'*') for i=1,#keys,5000 do redis.call('DEL',unpack(keys,i,math.min(i+4999,#keys))) end return 1", $evalArgs[0], $evalArgs[1]) && $cleared; + continue; + } + + $cursor = null; + do { + $keys = $host instanceof \Predis\ClientInterface ? $host->scan($cursor, 'MATCH', $namespace.'*', 'COUNT', 1000) : $host->scan($cursor, $namespace.'*', 1000); + if (isset($keys[1]) && \is_array($keys[1])) { + $cursor = $keys[0]; + $keys = $keys[1]; + } + if ($keys) { + $this->doDelete($keys); + } + } while ($cursor = (int) $cursor); + } + + return $cleared; + } + + /** + * {@inheritdoc} + */ + protected function doDelete(array $ids) + { + if (!$ids) { + return true; + } + + if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) { + $this->pipeline(function () use ($ids) { + foreach ($ids as $id) { + yield 'del' => [$id]; + } + })->rewind(); + } else { + $this->redis->del($ids); + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doSave(array $values, int $lifetime) + { + if (!$values = $this->marshaller->marshall($values, $failed)) { + return $failed; + } + + $results = $this->pipeline(function () use ($values, $lifetime) { + foreach ($values as $id => $value) { + if (0 >= $lifetime) { + yield 'set' => [$id, $value]; + } else { + yield 'setEx' => [$id, $lifetime, $value]; + } + } + }); + + foreach ($results as $id => $result) { + if (true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) { + $failed[] = $id; + } + } + + return $failed; + } + + private function pipeline(\Closure $generator, $redis = null): \Generator + { + $ids = []; + $redis = $redis ?? $this->redis; + + if ($redis instanceof RedisClusterProxy || $redis instanceof \RedisCluster || ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof RedisCluster)) { + // phpredis & predis don't support pipelining with RedisCluster + // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining + // see https://github.com/nrk/predis/issues/267#issuecomment-123781423 + $results = []; + foreach ($generator() as $command => $args) { + $results[] = $redis->{$command}(...$args); + $ids[] = 'eval' === $command ? ($redis instanceof \Predis\ClientInterface ? $args[2] : $args[1][0]) : $args[0]; + } + } elseif ($redis instanceof \Predis\ClientInterface) { + $results = $redis->pipeline(static function ($redis) use ($generator, &$ids) { + foreach ($generator() as $command => $args) { + $redis->{$command}(...$args); + $ids[] = 'eval' === $command ? $args[2] : $args[0]; + } + }); + } elseif ($redis instanceof \RedisArray) { + $connections = $results = $ids = []; + foreach ($generator() as $command => $args) { + $id = 'eval' === $command ? $args[1][0] : $args[0]; + if (!isset($connections[$h = $redis->_target($id)])) { + $connections[$h] = [$redis->_instance($h), -1]; + $connections[$h][0]->multi(\Redis::PIPELINE); + } + $connections[$h][0]->{$command}(...$args); + $results[] = [$h, ++$connections[$h][1]]; + $ids[] = $id; + } + foreach ($connections as $h => $c) { + $connections[$h] = $c[0]->exec(); + } + foreach ($results as $k => list($h, $c)) { + $results[$k] = $connections[$h][$c]; + } + } else { + $redis->multi(\Redis::PIPELINE); + foreach ($generator() as $command => $args) { + $redis->{$command}(...$args); + $ids[] = 'eval' === $command ? $args[1][0] : $args[0]; + } + $results = $redis->exec(); + } + + foreach ($ids as $k => $id) { + yield $id => $results[$k]; + } + } + + private function getHosts(): array + { + $hosts = [$this->redis]; + if ($this->redis instanceof \Predis\ClientInterface) { + $connection = $this->redis->getConnection(); + if ($connection instanceof ClusterInterface && $connection instanceof \Traversable) { + $hosts = []; + foreach ($connection as $c) { + $hosts[] = new \Predis\Client($c); + } + } + } elseif ($this->redis instanceof \RedisArray) { + $hosts = []; + foreach ($this->redis->_hosts() as $host) { + $hosts[] = $this->redis->_instance($host); + } + } elseif ($this->redis instanceof RedisClusterProxy || $this->redis instanceof \RedisCluster) { + $hosts = []; + foreach ($this->redis->_masters() as $host) { + $hosts[] = $h = new \Redis(); + $h->connect($host[0], $host[1]); + } + } + + return $hosts; + } +} diff --git a/vendor/symfony/cache/composer.json b/vendor/symfony/cache/composer.json new file mode 100644 index 0000000..6e23abc --- /dev/null +++ b/vendor/symfony/cache/composer.json @@ -0,0 +1,59 @@ +{ + "name": "symfony/cache", + "type": "library", + "description": "Symfony Cache component with PSR-6, PSR-16, and tags", + "keywords": ["caching", "psr6"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "provide": { + "psr/cache-implementation": "1.0", + "psr/simple-cache-implementation": "1.0", + "symfony/cache-implementation": "1.0" + }, + "require": { + "php": "^7.2.5", + "psr/cache": "~1.0", + "psr/log": "~1.0", + "symfony/cache-contracts": "^1.1.7|^2", + "symfony/service-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/cache": "~1.6", + "doctrine/dbal": "~2.5", + "predis/predis": "~1.1", + "psr/simple-cache": "^1.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "conflict": { + "doctrine/dbal": "<2.5", + "symfony/dependency-injection": "<4.4", + "symfony/http-kernel": "<4.4", + "symfony/var-dumper": "<4.4" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Cache\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/config/.gitattributes b/vendor/symfony/config/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/config/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/config/CHANGELOG.md b/vendor/symfony/config/CHANGELOG.md new file mode 100644 index 0000000..14743e4 --- /dev/null +++ b/vendor/symfony/config/CHANGELOG.md @@ -0,0 +1,116 @@ +CHANGELOG +========= + +5.0.0 +----- + + * Dropped support for constructing a `TreeBuilder` without passing root node information. + * Removed the `root()` method in `TreeBuilder`, pass the root node information to the constructor instead + * Added method `getChildNodeDefinitions()` to ParentNodeDefinitionInterface + * Removed `FileLoaderLoadException`, use `LoaderLoadException` instead + +4.4.0 +----- + + * added a way to exclude patterns of resources from being imported by the `import()` method + +4.3.0 +----- + + * deprecated using environment variables with `cannotBeEmpty()` if the value is validated with `validate()` + * made `Resource\*` classes final and not implement `Serializable` anymore + * deprecated the `root()` method in `TreeBuilder`, pass the root node information to the constructor instead + +4.2.0 +----- + + * deprecated constructing a `TreeBuilder` without passing root node information + * renamed `FileLoaderLoadException` to `LoaderLoadException` + +4.1.0 +----- + + * added `setPathSeparator` method to `NodeBuilder` class + * added third `$pathSeparator` constructor argument to `BaseNode` + * the `Processor` class has been made final + +4.0.0 +----- + + * removed `ConfigCachePass` + +3.4.0 +----- + + * added `setDeprecated()` method to indicate a deprecated node + * added `XmlUtils::parse()` method to parse an XML string + * deprecated `ConfigCachePass` + +3.3.0 +----- + + * added `ReflectionClassResource` class + * added second `$exists` constructor argument to `ClassExistenceResource` + * made `ClassExistenceResource` work with interfaces and traits + * added `ConfigCachePass` (originally in FrameworkBundle) + * added `castToArray()` helper to turn any config value into an array + +3.0.0 +----- + + * removed `ReferenceDumper` class + * removed the `ResourceInterface::isFresh()` method + * removed `BCResourceInterfaceChecker` class + * removed `ResourceInterface::getResource()` method + +2.8.0 +----- + +The edge case of defining just one value for nodes of type Enum is now allowed: + +```php +$rootNode + ->children() + ->enumNode('variable') + ->values(['value']) + ->end() + ->end() +; +``` + +Before: `InvalidArgumentException` (variable must contain at least two +distinct elements). +After: the code will work as expected and it will restrict the values of the +`variable` option to just `value`. + + * deprecated the `ResourceInterface::isFresh()` method. If you implement custom resource types and they + can be validated that way, make them implement the new `SelfCheckingResourceInterface`. + * deprecated the getResource() method in ResourceInterface. You can still call this method + on concrete classes implementing the interface, but it does not make sense at the interface + level as you need to know about the particular type of resource at hand to understand the + semantics of the returned value. + +2.7.0 +----- + + * added `ConfigCacheInterface`, `ConfigCacheFactoryInterface` and a basic `ConfigCacheFactory` + implementation to delegate creation of ConfigCache instances + +2.2.0 +----- + + * added `ArrayNodeDefinition::canBeEnabled()` and `ArrayNodeDefinition::canBeDisabled()` + to ease configuration when some sections are respectively disabled / enabled + by default. + * added a `normalizeKeys()` method for array nodes (to avoid key normalization) + * added numerical type handling for config definitions + * added convenience methods for optional configuration sections to `ArrayNodeDefinition` + * added a utils class for XML manipulations + +2.1.0 +----- + + * added a way to add documentation on configuration + * implemented `Serializable` on resources + * `LoaderResolverInterface` is now used instead of `LoaderResolver` for type + hinting diff --git a/vendor/symfony/config/ConfigCache.php b/vendor/symfony/config/ConfigCache.php new file mode 100644 index 0000000..053059b --- /dev/null +++ b/vendor/symfony/config/ConfigCache.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config; + +use Symfony\Component\Config\Resource\SelfCheckingResourceChecker; + +/** + * ConfigCache caches arbitrary content in files on disk. + * + * When in debug mode, those metadata resources that implement + * \Symfony\Component\Config\Resource\SelfCheckingResourceInterface will + * be used to check cache freshness. + * + * @author Fabien Potencier + * @author Matthias Pigulla + */ +class ConfigCache extends ResourceCheckerConfigCache +{ + private $debug; + + /** + * @param string $file The absolute cache path + * @param bool $debug Whether debugging is enabled or not + */ + public function __construct(string $file, bool $debug) + { + $this->debug = $debug; + + $checkers = []; + if (true === $this->debug) { + $checkers = [new SelfCheckingResourceChecker()]; + } + + parent::__construct($file, $checkers); + } + + /** + * Checks if the cache is still fresh. + * + * This implementation always returns true when debug is off and the + * cache file exists. + * + * @return bool true if the cache is fresh, false otherwise + */ + public function isFresh() + { + if (!$this->debug && is_file($this->getPath())) { + return true; + } + + return parent::isFresh(); + } +} diff --git a/vendor/symfony/config/ConfigCacheFactory.php b/vendor/symfony/config/ConfigCacheFactory.php new file mode 100644 index 0000000..11fd3cb --- /dev/null +++ b/vendor/symfony/config/ConfigCacheFactory.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config; + +/** + * Basic implementation of ConfigCacheFactoryInterface that + * creates an instance of the default ConfigCache. + * + * This factory and/or cache do not support cache validation + * by means of ResourceChecker instances (that is, service-based). + * + * @author Matthias Pigulla + */ +class ConfigCacheFactory implements ConfigCacheFactoryInterface +{ + private $debug; + + /** + * @param bool $debug The debug flag to pass to ConfigCache + */ + public function __construct(bool $debug) + { + $this->debug = $debug; + } + + /** + * {@inheritdoc} + */ + public function cache(string $file, callable $callback) + { + $cache = new ConfigCache($file, $this->debug); + if (!$cache->isFresh()) { + $callback($cache); + } + + return $cache; + } +} diff --git a/vendor/symfony/config/ConfigCacheFactoryInterface.php b/vendor/symfony/config/ConfigCacheFactoryInterface.php new file mode 100644 index 0000000..7dfa0f2 --- /dev/null +++ b/vendor/symfony/config/ConfigCacheFactoryInterface.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config; + +/** + * Interface for a ConfigCache factory. This factory creates + * an instance of ConfigCacheInterface and initializes the + * cache if necessary. + * + * @author Matthias Pigulla + */ +interface ConfigCacheFactoryInterface +{ + /** + * Creates a cache instance and (re-)initializes it if necessary. + * + * @param string $file The absolute cache file path + * @param callable $callable The callable to be executed when the cache needs to be filled (i. e. is not fresh). The cache will be passed as the only parameter to this callback + * + * @return ConfigCacheInterface The cache instance + */ + public function cache(string $file, callable $callable); +} diff --git a/vendor/symfony/config/ConfigCacheInterface.php b/vendor/symfony/config/ConfigCacheInterface.php new file mode 100644 index 0000000..001e7e7 --- /dev/null +++ b/vendor/symfony/config/ConfigCacheInterface.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config; + +use Symfony\Component\Config\Resource\ResourceInterface; + +/** + * Interface for ConfigCache. + * + * @author Matthias Pigulla + */ +interface ConfigCacheInterface +{ + /** + * Gets the cache file path. + * + * @return string The cache file path + */ + public function getPath(); + + /** + * Checks if the cache is still fresh. + * + * This check should take the metadata passed to the write() method into consideration. + * + * @return bool Whether the cache is still fresh + */ + public function isFresh(); + + /** + * Writes the given content into the cache file. Metadata will be stored + * independently and can be used to check cache freshness at a later time. + * + * @param string $content The content to write into the cache + * @param ResourceInterface[]|null $metadata An array of ResourceInterface instances + * + * @throws \RuntimeException When the cache file cannot be written + */ + public function write(string $content, array $metadata = null); +} diff --git a/vendor/symfony/config/Definition/ArrayNode.php b/vendor/symfony/config/Definition/ArrayNode.php new file mode 100644 index 0000000..88e8eaf --- /dev/null +++ b/vendor/symfony/config/Definition/ArrayNode.php @@ -0,0 +1,406 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; +use Symfony\Component\Config\Definition\Exception\InvalidTypeException; +use Symfony\Component\Config\Definition\Exception\UnsetKeyException; + +/** + * Represents an Array node in the config tree. + * + * @author Johannes M. Schmitt + */ +class ArrayNode extends BaseNode implements PrototypeNodeInterface +{ + protected $xmlRemappings = []; + protected $children = []; + protected $allowFalse = false; + protected $allowNewKeys = true; + protected $addIfNotSet = false; + protected $performDeepMerging = true; + protected $ignoreExtraKeys = false; + protected $removeExtraKeys = true; + protected $normalizeKeys = true; + + public function setNormalizeKeys($normalizeKeys) + { + $this->normalizeKeys = (bool) $normalizeKeys; + } + + /** + * {@inheritdoc} + * + * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML. + * After running this method, all keys are normalized to foo_bar. + * + * If you have a mixed key like foo-bar_moo, it will not be altered. + * The key will also not be altered if the target key already exists. + */ + protected function preNormalize($value) + { + if (!$this->normalizeKeys || !\is_array($value)) { + return $value; + } + + $normalized = []; + + foreach ($value as $k => $v) { + if (false !== strpos($k, '-') && false === strpos($k, '_') && !\array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) { + $normalized[$normalizedKey] = $v; + } else { + $normalized[$k] = $v; + } + } + + return $normalized; + } + + /** + * Retrieves the children of this node. + * + * @return array The children + */ + public function getChildren() + { + return $this->children; + } + + /** + * Sets the xml remappings that should be performed. + * + * @param array $remappings An array of the form [[string, string]] + */ + public function setXmlRemappings(array $remappings) + { + $this->xmlRemappings = $remappings; + } + + /** + * Gets the xml remappings that should be performed. + * + * @return array an array of the form [[string, string]] + */ + public function getXmlRemappings() + { + return $this->xmlRemappings; + } + + /** + * Sets whether to add default values for this array if it has not been + * defined in any of the configuration files. + */ + public function setAddIfNotSet(bool $boolean) + { + $this->addIfNotSet = $boolean; + } + + /** + * Sets whether false is allowed as value indicating that the array should be unset. + */ + public function setAllowFalse(bool $allow) + { + $this->allowFalse = $allow; + } + + /** + * Sets whether new keys can be defined in subsequent configurations. + */ + public function setAllowNewKeys(bool $allow) + { + $this->allowNewKeys = $allow; + } + + /** + * Sets if deep merging should occur. + */ + public function setPerformDeepMerging(bool $boolean) + { + $this->performDeepMerging = $boolean; + } + + /** + * Whether extra keys should just be ignored without an exception. + * + * @param bool $boolean To allow extra keys + * @param bool $remove To remove extra keys + */ + public function setIgnoreExtraKeys(bool $boolean, bool $remove = true) + { + $this->ignoreExtraKeys = $boolean; + $this->removeExtraKeys = $this->ignoreExtraKeys && $remove; + } + + /** + * {@inheritdoc} + */ + public function setName(string $name) + { + $this->name = $name; + } + + /** + * {@inheritdoc} + */ + public function hasDefaultValue() + { + return $this->addIfNotSet; + } + + /** + * {@inheritdoc} + */ + public function getDefaultValue() + { + if (!$this->hasDefaultValue()) { + throw new \RuntimeException(sprintf('The node at path "%s" has no default value.', $this->getPath())); + } + + $defaults = []; + foreach ($this->children as $name => $child) { + if ($child->hasDefaultValue()) { + $defaults[$name] = $child->getDefaultValue(); + } + } + + return $defaults; + } + + /** + * Adds a child node. + * + * @throws \InvalidArgumentException when the child node has no name + * @throws \InvalidArgumentException when the child node's name is not unique + */ + public function addChild(NodeInterface $node) + { + $name = $node->getName(); + if (!\strlen($name)) { + throw new \InvalidArgumentException('Child nodes must be named.'); + } + if (isset($this->children[$name])) { + throw new \InvalidArgumentException(sprintf('A child node named "%s" already exists.', $name)); + } + + $this->children[$name] = $node; + } + + /** + * Finalizes the value of this node. + * + * @param mixed $value + * + * @return mixed The finalised value + * + * @throws UnsetKeyException + * @throws InvalidConfigurationException if the node doesn't have enough children + */ + protected function finalizeValue($value) + { + if (false === $value) { + throw new UnsetKeyException(sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value))); + } + + foreach ($this->children as $name => $child) { + if (!\array_key_exists($name, $value)) { + if ($child->isRequired()) { + $ex = new InvalidConfigurationException(sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath())); + $ex->setPath($this->getPath()); + + throw $ex; + } + + if ($child->hasDefaultValue()) { + $value[$name] = $child->getDefaultValue(); + } + + continue; + } + + if ($child->isDeprecated()) { + @trigger_error($child->getDeprecationMessage($name, $this->getPath()), E_USER_DEPRECATED); + } + + try { + $value[$name] = $child->finalize($value[$name]); + } catch (UnsetKeyException $e) { + unset($value[$name]); + } + } + + return $value; + } + + /** + * Validates the type of the value. + * + * @param mixed $value + * + * @throws InvalidTypeException + */ + protected function validateType($value) + { + if (!\is_array($value) && (!$this->allowFalse || false !== $value)) { + $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected array, but got %s', $this->getPath(), \gettype($value))); + if ($hint = $this->getInfo()) { + $ex->addHint($hint); + } + $ex->setPath($this->getPath()); + + throw $ex; + } + } + + /** + * Normalizes the value. + * + * @param mixed $value The value to normalize + * + * @return mixed The normalized value + * + * @throws InvalidConfigurationException + */ + protected function normalizeValue($value) + { + if (false === $value) { + return $value; + } + + $value = $this->remapXml($value); + + $normalized = []; + foreach ($value as $name => $val) { + if (isset($this->children[$name])) { + try { + $normalized[$name] = $this->children[$name]->normalize($val); + } catch (UnsetKeyException $e) { + } + unset($value[$name]); + } elseif (!$this->removeExtraKeys) { + $normalized[$name] = $val; + } + } + + // if extra fields are present, throw exception + if (\count($value) && !$this->ignoreExtraKeys) { + $proposals = array_keys($this->children); + sort($proposals); + $guesses = []; + + foreach (array_keys($value) as $subject) { + $minScore = INF; + foreach ($proposals as $proposal) { + $distance = levenshtein($subject, $proposal); + if ($distance <= $minScore && $distance < 3) { + $guesses[$proposal] = $distance; + $minScore = $distance; + } + } + } + + $msg = sprintf('Unrecognized option%s "%s" under "%s"', 1 === \count($value) ? '' : 's', implode(', ', array_keys($value)), $this->getPath()); + + if (\count($guesses)) { + asort($guesses); + $msg .= sprintf('. Did you mean "%s"?', implode('", "', array_keys($guesses))); + } else { + $msg .= sprintf('. Available option%s %s "%s".', 1 === \count($proposals) ? '' : 's', 1 === \count($proposals) ? 'is' : 'are', implode('", "', $proposals)); + } + + $ex = new InvalidConfigurationException($msg); + $ex->setPath($this->getPath()); + + throw $ex; + } + + return $normalized; + } + + /** + * Remaps multiple singular values to a single plural value. + * + * @return array The remapped values + */ + protected function remapXml(array $value) + { + foreach ($this->xmlRemappings as list($singular, $plural)) { + if (!isset($value[$singular])) { + continue; + } + + $value[$plural] = Processor::normalizeConfig($value, $singular, $plural); + unset($value[$singular]); + } + + return $value; + } + + /** + * Merges values together. + * + * @param mixed $leftSide The left side to merge + * @param mixed $rightSide The right side to merge + * + * @return mixed The merged values + * + * @throws InvalidConfigurationException + * @throws \RuntimeException + */ + protected function mergeValues($leftSide, $rightSide) + { + if (false === $rightSide) { + // if this is still false after the last config has been merged the + // finalization pass will take care of removing this key entirely + return false; + } + + if (false === $leftSide || !$this->performDeepMerging) { + return $rightSide; + } + + foreach ($rightSide as $k => $v) { + // no conflict + if (!\array_key_exists($k, $leftSide)) { + if (!$this->allowNewKeys) { + $ex = new InvalidConfigurationException(sprintf('You are not allowed to define new elements for path "%s". Please define all elements for this path in one config file. If you are trying to overwrite an element, make sure you redefine it with the same name.', $this->getPath())); + $ex->setPath($this->getPath()); + + throw $ex; + } + + $leftSide[$k] = $v; + continue; + } + + if (!isset($this->children[$k])) { + if (!$this->ignoreExtraKeys || $this->removeExtraKeys) { + throw new \RuntimeException('merge() expects a normalized config array.'); + } + + $leftSide[$k] = $v; + continue; + } + + $leftSide[$k] = $this->children[$k]->merge($leftSide[$k], $v); + } + + return $leftSide; + } + + /** + * {@inheritdoc} + */ + protected function allowPlaceholders(): bool + { + return false; + } +} diff --git a/vendor/symfony/config/Definition/BaseNode.php b/vendor/symfony/config/Definition/BaseNode.php new file mode 100644 index 0000000..d721620 --- /dev/null +++ b/vendor/symfony/config/Definition/BaseNode.php @@ -0,0 +1,543 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +use Symfony\Component\Config\Definition\Exception\Exception; +use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException; +use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; +use Symfony\Component\Config\Definition\Exception\InvalidTypeException; +use Symfony\Component\Config\Definition\Exception\UnsetKeyException; + +/** + * The base node class. + * + * @author Johannes M. Schmitt + */ +abstract class BaseNode implements NodeInterface +{ + const DEFAULT_PATH_SEPARATOR = '.'; + + private static $placeholderUniquePrefix; + private static $placeholders = []; + + protected $name; + protected $parent; + protected $normalizationClosures = []; + protected $finalValidationClosures = []; + protected $allowOverwrite = true; + protected $required = false; + protected $deprecationMessage = null; + protected $equivalentValues = []; + protected $attributes = []; + protected $pathSeparator; + + private $handlingPlaceholder; + + /** + * @throws \InvalidArgumentException if the name contains a period + */ + public function __construct(?string $name, NodeInterface $parent = null, string $pathSeparator = self::DEFAULT_PATH_SEPARATOR) + { + if (false !== strpos($name = (string) $name, $pathSeparator)) { + throw new \InvalidArgumentException('The name must not contain "'.$pathSeparator.'".'); + } + + $this->name = $name; + $this->parent = $parent; + $this->pathSeparator = $pathSeparator; + } + + /** + * Register possible (dummy) values for a dynamic placeholder value. + * + * Matching configuration values will be processed with a provided value, one by one. After a provided value is + * successfully processed the configuration value is returned as is, thus preserving the placeholder. + * + * @internal + */ + public static function setPlaceholder(string $placeholder, array $values): void + { + if (!$values) { + throw new \InvalidArgumentException('At least one value must be provided.'); + } + + self::$placeholders[$placeholder] = $values; + } + + /** + * Sets a common prefix for dynamic placeholder values. + * + * Matching configuration values will be skipped from being processed and are returned as is, thus preserving the + * placeholder. An exact match provided by {@see setPlaceholder()} might take precedence. + * + * @internal + */ + public static function setPlaceholderUniquePrefix(string $prefix): void + { + self::$placeholderUniquePrefix = $prefix; + } + + /** + * Resets all current placeholders available. + * + * @internal + */ + public static function resetPlaceholders(): void + { + self::$placeholderUniquePrefix = null; + self::$placeholders = []; + } + + public function setAttribute(string $key, $value) + { + $this->attributes[$key] = $value; + } + + /** + * @return mixed + */ + public function getAttribute(string $key, $default = null) + { + return isset($this->attributes[$key]) ? $this->attributes[$key] : $default; + } + + /** + * @return bool + */ + public function hasAttribute(string $key) + { + return isset($this->attributes[$key]); + } + + /** + * @return array + */ + public function getAttributes() + { + return $this->attributes; + } + + public function setAttributes(array $attributes) + { + $this->attributes = $attributes; + } + + public function removeAttribute(string $key) + { + unset($this->attributes[$key]); + } + + /** + * Sets an info message. + */ + public function setInfo(string $info) + { + $this->setAttribute('info', $info); + } + + /** + * Returns info message. + * + * @return string|null The info text + */ + public function getInfo() + { + return $this->getAttribute('info'); + } + + /** + * Sets the example configuration for this node. + * + * @param string|array $example + */ + public function setExample($example) + { + $this->setAttribute('example', $example); + } + + /** + * Retrieves the example configuration for this node. + * + * @return string|array|null The example + */ + public function getExample() + { + return $this->getAttribute('example'); + } + + /** + * Adds an equivalent value. + * + * @param mixed $originalValue + * @param mixed $equivalentValue + */ + public function addEquivalentValue($originalValue, $equivalentValue) + { + $this->equivalentValues[] = [$originalValue, $equivalentValue]; + } + + /** + * Set this node as required. + * + * @param bool $boolean Required node + */ + public function setRequired(bool $boolean) + { + $this->required = $boolean; + } + + /** + * Sets this node as deprecated. + * + * You can use %node% and %path% placeholders in your message to display, + * respectively, the node name and its complete path. + */ + public function setDeprecated(?string $message) + { + $this->deprecationMessage = $message; + } + + /** + * Sets if this node can be overridden. + */ + public function setAllowOverwrite(bool $allow) + { + $this->allowOverwrite = $allow; + } + + /** + * Sets the closures used for normalization. + * + * @param \Closure[] $closures An array of Closures used for normalization + */ + public function setNormalizationClosures(array $closures) + { + $this->normalizationClosures = $closures; + } + + /** + * Sets the closures used for final validation. + * + * @param \Closure[] $closures An array of Closures used for final validation + */ + public function setFinalValidationClosures(array $closures) + { + $this->finalValidationClosures = $closures; + } + + /** + * {@inheritdoc} + */ + public function isRequired() + { + return $this->required; + } + + /** + * Checks if this node is deprecated. + * + * @return bool + */ + public function isDeprecated() + { + return null !== $this->deprecationMessage; + } + + /** + * Returns the deprecated message. + * + * @param string $node the configuration node name + * @param string $path the path of the node + * + * @return string + */ + public function getDeprecationMessage(string $node, string $path) + { + return strtr($this->deprecationMessage, ['%node%' => $node, '%path%' => $path]); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function getPath() + { + if (null !== $this->parent) { + return $this->parent->getPath().$this->pathSeparator.$this->name; + } + + return $this->name; + } + + /** + * {@inheritdoc} + */ + final public function merge($leftSide, $rightSide) + { + if (!$this->allowOverwrite) { + throw new ForbiddenOverwriteException(sprintf('Configuration path "%s" cannot be overwritten. You have to define all options for this path, and any of its sub-paths in one configuration section.', $this->getPath())); + } + + if ($leftSide !== $leftPlaceholders = self::resolvePlaceholderValue($leftSide)) { + foreach ($leftPlaceholders as $leftPlaceholder) { + $this->handlingPlaceholder = $leftSide; + try { + $this->merge($leftPlaceholder, $rightSide); + } finally { + $this->handlingPlaceholder = null; + } + } + + return $rightSide; + } + + if ($rightSide !== $rightPlaceholders = self::resolvePlaceholderValue($rightSide)) { + foreach ($rightPlaceholders as $rightPlaceholder) { + $this->handlingPlaceholder = $rightSide; + try { + $this->merge($leftSide, $rightPlaceholder); + } finally { + $this->handlingPlaceholder = null; + } + } + + return $rightSide; + } + + $this->doValidateType($leftSide); + $this->doValidateType($rightSide); + + return $this->mergeValues($leftSide, $rightSide); + } + + /** + * {@inheritdoc} + */ + final public function normalize($value) + { + $value = $this->preNormalize($value); + + // run custom normalization closures + foreach ($this->normalizationClosures as $closure) { + $value = $closure($value); + } + + // resolve placeholder value + if ($value !== $placeholders = self::resolvePlaceholderValue($value)) { + foreach ($placeholders as $placeholder) { + $this->handlingPlaceholder = $value; + try { + $this->normalize($placeholder); + } finally { + $this->handlingPlaceholder = null; + } + } + + return $value; + } + + // replace value with their equivalent + foreach ($this->equivalentValues as $data) { + if ($data[0] === $value) { + $value = $data[1]; + } + } + + // validate type + $this->doValidateType($value); + + // normalize value + return $this->normalizeValue($value); + } + + /** + * Normalizes the value before any other normalization is applied. + * + * @param mixed $value + * + * @return mixed The normalized array value + */ + protected function preNormalize($value) + { + return $value; + } + + /** + * Returns parent node for this node. + * + * @return NodeInterface|null + */ + public function getParent() + { + return $this->parent; + } + + /** + * {@inheritdoc} + */ + final public function finalize($value) + { + if ($value !== $placeholders = self::resolvePlaceholderValue($value)) { + foreach ($placeholders as $placeholder) { + $this->handlingPlaceholder = $value; + try { + $this->finalize($placeholder); + } finally { + $this->handlingPlaceholder = null; + } + } + + return $value; + } + + $this->doValidateType($value); + + $value = $this->finalizeValue($value); + + // Perform validation on the final value if a closure has been set. + // The closure is also allowed to return another value. + foreach ($this->finalValidationClosures as $closure) { + try { + $value = $closure($value); + } catch (Exception $e) { + if ($e instanceof UnsetKeyException && null !== $this->handlingPlaceholder) { + continue; + } + + throw $e; + } catch (\Exception $e) { + throw new InvalidConfigurationException(sprintf('Invalid configuration for path "%s": %s', $this->getPath(), $e->getMessage()), $e->getCode(), $e); + } + } + + return $value; + } + + /** + * Validates the type of a Node. + * + * @param mixed $value The value to validate + * + * @throws InvalidTypeException when the value is invalid + */ + abstract protected function validateType($value); + + /** + * Normalizes the value. + * + * @param mixed $value The value to normalize + * + * @return mixed The normalized value + */ + abstract protected function normalizeValue($value); + + /** + * Merges two values together. + * + * @param mixed $leftSide + * @param mixed $rightSide + * + * @return mixed The merged value + */ + abstract protected function mergeValues($leftSide, $rightSide); + + /** + * Finalizes a value. + * + * @param mixed $value The value to finalize + * + * @return mixed The finalized value + */ + abstract protected function finalizeValue($value); + + /** + * Tests if placeholder values are allowed for this node. + */ + protected function allowPlaceholders(): bool + { + return true; + } + + /** + * Tests if a placeholder is being handled currently. + */ + protected function isHandlingPlaceholder(): bool + { + return null !== $this->handlingPlaceholder; + } + + /** + * Gets allowed dynamic types for this node. + */ + protected function getValidPlaceholderTypes(): array + { + return []; + } + + private static function resolvePlaceholderValue($value) + { + if (\is_string($value)) { + if (isset(self::$placeholders[$value])) { + return self::$placeholders[$value]; + } + + if (self::$placeholderUniquePrefix && 0 === strpos($value, self::$placeholderUniquePrefix)) { + return []; + } + } + + return $value; + } + + private function doValidateType($value): void + { + if (null !== $this->handlingPlaceholder && !$this->allowPlaceholders()) { + $e = new InvalidTypeException(sprintf('A dynamic value is not compatible with a "%s" node type at path "%s".', \get_class($this), $this->getPath())); + $e->setPath($this->getPath()); + + throw $e; + } + + if (null === $this->handlingPlaceholder || null === $value) { + $this->validateType($value); + + return; + } + + $knownTypes = array_keys(self::$placeholders[$this->handlingPlaceholder]); + $validTypes = $this->getValidPlaceholderTypes(); + + if ($validTypes && array_diff($knownTypes, $validTypes)) { + $e = new InvalidTypeException(sprintf( + 'Invalid type for path "%s". Expected %s, but got %s.', + $this->getPath(), + 1 === \count($validTypes) ? '"'.reset($validTypes).'"' : 'one of "'.implode('", "', $validTypes).'"', + 1 === \count($knownTypes) ? '"'.reset($knownTypes).'"' : 'one of "'.implode('", "', $knownTypes).'"' + )); + if ($hint = $this->getInfo()) { + $e->addHint($hint); + } + $e->setPath($this->getPath()); + + throw $e; + } + + $this->validateType($value); + } +} diff --git a/vendor/symfony/config/Definition/BooleanNode.php b/vendor/symfony/config/Definition/BooleanNode.php new file mode 100644 index 0000000..c43c46f --- /dev/null +++ b/vendor/symfony/config/Definition/BooleanNode.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +use Symfony\Component\Config\Definition\Exception\InvalidTypeException; + +/** + * This node represents a Boolean value in the config tree. + * + * @author Johannes M. Schmitt + */ +class BooleanNode extends ScalarNode +{ + /** + * {@inheritdoc} + */ + protected function validateType($value) + { + if (!\is_bool($value)) { + $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected boolean, but got %s.', $this->getPath(), \gettype($value))); + if ($hint = $this->getInfo()) { + $ex->addHint($hint); + } + $ex->setPath($this->getPath()); + + throw $ex; + } + } + + /** + * {@inheritdoc} + */ + protected function isValueEmpty($value) + { + // a boolean value cannot be empty + return false; + } + + /** + * {@inheritdoc} + */ + protected function getValidPlaceholderTypes(): array + { + return ['bool']; + } +} diff --git a/vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php b/vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php new file mode 100644 index 0000000..fdac03a --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php @@ -0,0 +1,546 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +use Symfony\Component\Config\Definition\ArrayNode; +use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; +use Symfony\Component\Config\Definition\PrototypedArrayNode; + +/** + * This class provides a fluent interface for defining an array node. + * + * @author Johannes M. Schmitt + */ +class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface +{ + protected $performDeepMerging = true; + protected $ignoreExtraKeys = false; + protected $removeExtraKeys = true; + protected $children = []; + protected $prototype; + protected $atLeastOne = false; + protected $allowNewKeys = true; + protected $key; + protected $removeKeyItem; + protected $addDefaults = false; + protected $addDefaultChildren = false; + protected $nodeBuilder; + protected $normalizeKeys = true; + + /** + * {@inheritdoc} + */ + public function __construct(?string $name, NodeParentInterface $parent = null) + { + parent::__construct($name, $parent); + + $this->nullEquivalent = []; + $this->trueEquivalent = []; + } + + /** + * {@inheritdoc} + */ + public function setBuilder(NodeBuilder $builder) + { + $this->nodeBuilder = $builder; + } + + /** + * {@inheritdoc} + */ + public function children() + { + return $this->getNodeBuilder(); + } + + /** + * Sets a prototype for child nodes. + * + * @return NodeDefinition + */ + public function prototype(string $type) + { + return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this); + } + + /** + * @return VariableNodeDefinition + */ + public function variablePrototype() + { + return $this->prototype('variable'); + } + + /** + * @return ScalarNodeDefinition + */ + public function scalarPrototype() + { + return $this->prototype('scalar'); + } + + /** + * @return BooleanNodeDefinition + */ + public function booleanPrototype() + { + return $this->prototype('boolean'); + } + + /** + * @return IntegerNodeDefinition + */ + public function integerPrototype() + { + return $this->prototype('integer'); + } + + /** + * @return FloatNodeDefinition + */ + public function floatPrototype() + { + return $this->prototype('float'); + } + + /** + * @return ArrayNodeDefinition + */ + public function arrayPrototype() + { + return $this->prototype('array'); + } + + /** + * @return EnumNodeDefinition + */ + public function enumPrototype() + { + return $this->prototype('enum'); + } + + /** + * Adds the default value if the node is not set in the configuration. + * + * This method is applicable to concrete nodes only (not to prototype nodes). + * If this function has been called and the node is not set during the finalization + * phase, it's default value will be derived from its children default values. + * + * @return $this + */ + public function addDefaultsIfNotSet() + { + $this->addDefaults = true; + + return $this; + } + + /** + * Adds children with a default value when none are defined. + * + * This method is applicable to prototype nodes only. + * + * @param int|string|array|null $children The number of children|The child name|The children names to be added + * + * @return $this + */ + public function addDefaultChildrenIfNoneSet($children = null) + { + $this->addDefaultChildren = $children; + + return $this; + } + + /** + * Requires the node to have at least one element. + * + * This method is applicable to prototype nodes only. + * + * @return $this + */ + public function requiresAtLeastOneElement() + { + $this->atLeastOne = true; + + return $this; + } + + /** + * Disallows adding news keys in a subsequent configuration. + * + * If used all keys have to be defined in the same configuration file. + * + * @return $this + */ + public function disallowNewKeysInSubsequentConfigs() + { + $this->allowNewKeys = false; + + return $this; + } + + /** + * Sets a normalization rule for XML configurations. + * + * @param string $singular The key to remap + * @param string|null $plural The plural of the key for irregular plurals + * + * @return $this + */ + public function fixXmlConfig(string $singular, string $plural = null) + { + $this->normalization()->remap($singular, $plural); + + return $this; + } + + /** + * Sets the attribute which value is to be used as key. + * + * This is useful when you have an indexed array that should be an + * associative array. You can select an item from within the array + * to be the key of the particular item. For example, if "id" is the + * "key", then: + * + * [ + * ['id' => 'my_name', 'foo' => 'bar'], + * ]; + * + * becomes + * + * [ + * 'my_name' => ['foo' => 'bar'], + * ]; + * + * If you'd like "'id' => 'my_name'" to still be present in the resulting + * array, then you can set the second argument of this method to false. + * + * This method is applicable to prototype nodes only. + * + * @param string $name The name of the key + * @param bool $removeKeyItem Whether or not the key item should be removed + * + * @return $this + */ + public function useAttributeAsKey(string $name, bool $removeKeyItem = true) + { + $this->key = $name; + $this->removeKeyItem = $removeKeyItem; + + return $this; + } + + /** + * Sets whether the node can be unset. + * + * @return $this + */ + public function canBeUnset(bool $allow = true) + { + $this->merge()->allowUnset($allow); + + return $this; + } + + /** + * Adds an "enabled" boolean to enable the current section. + * + * By default, the section is disabled. If any configuration is specified then + * the node will be automatically enabled: + * + * enableableArrayNode: {enabled: true, ...} # The config is enabled & default values get overridden + * enableableArrayNode: ~ # The config is enabled & use the default values + * enableableArrayNode: true # The config is enabled & use the default values + * enableableArrayNode: {other: value, ...} # The config is enabled & default values get overridden + * enableableArrayNode: {enabled: false, ...} # The config is disabled + * enableableArrayNode: false # The config is disabled + * + * @return $this + */ + public function canBeEnabled() + { + $this + ->addDefaultsIfNotSet() + ->treatFalseLike(['enabled' => false]) + ->treatTrueLike(['enabled' => true]) + ->treatNullLike(['enabled' => true]) + ->beforeNormalization() + ->ifArray() + ->then(function ($v) { + $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true; + + return $v; + }) + ->end() + ->children() + ->booleanNode('enabled') + ->defaultFalse() + ; + + return $this; + } + + /** + * Adds an "enabled" boolean to enable the current section. + * + * By default, the section is enabled. + * + * @return $this + */ + public function canBeDisabled() + { + $this + ->addDefaultsIfNotSet() + ->treatFalseLike(['enabled' => false]) + ->treatTrueLike(['enabled' => true]) + ->treatNullLike(['enabled' => true]) + ->children() + ->booleanNode('enabled') + ->defaultTrue() + ; + + return $this; + } + + /** + * Disables the deep merging of the node. + * + * @return $this + */ + public function performNoDeepMerging() + { + $this->performDeepMerging = false; + + return $this; + } + + /** + * Allows extra config keys to be specified under an array without + * throwing an exception. + * + * Those config values are ignored and removed from the resulting + * array. This should be used only in special cases where you want + * to send an entire configuration array through a special tree that + * processes only part of the array. + * + * @param bool $remove Whether to remove the extra keys + * + * @return $this + */ + public function ignoreExtraKeys(bool $remove = true) + { + $this->ignoreExtraKeys = true; + $this->removeExtraKeys = $remove; + + return $this; + } + + /** + * Sets whether to enable key normalization. + * + * @return $this + */ + public function normalizeKeys(bool $bool) + { + $this->normalizeKeys = $bool; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function append(NodeDefinition $node) + { + $this->children[$node->name] = $node->setParent($this); + + return $this; + } + + /** + * Returns a node builder to be used to add children and prototype. + * + * @return NodeBuilder The node builder + */ + protected function getNodeBuilder() + { + if (null === $this->nodeBuilder) { + $this->nodeBuilder = new NodeBuilder(); + } + + return $this->nodeBuilder->setParent($this); + } + + /** + * {@inheritdoc} + */ + protected function createNode() + { + if (null === $this->prototype) { + $node = new ArrayNode($this->name, $this->parent, $this->pathSeparator); + + $this->validateConcreteNode($node); + + $node->setAddIfNotSet($this->addDefaults); + + foreach ($this->children as $child) { + $child->parent = $node; + $node->addChild($child->getNode()); + } + } else { + $node = new PrototypedArrayNode($this->name, $this->parent, $this->pathSeparator); + + $this->validatePrototypeNode($node); + + if (null !== $this->key) { + $node->setKeyAttribute($this->key, $this->removeKeyItem); + } + + if (true === $this->atLeastOne || false === $this->allowEmptyValue) { + $node->setMinNumberOfElements(1); + } + + if ($this->default) { + if (!\is_array($this->defaultValue)) { + throw new \InvalidArgumentException(sprintf('%s: the default value of an array node has to be an array.', $node->getPath())); + } + + $node->setDefaultValue($this->defaultValue); + } + + if (false !== $this->addDefaultChildren) { + $node->setAddChildrenIfNoneSet($this->addDefaultChildren); + if ($this->prototype instanceof static && null === $this->prototype->prototype) { + $this->prototype->addDefaultsIfNotSet(); + } + } + + $this->prototype->parent = $node; + $node->setPrototype($this->prototype->getNode()); + } + + $node->setAllowNewKeys($this->allowNewKeys); + $node->addEquivalentValue(null, $this->nullEquivalent); + $node->addEquivalentValue(true, $this->trueEquivalent); + $node->addEquivalentValue(false, $this->falseEquivalent); + $node->setPerformDeepMerging($this->performDeepMerging); + $node->setRequired($this->required); + $node->setDeprecated($this->deprecationMessage); + $node->setIgnoreExtraKeys($this->ignoreExtraKeys, $this->removeExtraKeys); + $node->setNormalizeKeys($this->normalizeKeys); + + if (null !== $this->normalization) { + $node->setNormalizationClosures($this->normalization->before); + $node->setXmlRemappings($this->normalization->remappings); + } + + if (null !== $this->merge) { + $node->setAllowOverwrite($this->merge->allowOverwrite); + $node->setAllowFalse($this->merge->allowFalse); + } + + if (null !== $this->validation) { + $node->setFinalValidationClosures($this->validation->rules); + } + + return $node; + } + + /** + * Validate the configuration of a concrete node. + * + * @throws InvalidDefinitionException + */ + protected function validateConcreteNode(ArrayNode $node) + { + $path = $node->getPath(); + + if (null !== $this->key) { + throw new InvalidDefinitionException(sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s"', $path)); + } + + if (false === $this->allowEmptyValue) { + throw new InvalidDefinitionException(sprintf('->cannotBeEmpty() is not applicable to concrete nodes at path "%s"', $path)); + } + + if (true === $this->atLeastOne) { + throw new InvalidDefinitionException(sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s"', $path)); + } + + if ($this->default) { + throw new InvalidDefinitionException(sprintf('->defaultValue() is not applicable to concrete nodes at path "%s"', $path)); + } + + if (false !== $this->addDefaultChildren) { + throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s"', $path)); + } + } + + /** + * Validate the configuration of a prototype node. + * + * @throws InvalidDefinitionException + */ + protected function validatePrototypeNode(PrototypedArrayNode $node) + { + $path = $node->getPath(); + + if ($this->addDefaults) { + throw new InvalidDefinitionException(sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s"', $path)); + } + + if (false !== $this->addDefaultChildren) { + if ($this->default) { + throw new InvalidDefinitionException(sprintf('A default value and default children might not be used together at path "%s"', $path)); + } + + if (null !== $this->key && (null === $this->addDefaultChildren || \is_int($this->addDefaultChildren) && $this->addDefaultChildren > 0)) { + throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s"', $path)); + } + + if (null === $this->key && (\is_string($this->addDefaultChildren) || \is_array($this->addDefaultChildren))) { + throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s"', $path)); + } + } + } + + /** + * @return NodeDefinition[] + */ + public function getChildNodeDefinitions() + { + return $this->children; + } + + /** + * Finds a node defined by the given $nodePath. + * + * @param string $nodePath The path of the node to find. e.g "doctrine.orm.mappings" + */ + public function find(string $nodePath): NodeDefinition + { + $firstPathSegment = (false === $pathSeparatorPos = strpos($nodePath, $this->pathSeparator)) + ? $nodePath + : substr($nodePath, 0, $pathSeparatorPos); + + if (null === $node = ($this->children[$firstPathSegment] ?? null)) { + throw new \RuntimeException(sprintf('Node with name "%s" does not exist in the current node "%s".', $firstPathSegment, $this->name)); + } + + if (false === $pathSeparatorPos) { + return $node; + } + + return $node->find(substr($nodePath, $pathSeparatorPos + \strlen($this->pathSeparator))); + } +} diff --git a/vendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php b/vendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php new file mode 100644 index 0000000..d193242 --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +use Symfony\Component\Config\Definition\BooleanNode; +use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; + +/** + * This class provides a fluent interface for defining a node. + * + * @author Johannes M. Schmitt + */ +class BooleanNodeDefinition extends ScalarNodeDefinition +{ + /** + * {@inheritdoc} + */ + public function __construct(?string $name, NodeParentInterface $parent = null) + { + parent::__construct($name, $parent); + + $this->nullEquivalent = true; + } + + /** + * Instantiate a Node. + * + * @return BooleanNode The node + */ + protected function instantiateNode() + { + return new BooleanNode($this->name, $this->parent, $this->pathSeparator); + } + + /** + * {@inheritdoc} + * + * @throws InvalidDefinitionException + */ + public function cannotBeEmpty() + { + throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to BooleanNodeDefinition.'); + } +} diff --git a/vendor/symfony/config/Definition/Builder/BuilderAwareInterface.php b/vendor/symfony/config/Definition/Builder/BuilderAwareInterface.php new file mode 100644 index 0000000..f30b873 --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/BuilderAwareInterface.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +/** + * An interface that can be implemented by nodes which build other nodes. + * + * @author Roland Franssen + */ +interface BuilderAwareInterface +{ + /** + * Sets a custom children builder. + */ + public function setBuilder(NodeBuilder $builder); +} diff --git a/vendor/symfony/config/Definition/Builder/EnumNodeDefinition.php b/vendor/symfony/config/Definition/Builder/EnumNodeDefinition.php new file mode 100644 index 0000000..9a9c096 --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/EnumNodeDefinition.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +use Symfony\Component\Config\Definition\EnumNode; + +/** + * Enum Node Definition. + * + * @author Johannes M. Schmitt + */ +class EnumNodeDefinition extends ScalarNodeDefinition +{ + private $values; + + /** + * @return $this + */ + public function values(array $values) + { + $values = array_unique($values); + + if (empty($values)) { + throw new \InvalidArgumentException('->values() must be called with at least one value.'); + } + + $this->values = $values; + + return $this; + } + + /** + * Instantiate a Node. + * + * @return EnumNode The node + * + * @throws \RuntimeException + */ + protected function instantiateNode() + { + if (null === $this->values) { + throw new \RuntimeException('You must call ->values() on enum nodes.'); + } + + return new EnumNode($this->name, $this->parent, $this->values, $this->pathSeparator); + } +} diff --git a/vendor/symfony/config/Definition/Builder/ExprBuilder.php b/vendor/symfony/config/Definition/Builder/ExprBuilder.php new file mode 100644 index 0000000..4d918ce --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/ExprBuilder.php @@ -0,0 +1,246 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +use Symfony\Component\Config\Definition\Exception\UnsetKeyException; + +/** + * This class builds an if expression. + * + * @author Johannes M. Schmitt + * @author Christophe Coevoet + */ +class ExprBuilder +{ + protected $node; + public $ifPart; + public $thenPart; + + public function __construct(NodeDefinition $node) + { + $this->node = $node; + } + + /** + * Marks the expression as being always used. + * + * @return $this + */ + public function always(\Closure $then = null) + { + $this->ifPart = function ($v) { return true; }; + + if (null !== $then) { + $this->thenPart = $then; + } + + return $this; + } + + /** + * Sets a closure to use as tests. + * + * The default one tests if the value is true. + * + * @return $this + */ + public function ifTrue(\Closure $closure = null) + { + if (null === $closure) { + $closure = function ($v) { return true === $v; }; + } + + $this->ifPart = $closure; + + return $this; + } + + /** + * Tests if the value is a string. + * + * @return $this + */ + public function ifString() + { + $this->ifPart = function ($v) { return \is_string($v); }; + + return $this; + } + + /** + * Tests if the value is null. + * + * @return $this + */ + public function ifNull() + { + $this->ifPart = function ($v) { return null === $v; }; + + return $this; + } + + /** + * Tests if the value is empty. + * + * @return ExprBuilder + */ + public function ifEmpty() + { + $this->ifPart = function ($v) { return empty($v); }; + + return $this; + } + + /** + * Tests if the value is an array. + * + * @return $this + */ + public function ifArray() + { + $this->ifPart = function ($v) { return \is_array($v); }; + + return $this; + } + + /** + * Tests if the value is in an array. + * + * @return $this + */ + public function ifInArray(array $array) + { + $this->ifPart = function ($v) use ($array) { return \in_array($v, $array, true); }; + + return $this; + } + + /** + * Tests if the value is not in an array. + * + * @return $this + */ + public function ifNotInArray(array $array) + { + $this->ifPart = function ($v) use ($array) { return !\in_array($v, $array, true); }; + + return $this; + } + + /** + * Transforms variables of any type into an array. + * + * @return $this + */ + public function castToArray() + { + $this->ifPart = function ($v) { return !\is_array($v); }; + $this->thenPart = function ($v) { return [$v]; }; + + return $this; + } + + /** + * Sets the closure to run if the test pass. + * + * @return $this + */ + public function then(\Closure $closure) + { + $this->thenPart = $closure; + + return $this; + } + + /** + * Sets a closure returning an empty array. + * + * @return $this + */ + public function thenEmptyArray() + { + $this->thenPart = function ($v) { return []; }; + + return $this; + } + + /** + * Sets a closure marking the value as invalid at processing time. + * + * if you want to add the value of the node in your message just use a %s placeholder. + * + * @return $this + * + * @throws \InvalidArgumentException + */ + public function thenInvalid(string $message) + { + $this->thenPart = function ($v) use ($message) { throw new \InvalidArgumentException(sprintf($message, json_encode($v))); }; + + return $this; + } + + /** + * Sets a closure unsetting this key of the array at processing time. + * + * @return $this + * + * @throws UnsetKeyException + */ + public function thenUnset() + { + $this->thenPart = function ($v) { throw new UnsetKeyException('Unsetting key'); }; + + return $this; + } + + /** + * Returns the related node. + * + * @return NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition + * + * @throws \RuntimeException + */ + public function end() + { + if (null === $this->ifPart) { + throw new \RuntimeException('You must specify an if part.'); + } + if (null === $this->thenPart) { + throw new \RuntimeException('You must specify a then part.'); + } + + return $this->node; + } + + /** + * Builds the expressions. + * + * @param ExprBuilder[] $expressions An array of ExprBuilder instances to build + * + * @return array + */ + public static function buildExpressions(array $expressions) + { + foreach ($expressions as $k => $expr) { + if ($expr instanceof self) { + $if = $expr->ifPart; + $then = $expr->thenPart; + $expressions[$k] = function ($v) use ($if, $then) { + return $if($v) ? $then($v) : $v; + }; + } + } + + return $expressions; + } +} diff --git a/vendor/symfony/config/Definition/Builder/FloatNodeDefinition.php b/vendor/symfony/config/Definition/Builder/FloatNodeDefinition.php new file mode 100644 index 0000000..7b74271 --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/FloatNodeDefinition.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +use Symfony\Component\Config\Definition\FloatNode; + +/** + * This class provides a fluent interface for defining a float node. + * + * @author Jeanmonod David + */ +class FloatNodeDefinition extends NumericNodeDefinition +{ + /** + * Instantiates a Node. + * + * @return FloatNode The node + */ + protected function instantiateNode() + { + return new FloatNode($this->name, $this->parent, $this->min, $this->max, $this->pathSeparator); + } +} diff --git a/vendor/symfony/config/Definition/Builder/IntegerNodeDefinition.php b/vendor/symfony/config/Definition/Builder/IntegerNodeDefinition.php new file mode 100644 index 0000000..0472a98 --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/IntegerNodeDefinition.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +use Symfony\Component\Config\Definition\IntegerNode; + +/** + * This class provides a fluent interface for defining an integer node. + * + * @author Jeanmonod David + */ +class IntegerNodeDefinition extends NumericNodeDefinition +{ + /** + * Instantiates a Node. + * + * @return IntegerNode The node + */ + protected function instantiateNode() + { + return new IntegerNode($this->name, $this->parent, $this->min, $this->max, $this->pathSeparator); + } +} diff --git a/vendor/symfony/config/Definition/Builder/MergeBuilder.php b/vendor/symfony/config/Definition/Builder/MergeBuilder.php new file mode 100644 index 0000000..a88d49b --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/MergeBuilder.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +/** + * This class builds merge conditions. + * + * @author Johannes M. Schmitt + */ +class MergeBuilder +{ + protected $node; + public $allowFalse = false; + public $allowOverwrite = true; + + public function __construct(NodeDefinition $node) + { + $this->node = $node; + } + + /** + * Sets whether the node can be unset. + * + * @return $this + */ + public function allowUnset(bool $allow = true) + { + $this->allowFalse = $allow; + + return $this; + } + + /** + * Sets whether the node can be overwritten. + * + * @return $this + */ + public function denyOverwrite(bool $deny = true) + { + $this->allowOverwrite = !$deny; + + return $this; + } + + /** + * Returns the related node. + * + * @return NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition + */ + public function end() + { + return $this->node; + } +} diff --git a/vendor/symfony/config/Definition/Builder/NodeBuilder.php b/vendor/symfony/config/Definition/Builder/NodeBuilder.php new file mode 100644 index 0000000..bab439b --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/NodeBuilder.php @@ -0,0 +1,219 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +/** + * This class provides a fluent interface for building a node. + * + * @author Johannes M. Schmitt + */ +class NodeBuilder implements NodeParentInterface +{ + protected $parent; + protected $nodeMapping; + + public function __construct() + { + $this->nodeMapping = [ + 'variable' => VariableNodeDefinition::class, + 'scalar' => ScalarNodeDefinition::class, + 'boolean' => BooleanNodeDefinition::class, + 'integer' => IntegerNodeDefinition::class, + 'float' => FloatNodeDefinition::class, + 'array' => ArrayNodeDefinition::class, + 'enum' => EnumNodeDefinition::class, + ]; + } + + /** + * Set the parent node. + * + * @return $this + */ + public function setParent(ParentNodeDefinitionInterface $parent = null) + { + $this->parent = $parent; + + return $this; + } + + /** + * Creates a child array node. + * + * @return ArrayNodeDefinition The child node + */ + public function arrayNode(string $name) + { + return $this->node($name, 'array'); + } + + /** + * Creates a child scalar node. + * + * @return ScalarNodeDefinition The child node + */ + public function scalarNode(string $name) + { + return $this->node($name, 'scalar'); + } + + /** + * Creates a child Boolean node. + * + * @return BooleanNodeDefinition The child node + */ + public function booleanNode(string $name) + { + return $this->node($name, 'boolean'); + } + + /** + * Creates a child integer node. + * + * @return IntegerNodeDefinition The child node + */ + public function integerNode(string $name) + { + return $this->node($name, 'integer'); + } + + /** + * Creates a child float node. + * + * @return FloatNodeDefinition The child node + */ + public function floatNode(string $name) + { + return $this->node($name, 'float'); + } + + /** + * Creates a child EnumNode. + * + * @return EnumNodeDefinition + */ + public function enumNode(string $name) + { + return $this->node($name, 'enum'); + } + + /** + * Creates a child variable node. + * + * @return VariableNodeDefinition The builder of the child node + */ + public function variableNode(string $name) + { + return $this->node($name, 'variable'); + } + + /** + * Returns the parent node. + * + * @return NodeDefinition&ParentNodeDefinitionInterface The parent node + */ + public function end() + { + return $this->parent; + } + + /** + * Creates a child node. + * + * @return NodeDefinition The child node + * + * @throws \RuntimeException When the node type is not registered + * @throws \RuntimeException When the node class is not found + */ + public function node(?string $name, string $type) + { + $class = $this->getNodeClass($type); + + $node = new $class($name); + + $this->append($node); + + return $node; + } + + /** + * Appends a node definition. + * + * Usage: + * + * $node = new ArrayNodeDefinition('name') + * ->children() + * ->scalarNode('foo')->end() + * ->scalarNode('baz')->end() + * ->append($this->getBarNodeDefinition()) + * ->end() + * ; + * + * @return $this + */ + public function append(NodeDefinition $node) + { + if ($node instanceof BuilderAwareInterface) { + $builder = clone $this; + $builder->setParent(null); + $node->setBuilder($builder); + } + + if (null !== $this->parent) { + $this->parent->append($node); + // Make this builder the node parent to allow for a fluid interface + $node->setParent($this); + } + + return $this; + } + + /** + * Adds or overrides a node Type. + * + * @param string $type The name of the type + * @param string $class The fully qualified name the node definition class + * + * @return $this + */ + public function setNodeClass(string $type, string $class) + { + $this->nodeMapping[strtolower($type)] = $class; + + return $this; + } + + /** + * Returns the class name of the node definition. + * + * @return string The node definition class name + * + * @throws \RuntimeException When the node type is not registered + * @throws \RuntimeException When the node class is not found + */ + protected function getNodeClass(string $type) + { + $type = strtolower($type); + + if (!isset($this->nodeMapping[$type])) { + throw new \RuntimeException(sprintf('The node type "%s" is not registered.', $type)); + } + + $class = $this->nodeMapping[$type]; + + if (!class_exists($class)) { + throw new \RuntimeException(sprintf('The node class "%s" does not exist.', $class)); + } + + return $class; + } +} diff --git a/vendor/symfony/config/Definition/Builder/NodeDefinition.php b/vendor/symfony/config/Definition/Builder/NodeDefinition.php new file mode 100644 index 0000000..3651990 --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/NodeDefinition.php @@ -0,0 +1,362 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +use Symfony\Component\Config\Definition\BaseNode; +use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; +use Symfony\Component\Config\Definition\NodeInterface; + +/** + * This class provides a fluent interface for defining a node. + * + * @author Johannes M. Schmitt + */ +abstract class NodeDefinition implements NodeParentInterface +{ + protected $name; + protected $normalization; + protected $validation; + protected $defaultValue; + protected $default = false; + protected $required = false; + protected $deprecationMessage = null; + protected $merge; + protected $allowEmptyValue = true; + protected $nullEquivalent; + protected $trueEquivalent = true; + protected $falseEquivalent = false; + protected $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR; + protected $parent; + protected $attributes = []; + + public function __construct(?string $name, NodeParentInterface $parent = null) + { + $this->parent = $parent; + $this->name = $name; + } + + /** + * Sets the parent node. + * + * @return $this + */ + public function setParent(NodeParentInterface $parent) + { + $this->parent = $parent; + + return $this; + } + + /** + * Sets info message. + * + * @return $this + */ + public function info(string $info) + { + return $this->attribute('info', $info); + } + + /** + * Sets example configuration. + * + * @param string|array $example + * + * @return $this + */ + public function example($example) + { + return $this->attribute('example', $example); + } + + /** + * Sets an attribute on the node. + * + * @param mixed $value + * + * @return $this + */ + public function attribute(string $key, $value) + { + $this->attributes[$key] = $value; + + return $this; + } + + /** + * Returns the parent node. + * + * @return NodeParentInterface|NodeBuilder|NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition|null The builder of the parent node + */ + public function end() + { + return $this->parent; + } + + /** + * Creates the node. + * + * @param bool $forceRootNode Whether to force this node as the root node + * + * @return NodeInterface + */ + public function getNode(bool $forceRootNode = false) + { + if ($forceRootNode) { + $this->parent = null; + } + + if (null !== $this->normalization) { + $this->normalization->before = ExprBuilder::buildExpressions($this->normalization->before); + } + + if (null !== $this->validation) { + $this->validation->rules = ExprBuilder::buildExpressions($this->validation->rules); + } + + $node = $this->createNode(); + $node->setAttributes($this->attributes); + + return $node; + } + + /** + * Sets the default value. + * + * @param mixed $value The default value + * + * @return $this + */ + public function defaultValue($value) + { + $this->default = true; + $this->defaultValue = $value; + + return $this; + } + + /** + * Sets the node as required. + * + * @return $this + */ + public function isRequired() + { + $this->required = true; + + return $this; + } + + /** + * Sets the node as deprecated. + * + * You can use %node% and %path% placeholders in your message to display, + * respectively, the node name and its complete path. + * + * @return $this + */ + public function setDeprecated(string $message = 'The child node "%node%" at path "%path%" is deprecated.') + { + $this->deprecationMessage = $message; + + return $this; + } + + /** + * Sets the equivalent value used when the node contains null. + * + * @param mixed $value + * + * @return $this + */ + public function treatNullLike($value) + { + $this->nullEquivalent = $value; + + return $this; + } + + /** + * Sets the equivalent value used when the node contains true. + * + * @param mixed $value + * + * @return $this + */ + public function treatTrueLike($value) + { + $this->trueEquivalent = $value; + + return $this; + } + + /** + * Sets the equivalent value used when the node contains false. + * + * @param mixed $value + * + * @return $this + */ + public function treatFalseLike($value) + { + $this->falseEquivalent = $value; + + return $this; + } + + /** + * Sets null as the default value. + * + * @return $this + */ + public function defaultNull() + { + return $this->defaultValue(null); + } + + /** + * Sets true as the default value. + * + * @return $this + */ + public function defaultTrue() + { + return $this->defaultValue(true); + } + + /** + * Sets false as the default value. + * + * @return $this + */ + public function defaultFalse() + { + return $this->defaultValue(false); + } + + /** + * Sets an expression to run before the normalization. + * + * @return ExprBuilder + */ + public function beforeNormalization() + { + return $this->normalization()->before(); + } + + /** + * Denies the node value being empty. + * + * @return $this + */ + public function cannotBeEmpty() + { + $this->allowEmptyValue = false; + + return $this; + } + + /** + * Sets an expression to run for the validation. + * + * The expression receives the value of the node and must return it. It can + * modify it. + * An exception should be thrown when the node is not valid. + * + * @return ExprBuilder + */ + public function validate() + { + return $this->validation()->rule(); + } + + /** + * Sets whether the node can be overwritten. + * + * @return $this + */ + public function cannotBeOverwritten(bool $deny = true) + { + $this->merge()->denyOverwrite($deny); + + return $this; + } + + /** + * Gets the builder for validation rules. + * + * @return ValidationBuilder + */ + protected function validation() + { + if (null === $this->validation) { + $this->validation = new ValidationBuilder($this); + } + + return $this->validation; + } + + /** + * Gets the builder for merging rules. + * + * @return MergeBuilder + */ + protected function merge() + { + if (null === $this->merge) { + $this->merge = new MergeBuilder($this); + } + + return $this->merge; + } + + /** + * Gets the builder for normalization rules. + * + * @return NormalizationBuilder + */ + protected function normalization() + { + if (null === $this->normalization) { + $this->normalization = new NormalizationBuilder($this); + } + + return $this->normalization; + } + + /** + * Instantiate and configure the node according to this definition. + * + * @return NodeInterface The node instance + * + * @throws InvalidDefinitionException When the definition is invalid + */ + abstract protected function createNode(); + + /** + * Set PathSeparator to use. + * + * @return $this + */ + public function setPathSeparator(string $separator) + { + if ($this instanceof ParentNodeDefinitionInterface) { + foreach ($this->getChildNodeDefinitions() as $child) { + $child->setPathSeparator($separator); + } + } + + $this->pathSeparator = $separator; + + return $this; + } +} diff --git a/vendor/symfony/config/Definition/Builder/NodeParentInterface.php b/vendor/symfony/config/Definition/Builder/NodeParentInterface.php new file mode 100644 index 0000000..305e993 --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/NodeParentInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +/** + * An interface that must be implemented by all node parents. + * + * @author Victor Berchet + */ +interface NodeParentInterface +{ +} diff --git a/vendor/symfony/config/Definition/Builder/NormalizationBuilder.php b/vendor/symfony/config/Definition/Builder/NormalizationBuilder.php new file mode 100644 index 0000000..06cbbd4 --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/NormalizationBuilder.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +/** + * This class builds normalization conditions. + * + * @author Johannes M. Schmitt + */ +class NormalizationBuilder +{ + protected $node; + public $before = []; + public $remappings = []; + + public function __construct(NodeDefinition $node) + { + $this->node = $node; + } + + /** + * Registers a key to remap to its plural form. + * + * @param string $key The key to remap + * @param string|null $plural The plural of the key in case of irregular plural + * + * @return $this + */ + public function remap(string $key, string $plural = null) + { + $this->remappings[] = [$key, null === $plural ? $key.'s' : $plural]; + + return $this; + } + + /** + * Registers a closure to run before the normalization or an expression builder to build it if null is provided. + * + * @return ExprBuilder|$this + */ + public function before(\Closure $closure = null) + { + if (null !== $closure) { + $this->before[] = $closure; + + return $this; + } + + return $this->before[] = new ExprBuilder($this->node); + } +} diff --git a/vendor/symfony/config/Definition/Builder/NumericNodeDefinition.php b/vendor/symfony/config/Definition/Builder/NumericNodeDefinition.php new file mode 100644 index 0000000..0d0207c --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/NumericNodeDefinition.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; + +/** + * Abstract class that contains common code of integer and float node definitions. + * + * @author David Jeanmonod + */ +abstract class NumericNodeDefinition extends ScalarNodeDefinition +{ + protected $min; + protected $max; + + /** + * Ensures that the value is smaller than the given reference. + * + * @param mixed $max + * + * @return $this + * + * @throws \InvalidArgumentException when the constraint is inconsistent + */ + public function max($max) + { + if (isset($this->min) && $this->min > $max) { + throw new \InvalidArgumentException(sprintf('You cannot define a max(%s) as you already have a min(%s)', $max, $this->min)); + } + $this->max = $max; + + return $this; + } + + /** + * Ensures that the value is bigger than the given reference. + * + * @param mixed $min + * + * @return $this + * + * @throws \InvalidArgumentException when the constraint is inconsistent + */ + public function min($min) + { + if (isset($this->max) && $this->max < $min) { + throw new \InvalidArgumentException(sprintf('You cannot define a min(%s) as you already have a max(%s)', $min, $this->max)); + } + $this->min = $min; + + return $this; + } + + /** + * {@inheritdoc} + * + * @throws InvalidDefinitionException + */ + public function cannotBeEmpty() + { + throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to NumericNodeDefinition.'); + } +} diff --git a/vendor/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php b/vendor/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php new file mode 100644 index 0000000..449b91a --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +/** + * An interface that must be implemented by nodes which can have children. + * + * @author Victor Berchet + */ +interface ParentNodeDefinitionInterface extends BuilderAwareInterface +{ + /** + * Returns a builder to add children nodes. + * + * @return NodeBuilder + */ + public function children(); + + /** + * Appends a node definition. + * + * Usage: + * + * $node = $parentNode + * ->children() + * ->scalarNode('foo')->end() + * ->scalarNode('baz')->end() + * ->append($this->getBarNodeDefinition()) + * ->end() + * ; + * + * @return $this + */ + public function append(NodeDefinition $node); + + /** + * Gets the child node definitions. + * + * @return NodeDefinition[] + */ + public function getChildNodeDefinitions(); +} diff --git a/vendor/symfony/config/Definition/Builder/ScalarNodeDefinition.php b/vendor/symfony/config/Definition/Builder/ScalarNodeDefinition.php new file mode 100644 index 0000000..428f612 --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/ScalarNodeDefinition.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +use Symfony\Component\Config\Definition\ScalarNode; + +/** + * This class provides a fluent interface for defining a node. + * + * @author Johannes M. Schmitt + */ +class ScalarNodeDefinition extends VariableNodeDefinition +{ + /** + * Instantiate a Node. + * + * @return ScalarNode The node + */ + protected function instantiateNode() + { + return new ScalarNode($this->name, $this->parent, $this->pathSeparator); + } +} diff --git a/vendor/symfony/config/Definition/Builder/TreeBuilder.php b/vendor/symfony/config/Definition/Builder/TreeBuilder.php new file mode 100644 index 0000000..13a18db --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/TreeBuilder.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +use Symfony\Component\Config\Definition\NodeInterface; + +/** + * This is the entry class for building a config tree. + * + * @author Johannes M. Schmitt + */ +class TreeBuilder implements NodeParentInterface +{ + protected $tree; + protected $root; + + public function __construct(string $name, string $type = 'array', NodeBuilder $builder = null) + { + $builder = $builder ?: new NodeBuilder(); + $this->root = $builder->node($name, $type)->setParent($this); + } + + /** + * @return NodeDefinition|ArrayNodeDefinition The root node (as an ArrayNodeDefinition when the type is 'array') + */ + public function getRootNode(): NodeDefinition + { + return $this->root; + } + + /** + * Builds the tree. + * + * @return NodeInterface + * + * @throws \RuntimeException + */ + public function buildTree() + { + if (null !== $this->tree) { + return $this->tree; + } + + return $this->tree = $this->root->getNode(true); + } + + public function setPathSeparator(string $separator) + { + // unset last built as changing path separator changes all nodes + $this->tree = null; + + $this->root->setPathSeparator($separator); + } +} diff --git a/vendor/symfony/config/Definition/Builder/ValidationBuilder.php b/vendor/symfony/config/Definition/Builder/ValidationBuilder.php new file mode 100644 index 0000000..4efc726 --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/ValidationBuilder.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +/** + * This class builds validation conditions. + * + * @author Christophe Coevoet + */ +class ValidationBuilder +{ + protected $node; + public $rules = []; + + public function __construct(NodeDefinition $node) + { + $this->node = $node; + } + + /** + * Registers a closure to run as normalization or an expression builder to build it if null is provided. + * + * @return ExprBuilder|$this + */ + public function rule(\Closure $closure = null) + { + if (null !== $closure) { + $this->rules[] = $closure; + + return $this; + } + + return $this->rules[] = new ExprBuilder($this->node); + } +} diff --git a/vendor/symfony/config/Definition/Builder/VariableNodeDefinition.php b/vendor/symfony/config/Definition/Builder/VariableNodeDefinition.php new file mode 100644 index 0000000..39a564f --- /dev/null +++ b/vendor/symfony/config/Definition/Builder/VariableNodeDefinition.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Builder; + +use Symfony\Component\Config\Definition\VariableNode; + +/** + * This class provides a fluent interface for defining a node. + * + * @author Johannes M. Schmitt + */ +class VariableNodeDefinition extends NodeDefinition +{ + /** + * Instantiate a Node. + * + * @return VariableNode The node + */ + protected function instantiateNode() + { + return new VariableNode($this->name, $this->parent, $this->pathSeparator); + } + + /** + * {@inheritdoc} + */ + protected function createNode() + { + $node = $this->instantiateNode(); + + if (null !== $this->normalization) { + $node->setNormalizationClosures($this->normalization->before); + } + + if (null !== $this->merge) { + $node->setAllowOverwrite($this->merge->allowOverwrite); + } + + if (true === $this->default) { + $node->setDefaultValue($this->defaultValue); + } + + $node->setAllowEmptyValue($this->allowEmptyValue); + $node->addEquivalentValue(null, $this->nullEquivalent); + $node->addEquivalentValue(true, $this->trueEquivalent); + $node->addEquivalentValue(false, $this->falseEquivalent); + $node->setRequired($this->required); + $node->setDeprecated($this->deprecationMessage); + + if (null !== $this->validation) { + $node->setFinalValidationClosures($this->validation->rules); + } + + return $node; + } +} diff --git a/vendor/symfony/config/Definition/ConfigurationInterface.php b/vendor/symfony/config/Definition/ConfigurationInterface.php new file mode 100644 index 0000000..d6456ed --- /dev/null +++ b/vendor/symfony/config/Definition/ConfigurationInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +/** + * Configuration interface. + * + * @author Victor Berchet + */ +interface ConfigurationInterface +{ + /** + * Generates the configuration tree builder. + * + * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder + */ + public function getConfigTreeBuilder(); +} diff --git a/vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.php b/vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.php new file mode 100644 index 0000000..32f32e0 --- /dev/null +++ b/vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.php @@ -0,0 +1,302 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Dumper; + +use Symfony\Component\Config\Definition\ArrayNode; +use Symfony\Component\Config\Definition\ConfigurationInterface; +use Symfony\Component\Config\Definition\EnumNode; +use Symfony\Component\Config\Definition\NodeInterface; +use Symfony\Component\Config\Definition\PrototypedArrayNode; + +/** + * Dumps a XML reference configuration for the given configuration/node instance. + * + * @author Wouter J + */ +class XmlReferenceDumper +{ + private $reference; + + public function dump(ConfigurationInterface $configuration, string $namespace = null) + { + return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree(), $namespace); + } + + public function dumpNode(NodeInterface $node, string $namespace = null) + { + $this->reference = ''; + $this->writeNode($node, 0, true, $namespace); + $ref = $this->reference; + $this->reference = null; + + return $ref; + } + + private function writeNode(NodeInterface $node, int $depth = 0, bool $root = false, string $namespace = null) + { + $rootName = ($root ? 'config' : $node->getName()); + $rootNamespace = ($namespace ?: ($root ? 'http://example.org/schema/dic/'.$node->getName() : null)); + + // xml remapping + if ($node->getParent()) { + $remapping = array_filter($node->getParent()->getXmlRemappings(), function ($mapping) use ($rootName) { + return $rootName === $mapping[1]; + }); + + if (\count($remapping)) { + list($singular) = current($remapping); + $rootName = $singular; + } + } + $rootName = str_replace('_', '-', $rootName); + + $rootAttributes = []; + $rootAttributeComments = []; + $rootChildren = []; + $rootComments = []; + + if ($node instanceof ArrayNode) { + $children = $node->getChildren(); + + // comments about the root node + if ($rootInfo = $node->getInfo()) { + $rootComments[] = $rootInfo; + } + + if ($rootNamespace) { + $rootComments[] = 'Namespace: '.$rootNamespace; + } + + // render prototyped nodes + if ($node instanceof PrototypedArrayNode) { + $prototype = $node->getPrototype(); + + $info = 'prototype'; + if (null !== $prototype->getInfo()) { + $info .= ': '.$prototype->getInfo(); + } + array_unshift($rootComments, $info); + + if ($key = $node->getKeyAttribute()) { + $rootAttributes[$key] = str_replace('-', ' ', $rootName).' '.$key; + } + + if ($prototype instanceof PrototypedArrayNode) { + $prototype->setName($key); + $children = [$key => $prototype]; + } elseif ($prototype instanceof ArrayNode) { + $children = $prototype->getChildren(); + } else { + if ($prototype->hasDefaultValue()) { + $prototypeValue = $prototype->getDefaultValue(); + } else { + switch (\get_class($prototype)) { + case 'Symfony\Component\Config\Definition\ScalarNode': + $prototypeValue = 'scalar value'; + break; + + case 'Symfony\Component\Config\Definition\FloatNode': + case 'Symfony\Component\Config\Definition\IntegerNode': + $prototypeValue = 'numeric value'; + break; + + case 'Symfony\Component\Config\Definition\BooleanNode': + $prototypeValue = 'true|false'; + break; + + case 'Symfony\Component\Config\Definition\EnumNode': + $prototypeValue = implode('|', array_map('json_encode', $prototype->getValues())); + break; + + default: + $prototypeValue = 'value'; + } + } + } + } + + // get attributes and elements + foreach ($children as $child) { + if (!$child instanceof ArrayNode) { + // get attributes + + // metadata + $name = str_replace('_', '-', $child->getName()); + $value = '%%%%not_defined%%%%'; // use a string which isn't used in the normal world + + // comments + $comments = []; + if ($info = $child->getInfo()) { + $comments[] = $info; + } + + if ($example = $child->getExample()) { + $comments[] = 'Example: '.$example; + } + + if ($child->isRequired()) { + $comments[] = 'Required'; + } + + if ($child->isDeprecated()) { + $comments[] = sprintf('Deprecated (%s)', $child->getDeprecationMessage($child->getName(), $node->getPath())); + } + + if ($child instanceof EnumNode) { + $comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues())); + } + + if (\count($comments)) { + $rootAttributeComments[$name] = implode(";\n", $comments); + } + + // default values + if ($child->hasDefaultValue()) { + $value = $child->getDefaultValue(); + } + + // append attribute + $rootAttributes[$name] = $value; + } else { + // get elements + $rootChildren[] = $child; + } + } + } + + // render comments + + // root node comment + if (\count($rootComments)) { + foreach ($rootComments as $comment) { + $this->writeLine('', $depth); + } + } + + // attribute comments + if (\count($rootAttributeComments)) { + foreach ($rootAttributeComments as $attrName => $comment) { + $commentDepth = $depth + 4 + \strlen($attrName) + 2; + $commentLines = explode("\n", $comment); + $multiline = (\count($commentLines) > 1); + $comment = implode(PHP_EOL.str_repeat(' ', $commentDepth), $commentLines); + + if ($multiline) { + $this->writeLine('', $depth); + } else { + $this->writeLine('', $depth); + } + } + } + + // render start tag + attributes + $rootIsVariablePrototype = isset($prototypeValue); + $rootIsEmptyTag = (0 === \count($rootChildren) && !$rootIsVariablePrototype); + $rootOpenTag = '<'.$rootName; + if (1 >= ($attributesCount = \count($rootAttributes))) { + if (1 === $attributesCount) { + $rootOpenTag .= sprintf(' %s="%s"', current(array_keys($rootAttributes)), $this->writeValue(current($rootAttributes))); + } + + $rootOpenTag .= $rootIsEmptyTag ? ' />' : '>'; + + if ($rootIsVariablePrototype) { + $rootOpenTag .= $prototypeValue.''; + } + + $this->writeLine($rootOpenTag, $depth); + } else { + $this->writeLine($rootOpenTag, $depth); + + $i = 1; + + foreach ($rootAttributes as $attrName => $attrValue) { + $attr = sprintf('%s="%s"', $attrName, $this->writeValue($attrValue)); + + $this->writeLine($attr, $depth + 4); + + if ($attributesCount === $i++) { + $this->writeLine($rootIsEmptyTag ? '/>' : '>', $depth); + + if ($rootIsVariablePrototype) { + $rootOpenTag .= $prototypeValue.''; + } + } + } + } + + // render children tags + foreach ($rootChildren as $child) { + $this->writeLine(''); + $this->writeNode($child, $depth + 4); + } + + // render end tag + if (!$rootIsEmptyTag && !$rootIsVariablePrototype) { + $this->writeLine(''); + + $rootEndTag = ''; + $this->writeLine($rootEndTag, $depth); + } + } + + /** + * Outputs a single config reference line. + */ + private function writeLine(string $text, int $indent = 0) + { + $indent = \strlen($text) + $indent; + $format = '%'.$indent.'s'; + + $this->reference .= sprintf($format, $text).PHP_EOL; + } + + /** + * Renders the string conversion of the value. + * + * @param mixed $value + */ + private function writeValue($value): string + { + if ('%%%%not_defined%%%%' === $value) { + return ''; + } + + if (\is_string($value) || is_numeric($value)) { + return $value; + } + + if (false === $value) { + return 'false'; + } + + if (true === $value) { + return 'true'; + } + + if (null === $value) { + return 'null'; + } + + if (empty($value)) { + return ''; + } + + if (\is_array($value)) { + return implode(',', $value); + } + + return ''; + } +} diff --git a/vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.php b/vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.php new file mode 100644 index 0000000..757963d --- /dev/null +++ b/vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.php @@ -0,0 +1,242 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Dumper; + +use Symfony\Component\Config\Definition\ArrayNode; +use Symfony\Component\Config\Definition\ConfigurationInterface; +use Symfony\Component\Config\Definition\EnumNode; +use Symfony\Component\Config\Definition\NodeInterface; +use Symfony\Component\Config\Definition\PrototypedArrayNode; +use Symfony\Component\Config\Definition\ScalarNode; +use Symfony\Component\Yaml\Inline; + +/** + * Dumps a Yaml reference configuration for the given configuration/node instance. + * + * @author Kevin Bond + */ +class YamlReferenceDumper +{ + private $reference; + + public function dump(ConfigurationInterface $configuration) + { + return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree()); + } + + public function dumpAtPath(ConfigurationInterface $configuration, string $path) + { + $rootNode = $node = $configuration->getConfigTreeBuilder()->buildTree(); + + foreach (explode('.', $path) as $step) { + if (!$node instanceof ArrayNode) { + throw new \UnexpectedValueException(sprintf('Unable to find node at path "%s.%s"', $rootNode->getName(), $path)); + } + + /** @var NodeInterface[] $children */ + $children = $node instanceof PrototypedArrayNode ? $this->getPrototypeChildren($node) : $node->getChildren(); + + foreach ($children as $child) { + if ($child->getName() === $step) { + $node = $child; + + continue 2; + } + } + + throw new \UnexpectedValueException(sprintf('Unable to find node at path "%s.%s"', $rootNode->getName(), $path)); + } + + return $this->dumpNode($node); + } + + public function dumpNode(NodeInterface $node) + { + $this->reference = ''; + $this->writeNode($node); + $ref = $this->reference; + $this->reference = null; + + return $ref; + } + + private function writeNode(NodeInterface $node, NodeInterface $parentNode = null, int $depth = 0, bool $prototypedArray = false) + { + $comments = []; + $default = ''; + $defaultArray = null; + $children = null; + $example = $node->getExample(); + + // defaults + if ($node instanceof ArrayNode) { + $children = $node->getChildren(); + + if ($node instanceof PrototypedArrayNode) { + $children = $this->getPrototypeChildren($node); + } + + if (!$children) { + if ($node->hasDefaultValue() && \count($defaultArray = $node->getDefaultValue())) { + $default = ''; + } elseif (!\is_array($example)) { + $default = '[]'; + } + } + } elseif ($node instanceof EnumNode) { + $comments[] = 'One of '.implode('; ', array_map('json_encode', $node->getValues())); + $default = $node->hasDefaultValue() ? Inline::dump($node->getDefaultValue()) : '~'; + } else { + $default = '~'; + + if ($node->hasDefaultValue()) { + $default = $node->getDefaultValue(); + + if (\is_array($default)) { + if (\count($defaultArray = $node->getDefaultValue())) { + $default = ''; + } elseif (!\is_array($example)) { + $default = '[]'; + } + } else { + $default = Inline::dump($default); + } + } + } + + // required? + if ($node->isRequired()) { + $comments[] = 'Required'; + } + + // deprecated? + if ($node->isDeprecated()) { + $comments[] = sprintf('Deprecated (%s)', $node->getDeprecationMessage($node->getName(), $parentNode ? $parentNode->getPath() : $node->getPath())); + } + + // example + if ($example && !\is_array($example)) { + $comments[] = 'Example: '.$example; + } + + $default = '' != (string) $default ? ' '.$default : ''; + $comments = \count($comments) ? '# '.implode(', ', $comments) : ''; + + $key = $prototypedArray ? '-' : $node->getName().':'; + $text = rtrim(sprintf('%-21s%s %s', $key, $default, $comments), ' '); + + if ($info = $node->getInfo()) { + $this->writeLine(''); + // indenting multi-line info + $info = str_replace("\n", sprintf("\n%".($depth * 4).'s# ', ' '), $info); + $this->writeLine('# '.$info, $depth * 4); + } + + $this->writeLine($text, $depth * 4); + + // output defaults + if ($defaultArray) { + $this->writeLine(''); + + $message = \count($defaultArray) > 1 ? 'Defaults' : 'Default'; + + $this->writeLine('# '.$message.':', $depth * 4 + 4); + + $this->writeArray($defaultArray, $depth + 1); + } + + if (\is_array($example)) { + $this->writeLine(''); + + $message = \count($example) > 1 ? 'Examples' : 'Example'; + + $this->writeLine('# '.$message.':', $depth * 4 + 4); + + $this->writeArray($example, $depth + 1); + } + + if ($children) { + foreach ($children as $childNode) { + $this->writeNode($childNode, $node, $depth + 1, $node instanceof PrototypedArrayNode && !$node->getKeyAttribute()); + } + } + } + + /** + * Outputs a single config reference line. + */ + private function writeLine(string $text, int $indent = 0) + { + $indent = \strlen($text) + $indent; + $format = '%'.$indent.'s'; + + $this->reference .= sprintf($format, $text)."\n"; + } + + private function writeArray(array $array, int $depth) + { + $isIndexed = array_values($array) === $array; + + foreach ($array as $key => $value) { + if (\is_array($value)) { + $val = ''; + } else { + $val = $value; + } + + if ($isIndexed) { + $this->writeLine('- '.$val, $depth * 4); + } else { + $this->writeLine(sprintf('%-20s %s', $key.':', $val), $depth * 4); + } + + if (\is_array($value)) { + $this->writeArray($value, $depth + 1); + } + } + } + + private function getPrototypeChildren(PrototypedArrayNode $node): array + { + $prototype = $node->getPrototype(); + $key = $node->getKeyAttribute(); + + // Do not expand prototype if it isn't an array node nor uses attribute as key + if (!$key && !$prototype instanceof ArrayNode) { + return $node->getChildren(); + } + + if ($prototype instanceof ArrayNode) { + $keyNode = new ArrayNode($key, $node); + $children = $prototype->getChildren(); + + if ($prototype instanceof PrototypedArrayNode && $prototype->getKeyAttribute()) { + $children = $this->getPrototypeChildren($prototype); + } + + // add children + foreach ($children as $childNode) { + $keyNode->addChild($childNode); + } + } else { + $keyNode = new ScalarNode($key, $node); + } + + $info = 'Prototype'; + if (null !== $prototype->getInfo()) { + $info .= ': '.$prototype->getInfo(); + } + $keyNode->setInfo($info); + + return [$key => $keyNode]; + } +} diff --git a/vendor/symfony/config/Definition/EnumNode.php b/vendor/symfony/config/Definition/EnumNode.php new file mode 100644 index 0000000..23fc508 --- /dev/null +++ b/vendor/symfony/config/Definition/EnumNode.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; + +/** + * Node which only allows a finite set of values. + * + * @author Johannes M. Schmitt + */ +class EnumNode extends ScalarNode +{ + private $values; + + public function __construct(?string $name, NodeInterface $parent = null, array $values = [], string $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR) + { + $values = array_unique($values); + if (empty($values)) { + throw new \InvalidArgumentException('$values must contain at least one element.'); + } + + parent::__construct($name, $parent, $pathSeparator); + $this->values = $values; + } + + public function getValues() + { + return $this->values; + } + + protected function finalizeValue($value) + { + $value = parent::finalizeValue($value); + + if (!\in_array($value, $this->values, true)) { + $ex = new InvalidConfigurationException(sprintf('The value %s is not allowed for path "%s". Permissible values: %s', json_encode($value), $this->getPath(), implode(', ', array_map('json_encode', $this->values)))); + $ex->setPath($this->getPath()); + + throw $ex; + } + + return $value; + } + + /** + * {@inheritdoc} + */ + protected function allowPlaceholders(): bool + { + return false; + } +} diff --git a/vendor/symfony/config/Definition/Exception/DuplicateKeyException.php b/vendor/symfony/config/Definition/Exception/DuplicateKeyException.php new file mode 100644 index 0000000..48dd932 --- /dev/null +++ b/vendor/symfony/config/Definition/Exception/DuplicateKeyException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Exception; + +/** + * This exception is thrown whenever the key of an array is not unique. This can + * only be the case if the configuration is coming from an XML file. + * + * @author Johannes M. Schmitt + */ +class DuplicateKeyException extends InvalidConfigurationException +{ +} diff --git a/vendor/symfony/config/Definition/Exception/Exception.php b/vendor/symfony/config/Definition/Exception/Exception.php new file mode 100644 index 0000000..8933a49 --- /dev/null +++ b/vendor/symfony/config/Definition/Exception/Exception.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Exception; + +/** + * Base exception for all configuration exceptions. + * + * @author Johannes M. Schmitt + */ +class Exception extends \RuntimeException +{ +} diff --git a/vendor/symfony/config/Definition/Exception/ForbiddenOverwriteException.php b/vendor/symfony/config/Definition/Exception/ForbiddenOverwriteException.php new file mode 100644 index 0000000..726c07f --- /dev/null +++ b/vendor/symfony/config/Definition/Exception/ForbiddenOverwriteException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Exception; + +/** + * This exception is thrown when a configuration path is overwritten from a + * subsequent configuration file, but the entry node specifically forbids this. + * + * @author Johannes M. Schmitt + */ +class ForbiddenOverwriteException extends InvalidConfigurationException +{ +} diff --git a/vendor/symfony/config/Definition/Exception/InvalidConfigurationException.php b/vendor/symfony/config/Definition/Exception/InvalidConfigurationException.php new file mode 100644 index 0000000..fcaaf49 --- /dev/null +++ b/vendor/symfony/config/Definition/Exception/InvalidConfigurationException.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Exception; + +/** + * A very general exception which can be thrown whenever non of the more specific + * exceptions is suitable. + * + * @author Johannes M. Schmitt + */ +class InvalidConfigurationException extends Exception +{ + private $path; + private $containsHints = false; + + public function setPath($path) + { + $this->path = $path; + } + + public function getPath() + { + return $this->path; + } + + /** + * Adds extra information that is suffixed to the original exception message. + */ + public function addHint(string $hint) + { + if (!$this->containsHints) { + $this->message .= "\nHint: ".$hint; + $this->containsHints = true; + } else { + $this->message .= ', '.$hint; + } + } +} diff --git a/vendor/symfony/config/Definition/Exception/InvalidDefinitionException.php b/vendor/symfony/config/Definition/Exception/InvalidDefinitionException.php new file mode 100644 index 0000000..98310da --- /dev/null +++ b/vendor/symfony/config/Definition/Exception/InvalidDefinitionException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Exception; + +/** + * Thrown when an error is detected in a node Definition. + * + * @author Victor Berchet + */ +class InvalidDefinitionException extends Exception +{ +} diff --git a/vendor/symfony/config/Definition/Exception/InvalidTypeException.php b/vendor/symfony/config/Definition/Exception/InvalidTypeException.php new file mode 100644 index 0000000..d7ca8c9 --- /dev/null +++ b/vendor/symfony/config/Definition/Exception/InvalidTypeException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Exception; + +/** + * This exception is thrown if an invalid type is encountered. + * + * @author Johannes M. Schmitt + */ +class InvalidTypeException extends InvalidConfigurationException +{ +} diff --git a/vendor/symfony/config/Definition/Exception/UnsetKeyException.php b/vendor/symfony/config/Definition/Exception/UnsetKeyException.php new file mode 100644 index 0000000..863181a --- /dev/null +++ b/vendor/symfony/config/Definition/Exception/UnsetKeyException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition\Exception; + +/** + * This exception is usually not encountered by the end-user, but only used + * internally to signal the parent scope to unset a key. + * + * @author Johannes M. Schmitt + */ +class UnsetKeyException extends Exception +{ +} diff --git a/vendor/symfony/config/Definition/FloatNode.php b/vendor/symfony/config/Definition/FloatNode.php new file mode 100644 index 0000000..8e229ed --- /dev/null +++ b/vendor/symfony/config/Definition/FloatNode.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +use Symfony\Component\Config\Definition\Exception\InvalidTypeException; + +/** + * This node represents a float value in the config tree. + * + * @author Jeanmonod David + */ +class FloatNode extends NumericNode +{ + /** + * {@inheritdoc} + */ + protected function validateType($value) + { + // Integers are also accepted, we just cast them + if (\is_int($value)) { + $value = (float) $value; + } + + if (!\is_float($value)) { + $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected float, but got %s.', $this->getPath(), \gettype($value))); + if ($hint = $this->getInfo()) { + $ex->addHint($hint); + } + $ex->setPath($this->getPath()); + + throw $ex; + } + } + + /** + * {@inheritdoc} + */ + protected function getValidPlaceholderTypes(): array + { + return ['float']; + } +} diff --git a/vendor/symfony/config/Definition/IntegerNode.php b/vendor/symfony/config/Definition/IntegerNode.php new file mode 100644 index 0000000..e8c6a81 --- /dev/null +++ b/vendor/symfony/config/Definition/IntegerNode.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +use Symfony\Component\Config\Definition\Exception\InvalidTypeException; + +/** + * This node represents an integer value in the config tree. + * + * @author Jeanmonod David + */ +class IntegerNode extends NumericNode +{ + /** + * {@inheritdoc} + */ + protected function validateType($value) + { + if (!\is_int($value)) { + $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected int, but got %s.', $this->getPath(), \gettype($value))); + if ($hint = $this->getInfo()) { + $ex->addHint($hint); + } + $ex->setPath($this->getPath()); + + throw $ex; + } + } + + /** + * {@inheritdoc} + */ + protected function getValidPlaceholderTypes(): array + { + return ['int']; + } +} diff --git a/vendor/symfony/config/Definition/NodeInterface.php b/vendor/symfony/config/Definition/NodeInterface.php new file mode 100644 index 0000000..45f1f68 --- /dev/null +++ b/vendor/symfony/config/Definition/NodeInterface.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException; +use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; +use Symfony\Component\Config\Definition\Exception\InvalidTypeException; + +/** + * Common Interface among all nodes. + * + * In most cases, it is better to inherit from BaseNode instead of implementing + * this interface yourself. + * + * @author Johannes M. Schmitt + */ +interface NodeInterface +{ + /** + * Returns the name of the node. + * + * @return string The name of the node + */ + public function getName(); + + /** + * Returns the path of the node. + * + * @return string The node path + */ + public function getPath(); + + /** + * Returns true when the node is required. + * + * @return bool If the node is required + */ + public function isRequired(); + + /** + * Returns true when the node has a default value. + * + * @return bool If the node has a default value + */ + public function hasDefaultValue(); + + /** + * Returns the default value of the node. + * + * @return mixed The default value + * + * @throws \RuntimeException if the node has no default value + */ + public function getDefaultValue(); + + /** + * Normalizes a value. + * + * @param mixed $value The value to normalize + * + * @return mixed The normalized value + * + * @throws InvalidTypeException if the value type is invalid + */ + public function normalize($value); + + /** + * Merges two values together. + * + * @param mixed $leftSide + * @param mixed $rightSide + * + * @return mixed The merged value + * + * @throws ForbiddenOverwriteException if the configuration path cannot be overwritten + * @throws InvalidTypeException if the value type is invalid + */ + public function merge($leftSide, $rightSide); + + /** + * Finalizes a value. + * + * @param mixed $value The value to finalize + * + * @return mixed The finalized value + * + * @throws InvalidTypeException if the value type is invalid + * @throws InvalidConfigurationException if the value is invalid configuration + */ + public function finalize($value); +} diff --git a/vendor/symfony/config/Definition/NumericNode.php b/vendor/symfony/config/Definition/NumericNode.php new file mode 100644 index 0000000..19c96e8 --- /dev/null +++ b/vendor/symfony/config/Definition/NumericNode.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; + +/** + * This node represents a numeric value in the config tree. + * + * @author David Jeanmonod + */ +class NumericNode extends ScalarNode +{ + protected $min; + protected $max; + + public function __construct(?string $name, NodeInterface $parent = null, $min = null, $max = null, string $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR) + { + parent::__construct($name, $parent, $pathSeparator); + $this->min = $min; + $this->max = $max; + } + + /** + * {@inheritdoc} + */ + protected function finalizeValue($value) + { + $value = parent::finalizeValue($value); + + $errorMsg = null; + if (isset($this->min) && $value < $this->min) { + $errorMsg = sprintf('The value %s is too small for path "%s". Should be greater than or equal to %s', $value, $this->getPath(), $this->min); + } + if (isset($this->max) && $value > $this->max) { + $errorMsg = sprintf('The value %s is too big for path "%s". Should be less than or equal to %s', $value, $this->getPath(), $this->max); + } + if (isset($errorMsg)) { + $ex = new InvalidConfigurationException($errorMsg); + $ex->setPath($this->getPath()); + throw $ex; + } + + return $value; + } + + /** + * {@inheritdoc} + */ + protected function isValueEmpty($value) + { + // a numeric value cannot be empty + return false; + } +} diff --git a/vendor/symfony/config/Definition/Processor.php b/vendor/symfony/config/Definition/Processor.php new file mode 100644 index 0000000..76f4700 --- /dev/null +++ b/vendor/symfony/config/Definition/Processor.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +/** + * This class is the entry point for config normalization/merging/finalization. + * + * @author Johannes M. Schmitt + * + * @final + */ +class Processor +{ + /** + * Processes an array of configurations. + * + * @param array $configs An array of configuration items to process + * + * @return array The processed configuration + */ + public function process(NodeInterface $configTree, array $configs): array + { + $currentConfig = []; + foreach ($configs as $config) { + $config = $configTree->normalize($config); + $currentConfig = $configTree->merge($currentConfig, $config); + } + + return $configTree->finalize($currentConfig); + } + + /** + * Processes an array of configurations. + * + * @param array $configs An array of configuration items to process + * + * @return array The processed configuration + */ + public function processConfiguration(ConfigurationInterface $configuration, array $configs): array + { + return $this->process($configuration->getConfigTreeBuilder()->buildTree(), $configs); + } + + /** + * Normalizes a configuration entry. + * + * This method returns a normalize configuration array for a given key + * to remove the differences due to the original format (YAML and XML mainly). + * + * Here is an example. + * + * The configuration in XML: + * + * twig.extension.foo + * twig.extension.bar + * + * And the same configuration in YAML: + * + * extensions: ['twig.extension.foo', 'twig.extension.bar'] + * + * @param array $config A config array + * @param string $key The key to normalize + * @param string $plural The plural form of the key if it is irregular + */ + public static function normalizeConfig(array $config, string $key, string $plural = null): array + { + if (null === $plural) { + $plural = $key.'s'; + } + + if (isset($config[$plural])) { + return $config[$plural]; + } + + if (isset($config[$key])) { + if (\is_string($config[$key]) || !\is_int(key($config[$key]))) { + // only one + return [$config[$key]]; + } + + return $config[$key]; + } + + return []; + } +} diff --git a/vendor/symfony/config/Definition/PrototypeNodeInterface.php b/vendor/symfony/config/Definition/PrototypeNodeInterface.php new file mode 100644 index 0000000..b160aa9 --- /dev/null +++ b/vendor/symfony/config/Definition/PrototypeNodeInterface.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +/** + * This interface must be implemented by nodes which can be used as prototypes. + * + * @author Johannes M. Schmitt + */ +interface PrototypeNodeInterface extends NodeInterface +{ + /** + * Sets the name of the node. + */ + public function setName(string $name); +} diff --git a/vendor/symfony/config/Definition/PrototypedArrayNode.php b/vendor/symfony/config/Definition/PrototypedArrayNode.php new file mode 100644 index 0000000..ff4570e --- /dev/null +++ b/vendor/symfony/config/Definition/PrototypedArrayNode.php @@ -0,0 +1,365 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +use Symfony\Component\Config\Definition\Exception\DuplicateKeyException; +use Symfony\Component\Config\Definition\Exception\Exception; +use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; +use Symfony\Component\Config\Definition\Exception\UnsetKeyException; + +/** + * Represents a prototyped Array node in the config tree. + * + * @author Johannes M. Schmitt + */ +class PrototypedArrayNode extends ArrayNode +{ + protected $prototype; + protected $keyAttribute; + protected $removeKeyAttribute = false; + protected $minNumberOfElements = 0; + protected $defaultValue = []; + protected $defaultChildren; + /** + * @var NodeInterface[] An array of the prototypes of the simplified value children + */ + private $valuePrototypes = []; + + /** + * Sets the minimum number of elements that a prototype based node must + * contain. By default this is zero, meaning no elements. + */ + public function setMinNumberOfElements(int $number) + { + $this->minNumberOfElements = $number; + } + + /** + * Sets the attribute which value is to be used as key. + * + * This is useful when you have an indexed array that should be an + * associative array. You can select an item from within the array + * to be the key of the particular item. For example, if "id" is the + * "key", then: + * + * [ + * ['id' => 'my_name', 'foo' => 'bar'], + * ]; + * + * becomes + * + * [ + * 'my_name' => ['foo' => 'bar'], + * ]; + * + * If you'd like "'id' => 'my_name'" to still be present in the resulting + * array, then you can set the second argument of this method to false. + * + * @param string $attribute The name of the attribute which value is to be used as a key + * @param bool $remove Whether or not to remove the key + */ + public function setKeyAttribute(string $attribute, bool $remove = true) + { + $this->keyAttribute = $attribute; + $this->removeKeyAttribute = $remove; + } + + /** + * Retrieves the name of the attribute which value should be used as key. + * + * @return string|null The name of the attribute + */ + public function getKeyAttribute() + { + return $this->keyAttribute; + } + + /** + * Sets the default value of this node. + */ + public function setDefaultValue(array $value) + { + $this->defaultValue = $value; + } + + /** + * {@inheritdoc} + */ + public function hasDefaultValue() + { + return true; + } + + /** + * Adds default children when none are set. + * + * @param int|string|array|null $children The number of children|The child name|The children names to be added + */ + public function setAddChildrenIfNoneSet($children = ['defaults']) + { + if (null === $children) { + $this->defaultChildren = ['defaults']; + } else { + $this->defaultChildren = \is_int($children) && $children > 0 ? range(1, $children) : (array) $children; + } + } + + /** + * {@inheritdoc} + * + * The default value could be either explicited or derived from the prototype + * default value. + */ + public function getDefaultValue() + { + if (null !== $this->defaultChildren) { + $default = $this->prototype->hasDefaultValue() ? $this->prototype->getDefaultValue() : []; + $defaults = []; + foreach (array_values($this->defaultChildren) as $i => $name) { + $defaults[null === $this->keyAttribute ? $i : $name] = $default; + } + + return $defaults; + } + + return $this->defaultValue; + } + + /** + * Sets the node prototype. + */ + public function setPrototype(PrototypeNodeInterface $node) + { + $this->prototype = $node; + } + + /** + * Retrieves the prototype. + * + * @return PrototypeNodeInterface The prototype + */ + public function getPrototype() + { + return $this->prototype; + } + + /** + * Disable adding concrete children for prototyped nodes. + * + * @throws Exception + */ + public function addChild(NodeInterface $node) + { + throw new Exception('A prototyped array node can not have concrete children.'); + } + + /** + * Finalizes the value of this node. + * + * @param mixed $value + * + * @return mixed The finalized value + * + * @throws UnsetKeyException + * @throws InvalidConfigurationException if the node doesn't have enough children + */ + protected function finalizeValue($value) + { + if (false === $value) { + throw new UnsetKeyException(sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value))); + } + + foreach ($value as $k => $v) { + $prototype = $this->getPrototypeForChild($k); + try { + $value[$k] = $prototype->finalize($v); + } catch (UnsetKeyException $e) { + unset($value[$k]); + } + } + + if (\count($value) < $this->minNumberOfElements) { + $ex = new InvalidConfigurationException(sprintf('The path "%s" should have at least %d element(s) defined.', $this->getPath(), $this->minNumberOfElements)); + $ex->setPath($this->getPath()); + + throw $ex; + } + + return $value; + } + + /** + * Normalizes the value. + * + * @param mixed $value The value to normalize + * + * @return mixed The normalized value + * + * @throws InvalidConfigurationException + * @throws DuplicateKeyException + */ + protected function normalizeValue($value) + { + if (false === $value) { + return $value; + } + + $value = $this->remapXml($value); + + $isAssoc = array_keys($value) !== range(0, \count($value) - 1); + $normalized = []; + foreach ($value as $k => $v) { + if (null !== $this->keyAttribute && \is_array($v)) { + if (!isset($v[$this->keyAttribute]) && \is_int($k) && !$isAssoc) { + $ex = new InvalidConfigurationException(sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath())); + $ex->setPath($this->getPath()); + + throw $ex; + } elseif (isset($v[$this->keyAttribute])) { + $k = $v[$this->keyAttribute]; + + // remove the key attribute when required + if ($this->removeKeyAttribute) { + unset($v[$this->keyAttribute]); + } + + // if only "value" is left + if (array_keys($v) === ['value']) { + $v = $v['value']; + if ($this->prototype instanceof ArrayNode && ($children = $this->prototype->getChildren()) && \array_key_exists('value', $children)) { + $valuePrototype = current($this->valuePrototypes) ?: clone $children['value']; + $valuePrototype->parent = $this; + $originalClosures = $this->prototype->normalizationClosures; + if (\is_array($originalClosures)) { + $valuePrototypeClosures = $valuePrototype->normalizationClosures; + $valuePrototype->normalizationClosures = \is_array($valuePrototypeClosures) ? array_merge($originalClosures, $valuePrototypeClosures) : $originalClosures; + } + $this->valuePrototypes[$k] = $valuePrototype; + } + } + } + + if (\array_key_exists($k, $normalized)) { + $ex = new DuplicateKeyException(sprintf('Duplicate key "%s" for path "%s".', $k, $this->getPath())); + $ex->setPath($this->getPath()); + + throw $ex; + } + } + + $prototype = $this->getPrototypeForChild($k); + if (null !== $this->keyAttribute || $isAssoc) { + $normalized[$k] = $prototype->normalize($v); + } else { + $normalized[] = $prototype->normalize($v); + } + } + + return $normalized; + } + + /** + * Merges values together. + * + * @param mixed $leftSide The left side to merge + * @param mixed $rightSide The right side to merge + * + * @return mixed The merged values + * + * @throws InvalidConfigurationException + * @throws \RuntimeException + */ + protected function mergeValues($leftSide, $rightSide) + { + if (false === $rightSide) { + // if this is still false after the last config has been merged the + // finalization pass will take care of removing this key entirely + return false; + } + + if (false === $leftSide || !$this->performDeepMerging) { + return $rightSide; + } + + foreach ($rightSide as $k => $v) { + // prototype, and key is irrelevant, append the element + if (null === $this->keyAttribute) { + $leftSide[] = $v; + continue; + } + + // no conflict + if (!\array_key_exists($k, $leftSide)) { + if (!$this->allowNewKeys) { + $ex = new InvalidConfigurationException(sprintf('You are not allowed to define new elements for path "%s". Please define all elements for this path in one config file.', $this->getPath())); + $ex->setPath($this->getPath()); + + throw $ex; + } + + $leftSide[$k] = $v; + continue; + } + + $prototype = $this->getPrototypeForChild($k); + $leftSide[$k] = $prototype->merge($leftSide[$k], $v); + } + + return $leftSide; + } + + /** + * Returns a prototype for the child node that is associated to $key in the value array. + * For general child nodes, this will be $this->prototype. + * But if $this->removeKeyAttribute is true and there are only two keys in the child node: + * one is same as this->keyAttribute and the other is 'value', then the prototype will be different. + * + * For example, assume $this->keyAttribute is 'name' and the value array is as follows: + * + * [ + * [ + * 'name' => 'name001', + * 'value' => 'value001' + * ] + * ] + * + * Now, the key is 0 and the child node is: + * + * [ + * 'name' => 'name001', + * 'value' => 'value001' + * ] + * + * When normalizing the value array, the 'name' element will removed from the child node + * and its value becomes the new key of the child node: + * + * [ + * 'name001' => ['value' => 'value001'] + * ] + * + * Now only 'value' element is left in the child node which can be further simplified into a string: + * + * ['name001' => 'value001'] + * + * Now, the key becomes 'name001' and the child node becomes 'value001' and + * the prototype of child node 'name001' should be a ScalarNode instead of an ArrayNode instance. + * + * @return mixed The prototype instance + */ + private function getPrototypeForChild(string $key) + { + $prototype = isset($this->valuePrototypes[$key]) ? $this->valuePrototypes[$key] : $this->prototype; + $prototype->setName($key); + + return $prototype; + } +} diff --git a/vendor/symfony/config/Definition/ScalarNode.php b/vendor/symfony/config/Definition/ScalarNode.php new file mode 100644 index 0000000..5ad28ec --- /dev/null +++ b/vendor/symfony/config/Definition/ScalarNode.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +use Symfony\Component\Config\Definition\Exception\InvalidTypeException; + +/** + * This node represents a scalar value in the config tree. + * + * The following values are considered scalars: + * * booleans + * * strings + * * null + * * integers + * * floats + * + * @author Johannes M. Schmitt + */ +class ScalarNode extends VariableNode +{ + /** + * {@inheritdoc} + */ + protected function validateType($value) + { + if (!is_scalar($value) && null !== $value) { + $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected scalar, but got %s.', $this->getPath(), \gettype($value))); + if ($hint = $this->getInfo()) { + $ex->addHint($hint); + } + $ex->setPath($this->getPath()); + + throw $ex; + } + } + + /** + * {@inheritdoc} + */ + protected function isValueEmpty($value) + { + // assume environment variables are never empty (which in practice is likely to be true during runtime) + // not doing so breaks many configs that are valid today + if ($this->isHandlingPlaceholder()) { + return false; + } + + return null === $value || '' === $value; + } + + /** + * {@inheritdoc} + */ + protected function getValidPlaceholderTypes(): array + { + return ['bool', 'int', 'float', 'string']; + } +} diff --git a/vendor/symfony/config/Definition/VariableNode.php b/vendor/symfony/config/Definition/VariableNode.php new file mode 100644 index 0000000..e868ece --- /dev/null +++ b/vendor/symfony/config/Definition/VariableNode.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Definition; + +use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; + +/** + * This node represents a value of variable type in the config tree. + * + * This node is intended for values of arbitrary type. + * Any PHP type is accepted as a value. + * + * @author Jeremy Mikola + */ +class VariableNode extends BaseNode implements PrototypeNodeInterface +{ + protected $defaultValueSet = false; + protected $defaultValue; + protected $allowEmptyValue = true; + + public function setDefaultValue($value) + { + $this->defaultValueSet = true; + $this->defaultValue = $value; + } + + /** + * {@inheritdoc} + */ + public function hasDefaultValue() + { + return $this->defaultValueSet; + } + + /** + * {@inheritdoc} + */ + public function getDefaultValue() + { + $v = $this->defaultValue; + + return $v instanceof \Closure ? $v() : $v; + } + + /** + * Sets if this node is allowed to have an empty value. + * + * @param bool $boolean True if this entity will accept empty values + */ + public function setAllowEmptyValue(bool $boolean) + { + $this->allowEmptyValue = $boolean; + } + + /** + * {@inheritdoc} + */ + public function setName(string $name) + { + $this->name = $name; + } + + /** + * {@inheritdoc} + */ + protected function validateType($value) + { + } + + /** + * {@inheritdoc} + */ + protected function finalizeValue($value) + { + // deny environment variables only when using custom validators + // this avoids ever passing an empty value to final validation closures + if (!$this->allowEmptyValue && $this->isHandlingPlaceholder() && $this->finalValidationClosures) { + $e = new InvalidConfigurationException(sprintf('The path "%s" cannot contain an environment variable when empty values are not allowed by definition and are validated.', $this->getPath())); + if ($hint = $this->getInfo()) { + $e->addHint($hint); + } + $e->setPath($this->getPath()); + + throw $e; + } + + if (!$this->allowEmptyValue && $this->isValueEmpty($value)) { + $ex = new InvalidConfigurationException(sprintf('The path "%s" cannot contain an empty value, but got %s.', $this->getPath(), json_encode($value))); + if ($hint = $this->getInfo()) { + $ex->addHint($hint); + } + $ex->setPath($this->getPath()); + + throw $ex; + } + + return $value; + } + + /** + * {@inheritdoc} + */ + protected function normalizeValue($value) + { + return $value; + } + + /** + * {@inheritdoc} + */ + protected function mergeValues($leftSide, $rightSide) + { + return $rightSide; + } + + /** + * Evaluates if the given value is to be treated as empty. + * + * By default, PHP's empty() function is used to test for emptiness. This + * method may be overridden by subtypes to better match their understanding + * of empty data. + * + * @param mixed $value + * + * @return bool + * + * @see finalizeValue() + */ + protected function isValueEmpty($value) + { + return empty($value); + } +} diff --git a/vendor/symfony/config/Exception/FileLoaderImportCircularReferenceException.php b/vendor/symfony/config/Exception/FileLoaderImportCircularReferenceException.php new file mode 100644 index 0000000..8c5e736 --- /dev/null +++ b/vendor/symfony/config/Exception/FileLoaderImportCircularReferenceException.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Exception; + +/** + * Exception class for when a circular reference is detected when importing resources. + * + * @author Fabien Potencier + */ +class FileLoaderImportCircularReferenceException extends LoaderLoadException +{ + public function __construct(array $resources, int $code = null, \Throwable $previous = null) + { + $message = sprintf('Circular reference detected in "%s" ("%s" > "%s").', $this->varToString($resources[0]), implode('" > "', $resources), $resources[0]); + + \Exception::__construct($message, $code, $previous); + } +} diff --git a/vendor/symfony/config/Exception/FileLocatorFileNotFoundException.php b/vendor/symfony/config/Exception/FileLocatorFileNotFoundException.php new file mode 100644 index 0000000..3ee4b93 --- /dev/null +++ b/vendor/symfony/config/Exception/FileLocatorFileNotFoundException.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Exception; + +/** + * File locator exception if a file does not exist. + * + * @author Leo Feyer + */ +class FileLocatorFileNotFoundException extends \InvalidArgumentException +{ + private $paths; + + public function __construct(string $message = '', int $code = 0, \Throwable $previous = null, array $paths = []) + { + parent::__construct($message, $code, $previous); + + $this->paths = $paths; + } + + public function getPaths() + { + return $this->paths; + } +} diff --git a/vendor/symfony/config/Exception/LoaderLoadException.php b/vendor/symfony/config/Exception/LoaderLoadException.php new file mode 100644 index 0000000..dcec320 --- /dev/null +++ b/vendor/symfony/config/Exception/LoaderLoadException.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Exception; + +/** + * Exception class for when a resource cannot be loaded or imported. + * + * @author Ryan Weaver + */ +class LoaderLoadException extends \Exception +{ + /** + * @param string $resource The resource that could not be imported + * @param string $sourceResource The original resource importing the new resource + * @param int $code The error code + * @param \Throwable $previous A previous exception + * @param string $type The type of resource + */ + public function __construct(string $resource, string $sourceResource = null, int $code = null, \Throwable $previous = null, string $type = null) + { + $message = ''; + if ($previous) { + // Include the previous exception, to help the user see what might be the underlying cause + + // Trim the trailing period of the previous message. We only want 1 period remove so no rtrim... + if ('.' === substr($previous->getMessage(), -1)) { + $trimmedMessage = substr($previous->getMessage(), 0, -1); + $message .= sprintf('%s', $trimmedMessage).' in '; + } else { + $message .= sprintf('%s', $previous->getMessage()).' in '; + } + $message .= $resource.' '; + + // show tweaked trace to complete the human readable sentence + if (null === $sourceResource) { + $message .= sprintf('(which is loaded in resource "%s")', $resource); + } else { + $message .= sprintf('(which is being imported from "%s")', $sourceResource); + } + $message .= '.'; + + // if there's no previous message, present it the default way + } elseif (null === $sourceResource) { + $message .= sprintf('Cannot load resource "%s".', $resource); + } else { + $message .= sprintf('Cannot import resource "%s" from "%s".', $resource, $sourceResource); + } + + // Is the resource located inside a bundle? + if ('@' === $resource[0]) { + $parts = explode(\DIRECTORY_SEPARATOR, $resource); + $bundle = substr($parts[0], 1); + $message .= sprintf(' Make sure the "%s" bundle is correctly registered and loaded in the application kernel class.', $bundle); + $message .= sprintf(' If the bundle is registered, make sure the bundle path "%s" is not empty.', $resource); + } elseif (null !== $type) { + // maybe there is no loader for this specific type + if ('annotation' === $type) { + $message .= ' Make sure annotations are installed and enabled.'; + } else { + $message .= sprintf(' Make sure there is a loader supporting the "%s" type.', $type); + } + } + + parent::__construct($message, $code, $previous); + } + + protected function varToString($var) + { + if (\is_object($var)) { + return sprintf('Object(%s)', \get_class($var)); + } + + if (\is_array($var)) { + $a = []; + foreach ($var as $k => $v) { + $a[] = sprintf('%s => %s', $k, $this->varToString($v)); + } + + return sprintf('Array(%s)', implode(', ', $a)); + } + + if (\is_resource($var)) { + return sprintf('Resource(%s)', get_resource_type($var)); + } + + if (null === $var) { + return 'null'; + } + + if (false === $var) { + return 'false'; + } + + if (true === $var) { + return 'true'; + } + + return (string) $var; + } +} diff --git a/vendor/symfony/config/FileLocator.php b/vendor/symfony/config/FileLocator.php new file mode 100644 index 0000000..965f940 --- /dev/null +++ b/vendor/symfony/config/FileLocator.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config; + +use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; + +/** + * FileLocator uses an array of pre-defined paths to find files. + * + * @author Fabien Potencier + */ +class FileLocator implements FileLocatorInterface +{ + protected $paths; + + /** + * @param string|string[] $paths A path or an array of paths where to look for resources + */ + public function __construct($paths = []) + { + $this->paths = (array) $paths; + } + + /** + * {@inheritdoc} + */ + public function locate(string $name, string $currentPath = null, bool $first = true) + { + if ('' === $name) { + throw new \InvalidArgumentException('An empty file name is not valid to be located.'); + } + + if ($this->isAbsolutePath($name)) { + if (!file_exists($name)) { + throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist.', $name), 0, null, [$name]); + } + + return $name; + } + + $paths = $this->paths; + + if (null !== $currentPath) { + array_unshift($paths, $currentPath); + } + + $paths = array_unique($paths); + $filepaths = $notfound = []; + + foreach ($paths as $path) { + if (@file_exists($file = $path.\DIRECTORY_SEPARATOR.$name)) { + if (true === $first) { + return $file; + } + $filepaths[] = $file; + } else { + $notfound[] = $file; + } + } + + if (!$filepaths) { + throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist (in: %s).', $name, implode(', ', $paths)), 0, null, $notfound); + } + + return $filepaths; + } + + /** + * Returns whether the file path is an absolute path. + */ + private function isAbsolutePath(string $file): bool + { + if ('/' === $file[0] || '\\' === $file[0] + || (\strlen($file) > 3 && ctype_alpha($file[0]) + && ':' === $file[1] + && ('\\' === $file[2] || '/' === $file[2]) + ) + || null !== parse_url($file, PHP_URL_SCHEME) + ) { + return true; + } + + return false; + } +} diff --git a/vendor/symfony/config/FileLocatorInterface.php b/vendor/symfony/config/FileLocatorInterface.php new file mode 100644 index 0000000..e3ca1d4 --- /dev/null +++ b/vendor/symfony/config/FileLocatorInterface.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config; + +use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; + +/** + * @author Fabien Potencier + */ +interface FileLocatorInterface +{ + /** + * Returns a full path for a given file name. + * + * @param string $name The file name to locate + * @param string|null $currentPath The current path + * @param bool $first Whether to return the first occurrence or an array of filenames + * + * @return string|array The full path to the file or an array of file paths + * + * @throws \InvalidArgumentException If $name is empty + * @throws FileLocatorFileNotFoundException If a file is not found + */ + public function locate(string $name, string $currentPath = null, bool $first = true); +} diff --git a/vendor/symfony/config/LICENSE b/vendor/symfony/config/LICENSE new file mode 100644 index 0000000..a677f43 --- /dev/null +++ b/vendor/symfony/config/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/config/Loader/DelegatingLoader.php b/vendor/symfony/config/Loader/DelegatingLoader.php new file mode 100644 index 0000000..2ec64cb --- /dev/null +++ b/vendor/symfony/config/Loader/DelegatingLoader.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Loader; + +use Symfony\Component\Config\Exception\LoaderLoadException; + +/** + * DelegatingLoader delegates loading to other loaders using a loader resolver. + * + * This loader acts as an array of LoaderInterface objects - each having + * a chance to load a given resource (handled by the resolver) + * + * @author Fabien Potencier + */ +class DelegatingLoader extends Loader +{ + public function __construct(LoaderResolverInterface $resolver) + { + $this->resolver = $resolver; + } + + /** + * {@inheritdoc} + */ + public function load($resource, string $type = null) + { + if (false === $loader = $this->resolver->resolve($resource, $type)) { + throw new LoaderLoadException($resource, null, null, null, $type); + } + + return $loader->load($resource, $type); + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + return false !== $this->resolver->resolve($resource, $type); + } +} diff --git a/vendor/symfony/config/Loader/FileLoader.php b/vendor/symfony/config/Loader/FileLoader.php new file mode 100644 index 0000000..58dc4e7 --- /dev/null +++ b/vendor/symfony/config/Loader/FileLoader.php @@ -0,0 +1,179 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Loader; + +use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException; +use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; +use Symfony\Component\Config\Exception\LoaderLoadException; +use Symfony\Component\Config\FileLocatorInterface; +use Symfony\Component\Config\Resource\FileExistenceResource; +use Symfony\Component\Config\Resource\GlobResource; + +/** + * FileLoader is the abstract class used by all built-in loaders that are file based. + * + * @author Fabien Potencier + */ +abstract class FileLoader extends Loader +{ + protected static $loading = []; + + protected $locator; + + private $currentDir; + + public function __construct(FileLocatorInterface $locator) + { + $this->locator = $locator; + } + + /** + * Sets the current directory. + */ + public function setCurrentDir(string $dir) + { + $this->currentDir = $dir; + } + + /** + * Returns the file locator used by this loader. + * + * @return FileLocatorInterface + */ + public function getLocator() + { + return $this->locator; + } + + /** + * Imports a resource. + * + * @param mixed $resource A Resource + * @param string|null $type The resource type or null if unknown + * @param bool $ignoreErrors Whether to ignore import errors or not + * @param string|null $sourceResource The original resource importing the new resource + * @param string|string[]|null $exclude Glob patterns to exclude from the import + * + * @return mixed + * + * @throws LoaderLoadException + * @throws FileLoaderImportCircularReferenceException + * @throws FileLocatorFileNotFoundException + */ + public function import($resource, string $type = null, bool $ignoreErrors = false, string $sourceResource = null, $exclude = null) + { + if (\is_string($resource) && \strlen($resource) !== $i = strcspn($resource, '*?{[')) { + $excluded = []; + foreach ((array) $exclude as $pattern) { + foreach ($this->glob($pattern, true, $_, false, true) as $path => $info) { + // normalize Windows slashes + $excluded[str_replace('\\', '/', $path)] = true; + } + } + + $ret = []; + $isSubpath = 0 !== $i && false !== strpos(substr($resource, 0, $i), '/'); + foreach ($this->glob($resource, false, $_, $ignoreErrors || !$isSubpath, false, $excluded) as $path => $info) { + if (null !== $res = $this->doImport($path, $type, $ignoreErrors, $sourceResource)) { + $ret[] = $res; + } + $isSubpath = true; + } + + if ($isSubpath) { + return isset($ret[1]) ? $ret : (isset($ret[0]) ? $ret[0] : null); + } + } + + return $this->doImport($resource, $type, $ignoreErrors, $sourceResource); + } + + /** + * @internal + */ + protected function glob(string $pattern, bool $recursive, &$resource = null, bool $ignoreErrors = false, bool $forExclusion = false, array $excluded = []) + { + if (\strlen($pattern) === $i = strcspn($pattern, '*?{[')) { + $prefix = $pattern; + $pattern = ''; + } elseif (0 === $i || false === strpos(substr($pattern, 0, $i), '/')) { + $prefix = '.'; + $pattern = '/'.$pattern; + } else { + $prefix = \dirname(substr($pattern, 0, 1 + $i)); + $pattern = substr($pattern, \strlen($prefix)); + } + + try { + $prefix = $this->locator->locate($prefix, $this->currentDir, true); + } catch (FileLocatorFileNotFoundException $e) { + if (!$ignoreErrors) { + throw $e; + } + + $resource = []; + foreach ($e->getPaths() as $path) { + $resource[] = new FileExistenceResource($path); + } + + return; + } + $resource = new GlobResource($prefix, $pattern, $recursive, $forExclusion, $excluded); + + yield from $resource; + } + + private function doImport($resource, string $type = null, bool $ignoreErrors = false, string $sourceResource = null) + { + try { + $loader = $this->resolve($resource, $type); + + if ($loader instanceof self && null !== $this->currentDir) { + $resource = $loader->getLocator()->locate($resource, $this->currentDir, false); + } + + $resources = \is_array($resource) ? $resource : [$resource]; + for ($i = 0; $i < $resourcesCount = \count($resources); ++$i) { + if (isset(self::$loading[$resources[$i]])) { + if ($i == $resourcesCount - 1) { + throw new FileLoaderImportCircularReferenceException(array_keys(self::$loading)); + } + } else { + $resource = $resources[$i]; + break; + } + } + self::$loading[$resource] = true; + + try { + $ret = $loader->load($resource, $type); + } finally { + unset(self::$loading[$resource]); + } + + return $ret; + } catch (FileLoaderImportCircularReferenceException $e) { + throw $e; + } catch (\Exception $e) { + if (!$ignoreErrors) { + // prevent embedded imports from nesting multiple exceptions + if ($e instanceof LoaderLoadException) { + throw $e; + } + + throw new LoaderLoadException($resource, $sourceResource, null, $e, $type); + } + } + + return null; + } +} diff --git a/vendor/symfony/config/Loader/GlobFileLoader.php b/vendor/symfony/config/Loader/GlobFileLoader.php new file mode 100644 index 0000000..fecb1c5 --- /dev/null +++ b/vendor/symfony/config/Loader/GlobFileLoader.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Loader; + +/** + * GlobFileLoader loads files from a glob pattern. + * + * @author Fabien Potencier + */ +class GlobFileLoader extends FileLoader +{ + /** + * {@inheritdoc} + */ + public function load($resource, string $type = null) + { + return $this->import($resource); + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + return 'glob' === $type; + } +} diff --git a/vendor/symfony/config/Loader/Loader.php b/vendor/symfony/config/Loader/Loader.php new file mode 100644 index 0000000..62cae68 --- /dev/null +++ b/vendor/symfony/config/Loader/Loader.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Loader; + +use Symfony\Component\Config\Exception\LoaderLoadException; + +/** + * Loader is the abstract class used by all built-in loaders. + * + * @author Fabien Potencier + */ +abstract class Loader implements LoaderInterface +{ + protected $resolver; + + /** + * {@inheritdoc} + */ + public function getResolver() + { + return $this->resolver; + } + + /** + * {@inheritdoc} + */ + public function setResolver(LoaderResolverInterface $resolver) + { + $this->resolver = $resolver; + } + + /** + * Imports a resource. + * + * @param mixed $resource A resource + * @param string|null $type The resource type or null if unknown + * + * @return mixed + */ + public function import($resource, string $type = null) + { + return $this->resolve($resource, $type)->load($resource, $type); + } + + /** + * Finds a loader able to load an imported resource. + * + * @param mixed $resource A resource + * @param string|null $type The resource type or null if unknown + * + * @return $this|LoaderInterface + * + * @throws LoaderLoadException If no loader is found + */ + public function resolve($resource, string $type = null) + { + if ($this->supports($resource, $type)) { + return $this; + } + + $loader = null === $this->resolver ? false : $this->resolver->resolve($resource, $type); + + if (false === $loader) { + throw new LoaderLoadException($resource, null, null, null, $type); + } + + return $loader; + } +} diff --git a/vendor/symfony/config/Loader/LoaderInterface.php b/vendor/symfony/config/Loader/LoaderInterface.php new file mode 100644 index 0000000..4dfb42c --- /dev/null +++ b/vendor/symfony/config/Loader/LoaderInterface.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Loader; + +/** + * LoaderInterface is the interface implemented by all loader classes. + * + * @author Fabien Potencier + */ +interface LoaderInterface +{ + /** + * Loads a resource. + * + * @param mixed $resource The resource + * + * @throws \Exception If something went wrong + */ + public function load($resource, string $type = null); + + /** + * Returns whether this class supports the given resource. + * + * @param mixed $resource A resource + * + * @return bool True if this class supports the given resource, false otherwise + */ + public function supports($resource, string $type = null); + + /** + * Gets the loader resolver. + * + * @return LoaderResolverInterface A LoaderResolverInterface instance + */ + public function getResolver(); + + /** + * Sets the loader resolver. + */ + public function setResolver(LoaderResolverInterface $resolver); +} diff --git a/vendor/symfony/config/Loader/LoaderResolver.php b/vendor/symfony/config/Loader/LoaderResolver.php new file mode 100644 index 0000000..d243b91 --- /dev/null +++ b/vendor/symfony/config/Loader/LoaderResolver.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Loader; + +/** + * LoaderResolver selects a loader for a given resource. + * + * A resource can be anything (e.g. a full path to a config file or a Closure). + * Each loader determines whether it can load a resource and how. + * + * @author Fabien Potencier + */ +class LoaderResolver implements LoaderResolverInterface +{ + /** + * @var LoaderInterface[] An array of LoaderInterface objects + */ + private $loaders = []; + + /** + * @param LoaderInterface[] $loaders An array of loaders + */ + public function __construct(array $loaders = []) + { + foreach ($loaders as $loader) { + $this->addLoader($loader); + } + } + + /** + * {@inheritdoc} + */ + public function resolve($resource, string $type = null) + { + foreach ($this->loaders as $loader) { + if ($loader->supports($resource, $type)) { + return $loader; + } + } + + return false; + } + + public function addLoader(LoaderInterface $loader) + { + $this->loaders[] = $loader; + $loader->setResolver($this); + } + + /** + * Returns the registered loaders. + * + * @return LoaderInterface[] An array of LoaderInterface instances + */ + public function getLoaders() + { + return $this->loaders; + } +} diff --git a/vendor/symfony/config/Loader/LoaderResolverInterface.php b/vendor/symfony/config/Loader/LoaderResolverInterface.php new file mode 100644 index 0000000..2c45a4c --- /dev/null +++ b/vendor/symfony/config/Loader/LoaderResolverInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Loader; + +/** + * LoaderResolverInterface selects a loader for a given resource. + * + * @author Fabien Potencier + */ +interface LoaderResolverInterface +{ + /** + * Returns a loader able to load the resource. + * + * @param mixed $resource A resource + * @param string|null $type The resource type or null if unknown + * + * @return LoaderInterface|false The loader or false if none is able to load the resource + */ + public function resolve($resource, string $type = null); +} diff --git a/vendor/symfony/config/README.md b/vendor/symfony/config/README.md new file mode 100644 index 0000000..bf400da --- /dev/null +++ b/vendor/symfony/config/README.md @@ -0,0 +1,15 @@ +Config Component +================ + +The Config component provides several classes to help you find, load, combine, +autofill and validate configuration values of any kind, whatever their source +may be (YAML, XML, INI files, or for instance a database). + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/config/index.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/config/Resource/ClassExistenceResource.php b/vendor/symfony/config/Resource/ClassExistenceResource.php new file mode 100644 index 0000000..a547fb4 --- /dev/null +++ b/vendor/symfony/config/Resource/ClassExistenceResource.php @@ -0,0 +1,231 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +/** + * ClassExistenceResource represents a class existence. + * Freshness is only evaluated against resource existence. + * + * The resource must be a fully-qualified class name. + * + * @author Fabien Potencier + * + * @final + */ +class ClassExistenceResource implements SelfCheckingResourceInterface +{ + private $resource; + private $exists; + + private static $autoloadLevel = 0; + private static $autoloadedClass; + private static $existsCache = []; + + /** + * @param string $resource The fully-qualified class name + * @param bool|null $exists Boolean when the existency check has already been done + */ + public function __construct(string $resource, bool $exists = null) + { + $this->resource = $resource; + if (null !== $exists) { + $this->exists = [(bool) $exists, null]; + } + } + + /** + * {@inheritdoc} + */ + public function __toString(): string + { + return $this->resource; + } + + /** + * @return string The file path to the resource + */ + public function getResource(): string + { + return $this->resource; + } + + /** + * {@inheritdoc} + * + * @throws \ReflectionException when a parent class/interface/trait is not found + */ + public function isFresh(int $timestamp): bool + { + $loaded = class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false); + + if (null !== $exists = &self::$existsCache[$this->resource]) { + if ($loaded) { + $exists = [true, null]; + } elseif (0 >= $timestamp && !$exists[0] && null !== $exists[1]) { + throw new \ReflectionException($exists[1]); + } + } elseif ([false, null] === $exists = [$loaded, null]) { + if (!self::$autoloadLevel++) { + spl_autoload_register(__CLASS__.'::throwOnRequiredClass'); + } + $autoloadedClass = self::$autoloadedClass; + self::$autoloadedClass = ltrim($this->resource, '\\'); + + try { + $exists[0] = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false); + } catch (\Exception $e) { + $exists[1] = $e->getMessage(); + + try { + self::throwOnRequiredClass($this->resource, $e); + } catch (\ReflectionException $e) { + if (0 >= $timestamp) { + throw $e; + } + } + } catch (\Throwable $e) { + $exists[1] = $e->getMessage(); + } finally { + self::$autoloadedClass = $autoloadedClass; + if (!--self::$autoloadLevel) { + spl_autoload_unregister(__CLASS__.'::throwOnRequiredClass'); + } + } + } + + if (null === $this->exists) { + $this->exists = $exists; + } + + return $this->exists[0] xor !$exists[0]; + } + + /** + * @internal + */ + public function __sleep(): array + { + if (null === $this->exists) { + $this->isFresh(0); + } + + return ['resource', 'exists']; + } + + /** + * @internal + */ + public function __wakeup() + { + if (\is_bool($this->exists)) { + $this->exists = [$this->exists, null]; + } + } + + /** + * Throws a reflection exception when the passed class does not exist but is required. + * + * A class is considered "not required" when it's loaded as part of a "class_exists" or similar check. + * + * This function can be used as an autoload function to throw a reflection + * exception if the class was not found by previous autoload functions. + * + * A previous exception can be passed. In this case, the class is considered as being + * required totally, so if it doesn't exist, a reflection exception is always thrown. + * If it exists, the previous exception is rethrown. + * + * @throws \ReflectionException + * + * @internal + */ + public static function throwOnRequiredClass(string $class, \Exception $previous = null) + { + // If the passed class is the resource being checked, we shouldn't throw. + if (null === $previous && self::$autoloadedClass === $class) { + return; + } + + if (class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) { + if (null !== $previous) { + throw $previous; + } + + return; + } + + if ($previous instanceof \ReflectionException) { + throw $previous; + } + + $message = sprintf('Class "%s" not found.', $class); + + if (self::$autoloadedClass !== $class) { + $message = substr_replace($message, sprintf(' while loading "%s"', self::$autoloadedClass), -1, 0); + } + + if (null !== $previous) { + $message = $previous->getMessage(); + } + + $e = new \ReflectionException($message, 0, $previous); + + if (null !== $previous) { + throw $e; + } + + $trace = debug_backtrace(); + $autoloadFrame = [ + 'function' => 'spl_autoload_call', + 'args' => [$class], + ]; + + if (false === $i = array_search($autoloadFrame, $trace, true)) { + throw $e; + } + + if (isset($trace[++$i]['function']) && !isset($trace[$i]['class'])) { + switch ($trace[$i]['function']) { + case 'get_class_methods': + case 'get_class_vars': + case 'get_parent_class': + case 'is_a': + case 'is_subclass_of': + case 'class_exists': + case 'class_implements': + case 'class_parents': + case 'trait_exists': + case 'defined': + case 'interface_exists': + case 'method_exists': + case 'property_exists': + case 'is_callable': + return; + } + + $props = [ + 'file' => isset($trace[$i]['file']) ? $trace[$i]['file'] : null, + 'line' => isset($trace[$i]['line']) ? $trace[$i]['line'] : null, + 'trace' => \array_slice($trace, 1 + $i), + ]; + + foreach ($props as $p => $v) { + if (null !== $v) { + $r = new \ReflectionProperty('Exception', $p); + $r->setAccessible(true); + $r->setValue($e, $v); + } + } + } + + throw $e; + } +} diff --git a/vendor/symfony/config/Resource/ComposerResource.php b/vendor/symfony/config/Resource/ComposerResource.php new file mode 100644 index 0000000..e2abe0c --- /dev/null +++ b/vendor/symfony/config/Resource/ComposerResource.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +/** + * ComposerResource tracks the PHP version and Composer dependencies. + * + * @author Nicolas Grekas + * + * @final + */ +class ComposerResource implements SelfCheckingResourceInterface +{ + private $vendors; + + private static $runtimeVendors; + + public function __construct() + { + self::refresh(); + $this->vendors = self::$runtimeVendors; + } + + public function getVendors(): array + { + return array_keys($this->vendors); + } + + /** + * {@inheritdoc} + */ + public function __toString(): string + { + return __CLASS__; + } + + /** + * {@inheritdoc} + */ + public function isFresh(int $timestamp): bool + { + self::refresh(); + + return array_values(self::$runtimeVendors) === array_values($this->vendors); + } + + private static function refresh() + { + self::$runtimeVendors = []; + + foreach (get_declared_classes() as $class) { + if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) { + $r = new \ReflectionClass($class); + $v = \dirname($r->getFileName(), 2); + if (file_exists($v.'/composer/installed.json')) { + self::$runtimeVendors[$v] = @filemtime($v.'/composer/installed.json'); + } + } + } + } +} diff --git a/vendor/symfony/config/Resource/DirectoryResource.php b/vendor/symfony/config/Resource/DirectoryResource.php new file mode 100644 index 0000000..1a28881 --- /dev/null +++ b/vendor/symfony/config/Resource/DirectoryResource.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +/** + * DirectoryResource represents a resources stored in a subdirectory tree. + * + * @author Fabien Potencier + * + * @final + */ +class DirectoryResource implements SelfCheckingResourceInterface +{ + private $resource; + private $pattern; + + /** + * @param string $resource The file path to the resource + * @param string|null $pattern A pattern to restrict monitored files + * + * @throws \InvalidArgumentException + */ + public function __construct(string $resource, string $pattern = null) + { + $this->resource = realpath($resource) ?: (file_exists($resource) ? $resource : false); + $this->pattern = $pattern; + + if (false === $this->resource || !is_dir($this->resource)) { + throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist.', $resource)); + } + } + + /** + * {@inheritdoc} + */ + public function __toString(): string + { + return md5(serialize([$this->resource, $this->pattern])); + } + + /** + * @return string The file path to the resource + */ + public function getResource(): string + { + return $this->resource; + } + + /** + * Returns the pattern to restrict monitored files. + */ + public function getPattern(): ?string + { + return $this->pattern; + } + + /** + * {@inheritdoc} + */ + public function isFresh(int $timestamp): bool + { + if (!is_dir($this->resource)) { + return false; + } + + if ($timestamp < filemtime($this->resource)) { + return false; + } + + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->resource), \RecursiveIteratorIterator::SELF_FIRST) as $file) { + // if regex filtering is enabled only check matching files + if ($this->pattern && $file->isFile() && !preg_match($this->pattern, $file->getBasename())) { + continue; + } + + // always monitor directories for changes, except the .. entries + // (otherwise deleted files wouldn't get detected) + if ($file->isDir() && '/..' === substr($file, -3)) { + continue; + } + + // for broken links + try { + $fileMTime = $file->getMTime(); + } catch (\RuntimeException $e) { + continue; + } + + // early return if a file's mtime exceeds the passed timestamp + if ($timestamp < $fileMTime) { + return false; + } + } + + return true; + } +} diff --git a/vendor/symfony/config/Resource/FileExistenceResource.php b/vendor/symfony/config/Resource/FileExistenceResource.php new file mode 100644 index 0000000..ca2d2c3 --- /dev/null +++ b/vendor/symfony/config/Resource/FileExistenceResource.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +/** + * FileExistenceResource represents a resource stored on the filesystem. + * Freshness is only evaluated against resource creation or deletion. + * + * The resource can be a file or a directory. + * + * @author Charles-Henri Bruyand + * + * @final + */ +class FileExistenceResource implements SelfCheckingResourceInterface +{ + private $resource; + + private $exists; + + /** + * @param string $resource The file path to the resource + */ + public function __construct(string $resource) + { + $this->resource = $resource; + $this->exists = file_exists($resource); + } + + /** + * {@inheritdoc} + */ + public function __toString(): string + { + return $this->resource; + } + + /** + * @return string The file path to the resource + */ + public function getResource(): string + { + return $this->resource; + } + + /** + * {@inheritdoc} + */ + public function isFresh(int $timestamp): bool + { + return file_exists($this->resource) === $this->exists; + } +} diff --git a/vendor/symfony/config/Resource/FileResource.php b/vendor/symfony/config/Resource/FileResource.php new file mode 100644 index 0000000..4274d07 --- /dev/null +++ b/vendor/symfony/config/Resource/FileResource.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +/** + * FileResource represents a resource stored on the filesystem. + * + * The resource can be a file or a directory. + * + * @author Fabien Potencier + * + * @final + */ +class FileResource implements SelfCheckingResourceInterface +{ + /** + * @var string|false + */ + private $resource; + + /** + * @param string $resource The file path to the resource + * + * @throws \InvalidArgumentException + */ + public function __construct(string $resource) + { + $this->resource = realpath($resource) ?: (file_exists($resource) ? $resource : false); + + if (false === $this->resource) { + throw new \InvalidArgumentException(sprintf('The file "%s" does not exist.', $resource)); + } + } + + /** + * {@inheritdoc} + */ + public function __toString(): string + { + return $this->resource; + } + + /** + * @return string The canonicalized, absolute path to the resource + */ + public function getResource(): string + { + return $this->resource; + } + + /** + * {@inheritdoc} + */ + public function isFresh(int $timestamp): bool + { + return false !== ($filemtime = @filemtime($this->resource)) && $filemtime <= $timestamp; + } +} diff --git a/vendor/symfony/config/Resource/GlobResource.php b/vendor/symfony/config/Resource/GlobResource.php new file mode 100644 index 0000000..8f5a2f1 --- /dev/null +++ b/vendor/symfony/config/Resource/GlobResource.php @@ -0,0 +1,230 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +use Symfony\Component\Finder\Finder; +use Symfony\Component\Finder\Glob; + +/** + * GlobResource represents a set of resources stored on the filesystem. + * + * Only existence/removal is tracked (not mtimes.) + * + * @author Nicolas Grekas + * + * @final + */ +class GlobResource implements \IteratorAggregate, SelfCheckingResourceInterface +{ + private $prefix; + private $pattern; + private $recursive; + private $hash; + private $forExclusion; + private $excludedPrefixes; + private $globBrace; + + /** + * @param string $prefix A directory prefix + * @param string $pattern A glob pattern + * @param bool $recursive Whether directories should be scanned recursively or not + * + * @throws \InvalidArgumentException + */ + public function __construct(string $prefix, string $pattern, bool $recursive, bool $forExclusion = false, array $excludedPrefixes = []) + { + ksort($excludedPrefixes); + $this->prefix = realpath($prefix) ?: (file_exists($prefix) ? $prefix : false); + $this->pattern = $pattern; + $this->recursive = $recursive; + $this->forExclusion = $forExclusion; + $this->excludedPrefixes = $excludedPrefixes; + $this->globBrace = \defined('GLOB_BRACE') ? GLOB_BRACE : 0; + + if (false === $this->prefix) { + throw new \InvalidArgumentException(sprintf('The path "%s" does not exist.', $prefix)); + } + } + + public function getPrefix(): string + { + return $this->prefix; + } + + /** + * {@inheritdoc} + */ + public function __toString(): string + { + return 'glob.'.$this->prefix.(int) $this->recursive.$this->pattern.(int) $this->forExclusion.implode("\0", $this->excludedPrefixes); + } + + /** + * {@inheritdoc} + */ + public function isFresh(int $timestamp): bool + { + $hash = $this->computeHash(); + + if (null === $this->hash) { + $this->hash = $hash; + } + + return $this->hash === $hash; + } + + /** + * @internal + */ + public function __sleep(): array + { + if (null === $this->hash) { + $this->hash = $this->computeHash(); + } + + return ['prefix', 'pattern', 'recursive', 'hash', 'forExclusion', 'excludedPrefixes']; + } + + public function getIterator(): \Traversable + { + if (!file_exists($this->prefix) || (!$this->recursive && '' === $this->pattern)) { + return; + } + $prefix = str_replace('\\', '/', $this->prefix); + $paths = null; + + if (0 !== strpos($this->prefix, 'phar://') && false === strpos($this->pattern, '/**/')) { + if ($this->globBrace || false === strpos($this->pattern, '{')) { + $paths = glob($this->prefix.$this->pattern, GLOB_NOSORT | $this->globBrace); + } elseif (false === strpos($this->pattern, '\\') || !preg_match('/\\\\[,{}]/', $this->pattern)) { + foreach ($this->expandGlob($this->pattern) as $p) { + $paths[] = glob($this->prefix.$p, GLOB_NOSORT); + } + $paths = array_merge(...$paths); + } + } + + if (null !== $paths) { + sort($paths); + foreach ($paths as $path) { + if ($this->excludedPrefixes) { + $normalizedPath = str_replace('\\', '/', $path); + do { + if (isset($this->excludedPrefixes[$dirPath = $normalizedPath])) { + continue 2; + } + } while ($prefix !== $dirPath && $dirPath !== $normalizedPath = \dirname($dirPath)); + } + + if (is_file($path)) { + yield $path => new \SplFileInfo($path); + } + if (!is_dir($path)) { + continue; + } + if ($this->forExclusion) { + yield $path => new \SplFileInfo($path); + continue; + } + if (!$this->recursive || isset($this->excludedPrefixes[str_replace('\\', '/', $path)])) { + continue; + } + $files = iterator_to_array(new \RecursiveIteratorIterator( + new \RecursiveCallbackFilterIterator( + new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), + function (\SplFileInfo $file, $path) { + return !isset($this->excludedPrefixes[str_replace('\\', '/', $path)]) && '.' !== $file->getBasename()[0]; + } + ), + \RecursiveIteratorIterator::LEAVES_ONLY + )); + uasort($files, 'strnatcmp'); + + foreach ($files as $path => $info) { + if ($info->isFile()) { + yield $path => $info; + } + } + } + + return; + } + + if (!class_exists(Finder::class)) { + throw new \LogicException(sprintf('Extended glob pattern "%s" cannot be used as the Finder component is not installed.', $this->pattern)); + } + + $finder = new Finder(); + $regex = Glob::toRegex($this->pattern); + if ($this->recursive) { + $regex = substr_replace($regex, '(/|$)', -2, 1); + } + + $prefixLen = \strlen($this->prefix); + foreach ($finder->followLinks()->sortByName()->in($this->prefix) as $path => $info) { + $normalizedPath = str_replace('\\', '/', $path); + if (!preg_match($regex, substr($normalizedPath, $prefixLen)) || !$info->isFile()) { + continue; + } + if ($this->excludedPrefixes) { + do { + if (isset($this->excludedPrefixes[$dirPath = $normalizedPath])) { + continue 2; + } + } while ($prefix !== $dirPath && $dirPath !== $normalizedPath = \dirname($dirPath)); + } + + yield $path => $info; + } + } + + private function computeHash(): string + { + $hash = hash_init('md5'); + + foreach ($this->getIterator() as $path => $info) { + hash_update($hash, $path."\n"); + } + + return hash_final($hash); + } + + private function expandGlob(string $pattern): array + { + $segments = preg_split('/\{([^{}]*+)\}/', $pattern, -1, PREG_SPLIT_DELIM_CAPTURE); + $paths = [$segments[0]]; + $patterns = []; + + for ($i = 1; $i < \count($segments); $i += 2) { + $patterns = []; + + foreach (explode(',', $segments[$i]) as $s) { + foreach ($paths as $p) { + $patterns[] = $p.$s.$segments[1 + $i]; + } + } + + $paths = $patterns; + } + + $j = 0; + foreach ($patterns as $i => $p) { + if (false !== strpos($p, '{')) { + $p = $this->expandGlob($p); + array_splice($paths, $i + $j, 1, $p); + $j += \count($p) - 1; + } + } + + return $paths; + } +} diff --git a/vendor/symfony/config/Resource/ReflectionClassResource.php b/vendor/symfony/config/Resource/ReflectionClassResource.php new file mode 100644 index 0000000..bca9269 --- /dev/null +++ b/vendor/symfony/config/Resource/ReflectionClassResource.php @@ -0,0 +1,220 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\Messenger\Handler\MessageSubscriberInterface; +use Symfony\Contracts\Service\ServiceSubscriberInterface; + +/** + * @author Nicolas Grekas + * + * @final + */ +class ReflectionClassResource implements SelfCheckingResourceInterface +{ + private $files = []; + private $className; + private $classReflector; + private $excludedVendors = []; + private $hash; + + public function __construct(\ReflectionClass $classReflector, array $excludedVendors = []) + { + $this->className = $classReflector->name; + $this->classReflector = $classReflector; + $this->excludedVendors = $excludedVendors; + } + + /** + * {@inheritdoc} + */ + public function isFresh(int $timestamp): bool + { + if (null === $this->hash) { + $this->hash = $this->computeHash(); + $this->loadFiles($this->classReflector); + } + + foreach ($this->files as $file => $v) { + if (false === $filemtime = @filemtime($file)) { + return false; + } + + if ($filemtime > $timestamp) { + return $this->hash === $this->computeHash(); + } + } + + return true; + } + + public function __toString(): string + { + return 'reflection.'.$this->className; + } + + /** + * @internal + */ + public function __sleep(): array + { + if (null === $this->hash) { + $this->hash = $this->computeHash(); + $this->loadFiles($this->classReflector); + } + + return ['files', 'className', 'hash']; + } + + private function loadFiles(\ReflectionClass $class) + { + foreach ($class->getInterfaces() as $v) { + $this->loadFiles($v); + } + do { + $file = $class->getFileName(); + if (false !== $file && file_exists($file)) { + foreach ($this->excludedVendors as $vendor) { + if (0 === strpos($file, $vendor) && false !== strpbrk(substr($file, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) { + $file = false; + break; + } + } + if ($file) { + $this->files[$file] = null; + } + } + foreach ($class->getTraits() as $v) { + $this->loadFiles($v); + } + } while ($class = $class->getParentClass()); + } + + private function computeHash(): string + { + if (null === $this->classReflector) { + try { + $this->classReflector = new \ReflectionClass($this->className); + } catch (\ReflectionException $e) { + // the class does not exist anymore + return false; + } + } + $hash = hash_init('md5'); + + foreach ($this->generateSignature($this->classReflector) as $info) { + hash_update($hash, $info); + } + + return hash_final($hash); + } + + private function generateSignature(\ReflectionClass $class): iterable + { + yield $class->getDocComment(); + yield (int) $class->isFinal(); + yield (int) $class->isAbstract(); + + if ($class->isTrait()) { + yield print_r(class_uses($class->name), true); + } else { + yield print_r(class_parents($class->name), true); + yield print_r(class_implements($class->name), true); + yield print_r($class->getConstants(), true); + } + + if (!$class->isInterface()) { + $defaults = $class->getDefaultProperties(); + + foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED) as $p) { + yield $p->getDocComment().$p; + yield print_r(isset($defaults[$p->name]) && !\is_object($defaults[$p->name]) ? $defaults[$p->name] : null, true); + } + } + + foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) { + $defaults = []; + $parametersWithUndefinedConstants = []; + foreach ($m->getParameters() as $p) { + if (!$p->isDefaultValueAvailable()) { + $defaults[$p->name] = null; + + continue; + } + + if (!$p->isDefaultValueConstant() || \defined($p->getDefaultValueConstantName())) { + $defaults[$p->name] = $p->getDefaultValue(); + + continue; + } + + $defaults[$p->name] = $p->getDefaultValueConstantName(); + $parametersWithUndefinedConstants[$p->name] = true; + } + + if (!$parametersWithUndefinedConstants) { + yield preg_replace('/^ @@.*/m', '', $m); + } else { + $stack = [ + $m->getDocComment(), + $m->getName(), + $m->isAbstract(), + $m->isFinal(), + $m->isStatic(), + $m->isPublic(), + $m->isPrivate(), + $m->isProtected(), + $m->returnsReference(), + $m->hasReturnType() ? $m->getReturnType()->getName() : '', + ]; + + foreach ($m->getParameters() as $p) { + if (!isset($parametersWithUndefinedConstants[$p->name])) { + $stack[] = (string) $p; + } else { + $stack[] = $p->isOptional(); + $stack[] = $p->hasType() ? $p->getType()->getName() : ''; + $stack[] = $p->isPassedByReference(); + $stack[] = $p->isVariadic(); + $stack[] = $p->getName(); + } + } + + yield implode(',', $stack); + } + + yield print_r($defaults, true); + } + + if ($class->isAbstract() || $class->isInterface() || $class->isTrait()) { + return; + } + + if (interface_exists(EventSubscriberInterface::class, false) && $class->isSubclassOf(EventSubscriberInterface::class)) { + yield EventSubscriberInterface::class; + yield print_r($class->name::getSubscribedEvents(), true); + } + + if (interface_exists(MessageSubscriberInterface::class, false) && $class->isSubclassOf(MessageSubscriberInterface::class)) { + yield MessageSubscriberInterface::class; + foreach ($class->name::getHandledMessages() as $key => $value) { + yield $key.print_r($value, true); + } + } + + if (interface_exists(ServiceSubscriberInterface::class, false) && $class->isSubclassOf(ServiceSubscriberInterface::class)) { + yield ServiceSubscriberInterface::class; + yield print_r($class->name::getSubscribedServices(), true); + } + } +} diff --git a/vendor/symfony/config/Resource/ResourceInterface.php b/vendor/symfony/config/Resource/ResourceInterface.php new file mode 100644 index 0000000..d98fd42 --- /dev/null +++ b/vendor/symfony/config/Resource/ResourceInterface.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +/** + * ResourceInterface is the interface that must be implemented by all Resource classes. + * + * @author Fabien Potencier + */ +interface ResourceInterface +{ + /** + * Returns a string representation of the Resource. + * + * This method is necessary to allow for resource de-duplication, for example by means + * of array_unique(). The string returned need not have a particular meaning, but has + * to be identical for different ResourceInterface instances referring to the same + * resource; and it should be unlikely to collide with that of other, unrelated + * resource instances. + * + * @return string A string representation unique to the underlying Resource + */ + public function __toString(); +} diff --git a/vendor/symfony/config/Resource/SelfCheckingResourceChecker.php b/vendor/symfony/config/Resource/SelfCheckingResourceChecker.php new file mode 100644 index 0000000..eab3323 --- /dev/null +++ b/vendor/symfony/config/Resource/SelfCheckingResourceChecker.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +use Symfony\Component\Config\ResourceCheckerInterface; + +/** + * Resource checker for instances of SelfCheckingResourceInterface. + * + * As these resources perform the actual check themselves, we can provide + * this class as a standard way of validating them. + * + * @author Matthias Pigulla + */ +class SelfCheckingResourceChecker implements ResourceCheckerInterface +{ + public function supports(ResourceInterface $metadata) + { + return $metadata instanceof SelfCheckingResourceInterface; + } + + public function isFresh(ResourceInterface $resource, int $timestamp) + { + /* @var SelfCheckingResourceInterface $resource */ + return $resource->isFresh($timestamp); + } +} diff --git a/vendor/symfony/config/Resource/SelfCheckingResourceInterface.php b/vendor/symfony/config/Resource/SelfCheckingResourceInterface.php new file mode 100644 index 0000000..c08d969 --- /dev/null +++ b/vendor/symfony/config/Resource/SelfCheckingResourceInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +/** + * Interface for Resources that can check for freshness autonomously, + * without special support from external services. + * + * @author Matthias Pigulla + */ +interface SelfCheckingResourceInterface extends ResourceInterface +{ + /** + * Returns true if the resource has not been updated since the given timestamp. + * + * @param int $timestamp The last time the resource was loaded + * + * @return bool True if the resource has not been updated, false otherwise + */ + public function isFresh(int $timestamp); +} diff --git a/vendor/symfony/config/ResourceCheckerConfigCache.php b/vendor/symfony/config/ResourceCheckerConfigCache.php new file mode 100644 index 0000000..753ee4d --- /dev/null +++ b/vendor/symfony/config/ResourceCheckerConfigCache.php @@ -0,0 +1,188 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config; + +use Symfony\Component\Config\Resource\ResourceInterface; +use Symfony\Component\Filesystem\Exception\IOException; +use Symfony\Component\Filesystem\Filesystem; + +/** + * ResourceCheckerConfigCache uses instances of ResourceCheckerInterface + * to check whether cached data is still fresh. + * + * @author Matthias Pigulla + */ +class ResourceCheckerConfigCache implements ConfigCacheInterface +{ + /** + * @var string + */ + private $file; + + /** + * @var iterable|ResourceCheckerInterface[] + */ + private $resourceCheckers; + + /** + * @param string $file The absolute cache path + * @param iterable|ResourceCheckerInterface[] $resourceCheckers The ResourceCheckers to use for the freshness check + */ + public function __construct(string $file, iterable $resourceCheckers = []) + { + $this->file = $file; + $this->resourceCheckers = $resourceCheckers; + } + + /** + * {@inheritdoc} + */ + public function getPath() + { + return $this->file; + } + + /** + * Checks if the cache is still fresh. + * + * This implementation will make a decision solely based on the ResourceCheckers + * passed in the constructor. + * + * The first ResourceChecker that supports a given resource is considered authoritative. + * Resources with no matching ResourceChecker will silently be ignored and considered fresh. + * + * @return bool true if the cache is fresh, false otherwise + */ + public function isFresh() + { + if (!is_file($this->file)) { + return false; + } + + if ($this->resourceCheckers instanceof \Traversable && !$this->resourceCheckers instanceof \Countable) { + $this->resourceCheckers = iterator_to_array($this->resourceCheckers); + } + + if (!\count($this->resourceCheckers)) { + return true; // shortcut - if we don't have any checkers we don't need to bother with the meta file at all + } + + $metadata = $this->getMetaFile(); + + if (!is_file($metadata)) { + return false; + } + + $meta = $this->safelyUnserialize($metadata); + + if (false === $meta) { + return false; + } + + $time = filemtime($this->file); + + foreach ($meta as $resource) { + /* @var ResourceInterface $resource */ + foreach ($this->resourceCheckers as $checker) { + if (!$checker->supports($resource)) { + continue; // next checker + } + if ($checker->isFresh($resource, $time)) { + break; // no need to further check this resource + } + + return false; // cache is stale + } + // no suitable checker found, ignore this resource + } + + return true; + } + + /** + * Writes cache. + * + * @param string $content The content to write in the cache + * @param ResourceInterface[] $metadata An array of metadata + * + * @throws \RuntimeException When cache file can't be written + */ + public function write(string $content, array $metadata = null) + { + $mode = 0666; + $umask = umask(); + $filesystem = new Filesystem(); + $filesystem->dumpFile($this->file, $content); + try { + $filesystem->chmod($this->file, $mode, $umask); + } catch (IOException $e) { + // discard chmod failure (some filesystem may not support it) + } + + if (null !== $metadata) { + $filesystem->dumpFile($this->getMetaFile(), serialize($metadata)); + try { + $filesystem->chmod($this->getMetaFile(), $mode, $umask); + } catch (IOException $e) { + // discard chmod failure (some filesystem may not support it) + } + } + + if (\function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN)) { + @opcache_invalidate($this->file, true); + } + } + + /** + * Gets the meta file path. + */ + private function getMetaFile(): string + { + return $this->file.'.meta'; + } + + private function safelyUnserialize(string $file) + { + $meta = false; + $content = file_get_contents($file); + $signalingException = new \UnexpectedValueException(); + $prevUnserializeHandler = ini_set('unserialize_callback_func', self::class.'::handleUnserializeCallback'); + $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler, $signalingException) { + if (__FILE__ === $file) { + throw $signalingException; + } + + return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false; + }); + + try { + $meta = unserialize($content); + } catch (\Throwable $e) { + if ($e !== $signalingException) { + throw $e; + } + } finally { + restore_error_handler(); + ini_set('unserialize_callback_func', $prevUnserializeHandler); + } + + return $meta; + } + + /** + * @internal + */ + public static function handleUnserializeCallback($class) + { + trigger_error('Class not found: '.$class); + } +} diff --git a/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php b/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php new file mode 100644 index 0000000..a789644 --- /dev/null +++ b/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config; + +/** + * A ConfigCacheFactory implementation that validates the + * cache with an arbitrary set of ResourceCheckers. + * + * @author Matthias Pigulla + */ +class ResourceCheckerConfigCacheFactory implements ConfigCacheFactoryInterface +{ + private $resourceCheckers = []; + + /** + * @param iterable|ResourceCheckerInterface[] $resourceCheckers + */ + public function __construct(iterable $resourceCheckers = []) + { + $this->resourceCheckers = $resourceCheckers; + } + + /** + * {@inheritdoc} + */ + public function cache(string $file, callable $callable) + { + $cache = new ResourceCheckerConfigCache($file, $this->resourceCheckers); + if (!$cache->isFresh()) { + $callable($cache); + } + + return $cache; + } +} diff --git a/vendor/symfony/config/ResourceCheckerInterface.php b/vendor/symfony/config/ResourceCheckerInterface.php new file mode 100644 index 0000000..0688f51 --- /dev/null +++ b/vendor/symfony/config/ResourceCheckerInterface.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config; + +use Symfony\Component\Config\Resource\ResourceInterface; + +/** + * Interface for ResourceCheckers. + * + * When a ResourceCheckerConfigCache instance is checked for freshness, all its associated + * metadata resources are passed to ResourceCheckers. The ResourceCheckers + * can then inspect the resources and decide whether the cache can be considered + * fresh or not. + * + * @author Matthias Pigulla + * @author Benjamin Klotz + */ +interface ResourceCheckerInterface +{ + /** + * Queries the ResourceChecker whether it can validate a given + * resource or not. + * + * @return bool True if the ResourceChecker can handle this resource type, false if not + */ + public function supports(ResourceInterface $metadata); + + /** + * Validates the resource. + * + * @param int $timestamp The timestamp at which the cache associated with this resource was created + * + * @return bool True if the resource has not changed since the given timestamp, false otherwise + */ + public function isFresh(ResourceInterface $resource, int $timestamp); +} diff --git a/vendor/symfony/config/Util/Exception/InvalidXmlException.php b/vendor/symfony/config/Util/Exception/InvalidXmlException.php new file mode 100644 index 0000000..a335bbd --- /dev/null +++ b/vendor/symfony/config/Util/Exception/InvalidXmlException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Util\Exception; + +/** + * Exception class for when XML parsing with an XSD schema file path or a callable validator produces errors unrelated + * to the actual XML parsing. + * + * @author Ole Rößner + */ +class InvalidXmlException extends XmlParsingException +{ +} diff --git a/vendor/symfony/config/Util/Exception/XmlParsingException.php b/vendor/symfony/config/Util/Exception/XmlParsingException.php new file mode 100644 index 0000000..9bceed6 --- /dev/null +++ b/vendor/symfony/config/Util/Exception/XmlParsingException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Util\Exception; + +/** + * Exception class for when XML cannot be parsed properly. + * + * @author Ole Rößner + */ +class XmlParsingException extends \InvalidArgumentException +{ +} diff --git a/vendor/symfony/config/Util/XmlUtils.php b/vendor/symfony/config/Util/XmlUtils.php new file mode 100644 index 0000000..0ebeec4 --- /dev/null +++ b/vendor/symfony/config/Util/XmlUtils.php @@ -0,0 +1,269 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Util; + +use Symfony\Component\Config\Util\Exception\InvalidXmlException; +use Symfony\Component\Config\Util\Exception\XmlParsingException; + +/** + * XMLUtils is a bunch of utility methods to XML operations. + * + * This class contains static methods only and is not meant to be instantiated. + * + * @author Fabien Potencier + * @author Martin Hasoň + * @author Ole Rößner + */ +class XmlUtils +{ + /** + * This class should not be instantiated. + */ + private function __construct() + { + } + + /** + * Parses an XML string. + * + * @param string $content An XML string + * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation + * + * @return \DOMDocument + * + * @throws XmlParsingException When parsing of XML file returns error + * @throws InvalidXmlException When parsing of XML with schema or callable produces any errors unrelated to the XML parsing itself + * @throws \RuntimeException When DOM extension is missing + */ + public static function parse(string $content, $schemaOrCallable = null) + { + if (!\extension_loaded('dom')) { + throw new \LogicException('Extension DOM is required.'); + } + + $internalErrors = libxml_use_internal_errors(true); + $disableEntities = libxml_disable_entity_loader(true); + libxml_clear_errors(); + + $dom = new \DOMDocument(); + $dom->validateOnParse = true; + if (!$dom->loadXML($content, LIBXML_NONET | (\defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) { + libxml_disable_entity_loader($disableEntities); + + throw new XmlParsingException(implode("\n", static::getXmlErrors($internalErrors))); + } + + $dom->normalizeDocument(); + + libxml_use_internal_errors($internalErrors); + libxml_disable_entity_loader($disableEntities); + + foreach ($dom->childNodes as $child) { + if (XML_DOCUMENT_TYPE_NODE === $child->nodeType) { + throw new XmlParsingException('Document types are not allowed.'); + } + } + + if (null !== $schemaOrCallable) { + $internalErrors = libxml_use_internal_errors(true); + libxml_clear_errors(); + + $e = null; + if (\is_callable($schemaOrCallable)) { + try { + $valid = $schemaOrCallable($dom, $internalErrors); + } catch (\Exception $e) { + $valid = false; + } + } elseif (!\is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) { + $schemaSource = file_get_contents((string) $schemaOrCallable); + $valid = @$dom->schemaValidateSource($schemaSource); + } else { + libxml_use_internal_errors($internalErrors); + + throw new XmlParsingException('The schemaOrCallable argument has to be a valid path to XSD file or callable.'); + } + + if (!$valid) { + $messages = static::getXmlErrors($internalErrors); + if (empty($messages)) { + throw new InvalidXmlException('The XML is not valid.', 0, $e); + } + throw new XmlParsingException(implode("\n", $messages), 0, $e); + } + } + + libxml_clear_errors(); + libxml_use_internal_errors($internalErrors); + + return $dom; + } + + /** + * Loads an XML file. + * + * @param string $file An XML file path + * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation + * + * @return \DOMDocument + * + * @throws \InvalidArgumentException When loading of XML file returns error + * @throws XmlParsingException When XML parsing returns any errors + * @throws \RuntimeException When DOM extension is missing + */ + public static function loadFile(string $file, $schemaOrCallable = null) + { + $content = @file_get_contents($file); + if ('' === trim($content)) { + throw new \InvalidArgumentException(sprintf('File %s does not contain valid XML, it is empty.', $file)); + } + + try { + return static::parse($content, $schemaOrCallable); + } catch (InvalidXmlException $e) { + throw new XmlParsingException(sprintf('The XML file "%s" is not valid.', $file), 0, $e->getPrevious()); + } + } + + /** + * Converts a \DOMElement object to a PHP array. + * + * The following rules applies during the conversion: + * + * * Each tag is converted to a key value or an array + * if there is more than one "value" + * + * * The content of a tag is set under a "value" key (bar) + * if the tag also has some nested tags + * + * * The attributes are converted to keys () + * + * * The nested-tags are converted to keys (bar) + * + * @param \DOMElement $element A \DOMElement instance + * @param bool $checkPrefix Check prefix in an element or an attribute name + * + * @return mixed + */ + public static function convertDomElementToArray(\DOMElement $element, bool $checkPrefix = true) + { + $prefix = (string) $element->prefix; + $empty = true; + $config = []; + foreach ($element->attributes as $name => $node) { + if ($checkPrefix && !\in_array((string) $node->prefix, ['', $prefix], true)) { + continue; + } + $config[$name] = static::phpize($node->value); + $empty = false; + } + + $nodeValue = false; + foreach ($element->childNodes as $node) { + if ($node instanceof \DOMText) { + if ('' !== trim($node->nodeValue)) { + $nodeValue = trim($node->nodeValue); + $empty = false; + } + } elseif ($checkPrefix && $prefix != (string) $node->prefix) { + continue; + } elseif (!$node instanceof \DOMComment) { + $value = static::convertDomElementToArray($node, $checkPrefix); + + $key = $node->localName; + if (isset($config[$key])) { + if (!\is_array($config[$key]) || !\is_int(key($config[$key]))) { + $config[$key] = [$config[$key]]; + } + $config[$key][] = $value; + } else { + $config[$key] = $value; + } + + $empty = false; + } + } + + if (false !== $nodeValue) { + $value = static::phpize($nodeValue); + if (\count($config)) { + $config['value'] = $value; + } else { + $config = $value; + } + } + + return !$empty ? $config : null; + } + + /** + * Converts an xml value to a PHP type. + * + * @param mixed $value + * + * @return mixed + */ + public static function phpize($value) + { + $value = (string) $value; + $lowercaseValue = strtolower($value); + + switch (true) { + case 'null' === $lowercaseValue: + return null; + case ctype_digit($value): + $raw = $value; + $cast = (int) $value; + + return '0' == $value[0] ? octdec($value) : (((string) $raw === (string) $cast) ? $cast : $raw); + case isset($value[1]) && '-' === $value[0] && ctype_digit(substr($value, 1)): + $raw = $value; + $cast = (int) $value; + + return '0' == $value[1] ? octdec($value) : (((string) $raw === (string) $cast) ? $cast : $raw); + case 'true' === $lowercaseValue: + return true; + case 'false' === $lowercaseValue: + return false; + case isset($value[1]) && '0b' == $value[0].$value[1] && preg_match('/^0b[01]*$/', $value): + return bindec($value); + case is_numeric($value): + return '0x' === $value[0].$value[1] ? hexdec($value) : (float) $value; + case preg_match('/^0x[0-9a-f]++$/i', $value): + return hexdec($value); + case preg_match('/^[+-]?[0-9]+(\.[0-9]+)?$/', $value): + return (float) $value; + default: + return $value; + } + } + + protected static function getXmlErrors(bool $internalErrors) + { + $errors = []; + foreach (libxml_get_errors() as $error) { + $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)', + LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', + $error->code, + trim($error->message), + $error->file ?: 'n/a', + $error->line, + $error->column + ); + } + + libxml_clear_errors(); + libxml_use_internal_errors($internalErrors); + + return $errors; + } +} diff --git a/vendor/symfony/config/composer.json b/vendor/symfony/config/composer.json new file mode 100644 index 0000000..cd31eb9 --- /dev/null +++ b/vendor/symfony/config/composer.json @@ -0,0 +1,48 @@ +{ + "name": "symfony/config", + "type": "library", + "description": "Symfony Config Component", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "symfony/filesystem": "^4.4|^5.0", + "symfony/polyfill-ctype": "~1.8" + }, + "require-dev": { + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/yaml": "^4.4|^5.0" + }, + "conflict": { + "symfony/finder": "<4.4" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Config\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/console/.gitattributes b/vendor/symfony/console/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/console/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/console/Application.php b/vendor/symfony/console/Application.php new file mode 100644 index 0000000..38956d1 --- /dev/null +++ b/vendor/symfony/console/Application.php @@ -0,0 +1,1187 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Command\HelpCommand; +use Symfony\Component\Console\Command\ListCommand; +use Symfony\Component\Console\CommandLoader\CommandLoaderInterface; +use Symfony\Component\Console\Event\ConsoleCommandEvent; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Event\ConsoleTerminateEvent; +use Symfony\Component\Console\Exception\CommandNotFoundException; +use Symfony\Component\Console\Exception\ExceptionInterface; +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Exception\NamespaceNotFoundException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\DebugFormatterHelper; +use Symfony\Component\Console\Helper\FormatterHelper; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Helper\ProcessHelper; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputAwareInterface; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\StreamableInputInterface; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\ErrorHandler\ErrorHandler; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\Service\ResetInterface; + +/** + * 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->add(new SimpleCommand()); + * $app->run(); + * + * @author Fabien Potencier + */ +class Application implements ResetInterface +{ + private $commands = []; + private $wantHelps = false; + private $runningCommand; + private $name; + private $version; + private $commandLoader; + private $catchExceptions = true; + private $autoExit = true; + private $definition; + private $helperSet; + private $dispatcher; + private $terminal; + private $defaultCommand; + private $singleCommand = false; + private $initialized; + + public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN') + { + $this->name = $name; + $this->version = $version; + $this->terminal = new Terminal(); + $this->defaultCommand = 'list'; + } + + /** + * @final + */ + public function setDispatcher(EventDispatcherInterface $dispatcher) + { + $this->dispatcher = $dispatcher; + } + + public function setCommandLoader(CommandLoaderInterface $commandLoader) + { + $this->commandLoader = $commandLoader; + } + + /** + * Runs the current application. + * + * @return int 0 if everything went fine, or an error code + * + * @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}. + */ + public function run(InputInterface $input = null, OutputInterface $output = null) + { + putenv('LINES='.$this->terminal->getHeight()); + putenv('COLUMNS='.$this->terminal->getWidth()); + + if (null === $input) { + $input = new ArgvInput(); + } + + if (null === $output) { + $output = new ConsoleOutput(); + } + + $renderException = function (\Throwable $e) use ($output) { + if ($output instanceof ConsoleOutputInterface) { + $this->renderThrowable($e, $output->getErrorOutput()); + } else { + $this->renderThrowable($e, $output); + } + }; + if ($phpHandler = set_exception_handler($renderException)) { + restore_exception_handler(); + if (!\is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) { + $errorHandler = true; + } elseif ($errorHandler = $phpHandler[0]->setExceptionHandler($renderException)) { + $phpHandler[0]->setExceptionHandler($errorHandler); + } + } + + $this->configureIO($input, $output); + + try { + $exitCode = $this->doRun($input, $output); + } catch (\Exception $e) { + if (!$this->catchExceptions) { + throw $e; + } + + $renderException($e); + + $exitCode = $e->getCode(); + if (is_numeric($exitCode)) { + $exitCode = (int) $exitCode; + if (0 === $exitCode) { + $exitCode = 1; + } + } else { + $exitCode = 1; + } + } finally { + // if the exception handler changed, keep it + // otherwise, unregister $renderException + if (!$phpHandler) { + if (set_exception_handler($renderException) === $renderException) { + restore_exception_handler(); + } + restore_exception_handler(); + } elseif (!$errorHandler) { + $finalHandler = $phpHandler[0]->setExceptionHandler(null); + if ($finalHandler !== $renderException) { + $phpHandler[0]->setExceptionHandler($finalHandler); + } + } + } + + if ($this->autoExit) { + if ($exitCode > 255) { + $exitCode = 255; + } + + exit($exitCode); + } + + return $exitCode; + } + + /** + * Runs the current application. + * + * @return int 0 if everything went fine, or an error code + */ + public function doRun(InputInterface $input, OutputInterface $output) + { + if (true === $input->hasParameterOption(['--version', '-V'], true)) { + $output->writeln($this->getLongVersion()); + + return 0; + } + + try { + // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument. + $input->bind($this->getDefinition()); + } catch (ExceptionInterface $e) { + // Errors must be ignored, full binding/validation happens later when the command is known. + } + + $name = $this->getCommandName($input); + if (true === $input->hasParameterOption(['--help', '-h'], true)) { + if (!$name) { + $name = 'help'; + $input = new ArrayInput(['command_name' => $this->defaultCommand]); + } else { + $this->wantHelps = true; + } + } + + if (!$name) { + $name = $this->defaultCommand; + $definition = $this->getDefinition(); + $definition->setArguments(array_merge( + $definition->getArguments(), + [ + 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name), + ] + )); + } + + try { + $this->runningCommand = null; + // the command name MUST be the first element of the input + $command = $this->find($name); + } catch (\Throwable $e) { + if (!($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException) || 1 !== \count($alternatives = $e->getAlternatives()) || !$input->isInteractive()) { + if (null !== $this->dispatcher) { + $event = new ConsoleErrorEvent($input, $output, $e); + $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); + + if (0 === $event->getExitCode()) { + return 0; + } + + $e = $event->getError(); + } + + throw $e; + } + + $alternative = $alternatives[0]; + + $style = new SymfonyStyle($input, $output); + $style->block(sprintf("\nCommand \"%s\" is not defined.\n", $name), null, 'error'); + if (!$style->confirm(sprintf('Do you want to run "%s" instead? ', $alternative), false)) { + if (null !== $this->dispatcher) { + $event = new ConsoleErrorEvent($input, $output, $e); + $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); + + return $event->getExitCode(); + } + + return 1; + } + + $command = $this->find($alternative); + } + + $this->runningCommand = $command; + $exitCode = $this->doRunCommand($command, $input, $output); + $this->runningCommand = null; + + return $exitCode; + } + + /** + * {@inheritdoc} + */ + public function reset() + { + } + + 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() + { + if (!$this->helperSet) { + $this->helperSet = $this->getDefaultHelperSet(); + } + + return $this->helperSet; + } + + public function setDefinition(InputDefinition $definition) + { + $this->definition = $definition; + } + + /** + * Gets the InputDefinition related to this Application. + * + * @return InputDefinition The InputDefinition instance + */ + public function getDefinition() + { + if (!$this->definition) { + $this->definition = $this->getDefaultInputDefinition(); + } + + if ($this->singleCommand) { + $inputDefinition = $this->definition; + $inputDefinition->setArguments(); + + return $inputDefinition; + } + + return $this->definition; + } + + /** + * Gets the help message. + * + * @return string A help message + */ + public function getHelp() + { + return $this->getLongVersion(); + } + + /** + * Gets whether to catch exceptions or not during commands execution. + * + * @return bool Whether to catch exceptions or not during commands execution + */ + public function areExceptionsCaught() + { + return $this->catchExceptions; + } + + /** + * Sets whether to catch exceptions or not during commands execution. + */ + public function setCatchExceptions(bool $boolean) + { + $this->catchExceptions = $boolean; + } + + /** + * Gets whether to automatically exit after a command execution or not. + * + * @return bool Whether to automatically exit after a command execution or not + */ + public function isAutoExitEnabled() + { + return $this->autoExit; + } + + /** + * Sets whether to automatically exit after a command execution or not. + */ + public function setAutoExit(bool $boolean) + { + $this->autoExit = $boolean; + } + + /** + * Gets the name of the application. + * + * @return string The application name + */ + public function getName() + { + return $this->name; + } + + /** + * Sets the application name. + **/ + public function setName(string $name) + { + $this->name = $name; + } + + /** + * Gets the application version. + * + * @return string The application version + */ + public function getVersion() + { + return $this->version; + } + + /** + * Sets the application version. + */ + public function setVersion(string $version) + { + $this->version = $version; + } + + /** + * Returns the long version of the application. + * + * @return string The long application version + */ + public function getLongVersion() + { + if ('UNKNOWN' !== $this->getName()) { + if ('UNKNOWN' !== $this->getVersion()) { + return sprintf('%s %s', $this->getName(), $this->getVersion()); + } + + return $this->getName(); + } + + return 'Console Tool'; + } + + /** + * Registers a new command. + * + * @return Command The newly created command + */ + public function register(string $name) + { + return $this->add(new Command($name)); + } + + /** + * Adds an array of command objects. + * + * If a Command is not enabled it will not be added. + * + * @param Command[] $commands An array of commands + */ + public function addCommands(array $commands) + { + foreach ($commands as $command) { + $this->add($command); + } + } + + /** + * Adds a command object. + * + * If a command with the same name already exists, it will be overridden. + * If the command is not enabled it will not be added. + * + * @return Command|null The registered command if enabled or null + */ + public function add(Command $command) + { + $this->init(); + + $command->setApplication($this); + + if (!$command->isEnabled()) { + $command->setApplication(null); + + return null; + } + + // Will throw if the command is not correctly initialized. + $command->getDefinition(); + + if (!$command->getName()) { + throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', \get_class($command))); + } + + $this->commands[$command->getName()] = $command; + + foreach ($command->getAliases() as $alias) { + $this->commands[$alias] = $command; + } + + return $command; + } + + /** + * Returns a registered command by name or alias. + * + * @return Command A Command object + * + * @throws CommandNotFoundException When given command name does not exist + */ + public function get(string $name) + { + $this->init(); + + if (!$this->has($name)) { + throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); + } + + $command = $this->commands[$name]; + + if ($this->wantHelps) { + $this->wantHelps = false; + + $helpCommand = $this->get('help'); + $helpCommand->setCommand($command); + + return $helpCommand; + } + + return $command; + } + + /** + * Returns true if the command exists, false otherwise. + * + * @return bool true if the command exists, false otherwise + */ + public function has(string $name) + { + $this->init(); + + return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name) && $this->add($this->commandLoader->get($name))); + } + + /** + * Returns an array of all unique namespaces used by currently registered commands. + * + * It does not return the global namespace which always exists. + * + * @return string[] An array of namespaces + */ + public function getNamespaces() + { + $namespaces = []; + foreach ($this->all() as $command) { + if ($command->isHidden()) { + continue; + } + + $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName())); + + foreach ($command->getAliases() as $alias) { + $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias)); + } + } + + return array_values(array_unique(array_filter($namespaces))); + } + + /** + * Finds a registered namespace by a name or an abbreviation. + * + * @return string A registered namespace + * + * @throws NamespaceNotFoundException When namespace is incorrect or ambiguous + */ + public function findNamespace(string $namespace) + { + $allNamespaces = $this->getNamespaces(); + $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace); + $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces); + + if (empty($namespaces)) { + $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); + + if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) { + if (1 == \count($alternatives)) { + $message .= "\n\nDid you mean this?\n "; + } else { + $message .= "\n\nDid you mean one of these?\n "; + } + + $message .= implode("\n ", $alternatives); + } + + throw new NamespaceNotFoundException($message, $alternatives); + } + + $exact = \in_array($namespace, $namespaces, true); + if (\count($namespaces) > 1 && !$exact) { + throw new NamespaceNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); + } + + return $exact ? $namespace : reset($namespaces); + } + + /** + * Finds a command by name or alias. + * + * Contrary to get, this command tries to find the best + * match if you give it an abbreviation of a name or alias. + * + * @return Command A Command instance + * + * @throws CommandNotFoundException When command name is incorrect or ambiguous + */ + public function find(string $name) + { + $this->init(); + + $aliases = []; + + foreach ($this->commands as $command) { + foreach ($command->getAliases() as $alias) { + if (!$this->has($alias)) { + $this->commands[$alias] = $command; + } + } + } + + if ($this->has($name)) { + return $this->get($name); + } + + $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands); + $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); + $commands = preg_grep('{^'.$expr.'}', $allCommands); + + if (empty($commands)) { + $commands = preg_grep('{^'.$expr.'}i', $allCommands); + } + + // if no commands matched or we just matched namespaces + if (empty($commands) || \count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) { + if (false !== $pos = strrpos($name, ':')) { + // check if a namespace exists and contains commands + $this->findNamespace(substr($name, 0, $pos)); + } + + $message = sprintf('Command "%s" is not defined.', $name); + + if ($alternatives = $this->findAlternatives($name, $allCommands)) { + // remove hidden commands + $alternatives = array_filter($alternatives, function ($name) { + return !$this->get($name)->isHidden(); + }); + + if (1 == \count($alternatives)) { + $message .= "\n\nDid you mean this?\n "; + } else { + $message .= "\n\nDid you mean one of these?\n "; + } + $message .= implode("\n ", $alternatives); + } + + throw new CommandNotFoundException($message, array_values($alternatives)); + } + + // filter out aliases for commands which are already on the list + if (\count($commands) > 1) { + $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands; + $commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) { + $commandName = $commandList[$nameOrAlias] instanceof Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias; + $aliases[$nameOrAlias] = $commandName; + + return $commandName === $nameOrAlias || !\in_array($commandName, $commands); + })); + } + + if (\count($commands) > 1) { + $usableWidth = $this->terminal->getWidth() - 10; + $abbrevs = array_values($commands); + $maxLen = 0; + foreach ($abbrevs as $abbrev) { + $maxLen = max(Helper::strlen($abbrev), $maxLen); + } + $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen, &$commands) { + if (!$commandList[$cmd] instanceof Command) { + $commandList[$cmd] = $this->commandLoader->get($cmd); + } + + if ($commandList[$cmd]->isHidden()) { + unset($commands[array_search($cmd, $commands)]); + + return false; + } + + $abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription(); + + return Helper::strlen($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev; + }, array_values($commands)); + + if (\count($commands) > 1) { + $suggestions = $this->getAbbreviationSuggestions(array_filter($abbrevs)); + + throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $name, $suggestions), array_values($commands)); + } + } + + $command = $this->get(reset($commands)); + + if ($command->isHidden()) { + throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); + } + + return $command; + } + + /** + * Gets the commands (registered in the given namespace if provided). + * + * The array keys are the full names and the values the command instances. + * + * @return Command[] An array of Command instances + */ + public function all(string $namespace = null) + { + $this->init(); + + if (null === $namespace) { + if (!$this->commandLoader) { + return $this->commands; + } + + $commands = $this->commands; + foreach ($this->commandLoader->getNames() as $name) { + if (!isset($commands[$name]) && $this->has($name)) { + $commands[$name] = $this->get($name); + } + } + + return $commands; + } + + $commands = []; + foreach ($this->commands as $name => $command) { + if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { + $commands[$name] = $command; + } + } + + if ($this->commandLoader) { + foreach ($this->commandLoader->getNames() as $name) { + if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1) && $this->has($name)) { + $commands[$name] = $this->get($name); + } + } + } + + return $commands; + } + + /** + * Returns an array of possible abbreviations given a set of names. + * + * @return string[][] An array of abbreviations + */ + public static function getAbbreviations(array $names) + { + $abbrevs = []; + foreach ($names as $name) { + for ($len = \strlen($name); $len > 0; --$len) { + $abbrev = substr($name, 0, $len); + $abbrevs[$abbrev][] = $name; + } + } + + return $abbrevs; + } + + public function renderThrowable(\Throwable $e, OutputInterface $output): void + { + $output->writeln('', OutputInterface::VERBOSITY_QUIET); + + $this->doRenderThrowable($e, $output); + + if (null !== $this->runningCommand) { + $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET); + $output->writeln('', OutputInterface::VERBOSITY_QUIET); + } + } + + protected function doRenderThrowable(\Throwable $e, OutputInterface $output): void + { + do { + $message = trim($e->getMessage()); + if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $class = \get_class($e); + $class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; + $title = sprintf(' [%s%s] ', $class, 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : ''); + $len = Helper::strlen($title); + } else { + $len = 0; + } + + if (false !== strpos($message, "class@anonymous\0")) { + $message = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:)[0-9a-fA-F]++/', function ($m) { + return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0]; + }, $message); + } + + $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX; + $lines = []; + foreach ('' !== $message ? preg_split('/\r?\n/', $message) : [] as $line) { + foreach ($this->splitStringByWidth($line, $width - 4) as $line) { + // pre-format lines to get the right string length + $lineLength = Helper::strlen($line) + 4; + $lines[] = [$line, $lineLength]; + + $len = max($lineLength, $len); + } + } + + $messages = []; + if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $messages[] = sprintf('%s', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); + } + $messages[] = $emptyLine = sprintf('%s', str_repeat(' ', $len)); + if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $messages[] = sprintf('%s%s', $title, str_repeat(' ', max(0, $len - Helper::strlen($title)))); + } + foreach ($lines as $line) { + $messages[] = sprintf(' %s %s', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1])); + } + $messages[] = $emptyLine; + $messages[] = ''; + + $output->writeln($messages, OutputInterface::VERBOSITY_QUIET); + + if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $output->writeln('Exception trace:', OutputInterface::VERBOSITY_QUIET); + + // exception related properties + $trace = $e->getTrace(); + + array_unshift($trace, [ + 'function' => '', + 'file' => $e->getFile() ?: 'n/a', + 'line' => $e->getLine() ?: 'n/a', + 'args' => [], + ]); + + 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 = isset($trace[$i]['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 at %s:%s', $class, $function ? $type.$function.'()' : '', $file, $line), OutputInterface::VERBOSITY_QUIET); + } + + $output->writeln('', OutputInterface::VERBOSITY_QUIET); + } + } while ($e = $e->getPrevious()); + } + + /** + * Configures the input and output instances based on the user arguments and options. + */ + protected function configureIO(InputInterface $input, OutputInterface $output) + { + if (true === $input->hasParameterOption(['--ansi'], true)) { + $output->setDecorated(true); + } elseif (true === $input->hasParameterOption(['--no-ansi'], true)) { + $output->setDecorated(false); + } + + if (true === $input->hasParameterOption(['--no-interaction', '-n'], true)) { + $input->setInteractive(false); + } else { + $inputStream = null; + + if ($input instanceof StreamableInputInterface) { + $inputStream = $input->getStream(); + } + + $inputStream = !$inputStream && \defined('STDIN') ? STDIN : $inputStream; + + if ((!$inputStream || !stream_isatty($inputStream)) && false === getenv('SHELL_INTERACTIVE')) { + $input->setInteractive(false); + } + } + + switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) { + case -1: $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); break; + case 1: $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); break; + case 2: $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); break; + case 3: $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); break; + default: $shellVerbosity = 0; break; + } + + if (true === $input->hasParameterOption(['--quiet', '-q'], true)) { + $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); + $shellVerbosity = -1; + } else { + if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) { + $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); + $shellVerbosity = 3; + } elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || 2 === $input->getParameterOption('--verbose', false, true)) { + $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); + $shellVerbosity = 2; + } elseif ($input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true)) { + $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); + $shellVerbosity = 1; + } + } + + if (-1 === $shellVerbosity) { + $input->setInteractive(false); + } + + putenv('SHELL_VERBOSITY='.$shellVerbosity); + $_ENV['SHELL_VERBOSITY'] = $shellVerbosity; + $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity; + } + + /** + * Runs the current command. + * + * If an event dispatcher has been attached to the application, + * events are also dispatched during the life-cycle of the command. + * + * @return int 0 if everything went fine, or an error code + */ + protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) + { + foreach ($command->getHelperSet() as $helper) { + if ($helper instanceof InputAwareInterface) { + $helper->setInput($input); + } + } + + if (null === $this->dispatcher) { + return $command->run($input, $output); + } + + // bind before the console.command event, so the listeners have access to input options/arguments + try { + $command->mergeApplicationDefinition(); + $input->bind($command->getDefinition()); + } catch (ExceptionInterface $e) { + // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition + } + + $event = new ConsoleCommandEvent($command, $input, $output); + $e = null; + + try { + $this->dispatcher->dispatch($event, ConsoleEvents::COMMAND); + + if ($event->commandShouldRun()) { + $exitCode = $command->run($input, $output); + } else { + $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED; + } + } catch (\Throwable $e) { + $event = new ConsoleErrorEvent($input, $output, $e, $command); + $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); + $e = $event->getError(); + + if (0 === $exitCode = $event->getExitCode()) { + $e = null; + } + } + + $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); + $this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE); + + if (null !== $e) { + throw $e; + } + + return $event->getExitCode(); + } + + /** + * Gets the name of the command based on input. + * + * @return string|null + */ + protected function getCommandName(InputInterface $input) + { + return $this->singleCommand ? $this->defaultCommand : $input->getFirstArgument(); + } + + /** + * Gets the default input definition. + * + * @return InputDefinition An InputDefinition instance + */ + protected function getDefaultInputDefinition() + { + return new InputDefinition([ + new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), + + new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'), + new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'), + new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), + new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'), + new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'), + new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'), + new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'), + ]); + } + + /** + * Gets the default commands that should always be available. + * + * @return Command[] An array of default Command instances + */ + protected function getDefaultCommands() + { + return [new HelpCommand(), new ListCommand()]; + } + + /** + * Gets the default helper set with the helpers that should always be available. + * + * @return HelperSet A HelperSet instance + */ + protected function getDefaultHelperSet() + { + return new HelperSet([ + new FormatterHelper(), + new DebugFormatterHelper(), + new ProcessHelper(), + new QuestionHelper(), + ]); + } + + /** + * Returns abbreviated suggestions in string format. + */ + private function getAbbreviationSuggestions(array $abbrevs): string + { + return ' '.implode("\n ", $abbrevs); + } + + /** + * Returns the namespace part of the command name. + * + * This method is not part of public API and should not be used directly. + * + * @return string The namespace of the command + */ + public function extractNamespace(string $name, int $limit = null) + { + $parts = explode(':', $name, -1); + + return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit)); + } + + /** + * Finds alternative of $name among $collection, + * if nothing is found in $collection, try in $abbrevs. + * + * @return string[] A sorted array of similar string + */ + private function findAlternatives(string $name, iterable $collection): array + { + $threshold = 1e3; + $alternatives = []; + + $collectionParts = []; + foreach ($collection as $item) { + $collectionParts[$item] = explode(':', $item); + } + + foreach (explode(':', $name) as $i => $subname) { + foreach ($collectionParts as $collectionName => $parts) { + $exists = isset($alternatives[$collectionName]); + if (!isset($parts[$i]) && $exists) { + $alternatives[$collectionName] += $threshold; + continue; + } elseif (!isset($parts[$i])) { + continue; + } + + $lev = levenshtein($subname, $parts[$i]); + if ($lev <= \strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) { + $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev; + } elseif ($exists) { + $alternatives[$collectionName] += $threshold; + } + } + } + + foreach ($collection as $item) { + $lev = levenshtein($name, $item); + if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) { + $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; + } + } + + $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; }); + ksort($alternatives, SORT_NATURAL | SORT_FLAG_CASE); + + return array_keys($alternatives); + } + + /** + * Sets the default Command name. + * + * @return self + */ + public function setDefaultCommand(string $commandName, bool $isSingleCommand = false) + { + $this->defaultCommand = $commandName; + + if ($isSingleCommand) { + // Ensure the command exist + $this->find($commandName); + + $this->singleCommand = true; + } + + return $this; + } + + /** + * @internal + */ + public function isSingleCommand(): bool + { + return $this->singleCommand; + } + + private function splitStringByWidth(string $string, int $width): array + { + // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly. + // additionally, array_slice() is not enough as some character has doubled width. + // we need a function to split string not by character count but by string width + if (false === $encoding = mb_detect_encoding($string, null, true)) { + return str_split($string, $width); + } + + $utf8String = mb_convert_encoding($string, 'utf8', $encoding); + $lines = []; + $line = ''; + + $offset = 0; + while (preg_match('/.{1,10000}/u', $utf8String, $m, 0, $offset)) { + $offset += \strlen($m[0]); + + foreach (preg_split('//u', $m[0]) as $char) { + // test if $char could be appended to current line + if (mb_strwidth($line.$char, 'utf8') <= $width) { + $line .= $char; + continue; + } + // if not, push current line to array and make new line + $lines[] = str_pad($line, $width); + $line = $char; + } + } + + $lines[] = \count($lines) ? str_pad($line, $width) : $line; + + mb_convert_variables($encoding, 'utf8', $lines); + + return $lines; + } + + /** + * Returns all namespaces of the command name. + * + * @return string[] The namespaces of the command + */ + private function extractAllNamespaces(string $name): array + { + // -1 as third argument is needed to skip the command short name when exploding + $parts = explode(':', $name, -1); + $namespaces = []; + + foreach ($parts as $part) { + if (\count($namespaces)) { + $namespaces[] = end($namespaces).':'.$part; + } else { + $namespaces[] = $part; + } + } + + return $namespaces; + } + + private function init() + { + if ($this->initialized) { + return; + } + $this->initialized = true; + + foreach ($this->getDefaultCommands() as $command) { + $this->add($command); + } + } +} diff --git a/vendor/symfony/console/CHANGELOG.md b/vendor/symfony/console/CHANGELOG.md new file mode 100644 index 0000000..3273efb --- /dev/null +++ b/vendor/symfony/console/CHANGELOG.md @@ -0,0 +1,178 @@ +CHANGELOG +========= + +5.0.0 +----- + + * removed support for finding hidden commands using an abbreviation, use the full name instead + * removed `TableStyle::setCrossingChar()` method in favor of `TableStyle::setDefaultCrossingChar()` + * removed `TableStyle::setHorizontalBorderChar()` method in favor of `TableStyle::setDefaultCrossingChars()` + * removed `TableStyle::getHorizontalBorderChar()` method in favor of `TableStyle::getBorderChars()` + * removed `TableStyle::setVerticalBorderChar()` method in favor of `TableStyle::setVerticalBorderChars()` + * removed `TableStyle::getVerticalBorderChar()` method in favor of `TableStyle::getBorderChars()` + * removed support for returning `null` from `Command::execute()`, return `0` instead + * `ProcessHelper::run()` accepts only `array|Symfony\Component\Process\Process` for its `command` argument + * `Application::setDispatcher` accepts only `Symfony\Contracts\EventDispatcher\EventDispatcherInterface` + for its `dispatcher` argument + * renamed `Application::renderException()` and `Application::doRenderException()` + to `renderThrowable()` and `doRenderThrowable()` respectively. + +4.4.0 +----- + + * deprecated finding hidden commands using an abbreviation, use the full name instead + * added `Question::setTrimmable` default to true to allow the answer to be trimmed + * added method `minSecondsBetweenRedraws()` and `maxSecondsBetweenRedraws()` on `ProgressBar` + * `Application` implements `ResetInterface` + * marked all dispatched event classes as `@final` + * added support for displaying table horizontally + * deprecated returning `null` from `Command::execute()`, return `0` instead + * Deprecated the `Application::renderException()` and `Application::doRenderException()` methods, + use `renderThrowable()` and `doRenderThrowable()` instead. + * added support for the `NO_COLOR` env var (https://no-color.org/) + +4.3.0 +----- + + * added support for hyperlinks + * added `ProgressBar::iterate()` method that simplify updating the progress bar when iterating + * added `Question::setAutocompleterCallback()` to provide a callback function + that dynamically generates suggestions as the user types + +4.2.0 +----- + + * allowed passing commands as `[$process, 'ENV_VAR' => 'value']` to + `ProcessHelper::run()` to pass environment variables + * deprecated passing a command as a string to `ProcessHelper::run()`, + pass it the command as an array of its arguments instead + * made the `ProcessHelper` class final + * added `WrappableOutputFormatterInterface::formatAndWrap()` (implemented in `OutputFormatter`) + * added `capture_stderr_separately` option to `CommandTester::execute()` + +4.1.0 +----- + + * added option to run suggested command if command is not found and only 1 alternative is available + * added option to modify console output and print multiple modifiable sections + * added support for iterable messages in output `write` and `writeln` methods + +4.0.0 +----- + + * `OutputFormatter` throws an exception when unknown options are used + * removed `QuestionHelper::setInputStream()/getInputStream()` + * removed `Application::getTerminalWidth()/getTerminalHeight()` and + `Application::setTerminalDimensions()/getTerminalDimensions()` +* removed `ConsoleExceptionEvent` +* removed `ConsoleEvents::EXCEPTION` + +3.4.0 +----- + + * added `SHELL_VERBOSITY` env var to control verbosity + * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11 + `ContainerCommandLoader` for commands lazy-loading + * added a case-insensitive command name matching fallback + * added static `Command::$defaultName/getDefaultName()`, allowing for + commands to be registered at compile time in the application command loader. + Setting the `$defaultName` property avoids the need for filling the `command` + attribute on the `console.command` tag when using `AddConsoleCommandPass`. + +3.3.0 +----- + +* added `ExceptionListener` +* added `AddConsoleCommandPass` (originally in FrameworkBundle) +* [BC BREAK] `Input::getOption()` no longer returns the default value for options + with value optional explicitly passed empty +* added console.error event to catch exceptions thrown by other listeners +* deprecated console.exception event in favor of console.error +* added ability to handle `CommandNotFoundException` through the + `console.error` event +* deprecated default validation in `SymfonyQuestionHelper::ask` + +3.2.0 +------ + +* added `setInputs()` method to CommandTester for ease testing of commands expecting inputs +* added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface) +* added StreamableInputInterface +* added LockableTrait + +3.1.0 +----- + + * added truncate method to FormatterHelper + * added setColumnWidth(s) method to Table + +2.8.3 +----- + + * remove readline support from the question helper as it caused issues + +2.8.0 +----- + + * use readline for user input in the question helper when available to allow + the use of arrow keys + +2.6.0 +----- + + * added a Process helper + * added a DebugFormatter helper + +2.5.0 +----- + + * deprecated the dialog helper (use the question helper instead) + * deprecated TableHelper in favor of Table + * deprecated ProgressHelper in favor of ProgressBar + * added ConsoleLogger + * added a question helper + * added a way to set the process name of a command + * added a way to set a default command instead of `ListCommand` + +2.4.0 +----- + + * added a way to force terminal dimensions + * added a convenient method to detect verbosity level + * [BC BREAK] made descriptors use output instead of returning a string + +2.3.0 +----- + + * added multiselect support to the select dialog helper + * added Table Helper for tabular data rendering + * added support for events in `Application` + * added a way to normalize EOLs in `ApplicationTester::getDisplay()` and `CommandTester::getDisplay()` + * added a way to set the progress bar progress via the `setCurrent` method + * added support for multiple InputOption shortcuts, written as `'-a|-b|-c'` + * added two additional verbosity levels, VERBOSITY_VERY_VERBOSE and VERBOSITY_DEBUG + +2.2.0 +----- + + * added support for colorization on Windows via ConEmu + * add a method to Dialog Helper to ask for a question and hide the response + * added support for interactive selections in console (DialogHelper::select()) + * added support for autocompletion as you type in Dialog Helper + +2.1.0 +----- + + * added ConsoleOutputInterface + * added the possibility to disable a command (Command::isEnabled()) + * added suggestions when a command does not exist + * added a --raw option to the list command + * added support for STDERR in the console output class (errors are now sent + to STDERR) + * made the defaults (helper set, commands, input definition) in Application + more easily customizable + * added support for the shell even if readline is not available + * added support for process isolation in Symfony shell via + `--process-isolation` switch + * added support for `--`, which disables options parsing after that point + (tokens will be parsed as arguments) diff --git a/vendor/symfony/console/Command/Command.php b/vendor/symfony/console/Command/Command.php new file mode 100644 index 0000000..b7bf16c --- /dev/null +++ b/vendor/symfony/console/Command/Command.php @@ -0,0 +1,642 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Exception\ExceptionInterface; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Base class for all commands. + * + * @author Fabien Potencier + */ +class Command +{ + /** + * @var string|null The default command name + */ + protected static $defaultName; + + private $application; + private $name; + private $processTitle; + private $aliases = []; + private $definition; + private $hidden = false; + private $help = ''; + private $description = ''; + private $ignoreValidationErrors = false; + private $applicationDefinitionMerged = false; + private $applicationDefinitionMergedWithArgs = false; + private $code; + private $synopsis = []; + private $usages = []; + private $helperSet; + + /** + * @return string|null The default command name or null when no default name is set + */ + public static function getDefaultName() + { + $class = \get_called_class(); + $r = new \ReflectionProperty($class, 'defaultName'); + + return $class === $r->class ? static::$defaultName : null; + } + + /** + * @param string|null $name The name of the command; passing null means it must be set in configure() + * + * @throws LogicException When the command name is empty + */ + public function __construct(string $name = null) + { + $this->definition = new InputDefinition(); + + if (null !== $name || null !== $name = static::getDefaultName()) { + $this->setName($name); + } + + $this->configure(); + } + + /** + * Ignores validation errors. + * + * This is mainly useful for the help command. + */ + public function ignoreValidationErrors() + { + $this->ignoreValidationErrors = true; + } + + public function setApplication(Application $application = null) + { + $this->application = $application; + if ($application) { + $this->setHelperSet($application->getHelperSet()); + } else { + $this->helperSet = null; + } + } + + public function setHelperSet(HelperSet $helperSet) + { + $this->helperSet = $helperSet; + } + + /** + * Gets the helper set. + * + * @return HelperSet|null A HelperSet instance + */ + public function getHelperSet() + { + return $this->helperSet; + } + + /** + * Gets the application instance for this command. + * + * @return Application|null An Application instance + */ + public function getApplication() + { + return $this->application; + } + + /** + * Checks whether the command is enabled or not in the current environment. + * + * Override this to check for x or y and return false if the command can not + * run properly under the current conditions. + * + * @return bool + */ + public function isEnabled() + { + return true; + } + + /** + * Configures the current command. + */ + protected function configure() + { + } + + /** + * Executes the current command. + * + * This method is not abstract because you can use this class + * as a concrete class. In this case, instead of defining the + * execute() method, you set the code to execute by passing + * a Closure to the setCode() method. + * + * @return int 0 if everything went fine, or an exit code + * + * @throws LogicException When this abstract method is not implemented + * + * @see setCode() + */ + 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. + * + * This method is executed before the InputDefinition is validated. + * This means that this is the only place where the command can + * interactively ask for values of missing required arguments. + */ + protected function interact(InputInterface $input, OutputInterface $output) + { + } + + /** + * Initializes the command after the input has been bound and before the input + * is 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. + * + * @see InputInterface::bind() + * @see InputInterface::validate() + */ + protected function initialize(InputInterface $input, OutputInterface $output) + { + } + + /** + * Runs the command. + * + * The code to execute is either defined directly with the + * setCode() method or by overriding the execute() method + * in a sub-class. + * + * @return int The command exit code + * + * @throws \Exception When binding input fails. Bypass this by calling {@link ignoreValidationErrors()}. + * + * @see setCode() + * @see execute() + */ + public function run(InputInterface $input, OutputInterface $output) + { + // force the creation of the synopsis before the merge with the app definition + $this->getSynopsis(true); + $this->getSynopsis(false); + + // add the application arguments and options + $this->mergeApplicationDefinition(); + + // bind the input against the command specific arguments/options + try { + $input->bind($this->definition); + } catch (ExceptionInterface $e) { + if (!$this->ignoreValidationErrors) { + throw $e; + } + } + + $this->initialize($input, $output); + + if (null !== $this->processTitle) { + if (\function_exists('cli_set_process_title')) { + if (!@cli_set_process_title($this->processTitle)) { + if ('Darwin' === PHP_OS) { + $output->writeln('Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.', OutputInterface::VERBOSITY_VERY_VERBOSE); + } else { + cli_set_process_title($this->processTitle); + } + } + } elseif (\function_exists('setproctitle')) { + setproctitle($this->processTitle); + } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) { + $output->writeln('Install the proctitle PECL to be able to change the process title.'); + } + } + + if ($input->isInteractive()) { + $this->interact($input, $output); + } + + // The command name argument is often omitted when a command is executed directly with its run() method. + // It would fail the validation if we didn't make sure the command argument is present, + // since it's required by the application. + if ($input->hasArgument('command') && null === $input->getArgument('command')) { + $input->setArgument('command', $this->getName()); + } + + $input->validate(); + + if ($this->code) { + $statusCode = ($this->code)($input, $output); + } else { + $statusCode = $this->execute($input, $output); + + if (!\is_int($statusCode)) { + throw new \TypeError(sprintf('Return value of "%s::execute()" must be of the type int, %s returned.', \get_class($this), \gettype($statusCode))); + } + } + + return is_numeric($statusCode) ? (int) $statusCode : 0; + } + + /** + * Sets the code to execute when running this command. + * + * If this method is used, it overrides the code defined + * in the execute() method. + * + * @param callable $code A callable(InputInterface $input, OutputInterface $output) + * + * @return $this + * + * @throws InvalidArgumentException + * + * @see execute() + */ + public function setCode(callable $code) + { + if ($code instanceof \Closure) { + $r = new \ReflectionFunction($code); + if (null === $r->getClosureThis()) { + $code = \Closure::bind($code, $this); + } + } + + $this->code = $code; + + return $this; + } + + /** + * Merges the application definition with the command definition. + * + * This method is not part of public API and should not be used directly. + * + * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments + */ + public function mergeApplicationDefinition(bool $mergeArgs = true) + { + if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) { + return; + } + + $this->definition->addOptions($this->application->getDefinition()->getOptions()); + + $this->applicationDefinitionMerged = true; + + if ($mergeArgs) { + $currentArguments = $this->definition->getArguments(); + $this->definition->setArguments($this->application->getDefinition()->getArguments()); + $this->definition->addArguments($currentArguments); + + $this->applicationDefinitionMergedWithArgs = true; + } + } + + /** + * Sets an array of argument and option instances. + * + * @param array|InputDefinition $definition An array of argument and option instances or a definition instance + * + * @return $this + */ + 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() + { + if (null === $this->definition) { + throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', \get_class($this))); + } + + return $this->definition; + } + + /** + * Gets the InputDefinition to be used to create representations of this Command. + * + * Can be overridden to provide the original command representation when it would otherwise + * be changed by merging with the application InputDefinition. + * + * This method is not part of public API and should not be used directly. + * + * @return InputDefinition An InputDefinition instance + */ + public function getNativeDefinition() + { + return $this->getDefinition(); + } + + /** + * Adds an argument. + * + * @param int|null $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL + * @param string|string[]|null $default The default value (for InputArgument::OPTIONAL mode only) + * + * @throws InvalidArgumentException When argument mode is not valid + * + * @return $this + */ + public function addArgument(string $name, int $mode = null, string $description = '', $default = null) + { + $this->definition->addArgument(new InputArgument($name, $mode, $description, $default)); + + return $this; + } + + /** + * Adds an option. + * + * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts + * @param int|null $mode The option mode: One of the InputOption::VALUE_* constants + * @param string|string[]|int|bool|null $default The default value (must be null for InputOption::VALUE_NONE) + * + * @throws InvalidArgumentException If option mode is invalid or incompatible + * + * @return $this + */ + public function addOption(string $name, $shortcut = null, int $mode = null, string $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'); + * + * @return $this + * + * @throws InvalidArgumentException When the name is invalid + */ + public function setName(string $name) + { + $this->validateName($name); + + $this->name = $name; + + return $this; + } + + /** + * Sets the process title of the command. + * + * This feature should be used only when creating a long process command, + * like a daemon. + * + * PHP 5.5+ or the proctitle PECL library is required + * + * @return $this + */ + public function setProcessTitle(string $title) + { + $this->processTitle = $title; + + return $this; + } + + /** + * Returns the command name. + * + * @return string|null + */ + public function getName() + { + return $this->name; + } + + /** + * @param bool $hidden Whether or not the command should be hidden from the list of commands + * + * @return Command The current instance + */ + public function setHidden(bool $hidden) + { + $this->hidden = $hidden; + + return $this; + } + + /** + * @return bool whether the command should be publicly shown or not + */ + public function isHidden() + { + return $this->hidden; + } + + /** + * Sets the description for the command. + * + * @return $this + */ + public function setDescription(string $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. + * + * @return $this + */ + public function setHelp(string $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->name; + $isSingleCommand = $this->application && $this->application->isSingleCommand(); + + $placeholders = [ + '%command.name%', + '%command.full_name%', + ]; + $replacements = [ + $name, + $isSingleCommand ? $_SERVER['PHP_SELF'] : $_SERVER['PHP_SELF'].' '.$name, + ]; + + return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription()); + } + + /** + * Sets the aliases for the command. + * + * @param string[] $aliases An array of aliases for the command + * + * @return $this + * + * @throws InvalidArgumentException When an alias is invalid + */ + public function setAliases(iterable $aliases) + { + foreach ($aliases as $alias) { + $this->validateName($alias); + } + + $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. + * + * @param bool $short Whether to show the short version of the synopsis (with options folded) or not + * + * @return string The synopsis + */ + public function getSynopsis(bool $short = false) + { + $key = $short ? 'short' : 'long'; + + if (!isset($this->synopsis[$key])) { + $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short))); + } + + return $this->synopsis[$key]; + } + + /** + * Add a command usage example, it'll be prefixed with the command name. + * + * @return $this + */ + public function addUsage(string $usage) + { + if (0 !== strpos($usage, $this->name)) { + $usage = sprintf('%s %s', $this->name, $usage); + } + + $this->usages[] = $usage; + + return $this; + } + + /** + * Returns alternative usages of the command. + * + * @return array + */ + public function getUsages() + { + return $this->usages; + } + + /** + * Gets a helper instance by name. + * + * @return mixed The helper value + * + * @throws LogicException if no HelperSet is defined + * @throws InvalidArgumentException if the helper is not defined + */ + public function getHelper(string $name) + { + if (null === $this->helperSet) { + throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name)); + } + + return $this->helperSet->get($name); + } + + /** + * Validates a command name. + * + * It must be non-empty and parts can optionally be separated by ":". + * + * @throws InvalidArgumentException When the name is invalid + */ + private function validateName(string $name) + { + if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) { + throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name)); + } + } +} diff --git a/vendor/symfony/console/Command/HelpCommand.php b/vendor/symfony/console/Command/HelpCommand.php new file mode 100644 index 0000000..b32be4c --- /dev/null +++ b/vendor/symfony/console/Command/HelpCommand.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Helper\DescriptorHelper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * HelpCommand displays the help for a given command. + * + * @author Fabien Potencier + */ +class HelpCommand extends Command +{ + private $command; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->ignoreValidationErrors(); + + $this + ->setName('help') + ->setDefinition([ + new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), + new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'), + ]) + ->setDescription('Displays help for a command') + ->setHelp(<<<'EOF' +The %command.name% command displays help for a given command: + + php %command.full_name% list + +You can also output the help in other formats by using the --format option: + + php %command.full_name% --format=xml list + +To display the list of available commands, please use the list command. +EOF + ) + ; + } + + public function setCommand(Command $command) + { + $this->command = $command; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + if (null === $this->command) { + $this->command = $this->getApplication()->find($input->getArgument('command_name')); + } + + $helper = new DescriptorHelper(); + $helper->describe($output, $this->command, [ + 'format' => $input->getOption('format'), + 'raw_text' => $input->getOption('raw'), + ]); + + $this->command = null; + + return 0; + } +} diff --git a/vendor/symfony/console/Command/ListCommand.php b/vendor/symfony/console/Command/ListCommand.php new file mode 100644 index 0000000..8af9526 --- /dev/null +++ b/vendor/symfony/console/Command/ListCommand.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Helper\DescriptorHelper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * ListCommand displays the list of all available commands for the application. + * + * @author Fabien Potencier + */ +class ListCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('list') + ->setDefinition($this->createDefinition()) + ->setDescription('Lists commands') + ->setHelp(<<<'EOF' +The %command.name% command lists all commands: + + php %command.full_name% + +You can also display the commands for a specific namespace: + + php %command.full_name% test + +You can also output the information in other formats by using the --format option: + + php %command.full_name% --format=xml + +It's also possible to get raw list of commands (useful for embedding command runner): + + php %command.full_name% --raw +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + public function getNativeDefinition() + { + return $this->createDefinition(); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $helper = new DescriptorHelper(); + $helper->describe($output, $this->getApplication(), [ + 'format' => $input->getOption('format'), + 'raw_text' => $input->getOption('raw'), + 'namespace' => $input->getArgument('namespace'), + ]); + + return 0; + } + + private function createDefinition(): InputDefinition + { + return new InputDefinition([ + new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), + new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), + ]); + } +} diff --git a/vendor/symfony/console/Command/LockableTrait.php b/vendor/symfony/console/Command/LockableTrait.php new file mode 100644 index 0000000..60cfe36 --- /dev/null +++ b/vendor/symfony/console/Command/LockableTrait.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Lock\Lock; +use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\Store\FlockStore; +use Symfony\Component\Lock\Store\SemaphoreStore; + +/** + * Basic lock feature for commands. + * + * @author Geoffrey Brier + */ +trait LockableTrait +{ + /** @var Lock */ + private $lock; + + /** + * Locks a command. + */ + private function lock(string $name = null, bool $blocking = false): bool + { + if (!class_exists(SemaphoreStore::class)) { + throw new LogicException('To enable the locking feature you must install the symfony/lock component.'); + } + + if (null !== $this->lock) { + throw new LogicException('A lock is already in place.'); + } + + if (SemaphoreStore::isSupported()) { + $store = new SemaphoreStore(); + } else { + $store = new FlockStore(); + } + + $this->lock = (new LockFactory($store))->createLock($name ?: $this->getName()); + if (!$this->lock->acquire($blocking)) { + $this->lock = null; + + return false; + } + + return true; + } + + /** + * Releases the command lock if there is one. + */ + private function release() + { + if ($this->lock) { + $this->lock->release(); + $this->lock = null; + } + } +} diff --git a/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php b/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php new file mode 100644 index 0000000..d4f44e8 --- /dev/null +++ b/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\CommandLoader; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * @author Robin Chalas + */ +interface CommandLoaderInterface +{ + /** + * Loads a command. + * + * @return Command + * + * @throws CommandNotFoundException + */ + public function get(string $name); + + /** + * Checks if a command exists. + * + * @return bool + */ + public function has(string $name); + + /** + * @return string[] All registered command names + */ + public function getNames(); +} diff --git a/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php b/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php new file mode 100644 index 0000000..ddccb3d --- /dev/null +++ b/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\CommandLoader; + +use Psr\Container\ContainerInterface; +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * Loads commands from a PSR-11 container. + * + * @author Robin Chalas + */ +class ContainerCommandLoader implements CommandLoaderInterface +{ + private $container; + private $commandMap; + + /** + * @param array $commandMap An array with command names as keys and service ids as values + */ + public function __construct(ContainerInterface $container, array $commandMap) + { + $this->container = $container; + $this->commandMap = $commandMap; + } + + /** + * {@inheritdoc} + */ + public function get(string $name) + { + if (!$this->has($name)) { + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + } + + return $this->container->get($this->commandMap[$name]); + } + + /** + * {@inheritdoc} + */ + public function has(string $name) + { + return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]); + } + + /** + * {@inheritdoc} + */ + public function getNames() + { + return array_keys($this->commandMap); + } +} diff --git a/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php b/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php new file mode 100644 index 0000000..7e2db34 --- /dev/null +++ b/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\CommandLoader; + +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * A simple command loader using factories to instantiate commands lazily. + * + * @author Maxime Steinhausser + */ +class FactoryCommandLoader implements CommandLoaderInterface +{ + private $factories; + + /** + * @param callable[] $factories Indexed by command names + */ + public function __construct(array $factories) + { + $this->factories = $factories; + } + + /** + * {@inheritdoc} + */ + public function has(string $name) + { + return isset($this->factories[$name]); + } + + /** + * {@inheritdoc} + */ + public function get(string $name) + { + if (!isset($this->factories[$name])) { + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + } + + $factory = $this->factories[$name]; + + return $factory(); + } + + /** + * {@inheritdoc} + */ + public function getNames() + { + return array_keys($this->factories); + } +} diff --git a/vendor/symfony/console/ConsoleEvents.php b/vendor/symfony/console/ConsoleEvents.php new file mode 100644 index 0000000..4975643 --- /dev/null +++ b/vendor/symfony/console/ConsoleEvents.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console; + +/** + * Contains all events dispatched by an Application. + * + * @author Francesco Levorato + */ +final class ConsoleEvents +{ + /** + * The COMMAND event allows you to attach listeners before any command is + * executed by the console. It also allows you to modify the command, input and output + * before they are handled to the command. + * + * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent") + */ + const COMMAND = 'console.command'; + + /** + * The TERMINATE event allows you to attach listeners after a command is + * executed by the console. + * + * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent") + */ + const TERMINATE = 'console.terminate'; + + /** + * The ERROR event occurs when an uncaught exception or error appears. + * + * This event allows you to deal with the exception/error or + * to modify the thrown exception. + * + * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent") + */ + const ERROR = 'console.error'; +} diff --git a/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php b/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php new file mode 100644 index 0000000..666c8fa --- /dev/null +++ b/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\DependencyInjection; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\TypedReference; + +/** + * Registers console commands. + * + * @author Grégoire Pineau + */ +class AddConsoleCommandPass implements CompilerPassInterface +{ + private $commandLoaderServiceId; + private $commandTag; + + public function __construct(string $commandLoaderServiceId = 'console.command_loader', string $commandTag = 'console.command') + { + $this->commandLoaderServiceId = $commandLoaderServiceId; + $this->commandTag = $commandTag; + } + + public function process(ContainerBuilder $container) + { + $commandServices = $container->findTaggedServiceIds($this->commandTag, true); + $lazyCommandMap = []; + $lazyCommandRefs = []; + $serviceIds = []; + + foreach ($commandServices as $id => $tags) { + $definition = $container->getDefinition($id); + $class = $container->getParameterBag()->resolveValue($definition->getClass()); + + if (isset($tags[0]['command'])) { + $commandName = $tags[0]['command']; + } else { + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + if (!$r->isSubclassOf(Command::class)) { + throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class)); + } + $commandName = $class::getDefaultName(); + } + + if (null === $commandName) { + if (!$definition->isPublic() || $definition->isPrivate()) { + $commandId = 'console.command.public_alias.'.$id; + $container->setAlias($commandId, $id)->setPublic(true); + $id = $commandId; + } + $serviceIds[] = $id; + + continue; + } + + unset($tags[0]); + $lazyCommandMap[$commandName] = $id; + $lazyCommandRefs[$id] = new TypedReference($id, $class); + $aliases = []; + + foreach ($tags as $tag) { + if (isset($tag['command'])) { + $aliases[] = $tag['command']; + $lazyCommandMap[$tag['command']] = $id; + } + } + + $definition->addMethodCall('setName', [$commandName]); + + if ($aliases) { + $definition->addMethodCall('setAliases', [$aliases]); + } + } + + $container + ->register($this->commandLoaderServiceId, ContainerCommandLoader::class) + ->setPublic(true) + ->setArguments([ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]); + + $container->setParameter('console.command.ids', $serviceIds); + } +} diff --git a/vendor/symfony/console/Descriptor/ApplicationDescription.php b/vendor/symfony/console/Descriptor/ApplicationDescription.php new file mode 100644 index 0000000..af88363 --- /dev/null +++ b/vendor/symfony/console/Descriptor/ApplicationDescription.php @@ -0,0 +1,143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * @author Jean-François Simon + * + * @internal + */ +class ApplicationDescription +{ + const GLOBAL_NAMESPACE = '_global'; + + private $application; + private $namespace; + private $showHidden; + + /** + * @var array + */ + private $namespaces; + + /** + * @var Command[] + */ + private $commands; + + /** + * @var Command[] + */ + private $aliases; + + public function __construct(Application $application, string $namespace = null, bool $showHidden = false) + { + $this->application = $application; + $this->namespace = $namespace; + $this->showHidden = $showHidden; + } + + public function getNamespaces(): array + { + if (null === $this->namespaces) { + $this->inspectApplication(); + } + + return $this->namespaces; + } + + /** + * @return Command[] + */ + public function getCommands(): array + { + if (null === $this->commands) { + $this->inspectApplication(); + } + + return $this->commands; + } + + /** + * @throws CommandNotFoundException + */ + public function getCommand(string $name): Command + { + if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { + throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name)); + } + + return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name]; + } + + private function inspectApplication() + { + $this->commands = []; + $this->namespaces = []; + + $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null); + foreach ($this->sortCommands($all) as $namespace => $commands) { + $names = []; + + /** @var Command $command */ + foreach ($commands as $name => $command) { + if (!$command->getName() || (!$this->showHidden && $command->isHidden())) { + continue; + } + + if ($command->getName() === $name) { + $this->commands[$name] = $command; + } else { + $this->aliases[$name] = $command; + } + + $names[] = $name; + } + + $this->namespaces[$namespace] = ['id' => $namespace, 'commands' => $names]; + } + } + + private function sortCommands(array $commands): array + { + $namespacedCommands = []; + $globalCommands = []; + $sortedCommands = []; + foreach ($commands as $name => $command) { + $key = $this->application->extractNamespace($name, 1); + if (\in_array($key, ['', self::GLOBAL_NAMESPACE], true)) { + $globalCommands[$name] = $command; + } else { + $namespacedCommands[$key][$name] = $command; + } + } + + if ($globalCommands) { + ksort($globalCommands); + $sortedCommands[self::GLOBAL_NAMESPACE] = $globalCommands; + } + + if ($namespacedCommands) { + ksort($namespacedCommands); + foreach ($namespacedCommands as $key => $commandsSet) { + ksort($commandsSet); + $sortedCommands[$key] = $commandsSet; + } + } + + return $sortedCommands; + } +} diff --git a/vendor/symfony/console/Descriptor/Descriptor.php b/vendor/symfony/console/Descriptor/Descriptor.php new file mode 100644 index 0000000..df85e38 --- /dev/null +++ b/vendor/symfony/console/Descriptor/Descriptor.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Jean-François Simon + * + * @internal + */ +abstract class Descriptor implements DescriptorInterface +{ + /** + * @var OutputInterface + */ + protected $output; + + /** + * {@inheritdoc} + */ + public function describe(OutputInterface $output, $object, array $options = []) + { + $this->output = $output; + + switch (true) { + case $object instanceof InputArgument: + $this->describeInputArgument($object, $options); + break; + case $object instanceof InputOption: + $this->describeInputOption($object, $options); + break; + case $object instanceof InputDefinition: + $this->describeInputDefinition($object, $options); + break; + case $object instanceof Command: + $this->describeCommand($object, $options); + break; + case $object instanceof Application: + $this->describeApplication($object, $options); + break; + default: + throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', \get_class($object))); + } + } + + /** + * Writes content to output. + */ + protected function write(string $content, bool $decorated = false) + { + $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); + } + + /** + * Describes an InputArgument instance. + * + * @return string|mixed + */ + abstract protected function describeInputArgument(InputArgument $argument, array $options = []); + + /** + * Describes an InputOption instance. + * + * @return string|mixed + */ + abstract protected function describeInputOption(InputOption $option, array $options = []); + + /** + * Describes an InputDefinition instance. + * + * @return string|mixed + */ + abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []); + + /** + * Describes a Command instance. + * + * @return string|mixed + */ + abstract protected function describeCommand(Command $command, array $options = []); + + /** + * Describes an Application instance. + * + * @return string|mixed + */ + abstract protected function describeApplication(Application $application, array $options = []); +} diff --git a/vendor/symfony/console/Descriptor/DescriptorInterface.php b/vendor/symfony/console/Descriptor/DescriptorInterface.php new file mode 100644 index 0000000..e3184a6 --- /dev/null +++ b/vendor/symfony/console/Descriptor/DescriptorInterface.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Descriptor interface. + * + * @author Jean-François Simon + */ +interface DescriptorInterface +{ + /** + * Describes an object if supported. + * + * @param object $object + */ + public function describe(OutputInterface $output, $object, array $options = []); +} diff --git a/vendor/symfony/console/Descriptor/JsonDescriptor.php b/vendor/symfony/console/Descriptor/JsonDescriptor.php new file mode 100644 index 0000000..131fef1 --- /dev/null +++ b/vendor/symfony/console/Descriptor/JsonDescriptor.php @@ -0,0 +1,156 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; + +/** + * JSON descriptor. + * + * @author Jean-François Simon + * + * @internal + */ +class JsonDescriptor extends Descriptor +{ + /** + * {@inheritdoc} + */ + protected function describeInputArgument(InputArgument $argument, array $options = []) + { + $this->writeData($this->getInputArgumentData($argument), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeInputOption(InputOption $option, array $options = []) + { + $this->writeData($this->getInputOptionData($option), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeInputDefinition(InputDefinition $definition, array $options = []) + { + $this->writeData($this->getInputDefinitionData($definition), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeCommand(Command $command, array $options = []) + { + $this->writeData($this->getCommandData($command), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeApplication(Application $application, array $options = []) + { + $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; + $description = new ApplicationDescription($application, $describedNamespace, true); + $commands = []; + + foreach ($description->getCommands() as $command) { + $commands[] = $this->getCommandData($command); + } + + $data = []; + if ('UNKNOWN' !== $application->getName()) { + $data['application']['name'] = $application->getName(); + if ('UNKNOWN' !== $application->getVersion()) { + $data['application']['version'] = $application->getVersion(); + } + } + + $data['commands'] = $commands; + + if ($describedNamespace) { + $data['namespace'] = $describedNamespace; + } else { + $data['namespaces'] = array_values($description->getNamespaces()); + } + + $this->writeData($data, $options); + } + + /** + * Writes data as json. + */ + private function writeData(array $data, array $options) + { + $flags = isset($options['json_encoding']) ? $options['json_encoding'] : 0; + + $this->write(json_encode($data, $flags)); + } + + private function getInputArgumentData(InputArgument $argument): array + { + return [ + 'name' => $argument->getName(), + 'is_required' => $argument->isRequired(), + 'is_array' => $argument->isArray(), + 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), + 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), + ]; + } + + private function getInputOptionData(InputOption $option): array + { + return [ + 'name' => '--'.$option->getName(), + 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '', + 'accept_value' => $option->acceptValue(), + 'is_value_required' => $option->isValueRequired(), + 'is_multiple' => $option->isArray(), + 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), + 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(), + ]; + } + + private function getInputDefinitionData(InputDefinition $definition): array + { + $inputArguments = []; + foreach ($definition->getArguments() as $name => $argument) { + $inputArguments[$name] = $this->getInputArgumentData($argument); + } + + $inputOptions = []; + foreach ($definition->getOptions() as $name => $option) { + $inputOptions[$name] = $this->getInputOptionData($option); + } + + return ['arguments' => $inputArguments, 'options' => $inputOptions]; + } + + private function getCommandData(Command $command): array + { + $command->getSynopsis(); + $command->mergeApplicationDefinition(false); + + return [ + 'name' => $command->getName(), + 'usage' => array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()), + 'description' => $command->getDescription(), + 'help' => $command->getProcessedHelp(), + 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()), + 'hidden' => $command->isHidden(), + ]; + } +} diff --git a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php new file mode 100644 index 0000000..8b3e182 --- /dev/null +++ b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php @@ -0,0 +1,188 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Markdown descriptor. + * + * @author Jean-François Simon + * + * @internal + */ +class MarkdownDescriptor extends Descriptor +{ + /** + * {@inheritdoc} + */ + public function describe(OutputInterface $output, $object, array $options = []) + { + $decorated = $output->isDecorated(); + $output->setDecorated(false); + + parent::describe($output, $object, $options); + + $output->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + protected function write(string $content, bool $decorated = true) + { + parent::write($content, $decorated); + } + + /** + * {@inheritdoc} + */ + protected function describeInputArgument(InputArgument $argument, array $options = []) + { + $this->write( + '#### `'.($argument->getName() ?: '')."`\n\n" + .($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription())."\n\n" : '') + .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" + .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" + .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`' + ); + } + + /** + * {@inheritdoc} + */ + protected function describeInputOption(InputOption $option, array $options = []) + { + $name = '--'.$option->getName(); + if ($option->getShortcut()) { + $name .= '|-'.str_replace('|', '|-', $option->getShortcut()).''; + } + + $this->write( + '#### `'.$name.'`'."\n\n" + .($option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $option->getDescription())."\n\n" : '') + .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" + .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" + .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" + .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`' + ); + } + + /** + * {@inheritdoc} + */ + protected function describeInputDefinition(InputDefinition $definition, array $options = []) + { + if ($showArguments = \count($definition->getArguments()) > 0) { + $this->write('### Arguments'); + foreach ($definition->getArguments() as $argument) { + $this->write("\n\n"); + if (null !== $describeInputArgument = $this->describeInputArgument($argument)) { + $this->write($describeInputArgument); + } + } + } + + if (\count($definition->getOptions()) > 0) { + if ($showArguments) { + $this->write("\n\n"); + } + + $this->write('### Options'); + foreach ($definition->getOptions() as $option) { + $this->write("\n\n"); + if (null !== $describeInputOption = $this->describeInputOption($option)) { + $this->write($describeInputOption); + } + } + } + } + + /** + * {@inheritdoc} + */ + protected function describeCommand(Command $command, array $options = []) + { + $command->getSynopsis(); + $command->mergeApplicationDefinition(false); + + $this->write( + '`'.$command->getName()."`\n" + .str_repeat('-', Helper::strlen($command->getName()) + 2)."\n\n" + .($command->getDescription() ? $command->getDescription()."\n\n" : '') + .'### Usage'."\n\n" + .array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), function ($carry, $usage) { + return $carry.'* `'.$usage.'`'."\n"; + }) + ); + + if ($help = $command->getProcessedHelp()) { + $this->write("\n"); + $this->write($help); + } + + if ($command->getNativeDefinition()) { + $this->write("\n\n"); + $this->describeInputDefinition($command->getNativeDefinition()); + } + } + + /** + * {@inheritdoc} + */ + protected function describeApplication(Application $application, array $options = []) + { + $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; + $description = new ApplicationDescription($application, $describedNamespace); + $title = $this->getApplicationTitle($application); + + $this->write($title."\n".str_repeat('=', Helper::strlen($title))); + + foreach ($description->getNamespaces() as $namespace) { + if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { + $this->write("\n\n"); + $this->write('**'.$namespace['id'].':**'); + } + + $this->write("\n\n"); + $this->write(implode("\n", array_map(function ($commandName) use ($description) { + return sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName())); + }, $namespace['commands']))); + } + + foreach ($description->getCommands() as $command) { + $this->write("\n\n"); + if (null !== $describeCommand = $this->describeCommand($command)) { + $this->write($describeCommand); + } + } + } + + private function getApplicationTitle(Application $application): string + { + if ('UNKNOWN' !== $application->getName()) { + if ('UNKNOWN' !== $application->getVersion()) { + return sprintf('%s %s', $application->getName(), $application->getVersion()); + } + + return $application->getName(); + } + + return 'Console Tool'; + } +} diff --git a/vendor/symfony/console/Descriptor/TextDescriptor.php b/vendor/symfony/console/Descriptor/TextDescriptor.php new file mode 100644 index 0000000..ef6d8af --- /dev/null +++ b/vendor/symfony/console/Descriptor/TextDescriptor.php @@ -0,0 +1,342 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; + +/** + * Text descriptor. + * + * @author Jean-François Simon + * + * @internal + */ +class TextDescriptor extends Descriptor +{ + /** + * {@inheritdoc} + */ + protected function describeInputArgument(InputArgument $argument, array $options = []) + { + if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) { + $default = sprintf(' [default: %s]', $this->formatDefaultValue($argument->getDefault())); + } else { + $default = ''; + } + + $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName()); + $spacingWidth = $totalWidth - \strlen($argument->getName()); + + $this->writeText(sprintf(' %s %s%s%s', + $argument->getName(), + str_repeat(' ', $spacingWidth), + // + 4 = 2 spaces before , 2 spaces after + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()), + $default + ), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeInputOption(InputOption $option, array $options = []) + { + if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) { + $default = sprintf(' [default: %s]', $this->formatDefaultValue($option->getDefault())); + } else { + $default = ''; + } + + $value = ''; + if ($option->acceptValue()) { + $value = '='.strtoupper($option->getName()); + + if ($option->isValueOptional()) { + $value = '['.$value.']'; + } + } + + $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions([$option]); + $synopsis = sprintf('%s%s', + $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ', + sprintf('--%s%s', $option->getName(), $value) + ); + + $spacingWidth = $totalWidth - Helper::strlen($synopsis); + + $this->writeText(sprintf(' %s %s%s%s%s', + $synopsis, + str_repeat(' ', $spacingWidth), + // + 4 = 2 spaces before , 2 spaces after + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()), + $default, + $option->isArray() ? ' (multiple values allowed)' : '' + ), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeInputDefinition(InputDefinition $definition, array $options = []) + { + $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions()); + foreach ($definition->getArguments() as $argument) { + $totalWidth = max($totalWidth, Helper::strlen($argument->getName())); + } + + if ($definition->getArguments()) { + $this->writeText('Arguments:', $options); + $this->writeText("\n"); + foreach ($definition->getArguments() as $argument) { + $this->describeInputArgument($argument, array_merge($options, ['total_width' => $totalWidth])); + $this->writeText("\n"); + } + } + + if ($definition->getArguments() && $definition->getOptions()) { + $this->writeText("\n"); + } + + if ($definition->getOptions()) { + $laterOptions = []; + + $this->writeText('Options:', $options); + foreach ($definition->getOptions() as $option) { + if (\strlen($option->getShortcut()) > 1) { + $laterOptions[] = $option; + continue; + } + $this->writeText("\n"); + $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); + } + foreach ($laterOptions as $option) { + $this->writeText("\n"); + $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); + } + } + } + + /** + * {@inheritdoc} + */ + protected function describeCommand(Command $command, array $options = []) + { + $command->getSynopsis(true); + $command->getSynopsis(false); + $command->mergeApplicationDefinition(false); + + if ($description = $command->getDescription()) { + $this->writeText('Description:', $options); + $this->writeText("\n"); + $this->writeText(' '.$description); + $this->writeText("\n\n"); + } + + $this->writeText('Usage:', $options); + foreach (array_merge([$command->getSynopsis(true)], $command->getAliases(), $command->getUsages()) as $usage) { + $this->writeText("\n"); + $this->writeText(' '.OutputFormatter::escape($usage), $options); + } + $this->writeText("\n"); + + $definition = $command->getNativeDefinition(); + if ($definition->getOptions() || $definition->getArguments()) { + $this->writeText("\n"); + $this->describeInputDefinition($definition, $options); + $this->writeText("\n"); + } + + $help = $command->getProcessedHelp(); + if ($help && $help !== $description) { + $this->writeText("\n"); + $this->writeText('Help:', $options); + $this->writeText("\n"); + $this->writeText(' '.str_replace("\n", "\n ", $help), $options); + $this->writeText("\n"); + } + } + + /** + * {@inheritdoc} + */ + protected function describeApplication(Application $application, array $options = []) + { + $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; + $description = new ApplicationDescription($application, $describedNamespace); + + if (isset($options['raw_text']) && $options['raw_text']) { + $width = $this->getColumnWidth($description->getCommands()); + + foreach ($description->getCommands() as $command) { + $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options); + $this->writeText("\n"); + } + } else { + if ('' != $help = $application->getHelp()) { + $this->writeText("$help\n\n", $options); + } + + $this->writeText("Usage:\n", $options); + $this->writeText(" command [options] [arguments]\n\n", $options); + + $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options); + + $this->writeText("\n"); + $this->writeText("\n"); + + $commands = $description->getCommands(); + $namespaces = $description->getNamespaces(); + if ($describedNamespace && $namespaces) { + // make sure all alias commands are included when describing a specific namespace + $describedNamespaceInfo = reset($namespaces); + foreach ($describedNamespaceInfo['commands'] as $name) { + $commands[$name] = $description->getCommand($name); + } + } + + // calculate max. width based on available commands per namespace + $width = $this->getColumnWidth(array_merge(...array_values(array_map(function ($namespace) use ($commands) { + return array_intersect($namespace['commands'], array_keys($commands)); + }, $namespaces)))); + + if ($describedNamespace) { + $this->writeText(sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options); + } else { + $this->writeText('Available commands:', $options); + } + + foreach ($namespaces as $namespace) { + $namespace['commands'] = array_filter($namespace['commands'], function ($name) use ($commands) { + return isset($commands[$name]); + }); + + if (!$namespace['commands']) { + continue; + } + + if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { + $this->writeText("\n"); + $this->writeText(' '.$namespace['id'].'', $options); + } + + foreach ($namespace['commands'] as $name) { + $this->writeText("\n"); + $spacingWidth = $width - Helper::strlen($name); + $command = $commands[$name]; + $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : ''; + $this->writeText(sprintf(' %s%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options); + } + } + + $this->writeText("\n"); + } + } + + /** + * {@inheritdoc} + */ + private function writeText(string $content, array $options = []) + { + $this->write( + isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, + isset($options['raw_output']) ? !$options['raw_output'] : true + ); + } + + /** + * Formats command aliases to show them in the command description. + */ + private function getCommandAliasesText(Command $command): string + { + $text = ''; + $aliases = $command->getAliases(); + + if ($aliases) { + $text = '['.implode('|', $aliases).'] '; + } + + return $text; + } + + /** + * Formats input option/argument default value. + * + * @param mixed $default + */ + private function formatDefaultValue($default): string + { + if (INF === $default) { + return 'INF'; + } + + if (\is_string($default)) { + $default = OutputFormatter::escape($default); + } elseif (\is_array($default)) { + foreach ($default as $key => $value) { + if (\is_string($value)) { + $default[$key] = OutputFormatter::escape($value); + } + } + } + + return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); + } + + /** + * @param (Command|string)[] $commands + */ + private function getColumnWidth(array $commands): int + { + $widths = []; + + foreach ($commands as $command) { + if ($command instanceof Command) { + $widths[] = Helper::strlen($command->getName()); + foreach ($command->getAliases() as $alias) { + $widths[] = Helper::strlen($alias); + } + } else { + $widths[] = Helper::strlen($command); + } + } + + return $widths ? max($widths) + 2 : 0; + } + + /** + * @param InputOption[] $options + */ + private function calculateTotalWidthForOptions(array $options): int + { + $totalWidth = 0; + foreach ($options as $option) { + // "-" + shortcut + ", --" + name + $nameLength = 1 + max(Helper::strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName()); + + if ($option->acceptValue()) { + $valueLength = 1 + Helper::strlen($option->getName()); // = + value + $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ] + + $nameLength += $valueLength; + } + $totalWidth = max($totalWidth, $nameLength); + } + + return $totalWidth; + } +} diff --git a/vendor/symfony/console/Descriptor/XmlDescriptor.php b/vendor/symfony/console/Descriptor/XmlDescriptor.php new file mode 100644 index 0000000..3d5dce1 --- /dev/null +++ b/vendor/symfony/console/Descriptor/XmlDescriptor.php @@ -0,0 +1,231 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; + +/** + * XML descriptor. + * + * @author Jean-François Simon + * + * @internal + */ +class XmlDescriptor extends Descriptor +{ + public function getInputDefinitionDocument(InputDefinition $definition): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($definitionXML = $dom->createElement('definition')); + + $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); + foreach ($definition->getArguments() as $argument) { + $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument)); + } + + $definitionXML->appendChild($optionsXML = $dom->createElement('options')); + foreach ($definition->getOptions() as $option) { + $this->appendDocument($optionsXML, $this->getInputOptionDocument($option)); + } + + return $dom; + } + + public function getCommandDocument(Command $command): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($commandXML = $dom->createElement('command')); + + $command->getSynopsis(); + $command->mergeApplicationDefinition(false); + + $commandXML->setAttribute('id', $command->getName()); + $commandXML->setAttribute('name', $command->getName()); + $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0); + + $commandXML->appendChild($usagesXML = $dom->createElement('usages')); + + foreach (array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()) as $usage) { + $usagesXML->appendChild($dom->createElement('usage', $usage)); + } + + $commandXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription()))); + + $commandXML->appendChild($helpXML = $dom->createElement('help')); + $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp()))); + + $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition()); + $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); + + return $dom; + } + + public function getApplicationDocument(Application $application, string $namespace = null): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($rootXml = $dom->createElement('symfony')); + + if ('UNKNOWN' !== $application->getName()) { + $rootXml->setAttribute('name', $application->getName()); + if ('UNKNOWN' !== $application->getVersion()) { + $rootXml->setAttribute('version', $application->getVersion()); + } + } + + $rootXml->appendChild($commandsXML = $dom->createElement('commands')); + + $description = new ApplicationDescription($application, $namespace, true); + + if ($namespace) { + $commandsXML->setAttribute('namespace', $namespace); + } + + foreach ($description->getCommands() as $command) { + $this->appendDocument($commandsXML, $this->getCommandDocument($command)); + } + + if (!$namespace) { + $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces')); + + foreach ($description->getNamespaces() as $namespaceDescription) { + $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace')); + $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']); + + foreach ($namespaceDescription['commands'] as $name) { + $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command')); + $commandXML->appendChild($dom->createTextNode($name)); + } + } + } + + return $dom; + } + + /** + * {@inheritdoc} + */ + protected function describeInputArgument(InputArgument $argument, array $options = []) + { + $this->writeDocument($this->getInputArgumentDocument($argument)); + } + + /** + * {@inheritdoc} + */ + protected function describeInputOption(InputOption $option, array $options = []) + { + $this->writeDocument($this->getInputOptionDocument($option)); + } + + /** + * {@inheritdoc} + */ + protected function describeInputDefinition(InputDefinition $definition, array $options = []) + { + $this->writeDocument($this->getInputDefinitionDocument($definition)); + } + + /** + * {@inheritdoc} + */ + protected function describeCommand(Command $command, array $options = []) + { + $this->writeDocument($this->getCommandDocument($command)); + } + + /** + * {@inheritdoc} + */ + protected function describeApplication(Application $application, array $options = []) + { + $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null)); + } + + /** + * Appends document children to parent node. + */ + private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) + { + foreach ($importedParent->childNodes as $childNode) { + $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true)); + } + } + + /** + * Writes DOM document. + */ + private function writeDocument(\DOMDocument $dom) + { + $dom->formatOutput = true; + $this->write($dom->saveXML()); + } + + private function getInputArgumentDocument(InputArgument $argument): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + + $dom->appendChild($objectXML = $dom->createElement('argument')); + $objectXML->setAttribute('name', $argument->getName()); + $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); + $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); + $objectXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); + + $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); + $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? [var_export($argument->getDefault(), true)] : ($argument->getDefault() ? [$argument->getDefault()] : [])); + foreach ($defaults as $default) { + $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); + $defaultXML->appendChild($dom->createTextNode($default)); + } + + return $dom; + } + + private function getInputOptionDocument(InputOption $option): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + + $dom->appendChild($objectXML = $dom->createElement('option')); + $objectXML->setAttribute('name', '--'.$option->getName()); + $pos = strpos($option->getShortcut(), '|'); + if (false !== $pos) { + $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); + $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut())); + } else { + $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); + } + $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0); + $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0); + $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); + $objectXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); + + if ($option->acceptValue()) { + $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? [var_export($option->getDefault(), true)] : ($option->getDefault() ? [$option->getDefault()] : [])); + $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); + + if (!empty($defaults)) { + foreach ($defaults as $default) { + $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); + $defaultXML->appendChild($dom->createTextNode($default)); + } + } + } + + return $dom; + } +} diff --git a/vendor/symfony/console/Event/ConsoleCommandEvent.php b/vendor/symfony/console/Event/ConsoleCommandEvent.php new file mode 100644 index 0000000..a24697c --- /dev/null +++ b/vendor/symfony/console/Event/ConsoleCommandEvent.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Event; + +/** + * Allows to do things before the command is executed, like skipping the command or changing the input. + * + * @author Fabien Potencier + */ +final class ConsoleCommandEvent extends ConsoleEvent +{ + /** + * The return code for skipped commands, this will also be passed into the terminate event. + */ + const RETURN_CODE_DISABLED = 113; + + /** + * Indicates if the command should be run or skipped. + */ + private $commandShouldRun = true; + + /** + * Disables the command, so it won't be run. + */ + public function disableCommand(): bool + { + return $this->commandShouldRun = false; + } + + public function enableCommand(): bool + { + return $this->commandShouldRun = true; + } + + /** + * Returns true if the command is runnable, false otherwise. + */ + public function commandShouldRun(): bool + { + return $this->commandShouldRun; + } +} diff --git a/vendor/symfony/console/Event/ConsoleErrorEvent.php b/vendor/symfony/console/Event/ConsoleErrorEvent.php new file mode 100644 index 0000000..25d9b88 --- /dev/null +++ b/vendor/symfony/console/Event/ConsoleErrorEvent.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Event; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Allows to handle throwables thrown while running a command. + * + * @author Wouter de Jong + */ +final class ConsoleErrorEvent extends ConsoleEvent +{ + private $error; + private $exitCode; + + public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null) + { + parent::__construct($command, $input, $output); + + $this->error = $error; + } + + public function getError(): \Throwable + { + return $this->error; + } + + public function setError(\Throwable $error): void + { + $this->error = $error; + } + + public function setExitCode(int $exitCode): void + { + $this->exitCode = $exitCode; + + $r = new \ReflectionProperty($this->error, 'code'); + $r->setAccessible(true); + $r->setValue($this->error, $this->exitCode); + } + + public function getExitCode(): int + { + return null !== $this->exitCode ? $this->exitCode : (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1); + } +} diff --git a/vendor/symfony/console/Event/ConsoleEvent.php b/vendor/symfony/console/Event/ConsoleEvent.php new file mode 100644 index 0000000..89ab645 --- /dev/null +++ b/vendor/symfony/console/Event/ConsoleEvent.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Event; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Contracts\EventDispatcher\Event; + +/** + * Allows to inspect input and output of a command. + * + * @author Francesco Levorato + */ +class ConsoleEvent extends Event +{ + protected $command; + + private $input; + private $output; + + public function __construct(Command $command = null, InputInterface $input, OutputInterface $output) + { + $this->command = $command; + $this->input = $input; + $this->output = $output; + } + + /** + * Gets the command that is executed. + * + * @return Command|null A Command instance + */ + public function getCommand() + { + return $this->command; + } + + /** + * Gets the input instance. + * + * @return InputInterface An InputInterface instance + */ + public function getInput() + { + return $this->input; + } + + /** + * Gets the output instance. + * + * @return OutputInterface An OutputInterface instance + */ + public function getOutput() + { + return $this->output; + } +} diff --git a/vendor/symfony/console/Event/ConsoleTerminateEvent.php b/vendor/symfony/console/Event/ConsoleTerminateEvent.php new file mode 100644 index 0000000..190038d --- /dev/null +++ b/vendor/symfony/console/Event/ConsoleTerminateEvent.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Event; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Allows to manipulate the exit code of a command after its execution. + * + * @author Francesco Levorato + */ +final class ConsoleTerminateEvent extends ConsoleEvent +{ + private $exitCode; + + public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $exitCode) + { + parent::__construct($command, $input, $output); + + $this->setExitCode($exitCode); + } + + public function setExitCode(int $exitCode): void + { + $this->exitCode = $exitCode; + } + + public function getExitCode(): int + { + return $this->exitCode; + } +} diff --git a/vendor/symfony/console/EventListener/ErrorListener.php b/vendor/symfony/console/EventListener/ErrorListener.php new file mode 100644 index 0000000..a340757 --- /dev/null +++ b/vendor/symfony/console/EventListener/ErrorListener.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\EventListener; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Console\ConsoleEvents; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Event\ConsoleEvent; +use Symfony\Component\Console\Event\ConsoleTerminateEvent; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +/** + * @author James Halsall + * @author Robin Chalas + */ +class ErrorListener implements EventSubscriberInterface +{ + private $logger; + + public function __construct(LoggerInterface $logger = null) + { + $this->logger = $logger; + } + + public function onConsoleError(ConsoleErrorEvent $event) + { + if (null === $this->logger) { + return; + } + + $error = $event->getError(); + + if (!$inputString = $this->getInputString($event)) { + $this->logger->error('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]); + + return; + } + + $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]); + } + + public function onConsoleTerminate(ConsoleTerminateEvent $event) + { + if (null === $this->logger) { + return; + } + + $exitCode = $event->getExitCode(); + + if (0 === $exitCode) { + return; + } + + if (!$inputString = $this->getInputString($event)) { + $this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]); + + return; + } + + $this->logger->debug('Command "{command}" exited with code "{code}"', ['command' => $inputString, 'code' => $exitCode]); + } + + public static function getSubscribedEvents() + { + return [ + ConsoleEvents::ERROR => ['onConsoleError', -128], + ConsoleEvents::TERMINATE => ['onConsoleTerminate', -128], + ]; + } + + private static function getInputString(ConsoleEvent $event): ?string + { + $commandName = $event->getCommand() ? $event->getCommand()->getName() : null; + $input = $event->getInput(); + + if (method_exists($input, '__toString')) { + if ($commandName) { + return str_replace(["'$commandName'", "\"$commandName\""], $commandName, (string) $input); + } + + return (string) $input; + } + + return $commandName; + } +} diff --git a/vendor/symfony/console/Exception/CommandNotFoundException.php b/vendor/symfony/console/Exception/CommandNotFoundException.php new file mode 100644 index 0000000..69d5cb9 --- /dev/null +++ b/vendor/symfony/console/Exception/CommandNotFoundException.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * Represents an incorrect command name typed in the console. + * + * @author Jérôme Tamarelle + */ +class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface +{ + private $alternatives; + + /** + * @param string $message Exception message to throw + * @param array $alternatives List of similar defined names + * @param int $code Exception code + * @param \Throwable $previous Previous exception used for the exception chaining + */ + public function __construct(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null) + { + parent::__construct($message, $code, $previous); + + $this->alternatives = $alternatives; + } + + /** + * @return array A list of similar defined names + */ + public function getAlternatives() + { + return $this->alternatives; + } +} diff --git a/vendor/symfony/console/Exception/ExceptionInterface.php b/vendor/symfony/console/Exception/ExceptionInterface.php new file mode 100644 index 0000000..1624e13 --- /dev/null +++ b/vendor/symfony/console/Exception/ExceptionInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * ExceptionInterface. + * + * @author Jérôme Tamarelle + */ +interface ExceptionInterface extends \Throwable +{ +} diff --git a/vendor/symfony/console/Exception/InvalidArgumentException.php b/vendor/symfony/console/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..07cc0b6 --- /dev/null +++ b/vendor/symfony/console/Exception/InvalidArgumentException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * @author Jérôme Tamarelle + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/console/Exception/InvalidOptionException.php b/vendor/symfony/console/Exception/InvalidOptionException.php new file mode 100644 index 0000000..b2eec61 --- /dev/null +++ b/vendor/symfony/console/Exception/InvalidOptionException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * Represents an incorrect option name typed in the console. + * + * @author Jérôme Tamarelle + */ +class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/console/Exception/LogicException.php b/vendor/symfony/console/Exception/LogicException.php new file mode 100644 index 0000000..fc37b8d --- /dev/null +++ b/vendor/symfony/console/Exception/LogicException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * @author Jérôme Tamarelle + */ +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/console/Exception/NamespaceNotFoundException.php b/vendor/symfony/console/Exception/NamespaceNotFoundException.php new file mode 100644 index 0000000..dd16e45 --- /dev/null +++ b/vendor/symfony/console/Exception/NamespaceNotFoundException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * Represents an incorrect namespace typed in the console. + * + * @author Pierre du Plessis + */ +class NamespaceNotFoundException extends CommandNotFoundException +{ +} diff --git a/vendor/symfony/console/Exception/RuntimeException.php b/vendor/symfony/console/Exception/RuntimeException.php new file mode 100644 index 0000000..51d7d80 --- /dev/null +++ b/vendor/symfony/console/Exception/RuntimeException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * @author Jérôme Tamarelle + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/console/Formatter/OutputFormatter.php b/vendor/symfony/console/Formatter/OutputFormatter.php new file mode 100644 index 0000000..2ca63b6 --- /dev/null +++ b/vendor/symfony/console/Formatter/OutputFormatter.php @@ -0,0 +1,275 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * Formatter class for console output. + * + * @author Konstantin Kudryashov + * @author Roland Franssen + */ +class OutputFormatter implements WrappableOutputFormatterInterface +{ + private $decorated; + private $styles = []; + private $styleStack; + + /** + * Escapes "<" special char in given text. + * + * @return string Escaped text + */ + public static function escape(string $text) + { + $text = preg_replace('/([^\\\\]?) FormatterStyle" instances + */ + public function __construct(bool $decorated = false, array $styles = []) + { + $this->decorated = $decorated; + + $this->setStyle('error', new OutputFormatterStyle('white', 'red')); + $this->setStyle('info', new OutputFormatterStyle('green')); + $this->setStyle('comment', new OutputFormatterStyle('yellow')); + $this->setStyle('question', new OutputFormatterStyle('black', 'cyan')); + + foreach ($styles as $name => $style) { + $this->setStyle($name, $style); + } + + $this->styleStack = new OutputFormatterStyleStack(); + } + + /** + * {@inheritdoc} + */ + public function setDecorated(bool $decorated) + { + $this->decorated = $decorated; + } + + /** + * {@inheritdoc} + */ + public function isDecorated() + { + return $this->decorated; + } + + /** + * {@inheritdoc} + */ + public function setStyle(string $name, OutputFormatterStyleInterface $style) + { + $this->styles[strtolower($name)] = $style; + } + + /** + * {@inheritdoc} + */ + public function hasStyle(string $name) + { + return isset($this->styles[strtolower($name)]); + } + + /** + * {@inheritdoc} + */ + public function getStyle(string $name) + { + if (!$this->hasStyle($name)) { + throw new InvalidArgumentException(sprintf('Undefined style: %s', $name)); + } + + return $this->styles[strtolower($name)]; + } + + /** + * {@inheritdoc} + */ + public function format(?string $message) + { + return $this->formatAndWrap($message, 0); + } + + /** + * {@inheritdoc} + */ + public function formatAndWrap(?string $message, int $width) + { + $offset = 0; + $output = ''; + $tagRegex = '[a-z][^<>]*+'; + $currentLineLength = 0; + preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE); + foreach ($matches[0] as $i => $match) { + $pos = $match[1]; + $text = $match[0]; + + if (0 != $pos && '\\' == $message[$pos - 1]) { + continue; + } + + // add the text up to the next tag + $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength); + $offset = $pos + \strlen($text); + + // opening tag? + if ($open = '/' != $text[1]) { + $tag = $matches[1][$i][0]; + } else { + $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : ''; + } + + if (!$open && !$tag) { + // + $this->styleStack->pop(); + } elseif (null === $style = $this->createStyleFromString($tag)) { + $output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength); + } elseif ($open) { + $this->styleStack->push($style); + } else { + $this->styleStack->pop($style); + } + } + + $output .= $this->applyCurrentStyle(substr($message, $offset), $output, $width, $currentLineLength); + + if (false !== strpos($output, "\0")) { + return strtr($output, ["\0" => '\\', '\\<' => '<']); + } + + return str_replace('\\<', '<', $output); + } + + /** + * @return OutputFormatterStyleStack + */ + public function getStyleStack() + { + return $this->styleStack; + } + + /** + * Tries to create new style instance from string. + */ + private function createStyleFromString(string $string): ?OutputFormatterStyleInterface + { + if (isset($this->styles[$string])) { + return $this->styles[$string]; + } + + if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, PREG_SET_ORDER)) { + return null; + } + + $style = new OutputFormatterStyle(); + foreach ($matches as $match) { + array_shift($match); + $match[0] = strtolower($match[0]); + + if ('fg' == $match[0]) { + $style->setForeground(strtolower($match[1])); + } elseif ('bg' == $match[0]) { + $style->setBackground(strtolower($match[1])); + } elseif ('href' === $match[0]) { + $style->setHref($match[1]); + } elseif ('options' === $match[0]) { + preg_match_all('([^,;]+)', strtolower($match[1]), $options); + $options = array_shift($options); + foreach ($options as $option) { + $style->setOption($option); + } + } else { + return null; + } + } + + return $style; + } + + /** + * Applies current style from stack to text, if must be applied. + */ + private function applyCurrentStyle(string $text, string $current, int $width, int &$currentLineLength): string + { + if ('' === $text) { + return ''; + } + + if (!$width) { + return $this->isDecorated() ? $this->styleStack->getCurrent()->apply($text) : $text; + } + + if (!$currentLineLength && '' !== $current) { + $text = ltrim($text); + } + + if ($currentLineLength) { + $prefix = substr($text, 0, $i = $width - $currentLineLength)."\n"; + $text = substr($text, $i); + } else { + $prefix = ''; + } + + preg_match('~(\\n)$~', $text, $matches); + $text = $prefix.preg_replace('~([^\\n]{'.$width.'})\\ *~', "\$1\n", $text); + $text = rtrim($text, "\n").($matches[1] ?? ''); + + if (!$currentLineLength && '' !== $current && "\n" !== substr($current, -1)) { + $text = "\n".$text; + } + + $lines = explode("\n", $text); + + foreach ($lines as $line) { + $currentLineLength += \strlen($line); + if ($width <= $currentLineLength) { + $currentLineLength = 0; + } + } + + if ($this->isDecorated()) { + foreach ($lines as $i => $line) { + $lines[$i] = $this->styleStack->getCurrent()->apply($line); + } + } + + return implode("\n", $lines); + } +} diff --git a/vendor/symfony/console/Formatter/OutputFormatterInterface.php b/vendor/symfony/console/Formatter/OutputFormatterInterface.php new file mode 100644 index 0000000..8c50d41 --- /dev/null +++ b/vendor/symfony/console/Formatter/OutputFormatterInterface.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +/** + * Formatter interface for console output. + * + * @author Konstantin Kudryashov + */ +interface OutputFormatterInterface +{ + /** + * Sets the decorated flag. + */ + public function setDecorated(bool $decorated); + + /** + * Gets the decorated flag. + * + * @return bool true if the output will decorate messages, false otherwise + */ + public function isDecorated(); + + /** + * Sets a new style. + */ + public function setStyle(string $name, OutputFormatterStyleInterface $style); + + /** + * Checks if output formatter has style with specified name. + * + * @return bool + */ + public function hasStyle(string $name); + + /** + * Gets style options from style with specified name. + * + * @return OutputFormatterStyleInterface + * + * @throws \InvalidArgumentException When style isn't defined + */ + public function getStyle(string $name); + + /** + * Formats a message according to the given styles. + */ + public function format(?string $message); +} diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyle.php b/vendor/symfony/console/Formatter/OutputFormatterStyle.php new file mode 100644 index 0000000..c5d3ea1 --- /dev/null +++ b/vendor/symfony/console/Formatter/OutputFormatterStyle.php @@ -0,0 +1,196 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * Formatter style class for defining styles. + * + * @author Konstantin Kudryashov + */ +class OutputFormatterStyle implements OutputFormatterStyleInterface +{ + private static $availableForegroundColors = [ + 'black' => ['set' => 30, 'unset' => 39], + 'red' => ['set' => 31, 'unset' => 39], + 'green' => ['set' => 32, 'unset' => 39], + 'yellow' => ['set' => 33, 'unset' => 39], + 'blue' => ['set' => 34, 'unset' => 39], + 'magenta' => ['set' => 35, 'unset' => 39], + 'cyan' => ['set' => 36, 'unset' => 39], + 'white' => ['set' => 37, 'unset' => 39], + 'default' => ['set' => 39, 'unset' => 39], + ]; + private static $availableBackgroundColors = [ + 'black' => ['set' => 40, 'unset' => 49], + 'red' => ['set' => 41, 'unset' => 49], + 'green' => ['set' => 42, 'unset' => 49], + 'yellow' => ['set' => 43, 'unset' => 49], + 'blue' => ['set' => 44, 'unset' => 49], + 'magenta' => ['set' => 45, 'unset' => 49], + 'cyan' => ['set' => 46, 'unset' => 49], + 'white' => ['set' => 47, 'unset' => 49], + 'default' => ['set' => 49, 'unset' => 49], + ]; + private static $availableOptions = [ + 'bold' => ['set' => 1, 'unset' => 22], + 'underscore' => ['set' => 4, 'unset' => 24], + 'blink' => ['set' => 5, 'unset' => 25], + 'reverse' => ['set' => 7, 'unset' => 27], + 'conceal' => ['set' => 8, 'unset' => 28], + ]; + + private $foreground; + private $background; + private $href; + private $options = []; + private $handlesHrefGracefully; + + /** + * Initializes output formatter style. + * + * @param string|null $foreground The style foreground color name + * @param string|null $background The style background color name + */ + public function __construct(string $foreground = null, string $background = null, array $options = []) + { + if (null !== $foreground) { + $this->setForeground($foreground); + } + if (null !== $background) { + $this->setBackground($background); + } + if (\count($options)) { + $this->setOptions($options); + } + } + + /** + * {@inheritdoc} + */ + public function setForeground(string $color = null) + { + if (null === $color) { + $this->foreground = null; + + return; + } + + if (!isset(static::$availableForegroundColors[$color])) { + throw new InvalidArgumentException(sprintf('Invalid foreground color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableForegroundColors)))); + } + + $this->foreground = static::$availableForegroundColors[$color]; + } + + /** + * {@inheritdoc} + */ + public function setBackground(string $color = null) + { + if (null === $color) { + $this->background = null; + + return; + } + + if (!isset(static::$availableBackgroundColors[$color])) { + throw new InvalidArgumentException(sprintf('Invalid background color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableBackgroundColors)))); + } + + $this->background = static::$availableBackgroundColors[$color]; + } + + public function setHref(string $url): void + { + $this->href = $url; + } + + /** + * {@inheritdoc} + */ + public function setOption(string $option) + { + if (!isset(static::$availableOptions[$option])) { + throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions)))); + } + + if (!\in_array(static::$availableOptions[$option], $this->options)) { + $this->options[] = static::$availableOptions[$option]; + } + } + + /** + * {@inheritdoc} + */ + public function unsetOption(string $option) + { + if (!isset(static::$availableOptions[$option])) { + throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions)))); + } + + $pos = array_search(static::$availableOptions[$option], $this->options); + if (false !== $pos) { + unset($this->options[$pos]); + } + } + + /** + * {@inheritdoc} + */ + public function setOptions(array $options) + { + $this->options = []; + + foreach ($options as $option) { + $this->setOption($option); + } + } + + /** + * {@inheritdoc} + */ + public function apply(string $text) + { + $setCodes = []; + $unsetCodes = []; + + if (null === $this->handlesHrefGracefully) { + $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') && !getenv('KONSOLE_VERSION'); + } + + if (null !== $this->foreground) { + $setCodes[] = $this->foreground['set']; + $unsetCodes[] = $this->foreground['unset']; + } + if (null !== $this->background) { + $setCodes[] = $this->background['set']; + $unsetCodes[] = $this->background['unset']; + } + + foreach ($this->options as $option) { + $setCodes[] = $option['set']; + $unsetCodes[] = $option['unset']; + } + + if (null !== $this->href && $this->handlesHrefGracefully) { + $text = "\033]8;;$this->href\033\\$text\033]8;;\033\\"; + } + + if (0 === \count($setCodes)) { + return $text; + } + + return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes)); + } +} diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php b/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php new file mode 100644 index 0000000..b30560d --- /dev/null +++ b/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +/** + * Formatter style interface for defining styles. + * + * @author Konstantin Kudryashov + */ +interface OutputFormatterStyleInterface +{ + /** + * Sets style foreground color. + */ + public function setForeground(string $color = null); + + /** + * Sets style background color. + */ + public function setBackground(string $color = null); + + /** + * Sets some specific style option. + */ + public function setOption(string $option); + + /** + * Unsets some specific style option. + */ + public function unsetOption(string $option); + + /** + * Sets multiple style options at once. + */ + public function setOptions(array $options); + + /** + * Applies the style to a given text. + * + * @return string + */ + public function apply(string $text); +} diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php new file mode 100644 index 0000000..33f7d52 --- /dev/null +++ b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Contracts\Service\ResetInterface; + +/** + * @author Jean-François Simon + */ +class OutputFormatterStyleStack implements ResetInterface +{ + /** + * @var OutputFormatterStyleInterface[] + */ + private $styles; + + private $emptyStyle; + + public function __construct(OutputFormatterStyleInterface $emptyStyle = null) + { + $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle(); + $this->reset(); + } + + /** + * Resets stack (ie. empty internal arrays). + */ + public function reset() + { + $this->styles = []; + } + + /** + * Pushes a style in the stack. + */ + public function push(OutputFormatterStyleInterface $style) + { + $this->styles[] = $style; + } + + /** + * Pops a style from the stack. + * + * @return OutputFormatterStyleInterface + * + * @throws InvalidArgumentException When style tags incorrectly nested + */ + public function pop(OutputFormatterStyleInterface $style = null) + { + if (empty($this->styles)) { + return $this->emptyStyle; + } + + if (null === $style) { + return array_pop($this->styles); + } + + foreach (array_reverse($this->styles, true) as $index => $stackedStyle) { + if ($style->apply('') === $stackedStyle->apply('')) { + $this->styles = \array_slice($this->styles, 0, $index); + + return $stackedStyle; + } + } + + throw new InvalidArgumentException('Incorrectly nested style tag found.'); + } + + /** + * Computes current style with stacks top codes. + * + * @return OutputFormatterStyle + */ + public function getCurrent() + { + if (empty($this->styles)) { + return $this->emptyStyle; + } + + return $this->styles[\count($this->styles) - 1]; + } + + /** + * @return $this + */ + public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle) + { + $this->emptyStyle = $emptyStyle; + + return $this; + } + + /** + * @return OutputFormatterStyleInterface + */ + public function getEmptyStyle() + { + return $this->emptyStyle; + } +} diff --git a/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php b/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php new file mode 100644 index 0000000..42319ee --- /dev/null +++ b/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +/** + * Formatter interface for console output that supports word wrapping. + * + * @author Roland Franssen + */ +interface WrappableOutputFormatterInterface extends OutputFormatterInterface +{ + /** + * Formats a message according to the given styles, wrapping at `$width` (0 means no wrapping). + */ + public function formatAndWrap(?string $message, int $width); +} diff --git a/vendor/symfony/console/Helper/DebugFormatterHelper.php b/vendor/symfony/console/Helper/DebugFormatterHelper.php new file mode 100644 index 0000000..9d07ec2 --- /dev/null +++ b/vendor/symfony/console/Helper/DebugFormatterHelper.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +/** + * Helps outputting debug information when running an external program from a command. + * + * An external program can be a Process, an HTTP request, or anything else. + * + * @author Fabien Potencier + */ +class DebugFormatterHelper extends Helper +{ + private $colors = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default']; + private $started = []; + private $count = -1; + + /** + * Starts a debug formatting session. + * + * @return string + */ + public function start(string $id, string $message, string $prefix = 'RUN') + { + $this->started[$id] = ['border' => ++$this->count % \count($this->colors)]; + + return sprintf("%s %s %s\n", $this->getBorder($id), $prefix, $message); + } + + /** + * Adds progress to a formatting session. + * + * @return string + */ + public function progress(string $id, string $buffer, bool $error = false, string $prefix = 'OUT', string $errorPrefix = 'ERR') + { + $message = ''; + + if ($error) { + if (isset($this->started[$id]['out'])) { + $message .= "\n"; + unset($this->started[$id]['out']); + } + if (!isset($this->started[$id]['err'])) { + $message .= sprintf('%s %s ', $this->getBorder($id), $errorPrefix); + $this->started[$id]['err'] = true; + } + + $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $errorPrefix), $buffer); + } else { + if (isset($this->started[$id]['err'])) { + $message .= "\n"; + unset($this->started[$id]['err']); + } + if (!isset($this->started[$id]['out'])) { + $message .= sprintf('%s %s ', $this->getBorder($id), $prefix); + $this->started[$id]['out'] = true; + } + + $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $prefix), $buffer); + } + + return $message; + } + + /** + * Stops a formatting session. + * + * @return string + */ + public function stop(string $id, string $message, bool $successful, string $prefix = 'RES') + { + $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : ''; + + if ($successful) { + return sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); + } + + $message = sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); + + unset($this->started[$id]['out'], $this->started[$id]['err']); + + return $message; + } + + private function getBorder(string $id): string + { + return sprintf(' ', $this->colors[$this->started[$id]['border']]); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'debug_formatter'; + } +} diff --git a/vendor/symfony/console/Helper/DescriptorHelper.php b/vendor/symfony/console/Helper/DescriptorHelper.php new file mode 100644 index 0000000..f2ad9db --- /dev/null +++ b/vendor/symfony/console/Helper/DescriptorHelper.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Descriptor\DescriptorInterface; +use Symfony\Component\Console\Descriptor\JsonDescriptor; +use Symfony\Component\Console\Descriptor\MarkdownDescriptor; +use Symfony\Component\Console\Descriptor\TextDescriptor; +use Symfony\Component\Console\Descriptor\XmlDescriptor; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * This class adds helper method to describe objects in various formats. + * + * @author Jean-François Simon + */ +class DescriptorHelper extends Helper +{ + /** + * @var DescriptorInterface[] + */ + private $descriptors = []; + + public function __construct() + { + $this + ->register('txt', new TextDescriptor()) + ->register('xml', new XmlDescriptor()) + ->register('json', new JsonDescriptor()) + ->register('md', new MarkdownDescriptor()) + ; + } + + /** + * Describes an object if supported. + * + * Available options are: + * * format: string, the output format name + * * raw_text: boolean, sets output type as raw + * + * @throws InvalidArgumentException when the given format is not supported + */ + public function describe(OutputInterface $output, ?object $object, array $options = []) + { + $options = array_merge([ + 'raw_text' => false, + 'format' => 'txt', + ], $options); + + if (!isset($this->descriptors[$options['format']])) { + throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format'])); + } + + $descriptor = $this->descriptors[$options['format']]; + $descriptor->describe($output, $object, $options); + } + + /** + * Registers a descriptor. + * + * @return $this + */ + public function register(string $format, DescriptorInterface $descriptor) + { + $this->descriptors[$format] = $descriptor; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'descriptor'; + } +} diff --git a/vendor/symfony/console/Helper/Dumper.php b/vendor/symfony/console/Helper/Dumper.php new file mode 100644 index 0000000..b013b6c --- /dev/null +++ b/vendor/symfony/console/Helper/Dumper.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\VarDumper\Cloner\ClonerInterface; +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Dumper\CliDumper; + +/** + * @author Roland Franssen + */ +final class Dumper +{ + private $output; + private $dumper; + private $cloner; + private $handler; + + public function __construct(OutputInterface $output, CliDumper $dumper = null, ClonerInterface $cloner = null) + { + $this->output = $output; + $this->dumper = $dumper; + $this->cloner = $cloner; + + if (class_exists(CliDumper::class)) { + $this->handler = function ($var): string { + $dumper = $this->dumper ?? $this->dumper = new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR); + $dumper->setColors($this->output->isDecorated()); + + return rtrim($dumper->dump(($this->cloner ?? $this->cloner = new VarCloner())->cloneVar($var)->withRefHandles(false), true)); + }; + } else { + $this->handler = function ($var): string { + switch (true) { + case null === $var: + return 'null'; + case true === $var: + return 'true'; + case false === $var: + return 'false'; + case \is_string($var): + return '"'.$var.'"'; + default: + return rtrim(print_r($var, true)); + } + }; + } + } + + public function __invoke($var): string + { + return ($this->handler)($var); + } +} diff --git a/vendor/symfony/console/Helper/FormatterHelper.php b/vendor/symfony/console/Helper/FormatterHelper.php new file mode 100644 index 0000000..75c9b61 --- /dev/null +++ b/vendor/symfony/console/Helper/FormatterHelper.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Formatter\OutputFormatter; + +/** + * The Formatter class provides helpers to format messages. + * + * @author Fabien Potencier + */ +class FormatterHelper extends Helper +{ + /** + * Formats a message within a section. + * + * @return string The format section + */ + public function formatSection(string $section, string $message, string $style = 'info') + { + return sprintf('<%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 + * + * @return string The formatter message + */ + public function formatBlock($messages, string $style, bool $large = false) + { + if (!\is_array($messages)) { + $messages = [$messages]; + } + + $len = 0; + $lines = []; + foreach ($messages as $message) { + $message = OutputFormatter::escape($message); + $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); + $len = max($this->strlen($message) + ($large ? 4 : 2), $len); + } + + $messages = $large ? [str_repeat(' ', $len)] : []; + for ($i = 0; isset($lines[$i]); ++$i) { + $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i])); + } + if ($large) { + $messages[] = str_repeat(' ', $len); + } + + for ($i = 0; isset($messages[$i]); ++$i) { + $messages[$i] = sprintf('<%s>%s', $style, $messages[$i], $style); + } + + return implode("\n", $messages); + } + + /** + * Truncates a message to the given length. + * + * @return string + */ + public function truncate(string $message, int $length, string $suffix = '...') + { + $computedLength = $length - $this->strlen($suffix); + + if ($computedLength > $this->strlen($message)) { + return $message; + } + + if (false === $encoding = mb_detect_encoding($message, null, true)) { + return substr($message, 0, $length).$suffix; + } + + return mb_substr($message, 0, $length, $encoding).$suffix; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'formatter'; + } +} diff --git a/vendor/symfony/console/Helper/Helper.php b/vendor/symfony/console/Helper/Helper.php new file mode 100644 index 0000000..e52e315 --- /dev/null +++ b/vendor/symfony/console/Helper/Helper.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * Helper is the base class for all helper classes. + * + * @author Fabien Potencier + */ +abstract class Helper implements HelperInterface +{ + protected $helperSet = null; + + /** + * {@inheritdoc} + */ + public function setHelperSet(HelperSet $helperSet = null) + { + $this->helperSet = $helperSet; + } + + /** + * {@inheritdoc} + */ + public function getHelperSet() + { + return $this->helperSet; + } + + /** + * Returns the length of a string, using mb_strwidth if it is available. + * + * @return int The length of the string + */ + public static function strlen(?string $string) + { + if (false === $encoding = mb_detect_encoding($string, null, true)) { + return \strlen($string); + } + + return mb_strwidth($string, $encoding); + } + + /** + * Returns the subset of a string, using mb_substr if it is available. + * + * @return string The string subset + */ + public static function substr(string $string, int $from, int $length = null) + { + if (false === $encoding = mb_detect_encoding($string, null, true)) { + return substr($string, $from, $length); + } + + return mb_substr($string, $from, $length, $encoding); + } + + public static function formatTime($secs) + { + static $timeFormats = [ + [0, '< 1 sec'], + [1, '1 sec'], + [2, 'secs', 1], + [60, '1 min'], + [120, 'mins', 60], + [3600, '1 hr'], + [7200, 'hrs', 3600], + [86400, '1 day'], + [172800, 'days', 86400], + ]; + + foreach ($timeFormats as $index => $format) { + if ($secs >= $format[0]) { + if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0]) + || $index == \count($timeFormats) - 1 + ) { + if (2 == \count($format)) { + return $format[1]; + } + + return floor($secs / $format[2]).' '.$format[1]; + } + } + } + } + + public static function formatMemory(int $memory) + { + if ($memory >= 1024 * 1024 * 1024) { + return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024); + } + + if ($memory >= 1024 * 1024) { + return sprintf('%.1f MiB', $memory / 1024 / 1024); + } + + if ($memory >= 1024) { + return sprintf('%d KiB', $memory / 1024); + } + + return sprintf('%d B', $memory); + } + + public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string) + { + return self::strlen(self::removeDecoration($formatter, $string)); + } + + public static function removeDecoration(OutputFormatterInterface $formatter, $string) + { + $isDecorated = $formatter->isDecorated(); + $formatter->setDecorated(false); + // remove <...> formatting + $string = $formatter->format($string); + // remove already formatted characters + $string = preg_replace("/\033\[[^m]*m/", '', $string); + $formatter->setDecorated($isDecorated); + + return $string; + } +} diff --git a/vendor/symfony/console/Helper/HelperInterface.php b/vendor/symfony/console/Helper/HelperInterface.php new file mode 100644 index 0000000..1ce8235 --- /dev/null +++ b/vendor/symfony/console/Helper/HelperInterface.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +/** + * HelperInterface is the interface all helpers must implement. + * + * @author Fabien Potencier + */ +interface HelperInterface +{ + /** + * Sets the helper set associated with this helper. + */ + public function setHelperSet(HelperSet $helperSet = null); + + /** + * Gets the helper set associated with this helper. + * + * @return HelperSet A HelperSet instance + */ + public function getHelperSet(); + + /** + * Returns the canonical name of this helper. + * + * @return string The canonical name + */ + public function getName(); +} diff --git a/vendor/symfony/console/Helper/HelperSet.php b/vendor/symfony/console/Helper/HelperSet.php new file mode 100644 index 0000000..5c08a76 --- /dev/null +++ b/vendor/symfony/console/Helper/HelperSet.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * HelperSet represents a set of helpers to be used with a command. + * + * @author Fabien Potencier + */ +class HelperSet implements \IteratorAggregate +{ + /** + * @var Helper[] + */ + private $helpers = []; + private $command; + + /** + * @param Helper[] $helpers An array of helper + */ + public function __construct(array $helpers = []) + { + foreach ($helpers as $alias => $helper) { + $this->set($helper, \is_int($alias) ? null : $alias); + } + } + + public function set(HelperInterface $helper, string $alias = null) + { + $this->helpers[$helper->getName()] = $helper; + if (null !== $alias) { + $this->helpers[$alias] = $helper; + } + + $helper->setHelperSet($this); + } + + /** + * Returns true if the helper if defined. + * + * @return bool true if the helper is defined, false otherwise + */ + public function has(string $name) + { + return isset($this->helpers[$name]); + } + + /** + * Gets a helper value. + * + * @return HelperInterface The helper instance + * + * @throws InvalidArgumentException if the helper is not defined + */ + public function get(string $name) + { + if (!$this->has($name)) { + throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); + } + + return $this->helpers[$name]; + } + + 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; + } + + /** + * @return Helper[] + */ + public function getIterator() + { + return new \ArrayIterator($this->helpers); + } +} diff --git a/vendor/symfony/console/Helper/InputAwareHelper.php b/vendor/symfony/console/Helper/InputAwareHelper.php new file mode 100644 index 0000000..0d0dba2 --- /dev/null +++ b/vendor/symfony/console/Helper/InputAwareHelper.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Input\InputAwareInterface; +use Symfony\Component\Console\Input\InputInterface; + +/** + * An implementation of InputAwareInterface for Helpers. + * + * @author Wouter J + */ +abstract class InputAwareHelper extends Helper implements InputAwareInterface +{ + protected $input; + + /** + * {@inheritdoc} + */ + public function setInput(InputInterface $input) + { + $this->input = $input; + } +} diff --git a/vendor/symfony/console/Helper/ProcessHelper.php b/vendor/symfony/console/Helper/ProcessHelper.php new file mode 100644 index 0000000..944c593 --- /dev/null +++ b/vendor/symfony/console/Helper/ProcessHelper.php @@ -0,0 +1,144 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Process\Exception\ProcessFailedException; +use Symfony\Component\Process\Process; + +/** + * The ProcessHelper class provides helpers to run external processes. + * + * @author Fabien Potencier + * + * @final + */ +class ProcessHelper extends Helper +{ + /** + * Runs an external process. + * + * @param array|Process $cmd An instance of Process or an array of the command and arguments + * @param callable|null $callback A PHP callback to run whenever there is some + * output available on STDOUT or STDERR + * + * @return Process The process that ran + */ + public function run(OutputInterface $output, $cmd, string $error = null, callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process + { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + $formatter = $this->getHelperSet()->get('debug_formatter'); + + if ($cmd instanceof Process) { + $cmd = [$cmd]; + } + + if (!\is_array($cmd)) { + throw new \TypeError(sprintf('The "command" argument of "%s()" must be an array or a "%s" instance, "%s" given.', __METHOD__, Process::class, \is_object($cmd) ? \get_class($cmd) : \gettype($cmd))); + } + + if (\is_string($cmd[0] ?? null)) { + $process = new Process($cmd); + $cmd = []; + } elseif (($cmd[0] ?? null) instanceof Process) { + $process = $cmd[0]; + unset($cmd[0]); + } else { + throw new \InvalidArgumentException(sprintf('Invalid command provided to "%s()": the command should be an array whose first element is either the path to the binary to run or a "Process" object.', __METHOD__)); + } + + if ($verbosity <= $output->getVerbosity()) { + $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine()))); + } + + if ($output->isDebug()) { + $callback = $this->wrapCallback($output, $process, $callback); + } + + $process->run($callback, $cmd); + + if ($verbosity <= $output->getVerbosity()) { + $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode()); + $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful())); + } + + if (!$process->isSuccessful() && null !== $error) { + $output->writeln(sprintf('%s', $this->escapeString($error))); + } + + return $process; + } + + /** + * Runs the process. + * + * This is identical to run() except that an exception is thrown if the process + * exits with a non-zero exit code. + * + * @param string|Process $cmd An instance of Process or a command to run + * @param callable|null $callback A PHP callback to run whenever there is some + * output available on STDOUT or STDERR + * + * @return Process The process that ran + * + * @throws ProcessFailedException + * + * @see run() + */ + public function mustRun(OutputInterface $output, $cmd, string $error = null, callable $callback = null): Process + { + $process = $this->run($output, $cmd, $error, $callback); + + if (!$process->isSuccessful()) { + throw new ProcessFailedException($process); + } + + return $process; + } + + /** + * Wraps a Process callback to add debugging output. + */ + public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null): callable + { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + $formatter = $this->getHelperSet()->get('debug_formatter'); + + return function ($type, $buffer) use ($output, $process, $callback, $formatter) { + $output->write($formatter->progress(spl_object_hash($process), $this->escapeString($buffer), Process::ERR === $type)); + + if (null !== $callback) { + $callback($type, $buffer); + } + }; + } + + private function escapeString(string $str): string + { + return str_replace('<', '\\<', $str); + } + + /** + * {@inheritdoc} + */ + public function getName(): string + { + return 'process'; + } +} diff --git a/vendor/symfony/console/Helper/ProgressBar.php b/vendor/symfony/console/Helper/ProgressBar.php new file mode 100644 index 0000000..e4f0a99 --- /dev/null +++ b/vendor/symfony/console/Helper/ProgressBar.php @@ -0,0 +1,592 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\ConsoleSectionOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Terminal; + +/** + * The ProgressBar provides helpers to display progress output. + * + * @author Fabien Potencier + * @author Chris Jones + */ +final class ProgressBar +{ + private $barWidth = 28; + private $barChar; + private $emptyBarChar = '-'; + private $progressChar = '>'; + private $format; + private $internalFormat; + private $redrawFreq = 1; + private $writeCount; + private $lastWriteTime; + private $minSecondsBetweenRedraws = 0; + private $maxSecondsBetweenRedraws = 1; + private $output; + private $step = 0; + private $max; + private $startTime; + private $stepWidth; + private $percent = 0.0; + private $formatLineCount; + private $messages = []; + private $overwrite = true; + private $terminal; + private $previousMessage; + + private static $formatters; + private static $formats; + + /** + * @param int $max Maximum steps (0 if unknown) + */ + public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 0.1) + { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + $this->output = $output; + $this->setMaxSteps($max); + $this->terminal = new Terminal(); + + if (0 < $minSecondsBetweenRedraws) { + $this->redrawFreq = null; + $this->minSecondsBetweenRedraws = $minSecondsBetweenRedraws; + } + + if (!$this->output->isDecorated()) { + // disable overwrite when output does not support ANSI codes. + $this->overwrite = false; + + // set a reasonable redraw frequency so output isn't flooded + $this->redrawFreq = null; + } + + $this->startTime = time(); + } + + /** + * Sets a placeholder formatter for a given name. + * + * This method also allow you to override an existing placeholder. + * + * @param string $name The placeholder name (including the delimiter char like %) + * @param callable $callable A PHP callable + */ + public static function setPlaceholderFormatterDefinition(string $name, callable $callable): void + { + if (!self::$formatters) { + self::$formatters = self::initPlaceholderFormatters(); + } + + self::$formatters[$name] = $callable; + } + + /** + * Gets the placeholder formatter for a given name. + * + * @param string $name The placeholder name (including the delimiter char like %) + * + * @return callable|null A PHP callable + */ + public static function getPlaceholderFormatterDefinition(string $name): ?callable + { + if (!self::$formatters) { + self::$formatters = self::initPlaceholderFormatters(); + } + + return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; + } + + /** + * Sets a format for a given name. + * + * This method also allow you to override an existing format. + * + * @param string $name The format name + * @param string $format A format string + */ + public static function setFormatDefinition(string $name, string $format): void + { + if (!self::$formats) { + self::$formats = self::initFormats(); + } + + self::$formats[$name] = $format; + } + + /** + * Gets the format for a given name. + * + * @param string $name The format name + * + * @return string|null A format string + */ + public static function getFormatDefinition(string $name): ?string + { + if (!self::$formats) { + self::$formats = self::initFormats(); + } + + return isset(self::$formats[$name]) ? self::$formats[$name] : null; + } + + /** + * Associates a text with a named placeholder. + * + * The text is displayed when the progress bar is rendered but only + * when the corresponding placeholder is part of the custom format line + * (by wrapping the name with %). + * + * @param string $message The text to associate with the placeholder + * @param string $name The name of the placeholder + */ + public function setMessage(string $message, string $name = 'message') + { + $this->messages[$name] = $message; + } + + public function getMessage(string $name = 'message') + { + return $this->messages[$name]; + } + + public function getStartTime(): int + { + return $this->startTime; + } + + public function getMaxSteps(): int + { + return $this->max; + } + + public function getProgress(): int + { + return $this->step; + } + + private function getStepWidth(): int + { + return $this->stepWidth; + } + + public function getProgressPercent(): float + { + return $this->percent; + } + + public function getBarOffset(): int + { + return floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? min(5, $this->barWidth / 15) * $this->writeCount : $this->step) % $this->barWidth); + } + + public function setBarWidth(int $size) + { + $this->barWidth = max(1, $size); + } + + public function getBarWidth(): int + { + return $this->barWidth; + } + + public function setBarCharacter(string $char) + { + $this->barChar = $char; + } + + public function getBarCharacter(): string + { + if (null === $this->barChar) { + return $this->max ? '=' : $this->emptyBarChar; + } + + return $this->barChar; + } + + public function setEmptyBarCharacter(string $char) + { + $this->emptyBarChar = $char; + } + + public function getEmptyBarCharacter(): string + { + return $this->emptyBarChar; + } + + public function setProgressCharacter(string $char) + { + $this->progressChar = $char; + } + + public function getProgressCharacter(): string + { + return $this->progressChar; + } + + public function setFormat(string $format) + { + $this->format = null; + $this->internalFormat = $format; + } + + /** + * Sets the redraw frequency. + * + * @param int|float $freq The frequency in steps + */ + public function setRedrawFrequency(?int $freq) + { + $this->redrawFreq = null !== $freq ? max(1, $freq) : null; + } + + public function minSecondsBetweenRedraws(float $seconds): void + { + $this->minSecondsBetweenRedraws = $seconds; + } + + public function maxSecondsBetweenRedraws(float $seconds): void + { + $this->maxSecondsBetweenRedraws = $seconds; + } + + /** + * Returns an iterator that will automatically update the progress bar when iterated. + * + * @param int|null $max Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable + */ + public function iterate(iterable $iterable, int $max = null): iterable + { + $this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0)); + + foreach ($iterable as $key => $value) { + yield $key => $value; + + $this->advance(); + } + + $this->finish(); + } + + /** + * Starts the progress output. + * + * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged + */ + public function start(int $max = null) + { + $this->startTime = time(); + $this->step = 0; + $this->percent = 0.0; + + if (null !== $max) { + $this->setMaxSteps($max); + } + + $this->display(); + } + + /** + * Advances the progress output X steps. + * + * @param int $step Number of steps to advance + */ + public function advance(int $step = 1) + { + $this->setProgress($this->step + $step); + } + + /** + * Sets whether to overwrite the progressbar, false for new line. + */ + public function setOverwrite(bool $overwrite) + { + $this->overwrite = $overwrite; + } + + public function setProgress(int $step) + { + if ($this->max && $step > $this->max) { + $this->max = $step; + } elseif ($step < 0) { + $step = 0; + } + + $redrawFreq = $this->redrawFreq ?? (($this->max ?: 10) / 10); + $prevPeriod = (int) ($this->step / $redrawFreq); + $currPeriod = (int) ($step / $redrawFreq); + $this->step = $step; + $this->percent = $this->max ? (float) $this->step / $this->max : 0; + $timeInterval = microtime(true) - $this->lastWriteTime; + + // Draw regardless of other limits + if ($this->max === $step) { + $this->display(); + + return; + } + + // Throttling + if ($timeInterval < $this->minSecondsBetweenRedraws) { + return; + } + + // Draw each step period, but not too late + if ($prevPeriod !== $currPeriod || $timeInterval >= $this->maxSecondsBetweenRedraws) { + $this->display(); + } + } + + public function setMaxSteps(int $max) + { + $this->format = null; + $this->max = max(0, $max); + $this->stepWidth = $this->max ? Helper::strlen((string) $this->max) : 4; + } + + /** + * Finishes the progress output. + */ + public function finish(): void + { + if (!$this->max) { + $this->max = $this->step; + } + + if ($this->step === $this->max && !$this->overwrite) { + // prevent double 100% output + return; + } + + $this->setProgress($this->max); + } + + /** + * Outputs the current progress string. + */ + public function display(): void + { + if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { + return; + } + + if (null === $this->format) { + $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat()); + } + + $this->overwrite($this->buildLine()); + } + + /** + * Removes the progress bar from the current line. + * + * This is useful if you wish to write some output + * while a progress bar is running. + * Call display() to show the progress bar again. + */ + public function clear(): void + { + if (!$this->overwrite) { + return; + } + + if (null === $this->format) { + $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat()); + } + + $this->overwrite(''); + } + + private function setRealFormat(string $format) + { + // try to use the _nomax variant if available + if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) { + $this->format = self::getFormatDefinition($format.'_nomax'); + } elseif (null !== self::getFormatDefinition($format)) { + $this->format = self::getFormatDefinition($format); + } else { + $this->format = $format; + } + + $this->formatLineCount = substr_count($this->format, "\n"); + } + + /** + * Overwrites a previous message to the output. + */ + private function overwrite(string $message): void + { + if ($this->previousMessage === $message) { + return; + } + + $originalMessage = $message; + + if ($this->overwrite) { + if (null !== $this->previousMessage) { + if ($this->output instanceof ConsoleSectionOutput) { + $lines = floor(Helper::strlen($message) / $this->terminal->getWidth()) + $this->formatLineCount + 1; + $this->output->clear($lines); + } else { + // Erase previous lines + if ($this->formatLineCount > 0) { + $message = str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount).$message; + } + + // Move the cursor to the beginning of the line and erase the line + $message = "\x0D\x1B[2K$message"; + } + } + } elseif ($this->step > 0) { + $message = PHP_EOL.$message; + } + + $this->previousMessage = $originalMessage; + $this->lastWriteTime = microtime(true); + + $this->output->write($message); + ++$this->writeCount; + } + + private function determineBestFormat(): string + { + switch ($this->output->getVerbosity()) { + // OutputInterface::VERBOSITY_QUIET: display is disabled anyway + case OutputInterface::VERBOSITY_VERBOSE: + return $this->max ? 'verbose' : 'verbose_nomax'; + case OutputInterface::VERBOSITY_VERY_VERBOSE: + return $this->max ? 'very_verbose' : 'very_verbose_nomax'; + case OutputInterface::VERBOSITY_DEBUG: + return $this->max ? 'debug' : 'debug_nomax'; + default: + return $this->max ? 'normal' : 'normal_nomax'; + } + } + + private static function initPlaceholderFormatters(): array + { + return [ + 'bar' => function (self $bar, OutputInterface $output) { + $completeBars = $bar->getBarOffset(); + $display = str_repeat($bar->getBarCharacter(), $completeBars); + if ($completeBars < $bar->getBarWidth()) { + $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter()); + $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars); + } + + return $display; + }, + 'elapsed' => function (self $bar) { + return Helper::formatTime(time() - $bar->getStartTime()); + }, + 'remaining' => function (self $bar) { + if (!$bar->getMaxSteps()) { + throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.'); + } + + if (!$bar->getProgress()) { + $remaining = 0; + } else { + $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress())); + } + + return Helper::formatTime($remaining); + }, + 'estimated' => function (self $bar) { + if (!$bar->getMaxSteps()) { + throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.'); + } + + if (!$bar->getProgress()) { + $estimated = 0; + } else { + $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps()); + } + + return Helper::formatTime($estimated); + }, + 'memory' => function (self $bar) { + return Helper::formatMemory(memory_get_usage(true)); + }, + 'current' => function (self $bar) { + return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT); + }, + 'max' => function (self $bar) { + return $bar->getMaxSteps(); + }, + 'percent' => function (self $bar) { + return floor($bar->getProgressPercent() * 100); + }, + ]; + } + + private static function initFormats(): array + { + return [ + 'normal' => ' %current%/%max% [%bar%] %percent:3s%%', + 'normal_nomax' => ' %current% [%bar%]', + + 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%', + 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', + + 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%', + 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', + + 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%', + 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%', + ]; + } + + private function buildLine(): string + { + $regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i"; + $callback = function ($matches) { + if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) { + $text = $formatter($this, $this->output); + } elseif (isset($this->messages[$matches[1]])) { + $text = $this->messages[$matches[1]]; + } else { + return $matches[0]; + } + + if (isset($matches[2])) { + $text = sprintf('%'.$matches[2], $text); + } + + return $text; + }; + $line = preg_replace_callback($regex, $callback, $this->format); + + // gets string length for each sub line with multiline format + $linesLength = array_map(function ($subLine) { + return Helper::strlenWithoutDecoration($this->output->getFormatter(), rtrim($subLine, "\r")); + }, explode("\n", $line)); + + $linesWidth = max($linesLength); + + $terminalWidth = $this->terminal->getWidth(); + if ($linesWidth <= $terminalWidth) { + return $line; + } + + $this->setBarWidth($this->barWidth - $linesWidth + $terminalWidth); + + return preg_replace_callback($regex, $callback, $this->format); + } +} diff --git a/vendor/symfony/console/Helper/ProgressIndicator.php b/vendor/symfony/console/Helper/ProgressIndicator.php new file mode 100644 index 0000000..81cb783 --- /dev/null +++ b/vendor/symfony/console/Helper/ProgressIndicator.php @@ -0,0 +1,254 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Kevin Bond + */ +class ProgressIndicator +{ + private $output; + private $startTime; + private $format; + private $message; + private $indicatorValues; + private $indicatorCurrent; + private $indicatorChangeInterval; + private $indicatorUpdateTime; + private $started = false; + + private static $formatters; + private static $formats; + + /** + * @param int $indicatorChangeInterval Change interval in milliseconds + * @param array|null $indicatorValues Animated indicator characters + */ + public function __construct(OutputInterface $output, string $format = null, int $indicatorChangeInterval = 100, array $indicatorValues = null) + { + $this->output = $output; + + if (null === $format) { + $format = $this->determineBestFormat(); + } + + if (null === $indicatorValues) { + $indicatorValues = ['-', '\\', '|', '/']; + } + + $indicatorValues = array_values($indicatorValues); + + if (2 > \count($indicatorValues)) { + throw new InvalidArgumentException('Must have at least 2 indicator value characters.'); + } + + $this->format = self::getFormatDefinition($format); + $this->indicatorChangeInterval = $indicatorChangeInterval; + $this->indicatorValues = $indicatorValues; + $this->startTime = time(); + } + + /** + * Sets the current indicator message. + */ + public function setMessage(?string $message) + { + $this->message = $message; + + $this->display(); + } + + /** + * Starts the indicator output. + */ + public function start(string $message) + { + if ($this->started) { + throw new LogicException('Progress indicator already started.'); + } + + $this->message = $message; + $this->started = true; + $this->startTime = time(); + $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval; + $this->indicatorCurrent = 0; + + $this->display(); + } + + /** + * Advances the indicator. + */ + public function advance() + { + if (!$this->started) { + throw new LogicException('Progress indicator has not yet been started.'); + } + + if (!$this->output->isDecorated()) { + return; + } + + $currentTime = $this->getCurrentTimeInMilliseconds(); + + if ($currentTime < $this->indicatorUpdateTime) { + return; + } + + $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval; + ++$this->indicatorCurrent; + + $this->display(); + } + + /** + * Finish the indicator with message. + * + * @param $message + */ + public function finish(string $message) + { + if (!$this->started) { + throw new LogicException('Progress indicator has not yet been started.'); + } + + $this->message = $message; + $this->display(); + $this->output->writeln(''); + $this->started = false; + } + + /** + * Gets the format for a given name. + * + * @return string|null A format string + */ + public static function getFormatDefinition(string $name) + { + if (!self::$formats) { + self::$formats = self::initFormats(); + } + + return isset(self::$formats[$name]) ? self::$formats[$name] : null; + } + + /** + * Sets a placeholder formatter for a given name. + * + * This method also allow you to override an existing placeholder. + */ + public static function setPlaceholderFormatterDefinition(string $name, callable $callable) + { + if (!self::$formatters) { + self::$formatters = self::initPlaceholderFormatters(); + } + + self::$formatters[$name] = $callable; + } + + /** + * Gets the placeholder formatter for a given name (including the delimiter char like %). + * + * @return callable|null A PHP callable + */ + public static function getPlaceholderFormatterDefinition(string $name) + { + if (!self::$formatters) { + self::$formatters = self::initPlaceholderFormatters(); + } + + return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; + } + + private function display() + { + if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { + return; + } + + $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) { + if ($formatter = self::getPlaceholderFormatterDefinition($matches[1])) { + return $formatter($this); + } + + return $matches[0]; + }, $this->format)); + } + + private function determineBestFormat(): string + { + switch ($this->output->getVerbosity()) { + // OutputInterface::VERBOSITY_QUIET: display is disabled anyway + case OutputInterface::VERBOSITY_VERBOSE: + return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi'; + case OutputInterface::VERBOSITY_VERY_VERBOSE: + case OutputInterface::VERBOSITY_DEBUG: + return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi'; + default: + return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi'; + } + } + + /** + * Overwrites a previous message to the output. + */ + private function overwrite(string $message) + { + if ($this->output->isDecorated()) { + $this->output->write("\x0D\x1B[2K"); + $this->output->write($message); + } else { + $this->output->writeln($message); + } + } + + private function getCurrentTimeInMilliseconds(): float + { + return round(microtime(true) * 1000); + } + + private static function initPlaceholderFormatters(): array + { + return [ + 'indicator' => function (self $indicator) { + return $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)]; + }, + 'message' => function (self $indicator) { + return $indicator->message; + }, + 'elapsed' => function (self $indicator) { + return Helper::formatTime(time() - $indicator->startTime); + }, + 'memory' => function () { + return Helper::formatMemory(memory_get_usage(true)); + }, + ]; + } + + private static function initFormats(): array + { + return [ + 'normal' => ' %indicator% %message%', + 'normal_no_ansi' => ' %message%', + + 'verbose' => ' %indicator% %message% (%elapsed:6s%)', + 'verbose_no_ansi' => ' %message% (%elapsed:6s%)', + + 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)', + 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)', + ]; + } +} diff --git a/vendor/symfony/console/Helper/QuestionHelper.php b/vendor/symfony/console/Helper/QuestionHelper.php new file mode 100644 index 0000000..594a291 --- /dev/null +++ b/vendor/symfony/console/Helper/QuestionHelper.php @@ -0,0 +1,485 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\OutputFormatterStyle; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\StreamableInputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\ConsoleSectionOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Terminal; + +/** + * The QuestionHelper class provides helpers to interact with the user. + * + * @author Fabien Potencier + */ +class QuestionHelper extends Helper +{ + private $inputStream; + private static $shell; + private static $stty; + + /** + * Asks a question to the user. + * + * @return mixed The user answer + * + * @throws RuntimeException If there is no data to read in the input stream + */ + public function ask(InputInterface $input, OutputInterface $output, Question $question) + { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + if (!$input->isInteractive()) { + $default = $question->getDefault(); + + if (null === $default) { + return $default; + } + + if ($validator = $question->getValidator()) { + return \call_user_func($question->getValidator(), $default); + } elseif ($question instanceof ChoiceQuestion) { + $choices = $question->getChoices(); + + if (!$question->isMultiselect()) { + return isset($choices[$default]) ? $choices[$default] : $default; + } + + $default = explode(',', $default); + foreach ($default as $k => $v) { + $v = $question->isTrimmable() ? trim($v) : $v; + $default[$k] = isset($choices[$v]) ? $choices[$v] : $v; + } + } + + return $default; + } + + if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) { + $this->inputStream = $stream; + } + + if (!$question->getValidator()) { + return $this->doAsk($output, $question); + } + + $interviewer = function () use ($output, $question) { + return $this->doAsk($output, $question); + }; + + return $this->validateAttempts($interviewer, $output, $question); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'question'; + } + + /** + * Prevents usage of stty. + */ + public static function disableStty() + { + self::$stty = false; + } + + /** + * Asks the question to the user. + * + * @return bool|mixed|string|null + * + * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden + */ + private function doAsk(OutputInterface $output, Question $question) + { + $this->writePrompt($output, $question); + + $inputStream = $this->inputStream ?: STDIN; + $autocomplete = $question->getAutocompleterCallback(); + + if (null === $autocomplete || !Terminal::hasSttyAvailable()) { + $ret = false; + if ($question->isHidden()) { + try { + $hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable()); + $ret = $question->isTrimmable() ? trim($hiddenResponse) : $hiddenResponse; + } catch (RuntimeException $e) { + if (!$question->isHiddenFallback()) { + throw $e; + } + } + } + + if (false === $ret) { + $ret = fgets($inputStream, 4096); + if (false === $ret) { + throw new RuntimeException('Aborted.'); + } + if ($question->isTrimmable()) { + $ret = trim($ret); + } + } + } else { + $autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete); + $ret = $question->isTrimmable() ? trim($autocomplete) : $autocomplete; + } + + if ($output instanceof ConsoleSectionOutput) { + $output->addContent($ret); + } + + $ret = \strlen($ret) > 0 ? $ret : $question->getDefault(); + + if ($normalizer = $question->getNormalizer()) { + return $normalizer($ret); + } + + return $ret; + } + + /** + * Outputs the question prompt. + */ + protected function writePrompt(OutputInterface $output, Question $question) + { + $message = $question->getQuestion(); + + if ($question instanceof ChoiceQuestion) { + $output->writeln(array_merge([ + $question->getQuestion(), + ], $this->formatChoiceQuestionChoices($question, 'info'))); + + $message = $question->getPrompt(); + } + + $output->write($message); + } + + /** + * @return string[] + */ + protected function formatChoiceQuestionChoices(ChoiceQuestion $question, string $tag) + { + $messages = []; + + $maxWidth = max(array_map('self::strlen', array_keys($choices = $question->getChoices()))); + + foreach ($choices as $key => $value) { + $padding = str_repeat(' ', $maxWidth - self::strlen($key)); + + $messages[] = sprintf(" [<$tag>%s$padding] %s", $key, $value); + } + + return $messages; + } + + /** + * Outputs an error message. + */ + protected function writeError(OutputInterface $output, \Exception $error) + { + if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) { + $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'); + } else { + $message = ''.$error->getMessage().''; + } + + $output->writeln($message); + } + + /** + * Autocompletes a question. + * + * @param resource $inputStream + */ + private function autocomplete(OutputInterface $output, Question $question, $inputStream, callable $autocomplete): string + { + $fullChoice = ''; + $ret = ''; + + $i = 0; + $ofs = -1; + $matches = $autocomplete($ret); + $numMatches = \count($matches); + + $sttyMode = shell_exec('stty -g'); + + // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) + shell_exec('stty -icanon -echo'); + + // Add highlighted text style + $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); + + // Read a keypress + while (!feof($inputStream)) { + $c = fread($inputStream, 1); + + // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false. + if (false === $c || ('' === $ret && '' === $c && null === $question->getDefault())) { + shell_exec(sprintf('stty %s', $sttyMode)); + throw new RuntimeException('Aborted.'); + } elseif ("\177" === $c) { // Backspace Character + if (0 === $numMatches && 0 !== $i) { + --$i; + $fullChoice = self::substr($fullChoice, 0, $i); + // Move cursor backwards + $output->write("\033[1D"); + } + + if (0 === $i) { + $ofs = -1; + $matches = $autocomplete($ret); + $numMatches = \count($matches); + } else { + $numMatches = 0; + } + + // Pop the last character off the end of our string + $ret = self::substr($ret, 0, $i); + } elseif ("\033" === $c) { + // Did we read an escape sequence? + $c .= fread($inputStream, 2); + + // A = Up Arrow. B = Down Arrow + if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) { + if ('A' === $c[2] && -1 === $ofs) { + $ofs = 0; + } + + if (0 === $numMatches) { + continue; + } + + $ofs += ('A' === $c[2]) ? -1 : 1; + $ofs = ($numMatches + $ofs) % $numMatches; + } + } elseif (\ord($c) < 32) { + if ("\t" === $c || "\n" === $c) { + if ($numMatches > 0 && -1 !== $ofs) { + $ret = (string) $matches[$ofs]; + // Echo out remaining chars for current match + $remainingCharacters = substr($ret, \strlen(trim($this->mostRecentlyEnteredValue($fullChoice)))); + $output->write($remainingCharacters); + $fullChoice .= $remainingCharacters; + $i = self::strlen($fullChoice); + + $matches = array_filter( + $autocomplete($ret), + function ($match) use ($ret) { + return '' === $ret || 0 === strpos($match, $ret); + } + ); + $numMatches = \count($matches); + $ofs = -1; + } + + if ("\n" === $c) { + $output->write($c); + break; + } + + $numMatches = 0; + } + + continue; + } else { + if ("\x80" <= $c) { + $c .= fread($inputStream, ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3][$c & "\xF0"]); + } + + $output->write($c); + $ret .= $c; + $fullChoice .= $c; + ++$i; + + $tempRet = $ret; + + if ($question instanceof ChoiceQuestion && $question->isMultiselect()) { + $tempRet = $this->mostRecentlyEnteredValue($fullChoice); + } + + $numMatches = 0; + $ofs = 0; + + foreach ($autocomplete($ret) as $value) { + // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) + if (0 === strpos($value, $tempRet)) { + $matches[$numMatches++] = $value; + } + } + } + + // Erase characters from cursor to end of line + $output->write("\033[K"); + + if ($numMatches > 0 && -1 !== $ofs) { + // Save cursor position + $output->write("\0337"); + // Write highlighted text, complete the partially entered response + $charactersEntered = \strlen(trim($this->mostRecentlyEnteredValue($fullChoice))); + $output->write(''.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $charactersEntered)).''); + // Restore cursor position + $output->write("\0338"); + } + } + + // Reset stty so it behaves normally again + shell_exec(sprintf('stty %s', $sttyMode)); + + return $fullChoice; + } + + private function mostRecentlyEnteredValue(string $entered): string + { + // Determine the most recent value that the user entered + if (false === strpos($entered, ',')) { + return $entered; + } + + $choices = explode(',', $entered); + if (\strlen($lastChoice = trim($choices[\count($choices) - 1])) > 0) { + return $lastChoice; + } + + return $entered; + } + + /** + * Gets a hidden response from user. + * + * @param resource $inputStream The handler resource + * @param bool $trimmable Is the answer trimmable + * + * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden + */ + private function getHiddenResponse(OutputInterface $output, $inputStream, bool $trimmable = true): string + { + if ('\\' === \DIRECTORY_SEPARATOR) { + $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; + + // handle code running from a phar + if ('phar:' === substr(__FILE__, 0, 5)) { + $tmpExe = sys_get_temp_dir().'/hiddeninput.exe'; + copy($exe, $tmpExe); + $exe = $tmpExe; + } + + $sExec = shell_exec($exe); + $value = $trimmable ? rtrim($sExec) : $sExec; + $output->writeln(''); + + if (isset($tmpExe)) { + unlink($tmpExe); + } + + return $value; + } + + if (Terminal::hasSttyAvailable()) { + $sttyMode = shell_exec('stty -g'); + + shell_exec('stty -echo'); + $value = fgets($inputStream, 4096); + shell_exec(sprintf('stty %s', $sttyMode)); + + if (false === $value) { + throw new RuntimeException('Aborted.'); + } + if ($trimmable) { + $value = trim($value); + } + $output->writeln(''); + + return $value; + } + + if (false !== $shell = $this->getShell()) { + $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword'; + $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); + $sCommand = shell_exec($command); + $value = $trimmable ? rtrim($sCommand) : $sCommand; + $output->writeln(''); + + return $value; + } + + throw new RuntimeException('Unable to hide the response.'); + } + + /** + * Validates an attempt. + * + * @param callable $interviewer A callable that will ask for a question and return the result + * + * @return mixed The validated response + * + * @throws \Exception In case the max number of attempts has been reached and no valid response has been given + */ + private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question) + { + $error = null; + $attempts = $question->getMaxAttempts(); + while (null === $attempts || $attempts--) { + if (null !== $error) { + $this->writeError($output, $error); + } + + try { + return $question->getValidator()($interviewer()); + } catch (RuntimeException $e) { + throw $e; + } catch (\Exception $error) { + } + } + + throw $error; + } + + /** + * Returns a valid unix shell. + * + * @return string|bool The valid shell name, false in case no valid shell is found + */ + private function getShell() + { + if (null !== self::$shell) { + return self::$shell; + } + + self::$shell = false; + + if (file_exists('/usr/bin/env')) { + // handle other OSs with bash/zsh/ksh/csh if available to hide the answer + $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null"; + foreach (['bash', 'zsh', 'ksh', 'csh'] as $sh) { + if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) { + self::$shell = $sh; + break; + } + } + } + + return self::$shell; + } +} diff --git a/vendor/symfony/console/Helper/SymfonyQuestionHelper.php b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php new file mode 100644 index 0000000..e4e87b2 --- /dev/null +++ b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Symfony Style Guide compliant question helper. + * + * @author Kevin Bond + */ +class SymfonyQuestionHelper extends QuestionHelper +{ + /** + * {@inheritdoc} + */ + protected function writePrompt(OutputInterface $output, Question $question) + { + $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion()); + $default = $question->getDefault(); + + switch (true) { + case null === $default: + $text = sprintf(' %s:', $text); + + break; + + case $question instanceof ConfirmationQuestion: + $text = sprintf(' %s (yes/no) [%s]:', $text, $default ? 'yes' : 'no'); + + break; + + case $question instanceof ChoiceQuestion && $question->isMultiselect(): + $choices = $question->getChoices(); + $default = explode(',', $default); + + foreach ($default as $key => $value) { + $default[$key] = $choices[trim($value)]; + } + + $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape(implode(', ', $default))); + + break; + + case $question instanceof ChoiceQuestion: + $choices = $question->getChoices(); + $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape(isset($choices[$default]) ? $choices[$default] : $default)); + + break; + + default: + $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape($default)); + } + + $output->writeln($text); + + $prompt = ' > '; + + if ($question instanceof ChoiceQuestion) { + $output->writeln($this->formatChoiceQuestionChoices($question, 'comment')); + + $prompt = $question->getPrompt(); + } + + $output->write($prompt); + } + + /** + * {@inheritdoc} + */ + protected function writeError(OutputInterface $output, \Exception $error) + { + if ($output instanceof SymfonyStyle) { + $output->newLine(); + $output->error($error->getMessage()); + + return; + } + + parent::writeError($output, $error); + } +} diff --git a/vendor/symfony/console/Helper/Table.php b/vendor/symfony/console/Helper/Table.php new file mode 100644 index 0000000..0a64110 --- /dev/null +++ b/vendor/symfony/console/Helper/Table.php @@ -0,0 +1,834 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface; +use Symfony\Component\Console\Output\ConsoleSectionOutput; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Provides helpers to display a table. + * + * @author Fabien Potencier + * @author Саша Стаменковић + * @author Abdellatif Ait boudad + * @author Max Grigorian + * @author Dany Maillard + */ +class Table +{ + private const SEPARATOR_TOP = 0; + private const SEPARATOR_TOP_BOTTOM = 1; + private const SEPARATOR_MID = 2; + private const SEPARATOR_BOTTOM = 3; + private const BORDER_OUTSIDE = 0; + private const BORDER_INSIDE = 1; + + private $headerTitle; + private $footerTitle; + + /** + * Table headers. + */ + private $headers = []; + + /** + * Table rows. + */ + private $rows = []; + private $horizontal = false; + + /** + * Column widths cache. + */ + private $effectiveColumnWidths = []; + + /** + * Number of columns cache. + * + * @var int + */ + private $numberOfColumns; + + /** + * @var OutputInterface + */ + private $output; + + /** + * @var TableStyle + */ + private $style; + + /** + * @var array + */ + private $columnStyles = []; + + /** + * User set column widths. + * + * @var array + */ + private $columnWidths = []; + private $columnMaxWidths = []; + + private static $styles; + + private $rendered = false; + + public function __construct(OutputInterface $output) + { + $this->output = $output; + + if (!self::$styles) { + self::$styles = self::initStyles(); + } + + $this->setStyle('default'); + } + + /** + * Sets a style definition. + */ + public static function setStyleDefinition(string $name, TableStyle $style) + { + if (!self::$styles) { + self::$styles = self::initStyles(); + } + + self::$styles[$name] = $style; + } + + /** + * Gets a style definition by name. + * + * @return TableStyle + */ + public static function getStyleDefinition(string $name) + { + if (!self::$styles) { + self::$styles = self::initStyles(); + } + + if (isset(self::$styles[$name])) { + return self::$styles[$name]; + } + + throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); + } + + /** + * Sets table style. + * + * @param TableStyle|string $name The style name or a TableStyle instance + * + * @return $this + */ + public function setStyle($name) + { + $this->style = $this->resolveStyle($name); + + return $this; + } + + /** + * Gets the current table style. + * + * @return TableStyle + */ + public function getStyle() + { + return $this->style; + } + + /** + * Sets table column style. + * + * @param TableStyle|string $name The style name or a TableStyle instance + * + * @return $this + */ + public function setColumnStyle(int $columnIndex, $name) + { + $this->columnStyles[$columnIndex] = $this->resolveStyle($name); + + return $this; + } + + /** + * Gets the current style for a column. + * + * If style was not set, it returns the global table style. + * + * @return TableStyle + */ + public function getColumnStyle(int $columnIndex) + { + return $this->columnStyles[$columnIndex] ?? $this->getStyle(); + } + + /** + * Sets the minimum width of a column. + * + * @return $this + */ + public function setColumnWidth(int $columnIndex, int $width) + { + $this->columnWidths[$columnIndex] = $width; + + return $this; + } + + /** + * Sets the minimum width of all columns. + * + * @return $this + */ + public function setColumnWidths(array $widths) + { + $this->columnWidths = []; + foreach ($widths as $index => $width) { + $this->setColumnWidth($index, $width); + } + + return $this; + } + + /** + * Sets the maximum width of a column. + * + * Any cell within this column which contents exceeds the specified width will be wrapped into multiple lines, while + * formatted strings are preserved. + * + * @return $this + */ + public function setColumnMaxWidth(int $columnIndex, int $width): self + { + if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) { + throw new \LogicException(sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, \get_class($this->output->getFormatter()))); + } + + $this->columnMaxWidths[$columnIndex] = $width; + + return $this; + } + + public function setHeaders(array $headers) + { + $headers = array_values($headers); + if (!empty($headers) && !\is_array($headers[0])) { + $headers = [$headers]; + } + + $this->headers = $headers; + + return $this; + } + + public function setRows(array $rows) + { + $this->rows = []; + + return $this->addRows($rows); + } + + public function addRows(array $rows) + { + foreach ($rows as $row) { + $this->addRow($row); + } + + return $this; + } + + public function addRow($row) + { + if ($row instanceof TableSeparator) { + $this->rows[] = $row; + + return $this; + } + + if (!\is_array($row)) { + throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.'); + } + + $this->rows[] = array_values($row); + + return $this; + } + + /** + * Adds a row to the table, and re-renders the table. + */ + public function appendRow($row): self + { + if (!$this->output instanceof ConsoleSectionOutput) { + throw new RuntimeException(sprintf('Output should be an instance of "%s" when calling "%s".', ConsoleSectionOutput::class, __METHOD__)); + } + + if ($this->rendered) { + $this->output->clear($this->calculateRowCount()); + } + + $this->addRow($row); + $this->render(); + + return $this; + } + + public function setRow($column, array $row) + { + $this->rows[$column] = $row; + + return $this; + } + + public function setHeaderTitle(?string $title): self + { + $this->headerTitle = $title; + + return $this; + } + + public function setFooterTitle(?string $title): self + { + $this->footerTitle = $title; + + return $this; + } + + public function setHorizontal(bool $horizontal = true): self + { + $this->horizontal = $horizontal; + + return $this; + } + + /** + * Renders table to output. + * + * Example: + * + * +---------------+-----------------------+------------------+ + * | ISBN | Title | Author | + * +---------------+-----------------------+------------------+ + * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | + * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | + * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | + * +---------------+-----------------------+------------------+ + */ + public function render() + { + $divider = new TableSeparator(); + if ($this->horizontal) { + $rows = []; + foreach ($this->headers[0] ?? [] as $i => $header) { + $rows[$i] = [$header]; + foreach ($this->rows as $row) { + if ($row instanceof TableSeparator) { + continue; + } + if (isset($row[$i])) { + $rows[$i][] = $row[$i]; + } elseif ($rows[$i][0] instanceof TableCell && $rows[$i][0]->getColspan() >= 2) { + // Noop, there is a "title" + } else { + $rows[$i][] = null; + } + } + } + } else { + $rows = array_merge($this->headers, [$divider], $this->rows); + } + + $this->calculateNumberOfColumns($rows); + + $rows = $this->buildTableRows($rows); + $this->calculateColumnsWidth($rows); + + $isHeader = !$this->horizontal; + $isFirstRow = $this->horizontal; + foreach ($rows as $row) { + if ($divider === $row) { + $isHeader = false; + $isFirstRow = true; + + continue; + } + if ($row instanceof TableSeparator) { + $this->renderRowSeparator(); + + continue; + } + if (!$row) { + continue; + } + + if ($isHeader || $isFirstRow) { + if ($isFirstRow) { + $this->renderRowSeparator(self::SEPARATOR_TOP_BOTTOM); + $isFirstRow = false; + } else { + $this->renderRowSeparator(self::SEPARATOR_TOP, $this->headerTitle, $this->style->getHeaderTitleFormat()); + } + } + if ($this->horizontal) { + $this->renderRow($row, $this->style->getCellRowFormat(), $this->style->getCellHeaderFormat()); + } else { + $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat()); + } + } + $this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat()); + + $this->cleanup(); + $this->rendered = true; + } + + /** + * Renders horizontal header separator. + * + * Example: + * + * +-----+-----------+-------+ + */ + private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null, string $titleFormat = null) + { + if (0 === $count = $this->numberOfColumns) { + return; + } + + $borders = $this->style->getBorderChars(); + if (!$borders[0] && !$borders[2] && !$this->style->getCrossingChar()) { + return; + } + + $crossings = $this->style->getCrossingChars(); + if (self::SEPARATOR_MID === $type) { + list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[2], $crossings[8], $crossings[0], $crossings[4]]; + } elseif (self::SEPARATOR_TOP === $type) { + list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[1], $crossings[2], $crossings[3]]; + } elseif (self::SEPARATOR_TOP_BOTTOM === $type) { + list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[9], $crossings[10], $crossings[11]]; + } else { + list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[7], $crossings[6], $crossings[5]]; + } + + $markup = $leftChar; + for ($column = 0; $column < $count; ++$column) { + $markup .= str_repeat($horizontal, $this->effectiveColumnWidths[$column]); + $markup .= $column === $count - 1 ? $rightChar : $midChar; + } + + if (null !== $title) { + $titleLength = Helper::strlenWithoutDecoration($formatter = $this->output->getFormatter(), $formattedTitle = sprintf($titleFormat, $title)); + $markupLength = Helper::strlen($markup); + if ($titleLength > $limit = $markupLength - 4) { + $titleLength = $limit; + $formatLength = Helper::strlenWithoutDecoration($formatter, sprintf($titleFormat, '')); + $formattedTitle = sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3).'...'); + } + + $titleStart = ($markupLength - $titleLength) / 2; + if (false === mb_detect_encoding($markup, null, true)) { + $markup = substr_replace($markup, $formattedTitle, $titleStart, $titleLength); + } else { + $markup = mb_substr($markup, 0, $titleStart).$formattedTitle.mb_substr($markup, $titleStart + $titleLength); + } + } + + $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup)); + } + + /** + * Renders vertical column separator. + */ + private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE): string + { + $borders = $this->style->getBorderChars(); + + return sprintf($this->style->getBorderFormat(), self::BORDER_OUTSIDE === $type ? $borders[1] : $borders[3]); + } + + /** + * Renders table row. + * + * Example: + * + * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | + */ + private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null) + { + $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE); + $columns = $this->getRowColumns($row); + $last = \count($columns) - 1; + foreach ($columns as $i => $column) { + if ($firstCellFormat && 0 === $i) { + $rowContent .= $this->renderCell($row, $column, $firstCellFormat); + } else { + $rowContent .= $this->renderCell($row, $column, $cellFormat); + } + $rowContent .= $this->renderColumnSeparator($last === $i ? self::BORDER_OUTSIDE : self::BORDER_INSIDE); + } + $this->output->writeln($rowContent); + } + + /** + * Renders table cell with padding. + */ + private function renderCell(array $row, int $column, string $cellFormat): string + { + $cell = isset($row[$column]) ? $row[$column] : ''; + $width = $this->effectiveColumnWidths[$column]; + if ($cell instanceof TableCell && $cell->getColspan() > 1) { + // add the width of the following columns(numbers of colspan). + foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) { + $width += $this->getColumnSeparatorWidth() + $this->effectiveColumnWidths[$nextColumn]; + } + } + + // str_pad won't work properly with multi-byte strings, we need to fix the padding + if (false !== $encoding = mb_detect_encoding($cell, null, true)) { + $width += \strlen($cell) - mb_strwidth($cell, $encoding); + } + + $style = $this->getColumnStyle($column); + + if ($cell instanceof TableSeparator) { + return sprintf($style->getBorderFormat(), str_repeat($style->getBorderChars()[2], $width)); + } + + $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); + $content = sprintf($style->getCellRowContentFormat(), $cell); + + return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType())); + } + + /** + * Calculate number of columns for this table. + */ + private function calculateNumberOfColumns(array $rows) + { + $columns = [0]; + foreach ($rows as $row) { + if ($row instanceof TableSeparator) { + continue; + } + + $columns[] = $this->getNumberOfColumns($row); + } + + $this->numberOfColumns = max($columns); + } + + private function buildTableRows(array $rows): TableRows + { + /** @var WrappableOutputFormatterInterface $formatter */ + $formatter = $this->output->getFormatter(); + $unmergedRows = []; + for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) { + $rows = $this->fillNextRows($rows, $rowKey); + + // Remove any new line breaks and replace it with a new line + foreach ($rows[$rowKey] as $column => $cell) { + $colspan = $cell instanceof TableCell ? $cell->getColspan() : 1; + + if (isset($this->columnMaxWidths[$column]) && Helper::strlenWithoutDecoration($formatter, $cell) > $this->columnMaxWidths[$column]) { + $cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column] * $colspan); + } + if (!strstr($cell, "\n")) { + continue; + } + $escaped = implode("\n", array_map([OutputFormatter::class, 'escapeTrailingBackslash'], explode("\n", $cell))); + $cell = $cell instanceof TableCell ? new TableCell($escaped, ['colspan' => $cell->getColspan()]) : $escaped; + $lines = explode("\n", str_replace("\n", "\n", $cell)); + foreach ($lines as $lineKey => $line) { + if ($colspan > 1) { + $line = new TableCell($line, ['colspan' => $colspan]); + } + if (0 === $lineKey) { + $rows[$rowKey][$column] = $line; + } else { + $unmergedRows[$rowKey][$lineKey][$column] = $line; + } + } + } + } + + return new TableRows(function () use ($rows, $unmergedRows): \Traversable { + foreach ($rows as $rowKey => $row) { + yield $this->fillCells($row); + + if (isset($unmergedRows[$rowKey])) { + foreach ($unmergedRows[$rowKey] as $row) { + yield $row; + } + } + } + }); + } + + private function calculateRowCount(): int + { + $numberOfRows = \count(iterator_to_array($this->buildTableRows(array_merge($this->headers, [new TableSeparator()], $this->rows)))); + + if ($this->headers) { + ++$numberOfRows; // Add row for header separator + } + + ++$numberOfRows; // Add row for footer separator + + return $numberOfRows; + } + + /** + * fill rows that contains rowspan > 1. + * + * @throws InvalidArgumentException + */ + private function fillNextRows(array $rows, int $line): array + { + $unmergedRows = []; + foreach ($rows[$line] as $column => $cell) { + if (null !== $cell && !$cell instanceof TableCell && !is_scalar($cell) && !(\is_object($cell) && method_exists($cell, '__toString'))) { + throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing __toString, %s given.', \gettype($cell))); + } + if ($cell instanceof TableCell && $cell->getRowspan() > 1) { + $nbLines = $cell->getRowspan() - 1; + $lines = [$cell]; + if (strstr($cell, "\n")) { + $lines = explode("\n", str_replace("\n", "\n", $cell)); + $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines; + + $rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan()]); + unset($lines[0]); + } + + // create a two dimensional array (rowspan x colspan) + $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, []), $unmergedRows); + foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { + $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : ''; + $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan()]); + if ($nbLines === $unmergedRowKey - $line) { + break; + } + } + } + } + + foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { + // we need to know if $unmergedRow will be merged or inserted into $rows + if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) { + foreach ($unmergedRow as $cellKey => $cell) { + // insert cell into row at cellKey position + array_splice($rows[$unmergedRowKey], $cellKey, 0, [$cell]); + } + } else { + $row = $this->copyRow($rows, $unmergedRowKey - 1); + foreach ($unmergedRow as $column => $cell) { + if (!empty($cell)) { + $row[$column] = $unmergedRow[$column]; + } + } + array_splice($rows, $unmergedRowKey, 0, [$row]); + } + } + + return $rows; + } + + /** + * fill cells for a row that contains colspan > 1. + */ + private function fillCells($row) + { + $newRow = []; + foreach ($row as $column => $cell) { + $newRow[] = $cell; + if ($cell instanceof TableCell && $cell->getColspan() > 1) { + foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) { + // insert empty value at column position + $newRow[] = ''; + } + } + } + + return $newRow ?: $row; + } + + private function copyRow(array $rows, int $line): array + { + $row = $rows[$line]; + foreach ($row as $cellKey => $cellValue) { + $row[$cellKey] = ''; + if ($cellValue instanceof TableCell) { + $row[$cellKey] = new TableCell('', ['colspan' => $cellValue->getColspan()]); + } + } + + return $row; + } + + /** + * Gets number of columns by row. + */ + private function getNumberOfColumns(array $row): int + { + $columns = \count($row); + foreach ($row as $column) { + $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0; + } + + return $columns; + } + + /** + * Gets list of columns for the given row. + */ + private function getRowColumns(array $row): array + { + $columns = range(0, $this->numberOfColumns - 1); + foreach ($row as $cellKey => $cell) { + if ($cell instanceof TableCell && $cell->getColspan() > 1) { + // exclude grouped columns. + $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1)); + } + } + + return $columns; + } + + /** + * Calculates columns widths. + */ + private function calculateColumnsWidth(iterable $rows) + { + for ($column = 0; $column < $this->numberOfColumns; ++$column) { + $lengths = []; + foreach ($rows as $row) { + if ($row instanceof TableSeparator) { + continue; + } + + foreach ($row as $i => $cell) { + if ($cell instanceof TableCell) { + $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell); + $textLength = Helper::strlen($textContent); + if ($textLength > 0) { + $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan())); + foreach ($contentColumns as $position => $content) { + $row[$i + $position] = $content; + } + } + } + } + + $lengths[] = $this->getCellWidth($row, $column); + } + + $this->effectiveColumnWidths[$column] = max($lengths) + Helper::strlen($this->style->getCellRowContentFormat()) - 2; + } + } + + private function getColumnSeparatorWidth(): int + { + return Helper::strlen(sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3])); + } + + private function getCellWidth(array $row, int $column): int + { + $cellWidth = 0; + + if (isset($row[$column])) { + $cell = $row[$column]; + $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); + } + + $columnWidth = isset($this->columnWidths[$column]) ? $this->columnWidths[$column] : 0; + $cellWidth = max($cellWidth, $columnWidth); + + return isset($this->columnMaxWidths[$column]) ? min($this->columnMaxWidths[$column], $cellWidth) : $cellWidth; + } + + /** + * Called after rendering to cleanup cache data. + */ + private function cleanup() + { + $this->effectiveColumnWidths = []; + $this->numberOfColumns = null; + } + + private static function initStyles(): array + { + $borderless = new TableStyle(); + $borderless + ->setHorizontalBorderChars('=') + ->setVerticalBorderChars(' ') + ->setDefaultCrossingChar(' ') + ; + + $compact = new TableStyle(); + $compact + ->setHorizontalBorderChars('') + ->setVerticalBorderChars(' ') + ->setDefaultCrossingChar('') + ->setCellRowContentFormat('%s') + ; + + $styleGuide = new TableStyle(); + $styleGuide + ->setHorizontalBorderChars('-') + ->setVerticalBorderChars(' ') + ->setDefaultCrossingChar(' ') + ->setCellHeaderFormat('%s') + ; + + $box = (new TableStyle()) + ->setHorizontalBorderChars('─') + ->setVerticalBorderChars('│') + ->setCrossingChars('┼', '┌', '┬', '┐', '┤', '┘', '┴', '└', '├') + ; + + $boxDouble = (new TableStyle()) + ->setHorizontalBorderChars('═', '─') + ->setVerticalBorderChars('║', '│') + ->setCrossingChars('┼', '╔', '╤', '╗', '╢', '╝', '╧', '╚', '╟', '╠', '╪', '╣') + ; + + return [ + 'default' => new TableStyle(), + 'borderless' => $borderless, + 'compact' => $compact, + 'symfony-style-guide' => $styleGuide, + 'box' => $box, + 'box-double' => $boxDouble, + ]; + } + + private function resolveStyle($name): TableStyle + { + if ($name instanceof TableStyle) { + return $name; + } + + if (isset(self::$styles[$name])) { + return self::$styles[$name]; + } + + throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); + } +} diff --git a/vendor/symfony/console/Helper/TableCell.php b/vendor/symfony/console/Helper/TableCell.php new file mode 100644 index 0000000..5b6af4a --- /dev/null +++ b/vendor/symfony/console/Helper/TableCell.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * @author Abdellatif Ait boudad + */ +class TableCell +{ + private $value; + private $options = [ + 'rowspan' => 1, + 'colspan' => 1, + ]; + + public function __construct(string $value = '', array $options = []) + { + $this->value = $value; + + // check option names + if ($diff = array_diff(array_keys($options), array_keys($this->options))) { + throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff))); + } + + $this->options = array_merge($this->options, $options); + } + + /** + * Returns the cell value. + * + * @return string + */ + public function __toString() + { + return $this->value; + } + + /** + * Gets number of colspan. + * + * @return int + */ + public function getColspan() + { + return (int) $this->options['colspan']; + } + + /** + * Gets number of rowspan. + * + * @return int + */ + public function getRowspan() + { + return (int) $this->options['rowspan']; + } +} diff --git a/vendor/symfony/console/Helper/TableRows.php b/vendor/symfony/console/Helper/TableRows.php new file mode 100644 index 0000000..16aabb3 --- /dev/null +++ b/vendor/symfony/console/Helper/TableRows.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +/** + * @internal + */ +class TableRows implements \IteratorAggregate +{ + private $generator; + + public function __construct(callable $generator) + { + $this->generator = $generator; + } + + public function getIterator(): \Traversable + { + $g = $this->generator; + + return $g(); + } +} diff --git a/vendor/symfony/console/Helper/TableSeparator.php b/vendor/symfony/console/Helper/TableSeparator.php new file mode 100644 index 0000000..e541c53 --- /dev/null +++ b/vendor/symfony/console/Helper/TableSeparator.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +/** + * Marks a row as being a separator. + * + * @author Fabien Potencier + */ +class TableSeparator extends TableCell +{ + public function __construct(array $options = []) + { + parent::__construct('', $options); + } +} diff --git a/vendor/symfony/console/Helper/TableStyle.php b/vendor/symfony/console/Helper/TableStyle.php new file mode 100644 index 0000000..8371942 --- /dev/null +++ b/vendor/symfony/console/Helper/TableStyle.php @@ -0,0 +1,364 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Defines the styles for a Table. + * + * @author Fabien Potencier + * @author Саша Стаменковић + * @author Dany Maillard + */ +class TableStyle +{ + private $paddingChar = ' '; + private $horizontalOutsideBorderChar = '-'; + private $horizontalInsideBorderChar = '-'; + private $verticalOutsideBorderChar = '|'; + private $verticalInsideBorderChar = '|'; + private $crossingChar = '+'; + private $crossingTopRightChar = '+'; + private $crossingTopMidChar = '+'; + private $crossingTopLeftChar = '+'; + private $crossingMidRightChar = '+'; + private $crossingBottomRightChar = '+'; + private $crossingBottomMidChar = '+'; + private $crossingBottomLeftChar = '+'; + private $crossingMidLeftChar = '+'; + private $crossingTopLeftBottomChar = '+'; + private $crossingTopMidBottomChar = '+'; + private $crossingTopRightBottomChar = '+'; + private $headerTitleFormat = ' %s '; + private $footerTitleFormat = ' %s '; + private $cellHeaderFormat = '%s'; + private $cellRowFormat = '%s'; + private $cellRowContentFormat = ' %s '; + private $borderFormat = '%s'; + private $padType = STR_PAD_RIGHT; + + /** + * Sets padding character, used for cell padding. + * + * @return $this + */ + public function setPaddingChar(string $paddingChar) + { + if (!$paddingChar) { + throw new LogicException('The padding char must not be empty'); + } + + $this->paddingChar = $paddingChar; + + return $this; + } + + /** + * Gets padding character, used for cell padding. + * + * @return string + */ + public function getPaddingChar() + { + return $this->paddingChar; + } + + /** + * Sets horizontal border characters. + * + * + * ╔═══════════════╤══════════════════════════╤══════════════════╗ + * 1 ISBN 2 Title │ Author ║ + * ╠═══════════════╪══════════════════════════╪══════════════════╣ + * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ + * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ + * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ + * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ + * ╚═══════════════╧══════════════════════════╧══════════════════╝ + * + */ + public function setHorizontalBorderChars(string $outside, string $inside = null): self + { + $this->horizontalOutsideBorderChar = $outside; + $this->horizontalInsideBorderChar = $inside ?? $outside; + + return $this; + } + + /** + * Sets vertical border characters. + * + * + * ╔═══════════════╤══════════════════════════╤══════════════════╗ + * ║ ISBN │ Title │ Author ║ + * ╠═══════1═══════╪══════════════════════════╪══════════════════╣ + * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ + * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ + * ╟───────2───────┼──────────────────────────┼──────────────────╢ + * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ + * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ + * ╚═══════════════╧══════════════════════════╧══════════════════╝ + * + */ + public function setVerticalBorderChars(string $outside, string $inside = null): self + { + $this->verticalOutsideBorderChar = $outside; + $this->verticalInsideBorderChar = $inside ?? $outside; + + return $this; + } + + /** + * Gets border characters. + * + * @internal + */ + public function getBorderChars(): array + { + return [ + $this->horizontalOutsideBorderChar, + $this->verticalOutsideBorderChar, + $this->horizontalInsideBorderChar, + $this->verticalInsideBorderChar, + ]; + } + + /** + * Sets crossing characters. + * + * Example: + * + * 1═══════════════2══════════════════════════2══════════════════3 + * ║ ISBN │ Title │ Author ║ + * 8'══════════════0'═════════════════════════0'═════════════════4' + * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ + * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ + * 8───────────────0──────────────────────────0──────────────────4 + * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ + * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ + * 7═══════════════6══════════════════════════6══════════════════5 + * + * + * @param string $cross Crossing char (see #0 of example) + * @param string $topLeft Top left char (see #1 of example) + * @param string $topMid Top mid char (see #2 of example) + * @param string $topRight Top right char (see #3 of example) + * @param string $midRight Mid right char (see #4 of example) + * @param string $bottomRight Bottom right char (see #5 of example) + * @param string $bottomMid Bottom mid char (see #6 of example) + * @param string $bottomLeft Bottom left char (see #7 of example) + * @param string $midLeft Mid left char (see #8 of example) + * @param string|null $topLeftBottom Top left bottom char (see #8' of example), equals to $midLeft if null + * @param string|null $topMidBottom Top mid bottom char (see #0' of example), equals to $cross if null + * @param string|null $topRightBottom Top right bottom char (see #4' of example), equals to $midRight if null + */ + public function setCrossingChars(string $cross, string $topLeft, string $topMid, string $topRight, string $midRight, string $bottomRight, string $bottomMid, string $bottomLeft, string $midLeft, string $topLeftBottom = null, string $topMidBottom = null, string $topRightBottom = null): self + { + $this->crossingChar = $cross; + $this->crossingTopLeftChar = $topLeft; + $this->crossingTopMidChar = $topMid; + $this->crossingTopRightChar = $topRight; + $this->crossingMidRightChar = $midRight; + $this->crossingBottomRightChar = $bottomRight; + $this->crossingBottomMidChar = $bottomMid; + $this->crossingBottomLeftChar = $bottomLeft; + $this->crossingMidLeftChar = $midLeft; + $this->crossingTopLeftBottomChar = $topLeftBottom ?? $midLeft; + $this->crossingTopMidBottomChar = $topMidBottom ?? $cross; + $this->crossingTopRightBottomChar = $topRightBottom ?? $midRight; + + return $this; + } + + /** + * Sets default crossing character used for each cross. + * + * @see {@link setCrossingChars()} for setting each crossing individually. + */ + public function setDefaultCrossingChar(string $char): self + { + return $this->setCrossingChars($char, $char, $char, $char, $char, $char, $char, $char, $char); + } + + /** + * Gets crossing character. + * + * @return string + */ + public function getCrossingChar() + { + return $this->crossingChar; + } + + /** + * Gets crossing characters. + * + * @internal + */ + public function getCrossingChars(): array + { + return [ + $this->crossingChar, + $this->crossingTopLeftChar, + $this->crossingTopMidChar, + $this->crossingTopRightChar, + $this->crossingMidRightChar, + $this->crossingBottomRightChar, + $this->crossingBottomMidChar, + $this->crossingBottomLeftChar, + $this->crossingMidLeftChar, + $this->crossingTopLeftBottomChar, + $this->crossingTopMidBottomChar, + $this->crossingTopRightBottomChar, + ]; + } + + /** + * Sets header cell format. + * + * @return $this + */ + public function setCellHeaderFormat(string $cellHeaderFormat) + { + $this->cellHeaderFormat = $cellHeaderFormat; + + return $this; + } + + /** + * Gets header cell format. + * + * @return string + */ + public function getCellHeaderFormat() + { + return $this->cellHeaderFormat; + } + + /** + * Sets row cell format. + * + * @return $this + */ + public function setCellRowFormat(string $cellRowFormat) + { + $this->cellRowFormat = $cellRowFormat; + + return $this; + } + + /** + * Gets row cell format. + * + * @return string + */ + public function getCellRowFormat() + { + return $this->cellRowFormat; + } + + /** + * Sets row cell content format. + * + * @return $this + */ + public function setCellRowContentFormat(string $cellRowContentFormat) + { + $this->cellRowContentFormat = $cellRowContentFormat; + + return $this; + } + + /** + * Gets row cell content format. + * + * @return string + */ + public function getCellRowContentFormat() + { + return $this->cellRowContentFormat; + } + + /** + * Sets table border format. + * + * @return $this + */ + public function setBorderFormat(string $borderFormat) + { + $this->borderFormat = $borderFormat; + + return $this; + } + + /** + * Gets table border format. + * + * @return string + */ + public function getBorderFormat() + { + return $this->borderFormat; + } + + /** + * Sets cell padding type. + * + * @return $this + */ + public function setPadType(int $padType) + { + if (!\in_array($padType, [STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH], true)) { + throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).'); + } + + $this->padType = $padType; + + return $this; + } + + /** + * Gets cell padding type. + * + * @return int + */ + public function getPadType() + { + return $this->padType; + } + + public function getHeaderTitleFormat(): string + { + return $this->headerTitleFormat; + } + + public function setHeaderTitleFormat(string $format): self + { + $this->headerTitleFormat = $format; + + return $this; + } + + public function getFooterTitleFormat(): string + { + return $this->footerTitleFormat; + } + + public function setFooterTitleFormat(string $format): self + { + $this->footerTitleFormat = $format; + + return $this; + } +} diff --git a/vendor/symfony/console/Input/ArgvInput.php b/vendor/symfony/console/Input/ArgvInput.php new file mode 100644 index 0000000..cbd9f41 --- /dev/null +++ b/vendor/symfony/console/Input/ArgvInput.php @@ -0,0 +1,349 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\RuntimeException; + +/** + * 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 application. + * + * 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 + * + * @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 +{ + private $tokens; + private $parsed; + + public function __construct(array $argv = null, InputDefinition $definition = null) + { + if (null === $argv) { + $argv = $_SERVER['argv']; + } + + // strip the application name + array_shift($argv); + + $this->tokens = $argv; + + parent::__construct($definition); + } + + protected function setTokens(array $tokens) + { + $this->tokens = $tokens; + } + + /** + * {@inheritdoc} + */ + protected function parse() + { + $parseOptions = true; + $this->parsed = $this->tokens; + while (null !== $token = array_shift($this->parsed)) { + if ($parseOptions && '' == $token) { + $this->parseArgument($token); + } elseif ($parseOptions && '--' == $token) { + $parseOptions = false; + } elseif ($parseOptions && 0 === strpos($token, '--')) { + $this->parseLongOption($token); + } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { + $this->parseShortOption($token); + } else { + $this->parseArgument($token); + } + } + } + + /** + * Parses a short option. + */ + private function parseShortOption(string $token) + { + $name = substr($token, 1); + + if (\strlen($name) > 1) { + if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { + // 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. + * + * @throws RuntimeException When option given doesn't exist + */ + private function parseShortOptionSet(string $name) + { + $len = \strlen($name); + for ($i = 0; $i < $len; ++$i) { + if (!$this->definition->hasShortcut($name[$i])) { + $encoding = mb_detect_encoding($name, null, true); + throw new RuntimeException(sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding))); + } + + $option = $this->definition->getOptionForShortcut($name[$i]); + if ($option->acceptValue()) { + $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); + + break; + } else { + $this->addLongOption($option->getName(), null); + } + } + } + + /** + * Parses a long option. + */ + private function parseLongOption(string $token) + { + $name = substr($token, 2); + + if (false !== $pos = strpos($name, '=')) { + if (0 === \strlen($value = substr($name, $pos + 1))) { + array_unshift($this->parsed, $value); + } + $this->addLongOption(substr($name, 0, $pos), $value); + } else { + $this->addLongOption($name, null); + } + } + + /** + * Parses an argument. + * + * @throws RuntimeException When too many arguments are given + */ + private function parseArgument(string $token) + { + $c = \count($this->arguments); + + // if input is expecting another argument, add it + if ($this->definition->hasArgument($c)) { + $arg = $this->definition->getArgument($c); + $this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token; + + // if last argument isArray(), append token to last argument + } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { + $arg = $this->definition->getArgument($c - 1); + $this->arguments[$arg->getName()][] = $token; + + // unexpected argument + } else { + $all = $this->definition->getArguments(); + if (\count($all)) { + throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all)))); + } + + throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token)); + } + } + + /** + * Adds a short option value. + * + * @throws RuntimeException When option given doesn't exist + */ + private function addShortOption(string $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. + * + * @throws RuntimeException When option given doesn't exist + */ + private function addLongOption(string $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->acceptValue()) { + throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name)); + } + + if (\in_array($value, ['', null], true) && $option->acceptValue() && \count($this->parsed)) { + // if option accepts an optional or mandatory argument + // let's see if there is one provided + $next = array_shift($this->parsed); + if ((isset($next[0]) && '-' !== $next[0]) || \in_array($next, ['', null], true)) { + $value = $next; + } else { + array_unshift($this->parsed, $next); + } + } + + if (null === $value) { + if ($option->isValueRequired()) { + throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name)); + } + + if (!$option->isArray() && !$option->isValueOptional()) { + $value = true; + } + } + + if ($option->isArray()) { + $this->options[$name][] = $value; + } else { + $this->options[$name] = $value; + } + } + + /** + * {@inheritdoc} + */ + public function getFirstArgument() + { + $isOption = false; + foreach ($this->tokens as $i => $token) { + if ($token && '-' === $token[0]) { + if (false !== strpos($token, '=') || !isset($this->tokens[$i + 1])) { + continue; + } + + // If it's a long option, consider that everything after "--" is the option name. + // Otherwise, use the last char (if it's a short option set, only the last one can take a value with space separator) + $name = '-' === $token[1] ? substr($token, 2) : substr($token, -1); + if (!isset($this->options[$name]) && !$this->definition->hasShortcut($name)) { + // noop + } elseif ((isset($this->options[$name]) || isset($this->options[$name = $this->definition->shortcutToName($name)])) && $this->tokens[$i + 1] === $this->options[$name]) { + $isOption = true; + } + + continue; + } + + if ($isOption) { + $isOption = false; + continue; + } + + return $token; + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function hasParameterOption($values, bool $onlyParams = false) + { + $values = (array) $values; + + foreach ($this->tokens as $token) { + if ($onlyParams && '--' === $token) { + return false; + } + foreach ($values as $value) { + // Options with values: + // For long options, test for '--option=' at beginning + // For short options, test for '-o' at beginning + $leading = 0 === strpos($value, '--') ? $value.'=' : $value; + if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) { + return true; + } + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function getParameterOption($values, $default = false, bool $onlyParams = false) + { + $values = (array) $values; + $tokens = $this->tokens; + + while (0 < \count($tokens)) { + $token = array_shift($tokens); + if ($onlyParams && '--' === $token) { + return $default; + } + + foreach ($values as $value) { + if ($token === $value) { + return array_shift($tokens); + } + // Options with values: + // For long options, test for '--option=' at beginning + // For short options, test for '-o' at beginning + $leading = 0 === strpos($value, '--') ? $value.'=' : $value; + if ('' !== $leading && 0 === strpos($token, $leading)) { + return substr($token, \strlen($leading)); + } + } + } + + return $default; + } + + /** + * Returns a stringified representation of the args passed to the command. + * + * @return string + */ + public function __toString() + { + $tokens = array_map(function ($token) { + if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) { + return $match[1].$this->escapeToken($match[2]); + } + + if ($token && '-' !== $token[0]) { + return $this->escapeToken($token); + } + + return $token; + }, $this->tokens); + + return implode(' ', $tokens); + } +} diff --git a/vendor/symfony/console/Input/ArrayInput.php b/vendor/symfony/console/Input/ArrayInput.php new file mode 100644 index 0000000..66f0bed --- /dev/null +++ b/vendor/symfony/console/Input/ArrayInput.php @@ -0,0 +1,202 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\InvalidOptionException; + +/** + * ArrayInput represents an input provided as an array. + * + * Usage: + * + * $input = new ArrayInput(['command' => 'foo:bar', 'foo' => 'bar', '--bar' => 'foobar']); + * + * @author Fabien Potencier + */ +class ArrayInput extends Input +{ + private $parameters; + + public function __construct(array $parameters, InputDefinition $definition = null) + { + $this->parameters = $parameters; + + parent::__construct($definition); + } + + /** + * {@inheritdoc} + */ + public function getFirstArgument() + { + foreach ($this->parameters as $param => $value) { + if ($param && \is_string($param) && '-' === $param[0]) { + continue; + } + + return $value; + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function hasParameterOption($values, bool $onlyParams = false) + { + $values = (array) $values; + + foreach ($this->parameters as $k => $v) { + if (!\is_int($k)) { + $v = $k; + } + + if ($onlyParams && '--' === $v) { + return false; + } + + if (\in_array($v, $values)) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function getParameterOption($values, $default = false, bool $onlyParams = false) + { + $values = (array) $values; + + foreach ($this->parameters as $k => $v) { + if ($onlyParams && ('--' === $k || (\is_int($k) && '--' === $v))) { + return $default; + } + + if (\is_int($k)) { + if (\in_array($v, $values)) { + return true; + } + } elseif (\in_array($k, $values)) { + return $v; + } + } + + return $default; + } + + /** + * Returns a stringified representation of the args passed to the command. + * + * @return string + */ + public function __toString() + { + $params = []; + foreach ($this->parameters as $param => $val) { + if ($param && \is_string($param) && '-' === $param[0]) { + if (\is_array($val)) { + foreach ($val as $v) { + $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : ''); + } + } else { + $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : ''); + } + } else { + $params[] = \is_array($val) ? implode(' ', array_map([$this, 'escapeToken'], $val)) : $this->escapeToken($val); + } + } + + return implode(' ', $params); + } + + /** + * {@inheritdoc} + */ + protected function parse() + { + foreach ($this->parameters as $key => $value) { + if ('--' === $key) { + return; + } + if (0 === strpos($key, '--')) { + $this->addLongOption(substr($key, 2), $value); + } elseif (0 === strpos($key, '-')) { + $this->addShortOption(substr($key, 1), $value); + } else { + $this->addArgument($key, $value); + } + } + } + + /** + * Adds a short option value. + * + * @throws InvalidOptionException When option given doesn't exist + */ + private function addShortOption(string $shortcut, $value) + { + if (!$this->definition->hasShortcut($shortcut)) { + throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut)); + } + + $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); + } + + /** + * Adds a long option value. + * + * @throws InvalidOptionException When option given doesn't exist + * @throws InvalidOptionException When a required value is missing + */ + private function addLongOption(string $name, $value) + { + if (!$this->definition->hasOption($name)) { + throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name)); + } + + $option = $this->definition->getOption($name); + + if (null === $value) { + if ($option->isValueRequired()) { + throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name)); + } + + if (!$option->isValueOptional()) { + $value = true; + } + } + + $this->options[$name] = $value; + } + + /** + * Adds an argument value. + * + * @param string|int $name The argument name + * @param mixed $value The value for the argument + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + private function addArgument($name, $value) + { + if (!$this->definition->hasArgument($name)) { + throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + } + + $this->arguments[$name] = $value; + } +} diff --git a/vendor/symfony/console/Input/Input.php b/vendor/symfony/console/Input/Input.php new file mode 100644 index 0000000..8c7905d --- /dev/null +++ b/vendor/symfony/console/Input/Input.php @@ -0,0 +1,201 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; + +/** + * 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 + */ +abstract class Input implements InputInterface, StreamableInputInterface +{ + protected $definition; + protected $stream; + protected $options = []; + protected $arguments = []; + protected $interactive = true; + + public function __construct(InputDefinition $definition = null) + { + if (null === $definition) { + $this->definition = new InputDefinition(); + } else { + $this->bind($definition); + $this->validate(); + } + } + + /** + * {@inheritdoc} + */ + public function bind(InputDefinition $definition) + { + $this->arguments = []; + $this->options = []; + $this->definition = $definition; + + $this->parse(); + } + + /** + * Processes command line arguments. + */ + abstract protected function parse(); + + /** + * {@inheritdoc} + */ + public function validate() + { + $definition = $this->definition; + $givenArguments = $this->arguments; + + $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) { + return !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired(); + }); + + if (\count($missingArguments) > 0) { + throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments))); + } + } + + /** + * {@inheritdoc} + */ + public function isInteractive() + { + return $this->interactive; + } + + /** + * {@inheritdoc} + */ + public function setInteractive(bool $interactive) + { + $this->interactive = $interactive; + } + + /** + * {@inheritdoc} + */ + public function getArguments() + { + return array_merge($this->definition->getArgumentDefaults(), $this->arguments); + } + + /** + * {@inheritdoc} + */ + 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(); + } + + /** + * {@inheritdoc} + */ + 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; + } + + /** + * {@inheritdoc} + */ + public function hasArgument($name) + { + return $this->definition->hasArgument($name); + } + + /** + * {@inheritdoc} + */ + public function getOptions() + { + return array_merge($this->definition->getOptionDefaults(), $this->options); + } + + /** + * {@inheritdoc} + */ + public function getOption(string $name) + { + if (!$this->definition->hasOption($name)) { + throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); + } + + return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); + } + + /** + * {@inheritdoc} + */ + public function setOption(string $name, $value) + { + if (!$this->definition->hasOption($name)) { + throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); + } + + $this->options[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function hasOption(string $name) + { + return $this->definition->hasOption($name); + } + + /** + * Escapes a token through escapeshellarg if it contains unsafe chars. + * + * @return string + */ + public function escapeToken(string $token) + { + return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token); + } + + /** + * {@inheritdoc} + */ + public function setStream($stream) + { + $this->stream = $stream; + } + + /** + * {@inheritdoc} + */ + public function getStream() + { + return $this->stream; + } +} diff --git a/vendor/symfony/console/Input/InputArgument.php b/vendor/symfony/console/Input/InputArgument.php new file mode 100644 index 0000000..b6aa645 --- /dev/null +++ b/vendor/symfony/console/Input/InputArgument.php @@ -0,0 +1,129 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Represents a command line argument. + * + * @author Fabien Potencier + */ +class InputArgument +{ + const REQUIRED = 1; + const OPTIONAL = 2; + const IS_ARRAY = 4; + + private $name; + private $mode; + private $default; + private $description; + + /** + * @param string $name The argument name + * @param int|null $mode The argument mode: self::REQUIRED or self::OPTIONAL + * @param string $description A description text + * @param string|string[]|null $default The default value (for self::OPTIONAL mode only) + * + * @throws InvalidArgumentException When argument mode is not valid + */ + public function __construct(string $name, int $mode = null, string $description = '', $default = null) + { + if (null === $mode) { + $mode = self::OPTIONAL; + } elseif ($mode > 7 || $mode < 1) { + 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 bool 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 bool 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 string|string[]|null $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 InputArgument::OPTIONAL mode.'); + } + + if ($this->isArray()) { + if (null === $default) { + $default = []; + } elseif (!\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 string|string[]|null The default value + */ + public function getDefault() + { + return $this->default; + } + + /** + * Returns the description text. + * + * @return string The description text + */ + public function getDescription() + { + return $this->description; + } +} diff --git a/vendor/symfony/console/Input/InputAwareInterface.php b/vendor/symfony/console/Input/InputAwareInterface.php new file mode 100644 index 0000000..5a288de --- /dev/null +++ b/vendor/symfony/console/Input/InputAwareInterface.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +/** + * InputAwareInterface should be implemented by classes that depends on the + * Console Input. + * + * @author Wouter J + */ +interface InputAwareInterface +{ + /** + * Sets the Console Input. + */ + public function setInput(InputInterface $input); +} diff --git a/vendor/symfony/console/Input/InputDefinition.php b/vendor/symfony/console/Input/InputDefinition.php new file mode 100644 index 0000000..4e95e9b --- /dev/null +++ b/vendor/symfony/console/Input/InputDefinition.php @@ -0,0 +1,390 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * A InputDefinition represents a set of valid command line arguments and options. + * + * Usage: + * + * $definition = new InputDefinition([ + * new InputArgument('name', InputArgument::REQUIRED), + * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED), + * ]); + * + * @author Fabien Potencier + */ +class InputDefinition +{ + private $arguments; + private $requiredCount; + private $hasAnArrayArgument = false; + private $hasOptional; + private $options; + private $shortcuts; + + /** + * @param array $definition An array of InputArgument and InputOption instance + */ + public function __construct(array $definition = []) + { + $this->setDefinition($definition); + } + + /** + * Sets the definition of the input. + */ + public function setDefinition(array $definition) + { + $arguments = []; + $options = []; + foreach ($definition as $item) { + if ($item instanceof InputOption) { + $options[] = $item; + } else { + $arguments[] = $item; + } + } + + $this->setArguments($arguments); + $this->setOptions($options); + } + + /** + * Sets the InputArgument objects. + * + * @param InputArgument[] $arguments An array of InputArgument objects + */ + public function setArguments(array $arguments = []) + { + $this->arguments = []; + $this->requiredCount = 0; + $this->hasOptional = false; + $this->hasAnArrayArgument = false; + $this->addArguments($arguments); + } + + /** + * Adds an array of InputArgument objects. + * + * @param InputArgument[] $arguments An array of InputArgument objects + */ + public function addArguments(?array $arguments = []) + { + if (null !== $arguments) { + foreach ($arguments as $argument) { + $this->addArgument($argument); + } + } + } + + /** + * @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 exists.', $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|int $name The InputArgument name or position + * + * @return InputArgument An InputArgument object + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + public function getArgument($name) + { + if (!$this->hasArgument($name)) { + throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + } + + $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments; + + return $arguments[$name]; + } + + /** + * Returns true if an InputArgument object exists by name or position. + * + * @param string|int $name The InputArgument name or position + * + * @return bool 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 InputArgument[] An array of InputArgument objects + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * Returns the number of InputArguments. + * + * @return int The number of InputArguments + */ + public function getArgumentCount() + { + return $this->hasAnArrayArgument ? PHP_INT_MAX : \count($this->arguments); + } + + /** + * Returns the number of required InputArguments. + * + * @return int 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 = []; + foreach ($this->arguments as $argument) { + $values[$argument->getName()] = $argument->getDefault(); + } + + return $values; + } + + /** + * Sets the InputOption objects. + * + * @param InputOption[] $options An array of InputOption objects + */ + public function setOptions(array $options = []) + { + $this->options = []; + $this->shortcuts = []; + $this->addOptions($options); + } + + /** + * Adds an array of InputOption objects. + * + * @param InputOption[] $options An array of InputOption objects + */ + public function addOptions(array $options = []) + { + foreach ($options as $option) { + $this->addOption($option); + } + } + + /** + * @throws LogicException When option given already exist + */ + public function addOption(InputOption $option) + { + if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) { + throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName())); + } + + if ($option->getShortcut()) { + foreach (explode('|', $option->getShortcut()) as $shortcut) { + if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) { + throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut)); + } + } + } + + $this->options[$option->getName()] = $option; + if ($option->getShortcut()) { + foreach (explode('|', $option->getShortcut()) as $shortcut) { + $this->shortcuts[$shortcut] = $option->getName(); + } + } + } + + /** + * Returns an InputOption by name. + * + * @return InputOption A InputOption object + * + * @throws InvalidArgumentException When option given doesn't exist + */ + public function getOption(string $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. + * + * This method can't be used to check if the user included the option when + * executing the command (use getOption() instead). + * + * @return bool true if the InputOption object exists, false otherwise + */ + public function hasOption(string $name) + { + return isset($this->options[$name]); + } + + /** + * Gets the array of InputOption objects. + * + * @return InputOption[] An array of InputOption objects + */ + public function getOptions() + { + return $this->options; + } + + /** + * Returns true if an InputOption object exists by shortcut. + * + * @return bool true if the InputOption object exists, false otherwise + */ + public function hasShortcut(string $name) + { + return isset($this->shortcuts[$name]); + } + + /** + * Gets an InputOption by shortcut. + * + * @return InputOption An InputOption object + */ + public function getOptionForShortcut(string $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 = []; + foreach ($this->options as $option) { + $values[$option->getName()] = $option->getDefault(); + } + + return $values; + } + + /** + * Returns the InputOption name given a shortcut. + * + * @throws InvalidArgumentException When option given does not exist + * + * @internal + */ + public function shortcutToName(string $shortcut): string + { + 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(bool $short = false) + { + $elements = []; + + if ($short && $this->getOptions()) { + $elements[] = '[options]'; + } elseif (!$short) { + foreach ($this->getOptions() as $option) { + $value = ''; + if ($option->acceptValue()) { + $value = sprintf( + ' %s%s%s', + $option->isValueOptional() ? '[' : '', + strtoupper($option->getName()), + $option->isValueOptional() ? ']' : '' + ); + } + + $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : ''; + $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value); + } + } + + if (\count($elements) && $this->getArguments()) { + $elements[] = '[--]'; + } + + $tail = ''; + foreach ($this->getArguments() as $argument) { + $element = '<'.$argument->getName().'>'; + if ($argument->isArray()) { + $element .= '...'; + } + + if (!$argument->isRequired()) { + $element = '['.$element; + $tail .= ']'; + } + + $elements[] = $element; + } + + return implode(' ', $elements).$tail; + } +} diff --git a/vendor/symfony/console/Input/InputInterface.php b/vendor/symfony/console/Input/InputInterface.php new file mode 100644 index 0000000..f6ad722 --- /dev/null +++ b/vendor/symfony/console/Input/InputInterface.php @@ -0,0 +1,153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; + +/** + * InputInterface is the interface implemented by all input classes. + * + * @author Fabien Potencier + */ +interface InputInterface +{ + /** + * Returns the first argument from the raw parameters (not parsed). + * + * @return string|null The value of the first argument or null otherwise + */ + public function getFirstArgument(); + + /** + * Returns true if the raw parameters (not parsed) contain a value. + * + * This method is to be used to introspect the input parameters + * before they have been validated. It must be used carefully. + * Does not necessarily return the correct result for short options + * when multiple flags are combined in the same option. + * + * @param string|array $values The values to look for in the raw parameters (can be an array) + * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal + * + * @return bool true if the value is contained in the raw parameters + */ + public function hasParameterOption($values, bool $onlyParams = false); + + /** + * Returns the value of a raw option (not parsed). + * + * This method is to be used to introspect the input parameters + * before they have been validated. It must be used carefully. + * Does not necessarily return the correct result for short options + * when multiple flags are combined in the same option. + * + * @param string|array $values The value(s) to look for in the raw parameters (can be an array) + * @param mixed $default The default value to return if no result is found + * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal + * + * @return mixed The option value + */ + public function getParameterOption($values, $default = false, bool $onlyParams = false); + + /** + * Binds the current Input instance with the given arguments and options. + * + * @throws RuntimeException + */ + public function bind(InputDefinition $definition); + + /** + * Validates the input. + * + * @throws RuntimeException When not enough arguments are given + */ + public function validate(); + + /** + * Returns all the given arguments merged with the default values. + * + * @return array + */ + public function getArguments(); + + /** + * Returns the argument value for a given argument name. + * + * @return string|string[]|null The argument value + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + public function getArgument(string $name); + + /** + * Sets an argument value by name. + * + * @param string|string[]|null $value The argument value + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + public function setArgument(string $name, $value); + + /** + * Returns true if an InputArgument object exists by name or position. + * + * @param string|int $name The InputArgument name or position + * + * @return bool true if the InputArgument object exists, false otherwise + */ + public function hasArgument($name); + + /** + * Returns all the given options merged with the default values. + * + * @return array + */ + public function getOptions(); + + /** + * Returns the option value for a given option name. + * + * @return string|string[]|bool|null The option value + * + * @throws InvalidArgumentException When option given doesn't exist + */ + public function getOption(string $name); + + /** + * Sets an option value by name. + * + * @param string|string[]|bool|null $value The option value + * + * @throws InvalidArgumentException When option given doesn't exist + */ + public function setOption(string $name, $value); + + /** + * Returns true if an InputOption object exists by name. + * + * @return bool true if the InputOption object exists, false otherwise + */ + public function hasOption(string $name); + + /** + * Is this input means interactive? + * + * @return bool + */ + public function isInteractive(); + + /** + * Sets the input interactivity. + */ + public function setInteractive(bool $interactive); +} diff --git a/vendor/symfony/console/Input/InputOption.php b/vendor/symfony/console/Input/InputOption.php new file mode 100644 index 0000000..d62e0ae --- /dev/null +++ b/vendor/symfony/console/Input/InputOption.php @@ -0,0 +1,208 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Represents a command line option. + * + * @author Fabien Potencier + */ +class InputOption +{ + const VALUE_NONE = 1; + const VALUE_REQUIRED = 2; + const VALUE_OPTIONAL = 4; + const VALUE_IS_ARRAY = 8; + + private $name; + private $shortcut; + private $mode; + private $default; + private $description; + + /** + * @param string $name The option name + * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts + * @param int|null $mode The option mode: One of the VALUE_* constants + * @param string $description A description text + * @param string|string[]|int|bool|null $default The default value (must be null for self::VALUE_NONE) + * + * @throws InvalidArgumentException If option mode is invalid or incompatible + */ + public function __construct(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null) + { + if (0 === strpos($name, '--')) { + $name = substr($name, 2); + } + + if (empty($name)) { + throw new InvalidArgumentException('An option name cannot be empty.'); + } + + if (empty($shortcut)) { + $shortcut = null; + } + + if (null !== $shortcut) { + if (\is_array($shortcut)) { + $shortcut = implode('|', $shortcut); + } + $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-')); + $shortcuts = array_filter($shortcuts); + $shortcut = implode('|', $shortcuts); + + if (empty($shortcut)) { + throw new InvalidArgumentException('An option shortcut cannot be empty.'); + } + } + + if (null === $mode) { + $mode = self::VALUE_NONE; + } elseif ($mode > 15 || $mode < 1) { + 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->acceptValue()) { + throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.'); + } + + $this->setDefault($default); + } + + /** + * Returns the option shortcut. + * + * @return string|null The shortcut + */ + public function getShortcut() + { + return $this->shortcut; + } + + /** + * Returns the option name. + * + * @return string The name + */ + public function getName() + { + return $this->name; + } + + /** + * Returns true if the option accepts a value. + * + * @return bool true if value mode is not self::VALUE_NONE, false otherwise + */ + public function acceptValue() + { + return $this->isValueRequired() || $this->isValueOptional(); + } + + /** + * Returns true if the option requires a value. + * + * @return bool true if value mode is self::VALUE_REQUIRED, false otherwise + */ + public function isValueRequired() + { + return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode); + } + + /** + * Returns true if the option takes an optional value. + * + * @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise + */ + public function isValueOptional() + { + return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode); + } + + /** + * Returns true if the option can take multiple values. + * + * @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise + */ + public function isArray() + { + return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); + } + + /** + * Sets the default value. + * + * @param string|string[]|int|bool|null $default The default value + * + * @throws LogicException When incorrect default value is given + */ + public function setDefault($default = null) + { + if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) { + throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.'); + } + + if ($this->isArray()) { + if (null === $default) { + $default = []; + } elseif (!\is_array($default)) { + throw new LogicException('A default value for an array option must be an array.'); + } + } + + $this->default = $this->acceptValue() ? $default : false; + } + + /** + * Returns the default value. + * + * @return string|string[]|int|bool|null The default value + */ + public function getDefault() + { + return $this->default; + } + + /** + * Returns the description text. + * + * @return string The description text + */ + public function getDescription() + { + return $this->description; + } + + /** + * Checks whether the given option equals this one. + * + * @return bool + */ + public function equals(self $option) + { + return $option->getName() === $this->getName() + && $option->getShortcut() === $this->getShortcut() + && $option->getDefault() === $this->getDefault() + && $option->isArray() === $this->isArray() + && $option->isValueRequired() === $this->isValueRequired() + && $option->isValueOptional() === $this->isValueOptional() + ; + } +} diff --git a/vendor/symfony/console/Input/StreamableInputInterface.php b/vendor/symfony/console/Input/StreamableInputInterface.php new file mode 100644 index 0000000..d7e462f --- /dev/null +++ b/vendor/symfony/console/Input/StreamableInputInterface.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +/** + * StreamableInputInterface is the interface implemented by all input classes + * that have an input stream. + * + * @author Robin Chalas + */ +interface StreamableInputInterface extends InputInterface +{ + /** + * Sets the input stream to read from when interacting with the user. + * + * This is mainly useful for testing purpose. + * + * @param resource $stream The input stream + */ + public function setStream($stream); + + /** + * Returns the input stream. + * + * @return resource|null + */ + public function getStream(); +} diff --git a/vendor/symfony/console/Input/StringInput.php b/vendor/symfony/console/Input/StringInput.php new file mode 100644 index 0000000..0ec0197 --- /dev/null +++ b/vendor/symfony/console/Input/StringInput.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * StringInput represents an input provided as a string. + * + * Usage: + * + * $input = new StringInput('foo --bar="foobar"'); + * + * @author Fabien Potencier + */ +class StringInput extends ArgvInput +{ + const REGEX_STRING = '([^\s]+?)(?:\s|(?setTokens($this->tokenize($input)); + } + + /** + * Tokenizes a string. + * + * @throws InvalidArgumentException When unable to parse input (should never happen) + */ + private function tokenize(string $input): array + { + $tokens = []; + $length = \strlen($input); + $cursor = 0; + while ($cursor < $length) { + if (preg_match('/\s+/A', $input, $match, null, $cursor)) { + } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) { + $tokens[] = $match[1].$match[2].stripcslashes(str_replace(['"\'', '\'"', '\'\'', '""'], '', 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 + throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10))); + } + + $cursor += \strlen($match[0]); + } + + return $tokens; + } +} diff --git a/vendor/symfony/console/LICENSE b/vendor/symfony/console/LICENSE new file mode 100644 index 0000000..a677f43 --- /dev/null +++ b/vendor/symfony/console/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/console/Logger/ConsoleLogger.php b/vendor/symfony/console/Logger/ConsoleLogger.php new file mode 100644 index 0000000..3236118 --- /dev/null +++ b/vendor/symfony/console/Logger/ConsoleLogger.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Logger; + +use Psr\Log\AbstractLogger; +use Psr\Log\InvalidArgumentException; +use Psr\Log\LogLevel; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * PSR-3 compliant console logger. + * + * @author Kévin Dunglas + * + * @see https://www.php-fig.org/psr/psr-3/ + */ +class ConsoleLogger extends AbstractLogger +{ + const INFO = 'info'; + const ERROR = 'error'; + + private $output; + private $verbosityLevelMap = [ + LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, + LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, + LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL, + LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL, + LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL, + LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE, + LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE, + LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG, + ]; + private $formatLevelMap = [ + LogLevel::EMERGENCY => self::ERROR, + LogLevel::ALERT => self::ERROR, + LogLevel::CRITICAL => self::ERROR, + LogLevel::ERROR => self::ERROR, + LogLevel::WARNING => self::INFO, + LogLevel::NOTICE => self::INFO, + LogLevel::INFO => self::INFO, + LogLevel::DEBUG => self::INFO, + ]; + private $errored = false; + + public function __construct(OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = []) + { + $this->output = $output; + $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap; + $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap; + } + + /** + * {@inheritdoc} + * + * @return void + */ + public function log($level, $message, array $context = []) + { + if (!isset($this->verbosityLevelMap[$level])) { + throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); + } + + $output = $this->output; + + // Write to the error output if necessary and available + if (self::ERROR === $this->formatLevelMap[$level]) { + if ($this->output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + $this->errored = true; + } + + // the if condition check isn't necessary -- it's the same one that $output will do internally anyway. + // We only do it for efficiency here as the message formatting is relatively expensive. + if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) { + $output->writeln(sprintf('<%1$s>[%2$s] %3$s', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]); + } + } + + /** + * Returns true when any messages have been logged at error levels. + * + * @return bool + */ + public function hasErrored() + { + return $this->errored; + } + + /** + * Interpolates context values into the message placeholders. + * + * @author PHP Framework Interoperability Group + */ + private function interpolate(string $message, array $context): string + { + if (false === strpos($message, '{')) { + return $message; + } + + $replacements = []; + foreach ($context as $key => $val) { + if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { + $replacements["{{$key}}"] = $val; + } elseif ($val instanceof \DateTimeInterface) { + $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); + } elseif (\is_object($val)) { + $replacements["{{$key}}"] = '[object '.\get_class($val).']'; + } else { + $replacements["{{$key}}"] = '['.\gettype($val).']'; + } + } + + return strtr($message, $replacements); + } +} diff --git a/vendor/symfony/console/Output/BufferedOutput.php b/vendor/symfony/console/Output/BufferedOutput.php new file mode 100644 index 0000000..a5ad7ad --- /dev/null +++ b/vendor/symfony/console/Output/BufferedOutput.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +/** + * @author Jean-François Simon + */ +class BufferedOutput extends Output +{ + private $buffer = ''; + + /** + * Empties buffer and returns its content. + * + * @return string + */ + public function fetch() + { + $content = $this->buffer; + $this->buffer = ''; + + return $content; + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $message, bool $newline) + { + $this->buffer .= $message; + + if ($newline) { + $this->buffer .= PHP_EOL; + } + } +} diff --git a/vendor/symfony/console/Output/ConsoleOutput.php b/vendor/symfony/console/Output/ConsoleOutput.php new file mode 100644 index 0000000..8356d4d --- /dev/null +++ b/vendor/symfony/console/Output/ConsoleOutput.php @@ -0,0 +1,159 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * ConsoleOutput is the default class for all CLI output. It uses STDOUT and STDERR. + * + * This class is a convenient wrapper around `StreamOutput` for both STDOUT and STDERR. + * + * $output = new ConsoleOutput(); + * + * This is equivalent to: + * + * $output = new StreamOutput(fopen('php://stdout', 'w')); + * $stdErr = new StreamOutput(fopen('php://stderr', 'w')); + * + * @author Fabien Potencier + */ +class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface +{ + private $stderr; + private $consoleSectionOutputs = []; + + /** + * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) + * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) + * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) + */ + public function __construct(int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null) + { + parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter); + + $actualDecorated = $this->isDecorated(); + $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter()); + + if (null === $decorated) { + $this->setDecorated($actualDecorated && $this->stderr->isDecorated()); + } + } + + /** + * Creates a new output section. + */ + public function section(): ConsoleSectionOutput + { + return new ConsoleSectionOutput($this->getStream(), $this->consoleSectionOutputs, $this->getVerbosity(), $this->isDecorated(), $this->getFormatter()); + } + + /** + * {@inheritdoc} + */ + public function setDecorated(bool $decorated) + { + parent::setDecorated($decorated); + $this->stderr->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + public function setFormatter(OutputFormatterInterface $formatter) + { + parent::setFormatter($formatter); + $this->stderr->setFormatter($formatter); + } + + /** + * {@inheritdoc} + */ + public function setVerbosity(int $level) + { + parent::setVerbosity($level); + $this->stderr->setVerbosity($level); + } + + /** + * {@inheritdoc} + */ + public function getErrorOutput() + { + return $this->stderr; + } + + /** + * {@inheritdoc} + */ + public function setErrorOutput(OutputInterface $error) + { + $this->stderr = $error; + } + + /** + * Returns true if current environment supports writing console output to + * STDOUT. + * + * @return bool + */ + protected function hasStdoutSupport() + { + return false === $this->isRunningOS400(); + } + + /** + * Returns true if current environment supports writing console output to + * STDERR. + * + * @return bool + */ + protected function hasStderrSupport() + { + return false === $this->isRunningOS400(); + } + + /** + * Checks if current executing environment is IBM iSeries (OS400), which + * doesn't properly convert character-encodings between ASCII to EBCDIC. + */ + private function isRunningOS400(): bool + { + $checks = [ + \function_exists('php_uname') ? php_uname('s') : '', + getenv('OSTYPE'), + PHP_OS, + ]; + + return false !== stripos(implode(';', $checks), 'OS400'); + } + + /** + * @return resource + */ + private function openOutputStream() + { + if (!$this->hasStdoutSupport()) { + return fopen('php://output', 'w'); + } + + return @fopen('php://stdout', 'w') ?: fopen('php://output', 'w'); + } + + /** + * @return resource + */ + private function openErrorStream() + { + return fopen($this->hasStderrSupport() ? 'php://stderr' : 'php://output', 'w'); + } +} diff --git a/vendor/symfony/console/Output/ConsoleOutputInterface.php b/vendor/symfony/console/Output/ConsoleOutputInterface.php new file mode 100644 index 0000000..6b6635f --- /dev/null +++ b/vendor/symfony/console/Output/ConsoleOutputInterface.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +/** + * ConsoleOutputInterface is the interface implemented by ConsoleOutput class. + * This adds information about stderr and section output stream. + * + * @author Dariusz Górecki + */ +interface ConsoleOutputInterface extends OutputInterface +{ + /** + * Gets the OutputInterface for errors. + * + * @return OutputInterface + */ + public function getErrorOutput(); + + public function setErrorOutput(OutputInterface $error); + + public function section(): ConsoleSectionOutput; +} diff --git a/vendor/symfony/console/Output/ConsoleSectionOutput.php b/vendor/symfony/console/Output/ConsoleSectionOutput.php new file mode 100644 index 0000000..024d99d --- /dev/null +++ b/vendor/symfony/console/Output/ConsoleSectionOutput.php @@ -0,0 +1,143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Terminal; + +/** + * @author Pierre du Plessis + * @author Gabriel Ostrolucký + */ +class ConsoleSectionOutput extends StreamOutput +{ + private $content = []; + private $lines = 0; + private $sections; + private $terminal; + + /** + * @param resource $stream + * @param ConsoleSectionOutput[] $sections + */ + public function __construct($stream, array &$sections, int $verbosity, bool $decorated, OutputFormatterInterface $formatter) + { + parent::__construct($stream, $verbosity, $decorated, $formatter); + array_unshift($sections, $this); + $this->sections = &$sections; + $this->terminal = new Terminal(); + } + + /** + * Clears previous output for this section. + * + * @param int $lines Number of lines to clear. If null, then the entire output of this section is cleared + */ + public function clear(int $lines = null) + { + if (empty($this->content) || !$this->isDecorated()) { + return; + } + + if ($lines) { + array_splice($this->content, -($lines * 2)); // Multiply lines by 2 to cater for each new line added between content + } else { + $lines = $this->lines; + $this->content = []; + } + + $this->lines -= $lines; + + parent::doWrite($this->popStreamContentUntilCurrentSection($lines), false); + } + + /** + * Overwrites the previous output with a new message. + * + * @param array|string $message + */ + public function overwrite($message) + { + $this->clear(); + $this->writeln($message); + } + + public function getContent(): string + { + return implode('', $this->content); + } + + /** + * @internal + */ + public function addContent(string $input) + { + foreach (explode(PHP_EOL, $input) as $lineContent) { + $this->lines += ceil($this->getDisplayLength($lineContent) / $this->terminal->getWidth()) ?: 1; + $this->content[] = $lineContent; + $this->content[] = PHP_EOL; + } + } + + /** + * {@inheritdoc} + */ + protected function doWrite($message, $newline) + { + if (!$this->isDecorated()) { + parent::doWrite($message, $newline); + + return; + } + + $erasedContent = $this->popStreamContentUntilCurrentSection(); + + $this->addContent($message); + + parent::doWrite($message, true); + parent::doWrite($erasedContent, false); + } + + /** + * At initial stage, cursor is at the end of stream output. This method makes cursor crawl upwards until it hits + * current section. Then it erases content it crawled through. Optionally, it erases part of current section too. + */ + private function popStreamContentUntilCurrentSection(int $numberOfLinesToClearFromCurrentSection = 0): string + { + $numberOfLinesToClear = $numberOfLinesToClearFromCurrentSection; + $erasedContent = []; + + foreach ($this->sections as $section) { + if ($section === $this) { + break; + } + + $numberOfLinesToClear += $section->lines; + $erasedContent[] = $section->getContent(); + } + + if ($numberOfLinesToClear > 0) { + // move cursor up n lines + parent::doWrite(sprintf("\x1b[%dA", $numberOfLinesToClear), false); + // erase to end of screen + parent::doWrite("\x1b[0J", false); + } + + return implode('', array_reverse($erasedContent)); + } + + private function getDisplayLength(string $text): string + { + return Helper::strlenWithoutDecoration($this->getFormatter(), str_replace("\t", ' ', $text)); + } +} diff --git a/vendor/symfony/console/Output/NullOutput.php b/vendor/symfony/console/Output/NullOutput.php new file mode 100644 index 0000000..78a1cb4 --- /dev/null +++ b/vendor/symfony/console/Output/NullOutput.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * NullOutput suppresses all output. + * + * $output = new NullOutput(); + * + * @author Fabien Potencier + * @author Tobias Schultze + */ +class NullOutput implements OutputInterface +{ + /** + * {@inheritdoc} + */ + public function setFormatter(OutputFormatterInterface $formatter) + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function getFormatter() + { + // to comply with the interface we must return a OutputFormatterInterface + return new OutputFormatter(); + } + + /** + * {@inheritdoc} + */ + public function setDecorated(bool $decorated) + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function isDecorated() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function setVerbosity(int $level) + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function getVerbosity() + { + return self::VERBOSITY_QUIET; + } + + /** + * {@inheritdoc} + */ + public function isQuiet() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isVerbose() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function isVeryVerbose() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function isDebug() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function writeln($messages, int $options = self::OUTPUT_NORMAL) + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function write($messages, bool $newline = false, int $options = self::OUTPUT_NORMAL) + { + // do nothing + } +} diff --git a/vendor/symfony/console/Output/Output.php b/vendor/symfony/console/Output/Output.php new file mode 100644 index 0000000..ed13d58 --- /dev/null +++ b/vendor/symfony/console/Output/Output.php @@ -0,0 +1,174 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * Base class for output classes. + * + * There are five levels of verbosity: + * + * * normal: no option passed (normal output) + * * verbose: -v (more output) + * * very verbose: -vv (highly extended output) + * * debug: -vvv (all debug output) + * * quiet: -q (no output) + * + * @author Fabien Potencier + */ +abstract class Output implements OutputInterface +{ + private $verbosity; + private $formatter; + + /** + * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) + * @param bool $decorated Whether to decorate messages + * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) + */ + public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null) + { + $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity; + $this->formatter = $formatter ?: new OutputFormatter(); + $this->formatter->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + public function setFormatter(OutputFormatterInterface $formatter) + { + $this->formatter = $formatter; + } + + /** + * {@inheritdoc} + */ + public function getFormatter() + { + return $this->formatter; + } + + /** + * {@inheritdoc} + */ + public function setDecorated(bool $decorated) + { + $this->formatter->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + public function isDecorated() + { + return $this->formatter->isDecorated(); + } + + /** + * {@inheritdoc} + */ + public function setVerbosity(int $level) + { + $this->verbosity = $level; + } + + /** + * {@inheritdoc} + */ + public function getVerbosity() + { + return $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function isQuiet() + { + return self::VERBOSITY_QUIET === $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function isVerbose() + { + return self::VERBOSITY_VERBOSE <= $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function isVeryVerbose() + { + return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function isDebug() + { + return self::VERBOSITY_DEBUG <= $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function writeln($messages, int $options = self::OUTPUT_NORMAL) + { + $this->write($messages, true, $options); + } + + /** + * {@inheritdoc} + */ + public function write($messages, bool $newline = false, int $options = self::OUTPUT_NORMAL) + { + if (!is_iterable($messages)) { + $messages = [$messages]; + } + + $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN; + $type = $types & $options ?: self::OUTPUT_NORMAL; + + $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG; + $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL; + + if ($verbosity > $this->getVerbosity()) { + return; + } + + foreach ($messages as $message) { + switch ($type) { + case OutputInterface::OUTPUT_NORMAL: + $message = $this->formatter->format($message); + break; + case OutputInterface::OUTPUT_RAW: + break; + case OutputInterface::OUTPUT_PLAIN: + $message = strip_tags($this->formatter->format($message)); + break; + } + + $this->doWrite($message, $newline); + } + } + + /** + * Writes a message to the output. + */ + abstract protected function doWrite(string $message, bool $newline); +} diff --git a/vendor/symfony/console/Output/OutputInterface.php b/vendor/symfony/console/Output/OutputInterface.php new file mode 100644 index 0000000..38f82d8 --- /dev/null +++ b/vendor/symfony/console/Output/OutputInterface.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * OutputInterface is the interface implemented by all Output classes. + * + * @author Fabien Potencier + */ +interface OutputInterface +{ + const VERBOSITY_QUIET = 16; + const VERBOSITY_NORMAL = 32; + const VERBOSITY_VERBOSE = 64; + const VERBOSITY_VERY_VERBOSE = 128; + const VERBOSITY_DEBUG = 256; + + const OUTPUT_NORMAL = 1; + const OUTPUT_RAW = 2; + const OUTPUT_PLAIN = 4; + + /** + * Writes a message to the output. + * + * @param string|iterable $messages The message as an iterable of strings or a single string + * @param bool $newline Whether to add a newline + * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL + */ + public function write($messages, bool $newline = false, int $options = 0); + + /** + * Writes a message to the output and adds a newline at the end. + * + * @param string|iterable $messages The message as an iterable of strings or a single string + * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL + */ + public function writeln($messages, int $options = 0); + + /** + * Sets the verbosity of the output. + */ + public function setVerbosity(int $level); + + /** + * Gets the current verbosity of the output. + * + * @return int The current level of verbosity (one of the VERBOSITY constants) + */ + public function getVerbosity(); + + /** + * Returns whether verbosity is quiet (-q). + * + * @return bool true if verbosity is set to VERBOSITY_QUIET, false otherwise + */ + public function isQuiet(); + + /** + * Returns whether verbosity is verbose (-v). + * + * @return bool true if verbosity is set to VERBOSITY_VERBOSE, false otherwise + */ + public function isVerbose(); + + /** + * Returns whether verbosity is very verbose (-vv). + * + * @return bool true if verbosity is set to VERBOSITY_VERY_VERBOSE, false otherwise + */ + public function isVeryVerbose(); + + /** + * Returns whether verbosity is debug (-vvv). + * + * @return bool true if verbosity is set to VERBOSITY_DEBUG, false otherwise + */ + public function isDebug(); + + /** + * Sets the decorated flag. + */ + public function setDecorated(bool $decorated); + + /** + * Gets the decorated flag. + * + * @return bool true if the output will decorate messages, false otherwise + */ + public function isDecorated(); + + public function setFormatter(OutputFormatterInterface $formatter); + + /** + * Returns current output formatter instance. + * + * @return OutputFormatterInterface + */ + public function getFormatter(); +} diff --git a/vendor/symfony/console/Output/StreamOutput.php b/vendor/symfony/console/Output/StreamOutput.php new file mode 100644 index 0000000..0b24052 --- /dev/null +++ b/vendor/symfony/console/Output/StreamOutput.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * 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 + */ +class StreamOutput extends Output +{ + private $stream; + + /** + * @param resource $stream A stream resource + * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) + * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) + * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) + * + * @throws InvalidArgumentException When first argument is not a real stream + */ + public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = 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(); + } + + parent::__construct($verbosity, $decorated, $formatter); + } + + /** + * Gets the stream attached to this StreamOutput instance. + * + * @return resource A stream resource + */ + public function getStream() + { + return $this->stream; + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $message, bool $newline) + { + if ($newline) { + $message .= PHP_EOL; + } + + if (false === @fwrite($this->stream, $message)) { + // should never happen + throw new RuntimeException('Unable to write output.'); + } + + fflush($this->stream); + } + + /** + * Returns true if the stream supports colorization. + * + * Colorization is disabled if not supported by the stream: + * + * This is tricky on Windows, because Cygwin, Msys2 etc emulate pseudo + * terminals via named pipes, so we can only check the environment. + * + * Reference: Composer\XdebugHandler\Process::supportsColor + * https://github.com/composer/xdebug-handler + * + * @return bool true if the stream supports colorization, false otherwise + */ + protected function hasColorSupport() + { + // Follow https://no-color.org/ + if (isset($_SERVER['NO_COLOR']) || false !== getenv('NO_COLOR')) { + return false; + } + + if ('Hyper' === getenv('TERM_PROGRAM')) { + return true; + } + + if (\DIRECTORY_SEPARATOR === '\\') { + return (\function_exists('sapi_windows_vt100_support') + && @sapi_windows_vt100_support($this->stream)) + || false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM'); + } + + return stream_isatty($this->stream); + } +} diff --git a/vendor/symfony/console/Question/ChoiceQuestion.php b/vendor/symfony/console/Question/ChoiceQuestion.php new file mode 100644 index 0000000..020b733 --- /dev/null +++ b/vendor/symfony/console/Question/ChoiceQuestion.php @@ -0,0 +1,182 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Question; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * Represents a choice question. + * + * @author Fabien Potencier + */ +class ChoiceQuestion extends Question +{ + private $choices; + private $multiselect = false; + private $prompt = ' > '; + private $errorMessage = 'Value "%s" is invalid'; + + /** + * @param string $question The question to ask to the user + * @param array $choices The list of available choices + * @param mixed $default The default answer to return + */ + public function __construct(string $question, array $choices, $default = null) + { + if (!$choices) { + throw new \LogicException('Choice question must have at least 1 choice available.'); + } + + parent::__construct($question, $default); + + $this->choices = $choices; + $this->setValidator($this->getDefaultValidator()); + $this->setAutocompleterValues($choices); + } + + /** + * Returns available choices. + * + * @return array + */ + public function getChoices() + { + return $this->choices; + } + + /** + * Sets multiselect option. + * + * When multiselect is set to true, multiple choices can be answered. + * + * @return $this + */ + public function setMultiselect(bool $multiselect) + { + $this->multiselect = $multiselect; + $this->setValidator($this->getDefaultValidator()); + + return $this; + } + + /** + * Returns whether the choices are multiselect. + * + * @return bool + */ + public function isMultiselect() + { + return $this->multiselect; + } + + /** + * Gets the prompt for choices. + * + * @return string + */ + public function getPrompt() + { + return $this->prompt; + } + + /** + * Sets the prompt for choices. + * + * @return $this + */ + public function setPrompt(string $prompt) + { + $this->prompt = $prompt; + + return $this; + } + + /** + * Sets the error message for invalid values. + * + * The error message has a string placeholder (%s) for the invalid value. + * + * @return $this + */ + public function setErrorMessage(string $errorMessage) + { + $this->errorMessage = $errorMessage; + $this->setValidator($this->getDefaultValidator()); + + return $this; + } + + private function getDefaultValidator(): callable + { + $choices = $this->choices; + $errorMessage = $this->errorMessage; + $multiselect = $this->multiselect; + $isAssoc = $this->isAssoc($choices); + + return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) { + if ($multiselect) { + // Check for a separated comma values + if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selected, $matches)) { + throw new InvalidArgumentException(sprintf($errorMessage, $selected)); + } + + $selectedChoices = explode(',', $selected); + } else { + $selectedChoices = [$selected]; + } + + if ($this->isTrimmable()) { + foreach ($selectedChoices as $k => $v) { + $selectedChoices[$k] = trim($v); + } + } + + $multiselectChoices = []; + foreach ($selectedChoices as $value) { + $results = []; + foreach ($choices as $key => $choice) { + if ($choice === $value) { + $results[] = $key; + } + } + + if (\count($results) > 1) { + throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results))); + } + + $result = array_search($value, $choices); + + if (!$isAssoc) { + if (false !== $result) { + $result = $choices[$result]; + } elseif (isset($choices[$value])) { + $result = $choices[$value]; + } + } elseif (false === $result && isset($choices[$value])) { + $result = $value; + } + + if (false === $result) { + throw new InvalidArgumentException(sprintf($errorMessage, $value)); + } + + $multiselectChoices[] = (string) $result; + } + + if ($multiselect) { + return $multiselectChoices; + } + + return current($multiselectChoices); + }; + } +} diff --git a/vendor/symfony/console/Question/ConfirmationQuestion.php b/vendor/symfony/console/Question/ConfirmationQuestion.php new file mode 100644 index 0000000..4228521 --- /dev/null +++ b/vendor/symfony/console/Question/ConfirmationQuestion.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Question; + +/** + * Represents a yes/no question. + * + * @author Fabien Potencier + */ +class ConfirmationQuestion extends Question +{ + private $trueAnswerRegex; + + /** + * @param string $question The question to ask to the user + * @param bool $default The default answer to return, true or false + * @param string $trueAnswerRegex A regex to match the "yes" answer + */ + public function __construct(string $question, bool $default = true, string $trueAnswerRegex = '/^y/i') + { + parent::__construct($question, $default); + + $this->trueAnswerRegex = $trueAnswerRegex; + $this->setNormalizer($this->getDefaultNormalizer()); + } + + /** + * Returns the default answer normalizer. + */ + private function getDefaultNormalizer(): callable + { + $default = $this->getDefault(); + $regex = $this->trueAnswerRegex; + + return function ($answer) use ($default, $regex) { + if (\is_bool($answer)) { + return $answer; + } + + $answerIsTrue = (bool) preg_match($regex, $answer); + if (false === $default) { + return $answer && $answerIsTrue; + } + + return '' === $answer || $answerIsTrue; + }; + } +} diff --git a/vendor/symfony/console/Question/Question.php b/vendor/symfony/console/Question/Question.php new file mode 100644 index 0000000..8b0e4d9 --- /dev/null +++ b/vendor/symfony/console/Question/Question.php @@ -0,0 +1,282 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Question; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Represents a Question. + * + * @author Fabien Potencier + */ +class Question +{ + private $question; + private $attempts; + private $hidden = false; + private $hiddenFallback = true; + private $autocompleterCallback; + private $validator; + private $default; + private $normalizer; + private $trimmable = true; + + /** + * @param string $question The question to ask to the user + * @param mixed $default The default answer to return if the user enters nothing + */ + public function __construct(string $question, $default = null) + { + $this->question = $question; + $this->default = $default; + } + + /** + * Returns the question. + * + * @return string + */ + public function getQuestion() + { + return $this->question; + } + + /** + * Returns the default answer. + * + * @return mixed + */ + public function getDefault() + { + return $this->default; + } + + /** + * Returns whether the user response must be hidden. + * + * @return bool + */ + public function isHidden() + { + return $this->hidden; + } + + /** + * Sets whether the user response must be hidden or not. + * + * @param bool $hidden + * + * @return $this + * + * @throws LogicException In case the autocompleter is also used + */ + public function setHidden($hidden) + { + if ($this->autocompleterCallback) { + throw new LogicException('A hidden question cannot use the autocompleter.'); + } + + $this->hidden = (bool) $hidden; + + return $this; + } + + /** + * In case the response can not be hidden, whether to fallback on non-hidden question or not. + * + * @return bool + */ + public function isHiddenFallback() + { + return $this->hiddenFallback; + } + + /** + * Sets whether to fallback on non-hidden question if the response can not be hidden. + * + * @param bool $fallback + * + * @return $this + */ + public function setHiddenFallback($fallback) + { + $this->hiddenFallback = (bool) $fallback; + + return $this; + } + + /** + * Gets values for the autocompleter. + * + * @return iterable|null + */ + public function getAutocompleterValues() + { + $callback = $this->getAutocompleterCallback(); + + return $callback ? $callback('') : null; + } + + /** + * Sets values for the autocompleter. + * + * @return $this + * + * @throws LogicException + */ + public function setAutocompleterValues(?iterable $values) + { + if (\is_array($values)) { + $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values); + + $callback = static function () use ($values) { + return $values; + }; + } elseif ($values instanceof \Traversable) { + $valueCache = null; + $callback = static function () use ($values, &$valueCache) { + return $valueCache ?? $valueCache = iterator_to_array($values, false); + }; + } else { + $callback = null; + } + + return $this->setAutocompleterCallback($callback); + } + + /** + * Gets the callback function used for the autocompleter. + */ + public function getAutocompleterCallback(): ?callable + { + return $this->autocompleterCallback; + } + + /** + * Sets the callback function used for the autocompleter. + * + * The callback is passed the user input as argument and should return an iterable of corresponding suggestions. + * + * @return $this + */ + public function setAutocompleterCallback(callable $callback = null): self + { + if ($this->hidden && null !== $callback) { + throw new LogicException('A hidden question cannot use the autocompleter.'); + } + + $this->autocompleterCallback = $callback; + + return $this; + } + + /** + * Sets a validator for the question. + * + * @return $this + */ + public function setValidator(callable $validator = null) + { + $this->validator = $validator; + + return $this; + } + + /** + * Gets the validator for the question. + * + * @return callable|null + */ + public function getValidator() + { + return $this->validator; + } + + /** + * Sets the maximum number of attempts. + * + * Null means an unlimited number of attempts. + * + * @return $this + * + * @throws InvalidArgumentException in case the number of attempts is invalid + */ + public function setMaxAttempts(?int $attempts) + { + if (null !== $attempts && $attempts < 1) { + throw new InvalidArgumentException('Maximum number of attempts must be a positive value.'); + } + + $this->attempts = $attempts; + + return $this; + } + + /** + * Gets the maximum number of attempts. + * + * Null means an unlimited number of attempts. + * + * @return int|null + */ + public function getMaxAttempts() + { + return $this->attempts; + } + + /** + * Sets a normalizer for the response. + * + * The normalizer can be a callable (a string), a closure or a class implementing __invoke. + * + * @return $this + */ + public function setNormalizer(callable $normalizer) + { + $this->normalizer = $normalizer; + + return $this; + } + + /** + * Gets the normalizer for the response. + * + * The normalizer can ba a callable (a string), a closure or a class implementing __invoke. + * + * @return callable|null + */ + public function getNormalizer() + { + return $this->normalizer; + } + + protected function isAssoc(array $array) + { + return (bool) \count(array_filter(array_keys($array), 'is_string')); + } + + public function isTrimmable(): bool + { + return $this->trimmable; + } + + /** + * @return $this + */ + public function setTrimmable(bool $trimmable): self + { + $this->trimmable = $trimmable; + + return $this; + } +} diff --git a/vendor/symfony/console/README.md b/vendor/symfony/console/README.md new file mode 100644 index 0000000..664a37c --- /dev/null +++ b/vendor/symfony/console/README.md @@ -0,0 +1,20 @@ +Console Component +================= + +The Console component eases the creation of beautiful and testable command line +interfaces. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/console/index.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) + +Credits +------- + +`Resources/bin/hiddeninput.exe` is a third party binary provided within this +component. Find sources and license at https://github.com/Seldaek/hidden-input. diff --git a/vendor/symfony/console/Resources/bin/hiddeninput.exe b/vendor/symfony/console/Resources/bin/hiddeninput.exe new file mode 100644 index 0000000000000000000000000000000000000000..c8cf65e8d819e6e525121cf6b21f1c2429746038 GIT binary patch literal 9216 zcmeHNe{@sVeZR8hV88~S)=Hp|Mpn({rC^@)BwNOI{ERJXCYlx+k1K6PLHo z_e!z_fhOzeA3JTX&-Z@s{rFOgjEwBlqjr!)9f zjyHz`A+ni`!0Taby{Uj5Y>jQq(k5A+X})PLWAi|{IZbtc8n^^trM{GI=P_15U6d?l zJJ3PW8XjfHpR}6`k{&5@JcEeH_SqQoQbU62o2YS30W)p_t&Fjy*RXQCZt$gCf|ao| zx&3R}m6|-Lfi@pua=$26n(UlnWo$>K67*|+#(qL_An=?l0M02AhOSJDv3;~?1ORfw z76EdK#MpSHqACHLcnJLIYlCSiX4eS@Pr8rN)Xwz0dk7O*y^0_C(Yks2Kvg! z-d-fJ)F9@k?>)m(XqDKIe2OKfhCQde9fpO0ko24yn*4xzX7q+ze`Z*=aJgwV?D?73 zaJ8UkSk|NN>@-|mB*f`EIK7$ElgAB<7p&p`^Vuq$58#;?B^*Bz7&d$B#+AYUC z(^m|`7{lqx&b^5$;i`j|S!+u|lcaQplp_&Nb)!>r>vGh3wb!tW zLq6%bkSt8jO|(vWH>LiPV(Xkp%BiGhl1q!PXXNKVKE!>Y5cHc2%cJOJA{-&ZsSn`T z#8~TA#(HWH4m>uCd+kCMTFgMI*s*n3!iCOwEI`{vGcVhzDu!Lw%-Ea^JATtrF`q3`+#KvvYJ0vM~A}D#LOD zlw`4ncB0U*Jji=--Wz#>I&5?hy;MgYW2u91d8ob=7MWfY`u;7Xe-J{Qsb0=0p|SM2 zG|=~mERIj4?gi)Ew|{LIN#oAsh20k_khIYjJBBN6rrIJ=eQO=nE;rTnPSiaQS$1$# z+|JRh0!IbQIa*f1(TZ}QM;|WO0+jTy(e)ggN4>zqp2E>C>hGPLHjHBh--2%@{EZNE zbUk{<3MABX&20QwK{MxK8`1Vk>^%dO5i@VTfu>NG3$K4NC=hSPsj9UYy`rNO}sBnB9QdKdIk7G+2_amnWstdTYVg z7HgLJGC~XLZG`63GwH8PdO_+G(k6~?J8Wj5mQos#21kC4W#2)guQXI)!z^{@F)U)5 z*re+r(2dib3D4P~%Z6TL=$PIkpmm<_#isu%t=%DcIwNkJhMeJ|bpahHO%8h|y~Ccf zUg#xVk+dyu>Q1O7JZ~8KS>tqi0qK**X*y6yHM71`bT=kFZ=@E%oe2!Km1^2sa>v+onZ%x_>aOJF+N0{i~z|<(IzgT*{0PpQq}E zQpU35@bm;qI?t_znGI&5&4sZV>+%m}w$(4hSDvLk)l<{5XyMlnCl7C%AjM3XnWvVz z{NoFsX)JB)SoqABZxUa*Yq+^^(cbq4mL%^lO12c${z{pf+)|kTTI~nQywyYF6}6|8 zlsN9&{-vwTrTyu<5^90_AsIU-ID#ZG@6d%poU44<**%xVe?`uxf}_Mr$SLHLS|K_N zQnw>(Lr2U=%$-<2D~RSzbG)2W2u^KMDnFFE?GmmbQ)V)fty957F`4OvQ_25E68ITr z5?`suu`|v?r!y=gFOGj$%9IJ zuTP=&2GcnoZZ0qSe6YL-*-lg>Q#>?Ew`a=GDc4vI#<1sNdKn?n7iSj0Orl$-#FMFi zykr>X-Xvi>sVr;92+8*H!r|3L$#o~hXa0z>AmF=z z?|@FF;*S|S0yqsw0j>Z(3mX-HD!|{N-vYc9paC8Ld=|6?00!6(_%lERupO`&um*4k z0b~W>e*uhTe4;V;mq>(ox$9FB`wLt!*DKj~!aOh|fL&#Pg*b??tm%5~_6M#02wqeC zS~wO>TWGnSp^r<0&8f2V6W->w=C+p~daC5e5wNQM*(* z66^}b0(!q3)zq$mu&VnbR#nr3;h5DS*o7{y66=!#;Dy4$pd1ZH<6WEOi0oJ8SxRL* z*v-9@Z^2w%^S(w5dO{_9Duby%2RT~;ppxaE$l()x6&}>7Wcg=u_&>f`Vs8OJGTy{X z2HpG=ThJz<{%|4Qq-~ad0qcrc87n88DHpM(nypwXIkZn<{zIT$ul&BQ?{ApCAZtyr zs2YpNt@x(G*faTU*HCKnAk(G=Tl~>r1QK8LY~J8mFFGoN5iIkYSwlm4Lsj#g4dsE5 zU-4;*Kdh-zv!rT4N$O}Q&n)?v0-9Y)lRFz58^P-KtKonzrfQ1p@0V_10^0||cGRn9 zRG<-#_TEV2nn4{BOh{YVBR4e!V!D?0K%BAlQN!D%M#k1bHypiIHT)5tlj>p0Pp_;+ z!cqC-JIs@JRhB+#teGs$Cib_=(yjRo4OJg^YPg%58aJVsC(LQ?W6%pn!-#aMZwoPcopo^Rn6BE z3=c5&W5~pP(C(-2r;PnH-S0{F`runM0ERCf3rESX$+S(MKOXmKJL9zXF}9-lf^xUs z+bb)+P%L&gV@<4q{6w^xEJ>Y>TQFUeoz0o-yq)jUqww=?wjUO8Y{a5G;DJ0Jr!LL+ zWhgsLuzi&eDrGDn$2DJwpFfH-?SGWbr>qRb?v{P`_%)So)CQgzO^HQ%;y#tJ=knH4 z95jX;^bF#BiuTH^%-j}{9VrZD=R%Q%wselH^p>5 z7d>gWB-st&3Fj%Mt*|tR5iK3J=`xhs&G)I7E>`FO@o7L z@S$B!pYMuzz5DN@X!O4DPm5n@raPJn-Q#o*m*e^5lk$g?0esg%$;>g5QW-|;c=H2GM}bo2tW^D924wmOkrUbWxcQ# z#v6bP%Tdfe~jtCRzAL;-OahZ=#yvUixu2-9fD2j$*|YY`F?0wF-{a# ztr<&kZjZ+81}6ZESqtgW)8kP#s@VLTSUR{}6?U^R*x7RE3Rl&n=VnFFqg9Uqz1n@N9N|=9<4} zuJfy^+}|D9X&vm3MAdqmu0&UMd^=K>b1hLAm_E!$rZC2b;;T~Dl zI`Eo_yRY76uM})|6wk9->of(=9&4jLv5#p@OzS~Yl>@pG)^>6`R+KtL{<4ly4o9WiM!%p_pfROU354)e8PIeE z1_s?#;OX6waNvvb&UQRN(WLbR+}&b#jo&WY-LlwCX}Q*$jGuKYuOGoIoyR(>e}}ix z+t}Q^cEcC8Y{@h}>HmJ^gD!l@gzwHmiBKl26x_lZVZG2UY!`w;RJd122;US&geQdW z3Qq}R!gIo5;ka;0I4c-Jq5X6A6?VzK&c4y!ZXdAUYu{r}*!SBXw?Aor+J4-A(*COb zb^CwV-?3k`zi-cX*c`VzL`RLI(b4MgIrGN z%ojf`E*6)Gg1A9!7q^N##2zsss^V9~-Qt7d!{UDNZ^XY9pA^3@9ui*?e=7c5d`nD; z?}~R(p>y1Kw!>|X4ycYEAkcZa*n-R%y! zqi)Up756UpqwfE7=hfigw$k~G@25gaxF9UGTkV>C(7x1Rbx4jb#|}rxq0vQ!n-c#f J0sQ~1{4brj`U(I5 literal 0 HcmV?d00001 diff --git a/vendor/symfony/console/Style/OutputStyle.php b/vendor/symfony/console/Style/OutputStyle.php new file mode 100644 index 0000000..d46947f --- /dev/null +++ b/vendor/symfony/console/Style/OutputStyle.php @@ -0,0 +1,153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Style; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Decorates output to add console style guide helpers. + * + * @author Kevin Bond + */ +abstract class OutputStyle implements OutputInterface, StyleInterface +{ + private $output; + + public function __construct(OutputInterface $output) + { + $this->output = $output; + } + + /** + * {@inheritdoc} + */ + public function newLine(int $count = 1) + { + $this->output->write(str_repeat(PHP_EOL, $count)); + } + + /** + * @return ProgressBar + */ + public function createProgressBar(int $max = 0) + { + return new ProgressBar($this->output, $max); + } + + /** + * {@inheritdoc} + */ + public function write($messages, bool $newline = false, int $type = self::OUTPUT_NORMAL) + { + $this->output->write($messages, $newline, $type); + } + + /** + * {@inheritdoc} + */ + public function writeln($messages, int $type = self::OUTPUT_NORMAL) + { + $this->output->writeln($messages, $type); + } + + /** + * {@inheritdoc} + */ + public function setVerbosity(int $level) + { + $this->output->setVerbosity($level); + } + + /** + * {@inheritdoc} + */ + public function getVerbosity() + { + return $this->output->getVerbosity(); + } + + /** + * {@inheritdoc} + */ + public function setDecorated(bool $decorated) + { + $this->output->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + public function isDecorated() + { + return $this->output->isDecorated(); + } + + /** + * {@inheritdoc} + */ + public function setFormatter(OutputFormatterInterface $formatter) + { + $this->output->setFormatter($formatter); + } + + /** + * {@inheritdoc} + */ + public function getFormatter() + { + return $this->output->getFormatter(); + } + + /** + * {@inheritdoc} + */ + public function isQuiet() + { + return $this->output->isQuiet(); + } + + /** + * {@inheritdoc} + */ + public function isVerbose() + { + return $this->output->isVerbose(); + } + + /** + * {@inheritdoc} + */ + public function isVeryVerbose() + { + return $this->output->isVeryVerbose(); + } + + /** + * {@inheritdoc} + */ + public function isDebug() + { + return $this->output->isDebug(); + } + + protected function getErrorOutput() + { + if (!$this->output instanceof ConsoleOutputInterface) { + return $this->output; + } + + return $this->output->getErrorOutput(); + } +} diff --git a/vendor/symfony/console/Style/StyleInterface.php b/vendor/symfony/console/Style/StyleInterface.php new file mode 100644 index 0000000..afb841c --- /dev/null +++ b/vendor/symfony/console/Style/StyleInterface.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Style; + +/** + * Output style helpers. + * + * @author Kevin Bond + */ +interface StyleInterface +{ + /** + * Formats a command title. + */ + public function title(string $message); + + /** + * Formats a section title. + */ + public function section(string $message); + + /** + * Formats a list. + */ + public function listing(array $elements); + + /** + * Formats informational text. + * + * @param string|array $message + */ + public function text($message); + + /** + * Formats a success result bar. + * + * @param string|array $message + */ + public function success($message); + + /** + * Formats an error result bar. + * + * @param string|array $message + */ + public function error($message); + + /** + * Formats an warning result bar. + * + * @param string|array $message + */ + public function warning($message); + + /** + * Formats a note admonition. + * + * @param string|array $message + */ + public function note($message); + + /** + * Formats a caution admonition. + * + * @param string|array $message + */ + public function caution($message); + + /** + * Formats a table. + */ + public function table(array $headers, array $rows); + + /** + * Asks a question. + * + * @return mixed + */ + public function ask(string $question, ?string $default = null, callable $validator = null); + + /** + * Asks a question with the user input hidden. + * + * @return mixed + */ + public function askHidden(string $question, callable $validator = null); + + /** + * Asks for confirmation. + * + * @return bool + */ + public function confirm(string $question, bool $default = true); + + /** + * Asks a choice question. + * + * @param string|int|null $default + * + * @return mixed + */ + public function choice(string $question, array $choices, $default = null); + + /** + * Add newline(s). + */ + public function newLine(int $count = 1); + + /** + * Starts the progress output. + */ + public function progressStart(int $max = 0); + + /** + * Advances the progress output X steps. + */ + public function progressAdvance(int $step = 1); + + /** + * Finishes the progress output. + */ + public function progressFinish(); +} diff --git a/vendor/symfony/console/Style/SymfonyStyle.php b/vendor/symfony/console/Style/SymfonyStyle.php new file mode 100644 index 0000000..eea624e --- /dev/null +++ b/vendor/symfony/console/Style/SymfonyStyle.php @@ -0,0 +1,499 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Style; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Helper\SymfonyQuestionHelper; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Helper\TableCell; +use Symfony\Component\Console\Helper\TableSeparator; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\BufferedOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Terminal; + +/** + * Output decorator helpers for the Symfony Style Guide. + * + * @author Kevin Bond + */ +class SymfonyStyle extends OutputStyle +{ + const MAX_LINE_LENGTH = 120; + + private $input; + private $questionHelper; + private $progressBar; + private $lineLength; + private $bufferedOutput; + + public function __construct(InputInterface $input, OutputInterface $output) + { + $this->input = $input; + $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter()); + // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not. + $width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH; + $this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH); + + parent::__construct($output); + } + + /** + * Formats a message as a block of text. + * + * @param string|array $messages The message to write in the block + */ + public function block($messages, ?string $type = null, ?string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = true) + { + $messages = \is_array($messages) ? array_values($messages) : [$messages]; + + $this->autoPrependBlock(); + $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape)); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function title(string $message) + { + $this->autoPrependBlock(); + $this->writeln([ + sprintf('%s', OutputFormatter::escapeTrailingBackslash($message)), + sprintf('%s', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))), + ]); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function section(string $message) + { + $this->autoPrependBlock(); + $this->writeln([ + sprintf('%s', OutputFormatter::escapeTrailingBackslash($message)), + sprintf('%s', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))), + ]); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function listing(array $elements) + { + $this->autoPrependText(); + $elements = array_map(function ($element) { + return sprintf(' * %s', $element); + }, $elements); + + $this->writeln($elements); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function text($message) + { + $this->autoPrependText(); + + $messages = \is_array($message) ? array_values($message) : [$message]; + foreach ($messages as $message) { + $this->writeln(sprintf(' %s', $message)); + } + } + + /** + * Formats a command comment. + * + * @param string|array $message + */ + public function comment($message) + { + $this->block($message, null, null, ' // ', false, false); + } + + /** + * {@inheritdoc} + */ + public function success($message) + { + $this->block($message, 'OK', 'fg=black;bg=green', ' ', true); + } + + /** + * {@inheritdoc} + */ + public function error($message) + { + $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true); + } + + /** + * {@inheritdoc} + */ + public function warning($message) + { + $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', true); + } + + /** + * {@inheritdoc} + */ + public function note($message) + { + $this->block($message, 'NOTE', 'fg=yellow', ' ! '); + } + + /** + * {@inheritdoc} + */ + public function caution($message) + { + $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true); + } + + /** + * {@inheritdoc} + */ + public function table(array $headers, array $rows) + { + $style = clone Table::getStyleDefinition('symfony-style-guide'); + $style->setCellHeaderFormat('%s'); + + $table = new Table($this); + $table->setHeaders($headers); + $table->setRows($rows); + $table->setStyle($style); + + $table->render(); + $this->newLine(); + } + + /** + * Formats a horizontal table. + */ + public function horizontalTable(array $headers, array $rows) + { + $style = clone Table::getStyleDefinition('symfony-style-guide'); + $style->setCellHeaderFormat('%s'); + + $table = new Table($this); + $table->setHeaders($headers); + $table->setRows($rows); + $table->setStyle($style); + $table->setHorizontal(true); + + $table->render(); + $this->newLine(); + } + + /** + * Formats a list of key/value horizontally. + * + * Each row can be one of: + * * 'A title' + * * ['key' => 'value'] + * * new TableSeparator() + * + * @param string|array|TableSeparator ...$list + */ + public function definitionList(...$list) + { + $style = clone Table::getStyleDefinition('symfony-style-guide'); + $style->setCellHeaderFormat('%s'); + + $table = new Table($this); + $headers = []; + $row = []; + foreach ($list as $value) { + if ($value instanceof TableSeparator) { + $headers[] = $value; + $row[] = $value; + continue; + } + if (\is_string($value)) { + $headers[] = new TableCell($value, ['colspan' => 2]); + $row[] = null; + continue; + } + if (!\is_array($value)) { + throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.'); + } + $headers[] = key($value); + $row[] = current($value); + } + + $table->setHeaders($headers); + $table->setRows([$row]); + $table->setHorizontal(); + $table->setStyle($style); + + $table->render(); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function ask(string $question, ?string $default = null, $validator = null) + { + $question = new Question($question, $default); + $question->setValidator($validator); + + return $this->askQuestion($question); + } + + /** + * {@inheritdoc} + */ + public function askHidden(string $question, $validator = null) + { + $question = new Question($question); + + $question->setHidden(true); + $question->setValidator($validator); + + return $this->askQuestion($question); + } + + /** + * {@inheritdoc} + */ + public function confirm($question, $default = true) + { + return $this->askQuestion(new ConfirmationQuestion($question, $default)); + } + + /** + * {@inheritdoc} + */ + public function choice(string $question, array $choices, $default = null) + { + if (null !== $default) { + $values = array_flip($choices); + $default = $values[$default]; + } + + return $this->askQuestion(new ChoiceQuestion($question, $choices, $default)); + } + + /** + * {@inheritdoc} + */ + public function progressStart(int $max = 0) + { + $this->progressBar = $this->createProgressBar($max); + $this->progressBar->start(); + } + + /** + * {@inheritdoc} + */ + public function progressAdvance(int $step = 1) + { + $this->getProgressBar()->advance($step); + } + + /** + * {@inheritdoc} + */ + public function progressFinish() + { + $this->getProgressBar()->finish(); + $this->newLine(2); + $this->progressBar = null; + } + + /** + * {@inheritdoc} + */ + public function createProgressBar(int $max = 0) + { + $progressBar = parent::createProgressBar($max); + + if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) { + $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591 + $progressBar->setProgressCharacter(''); + $progressBar->setBarCharacter('▓'); // dark shade character \u2593 + } + + return $progressBar; + } + + /** + * @return mixed + */ + public function askQuestion(Question $question) + { + if ($this->input->isInteractive()) { + $this->autoPrependBlock(); + } + + if (!$this->questionHelper) { + $this->questionHelper = new SymfonyQuestionHelper(); + } + + $answer = $this->questionHelper->ask($this->input, $this, $question); + + if ($this->input->isInteractive()) { + $this->newLine(); + $this->bufferedOutput->write("\n"); + } + + return $answer; + } + + /** + * {@inheritdoc} + */ + public function writeln($messages, int $type = self::OUTPUT_NORMAL) + { + if (!is_iterable($messages)) { + $messages = [$messages]; + } + + foreach ($messages as $message) { + parent::writeln($message, $type); + $this->writeBuffer($message, true, $type); + } + } + + /** + * {@inheritdoc} + */ + public function write($messages, bool $newline = false, int $type = self::OUTPUT_NORMAL) + { + if (!is_iterable($messages)) { + $messages = [$messages]; + } + + foreach ($messages as $message) { + parent::write($message, $newline, $type); + $this->writeBuffer($message, $newline, $type); + } + } + + /** + * {@inheritdoc} + */ + public function newLine(int $count = 1) + { + parent::newLine($count); + $this->bufferedOutput->write(str_repeat("\n", $count)); + } + + /** + * Returns a new instance which makes use of stderr if available. + * + * @return self + */ + public function getErrorStyle() + { + return new self($this->input, $this->getErrorOutput()); + } + + private function getProgressBar(): ProgressBar + { + if (!$this->progressBar) { + throw new RuntimeException('The ProgressBar is not started.'); + } + + return $this->progressBar; + } + + private function autoPrependBlock(): void + { + $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2); + + if (!isset($chars[0])) { + $this->newLine(); //empty history, so we should start with a new line. + + return; + } + //Prepend new line for each non LF chars (This means no blank line was output before) + $this->newLine(2 - substr_count($chars, "\n")); + } + + private function autoPrependText(): void + { + $fetched = $this->bufferedOutput->fetch(); + //Prepend new line if last char isn't EOL: + if ("\n" !== substr($fetched, -1)) { + $this->newLine(); + } + } + + private function writeBuffer(string $message, bool $newLine, int $type): void + { + // We need to know if the two last chars are PHP_EOL + // Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer + $this->bufferedOutput->write(substr($message, -4), $newLine, $type); + } + + private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false): array + { + $indentLength = 0; + $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix); + $lines = []; + + if (null !== $type) { + $type = sprintf('[%s] ', $type); + $indentLength = \strlen($type); + $lineIndentation = str_repeat(' ', $indentLength); + } + + // wrap and add newlines for each element + foreach ($messages as $key => $message) { + if ($escape) { + $message = OutputFormatter::escape($message); + } + + $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true))); + + if (\count($messages) > 1 && $key < \count($messages) - 1) { + $lines[] = ''; + } + } + + $firstLineIndex = 0; + if ($padding && $this->isDecorated()) { + $firstLineIndex = 1; + array_unshift($lines, ''); + $lines[] = ''; + } + + foreach ($lines as $i => &$line) { + if (null !== $type) { + $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line; + } + + $line = $prefix.$line; + $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line)); + + if ($style) { + $line = sprintf('<%s>%s', $style, $line); + } + } + + return $lines; + } +} diff --git a/vendor/symfony/console/Terminal.php b/vendor/symfony/console/Terminal.php new file mode 100644 index 0000000..b8cc04e --- /dev/null +++ b/vendor/symfony/console/Terminal.php @@ -0,0 +1,169 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console; + +class Terminal +{ + private static $width; + private static $height; + private static $stty; + + /** + * Gets the terminal width. + * + * @return int + */ + public function getWidth() + { + $width = getenv('COLUMNS'); + if (false !== $width) { + return (int) trim($width); + } + + if (null === self::$width) { + self::initDimensions(); + } + + return self::$width ?: 80; + } + + /** + * Gets the terminal height. + * + * @return int + */ + public function getHeight() + { + $height = getenv('LINES'); + if (false !== $height) { + return (int) trim($height); + } + + if (null === self::$height) { + self::initDimensions(); + } + + return self::$height ?: 50; + } + + /** + * @internal + * + * @return bool + */ + public static function hasSttyAvailable() + { + if (null !== self::$stty) { + return self::$stty; + } + + exec('stty 2>&1', $output, $exitcode); + + return self::$stty = 0 === $exitcode; + } + + private static function initDimensions() + { + if ('\\' === \DIRECTORY_SEPARATOR) { + if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON')), $matches)) { + // extract [w, H] from "wxh (WxH)" + // or [w, h] from "wxh" + self::$width = (int) $matches[1]; + self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; + } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) { + // only use stty on Windows if the terminal does not support vt100 (e.g. Windows 7 + git-bash) + // testing for stty in a Windows 10 vt100-enabled console will implicitly disable vt100 support on STDOUT + self::initDimensionsUsingStty(); + } elseif (null !== $dimensions = self::getConsoleMode()) { + // extract [w, h] from "wxh" + self::$width = (int) $dimensions[0]; + self::$height = (int) $dimensions[1]; + } + } else { + self::initDimensionsUsingStty(); + } + } + + /** + * Returns whether STDOUT has vt100 support (some Windows 10+ configurations). + */ + private static function hasVt100Support(): bool + { + return \function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(fopen('php://stdout', 'w')); + } + + /** + * Initializes dimensions using the output of an stty columns line. + */ + private static function initDimensionsUsingStty() + { + if ($sttyString = self::getSttyColumns()) { + if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { + // extract [w, h] from "rows h; columns w;" + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; + } elseif (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) { + // extract [w, h] from "; h rows; w columns" + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; + } + } + } + + /** + * Runs and parses mode CON if it's available, suppressing any error output. + * + * @return int[]|null An array composed of the width and the height or null if it could not be parsed + */ + private static function getConsoleMode(): ?array + { + $info = self::readFromProcess('mode CON'); + + if (null === $info || !preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { + return null; + } + + return [(int) $matches[2], (int) $matches[1]]; + } + + /** + * Runs and parses stty -a if it's available, suppressing any error output. + */ + private static function getSttyColumns(): ?string + { + return self::readFromProcess('stty -a | grep columns'); + } + + private static function readFromProcess(string $command): ?string + { + if (!\function_exists('proc_open')) { + return null; + } + + $descriptorspec = [ + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ]; + + $process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]); + if (!\is_resource($process)) { + return null; + } + + $info = stream_get_contents($pipes[1]); + fclose($pipes[1]); + fclose($pipes[2]); + proc_close($process); + + return $info; + } +} diff --git a/vendor/symfony/console/Tester/ApplicationTester.php b/vendor/symfony/console/Tester/ApplicationTester.php new file mode 100644 index 0000000..9da40cf --- /dev/null +++ b/vendor/symfony/console/Tester/ApplicationTester.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tester; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Input\ArrayInput; + +/** + * Eases the testing of console applications. + * + * When testing an application, don't forget to disable the auto exit flag: + * + * $application = new Application(); + * $application->setAutoExit(false); + * + * @author Fabien Potencier + */ +class ApplicationTester +{ + use TesterTrait; + + private $application; + private $input; + private $statusCode; + + 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 + * * capture_stderr_separately: Make output of stdOut and stdErr separately available + * + * @return int The command exit code + */ + public function run(array $input, array $options = []) + { + $this->input = new ArrayInput($input); + if (isset($options['interactive'])) { + $this->input->setInteractive($options['interactive']); + } + + $shellInteractive = getenv('SHELL_INTERACTIVE'); + + if ($this->inputs) { + $this->input->setStream(self::createStream($this->inputs)); + putenv('SHELL_INTERACTIVE=1'); + } + + $this->initOutput($options); + + $this->statusCode = $this->application->run($this->input, $this->output); + + putenv($shellInteractive ? "SHELL_INTERACTIVE=$shellInteractive" : 'SHELL_INTERACTIVE'); + + return $this->statusCode; + } +} diff --git a/vendor/symfony/console/Tester/CommandTester.php b/vendor/symfony/console/Tester/CommandTester.php new file mode 100644 index 0000000..57efc9a --- /dev/null +++ b/vendor/symfony/console/Tester/CommandTester.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tester; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\ArrayInput; + +/** + * Eases the testing of console commands. + * + * @author Fabien Potencier + * @author Robin Chalas + */ +class CommandTester +{ + use TesterTrait; + + private $command; + private $input; + private $statusCode; + + public function __construct(Command $command) + { + $this->command = $command; + } + + /** + * Executes the command. + * + * Available execution options: + * + * * interactive: Sets the input interactive flag + * * decorated: Sets the output decorated flag + * * verbosity: Sets the output verbosity flag + * * capture_stderr_separately: Make output of stdOut and stdErr separately available + * + * @param array $input An array of command arguments and options + * @param array $options An array of execution options + * + * @return int The command exit code + */ + public function execute(array $input, array $options = []) + { + // set the command name automatically if the application requires + // this argument and no command name was passed + if (!isset($input['command']) + && (null !== $application = $this->command->getApplication()) + && $application->getDefinition()->hasArgument('command') + ) { + $input = array_merge(['command' => $this->command->getName()], $input); + } + + $this->input = new ArrayInput($input); + // Use an in-memory input stream even if no inputs are set so that QuestionHelper::ask() does not rely on the blocking STDIN. + $this->input->setStream(self::createStream($this->inputs)); + + if (isset($options['interactive'])) { + $this->input->setInteractive($options['interactive']); + } + + if (!isset($options['decorated'])) { + $options['decorated'] = false; + } + + $this->initOutput($options); + + return $this->statusCode = $this->command->run($this->input, $this->output); + } +} diff --git a/vendor/symfony/console/Tester/TesterTrait.php b/vendor/symfony/console/Tester/TesterTrait.php new file mode 100644 index 0000000..73ee010 --- /dev/null +++ b/vendor/symfony/console/Tester/TesterTrait.php @@ -0,0 +1,178 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tester; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\StreamOutput; + +/** + * @author Amrouche Hamza + */ +trait TesterTrait +{ + /** @var StreamOutput */ + private $output; + private $inputs = []; + private $captureStreamsIndependently = false; + + /** + * Gets the display returned by the last execution of the command or application. + * + * @return string The display + */ + public function getDisplay(bool $normalize = false) + { + if (null === $this->output) { + throw new \RuntimeException('Output not initialized, did you execute the command before requesting the display?'); + } + + rewind($this->output->getStream()); + + $display = stream_get_contents($this->output->getStream()); + + if ($normalize) { + $display = str_replace(PHP_EOL, "\n", $display); + } + + return $display; + } + + /** + * Gets the output written to STDERR by the application. + * + * @param bool $normalize Whether to normalize end of lines to \n or not + * + * @return string + */ + public function getErrorOutput(bool $normalize = false) + { + if (!$this->captureStreamsIndependently) { + throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.'); + } + + rewind($this->output->getErrorOutput()->getStream()); + + $display = stream_get_contents($this->output->getErrorOutput()->getStream()); + + if ($normalize) { + $display = str_replace(PHP_EOL, "\n", $display); + } + + return $display; + } + + /** + * Gets the input instance used by the last execution of the command or application. + * + * @return InputInterface The current input instance + */ + public function getInput() + { + return $this->input; + } + + /** + * Gets the output instance used by the last execution of the command or application. + * + * @return OutputInterface The current output instance + */ + public function getOutput() + { + return $this->output; + } + + /** + * Gets the status code returned by the last execution of the command or application. + * + * @return int The status code + */ + public function getStatusCode() + { + return $this->statusCode; + } + + /** + * Sets the user inputs. + * + * @param array $inputs An array of strings representing each input + * passed to the command input stream + * + * @return $this + */ + public function setInputs(array $inputs) + { + $this->inputs = $inputs; + + return $this; + } + + /** + * Initializes the output property. + * + * Available options: + * + * * decorated: Sets the output decorated flag + * * verbosity: Sets the output verbosity flag + * * capture_stderr_separately: Make output of stdOut and stdErr separately available + */ + private function initOutput(array $options) + { + $this->captureStreamsIndependently = \array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately']; + if (!$this->captureStreamsIndependently) { + $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']); + } + } else { + $this->output = new ConsoleOutput( + isset($options['verbosity']) ? $options['verbosity'] : ConsoleOutput::VERBOSITY_NORMAL, + isset($options['decorated']) ? $options['decorated'] : null + ); + + $errorOutput = new StreamOutput(fopen('php://memory', 'w', false)); + $errorOutput->setFormatter($this->output->getFormatter()); + $errorOutput->setVerbosity($this->output->getVerbosity()); + $errorOutput->setDecorated($this->output->isDecorated()); + + $reflectedOutput = new \ReflectionObject($this->output); + $strErrProperty = $reflectedOutput->getProperty('stderr'); + $strErrProperty->setAccessible(true); + $strErrProperty->setValue($this->output, $errorOutput); + + $reflectedParent = $reflectedOutput->getParentClass(); + $streamProperty = $reflectedParent->getProperty('stream'); + $streamProperty->setAccessible(true); + $streamProperty->setValue($this->output, fopen('php://memory', 'w', false)); + } + } + + /** + * @return resource + */ + private static function createStream(array $inputs) + { + $stream = fopen('php://memory', 'r+', false); + + foreach ($inputs as $input) { + fwrite($stream, $input.PHP_EOL); + } + + rewind($stream); + + return $stream; + } +} diff --git a/vendor/symfony/console/composer.json b/vendor/symfony/console/composer.json new file mode 100644 index 0000000..8948071 --- /dev/null +++ b/vendor/symfony/console/composer.json @@ -0,0 +1,60 @@ +{ + "name": "symfony/console", + "type": "library", + "description": "Symfony Console Component", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/service-contracts": "^1.1|^2" + }, + "require-dev": { + "symfony/config": "^4.4|^5.0", + "symfony/event-dispatcher": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0", + "psr/log": "~1.0" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "suggest": { + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "", + "psr/log": "For using the console logger" + }, + "conflict": { + "symfony/dependency-injection": "<4.4", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Console\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/dependency-injection/.gitattributes b/vendor/symfony/dependency-injection/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/dependency-injection/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/dependency-injection/Alias.php b/vendor/symfony/dependency-injection/Alias.php new file mode 100644 index 0000000..79e7e24 --- /dev/null +++ b/vendor/symfony/dependency-injection/Alias.php @@ -0,0 +1,133 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +class Alias +{ + private $id; + private $public; + private $private; + private $deprecated; + private $deprecationTemplate; + + private static $defaultDeprecationTemplate = 'The "%alias_id%" service alias is deprecated. You should stop using it, as it will be removed in the future.'; + + public function __construct(string $id, bool $public = true) + { + $this->id = $id; + $this->public = $public; + $this->private = 2 > \func_num_args(); + $this->deprecated = false; + } + + /** + * Checks if this DI Alias should be public or not. + * + * @return bool + */ + public function isPublic() + { + return $this->public; + } + + /** + * Sets if this Alias is public. + * + * @return $this + */ + public function setPublic(bool $boolean) + { + $this->public = $boolean; + $this->private = false; + + return $this; + } + + /** + * Sets if this Alias is private. + * + * When set, the "private" state has a higher precedence than "public". + * In version 3.4, a "private" alias always remains publicly accessible, + * but triggers a deprecation notice when accessed from the container, + * so that the alias can be made really private in 4.0. + * + * @return $this + */ + public function setPrivate(bool $boolean) + { + $this->private = $boolean; + + return $this; + } + + /** + * Whether this alias is private. + * + * @return bool + */ + public function isPrivate() + { + return $this->private; + } + + /** + * Whether this alias is deprecated, that means it should not be referenced + * anymore. + * + * @param bool $status Whether this alias is deprecated, defaults to true + * @param string $template Optional template message to use if the alias is deprecated + * + * @return $this + * + * @throws InvalidArgumentException when the message template is invalid + */ + public function setDeprecated(bool $status = true, string $template = null) + { + if (null !== $template) { + if (preg_match('#[\r\n]|\*/#', $template)) { + throw new InvalidArgumentException('Invalid characters found in deprecation template.'); + } + + if (false === strpos($template, '%alias_id%')) { + throw new InvalidArgumentException('The deprecation template must contain the "%alias_id%" placeholder.'); + } + + $this->deprecationTemplate = $template; + } + + $this->deprecated = $status; + + return $this; + } + + public function isDeprecated(): bool + { + return $this->deprecated; + } + + public function getDeprecationMessage(string $id): string + { + return str_replace('%alias_id%', $id, $this->deprecationTemplate ?: self::$defaultDeprecationTemplate); + } + + /** + * Returns the Id of this alias. + * + * @return string The alias id + */ + public function __toString() + { + return $this->id; + } +} diff --git a/vendor/symfony/dependency-injection/Argument/ArgumentInterface.php b/vendor/symfony/dependency-injection/Argument/ArgumentInterface.php new file mode 100644 index 0000000..b46eb77 --- /dev/null +++ b/vendor/symfony/dependency-injection/Argument/ArgumentInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Argument; + +/** + * Represents a complex argument containing nested values. + * + * @author Titouan Galopin + */ +interface ArgumentInterface +{ + /** + * @return array + */ + public function getValues(); + + public function setValues(array $values); +} diff --git a/vendor/symfony/dependency-injection/Argument/BoundArgument.php b/vendor/symfony/dependency-injection/Argument/BoundArgument.php new file mode 100644 index 0000000..6005926 --- /dev/null +++ b/vendor/symfony/dependency-injection/Argument/BoundArgument.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Argument; + +/** + * @author Guilhem Niot + */ +final class BoundArgument implements ArgumentInterface +{ + const SERVICE_BINDING = 0; + const DEFAULTS_BINDING = 1; + const INSTANCEOF_BINDING = 2; + + private static $sequence = 0; + + private $value; + private $identifier; + private $used; + private $type; + private $file; + + public function __construct($value, bool $trackUsage = true, int $type = 0, string $file = null) + { + $this->value = $value; + if ($trackUsage) { + $this->identifier = ++self::$sequence; + } else { + $this->used = true; + } + $this->type = $type; + $this->file = $file; + } + + /** + * {@inheritdoc} + */ + public function getValues(): array + { + return [$this->value, $this->identifier, $this->used, $this->type, $this->file]; + } + + /** + * {@inheritdoc} + */ + public function setValues(array $values) + { + if (5 === \count($values)) { + list($this->value, $this->identifier, $this->used, $this->type, $this->file) = $values; + } else { + list($this->value, $this->identifier, $this->used) = $values; + } + } +} diff --git a/vendor/symfony/dependency-injection/Argument/IteratorArgument.php b/vendor/symfony/dependency-injection/Argument/IteratorArgument.php new file mode 100644 index 0000000..d413678 --- /dev/null +++ b/vendor/symfony/dependency-injection/Argument/IteratorArgument.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Argument; + +/** + * Represents a collection of values to lazily iterate over. + * + * @author Titouan Galopin + */ +class IteratorArgument implements ArgumentInterface +{ + use ReferenceSetArgumentTrait; +} diff --git a/vendor/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php b/vendor/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php new file mode 100644 index 0000000..6f8d5d9 --- /dev/null +++ b/vendor/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Argument; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Titouan Galopin + * @author Nicolas Grekas + */ +trait ReferenceSetArgumentTrait +{ + private $values; + + /** + * @param Reference[] $values + */ + public function __construct(array $values) + { + $this->setValues($values); + } + + /** + * @return Reference[] The values in the set + */ + public function getValues() + { + return $this->values; + } + + /** + * @param Reference[] $values The service references to put in the set + */ + public function setValues(array $values) + { + foreach ($values as $k => $v) { + if (null !== $v && !$v instanceof Reference) { + throw new InvalidArgumentException(sprintf('A %s must hold only Reference instances, "%s" given.', __CLASS__, \is_object($v) ? \get_class($v) : \gettype($v))); + } + } + + $this->values = $values; + } +} diff --git a/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php b/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php new file mode 100644 index 0000000..41fec78 --- /dev/null +++ b/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Argument; + +/** + * @internal + */ +class RewindableGenerator implements \IteratorAggregate, \Countable +{ + private $generator; + private $count; + + /** + * @param int|callable $count + */ + public function __construct(callable $generator, $count) + { + $this->generator = $generator; + $this->count = $count; + } + + public function getIterator(): \Traversable + { + $g = $this->generator; + + return $g(); + } + + public function count(): int + { + if (\is_callable($count = $this->count)) { + $this->count = $count(); + } + + return $this->count; + } +} diff --git a/vendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php b/vendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php new file mode 100644 index 0000000..6331aff --- /dev/null +++ b/vendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Argument; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Represents a service wrapped in a memoizing closure. + * + * @author Nicolas Grekas + */ +class ServiceClosureArgument implements ArgumentInterface +{ + private $values; + + public function __construct(Reference $reference) + { + $this->values = [$reference]; + } + + /** + * {@inheritdoc} + */ + public function getValues() + { + return $this->values; + } + + /** + * {@inheritdoc} + */ + public function setValues(array $values) + { + if ([0] !== array_keys($values) || !($values[0] instanceof Reference || null === $values[0])) { + throw new InvalidArgumentException('A ServiceClosureArgument must hold one and only one Reference.'); + } + + $this->values = $values; + } +} diff --git a/vendor/symfony/dependency-injection/Argument/ServiceLocator.php b/vendor/symfony/dependency-injection/Argument/ServiceLocator.php new file mode 100644 index 0000000..2001a95 --- /dev/null +++ b/vendor/symfony/dependency-injection/Argument/ServiceLocator.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Argument; + +use Symfony\Component\DependencyInjection\ServiceLocator as BaseServiceLocator; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class ServiceLocator extends BaseServiceLocator +{ + private $factory; + private $serviceMap; + private $serviceTypes; + + public function __construct(\Closure $factory, array $serviceMap, array $serviceTypes = null) + { + $this->factory = $factory; + $this->serviceMap = $serviceMap; + $this->serviceTypes = $serviceTypes; + parent::__construct($serviceMap); + } + + /** + * {@inheritdoc} + */ + public function get($id) + { + return isset($this->serviceMap[$id]) ? ($this->factory)(...$this->serviceMap[$id]) : parent::get($id); + } + + /** + * {@inheritdoc} + */ + public function getProvidedServices(): array + { + return $this->serviceTypes ?? $this->serviceTypes = array_map(function () { return '?'; }, $this->serviceMap); + } +} diff --git a/vendor/symfony/dependency-injection/Argument/ServiceLocatorArgument.php b/vendor/symfony/dependency-injection/Argument/ServiceLocatorArgument.php new file mode 100644 index 0000000..fcbf478 --- /dev/null +++ b/vendor/symfony/dependency-injection/Argument/ServiceLocatorArgument.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Argument; + +use Symfony\Component\DependencyInjection\Reference; + +/** + * Represents a closure acting as a service locator. + * + * @author Nicolas Grekas + */ +class ServiceLocatorArgument implements ArgumentInterface +{ + use ReferenceSetArgumentTrait; + + private $taggedIteratorArgument; + + /** + * @param Reference[]|TaggedIteratorArgument $values + */ + public function __construct($values = []) + { + if ($values instanceof TaggedIteratorArgument) { + $this->taggedIteratorArgument = $values; + $this->values = []; + } else { + $this->setValues($values); + } + } + + public function getTaggedIteratorArgument(): ?TaggedIteratorArgument + { + return $this->taggedIteratorArgument; + } +} diff --git a/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php b/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php new file mode 100644 index 0000000..d1d5f6d --- /dev/null +++ b/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Argument; + +/** + * Represents a collection of services found by tag name to lazily iterate over. + * + * @author Roland Franssen + */ +class TaggedIteratorArgument extends IteratorArgument +{ + private $tag; + private $indexAttribute; + private $defaultIndexMethod; + private $defaultPriorityMethod; + private $needsIndexes = false; + + /** + * @param string $tag The name of the tag identifying the target services + * @param string|null $indexAttribute The name of the attribute that defines the key referencing each service in the tagged collection + * @param string|null $defaultIndexMethod The static method that should be called to get each service's key when their tag doesn't define the previous attribute + * @param bool $needsIndexes Whether indexes are required and should be generated when computing the map + * @param string|null $defaultPriorityMethod The static method that should be called to get each service's priority when their tag doesn't define the "priority" attribute + */ + public function __construct(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, bool $needsIndexes = false, string $defaultPriorityMethod = null) + { + parent::__construct([]); + + if (null === $indexAttribute && $needsIndexes) { + $indexAttribute = preg_match('/[^.]++$/', $tag, $m) ? $m[0] : $tag; + } + + $this->tag = $tag; + $this->indexAttribute = $indexAttribute; + $this->defaultIndexMethod = $defaultIndexMethod ?: ('getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute ?? ''))).'Name'); + $this->needsIndexes = $needsIndexes; + $this->defaultPriorityMethod = $defaultPriorityMethod ?: ('getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute ?? ''))).'Priority'); + } + + public function getTag() + { + return $this->tag; + } + + public function getIndexAttribute(): ?string + { + return $this->indexAttribute; + } + + public function getDefaultIndexMethod(): ?string + { + return $this->defaultIndexMethod; + } + + public function needsIndexes(): bool + { + return $this->needsIndexes; + } + + public function getDefaultPriorityMethod(): ?string + { + return $this->defaultPriorityMethod; + } +} diff --git a/vendor/symfony/dependency-injection/CHANGELOG.md b/vendor/symfony/dependency-injection/CHANGELOG.md new file mode 100644 index 0000000..b043220 --- /dev/null +++ b/vendor/symfony/dependency-injection/CHANGELOG.md @@ -0,0 +1,248 @@ +CHANGELOG +========= + +5.0.0 +----- + + * removed support for auto-discovered extension configuration class which does not implement `ConfigurationInterface` + * removed support for non-string default env() parameters + * moved `ServiceSubscriberInterface` to the `Symfony\Contracts\Service` namespace + * removed `RepeatedPass` and `RepeatablePassInterface` + * removed support for short factory/configurator syntax from `YamlFileLoader` + * removed `ResettableContainerInterface`, use `ResetInterface` instead + * added argument `$returnsClone` to `Definition::addMethodCall()` + * removed `tagged`, use `tagged_iterator` instead + +4.4.0 +----- + + * added `CheckTypeDeclarationsPass` to check injected parameters type during compilation + * added support for opcache.preload by generating a preloading script in the cache folder + * added support for dumping the container in one file instead of many files + * deprecated support for short factories and short configurators in Yaml + * added `tagged_iterator` alias for `tagged` which might be deprecated in a future version + * deprecated passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition` + * added support for binding iterable and tagged services + * made singly-implemented interfaces detection be scoped by file + * added ability to define a static priority method for tagged service + * added support for improved syntax to define method calls in Yaml + * made the `%env(base64:...)%` processor able to decode base64url + * added ability to choose behavior of decorations on non existent decorated services + +4.3.0 +----- + + * added `%env(trim:...)%` processor to trim a string value + * added `%env(default:param_name:...)%` processor to fallback to a parameter or to null when using `%env(default::...)%` + * added `%env(url:...)%` processor to convert an URL or DNS into an array of components + * added `%env(query_string:...)%` processor to convert a query string into an array of key values + * added support for deprecating aliases + * made `ContainerParametersResource` final and not implement `Serializable` anymore + * added `ReverseContainer`: a container that turns services back to their ids + * added ability to define an index for a tagged collection + * added ability to define an index for services in an injected service locator argument + * made `ServiceLocator` implement `ServiceProviderInterface` + * deprecated support for non-string default env() parameters + * added `%env(require:...)%` processor to `require()` a PHP file and use the value returned from it + +4.2.0 +----- + + * added `ContainerBuilder::registerAliasForArgument()` to support autowiring by type+name + * added support for binding by type+name + * added `ServiceSubscriberTrait` to ease implementing `ServiceSubscriberInterface` using methods' return types + * added `ServiceLocatorArgument` and `!service_locator` config tag for creating optimized service-locators + * added support for autoconfiguring bindings + * added `%env(key:...)%` processor to fetch a specific key from an array + * deprecated `ServiceSubscriberInterface`, use the same interface from the `Symfony\Contracts\Service` namespace instead + * deprecated `ResettableContainerInterface`, use `Symfony\Contracts\Service\ResetInterface` instead + +4.1.0 +----- + + * added support for variadics in named arguments + * added PSR-11 `ContainerBagInterface` and its `ContainerBag` implementation to access parameters as-a-service + * added support for service's decorators autowiring + * deprecated the `TypedReference::canBeAutoregistered()` and `TypedReference::getRequiringClass()` methods + * environment variables are validated when used in extension configuration + * deprecated support for auto-discovered extension configuration class which does not implement `ConfigurationInterface` + +4.0.0 +----- + + * Relying on service auto-registration while autowiring is not supported anymore. + Explicitly inject your dependencies or create services whose ids are + their fully-qualified class name. + + Before: + + ```php + namespace App\Controller; + + use App\Mailer; + + class DefaultController + { + public function __construct(Mailer $mailer) { + // ... + } + + // ... + } + ``` + ```yml + services: + App\Controller\DefaultController: + autowire: true + ``` + + After: + + ```php + // same PHP code + ``` + ```yml + services: + App\Controller\DefaultController: + autowire: true + + # or + # App\Controller\DefaultController: + # arguments: { $mailer: "@App\Mailer" } + + App\Mailer: + autowire: true + ``` + * removed autowiring services based on the types they implement + * added a third `$methodName` argument to the `getProxyFactoryCode()` method + of the `DumperInterface` + * removed support for autowiring types + * removed `Container::isFrozen` + * removed support for dumping an ucompiled container in `PhpDumper` + * removed support for generating a dumped `Container` without populating the method map + * removed support for case insensitive service identifiers + * removed the `DefinitionDecorator` class, replaced by `ChildDefinition` + * removed the `AutowireServiceResource` class and related `AutowirePass::createResourceForClass()` method + * removed `LoggingFormatter`, `Compiler::getLoggingFormatter()` and `addLogMessage()` class and methods, use the `ContainerBuilder::log()` method instead + * removed `FactoryReturnTypePass` + * removed `ContainerBuilder::addClassResource()`, use the `addObjectResource()` or the `getReflectionClass()` method instead. + * removed support for top-level anonymous services + * removed silent behavior for unused attributes and elements + * removed support for setting and accessing private services in `Container` + * removed support for setting pre-defined services in `Container` + * removed support for case insensitivity of parameter names + * removed `AutowireExceptionPass` and `AutowirePass::getAutowiringExceptions()`, use `Definition::addError()` and the `DefinitionErrorExceptionPass` instead + +3.4.0 +----- + + * moved the `ExtensionCompilerPass` to before-optimization passes with priority -1000 + * deprecated "public-by-default" definitions and aliases, the new default will be "private" in 4.0 + * added `EnvVarProcessorInterface` and corresponding "container.env_var_processor" tag for processing env vars + * added support for ignore-on-uninitialized references + * deprecated service auto-registration while autowiring + * deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method + * deprecated support for top-level anonymous services in XML + * deprecated case insensitivity of parameter names + * deprecated the `ResolveDefinitionTemplatesPass` class in favor of `ResolveChildDefinitionsPass` + * added `TaggedIteratorArgument` with YAML (`!tagged foo`) and XML (``) support + * deprecated `AutowireExceptionPass` and `AutowirePass::getAutowiringExceptions()`, use `Definition::addError()` and the `DefinitionErrorExceptionPass` instead + + +3.3.0 +----- + + * deprecated autowiring services based on the types they implement; + rename (or alias) your services to their FQCN id to make them autowirable + * added "ServiceSubscriberInterface" - to allow for per-class explicit service-locator definitions + * added "container.service_locator" tag for defining service-locator services + * added anonymous services support in YAML configuration files using the `!service` tag. + * added "TypedReference" and "ServiceClosureArgument" for creating service-locator services + * added `ServiceLocator` - a PSR-11 container holding a set of services to be lazily loaded + * added "instanceof" section for local interface-defined configs + * added prototype services for PSR4-based discovery and registration + * added `ContainerBuilder::getReflectionClass()` for retrieving and tracking reflection class info + * deprecated `ContainerBuilder::getClassResource()`, use `ContainerBuilder::getReflectionClass()` or `ContainerBuilder::addObjectResource()` instead + * added `ContainerBuilder::fileExists()` for checking and tracking file or directory existence + * deprecated autowiring-types, use aliases instead + * added support for omitting the factory class name in a service definition if the definition class is set + * deprecated case insensitivity of service identifiers + * added "iterator" argument type for lazy iteration over a set of values and services + * added file-wide configurable defaults for service attributes "public", "tags", + "autowire" and "autoconfigure" + * made the "class" attribute optional, using the "id" as fallback + * using the `PhpDumper` with an uncompiled `ContainerBuilder` is deprecated and + will not be supported anymore in 4.0 + * deprecated the `DefinitionDecorator` class in favor of `ChildDefinition` + * allow config files to be loaded using a glob pattern + * [BC BREAK] the `NullDumper` class is now final + +3.2.0 +----- + + * allowed to prioritize compiler passes by introducing a third argument to `PassConfig::addPass()`, to `Compiler::addPass` and to `ContainerBuilder::addCompilerPass()` + * added support for PHP constants in YAML configuration files + * deprecated the ability to set or unset a private service with the `Container::set()` method + * deprecated the ability to check for the existence of a private service with the `Container::has()` method + * deprecated the ability to request a private service with the `Container::get()` method + * deprecated support for generating a dumped `Container` without populating the method map + +3.0.0 +----- + + * removed all deprecated codes from 2.x versions + +2.8.0 +----- + + * deprecated the abstract ContainerAware class in favor of ContainerAwareTrait + * deprecated IntrospectableContainerInterface, to be merged with ContainerInterface in 3.0 + * allowed specifying a directory to recursively load all configuration files it contains + * deprecated the concept of scopes + * added `Definition::setShared()` and `Definition::isShared()` + * added ResettableContainerInterface to be able to reset the container to release memory on shutdown + * added a way to define the priority of service decoration + * added support for service autowiring + +2.7.0 +----- + + * deprecated synchronized services + +2.6.0 +----- + + * added new factory syntax and deprecated the old one + +2.5.0 +----- + +* added DecoratorServicePass and a way to override a service definition (Definition::setDecoratedService()) +* deprecated SimpleXMLElement class. + +2.4.0 +----- + + * added support for expressions in service definitions + * added ContainerAwareTrait to add default container aware behavior to a class + +2.2.0 +----- + + * added Extension::isConfigEnabled() to ease working with enableable configurations + * added an Extension base class with sensible defaults to be used in conjunction + with the Config component. + * added PrependExtensionInterface (to be able to allow extensions to prepend + application configuration settings for any Bundle) + +2.1.0 +----- + + * added IntrospectableContainerInterface (to be able to check if a service + has been initialized or not) + * added ConfigurationExtensionInterface + * added Definition::clearTag() + * component exceptions that inherit base SPL classes are now used exclusively + (this includes dumped containers) + * [BC BREAK] fixed unescaping of class arguments, method + ParameterBag::unescapeValue() was made public diff --git a/vendor/symfony/dependency-injection/ChildDefinition.php b/vendor/symfony/dependency-injection/ChildDefinition.php new file mode 100644 index 0000000..657a7fa --- /dev/null +++ b/vendor/symfony/dependency-injection/ChildDefinition.php @@ -0,0 +1,124 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; + +/** + * This definition extends another definition. + * + * @author Johannes M. Schmitt + */ +class ChildDefinition extends Definition +{ + private $parent; + + /** + * @param string $parent The id of Definition instance to decorate + */ + public function __construct(string $parent) + { + $this->parent = $parent; + $this->setPrivate(false); + } + + /** + * Returns the Definition to inherit from. + * + * @return string + */ + public function getParent() + { + return $this->parent; + } + + /** + * Sets the Definition to inherit from. + * + * @param string $parent + * + * @return $this + */ + public function setParent($parent) + { + $this->parent = $parent; + + return $this; + } + + /** + * Gets an argument to pass to the service constructor/factory method. + * + * If replaceArgument() has been used to replace an argument, this method + * will return the replacement value. + * + * @param int|string $index + * + * @return mixed The argument value + * + * @throws OutOfBoundsException When the argument does not exist + */ + public function getArgument($index) + { + if (\array_key_exists('index_'.$index, $this->arguments)) { + return $this->arguments['index_'.$index]; + } + + return parent::getArgument($index); + } + + /** + * You should always use this method when overwriting existing arguments + * of the parent definition. + * + * If you directly call setArguments() keep in mind that you must follow + * certain conventions when you want to overwrite the arguments of the + * parent definition, otherwise your arguments will only be appended. + * + * @param int|string $index + * @param mixed $value + * + * @return $this + * + * @throws InvalidArgumentException when $index isn't an integer + */ + public function replaceArgument($index, $value) + { + if (\is_int($index)) { + $this->arguments['index_'.$index] = $value; + } elseif (0 === strpos($index, '$')) { + $this->arguments[$index] = $value; + } else { + throw new InvalidArgumentException('The argument must be an existing index or the name of a constructor\'s parameter.'); + } + + return $this; + } + + /** + * @internal + */ + public function setAutoconfigured(bool $autoconfigured): self + { + throw new BadMethodCallException('A ChildDefinition cannot be autoconfigured.'); + } + + /** + * @internal + */ + public function setInstanceofConditionals(array $instanceof): self + { + throw new BadMethodCallException('A ChildDefinition cannot have instanceof conditionals set on it.'); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php b/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php new file mode 100644 index 0000000..2920af1 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php @@ -0,0 +1,223 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\LogicException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\ExpressionLanguage; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\ExpressionLanguage\Expression; + +/** + * @author Nicolas Grekas + */ +abstract class AbstractRecursivePass implements CompilerPassInterface +{ + /** + * @var ContainerBuilder + */ + protected $container; + protected $currentId; + + private $processExpressions = false; + private $expressionLanguage; + private $inExpression = false; + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->container = $container; + + try { + $this->processValue($container->getDefinitions(), true); + } finally { + $this->container = null; + } + } + + protected function enableExpressionProcessing() + { + $this->processExpressions = true; + } + + protected function inExpression(bool $reset = true): bool + { + $inExpression = $this->inExpression; + if ($reset) { + $this->inExpression = false; + } + + return $inExpression; + } + + /** + * Processes a value found in a definition tree. + * + * @param mixed $value + * + * @return mixed The processed value + */ + protected function processValue($value, bool $isRoot = false) + { + if (\is_array($value)) { + foreach ($value as $k => $v) { + if ($isRoot) { + $this->currentId = $k; + } + if ($v !== $processedValue = $this->processValue($v, $isRoot)) { + $value[$k] = $processedValue; + } + } + } elseif ($value instanceof ArgumentInterface) { + $value->setValues($this->processValue($value->getValues())); + } elseif ($value instanceof Expression && $this->processExpressions) { + $this->getExpressionLanguage()->compile((string) $value, ['this' => 'container']); + } elseif ($value instanceof Definition) { + $value->setArguments($this->processValue($value->getArguments())); + $value->setProperties($this->processValue($value->getProperties())); + $value->setMethodCalls($this->processValue($value->getMethodCalls())); + + $changes = $value->getChanges(); + if (isset($changes['factory'])) { + $value->setFactory($this->processValue($value->getFactory())); + } + if (isset($changes['configurator'])) { + $value->setConfigurator($this->processValue($value->getConfigurator())); + } + } + + return $value; + } + + /** + * @return \ReflectionFunctionAbstract|null + * + * @throws RuntimeException + */ + protected function getConstructor(Definition $definition, bool $required) + { + if ($definition->isSynthetic()) { + return null; + } + + if (\is_string($factory = $definition->getFactory())) { + if (!\function_exists($factory)) { + throw new RuntimeException(sprintf('Invalid service "%s": function "%s" does not exist.', $this->currentId, $factory)); + } + $r = new \ReflectionFunction($factory); + if (false !== $r->getFileName() && file_exists($r->getFileName())) { + $this->container->fileExists($r->getFileName()); + } + + return $r; + } + + if ($factory) { + list($class, $method) = $factory; + if ($class instanceof Reference) { + $class = $this->container->findDefinition((string) $class)->getClass(); + } elseif ($class instanceof Definition) { + $class = $class->getClass(); + } elseif (null === $class) { + $class = $definition->getClass(); + } + + if ('__construct' === $method) { + throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId)); + } + + return $this->getReflectionMethod(new Definition($class), $method); + } + + $class = $definition->getClass(); + + try { + if (!$r = $this->container->getReflectionClass($class)) { + throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class)); + } + } catch (\ReflectionException $e) { + throw new RuntimeException(sprintf('Invalid service "%s": %s.', $this->currentId, lcfirst(rtrim($e->getMessage(), '.')))); + } + if (!$r = $r->getConstructor()) { + if ($required) { + throw new RuntimeException(sprintf('Invalid service "%s": class%s has no constructor.', $this->currentId, sprintf($class !== $this->currentId ? ' "%s"' : '', $class))); + } + } elseif (!$r->isPublic()) { + throw new RuntimeException(sprintf('Invalid service "%s": %s must be public.', $this->currentId, sprintf($class !== $this->currentId ? 'constructor of class "%s"' : 'its constructor', $class))); + } + + return $r; + } + + /** + * @throws RuntimeException + * + * @return \ReflectionFunctionAbstract + */ + protected function getReflectionMethod(Definition $definition, string $method) + { + if ('__construct' === $method) { + return $this->getConstructor($definition, true); + } + + if (!$class = $definition->getClass()) { + throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId)); + } + + if (!$r = $this->container->getReflectionClass($class)) { + throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class)); + } + + if (!$r->hasMethod($method)) { + throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" does not exist.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method)); + } + + $r = $r->getMethod($method); + if (!$r->isPublic()) { + throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" must be public.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method)); + } + + return $r; + } + + private function getExpressionLanguage(): ExpressionLanguage + { + if (null === $this->expressionLanguage) { + if (!class_exists(ExpressionLanguage::class)) { + throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); + } + + $providers = $this->container->getExpressionLanguageProviders(); + $this->expressionLanguage = new ExpressionLanguage(null, $providers, function (string $arg): string { + if ('""' === substr_replace($arg, '', 1, -1)) { + $id = stripcslashes(substr($arg, 1, -1)); + $this->inExpression = true; + $arg = $this->processValue(new Reference($id)); + $this->inExpression = false; + if (!$arg instanceof Reference) { + throw new RuntimeException(sprintf('"%s::processValue()" must return a Reference when processing an expression, %s returned for service("%s").', \get_class($this), \is_object($arg) ? \get_class($arg) : \gettype($arg), $id)); + } + $arg = sprintf('"%s"', $arg); + } + + return sprintf('$this->get(%s)', $arg); + }); + } + + return $this->expressionLanguage; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php b/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php new file mode 100644 index 0000000..beb4882 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php @@ -0,0 +1,184 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Run this pass before passes that need to know more about the relation of + * your services. + * + * This class will populate the ServiceReferenceGraph with information. You can + * retrieve the graph in other passes from the compiler. + * + * @author Johannes M. Schmitt + * @author Nicolas Grekas + */ +class AnalyzeServiceReferencesPass extends AbstractRecursivePass +{ + private $graph; + private $currentDefinition; + private $onlyConstructorArguments; + private $hasProxyDumper; + private $lazy; + private $byConstructor; + private $definitions; + private $aliases; + + /** + * @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls + */ + public function __construct(bool $onlyConstructorArguments = false, bool $hasProxyDumper = true) + { + $this->onlyConstructorArguments = $onlyConstructorArguments; + $this->hasProxyDumper = $hasProxyDumper; + $this->enableExpressionProcessing(); + } + + /** + * Processes a ContainerBuilder object to populate the service reference graph. + */ + public function process(ContainerBuilder $container) + { + $this->container = $container; + $this->graph = $container->getCompiler()->getServiceReferenceGraph(); + $this->graph->clear(); + $this->lazy = false; + $this->byConstructor = false; + $this->definitions = $container->getDefinitions(); + $this->aliases = $container->getAliases(); + + foreach ($this->aliases as $id => $alias) { + $targetId = $this->getDefinitionId((string) $alias); + $this->graph->connect($id, $alias, $targetId, null !== $targetId ? $this->container->getDefinition($targetId) : null, null); + } + + try { + parent::process($container); + } finally { + $this->aliases = $this->definitions = []; + } + } + + protected function processValue($value, bool $isRoot = false) + { + $lazy = $this->lazy; + $inExpression = $this->inExpression(); + + if ($value instanceof ArgumentInterface) { + $this->lazy = true; + parent::processValue($value->getValues()); + $this->lazy = $lazy; + + return $value; + } + if ($value instanceof Reference) { + $targetId = $this->getDefinitionId((string) $value); + $targetDefinition = null !== $targetId ? $this->container->getDefinition($targetId) : null; + + $this->graph->connect( + $this->currentId, + $this->currentDefinition, + $targetId, + $targetDefinition, + $value, + $this->lazy || ($this->hasProxyDumper && $targetDefinition && $targetDefinition->isLazy()), + ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior(), + $this->byConstructor + ); + + if ($inExpression) { + $this->graph->connect( + '.internal.reference_in_expression', + null, + $targetId, + $targetDefinition, + $value, + $this->lazy || ($targetDefinition && $targetDefinition->isLazy()), + true + ); + } + + return $value; + } + if (!$value instanceof Definition) { + return parent::processValue($value, $isRoot); + } + if ($isRoot) { + if ($value->isSynthetic() || $value->isAbstract()) { + return $value; + } + $this->currentDefinition = $value; + } elseif ($this->currentDefinition === $value) { + return $value; + } + $this->lazy = false; + + $byConstructor = $this->byConstructor; + $this->byConstructor = $isRoot || $byConstructor; + $this->processValue($value->getFactory()); + $this->processValue($value->getArguments()); + + $properties = $value->getProperties(); + $setters = $value->getMethodCalls(); + + // Any references before a "wither" are part of the constructor-instantiation graph + $lastWitherIndex = null; + foreach ($setters as $k => $call) { + if ($call[2] ?? false) { + $lastWitherIndex = $k; + } + } + + if (null !== $lastWitherIndex) { + $this->processValue($properties); + $setters = $properties = []; + + foreach ($value->getMethodCalls() as $k => $call) { + if (null === $lastWitherIndex) { + $setters[] = $call; + continue; + } + + if ($lastWitherIndex === $k) { + $lastWitherIndex = null; + } + + $this->processValue($call); + } + } + + $this->byConstructor = $byConstructor; + + if (!$this->onlyConstructorArguments) { + $this->processValue($properties); + $this->processValue($setters); + $this->processValue($value->getConfigurator()); + } + $this->lazy = $lazy; + + return $value; + } + + private function getDefinitionId(string $id): ?string + { + while (isset($this->aliases[$id])) { + $id = (string) $this->aliases[$id]; + } + + return isset($this->definitions[$id]) ? $id : null; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php b/vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php new file mode 100644 index 0000000..0342068 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +/** + * Sets a service to be an alias of another one, given a format pattern. + */ +class AutoAliasServicePass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + foreach ($container->findTaggedServiceIds('auto_alias') as $serviceId => $tags) { + foreach ($tags as $tag) { + if (!isset($tag['format'])) { + throw new InvalidArgumentException(sprintf('Missing tag information "format" on auto_alias service "%s".', $serviceId)); + } + + $aliasId = $container->getParameterBag()->resolveValue($tag['format']); + if ($container->hasDefinition($aliasId) || $container->hasAlias($aliasId)) { + $container->setAlias($serviceId, new Alias($aliasId, true)); + } + } + } + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/AutowirePass.php b/vendor/symfony/dependency-injection/Compiler/AutowirePass.php new file mode 100644 index 0000000..ba10e92 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/AutowirePass.php @@ -0,0 +1,475 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\Config\Resource\ClassExistenceResource; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; +use Symfony\Component\DependencyInjection\TypedReference; + +/** + * Inspects existing service definitions and wires the autowired ones using the type hints of their classes. + * + * @author Kévin Dunglas + * @author Nicolas Grekas + */ +class AutowirePass extends AbstractRecursivePass +{ + private $types; + private $ambiguousServiceTypes; + private $lastFailure; + private $throwOnAutowiringException; + private $decoratedClass; + private $decoratedId; + private $methodCalls; + private $getPreviousValue; + private $decoratedMethodIndex; + private $decoratedMethodArgumentIndex; + private $typesClone; + + public function __construct(bool $throwOnAutowireException = true) + { + $this->throwOnAutowiringException = $throwOnAutowireException; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + try { + $this->typesClone = clone $this; + parent::process($container); + } finally { + $this->decoratedClass = null; + $this->decoratedId = null; + $this->methodCalls = null; + $this->getPreviousValue = null; + $this->decoratedMethodIndex = null; + $this->decoratedMethodArgumentIndex = null; + $this->typesClone = null; + } + } + + /** + * {@inheritdoc} + */ + protected function processValue($value, bool $isRoot = false) + { + try { + return $this->doProcessValue($value, $isRoot); + } catch (AutowiringFailedException $e) { + if ($this->throwOnAutowiringException) { + throw $e; + } + + $this->container->getDefinition($this->currentId)->addError($e->getMessageCallback() ?? $e->getMessage()); + + return parent::processValue($value, $isRoot); + } + } + + /** + * @return mixed + */ + private function doProcessValue($value, bool $isRoot = false) + { + if ($value instanceof TypedReference) { + if ($ref = $this->getAutowiredReference($value)) { + return $ref; + } + if (ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) { + $message = $this->createTypeNotFoundMessageCallback($value, 'it'); + + // since the error message varies by referenced id and $this->currentId, so should the id of the dummy errored definition + $this->container->register($id = sprintf('.errored.%s.%s', $this->currentId, (string) $value), $value->getType()) + ->addError($message); + + return new TypedReference($id, $value->getType(), $value->getInvalidBehavior(), $value->getName()); + } + } + $value = parent::processValue($value, $isRoot); + + if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) { + return $value; + } + if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) { + $this->container->log($this, sprintf('Skipping service "%s": Class or interface "%s" cannot be loaded.', $this->currentId, $value->getClass())); + + return $value; + } + + $this->methodCalls = $value->getMethodCalls(); + + try { + $constructor = $this->getConstructor($value, false); + } catch (RuntimeException $e) { + throw new AutowiringFailedException($this->currentId, $e->getMessage(), 0, $e); + } + + if ($constructor) { + array_unshift($this->methodCalls, [$constructor, $value->getArguments()]); + } + + $this->methodCalls = $this->autowireCalls($reflectionClass, $isRoot); + + if ($constructor) { + list(, $arguments) = array_shift($this->methodCalls); + + if ($arguments !== $value->getArguments()) { + $value->setArguments($arguments); + } + } + + if ($this->methodCalls !== $value->getMethodCalls()) { + $value->setMethodCalls($this->methodCalls); + } + + return $value; + } + + private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot): array + { + $this->decoratedId = null; + $this->decoratedClass = null; + $this->getPreviousValue = null; + + if ($isRoot && ($definition = $this->container->getDefinition($this->currentId)) && $this->container->has($this->decoratedId = $definition->innerServiceId)) { + $this->decoratedClass = $this->container->findDefinition($this->decoratedId)->getClass(); + } + + foreach ($this->methodCalls as $i => $call) { + $this->decoratedMethodIndex = $i; + list($method, $arguments) = $call; + + if ($method instanceof \ReflectionFunctionAbstract) { + $reflectionMethod = $method; + } else { + $definition = new Definition($reflectionClass->name); + try { + $reflectionMethod = $this->getReflectionMethod($definition, $method); + } catch (RuntimeException $e) { + if ($definition->getFactory()) { + continue; + } + throw $e; + } + } + + $arguments = $this->autowireMethod($reflectionMethod, $arguments); + + if ($arguments !== $call[1]) { + $this->methodCalls[$i][1] = $arguments; + } + } + + return $this->methodCalls; + } + + /** + * Autowires the constructor or a method. + * + * @return array The autowired arguments + * + * @throws AutowiringFailedException + */ + private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments): array + { + $class = $reflectionMethod instanceof \ReflectionMethod ? $reflectionMethod->class : $this->currentId; + $method = $reflectionMethod->name; + $parameters = $reflectionMethod->getParameters(); + if ($reflectionMethod->isVariadic()) { + array_pop($parameters); + } + + foreach ($parameters as $index => $parameter) { + if (\array_key_exists($index, $arguments) && '' !== $arguments[$index]) { + continue; + } + + $type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true); + + if (!$type) { + if (isset($arguments[$index])) { + continue; + } + + // no default value? Then fail + if (!$parameter->isDefaultValueAvailable()) { + // For core classes, isDefaultValueAvailable() can + // be false when isOptional() returns true. If the + // argument *is* optional, allow it to be missing + if ($parameter->isOptional()) { + continue; + } + $type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, false); + $type = $type ? sprintf('is type-hinted "%s"', ltrim($type, '\\')) : 'has no type-hint'; + + throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" %s, you should configure its value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method, $type)); + } + + // specifically pass the default value + $arguments[$index] = $parameter->getDefaultValue(); + + continue; + } + + $getValue = function () use ($type, $parameter, $class, $method) { + if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $parameter->name))) { + $failureMessage = $this->createTypeNotFoundMessageCallback($ref, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method)); + + if ($parameter->isDefaultValueAvailable()) { + $value = $parameter->getDefaultValue(); + } elseif (!$parameter->allowsNull()) { + throw new AutowiringFailedException($this->currentId, $failureMessage); + } + } + + return $value; + }; + + if ($this->decoratedClass && $isDecorated = is_a($this->decoratedClass, $type, true)) { + if ($this->getPreviousValue) { + // The inner service is injected only if there is only 1 argument matching the type of the decorated class + // across all arguments of all autowired methods. + // If a second matching argument is found, the default behavior is restored. + + $getPreviousValue = $this->getPreviousValue; + $this->methodCalls[$this->decoratedMethodIndex][1][$this->decoratedMethodArgumentIndex] = $getPreviousValue(); + $this->decoratedClass = null; // Prevent further checks + } else { + $arguments[$index] = new TypedReference($this->decoratedId, $this->decoratedClass); + $this->getPreviousValue = $getValue; + $this->decoratedMethodArgumentIndex = $index; + + continue; + } + } + + $arguments[$index] = $getValue(); + } + + if ($parameters && !isset($arguments[++$index])) { + while (0 <= --$index) { + $parameter = $parameters[$index]; + if (!$parameter->isDefaultValueAvailable() || $parameter->getDefaultValue() !== $arguments[$index]) { + break; + } + unset($arguments[$index]); + } + } + + // it's possible index 1 was set, then index 0, then 2, etc + // make sure that we re-order so they're injected as expected + ksort($arguments); + + return $arguments; + } + + /** + * Returns a reference to the service matching the given type, if any. + */ + private function getAutowiredReference(TypedReference $reference): ?TypedReference + { + $this->lastFailure = null; + $type = $reference->getType(); + + if ($type !== (string) $reference) { + return $reference; + } + + if (null !== $name = $reference->getName()) { + if ($this->container->has($alias = $type.' $'.$name) && !$this->container->findDefinition($alias)->isAbstract()) { + return new TypedReference($alias, $type, $reference->getInvalidBehavior()); + } + + if ($this->container->has($name) && !$this->container->findDefinition($name)->isAbstract()) { + foreach ($this->container->getAliases() as $id => $alias) { + if ($name === (string) $alias && 0 === strpos($id, $type.' $')) { + return new TypedReference($name, $type, $reference->getInvalidBehavior()); + } + } + } + } + + if ($this->container->has($type) && !$this->container->findDefinition($type)->isAbstract()) { + return new TypedReference($type, $type, $reference->getInvalidBehavior()); + } + + return null; + } + + /** + * Populates the list of available types. + */ + private function populateAvailableTypes(ContainerBuilder $container) + { + $this->types = []; + $this->ambiguousServiceTypes = []; + + foreach ($container->getDefinitions() as $id => $definition) { + $this->populateAvailableType($container, $id, $definition); + } + } + + /** + * Populates the list of available types for a given definition. + */ + private function populateAvailableType(ContainerBuilder $container, string $id, Definition $definition) + { + // Never use abstract services + if ($definition->isAbstract()) { + return; + } + + if ('' === $id || '.' === $id[0] || $definition->isDeprecated() || !$reflectionClass = $container->getReflectionClass($definition->getClass(), false)) { + return; + } + + foreach ($reflectionClass->getInterfaces() as $reflectionInterface) { + $this->set($reflectionInterface->name, $id); + } + + do { + $this->set($reflectionClass->name, $id); + } while ($reflectionClass = $reflectionClass->getParentClass()); + } + + /** + * Associates a type and a service id if applicable. + */ + private function set(string $type, string $id) + { + // is this already a type/class that is known to match multiple services? + if (isset($this->ambiguousServiceTypes[$type])) { + $this->ambiguousServiceTypes[$type][] = $id; + + return; + } + + // check to make sure the type doesn't match multiple services + if (!isset($this->types[$type]) || $this->types[$type] === $id) { + $this->types[$type] = $id; + + return; + } + + // keep an array of all services matching this type + if (!isset($this->ambiguousServiceTypes[$type])) { + $this->ambiguousServiceTypes[$type] = [$this->types[$type]]; + unset($this->types[$type]); + } + $this->ambiguousServiceTypes[$type][] = $id; + } + + private function createTypeNotFoundMessageCallback(TypedReference $reference, string $label): callable + { + if (null === $this->typesClone->container) { + $this->typesClone->container = new ContainerBuilder($this->container->getParameterBag()); + $this->typesClone->container->setAliases($this->container->getAliases()); + $this->typesClone->container->setDefinitions($this->container->getDefinitions()); + $this->typesClone->container->setResourceTracking(false); + } + $currentId = $this->currentId; + + return (function () use ($reference, $label, $currentId) { + return $this->createTypeNotFoundMessage($reference, $label, $currentId); + })->bindTo($this->typesClone); + } + + private function createTypeNotFoundMessage(TypedReference $reference, string $label, string $currentId): string + { + if (!$r = $this->container->getReflectionClass($type = $reference->getType(), false)) { + // either $type does not exist or a parent class does not exist + try { + $resource = new ClassExistenceResource($type, false); + // isFresh() will explode ONLY if a parent class/trait does not exist + $resource->isFresh(0); + $parentMsg = false; + } catch (\ReflectionException $e) { + $parentMsg = $e->getMessage(); + } + + $message = sprintf('has type "%s" but this class %s.', $type, $parentMsg ? sprintf('is missing a parent class (%s)', $parentMsg) : 'was not found'); + } else { + $alternatives = $this->createTypeAlternatives($this->container, $reference); + $message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists'; + $message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $alternatives); + + if ($r->isInterface() && !$alternatives) { + $message .= ' Did you create a class that implements this interface?'; + } + } + + $message = sprintf('Cannot autowire service "%s": %s %s', $currentId, $label, $message); + + if (null !== $this->lastFailure) { + $message = $this->lastFailure."\n".$message; + $this->lastFailure = null; + } + + return $message; + } + + private function createTypeAlternatives(ContainerBuilder $container, TypedReference $reference): string + { + // try suggesting available aliases first + if ($message = $this->getAliasesSuggestionForType($container, $type = $reference->getType())) { + return ' '.$message; + } + if (null === $this->ambiguousServiceTypes) { + $this->populateAvailableTypes($container); + } + + $servicesAndAliases = $container->getServiceIds(); + if (!$container->has($type) && false !== $key = array_search(strtolower($type), array_map('strtolower', $servicesAndAliases))) { + return sprintf(' Did you mean "%s"?', $servicesAndAliases[$key]); + } elseif (isset($this->ambiguousServiceTypes[$type])) { + $message = sprintf('one of these existing services: "%s"', implode('", "', $this->ambiguousServiceTypes[$type])); + } elseif (isset($this->types[$type])) { + $message = sprintf('the existing "%s" service', $this->types[$type]); + } else { + return ''; + } + + return sprintf(' You should maybe alias this %s to %s.', class_exists($type, false) ? 'class' : 'interface', $message); + } + + private function getAliasesSuggestionForType(ContainerBuilder $container, string $type): ?string + { + $aliases = []; + foreach (class_parents($type) + class_implements($type) as $parent) { + if ($container->has($parent) && !$container->findDefinition($parent)->isAbstract()) { + $aliases[] = $parent; + } + } + + if (1 < $len = \count($aliases)) { + $message = 'Try changing the type-hint to one of its parents: '; + for ($i = 0, --$len; $i < $len; ++$i) { + $message .= sprintf('%s "%s", ', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]); + } + $message .= sprintf('or %s "%s".', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]); + + return $message; + } + + if ($aliases) { + return sprintf('Try changing the type-hint to "%s" instead.', $aliases[0]); + } + + return null; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php b/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php new file mode 100644 index 0000000..c46d71f --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Definition; + +/** + * Looks for definitions with autowiring enabled and registers their corresponding "@required" methods as setters. + * + * @author Nicolas Grekas + */ +class AutowireRequiredMethodsPass extends AbstractRecursivePass +{ + /** + * {@inheritdoc} + */ + protected function processValue($value, bool $isRoot = false) + { + $value = parent::processValue($value, $isRoot); + + if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) { + return $value; + } + if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) { + return $value; + } + + $alreadyCalledMethods = []; + $withers = []; + + foreach ($value->getMethodCalls() as list($method)) { + $alreadyCalledMethods[strtolower($method)] = true; + } + + foreach ($reflectionClass->getMethods() as $reflectionMethod) { + $r = $reflectionMethod; + + if ($r->isConstructor() || isset($alreadyCalledMethods[strtolower($r->name)])) { + continue; + } + + while (true) { + if (false !== $doc = $r->getDocComment()) { + if (false !== stripos($doc, '@required') && preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) { + if (preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@return\s++static[\s\*]#i', $doc)) { + $withers[] = [$reflectionMethod->name, [], true]; + } else { + $value->addMethodCall($reflectionMethod->name, []); + } + break; + } + if (false === stripos($doc, '@inheritdoc') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+(?:\{@inheritdoc\}|@inheritdoc)(?:\s|\*/$)#i', $doc)) { + break; + } + } + try { + $r = $r->getPrototype(); + } catch (\ReflectionException $e) { + break; // method has no prototype + } + } + } + + if ($withers) { + // Prepend withers to prevent creating circular loops + $setters = $value->getMethodCalls(); + $value->setMethodCalls($withers); + foreach ($setters as $call) { + $value->addMethodCall($call[0], $call[1], $call[2] ?? false); + } + } + + return $value; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php b/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php new file mode 100644 index 0000000..348498d --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + +/** + * Checks if arguments of methods are properly configured. + * + * @author Kévin Dunglas + * @author Nicolas Grekas + */ +class CheckArgumentsValidityPass extends AbstractRecursivePass +{ + private $throwExceptions; + + public function __construct(bool $throwExceptions = true) + { + $this->throwExceptions = $throwExceptions; + } + + /** + * {@inheritdoc} + */ + protected function processValue($value, bool $isRoot = false) + { + if (!$value instanceof Definition) { + return parent::processValue($value, $isRoot); + } + + $i = 0; + foreach ($value->getArguments() as $k => $v) { + if ($k !== $i++) { + if (!\is_int($k)) { + $msg = sprintf('Invalid constructor argument for service "%s": integer expected but found string "%s". Check your service definition.', $this->currentId, $k); + $value->addError($msg); + if ($this->throwExceptions) { + throw new RuntimeException($msg); + } + + break; + } + + $msg = sprintf('Invalid constructor argument %d for service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $this->currentId, $i); + $value->addError($msg); + if ($this->throwExceptions) { + throw new RuntimeException($msg); + } + } + } + + foreach ($value->getMethodCalls() as $methodCall) { + $i = 0; + foreach ($methodCall[1] as $k => $v) { + if ($k !== $i++) { + if (!\is_int($k)) { + $msg = sprintf('Invalid argument for method call "%s" of service "%s": integer expected but found string "%s". Check your service definition.', $methodCall[0], $this->currentId, $k); + $value->addError($msg); + if ($this->throwExceptions) { + throw new RuntimeException($msg); + } + + break; + } + + $msg = sprintf('Invalid argument %d for method call "%s" of service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $methodCall[0], $this->currentId, $i); + $value->addError($msg); + if ($this->throwExceptions) { + throw new RuntimeException($msg); + } + } + } + } + + return null; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php b/vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php new file mode 100644 index 0000000..55d911c --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; + +/** + * Checks your services for circular references. + * + * References from method calls are ignored since we might be able to resolve + * these references depending on the order in which services are called. + * + * Circular reference from method calls will only be detected at run-time. + * + * @author Johannes M. Schmitt + */ +class CheckCircularReferencesPass implements CompilerPassInterface +{ + private $currentPath; + private $checkedNodes; + + /** + * Checks the ContainerBuilder object for circular references. + */ + public function process(ContainerBuilder $container) + { + $graph = $container->getCompiler()->getServiceReferenceGraph(); + + $this->checkedNodes = []; + foreach ($graph->getNodes() as $id => $node) { + $this->currentPath = [$id]; + + $this->checkOutEdges($node->getOutEdges()); + } + } + + /** + * Checks for circular references. + * + * @param ServiceReferenceGraphEdge[] $edges An array of Edges + * + * @throws ServiceCircularReferenceException when a circular reference is found + */ + private function checkOutEdges(array $edges) + { + foreach ($edges as $edge) { + $node = $edge->getDestNode(); + $id = $node->getId(); + + if (empty($this->checkedNodes[$id])) { + // Don't check circular references for lazy edges + if (!$node->getValue() || (!$edge->isLazy() && !$edge->isWeak())) { + $searchKey = array_search($id, $this->currentPath); + $this->currentPath[] = $id; + + if (false !== $searchKey) { + throw new ServiceCircularReferenceException($id, \array_slice($this->currentPath, $searchKey)); + } + + $this->checkOutEdges($node->getOutEdges()); + } + + $this->checkedNodes[$id] = true; + array_pop($this->currentPath); + } + } + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php b/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php new file mode 100644 index 0000000..bb87f47 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\EnvParameterException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Loader\FileLoader; + +/** + * This pass validates each definition individually only taking the information + * into account which is contained in the definition itself. + * + * Later passes can rely on the following, and specifically do not need to + * perform these checks themselves: + * + * - non synthetic, non abstract services always have a class set + * - synthetic services are always public + * + * @author Johannes M. Schmitt + */ +class CheckDefinitionValidityPass implements CompilerPassInterface +{ + /** + * Processes the ContainerBuilder to validate the Definition. + * + * @throws RuntimeException When the Definition is invalid + */ + public function process(ContainerBuilder $container) + { + foreach ($container->getDefinitions() as $id => $definition) { + // synthetic service is public + if ($definition->isSynthetic() && !$definition->isPublic()) { + throw new RuntimeException(sprintf('A synthetic service ("%s") must be public.', $id)); + } + + // non-synthetic, non-abstract service has class + if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass() && (!$definition->getFactory() || !preg_match(FileLoader::ANONYMOUS_ID_REGEXP, $id))) { + if ($definition->getFactory()) { + throw new RuntimeException(sprintf('Please add the class to service "%s" even if it is constructed by a factory since we might need to add method calls based on compile-time checks.', $id)); + } + if (class_exists($id) || interface_exists($id, false)) { + if (0 === strpos($id, '\\') && 1 < substr_count($id, '\\')) { + throw new RuntimeException(sprintf('The definition for "%s" has no class attribute, and appears to reference a class or interface. Please specify the class attribute explicitly or remove the leading backslash by renaming the service to "%s" to get rid of this error.', $id, substr($id, 1))); + } + + throw new RuntimeException(sprintf('The definition for "%s" has no class attribute, and appears to reference a class or interface in the global namespace. Leaving out the "class" attribute is only allowed for namespaced classes. Please specify the class attribute explicitly to get rid of this error.', $id)); + } + + throw new RuntimeException(sprintf('The definition for "%s" has no class. If you intend to inject this service dynamically at runtime, please mark it as synthetic=true. If this is an abstract definition solely used by child definitions, please add abstract=true, otherwise specify a class to get rid of this error.', $id)); + } + + // tag attribute values must be scalars + foreach ($definition->getTags() as $name => $tags) { + foreach ($tags as $attributes) { + foreach ($attributes as $attribute => $value) { + if (!is_scalar($value) && null !== $value) { + throw new RuntimeException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $id, $name, $attribute)); + } + } + } + } + + if ($definition->isPublic() && !$definition->isPrivate()) { + $resolvedId = $container->resolveEnvPlaceholders($id, null, $usedEnvs); + if (null !== $usedEnvs) { + throw new EnvParameterException([$resolvedId], null, 'A service name ("%s") cannot contain dynamic values.'); + } + } + } + + foreach ($container->getAliases() as $id => $alias) { + if ($alias->isPublic() && !$alias->isPrivate()) { + $resolvedId = $container->resolveEnvPlaceholders($id, null, $usedEnvs); + if (null !== $usedEnvs) { + throw new EnvParameterException([$resolvedId], null, 'An alias name ("%s") cannot contain dynamic values.'); + } + } + } + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php b/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php new file mode 100644 index 0000000..4ffe354 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Checks that all references are pointing to a valid service. + * + * @author Johannes M. Schmitt + */ +class CheckExceptionOnInvalidReferenceBehaviorPass extends AbstractRecursivePass +{ + private $serviceLocatorContextIds = []; + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->serviceLocatorContextIds = []; + foreach ($container->findTaggedServiceIds('container.service_locator_context') as $id => $tags) { + $this->serviceLocatorContextIds[$id] = $tags[0]['id']; + $container->getDefinition($id)->clearTag('container.service_locator_context'); + } + + try { + return parent::process($container); + } finally { + $this->serviceLocatorContextIds = []; + } + } + + protected function processValue($value, bool $isRoot = false) + { + if (!$value instanceof Reference) { + return parent::processValue($value, $isRoot); + } + if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $value->getInvalidBehavior() || $this->container->has($id = (string) $value)) { + return $value; + } + + $currentId = $this->currentId; + $graph = $this->container->getCompiler()->getServiceReferenceGraph(); + + if (isset($this->serviceLocatorContextIds[$currentId])) { + $currentId = $this->serviceLocatorContextIds[$currentId]; + $locator = $this->container->getDefinition($this->currentId)->getFactory()[0]; + + foreach ($locator->getArgument(0) as $k => $v) { + if ($v->getValues()[0] === $value) { + if ($k !== $id) { + $currentId = $k.'" in the container provided to "'.$currentId; + } + throw new ServiceNotFoundException($id, $currentId); + } + } + } + + if ('.' === $currentId[0] && $graph->hasNode($currentId)) { + foreach ($graph->getNode($currentId)->getInEdges() as $edge) { + if (!$edge->getValue() instanceof Reference || ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $edge->getValue()->getInvalidBehavior()) { + continue; + } + $sourceId = $edge->getSourceNode()->getId(); + + if ('.' !== $sourceId[0]) { + $currentId = $sourceId; + break; + } + } + } + + throw new ServiceNotFoundException($id, $currentId); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php b/vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php new file mode 100644 index 0000000..0349ef7 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Checks the validity of references. + * + * The following checks are performed by this pass: + * - target definitions are not abstract + * + * @author Johannes M. Schmitt + */ +class CheckReferenceValidityPass extends AbstractRecursivePass +{ + protected function processValue($value, bool $isRoot = false) + { + if ($isRoot && $value instanceof Definition && ($value->isSynthetic() || $value->isAbstract())) { + return $value; + } + if ($value instanceof Reference && $this->container->hasDefinition((string) $value)) { + $targetDefinition = $this->container->getDefinition((string) $value); + + if ($targetDefinition->isAbstract()) { + throw new RuntimeException(sprintf('The definition "%s" has a reference to an abstract definition "%s". Abstract definitions cannot be the target of references.', $this->currentId, $value)); + } + } + + return parent::processValue($value, $isRoot); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php b/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php new file mode 100644 index 0000000..0743cbb --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php @@ -0,0 +1,245 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\InvalidParameterTypeException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\ExpressionLanguage; +use Symfony\Component\DependencyInjection\Parameter; +use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ServiceLocator; +use Symfony\Component\ExpressionLanguage\Expression; + +/** + * Checks whether injected parameters are compatible with type declarations. + * + * This pass should be run after all optimization passes. + * + * It can be added either: + * * before removing passes to check all services even if they are not currently used, + * * after removing passes to check only services are used in the app. + * + * @author Nicolas Grekas + * @author Julien Maulny + */ +final class CheckTypeDeclarationsPass extends AbstractRecursivePass +{ + private const SCALAR_TYPES = ['int', 'float', 'bool', 'string']; + + private $autoload; + private $skippedIds; + + private $expressionLanguage; + + /** + * @param bool $autoload Whether services who's class in not loaded should be checked or not. + * Defaults to false to save loading code during compilation. + * @param array $skippedIds An array indexed by the service ids to skip + */ + public function __construct(bool $autoload = false, array $skippedIds = []) + { + $this->autoload = $autoload; + $this->skippedIds = $skippedIds; + } + + /** + * {@inheritdoc} + */ + protected function processValue($value, $isRoot = false) + { + if (isset($this->skippedIds[$this->currentId])) { + return $value; + } + + if (!$value instanceof Definition || $value->hasErrors()) { + return parent::processValue($value, $isRoot); + } + + if (!$this->autoload && !class_exists($class = $value->getClass(), false) && !interface_exists($class, false)) { + return parent::processValue($value, $isRoot); + } + + if (ServiceLocator::class === $value->getClass()) { + return parent::processValue($value, $isRoot); + } + + if ($constructor = $this->getConstructor($value, false)) { + $this->checkTypeDeclarations($value, $constructor, $value->getArguments()); + } + + foreach ($value->getMethodCalls() as $methodCall) { + try { + $reflectionMethod = $this->getReflectionMethod($value, $methodCall[0]); + } catch (RuntimeException $e) { + if ($value->getFactory()) { + continue; + } + + throw $e; + } + + $this->checkTypeDeclarations($value, $reflectionMethod, $methodCall[1]); + } + + return parent::processValue($value, $isRoot); + } + + /** + * @throws InvalidArgumentException When not enough parameters are defined for the method + */ + private function checkTypeDeclarations(Definition $checkedDefinition, \ReflectionFunctionAbstract $reflectionFunction, array $values): void + { + $numberOfRequiredParameters = $reflectionFunction->getNumberOfRequiredParameters(); + + if (\count($values) < $numberOfRequiredParameters) { + throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": "%s::%s()" requires %d arguments, %d passed.', $this->currentId, $reflectionFunction->class, $reflectionFunction->name, $numberOfRequiredParameters, \count($values))); + } + + $reflectionParameters = $reflectionFunction->getParameters(); + $checksCount = min($reflectionFunction->getNumberOfParameters(), \count($values)); + + $envPlaceholderUniquePrefix = $this->container->getParameterBag() instanceof EnvPlaceholderParameterBag ? $this->container->getParameterBag()->getEnvPlaceholderUniquePrefix() : null; + + for ($i = 0; $i < $checksCount; ++$i) { + if (!$reflectionParameters[$i]->hasType() || $reflectionParameters[$i]->isVariadic()) { + continue; + } + + $this->checkType($checkedDefinition, $values[$i], $reflectionParameters[$i], $envPlaceholderUniquePrefix); + } + + if ($reflectionFunction->isVariadic() && ($lastParameter = end($reflectionParameters))->hasType()) { + $variadicParameters = \array_slice($values, $lastParameter->getPosition()); + + foreach ($variadicParameters as $variadicParameter) { + $this->checkType($checkedDefinition, $variadicParameter, $lastParameter, $envPlaceholderUniquePrefix); + } + } + } + + /** + * @throws InvalidParameterTypeException When a parameter is not compatible with the declared type + */ + private function checkType(Definition $checkedDefinition, $value, \ReflectionParameter $parameter, ?string $envPlaceholderUniquePrefix): void + { + $type = $parameter->getType()->getName(); + + if ($value instanceof Reference) { + if (!$this->container->has($value = (string) $value)) { + return; + } + + if ('service_container' === $value && is_a($type, Container::class, true)) { + return; + } + + $value = $this->container->findDefinition($value); + } + + if ('self' === $type) { + $type = $parameter->getDeclaringClass()->getName(); + } + + if ('static' === $type) { + $type = $checkedDefinition->getClass(); + } + + if ($value instanceof Definition) { + $class = $value->getClass(); + + if (!$class || (!$this->autoload && !class_exists($class, false) && !interface_exists($class, false))) { + return; + } + + if ('callable' === $type && method_exists($class, '__invoke')) { + return; + } + + if ('iterable' === $type && is_subclass_of($class, 'Traversable')) { + return; + } + + if ('object' === $type) { + return; + } + + if (is_a($class, $type, true)) { + return; + } + + throw new InvalidParameterTypeException($this->currentId, $class, $parameter); + } + + if ($value instanceof Parameter) { + $value = $this->container->getParameter($value); + } elseif ($value instanceof Expression) { + $value = $this->getExpressionLanguage()->evaluate($value, ['container' => $this->container]); + } elseif (\is_string($value)) { + if ('%' === ($value[0] ?? '') && preg_match('/^%([^%]+)%$/', $value, $match)) { + // Only array parameters are not inlined when dumped. + $value = []; + } elseif ($envPlaceholderUniquePrefix && false !== strpos($value, 'env_')) { + // If the value is an env placeholder that is either mixed with a string or with another env placeholder, then its resolved value will always be a string, so we don't need to resolve it. + // We don't need to change the value because it is already a string. + if ('' === preg_replace('/'.$envPlaceholderUniquePrefix.'_\w+_[a-f0-9]{32}/U', '', $value, -1, $c) && 1 === $c) { + try { + $value = $this->container->resolveEnvPlaceholders($value, true); + } catch (EnvNotFoundException | RuntimeException $e) { + // If an env placeholder cannot be resolved, we skip the validation. + return; + } + } + } + } + + if (null === $value && $parameter->allowsNull()) { + return; + } + + if (\in_array($type, self::SCALAR_TYPES, true) && is_scalar($value)) { + return; + } + + if ('callable' === $type && \is_array($value) && isset($value[0]) && ($value[0] instanceof Reference || $value[0] instanceof Definition)) { + return; + } + + if ('iterable' === $type && (\is_array($value) || $value instanceof \Traversable || $value instanceof IteratorArgument)) { + return; + } + + if ('Traversable' === $type && ($value instanceof \Traversable || $value instanceof IteratorArgument)) { + return; + } + + $checkFunction = sprintf('is_%s', $parameter->getType()->getName()); + + if (!$parameter->getType()->isBuiltin() || !$checkFunction($value)) { + throw new InvalidParameterTypeException($this->currentId, \is_object($value) ? \get_class($value) : \gettype($value), $parameter); + } + } + + private function getExpressionLanguage(): ExpressionLanguage + { + if (null === $this->expressionLanguage) { + $this->expressionLanguage = new ExpressionLanguage(null, $this->container->getExpressionLanguageProviders()); + } + + return $this->expressionLanguage; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/Compiler.php b/vendor/symfony/dependency-injection/Compiler/Compiler.php new file mode 100644 index 0000000..04ae8d5 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/Compiler.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\EnvParameterException; + +/** + * This class is used to remove circular dependencies between individual passes. + * + * @author Johannes M. Schmitt + */ +class Compiler +{ + private $passConfig; + private $log = []; + private $serviceReferenceGraph; + + public function __construct() + { + $this->passConfig = new PassConfig(); + $this->serviceReferenceGraph = new ServiceReferenceGraph(); + } + + /** + * Returns the PassConfig. + * + * @return PassConfig The PassConfig instance + */ + public function getPassConfig() + { + return $this->passConfig; + } + + /** + * Returns the ServiceReferenceGraph. + * + * @return ServiceReferenceGraph The ServiceReferenceGraph instance + */ + public function getServiceReferenceGraph() + { + return $this->serviceReferenceGraph; + } + + /** + * Adds a pass to the PassConfig. + */ + public function addPass(CompilerPassInterface $pass, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) + { + $this->passConfig->addPass($pass, $type, $priority); + } + + /** + * @final + */ + public function log(CompilerPassInterface $pass, string $message) + { + if (false !== strpos($message, "\n")) { + $message = str_replace("\n", "\n".\get_class($pass).': ', trim($message)); + } + + $this->log[] = \get_class($pass).': '.$message; + } + + /** + * Returns the log. + * + * @return array Log array + */ + public function getLog() + { + return $this->log; + } + + /** + * Run the Compiler and process all Passes. + */ + public function compile(ContainerBuilder $container) + { + try { + foreach ($this->passConfig->getPasses() as $pass) { + $pass->process($container); + } + } catch (\Exception $e) { + $usedEnvs = []; + $prev = $e; + + do { + $msg = $prev->getMessage(); + + if ($msg !== $resolvedMsg = $container->resolveEnvPlaceholders($msg, null, $usedEnvs)) { + $r = new \ReflectionProperty($prev, 'message'); + $r->setAccessible(true); + $r->setValue($prev, $resolvedMsg); + } + } while ($prev = $prev->getPrevious()); + + if ($usedEnvs) { + $e = new EnvParameterException($usedEnvs, $e); + } + + throw $e; + } finally { + $this->getServiceReferenceGraph()->clear(); + } + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/CompilerPassInterface.php b/vendor/symfony/dependency-injection/Compiler/CompilerPassInterface.php new file mode 100644 index 0000000..3085006 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/CompilerPassInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Interface that must be implemented by compilation passes. + * + * @author Johannes M. Schmitt + */ +interface CompilerPassInterface +{ + /** + * You can modify the container here before it is dumped to PHP code. + */ + public function process(ContainerBuilder $container); +} diff --git a/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php b/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php new file mode 100644 index 0000000..da909ae --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Overwrites a service but keeps the overridden one. + * + * @author Christophe Coevoet + * @author Fabien Potencier + * @author Diego Saint Esteben + */ +class DecoratorServicePass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + $definitions = new \SplPriorityQueue(); + $order = PHP_INT_MAX; + + foreach ($container->getDefinitions() as $id => $definition) { + if (!$decorated = $definition->getDecoratedService()) { + continue; + } + $definitions->insert([$id, $definition], [$decorated[2], --$order]); + } + $decoratingDefinitions = []; + + foreach ($definitions as list($id, $definition)) { + $decoratedService = $definition->getDecoratedService(); + list($inner, $renamedId) = $decoratedService; + $invalidBehavior = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + + $definition->setDecoratedService(null); + + if (!$renamedId) { + $renamedId = $id.'.inner'; + } + $definition->innerServiceId = $renamedId; + $definition->decorationOnInvalid = $invalidBehavior; + + // we create a new alias/service for the service we are replacing + // to be able to reference it in the new one + if ($container->hasAlias($inner)) { + $alias = $container->getAlias($inner); + $public = $alias->isPublic(); + $private = $alias->isPrivate(); + $container->setAlias($renamedId, new Alias((string) $alias, false)); + } elseif ($container->hasDefinition($inner)) { + $decoratedDefinition = $container->getDefinition($inner); + $public = $decoratedDefinition->isPublic(); + $private = $decoratedDefinition->isPrivate(); + $decoratedDefinition->setPublic(false); + $container->setDefinition($renamedId, $decoratedDefinition); + $decoratingDefinitions[$inner] = $decoratedDefinition; + } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) { + $container->removeDefinition($id); + continue; + } elseif (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) { + $public = $definition->isPublic(); + $private = $definition->isPrivate(); + } else { + throw new ServiceNotFoundException($inner, $id); + } + + if (isset($decoratingDefinitions[$inner])) { + $decoratingDefinition = $decoratingDefinitions[$inner]; + $definition->setTags(array_merge($decoratingDefinition->getTags(), $definition->getTags())); + $decoratingDefinition->setTags([]); + $decoratingDefinitions[$inner] = $definition; + } + + $container->setAlias($inner, $id)->setPublic($public)->setPrivate($private); + } + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php b/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php new file mode 100644 index 0000000..5e7ba31 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Throws an exception for any Definitions that have errors and still exist. + * + * @author Ryan Weaver + */ +class DefinitionErrorExceptionPass extends AbstractRecursivePass +{ + /** + * {@inheritdoc} + */ + protected function processValue($value, bool $isRoot = false) + { + if (!$value instanceof Definition || !$value->hasErrors()) { + return parent::processValue($value, $isRoot); + } + + if ($isRoot && !$value->isPublic()) { + $graph = $this->container->getCompiler()->getServiceReferenceGraph(); + $runtimeException = false; + foreach ($graph->getNode($this->currentId)->getInEdges() as $edge) { + if (!$edge->getValue() instanceof Reference || ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE !== $edge->getValue()->getInvalidBehavior()) { + $runtimeException = false; + break; + } + $runtimeException = true; + } + if ($runtimeException) { + return parent::processValue($value, $isRoot); + } + } + + // only show the first error so the user can focus on it + $errors = $value->getErrors(); + $message = reset($errors); + + throw new RuntimeException($message); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php b/vendor/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php new file mode 100644 index 0000000..27e5048 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * A pass to automatically process extensions if they implement + * CompilerPassInterface. + * + * @author Wouter J + */ +class ExtensionCompilerPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + foreach ($container->getExtensions() as $extension) { + if (!$extension instanceof CompilerPassInterface) { + continue; + } + + $extension->process($container); + } + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php b/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php new file mode 100644 index 0000000..41af126 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php @@ -0,0 +1,217 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Inline service definitions where this is possible. + * + * @author Johannes M. Schmitt + */ +class InlineServiceDefinitionsPass extends AbstractRecursivePass +{ + private $analyzingPass; + private $cloningIds = []; + private $connectedIds = []; + private $notInlinedIds = []; + private $inlinedIds = []; + private $graph; + + public function __construct(AnalyzeServiceReferencesPass $analyzingPass = null) + { + $this->analyzingPass = $analyzingPass; + } + + public function process(ContainerBuilder $container) + { + $this->container = $container; + if ($this->analyzingPass) { + $analyzedContainer = new ContainerBuilder(); + $analyzedContainer->setAliases($container->getAliases()); + $analyzedContainer->setDefinitions($container->getDefinitions()); + foreach ($container->getExpressionLanguageProviders() as $provider) { + $analyzedContainer->addExpressionLanguageProvider($provider); + } + } else { + $analyzedContainer = $container; + } + try { + $remainingInlinedIds = []; + $this->connectedIds = $this->notInlinedIds = $container->getDefinitions(); + do { + if ($this->analyzingPass) { + $analyzedContainer->setDefinitions(array_intersect_key($analyzedContainer->getDefinitions(), $this->connectedIds)); + $this->analyzingPass->process($analyzedContainer); + } + $this->graph = $analyzedContainer->getCompiler()->getServiceReferenceGraph(); + $notInlinedIds = $this->notInlinedIds; + $this->connectedIds = $this->notInlinedIds = $this->inlinedIds = []; + + foreach ($analyzedContainer->getDefinitions() as $id => $definition) { + if (!$this->graph->hasNode($id)) { + continue; + } + foreach ($this->graph->getNode($id)->getOutEdges() as $edge) { + if (isset($notInlinedIds[$edge->getSourceNode()->getId()])) { + $this->currentId = $id; + $this->processValue($definition, true); + break; + } + } + } + + foreach ($this->inlinedIds as $id => $isPublicOrNotShared) { + if ($isPublicOrNotShared) { + $remainingInlinedIds[$id] = $id; + } else { + $container->removeDefinition($id); + $analyzedContainer->removeDefinition($id); + } + } + } while ($this->inlinedIds && $this->analyzingPass); + + foreach ($remainingInlinedIds as $id) { + $definition = $container->getDefinition($id); + + if (!$definition->isShared() && !$definition->isPublic()) { + $container->removeDefinition($id); + } + } + } finally { + $this->container = null; + $this->connectedIds = $this->notInlinedIds = $this->inlinedIds = []; + $this->graph = null; + } + } + + /** + * {@inheritdoc} + */ + protected function processValue($value, bool $isRoot = false) + { + if ($value instanceof ArgumentInterface) { + // Reference found in ArgumentInterface::getValues() are not inlineable + return $value; + } + + if ($value instanceof Definition && $this->cloningIds) { + if ($value->isShared()) { + return $value; + } + $value = clone $value; + } + + if (!$value instanceof Reference) { + return parent::processValue($value, $isRoot); + } elseif (!$this->container->hasDefinition($id = (string) $value)) { + return $value; + } + + $definition = $this->container->getDefinition($id); + + if (!$this->isInlineableDefinition($id, $definition)) { + return $value; + } + + $this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId)); + $this->inlinedIds[$id] = $definition->isPublic() || !$definition->isShared(); + $this->notInlinedIds[$this->currentId] = true; + + if ($definition->isShared()) { + return $definition; + } + + if (isset($this->cloningIds[$id])) { + $ids = array_keys($this->cloningIds); + $ids[] = $id; + + throw new ServiceCircularReferenceException($id, \array_slice($ids, array_search($id, $ids))); + } + + $this->cloningIds[$id] = true; + try { + return $this->processValue($definition); + } finally { + unset($this->cloningIds[$id]); + } + } + + /** + * Checks if the definition is inlineable. + */ + private function isInlineableDefinition(string $id, Definition $definition): bool + { + if ($definition->hasErrors() || $definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic()) { + return false; + } + + if (!$definition->isShared()) { + if (!$this->graph->hasNode($id)) { + return true; + } + + foreach ($this->graph->getNode($id)->getInEdges() as $edge) { + $srcId = $edge->getSourceNode()->getId(); + $this->connectedIds[$srcId] = true; + if ($edge->isWeak() || $edge->isLazy()) { + return false; + } + } + + return true; + } + + if ($definition->isPublic()) { + return false; + } + + if (!$this->graph->hasNode($id)) { + return true; + } + + if ($this->currentId == $id) { + return false; + } + $this->connectedIds[$id] = true; + + $srcIds = []; + $srcCount = 0; + $isReferencedByConstructor = false; + foreach ($this->graph->getNode($id)->getInEdges() as $edge) { + $isReferencedByConstructor = $isReferencedByConstructor || $edge->isReferencedByConstructor(); + $srcId = $edge->getSourceNode()->getId(); + $this->connectedIds[$srcId] = true; + if ($edge->isWeak() || $edge->isLazy()) { + return false; + } + $srcIds[$srcId] = true; + ++$srcCount; + } + + if (1 !== \count($srcIds)) { + $this->notInlinedIds[$id] = true; + + return false; + } + + if ($srcCount > 1 && \is_array($factory = $definition->getFactory()) && ($factory[0] instanceof Reference || $factory[0] instanceof Definition)) { + return false; + } + + return $this->container->getDefinition($srcId)->isShared(); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php b/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php new file mode 100644 index 0000000..bfeb7b8 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php @@ -0,0 +1,220 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\Config\Definition\BaseNode; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\LogicException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; +use Symfony\Component\DependencyInjection\Extension\Extension; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; +use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; +use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; + +/** + * Merges extension configs into the container builder. + * + * @author Fabien Potencier + */ +class MergeExtensionConfigurationPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $parameters = $container->getParameterBag()->all(); + $definitions = $container->getDefinitions(); + $aliases = $container->getAliases(); + $exprLangProviders = $container->getExpressionLanguageProviders(); + $configAvailable = class_exists(BaseNode::class); + + foreach ($container->getExtensions() as $extension) { + if ($extension instanceof PrependExtensionInterface) { + $extension->prepend($container); + } + } + + foreach ($container->getExtensions() as $name => $extension) { + if (!$config = $container->getExtensionConfig($name)) { + // this extension was not called + continue; + } + $resolvingBag = $container->getParameterBag(); + if ($resolvingBag instanceof EnvPlaceholderParameterBag && $extension instanceof Extension) { + // create a dedicated bag so that we can track env vars per-extension + $resolvingBag = new MergeExtensionConfigurationParameterBag($resolvingBag); + if ($configAvailable) { + BaseNode::setPlaceholderUniquePrefix($resolvingBag->getEnvPlaceholderUniquePrefix()); + } + } + $config = $resolvingBag->resolveValue($config); + + try { + $tmpContainer = new MergeExtensionConfigurationContainerBuilder($extension, $resolvingBag); + $tmpContainer->setResourceTracking($container->isTrackingResources()); + $tmpContainer->addObjectResource($extension); + if ($extension instanceof ConfigurationExtensionInterface && null !== $configuration = $extension->getConfiguration($config, $tmpContainer)) { + $tmpContainer->addObjectResource($configuration); + } + + foreach ($exprLangProviders as $provider) { + $tmpContainer->addExpressionLanguageProvider($provider); + } + + $extension->load($config, $tmpContainer); + } catch (\Exception $e) { + if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) { + $container->getParameterBag()->mergeEnvPlaceholders($resolvingBag); + } + + throw $e; + } finally { + if ($configAvailable) { + BaseNode::resetPlaceholders(); + } + } + + if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) { + // don't keep track of env vars that are *overridden* when configs are merged + $resolvingBag->freezeAfterProcessing($extension, $tmpContainer); + } + + $container->merge($tmpContainer); + $container->getParameterBag()->add($parameters); + } + + $container->addDefinitions($definitions); + $container->addAliases($aliases); + } +} + +/** + * @internal + */ +class MergeExtensionConfigurationParameterBag extends EnvPlaceholderParameterBag +{ + private $processedEnvPlaceholders; + + public function __construct(parent $parameterBag) + { + parent::__construct($parameterBag->all()); + $this->mergeEnvPlaceholders($parameterBag); + } + + public function freezeAfterProcessing(Extension $extension, ContainerBuilder $container) + { + if (!$config = $extension->getProcessedConfigs()) { + // Extension::processConfiguration() wasn't called, we cannot know how configs were merged + return; + } + $this->processedEnvPlaceholders = []; + + // serialize config and container to catch env vars nested in object graphs + $config = serialize($config).serialize($container->getDefinitions()).serialize($container->getAliases()).serialize($container->getParameterBag()->all()); + + foreach (parent::getEnvPlaceholders() as $env => $placeholders) { + foreach ($placeholders as $placeholder) { + if (false !== stripos($config, $placeholder)) { + $this->processedEnvPlaceholders[$env] = $placeholders; + break; + } + } + } + } + + /** + * {@inheritdoc} + */ + public function getEnvPlaceholders(): array + { + return null !== $this->processedEnvPlaceholders ? $this->processedEnvPlaceholders : parent::getEnvPlaceholders(); + } + + public function getUnusedEnvPlaceholders(): array + { + return null === $this->processedEnvPlaceholders ? [] : array_diff_key(parent::getEnvPlaceholders(), $this->processedEnvPlaceholders); + } +} + +/** + * A container builder preventing using methods that wouldn't have any effect from extensions. + * + * @internal + */ +class MergeExtensionConfigurationContainerBuilder extends ContainerBuilder +{ + private $extensionClass; + + public function __construct(ExtensionInterface $extension, ParameterBagInterface $parameterBag = null) + { + parent::__construct($parameterBag); + + $this->extensionClass = \get_class($extension); + } + + /** + * {@inheritdoc} + */ + public function addCompilerPass(CompilerPassInterface $pass, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0): self + { + throw new LogicException(sprintf('You cannot add compiler pass "%s" from extension "%s". Compiler passes must be registered before the container is compiled.', \get_class($pass), $this->extensionClass)); + } + + /** + * {@inheritdoc} + */ + public function registerExtension(ExtensionInterface $extension) + { + throw new LogicException(sprintf('You cannot register extension "%s" from "%s". Extensions must be registered before the container is compiled.', \get_class($extension), $this->extensionClass)); + } + + /** + * {@inheritdoc} + */ + public function compile(bool $resolveEnvPlaceholders = false) + { + throw new LogicException(sprintf('Cannot compile the container in extension "%s".', $this->extensionClass)); + } + + /** + * {@inheritdoc} + */ + public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs = null) + { + if (true !== $format || !\is_string($value)) { + return parent::resolveEnvPlaceholders($value, $format, $usedEnvs); + } + + $bag = $this->getParameterBag(); + $value = $bag->resolveValue($value); + + if (!$bag instanceof EnvPlaceholderParameterBag) { + return parent::resolveEnvPlaceholders($value, $format, $usedEnvs); + } + + foreach ($bag->getEnvPlaceholders() as $env => $placeholders) { + if (false === strpos($env, ':')) { + continue; + } + foreach ($placeholders as $placeholder) { + if (false !== stripos($value, $placeholder)) { + throw new RuntimeException(sprintf('Using a cast in "env(%s)" is incompatible with resolution at compile time in "%s". The logic in the extension should be moved to a compiler pass, or an env parameter with no cast should be used instead.', $env, $this->extensionClass)); + } + } + } + + return parent::resolveEnvPlaceholders($value, $format, $usedEnvs); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/PassConfig.php b/vendor/symfony/dependency-injection/Compiler/PassConfig.php new file mode 100644 index 0000000..8df9f0e --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/PassConfig.php @@ -0,0 +1,266 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +/** + * Compiler Pass Configuration. + * + * This class has a default configuration embedded. + * + * @author Johannes M. Schmitt + */ +class PassConfig +{ + const TYPE_AFTER_REMOVING = 'afterRemoving'; + const TYPE_BEFORE_OPTIMIZATION = 'beforeOptimization'; + const TYPE_BEFORE_REMOVING = 'beforeRemoving'; + const TYPE_OPTIMIZE = 'optimization'; + const TYPE_REMOVE = 'removing'; + + private $mergePass; + private $afterRemovingPasses = []; + private $beforeOptimizationPasses = []; + private $beforeRemovingPasses = []; + private $optimizationPasses; + private $removingPasses; + + public function __construct() + { + $this->mergePass = new MergeExtensionConfigurationPass(); + + $this->beforeOptimizationPasses = [ + 100 => [ + new ResolveClassPass(), + new ResolveInstanceofConditionalsPass(), + new RegisterEnvVarProcessorsPass(), + ], + -1000 => [new ExtensionCompilerPass()], + ]; + + $this->optimizationPasses = [[ + new ValidateEnvPlaceholdersPass(), + new ResolveChildDefinitionsPass(), + new RegisterServiceSubscribersPass(), + new ResolveParameterPlaceHoldersPass(false), + new ResolveFactoryClassPass(), + new ResolveNamedArgumentsPass(), + new AutowireRequiredMethodsPass(), + new ResolveBindingsPass(), + new ServiceLocatorTagPass(), + new DecoratorServicePass(), + new CheckDefinitionValidityPass(), + new AutowirePass(false), + new ResolveTaggedIteratorArgumentPass(), + new ResolveServiceSubscribersPass(), + new ResolveReferencesToAliasesPass(), + new ResolveInvalidReferencesPass(), + new AnalyzeServiceReferencesPass(true), + new CheckCircularReferencesPass(), + new CheckReferenceValidityPass(), + new CheckArgumentsValidityPass(false), + ]]; + + $this->beforeRemovingPasses = [ + -100 => [ + new ResolvePrivatesPass(), + ], + ]; + + $this->removingPasses = [[ + new RemovePrivateAliasesPass(), + new ReplaceAliasByActualDefinitionPass(), + new RemoveAbstractDefinitionsPass(), + new RemoveUnusedDefinitionsPass(), + new InlineServiceDefinitionsPass(new AnalyzeServiceReferencesPass()), + new AnalyzeServiceReferencesPass(), + new DefinitionErrorExceptionPass(), + ]]; + + $this->afterRemovingPasses = [[ + new CheckExceptionOnInvalidReferenceBehaviorPass(), + new ResolveHotPathPass(), + ]]; + } + + /** + * Returns all passes in order to be processed. + * + * @return CompilerPassInterface[] + */ + public function getPasses() + { + return array_merge( + [$this->mergePass], + $this->getBeforeOptimizationPasses(), + $this->getOptimizationPasses(), + $this->getBeforeRemovingPasses(), + $this->getRemovingPasses(), + $this->getAfterRemovingPasses() + ); + } + + /** + * Adds a pass. + * + * @throws InvalidArgumentException when a pass type doesn't exist + */ + public function addPass(CompilerPassInterface $pass, string $type = self::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) + { + $property = $type.'Passes'; + if (!isset($this->$property)) { + throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type)); + } + + $passes = &$this->$property; + + if (!isset($passes[$priority])) { + $passes[$priority] = []; + } + $passes[$priority][] = $pass; + } + + /** + * Gets all passes for the AfterRemoving pass. + * + * @return CompilerPassInterface[] + */ + public function getAfterRemovingPasses() + { + return $this->sortPasses($this->afterRemovingPasses); + } + + /** + * Gets all passes for the BeforeOptimization pass. + * + * @return CompilerPassInterface[] + */ + public function getBeforeOptimizationPasses() + { + return $this->sortPasses($this->beforeOptimizationPasses); + } + + /** + * Gets all passes for the BeforeRemoving pass. + * + * @return CompilerPassInterface[] + */ + public function getBeforeRemovingPasses() + { + return $this->sortPasses($this->beforeRemovingPasses); + } + + /** + * Gets all passes for the Optimization pass. + * + * @return CompilerPassInterface[] + */ + public function getOptimizationPasses() + { + return $this->sortPasses($this->optimizationPasses); + } + + /** + * Gets all passes for the Removing pass. + * + * @return CompilerPassInterface[] + */ + public function getRemovingPasses() + { + return $this->sortPasses($this->removingPasses); + } + + /** + * Gets the Merge pass. + * + * @return CompilerPassInterface + */ + public function getMergePass() + { + return $this->mergePass; + } + + public function setMergePass(CompilerPassInterface $pass) + { + $this->mergePass = $pass; + } + + /** + * Sets the AfterRemoving passes. + * + * @param CompilerPassInterface[] $passes + */ + public function setAfterRemovingPasses(array $passes) + { + $this->afterRemovingPasses = [$passes]; + } + + /** + * Sets the BeforeOptimization passes. + * + * @param CompilerPassInterface[] $passes + */ + public function setBeforeOptimizationPasses(array $passes) + { + $this->beforeOptimizationPasses = [$passes]; + } + + /** + * Sets the BeforeRemoving passes. + * + * @param CompilerPassInterface[] $passes + */ + public function setBeforeRemovingPasses(array $passes) + { + $this->beforeRemovingPasses = [$passes]; + } + + /** + * Sets the Optimization passes. + * + * @param CompilerPassInterface[] $passes + */ + public function setOptimizationPasses(array $passes) + { + $this->optimizationPasses = [$passes]; + } + + /** + * Sets the Removing passes. + * + * @param CompilerPassInterface[] $passes + */ + public function setRemovingPasses(array $passes) + { + $this->removingPasses = [$passes]; + } + + /** + * Sort passes by priority. + * + * @param array $passes CompilerPassInterface instances with their priority as key + * + * @return CompilerPassInterface[] + */ + private function sortPasses(array $passes): array + { + if (0 === \count($passes)) { + return []; + } + + krsort($passes); + + // Flatten the array + return array_merge(...$passes); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php b/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php new file mode 100644 index 0000000..9b3760b --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\TypedReference; + +/** + * Trait that allows a generic method to find and sort service by priority option in the tag. + * + * @author Iltar van der Berg + */ +trait PriorityTaggedServiceTrait +{ + /** + * Finds all services with the given tag name and order them by their priority. + * + * The order of additions must be respected for services having the same priority, + * and knowing that the \SplPriorityQueue class does not respect the FIFO method, + * we should not use that class. + * + * @see https://bugs.php.net/53710 + * @see https://bugs.php.net/60926 + * + * @param string|TaggedIteratorArgument $tagName + * + * @return Reference[] + */ + private function findAndSortTaggedServices($tagName, ContainerBuilder $container): array + { + $indexAttribute = $defaultIndexMethod = $needsIndexes = $defaultPriorityMethod = null; + + if ($tagName instanceof TaggedIteratorArgument) { + $indexAttribute = $tagName->getIndexAttribute(); + $defaultIndexMethod = $tagName->getDefaultIndexMethod(); + $needsIndexes = $tagName->needsIndexes(); + $defaultPriorityMethod = $tagName->getDefaultPriorityMethod(); + $tagName = $tagName->getTag(); + } + + $services = []; + + foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) { + $class = $r = null; + $priority = 0; + if (isset($attributes[0]['priority'])) { + $priority = $attributes[0]['priority']; + } elseif ($defaultPriorityMethod) { + $class = $container->getDefinition($serviceId)->getClass(); + $class = $container->getParameterBag()->resolveValue($class) ?: null; + + if (($r = $container->getReflectionClass($class)) && $r->hasMethod($defaultPriorityMethod)) { + if (!($rm = $r->getMethod($defaultPriorityMethod))->isStatic()) { + throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId)); + } + + if (!$rm->isPublic()) { + throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId)); + } + + $priority = $rm->invoke(null); + + if (!\is_int($priority)) { + throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return an integer, got %s: tag "%s" on service "%s".', $class, $defaultPriorityMethod, \gettype($priority), $tagName, $serviceId)); + } + } + } + + if (null === $indexAttribute && !$needsIndexes) { + $services[$priority][] = new Reference($serviceId); + + continue; + } + + if (!$class) { + $class = $container->getDefinition($serviceId)->getClass(); + $class = $container->getParameterBag()->resolveValue($class) ?: null; + } + + if (null !== $indexAttribute && isset($attributes[0][$indexAttribute])) { + $services[$priority][$attributes[0][$indexAttribute]] = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $attributes[0][$indexAttribute]); + + continue; + } + + if (!$r && !$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $serviceId)); + } + + $class = $r->name; + + if (!$r->hasMethod($defaultIndexMethod)) { + if ($needsIndexes) { + $services[$priority][$serviceId] = new TypedReference($serviceId, $class); + + continue; + } + + throw new InvalidArgumentException(sprintf('Method "%s::%s()" not found: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute)); + } + + if (!($rm = $r->getMethod($defaultIndexMethod))->isStatic()) { + throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute)); + } + + if (!$rm->isPublic()) { + throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute)); + } + + $key = $rm->invoke(null); + + if (!\is_string($key)) { + throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return a string, got %s: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, \gettype($key), $tagName, $serviceId, $indexAttribute)); + } + + $services[$priority][$key] = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $key); + } + + if ($services) { + krsort($services); + $services = array_merge(...$services); + } + + return $services; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php b/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php new file mode 100644 index 0000000..a9a133b --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\EnvVarProcessor; +use Symfony\Component\DependencyInjection\EnvVarProcessorInterface; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Creates the container.env_var_processors_locator service. + * + * @author Nicolas Grekas + */ +class RegisterEnvVarProcessorsPass implements CompilerPassInterface +{ + private static $allowedTypes = ['array', 'bool', 'float', 'int', 'string']; + + public function process(ContainerBuilder $container) + { + $bag = $container->getParameterBag(); + $types = []; + $processors = []; + foreach ($container->findTaggedServiceIds('container.env_var_processor') as $id => $tags) { + if (!$r = $container->getReflectionClass($class = $container->getDefinition($id)->getClass())) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } elseif (!$r->isSubclassOf(EnvVarProcessorInterface::class)) { + throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EnvVarProcessorInterface::class)); + } + foreach ($class::getProvidedTypes() as $prefix => $type) { + $processors[$prefix] = new Reference($id); + $types[$prefix] = self::validateProvidedTypes($type, $class); + } + } + + if ($bag instanceof EnvPlaceholderParameterBag) { + foreach (EnvVarProcessor::getProvidedTypes() as $prefix => $type) { + if (!isset($types[$prefix])) { + $types[$prefix] = self::validateProvidedTypes($type, EnvVarProcessor::class); + } + } + $bag->setProvidedTypes($types); + } + + if ($processors) { + $container->setAlias('container.env_var_processors_locator', (string) ServiceLocatorTagPass::register($container, $processors)) + ->setPublic(true) + ; + } + } + + private static function validateProvidedTypes(string $types, string $class): array + { + $types = explode('|', $types); + + foreach ($types as $type) { + if (!\in_array($type, self::$allowedTypes)) { + throw new InvalidArgumentException(sprintf('Invalid type "%s" returned by "%s::getProvidedTypes()", expected one of "%s".', $type, $class, implode('", "', self::$allowedTypes))); + } + } + + return $types; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php b/vendor/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php new file mode 100644 index 0000000..571eab3 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Nicolas Grekas + */ +class RegisterReverseContainerPass implements CompilerPassInterface +{ + private $beforeRemoving; + private $serviceId; + private $tagName; + + public function __construct(bool $beforeRemoving, string $serviceId = 'reverse_container', string $tagName = 'container.reversible') + { + $this->beforeRemoving = $beforeRemoving; + $this->serviceId = $serviceId; + $this->tagName = $tagName; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->serviceId)) { + return; + } + + $refType = $this->beforeRemoving ? ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE : ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + $services = []; + foreach ($container->findTaggedServiceIds($this->tagName) as $id => $tags) { + $services[$id] = new Reference($id, $refType); + } + + if ($this->beforeRemoving) { + // prevent inlining of the reverse container + $services[$this->serviceId] = new Reference($this->serviceId, $refType); + } + $locator = $container->getDefinition($this->serviceId)->getArgument(1); + + if ($locator instanceof Reference) { + $locator = $container->getDefinition((string) $locator); + } + if ($locator instanceof Definition) { + foreach ($services as $id => $ref) { + $services[$id] = new ServiceClosureArgument($ref); + } + $locator->replaceArgument(0, $services); + } else { + $locator->setValues($services); + } + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php b/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php new file mode 100644 index 0000000..7d9c366 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Psr\Container\ContainerInterface as PsrContainerInterface; +use Symfony\Component\DependencyInjection\Argument\BoundArgument; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\TypedReference; +use Symfony\Contracts\Service\ServiceProviderInterface; +use Symfony\Contracts\Service\ServiceSubscriberInterface; + +/** + * Compiler pass to register tagged services that require a service locator. + * + * @author Nicolas Grekas + */ +class RegisterServiceSubscribersPass extends AbstractRecursivePass +{ + protected function processValue($value, bool $isRoot = false) + { + if (!$value instanceof Definition || $value->isAbstract() || $value->isSynthetic() || !$value->hasTag('container.service_subscriber')) { + return parent::processValue($value, $isRoot); + } + + $serviceMap = []; + $autowire = $value->isAutowired(); + + foreach ($value->getTag('container.service_subscriber') as $attributes) { + if (!$attributes) { + $autowire = true; + continue; + } + ksort($attributes); + if ([] !== array_diff(array_keys($attributes), ['id', 'key'])) { + throw new InvalidArgumentException(sprintf('The "container.service_subscriber" tag accepts only the "key" and "id" attributes, "%s" given for service "%s".', implode('", "', array_keys($attributes)), $this->currentId)); + } + if (!\array_key_exists('id', $attributes)) { + throw new InvalidArgumentException(sprintf('Missing "id" attribute on "container.service_subscriber" tag with key="%s" for service "%s".', $attributes['key'], $this->currentId)); + } + if (!\array_key_exists('key', $attributes)) { + $attributes['key'] = $attributes['id']; + } + if (isset($serviceMap[$attributes['key']])) { + continue; + } + $serviceMap[$attributes['key']] = new Reference($attributes['id']); + } + $class = $value->getClass(); + + if (!$r = $this->container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $this->currentId)); + } + if (!$r->isSubclassOf(ServiceSubscriberInterface::class)) { + throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $this->currentId, ServiceSubscriberInterface::class)); + } + $class = $r->name; + + $subscriberMap = []; + + foreach ($class::getSubscribedServices() as $key => $type) { + if (!\is_string($type) || !preg_match('/^\??[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $type)) { + throw new InvalidArgumentException(sprintf('"%s::getSubscribedServices()" must return valid PHP types for service "%s" key "%s", "%s" returned.', $class, $this->currentId, $key, \is_string($type) ? $type : \gettype($type))); + } + if ($optionalBehavior = '?' === $type[0]) { + $type = substr($type, 1); + $optionalBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; + } + if (\is_int($name = $key)) { + $key = $type; + $name = null; + } + if (!isset($serviceMap[$key])) { + if (!$autowire) { + throw new InvalidArgumentException(sprintf('Service "%s" misses a "container.service_subscriber" tag with "key"/"id" attributes corresponding to entry "%s" as returned by "%s::getSubscribedServices()".', $this->currentId, $key, $class)); + } + $serviceMap[$key] = new Reference($type); + } + + if (false !== $i = strpos($name, '::get')) { + $name = lcfirst(substr($name, 5 + $i)); + } elseif (false !== strpos($name, '::')) { + $name = null; + } + + if (null !== $name && !$this->container->has($name) && !$this->container->has($type.' $'.$name)) { + $camelCaseName = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $name)))); + $name = $this->container->has($type.' $'.$camelCaseName) ? $camelCaseName : $name; + } + + $subscriberMap[$key] = new TypedReference((string) $serviceMap[$key], $type, $optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $name); + unset($serviceMap[$key]); + } + + if ($serviceMap = array_keys($serviceMap)) { + $message = sprintf(1 < \count($serviceMap) ? 'keys "%s" do' : 'key "%s" does', str_replace('%', '%%', implode('", "', $serviceMap))); + throw new InvalidArgumentException(sprintf('Service %s not exist in the map returned by "%s::getSubscribedServices()" for service "%s".', $message, $class, $this->currentId)); + } + + $locatorRef = ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId); + + $value->addTag('container.service_subscriber.locator', ['id' => (string) $locatorRef]); + + $value->setBindings([ + PsrContainerInterface::class => new BoundArgument($locatorRef, false), + ServiceProviderInterface::class => new BoundArgument($locatorRef, false), + ] + $value->getBindings()); + + return parent::processValue($value); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php b/vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php new file mode 100644 index 0000000..04b6852 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Removes abstract Definitions. + */ +class RemoveAbstractDefinitionsPass implements CompilerPassInterface +{ + /** + * Removes abstract definitions from the ContainerBuilder. + */ + public function process(ContainerBuilder $container) + { + foreach ($container->getDefinitions() as $id => $definition) { + if ($definition->isAbstract()) { + $container->removeDefinition($id); + $container->log($this, sprintf('Removed service "%s"; reason: abstract.', $id)); + } + } + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php b/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php new file mode 100644 index 0000000..75b36d2 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Remove private aliases from the container. They were only used to establish + * dependencies between services, and these dependencies have been resolved in + * one of the previous passes. + * + * @author Johannes M. Schmitt + */ +class RemovePrivateAliasesPass implements CompilerPassInterface +{ + /** + * Removes private aliases from the ContainerBuilder. + */ + public function process(ContainerBuilder $container) + { + foreach ($container->getAliases() as $id => $alias) { + if ($alias->isPublic()) { + continue; + } + + $container->removeAlias($id); + $container->log($this, sprintf('Removed service "%s"; reason: private alias.', $id)); + } + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php b/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php new file mode 100644 index 0000000..cf1a3dd --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Removes unused service definitions from the container. + * + * @author Johannes M. Schmitt + * @author Nicolas Grekas + */ +class RemoveUnusedDefinitionsPass extends AbstractRecursivePass +{ + private $connectedIds = []; + + /** + * Processes the ContainerBuilder to remove unused definitions. + */ + public function process(ContainerBuilder $container) + { + try { + $this->enableExpressionProcessing(); + $this->container = $container; + $connectedIds = []; + $aliases = $container->getAliases(); + + foreach ($aliases as $id => $alias) { + if ($alias->isPublic()) { + $this->connectedIds[] = (string) $aliases[$id]; + } + } + + foreach ($container->getDefinitions() as $id => $definition) { + if ($definition->isPublic()) { + $connectedIds[$id] = true; + $this->processValue($definition); + } + } + + while ($this->connectedIds) { + $ids = $this->connectedIds; + $this->connectedIds = []; + foreach ($ids as $id) { + if (!isset($connectedIds[$id]) && $container->hasDefinition($id)) { + $connectedIds[$id] = true; + $this->processValue($container->getDefinition($id)); + } + } + } + + foreach ($container->getDefinitions() as $id => $definition) { + if (!isset($connectedIds[$id])) { + $container->removeDefinition($id); + $container->resolveEnvPlaceholders(!$definition->hasErrors() ? serialize($definition) : $definition); + $container->log($this, sprintf('Removed service "%s"; reason: unused.', $id)); + } + } + } finally { + $this->container = null; + $this->connectedIds = []; + } + } + + /** + * {@inheritdoc} + */ + protected function processValue($value, bool $isRoot = false) + { + if (!$value instanceof Reference) { + return parent::processValue($value, $isRoot); + } + + if (ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior()) { + $this->connectedIds[] = (string) $value; + } + + return $value; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php b/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php new file mode 100644 index 0000000..ca781f2 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Replaces aliases with actual service definitions, effectively removing these + * aliases. + * + * @author Johannes M. Schmitt + */ +class ReplaceAliasByActualDefinitionPass extends AbstractRecursivePass +{ + private $replacements; + + /** + * Process the Container to replace aliases with service definitions. + * + * @throws InvalidArgumentException if the service definition does not exist + */ + public function process(ContainerBuilder $container) + { + // First collect all alias targets that need to be replaced + $seenAliasTargets = []; + $replacements = []; + foreach ($container->getAliases() as $definitionId => $target) { + $targetId = (string) $target; + // Special case: leave this target alone + if ('service_container' === $targetId) { + continue; + } + // Check if target needs to be replaces + if (isset($replacements[$targetId])) { + $container->setAlias($definitionId, $replacements[$targetId])->setPublic($target->isPublic())->setPrivate($target->isPrivate()); + } + // No need to process the same target twice + if (isset($seenAliasTargets[$targetId])) { + continue; + } + // Process new target + $seenAliasTargets[$targetId] = true; + try { + $definition = $container->getDefinition($targetId); + } catch (ServiceNotFoundException $e) { + if ('' !== $e->getId() && '@' === $e->getId()[0]) { + throw new ServiceNotFoundException($e->getId(), $e->getSourceId(), null, [substr($e->getId(), 1)]); + } + + throw $e; + } + if ($definition->isPublic()) { + continue; + } + // Remove private definition and schedule for replacement + $definition->setPublic(!$target->isPrivate()); + $definition->setPrivate($target->isPrivate()); + $container->setDefinition($definitionId, $definition); + $container->removeDefinition($targetId); + $replacements[$targetId] = $definitionId; + } + $this->replacements = $replacements; + + parent::process($container); + $this->replacements = []; + } + + /** + * {@inheritdoc} + */ + protected function processValue($value, bool $isRoot = false) + { + if ($value instanceof Reference && isset($this->replacements[$referenceId = (string) $value])) { + // Perform the replacement + $newId = $this->replacements[$referenceId]; + $value = new Reference($newId, $value->getInvalidBehavior()); + $this->container->log($this, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $this->currentId, $referenceId, $newId)); + } + + return parent::processValue($value, $isRoot); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php new file mode 100644 index 0000000..77eff72 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php @@ -0,0 +1,227 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\BoundArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\TypedReference; + +/** + * @author Guilhem Niot + */ +class ResolveBindingsPass extends AbstractRecursivePass +{ + private $usedBindings = []; + private $unusedBindings = []; + private $errorMessages = []; + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->usedBindings = $container->getRemovedBindingIds(); + + try { + parent::process($container); + + foreach ($this->unusedBindings as list($key, $serviceId, $bindingType, $file)) { + $argumentType = $argumentName = $message = null; + + if (false !== strpos($key, ' ')) { + list($argumentType, $argumentName) = explode(' ', $key, 2); + } elseif ('$' === $key[0]) { + $argumentName = $key; + } else { + $argumentType = $key; + } + + if ($argumentType) { + $message .= sprintf('of type "%s" ', $argumentType); + } + + if ($argumentName) { + $message .= sprintf('named "%s" ', $argumentName); + } + + if (BoundArgument::DEFAULTS_BINDING === $bindingType) { + $message .= 'under "_defaults"'; + } elseif (BoundArgument::INSTANCEOF_BINDING === $bindingType) { + $message .= 'under "_instanceof"'; + } else { + $message .= sprintf('for service "%s"', $serviceId); + } + + if ($file) { + $message .= sprintf(' in file "%s"', $file); + } + + $message = sprintf('A binding is configured for an argument %s, but no corresponding argument has been found. It may be unused and should be removed, or it may have a typo.', $message); + + if ($this->errorMessages) { + $message .= sprintf("\nCould be related to%s:", 1 < \count($this->errorMessages) ? ' one of' : ''); + } + foreach ($this->errorMessages as $m) { + $message .= "\n - ".$m; + } + throw new InvalidArgumentException($message); + } + } finally { + $this->usedBindings = []; + $this->unusedBindings = []; + $this->errorMessages = []; + } + } + + /** + * {@inheritdoc} + */ + protected function processValue($value, bool $isRoot = false) + { + if ($value instanceof TypedReference && $value->getType() === (string) $value) { + // Already checked + $bindings = $this->container->getDefinition($this->currentId)->getBindings(); + $name = $value->getName(); + + if (isset($name, $bindings[$name = $value.' $'.$name])) { + return $this->getBindingValue($bindings[$name]); + } + + if (isset($bindings[$value->getType()])) { + return $this->getBindingValue($bindings[$value->getType()]); + } + + return parent::processValue($value, $isRoot); + } + + if (!$value instanceof Definition || !$bindings = $value->getBindings()) { + return parent::processValue($value, $isRoot); + } + + foreach ($bindings as $key => $binding) { + list($bindingValue, $bindingId, $used, $bindingType, $file) = $binding->getValues(); + if ($used) { + $this->usedBindings[$bindingId] = true; + unset($this->unusedBindings[$bindingId]); + } elseif (!isset($this->usedBindings[$bindingId])) { + $this->unusedBindings[$bindingId] = [$key, $this->currentId, $bindingType, $file]; + } + + if (preg_match('/^(?:(?:array|bool|float|int|string) )?\$/', $key)) { + continue; + } + + if (null !== $bindingValue && !$bindingValue instanceof Reference && !$bindingValue instanceof Definition && !$bindingValue instanceof TaggedIteratorArgument && !$bindingValue instanceof ServiceLocatorArgument) { + throw new InvalidArgumentException(sprintf('Invalid value for binding key "%s" for service "%s": expected null, %s, %s, %s or ServiceLocatorArgument, %s given.', $key, $this->currentId, Reference::class, Definition::class, TaggedIteratorArgument::class, \gettype($bindingValue))); + } + } + + if ($value->isAbstract()) { + return parent::processValue($value, $isRoot); + } + + $calls = $value->getMethodCalls(); + + try { + if ($constructor = $this->getConstructor($value, false)) { + $calls[] = [$constructor, $value->getArguments()]; + } + } catch (RuntimeException $e) { + $this->errorMessages[] = $e->getMessage(); + $this->container->getDefinition($this->currentId)->addError($e->getMessage()); + + return parent::processValue($value, $isRoot); + } + + foreach ($calls as $i => $call) { + list($method, $arguments) = $call; + + if ($method instanceof \ReflectionFunctionAbstract) { + $reflectionMethod = $method; + } else { + try { + $reflectionMethod = $this->getReflectionMethod($value, $method); + } catch (RuntimeException $e) { + if ($value->getFactory()) { + continue; + } + throw $e; + } + } + + foreach ($reflectionMethod->getParameters() as $key => $parameter) { + if (\array_key_exists($key, $arguments) && '' !== $arguments[$key]) { + continue; + } + + $typeHint = ProxyHelper::getTypeHint($reflectionMethod, $parameter); + + if (\array_key_exists($k = ltrim($typeHint, '\\').' $'.$parameter->name, $bindings)) { + $arguments[$key] = $this->getBindingValue($bindings[$k]); + + continue; + } + + if (\array_key_exists('$'.$parameter->name, $bindings)) { + $arguments[$key] = $this->getBindingValue($bindings['$'.$parameter->name]); + + continue; + } + + if (!$typeHint || '\\' !== $typeHint[0] || !isset($bindings[$typeHint = substr($typeHint, 1)])) { + continue; + } + + $arguments[$key] = $this->getBindingValue($bindings[$typeHint]); + } + + if ($arguments !== $call[1]) { + ksort($arguments); + $calls[$i][1] = $arguments; + } + } + + if ($constructor) { + list(, $arguments) = array_pop($calls); + + if ($arguments !== $value->getArguments()) { + $value->setArguments($arguments); + } + } + + if ($calls !== $value->getMethodCalls()) { + $value->setMethodCalls($calls); + } + + return parent::processValue($value, $isRoot); + } + + /** + * @return mixed + */ + private function getBindingValue(BoundArgument $binding) + { + list($bindingValue, $bindingId) = $binding->getValues(); + + $this->usedBindings[$bindingId] = true; + unset($this->unusedBindings[$bindingId]); + + return $bindingValue; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php new file mode 100644 index 0000000..f180d22 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php @@ -0,0 +1,190 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\ExceptionInterface; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; + +/** + * This replaces all ChildDefinition instances with their equivalent fully + * merged Definition instance. + * + * @author Johannes M. Schmitt + * @author Nicolas Grekas + */ +class ResolveChildDefinitionsPass extends AbstractRecursivePass +{ + private $currentPath; + + protected function processValue($value, bool $isRoot = false) + { + if (!$value instanceof Definition) { + return parent::processValue($value, $isRoot); + } + if ($isRoot) { + // yes, we are specifically fetching the definition from the + // container to ensure we are not operating on stale data + $value = $this->container->getDefinition($this->currentId); + } + if ($value instanceof ChildDefinition) { + $this->currentPath = []; + $value = $this->resolveDefinition($value); + if ($isRoot) { + $this->container->setDefinition($this->currentId, $value); + } + } + + return parent::processValue($value, $isRoot); + } + + /** + * Resolves the definition. + * + * @throws RuntimeException When the definition is invalid + */ + private function resolveDefinition(ChildDefinition $definition): Definition + { + try { + return $this->doResolveDefinition($definition); + } catch (ServiceCircularReferenceException $e) { + throw $e; + } catch (ExceptionInterface $e) { + $r = new \ReflectionProperty($e, 'message'); + $r->setAccessible(true); + $r->setValue($e, sprintf('Service "%s": %s', $this->currentId, $e->getMessage())); + + throw $e; + } + } + + private function doResolveDefinition(ChildDefinition $definition): Definition + { + if (!$this->container->has($parent = $definition->getParent())) { + throw new RuntimeException(sprintf('Parent definition "%s" does not exist.', $parent)); + } + + $searchKey = array_search($parent, $this->currentPath); + $this->currentPath[] = $parent; + + if (false !== $searchKey) { + throw new ServiceCircularReferenceException($parent, \array_slice($this->currentPath, $searchKey)); + } + + $parentDef = $this->container->findDefinition($parent); + if ($parentDef instanceof ChildDefinition) { + $id = $this->currentId; + $this->currentId = $parent; + $parentDef = $this->resolveDefinition($parentDef); + $this->container->setDefinition($parent, $parentDef); + $this->currentId = $id; + } + + $this->container->log($this, sprintf('Resolving inheritance for "%s" (parent: %s).', $this->currentId, $parent)); + $def = new Definition(); + + // merge in parent definition + // purposely ignored attributes: abstract, shared, tags, autoconfigured + $def->setClass($parentDef->getClass()); + $def->setArguments($parentDef->getArguments()); + $def->setMethodCalls($parentDef->getMethodCalls()); + $def->setProperties($parentDef->getProperties()); + if ($parentDef->isDeprecated()) { + $def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%')); + } + $def->setFactory($parentDef->getFactory()); + $def->setConfigurator($parentDef->getConfigurator()); + $def->setFile($parentDef->getFile()); + $def->setPublic($parentDef->isPublic()); + $def->setLazy($parentDef->isLazy()); + $def->setAutowired($parentDef->isAutowired()); + $def->setChanges($parentDef->getChanges()); + + $def->setBindings($definition->getBindings() + $parentDef->getBindings()); + + // overwrite with values specified in the decorator + $changes = $definition->getChanges(); + if (isset($changes['class'])) { + $def->setClass($definition->getClass()); + } + if (isset($changes['factory'])) { + $def->setFactory($definition->getFactory()); + } + if (isset($changes['configurator'])) { + $def->setConfigurator($definition->getConfigurator()); + } + if (isset($changes['file'])) { + $def->setFile($definition->getFile()); + } + if (isset($changes['public'])) { + $def->setPublic($definition->isPublic()); + } else { + $def->setPrivate($definition->isPrivate() || $parentDef->isPrivate()); + } + if (isset($changes['lazy'])) { + $def->setLazy($definition->isLazy()); + } + if (isset($changes['deprecated'])) { + $def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%')); + } + if (isset($changes['autowired'])) { + $def->setAutowired($definition->isAutowired()); + } + if (isset($changes['shared'])) { + $def->setShared($definition->isShared()); + } + if (isset($changes['decorated_service'])) { + $decoratedService = $definition->getDecoratedService(); + if (null === $decoratedService) { + $def->setDecoratedService($decoratedService); + } else { + $def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2], $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE); + } + } + + // merge arguments + foreach ($definition->getArguments() as $k => $v) { + if (is_numeric($k)) { + $def->addArgument($v); + } elseif (0 === strpos($k, 'index_')) { + $def->replaceArgument((int) substr($k, \strlen('index_')), $v); + } else { + $def->setArgument($k, $v); + } + } + + // merge properties + foreach ($definition->getProperties() as $k => $v) { + $def->setProperty($k, $v); + } + + // append method calls + if ($calls = $definition->getMethodCalls()) { + $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls)); + } + + $def->addError($parentDef); + $def->addError($definition); + + // these attributes are always taken from the child + $def->setAbstract($definition->isAbstract()); + $def->setTags($definition->getTags()); + // autoconfigure is never taken from parent (on purpose) + // and it's not legal on an instanceof + $def->setAutoconfigured($definition->isAutoconfigured()); + + return $def; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php new file mode 100644 index 0000000..5932472 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +/** + * @author Nicolas Grekas + */ +class ResolveClassPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + foreach ($container->getDefinitions() as $id => $definition) { + if ($definition->isSynthetic() || null !== $definition->getClass()) { + continue; + } + if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $id)) { + if ($definition instanceof ChildDefinition && !class_exists($id)) { + throw new InvalidArgumentException(sprintf('Service definition "%s" has a parent but no class, and its name looks like a FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.', $id)); + } + $definition->setClass($id); + } + } + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php new file mode 100644 index 0000000..ea52b14 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Definition; + +/** + * Replaces env var placeholders by their current values. + */ +class ResolveEnvPlaceholdersPass extends AbstractRecursivePass +{ + protected function processValue($value, bool $isRoot = false) + { + if (\is_string($value)) { + return $this->container->resolveEnvPlaceholders($value, true); + } + if ($value instanceof Definition) { + $changes = $value->getChanges(); + if (isset($changes['class'])) { + $value->setClass($this->container->resolveEnvPlaceholders($value->getClass(), true)); + } + if (isset($changes['file'])) { + $value->setFile($this->container->resolveEnvPlaceholders($value->getFile(), true)); + } + } + + $value = parent::processValue($value, $isRoot); + + if ($value && \is_array($value) && !$isRoot) { + $value = array_combine($this->container->resolveEnvPlaceholders(array_keys($value), true), $value); + } + + return $value; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php new file mode 100644 index 0000000..23f535b --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + +/** + * @author Maxime Steinhausser + */ +class ResolveFactoryClassPass extends AbstractRecursivePass +{ + /** + * {@inheritdoc} + */ + protected function processValue($value, bool $isRoot = false) + { + if ($value instanceof Definition && \is_array($factory = $value->getFactory()) && null === $factory[0]) { + if (null === $class = $value->getClass()) { + throw new RuntimeException(sprintf('The "%s" service is defined to be created by a factory, but is missing the factory class. Did you forget to define the factory or service class?', $this->currentId)); + } + + $factory[0] = $class; + $value->setFactory($factory); + } + + return parent::processValue($value, $isRoot); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php new file mode 100644 index 0000000..0d01e2a --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Propagate "container.hot_path" tags to referenced services. + * + * @author Nicolas Grekas + */ +class ResolveHotPathPass extends AbstractRecursivePass +{ + private $tagName; + private $resolvedIds = []; + + public function __construct(string $tagName = 'container.hot_path') + { + $this->tagName = $tagName; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + try { + parent::process($container); + $container->getDefinition('service_container')->clearTag($this->tagName); + } finally { + $this->resolvedIds = []; + } + } + + /** + * {@inheritdoc} + */ + protected function processValue($value, bool $isRoot = false) + { + if ($value instanceof ArgumentInterface) { + return $value; + } + if ($value instanceof Definition && $isRoot && (isset($this->resolvedIds[$this->currentId]) || !$value->hasTag($this->tagName) || $value->isDeprecated())) { + return $value->isDeprecated() ? $value->clearTag($this->tagName) : $value; + } + if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->has($id = (string) $value)) { + $definition = $this->container->findDefinition($id); + if (!$definition->hasTag($this->tagName) && !$definition->isDeprecated()) { + $this->resolvedIds[$id] = true; + $definition->addTag($this->tagName); + parent::processValue($definition, false); + } + + return $value; + } + + return parent::processValue($value, $isRoot); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php new file mode 100644 index 0000000..96afb03 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php @@ -0,0 +1,168 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + +/** + * Applies instanceof conditionals to definitions. + * + * @author Nicolas Grekas + */ +class ResolveInstanceofConditionalsPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + foreach ($container->getAutoconfiguredInstanceof() as $interface => $definition) { + if ($definition->getArguments()) { + throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines arguments but these are not supported and should be removed.', $interface)); + } + } + + foreach ($container->getDefinitions() as $id => $definition) { + if ($definition instanceof ChildDefinition) { + // don't apply "instanceof" to children: it will be applied to their parent + continue; + } + $container->setDefinition($id, $this->processDefinition($container, $id, $definition)); + } + } + + private function processDefinition(ContainerBuilder $container, string $id, Definition $definition): Definition + { + $instanceofConditionals = $definition->getInstanceofConditionals(); + $autoconfiguredInstanceof = $definition->isAutoconfigured() ? $container->getAutoconfiguredInstanceof() : []; + if (!$instanceofConditionals && !$autoconfiguredInstanceof) { + return $definition; + } + + if (!$class = $container->getParameterBag()->resolveValue($definition->getClass())) { + return $definition; + } + + $conditionals = $this->mergeConditionals($autoconfiguredInstanceof, $instanceofConditionals, $container); + + $definition->setInstanceofConditionals([]); + $parent = $shared = null; + $instanceofTags = []; + $instanceofCalls = []; + $instanceofBindings = []; + $reflectionClass = null; + + foreach ($conditionals as $interface => $instanceofDefs) { + if ($interface !== $class && !(null === $reflectionClass ? $reflectionClass = ($container->getReflectionClass($class, false) ?: false) : $reflectionClass)) { + continue; + } + + if ($interface !== $class && !is_subclass_of($class, $interface)) { + continue; + } + + foreach ($instanceofDefs as $key => $instanceofDef) { + /** @var ChildDefinition $instanceofDef */ + $instanceofDef = clone $instanceofDef; + $instanceofDef->setAbstract(true)->setParent($parent ?: '.abstract.instanceof.'.$id); + $parent = '.instanceof.'.$interface.'.'.$key.'.'.$id; + $container->setDefinition($parent, $instanceofDef); + $instanceofTags[] = $instanceofDef->getTags(); + $instanceofBindings = $instanceofDef->getBindings() + $instanceofBindings; + + foreach ($instanceofDef->getMethodCalls() as $methodCall) { + $instanceofCalls[] = $methodCall; + } + + $instanceofDef->setTags([]); + $instanceofDef->setMethodCalls([]); + $instanceofDef->setBindings([]); + + if (isset($instanceofDef->getChanges()['shared'])) { + $shared = $instanceofDef->isShared(); + } + } + } + + if ($parent) { + $bindings = $definition->getBindings(); + $abstract = $container->setDefinition('.abstract.instanceof.'.$id, $definition); + + // cast Definition to ChildDefinition + $definition->setBindings([]); + $definition = serialize($definition); + $definition = substr_replace($definition, '53', 2, 2); + $definition = substr_replace($definition, 'Child', 44, 0); + /** @var ChildDefinition $definition */ + $definition = unserialize($definition); + $definition->setParent($parent); + + if (null !== $shared && !isset($definition->getChanges()['shared'])) { + $definition->setShared($shared); + } + + // Don't add tags to service decorators + if (null === $definition->getDecoratedService()) { + $i = \count($instanceofTags); + while (0 <= --$i) { + foreach ($instanceofTags[$i] as $k => $v) { + foreach ($v as $v) { + if ($definition->hasTag($k) && \in_array($v, $definition->getTag($k))) { + continue; + } + $definition->addTag($k, $v); + } + } + } + } + + $definition->setMethodCalls(array_merge($instanceofCalls, $definition->getMethodCalls())); + $definition->setBindings($bindings + $instanceofBindings); + + // reset fields with "merge" behavior + $abstract + ->setBindings([]) + ->setArguments([]) + ->setMethodCalls([]) + ->setDecoratedService(null) + ->setTags([]) + ->setAbstract(true); + } + + return $definition; + } + + private function mergeConditionals(array $autoconfiguredInstanceof, array $instanceofConditionals, ContainerBuilder $container): array + { + // make each value an array of ChildDefinition + $conditionals = array_map(function ($childDef) { return [$childDef]; }, $autoconfiguredInstanceof); + + foreach ($instanceofConditionals as $interface => $instanceofDef) { + // make sure the interface/class exists (but don't validate automaticInstanceofConditionals) + if (!$container->getReflectionClass($interface)) { + throw new RuntimeException(sprintf('"%s" is set as an "instanceof" conditional, but it does not exist.', $interface)); + } + + if (!isset($autoconfiguredInstanceof[$interface])) { + $conditionals[$interface] = []; + } + + $conditionals[$interface][] = $instanceofDef; + } + + return $conditionals; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php new file mode 100644 index 0000000..948de42 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\TypedReference; + +/** + * Emulates the invalid behavior if the reference is not found within the + * container. + * + * @author Johannes M. Schmitt + */ +class ResolveInvalidReferencesPass implements CompilerPassInterface +{ + private $container; + private $signalingException; + private $currentId; + + /** + * Process the ContainerBuilder to resolve invalid references. + */ + public function process(ContainerBuilder $container) + { + $this->container = $container; + $this->signalingException = new RuntimeException('Invalid reference.'); + + try { + foreach ($container->getDefinitions() as $this->currentId => $definition) { + $this->processValue($definition); + } + } finally { + $this->container = $this->signalingException = null; + } + } + + /** + * Processes arguments to determine invalid references. + * + * @return mixed + * + * @throws RuntimeException When an invalid reference is found + */ + private function processValue($value, int $rootLevel = 0, int $level = 0) + { + if ($value instanceof ServiceClosureArgument) { + $value->setValues($this->processValue($value->getValues(), 1, 1)); + } elseif ($value instanceof ArgumentInterface) { + $value->setValues($this->processValue($value->getValues(), $rootLevel, 1 + $level)); + } elseif ($value instanceof Definition) { + if ($value->isSynthetic() || $value->isAbstract()) { + return $value; + } + $value->setArguments($this->processValue($value->getArguments(), 0)); + $value->setProperties($this->processValue($value->getProperties(), 1)); + $value->setMethodCalls($this->processValue($value->getMethodCalls(), 2)); + } elseif (\is_array($value)) { + $i = 0; + + foreach ($value as $k => $v) { + try { + if (false !== $i && $k !== $i++) { + $i = false; + } + if ($v !== $processedValue = $this->processValue($v, $rootLevel, 1 + $level)) { + $value[$k] = $processedValue; + } + } catch (RuntimeException $e) { + if ($rootLevel < $level || ($rootLevel && !$level)) { + unset($value[$k]); + } elseif ($rootLevel) { + throw $e; + } else { + $value[$k] = null; + } + } + } + + // Ensure numerically indexed arguments have sequential numeric keys. + if (false !== $i) { + $value = array_values($value); + } + } elseif ($value instanceof Reference) { + if ($this->container->has($id = (string) $value)) { + return $value; + } + + $currentDefinition = $this->container->getDefinition($this->currentId); + + // resolve decorated service behavior depending on decorator service + if ($currentDefinition->innerServiceId === $id && ContainerInterface::NULL_ON_INVALID_REFERENCE === $currentDefinition->decorationOnInvalid) { + return null; + } + + $invalidBehavior = $value->getInvalidBehavior(); + + if (ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior && $value instanceof TypedReference && !$this->container->has($id)) { + $e = new ServiceNotFoundException($id, $this->currentId); + + // since the error message varies by $id and $this->currentId, so should the id of the dummy errored definition + $this->container->register($id = sprintf('.errored.%s.%s', $this->currentId, $id), $value->getType()) + ->addError($e->getMessage()); + + return new TypedReference($id, $value->getType(), $value->getInvalidBehavior()); + } + + // resolve invalid behavior + if (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) { + $value = null; + } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) { + if (0 < $level || $rootLevel) { + throw $this->signalingException; + } + $value = null; + } + } + + return $value; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php new file mode 100644 index 0000000..8fa3868 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Resolves named arguments to their corresponding numeric index. + * + * @author Kévin Dunglas + */ +class ResolveNamedArgumentsPass extends AbstractRecursivePass +{ + /** + * {@inheritdoc} + */ + protected function processValue($value, bool $isRoot = false) + { + if (!$value instanceof Definition) { + return parent::processValue($value, $isRoot); + } + + $calls = $value->getMethodCalls(); + $calls[] = ['__construct', $value->getArguments()]; + + foreach ($calls as $i => $call) { + list($method, $arguments) = $call; + $parameters = null; + $resolvedArguments = []; + + foreach ($arguments as $key => $argument) { + if (\is_int($key)) { + $resolvedArguments[$key] = $argument; + continue; + } + + if (null === $parameters) { + $r = $this->getReflectionMethod($value, $method); + $class = $r instanceof \ReflectionMethod ? $r->class : $this->currentId; + $method = $r->getName(); + $parameters = $r->getParameters(); + } + + if (isset($key[0]) && '$' !== $key[0] && !class_exists($key) && !interface_exists($key, false)) { + throw new InvalidArgumentException(sprintf('Invalid service "%s": did you forget to add the "$" prefix to argument "%s"?', $this->currentId, $key)); + } + + if (isset($key[0]) && '$' === $key[0]) { + foreach ($parameters as $j => $p) { + if ($key === '$'.$p->name) { + if ($p->isVariadic() && \is_array($argument)) { + foreach ($argument as $variadicArgument) { + $resolvedArguments[$j++] = $variadicArgument; + } + } else { + $resolvedArguments[$j] = $argument; + } + + continue 2; + } + } + + throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument named "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); + } + + if (null !== $argument && !$argument instanceof Reference && !$argument instanceof Definition) { + throw new InvalidArgumentException(sprintf('Invalid service "%s": the value of argument "%s" of method "%s()" must be null, an instance of %s or an instance of %s, %s given.', $this->currentId, $key, $class !== $this->currentId ? $class.'::'.$method : $method, Reference::class, Definition::class, \gettype($argument))); + } + + $typeFound = false; + foreach ($parameters as $j => $p) { + if (!\array_key_exists($j, $resolvedArguments) && ProxyHelper::getTypeHint($r, $p, true) === $key) { + $resolvedArguments[$j] = $argument; + $typeFound = true; + } + } + + if (!$typeFound) { + throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument type-hinted as "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); + } + } + + if ($resolvedArguments !== $call[1]) { + ksort($resolvedArguments); + $calls[$i][1] = $resolvedArguments; + } + } + + list(, $arguments) = array_pop($calls); + + if ($arguments !== $value->getArguments()) { + $value->setArguments($arguments); + } + if ($calls !== $value->getMethodCalls()) { + $value->setMethodCalls($calls); + } + + return parent::processValue($value, $isRoot); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php new file mode 100644 index 0000000..91bba7d --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; + +/** + * Resolves all parameter placeholders "%somevalue%" to their real values. + * + * @author Johannes M. Schmitt + */ +class ResolveParameterPlaceHoldersPass extends AbstractRecursivePass +{ + private $bag; + private $resolveArrays; + + public function __construct(bool $resolveArrays = true) + { + $this->resolveArrays = $resolveArrays; + } + + /** + * {@inheritdoc} + * + * @throws ParameterNotFoundException + */ + public function process(ContainerBuilder $container) + { + $this->bag = $container->getParameterBag(); + + try { + parent::process($container); + + $aliases = []; + foreach ($container->getAliases() as $name => $target) { + $this->currentId = $name; + $aliases[$this->bag->resolveValue($name)] = $target; + } + $container->setAliases($aliases); + } catch (ParameterNotFoundException $e) { + $e->setSourceId($this->currentId); + + throw $e; + } + + $this->bag->resolve(); + $this->bag = null; + } + + protected function processValue($value, bool $isRoot = false) + { + if (\is_string($value)) { + $v = $this->bag->resolveValue($value); + + return $this->resolveArrays || !$v || !\is_array($v) ? $v : $value; + } + if ($value instanceof Definition) { + $value->setBindings($this->processValue($value->getBindings())); + $changes = $value->getChanges(); + if (isset($changes['class'])) { + $value->setClass($this->bag->resolveValue($value->getClass())); + } + if (isset($changes['file'])) { + $value->setFile($this->bag->resolveValue($value->getFile())); + } + } + + $value = parent::processValue($value, $isRoot); + + if ($value && \is_array($value)) { + $value = array_combine($this->bag->resolveValue(array_keys($value)), $value); + } + + return $value; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php b/vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php new file mode 100644 index 0000000..1bd9934 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * @author Nicolas Grekas + */ +class ResolvePrivatesPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + foreach ($container->getDefinitions() as $id => $definition) { + if ($definition->isPrivate()) { + $definition->setPublic(false); + $definition->setPrivate(true); + } + } + + foreach ($container->getAliases() as $id => $alias) { + if ($alias->isPrivate()) { + $alias->setPublic(false); + $alias->setPrivate(true); + } + } + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php new file mode 100644 index 0000000..f38dbc7 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Replaces all references to aliases with references to the actual service. + * + * @author Johannes M. Schmitt + */ +class ResolveReferencesToAliasesPass extends AbstractRecursivePass +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + parent::process($container); + + foreach ($container->getAliases() as $id => $alias) { + $aliasId = (string) $alias; + $this->currentId = $id; + + if ($aliasId !== $defId = $this->getDefinitionId($aliasId, $container)) { + $container->setAlias($id, $defId)->setPublic($alias->isPublic())->setPrivate($alias->isPrivate()); + } + } + } + + /** + * {@inheritdoc} + */ + protected function processValue($value, bool $isRoot = false) + { + if (!$value instanceof Reference) { + return parent::processValue($value, $isRoot); + } + + $defId = $this->getDefinitionId($id = (string) $value, $this->container); + + return $defId !== $id ? new Reference($defId, $value->getInvalidBehavior()) : $value; + } + + private function getDefinitionId(string $id, ContainerBuilder $container): string + { + if (!$container->hasAlias($id)) { + return $id; + } + + $alias = $container->getAlias($id); + + if ($alias->isDeprecated()) { + @trigger_error(sprintf('%s. It is being referenced by the "%s" %s.', rtrim($alias->getDeprecationMessage($id), '. '), $this->currentId, $container->hasDefinition($this->currentId) ? 'service' : 'alias'), E_USER_DEPRECATED); + } + + $seen = []; + do { + if (isset($seen[$id])) { + throw new ServiceCircularReferenceException($id, array_merge(array_keys($seen), [$id])); + } + + $seen[$id] = true; + $id = (string) $container->getAlias($id); + } while ($container->hasAlias($id)); + + return $id; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php new file mode 100644 index 0000000..518c03d --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Contracts\Service\ServiceProviderInterface; + +/** + * Compiler pass to inject their service locator to service subscribers. + * + * @author Nicolas Grekas + */ +class ResolveServiceSubscribersPass extends AbstractRecursivePass +{ + private $serviceLocator; + + protected function processValue($value, bool $isRoot = false) + { + if ($value instanceof Reference && $this->serviceLocator && \in_array((string) $value, [ContainerInterface::class, ServiceProviderInterface::class], true)) { + return new Reference($this->serviceLocator); + } + + if (!$value instanceof Definition) { + return parent::processValue($value, $isRoot); + } + + $serviceLocator = $this->serviceLocator; + $this->serviceLocator = null; + + if ($value->hasTag('container.service_subscriber.locator')) { + $this->serviceLocator = $value->getTag('container.service_subscriber.locator')[0]['id']; + $value->clearTag('container.service_subscriber.locator'); + } + + try { + return parent::processValue($value); + } finally { + $this->serviceLocator = $serviceLocator; + } + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php new file mode 100644 index 0000000..48a034a --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; + +/** + * Resolves all TaggedIteratorArgument arguments. + * + * @author Roland Franssen + */ +class ResolveTaggedIteratorArgumentPass extends AbstractRecursivePass +{ + use PriorityTaggedServiceTrait; + + /** + * {@inheritdoc} + */ + protected function processValue($value, bool $isRoot = false) + { + if (!$value instanceof TaggedIteratorArgument) { + return parent::processValue($value, $isRoot); + } + + $value->setValues($this->findAndSortTaggedServices($value, $this->container)); + + return $value; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php b/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php new file mode 100644 index 0000000..5985451 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php @@ -0,0 +1,135 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ServiceLocator; + +/** + * Applies the "container.service_locator" tag by wrapping references into ServiceClosureArgument instances. + * + * @author Nicolas Grekas + */ +final class ServiceLocatorTagPass extends AbstractRecursivePass +{ + use PriorityTaggedServiceTrait; + + protected function processValue($value, bool $isRoot = false) + { + if ($value instanceof ServiceLocatorArgument) { + if ($value->getTaggedIteratorArgument()) { + $value->setValues($this->findAndSortTaggedServices($value->getTaggedIteratorArgument(), $this->container)); + } + + return self::register($this->container, $value->getValues()); + } + + if (!$value instanceof Definition || !$value->hasTag('container.service_locator')) { + return parent::processValue($value, $isRoot); + } + + if (!$value->getClass()) { + $value->setClass(ServiceLocator::class); + } + + $arguments = $value->getArguments(); + if (!isset($arguments[0]) || !\is_array($arguments[0])) { + throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set.', $this->currentId)); + } + + $i = 0; + + foreach ($arguments[0] as $k => $v) { + if ($v instanceof ServiceClosureArgument) { + continue; + } + if (!$v instanceof Reference) { + throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set, "%s" found for key "%s".', $this->currentId, \is_object($v) ? \get_class($v) : \gettype($v), $k)); + } + + if ($i === $k) { + unset($arguments[0][$k]); + + $k = (string) $v; + ++$i; + } elseif (\is_int($k)) { + $i = null; + } + $arguments[0][$k] = new ServiceClosureArgument($v); + } + ksort($arguments[0]); + + $value->setArguments($arguments); + + $id = '.service_locator.'.ContainerBuilder::hash($value); + + if ($isRoot) { + if ($id !== $this->currentId) { + $this->container->setAlias($id, new Alias($this->currentId, false)); + } + + return $value; + } + + $this->container->setDefinition($id, $value->setPublic(false)); + + return new Reference($id); + } + + /** + * @param Reference[] $refMap + */ + public static function register(ContainerBuilder $container, array $refMap, string $callerId = null): Reference + { + foreach ($refMap as $id => $ref) { + if (!$ref instanceof Reference) { + throw new InvalidArgumentException(sprintf('Invalid service locator definition: only services can be referenced, "%s" found for key "%s". Inject parameter values using constructors instead.', \is_object($ref) ? \get_class($ref) : \gettype($ref), $id)); + } + $refMap[$id] = new ServiceClosureArgument($ref); + } + ksort($refMap); + + $locator = (new Definition(ServiceLocator::class)) + ->addArgument($refMap) + ->setPublic(false) + ->addTag('container.service_locator'); + + if (null !== $callerId && $container->hasDefinition($callerId)) { + $locator->setBindings($container->getDefinition($callerId)->getBindings()); + } + + if (!$container->hasDefinition($id = '.service_locator.'.ContainerBuilder::hash($locator))) { + $container->setDefinition($id, $locator); + } + + if (null !== $callerId) { + $locatorId = $id; + // Locators are shared when they hold the exact same list of factories; + // to have them specialized per consumer service, we use a cloning factory + // to derivate customized instances from the prototype one. + $container->register($id .= '.'.$callerId, ServiceLocator::class) + ->setPublic(false) + ->setFactory([new Reference($locatorId), 'withContext']) + ->addTag('container.service_locator_context', ['id' => $callerId]) + ->addArgument($callerId) + ->addArgument(new Reference('service_container')); + } + + return new Reference($id); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php new file mode 100644 index 0000000..308abc6 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +/** + * This is a directed graph of your services. + * + * This information can be used by your compiler passes instead of collecting + * it themselves which improves performance quite a lot. + * + * @author Johannes M. Schmitt + * + * @final + */ +class ServiceReferenceGraph +{ + /** + * @var ServiceReferenceGraphNode[] + */ + private $nodes = []; + + public function hasNode(string $id): bool + { + return isset($this->nodes[$id]); + } + + /** + * Gets a node by identifier. + * + * @throws InvalidArgumentException if no node matches the supplied identifier + */ + public function getNode(string $id): ServiceReferenceGraphNode + { + if (!isset($this->nodes[$id])) { + throw new InvalidArgumentException(sprintf('There is no node with id "%s".', $id)); + } + + return $this->nodes[$id]; + } + + /** + * Returns all nodes. + * + * @return ServiceReferenceGraphNode[] + */ + public function getNodes(): array + { + return $this->nodes; + } + + /** + * Clears all nodes. + */ + public function clear() + { + foreach ($this->nodes as $node) { + $node->clear(); + } + $this->nodes = []; + } + + /** + * Connects 2 nodes together in the Graph. + */ + public function connect(?string $sourceId, $sourceValue, ?string $destId, $destValue = null, $reference = null, bool $lazy = false, bool $weak = false, bool $byConstructor = false) + { + if (null === $sourceId || null === $destId) { + return; + } + + $sourceNode = $this->createNode($sourceId, $sourceValue); + $destNode = $this->createNode($destId, $destValue); + $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference, $lazy, $weak, $byConstructor); + + $sourceNode->addOutEdge($edge); + $destNode->addInEdge($edge); + } + + private function createNode(string $id, $value): ServiceReferenceGraphNode + { + if (isset($this->nodes[$id]) && $this->nodes[$id]->getValue() === $value) { + return $this->nodes[$id]; + } + + return $this->nodes[$id] = new ServiceReferenceGraphNode($id, $value); + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php new file mode 100644 index 0000000..9861456 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +/** + * Represents an edge in your service graph. + * + * Value is typically a reference. + * + * @author Johannes M. Schmitt + */ +class ServiceReferenceGraphEdge +{ + private $sourceNode; + private $destNode; + private $value; + private $lazy; + private $weak; + private $byConstructor; + + public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null, bool $lazy = false, bool $weak = false, bool $byConstructor = false) + { + $this->sourceNode = $sourceNode; + $this->destNode = $destNode; + $this->value = $value; + $this->lazy = $lazy; + $this->weak = $weak; + $this->byConstructor = $byConstructor; + } + + /** + * Returns the value of the edge. + * + * @return mixed + */ + public function getValue() + { + return $this->value; + } + + /** + * Returns the source node. + * + * @return ServiceReferenceGraphNode + */ + public function getSourceNode() + { + return $this->sourceNode; + } + + /** + * Returns the destination node. + * + * @return ServiceReferenceGraphNode + */ + public function getDestNode() + { + return $this->destNode; + } + + /** + * Returns true if the edge is lazy, meaning it's a dependency not requiring direct instantiation. + * + * @return bool + */ + public function isLazy() + { + return $this->lazy; + } + + /** + * Returns true if the edge is weak, meaning it shouldn't prevent removing the target service. + * + * @return bool + */ + public function isWeak() + { + return $this->weak; + } + + /** + * Returns true if the edge links with a constructor argument. + * + * @return bool + */ + public function isReferencedByConstructor() + { + return $this->byConstructor; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php new file mode 100644 index 0000000..fec1424 --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Definition; + +/** + * Represents a node in your service graph. + * + * Value is typically a definition, or an alias. + * + * @author Johannes M. Schmitt + */ +class ServiceReferenceGraphNode +{ + private $id; + private $inEdges = []; + private $outEdges = []; + private $value; + + /** + * @param string $id The node identifier + * @param mixed $value The node value + */ + public function __construct(string $id, $value) + { + $this->id = $id; + $this->value = $value; + } + + public function addInEdge(ServiceReferenceGraphEdge $edge) + { + $this->inEdges[] = $edge; + } + + public function addOutEdge(ServiceReferenceGraphEdge $edge) + { + $this->outEdges[] = $edge; + } + + /** + * Checks if the value of this node is an Alias. + * + * @return bool True if the value is an Alias instance + */ + public function isAlias() + { + return $this->value instanceof Alias; + } + + /** + * Checks if the value of this node is a Definition. + * + * @return bool True if the value is a Definition instance + */ + public function isDefinition() + { + return $this->value instanceof Definition; + } + + /** + * Returns the identifier. + * + * @return string + */ + public function getId() + { + return $this->id; + } + + /** + * Returns the in edges. + * + * @return ServiceReferenceGraphEdge[] + */ + public function getInEdges() + { + return $this->inEdges; + } + + /** + * Returns the out edges. + * + * @return ServiceReferenceGraphEdge[] + */ + public function getOutEdges() + { + return $this->outEdges; + } + + /** + * Returns the value of this Node. + * + * @return mixed The value + */ + public function getValue() + { + return $this->value; + } + + /** + * Clears all edges. + */ + public function clear() + { + $this->inEdges = $this->outEdges = []; + } +} diff --git a/vendor/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php b/vendor/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php new file mode 100644 index 0000000..be0f1ed --- /dev/null +++ b/vendor/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\Config\Definition\BaseNode; +use Symfony\Component\Config\Definition\Processor; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; +use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; + +/** + * Validates environment variable placeholders used in extension configuration with dummy values. + * + * @author Roland Franssen + */ +class ValidateEnvPlaceholdersPass implements CompilerPassInterface +{ + private static $typeFixtures = ['array' => [], 'bool' => false, 'float' => 0.0, 'int' => 0, 'string' => '']; + + private $extensionConfig = []; + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->extensionConfig = []; + + if (!class_exists(BaseNode::class) || !$extensions = $container->getExtensions()) { + return; + } + + $resolvingBag = $container->getParameterBag(); + if (!$resolvingBag instanceof EnvPlaceholderParameterBag) { + return; + } + + $defaultBag = new ParameterBag($resolvingBag->all()); + $envTypes = $resolvingBag->getProvidedTypes(); + try { + foreach ($resolvingBag->getEnvPlaceholders() + $resolvingBag->getUnusedEnvPlaceholders() as $env => $placeholders) { + $values = []; + if (false === $i = strpos($env, ':')) { + $default = $defaultBag->has("env($env)") ? $defaultBag->get("env($env)") : self::$typeFixtures['string']; + $defaultType = null !== $default ? self::getType($default) : 'string'; + $values[$defaultType] = $default; + } else { + $prefix = substr($env, 0, $i); + foreach ($envTypes[$prefix] ?? ['string'] as $type) { + $values[$type] = self::$typeFixtures[$type] ?? null; + } + } + foreach ($placeholders as $placeholder) { + BaseNode::setPlaceholder($placeholder, $values); + } + } + + $processor = new Processor(); + + foreach ($extensions as $name => $extension) { + if (!$extension instanceof ConfigurationExtensionInterface || !$config = array_filter($container->getExtensionConfig($name))) { + // this extension has no semantic configuration or was not called + continue; + } + + $config = $resolvingBag->resolveValue($config); + + if (null === $configuration = $extension->getConfiguration($config, $container)) { + continue; + } + + $this->extensionConfig[$name] = $processor->processConfiguration($configuration, $config); + } + } finally { + BaseNode::resetPlaceholders(); + } + + $resolvingBag->clearUnusedEnvPlaceholders(); + } + + /** + * @internal + */ + public function getExtensionConfig(): array + { + try { + return $this->extensionConfig; + } finally { + $this->extensionConfig = []; + } + } + + private static function getType($value): string + { + switch ($type = \gettype($value)) { + case 'boolean': + return 'bool'; + case 'double': + return 'float'; + case 'integer': + return 'int'; + } + + return $type; + } +} diff --git a/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php b/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php new file mode 100644 index 0000000..8ffb8dc --- /dev/null +++ b/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Config; + +use Symfony\Component\Config\Resource\ResourceInterface; + +/** + * Tracks container parameters. + * + * @author Maxime Steinhausser + * + * @final + */ +class ContainerParametersResource implements ResourceInterface +{ + private $parameters; + + /** + * @param array $parameters The container parameters to track + */ + public function __construct(array $parameters) + { + $this->parameters = $parameters; + } + + /** + * {@inheritdoc} + */ + public function __toString(): string + { + return 'container_parameters_'.md5(serialize($this->parameters)); + } + + /** + * @return array Tracked parameters + */ + public function getParameters(): array + { + return $this->parameters; + } +} diff --git a/vendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php b/vendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php new file mode 100644 index 0000000..2f2affa --- /dev/null +++ b/vendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Config; + +use Symfony\Component\Config\Resource\ResourceInterface; +use Symfony\Component\Config\ResourceCheckerInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * @author Maxime Steinhausser + */ +class ContainerParametersResourceChecker implements ResourceCheckerInterface +{ + /** @var ContainerInterface */ + private $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public function supports(ResourceInterface $metadata) + { + return $metadata instanceof ContainerParametersResource; + } + + /** + * {@inheritdoc} + */ + public function isFresh(ResourceInterface $resource, int $timestamp) + { + foreach ($resource->getParameters() as $key => $value) { + if (!$this->container->hasParameter($key) || $this->container->getParameter($key) !== $value) { + return false; + } + } + + return true; + } +} diff --git a/vendor/symfony/dependency-injection/Container.php b/vendor/symfony/dependency-injection/Container.php new file mode 100644 index 0000000..53bebdf --- /dev/null +++ b/vendor/symfony/dependency-injection/Container.php @@ -0,0 +1,447 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; +use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; +use Symfony\Contracts\Service\ResetInterface; + +/** + * Container is a dependency injection container. + * + * It gives access to object instances (services). + * Services and parameters are simple key/pair stores. + * The container can have four possible behaviors when a service + * does not exist (or is not initialized for the last case): + * + * * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default) + * * NULL_ON_INVALID_REFERENCE: Returns null + * * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference + * (for instance, ignore a setter if the service does not exist) + * * IGNORE_ON_UNINITIALIZED_REFERENCE: Ignores/returns null for uninitialized services or invalid references + * + * @author Fabien Potencier + * @author Johannes M. Schmitt + */ +class Container implements ContainerInterface, ResetInterface +{ + protected $parameterBag; + protected $services = []; + protected $privates = []; + protected $fileMap = []; + protected $methodMap = []; + protected $factories = []; + protected $aliases = []; + protected $loading = []; + protected $resolving = []; + protected $syntheticIds = []; + + private $envCache = []; + private $compiled = false; + private $getEnv; + + public function __construct(ParameterBagInterface $parameterBag = null) + { + $this->parameterBag = $parameterBag ?: new EnvPlaceholderParameterBag(); + } + + /** + * Compiles the container. + * + * This method does two things: + * + * * Parameter values are resolved; + * * The parameter bag is frozen. + */ + public function compile() + { + $this->parameterBag->resolve(); + + $this->parameterBag = new FrozenParameterBag($this->parameterBag->all()); + + $this->compiled = true; + } + + /** + * Returns true if the container is compiled. + * + * @return bool + */ + public function isCompiled() + { + return $this->compiled; + } + + /** + * Gets the service container parameter bag. + * + * @return ParameterBagInterface A ParameterBagInterface instance + */ + public function getParameterBag() + { + return $this->parameterBag; + } + + /** + * Gets a parameter. + * + * @param string $name The parameter name + * + * @return mixed The parameter value + * + * @throws InvalidArgumentException if the parameter is not defined + */ + public function getParameter(string $name) + { + return $this->parameterBag->get($name); + } + + /** + * Checks if a parameter exists. + * + * @param string $name The parameter name + * + * @return bool The presence of parameter in container + */ + public function hasParameter(string $name) + { + return $this->parameterBag->has($name); + } + + /** + * Sets a parameter. + * + * @param string $name The parameter name + * @param mixed $value The parameter value + */ + public function setParameter(string $name, $value) + { + $this->parameterBag->set($name, $value); + } + + /** + * Sets a service. + * + * Setting a synthetic service to null resets it: has() returns false and get() + * behaves in the same way as if the service was never created. + */ + public function set(string $id, ?object $service) + { + // Runs the internal initializer; used by the dumped container to include always-needed files + if (isset($this->privates['service_container']) && $this->privates['service_container'] instanceof \Closure) { + $initialize = $this->privates['service_container']; + unset($this->privates['service_container']); + $initialize(); + } + + if ('service_container' === $id) { + throw new InvalidArgumentException('You cannot set service "service_container".'); + } + + if (!(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) { + if (isset($this->syntheticIds[$id]) || !isset($this->getRemovedIds()[$id])) { + // no-op + } elseif (null === $service) { + throw new InvalidArgumentException(sprintf('The "%s" service is private, you cannot unset it.', $id)); + } else { + throw new InvalidArgumentException(sprintf('The "%s" service is private, you cannot replace it.', $id)); + } + } elseif (isset($this->services[$id])) { + throw new InvalidArgumentException(sprintf('The "%s" service is already initialized, you cannot replace it.', $id)); + } + + if (isset($this->aliases[$id])) { + unset($this->aliases[$id]); + } + + if (null === $service) { + unset($this->services[$id]); + + return; + } + + $this->services[$id] = $service; + } + + /** + * Returns true if the given service is defined. + * + * @param string $id The service identifier + * + * @return bool true if the service is defined, false otherwise + */ + public function has($id) + { + if (isset($this->aliases[$id])) { + $id = $this->aliases[$id]; + } + if (isset($this->services[$id])) { + return true; + } + if ('service_container' === $id) { + return true; + } + + return isset($this->fileMap[$id]) || isset($this->methodMap[$id]); + } + + /** + * Gets a service. + * + * @param string $id The service identifier + * @param int $invalidBehavior The behavior when the service does not exist + * + * @return object|null The associated service + * + * @throws ServiceCircularReferenceException When a circular reference is detected + * @throws ServiceNotFoundException When the service is not defined + * @throws \Exception if an exception has been thrown when the service has been resolved + * + * @see Reference + */ + public function get($id, int $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERENCE */ 1) + { + return $this->services[$id] + ?? $this->services[$id = $this->aliases[$id] ?? $id] + ?? ('service_container' === $id ? $this : ($this->factories[$id] ?? [$this, 'make'])($id, $invalidBehavior)); + } + + /** + * Creates a service. + * + * As a separate method to allow "get()" to use the really fast `??` operator. + */ + private function make(string $id, int $invalidBehavior) + { + if (isset($this->loading[$id])) { + throw new ServiceCircularReferenceException($id, array_merge(array_keys($this->loading), [$id])); + } + + $this->loading[$id] = true; + + try { + if (isset($this->fileMap[$id])) { + return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->load($this->fileMap[$id]); + } elseif (isset($this->methodMap[$id])) { + return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->{$this->methodMap[$id]}(); + } + } catch (\Exception $e) { + unset($this->services[$id]); + + throw $e; + } finally { + unset($this->loading[$id]); + } + + if (/* self::EXCEPTION_ON_INVALID_REFERENCE */ 1 === $invalidBehavior) { + if (!$id) { + throw new ServiceNotFoundException($id); + } + if (isset($this->syntheticIds[$id])) { + throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service is synthetic, it needs to be set at boot time before it can be used.', $id)); + } + if (isset($this->getRemovedIds()[$id])) { + throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.', $id)); + } + + $alternatives = []; + foreach ($this->getServiceIds() as $knownId) { + if ('' === $knownId || '.' === $knownId[0]) { + continue; + } + $lev = levenshtein($id, $knownId); + if ($lev <= \strlen($id) / 3 || false !== strpos($knownId, $id)) { + $alternatives[] = $knownId; + } + } + + throw new ServiceNotFoundException($id, null, null, $alternatives); + } + + return null; + } + + /** + * Returns true if the given service has actually been initialized. + * + * @param string $id The service identifier + * + * @return bool true if service has already been initialized, false otherwise + */ + public function initialized(string $id) + { + if (isset($this->aliases[$id])) { + $id = $this->aliases[$id]; + } + + if ('service_container' === $id) { + return false; + } + + return isset($this->services[$id]); + } + + /** + * {@inheritdoc} + */ + public function reset() + { + $services = $this->services + $this->privates; + $this->services = $this->factories = $this->privates = []; + + foreach ($services as $service) { + try { + if ($service instanceof ResetInterface) { + $service->reset(); + } + } catch (\Throwable $e) { + continue; + } + } + } + + /** + * Gets all service ids. + * + * @return string[] An array of all defined service ids + */ + public function getServiceIds() + { + return array_map('strval', array_unique(array_merge(['service_container'], array_keys($this->fileMap), array_keys($this->methodMap), array_keys($this->aliases), array_keys($this->services)))); + } + + /** + * Gets service ids that existed at compile time. + * + * @return array + */ + public function getRemovedIds() + { + return []; + } + + /** + * Camelizes a string. + * + * @param string $id A string to camelize + * + * @return string The camelized string + */ + public static function camelize($id) + { + return strtr(ucwords(strtr($id, ['_' => ' ', '.' => '_ ', '\\' => '_ '])), [' ' => '']); + } + + /** + * A string to underscore. + * + * @param string $id The string to underscore + * + * @return string The underscored string + */ + public static function underscore($id) + { + return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], str_replace('_', '.', $id))); + } + + /** + * Creates a service by requiring its factory file. + */ + protected function load($file) + { + return require $file; + } + + /** + * Fetches a variable from the environment. + * + * @param string $name The name of the environment variable + * + * @return mixed The value to use for the provided environment variable name + * + * @throws EnvNotFoundException When the environment variable is not found and has no default value + */ + protected function getEnv($name) + { + if (isset($this->resolving[$envName = "env($name)"])) { + throw new ParameterCircularReferenceException(array_keys($this->resolving)); + } + if (isset($this->envCache[$name]) || \array_key_exists($name, $this->envCache)) { + return $this->envCache[$name]; + } + if (!$this->has($id = 'container.env_var_processors_locator')) { + $this->set($id, new ServiceLocator([])); + } + if (!$this->getEnv) { + $this->getEnv = new \ReflectionMethod($this, __FUNCTION__); + $this->getEnv->setAccessible(true); + $this->getEnv = $this->getEnv->getClosure($this); + } + $processors = $this->get($id); + + if (false !== $i = strpos($name, ':')) { + $prefix = substr($name, 0, $i); + $localName = substr($name, 1 + $i); + } else { + $prefix = 'string'; + $localName = $name; + } + $processor = $processors->has($prefix) ? $processors->get($prefix) : new EnvVarProcessor($this); + + $this->resolving[$envName] = true; + try { + return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv); + } finally { + unset($this->resolving[$envName]); + } + } + + /** + * @param string|false $registry + * @param string|bool $load + * + * @return mixed + * + * @internal + */ + final protected function getService($registry, string $id, ?string $method, $load) + { + if ('service_container' === $id) { + return $this; + } + if (\is_string($load)) { + throw new RuntimeException($load); + } + if (null === $method) { + return false !== $registry ? $this->{$registry}[$id] ?? null : null; + } + if (false !== $registry) { + return $this->{$registry}[$id] ?? $this->{$registry}[$id] = $load ? $this->load($method) : $this->{$method}(); + } + if (!$load) { + return $this->{$method}(); + } + + return ($factory = $this->factories[$id] ?? $this->factories['service_container'][$id] ?? null) ? $factory() : $this->load($method); + } + + private function __clone() + { + } +} diff --git a/vendor/symfony/dependency-injection/ContainerAwareInterface.php b/vendor/symfony/dependency-injection/ContainerAwareInterface.php new file mode 100644 index 0000000..e7b9d57 --- /dev/null +++ b/vendor/symfony/dependency-injection/ContainerAwareInterface.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +/** + * ContainerAwareInterface should be implemented by classes that depends on a Container. + * + * @author Fabien Potencier + */ +interface ContainerAwareInterface +{ + /** + * Sets the container. + */ + public function setContainer(ContainerInterface $container = null); +} diff --git a/vendor/symfony/dependency-injection/ContainerAwareTrait.php b/vendor/symfony/dependency-injection/ContainerAwareTrait.php new file mode 100644 index 0000000..ee1ea2c --- /dev/null +++ b/vendor/symfony/dependency-injection/ContainerAwareTrait.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +/** + * ContainerAware trait. + * + * @author Fabien Potencier + */ +trait ContainerAwareTrait +{ + /** + * @var ContainerInterface + */ + protected $container; + + public function setContainer(ContainerInterface $container = null) + { + $this->container = $container; + } +} diff --git a/vendor/symfony/dependency-injection/ContainerBuilder.php b/vendor/symfony/dependency-injection/ContainerBuilder.php new file mode 100644 index 0000000..414dad6 --- /dev/null +++ b/vendor/symfony/dependency-injection/ContainerBuilder.php @@ -0,0 +1,1611 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +use Psr\Container\ContainerInterface as PsrContainerInterface; +use Symfony\Component\Config\Resource\ClassExistenceResource; +use Symfony\Component\Config\Resource\ComposerResource; +use Symfony\Component\Config\Resource\DirectoryResource; +use Symfony\Component\Config\Resource\FileExistenceResource; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Config\Resource\GlobResource; +use Symfony\Component\Config\Resource\ReflectionClassResource; +use Symfony\Component\Config\Resource\ResourceInterface; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceLocator; +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; +use Symfony\Component\DependencyInjection\Compiler\Compiler; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\PassConfig; +use Symfony\Component\DependencyInjection\Compiler\ResolveEnvPlaceholdersPass; +use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\LogicException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; +use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; +use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator; +use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; +use Symfony\Component\ExpressionLanguage\Expression; +use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; + +/** + * ContainerBuilder is a DI container that provides an API to easily describe services. + * + * @author Fabien Potencier + */ +class ContainerBuilder extends Container implements TaggedContainerInterface +{ + /** + * @var ExtensionInterface[] + */ + private $extensions = []; + + /** + * @var ExtensionInterface[] + */ + private $extensionsByNs = []; + + /** + * @var Definition[] + */ + private $definitions = []; + + /** + * @var Alias[] + */ + private $aliasDefinitions = []; + + /** + * @var ResourceInterface[] + */ + private $resources = []; + + private $extensionConfigs = []; + + /** + * @var Compiler + */ + private $compiler; + + private $trackResources; + + /** + * @var InstantiatorInterface|null + */ + private $proxyInstantiator; + + /** + * @var ExpressionLanguage|null + */ + private $expressionLanguage; + + /** + * @var ExpressionFunctionProviderInterface[] + */ + private $expressionLanguageProviders = []; + + /** + * @var string[] with tag names used by findTaggedServiceIds + */ + private $usedTags = []; + + /** + * @var string[][] a map of env var names to their placeholders + */ + private $envPlaceholders = []; + + /** + * @var int[] a map of env vars to their resolution counter + */ + private $envCounters = []; + + /** + * @var string[] the list of vendor directories + */ + private $vendors; + + private $autoconfiguredInstanceof = []; + + private $removedIds = []; + + private $removedBindingIds = []; + + private static $internalTypes = [ + 'int' => true, + 'float' => true, + 'string' => true, + 'bool' => true, + 'resource' => true, + 'object' => true, + 'array' => true, + 'null' => true, + 'callable' => true, + 'iterable' => true, + 'mixed' => true, + ]; + + public function __construct(ParameterBagInterface $parameterBag = null) + { + parent::__construct($parameterBag); + + $this->trackResources = interface_exists('Symfony\Component\Config\Resource\ResourceInterface'); + $this->setDefinition('service_container', (new Definition(ContainerInterface::class))->setSynthetic(true)->setPublic(true)); + $this->setAlias(PsrContainerInterface::class, new Alias('service_container', false)); + $this->setAlias(ContainerInterface::class, new Alias('service_container', false)); + } + + /** + * @var \ReflectionClass[] a list of class reflectors + */ + private $classReflectors; + + /** + * Sets the track resources flag. + * + * If you are not using the loaders and therefore don't want + * to depend on the Config component, set this flag to false. + */ + public function setResourceTracking(bool $track) + { + $this->trackResources = $track; + } + + /** + * Checks if resources are tracked. + * + * @return bool true If resources are tracked, false otherwise + */ + public function isTrackingResources() + { + return $this->trackResources; + } + + /** + * Sets the instantiator to be used when fetching proxies. + */ + public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator) + { + $this->proxyInstantiator = $proxyInstantiator; + } + + public function registerExtension(ExtensionInterface $extension) + { + $this->extensions[$extension->getAlias()] = $extension; + + if (false !== $extension->getNamespace()) { + $this->extensionsByNs[$extension->getNamespace()] = $extension; + } + } + + /** + * Returns an extension by alias or namespace. + * + * @return ExtensionInterface An extension instance + * + * @throws LogicException if the extension is not registered + */ + public function getExtension(string $name) + { + if (isset($this->extensions[$name])) { + return $this->extensions[$name]; + } + + if (isset($this->extensionsByNs[$name])) { + return $this->extensionsByNs[$name]; + } + + throw new LogicException(sprintf('Container extension "%s" is not registered', $name)); + } + + /** + * Returns all registered extensions. + * + * @return ExtensionInterface[] An array of ExtensionInterface + */ + public function getExtensions() + { + return $this->extensions; + } + + /** + * Checks if we have an extension. + * + * @return bool If the extension exists + */ + public function hasExtension(string $name) + { + return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]); + } + + /** + * Returns an array of resources loaded to build this configuration. + * + * @return ResourceInterface[] An array of resources + */ + public function getResources() + { + return array_values($this->resources); + } + + /** + * @return $this + */ + public function addResource(ResourceInterface $resource) + { + if (!$this->trackResources) { + return $this; + } + + if ($resource instanceof GlobResource && $this->inVendors($resource->getPrefix())) { + return $this; + } + + $this->resources[(string) $resource] = $resource; + + return $this; + } + + /** + * Sets the resources for this configuration. + * + * @param ResourceInterface[] $resources An array of resources + * + * @return $this + */ + public function setResources(array $resources) + { + if (!$this->trackResources) { + return $this; + } + + $this->resources = $resources; + + return $this; + } + + /** + * Adds the object class hierarchy as resources. + * + * @param object|string $object An object instance or class name + * + * @return $this + */ + public function addObjectResource($object) + { + if ($this->trackResources) { + if (\is_object($object)) { + $object = \get_class($object); + } + if (!isset($this->classReflectors[$object])) { + $this->classReflectors[$object] = new \ReflectionClass($object); + } + $class = $this->classReflectors[$object]; + + foreach ($class->getInterfaceNames() as $name) { + if (null === $interface = &$this->classReflectors[$name]) { + $interface = new \ReflectionClass($name); + } + $file = $interface->getFileName(); + if (false !== $file && file_exists($file)) { + $this->fileExists($file); + } + } + do { + $file = $class->getFileName(); + if (false !== $file && file_exists($file)) { + $this->fileExists($file); + } + foreach ($class->getTraitNames() as $name) { + $this->addObjectResource($name); + } + } while ($class = $class->getParentClass()); + } + + return $this; + } + + /** + * Retrieves the requested reflection class and registers it for resource tracking. + * + * @throws \ReflectionException when a parent class/interface/trait is not found and $throw is true + * + * @final + */ + public function getReflectionClass(?string $class, bool $throw = true): ?\ReflectionClass + { + if (!$class = $this->getParameterBag()->resolveValue($class)) { + return null; + } + + if (isset(self::$internalTypes[$class])) { + return null; + } + + $resource = $classReflector = null; + + try { + if (isset($this->classReflectors[$class])) { + $classReflector = $this->classReflectors[$class]; + } elseif (class_exists(ClassExistenceResource::class)) { + $resource = new ClassExistenceResource($class, false); + $classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class); + } else { + $classReflector = class_exists($class) ? new \ReflectionClass($class) : false; + } + } catch (\ReflectionException $e) { + if ($throw) { + throw $e; + } + } + + if ($this->trackResources) { + if (!$classReflector) { + $this->addResource($resource ?: new ClassExistenceResource($class, false)); + } elseif (!$classReflector->isInternal()) { + $path = $classReflector->getFileName(); + + if (!$this->inVendors($path)) { + $this->addResource(new ReflectionClassResource($classReflector, $this->vendors)); + } + } + $this->classReflectors[$class] = $classReflector; + } + + return $classReflector ?: null; + } + + /** + * Checks whether the requested file or directory exists and registers the result for resource tracking. + * + * @param string $path The file or directory path for which to check the existence + * @param bool|string $trackContents Whether to track contents of the given resource. If a string is passed, + * it will be used as pattern for tracking contents of the requested directory + * + * @final + */ + public function fileExists(string $path, $trackContents = true): bool + { + $exists = file_exists($path); + + if (!$this->trackResources || $this->inVendors($path)) { + return $exists; + } + + if (!$exists) { + $this->addResource(new FileExistenceResource($path)); + + return $exists; + } + + if (is_dir($path)) { + if ($trackContents) { + $this->addResource(new DirectoryResource($path, \is_string($trackContents) ? $trackContents : null)); + } else { + $this->addResource(new GlobResource($path, '/*', false)); + } + } elseif ($trackContents) { + $this->addResource(new FileResource($path)); + } + + return $exists; + } + + /** + * Loads the configuration for an extension. + * + * @param string $extension The extension alias or namespace + * @param array $values An array of values that customizes the extension + * + * @return $this + * + * @throws BadMethodCallException When this ContainerBuilder is compiled + * @throws \LogicException if the extension is not registered + */ + public function loadFromExtension(string $extension, array $values = null) + { + if ($this->isCompiled()) { + throw new BadMethodCallException('Cannot load from an extension on a compiled container.'); + } + + if (\func_num_args() < 2) { + $values = []; + } + + $namespace = $this->getExtension($extension)->getAlias(); + + $this->extensionConfigs[$namespace][] = $values; + + return $this; + } + + /** + * Adds a compiler pass. + * + * @param string $type The type of compiler pass + * @param int $priority Used to sort the passes + * + * @return $this + */ + public function addCompilerPass(CompilerPassInterface $pass, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) + { + $this->getCompiler()->addPass($pass, $type, $priority); + + $this->addObjectResource($pass); + + return $this; + } + + /** + * Returns the compiler pass config which can then be modified. + * + * @return PassConfig The compiler pass config + */ + public function getCompilerPassConfig() + { + return $this->getCompiler()->getPassConfig(); + } + + /** + * Returns the compiler. + * + * @return Compiler The compiler + */ + public function getCompiler() + { + if (null === $this->compiler) { + $this->compiler = new Compiler(); + } + + return $this->compiler; + } + + /** + * Sets a service. + * + * @throws BadMethodCallException When this ContainerBuilder is compiled + */ + public function set(string $id, ?object $service) + { + if ($this->isCompiled() && (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())) { + // setting a synthetic service on a compiled container is alright + throw new BadMethodCallException(sprintf('Setting service "%s" for an unknown or non-synthetic service definition on a compiled container is not allowed.', $id)); + } + + unset($this->definitions[$id], $this->aliasDefinitions[$id], $this->removedIds[$id]); + + parent::set($id, $service); + } + + /** + * Removes a service definition. + */ + public function removeDefinition(string $id) + { + if (isset($this->definitions[$id])) { + unset($this->definitions[$id]); + $this->removedIds[$id] = true; + } + } + + /** + * Returns true if the given service is defined. + * + * @param string $id The service identifier + * + * @return bool true if the service is defined, false otherwise + */ + public function has($id) + { + $id = (string) $id; + + return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id); + } + + /** + * Gets a service. + * + * @param string $id The service identifier + * @param int $invalidBehavior The behavior when the service does not exist + * + * @return object|null The associated service + * + * @throws InvalidArgumentException when no definitions are available + * @throws ServiceCircularReferenceException When a circular reference is detected + * @throws ServiceNotFoundException When the service is not defined + * @throws \Exception + * + * @see Reference + */ + public function get($id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) + { + if ($this->isCompiled() && isset($this->removedIds[$id = (string) $id]) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $invalidBehavior) { + return parent::get($id); + } + + return $this->doGet($id, $invalidBehavior); + } + + private function doGet(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, array &$inlineServices = null, bool $isConstructorArgument = false) + { + if (isset($inlineServices[$id])) { + return $inlineServices[$id]; + } + if (null === $inlineServices) { + $isConstructorArgument = true; + $inlineServices = []; + } + try { + if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior) { + return parent::get($id, $invalidBehavior); + } + if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) { + return $service; + } + } catch (ServiceCircularReferenceException $e) { + if ($isConstructorArgument) { + throw $e; + } + } + + if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) { + $alias = $this->aliasDefinitions[$id]; + + if ($alias->isDeprecated()) { + @trigger_error($alias->getDeprecationMessage($id), E_USER_DEPRECATED); + } + + return $this->doGet((string) $alias, $invalidBehavior, $inlineServices, $isConstructorArgument); + } + + try { + $definition = $this->getDefinition($id); + } catch (ServiceNotFoundException $e) { + if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $invalidBehavior) { + return null; + } + + throw $e; + } + + if ($definition->hasErrors() && $e = $definition->getErrors()) { + throw new RuntimeException(reset($e)); + } + + if ($isConstructorArgument) { + $this->loading[$id] = true; + } + + try { + return $this->createService($definition, $inlineServices, $isConstructorArgument, $id); + } finally { + if ($isConstructorArgument) { + unset($this->loading[$id]); + } + } + } + + /** + * Merges a ContainerBuilder with the current ContainerBuilder configuration. + * + * Service definitions overrides the current defined ones. + * + * But for parameters, they are overridden by the current ones. It allows + * the parameters passed to the container constructor to have precedence + * over the loaded ones. + * + * $container = new ContainerBuilder(new ParameterBag(['foo' => 'bar'])); + * $loader = new LoaderXXX($container); + * $loader->load('resource_name'); + * $container->register('foo', 'stdClass'); + * + * In the above example, even if the loaded resource defines a foo + * parameter, the value will still be 'bar' as defined in the ContainerBuilder + * constructor. + * + * @throws BadMethodCallException When this ContainerBuilder is compiled + */ + public function merge(self $container) + { + if ($this->isCompiled()) { + throw new BadMethodCallException('Cannot merge on a compiled container.'); + } + + $this->addDefinitions($container->getDefinitions()); + $this->addAliases($container->getAliases()); + $this->getParameterBag()->add($container->getParameterBag()->all()); + + if ($this->trackResources) { + foreach ($container->getResources() as $resource) { + $this->addResource($resource); + } + } + + foreach ($this->extensions as $name => $extension) { + if (!isset($this->extensionConfigs[$name])) { + $this->extensionConfigs[$name] = []; + } + + $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name)); + } + + if ($this->getParameterBag() instanceof EnvPlaceholderParameterBag && $container->getParameterBag() instanceof EnvPlaceholderParameterBag) { + $envPlaceholders = $container->getParameterBag()->getEnvPlaceholders(); + $this->getParameterBag()->mergeEnvPlaceholders($container->getParameterBag()); + } else { + $envPlaceholders = []; + } + + foreach ($container->envCounters as $env => $count) { + if (!$count && !isset($envPlaceholders[$env])) { + continue; + } + if (!isset($this->envCounters[$env])) { + $this->envCounters[$env] = $count; + } else { + $this->envCounters[$env] += $count; + } + } + + foreach ($container->getAutoconfiguredInstanceof() as $interface => $childDefinition) { + if (isset($this->autoconfiguredInstanceof[$interface])) { + throw new InvalidArgumentException(sprintf('"%s" has already been autoconfigured and merge() does not support merging autoconfiguration for the same class/interface.', $interface)); + } + + $this->autoconfiguredInstanceof[$interface] = $childDefinition; + } + } + + /** + * Returns the configuration array for the given extension. + * + * @return array An array of configuration + */ + public function getExtensionConfig(string $name) + { + if (!isset($this->extensionConfigs[$name])) { + $this->extensionConfigs[$name] = []; + } + + return $this->extensionConfigs[$name]; + } + + /** + * Prepends a config array to the configs of the given extension. + */ + public function prependExtensionConfig(string $name, array $config) + { + if (!isset($this->extensionConfigs[$name])) { + $this->extensionConfigs[$name] = []; + } + + array_unshift($this->extensionConfigs[$name], $config); + } + + /** + * Compiles the container. + * + * This method passes the container to compiler + * passes whose job is to manipulate and optimize + * the container. + * + * The main compiler passes roughly do four things: + * + * * The extension configurations are merged; + * * Parameter values are resolved; + * * The parameter bag is frozen; + * * Extension loading is disabled. + * + * @param bool $resolveEnvPlaceholders Whether %env()% parameters should be resolved using the current + * env vars or be replaced by uniquely identifiable placeholders. + * Set to "true" when you want to use the current ContainerBuilder + * directly, keep to "false" when the container is dumped instead. + */ + public function compile(bool $resolveEnvPlaceholders = false) + { + $compiler = $this->getCompiler(); + + if ($this->trackResources) { + foreach ($compiler->getPassConfig()->getPasses() as $pass) { + $this->addObjectResource($pass); + } + } + $bag = $this->getParameterBag(); + + if ($resolveEnvPlaceholders && $bag instanceof EnvPlaceholderParameterBag) { + $compiler->addPass(new ResolveEnvPlaceholdersPass(), PassConfig::TYPE_AFTER_REMOVING, -1000); + } + + $compiler->compile($this); + + foreach ($this->definitions as $id => $definition) { + if ($this->trackResources && $definition->isLazy()) { + $this->getReflectionClass($definition->getClass()); + } + } + + $this->extensionConfigs = []; + + if ($bag instanceof EnvPlaceholderParameterBag) { + if ($resolveEnvPlaceholders) { + $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true)); + } + + $this->envPlaceholders = $bag->getEnvPlaceholders(); + } + + parent::compile(); + + foreach ($this->definitions + $this->aliasDefinitions as $id => $definition) { + if (!$definition->isPublic() || $definition->isPrivate()) { + $this->removedIds[$id] = true; + } + } + } + + /** + * {@inheritdoc} + */ + public function getServiceIds() + { + return array_map('strval', array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds()))); + } + + /** + * Gets removed service or alias ids. + * + * @return array + */ + public function getRemovedIds() + { + return $this->removedIds; + } + + /** + * Adds the service aliases. + */ + public function addAliases(array $aliases) + { + foreach ($aliases as $alias => $id) { + $this->setAlias($alias, $id); + } + } + + /** + * Sets the service aliases. + */ + public function setAliases(array $aliases) + { + $this->aliasDefinitions = []; + $this->addAliases($aliases); + } + + /** + * Sets an alias for an existing service. + * + * @param string $alias The alias to create + * @param string|Alias $id The service to alias + * + * @return Alias + * + * @throws InvalidArgumentException if the id is not a string or an Alias + * @throws InvalidArgumentException if the alias is for itself + */ + public function setAlias(string $alias, $id) + { + if ('' === $alias || '\\' === $alias[-1] || \strlen($alias) !== strcspn($alias, "\0\r\n'")) { + throw new InvalidArgumentException(sprintf('Invalid alias id: "%s"', $alias)); + } + + if (\is_string($id)) { + $id = new Alias($id); + } elseif (!$id instanceof Alias) { + throw new InvalidArgumentException('$id must be a string, or an Alias object.'); + } + + if ($alias === (string) $id) { + throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias)); + } + + unset($this->definitions[$alias], $this->removedIds[$alias]); + + return $this->aliasDefinitions[$alias] = $id; + } + + /** + * Removes an alias. + * + * @param string $alias The alias to remove + */ + public function removeAlias(string $alias) + { + if (isset($this->aliasDefinitions[$alias])) { + unset($this->aliasDefinitions[$alias]); + $this->removedIds[$alias] = true; + } + } + + /** + * Returns true if an alias exists under the given identifier. + * + * @return bool true if the alias exists, false otherwise + */ + public function hasAlias(string $id) + { + return isset($this->aliasDefinitions[$id]); + } + + /** + * Gets all defined aliases. + * + * @return Alias[] An array of aliases + */ + public function getAliases() + { + return $this->aliasDefinitions; + } + + /** + * Gets an alias. + * + * @return Alias An Alias instance + * + * @throws InvalidArgumentException if the alias does not exist + */ + public function getAlias(string $id) + { + if (!isset($this->aliasDefinitions[$id])) { + throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id)); + } + + return $this->aliasDefinitions[$id]; + } + + /** + * Registers a service definition. + * + * This methods allows for simple registration of service definition + * with a fluid interface. + * + * @return Definition A Definition instance + */ + public function register(string $id, string $class = null) + { + return $this->setDefinition($id, new Definition($class)); + } + + /** + * Registers an autowired service definition. + * + * This method implements a shortcut for using setDefinition() with + * an autowired definition. + * + * @return Definition The created definition + */ + public function autowire(string $id, string $class = null) + { + return $this->setDefinition($id, (new Definition($class))->setAutowired(true)); + } + + /** + * Adds the service definitions. + * + * @param Definition[] $definitions An array of service definitions + */ + public function addDefinitions(array $definitions) + { + foreach ($definitions as $id => $definition) { + $this->setDefinition($id, $definition); + } + } + + /** + * Sets the service definitions. + * + * @param Definition[] $definitions An array of service definitions + */ + public function setDefinitions(array $definitions) + { + $this->definitions = []; + $this->addDefinitions($definitions); + } + + /** + * Gets all service definitions. + * + * @return Definition[] An array of Definition instances + */ + public function getDefinitions() + { + return $this->definitions; + } + + /** + * Sets a service definition. + * + * @return Definition the service definition + * + * @throws BadMethodCallException When this ContainerBuilder is compiled + */ + public function setDefinition(string $id, Definition $definition) + { + if ($this->isCompiled()) { + throw new BadMethodCallException('Adding definition to a compiled container is not allowed'); + } + + if ('' === $id || '\\' === $id[-1] || \strlen($id) !== strcspn($id, "\0\r\n'")) { + throw new InvalidArgumentException(sprintf('Invalid service id: "%s"', $id)); + } + + unset($this->aliasDefinitions[$id], $this->removedIds[$id]); + + return $this->definitions[$id] = $definition; + } + + /** + * Returns true if a service definition exists under the given identifier. + * + * @return bool true if the service definition exists, false otherwise + */ + public function hasDefinition(string $id) + { + return isset($this->definitions[$id]); + } + + /** + * Gets a service definition. + * + * @return Definition A Definition instance + * + * @throws ServiceNotFoundException if the service definition does not exist + */ + public function getDefinition(string $id) + { + if (!isset($this->definitions[$id])) { + throw new ServiceNotFoundException($id); + } + + return $this->definitions[$id]; + } + + /** + * Gets a service definition by id or alias. + * + * The method "unaliases" recursively to return a Definition instance. + * + * @return Definition A Definition instance + * + * @throws ServiceNotFoundException if the service definition does not exist + */ + public function findDefinition(string $id) + { + $seen = []; + while (isset($this->aliasDefinitions[$id])) { + $id = (string) $this->aliasDefinitions[$id]; + + if (isset($seen[$id])) { + $seen = array_values($seen); + $seen = \array_slice($seen, array_search($id, $seen)); + $seen[] = $id; + + throw new ServiceCircularReferenceException($id, $seen); + } + + $seen[$id] = $id; + } + + return $this->getDefinition($id); + } + + /** + * Creates a service for a service definition. + * + * @return mixed The service described by the service definition + * + * @throws RuntimeException When the factory definition is incomplete + * @throws RuntimeException When the service is a synthetic service + * @throws InvalidArgumentException When configure callable is not callable + */ + private function createService(Definition $definition, array &$inlineServices, bool $isConstructorArgument = false, string $id = null, bool $tryProxy = true) + { + if (null === $id && isset($inlineServices[$h = spl_object_hash($definition)])) { + return $inlineServices[$h]; + } + + if ($definition instanceof ChildDefinition) { + throw new RuntimeException(sprintf('Constructing service "%s" from a parent definition is not supported at build time.', $id)); + } + + if ($definition->isSynthetic()) { + throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id)); + } + + if ($definition->isDeprecated()) { + @trigger_error($definition->getDeprecationMessage($id), E_USER_DEPRECATED); + } + + if ($tryProxy && $definition->isLazy() && !$tryProxy = !($proxy = $this->proxyInstantiator) || $proxy instanceof RealServiceInstantiator) { + $proxy = $proxy->instantiateProxy( + $this, + $definition, + $id, function () use ($definition, &$inlineServices, $id) { + return $this->createService($definition, $inlineServices, true, $id, false); + } + ); + $this->shareService($definition, $proxy, $id, $inlineServices); + + return $proxy; + } + + $parameterBag = $this->getParameterBag(); + + if (null !== $definition->getFile()) { + require_once $parameterBag->resolveValue($definition->getFile()); + } + + $arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlineServices, $isConstructorArgument); + + if (null !== $factory = $definition->getFactory()) { + if (\is_array($factory)) { + $factory = [$this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlineServices, $isConstructorArgument), $factory[1]]; + } elseif (!\is_string($factory)) { + throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id)); + } + } + + if (null !== $id && $definition->isShared() && isset($this->services[$id]) && ($tryProxy || !$definition->isLazy())) { + return $this->services[$id]; + } + + if (null !== $factory) { + $service = $factory(...$arguments); + + if (!$definition->isDeprecated() && \is_array($factory) && \is_string($factory[0])) { + $r = new \ReflectionClass($factory[0]); + + if (0 < strpos($r->getDocComment(), "\n * @deprecated ")) { + @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" factory class. It should either be deprecated or its factory upgraded.', $id, $r->name), E_USER_DEPRECATED); + } + } + } else { + $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass())); + + $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); + + if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) { + @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name), E_USER_DEPRECATED); + } + } + + $lastWitherIndex = null; + foreach ($definition->getMethodCalls() as $k => $call) { + if ($call[2] ?? false) { + $lastWitherIndex = $k; + } + } + + if (null === $lastWitherIndex && ($tryProxy || !$definition->isLazy())) { + // share only if proxying failed, or if not a proxy, and if no withers are found + $this->shareService($definition, $service, $id, $inlineServices); + } + + $properties = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())), $inlineServices); + foreach ($properties as $name => $value) { + $service->$name = $value; + } + + foreach ($definition->getMethodCalls() as $k => $call) { + $service = $this->callMethod($service, $call, $inlineServices); + + if ($lastWitherIndex === $k && ($tryProxy || !$definition->isLazy())) { + // share only if proxying failed, or if not a proxy, and this is the last wither + $this->shareService($definition, $service, $id, $inlineServices); + } + } + + if ($callable = $definition->getConfigurator()) { + if (\is_array($callable)) { + $callable[0] = $parameterBag->resolveValue($callable[0]); + + if ($callable[0] instanceof Reference) { + $callable[0] = $this->doGet((string) $callable[0], $callable[0]->getInvalidBehavior(), $inlineServices); + } elseif ($callable[0] instanceof Definition) { + $callable[0] = $this->createService($callable[0], $inlineServices); + } + } + + if (!\is_callable($callable)) { + throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', \get_class($service))); + } + + $callable($service); + } + + return $service; + } + + /** + * Replaces service references by the real service instance and evaluates expressions. + * + * @param mixed $value A value + * + * @return mixed The same value with all service references replaced by + * the real service instances and all expressions evaluated + */ + public function resolveServices($value) + { + return $this->doResolveServices($value); + } + + private function doResolveServices($value, array &$inlineServices = [], bool $isConstructorArgument = false) + { + if (\is_array($value)) { + foreach ($value as $k => $v) { + $value[$k] = $this->doResolveServices($v, $inlineServices, $isConstructorArgument); + } + } elseif ($value instanceof ServiceClosureArgument) { + $reference = $value->getValues()[0]; + $value = function () use ($reference) { + return $this->resolveServices($reference); + }; + } elseif ($value instanceof IteratorArgument) { + $value = new RewindableGenerator(function () use ($value) { + foreach ($value->getValues() as $k => $v) { + foreach (self::getServiceConditionals($v) as $s) { + if (!$this->has($s)) { + continue 2; + } + } + foreach (self::getInitializedConditionals($v) as $s) { + if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { + continue 2; + } + } + + yield $k => $this->resolveServices($v); + } + }, function () use ($value): int { + $count = 0; + foreach ($value->getValues() as $v) { + foreach (self::getServiceConditionals($v) as $s) { + if (!$this->has($s)) { + continue 2; + } + } + foreach (self::getInitializedConditionals($v) as $s) { + if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { + continue 2; + } + } + + ++$count; + } + + return $count; + }); + } elseif ($value instanceof ServiceLocatorArgument) { + $refs = $types = []; + foreach ($value->getValues() as $k => $v) { + if ($v) { + $refs[$k] = [$v]; + $types[$k] = $v instanceof TypedReference ? $v->getType() : '?'; + } + } + $value = new ServiceLocator(\Closure::fromCallable([$this, 'resolveServices']), $refs, $types); + } elseif ($value instanceof Reference) { + $value = $this->doGet((string) $value, $value->getInvalidBehavior(), $inlineServices, $isConstructorArgument); + } elseif ($value instanceof Definition) { + $value = $this->createService($value, $inlineServices, $isConstructorArgument); + } elseif ($value instanceof Parameter) { + $value = $this->getParameter((string) $value); + } elseif ($value instanceof Expression) { + $value = $this->getExpressionLanguage()->evaluate($value, ['container' => $this]); + } + + return $value; + } + + /** + * Returns service ids for a given tag. + * + * Example: + * + * $container->register('foo')->addTag('my.tag', ['hello' => 'world']); + * + * $serviceIds = $container->findTaggedServiceIds('my.tag'); + * foreach ($serviceIds as $serviceId => $tags) { + * foreach ($tags as $tag) { + * echo $tag['hello']; + * } + * } + * + * @return array An array of tags with the tagged service as key, holding a list of attribute arrays + */ + public function findTaggedServiceIds(string $name, bool $throwOnAbstract = false) + { + $this->usedTags[] = $name; + $tags = []; + foreach ($this->getDefinitions() as $id => $definition) { + if ($definition->hasTag($name)) { + if ($throwOnAbstract && $definition->isAbstract()) { + throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must not be abstract.', $id, $name)); + } + $tags[$id] = $definition->getTag($name); + } + } + + return $tags; + } + + /** + * Returns all tags the defined services use. + * + * @return array An array of tags + */ + public function findTags() + { + $tags = []; + foreach ($this->getDefinitions() as $id => $definition) { + $tags = array_merge(array_keys($definition->getTags()), $tags); + } + + return array_unique($tags); + } + + /** + * Returns all tags not queried by findTaggedServiceIds. + * + * @return string[] An array of tags + */ + public function findUnusedTags() + { + return array_values(array_diff($this->findTags(), $this->usedTags)); + } + + public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) + { + $this->expressionLanguageProviders[] = $provider; + } + + /** + * @return ExpressionFunctionProviderInterface[] + */ + public function getExpressionLanguageProviders() + { + return $this->expressionLanguageProviders; + } + + /** + * Returns a ChildDefinition that will be used for autoconfiguring the interface/class. + * + * @return ChildDefinition + */ + public function registerForAutoconfiguration(string $interface) + { + if (!isset($this->autoconfiguredInstanceof[$interface])) { + $this->autoconfiguredInstanceof[$interface] = new ChildDefinition(''); + } + + return $this->autoconfiguredInstanceof[$interface]; + } + + /** + * Registers an autowiring alias that only binds to a specific argument name. + * + * The argument name is derived from $name if provided (from $id otherwise) + * using camel case: "foo.bar" or "foo_bar" creates an alias bound to + * "$fooBar"-named arguments with $type as type-hint. Such arguments will + * receive the service $id when autowiring is used. + */ + public function registerAliasForArgument(string $id, string $type, string $name = null): Alias + { + $name = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $name ?? $id)))); + + if (!preg_match('/^[a-zA-Z_\x7f-\xff]/', $name)) { + throw new InvalidArgumentException(sprintf('Invalid argument name "%s" for service "%s": the first character must be a letter.', $name, $id)); + } + + return $this->setAlias($type.' $'.$name, $id); + } + + /** + * Returns an array of ChildDefinition[] keyed by interface. + * + * @return ChildDefinition[] + */ + public function getAutoconfiguredInstanceof() + { + return $this->autoconfiguredInstanceof; + } + + /** + * Resolves env parameter placeholders in a string or an array. + * + * @param mixed $value The value to resolve + * @param string|true|null $format A sprintf() format returning the replacement for each env var name or + * null to resolve back to the original "%env(VAR)%" format or + * true to resolve to the actual values of the referenced env vars + * @param array &$usedEnvs Env vars found while resolving are added to this array + * + * @return mixed The value with env parameters resolved if a string or an array is passed + */ + public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs = null) + { + if (null === $format) { + $format = '%%env(%s)%%'; + } + + $bag = $this->getParameterBag(); + if (true === $format) { + $value = $bag->resolveValue($value); + } + + if ($value instanceof Definition) { + $value = (array) $value; + } + + if (\is_array($value)) { + $result = []; + foreach ($value as $k => $v) { + $result[\is_string($k) ? $this->resolveEnvPlaceholders($k, $format, $usedEnvs) : $k] = $this->resolveEnvPlaceholders($v, $format, $usedEnvs); + } + + return $result; + } + + if (!\is_string($value) || 38 > \strlen($value)) { + return $value; + } + $envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders; + + $completed = false; + foreach ($envPlaceholders as $env => $placeholders) { + foreach ($placeholders as $placeholder) { + if (false !== stripos($value, $placeholder)) { + if (true === $format) { + $resolved = $bag->escapeValue($this->getEnv($env)); + } else { + $resolved = sprintf($format, $env); + } + if ($placeholder === $value) { + $value = $resolved; + $completed = true; + } else { + if (!\is_string($resolved) && !is_numeric($resolved)) { + throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "env(%s)" of type %s inside string value "%s".', $env, \gettype($resolved), $this->resolveEnvPlaceholders($value))); + } + $value = str_ireplace($placeholder, $resolved, $value); + } + $usedEnvs[$env] = $env; + $this->envCounters[$env] = isset($this->envCounters[$env]) ? 1 + $this->envCounters[$env] : 1; + + if ($completed) { + break 2; + } + } + } + } + + return $value; + } + + /** + * Get statistics about env usage. + * + * @return int[] The number of time each env vars has been resolved + */ + public function getEnvCounters() + { + $bag = $this->getParameterBag(); + $envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders; + + foreach ($envPlaceholders as $env => $placeholders) { + if (!isset($this->envCounters[$env])) { + $this->envCounters[$env] = 0; + } + } + + return $this->envCounters; + } + + /** + * @final + */ + public function log(CompilerPassInterface $pass, string $message) + { + $this->getCompiler()->log($pass, $this->resolveEnvPlaceholders($message)); + } + + /** + * Gets removed binding ids. + * + * @internal + */ + public function getRemovedBindingIds(): array + { + return $this->removedBindingIds; + } + + /** + * Removes bindings for a service. + * + * @internal + */ + public function removeBindings(string $id) + { + if ($this->hasDefinition($id)) { + foreach ($this->getDefinition($id)->getBindings() as $key => $binding) { + list(, $bindingId) = $binding->getValues(); + $this->removedBindingIds[(int) $bindingId] = true; + } + } + } + + /** + * Returns the Service Conditionals. + * + * @param mixed $value An array of conditionals to return + * + * @internal + */ + public static function getServiceConditionals($value): array + { + $services = []; + + if (\is_array($value)) { + foreach ($value as $v) { + $services = array_unique(array_merge($services, self::getServiceConditionals($v))); + } + } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) { + $services[] = (string) $value; + } + + return $services; + } + + /** + * Returns the initialized conditionals. + * + * @param mixed $value An array of conditionals to return + * + * @internal + */ + public static function getInitializedConditionals($value): array + { + $services = []; + + if (\is_array($value)) { + foreach ($value as $v) { + $services = array_unique(array_merge($services, self::getInitializedConditionals($v))); + } + } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()) { + $services[] = (string) $value; + } + + return $services; + } + + /** + * Computes a reasonably unique hash of a value. + * + * @param mixed $value A serializable value + * + * @return string + */ + public static function hash($value) + { + $hash = substr(base64_encode(hash('sha256', serialize($value), true)), 0, 7); + + return str_replace(['/', '+'], ['.', '_'], $hash); + } + + /** + * {@inheritdoc} + */ + protected function getEnv($name) + { + $value = parent::getEnv($name); + $bag = $this->getParameterBag(); + + if (!\is_string($value) || !$bag instanceof EnvPlaceholderParameterBag) { + return $value; + } + + $envPlaceholders = $bag->getEnvPlaceholders(); + if (isset($envPlaceholders[$name][$value])) { + $bag = new ParameterBag($bag->all()); + + return $bag->unescapeValue($bag->get("env($name)")); + } + foreach ($envPlaceholders as $env => $placeholders) { + if (isset($placeholders[$value])) { + return $this->getEnv($env); + } + } + + $this->resolving["env($name)"] = true; + try { + return $bag->unescapeValue($this->resolveEnvPlaceholders($bag->escapeValue($value), true)); + } finally { + unset($this->resolving["env($name)"]); + } + } + + private function callMethod($service, array $call, array &$inlineServices) + { + foreach (self::getServiceConditionals($call[1]) as $s) { + if (!$this->has($s)) { + return $service; + } + } + foreach (self::getInitializedConditionals($call[1]) as $s) { + if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) { + return $service; + } + } + + $result = $service->{$call[0]}(...$this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlineServices)); + + return empty($call[2]) ? $service : $result; + } + + /** + * Shares a given service in the container. + * + * @param mixed $service + */ + private function shareService(Definition $definition, $service, ?string $id, array &$inlineServices) + { + $inlineServices[null !== $id ? $id : spl_object_hash($definition)] = $service; + + if (null !== $id && $definition->isShared()) { + $this->services[$id] = $service; + unset($this->loading[$id]); + } + } + + private function getExpressionLanguage(): ExpressionLanguage + { + if (null === $this->expressionLanguage) { + if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { + throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); + } + $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); + } + + return $this->expressionLanguage; + } + + private function inVendors(string $path): bool + { + if (null === $this->vendors) { + $resource = new ComposerResource(); + $this->vendors = $resource->getVendors(); + $this->addResource($resource); + } + $path = realpath($path) ?: $path; + + foreach ($this->vendors as $vendor) { + if (0 === strpos($path, $vendor) && false !== strpbrk(substr($path, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) { + return true; + } + } + + return false; + } +} diff --git a/vendor/symfony/dependency-injection/ContainerInterface.php b/vendor/symfony/dependency-injection/ContainerInterface.php new file mode 100644 index 0000000..616648f --- /dev/null +++ b/vendor/symfony/dependency-injection/ContainerInterface.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +use Psr\Container\ContainerInterface as PsrContainerInterface; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; + +/** + * ContainerInterface is the interface implemented by service container classes. + * + * @author Fabien Potencier + * @author Johannes M. Schmitt + */ +interface ContainerInterface extends PsrContainerInterface +{ + const RUNTIME_EXCEPTION_ON_INVALID_REFERENCE = 0; + const EXCEPTION_ON_INVALID_REFERENCE = 1; + const NULL_ON_INVALID_REFERENCE = 2; + const IGNORE_ON_INVALID_REFERENCE = 3; + const IGNORE_ON_UNINITIALIZED_REFERENCE = 4; + + /** + * Sets a service. + */ + public function set(string $id, ?object $service); + + /** + * Gets a service. + * + * @param string $id The service identifier + * @param int $invalidBehavior The behavior when the service does not exist + * + * @return object|null The associated service + * + * @throws ServiceCircularReferenceException When a circular reference is detected + * @throws ServiceNotFoundException When the service is not defined + * + * @see Reference + */ + public function get($id, int $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE); + + /** + * Returns true if the given service is defined. + * + * @param string $id The service identifier + * + * @return bool true if the service is defined, false otherwise + */ + public function has($id); + + /** + * Check for whether or not a service has been initialized. + * + * @return bool true if the service has been initialized, false otherwise + */ + public function initialized(string $id); + + /** + * Gets a parameter. + * + * @param string $name The parameter name + * + * @return mixed The parameter value + * + * @throws InvalidArgumentException if the parameter is not defined + */ + public function getParameter(string $name); + + /** + * Checks if a parameter exists. + * + * @param string $name The parameter name + * + * @return bool The presence of parameter in container + */ + public function hasParameter(string $name); + + /** + * Sets a parameter. + * + * @param string $name The parameter name + * @param mixed $value The parameter value + */ + public function setParameter(string $name, $value); +} diff --git a/vendor/symfony/dependency-injection/Definition.php b/vendor/symfony/dependency-injection/Definition.php new file mode 100644 index 0000000..83b7cd2 --- /dev/null +++ b/vendor/symfony/dependency-injection/Definition.php @@ -0,0 +1,890 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +use Symfony\Component\DependencyInjection\Argument\BoundArgument; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; + +/** + * Definition represents a service definition. + * + * @author Fabien Potencier + */ +class Definition +{ + private $class; + private $file; + private $factory; + private $shared = true; + private $deprecated = false; + private $deprecationTemplate; + private $properties = []; + private $calls = []; + private $instanceof = []; + private $autoconfigured = false; + private $configurator; + private $tags = []; + private $public = true; + private $private = true; + private $synthetic = false; + private $abstract = false; + private $lazy = false; + private $decoratedService; + private $autowired = false; + private $changes = []; + private $bindings = []; + private $errors = []; + + protected $arguments = []; + + private static $defaultDeprecationTemplate = 'The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.'; + + /** + * @internal + * + * Used to store the name of the inner id when using service decoration together with autowiring + */ + public $innerServiceId; + + /** + * @internal + * + * Used to store the behavior to follow when using service decoration and the decorated service is invalid + */ + public $decorationOnInvalid; + + public function __construct(string $class = null, array $arguments = []) + { + if (null !== $class) { + $this->setClass($class); + } + $this->arguments = $arguments; + } + + /** + * Returns all changes tracked for the Definition object. + * + * @return array An array of changes for this Definition + */ + public function getChanges() + { + return $this->changes; + } + + /** + * Sets the tracked changes for the Definition object. + * + * @param array $changes An array of changes for this Definition + * + * @return $this + */ + public function setChanges(array $changes) + { + $this->changes = $changes; + + return $this; + } + + /** + * Sets a factory. + * + * @param string|array|Reference $factory A PHP function, reference or an array containing a class/Reference and a method to call + * + * @return $this + */ + public function setFactory($factory) + { + $this->changes['factory'] = true; + + if (\is_string($factory) && false !== strpos($factory, '::')) { + $factory = explode('::', $factory, 2); + } elseif ($factory instanceof Reference) { + $factory = [$factory, '__invoke']; + } + + $this->factory = $factory; + + return $this; + } + + /** + * Gets the factory. + * + * @return string|array|null The PHP function or an array containing a class/Reference and a method to call + */ + public function getFactory() + { + return $this->factory; + } + + /** + * Sets the service that this service is decorating. + * + * @param string|null $id The decorated service id, use null to remove decoration + * @param string|null $renamedId The new decorated service id + * + * @return $this + * + * @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals + */ + public function setDecoratedService(?string $id, ?string $renamedId = null, int $priority = 0, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) + { + if ($renamedId && $id === $renamedId) { + throw new InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id)); + } + + $this->changes['decorated_service'] = true; + + if (null === $id) { + $this->decoratedService = null; + } else { + $this->decoratedService = [$id, $renamedId, (int) $priority]; + + if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { + $this->decoratedService[] = $invalidBehavior; + } + } + + return $this; + } + + /** + * Gets the service that this service is decorating. + * + * @return array|null An array composed of the decorated service id, the new id for it and the priority of decoration, null if no service is decorated + */ + public function getDecoratedService() + { + return $this->decoratedService; + } + + /** + * Sets the service class. + * + * @return $this + */ + public function setClass(?string $class) + { + $this->changes['class'] = true; + + $this->class = $class; + + return $this; + } + + /** + * Gets the service class. + * + * @return string|null The service class + */ + public function getClass() + { + return $this->class; + } + + /** + * Sets the arguments to pass to the service constructor/factory method. + * + * @return $this + */ + public function setArguments(array $arguments) + { + $this->arguments = $arguments; + + return $this; + } + + /** + * Sets the properties to define when creating the service. + * + * @return $this + */ + public function setProperties(array $properties) + { + $this->properties = $properties; + + return $this; + } + + /** + * Gets the properties to define when creating the service. + * + * @return array + */ + public function getProperties() + { + return $this->properties; + } + + /** + * Sets a specific property. + * + * @param mixed $value + * + * @return $this + */ + public function setProperty(string $name, $value) + { + $this->properties[$name] = $value; + + return $this; + } + + /** + * Adds an argument to pass to the service constructor/factory method. + * + * @param mixed $argument An argument + * + * @return $this + */ + public function addArgument($argument) + { + $this->arguments[] = $argument; + + return $this; + } + + /** + * Replaces a specific argument. + * + * @param int|string $index + * @param mixed $argument + * + * @return $this + * + * @throws OutOfBoundsException When the replaced argument does not exist + */ + public function replaceArgument($index, $argument) + { + if (0 === \count($this->arguments)) { + throw new OutOfBoundsException('Cannot replace arguments if none have been configured yet.'); + } + + if (\is_int($index) && ($index < 0 || $index > \count($this->arguments) - 1)) { + throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, \count($this->arguments) - 1)); + } + + if (!\array_key_exists($index, $this->arguments)) { + throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist.', $index)); + } + + $this->arguments[$index] = $argument; + + return $this; + } + + /** + * Sets a specific argument. + * + * @param int|string $key + * @param mixed $value + * + * @return $this + */ + public function setArgument($key, $value) + { + $this->arguments[$key] = $value; + + return $this; + } + + /** + * Gets the arguments to pass to the service constructor/factory method. + * + * @return array The array of arguments + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * Gets an argument to pass to the service constructor/factory method. + * + * @param int|string $index + * + * @return mixed The argument value + * + * @throws OutOfBoundsException When the argument does not exist + */ + public function getArgument($index) + { + if (!\array_key_exists($index, $this->arguments)) { + throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist.', $index)); + } + + return $this->arguments[$index]; + } + + /** + * Sets the methods to call after service initialization. + * + * @return $this + */ + public function setMethodCalls(array $calls = []) + { + $this->calls = []; + foreach ($calls as $call) { + $this->addMethodCall($call[0], $call[1], $call[2] ?? false); + } + + return $this; + } + + /** + * Adds a method to call after service initialization. + * + * @param string $method The method name to call + * @param array $arguments An array of arguments to pass to the method call + * @param bool $returnsClone Whether the call returns the service instance or not + * + * @return $this + * + * @throws InvalidArgumentException on empty $method param + */ + public function addMethodCall(string $method, array $arguments = [], bool $returnsClone = false) + { + if (empty($method)) { + throw new InvalidArgumentException('Method name cannot be empty.'); + } + $this->calls[] = $returnsClone ? [$method, $arguments, true] : [$method, $arguments]; + + return $this; + } + + /** + * Removes a method to call after service initialization. + * + * @return $this + */ + public function removeMethodCall(string $method) + { + foreach ($this->calls as $i => $call) { + if ($call[0] === $method) { + unset($this->calls[$i]); + break; + } + } + + return $this; + } + + /** + * Check if the current definition has a given method to call after service initialization. + * + * @return bool + */ + public function hasMethodCall(string $method) + { + foreach ($this->calls as $call) { + if ($call[0] === $method) { + return true; + } + } + + return false; + } + + /** + * Gets the methods to call after service initialization. + * + * @return array An array of method calls + */ + public function getMethodCalls() + { + return $this->calls; + } + + /** + * Sets the definition templates to conditionally apply on the current definition, keyed by parent interface/class. + * + * @param ChildDefinition[] $instanceof + * + * @return $this + */ + public function setInstanceofConditionals(array $instanceof) + { + $this->instanceof = $instanceof; + + return $this; + } + + /** + * Gets the definition templates to conditionally apply on the current definition, keyed by parent interface/class. + * + * @return ChildDefinition[] + */ + public function getInstanceofConditionals() + { + return $this->instanceof; + } + + /** + * Sets whether or not instanceof conditionals should be prepended with a global set. + * + * @return $this + */ + public function setAutoconfigured(bool $autoconfigured) + { + $this->changes['autoconfigured'] = true; + + $this->autoconfigured = $autoconfigured; + + return $this; + } + + /** + * @return bool + */ + public function isAutoconfigured() + { + return $this->autoconfigured; + } + + /** + * Sets tags for this definition. + * + * @return $this + */ + public function setTags(array $tags) + { + $this->tags = $tags; + + return $this; + } + + /** + * Returns all tags. + * + * @return array An array of tags + */ + public function getTags() + { + return $this->tags; + } + + /** + * Gets a tag by name. + * + * @return array An array of attributes + */ + public function getTag(string $name) + { + return isset($this->tags[$name]) ? $this->tags[$name] : []; + } + + /** + * Adds a tag for this definition. + * + * @return $this + */ + public function addTag(string $name, array $attributes = []) + { + $this->tags[$name][] = $attributes; + + return $this; + } + + /** + * Whether this definition has a tag with the given name. + * + * @return bool + */ + public function hasTag(string $name) + { + return isset($this->tags[$name]); + } + + /** + * Clears all tags for a given name. + * + * @return $this + */ + public function clearTag(string $name) + { + unset($this->tags[$name]); + + return $this; + } + + /** + * Clears the tags for this definition. + * + * @return $this + */ + public function clearTags() + { + $this->tags = []; + + return $this; + } + + /** + * Sets a file to require before creating the service. + * + * @return $this + */ + public function setFile(?string $file) + { + $this->changes['file'] = true; + + $this->file = $file; + + return $this; + } + + /** + * Gets the file to require before creating the service. + * + * @return string|null The full pathname to include + */ + public function getFile() + { + return $this->file; + } + + /** + * Sets if the service must be shared or not. + * + * @return $this + */ + public function setShared(bool $shared) + { + $this->changes['shared'] = true; + + $this->shared = $shared; + + return $this; + } + + /** + * Whether this service is shared. + * + * @return bool + */ + public function isShared() + { + return $this->shared; + } + + /** + * Sets the visibility of this service. + * + * @return $this + */ + public function setPublic(bool $boolean) + { + $this->changes['public'] = true; + + $this->public = $boolean; + $this->private = false; + + return $this; + } + + /** + * Whether this service is public facing. + * + * @return bool + */ + public function isPublic() + { + return $this->public; + } + + /** + * Sets if this service is private. + * + * When set, the "private" state has a higher precedence than "public". + * In version 3.4, a "private" service always remains publicly accessible, + * but triggers a deprecation notice when accessed from the container, + * so that the service can be made really private in 4.0. + * + * @return $this + */ + public function setPrivate(bool $boolean) + { + $this->private = $boolean; + + return $this; + } + + /** + * Whether this service is private. + * + * @return bool + */ + public function isPrivate() + { + return $this->private; + } + + /** + * Sets the lazy flag of this service. + * + * @return $this + */ + public function setLazy(bool $lazy) + { + $this->changes['lazy'] = true; + + $this->lazy = $lazy; + + return $this; + } + + /** + * Whether this service is lazy. + * + * @return bool + */ + public function isLazy() + { + return $this->lazy; + } + + /** + * Sets whether this definition is synthetic, that is not constructed by the + * container, but dynamically injected. + * + * @return $this + */ + public function setSynthetic(bool $boolean) + { + $this->synthetic = $boolean; + + return $this; + } + + /** + * Whether this definition is synthetic, that is not constructed by the + * container, but dynamically injected. + * + * @return bool + */ + public function isSynthetic() + { + return $this->synthetic; + } + + /** + * Whether this definition is abstract, that means it merely serves as a + * template for other definitions. + * + * @return $this + */ + public function setAbstract(bool $boolean) + { + $this->abstract = $boolean; + + return $this; + } + + /** + * Whether this definition is abstract, that means it merely serves as a + * template for other definitions. + * + * @return bool + */ + public function isAbstract() + { + return $this->abstract; + } + + /** + * Whether this definition is deprecated, that means it should not be called + * anymore. + * + * @param string $template Template message to use if the definition is deprecated + * + * @return $this + * + * @throws InvalidArgumentException when the message template is invalid + */ + public function setDeprecated(bool $status = true, string $template = null) + { + if (null !== $template) { + if (preg_match('#[\r\n]|\*/#', $template)) { + throw new InvalidArgumentException('Invalid characters found in deprecation template.'); + } + + if (false === strpos($template, '%service_id%')) { + throw new InvalidArgumentException('The deprecation template must contain the "%service_id%" placeholder.'); + } + + $this->deprecationTemplate = $template; + } + + $this->changes['deprecated'] = true; + + $this->deprecated = $status; + + return $this; + } + + /** + * Whether this definition is deprecated, that means it should not be called + * anymore. + * + * @return bool + */ + public function isDeprecated() + { + return $this->deprecated; + } + + /** + * Message to use if this definition is deprecated. + * + * @param string $id Service id relying on this definition + * + * @return string + */ + public function getDeprecationMessage(string $id) + { + return str_replace('%service_id%', $id, $this->deprecationTemplate ?: self::$defaultDeprecationTemplate); + } + + /** + * Sets a configurator to call after the service is fully initialized. + * + * @param string|array|Reference $configurator A PHP function, reference or an array containing a class/Reference and a method to call + * + * @return $this + */ + public function setConfigurator($configurator) + { + $this->changes['configurator'] = true; + + if (\is_string($configurator) && false !== strpos($configurator, '::')) { + $configurator = explode('::', $configurator, 2); + } elseif ($configurator instanceof Reference) { + $configurator = [$configurator, '__invoke']; + } + + $this->configurator = $configurator; + + return $this; + } + + /** + * Gets the configurator to call after the service is fully initialized. + * + * @return callable|array|null + */ + public function getConfigurator() + { + return $this->configurator; + } + + /** + * Is the definition autowired? + * + * @return bool + */ + public function isAutowired() + { + return $this->autowired; + } + + /** + * Enables/disables autowiring. + * + * @return $this + */ + public function setAutowired(bool $autowired) + { + $this->changes['autowired'] = true; + + $this->autowired = $autowired; + + return $this; + } + + /** + * Gets bindings. + * + * @return array|BoundArgument[] + */ + public function getBindings() + { + return $this->bindings; + } + + /** + * Sets bindings. + * + * Bindings map $named or FQCN arguments to values that should be + * injected in the matching parameters (of the constructor, of methods + * called and of controller actions). + * + * @return $this + */ + public function setBindings(array $bindings) + { + foreach ($bindings as $key => $binding) { + if (0 < strpos($key, '$') && $key !== $k = preg_replace('/[ \t]*\$/', ' $', $key)) { + unset($bindings[$key]); + $bindings[$key = $k] = $binding; + } + if (!$binding instanceof BoundArgument) { + $bindings[$key] = new BoundArgument($binding); + } + } + + $this->bindings = $bindings; + + return $this; + } + + /** + * Add an error that occurred when building this Definition. + * + * @param string|\Closure|self $error + * + * @return $this + */ + public function addError($error) + { + if ($error instanceof self) { + $this->errors = array_merge($this->errors, $error->errors); + } else { + $this->errors[] = $error; + } + + return $this; + } + + /** + * Returns any errors that occurred while building this Definition. + * + * @return array + */ + public function getErrors() + { + foreach ($this->errors as $i => $error) { + if ($error instanceof \Closure) { + $this->errors[$i] = (string) $error(); + } elseif (!\is_string($error)) { + $this->errors[$i] = (string) $error; + } + } + + return $this->errors; + } + + public function hasErrors(): bool + { + return (bool) $this->errors; + } +} diff --git a/vendor/symfony/dependency-injection/Dumper/Dumper.php b/vendor/symfony/dependency-injection/Dumper/Dumper.php new file mode 100644 index 0000000..e7407b0 --- /dev/null +++ b/vendor/symfony/dependency-injection/Dumper/Dumper.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Dumper; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Dumper is the abstract class for all built-in dumpers. + * + * @author Fabien Potencier + */ +abstract class Dumper implements DumperInterface +{ + protected $container; + + public function __construct(ContainerBuilder $container) + { + $this->container = $container; + } +} diff --git a/vendor/symfony/dependency-injection/Dumper/DumperInterface.php b/vendor/symfony/dependency-injection/Dumper/DumperInterface.php new file mode 100644 index 0000000..8abc192 --- /dev/null +++ b/vendor/symfony/dependency-injection/Dumper/DumperInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Dumper; + +/** + * DumperInterface is the interface implemented by service container dumper classes. + * + * @author Fabien Potencier + */ +interface DumperInterface +{ + /** + * Dumps the service container. + * + * @return string|array The representation of the service container + */ + public function dump(array $options = []); +} diff --git a/vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php b/vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php new file mode 100644 index 0000000..c21dd91 --- /dev/null +++ b/vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php @@ -0,0 +1,251 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Dumper; + +use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; +use Symfony\Component\DependencyInjection\Parameter; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\DependencyInjection\Reference; + +/** + * GraphvizDumper dumps a service container as a graphviz file. + * + * You can convert the generated dot file with the dot utility (http://www.graphviz.org/): + * + * dot -Tpng container.dot > foo.png + * + * @author Fabien Potencier + */ +class GraphvizDumper extends Dumper +{ + private $nodes; + private $edges; + private $options = [ + 'graph' => ['ratio' => 'compress'], + 'node' => ['fontsize' => 11, 'fontname' => 'Arial', 'shape' => 'record'], + 'edge' => ['fontsize' => 9, 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => 0.5], + 'node.instance' => ['fillcolor' => '#9999ff', 'style' => 'filled'], + 'node.definition' => ['fillcolor' => '#eeeeee'], + 'node.missing' => ['fillcolor' => '#ff9999', 'style' => 'filled'], + ]; + + /** + * Dumps the service container as a graphviz graph. + * + * Available options: + * + * * graph: The default options for the whole graph + * * node: The default options for nodes + * * edge: The default options for edges + * * node.instance: The default options for services that are defined directly by object instances + * * node.definition: The default options for services that are defined via service definition instances + * * node.missing: The default options for missing services + * + * @return string The dot representation of the service container + */ + public function dump(array $options = []) + { + foreach (['graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing'] as $key) { + if (isset($options[$key])) { + $this->options[$key] = array_merge($this->options[$key], $options[$key]); + } + } + + $this->nodes = $this->findNodes(); + + $this->edges = []; + foreach ($this->container->getDefinitions() as $id => $definition) { + $this->edges[$id] = array_merge( + $this->findEdges($id, $definition->getArguments(), true, ''), + $this->findEdges($id, $definition->getProperties(), false, '') + ); + + foreach ($definition->getMethodCalls() as $call) { + $this->edges[$id] = array_merge( + $this->edges[$id], + $this->findEdges($id, $call[1], false, $call[0].'()') + ); + } + } + + return $this->container->resolveEnvPlaceholders($this->startDot().$this->addNodes().$this->addEdges().$this->endDot(), '__ENV_%s__'); + } + + private function addNodes(): string + { + $code = ''; + foreach ($this->nodes as $id => $node) { + $aliases = $this->getAliases($id); + + $code .= sprintf(" node_%s [label=\"%s\\n%s\\n\", shape=%s%s];\n", $this->dotize($id), $id.($aliases ? ' ('.implode(', ', $aliases).')' : ''), $node['class'], $this->options['node']['shape'], $this->addAttributes($node['attributes'])); + } + + return $code; + } + + private function addEdges(): string + { + $code = ''; + foreach ($this->edges as $id => $edges) { + foreach ($edges as $edge) { + $code .= sprintf(" node_%s -> node_%s [label=\"%s\" style=\"%s\"%s];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed', $edge['lazy'] ? ' color="#9999ff"' : ''); + } + } + + return $code; + } + + /** + * Finds all edges belonging to a specific service id. + */ + private function findEdges(string $id, array $arguments, bool $required, string $name, bool $lazy = false): array + { + $edges = []; + foreach ($arguments as $argument) { + if ($argument instanceof Parameter) { + $argument = $this->container->hasParameter($argument) ? $this->container->getParameter($argument) : null; + } elseif (\is_string($argument) && preg_match('/^%([^%]+)%$/', $argument, $match)) { + $argument = $this->container->hasParameter($match[1]) ? $this->container->getParameter($match[1]) : null; + } + + if ($argument instanceof Reference) { + $lazyEdge = $lazy; + + if (!$this->container->has((string) $argument)) { + $this->nodes[(string) $argument] = ['name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']]; + } elseif ('service_container' !== (string) $argument) { + $lazyEdge = $lazy || $this->container->getDefinition((string) $argument)->isLazy(); + } + + $edges[] = ['name' => $name, 'required' => $required, 'to' => $argument, 'lazy' => $lazyEdge]; + } elseif ($argument instanceof ArgumentInterface) { + $edges = array_merge($edges, $this->findEdges($id, $argument->getValues(), $required, $name, true)); + } elseif ($argument instanceof Definition) { + $edges = array_merge($edges, + $this->findEdges($id, $argument->getArguments(), $required, ''), + $this->findEdges($id, $argument->getProperties(), false, '') + ); + foreach ($argument->getMethodCalls() as $call) { + $edges = array_merge($edges, $this->findEdges($id, $call[1], false, $call[0].'()')); + } + } elseif (\is_array($argument)) { + $edges = array_merge($edges, $this->findEdges($id, $argument, $required, $name, $lazy)); + } + } + + return $edges; + } + + private function findNodes(): array + { + $nodes = []; + + $container = $this->cloneContainer(); + + foreach ($container->getDefinitions() as $id => $definition) { + $class = $definition->getClass(); + + if ('\\' === substr($class, 0, 1)) { + $class = substr($class, 1); + } + + try { + $class = $this->container->getParameterBag()->resolveValue($class); + } catch (ParameterNotFoundException $e) { + } + + $nodes[$id] = ['class' => str_replace('\\', '\\\\', $class), 'attributes' => array_merge($this->options['node.definition'], ['style' => $definition->isShared() ? 'filled' : 'dotted'])]; + $container->setDefinition($id, new Definition('stdClass')); + } + + foreach ($container->getServiceIds() as $id) { + if (\array_key_exists($id, $container->getAliases())) { + continue; + } + + if (!$container->hasDefinition($id)) { + $nodes[$id] = ['class' => str_replace('\\', '\\\\', \get_class($container->get($id))), 'attributes' => $this->options['node.instance']]; + } + } + + return $nodes; + } + + private function cloneContainer(): ContainerBuilder + { + $parameterBag = new ParameterBag($this->container->getParameterBag()->all()); + + $container = new ContainerBuilder($parameterBag); + $container->setDefinitions($this->container->getDefinitions()); + $container->setAliases($this->container->getAliases()); + $container->setResources($this->container->getResources()); + foreach ($this->container->getExtensions() as $extension) { + $container->registerExtension($extension); + } + + return $container; + } + + private function startDot(): string + { + return sprintf("digraph sc {\n %s\n node [%s];\n edge [%s];\n\n", + $this->addOptions($this->options['graph']), + $this->addOptions($this->options['node']), + $this->addOptions($this->options['edge']) + ); + } + + private function endDot(): string + { + return "}\n"; + } + + private function addAttributes(array $attributes): string + { + $code = []; + foreach ($attributes as $k => $v) { + $code[] = sprintf('%s="%s"', $k, $v); + } + + return $code ? ', '.implode(', ', $code) : ''; + } + + private function addOptions(array $options): string + { + $code = []; + foreach ($options as $k => $v) { + $code[] = sprintf('%s="%s"', $k, $v); + } + + return implode(' ', $code); + } + + private function dotize(string $id): string + { + return preg_replace('/\W/i', '_', $id); + } + + private function getAliases(string $id): array + { + $aliases = []; + foreach ($this->container->getAliases() as $alias => $origin) { + if ($id == $origin) { + $aliases[] = $alias; + } + } + + return $aliases; + } +} diff --git a/vendor/symfony/dependency-injection/Dumper/PhpDumper.php b/vendor/symfony/dependency-injection/Dumper/PhpDumper.php new file mode 100644 index 0000000..b0dd269 --- /dev/null +++ b/vendor/symfony/dependency-injection/Dumper/PhpDumper.php @@ -0,0 +1,2064 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Dumper; + +use Composer\Autoload\ClassLoader; +use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader; +use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceLocator; +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; +use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass; +use Symfony\Component\DependencyInjection\Compiler\CheckCircularReferencesPass; +use Symfony\Component\DependencyInjection\Compiler\ServiceReferenceGraphEdge; +use Symfony\Component\DependencyInjection\Compiler\ServiceReferenceGraphNode; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\EnvParameterException; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\LogicException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; +use Symfony\Component\DependencyInjection\ExpressionLanguage; +use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper; +use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; +use Symfony\Component\DependencyInjection\Loader\FileLoader; +use Symfony\Component\DependencyInjection\Parameter; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ServiceLocator as BaseServiceLocator; +use Symfony\Component\DependencyInjection\TypedReference; +use Symfony\Component\DependencyInjection\Variable; +use Symfony\Component\ErrorHandler\DebugClassLoader; +use Symfony\Component\ExpressionLanguage\Expression; +use Symfony\Component\HttpKernel\Kernel; + +/** + * PhpDumper dumps a service container as a PHP class. + * + * @author Fabien Potencier + * @author Johannes M. Schmitt + */ +class PhpDumper extends Dumper +{ + /** + * Characters that might appear in the generated variable name as first character. + */ + const FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz'; + + /** + * Characters that might appear in the generated variable name as any but the first character. + */ + const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_'; + + private $definitionVariables; + private $referenceVariables; + private $variableCount; + private $inlinedDefinitions; + private $serviceCalls; + private $reservedVariables = ['instance', 'class', 'this']; + private $expressionLanguage; + private $targetDirRegex; + private $targetDirMaxMatches; + private $docStar; + private $serviceIdToMethodNameMap; + private $usedMethodNames; + private $namespace; + private $asFiles; + private $hotPathTag; + private $inlineFactories; + private $inlineRequires; + private $inlinedRequires = []; + private $circularReferences = []; + private $singleUsePrivateIds = []; + private $addThrow = false; + private $addGetService = false; + private $locatedIds = []; + private $serviceLocatorTag; + private $exportedVariables = []; + private $baseClass; + + /** + * @var ProxyDumper + */ + private $proxyDumper; + + /** + * {@inheritdoc} + */ + public function __construct(ContainerBuilder $container) + { + if (!$container->isCompiled()) { + throw new LogicException('Cannot dump an uncompiled container.'); + } + + parent::__construct($container); + } + + /** + * Sets the dumper to be used when dumping proxies in the generated container. + */ + public function setProxyDumper(ProxyDumper $proxyDumper) + { + $this->proxyDumper = $proxyDumper; + } + + /** + * Dumps the service container as a PHP class. + * + * Available options: + * + * * class: The class name + * * base_class: The base class name + * * namespace: The class namespace + * * as_files: To split the container in several files + * + * @return string|array A PHP class representing the service container or an array of PHP files if the "as_files" option is set + * + * @throws EnvParameterException When an env var exists but has not been dumped + */ + public function dump(array $options = []) + { + $this->locatedIds = []; + $this->targetDirRegex = null; + $this->inlinedRequires = []; + $this->exportedVariables = []; + $options = array_merge([ + 'class' => 'ProjectServiceContainer', + 'base_class' => 'Container', + 'namespace' => '', + 'as_files' => false, + 'debug' => true, + 'hot_path_tag' => 'container.hot_path', + 'inline_factories_parameter' => 'container.dumper.inline_factories', + 'inline_class_loader_parameter' => 'container.dumper.inline_class_loader', + 'service_locator_tag' => 'container.service_locator', + 'build_time' => time(), + ], $options); + + $this->addThrow = $this->addGetService = false; + $this->namespace = $options['namespace']; + $this->asFiles = $options['as_files']; + $this->hotPathTag = $options['hot_path_tag']; + $this->inlineFactories = $this->asFiles && $options['inline_factories_parameter'] && $this->container->hasParameter($options['inline_factories_parameter']) && $this->container->getParameter($options['inline_factories_parameter']); + $this->inlineRequires = $options['inline_class_loader_parameter'] && $this->container->hasParameter($options['inline_class_loader_parameter']) && $this->container->getParameter($options['inline_class_loader_parameter']); + $this->serviceLocatorTag = $options['service_locator_tag']; + + if (0 !== strpos($baseClass = $options['base_class'], '\\') && 'Container' !== $baseClass) { + $baseClass = sprintf('%s\%s', $options['namespace'] ? '\\'.$options['namespace'] : '', $baseClass); + $this->baseClass = $baseClass; + } elseif ('Container' === $baseClass) { + $this->baseClass = Container::class; + } else { + $this->baseClass = $baseClass; + } + + $this->initializeMethodNamesMap('Container' === $baseClass ? Container::class : $baseClass); + + if ($this->getProxyDumper() instanceof NullDumper) { + (new AnalyzeServiceReferencesPass(true, false))->process($this->container); + try { + (new CheckCircularReferencesPass())->process($this->container); + } catch (ServiceCircularReferenceException $e) { + $path = $e->getPath(); + end($path); + $path[key($path)] .= '". Try running "composer require symfony/proxy-manager-bridge'; + + throw new ServiceCircularReferenceException($e->getServiceId(), $path); + } + } + + (new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->process($this->container); + $checkedNodes = []; + $this->circularReferences = []; + $this->singleUsePrivateIds = []; + foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) { + if (!$node->getValue() instanceof Definition) { + continue; + } + if (!isset($checkedNodes[$id])) { + $this->analyzeCircularReferences($id, $node->getOutEdges(), $checkedNodes); + } + if ($this->isSingleUsePrivateNode($node)) { + $this->singleUsePrivateIds[$id] = $id; + } + } + $this->container->getCompiler()->getServiceReferenceGraph()->clear(); + $checkedNodes = []; + $this->singleUsePrivateIds = array_diff_key($this->singleUsePrivateIds, $this->circularReferences); + + $this->docStar = $options['debug'] ? '*' : ''; + + if (!empty($options['file']) && is_dir($dir = \dirname($options['file']))) { + // Build a regexp where the first root dirs are mandatory, + // but every other sub-dir is optional up to the full path in $dir + // Mandate at least 1 root dir and not more than 5 optional dirs. + + $dir = explode(\DIRECTORY_SEPARATOR, realpath($dir)); + $i = \count($dir); + + if (2 + (int) ('\\' === \DIRECTORY_SEPARATOR) <= $i) { + $regex = ''; + $lastOptionalDir = $i > 8 ? $i - 5 : (2 + (int) ('\\' === \DIRECTORY_SEPARATOR)); + $this->targetDirMaxMatches = $i - $lastOptionalDir; + + while (--$i >= $lastOptionalDir) { + $regex = sprintf('(%s%s)?', preg_quote(\DIRECTORY_SEPARATOR.$dir[$i], '#'), $regex); + } + + do { + $regex = preg_quote(\DIRECTORY_SEPARATOR.$dir[$i], '#').$regex; + } while (0 < --$i); + + $this->targetDirRegex = '#'.preg_quote($dir[0], '#').$regex.'#'; + } + } + + $proxyClasses = $this->inlineFactories ? $this->generateProxyClasses() : null; + + $code = + $this->startClass($options['class'], $baseClass, $preload). + $this->addServices($services). + $this->addDeprecatedAliases(). + $this->addDefaultParametersMethod() + ; + + $proxyClasses = $proxyClasses ?? $this->generateProxyClasses(); + + if ($this->addGetService) { + $code = preg_replace( + "/(\r?\n\r?\n public function __construct.+?\\{\r?\n)/s", + "\n private \$getService;$1 \$this->getService = \\Closure::fromCallable([\$this, 'getService']);\n", + $code, + 1 + ); + } + + if ($this->asFiles) { + $fileStart = <<container->getRemovedIds(); + foreach ($this->container->getDefinitions() as $id => $definition) { + if (!$definition->isPublic()) { + $ids[$id] = true; + } + } + if ($ids = array_keys($ids)) { + sort($ids); + $c = "doExport($id)." => true,\n"; + } + $files['removed-ids.php'] = $c."];\n"; + } + + if (!$this->inlineFactories) { + foreach ($this->generateServiceFiles($services) as $file => $c) { + $files[$file] = $fileStart.$c; + } + foreach ($proxyClasses as $file => $c) { + $files[$file] = "endClass(); + + if ($this->inlineFactories) { + foreach ($proxyClasses as $c) { + $code .= $c; + } + } + + $files[$options['class'].'.php'] = $code; + $hash = ucfirst(strtr(ContainerBuilder::hash($files), '._', 'xx')); + $code = []; + + foreach ($files as $file => $c) { + $code["Container{$hash}/{$file}"] = $c; + } + array_pop($code); + $code["Container{$hash}/{$options['class']}.php"] = substr_replace($files[$options['class'].'.php'], "namespace ? "\nnamespace {$this->namespace};\n" : ''; + $time = $options['build_time']; + $id = hash('crc32', $hash.$time); + $this->asFiles = false; + + if ($preload && null !== $autoloadFile = $this->getAutoloadFile()) { + $autoloadFile = substr($this->export($autoloadFile), 2, -1); + + $code[$options['class'].'.preload.php'] = <<= 7.4 when preloading is desired + +use Symfony\Component\DependencyInjection\Dumper\Preloader; + +require $autoloadFile; +require __DIR__.'/Container{$hash}/{$options['class']}.php'; + +\$classes = []; + +EOF; + + foreach ($preload as $class) { + $code[$options['class'].'.preload.php'] .= sprintf("\$classes[] = '%s';\n", $class); + } + + $code[$options['class'].'.preload.php'] .= <<<'EOF' + +Preloader::preload($classes); + +EOF; + } + + $code[$options['class'].'.php'] = << '$hash', + 'container.build_id' => '$id', + 'container.build_time' => $time, +], __DIR__.\\DIRECTORY_SEPARATOR.'Container{$hash}'); + +EOF; + } else { + $code .= $this->endClass(); + foreach ($proxyClasses as $c) { + $code .= $c; + } + } + + $this->targetDirRegex = null; + $this->inlinedRequires = []; + $this->circularReferences = []; + $this->locatedIds = []; + $this->exportedVariables = []; + + $unusedEnvs = []; + foreach ($this->container->getEnvCounters() as $env => $use) { + if (!$use) { + $unusedEnvs[] = $env; + } + } + if ($unusedEnvs) { + throw new EnvParameterException($unusedEnvs, null, 'Environment variables "%s" are never used. Please, check your container\'s configuration.'); + } + + return $code; + } + + /** + * Retrieves the currently set proxy dumper or instantiates one. + */ + private function getProxyDumper(): ProxyDumper + { + if (!$this->proxyDumper) { + $this->proxyDumper = new NullDumper(); + } + + return $this->proxyDumper; + } + + /** + * @param ServiceReferenceGraphEdge[] $edges + */ + private function analyzeCircularReferences(string $sourceId, array $edges, array &$checkedNodes, array &$currentPath = [], bool $byConstructor = true) + { + $checkedNodes[$sourceId] = true; + $currentPath[$sourceId] = $byConstructor; + + foreach ($edges as $edge) { + $node = $edge->getDestNode(); + $id = $node->getId(); + + if (!$node->getValue() instanceof Definition || $sourceId === $id || $edge->isLazy() || $edge->isWeak()) { + // no-op + } elseif (isset($currentPath[$id])) { + $this->addCircularReferences($id, $currentPath, $edge->isReferencedByConstructor()); + } elseif (!isset($checkedNodes[$id])) { + $this->analyzeCircularReferences($id, $node->getOutEdges(), $checkedNodes, $currentPath, $edge->isReferencedByConstructor()); + } elseif (isset($this->circularReferences[$id])) { + $this->connectCircularReferences($id, $currentPath, $edge->isReferencedByConstructor()); + } + } + unset($currentPath[$sourceId]); + } + + private function connectCircularReferences(string $sourceId, array &$currentPath, bool $byConstructor, array &$subPath = []) + { + $currentPath[$sourceId] = $subPath[$sourceId] = $byConstructor; + + foreach ($this->circularReferences[$sourceId] as $id => $byConstructor) { + if (isset($currentPath[$id])) { + $this->addCircularReferences($id, $currentPath, $byConstructor); + } elseif (!isset($subPath[$id]) && isset($this->circularReferences[$id])) { + $this->connectCircularReferences($id, $currentPath, $byConstructor, $subPath); + } + } + unset($currentPath[$sourceId], $subPath[$sourceId]); + } + + private function addCircularReferences(string $id, array $currentPath, bool $byConstructor) + { + $currentPath[$id] = $byConstructor; + $circularRefs = []; + + foreach (array_reverse($currentPath) as $parentId => $v) { + $byConstructor = $byConstructor && $v; + $circularRefs[] = $parentId; + + if ($parentId === $id) { + break; + } + } + + $currentId = $id; + foreach ($circularRefs as $parentId) { + if (empty($this->circularReferences[$parentId][$currentId])) { + $this->circularReferences[$parentId][$currentId] = $byConstructor; + } + + $currentId = $parentId; + } + } + + private function collectLineage(string $class, array &$lineage) + { + if (isset($lineage[$class])) { + return; + } + if (!$r = $this->container->getReflectionClass($class, false)) { + return; + } + if (is_a($class, $this->baseClass, true)) { + return; + } + $file = $r->getFileName(); + if (!$file || $this->doExport($file) === $exportedFile = $this->export($file)) { + return; + } + + $lineage[$class] = substr($exportedFile, 1, -1); + + if ($parent = $r->getParentClass()) { + $this->collectLineage($parent->name, $lineage); + } + + foreach ($r->getInterfaces() as $parent) { + $this->collectLineage($parent->name, $lineage); + } + + foreach ($r->getTraits() as $parent) { + $this->collectLineage($parent->name, $lineage); + } + + unset($lineage[$class]); + $lineage[$class] = substr($exportedFile, 1, -1); + } + + private function generateProxyClasses(): array + { + $proxyClasses = []; + $alreadyGenerated = []; + $definitions = $this->container->getDefinitions(); + $strip = '' === $this->docStar && method_exists('Symfony\Component\HttpKernel\Kernel', 'stripComments'); + $proxyDumper = $this->getProxyDumper(); + ksort($definitions); + foreach ($definitions as $definition) { + if (!$proxyDumper->isProxyCandidate($definition)) { + continue; + } + if (isset($alreadyGenerated[$class = $definition->getClass()])) { + continue; + } + $alreadyGenerated[$class] = true; + // register class' reflector for resource tracking + $this->container->getReflectionClass($class); + if ("\n" === $proxyCode = "\n".$proxyDumper->getProxyCode($definition)) { + continue; + } + + if ($this->inlineRequires) { + $lineage = []; + $this->collectLineage($class, $lineage); + + $code = ''; + foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) { + if ($this->inlineFactories) { + $this->inlinedRequires[$file] = true; + } + $code .= sprintf("include_once %s;\n", $file); + } + + $proxyCode = $code.$proxyCode; + } + + if ($strip) { + $proxyCode = "inlineRequires ? substr($proxyCode, \strlen($code)) : $proxyCode, 3)[1])] = $proxyCode; + } + + return $proxyClasses; + } + + private function addServiceInclude(string $cId, Definition $definition): string + { + $code = ''; + + if ($this->inlineRequires && (!$this->isHotPath($definition) || $this->getProxyDumper()->isProxyCandidate($definition))) { + $lineage = []; + foreach ($this->inlinedDefinitions as $def) { + if (!$def->isDeprecated() && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) { + $this->collectLineage($class, $lineage); + } + } + + foreach ($this->serviceCalls as $id => list($callCount, $behavior)) { + if ('service_container' !== $id && $id !== $cId + && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $behavior + && $this->container->has($id) + && $this->isTrivialInstance($def = $this->container->findDefinition($id)) + && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass()) + ) { + $this->collectLineage($class, $lineage); + } + } + + foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) { + $code .= sprintf(" include_once %s;\n", $file); + } + } + + foreach ($this->inlinedDefinitions as $def) { + if ($file = $def->getFile()) { + $file = $this->dumpValue($file); + $file = '(' === $file[0] ? substr($file, 1, -1) : $file; + $code .= sprintf(" include_once %s;\n", $file); + } + } + + if ('' !== $code) { + $code .= "\n"; + } + + return $code; + } + + /** + * @throws InvalidArgumentException + * @throws RuntimeException + */ + private function addServiceInstance(string $id, Definition $definition, bool $isSimpleInstance): string + { + $class = $this->dumpValue($definition->getClass()); + + if (0 === strpos($class, "'") && false === strpos($class, '$') && !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { + throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id)); + } + + $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); + $instantiation = ''; + + $lastWitherIndex = null; + foreach ($definition->getMethodCalls() as $k => $call) { + if ($call[2] ?? false) { + $lastWitherIndex = $k; + } + } + + if (!$isProxyCandidate && $definition->isShared() && !isset($this->singleUsePrivateIds[$id]) && null === $lastWitherIndex) { + $instantiation = sprintf('$this->%s[%s] = %s', $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', $this->doExport($id), $isSimpleInstance ? '' : '$instance'); + } elseif (!$isSimpleInstance) { + $instantiation = '$instance'; + } + + $return = ''; + if ($isSimpleInstance) { + $return = 'return '; + } else { + $instantiation .= ' = '; + } + + return $this->addNewInstance($definition, ' '.$return.$instantiation, $id); + } + + private function isTrivialInstance(Definition $definition): bool + { + if ($definition->hasErrors()) { + return true; + } + if ($definition->isSynthetic() || $definition->getFile() || $definition->getMethodCalls() || $definition->getProperties() || $definition->getConfigurator()) { + return false; + } + if ($definition->isDeprecated() || $definition->isLazy() || $definition->getFactory() || 3 < \count($definition->getArguments())) { + return false; + } + + foreach ($definition->getArguments() as $arg) { + if (!$arg || $arg instanceof Parameter) { + continue; + } + if (\is_array($arg) && 3 >= \count($arg)) { + foreach ($arg as $k => $v) { + if ($this->dumpValue($k) !== $this->dumpValue($k, false)) { + return false; + } + if (!$v || $v instanceof Parameter) { + continue; + } + if ($v instanceof Reference && $this->container->has($id = (string) $v) && $this->container->findDefinition($id)->isSynthetic()) { + continue; + } + if (!is_scalar($v) || $this->dumpValue($v) !== $this->dumpValue($v, false)) { + return false; + } + } + } elseif ($arg instanceof Reference && $this->container->has($id = (string) $arg) && $this->container->findDefinition($id)->isSynthetic()) { + continue; + } elseif (!is_scalar($arg) || $this->dumpValue($arg) !== $this->dumpValue($arg, false)) { + return false; + } + } + + return true; + } + + private function addServiceMethodCalls(Definition $definition, string $variableName, ?string $sharedNonLazyId): string + { + $lastWitherIndex = null; + foreach ($definition->getMethodCalls() as $k => $call) { + if ($call[2] ?? false) { + $lastWitherIndex = $k; + } + } + + $calls = ''; + foreach ($definition->getMethodCalls() as $k => $call) { + $arguments = []; + foreach ($call[1] as $value) { + $arguments[] = $this->dumpValue($value); + } + + $witherAssignation = ''; + + if ($call[2] ?? false) { + if (null !== $sharedNonLazyId && $lastWitherIndex === $k) { + $witherAssignation = sprintf('$this->%s[\'%s\'] = ', $definition->isPublic() ? 'services' : 'privates', $sharedNonLazyId); + } + $witherAssignation .= sprintf('$%s = ', $variableName); + } + + $calls .= $this->wrapServiceConditionals($call[1], sprintf(" %s\$%s->%s(%s);\n", $witherAssignation, $variableName, $call[0], implode(', ', $arguments))); + } + + return $calls; + } + + private function addServiceProperties(Definition $definition, string $variableName = 'instance'): string + { + $code = ''; + foreach ($definition->getProperties() as $name => $value) { + $code .= sprintf(" \$%s->%s = %s;\n", $variableName, $name, $this->dumpValue($value)); + } + + return $code; + } + + private function addServiceConfigurator(Definition $definition, string $variableName = 'instance'): string + { + if (!$callable = $definition->getConfigurator()) { + return ''; + } + + if (\is_array($callable)) { + if ($callable[0] instanceof Reference + || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0])) + ) { + return sprintf(" %s->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); + } + + $class = $this->dumpValue($callable[0]); + // If the class is a string we can optimize away + if (0 === strpos($class, "'") && false === strpos($class, '$')) { + return sprintf(" %s::%s(\$%s);\n", $this->dumpLiteralClass($class), $callable[1], $variableName); + } + + if (0 === strpos($class, 'new ')) { + return sprintf(" (%s)->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); + } + + return sprintf(" [%s, '%s'](\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); + } + + return sprintf(" %s(\$%s);\n", $callable, $variableName); + } + + private function addService(string $id, Definition $definition): array + { + $this->definitionVariables = new \SplObjectStorage(); + $this->referenceVariables = []; + $this->variableCount = 0; + $this->referenceVariables[$id] = new Variable('instance'); + + $return = []; + + if ($class = $definition->getClass()) { + $class = $class instanceof Parameter ? '%'.$class.'%' : $this->container->resolveEnvPlaceholders($class); + $return[] = sprintf(0 === strpos($class, '%') ? '@return object A %1$s instance' : '@return \%s', ltrim($class, '\\')); + } elseif ($definition->getFactory()) { + $factory = $definition->getFactory(); + if (\is_string($factory)) { + $return[] = sprintf('@return object An instance returned by %s()', $factory); + } elseif (\is_array($factory) && (\is_string($factory[0]) || $factory[0] instanceof Definition || $factory[0] instanceof Reference)) { + $class = $factory[0] instanceof Definition ? $factory[0]->getClass() : (string) $factory[0]; + $class = $class instanceof Parameter ? '%'.$class.'%' : $this->container->resolveEnvPlaceholders($class); + $return[] = sprintf('@return object An instance returned by %s::%s()', $class, $factory[1]); + } + } + + if ($definition->isDeprecated()) { + if ($return && 0 === strpos($return[\count($return) - 1], '@return')) { + $return[] = ''; + } + + $return[] = sprintf('@deprecated %s', $definition->getDeprecationMessage($id)); + } + + $return = str_replace("\n * \n", "\n *\n", implode("\n * ", $return)); + $return = $this->container->resolveEnvPlaceholders($return); + + $shared = $definition->isShared() ? ' shared' : ''; + $public = $definition->isPublic() ? 'public' : 'private'; + $autowired = $definition->isAutowired() ? ' autowired' : ''; + + if ($definition->isLazy()) { + $lazyInitialization = '$lazyLoad = true'; + } else { + $lazyInitialization = ''; + } + + $asFile = $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition); + $methodName = $this->generateMethodName($id); + if ($asFile) { + $file = $methodName.'.php'; + $code = " // Returns the $public '$id'$shared$autowired service.\n\n"; + } else { + $file = null; + $code = <<docStar} + * Gets the $public '$id'$shared$autowired service. + * + * $return +EOF; + $code = str_replace('*/', ' ', $code).<<serviceCalls = []; + $this->inlinedDefinitions = $this->getDefinitionsFromArguments([$definition], null, $this->serviceCalls); + + if ($definition->isDeprecated()) { + $code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id))); + } + + if ($this->getProxyDumper()->isProxyCandidate($definition)) { + $factoryCode = $asFile ? ($definition->isShared() ? "\$this->load('%s.php', false)" : '$this->factories[%2$s](false)') : '$this->%s(false)'; + $code .= $this->getProxyDumper()->getProxyFactoryCode($definition, $id, sprintf($factoryCode, $methodName, $this->doExport($id))); + } + + $code .= $this->addServiceInclude($id, $definition); + $code .= $this->addInlineService($id, $definition); + + if ($asFile) { + $code = implode("\n", array_map(function ($line) { return $line ? substr($line, 8) : $line; }, explode("\n", $code))); + } else { + $code .= " }\n"; + } + + $this->definitionVariables = $this->inlinedDefinitions = null; + $this->referenceVariables = $this->serviceCalls = null; + + return [$file, $code]; + } + + private function addInlineVariables(string $id, Definition $definition, array $arguments, bool $forConstructor): string + { + $code = ''; + + foreach ($arguments as $argument) { + if (\is_array($argument)) { + $code .= $this->addInlineVariables($id, $definition, $argument, $forConstructor); + } elseif ($argument instanceof Reference) { + $code .= $this->addInlineReference($id, $definition, $argument, $forConstructor); + } elseif ($argument instanceof Definition) { + $code .= $this->addInlineService($id, $definition, $argument, $forConstructor); + } + } + + return $code; + } + + private function addInlineReference(string $id, Definition $definition, string $targetId, bool $forConstructor): string + { + while ($this->container->hasAlias($targetId)) { + $targetId = (string) $this->container->getAlias($targetId); + } + + list($callCount, $behavior) = $this->serviceCalls[$targetId]; + + if ($id === $targetId) { + return $this->addInlineService($id, $definition, $definition); + } + + if ('service_container' === $targetId || isset($this->referenceVariables[$targetId])) { + return ''; + } + + $hasSelfRef = isset($this->circularReferences[$id][$targetId]) && !isset($this->definitionVariables[$definition]); + + if ($hasSelfRef && !$forConstructor && !$forConstructor = !$this->circularReferences[$id][$targetId]) { + $code = $this->addInlineService($id, $definition, $definition); + } else { + $code = ''; + } + + if (isset($this->referenceVariables[$targetId]) || (2 > $callCount && (!$hasSelfRef || !$forConstructor))) { + return $code; + } + + $name = $this->getNextVariableName(); + $this->referenceVariables[$targetId] = new Variable($name); + + $reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $behavior ? new Reference($targetId, $behavior) : null; + $code .= sprintf(" \$%s = %s;\n", $name, $this->getServiceCall($targetId, $reference)); + + if (!$hasSelfRef || !$forConstructor) { + return $code; + } + + $code .= sprintf(<<<'EOTXT' + + if (isset($this->%s[%s])) { + return $this->%1$s[%2$s]; + } + +EOTXT + , + $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', + $this->doExport($id) + ); + + return $code; + } + + private function addInlineService(string $id, Definition $definition, Definition $inlineDef = null, bool $forConstructor = true): string + { + $code = ''; + + if ($isSimpleInstance = $isRootInstance = null === $inlineDef) { + foreach ($this->serviceCalls as $targetId => list($callCount, $behavior, $byConstructor)) { + if ($byConstructor && isset($this->circularReferences[$id][$targetId]) && !$this->circularReferences[$id][$targetId]) { + $code .= $this->addInlineReference($id, $definition, $targetId, $forConstructor); + } + } + } + + if (isset($this->definitionVariables[$inlineDef = $inlineDef ?: $definition])) { + return $code; + } + + $arguments = [$inlineDef->getArguments(), $inlineDef->getFactory()]; + + $code .= $this->addInlineVariables($id, $definition, $arguments, $forConstructor); + + if ($arguments = array_filter([$inlineDef->getProperties(), $inlineDef->getMethodCalls(), $inlineDef->getConfigurator()])) { + $isSimpleInstance = false; + } elseif ($definition !== $inlineDef && 2 > $this->inlinedDefinitions[$inlineDef]) { + return $code; + } + + if (isset($this->definitionVariables[$inlineDef])) { + $isSimpleInstance = false; + } else { + $name = $definition === $inlineDef ? 'instance' : $this->getNextVariableName(); + $this->definitionVariables[$inlineDef] = new Variable($name); + $code .= '' !== $code ? "\n" : ''; + + if ('instance' === $name) { + $code .= $this->addServiceInstance($id, $definition, $isSimpleInstance); + } else { + $code .= $this->addNewInstance($inlineDef, ' $'.$name.' = ', $id); + } + + if ('' !== $inline = $this->addInlineVariables($id, $definition, $arguments, false)) { + $code .= "\n".$inline."\n"; + } elseif ($arguments && 'instance' === $name) { + $code .= "\n"; + } + + $code .= $this->addServiceProperties($inlineDef, $name); + $code .= $this->addServiceMethodCalls($inlineDef, $name, !$this->getProxyDumper()->isProxyCandidate($inlineDef) && $inlineDef->isShared() && !isset($this->singleUsePrivateIds[$id]) ? $id : null); + $code .= $this->addServiceConfigurator($inlineDef, $name); + } + + if ($isRootInstance && !$isSimpleInstance) { + $code .= "\n return \$instance;\n"; + } + + return $code; + } + + private function addServices(array &$services = null): string + { + $publicServices = $privateServices = ''; + $definitions = $this->container->getDefinitions(); + ksort($definitions); + foreach ($definitions as $id => $definition) { + $services[$id] = $definition->isSynthetic() ? null : $this->addService($id, $definition); + } + + foreach ($definitions as $id => $definition) { + if (!(list($file, $code) = $services[$id]) || null !== $file) { + continue; + } + if ($definition->isPublic()) { + $publicServices .= $code; + } elseif (!$this->isTrivialInstance($definition) || isset($this->locatedIds[$id])) { + $privateServices .= $code; + } + } + + return $publicServices.$privateServices; + } + + private function generateServiceFiles(array $services): iterable + { + $definitions = $this->container->getDefinitions(); + ksort($definitions); + foreach ($definitions as $id => $definition) { + if ((list($file, $code) = $services[$id]) && null !== $file && ($definition->isPublic() || !$this->isTrivialInstance($definition) || isset($this->locatedIds[$id]))) { + if (!$definition->isShared()) { + $i = strpos($code, "\n\ninclude_once "); + if (false !== $i && false !== $i = strpos($code, "\n\n", 2 + $i)) { + $code = [substr($code, 0, 2 + $i), substr($code, 2 + $i)]; + } else { + $code = ["\n", $code]; + } + $code[1] = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $code[1]))); + $factory = sprintf('$this->factories%s[%s]', $definition->isPublic() ? '' : "['service_container']", $this->doExport($id)); + $lazyloadInitialization = $definition->isLazy() ? '$lazyLoad = true' : ''; + + $code[1] = sprintf("%s = function (%s) {\n%s};\n\nreturn %1\$s();\n", $factory, $lazyloadInitialization, $code[1]); + $code = $code[0].$code[1]; + } + + yield $file => $code; + } + } + } + + private function addNewInstance(Definition $definition, string $return = '', string $id = null): string + { + $tail = $return ? ";\n" : ''; + + if (BaseServiceLocator::class === $definition->getClass() && $definition->hasTag($this->serviceLocatorTag)) { + $arguments = []; + foreach ($definition->getArgument(0) as $k => $argument) { + $arguments[$k] = $argument->getValues()[0]; + } + + return $return.$this->dumpValue(new ServiceLocatorArgument($arguments)).$tail; + } + + $arguments = []; + foreach ($definition->getArguments() as $value) { + $arguments[] = $this->dumpValue($value); + } + + if (null !== $definition->getFactory()) { + $callable = $definition->getFactory(); + + if (\is_array($callable)) { + if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $callable[1])) { + throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s)', $callable[1] ?: 'n/a')); + } + + if ($callable[0] instanceof Reference + || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) { + return $return.sprintf('%s->%s(%s)', $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : '').$tail; + } + + $class = $this->dumpValue($callable[0]); + // If the class is a string we can optimize away + if (0 === strpos($class, "'") && false === strpos($class, '$')) { + if ("''" === $class) { + throw new RuntimeException(sprintf('Cannot dump definition: %s service is defined to be created by a factory but is missing the service reference, did you forget to define the factory service id or class?', $id ? 'The "'.$id.'"' : 'inline')); + } + + return $return.sprintf('%s::%s(%s)', $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : '').$tail; + } + + if (0 === strpos($class, 'new ')) { + return $return.sprintf('(%s)->%s(%s)', $class, $callable[1], $arguments ? implode(', ', $arguments) : '').$tail; + } + + return $return.sprintf("[%s, '%s'](%s)", $class, $callable[1], $arguments ? implode(', ', $arguments) : '').$tail; + } + + return $return.sprintf('%s(%s)', $this->dumpLiteralClass($this->dumpValue($callable)), $arguments ? implode(', ', $arguments) : '').$tail; + } + + if (null === $class = $definition->getClass()) { + throw new RuntimeException('Cannot dump definitions which have no class nor factory.'); + } + + return $return.sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments)).$tail; + } + + private function startClass(string $class, string $baseClass, ?array &$preload): string + { + $namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : ''; + + $code = <<docStar} + * This class has been auto-generated + * by the Symfony Dependency Injection Component. + * + * @final + */ +class $class extends $baseClass +{ + private \$parameters = []; + + public function __construct() + { + +EOF; + if ($this->asFiles) { + $code = str_replace('$parameters', "\$buildParameters;\n private \$containerDir;\n private \$parameters", $code); + $code = str_replace('__construct()', '__construct(array $buildParameters = [], $containerDir = __DIR__)', $code); + $code .= " \$this->buildParameters = \$buildParameters;\n"; + $code .= " \$this->containerDir = \$containerDir;\n"; + + if (null !== $this->targetDirRegex) { + $code = str_replace('$parameters', "\$targetDir;\n private \$parameters", $code); + $code .= ' $this->targetDir = \\dirname($containerDir);'."\n"; + } + } + + if (Container::class !== $this->baseClass) { + $r = $this->container->getReflectionClass($this->baseClass, false); + if (null !== $r + && (null !== $constructor = $r->getConstructor()) + && 0 === $constructor->getNumberOfRequiredParameters() + && Container::class !== $constructor->getDeclaringClass()->name + ) { + $code .= " parent::__construct();\n"; + $code .= " \$this->parameterBag = null;\n\n"; + } + } + + if ($this->container->getParameterBag()->all()) { + $code .= " \$this->parameters = \$this->getDefaultParameters();\n\n"; + } + $code .= " \$this->services = \$this->privates = [];\n"; + + $code .= $this->addSyntheticIds(); + $code .= $this->addMethodMap(); + $code .= $this->asFiles && !$this->inlineFactories ? $this->addFileMap() : ''; + $code .= $this->addAliases(); + $code .= $this->addInlineRequires($preload); + $code .= <<addRemovedIds(); + + if ($this->asFiles && !$this->inlineFactories) { + $code .= <<containerDir.\\DIRECTORY_SEPARATOR.\$file; + } + +EOF; + } + + $proxyDumper = $this->getProxyDumper(); + foreach ($this->container->getDefinitions() as $definition) { + if (!$proxyDumper->isProxyCandidate($definition)) { + continue; + } + if ($this->asFiles && !$this->inlineFactories) { + $proxyLoader = '$this->load("{$class}.php")'; + } elseif ($this->namespace || $this->inlineFactories) { + $proxyLoader = 'class_alias(__NAMESPACE__."\\\\$class", $class, false)'; + } else { + $proxyLoader = ''; + } + if ($proxyLoader) { + $proxyLoader = "class_exists(\$class, false) || {$proxyLoader};\n\n "; + } + $code .= <<container->getDefinitions(); + ksort($definitions); + foreach ($definitions as $id => $definition) { + if ($definition->isSynthetic() && 'service_container' !== $id) { + $code .= ' '.$this->doExport($id)." => true,\n"; + } + } + + return $code ? " \$this->syntheticIds = [\n{$code} ];\n" : ''; + } + + private function addRemovedIds(): string + { + $ids = $this->container->getRemovedIds(); + foreach ($this->container->getDefinitions() as $id => $definition) { + if (!$definition->isPublic()) { + $ids[$id] = true; + } + } + if (!$ids) { + return ''; + } + if ($this->asFiles) { + $code = "require \$this->containerDir.\\DIRECTORY_SEPARATOR.'removed-ids.php'"; + } else { + $code = ''; + $ids = array_keys($ids); + sort($ids); + foreach ($ids as $id) { + if (preg_match(FileLoader::ANONYMOUS_ID_REGEXP, $id)) { + continue; + } + $code .= ' '.$this->doExport($id)." => true,\n"; + } + + $code = "[\n{$code} ]"; + } + + return <<container->getDefinitions(); + ksort($definitions); + foreach ($definitions as $id => $definition) { + if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || $this->inlineFactories || $this->isHotPath($definition))) { + $code .= ' '.$this->doExport($id).' => '.$this->doExport($this->generateMethodName($id)).",\n"; + } + } + + $aliases = $this->container->getAliases(); + foreach ($aliases as $alias => $id) { + if (!$id->isDeprecated()) { + continue; + } + $code .= ' '.$this->doExport($alias).' => '.$this->doExport($this->generateMethodName($alias)).",\n"; + } + + return $code ? " \$this->methodMap = [\n{$code} ];\n" : ''; + } + + private function addFileMap(): string + { + $code = ''; + $definitions = $this->container->getDefinitions(); + ksort($definitions); + foreach ($definitions as $id => $definition) { + if (!$definition->isSynthetic() && $definition->isPublic() && !$this->isHotPath($definition)) { + $code .= sprintf(" %s => '%s.php',\n", $this->doExport($id), $this->generateMethodName($id)); + } + } + + return $code ? " \$this->fileMap = [\n{$code} ];\n" : ''; + } + + private function addAliases(): string + { + if (!$aliases = $this->container->getAliases()) { + return "\n \$this->aliases = [];\n"; + } + + $code = " \$this->aliases = [\n"; + ksort($aliases); + foreach ($aliases as $alias => $id) { + if ($id->isDeprecated()) { + continue; + } + + $id = (string) $id; + while (isset($aliases[$id])) { + $id = (string) $aliases[$id]; + } + $code .= ' '.$this->doExport($alias).' => '.$this->doExport($id).",\n"; + } + + return $code." ];\n"; + } + + private function addDeprecatedAliases(): string + { + $code = ''; + $aliases = $this->container->getAliases(); + foreach ($aliases as $alias => $definition) { + if (!$definition->isDeprecated()) { + continue; + } + $public = $definition->isPublic() ? 'public' : 'private'; + $id = (string) $definition; + $methodNameAlias = $this->generateMethodName($alias); + $idExported = $this->export($id); + $messageExported = $this->export($definition->getDeprecationMessage($alias)); + $code .= <<docStar} + * Gets the $public '$alias' alias. + * + * @return object The "$id" service. + */ + protected function {$methodNameAlias}() + { + @trigger_error($messageExported, E_USER_DEPRECATED); + + return \$this->get($idExported); + } + +EOF; + } + + return $code; + } + + private function addInlineRequires(?array &$preload): string + { + if (!$this->hotPathTag || !$this->inlineRequires) { + return ''; + } + + $lineage = []; + + foreach ($this->container->findTaggedServiceIds($this->hotPathTag) as $id => $tags) { + $definition = $this->container->getDefinition($id); + + if ($this->getProxyDumper()->isProxyCandidate($definition)) { + continue; + } + + $inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]); + + foreach ($inlinedDefinitions as $def) { + if (\is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) { + $preload[$class] = $class; + $this->collectLineage($class, $lineage); + } + } + } + + $code = ''; + + foreach ($lineage as $file) { + if (!isset($this->inlinedRequires[$file])) { + $this->inlinedRequires[$file] = true; + $code .= sprintf("\n include_once %s;", $file); + } + } + + return $code ? sprintf("\n \$this->privates['service_container'] = function () {%s\n };\n", $code) : ''; + } + + private function addDefaultParametersMethod(): string + { + if (!$this->container->getParameterBag()->all()) { + return ''; + } + + $php = []; + $dynamicPhp = []; + + foreach ($this->container->getParameterBag()->all() as $key => $value) { + if ($key !== $resolvedKey = $this->container->resolveEnvPlaceholders($key)) { + throw new InvalidArgumentException(sprintf('Parameter name cannot use env parameters: %s.', $resolvedKey)); + } + $export = $this->exportParameters([$value]); + $export = explode('0 => ', substr(rtrim($export, " ]\n"), 2, -1), 2); + + if (preg_match("/\\\$this->(?:getEnv\('(?:\w++:)*+\w++'\)|targetDir\.'')/", $export[1])) { + $dynamicPhp[$key] = sprintf('%scase %s: $value = %s; break;', $export[0], $this->export($key), $export[1]); + } else { + $php[] = sprintf('%s%s => %s,', $export[0], $this->export($key), $export[1]); + } + } + $parameters = sprintf("[\n%s\n%s]", implode("\n", $php), str_repeat(' ', 8)); + + $code = <<<'EOF' + + public function getParameter(string $name) + { + if (isset($this->buildParameters[$name])) { + return $this->buildParameters[$name]; + } + + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } + if (isset($this->loadedDynamicParameters[$name])) { + return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + + return $this->parameters[$name]; + } + + public function hasParameter(string $name): bool + { + if (isset($this->buildParameters[$name])) { + return true; + } + + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); + } + + public function setParameter(string $name, $value): void + { + throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); + } + + public function getParameterBag(): ParameterBagInterface + { + if (null === $this->parameterBag) { + $parameters = $this->parameters; + foreach ($this->loadedDynamicParameters as $name => $loaded) { + $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + foreach ($this->buildParameters as $name => $value) { + $parameters[$name] = $value; + } + $this->parameterBag = new FrozenParameterBag($parameters); + } + + return $this->parameterBag; + } + +EOF; + if (!$this->asFiles) { + $code = preg_replace('/^.*buildParameters.*\n.*\n.*\n\n?/m', '', $code); + } + + if ($dynamicPhp) { + $loadedDynamicParameters = $this->exportParameters(array_combine(array_keys($dynamicPhp), array_fill(0, \count($dynamicPhp), false)), '', 8); + $getDynamicParameter = <<<'EOF' + switch ($name) { +%s + default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%%s" must be defined.', $name)); + } + $this->loadedDynamicParameters[$name] = true; + + return $this->dynamicParameters[$name] = $value; +EOF; + $getDynamicParameter = sprintf($getDynamicParameter, implode("\n", $dynamicPhp)); + } else { + $loadedDynamicParameters = '[]'; + $getDynamicParameter = str_repeat(' ', 8).'throw new InvalidArgumentException(sprintf(\'The dynamic parameter "%s" must be defined.\', $name));'; + } + + $code .= << $value) { + if (\is_array($value)) { + $value = $this->exportParameters($value, $path.'/'.$key, $indent + 4); + } elseif ($value instanceof ArgumentInterface) { + throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain special arguments. "%s" found in "%s".', \get_class($value), $path.'/'.$key)); + } elseif ($value instanceof Variable) { + throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain variable references. Variable "%s" found in "%s".', $value, $path.'/'.$key)); + } elseif ($value instanceof Definition) { + throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain service definitions. Definition for "%s" found in "%s".', $value->getClass(), $path.'/'.$key)); + } elseif ($value instanceof Reference) { + throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain references to other services (reference to service "%s" found in "%s").', $value, $path.'/'.$key)); + } elseif ($value instanceof Expression) { + throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain expressions. Expression "%s" found in "%s".', $value, $path.'/'.$key)); + } else { + $value = $this->export($value); + } + + $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), $this->export($key), $value); + } + + return sprintf("[\n%s\n%s]", implode("\n", $php), str_repeat(' ', $indent - 4)); + } + + private function endClass(): string + { + if ($this->addThrow) { + return <<<'EOF' + + protected function throw($message) + { + throw new RuntimeException($message); + } +} + +EOF; + } + + return <<<'EOF' +} + +EOF; + } + + private function wrapServiceConditionals($value, string $code): string + { + if (!$condition = $this->getServiceConditionals($value)) { + return $code; + } + + // re-indent the wrapped code + $code = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $code))); + + return sprintf(" if (%s) {\n%s }\n", $condition, $code); + } + + private function getServiceConditionals($value): string + { + $conditions = []; + foreach (ContainerBuilder::getInitializedConditionals($value) as $service) { + if (!$this->container->hasDefinition($service)) { + return 'false'; + } + $conditions[] = sprintf('isset($this->%s[%s])', $this->container->getDefinition($service)->isPublic() ? 'services' : 'privates', $this->doExport($service)); + } + foreach (ContainerBuilder::getServiceConditionals($value) as $service) { + if ($this->container->hasDefinition($service) && !$this->container->getDefinition($service)->isPublic()) { + continue; + } + + $conditions[] = sprintf('$this->has(%s)', $this->doExport($service)); + } + + if (!$conditions) { + return ''; + } + + return implode(' && ', $conditions); + } + + private function getDefinitionsFromArguments(array $arguments, \SplObjectStorage $definitions = null, array &$calls = [], bool $byConstructor = null): \SplObjectStorage + { + if (null === $definitions) { + $definitions = new \SplObjectStorage(); + } + + foreach ($arguments as $argument) { + if (\is_array($argument)) { + $this->getDefinitionsFromArguments($argument, $definitions, $calls, $byConstructor); + } elseif ($argument instanceof Reference) { + $id = (string) $argument; + + while ($this->container->hasAlias($id)) { + $id = (string) $this->container->getAlias($id); + } + + if (!isset($calls[$id])) { + $calls[$id] = [0, $argument->getInvalidBehavior(), $byConstructor]; + } else { + $calls[$id][1] = min($calls[$id][1], $argument->getInvalidBehavior()); + } + + ++$calls[$id][0]; + } elseif (!$argument instanceof Definition) { + // no-op + } elseif (isset($definitions[$argument])) { + $definitions[$argument] = 1 + $definitions[$argument]; + } else { + $definitions[$argument] = 1; + $arguments = [$argument->getArguments(), $argument->getFactory()]; + $this->getDefinitionsFromArguments($arguments, $definitions, $calls, null === $byConstructor || $byConstructor); + $arguments = [$argument->getProperties(), $argument->getMethodCalls(), $argument->getConfigurator()]; + $this->getDefinitionsFromArguments($arguments, $definitions, $calls, null !== $byConstructor && $byConstructor); + } + } + + return $definitions; + } + + /** + * @throws RuntimeException + */ + private function dumpValue($value, bool $interpolate = true): string + { + if (\is_array($value)) { + if ($value && $interpolate && false !== $param = array_search($value, $this->container->getParameterBag()->all(), true)) { + return $this->dumpValue("%$param%"); + } + $code = []; + foreach ($value as $k => $v) { + $code[] = sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate)); + } + + return sprintf('[%s]', implode(', ', $code)); + } elseif ($value instanceof ArgumentInterface) { + $scope = [$this->definitionVariables, $this->referenceVariables]; + $this->definitionVariables = $this->referenceVariables = null; + + try { + if ($value instanceof ServiceClosureArgument) { + $value = $value->getValues()[0]; + $code = $this->dumpValue($value, $interpolate); + + $returnedType = ''; + if ($value instanceof TypedReference) { + $returnedType = sprintf(': %s\%s', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $value->getInvalidBehavior() ? '' : '?', $value->getType()); + } + + $code = sprintf('return %s;', $code); + + return sprintf("function ()%s {\n %s\n }", $returnedType, $code); + } + + if ($value instanceof IteratorArgument) { + $operands = [0]; + $code = []; + $code[] = 'new RewindableGenerator(function () {'; + + if (!$values = $value->getValues()) { + $code[] = ' return new \EmptyIterator();'; + } else { + $countCode = []; + $countCode[] = 'function () {'; + + foreach ($values as $k => $v) { + ($c = $this->getServiceConditionals($v)) ? $operands[] = "(int) ($c)" : ++$operands[0]; + $v = $this->wrapServiceConditionals($v, sprintf(" yield %s => %s;\n", $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate))); + foreach (explode("\n", $v) as $v) { + if ($v) { + $code[] = ' '.$v; + } + } + } + + $countCode[] = sprintf(' return %s;', implode(' + ', $operands)); + $countCode[] = ' }'; + } + + $code[] = sprintf(' }, %s)', \count($operands) > 1 ? implode("\n", $countCode) : $operands[0]); + + return implode("\n", $code); + } + + if ($value instanceof ServiceLocatorArgument) { + $serviceMap = ''; + $serviceTypes = ''; + foreach ($value->getValues() as $k => $v) { + if (!$v) { + continue; + } + $definition = $this->container->findDefinition($id = (string) $v); + $load = !($definition->hasErrors() && $e = $definition->getErrors()) ? $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition) : reset($e); + $serviceMap .= sprintf("\n %s => [%s, %s, %s, %s],", + $this->export($k), + $this->export($definition->isShared() ? ($definition->isPublic() ? 'services' : 'privates') : false), + $this->doExport($id), + $this->export(ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $v->getInvalidBehavior() && !\is_string($load) ? $this->generateMethodName($id).($load ? '.php' : '') : null), + $this->export($load) + ); + $serviceTypes .= sprintf("\n %s => %s,", $this->export($k), $this->export($v instanceof TypedReference ? $v->getType() : '?')); + $this->locatedIds[$id] = true; + } + $this->addGetService = true; + + return sprintf('new \%s($this->getService, [%s%s], [%s%s])', ServiceLocator::class, $serviceMap, $serviceMap ? "\n " : '', $serviceTypes, $serviceTypes ? "\n " : ''); + } + } finally { + list($this->definitionVariables, $this->referenceVariables) = $scope; + } + } elseif ($value instanceof Definition) { + if ($value->hasErrors() && $e = $value->getErrors()) { + $this->addThrow = true; + + return sprintf('$this->throw(%s)', $this->export(reset($e))); + } + if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) { + return $this->dumpValue($this->definitionVariables[$value], $interpolate); + } + if ($value->getMethodCalls()) { + throw new RuntimeException('Cannot dump definitions which have method calls.'); + } + if ($value->getProperties()) { + throw new RuntimeException('Cannot dump definitions which have properties.'); + } + if (null !== $value->getConfigurator()) { + throw new RuntimeException('Cannot dump definitions which have a configurator.'); + } + + return $this->addNewInstance($value); + } elseif ($value instanceof Variable) { + return '$'.$value; + } elseif ($value instanceof Reference) { + $id = (string) $value; + + while ($this->container->hasAlias($id)) { + $id = (string) $this->container->getAlias($id); + } + + if (null !== $this->referenceVariables && isset($this->referenceVariables[$id])) { + return $this->dumpValue($this->referenceVariables[$id], $interpolate); + } + + return $this->getServiceCall($id, $value); + } elseif ($value instanceof Expression) { + return $this->getExpressionLanguage()->compile((string) $value, ['this' => 'container']); + } elseif ($value instanceof Parameter) { + return $this->dumpParameter($value); + } elseif (true === $interpolate && \is_string($value)) { + if (preg_match('/^%([^%]+)%$/', $value, $match)) { + // we do this to deal with non string values (Boolean, integer, ...) + // the preg_replace_callback converts them to strings + return $this->dumpParameter($match[1]); + } else { + $replaceParameters = function ($match) { + return "'.".$this->dumpParameter($match[2]).".'"; + }; + + $code = str_replace('%%', '%', preg_replace_callback('/(?export($value))); + + return $code; + } + } elseif (\is_object($value) || \is_resource($value)) { + throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); + } + + return $this->export($value); + } + + /** + * Dumps a string to a literal (aka PHP Code) class value. + * + * @throws RuntimeException + */ + private function dumpLiteralClass(string $class): string + { + if (false !== strpos($class, '$')) { + return sprintf('${($_ = %s) && false ?: "_"}', $class); + } + if (0 !== strpos($class, "'") || !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { + throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s)', $class ?: 'n/a')); + } + + $class = substr(str_replace('\\\\', '\\', $class), 1, -1); + + return 0 === strpos($class, '\\') ? $class : '\\'.$class; + } + + private function dumpParameter(string $name): string + { + if ($this->container->hasParameter($name)) { + $value = $this->container->getParameter($name); + $dumpedValue = $this->dumpValue($value, false); + + if (!$value || !\is_array($value)) { + return $dumpedValue; + } + + if (!preg_match("/\\\$this->(?:getEnv\('(?:\w++:)*+\w++'\)|targetDir\.'')/", $dumpedValue)) { + return sprintf('$this->parameters[%s]', $this->doExport($name)); + } + } + + return sprintf('$this->getParameter(%s)', $this->doExport($name)); + } + + private function getServiceCall(string $id, Reference $reference = null): string + { + while ($this->container->hasAlias($id)) { + $id = (string) $this->container->getAlias($id); + } + + if ('service_container' === $id) { + return '$this'; + } + + if ($this->container->hasDefinition($id) && $definition = $this->container->getDefinition($id)) { + if ($definition->isSynthetic()) { + $code = sprintf('$this->get(%s%s)', $this->doExport($id), null !== $reference ? ', '.$reference->getInvalidBehavior() : ''); + } elseif (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) { + $code = 'null'; + if (!$definition->isShared()) { + return $code; + } + } elseif ($this->isTrivialInstance($definition)) { + if ($definition->hasErrors() && $e = $definition->getErrors()) { + $this->addThrow = true; + + return sprintf('$this->throw(%s)', $this->export(reset($e))); + } + $code = $this->addNewInstance($definition, '', $id); + if ($definition->isShared() && !isset($this->singleUsePrivateIds[$id])) { + $code = sprintf('$this->%s[%s] = %s', $definition->isPublic() ? 'services' : 'privates', $this->doExport($id), $code); + } + $code = "($code)"; + } elseif ($this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition)) { + $code = sprintf("\$this->load('%s.php')", $this->generateMethodName($id)); + if (!$definition->isShared()) { + $factory = sprintf('$this->factories%s[%s]', $definition->isPublic() ? '' : "['service_container']", $this->doExport($id)); + $code = sprintf('(isset(%s) ? %1$s() : %s)', $factory, $code); + } + } else { + $code = sprintf('$this->%s()', $this->generateMethodName($id)); + } + if ($definition->isShared() && !isset($this->singleUsePrivateIds[$id])) { + $code = sprintf('($this->%s[%s] ?? %s)', $definition->isPublic() ? 'services' : 'privates', $this->doExport($id), $code); + } + + return $code; + } + if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) { + return 'null'; + } + if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $reference->getInvalidBehavior()) { + $code = sprintf('$this->get(%s, /* ContainerInterface::NULL_ON_INVALID_REFERENCE */ %d)', $this->doExport($id), ContainerInterface::NULL_ON_INVALID_REFERENCE); + } else { + $code = sprintf('$this->get(%s)', $this->doExport($id)); + } + + return sprintf('($this->services[%s] ?? %s)', $this->doExport($id), $code); + } + + /** + * Initializes the method names map to avoid conflicts with the Container methods. + */ + private function initializeMethodNamesMap(string $class) + { + $this->serviceIdToMethodNameMap = []; + $this->usedMethodNames = []; + + if ($reflectionClass = $this->container->getReflectionClass($class)) { + foreach ($reflectionClass->getMethods() as $method) { + $this->usedMethodNames[strtolower($method->getName())] = true; + } + } + } + + /** + * @throws InvalidArgumentException + */ + private function generateMethodName(string $id): string + { + if (isset($this->serviceIdToMethodNameMap[$id])) { + return $this->serviceIdToMethodNameMap[$id]; + } + + $i = strrpos($id, '\\'); + $name = Container::camelize(false !== $i && isset($id[1 + $i]) ? substr($id, 1 + $i) : $id); + $name = preg_replace('/[^a-zA-Z0-9_\x7f-\xff]/', '', $name); + $methodName = 'get'.$name.'Service'; + $suffix = 1; + + while (isset($this->usedMethodNames[strtolower($methodName)])) { + ++$suffix; + $methodName = 'get'.$name.$suffix.'Service'; + } + + $this->serviceIdToMethodNameMap[$id] = $methodName; + $this->usedMethodNames[strtolower($methodName)] = true; + + return $methodName; + } + + private function getNextVariableName(): string + { + $firstChars = self::FIRST_CHARS; + $firstCharsLength = \strlen($firstChars); + $nonFirstChars = self::NON_FIRST_CHARS; + $nonFirstCharsLength = \strlen($nonFirstChars); + + while (true) { + $name = ''; + $i = $this->variableCount; + + if ('' === $name) { + $name .= $firstChars[$i % $firstCharsLength]; + $i = (int) ($i / $firstCharsLength); + } + + while ($i > 0) { + --$i; + $name .= $nonFirstChars[$i % $nonFirstCharsLength]; + $i = (int) ($i / $nonFirstCharsLength); + } + + ++$this->variableCount; + + // check that the name is not reserved + if (\in_array($name, $this->reservedVariables, true)) { + continue; + } + + return $name; + } + } + + private function getExpressionLanguage(): ExpressionLanguage + { + if (null === $this->expressionLanguage) { + if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { + throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); + } + $providers = $this->container->getExpressionLanguageProviders(); + $this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) { + $id = '""' === substr_replace($arg, '', 1, -1) ? stripcslashes(substr($arg, 1, -1)) : null; + + if (null !== $id && ($this->container->hasAlias($id) || $this->container->hasDefinition($id))) { + return $this->getServiceCall($id); + } + + return sprintf('$this->get(%s)', $arg); + }); + + if ($this->container->isTrackingResources()) { + foreach ($providers as $provider) { + $this->container->addObjectResource($provider); + } + } + } + + return $this->expressionLanguage; + } + + private function isHotPath(Definition $definition): bool + { + return $this->hotPathTag && $definition->hasTag($this->hotPathTag) && !$definition->isDeprecated(); + } + + private function isSingleUsePrivateNode(ServiceReferenceGraphNode $node): bool + { + if ($node->getValue()->isPublic()) { + return false; + } + $ids = []; + foreach ($node->getInEdges() as $edge) { + if (!$value = $edge->getSourceNode()->getValue()) { + continue; + } + if ($edge->isLazy() || !$value instanceof Definition || !$value->isShared()) { + return false; + } + $ids[$edge->getSourceNode()->getId()] = true; + } + + return 1 === \count($ids); + } + + /** + * @return mixed + */ + private function export($value) + { + if (null !== $this->targetDirRegex && \is_string($value) && preg_match($this->targetDirRegex, $value, $matches, PREG_OFFSET_CAPTURE)) { + $prefix = $matches[0][1] ? $this->doExport(substr($value, 0, $matches[0][1]), true).'.' : ''; + $suffix = $matches[0][1] + \strlen($matches[0][0]); + $suffix = isset($value[$suffix]) ? '.'.$this->doExport(substr($value, $suffix), true) : ''; + $dirname = $this->asFiles ? '$this->containerDir' : '__DIR__'; + $offset = 1 + $this->targetDirMaxMatches - \count($matches); + + if (0 < $offset) { + $dirname = sprintf('\dirname(__DIR__, %d)', $offset + (int) $this->asFiles); + } elseif ($this->asFiles) { + $dirname = "\$this->targetDir.''"; // empty string concatenation on purpose + } + + if ($prefix || $suffix) { + return sprintf('(%s%s%s)', $prefix, $dirname, $suffix); + } + + return $dirname; + } + + return $this->doExport($value, true); + } + + /** + * @return mixed + */ + private function doExport($value, bool $resolveEnv = false) + { + $shouldCacheValue = $resolveEnv && \is_string($value); + if ($shouldCacheValue && isset($this->exportedVariables[$value])) { + return $this->exportedVariables[$value]; + } + if (\is_string($value) && false !== strpos($value, "\n")) { + $cleanParts = explode("\n", $value); + $cleanParts = array_map(function ($part) { return var_export($part, true); }, $cleanParts); + $export = implode('."\n".', $cleanParts); + } else { + $export = var_export($value, true); + } + + if ($resolveEnv && "'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$this->getEnv('string:%s').'")) { + $export = $resolvedExport; + if (".''" === substr($export, -3)) { + $export = substr($export, 0, -3); + if ("'" === $export[1]) { + $export = substr_replace($export, '', 18, 7); + } + } + if ("'" === $export[1]) { + $export = substr($export, 3); + } + } + + if ($shouldCacheValue) { + $this->exportedVariables[$value] = $export; + } + + return $export; + } + + private function getAutoloadFile(): ?string + { + if (null === $this->targetDirRegex) { + return null; + } + + foreach (spl_autoload_functions() as $autoloader) { + if (!\is_array($autoloader)) { + continue; + } + + if ($autoloader[0] instanceof DebugClassLoader || $autoloader[0] instanceof LegacyDebugClassLoader) { + $autoloader = $autoloader[0]->getClassLoader(); + } + + if (!\is_array($autoloader) || !$autoloader[0] instanceof ClassLoader || !$autoloader[0]->findFile(__CLASS__)) { + continue; + } + + foreach (get_declared_classes() as $class) { + if (0 === strpos($class, 'ComposerAutoloaderInit') && $class::getLoader() === $autoloader[0]) { + $file = \dirname((new \ReflectionClass($class))->getFileName(), 2).'/autoload.php'; + + if (preg_match($this->targetDirRegex.'A', $file)) { + return $file; + } + } + } + } + + return null; + } +} diff --git a/vendor/symfony/dependency-injection/Dumper/Preloader.php b/vendor/symfony/dependency-injection/Dumper/Preloader.php new file mode 100644 index 0000000..abb7d90 --- /dev/null +++ b/vendor/symfony/dependency-injection/Dumper/Preloader.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Dumper; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class Preloader +{ + public static function preload(array $classes) + { + set_error_handler(function ($t, $m, $f, $l) { + if (error_reporting() & $t) { + if (__FILE__ !== $f) { + throw new \ErrorException($m, 0, $t, $f, $l); + } + + throw new \ReflectionException($m); + } + }); + + $prev = []; + $preloaded = []; + + try { + while ($prev !== $classes) { + $prev = $classes; + foreach ($classes as $c) { + if (!isset($preloaded[$c])) { + self::doPreload($c, $preloaded); + } + } + $classes = array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits()); + } + } finally { + restore_error_handler(); + } + } + + private static function doPreload(string $class, array &$preloaded) + { + if (isset($preloaded[$class]) || \in_array($class, ['self', 'static', 'parent'], true)) { + return; + } + + $preloaded[$class] = true; + + try { + $r = new \ReflectionClass($class); + + if ($r->isInternal()) { + return; + } + + $r->getConstants(); + $r->getDefaultProperties(); + + if (\PHP_VERSION_ID >= 70400) { + foreach ($r->getProperties(\ReflectionProperty::IS_PUBLIC) as $p) { + if (($t = $p->getType()) && !$t->isBuiltin()) { + self::doPreload($t->getName(), $preloaded); + } + } + } + + foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $m) { + foreach ($m->getParameters() as $p) { + if ($p->isDefaultValueAvailable() && $p->isDefaultValueConstant()) { + $c = $p->getDefaultValueConstantName(); + + if ($i = strpos($c, '::')) { + self::doPreload(substr($c, 0, $i), $preloaded); + } + } + + if (($t = $p->getType()) && !$t->isBuiltin()) { + self::doPreload($t->getName(), $preloaded); + } + } + + if (($t = $m->getReturnType()) && !$t->isBuiltin()) { + self::doPreload($t->getName(), $preloaded); + } + } + } catch (\ReflectionException $e) { + // ignore missing classes + } + } +} diff --git a/vendor/symfony/dependency-injection/Dumper/XmlDumper.php b/vendor/symfony/dependency-injection/Dumper/XmlDumper.php new file mode 100644 index 0000000..fb5d827 --- /dev/null +++ b/vendor/symfony/dependency-injection/Dumper/XmlDumper.php @@ -0,0 +1,374 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Dumper; + +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Parameter; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\ExpressionLanguage\Expression; + +/** + * XmlDumper dumps a service container as an XML string. + * + * @author Fabien Potencier + * @author Martin Hasoň + */ +class XmlDumper extends Dumper +{ + /** + * @var \DOMDocument + */ + private $document; + + /** + * Dumps the service container as an XML string. + * + * @return string An xml string representing of the service container + */ + public function dump(array $options = []) + { + $this->document = new \DOMDocument('1.0', 'utf-8'); + $this->document->formatOutput = true; + + $container = $this->document->createElementNS('http://symfony.com/schema/dic/services', 'container'); + $container->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); + $container->setAttribute('xsi:schemaLocation', 'http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd'); + + $this->addParameters($container); + $this->addServices($container); + + $this->document->appendChild($container); + $xml = $this->document->saveXML(); + $this->document = null; + + return $this->container->resolveEnvPlaceholders($xml); + } + + private function addParameters(\DOMElement $parent) + { + $data = $this->container->getParameterBag()->all(); + if (!$data) { + return; + } + + if ($this->container->isCompiled()) { + $data = $this->escape($data); + } + + $parameters = $this->document->createElement('parameters'); + $parent->appendChild($parameters); + $this->convertParameters($data, 'parameter', $parameters); + } + + private function addMethodCalls(array $methodcalls, \DOMElement $parent) + { + foreach ($methodcalls as $methodcall) { + $call = $this->document->createElement('call'); + $call->setAttribute('method', $methodcall[0]); + if (\count($methodcall[1])) { + $this->convertParameters($methodcall[1], 'argument', $call); + } + if ($methodcall[2] ?? false) { + $call->setAttribute('returns-clone', 'true'); + } + $parent->appendChild($call); + } + } + + private function addService(Definition $definition, ?string $id, \DOMElement $parent) + { + $service = $this->document->createElement('service'); + if (null !== $id) { + $service->setAttribute('id', $id); + } + if ($class = $definition->getClass()) { + if ('\\' === substr($class, 0, 1)) { + $class = substr($class, 1); + } + + $service->setAttribute('class', $class); + } + if (!$definition->isShared()) { + $service->setAttribute('shared', 'false'); + } + if (!$definition->isPrivate()) { + $service->setAttribute('public', $definition->isPublic() ? 'true' : 'false'); + } + if ($definition->isSynthetic()) { + $service->setAttribute('synthetic', 'true'); + } + if ($definition->isLazy()) { + $service->setAttribute('lazy', 'true'); + } + if (null !== $decoratedService = $definition->getDecoratedService()) { + list($decorated, $renamedId, $priority) = $decoratedService; + $service->setAttribute('decorates', $decorated); + + $decorationOnInvalid = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + if (\in_array($decorationOnInvalid, [ContainerInterface::IGNORE_ON_INVALID_REFERENCE, ContainerInterface::NULL_ON_INVALID_REFERENCE], true)) { + $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE === $decorationOnInvalid ? 'null' : 'ignore'; + $service->setAttribute('decoration-on-invalid', $invalidBehavior); + } + if (null !== $renamedId) { + $service->setAttribute('decoration-inner-name', $renamedId); + } + if (0 !== $priority) { + $service->setAttribute('decoration-priority', $priority); + } + } + + foreach ($definition->getTags() as $name => $tags) { + foreach ($tags as $attributes) { + $tag = $this->document->createElement('tag'); + $tag->setAttribute('name', $name); + foreach ($attributes as $key => $value) { + $tag->setAttribute($key, $value); + } + $service->appendChild($tag); + } + } + + if ($definition->getFile()) { + $file = $this->document->createElement('file'); + $file->appendChild($this->document->createTextNode($definition->getFile())); + $service->appendChild($file); + } + + if ($parameters = $definition->getArguments()) { + $this->convertParameters($parameters, 'argument', $service); + } + + if ($parameters = $definition->getProperties()) { + $this->convertParameters($parameters, 'property', $service, 'name'); + } + + $this->addMethodCalls($definition->getMethodCalls(), $service); + + if ($callable = $definition->getFactory()) { + $factory = $this->document->createElement('factory'); + + if (\is_array($callable) && $callable[0] instanceof Definition) { + $this->addService($callable[0], null, $factory); + $factory->setAttribute('method', $callable[1]); + } elseif (\is_array($callable)) { + if (null !== $callable[0]) { + $factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); + } + $factory->setAttribute('method', $callable[1]); + } else { + $factory->setAttribute('function', $callable); + } + $service->appendChild($factory); + } + + if ($definition->isDeprecated()) { + $deprecated = $this->document->createElement('deprecated'); + $deprecated->appendChild($this->document->createTextNode($definition->getDeprecationMessage('%service_id%'))); + + $service->appendChild($deprecated); + } + + if ($definition->isAutowired()) { + $service->setAttribute('autowire', 'true'); + } + + if ($definition->isAutoconfigured()) { + $service->setAttribute('autoconfigure', 'true'); + } + + if ($definition->isAbstract()) { + $service->setAttribute('abstract', 'true'); + } + + if ($callable = $definition->getConfigurator()) { + $configurator = $this->document->createElement('configurator'); + + if (\is_array($callable) && $callable[0] instanceof Definition) { + $this->addService($callable[0], null, $configurator); + $configurator->setAttribute('method', $callable[1]); + } elseif (\is_array($callable)) { + $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); + $configurator->setAttribute('method', $callable[1]); + } else { + $configurator->setAttribute('function', $callable); + } + $service->appendChild($configurator); + } + + $parent->appendChild($service); + } + + private function addServiceAlias(string $alias, Alias $id, \DOMElement $parent) + { + $service = $this->document->createElement('service'); + $service->setAttribute('id', $alias); + $service->setAttribute('alias', $id); + if (!$id->isPrivate()) { + $service->setAttribute('public', $id->isPublic() ? 'true' : 'false'); + } + + if ($id->isDeprecated()) { + $deprecated = $this->document->createElement('deprecated'); + $deprecated->appendChild($this->document->createTextNode($id->getDeprecationMessage('%alias_id%'))); + + $service->appendChild($deprecated); + } + + $parent->appendChild($service); + } + + private function addServices(\DOMElement $parent) + { + $definitions = $this->container->getDefinitions(); + if (!$definitions) { + return; + } + + $services = $this->document->createElement('services'); + foreach ($definitions as $id => $definition) { + $this->addService($definition, $id, $services); + } + + $aliases = $this->container->getAliases(); + foreach ($aliases as $alias => $id) { + while (isset($aliases[(string) $id])) { + $id = $aliases[(string) $id]; + } + $this->addServiceAlias($alias, $id, $services); + } + $parent->appendChild($services); + } + + private function convertParameters(array $parameters, string $type, \DOMElement $parent, string $keyAttribute = 'key') + { + $withKeys = array_keys($parameters) !== range(0, \count($parameters) - 1); + foreach ($parameters as $key => $value) { + $element = $this->document->createElement($type); + if ($withKeys) { + $element->setAttribute($keyAttribute, $key); + } + + if ($value instanceof ServiceClosureArgument) { + $value = $value->getValues()[0]; + } + if (\is_array($tag = $value)) { + $element->setAttribute('type', 'collection'); + $this->convertParameters($value, $type, $element, 'key'); + } elseif ($value instanceof TaggedIteratorArgument || ($value instanceof ServiceLocatorArgument && $tag = $value->getTaggedIteratorArgument())) { + $element->setAttribute('type', $value instanceof TaggedIteratorArgument ? 'tagged_iterator' : 'tagged_locator'); + $element->setAttribute('tag', $tag->getTag()); + + if (null !== $tag->getIndexAttribute()) { + $element->setAttribute('index-by', $tag->getIndexAttribute()); + + if (null !== $tag->getDefaultIndexMethod()) { + $element->setAttribute('default-index-method', $tag->getDefaultIndexMethod()); + } + if (null !== $tag->getDefaultPriorityMethod()) { + $element->setAttribute('default-priority-method', $tag->getDefaultPriorityMethod()); + } + } + } elseif ($value instanceof IteratorArgument) { + $element->setAttribute('type', 'iterator'); + $this->convertParameters($value->getValues(), $type, $element, 'key'); + } elseif ($value instanceof ServiceLocatorArgument) { + $element->setAttribute('type', 'service_locator'); + $this->convertParameters($value->getValues(), $type, $element, 'key'); + } elseif ($value instanceof Reference) { + $element->setAttribute('type', 'service'); + $element->setAttribute('id', (string) $value); + $behavior = $value->getInvalidBehavior(); + if (ContainerInterface::NULL_ON_INVALID_REFERENCE == $behavior) { + $element->setAttribute('on-invalid', 'null'); + } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE == $behavior) { + $element->setAttribute('on-invalid', 'ignore'); + } elseif (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE == $behavior) { + $element->setAttribute('on-invalid', 'ignore_uninitialized'); + } + } elseif ($value instanceof Definition) { + $element->setAttribute('type', 'service'); + $this->addService($value, null, $element); + } elseif ($value instanceof Expression) { + $element->setAttribute('type', 'expression'); + $text = $this->document->createTextNode(self::phpToXml((string) $value)); + $element->appendChild($text); + } elseif (\is_string($value) && !preg_match('/^[^\x00-\x08\x0B\x0E-\x1A\x1C-\x1F\x7F]*+$/u', $value)) { + $element->setAttribute('type', 'binary'); + $text = $this->document->createTextNode(self::phpToXml(base64_encode($value))); + $element->appendChild($text); + } else { + if (\in_array($value, ['null', 'true', 'false'], true)) { + $element->setAttribute('type', 'string'); + } + + if (\is_string($value) && (is_numeric($value) || preg_match('/^0b[01]*$/', $value) || preg_match('/^0x[0-9a-f]++$/i', $value))) { + $element->setAttribute('type', 'string'); + } + + $text = $this->document->createTextNode(self::phpToXml($value)); + $element->appendChild($text); + } + $parent->appendChild($element); + } + } + + /** + * Escapes arguments. + */ + private function escape(array $arguments): array + { + $args = []; + foreach ($arguments as $k => $v) { + if (\is_array($v)) { + $args[$k] = $this->escape($v); + } elseif (\is_string($v)) { + $args[$k] = str_replace('%', '%%', $v); + } else { + $args[$k] = $v; + } + } + + return $args; + } + + /** + * Converts php types to xml types. + * + * @param mixed $value Value to convert + * + * @throws RuntimeException When trying to dump object or resource + */ + public static function phpToXml($value): string + { + switch (true) { + case null === $value: + return 'null'; + case true === $value: + return 'true'; + case false === $value: + return 'false'; + case $value instanceof Parameter: + return '%'.$value.'%'; + case \is_object($value) || \is_resource($value): + throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); + default: + return (string) $value; + } + } +} diff --git a/vendor/symfony/dependency-injection/Dumper/YamlDumper.php b/vendor/symfony/dependency-injection/Dumper/YamlDumper.php new file mode 100644 index 0000000..ccb68ee --- /dev/null +++ b/vendor/symfony/dependency-injection/Dumper/YamlDumper.php @@ -0,0 +1,349 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Dumper; + +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\LogicException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Parameter; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\ExpressionLanguage\Expression; +use Symfony\Component\Yaml\Dumper as YmlDumper; +use Symfony\Component\Yaml\Parser; +use Symfony\Component\Yaml\Tag\TaggedValue; +use Symfony\Component\Yaml\Yaml; + +/** + * YamlDumper dumps a service container as a YAML string. + * + * @author Fabien Potencier + */ +class YamlDumper extends Dumper +{ + private $dumper; + + /** + * Dumps the service container as an YAML string. + * + * @return string A YAML string representing of the service container + */ + public function dump(array $options = []) + { + if (!class_exists('Symfony\Component\Yaml\Dumper')) { + throw new LogicException('Unable to dump the container as the Symfony Yaml Component is not installed.'); + } + + if (null === $this->dumper) { + $this->dumper = new YmlDumper(); + } + + return $this->container->resolveEnvPlaceholders($this->addParameters()."\n".$this->addServices()); + } + + private function addService(string $id, Definition $definition): string + { + $code = " $id:\n"; + if ($class = $definition->getClass()) { + if ('\\' === substr($class, 0, 1)) { + $class = substr($class, 1); + } + + $code .= sprintf(" class: %s\n", $this->dumper->dump($class)); + } + + if (!$definition->isPrivate()) { + $code .= sprintf(" public: %s\n", $definition->isPublic() ? 'true' : 'false'); + } + + $tagsCode = ''; + foreach ($definition->getTags() as $name => $tags) { + foreach ($tags as $attributes) { + $att = []; + foreach ($attributes as $key => $value) { + $att[] = sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value)); + } + $att = $att ? ', '.implode(', ', $att) : ''; + + $tagsCode .= sprintf(" - { name: %s%s }\n", $this->dumper->dump($name), $att); + } + } + if ($tagsCode) { + $code .= " tags:\n".$tagsCode; + } + + if ($definition->getFile()) { + $code .= sprintf(" file: %s\n", $this->dumper->dump($definition->getFile())); + } + + if ($definition->isSynthetic()) { + $code .= " synthetic: true\n"; + } + + if ($definition->isDeprecated()) { + $code .= sprintf(" deprecated: %s\n", $this->dumper->dump($definition->getDeprecationMessage('%service_id%'))); + } + + if ($definition->isAutowired()) { + $code .= " autowire: true\n"; + } + + if ($definition->isAutoconfigured()) { + $code .= " autoconfigure: true\n"; + } + + if ($definition->isAbstract()) { + $code .= " abstract: true\n"; + } + + if ($definition->isLazy()) { + $code .= " lazy: true\n"; + } + + if ($definition->getArguments()) { + $code .= sprintf(" arguments: %s\n", $this->dumper->dump($this->dumpValue($definition->getArguments()), 0)); + } + + if ($definition->getProperties()) { + $code .= sprintf(" properties: %s\n", $this->dumper->dump($this->dumpValue($definition->getProperties()), 0)); + } + + if ($definition->getMethodCalls()) { + $code .= sprintf(" calls:\n%s\n", $this->dumper->dump($this->dumpValue($definition->getMethodCalls()), 1, 12)); + } + + if (!$definition->isShared()) { + $code .= " shared: false\n"; + } + + if (null !== $decoratedService = $definition->getDecoratedService()) { + list($decorated, $renamedId, $priority) = $decoratedService; + $code .= sprintf(" decorates: %s\n", $decorated); + if (null !== $renamedId) { + $code .= sprintf(" decoration_inner_name: %s\n", $renamedId); + } + if (0 !== $priority) { + $code .= sprintf(" decoration_priority: %s\n", $priority); + } + + $decorationOnInvalid = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + if (\in_array($decorationOnInvalid, [ContainerInterface::IGNORE_ON_INVALID_REFERENCE, ContainerInterface::NULL_ON_INVALID_REFERENCE])) { + $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE === $decorationOnInvalid ? 'null' : 'ignore'; + $code .= sprintf(" decoration_on_invalid: %s\n", $invalidBehavior); + } + } + + if ($callable = $definition->getFactory()) { + $code .= sprintf(" factory: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0)); + } + + if ($callable = $definition->getConfigurator()) { + $code .= sprintf(" configurator: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0)); + } + + return $code; + } + + private function addServiceAlias(string $alias, Alias $id): string + { + $deprecated = $id->isDeprecated() ? sprintf(" deprecated: %s\n", $id->getDeprecationMessage('%alias_id%')) : ''; + + if ($id->isPrivate()) { + return sprintf(" %s: '@%s'\n%s", $alias, $id, $deprecated); + } + + return sprintf(" %s:\n alias: %s\n public: %s\n%s", $alias, $id, $id->isPublic() ? 'true' : 'false', $deprecated); + } + + private function addServices(): string + { + if (!$this->container->getDefinitions()) { + return ''; + } + + $code = "services:\n"; + foreach ($this->container->getDefinitions() as $id => $definition) { + $code .= $this->addService($id, $definition); + } + + $aliases = $this->container->getAliases(); + foreach ($aliases as $alias => $id) { + while (isset($aliases[(string) $id])) { + $id = $aliases[(string) $id]; + } + $code .= $this->addServiceAlias($alias, $id); + } + + return $code; + } + + private function addParameters(): string + { + if (!$this->container->getParameterBag()->all()) { + return ''; + } + + $parameters = $this->prepareParameters($this->container->getParameterBag()->all(), $this->container->isCompiled()); + + return $this->dumper->dump(['parameters' => $parameters], 2); + } + + /** + * Dumps callable to YAML format. + * + * @param mixed $callable + * + * @return mixed + */ + private function dumpCallable($callable) + { + if (\is_array($callable)) { + if ($callable[0] instanceof Reference) { + $callable = [$this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]]; + } else { + $callable = [$callable[0], $callable[1]]; + } + } + + return $callable; + } + + /** + * Dumps the value to YAML format. + * + * @return mixed + * + * @throws RuntimeException When trying to dump object or resource + */ + private function dumpValue($value) + { + if ($value instanceof ServiceClosureArgument) { + $value = $value->getValues()[0]; + } + if ($value instanceof ArgumentInterface) { + $tag = $value; + + if ($value instanceof TaggedIteratorArgument || ($value instanceof ServiceLocatorArgument && $tag = $value->getTaggedIteratorArgument())) { + if (null === $tag->getIndexAttribute()) { + $content = $tag->getTag(); + } else { + $content = [ + 'tag' => $tag->getTag(), + 'index_by' => $tag->getIndexAttribute(), + ]; + + if (null !== $tag->getDefaultIndexMethod()) { + $content['default_index_method'] = $tag->getDefaultIndexMethod(); + } + if (null !== $tag->getDefaultPriorityMethod()) { + $content['default_priority_method'] = $tag->getDefaultPriorityMethod(); + } + } + + return new TaggedValue($value instanceof TaggedIteratorArgument ? 'tagged_iterator' : 'tagged_locator', $content); + } + + if ($value instanceof IteratorArgument) { + $tag = 'iterator'; + } elseif ($value instanceof ServiceLocatorArgument) { + $tag = 'service_locator'; + } else { + throw new RuntimeException(sprintf('Unspecified Yaml tag for type "%s".', \get_class($value))); + } + + return new TaggedValue($tag, $this->dumpValue($value->getValues())); + } + + if (\is_array($value)) { + $code = []; + foreach ($value as $k => $v) { + $code[$k] = $this->dumpValue($v); + } + + return $code; + } elseif ($value instanceof Reference) { + return $this->getServiceCall((string) $value, $value); + } elseif ($value instanceof Parameter) { + return $this->getParameterCall((string) $value); + } elseif ($value instanceof Expression) { + return $this->getExpressionCall((string) $value); + } elseif ($value instanceof Definition) { + return new TaggedValue('service', (new Parser())->parse("_:\n".$this->addService('_', $value), Yaml::PARSE_CUSTOM_TAGS)['_']['_']); + } elseif (\is_object($value) || \is_resource($value)) { + throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); + } + + return $value; + } + + private function getServiceCall(string $id, Reference $reference = null): string + { + if (null !== $reference) { + switch ($reference->getInvalidBehavior()) { + case ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE: break; + case ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE: break; + case ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE: return sprintf('@!%s', $id); + default: return sprintf('@?%s', $id); + } + } + + return sprintf('@%s', $id); + } + + private function getParameterCall(string $id): string + { + return sprintf('%%%s%%', $id); + } + + private function getExpressionCall(string $expression): string + { + return sprintf('@=%s', $expression); + } + + private function prepareParameters(array $parameters, bool $escape = true): array + { + $filtered = []; + foreach ($parameters as $key => $value) { + if (\is_array($value)) { + $value = $this->prepareParameters($value, $escape); + } elseif ($value instanceof Reference || \is_string($value) && 0 === strpos($value, '@')) { + $value = '@'.$value; + } + + $filtered[$key] = $value; + } + + return $escape ? $this->escape($filtered) : $filtered; + } + + private function escape(array $arguments): array + { + $args = []; + foreach ($arguments as $k => $v) { + if (\is_array($v)) { + $args[$k] = $this->escape($v); + } elseif (\is_string($v)) { + $args[$k] = str_replace('%', '%%', $v); + } else { + $args[$k] = $v; + } + } + + return $args; + } +} diff --git a/vendor/symfony/dependency-injection/EnvVarLoaderInterface.php b/vendor/symfony/dependency-injection/EnvVarLoaderInterface.php new file mode 100644 index 0000000..0c547f8 --- /dev/null +++ b/vendor/symfony/dependency-injection/EnvVarLoaderInterface.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +/** + * EnvVarLoaderInterface objects return key/value pairs that are added to the list of available env vars. + * + * @author Nicolas Grekas + */ +interface EnvVarLoaderInterface +{ + /** + * @return string[] Key/value pairs that can be accessed using the regular "%env()%" syntax + */ + public function loadEnvVars(): array; +} diff --git a/vendor/symfony/dependency-injection/EnvVarProcessor.php b/vendor/symfony/dependency-injection/EnvVarProcessor.php new file mode 100644 index 0000000..0e23d93 --- /dev/null +++ b/vendor/symfony/dependency-injection/EnvVarProcessor.php @@ -0,0 +1,280 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; +use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + +/** + * @author Nicolas Grekas + */ +class EnvVarProcessor implements EnvVarProcessorInterface +{ + private $container; + private $loaders; + private $loadedVars = []; + + /** + * @param EnvVarLoaderInterface[] $loaders + */ + public function __construct(ContainerInterface $container, \Traversable $loaders = null) + { + $this->container = $container; + $this->loaders = new \IteratorIterator($loaders ?? new \ArrayIterator()); + $this->loaders = $this->loaders->getInnerIterator(); + } + + /** + * {@inheritdoc} + */ + public static function getProvidedTypes() + { + return [ + 'base64' => 'string', + 'bool' => 'bool', + 'const' => 'bool|int|float|string|array', + 'csv' => 'array', + 'file' => 'string', + 'float' => 'float', + 'int' => 'int', + 'json' => 'array', + 'key' => 'bool|int|float|string|array', + 'url' => 'array', + 'query_string' => 'array', + 'resolve' => 'string', + 'default' => 'bool|int|float|string|array', + 'string' => 'string', + 'trim' => 'string', + 'require' => 'bool|int|float|string|array', + ]; + } + + /** + * {@inheritdoc} + */ + public function getEnv(string $prefix, string $name, \Closure $getEnv) + { + $i = strpos($name, ':'); + + if ('key' === $prefix) { + if (false === $i) { + throw new RuntimeException(sprintf('Invalid env "key:%s": a key specifier should be provided.', $name)); + } + + $next = substr($name, $i + 1); + $key = substr($name, 0, $i); + $array = $getEnv($next); + + if (!\is_array($array)) { + throw new RuntimeException(sprintf('Resolved value of "%s" did not result in an array value.', $next)); + } + + if (!isset($array[$key]) && !\array_key_exists($key, $array)) { + throw new EnvNotFoundException(sprintf('Key "%s" not found in "%s" (resolved from "%s").', $key, json_encode($array), $next)); + } + + return $array[$key]; + } + + if ('default' === $prefix) { + if (false === $i) { + throw new RuntimeException(sprintf('Invalid env "default:%s": a fallback parameter should be provided.', $name)); + } + + $next = substr($name, $i + 1); + $default = substr($name, 0, $i); + + if ('' !== $default && !$this->container->hasParameter($default)) { + throw new RuntimeException(sprintf('Invalid env fallback in "default:%s": parameter "%s" not found.', $name, $default)); + } + + try { + $env = $getEnv($next); + + if ('' !== $env && null !== $env) { + return $env; + } + } catch (EnvNotFoundException $e) { + // no-op + } + + return '' === $default ? null : $this->container->getParameter($default); + } + + if ('file' === $prefix || 'require' === $prefix) { + if (!is_scalar($file = $getEnv($name))) { + throw new RuntimeException(sprintf('Invalid file name: env var "%s" is non-scalar.', $name)); + } + if (!file_exists($file)) { + throw new EnvNotFoundException(sprintf('File "%s" not found (resolved from "%s").', $file, $name)); + } + + if ('file' === $prefix) { + return file_get_contents($file); + } else { + return require $file; + } + } + + if (false !== $i || 'string' !== $prefix) { + if (null === $env = $getEnv($name)) { + return null; + } + } elseif (isset($_ENV[$name])) { + $env = $_ENV[$name]; + } elseif (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) { + $env = $_SERVER[$name]; + } elseif (false === ($env = getenv($name)) || null === $env) { // null is a possible value because of thread safety issues + foreach ($this->loadedVars as $vars) { + if (false !== $env = ($vars[$name] ?? false)) { + break; + } + } + + $loaders = $this->loaders; + $this->loaders = new \ArrayIterator(); + + try { + while ((false === $env || null === $env) && $loaders->valid()) { + $loader = $loaders->current(); + $loaders->next(); + $this->loadedVars[] = $vars = $loader->loadEnvVars(); + $env = $vars[$name] ?? false; + } + } catch (ParameterCircularReferenceException $e) { + // skip loaders that need an env var that is not defined + } finally { + $this->loaders = $loaders; + } + + if (false === $env || null === $env) { + if (!$this->container->hasParameter("env($name)")) { + throw new EnvNotFoundException(sprintf('Environment variable not found: "%s".', $name)); + } + + if (null === $env = $this->container->getParameter("env($name)")) { + return null; + } + } + } + + if (!is_scalar($env)) { + throw new RuntimeException(sprintf('Non-scalar env var "%s" cannot be cast to %s.', $name, $prefix)); + } + + if ('string' === $prefix) { + return (string) $env; + } + + if ('bool' === $prefix) { + return (bool) (filter_var($env, FILTER_VALIDATE_BOOLEAN) ?: filter_var($env, FILTER_VALIDATE_INT) ?: filter_var($env, FILTER_VALIDATE_FLOAT)); + } + + if ('int' === $prefix) { + if (false === $env = filter_var($env, FILTER_VALIDATE_INT) ?: filter_var($env, FILTER_VALIDATE_FLOAT)) { + throw new RuntimeException(sprintf('Non-numeric env var "%s" cannot be cast to int.', $name)); + } + + return (int) $env; + } + + if ('float' === $prefix) { + if (false === $env = filter_var($env, FILTER_VALIDATE_FLOAT)) { + throw new RuntimeException(sprintf('Non-numeric env var "%s" cannot be cast to float.', $name)); + } + + return (float) $env; + } + + if ('const' === $prefix) { + if (!\defined($env)) { + throw new RuntimeException(sprintf('Env var "%s" maps to undefined constant "%s".', $name, $env)); + } + + return \constant($env); + } + + if ('base64' === $prefix) { + return base64_decode(strtr($env, '-_', '+/')); + } + + if ('json' === $prefix) { + $env = json_decode($env, true); + + if (JSON_ERROR_NONE !== json_last_error()) { + throw new RuntimeException(sprintf('Invalid JSON in env var "%s": '.json_last_error_msg(), $name)); + } + + if (null !== $env && !\is_array($env)) { + throw new RuntimeException(sprintf('Invalid JSON env var "%s": array or null expected, %s given.', $name, \gettype($env))); + } + + return $env; + } + + if ('url' === $prefix) { + $parsedEnv = parse_url($env); + + if (false === $parsedEnv) { + throw new RuntimeException(sprintf('Invalid URL in env var "%s"', $name)); + } + if (!isset($parsedEnv['scheme'], $parsedEnv['host'])) { + throw new RuntimeException(sprintf('Invalid URL env var "%s": schema and host expected, %s given.', $name, $env)); + } + $parsedEnv += [ + 'port' => null, + 'user' => null, + 'pass' => null, + 'path' => null, + 'query' => null, + 'fragment' => null, + ]; + + // remove the '/' separator + $parsedEnv['path'] = '/' === $parsedEnv['path'] ? null : substr($parsedEnv['path'], 1); + + return $parsedEnv; + } + + if ('query_string' === $prefix) { + $queryString = parse_url($env, PHP_URL_QUERY) ?: $env; + parse_str($queryString, $result); + + return $result; + } + + if ('resolve' === $prefix) { + return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($name) { + if (!isset($match[1])) { + return '%'; + } + $value = $this->container->getParameter($match[1]); + if (!is_scalar($value)) { + throw new RuntimeException(sprintf('Parameter "%s" found when resolving env var "%s" must be scalar, "%s" given.', $match[1], $name, \gettype($value))); + } + + return $value; + }, $env); + } + + if ('csv' === $prefix) { + return str_getcsv($env, ',', '"', \PHP_VERSION_ID >= 70400 ? '' : '\\'); + } + + if ('trim' === $prefix) { + return trim($env); + } + + throw new RuntimeException(sprintf('Unsupported env var prefix "%s".', $prefix)); + } +} diff --git a/vendor/symfony/dependency-injection/EnvVarProcessorInterface.php b/vendor/symfony/dependency-injection/EnvVarProcessorInterface.php new file mode 100644 index 0000000..d3275fe --- /dev/null +++ b/vendor/symfony/dependency-injection/EnvVarProcessorInterface.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + +/** + * The EnvVarProcessorInterface is implemented by objects that manage environment-like variables. + * + * @author Nicolas Grekas + */ +interface EnvVarProcessorInterface +{ + /** + * Returns the value of the given variable as managed by the current instance. + * + * @param string $prefix The namespace of the variable + * @param string $name The name of the variable within the namespace + * @param \Closure $getEnv A closure that allows fetching more env vars + * + * @return mixed + * + * @throws RuntimeException on error + */ + public function getEnv(string $prefix, string $name, \Closure $getEnv); + + /** + * @return string[] The PHP-types managed by getEnv(), keyed by prefixes + */ + public static function getProvidedTypes(); +} diff --git a/vendor/symfony/dependency-injection/Exception/AutowiringFailedException.php b/vendor/symfony/dependency-injection/Exception/AutowiringFailedException.php new file mode 100644 index 0000000..c203b85 --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/AutowiringFailedException.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +/** + * Thrown when a definition cannot be autowired. + */ +class AutowiringFailedException extends RuntimeException +{ + private $serviceId; + private $messageCallback; + + public function __construct(string $serviceId, $message = '', int $code = 0, \Throwable $previous = null) + { + $this->serviceId = $serviceId; + + if ($message instanceof \Closure && \function_exists('xdebug_is_enabled') && xdebug_is_enabled()) { + $message = $message(); + } + + if (!$message instanceof \Closure) { + parent::__construct($message, $code, $previous); + + return; + } + + $this->messageCallback = $message; + parent::__construct('', $code, $previous); + + $this->message = new class($this->message, $this->messageCallback) { + private $message; + private $messageCallback; + + public function __construct(&$message, &$messageCallback) + { + $this->message = &$message; + $this->messageCallback = &$messageCallback; + } + + public function __toString(): string + { + $messageCallback = $this->messageCallback; + $this->messageCallback = null; + + try { + return $this->message = $messageCallback(); + } catch (\Throwable $e) { + return $this->message = $e->getMessage(); + } + } + }; + } + + public function getMessageCallback(): ?\Closure + { + return $this->messageCallback; + } + + public function getServiceId() + { + return $this->serviceId; + } +} diff --git a/vendor/symfony/dependency-injection/Exception/BadMethodCallException.php b/vendor/symfony/dependency-injection/Exception/BadMethodCallException.php new file mode 100644 index 0000000..959238e --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/BadMethodCallException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +/** + * Base BadMethodCallException for Dependency Injection component. + */ +class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/dependency-injection/Exception/EnvNotFoundException.php b/vendor/symfony/dependency-injection/Exception/EnvNotFoundException.php new file mode 100644 index 0000000..04ac848 --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/EnvNotFoundException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +/** + * This exception is thrown when an environment variable is not found. + * + * @author Nicolas Grekas + */ +class EnvNotFoundException extends InvalidArgumentException +{ +} diff --git a/vendor/symfony/dependency-injection/Exception/EnvParameterException.php b/vendor/symfony/dependency-injection/Exception/EnvParameterException.php new file mode 100644 index 0000000..48b5e48 --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/EnvParameterException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +/** + * This exception wraps exceptions whose messages contain a reference to an env parameter. + * + * @author Nicolas Grekas + */ +class EnvParameterException extends InvalidArgumentException +{ + public function __construct(array $envs, \Throwable $previous = null, string $message = 'Incompatible use of dynamic environment variables "%s" found in parameters.') + { + parent::__construct(sprintf($message, implode('", "', $envs)), 0, $previous); + } +} diff --git a/vendor/symfony/dependency-injection/Exception/ExceptionInterface.php b/vendor/symfony/dependency-injection/Exception/ExceptionInterface.php new file mode 100644 index 0000000..6202df7 --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/ExceptionInterface.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +use Psr\Container\ContainerExceptionInterface; + +/** + * Base ExceptionInterface for Dependency Injection component. + * + * @author Fabien Potencier + * @author Bulat Shakirzyanov + */ +interface ExceptionInterface extends ContainerExceptionInterface, \Throwable +{ +} diff --git a/vendor/symfony/dependency-injection/Exception/InvalidArgumentException.php b/vendor/symfony/dependency-injection/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..119bb7d --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/InvalidArgumentException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +/** + * Base InvalidArgumentException for Dependency Injection component. + * + * @author Bulat Shakirzyanov + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/dependency-injection/Exception/InvalidParameterTypeException.php b/vendor/symfony/dependency-injection/Exception/InvalidParameterTypeException.php new file mode 100644 index 0000000..206561f --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/InvalidParameterTypeException.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +/** + * Thrown when trying to inject a parameter into a constructor/method with an incompatible type. + * + * @author Nicolas Grekas + * @author Julien Maulny + */ +class InvalidParameterTypeException extends InvalidArgumentException +{ + public function __construct(string $serviceId, string $type, \ReflectionParameter $parameter) + { + parent::__construct(sprintf('Invalid definition for service "%s": argument %d of "%s::%s" accepts "%s", "%s" passed.', $serviceId, 1 + $parameter->getPosition(), $parameter->getDeclaringClass()->getName(), $parameter->getDeclaringFunction()->getName(), $parameter->getType()->getName(), $type)); + } +} diff --git a/vendor/symfony/dependency-injection/Exception/LogicException.php b/vendor/symfony/dependency-injection/Exception/LogicException.php new file mode 100644 index 0000000..17a070c --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/LogicException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +/** + * Base LogicException for Dependency Injection component. + */ +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/dependency-injection/Exception/OutOfBoundsException.php b/vendor/symfony/dependency-injection/Exception/OutOfBoundsException.php new file mode 100644 index 0000000..a61f143 --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/OutOfBoundsException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +/** + * Base OutOfBoundsException for Dependency Injection component. + */ +class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php b/vendor/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php new file mode 100644 index 0000000..2450ccb --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +/** + * This exception is thrown when a circular reference in a parameter is detected. + * + * @author Fabien Potencier + */ +class ParameterCircularReferenceException extends RuntimeException +{ + private $parameters; + + public function __construct(array $parameters, \Throwable $previous = null) + { + parent::__construct(sprintf('Circular reference detected for parameter "%s" ("%s" > "%s").', $parameters[0], implode('" > "', $parameters), $parameters[0]), 0, $previous); + + $this->parameters = $parameters; + } + + public function getParameters() + { + return $this->parameters; + } +} diff --git a/vendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php b/vendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php new file mode 100644 index 0000000..7c0c5e3 --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +use Psr\Container\NotFoundExceptionInterface; + +/** + * This exception is thrown when a non-existent parameter is used. + * + * @author Fabien Potencier + */ +class ParameterNotFoundException extends InvalidArgumentException implements NotFoundExceptionInterface +{ + private $key; + private $sourceId; + private $sourceKey; + private $alternatives; + private $nonNestedAlternative; + + /** + * @param string $key The requested parameter key + * @param string $sourceId The service id that references the non-existent parameter + * @param string $sourceKey The parameter key that references the non-existent parameter + * @param \Throwable $previous The previous exception + * @param string[] $alternatives Some parameter name alternatives + * @param string|null $nonNestedAlternative The alternative parameter name when the user expected dot notation for nested parameters + */ + public function __construct(string $key, string $sourceId = null, string $sourceKey = null, \Throwable $previous = null, array $alternatives = [], string $nonNestedAlternative = null) + { + $this->key = $key; + $this->sourceId = $sourceId; + $this->sourceKey = $sourceKey; + $this->alternatives = $alternatives; + $this->nonNestedAlternative = $nonNestedAlternative; + + parent::__construct('', 0, $previous); + + $this->updateRepr(); + } + + public function updateRepr() + { + if (null !== $this->sourceId) { + $this->message = sprintf('The service "%s" has a dependency on a non-existent parameter "%s".', $this->sourceId, $this->key); + } elseif (null !== $this->sourceKey) { + $this->message = sprintf('The parameter "%s" has a dependency on a non-existent parameter "%s".', $this->sourceKey, $this->key); + } else { + $this->message = sprintf('You have requested a non-existent parameter "%s".', $this->key); + } + + if ($this->alternatives) { + if (1 == \count($this->alternatives)) { + $this->message .= ' Did you mean this: "'; + } else { + $this->message .= ' Did you mean one of these: "'; + } + $this->message .= implode('", "', $this->alternatives).'"?'; + } elseif (null !== $this->nonNestedAlternative) { + $this->message .= ' You cannot access nested array items, do you want to inject "'.$this->nonNestedAlternative.'" instead?'; + } + } + + public function getKey() + { + return $this->key; + } + + public function getSourceId() + { + return $this->sourceId; + } + + public function getSourceKey() + { + return $this->sourceKey; + } + + public function setSourceId($sourceId) + { + $this->sourceId = $sourceId; + + $this->updateRepr(); + } + + public function setSourceKey($sourceKey) + { + $this->sourceKey = $sourceKey; + + $this->updateRepr(); + } +} diff --git a/vendor/symfony/dependency-injection/Exception/RuntimeException.php b/vendor/symfony/dependency-injection/Exception/RuntimeException.php new file mode 100644 index 0000000..5c24541 --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/RuntimeException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +/** + * Base RuntimeException for Dependency Injection component. + * + * @author Johannes M. Schmitt + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php b/vendor/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php new file mode 100644 index 0000000..a38671b --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +/** + * This exception is thrown when a circular reference is detected. + * + * @author Johannes M. Schmitt + */ +class ServiceCircularReferenceException extends RuntimeException +{ + private $serviceId; + private $path; + + public function __construct(string $serviceId, array $path, \Throwable $previous = null) + { + parent::__construct(sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, implode(' -> ', $path)), 0, $previous); + + $this->serviceId = $serviceId; + $this->path = $path; + } + + public function getServiceId() + { + return $this->serviceId; + } + + public function getPath() + { + return $this->path; + } +} diff --git a/vendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php b/vendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php new file mode 100644 index 0000000..f91afae --- /dev/null +++ b/vendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Exception; + +use Psr\Container\NotFoundExceptionInterface; + +/** + * This exception is thrown when a non-existent service is requested. + * + * @author Johannes M. Schmitt + */ +class ServiceNotFoundException extends InvalidArgumentException implements NotFoundExceptionInterface +{ + private $id; + private $sourceId; + private $alternatives; + + public function __construct(string $id, string $sourceId = null, \Throwable $previous = null, array $alternatives = [], string $msg = null) + { + if (null !== $msg) { + // no-op + } elseif (null === $sourceId) { + $msg = sprintf('You have requested a non-existent service "%s".', $id); + } else { + $msg = sprintf('The service "%s" has a dependency on a non-existent service "%s".', $sourceId, $id); + } + + if ($alternatives) { + if (1 == \count($alternatives)) { + $msg .= ' Did you mean this: "'; + } else { + $msg .= ' Did you mean one of these: "'; + } + $msg .= implode('", "', $alternatives).'"?'; + } + + parent::__construct($msg, 0, $previous); + + $this->id = $id; + $this->sourceId = $sourceId; + $this->alternatives = $alternatives; + } + + public function getId() + { + return $this->id; + } + + public function getSourceId() + { + return $this->sourceId; + } + + public function getAlternatives() + { + return $this->alternatives; + } +} diff --git a/vendor/symfony/dependency-injection/ExpressionLanguage.php b/vendor/symfony/dependency-injection/ExpressionLanguage.php new file mode 100644 index 0000000..961c737 --- /dev/null +++ b/vendor/symfony/dependency-injection/ExpressionLanguage.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; + +if (!class_exists(BaseExpressionLanguage::class)) { + return; +} + +/** + * Adds some function to the default ExpressionLanguage. + * + * @author Fabien Potencier + * + * @see ExpressionLanguageProvider + */ +class ExpressionLanguage extends BaseExpressionLanguage +{ + /** + * {@inheritdoc} + */ + public function __construct(CacheItemPoolInterface $cache = null, array $providers = [], callable $serviceCompiler = null) + { + // prepend the default provider to let users override it easily + array_unshift($providers, new ExpressionLanguageProvider($serviceCompiler)); + + parent::__construct($cache, $providers); + } +} diff --git a/vendor/symfony/dependency-injection/ExpressionLanguageProvider.php b/vendor/symfony/dependency-injection/ExpressionLanguageProvider.php new file mode 100644 index 0000000..9198ca0 --- /dev/null +++ b/vendor/symfony/dependency-injection/ExpressionLanguageProvider.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +use Symfony\Component\ExpressionLanguage\ExpressionFunction; +use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; + +/** + * Define some ExpressionLanguage functions. + * + * To get a service, use service('request'). + * To get a parameter, use parameter('kernel.debug'). + * + * @author Fabien Potencier + */ +class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface +{ + private $serviceCompiler; + + public function __construct(callable $serviceCompiler = null) + { + $this->serviceCompiler = $serviceCompiler; + } + + public function getFunctions() + { + return [ + new ExpressionFunction('service', $this->serviceCompiler ?: function ($arg) { + return sprintf('$this->get(%s)', $arg); + }, function (array $variables, $value) { + return $variables['container']->get($value); + }), + + new ExpressionFunction('parameter', function ($arg) { + return sprintf('$this->getParameter(%s)', $arg); + }, function (array $variables, $value) { + return $variables['container']->getParameter($value); + }), + ]; + } +} diff --git a/vendor/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php b/vendor/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php new file mode 100644 index 0000000..c3bd842 --- /dev/null +++ b/vendor/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Extension; + +use Symfony\Component\Config\Definition\ConfigurationInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * ConfigurationExtensionInterface is the interface implemented by container extension classes. + * + * @author Kevin Bond + */ +interface ConfigurationExtensionInterface +{ + /** + * Returns extension configuration. + * + * @return ConfigurationInterface|null The configuration or null + */ + public function getConfiguration(array $config, ContainerBuilder $container); +} diff --git a/vendor/symfony/dependency-injection/Extension/Extension.php b/vendor/symfony/dependency-injection/Extension/Extension.php new file mode 100644 index 0000000..ffa4707 --- /dev/null +++ b/vendor/symfony/dependency-injection/Extension/Extension.php @@ -0,0 +1,139 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Extension; + +use Symfony\Component\Config\Definition\ConfigurationInterface; +use Symfony\Component\Config\Definition\Processor; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\LogicException; + +/** + * Provides useful features shared by many extensions. + * + * @author Fabien Potencier + */ +abstract class Extension implements ExtensionInterface, ConfigurationExtensionInterface +{ + private $processedConfigs = []; + + /** + * {@inheritdoc} + */ + public function getXsdValidationBasePath() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function getNamespace() + { + return 'http://example.org/schema/dic/'.$this->getAlias(); + } + + /** + * Returns the recommended alias to use in XML. + * + * This alias is also the mandatory prefix to use when using YAML. + * + * This convention is to remove the "Extension" postfix from the class + * name and then lowercase and underscore the result. So: + * + * AcmeHelloExtension + * + * becomes + * + * acme_hello + * + * This can be overridden in a sub-class to specify the alias manually. + * + * @return string The alias + * + * @throws BadMethodCallException When the extension name does not follow conventions + */ + public function getAlias() + { + $className = \get_class($this); + if ('Extension' != substr($className, -9)) { + throw new BadMethodCallException('This extension does not follow the naming convention; you must overwrite the getAlias() method.'); + } + $classBaseName = substr(strrchr($className, '\\'), 1, -9); + + return Container::underscore($classBaseName); + } + + /** + * {@inheritdoc} + */ + public function getConfiguration(array $config, ContainerBuilder $container) + { + $class = \get_class($this); + + if (false !== strpos($class, "\0")) { + return null; // ignore anonymous classes + } + + $class = substr_replace($class, '\Configuration', strrpos($class, '\\')); + $class = $container->getReflectionClass($class); + + if (!$class) { + return null; + } + + if (!$class->implementsInterface(ConfigurationInterface::class)) { + throw new LogicException(sprintf('The extension configuration class "%s" must implement "%s".', $class->getName(), ConfigurationInterface::class)); + } + + if (!($constructor = $class->getConstructor()) || !$constructor->getNumberOfRequiredParameters()) { + return $class->newInstance(); + } + + return null; + } + + final protected function processConfiguration(ConfigurationInterface $configuration, array $configs): array + { + $processor = new Processor(); + + return $this->processedConfigs[] = $processor->processConfiguration($configuration, $configs); + } + + /** + * @internal + */ + final public function getProcessedConfigs(): array + { + try { + return $this->processedConfigs; + } finally { + $this->processedConfigs = []; + } + } + + /** + * @return bool Whether the configuration is enabled + * + * @throws InvalidArgumentException When the config is not enableable + */ + protected function isConfigEnabled(ContainerBuilder $container, array $config) + { + if (!\array_key_exists('enabled', $config)) { + throw new InvalidArgumentException("The config array has no 'enabled' key."); + } + + return (bool) $container->getParameterBag()->resolveValue($config['enabled']); + } +} diff --git a/vendor/symfony/dependency-injection/Extension/ExtensionInterface.php b/vendor/symfony/dependency-injection/Extension/ExtensionInterface.php new file mode 100644 index 0000000..6a7a2cf --- /dev/null +++ b/vendor/symfony/dependency-injection/Extension/ExtensionInterface.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Extension; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * ExtensionInterface is the interface implemented by container extension classes. + * + * @author Fabien Potencier + */ +interface ExtensionInterface +{ + /** + * Loads a specific configuration. + * + * @throws \InvalidArgumentException When provided tag is not defined in this extension + */ + public function load(array $configs, ContainerBuilder $container); + + /** + * Returns the namespace to be used for this extension (XML namespace). + * + * @return string The XML namespace + */ + public function getNamespace(); + + /** + * Returns the base path for the XSD files. + * + * @return string|false + */ + public function getXsdValidationBasePath(); + + /** + * Returns the recommended alias to use in XML. + * + * This alias is also the mandatory prefix to use when using YAML. + * + * @return string The alias + */ + public function getAlias(); +} diff --git a/vendor/symfony/dependency-injection/Extension/PrependExtensionInterface.php b/vendor/symfony/dependency-injection/Extension/PrependExtensionInterface.php new file mode 100644 index 0000000..5bd18d7 --- /dev/null +++ b/vendor/symfony/dependency-injection/Extension/PrependExtensionInterface.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Extension; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +interface PrependExtensionInterface +{ + /** + * Allow an extension to prepend the extension configurations. + */ + public function prepend(ContainerBuilder $container); +} diff --git a/vendor/symfony/dependency-injection/LICENSE b/vendor/symfony/dependency-injection/LICENSE new file mode 100644 index 0000000..a677f43 --- /dev/null +++ b/vendor/symfony/dependency-injection/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php b/vendor/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php new file mode 100644 index 0000000..a9d7811 --- /dev/null +++ b/vendor/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; + +/** + * Lazy proxy instantiator, capable of instantiating a proxy given a container, the + * service definitions and a callback that produces the real service instance. + * + * @author Marco Pivetta + */ +interface InstantiatorInterface +{ + /** + * Instantiates a proxy object. + * + * @param string $id Identifier of the requested service + * @param callable $realInstantiator Zero-argument callback that is capable of producing the real service instance + * + * @return object + */ + public function instantiateProxy(ContainerInterface $container, Definition $definition, string $id, callable $realInstantiator); +} diff --git a/vendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php b/vendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php new file mode 100644 index 0000000..1696e7a --- /dev/null +++ b/vendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; + +/** + * {@inheritdoc} + * + * Noop proxy instantiator - produces the real service instead of a proxy instance. + * + * @author Marco Pivetta + */ +class RealServiceInstantiator implements InstantiatorInterface +{ + /** + * {@inheritdoc} + */ + public function instantiateProxy(ContainerInterface $container, Definition $definition, string $id, callable $realInstantiator) + { + return $realInstantiator(); + } +} diff --git a/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php b/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php new file mode 100644 index 0000000..351560d --- /dev/null +++ b/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; + +use Symfony\Component\DependencyInjection\Definition; + +/** + * Lazy proxy dumper capable of generating the instantiation logic PHP code for proxied services. + * + * @author Marco Pivetta + */ +interface DumperInterface +{ + /** + * Inspects whether the given definitions should produce proxy instantiation logic in the dumped container. + * + * @return bool + */ + public function isProxyCandidate(Definition $definition); + + /** + * Generates the code to be used to instantiate a proxy in the dumped factory code. + * + * @return string + */ + public function getProxyFactoryCode(Definition $definition, string $id, string $factoryCode); + + /** + * Generates the code for the lazy proxy. + * + * @return string + */ + public function getProxyCode(Definition $definition); +} diff --git a/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php b/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php new file mode 100644 index 0000000..7e0f14c --- /dev/null +++ b/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; + +use Symfony\Component\DependencyInjection\Definition; + +/** + * Null dumper, negates any proxy code generation for any given service definition. + * + * @author Marco Pivetta + * + * @final + */ +class NullDumper implements DumperInterface +{ + /** + * {@inheritdoc} + */ + public function isProxyCandidate(Definition $definition): bool + { + return false; + } + + /** + * {@inheritdoc} + */ + public function getProxyFactoryCode(Definition $definition, string $id, string $factoryCode): string + { + return ''; + } + + /** + * {@inheritdoc} + */ + public function getProxyCode(Definition $definition): string + { + return ''; + } +} diff --git a/vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php b/vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php new file mode 100644 index 0000000..e5611bc --- /dev/null +++ b/vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\LazyProxy; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class ProxyHelper +{ + /** + * @return string|null The FQCN or builtin name of the type hint, or null when the type hint references an invalid self|parent context + */ + public static function getTypeHint(\ReflectionFunctionAbstract $r, \ReflectionParameter $p = null, bool $noBuiltin = false): ?string + { + if ($p instanceof \ReflectionParameter) { + $type = $p->getType(); + } else { + $type = $r->getReturnType(); + } + if (!$type) { + return null; + } + if (!\is_string($type)) { + $name = $type->getName(); + + if ($type->isBuiltin()) { + return $noBuiltin ? null : $name; + } + } + $lcName = strtolower($name); + $prefix = $noBuiltin ? '' : '\\'; + + if ('self' !== $lcName && 'parent' !== $lcName) { + return $prefix.$name; + } + if (!$r instanceof \ReflectionMethod) { + return null; + } + if ('self' === $lcName) { + return $prefix.$r->getDeclaringClass()->name; + } + + return ($parent = $r->getDeclaringClass()->getParentClass()) ? $prefix.$parent->name : null; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/ClosureLoader.php b/vendor/symfony/dependency-injection/Loader/ClosureLoader.php new file mode 100644 index 0000000..57aa83d --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/ClosureLoader.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader; + +use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * ClosureLoader loads service definitions from a PHP closure. + * + * The Closure has access to the container as its first argument. + * + * @author Fabien Potencier + */ +class ClosureLoader extends Loader +{ + private $container; + + public function __construct(ContainerBuilder $container) + { + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public function load($resource, string $type = null) + { + $resource($this->container); + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + return $resource instanceof \Closure; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php new file mode 100644 index 0000000..539eb39 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Parameter; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\ExpressionLanguage\Expression; + +abstract class AbstractConfigurator +{ + const FACTORY = 'unknown'; + + /** @internal */ + protected $definition; + + public function __call(string $method, array $args) + { + if (method_exists($this, 'set'.$method)) { + return $this->{'set'.$method}(...$args); + } + + throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', \get_class($this), $method)); + } + + /** + * Checks that a value is valid, optionally replacing Definition and Reference configurators by their configure value. + * + * @param mixed $value + * @param bool $allowServices whether Definition and Reference are allowed; by default, only scalars and arrays are + * + * @return mixed the value, optionally cast to a Definition/Reference + */ + public static function processValue($value, $allowServices = false) + { + if (\is_array($value)) { + foreach ($value as $k => $v) { + $value[$k] = static::processValue($v, $allowServices); + } + + return $value; + } + + if ($value instanceof ReferenceConfigurator) { + return new Reference($value->id, $value->invalidBehavior); + } + + if ($value instanceof InlineServiceConfigurator) { + $def = $value->definition; + $value->definition = null; + + return $def; + } + + if ($value instanceof self) { + throw new InvalidArgumentException(sprintf('"%s()" can be used only at the root of service configuration files.', $value::FACTORY)); + } + + switch (true) { + case null === $value: + case is_scalar($value): + return $value; + + case $value instanceof ArgumentInterface: + case $value instanceof Definition: + case $value instanceof Expression: + case $value instanceof Parameter: + case $value instanceof Reference: + if ($allowServices) { + return $value; + } + } + + throw new InvalidArgumentException(sprintf('Cannot use values of type "%s" in service configuration files.', \is_object($value) ? \get_class($value) : \gettype($value))); + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php new file mode 100644 index 0000000..9d3305e --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; + +abstract class AbstractServiceConfigurator extends AbstractConfigurator +{ + protected $parent; + protected $id; + private $defaultTags = []; + + public function __construct(ServicesConfigurator $parent, Definition $definition, string $id = null, array $defaultTags = []) + { + $this->parent = $parent; + $this->definition = $definition; + $this->id = $id; + $this->defaultTags = $defaultTags; + } + + public function __destruct() + { + // default tags should be added last + foreach ($this->defaultTags as $name => $attributes) { + foreach ($attributes as $attributes) { + $this->definition->addTag($name, $attributes); + } + } + $this->defaultTags = []; + } + + /** + * Registers a service. + */ + final public function set(string $id, string $class = null): ServiceConfigurator + { + $this->__destruct(); + + return $this->parent->set($id, $class); + } + + /** + * Creates an alias. + */ + final public function alias(string $id, string $referencedId): AliasConfigurator + { + $this->__destruct(); + + return $this->parent->alias($id, $referencedId); + } + + /** + * Registers a PSR-4 namespace using a glob pattern. + */ + final public function load(string $namespace, string $resource): PrototypeConfigurator + { + $this->__destruct(); + + return $this->parent->load($namespace, $resource); + } + + /** + * Gets an already defined service definition. + * + * @throws ServiceNotFoundException if the service definition does not exist + */ + final public function get(string $id): ServiceConfigurator + { + $this->__destruct(); + + return $this->parent->get($id); + } + + /** + * Registers a service. + */ + final public function __invoke(string $id, string $class = null): ServiceConfigurator + { + $this->__destruct(); + + return $this->parent->set($id, $class); + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php new file mode 100644 index 0000000..cb00f58 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Alias; + +/** + * @author Nicolas Grekas + */ +class AliasConfigurator extends AbstractServiceConfigurator +{ + const FACTORY = 'alias'; + + use Traits\PublicTrait; + + public function __construct(ServicesConfigurator $parent, Alias $alias) + { + $this->parent = $parent; + $this->definition = $alias; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php new file mode 100644 index 0000000..28c9d79 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; +use Symfony\Component\ExpressionLanguage\Expression; + +/** + * @author Nicolas Grekas + */ +class ContainerConfigurator extends AbstractConfigurator +{ + const FACTORY = 'container'; + + private $container; + private $loader; + private $instanceof; + private $path; + private $file; + private $anonymousCount = 0; + + public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, string $path, string $file) + { + $this->container = $container; + $this->loader = $loader; + $this->instanceof = &$instanceof; + $this->path = $path; + $this->file = $file; + } + + final public function extension(string $namespace, array $config) + { + if (!$this->container->hasExtension($namespace)) { + $extensions = array_filter(array_map(function (ExtensionInterface $ext) { return $ext->getAlias(); }, $this->container->getExtensions())); + throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $namespace, $this->file, $namespace, $extensions ? sprintf('"%s"', implode('", "', $extensions)) : 'none')); + } + + $this->container->loadFromExtension($namespace, static::processValue($config)); + } + + final public function import(string $resource, string $type = null, $ignoreErrors = false) + { + $this->loader->setCurrentDir(\dirname($this->path)); + $this->loader->import($resource, $type, $ignoreErrors, $this->file); + } + + final public function parameters(): ParametersConfigurator + { + return new ParametersConfigurator($this->container); + } + + final public function services(): ServicesConfigurator + { + return new ServicesConfigurator($this->container, $this->loader, $this->instanceof, $this->path, $this->anonymousCount); + } +} + +/** + * Creates a service reference. + */ +function ref(string $id): ReferenceConfigurator +{ + return new ReferenceConfigurator($id); +} + +/** + * Creates an inline service. + */ +function inline(string $class = null): InlineServiceConfigurator +{ + return new InlineServiceConfigurator(new Definition($class)); +} + +/** + * Creates a service locator. + * + * @param ReferenceConfigurator[] $values + */ +function service_locator(array $values): ServiceLocatorArgument +{ + return new ServiceLocatorArgument(AbstractConfigurator::processValue($values, true)); +} + +/** + * Creates a lazy iterator. + * + * @param ReferenceConfigurator[] $values + */ +function iterator(array $values): IteratorArgument +{ + return new IteratorArgument(AbstractConfigurator::processValue($values, true)); +} + +/** + * Creates a lazy iterator by tag name. + */ +function tagged_iterator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, string $defaultPriorityMethod = null): TaggedIteratorArgument +{ + return new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, false, $defaultPriorityMethod); +} + +/** + * Creates a service locator by tag name. + */ +function tagged_locator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null): ServiceLocatorArgument +{ + return new ServiceLocatorArgument(new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, true)); +} + +/** + * Creates an expression. + */ +function expr(string $expression): Expression +{ + return new Expression($expression); +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php new file mode 100644 index 0000000..cd9088f --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +/** + * @author Nicolas Grekas + */ +class DefaultsConfigurator extends AbstractServiceConfigurator +{ + const FACTORY = 'defaults'; + + use Traits\AutoconfigureTrait; + use Traits\AutowireTrait; + use Traits\BindTrait; + use Traits\PublicTrait; + + private $path; + + public function __construct(ServicesConfigurator $parent, Definition $definition, string $path = null) + { + parent::__construct($parent, $definition, null, []); + + $this->path = $path; + } + + /** + * Adds a tag for this definition. + * + * @return $this + * + * @throws InvalidArgumentException when an invalid tag name or attribute is provided + */ + final public function tag(string $name, array $attributes = []): self + { + if ('' === $name) { + throw new InvalidArgumentException('The tag name in "_defaults" must be a non-empty string.'); + } + + foreach ($attributes as $attribute => $value) { + if (null !== $value && !is_scalar($value)) { + throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type.', $name, $attribute)); + } + } + + $this->definition->addTag($name, $attributes); + + return $this; + } + + /** + * Defines an instanceof-conditional to be applied to following service definitions. + */ + final public function instanceof(string $fqcn): InstanceofConfigurator + { + return $this->parent->instanceof($fqcn); + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php new file mode 100644 index 0000000..362b374 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Definition; + +/** + * @author Nicolas Grekas + */ +class InlineServiceConfigurator extends AbstractConfigurator +{ + const FACTORY = 'inline'; + + use Traits\ArgumentTrait; + use Traits\AutowireTrait; + use Traits\BindTrait; + use Traits\FactoryTrait; + use Traits\FileTrait; + use Traits\LazyTrait; + use Traits\ParentTrait; + use Traits\TagTrait; + + public function __construct(Definition $definition) + { + $this->definition = $definition; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php new file mode 100644 index 0000000..f75e176 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Definition; + +/** + * @author Nicolas Grekas + */ +class InstanceofConfigurator extends AbstractServiceConfigurator +{ + const FACTORY = 'instanceof'; + + use Traits\AutowireTrait; + use Traits\CallTrait; + use Traits\ConfiguratorTrait; + use Traits\LazyTrait; + use Traits\PropertyTrait; + use Traits\PublicTrait; + use Traits\ShareTrait; + use Traits\TagTrait; + use Traits\BindTrait; + + private $path; + + public function __construct(ServicesConfigurator $parent, Definition $definition, string $id, string $path = null) + { + parent::__construct($parent, $definition, $id, []); + + $this->path = $path; + } + + /** + * Defines an instanceof-conditional to be applied to following service definitions. + */ + final public function instanceof(string $fqcn): self + { + return $this->parent->instanceof($fqcn); + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php new file mode 100644 index 0000000..a88d28e --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * @author Nicolas Grekas + */ +class ParametersConfigurator extends AbstractConfigurator +{ + const FACTORY = 'parameters'; + + private $container; + + public function __construct(ContainerBuilder $container) + { + $this->container = $container; + } + + /** + * Creates a parameter. + * + * @return $this + */ + final public function set(string $name, $value): self + { + $this->container->setParameter($name, static::processValue($value, true)); + + return $this; + } + + /** + * Creates a parameter. + * + * @return $this + */ + final public function __invoke(string $name, $value): self + { + return $this->set($name, $value); + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php new file mode 100644 index 0000000..3cd56e0 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; + +/** + * @author Nicolas Grekas + */ +class PrototypeConfigurator extends AbstractServiceConfigurator +{ + const FACTORY = 'load'; + + use Traits\AbstractTrait; + use Traits\ArgumentTrait; + use Traits\AutoconfigureTrait; + use Traits\AutowireTrait; + use Traits\BindTrait; + use Traits\CallTrait; + use Traits\ConfiguratorTrait; + use Traits\DeprecateTrait; + use Traits\FactoryTrait; + use Traits\LazyTrait; + use Traits\ParentTrait; + use Traits\PropertyTrait; + use Traits\PublicTrait; + use Traits\ShareTrait; + use Traits\TagTrait; + + private $loader; + private $resource; + private $excludes; + private $allowParent; + + public function __construct(ServicesConfigurator $parent, PhpFileLoader $loader, Definition $defaults, string $namespace, string $resource, bool $allowParent) + { + $definition = new Definition(); + $definition->setPublic($defaults->isPublic()); + $definition->setAutowired($defaults->isAutowired()); + $definition->setAutoconfigured($defaults->isAutoconfigured()); + $definition->setBindings($defaults->getBindings()); + $definition->setChanges([]); + + $this->loader = $loader; + $this->resource = $resource; + $this->allowParent = $allowParent; + + parent::__construct($parent, $definition, $namespace, $defaults->getTags()); + } + + public function __destruct() + { + parent::__destruct(); + + if ($this->loader) { + $this->loader->registerClasses($this->definition, $this->id, $this->resource, $this->excludes); + } + $this->loader = null; + } + + /** + * Excludes files from registration using glob patterns. + * + * @param string[]|string $excludes + * + * @return $this + */ + final public function exclude($excludes): self + { + $this->excludes = (array) $excludes; + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php new file mode 100644 index 0000000..fa04253 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * @author Nicolas Grekas + */ +class ReferenceConfigurator extends AbstractConfigurator +{ + /** @internal */ + protected $id; + + /** @internal */ + protected $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + + public function __construct(string $id) + { + $this->id = $id; + } + + /** + * @return $this + */ + final public function ignoreOnInvalid(): self + { + $this->invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; + + return $this; + } + + /** + * @return $this + */ + final public function nullOnInvalid(): self + { + $this->invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; + + return $this; + } + + /** + * @return $this + */ + final public function ignoreOnUninitialized(): self + { + $this->invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; + + return $this; + } + + /** + * @return string + */ + public function __toString() + { + return $this->id; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php new file mode 100644 index 0000000..f1a6af7 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; + +/** + * @author Nicolas Grekas + */ +class ServiceConfigurator extends AbstractServiceConfigurator +{ + const FACTORY = 'services'; + + use Traits\AbstractTrait; + use Traits\ArgumentTrait; + use Traits\AutoconfigureTrait; + use Traits\AutowireTrait; + use Traits\BindTrait; + use Traits\CallTrait; + use Traits\ClassTrait; + use Traits\ConfiguratorTrait; + use Traits\DecorateTrait; + use Traits\DeprecateTrait; + use Traits\FactoryTrait; + use Traits\FileTrait; + use Traits\LazyTrait; + use Traits\ParentTrait; + use Traits\PropertyTrait; + use Traits\PublicTrait; + use Traits\ShareTrait; + use Traits\SyntheticTrait; + use Traits\TagTrait; + + private $container; + private $instanceof; + private $allowParent; + private $path; + + public function __construct(ContainerBuilder $container, array $instanceof, bool $allowParent, ServicesConfigurator $parent, Definition $definition, $id, array $defaultTags, string $path = null) + { + $this->container = $container; + $this->instanceof = $instanceof; + $this->allowParent = $allowParent; + $this->path = $path; + + parent::__construct($parent, $definition, $id, $defaultTags); + } + + public function __destruct() + { + parent::__destruct(); + + $this->container->removeBindings($this->id); + + if (!$this->definition instanceof ChildDefinition) { + $this->container->setDefinition($this->id, $this->definition->setInstanceofConditionals($this->instanceof)); + } else { + $this->container->setDefinition($this->id, $this->definition); + } + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php new file mode 100644 index 0000000..f0fdde8 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; + +/** + * @author Nicolas Grekas + */ +class ServicesConfigurator extends AbstractConfigurator +{ + const FACTORY = 'services'; + + private $defaults; + private $container; + private $loader; + private $instanceof; + private $path; + private $anonymousHash; + private $anonymousCount; + + public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, string $path = null, int &$anonymousCount = 0) + { + $this->defaults = new Definition(); + $this->container = $container; + $this->loader = $loader; + $this->instanceof = &$instanceof; + $this->path = $path; + $this->anonymousHash = ContainerBuilder::hash($path ?: mt_rand()); + $this->anonymousCount = &$anonymousCount; + $instanceof = []; + } + + /** + * Defines a set of defaults for following service definitions. + */ + final public function defaults(): DefaultsConfigurator + { + return new DefaultsConfigurator($this, $this->defaults = new Definition(), $this->path); + } + + /** + * Defines an instanceof-conditional to be applied to following service definitions. + */ + final public function instanceof(string $fqcn): InstanceofConfigurator + { + $this->instanceof[$fqcn] = $definition = new ChildDefinition(''); + + return new InstanceofConfigurator($this, $definition, $fqcn, $this->path); + } + + /** + * Registers a service. + * + * @param string|null $id The service id, or null to create an anonymous service + * @param string|null $class The class of the service, or null when $id is also the class name + */ + final public function set(?string $id, string $class = null): ServiceConfigurator + { + $defaults = $this->defaults; + $allowParent = !$defaults->getChanges() && empty($this->instanceof); + + $definition = new Definition(); + + if (null === $id) { + if (!$class) { + throw new \LogicException('Anonymous services must have a class name.'); + } + + $id = sprintf('.%d_%s', ++$this->anonymousCount, preg_replace('/^.*\\\\/', '', $class).'~'.$this->anonymousHash); + $definition->setPublic(false); + } else { + $definition->setPublic($defaults->isPublic()); + } + + $definition->setAutowired($defaults->isAutowired()); + $definition->setAutoconfigured($defaults->isAutoconfigured()); + $definition->setBindings($defaults->getBindings()); + $definition->setChanges([]); + + $configurator = new ServiceConfigurator($this->container, $this->instanceof, $allowParent, $this, $definition, $id, $defaults->getTags(), $this->path); + + return null !== $class ? $configurator->class($class) : $configurator; + } + + /** + * Creates an alias. + */ + final public function alias(string $id, string $referencedId): AliasConfigurator + { + $ref = static::processValue($referencedId, true); + $alias = new Alias((string) $ref, $this->defaults->isPublic()); + $this->container->setAlias($id, $alias); + + return new AliasConfigurator($this, $alias); + } + + /** + * Registers a PSR-4 namespace using a glob pattern. + */ + final public function load(string $namespace, string $resource): PrototypeConfigurator + { + $allowParent = !$this->defaults->getChanges() && empty($this->instanceof); + + return new PrototypeConfigurator($this, $this->loader, $this->defaults, $namespace, $resource, $allowParent); + } + + /** + * Gets an already defined service definition. + * + * @throws ServiceNotFoundException if the service definition does not exist + */ + final public function get(string $id): ServiceConfigurator + { + $allowParent = !$this->defaults->getChanges() && empty($this->instanceof); + $definition = $this->container->getDefinition($id); + + return new ServiceConfigurator($this->container, $definition->getInstanceofConditionals(), $allowParent, $this, $definition, $id, []); + } + + /** + * Registers a service. + */ + final public function __invoke(string $id, string $class = null): ServiceConfigurator + { + return $this->set($id, $class); + } + + public function __destruct() + { + $this->loader->registerAliasesForSinglyImplementedInterfaces(); + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php new file mode 100644 index 0000000..82ba21d --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait AbstractTrait +{ + /** + * Whether this definition is abstract, that means it merely serves as a + * template for other definitions. + * + * @return $this + */ + final public function abstract(bool $abstract = true): self + { + $this->definition->setAbstract($abstract); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php new file mode 100644 index 0000000..5c9a475 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait ArgumentTrait +{ + /** + * Sets the arguments to pass to the service constructor/factory method. + * + * @return $this + */ + final public function args(array $arguments): self + { + $this->definition->setArguments(static::processValue($arguments, true)); + + return $this; + } + + /** + * Sets one argument to pass to the service constructor/factory method. + * + * @param string|int $key + * @param mixed $value + * + * @return $this + */ + final public function arg($key, $value): self + { + $this->definition->setArgument($key, static::processValue($value, true)); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php new file mode 100644 index 0000000..836f458 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +trait AutoconfigureTrait +{ + /** + * Sets whether or not instanceof conditionals should be prepended with a global set. + * + * @return $this + * + * @throws InvalidArgumentException when a parent is already set + */ + final public function autoconfigure(bool $autoconfigured = true): self + { + if ($autoconfigured && $this->definition instanceof ChildDefinition) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try disabling autoconfiguration for the service.', $this->id)); + } + $this->definition->setAutoconfigured($autoconfigured); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php new file mode 100644 index 0000000..2837a02 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait AutowireTrait +{ + /** + * Enables/disables autowiring. + * + * @return $this + */ + final public function autowire(bool $autowired = true): self + { + $this->definition->setAutowired($autowired); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php new file mode 100644 index 0000000..1328494 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\Argument\BoundArgument; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Loader\Configurator\DefaultsConfigurator; +use Symfony\Component\DependencyInjection\Loader\Configurator\InstanceofConfigurator; +use Symfony\Component\DependencyInjection\Reference; + +trait BindTrait +{ + /** + * Sets bindings. + * + * Bindings map $named or FQCN arguments to values that should be + * injected in the matching parameters (of the constructor, of methods + * called and of controller actions). + * + * @param string $nameOrFqcn A parameter name with its "$" prefix, or a FQCN + * @param mixed $valueOrRef The value or reference to bind + * + * @return $this + */ + final public function bind(string $nameOrFqcn, $valueOrRef): self + { + $valueOrRef = static::processValue($valueOrRef, true); + if (!preg_match('/^(?:(?:array|bool|float|int|string)[ \t]*+)?\$/', $nameOrFqcn) && !$valueOrRef instanceof Reference) { + throw new InvalidArgumentException(sprintf('Invalid binding for service "%s": named arguments must start with a "$", and FQCN must map to references. Neither applies to binding "%s".', $this->id, $nameOrFqcn)); + } + $bindings = $this->definition->getBindings(); + $type = $this instanceof DefaultsConfigurator ? BoundArgument::DEFAULTS_BINDING : ($this instanceof InstanceofConfigurator ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING); + $bindings[$nameOrFqcn] = new BoundArgument($valueOrRef, true, $type, $this->path ?? null); + $this->definition->setBindings($bindings); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php new file mode 100644 index 0000000..28f92d2 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +trait CallTrait +{ + /** + * Adds a method to call after service initialization. + * + * @param string $method The method name to call + * @param array $arguments An array of arguments to pass to the method call + * @param bool $returnsClone Whether the call returns the service instance or not + * + * @return $this + * + * @throws InvalidArgumentException on empty $method param + */ + final public function call(string $method, array $arguments = [], bool $returnsClone = false): self + { + $this->definition->addMethodCall($method, static::processValue($arguments, true), $returnsClone); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php new file mode 100644 index 0000000..20da791 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait ClassTrait +{ + /** + * Sets the service class. + * + * @return $this + */ + final public function class(?string $class): self + { + $this->definition->setClass($class); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php new file mode 100644 index 0000000..25d363c --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait ConfiguratorTrait +{ + /** + * Sets a configurator to call after the service is fully initialized. + * + * @param string|array $configurator A PHP callable reference + * + * @return $this + */ + final public function configurator($configurator): self + { + $this->definition->setConfigurator(static::processValue($configurator, true)); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php new file mode 100644 index 0000000..b3a1ae1 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +trait DecorateTrait +{ + /** + * Sets the service that this service is decorating. + * + * @param string|null $id The decorated service id, use null to remove decoration + * + * @return $this + * + * @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals + */ + final public function decorate(?string $id, string $renamedId = null, int $priority = 0, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE): self + { + $this->definition->setDecoratedService($id, $renamedId, $priority, $invalidBehavior); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php new file mode 100644 index 0000000..b2d5b0e --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +trait DeprecateTrait +{ + /** + * Whether this definition is deprecated, that means it should not be called anymore. + * + * @param string $template Template message to use if the definition is deprecated + * + * @return $this + * + * @throws InvalidArgumentException when the message template is invalid + */ + final public function deprecate(string $template = null): self + { + $this->definition->setDeprecated(true, $template); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php new file mode 100644 index 0000000..3834d72 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +trait FactoryTrait +{ + /** + * Sets a factory. + * + * @param string|array $factory A PHP callable reference + * + * @return $this + */ + final public function factory($factory): self + { + if (\is_string($factory) && 1 === substr_count($factory, ':')) { + $factoryParts = explode(':', $factory); + + throw new InvalidArgumentException(sprintf('Invalid factory "%s": the "service:method" notation is not available when using PHP-based DI configuration. Use "[ref(\'%s\'), \'%s\']" instead.', $factory, $factoryParts[0], $factoryParts[1])); + } + + $this->definition->setFactory(static::processValue($factory, true)); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php new file mode 100644 index 0000000..5f42aef --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait FileTrait +{ + /** + * Sets a file to require before creating the service. + * + * @return $this + */ + final public function file(string $file): self + { + $this->definition->setFile($file); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php new file mode 100644 index 0000000..2829def --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait LazyTrait +{ + /** + * Sets the lazy flag of this service. + * + * @param bool|string $lazy A FQCN to derivate the lazy proxy from or `true` to make it extend from the definition's class + * + * @return $this + */ + final public function lazy($lazy = true): self + { + $this->definition->setLazy((bool) $lazy); + if (\is_string($lazy)) { + $this->definition->addTag('proxy', ['interface' => $lazy]); + } + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php new file mode 100644 index 0000000..7488a38 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +trait ParentTrait +{ + /** + * Sets the Definition to inherit from. + * + * @return $this + * + * @throws InvalidArgumentException when parent cannot be set + */ + final public function parent(string $parent): self + { + if (!$this->allowParent) { + throw new InvalidArgumentException(sprintf('A parent cannot be defined when either "_instanceof" or "_defaults" are also defined for service prototype "%s".', $this->id)); + } + + if ($this->definition instanceof ChildDefinition) { + $this->definition->setParent($parent); + } elseif ($this->definition->isAutoconfigured()) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try disabling autoconfiguration for the service.', $this->id)); + } elseif ($this->definition->getBindings()) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also "bind" arguments.', $this->id)); + } else { + // cast Definition to ChildDefinition + $definition = serialize($this->definition); + $definition = substr_replace($definition, '53', 2, 2); + $definition = substr_replace($definition, 'Child', 44, 0); + $definition = unserialize($definition); + + $this->definition = $definition->setParent($parent); + } + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php new file mode 100644 index 0000000..10fdcfb --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait PropertyTrait +{ + /** + * Sets a specific property. + * + * @return $this + */ + final public function property(string $name, $value): self + { + $this->definition->setProperty($name, static::processValue($value, true)); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php new file mode 100644 index 0000000..f15756c --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait PublicTrait +{ + /** + * @return $this + */ + final public function public(): self + { + $this->definition->setPublic(true); + + return $this; + } + + /** + * @return $this + */ + final public function private(): self + { + $this->definition->setPublic(false); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php new file mode 100644 index 0000000..16fde0f --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait ShareTrait +{ + /** + * Sets if the service must be shared or not. + * + * @return $this + */ + final public function share(bool $shared = true): self + { + $this->definition->setShared($shared); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php new file mode 100644 index 0000000..cb08b11 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait SyntheticTrait +{ + /** + * Sets whether this definition is synthetic, that is not constructed by the + * container, but dynamically injected. + * + * @return $this + */ + final public function synthetic(bool $synthetic = true): self + { + $this->definition->setSynthetic($synthetic); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php new file mode 100644 index 0000000..f4d5f00 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +trait TagTrait +{ + /** + * Adds a tag for this definition. + * + * @return $this + */ + final public function tag(string $name, array $attributes = []): self + { + if ('' === $name) { + throw new InvalidArgumentException(sprintf('The tag name for service "%s" must be a non-empty string.', $this->id)); + } + + foreach ($attributes as $attribute => $value) { + if (!is_scalar($value) && null !== $value) { + throw new InvalidArgumentException(sprintf('A tag attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $this->id, $name, $attribute)); + } + } + + $this->definition->addTag($name, $attributes); + + return $this; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/DirectoryLoader.php b/vendor/symfony/dependency-injection/Loader/DirectoryLoader.php new file mode 100644 index 0000000..9439869 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/DirectoryLoader.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader; + +/** + * DirectoryLoader is a recursive loader to go through directories. + * + * @author Sebastien Lavoie + */ +class DirectoryLoader extends FileLoader +{ + /** + * {@inheritdoc} + */ + public function load($file, string $type = null) + { + $file = rtrim($file, '/'); + $path = $this->locator->locate($file); + $this->container->fileExists($path, false); + + foreach (scandir($path) as $dir) { + if ('.' !== $dir[0]) { + if (is_dir($path.'/'.$dir)) { + $dir .= '/'; // append / to allow recursion + } + + $this->setCurrentDir($path); + + $this->import($dir, null, false, $path); + } + } + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + if ('directory' === $type) { + return true; + } + + return null === $type && \is_string($resource) && '/' === substr($resource, -1); + } +} diff --git a/vendor/symfony/dependency-injection/Loader/FileLoader.php b/vendor/symfony/dependency-injection/Loader/FileLoader.php new file mode 100644 index 0000000..26577c9 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/FileLoader.php @@ -0,0 +1,225 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader; + +use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; +use Symfony\Component\Config\Exception\LoaderLoadException; +use Symfony\Component\Config\FileLocatorInterface; +use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader; +use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\Config\Resource\GlobResource; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +/** + * FileLoader is the abstract class used by all built-in loaders that are file based. + * + * @author Fabien Potencier + */ +abstract class FileLoader extends BaseFileLoader +{ + public const ANONYMOUS_ID_REGEXP = '/^\.\d+_[^~]*+~[._a-zA-Z\d]{7}$/'; + + protected $container; + protected $isLoadingInstanceof = false; + protected $instanceof = []; + protected $interfaces = []; + protected $singlyImplemented = []; + protected $autoRegisterAliasesForSinglyImplementedInterfaces = true; + + public function __construct(ContainerBuilder $container, FileLocatorInterface $locator) + { + $this->container = $container; + + parent::__construct($locator); + } + + /** + * {@inheritdoc} + * + * @param bool|string $ignoreErrors Whether errors should be ignored; pass "not_found" to ignore only when the loaded resource is not found + */ + public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null, $exclude = null) + { + $args = \func_get_args(); + + if ($ignoreNotFound = 'not_found' === $ignoreErrors) { + $args[2] = false; + } elseif (!\is_bool($ignoreErrors)) { + throw new \TypeError(sprintf('Invalid argument $ignoreErrors provided to %s::import(): boolean or "not_found" expected, %s given.', \get_class($this), \gettype($ignoreErrors))); + } + + try { + parent::import(...$args); + } catch (LoaderLoadException $e) { + if (!$ignoreNotFound || !($prev = $e->getPrevious()) instanceof FileLocatorFileNotFoundException) { + throw $e; + } + + foreach ($prev->getTrace() as $frame) { + if ('import' === ($frame['function'] ?? null) && is_a($frame['class'] ?? '', Loader::class, true)) { + break; + } + } + + if (__FILE__ !== $frame['file']) { + throw $e; + } + } + } + + /** + * Registers a set of classes as services using PSR-4 for discovery. + * + * @param Definition $prototype A definition to use as template + * @param string $namespace The namespace prefix of classes in the scanned directory + * @param string $resource The directory to look for classes, glob-patterns allowed + * @param string|string[]|null $exclude A globbed path of files to exclude or an array of globbed paths of files to exclude + */ + public function registerClasses(Definition $prototype, $namespace, $resource, $exclude = null) + { + if ('\\' !== substr($namespace, -1)) { + throw new InvalidArgumentException(sprintf('Namespace prefix must end with a "\\": %s.', $namespace)); + } + if (!preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+\\\\)++$/', $namespace)) { + throw new InvalidArgumentException(sprintf('Namespace is not a valid PSR-4 prefix: %s.', $namespace)); + } + + $classes = $this->findClasses($namespace, $resource, (array) $exclude); + // prepare for deep cloning + $serializedPrototype = serialize($prototype); + + foreach ($classes as $class => $errorMessage) { + if (interface_exists($class, false)) { + $this->interfaces[] = $class; + } else { + $this->setDefinition($class, $definition = unserialize($serializedPrototype)); + if (null !== $errorMessage) { + $definition->addError($errorMessage); + + continue; + } + foreach (class_implements($class, false) as $interface) { + $this->singlyImplemented[$interface] = ($this->singlyImplemented[$interface] ?? $class) !== $class ? false : $class; + } + } + } + + if ($this->autoRegisterAliasesForSinglyImplementedInterfaces) { + $this->registerAliasesForSinglyImplementedInterfaces(); + } + } + + public function registerAliasesForSinglyImplementedInterfaces() + { + foreach ($this->interfaces as $interface) { + if (!empty($this->singlyImplemented[$interface]) && !$this->container->has($interface)) { + $this->container->setAlias($interface, $this->singlyImplemented[$interface])->setPublic(false); + } + } + + $this->interfaces = $this->singlyImplemented = []; + } + + /** + * Registers a definition in the container with its instanceof-conditionals. + * + * @param string $id + */ + protected function setDefinition($id, Definition $definition) + { + $this->container->removeBindings($id); + + if ($this->isLoadingInstanceof) { + if (!$definition instanceof ChildDefinition) { + throw new InvalidArgumentException(sprintf('Invalid type definition "%s": ChildDefinition expected, "%s" given.', $id, \get_class($definition))); + } + $this->instanceof[$id] = $definition; + } else { + $this->container->setDefinition($id, $definition instanceof ChildDefinition ? $definition : $definition->setInstanceofConditionals($this->instanceof)); + } + } + + private function findClasses(string $namespace, string $pattern, array $excludePatterns): array + { + $parameterBag = $this->container->getParameterBag(); + + $excludePaths = []; + $excludePrefix = null; + $excludePatterns = $parameterBag->unescapeValue($parameterBag->resolveValue($excludePatterns)); + foreach ($excludePatterns as $excludePattern) { + foreach ($this->glob($excludePattern, true, $resource, false, true) as $path => $info) { + if (null === $excludePrefix) { + $excludePrefix = $resource->getPrefix(); + } + + // normalize Windows slashes + $excludePaths[str_replace('\\', '/', $path)] = true; + } + } + + $pattern = $parameterBag->unescapeValue($parameterBag->resolveValue($pattern)); + $classes = []; + $extRegexp = '/\\.php$/'; + $prefixLen = null; + foreach ($this->glob($pattern, true, $resource, false, false, $excludePaths) as $path => $info) { + if (null === $prefixLen) { + $prefixLen = \strlen($resource->getPrefix()); + + if ($excludePrefix && 0 !== strpos($excludePrefix, $resource->getPrefix())) { + throw new InvalidArgumentException(sprintf('Invalid "exclude" pattern when importing classes for "%s": make sure your "exclude" pattern (%s) is a subset of the "resource" pattern (%s)', $namespace, $excludePattern, $pattern)); + } + } + + if (isset($excludePaths[str_replace('\\', '/', $path)])) { + continue; + } + + if (!preg_match($extRegexp, $path, $m) || !$info->isReadable()) { + continue; + } + $class = $namespace.ltrim(str_replace('/', '\\', substr($path, $prefixLen, -\strlen($m[0]))), '\\'); + + if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $class)) { + continue; + } + + try { + $r = $this->container->getReflectionClass($class); + } catch (\ReflectionException $e) { + $classes[$class] = $e->getMessage(); + continue; + } + // check to make sure the expected class exists + if (!$r) { + throw new InvalidArgumentException(sprintf('Expected to find class "%s" in file "%s" while importing services from resource "%s", but it was not found! Check the namespace prefix used with the resource.', $class, $path, $pattern)); + } + + if ($r->isInstantiable() || $r->isInterface()) { + $classes[$class] = null; + } + } + + // track only for new & removed files + if ($resource instanceof GlobResource) { + $this->container->addResource($resource); + } else { + foreach ($resource as $path) { + $this->container->fileExists($path, false); + } + } + + return $classes; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/GlobFileLoader.php b/vendor/symfony/dependency-injection/Loader/GlobFileLoader.php new file mode 100644 index 0000000..53af9cf --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/GlobFileLoader.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader; + +/** + * GlobFileLoader loads files from a glob pattern. + * + * @author Nicolas Grekas + */ +class GlobFileLoader extends FileLoader +{ + /** + * {@inheritdoc} + */ + public function load($resource, string $type = null) + { + foreach ($this->glob($resource, false, $globResource) as $path => $info) { + $this->import($path); + } + + $this->container->addResource($globResource); + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + return 'glob' === $type; + } +} diff --git a/vendor/symfony/dependency-injection/Loader/IniFileLoader.php b/vendor/symfony/dependency-injection/Loader/IniFileLoader.php new file mode 100644 index 0000000..8ed1e42 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/IniFileLoader.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader; + +use Symfony\Component\Config\Util\XmlUtils; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +/** + * IniFileLoader loads parameters from INI files. + * + * @author Fabien Potencier + */ +class IniFileLoader extends FileLoader +{ + /** + * {@inheritdoc} + */ + public function load($resource, string $type = null) + { + $path = $this->locator->locate($resource); + + $this->container->fileExists($path); + + // first pass to catch parsing errors + $result = parse_ini_file($path, true); + if (false === $result || [] === $result) { + throw new InvalidArgumentException(sprintf('The "%s" file is not valid.', $resource)); + } + + // real raw parsing + $result = parse_ini_file($path, true, INI_SCANNER_RAW); + + if (isset($result['parameters']) && \is_array($result['parameters'])) { + foreach ($result['parameters'] as $key => $value) { + $this->container->setParameter($key, $this->phpize($value)); + } + } + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + if (!\is_string($resource)) { + return false; + } + + if (null === $type && 'ini' === pathinfo($resource, PATHINFO_EXTENSION)) { + return true; + } + + return 'ini' === $type; + } + + /** + * Note that the following features are not supported: + * * strings with escaped quotes are not supported "foo\"bar"; + * * string concatenation ("foo" "bar"). + * + * @return mixed + */ + private function phpize(string $value) + { + // trim on the right as comments removal keep whitespaces + if ($value !== $v = rtrim($value)) { + $value = '""' === substr_replace($v, '', 1, -1) ? substr($v, 1, -1) : $v; + } + $lowercaseValue = strtolower($value); + + switch (true) { + case \defined($value): + return \constant($value); + case 'yes' === $lowercaseValue || 'on' === $lowercaseValue: + return true; + case 'no' === $lowercaseValue || 'off' === $lowercaseValue || 'none' === $lowercaseValue: + return false; + case isset($value[1]) && ( + ("'" === $value[0] && "'" === $value[\strlen($value) - 1]) || + ('"' === $value[0] && '"' === $value[\strlen($value) - 1]) + ): + // quoted string + return substr($value, 1, -1); + default: + return XmlUtils::phpize($value); + } + } +} diff --git a/vendor/symfony/dependency-injection/Loader/PhpFileLoader.php b/vendor/symfony/dependency-injection/Loader/PhpFileLoader.php new file mode 100644 index 0000000..207fb83 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/PhpFileLoader.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader; + +use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; + +/** + * PhpFileLoader loads service definitions from a PHP file. + * + * The PHP file is required and the $container variable can be + * used within the file to change the container. + * + * @author Fabien Potencier + */ +class PhpFileLoader extends FileLoader +{ + protected $autoRegisterAliasesForSinglyImplementedInterfaces = false; + + /** + * {@inheritdoc} + */ + public function load($resource, $type = null) + { + // the container and loader variables are exposed to the included file below + $container = $this->container; + $loader = $this; + + $path = $this->locator->locate($resource); + $this->setCurrentDir(\dirname($path)); + $this->container->fileExists($path); + + // the closure forbids access to the private scope in the included file + $load = \Closure::bind(function ($path) use ($container, $loader, $resource, $type) { + return include $path; + }, $this, ProtectedPhpFileLoader::class); + + try { + $callback = $load($path); + + if (\is_object($callback) && \is_callable($callback)) { + $callback(new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource), $this->container, $this); + } + } finally { + $this->instanceof = []; + $this->registerAliasesForSinglyImplementedInterfaces(); + } + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + if (!\is_string($resource)) { + return false; + } + + if (null === $type && 'php' === pathinfo($resource, PATHINFO_EXTENSION)) { + return true; + } + + return 'php' === $type; + } +} + +/** + * @internal + */ +final class ProtectedPhpFileLoader extends PhpFileLoader +{ +} diff --git a/vendor/symfony/dependency-injection/Loader/XmlFileLoader.php b/vendor/symfony/dependency-injection/Loader/XmlFileLoader.php new file mode 100644 index 0000000..82e61b6 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/XmlFileLoader.php @@ -0,0 +1,728 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader; + +use Symfony\Component\Config\Util\XmlUtils; +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Argument\BoundArgument; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\ExpressionLanguage\Expression; + +/** + * XmlFileLoader loads XML files service definitions. + * + * @author Fabien Potencier + */ +class XmlFileLoader extends FileLoader +{ + const NS = 'http://symfony.com/schema/dic/services'; + + protected $autoRegisterAliasesForSinglyImplementedInterfaces = false; + + /** + * {@inheritdoc} + */ + public function load($resource, string $type = null) + { + $path = $this->locator->locate($resource); + + $xml = $this->parseFileToDOM($path); + + $this->container->fileExists($path); + + $defaults = $this->getServiceDefaults($xml, $path); + + // anonymous services + $this->processAnonymousServices($xml, $path); + + // imports + $this->parseImports($xml, $path); + + // parameters + $this->parseParameters($xml, $path); + + // extensions + $this->loadFromExtensions($xml); + + // services + try { + $this->parseDefinitions($xml, $path, $defaults); + } finally { + $this->instanceof = []; + $this->registerAliasesForSinglyImplementedInterfaces(); + } + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + if (!\is_string($resource)) { + return false; + } + + if (null === $type && 'xml' === pathinfo($resource, PATHINFO_EXTENSION)) { + return true; + } + + return 'xml' === $type; + } + + private function parseParameters(\DOMDocument $xml, string $file) + { + if ($parameters = $this->getChildren($xml->documentElement, 'parameters')) { + $this->container->getParameterBag()->add($this->getArgumentsAsPhp($parameters[0], 'parameter', $file)); + } + } + + private function parseImports(\DOMDocument $xml, string $file) + { + $xpath = new \DOMXPath($xml); + $xpath->registerNamespace('container', self::NS); + + if (false === $imports = $xpath->query('//container:imports/container:import')) { + return; + } + + $defaultDirectory = \dirname($file); + foreach ($imports as $import) { + $this->setCurrentDir($defaultDirectory); + $this->import($import->getAttribute('resource'), XmlUtils::phpize($import->getAttribute('type')) ?: null, XmlUtils::phpize($import->getAttribute('ignore-errors')) ?: false, $file); + } + } + + private function parseDefinitions(\DOMDocument $xml, string $file, array $defaults) + { + $xpath = new \DOMXPath($xml); + $xpath->registerNamespace('container', self::NS); + + if (false === $services = $xpath->query('//container:services/container:service|//container:services/container:prototype')) { + return; + } + $this->setCurrentDir(\dirname($file)); + + $this->instanceof = []; + $this->isLoadingInstanceof = true; + $instanceof = $xpath->query('//container:services/container:instanceof'); + foreach ($instanceof as $service) { + $this->setDefinition((string) $service->getAttribute('id'), $this->parseDefinition($service, $file, [])); + } + + $this->isLoadingInstanceof = false; + foreach ($services as $service) { + if (null !== $definition = $this->parseDefinition($service, $file, $defaults)) { + if ('prototype' === $service->tagName) { + $excludes = array_column($this->getChildren($service, 'exclude'), 'nodeValue'); + if ($service->hasAttribute('exclude')) { + if (\count($excludes) > 0) { + throw new InvalidArgumentException('You cannot use both the attribute "exclude" and tags at the same time.'); + } + $excludes = [$service->getAttribute('exclude')]; + } + $this->registerClasses($definition, (string) $service->getAttribute('namespace'), (string) $service->getAttribute('resource'), $excludes); + } else { + $this->setDefinition((string) $service->getAttribute('id'), $definition); + } + } + } + } + + /** + * Get service defaults. + */ + private function getServiceDefaults(\DOMDocument $xml, string $file): array + { + $xpath = new \DOMXPath($xml); + $xpath->registerNamespace('container', self::NS); + + if (null === $defaultsNode = $xpath->query('//container:services/container:defaults')->item(0)) { + return []; + } + + $bindings = []; + foreach ($this->getArgumentsAsPhp($defaultsNode, 'bind', $file) as $argument => $value) { + $bindings[$argument] = new BoundArgument($value, true, BoundArgument::DEFAULTS_BINDING, $file); + } + + $defaults = [ + 'tags' => $this->getChildren($defaultsNode, 'tag'), + 'bind' => $bindings, + ]; + + foreach ($defaults['tags'] as $tag) { + if ('' === $tag->getAttribute('name')) { + throw new InvalidArgumentException(sprintf('The tag name for tag "" in %s must be a non-empty string.', $file)); + } + } + + if ($defaultsNode->hasAttribute('autowire')) { + $defaults['autowire'] = XmlUtils::phpize($defaultsNode->getAttribute('autowire')); + } + if ($defaultsNode->hasAttribute('public')) { + $defaults['public'] = XmlUtils::phpize($defaultsNode->getAttribute('public')); + } + if ($defaultsNode->hasAttribute('autoconfigure')) { + $defaults['autoconfigure'] = XmlUtils::phpize($defaultsNode->getAttribute('autoconfigure')); + } + + return $defaults; + } + + /** + * Parses an individual Definition. + */ + private function parseDefinition(\DOMElement $service, string $file, array $defaults): ?Definition + { + if ($alias = $service->getAttribute('alias')) { + $this->validateAlias($service, $file); + + $this->container->setAlias((string) $service->getAttribute('id'), $alias = new Alias($alias)); + if ($publicAttr = $service->getAttribute('public')) { + $alias->setPublic(XmlUtils::phpize($publicAttr)); + } elseif (isset($defaults['public'])) { + $alias->setPublic($defaults['public']); + } + + if ($deprecated = $this->getChildren($service, 'deprecated')) { + $alias->setDeprecated(true, $deprecated[0]->nodeValue ?: null); + } + + return null; + } + + if ($this->isLoadingInstanceof) { + $definition = new ChildDefinition(''); + } elseif ($parent = $service->getAttribute('parent')) { + if (!empty($this->instanceof)) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot use the "parent" option in the same file where "instanceof" configuration is defined as using both is not supported. Move your child definitions to a separate file.', $service->getAttribute('id'))); + } + + foreach ($defaults as $k => $v) { + if ('tags' === $k) { + // since tags are never inherited from parents, there is no confusion + // thus we can safely add them as defaults to ChildDefinition + continue; + } + if ('bind' === $k) { + if ($defaults['bind']) { + throw new InvalidArgumentException(sprintf('Bound values on service "%s" cannot be inherited from "defaults" when a "parent" is set. Move your child definitions to a separate file.', $service->getAttribute('id'))); + } + + continue; + } + if (!$service->hasAttribute($k)) { + throw new InvalidArgumentException(sprintf('Attribute "%s" on service "%s" cannot be inherited from "defaults" when a "parent" is set. Move your child definitions to a separate file or define this attribute explicitly.', $k, $service->getAttribute('id'))); + } + } + + $definition = new ChildDefinition($parent); + } else { + $definition = new Definition(); + + if (isset($defaults['public'])) { + $definition->setPublic($defaults['public']); + } + if (isset($defaults['autowire'])) { + $definition->setAutowired($defaults['autowire']); + } + if (isset($defaults['autoconfigure'])) { + $definition->setAutoconfigured($defaults['autoconfigure']); + } + + $definition->setChanges([]); + } + + foreach (['class', 'public', 'shared', 'synthetic', 'abstract'] as $key) { + if ($value = $service->getAttribute($key)) { + $method = 'set'.$key; + $definition->$method($value = XmlUtils::phpize($value)); + } + } + + if ($value = $service->getAttribute('lazy')) { + $definition->setLazy((bool) $value = XmlUtils::phpize($value)); + if (\is_string($value)) { + $definition->addTag('proxy', ['interface' => $value]); + } + } + + if ($value = $service->getAttribute('autowire')) { + $definition->setAutowired(XmlUtils::phpize($value)); + } + + if ($value = $service->getAttribute('autoconfigure')) { + if (!$definition instanceof ChildDefinition) { + $definition->setAutoconfigured(XmlUtils::phpize($value)); + } elseif ($value = XmlUtils::phpize($value)) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try setting autoconfigure="false" for the service.', $service->getAttribute('id'))); + } + } + + if ($files = $this->getChildren($service, 'file')) { + $definition->setFile($files[0]->nodeValue); + } + + if ($deprecated = $this->getChildren($service, 'deprecated')) { + $definition->setDeprecated(true, $deprecated[0]->nodeValue ?: null); + } + + $definition->setArguments($this->getArgumentsAsPhp($service, 'argument', $file, $definition instanceof ChildDefinition)); + $definition->setProperties($this->getArgumentsAsPhp($service, 'property', $file)); + + if ($factories = $this->getChildren($service, 'factory')) { + $factory = $factories[0]; + if ($function = $factory->getAttribute('function')) { + $definition->setFactory($function); + } else { + if ($childService = $factory->getAttribute('service')) { + $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE); + } else { + $class = $factory->hasAttribute('class') ? $factory->getAttribute('class') : null; + } + + $definition->setFactory([$class, $factory->getAttribute('method') ?: '__invoke']); + } + } + + if ($configurators = $this->getChildren($service, 'configurator')) { + $configurator = $configurators[0]; + if ($function = $configurator->getAttribute('function')) { + $definition->setConfigurator($function); + } else { + if ($childService = $configurator->getAttribute('service')) { + $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE); + } else { + $class = $configurator->getAttribute('class'); + } + + $definition->setConfigurator([$class, $configurator->getAttribute('method') ?: '__invoke']); + } + } + + foreach ($this->getChildren($service, 'call') as $call) { + $definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument', $file), XmlUtils::phpize($call->getAttribute('returns-clone'))); + } + + $tags = $this->getChildren($service, 'tag'); + + if (!empty($defaults['tags'])) { + $tags = array_merge($tags, $defaults['tags']); + } + + foreach ($tags as $tag) { + $parameters = []; + foreach ($tag->attributes as $name => $node) { + if ('name' === $name) { + continue; + } + + if (false !== strpos($name, '-') && false === strpos($name, '_') && !\array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) { + $parameters[$normalizedName] = XmlUtils::phpize($node->nodeValue); + } + // keep not normalized key + $parameters[$name] = XmlUtils::phpize($node->nodeValue); + } + + if ('' === $tag->getAttribute('name')) { + throw new InvalidArgumentException(sprintf('The tag name for service "%s" in %s must be a non-empty string.', (string) $service->getAttribute('id'), $file)); + } + + $definition->addTag($tag->getAttribute('name'), $parameters); + } + + $bindings = $this->getArgumentsAsPhp($service, 'bind', $file); + $bindingType = $this->isLoadingInstanceof ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING; + foreach ($bindings as $argument => $value) { + $bindings[$argument] = new BoundArgument($value, true, $bindingType, $file); + } + + if (isset($defaults['bind'])) { + // deep clone, to avoid multiple process of the same instance in the passes + $bindings = array_merge(unserialize(serialize($defaults['bind'])), $bindings); + } + if ($bindings) { + $definition->setBindings($bindings); + } + + if ($decorates = $service->getAttribute('decorates')) { + $decorationOnInvalid = $service->getAttribute('decoration-on-invalid') ?: 'exception'; + if ('exception' === $decorationOnInvalid) { + $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + } elseif ('ignore' === $decorationOnInvalid) { + $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; + } elseif ('null' === $decorationOnInvalid) { + $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; + } else { + throw new InvalidArgumentException(sprintf('Invalid value "%s" for attribute "decoration-on-invalid" on service "%s". Did you mean "exception", "ignore" or "null" in "%s"?', $decorationOnInvalid, (string) $service->getAttribute('id'), $file)); + } + + $renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null; + $priority = $service->hasAttribute('decoration-priority') ? $service->getAttribute('decoration-priority') : 0; + + $definition->setDecoratedService($decorates, $renameId, $priority, $invalidBehavior); + } + + return $definition; + } + + /** + * Parses a XML file to a \DOMDocument. + * + * @throws InvalidArgumentException When loading of XML file returns error + */ + private function parseFileToDOM(string $file): \DOMDocument + { + try { + $dom = XmlUtils::loadFile($file, [$this, 'validateSchema']); + } catch (\InvalidArgumentException $e) { + throw new InvalidArgumentException(sprintf('Unable to parse file "%s": %s', $file, $e->getMessage()), $e->getCode(), $e); + } + + $this->validateExtensions($dom, $file); + + return $dom; + } + + /** + * Processes anonymous services. + */ + private function processAnonymousServices(\DOMDocument $xml, string $file) + { + $definitions = []; + $count = 0; + $suffix = '~'.ContainerBuilder::hash($file); + + $xpath = new \DOMXPath($xml); + $xpath->registerNamespace('container', self::NS); + + // anonymous services as arguments/properties + if (false !== $nodes = $xpath->query('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]|//container:bind[not(@id)]|//container:factory[not(@service)]|//container:configurator[not(@service)]')) { + foreach ($nodes as $node) { + if ($services = $this->getChildren($node, 'service')) { + // give it a unique name + $id = sprintf('.%d_%s', ++$count, preg_replace('/^.*\\\\/', '', $services[0]->getAttribute('class')).$suffix); + $node->setAttribute('id', $id); + $node->setAttribute('service', $id); + + $definitions[$id] = [$services[0], $file]; + $services[0]->setAttribute('id', $id); + + // anonymous services are always private + // we could not use the constant false here, because of XML parsing + $services[0]->setAttribute('public', 'false'); + } + } + } + + // anonymous services "in the wild" + if (false !== $nodes = $xpath->query('//container:services/container:service[not(@id)]')) { + foreach ($nodes as $node) { + throw new InvalidArgumentException(sprintf('Top-level services must have "id" attribute, none found in %s at line %d.', $file, $node->getLineNo())); + } + } + + // resolve definitions + uksort($definitions, 'strnatcmp'); + foreach (array_reverse($definitions) as $id => list($domElement, $file)) { + if (null !== $definition = $this->parseDefinition($domElement, $file, [])) { + $this->setDefinition($id, $definition); + } + } + } + + private function getArgumentsAsPhp(\DOMElement $node, string $name, string $file, bool $isChildDefinition = false): array + { + $arguments = []; + foreach ($this->getChildren($node, $name) as $arg) { + if ($arg->hasAttribute('name')) { + $arg->setAttribute('key', $arg->getAttribute('name')); + } + + // this is used by ChildDefinition to overwrite a specific + // argument of the parent definition + if ($arg->hasAttribute('index')) { + $key = ($isChildDefinition ? 'index_' : '').$arg->getAttribute('index'); + } elseif (!$arg->hasAttribute('key')) { + // Append an empty argument, then fetch its key to overwrite it later + $arguments[] = null; + $keys = array_keys($arguments); + $key = array_pop($keys); + } else { + $key = $arg->getAttribute('key'); + } + + $onInvalid = $arg->getAttribute('on-invalid'); + $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + if ('ignore' == $onInvalid) { + $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; + } elseif ('ignore_uninitialized' == $onInvalid) { + $invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; + } elseif ('null' == $onInvalid) { + $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; + } + + switch ($arg->getAttribute('type')) { + case 'service': + if ('' === $arg->getAttribute('id')) { + throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service" has no or empty "id" attribute in "%s".', $name, $file)); + } + + $arguments[$key] = new Reference($arg->getAttribute('id'), $invalidBehavior); + break; + case 'expression': + if (!class_exists(Expression::class)) { + throw new \LogicException(sprintf('The type="expression" attribute cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".')); + } + + $arguments[$key] = new Expression($arg->nodeValue); + break; + case 'collection': + $arguments[$key] = $this->getArgumentsAsPhp($arg, $name, $file); + break; + case 'iterator': + $arg = $this->getArgumentsAsPhp($arg, $name, $file); + try { + $arguments[$key] = new IteratorArgument($arg); + } catch (InvalidArgumentException $e) { + throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="iterator" only accepts collections of type="service" references in "%s".', $name, $file)); + } + break; + case 'service_locator': + $arg = $this->getArgumentsAsPhp($arg, $name, $file); + try { + $arguments[$key] = new ServiceLocatorArgument($arg); + } catch (InvalidArgumentException $e) { + throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service_locator" only accepts maps of type="service" references in "%s".', $name, $file)); + } + break; + case 'tagged': + case 'tagged_iterator': + case 'tagged_locator': + $type = $arg->getAttribute('type'); + $forLocator = 'tagged_locator' === $type; + + if (!$arg->getAttribute('tag')) { + throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="%s" has no or empty "tag" attribute in "%s".', $name, $type, $file)); + } + + $arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'), $arg->getAttribute('index-by') ?: null, $arg->getAttribute('default-index-method') ?: null, $forLocator, $arg->getAttribute('default-priority-method') ?: null); + + if ($forLocator) { + $arguments[$key] = new ServiceLocatorArgument($arguments[$key]); + } + break; + case 'binary': + if (false === $value = base64_decode($arg->nodeValue)) { + throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="binary" is not a valid base64 encoded string.', $name)); + } + $arguments[$key] = $value; + break; + case 'string': + $arguments[$key] = $arg->nodeValue; + break; + case 'constant': + $arguments[$key] = \constant(trim($arg->nodeValue)); + break; + default: + $arguments[$key] = XmlUtils::phpize($arg->nodeValue); + } + } + + return $arguments; + } + + /** + * Get child elements by name. + * + * @return \DOMElement[] + */ + private function getChildren(\DOMNode $node, string $name): array + { + $children = []; + foreach ($node->childNodes as $child) { + if ($child instanceof \DOMElement && $child->localName === $name && self::NS === $child->namespaceURI) { + $children[] = $child; + } + } + + return $children; + } + + /** + * Validates a documents XML schema. + * + * @return bool + * + * @throws RuntimeException When extension references a non-existent XSD file + */ + public function validateSchema(\DOMDocument $dom) + { + $schemaLocations = ['http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd')]; + + if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) { + $items = preg_split('/\s+/', $element); + for ($i = 0, $nb = \count($items); $i < $nb; $i += 2) { + if (!$this->container->hasExtension($items[$i])) { + continue; + } + + if (($extension = $this->container->getExtension($items[$i])) && false !== $extension->getXsdValidationBasePath()) { + $ns = $extension->getNamespace(); + $path = str_replace([$ns, str_replace('http://', 'https://', $ns)], str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]); + + if (!is_file($path)) { + throw new RuntimeException(sprintf('Extension "%s" references a non-existent XSD file "%s"', \get_class($extension), $path)); + } + + $schemaLocations[$items[$i]] = $path; + } + } + } + + $tmpfiles = []; + $imports = ''; + foreach ($schemaLocations as $namespace => $location) { + $parts = explode('/', $location); + $locationstart = 'file:///'; + if (0 === stripos($location, 'phar://')) { + $tmpfile = tempnam(sys_get_temp_dir(), 'symfony'); + if ($tmpfile) { + copy($location, $tmpfile); + $tmpfiles[] = $tmpfile; + $parts = explode('/', str_replace('\\', '/', $tmpfile)); + } else { + array_shift($parts); + $locationstart = 'phar:///'; + } + } + $drive = '\\' === \DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; + $location = $locationstart.$drive.implode('/', array_map('rawurlencode', $parts)); + + $imports .= sprintf(' '."\n", $namespace, $location); + } + + $source = << + + + +$imports + +EOF + ; + + $disableEntities = libxml_disable_entity_loader(false); + $valid = @$dom->schemaValidateSource($source); + libxml_disable_entity_loader($disableEntities); + + foreach ($tmpfiles as $tmpfile) { + @unlink($tmpfile); + } + + return $valid; + } + + private function validateAlias(\DOMElement $alias, string $file) + { + foreach ($alias->attributes as $name => $node) { + if (!\in_array($name, ['alias', 'id', 'public'])) { + throw new InvalidArgumentException(sprintf('Invalid attribute "%s" defined for alias "%s" in "%s".', $name, $alias->getAttribute('id'), $file)); + } + } + + foreach ($alias->childNodes as $child) { + if (!$child instanceof \DOMElement || self::NS !== $child->namespaceURI) { + continue; + } + if (!\in_array($child->localName, ['deprecated'], true)) { + throw new InvalidArgumentException(sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $alias->getAttribute('id'), $file)); + } + } + } + + /** + * Validates an extension. + * + * @throws InvalidArgumentException When no extension is found corresponding to a tag + */ + private function validateExtensions(\DOMDocument $dom, string $file) + { + foreach ($dom->documentElement->childNodes as $node) { + if (!$node instanceof \DOMElement || 'http://symfony.com/schema/dic/services' === $node->namespaceURI) { + continue; + } + + // can it be handled by an extension? + if (!$this->container->hasExtension($node->namespaceURI)) { + $extensionNamespaces = array_filter(array_map(function (ExtensionInterface $ext) { return $ext->getNamespace(); }, $this->container->getExtensions())); + throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $node->tagName, $file, $node->namespaceURI, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none')); + } + } + } + + /** + * Loads from an extension. + */ + private function loadFromExtensions(\DOMDocument $xml) + { + foreach ($xml->documentElement->childNodes as $node) { + if (!$node instanceof \DOMElement || self::NS === $node->namespaceURI) { + continue; + } + + $values = static::convertDomElementToArray($node); + if (!\is_array($values)) { + $values = []; + } + + $this->container->loadFromExtension($node->namespaceURI, $values); + } + } + + /** + * Converts a \DOMElement object to a PHP array. + * + * The following rules applies during the conversion: + * + * * Each tag is converted to a key value or an array + * if there is more than one "value" + * + * * The content of a tag is set under a "value" key (bar) + * if the tag also has some nested tags + * + * * The attributes are converted to keys () + * + * * The nested-tags are converted to keys (bar) + * + * @param \DOMElement $element A \DOMElement instance + * + * @return mixed + */ + public static function convertDomElementToArray(\DOMElement $element) + { + return XmlUtils::convertDomElementToArray($element); + } +} diff --git a/vendor/symfony/dependency-injection/Loader/YamlFileLoader.php b/vendor/symfony/dependency-injection/Loader/YamlFileLoader.php new file mode 100644 index 0000000..cb17e57 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/YamlFileLoader.php @@ -0,0 +1,872 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader; + +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\Argument\BoundArgument; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\ExpressionLanguage\Expression; +use Symfony\Component\Yaml\Exception\ParseException; +use Symfony\Component\Yaml\Parser as YamlParser; +use Symfony\Component\Yaml\Tag\TaggedValue; +use Symfony\Component\Yaml\Yaml; + +/** + * YamlFileLoader loads YAML files service definitions. + * + * @author Fabien Potencier + */ +class YamlFileLoader extends FileLoader +{ + private static $serviceKeywords = [ + 'alias' => 'alias', + 'parent' => 'parent', + 'class' => 'class', + 'shared' => 'shared', + 'synthetic' => 'synthetic', + 'lazy' => 'lazy', + 'public' => 'public', + 'abstract' => 'abstract', + 'deprecated' => 'deprecated', + 'factory' => 'factory', + 'file' => 'file', + 'arguments' => 'arguments', + 'properties' => 'properties', + 'configurator' => 'configurator', + 'calls' => 'calls', + 'tags' => 'tags', + 'decorates' => 'decorates', + 'decoration_inner_name' => 'decoration_inner_name', + 'decoration_priority' => 'decoration_priority', + 'decoration_on_invalid' => 'decoration_on_invalid', + 'autowire' => 'autowire', + 'autoconfigure' => 'autoconfigure', + 'bind' => 'bind', + ]; + + private static $prototypeKeywords = [ + 'resource' => 'resource', + 'namespace' => 'namespace', + 'exclude' => 'exclude', + 'parent' => 'parent', + 'shared' => 'shared', + 'lazy' => 'lazy', + 'public' => 'public', + 'abstract' => 'abstract', + 'deprecated' => 'deprecated', + 'factory' => 'factory', + 'arguments' => 'arguments', + 'properties' => 'properties', + 'configurator' => 'configurator', + 'calls' => 'calls', + 'tags' => 'tags', + 'autowire' => 'autowire', + 'autoconfigure' => 'autoconfigure', + 'bind' => 'bind', + ]; + + private static $instanceofKeywords = [ + 'shared' => 'shared', + 'lazy' => 'lazy', + 'public' => 'public', + 'properties' => 'properties', + 'configurator' => 'configurator', + 'calls' => 'calls', + 'tags' => 'tags', + 'autowire' => 'autowire', + 'bind' => 'bind', + ]; + + private static $defaultsKeywords = [ + 'public' => 'public', + 'tags' => 'tags', + 'autowire' => 'autowire', + 'autoconfigure' => 'autoconfigure', + 'bind' => 'bind', + ]; + + private $yamlParser; + + private $anonymousServicesCount; + private $anonymousServicesSuffix; + + protected $autoRegisterAliasesForSinglyImplementedInterfaces = false; + + /** + * {@inheritdoc} + */ + public function load($resource, string $type = null) + { + $path = $this->locator->locate($resource); + + $content = $this->loadFile($path); + + $this->container->fileExists($path); + + // empty file + if (null === $content) { + return; + } + + // imports + $this->parseImports($content, $path); + + // parameters + if (isset($content['parameters'])) { + if (!\is_array($content['parameters'])) { + throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in %s. Check your YAML syntax.', $path)); + } + + foreach ($content['parameters'] as $key => $value) { + $this->container->setParameter($key, $this->resolveServices($value, $path, true)); + } + } + + // extensions + $this->loadFromExtensions($content); + + // services + $this->anonymousServicesCount = 0; + $this->anonymousServicesSuffix = '~'.ContainerBuilder::hash($path); + $this->setCurrentDir(\dirname($path)); + try { + $this->parseDefinitions($content, $path); + } finally { + $this->instanceof = []; + $this->registerAliasesForSinglyImplementedInterfaces(); + } + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + if (!\is_string($resource)) { + return false; + } + + if (null === $type && \in_array(pathinfo($resource, PATHINFO_EXTENSION), ['yaml', 'yml'], true)) { + return true; + } + + return \in_array($type, ['yaml', 'yml'], true); + } + + private function parseImports(array $content, string $file) + { + if (!isset($content['imports'])) { + return; + } + + if (!\is_array($content['imports'])) { + throw new InvalidArgumentException(sprintf('The "imports" key should contain an array in %s. Check your YAML syntax.', $file)); + } + + $defaultDirectory = \dirname($file); + foreach ($content['imports'] as $import) { + if (!\is_array($import)) { + $import = ['resource' => $import]; + } + if (!isset($import['resource'])) { + throw new InvalidArgumentException(sprintf('An import should provide a resource in %s. Check your YAML syntax.', $file)); + } + + $this->setCurrentDir($defaultDirectory); + $this->import($import['resource'], $import['type'] ?? null, $import['ignore_errors'] ?? false, $file); + } + } + + private function parseDefinitions(array $content, string $file) + { + if (!isset($content['services'])) { + return; + } + + if (!\is_array($content['services'])) { + throw new InvalidArgumentException(sprintf('The "services" key should contain an array in %s. Check your YAML syntax.', $file)); + } + + if (\array_key_exists('_instanceof', $content['services'])) { + $instanceof = $content['services']['_instanceof']; + unset($content['services']['_instanceof']); + + if (!\is_array($instanceof)) { + throw new InvalidArgumentException(sprintf('Service "_instanceof" key must be an array, "%s" given in "%s".', \gettype($instanceof), $file)); + } + $this->instanceof = []; + $this->isLoadingInstanceof = true; + foreach ($instanceof as $id => $service) { + if (!$service || !\is_array($service)) { + throw new InvalidArgumentException(sprintf('Type definition "%s" must be a non-empty array within "_instanceof" in %s. Check your YAML syntax.', $id, $file)); + } + if (\is_string($service) && 0 === strpos($service, '@')) { + throw new InvalidArgumentException(sprintf('Type definition "%s" cannot be an alias within "_instanceof" in %s. Check your YAML syntax.', $id, $file)); + } + $this->parseDefinition($id, $service, $file, []); + } + } + + $this->isLoadingInstanceof = false; + $defaults = $this->parseDefaults($content, $file); + foreach ($content['services'] as $id => $service) { + $this->parseDefinition($id, $service, $file, $defaults); + } + } + + /** + * @throws InvalidArgumentException + */ + private function parseDefaults(array &$content, string $file): array + { + if (!\array_key_exists('_defaults', $content['services'])) { + return []; + } + $defaults = $content['services']['_defaults']; + unset($content['services']['_defaults']); + + if (!\is_array($defaults)) { + throw new InvalidArgumentException(sprintf('Service "_defaults" key must be an array, "%s" given in "%s".', \gettype($defaults), $file)); + } + + foreach ($defaults as $key => $default) { + if (!isset(self::$defaultsKeywords[$key])) { + throw new InvalidArgumentException(sprintf('The configuration key "%s" cannot be used to define a default value in "%s". Allowed keys are "%s".', $key, $file, implode('", "', self::$defaultsKeywords))); + } + } + + if (isset($defaults['tags'])) { + if (!\is_array($tags = $defaults['tags'])) { + throw new InvalidArgumentException(sprintf('Parameter "tags" in "_defaults" must be an array in %s. Check your YAML syntax.', $file)); + } + + foreach ($tags as $tag) { + if (!\is_array($tag)) { + $tag = ['name' => $tag]; + } + + if (!isset($tag['name'])) { + throw new InvalidArgumentException(sprintf('A "tags" entry in "_defaults" is missing a "name" key in %s.', $file)); + } + $name = $tag['name']; + unset($tag['name']); + + if (!\is_string($name) || '' === $name) { + throw new InvalidArgumentException(sprintf('The tag name in "_defaults" must be a non-empty string in %s.', $file)); + } + + foreach ($tag as $attribute => $value) { + if (!is_scalar($value) && null !== $value) { + throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type in %s. Check your YAML syntax.', $name, $attribute, $file)); + } + } + } + } + + if (isset($defaults['bind'])) { + if (!\is_array($defaults['bind'])) { + throw new InvalidArgumentException(sprintf('Parameter "bind" in "_defaults" must be an array in %s. Check your YAML syntax.', $file)); + } + + foreach ($this->resolveServices($defaults['bind'], $file) as $argument => $value) { + $defaults['bind'][$argument] = new BoundArgument($value, true, BoundArgument::DEFAULTS_BINDING, $file); + } + } + + return $defaults; + } + + private function isUsingShortSyntax(array $service): bool + { + foreach ($service as $key => $value) { + if (\is_string($key) && ('' === $key || '$' !== $key[0])) { + return false; + } + } + + return true; + } + + /** + * Parses a definition. + * + * @param array|string $service + * + * @throws InvalidArgumentException When tags are invalid + */ + private function parseDefinition(string $id, $service, string $file, array $defaults) + { + if (preg_match('/^_[a-zA-Z0-9_]*$/', $id)) { + throw new InvalidArgumentException(sprintf('Service names that start with an underscore are reserved. Rename the "%s" service or define it in XML instead.', $id)); + } + + if (\is_string($service) && 0 === strpos($service, '@')) { + $this->container->setAlias($id, $alias = new Alias(substr($service, 1))); + if (isset($defaults['public'])) { + $alias->setPublic($defaults['public']); + } + + return; + } + + if (\is_array($service) && $this->isUsingShortSyntax($service)) { + $service = ['arguments' => $service]; + } + + if (null === $service) { + $service = []; + } + + if (!\is_array($service)) { + throw new InvalidArgumentException(sprintf('A service definition must be an array or a string starting with "@" but %s found for service "%s" in %s. Check your YAML syntax.', \gettype($service), $id, $file)); + } + + $this->checkDefinition($id, $service, $file); + + if (isset($service['alias'])) { + $this->container->setAlias($id, $alias = new Alias($service['alias'])); + if (\array_key_exists('public', $service)) { + $alias->setPublic($service['public']); + } elseif (isset($defaults['public'])) { + $alias->setPublic($defaults['public']); + } + + foreach ($service as $key => $value) { + if (!\in_array($key, ['alias', 'public', 'deprecated'])) { + throw new InvalidArgumentException(sprintf('The configuration key "%s" is unsupported for the service "%s" which is defined as an alias in "%s". Allowed configuration keys for service aliases are "alias", "public" and "deprecated".', $key, $id, $file)); + } + + if ('deprecated' === $key) { + $alias->setDeprecated(true, $value); + } + } + + return; + } + + if ($this->isLoadingInstanceof) { + $definition = new ChildDefinition(''); + } elseif (isset($service['parent'])) { + if (!empty($this->instanceof)) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot use the "parent" option in the same file where "_instanceof" configuration is defined as using both is not supported. Move your child definitions to a separate file.', $id)); + } + + foreach ($defaults as $k => $v) { + if ('tags' === $k) { + // since tags are never inherited from parents, there is no confusion + // thus we can safely add them as defaults to ChildDefinition + continue; + } + if ('bind' === $k) { + throw new InvalidArgumentException(sprintf('Attribute "bind" on service "%s" cannot be inherited from "_defaults" when a "parent" is set. Move your child definitions to a separate file.', $id)); + } + if (!isset($service[$k])) { + throw new InvalidArgumentException(sprintf('Attribute "%s" on service "%s" cannot be inherited from "_defaults" when a "parent" is set. Move your child definitions to a separate file or define this attribute explicitly.', $k, $id)); + } + } + + if ('' !== $service['parent'] && '@' === $service['parent'][0]) { + throw new InvalidArgumentException(sprintf('The value of the "parent" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s").', $id, $service['parent'], substr($service['parent'], 1))); + } + + $definition = new ChildDefinition($service['parent']); + } else { + $definition = new Definition(); + + if (isset($defaults['public'])) { + $definition->setPublic($defaults['public']); + } + if (isset($defaults['autowire'])) { + $definition->setAutowired($defaults['autowire']); + } + if (isset($defaults['autoconfigure'])) { + $definition->setAutoconfigured($defaults['autoconfigure']); + } + + $definition->setChanges([]); + } + + if (isset($service['class'])) { + $definition->setClass($service['class']); + } + + if (isset($service['shared'])) { + $definition->setShared($service['shared']); + } + + if (isset($service['synthetic'])) { + $definition->setSynthetic($service['synthetic']); + } + + if (isset($service['lazy'])) { + $definition->setLazy((bool) $service['lazy']); + if (\is_string($service['lazy'])) { + $definition->addTag('proxy', ['interface' => $service['lazy']]); + } + } + + if (isset($service['public'])) { + $definition->setPublic($service['public']); + } + + if (isset($service['abstract'])) { + $definition->setAbstract($service['abstract']); + } + + if (\array_key_exists('deprecated', $service)) { + $definition->setDeprecated(true, $service['deprecated']); + } + + if (isset($service['factory'])) { + $definition->setFactory($this->parseCallable($service['factory'], 'factory', $id, $file)); + } + + if (isset($service['file'])) { + $definition->setFile($service['file']); + } + + if (isset($service['arguments'])) { + $definition->setArguments($this->resolveServices($service['arguments'], $file)); + } + + if (isset($service['properties'])) { + $definition->setProperties($this->resolveServices($service['properties'], $file)); + } + + if (isset($service['configurator'])) { + $definition->setConfigurator($this->parseCallable($service['configurator'], 'configurator', $id, $file)); + } + + if (isset($service['calls'])) { + if (!\is_array($service['calls'])) { + throw new InvalidArgumentException(sprintf('Parameter "calls" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); + } + + foreach ($service['calls'] as $k => $call) { + if (!\is_array($call) && (!\is_string($k) || !$call instanceof TaggedValue)) { + throw new InvalidArgumentException(sprintf('Invalid method call for service "%s": expected map or array, %s given in %s.', $id, $call instanceof TaggedValue ? '!'.$call->getTag() : \gettype($call), $file)); + } + + if (\is_string($k)) { + throw new InvalidArgumentException(sprintf('Invalid method call for service "%s", did you forgot a leading dash before "%s: ..." in %s?', $id, $k, $file)); + } + + if (isset($call['method'])) { + $method = $call['method']; + $args = $call['arguments'] ?? []; + $returnsClone = $call['returns_clone'] ?? false; + } else { + if (1 === \count($call) && \is_string(key($call))) { + $method = key($call); + $args = $call[$method]; + + if ($args instanceof TaggedValue) { + if ('returns_clone' !== $args->getTag()) { + throw new InvalidArgumentException(sprintf('Unsupported tag "!%s", did you mean "!returns_clone" for service "%s" in %s?', $args->getTag(), $id, $file)); + } + + $returnsClone = true; + $args = $args->getValue(); + } else { + $returnsClone = false; + } + } elseif (empty($call[0])) { + throw new InvalidArgumentException(sprintf('Invalid call for service "%s": the method must be defined as the first index of an array or as the only key of a map in %s.', $id, $file)); + } else { + $method = $call[0]; + $args = $call[1] ?? []; + $returnsClone = $call[2] ?? false; + } + } + + if (!\is_array($args)) { + throw new InvalidArgumentException(sprintf('The second parameter for function call "%s" must be an array of its arguments for service "%s" in %s. Check your YAML syntax.', $method, $id, $file)); + } + + $args = $this->resolveServices($args, $file); + $definition->addMethodCall($method, $args, $returnsClone); + } + } + + $tags = isset($service['tags']) ? $service['tags'] : []; + if (!\is_array($tags)) { + throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); + } + + if (isset($defaults['tags'])) { + $tags = array_merge($tags, $defaults['tags']); + } + + foreach ($tags as $tag) { + if (!\is_array($tag)) { + $tag = ['name' => $tag]; + } + + if (!isset($tag['name'])) { + throw new InvalidArgumentException(sprintf('A "tags" entry is missing a "name" key for service "%s" in %s.', $id, $file)); + } + $name = $tag['name']; + unset($tag['name']); + + if (!\is_string($name) || '' === $name) { + throw new InvalidArgumentException(sprintf('The tag name for service "%s" in %s must be a non-empty string.', $id, $file)); + } + + foreach ($tag as $attribute => $value) { + if (!is_scalar($value) && null !== $value) { + throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s" in %s. Check your YAML syntax.', $id, $name, $attribute, $file)); + } + } + + $definition->addTag($name, $tag); + } + + if (null !== $decorates = $service['decorates'] ?? null) { + if ('' !== $decorates && '@' === $decorates[0]) { + throw new InvalidArgumentException(sprintf('The value of the "decorates" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s").', $id, $service['decorates'], substr($decorates, 1))); + } + + $decorationOnInvalid = \array_key_exists('decoration_on_invalid', $service) ? $service['decoration_on_invalid'] : 'exception'; + if ('exception' === $decorationOnInvalid) { + $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + } elseif ('ignore' === $decorationOnInvalid) { + $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; + } elseif (null === $decorationOnInvalid) { + $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; + } elseif ('null' === $decorationOnInvalid) { + throw new InvalidArgumentException(sprintf('Invalid value "%s" for attribute "decoration_on_invalid" on service "%s". Did you mean null (without quotes) in "%s"?', $decorationOnInvalid, $id, $file)); + } else { + throw new InvalidArgumentException(sprintf('Invalid value "%s" for attribute "decoration_on_invalid" on service "%s". Did you mean "exception", "ignore" or null in "%s"?', $decorationOnInvalid, $id, $file)); + } + + $renameId = isset($service['decoration_inner_name']) ? $service['decoration_inner_name'] : null; + $priority = isset($service['decoration_priority']) ? $service['decoration_priority'] : 0; + + $definition->setDecoratedService($decorates, $renameId, $priority, $invalidBehavior); + } + + if (isset($service['autowire'])) { + $definition->setAutowired($service['autowire']); + } + + if (isset($defaults['bind']) || isset($service['bind'])) { + // deep clone, to avoid multiple process of the same instance in the passes + $bindings = isset($defaults['bind']) ? unserialize(serialize($defaults['bind'])) : []; + + if (isset($service['bind'])) { + if (!\is_array($service['bind'])) { + throw new InvalidArgumentException(sprintf('Parameter "bind" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); + } + + $bindings = array_merge($bindings, $this->resolveServices($service['bind'], $file)); + $bindingType = $this->isLoadingInstanceof ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING; + foreach ($bindings as $argument => $value) { + if (!$value instanceof BoundArgument) { + $bindings[$argument] = new BoundArgument($value, true, $bindingType, $file); + } + } + } + + $definition->setBindings($bindings); + } + + if (isset($service['autoconfigure'])) { + if (!$definition instanceof ChildDefinition) { + $definition->setAutoconfigured($service['autoconfigure']); + } elseif ($service['autoconfigure']) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try setting "autoconfigure: false" for the service.', $id)); + } + } + + if (\array_key_exists('namespace', $service) && !\array_key_exists('resource', $service)) { + throw new InvalidArgumentException(sprintf('A "resource" attribute must be set when the "namespace" attribute is set for service "%s" in %s. Check your YAML syntax.', $id, $file)); + } + + if (\array_key_exists('resource', $service)) { + if (!\is_string($service['resource'])) { + throw new InvalidArgumentException(sprintf('A "resource" attribute must be of type string for service "%s" in %s. Check your YAML syntax.', $id, $file)); + } + $exclude = isset($service['exclude']) ? $service['exclude'] : null; + $namespace = isset($service['namespace']) ? $service['namespace'] : $id; + $this->registerClasses($definition, $namespace, $service['resource'], $exclude); + } else { + $this->setDefinition($id, $definition); + } + } + + /** + * Parses a callable. + * + * @param string|array $callable A callable reference + * + * @throws InvalidArgumentException When errors occur + * + * @return string|array|Reference A parsed callable + */ + private function parseCallable($callable, string $parameter, string $id, string $file) + { + if (\is_string($callable)) { + if ('' !== $callable && '@' === $callable[0]) { + if (false === strpos($callable, ':')) { + return [$this->resolveServices($callable, $file), '__invoke']; + } + + throw new InvalidArgumentException(sprintf('The value of the "%s" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s" in "%s").', $parameter, $id, $callable, substr($callable, 1), $file)); + } + + return $callable; + } + + if (\is_array($callable)) { + if (isset($callable[0]) && isset($callable[1])) { + return [$this->resolveServices($callable[0], $file), $callable[1]]; + } + + if ('factory' === $parameter && isset($callable[1]) && null === $callable[0]) { + return $callable; + } + + throw new InvalidArgumentException(sprintf('Parameter "%s" must contain an array with two elements for service "%s" in %s. Check your YAML syntax.', $parameter, $id, $file)); + } + + throw new InvalidArgumentException(sprintf('Parameter "%s" must be a string or an array for service "%s" in %s. Check your YAML syntax.', $parameter, $id, $file)); + } + + /** + * Loads a YAML file. + * + * @param string $file + * + * @return array The file content + * + * @throws InvalidArgumentException when the given file is not a local file or when it does not exist + */ + protected function loadFile($file) + { + if (!class_exists('Symfony\Component\Yaml\Parser')) { + throw new RuntimeException('Unable to load YAML config files as the Symfony Yaml Component is not installed.'); + } + + if (!stream_is_local($file)) { + throw new InvalidArgumentException(sprintf('This is not a local file "%s".', $file)); + } + + if (!file_exists($file)) { + throw new InvalidArgumentException(sprintf('The file "%s" does not exist.', $file)); + } + + if (null === $this->yamlParser) { + $this->yamlParser = new YamlParser(); + } + + try { + $configuration = $this->yamlParser->parseFile($file, Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS); + } catch (ParseException $e) { + throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML: %s', $file, $e->getMessage()), 0, $e); + } + + return $this->validate($configuration, $file); + } + + /** + * Validates a YAML file. + * + * @throws InvalidArgumentException When service file is not valid + */ + private function validate($content, string $file): ?array + { + if (null === $content) { + return $content; + } + + if (!\is_array($content)) { + throw new InvalidArgumentException(sprintf('The service file "%s" is not valid. It should contain an array. Check your YAML syntax.', $file)); + } + + foreach ($content as $namespace => $data) { + if (\in_array($namespace, ['imports', 'parameters', 'services'])) { + continue; + } + + if (!$this->container->hasExtension($namespace)) { + $extensionNamespaces = array_filter(array_map(function (ExtensionInterface $ext) { return $ext->getAlias(); }, $this->container->getExtensions())); + throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $namespace, $file, $namespace, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none')); + } + } + + return $content; + } + + /** + * Resolves services. + * + * @return array|string|Reference|ArgumentInterface + */ + private function resolveServices($value, string $file, bool $isParameter = false) + { + if ($value instanceof TaggedValue) { + $argument = $value->getValue(); + if ('iterator' === $value->getTag()) { + if (!\is_array($argument)) { + throw new InvalidArgumentException(sprintf('"!iterator" tag only accepts sequences in "%s".', $file)); + } + $argument = $this->resolveServices($argument, $file, $isParameter); + try { + return new IteratorArgument($argument); + } catch (InvalidArgumentException $e) { + throw new InvalidArgumentException(sprintf('"!iterator" tag only accepts arrays of "@service" references in "%s".', $file)); + } + } + if ('service_locator' === $value->getTag()) { + if (!\is_array($argument)) { + throw new InvalidArgumentException(sprintf('"!service_locator" tag only accepts maps in "%s".', $file)); + } + + $argument = $this->resolveServices($argument, $file, $isParameter); + + try { + return new ServiceLocatorArgument($argument); + } catch (InvalidArgumentException $e) { + throw new InvalidArgumentException(sprintf('"!service_locator" tag only accepts maps of "@service" references in "%s".', $file)); + } + } + if (\in_array($value->getTag(), ['tagged', 'tagged_iterator', 'tagged_locator'], true)) { + $forLocator = 'tagged_locator' === $value->getTag(); + + if (\is_array($argument) && isset($argument['tag']) && $argument['tag']) { + if ($diff = array_diff(array_keys($argument), ['tag', 'index_by', 'default_index_method', 'default_priority_method'])) { + throw new InvalidArgumentException(sprintf('"!%s" tag contains unsupported key "%s"; supported ones are "tag", "index_by", "default_index_method", and "default_priority_method".', $value->getTag(), implode('"", "', $diff))); + } + + $argument = new TaggedIteratorArgument($argument['tag'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null, $forLocator, $argument['default_priority_method'] ?? null); + } elseif (\is_string($argument) && $argument) { + $argument = new TaggedIteratorArgument($argument, null, null, $forLocator); + } else { + throw new InvalidArgumentException(sprintf('"!%s" tags only accept a non empty string or an array with a key "tag" in "%s".', $value->getTag(), $file)); + } + + if ($forLocator) { + $argument = new ServiceLocatorArgument($argument); + } + + return $argument; + } + if ('service' === $value->getTag()) { + if ($isParameter) { + throw new InvalidArgumentException(sprintf('Using an anonymous service in a parameter is not allowed in "%s".', $file)); + } + + $isLoadingInstanceof = $this->isLoadingInstanceof; + $this->isLoadingInstanceof = false; + $instanceof = $this->instanceof; + $this->instanceof = []; + + $id = sprintf('.%d_%s', ++$this->anonymousServicesCount, preg_replace('/^.*\\\\/', '', isset($argument['class']) ? $argument['class'] : '').$this->anonymousServicesSuffix); + $this->parseDefinition($id, $argument, $file, []); + + if (!$this->container->hasDefinition($id)) { + throw new InvalidArgumentException(sprintf('Creating an alias using the tag "!service" is not allowed in "%s".', $file)); + } + + $this->container->getDefinition($id)->setPublic(false); + + $this->isLoadingInstanceof = $isLoadingInstanceof; + $this->instanceof = $instanceof; + + return new Reference($id); + } + + throw new InvalidArgumentException(sprintf('Unsupported tag "!%s".', $value->getTag())); + } + + if (\is_array($value)) { + foreach ($value as $k => $v) { + $value[$k] = $this->resolveServices($v, $file, $isParameter); + } + } elseif (\is_string($value) && 0 === strpos($value, '@=')) { + if (!class_exists(Expression::class)) { + throw new \LogicException(sprintf('The "@=" expression syntax cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".')); + } + + return new Expression(substr($value, 2)); + } elseif (\is_string($value) && 0 === strpos($value, '@')) { + if (0 === strpos($value, '@@')) { + $value = substr($value, 1); + $invalidBehavior = null; + } elseif (0 === strpos($value, '@!')) { + $value = substr($value, 2); + $invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; + } elseif (0 === strpos($value, '@?')) { + $value = substr($value, 2); + $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; + } else { + $value = substr($value, 1); + $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + } + + if (null !== $invalidBehavior) { + $value = new Reference($value, $invalidBehavior); + } + } + + return $value; + } + + /** + * Loads from Extensions. + */ + private function loadFromExtensions(array $content) + { + foreach ($content as $namespace => $values) { + if (\in_array($namespace, ['imports', 'parameters', 'services'])) { + continue; + } + + if (!\is_array($values) && null !== $values) { + $values = []; + } + + $this->container->loadFromExtension($namespace, $values); + } + } + + /** + * Checks the keywords used to define a service. + */ + private function checkDefinition(string $id, array $definition, string $file) + { + if ($this->isLoadingInstanceof) { + $keywords = self::$instanceofKeywords; + } elseif (isset($definition['resource']) || isset($definition['namespace'])) { + $keywords = self::$prototypeKeywords; + } else { + $keywords = self::$serviceKeywords; + } + + foreach ($definition as $key => $value) { + if (!isset($keywords[$key])) { + throw new InvalidArgumentException(sprintf('The configuration key "%s" is unsupported for definition "%s" in "%s". Allowed configuration keys are "%s".', $key, $id, $file, implode('", "', $keywords))); + } + } + } +} diff --git a/vendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd b/vendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd new file mode 100644 index 0000000..2f745c3 --- /dev/null +++ b/vendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/dependency-injection/Parameter.php b/vendor/symfony/dependency-injection/Parameter.php new file mode 100644 index 0000000..d484ac0 --- /dev/null +++ b/vendor/symfony/dependency-injection/Parameter.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +/** + * Parameter represents a parameter reference. + * + * @author Fabien Potencier + */ +class Parameter +{ + private $id; + + public function __construct(string $id) + { + $this->id = $id; + } + + /** + * @return string The parameter key + */ + public function __toString() + { + return $this->id; + } +} diff --git a/vendor/symfony/dependency-injection/ParameterBag/ContainerBag.php b/vendor/symfony/dependency-injection/ParameterBag/ContainerBag.php new file mode 100644 index 0000000..7671dfc --- /dev/null +++ b/vendor/symfony/dependency-injection/ParameterBag/ContainerBag.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\ParameterBag; + +use Symfony\Component\DependencyInjection\Container; + +/** + * @author Nicolas Grekas + */ +class ContainerBag extends FrozenParameterBag implements ContainerBagInterface +{ + private $container; + + public function __construct(Container $container) + { + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public function all() + { + return $this->container->getParameterBag()->all(); + } + + /** + * {@inheritdoc} + */ + public function get($name) + { + return $this->container->getParameter($name); + } + + /** + * {@inheritdoc} + */ + public function has($name) + { + return $this->container->hasParameter($name); + } +} diff --git a/vendor/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php b/vendor/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php new file mode 100644 index 0000000..1c1227a --- /dev/null +++ b/vendor/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\ParameterBag; + +use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; + +/** + * ContainerBagInterface is the interface implemented by objects that manage service container parameters. + * + * @author Nicolas Grekas + */ +interface ContainerBagInterface extends ContainerInterface +{ + /** + * Gets the service container parameters. + * + * @return array An array of parameters + */ + public function all(); + + /** + * Replaces parameter placeholders (%name%) by their values. + * + * @param mixed $value A value + * + * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist + */ + public function resolveValue($value); + + /** + * Escape parameter placeholders %. + * + * @param mixed $value + * + * @return mixed + */ + public function escapeValue($value); + + /** + * Unescape parameter placeholders %. + * + * @param mixed $value + * + * @return mixed + */ + public function unescapeValue($value); +} diff --git a/vendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php b/vendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php new file mode 100644 index 0000000..ec95d4c --- /dev/null +++ b/vendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php @@ -0,0 +1,154 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\ParameterBag; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + +/** + * @author Nicolas Grekas + */ +class EnvPlaceholderParameterBag extends ParameterBag +{ + private $envPlaceholderUniquePrefix; + private $envPlaceholders = []; + private $unusedEnvPlaceholders = []; + private $providedTypes = []; + + private static $counter = 0; + + /** + * {@inheritdoc} + */ + public function get(string $name) + { + if (0 === strpos($name, 'env(') && ')' === substr($name, -1) && 'env()' !== $name) { + $env = substr($name, 4, -1); + + if (isset($this->envPlaceholders[$env])) { + foreach ($this->envPlaceholders[$env] as $placeholder) { + return $placeholder; // return first result + } + } + if (isset($this->unusedEnvPlaceholders[$env])) { + foreach ($this->unusedEnvPlaceholders[$env] as $placeholder) { + return $placeholder; // return first result + } + } + if (!preg_match('/^(?:\w*+:)*+\w++$/', $env)) { + throw new InvalidArgumentException(sprintf('Invalid %s name: only "word" characters are allowed.', $name)); + } + if ($this->has($name) && null !== ($defaultValue = parent::get($name)) && !\is_string($defaultValue)) { + throw new RuntimeException(sprintf('The default value of an env() parameter must be a string or null, but "%s" given to "%s".', \gettype($defaultValue), $name)); + } + + $uniqueName = md5($name.'_'.self::$counter++); + $placeholder = sprintf('%s_%s_%s', $this->getEnvPlaceholderUniquePrefix(), str_replace(':', '_', $env), $uniqueName); + $this->envPlaceholders[$env][$placeholder] = $placeholder; + + return $placeholder; + } + + return parent::get($name); + } + + /** + * Gets the common env placeholder prefix for env vars created by this bag. + */ + public function getEnvPlaceholderUniquePrefix(): string + { + if (null === $this->envPlaceholderUniquePrefix) { + $reproducibleEntropy = unserialize(serialize($this->parameters)); + array_walk_recursive($reproducibleEntropy, function (&$v) { $v = null; }); + $this->envPlaceholderUniquePrefix = 'env_'.substr(md5(serialize($reproducibleEntropy)), -16); + } + + return $this->envPlaceholderUniquePrefix; + } + + /** + * Returns the map of env vars used in the resolved parameter values to their placeholders. + * + * @return string[][] A map of env var names to their placeholders + */ + public function getEnvPlaceholders() + { + return $this->envPlaceholders; + } + + public function getUnusedEnvPlaceholders(): array + { + return $this->unusedEnvPlaceholders; + } + + public function clearUnusedEnvPlaceholders() + { + $this->unusedEnvPlaceholders = []; + } + + /** + * Merges the env placeholders of another EnvPlaceholderParameterBag. + */ + public function mergeEnvPlaceholders(self $bag) + { + if ($newPlaceholders = $bag->getEnvPlaceholders()) { + $this->envPlaceholders += $newPlaceholders; + + foreach ($newPlaceholders as $env => $placeholders) { + $this->envPlaceholders[$env] += $placeholders; + } + } + + if ($newUnusedPlaceholders = $bag->getUnusedEnvPlaceholders()) { + $this->unusedEnvPlaceholders += $newUnusedPlaceholders; + + foreach ($newUnusedPlaceholders as $env => $placeholders) { + $this->unusedEnvPlaceholders[$env] += $placeholders; + } + } + } + + /** + * Maps env prefixes to their corresponding PHP types. + */ + public function setProvidedTypes(array $providedTypes) + { + $this->providedTypes = $providedTypes; + } + + /** + * Gets the PHP types corresponding to env() parameter prefixes. + * + * @return string[][] + */ + public function getProvidedTypes() + { + return $this->providedTypes; + } + + /** + * {@inheritdoc} + */ + public function resolve() + { + if ($this->resolved) { + return; + } + parent::resolve(); + + foreach ($this->envPlaceholders as $env => $placeholders) { + if ($this->has($name = "env($env)") && null !== ($default = $this->parameters[$name]) && !\is_string($default)) { + throw new RuntimeException(sprintf('The default value of env parameter "%s" must be a string or null, %s given.', $env, \gettype($default))); + } + } + } +} diff --git a/vendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php b/vendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php new file mode 100644 index 0000000..5a4aaf8 --- /dev/null +++ b/vendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\ParameterBag; + +use Symfony\Component\DependencyInjection\Exception\LogicException; + +/** + * Holds read-only parameters. + * + * @author Fabien Potencier + */ +class FrozenParameterBag extends ParameterBag +{ + /** + * For performance reasons, the constructor assumes that + * all keys are already lowercased. + * + * This is always the case when used internally. + * + * @param array $parameters An array of parameters + */ + public function __construct(array $parameters = []) + { + $this->parameters = $parameters; + $this->resolved = true; + } + + /** + * {@inheritdoc} + */ + public function clear() + { + throw new LogicException('Impossible to call clear() on a frozen ParameterBag.'); + } + + /** + * {@inheritdoc} + */ + public function add(array $parameters) + { + throw new LogicException('Impossible to call add() on a frozen ParameterBag.'); + } + + /** + * {@inheritdoc} + */ + public function set(string $name, $value) + { + throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); + } + + /** + * {@inheritdoc} + */ + public function remove(string $name) + { + throw new LogicException('Impossible to call remove() on a frozen ParameterBag.'); + } +} diff --git a/vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php b/vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php new file mode 100644 index 0000000..643424a --- /dev/null +++ b/vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php @@ -0,0 +1,286 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\ParameterBag; + +use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; +use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + +/** + * Holds parameters. + * + * @author Fabien Potencier + */ +class ParameterBag implements ParameterBagInterface +{ + protected $parameters = []; + protected $resolved = false; + + /** + * @param array $parameters An array of parameters + */ + public function __construct(array $parameters = []) + { + $this->add($parameters); + } + + /** + * Clears all parameters. + */ + public function clear() + { + $this->parameters = []; + } + + /** + * Adds parameters to the service container parameters. + * + * @param array $parameters An array of parameters + */ + public function add(array $parameters) + { + foreach ($parameters as $key => $value) { + $this->set($key, $value); + } + } + + /** + * {@inheritdoc} + */ + public function all() + { + return $this->parameters; + } + + /** + * {@inheritdoc} + */ + public function get(string $name) + { + if (!\array_key_exists($name, $this->parameters)) { + if (!$name) { + throw new ParameterNotFoundException($name); + } + + $alternatives = []; + foreach ($this->parameters as $key => $parameterValue) { + $lev = levenshtein($name, $key); + if ($lev <= \strlen($name) / 3 || false !== strpos($key, $name)) { + $alternatives[] = $key; + } + } + + $nonNestedAlternative = null; + if (!\count($alternatives) && false !== strpos($name, '.')) { + $namePartsLength = array_map('strlen', explode('.', $name)); + $key = substr($name, 0, -1 * (1 + array_pop($namePartsLength))); + while (\count($namePartsLength)) { + if ($this->has($key)) { + if (\is_array($this->get($key))) { + $nonNestedAlternative = $key; + } + break; + } + + $key = substr($key, 0, -1 * (1 + array_pop($namePartsLength))); + } + } + + throw new ParameterNotFoundException($name, null, null, null, $alternatives, $nonNestedAlternative); + } + + return $this->parameters[$name]; + } + + /** + * Sets a service container parameter. + * + * @param string $name The parameter name + * @param mixed $value The parameter value + */ + public function set(string $name, $value) + { + $this->parameters[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function has(string $name) + { + return \array_key_exists((string) $name, $this->parameters); + } + + /** + * Removes a parameter. + * + * @param string $name The parameter name + */ + public function remove(string $name) + { + unset($this->parameters[$name]); + } + + /** + * {@inheritdoc} + */ + public function resolve() + { + if ($this->resolved) { + return; + } + + $parameters = []; + foreach ($this->parameters as $key => $value) { + try { + $value = $this->resolveValue($value); + $parameters[$key] = $this->unescapeValue($value); + } catch (ParameterNotFoundException $e) { + $e->setSourceKey($key); + + throw $e; + } + } + + $this->parameters = $parameters; + $this->resolved = true; + } + + /** + * Replaces parameter placeholders (%name%) by their values. + * + * @param mixed $value A value + * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) + * + * @return mixed The resolved value + * + * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist + * @throws ParameterCircularReferenceException if a circular reference if detected + * @throws RuntimeException when a given parameter has a type problem + */ + public function resolveValue($value, array $resolving = []) + { + if (\is_array($value)) { + $args = []; + foreach ($value as $k => $v) { + $args[\is_string($k) ? $this->resolveValue($k, $resolving) : $k] = $this->resolveValue($v, $resolving); + } + + return $args; + } + + if (!\is_string($value) || 2 > \strlen($value)) { + return $value; + } + + return $this->resolveString($value, $resolving); + } + + /** + * Resolves parameters inside a string. + * + * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) + * + * @return mixed The resolved string + * + * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist + * @throws ParameterCircularReferenceException if a circular reference if detected + * @throws RuntimeException when a given parameter has a type problem + */ + public function resolveString(string $value, array $resolving = []) + { + // we do this to deal with non string values (Boolean, integer, ...) + // as the preg_replace_callback throw an exception when trying + // a non-string in a parameter value + if (preg_match('/^%([^%\s]+)%$/', $value, $match)) { + $key = $match[1]; + + if (isset($resolving[$key])) { + throw new ParameterCircularReferenceException(array_keys($resolving)); + } + + $resolving[$key] = true; + + return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving); + } + + return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($resolving, $value) { + // skip %% + if (!isset($match[1])) { + return '%%'; + } + + $key = $match[1]; + if (isset($resolving[$key])) { + throw new ParameterCircularReferenceException(array_keys($resolving)); + } + + $resolved = $this->get($key); + + if (!\is_string($resolved) && !is_numeric($resolved)) { + throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type %s inside string value "%s".', $key, \gettype($resolved), $value)); + } + + $resolved = (string) $resolved; + $resolving[$key] = true; + + return $this->isResolved() ? $resolved : $this->resolveString($resolved, $resolving); + }, $value); + } + + public function isResolved() + { + return $this->resolved; + } + + /** + * {@inheritdoc} + */ + public function escapeValue($value) + { + if (\is_string($value)) { + return str_replace('%', '%%', $value); + } + + if (\is_array($value)) { + $result = []; + foreach ($value as $k => $v) { + $result[$k] = $this->escapeValue($v); + } + + return $result; + } + + return $value; + } + + /** + * {@inheritdoc} + */ + public function unescapeValue($value) + { + if (\is_string($value)) { + return str_replace('%%', '%', $value); + } + + if (\is_array($value)) { + $result = []; + foreach ($value as $k => $v) { + $result[$k] = $this->unescapeValue($v); + } + + return $result; + } + + return $value; + } +} diff --git a/vendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php b/vendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php new file mode 100644 index 0000000..f224216 --- /dev/null +++ b/vendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\ParameterBag; + +use Symfony\Component\DependencyInjection\Exception\LogicException; +use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; + +/** + * ParameterBagInterface is the interface implemented by objects that manage service container parameters. + * + * @author Fabien Potencier + */ +interface ParameterBagInterface +{ + /** + * Clears all parameters. + * + * @throws LogicException if the ParameterBagInterface can not be cleared + */ + public function clear(); + + /** + * Adds parameters to the service container parameters. + * + * @param array $parameters An array of parameters + * + * @throws LogicException if the parameter can not be added + */ + public function add(array $parameters); + + /** + * Gets the service container parameters. + * + * @return array An array of parameters + */ + public function all(); + + /** + * Gets a service container parameter. + * + * @return mixed The parameter value + * + * @throws ParameterNotFoundException if the parameter is not defined + */ + public function get(string $name); + + /** + * Removes a parameter. + */ + public function remove(string $name); + + /** + * Sets a service container parameter. + * + * @param mixed $value The parameter value + * + * @throws LogicException if the parameter can not be set + */ + public function set(string $name, $value); + + /** + * Returns true if a parameter name is defined. + * + * @return bool true if the parameter name is defined, false otherwise + */ + public function has(string $name); + + /** + * Replaces parameter placeholders (%name%) by their values for all parameters. + */ + public function resolve(); + + /** + * Replaces parameter placeholders (%name%) by their values. + * + * @param mixed $value A value + * + * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist + */ + public function resolveValue($value); + + /** + * Escape parameter placeholders %. + * + * @param mixed $value + * + * @return mixed + */ + public function escapeValue($value); + + /** + * Unescape parameter placeholders %. + * + * @param mixed $value + * + * @return mixed + */ + public function unescapeValue($value); +} diff --git a/vendor/symfony/dependency-injection/README.md b/vendor/symfony/dependency-injection/README.md new file mode 100644 index 0000000..932647f --- /dev/null +++ b/vendor/symfony/dependency-injection/README.md @@ -0,0 +1,14 @@ +DependencyInjection Component +============================= + +The DependencyInjection component allows you to standardize and centralize the +way objects are constructed in your application. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/dependency_injection/index.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/dependency-injection/Reference.php b/vendor/symfony/dependency-injection/Reference.php new file mode 100644 index 0000000..c13cf6f --- /dev/null +++ b/vendor/symfony/dependency-injection/Reference.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +/** + * Reference represents a service reference. + * + * @author Fabien Potencier + */ +class Reference +{ + private $id; + private $invalidBehavior; + + public function __construct(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) + { + $this->id = $id; + $this->invalidBehavior = $invalidBehavior; + } + + /** + * @return string The service identifier + */ + public function __toString() + { + return $this->id; + } + + /** + * Returns the behavior to be used when the service does not exist. + * + * @return int + */ + public function getInvalidBehavior() + { + return $this->invalidBehavior; + } +} diff --git a/vendor/symfony/dependency-injection/ReverseContainer.php b/vendor/symfony/dependency-injection/ReverseContainer.php new file mode 100644 index 0000000..280e9e2 --- /dev/null +++ b/vendor/symfony/dependency-injection/ReverseContainer.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; + +/** + * Turns public and "container.reversible" services back to their ids. + * + * @author Nicolas Grekas + */ +final class ReverseContainer +{ + private $serviceContainer; + private $reversibleLocator; + private $tagName; + private $getServiceId; + + public function __construct(Container $serviceContainer, ContainerInterface $reversibleLocator, string $tagName = 'container.reversible') + { + $this->serviceContainer = $serviceContainer; + $this->reversibleLocator = $reversibleLocator; + $this->tagName = $tagName; + $this->getServiceId = \Closure::bind(function (object $service): ?string { + return array_search($service, $this->services, true) ?: array_search($service, $this->privates, true) ?: null; + }, $serviceContainer, Container::class); + } + + /** + * Returns the id of the passed object when it exists as a service. + * + * To be reversible, services need to be either public or be tagged with "container.reversible". + */ + public function getId(object $service): ?string + { + if ($this->serviceContainer === $service) { + return 'service_container'; + } + + if (null === $id = ($this->getServiceId)($service)) { + return null; + } + + if ($this->serviceContainer->has($id) || $this->reversibleLocator->has($id)) { + return $id; + } + + return null; + } + + /** + * @throws ServiceNotFoundException When the service is not reversible + */ + public function getService(string $id): object + { + if ($this->serviceContainer->has($id)) { + return $this->serviceContainer->get($id); + } + + if ($this->reversibleLocator->has($id)) { + return $this->reversibleLocator->get($id); + } + + if (isset($this->serviceContainer->getRemovedIds()[$id])) { + throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service is private and cannot be accessed by reference. You should either make it public, or tag it as "%s".', $id, $this->tagName)); + } + + // will throw a ServiceNotFoundException + $this->serviceContainer->get($id); + } +} diff --git a/vendor/symfony/dependency-injection/ServiceLocator.php b/vendor/symfony/dependency-injection/ServiceLocator.php new file mode 100644 index 0000000..dd97e39 --- /dev/null +++ b/vendor/symfony/dependency-injection/ServiceLocator.php @@ -0,0 +1,145 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Contracts\Service\ServiceLocatorTrait; +use Symfony\Contracts\Service\ServiceProviderInterface; +use Symfony\Contracts\Service\ServiceSubscriberInterface; + +/** + * @author Robin Chalas + * @author Nicolas Grekas + */ +class ServiceLocator implements ServiceProviderInterface +{ + use ServiceLocatorTrait { + get as private doGet; + } + + private $externalId; + private $container; + + public function get($id) + { + if (!$this->externalId) { + return $this->doGet($id); + } + + try { + return $this->doGet($id); + } catch (RuntimeException $e) { + $what = sprintf('service "%s" required by "%s"', $id, $this->externalId); + $message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage()); + + if ($e->getMessage() === $message) { + $message = sprintf('Cannot resolve %s: %s', $what, $message); + } + + $r = new \ReflectionProperty($e, 'message'); + $r->setAccessible(true); + $r->setValue($e, $message); + + throw $e; + } + } + + public function __invoke(string $id) + { + return isset($this->factories[$id]) ? $this->get($id) : null; + } + + /** + * @internal + * + * @return static + */ + public function withContext(string $externalId, Container $container): self + { + $locator = clone $this; + $locator->externalId = $externalId; + $locator->container = $container; + + return $locator; + } + + private function createNotFoundException(string $id): NotFoundExceptionInterface + { + if ($this->loading) { + $msg = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $this->formatAlternatives()); + + return new ServiceNotFoundException($id, end($this->loading) ?: null, null, [], $msg); + } + + $class = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, 4); + $class = isset($class[3]['object']) ? \get_class($class[3]['object']) : null; + $externalId = $this->externalId ?: $class; + + $msg = []; + $msg[] = sprintf('Service "%s" not found:', $id); + + if (!$this->container) { + $class = null; + } elseif ($this->container->has($id) || isset($this->container->getRemovedIds()[$id])) { + $msg[] = 'even though it exists in the app\'s container,'; + } else { + try { + $this->container->get($id); + $class = null; + } catch (ServiceNotFoundException $e) { + if ($e->getAlternatives()) { + $msg[] = sprintf('did you mean %s? Anyway,', $this->formatAlternatives($e->getAlternatives(), 'or')); + } else { + $class = null; + } + } + } + if ($externalId) { + $msg[] = sprintf('the container inside "%s" is a smaller service locator that %s', $externalId, $this->formatAlternatives()); + } else { + $msg[] = sprintf('the current service locator %s', $this->formatAlternatives()); + } + + if (!$class) { + // no-op + } elseif (is_subclass_of($class, ServiceSubscriberInterface::class)) { + $msg[] = sprintf('Unless you need extra laziness, try using dependency injection instead. Otherwise, you need to declare it using "%s::getSubscribedServices()".', preg_replace('/([^\\\\]++\\\\)++/', '', $class)); + } else { + $msg[] = 'Try using dependency injection instead.'; + } + + return new ServiceNotFoundException($id, end($this->loading) ?: null, null, [], implode(' ', $msg)); + } + + private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface + { + return new ServiceCircularReferenceException($id, $path); + } + + private function formatAlternatives(array $alternatives = null, string $separator = 'and'): string + { + $format = '"%s"%s'; + if (null === $alternatives) { + if (!$alternatives = array_keys($this->factories)) { + return 'is empty...'; + } + $format = sprintf('only knows about the %s service%s.', $format, 1 < \count($alternatives) ? 's' : ''); + } + $last = array_pop($alternatives); + + return sprintf($format, $alternatives ? implode('", "', $alternatives) : $last, $alternatives ? sprintf(' %s "%s"', $separator, $last) : ''); + } +} diff --git a/vendor/symfony/dependency-injection/TaggedContainerInterface.php b/vendor/symfony/dependency-injection/TaggedContainerInterface.php new file mode 100644 index 0000000..2e32cd5 --- /dev/null +++ b/vendor/symfony/dependency-injection/TaggedContainerInterface.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +/** + * TaggedContainerInterface is the interface implemented when a container knows how to deals with tags. + * + * @author Fabien Potencier + */ +interface TaggedContainerInterface extends ContainerInterface +{ + /** + * Returns service ids for a given tag. + * + * @param string $name The tag name + * + * @return array An array of tags + */ + public function findTaggedServiceIds(string $name); +} diff --git a/vendor/symfony/dependency-injection/TypedReference.php b/vendor/symfony/dependency-injection/TypedReference.php new file mode 100644 index 0000000..3765bc7 --- /dev/null +++ b/vendor/symfony/dependency-injection/TypedReference.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +/** + * Represents a PHP type-hinted service reference. + * + * @author Nicolas Grekas + */ +class TypedReference extends Reference +{ + private $type; + private $name; + private $requiringClass; + + /** + * @param string $id The service identifier + * @param string $type The PHP type of the identified service + * @param int $invalidBehavior The behavior when the service does not exist + * @param string $name The name of the argument targeting the service + */ + public function __construct(string $id, string $type, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, string $name = null) + { + $this->name = $type === $id ? $name : null; + parent::__construct($id, $invalidBehavior); + $this->type = $type; + } + + public function getType() + { + return $this->type; + } + + public function getName(): ?string + { + return $this->name; + } +} diff --git a/vendor/symfony/dependency-injection/Variable.php b/vendor/symfony/dependency-injection/Variable.php new file mode 100644 index 0000000..21d33eb --- /dev/null +++ b/vendor/symfony/dependency-injection/Variable.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +/** + * Represents a variable. + * + * $var = new Variable('a'); + * + * will be dumped as + * + * $a + * + * by the PHP dumper. + * + * @author Johannes M. Schmitt + */ +class Variable +{ + private $name; + + public function __construct(string $name) + { + $this->name = $name; + } + + /** + * @return string + */ + public function __toString() + { + return $this->name; + } +} diff --git a/vendor/symfony/dependency-injection/composer.json b/vendor/symfony/dependency-injection/composer.json new file mode 100644 index 0000000..25e65e3 --- /dev/null +++ b/vendor/symfony/dependency-injection/composer.json @@ -0,0 +1,57 @@ +{ + "name": "symfony/dependency-injection", + "type": "library", + "description": "Symfony DependencyInjection Component", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "psr/container": "^1.0", + "symfony/service-contracts": "^1.1.6|^2" + }, + "require-dev": { + "symfony/yaml": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/expression-language": "^4.4|^5.0" + }, + "suggest": { + "symfony/yaml": "", + "symfony/config": "", + "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", + "symfony/expression-language": "For using expressions in service container configuration", + "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them" + }, + "conflict": { + "symfony/config": "<5.0", + "symfony/finder": "<4.4", + "symfony/proxy-manager-bridge": "<4.4", + "symfony/yaml": "<4.4" + }, + "provide": { + "psr/container-implementation": "1.0", + "symfony/service-implementation": "1.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\DependencyInjection\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/doctrine-bridge/.gitattributes b/vendor/symfony/doctrine-bridge/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/doctrine-bridge/CHANGELOG.md b/vendor/symfony/doctrine-bridge/CHANGELOG.md new file mode 100644 index 0000000..78ebd8b --- /dev/null +++ b/vendor/symfony/doctrine-bridge/CHANGELOG.md @@ -0,0 +1,114 @@ +CHANGELOG +========= + +5.0.0 +----- + + * the `getMetadataDriverClass()` method is abstract and must be implemented by class extending `AbstractDoctrineExtension` + * passing an `IdReader` to the `DoctrineChoiceLoader` when the query cannot be optimized with single id field, throws an exception; pass `null` instead + * not explicitly passing an instance of `IdReader` to `DoctrineChoiceLoader` when it can optimize single id field, will not apply any optimization + * `DoctrineExtractor` now requires an `EntityManagerInterface` on instantiation + +4.4.0 +----- + + * [BC BREAK] using null as `$classValidatorRegexp` value in `DoctrineLoader::__construct` will not enable auto-mapping for all classes anymore, use `'{.*}'` instead. + * added `DoctrineClearEntityManagerWorkerSubscriber` + * deprecated `RegistryInterface`, use `Doctrine\Persistence\ManagerRegistry` + * added support for invokable event listeners + * added `getMetadataDriverClass` method to deprecate class parameters in service configuration files + +4.3.0 +----- + + * changed guessing of DECIMAL to set the `input` option of `NumberType` to string + * deprecated not passing an `IdReader` to the `DoctrineChoiceLoader` when query can be optimized with a single id field + * deprecated passing an `IdReader` to the `DoctrineChoiceLoader` when entities have a composite id + * added two Messenger middleware: `DoctrinePingConnectionMiddleware` and `DoctrineCloseConnectionMiddleware` + +4.2.0 +----- + + * deprecated injecting `ClassMetadataFactory` in `DoctrineExtractor`, + an instance of `EntityManagerInterface` should be injected instead + * added support for `simple_array` type + * the `DoctrineTransactionMiddlewareFactory` class has been removed + +4.1.0 +----- + + * added support for datetime immutable types in form type guesser + +4.0.0 +----- + + * the first constructor argument of the `DoctrineChoiceLoader` class must be + an `ObjectManager` implementation + * removed the `MergeDoctrineCollectionListener::onBind()` method + * trying to reset a non-lazy manager service using the `ManagerRegistry::resetService()` + method throws an exception + * removed the `DoctrineParserCache` class + +3.4.0 +----- + + * added support for doctrine/dbal v2.6 types + * added cause of UniqueEntity constraint violation + * deprecated `DbalSessionHandler` and `DbalSessionHandlerSchema` in favor of + `Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler` + +3.1.0 +----- + + * added "{{ value }}" message placeholder to UniqueEntityValidator + * deprecated `MergeDoctrineCollectionListener::onBind` in favor of + `MergeDoctrineCollectionListener::onSubmit` + * deprecated passing `ChoiceListFactoryInterface` as first argument of + `DoctrineChoiceLoader`'s constructor + +3.0.0 +----- + + * removed `EntityChoiceList` + * removed `$manager` (2nd) and `$class` (3th) arguments of `ORMQueryBuilderLoader` + * removed passing a query builder closure to `ORMQueryBuilderLoader` + * removed `loader` and `property` options of the `DoctrineType` + +2.8.0 +----- + + * deprecated using the entity provider with a Doctrine repository implementing UserProviderInterface + * added UserLoaderInterface for loading users through Doctrine. + +2.7.0 +----- + + * added DoctrineChoiceLoader + * deprecated EntityChoiceList + * deprecated passing a query builder closure to ORMQueryBuilderLoader + * deprecated $manager and $em arguments of ORMQueryBuilderLoader + * added optional arguments $propertyAccessor and $choiceListFactory to DoctrineOrmExtension constructor + * deprecated "loader" and "property" options of DoctrineType + +2.4.0 +----- + + * deprecated DoctrineOrmTestCase class + +2.2.0 +----- + + * added an optional PropertyAccessorInterface parameter to DoctrineType, + EntityType and EntityChoiceList + +2.1.0 +----- + + * added a default implementation of the ManagerRegistry + * added a session storage for Doctrine DBAL + * DoctrineOrmTypeGuesser now guesses "collection" for array Doctrine type + * DoctrineType now caches its choice lists in order to improve performance + * DoctrineType now uses ManagerRegistry::getManagerForClass() if the option "em" is not set + * UniqueEntity validation constraint now accepts a "repositoryMethod" option that will be used to check for uniqueness instead of the default "findBy" + * [BC BREAK] the DbalLogger::log() visibility has been changed from public to + protected diff --git a/vendor/symfony/doctrine-bridge/CacheWarmer/ProxyCacheWarmer.php b/vendor/symfony/doctrine-bridge/CacheWarmer/ProxyCacheWarmer.php new file mode 100644 index 0000000..0a90bc1 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/CacheWarmer/ProxyCacheWarmer.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\CacheWarmer; + +use Doctrine\Persistence\ManagerRegistry; +use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; + +/** + * The proxy generator cache warmer generates all entity proxies. + * + * In the process of generating proxies the cache for all the metadata is primed also, + * since this information is necessary to build the proxies in the first place. + * + * @author Benjamin Eberlei + */ +class ProxyCacheWarmer implements CacheWarmerInterface +{ + private $registry; + + public function __construct(ManagerRegistry $registry) + { + $this->registry = $registry; + } + + /** + * This cache warmer is not optional, without proxies fatal error occurs! + * + * @return false + */ + public function isOptional() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function warmUp(string $cacheDir) + { + foreach ($this->registry->getManagers() as $em) { + // we need the directory no matter the proxy cache generation strategy + if (!is_dir($proxyCacheDir = $em->getConfiguration()->getProxyDir())) { + if (false === @mkdir($proxyCacheDir, 0777, true)) { + throw new \RuntimeException(sprintf('Unable to create the Doctrine Proxy directory "%s".', $proxyCacheDir)); + } + } elseif (!is_writable($proxyCacheDir)) { + throw new \RuntimeException(sprintf('The Doctrine Proxy directory "%s" is not writeable for the current system user.', $proxyCacheDir)); + } + + // if proxies are autogenerated we don't need to generate them in the cache warmer + if ($em->getConfiguration()->getAutoGenerateProxyClasses()) { + continue; + } + + $classes = $em->getMetadataFactory()->getAllMetadata(); + + $em->getProxyFactory()->generateProxyClasses($classes); + } + } +} diff --git a/vendor/symfony/doctrine-bridge/ContainerAwareEventManager.php b/vendor/symfony/doctrine-bridge/ContainerAwareEventManager.php new file mode 100644 index 0000000..67ba6ab --- /dev/null +++ b/vendor/symfony/doctrine-bridge/ContainerAwareEventManager.php @@ -0,0 +1,174 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine; + +use Doctrine\Common\EventArgs; +use Doctrine\Common\EventManager; +use Psr\Container\ContainerInterface; + +/** + * Allows lazy loading of listener services. + * + * @author Johannes M. Schmitt + */ +class ContainerAwareEventManager extends EventManager +{ + /** + * Map of registered listeners. + * + * => + */ + private $listeners = []; + private $initialized = []; + private $methods = []; + private $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * {@inheritdoc} + * + * @return void + */ + public function dispatchEvent($eventName, EventArgs $eventArgs = null) + { + if (!isset($this->listeners[$eventName])) { + return; + } + + $eventArgs = null === $eventArgs ? EventArgs::getEmptyInstance() : $eventArgs; + + if (!isset($this->initialized[$eventName])) { + $this->initializeListeners($eventName); + } + + foreach ($this->listeners[$eventName] as $hash => $listener) { + $listener->{$this->methods[$eventName][$hash]}($eventArgs); + } + } + + /** + * {@inheritdoc} + * + * @return object[][] + */ + public function getListeners($event = null) + { + if (null !== $event) { + if (!isset($this->initialized[$event])) { + $this->initializeListeners($event); + } + + return $this->listeners[$event]; + } + + foreach ($this->listeners as $event => $listeners) { + if (!isset($this->initialized[$event])) { + $this->initializeListeners($event); + } + } + + return $this->listeners; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function hasListeners($event) + { + return isset($this->listeners[$event]) && $this->listeners[$event]; + } + + /** + * {@inheritdoc} + * + * @return void + */ + public function addEventListener($events, $listener) + { + $hash = $this->getHash($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; + + if (\is_string($listener)) { + unset($this->initialized[$event]); + } else { + $this->methods[$event][$hash] = $this->getMethod($listener, $event); + } + } + } + + /** + * {@inheritdoc} + * + * @return void + */ + public function removeEventListener($events, $listener) + { + $hash = $this->getHash($listener); + + foreach ((array) $events as $event) { + // Check if we actually have this listener associated + if (isset($this->listeners[$event][$hash])) { + unset($this->listeners[$event][$hash]); + } + + if (isset($this->methods[$event][$hash])) { + unset($this->methods[$event][$hash]); + } + } + } + + private function initializeListeners(string $eventName) + { + foreach ($this->listeners[$eventName] as $hash => $listener) { + if (\is_string($listener)) { + $this->listeners[$eventName][$hash] = $listener = $this->container->get($listener); + + $this->methods[$eventName][$hash] = $this->getMethod($listener, $eventName); + } + } + $this->initialized[$eventName] = true; + } + + /** + * @param string|object $listener + */ + private function getHash($listener): string + { + if (\is_string($listener)) { + return '_service_'.$listener; + } + + return spl_object_hash($listener); + } + + /** + * @param object $listener + */ + private function getMethod($listener, string $event): string + { + if (!method_exists($listener, $event) && method_exists($listener, '__invoke')) { + return '__invoke'; + } + + return $event; + } +} diff --git a/vendor/symfony/doctrine-bridge/DataCollector/DoctrineDataCollector.php b/vendor/symfony/doctrine-bridge/DataCollector/DoctrineDataCollector.php new file mode 100644 index 0000000..67bf68d --- /dev/null +++ b/vendor/symfony/doctrine-bridge/DataCollector/DoctrineDataCollector.php @@ -0,0 +1,245 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\DataCollector; + +use Doctrine\DBAL\Logging\DebugStack; +use Doctrine\DBAL\Types\ConversionException; +use Doctrine\DBAL\Types\Type; +use Doctrine\Persistence\ManagerRegistry; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\DataCollector; +use Symfony\Component\VarDumper\Caster\Caster; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * DoctrineDataCollector. + * + * @author Fabien Potencier + */ +class DoctrineDataCollector extends DataCollector +{ + private $registry; + private $connections; + private $managers; + + /** + * @var DebugStack[] + */ + private $loggers = []; + + public function __construct(ManagerRegistry $registry) + { + $this->registry = $registry; + $this->connections = $registry->getConnectionNames(); + $this->managers = $registry->getManagerNames(); + } + + /** + * Adds the stack logger for a connection. + */ + public function addLogger(string $name, DebugStack $logger) + { + $this->loggers[$name] = $logger; + } + + /** + * {@inheritdoc} + */ + public function collect(Request $request, Response $response, \Throwable $exception = null) + { + $queries = []; + foreach ($this->loggers as $name => $logger) { + $queries[$name] = $this->sanitizeQueries($name, $logger->queries); + } + + $this->data = [ + 'queries' => $queries, + 'connections' => $this->connections, + 'managers' => $this->managers, + ]; + } + + public function reset() + { + $this->data = []; + + foreach ($this->loggers as $logger) { + $logger->queries = []; + $logger->currentQuery = 0; + } + } + + public function getManagers() + { + return $this->data['managers']; + } + + public function getConnections() + { + return $this->data['connections']; + } + + public function getQueryCount() + { + return array_sum(array_map('count', $this->data['queries'])); + } + + public function getQueries() + { + return $this->data['queries']; + } + + public function getTime() + { + $time = 0; + foreach ($this->data['queries'] as $queries) { + foreach ($queries as $query) { + $time += $query['executionMS']; + } + } + + return $time; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'db'; + } + + /** + * {@inheritdoc} + */ + protected function getCasters() + { + return parent::getCasters() + [ + ObjectParameter::class => static function (ObjectParameter $o, array $a, Stub $s): array { + $s->class = $o->getClass(); + $s->value = $o->getObject(); + + $r = new \ReflectionClass($o->getClass()); + if ($f = $r->getFileName()) { + $s->attr['file'] = $f; + $s->attr['line'] = $r->getStartLine(); + } else { + unset($s->attr['file']); + unset($s->attr['line']); + } + + if ($error = $o->getError()) { + return [Caster::PREFIX_VIRTUAL.'⚠' => $error->getMessage()]; + } + + if ($o->isStringable()) { + return [Caster::PREFIX_VIRTUAL.'__toString()' => (string) $o->getObject()]; + } + + return [Caster::PREFIX_VIRTUAL.'⚠' => sprintf('Object of class "%s" could not be converted to string.', $o->getClass())]; + }, + ]; + } + + private function sanitizeQueries(string $connectionName, array $queries): array + { + foreach ($queries as $i => $query) { + $queries[$i] = $this->sanitizeQuery($connectionName, $query); + } + + return $queries; + } + + private function sanitizeQuery(string $connectionName, array $query): array + { + $query['explainable'] = true; + $query['runnable'] = true; + if (null === $query['params']) { + $query['params'] = []; + } + if (!\is_array($query['params'])) { + $query['params'] = [$query['params']]; + } + if (!\is_array($query['types'])) { + $query['types'] = []; + } + foreach ($query['params'] as $j => $param) { + $e = null; + if (isset($query['types'][$j])) { + // Transform the param according to the type + $type = $query['types'][$j]; + if (\is_string($type)) { + $type = Type::getType($type); + } + if ($type instanceof Type) { + $query['types'][$j] = $type->getBindingType(); + try { + $param = $type->convertToDatabaseValue($param, $this->registry->getConnection($connectionName)->getDatabasePlatform()); + } catch (\TypeError $e) { + } catch (ConversionException $e) { + } + } + } + + list($query['params'][$j], $explainable, $runnable) = $this->sanitizeParam($param, $e); + if (!$explainable) { + $query['explainable'] = false; + } + + if (!$runnable) { + $query['runnable'] = false; + } + } + + $query['params'] = $this->cloneVar($query['params']); + + return $query; + } + + /** + * Sanitizes a param. + * + * The return value is an array with the sanitized value and a boolean + * indicating if the original value was kept (allowing to use the sanitized + * value to explain the query). + */ + private function sanitizeParam($var, ?\Throwable $error): array + { + if (\is_object($var)) { + return [$o = new ObjectParameter($var, $error), false, $o->isStringable() && !$error]; + } + + if ($error) { + return ['⚠ '.$error->getMessage(), false, false]; + } + + if (\is_array($var)) { + $a = []; + $explainable = $runnable = true; + foreach ($var as $k => $v) { + list($value, $e, $r) = $this->sanitizeParam($v, null); + $explainable = $explainable && $e; + $runnable = $runnable && $r; + $a[$k] = $value; + } + + return [$a, $explainable, $runnable]; + } + + if (\is_resource($var)) { + return [sprintf('/* Resource(%s) */', get_resource_type($var)), false, false]; + } + + return [$var, true, true]; + } +} diff --git a/vendor/symfony/doctrine-bridge/DataCollector/ObjectParameter.php b/vendor/symfony/doctrine-bridge/DataCollector/ObjectParameter.php new file mode 100644 index 0000000..26bdb7f --- /dev/null +++ b/vendor/symfony/doctrine-bridge/DataCollector/ObjectParameter.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\DataCollector; + +final class ObjectParameter +{ + private $object; + private $error; + private $stringable; + private $class; + + /** + * @param object $object + */ + public function __construct($object, ?\Throwable $error) + { + $this->object = $object; + $this->error = $error; + $this->stringable = \is_callable([$object, '__toString']); + $this->class = \get_class($object); + } + + /** + * @return object + */ + public function getObject() + { + return $this->object; + } + + public function getError(): ?\Throwable + { + return $this->error; + } + + public function isStringable(): bool + { + return $this->stringable; + } + + public function getClass(): string + { + return $this->class; + } +} diff --git a/vendor/symfony/doctrine-bridge/DataFixtures/ContainerAwareLoader.php b/vendor/symfony/doctrine-bridge/DataFixtures/ContainerAwareLoader.php new file mode 100644 index 0000000..7ccd1df --- /dev/null +++ b/vendor/symfony/doctrine-bridge/DataFixtures/ContainerAwareLoader.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\DataFixtures; + +use Doctrine\Common\DataFixtures\FixtureInterface; +use Doctrine\Common\DataFixtures\Loader; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Doctrine data fixtures loader that injects the service container into + * fixture objects that implement ContainerAwareInterface. + * + * Note: Use of this class requires the Doctrine data fixtures extension, which + * is a suggested dependency for Symfony. + */ +class ContainerAwareLoader extends Loader +{ + private $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public function addFixture(FixtureInterface $fixture) + { + if ($fixture instanceof ContainerAwareInterface) { + $fixture->setContainer($this->container); + } + + parent::addFixture($fixture); + } +} diff --git a/vendor/symfony/doctrine-bridge/DependencyInjection/AbstractDoctrineExtension.php b/vendor/symfony/doctrine-bridge/DependencyInjection/AbstractDoctrineExtension.php new file mode 100644 index 0000000..23230f7 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/DependencyInjection/AbstractDoctrineExtension.php @@ -0,0 +1,440 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\DependencyInjection; + +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; + +/** + * This abstract classes groups common code that Doctrine Object Manager extensions (ORM, MongoDB, CouchDB) need. + * + * @author Benjamin Eberlei + */ +abstract class AbstractDoctrineExtension extends Extension +{ + /** + * Used inside metadata driver method to simplify aggregation of data. + */ + protected $aliasMap = []; + + /** + * Used inside metadata driver method to simplify aggregation of data. + */ + protected $drivers = []; + + /** + * @param array $objectManager A configured object manager + * + * @throws \InvalidArgumentException + */ + protected function loadMappingInformation(array $objectManager, ContainerBuilder $container) + { + if ($objectManager['auto_mapping']) { + // automatically register bundle mappings + foreach (array_keys($container->getParameter('kernel.bundles')) as $bundle) { + if (!isset($objectManager['mappings'][$bundle])) { + $objectManager['mappings'][$bundle] = [ + 'mapping' => true, + 'is_bundle' => true, + ]; + } + } + } + + foreach ($objectManager['mappings'] as $mappingName => $mappingConfig) { + if (null !== $mappingConfig && false === $mappingConfig['mapping']) { + continue; + } + + $mappingConfig = array_replace([ + 'dir' => false, + 'type' => false, + 'prefix' => false, + ], (array) $mappingConfig); + + $mappingConfig['dir'] = $container->getParameterBag()->resolveValue($mappingConfig['dir']); + // a bundle configuration is detected by realizing that the specified dir is not absolute and existing + if (!isset($mappingConfig['is_bundle'])) { + $mappingConfig['is_bundle'] = !is_dir($mappingConfig['dir']); + } + + if ($mappingConfig['is_bundle']) { + $bundle = null; + foreach ($container->getParameter('kernel.bundles') as $name => $class) { + if ($mappingName === $name) { + $bundle = new \ReflectionClass($class); + + break; + } + } + + if (null === $bundle) { + throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled.', $mappingName)); + } + + $mappingConfig = $this->getMappingDriverBundleConfigDefaults($mappingConfig, $bundle, $container); + if (!$mappingConfig) { + continue; + } + } + + $this->assertValidMappingConfiguration($mappingConfig, $objectManager['name']); + $this->setMappingDriverConfig($mappingConfig, $mappingName); + $this->setMappingDriverAlias($mappingConfig, $mappingName); + } + } + + /** + * Register the alias for this mapping driver. + * + * Aliases can be used in the Query languages of all the Doctrine object managers to simplify writing tasks. + */ + protected function setMappingDriverAlias(array $mappingConfig, string $mappingName) + { + if (isset($mappingConfig['alias'])) { + $this->aliasMap[$mappingConfig['alias']] = $mappingConfig['prefix']; + } else { + $this->aliasMap[$mappingName] = $mappingConfig['prefix']; + } + } + + /** + * Register the mapping driver configuration for later use with the object managers metadata driver chain. + * + * @throws \InvalidArgumentException + */ + protected function setMappingDriverConfig(array $mappingConfig, string $mappingName) + { + $mappingDirectory = $mappingConfig['dir']; + if (!is_dir($mappingDirectory)) { + throw new \InvalidArgumentException(sprintf('Invalid Doctrine mapping path given. Cannot load Doctrine mapping/bundle named "%s".', $mappingName)); + } + + $this->drivers[$mappingConfig['type']][$mappingConfig['prefix']] = realpath($mappingDirectory) ?: $mappingDirectory; + } + + /** + * If this is a bundle controlled mapping all the missing information can be autodetected by this method. + * + * Returns false when autodetection failed, an array of the completed information otherwise. + * + * @return array|false + */ + protected function getMappingDriverBundleConfigDefaults(array $bundleConfig, \ReflectionClass $bundle, ContainerBuilder $container) + { + $bundleDir = \dirname($bundle->getFileName()); + + if (!$bundleConfig['type']) { + $bundleConfig['type'] = $this->detectMetadataDriver($bundleDir, $container); + } + + if (!$bundleConfig['type']) { + // skip this bundle, no mapping information was found. + return false; + } + + if (!$bundleConfig['dir']) { + if (\in_array($bundleConfig['type'], ['annotation', 'staticphp'])) { + $bundleConfig['dir'] = $bundleDir.'/'.$this->getMappingObjectDefaultName(); + } else { + $bundleConfig['dir'] = $bundleDir.'/'.$this->getMappingResourceConfigDirectory(); + } + } else { + $bundleConfig['dir'] = $bundleDir.'/'.$bundleConfig['dir']; + } + + if (!$bundleConfig['prefix']) { + $bundleConfig['prefix'] = $bundle->getNamespaceName().'\\'.$this->getMappingObjectDefaultName(); + } + + return $bundleConfig; + } + + /** + * Register all the collected mapping information with the object manager by registering the appropriate mapping drivers. + */ + protected function registerMappingDrivers(array $objectManager, ContainerBuilder $container) + { + // configure metadata driver for each bundle based on the type of mapping files found + if ($container->hasDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver'))) { + $chainDriverDef = $container->getDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver')); + } else { + $chainDriverDef = new Definition($this->getMetadataDriverClass('driver_chain')); + $chainDriverDef->setPublic(false); + } + + foreach ($this->drivers as $driverType => $driverPaths) { + $mappingService = $this->getObjectManagerElementName($objectManager['name'].'_'.$driverType.'_metadata_driver'); + if ($container->hasDefinition($mappingService)) { + $mappingDriverDef = $container->getDefinition($mappingService); + $args = $mappingDriverDef->getArguments(); + if ('annotation' == $driverType) { + $args[1] = array_merge(array_values($driverPaths), $args[1]); + } else { + $args[0] = array_merge(array_values($driverPaths), $args[0]); + } + $mappingDriverDef->setArguments($args); + } elseif ('annotation' == $driverType) { + $mappingDriverDef = new Definition($this->getMetadataDriverClass($driverType), [ + new Reference($this->getObjectManagerElementName('metadata.annotation_reader')), + array_values($driverPaths), + ]); + } else { + $mappingDriverDef = new Definition($this->getMetadataDriverClass($driverType), [ + array_values($driverPaths), + ]); + } + $mappingDriverDef->setPublic(false); + if (false !== strpos($mappingDriverDef->getClass(), 'yml') || false !== strpos($mappingDriverDef->getClass(), 'xml')) { + $mappingDriverDef->setArguments([array_flip($driverPaths)]); + $mappingDriverDef->addMethodCall('setGlobalBasename', ['mapping']); + } + + $container->setDefinition($mappingService, $mappingDriverDef); + + foreach ($driverPaths as $prefix => $driverPath) { + $chainDriverDef->addMethodCall('addDriver', [new Reference($mappingService), $prefix]); + } + } + + $container->setDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver'), $chainDriverDef); + } + + /** + * Assertion if the specified mapping information is valid. + * + * @throws \InvalidArgumentException + */ + protected function assertValidMappingConfiguration(array $mappingConfig, string $objectManagerName) + { + if (!$mappingConfig['type'] || !$mappingConfig['dir'] || !$mappingConfig['prefix']) { + throw new \InvalidArgumentException(sprintf('Mapping definitions for Doctrine manager "%s" require at least the "type", "dir" and "prefix" options.', $objectManagerName)); + } + + if (!is_dir($mappingConfig['dir'])) { + throw new \InvalidArgumentException(sprintf('Specified non-existing directory "%s" as Doctrine mapping source.', $mappingConfig['dir'])); + } + + if (!\in_array($mappingConfig['type'], ['xml', 'yml', 'annotation', 'php', 'staticphp'])) { + throw new \InvalidArgumentException(sprintf('Can only configure "xml", "yml", "annotation", "php" or "staticphp" through the DoctrineBundle. Use your own bundle to configure other metadata drivers. You can register them by adding a new driver to the "%s" service definition.', $this->getObjectManagerElementName($objectManagerName.'_metadata_driver'))); + } + } + + /** + * Detects what metadata driver to use for the supplied directory. + * + * @return string|null A metadata driver short name, if one can be detected + */ + protected function detectMetadataDriver(string $dir, ContainerBuilder $container) + { + $configPath = $this->getMappingResourceConfigDirectory(); + $extension = $this->getMappingResourceExtension(); + + if (glob($dir.'/'.$configPath.'/*.'.$extension.'.xml', GLOB_NOSORT)) { + $driver = 'xml'; + } elseif (glob($dir.'/'.$configPath.'/*.'.$extension.'.yml', GLOB_NOSORT)) { + $driver = 'yml'; + } elseif (glob($dir.'/'.$configPath.'/*.'.$extension.'.php', GLOB_NOSORT)) { + $driver = 'php'; + } else { + // add the closest existing directory as a resource + $resource = $dir.'/'.$configPath; + while (!is_dir($resource)) { + $resource = \dirname($resource); + } + $container->fileExists($resource, false); + + return $container->fileExists($dir.'/'.$this->getMappingObjectDefaultName(), false) ? 'annotation' : null; + } + $container->fileExists($dir.'/'.$configPath, false); + + return $driver; + } + + /** + * Loads a configured object manager metadata, query or result cache driver. + * + * @throws \InvalidArgumentException in case of unknown driver type + */ + protected function loadObjectManagerCacheDriver(array $objectManager, ContainerBuilder $container, string $cacheName) + { + $this->loadCacheDriver($cacheName, $objectManager['name'], $objectManager[$cacheName.'_driver'], $container); + } + + /** + * Loads a cache driver. + * + * @return string + * + * @throws \InvalidArgumentException + */ + protected function loadCacheDriver(string $cacheName, string $objectManagerName, array $cacheDriver, ContainerBuilder $container) + { + $cacheDriverServiceId = $this->getObjectManagerElementName($objectManagerName.'_'.$cacheName); + + switch ($cacheDriver['type']) { + case 'service': + $container->setAlias($cacheDriverServiceId, new Alias($cacheDriver['id'], false)); + + return $cacheDriverServiceId; + case 'memcached': + $memcachedClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.memcached.class').'%'; + $memcachedInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.memcached_instance.class').'%'; + $memcachedHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.memcached_host').'%'; + $memcachedPort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcached_port').'%'; + $cacheDef = new Definition($memcachedClass); + $memcachedInstance = new Definition($memcachedInstanceClass); + $memcachedInstance->setPrivate(true); + $memcachedInstance->addMethodCall('addServer', [ + $memcachedHost, $memcachedPort, + ]); + $container->setDefinition($this->getObjectManagerElementName(sprintf('%s_memcached_instance', $objectManagerName)), $memcachedInstance); + $cacheDef->addMethodCall('setMemcached', [new Reference($this->getObjectManagerElementName(sprintf('%s_memcached_instance', $objectManagerName)))]); + break; + case 'redis': + $redisClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.redis.class').'%'; + $redisInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.redis_instance.class').'%'; + $redisHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.redis_host').'%'; + $redisPort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.redis_port').'%'; + $cacheDef = new Definition($redisClass); + $redisInstance = new Definition($redisInstanceClass); + $redisInstance->setPrivate(true); + $redisInstance->addMethodCall('connect', [ + $redisHost, $redisPort, + ]); + $container->setDefinition($this->getObjectManagerElementName(sprintf('%s_redis_instance', $objectManagerName)), $redisInstance); + $cacheDef->addMethodCall('setRedis', [new Reference($this->getObjectManagerElementName(sprintf('%s_redis_instance', $objectManagerName)))]); + break; + case 'apc': + case 'apcu': + case 'array': + case 'xcache': + case 'wincache': + case 'zenddata': + $cacheDef = new Definition('%'.$this->getObjectManagerElementName(sprintf('cache.%s.class', $cacheDriver['type'])).'%'); + break; + default: + throw new \InvalidArgumentException(sprintf('"%s" is an unrecognized Doctrine cache driver.', $cacheDriver['type'])); + } + + $cacheDef->setPublic(false); + + if (!isset($cacheDriver['namespace'])) { + // generate a unique namespace for the given application + if ($container->hasParameter('cache.prefix.seed')) { + $seed = '.'.$container->getParameterBag()->resolveValue($container->getParameter('cache.prefix.seed')); + } else { + $seed = '_'.$container->getParameter('kernel.project_dir'); + } + $seed .= '.'.$container->getParameter('kernel.container_class'); + $namespace = 'sf_'.$this->getMappingResourceExtension().'_'.$objectManagerName.'_'.ContainerBuilder::hash($seed); + + $cacheDriver['namespace'] = $namespace; + } + + $cacheDef->addMethodCall('setNamespace', [$cacheDriver['namespace']]); + + $container->setDefinition($cacheDriverServiceId, $cacheDef); + + return $cacheDriverServiceId; + } + + /** + * Returns a modified version of $managerConfigs. + * + * The manager called $autoMappedManager will map all bundles that are not mapped by other managers. + * + * @return array The modified version of $managerConfigs + */ + protected function fixManagersAutoMappings(array $managerConfigs, array $bundles) + { + if ($autoMappedManager = $this->validateAutoMapping($managerConfigs)) { + foreach (array_keys($bundles) as $bundle) { + foreach ($managerConfigs as $manager) { + if (isset($manager['mappings'][$bundle])) { + continue 2; + } + } + $managerConfigs[$autoMappedManager]['mappings'][$bundle] = [ + 'mapping' => true, + 'is_bundle' => true, + ]; + } + $managerConfigs[$autoMappedManager]['auto_mapping'] = false; + } + + return $managerConfigs; + } + + /** + * Prefixes the relative dependency injection container path with the object manager prefix. + * + * @example $name is 'entity_manager' then the result would be 'doctrine.orm.entity_manager' + * + * @return string + */ + abstract protected function getObjectManagerElementName(string $name); + + /** + * Noun that describes the mapped objects such as Entity or Document. + * + * Will be used for autodetection of persistent objects directory. + * + * @return string + */ + abstract protected function getMappingObjectDefaultName(); + + /** + * Relative path from the bundle root to the directory where mapping files reside. + * + * @return string + */ + abstract protected function getMappingResourceConfigDirectory(); + + /** + * Extension used by the mapping files. + * + * @return string + */ + abstract protected function getMappingResourceExtension(); + + /** + * The class name used by the various mapping drivers. + */ + abstract protected function getMetadataDriverClass(string $driverType): string; + + /** + * Search for a manager that is declared as 'auto_mapping' = true. + * + * @throws \LogicException + */ + private function validateAutoMapping(array $managerConfigs): ?string + { + $autoMappedManager = null; + foreach ($managerConfigs as $name => $manager) { + if (!$manager['auto_mapping']) { + continue; + } + + if (null !== $autoMappedManager) { + throw new \LogicException(sprintf('You cannot enable "auto_mapping" on more than one manager at the same time (found in "%s" and %s").', $autoMappedManager, $name)); + } + + $autoMappedManager = $name; + } + + return $autoMappedManager; + } +} diff --git a/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/DoctrineValidationPass.php b/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/DoctrineValidationPass.php new file mode 100644 index 0000000..2577664 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/DoctrineValidationPass.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Registers additional validators. + * + * @author Benjamin Eberlei + */ +class DoctrineValidationPass implements CompilerPassInterface +{ + private $managerType; + + public function __construct(string $managerType) + { + $this->managerType = $managerType; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->updateValidatorMappingFiles($container, 'xml', 'xml'); + $this->updateValidatorMappingFiles($container, 'yaml', 'yml'); + } + + /** + * Gets the validation mapping files for the format and extends them with + * files matching a doctrine search pattern (Resources/config/validation.orm.xml). + */ + private function updateValidatorMappingFiles(ContainerBuilder $container, string $mapping, string $extension) + { + if (!$container->hasParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files')) { + return; + } + + $files = $container->getParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files'); + $validationPath = '/config/validation.'.$this->managerType.'.'.$extension; + + foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { + if ($container->fileExists($file = $bundle['path'].'/Resources'.$validationPath) || $container->fileExists($file = $bundle['path'].$validationPath)) { + $files[] = $file; + } + } + + $container->setParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files', $files); + } +} diff --git a/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php b/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php new file mode 100644 index 0000000..e73de3d --- /dev/null +++ b/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php @@ -0,0 +1,149 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Registers event listeners and subscribers to the available doctrine connections. + * + * @author Jeremy Mikola + * @author Alexander + * @author David Maicher + */ +class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface +{ + private $connections; + private $eventManagers; + private $managerTemplate; + private $tagPrefix; + + /** + * @param string $connections Parameter ID for connections + * @param string $managerTemplate sprintf() template for generating the event + * manager's service ID for a connection name + * @param string $tagPrefix Tag prefix for listeners and subscribers + */ + public function __construct(string $connections, string $managerTemplate, string $tagPrefix) + { + $this->connections = $connections; + $this->managerTemplate = $managerTemplate; + $this->tagPrefix = $tagPrefix; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasParameter($this->connections)) { + return; + } + + $this->connections = $container->getParameter($this->connections); + $this->addTaggedSubscribers($container); + $this->addTaggedListeners($container); + } + + private function addTaggedSubscribers(ContainerBuilder $container) + { + $subscriberTag = $this->tagPrefix.'.event_subscriber'; + $taggedSubscribers = $this->findAndSortTags($subscriberTag, $container); + + foreach ($taggedSubscribers as $taggedSubscriber) { + list($id, $tag) = $taggedSubscriber; + $connections = isset($tag['connection']) ? [$tag['connection']] : array_keys($this->connections); + foreach ($connections as $con) { + if (!isset($this->connections[$con])) { + throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections)))); + } + + $this->getEventManagerDef($container, $con)->addMethodCall('addEventSubscriber', [new Reference($id)]); + } + } + } + + private function addTaggedListeners(ContainerBuilder $container) + { + $listenerTag = $this->tagPrefix.'.event_listener'; + $taggedListeners = $this->findAndSortTags($listenerTag, $container); + $listenerRefs = []; + + foreach ($taggedListeners as $taggedListener) { + list($id, $tag) = $taggedListener; + if (!isset($tag['event'])) { + throw new InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id)); + } + + $connections = isset($tag['connection']) ? [$tag['connection']] : array_keys($this->connections); + foreach ($connections as $con) { + if (!isset($this->connections[$con])) { + throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections)))); + } + $listenerRefs[$con][$id] = new Reference($id); + + // we add one call per event per service so we have the correct order + $this->getEventManagerDef($container, $con)->addMethodCall('addEventListener', [[$tag['event']], $id]); + } + } + + // replace service container argument of event managers with smaller service locator + // so services can even remain private + foreach ($listenerRefs as $connection => $refs) { + $this->getEventManagerDef($container, $connection) + ->replaceArgument(0, ServiceLocatorTagPass::register($container, $refs)); + } + } + + private function getEventManagerDef(ContainerBuilder $container, string $name) + { + if (!isset($this->eventManagers[$name])) { + $this->eventManagers[$name] = $container->getDefinition(sprintf($this->managerTemplate, $name)); + } + + return $this->eventManagers[$name]; + } + + /** + * Finds and orders all service tags with the given name by their priority. + * + * The order of additions must be respected for services having the same priority, + * and knowing that the \SplPriorityQueue class does not respect the FIFO method, + * we should not use this class. + * + * @see https://bugs.php.net/53710 + * @see https://bugs.php.net/60926 + */ + private function findAndSortTags(string $tagName, ContainerBuilder $container): array + { + $sortedTags = []; + + foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $tags) { + foreach ($tags as $attributes) { + $priority = isset($attributes['priority']) ? $attributes['priority'] : 0; + $sortedTags[$priority][] = [$serviceId, $attributes]; + } + } + + if ($sortedTags) { + krsort($sortedTags); + $sortedTags = array_merge(...$sortedTags); + } + + return $sortedTags; + } +} diff --git a/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterMappingsPass.php b/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterMappingsPass.php new file mode 100644 index 0000000..3c06fa2 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterMappingsPass.php @@ -0,0 +1,237 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Base class for the doctrine bundles to provide a compiler pass class that + * helps to register doctrine mappings. + * + * The compiler pass is meant to register the mappings with the metadata + * chain driver corresponding to one of the object managers. + * + * For concrete implementations, see the RegisterXyMappingsPass classes + * in the DoctrineBundle resp. + * DoctrineMongodbBundle, DoctrineCouchdbBundle and DoctrinePhpcrBundle. + * + * @author David Buchmann + */ +abstract class RegisterMappingsPass implements CompilerPassInterface +{ + /** + * DI object for the driver to use, either a service definition for a + * private service or a reference for a public service. + * + * @var Definition|Reference + */ + protected $driver; + + /** + * List of namespaces handled by the driver. + * + * @var string[] + */ + protected $namespaces; + + /** + * List of potential container parameters that hold the object manager name + * to register the mappings with the correct metadata driver, for example + * ['acme.manager', 'doctrine.default_entity_manager']. + * + * @var string[] + */ + protected $managerParameters; + + /** + * Naming pattern of the metadata chain driver service ids, for example + * 'doctrine.orm.%s_metadata_driver'. + * + * @var string + */ + protected $driverPattern; + + /** + * A name for a parameter in the container. If set, this compiler pass will + * only do anything if the parameter is present. (But regardless of the + * value of that parameter. + * + * @var string|false + */ + protected $enabledParameter; + + /** + * Naming pattern for the configuration service id, for example + * 'doctrine.orm.%s_configuration'. + * + * @var string + */ + private $configurationPattern; + + /** + * Method name to call on the configuration service. This depends on the + * Doctrine implementation. For example addEntityNamespace. + * + * @var string + */ + private $registerAliasMethodName; + + /** + * Map of alias to namespace. + * + * @var string[] + */ + private $aliasMap; + + /** + * The $managerParameters is an ordered list of container parameters that could provide the + * name of the manager to register these namespaces and alias on. The first non-empty name + * is used, the others skipped. + * + * The $aliasMap parameter can be used to define bundle namespace shortcuts like the + * DoctrineBundle provides automatically for objects in the default Entity/Document folder. + * + * @param Definition|Reference $driver Driver DI definition or reference + * @param string[] $namespaces List of namespaces handled by $driver + * @param string[] $managerParameters list of container parameters that could + * hold the manager name + * @param string $driverPattern Pattern for the metadata driver service name + * @param string|false $enabledParameter Service container parameter that must be + * present to enable the mapping. Set to false + * to not do any check, optional. + * @param string $configurationPattern Pattern for the Configuration service name + * @param string $registerAliasMethodName Name of Configuration class method to + * register alias + * @param string[] $aliasMap Map of alias to namespace + */ + public function __construct($driver, array $namespaces, array $managerParameters, string $driverPattern, $enabledParameter = false, string $configurationPattern = '', string $registerAliasMethodName = '', array $aliasMap = []) + { + $this->driver = $driver; + $this->namespaces = $namespaces; + $this->managerParameters = $managerParameters; + $this->driverPattern = $driverPattern; + $this->enabledParameter = $enabledParameter; + if (\count($aliasMap) && (!$configurationPattern || !$registerAliasMethodName)) { + throw new \InvalidArgumentException('configurationPattern and registerAliasMethodName are required to register namespace alias'); + } + $this->configurationPattern = $configurationPattern; + $this->registerAliasMethodName = $registerAliasMethodName; + $this->aliasMap = $aliasMap; + } + + /** + * Register mappings and alias with the metadata drivers. + */ + public function process(ContainerBuilder $container) + { + if (!$this->enabled($container)) { + return; + } + + $mappingDriverDef = $this->getDriver($container); + $chainDriverDefService = $this->getChainDriverServiceName($container); + // Definition for a Doctrine\Persistence\Mapping\Driver\MappingDriverChain + $chainDriverDef = $container->getDefinition($chainDriverDefService); + foreach ($this->namespaces as $namespace) { + $chainDriverDef->addMethodCall('addDriver', [$mappingDriverDef, $namespace]); + } + + if (!\count($this->aliasMap)) { + return; + } + + $configurationServiceName = $this->getConfigurationServiceName($container); + // Definition of the Doctrine\...\Configuration class specific to the Doctrine flavour. + $configurationServiceDefinition = $container->getDefinition($configurationServiceName); + foreach ($this->aliasMap as $alias => $namespace) { + $configurationServiceDefinition->addMethodCall($this->registerAliasMethodName, [$alias, $namespace]); + } + } + + /** + * Get the service name of the metadata chain driver that the mappings + * should be registered with. + * + * @return string The name of the chain driver service + * + * @throws InvalidArgumentException if non of the managerParameters has a + * non-empty value + */ + protected function getChainDriverServiceName(ContainerBuilder $container) + { + return sprintf($this->driverPattern, $this->getManagerName($container)); + } + + /** + * Create the service definition for the metadata driver. + * + * @param ContainerBuilder $container Passed on in case an extending class + * needs access to the container + * + * @return Definition|Reference the metadata driver to add to all chain drivers + */ + protected function getDriver(ContainerBuilder $container) + { + return $this->driver; + } + + /** + * Get the service name from the pattern and the configured manager name. + * + * @throws InvalidArgumentException if none of the managerParameters has a + * non-empty value + */ + private function getConfigurationServiceName(ContainerBuilder $container): string + { + return sprintf($this->configurationPattern, $this->getManagerName($container)); + } + + /** + * Determine the manager name. + * + * The default implementation loops over the managerParameters and returns + * the first non-empty parameter. + * + * @throws InvalidArgumentException if none of the managerParameters is found in the container + */ + private function getManagerName(ContainerBuilder $container): string + { + foreach ($this->managerParameters as $param) { + if ($container->hasParameter($param)) { + $name = $container->getParameter($param); + if ($name) { + return $name; + } + } + } + + throw new InvalidArgumentException(sprintf('Could not find the manager name parameter in the container. Tried the following parameter names: "%s"', implode('", "', $this->managerParameters))); + } + + /** + * Determine whether this mapping should be activated or not. This allows + * to take this decision with the container builder available. + * + * This default implementation checks if the class has the enabledParameter + * configured and if so if that parameter is present in the container. + * + * @return bool whether this compiler pass really should register the mappings + */ + protected function enabled(ContainerBuilder $container) + { + return !$this->enabledParameter || $container->hasParameter($this->enabledParameter); + } +} diff --git a/vendor/symfony/doctrine-bridge/DependencyInjection/Security/UserProvider/EntityFactory.php b/vendor/symfony/doctrine-bridge/DependencyInjection/Security/UserProvider/EntityFactory.php new file mode 100644 index 0000000..454c7cc --- /dev/null +++ b/vendor/symfony/doctrine-bridge/DependencyInjection/Security/UserProvider/EntityFactory.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\DependencyInjection\Security\UserProvider; + +use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface; +use Symfony\Component\Config\Definition\Builder\NodeDefinition; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * EntityFactory creates services for Doctrine user provider. + * + * @author Fabien Potencier + * @author Christophe Coevoet + */ +class EntityFactory implements UserProviderFactoryInterface +{ + private $key; + private $providerId; + + public function __construct(string $key, string $providerId) + { + $this->key = $key; + $this->providerId = $providerId; + } + + public function create(ContainerBuilder $container, string $id, array $config) + { + $container + ->setDefinition($id, new ChildDefinition($this->providerId)) + ->addArgument($config['class']) + ->addArgument($config['property']) + ->addArgument($config['manager_name']) + ; + } + + public function getKey() + { + return $this->key; + } + + public function addConfiguration(NodeDefinition $node) + { + $node + ->children() + ->scalarNode('class')->isRequired()->cannotBeEmpty()->end() + ->scalarNode('property')->defaultNull()->end() + ->scalarNode('manager_name')->defaultNull()->end() + ->end() + ; + } +} diff --git a/vendor/symfony/doctrine-bridge/Form/ChoiceList/DoctrineChoiceLoader.php b/vendor/symfony/doctrine-bridge/Form/ChoiceList/DoctrineChoiceLoader.php new file mode 100644 index 0000000..cb09a3d --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Form/ChoiceList/DoctrineChoiceLoader.php @@ -0,0 +1,150 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Form\ChoiceList; + +use Doctrine\Persistence\ObjectManager; +use Symfony\Component\Form\ChoiceList\ArrayChoiceList; +use Symfony\Component\Form\ChoiceList\ChoiceListInterface; +use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; + +/** + * Loads choices using a Doctrine object manager. + * + * @author Bernhard Schussek + */ +class DoctrineChoiceLoader implements ChoiceLoaderInterface +{ + private $manager; + private $class; + private $idReader; + private $objectLoader; + + /** + * @var ChoiceListInterface + */ + private $choiceList; + + /** + * Creates a new choice loader. + * + * Optionally, an implementation of {@link EntityLoaderInterface} can be + * passed which optimizes the object loading for one of the Doctrine + * mapper implementations. + * + * @param string $class The class name of the loaded objects + */ + public function __construct(ObjectManager $manager, string $class, IdReader $idReader = null, EntityLoaderInterface $objectLoader = null) + { + $classMetadata = $manager->getClassMetadata($class); + + if ($idReader && !$idReader->isSingleId()) { + throw new \InvalidArgumentException(sprintf('The second argument `$idReader` of "%s" must be null when the query cannot be optimized because of composite id fields.', __METHOD__)); + } + + $this->manager = $manager; + $this->class = $classMetadata->getName(); + $this->idReader = $idReader; + $this->objectLoader = $objectLoader; + } + + /** + * {@inheritdoc} + */ + public function loadChoiceList(callable $value = null) + { + if ($this->choiceList) { + return $this->choiceList; + } + + $objects = $this->objectLoader + ? $this->objectLoader->getEntities() + : $this->manager->getRepository($this->class)->findAll(); + + return $this->choiceList = new ArrayChoiceList($objects, $value); + } + + /** + * {@inheritdoc} + */ + public function loadValuesForChoices(array $choices, callable $value = null) + { + // Performance optimization + if (empty($choices)) { + return []; + } + + // Optimize performance for single-field identifiers. We already + // know that the IDs are used as values + $optimize = $this->idReader && (null === $value || \is_array($value) && $value[0] === $this->idReader); + + // Attention: This optimization does not check choices for existence + if ($optimize && !$this->choiceList) { + $values = []; + + // Maintain order and indices of the given objects + foreach ($choices as $i => $object) { + if ($object instanceof $this->class) { + // Make sure to convert to the right format + $values[$i] = (string) $this->idReader->getIdValue($object); + } + } + + return $values; + } + + return $this->loadChoiceList($value)->getValuesForChoices($choices); + } + + /** + * {@inheritdoc} + */ + public function loadChoicesForValues(array $values, callable $value = null) + { + // Performance optimization + // Also prevents the generation of "WHERE id IN ()" queries through the + // object loader. At least with MySQL and on the development machine + // this was tested on, no exception was thrown for such invalid + // statements, consequently no test fails when this code is removed. + // https://github.com/symfony/symfony/pull/8981#issuecomment-24230557 + if (empty($values)) { + return []; + } + + // Optimize performance in case we have an object loader and + // a single-field identifier + $optimize = $this->idReader && (null === $value || \is_array($value) && $this->idReader === $value[0]); + + if ($optimize && !$this->choiceList && $this->objectLoader) { + $unorderedObjects = $this->objectLoader->getEntitiesByIds($this->idReader->getIdField(), $values); + $objectsById = []; + $objects = []; + + // Maintain order and indices from the given $values + // An alternative approach to the following loop is to add the + // "INDEX BY" clause to the Doctrine query in the loader, + // but I'm not sure whether that's doable in a generic fashion. + foreach ($unorderedObjects as $object) { + $objectsById[(string) $this->idReader->getIdValue($object)] = $object; + } + + foreach ($values as $i => $id) { + if (isset($objectsById[$id])) { + $objects[$i] = $objectsById[$id]; + } + } + + return $objects; + } + + return $this->loadChoiceList($value)->getChoicesForValues($values); + } +} diff --git a/vendor/symfony/doctrine-bridge/Form/ChoiceList/EntityLoaderInterface.php b/vendor/symfony/doctrine-bridge/Form/ChoiceList/EntityLoaderInterface.php new file mode 100644 index 0000000..8eb5a84 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Form/ChoiceList/EntityLoaderInterface.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Form\ChoiceList; + +/** + * Custom loader for entities in the choice list. + * + * @author Benjamin Eberlei + */ +interface EntityLoaderInterface +{ + /** + * Returns an array of entities that are valid choices in the corresponding choice list. + * + * @return array The entities + */ + public function getEntities(); + + /** + * Returns an array of entities matching the given identifiers. + * + * @return array The entities + */ + public function getEntitiesByIds(string $identifier, array $values); +} diff --git a/vendor/symfony/doctrine-bridge/Form/ChoiceList/IdReader.php b/vendor/symfony/doctrine-bridge/Form/ChoiceList/IdReader.php new file mode 100644 index 0000000..195e7ce --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Form/ChoiceList/IdReader.php @@ -0,0 +1,121 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Form\ChoiceList; + +use Doctrine\Persistence\Mapping\ClassMetadata; +use Doctrine\Persistence\ObjectManager; +use Symfony\Component\Form\Exception\RuntimeException; + +/** + * A utility for reading object IDs. + * + * @author Bernhard Schussek + * + * @internal + */ +class IdReader +{ + private $om; + private $classMetadata; + private $singleId; + private $intId; + private $idField; + + /** + * @var IdReader|null + */ + private $associationIdReader; + + public function __construct(ObjectManager $om, ClassMetadata $classMetadata) + { + $ids = $classMetadata->getIdentifierFieldNames(); + $idType = $classMetadata->getTypeOfField(current($ids)); + + $this->om = $om; + $this->classMetadata = $classMetadata; + $this->singleId = 1 === \count($ids); + $this->intId = $this->singleId && \in_array($idType, ['integer', 'smallint', 'bigint']); + $this->idField = current($ids); + + // single field association are resolved, since the schema column could be an int + if ($this->singleId && $classMetadata->hasAssociation($this->idField)) { + $this->associationIdReader = new self($om, $om->getClassMetadata( + $classMetadata->getAssociationTargetClass($this->idField) + )); + + $this->singleId = $this->associationIdReader->isSingleId(); + $this->intId = $this->associationIdReader->isIntId(); + } + } + + /** + * Returns whether the class has a single-column ID. + * + * @return bool returns `true` if the class has a single-column ID and + * `false` otherwise + */ + public function isSingleId(): bool + { + return $this->singleId; + } + + /** + * Returns whether the class has a single-column integer ID. + * + * @return bool returns `true` if the class has a single-column integer ID + * and `false` otherwise + */ + public function isIntId(): bool + { + return $this->intId; + } + + /** + * Returns the ID value for an object. + * + * This method assumes that the object has a single-column ID. + * + * @return mixed The ID value + */ + public function getIdValue(object $object = null) + { + if (!$object) { + return null; + } + + if (!$this->om->contains($object)) { + throw new RuntimeException(sprintf('Entity of type "%s" passed to the choice field must be managed. Maybe you forget to persist it in the entity manager?', \get_class($object))); + } + + $this->om->initializeObject($object); + + $idValue = current($this->classMetadata->getIdentifierValues($object)); + + if ($this->associationIdReader) { + $idValue = $this->associationIdReader->getIdValue($idValue); + } + + return $idValue; + } + + /** + * Returns the name of the ID field. + * + * This method assumes that the object has a single-column ID. + * + * @return string The name of the ID field + */ + public function getIdField(): string + { + return $this->idField; + } +} diff --git a/vendor/symfony/doctrine-bridge/Form/ChoiceList/ORMQueryBuilderLoader.php b/vendor/symfony/doctrine-bridge/Form/ChoiceList/ORMQueryBuilderLoader.php new file mode 100644 index 0000000..e208c6b --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Form/ChoiceList/ORMQueryBuilderLoader.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Form\ChoiceList; + +use Doctrine\DBAL\Connection; +use Doctrine\ORM\QueryBuilder; + +/** + * Loads entities using a {@link QueryBuilder} instance. + * + * @author Benjamin Eberlei + * @author Bernhard Schussek + */ +class ORMQueryBuilderLoader implements EntityLoaderInterface +{ + /** + * Contains the query builder that builds the query for fetching the + * entities. + * + * This property should only be accessed through queryBuilder. + * + * @var QueryBuilder + */ + private $queryBuilder; + + public function __construct(QueryBuilder $queryBuilder) + { + $this->queryBuilder = $queryBuilder; + } + + /** + * {@inheritdoc} + */ + public function getEntities() + { + return $this->queryBuilder->getQuery()->execute(); + } + + /** + * {@inheritdoc} + */ + public function getEntitiesByIds(string $identifier, array $values) + { + if (null !== $this->queryBuilder->getMaxResults() || null !== $this->queryBuilder->getFirstResult()) { + // an offset or a limit would apply on results including the where clause with submitted id values + // that could make invalid choices valid + $choices = []; + $metadata = $this->queryBuilder->getEntityManager()->getClassMetadata(current($this->queryBuilder->getRootEntities())); + + foreach ($this->getEntities() as $entity) { + if (\in_array(current($metadata->getIdentifierValues($entity)), $values, true)) { + $choices[] = $entity; + } + } + + return $choices; + } + + $qb = clone $this->queryBuilder; + $alias = current($qb->getRootAliases()); + $parameter = 'ORMQueryBuilderLoader_getEntitiesByIds_'.$identifier; + $parameter = str_replace('.', '_', $parameter); + $where = $qb->expr()->in($alias.'.'.$identifier, ':'.$parameter); + + // Guess type + $entity = current($qb->getRootEntities()); + $metadata = $qb->getEntityManager()->getClassMetadata($entity); + if (\in_array($metadata->getTypeOfField($identifier), ['integer', 'bigint', 'smallint'])) { + $parameterType = Connection::PARAM_INT_ARRAY; + + // Filter out non-integer values (e.g. ""). If we don't, some + // databases such as PostgreSQL fail. + $values = array_values(array_filter($values, function ($v) { + return (string) $v === (string) (int) $v || ctype_digit($v); + })); + } elseif (\in_array($metadata->getTypeOfField($identifier), ['uuid', 'guid'])) { + $parameterType = Connection::PARAM_STR_ARRAY; + + // Like above, but we just filter out empty strings. + $values = array_values(array_filter($values, function ($v) { + return '' !== (string) $v; + })); + } else { + $parameterType = Connection::PARAM_STR_ARRAY; + } + if (!$values) { + return []; + } + + return $qb->andWhere($where) + ->getQuery() + ->setParameter($parameter, $values, $parameterType) + ->getResult(); + } +} diff --git a/vendor/symfony/doctrine-bridge/Form/DataTransformer/CollectionToArrayTransformer.php b/vendor/symfony/doctrine-bridge/Form/DataTransformer/CollectionToArrayTransformer.php new file mode 100644 index 0000000..3202dae --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Form/DataTransformer/CollectionToArrayTransformer.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Form\DataTransformer; + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; +use Symfony\Component\Form\DataTransformerInterface; +use Symfony\Component\Form\Exception\TransformationFailedException; + +/** + * @author Bernhard Schussek + */ +class CollectionToArrayTransformer implements DataTransformerInterface +{ + /** + * Transforms a collection into an array. + * + * @return mixed An array of entities + * + * @throws TransformationFailedException + */ + public function transform($collection) + { + if (null === $collection) { + return []; + } + + // For cases when the collection getter returns $collection->toArray() + // in order to prevent modifications of the returned collection + if (\is_array($collection)) { + return $collection; + } + + if (!$collection instanceof Collection) { + throw new TransformationFailedException('Expected a Doctrine\Common\Collections\Collection object.'); + } + + return $collection->toArray(); + } + + /** + * Transforms choice keys into entities. + * + * @param mixed $array An array of entities + * + * @return Collection A collection of entities + */ + public function reverseTransform($array) + { + if ('' === $array || null === $array) { + $array = []; + } else { + $array = (array) $array; + } + + return new ArrayCollection($array); + } +} diff --git a/vendor/symfony/doctrine-bridge/Form/DoctrineOrmExtension.php b/vendor/symfony/doctrine-bridge/Form/DoctrineOrmExtension.php new file mode 100644 index 0000000..c2897c6 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Form/DoctrineOrmExtension.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Form; + +use Doctrine\Persistence\ManagerRegistry; +use Symfony\Bridge\Doctrine\Form\Type\EntityType; +use Symfony\Component\Form\AbstractExtension; + +class DoctrineOrmExtension extends AbstractExtension +{ + protected $registry; + + public function __construct(ManagerRegistry $registry) + { + $this->registry = $registry; + } + + protected function loadTypes() + { + return [ + new EntityType($this->registry), + ]; + } + + protected function loadTypeGuesser() + { + return new DoctrineOrmTypeGuesser($this->registry); + } +} diff --git a/vendor/symfony/doctrine-bridge/Form/DoctrineOrmTypeGuesser.php b/vendor/symfony/doctrine-bridge/Form/DoctrineOrmTypeGuesser.php new file mode 100644 index 0000000..4374ec3 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Form/DoctrineOrmTypeGuesser.php @@ -0,0 +1,201 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Form; + +use Doctrine\DBAL\Types\Type; +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Doctrine\ORM\Mapping\MappingException as LegacyMappingException; +use Doctrine\Persistence\ManagerRegistry; +use Doctrine\Persistence\Mapping\MappingException; +use Doctrine\Persistence\Proxy; +use Symfony\Component\Form\FormTypeGuesserInterface; +use Symfony\Component\Form\Guess\Guess; +use Symfony\Component\Form\Guess\TypeGuess; +use Symfony\Component\Form\Guess\ValueGuess; + +class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface +{ + protected $registry; + + private $cache = []; + + public function __construct(ManagerRegistry $registry) + { + $this->registry = $registry; + } + + /** + * {@inheritdoc} + */ + public function guessType(string $class, string $property) + { + if (!$ret = $this->getMetadata($class)) { + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE); + } + + list($metadata, $name) = $ret; + + if ($metadata->hasAssociation($property)) { + $multiple = $metadata->isCollectionValuedAssociation($property); + $mapping = $metadata->getAssociationMapping($property); + + return new TypeGuess('Symfony\Bridge\Doctrine\Form\Type\EntityType', ['em' => $name, 'class' => $mapping['targetEntity'], 'multiple' => $multiple], Guess::HIGH_CONFIDENCE); + } + + switch ($metadata->getTypeOfField($property)) { + case Type::TARRAY: + case Type::SIMPLE_ARRAY: + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CollectionType', [], Guess::MEDIUM_CONFIDENCE); + case Type::BOOLEAN: + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CheckboxType', [], Guess::HIGH_CONFIDENCE); + case Type::DATETIME: + case Type::DATETIMETZ: + case 'vardatetime': + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateTimeType', [], Guess::HIGH_CONFIDENCE); + case 'datetime_immutable': + case 'datetimetz_immutable': + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateTimeType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE); + case 'dateinterval': + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateIntervalType', [], Guess::HIGH_CONFIDENCE); + case Type::DATE: + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', [], Guess::HIGH_CONFIDENCE); + case 'date_immutable': + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE); + case Type::TIME: + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', [], Guess::HIGH_CONFIDENCE); + case 'time_immutable': + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE); + case Type::DECIMAL: + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', ['input' => 'string'], Guess::MEDIUM_CONFIDENCE); + case Type::FLOAT: + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', [], Guess::MEDIUM_CONFIDENCE); + case Type::INTEGER: + case Type::BIGINT: + case Type::SMALLINT: + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\IntegerType', [], Guess::MEDIUM_CONFIDENCE); + case Type::STRING: + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::MEDIUM_CONFIDENCE); + case Type::TEXT: + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextareaType', [], Guess::MEDIUM_CONFIDENCE); + default: + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE); + } + } + + /** + * {@inheritdoc} + */ + public function guessRequired(string $class, string $property) + { + $classMetadatas = $this->getMetadata($class); + + if (!$classMetadatas) { + return null; + } + + /** @var ClassMetadataInfo $classMetadata */ + $classMetadata = $classMetadatas[0]; + + // Check whether the field exists and is nullable or not + if (isset($classMetadata->fieldMappings[$property])) { + if (!$classMetadata->isNullable($property) && Type::BOOLEAN !== $classMetadata->getTypeOfField($property)) { + return new ValueGuess(true, Guess::HIGH_CONFIDENCE); + } + + return new ValueGuess(false, Guess::MEDIUM_CONFIDENCE); + } + + // Check whether the association exists, is a to-one association and its + // join column is nullable or not + if ($classMetadata->isAssociationWithSingleJoinColumn($property)) { + $mapping = $classMetadata->getAssociationMapping($property); + + if (!isset($mapping['joinColumns'][0]['nullable'])) { + // The "nullable" option defaults to true, in that case the + // field should not be required. + return new ValueGuess(false, Guess::HIGH_CONFIDENCE); + } + + return new ValueGuess(!$mapping['joinColumns'][0]['nullable'], Guess::HIGH_CONFIDENCE); + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function guessMaxLength(string $class, string $property) + { + $ret = $this->getMetadata($class); + if ($ret && isset($ret[0]->fieldMappings[$property]) && !$ret[0]->hasAssociation($property)) { + $mapping = $ret[0]->getFieldMapping($property); + + if (isset($mapping['length'])) { + return new ValueGuess($mapping['length'], Guess::HIGH_CONFIDENCE); + } + + if (\in_array($ret[0]->getTypeOfField($property), [Type::DECIMAL, Type::FLOAT])) { + return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); + } + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function guessPattern(string $class, string $property) + { + $ret = $this->getMetadata($class); + if ($ret && isset($ret[0]->fieldMappings[$property]) && !$ret[0]->hasAssociation($property)) { + if (\in_array($ret[0]->getTypeOfField($property), [Type::DECIMAL, Type::FLOAT])) { + return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); + } + } + + return null; + } + + protected function getMetadata(string $class) + { + // normalize class name + $class = self::getRealClass(ltrim($class, '\\')); + + if (\array_key_exists($class, $this->cache)) { + return $this->cache[$class]; + } + + $this->cache[$class] = null; + foreach ($this->registry->getManagers() as $name => $em) { + try { + return $this->cache[$class] = [$em->getClassMetadata($class), $name]; + } catch (MappingException $e) { + // not an entity or mapped super class + } catch (LegacyMappingException $e) { + // not an entity or mapped super class, using Doctrine ORM 2.2 + } + } + + return null; + } + + private static function getRealClass(string $class): string + { + if (false === $pos = strrpos($class, '\\'.Proxy::MARKER.'\\')) { + return $class; + } + + return substr($class, $pos + Proxy::MARKER_LENGTH + 2); + } +} diff --git a/vendor/symfony/doctrine-bridge/Form/EventListener/MergeDoctrineCollectionListener.php b/vendor/symfony/doctrine-bridge/Form/EventListener/MergeDoctrineCollectionListener.php new file mode 100644 index 0000000..1ec496b --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Form/EventListener/MergeDoctrineCollectionListener.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Form\EventListener; + +use Doctrine\Common\Collections\Collection; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\FormEvents; + +/** + * Merge changes from the request to a Doctrine\Common\Collections\Collection instance. + * + * This works with ORM, MongoDB and CouchDB instances of the collection interface. + * + * @author Bernhard Schussek + * + * @see Collection + */ +class MergeDoctrineCollectionListener implements EventSubscriberInterface +{ + public static function getSubscribedEvents() + { + // Higher priority than core MergeCollectionListener so that this one + // is called before + return [ + FormEvents::SUBMIT => [ + ['onSubmit', 5], + ], + ]; + } + + public function onSubmit(FormEvent $event) + { + $collection = $event->getForm()->getData(); + $data = $event->getData(); + + // If all items were removed, call clear which has a higher + // performance on persistent collections + if ($collection instanceof Collection && 0 === \count($data)) { + $collection->clear(); + } + } +} diff --git a/vendor/symfony/doctrine-bridge/Form/Type/DoctrineType.php b/vendor/symfony/doctrine-bridge/Form/Type/DoctrineType.php new file mode 100644 index 0000000..d7de810 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Form/Type/DoctrineType.php @@ -0,0 +1,279 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Form\Type; + +use Doctrine\Common\Collections\Collection; +use Doctrine\Persistence\ManagerRegistry; +use Doctrine\Persistence\ObjectManager; +use Symfony\Bridge\Doctrine\Form\ChoiceList\DoctrineChoiceLoader; +use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityLoaderInterface; +use Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader; +use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionToArrayTransformer; +use Symfony\Bridge\Doctrine\Form\EventListener\MergeDoctrineCollectionListener; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator; +use Symfony\Component\Form\Exception\RuntimeException; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\Options; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Contracts\Service\ResetInterface; + +abstract class DoctrineType extends AbstractType implements ResetInterface +{ + /** + * @var ManagerRegistry + */ + protected $registry; + + /** + * @var IdReader[] + */ + private $idReaders = []; + + /** + * @var DoctrineChoiceLoader[] + */ + private $choiceLoaders = []; + + /** + * Creates the label for a choice. + * + * For backwards compatibility, objects are cast to strings by default. + * + * @internal This method is public to be usable as callback. It should not + * be used in user code. + */ + public static function createChoiceLabel(object $choice): string + { + return (string) $choice; + } + + /** + * Creates the field name for a choice. + * + * This method is used to generate field names if the underlying object has + * a single-column integer ID. In that case, the value of the field is + * the ID of the object. That ID is also used as field name. + * + * @param int|string $key The choice key + * @param string $value The choice value. Corresponds to the object's + * ID here. + * + * @internal This method is public to be usable as callback. It should not + * be used in user code. + */ + public static function createChoiceName(object $choice, $key, string $value): string + { + return str_replace('-', '_', (string) $value); + } + + /** + * Gets important parts from QueryBuilder that will allow to cache its results. + * For instance in ORM two query builders with an equal SQL string and + * equal parameters are considered to be equal. + * + * @param object $queryBuilder A query builder, type declaration is not present here as there + * is no common base class for the different implementations + * + * @return array|null Array with important QueryBuilder parts or null if + * they can't be determined + * + * @internal This method is public to be usable as callback. It should not + * be used in user code. + */ + public function getQueryBuilderPartsForCachingHash($queryBuilder): ?array + { + return null; + } + + public function __construct(ManagerRegistry $registry) + { + $this->registry = $registry; + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + if ($options['multiple'] && interface_exists(Collection::class)) { + $builder + ->addEventSubscriber(new MergeDoctrineCollectionListener()) + ->addViewTransformer(new CollectionToArrayTransformer(), true) + ; + } + } + + public function configureOptions(OptionsResolver $resolver) + { + $choiceLoader = function (Options $options) { + // Unless the choices are given explicitly, load them on demand + if (null === $options['choices']) { + $hash = null; + $qbParts = null; + + // If there is no QueryBuilder we can safely cache DoctrineChoiceLoader, + // also if concrete Type can return important QueryBuilder parts to generate + // hash key we go for it as well + if (!$options['query_builder'] || null !== $qbParts = $this->getQueryBuilderPartsForCachingHash($options['query_builder'])) { + $hash = CachingFactoryDecorator::generateHash([ + $options['em'], + $options['class'], + $qbParts, + ]); + + if (isset($this->choiceLoaders[$hash])) { + return $this->choiceLoaders[$hash]; + } + } + + if (null !== $options['query_builder']) { + $entityLoader = $this->getLoader($options['em'], $options['query_builder'], $options['class']); + } else { + $queryBuilder = $options['em']->getRepository($options['class'])->createQueryBuilder('e'); + $entityLoader = $this->getLoader($options['em'], $queryBuilder, $options['class']); + } + + $doctrineChoiceLoader = new DoctrineChoiceLoader( + $options['em'], + $options['class'], + $options['id_reader'], + $entityLoader + ); + + if (null !== $hash) { + $this->choiceLoaders[$hash] = $doctrineChoiceLoader; + } + + return $doctrineChoiceLoader; + } + + return null; + }; + + $choiceName = function (Options $options) { + // If the object has a single-column, numeric ID, use that ID as + // field name. We can only use numeric IDs as names, as we cannot + // guarantee that a non-numeric ID contains a valid form name + if ($options['id_reader'] instanceof IdReader && $options['id_reader']->isIntId()) { + return [__CLASS__, 'createChoiceName']; + } + + // Otherwise, an incrementing integer is used as name automatically + return null; + }; + + // The choices are always indexed by ID (see "choices" normalizer + // and DoctrineChoiceLoader), unless the ID is composite. Then they + // are indexed by an incrementing integer. + // Use the ID/incrementing integer as choice value. + $choiceValue = function (Options $options) { + // If the entity has a single-column ID, use that ID as value + if ($options['id_reader'] instanceof IdReader && $options['id_reader']->isSingleId()) { + return [$options['id_reader'], 'getIdValue']; + } + + // Otherwise, an incrementing integer is used as value automatically + return null; + }; + + $emNormalizer = function (Options $options, $em) { + if (null !== $em) { + if ($em instanceof ObjectManager) { + return $em; + } + + return $this->registry->getManager($em); + } + + $em = $this->registry->getManagerForClass($options['class']); + + if (null === $em) { + throw new RuntimeException(sprintf('Class "%s" seems not to be a managed Doctrine entity. Did you forget to map it?', $options['class'])); + } + + return $em; + }; + + // Invoke the query builder closure so that we can cache choice lists + // for equal query builders + $queryBuilderNormalizer = function (Options $options, $queryBuilder) { + if (\is_callable($queryBuilder)) { + $queryBuilder = $queryBuilder($options['em']->getRepository($options['class'])); + } + + return $queryBuilder; + }; + + // Set the "id_reader" option via the normalizer. This option is not + // supposed to be set by the user. + $idReaderNormalizer = function (Options $options) { + $hash = CachingFactoryDecorator::generateHash([ + $options['em'], + $options['class'], + ]); + + // The ID reader is a utility that is needed to read the object IDs + // when generating the field values. The callback generating the + // field values has no access to the object manager or the class + // of the field, so we store that information in the reader. + // The reader is cached so that two choice lists for the same class + // (and hence with the same reader) can successfully be cached. + if (!isset($this->idReaders[$hash])) { + $classMetadata = $options['em']->getClassMetadata($options['class']); + $this->idReaders[$hash] = new IdReader($options['em'], $classMetadata); + } + + if ($this->idReaders[$hash]->isSingleId()) { + return $this->idReaders[$hash]; + } + + return null; + }; + + $resolver->setDefaults([ + 'em' => null, + 'query_builder' => null, + 'choices' => null, + 'choice_loader' => $choiceLoader, + 'choice_label' => [__CLASS__, 'createChoiceLabel'], + 'choice_name' => $choiceName, + 'choice_value' => $choiceValue, + 'id_reader' => null, // internal + 'choice_translation_domain' => false, + ]); + + $resolver->setRequired(['class']); + + $resolver->setNormalizer('em', $emNormalizer); + $resolver->setNormalizer('query_builder', $queryBuilderNormalizer); + $resolver->setNormalizer('id_reader', $idReaderNormalizer); + + $resolver->setAllowedTypes('em', ['null', 'string', ObjectManager::class]); + } + + /** + * Return the default loader object. + * + * @param mixed $queryBuilder + * + * @return EntityLoaderInterface + */ + abstract public function getLoader(ObjectManager $manager, $queryBuilder, string $class); + + public function getParent() + { + return 'Symfony\Component\Form\Extension\Core\Type\ChoiceType'; + } + + public function reset() + { + $this->choiceLoaders = []; + } +} diff --git a/vendor/symfony/doctrine-bridge/Form/Type/EntityType.php b/vendor/symfony/doctrine-bridge/Form/Type/EntityType.php new file mode 100644 index 0000000..e4dafdd --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Form/Type/EntityType.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Form\Type; + +use Doctrine\ORM\Query\Parameter; +use Doctrine\ORM\QueryBuilder; +use Doctrine\Persistence\ObjectManager; +use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader; +use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\OptionsResolver\Options; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class EntityType extends DoctrineType +{ + public function configureOptions(OptionsResolver $resolver) + { + parent::configureOptions($resolver); + + // Invoke the query builder closure so that we can cache choice lists + // for equal query builders + $queryBuilderNormalizer = function (Options $options, $queryBuilder) { + if (\is_callable($queryBuilder)) { + $queryBuilder = $queryBuilder($options['em']->getRepository($options['class'])); + + if (null !== $queryBuilder && !$queryBuilder instanceof QueryBuilder) { + throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder'); + } + } + + return $queryBuilder; + }; + + $resolver->setNormalizer('query_builder', $queryBuilderNormalizer); + $resolver->setAllowedTypes('query_builder', ['null', 'callable', 'Doctrine\ORM\QueryBuilder']); + } + + /** + * Return the default loader object. + * + * @param QueryBuilder $queryBuilder + * + * @return ORMQueryBuilderLoader + */ + public function getLoader(ObjectManager $manager, $queryBuilder, string $class) + { + if (!$queryBuilder instanceof QueryBuilder) { + throw new \TypeError(sprintf('Expected an instance of %s, but got %s.', QueryBuilder::class, \is_object($queryBuilder) ? \get_class($queryBuilder) : \gettype($queryBuilder))); + } + + return new ORMQueryBuilderLoader($queryBuilder); + } + + /** + * {@inheritdoc} + */ + public function getBlockPrefix() + { + return 'entity'; + } + + /** + * We consider two query builders with an equal SQL string and + * equal parameters to be equal. + * + * @param QueryBuilder $queryBuilder + * + * @internal This method is public to be usable as callback. It should not + * be used in user code. + */ + public function getQueryBuilderPartsForCachingHash($queryBuilder): ?array + { + if (!$queryBuilder instanceof QueryBuilder) { + throw new \TypeError(sprintf('Expected an instance of %s, but got %s.', QueryBuilder::class, \is_object($queryBuilder) ? \get_class($queryBuilder) : \gettype($queryBuilder))); + } + + return [ + $queryBuilder->getQuery()->getSQL(), + array_map([$this, 'parameterToArray'], $queryBuilder->getParameters()->toArray()), + ]; + } + + /** + * Converts a query parameter to an array. + */ + private function parameterToArray(Parameter $parameter): array + { + return [$parameter->getName(), $parameter->getType(), $parameter->getValue()]; + } +} diff --git a/vendor/symfony/doctrine-bridge/LICENSE b/vendor/symfony/doctrine-bridge/LICENSE new file mode 100644 index 0000000..a677f43 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/doctrine-bridge/Logger/DbalLogger.php b/vendor/symfony/doctrine-bridge/Logger/DbalLogger.php new file mode 100644 index 0000000..6343792 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Logger/DbalLogger.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Logger; + +use Doctrine\DBAL\Logging\SQLLogger; +use Psr\Log\LoggerInterface; +use Symfony\Component\Stopwatch\Stopwatch; + +/** + * @author Fabien Potencier + */ +class DbalLogger implements SQLLogger +{ + const MAX_STRING_LENGTH = 32; + const BINARY_DATA_VALUE = '(binary value)'; + + protected $logger; + protected $stopwatch; + + public function __construct(LoggerInterface $logger = null, Stopwatch $stopwatch = null) + { + $this->logger = $logger; + $this->stopwatch = $stopwatch; + } + + /** + * {@inheritdoc} + * + * @return void + */ + public function startQuery($sql, array $params = null, array $types = null) + { + if (null !== $this->stopwatch) { + $this->stopwatch->start('doctrine', 'doctrine'); + } + + if (null !== $this->logger) { + $this->log($sql, null === $params ? [] : $this->normalizeParams($params)); + } + } + + /** + * {@inheritdoc} + * + * @return void + */ + public function stopQuery() + { + if (null !== $this->stopwatch) { + $this->stopwatch->stop('doctrine'); + } + } + + /** + * Logs a message. + */ + protected function log(string $message, array $params) + { + $this->logger->debug($message, $params); + } + + private function normalizeParams(array $params): array + { + foreach ($params as $index => $param) { + // normalize recursively + if (\is_array($param)) { + $params[$index] = $this->normalizeParams($param); + continue; + } + + if (!\is_string($params[$index])) { + continue; + } + + // non utf-8 strings break json encoding + if (!preg_match('//u', $params[$index])) { + $params[$index] = self::BINARY_DATA_VALUE; + continue; + } + + // detect if the too long string must be shorten + if (self::MAX_STRING_LENGTH < mb_strlen($params[$index], 'UTF-8')) { + $params[$index] = mb_substr($params[$index], 0, self::MAX_STRING_LENGTH - 6, 'UTF-8').' [...]'; + continue; + } + } + + return $params; + } +} diff --git a/vendor/symfony/doctrine-bridge/ManagerRegistry.php b/vendor/symfony/doctrine-bridge/ManagerRegistry.php new file mode 100644 index 0000000..ab76c4c --- /dev/null +++ b/vendor/symfony/doctrine-bridge/ManagerRegistry.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine; + +use Doctrine\Persistence\AbstractManagerRegistry; +use ProxyManager\Proxy\LazyLoadingInterface; +use Symfony\Component\DependencyInjection\Container; + +/** + * References Doctrine connections and entity/document managers. + * + * @author Lukas Kahwe Smith + */ +abstract class ManagerRegistry extends AbstractManagerRegistry +{ + /** + * @var Container + */ + protected $container; + + /** + * {@inheritdoc} + * + * @return object + */ + protected function getService($name) + { + return $this->container->get($name); + } + + /** + * {@inheritdoc} + * + * @return void + */ + protected function resetService($name) + { + if (!$this->container->initialized($name)) { + return; + } + $manager = $this->container->get($name); + + if (!$manager instanceof LazyLoadingInterface) { + throw new \LogicException('Resetting a non-lazy manager service is not supported. '.(interface_exists(LazyLoadingInterface::class) ? sprintf('Declare the "%s" service as lazy.', $name) : 'Try running "composer require symfony/proxy-manager-bridge".')); + } + $manager->setProxyInitializer(\Closure::bind( + function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { + if (isset($this->aliases[$name])) { + $name = $this->aliases[$name]; + } + if (isset($this->fileMap[$name])) { + $wrappedInstance = $this->load($this->fileMap[$name]); + } else { + $wrappedInstance = $this->{$this->methodMap[$name]}(false); + } + + $manager->setProxyInitializer(null); + + return true; + }, + $this->container, + Container::class + )); + } +} diff --git a/vendor/symfony/doctrine-bridge/Messenger/AbstractDoctrineMiddleware.php b/vendor/symfony/doctrine-bridge/Messenger/AbstractDoctrineMiddleware.php new file mode 100644 index 0000000..9fbf2de --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Messenger/AbstractDoctrineMiddleware.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Messenger; + +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\Persistence\ManagerRegistry; +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException; +use Symfony\Component\Messenger\Middleware\MiddlewareInterface; +use Symfony\Component\Messenger\Middleware\StackInterface; + +/** + * @author Konstantin Myakshin + * + * @internal + */ +abstract class AbstractDoctrineMiddleware implements MiddlewareInterface +{ + protected $managerRegistry; + protected $entityManagerName; + + public function __construct(ManagerRegistry $managerRegistry, string $entityManagerName = null) + { + $this->managerRegistry = $managerRegistry; + $this->entityManagerName = $entityManagerName; + } + + final public function handle(Envelope $envelope, StackInterface $stack): Envelope + { + try { + $entityManager = $this->managerRegistry->getManager($this->entityManagerName); + } catch (\InvalidArgumentException $e) { + throw new UnrecoverableMessageHandlingException($e->getMessage(), 0, $e); + } + + return $this->handleForManager($entityManager, $envelope, $stack); + } + + abstract protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope; +} diff --git a/vendor/symfony/doctrine-bridge/Messenger/DoctrineClearEntityManagerWorkerSubscriber.php b/vendor/symfony/doctrine-bridge/Messenger/DoctrineClearEntityManagerWorkerSubscriber.php new file mode 100644 index 0000000..d702186 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Messenger/DoctrineClearEntityManagerWorkerSubscriber.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Messenger; + +use Doctrine\Persistence\ManagerRegistry; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent; +use Symfony\Component\Messenger\Event\WorkerMessageHandledEvent; + +/** + * Clears entity managers between messages being handled to avoid outdated data. + * + * @author Ryan Weaver + */ +class DoctrineClearEntityManagerWorkerSubscriber implements EventSubscriberInterface +{ + private $managerRegistry; + + public function __construct(ManagerRegistry $managerRegistry) + { + $this->managerRegistry = $managerRegistry; + } + + public function onWorkerMessageHandled() + { + $this->clearEntityManagers(); + } + + public function onWorkerMessageFailed() + { + $this->clearEntityManagers(); + } + + public static function getSubscribedEvents() + { + yield WorkerMessageHandledEvent::class => 'onWorkerMessageHandled'; + yield WorkerMessageFailedEvent::class => 'onWorkerMessageFailed'; + } + + private function clearEntityManagers() + { + foreach ($this->managerRegistry->getManagers() as $manager) { + $manager->clear(); + } + } +} diff --git a/vendor/symfony/doctrine-bridge/Messenger/DoctrineCloseConnectionMiddleware.php b/vendor/symfony/doctrine-bridge/Messenger/DoctrineCloseConnectionMiddleware.php new file mode 100644 index 0000000..b0a96e0 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Messenger/DoctrineCloseConnectionMiddleware.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Messenger; + +use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\Middleware\StackInterface; +use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp; + +/** + * Closes connection and therefore saves number of connections. + * + * @author Fuong + */ +class DoctrineCloseConnectionMiddleware extends AbstractDoctrineMiddleware +{ + protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope + { + try { + $connection = $entityManager->getConnection(); + + return $stack->next()->handle($envelope, $stack); + } finally { + if (null !== $envelope->last(ConsumedByWorkerStamp::class)) { + $connection->close(); + } + } + } +} diff --git a/vendor/symfony/doctrine-bridge/Messenger/DoctrinePingConnectionMiddleware.php b/vendor/symfony/doctrine-bridge/Messenger/DoctrinePingConnectionMiddleware.php new file mode 100644 index 0000000..f6febb2 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Messenger/DoctrinePingConnectionMiddleware.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Messenger; + +use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\Middleware\StackInterface; +use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp; + +/** + * Checks whether the connection is still open or reconnects otherwise. + * + * @author Fuong + */ +class DoctrinePingConnectionMiddleware extends AbstractDoctrineMiddleware +{ + protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope + { + if (null !== $envelope->last(ConsumedByWorkerStamp::class)) { + $this->pingConnection($entityManager); + } + + return $stack->next()->handle($envelope, $stack); + } + + private function pingConnection(EntityManagerInterface $entityManager) + { + $connection = $entityManager->getConnection(); + + if (!$connection->ping()) { + $connection->close(); + $connection->connect(); + } + + if (!$entityManager->isOpen()) { + $this->managerRegistry->resetManager($this->entityManagerName); + } + } +} diff --git a/vendor/symfony/doctrine-bridge/Messenger/DoctrineTransactionMiddleware.php b/vendor/symfony/doctrine-bridge/Messenger/DoctrineTransactionMiddleware.php new file mode 100644 index 0000000..4eb7afc --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Messenger/DoctrineTransactionMiddleware.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Messenger; + +use Doctrine\ORM\EntityManagerInterface; +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\Exception\HandlerFailedException; +use Symfony\Component\Messenger\Middleware\StackInterface; +use Symfony\Component\Messenger\Stamp\HandledStamp; + +/** + * Wraps all handlers in a single doctrine transaction. + * + * @author Tobias Nyholm + */ +class DoctrineTransactionMiddleware extends AbstractDoctrineMiddleware +{ + protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope + { + $entityManager->getConnection()->beginTransaction(); + try { + $envelope = $stack->next()->handle($envelope, $stack); + $entityManager->flush(); + $entityManager->getConnection()->commit(); + + return $envelope; + } catch (\Throwable $exception) { + $entityManager->getConnection()->rollBack(); + + if ($exception instanceof HandlerFailedException) { + // Remove all HandledStamp from the envelope so the retry will execute all handlers again. + // When a handler fails, the queries of allegedly successful previous handlers just got rolled back. + throw new HandlerFailedException($exception->getEnvelope()->withoutAll(HandledStamp::class), $exception->getNestedExceptions()); + } + + throw $exception; + } + } +} diff --git a/vendor/symfony/doctrine-bridge/PropertyInfo/DoctrineExtractor.php b/vendor/symfony/doctrine-bridge/PropertyInfo/DoctrineExtractor.php new file mode 100644 index 0000000..bc81982 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/PropertyInfo/DoctrineExtractor.php @@ -0,0 +1,255 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\PropertyInfo; + +use Doctrine\DBAL\Types\Type as DBALType; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Doctrine\ORM\Mapping\MappingException as OrmMappingException; +use Doctrine\Persistence\Mapping\MappingException; +use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; +use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; +use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; +use Symfony\Component\PropertyInfo\Type; + +/** + * Extracts data using Doctrine ORM and ODM metadata. + * + * @author Kévin Dunglas + */ +class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeExtractorInterface, PropertyAccessExtractorInterface +{ + private $entityManager; + private $classMetadataFactory; + + public function __construct(EntityManagerInterface $entityManager) + { + $this->entityManager = $entityManager; + } + + /** + * {@inheritdoc} + */ + public function getProperties(string $class, array $context = []) + { + if (null === $metadata = $this->getMetadata($class)) { + return null; + } + + $properties = array_merge($metadata->getFieldNames(), $metadata->getAssociationNames()); + + if ($metadata instanceof ClassMetadataInfo && class_exists('Doctrine\ORM\Mapping\Embedded') && $metadata->embeddedClasses) { + $properties = array_filter($properties, function ($property) { + return false === strpos($property, '.'); + }); + + $properties = array_merge($properties, array_keys($metadata->embeddedClasses)); + } + + return $properties; + } + + /** + * {@inheritdoc} + */ + public function getTypes(string $class, string $property, array $context = []) + { + if (null === $metadata = $this->getMetadata($class)) { + return null; + } + + if ($metadata->hasAssociation($property)) { + $class = $metadata->getAssociationTargetClass($property); + + if ($metadata->isSingleValuedAssociation($property)) { + if ($metadata instanceof ClassMetadataInfo) { + $associationMapping = $metadata->getAssociationMapping($property); + + $nullable = $this->isAssociationNullable($associationMapping); + } else { + $nullable = false; + } + + return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $class)]; + } + + $collectionKeyType = Type::BUILTIN_TYPE_INT; + + if ($metadata instanceof ClassMetadataInfo) { + $associationMapping = $metadata->getAssociationMapping($property); + + if (isset($associationMapping['indexBy'])) { + $indexProperty = $associationMapping['indexBy']; + /** @var ClassMetadataInfo $subMetadata */ + $subMetadata = $this->entityManager ? $this->entityManager->getClassMetadata($associationMapping['targetEntity']) : $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']); + $typeOfField = $subMetadata->getTypeOfField($indexProperty); + + if (null === $typeOfField) { + $associationMapping = $subMetadata->getAssociationMapping($indexProperty); + + /** @var ClassMetadataInfo $subMetadata */ + $indexProperty = $subMetadata->getSingleAssociationReferencedJoinColumnName($indexProperty); + $subMetadata = $this->entityManager ? $this->entityManager->getClassMetadata($associationMapping['targetEntity']) : $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']); + $typeOfField = $subMetadata->getTypeOfField($indexProperty); + } + + $collectionKeyType = $this->getPhpType($typeOfField); + } + } + + return [new Type( + Type::BUILTIN_TYPE_OBJECT, + false, + 'Doctrine\Common\Collections\Collection', + true, + new Type($collectionKeyType), + new Type(Type::BUILTIN_TYPE_OBJECT, false, $class) + )]; + } + + if ($metadata instanceof ClassMetadataInfo && class_exists('Doctrine\ORM\Mapping\Embedded') && isset($metadata->embeddedClasses[$property])) { + return [new Type(Type::BUILTIN_TYPE_OBJECT, false, $metadata->embeddedClasses[$property]['class'])]; + } + + if ($metadata->hasField($property)) { + $typeOfField = $metadata->getTypeOfField($property); + $nullable = $metadata instanceof ClassMetadataInfo && $metadata->isNullable($property); + + switch ($typeOfField) { + case DBALType::DATE: + case DBALType::DATETIME: + case DBALType::DATETIMETZ: + case 'vardatetime': + case DBALType::TIME: + return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTime')]; + + case 'date_immutable': + case 'datetime_immutable': + case 'datetimetz_immutable': + case 'time_immutable': + return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTimeImmutable')]; + + case 'dateinterval': + return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateInterval')]; + + case DBALType::TARRAY: + return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)]; + + case DBALType::SIMPLE_ARRAY: + return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]; + + case DBALType::JSON_ARRAY: + return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)]; + + default: + $builtinType = $this->getPhpType($typeOfField); + + return $builtinType ? [new Type($builtinType, $nullable)] : null; + } + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function isReadable(string $class, string $property, array $context = []) + { + return null; + } + + /** + * {@inheritdoc} + */ + public function isWritable(string $class, string $property, array $context = []) + { + if ( + null === ($metadata = $this->getMetadata($class)) + || ClassMetadata::GENERATOR_TYPE_NONE === $metadata->generatorType + || !\in_array($property, $metadata->getIdentifierFieldNames(), true) + ) { + return null; + } + + return false; + } + + private function getMetadata(string $class): ?ClassMetadata + { + try { + return $this->entityManager ? $this->entityManager->getClassMetadata($class) : $this->classMetadataFactory->getMetadataFor($class); + } catch (MappingException | OrmMappingException $exception) { + return null; + } + } + + /** + * Determines whether an association is nullable. + * + * @see https://github.com/doctrine/doctrine2/blob/v2.5.4/lib/Doctrine/ORM/Tools/EntityGenerator.php#L1221-L1246 + */ + private function isAssociationNullable(array $associationMapping): bool + { + if (isset($associationMapping['id']) && $associationMapping['id']) { + return false; + } + + if (!isset($associationMapping['joinColumns'])) { + return true; + } + + $joinColumns = $associationMapping['joinColumns']; + foreach ($joinColumns as $joinColumn) { + if (isset($joinColumn['nullable']) && !$joinColumn['nullable']) { + return false; + } + } + + return true; + } + + /** + * Gets the corresponding built-in PHP type. + */ + private function getPhpType(string $doctrineType): ?string + { + switch ($doctrineType) { + case DBALType::SMALLINT: + case DBALType::INTEGER: + return Type::BUILTIN_TYPE_INT; + + case DBALType::FLOAT: + return Type::BUILTIN_TYPE_FLOAT; + + case DBALType::BIGINT: + case DBALType::STRING: + case DBALType::TEXT: + case DBALType::GUID: + case DBALType::DECIMAL: + return Type::BUILTIN_TYPE_STRING; + + case DBALType::BOOLEAN: + return Type::BUILTIN_TYPE_BOOL; + + case DBALType::BLOB: + case 'binary': + return Type::BUILTIN_TYPE_RESOURCE; + + case DBALType::OBJECT: + return Type::BUILTIN_TYPE_OBJECT; + } + + return null; + } +} diff --git a/vendor/symfony/doctrine-bridge/README.md b/vendor/symfony/doctrine-bridge/README.md new file mode 100644 index 0000000..46d897d --- /dev/null +++ b/vendor/symfony/doctrine-bridge/README.md @@ -0,0 +1,13 @@ +Doctrine Bridge +=============== + +Provides integration for [Doctrine](http://www.doctrine-project.org/) with +various Symfony components. + +Resources +--------- + + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/doctrine-bridge/Security/RememberMe/DoctrineTokenProvider.php b/vendor/symfony/doctrine-bridge/Security/RememberMe/DoctrineTokenProvider.php new file mode 100644 index 0000000..7a6c832 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Security/RememberMe/DoctrineTokenProvider.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Security\RememberMe; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Types\Type as DoctrineType; +use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken; +use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentTokenInterface; +use Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface; +use Symfony\Component\Security\Core\Exception\TokenNotFoundException; + +/** + * This class provides storage for the tokens that is set in "remember me" + * cookies. This way no password secrets will be stored in the cookies on + * the client machine, and thus the security is improved. + * + * This depends only on doctrine in order to get a database connection + * and to do the conversion of the datetime column. + * + * In order to use this class, you need the following table in your database: + * + * CREATE TABLE `rememberme_token` ( + * `series` char(88) UNIQUE PRIMARY KEY NOT NULL, + * `value` char(88) NOT NULL, + * `lastUsed` datetime NOT NULL, + * `class` varchar(100) NOT NULL, + * `username` varchar(200) NOT NULL + * ); + */ +class DoctrineTokenProvider implements TokenProviderInterface +{ + private $conn; + + public function __construct(Connection $conn) + { + $this->conn = $conn; + } + + /** + * {@inheritdoc} + */ + public function loadTokenBySeries(string $series) + { + // the alias for lastUsed works around case insensitivity in PostgreSQL + $sql = 'SELECT class, username, value, lastUsed AS last_used' + .' FROM rememberme_token WHERE series=:series'; + $paramValues = ['series' => $series]; + $paramTypes = ['series' => \PDO::PARAM_STR]; + $stmt = $this->conn->executeQuery($sql, $paramValues, $paramTypes); + $row = $stmt->fetch(\PDO::FETCH_ASSOC); + + if ($row) { + return new PersistentToken($row['class'], $row['username'], $series, $row['value'], new \DateTime($row['last_used'])); + } + + throw new TokenNotFoundException('No token found.'); + } + + /** + * {@inheritdoc} + */ + public function deleteTokenBySeries(string $series) + { + $sql = 'DELETE FROM rememberme_token WHERE series=:series'; + $paramValues = ['series' => $series]; + $paramTypes = ['series' => \PDO::PARAM_STR]; + $this->conn->executeUpdate($sql, $paramValues, $paramTypes); + } + + /** + * {@inheritdoc} + */ + public function updateToken(string $series, string $tokenValue, \DateTime $lastUsed) + { + $sql = 'UPDATE rememberme_token SET value=:value, lastUsed=:lastUsed' + .' WHERE series=:series'; + $paramValues = [ + 'value' => $tokenValue, + 'lastUsed' => $lastUsed, + 'series' => $series, + ]; + $paramTypes = [ + 'value' => \PDO::PARAM_STR, + 'lastUsed' => DoctrineType::DATETIME, + 'series' => \PDO::PARAM_STR, + ]; + $updated = $this->conn->executeUpdate($sql, $paramValues, $paramTypes); + if ($updated < 1) { + throw new TokenNotFoundException('No token found.'); + } + } + + /** + * {@inheritdoc} + */ + public function createNewToken(PersistentTokenInterface $token) + { + $sql = 'INSERT INTO rememberme_token' + .' (class, username, series, value, lastUsed)' + .' VALUES (:class, :username, :series, :value, :lastUsed)'; + $paramValues = [ + 'class' => $token->getClass(), + 'username' => $token->getUsername(), + 'series' => $token->getSeries(), + 'value' => $token->getTokenValue(), + 'lastUsed' => $token->getLastUsed(), + ]; + $paramTypes = [ + 'class' => \PDO::PARAM_STR, + 'username' => \PDO::PARAM_STR, + 'series' => \PDO::PARAM_STR, + 'value' => \PDO::PARAM_STR, + 'lastUsed' => DoctrineType::DATETIME, + ]; + $this->conn->executeUpdate($sql, $paramValues, $paramTypes); + } +} diff --git a/vendor/symfony/doctrine-bridge/Security/User/EntityUserProvider.php b/vendor/symfony/doctrine-bridge/Security/User/EntityUserProvider.php new file mode 100644 index 0000000..01b2d64 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Security/User/EntityUserProvider.php @@ -0,0 +1,155 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Security\User; + +use Doctrine\Persistence\ManagerRegistry; +use Doctrine\Persistence\Mapping\ClassMetadata; +use Doctrine\Persistence\ObjectManager; +use Doctrine\Persistence\ObjectRepository; +use Symfony\Component\Security\Core\Exception\UnsupportedUserException; +use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; +use Symfony\Component\Security\Core\User\PasswordUpgraderInterface; +use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\Security\Core\User\UserProviderInterface; + +/** + * Wrapper around a Doctrine ObjectManager. + * + * Provides provisioning for Doctrine entity users. + * + * @author Fabien Potencier + * @author Johannes M. Schmitt + */ +class EntityUserProvider implements UserProviderInterface, PasswordUpgraderInterface +{ + private $registry; + private $managerName; + private $classOrAlias; + private $class; + private $property; + + public function __construct(ManagerRegistry $registry, string $classOrAlias, string $property = null, string $managerName = null) + { + $this->registry = $registry; + $this->managerName = $managerName; + $this->classOrAlias = $classOrAlias; + $this->property = $property; + } + + /** + * {@inheritdoc} + */ + public function loadUserByUsername(string $username) + { + $repository = $this->getRepository(); + if (null !== $this->property) { + $user = $repository->findOneBy([$this->property => $username]); + } else { + if (!$repository instanceof UserLoaderInterface) { + throw new \InvalidArgumentException(sprintf('You must either make the "%s" entity Doctrine Repository ("%s") implement "Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface" or set the "property" option in the corresponding entity provider configuration.', $this->classOrAlias, \get_class($repository))); + } + + $user = $repository->loadUserByUsername($username); + } + + if (null === $user) { + throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username)); + } + + return $user; + } + + /** + * {@inheritdoc} + */ + public function refreshUser(UserInterface $user) + { + $class = $this->getClass(); + if (!$user instanceof $class) { + throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', \get_class($user))); + } + + $repository = $this->getRepository(); + if ($repository instanceof UserProviderInterface) { + $refreshedUser = $repository->refreshUser($user); + } else { + // The user must be reloaded via the primary key as all other data + // might have changed without proper persistence in the database. + // That's the case when the user has been changed by a form with + // validation errors. + if (!$id = $this->getClassMetadata()->getIdentifierValues($user)) { + throw new \InvalidArgumentException('You cannot refresh a user from the EntityUserProvider that does not contain an identifier. The user object has to be serialized with its own identifier mapped by Doctrine.'); + } + + $refreshedUser = $repository->find($id); + if (null === $refreshedUser) { + throw new UsernameNotFoundException(sprintf('User with id %s not found', json_encode($id))); + } + } + + return $refreshedUser; + } + + /** + * {@inheritdoc} + */ + public function supportsClass(string $class) + { + return $class === $this->getClass() || is_subclass_of($class, $this->getClass()); + } + + /** + * {@inheritdoc} + */ + public function upgradePassword(UserInterface $user, string $newEncodedPassword): void + { + $class = $this->getClass(); + if (!$user instanceof $class) { + throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', \get_class($user))); + } + + $repository = $this->getRepository(); + if ($repository instanceof PasswordUpgraderInterface) { + $repository->upgradePassword($user, $newEncodedPassword); + } + } + + private function getObjectManager(): ObjectManager + { + return $this->registry->getManager($this->managerName); + } + + private function getRepository(): ObjectRepository + { + return $this->getObjectManager()->getRepository($this->classOrAlias); + } + + private function getClass(): string + { + if (null === $this->class) { + $class = $this->classOrAlias; + + if (false !== strpos($class, ':')) { + $class = $this->getClassMetadata()->getName(); + } + + $this->class = $class; + } + + return $this->class; + } + + private function getClassMetadata(): ClassMetadata + { + return $this->getObjectManager()->getClassMetadata($this->classOrAlias); + } +} diff --git a/vendor/symfony/doctrine-bridge/Security/User/UserLoaderInterface.php b/vendor/symfony/doctrine-bridge/Security/User/UserLoaderInterface.php new file mode 100644 index 0000000..d996f71 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Security/User/UserLoaderInterface.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Security\User; + +use Symfony\Component\Security\Core\User\UserInterface; + +/** + * Represents a class that loads UserInterface objects from Doctrine source for the authentication system. + * + * This interface is meant to facilitate the loading of a User from Doctrine source using a custom method. + * If you want to implement your own logic of retrieving the user from Doctrine your repository should implement this + * interface. + * + * @see UserInterface + * + * @author Michal Trojanowski + */ +interface UserLoaderInterface +{ + /** + * Loads the user for the given username. + * + * This method must return null if the user is not found. + * + * @return UserInterface|null + */ + public function loadUserByUsername(string $username); +} diff --git a/vendor/symfony/doctrine-bridge/Test/DoctrineTestHelper.php b/vendor/symfony/doctrine-bridge/Test/DoctrineTestHelper.php new file mode 100644 index 0000000..2ad16dc --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Test/DoctrineTestHelper.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Test; + +use Doctrine\Common\Annotations\AnnotationReader; +use Doctrine\Common\Cache\ArrayCache; +use Doctrine\ORM\Configuration; +use Doctrine\ORM\EntityManager; +use Doctrine\ORM\Mapping\Driver\AnnotationDriver; +use Doctrine\ORM\Mapping\Driver\XmlDriver; +use Doctrine\Persistence\Mapping\Driver\MappingDriverChain; +use Doctrine\Persistence\Mapping\Driver\SymfonyFileLocator; +use PHPUnit\Framework\TestCase; + +/** + * Provides utility functions needed in tests. + * + * @author Bernhard Schussek + */ +class DoctrineTestHelper +{ + /** + * Returns an entity manager for testing. + * + * @return EntityManager + */ + public static function createTestEntityManager(Configuration $config = null) + { + if (!\extension_loaded('pdo_sqlite')) { + TestCase::markTestSkipped('Extension pdo_sqlite is required.'); + } + + if (null === $config) { + $config = self::createTestConfiguration(); + } + + $params = [ + 'driver' => 'pdo_sqlite', + 'memory' => true, + ]; + + return EntityManager::create($params, $config); + } + + /** + * @return Configuration + */ + public static function createTestConfiguration() + { + $config = new Configuration(); + $config->setEntityNamespaces(['SymfonyTestsDoctrine' => 'Symfony\Bridge\Doctrine\Tests\Fixtures']); + $config->setAutoGenerateProxyClasses(true); + $config->setProxyDir(sys_get_temp_dir()); + $config->setProxyNamespace('SymfonyTests\Doctrine'); + $config->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader())); + $config->setQueryCacheImpl(new ArrayCache()); + $config->setMetadataCacheImpl(new ArrayCache()); + + return $config; + } + + /** + * @return Configuration + */ + public static function createTestConfigurationWithXmlLoader() + { + $config = static::createTestConfiguration(); + + $driverChain = new MappingDriverChain(); + $driverChain->addDriver( + new XmlDriver( + new SymfonyFileLocator( + [__DIR__.'/../Tests/Resources/orm' => 'Symfony\\Bridge\\Doctrine\\Tests\\Fixtures'], '.orm.xml' + ) + ), + 'Symfony\\Bridge\\Doctrine\\Tests\\Fixtures' + ); + + $config->setMetadataDriverImpl($driverChain); + + return $config; + } + + /** + * This class cannot be instantiated. + */ + private function __construct() + { + } +} diff --git a/vendor/symfony/doctrine-bridge/Test/TestRepositoryFactory.php b/vendor/symfony/doctrine-bridge/Test/TestRepositoryFactory.php new file mode 100644 index 0000000..6197c6a --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Test/TestRepositoryFactory.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Test; + +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\Repository\RepositoryFactory; +use Doctrine\Persistence\ObjectRepository; + +/** + * @author Andreas Braun + */ +final class TestRepositoryFactory implements RepositoryFactory +{ + /** + * @var ObjectRepository[] + */ + private $repositoryList = []; + + /** + * {@inheritdoc} + * + * @return ObjectRepository + */ + public function getRepository(EntityManagerInterface $entityManager, $entityName) + { + $repositoryHash = $this->getRepositoryHash($entityManager, $entityName); + + if (isset($this->repositoryList[$repositoryHash])) { + return $this->repositoryList[$repositoryHash]; + } + + return $this->repositoryList[$repositoryHash] = $this->createRepository($entityManager, $entityName); + } + + public function setRepository(EntityManagerInterface $entityManager, string $entityName, ObjectRepository $repository) + { + $repositoryHash = $this->getRepositoryHash($entityManager, $entityName); + + $this->repositoryList[$repositoryHash] = $repository; + } + + private function createRepository(EntityManagerInterface $entityManager, string $entityName): ObjectRepository + { + /* @var $metadata ClassMetadata */ + $metadata = $entityManager->getClassMetadata($entityName); + $repositoryClassName = $metadata->customRepositoryClassName ?: $entityManager->getConfiguration()->getDefaultRepositoryClassName(); + + return new $repositoryClassName($entityManager, $metadata); + } + + private function getRepositoryHash(EntityManagerInterface $entityManager, string $entityName): string + { + return $entityManager->getClassMetadata($entityName)->getName().spl_object_hash($entityManager); + } +} diff --git a/vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntity.php b/vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntity.php new file mode 100644 index 0000000..2c31970 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntity.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Validator\Constraints; + +use Symfony\Component\Validator\Constraint; + +/** + * Constraint for the Unique Entity validator. + * + * @Annotation + * @Target({"CLASS", "ANNOTATION"}) + * + * @author Benjamin Eberlei + */ +class UniqueEntity extends Constraint +{ + const NOT_UNIQUE_ERROR = '23bd9dbf-6b9b-41cd-a99e-4844bcf3077f'; + + public $message = 'This value is already used.'; + public $service = 'doctrine.orm.validator.unique'; + public $em = null; + public $entityClass = null; + public $repositoryMethod = 'findBy'; + public $fields = []; + public $errorPath = null; + public $ignoreNull = true; + + protected static $errorNames = [ + self::NOT_UNIQUE_ERROR => 'NOT_UNIQUE_ERROR', + ]; + + public function getRequiredOptions() + { + return ['fields']; + } + + /** + * The validator must be defined as a service with this name. + * + * @return string + */ + public function validatedBy() + { + return $this->service; + } + + /** + * {@inheritdoc} + */ + public function getTargets() + { + return self::CLASS_CONSTRAINT; + } + + public function getDefaultOption() + { + return 'fields'; + } +} diff --git a/vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntityValidator.php b/vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntityValidator.php new file mode 100644 index 0000000..35f723a --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntityValidator.php @@ -0,0 +1,218 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Validator\Constraints; + +use Doctrine\Persistence\ManagerRegistry; +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\ConstraintValidator; +use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\UnexpectedTypeException; + +/** + * Unique Entity Validator checks if one or a set of fields contain unique values. + * + * @author Benjamin Eberlei + */ +class UniqueEntityValidator extends ConstraintValidator +{ + private $registry; + + public function __construct(ManagerRegistry $registry) + { + $this->registry = $registry; + } + + /** + * @param object $entity + * + * @throws UnexpectedTypeException + * @throws ConstraintDefinitionException + */ + public function validate($entity, Constraint $constraint) + { + if (!$constraint instanceof UniqueEntity) { + throw new UnexpectedTypeException($constraint, UniqueEntity::class); + } + + if (!\is_array($constraint->fields) && !\is_string($constraint->fields)) { + throw new UnexpectedTypeException($constraint->fields, 'array'); + } + + if (null !== $constraint->errorPath && !\is_string($constraint->errorPath)) { + throw new UnexpectedTypeException($constraint->errorPath, 'string or null'); + } + + $fields = (array) $constraint->fields; + + if (0 === \count($fields)) { + throw new ConstraintDefinitionException('At least one field has to be specified.'); + } + + if (null === $entity) { + return; + } + + if ($constraint->em) { + $em = $this->registry->getManager($constraint->em); + + if (!$em) { + throw new ConstraintDefinitionException(sprintf('Object manager "%s" does not exist.', $constraint->em)); + } + } else { + $em = $this->registry->getManagerForClass(\get_class($entity)); + + if (!$em) { + throw new ConstraintDefinitionException(sprintf('Unable to find the object manager associated with an entity of class "%s".', \get_class($entity))); + } + } + + $class = $em->getClassMetadata(\get_class($entity)); + + $criteria = []; + $hasNullValue = false; + + foreach ($fields as $fieldName) { + if (!$class->hasField($fieldName) && !$class->hasAssociation($fieldName)) { + throw new ConstraintDefinitionException(sprintf('The field "%s" is not mapped by Doctrine, so it cannot be validated for uniqueness.', $fieldName)); + } + + $fieldValue = $class->reflFields[$fieldName]->getValue($entity); + + if (null === $fieldValue) { + $hasNullValue = true; + } + + if ($constraint->ignoreNull && null === $fieldValue) { + continue; + } + + $criteria[$fieldName] = $fieldValue; + + if (null !== $criteria[$fieldName] && $class->hasAssociation($fieldName)) { + /* Ensure the Proxy is initialized before using reflection to + * read its identifiers. This is necessary because the wrapped + * getter methods in the Proxy are being bypassed. + */ + $em->initializeObject($criteria[$fieldName]); + } + } + + // validation doesn't fail if one of the fields is null and if null values should be ignored + if ($hasNullValue && $constraint->ignoreNull) { + return; + } + + // skip validation if there are no criteria (this can happen when the + // "ignoreNull" option is enabled and fields to be checked are null + if (empty($criteria)) { + return; + } + + if (null !== $constraint->entityClass) { + /* Retrieve repository from given entity name. + * We ensure the retrieved repository can handle the entity + * by checking the entity is the same, or subclass of the supported entity. + */ + $repository = $em->getRepository($constraint->entityClass); + $supportedClass = $repository->getClassName(); + + if (!$entity instanceof $supportedClass) { + throw new ConstraintDefinitionException(sprintf('The "%s" entity repository does not support the "%s" entity. The entity should be an instance of or extend "%s".', $constraint->entityClass, $class->getName(), $supportedClass)); + } + } else { + $repository = $em->getRepository(\get_class($entity)); + } + + $result = $repository->{$constraint->repositoryMethod}($criteria); + + if ($result instanceof \IteratorAggregate) { + $result = $result->getIterator(); + } + + /* If the result is a MongoCursor, it must be advanced to the first + * element. Rewinding should have no ill effect if $result is another + * iterator implementation. + */ + if ($result instanceof \Iterator) { + $result->rewind(); + if ($result instanceof \Countable && 1 < \count($result)) { + $result = [$result->current(), $result->current()]; + } else { + $result = $result->current(); + $result = null === $result ? [] : [$result]; + } + } elseif (\is_array($result)) { + reset($result); + } else { + $result = null === $result ? [] : [$result]; + } + + /* If no entity matched the query criteria or a single entity matched, + * which is the same as the entity being validated, the criteria is + * unique. + */ + if (!$result || (1 === \count($result) && current($result) === $entity)) { + return; + } + + $errorPath = null !== $constraint->errorPath ? $constraint->errorPath : $fields[0]; + $invalidValue = isset($criteria[$errorPath]) ? $criteria[$errorPath] : $criteria[$fields[0]]; + + $this->context->buildViolation($constraint->message) + ->atPath($errorPath) + ->setParameter('{{ value }}', $this->formatWithIdentifiers($em, $class, $invalidValue)) + ->setInvalidValue($invalidValue) + ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) + ->setCause($result) + ->addViolation(); + } + + private function formatWithIdentifiers($em, $class, $value) + { + if (!\is_object($value) || $value instanceof \DateTimeInterface) { + return $this->formatValue($value, self::PRETTY_DATE); + } + + if (method_exists($value, '__toString')) { + return (string) $value; + } + + if ($class->getName() !== $idClass = \get_class($value)) { + // non unique value might be a composite PK that consists of other entity objects + if ($em->getMetadataFactory()->hasMetadataFor($idClass)) { + $identifiers = $em->getClassMetadata($idClass)->getIdentifierValues($value); + } else { + // this case might happen if the non unique column has a custom doctrine type and its value is an object + // in which case we cannot get any identifiers for it + $identifiers = []; + } + } else { + $identifiers = $class->getIdentifierValues($value); + } + + if (!$identifiers) { + return sprintf('object("%s")', $idClass); + } + + array_walk($identifiers, function (&$id, $field) { + if (!\is_object($id) || $id instanceof \DateTimeInterface) { + $idAsString = $this->formatValue($id, self::PRETTY_DATE); + } else { + $idAsString = sprintf('object("%s")', \get_class($id)); + } + + $id = sprintf('%s => %s', $field, $idAsString); + }); + + return sprintf('object("%s") identified by (%s)', $idClass, implode(', ', $identifiers)); + } +} diff --git a/vendor/symfony/doctrine-bridge/Validator/DoctrineInitializer.php b/vendor/symfony/doctrine-bridge/Validator/DoctrineInitializer.php new file mode 100644 index 0000000..28d5fcc --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Validator/DoctrineInitializer.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Validator; + +use Doctrine\Persistence\ManagerRegistry; +use Symfony\Component\Validator\ObjectInitializerInterface; + +/** + * Automatically loads proxy object before validation. + * + * @author Fabien Potencier + */ +class DoctrineInitializer implements ObjectInitializerInterface +{ + protected $registry; + + public function __construct(ManagerRegistry $registry) + { + $this->registry = $registry; + } + + public function initialize(object $object) + { + $manager = $this->registry->getManagerForClass(\get_class($object)); + if (null !== $manager) { + $manager->initializeObject($object); + } + } +} diff --git a/vendor/symfony/doctrine-bridge/Validator/DoctrineLoader.php b/vendor/symfony/doctrine-bridge/Validator/DoctrineLoader.php new file mode 100644 index 0000000..ca9eb4f --- /dev/null +++ b/vendor/symfony/doctrine-bridge/Validator/DoctrineLoader.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Validator; + +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Doctrine\ORM\Mapping\MappingException as OrmMappingException; +use Doctrine\Persistence\Mapping\MappingException; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; +use Symfony\Component\Validator\Constraints\Length; +use Symfony\Component\Validator\Constraints\Valid; +use Symfony\Component\Validator\Mapping\AutoMappingStrategy; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Mapping\Loader\AutoMappingTrait; +use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; + +/** + * Guesses and loads the appropriate constraints using Doctrine's metadata. + * + * @author Kévin Dunglas + */ +final class DoctrineLoader implements LoaderInterface +{ + use AutoMappingTrait; + + private $entityManager; + private $classValidatorRegexp; + + public function __construct(EntityManagerInterface $entityManager, string $classValidatorRegexp = null) + { + $this->entityManager = $entityManager; + $this->classValidatorRegexp = $classValidatorRegexp; + } + + /** + * {@inheritdoc} + */ + public function loadClassMetadata(ClassMetadata $metadata): bool + { + $className = $metadata->getClassName(); + try { + $doctrineMetadata = $this->entityManager->getClassMetadata($className); + } catch (MappingException | OrmMappingException $exception) { + return false; + } + + if (!$doctrineMetadata instanceof ClassMetadataInfo) { + return false; + } + + $loaded = false; + $enabledForClass = $this->isAutoMappingEnabledForClass($metadata, $this->classValidatorRegexp); + + /* Available keys: + - type + - scale + - length + - unique + - nullable + - precision + */ + $existingUniqueFields = $this->getExistingUniqueFields($metadata); + + // Type and nullable aren't handled here, use the PropertyInfo Loader instead. + foreach ($doctrineMetadata->fieldMappings as $mapping) { + $enabledForProperty = $enabledForClass; + $lengthConstraint = null; + foreach ($metadata->getPropertyMetadata($mapping['fieldName']) as $propertyMetadata) { + // Enabling or disabling auto-mapping explicitly always takes precedence + if (AutoMappingStrategy::DISABLED === $propertyMetadata->getAutoMappingStrategy()) { + continue 2; + } + if (AutoMappingStrategy::ENABLED === $propertyMetadata->getAutoMappingStrategy()) { + $enabledForProperty = true; + } + + foreach ($propertyMetadata->getConstraints() as $constraint) { + if ($constraint instanceof Length) { + $lengthConstraint = $constraint; + } + } + } + + if (!$enabledForProperty) { + continue; + } + + if (true === ($mapping['unique'] ?? false) && !isset($existingUniqueFields[$mapping['fieldName']])) { + $metadata->addConstraint(new UniqueEntity(['fields' => $mapping['fieldName']])); + $loaded = true; + } + + if (null === ($mapping['length'] ?? null) || !\in_array($mapping['type'], ['string', 'text'], true)) { + continue; + } + + if (null === $lengthConstraint) { + if (isset($mapping['originalClass']) && false === strpos($mapping['declaredField'], '.')) { + $metadata->addPropertyConstraint($mapping['declaredField'], new Valid()); + $loaded = true; + } elseif (property_exists($className, $mapping['fieldName'])) { + $metadata->addPropertyConstraint($mapping['fieldName'], new Length(['max' => $mapping['length']])); + $loaded = true; + } + } elseif (null === $lengthConstraint->max) { + // If a Length constraint exists and no max length has been explicitly defined, set it + $lengthConstraint->max = $mapping['length']; + } + } + + return $loaded; + } + + private function getExistingUniqueFields(ClassMetadata $metadata): array + { + $fields = []; + foreach ($metadata->getConstraints() as $constraint) { + if (!$constraint instanceof UniqueEntity) { + continue; + } + + if (\is_string($constraint->fields)) { + $fields[$constraint->fields] = true; + } elseif (\is_array($constraint->fields) && 1 === \count($constraint->fields)) { + $fields[$constraint->fields[0]] = true; + } + } + + return $fields; + } +} diff --git a/vendor/symfony/doctrine-bridge/composer.json b/vendor/symfony/doctrine-bridge/composer.json new file mode 100644 index 0000000..bf8b981 --- /dev/null +++ b/vendor/symfony/doctrine-bridge/composer.json @@ -0,0 +1,80 @@ +{ + "name": "symfony/doctrine-bridge", + "type": "symfony-bridge", + "description": "Symfony Doctrine Bridge", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "doctrine/event-manager": "~1.0", + "doctrine/persistence": "^1.3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2" + }, + "require-dev": { + "symfony/stopwatch": "^4.4|^5.0", + "symfony/config": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/form": "^5.0", + "symfony/http-kernel": "^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/property-access": "^4.4|^5.0", + "symfony/property-info": "^5.0", + "symfony/proxy-manager-bridge": "^4.4|^5.0", + "symfony/security-core": "^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/validator": "^5.0.2", + "symfony/translation": "^4.4|^5.0", + "symfony/var-dumper": "^4.4|^5.0", + "doctrine/annotations": "~1.7", + "doctrine/cache": "~1.6", + "doctrine/collections": "~1.0", + "doctrine/data-fixtures": "1.0.*", + "doctrine/dbal": "~2.4", + "doctrine/orm": "^2.6.3", + "doctrine/reflection": "~1.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/dependency-injection": "<4.4", + "symfony/form": "<5", + "symfony/http-kernel": "<5", + "symfony/messenger": "<4.4", + "symfony/property-info": "<5", + "symfony/security-bundle": "<5", + "symfony/security-core": "<5", + "symfony/validator": "<5.0.2" + }, + "suggest": { + "symfony/form": "", + "symfony/validator": "", + "symfony/property-info": "", + "doctrine/data-fixtures": "", + "doctrine/dbal": "", + "doctrine/orm": "" + }, + "autoload": { + "psr-4": { "Symfony\\Bridge\\Doctrine\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/error-handler/.gitattributes b/vendor/symfony/error-handler/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/error-handler/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/error-handler/BufferingLogger.php b/vendor/symfony/error-handler/BufferingLogger.php new file mode 100644 index 0000000..16e433d --- /dev/null +++ b/vendor/symfony/error-handler/BufferingLogger.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler; + +use Psr\Log\AbstractLogger; + +/** + * A buffering logger that stacks logs for later. + * + * @author Nicolas Grekas + */ +class BufferingLogger extends AbstractLogger +{ + private $logs = []; + + public function log($level, $message, array $context = []): void + { + $this->logs[] = [$level, $message, $context]; + } + + public function cleanLogs(): array + { + $logs = $this->logs; + $this->logs = []; + + return $logs; + } + + public function __destruct() + { + foreach ($this->logs as [$level, $message, $context]) { + if (false !== strpos($message, '{')) { + foreach ($context as $key => $val) { + if (null === $val || is_scalar($val) || (\is_object($val) && \is_callable([$val, '__toString']))) { + $message = str_replace("{{$key}}", $val, $message); + } elseif ($val instanceof \DateTimeInterface) { + $message = str_replace("{{$key}}", $val->format(\DateTime::RFC3339), $message); + } elseif (\is_object($val)) { + $message = str_replace("{{$key}}", '[object '.\get_class($val).']', $message); + } else { + $message = str_replace("{{$key}}", '['.\gettype($val).']', $message); + } + } + } + + error_log(sprintf('%s [%s] %s', date(\DateTime::RFC3339), $level, $message)); + } + } +} diff --git a/vendor/symfony/error-handler/CHANGELOG.md b/vendor/symfony/error-handler/CHANGELOG.md new file mode 100644 index 0000000..c7c245a --- /dev/null +++ b/vendor/symfony/error-handler/CHANGELOG.md @@ -0,0 +1,8 @@ +CHANGELOG +========= + +4.4.0 +----- + + * added the component + * added `ErrorHandler::call()` method utility to turn any PHP error into `\ErrorException` diff --git a/vendor/symfony/error-handler/Debug.php b/vendor/symfony/error-handler/Debug.php new file mode 100644 index 0000000..f95334e --- /dev/null +++ b/vendor/symfony/error-handler/Debug.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler; + +/** + * Registers all the debug tools. + * + * @author Fabien Potencier + */ +class Debug +{ + public static function enable(): ErrorHandler + { + error_reporting(-1); + + if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { + ini_set('display_errors', 0); + } elseif (!filter_var(ini_get('log_errors'), FILTER_VALIDATE_BOOLEAN) || ini_get('error_log')) { + // CLI - display errors only if they're not already logged to STDERR + ini_set('display_errors', 1); + } + + DebugClassLoader::enable(); + + return ErrorHandler::register(new ErrorHandler(new BufferingLogger())); + } +} diff --git a/vendor/symfony/error-handler/DebugClassLoader.php b/vendor/symfony/error-handler/DebugClassLoader.php new file mode 100644 index 0000000..a9ce96e --- /dev/null +++ b/vendor/symfony/error-handler/DebugClassLoader.php @@ -0,0 +1,1074 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler; + +use Doctrine\Common\Persistence\Proxy as LegacyProxy; +use Doctrine\Persistence\Proxy; +use PHPUnit\Framework\MockObject\Matcher\StatelessInvocation; +use PHPUnit\Framework\MockObject\MockObject; +use Prophecy\Prophecy\ProphecySubjectInterface; +use ProxyManager\Proxy\ProxyInterface; + +/** + * Autoloader checking if the class is really defined in the file found. + * + * The ClassLoader will wrap all registered autoloaders + * and will throw an exception if a file is found but does + * not declare the class. + * + * It can also patch classes to turn docblocks into actual return types. + * This behavior is controlled by the SYMFONY_PATCH_TYPE_DECLARATIONS env var, + * which is a url-encoded array with the follow parameters: + * - "force": any value enables deprecation notices - can be any of: + * - "docblock" to patch only docblock annotations + * - "object" to turn union types to the "object" type when possible (not recommended) + * - "1" to add all possible return types including magic methods + * - "0" to add possible return types excluding magic methods + * - "php": the target version of PHP - e.g. "7.1" doesn't generate "object" types + * - "deprecations": "1" to trigger a deprecation notice when a child class misses a + * return type while the parent declares an "@return" annotation + * + * Note that patching doesn't care about any coding style so you'd better to run + * php-cs-fixer after, with rules "phpdoc_trim_consecutive_blank_line_separation" + * and "no_superfluous_phpdoc_tags" enabled typically. + * + * @author Fabien Potencier + * @author Christophe Coevoet + * @author Nicolas Grekas + * @author Guilhem Niot + */ +class DebugClassLoader +{ + private const SPECIAL_RETURN_TYPES = [ + 'mixed' => 'mixed', + 'void' => 'void', + 'null' => 'null', + 'resource' => 'resource', + 'static' => 'object', + '$this' => 'object', + 'boolean' => 'bool', + 'true' => 'bool', + 'false' => 'bool', + 'integer' => 'int', + 'array' => 'array', + 'bool' => 'bool', + 'callable' => 'callable', + 'float' => 'float', + 'int' => 'int', + 'iterable' => 'iterable', + 'object' => 'object', + 'string' => 'string', + 'self' => 'self', + 'parent' => 'parent', + ]; + + private const BUILTIN_RETURN_TYPES = [ + 'void' => true, + 'array' => true, + 'bool' => true, + 'callable' => true, + 'float' => true, + 'int' => true, + 'iterable' => true, + 'object' => true, + 'string' => true, + 'self' => true, + 'parent' => true, + ]; + + private const MAGIC_METHODS = [ + '__set' => 'void', + '__isset' => 'bool', + '__unset' => 'void', + '__sleep' => 'array', + '__wakeup' => 'void', + '__toString' => 'string', + '__clone' => 'void', + '__debugInfo' => 'array', + '__serialize' => 'array', + '__unserialize' => 'void', + ]; + + private const INTERNAL_TYPES = [ + 'ArrayAccess' => [ + 'offsetExists' => 'bool', + 'offsetSet' => 'void', + 'offsetUnset' => 'void', + ], + 'Countable' => [ + 'count' => 'int', + ], + 'Iterator' => [ + 'next' => 'void', + 'valid' => 'bool', + 'rewind' => 'void', + ], + 'IteratorAggregate' => [ + 'getIterator' => '\Traversable', + ], + 'OuterIterator' => [ + 'getInnerIterator' => '\Iterator', + ], + 'RecursiveIterator' => [ + 'hasChildren' => 'bool', + ], + 'SeekableIterator' => [ + 'seek' => 'void', + ], + 'Serializable' => [ + 'serialize' => 'string', + 'unserialize' => 'void', + ], + 'SessionHandlerInterface' => [ + 'open' => 'bool', + 'close' => 'bool', + 'read' => 'string', + 'write' => 'bool', + 'destroy' => 'bool', + 'gc' => 'bool', + ], + 'SessionIdInterface' => [ + 'create_sid' => 'string', + ], + 'SessionUpdateTimestampHandlerInterface' => [ + 'validateId' => 'bool', + 'updateTimestamp' => 'bool', + ], + 'Throwable' => [ + 'getMessage' => 'string', + 'getCode' => 'int', + 'getFile' => 'string', + 'getLine' => 'int', + 'getTrace' => 'array', + 'getPrevious' => '?\Throwable', + 'getTraceAsString' => 'string', + ], + ]; + + private $classLoader; + private $isFinder; + private $loaded = []; + private $patchTypes; + + private static $caseCheck; + private static $checkedClasses = []; + private static $final = []; + private static $finalMethods = []; + private static $deprecated = []; + private static $internal = []; + private static $internalMethods = []; + private static $annotatedParameters = []; + private static $darwinCache = ['/' => ['/', []]]; + private static $method = []; + private static $returnTypes = []; + private static $methodTraits = []; + private static $fileOffsets = []; + + public function __construct(callable $classLoader) + { + $this->classLoader = $classLoader; + $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile'); + parse_str(getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?: '', $this->patchTypes); + $this->patchTypes += [ + 'force' => null, + 'php' => null, + 'deprecations' => false, + ]; + + if (!isset(self::$caseCheck)) { + $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR); + $i = strrpos($file, \DIRECTORY_SEPARATOR); + $dir = substr($file, 0, 1 + $i); + $file = substr($file, 1 + $i); + $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file); + $test = realpath($dir.$test); + + if (false === $test || false === $i) { + // filesystem is case sensitive + self::$caseCheck = 0; + } elseif (substr($test, -\strlen($file)) === $file) { + // filesystem is case insensitive and realpath() normalizes the case of characters + self::$caseCheck = 1; + } elseif (false !== stripos(PHP_OS, 'darwin')) { + // on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters + self::$caseCheck = 2; + } else { + // filesystem case checks failed, fallback to disabling them + self::$caseCheck = 0; + } + } + } + + /** + * Gets the wrapped class loader. + * + * @return callable The wrapped class loader + */ + public function getClassLoader(): callable + { + return $this->classLoader; + } + + /** + * Wraps all autoloaders. + */ + public static function enable(): void + { + // Ensures we don't hit https://bugs.php.net/42098 + class_exists('Symfony\Component\ErrorHandler\ErrorHandler'); + class_exists('Psr\Log\LogLevel'); + + if (!\is_array($functions = spl_autoload_functions())) { + return; + } + + foreach ($functions as $function) { + spl_autoload_unregister($function); + } + + foreach ($functions as $function) { + if (!\is_array($function) || !$function[0] instanceof self) { + $function = [new static($function), 'loadClass']; + } + + spl_autoload_register($function); + } + } + + /** + * Disables the wrapping. + */ + public static function disable(): void + { + if (!\is_array($functions = spl_autoload_functions())) { + return; + } + + foreach ($functions as $function) { + spl_autoload_unregister($function); + } + + foreach ($functions as $function) { + if (\is_array($function) && $function[0] instanceof self) { + $function = $function[0]->getClassLoader(); + } + + spl_autoload_register($function); + } + } + + public static function checkClasses(): bool + { + if (!\is_array($functions = spl_autoload_functions())) { + return false; + } + + $loader = null; + + foreach ($functions as $function) { + if (\is_array($function) && $function[0] instanceof self) { + $loader = $function[0]; + break; + } + } + + if (null === $loader) { + return false; + } + + static $offsets = [ + 'get_declared_interfaces' => 0, + 'get_declared_traits' => 0, + 'get_declared_classes' => 0, + ]; + + foreach ($offsets as $getSymbols => $i) { + $symbols = $getSymbols(); + + for (; $i < \count($symbols); ++$i) { + if (!is_subclass_of($symbols[$i], MockObject::class) + && !is_subclass_of($symbols[$i], ProphecySubjectInterface::class) + && !is_subclass_of($symbols[$i], Proxy::class) + && !is_subclass_of($symbols[$i], ProxyInterface::class) + && !is_subclass_of($symbols[$i], LegacyProxy::class) + ) { + $loader->checkClass($symbols[$i]); + } + } + + $offsets[$getSymbols] = $i; + } + + return true; + } + + public function findFile(string $class): ?string + { + return $this->isFinder ? ($this->classLoader[0]->findFile($class) ?: null) : null; + } + + /** + * Loads the given class or interface. + * + * @throws \RuntimeException + */ + public function loadClass(string $class): void + { + $e = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR); + + try { + if ($this->isFinder && !isset($this->loaded[$class])) { + $this->loaded[$class] = true; + if (!$file = $this->classLoader[0]->findFile($class) ?: '') { + // no-op + } elseif (\function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file)) { + include $file; + + return; + } elseif (false === include $file) { + return; + } + } else { + ($this->classLoader)($class); + $file = ''; + } + } finally { + error_reporting($e); + } + + $this->checkClass($class, $file); + } + + private function checkClass(string $class, string $file = null): void + { + $exists = null === $file || class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); + + if (null !== $file && $class && '\\' === $class[0]) { + $class = substr($class, 1); + } + + if ($exists) { + if (isset(self::$checkedClasses[$class])) { + return; + } + self::$checkedClasses[$class] = true; + + $refl = new \ReflectionClass($class); + if (null === $file && $refl->isInternal()) { + return; + } + $name = $refl->getName(); + + if ($name !== $class && 0 === strcasecmp($name, $class)) { + throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name)); + } + + $deprecations = $this->checkAnnotations($refl, $name); + + foreach ($deprecations as $message) { + @trigger_error($message, E_USER_DEPRECATED); + } + } + + if (!$file) { + return; + } + + if (!$exists) { + if (false !== strpos($class, '/')) { + throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class)); + } + + throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); + } + + if (self::$caseCheck && $message = $this->checkCase($refl, $file, $class)) { + throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', $message[0], $message[1], $message[2])); + } + } + + public function checkAnnotations(\ReflectionClass $refl, string $class): array + { + if ( + 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV7' === $class + || 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV6' === $class + ) { + return []; + } + $deprecations = []; + + $className = isset($class[15]) && "\0" === $class[15] && 0 === strpos($class, "class@anonymous\x00") ? get_parent_class($class).'@anonymous' : $class; + + // Don't trigger deprecations for classes in the same vendor + if ($class !== $className) { + $vendor = preg_match('/^namespace ([^;\\\\\s]++)[;\\\\]/m', @file_get_contents($refl->getFileName()), $vendor) ? $vendor[1].'\\' : ''; + $vendorLen = \strlen($vendor); + } elseif (2 > $vendorLen = 1 + (strpos($class, '\\') ?: strpos($class, '_'))) { + $vendorLen = 0; + $vendor = ''; + } else { + $vendor = str_replace('_', '\\', substr($class, 0, $vendorLen)); + } + + // Detect annotations on the class + if (false !== $doc = $refl->getDocComment()) { + foreach (['final', 'deprecated', 'internal'] as $annotation) { + if (false !== strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) { + self::${$annotation}[$class] = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : ''; + } + } + + if ($refl->isInterface() && false !== strpos($doc, 'method') && preg_match_all('#\n \* @method\s+(static\s+)?+(?:[\w\|&\[\]\\\]+\s+)?(\w+(?:\s*\([^\)]*\))?)+(.+?([[:punct:]]\s*)?)?(?=\r?\n \*(?: @|/$|\r?\n))#', $doc, $notice, PREG_SET_ORDER)) { + foreach ($notice as $method) { + $static = '' !== $method[1]; + $name = $method[2]; + $description = $method[3] ?? null; + if (false === strpos($name, '(')) { + $name .= '()'; + } + if (null !== $description) { + $description = trim($description); + if (!isset($method[4])) { + $description .= '.'; + } + } + self::$method[$class][] = [$class, $name, $static, $description]; + } + } + } + + $parent = get_parent_class($class) ?: null; + $parentAndOwnInterfaces = $this->getOwnInterfaces($class, $parent); + if ($parent) { + $parentAndOwnInterfaces[$parent] = $parent; + + if (!isset(self::$checkedClasses[$parent])) { + $this->checkClass($parent); + } + + if (isset(self::$final[$parent])) { + $deprecations[] = sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $className); + } + } + + // Detect if the parent is annotated + foreach ($parentAndOwnInterfaces + class_uses($class, false) as $use) { + if (!isset(self::$checkedClasses[$use])) { + $this->checkClass($use); + } + if (isset(self::$deprecated[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen) && !isset(self::$deprecated[$class])) { + $type = class_exists($class, false) ? 'class' : (interface_exists($class, false) ? 'interface' : 'trait'); + $verb = class_exists($use, false) || interface_exists($class, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses'); + + $deprecations[] = sprintf('The "%s" %s %s "%s" that is deprecated%s.', $className, $type, $verb, $use, self::$deprecated[$use]); + } + if (isset(self::$internal[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen)) { + $deprecations[] = sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $className); + } + if (isset(self::$method[$use])) { + if ($refl->isAbstract()) { + if (isset(self::$method[$class])) { + self::$method[$class] = array_merge(self::$method[$class], self::$method[$use]); + } else { + self::$method[$class] = self::$method[$use]; + } + } elseif (!$refl->isInterface()) { + $hasCall = $refl->hasMethod('__call'); + $hasStaticCall = $refl->hasMethod('__callStatic'); + foreach (self::$method[$use] as $method) { + list($interface, $name, $static, $description) = $method; + if ($static ? $hasStaticCall : $hasCall) { + continue; + } + $realName = substr($name, 0, strpos($name, '(')); + if (!$refl->hasMethod($realName) || !($methodRefl = $refl->getMethod($realName))->isPublic() || ($static && !$methodRefl->isStatic()) || (!$static && $methodRefl->isStatic())) { + $deprecations[] = sprintf('Class "%s" should implement method "%s::%s"%s', $className, ($static ? 'static ' : '').$interface, $name, null == $description ? '.' : ': '.$description); + } + } + } + } + } + + if (trait_exists($class)) { + $file = $refl->getFileName(); + + foreach ($refl->getMethods() as $method) { + if ($method->getFileName() === $file) { + self::$methodTraits[$file][$method->getStartLine()] = $class; + } + } + + return $deprecations; + } + + // Inherit @final, @internal, @param and @return annotations for methods + self::$finalMethods[$class] = []; + self::$internalMethods[$class] = []; + self::$annotatedParameters[$class] = []; + self::$returnTypes[$class] = []; + foreach ($parentAndOwnInterfaces as $use) { + foreach (['finalMethods', 'internalMethods', 'annotatedParameters', 'returnTypes'] as $property) { + if (isset(self::${$property}[$use])) { + self::${$property}[$class] = self::${$property}[$class] ? self::${$property}[$use] + self::${$property}[$class] : self::${$property}[$use]; + } + } + + if (null !== (self::INTERNAL_TYPES[$use] ?? null)) { + foreach (self::INTERNAL_TYPES[$use] as $method => $returnType) { + if ('void' !== $returnType) { + self::$returnTypes[$class] += [$method => [$returnType, $returnType, $class, '']]; + } + } + } + } + + foreach ($refl->getMethods() as $method) { + if ($method->class !== $class) { + continue; + } + + if (null === $ns = self::$methodTraits[$method->getFileName()][$method->getStartLine()] ?? null) { + $ns = $vendor; + $len = $vendorLen; + } elseif (2 > $len = 1 + (strpos($ns, '\\') ?: strpos($ns, '_'))) { + $len = 0; + $ns = ''; + } else { + $ns = str_replace('_', '\\', substr($ns, 0, $len)); + } + + if ($parent && isset(self::$finalMethods[$parent][$method->name])) { + list($declaringClass, $message) = self::$finalMethods[$parent][$method->name]; + $deprecations[] = sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className); + } + + if (isset(self::$internalMethods[$class][$method->name])) { + list($declaringClass, $message) = self::$internalMethods[$class][$method->name]; + if (strncmp($ns, $declaringClass, $len)) { + $deprecations[] = sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className); + } + } + + // To read method annotations + $doc = $method->getDocComment(); + + if (isset(self::$annotatedParameters[$class][$method->name])) { + $definedParameters = []; + foreach ($method->getParameters() as $parameter) { + $definedParameters[$parameter->name] = true; + } + + foreach (self::$annotatedParameters[$class][$method->name] as $parameterName => $deprecation) { + if (!isset($definedParameters[$parameterName]) && !($doc && preg_match("/\\n\\s+\\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\\\${$parameterName}\\b/", $doc))) { + $deprecations[] = sprintf($deprecation, $className); + } + } + } + + $forcePatchTypes = $this->patchTypes['force']; + + if ($canAddReturnType = null !== $forcePatchTypes && false === strpos($method->getFileName(), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) { + if ('void' !== (self::MAGIC_METHODS[$method->name] ?? 'void')) { + $this->patchTypes['force'] = $forcePatchTypes ?: 'docblock'; + } + + $canAddReturnType = false !== strpos($refl->getFileName(), \DIRECTORY_SEPARATOR.'Tests'.\DIRECTORY_SEPARATOR) + || $refl->isFinal() + || $method->isFinal() + || $method->isPrivate() + || ('' === (self::$internal[$class] ?? null) && !$refl->isAbstract()) + || '' === (self::$final[$class] ?? null) + || preg_match('/@(final|internal)$/m', $doc) + ; + } + + if (null !== ($returnType = self::$returnTypes[$class][$method->name] ?? self::MAGIC_METHODS[$method->name] ?? null) && !$method->hasReturnType() && !($doc && preg_match('/\n\s+\* @return +(\S+)/', $doc))) { + list($normalizedType, $returnType, $declaringClass, $declaringFile) = \is_string($returnType) ? [$returnType, $returnType, '', ''] : $returnType; + + if ('void' === $normalizedType) { + $canAddReturnType = false; + } + + if ($canAddReturnType && 'docblock' !== $this->patchTypes['force']) { + $this->patchMethod($method, $returnType, $declaringFile, $normalizedType); + } + + if (strncmp($ns, $declaringClass, $len)) { + if ($canAddReturnType && 'docblock' === $this->patchTypes['force'] && false === strpos($method->getFileName(), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) { + $this->patchMethod($method, $returnType, $declaringFile, $normalizedType); + } elseif ('' !== $declaringClass && $this->patchTypes['deprecations']) { + $deprecations[] = sprintf('Method "%s::%s()" will return "%s" as of its next major version. Doing the same in child class "%s" will be required when upgrading.', $declaringClass, $method->name, $normalizedType, $className); + } + } + } + + if (!$doc) { + $this->patchTypes['force'] = $forcePatchTypes; + + continue; + } + + $matches = []; + + if (!$method->hasReturnType() && ((false !== strpos($doc, '@return') && preg_match('/\n\s+\* @return +(\S+)/', $doc, $matches)) || 'void' !== (self::MAGIC_METHODS[$method->name] ?? 'void'))) { + $matches = $matches ?: [1 => self::MAGIC_METHODS[$method->name]]; + $this->setReturnType($matches[1], $method, $parent); + + if (isset(self::$returnTypes[$class][$method->name][0]) && $canAddReturnType) { + $this->fixReturnStatements($method, self::$returnTypes[$class][$method->name][0]); + } + + if ($method->isPrivate()) { + unset(self::$returnTypes[$class][$method->name]); + } + } + + $this->patchTypes['force'] = $forcePatchTypes; + + if ($method->isPrivate()) { + continue; + } + + $finalOrInternal = false; + + foreach (['final', 'internal'] as $annotation) { + if (false !== strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) { + $message = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : ''; + self::${$annotation.'Methods'}[$class][$method->name] = [$class, $message]; + $finalOrInternal = true; + } + } + + if ($finalOrInternal || $method->isConstructor() || false === strpos($doc, '@param') || StatelessInvocation::class === $class) { + continue; + } + if (!preg_match_all('#\n\s+\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\$([a-zA-Z0-9_\x7f-\xff]++)#', $doc, $matches, PREG_SET_ORDER)) { + continue; + } + if (!isset(self::$annotatedParameters[$class][$method->name])) { + $definedParameters = []; + foreach ($method->getParameters() as $parameter) { + $definedParameters[$parameter->name] = true; + } + } + foreach ($matches as list(, $parameterType, $parameterName)) { + if (!isset($definedParameters[$parameterName])) { + $parameterType = trim($parameterType); + self::$annotatedParameters[$class][$method->name][$parameterName] = sprintf('The "%%s::%s()" method will require a new "%s$%s" argument in the next major version of its parent class "%s", not defining it is deprecated.', $method->name, $parameterType ? $parameterType.' ' : '', $parameterName, $className); + } + } + } + + return $deprecations; + } + + public function checkCase(\ReflectionClass $refl, string $file, string $class): ?array + { + $real = explode('\\', $class.strrchr($file, '.')); + $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file)); + + $i = \count($tail) - 1; + $j = \count($real) - 1; + + while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) { + --$i; + --$j; + } + + array_splice($tail, 0, $i + 1); + + if (!$tail) { + return null; + } + + $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail); + $tailLen = \strlen($tail); + $real = $refl->getFileName(); + + if (2 === self::$caseCheck) { + $real = $this->darwinRealpath($real); + } + + if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true) + && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false) + ) { + return [substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)]; + } + + return null; + } + + /** + * `realpath` on MacOSX doesn't normalize the case of characters. + */ + private function darwinRealpath(string $real): string + { + $i = 1 + strrpos($real, '/'); + $file = substr($real, $i); + $real = substr($real, 0, $i); + + if (isset(self::$darwinCache[$real])) { + $kDir = $real; + } else { + $kDir = strtolower($real); + + if (isset(self::$darwinCache[$kDir])) { + $real = self::$darwinCache[$kDir][0]; + } else { + $dir = getcwd(); + + if (!@chdir($real)) { + return $real.$file; + } + + $real = getcwd().'/'; + chdir($dir); + + $dir = $real; + $k = $kDir; + $i = \strlen($dir) - 1; + while (!isset(self::$darwinCache[$k])) { + self::$darwinCache[$k] = [$dir, []]; + self::$darwinCache[$dir] = &self::$darwinCache[$k]; + + while ('/' !== $dir[--$i]) { + } + $k = substr($k, 0, ++$i); + $dir = substr($dir, 0, $i--); + } + } + } + + $dirFiles = self::$darwinCache[$kDir][1]; + + if (!isset($dirFiles[$file]) && ') : eval()\'d code' === substr($file, -17)) { + // Get the file name from "file_name.php(123) : eval()'d code" + $file = substr($file, 0, strrpos($file, '(', -17)); + } + + if (isset($dirFiles[$file])) { + return $real.$dirFiles[$file]; + } + + $kFile = strtolower($file); + + if (!isset($dirFiles[$kFile])) { + foreach (scandir($real, 2) as $f) { + if ('.' !== $f[0]) { + $dirFiles[$f] = $f; + if ($f === $file) { + $kFile = $k = $file; + } elseif ($f !== $k = strtolower($f)) { + $dirFiles[$k] = $f; + } + } + } + self::$darwinCache[$kDir][1] = $dirFiles; + } + + return $real.$dirFiles[$kFile]; + } + + /** + * `class_implements` includes interfaces from the parents so we have to manually exclude them. + * + * @return string[] + */ + private function getOwnInterfaces(string $class, ?string $parent): array + { + $ownInterfaces = class_implements($class, false); + + if ($parent) { + foreach (class_implements($parent, false) as $interface) { + unset($ownInterfaces[$interface]); + } + } + + foreach ($ownInterfaces as $interface) { + foreach (class_implements($interface) as $interface) { + unset($ownInterfaces[$interface]); + } + } + + return $ownInterfaces; + } + + private function setReturnType(string $types, \ReflectionMethod $method, ?string $parent): void + { + $nullable = false; + $typesMap = []; + foreach (explode('|', $types) as $t) { + $typesMap[$this->normalizeType($t, $method->class, $parent)] = $t; + } + + if (isset($typesMap['array'])) { + if (isset($typesMap['Traversable']) || isset($typesMap['\Traversable'])) { + $typesMap['iterable'] = 'array' !== $typesMap['array'] ? $typesMap['array'] : 'iterable'; + unset($typesMap['array'], $typesMap['Traversable'], $typesMap['\Traversable']); + } elseif ('array' !== $typesMap['array'] && isset(self::$returnTypes[$method->class][$method->name])) { + return; + } + } + + if (isset($typesMap['array']) && isset($typesMap['iterable'])) { + if ('[]' === substr($typesMap['array'], -2)) { + $typesMap['iterable'] = $typesMap['array']; + } + unset($typesMap['array']); + } + + $iterable = $object = true; + foreach ($typesMap as $n => $t) { + if ('null' !== $n) { + $iterable = $iterable && (\in_array($n, ['array', 'iterable']) || false !== strpos($n, 'Iterator')); + $object = $object && (\in_array($n, ['callable', 'object', '$this', 'static']) || !isset(self::SPECIAL_RETURN_TYPES[$n])); + } + } + + $normalizedType = key($typesMap); + $returnType = current($typesMap); + + foreach ($typesMap as $n => $t) { + if ('null' === $n) { + $nullable = true; + } elseif ('null' === $normalizedType) { + $normalizedType = $t; + $returnType = $t; + } elseif ($n !== $normalizedType || !preg_match('/^\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $n)) { + if ($iterable) { + $normalizedType = $returnType = 'iterable'; + } elseif ($object && 'object' === $this->patchTypes['force']) { + $normalizedType = $returnType = 'object'; + } else { + // ignore multi-types return declarations + return; + } + } + } + + if ('void' === $normalizedType) { + $nullable = false; + } elseif (!isset(self::BUILTIN_RETURN_TYPES[$normalizedType]) && isset(self::SPECIAL_RETURN_TYPES[$normalizedType])) { + // ignore other special return types + return; + } + + if ($nullable) { + $normalizedType = '?'.$normalizedType; + $returnType .= '|null'; + } + + self::$returnTypes[$method->class][$method->name] = [$normalizedType, $returnType, $method->class, $method->getFileName()]; + } + + private function normalizeType(string $type, string $class, ?string $parent): string + { + if (isset(self::SPECIAL_RETURN_TYPES[$lcType = strtolower($type)])) { + if ('parent' === $lcType = self::SPECIAL_RETURN_TYPES[$lcType]) { + $lcType = null !== $parent ? '\\'.$parent : 'parent'; + } elseif ('self' === $lcType) { + $lcType = '\\'.$class; + } + + return $lcType; + } + + if ('[]' === substr($type, -2)) { + return 'array'; + } + + if (preg_match('/^(array|iterable|callable) *[<(]/', $lcType, $m)) { + return $m[1]; + } + + // We could resolve "use" statements to return the FQDN + // but this would be too expensive for a runtime checker + + return $type; + } + + /** + * Utility method to add @return annotations to the Symfony code-base where it triggers a self-deprecations. + */ + private function patchMethod(\ReflectionMethod $method, string $returnType, string $declaringFile, string $normalizedType) + { + static $patchedMethods = []; + static $useStatements = []; + + if (!file_exists($file = $method->getFileName()) || isset($patchedMethods[$file][$startLine = $method->getStartLine()])) { + return; + } + + $patchedMethods[$file][$startLine] = true; + $fileOffset = self::$fileOffsets[$file] ?? 0; + $startLine += $fileOffset - 2; + $nullable = '?' === $normalizedType[0] ? '?' : ''; + $normalizedType = ltrim($normalizedType, '?'); + $returnType = explode('|', $returnType); + $code = file($file); + + foreach ($returnType as $i => $type) { + if (preg_match('/((?:\[\])+)$/', $type, $m)) { + $type = substr($type, 0, -\strlen($m[1])); + $format = '%s'.$m[1]; + } elseif (preg_match('/^(array|iterable)<([^,>]++)>$/', $type, $m)) { + $type = $m[2]; + $format = $m[1].'<%s>'; + } else { + $format = null; + } + + if (isset(self::SPECIAL_RETURN_TYPES[$type]) || ('\\' === $type[0] && !$p = strrpos($type, '\\', 1))) { + continue; + } + + list($namespace, $useOffset, $useMap) = $useStatements[$file] ?? $useStatements[$file] = self::getUseStatements($file); + + if ('\\' !== $type[0]) { + list($declaringNamespace, , $declaringUseMap) = $useStatements[$declaringFile] ?? $useStatements[$declaringFile] = self::getUseStatements($declaringFile); + + $p = strpos($type, '\\', 1); + $alias = $p ? substr($type, 0, $p) : $type; + + if (isset($declaringUseMap[$alias])) { + $type = '\\'.$declaringUseMap[$alias].($p ? substr($type, $p) : ''); + } else { + $type = '\\'.$declaringNamespace.$type; + } + + $p = strrpos($type, '\\', 1); + } + + $alias = substr($type, 1 + $p); + $type = substr($type, 1); + + if (!isset($useMap[$alias]) && (class_exists($c = $namespace.$alias) || interface_exists($c) || trait_exists($c))) { + $useMap[$alias] = $c; + } + + if (!isset($useMap[$alias])) { + $useStatements[$file][2][$alias] = $type; + $code[$useOffset] = "use $type;\n".$code[$useOffset]; + ++$fileOffset; + } elseif ($useMap[$alias] !== $type) { + $alias .= 'FIXME'; + $useStatements[$file][2][$alias] = $type; + $code[$useOffset] = "use $type as $alias;\n".$code[$useOffset]; + ++$fileOffset; + } + + $returnType[$i] = null !== $format ? sprintf($format, $alias) : $alias; + + if (!isset(self::SPECIAL_RETURN_TYPES[$normalizedType]) && !isset(self::SPECIAL_RETURN_TYPES[$returnType[$i]])) { + $normalizedType = $returnType[$i]; + } + } + + if ('docblock' === $this->patchTypes['force'] || ('object' === $normalizedType && '7.1' === $this->patchTypes['php'])) { + $returnType = implode('|', $returnType); + + if ($method->getDocComment()) { + $code[$startLine] = " * @return $returnType\n".$code[$startLine]; + } else { + $code[$startLine] .= <<fixReturnStatements($method, $nullable.$normalizedType); + } + + private static function getUseStatements(string $file): array + { + $namespace = ''; + $useMap = []; + $useOffset = 0; + + if (!file_exists($file)) { + return [$namespace, $useOffset, $useMap]; + } + + $file = file($file); + + for ($i = 0; $i < \count($file); ++$i) { + if (preg_match('/^(class|interface|trait|abstract) /', $file[$i])) { + break; + } + + if (0 === strpos($file[$i], 'namespace ')) { + $namespace = substr($file[$i], \strlen('namespace '), -2).'\\'; + $useOffset = $i + 2; + } + + if (0 === strpos($file[$i], 'use ')) { + $useOffset = $i; + + for (; 0 === strpos($file[$i], 'use '); ++$i) { + $u = explode(' as ', substr($file[$i], 4, -2), 2); + + if (1 === \count($u)) { + $p = strrpos($u[0], '\\'); + $useMap[substr($u[0], false !== $p ? 1 + $p : 0)] = $u[0]; + } else { + $useMap[$u[1]] = $u[0]; + } + } + + break; + } + } + + return [$namespace, $useOffset, $useMap]; + } + + private function fixReturnStatements(\ReflectionMethod $method, string $returnType) + { + if ('7.1' === $this->patchTypes['php'] && 'object' === ltrim($returnType, '?') && 'docblock' !== $this->patchTypes['force']) { + return; + } + + if (!file_exists($file = $method->getFileName())) { + return; + } + + $fixedCode = $code = file($file); + $i = (self::$fileOffsets[$file] ?? 0) + $method->getStartLine(); + + if ('?' !== $returnType && 'docblock' !== $this->patchTypes['force']) { + $fixedCode[$i - 1] = preg_replace('/\)(;?\n)/', "): $returnType\\1", $code[$i - 1]); + } + + $end = $method->isGenerator() ? $i : $method->getEndLine(); + for (; $i < $end; ++$i) { + if ('void' === $returnType) { + $fixedCode[$i] = str_replace(' return null;', ' return;', $code[$i]); + } elseif ('mixed' === $returnType || '?' === $returnType[0]) { + $fixedCode[$i] = str_replace(' return;', ' return null;', $code[$i]); + } else { + $fixedCode[$i] = str_replace(' return;', " return $returnType!?;", $code[$i]); + } + } + + if ($fixedCode !== $code) { + file_put_contents($file, $fixedCode); + } + } +} diff --git a/vendor/symfony/error-handler/Error/ClassNotFoundError.php b/vendor/symfony/error-handler/Error/ClassNotFoundError.php new file mode 100644 index 0000000..443fba2 --- /dev/null +++ b/vendor/symfony/error-handler/Error/ClassNotFoundError.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\Error; + +class ClassNotFoundError extends \Error +{ + /** + * {@inheritdoc} + */ + public function __construct(string $message, \Throwable $previous) + { + parent::__construct($message, $previous->getCode(), $previous->getPrevious()); + + foreach ([ + 'file' => $previous->getFile(), + 'line' => $previous->getLine(), + 'trace' => $previous->getTrace(), + ] as $property => $value) { + $refl = new \ReflectionProperty(\Error::class, $property); + $refl->setAccessible(true); + $refl->setValue($this, $value); + } + } +} diff --git a/vendor/symfony/error-handler/Error/FatalError.php b/vendor/symfony/error-handler/Error/FatalError.php new file mode 100644 index 0000000..68172d8 --- /dev/null +++ b/vendor/symfony/error-handler/Error/FatalError.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\Error; + +class FatalError extends \Error +{ + private $error; + + /** + * {@inheritdoc} + * + * @param array $error An array as returned by error_get_last() + */ + public function __construct(string $message, int $code, array $error, int $traceOffset = null, bool $traceArgs = true, array $trace = null) + { + parent::__construct($message, $code); + + $this->error = $error; + + if (null !== $trace) { + if (!$traceArgs) { + foreach ($trace as &$frame) { + unset($frame['args'], $frame['this'], $frame); + } + } + } elseif (null !== $traceOffset) { + if (\function_exists('xdebug_get_function_stack')) { + $trace = xdebug_get_function_stack(); + if (0 < $traceOffset) { + array_splice($trace, -$traceOffset); + } + + foreach ($trace as &$frame) { + if (!isset($frame['type'])) { + // XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695 + if (isset($frame['class'])) { + $frame['type'] = '::'; + } + } elseif ('dynamic' === $frame['type']) { + $frame['type'] = '->'; + } elseif ('static' === $frame['type']) { + $frame['type'] = '::'; + } + + // XDebug also has a different name for the parameters array + if (!$traceArgs) { + unset($frame['params'], $frame['args']); + } elseif (isset($frame['params']) && !isset($frame['args'])) { + $frame['args'] = $frame['params']; + unset($frame['params']); + } + } + + unset($frame); + $trace = array_reverse($trace); + } else { + $trace = []; + } + } + + foreach ([ + 'file' => $error['file'], + 'line' => $error['line'], + 'trace' => $trace, + ] as $property => $value) { + $refl = new \ReflectionProperty(\Error::class, $property); + $refl->setAccessible(true); + $refl->setValue($this, $value); + } + } + + /** + * {@inheritdoc} + */ + public function getError(): array + { + return $this->error; + } +} diff --git a/vendor/symfony/error-handler/Error/OutOfMemoryError.php b/vendor/symfony/error-handler/Error/OutOfMemoryError.php new file mode 100644 index 0000000..d685c3d --- /dev/null +++ b/vendor/symfony/error-handler/Error/OutOfMemoryError.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\Error; + +class OutOfMemoryError extends FatalError +{ +} diff --git a/vendor/symfony/error-handler/Error/UndefinedFunctionError.php b/vendor/symfony/error-handler/Error/UndefinedFunctionError.php new file mode 100644 index 0000000..b57dd15 --- /dev/null +++ b/vendor/symfony/error-handler/Error/UndefinedFunctionError.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\Error; + +class UndefinedFunctionError extends \Error +{ + /** + * {@inheritdoc} + */ + public function __construct(string $message, \Throwable $previous) + { + parent::__construct($message, $previous->getCode(), $previous->getPrevious()); + + foreach ([ + 'file' => $previous->getFile(), + 'line' => $previous->getLine(), + 'trace' => $previous->getTrace(), + ] as $property => $value) { + $refl = new \ReflectionProperty(\Error::class, $property); + $refl->setAccessible(true); + $refl->setValue($this, $value); + } + } +} diff --git a/vendor/symfony/error-handler/Error/UndefinedMethodError.php b/vendor/symfony/error-handler/Error/UndefinedMethodError.php new file mode 100644 index 0000000..adc8731 --- /dev/null +++ b/vendor/symfony/error-handler/Error/UndefinedMethodError.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\Error; + +class UndefinedMethodError extends \Error +{ + /** + * {@inheritdoc} + */ + public function __construct(string $message, \Throwable $previous) + { + parent::__construct($message, $previous->getCode(), $previous->getPrevious()); + + foreach ([ + 'file' => $previous->getFile(), + 'line' => $previous->getLine(), + 'trace' => $previous->getTrace(), + ] as $property => $value) { + $refl = new \ReflectionProperty(\Error::class, $property); + $refl->setAccessible(true); + $refl->setValue($this, $value); + } + } +} diff --git a/vendor/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php b/vendor/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php new file mode 100644 index 0000000..7cd2b38 --- /dev/null +++ b/vendor/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php @@ -0,0 +1,193 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\ErrorEnhancer; + +use Composer\Autoload\ClassLoader; +use Symfony\Component\ErrorHandler\DebugClassLoader; +use Symfony\Component\ErrorHandler\Error\ClassNotFoundError; +use Symfony\Component\ErrorHandler\Error\FatalError; + +/** + * @author Fabien Potencier + */ +class ClassNotFoundErrorEnhancer implements ErrorEnhancerInterface +{ + /** + * {@inheritdoc} + */ + public function enhance(\Throwable $error): ?\Throwable + { + // Some specific versions of PHP produce a fatal error when extending a not found class. + $message = !$error instanceof FatalError ? $error->getMessage() : $error->getError()['message']; + $messageLen = \strlen($message); + $notFoundSuffix = '\' not found'; + $notFoundSuffixLen = \strlen($notFoundSuffix); + if ($notFoundSuffixLen > $messageLen) { + return null; + } + + if (0 !== substr_compare($message, $notFoundSuffix, -$notFoundSuffixLen)) { + return null; + } + + foreach (['class', 'interface', 'trait'] as $typeName) { + $prefix = ucfirst($typeName).' \''; + $prefixLen = \strlen($prefix); + if (0 !== strpos($message, $prefix)) { + continue; + } + + $fullyQualifiedClassName = substr($message, $prefixLen, -$notFoundSuffixLen); + if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) { + $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1); + $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex); + $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix); + $tail = ' for another namespace?'; + } else { + $className = $fullyQualifiedClassName; + $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className); + $tail = '?'; + } + + if ($candidates = $this->getClassCandidates($className)) { + $tail = array_pop($candidates).'"?'; + if ($candidates) { + $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail; + } else { + $tail = ' for "'.$tail; + } + } + $message .= "\nDid you forget a \"use\" statement".$tail; + + return new ClassNotFoundError($message, $error); + } + + return null; + } + + /** + * Tries to guess the full namespace for a given class name. + * + * By default, it looks for PSR-0 and PSR-4 classes registered via a Symfony or a Composer + * autoloader (that should cover all common cases). + * + * @param string $class A class name (without its namespace) + * + * Returns an array of possible fully qualified class names + */ + private function getClassCandidates(string $class): array + { + if (!\is_array($functions = spl_autoload_functions())) { + return []; + } + + // find Symfony and Composer autoloaders + $classes = []; + + foreach ($functions as $function) { + if (!\is_array($function)) { + continue; + } + // get class loaders wrapped by DebugClassLoader + if ($function[0] instanceof DebugClassLoader) { + $function = $function[0]->getClassLoader(); + + if (!\is_array($function)) { + continue; + } + } + + if ($function[0] instanceof ClassLoader) { + foreach ($function[0]->getPrefixes() as $prefix => $paths) { + foreach ($paths as $path) { + $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix)); + } + } + + foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) { + foreach ($paths as $path) { + $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix)); + } + } + } + } + + return array_unique($classes); + } + + private function findClassInPath(string $path, string $class, string $prefix): array + { + if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) { + return []; + } + + $classes = []; + $filename = $class.'.php'; + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) { + $classes[] = $class; + } + } + + return $classes; + } + + private function convertFileToClass(string $path, string $file, string $prefix): ?string + { + $candidates = [ + // namespaced class + $namespacedClass = str_replace([$path.\DIRECTORY_SEPARATOR, '.php', '/'], ['', '', '\\'], $file), + // namespaced class (with target dir) + $prefix.$namespacedClass, + // namespaced class (with target dir and separator) + $prefix.'\\'.$namespacedClass, + // PEAR class + str_replace('\\', '_', $namespacedClass), + // PEAR class (with target dir) + str_replace('\\', '_', $prefix.$namespacedClass), + // PEAR class (with target dir and separator) + str_replace('\\', '_', $prefix.'\\'.$namespacedClass), + ]; + + if ($prefix) { + $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); }); + } + + // We cannot use the autoloader here as most of them use require; but if the class + // is not found, the new autoloader call will require the file again leading to a + // "cannot redeclare class" error. + foreach ($candidates as $candidate) { + if ($this->classExists($candidate)) { + return $candidate; + } + } + + try { + require_once $file; + } catch (\Throwable $e) { + return null; + } + + foreach ($candidates as $candidate) { + if ($this->classExists($candidate)) { + return $candidate; + } + } + + return null; + } + + private function classExists(string $class): bool + { + return class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); + } +} diff --git a/vendor/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php b/vendor/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php new file mode 100644 index 0000000..7c3f4ef --- /dev/null +++ b/vendor/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\ErrorEnhancer; + +interface ErrorEnhancerInterface +{ + /** + * Returns an \Throwable instance if the class is able to improve the error, null otherwise. + */ + public function enhance(\Throwable $error): ?\Throwable; +} diff --git a/vendor/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php b/vendor/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php new file mode 100644 index 0000000..f4c49c2 --- /dev/null +++ b/vendor/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\ErrorEnhancer; + +use Symfony\Component\ErrorHandler\Error\FatalError; +use Symfony\Component\ErrorHandler\Error\UndefinedFunctionError; + +/** + * @author Fabien Potencier + */ +class UndefinedFunctionErrorEnhancer implements ErrorEnhancerInterface +{ + /** + * {@inheritdoc} + */ + public function enhance(\Throwable $error): ?\Throwable + { + if ($error instanceof FatalError) { + return null; + } + + $message = $error->getMessage(); + $messageLen = \strlen($message); + $notFoundSuffix = '()'; + $notFoundSuffixLen = \strlen($notFoundSuffix); + if ($notFoundSuffixLen > $messageLen) { + return null; + } + + if (0 !== substr_compare($message, $notFoundSuffix, -$notFoundSuffixLen)) { + return null; + } + + $prefix = 'Call to undefined function '; + $prefixLen = \strlen($prefix); + if (0 !== strpos($message, $prefix)) { + return null; + } + + $fullyQualifiedFunctionName = substr($message, $prefixLen, -$notFoundSuffixLen); + if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) { + $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1); + $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex); + $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix); + } else { + $functionName = $fullyQualifiedFunctionName; + $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName); + } + + $candidates = []; + foreach (get_defined_functions() as $type => $definedFunctionNames) { + foreach ($definedFunctionNames as $definedFunctionName) { + if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) { + $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1); + } else { + $definedFunctionNameBasename = $definedFunctionName; + } + + if ($definedFunctionNameBasename === $functionName) { + $candidates[] = '\\'.$definedFunctionName; + } + } + } + + if ($candidates) { + sort($candidates); + $last = array_pop($candidates).'"?'; + if ($candidates) { + $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; + } else { + $candidates = '"'.$last; + } + $message .= "\nDid you mean to call ".$candidates; + } + + return new UndefinedFunctionError($message, $error); + } +} diff --git a/vendor/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php b/vendor/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php new file mode 100644 index 0000000..ad0e4b3 --- /dev/null +++ b/vendor/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\ErrorEnhancer; + +use Symfony\Component\ErrorHandler\Error\FatalError; +use Symfony\Component\ErrorHandler\Error\UndefinedMethodError; + +/** + * @author Grégoire Pineau + */ +class UndefinedMethodErrorEnhancer implements ErrorEnhancerInterface +{ + /** + * {@inheritdoc} + */ + public function enhance(\Throwable $error): ?\Throwable + { + if ($error instanceof FatalError) { + return null; + } + + $message = $error->getMessage(); + preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $message, $matches); + if (!$matches) { + return null; + } + + $className = $matches[1]; + $methodName = $matches[2]; + + $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className); + + if (!class_exists($className) || null === $methods = get_class_methods($className)) { + // failed to get the class or its methods on which an unknown method was called (for example on an anonymous class) + return new UndefinedMethodError($message, $error); + } + + $candidates = []; + foreach ($methods as $definedMethodName) { + $lev = levenshtein($methodName, $definedMethodName); + if ($lev <= \strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) { + $candidates[] = $definedMethodName; + } + } + + if ($candidates) { + sort($candidates); + $last = array_pop($candidates).'"?'; + if ($candidates) { + $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; + } else { + $candidates = '"'.$last; + } + + $message .= "\nDid you mean to call ".$candidates; + } + + return new UndefinedMethodError($message, $error); + } +} diff --git a/vendor/symfony/error-handler/ErrorHandler.php b/vendor/symfony/error-handler/ErrorHandler.php new file mode 100644 index 0000000..f4dcfb1 --- /dev/null +++ b/vendor/symfony/error-handler/ErrorHandler.php @@ -0,0 +1,768 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler; + +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; +use Symfony\Component\ErrorHandler\Error\FatalError; +use Symfony\Component\ErrorHandler\Error\OutOfMemoryError; +use Symfony\Component\ErrorHandler\ErrorEnhancer\ClassNotFoundErrorEnhancer; +use Symfony\Component\ErrorHandler\ErrorEnhancer\ErrorEnhancerInterface; +use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedFunctionErrorEnhancer; +use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedMethodErrorEnhancer; +use Symfony\Component\ErrorHandler\ErrorRenderer\CliErrorRenderer; +use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; +use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; + +/** + * A generic ErrorHandler for the PHP engine. + * + * Provides five bit fields that control how errors are handled: + * - thrownErrors: errors thrown as \ErrorException + * - loggedErrors: logged errors, when not @-silenced + * - scopedErrors: errors thrown or logged with their local context + * - tracedErrors: errors logged with their stack trace + * - screamedErrors: never @-silenced errors + * + * Each error level can be logged by a dedicated PSR-3 logger object. + * Screaming only applies to logging. + * Throwing takes precedence over logging. + * Uncaught exceptions are logged as E_ERROR. + * E_DEPRECATED and E_USER_DEPRECATED levels never throw. + * E_RECOVERABLE_ERROR and E_USER_ERROR levels always throw. + * Non catchable errors that can be detected at shutdown time are logged when the scream bit field allows so. + * As errors have a performance cost, repeated errors are all logged, so that the developer + * can see them and weight them as more important to fix than others of the same level. + * + * @author Nicolas Grekas + * @author Grégoire Pineau + * + * @final + */ +class ErrorHandler +{ + private $levels = [ + E_DEPRECATED => 'Deprecated', + E_USER_DEPRECATED => 'User Deprecated', + E_NOTICE => 'Notice', + E_USER_NOTICE => 'User Notice', + E_STRICT => 'Runtime Notice', + E_WARNING => 'Warning', + E_USER_WARNING => 'User Warning', + E_COMPILE_WARNING => 'Compile Warning', + E_CORE_WARNING => 'Core Warning', + E_USER_ERROR => 'User Error', + E_RECOVERABLE_ERROR => 'Catchable Fatal Error', + E_COMPILE_ERROR => 'Compile Error', + E_PARSE => 'Parse Error', + E_ERROR => 'Error', + E_CORE_ERROR => 'Core Error', + ]; + + private $loggers = [ + E_DEPRECATED => [null, LogLevel::INFO], + E_USER_DEPRECATED => [null, LogLevel::INFO], + E_NOTICE => [null, LogLevel::WARNING], + E_USER_NOTICE => [null, LogLevel::WARNING], + E_STRICT => [null, LogLevel::WARNING], + E_WARNING => [null, LogLevel::WARNING], + E_USER_WARNING => [null, LogLevel::WARNING], + E_COMPILE_WARNING => [null, LogLevel::WARNING], + E_CORE_WARNING => [null, LogLevel::WARNING], + E_USER_ERROR => [null, LogLevel::CRITICAL], + E_RECOVERABLE_ERROR => [null, LogLevel::CRITICAL], + E_COMPILE_ERROR => [null, LogLevel::CRITICAL], + E_PARSE => [null, LogLevel::CRITICAL], + E_ERROR => [null, LogLevel::CRITICAL], + E_CORE_ERROR => [null, LogLevel::CRITICAL], + ]; + + private $thrownErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED + private $scopedErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED + private $tracedErrors = 0x77FB; // E_ALL - E_STRICT - E_PARSE + private $screamedErrors = 0x55; // E_ERROR + E_CORE_ERROR + E_COMPILE_ERROR + E_PARSE + private $loggedErrors = 0; + private $traceReflector; + + private $isRecursive = 0; + private $isRoot = false; + private $exceptionHandler; + private $bootstrappingLogger; + + private static $reservedMemory; + private static $toStringException; + private static $silencedErrorCache = []; + private static $silencedErrorCount = 0; + private static $exitCode = 0; + + /** + * Registers the error handler. + */ + public static function register(self $handler = null, bool $replace = true): self + { + if (null === self::$reservedMemory) { + self::$reservedMemory = str_repeat('x', 10240); + register_shutdown_function(__CLASS__.'::handleFatalError'); + } + + if ($handlerIsNew = null === $handler) { + $handler = new static(); + } + + if (null === $prev = set_error_handler([$handler, 'handleError'])) { + restore_error_handler(); + // Specifying the error types earlier would expose us to https://bugs.php.net/63206 + set_error_handler([$handler, 'handleError'], $handler->thrownErrors | $handler->loggedErrors); + $handler->isRoot = true; + } + + if ($handlerIsNew && \is_array($prev) && $prev[0] instanceof self) { + $handler = $prev[0]; + $replace = false; + } + if (!$replace && $prev) { + restore_error_handler(); + $handlerIsRegistered = \is_array($prev) && $handler === $prev[0]; + } else { + $handlerIsRegistered = true; + } + if (\is_array($prev = set_exception_handler([$handler, 'handleException'])) && $prev[0] instanceof self) { + restore_exception_handler(); + if (!$handlerIsRegistered) { + $handler = $prev[0]; + } elseif ($handler !== $prev[0] && $replace) { + set_exception_handler([$handler, 'handleException']); + $p = $prev[0]->setExceptionHandler(null); + $handler->setExceptionHandler($p); + $prev[0]->setExceptionHandler($p); + } + } else { + $handler->setExceptionHandler($prev ?? [$handler, 'renderException']); + } + + $handler->throwAt(E_ALL & $handler->thrownErrors, true); + + return $handler; + } + + /** + * Calls a function and turns any PHP error into \ErrorException. + * + * @return mixed What $function(...$arguments) returns + * + * @throws \ErrorException When $function(...$arguments) triggers a PHP error + */ + public static function call(callable $function, ...$arguments) + { + set_error_handler(static function (int $type, string $message, string $file, int $line) { + if (__FILE__ === $file) { + $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3); + $file = $trace[2]['file'] ?? $file; + $line = $trace[2]['line'] ?? $line; + } + + throw new \ErrorException($message, 0, $type, $file, $line); + }); + + try { + return $function(...$arguments); + } finally { + restore_error_handler(); + } + } + + public function __construct(BufferingLogger $bootstrappingLogger = null) + { + if ($bootstrappingLogger) { + $this->bootstrappingLogger = $bootstrappingLogger; + $this->setDefaultLogger($bootstrappingLogger); + } + $this->traceReflector = new \ReflectionProperty('Exception', 'trace'); + $this->traceReflector->setAccessible(true); + } + + /** + * Sets a logger to non assigned errors levels. + * + * @param LoggerInterface $logger A PSR-3 logger to put as default for the given levels + * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants + * @param bool $replace Whether to replace or not any existing logger + */ + public function setDefaultLogger(LoggerInterface $logger, $levels = E_ALL, bool $replace = false): void + { + $loggers = []; + + if (\is_array($levels)) { + foreach ($levels as $type => $logLevel) { + if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) { + $loggers[$type] = [$logger, $logLevel]; + } + } + } else { + if (null === $levels) { + $levels = E_ALL; + } + foreach ($this->loggers as $type => $log) { + if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) { + $log[0] = $logger; + $loggers[$type] = $log; + } + } + } + + $this->setLoggers($loggers); + } + + /** + * Sets a logger for each error level. + * + * @param array $loggers Error levels to [LoggerInterface|null, LogLevel::*] map + * + * @return array The previous map + * + * @throws \InvalidArgumentException + */ + public function setLoggers(array $loggers): array + { + $prevLogged = $this->loggedErrors; + $prev = $this->loggers; + $flush = []; + + foreach ($loggers as $type => $log) { + if (!isset($prev[$type])) { + throw new \InvalidArgumentException('Unknown error type: '.$type); + } + if (!\is_array($log)) { + $log = [$log]; + } elseif (!\array_key_exists(0, $log)) { + throw new \InvalidArgumentException('No logger provided'); + } + if (null === $log[0]) { + $this->loggedErrors &= ~$type; + } elseif ($log[0] instanceof LoggerInterface) { + $this->loggedErrors |= $type; + } else { + throw new \InvalidArgumentException('Invalid logger provided'); + } + $this->loggers[$type] = $log + $prev[$type]; + + if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) { + $flush[$type] = $type; + } + } + $this->reRegister($prevLogged | $this->thrownErrors); + + if ($flush) { + foreach ($this->bootstrappingLogger->cleanLogs() as $log) { + $type = ThrowableUtils::getSeverity($log[2]['exception']); + if (!isset($flush[$type])) { + $this->bootstrappingLogger->log($log[0], $log[1], $log[2]); + } elseif ($this->loggers[$type][0]) { + $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]); + } + } + } + + return $prev; + } + + /** + * Sets a user exception handler. + * + * @param callable(\Throwable $e)|null $handler + * + * @return callable|null The previous exception handler + */ + public function setExceptionHandler(?callable $handler): ?callable + { + $prev = $this->exceptionHandler; + $this->exceptionHandler = $handler; + + return $prev; + } + + /** + * Sets the PHP error levels that throw an exception when a PHP error occurs. + * + * @param int $levels A bit field of E_* constants for thrown errors + * @param bool $replace Replace or amend the previous value + * + * @return int The previous value + */ + public function throwAt(int $levels, bool $replace = false): int + { + $prev = $this->thrownErrors; + $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED; + if (!$replace) { + $this->thrownErrors |= $prev; + } + $this->reRegister($prev | $this->loggedErrors); + + return $prev; + } + + /** + * Sets the PHP error levels for which local variables are preserved. + * + * @param int $levels A bit field of E_* constants for scoped errors + * @param bool $replace Replace or amend the previous value + * + * @return int The previous value + */ + public function scopeAt(int $levels, bool $replace = false): int + { + $prev = $this->scopedErrors; + $this->scopedErrors = $levels; + if (!$replace) { + $this->scopedErrors |= $prev; + } + + return $prev; + } + + /** + * Sets the PHP error levels for which the stack trace is preserved. + * + * @param int $levels A bit field of E_* constants for traced errors + * @param bool $replace Replace or amend the previous value + * + * @return int The previous value + */ + public function traceAt(int $levels, bool $replace = false): int + { + $prev = $this->tracedErrors; + $this->tracedErrors = (int) $levels; + if (!$replace) { + $this->tracedErrors |= $prev; + } + + return $prev; + } + + /** + * Sets the error levels where the @-operator is ignored. + * + * @param int $levels A bit field of E_* constants for screamed errors + * @param bool $replace Replace or amend the previous value + * + * @return int The previous value + */ + public function screamAt(int $levels, bool $replace = false): int + { + $prev = $this->screamedErrors; + $this->screamedErrors = $levels; + if (!$replace) { + $this->screamedErrors |= $prev; + } + + return $prev; + } + + /** + * Re-registers as a PHP error handler if levels changed. + */ + private function reRegister(int $prev): void + { + if ($prev !== $this->thrownErrors | $this->loggedErrors) { + $handler = set_error_handler('var_dump'); + $handler = \is_array($handler) ? $handler[0] : null; + restore_error_handler(); + if ($handler === $this) { + restore_error_handler(); + if ($this->isRoot) { + set_error_handler([$this, 'handleError'], $this->thrownErrors | $this->loggedErrors); + } else { + set_error_handler([$this, 'handleError']); + } + } + } + } + + /** + * Handles errors by filtering then logging them according to the configured bit fields. + * + * @return bool Returns false when no handling happens so that the PHP engine can handle the error itself + * + * @throws \ErrorException When $this->thrownErrors requests so + * + * @internal + */ + public function handleError(int $type, string $message, string $file, int $line): bool + { + if (\PHP_VERSION_ID >= 70300 && E_WARNING === $type && '"' === $message[0] && false !== strpos($message, '" targeting switch is equivalent to "break')) { + $type = E_DEPRECATED; + } + + // Level is the current error reporting level to manage silent error. + $level = error_reporting(); + $silenced = 0 === ($level & $type); + // Strong errors are not authorized to be silenced. + $level |= E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED; + $log = $this->loggedErrors & $type; + $throw = $this->thrownErrors & $type & $level; + $type &= $level | $this->screamedErrors; + + if (!$type || (!$log && !$throw)) { + return !$silenced && $type && $log; + } + $scope = $this->scopedErrors & $type; + + if (4 < $numArgs = \func_num_args()) { + $context = $scope ? (func_get_arg(4) ?: []) : []; + } else { + $context = []; + } + + if (isset($context['GLOBALS']) && $scope) { + $e = $context; // Whatever the signature of the method, + unset($e['GLOBALS'], $context); // $context is always a reference in 5.3 + $context = $e; + } + + if (false !== strpos($message, "class@anonymous\0")) { + $logMessage = $this->parseAnonymousClass($message); + } else { + $logMessage = $this->levels[$type].': '.$message; + } + + if (null !== self::$toStringException) { + $errorAsException = self::$toStringException; + self::$toStringException = null; + } elseif (!$throw && !($type & $level)) { + if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) { + $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5), $type, $file, $line, false) : []; + $errorAsException = new SilencedErrorContext($type, $file, $line, isset($lightTrace[1]) ? [$lightTrace[0]] : $lightTrace); + } elseif (isset(self::$silencedErrorCache[$id][$message])) { + $lightTrace = null; + $errorAsException = self::$silencedErrorCache[$id][$message]; + ++$errorAsException->count; + } else { + $lightTrace = []; + $errorAsException = null; + } + + if (100 < ++self::$silencedErrorCount) { + self::$silencedErrorCache = $lightTrace = []; + self::$silencedErrorCount = 1; + } + if ($errorAsException) { + self::$silencedErrorCache[$id][$message] = $errorAsException; + } + if (null === $lightTrace) { + return true; + } + } else { + $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line); + + if ($throw || $this->tracedErrors & $type) { + $backtrace = $errorAsException->getTrace(); + $lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw); + $this->traceReflector->setValue($errorAsException, $lightTrace); + } else { + $this->traceReflector->setValue($errorAsException, []); + $backtrace = []; + } + } + + if ($throw) { + if (\PHP_VERSION_ID < 70400 && E_USER_ERROR & $type) { + for ($i = 1; isset($backtrace[$i]); ++$i) { + if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function']) + && '__toString' === $backtrace[$i]['function'] + && '->' === $backtrace[$i]['type'] + && !isset($backtrace[$i - 1]['class']) + && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function']) + ) { + // Here, we know trigger_error() has been called from __toString(). + // PHP triggers a fatal error when throwing from __toString(). + // A small convention allows working around the limitation: + // given a caught $e exception in __toString(), quitting the method with + // `return trigger_error($e, E_USER_ERROR);` allows this error handler + // to make $e get through the __toString() barrier. + + foreach ($context as $e) { + if ($e instanceof \Throwable && $e->__toString() === $message) { + self::$toStringException = $e; + + return true; + } + } + + // Display the original error message instead of the default one. + $this->handleException($errorAsException); + + // Stop the process by giving back the error to the native handler. + return false; + } + } + } + + throw $errorAsException; + } + + if ($this->isRecursive) { + $log = 0; + } else { + if (!\defined('HHVM_VERSION')) { + $currentErrorHandler = set_error_handler('var_dump'); + restore_error_handler(); + } + + try { + $this->isRecursive = true; + $level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG; + $this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? ['exception' => $errorAsException] : []); + } finally { + $this->isRecursive = false; + + if (!\defined('HHVM_VERSION')) { + set_error_handler($currentErrorHandler); + } + } + } + + return !$silenced && $type && $log; + } + + /** + * Handles an exception by logging then forwarding it to another handler. + * + * @internal + */ + public function handleException(\Throwable $exception) + { + $handlerException = null; + + if (!$exception instanceof FatalError) { + self::$exitCode = 255; + + $type = ThrowableUtils::getSeverity($exception); + } else { + $type = $exception->getError()['type']; + } + + if ($this->loggedErrors & $type) { + if (false !== strpos($message = $exception->getMessage(), "class@anonymous\0")) { + $message = $this->parseAnonymousClass($message); + } + + if ($exception instanceof FatalError) { + $message = 'Fatal '.$message; + } elseif ($exception instanceof \Error) { + $message = 'Uncaught Error: '.$message; + } elseif ($exception instanceof \ErrorException) { + $message = 'Uncaught '.$message; + } else { + $message = 'Uncaught Exception: '.$message; + } + + try { + $this->loggers[$type][0]->log($this->loggers[$type][1], $message, ['exception' => $exception]); + } catch (\Throwable $handlerException) { + } + } + + if (!$exception instanceof OutOfMemoryError) { + foreach ($this->getErrorEnhancers() as $errorEnhancer) { + if ($e = $errorEnhancer->enhance($exception)) { + $exception = $e; + break; + } + } + } + + $exceptionHandler = $this->exceptionHandler; + $this->exceptionHandler = [$this, 'renderException']; + + if (null === $exceptionHandler || $exceptionHandler === $this->exceptionHandler) { + $this->exceptionHandler = null; + } + + try { + if (null !== $exceptionHandler) { + return $exceptionHandler($exception); + } + $handlerException = $handlerException ?: $exception; + } catch (\Throwable $handlerException) { + } + if ($exception === $handlerException && null === $this->exceptionHandler) { + self::$reservedMemory = null; // Disable the fatal error handler + throw $exception; // Give back $exception to the native handler + } + + $loggedErrors = $this->loggedErrors; + $this->loggedErrors = $exception === $handlerException ? 0 : $this->loggedErrors; + + try { + $this->handleException($handlerException); + } finally { + $this->loggedErrors = $loggedErrors; + } + } + + /** + * Shutdown registered function for handling PHP fatal errors. + * + * @param array|null $error An array as returned by error_get_last() + * + * @internal + */ + public static function handleFatalError(array $error = null): void + { + if (null === self::$reservedMemory) { + return; + } + + $handler = self::$reservedMemory = null; + $handlers = []; + $previousHandler = null; + $sameHandlerLimit = 10; + + while (!\is_array($handler) || !$handler[0] instanceof self) { + $handler = set_exception_handler('var_dump'); + restore_exception_handler(); + + if (!$handler) { + break; + } + restore_exception_handler(); + + if ($handler !== $previousHandler) { + array_unshift($handlers, $handler); + $previousHandler = $handler; + } elseif (0 === --$sameHandlerLimit) { + $handler = null; + break; + } + } + foreach ($handlers as $h) { + set_exception_handler($h); + } + if (!$handler) { + return; + } + if ($handler !== $h) { + $handler[0]->setExceptionHandler($h); + } + $handler = $handler[0]; + $handlers = []; + + if ($exit = null === $error) { + $error = error_get_last(); + } + + if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) { + // Let's not throw anymore but keep logging + $handler->throwAt(0, true); + $trace = isset($error['backtrace']) ? $error['backtrace'] : null; + + if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) { + $fatalError = new OutOfMemoryError($handler->levels[$error['type']].': '.$error['message'], 0, $error, 2, false, $trace); + } else { + $fatalError = new FatalError($handler->levels[$error['type']].': '.$error['message'], 0, $error, 2, true, $trace); + } + } else { + $fatalError = null; + } + + try { + if (null !== $fatalError) { + self::$exitCode = 255; + $handler->handleException($fatalError); + } + } catch (FatalError $e) { + // Ignore this re-throw + } + + if ($exit && self::$exitCode) { + $exitCode = self::$exitCode; + register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); }); + } + } + + /** + * Renders the given exception. + * + * As this method is mainly called during boot where nothing is yet available, + * the output is always either HTML or CLI depending where PHP runs. + */ + private function renderException(\Throwable $exception): void + { + $renderer = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliErrorRenderer() : new HtmlErrorRenderer(0 !== $this->scopedErrors); + + $exception = $renderer->render($exception); + + if (!headers_sent()) { + http_response_code($exception->getStatusCode()); + + foreach ($exception->getHeaders() as $name => $value) { + header($name.': '.$value, false); + } + } + + echo $exception->getAsString(); + } + + /** + * Override this method if you want to define more error enhancers. + * + * @return ErrorEnhancerInterface[] + */ + protected function getErrorEnhancers(): iterable + { + return [ + new UndefinedFunctionErrorEnhancer(), + new UndefinedMethodErrorEnhancer(), + new ClassNotFoundErrorEnhancer(), + ]; + } + + /** + * Cleans the trace by removing function arguments and the frames added by the error handler and DebugClassLoader. + */ + private function cleanTrace(array $backtrace, int $type, string $file, int $line, bool $throw): array + { + $lightTrace = $backtrace; + + for ($i = 0; isset($backtrace[$i]); ++$i) { + if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { + $lightTrace = \array_slice($lightTrace, 1 + $i); + break; + } + } + if (class_exists(DebugClassLoader::class, false)) { + for ($i = \count($lightTrace) - 2; 0 < $i; --$i) { + if (DebugClassLoader::class === ($lightTrace[$i]['class'] ?? null)) { + array_splice($lightTrace, --$i, 2); + } + } + } + if (!($throw || $this->scopedErrors & $type)) { + for ($i = 0; isset($lightTrace[$i]); ++$i) { + unset($lightTrace[$i]['args'], $lightTrace[$i]['object']); + } + } + + return $lightTrace; + } + + /** + * Parse the error message by removing the anonymous class notation + * and using the parent class instead if possible. + */ + private function parseAnonymousClass(string $message): string + { + return preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:)[0-9a-fA-F]++/', static function ($m) { + return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0]; + }, $message); + } +} diff --git a/vendor/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php b/vendor/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php new file mode 100644 index 0000000..aa132d1 --- /dev/null +++ b/vendor/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\ErrorRenderer; + +use Symfony\Component\ErrorHandler\Exception\FlattenException; +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Dumper\CliDumper; + +/** + * @author Nicolas Grekas + */ +class CliErrorRenderer implements ErrorRendererInterface +{ + /** + * {@inheritdoc} + */ + public function render(\Throwable $exception): FlattenException + { + $cloner = new VarCloner(); + $dumper = new class() extends CliDumper { + protected function supportsColors(): bool + { + $outputStream = $this->outputStream; + $this->outputStream = fopen('php://stdout', 'w'); + + try { + return parent::supportsColors(); + } finally { + $this->outputStream = $outputStream; + } + } + }; + + return FlattenException::createFromThrowable($exception) + ->setAsString($dumper->dump($cloner->cloneVar($exception), true)); + } +} diff --git a/vendor/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php b/vendor/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php new file mode 100644 index 0000000..aba1966 --- /dev/null +++ b/vendor/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\ErrorRenderer; + +use Symfony\Component\ErrorHandler\Exception\FlattenException; + +/** + * Formats an exception to be used as response content. + * + * @author Yonel Ceruto + */ +interface ErrorRendererInterface +{ + /** + * Renders a Throwable as a FlattenException. + */ + public function render(\Throwable $exception): FlattenException; +} diff --git a/vendor/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php b/vendor/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php new file mode 100644 index 0000000..883a94f --- /dev/null +++ b/vendor/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php @@ -0,0 +1,350 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\ErrorRenderer; + +use Psr\Log\LoggerInterface; +use Symfony\Component\ErrorHandler\Exception\FlattenException; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; + +/** + * @author Yonel Ceruto + */ +class HtmlErrorRenderer implements ErrorRendererInterface +{ + private const GHOST_ADDONS = [ + '02-14' => self::GHOST_HEART, + '02-29' => self::GHOST_PLUS, + '10-18' => self::GHOST_GIFT, + ]; + + private const GHOST_GIFT = 'M124.00534057617188,5.3606138080358505 C124.40059661865234,4.644828304648399 125.1237564086914,3.712414965033531 123.88127899169922,3.487462028861046 C123.53517150878906,3.3097832053899765 123.18894958496094,2.9953975528478622 122.8432846069336,3.345616325736046 C122.07421112060547,3.649444565176964 121.40750122070312,4.074306473135948 122.2164306640625,4.869479164481163 C122.57514953613281,5.3830065578222275 122.90142822265625,6.503447040915489 123.3077621459961,6.626829609274864 C123.55027770996094,6.210384353995323 123.7774658203125,5.785196766257286 124.00534057617188,5.3606138080358505 zM122.30630493164062,7.336987480521202 C121.60028076171875,6.076864704489708 121.03211975097656,4.72498320043087 120.16796875,3.562500938773155 C119.11695098876953,2.44033907353878 117.04605865478516,2.940566048026085 116.57544708251953,4.387995228171349 C115.95028686523438,5.819030746817589 117.2991714477539,7.527640804648399 118.826171875,7.348545059561729 C119.98493194580078,7.367936596274376 121.15027618408203,7.420116886496544 122.30630493164062,7.336987480521202 zM128.1732177734375,7.379541382193565 C129.67486572265625,7.17823551595211 130.53842163085938,5.287807449698448 129.68344116210938,4.032590612769127 C128.92578125,2.693056806921959 126.74605560302734,2.6463639587163925 125.98509216308594,4.007616028189659 C125.32617950439453,5.108129009604454 124.75428009033203,6.258124336600304 124.14962768554688,7.388818249106407 C125.48638916015625,7.465229496359825 126.8357162475586,7.447416767477989 128.1732177734375,7.379541382193565 zM130.6601104736328,8.991325363516808 C131.17202758789062,8.540884003043175 133.1543731689453,8.009847149252892 131.65304565429688,7.582054600119591 C131.2811279296875,7.476506695151329 130.84751892089844,6.99234913289547 130.5132598876953,7.124847874045372 C129.78744506835938,8.02728746831417 128.67140197753906,8.55669592320919 127.50616455078125,8.501235947012901 C127.27806091308594,8.576229080557823 126.11459350585938,8.38720129430294 126.428955078125,8.601900085806847 C127.25099182128906,9.070617660880089 128.0523223876953,9.579657539725304 128.902587890625,9.995706543326378 C129.49813842773438,9.678531631827354 130.0761260986328,9.329126343131065 130.6601104736328,8.991325363516808 zM118.96446990966797,9.246344551444054 C119.4022445678711,8.991325363516808 119.84001922607422,8.736305221915245 120.27779388427734,8.481284126639366 C118.93965911865234,8.414779648184776 117.40827941894531,8.607666000723839 116.39698791503906,7.531384453177452 C116.11186981201172,7.212117180228233 115.83845520019531,6.846597656607628 115.44329071044922,7.248530372977257 C114.96995544433594,7.574637398123741 113.5140609741211,7.908811077475548 114.63501739501953,8.306883797049522 C115.61112976074219,8.883499130606651 116.58037567138672,9.474181160330772 117.58061218261719,10.008124336600304 C118.05723571777344,9.784612640738487 118.50651550292969,9.5052699893713 118.96446990966797,9.246344551444054 zM125.38018035888672,12.091858848929405 C125.9474868774414,11.636047348380089 127.32159423828125,11.201767906546593 127.36749267578125,10.712632164359093 C126.08487701416016,9.974547371268272 124.83960723876953,9.152772888541222 123.49772644042969,8.528907760977745 C123.03594207763672,8.353693947196007 122.66152954101562,8.623294815421104 122.28982543945312,8.857431396842003 C121.19065856933594,9.51122473180294 120.06505584716797,10.12446115911007 119.00167083740234,10.835315689444542 C120.39238739013672,11.69529627263546 121.79983520507812,12.529837593436241 123.22095489501953,13.338589653372765 C123.94580841064453,12.932025894522667 124.66128540039062,12.508862480521202 125.38018035888672,12.091858848929405 zM131.07164001464844,13.514615997672081 C131.66018676757812,13.143282875418663 132.2487335205078,12.771927818655968 132.8372802734375,12.400571808218956 C132.8324737548828,11.156818374991417 132.8523406982422,9.912529930472374 132.81829833984375,8.669195160269737 C131.63046264648438,9.332009300589561 130.45948791503906,10.027913078665733 129.30828857421875,10.752535805106163 C129.182373046875,12.035354599356651 129.24623107910156,13.33940313756466 129.27359008789062,14.628684982657433 C129.88104248046875,14.27079389989376 130.4737548828125,13.888019546866417 131.07164001464844,13.514640793204308 zM117.26847839355469,12.731024727225304 C117.32825469970703,11.67083452641964 117.45709991455078,10.46224020421505 116.17853546142578,10.148179039359093 C115.37110900878906,9.77159021794796 114.25194549560547,8.806716904044151 113.62991333007812,8.81639002263546 C113.61052703857422,10.0110072940588 113.62078857421875,11.20585821568966 113.61869049072266,12.400571808218956 C114.81139373779297,13.144886955618858 115.98292541503906,13.925040230154991 117.20137023925781,14.626662239432335 C117.31951141357422,14.010867103934288 117.24227905273438,13.35805033147335 117.26847839355469,12.731024727225304 zM125.80937957763672,16.836034759879112 C126.51483917236328,16.390663132071495 127.22030639648438,15.945291504263878 127.92576599121094,15.49991987645626 C127.92250061035156,14.215868934988976 127.97560119628906,12.929980263113976 127.91757202148438,11.647302612662315 C127.14225769042969,11.869626984000206 126.25550079345703,12.556857094168663 125.43866729736328,12.983742699027061 C124.82704162597656,13.342005714774132 124.21542358398438,13.700271591544151 123.60379028320312,14.05853746831417 C123.61585235595703,15.429577812552452 123.57081604003906,16.803131088614464 123.64839172363281,18.172149643301964 C124.37957000732422,17.744937881827354 125.09130859375,17.284801468253136 125.80937957763672,16.836034759879112 zM122.8521499633789,16.115344032645226 C122.8521499633789,15.429741844534874 122.8521499633789,14.744139656424522 122.8521499633789,14.05853746831417 C121.43595123291016,13.230924591422081 120.02428436279297,12.395455345511436 118.60256958007812,11.577354416251183 C118.52394104003906,12.888403877615929 118.56887817382812,14.204405769705772 118.55702209472656,15.517732605338097 C119.97289276123047,16.4041957706213 121.37410736083984,17.314891800284386 122.80789947509766,18.172149643301964 C122.86368560791016,17.488990768790245 122.84332275390625,16.800363525748253 122.8521499633789,16.115344032645226 zM131.10684204101562,18.871450409293175 C131.68399047851562,18.48711584508419 132.2611541748047,18.10278509557247 132.8383026123047,17.718475326895714 C132.81423950195312,16.499977096915245 132.89776611328125,15.264989838004112 132.77627563476562,14.05993078649044 C131.5760040283203,14.744719490408897 130.41763305664062,15.524359688162804 129.23875427246094,16.255397781729698 C129.26707458496094,17.516149505972862 129.18060302734375,18.791316971182823 129.3108367919922,20.041303619742393 C129.91973876953125,19.667551025748253 130.51010131835938,19.264152511954308 131.10684204101562,18.871450409293175 zM117.2557373046875,18.188333496451378 C117.25104522705078,17.549470886588097 117.24633026123047,16.91058538854122 117.24163055419922,16.271720871329308 C116.04924774169922,15.525708183646202 114.87187957763672,14.75476549565792 113.66158294677734,14.038097366690636 C113.5858383178711,15.262084946036339 113.62901306152344,16.49083898961544 113.61761474609375,17.717010483145714 C114.82051086425781,18.513254150748253 116.00987243652344,19.330610260367393 117.22888946533203,20.101993545889854 C117.27559661865234,19.466014847159386 117.25241088867188,18.825733169913292 117.2557373046875,18.188333496451378 zM125.8398666381836,22.38675306737423 C126.54049682617188,21.921453461050987 127.24110412597656,21.456151947379112 127.94172668457031,20.99083136022091 C127.94009399414062,19.693386062979698 127.96646118164062,18.395381912589073 127.93160247802734,17.098379120230675 C126.50540924072266,17.97775076329708 125.08877563476562,18.873308166861534 123.68258666992188,19.78428266942501 C123.52366638183594,21.03710363805294 123.626708984375,22.32878302037716 123.62647247314453,23.595300659537315 C124.06291198730469,23.86113165318966 125.1788101196289,22.68297766149044 125.8398666381836,22.38675306737423 zM122.8521499633789,21.83134649693966 C122.76741790771484,20.936696991324425 123.21651458740234,19.67745779454708 122.0794677734375,19.330633148550987 C120.93280029296875,18.604360565543175 119.7907485961914,17.870157226920128 118.62899780273438,17.16818617284298 C118.45966339111328,18.396427139639854 118.63676452636719,19.675991043448448 118.50668334960938,20.919256195425987 C119.89984130859375,21.92635916173458 121.32942199707031,22.88914106786251 122.78502655029297,23.803510650992393 C122.90177917480469,23.1627406924963 122.82917022705078,22.48402212560177 122.8521499633789,21.83134649693966 zM117.9798355102539,21.59483526647091 C116.28416442871094,20.46288488805294 114.58848571777344,19.330957397818565 112.892822265625,18.199007019400597 C112.89473724365234,14.705654129385948 112.84647369384766,11.211485847830772 112.90847778320312,7.718807205557823 C113.7575912475586,7.194885239005089 114.66117858886719,6.765397056937218 115.5350341796875,6.284702762961388 C114.97061157226562,4.668964847922325 115.78496551513672,2.7054970115423203 117.42159271240234,2.1007001250982285 C118.79354095458984,1.537783369421959 120.44731903076172,2.0457767099142075 121.32200622558594,3.23083733022213 C121.95732116699219,2.9050118774175644 122.59264373779297,2.5791852325201035 123.22796630859375,2.253336176276207 C123.86669921875,2.5821153968572617 124.50543975830078,2.9108948558568954 125.1441650390625,3.23967407643795 C126.05941009521484,2.154020771384239 127.62747192382812,1.5344576686620712 128.986328125,2.1429056972265244 C130.61741638183594,2.716217741370201 131.50650024414062,4.675290569663048 130.9215545654297,6.2884936183691025 C131.8018341064453,6.78548763692379 132.7589111328125,7.1738648265600204 133.5660400390625,7.780336365103722 C133.60182189941406,11.252970680594444 133.56637573242188,14.726140961050987 133.5631103515625,18.199007019400597 C130.18914794921875,20.431867584586143 126.86984252929688,22.74994657933712 123.44108581542969,24.897907242178917 C122.44406127929688,24.897628769278526 121.5834732055664,23.815067276358604 120.65831756591797,23.37616156041622 C119.76387023925781,22.784828171133995 118.87168884277344,22.19007681310177 117.9798355102539,21.59483526647091 z'; + private const GHOST_HEART = 'M125.91386369681868,8.305165958366445 C128.95033202169043,-0.40540639102854037 140.8469835342744,8.305165958366445 125.91386369681868,19.504526138305664 C110.98208663272044,8.305165958366445 122.87795231771452,-0.40540639102854037 125.91386369681868,8.305165958366445 z'; + private const GHOST_PLUS = 'M111.36824226379395,8.969108581542969 L118.69175148010254,8.969108581542969 L118.69175148010254,1.6455793380737305 L126.20429420471191,1.6455793380737305 L126.20429420471191,8.969108581542969 L133.52781105041504,8.969108581542969 L133.52781105041504,16.481630325317383 L126.20429420471191,16.481630325317383 L126.20429420471191,23.805158615112305 L118.69175148010254,23.805158615112305 L118.69175148010254,16.481630325317383 L111.36824226379395,16.481630325317383 z'; + + private $debug; + private $charset; + private $fileLinkFormat; + private $projectDir; + private $outputBuffer; + private $logger; + + /** + * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it + * @param bool|callable $outputBuffer The output buffer as a string or a callable that should return it + */ + public function __construct($debug = false, string $charset = null, $fileLinkFormat = null, string $projectDir = null, $outputBuffer = '', LoggerInterface $logger = null) + { + if (!\is_bool($debug) && !\is_callable($debug)) { + throw new \TypeError(sprintf('Argument 1 passed to %s() must be a boolean or a callable, %s given.', __METHOD__, \is_object($debug) ? \get_class($debug) : \gettype($debug))); + } + + if (!\is_string($outputBuffer) && !\is_callable($outputBuffer)) { + throw new \TypeError(sprintf('Argument 5 passed to %s() must be a string or a callable, %s given.', __METHOD__, \is_object($outputBuffer) ? \get_class($outputBuffer) : \gettype($outputBuffer))); + } + + $this->debug = $debug; + $this->charset = $charset ?: (ini_get('default_charset') ?: 'UTF-8'); + $this->fileLinkFormat = $fileLinkFormat ?: (ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')); + $this->projectDir = $projectDir; + $this->outputBuffer = $outputBuffer; + $this->logger = $logger; + } + + /** + * {@inheritdoc} + */ + public function render(\Throwable $exception): FlattenException + { + $exception = FlattenException::createFromThrowable($exception, null, [ + 'Content-Type' => 'text/html; charset='.$this->charset, + ]); + + return $exception->setAsString($this->renderException($exception)); + } + + /** + * Gets the HTML content associated with the given exception. + */ + public function getBody(FlattenException $exception): string + { + return $this->renderException($exception, 'views/exception.html.php'); + } + + /** + * Gets the stylesheet associated with the given exception. + */ + public function getStylesheet(): string + { + if (!$this->debug) { + return $this->include('assets/css/error.css'); + } + + return $this->include('assets/css/exception.css'); + } + + public static function isDebug(RequestStack $requestStack, bool $debug): \Closure + { + return static function () use ($requestStack, $debug): bool { + if (!$request = $requestStack->getCurrentRequest()) { + return $debug; + } + + return $debug && $request->attributes->getBoolean('showException', true); + }; + } + + public static function getAndCleanOutputBuffer(RequestStack $requestStack): \Closure + { + return static function () use ($requestStack): string { + if (!$request = $requestStack->getCurrentRequest()) { + return ''; + } + + $startObLevel = $request->headers->get('X-Php-Ob-Level', -1); + + if (ob_get_level() <= $startObLevel) { + return ''; + } + + Response::closeOutputBuffers($startObLevel + 1, true); + + return ob_get_clean(); + }; + } + + private function renderException(FlattenException $exception, string $debugTemplate = 'views/exception_full.html.php'): string + { + $debug = \is_bool($this->debug) ? $this->debug : ($this->debug)($exception); + $statusText = $this->escape($exception->getStatusText()); + $statusCode = $this->escape($exception->getStatusCode()); + + if (!$debug) { + return $this->include('views/error.html.php', [ + 'statusText' => $statusText, + 'statusCode' => $statusCode, + ]); + } + + $exceptionMessage = $this->escape($exception->getMessage()); + + return $this->include($debugTemplate, [ + 'exception' => $exception, + 'exceptionMessage' => $exceptionMessage, + 'statusText' => $statusText, + 'statusCode' => $statusCode, + 'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null, + 'currentContent' => \is_string($this->outputBuffer) ? $this->outputBuffer : ($this->outputBuffer)(), + ]); + } + + /** + * Formats an array as a string. + */ + private function formatArgs(array $args): string + { + $result = []; + foreach ($args as $key => $item) { + if ('object' === $item[0]) { + $formattedValue = sprintf('object(%s)', $this->abbrClass($item[1])); + } elseif ('array' === $item[0]) { + $formattedValue = sprintf('array(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); + } elseif ('null' === $item[0]) { + $formattedValue = 'null'; + } elseif ('boolean' === $item[0]) { + $formattedValue = ''.strtolower(var_export($item[1], true)).''; + } elseif ('resource' === $item[0]) { + $formattedValue = 'resource'; + } else { + $formattedValue = str_replace("\n", '', $this->escape(var_export($item[1], true))); + } + + $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escape($key), $formattedValue); + } + + return implode(', ', $result); + } + + private function formatArgsAsText(array $args) + { + return strip_tags($this->formatArgs($args)); + } + + private function escape(string $string): string + { + return htmlspecialchars($string, ENT_COMPAT | ENT_SUBSTITUTE, $this->charset); + } + + private function abbrClass(string $class): string + { + $parts = explode('\\', $class); + $short = array_pop($parts); + + return sprintf('%s', $class, $short); + } + + private function getFileRelative(string $file): ?string + { + $file = str_replace('\\', '/', $file); + + if (null !== $this->projectDir && 0 === strpos($file, $this->projectDir)) { + return ltrim(substr($file, \strlen($this->projectDir)), '/'); + } + + return null; + } + + /** + * Returns the link for a given file/line pair. + * + * @return string|false A link or false + */ + private function getFileLink(string $file, int $line) + { + if ($fmt = $this->fileLinkFormat) { + return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line); + } + + return false; + } + + /** + * Formats a file path. + * + * @param string $file An absolute file path + * @param int $line The line number + * @param string $text Use this text for the link rather than the file path + */ + private function formatFile(string $file, int $line, string $text = null): string + { + $file = trim($file); + + if (null === $text) { + $text = $file; + if (null !== $rel = $this->getFileRelative($text)) { + $rel = explode('/', $rel, 2); + $text = sprintf('%s%s', $this->projectDir, $rel[0], '/'.($rel[1] ?? '')); + } + } + + if (0 < $line) { + $text .= ' at line '.$line; + } + + if (false !== $link = $this->getFileLink($file, $line)) { + return sprintf('%s', $this->escape($link), $text); + } + + return $text; + } + + /** + * Returns an excerpt of a code file around the given line number. + * + * @param string $file A file path + * @param int $line The selected line number + * @param int $srcContext The number of displayed lines around or -1 for the whole file + * + * @return string An HTML string + */ + private function fileExcerpt(string $file, int $line, int $srcContext = 3): string + { + if (is_file($file) && is_readable($file)) { + // highlight_file could throw warnings + // see https://bugs.php.net/25725 + $code = @highlight_file($file, true); + // remove main code/span tags + $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); + // split multiline spans + $code = preg_replace_callback('#]++)>((?:[^<]*+
    )++[^<]*+)
    #', function ($m) { + return "".str_replace('
    ', "

    ", $m[2]).''; + }, $code); + $content = explode('
    ', $code); + + $lines = []; + if (0 > $srcContext) { + $srcContext = \count($content); + } + + for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, \count($content)); $i <= $max; ++$i) { + $lines[] = ''.$this->fixCodeMarkup($content[$i - 1]).''; + } + + return '
      '.implode("\n", $lines).'
    '; + } + + return ''; + } + + private function fixCodeMarkup(string $line) + { + // ending tag from previous line + $opening = strpos($line, ''); + if (false !== $closing && (false === $opening || $closing < $opening)) { + $line = substr_replace($line, '', $closing, 7); + } + + // missing tag at the end of line + $opening = strpos($line, ''); + if (false !== $opening && (false === $closing || $closing > $opening)) { + $line .= ''; + } + + return trim($line); + } + + private function formatFileFromText(string $text) + { + return preg_replace_callback('/in ("|")?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', function ($match) { + return 'in '.$this->formatFile($match[2], $match[3]); + }, $text); + } + + private function formatLogMessage(string $message, array $context) + { + if ($context && false !== strpos($message, '{')) { + $replacements = []; + foreach ($context as $key => $val) { + if (is_scalar($val)) { + $replacements['{'.$key.'}'] = $val; + } + } + + if ($replacements) { + $message = strtr($message, $replacements); + } + } + + return $this->escape($message); + } + + private function addElementToGhost(): string + { + if (!isset(self::GHOST_ADDONS[date('m-d')])) { + return ''; + } + + return ''; + } + + private function include(string $name, array $context = []): string + { + extract($context, EXTR_SKIP); + ob_start(); + include __DIR__.'/../Resources/'.$name; + + return trim(ob_get_clean()); + } +} diff --git a/vendor/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php b/vendor/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php new file mode 100644 index 0000000..6cc363d --- /dev/null +++ b/vendor/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\ErrorRenderer; + +use Symfony\Component\ErrorHandler\Exception\FlattenException; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\Serializer\Exception\NotEncodableValueException; +use Symfony\Component\Serializer\SerializerInterface; + +/** + * Formats an exception using Serializer for rendering. + * + * @author Nicolas Grekas + */ +class SerializerErrorRenderer implements ErrorRendererInterface +{ + private $serializer; + private $format; + private $fallbackErrorRenderer; + private $debug; + + /** + * @param string|callable(FlattenException) $format The format as a string or a callable that should return it + * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it + */ + public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null, $debug = false) + { + if (!\is_string($format) && !\is_callable($format)) { + throw new \TypeError(sprintf('Argument 2 passed to %s() must be a string or a callable, %s given.', __METHOD__, \is_object($format) ? \get_class($format) : \gettype($format))); + } + + if (!\is_bool($debug) && !\is_callable($debug)) { + throw new \TypeError(sprintf('Argument 4 passed to %s() must be a boolean or a callable, %s given.', __METHOD__, \is_object($debug) ? \get_class($debug) : \gettype($debug))); + } + + $this->serializer = $serializer; + $this->format = $format; + $this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer(); + $this->debug = $debug; + } + + /** + * {@inheritdoc} + */ + public function render(\Throwable $exception): FlattenException + { + $flattenException = FlattenException::createFromThrowable($exception); + + try { + $format = \is_string($this->format) ? $this->format : ($this->format)($flattenException); + + return $flattenException->setAsString($this->serializer->serialize($flattenException, $format, [ + 'exception' => $exception, + 'debug' => \is_bool($this->debug) ? $this->debug : ($this->debug)($exception), + ])); + } catch (NotEncodableValueException $e) { + return $this->fallbackErrorRenderer->render($exception); + } + } + + public static function getPreferredFormat(RequestStack $requestStack): \Closure + { + return static function () use ($requestStack) { + if (!$request = $requestStack->getCurrentRequest()) { + throw new NotEncodableValueException(); + } + + return $request->getPreferredFormat(); + }; + } +} diff --git a/vendor/symfony/error-handler/Exception/FlattenException.php b/vendor/symfony/error-handler/Exception/FlattenException.php new file mode 100644 index 0000000..0cff4cd --- /dev/null +++ b/vendor/symfony/error-handler/Exception/FlattenException.php @@ -0,0 +1,397 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\Exception; + +use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; + +/** + * FlattenException wraps a PHP Error or Exception to be able to serialize it. + * + * Basically, this class removes all objects from the trace. + * + * @author Fabien Potencier + */ +class FlattenException +{ + private $message; + private $code; + private $previous; + private $trace; + private $traceAsString; + private $class; + private $statusCode; + private $statusText; + private $headers; + private $file; + private $line; + private $asString; + + /** + * @return static + */ + public static function create(\Exception $exception, $statusCode = null, array $headers = []): self + { + return static::createFromThrowable($exception, $statusCode, $headers); + } + + /** + * @return static + */ + public static function createFromThrowable(\Throwable $exception, int $statusCode = null, array $headers = []): self + { + $e = new static(); + $e->setMessage($exception->getMessage()); + $e->setCode($exception->getCode()); + + if ($exception instanceof HttpExceptionInterface) { + $statusCode = $exception->getStatusCode(); + $headers = array_merge($headers, $exception->getHeaders()); + } elseif ($exception instanceof RequestExceptionInterface) { + $statusCode = 400; + } + + if (null === $statusCode) { + $statusCode = 500; + } + + if (class_exists(Response::class) && isset(Response::$statusTexts[$statusCode])) { + $statusText = Response::$statusTexts[$statusCode]; + } else { + $statusText = 'Whoops, looks like something went wrong.'; + } + + $e->setStatusText($statusText); + $e->setStatusCode($statusCode); + $e->setHeaders($headers); + $e->setTraceFromThrowable($exception); + $e->setClass(\get_class($exception)); + $e->setFile($exception->getFile()); + $e->setLine($exception->getLine()); + + $previous = $exception->getPrevious(); + + if ($previous instanceof \Throwable) { + $e->setPrevious(static::createFromThrowable($previous)); + } + + return $e; + } + + public function toArray(): array + { + $exceptions = []; + foreach (array_merge([$this], $this->getAllPrevious()) as $exception) { + $exceptions[] = [ + 'message' => $exception->getMessage(), + 'class' => $exception->getClass(), + 'trace' => $exception->getTrace(), + ]; + } + + return $exceptions; + } + + public function getStatusCode(): int + { + return $this->statusCode; + } + + /** + * @return $this + */ + public function setStatusCode($code): self + { + $this->statusCode = $code; + + return $this; + } + + public function getHeaders(): array + { + return $this->headers; + } + + /** + * @return $this + */ + public function setHeaders(array $headers): self + { + $this->headers = $headers; + + return $this; + } + + public function getClass(): string + { + return $this->class; + } + + /** + * @return $this + */ + public function setClass($class): self + { + $this->class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; + + return $this; + } + + public function getFile(): string + { + return $this->file; + } + + /** + * @return $this + */ + public function setFile($file): self + { + $this->file = $file; + + return $this; + } + + public function getLine(): int + { + return $this->line; + } + + /** + * @return $this + */ + public function setLine($line): self + { + $this->line = $line; + + return $this; + } + + public function getStatusText(): string + { + return $this->statusText; + } + + public function setStatusText(string $statusText): self + { + $this->statusText = $statusText; + + return $this; + } + + public function getMessage(): string + { + return $this->message; + } + + /** + * @return $this + */ + public function setMessage($message): self + { + if (false !== strpos($message, "class@anonymous\0")) { + $message = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:)[0-9a-fA-F]++/', function ($m) { + return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0]; + }, $message); + } + + $this->message = $message; + + return $this; + } + + public function getCode(): int + { + return $this->code; + } + + /** + * @return $this + */ + public function setCode($code): self + { + $this->code = $code; + + return $this; + } + + public function getPrevious(): ?self + { + return $this->previous; + } + + /** + * @return $this + */ + public function setPrevious(self $previous): self + { + $this->previous = $previous; + + return $this; + } + + /** + * @return self[] + */ + public function getAllPrevious(): array + { + $exceptions = []; + $e = $this; + while ($e = $e->getPrevious()) { + $exceptions[] = $e; + } + + return $exceptions; + } + + public function getTrace(): array + { + return $this->trace; + } + + /** + * @return $this + */ + public function setTraceFromThrowable(\Throwable $throwable): self + { + $this->traceAsString = $throwable->getTraceAsString(); + + return $this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine()); + } + + /** + * @return $this + */ + public function setTrace($trace, $file, $line): self + { + $this->trace = []; + $this->trace[] = [ + 'namespace' => '', + 'short_class' => '', + 'class' => '', + 'type' => '', + 'function' => '', + 'file' => $file, + 'line' => $line, + 'args' => [], + ]; + foreach ($trace as $entry) { + $class = ''; + $namespace = ''; + if (isset($entry['class'])) { + $parts = explode('\\', $entry['class']); + $class = array_pop($parts); + $namespace = implode('\\', $parts); + } + + $this->trace[] = [ + 'namespace' => $namespace, + 'short_class' => $class, + 'class' => isset($entry['class']) ? $entry['class'] : '', + 'type' => isset($entry['type']) ? $entry['type'] : '', + 'function' => isset($entry['function']) ? $entry['function'] : null, + 'file' => isset($entry['file']) ? $entry['file'] : null, + 'line' => isset($entry['line']) ? $entry['line'] : null, + 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : [], + ]; + } + + return $this; + } + + private function flattenArgs(array $args, int $level = 0, int &$count = 0): array + { + $result = []; + foreach ($args as $key => $value) { + if (++$count > 1e4) { + return ['array', '*SKIPPED over 10000 entries*']; + } + if ($value instanceof \__PHP_Incomplete_Class) { + // is_object() returns false on PHP<=7.1 + $result[$key] = ['incomplete-object', $this->getClassNameFromIncomplete($value)]; + } elseif (\is_object($value)) { + $result[$key] = ['object', \get_class($value)]; + } elseif (\is_array($value)) { + if ($level > 10) { + $result[$key] = ['array', '*DEEP NESTED ARRAY*']; + } else { + $result[$key] = ['array', $this->flattenArgs($value, $level + 1, $count)]; + } + } elseif (null === $value) { + $result[$key] = ['null', null]; + } elseif (\is_bool($value)) { + $result[$key] = ['boolean', $value]; + } elseif (\is_int($value)) { + $result[$key] = ['integer', $value]; + } elseif (\is_float($value)) { + $result[$key] = ['float', $value]; + } elseif (\is_resource($value)) { + $result[$key] = ['resource', get_resource_type($value)]; + } else { + $result[$key] = ['string', (string) $value]; + } + } + + return $result; + } + + private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value): string + { + $array = new \ArrayObject($value); + + return $array['__PHP_Incomplete_Class_Name']; + } + + public function getTraceAsString(): string + { + return $this->traceAsString; + } + + /** + * @return $this + */ + public function setAsString(?string $asString): self + { + $this->asString = $asString; + + return $this; + } + + public function getAsString(): string + { + if (null !== $this->asString) { + return $this->asString; + } + + $message = ''; + $next = false; + + foreach (array_reverse(array_merge([$this], $this->getAllPrevious())) as $exception) { + if ($next) { + $message .= 'Next '; + } else { + $next = true; + } + $message .= $exception->getClass(); + + if ('' != $exception->getMessage()) { + $message .= ': '.$exception->getMessage(); + } + + $message .= ' in '.$exception->getFile().':'.$exception->getLine(). + "\nStack trace:\n".$exception->getTraceAsString()."\n\n"; + } + + return rtrim($message); + } +} diff --git a/vendor/symfony/error-handler/Exception/SilencedErrorContext.php b/vendor/symfony/error-handler/Exception/SilencedErrorContext.php new file mode 100644 index 0000000..18defc7 --- /dev/null +++ b/vendor/symfony/error-handler/Exception/SilencedErrorContext.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler\Exception; + +/** + * Data Object that represents a Silenced Error. + * + * @author Grégoire Pineau + */ +class SilencedErrorContext implements \JsonSerializable +{ + public $count = 1; + + private $severity; + private $file; + private $line; + private $trace; + + public function __construct(int $severity, string $file, int $line, array $trace = [], int $count = 1) + { + $this->severity = $severity; + $this->file = $file; + $this->line = $line; + $this->trace = $trace; + $this->count = $count; + } + + public function getSeverity(): int + { + return $this->severity; + } + + public function getFile(): string + { + return $this->file; + } + + public function getLine(): int + { + return $this->line; + } + + public function getTrace(): array + { + return $this->trace; + } + + public function jsonSerialize(): array + { + return [ + 'severity' => $this->severity, + 'file' => $this->file, + 'line' => $this->line, + 'trace' => $this->trace, + 'count' => $this->count, + ]; + } +} diff --git a/vendor/symfony/error-handler/LICENSE b/vendor/symfony/error-handler/LICENSE new file mode 100644 index 0000000..1a18697 --- /dev/null +++ b/vendor/symfony/error-handler/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/error-handler/README.md b/vendor/symfony/error-handler/README.md new file mode 100644 index 0000000..17e1cfd --- /dev/null +++ b/vendor/symfony/error-handler/README.md @@ -0,0 +1,12 @@ +ErrorHandler Component +====================== + +The ErrorHandler component provides tools to manage errors and ease debugging PHP code. + +Resources +--------- + + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/error-handler/Resources/assets/css/error.css b/vendor/symfony/error-handler/Resources/assets/css/error.css new file mode 100644 index 0000000..332d818 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/css/error.css @@ -0,0 +1,4 @@ +body { background-color: #fff; color: #222; font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 0; } +.container { margin: 30px; max-width: 600px; } +h1 { color: #dc3545; font-size: 24px; } +h2 { font-size: 18px; } diff --git a/vendor/symfony/error-handler/Resources/assets/css/exception.css b/vendor/symfony/error-handler/Resources/assets/css/exception.css new file mode 100644 index 0000000..952c66d --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/css/exception.css @@ -0,0 +1,209 @@ +/* This file is based on WebProfilerBundle/Resources/views/Profiler/profiler.css.twig. + If you make any change in this file, verify the same change is needed in the other file. */ +:root { + --font-sans-serif: Helvetica, Arial, sans-serif; + --page-background: #f9f9f9; + --color-text: #222; + /* when updating any of these colors, do the same in toolbar.css.twig */ + --color-success: #4f805d; + --color-warning: #a46a1f; + --color-error: #b0413e; + --color-muted: #999; + --tab-background: #fff; + --tab-color: #444; + --tab-active-background: #666; + --tab-active-color: #fafafa; + --tab-disabled-background: #f5f5f5; + --tab-disabled-color: #999; + --metric-value-background: #fff; + --metric-value-color: inherit; + --metric-unit-color: #999; + --metric-label-background: #e0e0e0; + --metric-label-color: inherit; + --table-border: #e0e0e0; + --table-background: #fff; + --table-header: #e0e0e0; + --trace-selected-background: #F7E5A1; + --tree-active-background: #F7E5A1; + --exception-title-color: var(--base-2); + --shadow: 0px 0px 1px rgba(128, 128, 128, .2); + --border: 1px solid #e0e0e0; + --background-error: var(--color-error); + --highlight-comment: #969896; + --highlight-default: #222222; + --highlight-keyword: #a71d5d; + --highlight-string: #183691; + --base-0: #fff; + --base-1: #f5f5f5; + --base-2: #e0e0e0; + --base-3: #ccc; + --base-4: #666; + --base-5: #444; + --base-6: #222; +} + +html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0} + +html { + /* always display the vertical scrollbar to avoid jumps when toggling contents */ + overflow-y: scroll; +} +body { background-color: #F9F9F9; color: var(--base-6); font: 14px/1.4 Helvetica, Arial, sans-serif; padding-bottom: 45px; } + +a { cursor: pointer; text-decoration: none; } +a:hover { text-decoration: underline; } +abbr[title] { border-bottom: none; cursor: help; text-decoration: none; } + +code, pre { font: 13px/1.5 Consolas, Monaco, Menlo, "Ubuntu Mono", "Liberation Mono", monospace; } + +table, tr, th, td { background: #FFF; border-collapse: collapse; vertical-align: top; } +table { background: #FFF; border: var(--border); box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; width: 100%; } +table th, table td { border: solid var(--base-2); border-width: 1px 0; padding: 8px 10px; } +table th { background-color: var(--base-2); font-weight: bold; text-align: left; } + +.m-t-5 { margin-top: 5px; } +.hidden-xs-down { display: none; } +.block { display: block; } +.full-width { width: 100%; } +.hidden { display: none; } +.prewrap { white-space: pre-wrap; } +.nowrap { white-space: nowrap; } +.newline { display: block; } +.break-long-words { word-wrap: break-word; overflow-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; min-width: 0; } +.text-small { font-size: 12px !important; } +.text-muted { color: #999; } +.text-bold { font-weight: bold; } +.empty { border: 4px dashed var(--base-2); color: #999; margin: 1em 0; padding: .5em 2em; } + +.status-success { background: rgba(94, 151, 110, 0.3); } +.status-warning { background: rgba(240, 181, 24, 0.3); } +.status-error { background: rgba(176, 65, 62, 0.2); } +.status-success td, .status-warning td, .status-error td { background: transparent; } +tr.status-error td, tr.status-warning td { border-bottom: 1px solid #FAFAFA; border-top: 1px solid #FAFAFA; } +.status-warning .colored { color: #A46A1F; } +.status-error .colored { color: var(--color-error); } + +.sf-toggle { cursor: pointer; } +.sf-toggle-content { -moz-transition: display .25s ease; -webkit-transition: display .25s ease; transition: display .25s ease; } +.sf-toggle-content.sf-toggle-hidden { display: none; } +.sf-toggle-content.sf-toggle-visible { display: block; } +thead.sf-toggle-content.sf-toggle-visible, tbody.sf-toggle-content.sf-toggle-visible { display: table-row-group; } +.sf-toggle-off .icon-close, .sf-toggle-on .icon-open { display: none; } +.sf-toggle-off .icon-open, .sf-toggle-on .icon-close { display: block; } + +.tab-navigation { margin: 0 0 1em 0; padding: 0; } +.tab-navigation li { background: var(--tab-background); border: 1px solid var(--table-border); color: var(--tab-color); cursor: pointer; display: inline-block; font-size: 16px; margin: 0 0 0 -1px; padding: .5em .75em; z-index: 1; } +.tab-navigation li .badge { background-color: var(--base-1); color: var(--base-4); display: inline-block; font-size: 14px; font-weight: bold; margin-left: 8px; min-width: 10px; padding: 1px 6px; text-align: center; white-space: nowrap; } +.tab-navigation li.disabled { background: var(--tab-disabled-background); color: var(--tab-disabled-color); } +.tab-navigation li.active { background: var(--tab-active-background); color: var(--tab-active-color); z-index: 1100; } +.tab-navigation li.active .badge { background-color: var(--base-5); color: var(--base-2); } +.tab-content > *:first-child { margin-top: 0; } +.tab-navigation li .badge.status-warning { background: var(--color-warning); color: #FFF; } +.tab-navigation li .badge.status-error { background: var(--background-error); color: #FFF; } +.sf-tabs .tab:not(:first-child) { display: none; } + +[data-filters] { position: relative; } +[data-filtered] { cursor: pointer; } +[data-filtered]:after { content: '\00a0\25BE'; } +[data-filtered]:hover .filter-list li { display: inline-flex; } +[class*="filter-hidden-"] { display: none; } +.filter-list { position: absolute; border: var(--border); box-shadow: var(--shadow); margin: 0; padding: 0; display: flex; flex-direction: column; } +.filter-list :after { content: ''; } +.filter-list li { + background: var(--tab-disabled-background); + border-bottom: var(--border); + color: var(--tab-disabled-color); + display: none; + list-style: none; + margin: 0; + padding: 5px 10px; + text-align: left; + font-weight: normal; +} +.filter-list li.active { + background: var(--tab-background); + color: var(--tab-color); +} +.filter-list li.last-active { + background: var(--tab-active-background); + color: var(--tab-active-color); +} + +.filter-list-level li { cursor: s-resize; } +.filter-list-level li.active { cursor: n-resize; } +.filter-list-level li.last-active { cursor: default; } +.filter-list-level li.last-active:before { content: '\2714\00a0'; } +.filter-list-choice li:before { content: '\2714\00a0'; color: transparent; } +.filter-list-choice li.active:before { color: unset; } + +.container { max-width: 1024px; margin: 0 auto; padding: 0 15px; } +.container::after { content: ""; display: table; clear: both; } + +header { background-color: var(--base-6); color: rgba(255, 255, 255, 0.75); font-size: 13px; height: 33px; line-height: 33px; padding: 0; } +header .container { display: flex; justify-content: space-between; } +.logo { flex: 1; font-size: 13px; font-weight: normal; margin: 0; padding: 0; } +.logo svg { height: 18px; width: 18px; opacity: .8; vertical-align: -5px; } + +.help-link { margin-left: 15px; } +.help-link a { color: inherit; } +.help-link .icon svg { height: 15px; width: 15px; opacity: .7; vertical-align: -2px; } +.help-link a:hover { color: #EEE; text-decoration: none; } +.help-link a:hover svg { opacity: .9; } + +.exception-summary { background: var(--background-error); border-bottom: 2px solid rgba(0, 0, 0, 0.1); border-top: 1px solid rgba(0, 0, 0, .3); flex: 0 0 auto; margin-bottom: 15px; } +.exception-metadata { background: rgba(0, 0, 0, 0.1); padding: 7px 0; } +.exception-metadata .container { display: flex; flex-direction: row; justify-content: space-between; } +.exception-metadata h2, .exception-metadata h2 > a { color: rgba(255, 255, 255, 0.8); font-size: 13px; font-weight: 400; margin: 0; } +.exception-http small { font-size: 13px; opacity: .7; } +.exception-hierarchy { flex: 1; } +.exception-hierarchy .icon { margin: 0 3px; opacity: .7; } +.exception-hierarchy .icon svg { height: 13px; width: 13px; vertical-align: -2px; } + +.exception-without-message .exception-message-wrapper { display: none; } +.exception-message-wrapper .container { display: flex; align-items: flex-start; min-height: 70px; padding: 10px 15px 8px; } +.exception-message { flex-grow: 1; } +.exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; } +.exception-message.long { font-size: 18px; } +.exception-message a { border-bottom: 1px solid rgba(255, 255, 255, 0.5); font-size: inherit; text-decoration: none; } +.exception-message a:hover { border-bottom-color: #ffffff; } + +.exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; } + +.trace + .trace { margin-top: 30px; } +.trace-head { background-color: var(--base-2); padding: 10px; position: relative; } +.trace-head .trace-class { color: var(--base-6); font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; } +.trace-head .trace-namespace { color: #999; display: block; font-size: 13px; } +.trace-head .icon { position: absolute; right: 0; top: 0; } +.trace-head .icon svg { height: 24px; width: 24px; } + +.trace-details { background: var(--base-0); border: var(--border); box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; table-layout: fixed; } + +.trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; } + +.trace-line { position: relative; padding-top: 8px; padding-bottom: 8px; } +.trace-line + .trace-line { border-top: var(--border); } +.trace-line:hover { background: var(--base-1); } +.trace-line a { color: var(--base-6); } +.trace-line .icon { opacity: .4; position: absolute; left: 10px; top: 11px; } +.trace-line .icon svg { height: 16px; width: 16px; } +.trace-line-header { padding-left: 36px; padding-right: 10px; } + +.trace-file-path, .trace-file-path a { color: var(--base-6); font-size: 13px; } +.trace-class { color: var(--color-error); } +.trace-type { padding: 0 2px; } +.trace-method { color: var(--color-error); font-weight: bold; } +.trace-arguments { color: #777; font-weight: normal; padding-left: 2px; } + +.trace-code { background: var(--base-0); font-size: 12px; margin: 10px 10px 2px 10px; padding: 10px; overflow-x: auto; white-space: nowrap; } +.trace-code ol { margin: 0; float: left; } +.trace-code li { color: #969896; margin: 0; padding-left: 10px; float: left; width: 100%; } +.trace-code li + li { margin-top: 5px; } +.trace-code li.selected { background: var(--trace-selected-background); margin-top: 2px; } +.trace-code li code { color: var(--base-6); white-space: nowrap; } + +.trace-as-text .stacktrace { line-height: 1.8; margin: 0 0 15px; white-space: pre-wrap; } + +@media (min-width: 575px) { + .hidden-xs-down { display: initial; } + .help-link { margin-left: 30px; } +} diff --git a/vendor/symfony/error-handler/Resources/assets/css/exception_full.css b/vendor/symfony/error-handler/Resources/assets/css/exception_full.css new file mode 100644 index 0000000..fa77cb3 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/css/exception_full.css @@ -0,0 +1,128 @@ +.sf-reset .traces { + padding-bottom: 14px; +} +.sf-reset .traces li { + font-size: 12px; + color: #868686; + padding: 5px 4px; + list-style-type: decimal; + margin-left: 20px; +} +.sf-reset #logs .traces li.error { + font-style: normal; + color: #AA3333; + background: #f9ecec; +} +.sf-reset #logs .traces li.warning { + font-style: normal; + background: #ffcc00; +} +/* fix for Opera not liking empty
  • */ +.sf-reset .traces li:after { + content: "\00A0"; +} +.sf-reset .trace { + border: 1px solid #D3D3D3; + padding: 10px; + overflow: auto; + margin: 10px 0 20px; +} +.sf-reset .block-exception { + -moz-border-radius: 16px; + -webkit-border-radius: 16px; + border-radius: 16px; + margin-bottom: 20px; + background-color: #f6f6f6; + border: 1px solid #dfdfdf; + padding: 30px 28px; + word-wrap: break-word; + overflow: hidden; +} +.sf-reset .block-exception div { + color: #313131; + font-size: 10px; +} +.sf-reset .block-exception-detected .illustration-exception, +.sf-reset .block-exception-detected .text-exception { + float: left; +} +.sf-reset .block-exception-detected .illustration-exception { + width: 152px; +} +.sf-reset .block-exception-detected .text-exception { + width: 670px; + padding: 30px 44px 24px 46px; + position: relative; +} +.sf-reset .text-exception .open-quote, +.sf-reset .text-exception .close-quote { + font-family: Arial, Helvetica, sans-serif; + position: absolute; + color: #C9C9C9; + font-size: 8em; +} +.sf-reset .open-quote { + top: 0; + left: 0; +} +.sf-reset .close-quote { + bottom: -0.5em; + right: 50px; +} +.sf-reset .block-exception p { + font-family: Arial, Helvetica, sans-serif; +} +.sf-reset .block-exception p a, +.sf-reset .block-exception p a:hover { + color: #565656; +} +.sf-reset .logs h2 { + float: left; + width: 654px; +} +.sf-reset .error-count, .sf-reset .support { + float: right; + width: 170px; + text-align: right; +} +.sf-reset .error-count span { + display: inline-block; + background-color: #aacd4e; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; + padding: 4px; + color: white; + margin-right: 2px; + font-size: 11px; + font-weight: bold; +} + +.sf-reset .support a { + display: inline-block; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; + padding: 4px; + color: #000000; + margin-right: 2px; + font-size: 11px; + font-weight: bold; +} + +.sf-reset .toggle { + vertical-align: middle; +} +.sf-reset .linked ul, +.sf-reset .linked li { + display: inline; +} +.sf-reset #output-content { + color: #000; + font-size: 12px; +} +.sf-reset #traces-text pre { + white-space: pre; + font-size: 12px; + font-family: monospace; +} diff --git a/vendor/symfony/error-handler/Resources/assets/images/chevron-right.svg b/vendor/symfony/error-handler/Resources/assets/images/chevron-right.svg new file mode 100644 index 0000000..6837aff --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/images/chevron-right.svg @@ -0,0 +1 @@ + diff --git a/vendor/symfony/error-handler/Resources/assets/images/favicon.png.base64 b/vendor/symfony/error-handler/Resources/assets/images/favicon.png.base64 new file mode 100644 index 0000000..fb076ed --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/images/favicon.png.base64 @@ -0,0 +1 @@ +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAgCAYAAAABtRhCAAADVUlEQVRIx82XX0jTURTHLYPyqZdefQx66CEo80+aYpoIkqzUikz6Z5klQoWUWYRIJYEUGpQ+lIr9U5dOTLdCtkmWZis3rbnC5fw/neYW002307mX/cZvP3/7o1PwwOdh95x7vnf39zvnd29AgBer2xO6DclAXiMqZAqxIiNIN/IYSUS2BPhjmGATchUxI+ADWiRhpWK7HKuHFVBFdmU5YvnI4grFGCaReF/EBH4KsZlGgj2JBTuCYBWRIYF8YoEOJ6wBt/gEs7mBbyOjQXruPLSdOgPCiEiPSUUHDoL8Ug5IUo9B/d5wrt+G7OAKNrODPuVdB6vRCIzN6SdBlpW9RIgk/1FeAXabzRlrUPVCS/JhbmwudztnGeeH9AyXBIwtmM3wLinZJZHifjHw2V+NBoRh+9ixQrbgbnaSIcl7cGea6hoXQbNe7za241oeO5Z0p42M4BV2EqP2D50wo+6HzvwC6C4sApNOR8cmOrtcnhtj2kYRyC9eBvXzKrBZrXSs72kFd1t3MoKVbMekQkEnSNKOO8fac3LpmK6l1TlGtsxmsdKFsecPYgwxst0cwROMYDXboSotg0WLBRqjY51jLYcENElXwW2XJKPydvoI2GN9T8rBtrAArYIUruBJXkFheCQYlCpQP6uk5dAQFQNaUROMSGVQFxLmkoQsxDJrhLbTZ+nvVsERME9MgPJRKV/58AsyomTSzE813WLFvWK++qI0xSfQl8k8Pg46sYRuv5t6dS+4RqxDwaa4BGjYH+NTQvKScIp9+YL/hoZh3jDtLRHtt2C3g6bmhX+CpsFBWg7ilDSPgj0lD2ncr5ev/BP8VvyAJhqVyZeUhPOrEhEFxgEtjft846Z/guQTNT89Q5P9flMLoth4F7808wKtWWKzAwNQHxrh/1vaid2F+XpYTSbQf1XA2McOmOpROnvpvMEA4tSjq1cW0sws2gCYxswY6TKkvzYnJq1NHZLnRU4BX+4U0uburvusu8Kv8iHY7qefkM4IFngJHEOUXmLEPgiGsI8YnlZILit3vSSLRTQe/MPIZva5pshNIEmyFQlCvruJKXPkCEfmePzkphXHdzZNQdoRI9KPlBAxlj/I8U97ERPS5bjGbWDFbEdqHVe5caTBeZZx2H/IMvzeN15yoQAAAABJRU5ErkJggg== diff --git a/vendor/symfony/error-handler/Resources/assets/images/icon-book.svg b/vendor/symfony/error-handler/Resources/assets/images/icon-book.svg new file mode 100644 index 0000000..498a74f --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/images/icon-book.svg @@ -0,0 +1 @@ + diff --git a/vendor/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg b/vendor/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg new file mode 100644 index 0000000..be534ad --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg @@ -0,0 +1 @@ + diff --git a/vendor/symfony/error-handler/Resources/assets/images/icon-minus-square.svg b/vendor/symfony/error-handler/Resources/assets/images/icon-minus-square.svg new file mode 100644 index 0000000..471c274 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/images/icon-minus-square.svg @@ -0,0 +1 @@ + diff --git a/vendor/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg b/vendor/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg new file mode 100644 index 0000000..b2593a9 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg @@ -0,0 +1 @@ + diff --git a/vendor/symfony/error-handler/Resources/assets/images/icon-plus-square.svg b/vendor/symfony/error-handler/Resources/assets/images/icon-plus-square.svg new file mode 100644 index 0000000..2f5c3b3 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/images/icon-plus-square.svg @@ -0,0 +1 @@ + diff --git a/vendor/symfony/error-handler/Resources/assets/images/icon-support.svg b/vendor/symfony/error-handler/Resources/assets/images/icon-support.svg new file mode 100644 index 0000000..03fd8e7 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/images/icon-support.svg @@ -0,0 +1 @@ + diff --git a/vendor/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php b/vendor/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php new file mode 100644 index 0000000..4b2f9c1 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php @@ -0,0 +1 @@ +addElementToGhost(); ?> diff --git a/vendor/symfony/error-handler/Resources/assets/images/symfony-logo.svg b/vendor/symfony/error-handler/Resources/assets/images/symfony-logo.svg new file mode 100644 index 0000000..f10824a --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/images/symfony-logo.svg @@ -0,0 +1 @@ + diff --git a/vendor/symfony/error-handler/Resources/assets/js/exception.js b/vendor/symfony/error-handler/Resources/assets/js/exception.js new file mode 100644 index 0000000..8cc7b53 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/assets/js/exception.js @@ -0,0 +1,279 @@ +/* This file is based on WebProfilerBundle/Resources/views/Profiler/base_js.html.twig. + If you make any change in this file, verify the same change is needed in the other file. */ +/* .tab'); + var tabNavigation = document.createElement('ul'); + tabNavigation.className = 'tab-navigation'; + + var selectedTabId = 'tab-' + i + '-0'; /* select the first tab by default */ + for (var j = 0; j < tabs.length; j++) { + var tabId = 'tab-' + i + '-' + j; + var tabTitle = tabs[j].querySelector('.tab-title').innerHTML; + + var tabNavigationItem = document.createElement('li'); + tabNavigationItem.setAttribute('data-tab-id', tabId); + if (hasClass(tabs[j], 'active')) { selectedTabId = tabId; } + if (hasClass(tabs[j], 'disabled')) { addClass(tabNavigationItem, 'disabled'); } + tabNavigationItem.innerHTML = tabTitle; + tabNavigation.appendChild(tabNavigationItem); + + var tabContent = tabs[j].querySelector('.tab-content'); + tabContent.parentElement.setAttribute('id', tabId); + } + + tabGroups[i].insertBefore(tabNavigation, tabGroups[i].firstChild); + addClass(document.querySelector('[data-tab-id="' + selectedTabId + '"]'), 'active'); + } + + /* display the active tab and add the 'click' event listeners */ + for (i = 0; i < tabGroups.length; i++) { + tabNavigation = tabGroups[i].querySelectorAll(':scope >.tab-navigation li'); + + for (j = 0; j < tabNavigation.length; j++) { + tabId = tabNavigation[j].getAttribute('data-tab-id'); + document.getElementById(tabId).querySelector('.tab-title').className = 'hidden'; + + if (hasClass(tabNavigation[j], 'active')) { + document.getElementById(tabId).className = 'block'; + } else { + document.getElementById(tabId).className = 'hidden'; + } + + tabNavigation[j].addEventListener('click', function(e) { + var activeTab = e.target || e.srcElement; + + /* needed because when the tab contains HTML contents, user can click */ + /* on any of those elements instead of their parent '
  • ' element */ + while (activeTab.tagName.toLowerCase() !== 'li') { + activeTab = activeTab.parentNode; + } + + /* get the full list of tabs through the parent of the active tab element */ + var tabNavigation = activeTab.parentNode.children; + for (var k = 0; k < tabNavigation.length; k++) { + var tabId = tabNavigation[k].getAttribute('data-tab-id'); + document.getElementById(tabId).className = 'hidden'; + removeClass(tabNavigation[k], 'active'); + } + + addClass(activeTab, 'active'); + var activeTabId = activeTab.getAttribute('data-tab-id'); + document.getElementById(activeTabId).className = 'block'; + }); + } + + tabGroups[i].setAttribute('data-processed', 'true'); + } + }, + + createToggles: function() { + var toggles = document.querySelectorAll('.sf-toggle:not([data-processed=true])'); + + for (var i = 0; i < toggles.length; i++) { + var elementSelector = toggles[i].getAttribute('data-toggle-selector'); + var element = document.querySelector(elementSelector); + + addClass(element, 'sf-toggle-content'); + + if (toggles[i].hasAttribute('data-toggle-initial') && toggles[i].getAttribute('data-toggle-initial') == 'display') { + addClass(toggles[i], 'sf-toggle-on'); + addClass(element, 'sf-toggle-visible'); + } else { + addClass(toggles[i], 'sf-toggle-off'); + addClass(element, 'sf-toggle-hidden'); + } + + addEventListener(toggles[i], 'click', function(e) { + e.preventDefault(); + + if ('' !== window.getSelection().toString()) { + /* Don't do anything on text selection */ + return; + } + + var toggle = e.target || e.srcElement; + + /* needed because when the toggle contains HTML contents, user can click */ + /* on any of those elements instead of their parent '.sf-toggle' element */ + while (!hasClass(toggle, 'sf-toggle')) { + toggle = toggle.parentNode; + } + + var element = document.querySelector(toggle.getAttribute('data-toggle-selector')); + + toggleClass(toggle, 'sf-toggle-on'); + toggleClass(toggle, 'sf-toggle-off'); + toggleClass(element, 'sf-toggle-hidden'); + toggleClass(element, 'sf-toggle-visible'); + + /* the toggle doesn't change its contents when clicking on it */ + if (!toggle.hasAttribute('data-toggle-alt-content')) { + return; + } + + if (!toggle.hasAttribute('data-toggle-original-content')) { + toggle.setAttribute('data-toggle-original-content', toggle.innerHTML); + } + + var currentContent = toggle.innerHTML; + var originalContent = toggle.getAttribute('data-toggle-original-content'); + var altContent = toggle.getAttribute('data-toggle-alt-content'); + toggle.innerHTML = currentContent !== altContent ? altContent : originalContent; + }); + + /* Prevents from disallowing clicks on links inside toggles */ + var toggleLinks = toggles[i].querySelectorAll('a'); + for (var j = 0; j < toggleLinks.length; j++) { + addEventListener(toggleLinks[j], 'click', function(e) { + e.stopPropagation(); + }); + } + + toggles[i].setAttribute('data-processed', 'true'); + } + }, + + createFilters: function() { + document.querySelectorAll('[data-filters] [data-filter]').forEach(function (filter) { + var filters = filter.closest('[data-filters]'), + type = 'choice', + name = filter.dataset.filter, + ucName = name.charAt(0).toUpperCase()+name.slice(1), + list = document.createElement('ul'), + values = filters.dataset['filter'+ucName] || filters.querySelectorAll('[data-filter-'+name+']'), + labels = {}, + defaults = null, + indexed = {}, + processed = {}; + if (typeof values === 'string') { + type = 'level'; + labels = values.split(','); + values = values.toLowerCase().split(','); + defaults = values.length - 1; + } + addClass(list, 'filter-list'); + addClass(list, 'filter-list-'+type); + values.forEach(function (value, i) { + if (value instanceof HTMLElement) { + value = value.dataset['filter'+ucName]; + } + if (value in processed) { + return; + } + var option = document.createElement('li'), + label = i in labels ? labels[i] : value, + active = false, + matches; + if ('' === label) { + option.innerHTML = '(none)'; + } else { + option.innerText = label; + } + option.dataset.filter = value; + option.setAttribute('title', 1 === (matches = filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').length) ? 'Matches 1 row' : 'Matches '+matches+' rows'); + indexed[value] = i; + list.appendChild(option); + addEventListener(option, 'click', function () { + if ('choice' === type) { + filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) { + if (option.dataset.filter === row.dataset['filter'+ucName]) { + toggleClass(row, 'filter-hidden-'+name); + } + }); + toggleClass(option, 'active'); + } else if ('level' === type) { + if (i === this.parentNode.querySelectorAll('.active').length - 1) { + return; + } + this.parentNode.querySelectorAll('li').forEach(function (currentOption, j) { + if (j <= i) { + addClass(currentOption, 'active'); + if (i === j) { + addClass(currentOption, 'last-active'); + } else { + removeClass(currentOption, 'last-active'); + } + } else { + removeClass(currentOption, 'active'); + removeClass(currentOption, 'last-active'); + } + }); + filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) { + if (i < indexed[row.dataset['filter'+ucName]]) { + addClass(row, 'filter-hidden-'+name); + } else { + removeClass(row, 'filter-hidden-'+name); + } + }); + } + }); + if ('choice' === type) { + active = null === defaults || 0 <= defaults.indexOf(value); + } else if ('level' === type) { + active = i <= defaults; + if (active && i === defaults) { + addClass(option, 'last-active'); + } + } + if (active) { + addClass(option, 'active'); + } else { + filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').forEach(function (row) { + toggleClass(row, 'filter-hidden-'+name); + }); + } + processed[value] = true; + }); + + if (1 < list.childNodes.length) { + filter.appendChild(list); + filter.dataset.filtered = ''; + } + }); + } + }; +})(); + +Sfjs.addEventListener(document, 'DOMContentLoaded', function() { + Sfjs.createTabs(); + Sfjs.createToggles(); + Sfjs.createFilters(); +}); + +/*]]>*/ diff --git a/vendor/symfony/error-handler/Resources/views/error.html.php b/vendor/symfony/error-handler/Resources/views/error.html.php new file mode 100644 index 0000000..5416d03 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/views/error.html.php @@ -0,0 +1,20 @@ + + + + + + An Error Occurred: <?= $statusText; ?> + + + +
    +

    Oops! An Error Occurred

    +

    The server returned a " ".

    + +

    + Something is broken. Please let us know what you were doing when this error occurred. + We will fix it as soon as possible. Sorry for any inconvenience caused. +

    +
    + + diff --git a/vendor/symfony/error-handler/Resources/views/exception.html.php b/vendor/symfony/error-handler/Resources/views/exception.html.php new file mode 100644 index 0000000..b470b56 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/views/exception.html.php @@ -0,0 +1,116 @@ +
    + + +
    +
    +

    formatFileFromText(nl2br($exceptionMessage)); ?>

    + +
    + include('assets/images/symfony-ghost.svg.php'); ?> +
    +
    +
    +
    + +
    +
    +
    + toArray(); + $exceptionWithUserCode = []; + $exceptionAsArrayCount = count($exceptionAsArray); + $last = count($exceptionAsArray) - 1; + foreach ($exceptionAsArray as $i => $e) { + foreach ($e['trace'] as $trace) { + if ($trace['file'] && false === mb_strpos($trace['file'], '/vendor/') && false === mb_strpos($trace['file'], '/var/cache/') && $i < $last) { + $exceptionWithUserCode[] = $i; + } + } + } + ?> +

    + 1) { ?> + Exceptions + + Exception + +

    + +
    + $e) { + echo $this->include('views/traces.html.php', [ + 'exception' => $e, + 'index' => $i + 1, + 'expand' => in_array($i, $exceptionWithUserCode, true) || ([] === $exceptionWithUserCode && 0 === $i), + ]); + } + ?> +
    +
    + + +
    +

    + Logs + countErrors()) { ?>countErrors(); ?> +

    + +
    + getLogs()) { ?> + include('views/logs.html.php', ['logs' => $logger->getLogs()]); ?> + +
    +

    No log messages

    +
    + +
    +
    + + +
    +

    + 1) { ?> + Stack Traces + + Stack Trace + +

    + +
    + $e) { + echo $this->include('views/traces_text.html.php', [ + 'exception' => $e, + 'index' => $i + 1, + 'numExceptions' => $exceptionAsArrayCount, + ]); + } + ?> +
    +
    + + +
    +

    Output content

    + +
    + +
    +
    + +
    +
    diff --git a/vendor/symfony/error-handler/Resources/views/exception_full.html.php b/vendor/symfony/error-handler/Resources/views/exception_full.html.php new file mode 100644 index 0000000..4d46d59 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/views/exception_full.html.php @@ -0,0 +1,43 @@ + + + + + + + + <?= $_message; ?> + + + + + + +
    + +
    + + + include('views/exception.html.php', $context); ?> + + + + + diff --git a/vendor/symfony/error-handler/Resources/views/logs.html.php b/vendor/symfony/error-handler/Resources/views/logs.html.php new file mode 100644 index 0000000..c866e06 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/views/logs.html.php @@ -0,0 +1,45 @@ + + + + + + + + + + + + = 400) { + $status = 'error'; + } elseif ($log['priority'] >= 300) { + $status = 'warning'; + } else { + $severity = 0; + if (($exception = $log['context']['exception'] ?? null) instanceof \ErrorException) { + $severity = $exception->getSeverity(); + } + $status = E_DEPRECATED === $severity || E_USER_DEPRECATED === $severity ? 'warning' : 'normal'; + } ?> + data-filter-channel="escape($log['channel']); ?>"> + + + + + + + + +
    LevelChannelMessage
    + escape($log['priorityName']); ?> + + + escape($log['channel']); ?> + + formatLogMessage($log['message'], $log['context']); ?> + +
    + +
    diff --git a/vendor/symfony/error-handler/Resources/views/trace.html.php b/vendor/symfony/error-handler/Resources/views/trace.html.php new file mode 100644 index 0000000..153f7d6 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/views/trace.html.php @@ -0,0 +1,40 @@ +
    + + include('assets/images/icon-minus-square.svg'); ?> + include('assets/images/icon-plus-square.svg'); ?> + + + + abbrClass($trace['class']); ?>(formatArgs($trace['args']); ?>) + + + + getFileLink($trace['file'], $lineNumber); + $filePath = strtr(strip_tags($this->formatFile($trace['file'], $lineNumber)), [' at line '.$lineNumber => '']); + $filePathParts = explode(DIRECTORY_SEPARATOR, $filePath); + ?> + + in + + + + + + + + (line ) + + +
    + +
    + fileExcerpt($trace['file'], $trace['line'], 5), [ + '#DD0000' => 'var(--highlight-string)', + '#007700' => 'var(--highlight-keyword)', + '#0000BB' => 'var(--highlight-default)', + '#FF8000' => 'var(--highlight-comment)', + ]); ?> +
    + diff --git a/vendor/symfony/error-handler/Resources/views/traces.html.php b/vendor/symfony/error-handler/Resources/views/traces.html.php new file mode 100644 index 0000000..d587b05 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/views/traces.html.php @@ -0,0 +1,42 @@ +
    +
    +
    + +

    + include('assets/images/icon-minus-square-o.svg'); ?> + include('assets/images/icon-plus-square-o.svg'); ?> + + + 1 ? '\\' : ''; ?> + + +

    + + 1) { ?> +

    escape($exception['message']); ?>

    + +
    +
    + +
    + $trace) { + $isVendorTrace = $trace['file'] && (false !== mb_strpos($trace['file'], '/vendor/') || false !== mb_strpos($trace['file'], '/var/cache/')); + $displayCodeSnippet = $isFirstUserCode && !$isVendorTrace; + if ($displayCodeSnippet) { + $isFirstUserCode = false; + } ?> +
    + include('views/trace.html.php', [ + 'prefix' => $index, + 'i' => $i, + 'trace' => $trace, + 'style' => $isVendorTrace ? 'compact' : ($displayCodeSnippet ? 'expanded' : ''), + ]); ?> +
    + +
    +
    +
    diff --git a/vendor/symfony/error-handler/Resources/views/traces_text.html.php b/vendor/symfony/error-handler/Resources/views/traces_text.html.php new file mode 100644 index 0000000..e178fe0 --- /dev/null +++ b/vendor/symfony/error-handler/Resources/views/traces_text.html.php @@ -0,0 +1,43 @@ + + + + + + + + + + + + +
    +

    + 1) { ?> + [/] + + + include('assets/images/icon-minus-square-o.svg'); ?> + include('assets/images/icon-plus-square-o.svg'); ?> +

    +
    + +
    +formatArgsAsText($trace['args']) : '').')';
    +                        }
    +                        if ($trace['file'] && $trace['line']) {
    +                            echo($trace['function'] ? "\n     (" : 'at ').strtr(strip_tags($this->formatFile($trace['file'], $trace['line'])), [' at line '.$trace['line'] => '']).':'.$trace['line'].($trace['function'] ? ')' : '');
    +                        }
    +                    }
    +?>
    +                
    + +
    diff --git a/vendor/symfony/error-handler/ThrowableUtils.php b/vendor/symfony/error-handler/ThrowableUtils.php new file mode 100644 index 0000000..5cbe87f --- /dev/null +++ b/vendor/symfony/error-handler/ThrowableUtils.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ErrorHandler; + +/** + * @internal + */ +class ThrowableUtils +{ + public static function getSeverity(\Throwable $throwable): int + { + if ($throwable instanceof \ErrorException) { + return $throwable->getSeverity(); + } + + if ($throwable instanceof \ParseError) { + return E_PARSE; + } + + if ($throwable instanceof \TypeError) { + return E_RECOVERABLE_ERROR; + } + + return E_ERROR; + } +} diff --git a/vendor/symfony/error-handler/composer.json b/vendor/symfony/error-handler/composer.json new file mode 100644 index 0000000..3ca2724 --- /dev/null +++ b/vendor/symfony/error-handler/composer.json @@ -0,0 +1,39 @@ +{ + "name": "symfony/error-handler", + "type": "library", + "description": "Symfony ErrorHandler Component", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "psr/log": "^1.0", + "symfony/var-dumper": "^4.4|^5.0" + }, + "require-dev": { + "symfony/http-kernel": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\ErrorHandler\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/event-dispatcher-contracts/.gitignore b/vendor/symfony/event-dispatcher-contracts/.gitignore new file mode 100644 index 0000000..c49a5d8 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/vendor/symfony/event-dispatcher-contracts/Event.php b/vendor/symfony/event-dispatcher-contracts/Event.php new file mode 100644 index 0000000..46dcb2b --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/Event.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\EventDispatcher; + +use Psr\EventDispatcher\StoppableEventInterface; + +/** + * Event 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. + * + * You can call the method stopPropagation() to abort the execution of + * further listeners in your event listener. + * + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Bernhard Schussek + * @author Nicolas Grekas + */ +class Event implements StoppableEventInterface +{ + private $propagationStopped = false; + + /** + * {@inheritdoc} + */ + public function isPropagationStopped(): bool + { + return $this->propagationStopped; + } + + /** + * Stops the propagation of the event to further event listeners. + * + * If multiple event listeners are connected to the same event, no + * further event listener will be triggered once any trigger calls + * stopPropagation(). + */ + public function stopPropagation(): void + { + $this->propagationStopped = true; + } +} diff --git a/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php b/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php new file mode 100644 index 0000000..351dc51 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\EventDispatcher; + +use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface; + +/** + * Allows providing hooks on domain-specific lifecycles by dispatching events. + */ +interface EventDispatcherInterface extends PsrEventDispatcherInterface +{ + /** + * Dispatches an event to all registered listeners. + * + * @param object $event The event to pass to the event handlers/listeners + * @param string|null $eventName The name of the event to dispatch. If not supplied, + * the class of $event should be used instead. + * + * @return object The passed $event MUST be returned + */ + public function dispatch(object $event, string $eventName = null): object; +} diff --git a/vendor/symfony/event-dispatcher-contracts/LICENSE b/vendor/symfony/event-dispatcher-contracts/LICENSE new file mode 100644 index 0000000..3f853aa --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/event-dispatcher-contracts/README.md b/vendor/symfony/event-dispatcher-contracts/README.md new file mode 100644 index 0000000..fb051c7 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/README.md @@ -0,0 +1,9 @@ +Symfony EventDispatcher Contracts +================================= + +A set of abstractions extracted out of the Symfony components. + +Can be used to build on semantics that the Symfony components proved useful - and +that already have battle tested implementations. + +See https://github.com/symfony/contracts/blob/master/README.md for more information. diff --git a/vendor/symfony/event-dispatcher-contracts/composer.json b/vendor/symfony/event-dispatcher-contracts/composer.json new file mode 100644 index 0000000..f7ba8f1 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/composer.json @@ -0,0 +1,34 @@ +{ + "name": "symfony/event-dispatcher-contracts", + "type": "library", + "description": "Generic abstractions related to dispatching event", + "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "autoload": { + "psr-4": { "Symfony\\Contracts\\EventDispatcher\\": "" } + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + } +} diff --git a/vendor/symfony/event-dispatcher/.gitattributes b/vendor/symfony/event-dispatcher/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/event-dispatcher/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/event-dispatcher/CHANGELOG.md b/vendor/symfony/event-dispatcher/CHANGELOG.md new file mode 100644 index 0000000..ce30074 --- /dev/null +++ b/vendor/symfony/event-dispatcher/CHANGELOG.md @@ -0,0 +1,75 @@ +CHANGELOG +========= + +5.0.0 +----- + + * The signature of the `EventDispatcherInterface::dispatch()` method has been changed to `dispatch($event, string $eventName = null): object`. + * The `Event` class has been removed in favor of `Symfony\Contracts\EventDispatcher\Event`. + * The `TraceableEventDispatcherInterface` has been removed. + * The `WrappedListener` class is now final. + +4.4.0 +----- + + * `AddEventAliasesPass` has been added, allowing applications and bundles to extend the event alias mapping used by `RegisterListenersPass`. + * Made the `event` attribute of the `kernel.event_listener` tag optional for FQCN events. + +4.3.0 +----- + + * The signature of the `EventDispatcherInterface::dispatch()` method should be updated to `dispatch($event, string $eventName = null)`, not doing so is deprecated + * deprecated the `Event` class, use `Symfony\Contracts\EventDispatcher\Event` instead + +4.1.0 +----- + + * added support for invokable event listeners tagged with `kernel.event_listener` by default + * The `TraceableEventDispatcher::getOrphanedEvents()` method has been added. + * The `TraceableEventDispatcherInterface` has been deprecated. + +4.0.0 +----- + + * removed the `ContainerAwareEventDispatcher` class + * added the `reset()` method to the `TraceableEventDispatcherInterface` + +3.4.0 +----- + + * Implementing `TraceableEventDispatcherInterface` without the `reset()` method has been deprecated. + +3.3.0 +----- + + * The ContainerAwareEventDispatcher class has been deprecated. Use EventDispatcher with closure factories instead. + +3.0.0 +----- + + * The method `getListenerPriority($eventName, $listener)` has been added to the + `EventDispatcherInterface`. + * The methods `Event::setDispatcher()`, `Event::getDispatcher()`, `Event::setName()` + and `Event::getName()` have been removed. + The event dispatcher and the event name are passed to the listener call. + +2.5.0 +----- + + * added Debug\TraceableEventDispatcher (originally in HttpKernel) + * changed Debug\TraceableEventDispatcherInterface to extend EventDispatcherInterface + * added RegisterListenersPass (originally in HttpKernel) + +2.1.0 +----- + + * added TraceableEventDispatcherInterface + * added ContainerAwareEventDispatcher + * added a reference to the EventDispatcher on the Event + * added a reference to the Event name on the event + * added fluid interface to the dispatch() method which now returns the Event + object + * added GenericEvent event class + * added the possibility for subscribers to subscribe several times for the + same event + * added ImmutableEventDispatcher diff --git a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php new file mode 100644 index 0000000..11dce48 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php @@ -0,0 +1,363 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Debug; + +use Psr\EventDispatcher\StoppableEventInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Contracts\Service\ResetInterface; + +/** + * Collects some data about event listeners. + * + * This event dispatcher delegates the dispatching to another one. + * + * @author Fabien Potencier + */ +class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterface +{ + protected $logger; + protected $stopwatch; + + private $callStack; + private $dispatcher; + private $wrappedListeners; + private $orphanedEvents; + private $requestStack; + private $currentRequestHash = ''; + + public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null, RequestStack $requestStack = null) + { + $this->dispatcher = $dispatcher; + $this->stopwatch = $stopwatch; + $this->logger = $logger; + $this->wrappedListeners = []; + $this->orphanedEvents = []; + $this->requestStack = $requestStack; + } + + /** + * {@inheritdoc} + */ + public function addListener(string $eventName, $listener, int $priority = 0) + { + $this->dispatcher->addListener($eventName, $listener, $priority); + } + + /** + * {@inheritdoc} + */ + public function addSubscriber(EventSubscriberInterface $subscriber) + { + $this->dispatcher->addSubscriber($subscriber); + } + + /** + * {@inheritdoc} + */ + public function removeListener(string $eventName, $listener) + { + if (isset($this->wrappedListeners[$eventName])) { + foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { + if ($wrappedListener->getWrappedListener() === $listener) { + $listener = $wrappedListener; + unset($this->wrappedListeners[$eventName][$index]); + break; + } + } + } + + return $this->dispatcher->removeListener($eventName, $listener); + } + + /** + * {@inheritdoc} + */ + public function removeSubscriber(EventSubscriberInterface $subscriber) + { + return $this->dispatcher->removeSubscriber($subscriber); + } + + /** + * {@inheritdoc} + */ + public function getListeners(string $eventName = null) + { + return $this->dispatcher->getListeners($eventName); + } + + /** + * {@inheritdoc} + */ + public function getListenerPriority(string $eventName, $listener) + { + // we might have wrapped listeners for the event (if called while dispatching) + // in that case get the priority by wrapper + if (isset($this->wrappedListeners[$eventName])) { + foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { + if ($wrappedListener->getWrappedListener() === $listener) { + return $this->dispatcher->getListenerPriority($eventName, $wrappedListener); + } + } + } + + return $this->dispatcher->getListenerPriority($eventName, $listener); + } + + /** + * {@inheritdoc} + */ + public function hasListeners(string $eventName = null) + { + return $this->dispatcher->hasListeners($eventName); + } + + /** + * {@inheritdoc} + */ + public function dispatch(object $event, string $eventName = null): object + { + $eventName = $eventName ?? \get_class($event); + + if (null === $this->callStack) { + $this->callStack = new \SplObjectStorage(); + } + + $currentRequestHash = $this->currentRequestHash = $this->requestStack && ($request = $this->requestStack->getCurrentRequest()) ? spl_object_hash($request) : ''; + + if (null !== $this->logger && $event instanceof StoppableEventInterface && $event->isPropagationStopped()) { + $this->logger->debug(sprintf('The "%s" event is already stopped. No listeners have been called.', $eventName)); + } + + $this->preProcess($eventName); + try { + $this->beforeDispatch($eventName, $event); + try { + $e = $this->stopwatch->start($eventName, 'section'); + try { + $this->dispatcher->dispatch($event, $eventName); + } finally { + if ($e->isStarted()) { + $e->stop(); + } + } + } finally { + $this->afterDispatch($eventName, $event); + } + } finally { + $this->currentRequestHash = $currentRequestHash; + $this->postProcess($eventName); + } + + return $event; + } + + /** + * @return array + */ + public function getCalledListeners(Request $request = null) + { + if (null === $this->callStack) { + return []; + } + + $hash = $request ? spl_object_hash($request) : null; + $called = []; + foreach ($this->callStack as $listener) { + list($eventName, $requestHash) = $this->callStack->getInfo(); + if (null === $hash || $hash === $requestHash) { + $called[] = $listener->getInfo($eventName); + } + } + + return $called; + } + + /** + * @return array + */ + public function getNotCalledListeners(Request $request = null) + { + try { + $allListeners = $this->getListeners(); + } catch (\Exception $e) { + if (null !== $this->logger) { + $this->logger->info('An exception was thrown while getting the uncalled listeners.', ['exception' => $e]); + } + + // unable to retrieve the uncalled listeners + return []; + } + + $hash = $request ? spl_object_hash($request) : null; + $calledListeners = []; + + if (null !== $this->callStack) { + foreach ($this->callStack as $calledListener) { + list(, $requestHash) = $this->callStack->getInfo(); + + if (null === $hash || $hash === $requestHash) { + $calledListeners[] = $calledListener->getWrappedListener(); + } + } + } + + $notCalled = []; + foreach ($allListeners as $eventName => $listeners) { + foreach ($listeners as $listener) { + if (!\in_array($listener, $calledListeners, true)) { + if (!$listener instanceof WrappedListener) { + $listener = new WrappedListener($listener, null, $this->stopwatch, $this); + } + $notCalled[] = $listener->getInfo($eventName); + } + } + } + + uasort($notCalled, [$this, 'sortNotCalledListeners']); + + return $notCalled; + } + + public function getOrphanedEvents(Request $request = null): array + { + if ($request) { + return $this->orphanedEvents[spl_object_hash($request)] ?? []; + } + + if (!$this->orphanedEvents) { + return []; + } + + return array_merge(...array_values($this->orphanedEvents)); + } + + public function reset() + { + $this->callStack = null; + $this->orphanedEvents = []; + $this->currentRequestHash = ''; + } + + /** + * Proxies all method calls to the original event dispatcher. + * + * @param string $method The method name + * @param array $arguments The method arguments + * + * @return mixed + */ + public function __call(string $method, array $arguments) + { + return $this->dispatcher->{$method}(...$arguments); + } + + /** + * Called before dispatching the event. + */ + protected function beforeDispatch(string $eventName, object $event) + { + } + + /** + * Called after dispatching the event. + */ + protected function afterDispatch(string $eventName, object $event) + { + } + + private function preProcess(string $eventName): void + { + if (!$this->dispatcher->hasListeners($eventName)) { + $this->orphanedEvents[$this->currentRequestHash][] = $eventName; + + return; + } + + foreach ($this->dispatcher->getListeners($eventName) as $listener) { + $priority = $this->getListenerPriority($eventName, $listener); + $wrappedListener = new WrappedListener($listener instanceof WrappedListener ? $listener->getWrappedListener() : $listener, null, $this->stopwatch, $this); + $this->wrappedListeners[$eventName][] = $wrappedListener; + $this->dispatcher->removeListener($eventName, $listener); + $this->dispatcher->addListener($eventName, $wrappedListener, $priority); + $this->callStack->attach($wrappedListener, [$eventName, $this->currentRequestHash]); + } + } + + private function postProcess(string $eventName): void + { + unset($this->wrappedListeners[$eventName]); + $skipped = false; + foreach ($this->dispatcher->getListeners($eventName) as $listener) { + if (!$listener instanceof WrappedListener) { // #12845: a new listener was added during dispatch. + continue; + } + // Unwrap listener + $priority = $this->getListenerPriority($eventName, $listener); + $this->dispatcher->removeListener($eventName, $listener); + $this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority); + + if (null !== $this->logger) { + $context = ['event' => $eventName, 'listener' => $listener->getPretty()]; + } + + if ($listener->wasCalled()) { + if (null !== $this->logger) { + $this->logger->debug('Notified event "{event}" to listener "{listener}".', $context); + } + } else { + $this->callStack->detach($listener); + } + + if (null !== $this->logger && $skipped) { + $this->logger->debug('Listener "{listener}" was not called for event "{event}".', $context); + } + + if ($listener->stoppedPropagation()) { + if (null !== $this->logger) { + $this->logger->debug('Listener "{listener}" stopped propagation of the event "{event}".', $context); + } + + $skipped = true; + } + } + } + + private function sortNotCalledListeners(array $a, array $b) + { + if (0 !== $cmp = strcmp($a['event'], $b['event'])) { + return $cmp; + } + + if (\is_int($a['priority']) && !\is_int($b['priority'])) { + return 1; + } + + if (!\is_int($a['priority']) && \is_int($b['priority'])) { + return -1; + } + + if ($a['priority'] === $b['priority']) { + return 0; + } + + if ($a['priority'] > $b['priority']) { + return -1; + } + + return 1; + } +} diff --git a/vendor/symfony/event-dispatcher/Debug/WrappedListener.php b/vendor/symfony/event-dispatcher/Debug/WrappedListener.php new file mode 100644 index 0000000..295bcae --- /dev/null +++ b/vendor/symfony/event-dispatcher/Debug/WrappedListener.php @@ -0,0 +1,127 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Debug; + +use Psr\EventDispatcher\StoppableEventInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\VarDumper\Caster\ClassStub; + +/** + * @author Fabien Potencier + */ +final class WrappedListener +{ + private $listener; + private $optimizedListener; + private $name; + private $called; + private $stoppedPropagation; + private $stopwatch; + private $dispatcher; + private $pretty; + private $stub; + private $priority; + private static $hasClassStub; + + public function __construct($listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) + { + $this->listener = $listener; + $this->optimizedListener = $listener instanceof \Closure ? $listener : (\is_callable($listener) ? \Closure::fromCallable($listener) : null); + $this->stopwatch = $stopwatch; + $this->dispatcher = $dispatcher; + $this->called = false; + $this->stoppedPropagation = false; + + if (\is_array($listener)) { + $this->name = \is_object($listener[0]) ? \get_class($listener[0]) : $listener[0]; + $this->pretty = $this->name.'::'.$listener[1]; + } elseif ($listener instanceof \Closure) { + $r = new \ReflectionFunction($listener); + if (false !== strpos($r->name, '{closure}')) { + $this->pretty = $this->name = 'closure'; + } elseif ($class = $r->getClosureScopeClass()) { + $this->name = $class->name; + $this->pretty = $this->name.'::'.$r->name; + } else { + $this->pretty = $this->name = $r->name; + } + } elseif (\is_string($listener)) { + $this->pretty = $this->name = $listener; + } else { + $this->name = \get_class($listener); + $this->pretty = $this->name.'::__invoke'; + } + + if (null !== $name) { + $this->name = $name; + } + + if (null === self::$hasClassStub) { + self::$hasClassStub = class_exists(ClassStub::class); + } + } + + public function getWrappedListener() + { + return $this->listener; + } + + public function wasCalled(): bool + { + return $this->called; + } + + public function stoppedPropagation(): bool + { + return $this->stoppedPropagation; + } + + public function getPretty(): string + { + return $this->pretty; + } + + public function getInfo(string $eventName): array + { + if (null === $this->stub) { + $this->stub = self::$hasClassStub ? new ClassStub($this->pretty.'()', $this->listener) : $this->pretty.'()'; + } + + return [ + 'event' => $eventName, + 'priority' => null !== $this->priority ? $this->priority : (null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null), + 'pretty' => $this->pretty, + 'stub' => $this->stub, + ]; + } + + public function __invoke(object $event, string $eventName, EventDispatcherInterface $dispatcher): void + { + $dispatcher = $this->dispatcher ?: $dispatcher; + + $this->called = true; + $this->priority = $dispatcher->getListenerPriority($eventName, $this->listener); + + $e = $this->stopwatch->start($this->name, 'event_listener'); + + ($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher); + + if ($e->isStarted()) { + $e->stop(); + } + + if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) { + $this->stoppedPropagation = true; + } + } +} diff --git a/vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php b/vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php new file mode 100644 index 0000000..c4ea50f --- /dev/null +++ b/vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * This pass allows bundles to extend the list of event aliases. + * + * @author Alexander M. Turek + */ +class AddEventAliasesPass implements CompilerPassInterface +{ + private $eventAliases; + private $eventAliasesParameter; + + public function __construct(array $eventAliases, string $eventAliasesParameter = 'event_dispatcher.event_aliases') + { + $this->eventAliases = $eventAliases; + $this->eventAliasesParameter = $eventAliasesParameter; + } + + public function process(ContainerBuilder $container): void + { + $eventAliases = $container->hasParameter($this->eventAliasesParameter) ? $container->getParameter($this->eventAliasesParameter) : []; + + $container->setParameter( + $this->eventAliasesParameter, + array_merge($eventAliases, $this->eventAliases) + ); + } +} diff --git a/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php b/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php new file mode 100644 index 0000000..7820d35 --- /dev/null +++ b/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php @@ -0,0 +1,178 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\DependencyInjection; + +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\EventDispatcher\Event as LegacyEvent; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Contracts\EventDispatcher\Event; + +/** + * Compiler pass to register tagged services for an event dispatcher. + */ +class RegisterListenersPass implements CompilerPassInterface +{ + protected $dispatcherService; + protected $listenerTag; + protected $subscriberTag; + protected $eventAliasesParameter; + + private $hotPathEvents = []; + private $hotPathTagName; + + public function __construct(string $dispatcherService = 'event_dispatcher', string $listenerTag = 'kernel.event_listener', string $subscriberTag = 'kernel.event_subscriber', string $eventAliasesParameter = 'event_dispatcher.event_aliases') + { + $this->dispatcherService = $dispatcherService; + $this->listenerTag = $listenerTag; + $this->subscriberTag = $subscriberTag; + $this->eventAliasesParameter = $eventAliasesParameter; + } + + public function setHotPathEvents(array $hotPathEvents, $tagName = 'container.hot_path') + { + $this->hotPathEvents = array_flip($hotPathEvents); + $this->hotPathTagName = $tagName; + + return $this; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) { + return; + } + + if ($container->hasParameter($this->eventAliasesParameter)) { + $aliases = $container->getParameter($this->eventAliasesParameter); + $container->getParameterBag()->remove($this->eventAliasesParameter); + } else { + $aliases = []; + } + $definition = $container->findDefinition($this->dispatcherService); + + foreach ($container->findTaggedServiceIds($this->listenerTag, true) as $id => $events) { + foreach ($events as $event) { + $priority = isset($event['priority']) ? $event['priority'] : 0; + + if (!isset($event['event'])) { + if ($container->getDefinition($id)->hasTag($this->subscriberTag)) { + continue; + } + + $event['method'] = $event['method'] ?? '__invoke'; + $event['event'] = $this->getEventFromTypeDeclaration($container, $id, $event['method']); + } + + $event['event'] = $aliases[$event['event']] ?? $event['event']; + + if (!isset($event['method'])) { + $event['method'] = 'on'.preg_replace_callback([ + '/(?<=\b)[a-z]/i', + '/[^a-z0-9]/i', + ], function ($matches) { return strtoupper($matches[0]); }, $event['event']); + $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); + + if (null !== ($class = $container->getDefinition($id)->getClass()) && ($r = $container->getReflectionClass($class, false)) && !$r->hasMethod($event['method']) && $r->hasMethod('__invoke')) { + $event['method'] = '__invoke'; + } + } + + $definition->addMethodCall('addListener', [$event['event'], [new ServiceClosureArgument(new Reference($id)), $event['method']], $priority]); + + if (isset($this->hotPathEvents[$event['event']])) { + $container->getDefinition($id)->addTag($this->hotPathTagName); + } + } + } + + $extractingDispatcher = new ExtractingEventDispatcher(); + + foreach ($container->findTaggedServiceIds($this->subscriberTag, true) as $id => $attributes) { + $def = $container->getDefinition($id); + + // We must assume that the class value has been correctly filled, even if the service is created by a factory + $class = $def->getClass(); + + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + if (!$r->isSubclassOf(EventSubscriberInterface::class)) { + throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EventSubscriberInterface::class)); + } + $class = $r->name; + + ExtractingEventDispatcher::$aliases = $aliases; + ExtractingEventDispatcher::$subscriber = $class; + $extractingDispatcher->addSubscriber($extractingDispatcher); + foreach ($extractingDispatcher->listeners as $args) { + $args[1] = [new ServiceClosureArgument(new Reference($id)), $args[1]]; + $definition->addMethodCall('addListener', $args); + + if (isset($this->hotPathEvents[$args[0]])) { + $container->getDefinition($id)->addTag($this->hotPathTagName); + } + } + $extractingDispatcher->listeners = []; + ExtractingEventDispatcher::$aliases = []; + } + } + + private function getEventFromTypeDeclaration(ContainerBuilder $container, string $id, string $method): string + { + if ( + null === ($class = $container->getDefinition($id)->getClass()) + || !($r = $container->getReflectionClass($class, false)) + || !$r->hasMethod($method) + || 1 > ($m = $r->getMethod($method))->getNumberOfParameters() + || !($type = $m->getParameters()[0]->getType()) + || $type->isBuiltin() + || Event::class === ($name = $type->getName()) + || LegacyEvent::class === $name + ) { + throw new InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag)); + } + + return $name; + } +} + +/** + * @internal + */ +class ExtractingEventDispatcher extends EventDispatcher implements EventSubscriberInterface +{ + public $listeners = []; + + public static $aliases = []; + public static $subscriber; + + public function addListener(string $eventName, $listener, int $priority = 0) + { + $this->listeners[] = [$eventName, $listener[1], $priority]; + } + + public static function getSubscribedEvents(): array + { + $events = []; + + foreach ([self::$subscriber, 'getSubscribedEvents']() as $eventName => $params) { + $events[self::$aliases[$eventName] ?? $eventName] = $params; + } + + return $events; + } +} diff --git a/vendor/symfony/event-dispatcher/EventDispatcher.php b/vendor/symfony/event-dispatcher/EventDispatcher.php new file mode 100644 index 0000000..c0f839b --- /dev/null +++ b/vendor/symfony/event-dispatcher/EventDispatcher.php @@ -0,0 +1,280 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +use Psr\EventDispatcher\StoppableEventInterface; +use Symfony\Component\EventDispatcher\Debug\WrappedListener; + +/** + * The EventDispatcherInterface is the central point of Symfony's event listener system. + * + * Listeners are registered on the manager and events are dispatched through the + * manager. + * + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Bernhard Schussek + * @author Fabien Potencier + * @author Jordi Boggiano + * @author Jordan Alliot + * @author Nicolas Grekas + */ +class EventDispatcher implements EventDispatcherInterface +{ + private $listeners = []; + private $sorted = []; + private $optimized; + + public function __construct() + { + if (__CLASS__ === \get_class($this)) { + $this->optimized = []; + } + } + + /** + * {@inheritdoc} + */ + public function dispatch(object $event, string $eventName = null): object + { + $eventName = $eventName ?? \get_class($event); + + if (null !== $this->optimized && null !== $eventName) { + $listeners = $this->optimized[$eventName] ?? (empty($this->listeners[$eventName]) ? [] : $this->optimizeListeners($eventName)); + } else { + $listeners = $this->getListeners($eventName); + } + + if ($listeners) { + $this->callListeners($listeners, $eventName, $event); + } + + return $event; + } + + /** + * {@inheritdoc} + */ + public function getListeners(string $eventName = null) + { + if (null !== $eventName) { + if (empty($this->listeners[$eventName])) { + return []; + } + + if (!isset($this->sorted[$eventName])) { + $this->sortListeners($eventName); + } + + return $this->sorted[$eventName]; + } + + foreach ($this->listeners as $eventName => $eventListeners) { + if (!isset($this->sorted[$eventName])) { + $this->sortListeners($eventName); + } + } + + return array_filter($this->sorted); + } + + /** + * {@inheritdoc} + */ + public function getListenerPriority(string $eventName, $listener) + { + if (empty($this->listeners[$eventName])) { + return null; + } + + if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { + $listener[0] = $listener[0](); + $listener[1] = $listener[1] ?? '__invoke'; + } + + foreach ($this->listeners[$eventName] as $priority => &$listeners) { + foreach ($listeners as &$v) { + if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) { + $v[0] = $v[0](); + $v[1] = $v[1] ?? '__invoke'; + } + if ($v === $listener) { + return $priority; + } + } + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function hasListeners(string $eventName = null) + { + if (null !== $eventName) { + return !empty($this->listeners[$eventName]); + } + + foreach ($this->listeners as $eventListeners) { + if ($eventListeners) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function addListener(string $eventName, $listener, int $priority = 0) + { + $this->listeners[$eventName][$priority][] = $listener; + unset($this->sorted[$eventName], $this->optimized[$eventName]); + } + + /** + * {@inheritdoc} + */ + public function removeListener(string $eventName, $listener) + { + if (empty($this->listeners[$eventName])) { + return; + } + + if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { + $listener[0] = $listener[0](); + $listener[1] = $listener[1] ?? '__invoke'; + } + + foreach ($this->listeners[$eventName] as $priority => &$listeners) { + foreach ($listeners as $k => &$v) { + if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) { + $v[0] = $v[0](); + $v[1] = $v[1] ?? '__invoke'; + } + if ($v === $listener) { + unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]); + } + } + + if (!$listeners) { + unset($this->listeners[$eventName][$priority]); + } + } + } + + /** + * {@inheritdoc} + */ + public function addSubscriber(EventSubscriberInterface $subscriber) + { + foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { + if (\is_string($params)) { + $this->addListener($eventName, [$subscriber, $params]); + } elseif (\is_string($params[0])) { + $this->addListener($eventName, [$subscriber, $params[0]], isset($params[1]) ? $params[1] : 0); + } else { + foreach ($params as $listener) { + $this->addListener($eventName, [$subscriber, $listener[0]], isset($listener[1]) ? $listener[1] : 0); + } + } + } + } + + /** + * {@inheritdoc} + */ + public function removeSubscriber(EventSubscriberInterface $subscriber) + { + foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { + if (\is_array($params) && \is_array($params[0])) { + foreach ($params as $listener) { + $this->removeListener($eventName, [$subscriber, $listener[0]]); + } + } else { + $this->removeListener($eventName, [$subscriber, \is_string($params) ? $params : $params[0]]); + } + } + } + + /** + * Triggers the listeners of an event. + * + * This method can be overridden to add functionality that is executed + * for each listener. + * + * @param callable[] $listeners The event listeners + * @param string $eventName The name of the event to dispatch + * @param object $event The event object to pass to the event handlers/listeners + */ + protected function callListeners(iterable $listeners, string $eventName, object $event) + { + $stoppable = $event instanceof StoppableEventInterface; + + foreach ($listeners as $listener) { + if ($stoppable && $event->isPropagationStopped()) { + break; + } + $listener($event, $eventName, $this); + } + } + + /** + * Sorts the internal list of listeners for the given event by priority. + */ + private function sortListeners(string $eventName) + { + krsort($this->listeners[$eventName]); + $this->sorted[$eventName] = []; + + foreach ($this->listeners[$eventName] as &$listeners) { + foreach ($listeners as $k => $listener) { + if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { + $listener[0] = $listener[0](); + $listener[1] = $listener[1] ?? '__invoke'; + } + $this->sorted[$eventName][] = $listener; + } + } + } + + /** + * Optimizes the internal list of listeners for the given event by priority. + */ + private function optimizeListeners(string $eventName): array + { + krsort($this->listeners[$eventName]); + $this->optimized[$eventName] = []; + + foreach ($this->listeners[$eventName] as &$listeners) { + foreach ($listeners as &$listener) { + $closure = &$this->optimized[$eventName][]; + if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { + $closure = static function (...$args) use (&$listener, &$closure) { + if ($listener[0] instanceof \Closure) { + $listener[0] = $listener[0](); + $listener[1] = $listener[1] ?? '__invoke'; + } + ($closure = \Closure::fromCallable($listener))(...$args); + }; + } else { + $closure = $listener instanceof \Closure || $listener instanceof WrappedListener ? $listener : \Closure::fromCallable($listener); + } + } + } + + return $this->optimized[$eventName]; + } +} diff --git a/vendor/symfony/event-dispatcher/EventDispatcherInterface.php b/vendor/symfony/event-dispatcher/EventDispatcherInterface.php new file mode 100644 index 0000000..88c707c --- /dev/null +++ b/vendor/symfony/event-dispatcher/EventDispatcherInterface.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface as ContractsEventDispatcherInterface; + +/** + * The EventDispatcherInterface is the central point of Symfony's event listener system. + * Listeners are registered on the manager and events are dispatched through the + * manager. + * + * @author Bernhard Schussek + */ +interface EventDispatcherInterface extends ContractsEventDispatcherInterface +{ + /** + * Adds an event listener that listens on the specified events. + * + * @param callable $listener The listener + * @param int $priority The higher this value, the earlier an event + * listener will be triggered in the chain (defaults to 0) + */ + public function addListener(string $eventName, $listener, int $priority = 0); + + /** + * Adds an event subscriber. + * + * The subscriber is asked for all the events it is + * interested in and added as a listener for these events. + */ + public function addSubscriber(EventSubscriberInterface $subscriber); + + /** + * Removes an event listener from the specified events. + * + * @param callable $listener The listener to remove + */ + public function removeListener(string $eventName, $listener); + + public function removeSubscriber(EventSubscriberInterface $subscriber); + + /** + * Gets the listeners of a specific event or all listeners sorted by descending priority. + * + * @return array The event listeners for the specified event, or all event listeners by event name + */ + public function getListeners(string $eventName = null); + + /** + * Gets the listener priority for a specific event. + * + * Returns null if the event or the listener does not exist. + * + * @param callable $listener The listener + * + * @return int|null The event listener priority + */ + public function getListenerPriority(string $eventName, $listener); + + /** + * Checks whether an event has any registered listeners. + * + * @return bool true if the specified event has any listeners, false otherwise + */ + public function hasListeners(string $eventName = null); +} diff --git a/vendor/symfony/event-dispatcher/EventSubscriberInterface.php b/vendor/symfony/event-dispatcher/EventSubscriberInterface.php new file mode 100644 index 0000000..824f215 --- /dev/null +++ b/vendor/symfony/event-dispatcher/EventSubscriberInterface.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +/** + * An EventSubscriber knows itself what events it is interested in. + * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes + * {@link getSubscribedEvents} and registers the subscriber as a listener for all + * returned events. + * + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel + * @author Bernhard Schussek + */ +interface EventSubscriberInterface +{ + /** + * Returns an array of event names this subscriber wants to listen to. + * + * The array keys are event names and the value can be: + * + * * The method name to call (priority defaults to 0) + * * An array composed of the method name to call and the priority + * * An array of arrays composed of the method names to call and respective + * priorities, or 0 if unset + * + * For instance: + * + * * ['eventName' => 'methodName'] + * * ['eventName' => ['methodName', $priority]] + * * ['eventName' => [['methodName1', $priority], ['methodName2']]] + * + * @return array The event names to listen to + */ + public static function getSubscribedEvents(); +} diff --git a/vendor/symfony/event-dispatcher/GenericEvent.php b/vendor/symfony/event-dispatcher/GenericEvent.php new file mode 100644 index 0000000..34b95ce --- /dev/null +++ b/vendor/symfony/event-dispatcher/GenericEvent.php @@ -0,0 +1,170 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +use Symfony\Contracts\EventDispatcher\Event; + +/** + * Event encapsulation class. + * + * Encapsulates events thus decoupling the observer from the subject they encapsulate. + * + * @author Drak + */ +class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate +{ + protected $subject; + protected $arguments; + + /** + * Encapsulate an event with $subject and $args. + * + * @param mixed $subject The subject of the event, usually an object or a callable + * @param array $arguments Arguments to store in the event + */ + public function __construct($subject = null, array $arguments = []) + { + $this->subject = $subject; + $this->arguments = $arguments; + } + + /** + * Getter for subject property. + * + * @return mixed The observer subject + */ + public function getSubject() + { + return $this->subject; + } + + /** + * Get argument by key. + * + * @return mixed Contents of array key + * + * @throws \InvalidArgumentException if key is not found + */ + public function getArgument(string $key) + { + if ($this->hasArgument($key)) { + return $this->arguments[$key]; + } + + throw new \InvalidArgumentException(sprintf('Argument "%s" not found.', $key)); + } + + /** + * Add argument to event. + * + * @param mixed $value Value + * + * @return $this + */ + public function setArgument(string $key, $value) + { + $this->arguments[$key] = $value; + + return $this; + } + + /** + * Getter for all arguments. + * + * @return array + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * Set args property. + * + * @return $this + */ + public function setArguments(array $args = []) + { + $this->arguments = $args; + + return $this; + } + + /** + * Has argument. + * + * @return bool + */ + public function hasArgument(string $key) + { + return \array_key_exists($key, $this->arguments); + } + + /** + * ArrayAccess for argument getter. + * + * @param string $key Array key + * + * @return mixed + * + * @throws \InvalidArgumentException if key does not exist in $this->args + */ + public function offsetGet($key) + { + return $this->getArgument($key); + } + + /** + * ArrayAccess for argument setter. + * + * @param string $key Array key to set + * @param mixed $value Value + */ + public function offsetSet($key, $value) + { + $this->setArgument($key, $value); + } + + /** + * ArrayAccess for unset argument. + * + * @param string $key Array key + */ + public function offsetUnset($key) + { + if ($this->hasArgument($key)) { + unset($this->arguments[$key]); + } + } + + /** + * ArrayAccess has argument. + * + * @param string $key Array key + * + * @return bool + */ + public function offsetExists($key) + { + return $this->hasArgument($key); + } + + /** + * IteratorAggregate for iterating over the object like an array. + * + * @return \ArrayIterator + */ + public function getIterator() + { + return new \ArrayIterator($this->arguments); + } +} diff --git a/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php b/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php new file mode 100644 index 0000000..568d79c --- /dev/null +++ b/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +/** + * A read-only proxy for an event dispatcher. + * + * @author Bernhard Schussek + */ +class ImmutableEventDispatcher implements EventDispatcherInterface +{ + private $dispatcher; + + public function __construct(EventDispatcherInterface $dispatcher) + { + $this->dispatcher = $dispatcher; + } + + /** + * {@inheritdoc} + */ + public function dispatch(object $event, string $eventName = null): object + { + return $this->dispatcher->dispatch($event, $eventName); + } + + /** + * {@inheritdoc} + */ + public function addListener(string $eventName, $listener, int $priority = 0) + { + throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); + } + + /** + * {@inheritdoc} + */ + public function addSubscriber(EventSubscriberInterface $subscriber) + { + throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); + } + + /** + * {@inheritdoc} + */ + public function removeListener(string $eventName, $listener) + { + throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); + } + + /** + * {@inheritdoc} + */ + public function removeSubscriber(EventSubscriberInterface $subscriber) + { + throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); + } + + /** + * {@inheritdoc} + */ + public function getListeners(string $eventName = null) + { + return $this->dispatcher->getListeners($eventName); + } + + /** + * {@inheritdoc} + */ + public function getListenerPriority(string $eventName, $listener) + { + return $this->dispatcher->getListenerPriority($eventName, $listener); + } + + /** + * {@inheritdoc} + */ + public function hasListeners(string $eventName = null) + { + return $this->dispatcher->hasListeners($eventName); + } +} diff --git a/vendor/symfony/event-dispatcher/LICENSE b/vendor/symfony/event-dispatcher/LICENSE new file mode 100644 index 0000000..a677f43 --- /dev/null +++ b/vendor/symfony/event-dispatcher/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php b/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php new file mode 100644 index 0000000..a44b766 --- /dev/null +++ b/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; + +/** + * A helper class to provide BC/FC with the legacy signature of EventDispatcherInterface::dispatch(). + * + * This class should be deprecated in Symfony 5.1 + * + * @author Nicolas Grekas + */ +final class LegacyEventDispatcherProxy +{ + public static function decorate(?EventDispatcherInterface $dispatcher): ?EventDispatcherInterface + { + return $dispatcher; + } +} diff --git a/vendor/symfony/event-dispatcher/README.md b/vendor/symfony/event-dispatcher/README.md new file mode 100644 index 0000000..185c3fe --- /dev/null +++ b/vendor/symfony/event-dispatcher/README.md @@ -0,0 +1,15 @@ +EventDispatcher Component +========================= + +The EventDispatcher component provides tools that allow your application +components to communicate with each other by dispatching events and listening to +them. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/event_dispatcher/index.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/event-dispatcher/composer.json b/vendor/symfony/event-dispatcher/composer.json new file mode 100644 index 0000000..e867a7c --- /dev/null +++ b/vendor/symfony/event-dispatcher/composer.json @@ -0,0 +1,54 @@ +{ + "name": "symfony/event-dispatcher", + "type": "library", + "description": "Symfony EventDispatcher Component", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "symfony/event-dispatcher-contracts": "^2" + }, + "require-dev": { + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/config": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/stopwatch": "^4.4|^5.0", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<4.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/filesystem/.gitattributes b/vendor/symfony/filesystem/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/filesystem/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/filesystem/CHANGELOG.md b/vendor/symfony/filesystem/CHANGELOG.md new file mode 100644 index 0000000..d103bc2 --- /dev/null +++ b/vendor/symfony/filesystem/CHANGELOG.md @@ -0,0 +1,75 @@ +CHANGELOG +========= + +5.0.0 +----- + + * `Filesystem::dumpFile()` and `appendToFile()` don't accept arrays anymore + +4.4.0 +----- + + * support for passing a `null` value to `Filesystem::isAbsolutePath()` is deprecated and will be removed in 5.0 + +4.3.0 +----- + + * support for passing arrays to `Filesystem::dumpFile()` is deprecated and will be removed in 5.0 + * support for passing arrays to `Filesystem::appendToFile()` is deprecated and will be removed in 5.0 + +4.0.0 +----- + + * removed `LockHandler` + * Support for passing relative paths to `Filesystem::makePathRelative()` has been removed. + +3.4.0 +----- + + * support for passing relative paths to `Filesystem::makePathRelative()` is deprecated and will be removed in 4.0 + +3.3.0 +----- + + * added `appendToFile()` to append contents to existing files + +3.2.0 +----- + + * added `readlink()` as a platform independent method to read links + +3.0.0 +----- + + * removed `$mode` argument from `Filesystem::dumpFile()` + +2.8.0 +----- + + * added tempnam() a stream aware version of PHP's native tempnam() + +2.6.0 +----- + + * added LockHandler + +2.3.12 +------ + + * deprecated dumpFile() file mode argument. + +2.3.0 +----- + + * added the dumpFile() method to atomically write files + +2.2.0 +----- + + * added a delete option for the mirror() method + +2.1.0 +----- + + * 24eb396 : BC Break : mkdir() function now throws exception in case of failure instead of returning Boolean value + * created the component diff --git a/vendor/symfony/filesystem/Exception/ExceptionInterface.php b/vendor/symfony/filesystem/Exception/ExceptionInterface.php new file mode 100644 index 0000000..fc438d9 --- /dev/null +++ b/vendor/symfony/filesystem/Exception/ExceptionInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Filesystem\Exception; + +/** + * Exception interface for all exceptions thrown by the component. + * + * @author Romain Neutron + */ +interface ExceptionInterface extends \Throwable +{ +} diff --git a/vendor/symfony/filesystem/Exception/FileNotFoundException.php b/vendor/symfony/filesystem/Exception/FileNotFoundException.php new file mode 100644 index 0000000..48b6408 --- /dev/null +++ b/vendor/symfony/filesystem/Exception/FileNotFoundException.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Filesystem\Exception; + +/** + * Exception class thrown when a file couldn't be found. + * + * @author Fabien Potencier + * @author Christian Gärtner + */ +class FileNotFoundException extends IOException +{ + public function __construct(string $message = null, int $code = 0, \Throwable $previous = null, string $path = null) + { + if (null === $message) { + if (null === $path) { + $message = 'File could not be found.'; + } else { + $message = sprintf('File "%s" could not be found.', $path); + } + } + + parent::__construct($message, $code, $previous, $path); + } +} diff --git a/vendor/symfony/filesystem/Exception/IOException.php b/vendor/symfony/filesystem/Exception/IOException.php new file mode 100644 index 0000000..fea26e4 --- /dev/null +++ b/vendor/symfony/filesystem/Exception/IOException.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Filesystem\Exception; + +/** + * Exception class thrown when a filesystem operation failure happens. + * + * @author Romain Neutron + * @author Christian Gärtner + * @author Fabien Potencier + */ +class IOException extends \RuntimeException implements IOExceptionInterface +{ + private $path; + + public function __construct(string $message, int $code = 0, \Throwable $previous = null, string $path = null) + { + $this->path = $path; + + parent::__construct($message, $code, $previous); + } + + /** + * {@inheritdoc} + */ + public function getPath() + { + return $this->path; + } +} diff --git a/vendor/symfony/filesystem/Exception/IOExceptionInterface.php b/vendor/symfony/filesystem/Exception/IOExceptionInterface.php new file mode 100644 index 0000000..f9d4644 --- /dev/null +++ b/vendor/symfony/filesystem/Exception/IOExceptionInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Filesystem\Exception; + +/** + * IOException interface for file and input/output stream related exceptions thrown by the component. + * + * @author Christian Gärtner + */ +interface IOExceptionInterface extends ExceptionInterface +{ + /** + * Returns the associated path for the exception. + * + * @return string|null The path + */ + public function getPath(); +} diff --git a/vendor/symfony/filesystem/Exception/InvalidArgumentException.php b/vendor/symfony/filesystem/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..abadc20 --- /dev/null +++ b/vendor/symfony/filesystem/Exception/InvalidArgumentException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Filesystem\Exception; + +/** + * @author Christian Flothmann + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/filesystem/Filesystem.php b/vendor/symfony/filesystem/Filesystem.php new file mode 100644 index 0000000..76c10b0 --- /dev/null +++ b/vendor/symfony/filesystem/Filesystem.php @@ -0,0 +1,734 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Filesystem; + +use Symfony\Component\Filesystem\Exception\FileNotFoundException; +use Symfony\Component\Filesystem\Exception\InvalidArgumentException; +use Symfony\Component\Filesystem\Exception\IOException; + +/** + * Provides basic utility to manipulate the file system. + * + * @author Fabien Potencier + */ +class Filesystem +{ + private static $lastError; + + /** + * Copies a file. + * + * If the target file is older than the origin file, it's always overwritten. + * If the target file is newer, it is overwritten only when the + * $overwriteNewerFiles option is set to true. + * + * @throws FileNotFoundException When originFile doesn't exist + * @throws IOException When copy fails + */ + public function copy(string $originFile, string $targetFile, bool $overwriteNewerFiles = false) + { + $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://'); + if ($originIsLocal && !is_file($originFile)) { + throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile); + } + + $this->mkdir(\dirname($targetFile)); + + $doCopy = true; + if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) { + $doCopy = filemtime($originFile) > filemtime($targetFile); + } + + if ($doCopy) { + // https://bugs.php.net/64634 + if (false === $source = @fopen($originFile, 'r')) { + throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile); + } + + // Stream context created to allow files overwrite when using FTP stream wrapper - disabled by default + if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(['ftp' => ['overwrite' => true]]))) { + throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile); + } + + $bytesCopied = stream_copy_to_stream($source, $target); + fclose($source); + fclose($target); + unset($source, $target); + + if (!is_file($targetFile)) { + throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile); + } + + if ($originIsLocal) { + // Like `cp`, preserve executable permission bits + @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111)); + + if ($bytesCopied !== $bytesOrigin = filesize($originFile)) { + throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile); + } + } + } + } + + /** + * Creates a directory recursively. + * + * @param string|iterable $dirs The directory path + * + * @throws IOException On any directory creation failure + */ + public function mkdir($dirs, int $mode = 0777) + { + foreach ($this->toIterable($dirs) as $dir) { + if (is_dir($dir)) { + continue; + } + + if (!self::box('mkdir', $dir, $mode, true)) { + if (!is_dir($dir)) { + // The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one + if (self::$lastError) { + throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir); + } + throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir); + } + } + } + } + + /** + * Checks the existence of files or directories. + * + * @param string|iterable $files A filename, an array of files, or a \Traversable instance to check + * + * @return bool true if the file exists, false otherwise + */ + public function exists($files) + { + $maxPathLength = PHP_MAXPATHLEN - 2; + + foreach ($this->toIterable($files) as $file) { + if (\strlen($file) > $maxPathLength) { + throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file); + } + + if (!file_exists($file)) { + return false; + } + } + + return true; + } + + /** + * Sets access and modification time of file. + * + * @param string|iterable $files A filename, an array of files, or a \Traversable instance to create + * @param int|null $time The touch time as a Unix timestamp, if not supplied the current system time is used + * @param int|null $atime The access time as a Unix timestamp, if not supplied the current system time is used + * + * @throws IOException When touch fails + */ + public function touch($files, int $time = null, int $atime = null) + { + foreach ($this->toIterable($files) as $file) { + $touch = $time ? @touch($file, $time, $atime) : @touch($file); + if (true !== $touch) { + throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file); + } + } + } + + /** + * Removes files or directories. + * + * @param string|iterable $files A filename, an array of files, or a \Traversable instance to remove + * + * @throws IOException When removal fails + */ + public function remove($files) + { + if ($files instanceof \Traversable) { + $files = iterator_to_array($files, false); + } elseif (!\is_array($files)) { + $files = [$files]; + } + $files = array_reverse($files); + foreach ($files as $file) { + if (is_link($file)) { + // See https://bugs.php.net/52176 + if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) { + throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError)); + } + } elseif (is_dir($file)) { + $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS)); + + if (!self::box('rmdir', $file) && file_exists($file)) { + throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError)); + } + } elseif (!self::box('unlink', $file) && file_exists($file)) { + throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError)); + } + } + } + + /** + * Change mode for an array of files or directories. + * + * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change mode + * @param int $mode The new mode (octal) + * @param int $umask The mode mask (octal) + * @param bool $recursive Whether change the mod recursively or not + * + * @throws IOException When the change fails + */ + public function chmod($files, int $mode, int $umask = 0000, bool $recursive = false) + { + foreach ($this->toIterable($files) as $file) { + if (true !== @chmod($file, $mode & ~$umask)) { + throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file); + } + if ($recursive && is_dir($file) && !is_link($file)) { + $this->chmod(new \FilesystemIterator($file), $mode, $umask, true); + } + } + } + + /** + * Change the owner of an array of files or directories. + * + * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change owner + * + * @throws IOException When the change fails + */ + public function chown($files, string $user, bool $recursive = false) + { + foreach ($this->toIterable($files) as $file) { + if ($recursive && is_dir($file) && !is_link($file)) { + $this->chown(new \FilesystemIterator($file), $user, true); + } + if (is_link($file) && \function_exists('lchown')) { + if (true !== @lchown($file, $user)) { + throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file); + } + } else { + if (true !== @chown($file, $user)) { + throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file); + } + } + } + } + + /** + * Change the group of an array of files or directories. + * + * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change group + * + * @throws IOException When the change fails + */ + public function chgrp($files, string $group, bool $recursive = false) + { + foreach ($this->toIterable($files) as $file) { + if ($recursive && is_dir($file) && !is_link($file)) { + $this->chgrp(new \FilesystemIterator($file), $group, true); + } + if (is_link($file) && \function_exists('lchgrp')) { + if (true !== @lchgrp($file, $group)) { + throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file); + } + } else { + if (true !== @chgrp($file, $group)) { + throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file); + } + } + } + } + + /** + * Renames a file or a directory. + * + * @throws IOException When target file or directory already exists + * @throws IOException When origin cannot be renamed + */ + public function rename(string $origin, string $target, bool $overwrite = false) + { + // we check that target does not exist + if (!$overwrite && $this->isReadable($target)) { + throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target); + } + + if (true !== @rename($origin, $target)) { + if (is_dir($origin)) { + // See https://bugs.php.net/54097 & https://php.net/rename#113943 + $this->mirror($origin, $target, null, ['override' => $overwrite, 'delete' => $overwrite]); + $this->remove($origin); + + return; + } + throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target); + } + } + + /** + * Tells whether a file exists and is readable. + * + * @throws IOException When windows path is longer than 258 characters + */ + private function isReadable(string $filename): bool + { + $maxPathLength = PHP_MAXPATHLEN - 2; + + if (\strlen($filename) > $maxPathLength) { + throw new IOException(sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename); + } + + return is_readable($filename); + } + + /** + * Creates a symbolic link or copy a directory. + * + * @throws IOException When symlink fails + */ + public function symlink(string $originDir, string $targetDir, bool $copyOnWindows = false) + { + if ('\\' === \DIRECTORY_SEPARATOR) { + $originDir = strtr($originDir, '/', '\\'); + $targetDir = strtr($targetDir, '/', '\\'); + + if ($copyOnWindows) { + $this->mirror($originDir, $targetDir); + + return; + } + } + + $this->mkdir(\dirname($targetDir)); + + if (is_link($targetDir)) { + if (readlink($targetDir) === $originDir) { + return; + } + $this->remove($targetDir); + } + + if (!self::box('symlink', $originDir, $targetDir)) { + $this->linkException($originDir, $targetDir, 'symbolic'); + } + } + + /** + * Creates a hard link, or several hard links to a file. + * + * @param string|string[] $targetFiles The target file(s) + * + * @throws FileNotFoundException When original file is missing or not a file + * @throws IOException When link fails, including if link already exists + */ + public function hardlink(string $originFile, $targetFiles) + { + if (!$this->exists($originFile)) { + throw new FileNotFoundException(null, 0, null, $originFile); + } + + if (!is_file($originFile)) { + throw new FileNotFoundException(sprintf('Origin file "%s" is not a file', $originFile)); + } + + foreach ($this->toIterable($targetFiles) as $targetFile) { + if (is_file($targetFile)) { + if (fileinode($originFile) === fileinode($targetFile)) { + continue; + } + $this->remove($targetFile); + } + + if (!self::box('link', $originFile, $targetFile)) { + $this->linkException($originFile, $targetFile, 'hard'); + } + } + } + + /** + * @param string $linkType Name of the link type, typically 'symbolic' or 'hard' + */ + private function linkException(string $origin, string $target, string $linkType) + { + if (self::$lastError) { + if ('\\' === \DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) { + throw new IOException(sprintf('Unable to create %s link due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', $linkType), 0, null, $target); + } + } + throw new IOException(sprintf('Failed to create %s link from "%s" to "%s".', $linkType, $origin, $target), 0, null, $target); + } + + /** + * Resolves links in paths. + * + * With $canonicalize = false (default) + * - if $path does not exist or is not a link, returns null + * - if $path is a link, returns the next direct target of the link without considering the existence of the target + * + * With $canonicalize = true + * - if $path does not exist, returns null + * - if $path exists, returns its absolute fully resolved final version + * + * @return string|null + */ + public function readlink(string $path, bool $canonicalize = false) + { + if (!$canonicalize && !is_link($path)) { + return null; + } + + if ($canonicalize) { + if (!$this->exists($path)) { + return null; + } + + if ('\\' === \DIRECTORY_SEPARATOR) { + $path = readlink($path); + } + + return realpath($path); + } + + if ('\\' === \DIRECTORY_SEPARATOR) { + return realpath($path); + } + + return readlink($path); + } + + /** + * Given an existing path, convert it to a path relative to a given starting path. + * + * @return string Path of target relative to starting path + */ + public function makePathRelative(string $endPath, string $startPath) + { + if (!$this->isAbsolutePath($startPath)) { + throw new InvalidArgumentException(sprintf('The start path "%s" is not absolute.', $startPath)); + } + + if (!$this->isAbsolutePath($endPath)) { + throw new InvalidArgumentException(sprintf('The end path "%s" is not absolute.', $endPath)); + } + + // Normalize separators on Windows + if ('\\' === \DIRECTORY_SEPARATOR) { + $endPath = str_replace('\\', '/', $endPath); + $startPath = str_replace('\\', '/', $startPath); + } + + $stripDriveLetter = function ($path) { + if (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) { + return substr($path, 2); + } + + return $path; + }; + + $endPath = $stripDriveLetter($endPath); + $startPath = $stripDriveLetter($startPath); + + // Split the paths into arrays + $startPathArr = explode('/', trim($startPath, '/')); + $endPathArr = explode('/', trim($endPath, '/')); + + $normalizePathArray = function ($pathSegments) { + $result = []; + + foreach ($pathSegments as $segment) { + if ('..' === $segment) { + array_pop($result); + } elseif ('.' !== $segment) { + $result[] = $segment; + } + } + + return $result; + }; + + $startPathArr = $normalizePathArray($startPathArr); + $endPathArr = $normalizePathArray($endPathArr); + + // Find for which directory the common path stops + $index = 0; + while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) { + ++$index; + } + + // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels) + if (1 === \count($startPathArr) && '' === $startPathArr[0]) { + $depth = 0; + } else { + $depth = \count($startPathArr) - $index; + } + + // Repeated "../" for each level need to reach the common path + $traverser = str_repeat('../', $depth); + + $endPathRemainder = implode('/', \array_slice($endPathArr, $index)); + + // Construct $endPath from traversing to the common path, then to the remaining $endPath + $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : ''); + + return '' === $relativePath ? './' : $relativePath; + } + + /** + * Mirrors a directory to another. + * + * Copies files and directories from the origin directory into the target directory. By default: + * + * - existing files in the target directory will be overwritten, except if they are newer (see the `override` option) + * - files in the target directory that do not exist in the source directory will not be deleted (see the `delete` option) + * + * @param \Traversable|null $iterator Iterator that filters which files and directories to copy, if null a recursive iterator is created + * @param array $options An array of boolean options + * Valid options are: + * - $options['override'] If true, target files newer than origin files are overwritten (see copy(), defaults to false) + * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false) + * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) + * + * @throws IOException When file type is unknown + */ + public function mirror(string $originDir, string $targetDir, \Traversable $iterator = null, array $options = []) + { + $targetDir = rtrim($targetDir, '/\\'); + $originDir = rtrim($originDir, '/\\'); + $originDirLen = \strlen($originDir); + + if (!$this->exists($originDir)) { + throw new IOException(sprintf('The origin directory specified "%s" was not found.', $originDir), 0, null, $originDir); + } + + // Iterate in destination folder to remove obsolete entries + if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) { + $deleteIterator = $iterator; + if (null === $deleteIterator) { + $flags = \FilesystemIterator::SKIP_DOTS; + $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST); + } + $targetDirLen = \strlen($targetDir); + foreach ($deleteIterator as $file) { + $origin = $originDir.substr($file->getPathname(), $targetDirLen); + if (!$this->exists($origin)) { + $this->remove($file); + } + } + } + + $copyOnWindows = $options['copy_on_windows'] ?? false; + + if (null === $iterator) { + $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS; + $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST); + } + + $this->mkdir($targetDir); + $filesCreatedWhileMirroring = []; + + foreach ($iterator as $file) { + if ($file->getPathname() === $targetDir || $file->getRealPath() === $targetDir || isset($filesCreatedWhileMirroring[$file->getRealPath()])) { + continue; + } + + $target = $targetDir.substr($file->getPathname(), $originDirLen); + $filesCreatedWhileMirroring[$target] = true; + + if (!$copyOnWindows && is_link($file)) { + $this->symlink($file->getLinkTarget(), $target); + } elseif (is_dir($file)) { + $this->mkdir($target); + } elseif (is_file($file)) { + $this->copy($file, $target, isset($options['override']) ? $options['override'] : false); + } else { + throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file); + } + } + } + + /** + * Returns whether the file path is an absolute path. + * + * @return bool + */ + public function isAbsolutePath(string $file) + { + return strspn($file, '/\\', 0, 1) + || (\strlen($file) > 3 && ctype_alpha($file[0]) + && ':' === $file[1] + && strspn($file, '/\\', 2, 1) + ) + || null !== parse_url($file, PHP_URL_SCHEME) + ; + } + + /** + * Creates a temporary file with support for custom stream wrappers. + * + * @param string $prefix The prefix of the generated temporary filename + * Note: Windows uses only the first three characters of prefix + * + * @return string The new temporary filename (with path), or throw an exception on failure + */ + public function tempnam(string $dir, string $prefix) + { + list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir); + + // If no scheme or scheme is "file" or "gs" (Google Cloud) create temp file in local filesystem + if (null === $scheme || 'file' === $scheme || 'gs' === $scheme) { + $tmpFile = @tempnam($hierarchy, $prefix); + + // If tempnam failed or no scheme return the filename otherwise prepend the scheme + if (false !== $tmpFile) { + if (null !== $scheme && 'gs' !== $scheme) { + return $scheme.'://'.$tmpFile; + } + + return $tmpFile; + } + + throw new IOException('A temporary file could not be created.'); + } + + // Loop until we create a valid temp file or have reached 10 attempts + for ($i = 0; $i < 10; ++$i) { + // Create a unique filename + $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true); + + // Use fopen instead of file_exists as some streams do not support stat + // Use mode 'x+' to atomically check existence and create to avoid a TOCTOU vulnerability + $handle = @fopen($tmpFile, 'x+'); + + // If unsuccessful restart the loop + if (false === $handle) { + continue; + } + + // Close the file if it was successfully opened + @fclose($handle); + + return $tmpFile; + } + + throw new IOException('A temporary file could not be created.'); + } + + /** + * Atomically dumps content into a file. + * + * @param string|resource $content The data to write into the file + * + * @throws IOException if the file cannot be written to + */ + public function dumpFile(string $filename, $content) + { + if (\is_array($content)) { + throw new \TypeError(sprintf('Argument 2 passed to %s() must be string or resource, array given.', __METHOD__)); + } + + $dir = \dirname($filename); + + if (!is_dir($dir)) { + $this->mkdir($dir); + } + + if (!is_writable($dir)) { + throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir); + } + + // Will create a temp file with 0600 access rights + // when the filesystem supports chmod. + $tmpFile = $this->tempnam($dir, basename($filename)); + + if (false === @file_put_contents($tmpFile, $content)) { + throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename); + } + + @chmod($tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask()); + + $this->rename($tmpFile, $filename, true); + } + + /** + * Appends content to an existing file. + * + * @param string|resource $content The content to append + * + * @throws IOException If the file is not writable + */ + public function appendToFile(string $filename, $content) + { + if (\is_array($content)) { + throw new \TypeError(sprintf('Argument 2 passed to %s() must be string or resource, array given.', __METHOD__)); + } + + $dir = \dirname($filename); + + if (!is_dir($dir)) { + $this->mkdir($dir); + } + + if (!is_writable($dir)) { + throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir); + } + + if (false === @file_put_contents($filename, $content, FILE_APPEND)) { + throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename); + } + } + + private function toIterable($files): iterable + { + return \is_array($files) || $files instanceof \Traversable ? $files : [$files]; + } + + /** + * Gets a 2-tuple of scheme (may be null) and hierarchical part of a filename (e.g. file:///tmp -> [file, tmp]). + */ + private function getSchemeAndHierarchy(string $filename): array + { + $components = explode('://', $filename, 2); + + return 2 === \count($components) ? [$components[0], $components[1]] : [null, $components[0]]; + } + + /** + * @return mixed + */ + private static function box(callable $func) + { + self::$lastError = null; + set_error_handler(__CLASS__.'::handleError'); + try { + $result = $func(...\array_slice(\func_get_args(), 1)); + restore_error_handler(); + + return $result; + } catch (\Throwable $e) { + } + restore_error_handler(); + + throw $e; + } + + /** + * @internal + */ + public static function handleError($type, $msg) + { + self::$lastError = $msg; + } +} diff --git a/vendor/symfony/filesystem/LICENSE b/vendor/symfony/filesystem/LICENSE new file mode 100644 index 0000000..a677f43 --- /dev/null +++ b/vendor/symfony/filesystem/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/filesystem/README.md b/vendor/symfony/filesystem/README.md new file mode 100644 index 0000000..877ab35 --- /dev/null +++ b/vendor/symfony/filesystem/README.md @@ -0,0 +1,13 @@ +Filesystem Component +==================== + +The Filesystem component provides basic utilities for the filesystem. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/filesystem/index.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/filesystem/composer.json b/vendor/symfony/filesystem/composer.json new file mode 100644 index 0000000..3eb1070 --- /dev/null +++ b/vendor/symfony/filesystem/composer.json @@ -0,0 +1,34 @@ +{ + "name": "symfony/filesystem", + "type": "library", + "description": "Symfony Filesystem Component", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "symfony/polyfill-ctype": "~1.8" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Filesystem\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/finder/.gitattributes b/vendor/symfony/finder/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/finder/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/finder/CHANGELOG.md b/vendor/symfony/finder/CHANGELOG.md new file mode 100644 index 0000000..33f5bd5 --- /dev/null +++ b/vendor/symfony/finder/CHANGELOG.md @@ -0,0 +1,79 @@ +CHANGELOG +========= + +5.0.0 +----- + + * added `$useNaturalSort` argument to `Finder::sortByName()` + +4.3.0 +----- + + * added Finder::ignoreVCSIgnored() to ignore files based on rules listed in .gitignore + +4.2.0 +----- + + * added $useNaturalSort option to Finder::sortByName() method + * the `Finder::sortByName()` method will have a new `$useNaturalSort` + argument in version 5.0, not defining it is deprecated + * added `Finder::reverseSorting()` to reverse the sorting + +4.0.0 +----- + + * removed `ExceptionInterface` + * removed `Symfony\Component\Finder\Iterator\FilterIterator` + +3.4.0 +----- + + * deprecated `Symfony\Component\Finder\Iterator\FilterIterator` + * added Finder::hasResults() method to check if any results were found + +3.3.0 +----- + + * added double-star matching to Glob::toRegex() + +3.0.0 +----- + + * removed deprecated classes + +2.8.0 +----- + + * deprecated adapters and related classes + +2.5.0 +----- + * added support for GLOB_BRACE in the paths passed to Finder::in() + +2.3.0 +----- + + * added a way to ignore unreadable directories (via Finder::ignoreUnreadableDirs()) + * unified the way subfolders that are not executable are handled by always throwing an AccessDeniedException exception + +2.2.0 +----- + + * added Finder::path() and Finder::notPath() methods + * added finder adapters to improve performance on specific platforms + * added support for wildcard characters (glob patterns) in the paths passed + to Finder::in() + +2.1.0 +----- + + * added Finder::sortByAccessedTime(), Finder::sortByChangedTime(), and + Finder::sortByModifiedTime() + * added Countable to Finder + * added support for an array of directories as an argument to + Finder::exclude() + * added searching based on the file content via Finder::contains() and + Finder::notContains() + * added support for the != operator in the Comparator + * [BC BREAK] filter expressions (used for file name and content) are no more + considered as regexps but glob patterns when they are enclosed in '*' or '?' diff --git a/vendor/symfony/finder/Comparator/Comparator.php b/vendor/symfony/finder/Comparator/Comparator.php new file mode 100644 index 0000000..cfe3965 --- /dev/null +++ b/vendor/symfony/finder/Comparator/Comparator.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Comparator; + +/** + * Comparator. + * + * @author Fabien Potencier + */ +class Comparator +{ + private $target; + private $operator = '=='; + + /** + * Gets the target value. + * + * @return string The target value + */ + public function getTarget() + { + return $this->target; + } + + public function setTarget(string $target) + { + $this->target = $target; + } + + /** + * Gets the comparison operator. + * + * @return string The operator + */ + public function getOperator() + { + return $this->operator; + } + + /** + * Sets the comparison operator. + * + * @throws \InvalidArgumentException + */ + public function setOperator(string $operator) + { + if ('' === $operator) { + $operator = '=='; + } + + if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) { + throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator)); + } + + $this->operator = $operator; + } + + /** + * Tests against the target. + * + * @param mixed $test A test value + * + * @return bool + */ + public function test($test) + { + switch ($this->operator) { + case '>': + return $test > $this->target; + case '>=': + return $test >= $this->target; + case '<': + return $test < $this->target; + case '<=': + return $test <= $this->target; + case '!=': + return $test != $this->target; + } + + return $test == $this->target; + } +} diff --git a/vendor/symfony/finder/Comparator/DateComparator.php b/vendor/symfony/finder/Comparator/DateComparator.php new file mode 100644 index 0000000..d17c77a --- /dev/null +++ b/vendor/symfony/finder/Comparator/DateComparator.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Comparator; + +/** + * DateCompare compiles date comparisons. + * + * @author Fabien Potencier + */ +class DateComparator extends Comparator +{ + /** + * @param string $test A comparison string + * + * @throws \InvalidArgumentException If the test is not understood + */ + public function __construct(string $test) + { + if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) { + throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test)); + } + + try { + $date = new \DateTime($matches[2]); + $target = $date->format('U'); + } catch (\Exception $e) { + throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2])); + } + + $operator = isset($matches[1]) ? $matches[1] : '=='; + if ('since' === $operator || 'after' === $operator) { + $operator = '>'; + } + + if ('until' === $operator || 'before' === $operator) { + $operator = '<'; + } + + $this->setOperator($operator); + $this->setTarget($target); + } +} diff --git a/vendor/symfony/finder/Comparator/NumberComparator.php b/vendor/symfony/finder/Comparator/NumberComparator.php new file mode 100644 index 0000000..80667c9 --- /dev/null +++ b/vendor/symfony/finder/Comparator/NumberComparator.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Comparator; + +/** + * NumberComparator compiles a simple comparison to an anonymous + * subroutine, which you can call with a value to be tested again. + * + * Now this would be very pointless, if NumberCompare didn't understand + * magnitudes. + * + * The target value may use magnitudes of kilobytes (k, ki), + * megabytes (m, mi), or gigabytes (g, gi). Those suffixed + * with an i use the appropriate 2**n version in accordance with the + * IEC standard: http://physics.nist.gov/cuu/Units/binary.html + * + * Based on the Perl Number::Compare module. + * + * @author Fabien Potencier PHP port + * @author Richard Clamp Perl version + * @copyright 2004-2005 Fabien Potencier + * @copyright 2002 Richard Clamp + * + * @see http://physics.nist.gov/cuu/Units/binary.html + */ +class NumberComparator extends Comparator +{ + /** + * @param string|int $test A comparison string or an integer + * + * @throws \InvalidArgumentException If the test is not understood + */ + public function __construct(?string $test) + { + if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) { + throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test)); + } + + $target = $matches[2]; + if (!is_numeric($target)) { + throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target)); + } + if (isset($matches[3])) { + // magnitude + switch (strtolower($matches[3])) { + case 'k': + $target *= 1000; + break; + case 'ki': + $target *= 1024; + break; + case 'm': + $target *= 1000000; + break; + case 'mi': + $target *= 1024 * 1024; + break; + case 'g': + $target *= 1000000000; + break; + case 'gi': + $target *= 1024 * 1024 * 1024; + break; + } + } + + $this->setTarget($target); + $this->setOperator(isset($matches[1]) ? $matches[1] : '=='); + } +} diff --git a/vendor/symfony/finder/Exception/AccessDeniedException.php b/vendor/symfony/finder/Exception/AccessDeniedException.php new file mode 100644 index 0000000..ee195ea --- /dev/null +++ b/vendor/symfony/finder/Exception/AccessDeniedException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Exception; + +/** + * @author Jean-François Simon + */ +class AccessDeniedException extends \UnexpectedValueException +{ +} diff --git a/vendor/symfony/finder/Exception/DirectoryNotFoundException.php b/vendor/symfony/finder/Exception/DirectoryNotFoundException.php new file mode 100644 index 0000000..c6cc0f2 --- /dev/null +++ b/vendor/symfony/finder/Exception/DirectoryNotFoundException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Exception; + +/** + * @author Andreas Erhard + */ +class DirectoryNotFoundException extends \InvalidArgumentException +{ +} diff --git a/vendor/symfony/finder/Finder.php b/vendor/symfony/finder/Finder.php new file mode 100644 index 0000000..da1c6ab --- /dev/null +++ b/vendor/symfony/finder/Finder.php @@ -0,0 +1,793 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder; + +use Symfony\Component\Finder\Comparator\DateComparator; +use Symfony\Component\Finder\Comparator\NumberComparator; +use Symfony\Component\Finder\Exception\DirectoryNotFoundException; +use Symfony\Component\Finder\Iterator\CustomFilterIterator; +use Symfony\Component\Finder\Iterator\DateRangeFilterIterator; +use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator; +use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator; +use Symfony\Component\Finder\Iterator\FilecontentFilterIterator; +use Symfony\Component\Finder\Iterator\FilenameFilterIterator; +use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator; +use Symfony\Component\Finder\Iterator\SortableIterator; + +/** + * Finder allows to build rules to find files and directories. + * + * It is a thin wrapper around several specialized iterator classes. + * + * All rules may be invoked several times. + * + * All methods return the current Finder object to allow chaining: + * + * $finder = Finder::create()->files()->name('*.php')->in(__DIR__); + * + * @author Fabien Potencier + */ +class Finder implements \IteratorAggregate, \Countable +{ + const IGNORE_VCS_FILES = 1; + const IGNORE_DOT_FILES = 2; + const IGNORE_VCS_IGNORED_FILES = 4; + + private $mode = 0; + private $names = []; + private $notNames = []; + private $exclude = []; + private $filters = []; + private $depths = []; + private $sizes = []; + private $followLinks = false; + private $reverseSorting = false; + private $sort = false; + private $ignore = 0; + private $dirs = []; + private $dates = []; + private $iterators = []; + private $contains = []; + private $notContains = []; + private $paths = []; + private $notPaths = []; + private $ignoreUnreadableDirs = false; + + private static $vcsPatterns = ['.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg']; + + public function __construct() + { + $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES; + } + + /** + * Creates a new Finder. + * + * @return static + */ + public static function create() + { + return new static(); + } + + /** + * Restricts the matching to directories only. + * + * @return $this + */ + public function directories() + { + $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES; + + return $this; + } + + /** + * Restricts the matching to files only. + * + * @return $this + */ + public function files() + { + $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES; + + return $this; + } + + /** + * Adds tests for the directory depth. + * + * Usage: + * + * $finder->depth('> 1') // the Finder will start matching at level 1. + * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point. + * $finder->depth(['>= 1', '< 3']) + * + * @param string|int|string[]|int[] $levels The depth level expression or an array of depth levels + * + * @return $this + * + * @see DepthRangeFilterIterator + * @see NumberComparator + */ + public function depth($levels) + { + foreach ((array) $levels as $level) { + $this->depths[] = new Comparator\NumberComparator($level); + } + + return $this; + } + + /** + * Adds tests for file dates (last modified). + * + * The date must be something that strtotime() is able to parse: + * + * $finder->date('since yesterday'); + * $finder->date('until 2 days ago'); + * $finder->date('> now - 2 hours'); + * $finder->date('>= 2005-10-15'); + * $finder->date(['>= 2005-10-15', '<= 2006-05-27']); + * + * @param string|string[] $dates A date range string or an array of date ranges + * + * @return $this + * + * @see strtotime + * @see DateRangeFilterIterator + * @see DateComparator + */ + public function date($dates) + { + foreach ((array) $dates as $date) { + $this->dates[] = new Comparator\DateComparator($date); + } + + return $this; + } + + /** + * Adds rules that files must match. + * + * You can use patterns (delimited with / sign), globs or simple strings. + * + * $finder->name('*.php') + * $finder->name('/\.php$/') // same as above + * $finder->name('test.php') + * $finder->name(['test.py', 'test.php']) + * + * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns + * + * @return $this + * + * @see FilenameFilterIterator + */ + public function name($patterns) + { + $this->names = array_merge($this->names, (array) $patterns); + + return $this; + } + + /** + * Adds rules that files must not match. + * + * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns + * + * @return $this + * + * @see FilenameFilterIterator + */ + public function notName($patterns) + { + $this->notNames = array_merge($this->notNames, (array) $patterns); + + return $this; + } + + /** + * Adds tests that file contents must match. + * + * Strings or PCRE patterns can be used: + * + * $finder->contains('Lorem ipsum') + * $finder->contains('/Lorem ipsum/i') + * $finder->contains(['dolor', '/ipsum/i']) + * + * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns + * + * @return $this + * + * @see FilecontentFilterIterator + */ + public function contains($patterns) + { + $this->contains = array_merge($this->contains, (array) $patterns); + + return $this; + } + + /** + * Adds tests that file contents must not match. + * + * Strings or PCRE patterns can be used: + * + * $finder->notContains('Lorem ipsum') + * $finder->notContains('/Lorem ipsum/i') + * $finder->notContains(['lorem', '/dolor/i']) + * + * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns + * + * @return $this + * + * @see FilecontentFilterIterator + */ + public function notContains($patterns) + { + $this->notContains = array_merge($this->notContains, (array) $patterns); + + return $this; + } + + /** + * Adds rules that filenames must match. + * + * You can use patterns (delimited with / sign) or simple strings. + * + * $finder->path('some/special/dir') + * $finder->path('/some\/special\/dir/') // same as above + * $finder->path(['some dir', 'another/dir']) + * + * Use only / as dirname separator. + * + * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns + * + * @return $this + * + * @see FilenameFilterIterator + */ + public function path($patterns) + { + $this->paths = array_merge($this->paths, (array) $patterns); + + return $this; + } + + /** + * Adds rules that filenames must not match. + * + * You can use patterns (delimited with / sign) or simple strings. + * + * $finder->notPath('some/special/dir') + * $finder->notPath('/some\/special\/dir/') // same as above + * $finder->notPath(['some/file.txt', 'another/file.log']) + * + * Use only / as dirname separator. + * + * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns + * + * @return $this + * + * @see FilenameFilterIterator + */ + public function notPath($patterns) + { + $this->notPaths = array_merge($this->notPaths, (array) $patterns); + + return $this; + } + + /** + * Adds tests for file sizes. + * + * $finder->size('> 10K'); + * $finder->size('<= 1Ki'); + * $finder->size(4); + * $finder->size(['> 10K', '< 20K']) + * + * @param string|int|string[]|int[] $sizes A size range string or an integer or an array of size ranges + * + * @return $this + * + * @see SizeRangeFilterIterator + * @see NumberComparator + */ + public function size($sizes) + { + foreach ((array) $sizes as $size) { + $this->sizes[] = new Comparator\NumberComparator($size); + } + + return $this; + } + + /** + * Excludes directories. + * + * Directories passed as argument must be relative to the ones defined with the `in()` method. For example: + * + * $finder->in(__DIR__)->exclude('ruby'); + * + * @param string|array $dirs A directory path or an array of directories + * + * @return $this + * + * @see ExcludeDirectoryFilterIterator + */ + public function exclude($dirs) + { + $this->exclude = array_merge($this->exclude, (array) $dirs); + + return $this; + } + + /** + * Excludes "hidden" directories and files (starting with a dot). + * + * This option is enabled by default. + * + * @return $this + * + * @see ExcludeDirectoryFilterIterator + */ + public function ignoreDotFiles(bool $ignoreDotFiles) + { + if ($ignoreDotFiles) { + $this->ignore |= static::IGNORE_DOT_FILES; + } else { + $this->ignore &= ~static::IGNORE_DOT_FILES; + } + + return $this; + } + + /** + * Forces the finder to ignore version control directories. + * + * This option is enabled by default. + * + * @return $this + * + * @see ExcludeDirectoryFilterIterator + */ + public function ignoreVCS(bool $ignoreVCS) + { + if ($ignoreVCS) { + $this->ignore |= static::IGNORE_VCS_FILES; + } else { + $this->ignore &= ~static::IGNORE_VCS_FILES; + } + + return $this; + } + + /** + * Forces Finder to obey .gitignore and ignore files based on rules listed there. + * + * This option is disabled by default. + * + * @return $this + */ + public function ignoreVCSIgnored(bool $ignoreVCSIgnored) + { + if ($ignoreVCSIgnored) { + $this->ignore |= static::IGNORE_VCS_IGNORED_FILES; + } else { + $this->ignore &= ~static::IGNORE_VCS_IGNORED_FILES; + } + + return $this; + } + + /** + * Adds VCS patterns. + * + * @see ignoreVCS() + * + * @param string|string[] $pattern VCS patterns to ignore + */ + public static function addVCSPattern($pattern) + { + foreach ((array) $pattern as $p) { + self::$vcsPatterns[] = $p; + } + + self::$vcsPatterns = array_unique(self::$vcsPatterns); + } + + /** + * Sorts files and directories by an anonymous function. + * + * The anonymous function receives two \SplFileInfo instances to compare. + * + * This can be slow as all the matching files and directories must be retrieved for comparison. + * + * @return $this + * + * @see SortableIterator + */ + public function sort(\Closure $closure) + { + $this->sort = $closure; + + return $this; + } + + /** + * Sorts files and directories by name. + * + * This can be slow as all the matching files and directories must be retrieved for comparison. + * + * @return $this + * + * @see SortableIterator + */ + public function sortByName(bool $useNaturalSort = false) + { + $this->sort = $useNaturalSort ? Iterator\SortableIterator::SORT_BY_NAME_NATURAL : Iterator\SortableIterator::SORT_BY_NAME; + + return $this; + } + + /** + * Sorts files and directories by type (directories before files), then by name. + * + * This can be slow as all the matching files and directories must be retrieved for comparison. + * + * @return $this + * + * @see SortableIterator + */ + public function sortByType() + { + $this->sort = Iterator\SortableIterator::SORT_BY_TYPE; + + return $this; + } + + /** + * Sorts files and directories by the last accessed time. + * + * This is the time that the file was last accessed, read or written to. + * + * This can be slow as all the matching files and directories must be retrieved for comparison. + * + * @return $this + * + * @see SortableIterator + */ + public function sortByAccessedTime() + { + $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME; + + return $this; + } + + /** + * Reverses the sorting. + * + * @return $this + */ + public function reverseSorting() + { + $this->reverseSorting = true; + + return $this; + } + + /** + * Sorts files and directories by the last inode changed time. + * + * This is the time that the inode information was last modified (permissions, owner, group or other metadata). + * + * On Windows, since inode is not available, changed time is actually the file creation time. + * + * This can be slow as all the matching files and directories must be retrieved for comparison. + * + * @return $this + * + * @see SortableIterator + */ + public function sortByChangedTime() + { + $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME; + + return $this; + } + + /** + * Sorts files and directories by the last modified time. + * + * This is the last time the actual contents of the file were last modified. + * + * This can be slow as all the matching files and directories must be retrieved for comparison. + * + * @return $this + * + * @see SortableIterator + */ + public function sortByModifiedTime() + { + $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME; + + return $this; + } + + /** + * Filters the iterator with an anonymous function. + * + * The anonymous function receives a \SplFileInfo and must return false + * to remove files. + * + * @return $this + * + * @see CustomFilterIterator + */ + public function filter(\Closure $closure) + { + $this->filters[] = $closure; + + return $this; + } + + /** + * Forces the following of symlinks. + * + * @return $this + */ + public function followLinks() + { + $this->followLinks = true; + + return $this; + } + + /** + * Tells finder to ignore unreadable directories. + * + * By default, scanning unreadable directories content throws an AccessDeniedException. + * + * @return $this + */ + public function ignoreUnreadableDirs(bool $ignore = true) + { + $this->ignoreUnreadableDirs = $ignore; + + return $this; + } + + /** + * Searches files and directories which match defined rules. + * + * @param string|string[] $dirs A directory path or an array of directories + * + * @return $this + * + * @throws DirectoryNotFoundException if one of the directories does not exist + */ + public function in($dirs) + { + $resolvedDirs = []; + + foreach ((array) $dirs as $dir) { + if (is_dir($dir)) { + $resolvedDirs[] = $this->normalizeDir($dir); + } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR | GLOB_NOSORT)) { + sort($glob); + $resolvedDirs = array_merge($resolvedDirs, array_map([$this, 'normalizeDir'], $glob)); + } else { + throw new DirectoryNotFoundException(sprintf('The "%s" directory does not exist.', $dir)); + } + } + + $this->dirs = array_merge($this->dirs, $resolvedDirs); + + return $this; + } + + /** + * Returns an Iterator for the current Finder configuration. + * + * This method implements the IteratorAggregate interface. + * + * @return \Iterator|SplFileInfo[] An iterator + * + * @throws \LogicException if the in() method has not been called + */ + public function getIterator() + { + if (0 === \count($this->dirs) && 0 === \count($this->iterators)) { + throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.'); + } + + if (1 === \count($this->dirs) && 0 === \count($this->iterators)) { + return $this->searchInDirectory($this->dirs[0]); + } + + $iterator = new \AppendIterator(); + foreach ($this->dirs as $dir) { + $iterator->append($this->searchInDirectory($dir)); + } + + foreach ($this->iterators as $it) { + $iterator->append($it); + } + + return $iterator; + } + + /** + * Appends an existing set of files/directories to the finder. + * + * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array. + * + * @return $this + * + * @throws \InvalidArgumentException when the given argument is not iterable + */ + public function append(iterable $iterator) + { + if ($iterator instanceof \IteratorAggregate) { + $this->iterators[] = $iterator->getIterator(); + } elseif ($iterator instanceof \Iterator) { + $this->iterators[] = $iterator; + } elseif ($iterator instanceof \Traversable || \is_array($iterator)) { + $it = new \ArrayIterator(); + foreach ($iterator as $file) { + $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file)); + } + $this->iterators[] = $it; + } else { + throw new \InvalidArgumentException('Finder::append() method wrong argument type.'); + } + + return $this; + } + + /** + * Check if the any results were found. + * + * @return bool + */ + public function hasResults() + { + foreach ($this->getIterator() as $_) { + return true; + } + + return false; + } + + /** + * Counts all the results collected by the iterators. + * + * @return int + */ + public function count() + { + return iterator_count($this->getIterator()); + } + + private function searchInDirectory(string $dir): \Iterator + { + $exclude = $this->exclude; + $notPaths = $this->notPaths; + + if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) { + $exclude = array_merge($exclude, self::$vcsPatterns); + } + + if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) { + $notPaths[] = '#(^|/)\..+(/|$)#'; + } + + if (static::IGNORE_VCS_IGNORED_FILES === (static::IGNORE_VCS_IGNORED_FILES & $this->ignore)) { + $gitignoreFilePath = sprintf('%s/.gitignore', $dir); + if (!is_readable($gitignoreFilePath)) { + throw new \RuntimeException(sprintf('The "ignoreVCSIgnored" option cannot be used by the Finder as the "%s" file is not readable.', $gitignoreFilePath)); + } + $notPaths = array_merge($notPaths, [Gitignore::toRegex(file_get_contents($gitignoreFilePath))]); + } + + $minDepth = 0; + $maxDepth = PHP_INT_MAX; + + foreach ($this->depths as $comparator) { + switch ($comparator->getOperator()) { + case '>': + $minDepth = $comparator->getTarget() + 1; + break; + case '>=': + $minDepth = $comparator->getTarget(); + break; + case '<': + $maxDepth = $comparator->getTarget() - 1; + break; + case '<=': + $maxDepth = $comparator->getTarget(); + break; + default: + $minDepth = $maxDepth = $comparator->getTarget(); + } + } + + $flags = \RecursiveDirectoryIterator::SKIP_DOTS; + + if ($this->followLinks) { + $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS; + } + + $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs); + + if ($exclude) { + $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $exclude); + } + + $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST); + + if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) { + $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth); + } + + if ($this->mode) { + $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode); + } + + if ($this->names || $this->notNames) { + $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames); + } + + if ($this->contains || $this->notContains) { + $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); + } + + if ($this->sizes) { + $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes); + } + + if ($this->dates) { + $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates); + } + + if ($this->filters) { + $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); + } + + if ($this->paths || $notPaths) { + $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $notPaths); + } + + if ($this->sort || $this->reverseSorting) { + $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort, $this->reverseSorting); + $iterator = $iteratorAggregate->getIterator(); + } + + return $iterator; + } + + /** + * Normalizes given directory names by removing trailing slashes. + * + * Excluding: (s)ftp:// or ssh2.(s)ftp:// wrapper + */ + private function normalizeDir(string $dir): string + { + $dir = rtrim($dir, '/'.\DIRECTORY_SEPARATOR); + + if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) { + $dir .= '/'; + } + + return $dir; + } +} diff --git a/vendor/symfony/finder/Gitignore.php b/vendor/symfony/finder/Gitignore.php new file mode 100644 index 0000000..5ffe585 --- /dev/null +++ b/vendor/symfony/finder/Gitignore.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder; + +/** + * Gitignore matches against text. + * + * @author Ahmed Abdou + */ +class Gitignore +{ + /** + * Returns a regexp which is the equivalent of the gitignore pattern. + * + * @return string The regexp + */ + public static function toRegex(string $gitignoreFileContent): string + { + $gitignoreFileContent = preg_replace('/^[^\\\r\n]*#.*/m', '', $gitignoreFileContent); + $gitignoreLines = preg_split('/\r\n|\r|\n/', $gitignoreFileContent); + $gitignoreLines = array_map('trim', $gitignoreLines); + $gitignoreLines = array_filter($gitignoreLines); + + $ignoreLinesPositive = array_filter($gitignoreLines, function (string $line) { + return !preg_match('/^!/', $line); + }); + + $ignoreLinesNegative = array_filter($gitignoreLines, function (string $line) { + return preg_match('/^!/', $line); + }); + + $ignoreLinesNegative = array_map(function (string $line) { + return preg_replace('/^!(.*)/', '${1}', $line); + }, $ignoreLinesNegative); + $ignoreLinesNegative = array_map([__CLASS__, 'getRegexFromGitignore'], $ignoreLinesNegative); + + $ignoreLinesPositive = array_map([__CLASS__, 'getRegexFromGitignore'], $ignoreLinesPositive); + if (empty($ignoreLinesPositive)) { + return '/^$/'; + } + + if (empty($ignoreLinesNegative)) { + return sprintf('/%s/', implode('|', $ignoreLinesPositive)); + } + + return sprintf('/(?=^(?:(?!(%s)).)*$)(%s)/', implode('|', $ignoreLinesNegative), implode('|', $ignoreLinesPositive)); + } + + private static function getRegexFromGitignore(string $gitignorePattern): string + { + $regex = '('; + if (0 === strpos($gitignorePattern, '/')) { + $gitignorePattern = substr($gitignorePattern, 1); + $regex .= '^'; + } else { + $regex .= '(^|\/)'; + } + + if ('/' === $gitignorePattern[\strlen($gitignorePattern) - 1]) { + $gitignorePattern = substr($gitignorePattern, 0, -1); + } + + $iMax = \strlen($gitignorePattern); + for ($i = 0; $i < $iMax; ++$i) { + $doubleChars = substr($gitignorePattern, $i, 2); + if ('**' === $doubleChars) { + $regex .= '.+'; + ++$i; + continue; + } + + $c = $gitignorePattern[$i]; + switch ($c) { + case '*': + $regex .= '[^\/]+'; + break; + case '/': + case '.': + case ':': + case '(': + case ')': + case '{': + case '}': + $regex .= '\\'.$c; + break; + default: + $regex .= $c; + } + } + + $regex .= '($|\/)'; + $regex .= ')'; + + return $regex; + } +} diff --git a/vendor/symfony/finder/Glob.php b/vendor/symfony/finder/Glob.php new file mode 100644 index 0000000..8447932 --- /dev/null +++ b/vendor/symfony/finder/Glob.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder; + +/** + * Glob matches globbing patterns against text. + * + * if match_glob("foo.*", "foo.bar") echo "matched\n"; + * + * // prints foo.bar and foo.baz + * $regex = glob_to_regex("foo.*"); + * for (['foo.bar', 'foo.baz', 'foo', 'bar'] as $t) + * { + * if (/$regex/) echo "matched: $car\n"; + * } + * + * Glob implements glob(3) style matching that can be used to match + * against text, rather than fetching names from a filesystem. + * + * Based on the Perl Text::Glob module. + * + * @author Fabien Potencier PHP port + * @author Richard Clamp Perl version + * @copyright 2004-2005 Fabien Potencier + * @copyright 2002 Richard Clamp + */ +class Glob +{ + /** + * Returns a regexp which is the equivalent of the glob pattern. + * + * @return string + */ + public static function toRegex(string $glob, bool $strictLeadingDot = true, bool $strictWildcardSlash = true, string $delimiter = '#') + { + $firstByte = true; + $escaping = false; + $inCurlies = 0; + $regex = ''; + $sizeGlob = \strlen($glob); + for ($i = 0; $i < $sizeGlob; ++$i) { + $car = $glob[$i]; + if ($firstByte && $strictLeadingDot && '.' !== $car) { + $regex .= '(?=[^\.])'; + } + + $firstByte = '/' === $car; + + if ($firstByte && $strictWildcardSlash && isset($glob[$i + 2]) && '**' === $glob[$i + 1].$glob[$i + 2] && (!isset($glob[$i + 3]) || '/' === $glob[$i + 3])) { + $car = '[^/]++/'; + if (!isset($glob[$i + 3])) { + $car .= '?'; + } + + if ($strictLeadingDot) { + $car = '(?=[^\.])'.$car; + } + + $car = '/(?:'.$car.')*'; + $i += 2 + isset($glob[$i + 3]); + + if ('/' === $delimiter) { + $car = str_replace('/', '\\/', $car); + } + } + + if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { + $regex .= "\\$car"; + } elseif ('*' === $car) { + $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); + } elseif ('?' === $car) { + $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); + } elseif ('{' === $car) { + $regex .= $escaping ? '\\{' : '('; + if (!$escaping) { + ++$inCurlies; + } + } elseif ('}' === $car && $inCurlies) { + $regex .= $escaping ? '}' : ')'; + if (!$escaping) { + --$inCurlies; + } + } elseif (',' === $car && $inCurlies) { + $regex .= $escaping ? ',' : '|'; + } elseif ('\\' === $car) { + if ($escaping) { + $regex .= '\\\\'; + $escaping = false; + } else { + $escaping = true; + } + + continue; + } else { + $regex .= $car; + } + $escaping = false; + } + + return $delimiter.'^'.$regex.'$'.$delimiter; + } +} diff --git a/vendor/symfony/finder/Iterator/CustomFilterIterator.php b/vendor/symfony/finder/Iterator/CustomFilterIterator.php new file mode 100644 index 0000000..a30bbd0 --- /dev/null +++ b/vendor/symfony/finder/Iterator/CustomFilterIterator.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +/** + * CustomFilterIterator filters files by applying anonymous functions. + * + * The anonymous function receives a \SplFileInfo and must return false + * to remove files. + * + * @author Fabien Potencier + */ +class CustomFilterIterator extends \FilterIterator +{ + private $filters = []; + + /** + * @param \Iterator $iterator The Iterator to filter + * @param callable[] $filters An array of PHP callbacks + * + * @throws \InvalidArgumentException + */ + public function __construct(\Iterator $iterator, array $filters) + { + foreach ($filters as $filter) { + if (!\is_callable($filter)) { + throw new \InvalidArgumentException('Invalid PHP callback.'); + } + } + $this->filters = $filters; + + parent::__construct($iterator); + } + + /** + * Filters the iterator values. + * + * @return bool true if the value should be kept, false otherwise + */ + public function accept() + { + $fileinfo = $this->current(); + + foreach ($this->filters as $filter) { + if (false === $filter($fileinfo)) { + return false; + } + } + + return true; + } +} diff --git a/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php b/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php new file mode 100644 index 0000000..2e97e00 --- /dev/null +++ b/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +use Symfony\Component\Finder\Comparator\DateComparator; + +/** + * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates). + * + * @author Fabien Potencier + */ +class DateRangeFilterIterator extends \FilterIterator +{ + private $comparators = []; + + /** + * @param \Iterator $iterator The Iterator to filter + * @param DateComparator[] $comparators An array of DateComparator instances + */ + public function __construct(\Iterator $iterator, array $comparators) + { + $this->comparators = $comparators; + + parent::__construct($iterator); + } + + /** + * Filters the iterator values. + * + * @return bool true if the value should be kept, false otherwise + */ + public function accept() + { + $fileinfo = $this->current(); + + if (!file_exists($fileinfo->getPathname())) { + return false; + } + + $filedate = $fileinfo->getMTime(); + foreach ($this->comparators as $compare) { + if (!$compare->test($filedate)) { + return false; + } + } + + return true; + } +} diff --git a/vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php b/vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php new file mode 100644 index 0000000..436a66d --- /dev/null +++ b/vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +/** + * DepthRangeFilterIterator limits the directory depth. + * + * @author Fabien Potencier + */ +class DepthRangeFilterIterator extends \FilterIterator +{ + private $minDepth = 0; + + /** + * @param \RecursiveIteratorIterator $iterator The Iterator to filter + * @param int $minDepth The min depth + * @param int $maxDepth The max depth + */ + public function __construct(\RecursiveIteratorIterator $iterator, int $minDepth = 0, int $maxDepth = PHP_INT_MAX) + { + $this->minDepth = $minDepth; + $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth); + + parent::__construct($iterator); + } + + /** + * Filters the iterator values. + * + * @return bool true if the value should be kept, false otherwise + */ + public function accept() + { + return $this->getInnerIterator()->getDepth() >= $this->minDepth; + } +} diff --git a/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php b/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php new file mode 100644 index 0000000..6a1b291 --- /dev/null +++ b/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +/** + * ExcludeDirectoryFilterIterator filters out directories. + * + * @author Fabien Potencier + */ +class ExcludeDirectoryFilterIterator extends \FilterIterator implements \RecursiveIterator +{ + private $iterator; + private $isRecursive; + private $excludedDirs = []; + private $excludedPattern; + + /** + * @param \Iterator $iterator The Iterator to filter + * @param string[] $directories An array of directories to exclude + */ + public function __construct(\Iterator $iterator, array $directories) + { + $this->iterator = $iterator; + $this->isRecursive = $iterator instanceof \RecursiveIterator; + $patterns = []; + foreach ($directories as $directory) { + $directory = rtrim($directory, '/'); + if (!$this->isRecursive || false !== strpos($directory, '/')) { + $patterns[] = preg_quote($directory, '#'); + } else { + $this->excludedDirs[$directory] = true; + } + } + if ($patterns) { + $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#'; + } + + parent::__construct($iterator); + } + + /** + * Filters the iterator values. + * + * @return bool True if the value should be kept, false otherwise + */ + public function accept() + { + if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) { + return false; + } + + if ($this->excludedPattern) { + $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath(); + $path = str_replace('\\', '/', $path); + + return !preg_match($this->excludedPattern, $path); + } + + return true; + } + + /** + * @return bool + */ + public function hasChildren() + { + return $this->isRecursive && $this->iterator->hasChildren(); + } + + public function getChildren() + { + $children = new self($this->iterator->getChildren(), []); + $children->excludedDirs = $this->excludedDirs; + $children->excludedPattern = $this->excludedPattern; + + return $children; + } +} diff --git a/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php b/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php new file mode 100644 index 0000000..a4c4eec --- /dev/null +++ b/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +/** + * FileTypeFilterIterator only keeps files, directories, or both. + * + * @author Fabien Potencier + */ +class FileTypeFilterIterator extends \FilterIterator +{ + const ONLY_FILES = 1; + const ONLY_DIRECTORIES = 2; + + private $mode; + + /** + * @param \Iterator $iterator The Iterator to filter + * @param int $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) + */ + public function __construct(\Iterator $iterator, int $mode) + { + $this->mode = $mode; + + parent::__construct($iterator); + } + + /** + * Filters the iterator values. + * + * @return bool true if the value should be kept, false otherwise + */ + public function accept() + { + $fileinfo = $this->current(); + if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) { + return false; + } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) { + return false; + } + + return true; + } +} diff --git a/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php b/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php new file mode 100644 index 0000000..b26a368 --- /dev/null +++ b/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +/** + * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings). + * + * @author Fabien Potencier + * @author Włodzimierz Gajda + */ +class FilecontentFilterIterator extends MultiplePcreFilterIterator +{ + /** + * Filters the iterator values. + * + * @return bool true if the value should be kept, false otherwise + */ + public function accept() + { + if (!$this->matchRegexps && !$this->noMatchRegexps) { + return true; + } + + $fileinfo = $this->current(); + + if ($fileinfo->isDir() || !$fileinfo->isReadable()) { + return false; + } + + $content = $fileinfo->getContents(); + if (!$content) { + return false; + } + + return $this->isAccepted($content); + } + + /** + * Converts string to regexp if necessary. + * + * @param string $str Pattern: string or regexp + * + * @return string regexp corresponding to a given string or regexp + */ + protected function toRegex(string $str) + { + return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; + } +} diff --git a/vendor/symfony/finder/Iterator/FilenameFilterIterator.php b/vendor/symfony/finder/Iterator/FilenameFilterIterator.php new file mode 100644 index 0000000..dedd1ca --- /dev/null +++ b/vendor/symfony/finder/Iterator/FilenameFilterIterator.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +use Symfony\Component\Finder\Glob; + +/** + * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string). + * + * @author Fabien Potencier + */ +class FilenameFilterIterator extends MultiplePcreFilterIterator +{ + /** + * Filters the iterator values. + * + * @return bool true if the value should be kept, false otherwise + */ + public function accept() + { + return $this->isAccepted($this->current()->getFilename()); + } + + /** + * Converts glob to regexp. + * + * PCRE patterns are left unchanged. + * Glob strings are transformed with Glob::toRegex(). + * + * @param string $str Pattern: glob or regexp + * + * @return string regexp corresponding to a given glob or regexp + */ + protected function toRegex(string $str) + { + return $this->isRegex($str) ? $str : Glob::toRegex($str); + } +} diff --git a/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php b/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php new file mode 100644 index 0000000..78a34ab --- /dev/null +++ b/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +/** + * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings). + * + * @author Fabien Potencier + */ +abstract class MultiplePcreFilterIterator extends \FilterIterator +{ + protected $matchRegexps = []; + protected $noMatchRegexps = []; + + /** + * @param \Iterator $iterator The Iterator to filter + * @param string[] $matchPatterns An array of patterns that need to match + * @param string[] $noMatchPatterns An array of patterns that need to not match + */ + public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns) + { + foreach ($matchPatterns as $pattern) { + $this->matchRegexps[] = $this->toRegex($pattern); + } + + foreach ($noMatchPatterns as $pattern) { + $this->noMatchRegexps[] = $this->toRegex($pattern); + } + + parent::__construct($iterator); + } + + /** + * Checks whether the string is accepted by the regex filters. + * + * If there is no regexps defined in the class, this method will accept the string. + * Such case can be handled by child classes before calling the method if they want to + * apply a different behavior. + * + * @return bool + */ + protected function isAccepted(string $string) + { + // should at least not match one rule to exclude + foreach ($this->noMatchRegexps as $regex) { + if (preg_match($regex, $string)) { + return false; + } + } + + // should at least match one rule + if ($this->matchRegexps) { + foreach ($this->matchRegexps as $regex) { + if (preg_match($regex, $string)) { + return true; + } + } + + return false; + } + + // If there is no match rules, the file is accepted + return true; + } + + /** + * Checks whether the string is a regex. + * + * @return bool + */ + protected function isRegex(string $str) + { + if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) { + $start = substr($m[1], 0, 1); + $end = substr($m[1], -1); + + if ($start === $end) { + return !preg_match('/[*?[:alnum:] \\\\]/', $start); + } + + foreach ([['{', '}'], ['(', ')'], ['[', ']'], ['<', '>']] as $delimiters) { + if ($start === $delimiters[0] && $end === $delimiters[1]) { + return true; + } + } + } + + return false; + } + + /** + * Converts string into regexp. + * + * @return string + */ + abstract protected function toRegex(string $str); +} diff --git a/vendor/symfony/finder/Iterator/PathFilterIterator.php b/vendor/symfony/finder/Iterator/PathFilterIterator.php new file mode 100644 index 0000000..67b71f4 --- /dev/null +++ b/vendor/symfony/finder/Iterator/PathFilterIterator.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +/** + * PathFilterIterator filters files by path patterns (e.g. some/special/dir). + * + * @author Fabien Potencier + * @author Włodzimierz Gajda + */ +class PathFilterIterator extends MultiplePcreFilterIterator +{ + /** + * Filters the iterator values. + * + * @return bool true if the value should be kept, false otherwise + */ + public function accept() + { + $filename = $this->current()->getRelativePathname(); + + if ('\\' === \DIRECTORY_SEPARATOR) { + $filename = str_replace('\\', '/', $filename); + } + + return $this->isAccepted($filename); + } + + /** + * Converts strings to regexp. + * + * PCRE patterns are left unchanged. + * + * Default conversion: + * 'lorem/ipsum/dolor' ==> 'lorem\/ipsum\/dolor/' + * + * Use only / as directory separator (on Windows also). + * + * @param string $str Pattern: regexp or dirname + * + * @return string regexp corresponding to a given string or regexp + */ + protected function toRegex(string $str) + { + return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; + } +} diff --git a/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php b/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php new file mode 100644 index 0000000..3facef5 --- /dev/null +++ b/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +use Symfony\Component\Finder\Exception\AccessDeniedException; +use Symfony\Component\Finder\SplFileInfo; + +/** + * Extends the \RecursiveDirectoryIterator to support relative paths. + * + * @author Victor Berchet + */ +class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator +{ + /** + * @var bool + */ + private $ignoreUnreadableDirs; + + /** + * @var bool + */ + private $rewindable; + + // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations + private $rootPath; + private $subPath; + private $directorySeparator = '/'; + + /** + * @throws \RuntimeException + */ + public function __construct(string $path, int $flags, bool $ignoreUnreadableDirs = false) + { + if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) { + throw new \RuntimeException('This iterator only support returning current as fileinfo.'); + } + + parent::__construct($path, $flags); + $this->ignoreUnreadableDirs = $ignoreUnreadableDirs; + $this->rootPath = $path; + if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) { + $this->directorySeparator = \DIRECTORY_SEPARATOR; + } + } + + /** + * Return an instance of SplFileInfo with support for relative paths. + * + * @return SplFileInfo File information + */ + public function current() + { + // the logic here avoids redoing the same work in all iterations + + if (null === $subPathname = $this->subPath) { + $subPathname = $this->subPath = (string) $this->getSubPath(); + } + if ('' !== $subPathname) { + $subPathname .= $this->directorySeparator; + } + $subPathname .= $this->getFilename(); + + return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname); + } + + /** + * @return \RecursiveIterator + * + * @throws AccessDeniedException + */ + public function getChildren() + { + try { + $children = parent::getChildren(); + + if ($children instanceof self) { + // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore + $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs; + + // performance optimization to avoid redoing the same work in all children + $children->rewindable = &$this->rewindable; + $children->rootPath = $this->rootPath; + } + + return $children; + } catch (\UnexpectedValueException $e) { + if ($this->ignoreUnreadableDirs) { + // If directory is unreadable and finder is set to ignore it, a fake empty content is returned. + return new \RecursiveArrayIterator([]); + } else { + throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); + } + } + } + + /** + * Do nothing for non rewindable stream. + */ + public function rewind() + { + if (false === $this->isRewindable()) { + return; + } + + parent::rewind(); + } + + /** + * Checks if the stream is rewindable. + * + * @return bool true when the stream is rewindable, false otherwise + */ + public function isRewindable() + { + if (null !== $this->rewindable) { + return $this->rewindable; + } + + if (false !== $stream = @opendir($this->getPath())) { + $infos = stream_get_meta_data($stream); + closedir($stream); + + if ($infos['seekable']) { + return $this->rewindable = true; + } + } + + return $this->rewindable = false; + } +} diff --git a/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php b/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php new file mode 100644 index 0000000..2aeef67 --- /dev/null +++ b/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +use Symfony\Component\Finder\Comparator\NumberComparator; + +/** + * SizeRangeFilterIterator filters out files that are not in the given size range. + * + * @author Fabien Potencier + */ +class SizeRangeFilterIterator extends \FilterIterator +{ + private $comparators = []; + + /** + * @param \Iterator $iterator The Iterator to filter + * @param NumberComparator[] $comparators An array of NumberComparator instances + */ + public function __construct(\Iterator $iterator, array $comparators) + { + $this->comparators = $comparators; + + parent::__construct($iterator); + } + + /** + * Filters the iterator values. + * + * @return bool true if the value should be kept, false otherwise + */ + public function accept() + { + $fileinfo = $this->current(); + if (!$fileinfo->isFile()) { + return true; + } + + $filesize = $fileinfo->getSize(); + foreach ($this->comparators as $compare) { + if (!$compare->test($filesize)) { + return false; + } + } + + return true; + } +} diff --git a/vendor/symfony/finder/Iterator/SortableIterator.php b/vendor/symfony/finder/Iterator/SortableIterator.php new file mode 100644 index 0000000..2aca397 --- /dev/null +++ b/vendor/symfony/finder/Iterator/SortableIterator.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Iterator; + +/** + * SortableIterator applies a sort on a given Iterator. + * + * @author Fabien Potencier + */ +class SortableIterator implements \IteratorAggregate +{ + const SORT_BY_NONE = 0; + const SORT_BY_NAME = 1; + const SORT_BY_TYPE = 2; + const SORT_BY_ACCESSED_TIME = 3; + const SORT_BY_CHANGED_TIME = 4; + const SORT_BY_MODIFIED_TIME = 5; + const SORT_BY_NAME_NATURAL = 6; + + private $iterator; + private $sort; + + /** + * @param \Traversable $iterator The Iterator to filter + * @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback) + * + * @throws \InvalidArgumentException + */ + public function __construct(\Traversable $iterator, $sort, bool $reverseOrder = false) + { + $this->iterator = $iterator; + $order = $reverseOrder ? -1 : 1; + + if (self::SORT_BY_NAME === $sort) { + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); + }; + } elseif (self::SORT_BY_NAME_NATURAL === $sort) { + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * strnatcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); + }; + } elseif (self::SORT_BY_TYPE === $sort) { + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + if ($a->isDir() && $b->isFile()) { + return -$order; + } elseif ($a->isFile() && $b->isDir()) { + return $order; + } + + return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); + }; + } elseif (self::SORT_BY_ACCESSED_TIME === $sort) { + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * ($a->getATime() - $b->getATime()); + }; + } elseif (self::SORT_BY_CHANGED_TIME === $sort) { + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * ($a->getCTime() - $b->getCTime()); + }; + } elseif (self::SORT_BY_MODIFIED_TIME === $sort) { + $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { + return $order * ($a->getMTime() - $b->getMTime()); + }; + } elseif (self::SORT_BY_NONE === $sort) { + $this->sort = $order; + } elseif (\is_callable($sort)) { + $this->sort = $reverseOrder ? static function (\SplFileInfo $a, \SplFileInfo $b) use ($sort) { return -$sort($a, $b); } : $sort; + } else { + throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.'); + } + } + + /** + * @return \Traversable + */ + public function getIterator() + { + if (1 === $this->sort) { + return $this->iterator; + } + + $array = iterator_to_array($this->iterator, true); + + if (-1 === $this->sort) { + $array = array_reverse($array); + } else { + uasort($array, $this->sort); + } + + return new \ArrayIterator($array); + } +} diff --git a/vendor/symfony/finder/LICENSE b/vendor/symfony/finder/LICENSE new file mode 100644 index 0000000..a677f43 --- /dev/null +++ b/vendor/symfony/finder/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/finder/README.md b/vendor/symfony/finder/README.md new file mode 100644 index 0000000..0b19c75 --- /dev/null +++ b/vendor/symfony/finder/README.md @@ -0,0 +1,14 @@ +Finder Component +================ + +The Finder component finds files and directories via an intuitive fluent +interface. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/finder.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/finder/SplFileInfo.php b/vendor/symfony/finder/SplFileInfo.php new file mode 100644 index 0000000..65d7423 --- /dev/null +++ b/vendor/symfony/finder/SplFileInfo.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder; + +/** + * Extends \SplFileInfo to support relative paths. + * + * @author Fabien Potencier + */ +class SplFileInfo extends \SplFileInfo +{ + private $relativePath; + private $relativePathname; + + /** + * @param string $file The file name + * @param string $relativePath The relative path + * @param string $relativePathname The relative path name + */ + public function __construct(string $file, string $relativePath, string $relativePathname) + { + parent::__construct($file); + $this->relativePath = $relativePath; + $this->relativePathname = $relativePathname; + } + + /** + * Returns the relative path. + * + * This path does not contain the file name. + * + * @return string the relative path + */ + public function getRelativePath() + { + return $this->relativePath; + } + + /** + * Returns the relative path name. + * + * This path contains the file name. + * + * @return string the relative path name + */ + public function getRelativePathname() + { + return $this->relativePathname; + } + + public function getFilenameWithoutExtension(): string + { + $filename = $this->getFilename(); + + return pathinfo($filename, PATHINFO_FILENAME); + } + + /** + * Returns the contents of the file. + * + * @return string the contents of the file + * + * @throws \RuntimeException + */ + public function getContents() + { + set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); + $content = file_get_contents($this->getPathname()); + restore_error_handler(); + if (false === $content) { + throw new \RuntimeException($error); + } + + return $content; + } +} diff --git a/vendor/symfony/finder/composer.json b/vendor/symfony/finder/composer.json new file mode 100644 index 0000000..65a1988 --- /dev/null +++ b/vendor/symfony/finder/composer.json @@ -0,0 +1,33 @@ +{ + "name": "symfony/finder", + "type": "library", + "description": "Symfony Finder Component", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Finder\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/framework-bundle/.gitattributes b/vendor/symfony/framework-bundle/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/framework-bundle/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/framework-bundle/CHANGELOG.md b/vendor/symfony/framework-bundle/CHANGELOG.md new file mode 100644 index 0000000..8188769 --- /dev/null +++ b/vendor/symfony/framework-bundle/CHANGELOG.md @@ -0,0 +1,413 @@ +CHANGELOG +========= + +5.0.0 +----- + + * Removed support to load translation resources from the legacy directories `src/Resources/translations/` and `src/Resources//translations/` + * Removed `ControllerNameParser`. + * Removed `ResolveControllerNameSubscriber` + * Removed support for `bundle:controller:action` to reference controllers. Use `serviceOrFqcn::method` instead + * Removed support for PHP templating, use Twig instead + * Removed `Controller`, use `AbstractController` instead + * Removed `Client`, use `KernelBrowser` instead + * Removed `ContainerAwareCommand`, use dependency injection instead + * Removed the `validation.strict_email` option, use `validation.email_validation_mode` instead + * Removed the `cache.app.simple` service and its corresponding PSR-16 autowiring alias + * Removed cache-related compiler passes and `RequestDataCollector` + * Removed the `translator.selector` and `session.save_listener` services + * Removed `SecurityUserValueResolver`, use `UserValueResolver` instead + * Removed `routing.loader.service`. + * Service route loaders must be tagged with `routing.route_loader`. + * Added `slugger` service and `SluggerInterface` alias + * Removed the `lock.store.flock`, `lock.store.semaphore`, `lock.store.memcached.abstract` and `lock.store.redis.abstract` services. + +4.4.0 +----- + + * Added `lint:container` command to check that services wiring matches type declarations + * Added `MailerAssertionsTrait` + * Deprecated support for `templating` engine in `TemplateController`, use Twig instead + * Deprecated the `$parser` argument of `ControllerResolver::__construct()` and `DelegatingLoader::__construct()` + * Deprecated the `controller_name_converter` and `resolve_controller_name_subscriber` services + * The `ControllerResolver` and `DelegatingLoader` classes have been marked as `final` + * Added support for configuring chained cache pools + * Deprecated calling `WebTestCase::createClient()` while a kernel has been booted, ensure the kernel is shut down before calling the method + * Deprecated `routing.loader.service`, use `routing.loader.container` instead. + * Not tagging service route loaders with `routing.route_loader` has been deprecated. + * Overriding the methods `KernelTestCase::tearDown()` and `WebTestCase::tearDown()` without the `void` return-type is deprecated. + * Added new `error_controller` configuration to handle system exceptions + * Added sort option for `translation:update` command. + * [BC Break] The `framework.messenger.routing.senders` config key is not deeply merged anymore. + * Added `secrets:*` commands to deal with secrets seamlessly. + * Made `framework.session.handler_id` accept a DSN + * Marked the `RouterDataCollector` class as `@final`. + * [BC Break] The `framework.messenger.buses..middleware` config key is not deeply merged anymore. + +4.3.0 +----- + + * Deprecated the `framework.templating` option, configure the Twig bundle instead. + * Added `WebTestAssertionsTrait` (included by default in `WebTestCase`) + * Renamed `Client` to `KernelBrowser` + * Not passing the project directory to the constructor of the `AssetsInstallCommand` is deprecated. This argument will + be mandatory in 5.0. + * Deprecated the "Psr\SimpleCache\CacheInterface" / "cache.app.simple" service, use "Symfony\Contracts\Cache\CacheInterface" / "cache.app" instead + * Added the ability to specify a custom `serializer` option for each + transport under`framework.messenger.transports`. + * Added the `RegisterLocaleAwareServicesPass` and configured the `LocaleAwareListener` + * [BC Break] When using Messenger, the default transport changed from + using Symfony's serializer service to use `PhpSerializer`, which uses + PHP's native `serialize()` and `unserialize()` functions. To use the + original serialization method, set the `framework.messenger.default_serializer` + config option to `messenger.transport.symfony_serializer`. Or set the + `serializer` option under one specific `transport`. + * [BC Break] The `framework.messenger.serializer` config key changed to + `framework.messenger.default_serializer`, which holds the string service + id and `framework.messenger.symfony_serializer`, which configures the + options if you're using Symfony's serializer. + * [BC Break] Removed the `framework.messenger.routing.send_and_handle` configuration. + Instead of setting it to true, configure a `SyncTransport` and route messages to it. + * Added information about deprecated aliases in `debug:autowiring` + * Added php ini session options `sid_length` and `sid_bits_per_character` + to the `session` section of the configuration + * Added support for Translator paths, Twig paths in translation commands. + * Added support for PHP files with translations in translation commands. + * Added support for boolean container parameters within routes. + * Added the `messenger:setup-transports` command to setup messenger transports + * Added a `InMemoryTransport` to Messenger. Use it with a DSN starting with `in-memory://`. + * Added `framework.property_access.throw_exception_on_invalid_property_path` config option. + * Added `cache:pool:list` command to list all available cache pools. + +4.2.0 +----- + + * Added a `AbstractController::addLink()` method to add Link headers to the current response + * Allowed configuring taggable cache pools via a new `framework.cache.pools.tags` option (bool|service-id) + * Allowed configuring PDO-based cache pools via a new `cache.adapter.pdo` abstract service + * Deprecated auto-injection of the container in AbstractController instances, register them as service subscribers instead + * Deprecated processing of services tagged `security.expression_language_provider` in favor of a new `AddExpressionLanguageProvidersPass` in SecurityBundle. + * Deprecated the `Symfony\Bundle\FrameworkBundle\Controller\Controller` class in favor of `Symfony\Bundle\FrameworkBundle\Controller\AbstractController`. + * Enabled autoconfiguration for `Psr\Log\LoggerAwareInterface` + * Added new "auto" mode for `framework.session.cookie_secure` to turn it on when HTTPS is used + * Removed the `framework.messenger.encoder` and `framework.messenger.decoder` options. Use the `framework.messenger.serializer.id` option to replace the Messenger serializer. + * Deprecated the `ContainerAwareCommand` class in favor of `Symfony\Component\Console\Command\Command` + * Made `debug:container` and `debug:autowiring` ignore backslashes in service ids + * Deprecated the `Templating\Helper\TranslatorHelper::transChoice()` method, use the `trans()` one instead with a `%count%` parameter + * Deprecated `CacheCollectorPass`. Use `Symfony\Component\Cache\DependencyInjection\CacheCollectorPass` instead. + * Deprecated `CachePoolClearerPass`. Use `Symfony\Component\Cache\DependencyInjection\CachePoolClearerPass` instead. + * Deprecated `CachePoolPass`. Use `Symfony\Component\Cache\DependencyInjection\CachePoolPass` instead. + * Deprecated `CachePoolPrunerPass`. Use `Symfony\Component\Cache\DependencyInjection\CachePoolPrunerPass` instead. + * Deprecated support for legacy translations directories `src/Resources/translations/` and `src/Resources//translations/`, use `translations/` instead. + * Deprecated support for the legacy directory structure in `translation:update` and `debug:translation` commands. + +4.1.0 +----- + + * Allowed to pass an optional `LoggerInterface $logger` instance to the `Router` + * Added a new `parameter_bag` service with related autowiring aliases to access parameters as-a-service + * Allowed the `Router` to work with any PSR-11 container + * Added option in workflow dump command to label graph with a custom label + * Using a `RouterInterface` that does not implement the `WarmableInterface` is deprecated. + * Warming up a router in `RouterCacheWarmer` that does not implement the `WarmableInterface` is deprecated and will not + be supported anymore in 5.0. + * The `RequestDataCollector` class has been deprecated. Use the `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector` class instead. + * The `RedirectController` class allows for 307/308 HTTP status codes + * Deprecated `bundle:controller:action` syntax to reference controllers. Use `serviceOrFqcn::method` instead where `serviceOrFqcn` + is either the service ID or the FQCN of the controller. + * Deprecated `Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser` + * The `container.service_locator` tag of `ServiceLocator`s is now autoconfigured. + * Add the ability to search a route in `debug:router`. + * Add the ability to use SameSite cookies for sessions. + +4.0.0 +----- + + * The default `type` option of the `framework.workflows.*` configuration entries is `state_machine` + * removed `AddConsoleCommandPass`, `AddConstraintValidatorsPass`, + `AddValidatorInitializersPass`, `CompilerDebugDumpPass`, `ConfigCachePass`, + `ControllerArgumentValueResolverPass`, `FormPass`, `PropertyInfoPass`, + `RoutingResolverPass`, `SerializerPass`, `ValidateWorkflowsPass` + * made `Translator::__construct()` `$defaultLocale` argument required + * removed `SessionListener`, `TestSessionListener` + * Removed `cache:clear` warmup part along with the `--no-optional-warmers` option + * Removed core form types services registration when unnecessary + * Removed `framework.serializer.cache` option and `serializer.mapping.cache.apc`, `serializer.mapping.cache.doctrine.apc` services + * Removed `ConstraintValidatorFactory` + * Removed class parameters related to routing + * Removed absolute template paths support in the template name parser + * Removed support of the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. + * Removed the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. + * Removed the "framework.validation.cache" configuration option. Configure the "cache.validator" service under "framework.cache.pools" instead. + * Removed `PhpStringTokenParser`, use `Symfony\Component\Translation\Extractor\PhpStringTokenParser` instead. + * Removed `PhpExtractor`, use `Symfony\Component\Translation\Extractor\PhpExtractor` instead. + * Removed the `use_strict_mode` session option, it's is now enabled by default + +3.4.0 +----- + + * Added `translator.default_path` option and parameter + * Session `use_strict_mode` is now enabled by default and the corresponding option has been deprecated + * Made the `cache:clear` command to *not* clear "app" PSR-6 cache pools anymore, + but to still clear "system" ones; use the `cache:pool:clear` command to clear "app" pools instead + * Always register a minimalist logger that writes in `stderr` + * Deprecated `profiler.matcher` option + * Added support for `EventSubscriberInterface` on `MicroKernelTrait` + * Removed `doctrine/cache` from the list of required dependencies in `composer.json` + * Deprecated `validator.mapping.cache.doctrine.apc` service + * The `symfony/stopwatch` dependency has been removed, require it via `composer + require symfony/stopwatch` in your `dev` environment. + * Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. + * Deprecated the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. + * Deprecated `AddCacheClearerPass`, use tagged iterator arguments instead. + * Deprecated `AddCacheWarmerPass`, use tagged iterator arguments instead. + * Deprecated `TranslationDumperPass`, use + `Symfony\Component\Translation\DependencyInjection\TranslationDumperPass` instead + * Deprecated `TranslationExtractorPass`, use + `Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass` instead + * Deprecated `TranslatorPass`, use + `Symfony\Component\Translation\DependencyInjection\TranslatorPass` instead + * Added `command` attribute to the `console.command` tag which takes the command + name as value, using it makes the command lazy + * Added `cache:pool:prune` command to allow manual stale cache item pruning of supported PSR-6 and PSR-16 cache pool + implementations + * Deprecated `Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader`, use + `Symfony\Component\Translation\Reader\TranslationReader` instead + * Deprecated `translation.loader` service, use `translation.reader` instead + * `AssetsInstallCommand::__construct()` now takes an instance of + `Symfony\Component\Filesystem\Filesystem` as first argument + * `CacheClearCommand::__construct()` now takes an instance of + `Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface` as + first argument + * `CachePoolClearCommand::__construct()` now takes an instance of + `Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer` as + first argument + * `EventDispatcherDebugCommand::__construct()` now takes an instance of + `Symfony\Component\EventDispatcher\EventDispatcherInterface` as + first argument + * `RouterDebugCommand::__construct()` now takes an instance of + `Symfony\Component\Routing\RouterInterface` as + first argument + * `RouterMatchCommand::__construct()` now takes an instance of + `Symfony\Component\Routing\RouterInterface` as + first argument + * `TranslationDebugCommand::__construct()` now takes an instance of + `Symfony\Component\Translation\TranslatorInterface` as + first argument + * `TranslationUpdateCommand::__construct()` now takes an instance of + `Symfony\Component\Translation\TranslatorInterface` as + first argument + * `AssetsInstallCommand`, `CacheClearCommand`, `CachePoolClearCommand`, + `EventDispatcherDebugCommand`, `RouterDebugCommand`, `RouterMatchCommand`, + `TranslationDebugCommand`, `TranslationUpdateCommand`, `XliffLintCommand` + and `YamlLintCommand` classes have been marked as final + * Added `asset.request_context.base_path` and `asset.request_context.secure` parameters + to provide a default request context in case the stack is empty (similar to `router.request_context.*` parameters) + * Display environment variables managed by `Dotenv` in `AboutCommand` + +3.3.0 +----- + + * Not defining the `type` option of the `framework.workflows.*` configuration entries is deprecated. + The default value will be `state_machine` in Symfony 4.0. + * Deprecated the `CompilerDebugDumpPass` class + * Deprecated the "framework.trusted_proxies" configuration option and the corresponding "kernel.trusted_proxies" parameter + * Added a new version strategy option called "json_manifest_path" + that allows you to use the `JsonManifestVersionStrategy`. + * Added `Symfony\Bundle\FrameworkBundle\Controller\AbstractController`. It provides + the same helpers as the `Controller` class, but does not allow accessing the dependency + injection container, in order to encourage explicit dependency declarations. + * Added support for the `controller.service_arguments` tag, for injecting services into controllers' actions + * Changed default configuration for + assets/forms/validation/translation/serialization/csrf from `canBeEnabled()` to + `canBeDisabled()` when Flex is used + * The server:* commands and their associated router files were moved to WebServerBundle + * Translation related services are not loaded anymore when the `framework.translator` option + is disabled. + * Added `GlobalVariables::getToken()` + * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass`. Use `Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass` instead. + * Added configurable paths for validation files + * Deprecated `SerializerPass`, use `Symfony\Component\Serializer\DependencyInjection\SerializerPass` instead + * Deprecated `FormPass`, use `Symfony\Component\Form\DependencyInjection\FormPass` instead + * Deprecated `SessionListener` + * Deprecated `TestSessionListener` + * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass`. + Use tagged iterator arguments instead. + * Deprecated `PropertyInfoPass`, use `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass` instead + * Deprecated `ControllerArgumentValueResolverPass`. Use + `Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass` instead + * Deprecated `RoutingResolverPass`, use `Symfony\Component\Routing\DependencyInjection\RoutingResolverPass` instead + * [BC BREAK] The `server:run`, `server:start`, `server:stop` and + `server:status` console commands have been moved to a dedicated bundle. + Require `symfony/web-server-bundle` in your composer.json and register + `Symfony\Bundle\WebServerBundle\WebServerBundle` in your AppKernel to use them. + * Added `$defaultLocale` as 3rd argument of `Translator::__construct()` + making `Translator` works with any PSR-11 container + * Added `framework.serializer.mapping` config option allowing to define custom + serialization mapping files and directories + * Deprecated `AddValidatorInitializersPass`, use + `Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass` instead + * Deprecated `AddConstraintValidatorsPass`, use + `Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass` instead + * Deprecated `ValidateWorkflowsPass`, use + `Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass` instead + * Deprecated `ConstraintValidatorFactory`, use + `Symfony\Component\Validator\ContainerConstraintValidatorFactory` instead. + * Deprecated `PhpStringTokenParser`, use + `Symfony\Component\Translation\Extractor\PhpStringTokenParser` instead. + * Deprecated `PhpExtractor`, use + `Symfony\Component\Translation\Extractor\PhpExtractor` instead. + +3.2.0 +----- + + * Removed `doctrine/annotations` from the list of required dependencies in `composer.json` + * Removed `symfony/security-core` and `symfony/security-csrf` from the list of required dependencies in `composer.json` + * Removed `symfony/templating` from the list of required dependencies in `composer.json` + * Removed `symfony/translation` from the list of required dependencies in `composer.json` + * Removed `symfony/asset` from the list of required dependencies in `composer.json` + * The `Resources/public/images/*` files have been removed. + * The `Resources/public/css/*.css` files have been removed (they are now inlined in TwigBundle). + * Added possibility to prioritize form type extensions with `'priority'` attribute on tags `form.type_extension` + +3.1.0 +----- + + * Added `Controller::json` to simplify creating JSON responses when using the Serializer component + * Deprecated absolute template paths support in the template name parser + * Deprecated using core form types without dependencies as services + * Added `Symfony\Component\HttpHernel\DataCollector\RequestDataCollector::onKernelResponse()` + * Added `Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector` + * The `framework.serializer.cache` option and the service `serializer.mapping.cache.apc` have been + deprecated. APCu should now be automatically used when available. + +3.0.0 +----- + + * removed `validator.api` parameter + * removed `alias` option of the `form.type` tag + +2.8.0 +----- + + * Deprecated the `alias` option of the `form.type_extension` tag in favor of the + `extended_type`/`extended-type` option + * Deprecated the `alias` option of the `form.type` tag + * Deprecated the Shell + +2.7.0 +----- + + * Added possibility to extract translation messages from a file or files besides extracting from a directory + * Added `TranslationsCacheWarmer` to create catalogues at warmup + +2.6.0 +----- + + * Added helper commands (`server:start`, `server:stop` and `server:status`) to control the built-in web + server in the background + * Added `Controller::isCsrfTokenValid` helper + * Added configuration for the PropertyAccess component + * Added `Controller::redirectToRoute` helper + * Added `Controller::addFlash` helper + * Added `Controller::isGranted` helper + * Added `Controller::denyAccessUnlessGranted` helper + * Deprecated `app.security` in twig as `app.user` and `is_granted()` are already available + +2.5.0 +----- + + * Added `translation:debug` command + * Added `--no-backup` option to `translation:update` command + * Added `config:debug` command + * Added `yaml:lint` command + * Deprecated the `RouterApacheDumperCommand` which will be removed in Symfony 3.0. + +2.4.0 +----- + + * allowed multiple IP addresses in profiler matcher settings + * added stopwatch helper to time templates with the WebProfilerBundle + * added service definition for "security.secure_random" service + * added service definitions for the new Security CSRF sub-component + +2.3.0 +----- + + * [BC BREAK] added a way to disable the profiler (when disabling the profiler, it is now completely removed) + To get the same "disabled" behavior as before, set `enabled` to `true` and `collect` to `false` + * [BC BREAK] the `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RegisterKernelListenersPass` was moved + to `Component\HttpKernel\DependencyInjection\RegisterListenersPass` + * added ControllerNameParser::build() which converts a controller short notation (a:b:c) to a class::method notation + * added possibility to run PHP built-in server in production environment + * added possibility to load the serializer component in the service container + * added route debug information when using the `router:match` command + * added `TimedPhpEngine` + * added `--clean` option to the `translation:update` command + * added `http_method_override` option + * added support for default templates per render tag + * added FormHelper::form(), FormHelper::start() and FormHelper::end() + * deprecated FormHelper::enctype() in favor of FormHelper::start() + * RedirectController actions now receive the Request instance via the method signature. + +2.2.0 +----- + + * added a new `uri_signer` service to help sign URIs + * deprecated `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` and `Symfony\Bundle\FrameworkBundle\HttpKernel::forward()` + * deprecated the `Symfony\Bundle\FrameworkBundle\HttpKernel` class in favor of `Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel` + * added support for adding new HTTP content rendering strategies (like ESI and Hinclude) + in the DIC via the `kernel.fragment_renderer` tag + * [BC BREAK] restricted the `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method to only accept URIs or ControllerReference instances + * `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method signature changed and the first argument + must now be a URI or a ControllerReference instance (the `generateInternalUri()` method was removed) + * The internal routes (`Resources/config/routing/internal.xml`) have been removed and replaced with a listener (`Symfony\Component\HttpKernel\EventListener\FragmentListener`) + * The `render` method of the `actions` templating helper signature and arguments changed + * replaced Symfony\Bundle\FrameworkBundle\Controller\TraceableControllerResolver by Symfony\Component\HttpKernel\Controller\TraceableControllerResolver + * replaced Symfony\Component\HttpKernel\Debug\ContainerAwareTraceableEventDispatcher by Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher + * added Client::enableProfiler() + * a new parameter has been added to the DIC: `router.request_context.base_url` + You can customize it for your functional tests or for generating URLs with + the right base URL when your are in the CLI context. + * added support for default templates per render tag + +2.1.0 +----- + + * moved the translation files to the Form and Validator components + * changed the default extension for XLIFF files from .xliff to .xlf + * moved Symfony\Bundle\FrameworkBundle\ContainerAwareEventDispatcher to Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher + * moved Symfony\Bundle\FrameworkBundle\Debug\TraceableEventDispatcher to Symfony\Component\EventDispatcher\ContainerAwareTraceableEventDispatcher + * added a router:match command + * added a config:dump-reference command + * added a server:run command + * added kernel.event_subscriber tag + * added a way to create relative symlinks when running assets:install command (--relative option) + * added Controller::getUser() + * [BC BREAK] assets_base_urls and base_urls merging strategy has changed + * changed the default profiler storage to use the filesystem instead of SQLite + * added support for placeholders in route defaults and requirements (replaced + by the value set in the service container) + * added Filesystem component as a dependency + * added support for hinclude (use ``standalone: 'js'`` in render tag) + * session options: lifetime, path, domain, secure, httponly were deprecated. + Prefixed versions should now be used instead: cookie_lifetime, cookie_path, + cookie_domain, cookie_secure, cookie_httponly + * [BC BREAK] following session options: 'lifetime', 'path', 'domain', 'secure', + 'httponly' are now prefixed with cookie_ when dumped to the container + * Added `handler_id` configuration under `session` key to represent `session.handler` + service, defaults to `session.handler.native_file`. + * Added `gc_maxlifetime`, `gc_probability`, and `gc_divisor` to session + configuration. This means session garbage collection has a + `gc_probability`/`gc_divisor` chance of being run. The `gc_maxlifetime` defines + how long a session can idle for. It is different from cookie lifetime which + declares how long a cookie can be stored on the remote client. + * Removed 'auto_start' configuration parameter from session config. The session will + start on demand. + * [BC BREAK] TemplateNameParser::parseFromFilename() has been moved to a dedicated + parser: TemplateFilenameParser::parse(). + * [BC BREAK] Kernel parameters are replaced by their value wherever they appear + in Route patterns, requirements and defaults. Use '%%' as the escaped value for '%'. + * [BC BREAK] Switched behavior of flash messages to expire flash messages on retrieval + using Symfony\Component\HttpFoundation\Session\Flash\FlashBag as opposed to on + next pageload regardless of whether they are displayed or not. diff --git a/vendor/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php b/vendor/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php new file mode 100644 index 0000000..0e4561a --- /dev/null +++ b/vendor/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; + +use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Cache\Adapter\NullAdapter; +use Symfony\Component\Cache\Adapter\PhpArrayAdapter; +use Symfony\Component\Config\Resource\ClassExistenceResource; +use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; + +/** + * @internal + */ +abstract class AbstractPhpFileCacheWarmer implements CacheWarmerInterface +{ + private $phpArrayFile; + + /** + * @param string $phpArrayFile The PHP file where metadata are cached + */ + public function __construct(string $phpArrayFile) + { + $this->phpArrayFile = $phpArrayFile; + } + + /** + * {@inheritdoc} + */ + public function isOptional() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function warmUp(string $cacheDir) + { + $arrayAdapter = new ArrayAdapter(); + + spl_autoload_register([ClassExistenceResource::class, 'throwOnRequiredClass']); + try { + if (!$this->doWarmUp($cacheDir, $arrayAdapter)) { + return; + } + } finally { + spl_autoload_unregister([ClassExistenceResource::class, 'throwOnRequiredClass']); + } + + // the ArrayAdapter stores the values serialized + // to avoid mutation of the data after it was written to the cache + // so here we un-serialize the values first + $values = array_map(function ($val) { return null !== $val ? unserialize($val) : null; }, $arrayAdapter->getValues()); + + $this->warmUpPhpArrayAdapter(new PhpArrayAdapter($this->phpArrayFile, new NullAdapter()), $values); + } + + protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values) + { + $phpArrayAdapter->warmUp($values); + } + + /** + * @internal + */ + final protected function ignoreAutoloadException(string $class, \Exception $exception): void + { + try { + ClassExistenceResource::throwOnRequiredClass($class, $exception); + } catch (\ReflectionException $e) { + } + } + + /** + * @return bool false if there is nothing to warm-up + */ + abstract protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter); +} diff --git a/vendor/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php b/vendor/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php new file mode 100644 index 0000000..2169eec --- /dev/null +++ b/vendor/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; + +use Doctrine\Common\Annotations\AnnotationException; +use Doctrine\Common\Annotations\CachedReader; +use Doctrine\Common\Annotations\Reader; +use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Cache\DoctrineProvider; + +/** + * Warms up annotation caches for classes found in composer's autoload class map + * and declared in DI bundle extensions using the addAnnotatedClassesToCache method. + * + * @author Titouan Galopin + */ +class AnnotationsCacheWarmer extends AbstractPhpFileCacheWarmer +{ + private $annotationReader; + private $excludeRegexp; + private $debug; + + /** + * @param string $phpArrayFile The PHP file where annotations are cached + */ + public function __construct(Reader $annotationReader, string $phpArrayFile, string $excludeRegexp = null, bool $debug = false) + { + parent::__construct($phpArrayFile); + $this->annotationReader = $annotationReader; + $this->excludeRegexp = $excludeRegexp; + $this->debug = $debug; + } + + /** + * {@inheritdoc} + */ + protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter) + { + $annotatedClassPatterns = $cacheDir.'/annotations.map'; + + if (!is_file($annotatedClassPatterns)) { + return true; + } + + $annotatedClasses = include $annotatedClassPatterns; + $reader = new CachedReader($this->annotationReader, new DoctrineProvider($arrayAdapter), $this->debug); + + foreach ($annotatedClasses as $class) { + if (null !== $this->excludeRegexp && preg_match($this->excludeRegexp, $class)) { + continue; + } + try { + $this->readAllComponents($reader, $class); + } catch (\Exception $e) { + $this->ignoreAutoloadException($class, $e); + } + } + + return true; + } + + private function readAllComponents(Reader $reader, string $class) + { + $reflectionClass = new \ReflectionClass($class); + + try { + $reader->getClassAnnotations($reflectionClass); + } catch (AnnotationException $e) { + /* + * Ignore any AnnotationException to not break the cache warming process if an Annotation is badly + * configured or could not be found / read / etc. + * + * In particular cases, an Annotation in your code can be used and defined only for a specific + * environment but is always added to the annotations.map file by some Symfony default behaviors, + * and you always end up with a not found Annotation. + */ + } + + foreach ($reflectionClass->getMethods() as $reflectionMethod) { + try { + $reader->getMethodAnnotations($reflectionMethod); + } catch (AnnotationException $e) { + } + } + + foreach ($reflectionClass->getProperties() as $reflectionProperty) { + try { + $reader->getPropertyAnnotations($reflectionProperty); + } catch (AnnotationException $e) { + } + } + } +} diff --git a/vendor/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php b/vendor/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php new file mode 100644 index 0000000..fecce27 --- /dev/null +++ b/vendor/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; + +use Psr\Container\ContainerInterface; +use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; +use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; +use Symfony\Component\Routing\RouterInterface; +use Symfony\Contracts\Service\ServiceSubscriberInterface; + +/** + * Generates the router matcher and generator classes. + * + * @author Fabien Potencier + * + * @final + */ +class RouterCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface +{ + private $container; + + public function __construct(ContainerInterface $container) + { + // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public function warmUp(string $cacheDir) + { + $router = $this->container->get('router'); + + if ($router instanceof WarmableInterface) { + $router->warmUp($cacheDir); + + return; + } + + throw new \LogicException(sprintf('The router %s cannot be warmed up because it does not implement %s.', \get_class($router), WarmableInterface::class)); + } + + /** + * Checks whether this warmer is optional or not. + * + * @return bool always true + */ + public function isOptional(): bool + { + return true; + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedServices(): array + { + return [ + 'router' => RouterInterface::class, + ]; + } +} diff --git a/vendor/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php b/vendor/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php new file mode 100644 index 0000000..0ada0ff --- /dev/null +++ b/vendor/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; + +use Doctrine\Common\Annotations\AnnotationException; +use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; +use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; +use Symfony\Component\Serializer\Mapping\Loader\LoaderChain; +use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface; +use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; +use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; + +/** + * Warms up XML and YAML serializer metadata. + * + * @author Titouan Galopin + */ +class SerializerCacheWarmer extends AbstractPhpFileCacheWarmer +{ + private $loaders; + + /** + * @param LoaderInterface[] $loaders The serializer metadata loaders + * @param string $phpArrayFile The PHP file where metadata are cached + */ + public function __construct(array $loaders, string $phpArrayFile) + { + parent::__construct($phpArrayFile); + $this->loaders = $loaders; + } + + /** + * {@inheritdoc} + */ + protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter) + { + if (!class_exists(CacheClassMetadataFactory::class) || !method_exists(XmlFileLoader::class, 'getMappedClasses') || !method_exists(YamlFileLoader::class, 'getMappedClasses')) { + return false; + } + + $metadataFactory = new CacheClassMetadataFactory(new ClassMetadataFactory(new LoaderChain($this->loaders)), $arrayAdapter); + + foreach ($this->extractSupportedLoaders($this->loaders) as $loader) { + foreach ($loader->getMappedClasses() as $mappedClass) { + try { + $metadataFactory->getMetadataFor($mappedClass); + } catch (AnnotationException $e) { + // ignore failing annotations + } catch (\Exception $e) { + $this->ignoreAutoloadException($mappedClass, $e); + } + } + } + + return true; + } + + /** + * @param LoaderInterface[] $loaders + * + * @return XmlFileLoader[]|YamlFileLoader[] + */ + private function extractSupportedLoaders(array $loaders): array + { + $supportedLoaders = []; + + foreach ($loaders as $loader) { + if ($loader instanceof XmlFileLoader || $loader instanceof YamlFileLoader) { + $supportedLoaders[] = $loader; + } elseif ($loader instanceof LoaderChain) { + $supportedLoaders = array_merge($supportedLoaders, $this->extractSupportedLoaders($loader->getLoaders())); + } + } + + return $supportedLoaders; + } +} diff --git a/vendor/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php b/vendor/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php new file mode 100644 index 0000000..28b6e43 --- /dev/null +++ b/vendor/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; + +use Psr\Container\ContainerInterface; +use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; +use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; +use Symfony\Contracts\Service\ServiceSubscriberInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * Generates the catalogues for translations. + * + * @author Xavier Leune + */ +class TranslationsCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface +{ + private $container; + private $translator; + + public function __construct(ContainerInterface $container) + { + // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public function warmUp(string $cacheDir) + { + if (null === $this->translator) { + $this->translator = $this->container->get('translator'); + } + + if ($this->translator instanceof WarmableInterface) { + $this->translator->warmUp($cacheDir); + } + } + + /** + * {@inheritdoc} + */ + public function isOptional() + { + return true; + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedServices() + { + return [ + 'translator' => TranslatorInterface::class, + ]; + } +} diff --git a/vendor/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php b/vendor/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php new file mode 100644 index 0000000..8569521 --- /dev/null +++ b/vendor/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; + +use Doctrine\Common\Annotations\AnnotationException; +use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Cache\Adapter\PhpArrayAdapter; +use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; +use Symfony\Component\Validator\Mapping\Loader\LoaderChain; +use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; +use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader; +use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader; +use Symfony\Component\Validator\ValidatorBuilder; + +/** + * Warms up XML and YAML validator metadata. + * + * @author Titouan Galopin + */ +class ValidatorCacheWarmer extends AbstractPhpFileCacheWarmer +{ + private $validatorBuilder; + + /** + * @param string $phpArrayFile The PHP file where metadata are cached + */ + public function __construct(ValidatorBuilder $validatorBuilder, string $phpArrayFile) + { + parent::__construct($phpArrayFile); + $this->validatorBuilder = $validatorBuilder; + } + + /** + * {@inheritdoc} + */ + protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter) + { + if (!method_exists($this->validatorBuilder, 'getLoaders')) { + return false; + } + + $loaders = $this->validatorBuilder->getLoaders(); + $metadataFactory = new LazyLoadingMetadataFactory(new LoaderChain($loaders), $arrayAdapter); + + foreach ($this->extractSupportedLoaders($loaders) as $loader) { + foreach ($loader->getMappedClasses() as $mappedClass) { + try { + if ($metadataFactory->hasMetadataFor($mappedClass)) { + $metadataFactory->getMetadataFor($mappedClass); + } + } catch (AnnotationException $e) { + // ignore failing annotations + } catch (\Exception $e) { + $this->ignoreAutoloadException($mappedClass, $e); + } + } + } + + return true; + } + + protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values) + { + // make sure we don't cache null values + parent::warmUpPhpArrayAdapter($phpArrayAdapter, array_filter($values)); + } + + /** + * @param LoaderInterface[] $loaders + * + * @return XmlFileLoader[]|YamlFileLoader[] + */ + private function extractSupportedLoaders(array $loaders): array + { + $supportedLoaders = []; + + foreach ($loaders as $loader) { + if ($loader instanceof XmlFileLoader || $loader instanceof YamlFileLoader) { + $supportedLoaders[] = $loader; + } elseif ($loader instanceof LoaderChain) { + $supportedLoaders = array_merge($supportedLoaders, $this->extractSupportedLoaders($loader->getLoaders())); + } + } + + return $supportedLoaders; + } +} diff --git a/vendor/symfony/framework-bundle/Command/AboutCommand.php b/vendor/symfony/framework-bundle/Command/AboutCommand.php new file mode 100644 index 0000000..b9fbe67 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/AboutCommand.php @@ -0,0 +1,144 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Helper\TableSeparator; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\HttpKernel\KernelInterface; + +/** + * A console command to display information about the current installation. + * + * @author Roland Franssen + * + * @final + */ +class AboutCommand extends Command +{ + protected static $defaultName = 'about'; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDescription('Displays information about the current project') + ->setHelp(<<<'EOT' +The %command.name% command displays information about the current Symfony project. + +The PHP section displays important configuration that could affect your application. The values might +be different between web and CLI. + +The Environment section displays the current environment variables managed by Symfony Dotenv. It will not +be shown if no variables were found. The values might be different between web and CLI. +EOT + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + /** @var KernelInterface $kernel */ + $kernel = $this->getApplication()->getKernel(); + + $rows = [ + ['Symfony'], + new TableSeparator(), + ['Version', Kernel::VERSION], + ['Long-Term Support', 4 === Kernel::MINOR_VERSION ? 'Yes' : 'No'], + ['End of maintenance', Kernel::END_OF_MAINTENANCE.(self::isExpired(Kernel::END_OF_MAINTENANCE) ? ' Expired' : '')], + ['End of life', Kernel::END_OF_LIFE.(self::isExpired(Kernel::END_OF_LIFE) ? ' Expired' : '')], + new TableSeparator(), + ['Kernel'], + new TableSeparator(), + ['Type', \get_class($kernel)], + ['Environment', $kernel->getEnvironment()], + ['Debug', $kernel->isDebug() ? 'true' : 'false'], + ['Charset', $kernel->getCharset()], + ['Cache directory', self::formatPath($kernel->getCacheDir(), $kernel->getProjectDir()).' ('.self::formatFileSize($kernel->getCacheDir()).')'], + ['Log directory', self::formatPath($kernel->getLogDir(), $kernel->getProjectDir()).' ('.self::formatFileSize($kernel->getLogDir()).')'], + new TableSeparator(), + ['PHP'], + new TableSeparator(), + ['Version', PHP_VERSION], + ['Architecture', (PHP_INT_SIZE * 8).' bits'], + ['Intl locale', class_exists('Locale', false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a'], + ['Timezone', date_default_timezone_get().' ('.(new \DateTime())->format(\DateTime::W3C).')'], + ['OPcache', \extension_loaded('Zend OPcache') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false'], + ['APCu', \extension_loaded('apcu') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false'], + ['Xdebug', \extension_loaded('xdebug') ? 'true' : 'false'], + ]; + + if ($dotenv = self::getDotenvVars()) { + $rows = array_merge($rows, [ + new TableSeparator(), + ['Environment (.env)'], + new TableSeparator(), + ], array_map(function ($value, $name) { + return [$name, $value]; + }, $dotenv, array_keys($dotenv))); + } + + $io->table([], $rows); + + return 0; + } + + private static function formatPath(string $path, string $baseDir): string + { + return preg_replace('~^'.preg_quote($baseDir, '~').'~', '.', $path); + } + + private static function formatFileSize(string $path): string + { + if (is_file($path)) { + $size = filesize($path) ?: 0; + } else { + $size = 0; + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS | \RecursiveDirectoryIterator::FOLLOW_SYMLINKS)) as $file) { + $size += $file->getSize(); + } + } + + return Helper::formatMemory($size); + } + + private static function isExpired(string $date): bool + { + $date = \DateTime::createFromFormat('d/m/Y', '01/'.$date); + + return false !== $date && new \DateTime() > $date->modify('last day of this month 23:59:59'); + } + + private static function getDotenvVars(): array + { + $vars = []; + foreach (explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? $_ENV['SYMFONY_DOTENV_VARS'] ?? '') as $name) { + if ('' !== $name && isset($_ENV[$name])) { + $vars[$name] = $_ENV[$name]; + } + } + + return $vars; + } +} diff --git a/vendor/symfony/framework-bundle/Command/AbstractConfigCommand.php b/vendor/symfony/framework-bundle/Command/AbstractConfigCommand.php new file mode 100644 index 0000000..232348d --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/AbstractConfigCommand.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Config\Definition\ConfigurationInterface; +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\StyleInterface; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; + +/** + * A console command for dumping available configuration reference. + * + * @author Kevin Bond + * @author Wouter J + * @author Grégoire Pineau + */ +abstract class AbstractConfigCommand extends ContainerDebugCommand +{ + /** + * @param OutputInterface|StyleInterface $output + */ + protected function listBundles($output) + { + $title = 'Available registered bundles with their extension alias if available'; + $headers = ['Bundle name', 'Extension alias']; + $rows = []; + + $bundles = $this->getApplication()->getKernel()->getBundles(); + usort($bundles, function ($bundleA, $bundleB) { + return strcmp($bundleA->getName(), $bundleB->getName()); + }); + + foreach ($bundles as $bundle) { + $extension = $bundle->getContainerExtension(); + $rows[] = [$bundle->getName(), $extension ? $extension->getAlias() : '']; + } + + if ($output instanceof StyleInterface) { + $output->title($title); + $output->table($headers, $rows); + } else { + $output->writeln($title); + $table = new Table($output); + $table->setHeaders($headers)->setRows($rows)->render(); + } + } + + /** + * @return ExtensionInterface + */ + protected function findExtension(string $name) + { + $bundles = $this->initializeBundles(); + $minScore = INF; + + foreach ($bundles as $bundle) { + if ($name === $bundle->getName()) { + if (!$bundle->getContainerExtension()) { + throw new \LogicException(sprintf('Bundle "%s" does not have a container extension.', $name)); + } + + return $bundle->getContainerExtension(); + } + + $distance = levenshtein($name, $bundle->getName()); + + if ($distance < $minScore) { + $guess = $bundle->getName(); + $minScore = $distance; + } + + $extension = $bundle->getContainerExtension(); + + if ($extension) { + if ($name === $extension->getAlias()) { + return $extension; + } + + $distance = levenshtein($name, $extension->getAlias()); + + if ($distance < $minScore) { + $guess = $extension->getAlias(); + $minScore = $distance; + } + } + } + + if ('Bundle' !== substr($name, -6)) { + $message = sprintf('No extensions with configuration available for "%s".', $name); + } else { + $message = sprintf('No extension with alias "%s" is enabled.', $name); + } + + if (isset($guess) && $minScore < 3) { + $message .= sprintf("\n\nDid you mean \"%s\"?", $guess); + } + + throw new LogicException($message); + } + + public function validateConfiguration(ExtensionInterface $extension, $configuration) + { + if (!$configuration) { + throw new \LogicException(sprintf('The extension with alias "%s" does not have its getConfiguration() method setup', $extension->getAlias())); + } + + if (!$configuration instanceof ConfigurationInterface) { + throw new \LogicException(sprintf('Configuration class "%s" should implement ConfigurationInterface in order to be dumpable', \get_class($configuration))); + } + } + + private function initializeBundles() + { + // Re-build bundle manually to initialize DI extensions that can be extended by other bundles in their build() method + // as this method is not called when the container is loaded from the cache. + $container = $this->getContainerBuilder(); + $bundles = $this->getApplication()->getKernel()->getBundles(); + foreach ($bundles as $bundle) { + if ($extension = $bundle->getContainerExtension()) { + $container->registerExtension($extension); + } + } + + foreach ($bundles as $bundle) { + $bundle->build($container); + } + + return $bundles; + } +} diff --git a/vendor/symfony/framework-bundle/Command/AssetsInstallCommand.php b/vendor/symfony/framework-bundle/Command/AssetsInstallCommand.php new file mode 100644 index 0000000..b02b6a4 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/AssetsInstallCommand.php @@ -0,0 +1,283 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\Filesystem\Exception\IOException; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Finder\Finder; +use Symfony\Component\HttpKernel\Bundle\BundleInterface; +use Symfony\Component\HttpKernel\KernelInterface; + +/** + * Command that places bundle web assets into a given directory. + * + * @author Fabien Potencier + * @author Gábor Egyed + * + * @final + */ +class AssetsInstallCommand extends Command +{ + const METHOD_COPY = 'copy'; + const METHOD_ABSOLUTE_SYMLINK = 'absolute symlink'; + const METHOD_RELATIVE_SYMLINK = 'relative symlink'; + + protected static $defaultName = 'assets:install'; + + private $filesystem; + private $projectDir; + + public function __construct(Filesystem $filesystem, string $projectDir) + { + parent::__construct(); + + $this->filesystem = $filesystem; + $this->projectDir = $projectDir; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputArgument('target', InputArgument::OPTIONAL, 'The target directory', null), + ]) + ->addOption('symlink', null, InputOption::VALUE_NONE, 'Symlinks the assets instead of copying it') + ->addOption('relative', null, InputOption::VALUE_NONE, 'Make relative symlinks') + ->addOption('no-cleanup', null, InputOption::VALUE_NONE, 'Do not remove the assets of the bundles that no longer exist') + ->setDescription('Installs bundles web assets under a public directory') + ->setHelp(<<<'EOT' +The %command.name% command installs bundle assets into a given +directory (e.g. the public directory). + + php %command.full_name% public + +A "bundles" directory will be created inside the target directory and the +"Resources/public" directory of each bundle will be copied into it. + +To create a symlink to each bundle instead of copying its assets, use the +--symlink option (will fall back to hard copies when symbolic links aren't possible: + + php %command.full_name% public --symlink + +To make symlink relative, add the --relative option: + + php %command.full_name% public --symlink --relative + +EOT + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + /** @var KernelInterface $kernel */ + $kernel = $this->getApplication()->getKernel(); + $targetArg = rtrim($input->getArgument('target'), '/'); + + if (!$targetArg) { + $targetArg = $this->getPublicDirectory($kernel->getContainer()); + } + + if (!is_dir($targetArg)) { + $targetArg = $kernel->getProjectDir().'/'.$targetArg; + + if (!is_dir($targetArg)) { + throw new InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target'))); + } + } + + $bundlesDir = $targetArg.'/bundles/'; + + $io = new SymfonyStyle($input, $output); + $io->newLine(); + + if ($input->getOption('relative')) { + $expectedMethod = self::METHOD_RELATIVE_SYMLINK; + $io->text('Trying to install assets as relative symbolic links.'); + } elseif ($input->getOption('symlink')) { + $expectedMethod = self::METHOD_ABSOLUTE_SYMLINK; + $io->text('Trying to install assets as absolute symbolic links.'); + } else { + $expectedMethod = self::METHOD_COPY; + $io->text('Installing assets as hard copies.'); + } + + $io->newLine(); + + $rows = []; + $copyUsed = false; + $exitCode = 0; + $validAssetDirs = []; + /** @var BundleInterface $bundle */ + foreach ($kernel->getBundles() as $bundle) { + if (!is_dir($originDir = $bundle->getPath().'/Resources/public') && !is_dir($originDir = $bundle->getPath().'/public')) { + continue; + } + + $assetDir = preg_replace('/bundle$/', '', strtolower($bundle->getName())); + $targetDir = $bundlesDir.$assetDir; + $validAssetDirs[] = $assetDir; + + if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $message = sprintf("%s\n-> %s", $bundle->getName(), $targetDir); + } else { + $message = $bundle->getName(); + } + + try { + $this->filesystem->remove($targetDir); + + if (self::METHOD_RELATIVE_SYMLINK === $expectedMethod) { + $method = $this->relativeSymlinkWithFallback($originDir, $targetDir); + } elseif (self::METHOD_ABSOLUTE_SYMLINK === $expectedMethod) { + $method = $this->absoluteSymlinkWithFallback($originDir, $targetDir); + } else { + $method = $this->hardCopy($originDir, $targetDir); + } + + if (self::METHOD_COPY === $method) { + $copyUsed = true; + } + + if ($method === $expectedMethod) { + $rows[] = [sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'OK' : "\xE2\x9C\x94" /* HEAVY CHECK MARK (U+2714) */), $message, $method]; + } else { + $rows[] = [sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'WARNING' : '!'), $message, $method]; + } + } catch (\Exception $e) { + $exitCode = 1; + $rows[] = [sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */), $message, $e->getMessage()]; + } + } + // remove the assets of the bundles that no longer exist + if (!$input->getOption('no-cleanup') && is_dir($bundlesDir)) { + $dirsToRemove = Finder::create()->depth(0)->directories()->exclude($validAssetDirs)->in($bundlesDir); + $this->filesystem->remove($dirsToRemove); + } + + if ($rows) { + $io->table(['', 'Bundle', 'Method / Error'], $rows); + } + + if (0 !== $exitCode) { + $io->error('Some errors occurred while installing assets.'); + } else { + if ($copyUsed) { + $io->note('Some assets were installed via copy. If you make changes to these assets you have to run this command again.'); + } + $io->success($rows ? 'All assets were successfully installed.' : 'No assets were provided by any bundle.'); + } + + return $exitCode; + } + + /** + * Try to create relative symlink. + * + * Falling back to absolute symlink and finally hard copy. + */ + private function relativeSymlinkWithFallback(string $originDir, string $targetDir): string + { + try { + $this->symlink($originDir, $targetDir, true); + $method = self::METHOD_RELATIVE_SYMLINK; + } catch (IOException $e) { + $method = $this->absoluteSymlinkWithFallback($originDir, $targetDir); + } + + return $method; + } + + /** + * Try to create absolute symlink. + * + * Falling back to hard copy. + */ + private function absoluteSymlinkWithFallback(string $originDir, string $targetDir): string + { + try { + $this->symlink($originDir, $targetDir); + $method = self::METHOD_ABSOLUTE_SYMLINK; + } catch (IOException $e) { + // fall back to copy + $method = $this->hardCopy($originDir, $targetDir); + } + + return $method; + } + + /** + * Creates symbolic link. + * + * @throws IOException if link can not be created + */ + private function symlink(string $originDir, string $targetDir, bool $relative = false) + { + if ($relative) { + $this->filesystem->mkdir(\dirname($targetDir)); + $originDir = $this->filesystem->makePathRelative($originDir, realpath(\dirname($targetDir))); + } + $this->filesystem->symlink($originDir, $targetDir); + if (!file_exists($targetDir)) { + throw new IOException(sprintf('Symbolic link "%s" was created but appears to be broken.', $targetDir), 0, null, $targetDir); + } + } + + /** + * Copies origin to target. + */ + private function hardCopy(string $originDir, string $targetDir): string + { + $this->filesystem->mkdir($targetDir, 0777); + // We use a custom iterator to ignore VCS files + $this->filesystem->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(false)->in($originDir)); + + return self::METHOD_COPY; + } + + private function getPublicDirectory(ContainerInterface $container): string + { + $defaultPublicDir = 'public'; + + if (null === $this->projectDir && !$container->hasParameter('kernel.project_dir')) { + return $defaultPublicDir; + } + + $composerFilePath = ($this->projectDir ?? $container->getParameter('kernel.project_dir')).'/composer.json'; + + if (!file_exists($composerFilePath)) { + return $defaultPublicDir; + } + + $composerConfig = json_decode(file_get_contents($composerFilePath), true); + + if (isset($composerConfig['extra']['public-dir'])) { + return $composerConfig['extra']['public-dir']; + } + + return $defaultPublicDir; + } +} diff --git a/vendor/symfony/framework-bundle/Command/CacheClearCommand.php b/vendor/symfony/framework-bundle/Command/CacheClearCommand.php new file mode 100644 index 0000000..6711e45 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/CacheClearCommand.php @@ -0,0 +1,209 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Filesystem\Exception\IOException; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Finder\Finder; +use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; +use Symfony\Component\HttpKernel\RebootableInterface; + +/** + * Clear and Warmup the cache. + * + * @author Francis Besset + * @author Fabien Potencier + * + * @final + */ +class CacheClearCommand extends Command +{ + protected static $defaultName = 'cache:clear'; + + private $cacheClearer; + private $filesystem; + + public function __construct(CacheClearerInterface $cacheClearer, Filesystem $filesystem = null) + { + parent::__construct(); + + $this->cacheClearer = $cacheClearer; + $this->filesystem = $filesystem ?: new Filesystem(); + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputOption('no-warmup', '', InputOption::VALUE_NONE, 'Do not warm up the cache'), + new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), + ]) + ->setDescription('Clears the cache') + ->setHelp(<<<'EOF' +The %command.name% command clears the application cache for a given environment +and debug mode: + + php %command.full_name% --env=dev + php %command.full_name% --env=prod --no-debug +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $fs = $this->filesystem; + $io = new SymfonyStyle($input, $output); + + $kernel = $this->getApplication()->getKernel(); + $realCacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir'); + // the old cache dir name must not be longer than the real one to avoid exceeding + // the maximum length of a directory or file path within it (esp. Windows MAX_PATH) + $oldCacheDir = substr($realCacheDir, 0, -1).('~' === substr($realCacheDir, -1) ? '+' : '~'); + $fs->remove($oldCacheDir); + + if (!is_writable($realCacheDir)) { + throw new RuntimeException(sprintf('Unable to write in the "%s" directory', $realCacheDir)); + } + + $io->comment(sprintf('Clearing the cache for the %s environment with debug %s', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); + $this->cacheClearer->clear($realCacheDir); + + // The current event dispatcher is stale, let's not use it anymore + $this->getApplication()->setDispatcher(new EventDispatcher()); + + $containerFile = (new \ReflectionObject($kernel->getContainer()))->getFileName(); + $containerDir = basename(\dirname($containerFile)); + + // the warmup cache dir name must have the same length as the real one + // to avoid the many problems in serialized resources files + $warmupDir = substr($realCacheDir, 0, -1).('_' === substr($realCacheDir, -1) ? '-' : '_'); + + if ($output->isVerbose() && $fs->exists($warmupDir)) { + $io->comment('Clearing outdated warmup directory...'); + } + $fs->remove($warmupDir); + + if ($_SERVER['REQUEST_TIME'] <= filemtime($containerFile) && filemtime($containerFile) <= time()) { + if ($output->isVerbose()) { + $io->comment('Cache is fresh.'); + } + if (!$input->getOption('no-warmup') && !$input->getOption('no-optional-warmers')) { + if ($output->isVerbose()) { + $io->comment('Warming up optional cache...'); + } + $warmer = $kernel->getContainer()->get('cache_warmer'); + // non optional warmers already ran during container compilation + $warmer->enableOnlyOptionalWarmers(); + $warmer->warmUp($realCacheDir); + } + } else { + $fs->mkdir($warmupDir); + + if (!$input->getOption('no-warmup')) { + if ($output->isVerbose()) { + $io->comment('Warming up cache...'); + } + $this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers')); + } + + if (!$fs->exists($warmupDir.'/'.$containerDir)) { + $fs->rename($realCacheDir.'/'.$containerDir, $warmupDir.'/'.$containerDir); + touch($warmupDir.'/'.$containerDir.'.legacy'); + } + + if ('/' === \DIRECTORY_SEPARATOR && $mounts = @file('/proc/mounts')) { + foreach ($mounts as $mount) { + $mount = \array_slice(explode(' ', $mount), 1, -3); + if (!\in_array(array_pop($mount), ['vboxsf', 'nfs'])) { + continue; + } + $mount = implode(' ', $mount).'/'; + + if (0 === strpos($realCacheDir, $mount)) { + $io->note('For better performances, you should move the cache and log directories to a non-shared folder of the VM.'); + $oldCacheDir = false; + break; + } + } + } + + if ($oldCacheDir) { + $fs->rename($realCacheDir, $oldCacheDir); + } else { + $fs->remove($realCacheDir); + } + $fs->rename($warmupDir, $realCacheDir); + + if ($output->isVerbose()) { + $io->comment('Removing old cache directory...'); + } + + try { + $fs->remove($oldCacheDir); + } catch (IOException $e) { + if ($output->isVerbose()) { + $io->warning($e->getMessage()); + } + } + } + + if ($output->isVerbose()) { + $io->comment('Finished'); + } + + $io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); + + return 0; + } + + private function warmup(string $warmupDir, string $realCacheDir, bool $enableOptionalWarmers = true) + { + // create a temporary kernel + $kernel = $this->getApplication()->getKernel(); + if (!$kernel instanceof RebootableInterface) { + throw new \LogicException('Calling "cache:clear" with a kernel that does not implement "Symfony\Component\HttpKernel\RebootableInterface" is not supported.'); + } + $kernel->reboot($warmupDir); + + // warmup temporary dir + if ($enableOptionalWarmers) { + $warmer = $kernel->getContainer()->get('cache_warmer'); + // non optional warmers already ran during container compilation + $warmer->enableOnlyOptionalWarmers(); + $warmer->warmUp($warmupDir); + } + + // fix references to cached files with the real cache directory name + $search = [$warmupDir, str_replace('\\', '\\\\', $warmupDir)]; + $replace = str_replace('\\', '/', $realCacheDir); + foreach (Finder::create()->files()->in($warmupDir) as $file) { + $content = str_replace($search, $replace, file_get_contents($file), $count); + if ($count) { + file_put_contents($file, $content); + } + } + } +} diff --git a/vendor/symfony/framework-bundle/Command/CachePoolClearCommand.php b/vendor/symfony/framework-bundle/Command/CachePoolClearCommand.php new file mode 100644 index 0000000..50aacd9 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/CachePoolClearCommand.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; + +/** + * Clear cache pools. + * + * @author Nicolas Grekas + */ +final class CachePoolClearCommand extends Command +{ + protected static $defaultName = 'cache:pool:clear'; + + private $poolClearer; + + public function __construct(Psr6CacheClearer $poolClearer) + { + parent::__construct(); + + $this->poolClearer = $poolClearer; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputArgument('pools', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'A list of cache pools or cache pool clearers'), + ]) + ->setDescription('Clears cache pools') + ->setHelp(<<<'EOF' +The %command.name% command clears the given cache pools or cache pool clearers. + + %command.full_name% [...] +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $kernel = $this->getApplication()->getKernel(); + $pools = []; + $clearers = []; + + foreach ($input->getArgument('pools') as $id) { + if ($this->poolClearer->hasPool($id)) { + $pools[$id] = $id; + } else { + $pool = $kernel->getContainer()->get($id); + + if ($pool instanceof CacheItemPoolInterface) { + $pools[$id] = $pool; + } elseif ($pool instanceof Psr6CacheClearer) { + $clearers[$id] = $pool; + } else { + throw new InvalidArgumentException(sprintf('"%s" is not a cache pool nor a cache clearer.', $id)); + } + } + } + + foreach ($clearers as $id => $clearer) { + $io->comment(sprintf('Calling cache clearer: %s', $id)); + $clearer->clear($kernel->getContainer()->getParameter('kernel.cache_dir')); + } + + foreach ($pools as $id => $pool) { + $io->comment(sprintf('Clearing cache pool: %s', $id)); + + if ($pool instanceof CacheItemPoolInterface) { + $pool->clear(); + } else { + $this->poolClearer->clearPool($id); + } + } + + $io->success('Cache was successfully cleared.'); + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/CachePoolDeleteCommand.php b/vendor/symfony/framework-bundle/Command/CachePoolDeleteCommand.php new file mode 100644 index 0000000..2a7a2fe --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/CachePoolDeleteCommand.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; + +/** + * Delete an item from a cache pool. + * + * @author Pierre du Plessis + */ +final class CachePoolDeleteCommand extends Command +{ + protected static $defaultName = 'cache:pool:delete'; + + private $poolClearer; + + public function __construct(Psr6CacheClearer $poolClearer) + { + parent::__construct(); + + $this->poolClearer = $poolClearer; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputArgument('pool', InputArgument::REQUIRED, 'The cache pool from which to delete an item'), + new InputArgument('key', InputArgument::REQUIRED, 'The cache key to delete from the pool'), + ]) + ->setDescription('Deletes an item from a cache pool') + ->setHelp(<<<'EOF' +The %command.name% deletes an item from a given cache pool. + + %command.full_name% +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $pool = $input->getArgument('pool'); + $key = $input->getArgument('key'); + $cachePool = $this->poolClearer->getPool($pool); + + if (!$cachePool->hasItem($key)) { + $io->note(sprintf('Cache item "%s" does not exist in cache pool "%s".', $key, $pool)); + + return 0; + } + + if (!$cachePool->deleteItem($key)) { + throw new \Exception(sprintf('Cache item "%s" could not be deleted.', $key)); + } + + $io->success(sprintf('Cache item "%s" was successfully deleted.', $key)); + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/CachePoolListCommand.php b/vendor/symfony/framework-bundle/Command/CachePoolListCommand.php new file mode 100644 index 0000000..7b72541 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/CachePoolListCommand.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * List available cache pools. + * + * @author Tobias Nyholm + */ +final class CachePoolListCommand extends Command +{ + protected static $defaultName = 'cache:pool:list'; + + private $poolNames; + + public function __construct(array $poolNames) + { + parent::__construct(); + + $this->poolNames = $poolNames; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDescription('List available cache pools') + ->setHelp(<<<'EOF' +The %command.name% command lists all available cache pools. +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + $io->table(['Pool name'], array_map(function ($pool) { + return [$pool]; + }, $this->poolNames)); + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/CachePoolPruneCommand.php b/vendor/symfony/framework-bundle/Command/CachePoolPruneCommand.php new file mode 100644 index 0000000..65f3ff6 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/CachePoolPruneCommand.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Cache pool pruner command. + * + * @author Rob Frawley 2nd + */ +final class CachePoolPruneCommand extends Command +{ + protected static $defaultName = 'cache:pool:prune'; + + private $pools; + + /** + * @param iterable|PruneableInterface[] $pools + */ + public function __construct(iterable $pools) + { + parent::__construct(); + + $this->pools = $pools; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDescription('Prunes cache pools') + ->setHelp(<<<'EOF' +The %command.name% command deletes all expired items from all pruneable pools. + + %command.full_name% +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + foreach ($this->pools as $name => $pool) { + $io->comment(sprintf('Pruning cache pool: %s', $name)); + $pool->prune(); + } + + $io->success('Successfully pruned cache pool(s).'); + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/CacheWarmupCommand.php b/vendor/symfony/framework-bundle/Command/CacheWarmupCommand.php new file mode 100644 index 0000000..0a87acf --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/CacheWarmupCommand.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate; + +/** + * Warmup the cache. + * + * @author Fabien Potencier + * + * @final + */ +class CacheWarmupCommand extends Command +{ + protected static $defaultName = 'cache:warmup'; + + private $cacheWarmer; + + public function __construct(CacheWarmerAggregate $cacheWarmer) + { + parent::__construct(); + + $this->cacheWarmer = $cacheWarmer; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), + ]) + ->setDescription('Warms up an empty cache') + ->setHelp(<<<'EOF' +The %command.name% command warms up the cache. + +Before running this command, the cache must be empty. + +This command does not generate the classes cache (as when executing this +command, too many classes that should be part of the cache are already loaded +in memory). Use curl or any other similar tool to warm up +the classes cache if you want. + +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + $kernel = $this->getApplication()->getKernel(); + $io->comment(sprintf('Warming up the cache for the %s environment with debug %s', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); + + if (!$input->getOption('no-optional-warmers')) { + $this->cacheWarmer->enableOptionalWarmers(); + } + + $this->cacheWarmer->warmUp($kernel->getContainer()->getParameter('kernel.cache_dir')); + + $io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully warmed.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/ConfigDebugCommand.php b/vendor/symfony/framework-bundle/Command/ConfigDebugCommand.php new file mode 100644 index 0000000..2aa631e --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/ConfigDebugCommand.php @@ -0,0 +1,156 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\DependencyInjection\Compiler\ValidateEnvPlaceholdersPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Yaml\Yaml; + +/** + * A console command for dumping available configuration reference. + * + * @author Grégoire Pineau + * + * @final + */ +class ConfigDebugCommand extends AbstractConfigCommand +{ + protected static $defaultName = 'debug:config'; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputArgument('name', InputArgument::OPTIONAL, 'The bundle name or the extension alias'), + new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), + ]) + ->setDescription('Dumps the current configuration for an extension') + ->setHelp(<<<'EOF' +The %command.name% command dumps the current configuration for an +extension/bundle. + +Either the extension alias or bundle name can be used: + + php %command.full_name% framework + php %command.full_name% FrameworkBundle + +For dumping a specific option, add its path as second argument: + + php %command.full_name% framework serializer.enabled + +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $errorIo = $io->getErrorStyle(); + + if (null === $name = $input->getArgument('name')) { + $this->listBundles($errorIo); + $errorIo->comment('Provide the name of a bundle as the first argument of this command to dump its configuration. (e.g. debug:config FrameworkBundle)'); + $errorIo->comment('For dumping a specific option, add its path as the second argument of this command. (e.g. debug:config FrameworkBundle serializer to dump the framework.serializer configuration)'); + + return 0; + } + + $extension = $this->findExtension($name); + $container = $this->compileContainer(); + + $extensionAlias = $extension->getAlias(); + $extensionConfig = []; + foreach ($container->getCompilerPassConfig()->getPasses() as $pass) { + if ($pass instanceof ValidateEnvPlaceholdersPass) { + $extensionConfig = $pass->getExtensionConfig(); + break; + } + } + + if (!isset($extensionConfig[$extensionAlias])) { + throw new \LogicException(sprintf('The extension with alias "%s" does not have configuration.', $extensionAlias)); + } + + $config = $container->resolveEnvPlaceholders($extensionConfig[$extensionAlias]); + + if (null === $path = $input->getArgument('path')) { + $io->title( + sprintf('Current configuration for %s', ($name === $extensionAlias ? sprintf('extension with alias "%s"', $extensionAlias) : sprintf('"%s"', $name))) + ); + + $io->writeln(Yaml::dump([$extensionAlias => $config], 10)); + + return 0; + } + + try { + $config = $this->getConfigForPath($config, $path, $extensionAlias); + } catch (LogicException $e) { + $errorIo->error($e->getMessage()); + + return 1; + } + + $io->title(sprintf('Current configuration for "%s.%s"', $extensionAlias, $path)); + + $io->writeln(Yaml::dump($config, 10)); + + return 0; + } + + private function compileContainer(): ContainerBuilder + { + $kernel = clone $this->getApplication()->getKernel(); + $kernel->boot(); + + $method = new \ReflectionMethod($kernel, 'buildContainer'); + $method->setAccessible(true); + $container = $method->invoke($kernel); + $container->getCompiler()->compile($container); + + return $container; + } + + /** + * Iterate over configuration until the last step of the given path. + * + * @throws LogicException If the configuration does not exist + * + * @return mixed + */ + private function getConfigForPath(array $config, string $path, string $alias) + { + $steps = explode('.', $path); + + foreach ($steps as $step) { + if (!\array_key_exists($step, $config)) { + throw new LogicException(sprintf('Unable to find configuration for "%s.%s"', $alias, $path)); + } + + $config = $config[$step]; + } + + return $config; + } +} diff --git a/vendor/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php b/vendor/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php new file mode 100644 index 0000000..60445e4 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php @@ -0,0 +1,135 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Config\Definition\Dumper\XmlReferenceDumper; +use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * A console command for dumping available configuration reference. + * + * @author Kevin Bond + * @author Wouter J + * @author Grégoire Pineau + * + * @final + */ +class ConfigDumpReferenceCommand extends AbstractConfigCommand +{ + protected static $defaultName = 'config:dump-reference'; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputArgument('name', InputArgument::OPTIONAL, 'The Bundle name or the extension alias'), + new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (yaml or xml)', 'yaml'), + ]) + ->setDescription('Dumps the default configuration for an extension') + ->setHelp(<<<'EOF' +The %command.name% command dumps the default configuration for an +extension/bundle. + +Either the extension alias or bundle name can be used: + + php %command.full_name% framework + php %command.full_name% FrameworkBundle + +With the --format option specifies the format of the configuration, +this is either yaml or xml. +When the option is not provided, yaml is used. + + php %command.full_name% FrameworkBundle --format=xml + +For dumping a specific option, add its path as second argument (only available for the yaml format): + + php %command.full_name% framework profiler.matcher + +EOF + ) + ; + } + + /** + * {@inheritdoc} + * + * @throws \LogicException + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $errorIo = $io->getErrorStyle(); + + if (null === $name = $input->getArgument('name')) { + $this->listBundles($errorIo); + $errorIo->comment([ + 'Provide the name of a bundle as the first argument of this command to dump its default configuration. (e.g. config:dump-reference FrameworkBundle)', + 'For dumping a specific option, add its path as the second argument of this command. (e.g. config:dump-reference FrameworkBundle profiler.matcher to dump the framework.profiler.matcher configuration)', + ]); + + return 0; + } + + $extension = $this->findExtension($name); + + $configuration = $extension->getConfiguration([], $this->getContainerBuilder()); + + $this->validateConfiguration($extension, $configuration); + + $format = $input->getOption('format'); + $path = $input->getArgument('path'); + + if (null !== $path && 'yaml' !== $format) { + $errorIo->error('The "path" option is only available for the "yaml" format.'); + + return 1; + } + + if ($name === $extension->getAlias()) { + $message = sprintf('Default configuration for extension with alias: "%s"', $name); + } else { + $message = sprintf('Default configuration for "%s"', $name); + } + + if (null !== $path) { + $message .= sprintf(' at path "%s"', $path); + } + + switch ($format) { + case 'yaml': + $io->writeln(sprintf('# %s', $message)); + $dumper = new YamlReferenceDumper(); + break; + case 'xml': + $io->writeln(sprintf('', $message)); + $dumper = new XmlReferenceDumper(); + break; + default: + $io->writeln($message); + throw new InvalidArgumentException('Only the yaml and xml formats are supported.'); + } + + $io->writeln(null === $path ? $dumper->dump($configuration, $extension->getNamespace()) : $dumper->dumpAtPath($configuration, $path)); + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/ContainerDebugCommand.php b/vendor/symfony/framework-bundle/Command/ContainerDebugCommand.php new file mode 100644 index 0000000..4440ed0 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/ContainerDebugCommand.php @@ -0,0 +1,295 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; +use Symfony\Component\Config\ConfigCache; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; + +/** + * A console command for retrieving information about services. + * + * @author Ryan Weaver + * + * @internal + */ +class ContainerDebugCommand extends Command +{ + protected static $defaultName = 'debug:container'; + + /** + * @var ContainerBuilder|null + */ + protected $containerBuilder; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputArgument('name', InputArgument::OPTIONAL, 'A service name (foo)'), + new InputOption('show-arguments', null, InputOption::VALUE_NONE, 'Used to show arguments in services'), + new InputOption('show-hidden', null, InputOption::VALUE_NONE, 'Used to show hidden (internal) services'), + new InputOption('tag', null, InputOption::VALUE_REQUIRED, 'Shows all services with a specific tag'), + new InputOption('tags', null, InputOption::VALUE_NONE, 'Displays tagged services for an application'), + new InputOption('parameter', null, InputOption::VALUE_REQUIRED, 'Displays a specific parameter for an application'), + new InputOption('parameters', null, InputOption::VALUE_NONE, 'Displays parameters for an application'), + new InputOption('types', null, InputOption::VALUE_NONE, 'Displays types (classes/interfaces) available in the container'), + new InputOption('env-var', null, InputOption::VALUE_REQUIRED, 'Displays a specific environment variable used in the container'), + new InputOption('env-vars', null, InputOption::VALUE_NONE, 'Displays environment variables used in the container'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), + new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'), + ]) + ->setDescription('Displays current services for an application') + ->setHelp(<<<'EOF' +The %command.name% command displays all configured public services: + + php %command.full_name% + +To get specific information about a service, specify its name: + + php %command.full_name% validator + +To see available types that can be used for autowiring, use the --types flag: + + php %command.full_name% --types + +To see environment variables used by the container, use the --env-vars flag: + + php %command.full_name% --env-vars + +Display a specific environment variable by specifying its name with the --env-var option: + + php %command.full_name% --env-var=APP_ENV + +Use the --tags option to display tagged public services grouped by tag: + + php %command.full_name% --tags + +Find all services with a specific tag by specifying the tag name with the --tag option: + + php %command.full_name% --tag=form.type + +Use the --parameters option to display all parameters: + + php %command.full_name% --parameters + +Display a specific parameter by specifying its name with the --parameter option: + + php %command.full_name% --parameter=kernel.debug + +By default, internal services are hidden. You can display them +using the --show-hidden flag: + + php %command.full_name% --show-hidden + +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $errorIo = $io->getErrorStyle(); + + $this->validateInput($input); + $object = $this->getContainerBuilder(); + + if ($input->getOption('env-vars')) { + $options = ['env-vars' => true]; + } elseif ($envVar = $input->getOption('env-var')) { + $options = ['env-vars' => true, 'name' => $envVar]; + } elseif ($input->getOption('types')) { + $options = []; + $options['filter'] = [$this, 'filterToServiceTypes']; + } elseif ($input->getOption('parameters')) { + $parameters = []; + foreach ($object->getParameterBag()->all() as $k => $v) { + $parameters[$k] = $object->resolveEnvPlaceholders($v); + } + $object = new ParameterBag($parameters); + $options = []; + } elseif ($parameter = $input->getOption('parameter')) { + $options = ['parameter' => $parameter]; + } elseif ($input->getOption('tags')) { + $options = ['group_by' => 'tags']; + } elseif ($tag = $input->getOption('tag')) { + $options = ['tag' => $tag]; + } elseif ($name = $input->getArgument('name')) { + $name = $this->findProperServiceName($input, $errorIo, $object, $name, $input->getOption('show-hidden')); + $options = ['id' => $name]; + } else { + $options = []; + } + + $helper = new DescriptorHelper(); + $options['format'] = $input->getOption('format'); + $options['show_arguments'] = $input->getOption('show-arguments'); + $options['show_hidden'] = $input->getOption('show-hidden'); + $options['raw_text'] = $input->getOption('raw'); + $options['output'] = $io; + $options['is_debug'] = $this->getApplication()->getKernel()->isDebug(); + + try { + $helper->describe($io, $object, $options); + + if (isset($options['id']) && isset($this->getApplication()->getKernel()->getContainer()->getRemovedIds()[$options['id']])) { + $errorIo->note(sprintf('The "%s" service or alias has been removed or inlined when the container was compiled.', $options['id'])); + } + } catch (ServiceNotFoundException $e) { + if ('' !== $e->getId() && '@' === $e->getId()[0]) { + throw new ServiceNotFoundException($e->getId(), $e->getSourceId(), null, [substr($e->getId(), 1)]); + } + + throw $e; + } + + if (!$input->getArgument('name') && !$input->getOption('tag') && !$input->getOption('parameter') && !$input->getOption('env-vars') && !$input->getOption('env-var') && $input->isInteractive()) { + if ($input->getOption('tags')) { + $errorIo->comment('To search for a specific tag, re-run this command with a search term. (e.g. debug:container --tag=form.type)'); + } elseif ($input->getOption('parameters')) { + $errorIo->comment('To search for a specific parameter, re-run this command with a search term. (e.g. debug:container --parameter=kernel.debug)'); + } else { + $errorIo->comment('To search for a specific service, re-run this command with a search term. (e.g. debug:container log)'); + } + } + + return 0; + } + + /** + * Validates input arguments and options. + * + * @throws \InvalidArgumentException + */ + protected function validateInput(InputInterface $input) + { + $options = ['tags', 'tag', 'parameters', 'parameter']; + + $optionsCount = 0; + foreach ($options as $option) { + if ($input->getOption($option)) { + ++$optionsCount; + } + } + + $name = $input->getArgument('name'); + if ((null !== $name) && ($optionsCount > 0)) { + throw new InvalidArgumentException('The options tags, tag, parameters & parameter can not be combined with the service name argument.'); + } elseif ((null === $name) && $optionsCount > 1) { + throw new InvalidArgumentException('The options tags, tag, parameters & parameter can not be combined together.'); + } + } + + /** + * Loads the ContainerBuilder from the cache. + * + * @throws \LogicException + */ + protected function getContainerBuilder(): ContainerBuilder + { + if ($this->containerBuilder) { + return $this->containerBuilder; + } + + $kernel = $this->getApplication()->getKernel(); + + if (!$kernel->isDebug() || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), true))->isFresh()) { + $buildContainer = \Closure::bind(function () { return $this->buildContainer(); }, $kernel, \get_class($kernel)); + $container = $buildContainer(); + $container->getCompilerPassConfig()->setRemovingPasses([]); + $container->getCompilerPassConfig()->setAfterRemovingPasses([]); + $container->compile(); + } else { + (new XmlFileLoader($container = new ContainerBuilder(), new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump')); + $locatorPass = new ServiceLocatorTagPass(); + $locatorPass->process($container); + } + + return $this->containerBuilder = $container; + } + + private function findProperServiceName(InputInterface $input, SymfonyStyle $io, ContainerBuilder $builder, string $name, bool $showHidden): string + { + $name = ltrim($name, '\\'); + + if ($builder->has($name) || !$input->isInteractive()) { + return $name; + } + + $matchingServices = $this->findServiceIdsContaining($builder, $name, $showHidden); + if (empty($matchingServices)) { + throw new InvalidArgumentException(sprintf('No services found that match "%s".', $name)); + } + + if (1 === \count($matchingServices)) { + return $matchingServices[0]; + } + + return $io->choice('Select one of the following services to display its information', $matchingServices); + } + + private function findServiceIdsContaining(ContainerBuilder $builder, string $name, bool $showHidden): array + { + $serviceIds = $builder->getServiceIds(); + $foundServiceIds = $foundServiceIdsIgnoringBackslashes = []; + foreach ($serviceIds as $serviceId) { + if (!$showHidden && 0 === strpos($serviceId, '.')) { + continue; + } + if (false !== stripos(str_replace('\\', '', $serviceId), $name)) { + $foundServiceIdsIgnoringBackslashes[] = $serviceId; + } + if (false !== stripos($serviceId, $name)) { + $foundServiceIds[] = $serviceId; + } + } + + return $foundServiceIds ?: $foundServiceIdsIgnoringBackslashes; + } + + /** + * @internal + */ + public function filterToServiceTypes(string $serviceId): bool + { + // filter out things that could not be valid class names + if (!preg_match('/(?(DEFINE)(?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^(?&V)(?:\\\\(?&V))*+(?: \$(?&V))?$/', $serviceId)) { + return false; + } + + // if the id has a \, assume it is a class + if (false !== strpos($serviceId, '\\')) { + return true; + } + + return class_exists($serviceId) || interface_exists($serviceId, false); + } +} diff --git a/vendor/symfony/framework-bundle/Command/ContainerLintCommand.php b/vendor/symfony/framework-bundle/Command/ContainerLintCommand.php new file mode 100644 index 0000000..5e62775 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/ContainerLintCommand.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Config\ConfigCache; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass; +use Symfony\Component\DependencyInjection\Compiler\PassConfig; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; +use Symfony\Component\HttpKernel\Kernel; + +final class ContainerLintCommand extends Command +{ + protected static $defaultName = 'lint:container'; + + /** + * @var ContainerBuilder + */ + private $containerBuilder; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDescription('Ensures that arguments injected into services match type declarations') + ->setHelp('This command parses service definitions and ensures that injected values match the type declarations of each services\' class.') + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $errorIo = $io->getErrorStyle(); + + try { + $container = $this->getContainerBuilder(); + } catch (RuntimeException $e) { + $errorIo->error($e->getMessage()); + + return 2; + } + + $container->setParameter('container.build_time', time()); + + $container->compile(); + + return 0; + } + + private function getContainerBuilder(): ContainerBuilder + { + if ($this->containerBuilder) { + return $this->containerBuilder; + } + + $kernel = $this->getApplication()->getKernel(); + $kernelContainer = $kernel->getContainer(); + + if (!$kernel->isDebug() || !(new ConfigCache($kernelContainer->getParameter('debug.container.dump'), true))->isFresh()) { + if (!$kernel instanceof Kernel) { + throw new RuntimeException(sprintf('This command does not support the application kernel: "%s" does not extend "%s".', \get_class($kernel), Kernel::class)); + } + + $buildContainer = \Closure::bind(function (): ContainerBuilder { + $this->initializeBundles(); + + return $this->buildContainer(); + }, $kernel, \get_class($kernel)); + $container = $buildContainer(); + + $skippedIds = []; + } else { + if (!$kernelContainer instanceof Container) { + throw new RuntimeException(sprintf('This command does not support the application container: "%s" does not extend "%s".', \get_class($kernelContainer), Container::class)); + } + + (new XmlFileLoader($container = new ContainerBuilder($parameterBag = new EnvPlaceholderParameterBag()), new FileLocator()))->load($kernelContainer->getParameter('debug.container.dump')); + + $refl = new \ReflectionProperty($parameterBag, 'resolved'); + $refl->setAccessible(true); + $refl->setValue($parameterBag, true); + + $passConfig = $container->getCompilerPassConfig(); + $passConfig->setRemovingPasses([]); + $passConfig->setAfterRemovingPasses([]); + + $skippedIds = $kernelContainer->getRemovedIds(); + } + + $container->setParameter('container.build_hash', 'lint_container'); + $container->setParameter('container.build_id', 'lint_container'); + + $container->addCompilerPass(new CheckTypeDeclarationsPass(true, $skippedIds), PassConfig::TYPE_AFTER_REMOVING, -100); + + return $this->containerBuilder = $container; + } +} diff --git a/vendor/symfony/framework-bundle/Command/DebugAutowiringCommand.php b/vendor/symfony/framework-bundle/Command/DebugAutowiringCommand.php new file mode 100644 index 0000000..04d391d --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/DebugAutowiringCommand.php @@ -0,0 +1,161 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Bundle\FrameworkBundle\Console\Descriptor\Descriptor; +use Symfony\Component\Console\Formatter\OutputFormatterStyle; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; + +/** + * A console command for autowiring information. + * + * @author Ryan Weaver + * + * @internal + */ +class DebugAutowiringCommand extends ContainerDebugCommand +{ + protected static $defaultName = 'debug:autowiring'; + private $supportsHref; + private $fileLinkFormatter; + + public function __construct(string $name = null, FileLinkFormatter $fileLinkFormatter = null) + { + $this->supportsHref = method_exists(OutputFormatterStyle::class, 'setHref'); + $this->fileLinkFormatter = $fileLinkFormatter; + parent::__construct($name); + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputArgument('search', InputArgument::OPTIONAL, 'A search filter'), + new InputOption('all', null, InputOption::VALUE_NONE, 'Show also services that are not aliased'), + ]) + ->setDescription('Lists classes/interfaces you can use for autowiring') + ->setHelp(<<<'EOF' +The %command.name% command displays the classes and interfaces that +you can use as type-hints for autowiring: + + php %command.full_name% + +You can also pass a search term to filter the list: + + php %command.full_name% log + +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $errorIo = $io->getErrorStyle(); + + $builder = $this->getContainerBuilder(); + $serviceIds = $builder->getServiceIds(); + $serviceIds = array_filter($serviceIds, [$this, 'filterToServiceTypes']); + + if ($search = $input->getArgument('search')) { + $serviceIds = array_filter($serviceIds, function ($serviceId) use ($search) { + return false !== stripos(str_replace('\\', '', $serviceId), $search) && 0 !== strpos($serviceId, '.'); + }); + + if (empty($serviceIds)) { + $errorIo->error(sprintf('No autowirable classes or interfaces found matching "%s"', $search)); + + return 1; + } + } + + uasort($serviceIds, 'strnatcmp'); + + $io->title('Autowirable Types'); + $io->text('The following classes & interfaces can be used as type-hints when autowiring:'); + if ($search) { + $io->text(sprintf('(only showing classes/interfaces matching %s)', $search)); + } + $hasAlias = []; + $all = $input->getOption('all'); + $previousId = '-'; + $serviceIdsNb = 0; + foreach ($serviceIds as $serviceId) { + $text = []; + if (0 !== strpos($serviceId, $previousId)) { + $text[] = ''; + if ('' !== $description = Descriptor::getClassDescription($serviceId, $serviceId)) { + if (isset($hasAlias[$serviceId])) { + continue; + } + $text[] = $description; + } + $previousId = $serviceId.' $'; + } + + $serviceLine = sprintf('%s', $serviceId); + if ($this->supportsHref && '' !== $fileLink = $this->getFileLink($serviceId)) { + $serviceLine = sprintf('%s', $fileLink, $serviceId); + } + + if ($builder->hasAlias($serviceId)) { + $hasAlias[$serviceId] = true; + $serviceAlias = $builder->getAlias($serviceId); + $serviceLine .= ' ('.$serviceAlias.')'; + + if ($serviceAlias->isDeprecated()) { + $serviceLine .= ' - deprecated'; + } + } elseif (!$all) { + ++$serviceIdsNb; + continue; + } + $text[] = $serviceLine; + $io->text($text); + } + + $io->newLine(); + + if (0 < $serviceIdsNb) { + $io->text(sprintf('%s more concrete service%s would be displayed when adding the "--all" option.', $serviceIdsNb, $serviceIdsNb > 1 ? 's' : '')); + } + if ($all) { + $io->text('Pro-tip: use interfaces in your type-hints instead of classes to benefit from the dependency inversion principle.'); + } + + $io->newLine(); + + return 0; + } + + private function getFileLink(string $class): string + { + if (null === $this->fileLinkFormatter + || (null === $r = $this->getContainerBuilder()->getReflectionClass($class, false))) { + return ''; + } + + return (string) $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine()); + } +} diff --git a/vendor/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php b/vendor/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php new file mode 100644 index 0000000..ad49cde --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * A console command for retrieving information about event dispatcher. + * + * @author Matthieu Auger + * + * @final + */ +class EventDispatcherDebugCommand extends Command +{ + protected static $defaultName = 'debug:event-dispatcher'; + private $dispatcher; + + public function __construct(EventDispatcherInterface $dispatcher) + { + parent::__construct(); + + $this->dispatcher = $dispatcher; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputArgument('event', InputArgument::OPTIONAL, 'An event name'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), + new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'), + ]) + ->setDescription('Displays configured listeners for an application') + ->setHelp(<<<'EOF' +The %command.name% command displays all configured listeners: + + php %command.full_name% + +To get specific listeners for an event, specify its name: + + php %command.full_name% kernel.request +EOF + ) + ; + } + + /** + * {@inheritdoc} + * + * @throws \LogicException + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + $options = []; + if ($event = $input->getArgument('event')) { + if (!$this->dispatcher->hasListeners($event)) { + $io->getErrorStyle()->warning(sprintf('The event "%s" does not have any registered listeners.', $event)); + + return 0; + } + + $options = ['event' => $event]; + } + + $helper = new DescriptorHelper(); + $options['format'] = $input->getOption('format'); + $options['raw_text'] = $input->getOption('raw'); + $options['output'] = $io; + $helper->describe($io, $this->dispatcher, $options); + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/RouterDebugCommand.php b/vendor/symfony/framework-bundle/Command/RouterDebugCommand.php new file mode 100644 index 0000000..9724e51 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/RouterDebugCommand.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\RouterInterface; + +/** + * A console command for retrieving information about routes. + * + * @author Fabien Potencier + * @author Tobias Schultze + * + * @final + */ +class RouterDebugCommand extends Command +{ + protected static $defaultName = 'debug:router'; + private $router; + private $fileLinkFormatter; + + public function __construct(RouterInterface $router, FileLinkFormatter $fileLinkFormatter = null) + { + parent::__construct(); + + $this->router = $router; + $this->fileLinkFormatter = $fileLinkFormatter; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputArgument('name', InputArgument::OPTIONAL, 'A route name'), + new InputOption('show-controllers', null, InputOption::VALUE_NONE, 'Show assigned controllers in overview'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), + new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw route(s)'), + ]) + ->setDescription('Displays current routes for an application') + ->setHelp(<<<'EOF' +The %command.name% displays the configured routes: + + php %command.full_name% + +EOF + ) + ; + } + + /** + * {@inheritdoc} + * + * @throws InvalidArgumentException When route does not exist + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $name = $input->getArgument('name'); + $helper = new DescriptorHelper($this->fileLinkFormatter); + $routes = $this->router->getRouteCollection(); + + if ($name) { + if (!($route = $routes->get($name)) && $matchingRoutes = $this->findRouteNameContaining($name, $routes)) { + $default = 1 === \count($matchingRoutes) ? $matchingRoutes[0] : null; + $name = $io->choice('Select one of the matching routes', $matchingRoutes, $default); + $route = $routes->get($name); + } + + if (!$route) { + throw new InvalidArgumentException(sprintf('The route "%s" does not exist.', $name)); + } + + $helper->describe($io, $route, [ + 'format' => $input->getOption('format'), + 'raw_text' => $input->getOption('raw'), + 'name' => $name, + 'output' => $io, + ]); + } else { + $helper->describe($io, $routes, [ + 'format' => $input->getOption('format'), + 'raw_text' => $input->getOption('raw'), + 'show_controllers' => $input->getOption('show-controllers'), + 'output' => $io, + ]); + } + + return 0; + } + + private function findRouteNameContaining(string $name, RouteCollection $routes): array + { + $foundRoutesNames = []; + foreach ($routes as $routeName => $route) { + if (false !== stripos($routeName, $name)) { + $foundRoutesNames[] = $routeName; + } + } + + return $foundRoutesNames; + } +} diff --git a/vendor/symfony/framework-bundle/Command/RouterMatchCommand.php b/vendor/symfony/framework-bundle/Command/RouterMatchCommand.php new file mode 100644 index 0000000..454767e --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/RouterMatchCommand.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Routing\Matcher\TraceableUrlMatcher; +use Symfony\Component\Routing\RouterInterface; + +/** + * A console command to test route matching. + * + * @author Fabien Potencier + * + * @final + */ +class RouterMatchCommand extends Command +{ + protected static $defaultName = 'router:match'; + + private $router; + + public function __construct(RouterInterface $router) + { + parent::__construct(); + + $this->router = $router; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputArgument('path_info', InputArgument::REQUIRED, 'A path info'), + new InputOption('method', null, InputOption::VALUE_REQUIRED, 'Sets the HTTP method'), + new InputOption('scheme', null, InputOption::VALUE_REQUIRED, 'Sets the URI scheme (usually http or https)'), + new InputOption('host', null, InputOption::VALUE_REQUIRED, 'Sets the URI host'), + ]) + ->setDescription('Helps debug routes by simulating a path info match') + ->setHelp(<<<'EOF' +The %command.name% shows which routes match a given request and which don't and for what reason: + + php %command.full_name% /foo + +or + + php %command.full_name% /foo --method POST --scheme https --host symfony.com --verbose + +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + $context = $this->router->getContext(); + if (null !== $method = $input->getOption('method')) { + $context->setMethod($method); + } + if (null !== $scheme = $input->getOption('scheme')) { + $context->setScheme($scheme); + } + if (null !== $host = $input->getOption('host')) { + $context->setHost($host); + } + + $matcher = new TraceableUrlMatcher($this->router->getRouteCollection(), $context); + + $traces = $matcher->getTraces($input->getArgument('path_info')); + + $io->newLine(); + + $matches = false; + foreach ($traces as $trace) { + if (TraceableUrlMatcher::ROUTE_ALMOST_MATCHES == $trace['level']) { + $io->text(sprintf('Route "%s" almost matches but %s', $trace['name'], lcfirst($trace['log']))); + } elseif (TraceableUrlMatcher::ROUTE_MATCHES == $trace['level']) { + $io->success(sprintf('Route "%s" matches', $trace['name'])); + + $routerDebugCommand = $this->getApplication()->find('debug:router'); + $routerDebugCommand->run(new ArrayInput(['name' => $trace['name']]), $output); + + $matches = true; + } elseif ($input->getOption('verbose')) { + $io->text(sprintf('Route "%s" does not match: %s', $trace['name'], $trace['log'])); + } + } + + if (!$matches) { + $io->error(sprintf('None of the routes match the path "%s"', $input->getArgument('path_info'))); + + return 1; + } + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php b/vendor/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php new file mode 100644 index 0000000..e4fbfd2 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * @author Nicolas Grekas + * + * @internal + */ +final class SecretsDecryptToLocalCommand extends Command +{ + protected static $defaultName = 'secrets:decrypt-to-local'; + + private $vault; + private $localVault; + + public function __construct(AbstractVault $vault, AbstractVault $localVault = null) + { + $this->vault = $vault; + $this->localVault = $localVault; + + parent::__construct(); + } + + protected function configure() + { + $this + ->setDescription('Decrypts all secrets and stores them in the local vault.') + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces overriding of secrets that already exist in the local vault') + ->setHelp(<<<'EOF' +The %command.name% command decrypts all secrets and copies them in the local vault. + + %command.full_name% + +When the option --force is provided, secrets that already exist in the local vault are overriden. + + %command.full_name% --force +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); + + if (null === $this->localVault) { + $io->error('The local vault is disabled.'); + + return 1; + } + + $secrets = $this->vault->list(true); + + if (!$input->getOption('force')) { + foreach ($this->localVault->list() as $k => $v) { + unset($secrets[$k]); + } + } + + foreach ($secrets as $k => $v) { + if (null === $v) { + $io->error($this->vault->getLastMessage()); + + return 1; + } + + $this->localVault->seal($k, $v); + } + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php b/vendor/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php new file mode 100644 index 0000000..607140e --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * @author Nicolas Grekas + * + * @internal + */ +final class SecretsEncryptFromLocalCommand extends Command +{ + protected static $defaultName = 'secrets:encrypt-from-local'; + + private $vault; + private $localVault; + + public function __construct(AbstractVault $vault, AbstractVault $localVault = null) + { + $this->vault = $vault; + $this->localVault = $localVault; + + parent::__construct(); + } + + protected function configure() + { + $this + ->setDescription('Encrypts all local secrets to the vault.') + ->setHelp(<<<'EOF' +The %command.name% command encrypts all locally overridden secrets to the vault. + + %command.full_name% +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); + + if (null === $this->localVault) { + $io->error('The local vault is disabled.'); + + return 1; + } + + foreach ($this->vault->list(true) as $name => $value) { + $localValue = $this->localVault->reveal($name); + + if (null !== $localValue && $value !== $localValue) { + $this->vault->seal($name, $localValue); + } elseif (null !== $message = $this->localVault->getLastMessage()) { + $io->error($message); + + return 1; + } + } + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php b/vendor/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php new file mode 100644 index 0000000..f56fd0f --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * @author Tobias Schultze + * @author Jérémy Derussé + * @author Nicolas Grekas + * + * @internal + */ +final class SecretsGenerateKeysCommand extends Command +{ + protected static $defaultName = 'secrets:generate-keys'; + + private $vault; + private $localVault; + + public function __construct(AbstractVault $vault, AbstractVault $localVault = null) + { + $this->vault = $vault; + $this->localVault = $localVault; + + parent::__construct(); + } + + protected function configure() + { + $this + ->setDescription('Generates new encryption keys.') + ->addOption('local', 'l', InputOption::VALUE_NONE, 'Updates the local vault.') + ->addOption('rotate', 'r', InputOption::VALUE_NONE, 'Re-encrypts existing secrets with the newly generated keys.') + ->setHelp(<<<'EOF' +The %command.name% command generates a new encryption key. + + %command.full_name% + +If encryption keys already exist, the command must be called with +the --rotate option in order to override those keys and re-encrypt +existing secrets. + + %command.full_name% --rotate +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); + $vault = $input->getOption('local') ? $this->localVault : $this->vault; + + if (null === $vault) { + $io->success('The local vault is disabled.'); + + return 1; + } + + if (!$input->getOption('rotate')) { + if ($vault->generateKeys()) { + $io->success($vault->getLastMessage()); + + if ($this->vault === $vault) { + $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️'); + } + + return 0; + } + + $io->warning($vault->getLastMessage()); + + return 1; + } + + $secrets = []; + foreach ($vault->list(true) as $name => $value) { + if (null === $value) { + $io->error($vault->getLastMessage()); + + return 1; + } + + $secrets[$name] = $value; + } + + if (!$vault->generateKeys(true)) { + $io->warning($vault->getLastMessage()); + + return 1; + } + + $io->success($vault->getLastMessage()); + + if ($secrets) { + foreach ($secrets as $name => $value) { + $vault->seal($name, $value); + } + + $io->comment('Existing secrets have been rotated to the new keys.'); + } + + if ($this->vault === $vault) { + $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️'); + } + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/SecretsListCommand.php b/vendor/symfony/framework-bundle/Command/SecretsListCommand.php new file mode 100644 index 0000000..cc32284 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/SecretsListCommand.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Dumper; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * @author Tobias Schultze + * @author Jérémy Derussé + * @author Nicolas Grekas + * + * @internal + */ +final class SecretsListCommand extends Command +{ + protected static $defaultName = 'secrets:list'; + + private $vault; + private $localVault; + + public function __construct(AbstractVault $vault, AbstractVault $localVault = null) + { + $this->vault = $vault; + $this->localVault = $localVault; + + parent::__construct(); + } + + protected function configure() + { + $this + ->setDescription('Lists all secrets.') + ->addOption('reveal', 'r', InputOption::VALUE_NONE, 'Display decrypted values alongside names') + ->setHelp(<<<'EOF' +The %command.name% command list all stored secrets. + + %command.full_name% + +When the option --reveal is provided, the decrypted secrets are also displayed. + + %command.full_name% --reveal +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); + + $io->comment('Use "%env()%" to reference a secret in a config file.'); + + if (!$reveal = $input->getOption('reveal')) { + $io->comment(sprintf('To reveal the secrets run php %s %s --reveal', $_SERVER['PHP_SELF'], $this->getName())); + } + + $secrets = $this->vault->list($reveal); + $localSecrets = null !== $this->localVault ? $this->localVault->list($reveal) : null; + + $rows = []; + + $dump = new Dumper($output); + $dump = static function (?string $v) use ($dump) { + return null === $v ? '******' : $dump($v); + }; + + foreach ($secrets as $name => $value) { + $rows[$name] = [$name, $dump($value)]; + } + + if (null !== $message = $this->vault->getLastMessage()) { + $io->comment($message); + } + + foreach ($localSecrets ?? [] as $name => $value) { + if (isset($rows[$name])) { + $rows[$name][] = $dump($value); + } + } + + if (null !== $this->localVault && null !== $message = $this->localVault->getLastMessage()) { + $io->comment($message); + } + + (new SymfonyStyle($input, $output)) + ->table(['Secret', 'Value'] + (null !== $localSecrets ? [2 => 'Local Value'] : []), $rows); + + $io->comment("Local values override secret values.\nUse secrets:set --local to defined them."); + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/SecretsRemoveCommand.php b/vendor/symfony/framework-bundle/Command/SecretsRemoveCommand.php new file mode 100644 index 0000000..b0ce9a8 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/SecretsRemoveCommand.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * @author Jérémy Derussé + * @author Nicolas Grekas + * + * @internal + */ +final class SecretsRemoveCommand extends Command +{ + protected static $defaultName = 'secrets:remove'; + + private $vault; + private $localVault; + + public function __construct(AbstractVault $vault, AbstractVault $localVault = null) + { + $this->vault = $vault; + $this->localVault = $localVault; + + parent::__construct(); + } + + protected function configure() + { + $this + ->setDescription('Removes a secret from the vault.') + ->addArgument('name', InputArgument::REQUIRED, 'The name of the secret') + ->addOption('local', 'l', InputOption::VALUE_NONE, 'Updates the local vault.') + ->setHelp(<<<'EOF' +The %command.name% command removes a secret from the vault. + + %command.full_name% +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); + $vault = $input->getOption('local') ? $this->localVault : $this->vault; + + if (null === $vault) { + $io->success('The local vault is disabled.'); + + return 1; + } + + if ($vault->remove($name = $input->getArgument('name'))) { + $io->success($vault->getLastMessage() ?? 'Secret was removed from the vault.'); + } else { + $io->comment($vault->getLastMessage() ?? 'Secret was not found in the vault.'); + } + + if ($this->vault === $vault && null !== $this->localVault->reveal($name)) { + $io->comment('Note that this secret is overridden in the local vault.'); + } + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/SecretsSetCommand.php b/vendor/symfony/framework-bundle/Command/SecretsSetCommand.php new file mode 100644 index 0000000..5cca8d7 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/SecretsSetCommand.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * @author Tobias Schultze + * @author Jérémy Derussé + * @author Nicolas Grekas + * + * @internal + */ +final class SecretsSetCommand extends Command +{ + protected static $defaultName = 'secrets:set'; + + private $vault; + private $localVault; + + public function __construct(AbstractVault $vault, AbstractVault $localVault = null) + { + $this->vault = $vault; + $this->localVault = $localVault; + + parent::__construct(); + } + + protected function configure() + { + $this + ->setDescription('Sets a secret in the vault.') + ->addArgument('name', InputArgument::REQUIRED, 'The name of the secret') + ->addArgument('file', InputArgument::OPTIONAL, 'A file where to read the secret from or "-" for reading from STDIN') + ->addOption('local', 'l', InputOption::VALUE_NONE, 'Updates the local vault.') + ->addOption('random', 'r', InputOption::VALUE_OPTIONAL, 'Generates a random value.', false) + ->setHelp(<<<'EOF' +The %command.name% command stores a secret in the vault. + + %command.full_name% + +To reference secrets in services.yaml or any other config +files, use "%env()%". + +By default, the secret value should be entered interactively. +Alternatively, provide a file where to read the secret from: + + php %command.full_name% filename + +Use "-" as a file name to read from STDIN: + + cat filename | php %command.full_name% - + +Use --local to override secrets for local needs. +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $errOutput = $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output; + $io = new SymfonyStyle($input, $errOutput); + $name = $input->getArgument('name'); + $vault = $input->getOption('local') ? $this->localVault : $this->vault; + + if (null === $vault) { + $io->error('The local vault is disabled.'); + + return 1; + } + + if ($this->localVault === $vault && !\array_key_exists($name, $this->vault->list())) { + $io->error(sprintf('Secret "%s" does not exist in the vault, you cannot override it locally.', $name)); + + return 1; + } + + if (0 < $random = $input->getOption('random') ?? 16) { + $value = strtr(substr(base64_encode(random_bytes($random)), 0, $random), '+/', '-_'); + } elseif (!$file = $input->getArgument('file')) { + $value = $io->askHidden('Please type the secret value'); + } elseif ('-' === $file) { + $value = file_get_contents('php://stdin'); + } elseif (is_file($file) && is_readable($file)) { + $value = file_get_contents($file); + } elseif (!is_file($file)) { + throw new \InvalidArgumentException(sprintf('File not found: "%s".', $file)); + } elseif (!is_readable($file)) { + throw new \InvalidArgumentException(sprintf('File is not readable: "%s".', $file)); + } + + if (null === $value) { + $io->warning('No value provided, aborting.'); + + return 1; + } + + if ($vault->generateKeys()) { + $io->success($vault->getLastMessage()); + + if ($this->vault === $vault) { + $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️'); + } + } + + $vault->seal($name, $value); + + $io->success($vault->getLastMessage() ?? 'Secret was successfully stored in the vault.'); + + if (0 < $random) { + $errOutput->write(' // The generated random value is: '); + $output->write($value); + $errOutput->writeln(''); + $io->newLine(); + } + + if ($this->vault === $vault && null !== $this->localVault->reveal($name)) { + $io->comment('Note that this secret is overridden in the local vault.'); + } + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/TranslationDebugCommand.php b/vendor/symfony/framework-bundle/Command/TranslationDebugCommand.php new file mode 100644 index 0000000..24290a4 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/TranslationDebugCommand.php @@ -0,0 +1,342 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Component\Translation\Catalogue\MergeOperation; +use Symfony\Component\Translation\DataCollectorTranslator; +use Symfony\Component\Translation\Extractor\ExtractorInterface; +use Symfony\Component\Translation\LoggingTranslator; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\Reader\TranslationReaderInterface; +use Symfony\Component\Translation\Translator; +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * Helps finding unused or missing translation messages in a given locale + * and comparing them with the fallback ones. + * + * @author Florian Voutzinos + * + * @final + */ +class TranslationDebugCommand extends Command +{ + const MESSAGE_MISSING = 0; + const MESSAGE_UNUSED = 1; + const MESSAGE_EQUALS_FALLBACK = 2; + + protected static $defaultName = 'debug:translation'; + + private $translator; + private $reader; + private $extractor; + private $defaultTransPath; + private $defaultViewsPath; + private $transPaths; + private $viewsPaths; + + public function __construct(TranslatorInterface $translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $viewsPaths = []) + { + parent::__construct(); + + $this->translator = $translator; + $this->reader = $reader; + $this->extractor = $extractor; + $this->defaultTransPath = $defaultTransPath; + $this->defaultViewsPath = $defaultViewsPath; + $this->transPaths = $transPaths; + $this->viewsPaths = $viewsPaths; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), + new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages'), + new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'The messages domain'), + new InputOption('only-missing', null, InputOption::VALUE_NONE, 'Displays only missing messages'), + new InputOption('only-unused', null, InputOption::VALUE_NONE, 'Displays only unused messages'), + new InputOption('all', null, InputOption::VALUE_NONE, 'Load messages from all registered bundles'), + ]) + ->setDescription('Displays translation messages information') + ->setHelp(<<<'EOF' +The %command.name% command helps finding unused or missing translation +messages and comparing them with the fallback ones by inspecting the +templates and translation files of a given bundle or the default translations directory. + +You can display information about bundle translations in a specific locale: + + php %command.full_name% en AcmeDemoBundle + +You can also specify a translation domain for the search: + + php %command.full_name% --domain=messages en AcmeDemoBundle + +You can only display missing messages: + + php %command.full_name% --only-missing en AcmeDemoBundle + +You can only display unused messages: + + php %command.full_name% --only-unused en AcmeDemoBundle + +You can display information about application translations in a specific locale: + + php %command.full_name% en + +You can display information about translations in all registered bundles in a specific locale: + + php %command.full_name% --all en + +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + $locale = $input->getArgument('locale'); + $domain = $input->getOption('domain'); + /** @var KernelInterface $kernel */ + $kernel = $this->getApplication()->getKernel(); + + // Define Root Paths + $transPaths = $this->transPaths; + if ($this->defaultTransPath) { + $transPaths[] = $this->defaultTransPath; + } + $viewsPaths = $this->viewsPaths; + if ($this->defaultViewsPath) { + $viewsPaths[] = $this->defaultViewsPath; + } + + // Override with provided Bundle info + if (null !== $input->getArgument('bundle')) { + try { + $bundle = $kernel->getBundle($input->getArgument('bundle')); + $bundleDir = $bundle->getPath(); + $transPaths = [is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundleDir.'/translations']; + $viewsPaths = [is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundleDir.'/templates']; + if ($this->defaultTransPath) { + $transPaths[] = $this->defaultTransPath; + } + if ($this->defaultViewsPath) { + $viewsPaths[] = $this->defaultViewsPath; + } + } catch (\InvalidArgumentException $e) { + // such a bundle does not exist, so treat the argument as path + $path = $input->getArgument('bundle'); + + $transPaths = [$path.'/translations']; + $viewsPaths = [$path.'/templates']; + + if (!is_dir($transPaths[0]) && !isset($transPaths[1])) { + throw new InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0])); + } + } + } elseif ($input->getOption('all')) { + foreach ($kernel->getBundles() as $bundle) { + $bundleDir = $bundle->getPath(); + $transPaths[] = is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundle->getPath().'/translations'; + $viewsPaths[] = is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundle->getPath().'/templates'; + } + } + + // Extract used messages + $extractedCatalogue = $this->extractMessages($locale, $viewsPaths); + + // Load defined messages + $currentCatalogue = $this->loadCurrentMessages($locale, $transPaths); + + // Merge defined and extracted messages to get all message ids + $mergeOperation = new MergeOperation($extractedCatalogue, $currentCatalogue); + $allMessages = $mergeOperation->getResult()->all($domain); + if (null !== $domain) { + $allMessages = [$domain => $allMessages]; + } + + // No defined or extracted messages + if (empty($allMessages) || null !== $domain && empty($allMessages[$domain])) { + $outputMessage = sprintf('No defined or extracted messages for locale "%s"', $locale); + + if (null !== $domain) { + $outputMessage .= sprintf(' and domain "%s"', $domain); + } + + $io->getErrorStyle()->warning($outputMessage); + + return 0; + } + + // Load the fallback catalogues + $fallbackCatalogues = $this->loadFallbackCatalogues($locale, $transPaths); + + // Display header line + $headers = ['State', 'Domain', 'Id', sprintf('Message Preview (%s)', $locale)]; + foreach ($fallbackCatalogues as $fallbackCatalogue) { + $headers[] = sprintf('Fallback Message Preview (%s)', $fallbackCatalogue->getLocale()); + } + $rows = []; + // Iterate all message ids and determine their state + foreach ($allMessages as $domain => $messages) { + foreach (array_keys($messages) as $messageId) { + $value = $currentCatalogue->get($messageId, $domain); + $states = []; + + if ($extractedCatalogue->defines($messageId, $domain)) { + if (!$currentCatalogue->defines($messageId, $domain)) { + $states[] = self::MESSAGE_MISSING; + } + } elseif ($currentCatalogue->defines($messageId, $domain)) { + $states[] = self::MESSAGE_UNUSED; + } + + if (!\in_array(self::MESSAGE_UNUSED, $states) && true === $input->getOption('only-unused') + || !\in_array(self::MESSAGE_MISSING, $states) && true === $input->getOption('only-missing')) { + continue; + } + + foreach ($fallbackCatalogues as $fallbackCatalogue) { + if ($fallbackCatalogue->defines($messageId, $domain) && $value === $fallbackCatalogue->get($messageId, $domain)) { + $states[] = self::MESSAGE_EQUALS_FALLBACK; + + break; + } + } + + $row = [$this->formatStates($states), $domain, $this->formatId($messageId), $this->sanitizeString($value)]; + foreach ($fallbackCatalogues as $fallbackCatalogue) { + $row[] = $this->sanitizeString($fallbackCatalogue->get($messageId, $domain)); + } + + $rows[] = $row; + } + } + + $io->table($headers, $rows); + + return 0; + } + + private function formatState(int $state): string + { + if (self::MESSAGE_MISSING === $state) { + return ' missing '; + } + + if (self::MESSAGE_UNUSED === $state) { + return ' unused '; + } + + if (self::MESSAGE_EQUALS_FALLBACK === $state) { + return ' fallback '; + } + + return $state; + } + + private function formatStates(array $states): string + { + $result = []; + foreach ($states as $state) { + $result[] = $this->formatState($state); + } + + return implode(' ', $result); + } + + private function formatId(string $id): string + { + return sprintf('%s', $id); + } + + private function sanitizeString(string $string, int $length = 40): string + { + $string = trim(preg_replace('/\s+/', ' ', $string)); + + if (false !== $encoding = mb_detect_encoding($string, null, true)) { + if (mb_strlen($string, $encoding) > $length) { + return mb_substr($string, 0, $length - 3, $encoding).'...'; + } + } elseif (\strlen($string) > $length) { + return substr($string, 0, $length - 3).'...'; + } + + return $string; + } + + private function extractMessages(string $locale, array $transPaths): MessageCatalogue + { + $extractedCatalogue = new MessageCatalogue($locale); + foreach ($transPaths as $path) { + if (is_dir($path) || is_file($path)) { + $this->extractor->extract($path, $extractedCatalogue); + } + } + + return $extractedCatalogue; + } + + private function loadCurrentMessages(string $locale, array $transPaths): MessageCatalogue + { + $currentCatalogue = new MessageCatalogue($locale); + foreach ($transPaths as $path) { + if (is_dir($path)) { + $this->reader->read($path, $currentCatalogue); + } + } + + return $currentCatalogue; + } + + /** + * @return MessageCatalogue[] + */ + private function loadFallbackCatalogues(string $locale, array $transPaths): array + { + $fallbackCatalogues = []; + if ($this->translator instanceof Translator || $this->translator instanceof DataCollectorTranslator || $this->translator instanceof LoggingTranslator) { + foreach ($this->translator->getFallbackLocales() as $fallbackLocale) { + if ($fallbackLocale === $locale) { + continue; + } + + $fallbackCatalogue = new MessageCatalogue($fallbackLocale); + foreach ($transPaths as $path) { + if (is_dir($path)) { + $this->reader->read($path, $fallbackCatalogue); + } + } + $fallbackCatalogues[] = $fallbackCatalogue; + } + } + + return $fallbackCatalogues; + } +} diff --git a/vendor/symfony/framework-bundle/Command/TranslationUpdateCommand.php b/vendor/symfony/framework-bundle/Command/TranslationUpdateCommand.php new file mode 100644 index 0000000..e717b07 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/TranslationUpdateCommand.php @@ -0,0 +1,316 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Component\Translation\Catalogue\MergeOperation; +use Symfony\Component\Translation\Catalogue\TargetOperation; +use Symfony\Component\Translation\Extractor\ExtractorInterface; +use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\Reader\TranslationReaderInterface; +use Symfony\Component\Translation\Writer\TranslationWriterInterface; + +/** + * A command that parses templates to extract translation messages and adds them + * into the translation files. + * + * @author Michel Salib + * + * @final + */ +class TranslationUpdateCommand extends Command +{ + private const ASC = 'asc'; + private const DESC = 'desc'; + private const SORT_ORDERS = [self::ASC, self::DESC]; + + protected static $defaultName = 'translation:update'; + + private $writer; + private $reader; + private $extractor; + private $defaultLocale; + private $defaultTransPath; + private $defaultViewsPath; + private $transPaths; + private $viewsPaths; + + public function __construct(TranslationWriterInterface $writer, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultLocale, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $viewsPaths = []) + { + parent::__construct(); + + $this->writer = $writer; + $this->reader = $reader; + $this->extractor = $extractor; + $this->defaultLocale = $defaultLocale; + $this->defaultTransPath = $defaultTransPath; + $this->defaultViewsPath = $defaultViewsPath; + $this->transPaths = $transPaths; + $this->viewsPaths = $viewsPaths; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), + new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages'), + new InputOption('prefix', null, InputOption::VALUE_OPTIONAL, 'Override the default prefix', '__'), + new InputOption('output-format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format', 'xlf'), + new InputOption('dump-messages', null, InputOption::VALUE_NONE, 'Should the messages be dumped in the console'), + new InputOption('force', null, InputOption::VALUE_NONE, 'Should the update be done'), + new InputOption('no-backup', null, InputOption::VALUE_NONE, 'Should backup be disabled'), + new InputOption('clean', null, InputOption::VALUE_NONE, 'Should clean not found messages'), + new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'Specify the domain to update'), + new InputOption('xliff-version', null, InputOption::VALUE_OPTIONAL, 'Override the default xliff version', '1.2'), + new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically'), + ]) + ->setDescription('Updates the translation file') + ->setHelp(<<<'EOF' +The %command.name% command extracts translation strings from templates +of a given bundle or the default translations directory. It can display them or merge +the new ones into the translation files. + +When new translation strings are found it can automatically add a prefix to the translation +message. + +Example running against a Bundle (AcmeBundle) + + php %command.full_name% --dump-messages en AcmeBundle + php %command.full_name% --force --prefix="new_" fr AcmeBundle + +Example running against default messages directory + + php %command.full_name% --dump-messages en + php %command.full_name% --force --prefix="new_" fr + +You can sort the output with the --sort flag: + + php %command.full_name% --dump-messages --sort=asc en AcmeBundle + php %command.full_name% --dump-messages --sort=desc fr +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $errorIo = $io->getErrorStyle(); + + // check presence of force or dump-message + if (true !== $input->getOption('force') && true !== $input->getOption('dump-messages')) { + $errorIo->error('You must choose one of --force or --dump-messages'); + + return 1; + } + + // check format + $supportedFormats = $this->writer->getFormats(); + if (!\in_array($input->getOption('output-format'), $supportedFormats, true)) { + $errorIo->error(['Wrong output format', 'Supported formats are: '.implode(', ', $supportedFormats).'.']); + + return 1; + } + /** @var KernelInterface $kernel */ + $kernel = $this->getApplication()->getKernel(); + + // Define Root Paths + $transPaths = $this->transPaths; + if ($this->defaultTransPath) { + $transPaths[] = $this->defaultTransPath; + } + $viewsPaths = $this->viewsPaths; + if ($this->defaultViewsPath) { + $viewsPaths[] = $this->defaultViewsPath; + } + $currentName = 'default directory'; + + // Override with provided Bundle info + if (null !== $input->getArgument('bundle')) { + try { + $foundBundle = $kernel->getBundle($input->getArgument('bundle')); + $bundleDir = $foundBundle->getPath(); + $transPaths = [is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundleDir.'/translations']; + $viewsPaths = [is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundleDir.'/templates']; + if ($this->defaultTransPath) { + $transPaths[] = $this->defaultTransPath; + } + if ($this->defaultViewsPath) { + $viewsPaths[] = $this->defaultViewsPath; + } + $currentName = $foundBundle->getName(); + } catch (\InvalidArgumentException $e) { + // such a bundle does not exist, so treat the argument as path + $path = $input->getArgument('bundle'); + + $transPaths = [$path.'/translations']; + $viewsPaths = [$path.'/templates']; + + if (!is_dir($transPaths[0]) && !isset($transPaths[1])) { + throw new InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0])); + } + } + } + + $errorIo->title('Translation Messages Extractor and Dumper'); + $errorIo->comment(sprintf('Generating "%s" translation files for "%s"', $input->getArgument('locale'), $currentName)); + + // load any messages from templates + $extractedCatalogue = new MessageCatalogue($input->getArgument('locale')); + $errorIo->comment('Parsing templates...'); + $this->extractor->setPrefix($input->getOption('prefix')); + foreach ($viewsPaths as $path) { + if (is_dir($path) || is_file($path)) { + $this->extractor->extract($path, $extractedCatalogue); + } + } + + // load any existing messages from the translation files + $currentCatalogue = new MessageCatalogue($input->getArgument('locale')); + $errorIo->comment('Loading translation files...'); + foreach ($transPaths as $path) { + if (is_dir($path)) { + $this->reader->read($path, $currentCatalogue); + } + } + + if (null !== $domain = $input->getOption('domain')) { + $currentCatalogue = $this->filterCatalogue($currentCatalogue, $domain); + $extractedCatalogue = $this->filterCatalogue($extractedCatalogue, $domain); + } + + // process catalogues + $operation = $input->getOption('clean') + ? new TargetOperation($currentCatalogue, $extractedCatalogue) + : new MergeOperation($currentCatalogue, $extractedCatalogue); + + // Exit if no messages found. + if (!\count($operation->getDomains())) { + $errorIo->warning('No translation messages were found.'); + + return 0; + } + + $resultMessage = 'Translation files were successfully updated'; + + // show compiled list of messages + if (true === $input->getOption('dump-messages')) { + $extractedMessagesCount = 0; + $io->newLine(); + foreach ($operation->getDomains() as $domain) { + $newKeys = array_keys($operation->getNewMessages($domain)); + $allKeys = array_keys($operation->getMessages($domain)); + + $list = array_merge( + array_diff($allKeys, $newKeys), + array_map(function ($id) { + return sprintf('%s', $id); + }, $newKeys), + array_map(function ($id) { + return sprintf('%s', $id); + }, array_keys($operation->getObsoleteMessages($domain))) + ); + + $domainMessagesCount = \count($list); + + if ($sort = $input->getOption('sort')) { + $sort = strtolower($sort); + if (!\in_array($sort, self::SORT_ORDERS, true)) { + $errorIo->error(['Wrong sort order', 'Supported formats are: '.implode(', ', self::SORT_ORDERS).'.']); + + return 1; + } + + if (self::DESC === $sort) { + rsort($list); + } else { + sort($list); + } + } + + $io->section(sprintf('Messages extracted for domain "%s" (%d message%s)', $domain, $domainMessagesCount, $domainMessagesCount > 1 ? 's' : '')); + $io->listing($list); + + $extractedMessagesCount += $domainMessagesCount; + } + + if ('xlf' === $input->getOption('output-format')) { + $errorIo->comment(sprintf('Xliff output version is %s', $input->getOption('xliff-version'))); + } + + $resultMessage = sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was'); + } + + if (true === $input->getOption('no-backup')) { + $this->writer->disableBackup(); + } + + // save the files + if (true === $input->getOption('force')) { + $errorIo->comment('Writing files...'); + + $bundleTransPath = false; + foreach ($transPaths as $path) { + if (is_dir($path)) { + $bundleTransPath = $path; + } + } + + if (!$bundleTransPath) { + $bundleTransPath = end($transPaths); + } + + $this->writer->write($operation->getResult(), $input->getOption('output-format'), ['path' => $bundleTransPath, 'default_locale' => $this->defaultLocale, 'xliff_version' => $input->getOption('xliff-version')]); + + if (true === $input->getOption('dump-messages')) { + $resultMessage .= ' and translation files were updated'; + } + } + + $errorIo->success($resultMessage.'.'); + + return 0; + } + + private function filterCatalogue(MessageCatalogue $catalogue, string $domain): MessageCatalogue + { + $filteredCatalogue = new MessageCatalogue($catalogue->getLocale()); + + if ($messages = $catalogue->all($domain)) { + $filteredCatalogue->add($messages, $domain); + } + foreach ($catalogue->getResources() as $resource) { + $filteredCatalogue->addResource($resource); + } + if ($metadata = $catalogue->getMetadata('', $domain)) { + foreach ($metadata as $k => $v) { + $filteredCatalogue->setMetadata($k, $v, $domain); + } + } + + return $filteredCatalogue; + } +} diff --git a/vendor/symfony/framework-bundle/Command/WorkflowDumpCommand.php b/vendor/symfony/framework-bundle/Command/WorkflowDumpCommand.php new file mode 100644 index 0000000..cec930d --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/WorkflowDumpCommand.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Workflow\Dumper\GraphvizDumper; +use Symfony\Component\Workflow\Dumper\PlantUmlDumper; +use Symfony\Component\Workflow\Dumper\StateMachineGraphvizDumper; +use Symfony\Component\Workflow\Marking; + +/** + * @author Grégoire Pineau + * + * @final + */ +class WorkflowDumpCommand extends Command +{ + protected static $defaultName = 'workflow:dump'; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition([ + new InputArgument('name', InputArgument::REQUIRED, 'A workflow name'), + new InputArgument('marking', InputArgument::IS_ARRAY, 'A marking (a list of places)'), + new InputOption('label', 'l', InputOption::VALUE_REQUIRED, 'Labels a graph'), + new InputOption('dump-format', null, InputOption::VALUE_REQUIRED, 'The dump format [dot|puml]', 'dot'), + ]) + ->setDescription('Dump a workflow') + ->setHelp(<<<'EOF' +The %command.name% command dumps the graphical representation of a +workflow in different formats + +DOT: %command.full_name% | dot -Tpng > workflow.png +PUML: %command.full_name% --dump-format=puml | java -jar plantuml.jar -p > workflow.png + +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $container = $this->getApplication()->getKernel()->getContainer(); + $serviceId = $input->getArgument('name'); + + if ($container->has('workflow.'.$serviceId)) { + $workflow = $container->get('workflow.'.$serviceId); + $type = 'workflow'; + } elseif ($container->has('state_machine.'.$serviceId)) { + $workflow = $container->get('state_machine.'.$serviceId); + $type = 'state_machine'; + } else { + throw new InvalidArgumentException(sprintf('No service found for "workflow.%1$s" nor "state_machine.%1$s".', $serviceId)); + } + + if ('puml' === $input->getOption('dump-format')) { + $transitionType = 'workflow' === $type ? PlantUmlDumper::WORKFLOW_TRANSITION : PlantUmlDumper::STATEMACHINE_TRANSITION; + $dumper = new PlantUmlDumper($transitionType); + } elseif ('workflow' === $type) { + $dumper = new GraphvizDumper(); + } else { + $dumper = new StateMachineGraphvizDumper(); + } + + $marking = new Marking(); + + foreach ($input->getArgument('marking') as $place) { + $marking->mark($place); + } + + $options = [ + 'name' => $serviceId, + 'nofooter' => true, + 'graph' => [ + 'label' => $input->getOption('label'), + ], + ]; + $output->writeln($dumper->dump($workflow->getDefinition(), $marking, $options)); + + return 0; + } +} diff --git a/vendor/symfony/framework-bundle/Command/XliffLintCommand.php b/vendor/symfony/framework-bundle/Command/XliffLintCommand.php new file mode 100644 index 0000000..0b5bb06 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/XliffLintCommand.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Translation\Command\XliffLintCommand as BaseLintCommand; + +/** + * Validates XLIFF files syntax and outputs encountered errors. + * + * @author Grégoire Pineau + * @author Robin Chalas + * @author Javier Eguiluz + * + * @final + */ +class XliffLintCommand extends BaseLintCommand +{ + protected static $defaultName = 'lint:xliff'; + + public function __construct() + { + $directoryIteratorProvider = function ($directory, $default) { + if (!is_dir($directory)) { + $directory = $this->getApplication()->getKernel()->locateResource($directory); + } + + return $default($directory); + }; + + $isReadableProvider = function ($fileOrDirectory, $default) { + return 0 === strpos($fileOrDirectory, '@') || $default($fileOrDirectory); + }; + + parent::__construct(null, $directoryIteratorProvider, $isReadableProvider); + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + parent::configure(); + + $this->setHelp($this->getHelp().<<<'EOF' + +Or find all files in a bundle: + + php %command.full_name% @AcmeDemoBundle + +EOF + ); + } +} diff --git a/vendor/symfony/framework-bundle/Command/YamlLintCommand.php b/vendor/symfony/framework-bundle/Command/YamlLintCommand.php new file mode 100644 index 0000000..1163ff1 --- /dev/null +++ b/vendor/symfony/framework-bundle/Command/YamlLintCommand.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Yaml\Command\LintCommand as BaseLintCommand; + +/** + * Validates YAML files syntax and outputs encountered errors. + * + * @author Grégoire Pineau + * @author Robin Chalas + * + * @final + */ +class YamlLintCommand extends BaseLintCommand +{ + protected static $defaultName = 'lint:yaml'; + + public function __construct() + { + $directoryIteratorProvider = function ($directory, $default) { + if (!is_dir($directory)) { + $directory = $this->getApplication()->getKernel()->locateResource($directory); + } + + return $default($directory); + }; + + $isReadableProvider = function ($fileOrDirectory, $default) { + return 0 === strpos($fileOrDirectory, '@') || $default($fileOrDirectory); + }; + + parent::__construct(null, $directoryIteratorProvider, $isReadableProvider); + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + parent::configure(); + + $this->setHelp($this->getHelp().<<<'EOF' + +Or find all files in a bundle: + + php %command.full_name% @AcmeDemoBundle + +EOF + ); + } +} diff --git a/vendor/symfony/framework-bundle/Console/Application.php b/vendor/symfony/framework-bundle/Console/Application.php new file mode 100644 index 0000000..dddde43 --- /dev/null +++ b/vendor/symfony/framework-bundle/Console/Application.php @@ -0,0 +1,221 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Console; + +use Symfony\Component\Console\Application as BaseApplication; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Command\ListCommand; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Debug\Exception\FatalThrowableError; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\HttpKernel\KernelInterface; + +/** + * @author Fabien Potencier + */ +class Application extends BaseApplication +{ + private $kernel; + private $commandsRegistered = false; + private $registrationErrors = []; + + public function __construct(KernelInterface $kernel) + { + $this->kernel = $kernel; + + parent::__construct('Symfony', Kernel::VERSION); + + $inputDefinition = $this->getDefinition(); + $inputDefinition->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'The Environment name.', $kernel->getEnvironment())); + $inputDefinition->addOption(new InputOption('--no-debug', null, InputOption::VALUE_NONE, 'Switches off debug mode.')); + } + + /** + * Gets the Kernel associated with this Console. + * + * @return KernelInterface A KernelInterface instance + */ + public function getKernel() + { + return $this->kernel; + } + + /** + * {@inheritdoc} + */ + public function reset() + { + if ($this->kernel->getContainer()->has('services_resetter')) { + $this->kernel->getContainer()->get('services_resetter')->reset(); + } + } + + /** + * Runs the current application. + * + * @return int 0 if everything went fine, or an error code + */ + public function doRun(InputInterface $input, OutputInterface $output) + { + $this->registerCommands(); + + if ($this->registrationErrors) { + $this->renderRegistrationErrors($input, $output); + } + + $this->setDispatcher($this->kernel->getContainer()->get('event_dispatcher')); + + return parent::doRun($input, $output); + } + + /** + * {@inheritdoc} + */ + protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) + { + if (!$command instanceof ListCommand) { + if ($this->registrationErrors) { + $this->renderRegistrationErrors($input, $output); + $this->registrationErrors = []; + } + + return parent::doRunCommand($command, $input, $output); + } + + $returnCode = parent::doRunCommand($command, $input, $output); + + if ($this->registrationErrors) { + $this->renderRegistrationErrors($input, $output); + $this->registrationErrors = []; + } + + return $returnCode; + } + + /** + * {@inheritdoc} + */ + public function find($name) + { + $this->registerCommands(); + + return parent::find($name); + } + + /** + * {@inheritdoc} + */ + public function get($name) + { + $this->registerCommands(); + + $command = parent::get($name); + + if ($command instanceof ContainerAwareInterface) { + $command->setContainer($this->kernel->getContainer()); + } + + return $command; + } + + /** + * {@inheritdoc} + */ + public function all($namespace = null) + { + $this->registerCommands(); + + return parent::all($namespace); + } + + /** + * {@inheritdoc} + */ + public function getLongVersion() + { + return parent::getLongVersion().sprintf(' (env: %s, debug: %s)', $this->kernel->getEnvironment(), $this->kernel->isDebug() ? 'true' : 'false'); + } + + public function add(Command $command) + { + $this->registerCommands(); + + return parent::add($command); + } + + protected function registerCommands() + { + if ($this->commandsRegistered) { + return; + } + + $this->commandsRegistered = true; + + $this->kernel->boot(); + + $container = $this->kernel->getContainer(); + + foreach ($this->kernel->getBundles() as $bundle) { + if ($bundle instanceof Bundle) { + try { + $bundle->registerCommands($this); + } catch (\Throwable $e) { + $this->registrationErrors[] = $e; + } + } + } + + if ($container->has('console.command_loader')) { + $this->setCommandLoader($container->get('console.command_loader')); + } + + if ($container->hasParameter('console.command.ids')) { + $lazyCommandIds = $container->hasParameter('console.lazy_command.ids') ? $container->getParameter('console.lazy_command.ids') : []; + foreach ($container->getParameter('console.command.ids') as $id) { + if (!isset($lazyCommandIds[$id])) { + try { + $this->add($container->get($id)); + } catch (\Throwable $e) { + $this->registrationErrors[] = $e; + } + } + } + } + } + + private function renderRegistrationErrors(InputInterface $input, OutputInterface $output) + { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + (new SymfonyStyle($input, $output))->warning('Some commands could not be registered:'); + + foreach ($this->registrationErrors as $error) { + if (method_exists($this, 'doRenderThrowable')) { + $this->doRenderThrowable($error, $output); + } else { + if (!$error instanceof \Exception) { + $error = new FatalThrowableError($error); + } + + $this->doRenderException($error, $output); + } + } + } +} diff --git a/vendor/symfony/framework-bundle/Console/Descriptor/Descriptor.php b/vendor/symfony/framework-bundle/Console/Descriptor/Descriptor.php new file mode 100644 index 0000000..cbb01dc --- /dev/null +++ b/vendor/symfony/framework-bundle/Console/Descriptor/Descriptor.php @@ -0,0 +1,384 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; + +use Symfony\Component\Config\Resource\ClassExistenceResource; +use Symfony\Component\Console\Descriptor\DescriptorInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * @author Jean-François Simon + * + * @internal + */ +abstract class Descriptor implements DescriptorInterface +{ + /** + * @var OutputInterface + */ + protected $output; + + /** + * {@inheritdoc} + */ + public function describe(OutputInterface $output, $object, array $options = []) + { + $this->output = $output; + + switch (true) { + case $object instanceof RouteCollection: + $this->describeRouteCollection($object, $options); + break; + case $object instanceof Route: + $this->describeRoute($object, $options); + break; + case $object instanceof ParameterBag: + $this->describeContainerParameters($object, $options); + break; + case $object instanceof ContainerBuilder && !empty($options['env-vars']): + $this->describeContainerEnvVars($this->getContainerEnvVars($object), $options); + break; + case $object instanceof ContainerBuilder && isset($options['group_by']) && 'tags' === $options['group_by']: + $this->describeContainerTags($object, $options); + break; + case $object instanceof ContainerBuilder && isset($options['id']): + $this->describeContainerService($this->resolveServiceDefinition($object, $options['id']), $options, $object); + break; + case $object instanceof ContainerBuilder && isset($options['parameter']): + $this->describeContainerParameter($object->resolveEnvPlaceholders($object->getParameter($options['parameter'])), $options); + break; + case $object instanceof ContainerBuilder: + $this->describeContainerServices($object, $options); + break; + case $object instanceof Definition: + $this->describeContainerDefinition($object, $options); + break; + case $object instanceof Alias: + $this->describeContainerAlias($object, $options); + break; + case $object instanceof EventDispatcherInterface: + $this->describeEventDispatcherListeners($object, $options); + break; + case \is_callable($object): + $this->describeCallable($object, $options); + break; + default: + throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', \get_class($object))); + } + } + + protected function getOutput(): OutputInterface + { + return $this->output; + } + + protected function write(string $content, bool $decorated = false) + { + $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); + } + + /** + * Describes an InputArgument instance. + */ + abstract protected function describeRouteCollection(RouteCollection $routes, array $options = []); + + /** + * Describes an InputOption instance. + */ + abstract protected function describeRoute(Route $route, array $options = []); + + /** + * Describes container parameters. + */ + abstract protected function describeContainerParameters(ParameterBag $parameters, array $options = []); + + /** + * Describes container tags. + */ + abstract protected function describeContainerTags(ContainerBuilder $builder, array $options = []); + + /** + * Describes a container service by its name. + * + * Common options are: + * * name: name of described service + * + * @param Definition|Alias|object $service + */ + abstract protected function describeContainerService($service, array $options = [], ContainerBuilder $builder = null); + + /** + * Describes container services. + * + * Common options are: + * * tag: filters described services by given tag + */ + abstract protected function describeContainerServices(ContainerBuilder $builder, array $options = []); + + /** + * Describes a service definition. + */ + abstract protected function describeContainerDefinition(Definition $definition, array $options = []); + + /** + * Describes a service alias. + */ + abstract protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null); + + /** + * Describes a container parameter. + */ + abstract protected function describeContainerParameter($parameter, array $options = []); + + /** + * Describes container environment variables. + */ + abstract protected function describeContainerEnvVars(array $envs, array $options = []); + + /** + * Describes event dispatcher listeners. + * + * Common options are: + * * name: name of listened event + */ + abstract protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []); + + /** + * Describes a callable. + * + * @param mixed $callable + */ + abstract protected function describeCallable($callable, array $options = []); + + /** + * Formats a value as string. + * + * @param mixed $value + */ + protected function formatValue($value): string + { + if (\is_object($value)) { + return sprintf('object(%s)', \get_class($value)); + } + + if (\is_string($value)) { + return $value; + } + + return preg_replace("/\n\s*/s", '', var_export($value, true)); + } + + /** + * Formats a parameter. + * + * @param mixed $value + */ + protected function formatParameter($value): string + { + if (\is_bool($value) || \is_array($value) || (null === $value)) { + $jsonString = json_encode($value); + + if (preg_match('/^(.{60})./us', $jsonString, $matches)) { + return $matches[1].'...'; + } + + return $jsonString; + } + + return (string) $value; + } + + /** + * @return mixed + */ + protected function resolveServiceDefinition(ContainerBuilder $builder, string $serviceId) + { + if ($builder->hasDefinition($serviceId)) { + return $builder->getDefinition($serviceId); + } + + // Some service IDs don't have a Definition, they're aliases + if ($builder->hasAlias($serviceId)) { + return $builder->getAlias($serviceId); + } + + if ('service_container' === $serviceId) { + return (new Definition(ContainerInterface::class))->setPublic(true)->setSynthetic(true); + } + + // the service has been injected in some special way, just return the service + return $builder->get($serviceId); + } + + protected function findDefinitionsByTag(ContainerBuilder $builder, bool $showHidden): array + { + $definitions = []; + $tags = $builder->findTags(); + asort($tags); + + foreach ($tags as $tag) { + foreach ($builder->findTaggedServiceIds($tag) as $serviceId => $attributes) { + $definition = $this->resolveServiceDefinition($builder, $serviceId); + + if ($showHidden xor '.' === ($serviceId[0] ?? null)) { + continue; + } + + if (!isset($definitions[$tag])) { + $definitions[$tag] = []; + } + + $definitions[$tag][$serviceId] = $definition; + } + } + + return $definitions; + } + + protected function sortParameters(ParameterBag $parameters) + { + $parameters = $parameters->all(); + ksort($parameters); + + return $parameters; + } + + protected function sortServiceIds(array $serviceIds) + { + asort($serviceIds); + + return $serviceIds; + } + + protected function sortTaggedServicesByPriority(array $services): array + { + $maxPriority = []; + foreach ($services as $service => $tags) { + $maxPriority[$service] = 0; + foreach ($tags as $tag) { + $currentPriority = $tag['priority'] ?? 0; + if ($maxPriority[$service] < $currentPriority) { + $maxPriority[$service] = $currentPriority; + } + } + } + uasort($maxPriority, function ($a, $b) { + return $b <=> $a; + }); + + return array_keys($maxPriority); + } + + protected function sortTagsByPriority(array $tags): array + { + $sortedTags = []; + foreach ($tags as $tagName => $tag) { + $sortedTags[$tagName] = $this->sortByPriority($tag); + } + + return $sortedTags; + } + + protected function sortByPriority(array $tag): array + { + usort($tag, function ($a, $b) { + return ($b['priority'] ?? 0) <=> ($a['priority'] ?? 0); + }); + + return $tag; + } + + /** + * Gets class description from a docblock. + */ + public static function getClassDescription(string $class, string &$resolvedClass = null): string + { + $resolvedClass = $class; + try { + $resource = new ClassExistenceResource($class, false); + + // isFresh() will explode ONLY if a parent class/trait does not exist + $resource->isFresh(0); + + $r = new \ReflectionClass($class); + $resolvedClass = $r->name; + + if ($docComment = $r->getDocComment()) { + $docComment = preg_split('#\n\s*\*\s*[\n@]#', substr($docComment, 3, -2), 2)[0]; + + return trim(preg_replace('#\s*\n\s*\*\s*#', ' ', $docComment)); + } + } catch (\ReflectionException $e) { + } + + return ''; + } + + private function getContainerEnvVars(ContainerBuilder $container): array + { + if (!$container->hasParameter('debug.container.dump')) { + return []; + } + + if (!is_file($container->getParameter('debug.container.dump'))) { + return []; + } + + $file = file_get_contents($container->getParameter('debug.container.dump')); + preg_match_all('{%env\(((?:\w++:)*+\w++)\)%}', $file, $envVars); + $envVars = array_unique($envVars[1]); + + $bag = $container->getParameterBag(); + $getDefaultParameter = function (string $name) { + return parent::get($name); + }; + $getDefaultParameter = $getDefaultParameter->bindTo($bag, \get_class($bag)); + + $getEnvReflection = new \ReflectionMethod($container, 'getEnv'); + $getEnvReflection->setAccessible(true); + + $envs = []; + + foreach ($envVars as $env) { + $processor = 'string'; + if (false !== $i = strrpos($name = $env, ':')) { + $name = substr($env, $i + 1); + $processor = substr($env, 0, $i); + } + $defaultValue = ($hasDefault = $container->hasParameter("env($name)")) ? $getDefaultParameter("env($name)") : null; + if (false === ($runtimeValue = $_ENV[$name] ?? $_SERVER[$name] ?? getenv($name))) { + $runtimeValue = null; + } + $processedValue = ($hasRuntime = null !== $runtimeValue) || $hasDefault ? $getEnvReflection->invoke($container, $env) : null; + $envs["$name$processor"] = [ + 'name' => $name, + 'processor' => $processor, + 'default_available' => $hasDefault, + 'default_value' => $defaultValue, + 'runtime_available' => $hasRuntime, + 'runtime_value' => $runtimeValue, + 'processed_value' => $processedValue, + ]; + } + ksort($envs); + + return array_values($envs); + } +} diff --git a/vendor/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php b/vendor/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php new file mode 100644 index 0000000..9d1e97d --- /dev/null +++ b/vendor/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php @@ -0,0 +1,420 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; + +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * @author Jean-François Simon + * + * @internal + */ +class JsonDescriptor extends Descriptor +{ + /** + * {@inheritdoc} + */ + protected function describeRouteCollection(RouteCollection $routes, array $options = []) + { + $data = []; + foreach ($routes->all() as $name => $route) { + $data[$name] = $this->getRouteData($route); + } + + $this->writeData($data, $options); + } + + /** + * {@inheritdoc} + */ + protected function describeRoute(Route $route, array $options = []) + { + $this->writeData($this->getRouteData($route), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerParameters(ParameterBag $parameters, array $options = []) + { + $this->writeData($this->sortParameters($parameters), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerTags(ContainerBuilder $builder, array $options = []) + { + $showHidden = isset($options['show_hidden']) && $options['show_hidden']; + $data = []; + + foreach ($this->findDefinitionsByTag($builder, $showHidden) as $tag => $definitions) { + $data[$tag] = []; + foreach ($definitions as $definition) { + $data[$tag][] = $this->getContainerDefinitionData($definition, true); + } + } + + $this->writeData($data, $options); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerService($service, array $options = [], ContainerBuilder $builder = null) + { + if (!isset($options['id'])) { + throw new \InvalidArgumentException('An "id" option must be provided.'); + } + + if ($service instanceof Alias) { + $this->describeContainerAlias($service, $options, $builder); + } elseif ($service instanceof Definition) { + $this->writeData($this->getContainerDefinitionData($service, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments']), $options); + } else { + $this->writeData(\get_class($service), $options); + } + } + + /** + * {@inheritdoc} + */ + protected function describeContainerServices(ContainerBuilder $builder, array $options = []) + { + $serviceIds = isset($options['tag']) && $options['tag'] + ? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($options['tag'])) + : $this->sortServiceIds($builder->getServiceIds()); + $showHidden = isset($options['show_hidden']) && $options['show_hidden']; + $omitTags = isset($options['omit_tags']) && $options['omit_tags']; + $showArguments = isset($options['show_arguments']) && $options['show_arguments']; + $data = ['definitions' => [], 'aliases' => [], 'services' => []]; + + if (isset($options['filter'])) { + $serviceIds = array_filter($serviceIds, $options['filter']); + } + + foreach ($serviceIds as $serviceId) { + $service = $this->resolveServiceDefinition($builder, $serviceId); + + if ($showHidden xor '.' === ($serviceId[0] ?? null)) { + continue; + } + + if ($service instanceof Alias) { + $data['aliases'][$serviceId] = $this->getContainerAliasData($service); + } elseif ($service instanceof Definition) { + $data['definitions'][$serviceId] = $this->getContainerDefinitionData($service, $omitTags, $showArguments); + } else { + $data['services'][$serviceId] = \get_class($service); + } + } + + $this->writeData($data, $options); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerDefinition(Definition $definition, array $options = []) + { + $this->writeData($this->getContainerDefinitionData($definition, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments']), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null) + { + if (!$builder) { + $this->writeData($this->getContainerAliasData($alias), $options); + + return; + } + + $this->writeData( + [$this->getContainerAliasData($alias), $this->getContainerDefinitionData($builder->getDefinition((string) $alias), isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'])], + array_merge($options, ['id' => (string) $alias]) + ); + } + + /** + * {@inheritdoc} + */ + protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) + { + $this->writeData($this->getEventDispatcherListenersData($eventDispatcher, \array_key_exists('event', $options) ? $options['event'] : null), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeCallable($callable, array $options = []) + { + $this->writeData($this->getCallableData($callable), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerParameter($parameter, array $options = []) + { + $key = isset($options['parameter']) ? $options['parameter'] : ''; + + $this->writeData([$key => $parameter], $options); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerEnvVars(array $envs, array $options = []) + { + throw new LogicException('Using the JSON format to debug environment variables is not supported.'); + } + + /** + * Writes data as json. + */ + private function writeData(array $data, array $options) + { + $flags = isset($options['json_encoding']) ? $options['json_encoding'] : 0; + + $this->write(json_encode($data, $flags | JSON_PRETTY_PRINT)."\n"); + } + + protected function getRouteData(Route $route): array + { + $data = [ + 'path' => $route->getPath(), + 'pathRegex' => $route->compile()->getRegex(), + 'host' => '' !== $route->getHost() ? $route->getHost() : 'ANY', + 'hostRegex' => '' !== $route->getHost() ? $route->compile()->getHostRegex() : '', + 'scheme' => $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY', + 'method' => $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY', + 'class' => \get_class($route), + 'defaults' => $route->getDefaults(), + 'requirements' => $route->getRequirements() ?: 'NO CUSTOM', + 'options' => $route->getOptions(), + ]; + + if ('' !== $route->getCondition()) { + $data['condition'] = $route->getCondition(); + } + + return $data; + } + + private function getContainerDefinitionData(Definition $definition, bool $omitTags = false, bool $showArguments = false): array + { + $data = [ + 'class' => (string) $definition->getClass(), + 'public' => $definition->isPublic() && !$definition->isPrivate(), + 'synthetic' => $definition->isSynthetic(), + 'lazy' => $definition->isLazy(), + 'shared' => $definition->isShared(), + 'abstract' => $definition->isAbstract(), + 'autowire' => $definition->isAutowired(), + 'autoconfigure' => $definition->isAutoconfigured(), + ]; + + if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) { + $data['description'] = $classDescription; + } + + if ($showArguments) { + $data['arguments'] = $this->describeValue($definition->getArguments(), $omitTags, $showArguments); + } + + $data['file'] = $definition->getFile(); + + if ($factory = $definition->getFactory()) { + if (\is_array($factory)) { + if ($factory[0] instanceof Reference) { + $data['factory_service'] = (string) $factory[0]; + } elseif ($factory[0] instanceof Definition) { + throw new \InvalidArgumentException('Factory is not describable.'); + } else { + $data['factory_class'] = $factory[0]; + } + $data['factory_method'] = $factory[1]; + } else { + $data['factory_function'] = $factory; + } + } + + $calls = $definition->getMethodCalls(); + if (\count($calls) > 0) { + $data['calls'] = []; + foreach ($calls as $callData) { + $data['calls'][] = $callData[0]; + } + } + + if (!$omitTags) { + $data['tags'] = []; + foreach ($this->sortTagsByPriority($definition->getTags()) as $tagName => $tagData) { + foreach ($tagData as $parameters) { + $data['tags'][] = ['name' => $tagName, 'parameters' => $parameters]; + } + } + } + + return $data; + } + + private function getContainerAliasData(Alias $alias): array + { + return [ + 'service' => (string) $alias, + 'public' => $alias->isPublic() && !$alias->isPrivate(), + ]; + } + + private function getEventDispatcherListenersData(EventDispatcherInterface $eventDispatcher, string $event = null): array + { + $data = []; + + $registeredListeners = $eventDispatcher->getListeners($event); + if (null !== $event) { + foreach ($registeredListeners as $listener) { + $l = $this->getCallableData($listener); + $l['priority'] = $eventDispatcher->getListenerPriority($event, $listener); + $data[] = $l; + } + } else { + ksort($registeredListeners); + + foreach ($registeredListeners as $eventListened => $eventListeners) { + foreach ($eventListeners as $eventListener) { + $l = $this->getCallableData($eventListener); + $l['priority'] = $eventDispatcher->getListenerPriority($eventListened, $eventListener); + $data[$eventListened][] = $l; + } + } + } + + return $data; + } + + private function getCallableData($callable): array + { + $data = []; + + if (\is_array($callable)) { + $data['type'] = 'function'; + + if (\is_object($callable[0])) { + $data['name'] = $callable[1]; + $data['class'] = \get_class($callable[0]); + } else { + if (0 !== strpos($callable[1], 'parent::')) { + $data['name'] = $callable[1]; + $data['class'] = $callable[0]; + $data['static'] = true; + } else { + $data['name'] = substr($callable[1], 8); + $data['class'] = $callable[0]; + $data['static'] = true; + $data['parent'] = true; + } + } + + return $data; + } + + if (\is_string($callable)) { + $data['type'] = 'function'; + + if (false === strpos($callable, '::')) { + $data['name'] = $callable; + } else { + $callableParts = explode('::', $callable); + + $data['name'] = $callableParts[1]; + $data['class'] = $callableParts[0]; + $data['static'] = true; + } + + return $data; + } + + if ($callable instanceof \Closure) { + $data['type'] = 'closure'; + + $r = new \ReflectionFunction($callable); + if (false !== strpos($r->name, '{closure}')) { + return $data; + } + $data['name'] = $r->name; + + if ($class = $r->getClosureScopeClass()) { + $data['class'] = $class->name; + if (!$r->getClosureThis()) { + $data['static'] = true; + } + } + + return $data; + } + + if (method_exists($callable, '__invoke')) { + $data['type'] = 'object'; + $data['name'] = \get_class($callable); + + return $data; + } + + throw new \InvalidArgumentException('Callable is not describable.'); + } + + private function describeValue($value, bool $omitTags, bool $showArguments) + { + if (\is_array($value)) { + $data = []; + foreach ($value as $k => $v) { + $data[$k] = $this->describeValue($v, $omitTags, $showArguments); + } + + return $data; + } + + if ($value instanceof ServiceClosureArgument) { + $value = $value->getValues()[0]; + } + + if ($value instanceof Reference) { + return [ + 'type' => 'service', + 'id' => (string) $value, + ]; + } + + if ($value instanceof ArgumentInterface) { + return $this->describeValue($value->getValues(), $omitTags, $showArguments); + } + + if ($value instanceof Definition) { + return $this->getContainerDefinitionData($value, $omitTags, $showArguments); + } + + return $value; + } +} diff --git a/vendor/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php b/vendor/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php new file mode 100644 index 0000000..ab4f056 --- /dev/null +++ b/vendor/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php @@ -0,0 +1,413 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; + +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * @author Jean-François Simon + * + * @internal + */ +class MarkdownDescriptor extends Descriptor +{ + /** + * {@inheritdoc} + */ + protected function describeRouteCollection(RouteCollection $routes, array $options = []) + { + $first = true; + foreach ($routes->all() as $name => $route) { + if ($first) { + $first = false; + } else { + $this->write("\n\n"); + } + $this->describeRoute($route, ['name' => $name]); + } + $this->write("\n"); + } + + /** + * {@inheritdoc} + */ + protected function describeRoute(Route $route, array $options = []) + { + $output = '- Path: '.$route->getPath() + ."\n".'- Path Regex: '.$route->compile()->getRegex() + ."\n".'- Host: '.('' !== $route->getHost() ? $route->getHost() : 'ANY') + ."\n".'- Host Regex: '.('' !== $route->getHost() ? $route->compile()->getHostRegex() : '') + ."\n".'- Scheme: '.($route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY') + ."\n".'- Method: '.($route->getMethods() ? implode('|', $route->getMethods()) : 'ANY') + ."\n".'- Class: '.\get_class($route) + ."\n".'- Defaults: '.$this->formatRouterConfig($route->getDefaults()) + ."\n".'- Requirements: '.($route->getRequirements() ? $this->formatRouterConfig($route->getRequirements()) : 'NO CUSTOM') + ."\n".'- Options: '.$this->formatRouterConfig($route->getOptions()); + + if ('' !== $route->getCondition()) { + $output .= "\n".'- Condition: '.$route->getCondition(); + } + + $this->write(isset($options['name']) + ? $options['name']."\n".str_repeat('-', \strlen($options['name']))."\n\n".$output + : $output); + $this->write("\n"); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerParameters(ParameterBag $parameters, array $options = []) + { + $this->write("Container parameters\n====================\n"); + foreach ($this->sortParameters($parameters) as $key => $value) { + $this->write(sprintf("\n- `%s`: `%s`", $key, $this->formatParameter($value))); + } + } + + /** + * {@inheritdoc} + */ + protected function describeContainerTags(ContainerBuilder $builder, array $options = []) + { + $showHidden = isset($options['show_hidden']) && $options['show_hidden']; + $this->write("Container tags\n=============="); + + foreach ($this->findDefinitionsByTag($builder, $showHidden) as $tag => $definitions) { + $this->write("\n\n".$tag."\n".str_repeat('-', \strlen($tag))); + foreach ($definitions as $serviceId => $definition) { + $this->write("\n\n"); + $this->describeContainerDefinition($definition, ['omit_tags' => true, 'id' => $serviceId]); + } + } + } + + /** + * {@inheritdoc} + */ + protected function describeContainerService($service, array $options = [], ContainerBuilder $builder = null) + { + if (!isset($options['id'])) { + throw new \InvalidArgumentException('An "id" option must be provided.'); + } + + $childOptions = array_merge($options, ['id' => $options['id'], 'as_array' => true]); + + if ($service instanceof Alias) { + $this->describeContainerAlias($service, $childOptions, $builder); + } elseif ($service instanceof Definition) { + $this->describeContainerDefinition($service, $childOptions); + } else { + $this->write(sprintf('**`%s`:** `%s`', $options['id'], \get_class($service))); + } + } + + /** + * {@inheritdoc} + */ + protected function describeContainerServices(ContainerBuilder $builder, array $options = []) + { + $showHidden = isset($options['show_hidden']) && $options['show_hidden']; + + $title = $showHidden ? 'Hidden services' : 'Services'; + if (isset($options['tag'])) { + $title .= ' with tag `'.$options['tag'].'`'; + } + $this->write($title."\n".str_repeat('=', \strlen($title))); + + $serviceIds = isset($options['tag']) && $options['tag'] + ? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($options['tag'])) + : $this->sortServiceIds($builder->getServiceIds()); + $showArguments = isset($options['show_arguments']) && $options['show_arguments']; + $services = ['definitions' => [], 'aliases' => [], 'services' => []]; + + if (isset($options['filter'])) { + $serviceIds = array_filter($serviceIds, $options['filter']); + } + + foreach ($serviceIds as $serviceId) { + $service = $this->resolveServiceDefinition($builder, $serviceId); + + if ($showHidden xor '.' === ($serviceId[0] ?? null)) { + continue; + } + + if ($service instanceof Alias) { + $services['aliases'][$serviceId] = $service; + } elseif ($service instanceof Definition) { + $services['definitions'][$serviceId] = $service; + } else { + $services['services'][$serviceId] = $service; + } + } + + if (!empty($services['definitions'])) { + $this->write("\n\nDefinitions\n-----------\n"); + foreach ($services['definitions'] as $id => $service) { + $this->write("\n"); + $this->describeContainerDefinition($service, ['id' => $id, 'show_arguments' => $showArguments]); + } + } + + if (!empty($services['aliases'])) { + $this->write("\n\nAliases\n-------\n"); + foreach ($services['aliases'] as $id => $service) { + $this->write("\n"); + $this->describeContainerAlias($service, ['id' => $id]); + } + } + + if (!empty($services['services'])) { + $this->write("\n\nServices\n--------\n"); + foreach ($services['services'] as $id => $service) { + $this->write("\n"); + $this->write(sprintf('- `%s`: `%s`', $id, \get_class($service))); + } + } + } + + /** + * {@inheritdoc} + */ + protected function describeContainerDefinition(Definition $definition, array $options = []) + { + $output = ''; + + if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) { + $output .= '- Description: `'.$classDescription.'`'."\n"; + } + + $output .= '- Class: `'.$definition->getClass().'`' + ."\n".'- Public: '.($definition->isPublic() && !$definition->isPrivate() ? 'yes' : 'no') + ."\n".'- Synthetic: '.($definition->isSynthetic() ? 'yes' : 'no') + ."\n".'- Lazy: '.($definition->isLazy() ? 'yes' : 'no') + ."\n".'- Shared: '.($definition->isShared() ? 'yes' : 'no') + ."\n".'- Abstract: '.($definition->isAbstract() ? 'yes' : 'no') + ."\n".'- Autowired: '.($definition->isAutowired() ? 'yes' : 'no') + ."\n".'- Autoconfigured: '.($definition->isAutoconfigured() ? 'yes' : 'no') + ; + + if (isset($options['show_arguments']) && $options['show_arguments']) { + $output .= "\n".'- Arguments: '.($definition->getArguments() ? 'yes' : 'no'); + } + + if ($definition->getFile()) { + $output .= "\n".'- File: `'.$definition->getFile().'`'; + } + + if ($factory = $definition->getFactory()) { + if (\is_array($factory)) { + if ($factory[0] instanceof Reference) { + $output .= "\n".'- Factory Service: `'.$factory[0].'`'; + } elseif ($factory[0] instanceof Definition) { + throw new \InvalidArgumentException('Factory is not describable.'); + } else { + $output .= "\n".'- Factory Class: `'.$factory[0].'`'; + } + $output .= "\n".'- Factory Method: `'.$factory[1].'`'; + } else { + $output .= "\n".'- Factory Function: `'.$factory.'`'; + } + } + + $calls = $definition->getMethodCalls(); + foreach ($calls as $callData) { + $output .= "\n".'- Call: `'.$callData[0].'`'; + } + + if (!(isset($options['omit_tags']) && $options['omit_tags'])) { + foreach ($this->sortTagsByPriority($definition->getTags()) as $tagName => $tagData) { + foreach ($tagData as $parameters) { + $output .= "\n".'- Tag: `'.$tagName.'`'; + foreach ($parameters as $name => $value) { + $output .= "\n".' - '.ucfirst($name).': '.$value; + } + } + } + } + + $this->write(isset($options['id']) ? sprintf("### %s\n\n%s\n", $options['id'], $output) : $output); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null) + { + $output = '- Service: `'.$alias.'`' + ."\n".'- Public: '.($alias->isPublic() && !$alias->isPrivate() ? 'yes' : 'no'); + + if (!isset($options['id'])) { + $this->write($output); + + return; + } + + $this->write(sprintf("### %s\n\n%s\n", $options['id'], $output)); + + if (!$builder) { + return; + } + + $this->write("\n"); + $this->describeContainerDefinition($builder->getDefinition((string) $alias), array_merge($options, ['id' => (string) $alias])); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerParameter($parameter, array $options = []) + { + $this->write(isset($options['parameter']) ? sprintf("%s\n%s\n\n%s", $options['parameter'], str_repeat('=', \strlen($options['parameter'])), $this->formatParameter($parameter)) : $parameter); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerEnvVars(array $envs, array $options = []) + { + throw new LogicException('Using the markdown format to debug environment variables is not supported.'); + } + + /** + * {@inheritdoc} + */ + protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) + { + $event = \array_key_exists('event', $options) ? $options['event'] : null; + + $title = 'Registered listeners'; + if (null !== $event) { + $title .= sprintf(' for event `%s` ordered by descending priority', $event); + } + + $this->write(sprintf('# %s', $title)."\n"); + + $registeredListeners = $eventDispatcher->getListeners($event); + if (null !== $event) { + foreach ($registeredListeners as $order => $listener) { + $this->write("\n".sprintf('## Listener %d', $order + 1)."\n"); + $this->describeCallable($listener); + $this->write(sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($event, $listener))."\n"); + } + } else { + ksort($registeredListeners); + + foreach ($registeredListeners as $eventListened => $eventListeners) { + $this->write("\n".sprintf('## %s', $eventListened)."\n"); + + foreach ($eventListeners as $order => $eventListener) { + $this->write("\n".sprintf('### Listener %d', $order + 1)."\n"); + $this->describeCallable($eventListener); + $this->write(sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($eventListened, $eventListener))."\n"); + } + } + } + } + + /** + * {@inheritdoc} + */ + protected function describeCallable($callable, array $options = []) + { + $string = ''; + + if (\is_array($callable)) { + $string .= "\n- Type: `function`"; + + if (\is_object($callable[0])) { + $string .= "\n".sprintf('- Name: `%s`', $callable[1]); + $string .= "\n".sprintf('- Class: `%s`', \get_class($callable[0])); + } else { + if (0 !== strpos($callable[1], 'parent::')) { + $string .= "\n".sprintf('- Name: `%s`', $callable[1]); + $string .= "\n".sprintf('- Class: `%s`', $callable[0]); + $string .= "\n- Static: yes"; + } else { + $string .= "\n".sprintf('- Name: `%s`', substr($callable[1], 8)); + $string .= "\n".sprintf('- Class: `%s`', $callable[0]); + $string .= "\n- Static: yes"; + $string .= "\n- Parent: yes"; + } + } + + return $this->write($string."\n"); + } + + if (\is_string($callable)) { + $string .= "\n- Type: `function`"; + + if (false === strpos($callable, '::')) { + $string .= "\n".sprintf('- Name: `%s`', $callable); + } else { + $callableParts = explode('::', $callable); + + $string .= "\n".sprintf('- Name: `%s`', $callableParts[1]); + $string .= "\n".sprintf('- Class: `%s`', $callableParts[0]); + $string .= "\n- Static: yes"; + } + + return $this->write($string."\n"); + } + + if ($callable instanceof \Closure) { + $string .= "\n- Type: `closure`"; + + $r = new \ReflectionFunction($callable); + if (false !== strpos($r->name, '{closure}')) { + return $this->write($string."\n"); + } + $string .= "\n".sprintf('- Name: `%s`', $r->name); + + if ($class = $r->getClosureScopeClass()) { + $string .= "\n".sprintf('- Class: `%s`', $class->name); + if (!$r->getClosureThis()) { + $string .= "\n- Static: yes"; + } + } + + return $this->write($string."\n"); + } + + if (method_exists($callable, '__invoke')) { + $string .= "\n- Type: `object`"; + $string .= "\n".sprintf('- Name: `%s`', \get_class($callable)); + + return $this->write($string."\n"); + } + + throw new \InvalidArgumentException('Callable is not describable.'); + } + + private function formatRouterConfig(array $array): string + { + if (!$array) { + return 'NONE'; + } + + $string = ''; + ksort($array); + foreach ($array as $name => $value) { + $string .= "\n".' - `'.$name.'`: '.$this->formatValue($value); + } + + return $string; + } +} diff --git a/vendor/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php b/vendor/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php new file mode 100644 index 0000000..37e2117 --- /dev/null +++ b/vendor/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php @@ -0,0 +1,608 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; + +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\Dumper; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * @author Jean-François Simon + * + * @internal + */ +class TextDescriptor extends Descriptor +{ + private $fileLinkFormatter; + + public function __construct(FileLinkFormatter $fileLinkFormatter = null) + { + $this->fileLinkFormatter = $fileLinkFormatter; + } + + /** + * {@inheritdoc} + */ + protected function describeRouteCollection(RouteCollection $routes, array $options = []) + { + $showControllers = isset($options['show_controllers']) && $options['show_controllers']; + + $tableHeaders = ['Name', 'Method', 'Scheme', 'Host', 'Path']; + if ($showControllers) { + $tableHeaders[] = 'Controller'; + } + + $tableRows = []; + foreach ($routes->all() as $name => $route) { + $controller = $route->getDefault('_controller'); + + $row = [ + $name, + $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY', + $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY', + '' !== $route->getHost() ? $route->getHost() : 'ANY', + $this->formatControllerLink($controller, $route->getPath()), + ]; + + if ($showControllers) { + $row[] = $controller ? $this->formatControllerLink($controller, $this->formatCallable($controller)) : ''; + } + + $tableRows[] = $row; + } + + if (isset($options['output'])) { + $options['output']->table($tableHeaders, $tableRows); + } else { + $table = new Table($this->getOutput()); + $table->setHeaders($tableHeaders)->setRows($tableRows); + $table->render(); + } + } + + /** + * {@inheritdoc} + */ + protected function describeRoute(Route $route, array $options = []) + { + $tableHeaders = ['Property', 'Value']; + $tableRows = [ + ['Route Name', isset($options['name']) ? $options['name'] : ''], + ['Path', $route->getPath()], + ['Path Regex', $route->compile()->getRegex()], + ['Host', ('' !== $route->getHost() ? $route->getHost() : 'ANY')], + ['Host Regex', ('' !== $route->getHost() ? $route->compile()->getHostRegex() : '')], + ['Scheme', ($route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY')], + ['Method', ($route->getMethods() ? implode('|', $route->getMethods()) : 'ANY')], + ['Requirements', ($route->getRequirements() ? $this->formatRouterConfig($route->getRequirements()) : 'NO CUSTOM')], + ['Class', \get_class($route)], + ['Defaults', $this->formatRouterConfig($route->getDefaults())], + ['Options', $this->formatRouterConfig($route->getOptions())], + ]; + + if ('' !== $route->getCondition()) { + $tableRows[] = ['Condition', $route->getCondition()]; + } + + $table = new Table($this->getOutput()); + $table->setHeaders($tableHeaders)->setRows($tableRows); + $table->render(); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerParameters(ParameterBag $parameters, array $options = []) + { + $tableHeaders = ['Parameter', 'Value']; + + $tableRows = []; + foreach ($this->sortParameters($parameters) as $parameter => $value) { + $tableRows[] = [$parameter, $this->formatParameter($value)]; + } + + $options['output']->title('Symfony Container Parameters'); + $options['output']->table($tableHeaders, $tableRows); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerTags(ContainerBuilder $builder, array $options = []) + { + $showHidden = isset($options['show_hidden']) && $options['show_hidden']; + + if ($showHidden) { + $options['output']->title('Symfony Container Hidden Tags'); + } else { + $options['output']->title('Symfony Container Tags'); + } + + foreach ($this->findDefinitionsByTag($builder, $showHidden) as $tag => $definitions) { + $options['output']->section(sprintf('"%s" tag', $tag)); + $options['output']->listing(array_keys($definitions)); + } + } + + /** + * {@inheritdoc} + */ + protected function describeContainerService($service, array $options = [], ContainerBuilder $builder = null) + { + if (!isset($options['id'])) { + throw new \InvalidArgumentException('An "id" option must be provided.'); + } + + if ($service instanceof Alias) { + $this->describeContainerAlias($service, $options, $builder); + } elseif ($service instanceof Definition) { + $this->describeContainerDefinition($service, $options); + } else { + $options['output']->title(sprintf('Information for Service "%s"', $options['id'])); + $options['output']->table( + ['Service ID', 'Class'], + [ + [isset($options['id']) ? $options['id'] : '-', \get_class($service)], + ] + ); + } + } + + /** + * {@inheritdoc} + */ + protected function describeContainerServices(ContainerBuilder $builder, array $options = []) + { + $showHidden = isset($options['show_hidden']) && $options['show_hidden']; + $showTag = isset($options['tag']) ? $options['tag'] : null; + + if ($showHidden) { + $title = 'Symfony Container Hidden Services'; + } else { + $title = 'Symfony Container Services'; + } + + if ($showTag) { + $title .= sprintf(' Tagged with "%s" Tag', $options['tag']); + } + + $options['output']->title($title); + + $serviceIds = isset($options['tag']) && $options['tag'] + ? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($options['tag'])) + : $this->sortServiceIds($builder->getServiceIds()); + $maxTags = []; + + if (isset($options['filter'])) { + $serviceIds = array_filter($serviceIds, $options['filter']); + } + + foreach ($serviceIds as $key => $serviceId) { + $definition = $this->resolveServiceDefinition($builder, $serviceId); + + // filter out hidden services unless shown explicitly + if ($showHidden xor '.' === ($serviceId[0] ?? null)) { + unset($serviceIds[$key]); + continue; + } + + if ($definition instanceof Definition) { + if ($showTag) { + $tags = $definition->getTag($showTag); + foreach ($tags as $tag) { + foreach ($tag as $key => $value) { + if (!isset($maxTags[$key])) { + $maxTags[$key] = \strlen($key); + } + if (\strlen($value) > $maxTags[$key]) { + $maxTags[$key] = \strlen($value); + } + } + } + } + } + } + + $tagsCount = \count($maxTags); + $tagsNames = array_keys($maxTags); + + $tableHeaders = array_merge(['Service ID'], $tagsNames, ['Class name']); + $tableRows = []; + $rawOutput = isset($options['raw_text']) && $options['raw_text']; + foreach ($serviceIds as $serviceId) { + $definition = $this->resolveServiceDefinition($builder, $serviceId); + + $styledServiceId = $rawOutput ? $serviceId : sprintf('%s', OutputFormatter::escape($serviceId)); + if ($definition instanceof Definition) { + if ($showTag) { + foreach ($this->sortByPriority($definition->getTag($showTag)) as $key => $tag) { + $tagValues = []; + foreach ($tagsNames as $tagName) { + $tagValues[] = isset($tag[$tagName]) ? $tag[$tagName] : ''; + } + if (0 === $key) { + $tableRows[] = array_merge([$serviceId], $tagValues, [$definition->getClass()]); + } else { + $tableRows[] = array_merge([' "'], $tagValues, ['']); + } + } + } else { + $tableRows[] = [$styledServiceId, $definition->getClass()]; + } + } elseif ($definition instanceof Alias) { + $alias = $definition; + $tableRows[] = array_merge([$styledServiceId, sprintf('alias for "%s"', $alias)], $tagsCount ? array_fill(0, $tagsCount, '') : []); + } else { + $tableRows[] = array_merge([$styledServiceId, \get_class($definition)], $tagsCount ? array_fill(0, $tagsCount, '') : []); + } + } + + $options['output']->table($tableHeaders, $tableRows); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerDefinition(Definition $definition, array $options = []) + { + if (isset($options['id'])) { + $options['output']->title(sprintf('Information for Service "%s"', $options['id'])); + } + + if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) { + $options['output']->text($classDescription."\n"); + } + + $tableHeaders = ['Option', 'Value']; + + $tableRows[] = ['Service ID', isset($options['id']) ? $options['id'] : '-']; + $tableRows[] = ['Class', $definition->getClass() ?: '-']; + + $omitTags = isset($options['omit_tags']) && $options['omit_tags']; + if (!$omitTags && ($tags = $definition->getTags())) { + $tagInformation = []; + foreach ($tags as $tagName => $tagData) { + foreach ($tagData as $tagParameters) { + $parameters = array_map(function ($key, $value) { + return sprintf('%s: %s', $key, $value); + }, array_keys($tagParameters), array_values($tagParameters)); + $parameters = implode(', ', $parameters); + + if ('' === $parameters) { + $tagInformation[] = sprintf('%s', $tagName); + } else { + $tagInformation[] = sprintf('%s (%s)', $tagName, $parameters); + } + } + } + $tagInformation = implode("\n", $tagInformation); + } else { + $tagInformation = '-'; + } + $tableRows[] = ['Tags', $tagInformation]; + + $calls = $definition->getMethodCalls(); + if (\count($calls) > 0) { + $callInformation = []; + foreach ($calls as $call) { + $callInformation[] = $call[0]; + } + $tableRows[] = ['Calls', implode(', ', $callInformation)]; + } + + $tableRows[] = ['Public', $definition->isPublic() && !$definition->isPrivate() ? 'yes' : 'no']; + $tableRows[] = ['Synthetic', $definition->isSynthetic() ? 'yes' : 'no']; + $tableRows[] = ['Lazy', $definition->isLazy() ? 'yes' : 'no']; + $tableRows[] = ['Shared', $definition->isShared() ? 'yes' : 'no']; + $tableRows[] = ['Abstract', $definition->isAbstract() ? 'yes' : 'no']; + $tableRows[] = ['Autowired', $definition->isAutowired() ? 'yes' : 'no']; + $tableRows[] = ['Autoconfigured', $definition->isAutoconfigured() ? 'yes' : 'no']; + + if ($definition->getFile()) { + $tableRows[] = ['Required File', $definition->getFile() ?: '-']; + } + + if ($factory = $definition->getFactory()) { + if (\is_array($factory)) { + if ($factory[0] instanceof Reference) { + $tableRows[] = ['Factory Service', $factory[0]]; + } elseif ($factory[0] instanceof Definition) { + throw new \InvalidArgumentException('Factory is not describable.'); + } else { + $tableRows[] = ['Factory Class', $factory[0]]; + } + $tableRows[] = ['Factory Method', $factory[1]]; + } else { + $tableRows[] = ['Factory Function', $factory]; + } + } + + $showArguments = isset($options['show_arguments']) && $options['show_arguments']; + $argumentsInformation = []; + if ($showArguments && ($arguments = $definition->getArguments())) { + foreach ($arguments as $argument) { + if ($argument instanceof ServiceClosureArgument) { + $argument = $argument->getValues()[0]; + } + if ($argument instanceof Reference) { + $argumentsInformation[] = sprintf('Service(%s)', (string) $argument); + } elseif ($argument instanceof IteratorArgument) { + if ($argument instanceof TaggedIteratorArgument) { + $argumentsInformation[] = sprintf('Tagged Iterator for "%s"%s', $argument->getTag(), $options['is_debug'] ? '' : sprintf(' (%d element(s))', \count($argument->getValues()))); + } else { + $argumentsInformation[] = sprintf('Iterator (%d element(s))', \count($argument->getValues())); + } + + foreach ($argument->getValues() as $ref) { + $argumentsInformation[] = sprintf('- Service(%s)', $ref); + } + } elseif ($argument instanceof ServiceLocatorArgument) { + $argumentsInformation[] = sprintf('Service locator (%d element(s))', \count($argument->getValues())); + } elseif ($argument instanceof Definition) { + $argumentsInformation[] = 'Inlined Service'; + } else { + $argumentsInformation[] = \is_array($argument) ? sprintf('Array (%d element(s))', \count($argument)) : $argument; + } + } + + $tableRows[] = ['Arguments', implode("\n", $argumentsInformation)]; + } + + $options['output']->table($tableHeaders, $tableRows); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null) + { + if ($alias->isPublic()) { + $options['output']->comment(sprintf('This service is a public alias for the service %s', (string) $alias)); + } else { + $options['output']->comment(sprintf('This service is a private alias for the service %s', (string) $alias)); + } + + if (!$builder) { + return; + } + + $this->describeContainerDefinition($builder->getDefinition((string) $alias), array_merge($options, ['id' => (string) $alias])); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerParameter($parameter, array $options = []) + { + $options['output']->table( + ['Parameter', 'Value'], + [ + [$options['parameter'], $this->formatParameter($parameter), + ], + ]); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerEnvVars(array $envs, array $options = []) + { + $dump = new Dumper($this->output); + $options['output']->title('Symfony Container Environment Variables'); + + if (null !== $name = $options['name'] ?? null) { + $options['output']->comment('Displaying detailed environment variable usage matching '.$name); + + $matches = false; + foreach ($envs as $env) { + if ($name === $env['name'] || false !== stripos($env['name'], $name)) { + $matches = true; + $options['output']->section('%env('.$env['processor'].':'.$env['name'].')%'); + $options['output']->table([], [ + ['Default value', $env['default_available'] ? $dump($env['default_value']) : 'n/a'], + ['Real value', $env['runtime_available'] ? $dump($env['runtime_value']) : 'n/a'], + ['Processed value', $env['default_available'] || $env['runtime_available'] ? $dump($env['processed_value']) : 'n/a'], + ]); + } + } + + if (!$matches) { + $options['output']->block('None of the environment variables match this name.'); + } else { + $options['output']->comment('Note real values might be different between web and CLI.'); + } + + return; + } + + if (!$envs) { + $options['output']->block('No environment variables are being used.'); + + return; + } + + $rows = []; + $missing = []; + foreach ($envs as $env) { + if (isset($rows[$env['name']])) { + continue; + } + + $rows[$env['name']] = [ + $env['name'], + $env['default_available'] ? $dump($env['default_value']) : 'n/a', + $env['runtime_available'] ? $dump($env['runtime_value']) : 'n/a', + ]; + if (!$env['default_available'] && !$env['runtime_available']) { + $missing[$env['name']] = true; + } + } + + $options['output']->table(['Name', 'Default value', 'Real value'], $rows); + $options['output']->comment('Note real values might be different between web and CLI.'); + + if ($missing) { + $options['output']->warning('The following variables are missing:'); + $options['output']->listing(array_keys($missing)); + } + } + + /** + * {@inheritdoc} + */ + protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) + { + $event = \array_key_exists('event', $options) ? $options['event'] : null; + + if (null !== $event) { + $title = sprintf('Registered Listeners for "%s" Event', $event); + } else { + $title = 'Registered Listeners Grouped by Event'; + } + + $options['output']->title($title); + + $registeredListeners = $eventDispatcher->getListeners($event); + if (null !== $event) { + $this->renderEventListenerTable($eventDispatcher, $event, $registeredListeners, $options['output']); + } else { + ksort($registeredListeners); + foreach ($registeredListeners as $eventListened => $eventListeners) { + $options['output']->section(sprintf('"%s" event', $eventListened)); + $this->renderEventListenerTable($eventDispatcher, $eventListened, $eventListeners, $options['output']); + } + } + } + + /** + * {@inheritdoc} + */ + protected function describeCallable($callable, array $options = []) + { + $this->writeText($this->formatCallable($callable), $options); + } + + private function renderEventListenerTable(EventDispatcherInterface $eventDispatcher, string $event, array $eventListeners, SymfonyStyle $io) + { + $tableHeaders = ['Order', 'Callable', 'Priority']; + $tableRows = []; + + foreach ($eventListeners as $order => $listener) { + $tableRows[] = [sprintf('#%d', $order + 1), $this->formatCallable($listener), $eventDispatcher->getListenerPriority($event, $listener)]; + } + + $io->table($tableHeaders, $tableRows); + } + + private function formatRouterConfig(array $config): string + { + if (empty($config)) { + return 'NONE'; + } + + ksort($config); + + $configAsString = ''; + foreach ($config as $key => $value) { + $configAsString .= sprintf("\n%s: %s", $key, $this->formatValue($value)); + } + + return trim($configAsString); + } + + private function formatControllerLink($controller, string $anchorText): string + { + if (null === $this->fileLinkFormatter) { + return $anchorText; + } + + try { + if (\is_array($controller)) { + $r = new \ReflectionMethod($controller[0], $controller[1]); + } elseif ($controller instanceof \Closure) { + $r = new \ReflectionFunction($controller); + } elseif (method_exists($controller, '__invoke')) { + $r = new \ReflectionMethod($controller, '__invoke'); + } elseif (!\is_string($controller)) { + return $anchorText; + } elseif (false !== strpos($controller, '::')) { + $r = new \ReflectionMethod($controller); + } else { + $r = new \ReflectionFunction($controller); + } + } catch (\ReflectionException $e) { + return $anchorText; + } + + $fileLink = $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine()); + if ($fileLink) { + return sprintf('%s', $fileLink, $anchorText); + } + + return $anchorText; + } + + private function formatCallable($callable): string + { + if (\is_array($callable)) { + if (\is_object($callable[0])) { + return sprintf('%s::%s()', \get_class($callable[0]), $callable[1]); + } + + return sprintf('%s::%s()', $callable[0], $callable[1]); + } + + if (\is_string($callable)) { + return sprintf('%s()', $callable); + } + + if ($callable instanceof \Closure) { + $r = new \ReflectionFunction($callable); + if (false !== strpos($r->name, '{closure}')) { + return 'Closure()'; + } + if ($class = $r->getClosureScopeClass()) { + return sprintf('%s::%s()', $class->name, $r->name); + } + + return $r->name.'()'; + } + + if (method_exists($callable, '__invoke')) { + return sprintf('%s::__invoke()', \get_class($callable)); + } + + throw new \InvalidArgumentException('Callable is not describable.'); + } + + private function writeText(string $content, array $options = []) + { + $this->write( + isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, + isset($options['raw_output']) ? !$options['raw_output'] : true + ); + } +} diff --git a/vendor/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php b/vendor/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php new file mode 100644 index 0000000..16e79f4 --- /dev/null +++ b/vendor/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php @@ -0,0 +1,570 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; + +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * @author Jean-François Simon + * + * @internal + */ +class XmlDescriptor extends Descriptor +{ + /** + * {@inheritdoc} + */ + protected function describeRouteCollection(RouteCollection $routes, array $options = []) + { + $this->writeDocument($this->getRouteCollectionDocument($routes)); + } + + /** + * {@inheritdoc} + */ + protected function describeRoute(Route $route, array $options = []) + { + $this->writeDocument($this->getRouteDocument($route, isset($options['name']) ? $options['name'] : null)); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerParameters(ParameterBag $parameters, array $options = []) + { + $this->writeDocument($this->getContainerParametersDocument($parameters)); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerTags(ContainerBuilder $builder, array $options = []) + { + $this->writeDocument($this->getContainerTagsDocument($builder, isset($options['show_hidden']) && $options['show_hidden'])); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerService($service, array $options = [], ContainerBuilder $builder = null) + { + if (!isset($options['id'])) { + throw new \InvalidArgumentException('An "id" option must be provided.'); + } + + $this->writeDocument($this->getContainerServiceDocument($service, $options['id'], $builder, isset($options['show_arguments']) && $options['show_arguments'])); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerServices(ContainerBuilder $builder, array $options = []) + { + $this->writeDocument($this->getContainerServicesDocument($builder, isset($options['tag']) ? $options['tag'] : null, isset($options['show_hidden']) && $options['show_hidden'], isset($options['show_arguments']) && $options['show_arguments'], isset($options['filter']) ? $options['filter'] : null)); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerDefinition(Definition $definition, array $options = []) + { + $this->writeDocument($this->getContainerDefinitionDocument($definition, isset($options['id']) ? $options['id'] : null, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'])); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null) + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($dom->importNode($this->getContainerAliasDocument($alias, isset($options['id']) ? $options['id'] : null)->childNodes->item(0), true)); + + if (!$builder) { + $this->writeDocument($dom); + + return; + } + + $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($builder->getDefinition((string) $alias), (string) $alias)->childNodes->item(0), true)); + + $this->writeDocument($dom); + } + + /** + * {@inheritdoc} + */ + protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) + { + $this->writeDocument($this->getEventDispatcherListenersDocument($eventDispatcher, \array_key_exists('event', $options) ? $options['event'] : null)); + } + + /** + * {@inheritdoc} + */ + protected function describeCallable($callable, array $options = []) + { + $this->writeDocument($this->getCallableDocument($callable)); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerParameter($parameter, array $options = []) + { + $this->writeDocument($this->getContainerParameterDocument($parameter, $options)); + } + + /** + * {@inheritdoc} + */ + protected function describeContainerEnvVars(array $envs, array $options = []) + { + throw new LogicException('Using the XML format to debug environment variables is not supported.'); + } + + /** + * Writes DOM document. + */ + private function writeDocument(\DOMDocument $dom) + { + $dom->formatOutput = true; + $this->write($dom->saveXML()); + } + + private function getRouteCollectionDocument(RouteCollection $routes): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($routesXML = $dom->createElement('routes')); + + foreach ($routes->all() as $name => $route) { + $routeXML = $this->getRouteDocument($route, $name); + $routesXML->appendChild($routesXML->ownerDocument->importNode($routeXML->childNodes->item(0), true)); + } + + return $dom; + } + + private function getRouteDocument(Route $route, string $name = null): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($routeXML = $dom->createElement('route')); + + if ($name) { + $routeXML->setAttribute('name', $name); + } + + $routeXML->setAttribute('class', \get_class($route)); + + $routeXML->appendChild($pathXML = $dom->createElement('path')); + $pathXML->setAttribute('regex', $route->compile()->getRegex()); + $pathXML->appendChild(new \DOMText($route->getPath())); + + if ('' !== $route->getHost()) { + $routeXML->appendChild($hostXML = $dom->createElement('host')); + $hostXML->setAttribute('regex', $route->compile()->getHostRegex()); + $hostXML->appendChild(new \DOMText($route->getHost())); + } + + foreach ($route->getSchemes() as $scheme) { + $routeXML->appendChild($schemeXML = $dom->createElement('scheme')); + $schemeXML->appendChild(new \DOMText($scheme)); + } + + foreach ($route->getMethods() as $method) { + $routeXML->appendChild($methodXML = $dom->createElement('method')); + $methodXML->appendChild(new \DOMText($method)); + } + + if ($route->getDefaults()) { + $routeXML->appendChild($defaultsXML = $dom->createElement('defaults')); + foreach ($route->getDefaults() as $attribute => $value) { + $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); + $defaultXML->setAttribute('key', $attribute); + $defaultXML->appendChild(new \DOMText($this->formatValue($value))); + } + } + + $originRequirements = $requirements = $route->getRequirements(); + unset($requirements['_scheme'], $requirements['_method']); + if ($requirements) { + $routeXML->appendChild($requirementsXML = $dom->createElement('requirements')); + foreach ($originRequirements as $attribute => $pattern) { + $requirementsXML->appendChild($requirementXML = $dom->createElement('requirement')); + $requirementXML->setAttribute('key', $attribute); + $requirementXML->appendChild(new \DOMText($pattern)); + } + } + + if ($route->getOptions()) { + $routeXML->appendChild($optionsXML = $dom->createElement('options')); + foreach ($route->getOptions() as $name => $value) { + $optionsXML->appendChild($optionXML = $dom->createElement('option')); + $optionXML->setAttribute('key', $name); + $optionXML->appendChild(new \DOMText($this->formatValue($value))); + } + } + + if ('' !== $route->getCondition()) { + $routeXML->appendChild($conditionXML = $dom->createElement('condition')); + $conditionXML->appendChild(new \DOMText($route->getCondition())); + } + + return $dom; + } + + private function getContainerParametersDocument(ParameterBag $parameters): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($parametersXML = $dom->createElement('parameters')); + + foreach ($this->sortParameters($parameters) as $key => $value) { + $parametersXML->appendChild($parameterXML = $dom->createElement('parameter')); + $parameterXML->setAttribute('key', $key); + $parameterXML->appendChild(new \DOMText($this->formatParameter($value))); + } + + return $dom; + } + + private function getContainerTagsDocument(ContainerBuilder $builder, bool $showHidden = false): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($containerXML = $dom->createElement('container')); + + foreach ($this->findDefinitionsByTag($builder, $showHidden) as $tag => $definitions) { + $containerXML->appendChild($tagXML = $dom->createElement('tag')); + $tagXML->setAttribute('name', $tag); + + foreach ($definitions as $serviceId => $definition) { + $definitionXML = $this->getContainerDefinitionDocument($definition, $serviceId, true); + $tagXML->appendChild($dom->importNode($definitionXML->childNodes->item(0), true)); + } + } + + return $dom; + } + + private function getContainerServiceDocument($service, string $id, ContainerBuilder $builder = null, bool $showArguments = false): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + + if ($service instanceof Alias) { + $dom->appendChild($dom->importNode($this->getContainerAliasDocument($service, $id)->childNodes->item(0), true)); + if ($builder) { + $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($builder->getDefinition((string) $service), (string) $service, false, $showArguments)->childNodes->item(0), true)); + } + } elseif ($service instanceof Definition) { + $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($service, $id, false, $showArguments)->childNodes->item(0), true)); + } else { + $dom->appendChild($serviceXML = $dom->createElement('service')); + $serviceXML->setAttribute('id', $id); + $serviceXML->setAttribute('class', \get_class($service)); + } + + return $dom; + } + + private function getContainerServicesDocument(ContainerBuilder $builder, string $tag = null, bool $showHidden = false, bool $showArguments = false, callable $filter = null): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($containerXML = $dom->createElement('container')); + + $serviceIds = $tag + ? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($tag)) + : $this->sortServiceIds($builder->getServiceIds()); + if ($filter) { + $serviceIds = array_filter($serviceIds, $filter); + } + + foreach ($serviceIds as $serviceId) { + $service = $this->resolveServiceDefinition($builder, $serviceId); + + if ($showHidden xor '.' === ($serviceId[0] ?? null)) { + continue; + } + + $serviceXML = $this->getContainerServiceDocument($service, $serviceId, null, $showArguments); + $containerXML->appendChild($containerXML->ownerDocument->importNode($serviceXML->childNodes->item(0), true)); + } + + return $dom; + } + + private function getContainerDefinitionDocument(Definition $definition, string $id = null, bool $omitTags = false, bool $showArguments = false): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($serviceXML = $dom->createElement('definition')); + + if ($id) { + $serviceXML->setAttribute('id', $id); + } + + if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) { + $serviceXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createCDATASection($classDescription)); + } + + $serviceXML->setAttribute('class', $definition->getClass()); + + if ($factory = $definition->getFactory()) { + $serviceXML->appendChild($factoryXML = $dom->createElement('factory')); + + if (\is_array($factory)) { + if ($factory[0] instanceof Reference) { + $factoryXML->setAttribute('service', (string) $factory[0]); + } elseif ($factory[0] instanceof Definition) { + throw new \InvalidArgumentException('Factory is not describable.'); + } else { + $factoryXML->setAttribute('class', $factory[0]); + } + $factoryXML->setAttribute('method', $factory[1]); + } else { + $factoryXML->setAttribute('function', $factory); + } + } + + $serviceXML->setAttribute('public', $definition->isPublic() && !$definition->isPrivate() ? 'true' : 'false'); + $serviceXML->setAttribute('synthetic', $definition->isSynthetic() ? 'true' : 'false'); + $serviceXML->setAttribute('lazy', $definition->isLazy() ? 'true' : 'false'); + $serviceXML->setAttribute('shared', $definition->isShared() ? 'true' : 'false'); + $serviceXML->setAttribute('abstract', $definition->isAbstract() ? 'true' : 'false'); + $serviceXML->setAttribute('autowired', $definition->isAutowired() ? 'true' : 'false'); + $serviceXML->setAttribute('autoconfigured', $definition->isAutoconfigured() ? 'true' : 'false'); + $serviceXML->setAttribute('file', $definition->getFile()); + + $calls = $definition->getMethodCalls(); + if (\count($calls) > 0) { + $serviceXML->appendChild($callsXML = $dom->createElement('calls')); + foreach ($calls as $callData) { + $callsXML->appendChild($callXML = $dom->createElement('call')); + $callXML->setAttribute('method', $callData[0]); + if ($callData[2] ?? false) { + $callXML->setAttribute('returns-clone', 'true'); + } + } + } + + if ($showArguments) { + foreach ($this->getArgumentNodes($definition->getArguments(), $dom) as $node) { + $serviceXML->appendChild($node); + } + } + + if (!$omitTags) { + if ($tags = $this->sortTagsByPriority($definition->getTags())) { + $serviceXML->appendChild($tagsXML = $dom->createElement('tags')); + foreach ($tags as $tagName => $tagData) { + foreach ($tagData as $parameters) { + $tagsXML->appendChild($tagXML = $dom->createElement('tag')); + $tagXML->setAttribute('name', $tagName); + foreach ($parameters as $name => $value) { + $tagXML->appendChild($parameterXML = $dom->createElement('parameter')); + $parameterXML->setAttribute('name', $name); + $parameterXML->appendChild(new \DOMText($this->formatParameter($value))); + } + } + } + } + } + + return $dom; + } + + /** + * @return \DOMNode[] + */ + private function getArgumentNodes(array $arguments, \DOMDocument $dom): array + { + $nodes = []; + + foreach ($arguments as $argumentKey => $argument) { + $argumentXML = $dom->createElement('argument'); + + if (\is_string($argumentKey)) { + $argumentXML->setAttribute('key', $argumentKey); + } + + if ($argument instanceof ServiceClosureArgument) { + $argument = $argument->getValues()[0]; + } + + if ($argument instanceof Reference) { + $argumentXML->setAttribute('type', 'service'); + $argumentXML->setAttribute('id', (string) $argument); + } elseif ($argument instanceof IteratorArgument || $argument instanceof ServiceLocatorArgument) { + $argumentXML->setAttribute('type', $argument instanceof IteratorArgument ? 'iterator' : 'service_locator'); + + foreach ($this->getArgumentNodes($argument->getValues(), $dom) as $childArgumentXML) { + $argumentXML->appendChild($childArgumentXML); + } + } elseif ($argument instanceof Definition) { + $argumentXML->appendChild($dom->importNode($this->getContainerDefinitionDocument($argument, null, false, true)->childNodes->item(0), true)); + } elseif (\is_array($argument)) { + $argumentXML->setAttribute('type', 'collection'); + + foreach ($this->getArgumentNodes($argument, $dom) as $childArgumenXML) { + $argumentXML->appendChild($childArgumenXML); + } + } else { + $argumentXML->appendChild(new \DOMText($argument)); + } + + $nodes[] = $argumentXML; + } + + return $nodes; + } + + private function getContainerAliasDocument(Alias $alias, string $id = null): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($aliasXML = $dom->createElement('alias')); + + if ($id) { + $aliasXML->setAttribute('id', $id); + } + + $aliasXML->setAttribute('service', (string) $alias); + $aliasXML->setAttribute('public', $alias->isPublic() && !$alias->isPrivate() ? 'true' : 'false'); + + return $dom; + } + + private function getContainerParameterDocument($parameter, array $options = []): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($parameterXML = $dom->createElement('parameter')); + + if (isset($options['parameter'])) { + $parameterXML->setAttribute('key', $options['parameter']); + } + + $parameterXML->appendChild(new \DOMText($this->formatParameter($parameter))); + + return $dom; + } + + private function getEventDispatcherListenersDocument(EventDispatcherInterface $eventDispatcher, string $event = null): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($eventDispatcherXML = $dom->createElement('event-dispatcher')); + + $registeredListeners = $eventDispatcher->getListeners($event); + if (null !== $event) { + $this->appendEventListenerDocument($eventDispatcher, $event, $eventDispatcherXML, $registeredListeners); + } else { + ksort($registeredListeners); + + foreach ($registeredListeners as $eventListened => $eventListeners) { + $eventDispatcherXML->appendChild($eventXML = $dom->createElement('event')); + $eventXML->setAttribute('name', $eventListened); + + $this->appendEventListenerDocument($eventDispatcher, $eventListened, $eventXML, $eventListeners); + } + } + + return $dom; + } + + private function appendEventListenerDocument(EventDispatcherInterface $eventDispatcher, string $event, \DOMElement $element, array $eventListeners) + { + foreach ($eventListeners as $listener) { + $callableXML = $this->getCallableDocument($listener); + $callableXML->childNodes->item(0)->setAttribute('priority', $eventDispatcher->getListenerPriority($event, $listener)); + + $element->appendChild($element->ownerDocument->importNode($callableXML->childNodes->item(0), true)); + } + } + + private function getCallableDocument($callable): \DOMDocument + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($callableXML = $dom->createElement('callable')); + + if (\is_array($callable)) { + $callableXML->setAttribute('type', 'function'); + + if (\is_object($callable[0])) { + $callableXML->setAttribute('name', $callable[1]); + $callableXML->setAttribute('class', \get_class($callable[0])); + } else { + if (0 !== strpos($callable[1], 'parent::')) { + $callableXML->setAttribute('name', $callable[1]); + $callableXML->setAttribute('class', $callable[0]); + $callableXML->setAttribute('static', 'true'); + } else { + $callableXML->setAttribute('name', substr($callable[1], 8)); + $callableXML->setAttribute('class', $callable[0]); + $callableXML->setAttribute('static', 'true'); + $callableXML->setAttribute('parent', 'true'); + } + } + + return $dom; + } + + if (\is_string($callable)) { + $callableXML->setAttribute('type', 'function'); + + if (false === strpos($callable, '::')) { + $callableXML->setAttribute('name', $callable); + } else { + $callableParts = explode('::', $callable); + + $callableXML->setAttribute('name', $callableParts[1]); + $callableXML->setAttribute('class', $callableParts[0]); + $callableXML->setAttribute('static', 'true'); + } + + return $dom; + } + + if ($callable instanceof \Closure) { + $callableXML->setAttribute('type', 'closure'); + + $r = new \ReflectionFunction($callable); + if (false !== strpos($r->name, '{closure}')) { + return $dom; + } + $callableXML->setAttribute('name', $r->name); + + if ($class = $r->getClosureScopeClass()) { + $callableXML->setAttribute('class', $class->name); + if (!$r->getClosureThis()) { + $callableXML->setAttribute('static', 'true'); + } + } + + return $dom; + } + + if (method_exists($callable, '__invoke')) { + $callableXML->setAttribute('type', 'object'); + $callableXML->setAttribute('name', \get_class($callable)); + + return $dom; + } + + throw new \InvalidArgumentException('Callable is not describable.'); + } +} diff --git a/vendor/symfony/framework-bundle/Console/Helper/DescriptorHelper.php b/vendor/symfony/framework-bundle/Console/Helper/DescriptorHelper.php new file mode 100644 index 0000000..1f17c99 --- /dev/null +++ b/vendor/symfony/framework-bundle/Console/Helper/DescriptorHelper.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Console\Helper; + +use Symfony\Bundle\FrameworkBundle\Console\Descriptor\JsonDescriptor; +use Symfony\Bundle\FrameworkBundle\Console\Descriptor\MarkdownDescriptor; +use Symfony\Bundle\FrameworkBundle\Console\Descriptor\TextDescriptor; +use Symfony\Bundle\FrameworkBundle\Console\Descriptor\XmlDescriptor; +use Symfony\Component\Console\Helper\DescriptorHelper as BaseDescriptorHelper; +use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; + +/** + * @author Jean-François Simon + * + * @internal + */ +class DescriptorHelper extends BaseDescriptorHelper +{ + public function __construct(FileLinkFormatter $fileLinkFormatter = null) + { + $this + ->register('txt', new TextDescriptor($fileLinkFormatter)) + ->register('xml', new XmlDescriptor()) + ->register('json', new JsonDescriptor()) + ->register('md', new MarkdownDescriptor()) + ; + } +} diff --git a/vendor/symfony/framework-bundle/Controller/AbstractController.php b/vendor/symfony/framework-bundle/Controller/AbstractController.php new file mode 100644 index 0000000..20f420c --- /dev/null +++ b/vendor/symfony/framework-bundle/Controller/AbstractController.php @@ -0,0 +1,427 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Controller; + +use Doctrine\Persistence\ManagerRegistry; +use Psr\Container\ContainerInterface; +use Psr\Link\LinkInterface; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface; +use Symfony\Component\Form\Extension\Core\Type\FormType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormFactoryInterface; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\HttpFoundation\BinaryFileResponse; +use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\ResponseHeaderBag; +use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\HttpFoundation\StreamedResponse; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\RouterInterface; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; +use Symfony\Component\Security\Core\Exception\AccessDeniedException; +use Symfony\Component\Security\Csrf\CsrfToken; +use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Serializer\SerializerInterface; +use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener; +use Symfony\Component\WebLink\GenericLinkProvider; +use Symfony\Contracts\Service\ServiceSubscriberInterface; +use Twig\Environment; + +/** + * Provides common features needed in controllers. + * + * @author Fabien Potencier + */ +abstract class AbstractController implements ServiceSubscriberInterface +{ + /** + * @var ContainerInterface + */ + protected $container; + + /** + * @internal + * @required + */ + public function setContainer(ContainerInterface $container): ?ContainerInterface + { + $previous = $this->container; + $this->container = $container; + + return $previous; + } + + /** + * Gets a container parameter by its name. + * + * @return mixed + */ + protected function getParameter(string $name) + { + if (!$this->container->has('parameter_bag')) { + throw new ServiceNotFoundException('parameter_bag', null, null, [], sprintf('The "%s::getParameter()" method is missing a parameter bag to work properly. Did you forget to register your controller as a service subscriber? This can be fixed either by using autoconfiguration or by manually wiring a "parameter_bag" in the service locator passed to the controller.', \get_class($this))); + } + + return $this->container->get('parameter_bag')->get($name); + } + + public static function getSubscribedServices() + { + return [ + 'router' => '?'.RouterInterface::class, + 'request_stack' => '?'.RequestStack::class, + 'http_kernel' => '?'.HttpKernelInterface::class, + 'serializer' => '?'.SerializerInterface::class, + 'session' => '?'.SessionInterface::class, + 'security.authorization_checker' => '?'.AuthorizationCheckerInterface::class, + 'twig' => '?'.Environment::class, + 'doctrine' => '?'.ManagerRegistry::class, + 'form.factory' => '?'.FormFactoryInterface::class, + 'security.token_storage' => '?'.TokenStorageInterface::class, + 'security.csrf.token_manager' => '?'.CsrfTokenManagerInterface::class, + 'parameter_bag' => '?'.ContainerBagInterface::class, + 'message_bus' => '?'.MessageBusInterface::class, + 'messenger.default_bus' => '?'.MessageBusInterface::class, + ]; + } + + /** + * Returns true if the service id is defined. + */ + protected function has(string $id): bool + { + return $this->container->has($id); + } + + /** + * Gets a container service by its id. + * + * @return object The service + */ + protected function get(string $id): object + { + return $this->container->get($id); + } + + /** + * Generates a URL from the given parameters. + * + * @see UrlGeneratorInterface + */ + protected function generateUrl(string $route, array $parameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): string + { + return $this->container->get('router')->generate($route, $parameters, $referenceType); + } + + /** + * Forwards the request to another controller. + * + * @param string $controller The controller name (a string like Bundle\BlogBundle\Controller\PostController::indexAction) + */ + protected function forward(string $controller, array $path = [], array $query = []): Response + { + $request = $this->container->get('request_stack')->getCurrentRequest(); + $path['_controller'] = $controller; + $subRequest = $request->duplicate($query, null, $path); + + return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST); + } + + /** + * Returns a RedirectResponse to the given URL. + */ + protected function redirect(string $url, int $status = 302): RedirectResponse + { + return new RedirectResponse($url, $status); + } + + /** + * Returns a RedirectResponse to the given route with the given parameters. + */ + protected function redirectToRoute(string $route, array $parameters = [], int $status = 302): RedirectResponse + { + return $this->redirect($this->generateUrl($route, $parameters), $status); + } + + /** + * Returns a JsonResponse that uses the serializer component if enabled, or json_encode. + */ + protected function json($data, int $status = 200, array $headers = [], array $context = []): JsonResponse + { + if ($this->container->has('serializer')) { + $json = $this->container->get('serializer')->serialize($data, 'json', array_merge([ + 'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS, + ], $context)); + + return new JsonResponse($json, $status, $headers, true); + } + + return new JsonResponse($data, $status, $headers); + } + + /** + * Returns a BinaryFileResponse object with original or customized file name and disposition header. + * + * @param \SplFileInfo|string $file File object or path to file to be sent as response + */ + protected function file($file, string $fileName = null, string $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT): BinaryFileResponse + { + $response = new BinaryFileResponse($file); + $response->setContentDisposition($disposition, null === $fileName ? $response->getFile()->getFilename() : $fileName); + + return $response; + } + + /** + * Adds a flash message to the current session for type. + * + * @throws \LogicException + */ + protected function addFlash(string $type, string $message): void + { + if (!$this->container->has('session')) { + throw new \LogicException('You can not use the addFlash method if sessions are disabled. Enable them in "config/packages/framework.yaml".'); + } + + $this->container->get('session')->getFlashBag()->add($type, $message); + } + + /** + * Checks if the attributes are granted against the current authentication token and optionally supplied subject. + * + * @throws \LogicException + */ + protected function isGranted($attributes, $subject = null): bool + { + if (!$this->container->has('security.authorization_checker')) { + throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".'); + } + + return $this->container->get('security.authorization_checker')->isGranted($attributes, $subject); + } + + /** + * Throws an exception unless the attributes are granted against the current authentication token and optionally + * supplied subject. + * + * @throws AccessDeniedException + */ + protected function denyAccessUnlessGranted($attributes, $subject = null, string $message = 'Access Denied.'): void + { + if (!$this->isGranted($attributes, $subject)) { + $exception = $this->createAccessDeniedException($message); + $exception->setAttributes($attributes); + $exception->setSubject($subject); + + throw $exception; + } + } + + /** + * Returns a rendered view. + */ + protected function renderView(string $view, array $parameters = []): string + { + if (!$this->container->has('twig')) { + throw new \LogicException('You can not use the "renderView" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".'); + } + + return $this->container->get('twig')->render($view, $parameters); + } + + /** + * Renders a view. + */ + protected function render(string $view, array $parameters = [], Response $response = null): Response + { + $content = $this->renderView($view, $parameters); + + if (null === $response) { + $response = new Response(); + } + + $response->setContent($content); + + return $response; + } + + /** + * Streams a view. + */ + protected function stream(string $view, array $parameters = [], StreamedResponse $response = null): StreamedResponse + { + if (!$this->container->has('twig')) { + throw new \LogicException('You can not use the "stream" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".'); + } + + $twig = $this->container->get('twig'); + + $callback = function () use ($twig, $view, $parameters) { + $twig->display($view, $parameters); + }; + + if (null === $response) { + return new StreamedResponse($callback); + } + + $response->setCallback($callback); + + return $response; + } + + /** + * Returns a NotFoundHttpException. + * + * This will result in a 404 response code. Usage example: + * + * throw $this->createNotFoundException('Page not found!'); + */ + protected function createNotFoundException(string $message = 'Not Found', \Throwable $previous = null): NotFoundHttpException + { + return new NotFoundHttpException($message, $previous); + } + + /** + * Returns an AccessDeniedException. + * + * This will result in a 403 response code. Usage example: + * + * throw $this->createAccessDeniedException('Unable to access this page!'); + * + * @throws \LogicException If the Security component is not available + */ + protected function createAccessDeniedException(string $message = 'Access Denied.', \Throwable $previous = null): AccessDeniedException + { + if (!class_exists(AccessDeniedException::class)) { + throw new \LogicException('You can not use the "createAccessDeniedException" method if the Security component is not available. Try running "composer require symfony/security-bundle".'); + } + + return new AccessDeniedException($message, $previous); + } + + /** + * Creates and returns a Form instance from the type of the form. + */ + protected function createForm(string $type, $data = null, array $options = []): FormInterface + { + return $this->container->get('form.factory')->create($type, $data, $options); + } + + /** + * Creates and returns a form builder instance. + */ + protected function createFormBuilder($data = null, array $options = []): FormBuilderInterface + { + return $this->container->get('form.factory')->createBuilder(FormType::class, $data, $options); + } + + /** + * Shortcut to return the Doctrine Registry service. + * + * @throws \LogicException If DoctrineBundle is not available + */ + protected function getDoctrine(): ManagerRegistry + { + if (!$this->container->has('doctrine')) { + throw new \LogicException('The DoctrineBundle is not registered in your application. Try running "composer require symfony/orm-pack".'); + } + + return $this->container->get('doctrine'); + } + + /** + * Get a user from the Security Token Storage. + * + * @return UserInterface|object|null + * + * @throws \LogicException If SecurityBundle is not available + * + * @see TokenInterface::getUser() + */ + protected function getUser() + { + if (!$this->container->has('security.token_storage')) { + throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".'); + } + + if (null === $token = $this->container->get('security.token_storage')->getToken()) { + return null; + } + + if (!\is_object($user = $token->getUser())) { + // e.g. anonymous authentication + return null; + } + + return $user; + } + + /** + * Checks the validity of a CSRF token. + * + * @param string $id The id used when generating the token + * @param string|null $token The actual token sent with the request that should be validated + */ + protected function isCsrfTokenValid(string $id, ?string $token): bool + { + if (!$this->container->has('security.csrf.token_manager')) { + throw new \LogicException('CSRF protection is not enabled in your application. Enable it with the "csrf_protection" key in "config/packages/framework.yaml".'); + } + + return $this->container->get('security.csrf.token_manager')->isTokenValid(new CsrfToken($id, $token)); + } + + /** + * Dispatches a message to the bus. + * + * @param object|Envelope $message The message or the message pre-wrapped in an envelope + */ + protected function dispatchMessage($message, array $stamps = []): Envelope + { + if (!$this->container->has('messenger.default_bus')) { + $message = class_exists(Envelope::class) ? 'You need to define the "messenger.default_bus" configuration option.' : 'Try running "composer require symfony/messenger".'; + throw new \LogicException('The message bus is not enabled in your application. '.$message); + } + + return $this->container->get('messenger.default_bus')->dispatch($message, $stamps); + } + + /** + * Adds a Link HTTP header to the current response. + * + * @see https://tools.ietf.org/html/rfc5988 + */ + protected function addLink(Request $request, LinkInterface $link): void + { + if (!class_exists(AddLinkHeaderListener::class)) { + throw new \LogicException('You can not use the "addLink" method if the WebLink component is not available. Try running "composer require symfony/web-link".'); + } + + if (null === $linkProvider = $request->attributes->get('_links')) { + $request->attributes->set('_links', new GenericLinkProvider([$link])); + + return; + } + + $request->attributes->set('_links', $linkProvider->withLink($link)); + } +} diff --git a/vendor/symfony/framework-bundle/Controller/ControllerResolver.php b/vendor/symfony/framework-bundle/Controller/ControllerResolver.php new file mode 100644 index 0000000..859d1c2 --- /dev/null +++ b/vendor/symfony/framework-bundle/Controller/ControllerResolver.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Controller; + +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver; + +/** + * @author Fabien Potencier + * + * @final + */ +class ControllerResolver extends ContainerControllerResolver +{ + /** + * {@inheritdoc} + */ + protected function instantiateController($class): object + { + return $this->configureController(parent::instantiateController($class), $class); + } + + private function configureController($controller, string $class): object + { + if ($controller instanceof ContainerAwareInterface) { + $controller->setContainer($this->container); + } + if ($controller instanceof AbstractController) { + if (null === $previousContainer = $controller->setContainer($this->container)) { + throw new \LogicException(sprintf('"%s" has no container set, did you forget to define it as a service subscriber?', $class)); + } else { + $controller->setContainer($previousContainer); + } + } + + return $controller; + } +} diff --git a/vendor/symfony/framework-bundle/Controller/RedirectController.php b/vendor/symfony/framework-bundle/Controller/RedirectController.php new file mode 100644 index 0000000..00d1a4a --- /dev/null +++ b/vendor/symfony/framework-bundle/Controller/RedirectController.php @@ -0,0 +1,179 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Controller; + +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; + +/** + * Redirects a request to another URL. + * + * @author Fabien Potencier + * + * @final + */ +class RedirectController +{ + private $router; + private $httpPort; + private $httpsPort; + + public function __construct(UrlGeneratorInterface $router = null, int $httpPort = null, int $httpsPort = null) + { + $this->router = $router; + $this->httpPort = $httpPort; + $this->httpsPort = $httpsPort; + } + + /** + * Redirects to another route with the given name. + * + * The response status code is 302 if the permanent parameter is false (default), + * and 301 if the redirection is permanent. + * + * In case the route name is empty, the status code will be 404 when permanent is false + * and 410 otherwise. + * + * @param string $route The route name to redirect to + * @param bool $permanent Whether the redirection is permanent + * @param bool|array $ignoreAttributes Whether to ignore attributes or an array of attributes to ignore + * @param bool $keepRequestMethod Whether redirect action should keep HTTP request method + * + * @throws HttpException In case the route name is empty + */ + public function redirectAction(Request $request, string $route, bool $permanent = false, $ignoreAttributes = false, bool $keepRequestMethod = false, bool $keepQueryParams = false): Response + { + if ('' == $route) { + throw new HttpException($permanent ? 410 : 404); + } + + $attributes = []; + if (false === $ignoreAttributes || \is_array($ignoreAttributes)) { + $attributes = $request->attributes->get('_route_params'); + $attributes = $keepQueryParams ? array_merge($request->query->all(), $attributes) : $attributes; + unset($attributes['route'], $attributes['permanent'], $attributes['ignoreAttributes'], $attributes['keepRequestMethod'], $attributes['keepQueryParams']); + if ($ignoreAttributes) { + $attributes = array_diff_key($attributes, array_flip($ignoreAttributes)); + } + } + + if ($keepRequestMethod) { + $statusCode = $permanent ? 308 : 307; + } else { + $statusCode = $permanent ? 301 : 302; + } + + return new RedirectResponse($this->router->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), $statusCode); + } + + /** + * Redirects to a URL. + * + * The response status code is 302 if the permanent parameter is false (default), + * and 301 if the redirection is permanent. + * + * In case the path is empty, the status code will be 404 when permanent is false + * and 410 otherwise. + * + * @param string $path The absolute path or URL to redirect to + * @param bool $permanent Whether the redirect is permanent or not + * @param string|null $scheme The URL scheme (null to keep the current one) + * @param int|null $httpPort The HTTP port (null to keep the current one for the same scheme or the default configured port) + * @param int|null $httpsPort The HTTPS port (null to keep the current one for the same scheme or the default configured port) + * @param bool $keepRequestMethod Whether redirect action should keep HTTP request method + * + * @throws HttpException In case the path is empty + */ + public function urlRedirectAction(Request $request, string $path, bool $permanent = false, string $scheme = null, int $httpPort = null, int $httpsPort = null, bool $keepRequestMethod = false): Response + { + if ('' == $path) { + throw new HttpException($permanent ? 410 : 404); + } + + if ($keepRequestMethod) { + $statusCode = $permanent ? 308 : 307; + } else { + $statusCode = $permanent ? 301 : 302; + } + + // redirect if the path is a full URL + if (parse_url($path, PHP_URL_SCHEME)) { + return new RedirectResponse($path, $statusCode); + } + + if (null === $scheme) { + $scheme = $request->getScheme(); + } + + $qs = $request->getQueryString(); + if ($qs) { + if (false === strpos($path, '?')) { + $qs = '?'.$qs; + } else { + $qs = '&'.$qs; + } + } + + $port = ''; + if ('http' === $scheme) { + if (null === $httpPort) { + if ('http' === $request->getScheme()) { + $httpPort = $request->getPort(); + } else { + $httpPort = $this->httpPort; + } + } + + if (null !== $httpPort && 80 != $httpPort) { + $port = ":$httpPort"; + } + } elseif ('https' === $scheme) { + if (null === $httpsPort) { + if ('https' === $request->getScheme()) { + $httpsPort = $request->getPort(); + } else { + $httpsPort = $this->httpsPort; + } + } + + if (null !== $httpsPort && 443 != $httpsPort) { + $port = ":$httpsPort"; + } + } + + $url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$path.$qs; + + return new RedirectResponse($url, $statusCode); + } + + public function __invoke(Request $request): Response + { + $p = $request->attributes->get('_route_params', []); + + if (\array_key_exists('route', $p)) { + if (\array_key_exists('path', $p)) { + throw new \RuntimeException(sprintf('Ambiguous redirection settings, use the "path" or "route" parameter, not both: "%s" and "%s" found respectively in "%s" routing configuration.', $p['path'], $p['route'], $request->attributes->get('_route'))); + } + + return $this->redirectAction($request, $p['route'], $p['permanent'] ?? false, $p['ignoreAttributes'] ?? false, $p['keepRequestMethod'] ?? false, $p['keepQueryParams'] ?? false); + } + + if (\array_key_exists('path', $p)) { + return $this->urlRedirectAction($request, $p['path'], $p['permanent'] ?? false, $p['scheme'] ?? null, $p['httpPort'] ?? null, $p['httpsPort'] ?? null, $p['keepRequestMethod'] ?? false); + } + + throw new \RuntimeException(sprintf('The parameter "path" or "route" is required to configure the redirect action in "%s" routing configuration.', $request->attributes->get('_route'))); + } +} diff --git a/vendor/symfony/framework-bundle/Controller/TemplateController.php b/vendor/symfony/framework-bundle/Controller/TemplateController.php new file mode 100644 index 0000000..0fff40b --- /dev/null +++ b/vendor/symfony/framework-bundle/Controller/TemplateController.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Controller; + +use Symfony\Component\HttpFoundation\Response; +use Twig\Environment; + +/** + * TemplateController. + * + * @author Fabien Potencier + * + * @final + */ +class TemplateController +{ + private $twig; + + public function __construct(Environment $twig = null) + { + $this->twig = $twig; + } + + /** + * Renders a template. + * + * @param string $template The template name + * @param int|null $maxAge Max age for client caching + * @param int|null $sharedAge Max age for shared (proxy) caching + * @param bool|null $private Whether or not caching should apply for client caches only + */ + public function templateAction(string $template, int $maxAge = null, int $sharedAge = null, bool $private = null): Response + { + if (null === $this->twig) { + throw new \LogicException('You can not use the TemplateController if the Twig Bundle is not available.'); + } + + $response = new Response($this->twig->render($template)); + + if ($maxAge) { + $response->setMaxAge($maxAge); + } + + if ($sharedAge) { + $response->setSharedMaxAge($sharedAge); + } + + if ($private) { + $response->setPrivate(); + } elseif (false === $private || (null === $private && ($maxAge || $sharedAge))) { + $response->setPublic(); + } + + return $response; + } + + public function __invoke(string $template, int $maxAge = null, int $sharedAge = null, bool $private = null): Response + { + return $this->templateAction($template, $maxAge, $sharedAge, $private); + } +} diff --git a/vendor/symfony/framework-bundle/DataCollector/RouterDataCollector.php b/vendor/symfony/framework-bundle/DataCollector/RouterDataCollector.php new file mode 100644 index 0000000..0acdc61 --- /dev/null +++ b/vendor/symfony/framework-bundle/DataCollector/RouterDataCollector.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DataCollector; + +use Symfony\Bundle\FrameworkBundle\Controller\RedirectController; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\DataCollector\RouterDataCollector as BaseRouterDataCollector; + +/** + * RouterDataCollector. + * + * @author Fabien Potencier + * + * @final + */ +class RouterDataCollector extends BaseRouterDataCollector +{ + public function guessRoute(Request $request, $controller) + { + if (\is_array($controller)) { + $controller = $controller[0]; + } + + if ($controller instanceof RedirectController) { + return $request->attributes->get('_route'); + } + + return parent::guessRoute($request, $controller); + } +} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php new file mode 100644 index 0000000..4f09e52 --- /dev/null +++ b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * @internal + */ +class AddAnnotationsCachedReaderPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + // "annotations.cached_reader" is wired late so that any passes using + // "annotation_reader" at build time don't get any cache + foreach ($container->findTaggedServiceIds('annotations.cached_reader') as $id => $tags) { + $reader = $container->getDefinition($id); + $properties = $reader->getProperties(); + + if (isset($properties['cacheProviderBackup'])) { + $provider = $properties['cacheProviderBackup']->getValues()[0]; + unset($properties['cacheProviderBackup']); + $reader->setProperties($properties); + $container->set($id, null); + $container->setDefinition($id, $reader->replaceArgument(1, $provider)); + } + } + } +} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php new file mode 100644 index 0000000..dbe88b0 --- /dev/null +++ b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +class AddDebugLogProcessorPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('profiler')) { + return; + } + if (!$container->hasDefinition('monolog.logger_prototype')) { + return; + } + if (!$container->hasDefinition('debug.log_processor')) { + return; + } + + $definition = $container->getDefinition('monolog.logger_prototype'); + $definition->setConfigurator([__CLASS__, 'configureLogger']); + $definition->addMethodCall('pushProcessor', [new Reference('debug.log_processor')]); + } + + public static function configureLogger($logger) + { + if (method_exists($logger, 'removeDebugLogger') && \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { + $logger->removeDebugLogger(); + } + } +} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php new file mode 100644 index 0000000..47195b4 --- /dev/null +++ b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Registers the expression language providers. + * + * @author Fabien Potencier + */ +class AddExpressionLanguageProvidersPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + // routing + if ($container->has('router')) { + $definition = $container->findDefinition('router'); + foreach ($container->findTaggedServiceIds('routing.expression_language_provider', true) as $id => $attributes) { + $definition->addMethodCall('addExpressionLanguageProvider', [new Reference($id)]); + } + } + } +} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php new file mode 100644 index 0000000..0df5420 --- /dev/null +++ b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\Config\ConfigCache; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Dumper\XmlDumper; + +/** + * Dumps the ContainerBuilder to a cache file so that it can be used by + * debugging tools such as the debug:container console command. + * + * @author Ryan Weaver + * @author Fabien Potencier + */ +class ContainerBuilderDebugDumpPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + $cache = new ConfigCache($container->getParameter('debug.container.dump'), true); + if (!$cache->isFresh()) { + $cache->write((new XmlDumper($container))->dump(), $container->getResources()); + } + } +} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php new file mode 100644 index 0000000..ee2bbb6 --- /dev/null +++ b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * @author Christian Flothmann + */ +class DataCollectorTranslatorPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + if (!$container->has('translator')) { + return; + } + + $translatorClass = $container->getParameterBag()->resolveValue($container->findDefinition('translator')->getClass()); + + if (!is_subclass_of($translatorClass, 'Symfony\Component\Translation\TranslatorBagInterface')) { + $container->removeDefinition('translator.data_collector'); + $container->removeDefinition('data_collector.translation'); + } + } +} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php new file mode 100644 index 0000000..80cbe52 --- /dev/null +++ b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\Translation\TranslatorBagInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +/** + * @author Abdellatif Ait boudad + */ +class LoggingTranslatorPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + if (!$container->hasAlias('logger') || !$container->hasAlias('translator')) { + return; + } + + if ($container->hasParameter('translator.logging') && $container->getParameter('translator.logging')) { + $translatorAlias = $container->getAlias('translator'); + $definition = $container->getDefinition((string) $translatorAlias); + $class = $container->getParameterBag()->resolveValue($definition->getClass()); + + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $translatorAlias)); + } + if ($r->isSubclassOf(TranslatorInterface::class) && $r->isSubclassOf(TranslatorBagInterface::class)) { + $container->getDefinition('translator.logging')->setDecoratedService('translator'); + $warmer = $container->getDefinition('translation.warmer'); + $subscriberAttributes = $warmer->getTag('container.service_subscriber'); + $warmer->clearTag('container.service_subscriber'); + + foreach ($subscriberAttributes as $k => $v) { + if ((!isset($v['id']) || 'translator' !== $v['id']) && (!isset($v['key']) || 'translator' !== $v['key'])) { + $warmer->addTag('container.service_subscriber', $v); + } + } + $warmer->addTag('container.service_subscriber', ['key' => 'translator', 'id' => 'translator.logging.inner']); + } + } + } +} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php new file mode 100644 index 0000000..357c079 --- /dev/null +++ b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Adds tagged data_collector services to profiler service. + * + * @author Fabien Potencier + */ +class ProfilerPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + if (false === $container->hasDefinition('profiler')) { + return; + } + + $definition = $container->getDefinition('profiler'); + + $collectors = new \SplPriorityQueue(); + $order = PHP_INT_MAX; + foreach ($container->findTaggedServiceIds('data_collector', true) as $id => $attributes) { + $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; + $template = null; + + if (isset($attributes[0]['template'])) { + if (!isset($attributes[0]['id'])) { + throw new InvalidArgumentException(sprintf('Data collector service "%s" must have an id attribute in order to specify a template', $id)); + } + $template = [$attributes[0]['id'], $attributes[0]['template']]; + } + + $collectors->insert([$id, $template], [$priority, --$order]); + } + + $templates = []; + foreach ($collectors as $collector) { + $definition->addMethodCall('add', [new Reference($collector[0])]); + $templates[$collector[0]] = $collector[1]; + } + + $container->setParameter('data_collector.templates', $templates); + } +} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php new file mode 100644 index 0000000..222b5c7 --- /dev/null +++ b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Nicolas Grekas + */ +class TestServiceContainerRealRefPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('test.private_services_locator')) { + return; + } + + $privateContainer = $container->getDefinition('test.private_services_locator'); + $definitions = $container->getDefinitions(); + $privateServices = $privateContainer->getArgument(0); + + foreach ($privateServices as $id => $argument) { + if (isset($definitions[$target = (string) $argument->getValues()[0]])) { + $argument->setValues([new Reference($target)]); + } else { + unset($privateServices[$id]); + } + } + + $privateContainer->replaceArgument(0, $privateServices); + } +} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php new file mode 100644 index 0000000..57aa592 --- /dev/null +++ b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Nicolas Grekas + */ +class TestServiceContainerWeakRefPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('test.private_services_locator')) { + return; + } + + $privateServices = []; + $definitions = $container->getDefinitions(); + $hasErrors = method_exists(Definition::class, 'hasErrors') ? 'hasErrors' : 'getErrors'; + + foreach ($definitions as $id => $definition) { + if ($id && '.' !== $id[0] && (!$definition->isPublic() || $definition->isPrivate()) && !$definition->$hasErrors() && !$definition->isAbstract()) { + $privateServices[$id] = new Reference($id, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE); + } + } + + $aliases = $container->getAliases(); + + foreach ($aliases as $id => $alias) { + if ($id && '.' !== $id[0] && (!$alias->isPublic() || $alias->isPrivate())) { + while (isset($aliases[$target = (string) $alias])) { + $alias = $aliases[$target]; + } + if (isset($definitions[$target]) && !$definitions[$target]->$hasErrors() && !$definitions[$target]->isAbstract()) { + $privateServices[$id] = new Reference($target, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE); + } + } + } + + if ($privateServices) { + $id = (string) ServiceLocatorTagPass::register($container, $privateServices); + $container->setDefinition('test.private_services_locator', $container->getDefinition($id))->setPublic(true); + $container->removeDefinition($id); + } + } +} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php new file mode 100644 index 0000000..5bbcb74 --- /dev/null +++ b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Find all service tags which are defined, but not used and yield a warning log message. + * + * @author Florian Pfitzer + */ +class UnusedTagsPass implements CompilerPassInterface +{ + private $whitelist = [ + 'annotations.cached_reader', + 'cache.pool.clearer', + 'console.command', + 'container.hot_path', + 'container.reversible', + 'container.service_locator', + 'container.service_subscriber', + 'controller.service_arguments', + 'config_cache.resource_checker', + 'data_collector', + 'form.type', + 'form.type_extension', + 'form.type_guesser', + 'http_client.client', + 'kernel.cache_clearer', + 'kernel.cache_warmer', + 'kernel.event_listener', + 'kernel.event_subscriber', + 'kernel.fragment_renderer', + 'kernel.locale_aware', + 'messenger.bus', + 'messenger.receiver', + 'messenger.message_handler', + 'mime.mime_type_guesser', + 'monolog.logger', + 'proxy', + 'routing.expression_language_provider', + 'routing.loader', + 'routing.route_loader', + 'security.expression_language_provider', + 'security.remember_me_aware', + 'security.voter', + 'serializer.encoder', + 'serializer.normalizer', + 'translation.dumper', + 'translation.extractor', + 'translation.loader', + 'twig.extension', + 'twig.loader', + 'validator.constraint_validator', + 'validator.initializer', + 'validator.auto_mapper', + ]; + + public function process(ContainerBuilder $container) + { + $tags = array_unique(array_merge($container->findTags(), $this->whitelist)); + + foreach ($container->findUnusedTags() as $tag) { + // skip whitelisted tags + if (\in_array($tag, $this->whitelist)) { + continue; + } + + // check for typos + $candidates = []; + foreach ($tags as $definedTag) { + if ($definedTag === $tag) { + continue; + } + + if (false !== strpos($definedTag, $tag) || levenshtein($tag, $definedTag) <= \strlen($tag) / 3) { + $candidates[] = $definedTag; + } + } + + $services = array_keys($container->findTaggedServiceIds($tag)); + $message = sprintf('Tag "%s" was defined on service(s) "%s", but was never used.', $tag, implode('", "', $services)); + if (!empty($candidates)) { + $message .= sprintf(' Did you mean "%s"?', implode('", "', $candidates)); + } + + $container->log($this, $message); + } + } +} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php new file mode 100644 index 0000000..ad62e19 --- /dev/null +++ b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\LogicException; + +/** + * @author Christian Flothmann + * @author Grégoire Pineau + */ +class WorkflowGuardListenerPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasParameter('workflow.has_guard_listeners')) { + return; + } + + $container->getParameterBag()->remove('workflow.has_guard_listeners'); + + $servicesNeeded = [ + 'security.token_storage', + 'security.authorization_checker', + 'security.authentication.trust_resolver', + 'security.role_hierarchy', + ]; + + foreach ($servicesNeeded as $service) { + if (!$container->has($service)) { + throw new LogicException(sprintf('The "%s" service is needed to be able to use the workflow guard listener.', $service)); + } + } + } +} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Configuration.php b/vendor/symfony/framework-bundle/DependencyInjection/Configuration.php new file mode 100644 index 0000000..47a508c --- /dev/null +++ b/vendor/symfony/framework-bundle/DependencyInjection/Configuration.php @@ -0,0 +1,1558 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; + +use Doctrine\Common\Annotations\Annotation; +use Doctrine\Common\Cache\Cache; +use Doctrine\DBAL\Connection; +use Symfony\Bundle\FullStack; +use Symfony\Component\Asset\Package; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\Config\Definition\Builder\TreeBuilder; +use Symfony\Component\Config\Definition\ConfigurationInterface; +use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; +use Symfony\Component\DependencyInjection\Exception\LogicException; +use Symfony\Component\Form\Form; +use Symfony\Component\HttpClient\HttpClient; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\Lock\Lock; +use Symfony\Component\Lock\Store\SemaphoreStore; +use Symfony\Component\Mailer\Mailer; +use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Notifier\Notifier; +use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; +use Symfony\Component\Serializer\Serializer; +use Symfony\Component\Translation\Translator; +use Symfony\Component\Validator\Validation; +use Symfony\Component\WebLink\HttpHeaderSerializer; + +/** + * FrameworkExtension configuration structure. + * + * @author Jeremy Mikola + * @author Grégoire Pineau + */ +class Configuration implements ConfigurationInterface +{ + private $debug; + + /** + * @param bool $debug Whether debugging is enabled or not + */ + public function __construct(bool $debug) + { + $this->debug = $debug; + } + + /** + * Generates the configuration tree builder. + * + * @return TreeBuilder The tree builder + */ + public function getConfigTreeBuilder() + { + $treeBuilder = new TreeBuilder('framework'); + $rootNode = $treeBuilder->getRootNode(); + + $rootNode + ->beforeNormalization() + ->ifTrue(function ($v) { return !isset($v['assets']) && isset($v['templating']) && class_exists(Package::class); }) + ->then(function ($v) { + $v['assets'] = []; + + return $v; + }) + ->end() + ->children() + ->scalarNode('secret')->end() + ->scalarNode('http_method_override') + ->info("Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. Note: When using the HttpCache, you need to call the method in your front controller instead") + ->defaultTrue() + ->end() + ->scalarNode('ide')->defaultNull()->end() + ->booleanNode('test')->end() + ->scalarNode('default_locale')->defaultValue('en')->end() + ->arrayNode('trusted_hosts') + ->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end() + ->prototype('scalar')->end() + ->end() + ->scalarNode('error_controller') + ->defaultValue('error_controller') + ->end() + ->end() + ; + + $this->addCsrfSection($rootNode); + $this->addFormSection($rootNode); + $this->addEsiSection($rootNode); + $this->addSsiSection($rootNode); + $this->addFragmentsSection($rootNode); + $this->addProfilerSection($rootNode); + $this->addWorkflowSection($rootNode); + $this->addRouterSection($rootNode); + $this->addSessionSection($rootNode); + $this->addRequestSection($rootNode); + $this->addAssetsSection($rootNode); + $this->addTranslatorSection($rootNode); + $this->addValidationSection($rootNode); + $this->addAnnotationsSection($rootNode); + $this->addSerializerSection($rootNode); + $this->addPropertyAccessSection($rootNode); + $this->addPropertyInfoSection($rootNode); + $this->addCacheSection($rootNode); + $this->addPhpErrorsSection($rootNode); + $this->addWebLinkSection($rootNode); + $this->addLockSection($rootNode); + $this->addMessengerSection($rootNode); + $this->addRobotsIndexSection($rootNode); + $this->addHttpClientSection($rootNode); + $this->addMailerSection($rootNode); + $this->addSecretsSection($rootNode); + $this->addNotifierSection($rootNode); + + return $treeBuilder; + } + + private function addSecretsSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('secrets') + ->canBeDisabled() + ->children() + ->scalarNode('vault_directory')->defaultValue('%kernel.project_dir%/config/secrets/%kernel.environment%')->cannotBeEmpty()->end() + ->scalarNode('local_dotenv_file')->defaultValue('%kernel.project_dir%/.env.%kernel.environment%.local')->end() + ->scalarNode('decryption_env_var')->defaultValue('base64:default::SYMFONY_DECRYPTION_SECRET')->end() + ->end() + ->end() + ->end() + ; + } + + private function addCsrfSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('csrf_protection') + ->treatFalseLike(['enabled' => false]) + ->treatTrueLike(['enabled' => true]) + ->treatNullLike(['enabled' => true]) + ->addDefaultsIfNotSet() + ->children() + // defaults to framework.session.enabled && !class_exists(FullStack::class) && interface_exists(CsrfTokenManagerInterface::class) + ->booleanNode('enabled')->defaultNull()->end() + ->end() + ->end() + ->end() + ; + } + + private function addFormSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('form') + ->info('form configuration') + ->{!class_exists(FullStack::class) && class_exists(Form::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->children() + ->arrayNode('csrf_protection') + ->treatFalseLike(['enabled' => false]) + ->treatTrueLike(['enabled' => true]) + ->treatNullLike(['enabled' => true]) + ->addDefaultsIfNotSet() + ->children() + ->booleanNode('enabled')->defaultNull()->end() // defaults to framework.csrf_protection.enabled + ->scalarNode('field_name')->defaultValue('_token')->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addEsiSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('esi') + ->info('esi configuration') + ->canBeEnabled() + ->end() + ->end() + ; + } + + private function addSsiSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('ssi') + ->info('ssi configuration') + ->canBeEnabled() + ->end() + ->end(); + } + + private function addFragmentsSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('fragments') + ->info('fragments configuration') + ->canBeEnabled() + ->children() + ->scalarNode('hinclude_default_template')->defaultNull()->end() + ->scalarNode('path')->defaultValue('/_fragment')->end() + ->end() + ->end() + ->end() + ; + } + + private function addProfilerSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('profiler') + ->info('profiler configuration') + ->canBeEnabled() + ->children() + ->booleanNode('collect')->defaultTrue()->end() + ->booleanNode('only_exceptions')->defaultFalse()->end() + ->booleanNode('only_master_requests')->defaultFalse()->end() + ->scalarNode('dsn')->defaultValue('file:%kernel.cache_dir%/profiler')->end() + ->end() + ->end() + ->end() + ; + } + + private function addWorkflowSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->fixXmlConfig('workflow') + ->children() + ->arrayNode('workflows') + ->canBeEnabled() + ->beforeNormalization() + ->always(function ($v) { + if (\is_array($v) && true === $v['enabled']) { + $workflows = $v; + unset($workflows['enabled']); + + if (1 === \count($workflows) && isset($workflows[0]['enabled']) && 1 === \count($workflows[0])) { + $workflows = []; + } + + if (1 === \count($workflows) && isset($workflows['workflows']) && array_keys($workflows['workflows']) !== range(0, \count($workflows) - 1) && !empty(array_diff(array_keys($workflows['workflows']), ['audit_trail', 'type', 'marking_store', 'supports', 'support_strategy', 'initial_marking', 'places', 'transitions']))) { + $workflows = $workflows['workflows']; + } + + foreach ($workflows as $key => $workflow) { + if (isset($workflow['enabled']) && false === $workflow['enabled']) { + throw new LogicException(sprintf('Cannot disable a single workflow. Remove the configuration for the workflow "%s" instead.', $workflow['name'])); + } + + unset($workflows[$key]['enabled']); + } + + $v = [ + 'enabled' => true, + 'workflows' => $workflows, + ]; + } + + return $v; + }) + ->end() + ->children() + ->arrayNode('workflows') + ->useAttributeAsKey('name') + ->prototype('array') + ->fixXmlConfig('support') + ->fixXmlConfig('place') + ->fixXmlConfig('transition') + ->children() + ->arrayNode('audit_trail') + ->canBeEnabled() + ->end() + ->enumNode('type') + ->values(['workflow', 'state_machine']) + ->defaultValue('state_machine') + ->end() + ->arrayNode('marking_store') + ->children() + ->enumNode('type') + ->values(['method']) + ->end() + ->scalarNode('property') + ->defaultValue('marking') + ->end() + ->scalarNode('service') + ->cannotBeEmpty() + ->end() + ->end() + ->end() + ->arrayNode('supports') + ->beforeNormalization() + ->ifString() + ->then(function ($v) { return [$v]; }) + ->end() + ->prototype('scalar') + ->cannotBeEmpty() + ->validate() + ->ifTrue(function ($v) { return !class_exists($v) && !interface_exists($v, false); }) + ->thenInvalid('The supported class or interface "%s" does not exist.') + ->end() + ->end() + ->end() + ->scalarNode('support_strategy') + ->cannotBeEmpty() + ->end() + ->arrayNode('initial_marking') + ->beforeNormalization()->castToArray()->end() + ->defaultValue([]) + ->prototype('scalar')->end() + ->end() + ->arrayNode('places') + ->beforeNormalization() + ->always() + ->then(function ($places) { + // It's an indexed array of shape ['place1', 'place2'] + if (isset($places[0]) && \is_string($places[0])) { + return array_map(function (string $place) { + return ['name' => $place]; + }, $places); + } + + // It's an indexed array, we let the validation occur + if (isset($places[0]) && \is_array($places[0])) { + return $places; + } + + foreach ($places as $name => $place) { + if (\is_array($place) && \array_key_exists('name', $place)) { + continue; + } + $place['name'] = $name; + $places[$name] = $place; + } + + return array_values($places); + }) + ->end() + ->isRequired() + ->requiresAtLeastOneElement() + ->prototype('array') + ->children() + ->scalarNode('name') + ->isRequired() + ->cannotBeEmpty() + ->end() + ->arrayNode('metadata') + ->normalizeKeys(false) + ->defaultValue([]) + ->example(['color' => 'blue', 'description' => 'Workflow to manage article.']) + ->prototype('variable') + ->end() + ->end() + ->end() + ->end() + ->end() + ->arrayNode('transitions') + ->beforeNormalization() + ->always() + ->then(function ($transitions) { + // It's an indexed array, we let the validation occur + if (isset($transitions[0]) && \is_array($transitions[0])) { + return $transitions; + } + + foreach ($transitions as $name => $transition) { + if (\is_array($transition) && \array_key_exists('name', $transition)) { + continue; + } + $transition['name'] = $name; + $transitions[$name] = $transition; + } + + return $transitions; + }) + ->end() + ->isRequired() + ->requiresAtLeastOneElement() + ->prototype('array') + ->children() + ->scalarNode('name') + ->isRequired() + ->cannotBeEmpty() + ->end() + ->scalarNode('guard') + ->cannotBeEmpty() + ->info('An expression to block the transition') + ->example('is_fully_authenticated() and is_granted(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'') + ->end() + ->arrayNode('from') + ->beforeNormalization() + ->ifString() + ->then(function ($v) { return [$v]; }) + ->end() + ->requiresAtLeastOneElement() + ->prototype('scalar') + ->cannotBeEmpty() + ->end() + ->end() + ->arrayNode('to') + ->beforeNormalization() + ->ifString() + ->then(function ($v) { return [$v]; }) + ->end() + ->requiresAtLeastOneElement() + ->prototype('scalar') + ->cannotBeEmpty() + ->end() + ->end() + ->arrayNode('metadata') + ->normalizeKeys(false) + ->defaultValue([]) + ->example(['color' => 'blue', 'description' => 'Workflow to manage article.']) + ->prototype('variable') + ->end() + ->end() + ->end() + ->end() + ->end() + ->arrayNode('metadata') + ->normalizeKeys(false) + ->defaultValue([]) + ->example(['color' => 'blue', 'description' => 'Workflow to manage article.']) + ->prototype('variable') + ->end() + ->end() + ->end() + ->validate() + ->ifTrue(function ($v) { + return $v['supports'] && isset($v['support_strategy']); + }) + ->thenInvalid('"supports" and "support_strategy" cannot be used together.') + ->end() + ->validate() + ->ifTrue(function ($v) { + return !$v['supports'] && !isset($v['support_strategy']); + }) + ->thenInvalid('"supports" or "support_strategy" should be configured.') + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addRouterSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('router') + ->info('router configuration') + ->canBeEnabled() + ->children() + ->scalarNode('resource')->isRequired()->end() + ->scalarNode('type')->end() + ->scalarNode('http_port')->defaultValue(80)->end() + ->scalarNode('https_port')->defaultValue(443)->end() + ->scalarNode('strict_requirements') + ->info( + "set to true to throw an exception when a parameter does not match the requirements\n". + "set to false to disable exceptions when a parameter does not match the requirements (and return null instead)\n". + "set to null to disable parameter checks against requirements\n". + "'true' is the preferred configuration in development mode, while 'false' or 'null' might be preferred in production" + ) + ->defaultTrue() + ->end() + ->booleanNode('utf8')->defaultFalse()->end() + ->end() + ->end() + ->end() + ; + } + + private function addSessionSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('session') + ->info('session configuration') + ->canBeEnabled() + ->children() + ->scalarNode('storage_id')->defaultValue('session.storage.native')->end() + ->scalarNode('handler_id')->defaultValue('session.handler.native_file')->end() + ->scalarNode('name') + ->validate() + ->ifTrue(function ($v) { + parse_str($v, $parsed); + + return implode('&', array_keys($parsed)) !== (string) $v; + }) + ->thenInvalid('Session name %s contains illegal character(s)') + ->end() + ->end() + ->scalarNode('cookie_lifetime')->end() + ->scalarNode('cookie_path')->end() + ->scalarNode('cookie_domain')->end() + ->enumNode('cookie_secure')->values([true, false, 'auto'])->end() + ->booleanNode('cookie_httponly')->defaultTrue()->end() + ->enumNode('cookie_samesite')->values([null, Cookie::SAMESITE_LAX, Cookie::SAMESITE_STRICT, Cookie::SAMESITE_NONE])->defaultNull()->end() + ->booleanNode('use_cookies')->end() + ->scalarNode('gc_divisor')->end() + ->scalarNode('gc_probability')->defaultValue(1)->end() + ->scalarNode('gc_maxlifetime')->end() + ->scalarNode('save_path')->defaultValue('%kernel.cache_dir%/sessions')->end() + ->integerNode('metadata_update_threshold') + ->defaultValue(0) + ->info('seconds to wait between 2 session metadata updates') + ->end() + ->integerNode('sid_length') + ->min(22) + ->max(256) + ->end() + ->integerNode('sid_bits_per_character') + ->min(4) + ->max(6) + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addRequestSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('request') + ->info('request configuration') + ->canBeEnabled() + ->fixXmlConfig('format') + ->children() + ->arrayNode('formats') + ->useAttributeAsKey('name') + ->prototype('array') + ->beforeNormalization() + ->ifTrue(function ($v) { return \is_array($v) && isset($v['mime_type']); }) + ->then(function ($v) { return $v['mime_type']; }) + ->end() + ->beforeNormalization()->castToArray()->end() + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addAssetsSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('assets') + ->info('assets configuration') + ->{!class_exists(FullStack::class) && class_exists(Package::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->fixXmlConfig('base_url') + ->children() + ->scalarNode('version_strategy')->defaultNull()->end() + ->scalarNode('version')->defaultNull()->end() + ->scalarNode('version_format')->defaultValue('%%s?%%s')->end() + ->scalarNode('json_manifest_path')->defaultNull()->end() + ->scalarNode('base_path')->defaultValue('')->end() + ->arrayNode('base_urls') + ->requiresAtLeastOneElement() + ->beforeNormalization()->castToArray()->end() + ->prototype('scalar')->end() + ->end() + ->end() + ->validate() + ->ifTrue(function ($v) { + return isset($v['version_strategy']) && isset($v['version']); + }) + ->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets".') + ->end() + ->validate() + ->ifTrue(function ($v) { + return isset($v['version_strategy']) && isset($v['json_manifest_path']); + }) + ->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets".') + ->end() + ->validate() + ->ifTrue(function ($v) { + return isset($v['version']) && isset($v['json_manifest_path']); + }) + ->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets".') + ->end() + ->fixXmlConfig('package') + ->children() + ->arrayNode('packages') + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->prototype('array') + ->fixXmlConfig('base_url') + ->children() + ->scalarNode('version_strategy')->defaultNull()->end() + ->scalarNode('version') + ->beforeNormalization() + ->ifTrue(function ($v) { return '' === $v; }) + ->then(function ($v) { return; }) + ->end() + ->end() + ->scalarNode('version_format')->defaultNull()->end() + ->scalarNode('json_manifest_path')->defaultNull()->end() + ->scalarNode('base_path')->defaultValue('')->end() + ->arrayNode('base_urls') + ->requiresAtLeastOneElement() + ->beforeNormalization()->castToArray()->end() + ->prototype('scalar')->end() + ->end() + ->end() + ->validate() + ->ifTrue(function ($v) { + return isset($v['version_strategy']) && isset($v['version']); + }) + ->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets" packages.') + ->end() + ->validate() + ->ifTrue(function ($v) { + return isset($v['version_strategy']) && isset($v['json_manifest_path']); + }) + ->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets" packages.') + ->end() + ->validate() + ->ifTrue(function ($v) { + return isset($v['version']) && isset($v['json_manifest_path']); + }) + ->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets" packages.') + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addTranslatorSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('translator') + ->info('translator configuration') + ->{!class_exists(FullStack::class) && class_exists(Translator::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->fixXmlConfig('fallback') + ->fixXmlConfig('path') + ->children() + ->arrayNode('fallbacks') + ->info('Defaults to the value of "default_locale".') + ->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end() + ->prototype('scalar')->end() + ->defaultValue([]) + ->end() + ->booleanNode('logging')->defaultValue(false)->end() + ->scalarNode('formatter')->defaultValue('translator.formatter.default')->end() + ->scalarNode('cache_dir')->defaultValue('%kernel.cache_dir%/translations')->end() + ->scalarNode('default_path') + ->info('The default path used to load translations') + ->defaultValue('%kernel.project_dir%/translations') + ->end() + ->arrayNode('paths') + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addValidationSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('validation') + ->info('validation configuration') + ->{!class_exists(FullStack::class) && class_exists(Validation::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->children() + ->scalarNode('cache')->end() + ->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && class_exists(Annotation::class) ? 'defaultTrue' : 'defaultFalse'}()->end() + ->arrayNode('static_method') + ->defaultValue(['loadValidatorMetadata']) + ->prototype('scalar')->end() + ->treatFalseLike([]) + ->validate()->castToArray()->end() + ->end() + ->scalarNode('translation_domain')->defaultValue('validators')->end() + ->enumNode('email_validation_mode')->values(['html5', 'loose', 'strict'])->end() + ->arrayNode('mapping') + ->addDefaultsIfNotSet() + ->fixXmlConfig('path') + ->children() + ->arrayNode('paths') + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->arrayNode('not_compromised_password') + ->canBeDisabled() + ->children() + ->booleanNode('enabled') + ->defaultTrue() + ->info('When disabled, compromised passwords will be accepted as valid.') + ->end() + ->scalarNode('endpoint') + ->defaultNull() + ->info('API endpoint for the NotCompromisedPassword Validator.') + ->end() + ->end() + ->end() + ->arrayNode('auto_mapping') + ->info('A collection of namespaces for which auto-mapping will be enabled by default, or null to opt-in with the EnableAutoMapping constraint.') + ->example([ + 'App\\Entity\\' => [], + 'App\\WithSpecificLoaders\\' => ['validator.property_info_loader'], + ]) + ->useAttributeAsKey('namespace') + ->normalizeKeys(false) + ->beforeNormalization() + ->ifArray() + ->then(function (array $values): array { + foreach ($values as $k => $v) { + if (isset($v['service'])) { + continue; + } + + if (isset($v['namespace'])) { + $values[$k]['services'] = []; + continue; + } + + if (!\is_array($v)) { + $values[$v]['services'] = []; + unset($values[$k]); + continue; + } + + $tmp = $v; + unset($values[$k]); + $values[$k]['services'] = $tmp; + } + + return $values; + }) + ->end() + ->arrayPrototype() + ->fixXmlConfig('service') + ->children() + ->arrayNode('services') + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addAnnotationsSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('annotations') + ->info('annotation configuration') + ->{class_exists(Annotation::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->children() + ->scalarNode('cache')->defaultValue(interface_exists(Cache::class) ? 'php_array' : 'none')->end() + ->scalarNode('file_cache_dir')->defaultValue('%kernel.cache_dir%/annotations')->end() + ->booleanNode('debug')->defaultValue($this->debug)->end() + ->end() + ->end() + ->end() + ; + } + + private function addSerializerSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('serializer') + ->info('serializer configuration') + ->{!class_exists(FullStack::class) && class_exists(Serializer::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->children() + ->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && class_exists(Annotation::class) ? 'defaultTrue' : 'defaultFalse'}()->end() + ->scalarNode('name_converter')->end() + ->scalarNode('circular_reference_handler')->end() + ->scalarNode('max_depth_handler')->end() + ->arrayNode('mapping') + ->addDefaultsIfNotSet() + ->fixXmlConfig('path') + ->children() + ->arrayNode('paths') + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addPropertyAccessSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('property_access') + ->addDefaultsIfNotSet() + ->info('Property access configuration') + ->children() + ->booleanNode('magic_call')->defaultFalse()->end() + ->booleanNode('throw_exception_on_invalid_index')->defaultFalse()->end() + ->booleanNode('throw_exception_on_invalid_property_path')->defaultTrue()->end() + ->end() + ->end() + ->end() + ; + } + + private function addPropertyInfoSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('property_info') + ->info('Property info configuration') + ->{!class_exists(FullStack::class) && interface_exists(PropertyInfoExtractorInterface::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->end() + ->end() + ; + } + + private function addCacheSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('cache') + ->info('Cache configuration') + ->addDefaultsIfNotSet() + ->fixXmlConfig('pool') + ->children() + ->scalarNode('prefix_seed') + ->info('Used to namespace cache keys when using several apps with the same shared backend') + ->example('my-application-name') + ->end() + ->scalarNode('app') + ->info('App related cache pools configuration') + ->defaultValue('cache.adapter.filesystem') + ->end() + ->scalarNode('system') + ->info('System related cache pools configuration') + ->defaultValue('cache.adapter.system') + ->end() + ->scalarNode('directory')->defaultValue('%kernel.cache_dir%/pools')->end() + ->scalarNode('default_doctrine_provider')->end() + ->scalarNode('default_psr6_provider')->end() + ->scalarNode('default_redis_provider')->defaultValue('redis://localhost')->end() + ->scalarNode('default_memcached_provider')->defaultValue('memcached://localhost')->end() + ->scalarNode('default_pdo_provider')->defaultValue(class_exists(Connection::class) ? 'database_connection' : null)->end() + ->arrayNode('pools') + ->useAttributeAsKey('name') + ->prototype('array') + ->fixXmlConfig('adapter') + ->beforeNormalization() + ->ifTrue(function ($v) { return (isset($v['adapters']) || \is_array($v['adapter'] ?? null)) && isset($v['provider']); }) + ->thenInvalid('Pool cannot have a "provider" while "adapter" is set to a map') + ->end() + ->children() + ->arrayNode('adapters') + ->performNoDeepMerging() + ->info('One or more adapters to chain for creating the pool, defaults to "cache.app".') + ->beforeNormalization() + ->always()->then(function ($values) { + if ([0] === array_keys($values) && \is_array($values[0])) { + return $values[0]; + } + $adapters = []; + + foreach ($values as $k => $v) { + if (\is_int($k) && \is_string($v)) { + $adapters[] = $v; + } elseif (!\is_array($v)) { + $adapters[$k] = $v; + } elseif (isset($v['provider'])) { + $adapters[$v['provider']] = $v['name'] ?? $v; + } else { + $adapters[] = $v['name'] ?? $v; + } + } + + return $adapters; + }) + ->end() + ->prototype('scalar')->end() + ->end() + ->scalarNode('tags')->defaultNull()->end() + ->booleanNode('public')->defaultFalse()->end() + ->integerNode('default_lifetime')->end() + ->scalarNode('provider') + ->info('Overwrite the setting from the default provider for this adapter.') + ->end() + ->scalarNode('clearer')->end() + ->end() + ->end() + ->validate() + ->ifTrue(function ($v) { return isset($v['cache.app']) || isset($v['cache.system']); }) + ->thenInvalid('"cache.app" and "cache.system" are reserved names') + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addPhpErrorsSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('php_errors') + ->info('PHP errors handling configuration') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('log') + ->info('Use the application logger instead of the PHP logger for logging PHP errors.') + ->example('"true" to use the default configuration: log all errors. "false" to disable. An integer bit field of E_* constants.') + ->defaultValue($this->debug) + ->treatNullLike($this->debug) + ->validate() + ->ifTrue(function ($v) { return !(\is_int($v) || \is_bool($v)); }) + ->thenInvalid('The "php_errors.log" parameter should be either an integer or a boolean.') + ->end() + ->end() + ->booleanNode('throw') + ->info('Throw PHP errors as \ErrorException instances.') + ->defaultValue($this->debug) + ->treatNullLike($this->debug) + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addLockSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('lock') + ->info('Lock configuration') + ->{!class_exists(FullStack::class) && class_exists(Lock::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->beforeNormalization() + ->ifString()->then(function ($v) { return ['enabled' => true, 'resources' => $v]; }) + ->end() + ->beforeNormalization() + ->ifTrue(function ($v) { return \is_array($v) && !isset($v['enabled']); }) + ->then(function ($v) { return $v + ['enabled' => true]; }) + ->end() + ->beforeNormalization() + ->ifTrue(function ($v) { return \is_array($v) && !isset($v['resources']) && !isset($v['resource']); }) + ->then(function ($v) { + $e = $v['enabled']; + unset($v['enabled']); + + return ['enabled' => $e, 'resources' => $v]; + }) + ->end() + ->addDefaultsIfNotSet() + ->fixXmlConfig('resource') + ->children() + ->arrayNode('resources') + ->requiresAtLeastOneElement() + ->defaultValue(['default' => [class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphore' : 'flock']]) + ->beforeNormalization() + ->ifString()->then(function ($v) { return ['default' => $v]; }) + ->end() + ->beforeNormalization() + ->ifTrue(function ($v) { return \is_array($v) && array_keys($v) === range(0, \count($v) - 1); }) + ->then(function ($v) { + $resources = []; + foreach ($v as $resource) { + $resources = array_merge_recursive( + $resources, + \is_array($resource) && isset($resource['name']) + ? [$resource['name'] => $resource['value']] + : ['default' => $resource] + ); + } + + return $resources; + }) + ->end() + ->prototype('array') + ->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end() + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addWebLinkSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('web_link') + ->info('web links configuration') + ->{!class_exists(FullStack::class) && class_exists(HttpHeaderSerializer::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->end() + ->end() + ; + } + + private function addMessengerSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('messenger') + ->info('Messenger configuration') + ->{!class_exists(FullStack::class) && interface_exists(MessageBusInterface::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->fixXmlConfig('transport') + ->fixXmlConfig('bus', 'buses') + ->validate() + ->ifTrue(function ($v) { return isset($v['buses']) && \count($v['buses']) > 1 && null === $v['default_bus']; }) + ->thenInvalid('You must specify the "default_bus" if you define more than one bus.') + ->end() + ->validate() + ->ifTrue(static function ($v): bool { return isset($v['buses']) && null !== $v['default_bus'] && !isset($v['buses'][$v['default_bus']]); }) + ->then(static function (array $v): void { throw new InvalidConfigurationException(sprintf('The specified default bus "%s" is not configured. Available buses are "%s".', $v['default_bus'], implode('", "', array_keys($v['buses'])))); }) + ->end() + ->children() + ->arrayNode('routing') + ->normalizeKeys(false) + ->useAttributeAsKey('message_class') + ->beforeNormalization() + ->always() + ->then(function ($config) { + if (!\is_array($config)) { + return []; + } + + $newConfig = []; + foreach ($config as $k => $v) { + if (!\is_int($k)) { + $newConfig[$k] = [ + 'senders' => $v['senders'] ?? (\is_array($v) ? array_values($v) : [$v]), + ]; + } else { + $newConfig[$v['message-class']]['senders'] = array_map( + function ($a) { + return \is_string($a) ? $a : $a['service']; + }, + array_values($v['sender']) + ); + } + } + + return $newConfig; + }) + ->end() + ->prototype('array') + ->performNoDeepMerging() + ->children() + ->arrayNode('senders') + ->requiresAtLeastOneElement() + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() + ->arrayNode('serializer') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('default_serializer') + ->defaultValue('messenger.transport.native_php_serializer') + ->info('Service id to use as the default serializer for the transports.') + ->end() + ->arrayNode('symfony_serializer') + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('format')->defaultValue('json')->info('Serialization format for the messenger.transport.symfony_serializer service (which is not the serializer used by default).')->end() + ->arrayNode('context') + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->defaultValue([]) + ->info('Context array for the messenger.transport.symfony_serializer service (which is not the serializer used by default).') + ->prototype('variable')->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->arrayNode('transports') + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->arrayPrototype() + ->beforeNormalization() + ->ifString() + ->then(function (string $dsn) { + return ['dsn' => $dsn]; + }) + ->end() + ->fixXmlConfig('option') + ->children() + ->scalarNode('dsn')->end() + ->scalarNode('serializer')->defaultNull()->info('Service id of a custom serializer to use.')->end() + ->arrayNode('options') + ->normalizeKeys(false) + ->defaultValue([]) + ->prototype('variable') + ->end() + ->end() + ->arrayNode('retry_strategy') + ->addDefaultsIfNotSet() + ->beforeNormalization() + ->always(function ($v) { + if (isset($v['service']) && (isset($v['max_retries']) || isset($v['delay']) || isset($v['multiplier']) || isset($v['max_delay']))) { + throw new \InvalidArgumentException('The "service" cannot be used along with the other "retry_strategy" options.'); + } + + return $v; + }) + ->end() + ->children() + ->scalarNode('service')->defaultNull()->info('Service id to override the retry strategy entirely')->end() + ->integerNode('max_retries')->defaultValue(3)->min(0)->end() + ->integerNode('delay')->defaultValue(1000)->min(0)->info('Time in ms to delay (or the initial value when multiplier is used)')->end() + ->floatNode('multiplier')->defaultValue(2)->min(1)->info('If greater than 1, delay will grow exponentially for each retry: this delay = (delay * (multiple ^ retries))')->end() + ->integerNode('max_delay')->defaultValue(0)->min(0)->info('Max time in ms that a retry should ever be delayed (0 = infinite)')->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->scalarNode('failure_transport') + ->defaultNull() + ->info('Transport name to send failed messages to (after all retries have failed).') + ->end() + ->scalarNode('default_bus')->defaultNull()->end() + ->arrayNode('buses') + ->defaultValue(['messenger.bus.default' => ['default_middleware' => true, 'middleware' => []]]) + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->arrayPrototype() + ->addDefaultsIfNotSet() + ->children() + ->enumNode('default_middleware') + ->values([true, false, 'allow_no_handlers']) + ->defaultTrue() + ->end() + ->arrayNode('middleware') + ->performNoDeepMerging() + ->beforeNormalization() + ->ifTrue(function ($v) { return \is_string($v) || (\is_array($v) && !\is_int(key($v))); }) + ->then(function ($v) { return [$v]; }) + ->end() + ->defaultValue([]) + ->arrayPrototype() + ->beforeNormalization() + ->always() + ->then(function ($middleware): array { + if (!\is_array($middleware)) { + return ['id' => $middleware]; + } + if (isset($middleware['id'])) { + return $middleware; + } + if (1 < \count($middleware)) { + throw new \InvalidArgumentException(sprintf('Invalid middleware at path "framework.messenger": a map with a single factory id as key and its arguments as value was expected, %s given.', json_encode($middleware))); + } + + return [ + 'id' => key($middleware), + 'arguments' => current($middleware), + ]; + }) + ->end() + ->fixXmlConfig('argument') + ->children() + ->scalarNode('id')->isRequired()->cannotBeEmpty()->end() + ->arrayNode('arguments') + ->normalizeKeys(false) + ->defaultValue([]) + ->prototype('variable') + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addRobotsIndexSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->booleanNode('disallow_search_engine_index') + ->info('Enabled by default when debug is enabled.') + ->defaultValue($this->debug) + ->treatNullLike($this->debug) + ->end() + ->end() + ; + } + + private function addHttpClientSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('http_client') + ->info('HTTP Client configuration') + ->{!class_exists(FullStack::class) && class_exists(HttpClient::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->fixXmlConfig('scoped_client') + ->children() + ->integerNode('max_host_connections') + ->info('The maximum number of connections to a single host.') + ->end() + ->arrayNode('default_options') + ->fixXmlConfig('header') + ->children() + ->arrayNode('headers') + ->info('Associative array: header => value(s).') + ->useAttributeAsKey('name') + ->normalizeKeys(false) + ->variablePrototype()->end() + ->end() + ->integerNode('max_redirects') + ->info('The maximum number of redirects to follow.') + ->end() + ->scalarNode('http_version') + ->info('The default HTTP version, typically 1.1 or 2.0, leave to null for the best version.') + ->end() + ->arrayNode('resolve') + ->info('Associative array: domain => IP.') + ->useAttributeAsKey('host') + ->beforeNormalization() + ->always(function ($config) { + if (!\is_array($config)) { + return []; + } + if (!isset($config['host'])) { + return $config; + } + + return [$config['host'] => $config['value']]; + }) + ->end() + ->normalizeKeys(false) + ->scalarPrototype()->end() + ->end() + ->scalarNode('proxy') + ->info('The URL of the proxy to pass requests through or null for automatic detection.') + ->end() + ->scalarNode('no_proxy') + ->info('A comma separated list of hosts that do not require a proxy to be reached.') + ->end() + ->floatNode('timeout') + ->info('The idle timeout, defaults to the "default_socket_timeout" ini parameter.') + ->end() + ->floatNode('max_duration') + ->info('The maximum execution time for the request+response as a whole.') + ->end() + ->scalarNode('bindto') + ->info('A network interface name, IP address, a host name or a UNIX socket to bind to.') + ->end() + ->booleanNode('verify_peer') + ->info('Indicates if the peer should be verified in a SSL/TLS context.') + ->end() + ->booleanNode('verify_host') + ->info('Indicates if the host should exist as a certificate common name.') + ->end() + ->scalarNode('cafile') + ->info('A certificate authority file.') + ->end() + ->scalarNode('capath') + ->info('A directory that contains multiple certificate authority files.') + ->end() + ->scalarNode('local_cert') + ->info('A PEM formatted certificate file.') + ->end() + ->scalarNode('local_pk') + ->info('A private key file.') + ->end() + ->scalarNode('passphrase') + ->info('The passphrase used to encrypt the "local_pk" file.') + ->end() + ->scalarNode('ciphers') + ->info('A list of SSL/TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...)') + ->end() + ->arrayNode('peer_fingerprint') + ->info('Associative array: hashing algorithm => hash(es).') + ->normalizeKeys(false) + ->children() + ->variableNode('sha1')->end() + ->variableNode('pin-sha256')->end() + ->variableNode('md5')->end() + ->end() + ->end() + ->end() + ->end() + ->arrayNode('scoped_clients') + ->useAttributeAsKey('name') + ->normalizeKeys(false) + ->arrayPrototype() + ->fixXmlConfig('header') + ->beforeNormalization() + ->always() + ->then(function ($config) { + if (!class_exists(HttpClient::class)) { + throw new LogicException('HttpClient support cannot be enabled as the component is not installed. Try running "composer require symfony/http-client".'); + } + + return \is_array($config) ? $config : ['base_uri' => $config]; + }) + ->end() + ->validate() + ->ifTrue(function ($v) { return !isset($v['scope']) && !isset($v['base_uri']); }) + ->thenInvalid('Either "scope" or "base_uri" should be defined.') + ->end() + ->validate() + ->ifTrue(function ($v) { return isset($v['query']) && !isset($v['base_uri']); }) + ->thenInvalid('"query" applies to "base_uri" but no base URI is defined.') + ->end() + ->children() + ->scalarNode('scope') + ->info('The regular expression that the request URL must match before adding the other options. When none is provided, the base URI is used instead.') + ->cannotBeEmpty() + ->end() + ->scalarNode('base_uri') + ->info('The URI to resolve relative URLs, following rules in RFC 3985, section 2.') + ->cannotBeEmpty() + ->end() + ->scalarNode('auth_basic') + ->info('An HTTP Basic authentication "username:password".') + ->end() + ->scalarNode('auth_bearer') + ->info('A token enabling HTTP Bearer authorization.') + ->end() + ->scalarNode('auth_ntlm') + ->info('A "username:password" pair to use Microsoft NTLM authentication (requires the cURL extension).') + ->end() + ->arrayNode('query') + ->info('Associative array of query string values merged with the base URI.') + ->useAttributeAsKey('key') + ->beforeNormalization() + ->always(function ($config) { + if (!\is_array($config)) { + return []; + } + if (!isset($config['key'])) { + return $config; + } + + return [$config['key'] => $config['value']]; + }) + ->end() + ->normalizeKeys(false) + ->scalarPrototype()->end() + ->end() + ->arrayNode('headers') + ->info('Associative array: header => value(s).') + ->useAttributeAsKey('name') + ->normalizeKeys(false) + ->variablePrototype()->end() + ->end() + ->integerNode('max_redirects') + ->info('The maximum number of redirects to follow.') + ->end() + ->scalarNode('http_version') + ->info('The default HTTP version, typically 1.1 or 2.0, leave to null for the best version.') + ->end() + ->arrayNode('resolve') + ->info('Associative array: domain => IP.') + ->useAttributeAsKey('host') + ->beforeNormalization() + ->always(function ($config) { + if (!\is_array($config)) { + return []; + } + if (!isset($config['host'])) { + return $config; + } + + return [$config['host'] => $config['value']]; + }) + ->end() + ->normalizeKeys(false) + ->scalarPrototype()->end() + ->end() + ->scalarNode('proxy') + ->info('The URL of the proxy to pass requests through or null for automatic detection.') + ->end() + ->scalarNode('no_proxy') + ->info('A comma separated list of hosts that do not require a proxy to be reached.') + ->end() + ->floatNode('timeout') + ->info('The idle timeout, defaults to the "default_socket_timeout" ini parameter.') + ->end() + ->floatNode('max_duration') + ->info('The maximum execution time for the request+response as a whole.') + ->end() + ->scalarNode('bindto') + ->info('A network interface name, IP address, a host name or a UNIX socket to bind to.') + ->end() + ->booleanNode('verify_peer') + ->info('Indicates if the peer should be verified in a SSL/TLS context.') + ->end() + ->booleanNode('verify_host') + ->info('Indicates if the host should exist as a certificate common name.') + ->end() + ->scalarNode('cafile') + ->info('A certificate authority file.') + ->end() + ->scalarNode('capath') + ->info('A directory that contains multiple certificate authority files.') + ->end() + ->scalarNode('local_cert') + ->info('A PEM formatted certificate file.') + ->end() + ->scalarNode('local_pk') + ->info('A private key file.') + ->end() + ->scalarNode('passphrase') + ->info('The passphrase used to encrypt the "local_pk" file.') + ->end() + ->scalarNode('ciphers') + ->info('A list of SSL/TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...)') + ->end() + ->arrayNode('peer_fingerprint') + ->info('Associative array: hashing algorithm => hash(es).') + ->normalizeKeys(false) + ->children() + ->variableNode('sha1')->end() + ->variableNode('pin-sha256')->end() + ->variableNode('md5')->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addMailerSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('mailer') + ->info('Mailer configuration') + ->{!class_exists(FullStack::class) && class_exists(Mailer::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->validate() + ->ifTrue(function ($v) { return isset($v['dsn']) && \count($v['transports']); }) + ->thenInvalid('"dsn" and "transports" cannot be used together.') + ->end() + ->fixXmlConfig('transport') + ->children() + ->scalarNode('dsn')->defaultNull()->end() + ->arrayNode('transports') + ->useAttributeAsKey('name') + ->prototype('scalar')->end() + ->end() + ->arrayNode('envelope') + ->info('Mailer Envelope configuration') + ->children() + ->scalarNode('sender')->end() + ->arrayNode('recipients') + ->performNoDeepMerging() + ->beforeNormalization() + ->ifArray() + ->then(function ($v) { + return array_filter(array_values($v)); + }) + ->end() + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } + + private function addNotifierSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('notifier') + ->info('Notifier configuration') + ->{!class_exists(FullStack::class) && class_exists(Notifier::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->fixXmlConfig('chatter_transport') + ->children() + ->arrayNode('chatter_transports') + ->useAttributeAsKey('name') + ->prototype('scalar')->end() + ->end() + ->end() + ->fixXmlConfig('texter_transport') + ->children() + ->arrayNode('texter_transports') + ->useAttributeAsKey('name') + ->prototype('scalar')->end() + ->end() + ->end() + ->children() + ->booleanNode('notification_on_failed_messages')->defaultFalse()->end() + ->end() + ->children() + ->arrayNode('channel_policy') + ->useAttributeAsKey('name') + ->prototype('array') + ->beforeNormalization()->ifString()->then(function (string $v) { return [$v]; })->end() + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->fixXmlConfig('admin_recipient') + ->children() + ->arrayNode('admin_recipients') + ->prototype('array') + ->children() + ->scalarNode('email')->cannotBeEmpty()->end() + ->scalarNode('phone')->defaultValue('')->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } +} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php b/vendor/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php new file mode 100644 index 0000000..8f1b86b --- /dev/null +++ b/vendor/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php @@ -0,0 +1,1989 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; + +use Doctrine\Common\Annotations\AnnotationRegistry; +use Doctrine\Common\Annotations\Reader; +use Http\Client\HttpClient; +use Psr\Cache\CacheItemPoolInterface; +use Psr\Container\ContainerInterface as PsrContainerInterface; +use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface; +use Psr\Http\Client\ClientInterface; +use Psr\Log\LoggerAwareInterface; +use Symfony\Bridge\Monolog\Processor\DebugProcessor; +use Symfony\Bridge\Twig\Extension\CsrfExtension; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader; +use Symfony\Bundle\FrameworkBundle\Routing\RouteLoaderInterface; +use Symfony\Bundle\FullStack; +use Symfony\Component\Asset\PackageInterface; +use Symfony\Component\BrowserKit\AbstractBrowser; +use Symfony\Component\Cache\Adapter\AdapterInterface; +use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Cache\Adapter\ChainAdapter; +use Symfony\Component\Cache\Adapter\TagAwareAdapter; +use Symfony\Component\Cache\DependencyInjection\CachePoolPass; +use Symfony\Component\Cache\Marshaller\DefaultMarshaller; +use Symfony\Component\Cache\Marshaller\MarshallerInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\Config\Resource\DirectoryResource; +use Symfony\Component\Config\ResourceCheckerInterface; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\EnvVarLoaderInterface; +use Symfony\Component\DependencyInjection\EnvVarProcessorInterface; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\LogicException; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\Parameter; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ServiceLocator; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; +use Symfony\Component\Finder\Finder; +use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator; +use Symfony\Component\Form\FormTypeExtensionInterface; +use Symfony\Component\Form\FormTypeGuesserInterface; +use Symfony\Component\Form\FormTypeInterface; +use Symfony\Component\HttpClient\ScopingHttpClient; +use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; +use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; +use Symfony\Component\Lock\Lock; +use Symfony\Component\Lock\LockFactory; +use Symfony\Component\Lock\LockInterface; +use Symfony\Component\Lock\PersistingStoreInterface; +use Symfony\Component\Lock\Store\StoreFactory; +use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesTransportFactory; +use Symfony\Component\Mailer\Bridge\Google\Transport\GmailTransportFactory; +use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; +use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; +use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; +use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; +use Symfony\Component\Mailer\Mailer; +use Symfony\Component\Messenger\Handler\MessageHandlerInterface; +use Symfony\Component\Messenger\MessageBus; +use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Messenger\Transport\TransportFactoryInterface; +use Symfony\Component\Messenger\Transport\TransportInterface; +use Symfony\Component\Mime\MimeTypeGuesserInterface; +use Symfony\Component\Mime\MimeTypes; +use Symfony\Component\Notifier\Bridge\Nexmo\NexmoTransportFactory; +use Symfony\Component\Notifier\Bridge\Slack\SlackTransportFactory; +use Symfony\Component\Notifier\Bridge\Telegram\TelegramTransportFactory; +use Symfony\Component\Notifier\Bridge\Twilio\TwilioTransportFactory; +use Symfony\Component\Notifier\Notifier; +use Symfony\Component\Notifier\Recipient\AdminRecipient; +use Symfony\Component\PropertyAccess\PropertyAccessor; +use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; +use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; +use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; +use Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface; +use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; +use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; +use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader; +use Symfony\Component\Routing\Loader\AnnotationFileLoader; +use Symfony\Component\Security\Core\Security; +use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Serializer\Encoder\DecoderInterface; +use Symfony\Component\Serializer\Encoder\EncoderInterface; +use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; +use Symfony\Component\Serializer\Normalizer\NormalizerInterface; +use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\String\Slugger\SluggerInterface; +use Symfony\Component\Translation\Command\XliffLintCommand as BaseXliffLintCommand; +use Symfony\Component\Translation\Translator; +use Symfony\Component\Validator\ConstraintValidatorInterface; +use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader; +use Symfony\Component\Validator\ObjectInitializerInterface; +use Symfony\Component\WebLink\HttpHeaderSerializer; +use Symfony\Component\Workflow; +use Symfony\Component\Workflow\WorkflowInterface; +use Symfony\Component\Yaml\Command\LintCommand as BaseYamlLintCommand; +use Symfony\Component\Yaml\Yaml; +use Symfony\Contracts\Cache\CacheInterface; +use Symfony\Contracts\Cache\TagAwareCacheInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; +use Symfony\Contracts\Service\ResetInterface; +use Symfony\Contracts\Service\ServiceSubscriberInterface; +use Symfony\Contracts\Translation\LocaleAwareInterface; + +/** + * FrameworkExtension. + * + * @author Fabien Potencier + * @author Jeremy Mikola + * @author Kévin Dunglas + * @author Grégoire Pineau + */ +class FrameworkExtension extends Extension +{ + private $formConfigEnabled = false; + private $translationConfigEnabled = false; + private $sessionConfigEnabled = false; + private $annotationsConfigEnabled = false; + private $validatorConfigEnabled = false; + private $messengerConfigEnabled = false; + private $mailerConfigEnabled = false; + private $httpClientConfigEnabled = false; + + /** + * Responds to the app.config configuration parameter. + * + * @throws LogicException + */ + public function load(array $configs, ContainerBuilder $container) + { + $loader = new XmlFileLoader($container, new FileLocator(\dirname(__DIR__).'/Resources/config')); + + $loader->load('web.xml'); + $loader->load('services.xml'); + $loader->load('fragment_renderer.xml'); + $loader->load('error_renderer.xml'); + + if (interface_exists(PsrEventDispatcherInterface::class)) { + $container->setAlias(PsrEventDispatcherInterface::class, 'event_dispatcher'); + } + + $container->registerAliasForArgument('parameter_bag', PsrContainerInterface::class); + + if (class_exists(Application::class)) { + $loader->load('console.xml'); + + if (!class_exists(BaseXliffLintCommand::class)) { + $container->removeDefinition('console.command.xliff_lint'); + } + if (!class_exists(BaseYamlLintCommand::class)) { + $container->removeDefinition('console.command.yaml_lint'); + } + } + + // Load Cache configuration first as it is used by other components + $loader->load('cache.xml'); + + $configuration = $this->getConfiguration($configs, $container); + $config = $this->processConfiguration($configuration, $configs); + + $this->annotationsConfigEnabled = $this->isConfigEnabled($container, $config['annotations']); + $this->translationConfigEnabled = $this->isConfigEnabled($container, $config['translator']); + + // A translator must always be registered (as support is included by + // default in the Form and Validator component). If disabled, an identity + // translator will be used and everything will still work as expected. + if ($this->isConfigEnabled($container, $config['translator']) || $this->isConfigEnabled($container, $config['form']) || $this->isConfigEnabled($container, $config['validation'])) { + if (!class_exists('Symfony\Component\Translation\Translator') && $this->isConfigEnabled($container, $config['translator'])) { + throw new LogicException('Translation support cannot be enabled as the Translation component is not installed. Try running "composer require symfony/translation".'); + } + + if (class_exists(Translator::class)) { + $loader->load('identity_translator.xml'); + } + } + + // If the slugger is used but the String component is not available, we should throw an error + if (!interface_exists(SluggerInterface::class)) { + $container->register('slugger', 'stdClass') + ->addError('You cannot use the "slugger" service since the String component is not installed. Try running "composer require symfony/string".'); + } else { + if (!interface_exists(LocaleAwareInterface::class)) { + $container->register('slugger', 'stdClass') + ->addError('You cannot use the "slugger" service since the Translation contracts are not installed. Try running "composer require symfony/translation".'); + } + + if (!\extension_loaded('intl') && !\defined('PHPUNIT_COMPOSER_INSTALL')) { + @trigger_error('Please install the "intl" PHP extension for best performance.', E_USER_DEPRECATED); + } + } + + if (isset($config['secret'])) { + $container->setParameter('kernel.secret', $config['secret']); + } + + $container->setParameter('kernel.http_method_override', $config['http_method_override']); + $container->setParameter('kernel.trusted_hosts', $config['trusted_hosts']); + $container->setParameter('kernel.default_locale', $config['default_locale']); + $container->setParameter('kernel.error_controller', $config['error_controller']); + + if (!$container->hasParameter('debug.file_link_format')) { + $links = [ + 'textmate' => 'txmt://open?url=file://%%f&line=%%l', + 'macvim' => 'mvim://open?url=file://%%f&line=%%l', + 'emacs' => 'emacs://open?url=file://%%f&line=%%l', + 'sublime' => 'subl://open?url=file://%%f&line=%%l', + 'phpstorm' => 'phpstorm://open?file=%%f&line=%%l', + 'atom' => 'atom://core/open/file?filename=%%f&line=%%l', + 'vscode' => 'vscode://file/%%f:%%l', + ]; + $ide = $config['ide']; + // mark any env vars found in the ide setting as used + $container->resolveEnvPlaceholders($ide); + + $container->setParameter('debug.file_link_format', str_replace('%', '%%', ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) ?: (isset($links[$ide]) ? $links[$ide] : $ide)); + } + + if (!empty($config['test'])) { + $loader->load('test.xml'); + + if (!class_exists(AbstractBrowser::class)) { + $container->removeDefinition('test.client'); + } + } + + // register cache before session so both can share the connection services + $this->registerCacheConfiguration($config['cache'], $container); + + if ($this->isConfigEnabled($container, $config['session'])) { + if (!\extension_loaded('session')) { + throw new LogicException('Session support cannot be enabled as the session extension is not installed. See https://php.net/session.installation for instructions.'); + } + + $this->sessionConfigEnabled = true; + $this->registerSessionConfiguration($config['session'], $container, $loader); + if (!empty($config['test'])) { + $container->getDefinition('test.session.listener')->setArgument(1, '%session.storage.options%'); + } + } + + if ($this->isConfigEnabled($container, $config['request'])) { + $this->registerRequestConfiguration($config['request'], $container, $loader); + } + + if (null === $config['csrf_protection']['enabled']) { + $config['csrf_protection']['enabled'] = $this->sessionConfigEnabled && !class_exists(FullStack::class) && interface_exists(CsrfTokenManagerInterface::class); + } + $this->registerSecurityCsrfConfiguration($config['csrf_protection'], $container, $loader); + + if ($this->isConfigEnabled($container, $config['form'])) { + if (!class_exists('Symfony\Component\Form\Form')) { + throw new LogicException('Form support cannot be enabled as the Form component is not installed. Try running "composer require symfony/form".'); + } + + $this->formConfigEnabled = true; + $this->registerFormConfiguration($config, $container, $loader); + + if (class_exists('Symfony\Component\Validator\Validation')) { + $config['validation']['enabled'] = true; + } else { + $container->setParameter('validator.translation_domain', 'validators'); + + $container->removeDefinition('form.type_extension.form.validator'); + $container->removeDefinition('form.type_guesser.validator'); + } + } else { + $container->removeDefinition('console.command.form_debug'); + } + + if ($this->isConfigEnabled($container, $config['assets'])) { + if (!class_exists('Symfony\Component\Asset\Package')) { + throw new LogicException('Asset support cannot be enabled as the Asset component is not installed. Try running "composer require symfony/asset".'); + } + + $this->registerAssetsConfiguration($config['assets'], $container, $loader); + } + + if ($this->messengerConfigEnabled = $this->isConfigEnabled($container, $config['messenger'])) { + $this->registerMessengerConfiguration($config['messenger'], $container, $loader, $config['validation']); + } else { + $container->removeDefinition('console.command.messenger_consume_messages'); + $container->removeDefinition('console.command.messenger_debug'); + $container->removeDefinition('console.command.messenger_stop_workers'); + $container->removeDefinition('console.command.messenger_setup_transports'); + $container->removeDefinition('console.command.messenger_failed_messages_retry'); + $container->removeDefinition('console.command.messenger_failed_messages_show'); + $container->removeDefinition('console.command.messenger_failed_messages_remove'); + } + + if ($this->httpClientConfigEnabled = $this->isConfigEnabled($container, $config['http_client'])) { + $this->registerHttpClientConfiguration($config['http_client'], $container, $loader, $config['profiler']); + } + + if ($this->mailerConfigEnabled = $this->isConfigEnabled($container, $config['mailer'])) { + $this->registerMailerConfiguration($config['mailer'], $container, $loader); + } + + if ($this->isConfigEnabled($container, $config['notifier'])) { + $this->registerNotifierConfiguration($config['notifier'], $container, $loader); + } + + $propertyInfoEnabled = $this->isConfigEnabled($container, $config['property_info']); + $this->registerValidationConfiguration($config['validation'], $container, $loader, $propertyInfoEnabled); + $this->registerEsiConfiguration($config['esi'], $container, $loader); + $this->registerSsiConfiguration($config['ssi'], $container, $loader); + $this->registerFragmentsConfiguration($config['fragments'], $container, $loader); + $this->registerTranslatorConfiguration($config['translator'], $container, $loader, $config['default_locale']); + $this->registerProfilerConfiguration($config['profiler'], $container, $loader); + $this->registerWorkflowConfiguration($config['workflows'], $container, $loader); + $this->registerDebugConfiguration($config['php_errors'], $container, $loader); + $this->registerRouterConfiguration($config['router'], $container, $loader); + $this->registerAnnotationsConfiguration($config['annotations'], $container, $loader); + $this->registerPropertyAccessConfiguration($config['property_access'], $container, $loader); + $this->registerSecretsConfiguration($config['secrets'], $container, $loader); + + if ($this->isConfigEnabled($container, $config['serializer'])) { + if (!class_exists('Symfony\Component\Serializer\Serializer')) { + throw new LogicException('Serializer support cannot be enabled as the Serializer component is not installed. Try running "composer require symfony/serializer-pack".'); + } + + $this->registerSerializerConfiguration($config['serializer'], $container, $loader); + } + + if ($propertyInfoEnabled) { + $this->registerPropertyInfoConfiguration($container, $loader); + } + + if ($this->isConfigEnabled($container, $config['lock'])) { + $this->registerLockConfiguration($config['lock'], $container, $loader); + } + + if ($this->isConfigEnabled($container, $config['web_link'])) { + if (!class_exists(HttpHeaderSerializer::class)) { + throw new LogicException('WebLink support cannot be enabled as the WebLink component is not installed. Try running "composer require symfony/weblink".'); + } + + $loader->load('web_link.xml'); + } + + $this->addAnnotatedClassesToCompile([ + '**\\Controller\\', + '**\\Entity\\', + + // Added explicitly so that we don't rely on the class map being dumped to make it work + 'Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController', + ]); + + if (class_exists(MimeTypes::class)) { + $loader->load('mime_type.xml'); + } + + $container->registerForAutoconfiguration(Command::class) + ->addTag('console.command'); + $container->registerForAutoconfiguration(ResourceCheckerInterface::class) + ->addTag('config_cache.resource_checker'); + $container->registerForAutoconfiguration(EnvVarLoaderInterface::class) + ->addTag('container.env_var_loader'); + $container->registerForAutoconfiguration(EnvVarProcessorInterface::class) + ->addTag('container.env_var_processor'); + $container->registerForAutoconfiguration(ServiceLocator::class) + ->addTag('container.service_locator'); + $container->registerForAutoconfiguration(ServiceSubscriberInterface::class) + ->addTag('container.service_subscriber'); + $container->registerForAutoconfiguration(ArgumentValueResolverInterface::class) + ->addTag('controller.argument_value_resolver'); + $container->registerForAutoconfiguration(AbstractController::class) + ->addTag('controller.service_arguments'); + $container->registerForAutoconfiguration('Symfony\Bundle\FrameworkBundle\Controller\Controller') + ->addTag('controller.service_arguments'); + $container->registerForAutoconfiguration(DataCollectorInterface::class) + ->addTag('data_collector'); + $container->registerForAutoconfiguration(FormTypeInterface::class) + ->addTag('form.type'); + $container->registerForAutoconfiguration(FormTypeGuesserInterface::class) + ->addTag('form.type_guesser'); + $container->registerForAutoconfiguration(FormTypeExtensionInterface::class) + ->addTag('form.type_extension'); + $container->registerForAutoconfiguration(CacheClearerInterface::class) + ->addTag('kernel.cache_clearer'); + $container->registerForAutoconfiguration(CacheWarmerInterface::class) + ->addTag('kernel.cache_warmer'); + $container->registerForAutoconfiguration(EventSubscriberInterface::class) + ->addTag('kernel.event_subscriber'); + $container->registerForAutoconfiguration(LocaleAwareInterface::class) + ->addTag('kernel.locale_aware'); + $container->registerForAutoconfiguration(ResetInterface::class) + ->addTag('kernel.reset', ['method' => 'reset']); + + if (!interface_exists(MarshallerInterface::class)) { + $container->registerForAutoconfiguration(ResettableInterface::class) + ->addTag('kernel.reset', ['method' => 'reset']); + } + + $container->registerForAutoconfiguration(PropertyListExtractorInterface::class) + ->addTag('property_info.list_extractor'); + $container->registerForAutoconfiguration(PropertyTypeExtractorInterface::class) + ->addTag('property_info.type_extractor'); + $container->registerForAutoconfiguration(PropertyDescriptionExtractorInterface::class) + ->addTag('property_info.description_extractor'); + $container->registerForAutoconfiguration(PropertyAccessExtractorInterface::class) + ->addTag('property_info.access_extractor'); + $container->registerForAutoconfiguration(PropertyInitializableExtractorInterface::class) + ->addTag('property_info.initializable_extractor'); + $container->registerForAutoconfiguration(EncoderInterface::class) + ->addTag('serializer.encoder'); + $container->registerForAutoconfiguration(DecoderInterface::class) + ->addTag('serializer.encoder'); + $container->registerForAutoconfiguration(NormalizerInterface::class) + ->addTag('serializer.normalizer'); + $container->registerForAutoconfiguration(DenormalizerInterface::class) + ->addTag('serializer.normalizer'); + $container->registerForAutoconfiguration(ConstraintValidatorInterface::class) + ->addTag('validator.constraint_validator'); + $container->registerForAutoconfiguration(ObjectInitializerInterface::class) + ->addTag('validator.initializer'); + $container->registerForAutoconfiguration(MessageHandlerInterface::class) + ->addTag('messenger.message_handler'); + $container->registerForAutoconfiguration(TransportFactoryInterface::class) + ->addTag('messenger.transport_factory'); + $container->registerForAutoconfiguration(MimeTypeGuesserInterface::class) + ->addTag('mime.mime_type_guesser'); + $container->registerForAutoconfiguration(LoggerAwareInterface::class) + ->addMethodCall('setLogger', [new Reference('logger')]); + + if (!$container->getParameter('kernel.debug')) { + // remove tagged iterator argument for resource checkers + $container->getDefinition('config_cache_factory')->setArguments([]); + } + + if (!$config['disallow_search_engine_index'] ?? false) { + $container->removeDefinition('disallow_search_engine_index_response_listener'); + } + + $container->registerForAutoconfiguration(RouteLoaderInterface::class) + ->addTag('routing.route_loader'); + } + + /** + * {@inheritdoc} + */ + public function getConfiguration(array $config, ContainerBuilder $container) + { + return new Configuration($container->getParameter('kernel.debug')); + } + + private function registerFormConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + $loader->load('form.xml'); + + if (null === $config['form']['csrf_protection']['enabled']) { + $config['form']['csrf_protection']['enabled'] = $config['csrf_protection']['enabled']; + } + + if ($this->isConfigEnabled($container, $config['form']['csrf_protection'])) { + $loader->load('form_csrf.xml'); + + $container->setParameter('form.type_extension.csrf.enabled', true); + $container->setParameter('form.type_extension.csrf.field_name', $config['form']['csrf_protection']['field_name']); + } else { + $container->setParameter('form.type_extension.csrf.enabled', false); + } + + if (!class_exists(Translator::class)) { + $container->removeDefinition('form.type_extension.upload.validator'); + } + if (!method_exists(CachingFactoryDecorator::class, 'reset')) { + $container->getDefinition('form.choice_list_factory.cached') + ->clearTag('kernel.reset') + ; + } + } + + private function registerEsiConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + if (!$this->isConfigEnabled($container, $config)) { + $container->removeDefinition('fragment.renderer.esi'); + + return; + } + + $loader->load('esi.xml'); + } + + private function registerSsiConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + if (!$this->isConfigEnabled($container, $config)) { + $container->removeDefinition('fragment.renderer.ssi'); + + return; + } + + $loader->load('ssi.xml'); + } + + private function registerFragmentsConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + if (!$this->isConfigEnabled($container, $config)) { + $container->removeDefinition('fragment.renderer.hinclude'); + + return; + } + + $container->setParameter('fragment.renderer.hinclude.global_template', $config['hinclude_default_template']); + + $loader->load('fragment_listener.xml'); + $container->setParameter('fragment.path', $config['path']); + } + + private function registerProfilerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + if (!$this->isConfigEnabled($container, $config)) { + // this is needed for the WebProfiler to work even if the profiler is disabled + $container->setParameter('data_collector.templates', []); + + return; + } + + $loader->load('profiling.xml'); + $loader->load('collectors.xml'); + $loader->load('cache_debug.xml'); + + if ($this->formConfigEnabled) { + $loader->load('form_debug.xml'); + } + + if ($this->validatorConfigEnabled) { + $loader->load('validator_debug.xml'); + } + + if ($this->translationConfigEnabled) { + $loader->load('translation_debug.xml'); + + $container->getDefinition('translator.data_collector')->setDecoratedService('translator'); + } + + if ($this->messengerConfigEnabled) { + $loader->load('messenger_debug.xml'); + } + + if ($this->mailerConfigEnabled) { + $loader->load('mailer_debug.xml'); + } + + if ($this->httpClientConfigEnabled) { + $loader->load('http_client_debug.xml'); + } + + $container->setParameter('profiler_listener.only_exceptions', $config['only_exceptions']); + $container->setParameter('profiler_listener.only_master_requests', $config['only_master_requests']); + + // Choose storage class based on the DSN + list($class) = explode(':', $config['dsn'], 2); + if ('file' !== $class) { + throw new \LogicException(sprintf('Driver "%s" is not supported for the profiler.', $class)); + } + + $container->setParameter('profiler.storage.dsn', $config['dsn']); + + $container->getDefinition('profiler') + ->addArgument($config['collect']) + ->addTag('kernel.reset', ['method' => 'reset']); + } + + private function registerWorkflowConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + if (!$config['enabled']) { + $container->removeDefinition('console.command.workflow_dump'); + + return; + } + + if (!class_exists(Workflow\Workflow::class)) { + throw new LogicException('Workflow support cannot be enabled as the Workflow component is not installed. Try running "composer require symfony/workflow".'); + } + + $loader->load('workflow.xml'); + + $registryDefinition = $container->getDefinition('workflow.registry'); + + foreach ($config['workflows'] as $name => $workflow) { + $type = $workflow['type']; + $workflowId = sprintf('%s.%s', $type, $name); + + // Process Metadata (workflow + places (transition is done in the "create transition" block)) + $metadataStoreDefinition = new Definition(Workflow\Metadata\InMemoryMetadataStore::class, [[], [], null]); + if ($workflow['metadata']) { + $metadataStoreDefinition->replaceArgument(0, $workflow['metadata']); + } + $placesMetadata = []; + foreach ($workflow['places'] as $place) { + if ($place['metadata']) { + $placesMetadata[$place['name']] = $place['metadata']; + } + } + if ($placesMetadata) { + $metadataStoreDefinition->replaceArgument(1, $placesMetadata); + } + + // Create transitions + $transitions = []; + $guardsConfiguration = []; + $transitionsMetadataDefinition = new Definition(\SplObjectStorage::class); + // Global transition counter per workflow + $transitionCounter = 0; + foreach ($workflow['transitions'] as $transition) { + if ('workflow' === $type) { + $transitionDefinition = new Definition(Workflow\Transition::class, [$transition['name'], $transition['from'], $transition['to']]); + $transitionDefinition->setPublic(false); + $transitionId = sprintf('%s.transition.%s', $workflowId, $transitionCounter++); + $container->setDefinition($transitionId, $transitionDefinition); + $transitions[] = new Reference($transitionId); + if (isset($transition['guard'])) { + $configuration = new Definition(Workflow\EventListener\GuardExpression::class); + $configuration->addArgument(new Reference($transitionId)); + $configuration->addArgument($transition['guard']); + $configuration->setPublic(false); + $eventName = sprintf('workflow.%s.guard.%s', $name, $transition['name']); + $guardsConfiguration[$eventName][] = $configuration; + } + if ($transition['metadata']) { + $transitionsMetadataDefinition->addMethodCall('attach', [ + new Reference($transitionId), + $transition['metadata'], + ]); + } + } elseif ('state_machine' === $type) { + foreach ($transition['from'] as $from) { + foreach ($transition['to'] as $to) { + $transitionDefinition = new Definition(Workflow\Transition::class, [$transition['name'], $from, $to]); + $transitionDefinition->setPublic(false); + $transitionId = sprintf('%s.transition.%s', $workflowId, $transitionCounter++); + $container->setDefinition($transitionId, $transitionDefinition); + $transitions[] = new Reference($transitionId); + if (isset($transition['guard'])) { + $configuration = new Definition(Workflow\EventListener\GuardExpression::class); + $configuration->addArgument(new Reference($transitionId)); + $configuration->addArgument($transition['guard']); + $configuration->setPublic(false); + $eventName = sprintf('workflow.%s.guard.%s', $name, $transition['name']); + $guardsConfiguration[$eventName][] = $configuration; + } + if ($transition['metadata']) { + $transitionsMetadataDefinition->addMethodCall('attach', [ + new Reference($transitionId), + $transition['metadata'], + ]); + } + } + } + } + } + $metadataStoreDefinition->replaceArgument(2, $transitionsMetadataDefinition); + + // Create places + $places = array_column($workflow['places'], 'name'); + $initialMarking = $workflow['initial_marking'] ?? []; + + // Create a Definition + $definitionDefinition = new Definition(Workflow\Definition::class); + $definitionDefinition->setPublic(false); + $definitionDefinition->addArgument($places); + $definitionDefinition->addArgument($transitions); + $definitionDefinition->addArgument($initialMarking); + $definitionDefinition->addArgument($metadataStoreDefinition); + $definitionDefinition->addTag('workflow.definition', [ + 'name' => $name, + 'type' => $type, + ]); + + // Create MarkingStore + if (isset($workflow['marking_store']['type'])) { + $markingStoreDefinition = new ChildDefinition('workflow.marking_store.method'); + $markingStoreDefinition->setArguments([ + 'state_machine' === $type, //single state + $workflow['marking_store']['property'], + ]); + } elseif (isset($workflow['marking_store']['service'])) { + $markingStoreDefinition = new Reference($workflow['marking_store']['service']); + } + + // Create Workflow + $workflowDefinition = new ChildDefinition(sprintf('%s.abstract', $type)); + $workflowDefinition->replaceArgument(0, new Reference(sprintf('%s.definition', $workflowId))); + if (isset($markingStoreDefinition)) { + $workflowDefinition->replaceArgument(1, $markingStoreDefinition); + } + $workflowDefinition->replaceArgument(3, $name); + + // Store to container + $container->setDefinition($workflowId, $workflowDefinition); + $container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition); + $container->registerAliasForArgument($workflowId, WorkflowInterface::class, $name.'.'.$type); + + // Validate Workflow + if ('state_machine' === $workflow['type']) { + $validator = new Workflow\Validator\StateMachineValidator(); + } else { + $validator = new Workflow\Validator\WorkflowValidator(); + } + + $trs = array_map(function (Reference $ref) use ($container): Workflow\Transition { + return $container->get((string) $ref); + }, $transitions); + $realDefinition = new Workflow\Definition($places, $trs, $initialMarking); + $validator->validate($realDefinition, $name); + + // Add workflow to Registry + if ($workflow['supports']) { + foreach ($workflow['supports'] as $supportedClassName) { + $strategyDefinition = new Definition(Workflow\SupportStrategy\InstanceOfSupportStrategy::class, [$supportedClassName]); + $strategyDefinition->setPublic(false); + $registryDefinition->addMethodCall('addWorkflow', [new Reference($workflowId), $strategyDefinition]); + } + } elseif (isset($workflow['support_strategy'])) { + $registryDefinition->addMethodCall('addWorkflow', [new Reference($workflowId), new Reference($workflow['support_strategy'])]); + } + + // Enable the AuditTrail + if ($workflow['audit_trail']['enabled']) { + $listener = new Definition(Workflow\EventListener\AuditTrailListener::class); + $listener->setPrivate(true); + $listener->addTag('monolog.logger', ['channel' => 'workflow']); + $listener->addTag('kernel.event_listener', ['event' => sprintf('workflow.%s.leave', $name), 'method' => 'onLeave']); + $listener->addTag('kernel.event_listener', ['event' => sprintf('workflow.%s.transition', $name), 'method' => 'onTransition']); + $listener->addTag('kernel.event_listener', ['event' => sprintf('workflow.%s.enter', $name), 'method' => 'onEnter']); + $listener->addArgument(new Reference('logger')); + $container->setDefinition(sprintf('%s.listener.audit_trail', $workflowId), $listener); + } + + // Add Guard Listener + if ($guardsConfiguration) { + if (!class_exists(ExpressionLanguage::class)) { + throw new LogicException('Cannot guard workflows as the ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".'); + } + + if (!class_exists(Security::class)) { + throw new LogicException('Cannot guard workflows as the Security component is not installed. Try running "composer require symfony/security-core".'); + } + + $guard = new Definition(Workflow\EventListener\GuardListener::class); + $guard->setPrivate(true); + + $guard->setArguments([ + $guardsConfiguration, + new Reference('workflow.security.expression_language'), + new Reference('security.token_storage'), + new Reference('security.authorization_checker'), + new Reference('security.authentication.trust_resolver'), + new Reference('security.role_hierarchy'), + new Reference('validator', ContainerInterface::NULL_ON_INVALID_REFERENCE), + ]); + foreach ($guardsConfiguration as $eventName => $config) { + $guard->addTag('kernel.event_listener', ['event' => $eventName, 'method' => 'onTransition']); + } + + $container->setDefinition(sprintf('%s.listener.guard', $workflowId), $guard); + $container->setParameter('workflow.has_guard_listeners', true); + } + } + } + + private function registerDebugConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + $loader->load('debug_prod.xml'); + + if (class_exists(Stopwatch::class)) { + $container->register('debug.stopwatch', Stopwatch::class) + ->addArgument(true) + ->setPrivate(true) + ->addTag('kernel.reset', ['method' => 'reset']); + $container->setAlias(Stopwatch::class, new Alias('debug.stopwatch', false)); + } + + $debug = $container->getParameter('kernel.debug'); + + if ($debug) { + $container->setParameter('debug.container.dump', '%kernel.cache_dir%/%kernel.container_class%.xml'); + } + + if ($debug && class_exists(Stopwatch::class)) { + $loader->load('debug.xml'); + } + + $definition = $container->findDefinition('debug.debug_handlers_listener'); + + if (false === $config['log']) { + $definition->replaceArgument(1, null); + } elseif (true !== $config['log']) { + $definition->replaceArgument(2, $config['log']); + } + + if (!$config['throw']) { + $container->setParameter('debug.error_handler.throw_at', 0); + } + + if ($debug && class_exists(DebugProcessor::class)) { + $definition = new Definition(DebugProcessor::class); + $definition->setPublic(false); + $definition->addArgument(new Reference('request_stack')); + $container->setDefinition('debug.log_processor', $definition); + } + } + + private function registerRouterConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + if (!$this->isConfigEnabled($container, $config)) { + $container->removeDefinition('console.command.router_debug'); + $container->removeDefinition('console.command.router_match'); + + return; + } + + $loader->load('routing.xml'); + + if ($config['utf8']) { + $container->getDefinition('routing.loader')->replaceArgument(1, ['utf8' => true]); + } + + $container->setParameter('router.resource', $config['resource']); + $router = $container->findDefinition('router.default'); + $argument = $router->getArgument(2); + $argument['strict_requirements'] = $config['strict_requirements']; + if (isset($config['type'])) { + $argument['resource_type'] = $config['type']; + } + $router->replaceArgument(2, $argument); + + $container->setParameter('request_listener.http_port', $config['http_port']); + $container->setParameter('request_listener.https_port', $config['https_port']); + + if ($this->annotationsConfigEnabled) { + $container->register('routing.loader.annotation', AnnotatedRouteControllerLoader::class) + ->setPublic(false) + ->addTag('routing.loader', ['priority' => -10]) + ->addArgument(new Reference('annotation_reader')); + + $container->register('routing.loader.annotation.directory', AnnotationDirectoryLoader::class) + ->setPublic(false) + ->addTag('routing.loader', ['priority' => -10]) + ->setArguments([ + new Reference('file_locator'), + new Reference('routing.loader.annotation'), + ]); + + $container->register('routing.loader.annotation.file', AnnotationFileLoader::class) + ->setPublic(false) + ->addTag('routing.loader', ['priority' => -10]) + ->setArguments([ + new Reference('file_locator'), + new Reference('routing.loader.annotation'), + ]); + } + } + + private function registerSessionConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + $loader->load('session.xml'); + + // session storage + $container->setAlias('session.storage', $config['storage_id'])->setPrivate(true); + $options = ['cache_limiter' => '0']; + foreach (['name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'cookie_samesite', 'use_cookies', 'gc_maxlifetime', 'gc_probability', 'gc_divisor', 'sid_length', 'sid_bits_per_character'] as $key) { + if (isset($config[$key])) { + $options[$key] = $config[$key]; + } + } + + if ('auto' === ($options['cookie_secure'] ?? null)) { + $locator = $container->getDefinition('session_listener')->getArgument(0); + $locator->setValues($locator->getValues() + [ + 'session_storage' => new Reference('session.storage', ContainerInterface::IGNORE_ON_INVALID_REFERENCE), + 'request_stack' => new Reference('request_stack'), + ]); + } + + $container->setParameter('session.storage.options', $options); + + // session handler (the internal callback registered with PHP session management) + if (null === $config['handler_id']) { + // Set the handler class to be null + $container->getDefinition('session.storage.native')->replaceArgument(1, null); + $container->getDefinition('session.storage.php_bridge')->replaceArgument(0, null); + } else { + $container->resolveEnvPlaceholders($config['handler_id'], null, $usedEnvs); + + if ($usedEnvs || preg_match('#^[a-z]++://#', $config['handler_id'])) { + $id = '.cache_connection.'.ContainerBuilder::hash($config['handler_id']); + + $container->getDefinition('session.abstract_handler') + ->replaceArgument(0, $container->hasDefinition($id) ? new Reference($id) : $config['handler_id']); + + $container->setAlias('session.handler', 'session.abstract_handler')->setPrivate(true); + } else { + $container->setAlias('session.handler', $config['handler_id'])->setPrivate(true); + } + } + + $container->setParameter('session.save_path', $config['save_path']); + + $container->setParameter('session.metadata.update_threshold', $config['metadata_update_threshold']); + } + + private function registerRequestConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + if ($config['formats']) { + $loader->load('request.xml'); + + $listener = $container->getDefinition('request.add_request_formats_listener'); + $listener->replaceArgument(0, $config['formats']); + } + } + + private function registerAssetsConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + $loader->load('assets.xml'); + + if ($config['version_strategy']) { + $defaultVersion = new Reference($config['version_strategy']); + } else { + $defaultVersion = $this->createVersion($container, $config['version'], $config['version_format'], $config['json_manifest_path'], '_default'); + } + + $defaultPackage = $this->createPackageDefinition($config['base_path'], $config['base_urls'], $defaultVersion); + $container->setDefinition('assets._default_package', $defaultPackage); + + $namedPackages = []; + foreach ($config['packages'] as $name => $package) { + if (null !== $package['version_strategy']) { + $version = new Reference($package['version_strategy']); + } elseif (!\array_key_exists('version', $package) && null === $package['json_manifest_path']) { + // if neither version nor json_manifest_path are specified, use the default + $version = $defaultVersion; + } else { + // let format fallback to main version_format + $format = $package['version_format'] ?: $config['version_format']; + $version = isset($package['version']) ? $package['version'] : null; + $version = $this->createVersion($container, $version, $format, $package['json_manifest_path'], $name); + } + + $container->setDefinition('assets._package_'.$name, $this->createPackageDefinition($package['base_path'], $package['base_urls'], $version)); + $container->registerAliasForArgument('assets._package_'.$name, PackageInterface::class, $name.'.package'); + $namedPackages[$name] = new Reference('assets._package_'.$name); + } + + $container->getDefinition('assets.packages') + ->replaceArgument(0, new Reference('assets._default_package')) + ->replaceArgument(1, $namedPackages) + ; + } + + /** + * Returns a definition for an asset package. + */ + private function createPackageDefinition(?string $basePath, array $baseUrls, Reference $version): Definition + { + if ($basePath && $baseUrls) { + throw new \LogicException('An asset package cannot have base URLs and base paths.'); + } + + $package = new ChildDefinition($baseUrls ? 'assets.url_package' : 'assets.path_package'); + $package + ->setPublic(false) + ->replaceArgument(0, $baseUrls ?: $basePath) + ->replaceArgument(1, $version) + ; + + return $package; + } + + private function createVersion(ContainerBuilder $container, ?string $version, ?string $format, ?string $jsonManifestPath, string $name): Reference + { + // Configuration prevents $version and $jsonManifestPath from being set + if (null !== $version) { + $def = new ChildDefinition('assets.static_version_strategy'); + $def + ->replaceArgument(0, $version) + ->replaceArgument(1, $format) + ; + $container->setDefinition('assets._version_'.$name, $def); + + return new Reference('assets._version_'.$name); + } + + if (null !== $jsonManifestPath) { + $def = new ChildDefinition('assets.json_manifest_version_strategy'); + $def->replaceArgument(0, $jsonManifestPath); + $container->setDefinition('assets._version_'.$name, $def); + + return new Reference('assets._version_'.$name); + } + + return new Reference('assets.empty_version_strategy'); + } + + private function registerTranslatorConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader, string $defaultLocale) + { + if (!$this->isConfigEnabled($container, $config)) { + $container->removeDefinition('console.command.translation_debug'); + $container->removeDefinition('console.command.translation_update'); + + return; + } + + $loader->load('translation.xml'); + + // Use the "real" translator instead of the identity default + $container->setAlias('translator', 'translator.default')->setPublic(true); + $container->setAlias('translator.formatter', new Alias($config['formatter'], false)); + $translator = $container->findDefinition('translator.default'); + $translator->addMethodCall('setFallbackLocales', [$config['fallbacks'] ?: [$defaultLocale]]); + + $defaultOptions = $translator->getArgument(4); + $defaultOptions['cache_dir'] = $config['cache_dir']; + $translator->setArgument(4, $defaultOptions); + + $container->setParameter('translator.logging', $config['logging']); + $container->setParameter('translator.default_path', $config['default_path']); + + // Discover translation directories + $dirs = []; + $transPaths = []; + $nonExistingDirs = []; + if (class_exists('Symfony\Component\Validator\Validation')) { + $r = new \ReflectionClass('Symfony\Component\Validator\Validation'); + + $dirs[] = $transPaths[] = \dirname($r->getFileName()).'/Resources/translations'; + } + if (class_exists('Symfony\Component\Form\Form')) { + $r = new \ReflectionClass('Symfony\Component\Form\Form'); + + $dirs[] = $transPaths[] = \dirname($r->getFileName()).'/Resources/translations'; + } + if (class_exists('Symfony\Component\Security\Core\Exception\AuthenticationException')) { + $r = new \ReflectionClass('Symfony\Component\Security\Core\Exception\AuthenticationException'); + + $dirs[] = $transPaths[] = \dirname($r->getFileName(), 2).'/Resources/translations'; + } + $defaultDir = $container->getParameterBag()->resolveValue($config['default_path']); + foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) { + if ($container->fileExists($dir = $bundle['path'].'/Resources/translations') || $container->fileExists($dir = $bundle['path'].'/translations')) { + $dirs[] = $dir; + } else { + $nonExistingDirs[] = $dir; + } + } + + foreach ($config['paths'] as $dir) { + if ($container->fileExists($dir)) { + $dirs[] = $transPaths[] = $dir; + } else { + throw new \UnexpectedValueException(sprintf('%s defined in translator.paths does not exist or is not a directory', $dir)); + } + } + + if ($container->hasDefinition('console.command.translation_debug')) { + $container->getDefinition('console.command.translation_debug')->replaceArgument(5, $transPaths); + } + + if ($container->hasDefinition('console.command.translation_update')) { + $container->getDefinition('console.command.translation_update')->replaceArgument(6, $transPaths); + } + + if ($container->fileExists($defaultDir)) { + $dirs[] = $defaultDir; + } else { + $nonExistingDirs[] = $defaultDir; + } + + // Register translation resources + if ($dirs) { + $files = []; + $finder = Finder::create() + ->followLinks() + ->files() + ->filter(function (\SplFileInfo $file) { + return 2 <= substr_count($file->getBasename(), '.') && preg_match('/\.\w+$/', $file->getBasename()); + }) + ->in($dirs) + ->sortByName() + ; + + foreach ($finder as $file) { + $fileNameParts = explode('.', basename($file)); + $locale = $fileNameParts[\count($fileNameParts) - 2]; + if (!isset($files[$locale])) { + $files[$locale] = []; + } + + $files[$locale][] = (string) $file; + } + + $projectDir = $container->getParameter('kernel.project_dir'); + + $options = array_merge( + $translator->getArgument(4), + [ + 'resource_files' => $files, + 'scanned_directories' => $scannedDirectories = array_merge($dirs, $nonExistingDirs), + 'cache_vary' => [ + 'scanned_directories' => array_map(static function (string $dir) use ($projectDir): string { + return 0 === strpos($dir, $projectDir.'/') ? substr($dir, 1 + \strlen($projectDir)) : $dir; + }, $scannedDirectories), + ], + ] + ); + + $translator->replaceArgument(4, $options); + } + } + + private function registerValidationConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader, bool $propertyInfoEnabled) + { + if (!$this->validatorConfigEnabled = $this->isConfigEnabled($container, $config)) { + return; + } + + if (!class_exists('Symfony\Component\Validator\Validation')) { + throw new LogicException('Validation support cannot be enabled as the Validator component is not installed. Try running "composer require symfony/validator".'); + } + + if (!isset($config['email_validation_mode'])) { + $config['email_validation_mode'] = 'loose'; + } + + $loader->load('validator.xml'); + + $validatorBuilder = $container->getDefinition('validator.builder'); + + $container->setParameter('validator.translation_domain', $config['translation_domain']); + + $files = ['xml' => [], 'yml' => []]; + $this->registerValidatorMapping($container, $config, $files); + + if (!empty($files['xml'])) { + $validatorBuilder->addMethodCall('addXmlMappings', [$files['xml']]); + } + + if (!empty($files['yml'])) { + $validatorBuilder->addMethodCall('addYamlMappings', [$files['yml']]); + } + + $definition = $container->findDefinition('validator.email'); + $definition->replaceArgument(0, $config['email_validation_mode']); + + if (\array_key_exists('enable_annotations', $config) && $config['enable_annotations']) { + if (!$this->annotationsConfigEnabled) { + throw new \LogicException('"enable_annotations" on the validator cannot be set as Annotations support is disabled.'); + } + + $validatorBuilder->addMethodCall('enableAnnotationMapping', [new Reference('annotation_reader')]); + } + + if (\array_key_exists('static_method', $config) && $config['static_method']) { + foreach ($config['static_method'] as $methodName) { + $validatorBuilder->addMethodCall('addMethodMapping', [$methodName]); + } + } + + if (!$container->getParameter('kernel.debug')) { + $validatorBuilder->addMethodCall('setMappingCache', [new Reference('validator.mapping.cache.adapter')]); + } + + $container->setParameter('validator.auto_mapping', $config['auto_mapping']); + if (!$propertyInfoEnabled || !class_exists(PropertyInfoLoader::class)) { + $container->removeDefinition('validator.property_info_loader'); + } + + $container + ->getDefinition('validator.not_compromised_password') + ->setArgument(2, $config['not_compromised_password']['enabled']) + ->setArgument(3, $config['not_compromised_password']['endpoint']) + ; + } + + private function registerValidatorMapping(ContainerBuilder $container, array $config, array &$files) + { + $fileRecorder = function ($extension, $path) use (&$files) { + $files['yaml' === $extension ? 'yml' : $extension][] = $path; + }; + + if (interface_exists('Symfony\Component\Form\FormInterface')) { + $reflClass = new \ReflectionClass('Symfony\Component\Form\FormInterface'); + $fileRecorder('xml', \dirname($reflClass->getFileName()).'/Resources/config/validation.xml'); + } + + foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { + $configDir = is_dir($bundle['path'].'/Resources/config') ? $bundle['path'].'/Resources/config' : $bundle['path'].'/config'; + + if ( + $container->fileExists($file = $configDir.'/validation.yaml', false) || + $container->fileExists($file = $configDir.'/validation.yml', false) + ) { + $fileRecorder('yml', $file); + } + + if ($container->fileExists($file = $configDir.'/validation.xml', false)) { + $fileRecorder('xml', $file); + } + + if ($container->fileExists($dir = $configDir.'/validation', '/^$/')) { + $this->registerMappingFilesFromDir($dir, $fileRecorder); + } + } + + $projectDir = $container->getParameter('kernel.project_dir'); + if ($container->fileExists($dir = $projectDir.'/config/validator', '/^$/')) { + $this->registerMappingFilesFromDir($dir, $fileRecorder); + } + + $this->registerMappingFilesFromConfig($container, $config, $fileRecorder); + } + + private function registerMappingFilesFromDir(string $dir, callable $fileRecorder) + { + foreach (Finder::create()->followLinks()->files()->in($dir)->name('/\.(xml|ya?ml)$/')->sortByName() as $file) { + $fileRecorder($file->getExtension(), $file->getRealPath()); + } + } + + private function registerMappingFilesFromConfig(ContainerBuilder $container, array $config, callable $fileRecorder) + { + foreach ($config['mapping']['paths'] as $path) { + if (is_dir($path)) { + $this->registerMappingFilesFromDir($path, $fileRecorder); + $container->addResource(new DirectoryResource($path, '/^$/')); + } elseif ($container->fileExists($path, false)) { + if (!preg_match('/\.(xml|ya?ml)$/', $path, $matches)) { + throw new \RuntimeException(sprintf('Unsupported mapping type in "%s", supported types are XML & Yaml.', $path)); + } + $fileRecorder($matches[1], $path); + } else { + throw new \RuntimeException(sprintf('Could not open file or directory "%s".', $path)); + } + } + } + + private function registerAnnotationsConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader) + { + if (!$this->annotationsConfigEnabled) { + return; + } + + if (!class_exists('Doctrine\Common\Annotations\Annotation')) { + throw new LogicException('Annotations cannot be enabled as the Doctrine Annotation library is not installed.'); + } + + $loader->load('annotations.xml'); + + if (!method_exists(AnnotationRegistry::class, 'registerUniqueLoader')) { + $container->getDefinition('annotations.dummy_registry') + ->setMethodCalls([['registerLoader', ['class_exists']]]); + } + + if ('none' !== $config['cache']) { + if (!class_exists('Doctrine\Common\Cache\CacheProvider')) { + throw new LogicException('Annotations cannot be enabled as the Doctrine Cache library is not installed.'); + } + + $cacheService = $config['cache']; + + if ('php_array' === $config['cache']) { + $cacheService = 'annotations.cache'; + + // Enable warmer only if PHP array is used for cache + $definition = $container->findDefinition('annotations.cache_warmer'); + $definition->addTag('kernel.cache_warmer'); + } elseif ('file' === $config['cache']) { + $cacheDir = $container->getParameterBag()->resolveValue($config['file_cache_dir']); + + if (!is_dir($cacheDir) && false === @mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) { + throw new \RuntimeException(sprintf('Could not create cache directory "%s".', $cacheDir)); + } + + $container + ->getDefinition('annotations.filesystem_cache') + ->replaceArgument(0, $cacheDir) + ; + + $cacheService = 'annotations.filesystem_cache'; + } + + $container + ->getDefinition('annotations.cached_reader') + ->replaceArgument(2, $config['debug']) + // temporary property to lazy-reference the cache provider without using it until AddAnnotationsCachedReaderPass runs + ->setProperty('cacheProviderBackup', new ServiceClosureArgument(new Reference($cacheService))) + ->addTag('annotations.cached_reader') + ; + + $container->setAlias('annotation_reader', 'annotations.cached_reader')->setPrivate(true); + $container->setAlias(Reader::class, new Alias('annotations.cached_reader', false)); + } else { + $container->removeDefinition('annotations.cached_reader'); + } + } + + private function registerPropertyAccessConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccessor')) { + return; + } + + $loader->load('property_access.xml'); + + $container + ->getDefinition('property_accessor') + ->replaceArgument(0, $config['magic_call']) + ->replaceArgument(1, $config['throw_exception_on_invalid_index']) + ->replaceArgument(3, $config['throw_exception_on_invalid_property_path']) + ; + } + + private function registerSecretsConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + if (!$this->isConfigEnabled($container, $config)) { + $container->removeDefinition('console.command.secrets_set'); + $container->removeDefinition('console.command.secrets_list'); + $container->removeDefinition('console.command.secrets_remove'); + $container->removeDefinition('console.command.secrets_generate_key'); + $container->removeDefinition('console.command.secrets_decrypt_to_local'); + $container->removeDefinition('console.command.secrets_encrypt_from_local'); + + return; + } + + $loader->load('secrets.xml'); + + $container->getDefinition('secrets.vault')->replaceArgument(0, $config['vault_directory']); + + if ($config['local_dotenv_file']) { + $container->getDefinition('secrets.local_vault')->replaceArgument(0, $config['local_dotenv_file']); + } else { + $container->removeDefinition('secrets.local_vault'); + } + + if ($config['decryption_env_var']) { + if (!preg_match('/^(?:\w*+:)*+\w++$/', $config['decryption_env_var'])) { + throw new InvalidArgumentException(sprintf('Invalid value "%s" set as "decryption_env_var": only "word" characters are allowed.', $config['decryption_env_var'])); + } + + $container->getDefinition('secrets.vault')->replaceArgument(1, "%env({$config['decryption_env_var']})%"); + } else { + $container->getDefinition('secrets.vault')->replaceArgument(1, null); + } + } + + private function registerSecurityCsrfConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + if (!$this->isConfigEnabled($container, $config)) { + return; + } + + if (!class_exists('Symfony\Component\Security\Csrf\CsrfToken')) { + throw new LogicException('CSRF support cannot be enabled as the Security CSRF component is not installed. Try running "composer require symfony/security-csrf".'); + } + + if (!$this->sessionConfigEnabled) { + throw new \LogicException('CSRF protection needs sessions to be enabled.'); + } + + // Enable services for CSRF protection (even without forms) + $loader->load('security_csrf.xml'); + + if (!class_exists(CsrfExtension::class)) { + $container->removeDefinition('twig.extension.security_csrf'); + } + } + + private function registerSerializerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + $loader->load('serializer.xml'); + + $chainLoader = $container->getDefinition('serializer.mapping.chain_loader'); + + if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccessor')) { + $container->removeAlias('serializer.property_accessor'); + $container->removeDefinition('serializer.normalizer.object'); + } + + if (!class_exists(Yaml::class)) { + $container->removeDefinition('serializer.encoder.yaml'); + } + + $serializerLoaders = []; + if (isset($config['enable_annotations']) && $config['enable_annotations']) { + if (!$this->annotationsConfigEnabled) { + throw new \LogicException('"enable_annotations" on the serializer cannot be set as Annotations support is disabled.'); + } + + $annotationLoader = new Definition( + 'Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader', + [new Reference('annotation_reader')] + ); + $annotationLoader->setPublic(false); + + $serializerLoaders[] = $annotationLoader; + } + + $fileRecorder = function ($extension, $path) use (&$serializerLoaders) { + $definition = new Definition(\in_array($extension, ['yaml', 'yml']) ? 'Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader' : 'Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', [$path]); + $definition->setPublic(false); + $serializerLoaders[] = $definition; + }; + + foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { + $configDir = is_dir($bundle['path'].'/Resources/config') ? $bundle['path'].'/Resources/config' : $bundle['path'].'/config'; + + if ($container->fileExists($file = $configDir.'/serialization.xml', false)) { + $fileRecorder('xml', $file); + } + + if ( + $container->fileExists($file = $configDir.'/serialization.yaml', false) || + $container->fileExists($file = $configDir.'/serialization.yml', false) + ) { + $fileRecorder('yml', $file); + } + + if ($container->fileExists($dir = $configDir.'/serialization', '/^$/')) { + $this->registerMappingFilesFromDir($dir, $fileRecorder); + } + } + + $projectDir = $container->getParameter('kernel.project_dir'); + if ($container->fileExists($dir = $projectDir.'/config/serializer', '/^$/')) { + $this->registerMappingFilesFromDir($dir, $fileRecorder); + } + + $this->registerMappingFilesFromConfig($container, $config, $fileRecorder); + + $chainLoader->replaceArgument(0, $serializerLoaders); + $container->getDefinition('serializer.mapping.cache_warmer')->replaceArgument(0, $serializerLoaders); + + if ($container->getParameter('kernel.debug')) { + $container->removeDefinition('serializer.mapping.cache_class_metadata_factory'); + } + + if (isset($config['name_converter']) && $config['name_converter']) { + $container->getDefinition('serializer.name_converter.metadata_aware')->setArgument(1, new Reference($config['name_converter'])); + } + + if (isset($config['circular_reference_handler']) && $config['circular_reference_handler']) { + $arguments = $container->getDefinition('serializer.normalizer.object')->getArguments(); + $context = ($arguments[6] ?? []) + ['circular_reference_handler' => new Reference($config['circular_reference_handler'])]; + $container->getDefinition('serializer.normalizer.object')->setArgument(5, null); + $container->getDefinition('serializer.normalizer.object')->setArgument(6, $context); + } + + if ($config['max_depth_handler'] ?? false) { + $defaultContext = $container->getDefinition('serializer.normalizer.object')->getArgument(6); + $defaultContext += ['max_depth_handler' => new Reference($config['max_depth_handler'])]; + $container->getDefinition('serializer.normalizer.object')->replaceArgument(6, $defaultContext); + } + } + + private function registerPropertyInfoConfiguration(ContainerBuilder $container, XmlFileLoader $loader) + { + if (!interface_exists(PropertyInfoExtractorInterface::class)) { + throw new LogicException('PropertyInfo support cannot be enabled as the PropertyInfo component is not installed. Try running "composer require symfony/property-info".'); + } + + $loader->load('property_info.xml'); + + if (interface_exists('phpDocumentor\Reflection\DocBlockFactoryInterface')) { + $definition = $container->register('property_info.php_doc_extractor', 'Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor'); + $definition->setPrivate(true); + $definition->addTag('property_info.description_extractor', ['priority' => -1000]); + $definition->addTag('property_info.type_extractor', ['priority' => -1001]); + } + + if ($container->getParameter('kernel.debug')) { + $container->removeDefinition('property_info.cache'); + } + } + + private function registerLockConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + $loader->load('lock.xml'); + + foreach ($config['resources'] as $resourceName => $resourceStores) { + if (0 === \count($resourceStores)) { + continue; + } + + // Generate stores + $storeDefinitions = []; + foreach ($resourceStores as $storeDsn) { + $storeDsn = $container->resolveEnvPlaceholders($storeDsn, null, $usedEnvs); + $storeDefinition = new Definition(interface_exists(StoreInterface::class) ? StoreInterface::class : PersistingStoreInterface::class); + $storeDefinition->setFactory([StoreFactory::class, 'createStore']); + $storeDefinition->setArguments([$storeDsn]); + + $container->setDefinition($storeDefinitionId = '.lock.'.$resourceName.'.store.'.$container->hash($storeDsn), $storeDefinition); + + $storeDefinition = new Reference($storeDefinitionId); + + $storeDefinitions[] = $storeDefinition; + } + + // Wrap array of stores with CombinedStore + if (\count($storeDefinitions) > 1) { + $combinedDefinition = new ChildDefinition('lock.store.combined.abstract'); + $combinedDefinition->replaceArgument(0, $storeDefinitions); + $container->setDefinition('lock.'.$resourceName.'.store', $combinedDefinition); + } else { + $container->setAlias('lock.'.$resourceName.'.store', new Alias((string) $storeDefinitions[0], false)); + } + + // Generate factories for each resource + $factoryDefinition = new ChildDefinition('lock.factory.abstract'); + $factoryDefinition->replaceArgument(0, new Reference('lock.'.$resourceName.'.store')); + $container->setDefinition('lock.'.$resourceName.'.factory', $factoryDefinition); + + // Generate services for lock instances + $lockDefinition = new Definition(Lock::class); + $lockDefinition->setPublic(false); + $lockDefinition->setFactory([new Reference('lock.'.$resourceName.'.factory'), 'createLock']); + $lockDefinition->setArguments([$resourceName]); + $container->setDefinition('lock.'.$resourceName, $lockDefinition); + + // provide alias for default resource + if ('default' === $resourceName) { + $container->setAlias('lock.store', new Alias('lock.'.$resourceName.'.store', false)); + $container->setAlias('lock.factory', new Alias('lock.'.$resourceName.'.factory', false)); + $container->setAlias('lock', new Alias('lock.'.$resourceName, false)); + $container->setAlias(PersistingStoreInterface::class, new Alias('lock.store', false)); + $container->setAlias(LockFactory::class, new Alias('lock.factory', false)); + $container->setAlias(LockInterface::class, new Alias('lock', false)); + } else { + $container->registerAliasForArgument('lock.'.$resourceName.'.store', PersistingStoreInterface::class, $resourceName.'.lock.store'); + $container->registerAliasForArgument('lock.'.$resourceName.'.factory', LockFactory::class, $resourceName.'.lock.factory'); + $container->registerAliasForArgument('lock.'.$resourceName, LockInterface::class, $resourceName.'.lock'); + } + } + } + + private function registerMessengerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader, array $validationConfig) + { + if (!interface_exists(MessageBusInterface::class)) { + throw new LogicException('Messenger support cannot be enabled as the Messenger component is not installed. Try running "composer require symfony/messenger".'); + } + + $loader->load('messenger.xml'); + + if (null === $config['default_bus'] && 1 === \count($config['buses'])) { + $config['default_bus'] = key($config['buses']); + } + + $defaultMiddleware = [ + 'before' => [ + ['id' => 'add_bus_name_stamp_middleware'], + ['id' => 'reject_redelivered_message_middleware'], + ['id' => 'dispatch_after_current_bus'], + ['id' => 'failed_message_processing_middleware'], + ], + 'after' => [ + ['id' => 'send_message'], + ['id' => 'handle_message'], + ], + ]; + foreach ($config['buses'] as $busId => $bus) { + $middleware = $bus['middleware']; + + if ($bus['default_middleware']) { + if ('allow_no_handlers' === $bus['default_middleware']) { + $defaultMiddleware['after'][1]['arguments'] = [true]; + } else { + unset($defaultMiddleware['after'][1]['arguments']); + } + + // argument to add_bus_name_stamp_middleware + $defaultMiddleware['before'][0]['arguments'] = [$busId]; + + $middleware = array_merge($defaultMiddleware['before'], $middleware, $defaultMiddleware['after']); + } + + foreach ($middleware as $middlewareItem) { + if (!$validationConfig['enabled'] && \in_array($middlewareItem['id'], ['validation', 'messenger.middleware.validation'], true)) { + throw new LogicException('The Validation middleware is only available when the Validator component is installed and enabled. Try running "composer require symfony/validator".'); + } + } + + if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class)) { + array_unshift($middleware, ['id' => 'traceable', 'arguments' => [$busId]]); + } + + $container->setParameter($busId.'.middleware', $middleware); + $container->register($busId, MessageBus::class)->addArgument([])->addTag('messenger.bus'); + + if ($busId === $config['default_bus']) { + $container->setAlias('messenger.default_bus', $busId)->setPublic(true); + $container->setAlias(MessageBusInterface::class, $busId); + } else { + $container->registerAliasForArgument($busId, MessageBusInterface::class); + } + } + + if (empty($config['transports'])) { + $container->removeDefinition('messenger.transport.symfony_serializer'); + $container->removeDefinition('messenger.transport.amqp.factory'); + $container->removeDefinition('messenger.transport.redis.factory'); + } else { + $container->getDefinition('messenger.transport.symfony_serializer') + ->replaceArgument(1, $config['serializer']['symfony_serializer']['format']) + ->replaceArgument(2, $config['serializer']['symfony_serializer']['context']); + $container->setAlias('messenger.default_serializer', $config['serializer']['default_serializer']); + } + + $senderAliases = []; + $transportRetryReferences = []; + foreach ($config['transports'] as $name => $transport) { + $serializerId = $transport['serializer'] ?? 'messenger.default_serializer'; + + $transportDefinition = (new Definition(TransportInterface::class)) + ->setFactory([new Reference('messenger.transport_factory'), 'createTransport']) + ->setArguments([$transport['dsn'], $transport['options'] + ['transport_name' => $name], new Reference($serializerId)]) + ->addTag('messenger.receiver', ['alias' => $name]) + ; + $container->setDefinition($transportId = 'messenger.transport.'.$name, $transportDefinition); + $senderAliases[$name] = $transportId; + + if (null !== $transport['retry_strategy']['service']) { + $transportRetryReferences[$name] = new Reference($transport['retry_strategy']['service']); + } else { + $retryServiceId = sprintf('messenger.retry.multiplier_retry_strategy.%s', $name); + $retryDefinition = new ChildDefinition('messenger.retry.abstract_multiplier_retry_strategy'); + $retryDefinition + ->replaceArgument(0, $transport['retry_strategy']['max_retries']) + ->replaceArgument(1, $transport['retry_strategy']['delay']) + ->replaceArgument(2, $transport['retry_strategy']['multiplier']) + ->replaceArgument(3, $transport['retry_strategy']['max_delay']); + $container->setDefinition($retryServiceId, $retryDefinition); + + $transportRetryReferences[$name] = new Reference($retryServiceId); + } + } + + $senderReferences = []; + // alias => service_id + foreach ($senderAliases as $alias => $serviceId) { + $senderReferences[$alias] = new Reference($serviceId); + } + // service_id => service_id + foreach ($senderAliases as $serviceId) { + $senderReferences[$serviceId] = new Reference($serviceId); + } + + $messageToSendersMapping = []; + foreach ($config['routing'] as $message => $messageConfiguration) { + if ('*' !== $message && !class_exists($message) && !interface_exists($message, false)) { + throw new LogicException(sprintf('Invalid Messenger routing configuration: class or interface "%s" not found.', $message)); + } + + // make sure senderAliases contains all senders + foreach ($messageConfiguration['senders'] as $sender) { + if (!isset($senderReferences[$sender])) { + throw new LogicException(sprintf('Invalid Messenger routing configuration: the "%s" class is being routed to a sender called "%s". This is not a valid transport or service id.', $message, $sender)); + } + } + + $messageToSendersMapping[$message] = $messageConfiguration['senders']; + } + + $sendersServiceLocator = ServiceLocatorTagPass::register($container, $senderReferences); + + $container->getDefinition('messenger.senders_locator') + ->replaceArgument(0, $messageToSendersMapping) + ->replaceArgument(1, $sendersServiceLocator) + ; + + $container->getDefinition('messenger.retry.send_failed_message_for_retry_listener') + ->replaceArgument(0, $sendersServiceLocator) + ; + + $container->getDefinition('messenger.retry_strategy_locator') + ->replaceArgument(0, $transportRetryReferences); + + if ($config['failure_transport']) { + if (!isset($senderReferences[$config['failure_transport']])) { + throw new LogicException(sprintf('Invalid Messenger configuration: the failure transport "%s" is not a valid transport or service id.', $config['failure_transport'])); + } + + $container->getDefinition('messenger.failure.send_failed_message_to_failure_transport_listener') + ->replaceArgument(0, $senderReferences[$config['failure_transport']]); + $container->getDefinition('console.command.messenger_failed_messages_retry') + ->replaceArgument(0, $config['failure_transport']); + $container->getDefinition('console.command.messenger_failed_messages_show') + ->replaceArgument(0, $config['failure_transport']); + $container->getDefinition('console.command.messenger_failed_messages_remove') + ->replaceArgument(0, $config['failure_transport']); + } else { + $container->removeDefinition('messenger.failure.send_failed_message_to_failure_transport_listener'); + $container->removeDefinition('console.command.messenger_failed_messages_retry'); + $container->removeDefinition('console.command.messenger_failed_messages_show'); + $container->removeDefinition('console.command.messenger_failed_messages_remove'); + } + } + + private function registerCacheConfiguration(array $config, ContainerBuilder $container) + { + if (!class_exists(DefaultMarshaller::class)) { + $container->removeDefinition('cache.default_marshaller'); + } + + $version = new Parameter('container.build_id'); + $container->getDefinition('cache.adapter.apcu')->replaceArgument(2, $version); + $container->getDefinition('cache.adapter.system')->replaceArgument(2, $version); + $container->getDefinition('cache.adapter.filesystem')->replaceArgument(2, $config['directory']); + + if (isset($config['prefix_seed'])) { + $container->setParameter('cache.prefix.seed', $config['prefix_seed']); + } + if ($container->hasParameter('cache.prefix.seed')) { + // Inline any env vars referenced in the parameter + $container->setParameter('cache.prefix.seed', $container->resolveEnvPlaceholders($container->getParameter('cache.prefix.seed'), true)); + } + foreach (['doctrine', 'psr6', 'redis', 'memcached', 'pdo'] as $name) { + if (isset($config[$name = 'default_'.$name.'_provider'])) { + $container->setAlias('cache.'.$name, new Alias(CachePoolPass::getServiceProvider($container, $config[$name]), false)); + } + } + foreach (['app', 'system'] as $name) { + $config['pools']['cache.'.$name] = [ + 'adapters' => [$config[$name]], + 'public' => true, + 'tags' => false, + ]; + } + foreach ($config['pools'] as $name => $pool) { + $pool['adapters'] = $pool['adapters'] ?: ['cache.app']; + + foreach ($pool['adapters'] as $provider => $adapter) { + if ($config['pools'][$adapter]['tags'] ?? false) { + $pool['adapters'][$provider] = $adapter = '.'.$adapter.'.inner'; + } + } + + if (1 === \count($pool['adapters'])) { + if (!isset($pool['provider']) && !\is_int($provider)) { + $pool['provider'] = $provider; + } + $definition = new ChildDefinition($adapter); + } else { + $definition = new Definition(ChainAdapter::class, [$pool['adapters'], 0]); + $pool['reset'] = 'reset'; + } + + if ($pool['tags']) { + if (true !== $pool['tags'] && ($config['pools'][$pool['tags']]['tags'] ?? false)) { + $pool['tags'] = '.'.$pool['tags'].'.inner'; + } + $container->register($name, TagAwareAdapter::class) + ->addArgument(new Reference('.'.$name.'.inner')) + ->addArgument(true !== $pool['tags'] ? new Reference($pool['tags']) : null) + ->setPublic($pool['public']) + ; + + $pool['name'] = $name; + $pool['public'] = false; + $name = '.'.$name.'.inner'; + + if (!\in_array($pool['name'], ['cache.app', 'cache.system'], true)) { + $container->registerAliasForArgument($pool['name'], TagAwareCacheInterface::class); + $container->registerAliasForArgument($name, CacheInterface::class, $pool['name']); + $container->registerAliasForArgument($name, CacheItemPoolInterface::class, $pool['name']); + } + } elseif (!\in_array($name, ['cache.app', 'cache.system'], true)) { + $container->register('.'.$name.'.taggable', TagAwareAdapter::class) + ->addArgument(new Reference($name)) + ; + $container->registerAliasForArgument('.'.$name.'.taggable', TagAwareCacheInterface::class, $name); + $container->registerAliasForArgument($name, CacheInterface::class); + $container->registerAliasForArgument($name, CacheItemPoolInterface::class); + } + + $definition->setPublic($pool['public']); + unset($pool['adapters'], $pool['public'], $pool['tags']); + + $definition->addTag('cache.pool', $pool); + $container->setDefinition($name, $definition); + } + + if (method_exists(PropertyAccessor::class, 'createCache')) { + $propertyAccessDefinition = $container->register('cache.property_access', AdapterInterface::class); + $propertyAccessDefinition->setPublic(false); + + if (!$container->getParameter('kernel.debug')) { + $propertyAccessDefinition->setFactory([PropertyAccessor::class, 'createCache']); + $propertyAccessDefinition->setArguments([null, 0, $version, new Reference('logger', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)]); + $propertyAccessDefinition->addTag('cache.pool', ['clearer' => 'cache.system_clearer']); + $propertyAccessDefinition->addTag('monolog.logger', ['channel' => 'cache']); + } else { + $propertyAccessDefinition->setClass(ArrayAdapter::class); + $propertyAccessDefinition->setArguments([0, false]); + } + } + } + + private function registerHttpClientConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader, array $profilerConfig) + { + $loader->load('http_client.xml'); + + $container->getDefinition('http_client')->setArguments([$config['default_options'] ?? [], $config['max_host_connections'] ?? 6]); + + if (!$hasPsr18 = interface_exists(ClientInterface::class)) { + $container->removeDefinition('psr18.http_client'); + $container->removeAlias(ClientInterface::class); + } + + if (!interface_exists(HttpClient::class)) { + $container->removeDefinition(HttpClient::class); + } + + $httpClientId = $this->isConfigEnabled($container, $profilerConfig) ? '.debug.http_client.inner' : 'http_client'; + + foreach ($config['scoped_clients'] as $name => $scopeConfig) { + if ('http_client' === $name) { + throw new InvalidArgumentException(sprintf('Invalid scope name: "%s" is reserved.', $name)); + } + + $scope = $scopeConfig['scope'] ?? null; + unset($scopeConfig['scope']); + + if (null === $scope) { + $container->register($name, ScopingHttpClient::class) + ->setFactory([ScopingHttpClient::class, 'forBaseUri']) + ->setArguments([new Reference($httpClientId), $scopeConfig['base_uri'], $scopeConfig]) + ->addTag('http_client.client') + ; + } else { + $container->register($name, ScopingHttpClient::class) + ->setArguments([new Reference($httpClientId), [$scope => $scopeConfig], $scope]) + ->addTag('http_client.client') + ; + } + + $container->registerAliasForArgument($name, HttpClientInterface::class); + + if ($hasPsr18) { + $container->setDefinition('psr18.'.$name, new ChildDefinition('psr18.http_client')) + ->replaceArgument(0, new Reference($name)); + + $container->registerAliasForArgument('psr18.'.$name, ClientInterface::class, $name); + } + } + } + + private function registerMailerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + if (!class_exists(Mailer::class)) { + throw new LogicException('Mailer support cannot be enabled as the component is not installed. Try running "composer require symfony/mailer".'); + } + + $loader->load('mailer.xml'); + $loader->load('mailer_transports.xml'); + if (!\count($config['transports']) && null === $config['dsn']) { + $config['dsn'] = 'smtp://null'; + } + $transports = $config['dsn'] ? ['main' => $config['dsn']] : $config['transports']; + $container->getDefinition('mailer.transports')->setArgument(0, $transports); + $container->getDefinition('mailer.default_transport')->setArgument(0, current($transports)); + + $classToServices = [ + SesTransportFactory::class => 'mailer.transport_factory.amazon', + GmailTransportFactory::class => 'mailer.transport_factory.gmail', + MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp', + MailgunTransportFactory::class => 'mailer.transport_factory.mailgun', + PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', + SendgridTransportFactory::class => 'mailer.transport_factory.sendgrid', + ]; + + foreach ($classToServices as $class => $service) { + if (!class_exists($class)) { + $container->removeDefinition($service); + } + } + + $recipients = $config['envelope']['recipients'] ?? null; + $sender = $config['envelope']['sender'] ?? null; + + $envelopeListener = $container->getDefinition('mailer.envelope_listener'); + $envelopeListener->setArgument(0, $sender); + $envelopeListener->setArgument(1, $recipients); + } + + private function registerNotifierConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + if (!class_exists(Notifier::class)) { + throw new LogicException('Notifier support cannot be enabled as the component is not installed. Try running "composer require symfony/notifier".'); + } + + $loader->load('notifier.xml'); + $loader->load('notifier_transports.xml'); + + if ($config['chatter_transports']) { + $container->getDefinition('chatter.transports')->setArgument(0, $config['chatter_transports']); + } else { + $container->removeDefinition('chatter'); + } + if ($config['texter_transports']) { + $container->getDefinition('texter.transports')->setArgument(0, $config['texter_transports']); + } else { + $container->removeDefinition('texter'); + } + + if ($this->mailerConfigEnabled) { + $sender = $container->getDefinition('mailer.envelope_listener')->getArgument(0); + $container->getDefinition('notifier.channel.email')->setArgument(2, $sender); + } else { + $container->removeDefinition('notifier.channel.email'); + } + + if ($this->messengerConfigEnabled) { + if ($config['notification_on_failed_messages']) { + $container->getDefinition('notifier.failed_message_listener')->addTag('kernel.event_subscriber'); + } + + // as we have a bus, the channels don't need the transports + $container->getDefinition('notifier.channel.chat')->setArgument(0, null); + if ($container->hasDefinition('notifier.channel.email')) { + $container->getDefinition('notifier.channel.email')->setArgument(0, null); + } + $container->getDefinition('notifier.channel.sms')->setArgument(0, null); + } + + $container->getDefinition('notifier.channel_policy')->setArgument(0, $config['channel_policy']); + + $classToServices = [ + SlackTransportFactory::class => 'notifier.transport_factory.slack', + TelegramTransportFactory::class => 'notifier.transport_factory.telegram', + NexmoTransportFactory::class => 'notifier.transport_factory.nexmo', + TwilioTransportFactory::class => 'notifier.transport_factory.twilio', + ]; + + foreach ($classToServices as $class => $service) { + if (!class_exists($class)) { + $container->removeDefinition($service); + } + } + + if (isset($config['admin_recipients'])) { + $notifier = $container->getDefinition('notifier'); + foreach ($config['admin_recipients'] as $i => $recipient) { + $id = 'notifier.admin_recipient.'.$i; + $container->setDefinition($id, new Definition(AdminRecipient::class, [$recipient['email'], $recipient['phone']])); + $notifier->addMethodCall('addAdminRecipient', [new Reference($id)]); + } + } + } + + /** + * {@inheritdoc} + */ + public function getXsdValidationBasePath() + { + return \dirname(__DIR__).'/Resources/config/schema'; + } + + public function getNamespace() + { + return 'http://symfony.com/schema/dic/symfony'; + } +} diff --git a/vendor/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php b/vendor/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php new file mode 100644 index 0000000..231329c --- /dev/null +++ b/vendor/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\EventListener; + +use Symfony\Component\Console\ConsoleEvents; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Exception\CommandNotFoundException; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +/** + * Suggests a package, that should be installed (via composer), + * if the package is missing, and the input command namespace can be mapped to a Symfony bundle. + * + * @author Przemysław Bogusz + * + * @internal + */ +final class SuggestMissingPackageSubscriber implements EventSubscriberInterface +{ + private const PACKAGES = [ + 'doctrine' => [ + 'fixtures' => ['DoctrineFixturesBundle', 'doctrine/doctrine-fixtures-bundle --dev'], + 'mongodb' => ['DoctrineMongoDBBundle', 'doctrine/mongodb-odm-bundle'], + '_default' => ['Doctrine ORM', 'symfony/orm-pack'], + ], + 'generate' => [ + '_default' => ['SensioGeneratorBundle', 'sensio/generator-bundle'], + ], + 'make' => [ + '_default' => ['MakerBundle', 'symfony/maker-bundle --dev'], + ], + 'server' => [ + 'dump' => ['Debug Bundle', 'symfony/debug-bundle --dev'], + '_default' => ['WebServerBundle', 'symfony/web-server-bundle --dev'], + ], + ]; + + public function onConsoleError(ConsoleErrorEvent $event): void + { + if (!$event->getError() instanceof CommandNotFoundException) { + return; + } + + [$namespace, $command] = explode(':', $event->getInput()->getFirstArgument()) + [1 => '']; + + if (!isset(self::PACKAGES[$namespace])) { + return; + } + + if (isset(self::PACKAGES[$namespace][$command])) { + $suggestion = self::PACKAGES[$namespace][$command]; + $exact = true; + } else { + $suggestion = self::PACKAGES[$namespace]['_default']; + $exact = false; + } + + $error = $event->getError(); + + if ($error->getAlternatives() && !$exact) { + return; + } + + $message = sprintf("%s\n\nYou may be looking for a command provided by the \"%s\" which is currently not installed. Try running \"composer require %s\".", $error->getMessage(), $suggestion[0], $suggestion[1]); + $event->setError(new CommandNotFoundException($message)); + } + + public static function getSubscribedEvents(): array + { + return [ + ConsoleEvents::ERROR => ['onConsoleError', 0], + ]; + } +} diff --git a/vendor/symfony/framework-bundle/FrameworkBundle.php b/vendor/symfony/framework-bundle/FrameworkBundle.php new file mode 100644 index 0000000..6cafc43 --- /dev/null +++ b/vendor/symfony/framework-bundle/FrameworkBundle.php @@ -0,0 +1,150 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle; + +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerRealRefPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerWeakRefPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass; +use Symfony\Component\Cache\DependencyInjection\CacheCollectorPass; +use Symfony\Component\Cache\DependencyInjection\CachePoolClearerPass; +use Symfony\Component\Cache\DependencyInjection\CachePoolPass; +use Symfony\Component\Cache\DependencyInjection\CachePoolPrunerPass; +use Symfony\Component\Config\Resource\ClassExistenceResource; +use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; +use Symfony\Component\DependencyInjection\Compiler\PassConfig; +use Symfony\Component\DependencyInjection\Compiler\RegisterReverseContainerPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\ErrorHandler\ErrorHandler; +use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; +use Symfony\Component\Form\DependencyInjection\FormPass; +use Symfony\Component\HttpClient\DependencyInjection\HttpClientPass; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass; +use Symfony\Component\HttpKernel\DependencyInjection\FragmentRendererPass; +use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; +use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass; +use Symfony\Component\HttpKernel\DependencyInjection\RegisterLocaleAwareServicesPass; +use Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass; +use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\Messenger\DependencyInjection\MessengerPass; +use Symfony\Component\Mime\DependencyInjection\AddMimeTypeGuesserPass; +use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass; +use Symfony\Component\Routing\DependencyInjection\RoutingResolverPass; +use Symfony\Component\Serializer\DependencyInjection\SerializerPass; +use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass; +use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass; +use Symfony\Component\Translation\DependencyInjection\TranslatorPass; +use Symfony\Component\Translation\DependencyInjection\TranslatorPathsPass; +use Symfony\Component\Validator\DependencyInjection\AddAutoMappingConfigurationPass; +use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass; +use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass; + +/** + * Bundle. + * + * @author Fabien Potencier + */ +class FrameworkBundle extends Bundle +{ + public function boot() + { + ErrorHandler::register(null, false)->throwAt($this->container->getParameter('debug.error_handler.throw_at'), true); + + if ($this->container->getParameter('kernel.http_method_override')) { + Request::enableHttpMethodParameterOverride(); + } + + if ($trustedHosts = $this->container->getParameter('kernel.trusted_hosts')) { + Request::setTrustedHosts($trustedHosts); + } + } + + public function build(ContainerBuilder $container) + { + parent::build($container); + + $hotPathEvents = [ + KernelEvents::REQUEST, + KernelEvents::CONTROLLER, + KernelEvents::CONTROLLER_ARGUMENTS, + KernelEvents::RESPONSE, + KernelEvents::FINISH_REQUEST, + ]; + + $container->addCompilerPass(new LoggerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); + $container->addCompilerPass(new RegisterControllerArgumentLocatorsPass()); + $container->addCompilerPass(new RemoveEmptyControllerArgumentLocatorsPass(), PassConfig::TYPE_BEFORE_REMOVING); + $container->addCompilerPass(new RoutingResolverPass()); + $container->addCompilerPass(new ProfilerPass()); + // must be registered before removing private services as some might be listeners/subscribers + // but as late as possible to get resolved parameters + $container->addCompilerPass((new RegisterListenersPass())->setHotPathEvents($hotPathEvents), PassConfig::TYPE_BEFORE_REMOVING); + $this->addCompilerPassIfExists($container, AddConstraintValidatorsPass::class); + $container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_AFTER_REMOVING, -255); + $this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class); + $this->addCompilerPassIfExists($container, AddConsoleCommandPass::class, PassConfig::TYPE_BEFORE_REMOVING); + // must be registered as late as possible to get access to all Twig paths registered in + // twig.template_iterator definition + $this->addCompilerPassIfExists($container, TranslatorPass::class, PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); + $this->addCompilerPassIfExists($container, TranslatorPathsPass::class, PassConfig::TYPE_AFTER_REMOVING); + $container->addCompilerPass(new LoggingTranslatorPass()); + $container->addCompilerPass(new AddExpressionLanguageProvidersPass(false)); + $this->addCompilerPassIfExists($container, TranslationExtractorPass::class); + $this->addCompilerPassIfExists($container, TranslationDumperPass::class); + $container->addCompilerPass(new FragmentRendererPass()); + $this->addCompilerPassIfExists($container, SerializerPass::class); + $this->addCompilerPassIfExists($container, PropertyInfoPass::class); + $container->addCompilerPass(new DataCollectorTranslatorPass()); + $container->addCompilerPass(new ControllerArgumentValueResolverPass()); + $container->addCompilerPass(new CachePoolPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 32); + $container->addCompilerPass(new CachePoolClearerPass(), PassConfig::TYPE_AFTER_REMOVING); + $container->addCompilerPass(new CachePoolPrunerPass(), PassConfig::TYPE_AFTER_REMOVING); + $this->addCompilerPassIfExists($container, FormPass::class); + $container->addCompilerPass(new WorkflowGuardListenerPass()); + $container->addCompilerPass(new ResettableServicePass()); + $container->addCompilerPass(new RegisterLocaleAwareServicesPass()); + $container->addCompilerPass(new TestServiceContainerWeakRefPass(), PassConfig::TYPE_BEFORE_REMOVING, -32); + $container->addCompilerPass(new TestServiceContainerRealRefPass(), PassConfig::TYPE_AFTER_REMOVING); + $this->addCompilerPassIfExists($container, AddMimeTypeGuesserPass::class); + $this->addCompilerPassIfExists($container, MessengerPass::class); + $this->addCompilerPassIfExists($container, HttpClientPass::class); + $this->addCompilerPassIfExists($container, AddAutoMappingConfigurationPass::class); + $container->addCompilerPass(new RegisterReverseContainerPass(true)); + $container->addCompilerPass(new RegisterReverseContainerPass(false), PassConfig::TYPE_AFTER_REMOVING); + + if ($container->getParameter('kernel.debug')) { + $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 2); + $container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING); + $container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_BEFORE_REMOVING, -255); + $container->addCompilerPass(new CacheCollectorPass(), PassConfig::TYPE_BEFORE_REMOVING); + } + } + + private function addCompilerPassIfExists(ContainerBuilder $container, string $class, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) + { + $container->addResource(new ClassExistenceResource($class)); + + if (class_exists($class)) { + $container->addCompilerPass(new $class(), $type, $priority); + } + } +} diff --git a/vendor/symfony/framework-bundle/HttpCache/HttpCache.php b/vendor/symfony/framework-bundle/HttpCache/HttpCache.php new file mode 100644 index 0000000..037d0f0 --- /dev/null +++ b/vendor/symfony/framework-bundle/HttpCache/HttpCache.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\HttpCache; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpCache\Esi; +use Symfony\Component\HttpKernel\HttpCache\HttpCache as BaseHttpCache; +use Symfony\Component\HttpKernel\HttpCache\Store; +use Symfony\Component\HttpKernel\KernelInterface; + +/** + * Manages HTTP cache objects in a Container. + * + * @author Fabien Potencier + */ +class HttpCache extends BaseHttpCache +{ + protected $cacheDir; + protected $kernel; + + /** + * @param string $cacheDir The cache directory (default used if null) + */ + public function __construct(KernelInterface $kernel, string $cacheDir = null) + { + $this->kernel = $kernel; + $this->cacheDir = $cacheDir; + + parent::__construct($kernel, $this->createStore(), $this->createSurrogate(), array_merge(['debug' => $kernel->isDebug()], $this->getOptions())); + } + + /** + * {@inheritdoc} + */ + protected function forward(Request $request, bool $catch = false, Response $entry = null) + { + $this->getKernel()->boot(); + $this->getKernel()->getContainer()->set('cache', $this); + + return parent::forward($request, $catch, $entry); + } + + /** + * Returns an array of options to customize the Cache configuration. + * + * @return array An array of options + */ + protected function getOptions() + { + return []; + } + + protected function createSurrogate() + { + return new Esi(); + } + + protected function createStore() + { + return new Store($this->cacheDir ?: $this->kernel->getCacheDir().'/http_cache'); + } +} diff --git a/vendor/symfony/framework-bundle/Kernel/MicroKernelTrait.php b/vendor/symfony/framework-bundle/Kernel/MicroKernelTrait.php new file mode 100644 index 0000000..181ea82 --- /dev/null +++ b/vendor/symfony/framework-bundle/Kernel/MicroKernelTrait.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Kernel; + +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\Routing\RouteCollectionBuilder; + +/** + * A Kernel that provides configuration hooks. + * + * @author Ryan Weaver + * @author Fabien Potencier + */ +trait MicroKernelTrait +{ + /** + * Add or import routes into your application. + * + * $routes->import('config/routing.yml'); + * $routes->add('/admin', 'App\Controller\AdminController::dashboard', 'admin_dashboard'); + */ + abstract protected function configureRoutes(RouteCollectionBuilder $routes); + + /** + * Configures the container. + * + * You can register extensions: + * + * $c->loadFromExtension('framework', [ + * 'secret' => '%secret%' + * ]); + * + * Or services: + * + * $c->register('halloween', 'FooBundle\HalloweenProvider'); + * + * Or parameters: + * + * $c->setParameter('halloween', 'lot of fun'); + */ + abstract protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader); + + /** + * {@inheritdoc} + */ + public function registerContainerConfiguration(LoaderInterface $loader) + { + $loader->load(function (ContainerBuilder $container) use ($loader) { + $container->loadFromExtension('framework', [ + 'router' => [ + 'resource' => 'kernel::loadRoutes', + 'type' => 'service', + ], + ]); + + if (!$container->hasDefinition('kernel')) { + $container->register('kernel', static::class) + ->setSynthetic(true) + ->setPublic(true) + ; + } + + $kernelDefinition = $container->getDefinition('kernel'); + $kernelDefinition->addTag('routing.route_loader'); + + if ($this instanceof EventSubscriberInterface) { + $kernelDefinition->addTag('kernel.event_subscriber'); + } + + $this->configureContainer($container, $loader); + + $container->addObjectResource($this); + }); + } + + /** + * @internal + */ + public function loadRoutes(LoaderInterface $loader) + { + $routes = new RouteCollectionBuilder($loader); + $this->configureRoutes($routes); + + return $routes->build(); + } +} diff --git a/vendor/symfony/framework-bundle/KernelBrowser.php b/vendor/symfony/framework-bundle/KernelBrowser.php new file mode 100644 index 0000000..38d2f06 --- /dev/null +++ b/vendor/symfony/framework-bundle/KernelBrowser.php @@ -0,0 +1,206 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle; + +use Symfony\Component\BrowserKit\CookieJar; +use Symfony\Component\BrowserKit\History; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelBrowser; +use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Component\HttpKernel\Profiler\Profile as HttpProfile; + +/** + * Simulates a browser and makes requests to a Kernel object. + * + * @author Fabien Potencier + */ +class KernelBrowser extends HttpKernelBrowser +{ + private $hasPerformedRequest = false; + private $profiler = false; + private $reboot = true; + + /** + * {@inheritdoc} + */ + public function __construct(KernelInterface $kernel, array $server = [], History $history = null, CookieJar $cookieJar = null) + { + parent::__construct($kernel, $server, $history, $cookieJar); + } + + /** + * Returns the container. + * + * @return ContainerInterface|null Returns null when the Kernel has been shutdown or not started yet + */ + public function getContainer() + { + return $this->kernel->getContainer(); + } + + /** + * Returns the kernel. + * + * @return KernelInterface + */ + public function getKernel() + { + return $this->kernel; + } + + /** + * Gets the profile associated with the current Response. + * + * @return HttpProfile|false A Profile instance + */ + public function getProfile() + { + if (null === $this->response || !$this->kernel->getContainer()->has('profiler')) { + return false; + } + + return $this->kernel->getContainer()->get('profiler')->loadProfileFromResponse($this->response); + } + + /** + * Enables the profiler for the very next request. + * + * If the profiler is not enabled, the call to this method does nothing. + */ + public function enableProfiler() + { + if ($this->kernel->getContainer()->has('profiler')) { + $this->profiler = true; + } + } + + /** + * Disables kernel reboot between requests. + * + * By default, the Client reboots the Kernel for each request. This method + * allows to keep the same kernel across requests. + */ + public function disableReboot() + { + $this->reboot = false; + } + + /** + * Enables kernel reboot between requests. + */ + public function enableReboot() + { + $this->reboot = true; + } + + /** + * {@inheritdoc} + * + * @param Request $request A Request instance + * + * @return Response A Response instance + */ + protected function doRequest($request) + { + // avoid shutting down the Kernel if no request has been performed yet + // WebTestCase::createClient() boots the Kernel but do not handle a request + if ($this->hasPerformedRequest && $this->reboot) { + $this->kernel->shutdown(); + } else { + $this->hasPerformedRequest = true; + } + + if ($this->profiler) { + $this->profiler = false; + + $this->kernel->boot(); + $this->kernel->getContainer()->get('profiler')->enable(); + } + + return parent::doRequest($request); + } + + /** + * {@inheritdoc} + * + * @param Request $request A Request instance + * + * @return Response A Response instance + */ + protected function doRequestInProcess($request) + { + $response = parent::doRequestInProcess($request); + + $this->profiler = false; + + return $response; + } + + /** + * Returns the script to execute when the request must be insulated. + * + * It assumes that the autoloader is named 'autoload.php' and that it is + * stored in the same directory as the kernel (this is the case for the + * Symfony Standard Edition). If this is not your case, create your own + * client and override this method. + * + * @param Request $request A Request instance + * + * @return string The script content + */ + protected function getScript($request) + { + $kernel = var_export(serialize($this->kernel), true); + $request = var_export(serialize($request), true); + $errorReporting = error_reporting(); + + $requires = ''; + foreach (get_declared_classes() as $class) { + if (0 === strpos($class, 'ComposerAutoloaderInit')) { + $r = new \ReflectionClass($class); + $file = \dirname($r->getFileName(), 2).'/autoload.php'; + if (file_exists($file)) { + $requires .= 'require_once '.var_export($file, true).";\n"; + } + } + } + + if (!$requires) { + throw new \RuntimeException('Composer autoloader not found.'); + } + + $requires .= 'require_once '.var_export((new \ReflectionObject($this->kernel))->getFileName(), true).";\n"; + + $profilerCode = ''; + if ($this->profiler) { + $profilerCode = '$kernel->getContainer()->get(\'profiler\')->enable();'; + } + + $code = <<boot(); +$profilerCode + +\$request = unserialize($request); +EOF; + + return $code.$this->getHandleScript(); + } +} diff --git a/vendor/symfony/framework-bundle/LICENSE b/vendor/symfony/framework-bundle/LICENSE new file mode 100644 index 0000000..a677f43 --- /dev/null +++ b/vendor/symfony/framework-bundle/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/framework-bundle/README.md b/vendor/symfony/framework-bundle/README.md new file mode 100644 index 0000000..9280d87 --- /dev/null +++ b/vendor/symfony/framework-bundle/README.md @@ -0,0 +1,10 @@ +FrameworkBundle +=============== + +Resources +--------- + + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/framework-bundle/Resources/config/annotations.xml b/vendor/symfony/framework-bundle/Resources/config/annotations.xml new file mode 100644 index 0000000..0ce6bf6 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/annotations.xml @@ -0,0 +1,56 @@ + + + + + + + + + + required + + + + + + + + class_exists + + + + + + + + + + + + + + + + + + %kernel.cache_dir%/annotations.php + #^Symfony\\(?:Component\\HttpKernel\\|Bundle\\FrameworkBundle\\Controller\\(?!.*Controller$))# + %kernel.debug% + + + + + + + %kernel.cache_dir%/annotations.php + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/assets.xml b/vendor/symfony/framework-bundle/Resources/config/assets.xml new file mode 100644 index 0000000..4aaa702 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/assets.xml @@ -0,0 +1,54 @@ + + + + + + + false + + + + + + + + + + + + + + + + + + %asset.request_context.base_path% + %asset.request_context.secure% + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/cache.xml b/vendor/symfony/framework-bundle/Resources/config/cache.xml new file mode 100644 index 0000000..9959deb --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/cache.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + %kernel.cache_dir%/pools + + + + + + + + 0 + + + + + + + + + + + + 0 + + + + + + + + + + 0 + %kernel.cache_dir%/pools + + + + + + + + + + + 0 + + + + + + + + 0 + + + + + + + + + + + + 0 + + + + + + + + + + + + 0 + + + + + + + + + + + 0 + + + + + + + null + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/cache_debug.xml b/vendor/symfony/framework-bundle/Resources/config/cache_debug.xml new file mode 100644 index 0000000..20e2276 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/cache_debug.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/collectors.xml b/vendor/symfony/framework-bundle/Resources/config/collectors.xml new file mode 100644 index 0000000..17df61d --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/collectors.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %kernel.cache_dir%/%kernel.container_class% + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/console.xml b/vendor/symfony/framework-bundle/Resources/config/console.xml new file mode 100644 index 0000000..6333f2d --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/console.xml @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + %kernel.project_dir% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + null + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %translator.default_path% + + + + + + + + + + + %kernel.default_locale% + %translator.default_path% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/debug.xml b/vendor/symfony/framework-bundle/Resources/config/debug.xml new file mode 100644 index 0000000..63a61ef --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/debug.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/debug_prod.xml b/vendor/symfony/framework-bundle/Resources/config/debug_prod.xml new file mode 100644 index 0000000..786158d --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/debug_prod.xml @@ -0,0 +1,31 @@ + + + + + + -1 + + + + + + + + + null + + null + %debug.error_handler.throw_at% + %kernel.debug% + + %kernel.debug% + + + + %debug.file_link_format% + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/error_renderer.xml b/vendor/symfony/framework-bundle/Resources/config/error_renderer.xml new file mode 100644 index 0000000..4d2423f --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/error_renderer.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + %kernel.debug% + + + %kernel.charset% + + %kernel.project_dir% + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/esi.xml b/vendor/symfony/framework-bundle/Resources/config/esi.xml new file mode 100644 index 0000000..65e26d8 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/esi.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/form.xml b/vendor/symfony/framework-bundle/Resources/config/form.xml new file mode 100644 index 0000000..17598fa --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/form.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %validator.translation_domain% + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/form_csrf.xml b/vendor/symfony/framework-bundle/Resources/config/form_csrf.xml new file mode 100644 index 0000000..5e897be --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/form_csrf.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + %form.type_extension.csrf.enabled% + %form.type_extension.csrf.field_name% + + %validator.translation_domain% + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/form_debug.xml b/vendor/symfony/framework-bundle/Resources/config/form_debug.xml new file mode 100644 index 0000000..5e3e97a --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/form_debug.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/fragment_listener.xml b/vendor/symfony/framework-bundle/Resources/config/fragment_listener.xml new file mode 100644 index 0000000..b7c6411 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/fragment_listener.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + %fragment.path% + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/fragment_renderer.xml b/vendor/symfony/framework-bundle/Resources/config/fragment_renderer.xml new file mode 100644 index 0000000..827a22f --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/fragment_renderer.xml @@ -0,0 +1,51 @@ + + + + + + + /_fragment + + + + + + + + + %kernel.debug% + + + + + + + %fragment.path% + + + + + + %fragment.renderer.hinclude.global_template% + %fragment.path% + + + + + + + + %fragment.path% + + + + + + + + %fragment.path% + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/http_client.xml b/vendor/symfony/framework-bundle/Resources/config/http_client.xml new file mode 100644 index 0000000..10256b6 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/http_client.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/http_client_debug.xml b/vendor/symfony/framework-bundle/Resources/config/http_client_debug.xml new file mode 100644 index 0000000..6d6ae4b --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/http_client_debug.xml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/identity_translator.xml b/vendor/symfony/framework-bundle/Resources/config/identity_translator.xml new file mode 100644 index 0000000..9dccb43 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/identity_translator.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/lock.xml b/vendor/symfony/framework-bundle/Resources/config/lock.xml new file mode 100644 index 0000000..86b8571 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/lock.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/mailer.xml b/vendor/symfony/framework-bundle/Resources/config/mailer.xml new file mode 100644 index 0000000..8a99eeb --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/mailer.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/mailer_debug.xml b/vendor/symfony/framework-bundle/Resources/config/mailer_debug.xml new file mode 100644 index 0000000..17e1a6e --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/mailer_debug.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/mailer_transports.xml b/vendor/symfony/framework-bundle/Resources/config/mailer_transports.xml new file mode 100644 index 0000000..d478942 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/mailer_transports.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/messenger.xml b/vendor/symfony/framework-bundle/Resources/config/messenger.xml new file mode 100644 index 0000000..14117ee --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/messenger.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/messenger_debug.xml b/vendor/symfony/framework-bundle/Resources/config/messenger_debug.xml new file mode 100644 index 0000000..96f43b3 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/messenger_debug.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/mime_type.xml b/vendor/symfony/framework-bundle/Resources/config/mime_type.xml new file mode 100644 index 0000000..d4c1eb1 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/mime_type.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/notifier.xml b/vendor/symfony/framework-bundle/Resources/config/notifier.xml new file mode 100644 index 0000000..dfc6cdc --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/notifier.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/notifier_transports.xml b/vendor/symfony/framework-bundle/Resources/config/notifier_transports.xml new file mode 100644 index 0000000..c4d9cf8 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/notifier_transports.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/profiling.xml b/vendor/symfony/framework-bundle/Resources/config/profiling.xml new file mode 100644 index 0000000..166be86 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/profiling.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + %profiler.storage.dsn% + + + + + + + null + %profiler_listener.only_exceptions% + %profiler_listener.only_master_requests% + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/property_access.xml b/vendor/symfony/framework-bundle/Resources/config/property_access.xml new file mode 100644 index 0000000..424f9f6 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/property_access.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/property_info.xml b/vendor/symfony/framework-bundle/Resources/config/property_info.xml new file mode 100644 index 0000000..cd78d7f --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/property_info.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/request.xml b/vendor/symfony/framework-bundle/Resources/config/request.xml new file mode 100644 index 0000000..048b61e --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/request.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/routing.xml b/vendor/symfony/framework-bundle/Resources/config/routing.xml new file mode 100644 index 0000000..49a3936 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/routing.xml @@ -0,0 +1,118 @@ + + + + + + localhost + http + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %router.resource% + + %kernel.cache_dir% + %kernel.debug% + Symfony\Component\Routing\Generator\CompiledUrlGenerator + Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper + Symfony\Bundle\FrameworkBundle\Routing\RedirectableCompiledUrlMatcher + Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper + + + + + %kernel.default_locale% + + + + + + + + + + + + + %router.request_context.base_url% + GET + %router.request_context.host% + %router.request_context.scheme% + %request_listener.http_port% + %request_listener.https_port% + + + + + + + + + + + + + + + + + %kernel.project_dir% + %kernel.debug% + + + + + %request_listener.http_port% + %request_listener.https_port% + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/routing/errors.xml b/vendor/symfony/framework-bundle/Resources/config/routing/errors.xml new file mode 100644 index 0000000..13a9cc4 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/routing/errors.xml @@ -0,0 +1,12 @@ + + + + + + error_controller::preview + html + \d+ + + diff --git a/vendor/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd b/vendor/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd new file mode 100644 index 0000000..b8e4488 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd @@ -0,0 +1,560 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/secrets.xml b/vendor/symfony/framework-bundle/Resources/config/secrets.xml new file mode 100644 index 0000000..65fd107 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/secrets.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/security_csrf.xml b/vendor/symfony/framework-bundle/Resources/config/security_csrf.xml new file mode 100644 index 0000000..eefe6ad --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/security_csrf.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/serializer.xml b/vendor/symfony/framework-bundle/Resources/config/serializer.xml new file mode 100644 index 0000000..0dbc388 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/serializer.xml @@ -0,0 +1,175 @@ + + + + + + %kernel.cache_dir%/serialization.php + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %kernel.debug% + + + + + + + + + + + null + + + + + + + + + + + + + + + + + + + + + null + + + + + + + + %serializer.mapping.cache.file% + + + + + + %serializer.mapping.cache.file% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %kernel.debug% + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/services.xml b/vendor/symfony/framework-bundle/Resources/config/services.xml new file mode 100644 index 0000000..ac406aa --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/services.xml @@ -0,0 +1,132 @@ + + + + + + + + console.command + console.error + console.terminate + form.pre_submit + form.submit + form.post_submit + form.pre_set_data + form.post_set_data + kernel.controller_arguments + kernel.controller + kernel.response + kernel.finish_request + kernel.request + kernel.view + kernel.exception + kernel.terminate + workflow.guard + workflow.leave + workflow.transition + workflow.enter + workflow.entered + workflow.completed + workflow.announce + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %kernel.debug% + %kernel.cache_dir%/%kernel.container_class%Deprecations.log + + + + + + + + + + + + + + + + + + + %kernel.secret% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %kernel.default_locale% + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/session.xml b/vendor/symfony/framework-bundle/Resources/config/session.xml new file mode 100644 index 0000000..0cb7b4e --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/session.xml @@ -0,0 +1,75 @@ + + + + + + _sf2_meta + + + + + + + + + + + + + + + + + %session.metadata.storage_key% + %session.metadata.update_threshold% + + + + %session.storage.options% + + + + + + + + + + + + + + + + %kernel.cache_dir%/sessions + MOCKSESSID + + + + + + + %session.save_path% + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/ssi.xml b/vendor/symfony/framework-bundle/Resources/config/ssi.xml new file mode 100644 index 0000000..b4e5b3d --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/ssi.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/test.xml b/vendor/symfony/framework-bundle/Resources/config/test.xml new file mode 100644 index 0000000..ef571fd --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/test.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + %test.client.parameters% + + + + + + + + + + + + + + + + + + test.private_services_locator + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/translation.xml b/vendor/symfony/framework-bundle/Resources/config/translation.xml new file mode 100644 index 0000000..07213a2 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/translation.xml @@ -0,0 +1,144 @@ + + + + + + + + + + + %kernel.default_locale% + + + %kernel.cache_dir%/translations + %kernel.debug% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + yaml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/translation_debug.xml b/vendor/symfony/framework-bundle/Resources/config/translation_debug.xml new file mode 100644 index 0000000..c9c5385 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/translation_debug.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/validator.xml b/vendor/symfony/framework-bundle/Resources/config/validator.xml new file mode 100644 index 0000000..070908f --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/validator.xml @@ -0,0 +1,75 @@ + + + + + + + %kernel.cache_dir%/validation.php + + + + + + + + + + + + + + + + + + + + %validator.translation_domain% + + + + + + + + %validator.mapping.cache.file% + + + + + + %validator.mapping.cache.file% + + + + + + + + + + + + + + + + + + + %kernel.charset% + false + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/validator_debug.xml b/vendor/symfony/framework-bundle/Resources/config/validator_debug.xml new file mode 100644 index 0000000..939c555 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/validator_debug.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/web.xml b/vendor/symfony/framework-bundle/Resources/config/web.xml new file mode 100644 index 0000000..cbdc558 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/web.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %kernel.charset% + + + + + + + + + + %kernel.default_locale% + + + + + + + + + + + + + + %kernel.error_controller% + + + + + + + %kernel.error_controller% + + %kernel.debug% + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/web_link.xml b/vendor/symfony/framework-bundle/Resources/config/web_link.xml new file mode 100644 index 0000000..bf3e8d7 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/web_link.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/config/workflow.xml b/vendor/symfony/framework-bundle/Resources/config/workflow.xml new file mode 100644 index 0000000..78741de --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/config/workflow.xml @@ -0,0 +1,30 @@ + + + + + + + + + + null + + + + + + null + + + + + + + + + + + + diff --git a/vendor/symfony/framework-bundle/Resources/views/Form/week_widget.html.php b/vendor/symfony/framework-bundle/Resources/views/Form/week_widget.html.php new file mode 100644 index 0000000..610b6e0 --- /dev/null +++ b/vendor/symfony/framework-bundle/Resources/views/Form/week_widget.html.php @@ -0,0 +1,14 @@ + + block($form, 'form_widget_simple'); ?> + + ['size' => 1]] : [] ?> +
    block($form, 'widget_container_attributes') ?>> + widget($form['year'], $vars); + echo '-'; + echo $view['form']->widget($form['week'], $vars); + ?> +
    + diff --git a/vendor/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php b/vendor/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php new file mode 100644 index 0000000..51419c8 --- /dev/null +++ b/vendor/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Routing; + +use Symfony\Component\Routing\Loader\AnnotationClassLoader; +use Symfony\Component\Routing\Route; + +/** + * AnnotatedRouteControllerLoader is an implementation of AnnotationClassLoader + * that sets the '_controller' default based on the class and method names. + * + * @author Fabien Potencier + */ +class AnnotatedRouteControllerLoader extends AnnotationClassLoader +{ + /** + * Configures the _controller default parameter of a given Route instance. + * + * @param mixed $annot The annotation class instance + */ + protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot) + { + if ('__invoke' === $method->getName()) { + $route->setDefault('_controller', $class->getName()); + } else { + $route->setDefault('_controller', $class->getName().'::'.$method->getName()); + } + } + + /** + * Makes the default route name more sane by removing common keywords. + * + * @return string + */ + protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) + { + return preg_replace([ + '/(bundle|controller)_/', + '/action(_\d+)?$/', + '/__/', + ], [ + '_', + '\\1', + '_', + ], parent::getDefaultRouteName($class, $method)); + } +} diff --git a/vendor/symfony/framework-bundle/Routing/DelegatingLoader.php b/vendor/symfony/framework-bundle/Routing/DelegatingLoader.php new file mode 100644 index 0000000..f25bdf3 --- /dev/null +++ b/vendor/symfony/framework-bundle/Routing/DelegatingLoader.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Routing; + +use Symfony\Component\Config\Exception\LoaderLoadException; +use Symfony\Component\Config\Loader\DelegatingLoader as BaseDelegatingLoader; +use Symfony\Component\Config\Loader\LoaderResolverInterface; + +/** + * DelegatingLoader delegates route loading to other loaders using a loader resolver. + * + * This implementation resolves the _controller attribute from the short notation + * to the fully-qualified form (from a:b:c to class::method). + * + * @author Fabien Potencier + * + * @final + */ +class DelegatingLoader extends BaseDelegatingLoader +{ + private $loading = false; + private $defaultOptions; + + public function __construct(LoaderResolverInterface $resolver, array $defaultOptions = []) + { + $this->defaultOptions = $defaultOptions; + + parent::__construct($resolver); + } + + /** + * {@inheritdoc} + */ + public function load($resource, string $type = null) + { + if ($this->loading) { + // This can happen if a fatal error occurs in parent::load(). + // Here is the scenario: + // - while routes are being loaded by parent::load() below, a fatal error + // occurs (e.g. parse error in a controller while loading annotations); + // - PHP abruptly empties the stack trace, bypassing all catch/finally blocks; + // it then calls the registered shutdown functions; + // - the ErrorHandler catches the fatal error and re-injects it for rendering + // thanks to HttpKernel->terminateWithException() (that calls handleException()); + // - at this stage, if we try to load the routes again, we must prevent + // the fatal error from occurring a second time, + // otherwise the PHP process would be killed immediately; + // - while rendering the exception page, the router can be required + // (by e.g. the web profiler that needs to generate an URL); + // - this handles the case and prevents the second fatal error + // by triggering an exception beforehand. + + throw new LoaderLoadException($resource, null, null, null, $type); + } + $this->loading = true; + + try { + $collection = parent::load($resource, $type); + } finally { + $this->loading = false; + } + + foreach ($collection->all() as $route) { + if ($this->defaultOptions) { + $route->setOptions($route->getOptions() + $this->defaultOptions); + } + if (!\is_string($controller = $route->getDefault('_controller'))) { + continue; + } + + if (false !== strpos($controller, '::')) { + continue; + } + + $route->setDefault('_controller', $controller); + } + + return $collection; + } +} diff --git a/vendor/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php b/vendor/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php new file mode 100644 index 0000000..dba9d6d --- /dev/null +++ b/vendor/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Routing; + +use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; + +/** + * @author Fabien Potencier + * + * @internal + */ +class RedirectableCompiledUrlMatcher extends CompiledUrlMatcher implements RedirectableUrlMatcherInterface +{ + /** + * {@inheritdoc} + */ + public function redirect(string $path, string $route, string $scheme = null): array + { + return [ + '_controller' => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController::urlRedirectAction', + 'path' => $path, + 'permanent' => true, + 'scheme' => $scheme, + 'httpPort' => $this->context->getHttpPort(), + 'httpsPort' => $this->context->getHttpsPort(), + '_route' => $route, + ]; + } +} diff --git a/vendor/symfony/framework-bundle/Routing/RouteLoaderInterface.php b/vendor/symfony/framework-bundle/Routing/RouteLoaderInterface.php new file mode 100644 index 0000000..d1cb55a --- /dev/null +++ b/vendor/symfony/framework-bundle/Routing/RouteLoaderInterface.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Routing; + +/** + * Marker interface for service route loaders. + */ +interface RouteLoaderInterface +{ +} diff --git a/vendor/symfony/framework-bundle/Routing/Router.php b/vendor/symfony/framework-bundle/Routing/Router.php new file mode 100644 index 0000000..f9def3d --- /dev/null +++ b/vendor/symfony/framework-bundle/Routing/Router.php @@ -0,0 +1,189 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Routing; + +use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\DependencyInjection\Config\ContainerParametersResource; +use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; +use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\Router as BaseRouter; +use Symfony\Contracts\Service\ServiceSubscriberInterface; + +/** + * This Router creates the Loader only when the cache is empty. + * + * @author Fabien Potencier + */ +class Router extends BaseRouter implements WarmableInterface, ServiceSubscriberInterface +{ + private $container; + private $collectedParameters = []; + private $paramFetcher; + + /** + * @param mixed $resource The main resource to load + */ + public function __construct(ContainerInterface $container, $resource, array $options = [], RequestContext $context = null, ContainerInterface $parameters = null, LoggerInterface $logger = null, string $defaultLocale = null) + { + $this->container = $container; + $this->resource = $resource; + $this->context = $context ?: new RequestContext(); + $this->logger = $logger; + $this->setOptions($options); + + if ($parameters) { + $this->paramFetcher = [$parameters, 'get']; + } elseif ($container instanceof SymfonyContainerInterface) { + $this->paramFetcher = [$container, 'getParameter']; + } else { + throw new \LogicException(sprintf('You should either pass a "%s" instance or provide the $parameters argument of the "%s" method.', SymfonyContainerInterface::class, __METHOD__)); + } + + $this->defaultLocale = $defaultLocale; + } + + /** + * {@inheritdoc} + */ + public function getRouteCollection() + { + if (null === $this->collection) { + $this->collection = $this->container->get('routing.loader')->load($this->resource, $this->options['resource_type']); + $this->resolveParameters($this->collection); + $this->collection->addResource(new ContainerParametersResource($this->collectedParameters)); + } + + return $this->collection; + } + + /** + * {@inheritdoc} + */ + public function warmUp(string $cacheDir) + { + $currentDir = $this->getOption('cache_dir'); + + // force cache generation + $this->setOption('cache_dir', $cacheDir); + $this->getMatcher(); + $this->getGenerator(); + + $this->setOption('cache_dir', $currentDir); + } + + /** + * Replaces placeholders with service container parameter values in: + * - the route defaults, + * - the route requirements, + * - the route path, + * - the route host, + * - the route schemes, + * - the route methods. + */ + private function resolveParameters(RouteCollection $collection) + { + foreach ($collection as $route) { + foreach ($route->getDefaults() as $name => $value) { + $route->setDefault($name, $this->resolve($value)); + } + + foreach ($route->getRequirements() as $name => $value) { + $route->setRequirement($name, $this->resolve($value)); + } + + $route->setPath($this->resolve($route->getPath())); + $route->setHost($this->resolve($route->getHost())); + + $schemes = []; + foreach ($route->getSchemes() as $scheme) { + $schemes = array_merge($schemes, explode('|', $this->resolve($scheme))); + } + $route->setSchemes($schemes); + + $methods = []; + foreach ($route->getMethods() as $method) { + $methods = array_merge($methods, explode('|', $this->resolve($method))); + } + $route->setMethods($methods); + $route->setCondition($this->resolve($route->getCondition())); + } + } + + /** + * Recursively replaces placeholders with the service container parameters. + * + * @param mixed $value The source which might contain "%placeholders%" + * + * @return mixed The source with the placeholders replaced by the container + * parameters. Arrays are resolved recursively. + * + * @throws ParameterNotFoundException When a placeholder does not exist as a container parameter + * @throws RuntimeException When a container value is not a string or a numeric value + */ + private function resolve($value) + { + if (\is_array($value)) { + foreach ($value as $key => $val) { + $value[$key] = $this->resolve($val); + } + + return $value; + } + + if (!\is_string($value)) { + return $value; + } + + $escapedValue = preg_replace_callback('/%%|%([^%\s]++)%/', function ($match) use ($value) { + // skip %% + if (!isset($match[1])) { + return '%%'; + } + + if (preg_match('/^env\((?:\w++:)*+\w++\)$/', $match[1])) { + throw new RuntimeException(sprintf('Using "%%%s%%" is not allowed in routing configuration.', $match[1])); + } + + $resolved = ($this->paramFetcher)($match[1]); + + if (\is_bool($resolved)) { + $resolved = (string) (int) $resolved; + } + + if (\is_string($resolved) || is_numeric($resolved)) { + $this->collectedParameters[$match[1]] = $resolved; + + return (string) $this->resolve($resolved); + } + + throw new RuntimeException(sprintf('The container parameter "%s", used in the route configuration value "%s", must be a string or numeric, but it is of type %s.', $match[1], $value, \gettype($resolved))); + }, $value); + + return str_replace('%%', '%', $escapedValue); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedServices() + { + return [ + 'routing.loader' => LoaderInterface::class, + ]; + } +} diff --git a/vendor/symfony/framework-bundle/Secrets/AbstractVault.php b/vendor/symfony/framework-bundle/Secrets/AbstractVault.php new file mode 100644 index 0000000..eeecbbb --- /dev/null +++ b/vendor/symfony/framework-bundle/Secrets/AbstractVault.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Secrets; + +/** + * @author Nicolas Grekas + * + * @internal + */ +abstract class AbstractVault +{ + protected $lastMessage; + + public function getLastMessage(): ?string + { + return $this->lastMessage; + } + + abstract public function generateKeys(bool $override = false): bool; + + abstract public function seal(string $name, string $value): void; + + abstract public function reveal(string $name): ?string; + + abstract public function remove(string $name): bool; + + abstract public function list(bool $reveal = false): array; + + protected function validateName(string $name): void + { + if (!preg_match('/^\w++$/D', $name)) { + throw new \LogicException(sprintf('Invalid secret name "%s": only "word" characters are allowed.', $name)); + } + } + + protected function getPrettyPath(string $path) + { + return str_replace(getcwd().\DIRECTORY_SEPARATOR, '', $path); + } +} diff --git a/vendor/symfony/framework-bundle/Secrets/DotenvVault.php b/vendor/symfony/framework-bundle/Secrets/DotenvVault.php new file mode 100644 index 0000000..a64a744 --- /dev/null +++ b/vendor/symfony/framework-bundle/Secrets/DotenvVault.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Secrets; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class DotenvVault extends AbstractVault +{ + private $dotenvFile; + + public function __construct(string $dotenvFile) + { + $this->dotenvFile = strtr($dotenvFile, '/', \DIRECTORY_SEPARATOR); + } + + public function generateKeys(bool $override = false): bool + { + $this->lastMessage = 'The dotenv vault doesn\'t encrypt secrets thus doesn\'t need keys.'; + + return false; + } + + public function seal(string $name, string $value): void + { + $this->lastMessage = null; + $this->validateName($name); + $v = str_replace("'", "'\\''", $value); + + $content = file_exists($this->dotenvFile) ? file_get_contents($this->dotenvFile) : ''; + $content = preg_replace("/^$name=((\\\\'|'[^']++')++|.*)/m", "$name='$v'", $content, -1, $count); + + if (!$count) { + $content .= "$name='$v'\n"; + } + + file_put_contents($this->dotenvFile, $content); + + $this->lastMessage = sprintf('Secret "%s" %s in "%s".', $name, $count ? 'added' : 'updated', $this->getPrettyPath($this->dotenvFile)); + } + + public function reveal(string $name): ?string + { + $this->lastMessage = null; + $this->validateName($name); + $v = \is_string($_SERVER[$name] ?? null) && 0 !== strpos($name, 'HTTP_') ? $_SERVER[$name] : ($_ENV[$name] ?? null); + + if (null === $v) { + $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile)); + + return null; + } + + return $v; + } + + public function remove(string $name): bool + { + $this->lastMessage = null; + $this->validateName($name); + + $content = file_exists($this->dotenvFile) ? file_get_contents($this->dotenvFile) : ''; + $content = preg_replace("/^$name=((\\\\'|'[^']++')++|.*)\n?/m", '', $content, -1, $count); + + if ($count) { + file_put_contents($this->dotenvFile, $content); + $this->lastMessage = sprintf('Secret "%s" removed from file "%s".', $name, $this->getPrettyPath($this->dotenvFile)); + + return true; + } + + $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile)); + + return false; + } + + public function list(bool $reveal = false): array + { + $this->lastMessage = null; + $secrets = []; + + foreach ($_ENV as $k => $v) { + if (preg_match('/^\w+$/D', $k)) { + $secrets[$k] = $reveal ? $v : null; + } + } + + foreach ($_SERVER as $k => $v) { + if (\is_string($v) && preg_match('/^\w+$/D', $k)) { + $secrets[$k] = $reveal ? $v : null; + } + } + + return $secrets; + } +} diff --git a/vendor/symfony/framework-bundle/Secrets/SodiumVault.php b/vendor/symfony/framework-bundle/Secrets/SodiumVault.php new file mode 100644 index 0000000..883a686 --- /dev/null +++ b/vendor/symfony/framework-bundle/Secrets/SodiumVault.php @@ -0,0 +1,220 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Secrets; + +use Symfony\Component\DependencyInjection\EnvVarLoaderInterface; + +/** + * @author Tobias Schultze + * @author Jérémy Derussé + * @author Nicolas Grekas + * + * @internal + */ +class SodiumVault extends AbstractVault implements EnvVarLoaderInterface +{ + private $encryptionKey; + private $decryptionKey; + private $pathPrefix; + private $secretsDir; + + /** + * @param string|object|null $decryptionKey A string or a stringable object that defines the private key to use to decrypt the vault + * or null to store generated keys in the provided $secretsDir + */ + public function __construct(string $secretsDir, $decryptionKey = null) + { + if (null !== $decryptionKey && !\is_string($decryptionKey) && !(\is_object($decryptionKey) && method_exists($decryptionKey, '__toString'))) { + throw new \TypeError(sprintf('Decryption key should be a string or an object that implements the __toString() method, %s given.', \gettype($decryptionKey))); + } + + $this->pathPrefix = rtrim(strtr($secretsDir, '/', \DIRECTORY_SEPARATOR), \DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR.basename($secretsDir).'.'; + $this->decryptionKey = $decryptionKey; + $this->secretsDir = $secretsDir; + } + + public function generateKeys(bool $override = false): bool + { + $this->lastMessage = null; + + if (null === $this->encryptionKey && '' !== $this->decryptionKey = (string) $this->decryptionKey) { + throw new \LogicException('Cannot generate keys when a decryption key has been provided while instantiating the vault.'); + } + + try { + $this->loadKeys(); + } catch (\RuntimeException $e) { + // ignore failures to load keys + } + + if ('' !== $this->decryptionKey && !file_exists($this->pathPrefix.'encrypt.public.php')) { + $this->export('encrypt.public', $this->encryptionKey); + } + + if (!$override && null !== $this->encryptionKey) { + $this->lastMessage = sprintf('Sodium keys already exist at "%s*.{public,private}" and won\'t be overridden.', $this->getPrettyPath($this->pathPrefix)); + + return false; + } + + $this->decryptionKey = sodium_crypto_box_keypair(); + $this->encryptionKey = sodium_crypto_box_publickey($this->decryptionKey); + + $this->export('encrypt.public', $this->encryptionKey); + $this->export('decrypt.private', $this->decryptionKey); + + $this->lastMessage = sprintf('Sodium keys have been generated at "%s*.public/private.php".', $this->getPrettyPath($this->pathPrefix)); + + return true; + } + + public function seal(string $name, string $value): void + { + $this->lastMessage = null; + $this->validateName($name); + $this->loadKeys(); + $this->export($name.'.'.substr(md5($name), 0, 6), sodium_crypto_box_seal($value, $this->encryptionKey ?? sodium_crypto_box_publickey($this->decryptionKey))); + + $list = $this->list(); + $list[$name] = null; + uksort($list, 'strnatcmp'); + file_put_contents($this->pathPrefix.'list.php', sprintf("lastMessage = sprintf('Secret "%s" encrypted in "%s"; you can commit it.', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); + } + + public function reveal(string $name): ?string + { + $this->lastMessage = null; + $this->validateName($name); + + if (!file_exists($file = $this->pathPrefix.$name.'.'.substr_replace(md5($name), '.php', -26))) { + $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); + + return null; + } + + if (!\function_exists('sodium_crypto_box_seal')) { + $this->lastMessage = sprintf('Secret "%s" cannot be revealed as the "sodium" PHP extension missing. Try running "composer require paragonie/sodium_compat" if you cannot enable the extension."', $name); + + return null; + } + + $this->loadKeys(); + + if ('' === $this->decryptionKey) { + $this->lastMessage = sprintf('Secret "%s" cannot be revealed as no decryption key was found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); + + return null; + } + + if (false === $value = sodium_crypto_box_seal_open(include $file, $this->decryptionKey)) { + $this->lastMessage = sprintf('Secret "%s" cannot be revealed as the wrong decryption key was provided for "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); + + return null; + } + + return $value; + } + + public function remove(string $name): bool + { + $this->lastMessage = null; + $this->validateName($name); + + if (!file_exists($file = $this->pathPrefix.$name.'.'.substr_replace(md5($name), '.php', -26))) { + $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); + + return false; + } + + $list = $this->list(); + unset($list[$name]); + file_put_contents($this->pathPrefix.'list.php', sprintf("lastMessage = sprintf('Secret "%s" removed from "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); + + return @unlink($file) || !file_exists($file); + } + + public function list(bool $reveal = false): array + { + $this->lastMessage = null; + + if (!file_exists($file = $this->pathPrefix.'list.php')) { + return []; + } + + $secrets = include $file; + + if (!$reveal) { + return $secrets; + } + + foreach ($secrets as $name => $value) { + $secrets[$name] = $this->reveal($name); + } + + return $secrets; + } + + public function loadEnvVars(): array + { + return $this->list(true); + } + + private function loadKeys(): void + { + if (!\function_exists('sodium_crypto_box_seal')) { + throw new \LogicException('The "sodium" PHP extension is required to deal with secrets. Alternatively, try running "composer require paragonie/sodium_compat" if you cannot enable the extension."'); + } + + if (null !== $this->encryptionKey || '' !== $this->decryptionKey = (string) $this->decryptionKey) { + return; + } + + if (file_exists($this->pathPrefix.'decrypt.private.php')) { + $this->decryptionKey = (string) include $this->pathPrefix.'decrypt.private.php'; + } + + if (file_exists($this->pathPrefix.'encrypt.public.php')) { + $this->encryptionKey = (string) include $this->pathPrefix.'encrypt.public.php'; + } elseif ('' !== $this->decryptionKey) { + $this->encryptionKey = sodium_crypto_box_publickey($this->decryptionKey); + } else { + throw new \RuntimeException(sprintf('Encryption key not found in "%s".', \dirname($this->pathPrefix))); + } + } + + private function export(string $file, string $data): void + { + $name = basename($this->pathPrefix.$file); + $data = str_replace('%', '\x', rawurlencode($data)); + $data = sprintf("createSecretsDir(); + + if (false === file_put_contents($this->pathPrefix.$file.'.php', $data, LOCK_EX)) { + $e = error_get_last(); + throw new \ErrorException($e['message'] ?? 'Failed to write secrets data.', 0, $e['type'] ?? E_USER_WARNING); + } + } + + private function createSecretsDir(): void + { + if ($this->secretsDir && !is_dir($this->secretsDir) && !@mkdir($this->secretsDir, 0777, true) && !is_dir($this->secretsDir)) { + throw new \RuntimeException(sprintf('Unable to create the secrets directory (%s)', $this->secretsDir)); + } + + $this->secretsDir = null; + } +} diff --git a/vendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php b/vendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php new file mode 100644 index 0000000..086d83e --- /dev/null +++ b/vendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php @@ -0,0 +1,159 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Test; + +use PHPUnit\Framework\Constraint\LogicalAnd; +use PHPUnit\Framework\Constraint\LogicalNot; +use Symfony\Component\BrowserKit\AbstractBrowser; +use Symfony\Component\BrowserKit\Test\Constraint as BrowserKitConstraint; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Test\Constraint as ResponseConstraint; + +/** + * Ideas borrowed from Laravel Dusk's assertions. + * + * @see https://laravel.com/docs/5.7/dusk#available-assertions + */ +trait BrowserKitAssertionsTrait +{ + public static function assertResponseIsSuccessful(string $message = ''): void + { + self::assertThat(self::getResponse(), new ResponseConstraint\ResponseIsSuccessful(), $message); + } + + public static function assertResponseStatusCodeSame(int $expectedCode, string $message = ''): void + { + self::assertThat(self::getResponse(), new ResponseConstraint\ResponseStatusCodeSame($expectedCode), $message); + } + + public static function assertResponseRedirects(string $expectedLocation = null, int $expectedCode = null, string $message = ''): void + { + $constraint = new ResponseConstraint\ResponseIsRedirected(); + if ($expectedLocation) { + $constraint = LogicalAnd::fromConstraints($constraint, new ResponseConstraint\ResponseHeaderSame('Location', $expectedLocation)); + } + if ($expectedCode) { + $constraint = LogicalAnd::fromConstraints($constraint, new ResponseConstraint\ResponseStatusCodeSame($expectedCode)); + } + + self::assertThat(self::getResponse(), $constraint, $message); + } + + public static function assertResponseHasHeader(string $headerName, string $message = ''): void + { + self::assertThat(self::getResponse(), new ResponseConstraint\ResponseHasHeader($headerName), $message); + } + + public static function assertResponseNotHasHeader(string $headerName, string $message = ''): void + { + self::assertThat(self::getResponse(), new LogicalNot(new ResponseConstraint\ResponseHasHeader($headerName)), $message); + } + + public static function assertResponseHeaderSame(string $headerName, string $expectedValue, string $message = ''): void + { + self::assertThat(self::getResponse(), new ResponseConstraint\ResponseHeaderSame($headerName, $expectedValue), $message); + } + + public static function assertResponseHeaderNotSame(string $headerName, string $expectedValue, string $message = ''): void + { + self::assertThat(self::getResponse(), new LogicalNot(new ResponseConstraint\ResponseHeaderSame($headerName, $expectedValue)), $message); + } + + public static function assertResponseHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void + { + self::assertThat(self::getResponse(), new ResponseConstraint\ResponseHasCookie($name, $path, $domain), $message); + } + + public static function assertResponseNotHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void + { + self::assertThat(self::getResponse(), new LogicalNot(new ResponseConstraint\ResponseHasCookie($name, $path, $domain)), $message); + } + + public static function assertResponseCookieValueSame(string $name, string $expectedValue, string $path = '/', string $domain = null, string $message = ''): void + { + self::assertThat(self::getResponse(), LogicalAnd::fromConstraints( + new ResponseConstraint\ResponseHasCookie($name, $path, $domain), + new ResponseConstraint\ResponseCookieValueSame($name, $expectedValue, $path, $domain) + ), $message); + } + + public static function assertBrowserHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void + { + self::assertThat(self::getClient(), new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain), $message); + } + + public static function assertBrowserNotHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void + { + self::assertThat(self::getClient(), new LogicalNot(new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain)), $message); + } + + public static function assertBrowserCookieValueSame(string $name, string $expectedValue, bool $raw = false, string $path = '/', string $domain = null, string $message = ''): void + { + self::assertThat(self::getClient(), LogicalAnd::fromConstraints( + new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain), + new BrowserKitConstraint\BrowserCookieValueSame($name, $expectedValue, $raw, $path, $domain) + ), $message); + } + + public static function assertRequestAttributeValueSame(string $name, string $expectedValue, string $message = ''): void + { + self::assertThat(self::getRequest(), new ResponseConstraint\RequestAttributeValueSame($name, $expectedValue), $message); + } + + public static function assertRouteSame($expectedRoute, array $parameters = [], string $message = ''): void + { + $constraint = new ResponseConstraint\RequestAttributeValueSame('_route', $expectedRoute); + $constraints = []; + foreach ($parameters as $key => $value) { + $constraints[] = new ResponseConstraint\RequestAttributeValueSame($key, $value); + } + if ($constraints) { + $constraint = LogicalAnd::fromConstraints($constraint, ...$constraints); + } + + self::assertThat(self::getRequest(), $constraint, $message); + } + + private static function getClient(AbstractBrowser $newClient = null): ?AbstractBrowser + { + static $client; + + if (0 < \func_num_args()) { + return $client = $newClient; + } + + if (!$client instanceof AbstractBrowser) { + static::fail(sprintf('A client must be set to make assertions on it. Did you forget to call "%s::createClient()"?', __CLASS__)); + } + + return $client; + } + + private static function getResponse(): Response + { + if (!$response = self::getClient()->getResponse()) { + static::fail('A client must have an HTTP Response to make assertions. Did you forget to make an HTTP request?'); + } + + return $response; + } + + private static function getRequest(): Request + { + if (!$request = self::getClient()->getRequest()) { + static::fail('A client must have an HTTP Request to make assertions. Did you forget to make an HTTP request?'); + } + + return $request; + } +} diff --git a/vendor/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php b/vendor/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php new file mode 100644 index 0000000..465c265 --- /dev/null +++ b/vendor/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Test; + +use PHPUnit\Framework\Constraint\LogicalAnd; +use PHPUnit\Framework\Constraint\LogicalNot; +use Symfony\Component\DomCrawler\Crawler; +use Symfony\Component\DomCrawler\Test\Constraint as DomCrawlerConstraint; + +/** + * Ideas borrowed from Laravel Dusk's assertions. + * + * @see https://laravel.com/docs/5.7/dusk#available-assertions + */ +trait DomCrawlerAssertionsTrait +{ + public static function assertSelectorExists(string $selector, string $message = ''): void + { + self::assertThat(self::getCrawler(), new DomCrawlerConstraint\CrawlerSelectorExists($selector), $message); + } + + public static function assertSelectorNotExists(string $selector, string $message = ''): void + { + self::assertThat(self::getCrawler(), new LogicalNot(new DomCrawlerConstraint\CrawlerSelectorExists($selector)), $message); + } + + public static function assertSelectorTextContains(string $selector, string $text, string $message = ''): void + { + self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( + new DomCrawlerConstraint\CrawlerSelectorExists($selector), + new DomCrawlerConstraint\CrawlerSelectorTextContains($selector, $text) + ), $message); + } + + public static function assertSelectorTextSame(string $selector, string $text, string $message = ''): void + { + self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( + new DomCrawlerConstraint\CrawlerSelectorExists($selector), + new DomCrawlerConstraint\CrawlerSelectorTextSame($selector, $text) + ), $message); + } + + public static function assertSelectorTextNotContains(string $selector, string $text, string $message = ''): void + { + self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( + new DomCrawlerConstraint\CrawlerSelectorExists($selector), + new LogicalNot(new DomCrawlerConstraint\CrawlerSelectorTextContains($selector, $text)) + ), $message); + } + + public static function assertPageTitleSame(string $expectedTitle, string $message = ''): void + { + self::assertSelectorTextSame('title', $expectedTitle, $message); + } + + public static function assertPageTitleContains(string $expectedTitle, string $message = ''): void + { + self::assertSelectorTextContains('title', $expectedTitle, $message); + } + + public static function assertInputValueSame(string $fieldName, string $expectedValue, string $message = ''): void + { + self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( + new DomCrawlerConstraint\CrawlerSelectorExists("input[name=\"$fieldName\"]"), + new DomCrawlerConstraint\CrawlerSelectorAttributeValueSame("input[name=\"$fieldName\"]", 'value', $expectedValue) + ), $message); + } + + public static function assertInputValueNotSame(string $fieldName, string $expectedValue, string $message = ''): void + { + self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( + new DomCrawlerConstraint\CrawlerSelectorExists("input[name=\"$fieldName\"]"), + new LogicalNot(new DomCrawlerConstraint\CrawlerSelectorAttributeValueSame("input[name=\"$fieldName\"]", 'value', $expectedValue)) + ), $message); + } + + private static function getCrawler(): Crawler + { + if (!$crawler = self::getClient()->getCrawler()) { + static::fail('A client must have a crawler to make assertions. Did you forget to make an HTTP request?'); + } + + return $crawler; + } +} diff --git a/vendor/symfony/framework-bundle/Test/KernelTestCase.php b/vendor/symfony/framework-bundle/Test/KernelTestCase.php new file mode 100644 index 0000000..478b398 --- /dev/null +++ b/vendor/symfony/framework-bundle/Test/KernelTestCase.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Test; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Contracts\Service\ResetInterface; + +/** + * KernelTestCase is the base class for tests needing a Kernel. + * + * @author Fabien Potencier + */ +abstract class KernelTestCase extends TestCase +{ + protected static $class; + + /** + * @var KernelInterface + */ + protected static $kernel; + + /** + * @var ContainerInterface + */ + protected static $container; + + protected static $booted = false; + + private static $kernelContainer; + + protected function tearDown(): void + { + static::ensureKernelShutdown(); + static::$kernel = null; + } + + /** + * @return string The Kernel class name + * + * @throws \RuntimeException + * @throws \LogicException + */ + protected static function getKernelClass() + { + if (!isset($_SERVER['KERNEL_CLASS']) && !isset($_ENV['KERNEL_CLASS'])) { + throw new \LogicException(sprintf('You must set the KERNEL_CLASS environment variable to the fully-qualified class name of your Kernel in phpunit.xml / phpunit.xml.dist or override the %1$s::createKernel() or %1$s::getKernelClass() method.', static::class)); + } + + if (!class_exists($class = $_ENV['KERNEL_CLASS'] ?? $_SERVER['KERNEL_CLASS'])) { + throw new \RuntimeException(sprintf('Class "%s" doesn\'t exist or cannot be autoloaded. Check that the KERNEL_CLASS value in phpunit.xml matches the fully-qualified class name of your Kernel or override the %s::createKernel() method.', $class, static::class)); + } + + return $class; + } + + /** + * Boots the Kernel for this test. + * + * @return KernelInterface A KernelInterface instance + */ + protected static function bootKernel(array $options = []) + { + static::ensureKernelShutdown(); + + static::$kernel = static::createKernel($options); + static::$kernel->boot(); + static::$booted = true; + + self::$kernelContainer = $container = static::$kernel->getContainer(); + static::$container = $container->has('test.service_container') ? $container->get('test.service_container') : $container; + + return static::$kernel; + } + + /** + * Creates a Kernel. + * + * Available options: + * + * * environment + * * debug + * + * @return KernelInterface A KernelInterface instance + */ + protected static function createKernel(array $options = []) + { + if (null === static::$class) { + static::$class = static::getKernelClass(); + } + + if (isset($options['environment'])) { + $env = $options['environment']; + } elseif (isset($_ENV['APP_ENV'])) { + $env = $_ENV['APP_ENV']; + } elseif (isset($_SERVER['APP_ENV'])) { + $env = $_SERVER['APP_ENV']; + } else { + $env = 'test'; + } + + if (isset($options['debug'])) { + $debug = $options['debug']; + } elseif (isset($_ENV['APP_DEBUG'])) { + $debug = $_ENV['APP_DEBUG']; + } elseif (isset($_SERVER['APP_DEBUG'])) { + $debug = $_SERVER['APP_DEBUG']; + } else { + $debug = true; + } + + return new static::$class($env, $debug); + } + + /** + * Shuts the kernel down if it was used in the test - called by the tearDown method by default. + */ + protected static function ensureKernelShutdown() + { + if (null !== static::$kernel) { + static::$kernel->shutdown(); + static::$booted = false; + } + + if (self::$kernelContainer instanceof ResetInterface) { + self::$kernelContainer->reset(); + } + + static::$container = self::$kernelContainer = null; + } +} diff --git a/vendor/symfony/framework-bundle/Test/MailerAssertionsTrait.php b/vendor/symfony/framework-bundle/Test/MailerAssertionsTrait.php new file mode 100644 index 0000000..15446a8 --- /dev/null +++ b/vendor/symfony/framework-bundle/Test/MailerAssertionsTrait.php @@ -0,0 +1,131 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Test; + +use PHPUnit\Framework\Constraint\LogicalNot; +use Symfony\Component\Mailer\Event\MessageEvent; +use Symfony\Component\Mailer\Event\MessageEvents; +use Symfony\Component\Mailer\Test\Constraint as MailerConstraint; +use Symfony\Component\Mime\RawMessage; +use Symfony\Component\Mime\Test\Constraint as MimeConstraint; + +trait MailerAssertionsTrait +{ + public static function assertEmailCount(int $count, string $transport = null, string $message = ''): void + { + self::assertThat(self::getMessageMailerEvents(), new MailerConstraint\EmailCount($count, $transport), $message); + } + + public static function assertQueuedEmailCount(int $count, string $transport = null, string $message = ''): void + { + self::assertThat(self::getMessageMailerEvents(), new MailerConstraint\EmailCount($count, $transport, true), $message); + } + + public static function assertEmailIsQueued(MessageEvent $event, string $message = ''): void + { + self::assertThat($event, new MailerConstraint\EmailIsQueued(), $message); + } + + public static function assertEmailIsNotQueued(MessageEvent $event, string $message = ''): void + { + self::assertThat($event, new LogicalNot(new MailerConstraint\EmailIsQueued()), $message); + } + + public static function assertEmailAttachmentCount(RawMessage $email, int $count, string $message = ''): void + { + self::assertThat($email, new MimeConstraint\EmailAttachmentCount($count), $message); + } + + public static function assertEmailTextBodyContains(RawMessage $email, string $text, string $message = ''): void + { + self::assertThat($email, new MimeConstraint\EmailTextBodyContains($text), $message); + } + + public static function assertEmailTextBodyNotContains(RawMessage $email, string $text, string $message = ''): void + { + self::assertThat($email, new LogicalNot(new MimeConstraint\EmailTextBodyContains($text)), $message); + } + + public static function assertEmailHtmlBodyContains(RawMessage $email, string $text, string $message = ''): void + { + self::assertThat($email, new MimeConstraint\EmailHtmlBodyContains($text), $message); + } + + public static function assertEmailHtmlBodyNotContains(RawMessage $email, string $text, string $message = ''): void + { + self::assertThat($email, new LogicalNot(new MimeConstraint\EmailHtmlBodyContains($text)), $message); + } + + public static function assertEmailHasHeader(RawMessage $email, string $headerName, string $message = ''): void + { + self::assertThat($email, new MimeConstraint\EmailHasHeader($headerName), $message); + } + + public static function assertEmailNotHasHeader(RawMessage $email, string $headerName, string $message = ''): void + { + self::assertThat($email, new LogicalNot(new MimeConstraint\EmailHasHeader($headerName)), $message); + } + + public static function assertEmailHeaderSame(RawMessage $email, string $headerName, string $expectedValue, string $message = ''): void + { + self::assertThat($email, new MimeConstraint\EmailHeaderSame($headerName, $expectedValue), $message); + } + + public static function assertEmailHeaderNotSame(RawMessage $email, string $headerName, string $expectedValue, string $message = ''): void + { + self::assertThat($email, new LogicalNot(new MimeConstraint\EmailHeaderSame($headerName, $expectedValue)), $message); + } + + public static function assertEmailAddressContains(RawMessage $email, string $headerName, string $expectedValue, string $message = ''): void + { + self::assertThat($email, new MimeConstraint\EmailAddressContains($headerName, $expectedValue), $message); + } + + /** + * @return MessageEvents[] + */ + public static function getMailerEvents(string $transport = null): array + { + return self::getMessageMailerEvents()->getEvents($transport); + } + + public static function getMailerEvent(int $index = 0, string $transport = null): ?MessageEvent + { + return self::getMailerEvents($transport)[$index] ?? null; + } + + /** + * @return RawMessage[] + */ + public static function getMailerMessages(string $transport = null): array + { + return self::getMessageMailerEvents()->getMessages($transport); + } + + public static function getMailerMessage(int $index = 0, string $transport = null): ?RawMessage + { + return self::getMailerMessages($transport)[$index] ?? null; + } + + private static function getMessageMailerEvents(): MessageEvents + { + if (!self::getClient()->getRequest()) { + static::fail('Unable to make email assertions. Did you forget to make an HTTP request?'); + } + + if (!$logger = self::$container->get('mailer.logger_message_listener')) { + static::fail('A client must have Mailer enabled to make email assertions. Did you forget to require symfony/mailer?'); + } + + return $logger->getEvents(); + } +} diff --git a/vendor/symfony/framework-bundle/Test/TestContainer.php b/vendor/symfony/framework-bundle/Test/TestContainer.php new file mode 100644 index 0000000..a0dd847 --- /dev/null +++ b/vendor/symfony/framework-bundle/Test/TestContainer.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Test; + +use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; +use Symfony\Component\HttpKernel\KernelInterface; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class TestContainer extends Container +{ + private $kernel; + private $privateServicesLocatorId; + + public function __construct(KernelInterface $kernel, string $privateServicesLocatorId) + { + $this->kernel = $kernel; + $this->privateServicesLocatorId = $privateServicesLocatorId; + } + + /** + * {@inheritdoc} + */ + public function compile() + { + $this->getPublicContainer()->compile(); + } + + /** + * {@inheritdoc} + */ + public function isCompiled(): bool + { + return $this->getPublicContainer()->isCompiled(); + } + + /** + * {@inheritdoc} + */ + public function getParameterBag(): ParameterBagInterface + { + return $this->getPublicContainer()->getParameterBag(); + } + + /** + * {@inheritdoc} + */ + public function getParameter(string $name) + { + return $this->getPublicContainer()->getParameter($name); + } + + /** + * {@inheritdoc} + */ + public function hasParameter(string $name): bool + { + return $this->getPublicContainer()->hasParameter($name); + } + + /** + * {@inheritdoc} + */ + public function setParameter(string $name, $value) + { + $this->getPublicContainer()->setParameter($name, $value); + } + + /** + * {@inheritdoc} + */ + public function set(string $id, $service) + { + $this->getPublicContainer()->set($id, $service); + } + + /** + * {@inheritdoc} + */ + public function has($id): bool + { + return $this->getPublicContainer()->has($id) || $this->getPrivateContainer()->has($id); + } + + /** + * {@inheritdoc} + */ + public function get($id, int $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERENCE */ 1): ?object + { + return $this->getPrivateContainer()->has($id) ? $this->getPrivateContainer()->get($id) : $this->getPublicContainer()->get($id, $invalidBehavior); + } + + /** + * {@inheritdoc} + */ + public function initialized(string $id): bool + { + return $this->getPublicContainer()->initialized($id); + } + + /** + * {@inheritdoc} + */ + public function reset() + { + // ignore the call + } + + /** + * {@inheritdoc} + */ + public function getServiceIds(): array + { + return $this->getPublicContainer()->getServiceIds(); + } + + /** + * {@inheritdoc} + */ + public function getRemovedIds(): array + { + return $this->getPublicContainer()->getRemovedIds(); + } + + private function getPublicContainer(): Container + { + if (null === $container = $this->kernel->getContainer()) { + throw new \LogicException('Cannot access the container on a non-booted kernel. Did you forget to boot it?'); + } + + return $container; + } + + private function getPrivateContainer(): ContainerInterface + { + return $this->getPublicContainer()->get($this->privateServicesLocatorId); + } +} diff --git a/vendor/symfony/framework-bundle/Test/WebTestAssertionsTrait.php b/vendor/symfony/framework-bundle/Test/WebTestAssertionsTrait.php new file mode 100644 index 0000000..0f1742e --- /dev/null +++ b/vendor/symfony/framework-bundle/Test/WebTestAssertionsTrait.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Test; + +trait WebTestAssertionsTrait +{ + use BrowserKitAssertionsTrait; + use DomCrawlerAssertionsTrait; +} diff --git a/vendor/symfony/framework-bundle/Test/WebTestCase.php b/vendor/symfony/framework-bundle/Test/WebTestCase.php new file mode 100644 index 0000000..4935dd8 --- /dev/null +++ b/vendor/symfony/framework-bundle/Test/WebTestCase.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Test; + +use Symfony\Bundle\FrameworkBundle\KernelBrowser; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; + +/** + * WebTestCase is the base class for functional tests. + * + * @author Fabien Potencier + */ +abstract class WebTestCase extends KernelTestCase +{ + use WebTestAssertionsTrait; + use MailerAssertionsTrait; + + protected function tearDown(): void + { + parent::tearDown(); + self::getClient(null); + } + + /** + * Creates a KernelBrowser. + * + * @param array $options An array of options to pass to the createKernel method + * @param array $server An array of server parameters + * + * @return KernelBrowser A KernelBrowser instance + */ + protected static function createClient(array $options = [], array $server = []) + { + if (static::$booted) { + throw new \LogicException(sprintf('Booting the kernel before calling %s() is not supported, the kernel should only be booted once.', __METHOD__)); + } + + $kernel = static::bootKernel($options); + + try { + $client = $kernel->getContainer()->get('test.client'); + } catch (ServiceNotFoundException $e) { + if (class_exists(KernelBrowser::class)) { + throw new \LogicException('You cannot create the client used in functional tests if the "framework.test" config is not set to true.'); + } + throw new \LogicException('You cannot create the client used in functional tests if the BrowserKit component is not available. Try running "composer require symfony/browser-kit"'); + } + + $client->setServerParameters($server); + + return self::getClient($client); + } +} diff --git a/vendor/symfony/framework-bundle/Translation/Translator.php b/vendor/symfony/framework-bundle/Translation/Translator.php new file mode 100644 index 0000000..da4384d --- /dev/null +++ b/vendor/symfony/framework-bundle/Translation/Translator.php @@ -0,0 +1,175 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Translation; + +use Psr\Container\ContainerInterface; +use Symfony\Component\Config\Resource\DirectoryResource; +use Symfony\Component\Config\Resource\FileExistenceResource; +use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Formatter\MessageFormatterInterface; +use Symfony\Component\Translation\Translator as BaseTranslator; + +/** + * Translator. + * + * @author Fabien Potencier + */ +class Translator extends BaseTranslator implements WarmableInterface +{ + protected $container; + protected $loaderIds; + + protected $options = [ + 'cache_dir' => null, + 'debug' => false, + 'resource_files' => [], + 'scanned_directories' => [], + 'cache_vary' => [], + ]; + + /** + * @var array + */ + private $resourceLocales; + + /** + * Holds parameters from addResource() calls so we can defer the actual + * parent::addResource() calls until initialize() is executed. + * + * @var array + */ + private $resources = []; + + private $resourceFiles; + + /** + * @var string[] + */ + private $scannedDirectories; + + /** + * Constructor. + * + * Available options: + * + * * cache_dir: The cache directory (or null to disable caching) + * * debug: Whether to enable debugging or not (false by default) + * * resource_files: List of translation resources available grouped by locale. + * * cache_vary: An array of data that is serialized to generate the cached catalogue name. + * + * @throws InvalidArgumentException + */ + public function __construct(ContainerInterface $container, MessageFormatterInterface $formatter, string $defaultLocale, array $loaderIds = [], array $options = []) + { + $this->container = $container; + $this->loaderIds = $loaderIds; + + // check option names + if ($diff = array_diff(array_keys($options), array_keys($this->options))) { + throw new InvalidArgumentException(sprintf('The Translator does not support the following options: \'%s\'.', implode('\', \'', $diff))); + } + + $this->options = array_merge($this->options, $options); + $this->resourceLocales = array_keys($this->options['resource_files']); + $this->resourceFiles = $this->options['resource_files']; + $this->scannedDirectories = $this->options['scanned_directories']; + + parent::__construct($defaultLocale, $formatter, $this->options['cache_dir'], $this->options['debug'], $this->options['cache_vary']); + } + + /** + * {@inheritdoc} + */ + public function warmUp(string $cacheDir) + { + // skip warmUp when translator doesn't use cache + if (null === $this->options['cache_dir']) { + return; + } + + $locales = array_merge($this->getFallbackLocales(), [$this->getLocale()], $this->resourceLocales); + foreach (array_unique($locales) as $locale) { + // reset catalogue in case it's already loaded during the dump of the other locales. + if (isset($this->catalogues[$locale])) { + unset($this->catalogues[$locale]); + } + + $this->loadCatalogue($locale); + } + } + + public function addResource(string $format, $resource, string $locale, string $domain = null) + { + if ($this->resourceFiles) { + $this->addResourceFiles(); + } + $this->resources[] = [$format, $resource, $locale, $domain]; + } + + /** + * {@inheritdoc} + */ + protected function initializeCatalogue(string $locale) + { + $this->initialize(); + parent::initializeCatalogue($locale); + } + + /** + * @internal + */ + protected function doLoadCatalogue(string $locale): void + { + parent::doLoadCatalogue($locale); + + foreach ($this->scannedDirectories as $directory) { + $resourceClass = file_exists($directory) ? DirectoryResource::class : FileExistenceResource::class; + $this->catalogues[$locale]->addResource(new $resourceClass($directory)); + } + } + + protected function initialize() + { + if ($this->resourceFiles) { + $this->addResourceFiles(); + } + foreach ($this->resources as $key => $params) { + list($format, $resource, $locale, $domain) = $params; + parent::addResource($format, $resource, $locale, $domain); + } + $this->resources = []; + + foreach ($this->loaderIds as $id => $aliases) { + foreach ($aliases as $alias) { + $this->addLoader($alias, $this->container->get($id)); + } + } + } + + private function addResourceFiles() + { + $filesByLocale = $this->resourceFiles; + $this->resourceFiles = []; + + foreach ($filesByLocale as $locale => $files) { + foreach ($files as $key => $file) { + // filename is domain.locale.format + $fileNameParts = explode('.', basename($file)); + $format = array_pop($fileNameParts); + $locale = array_pop($fileNameParts); + $domain = implode('.', $fileNameParts); + $this->addResource($format, $file, $locale, $domain); + } + } + } +} diff --git a/vendor/symfony/framework-bundle/composer.json b/vendor/symfony/framework-bundle/composer.json new file mode 100644 index 0000000..8bcf9e8 --- /dev/null +++ b/vendor/symfony/framework-bundle/composer.json @@ -0,0 +1,114 @@ +{ + "name": "symfony/framework-bundle", + "type": "symfony-bundle", + "description": "Symfony FrameworkBundle", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "ext-xml": "*", + "symfony/cache": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/dependency-injection": "^5.0.1", + "symfony/error-handler": "^4.4.1|^5.0.1", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-kernel": "^5.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/filesystem": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/routing": "^5.0" + }, + "require-dev": { + "doctrine/annotations": "~1.7", + "doctrine/cache": "~1.0", + "symfony/asset": "^4.4|^5.0", + "symfony/browser-kit": "^4.4|^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/dotenv": "^4.4|^5.0", + "symfony/polyfill-intl-icu": "~1.0", + "symfony/form": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/http-client": "^4.4|^5.0", + "symfony/lock": "^4.4|^5.0", + "symfony/mailer": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/security-csrf": "^4.4|^5.0", + "symfony/security-http": "^4.4|^5.0", + "symfony/serializer": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/string": "~5.0.0", + "symfony/translation": "^5.0", + "symfony/twig-bundle": "^4.4|^5.0", + "symfony/validator": "^4.4|^5.0", + "symfony/workflow": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0", + "symfony/property-info": "^4.4|^5.0", + "symfony/web-link": "^4.4|^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", + "paragonie/sodium_compat": "^1.8", + "twig/twig": "^2.10|^3.0" + }, + "conflict": { + "doctrine/persistence": "<1.3", + "phpdocumentor/reflection-docblock": "<3.0", + "phpdocumentor/type-resolver": "<0.2.1", + "phpunit/phpunit": "<5.4.3", + "symfony/asset": "<4.4", + "symfony/browser-kit": "<4.4", + "symfony/console": "<4.4", + "symfony/dotenv": "<4.4", + "symfony/dom-crawler": "<4.4", + "symfony/http-client": "<4.4", + "symfony/form": "<4.4", + "symfony/lock": "<4.4", + "symfony/mailer": "<4.4", + "symfony/messenger": "<4.4", + "symfony/mime": "<4.4", + "symfony/property-info": "<4.4", + "symfony/serializer": "<4.4", + "symfony/stopwatch": "<4.4", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<4.4", + "symfony/twig-bundle": "<4.4", + "symfony/validator": "<4.4", + "symfony/web-profiler-bundle": "<4.4", + "symfony/workflow": "<4.4" + }, + "suggest": { + "ext-apcu": "For best performance of the system caches", + "symfony/console": "For using the console commands", + "symfony/form": "For using forms", + "symfony/serializer": "For using the serializer service", + "symfony/validator": "For using validation", + "symfony/yaml": "For using the debug:config and lint:yaml commands", + "symfony/property-info": "For using the property_info service", + "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering" + }, + "autoload": { + "psr-4": { "Symfony\\Bundle\\FrameworkBundle\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/http-foundation/.gitattributes b/vendor/symfony/http-foundation/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/http-foundation/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/http-foundation/AcceptHeader.php b/vendor/symfony/http-foundation/AcceptHeader.php new file mode 100644 index 0000000..90f9f47 --- /dev/null +++ b/vendor/symfony/http-foundation/AcceptHeader.php @@ -0,0 +1,165 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * Represents an Accept-* header. + * + * An accept header is compound with a list of items, + * sorted by descending quality. + * + * @author Jean-François Simon + */ +class AcceptHeader +{ + /** + * @var AcceptHeaderItem[] + */ + private $items = []; + + /** + * @var bool + */ + private $sorted = true; + + /** + * @param AcceptHeaderItem[] $items + */ + public function __construct(array $items) + { + foreach ($items as $item) { + $this->add($item); + } + } + + /** + * Builds an AcceptHeader instance from a string. + * + * @return self + */ + public static function fromString(?string $headerValue) + { + $index = 0; + + $parts = HeaderUtils::split($headerValue ?? '', ',;='); + + return new self(array_map(function ($subParts) use (&$index) { + $part = array_shift($subParts); + $attributes = HeaderUtils::combine($subParts); + + $item = new AcceptHeaderItem($part[0], $attributes); + $item->setIndex($index++); + + return $item; + }, $parts)); + } + + /** + * Returns header value's string representation. + * + * @return string + */ + public function __toString() + { + return implode(',', $this->items); + } + + /** + * Tests if header has given value. + * + * @return bool + */ + public function has(string $value) + { + return isset($this->items[$value]); + } + + /** + * Returns given value's item, if exists. + * + * @return AcceptHeaderItem|null + */ + public function get(string $value) + { + return $this->items[$value] ?? $this->items[explode('/', $value)[0].'/*'] ?? $this->items['*/*'] ?? $this->items['*'] ?? null; + } + + /** + * Adds an item. + * + * @return $this + */ + public function add(AcceptHeaderItem $item) + { + $this->items[$item->getValue()] = $item; + $this->sorted = false; + + return $this; + } + + /** + * Returns all items. + * + * @return AcceptHeaderItem[] + */ + public function all() + { + $this->sort(); + + return $this->items; + } + + /** + * Filters items on their value using given regex. + * + * @return self + */ + public function filter(string $pattern) + { + return new self(array_filter($this->items, function (AcceptHeaderItem $item) use ($pattern) { + return preg_match($pattern, $item->getValue()); + })); + } + + /** + * Returns first item. + * + * @return AcceptHeaderItem|null + */ + public function first() + { + $this->sort(); + + return !empty($this->items) ? reset($this->items) : null; + } + + /** + * Sorts items by descending quality. + */ + private function sort(): void + { + if (!$this->sorted) { + uasort($this->items, function (AcceptHeaderItem $a, AcceptHeaderItem $b) { + $qA = $a->getQuality(); + $qB = $b->getQuality(); + + if ($qA === $qB) { + return $a->getIndex() > $b->getIndex() ? 1 : -1; + } + + return $qA > $qB ? -1 : 1; + }); + + $this->sorted = true; + } + } +} diff --git a/vendor/symfony/http-foundation/AcceptHeaderItem.php b/vendor/symfony/http-foundation/AcceptHeaderItem.php new file mode 100644 index 0000000..bc4014e --- /dev/null +++ b/vendor/symfony/http-foundation/AcceptHeaderItem.php @@ -0,0 +1,177 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * Represents an Accept-* header item. + * + * @author Jean-François Simon + */ +class AcceptHeaderItem +{ + private $value; + private $quality = 1.0; + private $index = 0; + private $attributes = []; + + public function __construct(string $value, array $attributes = []) + { + $this->value = $value; + foreach ($attributes as $name => $value) { + $this->setAttribute($name, $value); + } + } + + /** + * Builds an AcceptHeaderInstance instance from a string. + * + * @return self + */ + public static function fromString(?string $itemValue) + { + $parts = HeaderUtils::split($itemValue ?? '', ';='); + + $part = array_shift($parts); + $attributes = HeaderUtils::combine($parts); + + return new self($part[0], $attributes); + } + + /** + * Returns header value's string representation. + * + * @return string + */ + public function __toString() + { + $string = $this->value.($this->quality < 1 ? ';q='.$this->quality : ''); + if (\count($this->attributes) > 0) { + $string .= '; '.HeaderUtils::toString($this->attributes, ';'); + } + + return $string; + } + + /** + * Set the item value. + * + * @return $this + */ + public function setValue(string $value) + { + $this->value = $value; + + return $this; + } + + /** + * Returns the item value. + * + * @return string + */ + public function getValue() + { + return $this->value; + } + + /** + * Set the item quality. + * + * @return $this + */ + public function setQuality(float $quality) + { + $this->quality = $quality; + + return $this; + } + + /** + * Returns the item quality. + * + * @return float + */ + public function getQuality() + { + return $this->quality; + } + + /** + * Set the item index. + * + * @return $this + */ + public function setIndex(int $index) + { + $this->index = $index; + + return $this; + } + + /** + * Returns the item index. + * + * @return int + */ + public function getIndex() + { + return $this->index; + } + + /** + * Tests if an attribute exists. + * + * @return bool + */ + public function hasAttribute(string $name) + { + return isset($this->attributes[$name]); + } + + /** + * Returns an attribute by its name. + * + * @param mixed $default + * + * @return mixed + */ + public function getAttribute(string $name, $default = null) + { + return isset($this->attributes[$name]) ? $this->attributes[$name] : $default; + } + + /** + * Returns all attributes. + * + * @return array + */ + public function getAttributes() + { + return $this->attributes; + } + + /** + * Set an attribute. + * + * @return $this + */ + public function setAttribute(string $name, string $value) + { + if ('q' === $name) { + $this->quality = (float) $value; + } else { + $this->attributes[$name] = $value; + } + + return $this; + } +} diff --git a/vendor/symfony/http-foundation/BinaryFileResponse.php b/vendor/symfony/http-foundation/BinaryFileResponse.php new file mode 100644 index 0000000..d37cbd2 --- /dev/null +++ b/vendor/symfony/http-foundation/BinaryFileResponse.php @@ -0,0 +1,354 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +use Symfony\Component\HttpFoundation\File\Exception\FileException; +use Symfony\Component\HttpFoundation\File\File; + +/** + * BinaryFileResponse represents an HTTP response delivering a file. + * + * @author Niklas Fiekas + * @author stealth35 + * @author Igor Wiedler + * @author Jordan Alliot + * @author Sergey Linnik + */ +class BinaryFileResponse extends Response +{ + protected static $trustXSendfileTypeHeader = false; + + /** + * @var File + */ + protected $file; + protected $offset = 0; + protected $maxlen = -1; + protected $deleteFileAfterSend = false; + + /** + * @param \SplFileInfo|string $file The file to stream + * @param int $status The response status code + * @param array $headers An array of response headers + * @param bool $public Files are public by default + * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename + * @param bool $autoEtag Whether the ETag header should be automatically set + * @param bool $autoLastModified Whether the Last-Modified header should be automatically set + */ + public function __construct($file, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) + { + parent::__construct(null, $status, $headers); + + $this->setFile($file, $contentDisposition, $autoEtag, $autoLastModified); + + if ($public) { + $this->setPublic(); + } + } + + /** + * @param \SplFileInfo|string $file The file to stream + * @param int $status The response status code + * @param array $headers An array of response headers + * @param bool $public Files are public by default + * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename + * @param bool $autoEtag Whether the ETag header should be automatically set + * @param bool $autoLastModified Whether the Last-Modified header should be automatically set + * + * @return static + */ + public static function create($file = null, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) + { + return new static($file, $status, $headers, $public, $contentDisposition, $autoEtag, $autoLastModified); + } + + /** + * Sets the file to stream. + * + * @param \SplFileInfo|string $file The file to stream + * + * @return $this + * + * @throws FileException + */ + public function setFile($file, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) + { + if (!$file instanceof File) { + if ($file instanceof \SplFileInfo) { + $file = new File($file->getPathname()); + } else { + $file = new File((string) $file); + } + } + + if (!$file->isReadable()) { + throw new FileException('File must be readable.'); + } + + $this->file = $file; + + if ($autoEtag) { + $this->setAutoEtag(); + } + + if ($autoLastModified) { + $this->setAutoLastModified(); + } + + if ($contentDisposition) { + $this->setContentDisposition($contentDisposition); + } + + return $this; + } + + /** + * Gets the file. + * + * @return File The file to stream + */ + public function getFile() + { + return $this->file; + } + + /** + * Automatically sets the Last-Modified header according the file modification date. + */ + public function setAutoLastModified() + { + $this->setLastModified(\DateTime::createFromFormat('U', $this->file->getMTime())); + + return $this; + } + + /** + * Automatically sets the ETag header according to the checksum of the file. + */ + public function setAutoEtag() + { + $this->setEtag(base64_encode(hash_file('sha256', $this->file->getPathname(), true))); + + return $this; + } + + /** + * Sets the Content-Disposition header with the given filename. + * + * @param string $disposition ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT + * @param string $filename Optionally use this UTF-8 encoded filename instead of the real name of the file + * @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename + * + * @return $this + */ + public function setContentDisposition(string $disposition, string $filename = '', string $filenameFallback = '') + { + if ('' === $filename) { + $filename = $this->file->getFilename(); + } + + if ('' === $filenameFallback && (!preg_match('/^[\x20-\x7e]*$/', $filename) || false !== strpos($filename, '%'))) { + $encoding = mb_detect_encoding($filename, null, true) ?: '8bit'; + + for ($i = 0, $filenameLength = mb_strlen($filename, $encoding); $i < $filenameLength; ++$i) { + $char = mb_substr($filename, $i, 1, $encoding); + + if ('%' === $char || \ord($char) < 32 || \ord($char) > 126) { + $filenameFallback .= '_'; + } else { + $filenameFallback .= $char; + } + } + } + + $dispositionHeader = $this->headers->makeDisposition($disposition, $filename, $filenameFallback); + $this->headers->set('Content-Disposition', $dispositionHeader); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function prepare(Request $request) + { + if (!$this->headers->has('Content-Type')) { + $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream'); + } + + if ('HTTP/1.0' !== $request->server->get('SERVER_PROTOCOL')) { + $this->setProtocolVersion('1.1'); + } + + $this->ensureIEOverSSLCompatibility($request); + + $this->offset = 0; + $this->maxlen = -1; + + if (false === $fileSize = $this->file->getSize()) { + return $this; + } + $this->headers->set('Content-Length', $fileSize); + + if (!$this->headers->has('Accept-Ranges')) { + // Only accept ranges on safe HTTP methods + $this->headers->set('Accept-Ranges', $request->isMethodSafe() ? 'bytes' : 'none'); + } + + if (self::$trustXSendfileTypeHeader && $request->headers->has('X-Sendfile-Type')) { + // Use X-Sendfile, do not send any content. + $type = $request->headers->get('X-Sendfile-Type'); + $path = $this->file->getRealPath(); + // Fall back to scheme://path for stream wrapped locations. + if (false === $path) { + $path = $this->file->getPathname(); + } + if ('x-accel-redirect' === strtolower($type)) { + // Do X-Accel-Mapping substitutions. + // @link http://wiki.nginx.org/X-accel#X-Accel-Redirect + $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping', ''), ',='); + foreach ($parts as $part) { + list($pathPrefix, $location) = $part; + if (substr($path, 0, \strlen($pathPrefix)) === $pathPrefix) { + $path = $location.substr($path, \strlen($pathPrefix)); + // Only set X-Accel-Redirect header if a valid URI can be produced + // as nginx does not serve arbitrary file paths. + $this->headers->set($type, $path); + $this->maxlen = 0; + break; + } + } + } else { + $this->headers->set($type, $path); + $this->maxlen = 0; + } + } elseif ($request->headers->has('Range')) { + // Process the range headers. + if (!$request->headers->has('If-Range') || $this->hasValidIfRangeHeader($request->headers->get('If-Range'))) { + $range = $request->headers->get('Range'); + + list($start, $end) = explode('-', substr($range, 6), 2) + [0]; + + $end = ('' === $end) ? $fileSize - 1 : (int) $end; + + if ('' === $start) { + $start = $fileSize - $end; + $end = $fileSize - 1; + } else { + $start = (int) $start; + } + + if ($start <= $end) { + if ($start < 0 || $end > $fileSize - 1) { + $this->setStatusCode(416); + $this->headers->set('Content-Range', sprintf('bytes */%s', $fileSize)); + } elseif (0 !== $start || $end !== $fileSize - 1) { + $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1; + $this->offset = $start; + + $this->setStatusCode(206); + $this->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $start, $end, $fileSize)); + $this->headers->set('Content-Length', $end - $start + 1); + } + } + } + } + + return $this; + } + + private function hasValidIfRangeHeader(?string $header): bool + { + if ($this->getEtag() === $header) { + return true; + } + + if (null === $lastModified = $this->getLastModified()) { + return false; + } + + return $lastModified->format('D, d M Y H:i:s').' GMT' === $header; + } + + /** + * Sends the file. + * + * {@inheritdoc} + */ + public function sendContent() + { + if (!$this->isSuccessful()) { + return parent::sendContent(); + } + + if (0 === $this->maxlen) { + return $this; + } + + $out = fopen('php://output', 'wb'); + $file = fopen($this->file->getPathname(), 'rb'); + + stream_copy_to_stream($file, $out, $this->maxlen, $this->offset); + + fclose($out); + fclose($file); + + if ($this->deleteFileAfterSend && file_exists($this->file->getPathname())) { + unlink($this->file->getPathname()); + } + + return $this; + } + + /** + * {@inheritdoc} + * + * @throws \LogicException when the content is not null + */ + public function setContent(?string $content) + { + if (null !== $content) { + throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.'); + } + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getContent() + { + return false; + } + + /** + * Trust X-Sendfile-Type header. + */ + public static function trustXSendfileTypeHeader() + { + self::$trustXSendfileTypeHeader = true; + } + + /** + * If this is set to true, the file will be unlinked after the request is sent + * Note: If the X-Sendfile header is used, the deleteFileAfterSend setting will not be used. + * + * @return $this + */ + public function deleteFileAfterSend(bool $shouldDelete = true) + { + $this->deleteFileAfterSend = $shouldDelete; + + return $this; + } +} diff --git a/vendor/symfony/http-foundation/CHANGELOG.md b/vendor/symfony/http-foundation/CHANGELOG.md new file mode 100644 index 0000000..0af7d00 --- /dev/null +++ b/vendor/symfony/http-foundation/CHANGELOG.md @@ -0,0 +1,247 @@ +CHANGELOG +========= + +5.0.0 +----- + + * made `Cookie` auto-secure and lax by default + * removed classes in the `MimeType` namespace, use the Symfony Mime component instead + * removed method `UploadedFile::getClientSize()` and the related constructor argument + * made `Request::getSession()` throw if the session has not been set before + * removed `Response::HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL` + * passing a null url when instantiating a `RedirectResponse` is not allowed + +4.4.0 +----- + + * passing arguments to `Request::isMethodSafe()` is deprecated. + * `ApacheRequest` is deprecated, use the `Request` class instead. + * passing a third argument to `HeaderBag::get()` is deprecated, use method `all()` instead + * [BC BREAK] `PdoSessionHandler` with MySQL changed the type of the lifetime column, + make sure to run `ALTER TABLE sessions MODIFY sess_lifetime INTEGER UNSIGNED NOT NULL` to + update your database. + * `PdoSessionHandler` now precalculates the expiry timestamp in the lifetime column, + make sure to run `CREATE INDEX EXPIRY ON sessions (sess_lifetime)` to update your database + to speed up garbage collection of expired sessions. + * added `SessionHandlerFactory` to create session handlers with a DSN + * added `IpUtils::anonymize()` to help with GDPR compliance. + +4.3.0 +----- + + * added PHPUnit constraints: `RequestAttributeValueSame`, `ResponseCookieValueSame`, `ResponseHasCookie`, + `ResponseHasHeader`, `ResponseHeaderSame`, `ResponseIsRedirected`, `ResponseIsSuccessful`, and `ResponseStatusCodeSame` + * deprecated `MimeTypeGuesserInterface` and `ExtensionGuesserInterface` in favor of `Symfony\Component\Mime\MimeTypesInterface`. + * deprecated `MimeType` and `MimeTypeExtensionGuesser` in favor of `Symfony\Component\Mime\MimeTypes`. + * deprecated `FileBinaryMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileBinaryMimeTypeGuesser`. + * deprecated `FileinfoMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileinfoMimeTypeGuesser`. + * added `UrlHelper` that allows to get an absolute URL and a relative path for a given path + +4.2.0 +----- + + * the default value of the "$secure" and "$samesite" arguments of Cookie's constructor + will respectively change from "false" to "null" and from "null" to "lax" in Symfony + 5.0, you should define their values explicitly or use "Cookie::create()" instead. + * added `matchPort()` in RequestMatcher + +4.1.3 +----- + + * [BC BREAK] Support for the IIS-only `X_ORIGINAL_URL` and `X_REWRITE_URL` + HTTP headers has been dropped for security reasons. + +4.1.0 +----- + + * Query string normalization uses `parse_str()` instead of custom parsing logic. + * Passing the file size to the constructor of the `UploadedFile` class is deprecated. + * The `getClientSize()` method of the `UploadedFile` class is deprecated. Use `getSize()` instead. + * added `RedisSessionHandler` to use Redis as a session storage + * The `get()` method of the `AcceptHeader` class now takes into account the + `*` and `*/*` default values (if they are present in the Accept HTTP header) + when looking for items. + * deprecated `Request::getSession()` when no session has been set. Use `Request::hasSession()` instead. + * added `CannotWriteFileException`, `ExtensionFileException`, `FormSizeFileException`, + `IniSizeFileException`, `NoFileException`, `NoTmpDirFileException`, `PartialFileException` to + handle failed `UploadedFile`. + * added `MigratingSessionHandler` for migrating between two session handlers without losing sessions + * added `HeaderUtils`. + +4.0.0 +----- + + * the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` + methods have been removed + * the `Request::HEADER_CLIENT_IP` constant has been removed, use + `Request::HEADER_X_FORWARDED_FOR` instead + * the `Request::HEADER_CLIENT_HOST` constant has been removed, use + `Request::HEADER_X_FORWARDED_HOST` instead + * the `Request::HEADER_CLIENT_PROTO` constant has been removed, use + `Request::HEADER_X_FORWARDED_PROTO` instead + * the `Request::HEADER_CLIENT_PORT` constant has been removed, use + `Request::HEADER_X_FORWARDED_PORT` instead + * checking for cacheable HTTP methods using the `Request::isMethodSafe()` + method (by not passing `false` as its argument) is not supported anymore and + throws a `\BadMethodCallException` + * the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes have been removed + * setting session save handlers that do not implement `\SessionHandlerInterface` in + `NativeSessionStorage::setSaveHandler()` is not supported anymore and throws a + `\TypeError` + +3.4.0 +----- + + * implemented PHP 7.0's `SessionUpdateTimestampHandlerInterface` with a new + `AbstractSessionHandler` base class and a new `StrictSessionHandler` wrapper + * deprecated the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes + * deprecated setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()` + * deprecated using `MongoDbSessionHandler` with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead + * deprecated `MemcacheSessionHandler`; use `MemcachedSessionHandler` instead + +3.3.0 +----- + + * the `Request::setTrustedProxies()` method takes a new `$trustedHeaderSet` argument, + see https://symfony.com/doc/current/deployment/proxies.html for more info, + * deprecated the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` methods, + * added `File\Stream`, to be passed to `BinaryFileResponse` when the size of the served file is unknown, + disabling `Range` and `Content-Length` handling, switching to chunked encoding instead + * added the `Cookie::fromString()` method that allows to create a cookie from a + raw header string + +3.1.0 +----- + + * Added support for creating `JsonResponse` with a string of JSON data + +3.0.0 +----- + + * The precedence of parameters returned from `Request::get()` changed from "GET, PATH, BODY" to "PATH, GET, BODY" + +2.8.0 +----- + + * Finding deep items in `ParameterBag::get()` is deprecated since version 2.8 and + will be removed in 3.0. + +2.6.0 +----- + + * PdoSessionHandler changes + - implemented different session locking strategies to prevent loss of data by concurrent access to the same session + - [BC BREAK] save session data in a binary column without base64_encode + - [BC BREAK] added lifetime column to the session table which allows to have different lifetimes for each session + - implemented lazy connections that are only opened when a session is used by either passing a dsn string + explicitly or falling back to session.save_path ini setting + - added a createTable method that initializes a correctly defined table depending on the database vendor + +2.5.0 +----- + + * added `JsonResponse::setEncodingOptions()` & `JsonResponse::getEncodingOptions()` for easier manipulation + of the options used while encoding data to JSON format. + +2.4.0 +----- + + * added RequestStack + * added Request::getEncodings() + * added accessors methods to session handlers + +2.3.0 +----- + + * added support for ranges of IPs in trusted proxies + * `UploadedFile::isValid` now returns false if the file was not uploaded via HTTP (in a non-test mode) + * Improved error-handling of `\Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler` + to ensure the supplied PDO handler throws Exceptions on error (as the class expects). Added related test cases + to verify that Exceptions are properly thrown when the PDO queries fail. + +2.2.0 +----- + + * fixed the Request::create() precedence (URI information always take precedence now) + * added Request::getTrustedProxies() + * deprecated Request::isProxyTrusted() + * [BC BREAK] JsonResponse does not turn a top level empty array to an object anymore, use an ArrayObject to enforce objects + * added a IpUtils class to check if an IP belongs to a CIDR + * added Request::getRealMethod() to get the "real" HTTP method (getMethod() returns the "intended" HTTP method) + * disabled _method request parameter support by default (call Request::enableHttpMethodParameterOverride() to + enable it, and Request::getHttpMethodParameterOverride() to check if it is supported) + * Request::splitHttpAcceptHeader() method is deprecated and will be removed in 2.3 + * Deprecated Flashbag::count() and \Countable interface, will be removed in 2.3 + +2.1.0 +----- + + * added Request::getSchemeAndHttpHost() and Request::getUserInfo() + * added a fluent interface to the Response class + * added Request::isProxyTrusted() + * added JsonResponse + * added a getTargetUrl method to RedirectResponse + * added support for streamed responses + * made Response::prepare() method the place to enforce HTTP specification + * [BC BREAK] moved management of the locale from the Session class to the Request class + * added a generic access to the PHP built-in filter mechanism: ParameterBag::filter() + * made FileBinaryMimeTypeGuesser command configurable + * added Request::getUser() and Request::getPassword() + * added support for the PATCH method in Request + * removed the ContentTypeMimeTypeGuesser class as it is deprecated and never used on PHP 5.3 + * added ResponseHeaderBag::makeDisposition() (implements RFC 6266) + * made mimetype to extension conversion configurable + * [BC BREAK] Moved all session related classes and interfaces into own namespace, as + `Symfony\Component\HttpFoundation\Session` and renamed classes accordingly. + Session handlers are located in the subnamespace `Symfony\Component\HttpFoundation\Session\Handler`. + * SessionHandlers must implement `\SessionHandlerInterface` or extend from the + `Symfony\Component\HttpFoundation\Storage\Handler\NativeSessionHandler` base class. + * Added internal storage driver proxy mechanism for forward compatibility with + PHP 5.4 `\SessionHandler` class. + * Added session handlers for custom Memcache, Memcached and Null session save handlers. + * [BC BREAK] Removed `NativeSessionStorage` and replaced with `NativeFileSessionHandler`. + * [BC BREAK] `SessionStorageInterface` methods removed: `write()`, `read()` and + `remove()`. Added `getBag()`, `registerBag()`. The `NativeSessionStorage` class + is a mediator for the session storage internals including the session handlers + which do the real work of participating in the internal PHP session workflow. + * [BC BREAK] Introduced mock implementations of `SessionStorage` to enable unit + and functional testing without starting real PHP sessions. Removed + `ArraySessionStorage`, and replaced with `MockArraySessionStorage` for unit + tests; removed `FilesystemSessionStorage`, and replaced with`MockFileSessionStorage` + for functional tests. These do not interact with global session ini + configuration values, session functions or `$_SESSION` superglobal. This means + they can be configured directly allowing multiple instances to work without + conflicting in the same PHP process. + * [BC BREAK] Removed the `close()` method from the `Session` class, as this is + now redundant. + * Deprecated the following methods from the Session class: `setFlash()`, `setFlashes()` + `getFlash()`, `hasFlash()`, and `removeFlash()`. Use `getFlashBag()` instead + which returns a `FlashBagInterface`. + * `Session->clear()` now only clears session attributes as before it cleared + flash messages and attributes. `Session->getFlashBag()->all()` clears flashes now. + * Session data is now managed by `SessionBagInterface` to better encapsulate + session data. + * Refactored session attribute and flash messages system to their own + `SessionBagInterface` implementations. + * Added `FlashBag`. Flashes expire when retrieved by `get()` or `all()`. This + implementation is ESI compatible. + * Added `AutoExpireFlashBag` (default) to replicate Symfony 2.0.x auto expire + behavior of messages auto expiring after one page page load. Messages must + be retrieved by `get()` or `all()`. + * Added `Symfony\Component\HttpFoundation\Attribute\AttributeBag` to replicate + attributes storage behavior from 2.0.x (default). + * Added `Symfony\Component\HttpFoundation\Attribute\NamespacedAttributeBag` for + namespace session attributes. + * Flash API can stores messages in an array so there may be multiple messages + per flash type. The old `Session` class API remains without BC break as it + will allow single messages as before. + * Added basic session meta-data to the session to record session create time, + last updated time, and the lifetime of the session cookie that was provided + to the client. + * Request::getClientIp() method doesn't take a parameter anymore but bases + itself on the trustProxy parameter. + * Added isMethod() to Request object. + * [BC BREAK] The methods `getPathInfo()`, `getBaseUrl()` and `getBasePath()` of + a `Request` now all return a raw value (vs a urldecoded value before). Any call + to one of these methods must be checked and wrapped in a `rawurldecode()` if + needed. diff --git a/vendor/symfony/http-foundation/Cookie.php b/vendor/symfony/http-foundation/Cookie.php new file mode 100644 index 0000000..fc711ee --- /dev/null +++ b/vendor/symfony/http-foundation/Cookie.php @@ -0,0 +1,302 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * Represents a cookie. + * + * @author Johannes M. Schmitt + */ +class Cookie +{ + const SAMESITE_NONE = 'none'; + const SAMESITE_LAX = 'lax'; + const SAMESITE_STRICT = 'strict'; + + protected $name; + protected $value; + protected $domain; + protected $expire; + protected $path; + protected $secure; + protected $httpOnly; + + private $raw; + private $sameSite; + private $secureDefault = false; + + private static $reservedCharsList = "=,; \t\r\n\v\f"; + private static $reservedCharsFrom = ['=', ',', ';', ' ', "\t", "\r", "\n", "\v", "\f"]; + private static $reservedCharsTo = ['%3D', '%2C', '%3B', '%20', '%09', '%0D', '%0A', '%0B', '%0C']; + + /** + * Creates cookie from raw header string. + * + * @return static + */ + public static function fromString(string $cookie, bool $decode = false) + { + $data = [ + 'expires' => 0, + 'path' => '/', + 'domain' => null, + 'secure' => false, + 'httponly' => false, + 'raw' => !$decode, + 'samesite' => null, + ]; + + $parts = HeaderUtils::split($cookie, ';='); + $part = array_shift($parts); + + $name = $decode ? urldecode($part[0]) : $part[0]; + $value = isset($part[1]) ? ($decode ? urldecode($part[1]) : $part[1]) : null; + + $data = HeaderUtils::combine($parts) + $data; + + if (isset($data['max-age'])) { + $data['expires'] = time() + (int) $data['max-age']; + } + + return new static($name, $value, $data['expires'], $data['path'], $data['domain'], $data['secure'], $data['httponly'], $data['raw'], $data['samesite']); + } + + public static function create(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX): self + { + return new self($name, $value, $expire, $path, $domain, $secure, $httpOnly, $raw, $sameSite); + } + + /** + * @param string $name The name of the cookie + * @param string|null $value The value of the cookie + * @param int|string|\DateTimeInterface $expire The time the cookie expires + * @param string $path The path on the server in which the cookie will be available on + * @param string|null $domain The domain that the cookie is available to + * @param bool|null $secure Whether the client should send back the cookie only over HTTPS or null to auto-enable this when the request is already using HTTPS + * @param bool $httpOnly Whether the cookie will be made accessible only through the HTTP protocol + * @param bool $raw Whether the cookie value should be sent with no url encoding + * @param string|null $sameSite Whether the cookie will be available for cross-site requests + * + * @throws \InvalidArgumentException + */ + public function __construct(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = 'lax') + { + // from PHP source code + if ($raw && false !== strpbrk($name, self::$reservedCharsList)) { + throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name)); + } + + if (empty($name)) { + throw new \InvalidArgumentException('The cookie name cannot be empty.'); + } + + // convert expiration time to a Unix timestamp + if ($expire instanceof \DateTimeInterface) { + $expire = $expire->format('U'); + } elseif (!is_numeric($expire)) { + $expire = strtotime($expire); + + if (false === $expire) { + throw new \InvalidArgumentException('The cookie expiration time is not valid.'); + } + } + + $this->name = $name; + $this->value = $value; + $this->domain = $domain; + $this->expire = 0 < $expire ? (int) $expire : 0; + $this->path = empty($path) ? '/' : $path; + $this->secure = $secure; + $this->httpOnly = $httpOnly; + $this->raw = $raw; + + if ('' === $sameSite) { + $sameSite = null; + } elseif (null !== $sameSite) { + $sameSite = strtolower($sameSite); + } + + if (!\in_array($sameSite, [self::SAMESITE_LAX, self::SAMESITE_STRICT, self::SAMESITE_NONE, null], true)) { + throw new \InvalidArgumentException('The "sameSite" parameter value is not valid.'); + } + + $this->sameSite = $sameSite; + } + + /** + * Returns the cookie as a string. + * + * @return string The cookie + */ + public function __toString() + { + if ($this->isRaw()) { + $str = $this->getName(); + } else { + $str = str_replace(self::$reservedCharsFrom, self::$reservedCharsTo, $this->getName()); + } + + $str .= '='; + + if ('' === (string) $this->getValue()) { + $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0'; + } else { + $str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue()); + + if (0 !== $this->getExpiresTime()) { + $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; Max-Age='.$this->getMaxAge(); + } + } + + if ($this->getPath()) { + $str .= '; path='.$this->getPath(); + } + + if ($this->getDomain()) { + $str .= '; domain='.$this->getDomain(); + } + + if (true === $this->isSecure()) { + $str .= '; secure'; + } + + if (true === $this->isHttpOnly()) { + $str .= '; httponly'; + } + + if (null !== $this->getSameSite()) { + $str .= '; samesite='.$this->getSameSite(); + } + + return $str; + } + + /** + * Gets the name of the cookie. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Gets the value of the cookie. + * + * @return string|null + */ + public function getValue() + { + return $this->value; + } + + /** + * Gets the domain that the cookie is available to. + * + * @return string|null + */ + public function getDomain() + { + return $this->domain; + } + + /** + * Gets the time the cookie expires. + * + * @return int + */ + public function getExpiresTime() + { + return $this->expire; + } + + /** + * Gets the max-age attribute. + * + * @return int + */ + public function getMaxAge() + { + $maxAge = $this->expire - time(); + + return 0 >= $maxAge ? 0 : $maxAge; + } + + /** + * Gets the path on the server in which the cookie will be available on. + * + * @return string + */ + public function getPath() + { + return $this->path; + } + + /** + * Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client. + * + * @return bool + */ + public function isSecure() + { + return $this->secure ?? $this->secureDefault; + } + + /** + * Checks whether the cookie will be made accessible only through the HTTP protocol. + * + * @return bool + */ + public function isHttpOnly() + { + return $this->httpOnly; + } + + /** + * Whether this cookie is about to be cleared. + * + * @return bool + */ + public function isCleared() + { + return 0 !== $this->expire && $this->expire < time(); + } + + /** + * Checks if the cookie value should be sent with no url encoding. + * + * @return bool + */ + public function isRaw() + { + return $this->raw; + } + + /** + * Gets the SameSite attribute. + * + * @return string|null + */ + public function getSameSite() + { + return $this->sameSite; + } + + /** + * @param bool $default The default value of the "secure" flag when it is set to null + */ + public function setSecureDefault(bool $default): void + { + $this->secureDefault = $default; + } +} diff --git a/vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php b/vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php new file mode 100644 index 0000000..5fcf5b4 --- /dev/null +++ b/vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Exception; + +/** + * The HTTP request contains headers with conflicting information. + * + * @author Magnus Nordlander + */ +class ConflictingHeadersException extends \UnexpectedValueException implements RequestExceptionInterface +{ +} diff --git a/vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php b/vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php new file mode 100644 index 0000000..478d0dc --- /dev/null +++ b/vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Exception; + +/** + * Interface for Request exceptions. + * + * Exceptions implementing this interface should trigger an HTTP 400 response in the application code. + */ +interface RequestExceptionInterface +{ +} diff --git a/vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php b/vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php new file mode 100644 index 0000000..ae7a5f1 --- /dev/null +++ b/vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Exception; + +/** + * Raised when a user has performed an operation that should be considered + * suspicious from a security perspective. + */ +class SuspiciousOperationException extends \UnexpectedValueException implements RequestExceptionInterface +{ +} diff --git a/vendor/symfony/http-foundation/ExpressionRequestMatcher.php b/vendor/symfony/http-foundation/ExpressionRequestMatcher.php new file mode 100644 index 0000000..26bed7d --- /dev/null +++ b/vendor/symfony/http-foundation/ExpressionRequestMatcher.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; + +/** + * ExpressionRequestMatcher uses an expression to match a Request. + * + * @author Fabien Potencier + */ +class ExpressionRequestMatcher extends RequestMatcher +{ + private $language; + private $expression; + + public function setExpression(ExpressionLanguage $language, $expression) + { + $this->language = $language; + $this->expression = $expression; + } + + public function matches(Request $request) + { + if (!$this->language) { + throw new \LogicException('Unable to match the request as the expression language is not available.'); + } + + return $this->language->evaluate($this->expression, [ + 'request' => $request, + 'method' => $request->getMethod(), + 'path' => rawurldecode($request->getPathInfo()), + 'host' => $request->getHost(), + 'ip' => $request->getClientIp(), + 'attributes' => $request->attributes->all(), + ]) && parent::matches($request); + } +} diff --git a/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php b/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php new file mode 100644 index 0000000..136d2a9 --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when the access on a file was denied. + * + * @author Bernhard Schussek + */ +class AccessDeniedException extends FileException +{ + public function __construct(string $path) + { + parent::__construct(sprintf('The file %s could not be accessed', $path)); + } +} diff --git a/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php b/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php new file mode 100644 index 0000000..c49f53a --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an UPLOAD_ERR_CANT_WRITE error occurred with UploadedFile. + * + * @author Florent Mata + */ +class CannotWriteFileException extends FileException +{ +} diff --git a/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php b/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php new file mode 100644 index 0000000..ed83499 --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an UPLOAD_ERR_EXTENSION error occurred with UploadedFile. + * + * @author Florent Mata + */ +class ExtensionFileException extends FileException +{ +} diff --git a/vendor/symfony/http-foundation/File/Exception/FileException.php b/vendor/symfony/http-foundation/File/Exception/FileException.php new file mode 100644 index 0000000..fad5133 --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/FileException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an error occurred in the component File. + * + * @author Bernhard Schussek + */ +class FileException extends \RuntimeException +{ +} diff --git a/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php b/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php new file mode 100644 index 0000000..31bdf68 --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when a file was not found. + * + * @author Bernhard Schussek + */ +class FileNotFoundException extends FileException +{ + public function __construct(string $path) + { + parent::__construct(sprintf('The file "%s" does not exist', $path)); + } +} diff --git a/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php b/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php new file mode 100644 index 0000000..8741be0 --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an UPLOAD_ERR_FORM_SIZE error occurred with UploadedFile. + * + * @author Florent Mata + */ +class FormSizeFileException extends FileException +{ +} diff --git a/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php b/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php new file mode 100644 index 0000000..c8fde61 --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an UPLOAD_ERR_INI_SIZE error occurred with UploadedFile. + * + * @author Florent Mata + */ +class IniSizeFileException extends FileException +{ +} diff --git a/vendor/symfony/http-foundation/File/Exception/NoFileException.php b/vendor/symfony/http-foundation/File/Exception/NoFileException.php new file mode 100644 index 0000000..4b48cc7 --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/NoFileException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an UPLOAD_ERR_NO_FILE error occurred with UploadedFile. + * + * @author Florent Mata + */ +class NoFileException extends FileException +{ +} diff --git a/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php b/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php new file mode 100644 index 0000000..bdead2d --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an UPLOAD_ERR_NO_TMP_DIR error occurred with UploadedFile. + * + * @author Florent Mata + */ +class NoTmpDirFileException extends FileException +{ +} diff --git a/vendor/symfony/http-foundation/File/Exception/PartialFileException.php b/vendor/symfony/http-foundation/File/Exception/PartialFileException.php new file mode 100644 index 0000000..4641efb --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/PartialFileException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an UPLOAD_ERR_PARTIAL error occurred with UploadedFile. + * + * @author Florent Mata + */ +class PartialFileException extends FileException +{ +} diff --git a/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php b/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php new file mode 100644 index 0000000..82b982b --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +class UnexpectedTypeException extends FileException +{ + public function __construct($value, string $expectedType) + { + parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, \is_object($value) ? \get_class($value) : \gettype($value))); + } +} diff --git a/vendor/symfony/http-foundation/File/Exception/UploadException.php b/vendor/symfony/http-foundation/File/Exception/UploadException.php new file mode 100644 index 0000000..7074e76 --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/UploadException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an error occurred during file upload. + * + * @author Bernhard Schussek + */ +class UploadException extends FileException +{ +} diff --git a/vendor/symfony/http-foundation/File/File.php b/vendor/symfony/http-foundation/File/File.php new file mode 100644 index 0000000..d79c27f --- /dev/null +++ b/vendor/symfony/http-foundation/File/File.php @@ -0,0 +1,130 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File; + +use Symfony\Component\HttpFoundation\File\Exception\FileException; +use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; +use Symfony\Component\Mime\MimeTypes; + +/** + * A file in the file system. + * + * @author Bernhard Schussek + */ +class File extends \SplFileInfo +{ + /** + * Constructs a new file from the given path. + * + * @param string $path The path to the file + * @param bool $checkPath Whether to check the path or not + * + * @throws FileNotFoundException If the given path is not a file + */ + public function __construct(string $path, bool $checkPath = true) + { + if ($checkPath && !is_file($path)) { + throw new FileNotFoundException($path); + } + + parent::__construct($path); + } + + /** + * Returns the extension based on the mime type. + * + * If the mime type is unknown, returns null. + * + * This method uses the mime type as guessed by getMimeType() + * to guess the file extension. + * + * @return string|null The guessed extension or null if it cannot be guessed + * + * @see MimeTypes + * @see getMimeType() + */ + public function guessExtension() + { + return MimeTypes::getDefault()->getExtensions($this->getMimeType())[0] ?? null; + } + + /** + * Returns the mime type of the file. + * + * The mime type is guessed using a MimeTypeGuesserInterface instance, + * which uses finfo_file() then the "file" system binary, + * depending on which of those are available. + * + * @return string|null The guessed mime type (e.g. "application/pdf") + * + * @see MimeTypes + */ + public function getMimeType() + { + return MimeTypes::getDefault()->guessMimeType($this->getPathname()); + } + + /** + * Moves the file to a new location. + * + * @return self A File object representing the new file + * + * @throws FileException if the target file could not be created + */ + public function move(string $directory, string $name = null) + { + $target = $this->getTargetFile($directory, $name); + + set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); + $renamed = rename($this->getPathname(), $target); + restore_error_handler(); + if (!$renamed) { + throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error))); + } + + @chmod($target, 0666 & ~umask()); + + return $target; + } + + /** + * @return self + */ + protected function getTargetFile(string $directory, string $name = null) + { + if (!is_dir($directory)) { + if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) { + throw new FileException(sprintf('Unable to create the "%s" directory', $directory)); + } + } elseif (!is_writable($directory)) { + throw new FileException(sprintf('Unable to write in the "%s" directory', $directory)); + } + + $target = rtrim($directory, '/\\').\DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name)); + + return new self($target, false); + } + + /** + * Returns locale independent base name of the given path. + * + * @return string + */ + protected function getName(string $name) + { + $originalName = str_replace('\\', '/', $name); + $pos = strrpos($originalName, '/'); + $originalName = false === $pos ? $originalName : substr($originalName, $pos + 1); + + return $originalName; + } +} diff --git a/vendor/symfony/http-foundation/File/Stream.php b/vendor/symfony/http-foundation/File/Stream.php new file mode 100644 index 0000000..69ae74c --- /dev/null +++ b/vendor/symfony/http-foundation/File/Stream.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File; + +/** + * A PHP stream of unknown size. + * + * @author Nicolas Grekas + */ +class Stream extends File +{ + /** + * {@inheritdoc} + */ + public function getSize() + { + return false; + } +} diff --git a/vendor/symfony/http-foundation/File/UploadedFile.php b/vendor/symfony/http-foundation/File/UploadedFile.php new file mode 100644 index 0000000..3a258e2 --- /dev/null +++ b/vendor/symfony/http-foundation/File/UploadedFile.php @@ -0,0 +1,281 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File; + +use Symfony\Component\HttpFoundation\File\Exception\CannotWriteFileException; +use Symfony\Component\HttpFoundation\File\Exception\ExtensionFileException; +use Symfony\Component\HttpFoundation\File\Exception\FileException; +use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; +use Symfony\Component\HttpFoundation\File\Exception\FormSizeFileException; +use Symfony\Component\HttpFoundation\File\Exception\IniSizeFileException; +use Symfony\Component\HttpFoundation\File\Exception\NoFileException; +use Symfony\Component\HttpFoundation\File\Exception\NoTmpDirFileException; +use Symfony\Component\HttpFoundation\File\Exception\PartialFileException; +use Symfony\Component\Mime\MimeTypes; + +/** + * A file uploaded through a form. + * + * @author Bernhard Schussek + * @author Florian Eckerstorfer + * @author Fabien Potencier + */ +class UploadedFile extends File +{ + private $test = false; + private $originalName; + private $mimeType; + private $error; + + /** + * Accepts the information of the uploaded file as provided by the PHP global $_FILES. + * + * The file object is only created when the uploaded file is valid (i.e. when the + * isValid() method returns true). Otherwise the only methods that could be called + * on an UploadedFile instance are: + * + * * getClientOriginalName, + * * getClientMimeType, + * * isValid, + * * getError. + * + * Calling any other method on an non-valid instance will cause an unpredictable result. + * + * @param string $path The full temporary path to the file + * @param string $originalName The original file name of the uploaded file + * @param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream + * @param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK + * @param bool $test Whether the test mode is active + * Local files are used in test mode hence the code should not enforce HTTP uploads + * + * @throws FileException If file_uploads is disabled + * @throws FileNotFoundException If the file does not exist + */ + public function __construct(string $path, string $originalName, string $mimeType = null, int $error = null, bool $test = false) + { + $this->originalName = $this->getName($originalName); + $this->mimeType = $mimeType ?: 'application/octet-stream'; + $this->error = $error ?: UPLOAD_ERR_OK; + $this->test = $test; + + parent::__construct($path, UPLOAD_ERR_OK === $this->error); + } + + /** + * Returns the original file name. + * + * It is extracted from the request from which the file has been uploaded. + * Then it should not be considered as a safe value. + * + * @return string|null The original name + */ + public function getClientOriginalName() + { + return $this->originalName; + } + + /** + * Returns the original file extension. + * + * It is extracted from the original file name that was uploaded. + * Then it should not be considered as a safe value. + * + * @return string The extension + */ + public function getClientOriginalExtension() + { + return pathinfo($this->originalName, PATHINFO_EXTENSION); + } + + /** + * Returns the file mime type. + * + * The client mime type is extracted from the request from which the file + * was uploaded, so it should not be considered as a safe value. + * + * For a trusted mime type, use getMimeType() instead (which guesses the mime + * type based on the file content). + * + * @return string|null The mime type + * + * @see getMimeType() + */ + public function getClientMimeType() + { + return $this->mimeType; + } + + /** + * Returns the extension based on the client mime type. + * + * If the mime type is unknown, returns null. + * + * This method uses the mime type as guessed by getClientMimeType() + * to guess the file extension. As such, the extension returned + * by this method cannot be trusted. + * + * For a trusted extension, use guessExtension() instead (which guesses + * the extension based on the guessed mime type for the file). + * + * @return string|null The guessed extension or null if it cannot be guessed + * + * @see guessExtension() + * @see getClientMimeType() + */ + public function guessClientExtension() + { + return MimeTypes::getDefault()->getExtensions($this->getClientMimeType())[0] ?? null; + } + + /** + * Returns the upload error. + * + * If the upload was successful, the constant UPLOAD_ERR_OK is returned. + * Otherwise one of the other UPLOAD_ERR_XXX constants is returned. + * + * @return int The upload error + */ + public function getError() + { + return $this->error; + } + + /** + * Returns whether the file was uploaded successfully. + * + * @return bool True if the file has been uploaded with HTTP and no error occurred + */ + public function isValid() + { + $isOk = UPLOAD_ERR_OK === $this->error; + + return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname()); + } + + /** + * Moves the file to a new location. + * + * @return File A File object representing the new file + * + * @throws FileException if, for any reason, the file could not have been moved + */ + public function move(string $directory, string $name = null) + { + if ($this->isValid()) { + if ($this->test) { + return parent::move($directory, $name); + } + + $target = $this->getTargetFile($directory, $name); + + set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); + $moved = move_uploaded_file($this->getPathname(), $target); + restore_error_handler(); + if (!$moved) { + throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error))); + } + + @chmod($target, 0666 & ~umask()); + + return $target; + } + + switch ($this->error) { + case UPLOAD_ERR_INI_SIZE: + throw new IniSizeFileException($this->getErrorMessage()); + case UPLOAD_ERR_FORM_SIZE: + throw new FormSizeFileException($this->getErrorMessage()); + case UPLOAD_ERR_PARTIAL: + throw new PartialFileException($this->getErrorMessage()); + case UPLOAD_ERR_NO_FILE: + throw new NoFileException($this->getErrorMessage()); + case UPLOAD_ERR_CANT_WRITE: + throw new CannotWriteFileException($this->getErrorMessage()); + case UPLOAD_ERR_NO_TMP_DIR: + throw new NoTmpDirFileException($this->getErrorMessage()); + case UPLOAD_ERR_EXTENSION: + throw new ExtensionFileException($this->getErrorMessage()); + } + + throw new FileException($this->getErrorMessage()); + } + + /** + * Returns the maximum size of an uploaded file as configured in php.ini. + * + * @return int The maximum size of an uploaded file in bytes + */ + public static function getMaxFilesize() + { + $sizePostMax = self::parseFilesize(ini_get('post_max_size')); + $sizeUploadMax = self::parseFilesize(ini_get('upload_max_filesize')); + + return min($sizePostMax ?: PHP_INT_MAX, $sizeUploadMax ?: PHP_INT_MAX); + } + + /** + * Returns the given size from an ini value in bytes. + */ + private static function parseFilesize($size): int + { + if ('' === $size) { + return 0; + } + + $size = strtolower($size); + + $max = ltrim($size, '+'); + if (0 === strpos($max, '0x')) { + $max = \intval($max, 16); + } elseif (0 === strpos($max, '0')) { + $max = \intval($max, 8); + } else { + $max = (int) $max; + } + + switch (substr($size, -1)) { + case 't': $max *= 1024; + // no break + case 'g': $max *= 1024; + // no break + case 'm': $max *= 1024; + // no break + case 'k': $max *= 1024; + } + + return $max; + } + + /** + * Returns an informative upload error message. + * + * @return string The error message regarding the specified error code + */ + public function getErrorMessage() + { + static $errors = [ + UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).', + UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.', + UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.', + UPLOAD_ERR_NO_FILE => 'No file was uploaded.', + UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.', + UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.', + UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.', + ]; + + $errorCode = $this->error; + $maxFilesize = UPLOAD_ERR_INI_SIZE === $errorCode ? self::getMaxFilesize() / 1024 : 0; + $message = isset($errors[$errorCode]) ? $errors[$errorCode] : 'The file "%s" was not uploaded due to an unknown error.'; + + return sprintf($message, $this->getClientOriginalName(), $maxFilesize); + } +} diff --git a/vendor/symfony/http-foundation/FileBag.php b/vendor/symfony/http-foundation/FileBag.php new file mode 100644 index 0000000..5edd372 --- /dev/null +++ b/vendor/symfony/http-foundation/FileBag.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +use Symfony\Component\HttpFoundation\File\UploadedFile; + +/** + * FileBag is a container for uploaded files. + * + * @author Fabien Potencier + * @author Bulat Shakirzyanov + */ +class FileBag extends ParameterBag +{ + private static $fileKeys = ['error', 'name', 'size', 'tmp_name', 'type']; + + /** + * @param array|UploadedFile[] $parameters An array of HTTP files + */ + public function __construct(array $parameters = []) + { + $this->replace($parameters); + } + + /** + * {@inheritdoc} + */ + public function replace(array $files = []) + { + $this->parameters = []; + $this->add($files); + } + + /** + * {@inheritdoc} + */ + public function set(string $key, $value) + { + if (!\is_array($value) && !$value instanceof UploadedFile) { + throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.'); + } + + parent::set($key, $this->convertFileInformation($value)); + } + + /** + * {@inheritdoc} + */ + public function add(array $files = []) + { + foreach ($files as $key => $file) { + $this->set($key, $file); + } + } + + /** + * Converts uploaded files to UploadedFile instances. + * + * @param array|UploadedFile $file A (multi-dimensional) array of uploaded file information + * + * @return UploadedFile[]|UploadedFile|null A (multi-dimensional) array of UploadedFile instances + */ + protected function convertFileInformation($file) + { + if ($file instanceof UploadedFile) { + return $file; + } + + if (\is_array($file)) { + $file = $this->fixPhpFilesArray($file); + $keys = array_keys($file); + sort($keys); + + if ($keys == self::$fileKeys) { + if (UPLOAD_ERR_NO_FILE == $file['error']) { + $file = null; + } else { + $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['error'], false); + } + } else { + $file = array_map([$this, 'convertFileInformation'], $file); + if (array_keys($keys) === $keys) { + $file = array_filter($file); + } + } + } + + return $file; + } + + /** + * Fixes a malformed PHP $_FILES array. + * + * PHP has a bug that the format of the $_FILES array differs, depending on + * whether the uploaded file fields had normal field names or array-like + * field names ("normal" vs. "parent[child]"). + * + * This method fixes the array to look like the "normal" $_FILES array. + * + * It's safe to pass an already converted array, in which case this method + * just returns the original array unmodified. + * + * @param array $data + * + * @return array + */ + protected function fixPhpFilesArray($data) + { + $keys = array_keys($data); + sort($keys); + + if (self::$fileKeys != $keys || !isset($data['name']) || !\is_array($data['name'])) { + return $data; + } + + $files = $data; + foreach (self::$fileKeys as $k) { + unset($files[$k]); + } + + foreach ($data['name'] as $key => $name) { + $files[$key] = $this->fixPhpFilesArray([ + 'error' => $data['error'][$key], + 'name' => $name, + 'type' => $data['type'][$key], + 'tmp_name' => $data['tmp_name'][$key], + 'size' => $data['size'][$key], + ]); + } + + return $files; + } +} diff --git a/vendor/symfony/http-foundation/HeaderBag.php b/vendor/symfony/http-foundation/HeaderBag.php new file mode 100644 index 0000000..9c7273a --- /dev/null +++ b/vendor/symfony/http-foundation/HeaderBag.php @@ -0,0 +1,288 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * HeaderBag is a container for HTTP headers. + * + * @author Fabien Potencier + */ +class HeaderBag implements \IteratorAggregate, \Countable +{ + protected const UPPER = '_ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + protected const LOWER = '-abcdefghijklmnopqrstuvwxyz'; + + protected $headers = []; + protected $cacheControl = []; + + public function __construct(array $headers = []) + { + foreach ($headers as $key => $values) { + $this->set($key, $values); + } + } + + /** + * Returns the headers as a string. + * + * @return string The headers + */ + public function __toString() + { + if (!$headers = $this->all()) { + return ''; + } + + ksort($headers); + $max = max(array_map('strlen', array_keys($headers))) + 1; + $content = ''; + foreach ($headers as $name => $values) { + $name = ucwords($name, '-'); + foreach ($values as $value) { + $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value); + } + } + + return $content; + } + + /** + * Returns the headers. + * + * @param string|null $key The name of the headers to return or null to get them all + * + * @return array An array of headers + */ + public function all(string $key = null) + { + if (null !== $key) { + return $this->headers[strtr($key, self::UPPER, self::LOWER)] ?? []; + } + + return $this->headers; + } + + /** + * Returns the parameter keys. + * + * @return array An array of parameter keys + */ + public function keys() + { + return array_keys($this->all()); + } + + /** + * Replaces the current HTTP headers by a new set. + */ + public function replace(array $headers = []) + { + $this->headers = []; + $this->add($headers); + } + + /** + * Adds new headers the current HTTP headers set. + */ + public function add(array $headers) + { + foreach ($headers as $key => $values) { + $this->set($key, $values); + } + } + + /** + * Returns a header value by name. + * + * @return string|null The first header value or default value + */ + public function get(string $key, string $default = null) + { + $headers = $this->all($key); + + if (!$headers) { + return $default; + } + + if (null === $headers[0]) { + return null; + } + + return (string) $headers[0]; + } + + /** + * Sets a header by name. + * + * @param string|string[] $values The value or an array of values + * @param bool $replace Whether to replace the actual value or not (true by default) + */ + public function set(string $key, $values, bool $replace = true) + { + $key = strtr($key, self::UPPER, self::LOWER); + + if (\is_array($values)) { + $values = array_values($values); + + if (true === $replace || !isset($this->headers[$key])) { + $this->headers[$key] = $values; + } else { + $this->headers[$key] = array_merge($this->headers[$key], $values); + } + } else { + if (true === $replace || !isset($this->headers[$key])) { + $this->headers[$key] = [$values]; + } else { + $this->headers[$key][] = $values; + } + } + + if ('cache-control' === $key) { + $this->cacheControl = $this->parseCacheControl(implode(', ', $this->headers[$key])); + } + } + + /** + * Returns true if the HTTP header is defined. + * + * @return bool true if the parameter exists, false otherwise + */ + public function has(string $key) + { + return \array_key_exists(strtr($key, self::UPPER, self::LOWER), $this->all()); + } + + /** + * Returns true if the given HTTP header contains the given value. + * + * @return bool true if the value is contained in the header, false otherwise + */ + public function contains(string $key, string $value) + { + return \in_array($value, $this->all($key)); + } + + /** + * Removes a header. + */ + public function remove(string $key) + { + $key = strtr($key, self::UPPER, self::LOWER); + + unset($this->headers[$key]); + + if ('cache-control' === $key) { + $this->cacheControl = []; + } + } + + /** + * Returns the HTTP header value converted to a date. + * + * @return \DateTimeInterface|null The parsed DateTime or the default value if the header does not exist + * + * @throws \RuntimeException When the HTTP header is not parseable + */ + public function getDate(string $key, \DateTime $default = null) + { + if (null === $value = $this->get($key)) { + return $default; + } + + if (false === $date = \DateTime::createFromFormat(DATE_RFC2822, $value)) { + throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value)); + } + + return $date; + } + + /** + * Adds a custom Cache-Control directive. + * + * @param mixed $value The Cache-Control directive value + */ + public function addCacheControlDirective(string $key, $value = true) + { + $this->cacheControl[$key] = $value; + + $this->set('Cache-Control', $this->getCacheControlHeader()); + } + + /** + * Returns true if the Cache-Control directive is defined. + * + * @return bool true if the directive exists, false otherwise + */ + public function hasCacheControlDirective(string $key) + { + return \array_key_exists($key, $this->cacheControl); + } + + /** + * Returns a Cache-Control directive value by name. + * + * @return mixed|null The directive value if defined, null otherwise + */ + public function getCacheControlDirective(string $key) + { + return \array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null; + } + + /** + * Removes a Cache-Control directive. + */ + public function removeCacheControlDirective(string $key) + { + unset($this->cacheControl[$key]); + + $this->set('Cache-Control', $this->getCacheControlHeader()); + } + + /** + * Returns an iterator for headers. + * + * @return \ArrayIterator An \ArrayIterator instance + */ + public function getIterator() + { + return new \ArrayIterator($this->headers); + } + + /** + * Returns the number of headers. + * + * @return int The number of headers + */ + public function count() + { + return \count($this->headers); + } + + protected function getCacheControlHeader() + { + ksort($this->cacheControl); + + return HeaderUtils::toString($this->cacheControl, ','); + } + + /** + * Parses a Cache-Control HTTP header. + * + * @return array An array representing the attribute values + */ + protected function parseCacheControl(string $header) + { + $parts = HeaderUtils::split($header, ',='); + + return HeaderUtils::combine($parts); + } +} diff --git a/vendor/symfony/http-foundation/HeaderUtils.php b/vendor/symfony/http-foundation/HeaderUtils.php new file mode 100644 index 0000000..5866e3b --- /dev/null +++ b/vendor/symfony/http-foundation/HeaderUtils.php @@ -0,0 +1,224 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * HTTP header utility functions. + * + * @author Christian Schmidt + */ +class HeaderUtils +{ + public const DISPOSITION_ATTACHMENT = 'attachment'; + public const DISPOSITION_INLINE = 'inline'; + + /** + * This class should not be instantiated. + */ + private function __construct() + { + } + + /** + * Splits an HTTP header by one or more separators. + * + * Example: + * + * HeaderUtils::split("da, en-gb;q=0.8", ",;") + * // => ['da'], ['en-gb', 'q=0.8']] + * + * @param string $separators List of characters to split on, ordered by + * precedence, e.g. ",", ";=", or ",;=" + * + * @return array Nested array with as many levels as there are characters in + * $separators + */ + public static function split(string $header, string $separators): array + { + $quotedSeparators = preg_quote($separators, '/'); + + preg_match_all(' + / + (?!\s) + (?: + # quoted-string + "(?:[^"\\\\]|\\\\.)*(?:"|\\\\|$) + | + # token + [^"'.$quotedSeparators.']+ + )+ + (?['.$quotedSeparators.']) + \s* + /x', trim($header), $matches, PREG_SET_ORDER); + + return self::groupParts($matches, $separators); + } + + /** + * Combines an array of arrays into one associative array. + * + * Each of the nested arrays should have one or two elements. The first + * value will be used as the keys in the associative array, and the second + * will be used as the values, or true if the nested array only contains one + * element. Array keys are lowercased. + * + * Example: + * + * HeaderUtils::combine([["foo", "abc"], ["bar"]]) + * // => ["foo" => "abc", "bar" => true] + */ + public static function combine(array $parts): array + { + $assoc = []; + foreach ($parts as $part) { + $name = strtolower($part[0]); + $value = $part[1] ?? true; + $assoc[$name] = $value; + } + + return $assoc; + } + + /** + * Joins an associative array into a string for use in an HTTP header. + * + * The key and value of each entry are joined with "=", and all entries + * are joined with the specified separator and an additional space (for + * readability). Values are quoted if necessary. + * + * Example: + * + * HeaderUtils::toString(["foo" => "abc", "bar" => true, "baz" => "a b c"], ",") + * // => 'foo=abc, bar, baz="a b c"' + */ + public static function toString(array $assoc, string $separator): string + { + $parts = []; + foreach ($assoc as $name => $value) { + if (true === $value) { + $parts[] = $name; + } else { + $parts[] = $name.'='.self::quote($value); + } + } + + return implode($separator.' ', $parts); + } + + /** + * Encodes a string as a quoted string, if necessary. + * + * If a string contains characters not allowed by the "token" construct in + * the HTTP specification, it is backslash-escaped and enclosed in quotes + * to match the "quoted-string" construct. + */ + public static function quote(string $s): string + { + if (preg_match('/^[a-z0-9!#$%&\'*.^_`|~-]+$/i', $s)) { + return $s; + } + + return '"'.addcslashes($s, '"\\"').'"'; + } + + /** + * Decodes a quoted string. + * + * If passed an unquoted string that matches the "token" construct (as + * defined in the HTTP specification), it is passed through verbatimly. + */ + public static function unquote(string $s): string + { + return preg_replace('/\\\\(.)|"/', '$1', $s); + } + + /** + * Generates a HTTP Content-Disposition field-value. + * + * @param string $disposition One of "inline" or "attachment" + * @param string $filename A unicode string + * @param string $filenameFallback A string containing only ASCII characters that + * is semantically equivalent to $filename. If the filename is already ASCII, + * it can be omitted, or just copied from $filename + * + * @return string A string suitable for use as a Content-Disposition field-value + * + * @throws \InvalidArgumentException + * + * @see RFC 6266 + */ + public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string + { + if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE])) { + throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE)); + } + + if ('' === $filenameFallback) { + $filenameFallback = $filename; + } + + // filenameFallback is not ASCII. + if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) { + throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.'); + } + + // percent characters aren't safe in fallback. + if (false !== strpos($filenameFallback, '%')) { + throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.'); + } + + // path separators aren't allowed in either. + if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) { + throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.'); + } + + $params = ['filename' => $filenameFallback]; + if ($filename !== $filenameFallback) { + $params['filename*'] = "utf-8''".rawurlencode($filename); + } + + return $disposition.'; '.self::toString($params, ';'); + } + + private static function groupParts(array $matches, string $separators): array + { + $separator = $separators[0]; + $partSeparators = substr($separators, 1); + + $i = 0; + $partMatches = []; + foreach ($matches as $match) { + if (isset($match['separator']) && $match['separator'] === $separator) { + ++$i; + } else { + $partMatches[$i][] = $match; + } + } + + $parts = []; + if ($partSeparators) { + foreach ($partMatches as $matches) { + $parts[] = self::groupParts($matches, $partSeparators); + } + } else { + foreach ($partMatches as $matches) { + $parts[] = self::unquote($matches[0][0]); + } + } + + return $parts; + } +} diff --git a/vendor/symfony/http-foundation/IpUtils.php b/vendor/symfony/http-foundation/IpUtils.php new file mode 100644 index 0000000..80c5a95 --- /dev/null +++ b/vendor/symfony/http-foundation/IpUtils.php @@ -0,0 +1,185 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * Http utility functions. + * + * @author Fabien Potencier + */ +class IpUtils +{ + private static $checkedIps = []; + + /** + * This class should not be instantiated. + */ + private function __construct() + { + } + + /** + * Checks if an IPv4 or IPv6 address is contained in the list of given IPs or subnets. + * + * @param string|array $ips List of IPs or subnets (can be a string if only a single one) + * + * @return bool Whether the IP is valid + */ + public static function checkIp(?string $requestIp, $ips) + { + if (!\is_array($ips)) { + $ips = [$ips]; + } + + $method = substr_count($requestIp, ':') > 1 ? 'checkIp6' : 'checkIp4'; + + foreach ($ips as $ip) { + if (self::$method($requestIp, $ip)) { + return true; + } + } + + return false; + } + + /** + * Compares two IPv4 addresses. + * In case a subnet is given, it checks if it contains the request IP. + * + * @param string $ip IPv4 address or subnet in CIDR notation + * + * @return bool Whether the request IP matches the IP, or whether the request IP is within the CIDR subnet + */ + public static function checkIp4(?string $requestIp, string $ip) + { + $cacheKey = $requestIp.'-'.$ip; + if (isset(self::$checkedIps[$cacheKey])) { + return self::$checkedIps[$cacheKey]; + } + + if (!filter_var($requestIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + return self::$checkedIps[$cacheKey] = false; + } + + if (false !== strpos($ip, '/')) { + list($address, $netmask) = explode('/', $ip, 2); + + if ('0' === $netmask) { + return self::$checkedIps[$cacheKey] = filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); + } + + if ($netmask < 0 || $netmask > 32) { + return self::$checkedIps[$cacheKey] = false; + } + } else { + $address = $ip; + $netmask = 32; + } + + if (false === ip2long($address)) { + return self::$checkedIps[$cacheKey] = false; + } + + return self::$checkedIps[$cacheKey] = 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); + } + + /** + * Compares two IPv6 addresses. + * In case a subnet is given, it checks if it contains the request IP. + * + * @author David Soria Parra + * + * @see https://github.com/dsp/v6tools + * + * @param string $ip IPv6 address or subnet in CIDR notation + * + * @return bool Whether the IP is valid + * + * @throws \RuntimeException When IPV6 support is not enabled + */ + public static function checkIp6(?string $requestIp, string $ip) + { + $cacheKey = $requestIp.'-'.$ip; + if (isset(self::$checkedIps[$cacheKey])) { + return self::$checkedIps[$cacheKey]; + } + + if (!((\extension_loaded('sockets') && \defined('AF_INET6')) || @inet_pton('::1'))) { + throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); + } + + if (false !== strpos($ip, '/')) { + list($address, $netmask) = explode('/', $ip, 2); + + if ('0' === $netmask) { + return (bool) unpack('n*', @inet_pton($address)); + } + + if ($netmask < 1 || $netmask > 128) { + return self::$checkedIps[$cacheKey] = false; + } + } else { + $address = $ip; + $netmask = 128; + } + + $bytesAddr = unpack('n*', @inet_pton($address)); + $bytesTest = unpack('n*', @inet_pton($requestIp)); + + if (!$bytesAddr || !$bytesTest) { + return self::$checkedIps[$cacheKey] = false; + } + + for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; ++$i) { + $left = $netmask - 16 * ($i - 1); + $left = ($left <= 16) ? $left : 16; + $mask = ~(0xffff >> $left) & 0xffff; + if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { + return self::$checkedIps[$cacheKey] = false; + } + } + + return self::$checkedIps[$cacheKey] = true; + } + + /** + * Anonymizes an IP/IPv6. + * + * Removes the last byte for v4 and the last 8 bytes for v6 IPs + */ + public static function anonymize(string $ip): string + { + $wrappedIPv6 = false; + if ('[' === substr($ip, 0, 1) && ']' === substr($ip, -1, 1)) { + $wrappedIPv6 = true; + $ip = substr($ip, 1, -1); + } + + $packedAddress = inet_pton($ip); + if (4 === \strlen($packedAddress)) { + $mask = '255.255.255.0'; + } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff:ffff'))) { + $mask = '::ffff:ffff:ff00'; + } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff'))) { + $mask = '::ffff:ff00'; + } else { + $mask = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000'; + } + $ip = inet_ntop($packedAddress & inet_pton($mask)); + + if ($wrappedIPv6) { + $ip = '['.$ip.']'; + } + + return $ip; + } +} diff --git a/vendor/symfony/http-foundation/JsonResponse.php b/vendor/symfony/http-foundation/JsonResponse.php new file mode 100644 index 0000000..8489bc0 --- /dev/null +++ b/vendor/symfony/http-foundation/JsonResponse.php @@ -0,0 +1,215 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * Response represents an HTTP response in JSON format. + * + * Note that this class does not force the returned JSON content to be an + * object. It is however recommended that you do return an object as it + * protects yourself against XSSI and JSON-JavaScript Hijacking. + * + * @see https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/AJAX_Security_Cheat_Sheet.md#always-return-json-with-an-object-on-the-outside + * + * @author Igor Wiedler + */ +class JsonResponse extends Response +{ + protected $data; + protected $callback; + + // Encode <, >, ', &, and " characters in the JSON, making it also safe to be embedded into HTML. + // 15 === JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT + const DEFAULT_ENCODING_OPTIONS = 15; + + protected $encodingOptions = self::DEFAULT_ENCODING_OPTIONS; + + /** + * @param mixed $data The response data + * @param int $status The response status code + * @param array $headers An array of response headers + * @param bool $json If the data is already a JSON string + */ + public function __construct($data = null, int $status = 200, array $headers = [], bool $json = false) + { + parent::__construct('', $status, $headers); + + if (null === $data) { + $data = new \ArrayObject(); + } + + $json ? $this->setJson($data) : $this->setData($data); + } + + /** + * Factory method for chainability. + * + * Example: + * + * return JsonResponse::create(['key' => 'value']) + * ->setSharedMaxAge(300); + * + * @param mixed $data The JSON response data + * @param int $status The response status code + * @param array $headers An array of response headers + * + * @return static + */ + public static function create($data = null, int $status = 200, array $headers = []) + { + return new static($data, $status, $headers); + } + + /** + * Factory method for chainability. + * + * Example: + * + * return JsonResponse::fromJsonString('{"key": "value"}') + * ->setSharedMaxAge(300); + * + * @param string|null $data The JSON response string + * @param int $status The response status code + * @param array $headers An array of response headers + * + * @return static + */ + public static function fromJsonString(string $data = null, int $status = 200, array $headers = []) + { + return new static($data, $status, $headers, true); + } + + /** + * Sets the JSONP callback. + * + * @param string|null $callback The JSONP callback or null to use none + * + * @return $this + * + * @throws \InvalidArgumentException When the callback name is not valid + */ + public function setCallback(string $callback = null) + { + if (null !== $callback) { + // partially taken from https://geekality.net/2011/08/03/valid-javascript-identifier/ + // partially taken from https://github.com/willdurand/JsonpCallbackValidator + // JsonpCallbackValidator is released under the MIT License. See https://github.com/willdurand/JsonpCallbackValidator/blob/v1.1.0/LICENSE for details. + // (c) William Durand + $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*(?:\[(?:"(?:\\\.|[^"\\\])*"|\'(?:\\\.|[^\'\\\])*\'|\d+)\])*?$/u'; + $reserved = [ + 'break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 'var', 'catch', 'finally', 'return', 'void', 'continue', 'for', 'switch', 'while', + 'debugger', 'function', 'this', 'with', 'default', 'if', 'throw', 'delete', 'in', 'try', 'class', 'enum', 'extends', 'super', 'const', 'export', + 'import', 'implements', 'let', 'private', 'public', 'yield', 'interface', 'package', 'protected', 'static', 'null', 'true', 'false', + ]; + $parts = explode('.', $callback); + foreach ($parts as $part) { + if (!preg_match($pattern, $part) || \in_array($part, $reserved, true)) { + throw new \InvalidArgumentException('The callback name is not valid.'); + } + } + } + + $this->callback = $callback; + + return $this->update(); + } + + /** + * Sets a raw string containing a JSON document to be sent. + * + * @return $this + * + * @throws \InvalidArgumentException + */ + public function setJson(string $json) + { + $this->data = $json; + + return $this->update(); + } + + /** + * Sets the data to be sent as JSON. + * + * @param mixed $data + * + * @return $this + * + * @throws \InvalidArgumentException + */ + public function setData($data = []) + { + try { + $data = json_encode($data, $this->encodingOptions); + } catch (\Exception $e) { + if ('Exception' === \get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) { + throw $e->getPrevious() ?: $e; + } + throw $e; + } + + if (\PHP_VERSION_ID >= 70300 && (JSON_THROW_ON_ERROR & $this->encodingOptions)) { + return $this->setJson($data); + } + + if (JSON_ERROR_NONE !== json_last_error()) { + throw new \InvalidArgumentException(json_last_error_msg()); + } + + return $this->setJson($data); + } + + /** + * Returns options used while encoding data to JSON. + * + * @return int + */ + public function getEncodingOptions() + { + return $this->encodingOptions; + } + + /** + * Sets options used while encoding data to JSON. + * + * @return $this + */ + public function setEncodingOptions(int $encodingOptions) + { + $this->encodingOptions = $encodingOptions; + + return $this->setData(json_decode($this->data)); + } + + /** + * Updates the content and headers according to the JSON data and callback. + * + * @return $this + */ + protected function update() + { + if (null !== $this->callback) { + // Not using application/javascript for compatibility reasons with older browsers. + $this->headers->set('Content-Type', 'text/javascript'); + + return $this->setContent(sprintf('/**/%s(%s);', $this->callback, $this->data)); + } + + // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback) + // in order to not overwrite a custom definition. + if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) { + $this->headers->set('Content-Type', 'application/json'); + } + + return $this->setContent($this->data); + } +} diff --git a/vendor/symfony/http-foundation/LICENSE b/vendor/symfony/http-foundation/LICENSE new file mode 100644 index 0000000..a677f43 --- /dev/null +++ b/vendor/symfony/http-foundation/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/http-foundation/ParameterBag.php b/vendor/symfony/http-foundation/ParameterBag.php new file mode 100644 index 0000000..212149c --- /dev/null +++ b/vendor/symfony/http-foundation/ParameterBag.php @@ -0,0 +1,205 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * ParameterBag is a container for key/value pairs. + * + * @author Fabien Potencier + */ +class ParameterBag implements \IteratorAggregate, \Countable +{ + /** + * Parameter storage. + */ + protected $parameters; + + public function __construct(array $parameters = []) + { + $this->parameters = $parameters; + } + + /** + * Returns the parameters. + * + * @return array An array of parameters + */ + public function all() + { + return $this->parameters; + } + + /** + * Returns the parameter keys. + * + * @return array An array of parameter keys + */ + public function keys() + { + return array_keys($this->parameters); + } + + /** + * Replaces the current parameters by a new set. + */ + public function replace(array $parameters = []) + { + $this->parameters = $parameters; + } + + /** + * Adds parameters. + */ + public function add(array $parameters = []) + { + $this->parameters = array_replace($this->parameters, $parameters); + } + + /** + * Returns a parameter by name. + * + * @param mixed $default The default value if the parameter key does not exist + * + * @return mixed + */ + public function get(string $key, $default = null) + { + return \array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default; + } + + /** + * Sets a parameter by name. + * + * @param mixed $value The value + */ + public function set(string $key, $value) + { + $this->parameters[$key] = $value; + } + + /** + * Returns true if the parameter is defined. + * + * @return bool true if the parameter exists, false otherwise + */ + public function has(string $key) + { + return \array_key_exists($key, $this->parameters); + } + + /** + * Removes a parameter. + */ + public function remove(string $key) + { + unset($this->parameters[$key]); + } + + /** + * Returns the alphabetic characters of the parameter value. + * + * @return string The filtered value + */ + public function getAlpha(string $key, string $default = '') + { + return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default)); + } + + /** + * Returns the alphabetic characters and digits of the parameter value. + * + * @return string The filtered value + */ + public function getAlnum(string $key, string $default = '') + { + return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default)); + } + + /** + * Returns the digits of the parameter value. + * + * @return string The filtered value + */ + public function getDigits(string $key, string $default = '') + { + // we need to remove - and + because they're allowed in the filter + return str_replace(['-', '+'], '', $this->filter($key, $default, FILTER_SANITIZE_NUMBER_INT)); + } + + /** + * Returns the parameter value converted to integer. + * + * @return int The filtered value + */ + public function getInt(string $key, int $default = 0) + { + return (int) $this->get($key, $default); + } + + /** + * Returns the parameter value converted to boolean. + * + * @return bool The filtered value + */ + public function getBoolean(string $key, bool $default = false) + { + return $this->filter($key, $default, FILTER_VALIDATE_BOOLEAN); + } + + /** + * Filter key. + * + * @param mixed $default Default = null + * @param int $filter FILTER_* constant + * @param mixed $options Filter options + * + * @see https://php.net/filter-var + * + * @return mixed + */ + public function filter(string $key, $default = null, int $filter = FILTER_DEFAULT, $options = []) + { + $value = $this->get($key, $default); + + // Always turn $options into an array - this allows filter_var option shortcuts. + if (!\is_array($options) && $options) { + $options = ['flags' => $options]; + } + + // Add a convenience check for arrays. + if (\is_array($value) && !isset($options['flags'])) { + $options['flags'] = FILTER_REQUIRE_ARRAY; + } + + return filter_var($value, $filter, $options); + } + + /** + * Returns an iterator for parameters. + * + * @return \ArrayIterator An \ArrayIterator instance + */ + public function getIterator() + { + return new \ArrayIterator($this->parameters); + } + + /** + * Returns the number of parameters. + * + * @return int The number of parameters + */ + public function count() + { + return \count($this->parameters); + } +} diff --git a/vendor/symfony/http-foundation/README.md b/vendor/symfony/http-foundation/README.md new file mode 100644 index 0000000..8907f0b --- /dev/null +++ b/vendor/symfony/http-foundation/README.md @@ -0,0 +1,14 @@ +HttpFoundation Component +======================== + +The HttpFoundation component defines an object-oriented layer for the HTTP +specification. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/http_foundation/index.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/http-foundation/RedirectResponse.php b/vendor/symfony/http-foundation/RedirectResponse.php new file mode 100644 index 0000000..13da56a --- /dev/null +++ b/vendor/symfony/http-foundation/RedirectResponse.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * RedirectResponse represents an HTTP response doing a redirect. + * + * @author Fabien Potencier + */ +class RedirectResponse extends Response +{ + protected $targetUrl; + + /** + * Creates a redirect response so that it conforms to the rules defined for a redirect status code. + * + * @param string $url The URL to redirect to. The URL should be a full URL, with schema etc., + * but practically every browser redirects on paths only as well + * @param int $status The status code (302 by default) + * @param array $headers The headers (Location is always set to the given URL) + * + * @throws \InvalidArgumentException + * + * @see https://tools.ietf.org/html/rfc2616#section-10.3 + */ + public function __construct(string $url, int $status = 302, array $headers = []) + { + parent::__construct('', $status, $headers); + + $this->setTargetUrl($url); + + if (!$this->isRedirect()) { + throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status)); + } + + if (301 == $status && !\array_key_exists('cache-control', array_change_key_case($headers, \CASE_LOWER))) { + $this->headers->remove('cache-control'); + } + } + + /** + * Factory method for chainability. + * + * @param string $url The URL to redirect to + * + * @return static + */ + public static function create($url = '', int $status = 302, array $headers = []) + { + return new static($url, $status, $headers); + } + + /** + * Returns the target URL. + * + * @return string target URL + */ + public function getTargetUrl() + { + return $this->targetUrl; + } + + /** + * Sets the redirect target of this response. + * + * @return $this + * + * @throws \InvalidArgumentException + */ + public function setTargetUrl(string $url) + { + if ('' === $url) { + throw new \InvalidArgumentException('Cannot redirect to an empty URL.'); + } + + $this->targetUrl = $url; + + $this->setContent( + sprintf(' + + + + + + Redirecting to %1$s + + + Redirecting to %1$s. + +', htmlspecialchars($url, ENT_QUOTES, 'UTF-8'))); + + $this->headers->set('Location', $url); + + return $this; + } +} diff --git a/vendor/symfony/http-foundation/Request.php b/vendor/symfony/http-foundation/Request.php new file mode 100644 index 0000000..21cb157 --- /dev/null +++ b/vendor/symfony/http-foundation/Request.php @@ -0,0 +1,2057 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; +use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; +use Symfony\Component\HttpFoundation\Session\SessionInterface; + +/** + * Request represents an HTTP request. + * + * The methods dealing with URL accept / return a raw path (% encoded): + * * getBasePath + * * getBaseUrl + * * getPathInfo + * * getRequestUri + * * getUri + * * getUriForPath + * + * @author Fabien Potencier + */ +class Request +{ + const HEADER_FORWARDED = 0b00001; // When using RFC 7239 + const HEADER_X_FORWARDED_FOR = 0b00010; + const HEADER_X_FORWARDED_HOST = 0b00100; + const HEADER_X_FORWARDED_PROTO = 0b01000; + const HEADER_X_FORWARDED_PORT = 0b10000; + const HEADER_X_FORWARDED_ALL = 0b11110; // All "X-Forwarded-*" headers + const HEADER_X_FORWARDED_AWS_ELB = 0b11010; // AWS ELB doesn't send X-Forwarded-Host + + const METHOD_HEAD = 'HEAD'; + const METHOD_GET = 'GET'; + const METHOD_POST = 'POST'; + const METHOD_PUT = 'PUT'; + const METHOD_PATCH = 'PATCH'; + const METHOD_DELETE = 'DELETE'; + const METHOD_PURGE = 'PURGE'; + const METHOD_OPTIONS = 'OPTIONS'; + const METHOD_TRACE = 'TRACE'; + const METHOD_CONNECT = 'CONNECT'; + + /** + * @var string[] + */ + protected static $trustedProxies = []; + + /** + * @var string[] + */ + protected static $trustedHostPatterns = []; + + /** + * @var string[] + */ + protected static $trustedHosts = []; + + protected static $httpMethodParameterOverride = false; + + /** + * Custom parameters. + * + * @var ParameterBag + */ + public $attributes; + + /** + * Request body parameters ($_POST). + * + * @var ParameterBag + */ + public $request; + + /** + * Query string parameters ($_GET). + * + * @var ParameterBag + */ + public $query; + + /** + * Server and execution environment parameters ($_SERVER). + * + * @var ServerBag + */ + public $server; + + /** + * Uploaded files ($_FILES). + * + * @var FileBag + */ + public $files; + + /** + * Cookies ($_COOKIE). + * + * @var ParameterBag + */ + public $cookies; + + /** + * Headers (taken from the $_SERVER). + * + * @var HeaderBag + */ + public $headers; + + /** + * @var string|resource|false|null + */ + protected $content; + + /** + * @var array + */ + protected $languages; + + /** + * @var array + */ + protected $charsets; + + /** + * @var array + */ + protected $encodings; + + /** + * @var array + */ + protected $acceptableContentTypes; + + /** + * @var string + */ + protected $pathInfo; + + /** + * @var string + */ + protected $requestUri; + + /** + * @var string + */ + protected $baseUrl; + + /** + * @var string + */ + protected $basePath; + + /** + * @var string + */ + protected $method; + + /** + * @var string + */ + protected $format; + + /** + * @var SessionInterface + */ + protected $session; + + /** + * @var string + */ + protected $locale; + + /** + * @var string + */ + protected $defaultLocale = 'en'; + + /** + * @var array + */ + protected static $formats; + + protected static $requestFactory; + + /** + * @var string|null + */ + private $preferredFormat; + private $isHostValid = true; + private $isForwardedValid = true; + + private static $trustedHeaderSet = -1; + + private static $forwardedParams = [ + self::HEADER_X_FORWARDED_FOR => 'for', + self::HEADER_X_FORWARDED_HOST => 'host', + self::HEADER_X_FORWARDED_PROTO => 'proto', + self::HEADER_X_FORWARDED_PORT => 'host', + ]; + + /** + * Names for headers that can be trusted when + * using trusted proxies. + * + * The FORWARDED header is the standard as of rfc7239. + * + * The other headers are non-standard, but widely used + * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). + */ + private static $trustedHeaders = [ + self::HEADER_FORWARDED => 'FORWARDED', + self::HEADER_X_FORWARDED_FOR => 'X_FORWARDED_FOR', + self::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST', + self::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO', + self::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT', + ]; + + /** + * @param array $query The GET parameters + * @param array $request The POST parameters + * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) + * @param array $cookies The COOKIE parameters + * @param array $files The FILES parameters + * @param array $server The SERVER parameters + * @param string|resource|null $content The raw body data + */ + public function __construct(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) + { + $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content); + } + + /** + * Sets the parameters for this request. + * + * This method also re-initializes all properties. + * + * @param array $query The GET parameters + * @param array $request The POST parameters + * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) + * @param array $cookies The COOKIE parameters + * @param array $files The FILES parameters + * @param array $server The SERVER parameters + * @param string|resource|null $content The raw body data + */ + public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) + { + $this->request = new ParameterBag($request); + $this->query = new ParameterBag($query); + $this->attributes = new ParameterBag($attributes); + $this->cookies = new ParameterBag($cookies); + $this->files = new FileBag($files); + $this->server = new ServerBag($server); + $this->headers = new HeaderBag($this->server->getHeaders()); + + $this->content = $content; + $this->languages = null; + $this->charsets = null; + $this->encodings = null; + $this->acceptableContentTypes = null; + $this->pathInfo = null; + $this->requestUri = null; + $this->baseUrl = null; + $this->basePath = null; + $this->method = null; + $this->format = null; + } + + /** + * Creates a new request with values from PHP's super globals. + * + * @return static + */ + public static function createFromGlobals() + { + $request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER); + + if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded') + && \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'DELETE', 'PATCH']) + ) { + parse_str($request->getContent(), $data); + $request->request = new ParameterBag($data); + } + + return $request; + } + + /** + * Creates a Request based on a given URI and configuration. + * + * The information contained in the URI always take precedence + * over the other information (server and parameters). + * + * @param string $uri The URI + * @param string $method The HTTP method + * @param array $parameters The query (GET) or request (POST) parameters + * @param array $cookies The request cookies ($_COOKIE) + * @param array $files The request files ($_FILES) + * @param array $server The server parameters ($_SERVER) + * @param string|resource|null $content The raw body data + * + * @return static + */ + public static function create(string $uri, string $method = 'GET', array $parameters = [], array $cookies = [], array $files = [], array $server = [], $content = null) + { + $server = array_replace([ + 'SERVER_NAME' => 'localhost', + 'SERVER_PORT' => 80, + 'HTTP_HOST' => 'localhost', + 'HTTP_USER_AGENT' => 'Symfony', + 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5', + 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', + 'REMOTE_ADDR' => '127.0.0.1', + 'SCRIPT_NAME' => '', + 'SCRIPT_FILENAME' => '', + 'SERVER_PROTOCOL' => 'HTTP/1.1', + 'REQUEST_TIME' => time(), + ], $server); + + $server['PATH_INFO'] = ''; + $server['REQUEST_METHOD'] = strtoupper($method); + + $components = parse_url($uri); + if (isset($components['host'])) { + $server['SERVER_NAME'] = $components['host']; + $server['HTTP_HOST'] = $components['host']; + } + + if (isset($components['scheme'])) { + if ('https' === $components['scheme']) { + $server['HTTPS'] = 'on'; + $server['SERVER_PORT'] = 443; + } else { + unset($server['HTTPS']); + $server['SERVER_PORT'] = 80; + } + } + + if (isset($components['port'])) { + $server['SERVER_PORT'] = $components['port']; + $server['HTTP_HOST'] .= ':'.$components['port']; + } + + if (isset($components['user'])) { + $server['PHP_AUTH_USER'] = $components['user']; + } + + if (isset($components['pass'])) { + $server['PHP_AUTH_PW'] = $components['pass']; + } + + if (!isset($components['path'])) { + $components['path'] = '/'; + } + + switch (strtoupper($method)) { + case 'POST': + case 'PUT': + case 'DELETE': + if (!isset($server['CONTENT_TYPE'])) { + $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; + } + // no break + case 'PATCH': + $request = $parameters; + $query = []; + break; + default: + $request = []; + $query = $parameters; + break; + } + + $queryString = ''; + if (isset($components['query'])) { + parse_str(html_entity_decode($components['query']), $qs); + + if ($query) { + $query = array_replace($qs, $query); + $queryString = http_build_query($query, '', '&'); + } else { + $query = $qs; + $queryString = $components['query']; + } + } elseif ($query) { + $queryString = http_build_query($query, '', '&'); + } + + $server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : ''); + $server['QUERY_STRING'] = $queryString; + + return self::createRequestFromFactory($query, $request, [], $cookies, $files, $server, $content); + } + + /** + * Sets a callable able to create a Request instance. + * + * This is mainly useful when you need to override the Request class + * to keep BC with an existing system. It should not be used for any + * other purpose. + */ + public static function setFactory(?callable $callable) + { + self::$requestFactory = $callable; + } + + /** + * Clones a request and overrides some of its parameters. + * + * @param array $query The GET parameters + * @param array $request The POST parameters + * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) + * @param array $cookies The COOKIE parameters + * @param array $files The FILES parameters + * @param array $server The SERVER parameters + * + * @return static + */ + public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null) + { + $dup = clone $this; + if (null !== $query) { + $dup->query = new ParameterBag($query); + } + if (null !== $request) { + $dup->request = new ParameterBag($request); + } + if (null !== $attributes) { + $dup->attributes = new ParameterBag($attributes); + } + if (null !== $cookies) { + $dup->cookies = new ParameterBag($cookies); + } + if (null !== $files) { + $dup->files = new FileBag($files); + } + if (null !== $server) { + $dup->server = new ServerBag($server); + $dup->headers = new HeaderBag($dup->server->getHeaders()); + } + $dup->languages = null; + $dup->charsets = null; + $dup->encodings = null; + $dup->acceptableContentTypes = null; + $dup->pathInfo = null; + $dup->requestUri = null; + $dup->baseUrl = null; + $dup->basePath = null; + $dup->method = null; + $dup->format = null; + + if (!$dup->get('_format') && $this->get('_format')) { + $dup->attributes->set('_format', $this->get('_format')); + } + + if (!$dup->getRequestFormat(null)) { + $dup->setRequestFormat($this->getRequestFormat(null)); + } + + return $dup; + } + + /** + * Clones the current request. + * + * Note that the session is not cloned as duplicated requests + * are most of the time sub-requests of the main one. + */ + public function __clone() + { + $this->query = clone $this->query; + $this->request = clone $this->request; + $this->attributes = clone $this->attributes; + $this->cookies = clone $this->cookies; + $this->files = clone $this->files; + $this->server = clone $this->server; + $this->headers = clone $this->headers; + } + + /** + * Returns the request as a string. + * + * @return string The request + */ + public function __toString() + { + try { + $content = $this->getContent(); + } catch (\LogicException $e) { + if (\PHP_VERSION_ID >= 70400) { + throw $e; + } + + return trigger_error($e, E_USER_ERROR); + } + + $cookieHeader = ''; + $cookies = []; + + foreach ($this->cookies as $k => $v) { + $cookies[] = $k.'='.$v; + } + + if (!empty($cookies)) { + $cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n"; + } + + return + sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n". + $this->headers. + $cookieHeader."\r\n". + $content; + } + + /** + * Overrides the PHP global variables according to this request instance. + * + * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE. + * $_FILES is never overridden, see rfc1867 + */ + public function overrideGlobals() + { + $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), '', '&'))); + + $_GET = $this->query->all(); + $_POST = $this->request->all(); + $_SERVER = $this->server->all(); + $_COOKIE = $this->cookies->all(); + + foreach ($this->headers->all() as $key => $value) { + $key = strtoupper(str_replace('-', '_', $key)); + if (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) { + $_SERVER[$key] = implode(', ', $value); + } else { + $_SERVER['HTTP_'.$key] = implode(', ', $value); + } + } + + $request = ['g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE]; + + $requestOrder = ini_get('request_order') ?: ini_get('variables_order'); + $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp'; + + $_REQUEST = [[]]; + + foreach (str_split($requestOrder) as $order) { + $_REQUEST[] = $request[$order]; + } + + $_REQUEST = array_merge(...$_REQUEST); + } + + /** + * Sets a list of trusted proxies. + * + * You should only list the reverse proxies that you manage directly. + * + * @param array $proxies A list of trusted proxies, the string 'REMOTE_ADDR' will be replaced with $_SERVER['REMOTE_ADDR'] + * @param int $trustedHeaderSet A bit field of Request::HEADER_*, to set which headers to trust from your proxies + * + * @throws \InvalidArgumentException When $trustedHeaderSet is invalid + */ + public static function setTrustedProxies(array $proxies, int $trustedHeaderSet) + { + self::$trustedProxies = array_reduce($proxies, function ($proxies, $proxy) { + if ('REMOTE_ADDR' !== $proxy) { + $proxies[] = $proxy; + } elseif (isset($_SERVER['REMOTE_ADDR'])) { + $proxies[] = $_SERVER['REMOTE_ADDR']; + } + + return $proxies; + }, []); + self::$trustedHeaderSet = $trustedHeaderSet; + } + + /** + * Gets the list of trusted proxies. + * + * @return array An array of trusted proxies + */ + public static function getTrustedProxies() + { + return self::$trustedProxies; + } + + /** + * Gets the set of trusted headers from trusted proxies. + * + * @return int A bit field of Request::HEADER_* that defines which headers are trusted from your proxies + */ + public static function getTrustedHeaderSet() + { + return self::$trustedHeaderSet; + } + + /** + * Sets a list of trusted host patterns. + * + * You should only list the hosts you manage using regexs. + * + * @param array $hostPatterns A list of trusted host patterns + */ + public static function setTrustedHosts(array $hostPatterns) + { + self::$trustedHostPatterns = array_map(function ($hostPattern) { + return sprintf('{%s}i', $hostPattern); + }, $hostPatterns); + // we need to reset trusted hosts on trusted host patterns change + self::$trustedHosts = []; + } + + /** + * Gets the list of trusted host patterns. + * + * @return array An array of trusted host patterns + */ + public static function getTrustedHosts() + { + return self::$trustedHostPatterns; + } + + /** + * Normalizes a query string. + * + * It builds a normalized query string, where keys/value pairs are alphabetized, + * have consistent escaping and unneeded delimiters are removed. + * + * @return string A normalized query string for the Request + */ + public static function normalizeQueryString(?string $qs) + { + if ('' === ($qs ?? '')) { + return ''; + } + + parse_str($qs, $qs); + ksort($qs); + + return http_build_query($qs, '', '&', PHP_QUERY_RFC3986); + } + + /** + * Enables support for the _method request parameter to determine the intended HTTP method. + * + * Be warned that enabling this feature might lead to CSRF issues in your code. + * Check that you are using CSRF tokens when required. + * If the HTTP method parameter override is enabled, an html-form with method "POST" can be altered + * and used to send a "PUT" or "DELETE" request via the _method request parameter. + * If these methods are not protected against CSRF, this presents a possible vulnerability. + * + * The HTTP method can only be overridden when the real HTTP method is POST. + */ + public static function enableHttpMethodParameterOverride() + { + self::$httpMethodParameterOverride = true; + } + + /** + * Checks whether support for the _method request parameter is enabled. + * + * @return bool True when the _method request parameter is enabled, false otherwise + */ + public static function getHttpMethodParameterOverride() + { + return self::$httpMethodParameterOverride; + } + + /** + * Gets a "parameter" value from any bag. + * + * This method is mainly useful for libraries that want to provide some flexibility. If you don't need the + * flexibility in controllers, it is better to explicitly get request parameters from the appropriate + * public property instead (attributes, query, request). + * + * Order of precedence: PATH (routing placeholders or custom attributes), GET, BODY + * + * @param mixed $default The default value if the parameter key does not exist + * + * @return mixed + */ + public function get(string $key, $default = null) + { + if ($this !== $result = $this->attributes->get($key, $this)) { + return $result; + } + + if ($this !== $result = $this->query->get($key, $this)) { + return $result; + } + + if ($this !== $result = $this->request->get($key, $this)) { + return $result; + } + + return $default; + } + + /** + * Gets the Session. + * + * @return SessionInterface The session + */ + public function getSession() + { + $session = $this->session; + if (!$session instanceof SessionInterface && null !== $session) { + $this->setSession($session = $session()); + } + + if (null === $session) { + throw new \BadMethodCallException('Session has not been set.'); + } + + return $session; + } + + /** + * Whether the request contains a Session which was started in one of the + * previous requests. + * + * @return bool + */ + public function hasPreviousSession() + { + // the check for $this->session avoids malicious users trying to fake a session cookie with proper name + return $this->hasSession() && $this->cookies->has($this->getSession()->getName()); + } + + /** + * Whether the request contains a Session object. + * + * This method does not give any information about the state of the session object, + * like whether the session is started or not. It is just a way to check if this Request + * is associated with a Session instance. + * + * @return bool true when the Request contains a Session object, false otherwise + */ + public function hasSession() + { + return null !== $this->session; + } + + public function setSession(SessionInterface $session) + { + $this->session = $session; + } + + /** + * @internal + */ + public function setSessionFactory(callable $factory) + { + $this->session = $factory; + } + + /** + * Returns the client IP addresses. + * + * In the returned array the most trusted IP address is first, and the + * least trusted one last. The "real" client IP address is the last one, + * but this is also the least trusted one. Trusted proxies are stripped. + * + * Use this method carefully; you should use getClientIp() instead. + * + * @return array The client IP addresses + * + * @see getClientIp() + */ + public function getClientIps() + { + $ip = $this->server->get('REMOTE_ADDR'); + + if (!$this->isFromTrustedProxy()) { + return [$ip]; + } + + return $this->getTrustedValues(self::HEADER_X_FORWARDED_FOR, $ip) ?: [$ip]; + } + + /** + * Returns the client IP address. + * + * This method can read the client IP address from the "X-Forwarded-For" header + * when trusted proxies were set via "setTrustedProxies()". The "X-Forwarded-For" + * header value is a comma+space separated list of IP addresses, the left-most + * being the original client, and each successive proxy that passed the request + * adding the IP address where it received the request from. + * + * If your reverse proxy uses a different header name than "X-Forwarded-For", + * ("Client-Ip" for instance), configure it via the $trustedHeaderSet + * argument of the Request::setTrustedProxies() method instead. + * + * @return string|null The client IP address + * + * @see getClientIps() + * @see https://wikipedia.org/wiki/X-Forwarded-For + */ + public function getClientIp() + { + $ipAddresses = $this->getClientIps(); + + return $ipAddresses[0]; + } + + /** + * Returns current script name. + * + * @return string + */ + public function getScriptName() + { + return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', '')); + } + + /** + * Returns the path being requested relative to the executed script. + * + * The path info always starts with a /. + * + * Suppose this request is instantiated from /mysite on localhost: + * + * * http://localhost/mysite returns an empty string + * * http://localhost/mysite/about returns '/about' + * * http://localhost/mysite/enco%20ded returns '/enco%20ded' + * * http://localhost/mysite/about?var=1 returns '/about' + * + * @return string The raw path (i.e. not urldecoded) + */ + public function getPathInfo() + { + if (null === $this->pathInfo) { + $this->pathInfo = $this->preparePathInfo(); + } + + return $this->pathInfo; + } + + /** + * Returns the root path from which this request is executed. + * + * Suppose that an index.php file instantiates this request object: + * + * * http://localhost/index.php returns an empty string + * * http://localhost/index.php/page returns an empty string + * * http://localhost/web/index.php returns '/web' + * * http://localhost/we%20b/index.php returns '/we%20b' + * + * @return string The raw path (i.e. not urldecoded) + */ + public function getBasePath() + { + if (null === $this->basePath) { + $this->basePath = $this->prepareBasePath(); + } + + return $this->basePath; + } + + /** + * Returns the root URL from which this request is executed. + * + * The base URL never ends with a /. + * + * This is similar to getBasePath(), except that it also includes the + * script filename (e.g. index.php) if one exists. + * + * @return string The raw URL (i.e. not urldecoded) + */ + public function getBaseUrl() + { + if (null === $this->baseUrl) { + $this->baseUrl = $this->prepareBaseUrl(); + } + + return $this->baseUrl; + } + + /** + * Gets the request's scheme. + * + * @return string + */ + public function getScheme() + { + return $this->isSecure() ? 'https' : 'http'; + } + + /** + * Returns the port on which the request is made. + * + * This method can read the client port from the "X-Forwarded-Port" header + * when trusted proxies were set via "setTrustedProxies()". + * + * The "X-Forwarded-Port" header must contain the client port. + * + * @return int|string can be a string if fetched from the server bag + */ + public function getPort() + { + if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_PORT)) { + $host = $host[0]; + } elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { + $host = $host[0]; + } elseif (!$host = $this->headers->get('HOST')) { + return $this->server->get('SERVER_PORT'); + } + + if ('[' === $host[0]) { + $pos = strpos($host, ':', strrpos($host, ']')); + } else { + $pos = strrpos($host, ':'); + } + + if (false !== $pos && $port = substr($host, $pos + 1)) { + return (int) $port; + } + + return 'https' === $this->getScheme() ? 443 : 80; + } + + /** + * Returns the user. + * + * @return string|null + */ + public function getUser() + { + return $this->headers->get('PHP_AUTH_USER'); + } + + /** + * Returns the password. + * + * @return string|null + */ + public function getPassword() + { + return $this->headers->get('PHP_AUTH_PW'); + } + + /** + * Gets the user info. + * + * @return string A user name and, optionally, scheme-specific information about how to gain authorization to access the server + */ + public function getUserInfo() + { + $userinfo = $this->getUser(); + + $pass = $this->getPassword(); + if ('' != $pass) { + $userinfo .= ":$pass"; + } + + return $userinfo; + } + + /** + * Returns the HTTP host being requested. + * + * The port name will be appended to the host if it's non-standard. + * + * @return string + */ + public function getHttpHost() + { + $scheme = $this->getScheme(); + $port = $this->getPort(); + + if (('http' == $scheme && 80 == $port) || ('https' == $scheme && 443 == $port)) { + return $this->getHost(); + } + + return $this->getHost().':'.$port; + } + + /** + * Returns the requested URI (path and query string). + * + * @return string The raw URI (i.e. not URI decoded) + */ + public function getRequestUri() + { + if (null === $this->requestUri) { + $this->requestUri = $this->prepareRequestUri(); + } + + return $this->requestUri; + } + + /** + * Gets the scheme and HTTP host. + * + * If the URL was called with basic authentication, the user + * and the password are not added to the generated string. + * + * @return string The scheme and HTTP host + */ + public function getSchemeAndHttpHost() + { + return $this->getScheme().'://'.$this->getHttpHost(); + } + + /** + * Generates a normalized URI (URL) for the Request. + * + * @return string A normalized URI (URL) for the Request + * + * @see getQueryString() + */ + public function getUri() + { + if (null !== $qs = $this->getQueryString()) { + $qs = '?'.$qs; + } + + return $this->getSchemeAndHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs; + } + + /** + * Generates a normalized URI for the given path. + * + * @param string $path A path to use instead of the current one + * + * @return string The normalized URI for the path + */ + public function getUriForPath(string $path) + { + return $this->getSchemeAndHttpHost().$this->getBaseUrl().$path; + } + + /** + * Returns the path as relative reference from the current Request path. + * + * Only the URIs path component (no schema, host etc.) is relevant and must be given. + * Both paths must be absolute and not contain relative parts. + * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. + * Furthermore, they can be used to reduce the link size in documents. + * + * Example target paths, given a base path of "/a/b/c/d": + * - "/a/b/c/d" -> "" + * - "/a/b/c/" -> "./" + * - "/a/b/" -> "../" + * - "/a/b/c/other" -> "other" + * - "/a/x/y" -> "../../x/y" + * + * @return string The relative target path + */ + public function getRelativeUriForPath(string $path) + { + // be sure that we are dealing with an absolute path + if (!isset($path[0]) || '/' !== $path[0]) { + return $path; + } + + if ($path === $basePath = $this->getPathInfo()) { + return ''; + } + + $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); + $targetDirs = explode('/', substr($path, 1)); + array_pop($sourceDirs); + $targetFile = array_pop($targetDirs); + + foreach ($sourceDirs as $i => $dir) { + if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { + unset($sourceDirs[$i], $targetDirs[$i]); + } else { + break; + } + } + + $targetDirs[] = $targetFile; + $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs); + + // A reference to the same base directory or an empty subdirectory must be prefixed with "./". + // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used + // as the first segment of a relative-path reference, as it would be mistaken for a scheme name + // (see https://tools.ietf.org/html/rfc3986#section-4.2). + return !isset($path[0]) || '/' === $path[0] + || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) + ? "./$path" : $path; + } + + /** + * Generates the normalized query string for the Request. + * + * It builds a normalized query string, where keys/value pairs are alphabetized + * and have consistent escaping. + * + * @return string|null A normalized query string for the Request + */ + public function getQueryString() + { + $qs = static::normalizeQueryString($this->server->get('QUERY_STRING')); + + return '' === $qs ? null : $qs; + } + + /** + * Checks whether the request is secure or not. + * + * This method can read the client protocol from the "X-Forwarded-Proto" header + * when trusted proxies were set via "setTrustedProxies()". + * + * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http". + * + * @return bool + */ + public function isSecure() + { + if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) { + return \in_array(strtolower($proto[0]), ['https', 'on', 'ssl', '1'], true); + } + + $https = $this->server->get('HTTPS'); + + return !empty($https) && 'off' !== strtolower($https); + } + + /** + * Returns the host name. + * + * This method can read the client host name from the "X-Forwarded-Host" header + * when trusted proxies were set via "setTrustedProxies()". + * + * The "X-Forwarded-Host" header must contain the client host name. + * + * @return string + * + * @throws SuspiciousOperationException when the host name is invalid or not trusted + */ + public function getHost() + { + if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { + $host = $host[0]; + } elseif (!$host = $this->headers->get('HOST')) { + if (!$host = $this->server->get('SERVER_NAME')) { + $host = $this->server->get('SERVER_ADDR', ''); + } + } + + // trim and remove port number from host + // host is lowercase as per RFC 952/2181 + $host = strtolower(preg_replace('/:\d+$/', '', trim($host))); + + // as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user) + // check that it does not contain forbidden characters (see RFC 952 and RFC 2181) + // use preg_replace() instead of preg_match() to prevent DoS attacks with long host names + if ($host && '' !== preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host)) { + if (!$this->isHostValid) { + return ''; + } + $this->isHostValid = false; + + throw new SuspiciousOperationException(sprintf('Invalid Host "%s".', $host)); + } + + if (\count(self::$trustedHostPatterns) > 0) { + // to avoid host header injection attacks, you should provide a list of trusted host patterns + + if (\in_array($host, self::$trustedHosts)) { + return $host; + } + + foreach (self::$trustedHostPatterns as $pattern) { + if (preg_match($pattern, $host)) { + self::$trustedHosts[] = $host; + + return $host; + } + } + + if (!$this->isHostValid) { + return ''; + } + $this->isHostValid = false; + + throw new SuspiciousOperationException(sprintf('Untrusted Host "%s".', $host)); + } + + return $host; + } + + /** + * Sets the request method. + */ + public function setMethod(string $method) + { + $this->method = null; + $this->server->set('REQUEST_METHOD', $method); + } + + /** + * Gets the request "intended" method. + * + * If the X-HTTP-Method-Override header is set, and if the method is a POST, + * then it is used to determine the "real" intended HTTP method. + * + * The _method request parameter can also be used to determine the HTTP method, + * but only if enableHttpMethodParameterOverride() has been called. + * + * The method is always an uppercased string. + * + * @return string The request method + * + * @see getRealMethod() + */ + public function getMethod() + { + if (null !== $this->method) { + return $this->method; + } + + $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET')); + + if ('POST' !== $this->method) { + return $this->method; + } + + $method = $this->headers->get('X-HTTP-METHOD-OVERRIDE'); + + if (!$method && self::$httpMethodParameterOverride) { + $method = $this->request->get('_method', $this->query->get('_method', 'POST')); + } + + if (!\is_string($method)) { + return $this->method; + } + + $method = strtoupper($method); + + if (\in_array($method, ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'PATCH', 'PURGE', 'TRACE'], true)) { + return $this->method = $method; + } + + if (!preg_match('/^[A-Z]++$/D', $method)) { + throw new SuspiciousOperationException(sprintf('Invalid method override "%s".', $method)); + } + + return $this->method = $method; + } + + /** + * Gets the "real" request method. + * + * @return string The request method + * + * @see getMethod() + */ + public function getRealMethod() + { + return strtoupper($this->server->get('REQUEST_METHOD', 'GET')); + } + + /** + * Gets the mime type associated with the format. + * + * @return string|null The associated mime type (null if not found) + */ + public function getMimeType(string $format) + { + if (null === static::$formats) { + static::initializeFormats(); + } + + return isset(static::$formats[$format]) ? static::$formats[$format][0] : null; + } + + /** + * Gets the mime types associated with the format. + * + * @return array The associated mime types + */ + public static function getMimeTypes(string $format) + { + if (null === static::$formats) { + static::initializeFormats(); + } + + return isset(static::$formats[$format]) ? static::$formats[$format] : []; + } + + /** + * Gets the format associated with the mime type. + * + * @return string|null The format (null if not found) + */ + public function getFormat(?string $mimeType) + { + $canonicalMimeType = null; + if (false !== $pos = strpos($mimeType, ';')) { + $canonicalMimeType = trim(substr($mimeType, 0, $pos)); + } + + if (null === static::$formats) { + static::initializeFormats(); + } + + foreach (static::$formats as $format => $mimeTypes) { + if (\in_array($mimeType, (array) $mimeTypes)) { + return $format; + } + if (null !== $canonicalMimeType && \in_array($canonicalMimeType, (array) $mimeTypes)) { + return $format; + } + } + + return null; + } + + /** + * Associates a format with mime types. + * + * @param string|array $mimeTypes The associated mime types (the preferred one must be the first as it will be used as the content type) + */ + public function setFormat(?string $format, $mimeTypes) + { + if (null === static::$formats) { + static::initializeFormats(); + } + + static::$formats[$format] = \is_array($mimeTypes) ? $mimeTypes : [$mimeTypes]; + } + + /** + * Gets the request format. + * + * Here is the process to determine the format: + * + * * format defined by the user (with setRequestFormat()) + * * _format request attribute + * * $default + * + * @see getPreferredFormat + * + * @return string|null The request format + */ + public function getRequestFormat(?string $default = 'html') + { + if (null === $this->format) { + $this->format = $this->attributes->get('_format'); + } + + return null === $this->format ? $default : $this->format; + } + + /** + * Sets the request format. + */ + public function setRequestFormat(?string $format) + { + $this->format = $format; + } + + /** + * Gets the format associated with the request. + * + * @return string|null The format (null if no content type is present) + */ + public function getContentType() + { + return $this->getFormat($this->headers->get('CONTENT_TYPE')); + } + + /** + * Sets the default locale. + */ + public function setDefaultLocale(string $locale) + { + $this->defaultLocale = $locale; + + if (null === $this->locale) { + $this->setPhpDefaultLocale($locale); + } + } + + /** + * Get the default locale. + * + * @return string + */ + public function getDefaultLocale() + { + return $this->defaultLocale; + } + + /** + * Sets the locale. + */ + public function setLocale(string $locale) + { + $this->setPhpDefaultLocale($this->locale = $locale); + } + + /** + * Get the locale. + * + * @return string + */ + public function getLocale() + { + return null === $this->locale ? $this->defaultLocale : $this->locale; + } + + /** + * Checks if the request method is of specified type. + * + * @param string $method Uppercase request method (GET, POST etc) + * + * @return bool + */ + public function isMethod(string $method) + { + return $this->getMethod() === strtoupper($method); + } + + /** + * Checks whether or not the method is safe. + * + * @see https://tools.ietf.org/html/rfc7231#section-4.2.1 + * + * @return bool + */ + public function isMethodSafe() + { + return \in_array($this->getMethod(), ['GET', 'HEAD', 'OPTIONS', 'TRACE']); + } + + /** + * Checks whether or not the method is idempotent. + * + * @return bool + */ + public function isMethodIdempotent() + { + return \in_array($this->getMethod(), ['HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE']); + } + + /** + * Checks whether the method is cacheable or not. + * + * @see https://tools.ietf.org/html/rfc7231#section-4.2.3 + * + * @return bool True for GET and HEAD, false otherwise + */ + public function isMethodCacheable() + { + return \in_array($this->getMethod(), ['GET', 'HEAD']); + } + + /** + * Returns the protocol version. + * + * If the application is behind a proxy, the protocol version used in the + * requests between the client and the proxy and between the proxy and the + * server might be different. This returns the former (from the "Via" header) + * if the proxy is trusted (see "setTrustedProxies()"), otherwise it returns + * the latter (from the "SERVER_PROTOCOL" server parameter). + * + * @return string + */ + public function getProtocolVersion() + { + if ($this->isFromTrustedProxy()) { + preg_match('~^(HTTP/)?([1-9]\.[0-9]) ~', $this->headers->get('Via'), $matches); + + if ($matches) { + return 'HTTP/'.$matches[2]; + } + } + + return $this->server->get('SERVER_PROTOCOL'); + } + + /** + * Returns the request body content. + * + * @param bool $asResource If true, a resource will be returned + * + * @return string|resource The request body content or a resource to read the body stream + * + * @throws \LogicException + */ + public function getContent(bool $asResource = false) + { + $currentContentIsResource = \is_resource($this->content); + + if (true === $asResource) { + if ($currentContentIsResource) { + rewind($this->content); + + return $this->content; + } + + // Content passed in parameter (test) + if (\is_string($this->content)) { + $resource = fopen('php://temp', 'r+'); + fwrite($resource, $this->content); + rewind($resource); + + return $resource; + } + + $this->content = false; + + return fopen('php://input', 'rb'); + } + + if ($currentContentIsResource) { + rewind($this->content); + + return stream_get_contents($this->content); + } + + if (null === $this->content || false === $this->content) { + $this->content = file_get_contents('php://input'); + } + + return $this->content; + } + + /** + * Gets the Etags. + * + * @return array The entity tags + */ + public function getETags() + { + return preg_split('/\s*,\s*/', $this->headers->get('if_none_match'), null, PREG_SPLIT_NO_EMPTY); + } + + /** + * @return bool + */ + public function isNoCache() + { + return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma'); + } + + /** + * Gets the preferred format for the response by inspecting, in the following order: + * * the request format set using setRequestFormat + * * the values of the Accept HTTP header + * * the content type of the body of the request. + */ + public function getPreferredFormat(?string $default = 'html'): ?string + { + if (null !== $this->preferredFormat || null !== $this->preferredFormat = $this->getRequestFormat(null)) { + return $this->preferredFormat; + } + + foreach ($this->getAcceptableContentTypes() as $mimeType) { + if ($this->preferredFormat = $this->getFormat($mimeType)) { + return $this->preferredFormat; + } + } + + return $default; + } + + /** + * Returns the preferred language. + * + * @param string[] $locales An array of ordered available locales + * + * @return string|null The preferred locale + */ + public function getPreferredLanguage(array $locales = null) + { + $preferredLanguages = $this->getLanguages(); + + if (empty($locales)) { + return isset($preferredLanguages[0]) ? $preferredLanguages[0] : null; + } + + if (!$preferredLanguages) { + return $locales[0]; + } + + $extendedPreferredLanguages = []; + foreach ($preferredLanguages as $language) { + $extendedPreferredLanguages[] = $language; + if (false !== $position = strpos($language, '_')) { + $superLanguage = substr($language, 0, $position); + if (!\in_array($superLanguage, $preferredLanguages)) { + $extendedPreferredLanguages[] = $superLanguage; + } + } + } + + $preferredLanguages = array_values(array_intersect($extendedPreferredLanguages, $locales)); + + return isset($preferredLanguages[0]) ? $preferredLanguages[0] : $locales[0]; + } + + /** + * Gets a list of languages acceptable by the client browser. + * + * @return array Languages ordered in the user browser preferences + */ + public function getLanguages() + { + if (null !== $this->languages) { + return $this->languages; + } + + $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all(); + $this->languages = []; + foreach ($languages as $lang => $acceptHeaderItem) { + if (false !== strpos($lang, '-')) { + $codes = explode('-', $lang); + if ('i' === $codes[0]) { + // Language not listed in ISO 639 that are not variants + // of any listed language, which can be registered with the + // i-prefix, such as i-cherokee + if (\count($codes) > 1) { + $lang = $codes[1]; + } + } else { + for ($i = 0, $max = \count($codes); $i < $max; ++$i) { + if (0 === $i) { + $lang = strtolower($codes[0]); + } else { + $lang .= '_'.strtoupper($codes[$i]); + } + } + } + } + + $this->languages[] = $lang; + } + + return $this->languages; + } + + /** + * Gets a list of charsets acceptable by the client browser. + * + * @return array List of charsets in preferable order + */ + public function getCharsets() + { + if (null !== $this->charsets) { + return $this->charsets; + } + + return $this->charsets = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all()); + } + + /** + * Gets a list of encodings acceptable by the client browser. + * + * @return array List of encodings in preferable order + */ + public function getEncodings() + { + if (null !== $this->encodings) { + return $this->encodings; + } + + return $this->encodings = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all()); + } + + /** + * Gets a list of content types acceptable by the client browser. + * + * @return array List of content types in preferable order + */ + public function getAcceptableContentTypes() + { + if (null !== $this->acceptableContentTypes) { + return $this->acceptableContentTypes; + } + + return $this->acceptableContentTypes = array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all()); + } + + /** + * Returns true if the request is a XMLHttpRequest. + * + * It works if your JavaScript library sets an X-Requested-With HTTP header. + * It is known to work with common JavaScript frameworks: + * + * @see https://wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript + * + * @return bool true if the request is an XMLHttpRequest, false otherwise + */ + public function isXmlHttpRequest() + { + return 'XMLHttpRequest' == $this->headers->get('X-Requested-With'); + } + + /* + * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24) + * + * Code subject to the new BSD license (https://framework.zend.com/license). + * + * Copyright (c) 2005-2010 Zend Technologies USA Inc. (https://www.zend.com/) + */ + + protected function prepareRequestUri() + { + $requestUri = ''; + + if ('1' == $this->server->get('IIS_WasUrlRewritten') && '' != $this->server->get('UNENCODED_URL')) { + // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem) + $requestUri = $this->server->get('UNENCODED_URL'); + $this->server->remove('UNENCODED_URL'); + $this->server->remove('IIS_WasUrlRewritten'); + } elseif ($this->server->has('REQUEST_URI')) { + $requestUri = $this->server->get('REQUEST_URI'); + + if ('' !== $requestUri && '/' === $requestUri[0]) { + // To only use path and query remove the fragment. + if (false !== $pos = strpos($requestUri, '#')) { + $requestUri = substr($requestUri, 0, $pos); + } + } else { + // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, + // only use URL path. + $uriComponents = parse_url($requestUri); + + if (isset($uriComponents['path'])) { + $requestUri = $uriComponents['path']; + } + + if (isset($uriComponents['query'])) { + $requestUri .= '?'.$uriComponents['query']; + } + } + } elseif ($this->server->has('ORIG_PATH_INFO')) { + // IIS 5.0, PHP as CGI + $requestUri = $this->server->get('ORIG_PATH_INFO'); + if ('' != $this->server->get('QUERY_STRING')) { + $requestUri .= '?'.$this->server->get('QUERY_STRING'); + } + $this->server->remove('ORIG_PATH_INFO'); + } + + // normalize the request URI to ease creating sub-requests from this request + $this->server->set('REQUEST_URI', $requestUri); + + return $requestUri; + } + + /** + * Prepares the base URL. + * + * @return string + */ + protected function prepareBaseUrl() + { + $filename = basename($this->server->get('SCRIPT_FILENAME')); + + if (basename($this->server->get('SCRIPT_NAME')) === $filename) { + $baseUrl = $this->server->get('SCRIPT_NAME'); + } elseif (basename($this->server->get('PHP_SELF')) === $filename) { + $baseUrl = $this->server->get('PHP_SELF'); + } elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) { + $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility + } else { + // Backtrack up the script_filename to find the portion matching + // php_self + $path = $this->server->get('PHP_SELF', ''); + $file = $this->server->get('SCRIPT_FILENAME', ''); + $segs = explode('/', trim($file, '/')); + $segs = array_reverse($segs); + $index = 0; + $last = \count($segs); + $baseUrl = ''; + do { + $seg = $segs[$index]; + $baseUrl = '/'.$seg.$baseUrl; + ++$index; + } while ($last > $index && (false !== $pos = strpos($path, $baseUrl)) && 0 != $pos); + } + + // Does the baseUrl have anything in common with the request_uri? + $requestUri = $this->getRequestUri(); + if ('' !== $requestUri && '/' !== $requestUri[0]) { + $requestUri = '/'.$requestUri; + } + + if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) { + // full $baseUrl matches + return $prefix; + } + + if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(\dirname($baseUrl), '/'.\DIRECTORY_SEPARATOR).'/')) { + // directory portion of $baseUrl matches + return rtrim($prefix, '/'.\DIRECTORY_SEPARATOR); + } + + $truncatedRequestUri = $requestUri; + if (false !== $pos = strpos($requestUri, '?')) { + $truncatedRequestUri = substr($requestUri, 0, $pos); + } + + $basename = basename($baseUrl); + if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) { + // no match whatsoever; set it blank + return ''; + } + + // If using mod_rewrite or ISAPI_Rewrite strip the script filename + // out of baseUrl. $pos !== 0 makes sure it is not matching a value + // from PATH_INFO or QUERY_STRING + if (\strlen($requestUri) >= \strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && 0 !== $pos) { + $baseUrl = substr($requestUri, 0, $pos + \strlen($baseUrl)); + } + + return rtrim($baseUrl, '/'.\DIRECTORY_SEPARATOR); + } + + /** + * Prepares the base path. + * + * @return string base path + */ + protected function prepareBasePath() + { + $baseUrl = $this->getBaseUrl(); + if (empty($baseUrl)) { + return ''; + } + + $filename = basename($this->server->get('SCRIPT_FILENAME')); + if (basename($baseUrl) === $filename) { + $basePath = \dirname($baseUrl); + } else { + $basePath = $baseUrl; + } + + if ('\\' === \DIRECTORY_SEPARATOR) { + $basePath = str_replace('\\', '/', $basePath); + } + + return rtrim($basePath, '/'); + } + + /** + * Prepares the path info. + * + * @return string path info + */ + protected function preparePathInfo() + { + if (null === ($requestUri = $this->getRequestUri())) { + return '/'; + } + + // Remove the query string from REQUEST_URI + if (false !== $pos = strpos($requestUri, '?')) { + $requestUri = substr($requestUri, 0, $pos); + } + if ('' !== $requestUri && '/' !== $requestUri[0]) { + $requestUri = '/'.$requestUri; + } + + if (null === ($baseUrl = $this->getBaseUrl())) { + return $requestUri; + } + + $pathInfo = substr($requestUri, \strlen($baseUrl)); + if (false === $pathInfo || '' === $pathInfo) { + // If substr() returns false then PATH_INFO is set to an empty string + return '/'; + } + + return (string) $pathInfo; + } + + /** + * Initializes HTTP request formats. + */ + protected static function initializeFormats() + { + static::$formats = [ + 'html' => ['text/html', 'application/xhtml+xml'], + 'txt' => ['text/plain'], + 'js' => ['application/javascript', 'application/x-javascript', 'text/javascript'], + 'css' => ['text/css'], + 'json' => ['application/json', 'application/x-json'], + 'jsonld' => ['application/ld+json'], + 'xml' => ['text/xml', 'application/xml', 'application/x-xml'], + 'rdf' => ['application/rdf+xml'], + 'atom' => ['application/atom+xml'], + 'rss' => ['application/rss+xml'], + 'form' => ['application/x-www-form-urlencoded'], + ]; + } + + private function setPhpDefaultLocale(string $locale): void + { + // if either the class Locale doesn't exist, or an exception is thrown when + // setting the default locale, the intl module is not installed, and + // the call can be ignored: + try { + if (class_exists('Locale', false)) { + \Locale::setDefault($locale); + } + } catch (\Exception $e) { + } + } + + /** + * Returns the prefix as encoded in the string when the string starts with + * the given prefix, null otherwise. + */ + private function getUrlencodedPrefix(string $string, string $prefix): ?string + { + if (0 !== strpos(rawurldecode($string), $prefix)) { + return null; + } + + $len = \strlen($prefix); + + if (preg_match(sprintf('#^(%%[[:xdigit:]]{2}|.){%d}#', $len), $string, $match)) { + return $match[0]; + } + + return null; + } + + private static function createRequestFromFactory(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): self + { + if (self::$requestFactory) { + $request = (self::$requestFactory)($query, $request, $attributes, $cookies, $files, $server, $content); + + if (!$request instanceof self) { + throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.'); + } + + return $request; + } + + return new static($query, $request, $attributes, $cookies, $files, $server, $content); + } + + /** + * Indicates whether this request originated from a trusted proxy. + * + * This can be useful to determine whether or not to trust the + * contents of a proxy-specific header. + * + * @return bool true if the request came from a trusted proxy, false otherwise + */ + public function isFromTrustedProxy() + { + return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR'), self::$trustedProxies); + } + + private function getTrustedValues(int $type, string $ip = null): array + { + $clientValues = []; + $forwardedValues = []; + + if ((self::$trustedHeaderSet & $type) && $this->headers->has(self::$trustedHeaders[$type])) { + foreach (explode(',', $this->headers->get(self::$trustedHeaders[$type])) as $v) { + $clientValues[] = (self::HEADER_X_FORWARDED_PORT === $type ? '0.0.0.0:' : '').trim($v); + } + } + + if ((self::$trustedHeaderSet & self::HEADER_FORWARDED) && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) { + $forwarded = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]); + $parts = HeaderUtils::split($forwarded, ',;='); + $forwardedValues = []; + $param = self::$forwardedParams[$type]; + foreach ($parts as $subParts) { + if (null === $v = HeaderUtils::combine($subParts)[$param] ?? null) { + continue; + } + if (self::HEADER_X_FORWARDED_PORT === $type) { + if (']' === substr($v, -1) || false === $v = strrchr($v, ':')) { + $v = $this->isSecure() ? ':443' : ':80'; + } + $v = '0.0.0.0'.$v; + } + $forwardedValues[] = $v; + } + } + + if (null !== $ip) { + $clientValues = $this->normalizeAndFilterClientIps($clientValues, $ip); + $forwardedValues = $this->normalizeAndFilterClientIps($forwardedValues, $ip); + } + + if ($forwardedValues === $clientValues || !$clientValues) { + return $forwardedValues; + } + + if (!$forwardedValues) { + return $clientValues; + } + + if (!$this->isForwardedValid) { + return null !== $ip ? ['0.0.0.0', $ip] : []; + } + $this->isForwardedValid = false; + + throw new ConflictingHeadersException(sprintf('The request has both a trusted "%s" header and a trusted "%s" header, conflicting with each other. You should either configure your proxy to remove one of them, or configure your project to distrust the offending one.', self::$trustedHeaders[self::HEADER_FORWARDED], self::$trustedHeaders[$type])); + } + + private function normalizeAndFilterClientIps(array $clientIps, string $ip): array + { + if (!$clientIps) { + return []; + } + $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from + $firstTrustedIp = null; + + foreach ($clientIps as $key => $clientIp) { + if (strpos($clientIp, '.')) { + // Strip :port from IPv4 addresses. This is allowed in Forwarded + // and may occur in X-Forwarded-For. + $i = strpos($clientIp, ':'); + if ($i) { + $clientIps[$key] = $clientIp = substr($clientIp, 0, $i); + } + } elseif (0 === strpos($clientIp, '[')) { + // Strip brackets and :port from IPv6 addresses. + $i = strpos($clientIp, ']', 1); + $clientIps[$key] = $clientIp = substr($clientIp, 1, $i - 1); + } + + if (!filter_var($clientIp, FILTER_VALIDATE_IP)) { + unset($clientIps[$key]); + + continue; + } + + if (IpUtils::checkIp($clientIp, self::$trustedProxies)) { + unset($clientIps[$key]); + + // Fallback to this when the client IP falls into the range of trusted proxies + if (null === $firstTrustedIp) { + $firstTrustedIp = $clientIp; + } + } + } + + // Now the IP chain contains only untrusted proxies and the client IP + return $clientIps ? array_reverse($clientIps) : [$firstTrustedIp]; + } +} diff --git a/vendor/symfony/http-foundation/RequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher.php new file mode 100644 index 0000000..c32c5cd --- /dev/null +++ b/vendor/symfony/http-foundation/RequestMatcher.php @@ -0,0 +1,188 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * RequestMatcher compares a pre-defined set of checks against a Request instance. + * + * @author Fabien Potencier + */ +class RequestMatcher implements RequestMatcherInterface +{ + /** + * @var string|null + */ + private $path; + + /** + * @var string|null + */ + private $host; + + /** + * @var int|null + */ + private $port; + + /** + * @var string[] + */ + private $methods = []; + + /** + * @var string[] + */ + private $ips = []; + + /** + * @var array + */ + private $attributes = []; + + /** + * @var string[] + */ + private $schemes = []; + + /** + * @param string|string[]|null $methods + * @param string|string[]|null $ips + * @param string|string[]|null $schemes + */ + public function __construct(string $path = null, string $host = null, $methods = null, $ips = null, array $attributes = [], $schemes = null, int $port = null) + { + $this->matchPath($path); + $this->matchHost($host); + $this->matchMethod($methods); + $this->matchIps($ips); + $this->matchScheme($schemes); + $this->matchPort($port); + + foreach ($attributes as $k => $v) { + $this->matchAttribute($k, $v); + } + } + + /** + * Adds a check for the HTTP scheme. + * + * @param string|string[]|null $scheme An HTTP scheme or an array of HTTP schemes + */ + public function matchScheme($scheme) + { + $this->schemes = null !== $scheme ? array_map('strtolower', (array) $scheme) : []; + } + + /** + * Adds a check for the URL host name. + */ + public function matchHost(?string $regexp) + { + $this->host = $regexp; + } + + /** + * Adds a check for the the URL port. + * + * @param int|null $port The port number to connect to + */ + public function matchPort(?int $port) + { + $this->port = $port; + } + + /** + * Adds a check for the URL path info. + */ + public function matchPath(?string $regexp) + { + $this->path = $regexp; + } + + /** + * Adds a check for the client IP. + * + * @param string $ip A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 + */ + public function matchIp(string $ip) + { + $this->matchIps($ip); + } + + /** + * Adds a check for the client IP. + * + * @param string|string[]|null $ips A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 + */ + public function matchIps($ips) + { + $this->ips = null !== $ips ? (array) $ips : []; + } + + /** + * Adds a check for the HTTP method. + * + * @param string|string[]|null $method An HTTP method or an array of HTTP methods + */ + public function matchMethod($method) + { + $this->methods = null !== $method ? array_map('strtoupper', (array) $method) : []; + } + + /** + * Adds a check for request attribute. + */ + public function matchAttribute(string $key, string $regexp) + { + $this->attributes[$key] = $regexp; + } + + /** + * {@inheritdoc} + */ + public function matches(Request $request) + { + if ($this->schemes && !\in_array($request->getScheme(), $this->schemes, true)) { + return false; + } + + if ($this->methods && !\in_array($request->getMethod(), $this->methods, true)) { + return false; + } + + foreach ($this->attributes as $key => $pattern) { + if (!preg_match('{'.$pattern.'}', $request->attributes->get($key))) { + return false; + } + } + + if (null !== $this->path && !preg_match('{'.$this->path.'}', rawurldecode($request->getPathInfo()))) { + return false; + } + + if (null !== $this->host && !preg_match('{'.$this->host.'}i', $request->getHost())) { + return false; + } + + if (null !== $this->port && 0 < $this->port && $request->getPort() !== $this->port) { + return false; + } + + if (IpUtils::checkIp($request->getClientIp(), $this->ips)) { + return true; + } + + // Note to future implementors: add additional checks above the + // foreach above or else your check might not be run! + return 0 === \count($this->ips); + } +} diff --git a/vendor/symfony/http-foundation/RequestMatcherInterface.php b/vendor/symfony/http-foundation/RequestMatcherInterface.php new file mode 100644 index 0000000..c26db3e --- /dev/null +++ b/vendor/symfony/http-foundation/RequestMatcherInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * RequestMatcherInterface is an interface for strategies to match a Request. + * + * @author Fabien Potencier + */ +interface RequestMatcherInterface +{ + /** + * Decides whether the rule(s) implemented by the strategy matches the supplied request. + * + * @return bool true if the request matches, false otherwise + */ + public function matches(Request $request); +} diff --git a/vendor/symfony/http-foundation/RequestStack.php b/vendor/symfony/http-foundation/RequestStack.php new file mode 100644 index 0000000..244a77d --- /dev/null +++ b/vendor/symfony/http-foundation/RequestStack.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * Request stack that controls the lifecycle of requests. + * + * @author Benjamin Eberlei + */ +class RequestStack +{ + /** + * @var Request[] + */ + private $requests = []; + + /** + * Pushes a Request on the stack. + * + * This method should generally not be called directly as the stack + * management should be taken care of by the application itself. + */ + public function push(Request $request) + { + $this->requests[] = $request; + } + + /** + * Pops the current request from the stack. + * + * This operation lets the current request go out of scope. + * + * This method should generally not be called directly as the stack + * management should be taken care of by the application itself. + * + * @return Request|null + */ + public function pop() + { + if (!$this->requests) { + return null; + } + + return array_pop($this->requests); + } + + /** + * @return Request|null + */ + public function getCurrentRequest() + { + return end($this->requests) ?: null; + } + + /** + * Gets the master Request. + * + * Be warned that making your code aware of the master request + * might make it un-compatible with other features of your framework + * like ESI support. + * + * @return Request|null + */ + public function getMasterRequest() + { + if (!$this->requests) { + return null; + } + + return $this->requests[0]; + } + + /** + * Returns the parent request of the current. + * + * Be warned that making your code aware of the parent request + * might make it un-compatible with other features of your framework + * like ESI support. + * + * If current Request is the master request, it returns null. + * + * @return Request|null + */ + public function getParentRequest() + { + $pos = \count($this->requests) - 2; + + if (!isset($this->requests[$pos])) { + return null; + } + + return $this->requests[$pos]; + } +} diff --git a/vendor/symfony/http-foundation/Response.php b/vendor/symfony/http-foundation/Response.php new file mode 100644 index 0000000..9122b13 --- /dev/null +++ b/vendor/symfony/http-foundation/Response.php @@ -0,0 +1,1224 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * Response represents an HTTP response. + * + * @author Fabien Potencier + */ +class Response +{ + const HTTP_CONTINUE = 100; + const HTTP_SWITCHING_PROTOCOLS = 101; + const HTTP_PROCESSING = 102; // RFC2518 + const HTTP_EARLY_HINTS = 103; // RFC8297 + const HTTP_OK = 200; + const HTTP_CREATED = 201; + const HTTP_ACCEPTED = 202; + const HTTP_NON_AUTHORITATIVE_INFORMATION = 203; + const HTTP_NO_CONTENT = 204; + const HTTP_RESET_CONTENT = 205; + const HTTP_PARTIAL_CONTENT = 206; + const HTTP_MULTI_STATUS = 207; // RFC4918 + const HTTP_ALREADY_REPORTED = 208; // RFC5842 + const HTTP_IM_USED = 226; // RFC3229 + const HTTP_MULTIPLE_CHOICES = 300; + const HTTP_MOVED_PERMANENTLY = 301; + const HTTP_FOUND = 302; + const HTTP_SEE_OTHER = 303; + const HTTP_NOT_MODIFIED = 304; + const HTTP_USE_PROXY = 305; + const HTTP_RESERVED = 306; + const HTTP_TEMPORARY_REDIRECT = 307; + const HTTP_PERMANENTLY_REDIRECT = 308; // RFC7238 + const HTTP_BAD_REQUEST = 400; + const HTTP_UNAUTHORIZED = 401; + const HTTP_PAYMENT_REQUIRED = 402; + const HTTP_FORBIDDEN = 403; + const HTTP_NOT_FOUND = 404; + const HTTP_METHOD_NOT_ALLOWED = 405; + const HTTP_NOT_ACCEPTABLE = 406; + const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; + const HTTP_REQUEST_TIMEOUT = 408; + const HTTP_CONFLICT = 409; + const HTTP_GONE = 410; + const HTTP_LENGTH_REQUIRED = 411; + const HTTP_PRECONDITION_FAILED = 412; + const HTTP_REQUEST_ENTITY_TOO_LARGE = 413; + const HTTP_REQUEST_URI_TOO_LONG = 414; + const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; + const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; + const HTTP_EXPECTATION_FAILED = 417; + const HTTP_I_AM_A_TEAPOT = 418; // RFC2324 + const HTTP_MISDIRECTED_REQUEST = 421; // RFC7540 + const HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918 + const HTTP_LOCKED = 423; // RFC4918 + const HTTP_FAILED_DEPENDENCY = 424; // RFC4918 + const HTTP_TOO_EARLY = 425; // RFC-ietf-httpbis-replay-04 + const HTTP_UPGRADE_REQUIRED = 426; // RFC2817 + const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585 + const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585 + const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585 + const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; + const HTTP_INTERNAL_SERVER_ERROR = 500; + const HTTP_NOT_IMPLEMENTED = 501; + const HTTP_BAD_GATEWAY = 502; + const HTTP_SERVICE_UNAVAILABLE = 503; + const HTTP_GATEWAY_TIMEOUT = 504; + const HTTP_VERSION_NOT_SUPPORTED = 505; + const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506; // RFC2295 + const HTTP_INSUFFICIENT_STORAGE = 507; // RFC4918 + const HTTP_LOOP_DETECTED = 508; // RFC5842 + const HTTP_NOT_EXTENDED = 510; // RFC2774 + const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; // RFC6585 + + /** + * @var ResponseHeaderBag + */ + public $headers; + + /** + * @var string + */ + protected $content; + + /** + * @var string + */ + protected $version; + + /** + * @var int + */ + protected $statusCode; + + /** + * @var string + */ + protected $statusText; + + /** + * @var string + */ + protected $charset; + + /** + * Status codes translation table. + * + * The list of codes is complete according to the + * {@link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml Hypertext Transfer Protocol (HTTP) Status Code Registry} + * (last updated 2016-03-01). + * + * Unless otherwise noted, the status code is defined in RFC2616. + * + * @var array + */ + public static $statusTexts = [ + 100 => 'Continue', + 101 => 'Switching Protocols', + 102 => 'Processing', // RFC2518 + 103 => 'Early Hints', + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + 207 => 'Multi-Status', // RFC4918 + 208 => 'Already Reported', // RFC5842 + 226 => 'IM Used', // RFC3229 + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 307 => 'Temporary Redirect', + 308 => 'Permanent Redirect', // RFC7238 + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Payload Too Large', + 414 => 'URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Range Not Satisfiable', + 417 => 'Expectation Failed', + 418 => 'I\'m a teapot', // RFC2324 + 421 => 'Misdirected Request', // RFC7540 + 422 => 'Unprocessable Entity', // RFC4918 + 423 => 'Locked', // RFC4918 + 424 => 'Failed Dependency', // RFC4918 + 425 => 'Too Early', // RFC-ietf-httpbis-replay-04 + 426 => 'Upgrade Required', // RFC2817 + 428 => 'Precondition Required', // RFC6585 + 429 => 'Too Many Requests', // RFC6585 + 431 => 'Request Header Fields Too Large', // RFC6585 + 451 => 'Unavailable For Legal Reasons', // RFC7725 + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported', + 506 => 'Variant Also Negotiates', // RFC2295 + 507 => 'Insufficient Storage', // RFC4918 + 508 => 'Loop Detected', // RFC5842 + 510 => 'Not Extended', // RFC2774 + 511 => 'Network Authentication Required', // RFC6585 + ]; + + /** + * @throws \InvalidArgumentException When the HTTP status code is not valid + */ + public function __construct(?string $content = '', int $status = 200, array $headers = []) + { + $this->headers = new ResponseHeaderBag($headers); + $this->setContent($content); + $this->setStatusCode($status); + $this->setProtocolVersion('1.0'); + } + + /** + * Factory method for chainability. + * + * Example: + * + * return Response::create($body, 200) + * ->setSharedMaxAge(300); + * + * @return static + */ + public static function create(?string $content = '', int $status = 200, array $headers = []) + { + return new static($content, $status, $headers); + } + + /** + * Returns the Response as an HTTP string. + * + * The string representation of the Response is the same as the + * one that will be sent to the client only if the prepare() method + * has been called before. + * + * @return string The Response as an HTTP string + * + * @see prepare() + */ + public function __toString() + { + return + sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\r\n". + $this->headers."\r\n". + $this->getContent(); + } + + /** + * Clones the current Response instance. + */ + public function __clone() + { + $this->headers = clone $this->headers; + } + + /** + * Prepares the Response before it is sent to the client. + * + * This method tweaks the Response to ensure that it is + * compliant with RFC 2616. Most of the changes are based on + * the Request that is "associated" with this Response. + * + * @return $this + */ + public function prepare(Request $request) + { + $headers = $this->headers; + + if ($this->isInformational() || $this->isEmpty()) { + $this->setContent(null); + $headers->remove('Content-Type'); + $headers->remove('Content-Length'); + } else { + // Content-type based on the Request + if (!$headers->has('Content-Type')) { + $format = $request->getPreferredFormat(); + if (null !== $format && $mimeType = $request->getMimeType($format)) { + $headers->set('Content-Type', $mimeType); + } + } + + // Fix Content-Type + $charset = $this->charset ?: 'UTF-8'; + if (!$headers->has('Content-Type')) { + $headers->set('Content-Type', 'text/html; charset='.$charset); + } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) { + // add the charset + $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset); + } + + // Fix Content-Length + if ($headers->has('Transfer-Encoding')) { + $headers->remove('Content-Length'); + } + + if ($request->isMethod('HEAD')) { + // cf. RFC2616 14.13 + $length = $headers->get('Content-Length'); + $this->setContent(null); + if ($length) { + $headers->set('Content-Length', $length); + } + } + } + + // Fix protocol + if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) { + $this->setProtocolVersion('1.1'); + } + + // Check if we need to send extra expire info headers + if ('1.0' == $this->getProtocolVersion() && false !== strpos($headers->get('Cache-Control'), 'no-cache')) { + $headers->set('pragma', 'no-cache'); + $headers->set('expires', -1); + } + + $this->ensureIEOverSSLCompatibility($request); + + if ($request->isSecure()) { + foreach ($headers->getCookies() as $cookie) { + $cookie->setSecureDefault(true); + } + } + + return $this; + } + + /** + * Sends HTTP headers. + * + * @return $this + */ + public function sendHeaders() + { + // headers have already been sent by the developer + if (headers_sent()) { + return $this; + } + + // headers + foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) { + $replace = 0 === strcasecmp($name, 'Content-Type'); + foreach ($values as $value) { + header($name.': '.$value, $replace, $this->statusCode); + } + } + + // cookies + foreach ($this->headers->getCookies() as $cookie) { + header('Set-Cookie: '.$cookie, false, $this->statusCode); + } + + // status + header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode); + + return $this; + } + + /** + * Sends content for the current web response. + * + * @return $this + */ + public function sendContent() + { + echo $this->content; + + return $this; + } + + /** + * Sends HTTP headers and content. + * + * @return $this + */ + public function send() + { + $this->sendHeaders(); + $this->sendContent(); + + if (\function_exists('fastcgi_finish_request')) { + fastcgi_finish_request(); + } elseif (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { + static::closeOutputBuffers(0, true); + } + + return $this; + } + + /** + * Sets the response content. + * + * @return $this + * + * @throws \UnexpectedValueException + */ + public function setContent(?string $content) + { + $this->content = $content ?? ''; + + return $this; + } + + /** + * Gets the current response content. + * + * @return string|false + */ + public function getContent() + { + return $this->content; + } + + /** + * Sets the HTTP protocol version (1.0 or 1.1). + * + * @return $this + * + * @final + */ + public function setProtocolVersion(string $version): object + { + $this->version = $version; + + return $this; + } + + /** + * Gets the HTTP protocol version. + * + * @final + */ + public function getProtocolVersion(): string + { + return $this->version; + } + + /** + * Sets the response status code. + * + * If the status text is null it will be automatically populated for the known + * status codes and left empty otherwise. + * + * @return $this + * + * @throws \InvalidArgumentException When the HTTP status code is not valid + * + * @final + */ + public function setStatusCode(int $code, $text = null): object + { + $this->statusCode = $code; + if ($this->isInvalid()) { + throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code)); + } + + if (null === $text) { + $this->statusText = isset(self::$statusTexts[$code]) ? self::$statusTexts[$code] : 'unknown status'; + + return $this; + } + + if (false === $text) { + $this->statusText = ''; + + return $this; + } + + $this->statusText = $text; + + return $this; + } + + /** + * Retrieves the status code for the current web response. + * + * @final + */ + public function getStatusCode(): int + { + return $this->statusCode; + } + + /** + * Sets the response charset. + * + * @return $this + * + * @final + */ + public function setCharset(string $charset): object + { + $this->charset = $charset; + + return $this; + } + + /** + * Retrieves the response charset. + * + * @final + */ + public function getCharset(): ?string + { + return $this->charset; + } + + /** + * Returns true if the response may safely be kept in a shared (surrogate) cache. + * + * Responses marked "private" with an explicit Cache-Control directive are + * considered uncacheable. + * + * Responses with neither a freshness lifetime (Expires, max-age) nor cache + * validator (Last-Modified, ETag) are considered uncacheable because there is + * no way to tell when or how to remove them from the cache. + * + * Note that RFC 7231 and RFC 7234 possibly allow for a more permissive implementation, + * for example "status codes that are defined as cacheable by default [...] + * can be reused by a cache with heuristic expiration unless otherwise indicated" + * (https://tools.ietf.org/html/rfc7231#section-6.1) + * + * @final + */ + public function isCacheable(): bool + { + if (!\in_array($this->statusCode, [200, 203, 300, 301, 302, 404, 410])) { + return false; + } + + if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) { + return false; + } + + return $this->isValidateable() || $this->isFresh(); + } + + /** + * Returns true if the response is "fresh". + * + * Fresh responses may be served from cache without any interaction with the + * origin. A response is considered fresh when it includes a Cache-Control/max-age + * indicator or Expires header and the calculated age is less than the freshness lifetime. + * + * @final + */ + public function isFresh(): bool + { + return $this->getTtl() > 0; + } + + /** + * Returns true if the response includes headers that can be used to validate + * the response with the origin server using a conditional GET request. + * + * @final + */ + public function isValidateable(): bool + { + return $this->headers->has('Last-Modified') || $this->headers->has('ETag'); + } + + /** + * Marks the response as "private". + * + * It makes the response ineligible for serving other clients. + * + * @return $this + * + * @final + */ + public function setPrivate(): object + { + $this->headers->removeCacheControlDirective('public'); + $this->headers->addCacheControlDirective('private'); + + return $this; + } + + /** + * Marks the response as "public". + * + * It makes the response eligible for serving other clients. + * + * @return $this + * + * @final + */ + public function setPublic(): object + { + $this->headers->addCacheControlDirective('public'); + $this->headers->removeCacheControlDirective('private'); + + return $this; + } + + /** + * Marks the response as "immutable". + * + * @return $this + * + * @final + */ + public function setImmutable(bool $immutable = true): object + { + if ($immutable) { + $this->headers->addCacheControlDirective('immutable'); + } else { + $this->headers->removeCacheControlDirective('immutable'); + } + + return $this; + } + + /** + * Returns true if the response is marked as "immutable". + * + * @final + */ + public function isImmutable(): bool + { + return $this->headers->hasCacheControlDirective('immutable'); + } + + /** + * Returns true if the response must be revalidated by caches. + * + * This method indicates that the response must not be served stale by a + * cache in any circumstance without first revalidating with the origin. + * When present, the TTL of the response should not be overridden to be + * greater than the value provided by the origin. + * + * @final + */ + public function mustRevalidate(): bool + { + return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->hasCacheControlDirective('proxy-revalidate'); + } + + /** + * Returns the Date header as a DateTime instance. + * + * @throws \RuntimeException When the header is not parseable + * + * @final + */ + public function getDate(): ?\DateTimeInterface + { + return $this->headers->getDate('Date'); + } + + /** + * Sets the Date header. + * + * @return $this + * + * @final + */ + public function setDate(\DateTimeInterface $date): object + { + if ($date instanceof \DateTime) { + $date = \DateTimeImmutable::createFromMutable($date); + } + + $date = $date->setTimezone(new \DateTimeZone('UTC')); + $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT'); + + return $this; + } + + /** + * Returns the age of the response in seconds. + * + * @final + */ + public function getAge(): int + { + if (null !== $age = $this->headers->get('Age')) { + return (int) $age; + } + + return max(time() - (int) $this->getDate()->format('U'), 0); + } + + /** + * Marks the response stale by setting the Age header to be equal to the maximum age of the response. + * + * @return $this + */ + public function expire() + { + if ($this->isFresh()) { + $this->headers->set('Age', $this->getMaxAge()); + $this->headers->remove('Expires'); + } + + return $this; + } + + /** + * Returns the value of the Expires header as a DateTime instance. + * + * @final + */ + public function getExpires(): ?\DateTimeInterface + { + try { + return $this->headers->getDate('Expires'); + } catch (\RuntimeException $e) { + // according to RFC 2616 invalid date formats (e.g. "0" and "-1") must be treated as in the past + return \DateTime::createFromFormat('U', time() - 172800); + } + } + + /** + * Sets the Expires HTTP header with a DateTime instance. + * + * Passing null as value will remove the header. + * + * @return $this + * + * @final + */ + public function setExpires(\DateTimeInterface $date = null): object + { + if (null === $date) { + $this->headers->remove('Expires'); + + return $this; + } + + if ($date instanceof \DateTime) { + $date = \DateTimeImmutable::createFromMutable($date); + } + + $date = $date->setTimezone(new \DateTimeZone('UTC')); + $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT'); + + return $this; + } + + /** + * Returns the number of seconds after the time specified in the response's Date + * header when the response should no longer be considered fresh. + * + * First, it checks for a s-maxage directive, then a max-age directive, and then it falls + * back on an expires header. It returns null when no maximum age can be established. + * + * @final + */ + public function getMaxAge(): ?int + { + if ($this->headers->hasCacheControlDirective('s-maxage')) { + return (int) $this->headers->getCacheControlDirective('s-maxage'); + } + + if ($this->headers->hasCacheControlDirective('max-age')) { + return (int) $this->headers->getCacheControlDirective('max-age'); + } + + if (null !== $this->getExpires()) { + return (int) $this->getExpires()->format('U') - (int) $this->getDate()->format('U'); + } + + return null; + } + + /** + * Sets the number of seconds after which the response should no longer be considered fresh. + * + * This methods sets the Cache-Control max-age directive. + * + * @return $this + * + * @final + */ + public function setMaxAge(int $value): object + { + $this->headers->addCacheControlDirective('max-age', $value); + + return $this; + } + + /** + * Sets the number of seconds after which the response should no longer be considered fresh by shared caches. + * + * This methods sets the Cache-Control s-maxage directive. + * + * @return $this + * + * @final + */ + public function setSharedMaxAge(int $value): object + { + $this->setPublic(); + $this->headers->addCacheControlDirective('s-maxage', $value); + + return $this; + } + + /** + * Returns the response's time-to-live in seconds. + * + * It returns null when no freshness information is present in the response. + * + * When the responses TTL is <= 0, the response may not be served from cache without first + * revalidating with the origin. + * + * @final + */ + public function getTtl(): ?int + { + $maxAge = $this->getMaxAge(); + + return null !== $maxAge ? $maxAge - $this->getAge() : null; + } + + /** + * Sets the response's time-to-live for shared caches in seconds. + * + * This method adjusts the Cache-Control/s-maxage directive. + * + * @return $this + * + * @final + */ + public function setTtl(int $seconds): object + { + $this->setSharedMaxAge($this->getAge() + $seconds); + + return $this; + } + + /** + * Sets the response's time-to-live for private/client caches in seconds. + * + * This method adjusts the Cache-Control/max-age directive. + * + * @return $this + * + * @final + */ + public function setClientTtl(int $seconds): object + { + $this->setMaxAge($this->getAge() + $seconds); + + return $this; + } + + /** + * Returns the Last-Modified HTTP header as a DateTime instance. + * + * @throws \RuntimeException When the HTTP header is not parseable + * + * @final + */ + public function getLastModified(): ?\DateTimeInterface + { + return $this->headers->getDate('Last-Modified'); + } + + /** + * Sets the Last-Modified HTTP header with a DateTime instance. + * + * Passing null as value will remove the header. + * + * @return $this + * + * @final + */ + public function setLastModified(\DateTimeInterface $date = null): object + { + if (null === $date) { + $this->headers->remove('Last-Modified'); + + return $this; + } + + if ($date instanceof \DateTime) { + $date = \DateTimeImmutable::createFromMutable($date); + } + + $date = $date->setTimezone(new \DateTimeZone('UTC')); + $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT'); + + return $this; + } + + /** + * Returns the literal value of the ETag HTTP header. + * + * @final + */ + public function getEtag(): ?string + { + return $this->headers->get('ETag'); + } + + /** + * Sets the ETag value. + * + * @param string|null $etag The ETag unique identifier or null to remove the header + * @param bool $weak Whether you want a weak ETag or not + * + * @return $this + * + * @final + */ + public function setEtag(string $etag = null, bool $weak = false): object + { + if (null === $etag) { + $this->headers->remove('Etag'); + } else { + if (0 !== strpos($etag, '"')) { + $etag = '"'.$etag.'"'; + } + + $this->headers->set('ETag', (true === $weak ? 'W/' : '').$etag); + } + + return $this; + } + + /** + * Sets the response's cache headers (validation and/or expiration). + * + * Available options are: etag, last_modified, max_age, s_maxage, private, public and immutable. + * + * @return $this + * + * @throws \InvalidArgumentException + * + * @final + */ + public function setCache(array $options): object + { + if ($diff = array_diff(array_keys($options), ['etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public', 'immutable'])) { + throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', $diff))); + } + + if (isset($options['etag'])) { + $this->setEtag($options['etag']); + } + + if (isset($options['last_modified'])) { + $this->setLastModified($options['last_modified']); + } + + if (isset($options['max_age'])) { + $this->setMaxAge($options['max_age']); + } + + if (isset($options['s_maxage'])) { + $this->setSharedMaxAge($options['s_maxage']); + } + + if (isset($options['public'])) { + if ($options['public']) { + $this->setPublic(); + } else { + $this->setPrivate(); + } + } + + if (isset($options['private'])) { + if ($options['private']) { + $this->setPrivate(); + } else { + $this->setPublic(); + } + } + + if (isset($options['immutable'])) { + $this->setImmutable((bool) $options['immutable']); + } + + return $this; + } + + /** + * Modifies the response so that it conforms to the rules defined for a 304 status code. + * + * This sets the status, removes the body, and discards any headers + * that MUST NOT be included in 304 responses. + * + * @return $this + * + * @see https://tools.ietf.org/html/rfc2616#section-10.3.5 + * + * @final + */ + public function setNotModified(): object + { + $this->setStatusCode(304); + $this->setContent(null); + + // remove headers that MUST NOT be included with 304 Not Modified responses + foreach (['Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified'] as $header) { + $this->headers->remove($header); + } + + return $this; + } + + /** + * Returns true if the response includes a Vary header. + * + * @final + */ + public function hasVary(): bool + { + return null !== $this->headers->get('Vary'); + } + + /** + * Returns an array of header names given in the Vary header. + * + * @final + */ + public function getVary(): array + { + if (!$vary = $this->headers->all('Vary')) { + return []; + } + + $ret = []; + foreach ($vary as $item) { + $ret = array_merge($ret, preg_split('/[\s,]+/', $item)); + } + + return $ret; + } + + /** + * Sets the Vary header. + * + * @param string|array $headers + * @param bool $replace Whether to replace the actual value or not (true by default) + * + * @return $this + * + * @final + */ + public function setVary($headers, bool $replace = true): object + { + $this->headers->set('Vary', $headers, $replace); + + return $this; + } + + /** + * Determines if the Response validators (ETag, Last-Modified) match + * a conditional value specified in the Request. + * + * If the Response is not modified, it sets the status code to 304 and + * removes the actual content by calling the setNotModified() method. + * + * @return bool true if the Response validators match the Request, false otherwise + * + * @final + */ + public function isNotModified(Request $request): bool + { + if (!$request->isMethodCacheable()) { + return false; + } + + $notModified = false; + $lastModified = $this->headers->get('Last-Modified'); + $modifiedSince = $request->headers->get('If-Modified-Since'); + + if ($etags = $request->getETags()) { + $notModified = \in_array($this->getEtag(), $etags) || \in_array('*', $etags); + } + + if ($modifiedSince && $lastModified) { + $notModified = strtotime($modifiedSince) >= strtotime($lastModified) && (!$etags || $notModified); + } + + if ($notModified) { + $this->setNotModified(); + } + + return $notModified; + } + + /** + * Is response invalid? + * + * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html + * + * @final + */ + public function isInvalid(): bool + { + return $this->statusCode < 100 || $this->statusCode >= 600; + } + + /** + * Is response informative? + * + * @final + */ + public function isInformational(): bool + { + return $this->statusCode >= 100 && $this->statusCode < 200; + } + + /** + * Is response successful? + * + * @final + */ + public function isSuccessful(): bool + { + return $this->statusCode >= 200 && $this->statusCode < 300; + } + + /** + * Is the response a redirect? + * + * @final + */ + public function isRedirection(): bool + { + return $this->statusCode >= 300 && $this->statusCode < 400; + } + + /** + * Is there a client error? + * + * @final + */ + public function isClientError(): bool + { + return $this->statusCode >= 400 && $this->statusCode < 500; + } + + /** + * Was there a server side error? + * + * @final + */ + public function isServerError(): bool + { + return $this->statusCode >= 500 && $this->statusCode < 600; + } + + /** + * Is the response OK? + * + * @final + */ + public function isOk(): bool + { + return 200 === $this->statusCode; + } + + /** + * Is the response forbidden? + * + * @final + */ + public function isForbidden(): bool + { + return 403 === $this->statusCode; + } + + /** + * Is the response a not found error? + * + * @final + */ + public function isNotFound(): bool + { + return 404 === $this->statusCode; + } + + /** + * Is the response a redirect of some form? + * + * @final + */ + public function isRedirect(string $location = null): bool + { + return \in_array($this->statusCode, [201, 301, 302, 303, 307, 308]) && (null === $location ?: $location == $this->headers->get('Location')); + } + + /** + * Is the response empty? + * + * @final + */ + public function isEmpty(): bool + { + return \in_array($this->statusCode, [204, 304]); + } + + /** + * Cleans or flushes output buffers up to target level. + * + * Resulting level can be greater than target level if a non-removable buffer has been encountered. + * + * @final + */ + public static function closeOutputBuffers(int $targetLevel, bool $flush): void + { + $status = ob_get_status(true); + $level = \count($status); + $flags = PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? PHP_OUTPUT_HANDLER_FLUSHABLE : PHP_OUTPUT_HANDLER_CLEANABLE); + + while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || ($s['flags'] & $flags) === $flags : $s['del'])) { + if ($flush) { + ob_end_flush(); + } else { + ob_end_clean(); + } + } + } + + /** + * Checks if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9. + * + * @see http://support.microsoft.com/kb/323308 + * + * @final + */ + protected function ensureIEOverSSLCompatibility(Request $request): void + { + if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && 1 == preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) && true === $request->isSecure()) { + if ((int) preg_replace('/(MSIE )(.*?);/', '$2', $match[0]) < 9) { + $this->headers->remove('Cache-Control'); + } + } + } +} diff --git a/vendor/symfony/http-foundation/ResponseHeaderBag.php b/vendor/symfony/http-foundation/ResponseHeaderBag.php new file mode 100644 index 0000000..56b9245 --- /dev/null +++ b/vendor/symfony/http-foundation/ResponseHeaderBag.php @@ -0,0 +1,293 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * ResponseHeaderBag is a container for Response HTTP headers. + * + * @author Fabien Potencier + */ +class ResponseHeaderBag extends HeaderBag +{ + const COOKIES_FLAT = 'flat'; + const COOKIES_ARRAY = 'array'; + + const DISPOSITION_ATTACHMENT = 'attachment'; + const DISPOSITION_INLINE = 'inline'; + + protected $computedCacheControl = []; + protected $cookies = []; + protected $headerNames = []; + + public function __construct(array $headers = []) + { + parent::__construct($headers); + + if (!isset($this->headers['cache-control'])) { + $this->set('Cache-Control', ''); + } + + /* RFC2616 - 14.18 says all Responses need to have a Date */ + if (!isset($this->headers['date'])) { + $this->initDate(); + } + } + + /** + * Returns the headers, with original capitalizations. + * + * @return array An array of headers + */ + public function allPreserveCase() + { + $headers = []; + foreach ($this->all() as $name => $value) { + $headers[$this->headerNames[$name] ?? $name] = $value; + } + + return $headers; + } + + public function allPreserveCaseWithoutCookies() + { + $headers = $this->allPreserveCase(); + if (isset($this->headerNames['set-cookie'])) { + unset($headers[$this->headerNames['set-cookie']]); + } + + return $headers; + } + + /** + * {@inheritdoc} + */ + public function replace(array $headers = []) + { + $this->headerNames = []; + + parent::replace($headers); + + if (!isset($this->headers['cache-control'])) { + $this->set('Cache-Control', ''); + } + + if (!isset($this->headers['date'])) { + $this->initDate(); + } + } + + /** + * {@inheritdoc} + */ + public function all(string $key = null) + { + $headers = parent::all(); + + if (null !== $key) { + $key = strtr($key, self::UPPER, self::LOWER); + + return 'set-cookie' !== $key ? $headers[$key] ?? [] : array_map('strval', $this->getCookies()); + } + + foreach ($this->getCookies() as $cookie) { + $headers['set-cookie'][] = (string) $cookie; + } + + return $headers; + } + + /** + * {@inheritdoc} + */ + public function set(string $key, $values, bool $replace = true) + { + $uniqueKey = strtr($key, self::UPPER, self::LOWER); + + if ('set-cookie' === $uniqueKey) { + if ($replace) { + $this->cookies = []; + } + foreach ((array) $values as $cookie) { + $this->setCookie(Cookie::fromString($cookie)); + } + $this->headerNames[$uniqueKey] = $key; + + return; + } + + $this->headerNames[$uniqueKey] = $key; + + parent::set($key, $values, $replace); + + // ensure the cache-control header has sensible defaults + if (\in_array($uniqueKey, ['cache-control', 'etag', 'last-modified', 'expires'], true) && '' !== $computed = $this->computeCacheControlValue()) { + $this->headers['cache-control'] = [$computed]; + $this->headerNames['cache-control'] = 'Cache-Control'; + $this->computedCacheControl = $this->parseCacheControl($computed); + } + } + + /** + * {@inheritdoc} + */ + public function remove(string $key) + { + $uniqueKey = strtr($key, self::UPPER, self::LOWER); + unset($this->headerNames[$uniqueKey]); + + if ('set-cookie' === $uniqueKey) { + $this->cookies = []; + + return; + } + + parent::remove($key); + + if ('cache-control' === $uniqueKey) { + $this->computedCacheControl = []; + } + + if ('date' === $uniqueKey) { + $this->initDate(); + } + } + + /** + * {@inheritdoc} + */ + public function hasCacheControlDirective(string $key) + { + return \array_key_exists($key, $this->computedCacheControl); + } + + /** + * {@inheritdoc} + */ + public function getCacheControlDirective(string $key) + { + return \array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null; + } + + public function setCookie(Cookie $cookie) + { + $this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie; + $this->headerNames['set-cookie'] = 'Set-Cookie'; + } + + /** + * Removes a cookie from the array, but does not unset it in the browser. + */ + public function removeCookie(string $name, ?string $path = '/', string $domain = null) + { + if (null === $path) { + $path = '/'; + } + + unset($this->cookies[$domain][$path][$name]); + + if (empty($this->cookies[$domain][$path])) { + unset($this->cookies[$domain][$path]); + + if (empty($this->cookies[$domain])) { + unset($this->cookies[$domain]); + } + } + + if (empty($this->cookies)) { + unset($this->headerNames['set-cookie']); + } + } + + /** + * Returns an array with all cookies. + * + * @return Cookie[] + * + * @throws \InvalidArgumentException When the $format is invalid + */ + public function getCookies(string $format = self::COOKIES_FLAT) + { + if (!\in_array($format, [self::COOKIES_FLAT, self::COOKIES_ARRAY])) { + throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', [self::COOKIES_FLAT, self::COOKIES_ARRAY]))); + } + + if (self::COOKIES_ARRAY === $format) { + return $this->cookies; + } + + $flattenedCookies = []; + foreach ($this->cookies as $path) { + foreach ($path as $cookies) { + foreach ($cookies as $cookie) { + $flattenedCookies[] = $cookie; + } + } + } + + return $flattenedCookies; + } + + /** + * Clears a cookie in the browser. + */ + public function clearCookie(string $name, ?string $path = '/', string $domain = null, bool $secure = false, bool $httpOnly = true) + { + $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, null)); + } + + /** + * @see HeaderUtils::makeDisposition() + */ + public function makeDisposition(string $disposition, string $filename, string $filenameFallback = '') + { + return HeaderUtils::makeDisposition($disposition, $filename, $filenameFallback); + } + + /** + * Returns the calculated value of the cache-control header. + * + * This considers several other headers and calculates or modifies the + * cache-control header to a sensible, conservative value. + * + * @return string + */ + protected function computeCacheControlValue() + { + if (!$this->cacheControl) { + if ($this->has('Last-Modified') || $this->has('Expires')) { + return 'private, must-revalidate'; // allows for heuristic expiration (RFC 7234 Section 4.2.2) in the case of "Last-Modified" + } + + // conservative by default + return 'no-cache, private'; + } + + $header = $this->getCacheControlHeader(); + if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) { + return $header; + } + + // public if s-maxage is defined, private otherwise + if (!isset($this->cacheControl['s-maxage'])) { + return $header.', private'; + } + + return $header; + } + + private function initDate(): void + { + $now = \DateTime::createFromFormat('U', time()); + $now->setTimezone(new \DateTimeZone('UTC')); + $this->set('Date', $now->format('D, d M Y H:i:s').' GMT'); + } +} diff --git a/vendor/symfony/http-foundation/ServerBag.php b/vendor/symfony/http-foundation/ServerBag.php new file mode 100644 index 0000000..02c7091 --- /dev/null +++ b/vendor/symfony/http-foundation/ServerBag.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * ServerBag is a container for HTTP headers from the $_SERVER variable. + * + * @author Fabien Potencier + * @author Bulat Shakirzyanov + * @author Robert Kiss + */ +class ServerBag extends ParameterBag +{ + /** + * Gets the HTTP headers. + * + * @return array + */ + public function getHeaders() + { + $headers = []; + foreach ($this->parameters as $key => $value) { + if (0 === strpos($key, 'HTTP_')) { + $headers[substr($key, 5)] = $value; + } elseif (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) { + $headers[$key] = $value; + } + } + + if (isset($this->parameters['PHP_AUTH_USER'])) { + $headers['PHP_AUTH_USER'] = $this->parameters['PHP_AUTH_USER']; + $headers['PHP_AUTH_PW'] = isset($this->parameters['PHP_AUTH_PW']) ? $this->parameters['PHP_AUTH_PW'] : ''; + } else { + /* + * php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default + * For this workaround to work, add these lines to your .htaccess file: + * RewriteCond %{HTTP:Authorization} .+ + * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] + * + * A sample .htaccess file: + * RewriteEngine On + * RewriteCond %{HTTP:Authorization} .+ + * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] + * RewriteCond %{REQUEST_FILENAME} !-f + * RewriteRule ^(.*)$ app.php [QSA,L] + */ + + $authorizationHeader = null; + if (isset($this->parameters['HTTP_AUTHORIZATION'])) { + $authorizationHeader = $this->parameters['HTTP_AUTHORIZATION']; + } elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) { + $authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION']; + } + + if (null !== $authorizationHeader) { + if (0 === stripos($authorizationHeader, 'basic ')) { + // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic + $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)), 2); + if (2 == \count($exploded)) { + list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded; + } + } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest '))) { + // In some circumstances PHP_AUTH_DIGEST needs to be set + $headers['PHP_AUTH_DIGEST'] = $authorizationHeader; + $this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader; + } elseif (0 === stripos($authorizationHeader, 'bearer ')) { + /* + * XXX: Since there is no PHP_AUTH_BEARER in PHP predefined variables, + * I'll just set $headers['AUTHORIZATION'] here. + * https://php.net/reserved.variables.server + */ + $headers['AUTHORIZATION'] = $authorizationHeader; + } + } + } + + if (isset($headers['AUTHORIZATION'])) { + return $headers; + } + + // PHP_AUTH_USER/PHP_AUTH_PW + if (isset($headers['PHP_AUTH_USER'])) { + $headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.$headers['PHP_AUTH_PW']); + } elseif (isset($headers['PHP_AUTH_DIGEST'])) { + $headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST']; + } + + return $headers; + } +} diff --git a/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php b/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php new file mode 100644 index 0000000..aad6b61 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php @@ -0,0 +1,148 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Attribute; + +/** + * This class relates to session attribute storage. + */ +class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Countable +{ + private $name = 'attributes'; + private $storageKey; + + protected $attributes = []; + + /** + * @param string $storageKey The key used to store attributes in the session + */ + public function __construct(string $storageKey = '_sf2_attributes') + { + $this->storageKey = $storageKey; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + public function setName(string $name) + { + $this->name = $name; + } + + /** + * {@inheritdoc} + */ + public function initialize(array &$attributes) + { + $this->attributes = &$attributes; + } + + /** + * {@inheritdoc} + */ + public function getStorageKey() + { + return $this->storageKey; + } + + /** + * {@inheritdoc} + */ + public function has(string $name) + { + return \array_key_exists($name, $this->attributes); + } + + /** + * {@inheritdoc} + */ + public function get(string $name, $default = null) + { + return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; + } + + /** + * {@inheritdoc} + */ + public function set(string $name, $value) + { + $this->attributes[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function all() + { + return $this->attributes; + } + + /** + * {@inheritdoc} + */ + public function replace(array $attributes) + { + $this->attributes = []; + foreach ($attributes as $key => $value) { + $this->set($key, $value); + } + } + + /** + * {@inheritdoc} + */ + public function remove(string $name) + { + $retval = null; + if (\array_key_exists($name, $this->attributes)) { + $retval = $this->attributes[$name]; + unset($this->attributes[$name]); + } + + return $retval; + } + + /** + * {@inheritdoc} + */ + public function clear() + { + $return = $this->attributes; + $this->attributes = []; + + return $return; + } + + /** + * Returns an iterator for attributes. + * + * @return \ArrayIterator An \ArrayIterator instance + */ + public function getIterator() + { + return new \ArrayIterator($this->attributes); + } + + /** + * Returns the number of attributes. + * + * @return int The number of attributes + */ + public function count() + { + return \count($this->attributes); + } +} diff --git a/vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php b/vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php new file mode 100644 index 0000000..7017b71 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Attribute; + +use Symfony\Component\HttpFoundation\Session\SessionBagInterface; + +/** + * Attributes store. + * + * @author Drak + */ +interface AttributeBagInterface extends SessionBagInterface +{ + /** + * Checks if an attribute is defined. + * + * @return bool true if the attribute is defined, false otherwise + */ + public function has(string $name); + + /** + * Returns an attribute. + * + * @param mixed $default The default value if not found + * + * @return mixed + */ + public function get(string $name, $default = null); + + /** + * Sets an attribute. + * + * @param mixed $value + */ + public function set(string $name, $value); + + /** + * Returns attributes. + * + * @return array + */ + public function all(); + + public function replace(array $attributes); + + /** + * Removes an attribute. + * + * @return mixed The removed value or null when it does not exist + */ + public function remove(string $name); +} diff --git a/vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php b/vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php new file mode 100644 index 0000000..7e752dd --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php @@ -0,0 +1,157 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Attribute; + +/** + * This class provides structured storage of session attributes using + * a name spacing character in the key. + * + * @author Drak + */ +class NamespacedAttributeBag extends AttributeBag +{ + private $namespaceCharacter; + + /** + * @param string $storageKey Session storage key + * @param string $namespaceCharacter Namespace character to use in keys + */ + public function __construct(string $storageKey = '_sf2_attributes', string $namespaceCharacter = '/') + { + $this->namespaceCharacter = $namespaceCharacter; + parent::__construct($storageKey); + } + + /** + * {@inheritdoc} + */ + public function has(string $name) + { + // reference mismatch: if fixed, re-introduced in array_key_exists; keep as it is + $attributes = $this->resolveAttributePath($name); + $name = $this->resolveKey($name); + + if (null === $attributes) { + return false; + } + + return \array_key_exists($name, $attributes); + } + + /** + * {@inheritdoc} + */ + public function get(string $name, $default = null) + { + // reference mismatch: if fixed, re-introduced in array_key_exists; keep as it is + $attributes = $this->resolveAttributePath($name); + $name = $this->resolveKey($name); + + if (null === $attributes) { + return $default; + } + + return \array_key_exists($name, $attributes) ? $attributes[$name] : $default; + } + + /** + * {@inheritdoc} + */ + public function set(string $name, $value) + { + $attributes = &$this->resolveAttributePath($name, true); + $name = $this->resolveKey($name); + $attributes[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function remove(string $name) + { + $retval = null; + $attributes = &$this->resolveAttributePath($name); + $name = $this->resolveKey($name); + if (null !== $attributes && \array_key_exists($name, $attributes)) { + $retval = $attributes[$name]; + unset($attributes[$name]); + } + + return $retval; + } + + /** + * Resolves a path in attributes property and returns it as a reference. + * + * This method allows structured namespacing of session attributes. + * + * @param string $name Key name + * @param bool $writeContext Write context, default false + * + * @return array|null + */ + protected function &resolveAttributePath(string $name, bool $writeContext = false) + { + $array = &$this->attributes; + $name = (0 === strpos($name, $this->namespaceCharacter)) ? substr($name, 1) : $name; + + // Check if there is anything to do, else return + if (!$name) { + return $array; + } + + $parts = explode($this->namespaceCharacter, $name); + if (\count($parts) < 2) { + if (!$writeContext) { + return $array; + } + + $array[$parts[0]] = []; + + return $array; + } + + unset($parts[\count($parts) - 1]); + + foreach ($parts as $part) { + if (null !== $array && !\array_key_exists($part, $array)) { + if (!$writeContext) { + $null = null; + + return $null; + } + + $array[$part] = []; + } + + $array = &$array[$part]; + } + + return $array; + } + + /** + * Resolves the key from the name. + * + * This is the last part in a dot separated string. + * + * @return string + */ + protected function resolveKey(string $name) + { + if (false !== $pos = strrpos($name, $this->namespaceCharacter)) { + $name = substr($name, $pos + 1); + } + + return $name; + } +} diff --git a/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php b/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php new file mode 100644 index 0000000..2707d64 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php @@ -0,0 +1,161 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Flash; + +/** + * AutoExpireFlashBag flash message container. + * + * @author Drak + */ +class AutoExpireFlashBag implements FlashBagInterface +{ + private $name = 'flashes'; + private $flashes = ['display' => [], 'new' => []]; + private $storageKey; + + /** + * @param string $storageKey The key used to store flashes in the session + */ + public function __construct(string $storageKey = '_symfony_flashes') + { + $this->storageKey = $storageKey; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + public function setName(string $name) + { + $this->name = $name; + } + + /** + * {@inheritdoc} + */ + public function initialize(array &$flashes) + { + $this->flashes = &$flashes; + + // The logic: messages from the last request will be stored in new, so we move them to previous + // This request we will show what is in 'display'. What is placed into 'new' this time round will + // be moved to display next time round. + $this->flashes['display'] = \array_key_exists('new', $this->flashes) ? $this->flashes['new'] : []; + $this->flashes['new'] = []; + } + + /** + * {@inheritdoc} + */ + public function add(string $type, $message) + { + $this->flashes['new'][$type][] = $message; + } + + /** + * {@inheritdoc} + */ + public function peek(string $type, array $default = []) + { + return $this->has($type) ? $this->flashes['display'][$type] : $default; + } + + /** + * {@inheritdoc} + */ + public function peekAll() + { + return \array_key_exists('display', $this->flashes) ? (array) $this->flashes['display'] : []; + } + + /** + * {@inheritdoc} + */ + public function get(string $type, array $default = []) + { + $return = $default; + + if (!$this->has($type)) { + return $return; + } + + if (isset($this->flashes['display'][$type])) { + $return = $this->flashes['display'][$type]; + unset($this->flashes['display'][$type]); + } + + return $return; + } + + /** + * {@inheritdoc} + */ + public function all() + { + $return = $this->flashes['display']; + $this->flashes['display'] = []; + + return $return; + } + + /** + * {@inheritdoc} + */ + public function setAll(array $messages) + { + $this->flashes['new'] = $messages; + } + + /** + * {@inheritdoc} + */ + public function set(string $type, $messages) + { + $this->flashes['new'][$type] = (array) $messages; + } + + /** + * {@inheritdoc} + */ + public function has(string $type) + { + return \array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type]; + } + + /** + * {@inheritdoc} + */ + public function keys() + { + return array_keys($this->flashes['display']); + } + + /** + * {@inheritdoc} + */ + public function getStorageKey() + { + return $this->storageKey; + } + + /** + * {@inheritdoc} + */ + public function clear() + { + return $this->all(); + } +} diff --git a/vendor/symfony/http-foundation/Session/Flash/FlashBag.php b/vendor/symfony/http-foundation/Session/Flash/FlashBag.php new file mode 100644 index 0000000..88df750 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Flash/FlashBag.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Flash; + +/** + * FlashBag flash message container. + * + * @author Drak + */ +class FlashBag implements FlashBagInterface +{ + private $name = 'flashes'; + private $flashes = []; + private $storageKey; + + /** + * @param string $storageKey The key used to store flashes in the session + */ + public function __construct(string $storageKey = '_symfony_flashes') + { + $this->storageKey = $storageKey; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + public function setName(string $name) + { + $this->name = $name; + } + + /** + * {@inheritdoc} + */ + public function initialize(array &$flashes) + { + $this->flashes = &$flashes; + } + + /** + * {@inheritdoc} + */ + public function add(string $type, $message) + { + $this->flashes[$type][] = $message; + } + + /** + * {@inheritdoc} + */ + public function peek(string $type, array $default = []) + { + return $this->has($type) ? $this->flashes[$type] : $default; + } + + /** + * {@inheritdoc} + */ + public function peekAll() + { + return $this->flashes; + } + + /** + * {@inheritdoc} + */ + public function get(string $type, array $default = []) + { + if (!$this->has($type)) { + return $default; + } + + $return = $this->flashes[$type]; + + unset($this->flashes[$type]); + + return $return; + } + + /** + * {@inheritdoc} + */ + public function all() + { + $return = $this->peekAll(); + $this->flashes = []; + + return $return; + } + + /** + * {@inheritdoc} + */ + public function set(string $type, $messages) + { + $this->flashes[$type] = (array) $messages; + } + + /** + * {@inheritdoc} + */ + public function setAll(array $messages) + { + $this->flashes = $messages; + } + + /** + * {@inheritdoc} + */ + public function has(string $type) + { + return \array_key_exists($type, $this->flashes) && $this->flashes[$type]; + } + + /** + * {@inheritdoc} + */ + public function keys() + { + return array_keys($this->flashes); + } + + /** + * {@inheritdoc} + */ + public function getStorageKey() + { + return $this->storageKey; + } + + /** + * {@inheritdoc} + */ + public function clear() + { + return $this->all(); + } +} diff --git a/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php b/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php new file mode 100644 index 0000000..8713e71 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Flash; + +use Symfony\Component\HttpFoundation\Session\SessionBagInterface; + +/** + * FlashBagInterface. + * + * @author Drak + */ +interface FlashBagInterface extends SessionBagInterface +{ + /** + * Adds a flash message for the given type. + * + * @param mixed $message + */ + public function add(string $type, $message); + + /** + * Registers one or more messages for a given type. + * + * @param string|array $messages + */ + public function set(string $type, $messages); + + /** + * Gets flash messages for a given type. + * + * @param string $type Message category type + * @param array $default Default value if $type does not exist + * + * @return array + */ + public function peek(string $type, array $default = []); + + /** + * Gets all flash messages. + * + * @return array + */ + public function peekAll(); + + /** + * Gets and clears flash from the stack. + * + * @param array $default Default value if $type does not exist + * + * @return array + */ + public function get(string $type, array $default = []); + + /** + * Gets and clears flashes from the stack. + * + * @return array + */ + public function all(); + + /** + * Sets all flash messages. + */ + public function setAll(array $messages); + + /** + * Has flash messages for a given type? + * + * @return bool + */ + public function has(string $type); + + /** + * Returns a list of all defined types. + * + * @return array + */ + public function keys(); +} diff --git a/vendor/symfony/http-foundation/Session/Session.php b/vendor/symfony/http-foundation/Session/Session.php new file mode 100644 index 0000000..89071b8 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Session.php @@ -0,0 +1,268 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session; + +use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; +use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; +use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; +use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; +use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; + +/** + * @author Fabien Potencier + * @author Drak + */ +class Session implements SessionInterface, \IteratorAggregate, \Countable +{ + protected $storage; + + private $flashName; + private $attributeName; + private $data = []; + private $usageIndex = 0; + + public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null) + { + $this->storage = $storage ?: new NativeSessionStorage(); + + $attributes = $attributes ?: new AttributeBag(); + $this->attributeName = $attributes->getName(); + $this->registerBag($attributes); + + $flashes = $flashes ?: new FlashBag(); + $this->flashName = $flashes->getName(); + $this->registerBag($flashes); + } + + /** + * {@inheritdoc} + */ + public function start() + { + return $this->storage->start(); + } + + /** + * {@inheritdoc} + */ + public function has(string $name) + { + return $this->getAttributeBag()->has($name); + } + + /** + * {@inheritdoc} + */ + public function get(string $name, $default = null) + { + return $this->getAttributeBag()->get($name, $default); + } + + /** + * {@inheritdoc} + */ + public function set(string $name, $value) + { + $this->getAttributeBag()->set($name, $value); + } + + /** + * {@inheritdoc} + */ + public function all() + { + return $this->getAttributeBag()->all(); + } + + /** + * {@inheritdoc} + */ + public function replace(array $attributes) + { + $this->getAttributeBag()->replace($attributes); + } + + /** + * {@inheritdoc} + */ + public function remove(string $name) + { + return $this->getAttributeBag()->remove($name); + } + + /** + * {@inheritdoc} + */ + public function clear() + { + $this->getAttributeBag()->clear(); + } + + /** + * {@inheritdoc} + */ + public function isStarted() + { + return $this->storage->isStarted(); + } + + /** + * Returns an iterator for attributes. + * + * @return \ArrayIterator An \ArrayIterator instance + */ + public function getIterator() + { + return new \ArrayIterator($this->getAttributeBag()->all()); + } + + /** + * Returns the number of attributes. + * + * @return int + */ + public function count() + { + return \count($this->getAttributeBag()->all()); + } + + public function &getUsageIndex(): int + { + return $this->usageIndex; + } + + /** + * @internal + */ + public function isEmpty(): bool + { + if ($this->isStarted()) { + ++$this->usageIndex; + } + foreach ($this->data as &$data) { + if (!empty($data)) { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function invalidate(int $lifetime = null) + { + $this->storage->clear(); + + return $this->migrate(true, $lifetime); + } + + /** + * {@inheritdoc} + */ + public function migrate(bool $destroy = false, int $lifetime = null) + { + return $this->storage->regenerate($destroy, $lifetime); + } + + /** + * {@inheritdoc} + */ + public function save() + { + $this->storage->save(); + } + + /** + * {@inheritdoc} + */ + public function getId() + { + return $this->storage->getId(); + } + + /** + * {@inheritdoc} + */ + public function setId(string $id) + { + if ($this->storage->getId() !== $id) { + $this->storage->setId($id); + } + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->storage->getName(); + } + + /** + * {@inheritdoc} + */ + public function setName(string $name) + { + $this->storage->setName($name); + } + + /** + * {@inheritdoc} + */ + public function getMetadataBag() + { + ++$this->usageIndex; + + return $this->storage->getMetadataBag(); + } + + /** + * {@inheritdoc} + */ + public function registerBag(SessionBagInterface $bag) + { + $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->usageIndex)); + } + + /** + * {@inheritdoc} + */ + public function getBag(string $name) + { + $bag = $this->storage->getBag($name); + + return method_exists($bag, 'getBag') ? $bag->getBag() : $bag; + } + + /** + * Gets the flashbag interface. + * + * @return FlashBagInterface + */ + public function getFlashBag() + { + return $this->getBag($this->flashName); + } + + /** + * Gets the attributebag interface. + * + * Note that this method was added to help with IDE autocompletion. + */ + private function getAttributeBag(): AttributeBagInterface + { + return $this->getBag($this->attributeName); + } +} diff --git a/vendor/symfony/http-foundation/Session/SessionBagInterface.php b/vendor/symfony/http-foundation/Session/SessionBagInterface.php new file mode 100644 index 0000000..8e37d06 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/SessionBagInterface.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session; + +/** + * Session Bag store. + * + * @author Drak + */ +interface SessionBagInterface +{ + /** + * Gets this bag's name. + * + * @return string + */ + public function getName(); + + /** + * Initializes the Bag. + */ + public function initialize(array &$array); + + /** + * Gets the storage key for this bag. + * + * @return string + */ + public function getStorageKey(); + + /** + * Clears out data from bag. + * + * @return mixed Whatever data was contained + */ + public function clear(); +} diff --git a/vendor/symfony/http-foundation/Session/SessionBagProxy.php b/vendor/symfony/http-foundation/Session/SessionBagProxy.php new file mode 100644 index 0000000..0ae8231 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/SessionBagProxy.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session; + +/** + * @author Nicolas Grekas + * + * @internal + */ +final class SessionBagProxy implements SessionBagInterface +{ + private $bag; + private $data; + private $usageIndex; + + public function __construct(SessionBagInterface $bag, array &$data, ?int &$usageIndex) + { + $this->bag = $bag; + $this->data = &$data; + $this->usageIndex = &$usageIndex; + } + + public function getBag(): SessionBagInterface + { + ++$this->usageIndex; + + return $this->bag; + } + + public function isEmpty(): bool + { + if (!isset($this->data[$this->bag->getStorageKey()])) { + return true; + } + ++$this->usageIndex; + + return empty($this->data[$this->bag->getStorageKey()]); + } + + /** + * {@inheritdoc} + */ + public function getName(): string + { + return $this->bag->getName(); + } + + /** + * {@inheritdoc} + */ + public function initialize(array &$array): void + { + ++$this->usageIndex; + $this->data[$this->bag->getStorageKey()] = &$array; + + $this->bag->initialize($array); + } + + /** + * {@inheritdoc} + */ + public function getStorageKey(): string + { + return $this->bag->getStorageKey(); + } + + /** + * {@inheritdoc} + */ + public function clear() + { + return $this->bag->clear(); + } +} diff --git a/vendor/symfony/http-foundation/Session/SessionInterface.php b/vendor/symfony/http-foundation/Session/SessionInterface.php new file mode 100644 index 0000000..b2f09fd --- /dev/null +++ b/vendor/symfony/http-foundation/Session/SessionInterface.php @@ -0,0 +1,166 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session; + +use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; + +/** + * Interface for the session. + * + * @author Drak + */ +interface SessionInterface +{ + /** + * Starts the session storage. + * + * @return bool + * + * @throws \RuntimeException if session fails to start + */ + public function start(); + + /** + * Returns the session ID. + * + * @return string + */ + public function getId(); + + /** + * Sets the session ID. + */ + public function setId(string $id); + + /** + * Returns the session name. + * + * @return string + */ + public function getName(); + + /** + * Sets the session name. + */ + public function setName(string $name); + + /** + * Invalidates the current session. + * + * Clears all session attributes and flashes and regenerates the + * session and deletes the old session from persistence. + * + * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value + * will leave the system settings unchanged, 0 sets the cookie + * to expire with browser session. Time is in seconds, and is + * not a Unix timestamp. + * + * @return bool + */ + public function invalidate(int $lifetime = null); + + /** + * Migrates the current session to a new session id while maintaining all + * session attributes. + * + * @param bool $destroy Whether to delete the old session or leave it to garbage collection + * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value + * will leave the system settings unchanged, 0 sets the cookie + * to expire with browser session. Time is in seconds, and is + * not a Unix timestamp. + * + * @return bool + */ + public function migrate(bool $destroy = false, int $lifetime = null); + + /** + * Force the session to be saved and closed. + * + * This method is generally not required for real sessions as + * the session will be automatically saved at the end of + * code execution. + */ + public function save(); + + /** + * Checks if an attribute is defined. + * + * @return bool + */ + public function has(string $name); + + /** + * Returns an attribute. + * + * @param mixed $default The default value if not found + * + * @return mixed + */ + public function get(string $name, $default = null); + + /** + * Sets an attribute. + * + * @param mixed $value + */ + public function set(string $name, $value); + + /** + * Returns attributes. + * + * @return array + */ + public function all(); + + /** + * Sets attributes. + */ + public function replace(array $attributes); + + /** + * Removes an attribute. + * + * @return mixed The removed value or null when it does not exist + */ + public function remove(string $name); + + /** + * Clears all attributes. + */ + public function clear(); + + /** + * Checks if the session was started. + * + * @return bool + */ + public function isStarted(); + + /** + * Registers a SessionBagInterface with the session. + */ + public function registerBag(SessionBagInterface $bag); + + /** + * Gets a bag instance by name. + * + * @return SessionBagInterface + */ + public function getBag(string $name); + + /** + * Gets session meta. + * + * @return MetadataBag + */ + public function getMetadataBag(); +} diff --git a/vendor/symfony/http-foundation/Session/SessionUtils.php b/vendor/symfony/http-foundation/Session/SessionUtils.php new file mode 100644 index 0000000..b5bce4a --- /dev/null +++ b/vendor/symfony/http-foundation/Session/SessionUtils.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session; + +/** + * Session utility functions. + * + * @author Nicolas Grekas + * @author Rémon van de Kamp + * + * @internal + */ +final class SessionUtils +{ + /** + * Finds the session header amongst the headers that are to be sent, removes it, and returns + * it so the caller can process it further. + */ + public static function popSessionCookie(string $sessionName, string $sessionId): ?string + { + $sessionCookie = null; + $sessionCookiePrefix = sprintf(' %s=', urlencode($sessionName)); + $sessionCookieWithId = sprintf('%s%s;', $sessionCookiePrefix, urlencode($sessionId)); + $otherCookies = []; + foreach (headers_list() as $h) { + if (0 !== stripos($h, 'Set-Cookie:')) { + continue; + } + if (11 === strpos($h, $sessionCookiePrefix, 11)) { + $sessionCookie = $h; + + if (11 !== strpos($h, $sessionCookieWithId, 11)) { + $otherCookies[] = $h; + } + } else { + $otherCookies[] = $h; + } + } + if (null === $sessionCookie) { + return null; + } + + header_remove('Set-Cookie'); + foreach ($otherCookies as $h) { + header($h, false); + } + + return $sessionCookie; + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php new file mode 100644 index 0000000..0618035 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +use Symfony\Component\HttpFoundation\Session\SessionUtils; + +/** + * This abstract session handler provides a generic implementation + * of the PHP 7.0 SessionUpdateTimestampHandlerInterface, + * enabling strict and lazy session handling. + * + * @author Nicolas Grekas + */ +abstract class AbstractSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface +{ + private $sessionName; + private $prefetchId; + private $prefetchData; + private $newSessionId; + private $igbinaryEmptyData; + + /** + * @return bool + */ + public function open($savePath, $sessionName) + { + $this->sessionName = $sessionName; + if (!headers_sent() && !ini_get('session.cache_limiter') && '0' !== ini_get('session.cache_limiter')) { + header(sprintf('Cache-Control: max-age=%d, private, must-revalidate', 60 * (int) ini_get('session.cache_expire'))); + } + + return true; + } + + /** + * @return string + */ + abstract protected function doRead(string $sessionId); + + /** + * @return bool + */ + abstract protected function doWrite(string $sessionId, string $data); + + /** + * @return bool + */ + abstract protected function doDestroy(string $sessionId); + + /** + * @return bool + */ + public function validateId($sessionId) + { + $this->prefetchData = $this->read($sessionId); + $this->prefetchId = $sessionId; + + return '' !== $this->prefetchData; + } + + /** + * @return string + */ + public function read($sessionId) + { + if (null !== $this->prefetchId) { + $prefetchId = $this->prefetchId; + $prefetchData = $this->prefetchData; + $this->prefetchId = $this->prefetchData = null; + + if ($prefetchId === $sessionId || '' === $prefetchData) { + $this->newSessionId = '' === $prefetchData ? $sessionId : null; + + return $prefetchData; + } + } + + $data = $this->doRead($sessionId); + $this->newSessionId = '' === $data ? $sessionId : null; + + return $data; + } + + /** + * @return bool + */ + public function write($sessionId, $data) + { + if (null === $this->igbinaryEmptyData) { + // see https://github.com/igbinary/igbinary/issues/146 + $this->igbinaryEmptyData = \function_exists('igbinary_serialize') ? igbinary_serialize([]) : ''; + } + if ('' === $data || $this->igbinaryEmptyData === $data) { + return $this->destroy($sessionId); + } + $this->newSessionId = null; + + return $this->doWrite($sessionId, $data); + } + + /** + * @return bool + */ + public function destroy($sessionId) + { + if (!headers_sent() && filter_var(ini_get('session.use_cookies'), FILTER_VALIDATE_BOOLEAN)) { + if (!$this->sessionName) { + throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', \get_class($this))); + } + $cookie = SessionUtils::popSessionCookie($this->sessionName, $sessionId); + + /* + * We send an invalidation Set-Cookie header (zero lifetime) + * when either the session was started or a cookie with + * the session name was sent by the client (in which case + * we know it's invalid as a valid session cookie would've + * started the session). + */ + if (null === $cookie || isset($_COOKIE[$this->sessionName])) { + if (\PHP_VERSION_ID < 70300) { + setcookie($this->sessionName, '', 0, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), filter_var(ini_get('session.cookie_secure'), FILTER_VALIDATE_BOOLEAN), filter_var(ini_get('session.cookie_httponly'), FILTER_VALIDATE_BOOLEAN)); + } else { + $params = session_get_cookie_params(); + unset($params['lifetime']); + setcookie($this->sessionName, '', $params); + } + } + } + + return $this->newSessionId === $sessionId || $this->doDestroy($sessionId); + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php new file mode 100644 index 0000000..8896964 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +/** + * Memcached based session storage handler based on the Memcached class + * provided by the PHP memcached extension. + * + * @see https://php.net/memcached + * + * @author Drak + */ +class MemcachedSessionHandler extends AbstractSessionHandler +{ + private $memcached; + + /** + * @var int Time to live in seconds + */ + private $ttl; + + /** + * @var string Key prefix for shared environments + */ + private $prefix; + + /** + * Constructor. + * + * List of available options: + * * prefix: The prefix to use for the memcached keys in order to avoid collision + * * expiretime: The time to live in seconds. + * + * @throws \InvalidArgumentException When unsupported options are passed + */ + public function __construct(\Memcached $memcached, array $options = []) + { + $this->memcached = $memcached; + + if ($diff = array_diff(array_keys($options), ['prefix', 'expiretime'])) { + throw new \InvalidArgumentException(sprintf('The following options are not supported "%s"', implode(', ', $diff))); + } + + $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400; + $this->prefix = isset($options['prefix']) ? $options['prefix'] : 'sf2s'; + } + + /** + * @return bool + */ + public function close() + { + return $this->memcached->quit(); + } + + /** + * {@inheritdoc} + */ + protected function doRead(string $sessionId) + { + return $this->memcached->get($this->prefix.$sessionId) ?: ''; + } + + /** + * @return bool + */ + public function updateTimestamp($sessionId, $data) + { + $this->memcached->touch($this->prefix.$sessionId, time() + $this->ttl); + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $sessionId, string $data) + { + return $this->memcached->set($this->prefix.$sessionId, $data, time() + $this->ttl); + } + + /** + * {@inheritdoc} + */ + protected function doDestroy(string $sessionId) + { + $result = $this->memcached->delete($this->prefix.$sessionId); + + return $result || \Memcached::RES_NOTFOUND == $this->memcached->getResultCode(); + } + + /** + * @return bool + */ + public function gc($maxlifetime) + { + // not required here because memcached will auto expire the records anyhow. + return true; + } + + /** + * Return a Memcached instance. + * + * @return \Memcached + */ + protected function getMemcached() + { + return $this->memcached; + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php new file mode 100644 index 0000000..c6b16d1 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php @@ -0,0 +1,124 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +/** + * Migrating session handler for migrating from one handler to another. It reads + * from the current handler and writes both the current and new ones. + * + * It ignores errors from the new handler. + * + * @author Ross Motley + * @author Oliver Radwell + */ +class MigratingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface +{ + private $currentHandler; + private $writeOnlyHandler; + + public function __construct(\SessionHandlerInterface $currentHandler, \SessionHandlerInterface $writeOnlyHandler) + { + if (!$currentHandler instanceof \SessionUpdateTimestampHandlerInterface) { + $currentHandler = new StrictSessionHandler($currentHandler); + } + if (!$writeOnlyHandler instanceof \SessionUpdateTimestampHandlerInterface) { + $writeOnlyHandler = new StrictSessionHandler($writeOnlyHandler); + } + + $this->currentHandler = $currentHandler; + $this->writeOnlyHandler = $writeOnlyHandler; + } + + /** + * @return bool + */ + public function close() + { + $result = $this->currentHandler->close(); + $this->writeOnlyHandler->close(); + + return $result; + } + + /** + * @return bool + */ + public function destroy($sessionId) + { + $result = $this->currentHandler->destroy($sessionId); + $this->writeOnlyHandler->destroy($sessionId); + + return $result; + } + + /** + * @return bool + */ + public function gc($maxlifetime) + { + $result = $this->currentHandler->gc($maxlifetime); + $this->writeOnlyHandler->gc($maxlifetime); + + return $result; + } + + /** + * @return bool + */ + public function open($savePath, $sessionName) + { + $result = $this->currentHandler->open($savePath, $sessionName); + $this->writeOnlyHandler->open($savePath, $sessionName); + + return $result; + } + + /** + * @return string + */ + public function read($sessionId) + { + // No reading from new handler until switch-over + return $this->currentHandler->read($sessionId); + } + + /** + * @return bool + */ + public function write($sessionId, $sessionData) + { + $result = $this->currentHandler->write($sessionId, $sessionData); + $this->writeOnlyHandler->write($sessionId, $sessionData); + + return $result; + } + + /** + * @return bool + */ + public function validateId($sessionId) + { + // No reading from new handler until switch-over + return $this->currentHandler->validateId($sessionId); + } + + /** + * @return bool + */ + public function updateTimestamp($sessionId, $sessionData) + { + $result = $this->currentHandler->updateTimestamp($sessionId, $sessionData); + $this->writeOnlyHandler->updateTimestamp($sessionId, $sessionData); + + return $result; + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php new file mode 100644 index 0000000..a6889e4 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -0,0 +1,187 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +/** + * Session handler using the mongodb/mongodb package and MongoDB driver extension. + * + * @author Markus Bachmann + * + * @see https://packagist.org/packages/mongodb/mongodb + * @see https://php.net/mongodb + */ +class MongoDbSessionHandler extends AbstractSessionHandler +{ + private $mongo; + + /** + * @var \MongoDB\Collection + */ + private $collection; + + /** + * @var array + */ + private $options; + + /** + * Constructor. + * + * List of available options: + * * database: The name of the database [required] + * * collection: The name of the collection [required] + * * id_field: The field name for storing the session id [default: _id] + * * data_field: The field name for storing the session data [default: data] + * * time_field: The field name for storing the timestamp [default: time] + * * expiry_field: The field name for storing the expiry-timestamp [default: expires_at]. + * + * It is strongly recommended to put an index on the `expiry_field` for + * garbage-collection. Alternatively it's possible to automatically expire + * the sessions in the database as described below: + * + * A TTL collections can be used on MongoDB 2.2+ to cleanup expired sessions + * automatically. Such an index can for example look like this: + * + * db..ensureIndex( + * { "": 1 }, + * { "expireAfterSeconds": 0 } + * ) + * + * More details on: https://docs.mongodb.org/manual/tutorial/expire-data/ + * + * If you use such an index, you can drop `gc_probability` to 0 since + * no garbage-collection is required. + * + * @throws \InvalidArgumentException When "database" or "collection" not provided + */ + public function __construct(\MongoDB\Client $mongo, array $options) + { + if (!isset($options['database']) || !isset($options['collection'])) { + throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler'); + } + + $this->mongo = $mongo; + + $this->options = array_merge([ + 'id_field' => '_id', + 'data_field' => 'data', + 'time_field' => 'time', + 'expiry_field' => 'expires_at', + ], $options); + } + + /** + * @return bool + */ + public function close() + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function doDestroy(string $sessionId) + { + $this->getCollection()->deleteOne([ + $this->options['id_field'] => $sessionId, + ]); + + return true; + } + + /** + * @return bool + */ + public function gc($maxlifetime) + { + $this->getCollection()->deleteMany([ + $this->options['expiry_field'] => ['$lt' => new \MongoDB\BSON\UTCDateTime()], + ]); + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $sessionId, string $data) + { + $expiry = new \MongoDB\BSON\UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000); + + $fields = [ + $this->options['time_field'] => new \MongoDB\BSON\UTCDateTime(), + $this->options['expiry_field'] => $expiry, + $this->options['data_field'] => new \MongoDB\BSON\Binary($data, \MongoDB\BSON\Binary::TYPE_OLD_BINARY), + ]; + + $this->getCollection()->updateOne( + [$this->options['id_field'] => $sessionId], + ['$set' => $fields], + ['upsert' => true] + ); + + return true; + } + + /** + * @return bool + */ + public function updateTimestamp($sessionId, $data) + { + $expiry = new \MongoDB\BSON\UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000); + + $this->getCollection()->updateOne( + [$this->options['id_field'] => $sessionId], + ['$set' => [ + $this->options['time_field'] => new \MongoDB\BSON\UTCDateTime(), + $this->options['expiry_field'] => $expiry, + ]] + ); + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doRead(string $sessionId) + { + $dbData = $this->getCollection()->findOne([ + $this->options['id_field'] => $sessionId, + $this->options['expiry_field'] => ['$gte' => new \MongoDB\BSON\UTCDateTime()], + ]); + + if (null === $dbData) { + return ''; + } + + return $dbData[$this->options['data_field']]->getData(); + } + + private function getCollection(): \MongoDB\Collection + { + if (null === $this->collection) { + $this->collection = $this->mongo->selectCollection($this->options['database'], $this->options['collection']); + } + + return $this->collection; + } + + /** + * @return \MongoDB\Client + */ + protected function getMongo() + { + return $this->mongo; + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php new file mode 100644 index 0000000..bdfc9d8 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +/** + * Native session handler using PHP's built in file storage. + * + * @author Drak + */ +class NativeFileSessionHandler extends \SessionHandler +{ + /** + * @param string $savePath Path of directory to save session files + * Default null will leave setting as defined by PHP. + * '/path', 'N;/path', or 'N;octal-mode;/path + * + * @see https://php.net/session.configuration#ini.session.save-path for further details. + * + * @throws \InvalidArgumentException On invalid $savePath + * @throws \RuntimeException When failing to create the save directory + */ + public function __construct(string $savePath = null) + { + if (null === $savePath) { + $savePath = ini_get('session.save_path'); + } + + $baseDir = $savePath; + + if ($count = substr_count($savePath, ';')) { + if ($count > 2) { + throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'', $savePath)); + } + + // characters after last ';' are the path + $baseDir = ltrim(strrchr($savePath, ';'), ';'); + } + + if ($baseDir && !is_dir($baseDir) && !@mkdir($baseDir, 0777, true) && !is_dir($baseDir)) { + throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"', $baseDir)); + } + + ini_set('session.save_path', $savePath); + ini_set('session.save_handler', 'files'); + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php new file mode 100644 index 0000000..aa0e595 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +/** + * Can be used in unit testing or in a situations where persisted sessions are not desired. + * + * @author Drak + */ +class NullSessionHandler extends AbstractSessionHandler +{ + /** + * @return bool + */ + public function close() + { + return true; + } + + /** + * @return bool + */ + public function validateId($sessionId) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function doRead(string $sessionId) + { + return ''; + } + + /** + * @return bool + */ + public function updateTimestamp($sessionId, $data) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $sessionId, string $data) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function doDestroy(string $sessionId) + { + return true; + } + + /** + * @return bool + */ + public function gc($maxlifetime) + { + return true; + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php new file mode 100644 index 0000000..74412e0 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php @@ -0,0 +1,899 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +/** + * Session handler using a PDO connection to read and write data. + * + * It works with MySQL, PostgreSQL, Oracle, SQL Server and SQLite and implements + * different locking strategies to handle concurrent access to the same session. + * Locking is necessary to prevent loss of data due to race conditions and to keep + * the session data consistent between read() and write(). With locking, requests + * for the same session will wait until the other one finished writing. For this + * reason it's best practice to close a session as early as possible to improve + * concurrency. PHPs internal files session handler also implements locking. + * + * Attention: Since SQLite does not support row level locks but locks the whole database, + * it means only one session can be accessed at a time. Even different sessions would wait + * for another to finish. So saving session in SQLite should only be considered for + * development or prototypes. + * + * Session data is a binary string that can contain non-printable characters like the null byte. + * For this reason it must be saved in a binary column in the database like BLOB in MySQL. + * Saving it in a character column could corrupt the data. You can use createTable() + * to initialize a correctly defined table. + * + * @see https://php.net/sessionhandlerinterface + * + * @author Fabien Potencier + * @author Michael Williams + * @author Tobias Schultze + */ +class PdoSessionHandler extends AbstractSessionHandler +{ + /** + * No locking is done. This means sessions are prone to loss of data due to + * race conditions of concurrent requests to the same session. The last session + * write will win in this case. It might be useful when you implement your own + * logic to deal with this like an optimistic approach. + */ + const LOCK_NONE = 0; + + /** + * Creates an application-level lock on a session. The disadvantage is that the + * lock is not enforced by the database and thus other, unaware parts of the + * application could still concurrently modify the session. The advantage is it + * does not require a transaction. + * This mode is not available for SQLite and not yet implemented for oci and sqlsrv. + */ + const LOCK_ADVISORY = 1; + + /** + * Issues a real row lock. Since it uses a transaction between opening and + * closing a session, you have to be careful when you use same database connection + * that you also use for your application logic. This mode is the default because + * it's the only reliable solution across DBMSs. + */ + const LOCK_TRANSACTIONAL = 2; + + private const MAX_LIFETIME = 315576000; + + /** + * @var \PDO|null PDO instance or null when not connected yet + */ + private $pdo; + + /** + * @var string|false|null DSN string or null for session.save_path or false when lazy connection disabled + */ + private $dsn = false; + + /** + * @var string Database driver + */ + private $driver; + + /** + * @var string Table name + */ + private $table = 'sessions'; + + /** + * @var string Column for session id + */ + private $idCol = 'sess_id'; + + /** + * @var string Column for session data + */ + private $dataCol = 'sess_data'; + + /** + * @var string Column for lifetime + */ + private $lifetimeCol = 'sess_lifetime'; + + /** + * @var string Column for timestamp + */ + private $timeCol = 'sess_time'; + + /** + * @var string Username when lazy-connect + */ + private $username = ''; + + /** + * @var string Password when lazy-connect + */ + private $password = ''; + + /** + * @var array Connection options when lazy-connect + */ + private $connectionOptions = []; + + /** + * @var int The strategy for locking, see constants + */ + private $lockMode = self::LOCK_TRANSACTIONAL; + + /** + * It's an array to support multiple reads before closing which is manual, non-standard usage. + * + * @var \PDOStatement[] An array of statements to release advisory locks + */ + private $unlockStatements = []; + + /** + * @var bool True when the current session exists but expired according to session.gc_maxlifetime + */ + private $sessionExpired = false; + + /** + * @var bool Whether a transaction is active + */ + private $inTransaction = false; + + /** + * @var bool Whether gc() has been called + */ + private $gcCalled = false; + + /** + * You can either pass an existing database connection as PDO instance or + * pass a DSN string that will be used to lazy-connect to the database + * when the session is actually used. Furthermore it's possible to pass null + * which will then use the session.save_path ini setting as PDO DSN parameter. + * + * List of available options: + * * db_table: The name of the table [default: sessions] + * * db_id_col: The column where to store the session id [default: sess_id] + * * db_data_col: The column where to store the session data [default: sess_data] + * * db_lifetime_col: The column where to store the lifetime [default: sess_lifetime] + * * db_time_col: The column where to store the timestamp [default: sess_time] + * * db_username: The username when lazy-connect [default: ''] + * * db_password: The password when lazy-connect [default: ''] + * * db_connection_options: An array of driver-specific connection options [default: []] + * * lock_mode: The strategy for locking, see constants [default: LOCK_TRANSACTIONAL] + * + * @param \PDO|string|null $pdoOrDsn A \PDO instance or DSN string or URL string or null + * + * @throws \InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION + */ + public function __construct($pdoOrDsn = null, array $options = []) + { + if ($pdoOrDsn instanceof \PDO) { + if (\PDO::ERRMODE_EXCEPTION !== $pdoOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { + throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION))', __CLASS__)); + } + + $this->pdo = $pdoOrDsn; + $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); + } elseif (\is_string($pdoOrDsn) && false !== strpos($pdoOrDsn, '://')) { + $this->dsn = $this->buildDsnFromUrl($pdoOrDsn); + } else { + $this->dsn = $pdoOrDsn; + } + + $this->table = isset($options['db_table']) ? $options['db_table'] : $this->table; + $this->idCol = isset($options['db_id_col']) ? $options['db_id_col'] : $this->idCol; + $this->dataCol = isset($options['db_data_col']) ? $options['db_data_col'] : $this->dataCol; + $this->lifetimeCol = isset($options['db_lifetime_col']) ? $options['db_lifetime_col'] : $this->lifetimeCol; + $this->timeCol = isset($options['db_time_col']) ? $options['db_time_col'] : $this->timeCol; + $this->username = isset($options['db_username']) ? $options['db_username'] : $this->username; + $this->password = isset($options['db_password']) ? $options['db_password'] : $this->password; + $this->connectionOptions = isset($options['db_connection_options']) ? $options['db_connection_options'] : $this->connectionOptions; + $this->lockMode = isset($options['lock_mode']) ? $options['lock_mode'] : $this->lockMode; + } + + /** + * Creates the table to store sessions which can be called once for setup. + * + * Session ID is saved in a column of maximum length 128 because that is enough even + * for a 512 bit configured session.hash_function like Whirlpool. Session data is + * saved in a BLOB. One could also use a shorter inlined varbinary column + * if one was sure the data fits into it. + * + * @throws \PDOException When the table already exists + * @throws \DomainException When an unsupported PDO driver is used + */ + public function createTable() + { + // connect if we are not yet + $this->getConnection(); + + switch ($this->driver) { + case 'mysql': + // We use varbinary for the ID column because it prevents unwanted conversions: + // - character set conversions between server and client + // - trailing space removal + // - case-insensitivity + // - language processing like é == e + $sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB"; + break; + case 'sqlite': + $sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; + break; + case 'pgsql': + $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; + break; + case 'oci': + $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR2(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; + break; + case 'sqlsrv': + $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; + break; + default: + throw new \DomainException(sprintf('Creating the session table is currently not implemented for PDO driver "%s".', $this->driver)); + } + + try { + $this->pdo->exec($sql); + $this->pdo->exec("CREATE INDEX EXPIRY ON $this->table ($this->lifetimeCol)"); + } catch (\PDOException $e) { + $this->rollback(); + + throw $e; + } + } + + /** + * Returns true when the current session exists but expired according to session.gc_maxlifetime. + * + * Can be used to distinguish between a new session and one that expired due to inactivity. + * + * @return bool Whether current session expired + */ + public function isSessionExpired() + { + return $this->sessionExpired; + } + + /** + * @return bool + */ + public function open($savePath, $sessionName) + { + $this->sessionExpired = false; + + if (null === $this->pdo) { + $this->connect($this->dsn ?: $savePath); + } + + return parent::open($savePath, $sessionName); + } + + /** + * @return string + */ + public function read($sessionId) + { + try { + return parent::read($sessionId); + } catch (\PDOException $e) { + $this->rollback(); + + throw $e; + } + } + + /** + * @return bool + */ + public function gc($maxlifetime) + { + // We delay gc() to close() so that it is executed outside the transactional and blocking read-write process. + // This way, pruning expired sessions does not block them from being started while the current session is used. + $this->gcCalled = true; + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doDestroy(string $sessionId) + { + // delete the record associated with this id + $sql = "DELETE FROM $this->table WHERE $this->idCol = :id"; + + try { + $stmt = $this->pdo->prepare($sql); + $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $stmt->execute(); + } catch (\PDOException $e) { + $this->rollback(); + + throw $e; + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $sessionId, string $data) + { + $maxlifetime = (int) ini_get('session.gc_maxlifetime'); + + try { + // We use a single MERGE SQL query when supported by the database. + $mergeStmt = $this->getMergeStatement($sessionId, $data, $maxlifetime); + if (null !== $mergeStmt) { + $mergeStmt->execute(); + + return true; + } + + $updateStmt = $this->getUpdateStatement($sessionId, $data, $maxlifetime); + $updateStmt->execute(); + + // When MERGE is not supported, like in Postgres < 9.5, we have to use this approach that can result in + // duplicate key errors when the same session is written simultaneously (given the LOCK_NONE behavior). + // We can just catch such an error and re-execute the update. This is similar to a serializable + // transaction with retry logic on serialization failures but without the overhead and without possible + // false positives due to longer gap locking. + if (!$updateStmt->rowCount()) { + try { + $insertStmt = $this->getInsertStatement($sessionId, $data, $maxlifetime); + $insertStmt->execute(); + } catch (\PDOException $e) { + // Handle integrity violation SQLSTATE 23000 (or a subclass like 23505 in Postgres) for duplicate keys + if (0 === strpos($e->getCode(), '23')) { + $updateStmt->execute(); + } else { + throw $e; + } + } + } + } catch (\PDOException $e) { + $this->rollback(); + + throw $e; + } + + return true; + } + + /** + * @return bool + */ + public function updateTimestamp($sessionId, $data) + { + $expiry = time() + (int) ini_get('session.gc_maxlifetime'); + + try { + $updateStmt = $this->pdo->prepare( + "UPDATE $this->table SET $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id" + ); + $updateStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $updateStmt->bindParam(':expiry', $expiry, \PDO::PARAM_INT); + $updateStmt->bindValue(':time', time(), \PDO::PARAM_INT); + $updateStmt->execute(); + } catch (\PDOException $e) { + $this->rollback(); + + throw $e; + } + + return true; + } + + /** + * @return bool + */ + public function close() + { + $this->commit(); + + while ($unlockStmt = array_shift($this->unlockStatements)) { + $unlockStmt->execute(); + } + + if ($this->gcCalled) { + $this->gcCalled = false; + + // delete the session records that have expired + $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol < :time AND $this->lifetimeCol > :min"; + $stmt = $this->pdo->prepare($sql); + $stmt->bindValue(':time', time(), \PDO::PARAM_INT); + $stmt->bindValue(':min', self::MAX_LIFETIME, \PDO::PARAM_INT); + $stmt->execute(); + // to be removed in 6.0 + if ('mysql' === $this->driver) { + $legacySql = "DELETE FROM $this->table WHERE $this->lifetimeCol <= :min AND $this->lifetimeCol + $this->timeCol < :time"; + } else { + $legacySql = "DELETE FROM $this->table WHERE $this->lifetimeCol <= :min AND $this->lifetimeCol < :time - $this->timeCol"; + } + + $stmt = $this->pdo->prepare($legacySql); + $stmt->bindValue(':time', time(), \PDO::PARAM_INT); + $stmt->bindValue(':min', self::MAX_LIFETIME, \PDO::PARAM_INT); + $stmt->execute(); + } + + if (false !== $this->dsn) { + $this->pdo = null; // only close lazy-connection + } + + return true; + } + + /** + * Lazy-connects to the database. + */ + private function connect(string $dsn): void + { + $this->pdo = new \PDO($dsn, $this->username, $this->password, $this->connectionOptions); + $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); + } + + /** + * Builds a PDO DSN from a URL-like connection string. + * + * @todo implement missing support for oci DSN (which look totally different from other PDO ones) + */ + private function buildDsnFromUrl(string $dsnOrUrl): string + { + // (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid + $url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $dsnOrUrl); + + $params = parse_url($url); + + if (false === $params) { + return $dsnOrUrl; // If the URL is not valid, let's assume it might be a DSN already. + } + + $params = array_map('rawurldecode', $params); + + // Override the default username and password. Values passed through options will still win over these in the constructor. + if (isset($params['user'])) { + $this->username = $params['user']; + } + + if (isset($params['pass'])) { + $this->password = $params['pass']; + } + + if (!isset($params['scheme'])) { + throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler'); + } + + $driverAliasMap = [ + 'mssql' => 'sqlsrv', + 'mysql2' => 'mysql', // Amazon RDS, for some weird reason + 'postgres' => 'pgsql', + 'postgresql' => 'pgsql', + 'sqlite3' => 'sqlite', + ]; + + $driver = isset($driverAliasMap[$params['scheme']]) ? $driverAliasMap[$params['scheme']] : $params['scheme']; + + // Doctrine DBAL supports passing its internal pdo_* driver names directly too (allowing both dashes and underscores). This allows supporting the same here. + if (0 === strpos($driver, 'pdo_') || 0 === strpos($driver, 'pdo-')) { + $driver = substr($driver, 4); + } + + switch ($driver) { + case 'mysql': + case 'pgsql': + $dsn = $driver.':'; + + if (isset($params['host']) && '' !== $params['host']) { + $dsn .= 'host='.$params['host'].';'; + } + + if (isset($params['port']) && '' !== $params['port']) { + $dsn .= 'port='.$params['port'].';'; + } + + if (isset($params['path'])) { + $dbName = substr($params['path'], 1); // Remove the leading slash + $dsn .= 'dbname='.$dbName.';'; + } + + return $dsn; + + case 'sqlite': + return 'sqlite:'.substr($params['path'], 1); + + case 'sqlsrv': + $dsn = 'sqlsrv:server='; + + if (isset($params['host'])) { + $dsn .= $params['host']; + } + + if (isset($params['port']) && '' !== $params['port']) { + $dsn .= ','.$params['port']; + } + + if (isset($params['path'])) { + $dbName = substr($params['path'], 1); // Remove the leading slash + $dsn .= ';Database='.$dbName; + } + + return $dsn; + + default: + throw new \InvalidArgumentException(sprintf('The scheme "%s" is not supported by the PdoSessionHandler URL configuration. Pass a PDO DSN directly.', $params['scheme'])); + } + } + + /** + * Helper method to begin a transaction. + * + * Since SQLite does not support row level locks, we have to acquire a reserved lock + * on the database immediately. Because of https://bugs.php.net/42766 we have to create + * such a transaction manually which also means we cannot use PDO::commit or + * PDO::rollback or PDO::inTransaction for SQLite. + * + * Also MySQLs default isolation, REPEATABLE READ, causes deadlock for different sessions + * due to https://percona.com/blog/2013/12/12/one-more-innodb-gap-lock-to-avoid/ . + * So we change it to READ COMMITTED. + */ + private function beginTransaction(): void + { + if (!$this->inTransaction) { + if ('sqlite' === $this->driver) { + $this->pdo->exec('BEGIN IMMEDIATE TRANSACTION'); + } else { + if ('mysql' === $this->driver) { + $this->pdo->exec('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); + } + $this->pdo->beginTransaction(); + } + $this->inTransaction = true; + } + } + + /** + * Helper method to commit a transaction. + */ + private function commit(): void + { + if ($this->inTransaction) { + try { + // commit read-write transaction which also releases the lock + if ('sqlite' === $this->driver) { + $this->pdo->exec('COMMIT'); + } else { + $this->pdo->commit(); + } + $this->inTransaction = false; + } catch (\PDOException $e) { + $this->rollback(); + + throw $e; + } + } + } + + /** + * Helper method to rollback a transaction. + */ + private function rollback(): void + { + // We only need to rollback if we are in a transaction. Otherwise the resulting + // error would hide the real problem why rollback was called. We might not be + // in a transaction when not using the transactional locking behavior or when + // two callbacks (e.g. destroy and write) are invoked that both fail. + if ($this->inTransaction) { + if ('sqlite' === $this->driver) { + $this->pdo->exec('ROLLBACK'); + } else { + $this->pdo->rollBack(); + } + $this->inTransaction = false; + } + } + + /** + * Reads the session data in respect to the different locking strategies. + * + * We need to make sure we do not return session data that is already considered garbage according + * to the session.gc_maxlifetime setting because gc() is called after read() and only sometimes. + * + * @return string + */ + protected function doRead(string $sessionId) + { + if (self::LOCK_ADVISORY === $this->lockMode) { + $this->unlockStatements[] = $this->doAdvisoryLock($sessionId); + } + + $selectSql = $this->getSelectSql(); + $selectStmt = $this->pdo->prepare($selectSql); + $selectStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $insertStmt = null; + + do { + $selectStmt->execute(); + $sessionRows = $selectStmt->fetchAll(\PDO::FETCH_NUM); + + if ($sessionRows) { + $expiry = (int) $sessionRows[0][1]; + if ($expiry <= self::MAX_LIFETIME) { + $expiry += $sessionRows[0][2]; + } + + if ($expiry < time()) { + $this->sessionExpired = true; + + return ''; + } + + return \is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0]; + } + + if (null !== $insertStmt) { + $this->rollback(); + throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.'); + } + + if (!filter_var(ini_get('session.use_strict_mode'), FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { + // In strict mode, session fixation is not possible: new sessions always start with a unique + // random id, so that concurrency is not possible and this code path can be skipped. + // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block + // until other connections to the session are committed. + try { + $insertStmt = $this->getInsertStatement($sessionId, '', 0); + $insertStmt->execute(); + } catch (\PDOException $e) { + // Catch duplicate key error because other connection created the session already. + // It would only not be the case when the other connection destroyed the session. + if (0 === strpos($e->getCode(), '23')) { + // Retrieve finished session data written by concurrent connection by restarting the loop. + // We have to start a new transaction as a failed query will mark the current transaction as + // aborted in PostgreSQL and disallow further queries within it. + $this->rollback(); + $this->beginTransaction(); + continue; + } + + throw $e; + } + } + + return ''; + } while (true); + } + + /** + * Executes an application-level lock on the database. + * + * @return \PDOStatement The statement that needs to be executed later to release the lock + * + * @throws \DomainException When an unsupported PDO driver is used + * + * @todo implement missing advisory locks + * - for oci using DBMS_LOCK.REQUEST + * - for sqlsrv using sp_getapplock with LockOwner = Session + */ + private function doAdvisoryLock(string $sessionId): \PDOStatement + { + switch ($this->driver) { + case 'mysql': + // MySQL 5.7.5 and later enforces a maximum length on lock names of 64 characters. Previously, no limit was enforced. + $lockId = substr($sessionId, 0, 64); + // should we handle the return value? 0 on timeout, null on error + // we use a timeout of 50 seconds which is also the default for innodb_lock_wait_timeout + $stmt = $this->pdo->prepare('SELECT GET_LOCK(:key, 50)'); + $stmt->bindValue(':key', $lockId, \PDO::PARAM_STR); + $stmt->execute(); + + $releaseStmt = $this->pdo->prepare('DO RELEASE_LOCK(:key)'); + $releaseStmt->bindValue(':key', $lockId, \PDO::PARAM_STR); + + return $releaseStmt; + case 'pgsql': + // Obtaining an exclusive session level advisory lock requires an integer key. + // When session.sid_bits_per_character > 4, the session id can contain non-hex-characters. + // So we cannot just use hexdec(). + if (4 === \PHP_INT_SIZE) { + $sessionInt1 = $this->convertStringToInt($sessionId); + $sessionInt2 = $this->convertStringToInt(substr($sessionId, 4, 4)); + + $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key1, :key2)'); + $stmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); + $stmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT); + $stmt->execute(); + + $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key1, :key2)'); + $releaseStmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); + $releaseStmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT); + } else { + $sessionBigInt = $this->convertStringToInt($sessionId); + + $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key)'); + $stmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT); + $stmt->execute(); + + $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key)'); + $releaseStmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT); + } + + return $releaseStmt; + case 'sqlite': + throw new \DomainException('SQLite does not support advisory locks.'); + default: + throw new \DomainException(sprintf('Advisory locks are currently not implemented for PDO driver "%s".', $this->driver)); + } + } + + /** + * Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer. + * + * Keep in mind, PHP integers are signed. + */ + private function convertStringToInt(string $string): int + { + if (4 === \PHP_INT_SIZE) { + return (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); + } + + $int1 = (\ord($string[7]) << 24) + (\ord($string[6]) << 16) + (\ord($string[5]) << 8) + \ord($string[4]); + $int2 = (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); + + return $int2 + ($int1 << 32); + } + + /** + * Return a locking or nonlocking SQL query to read session information. + * + * @throws \DomainException When an unsupported PDO driver is used + */ + private function getSelectSql(): string + { + if (self::LOCK_TRANSACTIONAL === $this->lockMode) { + $this->beginTransaction(); + + // selecting the time column should be removed in 6.0 + switch ($this->driver) { + case 'mysql': + case 'oci': + case 'pgsql': + return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WHERE $this->idCol = :id FOR UPDATE"; + case 'sqlsrv': + return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WITH (UPDLOCK, ROWLOCK) WHERE $this->idCol = :id"; + case 'sqlite': + // we already locked when starting transaction + break; + default: + throw new \DomainException(sprintf('Transactional locks are currently not implemented for PDO driver "%s".', $this->driver)); + } + } + + return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WHERE $this->idCol = :id"; + } + + /** + * Returns an insert statement supported by the database for writing session data. + */ + private function getInsertStatement(string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement + { + switch ($this->driver) { + case 'oci': + $data = fopen('php://memory', 'r+'); + fwrite($data, $sessionData); + rewind($data); + $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, EMPTY_BLOB(), :expiry, :time) RETURNING $this->dataCol into :data"; + break; + default: + $data = $sessionData; + $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)"; + break; + } + + $stmt = $this->pdo->prepare($sql); + $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); + $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); + $stmt->bindValue(':time', time(), \PDO::PARAM_INT); + + return $stmt; + } + + /** + * Returns an update statement supported by the database for writing session data. + */ + private function getUpdateStatement(string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement + { + switch ($this->driver) { + case 'oci': + $data = fopen('php://memory', 'r+'); + fwrite($data, $sessionData); + rewind($data); + $sql = "UPDATE $this->table SET $this->dataCol = EMPTY_BLOB(), $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id RETURNING $this->dataCol into :data"; + break; + default: + $data = $sessionData; + $sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id"; + break; + } + + $stmt = $this->pdo->prepare($sql); + $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); + $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); + $stmt->bindValue(':time', time(), \PDO::PARAM_INT); + + return $stmt; + } + + /** + * Returns a merge/upsert (i.e. insert or update) statement when supported by the database for writing session data. + */ + private function getMergeStatement(string $sessionId, string $data, int $maxlifetime): ?\PDOStatement + { + switch (true) { + case 'mysql' === $this->driver: + $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ". + "ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)"; + break; + case 'sqlsrv' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '10', '>='): + // MERGE is only available since SQL Server 2008 and must be terminated by semicolon + // It also requires HOLDLOCK according to https://weblogs.sqlteam.com/dang/2009/01/31/upsert-race-condition-with-merge/ + $mergeSql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ". + "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". + "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;"; + break; + case 'sqlite' === $this->driver: + $mergeSql = "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)"; + break; + case 'pgsql' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '9.5', '>='): + $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ". + "ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; + break; + default: + // MERGE is not supported with LOBs: https://oracle.com/technetwork/articles/fuecks-lobs-095315.html + return null; + } + + $mergeStmt = $this->pdo->prepare($mergeSql); + + if ('sqlsrv' === $this->driver) { + $mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR); + $mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR); + $mergeStmt->bindParam(3, $data, \PDO::PARAM_LOB); + $mergeStmt->bindValue(4, time() + $maxlifetime, \PDO::PARAM_INT); + $mergeStmt->bindValue(5, time(), \PDO::PARAM_INT); + $mergeStmt->bindParam(6, $data, \PDO::PARAM_LOB); + $mergeStmt->bindValue(7, time() + $maxlifetime, \PDO::PARAM_INT); + $mergeStmt->bindValue(8, time(), \PDO::PARAM_INT); + } else { + $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB); + $mergeStmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); + $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT); + } + + return $mergeStmt; + } + + /** + * Return a PDO instance. + * + * @return \PDO + */ + protected function getConnection() + { + if (null === $this->pdo) { + $this->connect($this->dsn ?: ini_get('session.save_path')); + } + + return $this->pdo; + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php new file mode 100644 index 0000000..b9ca28f --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +use Predis\Response\ErrorInterface; +use Symfony\Component\Cache\Traits\RedisClusterProxy; +use Symfony\Component\Cache\Traits\RedisProxy; + +/** + * Redis based session storage handler based on the Redis class + * provided by the PHP redis extension. + * + * @author Dalibor Karlović + */ +class RedisSessionHandler extends AbstractSessionHandler +{ + private $redis; + + /** + * @var string Key prefix for shared environments + */ + private $prefix; + + /** + * @var int Time to live in seconds + */ + private $ttl; + + /** + * List of available options: + * * prefix: The prefix to use for the keys in order to avoid collision on the Redis server + * * ttl: The time to live in seconds. + * + * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis + * + * @throws \InvalidArgumentException When unsupported client or options are passed + */ + public function __construct($redis, array $options = []) + { + if ( + !$redis instanceof \Redis && + !$redis instanceof \RedisArray && + !$redis instanceof \RedisCluster && + !$redis instanceof \Predis\ClientInterface && + !$redis instanceof RedisProxy && + !$redis instanceof RedisClusterProxy + ) { + throw new \InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, %s given', __METHOD__, \is_object($redis) ? \get_class($redis) : \gettype($redis))); + } + + if ($diff = array_diff(array_keys($options), ['prefix', 'ttl'])) { + throw new \InvalidArgumentException(sprintf('The following options are not supported "%s"', implode(', ', $diff))); + } + + $this->redis = $redis; + $this->prefix = $options['prefix'] ?? 'sf_s'; + $this->ttl = $options['ttl'] ?? null; + } + + /** + * {@inheritdoc} + */ + protected function doRead(string $sessionId): string + { + return $this->redis->get($this->prefix.$sessionId) ?: ''; + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $sessionId, string $data): bool + { + $result = $this->redis->setEx($this->prefix.$sessionId, (int) ($this->ttl ?? ini_get('session.gc_maxlifetime')), $data); + + return $result && !$result instanceof ErrorInterface; + } + + /** + * {@inheritdoc} + */ + protected function doDestroy(string $sessionId): bool + { + $this->redis->del($this->prefix.$sessionId); + + return true; + } + + /** + * {@inheritdoc} + */ + public function close(): bool + { + return true; + } + + /** + * {@inheritdoc} + */ + public function gc($maxlifetime): bool + { + return true; + } + + /** + * @return bool + */ + public function updateTimestamp($sessionId, $data) + { + return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ($this->ttl ?? ini_get('session.gc_maxlifetime'))); + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php b/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php new file mode 100644 index 0000000..1f017c8 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +use Doctrine\DBAL\DriverManager; +use Symfony\Component\Cache\Adapter\AbstractAdapter; +use Symfony\Component\Cache\Traits\RedisClusterProxy; +use Symfony\Component\Cache\Traits\RedisProxy; + +/** + * @author Nicolas Grekas + */ +class SessionHandlerFactory +{ + /** + * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy|\Memcached|\PDO|string $connection Connection or DSN + */ + public static function createHandler($connection): AbstractSessionHandler + { + if (!\is_string($connection) && !\is_object($connection)) { + throw new \TypeError(sprintf('Argument 1 passed to %s() must be a string or a connection object, %s given.', __METHOD__, \gettype($connection))); + } + + switch (true) { + case $connection instanceof \Redis: + case $connection instanceof \RedisArray: + case $connection instanceof \RedisCluster: + case $connection instanceof \Predis\ClientInterface: + case $connection instanceof RedisProxy: + case $connection instanceof RedisClusterProxy: + return new RedisSessionHandler($connection); + + case $connection instanceof \Memcached: + return new MemcachedSessionHandler($connection); + + case $connection instanceof \PDO: + return new PdoSessionHandler($connection); + + case !\is_string($connection): + throw new \InvalidArgumentException(sprintf('Unsupported Connection: %s.', \get_class($connection))); + case 0 === strpos($connection, 'file://'): + return new StrictSessionHandler(new NativeFileSessionHandler(substr($connection, 7))); + + case 0 === strpos($connection, 'redis:'): + case 0 === strpos($connection, 'rediss:'): + case 0 === strpos($connection, 'memcached:'): + if (!class_exists(AbstractAdapter::class)) { + throw new InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require symfony/cache".', $connection)); + } + $handlerClass = 0 === strpos($connection, 'memcached:') ? MemcachedSessionHandler::class : RedisSessionHandler::class; + $connection = AbstractAdapter::createConnection($connection, ['lazy' => true]); + + return new $handlerClass($connection); + + case 0 === strpos($connection, 'pdo_oci://'): + if (!class_exists(DriverManager::class)) { + throw new \InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require doctrine/dbal".', $connection)); + } + $connection = DriverManager::getConnection(['url' => $connection])->getWrappedConnection(); + // no break; + + case 0 === strpos($connection, 'mssql://'): + case 0 === strpos($connection, 'mysql://'): + case 0 === strpos($connection, 'mysql2://'): + case 0 === strpos($connection, 'pgsql://'): + case 0 === strpos($connection, 'postgres://'): + case 0 === strpos($connection, 'postgresql://'): + case 0 === strpos($connection, 'sqlsrv://'): + case 0 === strpos($connection, 'sqlite://'): + case 0 === strpos($connection, 'sqlite3://'): + return new PdoSessionHandler($connection); + } + + throw new \InvalidArgumentException(sprintf('Unsupported Connection: %s.', $connection)); + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php new file mode 100644 index 0000000..4292a3b --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +/** + * Adds basic `SessionUpdateTimestampHandlerInterface` behaviors to another `SessionHandlerInterface`. + * + * @author Nicolas Grekas + */ +class StrictSessionHandler extends AbstractSessionHandler +{ + private $handler; + private $doDestroy; + + public function __construct(\SessionHandlerInterface $handler) + { + if ($handler instanceof \SessionUpdateTimestampHandlerInterface) { + throw new \LogicException(sprintf('"%s" is already an instance of "SessionUpdateTimestampHandlerInterface", you cannot wrap it with "%s".', \get_class($handler), self::class)); + } + + $this->handler = $handler; + } + + /** + * @return bool + */ + public function open($savePath, $sessionName) + { + parent::open($savePath, $sessionName); + + return $this->handler->open($savePath, $sessionName); + } + + /** + * {@inheritdoc} + */ + protected function doRead(string $sessionId) + { + return $this->handler->read($sessionId); + } + + /** + * @return bool + */ + public function updateTimestamp($sessionId, $data) + { + return $this->write($sessionId, $data); + } + + /** + * {@inheritdoc} + */ + protected function doWrite(string $sessionId, string $data) + { + return $this->handler->write($sessionId, $data); + } + + /** + * @return bool + */ + public function destroy($sessionId) + { + $this->doDestroy = true; + $destroyed = parent::destroy($sessionId); + + return $this->doDestroy ? $this->doDestroy($sessionId) : $destroyed; + } + + /** + * {@inheritdoc} + */ + protected function doDestroy(string $sessionId) + { + $this->doDestroy = false; + + return $this->handler->destroy($sessionId); + } + + /** + * @return bool + */ + public function close() + { + return $this->handler->close(); + } + + /** + * @return bool + */ + public function gc($maxlifetime) + { + return $this->handler->gc($maxlifetime); + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php b/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php new file mode 100644 index 0000000..c79ee02 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php @@ -0,0 +1,166 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage; + +use Symfony\Component\HttpFoundation\Session\SessionBagInterface; + +/** + * Metadata container. + * + * Adds metadata to the session. + * + * @author Drak + */ +class MetadataBag implements SessionBagInterface +{ + const CREATED = 'c'; + const UPDATED = 'u'; + const LIFETIME = 'l'; + + /** + * @var string + */ + private $name = '__metadata'; + + /** + * @var string + */ + private $storageKey; + + /** + * @var array + */ + protected $meta = [self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0]; + + /** + * Unix timestamp. + * + * @var int + */ + private $lastUsed; + + /** + * @var int + */ + private $updateThreshold; + + /** + * @param string $storageKey The key used to store bag in the session + * @param int $updateThreshold The time to wait between two UPDATED updates + */ + public function __construct(string $storageKey = '_sf2_meta', int $updateThreshold = 0) + { + $this->storageKey = $storageKey; + $this->updateThreshold = $updateThreshold; + } + + /** + * {@inheritdoc} + */ + public function initialize(array &$array) + { + $this->meta = &$array; + + if (isset($array[self::CREATED])) { + $this->lastUsed = $this->meta[self::UPDATED]; + + $timeStamp = time(); + if ($timeStamp - $array[self::UPDATED] >= $this->updateThreshold) { + $this->meta[self::UPDATED] = $timeStamp; + } + } else { + $this->stampCreated(); + } + } + + /** + * Gets the lifetime that the session cookie was set with. + * + * @return int + */ + public function getLifetime() + { + return $this->meta[self::LIFETIME]; + } + + /** + * Stamps a new session's metadata. + * + * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value + * will leave the system settings unchanged, 0 sets the cookie + * to expire with browser session. Time is in seconds, and is + * not a Unix timestamp. + */ + public function stampNew(int $lifetime = null) + { + $this->stampCreated($lifetime); + } + + /** + * {@inheritdoc} + */ + public function getStorageKey() + { + return $this->storageKey; + } + + /** + * Gets the created timestamp metadata. + * + * @return int Unix timestamp + */ + public function getCreated() + { + return $this->meta[self::CREATED]; + } + + /** + * Gets the last used metadata. + * + * @return int Unix timestamp + */ + public function getLastUsed() + { + return $this->lastUsed; + } + + /** + * {@inheritdoc} + */ + public function clear() + { + // nothing to do + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * Sets name. + */ + public function setName(string $name) + { + $this->name = $name; + } + + private function stampCreated(int $lifetime = null): void + { + $timeStamp = time(); + $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; + $this->meta[self::LIFETIME] = (null === $lifetime) ? ini_get('session.cookie_lifetime') : $lifetime; + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php new file mode 100644 index 0000000..4662bd8 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php @@ -0,0 +1,252 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage; + +use Symfony\Component\HttpFoundation\Session\SessionBagInterface; + +/** + * MockArraySessionStorage mocks the session for unit tests. + * + * No PHP session is actually started since a session can be initialized + * and shutdown only once per PHP execution cycle. + * + * When doing functional testing, you should use MockFileSessionStorage instead. + * + * @author Fabien Potencier + * @author Bulat Shakirzyanov + * @author Drak + */ +class MockArraySessionStorage implements SessionStorageInterface +{ + /** + * @var string + */ + protected $id = ''; + + /** + * @var string + */ + protected $name; + + /** + * @var bool + */ + protected $started = false; + + /** + * @var bool + */ + protected $closed = false; + + /** + * @var array + */ + protected $data = []; + + /** + * @var MetadataBag + */ + protected $metadataBag; + + /** + * @var array|SessionBagInterface[] + */ + protected $bags = []; + + public function __construct(string $name = 'MOCKSESSID', MetadataBag $metaBag = null) + { + $this->name = $name; + $this->setMetadataBag($metaBag); + } + + public function setSessionData(array $array) + { + $this->data = $array; + } + + /** + * {@inheritdoc} + */ + public function start() + { + if ($this->started) { + return true; + } + + if (empty($this->id)) { + $this->id = $this->generateId(); + } + + $this->loadSession(); + + return true; + } + + /** + * {@inheritdoc} + */ + public function regenerate(bool $destroy = false, int $lifetime = null) + { + if (!$this->started) { + $this->start(); + } + + $this->metadataBag->stampNew($lifetime); + $this->id = $this->generateId(); + + return true; + } + + /** + * {@inheritdoc} + */ + public function getId() + { + return $this->id; + } + + /** + * {@inheritdoc} + */ + public function setId(string $id) + { + if ($this->started) { + throw new \LogicException('Cannot set session ID after the session has started.'); + } + + $this->id = $id; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function setName(string $name) + { + $this->name = $name; + } + + /** + * {@inheritdoc} + */ + public function save() + { + if (!$this->started || $this->closed) { + throw new \RuntimeException('Trying to save a session that was not started yet or was already closed'); + } + // nothing to do since we don't persist the session data + $this->closed = false; + $this->started = false; + } + + /** + * {@inheritdoc} + */ + public function clear() + { + // clear out the bags + foreach ($this->bags as $bag) { + $bag->clear(); + } + + // clear out the session + $this->data = []; + + // reconnect the bags to the session + $this->loadSession(); + } + + /** + * {@inheritdoc} + */ + public function registerBag(SessionBagInterface $bag) + { + $this->bags[$bag->getName()] = $bag; + } + + /** + * {@inheritdoc} + */ + public function getBag(string $name) + { + if (!isset($this->bags[$name])) { + throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); + } + + if (!$this->started) { + $this->start(); + } + + return $this->bags[$name]; + } + + /** + * {@inheritdoc} + */ + public function isStarted() + { + return $this->started; + } + + public function setMetadataBag(MetadataBag $bag = null) + { + if (null === $bag) { + $bag = new MetadataBag(); + } + + $this->metadataBag = $bag; + } + + /** + * Gets the MetadataBag. + * + * @return MetadataBag + */ + public function getMetadataBag() + { + return $this->metadataBag; + } + + /** + * Generates a session ID. + * + * This doesn't need to be particularly cryptographically secure since this is just + * a mock. + * + * @return string + */ + protected function generateId() + { + return hash('sha256', uniqid('ss_mock_', true)); + } + + protected function loadSession() + { + $bags = array_merge($this->bags, [$this->metadataBag]); + + foreach ($bags as $bag) { + $key = $bag->getStorageKey(); + $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : []; + $bag->initialize($this->data[$key]); + } + + $this->started = true; + $this->closed = false; + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php new file mode 100644 index 0000000..019a634 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php @@ -0,0 +1,148 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage; + +/** + * MockFileSessionStorage is used to mock sessions for + * functional testing when done in a single PHP process. + * + * No PHP session is actually started since a session can be initialized + * and shutdown only once per PHP execution cycle and this class does + * not pollute any session related globals, including session_*() functions + * or session.* PHP ini directives. + * + * @author Drak + */ +class MockFileSessionStorage extends MockArraySessionStorage +{ + private $savePath; + + /** + * @param string $savePath Path of directory to save session files + */ + public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null) + { + if (null === $savePath) { + $savePath = sys_get_temp_dir(); + } + + if (!is_dir($savePath) && !@mkdir($savePath, 0777, true) && !is_dir($savePath)) { + throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"', $savePath)); + } + + $this->savePath = $savePath; + + parent::__construct($name, $metaBag); + } + + /** + * {@inheritdoc} + */ + public function start() + { + if ($this->started) { + return true; + } + + if (!$this->id) { + $this->id = $this->generateId(); + } + + $this->read(); + + $this->started = true; + + return true; + } + + /** + * {@inheritdoc} + */ + public function regenerate(bool $destroy = false, int $lifetime = null) + { + if (!$this->started) { + $this->start(); + } + + if ($destroy) { + $this->destroy(); + } + + return parent::regenerate($destroy, $lifetime); + } + + /** + * {@inheritdoc} + */ + public function save() + { + if (!$this->started) { + throw new \RuntimeException('Trying to save a session that was not started yet or was already closed'); + } + + $data = $this->data; + + foreach ($this->bags as $bag) { + if (empty($data[$key = $bag->getStorageKey()])) { + unset($data[$key]); + } + } + if ([$key = $this->metadataBag->getStorageKey()] === array_keys($data)) { + unset($data[$key]); + } + + try { + if ($data) { + file_put_contents($this->getFilePath(), serialize($data)); + } else { + $this->destroy(); + } + } finally { + $this->data = $data; + } + + // this is needed for Silex, where the session object is re-used across requests + // in functional tests. In Symfony, the container is rebooted, so we don't have + // this issue + $this->started = false; + } + + /** + * Deletes a session from persistent storage. + * Deliberately leaves session data in memory intact. + */ + private function destroy(): void + { + if (is_file($this->getFilePath())) { + unlink($this->getFilePath()); + } + } + + /** + * Calculate path to file. + */ + private function getFilePath(): string + { + return $this->savePath.'/'.$this->id.'.mocksess'; + } + + /** + * Reads session from storage and loads session. + */ + private function read(): void + { + $filePath = $this->getFilePath(); + $this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : []; + + $this->loadSession(); + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php new file mode 100644 index 0000000..eb754db --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php @@ -0,0 +1,464 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage; + +use Symfony\Component\HttpFoundation\Session\SessionBagInterface; +use Symfony\Component\HttpFoundation\Session\SessionUtils; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; +use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; +use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; + +/** + * This provides a base class for session attribute storage. + * + * @author Drak + */ +class NativeSessionStorage implements SessionStorageInterface +{ + /** + * @var SessionBagInterface[] + */ + protected $bags = []; + + /** + * @var bool + */ + protected $started = false; + + /** + * @var bool + */ + protected $closed = false; + + /** + * @var AbstractProxy|\SessionHandlerInterface + */ + protected $saveHandler; + + /** + * @var MetadataBag + */ + protected $metadataBag; + + /** + * @var string|null + */ + private $emulateSameSite; + + /** + * Depending on how you want the storage driver to behave you probably + * want to override this constructor entirely. + * + * List of options for $options array with their defaults. + * + * @see https://php.net/session.configuration for options + * but we omit 'session.' from the beginning of the keys for convenience. + * + * ("auto_start", is not supported as it tells PHP to start a session before + * PHP starts to execute user-land code. Setting during runtime has no effect). + * + * cache_limiter, "" (use "0" to prevent headers from being sent entirely). + * cache_expire, "0" + * cookie_domain, "" + * cookie_httponly, "" + * cookie_lifetime, "0" + * cookie_path, "/" + * cookie_secure, "" + * cookie_samesite, null + * gc_divisor, "100" + * gc_maxlifetime, "1440" + * gc_probability, "1" + * lazy_write, "1" + * name, "PHPSESSID" + * referer_check, "" + * serialize_handler, "php" + * use_strict_mode, "0" + * use_cookies, "1" + * use_only_cookies, "1" + * use_trans_sid, "0" + * upload_progress.enabled, "1" + * upload_progress.cleanup, "1" + * upload_progress.prefix, "upload_progress_" + * upload_progress.name, "PHP_SESSION_UPLOAD_PROGRESS" + * upload_progress.freq, "1%" + * upload_progress.min-freq, "1" + * url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset=" + * sid_length, "32" + * sid_bits_per_character, "5" + * trans_sid_hosts, $_SERVER['HTTP_HOST'] + * trans_sid_tags, "a=href,area=href,frame=src,form=" + * + * @param AbstractProxy|\SessionHandlerInterface|null $handler + */ + public function __construct(array $options = [], $handler = null, MetadataBag $metaBag = null) + { + if (!\extension_loaded('session')) { + throw new \LogicException('PHP extension "session" is required.'); + } + + $options += [ + 'cache_limiter' => '', + 'cache_expire' => 0, + 'use_cookies' => 1, + 'lazy_write' => 1, + 'use_strict_mode' => 1, + ]; + + session_register_shutdown(); + + $this->setMetadataBag($metaBag); + $this->setOptions($options); + $this->setSaveHandler($handler); + } + + /** + * Gets the save handler instance. + * + * @return AbstractProxy|\SessionHandlerInterface + */ + public function getSaveHandler() + { + return $this->saveHandler; + } + + /** + * {@inheritdoc} + */ + public function start() + { + if ($this->started) { + return true; + } + + if (\PHP_SESSION_ACTIVE === session_status()) { + throw new \RuntimeException('Failed to start the session: already started by PHP.'); + } + + if (filter_var(ini_get('session.use_cookies'), FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) { + throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line)); + } + + // ok to try and start the session + if (!session_start()) { + throw new \RuntimeException('Failed to start the session'); + } + + if (null !== $this->emulateSameSite) { + $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); + if (null !== $originalCookie) { + header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); + } + } + + $this->loadSession(); + + return true; + } + + /** + * {@inheritdoc} + */ + public function getId() + { + return $this->saveHandler->getId(); + } + + /** + * {@inheritdoc} + */ + public function setId(string $id) + { + $this->saveHandler->setId($id); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->saveHandler->getName(); + } + + /** + * {@inheritdoc} + */ + public function setName(string $name) + { + $this->saveHandler->setName($name); + } + + /** + * {@inheritdoc} + */ + public function regenerate(bool $destroy = false, int $lifetime = null) + { + // Cannot regenerate the session ID for non-active sessions. + if (\PHP_SESSION_ACTIVE !== session_status()) { + return false; + } + + if (headers_sent()) { + return false; + } + + if (null !== $lifetime) { + ini_set('session.cookie_lifetime', $lifetime); + } + + if ($destroy) { + $this->metadataBag->stampNew(); + } + + $isRegenerated = session_regenerate_id($destroy); + + // The reference to $_SESSION in session bags is lost in PHP7 and we need to re-create it. + // @see https://bugs.php.net/70013 + $this->loadSession(); + + if (null !== $this->emulateSameSite) { + $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); + if (null !== $originalCookie) { + header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); + } + } + + return $isRegenerated; + } + + /** + * {@inheritdoc} + */ + public function save() + { + // Store a copy so we can restore the bags in case the session was not left empty + $session = $_SESSION; + + foreach ($this->bags as $bag) { + if (empty($_SESSION[$key = $bag->getStorageKey()])) { + unset($_SESSION[$key]); + } + } + if ([$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) { + unset($_SESSION[$key]); + } + + // Register error handler to add information about the current save handler + $previousHandler = set_error_handler(function ($type, $msg, $file, $line) use (&$previousHandler) { + if (E_WARNING === $type && 0 === strpos($msg, 'session_write_close():')) { + $handler = $this->saveHandler instanceof SessionHandlerProxy ? $this->saveHandler->getHandler() : $this->saveHandler; + $msg = sprintf('session_write_close(): Failed to write session data with "%s" handler', \get_class($handler)); + } + + return $previousHandler ? $previousHandler($type, $msg, $file, $line) : false; + }); + + try { + session_write_close(); + } finally { + restore_error_handler(); + + // Restore only if not empty + if ($_SESSION) { + $_SESSION = $session; + } + } + + $this->closed = true; + $this->started = false; + } + + /** + * {@inheritdoc} + */ + public function clear() + { + // clear out the bags + foreach ($this->bags as $bag) { + $bag->clear(); + } + + // clear out the session + $_SESSION = []; + + // reconnect the bags to the session + $this->loadSession(); + } + + /** + * {@inheritdoc} + */ + public function registerBag(SessionBagInterface $bag) + { + if ($this->started) { + throw new \LogicException('Cannot register a bag when the session is already started.'); + } + + $this->bags[$bag->getName()] = $bag; + } + + /** + * {@inheritdoc} + */ + public function getBag(string $name) + { + if (!isset($this->bags[$name])) { + throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); + } + + if (!$this->started && $this->saveHandler->isActive()) { + $this->loadSession(); + } elseif (!$this->started) { + $this->start(); + } + + return $this->bags[$name]; + } + + public function setMetadataBag(MetadataBag $metaBag = null) + { + if (null === $metaBag) { + $metaBag = new MetadataBag(); + } + + $this->metadataBag = $metaBag; + } + + /** + * Gets the MetadataBag. + * + * @return MetadataBag + */ + public function getMetadataBag() + { + return $this->metadataBag; + } + + /** + * {@inheritdoc} + */ + public function isStarted() + { + return $this->started; + } + + /** + * Sets session.* ini variables. + * + * For convenience we omit 'session.' from the beginning of the keys. + * Explicitly ignores other ini keys. + * + * @param array $options Session ini directives [key => value] + * + * @see https://php.net/session.configuration + */ + public function setOptions(array $options) + { + if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { + return; + } + + $validOptions = array_flip([ + 'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', + 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'cookie_samesite', + 'gc_divisor', 'gc_maxlifetime', 'gc_probability', + 'lazy_write', 'name', 'referer_check', + 'serialize_handler', 'use_strict_mode', 'use_cookies', + 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', + 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', + 'upload_progress.freq', 'upload_progress.min_freq', 'url_rewriter.tags', + 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', + ]); + + foreach ($options as $key => $value) { + if (isset($validOptions[$key])) { + if ('cookie_samesite' === $key && \PHP_VERSION_ID < 70300) { + // PHP < 7.3 does not support same_site cookies. We will emulate it in + // the start() method instead. + $this->emulateSameSite = $value; + continue; + } + ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value); + } + } + } + + /** + * Registers session save handler as a PHP session handler. + * + * To use internal PHP session save handlers, override this method using ini_set with + * session.save_handler and session.save_path e.g. + * + * ini_set('session.save_handler', 'files'); + * ini_set('session.save_path', '/tmp'); + * + * or pass in a \SessionHandler instance which configures session.save_handler in the + * constructor, for a template see NativeFileSessionHandler. + * + * @see https://php.net/session-set-save-handler + * @see https://php.net/sessionhandlerinterface + * @see https://php.net/sessionhandler + * + * @param AbstractProxy|\SessionHandlerInterface|null $saveHandler + * + * @throws \InvalidArgumentException + */ + public function setSaveHandler($saveHandler = null) + { + if (!$saveHandler instanceof AbstractProxy && + !$saveHandler instanceof \SessionHandlerInterface && + null !== $saveHandler) { + throw new \InvalidArgumentException('Must be instance of AbstractProxy; implement \SessionHandlerInterface; or be null.'); + } + + // Wrap $saveHandler in proxy and prevent double wrapping of proxy + if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { + $saveHandler = new SessionHandlerProxy($saveHandler); + } elseif (!$saveHandler instanceof AbstractProxy) { + $saveHandler = new SessionHandlerProxy(new StrictSessionHandler(new \SessionHandler())); + } + $this->saveHandler = $saveHandler; + + if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { + return; + } + + if ($this->saveHandler instanceof SessionHandlerProxy) { + session_set_save_handler($this->saveHandler, false); + } + } + + /** + * Load the session with attributes. + * + * After starting the session, PHP retrieves the session from whatever handlers + * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()). + * PHP takes the return value from the read() handler, unserializes it + * and populates $_SESSION with the result automatically. + */ + protected function loadSession(array &$session = null) + { + if (null === $session) { + $session = &$_SESSION; + } + + $bags = array_merge($this->bags, [$this->metadataBag]); + + foreach ($bags as $bag) { + $key = $bag->getStorageKey(); + $session[$key] = isset($session[$key]) && \is_array($session[$key]) ? $session[$key] : []; + $bag->initialize($session[$key]); + } + + $this->started = true; + $this->closed = false; + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php new file mode 100644 index 0000000..72dbef1 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage; + +use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; + +/** + * Allows session to be started by PHP and managed by Symfony. + * + * @author Drak + */ +class PhpBridgeSessionStorage extends NativeSessionStorage +{ + /** + * @param AbstractProxy|\SessionHandlerInterface|null $handler + */ + public function __construct($handler = null, MetadataBag $metaBag = null) + { + if (!\extension_loaded('session')) { + throw new \LogicException('PHP extension "session" is required.'); + } + + $this->setMetadataBag($metaBag); + $this->setSaveHandler($handler); + } + + /** + * {@inheritdoc} + */ + public function start() + { + if ($this->started) { + return true; + } + + $this->loadSession(); + + return true; + } + + /** + * {@inheritdoc} + */ + public function clear() + { + // clear out the bags and nothing else that may be set + // since the purpose of this driver is to share a handler + foreach ($this->bags as $bag) { + $bag->clear(); + } + + // reconnect the bags to the session + $this->loadSession(); + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php b/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php new file mode 100644 index 0000000..ded79d6 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; + +/** + * @author Drak + */ +abstract class AbstractProxy +{ + /** + * Flag if handler wraps an internal PHP session handler (using \SessionHandler). + * + * @var bool + */ + protected $wrapper = false; + + /** + * @var string + */ + protected $saveHandlerName; + + /** + * Gets the session.save_handler name. + * + * @return string|null + */ + public function getSaveHandlerName() + { + return $this->saveHandlerName; + } + + /** + * Is this proxy handler and instance of \SessionHandlerInterface. + * + * @return bool + */ + public function isSessionHandlerInterface() + { + return $this instanceof \SessionHandlerInterface; + } + + /** + * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. + * + * @return bool + */ + public function isWrapper() + { + return $this->wrapper; + } + + /** + * Has a session started? + * + * @return bool + */ + public function isActive() + { + return \PHP_SESSION_ACTIVE === session_status(); + } + + /** + * Gets the session ID. + * + * @return string + */ + public function getId() + { + return session_id(); + } + + /** + * Sets the session ID. + * + * @throws \LogicException + */ + public function setId(string $id) + { + if ($this->isActive()) { + throw new \LogicException('Cannot change the ID of an active session'); + } + + session_id($id); + } + + /** + * Gets the session name. + * + * @return string + */ + public function getName() + { + return session_name(); + } + + /** + * Sets the session name. + * + * @throws \LogicException + */ + public function setName(string $name) + { + if ($this->isActive()) { + throw new \LogicException('Cannot change the name of an active session'); + } + + session_name($name); + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php b/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php new file mode 100644 index 0000000..de4f550 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; + +/** + * @author Drak + */ +class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface +{ + protected $handler; + + public function __construct(\SessionHandlerInterface $handler) + { + $this->handler = $handler; + $this->wrapper = ($handler instanceof \SessionHandler); + $this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') : 'user'; + } + + /** + * @return \SessionHandlerInterface + */ + public function getHandler() + { + return $this->handler; + } + + // \SessionHandlerInterface + + /** + * @return bool + */ + public function open($savePath, $sessionName) + { + return (bool) $this->handler->open($savePath, $sessionName); + } + + /** + * @return bool + */ + public function close() + { + return (bool) $this->handler->close(); + } + + /** + * @return string + */ + public function read($sessionId) + { + return (string) $this->handler->read($sessionId); + } + + /** + * @return bool + */ + public function write($sessionId, $data) + { + return (bool) $this->handler->write($sessionId, $data); + } + + /** + * @return bool + */ + public function destroy($sessionId) + { + return (bool) $this->handler->destroy($sessionId); + } + + /** + * @return bool + */ + public function gc($maxlifetime) + { + return (bool) $this->handler->gc($maxlifetime); + } + + /** + * @return bool + */ + public function validateId($sessionId) + { + return !$this->handler instanceof \SessionUpdateTimestampHandlerInterface || $this->handler->validateId($sessionId); + } + + /** + * @return bool + */ + public function updateTimestamp($sessionId, $data) + { + return $this->handler instanceof \SessionUpdateTimestampHandlerInterface ? $this->handler->updateTimestamp($sessionId, $data) : $this->write($sessionId, $data); + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php b/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php new file mode 100644 index 0000000..eb8e8ff --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php @@ -0,0 +1,131 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage; + +use Symfony\Component\HttpFoundation\Session\SessionBagInterface; + +/** + * StorageInterface. + * + * @author Fabien Potencier + * @author Drak + */ +interface SessionStorageInterface +{ + /** + * Starts the session. + * + * @return bool True if started + * + * @throws \RuntimeException if something goes wrong starting the session + */ + public function start(); + + /** + * Checks if the session is started. + * + * @return bool True if started, false otherwise + */ + public function isStarted(); + + /** + * Returns the session ID. + * + * @return string The session ID or empty + */ + public function getId(); + + /** + * Sets the session ID. + */ + public function setId(string $id); + + /** + * Returns the session name. + * + * @return string The session name + */ + public function getName(); + + /** + * Sets the session name. + */ + public function setName(string $name); + + /** + * Regenerates id that represents this storage. + * + * This method must invoke session_regenerate_id($destroy) unless + * this interface is used for a storage object designed for unit + * or functional testing where a real PHP session would interfere + * with testing. + * + * Note regenerate+destroy should not clear the session data in memory + * only delete the session data from persistent storage. + * + * Care: When regenerating the session ID no locking is involved in PHP's + * session design. See https://bugs.php.net/61470 for a discussion. + * So you must make sure the regenerated session is saved BEFORE sending the + * headers with the new ID. Symfony's HttpKernel offers a listener for this. + * See Symfony\Component\HttpKernel\EventListener\SaveSessionListener. + * Otherwise session data could get lost again for concurrent requests with the + * new ID. One result could be that you get logged out after just logging in. + * + * @param bool $destroy Destroy session when regenerating? + * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value + * will leave the system settings unchanged, 0 sets the cookie + * to expire with browser session. Time is in seconds, and is + * not a Unix timestamp. + * + * @return bool True if session regenerated, false if error + * + * @throws \RuntimeException If an error occurs while regenerating this storage + */ + public function regenerate(bool $destroy = false, int $lifetime = null); + + /** + * Force the session to be saved and closed. + * + * This method must invoke session_write_close() unless this interface is + * used for a storage object design for unit or functional testing where + * a real PHP session would interfere with testing, in which case + * it should actually persist the session data if required. + * + * @throws \RuntimeException if the session is saved without being started, or if the session + * is already closed + */ + public function save(); + + /** + * Clear all session data in memory. + */ + public function clear(); + + /** + * Gets a SessionBagInterface by name. + * + * @return SessionBagInterface + * + * @throws \InvalidArgumentException If the bag does not exist + */ + public function getBag(string $name); + + /** + * Registers a SessionBagInterface for use. + */ + public function registerBag(SessionBagInterface $bag); + + /** + * @return MetadataBag + */ + public function getMetadataBag(); +} diff --git a/vendor/symfony/http-foundation/StreamedResponse.php b/vendor/symfony/http-foundation/StreamedResponse.php new file mode 100644 index 0000000..65ec2d9 --- /dev/null +++ b/vendor/symfony/http-foundation/StreamedResponse.php @@ -0,0 +1,135 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * StreamedResponse represents a streamed HTTP response. + * + * A StreamedResponse uses a callback for its content. + * + * The callback should use the standard PHP functions like echo + * to stream the response back to the client. The flush() function + * can also be used if needed. + * + * @see flush() + * + * @author Fabien Potencier + */ +class StreamedResponse extends Response +{ + protected $callback; + protected $streamed; + private $headersSent; + + public function __construct(callable $callback = null, int $status = 200, array $headers = []) + { + parent::__construct(null, $status, $headers); + + if (null !== $callback) { + $this->setCallback($callback); + } + $this->streamed = false; + $this->headersSent = false; + } + + /** + * Factory method for chainability. + * + * @param callable|null $callback A valid PHP callback or null to set it later + * + * @return static + */ + public static function create($callback = null, int $status = 200, array $headers = []) + { + return new static($callback, $status, $headers); + } + + /** + * Sets the PHP callback associated with this Response. + * + * @return $this + */ + public function setCallback(callable $callback) + { + $this->callback = $callback; + + return $this; + } + + /** + * {@inheritdoc} + * + * This method only sends the headers once. + * + * @return $this + */ + public function sendHeaders() + { + if ($this->headersSent) { + return $this; + } + + $this->headersSent = true; + + return parent::sendHeaders(); + } + + /** + * {@inheritdoc} + * + * This method only sends the content once. + * + * @return $this + */ + public function sendContent() + { + if ($this->streamed) { + return $this; + } + + $this->streamed = true; + + if (null === $this->callback) { + throw new \LogicException('The Response callback must not be null.'); + } + + ($this->callback)(); + + return $this; + } + + /** + * {@inheritdoc} + * + * @throws \LogicException when the content is not null + * + * @return $this + */ + public function setContent(?string $content) + { + if (null !== $content) { + throw new \LogicException('The content cannot be set on a StreamedResponse instance.'); + } + + $this->streamed = true; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getContent() + { + return false; + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php b/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php new file mode 100644 index 0000000..cb216ea --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Request; + +final class RequestAttributeValueSame extends Constraint +{ + private $name; + private $value; + + public function __construct(string $name, string $value) + { + $this->name = $name; + $this->value = $value; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return sprintf('has attribute "%s" with value "%s"', $this->name, $this->value); + } + + /** + * @param Request $request + * + * {@inheritdoc} + */ + protected function matches($request): bool + { + return $this->value === $request->attributes->get($this->name); + } + + /** + * @param Request $request + * + * {@inheritdoc} + */ + protected function failureDescription($request): string + { + return 'the Request '.$this->toString(); + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php new file mode 100644 index 0000000..554e1a1 --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseCookieValueSame extends Constraint +{ + private $name; + private $value; + private $path; + private $domain; + + public function __construct(string $name, string $value, string $path = '/', string $domain = null) + { + $this->name = $name; + $this->value = $value; + $this->path = $path; + $this->domain = $domain; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + $str = sprintf('has cookie "%s"', $this->name); + if ('/' !== $this->path) { + $str .= sprintf(' with path "%s"', $this->path); + } + if ($this->domain) { + $str .= sprintf(' for domain "%s"', $this->domain); + } + $str .= sprintf(' with value "%s"', $this->value); + + return $str; + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + $cookie = $this->getCookie($response); + if (!$cookie) { + return false; + } + + return $this->value === $cookie->getValue(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } + + protected function getCookie(Response $response): ?Cookie + { + $cookies = $response->headers->getCookies(); + + $filteredCookies = array_filter($cookies, function (Cookie $cookie) { + return $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain; + }); + + return reset($filteredCookies) ?: null; + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php new file mode 100644 index 0000000..eae9e27 --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseHasCookie extends Constraint +{ + private $name; + private $path; + private $domain; + + public function __construct(string $name, string $path = '/', string $domain = null) + { + $this->name = $name; + $this->path = $path; + $this->domain = $domain; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + $str = sprintf('has cookie "%s"', $this->name); + if ('/' !== $this->path) { + $str .= sprintf(' with path "%s"', $this->path); + } + if ($this->domain) { + $str .= sprintf(' for domain "%s"', $this->domain); + } + + return $str; + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + return null !== $this->getCookie($response); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } + + private function getCookie(Response $response): ?Cookie + { + $cookies = $response->headers->getCookies(); + + $filteredCookies = array_filter($cookies, function (Cookie $cookie) { + return $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain; + }); + + return reset($filteredCookies) ?: null; + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php new file mode 100644 index 0000000..68ad827 --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseHasHeader extends Constraint +{ + private $headerName; + + public function __construct(string $headerName) + { + $this->headerName = $headerName; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return sprintf('has header "%s"', $this->headerName); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + return $response->headers->has($this->headerName); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php new file mode 100644 index 0000000..a27d0c7 --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseHeaderSame extends Constraint +{ + private $headerName; + private $expectedValue; + + public function __construct(string $headerName, string $expectedValue) + { + $this->headerName = $headerName; + $this->expectedValue = $expectedValue; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return sprintf('has header "%s" with value "%s"', $this->headerName, $this->expectedValue); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + return $this->expectedValue === $response->headers->get($this->headerName, null); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php new file mode 100644 index 0000000..8c4b883 --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseIsRedirected extends Constraint +{ + /** + * {@inheritdoc} + */ + public function toString(): string + { + return 'is redirected'; + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + return $response->isRedirect(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function additionalFailureDescription($response): string + { + return (string) $response; + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php new file mode 100644 index 0000000..9c66558 --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseIsSuccessful extends Constraint +{ + /** + * {@inheritdoc} + */ + public function toString(): string + { + return 'is successful'; + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + return $response->isSuccessful(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function additionalFailureDescription($response): string + { + return (string) $response; + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php new file mode 100644 index 0000000..72bb000 --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseStatusCodeSame extends Constraint +{ + private $statusCode; + + public function __construct(int $statusCode) + { + $this->statusCode = $statusCode; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return 'status code is '.$this->statusCode; + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + return $this->statusCode === $response->getStatusCode(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function additionalFailureDescription($response): string + { + return (string) $response; + } +} diff --git a/vendor/symfony/http-foundation/UrlHelper.php b/vendor/symfony/http-foundation/UrlHelper.php new file mode 100644 index 0000000..f114c0a --- /dev/null +++ b/vendor/symfony/http-foundation/UrlHelper.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +use Symfony\Component\Routing\RequestContext; + +/** + * A helper service for manipulating URLs within and outside the request scope. + * + * @author Valentin Udaltsov + */ +final class UrlHelper +{ + private $requestStack; + private $requestContext; + + public function __construct(RequestStack $requestStack, RequestContext $requestContext = null) + { + $this->requestStack = $requestStack; + $this->requestContext = $requestContext; + } + + public function getAbsoluteUrl(string $path): string + { + if (false !== strpos($path, '://') || '//' === substr($path, 0, 2)) { + return $path; + } + + if (null === $request = $this->requestStack->getMasterRequest()) { + return $this->getAbsoluteUrlFromContext($path); + } + + if ('#' === $path[0]) { + $path = $request->getRequestUri().$path; + } elseif ('?' === $path[0]) { + $path = $request->getPathInfo().$path; + } + + if (!$path || '/' !== $path[0]) { + $prefix = $request->getPathInfo(); + $last = \strlen($prefix) - 1; + if ($last !== $pos = strrpos($prefix, '/')) { + $prefix = substr($prefix, 0, $pos).'/'; + } + + return $request->getUriForPath($prefix.$path); + } + + return $request->getSchemeAndHttpHost().$path; + } + + public function getRelativePath(string $path): string + { + if (false !== strpos($path, '://') || '//' === substr($path, 0, 2)) { + return $path; + } + + if (null === $request = $this->requestStack->getMasterRequest()) { + return $path; + } + + return $request->getRelativeUriForPath($path); + } + + private function getAbsoluteUrlFromContext(string $path): string + { + if (null === $this->requestContext || '' === $host = $this->requestContext->getHost()) { + return $path; + } + + $scheme = $this->requestContext->getScheme(); + $port = ''; + + if ('http' === $scheme && 80 !== $this->requestContext->getHttpPort()) { + $port = ':'.$this->requestContext->getHttpPort(); + } elseif ('https' === $scheme && 443 !== $this->requestContext->getHttpsPort()) { + $port = ':'.$this->requestContext->getHttpsPort(); + } + + if ('#' === $path[0]) { + $queryString = $this->requestContext->getQueryString(); + $path = $this->requestContext->getPathInfo().($queryString ? '?'.$queryString : '').$path; + } elseif ('?' === $path[0]) { + $path = $this->requestContext->getPathInfo().$path; + } + + if ('/' !== $path[0]) { + $path = rtrim($this->requestContext->getBaseUrl(), '/').'/'.$path; + } + + return $scheme.'://'.$host.$port.$path; + } +} diff --git a/vendor/symfony/http-foundation/composer.json b/vendor/symfony/http-foundation/composer.json new file mode 100644 index 0000000..fcec68c --- /dev/null +++ b/vendor/symfony/http-foundation/composer.json @@ -0,0 +1,39 @@ +{ + "name": "symfony/http-foundation", + "type": "library", + "description": "Symfony HttpFoundation Component", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "symfony/mime": "^4.4|^5.0", + "symfony/polyfill-mbstring": "~1.1" + }, + "require-dev": { + "predis/predis": "~1.0", + "symfony/expression-language": "^4.4|^5.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/http-kernel/.gitattributes b/vendor/symfony/http-kernel/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/http-kernel/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/http-kernel/Bundle/Bundle.php b/vendor/symfony/http-kernel/Bundle/Bundle.php new file mode 100644 index 0000000..2ff356c --- /dev/null +++ b/vendor/symfony/http-kernel/Bundle/Bundle.php @@ -0,0 +1,163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Bundle; + +use Symfony\Component\Console\Application; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\ContainerAwareTrait; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; + +/** + * An implementation of BundleInterface that adds a few conventions for DependencyInjection extensions. + * + * @author Fabien Potencier + */ +abstract class Bundle implements BundleInterface +{ + use ContainerAwareTrait; + + protected $name; + protected $extension; + protected $path; + private $namespace; + + /** + * {@inheritdoc} + */ + public function boot() + { + } + + /** + * {@inheritdoc} + */ + public function shutdown() + { + } + + /** + * {@inheritdoc} + * + * This method can be overridden to register compilation passes, + * other extensions, ... + */ + public function build(ContainerBuilder $container) + { + } + + /** + * Returns the bundle's container extension. + * + * @return ExtensionInterface|null The container extension + * + * @throws \LogicException + */ + public function getContainerExtension() + { + if (null === $this->extension) { + $extension = $this->createContainerExtension(); + + if (null !== $extension) { + if (!$extension instanceof ExtensionInterface) { + throw new \LogicException(sprintf('Extension %s must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', \get_class($extension))); + } + + // check naming convention + $basename = preg_replace('/Bundle$/', '', $this->getName()); + $expectedAlias = Container::underscore($basename); + + if ($expectedAlias != $extension->getAlias()) { + throw new \LogicException(sprintf('Users will expect the alias of the default extension of a bundle to be the underscored version of the bundle name ("%s"). You can override "Bundle::getContainerExtension()" if you want to use "%s" or another alias.', $expectedAlias, $extension->getAlias())); + } + + $this->extension = $extension; + } else { + $this->extension = false; + } + } + + return $this->extension ?: null; + } + + /** + * {@inheritdoc} + */ + public function getNamespace() + { + if (null === $this->namespace) { + $this->parseClassName(); + } + + return $this->namespace; + } + + /** + * {@inheritdoc} + */ + public function getPath() + { + if (null === $this->path) { + $reflected = new \ReflectionObject($this); + $this->path = \dirname($reflected->getFileName()); + } + + return $this->path; + } + + /** + * Returns the bundle name (the class short name). + */ + final public function getName(): string + { + if (null === $this->name) { + $this->parseClassName(); + } + + return $this->name; + } + + public function registerCommands(Application $application) + { + } + + /** + * Returns the bundle's container extension class. + * + * @return string + */ + protected function getContainerExtensionClass() + { + $basename = preg_replace('/Bundle$/', '', $this->getName()); + + return $this->getNamespace().'\\DependencyInjection\\'.$basename.'Extension'; + } + + /** + * Creates the bundle's container extension. + * + * @return ExtensionInterface|null + */ + protected function createContainerExtension() + { + return class_exists($class = $this->getContainerExtensionClass()) ? new $class() : null; + } + + private function parseClassName() + { + $pos = strrpos(static::class, '\\'); + $this->namespace = false === $pos ? '' : substr(static::class, 0, $pos); + if (null === $this->name) { + $this->name = false === $pos ? static::class : substr(static::class, $pos + 1); + } + } +} diff --git a/vendor/symfony/http-kernel/Bundle/BundleInterface.php b/vendor/symfony/http-kernel/Bundle/BundleInterface.php new file mode 100644 index 0000000..88a95d8 --- /dev/null +++ b/vendor/symfony/http-kernel/Bundle/BundleInterface.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Bundle; + +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; + +/** + * BundleInterface. + * + * @author Fabien Potencier + */ +interface BundleInterface extends ContainerAwareInterface +{ + /** + * Boots the Bundle. + */ + public function boot(); + + /** + * Shutdowns the Bundle. + */ + public function shutdown(); + + /** + * Builds the bundle. + * + * It is only ever called once when the cache is empty. + */ + public function build(ContainerBuilder $container); + + /** + * Returns the container extension that should be implicitly loaded. + * + * @return ExtensionInterface|null The default extension or null if there is none + */ + public function getContainerExtension(); + + /** + * Returns the bundle name (the class short name). + * + * @return string The Bundle name + */ + public function getName(); + + /** + * Gets the Bundle namespace. + * + * @return string The Bundle namespace + */ + public function getNamespace(); + + /** + * Gets the Bundle directory path. + * + * The path should always be returned as a Unix path (with /). + * + * @return string The Bundle absolute path + */ + public function getPath(); +} diff --git a/vendor/symfony/http-kernel/CHANGELOG.md b/vendor/symfony/http-kernel/CHANGELOG.md new file mode 100644 index 0000000..adcbe66 --- /dev/null +++ b/vendor/symfony/http-kernel/CHANGELOG.md @@ -0,0 +1,269 @@ +CHANGELOG +========= + +5.0.0 +----- + + * removed support for getting the container from a non-booted kernel + * removed the first and second constructor argument of `ConfigDataCollector` + * removed `ConfigDataCollector::getApplicationName()` + * removed `ConfigDataCollector::getApplicationVersion()` + * removed support for `Symfony\Component\Templating\EngineInterface` in `HIncludeFragmentRenderer`, use a `Twig\Environment` only + * removed `TranslatorListener` in favor of `LocaleAwareListener` + * removed `getRootDir()` and `getName()` from `Kernel` and `KernelInterface` + * removed `FilterControllerArgumentsEvent`, use `ControllerArgumentsEvent` instead + * removed `FilterControllerEvent`, use `ControllerEvent` instead + * removed `FilterResponseEvent`, use `ResponseEvent` instead + * removed `GetResponseEvent`, use `RequestEvent` instead + * removed `GetResponseForControllerResultEvent`, use `ViewEvent` instead + * removed `GetResponseForExceptionEvent`, use `ExceptionEvent` instead + * removed `PostResponseEvent`, use `TerminateEvent` instead + * removed `SaveSessionListener` in favor of `AbstractSessionListener` + * removed `Client`, use `HttpKernelBrowser` instead + * added method `getProjectDir()` to `KernelInterface` + * removed methods `serialize` and `unserialize` from `DataCollector`, store the serialized state in the data property instead + * made `ProfilerStorageInterface` internal + * removed the second and third argument of `KernelInterface::locateResource` + * removed the second and third argument of `FileLocator::__construct` + * removed loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as + fallback directories. + * removed class `ExceptionListener`, use `ErrorListener` instead + +4.4.0 +----- + + * The `DebugHandlersListener` class has been marked as `final` + * Added new Bundle directory convention consistent with standard skeletons + * Deprecated the second and third argument of `KernelInterface::locateResource` + * Deprecated the second and third argument of `FileLocator::__construct` + * Deprecated loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as + fallback directories. Resources like service definitions are usually loaded relative to the + current directory or with a glob pattern. The fallback directories have never been advocated + so you likely do not use those in any app based on the SF Standard or Flex edition. + * Marked all dispatched event classes as `@final` + * Added `ErrorController` to enable the preview and error rendering mechanism + * Getting the container from a non-booted kernel is deprecated. + * Marked the `AjaxDataCollector`, `ConfigDataCollector`, `EventDataCollector`, + `ExceptionDataCollector`, `LoggerDataCollector`, `MemoryDataCollector`, + `RequestDataCollector` and `TimeDataCollector` classes as `@final`. + * Marked the `RouterDataCollector::collect()` method as `@final`. + * The `DataCollectorInterface::collect()` and `Profiler::collect()` methods third parameter signature + will be `\Throwable $exception = null` instead of `\Exception $exception = null` in Symfony 5.0. + * Deprecated methods `ExceptionEvent::get/setException()`, use `get/setThrowable()` instead + * Deprecated class `ExceptionListener`, use `ErrorListener` instead + +4.3.0 +----- + + * renamed `Client` to `HttpKernelBrowser` + * `KernelInterface` doesn't extend `Serializable` anymore + * deprecated the `Kernel::serialize()` and `unserialize()` methods + * increased the priority of `Symfony\Component\HttpKernel\EventListener\AddRequestFormatsListener` + * made `Symfony\Component\HttpKernel\EventListener\LocaleListener` set the default locale early + * deprecated `TranslatorListener` in favor of `LocaleAwareListener` + * added the registration of all `LocaleAwareInterface` implementations into the `LocaleAwareListener` + * made `FileLinkFormatter` final and not implement `Serializable` anymore + * the base `DataCollector` doesn't implement `Serializable` anymore, you should + store all the serialized state in the data property instead + * `DumpDataCollector` has been marked as `final` + * added an event listener to prevent search engines from indexing applications in debug mode. + * renamed `FilterControllerArgumentsEvent` to `ControllerArgumentsEvent` + * renamed `FilterControllerEvent` to `ControllerEvent` + * renamed `FilterResponseEvent` to `ResponseEvent` + * renamed `GetResponseEvent` to `RequestEvent` + * renamed `GetResponseForControllerResultEvent` to `ViewEvent` + * renamed `GetResponseForExceptionEvent` to `ExceptionEvent` + * renamed `PostResponseEvent` to `TerminateEvent` + * added `HttpClientKernel` for handling requests with an `HttpClientInterface` instance + * added `trace_header` and `trace_level` configuration options to `HttpCache` + +4.2.0 +----- + + * deprecated `KernelInterface::getRootDir()` and the `kernel.root_dir` parameter + * deprecated `KernelInterface::getName()` and the `kernel.name` parameter + * deprecated the first and second constructor argument of `ConfigDataCollector` + * deprecated `ConfigDataCollector::getApplicationName()` + * deprecated `ConfigDataCollector::getApplicationVersion()` + +4.1.0 +----- + + * added orphaned events support to `EventDataCollector` + * `ExceptionListener` now logs exceptions at priority `0` (previously logged at `-128`) + * Added support for using `service::method` to reference controllers, making it consistent with other cases. It is recommended over the `service:action` syntax with a single colon, which will be deprecated in the future. + * Added the ability to profile individual argument value resolvers via the + `Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver` + +4.0.0 +----- + + * removed the `DataCollector::varToString()` method, use `DataCollector::cloneVar()` + instead + * using the `DataCollector::cloneVar()` method requires the VarDumper component + * removed the `ValueExporter` class + * removed `ControllerResolverInterface::getArguments()` + * removed `TraceableControllerResolver::getArguments()` + * removed `ControllerResolver::getArguments()` and the ability to resolve arguments + * removed the `argument_resolver` service dependency from the `debug.controller_resolver` + * removed `LazyLoadingFragmentHandler::addRendererService()` + * removed `Psr6CacheClearer::addPool()` + * removed `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()` + * removed `Kernel::loadClassCache()`, `Kernel::doLoadClassCache()`, `Kernel::setClassCache()`, + and `Kernel::getEnvParameters()` + * support for the `X-Status-Code` when handling exceptions in the `HttpKernel` + has been dropped, use the `HttpKernel::allowCustomResponseCode()` method + instead + * removed convention-based commands registration + * removed the `ChainCacheClearer::add()` method + * removed the `CacheaWarmerAggregate::add()` and `setWarmers()` methods + * made `CacheWarmerAggregate` and `ChainCacheClearer` classes final + +3.4.0 +----- + + * added a minimalist PSR-3 `Logger` class that writes in `stderr` + * made kernels implementing `CompilerPassInterface` able to process the container + * deprecated bundle inheritance + * added `RebootableInterface` and implemented it in `Kernel` + * deprecated commands auto registration + * deprecated `EnvParametersResource` + * added `Symfony\Component\HttpKernel\Client::catchExceptions()` + * deprecated the `ChainCacheClearer::add()` method + * deprecated the `CacheaWarmerAggregate::add()` and `setWarmers()` methods + * made `CacheWarmerAggregate` and `ChainCacheClearer` classes final + * added the possibility to reset the profiler to its initial state + * deprecated data collectors without a `reset()` method + * deprecated implementing `DebugLoggerInterface` without a `clear()` method + +3.3.0 +----- + + * added `kernel.project_dir` and `Kernel::getProjectDir()` + * deprecated `kernel.root_dir` and `Kernel::getRootDir()` + * deprecated `Kernel::getEnvParameters()` + * deprecated the special `SYMFONY__` environment variables + * added the possibility to change the query string parameter used by `UriSigner` + * deprecated `LazyLoadingFragmentHandler::addRendererService()` + * deprecated `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()` + * deprecated `Psr6CacheClearer::addPool()` + +3.2.0 +----- + + * deprecated `DataCollector::varToString()`, use `cloneVar()` instead + * changed surrogate capability name in `AbstractSurrogate::addSurrogateCapability` to 'symfony' + * Added `ControllerArgumentValueResolverPass` + +3.1.0 +----- + * deprecated passing objects as URI attributes to the ESI and SSI renderers + * deprecated `ControllerResolver::getArguments()` + * added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface` + * added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface` as argument to `HttpKernel` + * added `Symfony\Component\HttpKernel\Controller\ArgumentResolver` + * added `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector::getMethod()` + * added `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector::getRedirect()` + * added the `kernel.controller_arguments` event, triggered after controller arguments have been resolved + +3.0.0 +----- + + * removed `Symfony\Component\HttpKernel\Kernel::init()` + * removed `Symfony\Component\HttpKernel\Kernel::isClassInActiveBundle()` and `Symfony\Component\HttpKernel\KernelInterface::isClassInActiveBundle()` + * removed `Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher::setProfiler()` + * removed `Symfony\Component\HttpKernel\EventListener\FragmentListener::getLocalIpAddresses()` + * removed `Symfony\Component\HttpKernel\EventListener\LocaleListener::setRequest()` + * removed `Symfony\Component\HttpKernel\EventListener\RouterListener::setRequest()` + * removed `Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelRequest()` + * removed `Symfony\Component\HttpKernel\Fragment\FragmentHandler::setRequest()` + * removed `Symfony\Component\HttpKernel\HttpCache\Esi::hasSurrogateEsiCapability()` + * removed `Symfony\Component\HttpKernel\HttpCache\Esi::addSurrogateEsiCapability()` + * removed `Symfony\Component\HttpKernel\HttpCache\Esi::needsEsiParsing()` + * removed `Symfony\Component\HttpKernel\HttpCache\HttpCache::getEsi()` + * removed `Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel` + * removed `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass` + * removed `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener` + * removed `Symfony\Component\HttpKernel\EventListener\EsiListener` + * removed `Symfony\Component\HttpKernel\HttpCache\EsiResponseCacheStrategy` + * removed `Symfony\Component\HttpKernel\HttpCache\EsiResponseCacheStrategyInterface` + * removed `Symfony\Component\HttpKernel\Log\LoggerInterface` + * removed `Symfony\Component\HttpKernel\Log\NullLogger` + * removed `Symfony\Component\HttpKernel\Profiler::import()` + * removed `Symfony\Component\HttpKernel\Profiler::export()` + +2.8.0 +----- + + * deprecated `Profiler::import` and `Profiler::export` + +2.7.0 +----- + + * added the HTTP status code to profiles + +2.6.0 +----- + + * deprecated `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener`, use `Symfony\Component\HttpKernel\EventListener\DebugHandlersListener` instead + * deprecated unused method `Symfony\Component\HttpKernel\Kernel::isClassInActiveBundle` and `Symfony\Component\HttpKernel\KernelInterface::isClassInActiveBundle` + +2.5.0 +----- + + * deprecated `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass`, use `Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass` instead + +2.4.0 +----- + + * added event listeners for the session + * added the KernelEvents::FINISH_REQUEST event + +2.3.0 +----- + + * [BC BREAK] renamed `Symfony\Component\HttpKernel\EventListener\DeprecationLoggerListener` to `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener` and changed its constructor + * deprecated `Symfony\Component\HttpKernel\Debug\ErrorHandler`, `Symfony\Component\HttpKernel\Debug\ExceptionHandler`, + `Symfony\Component\HttpKernel\Exception\FatalErrorException` and `Symfony\Component\HttpKernel\Exception\FlattenException` + * deprecated `Symfony\Component\HttpKernel\Kernel::init()` + * added the possibility to specify an id an extra attributes to hinclude tags + * added the collect of data if a controller is a Closure in the Request collector + * pass exceptions from the ExceptionListener to the logger using the logging context to allow for more + detailed messages + +2.2.0 +----- + + * [BC BREAK] the path info for sub-request is now always _fragment (or whatever you configured instead of the default) + * added Symfony\Component\HttpKernel\EventListener\FragmentListener + * added Symfony\Component\HttpKernel\UriSigner + * added Symfony\Component\HttpKernel\FragmentRenderer and rendering strategies (in Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface) + * added Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel + * added ControllerReference to create reference of Controllers (used in the FragmentRenderer class) + * [BC BREAK] renamed TimeDataCollector::getTotalTime() to + TimeDataCollector::getDuration() + * updated the MemoryDataCollector to include the memory used in the + kernel.terminate event listeners + * moved the Stopwatch classes to a new component + * added TraceableControllerResolver + * added TraceableEventDispatcher (removed ContainerAwareTraceableEventDispatcher) + * added support for WinCache opcode cache in ConfigDataCollector + +2.1.0 +----- + + * [BC BREAK] the charset is now configured via the Kernel::getCharset() method + * [BC BREAK] the current locale for the user is not stored anymore in the session + * added the HTTP method to the profiler storage + * updated all listeners to implement EventSubscriberInterface + * added TimeDataCollector + * added ContainerAwareTraceableEventDispatcher + * moved TraceableEventDispatcherInterface to the EventDispatcher component + * added RouterListener, LocaleListener, and StreamedResponseListener + * added CacheClearerInterface (and ChainCacheClearer) + * added a kernel.terminate event (via TerminableInterface and PostResponseEvent) + * added a Stopwatch class + * added WarmableInterface + * improved extensibility between bundles + * added profiler storages for Memcache(d), File-based, MongoDB, Redis + * moved Filesystem class to its own component diff --git a/vendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.php b/vendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.php new file mode 100644 index 0000000..270f690 --- /dev/null +++ b/vendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\CacheClearer; + +/** + * CacheClearerInterface. + * + * @author Dustin Dobervich + */ +interface CacheClearerInterface +{ + /** + * Clears any caches necessary. + */ + public function clear(string $cacheDir); +} diff --git a/vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php b/vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php new file mode 100644 index 0000000..95d41a8 --- /dev/null +++ b/vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\CacheClearer; + +/** + * ChainCacheClearer. + * + * @author Dustin Dobervich + * + * @final + */ +class ChainCacheClearer implements CacheClearerInterface +{ + private $clearers; + + public function __construct(iterable $clearers = []) + { + $this->clearers = $clearers; + } + + /** + * {@inheritdoc} + */ + public function clear(string $cacheDir) + { + foreach ($this->clearers as $clearer) { + $clearer->clear($cacheDir); + } + } +} diff --git a/vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php b/vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php new file mode 100644 index 0000000..ab37853 --- /dev/null +++ b/vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\CacheClearer; + +/** + * @author Nicolas Grekas + */ +class Psr6CacheClearer implements CacheClearerInterface +{ + private $pools = []; + + public function __construct(array $pools = []) + { + $this->pools = $pools; + } + + public function hasPool(string $name) + { + return isset($this->pools[$name]); + } + + public function getPool(string $name) + { + if (!$this->hasPool($name)) { + throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name)); + } + + return $this->pools[$name]; + } + + public function clearPool(string $name) + { + if (!isset($this->pools[$name])) { + throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name)); + } + + return $this->pools[$name]->clear(); + } + + /** + * {@inheritdoc} + */ + public function clear(string $cacheDir) + { + foreach ($this->pools as $pool) { + $pool->clear(); + } + } +} diff --git a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php new file mode 100644 index 0000000..aef42d6 --- /dev/null +++ b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\CacheWarmer; + +/** + * Abstract cache warmer that knows how to write a file to the cache. + * + * @author Fabien Potencier + */ +abstract class CacheWarmer implements CacheWarmerInterface +{ + protected function writeCacheFile(string $file, $content) + { + $tmpFile = @tempnam(\dirname($file), basename($file)); + if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) { + @chmod($file, 0666 & ~umask()); + + return; + } + + throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file)); + } +} diff --git a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php new file mode 100644 index 0000000..1b3d73b --- /dev/null +++ b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\CacheWarmer; + +/** + * Aggregates several cache warmers into a single one. + * + * @author Fabien Potencier + * + * @final + */ +class CacheWarmerAggregate implements CacheWarmerInterface +{ + private $warmers; + private $debug; + private $deprecationLogsFilepath; + private $optionalsEnabled = false; + private $onlyOptionalsEnabled = false; + + public function __construct(iterable $warmers = [], bool $debug = false, string $deprecationLogsFilepath = null) + { + $this->warmers = $warmers; + $this->debug = $debug; + $this->deprecationLogsFilepath = $deprecationLogsFilepath; + } + + public function enableOptionalWarmers() + { + $this->optionalsEnabled = true; + } + + public function enableOnlyOptionalWarmers() + { + $this->onlyOptionalsEnabled = $this->optionalsEnabled = true; + } + + /** + * Warms up the cache. + */ + public function warmUp(string $cacheDir) + { + if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) { + $collectedLogs = []; + $previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) { + if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) { + return $previousHandler ? $previousHandler($type, $message, $file, $line) : false; + } + + if (isset($collectedLogs[$message])) { + ++$collectedLogs[$message]['count']; + + return null; + } + + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3); + // Clean the trace by removing first frames added by the error handler itself. + for ($i = 0; isset($backtrace[$i]); ++$i) { + if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { + $backtrace = \array_slice($backtrace, 1 + $i); + break; + } + } + + $collectedLogs[$message] = [ + 'type' => $type, + 'message' => $message, + 'file' => $file, + 'line' => $line, + 'trace' => $backtrace, + 'count' => 1, + ]; + + return null; + }); + } + + try { + foreach ($this->warmers as $warmer) { + if (!$this->optionalsEnabled && $warmer->isOptional()) { + continue; + } + if ($this->onlyOptionalsEnabled && !$warmer->isOptional()) { + continue; + } + + $warmer->warmUp($cacheDir); + } + } finally { + if ($collectDeprecations) { + restore_error_handler(); + + if (file_exists($this->deprecationLogsFilepath)) { + $previousLogs = unserialize(file_get_contents($this->deprecationLogsFilepath)); + $collectedLogs = array_merge($previousLogs, $collectedLogs); + } + + file_put_contents($this->deprecationLogsFilepath, serialize(array_values($collectedLogs))); + } + } + } + + /** + * Checks whether this warmer is optional or not. + * + * @return bool always false + */ + public function isOptional(): bool + { + return false; + } +} diff --git a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php new file mode 100644 index 0000000..8fece5e --- /dev/null +++ b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\CacheWarmer; + +/** + * Interface for classes able to warm up the cache. + * + * @author Fabien Potencier + */ +interface CacheWarmerInterface extends WarmableInterface +{ + /** + * Checks whether this warmer is optional or not. + * + * Optional warmers can be ignored on certain conditions. + * + * A warmer should return true if the cache can be + * generated incrementally and on-demand. + * + * @return bool true if the warmer is optional, false otherwise + */ + public function isOptional(); +} diff --git a/vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.php b/vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.php new file mode 100644 index 0000000..e7715a3 --- /dev/null +++ b/vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\CacheWarmer; + +/** + * Interface for classes that support warming their cache. + * + * @author Fabien Potencier + */ +interface WarmableInterface +{ + /** + * Warms up the cache. + */ + public function warmUp(string $cacheDir); +} diff --git a/vendor/symfony/http-kernel/Config/FileLocator.php b/vendor/symfony/http-kernel/Config/FileLocator.php new file mode 100644 index 0000000..6eca986 --- /dev/null +++ b/vendor/symfony/http-kernel/Config/FileLocator.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Config; + +use Symfony\Component\Config\FileLocator as BaseFileLocator; +use Symfony\Component\HttpKernel\KernelInterface; + +/** + * FileLocator uses the KernelInterface to locate resources in bundles. + * + * @author Fabien Potencier + */ +class FileLocator extends BaseFileLocator +{ + private $kernel; + + public function __construct(KernelInterface $kernel) + { + $this->kernel = $kernel; + + parent::__construct(); + } + + /** + * {@inheritdoc} + */ + public function locate(string $file, string $currentPath = null, bool $first = true) + { + if (isset($file[0]) && '@' === $file[0]) { + $resource = $this->kernel->locateResource($file); + + return $first ? $resource : [$resource]; + } + + return parent::locate($file, $currentPath, $first); + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver.php new file mode 100644 index 0000000..43bbe17 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface; + +/** + * Responsible for resolving the arguments passed to an action. + * + * @author Iltar van der Berg + */ +final class ArgumentResolver implements ArgumentResolverInterface +{ + private $argumentMetadataFactory; + + /** + * @var iterable|ArgumentValueResolverInterface[] + */ + private $argumentValueResolvers; + + public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = []) + { + $this->argumentMetadataFactory = $argumentMetadataFactory ?: new ArgumentMetadataFactory(); + $this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers(); + } + + /** + * {@inheritdoc} + */ + public function getArguments(Request $request, callable $controller): array + { + $arguments = []; + + foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller) as $metadata) { + foreach ($this->argumentValueResolvers as $resolver) { + if (!$resolver->supports($request, $metadata)) { + continue; + } + + $resolved = $resolver->resolve($request, $metadata); + + $atLeastOne = false; + foreach ($resolved as $append) { + $atLeastOne = true; + $arguments[] = $append; + } + + if (!$atLeastOne) { + throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', \get_class($resolver))); + } + + // continue to the next controller argument + continue 2; + } + + $representative = $controller; + + if (\is_array($representative)) { + $representative = sprintf('%s::%s()', \get_class($representative[0]), $representative[1]); + } elseif (\is_object($representative)) { + $representative = \get_class($representative); + } + + throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.', $representative, $metadata->getName())); + } + + return $arguments; + } + + public static function getDefaultArgumentValueResolvers(): iterable + { + return [ + new RequestAttributeValueResolver(), + new RequestValueResolver(), + new SessionValueResolver(), + new DefaultValueResolver(), + new VariadicValueResolver(), + ]; + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php new file mode 100644 index 0000000..32a0e07 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Yields the default value defined in the action signature when no value has been given. + * + * @author Iltar van der Berg + */ +final class DefaultValueResolver implements ArgumentValueResolverInterface +{ + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument): bool + { + return $argument->hasDefaultValue() || (null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic()); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument): iterable + { + yield $argument->hasDefaultValue() ? $argument->getDefaultValue() : null; + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php new file mode 100644 index 0000000..d4971cc --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Provides an intuitive error message when controller fails because it is not registered as a service. + * + * @author Simeon Kolev + */ +final class NotTaggedControllerValueResolver implements ArgumentValueResolverInterface +{ + private $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument): bool + { + $controller = $request->attributes->get('_controller'); + + if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) { + $controller = $controller[0].'::'.$controller[1]; + } elseif (!\is_string($controller) || '' === $controller) { + return false; + } + + if ('\\' === $controller[0]) { + $controller = ltrim($controller, '\\'); + } + + if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) { + $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); + } + + return false === $this->container->has($controller); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument): iterable + { + if (\is_array($controller = $request->attributes->get('_controller'))) { + $controller = $controller[0].'::'.$controller[1]; + } + + if ('\\' === $controller[0]) { + $controller = ltrim($controller, '\\'); + } + + if (!$this->container->has($controller)) { + $i = strrpos($controller, ':'); + $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); + } + + $what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller); + $message = sprintf('Could not resolve %s, maybe you forgot to register the controller as a service or missed tagging it with the "controller.service_arguments"?', $what); + + throw new RuntimeException($message); + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php new file mode 100644 index 0000000..c62d327 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Yields a non-variadic argument's value from the request attributes. + * + * @author Iltar van der Berg + */ +final class RequestAttributeValueResolver implements ArgumentValueResolverInterface +{ + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument): bool + { + return !$argument->isVariadic() && $request->attributes->has($argument->getName()); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument): iterable + { + yield $request->attributes->get($argument->getName()); + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php new file mode 100644 index 0000000..75cbd97 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Yields the same instance as the request object passed along. + * + * @author Iltar van der Berg + */ +final class RequestValueResolver implements ArgumentValueResolverInterface +{ + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument): bool + { + return Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument): iterable + { + yield $request; + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php new file mode 100644 index 0000000..4ffb8c9 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Yields a service keyed by _controller and argument name. + * + * @author Nicolas Grekas + */ +final class ServiceValueResolver implements ArgumentValueResolverInterface +{ + private $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument): bool + { + $controller = $request->attributes->get('_controller'); + + if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) { + $controller = $controller[0].'::'.$controller[1]; + } elseif (!\is_string($controller) || '' === $controller) { + return false; + } + + if ('\\' === $controller[0]) { + $controller = ltrim($controller, '\\'); + } + + if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) { + $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); + } + + return $this->container->has($controller) && $this->container->get($controller)->has($argument->getName()); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument): iterable + { + if (\is_array($controller = $request->attributes->get('_controller'))) { + $controller = $controller[0].'::'.$controller[1]; + } + + if ('\\' === $controller[0]) { + $controller = ltrim($controller, '\\'); + } + + if (!$this->container->has($controller)) { + $i = strrpos($controller, ':'); + $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); + } + + try { + yield $this->container->get($controller)->get($argument->getName()); + } catch (RuntimeException $e) { + $what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller); + $message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage()); + + if ($e->getMessage() === $message) { + $message = sprintf('Cannot resolve %s: %s', $what, $message); + } + + $r = new \ReflectionProperty($e, 'message'); + $r->setAccessible(true); + $r->setValue($e, $message); + + throw $e; + } + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php new file mode 100644 index 0000000..a1e6b43 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Yields the Session. + * + * @author Iltar van der Berg + */ +final class SessionValueResolver implements ArgumentValueResolverInterface +{ + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument): bool + { + if (!$request->hasSession()) { + return false; + } + + $type = $argument->getType(); + if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) { + return false; + } + + return $request->getSession() instanceof $type; + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument): iterable + { + yield $request->getSession(); + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php new file mode 100644 index 0000000..bde3c90 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; +use Symfony\Component\Stopwatch\Stopwatch; + +/** + * Provides timing information via the stopwatch. + * + * @author Iltar van der Berg + */ +final class TraceableValueResolver implements ArgumentValueResolverInterface +{ + private $inner; + private $stopwatch; + + public function __construct(ArgumentValueResolverInterface $inner, Stopwatch $stopwatch) + { + $this->inner = $inner; + $this->stopwatch = $stopwatch; + } + + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument): bool + { + $method = \get_class($this->inner).'::'.__FUNCTION__; + $this->stopwatch->start($method, 'controller.argument_value_resolver'); + + $return = $this->inner->supports($request, $argument); + + $this->stopwatch->stop($method); + + return $return; + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument): iterable + { + $method = \get_class($this->inner).'::'.__FUNCTION__; + $this->stopwatch->start($method, 'controller.argument_value_resolver'); + + yield from $this->inner->resolve($request, $argument); + + $this->stopwatch->stop($method); + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php new file mode 100644 index 0000000..ed61420 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Yields a variadic argument's values from the request attributes. + * + * @author Iltar van der Berg + */ +final class VariadicValueResolver implements ArgumentValueResolverInterface +{ + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument): bool + { + return $argument->isVariadic() && $request->attributes->has($argument->getName()); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument): iterable + { + $values = $request->attributes->get($argument->getName()); + + if (!\is_array($values)) { + throw new \InvalidArgumentException(sprintf('The action argument "...$%1$s" is required to be an array, the request attribute "%1$s" contains a type of "%2$s" instead.', $argument->getName(), \gettype($values))); + } + + yield from $values; + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php b/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php new file mode 100644 index 0000000..2c32492 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\HttpFoundation\Request; + +/** + * An ArgumentResolverInterface instance knows how to determine the + * arguments for a specific action. + * + * @author Fabien Potencier + */ +interface ArgumentResolverInterface +{ + /** + * Returns the arguments to pass to the controller. + * + * @return array An array of arguments to pass to the controller + * + * @throws \RuntimeException When no value could be provided for a required argument + */ + public function getArguments(Request $request, callable $controller); +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php b/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php new file mode 100644 index 0000000..1317707 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Responsible for resolving the value of an argument based on its metadata. + * + * @author Iltar van der Berg + */ +interface ArgumentValueResolverInterface +{ + /** + * Whether this resolver can resolve the value for the given ArgumentMetadata. + * + * @return bool + */ + public function supports(Request $request, ArgumentMetadata $argument); + + /** + * Returns the possible value(s). + * + * @return iterable + */ + public function resolve(Request $request, ArgumentMetadata $argument); +} diff --git a/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php b/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php new file mode 100644 index 0000000..447df4a --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\DependencyInjection\Container; + +/** + * A controller resolver searching for a controller in a psr-11 container when using the "service:method" notation. + * + * @author Fabien Potencier + * @author Maxime Steinhausser + */ +class ContainerControllerResolver extends ControllerResolver +{ + protected $container; + + public function __construct(ContainerInterface $container, LoggerInterface $logger = null) + { + $this->container = $container; + + parent::__construct($logger); + } + + protected function createController(string $controller) + { + if (1 === substr_count($controller, ':')) { + $controller = str_replace(':', '::', $controller); + // TODO deprecate this in 5.1 + } + + return parent::createController($controller); + } + + /** + * {@inheritdoc} + */ + protected function instantiateController(string $class) + { + $class = ltrim($class, '\\'); + + if ($this->container->has($class)) { + return $this->container->get($class); + } + + try { + return parent::instantiateController($class); + } catch (\Error $e) { + } + + $this->throwExceptionIfControllerWasRemoved($class, $e); + + if ($e instanceof \ArgumentCountError) { + throw new \InvalidArgumentException(sprintf('Controller "%s" has required constructor arguments and does not exist in the container. Did you forget to define the controller as a service?', $class), 0, $e); + } + + throw new \InvalidArgumentException(sprintf('Controller "%s" does neither exist as service nor as class', $class), 0, $e); + } + + private function throwExceptionIfControllerWasRemoved(string $controller, \Throwable $previous) + { + if ($this->container instanceof Container && isset($this->container->getRemovedIds()[$controller])) { + throw new \InvalidArgumentException(sprintf('Controller "%s" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?', $controller), 0, $previous); + } + } +} diff --git a/vendor/symfony/http-kernel/Controller/ControllerReference.php b/vendor/symfony/http-kernel/Controller/ControllerReference.php new file mode 100644 index 0000000..b4fdadd --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ControllerReference.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface; + +/** + * Acts as a marker and a data holder for a Controller. + * + * Some methods in Symfony accept both a URI (as a string) or a controller as + * an argument. In the latter case, instead of passing an array representing + * the controller, you can use an instance of this class. + * + * @author Fabien Potencier + * + * @see FragmentRendererInterface + */ +class ControllerReference +{ + public $controller; + public $attributes = []; + public $query = []; + + /** + * @param string $controller The controller name + * @param array $attributes An array of parameters to add to the Request attributes + * @param array $query An array of parameters to add to the Request query string + */ + public function __construct(string $controller, array $attributes = [], array $query = []) + { + $this->controller = $controller; + $this->attributes = $attributes; + $this->query = $query; + } +} diff --git a/vendor/symfony/http-kernel/Controller/ControllerResolver.php b/vendor/symfony/http-kernel/Controller/ControllerResolver.php new file mode 100644 index 0000000..b5bd403 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ControllerResolver.php @@ -0,0 +1,220 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Psr\Log\LoggerInterface; +use Symfony\Component\HttpFoundation\Request; + +/** + * This implementation uses the '_controller' request attribute to determine + * the controller to execute. + * + * @author Fabien Potencier + * @author Tobias Schultze + */ +class ControllerResolver implements ControllerResolverInterface +{ + private $logger; + + public function __construct(LoggerInterface $logger = null) + { + $this->logger = $logger; + } + + /** + * {@inheritdoc} + */ + public function getController(Request $request) + { + if (!$controller = $request->attributes->get('_controller')) { + if (null !== $this->logger) { + $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.'); + } + + return false; + } + + if (\is_array($controller)) { + if (isset($controller[0]) && \is_string($controller[0]) && isset($controller[1])) { + try { + $controller[0] = $this->instantiateController($controller[0]); + } catch (\Error | \LogicException $e) { + try { + // We cannot just check is_callable but have to use reflection because a non-static method + // can still be called statically in PHP but we don't want that. This is deprecated in PHP 7, so we + // could simplify this with PHP 8. + if ((new \ReflectionMethod($controller[0], $controller[1]))->isStatic()) { + return $controller; + } + } catch (\ReflectionException $reflectionException) { + throw $e; + } + + throw $e; + } + } + + if (!\is_callable($controller)) { + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($controller))); + } + + return $controller; + } + + if (\is_object($controller)) { + if (!\is_callable($controller)) { + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($controller))); + } + + return $controller; + } + + if (\function_exists($controller)) { + return $controller; + } + + try { + $callable = $this->createController($controller); + } catch (\InvalidArgumentException $e) { + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $e->getMessage())); + } + + if (!\is_callable($callable)) { + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($callable))); + } + + return $callable; + } + + /** + * Returns a callable for the given controller. + * + * @return callable A PHP callable + * + * @throws \InvalidArgumentException When the controller cannot be created + */ + protected function createController(string $controller) + { + if (false === strpos($controller, '::')) { + $controller = $this->instantiateController($controller); + + if (!\is_callable($controller)) { + throw new \InvalidArgumentException($this->getControllerError($controller)); + } + + return $controller; + } + + list($class, $method) = explode('::', $controller, 2); + + try { + $controller = [$this->instantiateController($class), $method]; + } catch (\Error | \LogicException $e) { + try { + if ((new \ReflectionMethod($class, $method))->isStatic()) { + return $class.'::'.$method; + } + } catch (\ReflectionException $reflectionException) { + throw $e; + } + + throw $e; + } + + if (!\is_callable($controller)) { + throw new \InvalidArgumentException($this->getControllerError($controller)); + } + + return $controller; + } + + /** + * Returns an instantiated controller. + * + * @return object + */ + protected function instantiateController(string $class) + { + return new $class(); + } + + private function getControllerError($callable): string + { + if (\is_string($callable)) { + if (false !== strpos($callable, '::')) { + $callable = explode('::', $callable, 2); + } else { + return sprintf('Function "%s" does not exist.', $callable); + } + } + + if (\is_object($callable)) { + $availableMethods = $this->getClassMethodsWithoutMagicMethods($callable); + $alternativeMsg = $availableMethods ? sprintf(' or use one of the available methods: "%s"', implode('", "', $availableMethods)) : ''; + + return sprintf('Controller class "%s" cannot be called without a method name. You need to implement "__invoke"%s.', \get_class($callable), $alternativeMsg); + } + + if (!\is_array($callable)) { + return sprintf('Invalid type for controller given, expected string, array or object, got "%s".', \gettype($callable)); + } + + if (!isset($callable[0]) || !isset($callable[1]) || 2 !== \count($callable)) { + return 'Invalid array callable, expected [controller, method].'; + } + + list($controller, $method) = $callable; + + if (\is_string($controller) && !class_exists($controller)) { + return sprintf('Class "%s" does not exist.', $controller); + } + + $className = \is_object($controller) ? \get_class($controller) : $controller; + + if (method_exists($controller, $method)) { + return sprintf('Method "%s" on class "%s" should be public and non-abstract.', $method, $className); + } + + $collection = $this->getClassMethodsWithoutMagicMethods($controller); + + $alternatives = []; + + foreach ($collection as $item) { + $lev = levenshtein($method, $item); + + if ($lev <= \strlen($method) / 3 || false !== strpos($item, $method)) { + $alternatives[] = $item; + } + } + + asort($alternatives); + + $message = sprintf('Expected method "%s" on class "%s"', $method, $className); + + if (\count($alternatives) > 0) { + $message .= sprintf(', did you mean "%s"?', implode('", "', $alternatives)); + } else { + $message .= sprintf('. Available methods: "%s".', implode('", "', $collection)); + } + + return $message; + } + + private function getClassMethodsWithoutMagicMethods($classOrObject): array + { + $methods = get_class_methods($classOrObject); + + return array_filter($methods, function (string $method) { + return 0 !== strncmp($method, '__', 2); + }); + } +} diff --git a/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php b/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php new file mode 100644 index 0000000..8b70a88 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\HttpFoundation\Request; + +/** + * A ControllerResolverInterface implementation knows how to determine the + * controller to execute based on a Request object. + * + * A Controller can be any valid PHP callable. + * + * @author Fabien Potencier + */ +interface ControllerResolverInterface +{ + /** + * Returns the Controller instance associated with a Request. + * + * As several resolvers can exist for a single application, a resolver must + * return false when it is not able to determine the controller. + * + * The resolver must only throw an exception when it should be able to load a + * controller but cannot because of some errors made by the developer. + * + * @return callable|false A PHP callable representing the Controller, + * or false if this resolver is not able to determine the controller + * + * @throws \LogicException If a controller was found based on the request but it is not callable + */ + public function getController(Request $request); +} diff --git a/vendor/symfony/http-kernel/Controller/ErrorController.php b/vendor/symfony/http-kernel/Controller/ErrorController.php new file mode 100644 index 0000000..b6c4401 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ErrorController.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * Renders error or exception pages from a given FlattenException. + * + * @author Yonel Ceruto + * @author Matthias Pigulla + */ +class ErrorController +{ + private $kernel; + private $controller; + private $errorRenderer; + + public function __construct(HttpKernelInterface $kernel, $controller, ErrorRendererInterface $errorRenderer) + { + $this->kernel = $kernel; + $this->controller = $controller; + $this->errorRenderer = $errorRenderer; + } + + public function __invoke(\Throwable $exception): Response + { + $exception = $this->errorRenderer->render($exception); + + return new Response($exception->getAsString(), $exception->getStatusCode(), $exception->getHeaders()); + } + + public function preview(Request $request, int $code): Response + { + /* + * This Request mimics the parameters set by + * \Symfony\Component\HttpKernel\EventListener\ErrorListener::duplicateRequest, with + * the additional "showException" flag. + */ + $subRequest = $request->duplicate(null, null, [ + '_controller' => $this->controller, + 'exception' => new HttpException($code, 'This is a sample exception.'), + 'logger' => null, + 'showException' => false, + ]); + + return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST); + } +} diff --git a/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php b/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php new file mode 100644 index 0000000..e22cf08 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Stopwatch\Stopwatch; + +/** + * @author Fabien Potencier + */ +class TraceableArgumentResolver implements ArgumentResolverInterface +{ + private $resolver; + private $stopwatch; + + public function __construct(ArgumentResolverInterface $resolver, Stopwatch $stopwatch) + { + $this->resolver = $resolver; + $this->stopwatch = $stopwatch; + } + + /** + * {@inheritdoc} + */ + public function getArguments(Request $request, callable $controller) + { + $e = $this->stopwatch->start('controller.get_arguments'); + + $ret = $this->resolver->getArguments($request, $controller); + + $e->stop(); + + return $ret; + } +} diff --git a/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php b/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php new file mode 100644 index 0000000..bf6b6aa --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Stopwatch\Stopwatch; + +/** + * @author Fabien Potencier + */ +class TraceableControllerResolver implements ControllerResolverInterface +{ + private $resolver; + private $stopwatch; + + public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch) + { + $this->resolver = $resolver; + $this->stopwatch = $stopwatch; + } + + /** + * {@inheritdoc} + */ + public function getController(Request $request) + { + $e = $this->stopwatch->start('controller.get_callable'); + + $ret = $this->resolver->getController($request); + + $e->stop(); + + return $ret; + } +} diff --git a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php new file mode 100644 index 0000000..e73b848 --- /dev/null +++ b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\ControllerMetadata; + +/** + * Responsible for storing metadata of an argument. + * + * @author Iltar van der Berg + */ +class ArgumentMetadata +{ + private $name; + private $type; + private $isVariadic; + private $hasDefaultValue; + private $defaultValue; + private $isNullable; + + public function __construct(string $name, ?string $type, bool $isVariadic, bool $hasDefaultValue, $defaultValue, bool $isNullable = false) + { + $this->name = $name; + $this->type = $type; + $this->isVariadic = $isVariadic; + $this->hasDefaultValue = $hasDefaultValue; + $this->defaultValue = $defaultValue; + $this->isNullable = $isNullable || null === $type || ($hasDefaultValue && null === $defaultValue); + } + + /** + * Returns the name as given in PHP, $foo would yield "foo". + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Returns the type of the argument. + * + * The type is the PHP class in 5.5+ and additionally the basic type in PHP 7.0+. + * + * @return string|null + */ + public function getType() + { + return $this->type; + } + + /** + * Returns whether the argument is defined as "...$variadic". + * + * @return bool + */ + public function isVariadic() + { + return $this->isVariadic; + } + + /** + * Returns whether the argument has a default value. + * + * Implies whether an argument is optional. + * + * @return bool + */ + public function hasDefaultValue() + { + return $this->hasDefaultValue; + } + + /** + * Returns whether the argument accepts null values. + * + * @return bool + */ + public function isNullable() + { + return $this->isNullable; + } + + /** + * Returns the default value of the argument. + * + * @throws \LogicException if no default value is present; {@see self::hasDefaultValue()} + * + * @return mixed + */ + public function getDefaultValue() + { + if (!$this->hasDefaultValue) { + throw new \LogicException(sprintf('Argument $%s does not have a default value. Use %s::hasDefaultValue() to avoid this exception.', $this->name, __CLASS__)); + } + + return $this->defaultValue; + } +} diff --git a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php new file mode 100644 index 0000000..9370174 --- /dev/null +++ b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\ControllerMetadata; + +/** + * Builds {@see ArgumentMetadata} objects based on the given Controller. + * + * @author Iltar van der Berg + */ +final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface +{ + /** + * {@inheritdoc} + */ + public function createArgumentMetadata($controller): array + { + $arguments = []; + + if (\is_array($controller)) { + $reflection = new \ReflectionMethod($controller[0], $controller[1]); + } elseif (\is_object($controller) && !$controller instanceof \Closure) { + $reflection = (new \ReflectionObject($controller))->getMethod('__invoke'); + } else { + $reflection = new \ReflectionFunction($controller); + } + + foreach ($reflection->getParameters() as $param) { + $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param, $reflection), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull()); + } + + return $arguments; + } + + /** + * Returns an associated type to the given parameter if available. + */ + private function getType(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $function): ?string + { + if (!$type = $parameter->getType()) { + return null; + } + $name = $type->getName(); + + if ($function instanceof \ReflectionMethod) { + $lcName = strtolower($name); + switch ($lcName) { + case 'self': + return $function->getDeclaringClass()->name; + case 'parent': + return ($parent = $function->getDeclaringClass()->getParentClass()) ? $parent->name : null; + } + } + + return $name; + } +} diff --git a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php new file mode 100644 index 0000000..6ea179d --- /dev/null +++ b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\ControllerMetadata; + +/** + * Builds method argument data. + * + * @author Iltar van der Berg + */ +interface ArgumentMetadataFactoryInterface +{ + /** + * @param mixed $controller The controller to resolve the arguments for + * + * @return ArgumentMetadata[] + */ + public function createArgumentMetadata($controller); +} diff --git a/vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.php b/vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.php new file mode 100644 index 0000000..7b38ed5 --- /dev/null +++ b/vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DataCollector; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * AjaxDataCollector. + * + * @author Bart van den Burg + * + * @final + */ +class AjaxDataCollector extends DataCollector +{ + public function collect(Request $request, Response $response, \Throwable $exception = null) + { + // all collecting is done client side + } + + public function reset() + { + // all collecting is done client side + } + + public function getName() + { + return 'ajax'; + } +} diff --git a/vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php b/vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php new file mode 100644 index 0000000..1e435cd --- /dev/null +++ b/vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php @@ -0,0 +1,306 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DataCollector; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Component\VarDumper\Caster\ClassStub; + +/** + * @author Fabien Potencier + * + * @final + */ +class ConfigDataCollector extends DataCollector implements LateDataCollectorInterface +{ + /** + * @var KernelInterface + */ + private $kernel; + + /** + * Sets the Kernel associated with this Request. + */ + public function setKernel(KernelInterface $kernel = null) + { + $this->kernel = $kernel; + } + + /** + * {@inheritdoc} + */ + public function collect(Request $request, Response $response, \Throwable $exception = null) + { + $this->data = [ + 'token' => $response->headers->get('X-Debug-Token'), + 'symfony_version' => Kernel::VERSION, + 'symfony_state' => 'unknown', + 'env' => isset($this->kernel) ? $this->kernel->getEnvironment() : 'n/a', + 'debug' => isset($this->kernel) ? $this->kernel->isDebug() : 'n/a', + 'php_version' => PHP_VERSION, + 'php_architecture' => PHP_INT_SIZE * 8, + 'php_intl_locale' => class_exists('Locale', false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a', + 'php_timezone' => date_default_timezone_get(), + 'xdebug_enabled' => \extension_loaded('xdebug'), + 'apcu_enabled' => \extension_loaded('apcu') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN), + 'zend_opcache_enabled' => \extension_loaded('Zend OPcache') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN), + 'bundles' => [], + 'sapi_name' => \PHP_SAPI, + ]; + + if (isset($this->kernel)) { + foreach ($this->kernel->getBundles() as $name => $bundle) { + $this->data['bundles'][$name] = new ClassStub(\get_class($bundle)); + } + + $this->data['symfony_state'] = $this->determineSymfonyState(); + $this->data['symfony_minor_version'] = sprintf('%s.%s', Kernel::MAJOR_VERSION, Kernel::MINOR_VERSION); + $this->data['symfony_lts'] = 4 === Kernel::MINOR_VERSION; + $eom = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_MAINTENANCE); + $eol = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_LIFE); + $this->data['symfony_eom'] = $eom->format('F Y'); + $this->data['symfony_eol'] = $eol->format('F Y'); + } + + if (preg_match('~^(\d+(?:\.\d+)*)(.+)?$~', $this->data['php_version'], $matches) && isset($matches[2])) { + $this->data['php_version'] = $matches[1]; + $this->data['php_version_extra'] = $matches[2]; + } + } + + /** + * {@inheritdoc} + */ + public function reset() + { + $this->data = []; + } + + public function lateCollect() + { + $this->data = $this->cloneVar($this->data); + } + + /** + * Gets the token. + * + * @return string|null The token + */ + public function getToken() + { + return $this->data['token']; + } + + /** + * Gets the Symfony version. + * + * @return string The Symfony version + */ + public function getSymfonyVersion() + { + return $this->data['symfony_version']; + } + + /** + * Returns the state of the current Symfony release. + * + * @return string One of: unknown, dev, stable, eom, eol + */ + public function getSymfonyState() + { + return $this->data['symfony_state']; + } + + /** + * Returns the minor Symfony version used (without patch numbers of extra + * suffix like "RC", "beta", etc.). + * + * @return string + */ + public function getSymfonyMinorVersion() + { + return $this->data['symfony_minor_version']; + } + + /** + * Returns if the current Symfony version is a Long-Term Support one. + */ + public function isSymfonyLts(): bool + { + return $this->data['symfony_lts']; + } + + /** + * Returns the human redable date when this Symfony version ends its + * maintenance period. + * + * @return string + */ + public function getSymfonyEom() + { + return $this->data['symfony_eom']; + } + + /** + * Returns the human redable date when this Symfony version reaches its + * "end of life" and won't receive bugs or security fixes. + * + * @return string + */ + public function getSymfonyEol() + { + return $this->data['symfony_eol']; + } + + /** + * Gets the PHP version. + * + * @return string The PHP version + */ + public function getPhpVersion() + { + return $this->data['php_version']; + } + + /** + * Gets the PHP version extra part. + * + * @return string|null The extra part + */ + public function getPhpVersionExtra() + { + return isset($this->data['php_version_extra']) ? $this->data['php_version_extra'] : null; + } + + /** + * @return int The PHP architecture as number of bits (e.g. 32 or 64) + */ + public function getPhpArchitecture() + { + return $this->data['php_architecture']; + } + + /** + * @return string + */ + public function getPhpIntlLocale() + { + return $this->data['php_intl_locale']; + } + + /** + * @return string + */ + public function getPhpTimezone() + { + return $this->data['php_timezone']; + } + + /** + * Gets the environment. + * + * @return string The environment + */ + public function getEnv() + { + return $this->data['env']; + } + + /** + * Returns true if the debug is enabled. + * + * @return bool true if debug is enabled, false otherwise + */ + public function isDebug() + { + return $this->data['debug']; + } + + /** + * Returns true if the XDebug is enabled. + * + * @return bool true if XDebug is enabled, false otherwise + */ + public function hasXDebug() + { + return $this->data['xdebug_enabled']; + } + + /** + * Returns true if APCu is enabled. + * + * @return bool true if APCu is enabled, false otherwise + */ + public function hasApcu() + { + return $this->data['apcu_enabled']; + } + + /** + * Returns true if Zend OPcache is enabled. + * + * @return bool true if Zend OPcache is enabled, false otherwise + */ + public function hasZendOpcache() + { + return $this->data['zend_opcache_enabled']; + } + + public function getBundles() + { + return $this->data['bundles']; + } + + /** + * Gets the PHP SAPI name. + * + * @return string The environment + */ + public function getSapiName() + { + return $this->data['sapi_name']; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'config'; + } + + /** + * Tries to retrieve information about the current Symfony version. + * + * @return string One of: dev, stable, eom, eol + */ + private function determineSymfonyState(): string + { + $now = new \DateTime(); + $eom = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_MAINTENANCE)->modify('last day of this month'); + $eol = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_LIFE)->modify('last day of this month'); + + if ($now > $eol) { + $versionState = 'eol'; + } elseif ($now > $eom) { + $versionState = 'eom'; + } elseif ('' !== Kernel::EXTRA_VERSION) { + $versionState = 'dev'; + } else { + $versionState = 'stable'; + } + + return $versionState; + } +} diff --git a/vendor/symfony/http-kernel/DataCollector/DataCollector.php b/vendor/symfony/http-kernel/DataCollector/DataCollector.php new file mode 100644 index 0000000..ccaf66d --- /dev/null +++ b/vendor/symfony/http-kernel/DataCollector/DataCollector.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DataCollector; + +use Symfony\Component\VarDumper\Caster\CutStub; +use Symfony\Component\VarDumper\Caster\ReflectionCaster; +use Symfony\Component\VarDumper\Cloner\ClonerInterface; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Cloner\Stub; +use Symfony\Component\VarDumper\Cloner\VarCloner; + +/** + * DataCollector. + * + * Children of this class must store the collected data in the data property. + * + * @author Fabien Potencier + * @author Bernhard Schussek + */ +abstract class DataCollector implements DataCollectorInterface +{ + /** + * @var array|Data + */ + protected $data = []; + + /** + * @var ClonerInterface + */ + private $cloner; + + /** + * Converts the variable into a serializable Data instance. + * + * This array can be displayed in the template using + * the VarDumper component. + * + * @param mixed $var + * + * @return Data + */ + protected function cloneVar($var) + { + if ($var instanceof Data) { + return $var; + } + if (null === $this->cloner) { + $this->cloner = new VarCloner(); + $this->cloner->setMaxItems(-1); + $this->cloner->addCasters($this->getCasters()); + } + + return $this->cloner->cloneVar($var); + } + + /** + * @return callable[] The casters to add to the cloner + */ + protected function getCasters() + { + $casters = [ + '*' => function ($v, array $a, Stub $s, $isNested) { + if (!$v instanceof Stub) { + foreach ($a as $k => $v) { + if (\is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) { + $a[$k] = new CutStub($v); + } + } + } + + return $a; + }, + ] + ReflectionCaster::UNSET_CLOSURE_FILE_INFO; + + return $casters; + } + + /** + * @return array + */ + public function __sleep() + { + return ['data']; + } + + public function __wakeup() + { + } + + /** + * @internal to prevent implementing \Serializable + */ + final protected function serialize() + { + } + + /** + * @internal to prevent implementing \Serializable + */ + final protected function unserialize($data) + { + } +} diff --git a/vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php b/vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php new file mode 100644 index 0000000..30ab7cc --- /dev/null +++ b/vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DataCollector; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Contracts\Service\ResetInterface; + +/** + * DataCollectorInterface. + * + * @author Fabien Potencier + */ +interface DataCollectorInterface extends ResetInterface +{ + /** + * Collects data for the given Request and Response. + */ + public function collect(Request $request, Response $response, \Throwable $exception = null); + + /** + * Returns the name of the collector. + * + * @return string The collector name + */ + public function getName(); +} diff --git a/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php b/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php new file mode 100644 index 0000000..b3288b5 --- /dev/null +++ b/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php @@ -0,0 +1,290 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DataCollector; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Dumper\CliDumper; +use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; +use Symfony\Component\VarDumper\Dumper\DataDumperInterface; +use Symfony\Component\VarDumper\Dumper\HtmlDumper; +use Symfony\Component\VarDumper\Server\Connection; + +/** + * @author Nicolas Grekas + * + * @final + */ +class DumpDataCollector extends DataCollector implements DataDumperInterface +{ + private $stopwatch; + private $fileLinkFormat; + private $dataCount = 0; + private $isCollected = true; + private $clonesCount = 0; + private $clonesIndex = 0; + private $rootRefs; + private $charset; + private $requestStack; + private $dumper; + private $sourceContextProvider; + + /** + * @param DataDumperInterface|Connection|null $dumper + */ + public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, string $charset = null, RequestStack $requestStack = null, $dumper = null) + { + $this->stopwatch = $stopwatch; + $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + $this->charset = $charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8'; + $this->requestStack = $requestStack; + $this->dumper = $dumper; + + // All clones share these properties by reference: + $this->rootRefs = [ + &$this->data, + &$this->dataCount, + &$this->isCollected, + &$this->clonesCount, + ]; + + $this->sourceContextProvider = $dumper instanceof Connection && isset($dumper->getContextProviders()['source']) ? $dumper->getContextProviders()['source'] : new SourceContextProvider($this->charset); + } + + public function __clone() + { + $this->clonesIndex = ++$this->clonesCount; + } + + public function dump(Data $data) + { + if ($this->stopwatch) { + $this->stopwatch->start('dump'); + } + + list('name' => $name, 'file' => $file, 'line' => $line, 'file_excerpt' => $fileExcerpt) = $this->sourceContextProvider->getContext(); + + if ($this->dumper instanceof Connection) { + if (!$this->dumper->write($data)) { + $this->isCollected = false; + } + } elseif ($this->dumper) { + $this->doDump($this->dumper, $data, $name, $file, $line); + } else { + $this->isCollected = false; + } + + if (!$this->dataCount) { + $this->data = []; + } + $this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt'); + ++$this->dataCount; + + if ($this->stopwatch) { + $this->stopwatch->stop('dump'); + } + } + + public function collect(Request $request, Response $response, \Throwable $exception = null) + { + if (!$this->dataCount) { + $this->data = []; + } + + // Sub-requests and programmatic calls stay in the collected profile. + if ($this->dumper || ($this->requestStack && $this->requestStack->getMasterRequest() !== $request) || $request->isXmlHttpRequest() || $request->headers->has('Origin')) { + return; + } + + // In all other conditions that remove the web debug toolbar, dumps are written on the output. + if (!$this->requestStack + || !$response->headers->has('X-Debug-Token') + || $response->isRedirection() + || ($response->headers->has('Content-Type') && false === strpos($response->headers->get('Content-Type'), 'html')) + || 'html' !== $request->getRequestFormat() + || false === strripos($response->getContent(), '') + ) { + if ($response->headers->has('Content-Type') && false !== strpos($response->headers->get('Content-Type'), 'html')) { + $dumper = new HtmlDumper('php://output', $this->charset); + $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); + } else { + $dumper = new CliDumper('php://output', $this->charset); + if (method_exists($dumper, 'setDisplayOptions')) { + $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); + } + } + + foreach ($this->data as $dump) { + $this->doDump($dumper, $dump['data'], $dump['name'], $dump['file'], $dump['line']); + } + } + } + + public function reset() + { + if ($this->stopwatch) { + $this->stopwatch->reset(); + } + $this->data = []; + $this->dataCount = 0; + $this->isCollected = true; + $this->clonesCount = 0; + $this->clonesIndex = 0; + } + + /** + * @internal + */ + public function __sleep(): array + { + if (!$this->dataCount) { + $this->data = []; + } + + if ($this->clonesCount !== $this->clonesIndex) { + return []; + } + + $this->data[] = $this->fileLinkFormat; + $this->data[] = $this->charset; + $this->dataCount = 0; + $this->isCollected = true; + + return parent::__sleep(); + } + + /** + * @internal + */ + public function __wakeup() + { + parent::__wakeup(); + + $charset = array_pop($this->data); + $fileLinkFormat = array_pop($this->data); + $this->dataCount = \count($this->data); + + self::__construct($this->stopwatch, $fileLinkFormat, $charset); + } + + public function getDumpsCount(): int + { + return $this->dataCount; + } + + public function getDumps($format, $maxDepthLimit = -1, $maxItemsPerDepth = -1): array + { + $data = fopen('php://memory', 'r+b'); + + if ('html' === $format) { + $dumper = new HtmlDumper($data, $this->charset); + $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); + } else { + throw new \InvalidArgumentException(sprintf('Invalid dump format: %s', $format)); + } + $dumps = []; + + if (!$this->dataCount) { + return $this->data = []; + } + + foreach ($this->data as $dump) { + $dumper->dump($dump['data']->withMaxDepth($maxDepthLimit)->withMaxItemsPerDepth($maxItemsPerDepth)); + $dump['data'] = stream_get_contents($data, -1, 0); + ftruncate($data, 0); + rewind($data); + $dumps[] = $dump; + } + + return $dumps; + } + + public function getName(): string + { + return 'dump'; + } + + public function __destruct() + { + if (0 === $this->clonesCount-- && !$this->isCollected && $this->dataCount) { + $this->clonesCount = 0; + $this->isCollected = true; + + $h = headers_list(); + $i = \count($h); + array_unshift($h, 'Content-Type: '.ini_get('default_mimetype')); + while (0 !== stripos($h[$i], 'Content-Type:')) { + --$i; + } + + if (isset($_SERVER['VAR_DUMPER_FORMAT'])) { + $html = 'html' === $_SERVER['VAR_DUMPER_FORMAT']; + } else { + $html = !\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && stripos($h[$i], 'html'); + } + + if ($html) { + $dumper = new HtmlDumper('php://output', $this->charset); + $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); + } else { + $dumper = new CliDumper('php://output', $this->charset); + if (method_exists($dumper, 'setDisplayOptions')) { + $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); + } + } + + foreach ($this->data as $i => $dump) { + $this->data[$i] = null; + $this->doDump($dumper, $dump['data'], $dump['name'], $dump['file'], $dump['line']); + } + + $this->data = []; + $this->dataCount = 0; + } + } + + private function doDump(DataDumperInterface $dumper, $data, string $name, string $file, int $line) + { + if ($dumper instanceof CliDumper) { + $contextDumper = function ($name, $file, $line, $fmt) { + if ($this instanceof HtmlDumper) { + if ($file) { + $s = $this->style('meta', '%s'); + $f = strip_tags($this->style('', $file)); + $name = strip_tags($this->style('', $name)); + if ($fmt && $link = \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line)) { + $name = sprintf(''.$s.'', strip_tags($this->style('', $link)), $f, $name); + } else { + $name = sprintf(''.$s.'', $f, $name); + } + } else { + $name = $this->style('meta', $name); + } + $this->line = $name.' on line '.$this->style('meta', $line).':'; + } else { + $this->line = $this->style('meta', $name).' on line '.$this->style('meta', $line).':'; + } + $this->dumpLine(0); + }; + $contextDumper = $contextDumper->bindTo($dumper, $dumper); + $contextDumper($name, $file, $line, $this->fileLinkFormat); + } else { + $cloner = new VarCloner(); + $dumper->dump($cloner->cloneVar($name.' on line '.$line.':')); + } + $dumper->dump($data); + } +} diff --git a/vendor/symfony/http-kernel/DataCollector/EventDataCollector.php b/vendor/symfony/http-kernel/DataCollector/EventDataCollector.php new file mode 100644 index 0000000..27930fe --- /dev/null +++ b/vendor/symfony/http-kernel/DataCollector/EventDataCollector.php @@ -0,0 +1,150 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DataCollector; + +use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\Service\ResetInterface; + +/** + * EventDataCollector. + * + * @author Fabien Potencier + * + * @final + */ +class EventDataCollector extends DataCollector implements LateDataCollectorInterface +{ + protected $dispatcher; + private $requestStack; + private $currentRequest; + + public function __construct(EventDispatcherInterface $dispatcher = null, RequestStack $requestStack = null) + { + $this->dispatcher = $dispatcher; + $this->requestStack = $requestStack; + } + + /** + * {@inheritdoc} + */ + public function collect(Request $request, Response $response, \Throwable $exception = null) + { + $this->currentRequest = $this->requestStack && $this->requestStack->getMasterRequest() !== $request ? $request : null; + $this->data = [ + 'called_listeners' => [], + 'not_called_listeners' => [], + 'orphaned_events' => [], + ]; + } + + public function reset() + { + $this->data = []; + + if ($this->dispatcher instanceof ResetInterface) { + $this->dispatcher->reset(); + } + } + + public function lateCollect() + { + if ($this->dispatcher instanceof TraceableEventDispatcher) { + $this->setCalledListeners($this->dispatcher->getCalledListeners($this->currentRequest)); + $this->setNotCalledListeners($this->dispatcher->getNotCalledListeners($this->currentRequest)); + $this->setOrphanedEvents($this->dispatcher->getOrphanedEvents($this->currentRequest)); + } + + $this->data = $this->cloneVar($this->data); + } + + /** + * Sets the called listeners. + * + * @param array $listeners An array of called listeners + * + * @see TraceableEventDispatcher + */ + public function setCalledListeners(array $listeners) + { + $this->data['called_listeners'] = $listeners; + } + + /** + * Gets the called listeners. + * + * @return array An array of called listeners + * + * @see TraceableEventDispatcher + */ + public function getCalledListeners() + { + return $this->data['called_listeners']; + } + + /** + * Sets the not called listeners. + * + * @see TraceableEventDispatcher + */ + public function setNotCalledListeners(array $listeners) + { + $this->data['not_called_listeners'] = $listeners; + } + + /** + * Gets the not called listeners. + * + * @return array + * + * @see TraceableEventDispatcher + */ + public function getNotCalledListeners() + { + return $this->data['not_called_listeners']; + } + + /** + * Sets the orphaned events. + * + * @param array $events An array of orphaned events + * + * @see TraceableEventDispatcher + */ + public function setOrphanedEvents(array $events) + { + $this->data['orphaned_events'] = $events; + } + + /** + * Gets the orphaned events. + * + * @return array An array of orphaned events + * + * @see TraceableEventDispatcher + */ + public function getOrphanedEvents() + { + return $this->data['orphaned_events']; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'events'; + } +} diff --git a/vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php b/vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php new file mode 100644 index 0000000..5ff13f7 --- /dev/null +++ b/vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DataCollector; + +use Symfony\Component\ErrorHandler\Exception\FlattenException; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * ExceptionDataCollector. + * + * @author Fabien Potencier + * + * @final + */ +class ExceptionDataCollector extends DataCollector +{ + /** + * {@inheritdoc} + */ + public function collect(Request $request, Response $response, \Throwable $exception = null) + { + if (null !== $exception) { + $this->data = [ + 'exception' => FlattenException::createFromThrowable($exception), + ]; + } + } + + /** + * {@inheritdoc} + */ + public function reset() + { + $this->data = []; + } + + /** + * Checks if the exception is not null. + * + * @return bool true if the exception is not null, false otherwise + */ + public function hasException() + { + return isset($this->data['exception']); + } + + /** + * Gets the exception. + * + * @return \Exception|FlattenException + */ + public function getException() + { + return $this->data['exception']; + } + + /** + * Gets the exception message. + * + * @return string The exception message + */ + public function getMessage() + { + return $this->data['exception']->getMessage(); + } + + /** + * Gets the exception code. + * + * @return int The exception code + */ + public function getCode() + { + return $this->data['exception']->getCode(); + } + + /** + * Gets the status code. + * + * @return int The status code + */ + public function getStatusCode() + { + return $this->data['exception']->getStatusCode(); + } + + /** + * Gets the exception trace. + * + * @return array The exception trace + */ + public function getTrace() + { + return $this->data['exception']->getTrace(); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'exception'; + } +} diff --git a/vendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php b/vendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php new file mode 100644 index 0000000..012332d --- /dev/null +++ b/vendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DataCollector; + +/** + * LateDataCollectorInterface. + * + * @author Fabien Potencier + */ +interface LateDataCollectorInterface +{ + /** + * Collects data as late as possible. + */ + public function lateCollect(); +} diff --git a/vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php b/vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php new file mode 100644 index 0000000..f8dc885 --- /dev/null +++ b/vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php @@ -0,0 +1,282 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DataCollector; + +use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; + +/** + * LogDataCollector. + * + * @author Fabien Potencier + * + * @final + */ +class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface +{ + private $logger; + private $containerPathPrefix; + private $currentRequest; + private $requestStack; + + public function __construct($logger = null, string $containerPathPrefix = null, RequestStack $requestStack = null) + { + if (null !== $logger && $logger instanceof DebugLoggerInterface) { + $this->logger = $logger; + } + + $this->containerPathPrefix = $containerPathPrefix; + $this->requestStack = $requestStack; + } + + /** + * {@inheritdoc} + */ + public function collect(Request $request, Response $response, \Throwable $exception = null) + { + $this->currentRequest = $this->requestStack && $this->requestStack->getMasterRequest() !== $request ? $request : null; + } + + /** + * {@inheritdoc} + */ + public function reset() + { + if ($this->logger instanceof DebugLoggerInterface) { + $this->logger->clear(); + } + $this->data = []; + } + + /** + * {@inheritdoc} + */ + public function lateCollect() + { + if (null !== $this->logger) { + $containerDeprecationLogs = $this->getContainerDeprecationLogs(); + $this->data = $this->computeErrorsCount($containerDeprecationLogs); + // get compiler logs later (only when they are needed) to improve performance + $this->data['compiler_logs'] = []; + $this->data['compiler_logs_filepath'] = $this->containerPathPrefix.'Compiler.log'; + $this->data['logs'] = $this->sanitizeLogs(array_merge($this->logger->getLogs($this->currentRequest), $containerDeprecationLogs)); + $this->data = $this->cloneVar($this->data); + } + $this->currentRequest = null; + } + + public function getLogs() + { + return isset($this->data['logs']) ? $this->data['logs'] : []; + } + + public function getPriorities() + { + return isset($this->data['priorities']) ? $this->data['priorities'] : []; + } + + public function countErrors() + { + return isset($this->data['error_count']) ? $this->data['error_count'] : 0; + } + + public function countDeprecations() + { + return isset($this->data['deprecation_count']) ? $this->data['deprecation_count'] : 0; + } + + public function countWarnings() + { + return isset($this->data['warning_count']) ? $this->data['warning_count'] : 0; + } + + public function countScreams() + { + return isset($this->data['scream_count']) ? $this->data['scream_count'] : 0; + } + + public function getCompilerLogs() + { + return $this->cloneVar($this->getContainerCompilerLogs($this->data['compiler_logs_filepath'] ?? null)); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'logger'; + } + + private function getContainerDeprecationLogs(): array + { + if (null === $this->containerPathPrefix || !file_exists($file = $this->containerPathPrefix.'Deprecations.log')) { + return []; + } + + if ('' === $logContent = trim(file_get_contents($file))) { + return []; + } + + $bootTime = filemtime($file); + $logs = []; + foreach (unserialize($logContent) as $log) { + $log['context'] = ['exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'], $log['trace'], $log['count'])]; + $log['timestamp'] = $bootTime; + $log['priority'] = 100; + $log['priorityName'] = 'DEBUG'; + $log['channel'] = null; + $log['scream'] = false; + unset($log['type'], $log['file'], $log['line'], $log['trace'], $log['trace'], $log['count']); + $logs[] = $log; + } + + return $logs; + } + + private function getContainerCompilerLogs(string $compilerLogsFilepath = null): array + { + if (!file_exists($compilerLogsFilepath)) { + return []; + } + + $logs = []; + foreach (file($compilerLogsFilepath, FILE_IGNORE_NEW_LINES) as $log) { + $log = explode(': ', $log, 2); + if (!isset($log[1]) || !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $log[0])) { + $log = ['Unknown Compiler Pass', implode(': ', $log)]; + } + + $logs[$log[0]][] = ['message' => $log[1]]; + } + + return $logs; + } + + private function sanitizeLogs(array $logs) + { + $sanitizedLogs = []; + $silencedLogs = []; + + foreach ($logs as $log) { + if (!$this->isSilencedOrDeprecationErrorLog($log)) { + $sanitizedLogs[] = $log; + + continue; + } + + $message = $log['message']; + $exception = $log['context']['exception']; + + if ($exception instanceof SilencedErrorContext) { + if (isset($silencedLogs[$h = spl_object_hash($exception)])) { + continue; + } + $silencedLogs[$h] = true; + + if (!isset($sanitizedLogs[$message])) { + $sanitizedLogs[$message] = $log + [ + 'errorCount' => 0, + 'scream' => true, + ]; + } + $sanitizedLogs[$message]['errorCount'] += $exception->count; + + continue; + } + + $errorId = md5("{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}\0{$message}", true); + + if (isset($sanitizedLogs[$errorId])) { + ++$sanitizedLogs[$errorId]['errorCount']; + } else { + $log += [ + 'errorCount' => 1, + 'scream' => false, + ]; + + $sanitizedLogs[$errorId] = $log; + } + } + + return array_values($sanitizedLogs); + } + + private function isSilencedOrDeprecationErrorLog(array $log): bool + { + if (!isset($log['context']['exception'])) { + return false; + } + + $exception = $log['context']['exception']; + + if ($exception instanceof SilencedErrorContext) { + return true; + } + + if ($exception instanceof \ErrorException && \in_array($exception->getSeverity(), [E_DEPRECATED, E_USER_DEPRECATED], true)) { + return true; + } + + return false; + } + + private function computeErrorsCount(array $containerDeprecationLogs): array + { + $silencedLogs = []; + $count = [ + 'error_count' => $this->logger->countErrors($this->currentRequest), + 'deprecation_count' => 0, + 'warning_count' => 0, + 'scream_count' => 0, + 'priorities' => [], + ]; + + foreach ($this->logger->getLogs($this->currentRequest) as $log) { + if (isset($count['priorities'][$log['priority']])) { + ++$count['priorities'][$log['priority']]['count']; + } else { + $count['priorities'][$log['priority']] = [ + 'count' => 1, + 'name' => $log['priorityName'], + ]; + } + if ('WARNING' === $log['priorityName']) { + ++$count['warning_count']; + } + + if ($this->isSilencedOrDeprecationErrorLog($log)) { + $exception = $log['context']['exception']; + if ($exception instanceof SilencedErrorContext) { + if (isset($silencedLogs[$h = spl_object_hash($exception)])) { + continue; + } + $silencedLogs[$h] = true; + $count['scream_count'] += $exception->count; + } else { + ++$count['deprecation_count']; + } + } + } + + foreach ($containerDeprecationLogs as $deprecationLog) { + $count['deprecation_count'] += $deprecationLog['context']['exception']->count; + } + + ksort($count['priorities']); + + return $count; + } +} diff --git a/vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php b/vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php new file mode 100644 index 0000000..3730212 --- /dev/null +++ b/vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DataCollector; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * MemoryDataCollector. + * + * @author Fabien Potencier + * + * @final + */ +class MemoryDataCollector extends DataCollector implements LateDataCollectorInterface +{ + public function __construct() + { + $this->reset(); + } + + /** + * {@inheritdoc} + */ + public function collect(Request $request, Response $response, \Throwable $exception = null) + { + $this->updateMemoryUsage(); + } + + /** + * {@inheritdoc} + */ + public function reset() + { + $this->data = [ + 'memory' => 0, + 'memory_limit' => $this->convertToBytes(ini_get('memory_limit')), + ]; + } + + /** + * {@inheritdoc} + */ + public function lateCollect() + { + $this->updateMemoryUsage(); + } + + /** + * Gets the memory. + * + * @return int The memory + */ + public function getMemory() + { + return $this->data['memory']; + } + + /** + * Gets the PHP memory limit. + * + * @return int The memory limit + */ + public function getMemoryLimit() + { + return $this->data['memory_limit']; + } + + /** + * Updates the memory usage data. + */ + public function updateMemoryUsage() + { + $this->data['memory'] = memory_get_peak_usage(true); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'memory'; + } + + /** + * @return int|float + */ + private function convertToBytes(string $memoryLimit) + { + if ('-1' === $memoryLimit) { + return -1; + } + + $memoryLimit = strtolower($memoryLimit); + $max = strtolower(ltrim($memoryLimit, '+')); + if (0 === strpos($max, '0x')) { + $max = \intval($max, 16); + } elseif (0 === strpos($max, '0')) { + $max = \intval($max, 8); + } else { + $max = (int) $max; + } + + switch (substr($memoryLimit, -1)) { + case 't': $max *= 1024; + // no break + case 'g': $max *= 1024; + // no break + case 'm': $max *= 1024; + // no break + case 'k': $max *= 1024; + } + + return $max; + } +} diff --git a/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php b/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php new file mode 100644 index 0000000..9585c13 --- /dev/null +++ b/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php @@ -0,0 +1,458 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DataCollector; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\ParameterBag; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\ControllerEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * @author Fabien Potencier + * + * @final + */ +class RequestDataCollector extends DataCollector implements EventSubscriberInterface, LateDataCollectorInterface +{ + protected $controllers; + + public function __construct() + { + $this->controllers = new \SplObjectStorage(); + } + + /** + * {@inheritdoc} + */ + public function collect(Request $request, Response $response, \Throwable $exception = null) + { + // attributes are serialized and as they can be anything, they need to be converted to strings. + $attributes = []; + $route = ''; + foreach ($request->attributes->all() as $key => $value) { + if ('_route' === $key) { + $route = \is_object($value) ? $value->getPath() : $value; + $attributes[$key] = $route; + } else { + $attributes[$key] = $value; + } + } + + try { + $content = $request->getContent(); + } catch (\LogicException $e) { + // the user already got the request content as a resource + $content = false; + } + + $sessionMetadata = []; + $sessionAttributes = []; + $flashes = []; + if ($request->hasSession()) { + $session = $request->getSession(); + if ($session->isStarted()) { + $sessionMetadata['Created'] = date(DATE_RFC822, $session->getMetadataBag()->getCreated()); + $sessionMetadata['Last used'] = date(DATE_RFC822, $session->getMetadataBag()->getLastUsed()); + $sessionMetadata['Lifetime'] = $session->getMetadataBag()->getLifetime(); + $sessionAttributes = $session->all(); + $flashes = $session->getFlashBag()->peekAll(); + } + } + + $statusCode = $response->getStatusCode(); + + $responseCookies = []; + foreach ($response->headers->getCookies() as $cookie) { + $responseCookies[$cookie->getName()] = $cookie; + } + + $dotenvVars = []; + foreach (explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? $_ENV['SYMFONY_DOTENV_VARS'] ?? '') as $name) { + if ('' !== $name && isset($_ENV[$name])) { + $dotenvVars[$name] = $_ENV[$name]; + } + } + + $this->data = [ + 'method' => $request->getMethod(), + 'format' => $request->getRequestFormat(), + 'content' => $content, + 'content_type' => $response->headers->get('Content-Type', 'text/html'), + 'status_text' => isset(Response::$statusTexts[$statusCode]) ? Response::$statusTexts[$statusCode] : '', + 'status_code' => $statusCode, + 'request_query' => $request->query->all(), + 'request_request' => $request->request->all(), + 'request_files' => $request->files->all(), + 'request_headers' => $request->headers->all(), + 'request_server' => $request->server->all(), + 'request_cookies' => $request->cookies->all(), + 'request_attributes' => $attributes, + 'route' => $route, + 'response_headers' => $response->headers->all(), + 'response_cookies' => $responseCookies, + 'session_metadata' => $sessionMetadata, + 'session_attributes' => $sessionAttributes, + 'flashes' => $flashes, + 'path_info' => $request->getPathInfo(), + 'controller' => 'n/a', + 'locale' => $request->getLocale(), + 'dotenv_vars' => $dotenvVars, + ]; + + if (isset($this->data['request_headers']['php-auth-pw'])) { + $this->data['request_headers']['php-auth-pw'] = '******'; + } + + if (isset($this->data['request_server']['PHP_AUTH_PW'])) { + $this->data['request_server']['PHP_AUTH_PW'] = '******'; + } + + if (isset($this->data['request_request']['_password'])) { + $this->data['request_request']['_password'] = '******'; + } + + foreach ($this->data as $key => $value) { + if (!\is_array($value)) { + continue; + } + if ('request_headers' === $key || 'response_headers' === $key) { + $this->data[$key] = array_map(function ($v) { return isset($v[0]) && !isset($v[1]) ? $v[0] : $v; }, $value); + } + } + + if (isset($this->controllers[$request])) { + $this->data['controller'] = $this->parseController($this->controllers[$request]); + unset($this->controllers[$request]); + } + + if ($request->attributes->has('_redirected') && $redirectCookie = $request->cookies->get('sf_redirect')) { + $this->data['redirect'] = json_decode($redirectCookie, true); + + $response->headers->clearCookie('sf_redirect'); + } + + if ($response->isRedirect()) { + $response->headers->setCookie(new Cookie( + 'sf_redirect', + json_encode([ + 'token' => $response->headers->get('x-debug-token'), + 'route' => $request->attributes->get('_route', 'n/a'), + 'method' => $request->getMethod(), + 'controller' => $this->parseController($request->attributes->get('_controller')), + 'status_code' => $statusCode, + 'status_text' => Response::$statusTexts[(int) $statusCode], + ]), + 0, '/', null, $request->isSecure(), true, false, 'lax' + )); + } + + $this->data['identifier'] = $this->data['route'] ?: (\is_array($this->data['controller']) ? $this->data['controller']['class'].'::'.$this->data['controller']['method'].'()' : $this->data['controller']); + + if ($response->headers->has('x-previous-debug-token')) { + $this->data['forward_token'] = $response->headers->get('x-previous-debug-token'); + } + } + + public function lateCollect() + { + $this->data = $this->cloneVar($this->data); + } + + public function reset() + { + $this->data = []; + $this->controllers = new \SplObjectStorage(); + } + + public function getMethod() + { + return $this->data['method']; + } + + public function getPathInfo() + { + return $this->data['path_info']; + } + + public function getRequestRequest() + { + return new ParameterBag($this->data['request_request']->getValue()); + } + + public function getRequestQuery() + { + return new ParameterBag($this->data['request_query']->getValue()); + } + + public function getRequestFiles() + { + return new ParameterBag($this->data['request_files']->getValue()); + } + + public function getRequestHeaders() + { + return new ParameterBag($this->data['request_headers']->getValue()); + } + + public function getRequestServer($raw = false) + { + return new ParameterBag($this->data['request_server']->getValue($raw)); + } + + public function getRequestCookies($raw = false) + { + return new ParameterBag($this->data['request_cookies']->getValue($raw)); + } + + public function getRequestAttributes() + { + return new ParameterBag($this->data['request_attributes']->getValue()); + } + + public function getResponseHeaders() + { + return new ParameterBag($this->data['response_headers']->getValue()); + } + + public function getResponseCookies() + { + return new ParameterBag($this->data['response_cookies']->getValue()); + } + + public function getSessionMetadata() + { + return $this->data['session_metadata']->getValue(); + } + + public function getSessionAttributes() + { + return $this->data['session_attributes']->getValue(); + } + + public function getFlashes() + { + return $this->data['flashes']->getValue(); + } + + public function getContent() + { + return $this->data['content']; + } + + public function isJsonRequest() + { + return 1 === preg_match('{^application/(?:\w+\++)*json$}i', $this->data['request_headers']['content-type']); + } + + public function getPrettyJson() + { + $decoded = json_decode($this->getContent()); + + return JSON_ERROR_NONE === json_last_error() ? json_encode($decoded, JSON_PRETTY_PRINT) : null; + } + + public function getContentType() + { + return $this->data['content_type']; + } + + public function getStatusText() + { + return $this->data['status_text']; + } + + public function getStatusCode() + { + return $this->data['status_code']; + } + + public function getFormat() + { + return $this->data['format']; + } + + public function getLocale() + { + return $this->data['locale']; + } + + public function getDotenvVars() + { + return new ParameterBag($this->data['dotenv_vars']->getValue()); + } + + /** + * Gets the route name. + * + * The _route request attributes is automatically set by the Router Matcher. + * + * @return string The route + */ + public function getRoute() + { + return $this->data['route']; + } + + public function getIdentifier() + { + return $this->data['identifier']; + } + + /** + * Gets the route parameters. + * + * The _route_params request attributes is automatically set by the RouterListener. + * + * @return array The parameters + */ + public function getRouteParams() + { + return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params']->getValue() : []; + } + + /** + * Gets the parsed controller. + * + * @return array|string The controller as a string or array of data + * with keys 'class', 'method', 'file' and 'line' + */ + public function getController() + { + return $this->data['controller']; + } + + /** + * Gets the previous request attributes. + * + * @return array|bool A legacy array of data from the previous redirection response + * or false otherwise + */ + public function getRedirect() + { + return isset($this->data['redirect']) ? $this->data['redirect'] : false; + } + + public function getForwardToken() + { + return isset($this->data['forward_token']) ? $this->data['forward_token'] : null; + } + + public function onKernelController(ControllerEvent $event) + { + $this->controllers[$event->getRequest()] = $event->getController(); + } + + public function onKernelResponse(ResponseEvent $event) + { + if (!$event->isMasterRequest()) { + return; + } + + if ($event->getRequest()->cookies->has('sf_redirect')) { + $event->getRequest()->attributes->set('_redirected', true); + } + } + + public static function getSubscribedEvents() + { + return [ + KernelEvents::CONTROLLER => 'onKernelController', + KernelEvents::RESPONSE => 'onKernelResponse', + ]; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'request'; + } + + /** + * Parse a controller. + * + * @param mixed $controller The controller to parse + * + * @return array|string An array of controller data or a simple string + */ + protected function parseController($controller) + { + if (\is_string($controller) && false !== strpos($controller, '::')) { + $controller = explode('::', $controller); + } + + if (\is_array($controller)) { + try { + $r = new \ReflectionMethod($controller[0], $controller[1]); + + return [ + 'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0], + 'method' => $controller[1], + 'file' => $r->getFileName(), + 'line' => $r->getStartLine(), + ]; + } catch (\ReflectionException $e) { + if (\is_callable($controller)) { + // using __call or __callStatic + return [ + 'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0], + 'method' => $controller[1], + 'file' => 'n/a', + 'line' => 'n/a', + ]; + } + } + } + + if ($controller instanceof \Closure) { + $r = new \ReflectionFunction($controller); + + $controller = [ + 'class' => $r->getName(), + 'method' => null, + 'file' => $r->getFileName(), + 'line' => $r->getStartLine(), + ]; + + if (false !== strpos($r->name, '{closure}')) { + return $controller; + } + $controller['method'] = $r->name; + + if ($class = $r->getClosureScopeClass()) { + $controller['class'] = $class->name; + } else { + return $r->name; + } + + return $controller; + } + + if (\is_object($controller)) { + $r = new \ReflectionClass($controller); + + return [ + 'class' => $r->getName(), + 'method' => null, + 'file' => $r->getFileName(), + 'line' => $r->getStartLine(), + ]; + } + + return \is_string($controller) ? $controller : 'n/a'; + } +} diff --git a/vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php b/vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php new file mode 100644 index 0000000..5ed6970 --- /dev/null +++ b/vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DataCollector; + +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\ControllerEvent; + +/** + * @author Fabien Potencier + */ +class RouterDataCollector extends DataCollector +{ + /** + * @var \SplObjectStorage + */ + protected $controllers; + + public function __construct() + { + $this->reset(); + } + + /** + * {@inheritdoc} + * + * @final + */ + public function collect(Request $request, Response $response, \Throwable $exception = null) + { + if ($response instanceof RedirectResponse) { + $this->data['redirect'] = true; + $this->data['url'] = $response->getTargetUrl(); + + if ($this->controllers->contains($request)) { + $this->data['route'] = $this->guessRoute($request, $this->controllers[$request]); + } + } + + unset($this->controllers[$request]); + } + + public function reset() + { + $this->controllers = new \SplObjectStorage(); + + $this->data = [ + 'redirect' => false, + 'url' => null, + 'route' => null, + ]; + } + + protected function guessRoute(Request $request, $controller) + { + return 'n/a'; + } + + /** + * Remembers the controller associated to each request. + */ + public function onKernelController(ControllerEvent $event) + { + $this->controllers[$event->getRequest()] = $event->getController(); + } + + /** + * @return bool Whether this request will result in a redirect + */ + public function getRedirect() + { + return $this->data['redirect']; + } + + /** + * @return string|null The target URL + */ + public function getTargetUrl() + { + return $this->data['url']; + } + + /** + * @return string|null The target route + */ + public function getTargetRoute() + { + return $this->data['route']; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'router'; + } +} diff --git a/vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php b/vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php new file mode 100644 index 0000000..4e95603 --- /dev/null +++ b/vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php @@ -0,0 +1,159 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DataCollector; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\Stopwatch\StopwatchEvent; + +/** + * @author Fabien Potencier + * + * @final + */ +class TimeDataCollector extends DataCollector implements LateDataCollectorInterface +{ + protected $kernel; + protected $stopwatch; + + public function __construct(KernelInterface $kernel = null, Stopwatch $stopwatch = null) + { + $this->kernel = $kernel; + $this->stopwatch = $stopwatch; + } + + /** + * {@inheritdoc} + */ + public function collect(Request $request, Response $response, \Throwable $exception = null) + { + if (null !== $this->kernel) { + $startTime = $this->kernel->getStartTime(); + } else { + $startTime = $request->server->get('REQUEST_TIME_FLOAT'); + } + + $this->data = [ + 'token' => $response->headers->get('X-Debug-Token'), + 'start_time' => $startTime * 1000, + 'events' => [], + 'stopwatch_installed' => class_exists(Stopwatch::class, false), + ]; + } + + /** + * {@inheritdoc} + */ + public function reset() + { + $this->data = []; + + if (null !== $this->stopwatch) { + $this->stopwatch->reset(); + } + } + + /** + * {@inheritdoc} + */ + public function lateCollect() + { + if (null !== $this->stopwatch && isset($this->data['token'])) { + $this->setEvents($this->stopwatch->getSectionEvents($this->data['token'])); + } + unset($this->data['token']); + } + + /** + * Sets the request events. + * + * @param StopwatchEvent[] $events The request events + */ + public function setEvents(array $events) + { + foreach ($events as $event) { + $event->ensureStopped(); + } + + $this->data['events'] = $events; + } + + /** + * Gets the request events. + * + * @return StopwatchEvent[] The request events + */ + public function getEvents() + { + return $this->data['events']; + } + + /** + * Gets the request elapsed time. + * + * @return float The elapsed time + */ + public function getDuration() + { + if (!isset($this->data['events']['__section__'])) { + return 0; + } + + $lastEvent = $this->data['events']['__section__']; + + return $lastEvent->getOrigin() + $lastEvent->getDuration() - $this->getStartTime(); + } + + /** + * Gets the initialization time. + * + * This is the time spent until the beginning of the request handling. + * + * @return float The elapsed time + */ + public function getInitTime() + { + if (!isset($this->data['events']['__section__'])) { + return 0; + } + + return $this->data['events']['__section__']->getOrigin() - $this->getStartTime(); + } + + /** + * Gets the request time. + * + * @return float + */ + public function getStartTime() + { + return $this->data['start_time']; + } + + /** + * @return bool whether or not the stopwatch component is installed + */ + public function isStopwatchInstalled() + { + return $this->data['stopwatch_installed']; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'time'; + } +} diff --git a/vendor/symfony/http-kernel/Debug/FileLinkFormatter.php b/vendor/symfony/http-kernel/Debug/FileLinkFormatter.php new file mode 100644 index 0000000..74abb81 --- /dev/null +++ b/vendor/symfony/http-kernel/Debug/FileLinkFormatter.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Debug; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; + +/** + * Formats debug file links. + * + * @author Jérémy Romey + * + * @final + */ +class FileLinkFormatter +{ + private $fileLinkFormat; + private $requestStack; + private $baseDir; + private $urlFormat; + + /** + * @param string|\Closure $urlFormat the URL format, or a closure that returns it on-demand + */ + public function __construct($fileLinkFormat = null, RequestStack $requestStack = null, string $baseDir = null, $urlFormat = null) + { + $fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + if ($fileLinkFormat && !\is_array($fileLinkFormat)) { + $i = strpos($f = $fileLinkFormat, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: \strlen($f); + $fileLinkFormat = [substr($f, 0, $i)] + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE); + } + + $this->fileLinkFormat = $fileLinkFormat; + $this->requestStack = $requestStack; + $this->baseDir = $baseDir; + $this->urlFormat = $urlFormat; + } + + public function format(string $file, int $line) + { + if ($fmt = $this->getFileLinkFormat()) { + for ($i = 1; isset($fmt[$i]); ++$i) { + if (0 === strpos($file, $k = $fmt[$i++])) { + $file = substr_replace($file, $fmt[$i], 0, \strlen($k)); + break; + } + } + + return strtr($fmt[0], ['%f' => $file, '%l' => $line]); + } + + return false; + } + + /** + * @internal + */ + public function __sleep(): array + { + $this->fileLinkFormat = $this->getFileLinkFormat(); + + return ['fileLinkFormat']; + } + + /** + * @internal + */ + public static function generateUrlFormat(UrlGeneratorInterface $router, string $routeName, string $queryString): ?string + { + try { + return $router->generate($routeName).$queryString; + } catch (\Throwable $e) { + return null; + } + } + + private function getFileLinkFormat() + { + if ($this->fileLinkFormat) { + return $this->fileLinkFormat; + } + + if ($this->requestStack && $this->baseDir && $this->urlFormat) { + $request = $this->requestStack->getMasterRequest(); + + if ($request instanceof Request && (!$this->urlFormat instanceof \Closure || $this->urlFormat = ($this->urlFormat)())) { + return [ + $request->getSchemeAndHttpHost().$this->urlFormat, + $this->baseDir.\DIRECTORY_SEPARATOR, '', + ]; + } + } + + return null; + } +} diff --git a/vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php b/vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php new file mode 100644 index 0000000..1ece493 --- /dev/null +++ b/vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Debug; + +use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher as BaseTraceableEventDispatcher; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * Collects some data about event listeners. + * + * This event dispatcher delegates the dispatching to another one. + * + * @author Fabien Potencier + */ +class TraceableEventDispatcher extends BaseTraceableEventDispatcher +{ + /** + * {@inheritdoc} + */ + protected function beforeDispatch(string $eventName, object $event) + { + switch ($eventName) { + case KernelEvents::REQUEST: + $this->stopwatch->openSection(); + break; + case KernelEvents::VIEW: + case KernelEvents::RESPONSE: + // stop only if a controller has been executed + if ($this->stopwatch->isStarted('controller')) { + $this->stopwatch->stop('controller'); + } + break; + case KernelEvents::TERMINATE: + $token = $event->getResponse()->headers->get('X-Debug-Token'); + if (null === $token) { + break; + } + // There is a very special case when using built-in AppCache class as kernel wrapper, in the case + // of an ESI request leading to a `stale` response [B] inside a `fresh` cached response [A]. + // In this case, `$token` contains the [B] debug token, but the open `stopwatch` section ID + // is equal to the [A] debug token. Trying to reopen section with the [B] token throws an exception + // which must be caught. + try { + $this->stopwatch->openSection($token); + } catch (\LogicException $e) { + } + break; + } + } + + /** + * {@inheritdoc} + */ + protected function afterDispatch(string $eventName, object $event) + { + switch ($eventName) { + case KernelEvents::CONTROLLER_ARGUMENTS: + $this->stopwatch->start('controller', 'section'); + break; + case KernelEvents::RESPONSE: + $token = $event->getResponse()->headers->get('X-Debug-Token'); + if (null === $token) { + break; + } + $this->stopwatch->stopSection($token); + break; + case KernelEvents::TERMINATE: + // In the special case described in the `preDispatch` method above, the `$token` section + // does not exist, then closing it throws an exception which must be caught. + $token = $event->getResponse()->headers->get('X-Debug-Token'); + if (null === $token) { + break; + } + try { + $this->stopwatch->stopSection($token); + } catch (\LogicException $e) { + } + break; + } + } +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php b/vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php new file mode 100644 index 0000000..70a987e --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php @@ -0,0 +1,144 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Composer\Autoload\ClassLoader; +use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\ErrorHandler\DebugClassLoader; +use Symfony\Component\HttpKernel\Kernel; + +/** + * Sets the classes to compile in the cache for the container. + * + * @author Fabien Potencier + */ +class AddAnnotatedClassesToCachePass implements CompilerPassInterface +{ + private $kernel; + + public function __construct(Kernel $kernel) + { + $this->kernel = $kernel; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $annotatedClasses = $this->kernel->getAnnotatedClassesToCompile(); + foreach ($container->getExtensions() as $extension) { + if ($extension instanceof Extension) { + $annotatedClasses = array_merge($annotatedClasses, $extension->getAnnotatedClassesToCompile()); + } + } + + $existingClasses = $this->getClassesInComposerClassMaps(); + + $annotatedClasses = $container->getParameterBag()->resolveValue($annotatedClasses); + $this->kernel->setAnnotatedClassCache($this->expandClasses($annotatedClasses, $existingClasses)); + } + + /** + * Expands the given class patterns using a list of existing classes. + * + * @param array $patterns The class patterns to expand + * @param array $classes The existing classes to match against the patterns + */ + private function expandClasses(array $patterns, array $classes): array + { + $expanded = []; + + // Explicit classes declared in the patterns are returned directly + foreach ($patterns as $key => $pattern) { + if ('\\' !== substr($pattern, -1) && false === strpos($pattern, '*')) { + unset($patterns[$key]); + $expanded[] = ltrim($pattern, '\\'); + } + } + + // Match patterns with the classes list + $regexps = $this->patternsToRegexps($patterns); + + foreach ($classes as $class) { + $class = ltrim($class, '\\'); + + if ($this->matchAnyRegexps($class, $regexps)) { + $expanded[] = $class; + } + } + + return array_unique($expanded); + } + + private function getClassesInComposerClassMaps(): array + { + $classes = []; + + foreach (spl_autoload_functions() as $function) { + if (!\is_array($function)) { + continue; + } + + if ($function[0] instanceof DebugClassLoader || $function[0] instanceof LegacyDebugClassLoader) { + $function = $function[0]->getClassLoader(); + } + + if (\is_array($function) && $function[0] instanceof ClassLoader) { + $classes += array_filter($function[0]->getClassMap()); + } + } + + return array_keys($classes); + } + + private function patternsToRegexps(array $patterns): array + { + $regexps = []; + + foreach ($patterns as $pattern) { + // Escape user input + $regex = preg_quote(ltrim($pattern, '\\')); + + // Wildcards * and ** + $regex = strtr($regex, ['\\*\\*' => '.*?', '\\*' => '[^\\\\]*?']); + + // If this class does not end by a slash, anchor the end + if ('\\' !== substr($regex, -1)) { + $regex .= '$'; + } + + $regexps[] = '{^\\\\'.$regex.'}'; + } + + return $regexps; + } + + private function matchAnyRegexps(string $class, array $regexps): bool + { + $blacklisted = false !== strpos($class, 'Test'); + + foreach ($regexps as $regex) { + if ($blacklisted && false === strpos($regex, 'Test')) { + continue; + } + + if (preg_match($regex, '\\'.$class)) { + return true; + } + } + + return false; + } +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php b/vendor/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php new file mode 100644 index 0000000..072c35f --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * This extension sub-class provides first-class integration with the + * Config/Definition Component. + * + * You can use this as base class if + * + * a) you use the Config/Definition component for configuration, + * b) your configuration class is named "Configuration", and + * c) the configuration class resides in the DependencyInjection sub-folder. + * + * @author Johannes M. Schmitt + */ +abstract class ConfigurableExtension extends Extension +{ + /** + * {@inheritdoc} + */ + final public function load(array $configs, ContainerBuilder $container) + { + $this->loadInternal($this->processConfiguration($this->getConfiguration($configs, $container), $configs), $container); + } + + /** + * Configures the passed container according to the merged configuration. + */ + abstract protected function loadInternal(array $mergedConfig, ContainerBuilder $container); +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php b/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php new file mode 100644 index 0000000..705c88d --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver; +use Symfony\Component\Stopwatch\Stopwatch; + +/** + * Gathers and configures the argument value resolvers. + * + * @author Iltar van der Berg + */ +class ControllerArgumentValueResolverPass implements CompilerPassInterface +{ + use PriorityTaggedServiceTrait; + + private $argumentResolverService; + private $argumentValueResolverTag; + private $traceableResolverStopwatch; + + public function __construct(string $argumentResolverService = 'argument_resolver', string $argumentValueResolverTag = 'controller.argument_value_resolver', string $traceableResolverStopwatch = 'debug.stopwatch') + { + $this->argumentResolverService = $argumentResolverService; + $this->argumentValueResolverTag = $argumentValueResolverTag; + $this->traceableResolverStopwatch = $traceableResolverStopwatch; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->argumentResolverService)) { + return; + } + + $resolvers = $this->findAndSortTaggedServices($this->argumentValueResolverTag, $container); + + if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class) && $container->has($this->traceableResolverStopwatch)) { + foreach ($resolvers as $resolverReference) { + $id = (string) $resolverReference; + $container->register("debug.$id", TraceableValueResolver::class) + ->setDecoratedService($id) + ->setArguments([new Reference("debug.$id.inner"), new Reference($this->traceableResolverStopwatch)]); + } + } + + $container + ->getDefinition($this->argumentResolverService) + ->replaceArgument(1, new IteratorArgument($resolvers)) + ; + } +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/Extension.php b/vendor/symfony/http-kernel/DependencyInjection/Extension.php new file mode 100644 index 0000000..db376e6 --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/Extension.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Component\DependencyInjection\Extension\Extension as BaseExtension; + +/** + * Allow adding classes to the class cache. + * + * @author Fabien Potencier + */ +abstract class Extension extends BaseExtension +{ + private $annotatedClasses = []; + + /** + * Gets the annotated classes to cache. + * + * @return array An array of classes + */ + public function getAnnotatedClassesToCompile() + { + return $this->annotatedClasses; + } + + /** + * Adds annotated classes to the class cache. + * + * @param array $annotatedClasses An array of class patterns + */ + public function addAnnotatedClassesToCompile(array $annotatedClasses) + { + $this->annotatedClasses = array_merge($this->annotatedClasses, $annotatedClasses); + } +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php b/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php new file mode 100644 index 0000000..432f767 --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface; + +/** + * Adds services tagged kernel.fragment_renderer as HTTP content rendering strategies. + * + * @author Fabien Potencier + */ +class FragmentRendererPass implements CompilerPassInterface +{ + private $handlerService; + private $rendererTag; + + public function __construct(string $handlerService = 'fragment.handler', string $rendererTag = 'kernel.fragment_renderer') + { + $this->handlerService = $handlerService; + $this->rendererTag = $rendererTag; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->handlerService)) { + return; + } + + $definition = $container->getDefinition($this->handlerService); + $renderers = []; + foreach ($container->findTaggedServiceIds($this->rendererTag, true) as $id => $tags) { + $def = $container->getDefinition($id); + $class = $container->getParameterBag()->resolveValue($def->getClass()); + + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + if (!$r->isSubclassOf(FragmentRendererInterface::class)) { + throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, FragmentRendererInterface::class)); + } + + foreach ($tags as $tag) { + $renderers[$tag['alias']] = new Reference($id); + } + } + + $definition->replaceArgument(0, ServiceLocatorTagPass::register($container, $renderers)); + } +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php b/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php new file mode 100644 index 0000000..2ee6737 --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Psr\Container\ContainerInterface; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpKernel\Fragment\FragmentHandler; + +/** + * Lazily loads fragment renderers from the dependency injection container. + * + * @author Fabien Potencier + */ +class LazyLoadingFragmentHandler extends FragmentHandler +{ + private $container; + private $initialized = []; + + public function __construct(ContainerInterface $container, RequestStack $requestStack, bool $debug = false) + { + $this->container = $container; + + parent::__construct($requestStack, [], $debug); + } + + /** + * {@inheritdoc} + */ + public function render($uri, string $renderer = 'inline', array $options = []) + { + if (!isset($this->initialized[$renderer]) && $this->container->has($renderer)) { + $this->addRenderer($this->container->get($renderer)); + $this->initialized[$renderer] = true; + } + + return parent::render($uri, $renderer, $options); + } +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php b/vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php new file mode 100644 index 0000000..b6df1f6 --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Psr\Log\LoggerInterface; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\Log\Logger; + +/** + * Registers the default logger if necessary. + * + * @author Kévin Dunglas + */ +class LoggerPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $container->setAlias(LoggerInterface::class, 'logger') + ->setPublic(false); + + if ($container->has('logger')) { + return; + } + + $container->register('logger', Logger::class) + ->setPublic(false); + } +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php b/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php new file mode 100644 index 0000000..83e1b75 --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass as BaseMergeExtensionConfigurationPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Ensures certain extensions are always loaded. + * + * @author Kris Wallsmith + */ +class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPass +{ + private $extensions; + + public function __construct(array $extensions) + { + $this->extensions = $extensions; + } + + public function process(ContainerBuilder $container) + { + foreach ($this->extensions as $extension) { + if (!\count($container->getExtensionConfig($extension))) { + $container->loadFromExtension($extension, []); + } + } + + parent::process($container); + } +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php new file mode 100644 index 0000000..a3f5012 --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php @@ -0,0 +1,200 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\TypedReference; +use Symfony\Component\HttpFoundation\Request; + +/** + * Creates the service-locators required by ServiceValueResolver. + * + * @author Nicolas Grekas + */ +class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface +{ + private $resolverServiceId; + private $controllerTag; + private $controllerLocator; + private $notTaggedControllerResolverServiceId; + + public function __construct(string $resolverServiceId = 'argument_resolver.service', string $controllerTag = 'controller.service_arguments', string $controllerLocator = 'argument_resolver.controller_locator', string $notTaggedControllerResolverServiceId = 'argument_resolver.not_tagged_controller') + { + $this->resolverServiceId = $resolverServiceId; + $this->controllerTag = $controllerTag; + $this->controllerLocator = $controllerLocator; + $this->notTaggedControllerResolverServiceId = $notTaggedControllerResolverServiceId; + } + + public function process(ContainerBuilder $container) + { + if (false === $container->hasDefinition($this->resolverServiceId) && false === $container->hasDefinition($this->notTaggedControllerResolverServiceId)) { + return; + } + + $parameterBag = $container->getParameterBag(); + $controllers = []; + + foreach ($container->findTaggedServiceIds($this->controllerTag, true) as $id => $tags) { + $def = $container->getDefinition($id); + $def->setPublic(true); + $class = $def->getClass(); + $autowire = $def->isAutowired(); + $bindings = $def->getBindings(); + + // resolve service class, taking parent definitions into account + while ($def instanceof ChildDefinition) { + $def = $container->findDefinition($def->getParent()); + $class = $class ?: $def->getClass(); + $bindings += $def->getBindings(); + } + $class = $parameterBag->resolveValue($class); + + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + $isContainerAware = $r->implementsInterface(ContainerAwareInterface::class) || is_subclass_of($class, AbstractController::class); + + // get regular public methods + $methods = []; + $arguments = []; + foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $r) { + if ('setContainer' === $r->name && $isContainerAware) { + continue; + } + if (!$r->isConstructor() && !$r->isDestructor() && !$r->isAbstract()) { + $methods[strtolower($r->name)] = [$r, $r->getParameters()]; + } + } + + // validate and collect explicit per-actions and per-arguments service references + foreach ($tags as $attributes) { + if (!isset($attributes['action']) && !isset($attributes['argument']) && !isset($attributes['id'])) { + $autowire = true; + continue; + } + foreach (['action', 'argument', 'id'] as $k) { + if (!isset($attributes[$k][0])) { + throw new InvalidArgumentException(sprintf('Missing "%s" attribute on tag "%s" %s for service "%s".', $k, $this->controllerTag, json_encode($attributes, JSON_UNESCAPED_UNICODE), $id)); + } + } + if (!isset($methods[$action = strtolower($attributes['action'])])) { + throw new InvalidArgumentException(sprintf('Invalid "action" attribute on tag "%s" for service "%s": no public "%s()" method found on class "%s".', $this->controllerTag, $id, $attributes['action'], $class)); + } + list($r, $parameters) = $methods[$action]; + $found = false; + + foreach ($parameters as $p) { + if ($attributes['argument'] === $p->name) { + if (!isset($arguments[$r->name][$p->name])) { + $arguments[$r->name][$p->name] = $attributes['id']; + } + $found = true; + break; + } + } + + if (!$found) { + throw new InvalidArgumentException(sprintf('Invalid "%s" tag for service "%s": method "%s()" has no "%s" argument on class "%s".', $this->controllerTag, $id, $r->name, $attributes['argument'], $class)); + } + } + + foreach ($methods as list($r, $parameters)) { + /** @var \ReflectionMethod $r */ + + // create a per-method map of argument-names to service/type-references + $args = []; + foreach ($parameters as $p) { + /** @var \ReflectionParameter $p */ + $type = ltrim($target = ProxyHelper::getTypeHint($r, $p), '\\'); + $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; + + if (isset($arguments[$r->name][$p->name])) { + $target = $arguments[$r->name][$p->name]; + if ('?' !== $target[0]) { + $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE; + } elseif ('' === $target = (string) substr($target, 1)) { + throw new InvalidArgumentException(sprintf('A "%s" tag must have non-empty "id" attributes for service "%s".', $this->controllerTag, $id)); + } elseif ($p->allowsNull() && !$p->isOptional()) { + $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; + } + } elseif (isset($bindings[$bindingName = $type.' $'.$p->name]) || isset($bindings[$bindingName = '$'.$p->name]) || isset($bindings[$bindingName = $type])) { + $binding = $bindings[$bindingName]; + + list($bindingValue, $bindingId, , $bindingType, $bindingFile) = $binding->getValues(); + $binding->setValues([$bindingValue, $bindingId, true, $bindingType, $bindingFile]); + + if (!$bindingValue instanceof Reference) { + $args[$p->name] = new Reference('.value.'.$container->hash($bindingValue)); + $container->register((string) $args[$p->name], 'mixed') + ->setFactory('current') + ->addArgument([$bindingValue]); + } else { + $args[$p->name] = $bindingValue; + } + + continue; + } elseif (!$type || !$autowire || '\\' !== $target[0]) { + continue; + } elseif (!$p->allowsNull()) { + $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE; + } + + if (Request::class === $type) { + continue; + } + + if ($type && !$p->isOptional() && !$p->allowsNull() && !class_exists($type) && !interface_exists($type, false)) { + $message = sprintf('Cannot determine controller argument for "%s::%s()": the $%s argument is type-hinted with the non-existent class or interface: "%s".', $class, $r->name, $p->name, $type); + + // see if the type-hint lives in the same namespace as the controller + if (0 === strncmp($type, $class, strrpos($class, '\\'))) { + $message .= ' Did you forget to add a use statement?'; + } + + throw new InvalidArgumentException($message); + } + + $target = ltrim($target, '\\'); + $args[$p->name] = $type ? new TypedReference($target, $type, $invalidBehavior, $p->name) : new Reference($target, $invalidBehavior); + } + // register the maps as a per-method service-locators + if ($args) { + $controllers[$id.'::'.$r->name] = ServiceLocatorTagPass::register($container, $args); + } + } + } + + $controllerLocatorRef = ServiceLocatorTagPass::register($container, $controllers); + + if ($container->hasDefinition($this->resolverServiceId)) { + $container->getDefinition($this->resolverServiceId) + ->replaceArgument(0, $controllerLocatorRef); + } + + if ($container->hasDefinition($this->notTaggedControllerResolverServiceId)) { + $container->getDefinition($this->notTaggedControllerResolverServiceId) + ->replaceArgument(0, $controllerLocatorRef); + } + + $container->setAlias($this->controllerLocator, (string) $controllerLocatorRef); + } +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php b/vendor/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php new file mode 100644 index 0000000..0efb164 --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Register all services that have the "kernel.locale_aware" tag into the listener. + * + * @author Pierre Bobiet + */ +class RegisterLocaleAwareServicesPass implements CompilerPassInterface +{ + private $listenerServiceId; + private $localeAwareTag; + + public function __construct(string $listenerServiceId = 'locale_aware_listener', string $localeAwareTag = 'kernel.locale_aware') + { + $this->listenerServiceId = $listenerServiceId; + $this->localeAwareTag = $localeAwareTag; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->listenerServiceId)) { + return; + } + + $services = []; + + foreach ($container->findTaggedServiceIds($this->localeAwareTag) as $id => $tags) { + $services[] = new Reference($id); + } + + if (!$services) { + $container->removeDefinition($this->listenerServiceId); + + return; + } + + $container + ->getDefinition($this->listenerServiceId) + ->setArgument(0, new IteratorArgument($services)) + ; + } +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php b/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php new file mode 100644 index 0000000..596b618 --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Removes empty service-locators registered for ServiceValueResolver. + * + * @author Nicolas Grekas + */ +class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface +{ + private $controllerLocator; + + public function __construct(string $controllerLocator = 'argument_resolver.controller_locator') + { + $this->controllerLocator = $controllerLocator; + } + + public function process(ContainerBuilder $container) + { + $controllerLocator = $container->findDefinition($this->controllerLocator); + $controllers = $controllerLocator->getArgument(0); + + foreach ($controllers as $controller => $argumentRef) { + $argumentLocator = $container->getDefinition((string) $argumentRef->getValues()[0]); + + if (!$argumentLocator->getArgument(0)) { + // remove empty argument locators + $reason = sprintf('Removing service-argument resolver for controller "%s": no corresponding services exist for the referenced types.', $controller); + } else { + // any methods listed for call-at-instantiation cannot be actions + $reason = false; + list($id, $action) = explode('::', $controller); + $controllerDef = $container->getDefinition($id); + foreach ($controllerDef->getMethodCalls() as list($method)) { + if (0 === strcasecmp($action, $method)) { + $reason = sprintf('Removing method "%s" of service "%s" from controller candidates: the method is called at instantiation, thus cannot be an action.', $action, $id); + break; + } + } + if (!$reason) { + // Deprecated since Symfony 4.1. See Symfony\Component\HttpKernel\Controller\ContainerControllerResolver + $controllers[$id.':'.$action] = $argumentRef; + + if ('__invoke' === $action) { + $controllers[$id] = $argumentRef; + } + continue; + } + } + + unset($controllers[$controller]); + $container->log($this, $reason); + } + + $controllerLocator->replaceArgument(0, $controllers); + } +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php b/vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php new file mode 100644 index 0000000..b5e4610 --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Alexander M. Turek + */ +class ResettableServicePass implements CompilerPassInterface +{ + private $tagName; + + public function __construct(string $tagName = 'kernel.reset') + { + $this->tagName = $tagName; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->has('services_resetter')) { + return; + } + + $services = $methods = []; + + foreach ($container->findTaggedServiceIds($this->tagName, true) as $id => $tags) { + $services[$id] = new Reference($id, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE); + + foreach ($tags as $attributes) { + if (!isset($attributes['method'])) { + throw new RuntimeException(sprintf('Tag "%s" requires the "method" attribute to be set.', $this->tagName)); + } + + if (!isset($methods[$id])) { + $methods[$id] = []; + } + + $methods[$id][] = $attributes['method']; + } + } + + if (!$services) { + $container->removeAlias('services_resetter'); + $container->removeDefinition('services_resetter'); + + return; + } + + $container->findDefinition('services_resetter') + ->setArgument(0, new IteratorArgument($services)) + ->setArgument(1, $methods); + } +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php b/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php new file mode 100644 index 0000000..d9e0028 --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Contracts\Service\ResetInterface; + +/** + * Resets provided services. + * + * @author Alexander M. Turek + * @author Nicolas Grekas + * + * @internal + */ +class ServicesResetter implements ResetInterface +{ + private $resettableServices; + private $resetMethods; + + public function __construct(\Traversable $resettableServices, array $resetMethods) + { + $this->resettableServices = $resettableServices; + $this->resetMethods = $resetMethods; + } + + public function reset() + { + foreach ($this->resettableServices as $id => $service) { + foreach ((array) $this->resetMethods[$id] as $resetMethod) { + $service->$resetMethod(); + } + } + } +} diff --git a/vendor/symfony/http-kernel/Event/ControllerArgumentsEvent.php b/vendor/symfony/http-kernel/Event/ControllerArgumentsEvent.php new file mode 100644 index 0000000..d075ee9 --- /dev/null +++ b/vendor/symfony/http-kernel/Event/ControllerArgumentsEvent.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * Allows filtering of controller arguments. + * + * You can call getController() to retrieve the controller and getArguments + * to retrieve the current arguments. With setArguments() you can replace + * arguments that are used to call the controller. + * + * Arguments set in the event must be compatible with the signature of the + * controller. + * + * @author Christophe Coevoet + */ +final class ControllerArgumentsEvent extends KernelEvent +{ + private $controller; + private $arguments; + + public function __construct(HttpKernelInterface $kernel, callable $controller, array $arguments, Request $request, ?int $requestType) + { + parent::__construct($kernel, $request, $requestType); + + $this->controller = $controller; + $this->arguments = $arguments; + } + + public function getController(): callable + { + return $this->controller; + } + + public function setController(callable $controller) + { + $this->controller = $controller; + } + + public function getArguments(): array + { + return $this->arguments; + } + + public function setArguments(array $arguments) + { + $this->arguments = $arguments; + } +} diff --git a/vendor/symfony/http-kernel/Event/ControllerEvent.php b/vendor/symfony/http-kernel/Event/ControllerEvent.php new file mode 100644 index 0000000..da88800 --- /dev/null +++ b/vendor/symfony/http-kernel/Event/ControllerEvent.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * Allows filtering of a controller callable. + * + * You can call getController() to retrieve the current controller. With + * setController() you can set a new controller that is used in the processing + * of the request. + * + * Controllers should be callables. + * + * @author Bernhard Schussek + */ +final class ControllerEvent extends KernelEvent +{ + private $controller; + + public function __construct(HttpKernelInterface $kernel, callable $controller, Request $request, ?int $requestType) + { + parent::__construct($kernel, $request, $requestType); + + $this->setController($controller); + } + + public function getController(): callable + { + return $this->controller; + } + + public function setController(callable $controller): void + { + $this->controller = $controller; + } +} diff --git a/vendor/symfony/http-kernel/Event/ExceptionEvent.php b/vendor/symfony/http-kernel/Event/ExceptionEvent.php new file mode 100644 index 0000000..a10741a --- /dev/null +++ b/vendor/symfony/http-kernel/Event/ExceptionEvent.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * Allows to create a response for a thrown exception. + * + * Call setResponse() to set the response that will be returned for the + * current request. The propagation of this event is stopped as soon as a + * response is set. + * + * You can also call setException() to replace the thrown exception. This + * exception will be thrown if no response is set during processing of this + * event. + * + * @author Bernhard Schussek + */ +final class ExceptionEvent extends RequestEvent +{ + private $throwable; + + /** + * @var bool + */ + private $allowCustomResponseCode = false; + + public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, \Throwable $e) + { + parent::__construct($kernel, $request, $requestType); + + $this->setThrowable($e); + } + + public function getThrowable(): \Throwable + { + return $this->throwable; + } + + /** + * Replaces the thrown exception. + * + * This exception will be thrown if no response is set in the event. + */ + public function setThrowable(\Throwable $exception): void + { + $this->throwable = $exception; + } + + /** + * Mark the event as allowing a custom response code. + */ + public function allowCustomResponseCode(): void + { + $this->allowCustomResponseCode = true; + } + + /** + * Returns true if the event allows a custom response code. + */ + public function isAllowingCustomResponseCode(): bool + { + return $this->allowCustomResponseCode; + } +} diff --git a/vendor/symfony/http-kernel/Event/FinishRequestEvent.php b/vendor/symfony/http-kernel/Event/FinishRequestEvent.php new file mode 100644 index 0000000..306a7ad --- /dev/null +++ b/vendor/symfony/http-kernel/Event/FinishRequestEvent.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +/** + * Triggered whenever a request is fully processed. + * + * @author Benjamin Eberlei + */ +final class FinishRequestEvent extends KernelEvent +{ +} diff --git a/vendor/symfony/http-kernel/Event/KernelEvent.php b/vendor/symfony/http-kernel/Event/KernelEvent.php new file mode 100644 index 0000000..08558d5 --- /dev/null +++ b/vendor/symfony/http-kernel/Event/KernelEvent.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Contracts\EventDispatcher\Event; + +/** + * Base class for events thrown in the HttpKernel component. + * + * @author Bernhard Schussek + */ +class KernelEvent extends Event +{ + private $kernel; + private $request; + private $requestType; + + /** + * @param int $requestType The request type the kernel is currently processing; one of + * HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST + */ + public function __construct(HttpKernelInterface $kernel, Request $request, ?int $requestType) + { + $this->kernel = $kernel; + $this->request = $request; + $this->requestType = $requestType; + } + + /** + * Returns the kernel in which this event was thrown. + * + * @return HttpKernelInterface + */ + public function getKernel() + { + return $this->kernel; + } + + /** + * Returns the request the kernel is currently processing. + * + * @return Request + */ + public function getRequest() + { + return $this->request; + } + + /** + * Returns the request type the kernel is currently processing. + * + * @return int One of HttpKernelInterface::MASTER_REQUEST and + * HttpKernelInterface::SUB_REQUEST + */ + public function getRequestType() + { + return $this->requestType; + } + + /** + * Checks if this is a master request. + * + * @return bool True if the request is a master request + */ + public function isMasterRequest() + { + return HttpKernelInterface::MASTER_REQUEST === $this->requestType; + } +} diff --git a/vendor/symfony/http-kernel/Event/RequestEvent.php b/vendor/symfony/http-kernel/Event/RequestEvent.php new file mode 100644 index 0000000..0b2b98e --- /dev/null +++ b/vendor/symfony/http-kernel/Event/RequestEvent.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +use Symfony\Component\HttpFoundation\Response; + +/** + * Allows to create a response for a request. + * + * Call setResponse() to set the response that will be returned for the + * current request. The propagation of this event is stopped as soon as a + * response is set. + * + * @author Bernhard Schussek + */ +class RequestEvent extends KernelEvent +{ + private $response; + + /** + * Returns the response object. + * + * @return Response|null + */ + public function getResponse() + { + return $this->response; + } + + /** + * Sets a response and stops event propagation. + */ + public function setResponse(Response $response) + { + $this->response = $response; + + $this->stopPropagation(); + } + + /** + * Returns whether a response was set. + * + * @return bool Whether a response was set + */ + public function hasResponse() + { + return null !== $this->response; + } +} diff --git a/vendor/symfony/http-kernel/Event/ResponseEvent.php b/vendor/symfony/http-kernel/Event/ResponseEvent.php new file mode 100644 index 0000000..1e56ebe --- /dev/null +++ b/vendor/symfony/http-kernel/Event/ResponseEvent.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * Allows to filter a Response object. + * + * You can call getResponse() to retrieve the current response. With + * setResponse() you can set a new response that will be returned to the + * browser. + * + * @author Bernhard Schussek + */ +final class ResponseEvent extends KernelEvent +{ + private $response; + + public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, Response $response) + { + parent::__construct($kernel, $request, $requestType); + + $this->setResponse($response); + } + + public function getResponse(): Response + { + return $this->response; + } + + public function setResponse(Response $response): void + { + $this->response = $response; + } +} diff --git a/vendor/symfony/http-kernel/Event/TerminateEvent.php b/vendor/symfony/http-kernel/Event/TerminateEvent.php new file mode 100644 index 0000000..e0002fb --- /dev/null +++ b/vendor/symfony/http-kernel/Event/TerminateEvent.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * Allows to execute logic after a response was sent. + * + * Since it's only triggered on master requests, the `getRequestType()` method + * will always return the value of `HttpKernelInterface::MASTER_REQUEST`. + * + * @author Jordi Boggiano + */ +final class TerminateEvent extends KernelEvent +{ + private $response; + + public function __construct(HttpKernelInterface $kernel, Request $request, Response $response) + { + parent::__construct($kernel, $request, HttpKernelInterface::MASTER_REQUEST); + + $this->response = $response; + } + + public function getResponse(): Response + { + return $this->response; + } +} diff --git a/vendor/symfony/http-kernel/Event/ViewEvent.php b/vendor/symfony/http-kernel/Event/ViewEvent.php new file mode 100644 index 0000000..66a4cea --- /dev/null +++ b/vendor/symfony/http-kernel/Event/ViewEvent.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * Allows to create a response for the return value of a controller. + * + * Call setResponse() to set the response that will be returned for the + * current request. The propagation of this event is stopped as soon as a + * response is set. + * + * @author Bernhard Schussek + */ +final class ViewEvent extends RequestEvent +{ + /** + * The return value of the controller. + * + * @var mixed + */ + private $controllerResult; + + public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, $controllerResult) + { + parent::__construct($kernel, $request, $requestType); + + $this->controllerResult = $controllerResult; + } + + /** + * Returns the return value of the controller. + * + * @return mixed The controller return value + */ + public function getControllerResult() + { + return $this->controllerResult; + } + + /** + * Assigns the return value of the controller. + * + * @param mixed $controllerResult The controller return value + */ + public function setControllerResult($controllerResult): void + { + $this->controllerResult = $controllerResult; + } +} diff --git a/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php b/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php new file mode 100644 index 0000000..9c9c422 --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php @@ -0,0 +1,148 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Psr\Container\ContainerInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\HttpKernel\Event\FinishRequestEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * Sets the session onto the request on the "kernel.request" event and saves + * it on the "kernel.response" event. + * + * In addition, if the session has been started it overrides the Cache-Control + * header in such a way that all caching is disabled in that case. + * If you have a scenario where caching responses with session information in + * them makes sense, you can disable this behaviour by setting the header + * AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER on the response. + * + * @author Johannes M. Schmitt + * @author Tobias Schultze + * + * @internal + */ +abstract class AbstractSessionListener implements EventSubscriberInterface +{ + const NO_AUTO_CACHE_CONTROL_HEADER = 'Symfony-Session-NoAutoCacheControl'; + + protected $container; + private $sessionUsageStack = []; + + public function __construct(ContainerInterface $container = null) + { + $this->container = $container; + } + + public function onKernelRequest(RequestEvent $event) + { + if (!$event->isMasterRequest()) { + return; + } + + $session = null; + $request = $event->getRequest(); + if ($request->hasSession()) { + // no-op + } elseif (method_exists($request, 'setSessionFactory')) { + $request->setSessionFactory(function () { return $this->getSession(); }); + } elseif ($session = $this->getSession()) { + $request->setSession($session); + } + + $session = $session ?? ($this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : null); + $this->sessionUsageStack[] = $session instanceof Session ? $session->getUsageIndex() : 0; + } + + public function onKernelResponse(ResponseEvent $event) + { + if (!$event->isMasterRequest()) { + return; + } + + $response = $event->getResponse(); + $autoCacheControl = !$response->headers->has(self::NO_AUTO_CACHE_CONTROL_HEADER); + // Always remove the internal header if present + $response->headers->remove(self::NO_AUTO_CACHE_CONTROL_HEADER); + + if (!$session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : $event->getRequest()->getSession()) { + return; + } + + if ($session instanceof Session ? $session->getUsageIndex() !== end($this->sessionUsageStack) : $session->isStarted()) { + if ($autoCacheControl) { + $response + ->setExpires(new \DateTime()) + ->setPrivate() + ->setMaxAge(0) + ->headers->addCacheControlDirective('must-revalidate'); + } + } + + if ($session->isStarted()) { + /* + * Saves the session, in case it is still open, before sending the response/headers. + * + * This ensures several things in case the developer did not save the session explicitly: + * + * * If a session save handler without locking is used, it ensures the data is available + * on the next request, e.g. after a redirect. PHPs auto-save at script end via + * session_register_shutdown is executed after fastcgi_finish_request. So in this case + * the data could be missing the next request because it might not be saved the moment + * the new request is processed. + * * A locking save handler (e.g. the native 'files') circumvents concurrency problems like + * the one above. But by saving the session before long-running things in the terminate event, + * we ensure the session is not blocked longer than needed. + * * When regenerating the session ID no locking is involved in PHPs session design. See + * https://bugs.php.net/61470 for a discussion. So in this case, the session must + * be saved anyway before sending the headers with the new session ID. Otherwise session + * data could get lost again for concurrent requests with the new ID. One result could be + * that you get logged out after just logging in. + * + * This listener should be executed as one of the last listeners, so that previous listeners + * can still operate on the open session. This prevents the overhead of restarting it. + * Listeners after closing the session can still work with the session as usual because + * Symfonys session implementation starts the session on demand. So writing to it after + * it is saved will just restart it. + */ + $session->save(); + } + } + + public function onFinishRequest(FinishRequestEvent $event) + { + if ($event->isMasterRequest()) { + array_pop($this->sessionUsageStack); + } + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::REQUEST => ['onKernelRequest', 128], + // low priority to come after regular response listeners, but higher than StreamedResponseListener + KernelEvents::RESPONSE => ['onKernelResponse', -1000], + KernelEvents::FINISH_REQUEST => ['onFinishRequest'], + ]; + } + + /** + * Gets the session object. + * + * @return SessionInterface|null A SessionInterface instance or null if no session is available + */ + abstract protected function getSession(); +} diff --git a/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php b/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php new file mode 100644 index 0000000..19d13b8 --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * TestSessionListener. + * + * Saves session in test environment. + * + * @author Bulat Shakirzyanov + * @author Fabien Potencier + * + * @internal + */ +abstract class AbstractTestSessionListener implements EventSubscriberInterface +{ + private $sessionId; + private $sessionOptions; + + public function __construct(array $sessionOptions = []) + { + $this->sessionOptions = $sessionOptions; + } + + public function onKernelRequest(RequestEvent $event) + { + if (!$event->isMasterRequest()) { + return; + } + + // bootstrap the session + if (!$session = $this->getSession()) { + return; + } + + $cookies = $event->getRequest()->cookies; + + if ($cookies->has($session->getName())) { + $this->sessionId = $cookies->get($session->getName()); + $session->setId($this->sessionId); + } + } + + /** + * Checks if session was initialized and saves if current request is master + * Runs on 'kernel.response' in test environment. + */ + public function onKernelResponse(ResponseEvent $event) + { + if (!$event->isMasterRequest()) { + return; + } + + $request = $event->getRequest(); + if (!$request->hasSession()) { + return; + } + + $session = $request->getSession(); + if ($wasStarted = $session->isStarted()) { + $session->save(); + } + + if ($session instanceof Session ? !$session->isEmpty() || (null !== $this->sessionId && $session->getId() !== $this->sessionId) : $wasStarted) { + $params = session_get_cookie_params() + ['samesite' => null]; + foreach ($this->sessionOptions as $k => $v) { + if (0 === strpos($k, 'cookie_')) { + $params[substr($k, 7)] = $v; + } + } + + foreach ($event->getResponse()->headers->getCookies() as $cookie) { + if ($session->getName() === $cookie->getName() && $params['path'] === $cookie->getPath() && $params['domain'] == $cookie->getDomain()) { + return; + } + } + + $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'], false, $params['samesite'] ?: null)); + $this->sessionId = $session->getId(); + } + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::REQUEST => ['onKernelRequest', 192], + KernelEvents::RESPONSE => ['onKernelResponse', -128], + ]; + } + + /** + * Gets the session object. + * + * @return SessionInterface|null A SessionInterface instance or null if no session is available + */ + abstract protected function getSession(); +} diff --git a/vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php b/vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php new file mode 100644 index 0000000..9e896ad --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * Adds configured formats to each request. + * + * @author Gildas Quemener + * + * @final + */ +class AddRequestFormatsListener implements EventSubscriberInterface +{ + protected $formats; + + public function __construct(array $formats) + { + $this->formats = $formats; + } + + /** + * Adds request formats. + */ + public function onKernelRequest(RequestEvent $event) + { + $request = $event->getRequest(); + foreach ($this->formats as $format => $mimeTypes) { + $request->setFormat($format, $mimeTypes); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents(): array + { + return [KernelEvents::REQUEST => ['onKernelRequest', 100]]; + } +} diff --git a/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php b/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php new file mode 100644 index 0000000..fbb1f2e --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php @@ -0,0 +1,153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Console\ConsoleEvents; +use Symfony\Component\Console\Event\ConsoleEvent; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\ErrorHandler\ErrorHandler; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; +use Symfony\Component\HttpKernel\Event\KernelEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * Configures errors and exceptions handlers. + * + * @author Nicolas Grekas + * + * @final + */ +class DebugHandlersListener implements EventSubscriberInterface +{ + private $exceptionHandler; + private $logger; + private $levels; + private $throwAt; + private $scream; + private $fileLinkFormat; + private $scope; + private $firstCall = true; + private $hasTerminatedWithException; + + /** + * @param callable|null $exceptionHandler A handler that must support \Throwable instances that will be called on Exception + * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants + * @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value + * @param bool $scream Enables/disables screaming mode, where even silenced errors are logged + * @param string|FileLinkFormatter|null $fileLinkFormat The format for links to source files + * @param bool $scope Enables/disables scoping mode + */ + public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = E_ALL, ?int $throwAt = E_ALL, bool $scream = true, $fileLinkFormat = null, bool $scope = true) + { + $this->exceptionHandler = $exceptionHandler; + $this->logger = $logger; + $this->levels = null === $levels ? E_ALL : $levels; + $this->throwAt = \is_int($throwAt) ? $throwAt : (null === $throwAt ? null : ($throwAt ? E_ALL : null)); + $this->scream = $scream; + $this->fileLinkFormat = $fileLinkFormat; + $this->scope = $scope; + } + + /** + * Configures the error handler. + */ + public function configure(object $event = null) + { + if (!$event instanceof KernelEvent ? !$this->firstCall : !$event->isMasterRequest()) { + return; + } + $this->firstCall = $this->hasTerminatedWithException = false; + + $handler = set_exception_handler('var_dump'); + $handler = \is_array($handler) ? $handler[0] : null; + restore_exception_handler(); + + if ($this->logger || null !== $this->throwAt) { + if ($handler instanceof ErrorHandler) { + if ($this->logger) { + $handler->setDefaultLogger($this->logger, $this->levels); + if (\is_array($this->levels)) { + $levels = 0; + foreach ($this->levels as $type => $log) { + $levels |= $type; + } + } else { + $levels = $this->levels; + } + if ($this->scream) { + $handler->screamAt($levels); + } + if ($this->scope) { + $handler->scopeAt($levels & ~E_USER_DEPRECATED & ~E_DEPRECATED); + } else { + $handler->scopeAt(0, true); + } + $this->logger = $this->levels = null; + } + if (null !== $this->throwAt) { + $handler->throwAt($this->throwAt, true); + } + } + } + if (!$this->exceptionHandler) { + if ($event instanceof KernelEvent) { + if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) { + $request = $event->getRequest(); + $hasRun = &$this->hasTerminatedWithException; + $this->exceptionHandler = static function (\Throwable $e) use ($kernel, $request, &$hasRun) { + if ($hasRun) { + throw $e; + } + + $hasRun = true; + $kernel->terminateWithException($e, $request); + }; + } + } elseif ($event instanceof ConsoleEvent && $app = $event->getCommand()->getApplication()) { + $output = $event->getOutput(); + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + $this->exceptionHandler = static function (\Throwable $e) use ($app, $output) { + if (method_exists($app, 'renderThrowable')) { + $app->renderThrowable($e, $output); + } else { + if (!$e instanceof \Exception) { + $e = new FatalThrowableError($e); + } + + $app->renderException($e, $output); + } + }; + } + } + if ($this->exceptionHandler) { + if ($handler instanceof ErrorHandler) { + $handler->setExceptionHandler($this->exceptionHandler); + } + $this->exceptionHandler = null; + } + } + + public static function getSubscribedEvents(): array + { + $events = [KernelEvents::REQUEST => ['configure', 2048]]; + + if ('cli' === \PHP_SAPI && \defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) { + $events[ConsoleEvents::COMMAND] = ['configure', 2048]; + } + + return $events; + } +} diff --git a/vendor/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php b/vendor/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php new file mode 100644 index 0000000..6607e49 --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * Ensures that the application is not indexed by search engines. + * + * @author Gary PEGEOT + */ +class DisallowRobotsIndexingListener implements EventSubscriberInterface +{ + private const HEADER_NAME = 'X-Robots-Tag'; + + public function onResponse(ResponseEvent $event): void + { + if (!$event->getResponse()->headers->has(static::HEADER_NAME)) { + $event->getResponse()->headers->set(static::HEADER_NAME, 'noindex'); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return [ + KernelEvents::RESPONSE => ['onResponse', -255], + ]; + } +} diff --git a/vendor/symfony/http-kernel/EventListener/DumpListener.php b/vendor/symfony/http-kernel/EventListener/DumpListener.php new file mode 100644 index 0000000..30908a4 --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/DumpListener.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\Console\ConsoleEvents; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\VarDumper\Cloner\ClonerInterface; +use Symfony\Component\VarDumper\Dumper\DataDumperInterface; +use Symfony\Component\VarDumper\Server\Connection; +use Symfony\Component\VarDumper\VarDumper; + +/** + * Configures dump() handler. + * + * @author Nicolas Grekas + */ +class DumpListener implements EventSubscriberInterface +{ + private $cloner; + private $dumper; + private $connection; + + public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper, Connection $connection = null) + { + $this->cloner = $cloner; + $this->dumper = $dumper; + $this->connection = $connection; + } + + public function configure() + { + $cloner = $this->cloner; + $dumper = $this->dumper; + $connection = $this->connection; + + VarDumper::setHandler(static function ($var) use ($cloner, $dumper, $connection) { + $data = $cloner->cloneVar($var); + + if (!$connection || !$connection->write($data)) { + $dumper->dump($data); + } + }); + } + + public static function getSubscribedEvents() + { + if (!class_exists(ConsoleEvents::class)) { + return []; + } + + // Register early to have a working dump() as early as possible + return [ConsoleEvents::COMMAND => ['configure', 1024]]; + } +} diff --git a/vendor/symfony/http-kernel/EventListener/ErrorListener.php b/vendor/symfony/http-kernel/EventListener/ErrorListener.php new file mode 100644 index 0000000..26c361f --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/ErrorListener.php @@ -0,0 +1,149 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException; +use Symfony\Component\ErrorHandler\Exception\FlattenException; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; +use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; + +/** + * @author Fabien Potencier + */ +class ErrorListener implements EventSubscriberInterface +{ + protected $controller; + protected $logger; + protected $debug; + + public function __construct($controller, LoggerInterface $logger = null, $debug = false) + { + $this->controller = $controller; + $this->logger = $logger; + $this->debug = $debug; + } + + public function logKernelException(ExceptionEvent $event) + { + $e = FlattenException::createFromThrowable($event->getThrowable()); + + $this->logException($event->getThrowable(), sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $e->getClass(), $e->getMessage(), $e->getFile(), $e->getLine())); + } + + public function onKernelException(ExceptionEvent $event, string $eventName = null, EventDispatcherInterface $eventDispatcher = null) + { + if (null === $this->controller) { + return; + } + + $exception = $event->getThrowable(); + $request = $this->duplicateRequest($exception, $event->getRequest()); + + try { + $response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, false); + } catch (\Exception $e) { + $f = FlattenException::createFromThrowable($e); + + $this->logException($e, sprintf('Exception thrown when handling an exception (%s: %s at %s line %s)', $f->getClass(), $f->getMessage(), $e->getFile(), $e->getLine())); + + $prev = $e; + do { + if ($exception === $wrapper = $prev) { + throw $e; + } + } while ($prev = $wrapper->getPrevious()); + + $prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous'); + $prev->setAccessible(true); + $prev->setValue($wrapper, $exception); + + throw $e; + } + + $event->setResponse($response); + + if ($this->debug && $eventDispatcher instanceof EventDispatcherInterface) { + $cspRemovalListener = function ($event) use (&$cspRemovalListener, $eventDispatcher) { + $event->getResponse()->headers->remove('Content-Security-Policy'); + $eventDispatcher->removeListener(KernelEvents::RESPONSE, $cspRemovalListener); + }; + $eventDispatcher->addListener(KernelEvents::RESPONSE, $cspRemovalListener, -128); + } + } + + public function onControllerArguments(ControllerArgumentsEvent $event) + { + $e = $event->getRequest()->attributes->get('exception'); + + if (!$e instanceof \Throwable || false === $k = array_search($e, $event->getArguments(), true)) { + return; + } + + $r = new \ReflectionFunction(\Closure::fromCallable($event->getController())); + $r = $r->getParameters()[$k] ?? null; + + if ($r && (!$r->hasType() || \in_array($r->getType()->getName(), [FlattenException::class, LegacyFlattenException::class], true))) { + $arguments = $event->getArguments(); + $arguments[$k] = FlattenException::createFromThrowable($e); + $event->setArguments($arguments); + } + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::CONTROLLER_ARGUMENTS => 'onControllerArguments', + KernelEvents::EXCEPTION => [ + ['logKernelException', 0], + ['onKernelException', -128], + ], + ]; + } + + /** + * Logs an exception. + */ + protected function logException(\Throwable $exception, string $message): void + { + if (null !== $this->logger) { + if (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) { + $this->logger->critical($message, ['exception' => $exception]); + } else { + $this->logger->error($message, ['exception' => $exception]); + } + } + } + + /** + * Clones the request for the exception. + */ + protected function duplicateRequest(\Throwable $exception, Request $request): Request + { + $attributes = [ + '_controller' => $this->controller, + 'exception' => $exception, + 'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null, + ]; + $request = $request->duplicate(null, null, $attributes); + $request->setMethod('GET'); + + return $request; + } +} diff --git a/vendor/symfony/http-kernel/EventListener/FragmentListener.php b/vendor/symfony/http-kernel/EventListener/FragmentListener.php new file mode 100644 index 0000000..afe5cb1 --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/FragmentListener.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\UriSigner; + +/** + * Handles content fragments represented by special URIs. + * + * All URL paths starting with /_fragment are handled as + * content fragments by this listener. + * + * Throws an AccessDeniedHttpException exception if the request + * is not signed or if it is not an internal sub-request. + * + * @author Fabien Potencier + * + * @final + */ +class FragmentListener implements EventSubscriberInterface +{ + private $signer; + private $fragmentPath; + + /** + * @param string $fragmentPath The path that triggers this listener + */ + public function __construct(UriSigner $signer, string $fragmentPath = '/_fragment') + { + $this->signer = $signer; + $this->fragmentPath = $fragmentPath; + } + + /** + * Fixes request attributes when the path is '/_fragment'. + * + * @throws AccessDeniedHttpException if the request does not come from a trusted IP + */ + public function onKernelRequest(RequestEvent $event) + { + $request = $event->getRequest(); + + if ($this->fragmentPath !== rawurldecode($request->getPathInfo())) { + return; + } + + if ($request->attributes->has('_controller')) { + // Is a sub-request: no need to parse _path but it should still be removed from query parameters as below. + $request->query->remove('_path'); + + return; + } + + if ($event->isMasterRequest()) { + $this->validateRequest($request); + } + + parse_str($request->query->get('_path', ''), $attributes); + $request->attributes->add($attributes); + $request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', []), $attributes)); + $request->query->remove('_path'); + } + + protected function validateRequest(Request $request) + { + // is the Request safe? + if (!$request->isMethodSafe()) { + throw new AccessDeniedHttpException(); + } + + // is the Request signed? + // we cannot use $request->getUri() here as we want to work with the original URI (no query string reordering) + if ($this->signer->check($request->getSchemeAndHttpHost().$request->getBaseUrl().$request->getPathInfo().(null !== ($qs = $request->server->get('QUERY_STRING')) ? '?'.$qs : ''))) { + return; + } + + throw new AccessDeniedHttpException(); + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::REQUEST => [['onKernelRequest', 48]], + ]; + } +} diff --git a/vendor/symfony/http-kernel/EventListener/LocaleAwareListener.php b/vendor/symfony/http-kernel/EventListener/LocaleAwareListener.php new file mode 100644 index 0000000..62d0302 --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/LocaleAwareListener.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpKernel\Event\FinishRequestEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Contracts\Translation\LocaleAwareInterface; + +/** + * Pass the current locale to the provided services. + * + * @author Pierre Bobiet + */ +class LocaleAwareListener implements EventSubscriberInterface +{ + private $localeAwareServices; + private $requestStack; + + /** + * @param LocaleAwareInterface[] $localeAwareServices + */ + public function __construct(iterable $localeAwareServices, RequestStack $requestStack) + { + $this->localeAwareServices = $localeAwareServices; + $this->requestStack = $requestStack; + } + + public function onKernelRequest(RequestEvent $event): void + { + $this->setLocale($event->getRequest()->getLocale(), $event->getRequest()->getDefaultLocale()); + } + + public function onKernelFinishRequest(FinishRequestEvent $event): void + { + if (null === $parentRequest = $this->requestStack->getParentRequest()) { + foreach ($this->localeAwareServices as $service) { + $service->setLocale($event->getRequest()->getDefaultLocale()); + } + + return; + } + + $this->setLocale($parentRequest->getLocale(), $parentRequest->getDefaultLocale()); + } + + public static function getSubscribedEvents() + { + return [ + // must be registered after the Locale listener + KernelEvents::REQUEST => [['onKernelRequest', 15]], + KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', -15]], + ]; + } + + private function setLocale(string $locale, string $defaultLocale): void + { + foreach ($this->localeAwareServices as $service) { + try { + $service->setLocale($locale); + } catch (\InvalidArgumentException $e) { + $service->setLocale($defaultLocale); + } + } + } +} diff --git a/vendor/symfony/http-kernel/EventListener/LocaleListener.php b/vendor/symfony/http-kernel/EventListener/LocaleListener.php new file mode 100644 index 0000000..8037e32 --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/LocaleListener.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpKernel\Event\FinishRequestEvent; +use Symfony\Component\HttpKernel\Event\KernelEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\Routing\RequestContextAwareInterface; + +/** + * Initializes the locale based on the current request. + * + * @author Fabien Potencier + * + * @final + */ +class LocaleListener implements EventSubscriberInterface +{ + private $router; + private $defaultLocale; + private $requestStack; + + public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null) + { + $this->defaultLocale = $defaultLocale; + $this->requestStack = $requestStack; + $this->router = $router; + } + + public function setDefaultLocale(KernelEvent $event) + { + $event->getRequest()->setDefaultLocale($this->defaultLocale); + } + + public function onKernelRequest(RequestEvent $event) + { + $request = $event->getRequest(); + + $this->setLocale($request); + $this->setRouterContext($request); + } + + public function onKernelFinishRequest(FinishRequestEvent $event) + { + if (null !== $parentRequest = $this->requestStack->getParentRequest()) { + $this->setRouterContext($parentRequest); + } + } + + private function setLocale(Request $request) + { + if ($locale = $request->attributes->get('_locale')) { + $request->setLocale($locale); + } + } + + private function setRouterContext(Request $request) + { + if (null !== $this->router) { + $this->router->getContext()->setParameter('_locale', $request->getLocale()); + } + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::REQUEST => [ + ['setDefaultLocale', 100], + // must be registered after the Router to have access to the _locale + ['onKernelRequest', 16], + ], + KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]], + ]; + } +} diff --git a/vendor/symfony/http-kernel/EventListener/ProfilerListener.php b/vendor/symfony/http-kernel/EventListener/ProfilerListener.php new file mode 100644 index 0000000..3143f2b --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/ProfilerListener.php @@ -0,0 +1,127 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\RequestMatcherInterface; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\Event\TerminateEvent; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\Profiler\Profiler; + +/** + * ProfilerListener collects data for the current request by listening to the kernel events. + * + * @author Fabien Potencier + * + * @final + */ +class ProfilerListener implements EventSubscriberInterface +{ + protected $profiler; + protected $matcher; + protected $onlyException; + protected $onlyMasterRequests; + protected $exception; + protected $profiles; + protected $requestStack; + protected $parents; + + /** + * @param bool $onlyException True if the profiler only collects data when an exception occurs, false otherwise + * @param bool $onlyMasterRequests True if the profiler only collects data when the request is a master request, false otherwise + */ + public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMasterRequests = false) + { + $this->profiler = $profiler; + $this->matcher = $matcher; + $this->onlyException = $onlyException; + $this->onlyMasterRequests = $onlyMasterRequests; + $this->profiles = new \SplObjectStorage(); + $this->parents = new \SplObjectStorage(); + $this->requestStack = $requestStack; + } + + /** + * Handles the onKernelException event. + */ + public function onKernelException(ExceptionEvent $event) + { + if ($this->onlyMasterRequests && !$event->isMasterRequest()) { + return; + } + + $this->exception = $event->getThrowable(); + } + + /** + * Handles the onKernelResponse event. + */ + public function onKernelResponse(ResponseEvent $event) + { + $master = $event->isMasterRequest(); + if ($this->onlyMasterRequests && !$master) { + return; + } + + if ($this->onlyException && null === $this->exception) { + return; + } + + $request = $event->getRequest(); + $exception = $this->exception; + $this->exception = null; + + if (null !== $this->matcher && !$this->matcher->matches($request)) { + return; + } + + if (!$profile = $this->profiler->collect($request, $event->getResponse(), $exception)) { + return; + } + + $this->profiles[$request] = $profile; + + $this->parents[$request] = $this->requestStack->getParentRequest(); + } + + public function onKernelTerminate(TerminateEvent $event) + { + // attach children to parents + foreach ($this->profiles as $request) { + if (null !== $parentRequest = $this->parents[$request]) { + if (isset($this->profiles[$parentRequest])) { + $this->profiles[$parentRequest]->addChild($this->profiles[$request]); + } + } + } + + // save profiles + foreach ($this->profiles as $request) { + $this->profiler->saveProfile($this->profiles[$request]); + } + + $this->profiles = new \SplObjectStorage(); + $this->parents = new \SplObjectStorage(); + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::RESPONSE => ['onKernelResponse', -100], + KernelEvents::EXCEPTION => ['onKernelException', 0], + KernelEvents::TERMINATE => ['onKernelTerminate', -1024], + ]; + } +} diff --git a/vendor/symfony/http-kernel/EventListener/ResponseListener.php b/vendor/symfony/http-kernel/EventListener/ResponseListener.php new file mode 100644 index 0000000..d8292ae --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/ResponseListener.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * ResponseListener fixes the Response headers based on the Request. + * + * @author Fabien Potencier + * + * @final + */ +class ResponseListener implements EventSubscriberInterface +{ + private $charset; + + public function __construct(string $charset) + { + $this->charset = $charset; + } + + /** + * Filters the Response. + */ + public function onKernelResponse(ResponseEvent $event) + { + if (!$event->isMasterRequest()) { + return; + } + + $response = $event->getResponse(); + + if (null === $response->getCharset()) { + $response->setCharset($this->charset); + } + + $response->prepare($event->getRequest()); + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::RESPONSE => 'onKernelResponse', + ]; + } +} diff --git a/vendor/symfony/http-kernel/EventListener/RouterListener.php b/vendor/symfony/http-kernel/EventListener/RouterListener.php new file mode 100644 index 0000000..31bbc3b --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/RouterListener.php @@ -0,0 +1,175 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Psr\Log\LoggerInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; +use Symfony\Component\HttpKernel\Event\FinishRequestEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\Routing\Exception\MethodNotAllowedException; +use Symfony\Component\Routing\Exception\NoConfigurationException; +use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\RequestMatcherInterface; +use Symfony\Component\Routing\Matcher\UrlMatcherInterface; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RequestContextAwareInterface; + +/** + * Initializes the context from the request and sets request attributes based on a matching route. + * + * @author Fabien Potencier + * @author Yonel Ceruto + * + * @final + */ +class RouterListener implements EventSubscriberInterface +{ + private $matcher; + private $context; + private $logger; + private $requestStack; + private $projectDir; + private $debug; + + /** + * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher + * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface) + * @param string $projectDir + * + * @throws \InvalidArgumentException + */ + public function __construct($matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null, string $projectDir = null, bool $debug = true) + { + if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) { + throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); + } + + if (null === $context && !$matcher instanceof RequestContextAwareInterface) { + throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.'); + } + + $this->matcher = $matcher; + $this->context = $context ?: $matcher->getContext(); + $this->requestStack = $requestStack; + $this->logger = $logger; + $this->projectDir = $projectDir; + $this->debug = $debug; + } + + private function setCurrentRequest(Request $request = null) + { + if (null !== $request) { + try { + $this->context->fromRequest($request); + } catch (\UnexpectedValueException $e) { + throw new BadRequestHttpException($e->getMessage(), $e, $e->getCode()); + } + } + } + + /** + * After a sub-request is done, we need to reset the routing context to the parent request so that the URL generator + * operates on the correct context again. + */ + public function onKernelFinishRequest(FinishRequestEvent $event) + { + $this->setCurrentRequest($this->requestStack->getParentRequest()); + } + + public function onKernelRequest(RequestEvent $event) + { + $request = $event->getRequest(); + + $this->setCurrentRequest($request); + + if ($request->attributes->has('_controller')) { + // routing is already done + return; + } + + // add attributes based on the request (routing) + try { + // matching a request is more powerful than matching a URL path + context, so try that first + if ($this->matcher instanceof RequestMatcherInterface) { + $parameters = $this->matcher->matchRequest($request); + } else { + $parameters = $this->matcher->match($request->getPathInfo()); + } + + if (null !== $this->logger) { + $this->logger->info('Matched route "{route}".', [ + 'route' => isset($parameters['_route']) ? $parameters['_route'] : 'n/a', + 'route_parameters' => $parameters, + 'request_uri' => $request->getUri(), + 'method' => $request->getMethod(), + ]); + } + + $request->attributes->add($parameters); + unset($parameters['_route'], $parameters['_controller']); + $request->attributes->set('_route_params', $parameters); + } catch (ResourceNotFoundException $e) { + $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo()); + + if ($referer = $request->headers->get('referer')) { + $message .= sprintf(' (from "%s")', $referer); + } + + throw new NotFoundHttpException($message, $e); + } catch (MethodNotAllowedException $e) { + $message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getPathInfo(), implode(', ', $e->getAllowedMethods())); + + throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e); + } + } + + public function onKernelException(ExceptionEvent $event) + { + if (!$this->debug || !($e = $event->getThrowable()) instanceof NotFoundHttpException) { + return; + } + + if ($e->getPrevious() instanceof NoConfigurationException) { + $event->setResponse($this->createWelcomeResponse()); + } + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::REQUEST => [['onKernelRequest', 32]], + KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]], + KernelEvents::EXCEPTION => ['onKernelException', -64], + ]; + } + + private function createWelcomeResponse(): Response + { + $version = Kernel::VERSION; + $projectDir = realpath($this->projectDir).\DIRECTORY_SEPARATOR; + $docVersion = substr(Kernel::VERSION, 0, 3); + + ob_start(); + include \dirname(__DIR__).'/Resources/welcome.html.php'; + + return new Response(ob_get_clean(), Response::HTTP_NOT_FOUND); + } +} diff --git a/vendor/symfony/http-kernel/EventListener/SessionListener.php b/vendor/symfony/http-kernel/EventListener/SessionListener.php new file mode 100644 index 0000000..a53ade7 --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/SessionListener.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Psr\Container\ContainerInterface; +use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; + +/** + * Sets the session in the request. + * + * When the passed container contains a "session_storage" entry which + * holds a NativeSessionStorage instance, the "cookie_secure" option + * will be set to true whenever the current master request is secure. + * + * @author Fabien Potencier + * + * @final + */ +class SessionListener extends AbstractSessionListener +{ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + protected function getSession(): ?SessionInterface + { + if (!$this->container->has('session')) { + return null; + } + + if ($this->container->has('session_storage') + && ($storage = $this->container->get('session_storage')) instanceof NativeSessionStorage + && ($masterRequest = $this->container->get('request_stack')->getMasterRequest()) + && $masterRequest->isSecure() + ) { + $storage->setOptions(['cookie_secure' => true]); + } + + return $this->container->get('session'); + } +} diff --git a/vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php b/vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php new file mode 100644 index 0000000..730ee54 --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\StreamedResponse; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * StreamedResponseListener is responsible for sending the Response + * to the client. + * + * @author Fabien Potencier + * + * @final + */ +class StreamedResponseListener implements EventSubscriberInterface +{ + /** + * Filters the Response. + */ + public function onKernelResponse(ResponseEvent $event) + { + if (!$event->isMasterRequest()) { + return; + } + + $response = $event->getResponse(); + + if ($response instanceof StreamedResponse) { + $response->send(); + } + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::RESPONSE => ['onKernelResponse', -1024], + ]; + } +} diff --git a/vendor/symfony/http-kernel/EventListener/SurrogateListener.php b/vendor/symfony/http-kernel/EventListener/SurrogateListener.php new file mode 100644 index 0000000..2ef4af7 --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/SurrogateListener.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\HttpCache\HttpCache; +use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * SurrogateListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for Surrogates. + * + * @author Fabien Potencier + * + * @final + */ +class SurrogateListener implements EventSubscriberInterface +{ + private $surrogate; + + public function __construct(SurrogateInterface $surrogate = null) + { + $this->surrogate = $surrogate; + } + + /** + * Filters the Response. + */ + public function onKernelResponse(ResponseEvent $event) + { + if (!$event->isMasterRequest()) { + return; + } + + $kernel = $event->getKernel(); + $surrogate = $this->surrogate; + if ($kernel instanceof HttpCache) { + $surrogate = $kernel->getSurrogate(); + if (null !== $this->surrogate && $this->surrogate->getName() !== $surrogate->getName()) { + $surrogate = $this->surrogate; + } + } + + if (null === $surrogate) { + return; + } + + $surrogate->addSurrogateControl($event->getResponse()); + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::RESPONSE => 'onKernelResponse', + ]; + } +} diff --git a/vendor/symfony/http-kernel/EventListener/TestSessionListener.php b/vendor/symfony/http-kernel/EventListener/TestSessionListener.php new file mode 100644 index 0000000..ff8b4aa --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/TestSessionListener.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Psr\Container\ContainerInterface; +use Symfony\Component\HttpFoundation\Session\SessionInterface; + +/** + * Sets the session in the request. + * + * @author Fabien Potencier + * + * @final + */ +class TestSessionListener extends AbstractTestSessionListener +{ + private $container; + + public function __construct(ContainerInterface $container, array $sessionOptions = []) + { + $this->container = $container; + parent::__construct($sessionOptions); + } + + protected function getSession(): ?SessionInterface + { + if (!$this->container->has('session')) { + return null; + } + + return $this->container->get('session'); + } +} diff --git a/vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php b/vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php new file mode 100644 index 0000000..1f0c798 --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * Validates Requests. + * + * @author Magnus Nordlander + * + * @final + */ +class ValidateRequestListener implements EventSubscriberInterface +{ + /** + * Performs the validation. + */ + public function onKernelRequest(RequestEvent $event) + { + if (!$event->isMasterRequest()) { + return; + } + $request = $event->getRequest(); + + if ($request::getTrustedProxies()) { + $request->getClientIps(); + } + + $request->getHost(); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::REQUEST => [ + ['onKernelRequest', 256], + ], + ]; + } +} diff --git a/vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php b/vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php new file mode 100644 index 0000000..65e5f8c --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Fabien Potencier + * @author Christophe Coevoet + */ +class AccessDeniedHttpException extends HttpException +{ + /** + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + { + parent::__construct(403, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/BadRequestHttpException.php b/vendor/symfony/http-kernel/Exception/BadRequestHttpException.php new file mode 100644 index 0000000..7de9105 --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/BadRequestHttpException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Ben Ramsey + */ +class BadRequestHttpException extends HttpException +{ + /** + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + { + parent::__construct(400, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/ConflictHttpException.php b/vendor/symfony/http-kernel/Exception/ConflictHttpException.php new file mode 100644 index 0000000..ebb86ba --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/ConflictHttpException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Ben Ramsey + */ +class ConflictHttpException extends HttpException +{ + /** + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + { + parent::__construct(409, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php b/vendor/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php new file mode 100644 index 0000000..1e87690 --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Grégoire Pineau + */ +class ControllerDoesNotReturnResponseException extends \LogicException +{ + public function __construct(string $message, callable $controller, string $file, int $line) + { + parent::__construct($message); + + if (!$controllerDefinition = $this->parseControllerDefinition($controller)) { + return; + } + + $this->file = $controllerDefinition['file']; + $this->line = $controllerDefinition['line']; + $r = new \ReflectionProperty(\Exception::class, 'trace'); + $r->setAccessible(true); + $r->setValue($this, array_merge([ + [ + 'line' => $line, + 'file' => $file, + ], + ], $this->getTrace())); + } + + private function parseControllerDefinition(callable $controller): ?array + { + if (\is_string($controller) && false !== strpos($controller, '::')) { + $controller = explode('::', $controller); + } + + if (\is_array($controller)) { + try { + $r = new \ReflectionMethod($controller[0], $controller[1]); + + return [ + 'file' => $r->getFileName(), + 'line' => $r->getEndLine(), + ]; + } catch (\ReflectionException $e) { + return null; + } + } + + if ($controller instanceof \Closure) { + $r = new \ReflectionFunction($controller); + + return [ + 'file' => $r->getFileName(), + 'line' => $r->getEndLine(), + ]; + } + + if (\is_object($controller)) { + $r = new \ReflectionClass($controller); + + try { + $line = $r->getMethod('__invoke')->getEndLine(); + } catch (\ReflectionException $e) { + $line = $r->getEndLine(); + } + + return [ + 'file' => $r->getFileName(), + 'line' => $line, + ]; + } + + return null; + } +} diff --git a/vendor/symfony/http-kernel/Exception/GoneHttpException.php b/vendor/symfony/http-kernel/Exception/GoneHttpException.php new file mode 100644 index 0000000..aea283a --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/GoneHttpException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Ben Ramsey + */ +class GoneHttpException extends HttpException +{ + /** + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + { + parent::__construct(410, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/HttpException.php b/vendor/symfony/http-kernel/Exception/HttpException.php new file mode 100644 index 0000000..d822cd5 --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/HttpException.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * HttpException. + * + * @author Kris Wallsmith + */ +class HttpException extends \RuntimeException implements HttpExceptionInterface +{ + private $statusCode; + private $headers; + + public function __construct(int $statusCode, string $message = null, \Throwable $previous = null, array $headers = [], ?int $code = 0) + { + $this->statusCode = $statusCode; + $this->headers = $headers; + + parent::__construct($message, $code, $previous); + } + + public function getStatusCode() + { + return $this->statusCode; + } + + public function getHeaders() + { + return $this->headers; + } + + /** + * Set response headers. + * + * @param array $headers Response headers + */ + public function setHeaders(array $headers) + { + $this->headers = $headers; + } +} diff --git a/vendor/symfony/http-kernel/Exception/HttpExceptionInterface.php b/vendor/symfony/http-kernel/Exception/HttpExceptionInterface.php new file mode 100644 index 0000000..735e9c8 --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/HttpExceptionInterface.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * Interface for HTTP error exceptions. + * + * @author Kris Wallsmith + */ +interface HttpExceptionInterface extends \Throwable +{ + /** + * Returns the status code. + * + * @return int An HTTP response status code + */ + public function getStatusCode(); + + /** + * Returns response headers. + * + * @return array Response headers + */ + public function getHeaders(); +} diff --git a/vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php b/vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php new file mode 100644 index 0000000..44fb770 --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Ben Ramsey + */ +class LengthRequiredHttpException extends HttpException +{ + /** + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + { + parent::__construct(411, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php b/vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php new file mode 100644 index 0000000..c15e46f --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Kris Wallsmith + */ +class MethodNotAllowedHttpException extends HttpException +{ + /** + * @param array $allow An array of allowed methods + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct(array $allow, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + { + $headers['Allow'] = strtoupper(implode(', ', $allow)); + + parent::__construct(405, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.php b/vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.php new file mode 100644 index 0000000..c5f5324 --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Ben Ramsey + */ +class NotAcceptableHttpException extends HttpException +{ + /** + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + { + parent::__construct(406, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/NotFoundHttpException.php b/vendor/symfony/http-kernel/Exception/NotFoundHttpException.php new file mode 100644 index 0000000..146b908 --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/NotFoundHttpException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Fabien Potencier + */ +class NotFoundHttpException extends HttpException +{ + /** + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + { + parent::__construct(404, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php b/vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php new file mode 100644 index 0000000..e878b10 --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Ben Ramsey + */ +class PreconditionFailedHttpException extends HttpException +{ + /** + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + { + parent::__construct(412, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php b/vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php new file mode 100644 index 0000000..a6cb2f0 --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Ben Ramsey + * + * @see http://tools.ietf.org/html/rfc6585 + */ +class PreconditionRequiredHttpException extends HttpException +{ + /** + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + { + parent::__construct(428, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php b/vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php new file mode 100644 index 0000000..c786ccf --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Ben Ramsey + */ +class ServiceUnavailableHttpException extends HttpException +{ + /** + * @param int|string $retryAfter The number of seconds or HTTP-date after which the request may be retried + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct($retryAfter = null, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + { + if ($retryAfter) { + $headers['Retry-After'] = $retryAfter; + } + + parent::__construct(503, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php b/vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php new file mode 100644 index 0000000..b709f1a --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Ben Ramsey + * + * @see http://tools.ietf.org/html/rfc6585 + */ +class TooManyRequestsHttpException extends HttpException +{ + /** + * @param int|string $retryAfter The number of seconds or HTTP-date after which the request may be retried + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct($retryAfter = null, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + { + if ($retryAfter) { + $headers['Retry-After'] = $retryAfter; + } + + parent::__construct(429, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php b/vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php new file mode 100644 index 0000000..fb86c1e --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Ben Ramsey + */ +class UnauthorizedHttpException extends HttpException +{ + /** + * @param string $challenge WWW-Authenticate challenge string + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct(string $challenge, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + { + $headers['WWW-Authenticate'] = $challenge; + + parent::__construct(401, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php b/vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php new file mode 100644 index 0000000..93d4bce --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Steve Hutchins + */ +class UnprocessableEntityHttpException extends HttpException +{ + /** + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + { + parent::__construct(422, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php b/vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php new file mode 100644 index 0000000..7cda3a6 --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Ben Ramsey + */ +class UnsupportedMediaTypeHttpException extends HttpException +{ + /** + * @param string $message The internal exception message + * @param \Throwable $previous The previous exception + * @param int $code The internal exception code + */ + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) + { + parent::__construct(415, $message, $previous, $headers, $code); + } +} diff --git a/vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php new file mode 100644 index 0000000..f81199d --- /dev/null +++ b/vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Fragment; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Controller\ControllerReference; +use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface; +use Symfony\Component\HttpKernel\UriSigner; + +/** + * Implements Surrogate rendering strategy. + * + * @author Fabien Potencier + */ +abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRenderer +{ + private $surrogate; + private $inlineStrategy; + private $signer; + + /** + * The "fallback" strategy when surrogate is not available should always be an + * instance of InlineFragmentRenderer. + * + * @param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported + */ + public function __construct(SurrogateInterface $surrogate = null, FragmentRendererInterface $inlineStrategy, UriSigner $signer = null) + { + $this->surrogate = $surrogate; + $this->inlineStrategy = $inlineStrategy; + $this->signer = $signer; + } + + /** + * {@inheritdoc} + * + * Note that if the current Request has no surrogate capability, this method + * falls back to use the inline rendering strategy. + * + * Additional available options: + * + * * alt: an alternative URI to render in case of an error + * * comment: a comment to add when returning the surrogate tag + * + * Note, that not all surrogate strategies support all options. For now + * 'alt' and 'comment' are only supported by ESI. + * + * @see Symfony\Component\HttpKernel\HttpCache\SurrogateInterface + */ + public function render($uri, Request $request, array $options = []) + { + if (!$this->surrogate || !$this->surrogate->hasSurrogateCapability($request)) { + if ($uri instanceof ControllerReference && $this->containsNonScalars($uri->attributes)) { + throw new \InvalidArgumentException('Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is not supported. Use a different rendering strategy or pass scalar values.'); + } + + return $this->inlineStrategy->render($uri, $request, $options); + } + + if ($uri instanceof ControllerReference) { + $uri = $this->generateSignedFragmentUri($uri, $request); + } + + $alt = isset($options['alt']) ? $options['alt'] : null; + if ($alt instanceof ControllerReference) { + $alt = $this->generateSignedFragmentUri($alt, $request); + } + + $tag = $this->surrogate->renderIncludeTag($uri, $alt, isset($options['ignore_errors']) ? $options['ignore_errors'] : false, isset($options['comment']) ? $options['comment'] : ''); + + return new Response($tag); + } + + private function generateSignedFragmentUri(ControllerReference $uri, Request $request): string + { + if (null === $this->signer) { + throw new \LogicException('You must use a URI when using the ESI rendering strategy or set a URL signer.'); + } + + // we need to sign the absolute URI, but want to return the path only. + $fragmentUri = $this->signer->sign($this->generateFragmentUri($uri, $request, true)); + + return substr($fragmentUri, \strlen($request->getSchemeAndHttpHost())); + } + + private function containsNonScalars(array $values): bool + { + foreach ($values as $value) { + if (\is_array($value)) { + return $this->containsNonScalars($value); + } elseif (!is_scalar($value) && null !== $value) { + return true; + } + } + + return false; + } +} diff --git a/vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.php new file mode 100644 index 0000000..a4570e3 --- /dev/null +++ b/vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Fragment; + +/** + * Implements the ESI rendering strategy. + * + * @author Fabien Potencier + */ +class EsiFragmentRenderer extends AbstractSurrogateFragmentRenderer +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'esi'; + } +} diff --git a/vendor/symfony/http-kernel/Fragment/FragmentHandler.php b/vendor/symfony/http-kernel/Fragment/FragmentHandler.php new file mode 100644 index 0000000..f3d3f0d --- /dev/null +++ b/vendor/symfony/http-kernel/Fragment/FragmentHandler.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Fragment; + +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\StreamedResponse; +use Symfony\Component\HttpKernel\Controller\ControllerReference; + +/** + * Renders a URI that represents a resource fragment. + * + * This class handles the rendering of resource fragments that are included into + * a main resource. The handling of the rendering is managed by specialized renderers. + * + * @author Fabien Potencier + * + * @see FragmentRendererInterface + */ +class FragmentHandler +{ + private $debug; + private $renderers = []; + private $requestStack; + + /** + * @param FragmentRendererInterface[] $renderers An array of FragmentRendererInterface instances + * @param bool $debug Whether the debug mode is enabled or not + */ + public function __construct(RequestStack $requestStack, array $renderers = [], bool $debug = false) + { + $this->requestStack = $requestStack; + foreach ($renderers as $renderer) { + $this->addRenderer($renderer); + } + $this->debug = $debug; + } + + /** + * Adds a renderer. + */ + public function addRenderer(FragmentRendererInterface $renderer) + { + $this->renderers[$renderer->getName()] = $renderer; + } + + /** + * Renders a URI and returns the Response content. + * + * Available options: + * + * * ignore_errors: true to return an empty string in case of an error + * + * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance + * + * @return string|null The Response content or null when the Response is streamed + * + * @throws \InvalidArgumentException when the renderer does not exist + * @throws \LogicException when no master request is being handled + */ + public function render($uri, string $renderer = 'inline', array $options = []) + { + if (!isset($options['ignore_errors'])) { + $options['ignore_errors'] = !$this->debug; + } + + if (!isset($this->renderers[$renderer])) { + throw new \InvalidArgumentException(sprintf('The "%s" renderer does not exist.', $renderer)); + } + + if (!$request = $this->requestStack->getCurrentRequest()) { + throw new \LogicException('Rendering a fragment can only be done when handling a Request.'); + } + + return $this->deliver($this->renderers[$renderer]->render($uri, $request, $options)); + } + + /** + * Delivers the Response as a string. + * + * When the Response is a StreamedResponse, the content is streamed immediately + * instead of being returned. + * + * @return string|null The Response content or null when the Response is streamed + * + * @throws \RuntimeException when the Response is not successful + */ + protected function deliver(Response $response) + { + if (!$response->isSuccessful()) { + throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $this->requestStack->getCurrentRequest()->getUri(), $response->getStatusCode())); + } + + if (!$response instanceof StreamedResponse) { + return $response->getContent(); + } + + $response->sendContent(); + + return null; + } +} diff --git a/vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php b/vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php new file mode 100644 index 0000000..4f8ac50 --- /dev/null +++ b/vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Fragment; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Controller\ControllerReference; + +/** + * Interface implemented by all rendering strategies. + * + * @author Fabien Potencier + */ +interface FragmentRendererInterface +{ + /** + * Renders a URI and returns the Response content. + * + * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance + * + * @return Response A Response instance + */ + public function render($uri, Request $request, array $options = []); + + /** + * Gets the name of the strategy. + * + * @return string The strategy name + */ + public function getName(); +} diff --git a/vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php new file mode 100644 index 0000000..9db6557 --- /dev/null +++ b/vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Fragment; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Controller\ControllerReference; +use Symfony\Component\HttpKernel\UriSigner; +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Loader\ExistsLoaderInterface; +use Twig\Loader\SourceContextLoaderInterface; + +/** + * Implements the Hinclude rendering strategy. + * + * @author Fabien Potencier + */ +class HIncludeFragmentRenderer extends RoutableFragmentRenderer +{ + private $globalDefaultTemplate; + private $signer; + private $twig; + private $charset; + + /** + * @param string $globalDefaultTemplate The global default content (it can be a template name or the content) + */ + public function __construct(Environment $twig = null, UriSigner $signer = null, string $globalDefaultTemplate = null, string $charset = 'utf-8') + { + $this->twig = $twig; + $this->globalDefaultTemplate = $globalDefaultTemplate; + $this->signer = $signer; + $this->charset = $charset; + } + + /** + * Checks if a templating engine has been set. + * + * @return bool true if the templating engine has been set, false otherwise + */ + public function hasTemplating() + { + return null !== $this->twig; + } + + /** + * {@inheritdoc} + * + * Additional available options: + * + * * default: The default content (it can be a template name or the content) + * * id: An optional hx:include tag id attribute + * * attributes: An optional array of hx:include tag attributes + */ + public function render($uri, Request $request, array $options = []) + { + if ($uri instanceof ControllerReference) { + if (null === $this->signer) { + throw new \LogicException('You must use a proper URI when using the Hinclude rendering strategy or set a URL signer.'); + } + + // we need to sign the absolute URI, but want to return the path only. + $uri = substr($this->signer->sign($this->generateFragmentUri($uri, $request, true)), \strlen($request->getSchemeAndHttpHost())); + } + + // We need to replace ampersands in the URI with the encoded form in order to return valid html/xml content. + $uri = str_replace('&', '&', $uri); + + $template = isset($options['default']) ? $options['default'] : $this->globalDefaultTemplate; + if (null !== $this->twig && $template && $this->twig->getLoader()->exists($template)) { + $content = $this->twig->render($template); + } else { + $content = $template; + } + + $attributes = isset($options['attributes']) && \is_array($options['attributes']) ? $options['attributes'] : []; + if (isset($options['id']) && $options['id']) { + $attributes['id'] = $options['id']; + } + $renderedAttributes = ''; + if (\count($attributes) > 0) { + $flags = ENT_QUOTES | ENT_SUBSTITUTE; + foreach ($attributes as $attribute => $value) { + $renderedAttributes .= sprintf( + ' %s="%s"', + htmlspecialchars($attribute, $flags, $this->charset, false), + htmlspecialchars($value, $flags, $this->charset, false) + ); + } + } + + return new Response(sprintf('%s', $uri, $renderedAttributes, $content)); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'hinclude'; + } +} diff --git a/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php new file mode 100644 index 0000000..3bbdbd3 --- /dev/null +++ b/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php @@ -0,0 +1,145 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Fragment; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Controller\ControllerReference; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; +use Symfony\Component\HttpKernel\HttpCache\SubRequestHandler; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; + +/** + * Implements the inline rendering strategy where the Request is rendered by the current HTTP kernel. + * + * @author Fabien Potencier + */ +class InlineFragmentRenderer extends RoutableFragmentRenderer +{ + private $kernel; + private $dispatcher; + + public function __construct(HttpKernelInterface $kernel, EventDispatcherInterface $dispatcher = null) + { + $this->kernel = $kernel; + $this->dispatcher = $dispatcher; + } + + /** + * {@inheritdoc} + * + * Additional available options: + * + * * alt: an alternative URI to render in case of an error + */ + public function render($uri, Request $request, array $options = []) + { + $reference = null; + if ($uri instanceof ControllerReference) { + $reference = $uri; + + // Remove attributes from the generated URI because if not, the Symfony + // routing system will use them to populate the Request attributes. We don't + // want that as we want to preserve objects (so we manually set Request attributes + // below instead) + $attributes = $reference->attributes; + $reference->attributes = []; + + // The request format and locale might have been overridden by the user + foreach (['_format', '_locale'] as $key) { + if (isset($attributes[$key])) { + $reference->attributes[$key] = $attributes[$key]; + } + } + + $uri = $this->generateFragmentUri($uri, $request, false, false); + + $reference->attributes = array_merge($attributes, $reference->attributes); + } + + $subRequest = $this->createSubRequest($uri, $request); + + // override Request attributes as they can be objects (which are not supported by the generated URI) + if (null !== $reference) { + $subRequest->attributes->add($reference->attributes); + } + + $level = ob_get_level(); + try { + return SubRequestHandler::handle($this->kernel, $subRequest, HttpKernelInterface::SUB_REQUEST, false); + } catch (\Exception $e) { + // we dispatch the exception event to trigger the logging + // the response that comes back is ignored + if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) { + $event = new ExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e); + + $this->dispatcher->dispatch($event, KernelEvents::EXCEPTION); + } + + // let's clean up the output buffers that were created by the sub-request + Response::closeOutputBuffers($level, false); + + if (isset($options['alt'])) { + $alt = $options['alt']; + unset($options['alt']); + + return $this->render($alt, $request, $options); + } + + if (!isset($options['ignore_errors']) || !$options['ignore_errors']) { + throw $e; + } + + return new Response(); + } + } + + protected function createSubRequest($uri, Request $request) + { + $cookies = $request->cookies->all(); + $server = $request->server->all(); + + unset($server['HTTP_IF_MODIFIED_SINCE']); + unset($server['HTTP_IF_NONE_MATCH']); + + $subRequest = Request::create($uri, 'get', [], $cookies, [], $server); + if ($request->headers->has('Surrogate-Capability')) { + $subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability')); + } + + static $setSession; + + if (null === $setSession) { + $setSession = \Closure::bind(static function ($subRequest, $request) { $subRequest->session = $request->session; }, null, Request::class); + } + $setSession($subRequest, $request); + + if ($request->get('_format')) { + $subRequest->attributes->set('_format', $request->get('_format')); + } + if ($request->getDefaultLocale() !== $request->getLocale()) { + $subRequest->setLocale($request->getLocale()); + } + + return $subRequest; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'inline'; + } +} diff --git a/vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php new file mode 100644 index 0000000..c9a1757 --- /dev/null +++ b/vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Fragment; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ControllerReference; +use Symfony\Component\HttpKernel\EventListener\FragmentListener; + +/** + * Adds the possibility to generate a fragment URI for a given Controller. + * + * @author Fabien Potencier + */ +abstract class RoutableFragmentRenderer implements FragmentRendererInterface +{ + private $fragmentPath = '/_fragment'; + + /** + * Sets the fragment path that triggers the fragment listener. + * + * @see FragmentListener + */ + public function setFragmentPath(string $path) + { + $this->fragmentPath = $path; + } + + /** + * Generates a fragment URI for a given controller. + * + * @param bool $absolute Whether to generate an absolute URL or not + * @param bool $strict Whether to allow non-scalar attributes or not + * + * @return string A fragment URI + */ + protected function generateFragmentUri(ControllerReference $reference, Request $request, bool $absolute = false, bool $strict = true) + { + if ($strict) { + $this->checkNonScalar($reference->attributes); + } + + // We need to forward the current _format and _locale values as we don't have + // a proper routing pattern to do the job for us. + // This makes things inconsistent if you switch from rendering a controller + // to rendering a route if the route pattern does not contain the special + // _format and _locale placeholders. + if (!isset($reference->attributes['_format'])) { + $reference->attributes['_format'] = $request->getRequestFormat(); + } + if (!isset($reference->attributes['_locale'])) { + $reference->attributes['_locale'] = $request->getLocale(); + } + + $reference->attributes['_controller'] = $reference->controller; + + $reference->query['_path'] = http_build_query($reference->attributes, '', '&'); + + $path = $this->fragmentPath.'?'.http_build_query($reference->query, '', '&'); + + if ($absolute) { + return $request->getUriForPath($path); + } + + return $request->getBaseUrl().$path; + } + + private function checkNonScalar(array $values) + { + foreach ($values as $key => $value) { + if (\is_array($value)) { + $this->checkNonScalar($value); + } elseif (!is_scalar($value) && null !== $value) { + throw new \LogicException(sprintf('Controller attributes cannot contain non-scalar/non-null values (value for key "%s" is not a scalar or null).', $key)); + } + } + } +} diff --git a/vendor/symfony/http-kernel/Fragment/SsiFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/SsiFragmentRenderer.php new file mode 100644 index 0000000..45e7122 --- /dev/null +++ b/vendor/symfony/http-kernel/Fragment/SsiFragmentRenderer.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Fragment; + +/** + * Implements the SSI rendering strategy. + * + * @author Sebastian Krebs + */ +class SsiFragmentRenderer extends AbstractSurrogateFragmentRenderer +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'ssi'; + } +} diff --git a/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php b/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php new file mode 100644 index 0000000..ac2c341 --- /dev/null +++ b/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\HttpCache; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * Abstract class implementing Surrogate capabilities to Request and Response instances. + * + * @author Fabien Potencier + * @author Robin Chalas + */ +abstract class AbstractSurrogate implements SurrogateInterface +{ + protected $contentTypes; + protected $phpEscapeMap = [ + ['', '', '', ''], + ]; + + /** + * @param array $contentTypes An array of content-type that should be parsed for Surrogate information + * (default: text/html, text/xml, application/xhtml+xml, and application/xml) + */ + public function __construct(array $contentTypes = ['text/html', 'text/xml', 'application/xhtml+xml', 'application/xml']) + { + $this->contentTypes = $contentTypes; + } + + /** + * Returns a new cache strategy instance. + * + * @return ResponseCacheStrategyInterface A ResponseCacheStrategyInterface instance + */ + public function createCacheStrategy() + { + return new ResponseCacheStrategy(); + } + + /** + * {@inheritdoc} + */ + public function hasSurrogateCapability(Request $request) + { + if (null === $value = $request->headers->get('Surrogate-Capability')) { + return false; + } + + return false !== strpos($value, sprintf('%s/1.0', strtoupper($this->getName()))); + } + + /** + * {@inheritdoc} + */ + public function addSurrogateCapability(Request $request) + { + $current = $request->headers->get('Surrogate-Capability'); + $new = sprintf('symfony="%s/1.0"', strtoupper($this->getName())); + + $request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new); + } + + /** + * {@inheritdoc} + */ + public function needsParsing(Response $response) + { + if (!$control = $response->headers->get('Surrogate-Control')) { + return false; + } + + $pattern = sprintf('#content="[^"]*%s/1.0[^"]*"#', strtoupper($this->getName())); + + return (bool) preg_match($pattern, $control); + } + + /** + * {@inheritdoc} + */ + public function handle(HttpCache $cache, string $uri, string $alt, bool $ignoreErrors) + { + $subRequest = Request::create($uri, Request::METHOD_GET, [], $cache->getRequest()->cookies->all(), [], $cache->getRequest()->server->all()); + + try { + $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true); + + if (!$response->isSuccessful()) { + throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode())); + } + + return $response->getContent(); + } catch (\Exception $e) { + if ($alt) { + return $this->handle($cache, $alt, '', $ignoreErrors); + } + + if (!$ignoreErrors) { + throw $e; + } + } + + return ''; + } + + /** + * Remove the Surrogate from the Surrogate-Control header. + */ + protected function removeFromControl(Response $response) + { + if (!$response->headers->has('Surrogate-Control')) { + return; + } + + $value = $response->headers->get('Surrogate-Control'); + $upperName = strtoupper($this->getName()); + + if (sprintf('content="%s/1.0"', $upperName) == $value) { + $response->headers->remove('Surrogate-Control'); + } elseif (preg_match(sprintf('#,\s*content="%s/1.0"#', $upperName), $value)) { + $response->headers->set('Surrogate-Control', preg_replace(sprintf('#,\s*content="%s/1.0"#', $upperName), '', $value)); + } elseif (preg_match(sprintf('#content="%s/1.0",\s*#', $upperName), $value)) { + $response->headers->set('Surrogate-Control', preg_replace(sprintf('#content="%s/1.0",\s*#', $upperName), '', $value)); + } + } +} diff --git a/vendor/symfony/http-kernel/HttpCache/Esi.php b/vendor/symfony/http-kernel/HttpCache/Esi.php new file mode 100644 index 0000000..af67e8f --- /dev/null +++ b/vendor/symfony/http-kernel/HttpCache/Esi.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\HttpCache; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * Esi implements the ESI capabilities to Request and Response instances. + * + * For more information, read the following W3C notes: + * + * * ESI Language Specification 1.0 (http://www.w3.org/TR/esi-lang) + * + * * Edge Architecture Specification (http://www.w3.org/TR/edge-arch) + * + * @author Fabien Potencier + */ +class Esi extends AbstractSurrogate +{ + public function getName() + { + return 'esi'; + } + + /** + * {@inheritdoc} + */ + public function addSurrogateControl(Response $response) + { + if (false !== strpos($response->getContent(), 'headers->set('Surrogate-Control', 'content="ESI/1.0"'); + } + } + + /** + * {@inheritdoc} + */ + public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = '') + { + $html = sprintf('', + $uri, + $ignoreErrors ? ' onerror="continue"' : '', + $alt ? sprintf(' alt="%s"', $alt) : '' + ); + + if (!empty($comment)) { + return sprintf("\n%s", $comment, $html); + } + + return $html; + } + + /** + * {@inheritdoc} + */ + public function process(Request $request, Response $response) + { + $type = $response->headers->get('Content-Type'); + if (empty($type)) { + $type = 'text/html'; + } + + $parts = explode(';', $type); + if (!\in_array($parts[0], $this->contentTypes)) { + return $response; + } + + // we don't use a proper XML parser here as we can have ESI tags in a plain text response + $content = $response->getContent(); + $content = preg_replace('#.*?#s', '', $content); + $content = preg_replace('#]+>#s', '', $content); + + $chunks = preg_split('##', $content, -1, PREG_SPLIT_DELIM_CAPTURE); + $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]); + + $i = 1; + while (isset($chunks[$i])) { + $options = []; + preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER); + foreach ($matches as $set) { + $options[$set[1]] = $set[2]; + } + + if (!isset($options['src'])) { + throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.'); + } + + $chunks[$i] = sprintf('surrogate->handle($this, %s, %s, %s) ?>'."\n", + var_export($options['src'], true), + var_export(isset($options['alt']) ? $options['alt'] : '', true), + isset($options['onerror']) && 'continue' === $options['onerror'] ? 'true' : 'false' + ); + ++$i; + $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]); + ++$i; + } + $content = implode('', $chunks); + + $response->setContent($content); + $response->headers->set('X-Body-Eval', 'ESI'); + + // remove ESI/1.0 from the Surrogate-Control header + $this->removeFromControl($response); + + return $response; + } +} diff --git a/vendor/symfony/http-kernel/HttpCache/HttpCache.php b/vendor/symfony/http-kernel/HttpCache/HttpCache.php new file mode 100644 index 0000000..698af72 --- /dev/null +++ b/vendor/symfony/http-kernel/HttpCache/HttpCache.php @@ -0,0 +1,707 @@ + + * + * This code is partially based on the Rack-Cache library by Ryan Tomayko, + * which is released under the MIT license. + * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\HttpCache; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\TerminableInterface; + +/** + * Cache provides HTTP caching. + * + * @author Fabien Potencier + */ +class HttpCache implements HttpKernelInterface, TerminableInterface +{ + private $kernel; + private $store; + private $request; + private $surrogate; + private $surrogateCacheStrategy; + private $options = []; + private $traces = []; + + /** + * Constructor. + * + * The available options are: + * + * * debug If true, exceptions are thrown when things go wrong. Otherwise, the cache + * will try to carry on and deliver a meaningful response. + * + * * trace_level May be one of 'none', 'short' and 'full'. For 'short', a concise trace of the + * master request will be added as an HTTP header. 'full' will add traces for all + * requests (including ESI subrequests). (default: 'full' if in debug; 'none' otherwise) + * + * * trace_header Header name to use for traces. (default: X-Symfony-Cache) + * + * * default_ttl The number of seconds that a cache entry should be considered + * fresh when no explicit freshness information is provided in + * a response. Explicit Cache-Control or Expires headers + * override this value. (default: 0) + * + * * private_headers Set of request headers that trigger "private" cache-control behavior + * on responses that don't explicitly state whether the response is + * public or private via a Cache-Control directive. (default: Authorization and Cookie) + * + * * allow_reload Specifies whether the client can force a cache reload by including a + * Cache-Control "no-cache" directive in the request. Set it to ``true`` + * for compliance with RFC 2616. (default: false) + * + * * allow_revalidate Specifies whether the client can force a cache revalidate by including + * a Cache-Control "max-age=0" directive in the request. Set it to ``true`` + * for compliance with RFC 2616. (default: false) + * + * * stale_while_revalidate Specifies the default number of seconds (the granularity is the second as the + * Response TTL precision is a second) during which the cache can immediately return + * a stale response while it revalidates it in the background (default: 2). + * This setting is overridden by the stale-while-revalidate HTTP Cache-Control + * extension (see RFC 5861). + * + * * stale_if_error Specifies the default number of seconds (the granularity is the second) during which + * the cache can serve a stale response when an error is encountered (default: 60). + * This setting is overridden by the stale-if-error HTTP Cache-Control extension + * (see RFC 5861). + */ + public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = []) + { + $this->store = $store; + $this->kernel = $kernel; + $this->surrogate = $surrogate; + + // needed in case there is a fatal error because the backend is too slow to respond + register_shutdown_function([$this->store, 'cleanup']); + + $this->options = array_merge([ + 'debug' => false, + 'default_ttl' => 0, + 'private_headers' => ['Authorization', 'Cookie'], + 'allow_reload' => false, + 'allow_revalidate' => false, + 'stale_while_revalidate' => 2, + 'stale_if_error' => 60, + 'trace_level' => 'none', + 'trace_header' => 'X-Symfony-Cache', + ], $options); + + if (!isset($options['trace_level'])) { + $this->options['trace_level'] = $this->options['debug'] ? 'full' : 'none'; + } + } + + /** + * Gets the current store. + * + * @return StoreInterface A StoreInterface instance + */ + public function getStore() + { + return $this->store; + } + + /** + * Returns an array of events that took place during processing of the last request. + * + * @return array An array of events + */ + public function getTraces() + { + return $this->traces; + } + + private function addTraces(Response $response) + { + $traceString = null; + + if ('full' === $this->options['trace_level']) { + $traceString = $this->getLog(); + } + + if ('short' === $this->options['trace_level'] && $masterId = array_key_first($this->traces)) { + $traceString = implode('/', $this->traces[$masterId]); + } + + if (null !== $traceString) { + $response->headers->add([$this->options['trace_header'] => $traceString]); + } + } + + /** + * Returns a log message for the events of the last request processing. + * + * @return string A log message + */ + public function getLog() + { + $log = []; + foreach ($this->traces as $request => $traces) { + $log[] = sprintf('%s: %s', $request, implode(', ', $traces)); + } + + return implode('; ', $log); + } + + /** + * Gets the Request instance associated with the master request. + * + * @return Request A Request instance + */ + public function getRequest() + { + return $this->request; + } + + /** + * Gets the Kernel instance. + * + * @return HttpKernelInterface An HttpKernelInterface instance + */ + public function getKernel() + { + return $this->kernel; + } + + /** + * Gets the Surrogate instance. + * + * @return SurrogateInterface A Surrogate instance + * + * @throws \LogicException + */ + public function getSurrogate() + { + return $this->surrogate; + } + + /** + * {@inheritdoc} + */ + public function handle(Request $request, int $type = HttpKernelInterface::MASTER_REQUEST, bool $catch = true) + { + // FIXME: catch exceptions and implement a 500 error page here? -> in Varnish, there is a built-in error page mechanism + if (HttpKernelInterface::MASTER_REQUEST === $type) { + $this->traces = []; + // Keep a clone of the original request for surrogates so they can access it. + // We must clone here to get a separate instance because the application will modify the request during + // the application flow (we know it always does because we do ourselves by setting REMOTE_ADDR to 127.0.0.1 + // and adding the X-Forwarded-For header, see HttpCache::forward()). + $this->request = clone $request; + if (null !== $this->surrogate) { + $this->surrogateCacheStrategy = $this->surrogate->createCacheStrategy(); + } + } + + $this->traces[$this->getTraceKey($request)] = []; + + if (!$request->isMethodSafe()) { + $response = $this->invalidate($request, $catch); + } elseif ($request->headers->has('expect') || !$request->isMethodCacheable()) { + $response = $this->pass($request, $catch); + } elseif ($this->options['allow_reload'] && $request->isNoCache()) { + /* + If allow_reload is configured and the client requests "Cache-Control: no-cache", + reload the cache by fetching a fresh response and caching it (if possible). + */ + $this->record($request, 'reload'); + $response = $this->fetch($request, $catch); + } else { + $response = $this->lookup($request, $catch); + } + + $this->restoreResponseBody($request, $response); + + if (HttpKernelInterface::MASTER_REQUEST === $type) { + $this->addTraces($response); + } + + if (null !== $this->surrogate) { + if (HttpKernelInterface::MASTER_REQUEST === $type) { + $this->surrogateCacheStrategy->update($response); + } else { + $this->surrogateCacheStrategy->add($response); + } + } + + $response->prepare($request); + + $response->isNotModified($request); + + return $response; + } + + /** + * {@inheritdoc} + */ + public function terminate(Request $request, Response $response) + { + if ($this->getKernel() instanceof TerminableInterface) { + $this->getKernel()->terminate($request, $response); + } + } + + /** + * Forwards the Request to the backend without storing the Response in the cache. + * + * @param bool $catch Whether to process exceptions + * + * @return Response A Response instance + */ + protected function pass(Request $request, bool $catch = false) + { + $this->record($request, 'pass'); + + return $this->forward($request, $catch); + } + + /** + * Invalidates non-safe methods (like POST, PUT, and DELETE). + * + * @param bool $catch Whether to process exceptions + * + * @return Response A Response instance + * + * @throws \Exception + * + * @see RFC2616 13.10 + */ + protected function invalidate(Request $request, bool $catch = false) + { + $response = $this->pass($request, $catch); + + // invalidate only when the response is successful + if ($response->isSuccessful() || $response->isRedirect()) { + try { + $this->store->invalidate($request); + + // As per the RFC, invalidate Location and Content-Location URLs if present + foreach (['Location', 'Content-Location'] as $header) { + if ($uri = $response->headers->get($header)) { + $subRequest = Request::create($uri, 'get', [], [], [], $request->server->all()); + + $this->store->invalidate($subRequest); + } + } + + $this->record($request, 'invalidate'); + } catch (\Exception $e) { + $this->record($request, 'invalidate-failed'); + + if ($this->options['debug']) { + throw $e; + } + } + } + + return $response; + } + + /** + * Lookups a Response from the cache for the given Request. + * + * When a matching cache entry is found and is fresh, it uses it as the + * response without forwarding any request to the backend. When a matching + * cache entry is found but is stale, it attempts to "validate" the entry with + * the backend using conditional GET. When no matching cache entry is found, + * it triggers "miss" processing. + * + * @param bool $catch Whether to process exceptions + * + * @return Response A Response instance + * + * @throws \Exception + */ + protected function lookup(Request $request, bool $catch = false) + { + try { + $entry = $this->store->lookup($request); + } catch (\Exception $e) { + $this->record($request, 'lookup-failed'); + + if ($this->options['debug']) { + throw $e; + } + + return $this->pass($request, $catch); + } + + if (null === $entry) { + $this->record($request, 'miss'); + + return $this->fetch($request, $catch); + } + + if (!$this->isFreshEnough($request, $entry)) { + $this->record($request, 'stale'); + + return $this->validate($request, $entry, $catch); + } + + $this->record($request, 'fresh'); + + $entry->headers->set('Age', $entry->getAge()); + + return $entry; + } + + /** + * Validates that a cache entry is fresh. + * + * The original request is used as a template for a conditional + * GET request with the backend. + * + * @param bool $catch Whether to process exceptions + * + * @return Response A Response instance + */ + protected function validate(Request $request, Response $entry, bool $catch = false) + { + $subRequest = clone $request; + + // send no head requests because we want content + if ('HEAD' === $request->getMethod()) { + $subRequest->setMethod('GET'); + } + + // add our cached last-modified validator + if ($entry->headers->has('Last-Modified')) { + $subRequest->headers->set('if_modified_since', $entry->headers->get('Last-Modified')); + } + + // Add our cached etag validator to the environment. + // We keep the etags from the client to handle the case when the client + // has a different private valid entry which is not cached here. + $cachedEtags = $entry->getEtag() ? [$entry->getEtag()] : []; + $requestEtags = $request->getETags(); + if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) { + $subRequest->headers->set('if_none_match', implode(', ', $etags)); + } + + $response = $this->forward($subRequest, $catch, $entry); + + if (304 == $response->getStatusCode()) { + $this->record($request, 'valid'); + + // return the response and not the cache entry if the response is valid but not cached + $etag = $response->getEtag(); + if ($etag && \in_array($etag, $requestEtags) && !\in_array($etag, $cachedEtags)) { + return $response; + } + + $entry = clone $entry; + $entry->headers->remove('Date'); + + foreach (['Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified'] as $name) { + if ($response->headers->has($name)) { + $entry->headers->set($name, $response->headers->get($name)); + } + } + + $response = $entry; + } else { + $this->record($request, 'invalid'); + } + + if ($response->isCacheable()) { + $this->store($request, $response); + } + + return $response; + } + + /** + * Unconditionally fetches a fresh response from the backend and + * stores it in the cache if is cacheable. + * + * @param bool $catch Whether to process exceptions + * + * @return Response A Response instance + */ + protected function fetch(Request $request, bool $catch = false) + { + $subRequest = clone $request; + + // send no head requests because we want content + if ('HEAD' === $request->getMethod()) { + $subRequest->setMethod('GET'); + } + + // avoid that the backend sends no content + $subRequest->headers->remove('if_modified_since'); + $subRequest->headers->remove('if_none_match'); + + $response = $this->forward($subRequest, $catch); + + if ($response->isCacheable()) { + $this->store($request, $response); + } + + return $response; + } + + /** + * Forwards the Request to the backend and returns the Response. + * + * All backend requests (cache passes, fetches, cache validations) + * run through this method. + * + * @param bool $catch Whether to catch exceptions or not + * @param Response|null $entry A Response instance (the stale entry if present, null otherwise) + * + * @return Response A Response instance + */ + protected function forward(Request $request, bool $catch = false, Response $entry = null) + { + if ($this->surrogate) { + $this->surrogate->addSurrogateCapability($request); + } + + // always a "master" request (as the real master request can be in cache) + $response = SubRequestHandler::handle($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $catch); + + // we don't implement the stale-if-error on Requests, which is nonetheless part of the RFC + if (null !== $entry && \in_array($response->getStatusCode(), [500, 502, 503, 504])) { + if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) { + $age = $this->options['stale_if_error']; + } + + if (abs($entry->getTtl()) < $age) { + $this->record($request, 'stale-if-error'); + + return $entry; + } + } + + /* + RFC 7231 Sect. 7.1.1.2 says that a server that does not have a reasonably accurate + clock MUST NOT send a "Date" header, although it MUST send one in most other cases + except for 1xx or 5xx responses where it MAY do so. + + Anyway, a client that received a message without a "Date" header MUST add it. + */ + if (!$response->headers->has('Date')) { + $response->setDate(\DateTime::createFromFormat('U', time())); + } + + $this->processResponseBody($request, $response); + + if ($this->isPrivateRequest($request) && !$response->headers->hasCacheControlDirective('public')) { + $response->setPrivate(); + } elseif ($this->options['default_ttl'] > 0 && null === $response->getTtl() && !$response->headers->getCacheControlDirective('must-revalidate')) { + $response->setTtl($this->options['default_ttl']); + } + + return $response; + } + + /** + * Checks whether the cache entry is "fresh enough" to satisfy the Request. + * + * @return bool true if the cache entry if fresh enough, false otherwise + */ + protected function isFreshEnough(Request $request, Response $entry) + { + if (!$entry->isFresh()) { + return $this->lock($request, $entry); + } + + if ($this->options['allow_revalidate'] && null !== $maxAge = $request->headers->getCacheControlDirective('max-age')) { + return $maxAge > 0 && $maxAge >= $entry->getAge(); + } + + return true; + } + + /** + * Locks a Request during the call to the backend. + * + * @return bool true if the cache entry can be returned even if it is staled, false otherwise + */ + protected function lock(Request $request, Response $entry) + { + // try to acquire a lock to call the backend + $lock = $this->store->lock($request); + + if (true === $lock) { + // we have the lock, call the backend + return false; + } + + // there is already another process calling the backend + + // May we serve a stale response? + if ($this->mayServeStaleWhileRevalidate($entry)) { + $this->record($request, 'stale-while-revalidate'); + + return true; + } + + // wait for the lock to be released + if ($this->waitForLock($request)) { + // replace the current entry with the fresh one + $new = $this->lookup($request); + $entry->headers = $new->headers; + $entry->setContent($new->getContent()); + $entry->setStatusCode($new->getStatusCode()); + $entry->setProtocolVersion($new->getProtocolVersion()); + foreach ($new->headers->getCookies() as $cookie) { + $entry->headers->setCookie($cookie); + } + } else { + // backend is slow as hell, send a 503 response (to avoid the dog pile effect) + $entry->setStatusCode(503); + $entry->setContent('503 Service Unavailable'); + $entry->headers->set('Retry-After', 10); + } + + return true; + } + + /** + * Writes the Response to the cache. + * + * @throws \Exception + */ + protected function store(Request $request, Response $response) + { + try { + $this->store->write($request, $response); + + $this->record($request, 'store'); + + $response->headers->set('Age', $response->getAge()); + } catch (\Exception $e) { + $this->record($request, 'store-failed'); + + if ($this->options['debug']) { + throw $e; + } + } + + // now that the response is cached, release the lock + $this->store->unlock($request); + } + + /** + * Restores the Response body. + */ + private function restoreResponseBody(Request $request, Response $response) + { + if ($response->headers->has('X-Body-Eval')) { + ob_start(); + + if ($response->headers->has('X-Body-File')) { + include $response->headers->get('X-Body-File'); + } else { + eval('; ?>'.$response->getContent().'setContent(ob_get_clean()); + $response->headers->remove('X-Body-Eval'); + if (!$response->headers->has('Transfer-Encoding')) { + $response->headers->set('Content-Length', \strlen($response->getContent())); + } + } elseif ($response->headers->has('X-Body-File')) { + // Response does not include possibly dynamic content (ESI, SSI), so we need + // not handle the content for HEAD requests + if (!$request->isMethod('HEAD')) { + $response->setContent(file_get_contents($response->headers->get('X-Body-File'))); + } + } else { + return; + } + + $response->headers->remove('X-Body-File'); + } + + protected function processResponseBody(Request $request, Response $response) + { + if (null !== $this->surrogate && $this->surrogate->needsParsing($response)) { + $this->surrogate->process($request, $response); + } + } + + /** + * Checks if the Request includes authorization or other sensitive information + * that should cause the Response to be considered private by default. + */ + private function isPrivateRequest(Request $request): bool + { + foreach ($this->options['private_headers'] as $key) { + $key = strtolower(str_replace('HTTP_', '', $key)); + + if ('cookie' === $key) { + if (\count($request->cookies->all())) { + return true; + } + } elseif ($request->headers->has($key)) { + return true; + } + } + + return false; + } + + /** + * Records that an event took place. + */ + private function record(Request $request, string $event) + { + $this->traces[$this->getTraceKey($request)][] = $event; + } + + /** + * Calculates the key we use in the "trace" array for a given request. + */ + private function getTraceKey(Request $request): string + { + $path = $request->getPathInfo(); + if ($qs = $request->getQueryString()) { + $path .= '?'.$qs; + } + + return $request->getMethod().' '.$path; + } + + /** + * Checks whether the given (cached) response may be served as "stale" when a revalidation + * is currently in progress. + */ + private function mayServeStaleWhileRevalidate(Response $entry): bool + { + $timeout = $entry->headers->getCacheControlDirective('stale-while-revalidate'); + + if (null === $timeout) { + $timeout = $this->options['stale_while_revalidate']; + } + + return abs($entry->getTtl()) < $timeout; + } + + /** + * Waits for the store to release a locked entry. + */ + private function waitForLock(Request $request): bool + { + $wait = 0; + while ($this->store->isLocked($request) && $wait < 100) { + usleep(50000); + ++$wait; + } + + return $wait < 100; + } +} diff --git a/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php b/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php new file mode 100644 index 0000000..c30ffac --- /dev/null +++ b/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php @@ -0,0 +1,213 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\HttpCache; + +use Symfony\Component\HttpFoundation\Response; + +/** + * ResponseCacheStrategy knows how to compute the Response cache HTTP header + * based on the different response cache headers. + * + * This implementation changes the master response TTL to the smallest TTL received + * or force validation if one of the surrogates has validation cache strategy. + * + * @author Fabien Potencier + */ +class ResponseCacheStrategy implements ResponseCacheStrategyInterface +{ + /** + * Cache-Control headers that are sent to the final response if they appear in ANY of the responses. + */ + private static $overrideDirectives = ['private', 'no-cache', 'no-store', 'no-transform', 'must-revalidate', 'proxy-revalidate']; + + /** + * Cache-Control headers that are sent to the final response if they appear in ALL of the responses. + */ + private static $inheritDirectives = ['public', 'immutable']; + + private $embeddedResponses = 0; + private $isNotCacheableResponseEmbedded = false; + private $age = 0; + private $flagDirectives = [ + 'no-cache' => null, + 'no-store' => null, + 'no-transform' => null, + 'must-revalidate' => null, + 'proxy-revalidate' => null, + 'public' => null, + 'private' => null, + 'immutable' => null, + ]; + private $ageDirectives = [ + 'max-age' => null, + 's-maxage' => null, + 'expires' => null, + ]; + + /** + * {@inheritdoc} + */ + public function add(Response $response) + { + ++$this->embeddedResponses; + + foreach (self::$overrideDirectives as $directive) { + if ($response->headers->hasCacheControlDirective($directive)) { + $this->flagDirectives[$directive] = true; + } + } + + foreach (self::$inheritDirectives as $directive) { + if (false !== $this->flagDirectives[$directive]) { + $this->flagDirectives[$directive] = $response->headers->hasCacheControlDirective($directive); + } + } + + $age = $response->getAge(); + $this->age = max($this->age, $age); + + if ($this->willMakeFinalResponseUncacheable($response)) { + $this->isNotCacheableResponseEmbedded = true; + + return; + } + + $this->storeRelativeAgeDirective('max-age', $response->headers->getCacheControlDirective('max-age'), $age); + $this->storeRelativeAgeDirective('s-maxage', $response->headers->getCacheControlDirective('s-maxage') ?: $response->headers->getCacheControlDirective('max-age'), $age); + + $expires = $response->getExpires(); + $expires = null !== $expires ? (int) $expires->format('U') - (int) $response->getDate()->format('U') : null; + $this->storeRelativeAgeDirective('expires', $expires >= 0 ? $expires : null, 0); + } + + /** + * {@inheritdoc} + */ + public function update(Response $response) + { + // if we have no embedded Response, do nothing + if (0 === $this->embeddedResponses) { + return; + } + + // Remove validation related headers of the master response, + // because some of the response content comes from at least + // one embedded response (which likely has a different caching strategy). + $response->setEtag(null); + $response->setLastModified(null); + + $this->add($response); + + $response->headers->set('Age', $this->age); + + if ($this->isNotCacheableResponseEmbedded) { + if ($this->flagDirectives['no-store']) { + $response->headers->set('Cache-Control', 'no-cache, no-store, must-revalidate'); + } else { + $response->headers->set('Cache-Control', 'no-cache, must-revalidate'); + } + + return; + } + + $flags = array_filter($this->flagDirectives); + + if (isset($flags['must-revalidate'])) { + $flags['no-cache'] = true; + } + + $response->headers->set('Cache-Control', implode(', ', array_keys($flags))); + + $maxAge = null; + + if (is_numeric($this->ageDirectives['max-age'])) { + $maxAge = $this->ageDirectives['max-age'] + $this->age; + $response->headers->addCacheControlDirective('max-age', $maxAge); + } + + if (is_numeric($this->ageDirectives['s-maxage'])) { + $sMaxage = $this->ageDirectives['s-maxage'] + $this->age; + + if ($maxAge !== $sMaxage) { + $response->headers->addCacheControlDirective('s-maxage', $sMaxage); + } + } + + if (is_numeric($this->ageDirectives['expires'])) { + $date = clone $response->getDate(); + $date->modify('+'.($this->ageDirectives['expires'] + $this->age).' seconds'); + $response->setExpires($date); + } + } + + /** + * RFC2616, Section 13.4. + * + * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4 + */ + private function willMakeFinalResponseUncacheable(Response $response): bool + { + // RFC2616: A response received with a status code of 200, 203, 300, 301 or 410 + // MAY be stored by a cache […] unless a cache-control directive prohibits caching. + if ($response->headers->hasCacheControlDirective('no-cache') + || $response->headers->getCacheControlDirective('no-store') + ) { + return true; + } + + // Last-Modified and Etag headers cannot be merged, they render the response uncacheable + // by default (except if the response also has max-age etc.). + if (\in_array($response->getStatusCode(), [200, 203, 300, 301, 410]) + && null === $response->getLastModified() + && null === $response->getEtag() + ) { + return false; + } + + // RFC2616: A response received with any other status code (e.g. status codes 302 and 307) + // MUST NOT be returned in a reply to a subsequent request unless there are + // cache-control directives or another header(s) that explicitly allow it. + $cacheControl = ['max-age', 's-maxage', 'must-revalidate', 'proxy-revalidate', 'public', 'private']; + foreach ($cacheControl as $key) { + if ($response->headers->hasCacheControlDirective($key)) { + return false; + } + } + + if ($response->headers->has('Expires')) { + return false; + } + + return true; + } + + /** + * Store lowest max-age/s-maxage/expires for the final response. + * + * The response might have been stored in cache a while ago. To keep things comparable, + * we have to subtract the age so that the value is normalized for an age of 0. + * + * If the value is lower than the currently stored value, we update the value, to keep a rolling + * minimal value of each instruction. If the value is NULL, the directive will not be set on the final response. + */ + private function storeRelativeAgeDirective(string $directive, ?int $value, int $age) + { + if (null === $value) { + $this->ageDirectives[$directive] = false; + } + + if (false !== $this->ageDirectives[$directive]) { + $value -= $age; + $this->ageDirectives[$directive] = null !== $this->ageDirectives[$directive] ? min($this->ageDirectives[$directive], $value) : $value; + } + } +} diff --git a/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php b/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php new file mode 100644 index 0000000..e282299 --- /dev/null +++ b/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php @@ -0,0 +1,37 @@ + + * + * This code is partially based on the Rack-Cache library by Ryan Tomayko, + * which is released under the MIT license. + * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\HttpCache; + +use Symfony\Component\HttpFoundation\Response; + +/** + * ResponseCacheStrategyInterface implementations know how to compute the + * Response cache HTTP header based on the different response cache headers. + * + * @author Fabien Potencier + */ +interface ResponseCacheStrategyInterface +{ + /** + * Adds a Response. + */ + public function add(Response $response); + + /** + * Updates the Response HTTP headers based on the embedded Responses. + */ + public function update(Response $response); +} diff --git a/vendor/symfony/http-kernel/HttpCache/Ssi.php b/vendor/symfony/http-kernel/HttpCache/Ssi.php new file mode 100644 index 0000000..587c43a --- /dev/null +++ b/vendor/symfony/http-kernel/HttpCache/Ssi.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\HttpCache; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * Ssi implements the SSI capabilities to Request and Response instances. + * + * @author Sebastian Krebs + */ +class Ssi extends AbstractSurrogate +{ + /** + * {@inheritdoc} + */ + public function getName() + { + return 'ssi'; + } + + /** + * {@inheritdoc} + */ + public function addSurrogateControl(Response $response) + { + if (false !== strpos($response->getContent(), '', $uri); + } + + /** + * {@inheritdoc} + */ + public function process(Request $request, Response $response) + { + $type = $response->headers->get('Content-Type'); + if (empty($type)) { + $type = 'text/html'; + } + + $parts = explode(';', $type); + if (!\in_array($parts[0], $this->contentTypes)) { + return $response; + } + + // we don't use a proper XML parser here as we can have SSI tags in a plain text response + $content = $response->getContent(); + + $chunks = preg_split('##', $content, -1, PREG_SPLIT_DELIM_CAPTURE); + $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]); + + $i = 1; + while (isset($chunks[$i])) { + $options = []; + preg_match_all('/(virtual)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER); + foreach ($matches as $set) { + $options[$set[1]] = $set[2]; + } + + if (!isset($options['virtual'])) { + throw new \RuntimeException('Unable to process an SSI tag without a "virtual" attribute.'); + } + + $chunks[$i] = sprintf('surrogate->handle($this, %s, \'\', false) ?>'."\n", + var_export($options['virtual'], true) + ); + ++$i; + $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]); + ++$i; + } + $content = implode('', $chunks); + + $response->setContent($content); + $response->headers->set('X-Body-Eval', 'SSI'); + + // remove SSI/1.0 from the Surrogate-Control header + $this->removeFromControl($response); + + return $response; + } +} diff --git a/vendor/symfony/http-kernel/HttpCache/Store.php b/vendor/symfony/http-kernel/HttpCache/Store.php new file mode 100644 index 0000000..b7953e1 --- /dev/null +++ b/vendor/symfony/http-kernel/HttpCache/Store.php @@ -0,0 +1,460 @@ + + * + * This code is partially based on the Rack-Cache library by Ryan Tomayko, + * which is released under the MIT license. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\HttpCache; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * Store implements all the logic for storing cache metadata (Request and Response headers). + * + * @author Fabien Potencier + */ +class Store implements StoreInterface +{ + protected $root; + private $keyCache; + private $locks; + + /** + * @throws \RuntimeException + */ + public function __construct(string $root) + { + $this->root = $root; + if (!file_exists($this->root) && !@mkdir($this->root, 0777, true) && !is_dir($this->root)) { + throw new \RuntimeException(sprintf('Unable to create the store directory (%s).', $this->root)); + } + $this->keyCache = new \SplObjectStorage(); + $this->locks = []; + } + + /** + * Cleanups storage. + */ + public function cleanup() + { + // unlock everything + foreach ($this->locks as $lock) { + flock($lock, LOCK_UN); + fclose($lock); + } + + $this->locks = []; + } + + /** + * Tries to lock the cache for a given Request, without blocking. + * + * @return bool|string true if the lock is acquired, the path to the current lock otherwise + */ + public function lock(Request $request) + { + $key = $this->getCacheKey($request); + + if (!isset($this->locks[$key])) { + $path = $this->getPath($key); + if (!file_exists(\dirname($path)) && false === @mkdir(\dirname($path), 0777, true) && !is_dir(\dirname($path))) { + return $path; + } + $h = fopen($path, 'cb'); + if (!flock($h, LOCK_EX | LOCK_NB)) { + fclose($h); + + return $path; + } + + $this->locks[$key] = $h; + } + + return true; + } + + /** + * Releases the lock for the given Request. + * + * @return bool False if the lock file does not exist or cannot be unlocked, true otherwise + */ + public function unlock(Request $request) + { + $key = $this->getCacheKey($request); + + if (isset($this->locks[$key])) { + flock($this->locks[$key], LOCK_UN); + fclose($this->locks[$key]); + unset($this->locks[$key]); + + return true; + } + + return false; + } + + public function isLocked(Request $request) + { + $key = $this->getCacheKey($request); + + if (isset($this->locks[$key])) { + return true; // shortcut if lock held by this process + } + + if (!file_exists($path = $this->getPath($key))) { + return false; + } + + $h = fopen($path, 'rb'); + flock($h, LOCK_EX | LOCK_NB, $wouldBlock); + flock($h, LOCK_UN); // release the lock we just acquired + fclose($h); + + return (bool) $wouldBlock; + } + + /** + * Locates a cached Response for the Request provided. + * + * @return Response|null A Response instance, or null if no cache entry was found + */ + public function lookup(Request $request) + { + $key = $this->getCacheKey($request); + + if (!$entries = $this->getMetadata($key)) { + return null; + } + + // find a cached entry that matches the request. + $match = null; + foreach ($entries as $entry) { + if ($this->requestsMatch(isset($entry[1]['vary'][0]) ? implode(', ', $entry[1]['vary']) : '', $request->headers->all(), $entry[0])) { + $match = $entry; + + break; + } + } + + if (null === $match) { + return null; + } + + $headers = $match[1]; + if (file_exists($body = $this->getPath($headers['x-content-digest'][0]))) { + return $this->restoreResponse($headers, $body); + } + + // TODO the metaStore referenced an entity that doesn't exist in + // the entityStore. We definitely want to return nil but we should + // also purge the entry from the meta-store when this is detected. + return null; + } + + /** + * Writes a cache entry to the store for the given Request and Response. + * + * Existing entries are read and any that match the response are removed. This + * method calls write with the new list of cache entries. + * + * @return string The key under which the response is stored + * + * @throws \RuntimeException + */ + public function write(Request $request, Response $response) + { + $key = $this->getCacheKey($request); + $storedEnv = $this->persistRequest($request); + + // write the response body to the entity store if this is the original response + if (!$response->headers->has('X-Content-Digest')) { + $digest = $this->generateContentDigest($response); + + if (!$this->save($digest, $response->getContent())) { + throw new \RuntimeException('Unable to store the entity.'); + } + + $response->headers->set('X-Content-Digest', $digest); + + if (!$response->headers->has('Transfer-Encoding')) { + $response->headers->set('Content-Length', \strlen($response->getContent())); + } + } + + // read existing cache entries, remove non-varying, and add this one to the list + $entries = []; + $vary = $response->headers->get('vary'); + foreach ($this->getMetadata($key) as $entry) { + if (!isset($entry[1]['vary'][0])) { + $entry[1]['vary'] = ['']; + } + + if ($entry[1]['vary'][0] != $vary || !$this->requestsMatch($vary ?? '', $entry[0], $storedEnv)) { + $entries[] = $entry; + } + } + + $headers = $this->persistResponse($response); + unset($headers['age']); + + array_unshift($entries, [$storedEnv, $headers]); + + if (!$this->save($key, serialize($entries))) { + throw new \RuntimeException('Unable to store the metadata.'); + } + + return $key; + } + + /** + * Returns content digest for $response. + * + * @return string + */ + protected function generateContentDigest(Response $response) + { + return 'en'.hash('sha256', $response->getContent()); + } + + /** + * Invalidates all cache entries that match the request. + * + * @throws \RuntimeException + */ + public function invalidate(Request $request) + { + $modified = false; + $key = $this->getCacheKey($request); + + $entries = []; + foreach ($this->getMetadata($key) as $entry) { + $response = $this->restoreResponse($entry[1]); + if ($response->isFresh()) { + $response->expire(); + $modified = true; + $entries[] = [$entry[0], $this->persistResponse($response)]; + } else { + $entries[] = $entry; + } + } + + if ($modified && !$this->save($key, serialize($entries))) { + throw new \RuntimeException('Unable to store the metadata.'); + } + } + + /** + * Determines whether two Request HTTP header sets are non-varying based on + * the vary response header value provided. + * + * @param string|null $vary A Response vary header + * @param array $env1 A Request HTTP header array + * @param array $env2 A Request HTTP header array + */ + private function requestsMatch(?string $vary, array $env1, array $env2): bool + { + if (empty($vary)) { + return true; + } + + foreach (preg_split('/[\s,]+/', $vary) as $header) { + $key = str_replace('_', '-', strtolower($header)); + $v1 = isset($env1[$key]) ? $env1[$key] : null; + $v2 = isset($env2[$key]) ? $env2[$key] : null; + if ($v1 !== $v2) { + return false; + } + } + + return true; + } + + /** + * Gets all data associated with the given key. + * + * Use this method only if you know what you are doing. + */ + private function getMetadata(string $key): array + { + if (!$entries = $this->load($key)) { + return []; + } + + return unserialize($entries); + } + + /** + * Purges data for the given URL. + * + * This method purges both the HTTP and the HTTPS version of the cache entry. + * + * @return bool true if the URL exists with either HTTP or HTTPS scheme and has been purged, false otherwise + */ + public function purge(string $url) + { + $http = preg_replace('#^https:#', 'http:', $url); + $https = preg_replace('#^http:#', 'https:', $url); + + $purgedHttp = $this->doPurge($http); + $purgedHttps = $this->doPurge($https); + + return $purgedHttp || $purgedHttps; + } + + /** + * Purges data for the given URL. + */ + private function doPurge(string $url): bool + { + $key = $this->getCacheKey(Request::create($url)); + if (isset($this->locks[$key])) { + flock($this->locks[$key], LOCK_UN); + fclose($this->locks[$key]); + unset($this->locks[$key]); + } + + if (file_exists($path = $this->getPath($key))) { + unlink($path); + + return true; + } + + return false; + } + + /** + * Loads data for the given key. + */ + private function load(string $key): ?string + { + $path = $this->getPath($key); + + return file_exists($path) && false !== ($contents = file_get_contents($path)) ? $contents : null; + } + + /** + * Save data for the given key. + */ + private function save(string $key, string $data): bool + { + $path = $this->getPath($key); + + if (isset($this->locks[$key])) { + $fp = $this->locks[$key]; + @ftruncate($fp, 0); + @fseek($fp, 0); + $len = @fwrite($fp, $data); + if (\strlen($data) !== $len) { + @ftruncate($fp, 0); + + return false; + } + } else { + if (!file_exists(\dirname($path)) && false === @mkdir(\dirname($path), 0777, true) && !is_dir(\dirname($path))) { + return false; + } + + $tmpFile = tempnam(\dirname($path), basename($path)); + if (false === $fp = @fopen($tmpFile, 'wb')) { + @unlink($tmpFile); + + return false; + } + @fwrite($fp, $data); + @fclose($fp); + + if ($data != file_get_contents($tmpFile)) { + @unlink($tmpFile); + + return false; + } + + if (false === @rename($tmpFile, $path)) { + @unlink($tmpFile); + + return false; + } + } + + @chmod($path, 0666 & ~umask()); + + return true; + } + + public function getPath(string $key) + { + return $this->root.\DIRECTORY_SEPARATOR.substr($key, 0, 2).\DIRECTORY_SEPARATOR.substr($key, 2, 2).\DIRECTORY_SEPARATOR.substr($key, 4, 2).\DIRECTORY_SEPARATOR.substr($key, 6); + } + + /** + * Generates a cache key for the given Request. + * + * This method should return a key that must only depend on a + * normalized version of the request URI. + * + * If the same URI can have more than one representation, based on some + * headers, use a Vary header to indicate them, and each representation will + * be stored independently under the same cache key. + * + * @return string A key for the given Request + */ + protected function generateCacheKey(Request $request) + { + return 'md'.hash('sha256', $request->getUri()); + } + + /** + * Returns a cache key for the given Request. + */ + private function getCacheKey(Request $request): string + { + if (isset($this->keyCache[$request])) { + return $this->keyCache[$request]; + } + + return $this->keyCache[$request] = $this->generateCacheKey($request); + } + + /** + * Persists the Request HTTP headers. + */ + private function persistRequest(Request $request): array + { + return $request->headers->all(); + } + + /** + * Persists the Response HTTP headers. + */ + private function persistResponse(Response $response): array + { + $headers = $response->headers->all(); + $headers['X-Status'] = [$response->getStatusCode()]; + + return $headers; + } + + /** + * Restores a Response from the HTTP headers and body. + */ + private function restoreResponse(array $headers, string $body = null): Response + { + $status = $headers['X-Status'][0]; + unset($headers['X-Status']); + + if (null !== $body) { + $headers['X-Body-File'] = [$body]; + } + + return new Response($body, $status, $headers); + } +} diff --git a/vendor/symfony/http-kernel/HttpCache/StoreInterface.php b/vendor/symfony/http-kernel/HttpCache/StoreInterface.php new file mode 100644 index 0000000..49d88c2 --- /dev/null +++ b/vendor/symfony/http-kernel/HttpCache/StoreInterface.php @@ -0,0 +1,81 @@ + + * + * This code is partially based on the Rack-Cache library by Ryan Tomayko, + * which is released under the MIT license. + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\HttpCache; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * Interface implemented by HTTP cache stores. + * + * @author Fabien Potencier + */ +interface StoreInterface +{ + /** + * Locates a cached Response for the Request provided. + * + * @return Response|null A Response instance, or null if no cache entry was found + */ + public function lookup(Request $request); + + /** + * Writes a cache entry to the store for the given Request and Response. + * + * Existing entries are read and any that match the response are removed. This + * method calls write with the new list of cache entries. + * + * @return string The key under which the response is stored + */ + public function write(Request $request, Response $response); + + /** + * Invalidates all cache entries that match the request. + */ + public function invalidate(Request $request); + + /** + * Locks the cache for a given Request. + * + * @return bool|string true if the lock is acquired, the path to the current lock otherwise + */ + public function lock(Request $request); + + /** + * Releases the lock for the given Request. + * + * @return bool False if the lock file does not exist or cannot be unlocked, true otherwise + */ + public function unlock(Request $request); + + /** + * Returns whether or not a lock exists. + * + * @return bool true if lock exists, false otherwise + */ + public function isLocked(Request $request); + + /** + * Purges data for the given URL. + * + * @return bool true if the URL exists and has been purged, false otherwise + */ + public function purge(string $url); + + /** + * Cleanups storage. + */ + public function cleanup(); +} diff --git a/vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php b/vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php new file mode 100644 index 0000000..294b964 --- /dev/null +++ b/vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\HttpCache; + +use Symfony\Component\HttpFoundation\IpUtils; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class SubRequestHandler +{ + public static function handle(HttpKernelInterface $kernel, Request $request, int $type, bool $catch): Response + { + // save global state related to trusted headers and proxies + $trustedProxies = Request::getTrustedProxies(); + $trustedHeaderSet = Request::getTrustedHeaderSet(); + + // remove untrusted values + $remoteAddr = $request->server->get('REMOTE_ADDR'); + if (!IpUtils::checkIp($remoteAddr, $trustedProxies)) { + $trustedHeaders = [ + 'FORWARDED' => $trustedHeaderSet & Request::HEADER_FORWARDED, + 'X_FORWARDED_FOR' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_FOR, + 'X_FORWARDED_HOST' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_HOST, + 'X_FORWARDED_PROTO' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PROTO, + 'X_FORWARDED_PORT' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PORT, + ]; + foreach (array_filter($trustedHeaders) as $name => $key) { + $request->headers->remove($name); + $request->server->remove('HTTP_'.$name); + } + } + + // compute trusted values, taking any trusted proxies into account + $trustedIps = []; + $trustedValues = []; + foreach (array_reverse($request->getClientIps()) as $ip) { + $trustedIps[] = $ip; + $trustedValues[] = sprintf('for="%s"', $ip); + } + if ($ip !== $remoteAddr) { + $trustedIps[] = $remoteAddr; + $trustedValues[] = sprintf('for="%s"', $remoteAddr); + } + + // set trusted values, reusing as much as possible the global trusted settings + if (Request::HEADER_FORWARDED & $trustedHeaderSet) { + $trustedValues[0] .= sprintf(';host="%s";proto=%s', $request->getHttpHost(), $request->getScheme()); + $request->headers->set('Forwarded', $v = implode(', ', $trustedValues)); + $request->server->set('HTTP_FORWARDED', $v); + } + if (Request::HEADER_X_FORWARDED_FOR & $trustedHeaderSet) { + $request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps)); + $request->server->set('HTTP_X_FORWARDED_FOR', $v); + } elseif (!(Request::HEADER_FORWARDED & $trustedHeaderSet)) { + Request::setTrustedProxies($trustedProxies, $trustedHeaderSet | Request::HEADER_X_FORWARDED_FOR); + $request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps)); + $request->server->set('HTTP_X_FORWARDED_FOR', $v); + } + + // fix the client IP address by setting it to 127.0.0.1, + // which is the core responsibility of this method + $request->server->set('REMOTE_ADDR', '127.0.0.1'); + + // ensure 127.0.0.1 is set as trusted proxy + if (!IpUtils::checkIp('127.0.0.1', $trustedProxies)) { + Request::setTrustedProxies(array_merge($trustedProxies, ['127.0.0.1']), Request::getTrustedHeaderSet()); + } + + try { + return $kernel->handle($request, $type, $catch); + } finally { + // restore global state + Request::setTrustedProxies($trustedProxies, $trustedHeaderSet); + } + } +} diff --git a/vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php b/vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php new file mode 100644 index 0000000..53a7e2a --- /dev/null +++ b/vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\HttpCache; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +interface SurrogateInterface +{ + /** + * Returns surrogate name. + * + * @return string + */ + public function getName(); + + /** + * Returns a new cache strategy instance. + * + * @return ResponseCacheStrategyInterface A ResponseCacheStrategyInterface instance + */ + public function createCacheStrategy(); + + /** + * Checks that at least one surrogate has Surrogate capability. + * + * @return bool true if one surrogate has Surrogate capability, false otherwise + */ + public function hasSurrogateCapability(Request $request); + + /** + * Adds Surrogate-capability to the given Request. + */ + public function addSurrogateCapability(Request $request); + + /** + * Adds HTTP headers to specify that the Response needs to be parsed for Surrogate. + * + * This method only adds an Surrogate HTTP header if the Response has some Surrogate tags. + */ + public function addSurrogateControl(Response $response); + + /** + * Checks that the Response needs to be parsed for Surrogate tags. + * + * @return bool true if the Response needs to be parsed, false otherwise + */ + public function needsParsing(Response $response); + + /** + * Renders a Surrogate tag. + * + * @param string $alt An alternate URI + * @param string $comment A comment to add as an esi:include tag + * + * @return string + */ + public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = ''); + + /** + * Replaces a Response Surrogate tags with the included resource content. + * + * @return Response + */ + public function process(Request $request, Response $response); + + /** + * Handles a Surrogate from the cache. + * + * @param string $alt An alternative URI + * + * @return string + * + * @throws \RuntimeException + * @throws \Exception + */ + public function handle(HttpCache $cache, string $uri, string $alt, bool $ignoreErrors); +} diff --git a/vendor/symfony/http-kernel/HttpClientKernel.php b/vendor/symfony/http-kernel/HttpClientKernel.php new file mode 100644 index 0000000..10bac3a --- /dev/null +++ b/vendor/symfony/http-kernel/HttpClientKernel.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +use Symfony\Component\HttpClient\HttpClient; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\ResponseHeaderBag; +use Symfony\Component\Mime\Part\AbstractPart; +use Symfony\Component\Mime\Part\DataPart; +use Symfony\Component\Mime\Part\Multipart\FormDataPart; +use Symfony\Component\Mime\Part\TextPart; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +/** + * An implementation of a Symfony HTTP kernel using a "real" HTTP client. + * + * @author Fabien Potencier + */ +final class HttpClientKernel implements HttpKernelInterface +{ + private $client; + + public function __construct(HttpClientInterface $client = null) + { + if (!class_exists(HttpClient::class)) { + throw new \LogicException(sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__)); + } + + $this->client = $client ?? HttpClient::create(); + } + + public function handle(Request $request, int $type = HttpKernelInterface::MASTER_REQUEST, bool $catch = true): Response + { + $headers = $this->getHeaders($request); + $body = ''; + if (null !== $part = $this->getBody($request)) { + $headers = array_merge($headers, $part->getPreparedHeaders()->toArray()); + $body = $part->bodyToIterable(); + } + $response = $this->client->request($request->getMethod(), $request->getUri(), [ + 'headers' => $headers, + 'body' => $body, + 'max_redirects' => 0, + ] + $request->attributes->get('http_client_options', [])); + + $response = new Response($response->getContent(!$catch), $response->getStatusCode(), $response->getHeaders(!$catch)); + + $response->headers = new class($response->headers->all()) extends ResponseHeaderBag { + protected function computeCacheControlValue(): string + { + return $this->getCacheControlHeader(); // preserve the original value + } + }; + + return $response; + } + + private function getBody(Request $request): ?AbstractPart + { + if (\in_array($request->getMethod(), ['GET', 'HEAD'])) { + return null; + } + + if (!class_exists(AbstractPart::class)) { + throw new \LogicException('You cannot pass non-empty bodies as the Mime component is not installed. Try running "composer require symfony/mime".'); + } + + if ($content = $request->getContent()) { + return new TextPart($content, 'utf-8', 'plain', '8bit'); + } + + $fields = $request->request->all(); + foreach ($request->files->all() as $name => $file) { + $fields[$name] = DataPart::fromPath($file->getPathname(), $file->getClientOriginalName(), $file->getClientMimeType()); + } + + return new FormDataPart($fields); + } + + private function getHeaders(Request $request): array + { + $headers = []; + foreach ($request->headers as $key => $value) { + $headers[$key] = $value; + } + $cookies = []; + foreach ($request->cookies->all() as $name => $value) { + $cookies[] = $name.'='.$value; + } + if ($cookies) { + $headers['cookie'] = implode('; ', $cookies); + } + + return $headers; + } +} diff --git a/vendor/symfony/http-kernel/HttpKernel.php b/vendor/symfony/http-kernel/HttpKernel.php new file mode 100644 index 0000000..04b3183 --- /dev/null +++ b/vendor/symfony/http-kernel/HttpKernel.php @@ -0,0 +1,282 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; +use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; +use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; +use Symfony\Component\HttpKernel\Event\ControllerEvent; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; +use Symfony\Component\HttpKernel\Event\FinishRequestEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\Event\TerminateEvent; +use Symfony\Component\HttpKernel\Event\ViewEvent; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; +use Symfony\Component\HttpKernel\Exception\ControllerDoesNotReturnResponseException; +use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; + +/** + * HttpKernel notifies events to convert a Request object to a Response one. + * + * @author Fabien Potencier + */ +class HttpKernel implements HttpKernelInterface, TerminableInterface +{ + protected $dispatcher; + protected $resolver; + protected $requestStack; + private $argumentResolver; + + public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null, ArgumentResolverInterface $argumentResolver = null) + { + $this->dispatcher = $dispatcher; + $this->resolver = $resolver; + $this->requestStack = $requestStack ?: new RequestStack(); + $this->argumentResolver = $argumentResolver; + + if (null === $this->argumentResolver) { + $this->argumentResolver = new ArgumentResolver(); + } + } + + /** + * {@inheritdoc} + */ + public function handle(Request $request, int $type = HttpKernelInterface::MASTER_REQUEST, bool $catch = true) + { + $request->headers->set('X-Php-Ob-Level', (string) ob_get_level()); + + try { + return $this->handleRaw($request, $type); + } catch (\Exception $e) { + if ($e instanceof RequestExceptionInterface) { + $e = new BadRequestHttpException($e->getMessage(), $e); + } + if (false === $catch) { + $this->finishRequest($request, $type); + + throw $e; + } + + return $this->handleThrowable($e, $request, $type); + } + } + + /** + * {@inheritdoc} + */ + public function terminate(Request $request, Response $response) + { + $this->dispatcher->dispatch(new TerminateEvent($this, $request, $response), KernelEvents::TERMINATE); + } + + /** + * @internal + */ + public function terminateWithException(\Throwable $exception, Request $request = null) + { + if (!$request = $request ?: $this->requestStack->getMasterRequest()) { + throw $exception; + } + + $response = $this->handleThrowable($exception, $request, self::MASTER_REQUEST); + + $response->sendHeaders(); + $response->sendContent(); + + $this->terminate($request, $response); + } + + /** + * Handles a request to convert it to a response. + * + * Exceptions are not caught. + * + * @throws \LogicException If one of the listener does not behave as expected + * @throws NotFoundHttpException When controller cannot be found + */ + private function handleRaw(Request $request, int $type = self::MASTER_REQUEST): Response + { + $this->requestStack->push($request); + + // request + $event = new RequestEvent($this, $request, $type); + $this->dispatcher->dispatch($event, KernelEvents::REQUEST); + + if ($event->hasResponse()) { + return $this->filterResponse($event->getResponse(), $request, $type); + } + + // load controller + if (false === $controller = $this->resolver->getController($request)) { + throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". The route is wrongly configured.', $request->getPathInfo())); + } + + $event = new ControllerEvent($this, $controller, $request, $type); + $this->dispatcher->dispatch($event, KernelEvents::CONTROLLER); + $controller = $event->getController(); + + // controller arguments + $arguments = $this->argumentResolver->getArguments($request, $controller); + + $event = new ControllerArgumentsEvent($this, $controller, $arguments, $request, $type); + $this->dispatcher->dispatch($event, KernelEvents::CONTROLLER_ARGUMENTS); + $controller = $event->getController(); + $arguments = $event->getArguments(); + + // call controller + $response = $controller(...$arguments); + + // view + if (!$response instanceof Response) { + $event = new ViewEvent($this, $request, $type, $response); + $this->dispatcher->dispatch($event, KernelEvents::VIEW); + + if ($event->hasResponse()) { + $response = $event->getResponse(); + } else { + $msg = sprintf('The controller must return a "Symfony\Component\HttpFoundation\Response" object but it returned %s.', $this->varToString($response)); + + // the user may have forgotten to return something + if (null === $response) { + $msg .= ' Did you forget to add a return statement somewhere in your controller?'; + } + + throw new ControllerDoesNotReturnResponseException($msg, $controller, __FILE__, __LINE__ - 17); + } + } + + return $this->filterResponse($response, $request, $type); + } + + /** + * Filters a response object. + * + * @throws \RuntimeException if the passed object is not a Response instance + */ + private function filterResponse(Response $response, Request $request, int $type): Response + { + $event = new ResponseEvent($this, $request, $type, $response); + + $this->dispatcher->dispatch($event, KernelEvents::RESPONSE); + + $this->finishRequest($request, $type); + + return $event->getResponse(); + } + + /** + * Publishes the finish request event, then pop the request from the stack. + * + * Note that the order of the operations is important here, otherwise + * operations such as {@link RequestStack::getParentRequest()} can lead to + * weird results. + */ + private function finishRequest(Request $request, int $type) + { + $this->dispatcher->dispatch(new FinishRequestEvent($this, $request, $type), KernelEvents::FINISH_REQUEST); + $this->requestStack->pop(); + } + + /** + * Handles a throwable by trying to convert it to a Response. + * + * @throws \Exception + */ + private function handleThrowable(\Throwable $e, Request $request, int $type): Response + { + $event = new ExceptionEvent($this, $request, $type, $e); + $this->dispatcher->dispatch($event, KernelEvents::EXCEPTION); + + // a listener might have replaced the exception + $e = $event->getThrowable(); + + if (!$event->hasResponse()) { + $this->finishRequest($request, $type); + + throw $e; + } + + $response = $event->getResponse(); + + // the developer asked for a specific status code + if (!$event->isAllowingCustomResponseCode() && !$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) { + // ensure that we actually have an error response + if ($e instanceof HttpExceptionInterface) { + // keep the HTTP status code and headers + $response->setStatusCode($e->getStatusCode()); + $response->headers->add($e->getHeaders()); + } else { + $response->setStatusCode(500); + } + } + + try { + return $this->filterResponse($response, $request, $type); + } catch (\Exception $e) { + return $response; + } + } + + /** + * Returns a human-readable string for the specified variable. + */ + private function varToString($var): string + { + if (\is_object($var)) { + return sprintf('an object of type %s', \get_class($var)); + } + + if (\is_array($var)) { + $a = []; + foreach ($var as $k => $v) { + $a[] = sprintf('%s => ...', $k); + } + + return sprintf('an array ([%s])', mb_substr(implode(', ', $a), 0, 255)); + } + + if (\is_resource($var)) { + return sprintf('a resource (%s)', get_resource_type($var)); + } + + if (null === $var) { + return 'null'; + } + + if (false === $var) { + return 'a boolean value (false)'; + } + + if (true === $var) { + return 'a boolean value (true)'; + } + + if (\is_string($var)) { + return sprintf('a string ("%s%s")', mb_substr($var, 0, 255), mb_strlen($var) > 255 ? '...' : ''); + } + + if (is_numeric($var)) { + return sprintf('a number (%s)', (string) $var); + } + + return (string) $var; + } +} diff --git a/vendor/symfony/http-kernel/HttpKernelBrowser.php b/vendor/symfony/http-kernel/HttpKernelBrowser.php new file mode 100644 index 0000000..d28be99 --- /dev/null +++ b/vendor/symfony/http-kernel/HttpKernelBrowser.php @@ -0,0 +1,199 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +use Symfony\Component\BrowserKit\AbstractBrowser; +use Symfony\Component\BrowserKit\CookieJar; +use Symfony\Component\BrowserKit\History; +use Symfony\Component\BrowserKit\Request as DomRequest; +use Symfony\Component\BrowserKit\Response as DomResponse; +use Symfony\Component\HttpFoundation\File\UploadedFile; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * Simulates a browser and makes requests to an HttpKernel instance. + * + * @author Fabien Potencier + * + * @method Request getRequest() A Request instance + * @method Response getResponse() A Response instance + */ +class HttpKernelBrowser extends AbstractBrowser +{ + protected $kernel; + private $catchExceptions = true; + + /** + * @param array $server The server parameters (equivalent of $_SERVER) + */ + public function __construct(HttpKernelInterface $kernel, array $server = [], History $history = null, CookieJar $cookieJar = null) + { + // These class properties must be set before calling the parent constructor, as it may depend on it. + $this->kernel = $kernel; + $this->followRedirects = false; + + parent::__construct($server, $history, $cookieJar); + } + + /** + * Sets whether to catch exceptions when the kernel is handling a request. + */ + public function catchExceptions(bool $catchExceptions) + { + $this->catchExceptions = $catchExceptions; + } + + /** + * Makes a request. + * + * @return Response A Response instance + */ + protected function doRequest($request) + { + $response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $this->catchExceptions); + + if ($this->kernel instanceof TerminableInterface) { + $this->kernel->terminate($request, $response); + } + + return $response; + } + + /** + * Returns the script to execute when the request must be insulated. + * + * @return string + */ + protected function getScript($request) + { + $kernel = var_export(serialize($this->kernel), true); + $request = var_export(serialize($request), true); + + $errorReporting = error_reporting(); + + $requires = ''; + foreach (get_declared_classes() as $class) { + if (0 === strpos($class, 'ComposerAutoloaderInit')) { + $r = new \ReflectionClass($class); + $file = \dirname($r->getFileName(), 2).'/autoload.php'; + if (file_exists($file)) { + $requires .= 'require_once '.var_export($file, true).";\n"; + } + } + } + + if (!$requires) { + throw new \RuntimeException('Composer autoloader not found.'); + } + + $code = <<getHandleScript(); + } + + protected function getHandleScript() + { + return <<<'EOF' +$response = $kernel->handle($request); + +if ($kernel instanceof Symfony\Component\HttpKernel\TerminableInterface) { + $kernel->terminate($request, $response); +} + +echo serialize($response); +EOF; + } + + /** + * Converts the BrowserKit request to a HttpKernel request. + * + * @return Request A Request instance + */ + protected function filterRequest(DomRequest $request) + { + $httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $request->getServer(), $request->getContent()); + + foreach ($this->filterFiles($httpRequest->files->all()) as $key => $value) { + $httpRequest->files->set($key, $value); + } + + return $httpRequest; + } + + /** + * Filters an array of files. + * + * This method created test instances of UploadedFile so that the move() + * method can be called on those instances. + * + * If the size of a file is greater than the allowed size (from php.ini) then + * an invalid UploadedFile is returned with an error set to UPLOAD_ERR_INI_SIZE. + * + * @see UploadedFile + * + * @return array An array with all uploaded files marked as already moved + */ + protected function filterFiles(array $files) + { + $filtered = []; + foreach ($files as $key => $value) { + if (\is_array($value)) { + $filtered[$key] = $this->filterFiles($value); + } elseif ($value instanceof UploadedFile) { + if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) { + $filtered[$key] = new UploadedFile( + '', + $value->getClientOriginalName(), + $value->getClientMimeType(), + UPLOAD_ERR_INI_SIZE, + true + ); + } else { + $filtered[$key] = new UploadedFile( + $value->getPathname(), + $value->getClientOriginalName(), + $value->getClientMimeType(), + $value->getError(), + true + ); + } + } + } + + return $filtered; + } + + /** + * Converts the HttpKernel response to a BrowserKit response. + * + * @return DomResponse A DomResponse instance + */ + protected function filterResponse($response) + { + // this is needed to support StreamedResponse + ob_start(); + $response->sendContent(); + $content = ob_get_clean(); + + return new DomResponse($content, $response->getStatusCode(), $response->headers->all()); + } +} diff --git a/vendor/symfony/http-kernel/HttpKernelInterface.php b/vendor/symfony/http-kernel/HttpKernelInterface.php new file mode 100644 index 0000000..a75d1a8 --- /dev/null +++ b/vendor/symfony/http-kernel/HttpKernelInterface.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * HttpKernelInterface handles a Request to convert it to a Response. + * + * @author Fabien Potencier + */ +interface HttpKernelInterface +{ + const MASTER_REQUEST = 1; + const SUB_REQUEST = 2; + + /** + * Handles a Request to convert it to a Response. + * + * When $catch is true, the implementation must catch all exceptions + * and do its best to convert them to a Response instance. + * + * @param int $type The type of the request + * (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) + * @param bool $catch Whether to catch exceptions or not + * + * @return Response A Response instance + * + * @throws \Exception When an Exception occurs during processing + */ + public function handle(Request $request, int $type = self::MASTER_REQUEST, bool $catch = true); +} diff --git a/vendor/symfony/http-kernel/Kernel.php b/vendor/symfony/http-kernel/Kernel.php new file mode 100644 index 0000000..2394fac --- /dev/null +++ b/vendor/symfony/http-kernel/Kernel.php @@ -0,0 +1,825 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; +use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; +use Symfony\Component\Config\ConfigCache; +use Symfony\Component\Config\Loader\DelegatingLoader; +use Symfony\Component\Config\Loader\LoaderResolver; +use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\PassConfig; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Dumper\PhpDumper; +use Symfony\Component\DependencyInjection\Loader\ClosureLoader; +use Symfony\Component\DependencyInjection\Loader\DirectoryLoader; +use Symfony\Component\DependencyInjection\Loader\GlobFileLoader; +use Symfony\Component\DependencyInjection\Loader\IniFileLoader; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\ErrorHandler\DebugClassLoader; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Bundle\BundleInterface; +use Symfony\Component\HttpKernel\Config\FileLocator; +use Symfony\Component\HttpKernel\DependencyInjection\AddAnnotatedClassesToCachePass; +use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; + +/** + * The Kernel is the heart of the Symfony system. + * + * It manages an environment made of bundles. + * + * Environment names must always start with a letter and + * they must only contain letters and numbers. + * + * @author Fabien Potencier + */ +abstract class Kernel implements KernelInterface, RebootableInterface, TerminableInterface +{ + /** + * @var BundleInterface[] + */ + protected $bundles = []; + + protected $container; + protected $environment; + protected $debug; + protected $booted = false; + protected $startTime; + + private $projectDir; + private $warmupDir; + private $requestStackSize = 0; + private $resetServices = false; + + private static $freshCache = []; + + const VERSION = '5.0.2'; + const VERSION_ID = 50002; + const MAJOR_VERSION = 5; + const MINOR_VERSION = 0; + const RELEASE_VERSION = 2; + const EXTRA_VERSION = ''; + + const END_OF_MAINTENANCE = '07/2020'; + const END_OF_LIFE = '07/2020'; + + public function __construct(string $environment, bool $debug) + { + $this->environment = $environment; + $this->debug = $debug; + } + + public function __clone() + { + $this->booted = false; + $this->container = null; + $this->requestStackSize = 0; + $this->resetServices = false; + } + + /** + * {@inheritdoc} + */ + public function boot() + { + if (true === $this->booted) { + if (!$this->requestStackSize && $this->resetServices) { + if ($this->container->has('services_resetter')) { + $this->container->get('services_resetter')->reset(); + } + $this->resetServices = false; + if ($this->debug) { + $this->startTime = microtime(true); + } + } + + return; + } + if ($this->debug) { + $this->startTime = microtime(true); + } + if ($this->debug && !isset($_ENV['SHELL_VERBOSITY']) && !isset($_SERVER['SHELL_VERBOSITY'])) { + putenv('SHELL_VERBOSITY=3'); + $_ENV['SHELL_VERBOSITY'] = 3; + $_SERVER['SHELL_VERBOSITY'] = 3; + } + + // init bundles + $this->initializeBundles(); + + // init container + $this->initializeContainer(); + + foreach ($this->getBundles() as $bundle) { + $bundle->setContainer($this->container); + $bundle->boot(); + } + + $this->booted = true; + } + + /** + * {@inheritdoc} + */ + public function reboot(?string $warmupDir) + { + $this->shutdown(); + $this->warmupDir = $warmupDir; + $this->boot(); + } + + /** + * {@inheritdoc} + */ + public function terminate(Request $request, Response $response) + { + if (false === $this->booted) { + return; + } + + if ($this->getHttpKernel() instanceof TerminableInterface) { + $this->getHttpKernel()->terminate($request, $response); + } + } + + /** + * {@inheritdoc} + */ + public function shutdown() + { + if (false === $this->booted) { + return; + } + + $this->booted = false; + + foreach ($this->getBundles() as $bundle) { + $bundle->shutdown(); + $bundle->setContainer(null); + } + + $this->container = null; + $this->requestStackSize = 0; + $this->resetServices = false; + } + + /** + * {@inheritdoc} + */ + public function handle(Request $request, int $type = HttpKernelInterface::MASTER_REQUEST, bool $catch = true) + { + $this->boot(); + ++$this->requestStackSize; + $this->resetServices = true; + + try { + return $this->getHttpKernel()->handle($request, $type, $catch); + } finally { + --$this->requestStackSize; + } + } + + /** + * Gets a HTTP kernel from the container. + * + * @return HttpKernelInterface + */ + protected function getHttpKernel() + { + return $this->container->get('http_kernel'); + } + + /** + * {@inheritdoc} + */ + public function getBundles() + { + return $this->bundles; + } + + /** + * {@inheritdoc} + */ + public function getBundle(string $name) + { + if (!isset($this->bundles[$name])) { + $class = \get_class($this); + $class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; + + throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, $class)); + } + + return $this->bundles[$name]; + } + + /** + * {@inheritdoc} + */ + public function locateResource(string $name) + { + if ('@' !== $name[0]) { + throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name)); + } + + if (false !== strpos($name, '..')) { + throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name)); + } + + $bundleName = substr($name, 1); + $path = ''; + if (false !== strpos($bundleName, '/')) { + list($bundleName, $path) = explode('/', $bundleName, 2); + } + + $bundle = $this->getBundle($bundleName); + if (file_exists($file = $bundle->getPath().'/'.$path)) { + return $file; + } + + throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name)); + } + + /** + * {@inheritdoc} + */ + public function getEnvironment() + { + return $this->environment; + } + + /** + * {@inheritdoc} + */ + public function isDebug() + { + return $this->debug; + } + + /** + * Gets the application root dir (path of the project's composer file). + * + * @return string The project root dir + */ + public function getProjectDir() + { + if (null === $this->projectDir) { + $r = new \ReflectionObject($this); + + if (!file_exists($dir = $r->getFileName())) { + throw new \LogicException(sprintf('Cannot auto-detect project dir for kernel of class "%s".', $r->name)); + } + + $dir = $rootDir = \dirname($dir); + while (!file_exists($dir.'/composer.json')) { + if ($dir === \dirname($dir)) { + return $this->projectDir = $rootDir; + } + $dir = \dirname($dir); + } + $this->projectDir = $dir; + } + + return $this->projectDir; + } + + /** + * {@inheritdoc} + */ + public function getContainer() + { + if (!$this->container) { + throw new \LogicException('Cannot retrieve the container from a non-booted kernel.'); + } + + return $this->container; + } + + /** + * @internal + */ + public function setAnnotatedClassCache(array $annotatedClasses) + { + file_put_contents(($this->warmupDir ?: $this->getCacheDir()).'/annotations.map', sprintf('debug && null !== $this->startTime ? $this->startTime : -INF; + } + + /** + * {@inheritdoc} + */ + public function getCacheDir() + { + return $this->getProjectDir().'/var/cache/'.$this->environment; + } + + /** + * {@inheritdoc} + */ + public function getLogDir() + { + return $this->getProjectDir().'/var/log'; + } + + /** + * {@inheritdoc} + */ + public function getCharset() + { + return 'UTF-8'; + } + + /** + * Gets the patterns defining the classes to parse and cache for annotations. + */ + public function getAnnotatedClassesToCompile(): array + { + return []; + } + + /** + * Initializes bundles. + * + * @throws \LogicException if two bundles share a common name + */ + protected function initializeBundles() + { + // init bundles + $this->bundles = []; + foreach ($this->registerBundles() as $bundle) { + $name = $bundle->getName(); + if (isset($this->bundles[$name])) { + throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name)); + } + $this->bundles[$name] = $bundle; + } + } + + /** + * The extension point similar to the Bundle::build() method. + * + * Use this method to register compiler passes and manipulate the container during the building process. + */ + protected function build(ContainerBuilder $container) + { + } + + /** + * Gets the container class. + * + * @throws \InvalidArgumentException If the generated classname is invalid + * + * @return string The container class + */ + protected function getContainerClass() + { + $class = \get_class($this); + $class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).str_replace('.', '_', ContainerBuilder::hash($class)) : $class; + $class = str_replace('\\', '_', $class).ucfirst($this->environment).($this->debug ? 'Debug' : '').'Container'; + if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $class)) { + throw new \InvalidArgumentException(sprintf('The environment "%s" contains invalid characters, it can only contain characters allowed in PHP class names.', $this->environment)); + } + + return $class; + } + + /** + * Gets the container's base class. + * + * All names except Container must be fully qualified. + * + * @return string + */ + protected function getContainerBaseClass() + { + return 'Container'; + } + + /** + * Initializes the service container. + * + * The cached version of the service container is used when fresh, otherwise the + * container is built. + */ + protected function initializeContainer() + { + $class = $this->getContainerClass(); + $cacheDir = $this->warmupDir ?: $this->getCacheDir(); + $cache = new ConfigCache($cacheDir.'/'.$class.'.php', $this->debug); + $cachePath = $cache->getPath(); + + // Silence E_WARNING to ignore "include" failures - don't use "@" to prevent silencing fatal errors + $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); + + try { + if (file_exists($cachePath) && \is_object($this->container = include $cachePath) + && (!$this->debug || (self::$freshCache[$cachePath] ?? $cache->isFresh())) + ) { + self::$freshCache[$cachePath] = true; + $this->container->set('kernel', $this); + error_reporting($errorLevel); + + return; + } + } catch (\Throwable $e) { + } + + $oldContainer = \is_object($this->container) ? new \ReflectionClass($this->container) : $this->container = null; + + try { + is_dir($cacheDir) ?: mkdir($cacheDir, 0777, true); + + if ($lock = fopen($cachePath, 'w')) { + chmod($cachePath, 0666 & ~umask()); + flock($lock, LOCK_EX | LOCK_NB, $wouldBlock); + + if (!flock($lock, $wouldBlock ? LOCK_SH : LOCK_EX)) { + fclose($lock); + } else { + $cache = new class($cachePath, $this->debug) extends ConfigCache { + public $lock; + + public function write(string $content, array $metadata = null) + { + rewind($this->lock); + ftruncate($this->lock, 0); + fwrite($this->lock, $content); + + if (null !== $metadata) { + file_put_contents($this->getPath().'.meta', serialize($metadata)); + @chmod($this->getPath().'.meta', 0666 & ~umask()); + } + + if (\function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN)) { + @opcache_invalidate($this->getPath(), true); + } + } + + public function __destruct() + { + flock($this->lock, LOCK_UN); + fclose($this->lock); + } + }; + $cache->lock = $lock; + + if (!\is_object($this->container = include $cachePath)) { + $this->container = null; + } elseif (!$oldContainer || \get_class($this->container) !== $oldContainer->name) { + $this->container->set('kernel', $this); + + return; + } + } + } + } catch (\Throwable $e) { + } finally { + error_reporting($errorLevel); + } + + if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) { + $collectedLogs = []; + $previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) { + if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) { + return $previousHandler ? $previousHandler($type, $message, $file, $line) : false; + } + + if (isset($collectedLogs[$message])) { + ++$collectedLogs[$message]['count']; + + return null; + } + + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5); + // Clean the trace by removing first frames added by the error handler itself. + for ($i = 0; isset($backtrace[$i]); ++$i) { + if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { + $backtrace = \array_slice($backtrace, 1 + $i); + break; + } + } + // Remove frames added by DebugClassLoader. + for ($i = \count($backtrace) - 2; 0 < $i; --$i) { + if (\in_array($backtrace[$i]['class'] ?? null, [DebugClassLoader::class, LegacyDebugClassLoader::class], true)) { + $backtrace = [$backtrace[$i + 1]]; + break; + } + } + + $collectedLogs[$message] = [ + 'type' => $type, + 'message' => $message, + 'file' => $file, + 'line' => $line, + 'trace' => [$backtrace[0]], + 'count' => 1, + ]; + + return null; + }); + } + + try { + $container = null; + $container = $this->buildContainer(); + $container->compile(); + } finally { + if ($collectDeprecations) { + restore_error_handler(); + + file_put_contents($cacheDir.'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs))); + file_put_contents($cacheDir.'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : ''); + } + } + + $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); + unset($cache); + $this->container = require $cachePath; + $this->container->set('kernel', $this); + + if ($oldContainer && \get_class($this->container) !== $oldContainer->name) { + // Because concurrent requests might still be using them, + // old container files are not removed immediately, + // but on a next dump of the container. + static $legacyContainers = []; + $oldContainerDir = \dirname($oldContainer->getFileName()); + $legacyContainers[$oldContainerDir.'.legacy'] = true; + foreach (glob(\dirname($oldContainerDir).\DIRECTORY_SEPARATOR.'*.legacy', GLOB_NOSORT) as $legacyContainer) { + if (!isset($legacyContainers[$legacyContainer]) && @unlink($legacyContainer)) { + (new Filesystem())->remove(substr($legacyContainer, 0, -7)); + } + } + + touch($oldContainerDir.'.legacy'); + } + + if ($this->container->has('cache_warmer')) { + $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir')); + } + } + + /** + * Returns the kernel parameters. + * + * @return array An array of kernel parameters + */ + protected function getKernelParameters() + { + $bundles = []; + $bundlesMetadata = []; + + foreach ($this->bundles as $name => $bundle) { + $bundles[$name] = \get_class($bundle); + $bundlesMetadata[$name] = [ + 'path' => $bundle->getPath(), + 'namespace' => $bundle->getNamespace(), + ]; + } + + return [ + 'kernel.project_dir' => realpath($this->getProjectDir()) ?: $this->getProjectDir(), + 'kernel.environment' => $this->environment, + 'kernel.debug' => $this->debug, + 'kernel.cache_dir' => realpath($cacheDir = $this->warmupDir ?: $this->getCacheDir()) ?: $cacheDir, + 'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(), + 'kernel.bundles' => $bundles, + 'kernel.bundles_metadata' => $bundlesMetadata, + 'kernel.charset' => $this->getCharset(), + 'kernel.container_class' => $this->getContainerClass(), + ]; + } + + /** + * Builds the service container. + * + * @return ContainerBuilder The compiled service container + * + * @throws \RuntimeException + */ + protected function buildContainer() + { + foreach (['cache' => $this->warmupDir ?: $this->getCacheDir(), 'logs' => $this->getLogDir()] as $name => $dir) { + if (!is_dir($dir)) { + if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) { + throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir)); + } + } elseif (!is_writable($dir)) { + throw new \RuntimeException(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir)); + } + } + + $container = $this->getContainerBuilder(); + $container->addObjectResource($this); + $this->prepareContainer($container); + + if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) { + $container->merge($cont); + } + + $container->addCompilerPass(new AddAnnotatedClassesToCachePass($this)); + + return $container; + } + + /** + * Prepares the ContainerBuilder before it is compiled. + */ + protected function prepareContainer(ContainerBuilder $container) + { + $extensions = []; + foreach ($this->bundles as $bundle) { + if ($extension = $bundle->getContainerExtension()) { + $container->registerExtension($extension); + } + + if ($this->debug) { + $container->addObjectResource($bundle); + } + } + + foreach ($this->bundles as $bundle) { + $bundle->build($container); + } + + $this->build($container); + + foreach ($container->getExtensions() as $extension) { + $extensions[] = $extension->getAlias(); + } + + // ensure these extensions are implicitly loaded + $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions)); + } + + /** + * Gets a new ContainerBuilder instance used to build the service container. + * + * @return ContainerBuilder + */ + protected function getContainerBuilder() + { + $container = new ContainerBuilder(); + $container->getParameterBag()->add($this->getKernelParameters()); + + if ($this instanceof CompilerPassInterface) { + $container->addCompilerPass($this, PassConfig::TYPE_BEFORE_OPTIMIZATION, -10000); + } + if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator')) { + $container->setProxyInstantiator(new RuntimeInstantiator()); + } + + return $container; + } + + /** + * Dumps the service container to PHP code in the cache. + * + * @param string $class The name of the class to generate + * @param string $baseClass The name of the container's base class + */ + protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, string $class, string $baseClass) + { + // cache the container + $dumper = new PhpDumper($container); + + if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper')) { + $dumper->setProxyDumper(new ProxyDumper()); + } + + $content = $dumper->dump([ + 'class' => $class, + 'base_class' => $baseClass, + 'file' => $cache->getPath(), + 'as_files' => true, + 'debug' => $this->debug, + 'build_time' => $container->hasParameter('kernel.container_build_time') ? $container->getParameter('kernel.container_build_time') : time(), + ]); + + $rootCode = array_pop($content); + $dir = \dirname($cache->getPath()).'/'; + $fs = new Filesystem(); + + foreach ($content as $file => $code) { + $fs->dumpFile($dir.$file, $code); + @chmod($dir.$file, 0666 & ~umask()); + } + $legacyFile = \dirname($dir.key($content)).'.legacy'; + if (file_exists($legacyFile)) { + @unlink($legacyFile); + } + + $cache->write($rootCode, $container->getResources()); + } + + /** + * Returns a loader for the container. + * + * @return DelegatingLoader The loader + */ + protected function getContainerLoader(ContainerInterface $container) + { + $locator = new FileLocator($this); + $resolver = new LoaderResolver([ + new XmlFileLoader($container, $locator), + new YamlFileLoader($container, $locator), + new IniFileLoader($container, $locator), + new PhpFileLoader($container, $locator), + new GlobFileLoader($container, $locator), + new DirectoryLoader($container, $locator), + new ClosureLoader($container), + ]); + + return new DelegatingLoader($resolver); + } + + /** + * Removes comments from a PHP source string. + * + * We don't use the PHP php_strip_whitespace() function + * as we want the content to be readable and well-formatted. + * + * @return string The PHP string with the comments removed + */ + public static function stripComments(string $source) + { + if (!\function_exists('token_get_all')) { + return $source; + } + + $rawChunk = ''; + $output = ''; + $tokens = token_get_all($source); + $ignoreSpace = false; + for ($i = 0; isset($tokens[$i]); ++$i) { + $token = $tokens[$i]; + if (!isset($token[1]) || 'b"' === $token) { + $rawChunk .= $token; + } elseif (T_START_HEREDOC === $token[0]) { + $output .= $rawChunk.$token[1]; + do { + $token = $tokens[++$i]; + $output .= isset($token[1]) && 'b"' !== $token ? $token[1] : $token; + } while (T_END_HEREDOC !== $token[0]); + $rawChunk = ''; + } elseif (T_WHITESPACE === $token[0]) { + if ($ignoreSpace) { + $ignoreSpace = false; + + continue; + } + + // replace multiple new lines with a single newline + $rawChunk .= preg_replace(['/\n{2,}/S'], "\n", $token[1]); + } elseif (\in_array($token[0], [T_COMMENT, T_DOC_COMMENT])) { + $ignoreSpace = true; + } else { + $rawChunk .= $token[1]; + + // The PHP-open tag already has a new-line + if (T_OPEN_TAG === $token[0]) { + $ignoreSpace = true; + } + } + } + + $output .= $rawChunk; + + unset($tokens, $rawChunk); + gc_mem_caches(); + + return $output; + } + + /** + * @return array + */ + public function __sleep() + { + return ['environment', 'debug']; + } + + public function __wakeup() + { + $this->__construct($this->environment, $this->debug); + } +} diff --git a/vendor/symfony/http-kernel/KernelEvents.php b/vendor/symfony/http-kernel/KernelEvents.php new file mode 100644 index 0000000..682561c --- /dev/null +++ b/vendor/symfony/http-kernel/KernelEvents.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +/** + * Contains all events thrown in the HttpKernel component. + * + * @author Bernhard Schussek + */ +final class KernelEvents +{ + /** + * The REQUEST event occurs at the very beginning of request + * dispatching. + * + * This event allows you to create a response for a request before any + * other code in the framework is executed. + * + * @Event("Symfony\Component\HttpKernel\Event\RequestEvent") + */ + const REQUEST = 'kernel.request'; + + /** + * The EXCEPTION event occurs when an uncaught exception appears. + * + * This event allows you to create a response for a thrown exception or + * to modify the thrown exception. + * + * @Event("Symfony\Component\HttpKernel\Event\ExceptionEvent") + */ + const EXCEPTION = 'kernel.exception'; + + /** + * The VIEW event occurs when the return value of a controller + * is not a Response instance. + * + * This event allows you to create a response for the return value of the + * controller. + * + * @Event("Symfony\Component\HttpKernel\Event\ViewEvent") + */ + const VIEW = 'kernel.view'; + + /** + * The CONTROLLER event occurs once a controller was found for + * handling a request. + * + * This event allows you to change the controller that will handle the + * request. + * + * @Event("Symfony\Component\HttpKernel\Event\ControllerEvent") + */ + const CONTROLLER = 'kernel.controller'; + + /** + * The CONTROLLER_ARGUMENTS event occurs once controller arguments have been resolved. + * + * This event allows you to change the arguments that will be passed to + * the controller. + * + * @Event("Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent") + */ + const CONTROLLER_ARGUMENTS = 'kernel.controller_arguments'; + + /** + * The RESPONSE event occurs once a response was created for + * replying to a request. + * + * This event allows you to modify or replace the response that will be + * replied. + * + * @Event("Symfony\Component\HttpKernel\Event\ResponseEvent") + */ + const RESPONSE = 'kernel.response'; + + /** + * The TERMINATE event occurs once a response was sent. + * + * This event allows you to run expensive post-response jobs. + * + * @Event("Symfony\Component\HttpKernel\Event\TerminateEvent") + */ + const TERMINATE = 'kernel.terminate'; + + /** + * The FINISH_REQUEST event occurs when a response was generated for a request. + * + * This event allows you to reset the global and environmental state of + * the application, when it was changed during the request. + * + * @Event("Symfony\Component\HttpKernel\Event\FinishRequestEvent") + */ + const FINISH_REQUEST = 'kernel.finish_request'; +} diff --git a/vendor/symfony/http-kernel/KernelInterface.php b/vendor/symfony/http-kernel/KernelInterface.php new file mode 100644 index 0000000..cea86f6 --- /dev/null +++ b/vendor/symfony/http-kernel/KernelInterface.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpKernel\Bundle\BundleInterface; + +/** + * The Kernel is the heart of the Symfony system. + * + * It manages an environment made of application kernel and bundles. + * + * @author Fabien Potencier + */ +interface KernelInterface extends HttpKernelInterface +{ + /** + * Returns an array of bundles to register. + * + * @return iterable|BundleInterface[] An iterable of bundle instances + */ + public function registerBundles(); + + /** + * Loads the container configuration. + */ + public function registerContainerConfiguration(LoaderInterface $loader); + + /** + * Boots the current kernel. + */ + public function boot(); + + /** + * Shutdowns the kernel. + * + * This method is mainly useful when doing functional testing. + */ + public function shutdown(); + + /** + * Gets the registered bundle instances. + * + * @return BundleInterface[] An array of registered bundle instances + */ + public function getBundles(); + + /** + * Returns a bundle. + * + * @return BundleInterface A BundleInterface instance + * + * @throws \InvalidArgumentException when the bundle is not enabled + */ + public function getBundle(string $name); + + /** + * Returns the file path for a given bundle resource. + * + * A Resource can be a file or a directory. + * + * The resource name must follow the following pattern: + * + * "@BundleName/path/to/a/file.something" + * + * where BundleName is the name of the bundle + * and the remaining part is the relative path in the bundle. + * + * @return string The absolute path of the resource + * + * @throws \InvalidArgumentException if the file cannot be found or the name is not valid + * @throws \RuntimeException if the name contains invalid/unsafe characters + */ + public function locateResource(string $name); + + /** + * Gets the environment. + * + * @return string The current environment + */ + public function getEnvironment(); + + /** + * Checks if debug mode is enabled. + * + * @return bool true if debug mode is enabled, false otherwise + */ + public function isDebug(); + + /** + * Gets the project dir (path of the project's composer file). + * + * @return string + */ + public function getProjectDir(); + + /** + * Gets the current container. + * + * @return ContainerInterface + */ + public function getContainer(); + + /** + * Gets the request start time (not available if debug is disabled). + * + * @return float The request start timestamp + */ + public function getStartTime(); + + /** + * Gets the cache directory. + * + * @return string The cache directory + */ + public function getCacheDir(); + + /** + * Gets the log directory. + * + * @return string The log directory + */ + public function getLogDir(); + + /** + * Gets the charset of the application. + * + * @return string The charset + */ + public function getCharset(); +} diff --git a/vendor/symfony/http-kernel/LICENSE b/vendor/symfony/http-kernel/LICENSE new file mode 100644 index 0000000..a677f43 --- /dev/null +++ b/vendor/symfony/http-kernel/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/http-kernel/Log/DebugLoggerInterface.php b/vendor/symfony/http-kernel/Log/DebugLoggerInterface.php new file mode 100644 index 0000000..2c2eae6 --- /dev/null +++ b/vendor/symfony/http-kernel/Log/DebugLoggerInterface.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Log; + +use Symfony\Component\HttpFoundation\Request; + +/** + * DebugLoggerInterface. + * + * @author Fabien Potencier + */ +interface DebugLoggerInterface +{ + /** + * Returns an array of logs. + * + * A log is an array with the following mandatory keys: + * timestamp, message, priority, and priorityName. + * It can also have an optional context key containing an array. + * + * @return array An array of logs + */ + public function getLogs(Request $request = null); + + /** + * Returns the number of errors. + * + * @return int The number of errors + */ + public function countErrors(Request $request = null); + + /** + * Removes all log records. + */ + public function clear(); +} diff --git a/vendor/symfony/http-kernel/Log/Logger.php b/vendor/symfony/http-kernel/Log/Logger.php new file mode 100644 index 0000000..c27bb3f --- /dev/null +++ b/vendor/symfony/http-kernel/Log/Logger.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Log; + +use Psr\Log\AbstractLogger; +use Psr\Log\InvalidArgumentException; +use Psr\Log\LogLevel; + +/** + * Minimalist PSR-3 logger designed to write in stderr or any other stream. + * + * @author Kévin Dunglas + */ +class Logger extends AbstractLogger +{ + private static $levels = [ + LogLevel::DEBUG => 0, + LogLevel::INFO => 1, + LogLevel::NOTICE => 2, + LogLevel::WARNING => 3, + LogLevel::ERROR => 4, + LogLevel::CRITICAL => 5, + LogLevel::ALERT => 6, + LogLevel::EMERGENCY => 7, + ]; + + private $minLevelIndex; + private $formatter; + private $handle; + + public function __construct(string $minLevel = null, $output = 'php://stderr', callable $formatter = null) + { + if (null === $minLevel) { + $minLevel = 'php://stdout' === $output || 'php://stderr' === $output ? LogLevel::CRITICAL : LogLevel::WARNING; + + if (isset($_ENV['SHELL_VERBOSITY']) || isset($_SERVER['SHELL_VERBOSITY'])) { + switch ((int) (isset($_ENV['SHELL_VERBOSITY']) ? $_ENV['SHELL_VERBOSITY'] : $_SERVER['SHELL_VERBOSITY'])) { + case -1: $minLevel = LogLevel::ERROR; break; + case 1: $minLevel = LogLevel::NOTICE; break; + case 2: $minLevel = LogLevel::INFO; break; + case 3: $minLevel = LogLevel::DEBUG; break; + } + } + } + + if (!isset(self::$levels[$minLevel])) { + throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $minLevel)); + } + + $this->minLevelIndex = self::$levels[$minLevel]; + $this->formatter = $formatter ?: [$this, 'format']; + if (false === $this->handle = \is_resource($output) ? $output : @fopen($output, 'a')) { + throw new InvalidArgumentException(sprintf('Unable to open "%s".', $output)); + } + } + + /** + * {@inheritdoc} + * + * @return void + */ + public function log($level, $message, array $context = []) + { + if (!isset(self::$levels[$level])) { + throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); + } + + if (self::$levels[$level] < $this->minLevelIndex) { + return; + } + + $formatter = $this->formatter; + fwrite($this->handle, $formatter($level, $message, $context)); + } + + private function format(string $level, string $message, array $context): string + { + if (false !== strpos($message, '{')) { + $replacements = []; + foreach ($context as $key => $val) { + if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { + $replacements["{{$key}}"] = $val; + } elseif ($val instanceof \DateTimeInterface) { + $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); + } elseif (\is_object($val)) { + $replacements["{{$key}}"] = '[object '.\get_class($val).']'; + } else { + $replacements["{{$key}}"] = '['.\gettype($val).']'; + } + } + + $message = strtr($message, $replacements); + } + + return sprintf('%s [%s] %s', date(\DateTime::RFC3339), $level, $message).\PHP_EOL; + } +} diff --git a/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php b/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php new file mode 100644 index 0000000..3b5dfbf --- /dev/null +++ b/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php @@ -0,0 +1,303 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Profiler; + +/** + * Storage for profiler using files. + * + * @author Alexandre Salomé + */ +class FileProfilerStorage implements ProfilerStorageInterface +{ + /** + * Folder where profiler data are stored. + * + * @var string + */ + private $folder; + + /** + * Constructs the file storage using a "dsn-like" path. + * + * Example : "file:/path/to/the/storage/folder" + * + * @throws \RuntimeException + */ + public function __construct(string $dsn) + { + if (0 !== strpos($dsn, 'file:')) { + throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use FileStorage with an invalid dsn "%s". The expected format is "file:/path/to/the/storage/folder".', $dsn)); + } + $this->folder = substr($dsn, 5); + + if (!is_dir($this->folder) && false === @mkdir($this->folder, 0777, true) && !is_dir($this->folder)) { + throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $this->folder)); + } + } + + /** + * {@inheritdoc} + */ + public function find(?string $ip, ?string $url, ?int $limit, ?string $method, int $start = null, int $end = null, string $statusCode = null): array + { + $file = $this->getIndexFilename(); + + if (!file_exists($file)) { + return []; + } + + $file = fopen($file, 'r'); + fseek($file, 0, SEEK_END); + + $result = []; + while (\count($result) < $limit && $line = $this->readLineFromFile($file)) { + $values = str_getcsv($line); + list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode) = $values; + $csvTime = (int) $csvTime; + + if ($ip && false === strpos($csvIp, $ip) || $url && false === strpos($csvUrl, $url) || $method && false === strpos($csvMethod, $method) || $statusCode && false === strpos($csvStatusCode, $statusCode)) { + continue; + } + + if (!empty($start) && $csvTime < $start) { + continue; + } + + if (!empty($end) && $csvTime > $end) { + continue; + } + + $result[$csvToken] = [ + 'token' => $csvToken, + 'ip' => $csvIp, + 'method' => $csvMethod, + 'url' => $csvUrl, + 'time' => $csvTime, + 'parent' => $csvParent, + 'status_code' => $csvStatusCode, + ]; + } + + fclose($file); + + return array_values($result); + } + + /** + * {@inheritdoc} + */ + public function purge() + { + $flags = \FilesystemIterator::SKIP_DOTS; + $iterator = new \RecursiveDirectoryIterator($this->folder, $flags); + $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST); + + foreach ($iterator as $file) { + if (is_file($file)) { + unlink($file); + } else { + rmdir($file); + } + } + } + + /** + * {@inheritdoc} + */ + public function read(string $token): ?Profile + { + if (!$token || !file_exists($file = $this->getFilename($token))) { + return null; + } + + if (\function_exists('gzcompress')) { + $file = 'compress.zlib://'.$file; + } + + return $this->createProfileFromData($token, unserialize(file_get_contents($file))); + } + + /** + * {@inheritdoc} + * + * @throws \RuntimeException + */ + public function write(Profile $profile): bool + { + $file = $this->getFilename($profile->getToken()); + + $profileIndexed = is_file($file); + if (!$profileIndexed) { + // Create directory + $dir = \dirname($file); + if (!is_dir($dir) && false === @mkdir($dir, 0777, true) && !is_dir($dir)) { + throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $dir)); + } + } + + $profileToken = $profile->getToken(); + // when there are errors in sub-requests, the parent and/or children tokens + // may equal the profile token, resulting in infinite loops + $parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null; + $childrenToken = array_filter(array_map(function (Profile $p) use ($profileToken) { + return $profileToken !== $p->getToken() ? $p->getToken() : null; + }, $profile->getChildren())); + + // Store profile + $data = [ + 'token' => $profileToken, + 'parent' => $parentToken, + 'children' => $childrenToken, + 'data' => $profile->getCollectors(), + 'ip' => $profile->getIp(), + 'method' => $profile->getMethod(), + 'url' => $profile->getUrl(), + 'time' => $profile->getTime(), + 'status_code' => $profile->getStatusCode(), + ]; + + $context = stream_context_create(); + + if (\function_exists('gzcompress')) { + $file = 'compress.zlib://'.$file; + stream_context_set_option($context, 'zlib', 'level', 3); + } + + if (false === file_put_contents($file, serialize($data), 0, $context)) { + return false; + } + + if (!$profileIndexed) { + // Add to index + if (false === $file = fopen($this->getIndexFilename(), 'a')) { + return false; + } + + fputcsv($file, [ + $profile->getToken(), + $profile->getIp(), + $profile->getMethod(), + $profile->getUrl(), + $profile->getTime(), + $profile->getParentToken(), + $profile->getStatusCode(), + ]); + fclose($file); + } + + return true; + } + + /** + * Gets filename to store data, associated to the token. + * + * @return string The profile filename + */ + protected function getFilename(string $token) + { + // Uses 4 last characters, because first are mostly the same. + $folderA = substr($token, -2, 2); + $folderB = substr($token, -4, 2); + + return $this->folder.'/'.$folderA.'/'.$folderB.'/'.$token; + } + + /** + * Gets the index filename. + * + * @return string The index filename + */ + protected function getIndexFilename() + { + return $this->folder.'/index.csv'; + } + + /** + * Reads a line in the file, backward. + * + * This function automatically skips the empty lines and do not include the line return in result value. + * + * @param resource $file The file resource, with the pointer placed at the end of the line to read + * + * @return mixed A string representing the line or null if beginning of file is reached + */ + protected function readLineFromFile($file) + { + $line = ''; + $position = ftell($file); + + if (0 === $position) { + return null; + } + + while (true) { + $chunkSize = min($position, 1024); + $position -= $chunkSize; + fseek($file, $position); + + if (0 === $chunkSize) { + // bof reached + break; + } + + $buffer = fread($file, $chunkSize); + + if (false === ($upTo = strrpos($buffer, "\n"))) { + $line = $buffer.$line; + continue; + } + + $position += $upTo; + $line = substr($buffer, $upTo + 1).$line; + fseek($file, max(0, $position), SEEK_SET); + + if ('' !== $line) { + break; + } + } + + return '' === $line ? null : $line; + } + + protected function createProfileFromData(string $token, array $data, Profile $parent = null) + { + $profile = new Profile($token); + $profile->setIp($data['ip']); + $profile->setMethod($data['method']); + $profile->setUrl($data['url']); + $profile->setTime($data['time']); + $profile->setStatusCode($data['status_code']); + $profile->setCollectors($data['data']); + + if (!$parent && $data['parent']) { + $parent = $this->read($data['parent']); + } + + if ($parent) { + $profile->setParent($parent); + } + + foreach ($data['children'] as $token) { + if (!$token || !file_exists($file = $this->getFilename($token))) { + continue; + } + + if (\function_exists('gzcompress')) { + $file = 'compress.zlib://'.$file; + } + + $profile->addChild($this->createProfileFromData($token, unserialize(file_get_contents($file)), $profile)); + } + + return $profile; + } +} diff --git a/vendor/symfony/http-kernel/Profiler/Profile.php b/vendor/symfony/http-kernel/Profiler/Profile.php new file mode 100644 index 0000000..c18e998 --- /dev/null +++ b/vendor/symfony/http-kernel/Profiler/Profile.php @@ -0,0 +1,274 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Profiler; + +use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; + +/** + * Profile. + * + * @author Fabien Potencier + */ +class Profile +{ + private $token; + + /** + * @var DataCollectorInterface[] + */ + private $collectors = []; + + private $ip; + private $method; + private $url; + private $time; + private $statusCode; + + /** + * @var Profile + */ + private $parent; + + /** + * @var Profile[] + */ + private $children = []; + + public function __construct(string $token) + { + $this->token = $token; + } + + public function setToken(string $token) + { + $this->token = $token; + } + + /** + * Gets the token. + * + * @return string The token + */ + public function getToken() + { + return $this->token; + } + + /** + * Sets the parent token. + */ + public function setParent(self $parent) + { + $this->parent = $parent; + } + + /** + * Returns the parent profile. + * + * @return self + */ + public function getParent() + { + return $this->parent; + } + + /** + * Returns the parent token. + * + * @return string|null The parent token + */ + public function getParentToken() + { + return $this->parent ? $this->parent->getToken() : null; + } + + /** + * Returns the IP. + * + * @return string|null The IP + */ + public function getIp() + { + return $this->ip; + } + + public function setIp(string $ip) + { + $this->ip = $ip; + } + + /** + * Returns the request method. + * + * @return string|null The request method + */ + public function getMethod() + { + return $this->method; + } + + public function setMethod(string $method) + { + $this->method = $method; + } + + /** + * Returns the URL. + * + * @return string|null The URL + */ + public function getUrl() + { + return $this->url; + } + + public function setUrl(string $url) + { + $this->url = $url; + } + + /** + * @return int The time + */ + public function getTime() + { + if (null === $this->time) { + return 0; + } + + return $this->time; + } + + public function setTime(int $time) + { + $this->time = $time; + } + + public function setStatusCode(int $statusCode) + { + $this->statusCode = $statusCode; + } + + /** + * @return int|null + */ + public function getStatusCode() + { + return $this->statusCode; + } + + /** + * Finds children profilers. + * + * @return self[] + */ + public function getChildren() + { + return $this->children; + } + + /** + * Sets children profiler. + * + * @param Profile[] $children + */ + public function setChildren(array $children) + { + $this->children = []; + foreach ($children as $child) { + $this->addChild($child); + } + } + + /** + * Adds the child token. + */ + public function addChild(self $child) + { + $this->children[] = $child; + $child->setParent($this); + } + + public function getChildByToken(string $token): ?self + { + foreach ($this->children as $child) { + if ($token === $child->getToken()) { + return $child; + } + } + + return null; + } + + /** + * Gets a Collector by name. + * + * @return DataCollectorInterface A DataCollectorInterface instance + * + * @throws \InvalidArgumentException if the collector does not exist + */ + public function getCollector(string $name) + { + if (!isset($this->collectors[$name])) { + throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name)); + } + + return $this->collectors[$name]; + } + + /** + * Gets the Collectors associated with this profile. + * + * @return DataCollectorInterface[] + */ + public function getCollectors() + { + return $this->collectors; + } + + /** + * Sets the Collectors associated with this profile. + * + * @param DataCollectorInterface[] $collectors + */ + public function setCollectors(array $collectors) + { + $this->collectors = []; + foreach ($collectors as $collector) { + $this->addCollector($collector); + } + } + + /** + * Adds a Collector. + */ + public function addCollector(DataCollectorInterface $collector) + { + $this->collectors[$collector->getName()] = $collector; + } + + /** + * @return bool + */ + public function hasCollector(string $name) + { + return isset($this->collectors[$name]); + } + + /** + * @return array + */ + public function __sleep() + { + return ['token', 'parent', 'children', 'collectors', 'ip', 'method', 'url', 'time', 'statusCode']; + } +} diff --git a/vendor/symfony/http-kernel/Profiler/Profiler.php b/vendor/symfony/http-kernel/Profiler/Profiler.php new file mode 100644 index 0000000..72af8e0 --- /dev/null +++ b/vendor/symfony/http-kernel/Profiler/Profiler.php @@ -0,0 +1,253 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Profiler; + +use Psr\Log\LoggerInterface; +use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; +use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; +use Symfony\Contracts\Service\ResetInterface; + +/** + * Profiler. + * + * @author Fabien Potencier + */ +class Profiler implements ResetInterface +{ + private $storage; + + /** + * @var DataCollectorInterface[] + */ + private $collectors = []; + + private $logger; + private $initiallyEnabled = true; + private $enabled = true; + + public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null, bool $enable = true) + { + $this->storage = $storage; + $this->logger = $logger; + $this->initiallyEnabled = $this->enabled = $enable; + } + + /** + * Disables the profiler. + */ + public function disable() + { + $this->enabled = false; + } + + /** + * Enables the profiler. + */ + public function enable() + { + $this->enabled = true; + } + + /** + * Loads the Profile for the given Response. + * + * @return Profile|null A Profile instance + */ + public function loadProfileFromResponse(Response $response) + { + if (!$token = $response->headers->get('X-Debug-Token')) { + return null; + } + + return $this->loadProfile($token); + } + + /** + * Loads the Profile for the given token. + * + * @return Profile|null A Profile instance + */ + public function loadProfile(string $token) + { + return $this->storage->read($token); + } + + /** + * Saves a Profile. + * + * @return bool + */ + public function saveProfile(Profile $profile) + { + // late collect + foreach ($profile->getCollectors() as $collector) { + if ($collector instanceof LateDataCollectorInterface) { + $collector->lateCollect(); + } + } + + if (!($ret = $this->storage->write($profile)) && null !== $this->logger) { + $this->logger->warning('Unable to store the profiler information.', ['configured_storage' => \get_class($this->storage)]); + } + + return $ret; + } + + /** + * Purges all data from the storage. + */ + public function purge() + { + $this->storage->purge(); + } + + /** + * Finds profiler tokens for the given criteria. + * + * @param string|null $limit The maximum number of tokens to return + * @param string|null $start The start date to search from + * @param string|null $end The end date to search to + * + * @return array An array of tokens + * + * @see https://php.net/datetime.formats for the supported date/time formats + */ + public function find(?string $ip, ?string $url, ?string $limit, ?string $method, ?string $start, ?string $end, string $statusCode = null) + { + return $this->storage->find($ip, $url, $limit, $method, $this->getTimestamp($start), $this->getTimestamp($end), $statusCode); + } + + /** + * Collects data for the given Response. + * + * @return Profile|null A Profile instance or null if the profiler is disabled + */ + public function collect(Request $request, Response $response, \Throwable $exception = null) + { + if (false === $this->enabled) { + return null; + } + + $profile = new Profile(substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6)); + $profile->setTime(time()); + $profile->setUrl($request->getUri()); + $profile->setMethod($request->getMethod()); + $profile->setStatusCode($response->getStatusCode()); + try { + $profile->setIp($request->getClientIp()); + } catch (ConflictingHeadersException $e) { + $profile->setIp('Unknown'); + } + + if ($prevToken = $response->headers->get('X-Debug-Token')) { + $response->headers->set('X-Previous-Debug-Token', $prevToken); + } + + $response->headers->set('X-Debug-Token', $profile->getToken()); + + foreach ($this->collectors as $collector) { + $collector->collect($request, $response, $exception); + + // we need to clone for sub-requests + $profile->addCollector(clone $collector); + } + + return $profile; + } + + public function reset() + { + foreach ($this->collectors as $collector) { + $collector->reset(); + } + $this->enabled = $this->initiallyEnabled; + } + + /** + * Gets the Collectors associated with this profiler. + * + * @return array An array of collectors + */ + public function all() + { + return $this->collectors; + } + + /** + * Sets the Collectors associated with this profiler. + * + * @param DataCollectorInterface[] $collectors An array of collectors + */ + public function set(array $collectors = []) + { + $this->collectors = []; + foreach ($collectors as $collector) { + $this->add($collector); + } + } + + /** + * Adds a Collector. + */ + public function add(DataCollectorInterface $collector) + { + $this->collectors[$collector->getName()] = $collector; + } + + /** + * Returns true if a Collector for the given name exists. + * + * @param string $name A collector name + * + * @return bool + */ + public function has(string $name) + { + return isset($this->collectors[$name]); + } + + /** + * Gets a Collector by name. + * + * @param string $name A collector name + * + * @return DataCollectorInterface A DataCollectorInterface instance + * + * @throws \InvalidArgumentException if the collector does not exist + */ + public function get(string $name) + { + if (!isset($this->collectors[$name])) { + throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name)); + } + + return $this->collectors[$name]; + } + + private function getTimestamp(?string $value): ?int + { + if (null === $value || '' === $value) { + return null; + } + + try { + $value = new \DateTime(is_numeric($value) ? '@'.$value : $value); + } catch (\Exception $e) { + return null; + } + + return $value->getTimestamp(); + } +} diff --git a/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php b/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php new file mode 100644 index 0000000..0fbc449 --- /dev/null +++ b/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Profiler; + +/** + * ProfilerStorageInterface. + * + * This interface exists for historical reasons. The only supported + * implementation is FileProfilerStorage. + * + * As the profiler must only be used on non-production servers, the file storage + * is more than enough and no other implementations will ever be supported. + * + * @internal + * + * @author Fabien Potencier + */ +interface ProfilerStorageInterface +{ + /** + * Finds profiler tokens for the given criteria. + * + * @param int|null $limit The maximum number of tokens to return + * @param int|null $start The start date to search from + * @param int|null $end The end date to search to + * + * @return array An array of tokens + */ + public function find(?string $ip, ?string $url, ?int $limit, ?string $method, int $start = null, int $end = null): array; + + /** + * Reads data associated with the given token. + * + * The method returns false if the token does not exist in the storage. + * + * @return Profile|null The profile associated with token + */ + public function read(string $token): ?Profile; + + /** + * Saves a Profile. + * + * @return bool Write operation successful + */ + public function write(Profile $profile): bool; + + /** + * Purges all data from the database. + */ + public function purge(); +} diff --git a/vendor/symfony/http-kernel/README.md b/vendor/symfony/http-kernel/README.md new file mode 100644 index 0000000..cc5e74b --- /dev/null +++ b/vendor/symfony/http-kernel/README.md @@ -0,0 +1,16 @@ +HttpKernel Component +==================== + +The HttpKernel component provides a structured process for converting a Request +into a Response by making use of the EventDispatcher component. It's flexible +enough to create a full-stack framework (Symfony), a micro-framework (Silex) or +an advanced CMS system (Drupal). + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/http_kernel/index.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/http-kernel/RebootableInterface.php b/vendor/symfony/http-kernel/RebootableInterface.php new file mode 100644 index 0000000..0dc46c3 --- /dev/null +++ b/vendor/symfony/http-kernel/RebootableInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +/** + * Allows the Kernel to be rebooted using a temporary cache directory. + * + * @author Nicolas Grekas + */ +interface RebootableInterface +{ + /** + * Reboots a kernel. + * + * The getCacheDir() method of a rebootable kernel should not be called + * while building the container. Use the %kernel.cache_dir% parameter instead. + * + * @param string|null $warmupDir pass null to reboot in the regular cache directory + */ + public function reboot(?string $warmupDir); +} diff --git a/vendor/symfony/http-kernel/Resources/welcome.html.php b/vendor/symfony/http-kernel/Resources/welcome.html.php new file mode 100644 index 0000000..e1c0ff1 --- /dev/null +++ b/vendor/symfony/http-kernel/Resources/welcome.html.php @@ -0,0 +1,119 @@ + + + + + + Welcome to Symfony! + + + +
    +
    + + You're seeing this page because you haven't configured any homepage URL. +
    + +
    +
    + +

    Welcome to Symfony

    +
    + +
    + + + + + + +

    Your application is now ready and you can start working on it.

    +
    + + +
    + +
    + +
    +
    + + diff --git a/vendor/symfony/http-kernel/TerminableInterface.php b/vendor/symfony/http-kernel/TerminableInterface.php new file mode 100644 index 0000000..8aa3319 --- /dev/null +++ b/vendor/symfony/http-kernel/TerminableInterface.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * Terminable extends the Kernel request/response cycle with dispatching a post + * response event after sending the response and before shutting down the kernel. + * + * @author Jordi Boggiano + * @author Pierre Minnieur + */ +interface TerminableInterface +{ + /** + * Terminates a request/response cycle. + * + * Should be called after sending the response and before shutting down the kernel. + */ + public function terminate(Request $request, Response $response); +} diff --git a/vendor/symfony/http-kernel/UriSigner.php b/vendor/symfony/http-kernel/UriSigner.php new file mode 100644 index 0000000..4dfb2bb --- /dev/null +++ b/vendor/symfony/http-kernel/UriSigner.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +/** + * Signs URIs. + * + * @author Fabien Potencier + */ +class UriSigner +{ + private $secret; + private $parameter; + + /** + * @param string $secret A secret + * @param string $parameter Query string parameter to use + */ + public function __construct(string $secret, string $parameter = '_hash') + { + $this->secret = $secret; + $this->parameter = $parameter; + } + + /** + * Signs a URI. + * + * The given URI is signed by adding the query string parameter + * which value depends on the URI and the secret. + * + * @return string The signed URI + */ + public function sign(string $uri) + { + $url = parse_url($uri); + if (isset($url['query'])) { + parse_str($url['query'], $params); + } else { + $params = []; + } + + $uri = $this->buildUrl($url, $params); + $params[$this->parameter] = $this->computeHash($uri); + + return $this->buildUrl($url, $params); + } + + /** + * Checks that a URI contains the correct hash. + * + * @return bool True if the URI is signed correctly, false otherwise + */ + public function check(string $uri) + { + $url = parse_url($uri); + if (isset($url['query'])) { + parse_str($url['query'], $params); + } else { + $params = []; + } + + if (empty($params[$this->parameter])) { + return false; + } + + $hash = $params[$this->parameter]; + unset($params[$this->parameter]); + + return hash_equals($this->computeHash($this->buildUrl($url, $params)), $hash); + } + + private function computeHash(string $uri): string + { + return base64_encode(hash_hmac('sha256', $uri, $this->secret, true)); + } + + private function buildUrl(array $url, array $params = []): string + { + ksort($params, SORT_STRING); + $url['query'] = http_build_query($params, '', '&'); + + $scheme = isset($url['scheme']) ? $url['scheme'].'://' : ''; + $host = isset($url['host']) ? $url['host'] : ''; + $port = isset($url['port']) ? ':'.$url['port'] : ''; + $user = isset($url['user']) ? $url['user'] : ''; + $pass = isset($url['pass']) ? ':'.$url['pass'] : ''; + $pass = ($user || $pass) ? "$pass@" : ''; + $path = isset($url['path']) ? $url['path'] : ''; + $query = isset($url['query']) && $url['query'] ? '?'.$url['query'] : ''; + $fragment = isset($url['fragment']) ? '#'.$url['fragment'] : ''; + + return $scheme.$user.$pass.$host.$port.$path.$query.$fragment; + } +} diff --git a/vendor/symfony/http-kernel/composer.json b/vendor/symfony/http-kernel/composer.json new file mode 100644 index 0000000..73621a5 --- /dev/null +++ b/vendor/symfony/http-kernel/composer.json @@ -0,0 +1,80 @@ +{ + "name": "symfony/http-kernel", + "type": "library", + "description": "Symfony HttpKernel Component", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "symfony/error-handler": "^4.4|^5.0", + "symfony/event-dispatcher": "^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-php73": "^1.9", + "psr/log": "~1.0" + }, + "require-dev": { + "symfony/browser-kit": "^4.4|^5.0", + "symfony/config": "^5.0", + "symfony/console": "^4.4|^5.0", + "symfony/css-selector": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/finder": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "symfony/routing": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0", + "symfony/translation": "^4.4|^5.0", + "symfony/translation-contracts": "^1.1|^2", + "psr/cache": "~1.0", + "twig/twig": "^2.4|^3.0" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "conflict": { + "symfony/browser-kit": "<4.4", + "symfony/cache": "<5.0", + "symfony/config": "<5.0", + "symfony/form": "<5.0", + "symfony/dependency-injection": "<4.4", + "symfony/doctrine-bridge": "<5.0", + "symfony/http-client": "<5.0", + "symfony/mailer": "<5.0", + "symfony/messenger": "<5.0", + "symfony/translation": "<5.0", + "symfony/twig-bridge": "<5.0", + "symfony/validator": "<5.0", + "twig/twig": "<2.4" + }, + "suggest": { + "symfony/browser-kit": "", + "symfony/config": "", + "symfony/console": "", + "symfony/dependency-injection": "" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\HttpKernel\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/mime/.gitattributes b/vendor/symfony/mime/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/mime/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/mime/Address.php b/vendor/symfony/mime/Address.php new file mode 100644 index 0000000..b0dcbd0 --- /dev/null +++ b/vendor/symfony/mime/Address.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Egulias\EmailValidator\EmailValidator; +use Egulias\EmailValidator\Validation\RFCValidation; +use Symfony\Component\Mime\Encoder\IdnAddressEncoder; +use Symfony\Component\Mime\Exception\InvalidArgumentException; +use Symfony\Component\Mime\Exception\LogicException; +use Symfony\Component\Mime\Exception\RfcComplianceException; + +/** + * @author Fabien Potencier + */ +final class Address +{ + /** + * A regex that matches a structure like 'Name '. + * It matches anything between the first < and last > as email address. + * This allows to use a single string to construct an Address, which can be convenient to use in + * config, and allows to have more readable config. + * This does not try to cover all edge cases for address. + */ + private const FROM_STRING_PATTERN = '~(?[^<]*)<(?.*)>[^>]*~'; + + private static $validator; + private static $encoder; + + private $address; + private $name; + + public function __construct(string $address, string $name = '') + { + if (!class_exists(EmailValidator::class)) { + throw new LogicException(sprintf('The "%s" class cannot be used as it needs "%s"; try running "composer require egulias/email-validator".', __CLASS__, EmailValidator::class)); + } + + if (null === self::$validator) { + self::$validator = new EmailValidator(); + } + + $this->address = trim($address); + $this->name = trim(str_replace(["\n", "\r"], '', $name)); + + if (!self::$validator->isValid($this->address, new RFCValidation())) { + throw new RfcComplianceException(sprintf('Email "%s" does not comply with addr-spec of RFC 2822.', $address)); + } + } + + public function getAddress(): string + { + return $this->address; + } + + public function getName(): string + { + return $this->name; + } + + public function getEncodedAddress(): string + { + if (null === self::$encoder) { + self::$encoder = new IdnAddressEncoder(); + } + + return self::$encoder->encodeString($this->address); + } + + public function toString(): string + { + return ($n = $this->getName()) ? $n.' <'.$this->getEncodedAddress().'>' : $this->getEncodedAddress(); + } + + /** + * @param Address|string $address + */ + public static function create($address): self + { + if ($address instanceof self) { + return $address; + } + if (\is_string($address)) { + return new self($address); + } + + throw new InvalidArgumentException(sprintf('An address can be an instance of Address or a string ("%s") given).', \is_object($address) ? \get_class($address) : \gettype($address))); + } + + /** + * @param (Address|string)[] $addresses + * + * @return Address[] + */ + public static function createArray(array $addresses): array + { + $addrs = []; + foreach ($addresses as $address) { + $addrs[] = self::create($address); + } + + return $addrs; + } + + public static function fromString(string $string): self + { + if (false === strpos($string, '<')) { + return new self($string, ''); + } + + if (!preg_match(self::FROM_STRING_PATTERN, $string, $matches)) { + throw new InvalidArgumentException(sprintf('Could not parse "%s" to a "%s" instance.', $string, static::class)); + } + + return new self($matches['addrSpec'], trim($matches['displayName'], ' \'"')); + } +} diff --git a/vendor/symfony/mime/BodyRendererInterface.php b/vendor/symfony/mime/BodyRendererInterface.php new file mode 100644 index 0000000..d692172 --- /dev/null +++ b/vendor/symfony/mime/BodyRendererInterface.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +/** + * @author Fabien Potencier + */ +interface BodyRendererInterface +{ + public function render(Message $message): void; +} diff --git a/vendor/symfony/mime/CHANGELOG.md b/vendor/symfony/mime/CHANGELOG.md new file mode 100644 index 0000000..6148360 --- /dev/null +++ b/vendor/symfony/mime/CHANGELOG.md @@ -0,0 +1,20 @@ +CHANGELOG +========= + +4.4.0 +----- + + * [BC BREAK] Removed `NamedAddress` (`Address` now supports a name) + * Added PHPUnit constraints + * Added `AbstractPart::asDebugString()` + * Added `Address::fromString()` + +4.3.3 +----- + + * [BC BREAK] Renamed method `Headers::getAll()` to `Headers::all()`. + +4.3.0 +----- + + * Introduced the component as experimental diff --git a/vendor/symfony/mime/CharacterStream.php b/vendor/symfony/mime/CharacterStream.php new file mode 100644 index 0000000..749066f --- /dev/null +++ b/vendor/symfony/mime/CharacterStream.php @@ -0,0 +1,221 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +/** + * @author Fabien Potencier + * @author Xavier De Cock + * + * @internal + */ +final class CharacterStream +{ + /** Pre-computed for optimization */ + private const UTF8_LENGTH_MAP = [ + "\x00" => 1, "\x01" => 1, "\x02" => 1, "\x03" => 1, "\x04" => 1, "\x05" => 1, "\x06" => 1, "\x07" => 1, + "\x08" => 1, "\x09" => 1, "\x0a" => 1, "\x0b" => 1, "\x0c" => 1, "\x0d" => 1, "\x0e" => 1, "\x0f" => 1, + "\x10" => 1, "\x11" => 1, "\x12" => 1, "\x13" => 1, "\x14" => 1, "\x15" => 1, "\x16" => 1, "\x17" => 1, + "\x18" => 1, "\x19" => 1, "\x1a" => 1, "\x1b" => 1, "\x1c" => 1, "\x1d" => 1, "\x1e" => 1, "\x1f" => 1, + "\x20" => 1, "\x21" => 1, "\x22" => 1, "\x23" => 1, "\x24" => 1, "\x25" => 1, "\x26" => 1, "\x27" => 1, + "\x28" => 1, "\x29" => 1, "\x2a" => 1, "\x2b" => 1, "\x2c" => 1, "\x2d" => 1, "\x2e" => 1, "\x2f" => 1, + "\x30" => 1, "\x31" => 1, "\x32" => 1, "\x33" => 1, "\x34" => 1, "\x35" => 1, "\x36" => 1, "\x37" => 1, + "\x38" => 1, "\x39" => 1, "\x3a" => 1, "\x3b" => 1, "\x3c" => 1, "\x3d" => 1, "\x3e" => 1, "\x3f" => 1, + "\x40" => 1, "\x41" => 1, "\x42" => 1, "\x43" => 1, "\x44" => 1, "\x45" => 1, "\x46" => 1, "\x47" => 1, + "\x48" => 1, "\x49" => 1, "\x4a" => 1, "\x4b" => 1, "\x4c" => 1, "\x4d" => 1, "\x4e" => 1, "\x4f" => 1, + "\x50" => 1, "\x51" => 1, "\x52" => 1, "\x53" => 1, "\x54" => 1, "\x55" => 1, "\x56" => 1, "\x57" => 1, + "\x58" => 1, "\x59" => 1, "\x5a" => 1, "\x5b" => 1, "\x5c" => 1, "\x5d" => 1, "\x5e" => 1, "\x5f" => 1, + "\x60" => 1, "\x61" => 1, "\x62" => 1, "\x63" => 1, "\x64" => 1, "\x65" => 1, "\x66" => 1, "\x67" => 1, + "\x68" => 1, "\x69" => 1, "\x6a" => 1, "\x6b" => 1, "\x6c" => 1, "\x6d" => 1, "\x6e" => 1, "\x6f" => 1, + "\x70" => 1, "\x71" => 1, "\x72" => 1, "\x73" => 1, "\x74" => 1, "\x75" => 1, "\x76" => 1, "\x77" => 1, + "\x78" => 1, "\x79" => 1, "\x7a" => 1, "\x7b" => 1, "\x7c" => 1, "\x7d" => 1, "\x7e" => 1, "\x7f" => 1, + "\x80" => 0, "\x81" => 0, "\x82" => 0, "\x83" => 0, "\x84" => 0, "\x85" => 0, "\x86" => 0, "\x87" => 0, + "\x88" => 0, "\x89" => 0, "\x8a" => 0, "\x8b" => 0, "\x8c" => 0, "\x8d" => 0, "\x8e" => 0, "\x8f" => 0, + "\x90" => 0, "\x91" => 0, "\x92" => 0, "\x93" => 0, "\x94" => 0, "\x95" => 0, "\x96" => 0, "\x97" => 0, + "\x98" => 0, "\x99" => 0, "\x9a" => 0, "\x9b" => 0, "\x9c" => 0, "\x9d" => 0, "\x9e" => 0, "\x9f" => 0, + "\xa0" => 0, "\xa1" => 0, "\xa2" => 0, "\xa3" => 0, "\xa4" => 0, "\xa5" => 0, "\xa6" => 0, "\xa7" => 0, + "\xa8" => 0, "\xa9" => 0, "\xaa" => 0, "\xab" => 0, "\xac" => 0, "\xad" => 0, "\xae" => 0, "\xaf" => 0, + "\xb0" => 0, "\xb1" => 0, "\xb2" => 0, "\xb3" => 0, "\xb4" => 0, "\xb5" => 0, "\xb6" => 0, "\xb7" => 0, + "\xb8" => 0, "\xb9" => 0, "\xba" => 0, "\xbb" => 0, "\xbc" => 0, "\xbd" => 0, "\xbe" => 0, "\xbf" => 0, + "\xc0" => 2, "\xc1" => 2, "\xc2" => 2, "\xc3" => 2, "\xc4" => 2, "\xc5" => 2, "\xc6" => 2, "\xc7" => 2, + "\xc8" => 2, "\xc9" => 2, "\xca" => 2, "\xcb" => 2, "\xcc" => 2, "\xcd" => 2, "\xce" => 2, "\xcf" => 2, + "\xd0" => 2, "\xd1" => 2, "\xd2" => 2, "\xd3" => 2, "\xd4" => 2, "\xd5" => 2, "\xd6" => 2, "\xd7" => 2, + "\xd8" => 2, "\xd9" => 2, "\xda" => 2, "\xdb" => 2, "\xdc" => 2, "\xdd" => 2, "\xde" => 2, "\xdf" => 2, + "\xe0" => 3, "\xe1" => 3, "\xe2" => 3, "\xe3" => 3, "\xe4" => 3, "\xe5" => 3, "\xe6" => 3, "\xe7" => 3, + "\xe8" => 3, "\xe9" => 3, "\xea" => 3, "\xeb" => 3, "\xec" => 3, "\xed" => 3, "\xee" => 3, "\xef" => 3, + "\xf0" => 4, "\xf1" => 4, "\xf2" => 4, "\xf3" => 4, "\xf4" => 4, "\xf5" => 4, "\xf6" => 4, "\xf7" => 4, + "\xf8" => 5, "\xf9" => 5, "\xfa" => 5, "\xfb" => 5, "\xfc" => 6, "\xfd" => 6, "\xfe" => 0, "\xff" => 0, + ]; + + private $data = ''; + private $dataSize = 0; + private $map = []; + private $charCount = 0; + private $currentPos = 0; + private $fixedWidth = 0; + + /** + * @param resource|string $input + */ + public function __construct($input, ?string $charset = 'utf-8') + { + $charset = strtolower(trim($charset)) ?: 'utf-8'; + if ('utf-8' === $charset || 'utf8' === $charset) { + $this->fixedWidth = 0; + $this->map = ['p' => [], 'i' => []]; + } else { + switch ($charset) { + // 16 bits + case 'ucs2': + case 'ucs-2': + case 'utf16': + case 'utf-16': + $this->fixedWidth = 2; + break; + + // 32 bits + case 'ucs4': + case 'ucs-4': + case 'utf32': + case 'utf-32': + $this->fixedWidth = 4; + break; + + // 7-8 bit charsets: (us-)?ascii, (iso|iec)-?8859-?[0-9]+, windows-?125[0-9], cp-?[0-9]+, ansi, macintosh, + // koi-?7, koi-?8-?.+, mik, (cork|t1), v?iscii + // and fallback + default: + $this->fixedWidth = 1; + } + } + if (\is_resource($input)) { + $blocks = 512; + if (stream_get_meta_data($input)['seekable'] ?? false) { + rewind($input); + } + while (false !== $read = fread($input, $blocks)) { + $this->write($read); + } + } else { + $this->write($input); + } + } + + public function read(int $length): ?string + { + if ($this->currentPos >= $this->charCount) { + return null; + } + $length = ($this->currentPos + $length > $this->charCount) ? $this->charCount - $this->currentPos : $length; + if ($this->fixedWidth > 0) { + $len = $length * $this->fixedWidth; + $ret = substr($this->data, $this->currentPos * $this->fixedWidth, $len); + $this->currentPos += $length; + } else { + $end = $this->currentPos + $length; + $end = $end > $this->charCount ? $this->charCount : $end; + $ret = ''; + $start = 0; + if ($this->currentPos > 0) { + $start = $this->map['p'][$this->currentPos - 1]; + } + $to = $start; + for (; $this->currentPos < $end; ++$this->currentPos) { + if (isset($this->map['i'][$this->currentPos])) { + $ret .= substr($this->data, $start, $to - $start).'?'; + $start = $this->map['p'][$this->currentPos]; + } else { + $to = $this->map['p'][$this->currentPos]; + } + } + $ret .= substr($this->data, $start, $to - $start); + } + + return $ret; + } + + public function readBytes(int $length): ?array + { + if (null !== $read = $this->read($length)) { + return array_map('ord', str_split($read, 1)); + } + + return null; + } + + public function setPointer(int $charOffset): void + { + if ($this->charCount < $charOffset) { + $charOffset = $this->charCount; + } + $this->currentPos = $charOffset; + } + + public function write(string $chars): void + { + $ignored = ''; + $this->data .= $chars; + if ($this->fixedWidth > 0) { + $strlen = \strlen($chars); + $ignoredL = $strlen % $this->fixedWidth; + $ignored = $ignoredL ? substr($chars, -$ignoredL) : ''; + $this->charCount += ($strlen - $ignoredL) / $this->fixedWidth; + } else { + $this->charCount += $this->getUtf8CharPositions($chars, $this->dataSize, $ignored); + } + $this->dataSize = \strlen($this->data) - \strlen($ignored); + } + + private function getUtf8CharPositions(string $string, int $startOffset, string &$ignoredChars): int + { + $strlen = \strlen($string); + $charPos = \count($this->map['p']); + $foundChars = 0; + $invalid = false; + for ($i = 0; $i < $strlen; ++$i) { + $char = $string[$i]; + $size = self::UTF8_LENGTH_MAP[$char]; + if (0 == $size) { + /* char is invalid, we must wait for a resync */ + $invalid = true; + continue; + } + + if ($invalid) { + /* We mark the chars as invalid and start a new char */ + $this->map['p'][$charPos + $foundChars] = $startOffset + $i; + $this->map['i'][$charPos + $foundChars] = true; + ++$foundChars; + $invalid = false; + } + if (($i + $size) > $strlen) { + $ignoredChars = substr($string, $i); + break; + } + for ($j = 1; $j < $size; ++$j) { + $char = $string[$i + $j]; + if ($char > "\x7F" && $char < "\xC0") { + // Valid - continue parsing + } else { + /* char is invalid, we must wait for a resync */ + $invalid = true; + continue 2; + } + } + /* Ok we got a complete char here */ + $this->map['p'][$charPos + $foundChars] = $startOffset + $i + $size; + $i += $j - 1; + ++$foundChars; + } + + return $foundChars; + } +} diff --git a/vendor/symfony/mime/Crypto/SMime.php b/vendor/symfony/mime/Crypto/SMime.php new file mode 100644 index 0000000..55941be --- /dev/null +++ b/vendor/symfony/mime/Crypto/SMime.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Crypto; + +use Symfony\Component\Mime\Exception\RuntimeException; +use Symfony\Component\Mime\Part\SMimePart; + +/** + * @author Sebastiaan Stok + * + * @internal + */ +abstract class SMime +{ + protected function normalizeFilePath(string $path): string + { + if (!file_exists($path)) { + throw new RuntimeException(sprintf('File does not exist: %s.', $path)); + } + + return 'file://'.str_replace('\\', '/', realpath($path)); + } + + protected function iteratorToFile(iterable $iterator, $stream): void + { + foreach ($iterator as $chunk) { + fwrite($stream, $chunk); + } + } + + protected function convertMessageToSMimePart($stream, string $type, string $subtype): SMimePart + { + rewind($stream); + + $headers = ''; + + while (!feof($stream)) { + $buffer = fread($stream, 78); + $headers .= $buffer; + + // Detect ending of header list + if (preg_match('/(\r\n\r\n|\n\n)/', $headers, $match)) { + $headersPosEnd = strpos($headers, $headerBodySeparator = $match[0]); + + break; + } + } + + $headers = $this->getMessageHeaders(trim(substr($headers, 0, $headersPosEnd))); + + fseek($stream, $headersPosEnd + \strlen($headerBodySeparator)); + + return new SMimePart($this->getStreamIterator($stream), $type, $subtype, $this->getParametersFromHeader($headers['content-type'])); + } + + protected function getStreamIterator($stream): iterable + { + while (!feof($stream)) { + yield fread($stream, 16372); + } + } + + private function getMessageHeaders(string $headerData): array + { + $headers = []; + $headerLines = explode("\r\n", str_replace("\n", "\r\n", str_replace("\r\n", "\n", $headerData))); + $currentHeaderName = ''; + + // Transform header lines into an associative array + foreach ($headerLines as $headerLine) { + // Empty lines between headers indicate a new mime-entity + if ('' === $headerLine) { + break; + } + + // Handle headers that span multiple lines + if (false === strpos($headerLine, ':')) { + $headers[$currentHeaderName] .= ' '.trim($headerLine); + continue; + } + + $header = explode(':', $headerLine, 2); + $currentHeaderName = strtolower($header[0]); + $headers[$currentHeaderName] = trim($header[1]); + } + + return $headers; + } + + private function getParametersFromHeader(string $header): array + { + $params = []; + + preg_match_all('/(?P[a-z-0-9]+)=(?P"[^"]+"|(?:[^\s;]+|$))(?:\s+;)?/i', $header, $matches); + + foreach ($matches['value'] as $pos => $paramValue) { + $params[$matches['name'][$pos]] = trim($paramValue, '"'); + } + + return $params; + } +} diff --git a/vendor/symfony/mime/Crypto/SMimeEncrypter.php b/vendor/symfony/mime/Crypto/SMimeEncrypter.php new file mode 100644 index 0000000..d6961a6 --- /dev/null +++ b/vendor/symfony/mime/Crypto/SMimeEncrypter.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Crypto; + +use Symfony\Component\Mime\Exception\RuntimeException; +use Symfony\Component\Mime\Message; + +/** + * @author Sebastiaan Stok + */ +final class SMimeEncrypter extends SMime +{ + private $certs; + private $cipher; + + /** + * @param string|string[] $certificate The path (or array of paths) of the file(s) containing the X.509 certificate(s) + * @param int|null $cipher A set of algorithms used to encrypt the message. Must be one of these PHP constants: https://www.php.net/manual/en/openssl.ciphers.php + */ + public function __construct($certificate, int $cipher = null) + { + if (!\extension_loaded('openssl')) { + throw new \LogicException('PHP extension "openssl" is required to use SMime.'); + } + + if (\is_array($certificate)) { + $this->certs = array_map([$this, 'normalizeFilePath'], $certificate); + } else { + $this->certs = $this->normalizeFilePath($certificate); + } + + $this->cipher = $cipher ?? OPENSSL_CIPHER_AES_256_CBC; + } + + public function encrypt(Message $message): Message + { + $bufferFile = tmpfile(); + $outputFile = tmpfile(); + + $this->iteratorToFile($message->toIterable(), $bufferFile); + + if (!@openssl_pkcs7_encrypt(stream_get_meta_data($bufferFile)['uri'], stream_get_meta_data($outputFile)['uri'], $this->certs, [], 0, $this->cipher)) { + throw new RuntimeException(sprintf('Failed to encrypt S/Mime message. Error: "%s".', openssl_error_string())); + } + + $mimePart = $this->convertMessageToSMimePart($outputFile, 'application', 'pkcs7-mime'); + $mimePart->getHeaders() + ->addTextHeader('Content-Transfer-Encoding', 'base64') + ->addParameterizedHeader('Content-Disposition', 'attachment', ['name' => 'smime.p7m']) + ; + + return new Message($message->getHeaders(), $mimePart); + } +} diff --git a/vendor/symfony/mime/Crypto/SMimeSigner.php b/vendor/symfony/mime/Crypto/SMimeSigner.php new file mode 100644 index 0000000..243aaf1 --- /dev/null +++ b/vendor/symfony/mime/Crypto/SMimeSigner.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Crypto; + +use Symfony\Component\Mime\Exception\RuntimeException; +use Symfony\Component\Mime\Message; + +/** + * @author Sebastiaan Stok + */ +final class SMimeSigner extends SMime +{ + private $signCertificate; + private $signPrivateKey; + private $signOptions; + private $extraCerts; + + /** + * @var string|null + */ + private $privateKeyPassphrase; + + /** + * @param string $certificate The path of the file containing the signing certificate (in PEM format) + * @param string $privateKey The path of the file containing the private key (in PEM format) + * @param string|null $privateKeyPassphrase A passphrase of the private key (if any) + * @param string|null $extraCerts The path of the file containing intermediate certificates (in PEM format) needed by the signing certificate + * @param int|null $signOptions Bitwise operator options for openssl_pkcs7_sign() (@see https://secure.php.net/manual/en/openssl.pkcs7.flags.php) + */ + public function __construct(string $certificate, string $privateKey, string $privateKeyPassphrase = null, string $extraCerts = null, int $signOptions = null) + { + if (!\extension_loaded('openssl')) { + throw new \LogicException('PHP extension "openssl" is required to use SMime.'); + } + + $this->signCertificate = $this->normalizeFilePath($certificate); + + if (null !== $privateKeyPassphrase) { + $this->signPrivateKey = [$this->normalizeFilePath($privateKey), $privateKeyPassphrase]; + } else { + $this->signPrivateKey = $this->normalizeFilePath($privateKey); + } + + $this->signOptions = $signOptions ?? PKCS7_DETACHED; + $this->extraCerts = $extraCerts ? realpath($extraCerts) : null; + $this->privateKeyPassphrase = $privateKeyPassphrase; + } + + public function sign(Message $message): Message + { + $bufferFile = tmpfile(); + $outputFile = tmpfile(); + + $this->iteratorToFile($message->getBody()->toIterable(), $bufferFile); + + if (!@openssl_pkcs7_sign(stream_get_meta_data($bufferFile)['uri'], stream_get_meta_data($outputFile)['uri'], $this->signCertificate, $this->signPrivateKey, [], $this->signOptions, $this->extraCerts)) { + throw new RuntimeException(sprintf('Failed to sign S/Mime message. Error: "%s".', openssl_error_string())); + } + + return new Message($message->getHeaders(), $this->convertMessageToSMimePart($outputFile, 'multipart', 'signed')); + } +} diff --git a/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php b/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php new file mode 100644 index 0000000..e24beb0 --- /dev/null +++ b/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Registers custom mime types guessers. + * + * @author Fabien Potencier + */ +class AddMimeTypeGuesserPass implements CompilerPassInterface +{ + private $mimeTypesService; + private $mimeTypeGuesserTag; + + public function __construct(string $mimeTypesService = 'mime_types', string $mimeTypeGuesserTag = 'mime.mime_type_guesser') + { + $this->mimeTypesService = $mimeTypesService; + $this->mimeTypeGuesserTag = $mimeTypeGuesserTag; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if ($container->has($this->mimeTypesService)) { + $definition = $container->findDefinition($this->mimeTypesService); + foreach ($container->findTaggedServiceIds($this->mimeTypeGuesserTag, true) as $id => $attributes) { + $definition->addMethodCall('registerGuesser', [new Reference($id)]); + } + } + } +} diff --git a/vendor/symfony/mime/Email.php b/vendor/symfony/mime/Email.php new file mode 100644 index 0000000..fb91262 --- /dev/null +++ b/vendor/symfony/mime/Email.php @@ -0,0 +1,599 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Symfony\Component\Mime\Exception\LogicException; +use Symfony\Component\Mime\Part\AbstractPart; +use Symfony\Component\Mime\Part\DataPart; +use Symfony\Component\Mime\Part\Multipart\AlternativePart; +use Symfony\Component\Mime\Part\Multipart\MixedPart; +use Symfony\Component\Mime\Part\Multipart\RelatedPart; +use Symfony\Component\Mime\Part\TextPart; + +/** + * @author Fabien Potencier + */ +class Email extends Message +{ + const PRIORITY_HIGHEST = 1; + const PRIORITY_HIGH = 2; + const PRIORITY_NORMAL = 3; + const PRIORITY_LOW = 4; + const PRIORITY_LOWEST = 5; + + private const PRIORITY_MAP = [ + self::PRIORITY_HIGHEST => 'Highest', + self::PRIORITY_HIGH => 'High', + self::PRIORITY_NORMAL => 'Normal', + self::PRIORITY_LOW => 'Low', + self::PRIORITY_LOWEST => 'Lowest', + ]; + + private $text; + private $textCharset; + private $html; + private $htmlCharset; + private $attachments = []; + + /** + * @return $this + */ + public function subject(string $subject) + { + return $this->setHeaderBody('Text', 'Subject', $subject); + } + + public function getSubject(): ?string + { + return $this->getHeaders()->getHeaderBody('Subject'); + } + + /** + * @return $this + */ + public function date(\DateTimeInterface $dateTime) + { + return $this->setHeaderBody('Date', 'Date', $dateTime); + } + + public function getDate(): ?\DateTimeImmutable + { + return $this->getHeaders()->getHeaderBody('Date'); + } + + /** + * @param Address|string $address + * + * @return $this + */ + public function returnPath($address) + { + return $this->setHeaderBody('Path', 'Return-Path', Address::create($address)); + } + + public function getReturnPath(): ?Address + { + return $this->getHeaders()->getHeaderBody('Return-Path'); + } + + /** + * @param Address|string $address + * + * @return $this + */ + public function sender($address) + { + return $this->setHeaderBody('Mailbox', 'Sender', Address::create($address)); + } + + public function getSender(): ?Address + { + return $this->getHeaders()->getHeaderBody('Sender'); + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function addFrom(...$addresses) + { + return $this->addListAddressHeaderBody('From', $addresses); + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function from(...$addresses) + { + return $this->setListAddressHeaderBody('From', $addresses); + } + + /** + * @return Address[] + */ + public function getFrom(): array + { + return $this->getHeaders()->getHeaderBody('From') ?: []; + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function addReplyTo(...$addresses) + { + return $this->addListAddressHeaderBody('Reply-To', $addresses); + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function replyTo(...$addresses) + { + return $this->setListAddressHeaderBody('Reply-To', $addresses); + } + + /** + * @return Address[] + */ + public function getReplyTo(): array + { + return $this->getHeaders()->getHeaderBody('Reply-To') ?: []; + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function addTo(...$addresses) + { + return $this->addListAddressHeaderBody('To', $addresses); + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function to(...$addresses) + { + return $this->setListAddressHeaderBody('To', $addresses); + } + + /** + * @return Address[] + */ + public function getTo(): array + { + return $this->getHeaders()->getHeaderBody('To') ?: []; + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function addCc(...$addresses) + { + return $this->addListAddressHeaderBody('Cc', $addresses); + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function cc(...$addresses) + { + return $this->setListAddressHeaderBody('Cc', $addresses); + } + + /** + * @return Address[] + */ + public function getCc(): array + { + return $this->getHeaders()->getHeaderBody('Cc') ?: []; + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function addBcc(...$addresses) + { + return $this->addListAddressHeaderBody('Bcc', $addresses); + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function bcc(...$addresses) + { + return $this->setListAddressHeaderBody('Bcc', $addresses); + } + + /** + * @return Address[] + */ + public function getBcc(): array + { + return $this->getHeaders()->getHeaderBody('Bcc') ?: []; + } + + /** + * Sets the priority of this message. + * + * The value is an integer where 1 is the highest priority and 5 is the lowest. + * + * @return $this + */ + public function priority(int $priority) + { + if ($priority > 5) { + $priority = 5; + } elseif ($priority < 1) { + $priority = 1; + } + + return $this->setHeaderBody('Text', 'X-Priority', sprintf('%d (%s)', $priority, self::PRIORITY_MAP[$priority])); + } + + /** + * Get the priority of this message. + * + * The returned value is an integer where 1 is the highest priority and 5 + * is the lowest. + */ + public function getPriority(): int + { + list($priority) = sscanf($this->getHeaders()->getHeaderBody('X-Priority'), '%[1-5]'); + + return $priority ?? 3; + } + + /** + * @param resource|string $body + * + * @return $this + */ + public function text($body, string $charset = 'utf-8') + { + $this->text = $body; + $this->textCharset = $charset; + + return $this; + } + + /** + * @return resource|string|null + */ + public function getTextBody() + { + return $this->text; + } + + public function getTextCharset(): ?string + { + return $this->textCharset; + } + + /** + * @param resource|string|null $body + * + * @return $this + */ + public function html($body, string $charset = 'utf-8') + { + $this->html = $body; + $this->htmlCharset = $charset; + + return $this; + } + + /** + * @return resource|string|null + */ + public function getHtmlBody() + { + return $this->html; + } + + public function getHtmlCharset(): ?string + { + return $this->htmlCharset; + } + + /** + * @param resource|string $body + * + * @return $this + */ + public function attach($body, string $name = null, string $contentType = null) + { + $this->attachments[] = ['body' => $body, 'name' => $name, 'content-type' => $contentType, 'inline' => false]; + + return $this; + } + + /** + * @return $this + */ + public function attachFromPath(string $path, string $name = null, string $contentType = null) + { + $this->attachments[] = ['path' => $path, 'name' => $name, 'content-type' => $contentType, 'inline' => false]; + + return $this; + } + + /** + * @param resource|string $body + * + * @return $this + */ + public function embed($body, string $name = null, string $contentType = null) + { + $this->attachments[] = ['body' => $body, 'name' => $name, 'content-type' => $contentType, 'inline' => true]; + + return $this; + } + + /** + * @return $this + */ + public function embedFromPath(string $path, string $name = null, string $contentType = null) + { + $this->attachments[] = ['path' => $path, 'name' => $name, 'content-type' => $contentType, 'inline' => true]; + + return $this; + } + + /** + * @return $this + */ + public function attachPart(DataPart $part) + { + $this->attachments[] = ['part' => $part]; + + return $this; + } + + /** + * @return DataPart[] + */ + public function getAttachments(): array + { + $parts = []; + foreach ($this->attachments as $attachment) { + $parts[] = $this->createDataPart($attachment); + } + + return $parts; + } + + public function getBody(): AbstractPart + { + if (null !== $body = parent::getBody()) { + return $body; + } + + return $this->generateBody(); + } + + public function ensureValidity() + { + if (null === $this->text && null === $this->html && !$this->attachments) { + throw new LogicException('A message must have a text or an HTML part or attachments.'); + } + + parent::ensureValidity(); + } + + /** + * Generates an AbstractPart based on the raw body of a message. + * + * The most "complex" part generated by this method is when there is text and HTML bodies + * with related images for the HTML part and some attachments: + * + * multipart/mixed + * | + * |------------> multipart/related + * | | + * | |------------> multipart/alternative + * | | | + * | | ------------> text/plain (with content) + * | | | + * | | ------------> text/html (with content) + * | | + * | ------------> image/png (with content) + * | + * ------------> application/pdf (with content) + */ + private function generateBody(): AbstractPart + { + $this->ensureValidity(); + + [$htmlPart, $attachmentParts, $inlineParts] = $this->prepareParts(); + + $part = null === $this->text ? null : new TextPart($this->text, $this->textCharset); + if (null !== $htmlPart) { + if (null !== $part) { + $part = new AlternativePart($part, $htmlPart); + } else { + $part = $htmlPart; + } + } + + if ($inlineParts) { + $part = new RelatedPart($part, ...$inlineParts); + } + + if ($attachmentParts) { + if ($part) { + $part = new MixedPart($part, ...$attachmentParts); + } else { + $part = new MixedPart(...$attachmentParts); + } + } + + return $part; + } + + private function prepareParts(): ?array + { + $names = []; + $htmlPart = null; + $html = $this->html; + if (null !== $this->html) { + if (\is_resource($html)) { + if (stream_get_meta_data($html)['seekable'] ?? false) { + rewind($html); + } + + $html = stream_get_contents($html); + } + $htmlPart = new TextPart($html, $this->htmlCharset, 'html'); + preg_match_all('(]*src\s*=\s*(?:([\'"])cid:([^"]+)\\1|cid:([^>\s]+)))i', $html, $names); + $names = array_filter(array_unique(array_merge($names[2], $names[3]))); + } + + $attachmentParts = $inlineParts = []; + foreach ($this->attachments as $attachment) { + foreach ($names as $name) { + if (isset($attachment['part'])) { + continue; + } + if ($name !== $attachment['name']) { + continue; + } + if (isset($inlineParts[$name])) { + continue 2; + } + $attachment['inline'] = true; + $inlineParts[$name] = $part = $this->createDataPart($attachment); + $html = str_replace('cid:'.$name, 'cid:'.$part->getContentId(), $html); + continue 2; + } + $attachmentParts[] = $this->createDataPart($attachment); + } + if (null !== $htmlPart) { + $htmlPart = new TextPart($html, $this->htmlCharset, 'html'); + } + + return [$htmlPart, $attachmentParts, array_values($inlineParts)]; + } + + private function createDataPart(array $attachment): DataPart + { + if (isset($attachment['part'])) { + return $attachment['part']; + } + + if (isset($attachment['body'])) { + $part = new DataPart($attachment['body'], $attachment['name'] ?? null, $attachment['content-type'] ?? null); + } else { + $part = DataPart::fromPath($attachment['path'] ?? '', $attachment['name'] ?? null, $attachment['content-type'] ?? null); + } + if ($attachment['inline']) { + $part->asInline(); + } + + return $part; + } + + /** + * @return $this + */ + private function setHeaderBody(string $type, string $name, $body): object + { + $this->getHeaders()->setHeaderBody($type, $name, $body); + + return $this; + } + + private function addListAddressHeaderBody(string $name, array $addresses) + { + if (!$header = $this->getHeaders()->get($name)) { + return $this->setListAddressHeaderBody($name, $addresses); + } + $header->addAddresses(Address::createArray($addresses)); + + return $this; + } + + private function setListAddressHeaderBody(string $name, array $addresses) + { + $addresses = Address::createArray($addresses); + $headers = $this->getHeaders(); + if ($header = $headers->get($name)) { + $header->setAddresses($addresses); + } else { + $headers->addMailboxListHeader($name, $addresses); + } + + return $this; + } + + /** + * @internal + */ + public function __serialize(): array + { + if (\is_resource($this->text)) { + if (stream_get_meta_data($this->text)['seekable'] ?? false) { + rewind($this->text); + } + + $this->text = stream_get_contents($this->text); + } + + if (\is_resource($this->html)) { + if (stream_get_meta_data($this->html)['seekable'] ?? false) { + rewind($this->html); + } + + $this->html = stream_get_contents($this->html); + } + + foreach ($this->attachments as $i => $attachment) { + if (isset($attachment['body']) && \is_resource($attachment['body'])) { + if (stream_get_meta_data($attachment['body'])['seekable'] ?? false) { + rewind($attachment['body']); + } + + $this->attachments[$i]['body'] = stream_get_contents($attachment['body']); + } + } + + return [$this->text, $this->textCharset, $this->html, $this->htmlCharset, $this->attachments, parent::__serialize()]; + } + + /** + * @internal + */ + public function __unserialize(array $data): void + { + [$this->text, $this->textCharset, $this->html, $this->htmlCharset, $this->attachments, $parentData] = $data; + + parent::__unserialize($parentData); + } +} diff --git a/vendor/symfony/mime/Encoder/AddressEncoderInterface.php b/vendor/symfony/mime/Encoder/AddressEncoderInterface.php new file mode 100644 index 0000000..de477d8 --- /dev/null +++ b/vendor/symfony/mime/Encoder/AddressEncoderInterface.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +use Symfony\Component\Mime\Exception\AddressEncoderException; + +/** + * @author Christian Schmidt + */ +interface AddressEncoderInterface +{ + /** + * Encodes an email address. + * + * @throws AddressEncoderException if the email cannot be represented in + * the encoding implemented by this class + */ + public function encodeString(string $address): string; +} diff --git a/vendor/symfony/mime/Encoder/Base64ContentEncoder.php b/vendor/symfony/mime/Encoder/Base64ContentEncoder.php new file mode 100644 index 0000000..338490b --- /dev/null +++ b/vendor/symfony/mime/Encoder/Base64ContentEncoder.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +use Symfony\Component\Mime\Exception\RuntimeException; + +/** + * @author Fabien Potencier + */ +final class Base64ContentEncoder extends Base64Encoder implements ContentEncoderInterface +{ + public function encodeByteStream($stream, int $maxLineLength = 0): iterable + { + if (!\is_resource($stream)) { + throw new \TypeError(sprintf('Method "%s" takes a stream as a first argument.', __METHOD__)); + } + + $filter = stream_filter_append($stream, 'convert.base64-encode', \STREAM_FILTER_READ, [ + 'line-length' => 0 >= $maxLineLength || 76 < $maxLineLength ? 76 : $maxLineLength, + 'line-break-chars' => "\r\n", + ]); + if (!\is_resource($filter)) { + throw new RuntimeException('Unable to set the base64 content encoder to the filter.'); + } + + if (stream_get_meta_data($stream)['seekable'] ?? false) { + rewind($stream); + } + while (!feof($stream)) { + yield fread($stream, 8192); + } + stream_filter_remove($filter); + } + + public function getName(): string + { + return 'base64'; + } +} diff --git a/vendor/symfony/mime/Encoder/Base64Encoder.php b/vendor/symfony/mime/Encoder/Base64Encoder.php new file mode 100644 index 0000000..7106478 --- /dev/null +++ b/vendor/symfony/mime/Encoder/Base64Encoder.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Chris Corbyn + */ +class Base64Encoder implements EncoderInterface +{ + /** + * Takes an unencoded string and produces a Base64 encoded string from it. + * + * Base64 encoded strings have a maximum line length of 76 characters. + * If the first line needs to be shorter, indicate the difference with + * $firstLineOffset. + */ + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + if (0 >= $maxLineLength || 76 < $maxLineLength) { + $maxLineLength = 76; + } + + $encodedString = base64_encode($string); + $firstLine = ''; + if (0 !== $firstLineOffset) { + $firstLine = substr($encodedString, 0, $maxLineLength - $firstLineOffset)."\r\n"; + $encodedString = substr($encodedString, $maxLineLength - $firstLineOffset); + } + + return $firstLine.trim(chunk_split($encodedString, $maxLineLength, "\r\n")); + } +} diff --git a/vendor/symfony/mime/Encoder/Base64MimeHeaderEncoder.php b/vendor/symfony/mime/Encoder/Base64MimeHeaderEncoder.php new file mode 100644 index 0000000..5c06f6d --- /dev/null +++ b/vendor/symfony/mime/Encoder/Base64MimeHeaderEncoder.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Chris Corbyn + */ +final class Base64MimeHeaderEncoder extends Base64Encoder implements MimeHeaderEncoderInterface +{ + public function getName(): string + { + return 'B'; + } + + /** + * Takes an unencoded string and produces a Base64 encoded string from it. + * + * If the charset is iso-2022-jp, it uses mb_encode_mimeheader instead of + * default encodeString, otherwise pass to the parent method. + */ + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + if ('iso-2022-jp' === strtolower($charset)) { + $old = mb_internal_encoding(); + mb_internal_encoding('utf-8'); + $newstring = mb_encode_mimeheader($string, 'iso-2022-jp', $this->getName(), "\r\n"); + mb_internal_encoding($old); + + return $newstring; + } + + return parent::encodeString($string, $charset, $firstLineOffset, $maxLineLength); + } +} diff --git a/vendor/symfony/mime/Encoder/ContentEncoderInterface.php b/vendor/symfony/mime/Encoder/ContentEncoderInterface.php new file mode 100644 index 0000000..a45ad04 --- /dev/null +++ b/vendor/symfony/mime/Encoder/ContentEncoderInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Chris Corbyn + */ +interface ContentEncoderInterface extends EncoderInterface +{ + /** + * Encodes the stream to a Generator. + * + * @param resource $stream + */ + public function encodeByteStream($stream, int $maxLineLength = 0): iterable; + + /** + * Gets the MIME name of this content encoding scheme. + */ + public function getName(): string; +} diff --git a/vendor/symfony/mime/Encoder/EightBitContentEncoder.php b/vendor/symfony/mime/Encoder/EightBitContentEncoder.php new file mode 100644 index 0000000..8283120 --- /dev/null +++ b/vendor/symfony/mime/Encoder/EightBitContentEncoder.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Fabien Potencier + */ +final class EightBitContentEncoder implements ContentEncoderInterface +{ + public function encodeByteStream($stream, int $maxLineLength = 0): iterable + { + while (!feof($stream)) { + yield fread($stream, 16372); + } + } + + public function getName(): string + { + return '8bit'; + } + + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + return $string; + } +} diff --git a/vendor/symfony/mime/Encoder/EncoderInterface.php b/vendor/symfony/mime/Encoder/EncoderInterface.php new file mode 100644 index 0000000..bbf6d48 --- /dev/null +++ b/vendor/symfony/mime/Encoder/EncoderInterface.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Chris Corbyn + */ +interface EncoderInterface +{ + /** + * Encode a given string to produce an encoded string. + * + * @param int $firstLineOffset if first line needs to be shorter + * @param int $maxLineLength - 0 indicates the default length for this encoding + */ + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string; +} diff --git a/vendor/symfony/mime/Encoder/IdnAddressEncoder.php b/vendor/symfony/mime/Encoder/IdnAddressEncoder.php new file mode 100644 index 0000000..1c5e32c --- /dev/null +++ b/vendor/symfony/mime/Encoder/IdnAddressEncoder.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +use Symfony\Component\Mime\Exception\AddressEncoderException; + +/** + * An IDN email address encoder. + * + * Encodes the domain part of an address using IDN. This is compatible will all + * SMTP servers. + * + * This encoder does not support email addresses with non-ASCII characters in + * local-part (the substring before @). To send to such addresses, use + * Utf8AddressEncoder together with SmtpUtf8Handler. Your outbound SMTP server must support + * the SMTPUTF8 extension. + * + * @author Christian Schmidt + */ +final class IdnAddressEncoder implements AddressEncoderInterface +{ + /** + * Encodes the domain part of an address using IDN. + * + * @throws AddressEncoderException If local-part contains non-ASCII characters + */ + public function encodeString(string $address): string + { + $i = strrpos($address, '@'); + if (false !== $i) { + $local = substr($address, 0, $i); + $domain = substr($address, $i + 1); + + if (preg_match('/[^\x00-\x7F]/', $local)) { + throw new AddressEncoderException(sprintf('Non-ASCII characters not supported in local-part os "%s".', $address)); + } + + if (preg_match('/[^\x00-\x7F]/', $domain)) { + $address = sprintf('%s@%s', $local, idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46)); + } + } + + return $address; + } +} diff --git a/vendor/symfony/mime/Encoder/MimeHeaderEncoderInterface.php b/vendor/symfony/mime/Encoder/MimeHeaderEncoderInterface.php new file mode 100644 index 0000000..fff2c78 --- /dev/null +++ b/vendor/symfony/mime/Encoder/MimeHeaderEncoderInterface.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Chris Corbyn + */ +interface MimeHeaderEncoderInterface +{ + /** + * Get the MIME name of this content encoding scheme. + */ + public function getName(): string; +} diff --git a/vendor/symfony/mime/Encoder/QpContentEncoder.php b/vendor/symfony/mime/Encoder/QpContentEncoder.php new file mode 100644 index 0000000..e0b8605 --- /dev/null +++ b/vendor/symfony/mime/Encoder/QpContentEncoder.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Lars Strojny + */ +final class QpContentEncoder implements ContentEncoderInterface +{ + public function encodeByteStream($stream, int $maxLineLength = 0): iterable + { + if (!\is_resource($stream)) { + throw new \TypeError(sprintf('Method "%s" takes a stream as a first argument.', __METHOD__)); + } + + // we don't use PHP stream filters here as the content should be small enough + if (stream_get_meta_data($stream)['seekable'] ?? false) { + rewind($stream); + } + + yield $this->encodeString(stream_get_contents($stream), 'utf-8', 0, $maxLineLength); + } + + public function getName(): string + { + return 'quoted-printable'; + } + + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + return $this->standardize(quoted_printable_encode($string)); + } + + /** + * Make sure CRLF is correct and HT/SPACE are in valid places. + */ + private function standardize(string $string): string + { + // transform CR or LF to CRLF + $string = preg_replace('~=0D(?!=0A)|(? + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +use Symfony\Component\Mime\CharacterStream; + +/** + * @author Chris Corbyn + */ +class QpEncoder implements EncoderInterface +{ + /** + * Pre-computed QP for HUGE optimization. + */ + private static $qpMap = [ + 0 => '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04', + 5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09', + 10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E', + 15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13', + 20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18', + 25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D', + 30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22', + 35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27', + 40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C', + 45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31', + 50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36', + 55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B', + 60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40', + 65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45', + 70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A', + 75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F', + 80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54', + 85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59', + 90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E', + 95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63', + 100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68', + 105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D', + 110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72', + 115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77', + 120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C', + 125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81', + 130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86', + 135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B', + 140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90', + 145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95', + 150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A', + 155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F', + 160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4', + 165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9', + 170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE', + 175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3', + 180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8', + 185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD', + 190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2', + 195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7', + 200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC', + 205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1', + 210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6', + 215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB', + 220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0', + 225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5', + 230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA', + 235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF', + 240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4', + 245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9', + 250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE', + 255 => '=FF', + ]; + + private static $safeMapShare = []; + + /** + * A map of non-encoded ascii characters. + * + * @var string[] + * + * @internal + */ + protected $safeMap = []; + + public function __construct() + { + $id = \get_class($this); + if (!isset(self::$safeMapShare[$id])) { + $this->initSafeMap(); + self::$safeMapShare[$id] = $this->safeMap; + } else { + $this->safeMap = self::$safeMapShare[$id]; + } + } + + protected function initSafeMap(): void + { + foreach (array_merge([0x09, 0x20], range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte) { + $this->safeMap[$byte] = \chr($byte); + } + } + + /** + * {@inheritdoc} + * + * Takes an unencoded string and produces a QP encoded string from it. + * + * QP encoded strings have a maximum line length of 76 characters. + * If the first line needs to be shorter, indicate the difference with + * $firstLineOffset. + */ + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + if ($maxLineLength > 76 || $maxLineLength <= 0) { + $maxLineLength = 76; + } + + $thisLineLength = $maxLineLength - $firstLineOffset; + + $lines = []; + $lNo = 0; + $lines[$lNo] = ''; + $currentLine = &$lines[$lNo++]; + $size = $lineLen = 0; + $charStream = new CharacterStream($string, $charset); + + // Fetching more than 4 chars at one is slower, as is fetching fewer bytes + // Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6 + // bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes + while (null !== $bytes = $charStream->readBytes(4)) { + $enc = $this->encodeByteSequence($bytes, $size); + + $i = strpos($enc, '=0D=0A'); + $newLineLength = $lineLen + (false === $i ? $size : $i); + + if ($currentLine && $newLineLength >= $thisLineLength) { + $lines[$lNo] = ''; + $currentLine = &$lines[$lNo++]; + $thisLineLength = $maxLineLength; + $lineLen = 0; + } + + $currentLine .= $enc; + + if (false === $i) { + $lineLen += $size; + } else { + // 6 is the length of '=0D=0A'. + $lineLen = $size - strrpos($enc, '=0D=0A') - 6; + } + } + + return $this->standardize(implode("=\r\n", $lines)); + } + + /** + * Encode the given byte array into a verbatim QP form. + */ + private function encodeByteSequence(array $bytes, int &$size): string + { + $ret = ''; + $size = 0; + foreach ($bytes as $b) { + if (isset($this->safeMap[$b])) { + $ret .= $this->safeMap[$b]; + ++$size; + } else { + $ret .= self::$qpMap[$b]; + $size += 3; + } + } + + return $ret; + } + + /** + * Make sure CRLF is correct and HT/SPACE are in valid places. + */ + private function standardize(string $string): string + { + $string = str_replace(["\t=0D=0A", ' =0D=0A', '=0D=0A'], ["=09\r\n", "=20\r\n", "\r\n"], $string); + switch ($end = \ord(substr($string, -1))) { + case 0x09: + case 0x20: + $string = substr_replace($string, self::$qpMap[$end], -1); + } + + return $string; + } +} diff --git a/vendor/symfony/mime/Encoder/QpMimeHeaderEncoder.php b/vendor/symfony/mime/Encoder/QpMimeHeaderEncoder.php new file mode 100644 index 0000000..d1d3837 --- /dev/null +++ b/vendor/symfony/mime/Encoder/QpMimeHeaderEncoder.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Chris Corbyn + */ +final class QpMimeHeaderEncoder extends QpEncoder implements MimeHeaderEncoderInterface +{ + protected function initSafeMap(): void + { + foreach (array_merge( + range(0x61, 0x7A), range(0x41, 0x5A), + range(0x30, 0x39), [0x20, 0x21, 0x2A, 0x2B, 0x2D, 0x2F] + ) as $byte) { + $this->safeMap[$byte] = \chr($byte); + } + } + + public function getName(): string + { + return 'Q'; + } + + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + return str_replace([' ', '=20', "=\r\n"], ['_', '_', "\r\n"], + parent::encodeString($string, $charset, $firstLineOffset, $maxLineLength) + ); + } +} diff --git a/vendor/symfony/mime/Encoder/Rfc2231Encoder.php b/vendor/symfony/mime/Encoder/Rfc2231Encoder.php new file mode 100644 index 0000000..aa3e062 --- /dev/null +++ b/vendor/symfony/mime/Encoder/Rfc2231Encoder.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +use Symfony\Component\Mime\CharacterStream; + +/** + * @author Chris Corbyn + */ +final class Rfc2231Encoder implements EncoderInterface +{ + /** + * Takes an unencoded string and produces a string encoded according to RFC 2231 from it. + */ + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + $lines = []; + $lineCount = 0; + $lines[] = ''; + $currentLine = &$lines[$lineCount++]; + + if (0 >= $maxLineLength) { + $maxLineLength = 75; + } + + $charStream = new CharacterStream($string, $charset); + $thisLineLength = $maxLineLength - $firstLineOffset; + + while (null !== $char = $charStream->read(4)) { + $encodedChar = rawurlencode($char); + if (0 !== \strlen($currentLine) && \strlen($currentLine.$encodedChar) > $thisLineLength) { + $lines[] = ''; + $currentLine = &$lines[$lineCount++]; + $thisLineLength = $maxLineLength; + } + $currentLine .= $encodedChar; + } + + return implode("\r\n", $lines); + } +} diff --git a/vendor/symfony/mime/Exception/AddressEncoderException.php b/vendor/symfony/mime/Exception/AddressEncoderException.php new file mode 100644 index 0000000..51ee2e0 --- /dev/null +++ b/vendor/symfony/mime/Exception/AddressEncoderException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Exception; + +/** + * @author Fabien Potencier + */ +class AddressEncoderException extends RfcComplianceException +{ +} diff --git a/vendor/symfony/mime/Exception/ExceptionInterface.php b/vendor/symfony/mime/Exception/ExceptionInterface.php new file mode 100644 index 0000000..1193390 --- /dev/null +++ b/vendor/symfony/mime/Exception/ExceptionInterface.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Exception; + +/** + * @author Fabien Potencier + */ +interface ExceptionInterface extends \Throwable +{ +} diff --git a/vendor/symfony/mime/Exception/InvalidArgumentException.php b/vendor/symfony/mime/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..e89ebae --- /dev/null +++ b/vendor/symfony/mime/Exception/InvalidArgumentException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Exception; + +/** + * @author Fabien Potencier + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/mime/Exception/LogicException.php b/vendor/symfony/mime/Exception/LogicException.php new file mode 100644 index 0000000..0508ee7 --- /dev/null +++ b/vendor/symfony/mime/Exception/LogicException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Exception; + +/** + * @author Fabien Potencier + */ +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/mime/Exception/RfcComplianceException.php b/vendor/symfony/mime/Exception/RfcComplianceException.php new file mode 100644 index 0000000..26e4a50 --- /dev/null +++ b/vendor/symfony/mime/Exception/RfcComplianceException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Exception; + +/** + * @author Fabien Potencier + */ +class RfcComplianceException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/mime/Exception/RuntimeException.php b/vendor/symfony/mime/Exception/RuntimeException.php new file mode 100644 index 0000000..fb018b0 --- /dev/null +++ b/vendor/symfony/mime/Exception/RuntimeException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Exception; + +/** + * @author Fabien Potencier + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php b/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php new file mode 100644 index 0000000..fe1e0cd --- /dev/null +++ b/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Symfony\Component\Mime\Exception\InvalidArgumentException; +use Symfony\Component\Mime\Exception\LogicException; + +/** + * Guesses the MIME type with the binary "file" (only available on *nix). + * + * @author Bernhard Schussek + */ +class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface +{ + private $cmd; + + /** + * The $cmd pattern must contain a "%s" string that will be replaced + * with the file name to guess. + * + * The command output must start with the MIME type of the file. + * + * @param string $cmd The command to run to get the MIME type of a file + */ + public function __construct(string $cmd = 'file -b --mime -- %s 2>/dev/null') + { + $this->cmd = $cmd; + } + + /** + * {@inheritdoc} + */ + public function isGuesserSupported(): bool + { + static $supported = null; + + if (null !== $supported) { + return $supported; + } + + if ('\\' === \DIRECTORY_SEPARATOR || !\function_exists('passthru') || !\function_exists('escapeshellarg')) { + return $supported = false; + } + + ob_start(); + passthru('command -v file', $exitStatus); + $binPath = trim(ob_get_clean()); + + return $supported = 0 === $exitStatus && '' !== $binPath; + } + + /** + * {@inheritdoc} + */ + public function guessMimeType(string $path): ?string + { + if (!is_file($path) || !is_readable($path)) { + throw new InvalidArgumentException(sprintf('The "%s" file does not exist or is not readable.', $path)); + } + + if (!$this->isGuesserSupported()) { + throw new LogicException(sprintf('The "%s" guesser is not supported.', __CLASS__)); + } + + ob_start(); + + // need to use --mime instead of -i. see #6641 + passthru(sprintf($this->cmd, escapeshellarg((0 === strpos($path, '-') ? './' : '').$path)), $return); + if ($return > 0) { + ob_end_clean(); + + return null; + } + + $type = trim(ob_get_clean()); + + if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\+\.]+)#i', $type, $match)) { + // it's not a type, but an error message + return null; + } + + return $match[1]; + } +} diff --git a/vendor/symfony/mime/FileinfoMimeTypeGuesser.php b/vendor/symfony/mime/FileinfoMimeTypeGuesser.php new file mode 100644 index 0000000..b91a4ff --- /dev/null +++ b/vendor/symfony/mime/FileinfoMimeTypeGuesser.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Symfony\Component\Mime\Exception\InvalidArgumentException; +use Symfony\Component\Mime\Exception\LogicException; + +/** + * Guesses the MIME type using the PECL extension FileInfo. + * + * @author Bernhard Schussek + */ +class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface +{ + private $magicFile; + + /** + * @param string $magicFile A magic file to use with the finfo instance + * + * @see http://www.php.net/manual/en/function.finfo-open.php + */ + public function __construct(string $magicFile = null) + { + $this->magicFile = $magicFile; + } + + /** + * {@inheritdoc} + */ + public function isGuesserSupported(): bool + { + return \function_exists('finfo_open'); + } + + /** + * {@inheritdoc} + */ + public function guessMimeType(string $path): ?string + { + if (!is_file($path) || !is_readable($path)) { + throw new InvalidArgumentException(sprintf('The "%s" file does not exist or is not readable.', $path)); + } + + if (!$this->isGuesserSupported()) { + throw new LogicException(sprintf('The "%s" guesser is not supported.', __CLASS__)); + } + + if (false === $finfo = new \finfo(FILEINFO_MIME_TYPE, $this->magicFile)) { + return null; + } + + return $finfo->file($path); + } +} diff --git a/vendor/symfony/mime/Header/AbstractHeader.php b/vendor/symfony/mime/Header/AbstractHeader.php new file mode 100644 index 0000000..548c192 --- /dev/null +++ b/vendor/symfony/mime/Header/AbstractHeader.php @@ -0,0 +1,279 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Encoder\QpMimeHeaderEncoder; + +/** + * An abstract base MIME Header. + * + * @author Chris Corbyn + */ +abstract class AbstractHeader implements HeaderInterface +{ + const PHRASE_PATTERN = '(?:(?:(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]+(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?)|(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?"((?:(?:[ \t]*(?:\r\n))?[ \t])?(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])))*(?:(?:[ \t]*(?:\r\n))?[ \t])?"(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?))+?)'; + + private static $encoder; + + private $name; + private $lineLength = 76; + private $lang; + private $charset = 'utf-8'; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function setCharset(string $charset) + { + $this->charset = $charset; + } + + public function getCharset(): ?string + { + return $this->charset; + } + + /** + * Set the language used in this Header. + * + * For example, for US English, 'en-us'. + */ + public function setLanguage(string $lang) + { + $this->lang = $lang; + } + + public function getLanguage(): ?string + { + return $this->lang; + } + + public function getName(): string + { + return $this->name; + } + + public function setMaxLineLength(int $lineLength) + { + $this->lineLength = $lineLength; + } + + public function getMaxLineLength(): int + { + return $this->lineLength; + } + + public function toString(): string + { + return $this->tokensToString($this->toTokens()); + } + + /** + * Produces a compliant, formatted RFC 2822 'phrase' based on the string given. + * + * @param string $string as displayed + * @param bool $shorten the first line to make remove for header name + */ + protected function createPhrase(HeaderInterface $header, string $string, string $charset, bool $shorten = false): string + { + // Treat token as exactly what was given + $phraseStr = $string; + + // If it's not valid + if (!preg_match('/^'.self::PHRASE_PATTERN.'$/D', $phraseStr)) { + // .. but it is just ascii text, try escaping some characters + // and make it a quoted-string + if (preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $phraseStr)) { + foreach (['\\', '"'] as $char) { + $phraseStr = str_replace($char, '\\'.$char, $phraseStr); + } + $phraseStr = '"'.$phraseStr.'"'; + } else { + // ... otherwise it needs encoding + // Determine space remaining on line if first line + if ($shorten) { + $usedLength = \strlen($header->getName().': '); + } else { + $usedLength = 0; + } + $phraseStr = $this->encodeWords($header, $string, $usedLength); + } + } + + return $phraseStr; + } + + /** + * Encode needed word tokens within a string of input. + */ + protected function encodeWords(HeaderInterface $header, string $input, int $usedLength = -1): string + { + $value = ''; + $tokens = $this->getEncodableWordTokens($input); + foreach ($tokens as $token) { + // See RFC 2822, Sect 2.2 (really 2.2 ??) + if ($this->tokenNeedsEncoding($token)) { + // Don't encode starting WSP + $firstChar = substr($token, 0, 1); + switch ($firstChar) { + case ' ': + case "\t": + $value .= $firstChar; + $token = substr($token, 1); + } + + if (-1 == $usedLength) { + $usedLength = \strlen($header->getName().': ') + \strlen($value); + } + $value .= $this->getTokenAsEncodedWord($token, $usedLength); + } else { + $value .= $token; + } + } + + return $value; + } + + protected function tokenNeedsEncoding(string $token): bool + { + return (bool) preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token); + } + + /** + * Splits a string into tokens in blocks of words which can be encoded quickly. + * + * @return string[] + */ + protected function getEncodableWordTokens(string $string): array + { + $tokens = []; + $encodedToken = ''; + // Split at all whitespace boundaries + foreach (preg_split('~(?=[\t ])~', $string) as $token) { + if ($this->tokenNeedsEncoding($token)) { + $encodedToken .= $token; + } else { + if (\strlen($encodedToken) > 0) { + $tokens[] = $encodedToken; + $encodedToken = ''; + } + $tokens[] = $token; + } + } + if (\strlen($encodedToken)) { + $tokens[] = $encodedToken; + } + + return $tokens; + } + + /** + * Get a token as an encoded word for safe insertion into headers. + */ + protected function getTokenAsEncodedWord(string $token, int $firstLineOffset = 0): string + { + if (null === self::$encoder) { + self::$encoder = new QpMimeHeaderEncoder(); + } + + // Adjust $firstLineOffset to account for space needed for syntax + $charsetDecl = $this->charset; + if (null !== $this->lang) { + $charsetDecl .= '*'.$this->lang; + } + $encodingWrapperLength = \strlen('=?'.$charsetDecl.'?'.self::$encoder->getName().'??='); + + if ($firstLineOffset >= 75) { + //Does this logic need to be here? + $firstLineOffset = 0; + } + + $encodedTextLines = explode("\r\n", + self::$encoder->encodeString($token, $this->charset, $firstLineOffset, 75 - $encodingWrapperLength) + ); + + if ('iso-2022-jp' !== strtolower($this->charset)) { + // special encoding for iso-2022-jp using mb_encode_mimeheader + foreach ($encodedTextLines as $lineNum => $line) { + $encodedTextLines[$lineNum] = '=?'.$charsetDecl.'?'.self::$encoder->getName().'?'.$line.'?='; + } + } + + return implode("\r\n ", $encodedTextLines); + } + + /** + * Generates tokens from the given string which include CRLF as individual tokens. + * + * @return string[] + */ + protected function generateTokenLines(string $token): array + { + return preg_split('~(\r\n)~', $token, -1, PREG_SPLIT_DELIM_CAPTURE); + } + + /** + * Generate a list of all tokens in the final header. + */ + protected function toTokens(string $string = null): array + { + if (null === $string) { + $string = $this->getBodyAsString(); + } + + $tokens = []; + // Generate atoms; split at all invisible boundaries followed by WSP + foreach (preg_split('~(?=[ \t])~', $string) as $token) { + $newTokens = $this->generateTokenLines($token); + foreach ($newTokens as $newToken) { + $tokens[] = $newToken; + } + } + + return $tokens; + } + + /** + * Takes an array of tokens which appear in the header and turns them into + * an RFC 2822 compliant string, adding FWSP where needed. + * + * @param string[] $tokens + */ + private function tokensToString(array $tokens): string + { + $lineCount = 0; + $headerLines = []; + $headerLines[] = $this->name.': '; + $currentLine = &$headerLines[$lineCount++]; + + // Build all tokens back into compliant header + foreach ($tokens as $i => $token) { + // Line longer than specified maximum or token was just a new line + if (("\r\n" === $token) || + ($i > 0 && \strlen($currentLine.$token) > $this->lineLength) + && 0 < \strlen($currentLine)) { + $headerLines[] = ''; + $currentLine = &$headerLines[$lineCount++]; + } + + // Append token to the line + if ("\r\n" !== $token) { + $currentLine .= $token; + } + } + + // Implode with FWS (RFC 2822, 2.2.3) + return implode("\r\n", $headerLines); + } +} diff --git a/vendor/symfony/mime/Header/DateHeader.php b/vendor/symfony/mime/Header/DateHeader.php new file mode 100644 index 0000000..a7385d4 --- /dev/null +++ b/vendor/symfony/mime/Header/DateHeader.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +/** + * A Date MIME Header. + * + * @author Chris Corbyn + */ +final class DateHeader extends AbstractHeader +{ + private $dateTime; + + public function __construct(string $name, \DateTimeInterface $date) + { + parent::__construct($name); + + $this->setDateTime($date); + } + + /** + * @param \DateTimeInterface $body + */ + public function setBody($body) + { + $this->setDateTime($body); + } + + public function getBody(): \DateTimeImmutable + { + return $this->getDateTime(); + } + + public function getDateTime(): \DateTimeImmutable + { + return $this->dateTime; + } + + /** + * Set the date-time of the Date in this Header. + * + * If a DateTime instance is provided, it is converted to DateTimeImmutable. + */ + public function setDateTime(\DateTimeInterface $dateTime) + { + if ($dateTime instanceof \DateTime) { + $immutable = new \DateTimeImmutable('@'.$dateTime->getTimestamp()); + $dateTime = $immutable->setTimezone($dateTime->getTimezone()); + } + $this->dateTime = $dateTime; + } + + public function getBodyAsString(): string + { + return $this->dateTime->format(\DateTime::RFC2822); + } +} diff --git a/vendor/symfony/mime/Header/HeaderInterface.php b/vendor/symfony/mime/Header/HeaderInterface.php new file mode 100644 index 0000000..4546947 --- /dev/null +++ b/vendor/symfony/mime/Header/HeaderInterface.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +/** + * A MIME Header. + * + * @author Chris Corbyn + */ +interface HeaderInterface +{ + /** + * Sets the body. + * + * The type depends on the Header concrete class. + * + * @param mixed $body + */ + public function setBody($body); + + /** + * Gets the body. + * + * The return type depends on the Header concrete class. + * + * @return mixed + */ + public function getBody(); + + public function setCharset(string $charset); + + public function getCharset(): ?string; + + public function setLanguage(string $lang); + + public function getLanguage(): ?string; + + public function getName(): string; + + public function setMaxLineLength(int $lineLength); + + public function getMaxLineLength(): int; + + /** + * Gets this Header rendered as a compliant string. + */ + public function toString(): string; + + /** + * Gets the header's body, prepared for folding into a final header value. + * + * This is not necessarily RFC 2822 compliant since folding white space is + * not added at this stage (see {@link toString()} for that). + */ + public function getBodyAsString(): string; +} diff --git a/vendor/symfony/mime/Header/Headers.php b/vendor/symfony/mime/Header/Headers.php new file mode 100644 index 0000000..9de506e --- /dev/null +++ b/vendor/symfony/mime/Header/Headers.php @@ -0,0 +1,282 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Exception\LogicException; + +/** + * A collection of headers. + * + * @author Fabien Potencier + */ +final class Headers +{ + private static $uniqueHeaders = [ + 'date', 'from', 'sender', 'reply-to', 'to', 'cc', 'bcc', + 'message-id', 'in-reply-to', 'references', 'subject', + ]; + + private $headers = []; + private $lineLength = 76; + + public function __construct(HeaderInterface ...$headers) + { + foreach ($headers as $header) { + $this->add($header); + } + } + + public function __clone() + { + foreach ($this->headers as $name => $collection) { + foreach ($collection as $i => $header) { + $this->headers[$name][$i] = clone $header; + } + } + } + + public function setMaxLineLength(int $lineLength) + { + $this->lineLength = $lineLength; + foreach ($this->all() as $header) { + $header->setMaxLineLength($lineLength); + } + } + + public function getMaxLineLength(): int + { + return $this->lineLength; + } + + /** + * @param (Address|string)[] $addresses + * + * @return $this + */ + public function addMailboxListHeader(string $name, array $addresses): self + { + return $this->add(new MailboxListHeader($name, Address::createArray($addresses))); + } + + /** + * @param Address|string $address + * + * @return $this + */ + public function addMailboxHeader(string $name, $address): self + { + return $this->add(new MailboxHeader($name, Address::create($address))); + } + + /** + * @param string|array $ids + * + * @return $this + */ + public function addIdHeader(string $name, $ids): self + { + return $this->add(new IdentificationHeader($name, $ids)); + } + + /** + * @param Address|string $path + * + * @return $this + */ + public function addPathHeader(string $name, $path): self + { + return $this->add(new PathHeader($name, $path instanceof Address ? $path : new Address($path))); + } + + /** + * @return $this + */ + public function addDateHeader(string $name, \DateTimeInterface $dateTime): self + { + return $this->add(new DateHeader($name, $dateTime)); + } + + /** + * @return $this + */ + public function addTextHeader(string $name, string $value): self + { + return $this->add(new UnstructuredHeader($name, $value)); + } + + /** + * @return $this + */ + public function addParameterizedHeader(string $name, string $value, array $params = []): self + { + return $this->add(new ParameterizedHeader($name, $value, $params)); + } + + public function has(string $name): bool + { + return isset($this->headers[strtolower($name)]); + } + + /** + * @return $this + */ + public function add(HeaderInterface $header): self + { + static $map = [ + 'date' => DateHeader::class, + 'from' => MailboxListHeader::class, + 'sender' => MailboxHeader::class, + 'reply-to' => MailboxListHeader::class, + 'to' => MailboxListHeader::class, + 'cc' => MailboxListHeader::class, + 'bcc' => MailboxListHeader::class, + 'message-id' => IdentificationHeader::class, + 'in-reply-to' => IdentificationHeader::class, + 'references' => IdentificationHeader::class, + 'return-path' => PathHeader::class, + ]; + + $header->setMaxLineLength($this->lineLength); + $name = strtolower($header->getName()); + + if (isset($map[$name]) && !$header instanceof $map[$name]) { + throw new LogicException(sprintf('The "%s" header must be an instance of "%s" (got "%s").', $header->getName(), $map[$name], \get_class($header))); + } + + if (\in_array($name, self::$uniqueHeaders, true) && isset($this->headers[$name]) && \count($this->headers[$name]) > 0) { + throw new LogicException(sprintf('Impossible to set header "%s" as it\'s already defined and must be unique.', $header->getName())); + } + + $this->headers[$name][] = $header; + + return $this; + } + + public function get(string $name): ?HeaderInterface + { + $name = strtolower($name); + if (!isset($this->headers[$name])) { + return null; + } + + $values = array_values($this->headers[$name]); + + return array_shift($values); + } + + public function all(string $name = null): iterable + { + if (null === $name) { + foreach ($this->headers as $name => $collection) { + foreach ($collection as $header) { + yield $name => $header; + } + } + } elseif (isset($this->headers[strtolower($name)])) { + foreach ($this->headers[strtolower($name)] as $header) { + yield $header; + } + } + } + + public function getNames(): array + { + return array_keys($this->headers); + } + + public function remove(string $name): void + { + unset($this->headers[strtolower($name)]); + } + + public static function isUniqueHeader(string $name): bool + { + return \in_array($name, self::$uniqueHeaders, true); + } + + public function toString(): string + { + $string = ''; + foreach ($this->toArray() as $str) { + $string .= $str."\r\n"; + } + + return $string; + } + + public function toArray(): array + { + $arr = []; + foreach ($this->all() as $header) { + if ('' !== $header->getBodyAsString()) { + $arr[] = $header->toString(); + } + } + + return $arr; + } + + /** + * @internal + */ + public function getHeaderBody($name) + { + return $this->has($name) ? $this->get($name)->getBody() : null; + } + + /** + * @internal + */ + public function setHeaderBody(string $type, string $name, $body): void + { + if ($this->has($name)) { + $this->get($name)->setBody($body); + } else { + $this->{'add'.$type.'Header'}($name, $body); + } + } + + /** + * @internal + */ + public function getHeaderParameter(string $name, string $parameter): ?string + { + if (!$this->has($name)) { + return null; + } + + $header = $this->get($name); + if (!$header instanceof ParameterizedHeader) { + throw new LogicException(sprintf('Unable to get parameter "%s" on header "%s" as the header is not of class "%s".', $parameter, $name, ParameterizedHeader::class)); + } + + return $header->getParameter($parameter); + } + + /** + * @internal + */ + public function setHeaderParameter(string $name, string $parameter, $value): void + { + if (!$this->has($name)) { + throw new LogicException(sprintf('Unable to set parameter "%s" on header "%s" as the header is not defined.', $parameter, $name)); + } + + $header = $this->get($name); + if (!$header instanceof ParameterizedHeader) { + throw new LogicException(sprintf('Unable to set parameter "%s" on header "%s" as the header is not of class "%s".', $parameter, $name, ParameterizedHeader::class)); + } + + $header->setParameter($parameter, $value); + } +} diff --git a/vendor/symfony/mime/Header/IdentificationHeader.php b/vendor/symfony/mime/Header/IdentificationHeader.php new file mode 100644 index 0000000..8a94574 --- /dev/null +++ b/vendor/symfony/mime/Header/IdentificationHeader.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Exception\RfcComplianceException; + +/** + * An ID MIME Header for something like Message-ID or Content-ID (one or more addresses). + * + * @author Chris Corbyn + */ +final class IdentificationHeader extends AbstractHeader +{ + private $ids = []; + private $idsAsAddresses = []; + + /** + * @param string|array $ids + */ + public function __construct(string $name, $ids) + { + parent::__construct($name); + + $this->setId($ids); + } + + /** + * @param string|array $body a string ID or an array of IDs + * + * @throws RfcComplianceException + */ + public function setBody($body) + { + $this->setId($body); + } + + public function getBody(): array + { + return $this->getIds(); + } + + /** + * Set the ID used in the value of this header. + * + * @param string|array $id + * + * @throws RfcComplianceException + */ + public function setId($id) + { + $this->setIds(\is_array($id) ? $id : [$id]); + } + + /** + * Get the ID used in the value of this Header. + * + * If multiple IDs are set only the first is returned. + */ + public function getId(): ?string + { + return $this->ids[0] ?? null; + } + + /** + * Set a collection of IDs to use in the value of this Header. + * + * @param string[] $ids + * + * @throws RfcComplianceException + */ + public function setIds(array $ids) + { + $this->ids = []; + $this->idsAsAddresses = []; + foreach ($ids as $id) { + $this->idsAsAddresses[] = new Address($id); + $this->ids[] = $id; + } + } + + /** + * Get the list of IDs used in this Header. + * + * @return string[] + */ + public function getIds(): array + { + return $this->ids; + } + + public function getBodyAsString(): string + { + $addrs = []; + foreach ($this->idsAsAddresses as $address) { + $addrs[] = '<'.$address->toString().'>'; + } + + return implode(' ', $addrs); + } +} diff --git a/vendor/symfony/mime/Header/MailboxHeader.php b/vendor/symfony/mime/Header/MailboxHeader.php new file mode 100644 index 0000000..b58c825 --- /dev/null +++ b/vendor/symfony/mime/Header/MailboxHeader.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Exception\RfcComplianceException; + +/** + * A Mailbox MIME Header for something like Sender (one named address). + * + * @author Fabien Potencier + */ +final class MailboxHeader extends AbstractHeader +{ + private $address; + + public function __construct(string $name, Address $address) + { + parent::__construct($name); + + $this->setAddress($address); + } + + /** + * @param Address $body + * + * @throws RfcComplianceException + */ + public function setBody($body) + { + $this->setAddress($body); + } + + /** + * @throws RfcComplianceException + */ + public function getBody(): Address + { + return $this->getAddress(); + } + + /** + * @throws RfcComplianceException + */ + public function setAddress(Address $address) + { + $this->address = $address; + } + + public function getAddress(): Address + { + return $this->address; + } + + public function getBodyAsString(): string + { + $str = $this->address->getEncodedAddress(); + if ($name = $this->address->getName()) { + $str = $this->createPhrase($this, $name, $this->getCharset(), true).' <'.$str.'>'; + } + + return $str; + } + + /** + * Redefine the encoding requirements for an address. + * + * All "specials" must be encoded as the full header value will not be quoted + * + * @see RFC 2822 3.2.1 + */ + protected function tokenNeedsEncoding(string $token): bool + { + return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token); + } +} diff --git a/vendor/symfony/mime/Header/MailboxListHeader.php b/vendor/symfony/mime/Header/MailboxListHeader.php new file mode 100644 index 0000000..1d00fdb --- /dev/null +++ b/vendor/symfony/mime/Header/MailboxListHeader.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Exception\RfcComplianceException; + +/** + * A Mailbox list MIME Header for something like From, To, Cc, and Bcc (one or more named addresses). + * + * @author Chris Corbyn + */ +final class MailboxListHeader extends AbstractHeader +{ + private $addresses = []; + + /** + * @param Address[] $addresses + */ + public function __construct(string $name, array $addresses) + { + parent::__construct($name); + + $this->setAddresses($addresses); + } + + /** + * @param Address[] $body + * + * @throws RfcComplianceException + */ + public function setBody($body) + { + $this->setAddresses($body); + } + + /** + * @throws RfcComplianceException + * + * @return Address[] + */ + public function getBody(): array + { + return $this->getAddresses(); + } + + /** + * Sets a list of addresses to be shown in this Header. + * + * @param Address[] $addresses + * + * @throws RfcComplianceException + */ + public function setAddresses(array $addresses) + { + $this->addresses = []; + $this->addAddresses($addresses); + } + + /** + * Sets a list of addresses to be shown in this Header. + * + * @param Address[] $addresses + * + * @throws RfcComplianceException + */ + public function addAddresses(array $addresses) + { + foreach ($addresses as $address) { + $this->addAddress($address); + } + } + + /** + * @throws RfcComplianceException + */ + public function addAddress(Address $address) + { + $this->addresses[] = $address; + } + + /** + * @return Address[] + */ + public function getAddresses(): array + { + return $this->addresses; + } + + /** + * Gets the full mailbox list of this Header as an array of valid RFC 2822 strings. + * + * @throws RfcComplianceException + * + * @return string[] + */ + public function getAddressStrings(): array + { + $strings = []; + foreach ($this->addresses as $address) { + $str = $address->getEncodedAddress(); + if ($name = $address->getName()) { + $str = $this->createPhrase($this, $name, $this->getCharset(), !$strings).' <'.$str.'>'; + } + $strings[] = $str; + } + + return $strings; + } + + public function getBodyAsString(): string + { + return implode(', ', $this->getAddressStrings()); + } + + /** + * Redefine the encoding requirements for addresses. + * + * All "specials" must be encoded as the full header value will not be quoted + * + * @see RFC 2822 3.2.1 + */ + protected function tokenNeedsEncoding(string $token): bool + { + return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token); + } +} diff --git a/vendor/symfony/mime/Header/ParameterizedHeader.php b/vendor/symfony/mime/Header/ParameterizedHeader.php new file mode 100644 index 0000000..d8e5001 --- /dev/null +++ b/vendor/symfony/mime/Header/ParameterizedHeader.php @@ -0,0 +1,174 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Encoder\Rfc2231Encoder; + +/** + * @author Chris Corbyn + */ +final class ParameterizedHeader extends UnstructuredHeader +{ + /** + * RFC 2231's definition of a token. + * + * @var string + */ + const TOKEN_REGEX = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)'; + + private $encoder; + private $parameters = []; + + public function __construct(string $name, string $value, array $parameters = []) + { + parent::__construct($name, $value); + + foreach ($parameters as $k => $v) { + $this->setParameter($k, $v); + } + + if ('content-type' !== strtolower($name)) { + $this->encoder = new Rfc2231Encoder(); + } + } + + public function setParameter(string $parameter, ?string $value) + { + $this->setParameters(array_merge($this->getParameters(), [$parameter => $value])); + } + + public function getParameter(string $parameter): string + { + return $this->getParameters()[$parameter] ?? ''; + } + + /** + * @param string[] $parameters + */ + public function setParameters(array $parameters) + { + $this->parameters = $parameters; + } + + /** + * @return string[] + */ + public function getParameters(): array + { + return $this->parameters; + } + + public function getBodyAsString(): string + { + $body = parent::getBodyAsString(); + foreach ($this->parameters as $name => $value) { + if (null !== $value) { + $body .= '; '.$this->createParameter($name, $value); + } + } + + return $body; + } + + /** + * Generate a list of all tokens in the final header. + * + * This doesn't need to be overridden in theory, but it is for implementation + * reasons to prevent potential breakage of attributes. + */ + protected function toTokens(string $string = null): array + { + $tokens = parent::toTokens(parent::getBodyAsString()); + + // Try creating any parameters + foreach ($this->parameters as $name => $value) { + if (null !== $value) { + // Add the semi-colon separator + $tokens[\count($tokens) - 1] .= ';'; + $tokens = array_merge($tokens, $this->generateTokenLines(' '.$this->createParameter($name, $value))); + } + } + + return $tokens; + } + + /** + * Render a RFC 2047 compliant header parameter from the $name and $value. + */ + private function createParameter(string $name, string $value): string + { + $origValue = $value; + + $encoded = false; + // Allow room for parameter name, indices, "=" and DQUOTEs + $maxValueLength = $this->getMaxLineLength() - \strlen($name.'=*N"";') - 1; + $firstLineOffset = 0; + + // If it's not already a valid parameter value... + if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { + // TODO: text, or something else?? + // ... and it's not ascii + if (!preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $value)) { + $encoded = true; + // Allow space for the indices, charset and language + $maxValueLength = $this->getMaxLineLength() - \strlen($name.'*N*="";') - 1; + $firstLineOffset = \strlen($this->getCharset()."'".$this->getLanguage()."'"); + } + } + + // Encode if we need to + if ($encoded || \strlen($value) > $maxValueLength) { + if (null !== $this->encoder) { + $value = $this->encoder->encodeString($origValue, $this->getCharset(), $firstLineOffset, $maxValueLength); + } else { + // We have to go against RFC 2183/2231 in some areas for interoperability + $value = $this->getTokenAsEncodedWord($origValue); + $encoded = false; + } + } + + $valueLines = $this->encoder ? explode("\r\n", $value) : [$value]; + + // Need to add indices + if (\count($valueLines) > 1) { + $paramLines = []; + foreach ($valueLines as $i => $line) { + $paramLines[] = $name.'*'.$i.$this->getEndOfParameterValue($line, true, 0 === $i); + } + + return implode(";\r\n ", $paramLines); + } else { + return $name.$this->getEndOfParameterValue($valueLines[0], $encoded, true); + } + } + + /** + * Returns the parameter value from the "=" and beyond. + * + * @param string $value to append + */ + private function getEndOfParameterValue(string $value, bool $encoded = false, bool $firstLine = false): string + { + if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { + $value = '"'.$value.'"'; + } + $prepend = '='; + if ($encoded) { + $prepend = '*='; + if ($firstLine) { + $prepend = '*='.$this->getCharset()."'".$this->getLanguage()."'"; + } + } + + return $prepend.$value; + } +} diff --git a/vendor/symfony/mime/Header/PathHeader.php b/vendor/symfony/mime/Header/PathHeader.php new file mode 100644 index 0000000..5101ad0 --- /dev/null +++ b/vendor/symfony/mime/Header/PathHeader.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Exception\RfcComplianceException; + +/** + * A Path Header, such a Return-Path (one address). + * + * @author Chris Corbyn + */ +final class PathHeader extends AbstractHeader +{ + private $address; + + public function __construct(string $name, Address $address) + { + parent::__construct($name); + + $this->setAddress($address); + } + + /** + * @param Address $body + * + * @throws RfcComplianceException + */ + public function setBody($body) + { + $this->setAddress($body); + } + + public function getBody(): Address + { + return $this->getAddress(); + } + + public function setAddress(Address $address) + { + $this->address = $address; + } + + public function getAddress(): Address + { + return $this->address; + } + + public function getBodyAsString(): string + { + return '<'.$this->address->toString().'>'; + } +} diff --git a/vendor/symfony/mime/Header/UnstructuredHeader.php b/vendor/symfony/mime/Header/UnstructuredHeader.php new file mode 100644 index 0000000..2085ddf --- /dev/null +++ b/vendor/symfony/mime/Header/UnstructuredHeader.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +/** + * A Simple MIME Header. + * + * @author Chris Corbyn + */ +class UnstructuredHeader extends AbstractHeader +{ + private $value; + + public function __construct(string $name, string $value) + { + parent::__construct($name); + + $this->setValue($value); + } + + /** + * @param string $body + */ + public function setBody($body) + { + $this->setValue($body); + } + + /** + * @return string + */ + public function getBody() + { + return $this->getValue(); + } + + /** + * Get the (unencoded) value of this header. + */ + public function getValue(): string + { + return $this->value; + } + + /** + * Set the (unencoded) value of this header. + */ + public function setValue(string $value) + { + $this->value = $value; + } + + /** + * Get the value of this header prepared for rendering. + */ + public function getBodyAsString(): string + { + return $this->encodeWords($this, $this->value); + } +} diff --git a/vendor/symfony/mime/LICENSE b/vendor/symfony/mime/LICENSE new file mode 100644 index 0000000..9a9a61b --- /dev/null +++ b/vendor/symfony/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/mime/Message.php b/vendor/symfony/mime/Message.php new file mode 100644 index 0000000..5b4e67f --- /dev/null +++ b/vendor/symfony/mime/Message.php @@ -0,0 +1,151 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Symfony\Component\Mime\Exception\LogicException; +use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\Part\AbstractPart; +use Symfony\Component\Mime\Part\TextPart; + +/** + * @author Fabien Potencier + */ +class Message extends RawMessage +{ + private $headers; + private $body; + + public function __construct(Headers $headers = null, AbstractPart $body = null) + { + $this->headers = $headers ? clone $headers : new Headers(); + $this->body = $body; + } + + public function __clone() + { + $this->headers = clone $this->headers; + + if (null !== $this->body) { + $this->body = clone $this->body; + } + } + + /** + * @return $this + */ + public function setBody(AbstractPart $body = null) + { + $this->body = $body; + + return $this; + } + + public function getBody(): ?AbstractPart + { + return $this->body; + } + + /** + * @return $this + */ + public function setHeaders(Headers $headers) + { + $this->headers = $headers; + + return $this; + } + + public function getHeaders(): Headers + { + return $this->headers; + } + + public function getPreparedHeaders(): Headers + { + $headers = clone $this->headers; + + if (!$headers->has('From')) { + throw new LogicException('An email must have a "From" header.'); + } + + $headers->addTextHeader('MIME-Version', '1.0'); + + if (!$headers->has('Date')) { + $headers->addDateHeader('Date', new \DateTimeImmutable()); + } + + // determine the "real" sender + if (!$headers->has('Sender') && \count($froms = $headers->get('From')->getAddresses()) > 1) { + $headers->addMailboxHeader('Sender', $froms[0]); + } + + if (!$headers->has('Message-ID')) { + $headers->addIdHeader('Message-ID', $this->generateMessageId()); + } + + // remove the Bcc field which should NOT be part of the sent message + $headers->remove('Bcc'); + + return $headers; + } + + public function toString(): string + { + if (null === $body = $this->getBody()) { + $body = new TextPart(''); + } + + return $this->getPreparedHeaders()->toString().$body->toString(); + } + + public function toIterable(): iterable + { + if (null === $body = $this->getBody()) { + $body = new TextPart(''); + } + + yield $this->getPreparedHeaders()->toString(); + yield from $body->toIterable(); + } + + public function ensureValidity() + { + if (!$this->headers->has('From')) { + throw new LogicException('An email must have a "From" header.'); + } + + parent::ensureValidity(); + } + + public function generateMessageId(): string + { + if ($this->headers->has('Sender')) { + $sender = $this->headers->get('Sender')->getAddress(); + } elseif ($this->headers->has('From')) { + $sender = $this->headers->get('From')->getAddresses()[0]; + } else { + throw new LogicException('An email must have a "From" or a "Sender" header to compute a Messsage ID.'); + } + + return bin2hex(random_bytes(16)).strstr($sender->getAddress(), '@'); + } + + public function __serialize(): array + { + return [$this->headers, $this->body]; + } + + public function __unserialize(array $data): void + { + [$this->headers, $this->body] = $data; + } +} diff --git a/vendor/symfony/mime/MessageConverter.php b/vendor/symfony/mime/MessageConverter.php new file mode 100644 index 0000000..a810cb7 --- /dev/null +++ b/vendor/symfony/mime/MessageConverter.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Symfony\Component\Mime\Exception\RuntimeException; +use Symfony\Component\Mime\Part\DataPart; +use Symfony\Component\Mime\Part\Multipart\AlternativePart; +use Symfony\Component\Mime\Part\Multipart\MixedPart; +use Symfony\Component\Mime\Part\Multipart\RelatedPart; +use Symfony\Component\Mime\Part\TextPart; + +/** + * @author Fabien Potencier + */ +final class MessageConverter +{ + /** + * @throws RuntimeException when unable to convert the message to an email + */ + public static function toEmail(Message $message): Email + { + if ($message instanceof Email) { + return $message; + } + + // try to convert to a "simple" Email instance + $body = $message->getBody(); + if ($body instanceof TextPart) { + return self::createEmailFromTextPart($message, $body); + } + + if ($body instanceof AlternativePart) { + return self::createEmailFromAlternativePart($message, $body); + } + + if ($body instanceof RelatedPart) { + return self::createEmailFromRelatedPart($message, $body); + } + + if ($body instanceof MixedPart) { + $parts = $body->getParts(); + if ($parts[0] instanceof RelatedPart) { + $email = self::createEmailFromRelatedPart($message, $parts[0]); + } elseif ($parts[0] instanceof AlternativePart) { + $email = self::createEmailFromAlternativePart($message, $parts[0]); + } elseif ($parts[0] instanceof TextPart) { + $email = self::createEmailFromTextPart($message, $parts[0]); + } else { + throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); + } + + return self::attachParts($email, \array_slice($parts, 1)); + } + + throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); + } + + private static function createEmailFromTextPart(Message $message, TextPart $part): Email + { + if ('text' === $part->getMediaType() && 'plain' === $part->getMediaSubtype()) { + return (new Email(clone $message->getHeaders()))->text($part->getBody(), $part->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8'); + } + if ('text' === $part->getMediaType() && 'html' === $part->getMediaSubtype()) { + return (new Email(clone $message->getHeaders()))->html($part->getBody(), $part->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8'); + } + + throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); + } + + private static function createEmailFromAlternativePart(Message $message, AlternativePart $part): Email + { + $parts = $part->getParts(); + if ( + 2 === \count($parts) && + $parts[0] instanceof TextPart && 'text' === $parts[0]->getMediaType() && 'plain' === $parts[0]->getMediaSubtype() && + $parts[1] instanceof TextPart && 'text' === $parts[1]->getMediaType() && 'html' === $parts[1]->getMediaSubtype() + ) { + return (new Email(clone $message->getHeaders())) + ->text($parts[0]->getBody(), $parts[0]->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8') + ->html($parts[1]->getBody(), $parts[1]->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8') + ; + } + + throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); + } + + private static function createEmailFromRelatedPart(Message $message, RelatedPart $part): Email + { + $parts = $part->getParts(); + if ($parts[0] instanceof AlternativePart) { + $email = self::createEmailFromAlternativePart($message, $parts[0]); + } elseif ($parts[0] instanceof TextPart) { + $email = self::createEmailFromTextPart($message, $parts[0]); + } else { + throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); + } + + return self::attachParts($email, \array_slice($parts, 1)); + } + + private static function attachParts(Email $email, array $parts): Email + { + foreach ($parts as $part) { + if (!$part instanceof DataPart) { + throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($email))); + } + + $headers = $part->getPreparedHeaders(); + $method = 'inline' === $headers->getHeaderBody('Content-Disposition') ? 'embed' : 'attach'; + $name = $headers->getHeaderParameter('Content-Disposition', 'filename'); + $email->$method($part->getBody(), $name, $part->getMediaType().'/'.$part->getMediaSubtype()); + } + + return $email; + } +} diff --git a/vendor/symfony/mime/MimeTypeGuesserInterface.php b/vendor/symfony/mime/MimeTypeGuesserInterface.php new file mode 100644 index 0000000..68b0505 --- /dev/null +++ b/vendor/symfony/mime/MimeTypeGuesserInterface.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +/** + * Guesses the MIME type of a file. + * + * @author Fabien Potencier + */ +interface MimeTypeGuesserInterface +{ + /** + * Returns true if this guesser is supported. + */ + public function isGuesserSupported(): bool; + + /** + * Guesses the MIME type of the file with the given path. + * + * @param string $path The path to the file + * + * @return string|null The MIME type or null, if none could be guessed + * + * @throws \LogicException If the guesser is not supported + * @throws \InvalidArgumentException If the file does not exist or is not readable + */ + public function guessMimeType(string $path): ?string; +} diff --git a/vendor/symfony/mime/MimeTypes.php b/vendor/symfony/mime/MimeTypes.php new file mode 100644 index 0000000..268658d --- /dev/null +++ b/vendor/symfony/mime/MimeTypes.php @@ -0,0 +1,3153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Symfony\Component\Mime\Exception\LogicException; + +/** + * Manages MIME types and file extensions. + * + * For MIME type guessing, you can register custom guessers + * by calling the registerGuesser() method. + * Custom guessers are always called before any default ones: + * + * $guesser = new MimeTypes(); + * $guesser->registerGuesser(new MyCustomMimeTypeGuesser()); + * + * If you want to change the order of the default guessers, just re-register your + * preferred one as a custom one. The last registered guesser is preferred over + * previously registered ones. + * + * Re-registering a built-in guesser also allows you to configure it: + * + * $guesser = new MimeTypes(); + * $guesser->registerGuesser(new FileinfoMimeTypeGuesser('/path/to/magic/file')); + * + * @author Fabien Potencier + */ +final class MimeTypes implements MimeTypesInterface +{ + private $extensions = []; + private $mimeTypes = []; + + /** + * @var MimeTypeGuesserInterface[] + */ + private $guessers = []; + private static $default; + + public function __construct(array $map = []) + { + foreach ($map as $mimeType => $extensions) { + $this->extensions[$mimeType] = $extensions; + + foreach ($extensions as $extension) { + $this->mimeTypes[$extension] = $mimeType; + } + } + $this->registerGuesser(new FileBinaryMimeTypeGuesser()); + $this->registerGuesser(new FileinfoMimeTypeGuesser()); + } + + public static function setDefault(self $default) + { + self::$default = $default; + } + + public static function getDefault(): self + { + return self::$default ?? self::$default = new self(); + } + + /** + * Registers a MIME type guesser. + * + * The last registered guesser has precedence over the other ones. + */ + public function registerGuesser(MimeTypeGuesserInterface $guesser) + { + array_unshift($this->guessers, $guesser); + } + + /** + * {@inheritdoc} + */ + public function getExtensions(string $mimeType): array + { + if ($this->extensions) { + $extensions = $this->extensions[$mimeType] ?? $this->extensions[$lcMimeType = strtolower($mimeType)] ?? null; + } + + return $extensions ?? self::$map[$mimeType] ?? self::$map[$lcMimeType ?? strtolower($mimeType)] ?? []; + } + + /** + * {@inheritdoc} + */ + public function getMimeTypes(string $ext): array + { + if ($this->mimeTypes) { + $mimeTypes = $this->mimeTypes[$ext] ?? $this->mimeTypes[$lcExt = strtolower($ext)] ?? null; + } + + return $mimeTypes ?? self::$reverseMap[$ext] ?? self::$reverseMap[$lcExt ?? strtolower($ext)] ?? []; + } + + /** + * {@inheritdoc} + */ + public function isGuesserSupported(): bool + { + foreach ($this->guessers as $guesser) { + if ($guesser->isGuesserSupported()) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + * + * The file is passed to each registered MIME type guesser in reverse order + * of their registration (last registered is queried first). Once a guesser + * returns a value that is not null, this method terminates and returns the + * value. + */ + public function guessMimeType(string $path): ?string + { + foreach ($this->guessers as $guesser) { + if (!$guesser->isGuesserSupported()) { + continue; + } + + if (null !== $mimeType = $guesser->guessMimeType($path)) { + return $mimeType; + } + } + + if (!$this->isGuesserSupported()) { + throw new LogicException('Unable to guess the MIME type as no guessers are available (have you enable the php_fileinfo extension?).'); + } + + return null; + } + + /** + * A map of MIME types and their default extensions. + * + * Updated from upstream on 2019-01-16 + * + * @see Resources/bin/update_mime_types.php + */ + private static $map = [ + 'application/acrobat' => ['pdf'], + 'application/andrew-inset' => ['ez'], + 'application/annodex' => ['anx'], + 'application/applixware' => ['aw'], + 'application/atom+xml' => ['atom'], + 'application/atomcat+xml' => ['atomcat'], + 'application/atomsvc+xml' => ['atomsvc'], + 'application/ccxml+xml' => ['ccxml'], + 'application/cdmi-capability' => ['cdmia'], + 'application/cdmi-container' => ['cdmic'], + 'application/cdmi-domain' => ['cdmid'], + 'application/cdmi-object' => ['cdmio'], + 'application/cdmi-queue' => ['cdmiq'], + 'application/cdr' => ['cdr'], + 'application/coreldraw' => ['cdr'], + 'application/cu-seeme' => ['cu'], + 'application/davmount+xml' => ['davmount'], + 'application/dbase' => ['dbf'], + 'application/dbf' => ['dbf'], + 'application/dicom' => ['dcm'], + 'application/docbook+xml' => ['dbk', 'docbook'], + 'application/dssc+der' => ['dssc'], + 'application/dssc+xml' => ['xdssc'], + 'application/ecmascript' => ['ecma', 'es'], + 'application/emf' => ['emf'], + 'application/emma+xml' => ['emma'], + 'application/epub+zip' => ['epub'], + 'application/exi' => ['exi'], + 'application/font-tdpfr' => ['pfr'], + 'application/font-woff' => ['woff'], + 'application/futuresplash' => ['swf', 'spl'], + 'application/geo+json' => ['geojson', 'geo.json'], + 'application/gml+xml' => ['gml'], + 'application/gnunet-directory' => ['gnd'], + 'application/gpx' => ['gpx'], + 'application/gpx+xml' => ['gpx'], + 'application/gxf' => ['gxf'], + 'application/gzip' => ['gz'], + 'application/hyperstudio' => ['stk'], + 'application/ico' => ['ico'], + 'application/ics' => ['vcs', 'ics'], + 'application/illustrator' => ['ai'], + 'application/inkml+xml' => ['ink', 'inkml'], + 'application/ipfix' => ['ipfix'], + 'application/java' => ['class'], + 'application/java-archive' => ['jar'], + 'application/java-byte-code' => ['class'], + 'application/java-serialized-object' => ['ser'], + 'application/java-vm' => ['class'], + 'application/javascript' => ['js', 'jsm', 'mjs'], + 'application/jrd+json' => ['jrd'], + 'application/json' => ['json'], + 'application/json-patch+json' => ['json-patch'], + 'application/jsonml+json' => ['jsonml'], + 'application/ld+json' => ['jsonld'], + 'application/lost+xml' => ['lostxml'], + 'application/lotus123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], + 'application/m3u' => ['m3u', 'm3u8', 'vlc'], + 'application/mac-binhex40' => ['hqx'], + 'application/mac-compactpro' => ['cpt'], + 'application/mads+xml' => ['mads'], + 'application/marc' => ['mrc'], + 'application/marcxml+xml' => ['mrcx'], + 'application/mathematica' => ['ma', 'nb', 'mb'], + 'application/mathml+xml' => ['mathml', 'mml'], + 'application/mbox' => ['mbox'], + 'application/mdb' => ['mdb'], + 'application/mediaservercontrol+xml' => ['mscml'], + 'application/metalink+xml' => ['metalink'], + 'application/metalink4+xml' => ['meta4'], + 'application/mets+xml' => ['mets'], + 'application/mods+xml' => ['mods'], + 'application/mp21' => ['m21', 'mp21'], + 'application/mp4' => ['mp4s'], + 'application/ms-tnef' => ['tnef', 'tnf'], + 'application/msaccess' => ['mdb'], + 'application/msexcel' => ['xls', 'xlc', 'xll', 'xlm', 'xlw', 'xla', 'xlt', 'xld'], + 'application/mspowerpoint' => ['ppz', 'ppt', 'pps', 'pot'], + 'application/msword' => ['doc', 'dot'], + 'application/msword-template' => ['dot'], + 'application/mxf' => ['mxf'], + 'application/nappdf' => ['pdf'], + 'application/octet-stream' => ['bin', 'dms', 'lrf', 'mar', 'so', 'dist', 'distz', 'pkg', 'bpk', 'dump', 'elc', 'deploy'], + 'application/oda' => ['oda'], + 'application/oebps-package+xml' => ['opf'], + 'application/ogg' => ['ogx'], + 'application/omdoc+xml' => ['omdoc'], + 'application/onenote' => ['onetoc', 'onetoc2', 'onetmp', 'onepkg'], + 'application/owl+xml' => ['owx'], + 'application/oxps' => ['oxps', 'xps'], + 'application/patch-ops-error+xml' => ['xer'], + 'application/pcap' => ['pcap', 'cap', 'dmp'], + 'application/pdf' => ['pdf'], + 'application/pgp' => ['pgp', 'gpg', 'asc'], + 'application/pgp-encrypted' => ['pgp', 'gpg', 'asc'], + 'application/pgp-keys' => ['skr', 'pkr', 'asc', 'pgp', 'gpg'], + 'application/pgp-signature' => ['asc', 'sig', 'pgp', 'gpg'], + 'application/photoshop' => ['psd'], + 'application/pics-rules' => ['prf'], + 'application/pkcs10' => ['p10'], + 'application/pkcs12' => ['p12', 'pfx'], + 'application/pkcs7-mime' => ['p7m', 'p7c'], + 'application/pkcs7-signature' => ['p7s'], + 'application/pkcs8' => ['p8'], + 'application/pkcs8-encrypted' => ['p8e'], + 'application/pkix-attr-cert' => ['ac'], + 'application/pkix-cert' => ['cer'], + 'application/pkix-crl' => ['crl'], + 'application/pkix-pkipath' => ['pkipath'], + 'application/pkixcmp' => ['pki'], + 'application/pls' => ['pls'], + 'application/pls+xml' => ['pls'], + 'application/postscript' => ['ai', 'eps', 'ps'], + 'application/powerpoint' => ['ppz', 'ppt', 'pps', 'pot'], + 'application/prs.cww' => ['cww'], + 'application/pskc+xml' => ['pskcxml'], + 'application/ram' => ['ram'], + 'application/raml+yaml' => ['raml'], + 'application/rdf+xml' => ['rdf', 'rdfs', 'owl'], + 'application/reginfo+xml' => ['rif'], + 'application/relax-ng-compact-syntax' => ['rnc'], + 'application/resource-lists+xml' => ['rl'], + 'application/resource-lists-diff+xml' => ['rld'], + 'application/rls-services+xml' => ['rs'], + 'application/rpki-ghostbusters' => ['gbr'], + 'application/rpki-manifest' => ['mft'], + 'application/rpki-roa' => ['roa'], + 'application/rsd+xml' => ['rsd'], + 'application/rss+xml' => ['rss'], + 'application/rtf' => ['rtf'], + 'application/sbml+xml' => ['sbml'], + 'application/scvp-cv-request' => ['scq'], + 'application/scvp-cv-response' => ['scs'], + 'application/scvp-vp-request' => ['spq'], + 'application/scvp-vp-response' => ['spp'], + 'application/sdp' => ['sdp'], + 'application/set-payment-initiation' => ['setpay'], + 'application/set-registration-initiation' => ['setreg'], + 'application/shf+xml' => ['shf'], + 'application/sieve' => ['siv'], + 'application/smil' => ['smil', 'smi', 'sml', 'kino'], + 'application/smil+xml' => ['smi', 'smil', 'sml', 'kino'], + 'application/sparql-query' => ['rq'], + 'application/sparql-results+xml' => ['srx'], + 'application/sql' => ['sql'], + 'application/srgs' => ['gram'], + 'application/srgs+xml' => ['grxml'], + 'application/sru+xml' => ['sru'], + 'application/ssdl+xml' => ['ssdl'], + 'application/ssml+xml' => ['ssml'], + 'application/stuffit' => ['sit'], + 'application/tei+xml' => ['tei', 'teicorpus'], + 'application/thraud+xml' => ['tfi'], + 'application/timestamped-data' => ['tsd'], + 'application/trig' => ['trig'], + 'application/vnd.3gpp.pic-bw-large' => ['plb'], + 'application/vnd.3gpp.pic-bw-small' => ['psb'], + 'application/vnd.3gpp.pic-bw-var' => ['pvb'], + 'application/vnd.3gpp2.tcap' => ['tcap'], + 'application/vnd.3m.post-it-notes' => ['pwn'], + 'application/vnd.accpac.simply.aso' => ['aso'], + 'application/vnd.accpac.simply.imp' => ['imp'], + 'application/vnd.acucobol' => ['acu'], + 'application/vnd.acucorp' => ['atc', 'acutc'], + 'application/vnd.adobe.air-application-installer-package+zip' => ['air'], + 'application/vnd.adobe.flash.movie' => ['swf', 'spl'], + 'application/vnd.adobe.formscentral.fcdt' => ['fcdt'], + 'application/vnd.adobe.fxp' => ['fxp', 'fxpl'], + 'application/vnd.adobe.illustrator' => ['ai'], + 'application/vnd.adobe.xdp+xml' => ['xdp'], + 'application/vnd.adobe.xfdf' => ['xfdf'], + 'application/vnd.ahead.space' => ['ahead'], + 'application/vnd.airzip.filesecure.azf' => ['azf'], + 'application/vnd.airzip.filesecure.azs' => ['azs'], + 'application/vnd.amazon.ebook' => ['azw'], + 'application/vnd.americandynamics.acc' => ['acc'], + 'application/vnd.amiga.ami' => ['ami'], + 'application/vnd.android.package-archive' => ['apk'], + 'application/vnd.anser-web-certificate-issue-initiation' => ['cii'], + 'application/vnd.anser-web-funds-transfer-initiation' => ['fti'], + 'application/vnd.antix.game-component' => ['atx'], + 'application/vnd.appimage' => ['appimage'], + 'application/vnd.apple.installer+xml' => ['mpkg'], + 'application/vnd.apple.keynote' => ['key'], + 'application/vnd.apple.mpegurl' => ['m3u8', 'm3u'], + 'application/vnd.aristanetworks.swi' => ['swi'], + 'application/vnd.astraea-software.iota' => ['iota'], + 'application/vnd.audiograph' => ['aep'], + 'application/vnd.blueice.multipass' => ['mpm'], + 'application/vnd.bmi' => ['bmi'], + 'application/vnd.businessobjects' => ['rep'], + 'application/vnd.chemdraw+xml' => ['cdxml'], + 'application/vnd.chess-pgn' => ['pgn'], + 'application/vnd.chipnuts.karaoke-mmd' => ['mmd'], + 'application/vnd.cinderella' => ['cdy'], + 'application/vnd.claymore' => ['cla'], + 'application/vnd.cloanto.rp9' => ['rp9'], + 'application/vnd.clonk.c4group' => ['c4g', 'c4d', 'c4f', 'c4p', 'c4u'], + 'application/vnd.cluetrust.cartomobile-config' => ['c11amc'], + 'application/vnd.cluetrust.cartomobile-config-pkg' => ['c11amz'], + 'application/vnd.coffeescript' => ['coffee'], + 'application/vnd.comicbook+zip' => ['cbz'], + 'application/vnd.comicbook-rar' => ['cbr'], + 'application/vnd.commonspace' => ['csp'], + 'application/vnd.contact.cmsg' => ['cdbcmsg'], + 'application/vnd.corel-draw' => ['cdr'], + 'application/vnd.cosmocaller' => ['cmc'], + 'application/vnd.crick.clicker' => ['clkx'], + 'application/vnd.crick.clicker.keyboard' => ['clkk'], + 'application/vnd.crick.clicker.palette' => ['clkp'], + 'application/vnd.crick.clicker.template' => ['clkt'], + 'application/vnd.crick.clicker.wordbank' => ['clkw'], + 'application/vnd.criticaltools.wbs+xml' => ['wbs'], + 'application/vnd.ctc-posml' => ['pml'], + 'application/vnd.cups-ppd' => ['ppd'], + 'application/vnd.curl.car' => ['car'], + 'application/vnd.curl.pcurl' => ['pcurl'], + 'application/vnd.dart' => ['dart'], + 'application/vnd.data-vision.rdz' => ['rdz'], + 'application/vnd.debian.binary-package' => ['deb', 'udeb'], + 'application/vnd.dece.data' => ['uvf', 'uvvf', 'uvd', 'uvvd'], + 'application/vnd.dece.ttml+xml' => ['uvt', 'uvvt'], + 'application/vnd.dece.unspecified' => ['uvx', 'uvvx'], + 'application/vnd.dece.zip' => ['uvz', 'uvvz'], + 'application/vnd.denovo.fcselayout-link' => ['fe_launch'], + 'application/vnd.dna' => ['dna'], + 'application/vnd.dolby.mlp' => ['mlp'], + 'application/vnd.dpgraph' => ['dpg'], + 'application/vnd.dreamfactory' => ['dfac'], + 'application/vnd.ds-keypoint' => ['kpxx'], + 'application/vnd.dvb.ait' => ['ait'], + 'application/vnd.dvb.service' => ['svc'], + 'application/vnd.dynageo' => ['geo'], + 'application/vnd.ecowin.chart' => ['mag'], + 'application/vnd.emusic-emusic_package' => ['emp'], + 'application/vnd.enliven' => ['nml'], + 'application/vnd.epson.esf' => ['esf'], + 'application/vnd.epson.msf' => ['msf'], + 'application/vnd.epson.quickanime' => ['qam'], + 'application/vnd.epson.salt' => ['slt'], + 'application/vnd.epson.ssf' => ['ssf'], + 'application/vnd.eszigno3+xml' => ['es3', 'et3'], + 'application/vnd.ezpix-album' => ['ez2'], + 'application/vnd.ezpix-package' => ['ez3'], + 'application/vnd.fdf' => ['fdf'], + 'application/vnd.fdsn.mseed' => ['mseed'], + 'application/vnd.fdsn.seed' => ['seed', 'dataless'], + 'application/vnd.flatpak' => ['flatpak', 'xdgapp'], + 'application/vnd.flatpak.ref' => ['flatpakref'], + 'application/vnd.flatpak.repo' => ['flatpakrepo'], + 'application/vnd.flographit' => ['gph'], + 'application/vnd.fluxtime.clip' => ['ftc'], + 'application/vnd.framemaker' => ['fm', 'frame', 'maker', 'book'], + 'application/vnd.frogans.fnc' => ['fnc'], + 'application/vnd.frogans.ltf' => ['ltf'], + 'application/vnd.fsc.weblaunch' => ['fsc'], + 'application/vnd.fujitsu.oasys' => ['oas'], + 'application/vnd.fujitsu.oasys2' => ['oa2'], + 'application/vnd.fujitsu.oasys3' => ['oa3'], + 'application/vnd.fujitsu.oasysgp' => ['fg5'], + 'application/vnd.fujitsu.oasysprs' => ['bh2'], + 'application/vnd.fujixerox.ddd' => ['ddd'], + 'application/vnd.fujixerox.docuworks' => ['xdw'], + 'application/vnd.fujixerox.docuworks.binder' => ['xbd'], + 'application/vnd.fuzzysheet' => ['fzs'], + 'application/vnd.genomatix.tuxedo' => ['txd'], + 'application/vnd.geo+json' => ['geojson', 'geo.json'], + 'application/vnd.geogebra.file' => ['ggb'], + 'application/vnd.geogebra.tool' => ['ggt'], + 'application/vnd.geometry-explorer' => ['gex', 'gre'], + 'application/vnd.geonext' => ['gxt'], + 'application/vnd.geoplan' => ['g2w'], + 'application/vnd.geospace' => ['g3w'], + 'application/vnd.gmx' => ['gmx'], + 'application/vnd.google-earth.kml+xml' => ['kml'], + 'application/vnd.google-earth.kmz' => ['kmz'], + 'application/vnd.grafeq' => ['gqf', 'gqs'], + 'application/vnd.groove-account' => ['gac'], + 'application/vnd.groove-help' => ['ghf'], + 'application/vnd.groove-identity-message' => ['gim'], + 'application/vnd.groove-injector' => ['grv'], + 'application/vnd.groove-tool-message' => ['gtm'], + 'application/vnd.groove-tool-template' => ['tpl'], + 'application/vnd.groove-vcard' => ['vcg'], + 'application/vnd.haansoft-hwp' => ['hwp'], + 'application/vnd.haansoft-hwt' => ['hwt'], + 'application/vnd.hal+xml' => ['hal'], + 'application/vnd.handheld-entertainment+xml' => ['zmm'], + 'application/vnd.hbci' => ['hbci'], + 'application/vnd.hhe.lesson-player' => ['les'], + 'application/vnd.hp-hpgl' => ['hpgl'], + 'application/vnd.hp-hpid' => ['hpid'], + 'application/vnd.hp-hps' => ['hps'], + 'application/vnd.hp-jlyt' => ['jlt'], + 'application/vnd.hp-pcl' => ['pcl'], + 'application/vnd.hp-pclxl' => ['pclxl'], + 'application/vnd.hydrostatix.sof-data' => ['sfd-hdstx'], + 'application/vnd.ibm.minipay' => ['mpy'], + 'application/vnd.ibm.modcap' => ['afp', 'listafp', 'list3820'], + 'application/vnd.ibm.rights-management' => ['irm'], + 'application/vnd.ibm.secure-container' => ['sc'], + 'application/vnd.iccprofile' => ['icc', 'icm'], + 'application/vnd.igloader' => ['igl'], + 'application/vnd.immervision-ivp' => ['ivp'], + 'application/vnd.immervision-ivu' => ['ivu'], + 'application/vnd.insors.igm' => ['igm'], + 'application/vnd.intercon.formnet' => ['xpw', 'xpx'], + 'application/vnd.intergeo' => ['i2g'], + 'application/vnd.intu.qbo' => ['qbo'], + 'application/vnd.intu.qfx' => ['qfx'], + 'application/vnd.ipunplugged.rcprofile' => ['rcprofile'], + 'application/vnd.irepository.package+xml' => ['irp'], + 'application/vnd.is-xpr' => ['xpr'], + 'application/vnd.isac.fcs' => ['fcs'], + 'application/vnd.jam' => ['jam'], + 'application/vnd.jcp.javame.midlet-rms' => ['rms'], + 'application/vnd.jisp' => ['jisp'], + 'application/vnd.joost.joda-archive' => ['joda'], + 'application/vnd.kahootz' => ['ktz', 'ktr'], + 'application/vnd.kde.karbon' => ['karbon'], + 'application/vnd.kde.kchart' => ['chrt'], + 'application/vnd.kde.kformula' => ['kfo'], + 'application/vnd.kde.kivio' => ['flw'], + 'application/vnd.kde.kontour' => ['kon'], + 'application/vnd.kde.kpresenter' => ['kpr', 'kpt'], + 'application/vnd.kde.kspread' => ['ksp'], + 'application/vnd.kde.kword' => ['kwd', 'kwt'], + 'application/vnd.kenameaapp' => ['htke'], + 'application/vnd.kidspiration' => ['kia'], + 'application/vnd.kinar' => ['kne', 'knp'], + 'application/vnd.koan' => ['skp', 'skd', 'skt', 'skm'], + 'application/vnd.kodak-descriptor' => ['sse'], + 'application/vnd.las.las+xml' => ['lasxml'], + 'application/vnd.llamagraphics.life-balance.desktop' => ['lbd'], + 'application/vnd.llamagraphics.life-balance.exchange+xml' => ['lbe'], + 'application/vnd.lotus-1-2-3' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], + 'application/vnd.lotus-approach' => ['apr'], + 'application/vnd.lotus-freelance' => ['pre'], + 'application/vnd.lotus-notes' => ['nsf'], + 'application/vnd.lotus-organizer' => ['org'], + 'application/vnd.lotus-screencam' => ['scm'], + 'application/vnd.lotus-wordpro' => ['lwp'], + 'application/vnd.macports.portpkg' => ['portpkg'], + 'application/vnd.mcd' => ['mcd'], + 'application/vnd.medcalcdata' => ['mc1'], + 'application/vnd.mediastation.cdkey' => ['cdkey'], + 'application/vnd.mfer' => ['mwf'], + 'application/vnd.mfmp' => ['mfm'], + 'application/vnd.micrografx.flo' => ['flo'], + 'application/vnd.micrografx.igx' => ['igx'], + 'application/vnd.mif' => ['mif'], + 'application/vnd.mobius.daf' => ['daf'], + 'application/vnd.mobius.dis' => ['dis'], + 'application/vnd.mobius.mbk' => ['mbk'], + 'application/vnd.mobius.mqy' => ['mqy'], + 'application/vnd.mobius.msl' => ['msl'], + 'application/vnd.mobius.plc' => ['plc'], + 'application/vnd.mobius.txf' => ['txf'], + 'application/vnd.mophun.application' => ['mpn'], + 'application/vnd.mophun.certificate' => ['mpc'], + 'application/vnd.mozilla.xul+xml' => ['xul'], + 'application/vnd.ms-access' => ['mdb'], + 'application/vnd.ms-artgalry' => ['cil'], + 'application/vnd.ms-asf' => ['asf'], + 'application/vnd.ms-cab-compressed' => ['cab'], + 'application/vnd.ms-excel' => ['xls', 'xlm', 'xla', 'xlc', 'xlt', 'xlw', 'xll', 'xld'], + 'application/vnd.ms-excel.addin.macroenabled.12' => ['xlam'], + 'application/vnd.ms-excel.sheet.binary.macroenabled.12' => ['xlsb'], + 'application/vnd.ms-excel.sheet.macroenabled.12' => ['xlsm'], + 'application/vnd.ms-excel.template.macroenabled.12' => ['xltm'], + 'application/vnd.ms-fontobject' => ['eot'], + 'application/vnd.ms-htmlhelp' => ['chm'], + 'application/vnd.ms-ims' => ['ims'], + 'application/vnd.ms-lrm' => ['lrm'], + 'application/vnd.ms-officetheme' => ['thmx'], + 'application/vnd.ms-pki.seccat' => ['cat'], + 'application/vnd.ms-pki.stl' => ['stl'], + 'application/vnd.ms-powerpoint' => ['ppt', 'pps', 'pot', 'ppz'], + 'application/vnd.ms-powerpoint.addin.macroenabled.12' => ['ppam'], + 'application/vnd.ms-powerpoint.presentation.macroenabled.12' => ['pptm'], + 'application/vnd.ms-powerpoint.slide.macroenabled.12' => ['sldm'], + 'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => ['ppsm'], + 'application/vnd.ms-powerpoint.template.macroenabled.12' => ['potm'], + 'application/vnd.ms-project' => ['mpp', 'mpt'], + 'application/vnd.ms-publisher' => ['pub'], + 'application/vnd.ms-tnef' => ['tnef', 'tnf'], + 'application/vnd.ms-visio.drawing.macroenabled.main+xml' => ['vsdm'], + 'application/vnd.ms-visio.drawing.main+xml' => ['vsdx'], + 'application/vnd.ms-visio.stencil.macroenabled.main+xml' => ['vssm'], + 'application/vnd.ms-visio.stencil.main+xml' => ['vssx'], + 'application/vnd.ms-visio.template.macroenabled.main+xml' => ['vstm'], + 'application/vnd.ms-visio.template.main+xml' => ['vstx'], + 'application/vnd.ms-word' => ['doc'], + 'application/vnd.ms-word.document.macroenabled.12' => ['docm'], + 'application/vnd.ms-word.template.macroenabled.12' => ['dotm'], + 'application/vnd.ms-works' => ['wps', 'wks', 'wcm', 'wdb', 'xlr'], + 'application/vnd.ms-wpl' => ['wpl'], + 'application/vnd.ms-xpsdocument' => ['xps', 'oxps'], + 'application/vnd.msaccess' => ['mdb'], + 'application/vnd.mseq' => ['mseq'], + 'application/vnd.musician' => ['mus'], + 'application/vnd.muvee.style' => ['msty'], + 'application/vnd.mynfc' => ['taglet'], + 'application/vnd.neurolanguage.nlu' => ['nlu'], + 'application/vnd.nintendo.snes.rom' => ['sfc', 'smc'], + 'application/vnd.nitf' => ['ntf', 'nitf'], + 'application/vnd.noblenet-directory' => ['nnd'], + 'application/vnd.noblenet-sealer' => ['nns'], + 'application/vnd.noblenet-web' => ['nnw'], + 'application/vnd.nokia.n-gage.data' => ['ngdat'], + 'application/vnd.nokia.n-gage.symbian.install' => ['n-gage'], + 'application/vnd.nokia.radio-preset' => ['rpst'], + 'application/vnd.nokia.radio-presets' => ['rpss'], + 'application/vnd.novadigm.edm' => ['edm'], + 'application/vnd.novadigm.edx' => ['edx'], + 'application/vnd.novadigm.ext' => ['ext'], + 'application/vnd.oasis.docbook+xml' => ['dbk', 'docbook'], + 'application/vnd.oasis.opendocument.chart' => ['odc'], + 'application/vnd.oasis.opendocument.chart-template' => ['otc'], + 'application/vnd.oasis.opendocument.database' => ['odb'], + 'application/vnd.oasis.opendocument.formula' => ['odf'], + 'application/vnd.oasis.opendocument.formula-template' => ['odft', 'otf'], + 'application/vnd.oasis.opendocument.graphics' => ['odg'], + 'application/vnd.oasis.opendocument.graphics-flat-xml' => ['fodg'], + 'application/vnd.oasis.opendocument.graphics-template' => ['otg'], + 'application/vnd.oasis.opendocument.image' => ['odi'], + 'application/vnd.oasis.opendocument.image-template' => ['oti'], + 'application/vnd.oasis.opendocument.presentation' => ['odp'], + 'application/vnd.oasis.opendocument.presentation-flat-xml' => ['fodp'], + 'application/vnd.oasis.opendocument.presentation-template' => ['otp'], + 'application/vnd.oasis.opendocument.spreadsheet' => ['ods'], + 'application/vnd.oasis.opendocument.spreadsheet-flat-xml' => ['fods'], + 'application/vnd.oasis.opendocument.spreadsheet-template' => ['ots'], + 'application/vnd.oasis.opendocument.text' => ['odt'], + 'application/vnd.oasis.opendocument.text-flat-xml' => ['fodt'], + 'application/vnd.oasis.opendocument.text-master' => ['odm'], + 'application/vnd.oasis.opendocument.text-template' => ['ott'], + 'application/vnd.oasis.opendocument.text-web' => ['oth'], + 'application/vnd.olpc-sugar' => ['xo'], + 'application/vnd.oma.dd2+xml' => ['dd2'], + 'application/vnd.openofficeorg.extension' => ['oxt'], + 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => ['pptx'], + 'application/vnd.openxmlformats-officedocument.presentationml.slide' => ['sldx'], + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => ['ppsx'], + 'application/vnd.openxmlformats-officedocument.presentationml.template' => ['potx'], + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => ['xlsx'], + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => ['xltx'], + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => ['docx'], + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => ['dotx'], + 'application/vnd.osgeo.mapguide.package' => ['mgp'], + 'application/vnd.osgi.dp' => ['dp'], + 'application/vnd.osgi.subsystem' => ['esa'], + 'application/vnd.palm' => ['pdb', 'pqa', 'oprc', 'prc'], + 'application/vnd.pawaafile' => ['paw'], + 'application/vnd.pg.format' => ['str'], + 'application/vnd.pg.osasli' => ['ei6'], + 'application/vnd.picsel' => ['efif'], + 'application/vnd.pmi.widget' => ['wg'], + 'application/vnd.pocketlearn' => ['plf'], + 'application/vnd.powerbuilder6' => ['pbd'], + 'application/vnd.previewsystems.box' => ['box'], + 'application/vnd.proteus.magazine' => ['mgz'], + 'application/vnd.publishare-delta-tree' => ['qps'], + 'application/vnd.pvi.ptid1' => ['ptid'], + 'application/vnd.quark.quarkxpress' => ['qxd', 'qxt', 'qwd', 'qwt', 'qxl', 'qxb'], + 'application/vnd.rar' => ['rar'], + 'application/vnd.realvnc.bed' => ['bed'], + 'application/vnd.recordare.musicxml' => ['mxl'], + 'application/vnd.recordare.musicxml+xml' => ['musicxml'], + 'application/vnd.rig.cryptonote' => ['cryptonote'], + 'application/vnd.rim.cod' => ['cod'], + 'application/vnd.rn-realmedia' => ['rm', 'rmj', 'rmm', 'rms', 'rmx', 'rmvb'], + 'application/vnd.rn-realmedia-vbr' => ['rmvb', 'rm', 'rmj', 'rmm', 'rms', 'rmx'], + 'application/vnd.route66.link66+xml' => ['link66'], + 'application/vnd.sailingtracker.track' => ['st'], + 'application/vnd.sdp' => ['sdp'], + 'application/vnd.seemail' => ['see'], + 'application/vnd.sema' => ['sema'], + 'application/vnd.semd' => ['semd'], + 'application/vnd.semf' => ['semf'], + 'application/vnd.shana.informed.formdata' => ['ifm'], + 'application/vnd.shana.informed.formtemplate' => ['itp'], + 'application/vnd.shana.informed.interchange' => ['iif'], + 'application/vnd.shana.informed.package' => ['ipk'], + 'application/vnd.simtech-mindmapper' => ['twd', 'twds'], + 'application/vnd.smaf' => ['mmf', 'smaf'], + 'application/vnd.smart.teacher' => ['teacher'], + 'application/vnd.snap' => ['snap'], + 'application/vnd.solent.sdkm+xml' => ['sdkm', 'sdkd'], + 'application/vnd.spotfire.dxp' => ['dxp'], + 'application/vnd.spotfire.sfs' => ['sfs'], + 'application/vnd.sqlite3' => ['sqlite3'], + 'application/vnd.squashfs' => ['sqsh'], + 'application/vnd.stardivision.calc' => ['sdc'], + 'application/vnd.stardivision.chart' => ['sds'], + 'application/vnd.stardivision.draw' => ['sda'], + 'application/vnd.stardivision.impress' => ['sdd', 'sdp'], + 'application/vnd.stardivision.mail' => ['smd'], + 'application/vnd.stardivision.math' => ['smf'], + 'application/vnd.stardivision.writer' => ['sdw', 'vor', 'sgl'], + 'application/vnd.stardivision.writer-global' => ['sgl', 'sdw', 'vor'], + 'application/vnd.stepmania.package' => ['smzip'], + 'application/vnd.stepmania.stepchart' => ['sm'], + 'application/vnd.sun.xml.base' => ['odb'], + 'application/vnd.sun.xml.calc' => ['sxc'], + 'application/vnd.sun.xml.calc.template' => ['stc'], + 'application/vnd.sun.xml.draw' => ['sxd'], + 'application/vnd.sun.xml.draw.template' => ['std'], + 'application/vnd.sun.xml.impress' => ['sxi'], + 'application/vnd.sun.xml.impress.template' => ['sti'], + 'application/vnd.sun.xml.math' => ['sxm'], + 'application/vnd.sun.xml.writer' => ['sxw'], + 'application/vnd.sun.xml.writer.global' => ['sxg'], + 'application/vnd.sun.xml.writer.template' => ['stw'], + 'application/vnd.sus-calendar' => ['sus', 'susp'], + 'application/vnd.svd' => ['svd'], + 'application/vnd.symbian.install' => ['sis', 'sisx'], + 'application/vnd.syncml+xml' => ['xsm'], + 'application/vnd.syncml.dm+wbxml' => ['bdm'], + 'application/vnd.syncml.dm+xml' => ['xdm'], + 'application/vnd.tao.intent-module-archive' => ['tao'], + 'application/vnd.tcpdump.pcap' => ['pcap', 'cap', 'dmp'], + 'application/vnd.tmobile-livetv' => ['tmo'], + 'application/vnd.trid.tpt' => ['tpt'], + 'application/vnd.triscape.mxs' => ['mxs'], + 'application/vnd.trueapp' => ['tra'], + 'application/vnd.ufdl' => ['ufd', 'ufdl'], + 'application/vnd.uiq.theme' => ['utz'], + 'application/vnd.umajin' => ['umj'], + 'application/vnd.unity' => ['unityweb'], + 'application/vnd.uoml+xml' => ['uoml'], + 'application/vnd.vcx' => ['vcx'], + 'application/vnd.visio' => ['vsd', 'vst', 'vss', 'vsw'], + 'application/vnd.visionary' => ['vis'], + 'application/vnd.vsf' => ['vsf'], + 'application/vnd.wap.wbxml' => ['wbxml'], + 'application/vnd.wap.wmlc' => ['wmlc'], + 'application/vnd.wap.wmlscriptc' => ['wmlsc'], + 'application/vnd.webturbo' => ['wtb'], + 'application/vnd.wolfram.player' => ['nbp'], + 'application/vnd.wordperfect' => ['wpd', 'wp', 'wp4', 'wp5', 'wp6', 'wpp'], + 'application/vnd.wqd' => ['wqd'], + 'application/vnd.wt.stf' => ['stf'], + 'application/vnd.xara' => ['xar'], + 'application/vnd.xdgapp' => ['flatpak', 'xdgapp'], + 'application/vnd.xfdl' => ['xfdl'], + 'application/vnd.yamaha.hv-dic' => ['hvd'], + 'application/vnd.yamaha.hv-script' => ['hvs'], + 'application/vnd.yamaha.hv-voice' => ['hvp'], + 'application/vnd.yamaha.openscoreformat' => ['osf'], + 'application/vnd.yamaha.openscoreformat.osfpvg+xml' => ['osfpvg'], + 'application/vnd.yamaha.smaf-audio' => ['saf'], + 'application/vnd.yamaha.smaf-phrase' => ['spf'], + 'application/vnd.yellowriver-custom-menu' => ['cmp'], + 'application/vnd.youtube.yt' => ['yt'], + 'application/vnd.zul' => ['zir', 'zirz'], + 'application/vnd.zzazz.deck+xml' => ['zaz'], + 'application/voicexml+xml' => ['vxml'], + 'application/widget' => ['wgt'], + 'application/winhlp' => ['hlp'], + 'application/wk1' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], + 'application/wmf' => ['wmf'], + 'application/wordperfect' => ['wp', 'wp4', 'wp5', 'wp6', 'wpd', 'wpp'], + 'application/wsdl+xml' => ['wsdl'], + 'application/wspolicy+xml' => ['wspolicy'], + 'application/wwf' => ['wwf'], + 'application/x-123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], + 'application/x-7z-compressed' => ['7z'], + 'application/x-abiword' => ['abw', 'abw.CRASHED', 'abw.gz', 'zabw'], + 'application/x-ace' => ['ace'], + 'application/x-ace-compressed' => ['ace'], + 'application/x-alz' => ['alz'], + 'application/x-amiga-disk-format' => ['adf'], + 'application/x-amipro' => ['sam'], + 'application/x-annodex' => ['anx'], + 'application/x-aportisdoc' => ['pdb', 'pdc'], + 'application/x-apple-diskimage' => ['dmg'], + 'application/x-applix-spreadsheet' => ['as'], + 'application/x-applix-word' => ['aw'], + 'application/x-archive' => ['a', 'ar'], + 'application/x-arj' => ['arj'], + 'application/x-asp' => ['asp'], + 'application/x-atari-2600-rom' => ['a26'], + 'application/x-atari-7800-rom' => ['a78'], + 'application/x-atari-lynx-rom' => ['lnx'], + 'application/x-authorware-bin' => ['aab', 'x32', 'u32', 'vox'], + 'application/x-authorware-map' => ['aam'], + 'application/x-authorware-seg' => ['aas'], + 'application/x-awk' => ['awk'], + 'application/x-bcpio' => ['bcpio'], + 'application/x-bittorrent' => ['torrent'], + 'application/x-blender' => ['blender', 'blend', 'BLEND'], + 'application/x-blorb' => ['blb', 'blorb'], + 'application/x-bsdiff' => ['bsdiff'], + 'application/x-bzdvi' => ['dvi.bz2'], + 'application/x-bzip' => ['bz', 'bz2'], + 'application/x-bzip-compressed-tar' => ['tar.bz2', 'tar.bz', 'tbz2', 'tbz', 'tb2'], + 'application/x-bzip2' => ['bz2', 'boz', 'bz'], + 'application/x-bzpdf' => ['pdf.bz2'], + 'application/x-bzpostscript' => ['ps.bz2'], + 'application/x-cb7' => ['cb7'], + 'application/x-cbr' => ['cbr', 'cba', 'cbt', 'cbz', 'cb7'], + 'application/x-cbt' => ['cbt'], + 'application/x-cbz' => ['cbz'], + 'application/x-ccmx' => ['ccmx'], + 'application/x-cd-image' => ['iso', 'iso9660'], + 'application/x-cdlink' => ['vcd'], + 'application/x-cdr' => ['cdr'], + 'application/x-cdrdao-toc' => ['toc'], + 'application/x-cfs-compressed' => ['cfs'], + 'application/x-chat' => ['chat'], + 'application/x-chess-pgn' => ['pgn'], + 'application/x-chm' => ['chm'], + 'application/x-cisco-vpn-settings' => ['pcf'], + 'application/x-compress' => ['Z'], + 'application/x-compressed-tar' => ['tar.gz', 'tgz'], + 'application/x-conference' => ['nsc'], + 'application/x-coreldraw' => ['cdr'], + 'application/x-cpio' => ['cpio'], + 'application/x-cpio-compressed' => ['cpio.gz'], + 'application/x-csh' => ['csh'], + 'application/x-cue' => ['cue'], + 'application/x-dar' => ['dar'], + 'application/x-dbase' => ['dbf'], + 'application/x-dbf' => ['dbf'], + 'application/x-dc-rom' => ['dc'], + 'application/x-deb' => ['deb', 'udeb'], + 'application/x-debian-package' => ['deb', 'udeb'], + 'application/x-designer' => ['ui'], + 'application/x-desktop' => ['desktop', 'kdelnk'], + 'application/x-dgc-compressed' => ['dgc'], + 'application/x-dia-diagram' => ['dia'], + 'application/x-dia-shape' => ['shape'], + 'application/x-director' => ['dir', 'dcr', 'dxr', 'cst', 'cct', 'cxt', 'w3d', 'fgd', 'swa'], + 'application/x-docbook+xml' => ['dbk', 'docbook'], + 'application/x-doom' => ['wad'], + 'application/x-doom-wad' => ['wad'], + 'application/x-dtbncx+xml' => ['ncx'], + 'application/x-dtbook+xml' => ['dtb'], + 'application/x-dtbresource+xml' => ['res'], + 'application/x-dvi' => ['dvi'], + 'application/x-e-theme' => ['etheme'], + 'application/x-egon' => ['egon'], + 'application/x-emf' => ['emf'], + 'application/x-envoy' => ['evy'], + 'application/x-eva' => ['eva'], + 'application/x-fd-file' => ['fd', 'qd'], + 'application/x-fds-disk' => ['fds'], + 'application/x-fictionbook' => ['fb2'], + 'application/x-fictionbook+xml' => ['fb2'], + 'application/x-flash-video' => ['flv'], + 'application/x-fluid' => ['fl'], + 'application/x-font-afm' => ['afm'], + 'application/x-font-bdf' => ['bdf'], + 'application/x-font-ghostscript' => ['gsf'], + 'application/x-font-linux-psf' => ['psf'], + 'application/x-font-otf' => ['otf'], + 'application/x-font-pcf' => ['pcf', 'pcf.Z', 'pcf.gz'], + 'application/x-font-snf' => ['snf'], + 'application/x-font-speedo' => ['spd'], + 'application/x-font-ttf' => ['ttf'], + 'application/x-font-ttx' => ['ttx'], + 'application/x-font-type1' => ['pfa', 'pfb', 'pfm', 'afm', 'gsf'], + 'application/x-font-woff' => ['woff'], + 'application/x-frame' => ['fm'], + 'application/x-freearc' => ['arc'], + 'application/x-futuresplash' => ['spl'], + 'application/x-gameboy-color-rom' => ['gbc', 'cgb'], + 'application/x-gameboy-rom' => ['gb', 'sgb'], + 'application/x-gamecube-iso-image' => ['iso'], + 'application/x-gamecube-rom' => ['iso'], + 'application/x-gamegear-rom' => ['gg'], + 'application/x-gba-rom' => ['gba', 'agb'], + 'application/x-gca-compressed' => ['gca'], + 'application/x-gedcom' => ['ged', 'gedcom'], + 'application/x-genesis-32x-rom' => ['32x', 'mdx'], + 'application/x-genesis-rom' => ['gen', 'smd'], + 'application/x-gettext' => ['po'], + 'application/x-gettext-translation' => ['gmo', 'mo'], + 'application/x-glade' => ['glade'], + 'application/x-glulx' => ['ulx'], + 'application/x-gnome-app-info' => ['desktop', 'kdelnk'], + 'application/x-gnucash' => ['gnucash', 'gnc', 'xac'], + 'application/x-gnumeric' => ['gnumeric'], + 'application/x-gnuplot' => ['gp', 'gplt', 'gnuplot'], + 'application/x-go-sgf' => ['sgf'], + 'application/x-gpx' => ['gpx'], + 'application/x-gpx+xml' => ['gpx'], + 'application/x-gramps-xml' => ['gramps'], + 'application/x-graphite' => ['gra'], + 'application/x-gtar' => ['gtar', 'tar', 'gem'], + 'application/x-gtk-builder' => ['ui'], + 'application/x-gz-font-linux-psf' => ['psf.gz'], + 'application/x-gzdvi' => ['dvi.gz'], + 'application/x-gzip' => ['gz'], + 'application/x-gzpdf' => ['pdf.gz'], + 'application/x-gzpostscript' => ['ps.gz'], + 'application/x-hdf' => ['hdf', 'hdf4', 'h4', 'hdf5', 'h5'], + 'application/x-hfe-file' => ['hfe'], + 'application/x-hfe-floppy-image' => ['hfe'], + 'application/x-hwp' => ['hwp'], + 'application/x-hwt' => ['hwt'], + 'application/x-ica' => ['ica'], + 'application/x-install-instructions' => ['install'], + 'application/x-ipynb+json' => ['ipynb'], + 'application/x-iso9660-appimage' => ['appimage'], + 'application/x-iso9660-image' => ['iso', 'iso9660'], + 'application/x-it87' => ['it87'], + 'application/x-iwork-keynote-sffkey' => ['key'], + 'application/x-jar' => ['jar'], + 'application/x-java' => ['class'], + 'application/x-java-archive' => ['jar'], + 'application/x-java-class' => ['class'], + 'application/x-java-jce-keystore' => ['jceks'], + 'application/x-java-jnlp-file' => ['jnlp'], + 'application/x-java-keystore' => ['jks', 'ks'], + 'application/x-java-pack200' => ['pack'], + 'application/x-java-vm' => ['class'], + 'application/x-javascript' => ['js', 'jsm', 'mjs'], + 'application/x-jbuilder-project' => ['jpr', 'jpx'], + 'application/x-karbon' => ['karbon'], + 'application/x-kchart' => ['chrt'], + 'application/x-kexi-connectiondata' => ['kexic'], + 'application/x-kexiproject-shortcut' => ['kexis'], + 'application/x-kexiproject-sqlite' => ['kexi'], + 'application/x-kexiproject-sqlite2' => ['kexi'], + 'application/x-kexiproject-sqlite3' => ['kexi'], + 'application/x-kformula' => ['kfo'], + 'application/x-killustrator' => ['kil'], + 'application/x-kivio' => ['flw'], + 'application/x-kontour' => ['kon'], + 'application/x-kpovmodeler' => ['kpm'], + 'application/x-kpresenter' => ['kpr', 'kpt'], + 'application/x-krita' => ['kra'], + 'application/x-kspread' => ['ksp'], + 'application/x-kugar' => ['kud'], + 'application/x-kword' => ['kwd', 'kwt'], + 'application/x-latex' => ['latex'], + 'application/x-lha' => ['lha', 'lzh'], + 'application/x-lhz' => ['lhz'], + 'application/x-linguist' => ['ts'], + 'application/x-lotus123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], + 'application/x-lrzip' => ['lrz'], + 'application/x-lrzip-compressed-tar' => ['tar.lrz', 'tlrz'], + 'application/x-lyx' => ['lyx'], + 'application/x-lz4' => ['lz4'], + 'application/x-lz4-compressed-tar' => ['tar.lz4'], + 'application/x-lzh-compressed' => ['lzh', 'lha'], + 'application/x-lzip' => ['lz'], + 'application/x-lzip-compressed-tar' => ['tar.lz'], + 'application/x-lzma' => ['lzma'], + 'application/x-lzma-compressed-tar' => ['tar.lzma', 'tlz'], + 'application/x-lzop' => ['lzo'], + 'application/x-lzpdf' => ['pdf.lz'], + 'application/x-m4' => ['m4'], + 'application/x-magicpoint' => ['mgp'], + 'application/x-markaby' => ['mab'], + 'application/x-mathematica' => ['nb'], + 'application/x-mdb' => ['mdb'], + 'application/x-mie' => ['mie'], + 'application/x-mif' => ['mif'], + 'application/x-mimearchive' => ['mhtml', 'mht'], + 'application/x-mobipocket-ebook' => ['prc', 'mobi'], + 'application/x-ms-application' => ['application'], + 'application/x-ms-asx' => ['asx', 'wax', 'wvx', 'wmx'], + 'application/x-ms-dos-executable' => ['exe'], + 'application/x-ms-shortcut' => ['lnk'], + 'application/x-ms-wim' => ['wim', 'swm'], + 'application/x-ms-wmd' => ['wmd'], + 'application/x-ms-wmz' => ['wmz'], + 'application/x-ms-xbap' => ['xbap'], + 'application/x-msaccess' => ['mdb'], + 'application/x-msbinder' => ['obd'], + 'application/x-mscardfile' => ['crd'], + 'application/x-msclip' => ['clp'], + 'application/x-msdownload' => ['exe', 'dll', 'com', 'bat', 'msi'], + 'application/x-msexcel' => ['xls', 'xlc', 'xll', 'xlm', 'xlw', 'xla', 'xlt', 'xld'], + 'application/x-msi' => ['msi'], + 'application/x-msmediaview' => ['mvb', 'm13', 'm14'], + 'application/x-msmetafile' => ['wmf', 'wmz', 'emf', 'emz'], + 'application/x-msmoney' => ['mny'], + 'application/x-mspowerpoint' => ['ppz', 'ppt', 'pps', 'pot'], + 'application/x-mspublisher' => ['pub'], + 'application/x-msschedule' => ['scd'], + 'application/x-msterminal' => ['trm'], + 'application/x-mswinurl' => ['url'], + 'application/x-msword' => ['doc'], + 'application/x-mswrite' => ['wri'], + 'application/x-msx-rom' => ['msx'], + 'application/x-n64-rom' => ['n64', 'z64', 'v64'], + 'application/x-navi-animation' => ['ani'], + 'application/x-neo-geo-pocket-color-rom' => ['ngc'], + 'application/x-neo-geo-pocket-rom' => ['ngp'], + 'application/x-nes-rom' => ['nes', 'nez', 'unf', 'unif'], + 'application/x-netcdf' => ['nc', 'cdf'], + 'application/x-netshow-channel' => ['nsc'], + 'application/x-nintendo-ds-rom' => ['nds'], + 'application/x-nzb' => ['nzb'], + 'application/x-object' => ['o'], + 'application/x-ogg' => ['ogx'], + 'application/x-oleo' => ['oleo'], + 'application/x-pagemaker' => ['p65', 'pm', 'pm6', 'pmd'], + 'application/x-pak' => ['pak'], + 'application/x-palm-database' => ['prc', 'pdb', 'pqa', 'oprc'], + 'application/x-par2' => ['PAR2', 'par2'], + 'application/x-partial-download' => ['wkdownload', 'crdownload', 'part'], + 'application/x-pc-engine-rom' => ['pce'], + 'application/x-pcap' => ['pcap', 'cap', 'dmp'], + 'application/x-pdf' => ['pdf'], + 'application/x-perl' => ['pl', 'PL', 'pm', 'al', 'perl', 'pod', 't'], + 'application/x-photoshop' => ['psd'], + 'application/x-php' => ['php', 'php3', 'php4', 'php5', 'phps'], + 'application/x-pkcs12' => ['p12', 'pfx'], + 'application/x-pkcs7-certificates' => ['p7b', 'spc'], + 'application/x-pkcs7-certreqresp' => ['p7r'], + 'application/x-planperfect' => ['pln'], + 'application/x-pocket-word' => ['psw'], + 'application/x-pw' => ['pw'], + 'application/x-python-bytecode' => ['pyc', 'pyo'], + 'application/x-qpress' => ['qp'], + 'application/x-qtiplot' => ['qti', 'qti.gz'], + 'application/x-quattropro' => ['wb1', 'wb2', 'wb3'], + 'application/x-quicktime-media-link' => ['qtl'], + 'application/x-quicktimeplayer' => ['qtl'], + 'application/x-qw' => ['qif'], + 'application/x-rar' => ['rar'], + 'application/x-rar-compressed' => ['rar'], + 'application/x-raw-disk-image' => ['raw-disk-image', 'img'], + 'application/x-raw-disk-image-xz-compressed' => ['raw-disk-image.xz', 'img.xz'], + 'application/x-raw-floppy-disk-image' => ['fd', 'qd'], + 'application/x-redhat-package-manager' => ['rpm'], + 'application/x-reject' => ['rej'], + 'application/x-research-info-systems' => ['ris'], + 'application/x-rnc' => ['rnc'], + 'application/x-rpm' => ['rpm'], + 'application/x-ruby' => ['rb'], + 'application/x-sami' => ['smi', 'sami'], + 'application/x-sap-file' => ['sap'], + 'application/x-saturn-rom' => ['bin', 'iso'], + 'application/x-sdp' => ['sdp'], + 'application/x-sega-cd-rom' => ['bin', 'iso'], + 'application/x-sg1000-rom' => ['sg'], + 'application/x-sh' => ['sh'], + 'application/x-shar' => ['shar'], + 'application/x-shared-library-la' => ['la'], + 'application/x-sharedlib' => ['so'], + 'application/x-shellscript' => ['sh'], + 'application/x-shockwave-flash' => ['swf', 'spl'], + 'application/x-shorten' => ['shn'], + 'application/x-siag' => ['siag'], + 'application/x-silverlight-app' => ['xap'], + 'application/x-sit' => ['sit'], + 'application/x-smaf' => ['mmf', 'smaf'], + 'application/x-sms-rom' => ['sms'], + 'application/x-snes-rom' => ['sfc', 'smc'], + 'application/x-source-rpm' => ['src.rpm', 'spm'], + 'application/x-spss-por' => ['por'], + 'application/x-spss-sav' => ['sav', 'zsav'], + 'application/x-spss-savefile' => ['sav', 'zsav'], + 'application/x-sql' => ['sql'], + 'application/x-sqlite2' => ['sqlite2'], + 'application/x-sqlite3' => ['sqlite3'], + 'application/x-srt' => ['srt'], + 'application/x-stuffit' => ['sit'], + 'application/x-stuffitx' => ['sitx'], + 'application/x-subrip' => ['srt'], + 'application/x-sv4cpio' => ['sv4cpio'], + 'application/x-sv4crc' => ['sv4crc'], + 'application/x-t3vm-image' => ['t3'], + 'application/x-t602' => ['602'], + 'application/x-tads' => ['gam'], + 'application/x-tar' => ['tar', 'gtar', 'gem'], + 'application/x-tarz' => ['tar.Z', 'taz'], + 'application/x-tcl' => ['tcl'], + 'application/x-tex' => ['tex', 'ltx', 'sty', 'cls', 'dtx', 'ins', 'latex'], + 'application/x-tex-gf' => ['gf'], + 'application/x-tex-pk' => ['pk'], + 'application/x-tex-tfm' => ['tfm'], + 'application/x-texinfo' => ['texinfo', 'texi'], + 'application/x-tgif' => ['obj'], + 'application/x-theme' => ['theme'], + 'application/x-thomson-cartridge-memo7' => ['m7'], + 'application/x-thomson-cassette' => ['k7'], + 'application/x-thomson-sap-image' => ['sap'], + 'application/x-trash' => ['bak', 'old', 'sik'], + 'application/x-trig' => ['trig'], + 'application/x-troff' => ['tr', 'roff', 't'], + 'application/x-troff-man' => ['man'], + 'application/x-tzo' => ['tar.lzo', 'tzo'], + 'application/x-ufraw' => ['ufraw'], + 'application/x-ustar' => ['ustar'], + 'application/x-virtual-boy-rom' => ['vb'], + 'application/x-vnd.kde.kexi' => ['kexi'], + 'application/x-wais-source' => ['src'], + 'application/x-wbfs' => ['iso'], + 'application/x-wia' => ['iso'], + 'application/x-wii-iso-image' => ['iso'], + 'application/x-wii-rom' => ['iso'], + 'application/x-wii-wad' => ['wad'], + 'application/x-windows-themepack' => ['themepack'], + 'application/x-wmf' => ['wmf'], + 'application/x-wonderswan-color-rom' => ['wsc'], + 'application/x-wonderswan-rom' => ['ws'], + 'application/x-wordperfect' => ['wp', 'wp4', 'wp5', 'wp6', 'wpd', 'wpp'], + 'application/x-wpg' => ['wpg'], + 'application/x-wwf' => ['wwf'], + 'application/x-x509-ca-cert' => ['der', 'crt', 'cert', 'pem'], + 'application/x-xar' => ['xar', 'pkg'], + 'application/x-xbel' => ['xbel'], + 'application/x-xfig' => ['fig'], + 'application/x-xliff' => ['xlf', 'xliff'], + 'application/x-xliff+xml' => ['xlf'], + 'application/x-xpinstall' => ['xpi'], + 'application/x-xspf+xml' => ['xspf'], + 'application/x-xz' => ['xz'], + 'application/x-xz-compressed-tar' => ['tar.xz', 'txz'], + 'application/x-xzpdf' => ['pdf.xz'], + 'application/x-yaml' => ['yaml', 'yml'], + 'application/x-zip' => ['zip'], + 'application/x-zip-compressed' => ['zip'], + 'application/x-zip-compressed-fb2' => ['fb2.zip'], + 'application/x-zmachine' => ['z1', 'z2', 'z3', 'z4', 'z5', 'z6', 'z7', 'z8'], + 'application/x-zoo' => ['zoo'], + 'application/xaml+xml' => ['xaml'], + 'application/xcap-diff+xml' => ['xdf'], + 'application/xenc+xml' => ['xenc'], + 'application/xhtml+xml' => ['xhtml', 'xht'], + 'application/xliff+xml' => ['xlf', 'xliff'], + 'application/xml' => ['xml', 'xsl', 'xbl', 'xsd', 'rng'], + 'application/xml-dtd' => ['dtd'], + 'application/xml-external-parsed-entity' => ['ent'], + 'application/xop+xml' => ['xop'], + 'application/xproc+xml' => ['xpl'], + 'application/xps' => ['oxps', 'xps'], + 'application/xslt+xml' => ['xslt', 'xsl'], + 'application/xspf+xml' => ['xspf'], + 'application/xv+xml' => ['mxml', 'xhvml', 'xvml', 'xvm'], + 'application/yang' => ['yang'], + 'application/yin+xml' => ['yin'], + 'application/zip' => ['zip'], + 'application/zlib' => ['zz'], + 'audio/3gpp' => ['3gp', '3gpp', '3ga'], + 'audio/3gpp-encrypted' => ['3gp', '3gpp', '3ga'], + 'audio/3gpp2' => ['3g2', '3gp2', '3gpp2'], + 'audio/aac' => ['aac', 'adts', 'ass'], + 'audio/ac3' => ['ac3'], + 'audio/adpcm' => ['adp'], + 'audio/amr' => ['amr'], + 'audio/amr-encrypted' => ['amr'], + 'audio/amr-wb' => ['awb'], + 'audio/amr-wb-encrypted' => ['awb'], + 'audio/annodex' => ['axa'], + 'audio/basic' => ['au', 'snd'], + 'audio/flac' => ['flac'], + 'audio/imelody' => ['imy', 'ime'], + 'audio/m3u' => ['m3u', 'm3u8', 'vlc'], + 'audio/m4a' => ['m4a', 'f4a'], + 'audio/midi' => ['mid', 'midi', 'kar', 'rmi'], + 'audio/mobile-xmf' => ['xmf'], + 'audio/mp2' => ['mp2'], + 'audio/mp3' => ['mp3', 'mpga'], + 'audio/mp4' => ['m4a', 'mp4a', 'f4a'], + 'audio/mpeg' => ['mpga', 'mp2', 'mp2a', 'mp3', 'm2a', 'm3a'], + 'audio/mpegurl' => ['m3u', 'm3u8', 'vlc'], + 'audio/ogg' => ['oga', 'ogg', 'spx', 'opus'], + 'audio/prs.sid' => ['sid', 'psid'], + 'audio/s3m' => ['s3m'], + 'audio/scpls' => ['pls'], + 'audio/silk' => ['sil'], + 'audio/tta' => ['tta'], + 'audio/usac' => ['loas', 'xhe'], + 'audio/vnd.audible' => ['aa', 'aax'], + 'audio/vnd.audible.aax' => ['aa', 'aax'], + 'audio/vnd.dece.audio' => ['uva', 'uvva'], + 'audio/vnd.digital-winds' => ['eol'], + 'audio/vnd.dra' => ['dra'], + 'audio/vnd.dts' => ['dts'], + 'audio/vnd.dts.hd' => ['dtshd'], + 'audio/vnd.lucent.voice' => ['lvp'], + 'audio/vnd.m-realaudio' => ['ra', 'rax'], + 'audio/vnd.ms-playready.media.pya' => ['pya'], + 'audio/vnd.nuera.ecelp4800' => ['ecelp4800'], + 'audio/vnd.nuera.ecelp7470' => ['ecelp7470'], + 'audio/vnd.nuera.ecelp9600' => ['ecelp9600'], + 'audio/vnd.rip' => ['rip'], + 'audio/vnd.rn-realaudio' => ['ra', 'rax'], + 'audio/vnd.wave' => ['wav'], + 'audio/vorbis' => ['oga', 'ogg'], + 'audio/wav' => ['wav'], + 'audio/webm' => ['weba'], + 'audio/wma' => ['wma'], + 'audio/x-aac' => ['aac', 'adts', 'ass'], + 'audio/x-aifc' => ['aifc', 'aiffc'], + 'audio/x-aiff' => ['aif', 'aiff', 'aifc'], + 'audio/x-aiffc' => ['aifc', 'aiffc'], + 'audio/x-amzxml' => ['amz'], + 'audio/x-annodex' => ['axa'], + 'audio/x-ape' => ['ape'], + 'audio/x-caf' => ['caf'], + 'audio/x-dts' => ['dts'], + 'audio/x-dtshd' => ['dtshd'], + 'audio/x-flac' => ['flac'], + 'audio/x-flac+ogg' => ['oga', 'ogg'], + 'audio/x-gsm' => ['gsm'], + 'audio/x-hx-aac-adts' => ['aac', 'adts', 'ass'], + 'audio/x-imelody' => ['imy', 'ime'], + 'audio/x-iriver-pla' => ['pla'], + 'audio/x-it' => ['it'], + 'audio/x-m3u' => ['m3u', 'm3u8', 'vlc'], + 'audio/x-m4a' => ['m4a', 'f4a'], + 'audio/x-m4b' => ['m4b', 'f4b'], + 'audio/x-m4r' => ['m4r'], + 'audio/x-matroska' => ['mka'], + 'audio/x-midi' => ['mid', 'midi', 'kar'], + 'audio/x-minipsf' => ['minipsf'], + 'audio/x-mo3' => ['mo3'], + 'audio/x-mod' => ['mod', 'ult', 'uni', 'm15', 'mtm', '669', 'med'], + 'audio/x-mp2' => ['mp2'], + 'audio/x-mp3' => ['mp3', 'mpga'], + 'audio/x-mp3-playlist' => ['m3u', 'm3u8', 'vlc'], + 'audio/x-mpeg' => ['mp3', 'mpga'], + 'audio/x-mpegurl' => ['m3u', 'm3u8', 'vlc'], + 'audio/x-mpg' => ['mp3', 'mpga'], + 'audio/x-ms-asx' => ['asx', 'wax', 'wvx', 'wmx'], + 'audio/x-ms-wax' => ['wax'], + 'audio/x-ms-wma' => ['wma'], + 'audio/x-musepack' => ['mpc', 'mpp', 'mp+'], + 'audio/x-ogg' => ['oga', 'ogg', 'opus'], + 'audio/x-oggflac' => ['oga', 'ogg'], + 'audio/x-opus+ogg' => ['opus'], + 'audio/x-pn-audibleaudio' => ['aa', 'aax'], + 'audio/x-pn-realaudio' => ['ram', 'ra', 'rax'], + 'audio/x-pn-realaudio-plugin' => ['rmp'], + 'audio/x-psf' => ['psf'], + 'audio/x-psflib' => ['psflib'], + 'audio/x-rn-3gpp-amr' => ['3gp', '3gpp', '3ga'], + 'audio/x-rn-3gpp-amr-encrypted' => ['3gp', '3gpp', '3ga'], + 'audio/x-rn-3gpp-amr-wb' => ['3gp', '3gpp', '3ga'], + 'audio/x-rn-3gpp-amr-wb-encrypted' => ['3gp', '3gpp', '3ga'], + 'audio/x-s3m' => ['s3m'], + 'audio/x-scpls' => ['pls'], + 'audio/x-shorten' => ['shn'], + 'audio/x-speex' => ['spx'], + 'audio/x-speex+ogg' => ['oga', 'ogg'], + 'audio/x-stm' => ['stm'], + 'audio/x-tta' => ['tta'], + 'audio/x-voc' => ['voc'], + 'audio/x-vorbis' => ['oga', 'ogg'], + 'audio/x-vorbis+ogg' => ['oga', 'ogg'], + 'audio/x-wav' => ['wav'], + 'audio/x-wavpack' => ['wv', 'wvp'], + 'audio/x-wavpack-correction' => ['wvc'], + 'audio/x-xi' => ['xi'], + 'audio/x-xm' => ['xm'], + 'audio/x-xmf' => ['xmf'], + 'audio/xm' => ['xm'], + 'audio/xmf' => ['xmf'], + 'chemical/x-cdx' => ['cdx'], + 'chemical/x-cif' => ['cif'], + 'chemical/x-cmdf' => ['cmdf'], + 'chemical/x-cml' => ['cml'], + 'chemical/x-csml' => ['csml'], + 'chemical/x-xyz' => ['xyz'], + 'flv-application/octet-stream' => ['flv'], + 'font/collection' => ['ttc'], + 'font/otf' => ['otf'], + 'font/ttf' => ['ttf'], + 'font/woff' => ['woff', 'woff2'], + 'font/woff2' => ['woff2'], + 'image/bmp' => ['bmp', 'dib'], + 'image/cdr' => ['cdr'], + 'image/cgm' => ['cgm'], + 'image/emf' => ['emf'], + 'image/fax-g3' => ['g3'], + 'image/fits' => ['fits'], + 'image/g3fax' => ['g3'], + 'image/gif' => ['gif'], + 'image/heic' => ['heic', 'heif'], + 'image/heic-sequence' => ['heic', 'heif'], + 'image/heif' => ['heic', 'heif'], + 'image/heif-sequence' => ['heic', 'heif'], + 'image/ico' => ['ico'], + 'image/icon' => ['ico'], + 'image/ief' => ['ief'], + 'image/jp2' => ['jp2', 'jpg2'], + 'image/jpeg' => ['jpeg', 'jpg', 'jpe'], + 'image/jpeg2000' => ['jp2', 'jpg2'], + 'image/jpeg2000-image' => ['jp2', 'jpg2'], + 'image/jpm' => ['jpm', 'jpgm'], + 'image/jpx' => ['jpf', 'jpx'], + 'image/ktx' => ['ktx'], + 'image/openraster' => ['ora'], + 'image/pdf' => ['pdf'], + 'image/photoshop' => ['psd'], + 'image/pjpeg' => ['jpeg', 'jpg', 'jpe'], + 'image/png' => ['png'], + 'image/prs.btif' => ['btif'], + 'image/psd' => ['psd'], + 'image/rle' => ['rle'], + 'image/sgi' => ['sgi'], + 'image/svg' => ['svg'], + 'image/svg+xml' => ['svg', 'svgz'], + 'image/svg+xml-compressed' => ['svgz'], + 'image/tiff' => ['tiff', 'tif'], + 'image/vnd.adobe.photoshop' => ['psd'], + 'image/vnd.dece.graphic' => ['uvi', 'uvvi', 'uvg', 'uvvg'], + 'image/vnd.djvu' => ['djvu', 'djv'], + 'image/vnd.djvu+multipage' => ['djvu', 'djv'], + 'image/vnd.dvb.subtitle' => ['sub'], + 'image/vnd.dwg' => ['dwg'], + 'image/vnd.dxf' => ['dxf'], + 'image/vnd.fastbidsheet' => ['fbs'], + 'image/vnd.fpx' => ['fpx'], + 'image/vnd.fst' => ['fst'], + 'image/vnd.fujixerox.edmics-mmr' => ['mmr'], + 'image/vnd.fujixerox.edmics-rlc' => ['rlc'], + 'image/vnd.microsoft.icon' => ['ico'], + 'image/vnd.ms-modi' => ['mdi'], + 'image/vnd.ms-photo' => ['wdp'], + 'image/vnd.net-fpx' => ['npx'], + 'image/vnd.rn-realpix' => ['rp'], + 'image/vnd.wap.wbmp' => ['wbmp'], + 'image/vnd.xiff' => ['xif'], + 'image/vnd.zbrush.pcx' => ['pcx'], + 'image/webp' => ['webp'], + 'image/wmf' => ['wmf'], + 'image/x-3ds' => ['3ds'], + 'image/x-adobe-dng' => ['dng'], + 'image/x-applix-graphics' => ['ag'], + 'image/x-bmp' => ['bmp', 'dib'], + 'image/x-bzeps' => ['eps.bz2', 'epsi.bz2', 'epsf.bz2'], + 'image/x-canon-cr2' => ['cr2'], + 'image/x-canon-crw' => ['crw'], + 'image/x-cdr' => ['cdr'], + 'image/x-cmu-raster' => ['ras'], + 'image/x-cmx' => ['cmx'], + 'image/x-compressed-xcf' => ['xcf.gz', 'xcf.bz2'], + 'image/x-dds' => ['dds'], + 'image/x-djvu' => ['djvu', 'djv'], + 'image/x-emf' => ['emf'], + 'image/x-eps' => ['eps', 'epsi', 'epsf'], + 'image/x-exr' => ['exr'], + 'image/x-fits' => ['fits'], + 'image/x-freehand' => ['fh', 'fhc', 'fh4', 'fh5', 'fh7'], + 'image/x-fuji-raf' => ['raf'], + 'image/x-gimp-gbr' => ['gbr'], + 'image/x-gimp-gih' => ['gih'], + 'image/x-gimp-pat' => ['pat'], + 'image/x-gzeps' => ['eps.gz', 'epsi.gz', 'epsf.gz'], + 'image/x-icb' => ['tga', 'icb', 'tpic', 'vda', 'vst'], + 'image/x-icns' => ['icns'], + 'image/x-ico' => ['ico'], + 'image/x-icon' => ['ico'], + 'image/x-iff' => ['iff', 'ilbm', 'lbm'], + 'image/x-ilbm' => ['iff', 'ilbm', 'lbm'], + 'image/x-jng' => ['jng'], + 'image/x-jp2-codestream' => ['j2c', 'j2k', 'jpc'], + 'image/x-jpeg2000-image' => ['jp2', 'jpg2'], + 'image/x-kodak-dcr' => ['dcr'], + 'image/x-kodak-k25' => ['k25'], + 'image/x-kodak-kdc' => ['kdc'], + 'image/x-lwo' => ['lwo', 'lwob'], + 'image/x-lws' => ['lws'], + 'image/x-macpaint' => ['pntg'], + 'image/x-minolta-mrw' => ['mrw'], + 'image/x-mrsid-image' => ['sid'], + 'image/x-ms-bmp' => ['bmp', 'dib'], + 'image/x-msod' => ['msod'], + 'image/x-nikon-nef' => ['nef'], + 'image/x-olympus-orf' => ['orf'], + 'image/x-panasonic-raw' => ['raw'], + 'image/x-panasonic-raw2' => ['rw2'], + 'image/x-panasonic-rw' => ['raw'], + 'image/x-panasonic-rw2' => ['rw2'], + 'image/x-pcx' => ['pcx'], + 'image/x-pentax-pef' => ['pef'], + 'image/x-photo-cd' => ['pcd'], + 'image/x-photoshop' => ['psd'], + 'image/x-pict' => ['pic', 'pct', 'pict', 'pict1', 'pict2'], + 'image/x-portable-anymap' => ['pnm'], + 'image/x-portable-bitmap' => ['pbm'], + 'image/x-portable-graymap' => ['pgm'], + 'image/x-portable-pixmap' => ['ppm'], + 'image/x-psd' => ['psd'], + 'image/x-quicktime' => ['qtif', 'qif'], + 'image/x-rgb' => ['rgb'], + 'image/x-sgi' => ['sgi'], + 'image/x-sigma-x3f' => ['x3f'], + 'image/x-skencil' => ['sk', 'sk1'], + 'image/x-sony-arw' => ['arw'], + 'image/x-sony-sr2' => ['sr2'], + 'image/x-sony-srf' => ['srf'], + 'image/x-sun-raster' => ['sun'], + 'image/x-tga' => ['tga', 'icb', 'tpic', 'vda', 'vst'], + 'image/x-win-bitmap' => ['cur'], + 'image/x-win-metafile' => ['wmf'], + 'image/x-wmf' => ['wmf'], + 'image/x-xbitmap' => ['xbm'], + 'image/x-xcf' => ['xcf'], + 'image/x-xfig' => ['fig'], + 'image/x-xpixmap' => ['xpm'], + 'image/x-xpm' => ['xpm'], + 'image/x-xwindowdump' => ['xwd'], + 'image/x.djvu' => ['djvu', 'djv'], + 'message/rfc822' => ['eml', 'mime'], + 'model/iges' => ['igs', 'iges'], + 'model/mesh' => ['msh', 'mesh', 'silo'], + 'model/stl' => ['stl'], + 'model/vnd.collada+xml' => ['dae'], + 'model/vnd.dwf' => ['dwf'], + 'model/vnd.gdl' => ['gdl'], + 'model/vnd.gtw' => ['gtw'], + 'model/vnd.mts' => ['mts'], + 'model/vnd.vtu' => ['vtu'], + 'model/vrml' => ['wrl', 'vrml', 'vrm'], + 'model/x.stl-ascii' => ['stl'], + 'model/x.stl-binary' => ['stl'], + 'model/x3d+binary' => ['x3db', 'x3dbz'], + 'model/x3d+vrml' => ['x3dv', 'x3dvz'], + 'model/x3d+xml' => ['x3d', 'x3dz'], + 'text/cache-manifest' => ['appcache', 'manifest'], + 'text/calendar' => ['ics', 'ifb', 'vcs'], + 'text/css' => ['css'], + 'text/csv' => ['csv'], + 'text/csv-schema' => ['csvs'], + 'text/directory' => ['vcard', 'vcf', 'vct', 'gcrd'], + 'text/ecmascript' => ['es'], + 'text/gedcom' => ['ged', 'gedcom'], + 'text/google-video-pointer' => ['gvp'], + 'text/html' => ['html', 'htm'], + 'text/ico' => ['ico'], + 'text/javascript' => ['js', 'jsm', 'mjs'], + 'text/markdown' => ['md', 'mkd', 'markdown'], + 'text/mathml' => ['mml'], + 'text/n3' => ['n3'], + 'text/plain' => ['txt', 'text', 'conf', 'def', 'list', 'log', 'in', 'asc'], + 'text/prs.lines.tag' => ['dsc'], + 'text/rdf' => ['rdf', 'rdfs', 'owl'], + 'text/richtext' => ['rtx'], + 'text/rss' => ['rss'], + 'text/rtf' => ['rtf'], + 'text/rust' => ['rs'], + 'text/sgml' => ['sgml', 'sgm'], + 'text/spreadsheet' => ['sylk', 'slk'], + 'text/tab-separated-values' => ['tsv'], + 'text/troff' => ['t', 'tr', 'roff', 'man', 'me', 'ms'], + 'text/turtle' => ['ttl'], + 'text/uri-list' => ['uri', 'uris', 'urls'], + 'text/vcard' => ['vcard', 'vcf', 'vct', 'gcrd'], + 'text/vnd.curl' => ['curl'], + 'text/vnd.curl.dcurl' => ['dcurl'], + 'text/vnd.curl.mcurl' => ['mcurl'], + 'text/vnd.curl.scurl' => ['scurl'], + 'text/vnd.dvb.subtitle' => ['sub'], + 'text/vnd.fly' => ['fly'], + 'text/vnd.fmi.flexstor' => ['flx'], + 'text/vnd.graphviz' => ['gv', 'dot'], + 'text/vnd.in3d.3dml' => ['3dml'], + 'text/vnd.in3d.spot' => ['spot'], + 'text/vnd.qt.linguist' => ['ts'], + 'text/vnd.rn-realtext' => ['rt'], + 'text/vnd.sun.j2me.app-descriptor' => ['jad'], + 'text/vnd.trolltech.linguist' => ['ts'], + 'text/vnd.wap.wml' => ['wml'], + 'text/vnd.wap.wmlscript' => ['wmls'], + 'text/vtt' => ['vtt'], + 'text/x-adasrc' => ['adb', 'ads'], + 'text/x-asm' => ['s', 'asm'], + 'text/x-bibtex' => ['bib'], + 'text/x-c' => ['c', 'cc', 'cxx', 'cpp', 'h', 'hh', 'dic'], + 'text/x-c++hdr' => ['hh', 'hp', 'hpp', 'h++', 'hxx'], + 'text/x-c++src' => ['cpp', 'cxx', 'cc', 'C', 'c++'], + 'text/x-chdr' => ['h'], + 'text/x-cmake' => ['cmake'], + 'text/x-cobol' => ['cbl', 'cob'], + 'text/x-comma-separated-values' => ['csv'], + 'text/x-csharp' => ['cs'], + 'text/x-csrc' => ['c'], + 'text/x-csv' => ['csv'], + 'text/x-dbus-service' => ['service'], + 'text/x-dcl' => ['dcl'], + 'text/x-diff' => ['diff', 'patch'], + 'text/x-dsl' => ['dsl'], + 'text/x-dsrc' => ['d', 'di'], + 'text/x-dtd' => ['dtd'], + 'text/x-eiffel' => ['e', 'eif'], + 'text/x-emacs-lisp' => ['el'], + 'text/x-erlang' => ['erl'], + 'text/x-fortran' => ['f', 'for', 'f77', 'f90', 'f95'], + 'text/x-genie' => ['gs'], + 'text/x-gettext-translation' => ['po'], + 'text/x-gettext-translation-template' => ['pot'], + 'text/x-gherkin' => ['feature'], + 'text/x-go' => ['go'], + 'text/x-google-video-pointer' => ['gvp'], + 'text/x-haskell' => ['hs'], + 'text/x-idl' => ['idl'], + 'text/x-imelody' => ['imy', 'ime'], + 'text/x-iptables' => ['iptables'], + 'text/x-java' => ['java'], + 'text/x-java-source' => ['java'], + 'text/x-ldif' => ['ldif'], + 'text/x-lilypond' => ['ly'], + 'text/x-literate-haskell' => ['lhs'], + 'text/x-log' => ['log'], + 'text/x-lua' => ['lua'], + 'text/x-lyx' => ['lyx'], + 'text/x-makefile' => ['mk', 'mak'], + 'text/x-markdown' => ['md', 'mkd', 'markdown'], + 'text/x-matlab' => ['m'], + 'text/x-microdvd' => ['sub'], + 'text/x-moc' => ['moc'], + 'text/x-modelica' => ['mo'], + 'text/x-mof' => ['mof'], + 'text/x-mpsub' => ['sub'], + 'text/x-mrml' => ['mrml', 'mrl'], + 'text/x-ms-regedit' => ['reg'], + 'text/x-mup' => ['mup', 'not'], + 'text/x-nfo' => ['nfo'], + 'text/x-objcsrc' => ['m'], + 'text/x-ocaml' => ['ml', 'mli'], + 'text/x-ocl' => ['ocl'], + 'text/x-octave' => ['m'], + 'text/x-ooc' => ['ooc'], + 'text/x-opencl-src' => ['cl'], + 'text/x-opml' => ['opml'], + 'text/x-opml+xml' => ['opml'], + 'text/x-pascal' => ['p', 'pas'], + 'text/x-patch' => ['diff', 'patch'], + 'text/x-perl' => ['pl', 'PL', 'pm', 'al', 'perl', 'pod', 't'], + 'text/x-po' => ['po'], + 'text/x-pot' => ['pot'], + 'text/x-python' => ['py', 'pyx', 'wsgi'], + 'text/x-python3' => ['py', 'py3', 'py3x'], + 'text/x-qml' => ['qml', 'qmltypes', 'qmlproject'], + 'text/x-reject' => ['rej'], + 'text/x-rpm-spec' => ['spec'], + 'text/x-sass' => ['sass'], + 'text/x-scala' => ['scala'], + 'text/x-scheme' => ['scm', 'ss'], + 'text/x-scss' => ['scss'], + 'text/x-setext' => ['etx'], + 'text/x-sfv' => ['sfv'], + 'text/x-sh' => ['sh'], + 'text/x-sql' => ['sql'], + 'text/x-ssa' => ['ssa', 'ass'], + 'text/x-subviewer' => ['sub'], + 'text/x-svhdr' => ['svh'], + 'text/x-svsrc' => ['sv'], + 'text/x-systemd-unit' => ['automount', 'device', 'mount', 'path', 'scope', 'service', 'slice', 'socket', 'swap', 'target', 'timer'], + 'text/x-tcl' => ['tcl', 'tk'], + 'text/x-tex' => ['tex', 'ltx', 'sty', 'cls', 'dtx', 'ins', 'latex'], + 'text/x-texinfo' => ['texi', 'texinfo'], + 'text/x-troff' => ['tr', 'roff', 't'], + 'text/x-troff-me' => ['me'], + 'text/x-troff-mm' => ['mm'], + 'text/x-troff-ms' => ['ms'], + 'text/x-twig' => ['twig'], + 'text/x-txt2tags' => ['t2t'], + 'text/x-uil' => ['uil'], + 'text/x-uuencode' => ['uu', 'uue'], + 'text/x-vala' => ['vala', 'vapi'], + 'text/x-vcalendar' => ['vcs', 'ics'], + 'text/x-vcard' => ['vcf', 'vcard', 'vct', 'gcrd'], + 'text/x-verilog' => ['v'], + 'text/x-vhdl' => ['vhd', 'vhdl'], + 'text/x-xmi' => ['xmi'], + 'text/x-xslfo' => ['fo', 'xslfo'], + 'text/x-yaml' => ['yaml', 'yml'], + 'text/x.gcode' => ['gcode'], + 'text/xml' => ['xml', 'xbl', 'xsd', 'rng'], + 'text/xml-external-parsed-entity' => ['ent'], + 'text/yaml' => ['yaml', 'yml'], + 'video/3gp' => ['3gp', '3gpp', '3ga'], + 'video/3gpp' => ['3gp', '3gpp', '3ga'], + 'video/3gpp-encrypted' => ['3gp', '3gpp', '3ga'], + 'video/3gpp2' => ['3g2', '3gp2', '3gpp2'], + 'video/annodex' => ['axv'], + 'video/avi' => ['avi', 'avf', 'divx'], + 'video/divx' => ['avi', 'avf', 'divx'], + 'video/dv' => ['dv'], + 'video/fli' => ['fli', 'flc'], + 'video/flv' => ['flv'], + 'video/h261' => ['h261'], + 'video/h263' => ['h263'], + 'video/h264' => ['h264'], + 'video/jpeg' => ['jpgv'], + 'video/jpm' => ['jpm', 'jpgm'], + 'video/mj2' => ['mj2', 'mjp2'], + 'video/mp2t' => ['m2t', 'm2ts', 'ts', 'mts', 'cpi', 'clpi', 'mpl', 'mpls', 'bdm', 'bdmv'], + 'video/mp4' => ['mp4', 'mp4v', 'mpg4', 'm4v', 'f4v', 'lrv'], + 'video/mp4v-es' => ['mp4', 'm4v', 'f4v', 'lrv'], + 'video/mpeg' => ['mpeg', 'mpg', 'mpe', 'm1v', 'm2v', 'mp2', 'vob'], + 'video/mpeg-system' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], + 'video/msvideo' => ['avi', 'avf', 'divx'], + 'video/ogg' => ['ogv', 'ogg'], + 'video/quicktime' => ['qt', 'mov', 'moov', 'qtvr'], + 'video/vivo' => ['viv', 'vivo'], + 'video/vnd.dece.hd' => ['uvh', 'uvvh'], + 'video/vnd.dece.mobile' => ['uvm', 'uvvm'], + 'video/vnd.dece.pd' => ['uvp', 'uvvp'], + 'video/vnd.dece.sd' => ['uvs', 'uvvs'], + 'video/vnd.dece.video' => ['uvv', 'uvvv'], + 'video/vnd.divx' => ['avi', 'avf', 'divx'], + 'video/vnd.dvb.file' => ['dvb'], + 'video/vnd.fvt' => ['fvt'], + 'video/vnd.mpegurl' => ['mxu', 'm4u', 'm1u'], + 'video/vnd.ms-playready.media.pyv' => ['pyv'], + 'video/vnd.rn-realvideo' => ['rv', 'rvx'], + 'video/vnd.uvvu.mp4' => ['uvu', 'uvvu'], + 'video/vnd.vivo' => ['viv', 'vivo'], + 'video/webm' => ['webm'], + 'video/x-anim' => ['anim[1-9j]'], + 'video/x-annodex' => ['axv'], + 'video/x-avi' => ['avi', 'avf', 'divx'], + 'video/x-f4v' => ['f4v'], + 'video/x-fli' => ['fli', 'flc'], + 'video/x-flic' => ['fli', 'flc'], + 'video/x-flv' => ['flv'], + 'video/x-javafx' => ['fxm'], + 'video/x-m4v' => ['m4v', 'mp4', 'f4v', 'lrv'], + 'video/x-matroska' => ['mkv', 'mk3d', 'mks'], + 'video/x-matroska-3d' => ['mk3d'], + 'video/x-mjpeg' => ['mjpeg', 'mjpg'], + 'video/x-mng' => ['mng'], + 'video/x-mpeg' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], + 'video/x-mpeg-system' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], + 'video/x-mpeg2' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], + 'video/x-mpegurl' => ['m1u', 'm4u', 'mxu'], + 'video/x-ms-asf' => ['asf', 'asx'], + 'video/x-ms-asf-plugin' => ['asf'], + 'video/x-ms-vob' => ['vob'], + 'video/x-ms-wax' => ['asx', 'wax', 'wvx', 'wmx'], + 'video/x-ms-wm' => ['wm', 'asf'], + 'video/x-ms-wmv' => ['wmv'], + 'video/x-ms-wmx' => ['wmx', 'asx', 'wax', 'wvx'], + 'video/x-ms-wvx' => ['wvx', 'asx', 'wax', 'wmx'], + 'video/x-msvideo' => ['avi', 'avf', 'divx'], + 'video/x-nsv' => ['nsv'], + 'video/x-ogg' => ['ogv', 'ogg'], + 'video/x-ogm' => ['ogm'], + 'video/x-ogm+ogg' => ['ogm'], + 'video/x-real-video' => ['rv', 'rvx'], + 'video/x-sgi-movie' => ['movie'], + 'video/x-smv' => ['smv'], + 'video/x-theora' => ['ogg'], + 'video/x-theora+ogg' => ['ogg'], + 'x-conference/x-cooltalk' => ['ice'], + 'x-epoc/x-sisx-app' => ['sisx'], + 'zz-application/zz-winassoc-123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], + 'zz-application/zz-winassoc-cab' => ['cab'], + 'zz-application/zz-winassoc-cdr' => ['cdr'], + 'zz-application/zz-winassoc-doc' => ['doc'], + 'zz-application/zz-winassoc-hlp' => ['hlp'], + 'zz-application/zz-winassoc-mdb' => ['mdb'], + 'zz-application/zz-winassoc-uu' => ['uue'], + 'zz-application/zz-winassoc-xls' => ['xls', 'xlc', 'xll', 'xlm', 'xlw', 'xla', 'xlt', 'xld'], + ]; + + private static $reverseMap = [ + '32x' => ['application/x-genesis-32x-rom'], + '3dml' => ['text/vnd.in3d.3dml'], + '3ds' => ['image/x-3ds'], + '3g2' => ['audio/3gpp2', 'video/3gpp2'], + '3ga' => ['audio/3gpp', 'audio/3gpp-encrypted', 'audio/x-rn-3gpp-amr', 'audio/x-rn-3gpp-amr-encrypted', 'audio/x-rn-3gpp-amr-wb', 'audio/x-rn-3gpp-amr-wb-encrypted', 'video/3gp', 'video/3gpp', 'video/3gpp-encrypted'], + '3gp' => ['audio/3gpp', 'audio/3gpp-encrypted', 'audio/x-rn-3gpp-amr', 'audio/x-rn-3gpp-amr-encrypted', 'audio/x-rn-3gpp-amr-wb', 'audio/x-rn-3gpp-amr-wb-encrypted', 'video/3gp', 'video/3gpp', 'video/3gpp-encrypted'], + '3gp2' => ['audio/3gpp2', 'video/3gpp2'], + '3gpp' => ['audio/3gpp', 'audio/3gpp-encrypted', 'audio/x-rn-3gpp-amr', 'audio/x-rn-3gpp-amr-encrypted', 'audio/x-rn-3gpp-amr-wb', 'audio/x-rn-3gpp-amr-wb-encrypted', 'video/3gp', 'video/3gpp', 'video/3gpp-encrypted'], + '3gpp2' => ['audio/3gpp2', 'video/3gpp2'], + '7z' => ['application/x-7z-compressed'], + 'BLEND' => ['application/x-blender'], + 'C' => ['text/x-c++src'], + 'PAR2' => ['application/x-par2'], + 'PL' => ['application/x-perl', 'text/x-perl'], + 'Z' => ['application/x-compress'], + 'a' => ['application/x-archive'], + 'a26' => ['application/x-atari-2600-rom'], + 'a78' => ['application/x-atari-7800-rom'], + 'aa' => ['audio/vnd.audible', 'audio/vnd.audible.aax', 'audio/x-pn-audibleaudio'], + 'aab' => ['application/x-authorware-bin'], + 'aac' => ['audio/aac', 'audio/x-aac', 'audio/x-hx-aac-adts'], + 'aam' => ['application/x-authorware-map'], + 'aas' => ['application/x-authorware-seg'], + 'aax' => ['audio/vnd.audible', 'audio/vnd.audible.aax', 'audio/x-pn-audibleaudio'], + 'abw' => ['application/x-abiword'], + 'abw.CRASHED' => ['application/x-abiword'], + 'abw.gz' => ['application/x-abiword'], + 'ac' => ['application/pkix-attr-cert'], + 'ac3' => ['audio/ac3'], + 'acc' => ['application/vnd.americandynamics.acc'], + 'ace' => ['application/x-ace', 'application/x-ace-compressed'], + 'acu' => ['application/vnd.acucobol'], + 'acutc' => ['application/vnd.acucorp'], + 'adb' => ['text/x-adasrc'], + 'adf' => ['application/x-amiga-disk-format'], + 'adp' => ['audio/adpcm'], + 'ads' => ['text/x-adasrc'], + 'adts' => ['audio/aac', 'audio/x-aac', 'audio/x-hx-aac-adts'], + 'aep' => ['application/vnd.audiograph'], + 'afm' => ['application/x-font-afm', 'application/x-font-type1'], + 'afp' => ['application/vnd.ibm.modcap'], + 'ag' => ['image/x-applix-graphics'], + 'agb' => ['application/x-gba-rom'], + 'ahead' => ['application/vnd.ahead.space'], + 'ai' => ['application/illustrator', 'application/postscript', 'application/vnd.adobe.illustrator'], + 'aif' => ['audio/x-aiff'], + 'aifc' => ['audio/x-aifc', 'audio/x-aiff', 'audio/x-aiffc'], + 'aiff' => ['audio/x-aiff'], + 'aiffc' => ['audio/x-aifc', 'audio/x-aiffc'], + 'air' => ['application/vnd.adobe.air-application-installer-package+zip'], + 'ait' => ['application/vnd.dvb.ait'], + 'al' => ['application/x-perl', 'text/x-perl'], + 'alz' => ['application/x-alz'], + 'ami' => ['application/vnd.amiga.ami'], + 'amr' => ['audio/amr', 'audio/amr-encrypted'], + 'amz' => ['audio/x-amzxml'], + 'ani' => ['application/x-navi-animation'], + 'anim[1-9j]' => ['video/x-anim'], + 'anx' => ['application/annodex', 'application/x-annodex'], + 'ape' => ['audio/x-ape'], + 'apk' => ['application/vnd.android.package-archive'], + 'appcache' => ['text/cache-manifest'], + 'appimage' => ['application/vnd.appimage', 'application/x-iso9660-appimage'], + 'application' => ['application/x-ms-application'], + 'apr' => ['application/vnd.lotus-approach'], + 'aps' => ['application/postscript'], + 'ar' => ['application/x-archive'], + 'arc' => ['application/x-freearc'], + 'arj' => ['application/x-arj'], + 'arw' => ['image/x-sony-arw'], + 'as' => ['application/x-applix-spreadsheet'], + 'asc' => ['application/pgp', 'application/pgp-encrypted', 'application/pgp-keys', 'application/pgp-signature', 'text/plain'], + 'asf' => ['application/vnd.ms-asf', 'video/x-ms-asf', 'video/x-ms-asf-plugin', 'video/x-ms-wm'], + 'asm' => ['text/x-asm'], + 'aso' => ['application/vnd.accpac.simply.aso'], + 'asp' => ['application/x-asp'], + 'ass' => ['audio/aac', 'audio/x-aac', 'audio/x-hx-aac-adts', 'text/x-ssa'], + 'asx' => ['application/x-ms-asx', 'audio/x-ms-asx', 'video/x-ms-asf', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], + 'atc' => ['application/vnd.acucorp'], + 'atom' => ['application/atom+xml'], + 'atomcat' => ['application/atomcat+xml'], + 'atomsvc' => ['application/atomsvc+xml'], + 'atx' => ['application/vnd.antix.game-component'], + 'au' => ['audio/basic'], + 'automount' => ['text/x-systemd-unit'], + 'avf' => ['video/avi', 'video/divx', 'video/msvideo', 'video/vnd.divx', 'video/x-avi', 'video/x-msvideo'], + 'avi' => ['video/avi', 'video/divx', 'video/msvideo', 'video/vnd.divx', 'video/x-avi', 'video/x-msvideo'], + 'aw' => ['application/applixware', 'application/x-applix-word'], + 'awb' => ['audio/amr-wb', 'audio/amr-wb-encrypted'], + 'awk' => ['application/x-awk'], + 'axa' => ['audio/annodex', 'audio/x-annodex'], + 'axv' => ['video/annodex', 'video/x-annodex'], + 'azf' => ['application/vnd.airzip.filesecure.azf'], + 'azs' => ['application/vnd.airzip.filesecure.azs'], + 'azw' => ['application/vnd.amazon.ebook'], + 'bak' => ['application/x-trash'], + 'bat' => ['application/x-msdownload'], + 'bcpio' => ['application/x-bcpio'], + 'bdf' => ['application/x-font-bdf'], + 'bdm' => ['application/vnd.syncml.dm+wbxml', 'video/mp2t'], + 'bdmv' => ['video/mp2t'], + 'bed' => ['application/vnd.realvnc.bed'], + 'bh2' => ['application/vnd.fujitsu.oasysprs'], + 'bib' => ['text/x-bibtex'], + 'bin' => ['application/octet-stream', 'application/x-saturn-rom', 'application/x-sega-cd-rom'], + 'blb' => ['application/x-blorb'], + 'blend' => ['application/x-blender'], + 'blender' => ['application/x-blender'], + 'blorb' => ['application/x-blorb'], + 'bmi' => ['application/vnd.bmi'], + 'bmp' => ['image/bmp', 'image/x-bmp', 'image/x-ms-bmp'], + 'book' => ['application/vnd.framemaker'], + 'box' => ['application/vnd.previewsystems.box'], + 'boz' => ['application/x-bzip2'], + 'bpk' => ['application/octet-stream'], + 'bsdiff' => ['application/x-bsdiff'], + 'btif' => ['image/prs.btif'], + 'bz' => ['application/x-bzip', 'application/x-bzip2'], + 'bz2' => ['application/x-bz2', 'application/x-bzip', 'application/x-bzip2'], + 'c' => ['text/x-c', 'text/x-csrc'], + 'c++' => ['text/x-c++src'], + 'c11amc' => ['application/vnd.cluetrust.cartomobile-config'], + 'c11amz' => ['application/vnd.cluetrust.cartomobile-config-pkg'], + 'c4d' => ['application/vnd.clonk.c4group'], + 'c4f' => ['application/vnd.clonk.c4group'], + 'c4g' => ['application/vnd.clonk.c4group'], + 'c4p' => ['application/vnd.clonk.c4group'], + 'c4u' => ['application/vnd.clonk.c4group'], + 'cab' => ['application/vnd.ms-cab-compressed', 'zz-application/zz-winassoc-cab'], + 'caf' => ['audio/x-caf'], + 'cap' => ['application/pcap', 'application/vnd.tcpdump.pcap', 'application/x-pcap'], + 'car' => ['application/vnd.curl.car'], + 'cat' => ['application/vnd.ms-pki.seccat'], + 'cb7' => ['application/x-cb7', 'application/x-cbr'], + 'cba' => ['application/x-cbr'], + 'cbl' => ['text/x-cobol'], + 'cbr' => ['application/vnd.comicbook-rar', 'application/x-cbr'], + 'cbt' => ['application/x-cbr', 'application/x-cbt'], + 'cbz' => ['application/vnd.comicbook+zip', 'application/x-cbr', 'application/x-cbz'], + 'cc' => ['text/x-c', 'text/x-c++src'], + 'ccmx' => ['application/x-ccmx'], + 'cct' => ['application/x-director'], + 'ccxml' => ['application/ccxml+xml'], + 'cdbcmsg' => ['application/vnd.contact.cmsg'], + 'cdf' => ['application/x-netcdf'], + 'cdkey' => ['application/vnd.mediastation.cdkey'], + 'cdmia' => ['application/cdmi-capability'], + 'cdmic' => ['application/cdmi-container'], + 'cdmid' => ['application/cdmi-domain'], + 'cdmio' => ['application/cdmi-object'], + 'cdmiq' => ['application/cdmi-queue'], + 'cdr' => ['application/cdr', 'application/coreldraw', 'application/vnd.corel-draw', 'application/x-cdr', 'application/x-coreldraw', 'image/cdr', 'image/x-cdr', 'zz-application/zz-winassoc-cdr'], + 'cdx' => ['chemical/x-cdx'], + 'cdxml' => ['application/vnd.chemdraw+xml'], + 'cdy' => ['application/vnd.cinderella'], + 'cer' => ['application/pkix-cert'], + 'cert' => ['application/x-x509-ca-cert'], + 'cfs' => ['application/x-cfs-compressed'], + 'cgb' => ['application/x-gameboy-color-rom'], + 'cgm' => ['image/cgm'], + 'chat' => ['application/x-chat'], + 'chm' => ['application/vnd.ms-htmlhelp', 'application/x-chm'], + 'chrt' => ['application/vnd.kde.kchart', 'application/x-kchart'], + 'cif' => ['chemical/x-cif'], + 'cii' => ['application/vnd.anser-web-certificate-issue-initiation'], + 'cil' => ['application/vnd.ms-artgalry'], + 'cl' => ['text/x-opencl-src'], + 'cla' => ['application/vnd.claymore'], + 'class' => ['application/java', 'application/java-byte-code', 'application/java-vm', 'application/x-java', 'application/x-java-class', 'application/x-java-vm'], + 'clkk' => ['application/vnd.crick.clicker.keyboard'], + 'clkp' => ['application/vnd.crick.clicker.palette'], + 'clkt' => ['application/vnd.crick.clicker.template'], + 'clkw' => ['application/vnd.crick.clicker.wordbank'], + 'clkx' => ['application/vnd.crick.clicker'], + 'clp' => ['application/x-msclip'], + 'clpi' => ['video/mp2t'], + 'cls' => ['application/x-tex', 'text/x-tex'], + 'cmake' => ['text/x-cmake'], + 'cmc' => ['application/vnd.cosmocaller'], + 'cmdf' => ['chemical/x-cmdf'], + 'cml' => ['chemical/x-cml'], + 'cmp' => ['application/vnd.yellowriver-custom-menu'], + 'cmx' => ['image/x-cmx'], + 'cob' => ['text/x-cobol'], + 'cod' => ['application/vnd.rim.cod'], + 'coffee' => ['application/vnd.coffeescript'], + 'com' => ['application/x-msdownload'], + 'conf' => ['text/plain'], + 'cpi' => ['video/mp2t'], + 'cpio' => ['application/x-cpio'], + 'cpio.gz' => ['application/x-cpio-compressed'], + 'cpp' => ['text/x-c', 'text/x-c++src'], + 'cpt' => ['application/mac-compactpro'], + 'cr2' => ['image/x-canon-cr2'], + 'crd' => ['application/x-mscardfile'], + 'crdownload' => ['application/x-partial-download'], + 'crl' => ['application/pkix-crl'], + 'crt' => ['application/x-x509-ca-cert'], + 'crw' => ['image/x-canon-crw'], + 'cryptonote' => ['application/vnd.rig.cryptonote'], + 'cs' => ['text/x-csharp'], + 'csh' => ['application/x-csh'], + 'csml' => ['chemical/x-csml'], + 'csp' => ['application/vnd.commonspace'], + 'css' => ['text/css'], + 'cst' => ['application/x-director'], + 'csv' => ['text/csv', 'text/x-comma-separated-values', 'text/x-csv'], + 'csvs' => ['text/csv-schema'], + 'cu' => ['application/cu-seeme'], + 'cue' => ['application/x-cue'], + 'cur' => ['image/x-win-bitmap'], + 'curl' => ['text/vnd.curl'], + 'cww' => ['application/prs.cww'], + 'cxt' => ['application/x-director'], + 'cxx' => ['text/x-c', 'text/x-c++src'], + 'd' => ['text/x-dsrc'], + 'dae' => ['model/vnd.collada+xml'], + 'daf' => ['application/vnd.mobius.daf'], + 'dar' => ['application/x-dar'], + 'dart' => ['application/vnd.dart'], + 'dataless' => ['application/vnd.fdsn.seed'], + 'davmount' => ['application/davmount+xml'], + 'dbf' => ['application/dbase', 'application/dbf', 'application/x-dbase', 'application/x-dbf'], + 'dbk' => ['application/docbook+xml', 'application/vnd.oasis.docbook+xml', 'application/x-docbook+xml'], + 'dc' => ['application/x-dc-rom'], + 'dcl' => ['text/x-dcl'], + 'dcm' => ['application/dicom'], + 'dcr' => ['application/x-director', 'image/x-kodak-dcr'], + 'dcurl' => ['text/vnd.curl.dcurl'], + 'dd2' => ['application/vnd.oma.dd2+xml'], + 'ddd' => ['application/vnd.fujixerox.ddd'], + 'dds' => ['image/x-dds'], + 'deb' => ['application/vnd.debian.binary-package', 'application/x-deb', 'application/x-debian-package'], + 'def' => ['text/plain'], + 'deploy' => ['application/octet-stream'], + 'der' => ['application/x-x509-ca-cert'], + 'desktop' => ['application/x-desktop', 'application/x-gnome-app-info'], + 'device' => ['text/x-systemd-unit'], + 'dfac' => ['application/vnd.dreamfactory'], + 'dgc' => ['application/x-dgc-compressed'], + 'di' => ['text/x-dsrc'], + 'dia' => ['application/x-dia-diagram'], + 'dib' => ['image/bmp', 'image/x-bmp', 'image/x-ms-bmp'], + 'dic' => ['text/x-c'], + 'diff' => ['text/x-diff', 'text/x-patch'], + 'dir' => ['application/x-director'], + 'dis' => ['application/vnd.mobius.dis'], + 'dist' => ['application/octet-stream'], + 'distz' => ['application/octet-stream'], + 'divx' => ['video/avi', 'video/divx', 'video/msvideo', 'video/vnd.divx', 'video/x-avi', 'video/x-msvideo'], + 'djv' => ['image/vnd.djvu', 'image/vnd.djvu+multipage', 'image/x-djvu', 'image/x.djvu'], + 'djvu' => ['image/vnd.djvu', 'image/vnd.djvu+multipage', 'image/x-djvu', 'image/x.djvu'], + 'dll' => ['application/x-msdownload'], + 'dmg' => ['application/x-apple-diskimage'], + 'dmp' => ['application/pcap', 'application/vnd.tcpdump.pcap', 'application/x-pcap'], + 'dms' => ['application/octet-stream'], + 'dna' => ['application/vnd.dna'], + 'dng' => ['image/x-adobe-dng'], + 'doc' => ['application/msword', 'application/vnd.ms-word', 'application/x-msword', 'zz-application/zz-winassoc-doc'], + 'docbook' => ['application/docbook+xml', 'application/vnd.oasis.docbook+xml', 'application/x-docbook+xml'], + 'docm' => ['application/vnd.ms-word.document.macroenabled.12'], + 'docx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'], + 'dot' => ['application/msword', 'application/msword-template', 'text/vnd.graphviz'], + 'dotm' => ['application/vnd.ms-word.template.macroenabled.12'], + 'dotx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.template'], + 'dp' => ['application/vnd.osgi.dp'], + 'dpg' => ['application/vnd.dpgraph'], + 'dra' => ['audio/vnd.dra'], + 'dsc' => ['text/prs.lines.tag'], + 'dsl' => ['text/x-dsl'], + 'dssc' => ['application/dssc+der'], + 'dtb' => ['application/x-dtbook+xml'], + 'dtd' => ['application/xml-dtd', 'text/x-dtd'], + 'dts' => ['audio/vnd.dts', 'audio/x-dts'], + 'dtshd' => ['audio/vnd.dts.hd', 'audio/x-dtshd'], + 'dtx' => ['application/x-tex', 'text/x-tex'], + 'dump' => ['application/octet-stream'], + 'dv' => ['video/dv'], + 'dvb' => ['video/vnd.dvb.file'], + 'dvi' => ['application/x-dvi'], + 'dvi.bz2' => ['application/x-bzdvi'], + 'dvi.gz' => ['application/x-gzdvi'], + 'dwf' => ['model/vnd.dwf'], + 'dwg' => ['image/vnd.dwg'], + 'dxf' => ['image/vnd.dxf'], + 'dxp' => ['application/vnd.spotfire.dxp'], + 'dxr' => ['application/x-director'], + 'e' => ['text/x-eiffel'], + 'ecelp4800' => ['audio/vnd.nuera.ecelp4800'], + 'ecelp7470' => ['audio/vnd.nuera.ecelp7470'], + 'ecelp9600' => ['audio/vnd.nuera.ecelp9600'], + 'ecma' => ['application/ecmascript'], + 'edm' => ['application/vnd.novadigm.edm'], + 'edx' => ['application/vnd.novadigm.edx'], + 'efif' => ['application/vnd.picsel'], + 'egon' => ['application/x-egon'], + 'ei6' => ['application/vnd.pg.osasli'], + 'eif' => ['text/x-eiffel'], + 'el' => ['text/x-emacs-lisp'], + 'elc' => ['application/octet-stream'], + 'emf' => ['application/emf', 'application/x-emf', 'application/x-msmetafile', 'image/emf', 'image/x-emf'], + 'eml' => ['message/rfc822'], + 'emma' => ['application/emma+xml'], + 'emp' => ['application/vnd.emusic-emusic_package'], + 'emz' => ['application/x-msmetafile'], + 'ent' => ['application/xml-external-parsed-entity', 'text/xml-external-parsed-entity'], + 'eol' => ['audio/vnd.digital-winds'], + 'eot' => ['application/vnd.ms-fontobject'], + 'eps' => ['application/postscript', 'image/x-eps'], + 'eps.bz2' => ['image/x-bzeps'], + 'eps.gz' => ['image/x-gzeps'], + 'epsf' => ['image/x-eps'], + 'epsf.bz2' => ['image/x-bzeps'], + 'epsf.gz' => ['image/x-gzeps'], + 'epsi' => ['image/x-eps'], + 'epsi.bz2' => ['image/x-bzeps'], + 'epsi.gz' => ['image/x-gzeps'], + 'epub' => ['application/epub+zip'], + 'erl' => ['text/x-erlang'], + 'es' => ['application/ecmascript', 'text/ecmascript'], + 'es3' => ['application/vnd.eszigno3+xml'], + 'esa' => ['application/vnd.osgi.subsystem'], + 'esf' => ['application/vnd.epson.esf'], + 'et3' => ['application/vnd.eszigno3+xml'], + 'etheme' => ['application/x-e-theme'], + 'etx' => ['text/x-setext'], + 'eva' => ['application/x-eva'], + 'evy' => ['application/x-envoy'], + 'exe' => ['application/x-ms-dos-executable', 'application/x-msdownload'], + 'exi' => ['application/exi'], + 'exr' => ['image/x-exr'], + 'ext' => ['application/vnd.novadigm.ext'], + 'ez' => ['application/andrew-inset'], + 'ez2' => ['application/vnd.ezpix-album'], + 'ez3' => ['application/vnd.ezpix-package'], + 'f' => ['text/x-fortran'], + 'f4a' => ['audio/m4a', 'audio/mp4', 'audio/x-m4a'], + 'f4b' => ['audio/x-m4b'], + 'f4v' => ['video/mp4', 'video/mp4v-es', 'video/x-f4v', 'video/x-m4v'], + 'f77' => ['text/x-fortran'], + 'f90' => ['text/x-fortran'], + 'f95' => ['text/x-fortran'], + 'fb2' => ['application/x-fictionbook', 'application/x-fictionbook+xml'], + 'fb2.zip' => ['application/x-zip-compressed-fb2'], + 'fbs' => ['image/vnd.fastbidsheet'], + 'fcdt' => ['application/vnd.adobe.formscentral.fcdt'], + 'fcs' => ['application/vnd.isac.fcs'], + 'fd' => ['application/x-fd-file', 'application/x-raw-floppy-disk-image'], + 'fdf' => ['application/vnd.fdf'], + 'fds' => ['application/x-fds-disk'], + 'fe_launch' => ['application/vnd.denovo.fcselayout-link'], + 'feature' => ['text/x-gherkin'], + 'fg5' => ['application/vnd.fujitsu.oasysgp'], + 'fgd' => ['application/x-director'], + 'fh' => ['image/x-freehand'], + 'fh4' => ['image/x-freehand'], + 'fh5' => ['image/x-freehand'], + 'fh7' => ['image/x-freehand'], + 'fhc' => ['image/x-freehand'], + 'fig' => ['application/x-xfig', 'image/x-xfig'], + 'fits' => ['image/fits', 'image/x-fits'], + 'fl' => ['application/x-fluid'], + 'flac' => ['audio/flac', 'audio/x-flac'], + 'flatpak' => ['application/vnd.flatpak', 'application/vnd.xdgapp'], + 'flatpakref' => ['application/vnd.flatpak.ref'], + 'flatpakrepo' => ['application/vnd.flatpak.repo'], + 'flc' => ['video/fli', 'video/x-fli', 'video/x-flic'], + 'fli' => ['video/fli', 'video/x-fli', 'video/x-flic'], + 'flo' => ['application/vnd.micrografx.flo'], + 'flv' => ['video/x-flv', 'application/x-flash-video', 'flv-application/octet-stream', 'video/flv'], + 'flw' => ['application/vnd.kde.kivio', 'application/x-kivio'], + 'flx' => ['text/vnd.fmi.flexstor'], + 'fly' => ['text/vnd.fly'], + 'fm' => ['application/vnd.framemaker', 'application/x-frame'], + 'fnc' => ['application/vnd.frogans.fnc'], + 'fo' => ['text/x-xslfo'], + 'fodg' => ['application/vnd.oasis.opendocument.graphics-flat-xml'], + 'fodp' => ['application/vnd.oasis.opendocument.presentation-flat-xml'], + 'fods' => ['application/vnd.oasis.opendocument.spreadsheet-flat-xml'], + 'fodt' => ['application/vnd.oasis.opendocument.text-flat-xml'], + 'for' => ['text/x-fortran'], + 'fpx' => ['image/vnd.fpx'], + 'frame' => ['application/vnd.framemaker'], + 'fsc' => ['application/vnd.fsc.weblaunch'], + 'fst' => ['image/vnd.fst'], + 'ftc' => ['application/vnd.fluxtime.clip'], + 'fti' => ['application/vnd.anser-web-funds-transfer-initiation'], + 'fvt' => ['video/vnd.fvt'], + 'fxm' => ['video/x-javafx'], + 'fxp' => ['application/vnd.adobe.fxp'], + 'fxpl' => ['application/vnd.adobe.fxp'], + 'fzs' => ['application/vnd.fuzzysheet'], + 'g2w' => ['application/vnd.geoplan'], + 'g3' => ['image/fax-g3', 'image/g3fax'], + 'g3w' => ['application/vnd.geospace'], + 'gac' => ['application/vnd.groove-account'], + 'gam' => ['application/x-tads'], + 'gb' => ['application/x-gameboy-rom'], + 'gba' => ['application/x-gba-rom'], + 'gbc' => ['application/x-gameboy-color-rom'], + 'gbr' => ['application/rpki-ghostbusters', 'image/x-gimp-gbr'], + 'gca' => ['application/x-gca-compressed'], + 'gcode' => ['text/x.gcode'], + 'gcrd' => ['text/directory', 'text/vcard', 'text/x-vcard'], + 'gdl' => ['model/vnd.gdl'], + 'ged' => ['application/x-gedcom', 'text/gedcom'], + 'gedcom' => ['application/x-gedcom', 'text/gedcom'], + 'gem' => ['application/x-gtar', 'application/x-tar'], + 'gen' => ['application/x-genesis-rom'], + 'geo' => ['application/vnd.dynageo'], + 'geo.json' => ['application/geo+json', 'application/vnd.geo+json'], + 'geojson' => ['application/geo+json', 'application/vnd.geo+json'], + 'gex' => ['application/vnd.geometry-explorer'], + 'gf' => ['application/x-tex-gf'], + 'gg' => ['application/x-gamegear-rom'], + 'ggb' => ['application/vnd.geogebra.file'], + 'ggt' => ['application/vnd.geogebra.tool'], + 'ghf' => ['application/vnd.groove-help'], + 'gif' => ['image/gif'], + 'gih' => ['image/x-gimp-gih'], + 'gim' => ['application/vnd.groove-identity-message'], + 'glade' => ['application/x-glade'], + 'gml' => ['application/gml+xml'], + 'gmo' => ['application/x-gettext-translation'], + 'gmx' => ['application/vnd.gmx'], + 'gnc' => ['application/x-gnucash'], + 'gnd' => ['application/gnunet-directory'], + 'gnucash' => ['application/x-gnucash'], + 'gnumeric' => ['application/x-gnumeric'], + 'gnuplot' => ['application/x-gnuplot'], + 'go' => ['text/x-go'], + 'gp' => ['application/x-gnuplot'], + 'gpg' => ['application/pgp', 'application/pgp-encrypted', 'application/pgp-keys', 'application/pgp-signature'], + 'gph' => ['application/vnd.flographit'], + 'gplt' => ['application/x-gnuplot'], + 'gpx' => ['application/gpx', 'application/gpx+xml', 'application/x-gpx', 'application/x-gpx+xml'], + 'gqf' => ['application/vnd.grafeq'], + 'gqs' => ['application/vnd.grafeq'], + 'gra' => ['application/x-graphite'], + 'gram' => ['application/srgs'], + 'gramps' => ['application/x-gramps-xml'], + 'gre' => ['application/vnd.geometry-explorer'], + 'grv' => ['application/vnd.groove-injector'], + 'grxml' => ['application/srgs+xml'], + 'gs' => ['text/x-genie'], + 'gsf' => ['application/x-font-ghostscript', 'application/x-font-type1'], + 'gsm' => ['audio/x-gsm'], + 'gtar' => ['application/x-gtar', 'application/x-tar'], + 'gtm' => ['application/vnd.groove-tool-message'], + 'gtw' => ['model/vnd.gtw'], + 'gv' => ['text/vnd.graphviz'], + 'gvp' => ['text/google-video-pointer', 'text/x-google-video-pointer'], + 'gxf' => ['application/gxf'], + 'gxt' => ['application/vnd.geonext'], + 'gz' => ['application/x-gzip', 'application/gzip'], + 'h' => ['text/x-c', 'text/x-chdr'], + 'h++' => ['text/x-c++hdr'], + 'h261' => ['video/h261'], + 'h263' => ['video/h263'], + 'h264' => ['video/h264'], + 'h4' => ['application/x-hdf'], + 'h5' => ['application/x-hdf'], + 'hal' => ['application/vnd.hal+xml'], + 'hbci' => ['application/vnd.hbci'], + 'hdf' => ['application/x-hdf'], + 'hdf4' => ['application/x-hdf'], + 'hdf5' => ['application/x-hdf'], + 'heic' => ['image/heic', 'image/heic-sequence', 'image/heif', 'image/heif-sequence'], + 'heif' => ['image/heic', 'image/heic-sequence', 'image/heif', 'image/heif-sequence'], + 'hfe' => ['application/x-hfe-file', 'application/x-hfe-floppy-image'], + 'hh' => ['text/x-c', 'text/x-c++hdr'], + 'hlp' => ['application/winhlp', 'zz-application/zz-winassoc-hlp'], + 'hp' => ['text/x-c++hdr'], + 'hpgl' => ['application/vnd.hp-hpgl'], + 'hpid' => ['application/vnd.hp-hpid'], + 'hpp' => ['text/x-c++hdr'], + 'hps' => ['application/vnd.hp-hps'], + 'hqx' => ['application/stuffit', 'application/mac-binhex40'], + 'hs' => ['text/x-haskell'], + 'htke' => ['application/vnd.kenameaapp'], + 'htm' => ['text/html'], + 'html' => ['text/html'], + 'hvd' => ['application/vnd.yamaha.hv-dic'], + 'hvp' => ['application/vnd.yamaha.hv-voice'], + 'hvs' => ['application/vnd.yamaha.hv-script'], + 'hwp' => ['application/vnd.haansoft-hwp', 'application/x-hwp'], + 'hwt' => ['application/vnd.haansoft-hwt', 'application/x-hwt'], + 'hxx' => ['text/x-c++hdr'], + 'i2g' => ['application/vnd.intergeo'], + 'ica' => ['application/x-ica'], + 'icb' => ['image/x-icb', 'image/x-tga'], + 'icc' => ['application/vnd.iccprofile'], + 'ice' => ['x-conference/x-cooltalk'], + 'icm' => ['application/vnd.iccprofile'], + 'icns' => ['image/x-icns'], + 'ico' => ['application/ico', 'image/ico', 'image/icon', 'image/vnd.microsoft.icon', 'image/x-ico', 'image/x-icon', 'text/ico'], + 'ics' => ['application/ics', 'text/calendar', 'text/x-vcalendar'], + 'idl' => ['text/x-idl'], + 'ief' => ['image/ief'], + 'ifb' => ['text/calendar'], + 'iff' => ['image/x-iff', 'image/x-ilbm'], + 'ifm' => ['application/vnd.shana.informed.formdata'], + 'iges' => ['model/iges'], + 'igl' => ['application/vnd.igloader'], + 'igm' => ['application/vnd.insors.igm'], + 'igs' => ['model/iges'], + 'igx' => ['application/vnd.micrografx.igx'], + 'iif' => ['application/vnd.shana.informed.interchange'], + 'ilbm' => ['image/x-iff', 'image/x-ilbm'], + 'ime' => ['audio/imelody', 'audio/x-imelody', 'text/x-imelody'], + 'img' => ['application/x-raw-disk-image'], + 'img.xz' => ['application/x-raw-disk-image-xz-compressed'], + 'imp' => ['application/vnd.accpac.simply.imp'], + 'ims' => ['application/vnd.ms-ims'], + 'imy' => ['audio/imelody', 'audio/x-imelody', 'text/x-imelody'], + 'in' => ['text/plain'], + 'ink' => ['application/inkml+xml'], + 'inkml' => ['application/inkml+xml'], + 'ins' => ['application/x-tex', 'text/x-tex'], + 'install' => ['application/x-install-instructions'], + 'iota' => ['application/vnd.astraea-software.iota'], + 'ipfix' => ['application/ipfix'], + 'ipk' => ['application/vnd.shana.informed.package'], + 'iptables' => ['text/x-iptables'], + 'ipynb' => ['application/x-ipynb+json'], + 'irm' => ['application/vnd.ibm.rights-management'], + 'irp' => ['application/vnd.irepository.package+xml'], + 'iso' => ['application/x-cd-image', 'application/x-gamecube-iso-image', 'application/x-gamecube-rom', 'application/x-iso9660-image', 'application/x-saturn-rom', 'application/x-sega-cd-rom', 'application/x-wbfs', 'application/x-wia', 'application/x-wii-iso-image', 'application/x-wii-rom'], + 'iso9660' => ['application/x-cd-image', 'application/x-iso9660-image'], + 'it' => ['audio/x-it'], + 'it87' => ['application/x-it87'], + 'itp' => ['application/vnd.shana.informed.formtemplate'], + 'ivp' => ['application/vnd.immervision-ivp'], + 'ivu' => ['application/vnd.immervision-ivu'], + 'j2c' => ['image/x-jp2-codestream'], + 'j2k' => ['image/x-jp2-codestream'], + 'jad' => ['text/vnd.sun.j2me.app-descriptor'], + 'jam' => ['application/vnd.jam'], + 'jar' => ['application/x-java-archive', 'application/java-archive', 'application/x-jar'], + 'java' => ['text/x-java', 'text/x-java-source'], + 'jceks' => ['application/x-java-jce-keystore'], + 'jisp' => ['application/vnd.jisp'], + 'jks' => ['application/x-java-keystore'], + 'jlt' => ['application/vnd.hp-jlyt'], + 'jng' => ['image/x-jng'], + 'jnlp' => ['application/x-java-jnlp-file'], + 'joda' => ['application/vnd.joost.joda-archive'], + 'jp2' => ['image/jp2', 'image/jpeg2000', 'image/jpeg2000-image', 'image/x-jpeg2000-image'], + 'jpc' => ['image/x-jp2-codestream'], + 'jpe' => ['image/jpeg', 'image/pjpeg'], + 'jpeg' => ['image/jpeg', 'image/pjpeg'], + 'jpf' => ['image/jpx'], + 'jpg' => ['image/jpeg', 'image/pjpeg'], + 'jpg2' => ['image/jp2', 'image/jpeg2000', 'image/jpeg2000-image', 'image/x-jpeg2000-image'], + 'jpgm' => ['image/jpm', 'video/jpm'], + 'jpgv' => ['video/jpeg'], + 'jpm' => ['image/jpm', 'video/jpm'], + 'jpr' => ['application/x-jbuilder-project'], + 'jpx' => ['application/x-jbuilder-project', 'image/jpx'], + 'jrd' => ['application/jrd+json'], + 'js' => ['text/javascript', 'application/javascript', 'application/x-javascript'], + 'jsm' => ['application/javascript', 'application/x-javascript', 'text/javascript'], + 'json' => ['application/json'], + 'json-patch' => ['application/json-patch+json'], + 'jsonld' => ['application/ld+json'], + 'jsonml' => ['application/jsonml+json'], + 'k25' => ['image/x-kodak-k25'], + 'k7' => ['application/x-thomson-cassette'], + 'kar' => ['audio/midi', 'audio/x-midi'], + 'karbon' => ['application/vnd.kde.karbon', 'application/x-karbon'], + 'kdc' => ['image/x-kodak-kdc'], + 'kdelnk' => ['application/x-desktop', 'application/x-gnome-app-info'], + 'kexi' => ['application/x-kexiproject-sqlite', 'application/x-kexiproject-sqlite2', 'application/x-kexiproject-sqlite3', 'application/x-vnd.kde.kexi'], + 'kexic' => ['application/x-kexi-connectiondata'], + 'kexis' => ['application/x-kexiproject-shortcut'], + 'key' => ['application/vnd.apple.keynote', 'application/x-iwork-keynote-sffkey'], + 'kfo' => ['application/vnd.kde.kformula', 'application/x-kformula'], + 'kia' => ['application/vnd.kidspiration'], + 'kil' => ['application/x-killustrator'], + 'kino' => ['application/smil', 'application/smil+xml'], + 'kml' => ['application/vnd.google-earth.kml+xml'], + 'kmz' => ['application/vnd.google-earth.kmz'], + 'kne' => ['application/vnd.kinar'], + 'knp' => ['application/vnd.kinar'], + 'kon' => ['application/vnd.kde.kontour', 'application/x-kontour'], + 'kpm' => ['application/x-kpovmodeler'], + 'kpr' => ['application/vnd.kde.kpresenter', 'application/x-kpresenter'], + 'kpt' => ['application/vnd.kde.kpresenter', 'application/x-kpresenter'], + 'kpxx' => ['application/vnd.ds-keypoint'], + 'kra' => ['application/x-krita'], + 'ks' => ['application/x-java-keystore'], + 'ksp' => ['application/vnd.kde.kspread', 'application/x-kspread'], + 'ktr' => ['application/vnd.kahootz'], + 'ktx' => ['image/ktx'], + 'ktz' => ['application/vnd.kahootz'], + 'kud' => ['application/x-kugar'], + 'kwd' => ['application/vnd.kde.kword', 'application/x-kword'], + 'kwt' => ['application/vnd.kde.kword', 'application/x-kword'], + 'la' => ['application/x-shared-library-la'], + 'lasxml' => ['application/vnd.las.las+xml'], + 'latex' => ['application/x-latex', 'application/x-tex', 'text/x-tex'], + 'lbd' => ['application/vnd.llamagraphics.life-balance.desktop'], + 'lbe' => ['application/vnd.llamagraphics.life-balance.exchange+xml'], + 'lbm' => ['image/x-iff', 'image/x-ilbm'], + 'ldif' => ['text/x-ldif'], + 'les' => ['application/vnd.hhe.lesson-player'], + 'lha' => ['application/x-lha', 'application/x-lzh-compressed'], + 'lhs' => ['text/x-literate-haskell'], + 'lhz' => ['application/x-lhz'], + 'link66' => ['application/vnd.route66.link66+xml'], + 'list' => ['text/plain'], + 'list3820' => ['application/vnd.ibm.modcap'], + 'listafp' => ['application/vnd.ibm.modcap'], + 'lnk' => ['application/x-ms-shortcut'], + 'lnx' => ['application/x-atari-lynx-rom'], + 'loas' => ['audio/usac'], + 'log' => ['text/plain', 'text/x-log'], + 'lostxml' => ['application/lost+xml'], + 'lrf' => ['application/octet-stream'], + 'lrm' => ['application/vnd.ms-lrm'], + 'lrv' => ['video/mp4', 'video/mp4v-es', 'video/x-m4v'], + 'lrz' => ['application/x-lrzip'], + 'ltf' => ['application/vnd.frogans.ltf'], + 'ltx' => ['application/x-tex', 'text/x-tex'], + 'lua' => ['text/x-lua'], + 'lvp' => ['audio/vnd.lucent.voice'], + 'lwo' => ['image/x-lwo'], + 'lwob' => ['image/x-lwo'], + 'lwp' => ['application/vnd.lotus-wordpro'], + 'lws' => ['image/x-lws'], + 'ly' => ['text/x-lilypond'], + 'lyx' => ['application/x-lyx', 'text/x-lyx'], + 'lz' => ['application/x-lzip'], + 'lz4' => ['application/x-lz4'], + 'lzh' => ['application/x-lha', 'application/x-lzh-compressed'], + 'lzma' => ['application/x-lzma'], + 'lzo' => ['application/x-lzop'], + 'm' => ['text/x-matlab', 'text/x-objcsrc', 'text/x-octave'], + 'm13' => ['application/x-msmediaview'], + 'm14' => ['application/x-msmediaview'], + 'm15' => ['audio/x-mod'], + 'm1u' => ['video/vnd.mpegurl', 'video/x-mpegurl'], + 'm1v' => ['video/mpeg'], + 'm21' => ['application/mp21'], + 'm2a' => ['audio/mpeg'], + 'm2t' => ['video/mp2t'], + 'm2ts' => ['video/mp2t'], + 'm2v' => ['video/mpeg'], + 'm3a' => ['audio/mpeg'], + 'm3u' => ['audio/x-mpegurl', 'application/m3u', 'application/vnd.apple.mpegurl', 'audio/m3u', 'audio/mpegurl', 'audio/x-m3u', 'audio/x-mp3-playlist'], + 'm3u8' => ['application/m3u', 'application/vnd.apple.mpegurl', 'audio/m3u', 'audio/mpegurl', 'audio/x-m3u', 'audio/x-mp3-playlist', 'audio/x-mpegurl'], + 'm4' => ['application/x-m4'], + 'm4a' => ['audio/mp4', 'audio/m4a', 'audio/x-m4a'], + 'm4b' => ['audio/x-m4b'], + 'm4r' => ['audio/x-m4r'], + 'm4u' => ['video/vnd.mpegurl', 'video/x-mpegurl'], + 'm4v' => ['video/mp4', 'video/mp4v-es', 'video/x-m4v'], + 'm7' => ['application/x-thomson-cartridge-memo7'], + 'ma' => ['application/mathematica'], + 'mab' => ['application/x-markaby'], + 'mads' => ['application/mads+xml'], + 'mag' => ['application/vnd.ecowin.chart'], + 'mak' => ['text/x-makefile'], + 'maker' => ['application/vnd.framemaker'], + 'man' => ['application/x-troff-man', 'text/troff'], + 'manifest' => ['text/cache-manifest'], + 'mar' => ['application/octet-stream'], + 'markdown' => ['text/markdown', 'text/x-markdown'], + 'mathml' => ['application/mathml+xml'], + 'mb' => ['application/mathematica'], + 'mbk' => ['application/vnd.mobius.mbk'], + 'mbox' => ['application/mbox'], + 'mc1' => ['application/vnd.medcalcdata'], + 'mcd' => ['application/vnd.mcd'], + 'mcurl' => ['text/vnd.curl.mcurl'], + 'md' => ['text/markdown', 'text/x-markdown'], + 'mdb' => ['application/x-msaccess', 'application/mdb', 'application/msaccess', 'application/vnd.ms-access', 'application/vnd.msaccess', 'application/x-mdb', 'zz-application/zz-winassoc-mdb'], + 'mdi' => ['image/vnd.ms-modi'], + 'mdx' => ['application/x-genesis-32x-rom'], + 'me' => ['text/troff', 'text/x-troff-me'], + 'med' => ['audio/x-mod'], + 'mesh' => ['model/mesh'], + 'meta4' => ['application/metalink4+xml'], + 'metalink' => ['application/metalink+xml'], + 'mets' => ['application/mets+xml'], + 'mfm' => ['application/vnd.mfmp'], + 'mft' => ['application/rpki-manifest'], + 'mgp' => ['application/vnd.osgeo.mapguide.package', 'application/x-magicpoint'], + 'mgz' => ['application/vnd.proteus.magazine'], + 'mht' => ['application/x-mimearchive'], + 'mhtml' => ['application/x-mimearchive'], + 'mid' => ['audio/midi', 'audio/x-midi'], + 'midi' => ['audio/midi', 'audio/x-midi'], + 'mie' => ['application/x-mie'], + 'mif' => ['application/vnd.mif', 'application/x-mif'], + 'mime' => ['message/rfc822'], + 'minipsf' => ['audio/x-minipsf'], + 'mj2' => ['video/mj2'], + 'mjp2' => ['video/mj2'], + 'mjpeg' => ['video/x-mjpeg'], + 'mjpg' => ['video/x-mjpeg'], + 'mjs' => ['application/javascript', 'application/x-javascript', 'text/javascript'], + 'mk' => ['text/x-makefile'], + 'mk3d' => ['video/x-matroska', 'video/x-matroska-3d'], + 'mka' => ['audio/x-matroska'], + 'mkd' => ['text/markdown', 'text/x-markdown'], + 'mks' => ['video/x-matroska'], + 'mkv' => ['video/x-matroska'], + 'ml' => ['text/x-ocaml'], + 'mli' => ['text/x-ocaml'], + 'mlp' => ['application/vnd.dolby.mlp'], + 'mm' => ['text/x-troff-mm'], + 'mmd' => ['application/vnd.chipnuts.karaoke-mmd'], + 'mmf' => ['application/vnd.smaf', 'application/x-smaf'], + 'mml' => ['application/mathml+xml', 'text/mathml'], + 'mmr' => ['image/vnd.fujixerox.edmics-mmr'], + 'mng' => ['video/x-mng'], + 'mny' => ['application/x-msmoney'], + 'mo' => ['application/x-gettext-translation', 'text/x-modelica'], + 'mo3' => ['audio/x-mo3'], + 'mobi' => ['application/x-mobipocket-ebook'], + 'moc' => ['text/x-moc'], + 'mod' => ['audio/x-mod'], + 'mods' => ['application/mods+xml'], + 'mof' => ['text/x-mof'], + 'moov' => ['video/quicktime'], + 'mount' => ['text/x-systemd-unit'], + 'mov' => ['video/quicktime'], + 'movie' => ['video/x-sgi-movie'], + 'mp+' => ['audio/x-musepack'], + 'mp2' => ['audio/mp2', 'audio/mpeg', 'audio/x-mp2', 'video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], + 'mp21' => ['application/mp21'], + 'mp2a' => ['audio/mpeg'], + 'mp3' => ['audio/mpeg', 'audio/mp3', 'audio/x-mp3', 'audio/x-mpeg', 'audio/x-mpg'], + 'mp4' => ['video/mp4', 'video/mp4v-es', 'video/x-m4v'], + 'mp4a' => ['audio/mp4'], + 'mp4s' => ['application/mp4'], + 'mp4v' => ['video/mp4'], + 'mpc' => ['application/vnd.mophun.certificate', 'audio/x-musepack'], + 'mpe' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], + 'mpeg' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], + 'mpg' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], + 'mpg4' => ['video/mp4'], + 'mpga' => ['audio/mp3', 'audio/mpeg', 'audio/x-mp3', 'audio/x-mpeg', 'audio/x-mpg'], + 'mpkg' => ['application/vnd.apple.installer+xml'], + 'mpl' => ['video/mp2t'], + 'mpls' => ['video/mp2t'], + 'mpm' => ['application/vnd.blueice.multipass'], + 'mpn' => ['application/vnd.mophun.application'], + 'mpp' => ['application/vnd.ms-project', 'audio/x-musepack'], + 'mpt' => ['application/vnd.ms-project'], + 'mpy' => ['application/vnd.ibm.minipay'], + 'mqy' => ['application/vnd.mobius.mqy'], + 'mrc' => ['application/marc'], + 'mrcx' => ['application/marcxml+xml'], + 'mrl' => ['text/x-mrml'], + 'mrml' => ['text/x-mrml'], + 'mrw' => ['image/x-minolta-mrw'], + 'ms' => ['text/troff', 'text/x-troff-ms'], + 'mscml' => ['application/mediaservercontrol+xml'], + 'mseed' => ['application/vnd.fdsn.mseed'], + 'mseq' => ['application/vnd.mseq'], + 'msf' => ['application/vnd.epson.msf'], + 'msh' => ['model/mesh'], + 'msi' => ['application/x-msdownload', 'application/x-msi'], + 'msl' => ['application/vnd.mobius.msl'], + 'msod' => ['image/x-msod'], + 'msty' => ['application/vnd.muvee.style'], + 'msx' => ['application/x-msx-rom'], + 'mtm' => ['audio/x-mod'], + 'mts' => ['model/vnd.mts', 'video/mp2t'], + 'mup' => ['text/x-mup'], + 'mus' => ['application/vnd.musician'], + 'musicxml' => ['application/vnd.recordare.musicxml+xml'], + 'mvb' => ['application/x-msmediaview'], + 'mwf' => ['application/vnd.mfer'], + 'mxf' => ['application/mxf'], + 'mxl' => ['application/vnd.recordare.musicxml'], + 'mxml' => ['application/xv+xml'], + 'mxs' => ['application/vnd.triscape.mxs'], + 'mxu' => ['video/vnd.mpegurl', 'video/x-mpegurl'], + 'n-gage' => ['application/vnd.nokia.n-gage.symbian.install'], + 'n3' => ['text/n3'], + 'n64' => ['application/x-n64-rom'], + 'nb' => ['application/mathematica', 'application/x-mathematica'], + 'nbp' => ['application/vnd.wolfram.player'], + 'nc' => ['application/x-netcdf'], + 'ncx' => ['application/x-dtbncx+xml'], + 'nds' => ['application/x-nintendo-ds-rom'], + 'nef' => ['image/x-nikon-nef'], + 'nes' => ['application/x-nes-rom'], + 'nez' => ['application/x-nes-rom'], + 'nfo' => ['text/x-nfo'], + 'ngc' => ['application/x-neo-geo-pocket-color-rom'], + 'ngdat' => ['application/vnd.nokia.n-gage.data'], + 'ngp' => ['application/x-neo-geo-pocket-rom'], + 'nitf' => ['application/vnd.nitf'], + 'nlu' => ['application/vnd.neurolanguage.nlu'], + 'nml' => ['application/vnd.enliven'], + 'nnd' => ['application/vnd.noblenet-directory'], + 'nns' => ['application/vnd.noblenet-sealer'], + 'nnw' => ['application/vnd.noblenet-web'], + 'not' => ['text/x-mup'], + 'npx' => ['image/vnd.net-fpx'], + 'nsc' => ['application/x-conference', 'application/x-netshow-channel'], + 'nsf' => ['application/vnd.lotus-notes'], + 'nsv' => ['video/x-nsv'], + 'ntf' => ['application/vnd.nitf'], + 'nzb' => ['application/x-nzb'], + 'o' => ['application/x-object'], + 'oa2' => ['application/vnd.fujitsu.oasys2'], + 'oa3' => ['application/vnd.fujitsu.oasys3'], + 'oas' => ['application/vnd.fujitsu.oasys'], + 'obd' => ['application/x-msbinder'], + 'obj' => ['application/x-tgif'], + 'ocl' => ['text/x-ocl'], + 'oda' => ['application/oda'], + 'odb' => ['application/vnd.oasis.opendocument.database', 'application/vnd.sun.xml.base'], + 'odc' => ['application/vnd.oasis.opendocument.chart'], + 'odf' => ['application/vnd.oasis.opendocument.formula'], + 'odft' => ['application/vnd.oasis.opendocument.formula-template'], + 'odg' => ['application/vnd.oasis.opendocument.graphics'], + 'odi' => ['application/vnd.oasis.opendocument.image'], + 'odm' => ['application/vnd.oasis.opendocument.text-master'], + 'odp' => ['application/vnd.oasis.opendocument.presentation'], + 'ods' => ['application/vnd.oasis.opendocument.spreadsheet'], + 'odt' => ['application/vnd.oasis.opendocument.text'], + 'oga' => ['audio/ogg', 'audio/vorbis', 'audio/x-flac+ogg', 'audio/x-ogg', 'audio/x-oggflac', 'audio/x-speex+ogg', 'audio/x-vorbis', 'audio/x-vorbis+ogg'], + 'ogg' => ['audio/ogg', 'audio/vorbis', 'audio/x-flac+ogg', 'audio/x-ogg', 'audio/x-oggflac', 'audio/x-speex+ogg', 'audio/x-vorbis', 'audio/x-vorbis+ogg', 'video/ogg', 'video/x-ogg', 'video/x-theora', 'video/x-theora+ogg'], + 'ogm' => ['video/x-ogm', 'video/x-ogm+ogg'], + 'ogv' => ['video/ogg', 'video/x-ogg'], + 'ogx' => ['application/ogg', 'application/x-ogg'], + 'old' => ['application/x-trash'], + 'oleo' => ['application/x-oleo'], + 'omdoc' => ['application/omdoc+xml'], + 'onepkg' => ['application/onenote'], + 'onetmp' => ['application/onenote'], + 'onetoc' => ['application/onenote'], + 'onetoc2' => ['application/onenote'], + 'ooc' => ['text/x-ooc'], + 'opf' => ['application/oebps-package+xml'], + 'opml' => ['text/x-opml', 'text/x-opml+xml'], + 'oprc' => ['application/vnd.palm', 'application/x-palm-database'], + 'opus' => ['audio/ogg', 'audio/x-ogg', 'audio/x-opus+ogg'], + 'ora' => ['image/openraster'], + 'orf' => ['image/x-olympus-orf'], + 'org' => ['application/vnd.lotus-organizer'], + 'osf' => ['application/vnd.yamaha.openscoreformat'], + 'osfpvg' => ['application/vnd.yamaha.openscoreformat.osfpvg+xml'], + 'otc' => ['application/vnd.oasis.opendocument.chart-template'], + 'otf' => ['application/vnd.oasis.opendocument.formula-template', 'application/x-font-otf', 'font/otf'], + 'otg' => ['application/vnd.oasis.opendocument.graphics-template'], + 'oth' => ['application/vnd.oasis.opendocument.text-web'], + 'oti' => ['application/vnd.oasis.opendocument.image-template'], + 'otp' => ['application/vnd.oasis.opendocument.presentation-template'], + 'ots' => ['application/vnd.oasis.opendocument.spreadsheet-template'], + 'ott' => ['application/vnd.oasis.opendocument.text-template'], + 'owl' => ['application/rdf+xml', 'text/rdf'], + 'owx' => ['application/owl+xml'], + 'oxps' => ['application/oxps', 'application/vnd.ms-xpsdocument', 'application/xps'], + 'oxt' => ['application/vnd.openofficeorg.extension'], + 'p' => ['text/x-pascal'], + 'p10' => ['application/pkcs10'], + 'p12' => ['application/pkcs12', 'application/x-pkcs12'], + 'p65' => ['application/x-pagemaker'], + 'p7b' => ['application/x-pkcs7-certificates'], + 'p7c' => ['application/pkcs7-mime'], + 'p7m' => ['application/pkcs7-mime'], + 'p7r' => ['application/x-pkcs7-certreqresp'], + 'p7s' => ['application/pkcs7-signature'], + 'p8' => ['application/pkcs8'], + 'p8e' => ['application/pkcs8-encrypted'], + 'pack' => ['application/x-java-pack200'], + 'pak' => ['application/x-pak'], + 'par2' => ['application/x-par2'], + 'part' => ['application/x-partial-download'], + 'pas' => ['text/x-pascal'], + 'pat' => ['image/x-gimp-pat'], + 'patch' => ['text/x-diff', 'text/x-patch'], + 'path' => ['text/x-systemd-unit'], + 'paw' => ['application/vnd.pawaafile'], + 'pbd' => ['application/vnd.powerbuilder6'], + 'pbm' => ['image/x-portable-bitmap'], + 'pcap' => ['application/pcap', 'application/vnd.tcpdump.pcap', 'application/x-pcap'], + 'pcd' => ['image/x-photo-cd'], + 'pce' => ['application/x-pc-engine-rom'], + 'pcf' => ['application/x-cisco-vpn-settings', 'application/x-font-pcf'], + 'pcf.Z' => ['application/x-font-pcf'], + 'pcf.gz' => ['application/x-font-pcf'], + 'pcl' => ['application/vnd.hp-pcl'], + 'pclxl' => ['application/vnd.hp-pclxl'], + 'pct' => ['image/x-pict'], + 'pcurl' => ['application/vnd.curl.pcurl'], + 'pcx' => ['image/vnd.zbrush.pcx', 'image/x-pcx'], + 'pdb' => ['application/vnd.palm', 'application/x-aportisdoc', 'application/x-palm-database'], + 'pdc' => ['application/x-aportisdoc'], + 'pdf' => ['application/pdf', 'application/acrobat', 'application/nappdf', 'application/x-pdf', 'image/pdf'], + 'pdf.bz2' => ['application/x-bzpdf'], + 'pdf.gz' => ['application/x-gzpdf'], + 'pdf.lz' => ['application/x-lzpdf'], + 'pdf.xz' => ['application/x-xzpdf'], + 'pef' => ['image/x-pentax-pef'], + 'pem' => ['application/x-x509-ca-cert'], + 'perl' => ['application/x-perl', 'text/x-perl'], + 'pfa' => ['application/x-font-type1'], + 'pfb' => ['application/x-font-type1'], + 'pfm' => ['application/x-font-type1'], + 'pfr' => ['application/font-tdpfr'], + 'pfx' => ['application/pkcs12', 'application/x-pkcs12'], + 'pgm' => ['image/x-portable-graymap'], + 'pgn' => ['application/vnd.chess-pgn', 'application/x-chess-pgn'], + 'pgp' => ['application/pgp', 'application/pgp-encrypted', 'application/pgp-keys', 'application/pgp-signature'], + 'php' => ['application/x-php'], + 'php3' => ['application/x-php'], + 'php4' => ['application/x-php'], + 'php5' => ['application/x-php'], + 'phps' => ['application/x-php'], + 'pic' => ['image/x-pict'], + 'pict' => ['image/x-pict'], + 'pict1' => ['image/x-pict'], + 'pict2' => ['image/x-pict'], + 'pk' => ['application/x-tex-pk'], + 'pkg' => ['application/octet-stream', 'application/x-xar'], + 'pki' => ['application/pkixcmp'], + 'pkipath' => ['application/pkix-pkipath'], + 'pkr' => ['application/pgp-keys'], + 'pl' => ['application/x-perl', 'text/x-perl'], + 'pla' => ['audio/x-iriver-pla'], + 'plb' => ['application/vnd.3gpp.pic-bw-large'], + 'plc' => ['application/vnd.mobius.plc'], + 'plf' => ['application/vnd.pocketlearn'], + 'pln' => ['application/x-planperfect'], + 'pls' => ['application/pls', 'application/pls+xml', 'audio/scpls', 'audio/x-scpls'], + 'pm' => ['application/x-pagemaker', 'application/x-perl', 'text/x-perl'], + 'pm6' => ['application/x-pagemaker'], + 'pmd' => ['application/x-pagemaker'], + 'pml' => ['application/vnd.ctc-posml'], + 'png' => ['image/png'], + 'pnm' => ['image/x-portable-anymap'], + 'pntg' => ['image/x-macpaint'], + 'po' => ['application/x-gettext', 'text/x-gettext-translation', 'text/x-po'], + 'pod' => ['application/x-perl', 'text/x-perl'], + 'por' => ['application/x-spss-por'], + 'portpkg' => ['application/vnd.macports.portpkg'], + 'pot' => ['application/mspowerpoint', 'application/powerpoint', 'application/vnd.ms-powerpoint', 'application/x-mspowerpoint', 'text/x-gettext-translation-template', 'text/x-pot'], + 'potm' => ['application/vnd.ms-powerpoint.template.macroenabled.12'], + 'potx' => ['application/vnd.openxmlformats-officedocument.presentationml.template'], + 'ppam' => ['application/vnd.ms-powerpoint.addin.macroenabled.12'], + 'ppd' => ['application/vnd.cups-ppd'], + 'ppm' => ['image/x-portable-pixmap'], + 'pps' => ['application/mspowerpoint', 'application/powerpoint', 'application/vnd.ms-powerpoint', 'application/x-mspowerpoint'], + 'ppsm' => ['application/vnd.ms-powerpoint.slideshow.macroenabled.12'], + 'ppsx' => ['application/vnd.openxmlformats-officedocument.presentationml.slideshow'], + 'ppt' => ['application/vnd.ms-powerpoint', 'application/mspowerpoint', 'application/powerpoint', 'application/x-mspowerpoint'], + 'pptm' => ['application/vnd.ms-powerpoint.presentation.macroenabled.12'], + 'pptx' => ['application/vnd.openxmlformats-officedocument.presentationml.presentation'], + 'ppz' => ['application/mspowerpoint', 'application/powerpoint', 'application/vnd.ms-powerpoint', 'application/x-mspowerpoint'], + 'pqa' => ['application/vnd.palm', 'application/x-palm-database'], + 'prc' => ['application/vnd.palm', 'application/x-mobipocket-ebook', 'application/x-palm-database'], + 'pre' => ['application/vnd.lotus-freelance'], + 'prf' => ['application/pics-rules'], + 'ps' => ['application/postscript'], + 'ps.bz2' => ['application/x-bzpostscript'], + 'ps.gz' => ['application/x-gzpostscript'], + 'psb' => ['application/vnd.3gpp.pic-bw-small'], + 'psd' => ['application/photoshop', 'application/x-photoshop', 'image/photoshop', 'image/psd', 'image/vnd.adobe.photoshop', 'image/x-photoshop', 'image/x-psd'], + 'psf' => ['application/x-font-linux-psf', 'audio/x-psf'], + 'psf.gz' => ['application/x-gz-font-linux-psf'], + 'psflib' => ['audio/x-psflib'], + 'psid' => ['audio/prs.sid'], + 'pskcxml' => ['application/pskc+xml'], + 'psw' => ['application/x-pocket-word'], + 'ptid' => ['application/vnd.pvi.ptid1'], + 'pub' => ['application/vnd.ms-publisher', 'application/x-mspublisher'], + 'pvb' => ['application/vnd.3gpp.pic-bw-var'], + 'pw' => ['application/x-pw'], + 'pwn' => ['application/vnd.3m.post-it-notes'], + 'py' => ['text/x-python', 'text/x-python3'], + 'py3' => ['text/x-python3'], + 'py3x' => ['text/x-python3'], + 'pya' => ['audio/vnd.ms-playready.media.pya'], + 'pyc' => ['application/x-python-bytecode'], + 'pyo' => ['application/x-python-bytecode'], + 'pyv' => ['video/vnd.ms-playready.media.pyv'], + 'pyx' => ['text/x-python'], + 'qam' => ['application/vnd.epson.quickanime'], + 'qbo' => ['application/vnd.intu.qbo'], + 'qd' => ['application/x-fd-file', 'application/x-raw-floppy-disk-image'], + 'qfx' => ['application/vnd.intu.qfx'], + 'qif' => ['application/x-qw', 'image/x-quicktime'], + 'qml' => ['text/x-qml'], + 'qmlproject' => ['text/x-qml'], + 'qmltypes' => ['text/x-qml'], + 'qp' => ['application/x-qpress'], + 'qps' => ['application/vnd.publishare-delta-tree'], + 'qt' => ['video/quicktime'], + 'qti' => ['application/x-qtiplot'], + 'qti.gz' => ['application/x-qtiplot'], + 'qtif' => ['image/x-quicktime'], + 'qtl' => ['application/x-quicktime-media-link', 'application/x-quicktimeplayer'], + 'qtvr' => ['video/quicktime'], + 'qwd' => ['application/vnd.quark.quarkxpress'], + 'qwt' => ['application/vnd.quark.quarkxpress'], + 'qxb' => ['application/vnd.quark.quarkxpress'], + 'qxd' => ['application/vnd.quark.quarkxpress'], + 'qxl' => ['application/vnd.quark.quarkxpress'], + 'qxt' => ['application/vnd.quark.quarkxpress'], + 'ra' => ['audio/vnd.m-realaudio', 'audio/vnd.rn-realaudio', 'audio/x-pn-realaudio'], + 'raf' => ['image/x-fuji-raf'], + 'ram' => ['application/ram', 'audio/x-pn-realaudio'], + 'raml' => ['application/raml+yaml'], + 'rar' => ['application/x-rar-compressed', 'application/vnd.rar', 'application/x-rar'], + 'ras' => ['image/x-cmu-raster'], + 'raw' => ['image/x-panasonic-raw', 'image/x-panasonic-rw'], + 'raw-disk-image' => ['application/x-raw-disk-image'], + 'raw-disk-image.xz' => ['application/x-raw-disk-image-xz-compressed'], + 'rax' => ['audio/vnd.m-realaudio', 'audio/vnd.rn-realaudio', 'audio/x-pn-realaudio'], + 'rb' => ['application/x-ruby'], + 'rcprofile' => ['application/vnd.ipunplugged.rcprofile'], + 'rdf' => ['application/rdf+xml', 'text/rdf'], + 'rdfs' => ['application/rdf+xml', 'text/rdf'], + 'rdz' => ['application/vnd.data-vision.rdz'], + 'reg' => ['text/x-ms-regedit'], + 'rej' => ['application/x-reject', 'text/x-reject'], + 'rep' => ['application/vnd.businessobjects'], + 'res' => ['application/x-dtbresource+xml'], + 'rgb' => ['image/x-rgb'], + 'rif' => ['application/reginfo+xml'], + 'rip' => ['audio/vnd.rip'], + 'ris' => ['application/x-research-info-systems'], + 'rl' => ['application/resource-lists+xml'], + 'rlc' => ['image/vnd.fujixerox.edmics-rlc'], + 'rld' => ['application/resource-lists-diff+xml'], + 'rle' => ['image/rle'], + 'rm' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], + 'rmi' => ['audio/midi'], + 'rmj' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], + 'rmm' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], + 'rmp' => ['audio/x-pn-realaudio-plugin'], + 'rms' => ['application/vnd.jcp.javame.midlet-rms', 'application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], + 'rmvb' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], + 'rmx' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], + 'rnc' => ['application/relax-ng-compact-syntax', 'application/x-rnc'], + 'rng' => ['application/xml', 'text/xml'], + 'roa' => ['application/rpki-roa'], + 'roff' => ['application/x-troff', 'text/troff', 'text/x-troff'], + 'rp' => ['image/vnd.rn-realpix'], + 'rp9' => ['application/vnd.cloanto.rp9'], + 'rpm' => ['application/x-redhat-package-manager', 'application/x-rpm'], + 'rpss' => ['application/vnd.nokia.radio-presets'], + 'rpst' => ['application/vnd.nokia.radio-preset'], + 'rq' => ['application/sparql-query'], + 'rs' => ['application/rls-services+xml', 'text/rust'], + 'rsd' => ['application/rsd+xml'], + 'rss' => ['application/rss+xml', 'text/rss'], + 'rt' => ['text/vnd.rn-realtext'], + 'rtf' => ['application/rtf', 'text/rtf'], + 'rtx' => ['text/richtext'], + 'rv' => ['video/vnd.rn-realvideo', 'video/x-real-video'], + 'rvx' => ['video/vnd.rn-realvideo', 'video/x-real-video'], + 'rw2' => ['image/x-panasonic-raw2', 'image/x-panasonic-rw2'], + 's' => ['text/x-asm'], + 's3m' => ['audio/s3m', 'audio/x-s3m'], + 'saf' => ['application/vnd.yamaha.smaf-audio'], + 'sam' => ['application/x-amipro'], + 'sami' => ['application/x-sami'], + 'sap' => ['application/x-sap-file', 'application/x-thomson-sap-image'], + 'sass' => ['text/x-sass'], + 'sav' => ['application/x-spss-sav', 'application/x-spss-savefile'], + 'sbml' => ['application/sbml+xml'], + 'sc' => ['application/vnd.ibm.secure-container'], + 'scala' => ['text/x-scala'], + 'scd' => ['application/x-msschedule'], + 'scm' => ['application/vnd.lotus-screencam', 'text/x-scheme'], + 'scope' => ['text/x-systemd-unit'], + 'scq' => ['application/scvp-cv-request'], + 'scs' => ['application/scvp-cv-response'], + 'scss' => ['text/x-scss'], + 'scurl' => ['text/vnd.curl.scurl'], + 'sda' => ['application/vnd.stardivision.draw'], + 'sdc' => ['application/vnd.stardivision.calc'], + 'sdd' => ['application/vnd.stardivision.impress'], + 'sdkd' => ['application/vnd.solent.sdkm+xml'], + 'sdkm' => ['application/vnd.solent.sdkm+xml'], + 'sdp' => ['application/sdp', 'application/vnd.sdp', 'application/vnd.stardivision.impress', 'application/x-sdp'], + 'sds' => ['application/vnd.stardivision.chart'], + 'sdw' => ['application/vnd.stardivision.writer', 'application/vnd.stardivision.writer-global'], + 'see' => ['application/vnd.seemail'], + 'seed' => ['application/vnd.fdsn.seed'], + 'sema' => ['application/vnd.sema'], + 'semd' => ['application/vnd.semd'], + 'semf' => ['application/vnd.semf'], + 'ser' => ['application/java-serialized-object'], + 'service' => ['text/x-dbus-service', 'text/x-systemd-unit'], + 'setpay' => ['application/set-payment-initiation'], + 'setreg' => ['application/set-registration-initiation'], + 'sfc' => ['application/vnd.nintendo.snes.rom', 'application/x-snes-rom'], + 'sfd-hdstx' => ['application/vnd.hydrostatix.sof-data'], + 'sfs' => ['application/vnd.spotfire.sfs'], + 'sfv' => ['text/x-sfv'], + 'sg' => ['application/x-sg1000-rom'], + 'sgb' => ['application/x-gameboy-rom'], + 'sgf' => ['application/x-go-sgf'], + 'sgi' => ['image/sgi', 'image/x-sgi'], + 'sgl' => ['application/vnd.stardivision.writer', 'application/vnd.stardivision.writer-global'], + 'sgm' => ['text/sgml'], + 'sgml' => ['text/sgml'], + 'sh' => ['application/x-sh', 'application/x-shellscript', 'text/x-sh'], + 'shape' => ['application/x-dia-shape'], + 'shar' => ['application/x-shar'], + 'shf' => ['application/shf+xml'], + 'shn' => ['application/x-shorten', 'audio/x-shorten'], + 'siag' => ['application/x-siag'], + 'sid' => ['audio/prs.sid', 'image/x-mrsid-image'], + 'sig' => ['application/pgp-signature'], + 'sik' => ['application/x-trash'], + 'sil' => ['audio/silk'], + 'silo' => ['model/mesh'], + 'sis' => ['application/vnd.symbian.install'], + 'sisx' => ['application/vnd.symbian.install', 'x-epoc/x-sisx-app'], + 'sit' => ['application/x-stuffit', 'application/stuffit', 'application/x-sit'], + 'sitx' => ['application/x-stuffitx'], + 'siv' => ['application/sieve'], + 'sk' => ['image/x-skencil'], + 'sk1' => ['image/x-skencil'], + 'skd' => ['application/vnd.koan'], + 'skm' => ['application/vnd.koan'], + 'skp' => ['application/vnd.koan'], + 'skr' => ['application/pgp-keys'], + 'skt' => ['application/vnd.koan'], + 'sldm' => ['application/vnd.ms-powerpoint.slide.macroenabled.12'], + 'sldx' => ['application/vnd.openxmlformats-officedocument.presentationml.slide'], + 'slice' => ['text/x-systemd-unit'], + 'slk' => ['text/spreadsheet'], + 'slt' => ['application/vnd.epson.salt'], + 'sm' => ['application/vnd.stepmania.stepchart'], + 'smaf' => ['application/vnd.smaf', 'application/x-smaf'], + 'smc' => ['application/vnd.nintendo.snes.rom', 'application/x-snes-rom'], + 'smd' => ['application/vnd.stardivision.mail', 'application/x-genesis-rom'], + 'smf' => ['application/vnd.stardivision.math'], + 'smi' => ['application/smil', 'application/smil+xml', 'application/x-sami'], + 'smil' => ['application/smil', 'application/smil+xml'], + 'sml' => ['application/smil', 'application/smil+xml'], + 'sms' => ['application/x-sms-rom'], + 'smv' => ['video/x-smv'], + 'smzip' => ['application/vnd.stepmania.package'], + 'snap' => ['application/vnd.snap'], + 'snd' => ['audio/basic'], + 'snf' => ['application/x-font-snf'], + 'so' => ['application/octet-stream', 'application/x-sharedlib'], + 'socket' => ['text/x-systemd-unit'], + 'spc' => ['application/x-pkcs7-certificates'], + 'spd' => ['application/x-font-speedo'], + 'spec' => ['text/x-rpm-spec'], + 'spf' => ['application/vnd.yamaha.smaf-phrase'], + 'spl' => ['application/futuresplash', 'application/vnd.adobe.flash.movie', 'application/x-futuresplash', 'application/x-shockwave-flash'], + 'spm' => ['application/x-source-rpm'], + 'spot' => ['text/vnd.in3d.spot'], + 'spp' => ['application/scvp-vp-response'], + 'spq' => ['application/scvp-vp-request'], + 'spx' => ['audio/ogg', 'audio/x-speex'], + 'sql' => ['application/sql', 'application/x-sql', 'text/x-sql'], + 'sqlite2' => ['application/x-sqlite2'], + 'sqlite3' => ['application/vnd.sqlite3', 'application/x-sqlite3'], + 'sqsh' => ['application/vnd.squashfs'], + 'sr2' => ['image/x-sony-sr2'], + 'src' => ['application/x-wais-source'], + 'src.rpm' => ['application/x-source-rpm'], + 'srf' => ['image/x-sony-srf'], + 'srt' => ['application/x-srt', 'application/x-subrip'], + 'sru' => ['application/sru+xml'], + 'srx' => ['application/sparql-results+xml'], + 'ss' => ['text/x-scheme'], + 'ssa' => ['text/x-ssa'], + 'ssdl' => ['application/ssdl+xml'], + 'sse' => ['application/vnd.kodak-descriptor'], + 'ssf' => ['application/vnd.epson.ssf'], + 'ssml' => ['application/ssml+xml'], + 'st' => ['application/vnd.sailingtracker.track'], + 'stc' => ['application/vnd.sun.xml.calc.template'], + 'std' => ['application/vnd.sun.xml.draw.template'], + 'stf' => ['application/vnd.wt.stf'], + 'sti' => ['application/vnd.sun.xml.impress.template'], + 'stk' => ['application/hyperstudio'], + 'stl' => ['application/vnd.ms-pki.stl', 'model/stl', 'model/x.stl-ascii', 'model/x.stl-binary'], + 'stm' => ['audio/x-stm'], + 'str' => ['application/vnd.pg.format'], + 'stw' => ['application/vnd.sun.xml.writer.template'], + 'sty' => ['application/x-tex', 'text/x-tex'], + 'sub' => ['image/vnd.dvb.subtitle', 'text/vnd.dvb.subtitle', 'text/x-microdvd', 'text/x-mpsub', 'text/x-subviewer'], + 'sun' => ['image/x-sun-raster'], + 'sus' => ['application/vnd.sus-calendar'], + 'susp' => ['application/vnd.sus-calendar'], + 'sv' => ['text/x-svsrc'], + 'sv4cpio' => ['application/x-sv4cpio'], + 'sv4crc' => ['application/x-sv4crc'], + 'svc' => ['application/vnd.dvb.service'], + 'svd' => ['application/vnd.svd'], + 'svg' => ['image/svg+xml', 'image/svg'], + 'svgz' => ['image/svg+xml', 'image/svg+xml-compressed'], + 'svh' => ['text/x-svhdr'], + 'swa' => ['application/x-director'], + 'swap' => ['text/x-systemd-unit'], + 'swf' => ['application/futuresplash', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash'], + 'swi' => ['application/vnd.aristanetworks.swi'], + 'swm' => ['application/x-ms-wim'], + 'sxc' => ['application/vnd.sun.xml.calc'], + 'sxd' => ['application/vnd.sun.xml.draw'], + 'sxg' => ['application/vnd.sun.xml.writer.global'], + 'sxi' => ['application/vnd.sun.xml.impress'], + 'sxm' => ['application/vnd.sun.xml.math'], + 'sxw' => ['application/vnd.sun.xml.writer'], + 'sylk' => ['text/spreadsheet'], + 't' => ['application/x-perl', 'application/x-troff', 'text/troff', 'text/x-perl', 'text/x-troff'], + 't2t' => ['text/x-txt2tags'], + 't3' => ['application/x-t3vm-image'], + 'taglet' => ['application/vnd.mynfc'], + 'tao' => ['application/vnd.tao.intent-module-archive'], + 'tar' => ['application/x-tar', 'application/x-gtar'], + 'tar.Z' => ['application/x-tarz'], + 'tar.bz' => ['application/x-bzip-compressed-tar'], + 'tar.bz2' => ['application/x-bzip-compressed-tar'], + 'tar.gz' => ['application/x-compressed-tar'], + 'tar.lrz' => ['application/x-lrzip-compressed-tar'], + 'tar.lz' => ['application/x-lzip-compressed-tar'], + 'tar.lz4' => ['application/x-lz4-compressed-tar'], + 'tar.lzma' => ['application/x-lzma-compressed-tar'], + 'tar.lzo' => ['application/x-tzo'], + 'tar.xz' => ['application/x-xz-compressed-tar'], + 'target' => ['text/x-systemd-unit'], + 'taz' => ['application/x-tarz'], + 'tb2' => ['application/x-bzip-compressed-tar'], + 'tbz' => ['application/x-bzip-compressed-tar'], + 'tbz2' => ['application/x-bzip-compressed-tar'], + 'tcap' => ['application/vnd.3gpp2.tcap'], + 'tcl' => ['application/x-tcl', 'text/x-tcl'], + 'teacher' => ['application/vnd.smart.teacher'], + 'tei' => ['application/tei+xml'], + 'teicorpus' => ['application/tei+xml'], + 'tex' => ['application/x-tex', 'text/x-tex'], + 'texi' => ['application/x-texinfo', 'text/x-texinfo'], + 'texinfo' => ['application/x-texinfo', 'text/x-texinfo'], + 'text' => ['text/plain'], + 'tfi' => ['application/thraud+xml'], + 'tfm' => ['application/x-tex-tfm'], + 'tga' => ['image/x-icb', 'image/x-tga'], + 'tgz' => ['application/x-compressed-tar'], + 'theme' => ['application/x-theme'], + 'themepack' => ['application/x-windows-themepack'], + 'thmx' => ['application/vnd.ms-officetheme'], + 'tif' => ['image/tiff'], + 'tiff' => ['image/tiff'], + 'timer' => ['text/x-systemd-unit'], + 'tk' => ['text/x-tcl'], + 'tlrz' => ['application/x-lrzip-compressed-tar'], + 'tlz' => ['application/x-lzma-compressed-tar'], + 'tmo' => ['application/vnd.tmobile-livetv'], + 'tnef' => ['application/ms-tnef', 'application/vnd.ms-tnef'], + 'tnf' => ['application/ms-tnef', 'application/vnd.ms-tnef'], + 'toc' => ['application/x-cdrdao-toc'], + 'torrent' => ['application/x-bittorrent'], + 'tpic' => ['image/x-icb', 'image/x-tga'], + 'tpl' => ['application/vnd.groove-tool-template'], + 'tpt' => ['application/vnd.trid.tpt'], + 'tr' => ['application/x-troff', 'text/troff', 'text/x-troff'], + 'tra' => ['application/vnd.trueapp'], + 'trig' => ['application/trig', 'application/x-trig'], + 'trm' => ['application/x-msterminal'], + 'ts' => ['application/x-linguist', 'text/vnd.qt.linguist', 'text/vnd.trolltech.linguist', 'video/mp2t'], + 'tsd' => ['application/timestamped-data'], + 'tsv' => ['text/tab-separated-values'], + 'tta' => ['audio/tta', 'audio/x-tta'], + 'ttc' => ['font/collection'], + 'ttf' => ['application/x-font-truetype', 'application/x-font-ttf', 'font/ttf'], + 'ttl' => ['text/turtle'], + 'ttx' => ['application/x-font-ttx'], + 'twd' => ['application/vnd.simtech-mindmapper'], + 'twds' => ['application/vnd.simtech-mindmapper'], + 'twig' => ['text/x-twig'], + 'txd' => ['application/vnd.genomatix.tuxedo'], + 'txf' => ['application/vnd.mobius.txf'], + 'txt' => ['text/plain'], + 'txz' => ['application/x-xz-compressed-tar'], + 'tzo' => ['application/x-tzo'], + 'u32' => ['application/x-authorware-bin'], + 'udeb' => ['application/vnd.debian.binary-package', 'application/x-deb', 'application/x-debian-package'], + 'ufd' => ['application/vnd.ufdl'], + 'ufdl' => ['application/vnd.ufdl'], + 'ufraw' => ['application/x-ufraw'], + 'ui' => ['application/x-designer', 'application/x-gtk-builder'], + 'uil' => ['text/x-uil'], + 'ult' => ['audio/x-mod'], + 'ulx' => ['application/x-glulx'], + 'umj' => ['application/vnd.umajin'], + 'unf' => ['application/x-nes-rom'], + 'uni' => ['audio/x-mod'], + 'unif' => ['application/x-nes-rom'], + 'unityweb' => ['application/vnd.unity'], + 'uoml' => ['application/vnd.uoml+xml'], + 'uri' => ['text/uri-list'], + 'uris' => ['text/uri-list'], + 'url' => ['application/x-mswinurl'], + 'urls' => ['text/uri-list'], + 'ustar' => ['application/x-ustar'], + 'utz' => ['application/vnd.uiq.theme'], + 'uu' => ['text/x-uuencode'], + 'uue' => ['text/x-uuencode', 'zz-application/zz-winassoc-uu'], + 'uva' => ['audio/vnd.dece.audio'], + 'uvd' => ['application/vnd.dece.data'], + 'uvf' => ['application/vnd.dece.data'], + 'uvg' => ['image/vnd.dece.graphic'], + 'uvh' => ['video/vnd.dece.hd'], + 'uvi' => ['image/vnd.dece.graphic'], + 'uvm' => ['video/vnd.dece.mobile'], + 'uvp' => ['video/vnd.dece.pd'], + 'uvs' => ['video/vnd.dece.sd'], + 'uvt' => ['application/vnd.dece.ttml+xml'], + 'uvu' => ['video/vnd.uvvu.mp4'], + 'uvv' => ['video/vnd.dece.video'], + 'uvva' => ['audio/vnd.dece.audio'], + 'uvvd' => ['application/vnd.dece.data'], + 'uvvf' => ['application/vnd.dece.data'], + 'uvvg' => ['image/vnd.dece.graphic'], + 'uvvh' => ['video/vnd.dece.hd'], + 'uvvi' => ['image/vnd.dece.graphic'], + 'uvvm' => ['video/vnd.dece.mobile'], + 'uvvp' => ['video/vnd.dece.pd'], + 'uvvs' => ['video/vnd.dece.sd'], + 'uvvt' => ['application/vnd.dece.ttml+xml'], + 'uvvu' => ['video/vnd.uvvu.mp4'], + 'uvvv' => ['video/vnd.dece.video'], + 'uvvx' => ['application/vnd.dece.unspecified'], + 'uvvz' => ['application/vnd.dece.zip'], + 'uvx' => ['application/vnd.dece.unspecified'], + 'uvz' => ['application/vnd.dece.zip'], + 'v' => ['text/x-verilog'], + 'v64' => ['application/x-n64-rom'], + 'vala' => ['text/x-vala'], + 'vapi' => ['text/x-vala'], + 'vb' => ['application/x-virtual-boy-rom'], + 'vcard' => ['text/directory', 'text/vcard', 'text/x-vcard'], + 'vcd' => ['application/x-cdlink'], + 'vcf' => ['text/x-vcard', 'text/directory', 'text/vcard'], + 'vcg' => ['application/vnd.groove-vcard'], + 'vcs' => ['application/ics', 'text/calendar', 'text/x-vcalendar'], + 'vct' => ['text/directory', 'text/vcard', 'text/x-vcard'], + 'vcx' => ['application/vnd.vcx'], + 'vda' => ['image/x-icb', 'image/x-tga'], + 'vhd' => ['text/x-vhdl'], + 'vhdl' => ['text/x-vhdl'], + 'vis' => ['application/vnd.visionary'], + 'viv' => ['video/vivo', 'video/vnd.vivo'], + 'vivo' => ['video/vivo', 'video/vnd.vivo'], + 'vlc' => ['application/m3u', 'audio/m3u', 'audio/mpegurl', 'audio/x-m3u', 'audio/x-mp3-playlist', 'audio/x-mpegurl'], + 'vob' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2', 'video/x-ms-vob'], + 'voc' => ['audio/x-voc'], + 'vor' => ['application/vnd.stardivision.writer', 'application/vnd.stardivision.writer-global'], + 'vox' => ['application/x-authorware-bin'], + 'vrm' => ['model/vrml'], + 'vrml' => ['model/vrml'], + 'vsd' => ['application/vnd.visio'], + 'vsdm' => ['application/vnd.ms-visio.drawing.macroenabled.main+xml'], + 'vsdx' => ['application/vnd.ms-visio.drawing.main+xml'], + 'vsf' => ['application/vnd.vsf'], + 'vss' => ['application/vnd.visio'], + 'vssm' => ['application/vnd.ms-visio.stencil.macroenabled.main+xml'], + 'vssx' => ['application/vnd.ms-visio.stencil.main+xml'], + 'vst' => ['application/vnd.visio', 'image/x-icb', 'image/x-tga'], + 'vstm' => ['application/vnd.ms-visio.template.macroenabled.main+xml'], + 'vstx' => ['application/vnd.ms-visio.template.main+xml'], + 'vsw' => ['application/vnd.visio'], + 'vtt' => ['text/vtt'], + 'vtu' => ['model/vnd.vtu'], + 'vxml' => ['application/voicexml+xml'], + 'w3d' => ['application/x-director'], + 'wad' => ['application/x-doom', 'application/x-doom-wad', 'application/x-wii-wad'], + 'wav' => ['audio/wav', 'audio/vnd.wave', 'audio/x-wav'], + 'wax' => ['application/x-ms-asx', 'audio/x-ms-asx', 'audio/x-ms-wax', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], + 'wb1' => ['application/x-quattropro'], + 'wb2' => ['application/x-quattropro'], + 'wb3' => ['application/x-quattropro'], + 'wbmp' => ['image/vnd.wap.wbmp'], + 'wbs' => ['application/vnd.criticaltools.wbs+xml'], + 'wbxml' => ['application/vnd.wap.wbxml'], + 'wcm' => ['application/vnd.ms-works'], + 'wdb' => ['application/vnd.ms-works'], + 'wdp' => ['image/vnd.ms-photo'], + 'weba' => ['audio/webm'], + 'webm' => ['video/webm'], + 'webp' => ['image/webp'], + 'wg' => ['application/vnd.pmi.widget'], + 'wgt' => ['application/widget'], + 'wim' => ['application/x-ms-wim'], + 'wk1' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], + 'wk3' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], + 'wk4' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], + 'wkdownload' => ['application/x-partial-download'], + 'wks' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/vnd.ms-works', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], + 'wm' => ['video/x-ms-wm'], + 'wma' => ['audio/x-ms-wma', 'audio/wma'], + 'wmd' => ['application/x-ms-wmd'], + 'wmf' => ['application/wmf', 'application/x-msmetafile', 'application/x-wmf', 'image/wmf', 'image/x-win-metafile', 'image/x-wmf'], + 'wml' => ['text/vnd.wap.wml'], + 'wmlc' => ['application/vnd.wap.wmlc'], + 'wmls' => ['text/vnd.wap.wmlscript'], + 'wmlsc' => ['application/vnd.wap.wmlscriptc'], + 'wmv' => ['audio/x-ms-wmv', 'video/x-ms-wmv'], + 'wmx' => ['application/x-ms-asx', 'audio/x-ms-asx', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], + 'wmz' => ['application/x-ms-wmz', 'application/x-msmetafile'], + 'woff' => ['application/font-woff', 'application/x-font-woff', 'font/woff'], + 'woff2' => ['font/woff', 'font/woff2'], + 'wp' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], + 'wp4' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], + 'wp5' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], + 'wp6' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], + 'wpd' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], + 'wpg' => ['application/x-wpg'], + 'wpl' => ['application/vnd.ms-wpl'], + 'wpp' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], + 'wps' => ['application/vnd.ms-works'], + 'wqd' => ['application/vnd.wqd'], + 'wri' => ['application/x-mswrite'], + 'wrl' => ['model/vrml'], + 'ws' => ['application/x-wonderswan-rom'], + 'wsc' => ['application/x-wonderswan-color-rom'], + 'wsdl' => ['application/wsdl+xml'], + 'wsgi' => ['text/x-python'], + 'wspolicy' => ['application/wspolicy+xml'], + 'wtb' => ['application/vnd.webturbo'], + 'wv' => ['audio/x-wavpack'], + 'wvc' => ['audio/x-wavpack-correction'], + 'wvp' => ['audio/x-wavpack'], + 'wvx' => ['application/x-ms-asx', 'audio/x-ms-asx', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], + 'wwf' => ['application/wwf', 'application/x-wwf'], + 'x32' => ['application/x-authorware-bin'], + 'x3d' => ['model/x3d+xml'], + 'x3db' => ['model/x3d+binary'], + 'x3dbz' => ['model/x3d+binary'], + 'x3dv' => ['model/x3d+vrml'], + 'x3dvz' => ['model/x3d+vrml'], + 'x3dz' => ['model/x3d+xml'], + 'x3f' => ['image/x-sigma-x3f'], + 'xac' => ['application/x-gnucash'], + 'xaml' => ['application/xaml+xml'], + 'xap' => ['application/x-silverlight-app'], + 'xar' => ['application/vnd.xara', 'application/x-xar'], + 'xbap' => ['application/x-ms-xbap'], + 'xbd' => ['application/vnd.fujixerox.docuworks.binder'], + 'xbel' => ['application/x-xbel'], + 'xbl' => ['application/xml', 'text/xml'], + 'xbm' => ['image/x-xbitmap'], + 'xcf' => ['image/x-xcf'], + 'xcf.bz2' => ['image/x-compressed-xcf'], + 'xcf.gz' => ['image/x-compressed-xcf'], + 'xdf' => ['application/xcap-diff+xml'], + 'xdgapp' => ['application/vnd.flatpak', 'application/vnd.xdgapp'], + 'xdm' => ['application/vnd.syncml.dm+xml'], + 'xdp' => ['application/vnd.adobe.xdp+xml'], + 'xdssc' => ['application/dssc+xml'], + 'xdw' => ['application/vnd.fujixerox.docuworks'], + 'xenc' => ['application/xenc+xml'], + 'xer' => ['application/patch-ops-error+xml'], + 'xfdf' => ['application/vnd.adobe.xfdf'], + 'xfdl' => ['application/vnd.xfdl'], + 'xhe' => ['audio/usac'], + 'xht' => ['application/xhtml+xml'], + 'xhtml' => ['application/xhtml+xml'], + 'xhvml' => ['application/xv+xml'], + 'xi' => ['audio/x-xi'], + 'xif' => ['image/vnd.xiff'], + 'xla' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xlam' => ['application/vnd.ms-excel.addin.macroenabled.12'], + 'xlc' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xld' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xlf' => ['application/x-xliff', 'application/x-xliff+xml', 'application/xliff+xml'], + 'xliff' => ['application/x-xliff', 'application/xliff+xml'], + 'xll' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xlm' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xlr' => ['application/vnd.ms-works'], + 'xls' => ['application/vnd.ms-excel', 'application/msexcel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xlsb' => ['application/vnd.ms-excel.sheet.binary.macroenabled.12'], + 'xlsm' => ['application/vnd.ms-excel.sheet.macroenabled.12'], + 'xlsx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], + 'xlt' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xltm' => ['application/vnd.ms-excel.template.macroenabled.12'], + 'xltx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.template'], + 'xlw' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xm' => ['audio/x-xm', 'audio/xm'], + 'xmf' => ['audio/mobile-xmf', 'audio/x-xmf', 'audio/xmf'], + 'xmi' => ['text/x-xmi'], + 'xml' => ['application/xml', 'text/xml'], + 'xo' => ['application/vnd.olpc-sugar'], + 'xop' => ['application/xop+xml'], + 'xpi' => ['application/x-xpinstall'], + 'xpl' => ['application/xproc+xml'], + 'xpm' => ['image/x-xpixmap', 'image/x-xpm'], + 'xpr' => ['application/vnd.is-xpr'], + 'xps' => ['application/oxps', 'application/vnd.ms-xpsdocument', 'application/xps'], + 'xpw' => ['application/vnd.intercon.formnet'], + 'xpx' => ['application/vnd.intercon.formnet'], + 'xsd' => ['application/xml', 'text/xml'], + 'xsl' => ['application/xml', 'application/xslt+xml'], + 'xslfo' => ['text/x-xslfo'], + 'xslt' => ['application/xslt+xml'], + 'xsm' => ['application/vnd.syncml+xml'], + 'xspf' => ['application/x-xspf+xml', 'application/xspf+xml'], + 'xul' => ['application/vnd.mozilla.xul+xml'], + 'xvm' => ['application/xv+xml'], + 'xvml' => ['application/xv+xml'], + 'xwd' => ['image/x-xwindowdump'], + 'xyz' => ['chemical/x-xyz'], + 'xz' => ['application/x-xz'], + 'yaml' => ['application/x-yaml', 'text/x-yaml', 'text/yaml'], + 'yang' => ['application/yang'], + 'yin' => ['application/yin+xml'], + 'yml' => ['application/x-yaml', 'text/x-yaml', 'text/yaml'], + 'yt' => ['application/vnd.youtube.yt'], + 'z1' => ['application/x-zmachine'], + 'z2' => ['application/x-zmachine'], + 'z3' => ['application/x-zmachine'], + 'z4' => ['application/x-zmachine'], + 'z5' => ['application/x-zmachine'], + 'z6' => ['application/x-zmachine'], + 'z64' => ['application/x-n64-rom'], + 'z7' => ['application/x-zmachine'], + 'z8' => ['application/x-zmachine'], + 'zabw' => ['application/x-abiword'], + 'zaz' => ['application/vnd.zzazz.deck+xml'], + 'zip' => ['application/zip', 'application/x-zip', 'application/x-zip-compressed'], + 'zir' => ['application/vnd.zul'], + 'zirz' => ['application/vnd.zul'], + 'zmm' => ['application/vnd.handheld-entertainment+xml'], + 'zoo' => ['application/x-zoo'], + 'zsav' => ['application/x-spss-sav', 'application/x-spss-savefile'], + 'zz' => ['application/zlib'], + '123' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], + '602' => ['application/x-t602'], + '669' => ['audio/x-mod'], + ]; +} diff --git a/vendor/symfony/mime/MimeTypesInterface.php b/vendor/symfony/mime/MimeTypesInterface.php new file mode 100644 index 0000000..9fbd2cc --- /dev/null +++ b/vendor/symfony/mime/MimeTypesInterface.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +/** + * @author Fabien Potencier + */ +interface MimeTypesInterface extends MimeTypeGuesserInterface +{ + /** + * Gets the extensions for the given MIME type. + * + * @return string[] an array of extensions (first one is the preferred one) + */ + public function getExtensions(string $mimeType): array; + + /** + * Gets the MIME types for the given extension. + * + * @return string[] an array of MIME types (first one is the preferred one) + */ + public function getMimeTypes(string $ext): array; +} diff --git a/vendor/symfony/mime/Part/AbstractMultipartPart.php b/vendor/symfony/mime/Part/AbstractMultipartPart.php new file mode 100644 index 0000000..48b8620 --- /dev/null +++ b/vendor/symfony/mime/Part/AbstractMultipartPart.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part; + +use Symfony\Component\Mime\Header\Headers; + +/** + * @author Fabien Potencier + */ +abstract class AbstractMultipartPart extends AbstractPart +{ + private $boundary; + private $parts = []; + + public function __construct(AbstractPart ...$parts) + { + parent::__construct(); + + foreach ($parts as $part) { + $this->parts[] = $part; + } + } + + /** + * @return AbstractPart[] + */ + public function getParts(): array + { + return $this->parts; + } + + public function getMediaType(): string + { + return 'multipart'; + } + + public function getPreparedHeaders(): Headers + { + $headers = parent::getPreparedHeaders(); + $headers->setHeaderParameter('Content-Type', 'boundary', $this->getBoundary()); + + return $headers; + } + + public function bodyToString(): string + { + $parts = $this->getParts(); + $string = ''; + foreach ($parts as $part) { + $string .= '--'.$this->getBoundary()."\r\n".$part->toString()."\r\n"; + } + $string .= '--'.$this->getBoundary()."--\r\n"; + + return $string; + } + + public function bodyToIterable(): iterable + { + $parts = $this->getParts(); + foreach ($parts as $part) { + yield '--'.$this->getBoundary()."\r\n"; + yield from $part->toIterable(); + yield "\r\n"; + } + yield '--'.$this->getBoundary()."--\r\n"; + } + + public function asDebugString(): string + { + $str = parent::asDebugString(); + foreach ($this->getParts() as $part) { + $lines = explode("\n", $part->asDebugString()); + $str .= "\n └ ".array_shift($lines); + foreach ($lines as $line) { + $str .= "\n |".$line; + } + } + + return $str; + } + + private function getBoundary(): string + { + if (null === $this->boundary) { + $this->boundary = '_=_symfony_'.time().'_'.bin2hex(random_bytes(16)).'_=_'; + } + + return $this->boundary; + } +} diff --git a/vendor/symfony/mime/Part/AbstractPart.php b/vendor/symfony/mime/Part/AbstractPart.php new file mode 100644 index 0000000..93892d9 --- /dev/null +++ b/vendor/symfony/mime/Part/AbstractPart.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part; + +use Symfony\Component\Mime\Header\Headers; + +/** + * @author Fabien Potencier + */ +abstract class AbstractPart +{ + private $headers; + + public function __construct() + { + $this->headers = new Headers(); + } + + public function getHeaders(): Headers + { + return $this->headers; + } + + public function getPreparedHeaders(): Headers + { + $headers = clone $this->headers; + $headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype()); + + return $headers; + } + + public function toString(): string + { + return $this->getPreparedHeaders()->toString()."\r\n".$this->bodyToString(); + } + + public function toIterable(): iterable + { + yield $this->getPreparedHeaders()->toString(); + yield "\r\n"; + yield from $this->bodyToIterable(); + } + + public function asDebugString(): string + { + return $this->getMediaType().'/'.$this->getMediaSubtype(); + } + + abstract public function bodyToString(): string; + + abstract public function bodyToIterable(): iterable; + + abstract public function getMediaType(): string; + + abstract public function getMediaSubtype(): string; +} diff --git a/vendor/symfony/mime/Part/DataPart.php b/vendor/symfony/mime/Part/DataPart.php new file mode 100644 index 0000000..423185f --- /dev/null +++ b/vendor/symfony/mime/Part/DataPart.php @@ -0,0 +1,161 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part; + +use Symfony\Component\Mime\Exception\InvalidArgumentException; +use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\MimeTypes; + +/** + * @author Fabien Potencier + */ +class DataPart extends TextPart +{ + private static $mimeTypes; + + private $filename; + private $mediaType; + private $cid; + private $handle; + + /** + * @param resource|string $body + */ + public function __construct($body, string $filename = null, string $contentType = null, string $encoding = null) + { + if (null === $contentType) { + $contentType = 'application/octet-stream'; + } + list($this->mediaType, $subtype) = explode('/', $contentType); + + parent::__construct($body, null, $subtype, $encoding); + + $this->filename = $filename; + $this->setName($filename); + $this->setDisposition('attachment'); + } + + public static function fromPath(string $path, string $name = null, string $contentType = null): self + { + // FIXME: if file is not readable, exception? + + if (null === $contentType) { + $ext = strtolower(substr($path, strrpos($path, '.') + 1)); + if (null === self::$mimeTypes) { + self::$mimeTypes = new MimeTypes(); + } + $contentType = self::$mimeTypes->getMimeTypes($ext)[0] ?? 'application/octet-stream'; + } + + if (false === $handle = @fopen($path, 'r', false)) { + throw new InvalidArgumentException(sprintf('Unable to open path "%s"', $path)); + } + $p = new self($handle, $name ?: basename($path), $contentType); + $p->handle = $handle; + + return $p; + } + + /** + * @return $this + */ + public function asInline() + { + return $this->setDisposition('inline'); + } + + public function getContentId(): string + { + return $this->cid ?: $this->cid = $this->generateContentId(); + } + + public function hasContentId(): bool + { + return null !== $this->cid; + } + + public function getMediaType(): string + { + return $this->mediaType; + } + + public function getPreparedHeaders(): Headers + { + $headers = parent::getPreparedHeaders(); + + if (null !== $this->cid) { + $headers->setHeaderBody('Id', 'Content-ID', $this->cid); + } + + if (null !== $this->filename) { + $headers->setHeaderParameter('Content-Disposition', 'filename', $this->filename); + } + + return $headers; + } + + public function asDebugString(): string + { + $str = parent::asDebugString(); + if (null !== $this->filename) { + $str .= ' filename: '.$this->filename; + } + + return $str; + } + + private function generateContentId(): string + { + return bin2hex(random_bytes(16)).'@symfony'; + } + + public function __destruct() + { + if (null !== $this->handle && \is_resource($this->handle)) { + fclose($this->handle); + } + } + + /** + * @return array + */ + public function __sleep() + { + // converts the body to a string + parent::__sleep(); + + $this->_parent = []; + foreach (['body', 'charset', 'subtype', 'disposition', 'name', 'encoding'] as $name) { + $r = new \ReflectionProperty(TextPart::class, $name); + $r->setAccessible(true); + $this->_parent[$name] = $r->getValue($this); + } + $this->_headers = $this->getHeaders(); + + return ['_headers', '_parent', 'filename', 'mediaType']; + } + + public function __wakeup() + { + $r = new \ReflectionProperty(AbstractPart::class, 'headers'); + $r->setAccessible(true); + $r->setValue($this, $this->_headers); + unset($this->_headers); + + foreach (['body', 'charset', 'subtype', 'disposition', 'name', 'encoding'] as $name) { + $r = new \ReflectionProperty(TextPart::class, $name); + $r->setAccessible(true); + $r->setValue($this, $this->_parent[$name]); + } + unset($this->_parent); + } +} diff --git a/vendor/symfony/mime/Part/MessagePart.php b/vendor/symfony/mime/Part/MessagePart.php new file mode 100644 index 0000000..1b5c23e --- /dev/null +++ b/vendor/symfony/mime/Part/MessagePart.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part; + +use Symfony\Component\Mime\Message; +use Symfony\Component\Mime\RawMessage; + +/** + * @final + * + * @author Fabien Potencier + */ +class MessagePart extends DataPart +{ + private $message; + + public function __construct(RawMessage $message) + { + if ($message instanceof Message) { + $name = $message->getHeaders()->getHeaderBody('Subject').'.eml'; + } else { + $name = 'email.eml'; + } + parent::__construct('', $name); + + $this->message = $message; + } + + public function getMediaType(): string + { + return 'message'; + } + + public function getMediaSubtype(): string + { + return 'rfc822'; + } + + public function getBody(): string + { + return $this->message->toString(); + } + + public function bodyToString(): string + { + return $this->getBody(); + } + + public function bodyToIterable(): iterable + { + return $this->message->toIterable(); + } +} diff --git a/vendor/symfony/mime/Part/Multipart/AlternativePart.php b/vendor/symfony/mime/Part/Multipart/AlternativePart.php new file mode 100644 index 0000000..fd75423 --- /dev/null +++ b/vendor/symfony/mime/Part/Multipart/AlternativePart.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part\Multipart; + +use Symfony\Component\Mime\Part\AbstractMultipartPart; + +/** + * @author Fabien Potencier + */ +final class AlternativePart extends AbstractMultipartPart +{ + public function getMediaSubtype(): string + { + return 'alternative'; + } +} diff --git a/vendor/symfony/mime/Part/Multipart/DigestPart.php b/vendor/symfony/mime/Part/Multipart/DigestPart.php new file mode 100644 index 0000000..27537f1 --- /dev/null +++ b/vendor/symfony/mime/Part/Multipart/DigestPart.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part\Multipart; + +use Symfony\Component\Mime\Part\AbstractMultipartPart; +use Symfony\Component\Mime\Part\MessagePart; + +/** + * @author Fabien Potencier + */ +final class DigestPart extends AbstractMultipartPart +{ + public function __construct(MessagePart ...$parts) + { + parent::__construct(...$parts); + } + + public function getMediaSubtype(): string + { + return 'digest'; + } +} diff --git a/vendor/symfony/mime/Part/Multipart/FormDataPart.php b/vendor/symfony/mime/Part/Multipart/FormDataPart.php new file mode 100644 index 0000000..6838620 --- /dev/null +++ b/vendor/symfony/mime/Part/Multipart/FormDataPart.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part\Multipart; + +use Symfony\Component\Mime\Exception\InvalidArgumentException; +use Symfony\Component\Mime\Part\AbstractMultipartPart; +use Symfony\Component\Mime\Part\DataPart; +use Symfony\Component\Mime\Part\TextPart; + +/** + * Implements RFC 7578. + * + * @author Fabien Potencier + */ +final class FormDataPart extends AbstractMultipartPart +{ + private $fields = []; + + /** + * @param (string|array|DataPart)[] $fields + */ + public function __construct(array $fields = []) + { + parent::__construct(); + + foreach ($fields as $name => $value) { + if (!\is_string($value) && !\is_array($value) && !$value instanceof TextPart) { + throw new InvalidArgumentException(sprintf('A form field value can only be a string, an array, or an instance of TextPart ("%s" given).', \is_object($value) ? \get_class($value) : \gettype($value))); + } + + $this->fields[$name] = $value; + } + // HTTP does not support \r\n in header values + $this->getHeaders()->setMaxLineLength(PHP_INT_MAX); + } + + public function getMediaSubtype(): string + { + return 'form-data'; + } + + public function getParts(): array + { + return $this->prepareFields($this->fields); + } + + private function prepareFields(array $fields): array + { + $values = []; + + $prepare = function ($item, $key, $root = null) use (&$values, &$prepare) { + $fieldName = $root ? sprintf('%s[%s]', $root, $key) : $key; + + if (\is_array($item)) { + array_walk($item, $prepare, $fieldName); + + return; + } + + $values[] = $this->preparePart($fieldName, $item); + }; + + array_walk($fields, $prepare); + + return $values; + } + + private function preparePart(string $name, $value): TextPart + { + if (\is_string($value)) { + return $this->configurePart($name, new TextPart($value, 'utf-8', 'plain', '8bit')); + } + + return $this->configurePart($name, $value); + } + + private function configurePart(string $name, TextPart $part): TextPart + { + static $r; + + if (null === $r) { + $r = new \ReflectionProperty(TextPart::class, 'encoding'); + $r->setAccessible(true); + } + + $part->setDisposition('form-data'); + $part->setName($name); + // HTTP does not support \r\n in header values + $part->getHeaders()->setMaxLineLength(PHP_INT_MAX); + $r->setValue($part, '8bit'); + + return $part; + } +} diff --git a/vendor/symfony/mime/Part/Multipart/MixedPart.php b/vendor/symfony/mime/Part/Multipart/MixedPart.php new file mode 100644 index 0000000..c8d7028 --- /dev/null +++ b/vendor/symfony/mime/Part/Multipart/MixedPart.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part\Multipart; + +use Symfony\Component\Mime\Part\AbstractMultipartPart; + +/** + * @author Fabien Potencier + */ +final class MixedPart extends AbstractMultipartPart +{ + public function getMediaSubtype(): string + { + return 'mixed'; + } +} diff --git a/vendor/symfony/mime/Part/Multipart/RelatedPart.php b/vendor/symfony/mime/Part/Multipart/RelatedPart.php new file mode 100644 index 0000000..08fdd5f --- /dev/null +++ b/vendor/symfony/mime/Part/Multipart/RelatedPart.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part\Multipart; + +use Symfony\Component\Mime\Part\AbstractMultipartPart; +use Symfony\Component\Mime\Part\AbstractPart; + +/** + * @author Fabien Potencier + */ +final class RelatedPart extends AbstractMultipartPart +{ + private $mainPart; + + public function __construct(AbstractPart $mainPart, AbstractPart $part, AbstractPart ...$parts) + { + $this->mainPart = $mainPart; + $this->prepareParts($part, ...$parts); + + parent::__construct($part, ...$parts); + } + + public function getParts(): array + { + return array_merge([$this->mainPart], parent::getParts()); + } + + public function getMediaSubtype(): string + { + return 'related'; + } + + private function generateContentId(): string + { + return bin2hex(random_bytes(16)).'@symfony'; + } + + private function prepareParts(AbstractPart ...$parts): void + { + foreach ($parts as $part) { + if (!$part->getHeaders()->has('Content-ID')) { + $part->getHeaders()->setHeaderBody('Id', 'Content-ID', $this->generateContentId()); + } + } + } +} diff --git a/vendor/symfony/mime/Part/SMimePart.php b/vendor/symfony/mime/Part/SMimePart.php new file mode 100644 index 0000000..1dfc1ae --- /dev/null +++ b/vendor/symfony/mime/Part/SMimePart.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part; + +use Symfony\Component\Mime\Header\Headers; + +/** + * @author Sebastiaan Stok + */ +class SMimePart extends AbstractPart +{ + private $body; + private $type; + private $subtype; + private $parameters; + + /** + * @param iterable|string $body + */ + public function __construct($body, string $type, string $subtype, array $parameters) + { + parent::__construct(); + + if (!\is_string($body) && !is_iterable($body)) { + throw new \TypeError(sprintf('The body of "%s" must be a string or a iterable (got "%s").', self::class, \is_object($body) ? \get_class($body) : \gettype($body))); + } + + $this->body = $body; + $this->type = $type; + $this->subtype = $subtype; + $this->parameters = $parameters; + } + + public function getMediaType(): string + { + return $this->type; + } + + public function getMediaSubtype(): string + { + return $this->subtype; + } + + public function bodyToString(): string + { + if (\is_string($this->body)) { + return $this->body; + } + + $body = ''; + foreach ($this->body as $chunk) { + $body .= $chunk; + } + $this->body = $body; + + return $body; + } + + public function bodyToIterable(): iterable + { + if (\is_string($this->body)) { + yield $this->body; + + return; + } + + $body = ''; + foreach ($this->body as $chunk) { + $body .= $chunk; + yield $chunk; + } + $this->body = $body; + } + + public function getPreparedHeaders(): Headers + { + $headers = clone parent::getHeaders(); + + $headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype()); + + foreach ($this->parameters as $name => $value) { + $headers->setHeaderParameter('Content-Type', $name, $value); + } + + return $headers; + } + + public function __sleep(): array + { + // convert iterables to strings for serialization + if (is_iterable($this->body)) { + $this->body = $this->bodyToString(); + } + + $this->_headers = $this->getHeaders(); + + return ['_headers', 'body', 'type', 'subtype', 'parameters']; + } + + public function __wakeup(): void + { + $r = new \ReflectionProperty(AbstractPart::class, 'headers'); + $r->setAccessible(true); + $r->setValue($this, $this->_headers); + unset($this->_headers); + } +} diff --git a/vendor/symfony/mime/Part/TextPart.php b/vendor/symfony/mime/Part/TextPart.php new file mode 100644 index 0000000..a41d91d --- /dev/null +++ b/vendor/symfony/mime/Part/TextPart.php @@ -0,0 +1,204 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part; + +use Symfony\Component\Mime\Encoder\Base64ContentEncoder; +use Symfony\Component\Mime\Encoder\ContentEncoderInterface; +use Symfony\Component\Mime\Encoder\EightBitContentEncoder; +use Symfony\Component\Mime\Encoder\QpContentEncoder; +use Symfony\Component\Mime\Exception\InvalidArgumentException; +use Symfony\Component\Mime\Header\Headers; + +/** + * @author Fabien Potencier + */ +class TextPart extends AbstractPart +{ + private static $encoders = []; + + private $body; + private $charset; + private $subtype; + private $disposition; + private $name; + private $encoding; + + /** + * @param resource|string $body + */ + public function __construct($body, ?string $charset = 'utf-8', $subtype = 'plain', string $encoding = null) + { + parent::__construct(); + + if (!\is_string($body) && !\is_resource($body)) { + throw new \TypeError(sprintf('The body of "%s" must be a string or a resource (got "%s").', self::class, \is_object($body) ? \get_class($body) : \gettype($body))); + } + + $this->body = $body; + $this->charset = $charset; + $this->subtype = $subtype; + + if (null === $encoding) { + $this->encoding = $this->chooseEncoding(); + } else { + if ('quoted-printable' !== $encoding && 'base64' !== $encoding && '8bit' !== $encoding) { + throw new InvalidArgumentException(sprintf('The encoding must be one of "quoted-printable", "base64", or "8bit" ("%s" given).', $encoding)); + } + $this->encoding = $encoding; + } + } + + public function getMediaType(): string + { + return 'text'; + } + + public function getMediaSubtype(): string + { + return $this->subtype; + } + + /** + * @param string $disposition one of attachment, inline, or form-data + * + * @return $this + */ + public function setDisposition(string $disposition) + { + $this->disposition = $disposition; + + return $this; + } + + /** + * Sets the name of the file (used by FormDataPart). + * + * @return $this + */ + public function setName($name) + { + $this->name = $name; + + return $this; + } + + public function getBody(): string + { + if (!\is_resource($this->body)) { + return $this->body; + } + + if (stream_get_meta_data($this->body)['seekable'] ?? false) { + rewind($this->body); + } + + return stream_get_contents($this->body) ?: ''; + } + + public function bodyToString(): string + { + return $this->getEncoder()->encodeString($this->getBody(), $this->charset); + } + + public function bodyToIterable(): iterable + { + if (\is_resource($this->body)) { + if (stream_get_meta_data($this->body)['seekable'] ?? false) { + rewind($this->body); + } + yield from $this->getEncoder()->encodeByteStream($this->body); + } else { + yield $this->getEncoder()->encodeString($this->body); + } + } + + public function getPreparedHeaders(): Headers + { + $headers = parent::getPreparedHeaders(); + + $headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype()); + if ($this->charset) { + $headers->setHeaderParameter('Content-Type', 'charset', $this->charset); + } + if ($this->name) { + $headers->setHeaderParameter('Content-Type', 'name', $this->name); + } + $headers->setHeaderBody('Text', 'Content-Transfer-Encoding', $this->encoding); + + if (!$headers->has('Content-Disposition') && null !== $this->disposition) { + $headers->setHeaderBody('Parameterized', 'Content-Disposition', $this->disposition); + if ($this->name) { + $headers->setHeaderParameter('Content-Disposition', 'name', $this->name); + } + } + + return $headers; + } + + public function asDebugString(): string + { + $str = parent::asDebugString(); + if (null !== $this->charset) { + $str .= ' charset: '.$this->charset; + } + if (null !== $this->disposition) { + $str .= ' disposition: '.$this->disposition; + } + + return $str; + } + + private function getEncoder(): ContentEncoderInterface + { + if ('8bit' === $this->encoding) { + return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new EightBitContentEncoder()); + } + + if ('quoted-printable' === $this->encoding) { + return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new QpContentEncoder()); + } + + return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new Base64ContentEncoder()); + } + + private function chooseEncoding(): string + { + if (null === $this->charset) { + return 'base64'; + } + + return 'quoted-printable'; + } + + /** + * @return array + */ + public function __sleep() + { + // convert resources to strings for serialization + if (\is_resource($this->body)) { + $this->body = $this->getBody(); + } + + $this->_headers = $this->getHeaders(); + + return ['_headers', 'body', 'charset', 'subtype', 'disposition', 'name', 'encoding']; + } + + public function __wakeup() + { + $r = new \ReflectionProperty(AbstractPart::class, 'headers'); + $r->setAccessible(true); + $r->setValue($this, $this->_headers); + unset($this->_headers); + } +} diff --git a/vendor/symfony/mime/README.md b/vendor/symfony/mime/README.md new file mode 100644 index 0000000..4d565c9 --- /dev/null +++ b/vendor/symfony/mime/README.md @@ -0,0 +1,13 @@ +MIME Component +============== + +The MIME component allows manipulating MIME messages. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/mime.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/mime/RawMessage.php b/vendor/symfony/mime/RawMessage.php new file mode 100644 index 0000000..79a27e9 --- /dev/null +++ b/vendor/symfony/mime/RawMessage.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Symfony\Component\Mime\Exception\LogicException; + +/** + * @author Fabien Potencier + */ +class RawMessage implements \Serializable +{ + private $message; + + /** + * @param iterable|string $message + */ + public function __construct($message) + { + $this->message = $message; + } + + public function toString(): string + { + if (\is_string($this->message)) { + return $this->message; + } + + return $this->message = implode('', iterator_to_array($this->message, false)); + } + + public function toIterable(): iterable + { + if (\is_string($this->message)) { + yield $this->message; + + return; + } + + $message = ''; + foreach ($this->message as $chunk) { + $message .= $chunk; + yield $chunk; + } + $this->message = $message; + } + + /** + * @throws LogicException if the message is not valid + */ + public function ensureValidity() + { + } + + /** + * @internal + */ + final public function serialize(): string + { + return serialize($this->__serialize()); + } + + /** + * @internal + */ + final public function unserialize($serialized) + { + $this->__unserialize(unserialize($serialized)); + } + + public function __serialize(): array + { + return [$this->message]; + } + + public function __unserialize(array $data): void + { + [$this->message] = $data; + } +} diff --git a/vendor/symfony/mime/Resources/bin/update_mime_types.php b/vendor/symfony/mime/Resources/bin/update_mime_types.php new file mode 100644 index 0000000..74a9449 --- /dev/null +++ b/vendor/symfony/mime/Resources/bin/update_mime_types.php @@ -0,0 +1,166 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +// load new map +$data = file_get_contents('https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types'); +$new = []; +foreach (explode("\n", $data) as $line) { + if (!$line || '#' == $line[0]) { + continue; + } + $mimeType = substr($line, 0, strpos($line, "\t")); + $extensions = explode(' ', substr($line, strrpos($line, "\t") + 1)); + $new[$mimeType] = $extensions; +} + +$xml = simplexml_load_string(file_get_contents('https://raw.github.com/minad/mimemagic/master/script/freedesktop.org.xml')); +foreach ($xml as $node) { + $exts = []; + foreach ($node->glob as $glob) { + $pattern = (string) $glob['pattern']; + if ('*' != $pattern[0] || '.' != $pattern[1]) { + continue; + } + + $exts[] = substr($pattern, 2); + } + + if (!$exts) { + continue; + } + + $mt = strtolower((string) $node['type']); + $new[$mt] = array_merge($new[$mt] ?? [], $exts); + foreach ($node->alias as $alias) { + $mt = strtolower((string) $alias['type']); + $new[$mt] = array_merge($new[$mt] ?? [], $exts); + } +} + +// load current map +$data = file_get_contents($output = __DIR__.'/../../MimeTypes.php'); +$current = []; +$pre = ''; +$post = ''; +foreach (explode("\n", $data) as $line) { + if (!preg_match("{^ '([^']+/[^']+)' => \['(.+)'\],$}", $line, $matches)) { + if (!$current) { + $pre .= $line."\n"; + } else { + $post .= $line."\n"; + } + continue; + } + $current[$matches[1]] = explode("', '", $matches[2]); +} + +// we merge the 2 maps (we never remove old mime types) +$map = array_replace_recursive($current, $new); +ksort($map); + +$data = $pre; +foreach ($map as $mimeType => $exts) { + $data .= sprintf(" '%s' => ['%s'],\n", $mimeType, implode("', '", array_unique($exts))); +} +$data .= $post; + +// reverse map +// we prefill the extensions with some preferences for content-types +$exts = [ + 'aif' => ['audio/x-aiff'], + 'aiff' => ['audio/x-aiff'], + 'aps' => ['application/postscript'], + 'avi' => ['video/avi'], + 'bmp' => ['image/bmp'], + 'bz2' => ['application/x-bz2'], + 'css' => ['text/css'], + 'csv' => ['text/csv'], + 'dmg' => ['application/x-apple-diskimage'], + 'doc' => ['application/msword'], + 'docx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'], + 'eml' => ['message/rfc822'], + 'exe' => ['application/x-ms-dos-executable'], + 'flv' => ['video/x-flv'], + 'gif' => ['image/gif'], + 'gz' => ['application/x-gzip'], + 'hqx' => ['application/stuffit'], + 'htm' => ['text/html'], + 'html' => ['text/html'], + 'jar' => ['application/x-java-archive'], + 'jpeg' => ['image/jpeg'], + 'jpg' => ['image/jpeg'], + 'js' => ['text/javascript'], + 'm3u' => ['audio/x-mpegurl'], + 'm4a' => ['audio/mp4'], + 'mdb' => ['application/x-msaccess'], + 'mid' => ['audio/midi'], + 'midi' => ['audio/midi'], + 'mov' => ['video/quicktime'], + 'mp3' => ['audio/mpeg'], + 'mp4' => ['video/mp4'], + 'mpeg' => ['video/mpeg'], + 'mpg' => ['video/mpeg'], + 'ogg' => ['audio/ogg'], + 'pdf' => ['application/pdf'], + 'php' => ['application/x-php'], + 'php3' => ['application/x-php'], + 'php4' => ['application/x-php'], + 'php5' => ['application/x-php'], + 'png' => ['image/png'], + 'ppt' => ['application/vnd.ms-powerpoint'], + 'pptx' => ['application/vnd.openxmlformats-officedocument.presentationml.presentation'], + 'ps' => ['application/postscript'], + 'rar' => ['application/x-rar-compressed'], + 'rtf' => ['application/rtf'], + 'sit' => ['application/x-stuffit'], + 'svg' => ['image/svg+xml'], + 'tar' => ['application/x-tar'], + 'tif' => ['image/tiff'], + 'tiff' => ['image/tiff'], + 'ttf' => ['application/x-font-truetype'], + 'txt' => ['text/plain'], + 'vcf' => ['text/x-vcard'], + 'wav' => ['audio/wav'], + 'wma' => ['audio/x-ms-wma'], + 'wmv' => ['audio/x-ms-wmv'], + 'xls' => ['application/vnd.ms-excel'], + 'xlsx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], + 'xml' => ['application/xml'], + 'zip' => ['application/zip'], +]; +foreach ($map as $mimeType => $extensions) { + foreach ($extensions as $extension) { + $exts[$extension][] = $mimeType; + } +} +ksort($exts); + +$updated = ''; +$state = 0; +foreach (explode("\n", $data) as $line) { + if (!preg_match("{^ '([^'/]+)' => \['(.+)'\],$}", $line, $matches)) { + if (1 === $state) { + $state = 2; + foreach ($exts as $ext => $mimeTypes) { + $updated .= sprintf(" '%s' => ['%s'],\n", $ext, implode("', '", array_unique($mimeTypes))); + } + } + $updated .= $line."\n"; + continue; + } + $state = 1; +} + +$updated = preg_replace('{Updated from upstream on .+?\.}', 'Updated from upstream on '.date('Y-m-d'), $updated, -1); + +file_put_contents($output, rtrim($updated, "\n")."\n"); + +echo "Done.\n"; diff --git a/vendor/symfony/mime/Test/Constraint/EmailAddressContains.php b/vendor/symfony/mime/Test/Constraint/EmailAddressContains.php new file mode 100644 index 0000000..58ef360 --- /dev/null +++ b/vendor/symfony/mime/Test/Constraint/EmailAddressContains.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\Mime\Header\MailboxHeader; +use Symfony\Component\Mime\Header\MailboxListHeader; +use Symfony\Component\Mime\RawMessage; + +final class EmailAddressContains extends Constraint +{ + private $headerName; + private $expectedValue; + + public function __construct(string $headerName, string $expectedValue) + { + $this->headerName = $headerName; + $this->expectedValue = $expectedValue; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return sprintf('contains address "%s" with value "%s"', $this->headerName, $this->expectedValue); + } + + /** + * @param RawMessage $message + * + * {@inheritdoc} + */ + protected function matches($message): bool + { + if (RawMessage::class === \get_class($message)) { + throw new \LogicException('Unable to test a message address on a RawMessage instance.'); + } + + $header = $message->getHeaders()->get($this->headerName); + if ($header instanceof MailboxHeader) { + return $this->expectedValue === $header->Address()->getAddress(); + } elseif ($header instanceof MailboxListHeader) { + foreach ($header->getAddresses() as $address) { + if ($this->expectedValue === $address->getAddress()) { + return true; + } + } + + return false; + } + + throw new \LogicException(sprintf('Unable to test a message address on a non-address header.')); + } + + /** + * @param RawMessage $message + * + * {@inheritdoc} + */ + protected function failureDescription($message): string + { + return sprintf('the Email %s (value is %s)', $this->toString(), $message->getHeaders()->get($this->headerName)->getBodyAsString()); + } +} diff --git a/vendor/symfony/mime/Test/Constraint/EmailAttachmentCount.php b/vendor/symfony/mime/Test/Constraint/EmailAttachmentCount.php new file mode 100644 index 0000000..b219f28 --- /dev/null +++ b/vendor/symfony/mime/Test/Constraint/EmailAttachmentCount.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\Mime\RawMessage; + +final class EmailAttachmentCount extends Constraint +{ + private $expectedValue; + private $transport; + + public function __construct(int $expectedValue, string $transport = null) + { + $this->expectedValue = $expectedValue; + $this->transport = $transport; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return sprintf('has sent "%d" attachment(s)', $this->expectedValue); + } + + /** + * @param RawMessage $message + * + * {@inheritdoc} + */ + protected function matches($message): bool + { + if (RawMessage::class === \get_class($message) || Message::class === \get_class($message)) { + throw new \LogicException('Unable to test a message attachment on a RawMessage or Message instance.'); + } + + return $this->expectedValue === \count($message->getAttachments()); + } + + /** + * @param RawMessage $message + * + * {@inheritdoc} + */ + protected function failureDescription($message): string + { + return 'the Email '.$this->toString(); + } +} diff --git a/vendor/symfony/mime/Test/Constraint/EmailHasHeader.php b/vendor/symfony/mime/Test/Constraint/EmailHasHeader.php new file mode 100644 index 0000000..a29f835 --- /dev/null +++ b/vendor/symfony/mime/Test/Constraint/EmailHasHeader.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\Mime\RawMessage; + +final class EmailHasHeader extends Constraint +{ + private $headerName; + + public function __construct(string $headerName) + { + $this->headerName = $headerName; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return sprintf('has header "%s"', $this->headerName); + } + + /** + * @param RawMessage $message + * + * {@inheritdoc} + */ + protected function matches($message): bool + { + if (RawMessage::class === \get_class($message)) { + throw new \LogicException('Unable to test a message header on a RawMessage instance.'); + } + + return $message->getHeaders()->has($this->headerName); + } + + /** + * @param RawMessage $message + * + * {@inheritdoc} + */ + protected function failureDescription($message): string + { + return 'the Email '.$this->toString(); + } +} diff --git a/vendor/symfony/mime/Test/Constraint/EmailHeaderSame.php b/vendor/symfony/mime/Test/Constraint/EmailHeaderSame.php new file mode 100644 index 0000000..bc7e330 --- /dev/null +++ b/vendor/symfony/mime/Test/Constraint/EmailHeaderSame.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\Mime\RawMessage; + +final class EmailHeaderSame extends Constraint +{ + private $headerName; + private $expectedValue; + + public function __construct(string $headerName, string $expectedValue) + { + $this->headerName = $headerName; + $this->expectedValue = $expectedValue; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return sprintf('has header "%s" with value "%s"', $this->headerName, $this->expectedValue); + } + + /** + * @param RawMessage $message + * + * {@inheritdoc} + */ + protected function matches($message): bool + { + if (RawMessage::class === \get_class($message)) { + throw new \LogicException('Unable to test a message header on a RawMessage instance.'); + } + + return $this->expectedValue === $message->getHeaders()->get($this->headerName)->getBodyAsString(); + } + + /** + * @param RawMessage $message + * + * {@inheritdoc} + */ + protected function failureDescription($message): string + { + return sprintf('the Email %s (value is %s)', $this->toString(), $message->getHeaders()->get($this->headerName)->getBodyAsString()); + } +} diff --git a/vendor/symfony/mime/Test/Constraint/EmailHtmlBodyContains.php b/vendor/symfony/mime/Test/Constraint/EmailHtmlBodyContains.php new file mode 100644 index 0000000..8965195 --- /dev/null +++ b/vendor/symfony/mime/Test/Constraint/EmailHtmlBodyContains.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; + +final class EmailHtmlBodyContains extends Constraint +{ + private $expectedText; + + public function __construct(string $expectedText) + { + $this->expectedText = $expectedText; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return sprintf('contains "%s"', $this->expectedText); + } + + /** + * {@inheritdoc} + * + * @param RawMessage $message + */ + protected function matches($message): bool + { + if (RawMessage::class === \get_class($message) || Message::class === \get_class($message)) { + throw new \LogicException('Unable to test a message HTML body on a RawMessage or Message instance.'); + } + + return false !== mb_strpos($message->getHtmlBody(), $this->expectedText); + } + + /** + * {@inheritdoc} + * + * @param RawMessage $message + */ + protected function failureDescription($message): string + { + return 'the Email HTML body '.$this->toString(); + } +} diff --git a/vendor/symfony/mime/Test/Constraint/EmailTextBodyContains.php b/vendor/symfony/mime/Test/Constraint/EmailTextBodyContains.php new file mode 100644 index 0000000..b5e87f9 --- /dev/null +++ b/vendor/symfony/mime/Test/Constraint/EmailTextBodyContains.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; + +final class EmailTextBodyContains extends Constraint +{ + private $expectedText; + + public function __construct(string $expectedText) + { + $this->expectedText = $expectedText; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return sprintf('contains "%s"', $this->expectedText); + } + + /** + * {@inheritdoc} + * + * @param RawMessage $message + */ + protected function matches($message): bool + { + if (RawMessage::class === \get_class($message) || Message::class === \get_class($message)) { + throw new \LogicException('Unable to test a message text body on a RawMessage or Message instance.'); + } + + return false !== mb_strpos($message->getTextBody(), $this->expectedText); + } + + /** + * {@inheritdoc} + * + * @param RawMessage $message + */ + protected function failureDescription($message): string + { + return 'the Email text body '.$this->toString(); + } +} diff --git a/vendor/symfony/mime/composer.json b/vendor/symfony/mime/composer.json new file mode 100644 index 0000000..c3f2626 --- /dev/null +++ b/vendor/symfony/mime/composer.json @@ -0,0 +1,42 @@ +{ + "name": "symfony/mime", + "type": "library", + "description": "A library to manipulate MIME messages", + "keywords": ["mime", "mime-type"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10", + "symfony/dependency-injection": "^4.4|^5.0" + }, + "conflict": { + "symfony/mailer": "<4.4" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Mime\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/polyfill-ctype/Ctype.php b/vendor/symfony/polyfill-ctype/Ctype.php new file mode 100644 index 0000000..58414dc --- /dev/null +++ b/vendor/symfony/polyfill-ctype/Ctype.php @@ -0,0 +1,227 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Ctype; + +/** + * Ctype implementation through regex. + * + * @internal + * + * @author Gert de Pagter + */ +final class Ctype +{ + /** + * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise. + * + * @see https://php.net/ctype-alnum + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_alnum($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text); + } + + /** + * Returns TRUE if every character in text is a letter, FALSE otherwise. + * + * @see https://php.net/ctype-alpha + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_alpha($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text); + } + + /** + * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise. + * + * @see https://php.net/ctype-cntrl + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_cntrl($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text); + } + + /** + * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise. + * + * @see https://php.net/ctype-digit + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_digit($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text); + } + + /** + * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise. + * + * @see https://php.net/ctype-graph + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_graph($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text); + } + + /** + * Returns TRUE if every character in text is a lowercase letter. + * + * @see https://php.net/ctype-lower + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_lower($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text); + } + + /** + * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all. + * + * @see https://php.net/ctype-print + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_print($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text); + } + + /** + * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise. + * + * @see https://php.net/ctype-punct + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_punct($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text); + } + + /** + * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters. + * + * @see https://php.net/ctype-space + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_space($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text); + } + + /** + * Returns TRUE if every character in text is an uppercase letter. + * + * @see https://php.net/ctype-upper + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_upper($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text); + } + + /** + * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise. + * + * @see https://php.net/ctype-xdigit + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_xdigit($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text); + } + + /** + * Converts integers to their char versions according to normal ctype behaviour, if needed. + * + * If an integer between -128 and 255 inclusive is provided, + * it is interpreted as the ASCII value of a single character + * (negative values have 256 added in order to allow characters in the Extended ASCII range). + * Any other integer is interpreted as a string containing the decimal digits of the integer. + * + * @param string|int $int + * + * @return mixed + */ + private static function convert_int_to_char_for_ctype($int) + { + if (!\is_int($int)) { + return $int; + } + + if ($int < -128 || $int > 255) { + return (string) $int; + } + + if ($int < 0) { + $int += 256; + } + + return \chr($int); + } +} diff --git a/vendor/symfony/polyfill-ctype/LICENSE b/vendor/symfony/polyfill-ctype/LICENSE new file mode 100644 index 0000000..3f853aa --- /dev/null +++ b/vendor/symfony/polyfill-ctype/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/polyfill-ctype/README.md b/vendor/symfony/polyfill-ctype/README.md new file mode 100644 index 0000000..8add1ab --- /dev/null +++ b/vendor/symfony/polyfill-ctype/README.md @@ -0,0 +1,12 @@ +Symfony Polyfill / Ctype +======================== + +This component provides `ctype_*` functions to users who run php versions without the ctype extension. + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-ctype/bootstrap.php b/vendor/symfony/polyfill-ctype/bootstrap.php new file mode 100644 index 0000000..14d1d0f --- /dev/null +++ b/vendor/symfony/polyfill-ctype/bootstrap.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Ctype as p; + +if (!function_exists('ctype_alnum')) { + function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); } + function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); } + function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); } + function ctype_digit($text) { return p\Ctype::ctype_digit($text); } + function ctype_graph($text) { return p\Ctype::ctype_graph($text); } + function ctype_lower($text) { return p\Ctype::ctype_lower($text); } + function ctype_print($text) { return p\Ctype::ctype_print($text); } + function ctype_punct($text) { return p\Ctype::ctype_punct($text); } + function ctype_space($text) { return p\Ctype::ctype_space($text); } + function ctype_upper($text) { return p\Ctype::ctype_upper($text); } + function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); } +} diff --git a/vendor/symfony/polyfill-ctype/composer.json b/vendor/symfony/polyfill-ctype/composer.json new file mode 100644 index 0000000..2a2ea04 --- /dev/null +++ b/vendor/symfony/polyfill-ctype/composer.json @@ -0,0 +1,34 @@ +{ + "name": "symfony/polyfill-ctype", + "type": "library", + "description": "Symfony polyfill for ctype functions", + "keywords": ["polyfill", "compatibility", "portable", "ctype"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" }, + "files": [ "bootstrap.php" ] + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + } +} diff --git a/vendor/symfony/polyfill-intl-idn/Idn.php b/vendor/symfony/polyfill-intl-idn/Idn.php new file mode 100644 index 0000000..adb718d --- /dev/null +++ b/vendor/symfony/polyfill-intl-idn/Idn.php @@ -0,0 +1,283 @@ + + * @author Sebastian Kroczek + * @author Dmitry Lukashin + * @author Laurent Bassin + * + * @internal + */ +final class Idn +{ + const INTL_IDNA_VARIANT_2003 = 0; + const INTL_IDNA_VARIANT_UTS46 = 1; + + private static $encodeTable = array( + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + ); + + private static $decodeTable = array( + 'a' => 0, 'b' => 1, 'c' => 2, 'd' => 3, 'e' => 4, 'f' => 5, + 'g' => 6, 'h' => 7, 'i' => 8, 'j' => 9, 'k' => 10, 'l' => 11, + 'm' => 12, 'n' => 13, 'o' => 14, 'p' => 15, 'q' => 16, 'r' => 17, + 's' => 18, 't' => 19, 'u' => 20, 'v' => 21, 'w' => 22, 'x' => 23, + 'y' => 24, 'z' => 25, '0' => 26, '1' => 27, '2' => 28, '3' => 29, + '4' => 30, '5' => 31, '6' => 32, '7' => 33, '8' => 34, '9' => 35, + ); + + public static function idn_to_ascii($domain, $options, $variant, &$idna_info = array()) + { + if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) { + @trigger_error('idn_to_ascii(): INTL_IDNA_VARIANT_2003 is deprecated', E_USER_DEPRECATED); + } + + if (self::INTL_IDNA_VARIANT_UTS46 === $variant) { + $domain = mb_strtolower($domain, 'utf-8'); + } + + $parts = explode('.', $domain); + + foreach ($parts as $i => &$part) { + if ('' === $part && \count($parts) > 1 + $i) { + return false; + } + if (false === $part = self::encodePart($part)) { + return false; + } + } + + $output = implode('.', $parts); + + $idna_info = array( + 'result' => \strlen($output) > 255 ? false : $output, + 'isTransitionalDifferent' => false, + 'errors' => 0, + ); + + return $idna_info['result']; + } + + public static function idn_to_utf8($domain, $options, $variant, &$idna_info = array()) + { + if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) { + @trigger_error('idn_to_utf8(): INTL_IDNA_VARIANT_2003 is deprecated', E_USER_DEPRECATED); + } + + $parts = explode('.', $domain); + + foreach ($parts as &$part) { + $length = \strlen($part); + if ($length < 1 || 63 < $length) { + continue; + } + if (0 !== strpos($part, 'xn--')) { + continue; + } + + $part = substr($part, 4); + $part = self::decodePart($part); + } + + $output = implode('.', $parts); + + $idna_info = array( + 'result' => \strlen($output) > 255 ? false : $output, + 'isTransitionalDifferent' => false, + 'errors' => 0, + ); + + return $idna_info['result']; + } + + private static function encodePart($input) + { + $codePoints = self::listCodePoints($input); + + $n = 128; + $bias = 72; + $delta = 0; + $h = $b = \count($codePoints['basic']); + + $output = ''; + foreach ($codePoints['basic'] as $code) { + $output .= mb_chr($code, 'utf-8'); + } + if ($input === $output) { + return $output; + } + if ($b > 0) { + $output .= '-'; + } + + $codePoints['nonBasic'] = array_unique($codePoints['nonBasic']); + sort($codePoints['nonBasic']); + + $i = 0; + $length = mb_strlen($input, 'utf-8'); + while ($h < $length) { + $m = $codePoints['nonBasic'][$i++]; + $delta += ($m - $n) * ($h + 1); + $n = $m; + + foreach ($codePoints['all'] as $c) { + if ($c < $n || $c < 128) { + ++$delta; + } + if ($c === $n) { + $q = $delta; + for ($k = 36;; $k += 36) { + $t = self::calculateThreshold($k, $bias); + if ($q < $t) { + break; + } + + $code = $t + (($q - $t) % (36 - $t)); + $output .= self::$encodeTable[$code]; + + $q = ($q - $t) / (36 - $t); + } + + $output .= self::$encodeTable[$q]; + $bias = self::adapt($delta, $h + 1, ($h === $b)); + $delta = 0; + ++$h; + } + } + + ++$delta; + ++$n; + } + + $output = 'xn--'.$output; + + return \strlen($output) < 1 || 63 < \strlen($output) ? false : strtolower($output); + } + + private static function listCodePoints($input) + { + $codePoints = array( + 'all' => array(), + 'basic' => array(), + 'nonBasic' => array(), + ); + + $length = mb_strlen($input, 'utf-8'); + for ($i = 0; $i < $length; ++$i) { + $char = mb_substr($input, $i, 1, 'utf-8'); + $code = mb_ord($char, 'utf-8'); + if ($code < 128) { + $codePoints['all'][] = $codePoints['basic'][] = $code; + } else { + $codePoints['all'][] = $codePoints['nonBasic'][] = $code; + } + } + + return $codePoints; + } + + private static function calculateThreshold($k, $bias) + { + if ($k <= $bias + 1) { + return 1; + } + if ($k >= $bias + 26) { + return 26; + } + + return $k - $bias; + } + + private static function adapt($delta, $numPoints, $firstTime) + { + $delta = (int) ($firstTime ? $delta / 700 : $delta / 2); + $delta += (int) ($delta / $numPoints); + + $k = 0; + while ($delta > 35 * 13) { + $delta = (int) ($delta / 35); + $k = $k + 36; + } + + return $k + (int) (36 * $delta / ($delta + 38)); + } + + private static function decodePart($input) + { + $n = 128; + $i = 0; + $bias = 72; + $output = ''; + + $pos = strrpos($input, '-'); + if (false !== $pos) { + $output = substr($input, 0, $pos++); + } else { + $pos = 0; + } + + $outputLength = \strlen($output); + $inputLength = \strlen($input); + + while ($pos < $inputLength) { + $oldi = $i; + $w = 1; + + for ($k = 36;; $k += 36) { + $digit = self::$decodeTable[$input[$pos++]]; + $i += $digit * $w; + $t = self::calculateThreshold($k, $bias); + + if ($digit < $t) { + break; + } + + $w *= 36 - $t; + } + + $bias = self::adapt($i - $oldi, ++$outputLength, 0 === $oldi); + $n = $n + (int) ($i / $outputLength); + $i = $i % $outputLength; + $output = mb_substr($output, 0, $i, 'utf-8').mb_chr($n, 'utf-8').mb_substr($output, $i, $outputLength - 1, 'utf-8'); + + ++$i; + } + + return $output; + } +} diff --git a/vendor/symfony/polyfill-intl-idn/LICENSE b/vendor/symfony/polyfill-intl-idn/LICENSE new file mode 100644 index 0000000..3f853aa --- /dev/null +++ b/vendor/symfony/polyfill-intl-idn/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/polyfill-intl-idn/README.md b/vendor/symfony/polyfill-intl-idn/README.md new file mode 100644 index 0000000..5fd8c6e --- /dev/null +++ b/vendor/symfony/polyfill-intl-idn/README.md @@ -0,0 +1,12 @@ +Symfony Polyfill / Intl: Idn +============================ + +This component provides `idn_to_ascii` and `idn_to_utf8` functions to users who run php versions without the intl extension. + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-intl-idn/bootstrap.php b/vendor/symfony/polyfill-intl-idn/bootstrap.php new file mode 100644 index 0000000..c6e3921 --- /dev/null +++ b/vendor/symfony/polyfill-intl-idn/bootstrap.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Intl\Idn as p; + +if (!function_exists('idn_to_ascii')) { + define('U_IDNA_PROHIBITED_ERROR', 66560); + define('U_IDNA_ERROR_START', 66560); + define('U_IDNA_UNASSIGNED_ERROR', 66561); + define('U_IDNA_CHECK_BIDI_ERROR', 66562); + define('U_IDNA_STD3_ASCII_RULES_ERROR', 66563); + define('U_IDNA_ACE_PREFIX_ERROR', 66564); + define('U_IDNA_VERIFICATION_ERROR', 66565); + define('U_IDNA_LABEL_TOO_LONG_ERROR', 66566); + define('U_IDNA_ZERO_LENGTH_LABEL_ERROR', 66567); + define('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR', 66568); + define('U_IDNA_ERROR_LIMIT', 66569); + define('U_STRINGPREP_PROHIBITED_ERROR', 66560); + define('U_STRINGPREP_UNASSIGNED_ERROR', 66561); + define('U_STRINGPREP_CHECK_BIDI_ERROR', 66562); + define('IDNA_DEFAULT', 0); + define('IDNA_ALLOW_UNASSIGNED', 1); + define('IDNA_USE_STD3_RULES', 2); + define('IDNA_CHECK_BIDI', 4); + define('IDNA_CHECK_CONTEXTJ', 8); + define('IDNA_NONTRANSITIONAL_TO_ASCII', 16); + define('IDNA_NONTRANSITIONAL_TO_UNICODE', 32); + define('INTL_IDNA_VARIANT_2003', 0); + define('INTL_IDNA_VARIANT_UTS46', 1); + define('IDNA_ERROR_EMPTY_LABEL', 1); + define('IDNA_ERROR_LABEL_TOO_LONG', 2); + define('IDNA_ERROR_DOMAIN_NAME_TOO_LONG', 4); + define('IDNA_ERROR_LEADING_HYPHEN', 8); + define('IDNA_ERROR_TRAILING_HYPHEN', 16); + define('IDNA_ERROR_HYPHEN_3_4', 32); + define('IDNA_ERROR_LEADING_COMBINING_MARK', 64); + define('IDNA_ERROR_DISALLOWED', 128); + define('IDNA_ERROR_PUNYCODE', 256); + define('IDNA_ERROR_LABEL_HAS_DOT', 512); + define('IDNA_ERROR_INVALID_ACE_LABEL', 1024); + define('IDNA_ERROR_BIDI', 2048); + define('IDNA_ERROR_CONTEXTJ', 4096); + + if (PHP_VERSION_ID < 70400) { + function idn_to_ascii($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_2003, &$idna_info = array()) { return p\Idn::idn_to_ascii($domain, $options, $variant, $idna_info); } + function idn_to_utf8($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_2003, &$idna_info = array()) { return p\Idn::idn_to_utf8($domain, $options, $variant, $idna_info); } + } else { + function idn_to_ascii($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = array()) { return p\Idn::idn_to_ascii($domain, $options, $variant, $idna_info); } + function idn_to_utf8($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = array()) { return p\Idn::idn_to_utf8($domain, $options, $variant, $idna_info); } + } +} diff --git a/vendor/symfony/polyfill-intl-idn/composer.json b/vendor/symfony/polyfill-intl-idn/composer.json new file mode 100644 index 0000000..428c13e --- /dev/null +++ b/vendor/symfony/polyfill-intl-idn/composer.json @@ -0,0 +1,36 @@ +{ + "name": "symfony/polyfill-intl-idn", + "type": "library", + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "idn"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.9" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Intl\\Idn\\": "" }, + "files": [ "bootstrap.php" ] + }, + "suggest": { + "ext-intl": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + } +} diff --git a/vendor/symfony/polyfill-mbstring/LICENSE b/vendor/symfony/polyfill-mbstring/LICENSE new file mode 100644 index 0000000..4cd8bdd --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/polyfill-mbstring/Mbstring.php b/vendor/symfony/polyfill-mbstring/Mbstring.php new file mode 100644 index 0000000..bf882ba --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/Mbstring.php @@ -0,0 +1,840 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Mbstring; + +/** + * Partial mbstring implementation in PHP, iconv based, UTF-8 centric. + * + * Implemented: + * - mb_chr - Returns a specific character from its Unicode code point + * - mb_convert_encoding - Convert character encoding + * - mb_convert_variables - Convert character code in variable(s) + * - mb_decode_mimeheader - Decode string in MIME header field + * - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED + * - mb_decode_numericentity - Decode HTML numeric string reference to character + * - mb_encode_numericentity - Encode character to HTML numeric string reference + * - mb_convert_case - Perform case folding on a string + * - mb_detect_encoding - Detect character encoding + * - mb_get_info - Get internal settings of mbstring + * - mb_http_input - Detect HTTP input character encoding + * - mb_http_output - Set/Get HTTP output character encoding + * - mb_internal_encoding - Set/Get internal character encoding + * - mb_list_encodings - Returns an array of all supported encodings + * - mb_ord - Returns the Unicode code point of a character + * - mb_output_handler - Callback function converts character encoding in output buffer + * - mb_scrub - Replaces ill-formed byte sequences with substitute characters + * - mb_strlen - Get string length + * - mb_strpos - Find position of first occurrence of string in a string + * - mb_strrpos - Find position of last occurrence of a string in a string + * - mb_str_split - Convert a string to an array + * - mb_strtolower - Make a string lowercase + * - mb_strtoupper - Make a string uppercase + * - mb_substitute_character - Set/Get substitution character + * - mb_substr - Get part of string + * - mb_stripos - Finds position of first occurrence of a string within another, case insensitive + * - mb_stristr - Finds first occurrence of a string within another, case insensitive + * - mb_strrchr - Finds the last occurrence of a character in a string within another + * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive + * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive + * - mb_strstr - Finds first occurrence of a string within another + * - mb_strwidth - Return width of string + * - mb_substr_count - Count the number of substring occurrences + * + * Not implemented: + * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more) + * - mb_ereg_* - Regular expression with multibyte support + * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable + * - mb_preferred_mime_name - Get MIME charset string + * - mb_regex_encoding - Returns current encoding for multibyte regex as string + * - mb_regex_set_options - Set/Get the default options for mbregex functions + * - mb_send_mail - Send encoded mail + * - mb_split - Split multibyte string using regular expression + * - mb_strcut - Get part of string + * - mb_strimwidth - Get truncated string with specified width + * + * @author Nicolas Grekas + * + * @internal + */ +final class Mbstring +{ + const MB_CASE_FOLD = PHP_INT_MAX; + + private static $encodingList = array('ASCII', 'UTF-8'); + private static $language = 'neutral'; + private static $internalEncoding = 'UTF-8'; + private static $caseFold = array( + array('µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"), + array('μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'), + ); + + public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) + { + if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) { + $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); + } else { + $fromEncoding = self::getEncoding($fromEncoding); + } + + $toEncoding = self::getEncoding($toEncoding); + + if ('BASE64' === $fromEncoding) { + $s = base64_decode($s); + $fromEncoding = $toEncoding; + } + + if ('BASE64' === $toEncoding) { + return base64_encode($s); + } + + if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) { + if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) { + $fromEncoding = 'Windows-1252'; + } + if ('UTF-8' !== $fromEncoding) { + $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s); + } + + return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s); + } + + if ('HTML-ENTITIES' === $fromEncoding) { + $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8'); + $fromEncoding = 'UTF-8'; + } + + return iconv($fromEncoding, $toEncoding.'//IGNORE', $s); + } + + public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) + { + $vars = array(&$a, &$b, &$c, &$d, &$e, &$f); + + $ok = true; + array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) { + if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) { + $ok = false; + } + }); + + return $ok ? $fromEncoding : false; + } + + public static function mb_decode_mimeheader($s) + { + return iconv_mime_decode($s, 2, self::$internalEncoding); + } + + public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null) + { + trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING); + } + + public static function mb_decode_numericentity($s, $convmap, $encoding = null) + { + if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) { + trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING); + + return null; + } + + if (!\is_array($convmap) || !$convmap) { + return false; + } + + if (null !== $encoding && !\is_scalar($encoding)) { + trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING); + + return ''; // Instead of null (cf. mb_encode_numericentity). + } + + $s = (string) $s; + if ('' === $s) { + return ''; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding) { + $encoding = null; + if (!preg_match('//u', $s)) { + $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + } + } else { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + $cnt = floor(\count($convmap) / 4) * 4; + + for ($i = 0; $i < $cnt; $i += 4) { + // collector_decode_htmlnumericentity ignores $convmap[$i + 3] + $convmap[$i] += $convmap[$i + 2]; + $convmap[$i + 1] += $convmap[$i + 2]; + } + + $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) { + $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1]; + for ($i = 0; $i < $cnt; $i += 4) { + if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) { + return Mbstring::mb_chr($c - $convmap[$i + 2]); + } + } + + return $m[0]; + }, $s); + + if (null === $encoding) { + return $s; + } + + return iconv('UTF-8', $encoding.'//IGNORE', $s); + } + + public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false) + { + if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) { + trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING); + + return null; + } + + if (!\is_array($convmap) || !$convmap) { + return false; + } + + if (null !== $encoding && !\is_scalar($encoding)) { + trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING); + + return null; // Instead of '' (cf. mb_decode_numericentity). + } + + if (null !== $is_hex && !\is_scalar($is_hex)) { + trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', E_USER_WARNING); + + return null; + } + + $s = (string) $s; + if ('' === $s) { + return ''; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding) { + $encoding = null; + if (!preg_match('//u', $s)) { + $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + } + } else { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4); + + $cnt = floor(\count($convmap) / 4) * 4; + $i = 0; + $len = \strlen($s); + $result = ''; + + while ($i < $len) { + $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; + $uchr = substr($s, $i, $ulen); + $i += $ulen; + $c = self::mb_ord($uchr); + + for ($j = 0; $j < $cnt; $j += 4) { + if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) { + $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3]; + $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';'; + continue 2; + } + } + $result .= $uchr; + } + + if (null === $encoding) { + return $result; + } + + return iconv('UTF-8', $encoding.'//IGNORE', $result); + } + + public static function mb_convert_case($s, $mode, $encoding = null) + { + $s = (string) $s; + if ('' === $s) { + return ''; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding) { + $encoding = null; + if (!preg_match('//u', $s)) { + $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); + } + } else { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + if (MB_CASE_TITLE == $mode) { + static $titleRegexp = null; + if (null === $titleRegexp) { + $titleRegexp = self::getData('titleCaseRegexp'); + } + $s = preg_replace_callback($titleRegexp, array(__CLASS__, 'title_case'), $s); + } else { + if (MB_CASE_UPPER == $mode) { + static $upper = null; + if (null === $upper) { + $upper = self::getData('upperCase'); + } + $map = $upper; + } else { + if (self::MB_CASE_FOLD === $mode) { + $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s); + } + + static $lower = null; + if (null === $lower) { + $lower = self::getData('lowerCase'); + } + $map = $lower; + } + + static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4); + + $i = 0; + $len = \strlen($s); + + while ($i < $len) { + $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; + $uchr = substr($s, $i, $ulen); + $i += $ulen; + + if (isset($map[$uchr])) { + $uchr = $map[$uchr]; + $nlen = \strlen($uchr); + + if ($nlen == $ulen) { + $nlen = $i; + do { + $s[--$nlen] = $uchr[--$ulen]; + } while ($ulen); + } else { + $s = substr_replace($s, $uchr, $i - $ulen, $ulen); + $len += $nlen - $ulen; + $i += $nlen - $ulen; + } + } + } + } + + if (null === $encoding) { + return $s; + } + + return iconv('UTF-8', $encoding.'//IGNORE', $s); + } + + public static function mb_internal_encoding($encoding = null) + { + if (null === $encoding) { + return self::$internalEncoding; + } + + $encoding = self::getEncoding($encoding); + + if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) { + self::$internalEncoding = $encoding; + + return true; + } + + return false; + } + + public static function mb_language($lang = null) + { + if (null === $lang) { + return self::$language; + } + + switch ($lang = strtolower($lang)) { + case 'uni': + case 'neutral': + self::$language = $lang; + + return true; + } + + return false; + } + + public static function mb_list_encodings() + { + return array('UTF-8'); + } + + public static function mb_encoding_aliases($encoding) + { + switch (strtoupper($encoding)) { + case 'UTF8': + case 'UTF-8': + return array('utf8'); + } + + return false; + } + + public static function mb_check_encoding($var = null, $encoding = null) + { + if (null === $encoding) { + if (null === $var) { + return false; + } + $encoding = self::$internalEncoding; + } + + return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var); + } + + public static function mb_detect_encoding($str, $encodingList = null, $strict = false) + { + if (null === $encodingList) { + $encodingList = self::$encodingList; + } else { + if (!\is_array($encodingList)) { + $encodingList = array_map('trim', explode(',', $encodingList)); + } + $encodingList = array_map('strtoupper', $encodingList); + } + + foreach ($encodingList as $enc) { + switch ($enc) { + case 'ASCII': + if (!preg_match('/[\x80-\xFF]/', $str)) { + return $enc; + } + break; + + case 'UTF8': + case 'UTF-8': + if (preg_match('//u', $str)) { + return 'UTF-8'; + } + break; + + default: + if (0 === strncmp($enc, 'ISO-8859-', 9)) { + return $enc; + } + } + } + + return false; + } + + public static function mb_detect_order($encodingList = null) + { + if (null === $encodingList) { + return self::$encodingList; + } + + if (!\is_array($encodingList)) { + $encodingList = array_map('trim', explode(',', $encodingList)); + } + $encodingList = array_map('strtoupper', $encodingList); + + foreach ($encodingList as $enc) { + switch ($enc) { + default: + if (strncmp($enc, 'ISO-8859-', 9)) { + return false; + } + // no break + case 'ASCII': + case 'UTF8': + case 'UTF-8': + } + } + + self::$encodingList = $encodingList; + + return true; + } + + public static function mb_strlen($s, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return \strlen($s); + } + + return @iconv_strlen($s, $encoding); + } + + public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return strpos($haystack, $needle, $offset); + } + + $needle = (string) $needle; + if ('' === $needle) { + trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING); + + return false; + } + + return iconv_strpos($haystack, $needle, $offset, $encoding); + } + + public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return strrpos($haystack, $needle, $offset); + } + + if ($offset != (int) $offset) { + $offset = 0; + } elseif ($offset = (int) $offset) { + if ($offset < 0) { + if (0 > $offset += self::mb_strlen($needle)) { + $haystack = self::mb_substr($haystack, 0, $offset, $encoding); + } + $offset = 0; + } else { + $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding); + } + } + + $pos = iconv_strrpos($haystack, $needle, $encoding); + + return false !== $pos ? $offset + $pos : false; + } + + public static function mb_str_split($string, $split_length = 1, $encoding = null) + { + if (null !== $string && !\is_scalar($string) && !(\is_object($string) && \method_exists($string, '__toString'))) { + trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', E_USER_WARNING); + + return null; + } + + if (1 > $split_length = (int) $split_length) { + trigger_error('The length of each segment must be greater than zero', E_USER_WARNING); + + return false; + } + + if (null === $encoding) { + $encoding = mb_internal_encoding(); + } + + if ('UTF-8' === $encoding = self::getEncoding($encoding)) { + return preg_split("/(.{{$split_length}})/u", $string, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + } + + $result = array(); + $length = mb_strlen($string, $encoding); + + for ($i = 0; $i < $length; $i += $split_length) { + $result[] = mb_substr($string, $i, $split_length, $encoding); + } + + return $result; + } + + public static function mb_strtolower($s, $encoding = null) + { + return self::mb_convert_case($s, MB_CASE_LOWER, $encoding); + } + + public static function mb_strtoupper($s, $encoding = null) + { + return self::mb_convert_case($s, MB_CASE_UPPER, $encoding); + } + + public static function mb_substitute_character($c = null) + { + if (0 === strcasecmp($c, 'none')) { + return true; + } + + return null !== $c ? false : 'none'; + } + + public static function mb_substr($s, $start, $length = null, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return (string) substr($s, $start, null === $length ? 2147483647 : $length); + } + + if ($start < 0) { + $start = iconv_strlen($s, $encoding) + $start; + if ($start < 0) { + $start = 0; + } + } + + if (null === $length) { + $length = 2147483647; + } elseif ($length < 0) { + $length = iconv_strlen($s, $encoding) + $length - $start; + if ($length < 0) { + return ''; + } + } + + return (string) iconv_substr($s, $start, $length, $encoding); + } + + public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) + { + $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); + $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); + + return self::mb_strpos($haystack, $needle, $offset, $encoding); + } + + public static function mb_stristr($haystack, $needle, $part = false, $encoding = null) + { + $pos = self::mb_stripos($haystack, $needle, 0, $encoding); + + return self::getSubpart($pos, $part, $haystack, $encoding); + } + + public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null) + { + $encoding = self::getEncoding($encoding); + if ('CP850' === $encoding || 'ASCII' === $encoding) { + return strrchr($haystack, $needle, $part); + } + $needle = self::mb_substr($needle, 0, 1, $encoding); + $pos = iconv_strrpos($haystack, $needle, $encoding); + + return self::getSubpart($pos, $part, $haystack, $encoding); + } + + public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null) + { + $needle = self::mb_substr($needle, 0, 1, $encoding); + $pos = self::mb_strripos($haystack, $needle, $encoding); + + return self::getSubpart($pos, $part, $haystack, $encoding); + } + + public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) + { + $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); + $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); + + return self::mb_strrpos($haystack, $needle, $offset, $encoding); + } + + public static function mb_strstr($haystack, $needle, $part = false, $encoding = null) + { + $pos = strpos($haystack, $needle); + if (false === $pos) { + return false; + } + if ($part) { + return substr($haystack, 0, $pos); + } + + return substr($haystack, $pos); + } + + public static function mb_get_info($type = 'all') + { + $info = array( + 'internal_encoding' => self::$internalEncoding, + 'http_output' => 'pass', + 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)', + 'func_overload' => 0, + 'func_overload_list' => 'no overload', + 'mail_charset' => 'UTF-8', + 'mail_header_encoding' => 'BASE64', + 'mail_body_encoding' => 'BASE64', + 'illegal_chars' => 0, + 'encoding_translation' => 'Off', + 'language' => self::$language, + 'detect_order' => self::$encodingList, + 'substitute_character' => 'none', + 'strict_detection' => 'Off', + ); + + if ('all' === $type) { + return $info; + } + if (isset($info[$type])) { + return $info[$type]; + } + + return false; + } + + public static function mb_http_input($type = '') + { + return false; + } + + public static function mb_http_output($encoding = null) + { + return null !== $encoding ? 'pass' === $encoding : 'pass'; + } + + public static function mb_strwidth($s, $encoding = null) + { + $encoding = self::getEncoding($encoding); + + if ('UTF-8' !== $encoding) { + $s = iconv($encoding, 'UTF-8//IGNORE', $s); + } + + $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide); + + return ($wide << 1) + iconv_strlen($s, 'UTF-8'); + } + + public static function mb_substr_count($haystack, $needle, $encoding = null) + { + return substr_count($haystack, $needle); + } + + public static function mb_output_handler($contents, $status) + { + return $contents; + } + + public static function mb_chr($code, $encoding = null) + { + if (0x80 > $code %= 0x200000) { + $s = \chr($code); + } elseif (0x800 > $code) { + $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); + } elseif (0x10000 > $code) { + $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } else { + $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } + + if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { + $s = mb_convert_encoding($s, $encoding, 'UTF-8'); + } + + return $s; + } + + public static function mb_ord($s, $encoding = null) + { + if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { + $s = mb_convert_encoding($s, 'UTF-8', $encoding); + } + + if (1 === \strlen($s)) { + return \ord($s); + } + + $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; + if (0xF0 <= $code) { + return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; + } + if (0xE0 <= $code) { + return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; + } + if (0xC0 <= $code) { + return (($code - 0xC0) << 6) + $s[2] - 0x80; + } + + return $code; + } + + private static function getSubpart($pos, $part, $haystack, $encoding) + { + if (false === $pos) { + return false; + } + if ($part) { + return self::mb_substr($haystack, 0, $pos, $encoding); + } + + return self::mb_substr($haystack, $pos, null, $encoding); + } + + private static function html_encoding_callback(array $m) + { + $i = 1; + $entities = ''; + $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8')); + + while (isset($m[$i])) { + if (0x80 > $m[$i]) { + $entities .= \chr($m[$i++]); + continue; + } + if (0xF0 <= $m[$i]) { + $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; + } elseif (0xE0 <= $m[$i]) { + $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; + } else { + $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80; + } + + $entities .= '&#'.$c.';'; + } + + return $entities; + } + + private static function title_case(array $s) + { + return self::mb_convert_case($s[1], MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], MB_CASE_LOWER, 'UTF-8'); + } + + private static function getData($file) + { + if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) { + return require $file; + } + + return false; + } + + private static function getEncoding($encoding) + { + if (null === $encoding) { + return self::$internalEncoding; + } + + if ('UTF-8' === $encoding) { + return 'UTF-8'; + } + + $encoding = strtoupper($encoding); + + if ('8BIT' === $encoding || 'BINARY' === $encoding) { + return 'CP850'; + } + + if ('UTF8' === $encoding) { + return 'UTF-8'; + } + + return $encoding; + } +} diff --git a/vendor/symfony/polyfill-mbstring/README.md b/vendor/symfony/polyfill-mbstring/README.md new file mode 100644 index 0000000..342e828 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/README.md @@ -0,0 +1,13 @@ +Symfony Polyfill / Mbstring +=========================== + +This component provides a partial, native PHP implementation for the +[Mbstring](http://php.net/mbstring) extension. + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php new file mode 100644 index 0000000..e6fbfa6 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php @@ -0,0 +1,1096 @@ + 'a', + 'B' => 'b', + 'C' => 'c', + 'D' => 'd', + 'E' => 'e', + 'F' => 'f', + 'G' => 'g', + 'H' => 'h', + 'I' => 'i', + 'J' => 'j', + 'K' => 'k', + 'L' => 'l', + 'M' => 'm', + 'N' => 'n', + 'O' => 'o', + 'P' => 'p', + 'Q' => 'q', + 'R' => 'r', + 'S' => 's', + 'T' => 't', + 'U' => 'u', + 'V' => 'v', + 'W' => 'w', + 'X' => 'x', + 'Y' => 'y', + 'Z' => 'z', + 'À' => 'à', + 'Á' => 'á', + 'Â' => 'â', + 'Ã' => 'ã', + 'Ä' => 'ä', + 'Å' => 'å', + 'Æ' => 'æ', + 'Ç' => 'ç', + 'È' => 'è', + 'É' => 'é', + 'Ê' => 'ê', + 'Ë' => 'ë', + 'Ì' => 'ì', + 'Í' => 'í', + 'Î' => 'î', + 'Ï' => 'ï', + 'Ð' => 'ð', + 'Ñ' => 'ñ', + 'Ò' => 'ò', + 'Ó' => 'ó', + 'Ô' => 'ô', + 'Õ' => 'õ', + 'Ö' => 'ö', + 'Ø' => 'ø', + 'Ù' => 'ù', + 'Ú' => 'ú', + 'Û' => 'û', + 'Ü' => 'ü', + 'Ý' => 'ý', + 'Þ' => 'þ', + 'Ā' => 'ā', + 'Ă' => 'ă', + 'Ą' => 'ą', + 'Ć' => 'ć', + 'Ĉ' => 'ĉ', + 'Ċ' => 'ċ', + 'Č' => 'č', + 'Ď' => 'ď', + 'Đ' => 'đ', + 'Ē' => 'ē', + 'Ĕ' => 'ĕ', + 'Ė' => 'ė', + 'Ę' => 'ę', + 'Ě' => 'ě', + 'Ĝ' => 'ĝ', + 'Ğ' => 'ğ', + 'Ġ' => 'ġ', + 'Ģ' => 'ģ', + 'Ĥ' => 'ĥ', + 'Ħ' => 'ħ', + 'Ĩ' => 'ĩ', + 'Ī' => 'ī', + 'Ĭ' => 'ĭ', + 'Į' => 'į', + 'İ' => 'i', + 'IJ' => 'ij', + 'Ĵ' => 'ĵ', + 'Ķ' => 'ķ', + 'Ĺ' => 'ĺ', + 'Ļ' => 'ļ', + 'Ľ' => 'ľ', + 'Ŀ' => 'ŀ', + 'Ł' => 'ł', + 'Ń' => 'ń', + 'Ņ' => 'ņ', + 'Ň' => 'ň', + 'Ŋ' => 'ŋ', + 'Ō' => 'ō', + 'Ŏ' => 'ŏ', + 'Ő' => 'ő', + 'Œ' => 'œ', + 'Ŕ' => 'ŕ', + 'Ŗ' => 'ŗ', + 'Ř' => 'ř', + 'Ś' => 'ś', + 'Ŝ' => 'ŝ', + 'Ş' => 'ş', + 'Š' => 'š', + 'Ţ' => 'ţ', + 'Ť' => 'ť', + 'Ŧ' => 'ŧ', + 'Ũ' => 'ũ', + 'Ū' => 'ū', + 'Ŭ' => 'ŭ', + 'Ů' => 'ů', + 'Ű' => 'ű', + 'Ų' => 'ų', + 'Ŵ' => 'ŵ', + 'Ŷ' => 'ŷ', + 'Ÿ' => 'ÿ', + 'Ź' => 'ź', + 'Ż' => 'ż', + 'Ž' => 'ž', + 'Ɓ' => 'ɓ', + 'Ƃ' => 'ƃ', + 'Ƅ' => 'ƅ', + 'Ɔ' => 'ɔ', + 'Ƈ' => 'ƈ', + 'Ɖ' => 'ɖ', + 'Ɗ' => 'ɗ', + 'Ƌ' => 'ƌ', + 'Ǝ' => 'ǝ', + 'Ə' => 'ə', + 'Ɛ' => 'ɛ', + 'Ƒ' => 'ƒ', + 'Ɠ' => 'ɠ', + 'Ɣ' => 'ɣ', + 'Ɩ' => 'ɩ', + 'Ɨ' => 'ɨ', + 'Ƙ' => 'ƙ', + 'Ɯ' => 'ɯ', + 'Ɲ' => 'ɲ', + 'Ɵ' => 'ɵ', + 'Ơ' => 'ơ', + 'Ƣ' => 'ƣ', + 'Ƥ' => 'ƥ', + 'Ʀ' => 'ʀ', + 'Ƨ' => 'ƨ', + 'Ʃ' => 'ʃ', + 'Ƭ' => 'ƭ', + 'Ʈ' => 'ʈ', + 'Ư' => 'ư', + 'Ʊ' => 'ʊ', + 'Ʋ' => 'ʋ', + 'Ƴ' => 'ƴ', + 'Ƶ' => 'ƶ', + 'Ʒ' => 'ʒ', + 'Ƹ' => 'ƹ', + 'Ƽ' => 'ƽ', + 'DŽ' => 'dž', + 'Dž' => 'dž', + 'LJ' => 'lj', + 'Lj' => 'lj', + 'NJ' => 'nj', + 'Nj' => 'nj', + 'Ǎ' => 'ǎ', + 'Ǐ' => 'ǐ', + 'Ǒ' => 'ǒ', + 'Ǔ' => 'ǔ', + 'Ǖ' => 'ǖ', + 'Ǘ' => 'ǘ', + 'Ǚ' => 'ǚ', + 'Ǜ' => 'ǜ', + 'Ǟ' => 'ǟ', + 'Ǡ' => 'ǡ', + 'Ǣ' => 'ǣ', + 'Ǥ' => 'ǥ', + 'Ǧ' => 'ǧ', + 'Ǩ' => 'ǩ', + 'Ǫ' => 'ǫ', + 'Ǭ' => 'ǭ', + 'Ǯ' => 'ǯ', + 'DZ' => 'dz', + 'Dz' => 'dz', + 'Ǵ' => 'ǵ', + 'Ƕ' => 'ƕ', + 'Ƿ' => 'ƿ', + 'Ǹ' => 'ǹ', + 'Ǻ' => 'ǻ', + 'Ǽ' => 'ǽ', + 'Ǿ' => 'ǿ', + 'Ȁ' => 'ȁ', + 'Ȃ' => 'ȃ', + 'Ȅ' => 'ȅ', + 'Ȇ' => 'ȇ', + 'Ȉ' => 'ȉ', + 'Ȋ' => 'ȋ', + 'Ȍ' => 'ȍ', + 'Ȏ' => 'ȏ', + 'Ȑ' => 'ȑ', + 'Ȓ' => 'ȓ', + 'Ȕ' => 'ȕ', + 'Ȗ' => 'ȗ', + 'Ș' => 'ș', + 'Ț' => 'ț', + 'Ȝ' => 'ȝ', + 'Ȟ' => 'ȟ', + 'Ƞ' => 'ƞ', + 'Ȣ' => 'ȣ', + 'Ȥ' => 'ȥ', + 'Ȧ' => 'ȧ', + 'Ȩ' => 'ȩ', + 'Ȫ' => 'ȫ', + 'Ȭ' => 'ȭ', + 'Ȯ' => 'ȯ', + 'Ȱ' => 'ȱ', + 'Ȳ' => 'ȳ', + 'Ⱥ' => 'ⱥ', + 'Ȼ' => 'ȼ', + 'Ƚ' => 'ƚ', + 'Ⱦ' => 'ⱦ', + 'Ɂ' => 'ɂ', + 'Ƀ' => 'ƀ', + 'Ʉ' => 'ʉ', + 'Ʌ' => 'ʌ', + 'Ɇ' => 'ɇ', + 'Ɉ' => 'ɉ', + 'Ɋ' => 'ɋ', + 'Ɍ' => 'ɍ', + 'Ɏ' => 'ɏ', + 'Ͱ' => 'ͱ', + 'Ͳ' => 'ͳ', + 'Ͷ' => 'ͷ', + 'Ϳ' => 'ϳ', + 'Ά' => 'ά', + 'Έ' => 'έ', + 'Ή' => 'ή', + 'Ί' => 'ί', + 'Ό' => 'ό', + 'Ύ' => 'ύ', + 'Ώ' => 'ώ', + 'Α' => 'α', + 'Β' => 'β', + 'Γ' => 'γ', + 'Δ' => 'δ', + 'Ε' => 'ε', + 'Ζ' => 'ζ', + 'Η' => 'η', + 'Θ' => 'θ', + 'Ι' => 'ι', + 'Κ' => 'κ', + 'Λ' => 'λ', + 'Μ' => 'μ', + 'Ν' => 'ν', + 'Ξ' => 'ξ', + 'Ο' => 'ο', + 'Π' => 'π', + 'Ρ' => 'ρ', + 'Σ' => 'σ', + 'Τ' => 'τ', + 'Υ' => 'υ', + 'Φ' => 'φ', + 'Χ' => 'χ', + 'Ψ' => 'ψ', + 'Ω' => 'ω', + 'Ϊ' => 'ϊ', + 'Ϋ' => 'ϋ', + 'Ϗ' => 'ϗ', + 'Ϙ' => 'ϙ', + 'Ϛ' => 'ϛ', + 'Ϝ' => 'ϝ', + 'Ϟ' => 'ϟ', + 'Ϡ' => 'ϡ', + 'Ϣ' => 'ϣ', + 'Ϥ' => 'ϥ', + 'Ϧ' => 'ϧ', + 'Ϩ' => 'ϩ', + 'Ϫ' => 'ϫ', + 'Ϭ' => 'ϭ', + 'Ϯ' => 'ϯ', + 'ϴ' => 'θ', + 'Ϸ' => 'ϸ', + 'Ϲ' => 'ϲ', + 'Ϻ' => 'ϻ', + 'Ͻ' => 'ͻ', + 'Ͼ' => 'ͼ', + 'Ͽ' => 'ͽ', + 'Ѐ' => 'ѐ', + 'Ё' => 'ё', + 'Ђ' => 'ђ', + 'Ѓ' => 'ѓ', + 'Є' => 'є', + 'Ѕ' => 'ѕ', + 'І' => 'і', + 'Ї' => 'ї', + 'Ј' => 'ј', + 'Љ' => 'љ', + 'Њ' => 'њ', + 'Ћ' => 'ћ', + 'Ќ' => 'ќ', + 'Ѝ' => 'ѝ', + 'Ў' => 'ў', + 'Џ' => 'џ', + 'А' => 'а', + 'Б' => 'б', + 'В' => 'в', + 'Г' => 'г', + 'Д' => 'д', + 'Е' => 'е', + 'Ж' => 'ж', + 'З' => 'з', + 'И' => 'и', + 'Й' => 'й', + 'К' => 'к', + 'Л' => 'л', + 'М' => 'м', + 'Н' => 'н', + 'О' => 'о', + 'П' => 'п', + 'Р' => 'р', + 'С' => 'с', + 'Т' => 'т', + 'У' => 'у', + 'Ф' => 'ф', + 'Х' => 'х', + 'Ц' => 'ц', + 'Ч' => 'ч', + 'Ш' => 'ш', + 'Щ' => 'щ', + 'Ъ' => 'ъ', + 'Ы' => 'ы', + 'Ь' => 'ь', + 'Э' => 'э', + 'Ю' => 'ю', + 'Я' => 'я', + 'Ѡ' => 'ѡ', + 'Ѣ' => 'ѣ', + 'Ѥ' => 'ѥ', + 'Ѧ' => 'ѧ', + 'Ѩ' => 'ѩ', + 'Ѫ' => 'ѫ', + 'Ѭ' => 'ѭ', + 'Ѯ' => 'ѯ', + 'Ѱ' => 'ѱ', + 'Ѳ' => 'ѳ', + 'Ѵ' => 'ѵ', + 'Ѷ' => 'ѷ', + 'Ѹ' => 'ѹ', + 'Ѻ' => 'ѻ', + 'Ѽ' => 'ѽ', + 'Ѿ' => 'ѿ', + 'Ҁ' => 'ҁ', + 'Ҋ' => 'ҋ', + 'Ҍ' => 'ҍ', + 'Ҏ' => 'ҏ', + 'Ґ' => 'ґ', + 'Ғ' => 'ғ', + 'Ҕ' => 'ҕ', + 'Җ' => 'җ', + 'Ҙ' => 'ҙ', + 'Қ' => 'қ', + 'Ҝ' => 'ҝ', + 'Ҟ' => 'ҟ', + 'Ҡ' => 'ҡ', + 'Ң' => 'ң', + 'Ҥ' => 'ҥ', + 'Ҧ' => 'ҧ', + 'Ҩ' => 'ҩ', + 'Ҫ' => 'ҫ', + 'Ҭ' => 'ҭ', + 'Ү' => 'ү', + 'Ұ' => 'ұ', + 'Ҳ' => 'ҳ', + 'Ҵ' => 'ҵ', + 'Ҷ' => 'ҷ', + 'Ҹ' => 'ҹ', + 'Һ' => 'һ', + 'Ҽ' => 'ҽ', + 'Ҿ' => 'ҿ', + 'Ӏ' => 'ӏ', + 'Ӂ' => 'ӂ', + 'Ӄ' => 'ӄ', + 'Ӆ' => 'ӆ', + 'Ӈ' => 'ӈ', + 'Ӊ' => 'ӊ', + 'Ӌ' => 'ӌ', + 'Ӎ' => 'ӎ', + 'Ӑ' => 'ӑ', + 'Ӓ' => 'ӓ', + 'Ӕ' => 'ӕ', + 'Ӗ' => 'ӗ', + 'Ә' => 'ә', + 'Ӛ' => 'ӛ', + 'Ӝ' => 'ӝ', + 'Ӟ' => 'ӟ', + 'Ӡ' => 'ӡ', + 'Ӣ' => 'ӣ', + 'Ӥ' => 'ӥ', + 'Ӧ' => 'ӧ', + 'Ө' => 'ө', + 'Ӫ' => 'ӫ', + 'Ӭ' => 'ӭ', + 'Ӯ' => 'ӯ', + 'Ӱ' => 'ӱ', + 'Ӳ' => 'ӳ', + 'Ӵ' => 'ӵ', + 'Ӷ' => 'ӷ', + 'Ӹ' => 'ӹ', + 'Ӻ' => 'ӻ', + 'Ӽ' => 'ӽ', + 'Ӿ' => 'ӿ', + 'Ԁ' => 'ԁ', + 'Ԃ' => 'ԃ', + 'Ԅ' => 'ԅ', + 'Ԇ' => 'ԇ', + 'Ԉ' => 'ԉ', + 'Ԋ' => 'ԋ', + 'Ԍ' => 'ԍ', + 'Ԏ' => 'ԏ', + 'Ԑ' => 'ԑ', + 'Ԓ' => 'ԓ', + 'Ԕ' => 'ԕ', + 'Ԗ' => 'ԗ', + 'Ԙ' => 'ԙ', + 'Ԛ' => 'ԛ', + 'Ԝ' => 'ԝ', + 'Ԟ' => 'ԟ', + 'Ԡ' => 'ԡ', + 'Ԣ' => 'ԣ', + 'Ԥ' => 'ԥ', + 'Ԧ' => 'ԧ', + 'Ԩ' => 'ԩ', + 'Ԫ' => 'ԫ', + 'Ԭ' => 'ԭ', + 'Ԯ' => 'ԯ', + 'Ա' => 'ա', + 'Բ' => 'բ', + 'Գ' => 'գ', + 'Դ' => 'դ', + 'Ե' => 'ե', + 'Զ' => 'զ', + 'Է' => 'է', + 'Ը' => 'ը', + 'Թ' => 'թ', + 'Ժ' => 'ժ', + 'Ի' => 'ի', + 'Լ' => 'լ', + 'Խ' => 'խ', + 'Ծ' => 'ծ', + 'Կ' => 'կ', + 'Հ' => 'հ', + 'Ձ' => 'ձ', + 'Ղ' => 'ղ', + 'Ճ' => 'ճ', + 'Մ' => 'մ', + 'Յ' => 'յ', + 'Ն' => 'ն', + 'Շ' => 'շ', + 'Ո' => 'ո', + 'Չ' => 'չ', + 'Պ' => 'պ', + 'Ջ' => 'ջ', + 'Ռ' => 'ռ', + 'Ս' => 'ս', + 'Վ' => 'վ', + 'Տ' => 'տ', + 'Ր' => 'ր', + 'Ց' => 'ց', + 'Ւ' => 'ւ', + 'Փ' => 'փ', + 'Ք' => 'ք', + 'Օ' => 'օ', + 'Ֆ' => 'ֆ', + 'Ⴀ' => 'ⴀ', + 'Ⴁ' => 'ⴁ', + 'Ⴂ' => 'ⴂ', + 'Ⴃ' => 'ⴃ', + 'Ⴄ' => 'ⴄ', + 'Ⴅ' => 'ⴅ', + 'Ⴆ' => 'ⴆ', + 'Ⴇ' => 'ⴇ', + 'Ⴈ' => 'ⴈ', + 'Ⴉ' => 'ⴉ', + 'Ⴊ' => 'ⴊ', + 'Ⴋ' => 'ⴋ', + 'Ⴌ' => 'ⴌ', + 'Ⴍ' => 'ⴍ', + 'Ⴎ' => 'ⴎ', + 'Ⴏ' => 'ⴏ', + 'Ⴐ' => 'ⴐ', + 'Ⴑ' => 'ⴑ', + 'Ⴒ' => 'ⴒ', + 'Ⴓ' => 'ⴓ', + 'Ⴔ' => 'ⴔ', + 'Ⴕ' => 'ⴕ', + 'Ⴖ' => 'ⴖ', + 'Ⴗ' => 'ⴗ', + 'Ⴘ' => 'ⴘ', + 'Ⴙ' => 'ⴙ', + 'Ⴚ' => 'ⴚ', + 'Ⴛ' => 'ⴛ', + 'Ⴜ' => 'ⴜ', + 'Ⴝ' => 'ⴝ', + 'Ⴞ' => 'ⴞ', + 'Ⴟ' => 'ⴟ', + 'Ⴠ' => 'ⴠ', + 'Ⴡ' => 'ⴡ', + 'Ⴢ' => 'ⴢ', + 'Ⴣ' => 'ⴣ', + 'Ⴤ' => 'ⴤ', + 'Ⴥ' => 'ⴥ', + 'Ⴧ' => 'ⴧ', + 'Ⴭ' => 'ⴭ', + 'Ḁ' => 'ḁ', + 'Ḃ' => 'ḃ', + 'Ḅ' => 'ḅ', + 'Ḇ' => 'ḇ', + 'Ḉ' => 'ḉ', + 'Ḋ' => 'ḋ', + 'Ḍ' => 'ḍ', + 'Ḏ' => 'ḏ', + 'Ḑ' => 'ḑ', + 'Ḓ' => 'ḓ', + 'Ḕ' => 'ḕ', + 'Ḗ' => 'ḗ', + 'Ḙ' => 'ḙ', + 'Ḛ' => 'ḛ', + 'Ḝ' => 'ḝ', + 'Ḟ' => 'ḟ', + 'Ḡ' => 'ḡ', + 'Ḣ' => 'ḣ', + 'Ḥ' => 'ḥ', + 'Ḧ' => 'ḧ', + 'Ḩ' => 'ḩ', + 'Ḫ' => 'ḫ', + 'Ḭ' => 'ḭ', + 'Ḯ' => 'ḯ', + 'Ḱ' => 'ḱ', + 'Ḳ' => 'ḳ', + 'Ḵ' => 'ḵ', + 'Ḷ' => 'ḷ', + 'Ḹ' => 'ḹ', + 'Ḻ' => 'ḻ', + 'Ḽ' => 'ḽ', + 'Ḿ' => 'ḿ', + 'Ṁ' => 'ṁ', + 'Ṃ' => 'ṃ', + 'Ṅ' => 'ṅ', + 'Ṇ' => 'ṇ', + 'Ṉ' => 'ṉ', + 'Ṋ' => 'ṋ', + 'Ṍ' => 'ṍ', + 'Ṏ' => 'ṏ', + 'Ṑ' => 'ṑ', + 'Ṓ' => 'ṓ', + 'Ṕ' => 'ṕ', + 'Ṗ' => 'ṗ', + 'Ṙ' => 'ṙ', + 'Ṛ' => 'ṛ', + 'Ṝ' => 'ṝ', + 'Ṟ' => 'ṟ', + 'Ṡ' => 'ṡ', + 'Ṣ' => 'ṣ', + 'Ṥ' => 'ṥ', + 'Ṧ' => 'ṧ', + 'Ṩ' => 'ṩ', + 'Ṫ' => 'ṫ', + 'Ṭ' => 'ṭ', + 'Ṯ' => 'ṯ', + 'Ṱ' => 'ṱ', + 'Ṳ' => 'ṳ', + 'Ṵ' => 'ṵ', + 'Ṷ' => 'ṷ', + 'Ṹ' => 'ṹ', + 'Ṻ' => 'ṻ', + 'Ṽ' => 'ṽ', + 'Ṿ' => 'ṿ', + 'Ẁ' => 'ẁ', + 'Ẃ' => 'ẃ', + 'Ẅ' => 'ẅ', + 'Ẇ' => 'ẇ', + 'Ẉ' => 'ẉ', + 'Ẋ' => 'ẋ', + 'Ẍ' => 'ẍ', + 'Ẏ' => 'ẏ', + 'Ẑ' => 'ẑ', + 'Ẓ' => 'ẓ', + 'Ẕ' => 'ẕ', + 'ẞ' => 'ß', + 'Ạ' => 'ạ', + 'Ả' => 'ả', + 'Ấ' => 'ấ', + 'Ầ' => 'ầ', + 'Ẩ' => 'ẩ', + 'Ẫ' => 'ẫ', + 'Ậ' => 'ậ', + 'Ắ' => 'ắ', + 'Ằ' => 'ằ', + 'Ẳ' => 'ẳ', + 'Ẵ' => 'ẵ', + 'Ặ' => 'ặ', + 'Ẹ' => 'ẹ', + 'Ẻ' => 'ẻ', + 'Ẽ' => 'ẽ', + 'Ế' => 'ế', + 'Ề' => 'ề', + 'Ể' => 'ể', + 'Ễ' => 'ễ', + 'Ệ' => 'ệ', + 'Ỉ' => 'ỉ', + 'Ị' => 'ị', + 'Ọ' => 'ọ', + 'Ỏ' => 'ỏ', + 'Ố' => 'ố', + 'Ồ' => 'ồ', + 'Ổ' => 'ổ', + 'Ỗ' => 'ỗ', + 'Ộ' => 'ộ', + 'Ớ' => 'ớ', + 'Ờ' => 'ờ', + 'Ở' => 'ở', + 'Ỡ' => 'ỡ', + 'Ợ' => 'ợ', + 'Ụ' => 'ụ', + 'Ủ' => 'ủ', + 'Ứ' => 'ứ', + 'Ừ' => 'ừ', + 'Ử' => 'ử', + 'Ữ' => 'ữ', + 'Ự' => 'ự', + 'Ỳ' => 'ỳ', + 'Ỵ' => 'ỵ', + 'Ỷ' => 'ỷ', + 'Ỹ' => 'ỹ', + 'Ỻ' => 'ỻ', + 'Ỽ' => 'ỽ', + 'Ỿ' => 'ỿ', + 'Ἀ' => 'ἀ', + 'Ἁ' => 'ἁ', + 'Ἂ' => 'ἂ', + 'Ἃ' => 'ἃ', + 'Ἄ' => 'ἄ', + 'Ἅ' => 'ἅ', + 'Ἆ' => 'ἆ', + 'Ἇ' => 'ἇ', + 'Ἐ' => 'ἐ', + 'Ἑ' => 'ἑ', + 'Ἒ' => 'ἒ', + 'Ἓ' => 'ἓ', + 'Ἔ' => 'ἔ', + 'Ἕ' => 'ἕ', + 'Ἠ' => 'ἠ', + 'Ἡ' => 'ἡ', + 'Ἢ' => 'ἢ', + 'Ἣ' => 'ἣ', + 'Ἤ' => 'ἤ', + 'Ἥ' => 'ἥ', + 'Ἦ' => 'ἦ', + 'Ἧ' => 'ἧ', + 'Ἰ' => 'ἰ', + 'Ἱ' => 'ἱ', + 'Ἲ' => 'ἲ', + 'Ἳ' => 'ἳ', + 'Ἴ' => 'ἴ', + 'Ἵ' => 'ἵ', + 'Ἶ' => 'ἶ', + 'Ἷ' => 'ἷ', + 'Ὀ' => 'ὀ', + 'Ὁ' => 'ὁ', + 'Ὂ' => 'ὂ', + 'Ὃ' => 'ὃ', + 'Ὄ' => 'ὄ', + 'Ὅ' => 'ὅ', + 'Ὑ' => 'ὑ', + 'Ὓ' => 'ὓ', + 'Ὕ' => 'ὕ', + 'Ὗ' => 'ὗ', + 'Ὠ' => 'ὠ', + 'Ὡ' => 'ὡ', + 'Ὢ' => 'ὢ', + 'Ὣ' => 'ὣ', + 'Ὤ' => 'ὤ', + 'Ὥ' => 'ὥ', + 'Ὦ' => 'ὦ', + 'Ὧ' => 'ὧ', + 'ᾈ' => 'ᾀ', + 'ᾉ' => 'ᾁ', + 'ᾊ' => 'ᾂ', + 'ᾋ' => 'ᾃ', + 'ᾌ' => 'ᾄ', + 'ᾍ' => 'ᾅ', + 'ᾎ' => 'ᾆ', + 'ᾏ' => 'ᾇ', + 'ᾘ' => 'ᾐ', + 'ᾙ' => 'ᾑ', + 'ᾚ' => 'ᾒ', + 'ᾛ' => 'ᾓ', + 'ᾜ' => 'ᾔ', + 'ᾝ' => 'ᾕ', + 'ᾞ' => 'ᾖ', + 'ᾟ' => 'ᾗ', + 'ᾨ' => 'ᾠ', + 'ᾩ' => 'ᾡ', + 'ᾪ' => 'ᾢ', + 'ᾫ' => 'ᾣ', + 'ᾬ' => 'ᾤ', + 'ᾭ' => 'ᾥ', + 'ᾮ' => 'ᾦ', + 'ᾯ' => 'ᾧ', + 'Ᾰ' => 'ᾰ', + 'Ᾱ' => 'ᾱ', + 'Ὰ' => 'ὰ', + 'Ά' => 'ά', + 'ᾼ' => 'ᾳ', + 'Ὲ' => 'ὲ', + 'Έ' => 'έ', + 'Ὴ' => 'ὴ', + 'Ή' => 'ή', + 'ῌ' => 'ῃ', + 'Ῐ' => 'ῐ', + 'Ῑ' => 'ῑ', + 'Ὶ' => 'ὶ', + 'Ί' => 'ί', + 'Ῠ' => 'ῠ', + 'Ῡ' => 'ῡ', + 'Ὺ' => 'ὺ', + 'Ύ' => 'ύ', + 'Ῥ' => 'ῥ', + 'Ὸ' => 'ὸ', + 'Ό' => 'ό', + 'Ὼ' => 'ὼ', + 'Ώ' => 'ώ', + 'ῼ' => 'ῳ', + 'Ω' => 'ω', + 'K' => 'k', + 'Å' => 'å', + 'Ⅎ' => 'ⅎ', + 'Ⅰ' => 'ⅰ', + 'Ⅱ' => 'ⅱ', + 'Ⅲ' => 'ⅲ', + 'Ⅳ' => 'ⅳ', + 'Ⅴ' => 'ⅴ', + 'Ⅵ' => 'ⅵ', + 'Ⅶ' => 'ⅶ', + 'Ⅷ' => 'ⅷ', + 'Ⅸ' => 'ⅸ', + 'Ⅹ' => 'ⅹ', + 'Ⅺ' => 'ⅺ', + 'Ⅻ' => 'ⅻ', + 'Ⅼ' => 'ⅼ', + 'Ⅽ' => 'ⅽ', + 'Ⅾ' => 'ⅾ', + 'Ⅿ' => 'ⅿ', + 'Ↄ' => 'ↄ', + 'Ⓐ' => 'ⓐ', + 'Ⓑ' => 'ⓑ', + 'Ⓒ' => 'ⓒ', + 'Ⓓ' => 'ⓓ', + 'Ⓔ' => 'ⓔ', + 'Ⓕ' => 'ⓕ', + 'Ⓖ' => 'ⓖ', + 'Ⓗ' => 'ⓗ', + 'Ⓘ' => 'ⓘ', + 'Ⓙ' => 'ⓙ', + 'Ⓚ' => 'ⓚ', + 'Ⓛ' => 'ⓛ', + 'Ⓜ' => 'ⓜ', + 'Ⓝ' => 'ⓝ', + 'Ⓞ' => 'ⓞ', + 'Ⓟ' => 'ⓟ', + 'Ⓠ' => 'ⓠ', + 'Ⓡ' => 'ⓡ', + 'Ⓢ' => 'ⓢ', + 'Ⓣ' => 'ⓣ', + 'Ⓤ' => 'ⓤ', + 'Ⓥ' => 'ⓥ', + 'Ⓦ' => 'ⓦ', + 'Ⓧ' => 'ⓧ', + 'Ⓨ' => 'ⓨ', + 'Ⓩ' => 'ⓩ', + 'Ⰰ' => 'ⰰ', + 'Ⰱ' => 'ⰱ', + 'Ⰲ' => 'ⰲ', + 'Ⰳ' => 'ⰳ', + 'Ⰴ' => 'ⰴ', + 'Ⰵ' => 'ⰵ', + 'Ⰶ' => 'ⰶ', + 'Ⰷ' => 'ⰷ', + 'Ⰸ' => 'ⰸ', + 'Ⰹ' => 'ⰹ', + 'Ⰺ' => 'ⰺ', + 'Ⰻ' => 'ⰻ', + 'Ⰼ' => 'ⰼ', + 'Ⰽ' => 'ⰽ', + 'Ⰾ' => 'ⰾ', + 'Ⰿ' => 'ⰿ', + 'Ⱀ' => 'ⱀ', + 'Ⱁ' => 'ⱁ', + 'Ⱂ' => 'ⱂ', + 'Ⱃ' => 'ⱃ', + 'Ⱄ' => 'ⱄ', + 'Ⱅ' => 'ⱅ', + 'Ⱆ' => 'ⱆ', + 'Ⱇ' => 'ⱇ', + 'Ⱈ' => 'ⱈ', + 'Ⱉ' => 'ⱉ', + 'Ⱊ' => 'ⱊ', + 'Ⱋ' => 'ⱋ', + 'Ⱌ' => 'ⱌ', + 'Ⱍ' => 'ⱍ', + 'Ⱎ' => 'ⱎ', + 'Ⱏ' => 'ⱏ', + 'Ⱐ' => 'ⱐ', + 'Ⱑ' => 'ⱑ', + 'Ⱒ' => 'ⱒ', + 'Ⱓ' => 'ⱓ', + 'Ⱔ' => 'ⱔ', + 'Ⱕ' => 'ⱕ', + 'Ⱖ' => 'ⱖ', + 'Ⱗ' => 'ⱗ', + 'Ⱘ' => 'ⱘ', + 'Ⱙ' => 'ⱙ', + 'Ⱚ' => 'ⱚ', + 'Ⱛ' => 'ⱛ', + 'Ⱜ' => 'ⱜ', + 'Ⱝ' => 'ⱝ', + 'Ⱞ' => 'ⱞ', + 'Ⱡ' => 'ⱡ', + 'Ɫ' => 'ɫ', + 'Ᵽ' => 'ᵽ', + 'Ɽ' => 'ɽ', + 'Ⱨ' => 'ⱨ', + 'Ⱪ' => 'ⱪ', + 'Ⱬ' => 'ⱬ', + 'Ɑ' => 'ɑ', + 'Ɱ' => 'ɱ', + 'Ɐ' => 'ɐ', + 'Ɒ' => 'ɒ', + 'Ⱳ' => 'ⱳ', + 'Ⱶ' => 'ⱶ', + 'Ȿ' => 'ȿ', + 'Ɀ' => 'ɀ', + 'Ⲁ' => 'ⲁ', + 'Ⲃ' => 'ⲃ', + 'Ⲅ' => 'ⲅ', + 'Ⲇ' => 'ⲇ', + 'Ⲉ' => 'ⲉ', + 'Ⲋ' => 'ⲋ', + 'Ⲍ' => 'ⲍ', + 'Ⲏ' => 'ⲏ', + 'Ⲑ' => 'ⲑ', + 'Ⲓ' => 'ⲓ', + 'Ⲕ' => 'ⲕ', + 'Ⲗ' => 'ⲗ', + 'Ⲙ' => 'ⲙ', + 'Ⲛ' => 'ⲛ', + 'Ⲝ' => 'ⲝ', + 'Ⲟ' => 'ⲟ', + 'Ⲡ' => 'ⲡ', + 'Ⲣ' => 'ⲣ', + 'Ⲥ' => 'ⲥ', + 'Ⲧ' => 'ⲧ', + 'Ⲩ' => 'ⲩ', + 'Ⲫ' => 'ⲫ', + 'Ⲭ' => 'ⲭ', + 'Ⲯ' => 'ⲯ', + 'Ⲱ' => 'ⲱ', + 'Ⲳ' => 'ⲳ', + 'Ⲵ' => 'ⲵ', + 'Ⲷ' => 'ⲷ', + 'Ⲹ' => 'ⲹ', + 'Ⲻ' => 'ⲻ', + 'Ⲽ' => 'ⲽ', + 'Ⲿ' => 'ⲿ', + 'Ⳁ' => 'ⳁ', + 'Ⳃ' => 'ⳃ', + 'Ⳅ' => 'ⳅ', + 'Ⳇ' => 'ⳇ', + 'Ⳉ' => 'ⳉ', + 'Ⳋ' => 'ⳋ', + 'Ⳍ' => 'ⳍ', + 'Ⳏ' => 'ⳏ', + 'Ⳑ' => 'ⳑ', + 'Ⳓ' => 'ⳓ', + 'Ⳕ' => 'ⳕ', + 'Ⳗ' => 'ⳗ', + 'Ⳙ' => 'ⳙ', + 'Ⳛ' => 'ⳛ', + 'Ⳝ' => 'ⳝ', + 'Ⳟ' => 'ⳟ', + 'Ⳡ' => 'ⳡ', + 'Ⳣ' => 'ⳣ', + 'Ⳬ' => 'ⳬ', + 'Ⳮ' => 'ⳮ', + 'Ⳳ' => 'ⳳ', + 'Ꙁ' => 'ꙁ', + 'Ꙃ' => 'ꙃ', + 'Ꙅ' => 'ꙅ', + 'Ꙇ' => 'ꙇ', + 'Ꙉ' => 'ꙉ', + 'Ꙋ' => 'ꙋ', + 'Ꙍ' => 'ꙍ', + 'Ꙏ' => 'ꙏ', + 'Ꙑ' => 'ꙑ', + 'Ꙓ' => 'ꙓ', + 'Ꙕ' => 'ꙕ', + 'Ꙗ' => 'ꙗ', + 'Ꙙ' => 'ꙙ', + 'Ꙛ' => 'ꙛ', + 'Ꙝ' => 'ꙝ', + 'Ꙟ' => 'ꙟ', + 'Ꙡ' => 'ꙡ', + 'Ꙣ' => 'ꙣ', + 'Ꙥ' => 'ꙥ', + 'Ꙧ' => 'ꙧ', + 'Ꙩ' => 'ꙩ', + 'Ꙫ' => 'ꙫ', + 'Ꙭ' => 'ꙭ', + 'Ꚁ' => 'ꚁ', + 'Ꚃ' => 'ꚃ', + 'Ꚅ' => 'ꚅ', + 'Ꚇ' => 'ꚇ', + 'Ꚉ' => 'ꚉ', + 'Ꚋ' => 'ꚋ', + 'Ꚍ' => 'ꚍ', + 'Ꚏ' => 'ꚏ', + 'Ꚑ' => 'ꚑ', + 'Ꚓ' => 'ꚓ', + 'Ꚕ' => 'ꚕ', + 'Ꚗ' => 'ꚗ', + 'Ꚙ' => 'ꚙ', + 'Ꚛ' => 'ꚛ', + 'Ꜣ' => 'ꜣ', + 'Ꜥ' => 'ꜥ', + 'Ꜧ' => 'ꜧ', + 'Ꜩ' => 'ꜩ', + 'Ꜫ' => 'ꜫ', + 'Ꜭ' => 'ꜭ', + 'Ꜯ' => 'ꜯ', + 'Ꜳ' => 'ꜳ', + 'Ꜵ' => 'ꜵ', + 'Ꜷ' => 'ꜷ', + 'Ꜹ' => 'ꜹ', + 'Ꜻ' => 'ꜻ', + 'Ꜽ' => 'ꜽ', + 'Ꜿ' => 'ꜿ', + 'Ꝁ' => 'ꝁ', + 'Ꝃ' => 'ꝃ', + 'Ꝅ' => 'ꝅ', + 'Ꝇ' => 'ꝇ', + 'Ꝉ' => 'ꝉ', + 'Ꝋ' => 'ꝋ', + 'Ꝍ' => 'ꝍ', + 'Ꝏ' => 'ꝏ', + 'Ꝑ' => 'ꝑ', + 'Ꝓ' => 'ꝓ', + 'Ꝕ' => 'ꝕ', + 'Ꝗ' => 'ꝗ', + 'Ꝙ' => 'ꝙ', + 'Ꝛ' => 'ꝛ', + 'Ꝝ' => 'ꝝ', + 'Ꝟ' => 'ꝟ', + 'Ꝡ' => 'ꝡ', + 'Ꝣ' => 'ꝣ', + 'Ꝥ' => 'ꝥ', + 'Ꝧ' => 'ꝧ', + 'Ꝩ' => 'ꝩ', + 'Ꝫ' => 'ꝫ', + 'Ꝭ' => 'ꝭ', + 'Ꝯ' => 'ꝯ', + 'Ꝺ' => 'ꝺ', + 'Ꝼ' => 'ꝼ', + 'Ᵹ' => 'ᵹ', + 'Ꝿ' => 'ꝿ', + 'Ꞁ' => 'ꞁ', + 'Ꞃ' => 'ꞃ', + 'Ꞅ' => 'ꞅ', + 'Ꞇ' => 'ꞇ', + 'Ꞌ' => 'ꞌ', + 'Ɥ' => 'ɥ', + 'Ꞑ' => 'ꞑ', + 'Ꞓ' => 'ꞓ', + 'Ꞗ' => 'ꞗ', + 'Ꞙ' => 'ꞙ', + 'Ꞛ' => 'ꞛ', + 'Ꞝ' => 'ꞝ', + 'Ꞟ' => 'ꞟ', + 'Ꞡ' => 'ꞡ', + 'Ꞣ' => 'ꞣ', + 'Ꞥ' => 'ꞥ', + 'Ꞧ' => 'ꞧ', + 'Ꞩ' => 'ꞩ', + 'Ɦ' => 'ɦ', + 'Ɜ' => 'ɜ', + 'Ɡ' => 'ɡ', + 'Ɬ' => 'ɬ', + 'Ʞ' => 'ʞ', + 'Ʇ' => 'ʇ', + 'A' => 'a', + 'B' => 'b', + 'C' => 'c', + 'D' => 'd', + 'E' => 'e', + 'F' => 'f', + 'G' => 'g', + 'H' => 'h', + 'I' => 'i', + 'J' => 'j', + 'K' => 'k', + 'L' => 'l', + 'M' => 'm', + 'N' => 'n', + 'O' => 'o', + 'P' => 'p', + 'Q' => 'q', + 'R' => 'r', + 'S' => 's', + 'T' => 't', + 'U' => 'u', + 'V' => 'v', + 'W' => 'w', + 'X' => 'x', + 'Y' => 'y', + 'Z' => 'z', + '𐐀' => '𐐨', + '𐐁' => '𐐩', + '𐐂' => '𐐪', + '𐐃' => '𐐫', + '𐐄' => '𐐬', + '𐐅' => '𐐭', + '𐐆' => '𐐮', + '𐐇' => '𐐯', + '𐐈' => '𐐰', + '𐐉' => '𐐱', + '𐐊' => '𐐲', + '𐐋' => '𐐳', + '𐐌' => '𐐴', + '𐐍' => '𐐵', + '𐐎' => '𐐶', + '𐐏' => '𐐷', + '𐐐' => '𐐸', + '𐐑' => '𐐹', + '𐐒' => '𐐺', + '𐐓' => '𐐻', + '𐐔' => '𐐼', + '𐐕' => '𐐽', + '𐐖' => '𐐾', + '𐐗' => '𐐿', + '𐐘' => '𐑀', + '𐐙' => '𐑁', + '𐐚' => '𐑂', + '𐐛' => '𐑃', + '𐐜' => '𐑄', + '𐐝' => '𐑅', + '𐐞' => '𐑆', + '𐐟' => '𐑇', + '𐐠' => '𐑈', + '𐐡' => '𐑉', + '𐐢' => '𐑊', + '𐐣' => '𐑋', + '𐐤' => '𐑌', + '𐐥' => '𐑍', + '𐐦' => '𐑎', + '𐐧' => '𐑏', + '𑢠' => '𑣀', + '𑢡' => '𑣁', + '𑢢' => '𑣂', + '𑢣' => '𑣃', + '𑢤' => '𑣄', + '𑢥' => '𑣅', + '𑢦' => '𑣆', + '𑢧' => '𑣇', + '𑢨' => '𑣈', + '𑢩' => '𑣉', + '𑢪' => '𑣊', + '𑢫' => '𑣋', + '𑢬' => '𑣌', + '𑢭' => '𑣍', + '𑢮' => '𑣎', + '𑢯' => '𑣏', + '𑢰' => '𑣐', + '𑢱' => '𑣑', + '𑢲' => '𑣒', + '𑢳' => '𑣓', + '𑢴' => '𑣔', + '𑢵' => '𑣕', + '𑢶' => '𑣖', + '𑢷' => '𑣗', + '𑢸' => '𑣘', + '𑢹' => '𑣙', + '𑢺' => '𑣚', + '𑢻' => '𑣛', + '𑢼' => '𑣜', + '𑢽' => '𑣝', + '𑢾' => '𑣞', + '𑢿' => '𑣟', +); diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php new file mode 100644 index 0000000..2a8f6e7 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php @@ -0,0 +1,5 @@ + 'A', + 'b' => 'B', + 'c' => 'C', + 'd' => 'D', + 'e' => 'E', + 'f' => 'F', + 'g' => 'G', + 'h' => 'H', + 'i' => 'I', + 'j' => 'J', + 'k' => 'K', + 'l' => 'L', + 'm' => 'M', + 'n' => 'N', + 'o' => 'O', + 'p' => 'P', + 'q' => 'Q', + 'r' => 'R', + 's' => 'S', + 't' => 'T', + 'u' => 'U', + 'v' => 'V', + 'w' => 'W', + 'x' => 'X', + 'y' => 'Y', + 'z' => 'Z', + 'µ' => 'Μ', + 'à' => 'À', + 'á' => 'Á', + 'â' => 'Â', + 'ã' => 'Ã', + 'ä' => 'Ä', + 'å' => 'Å', + 'æ' => 'Æ', + 'ç' => 'Ç', + 'è' => 'È', + 'é' => 'É', + 'ê' => 'Ê', + 'ë' => 'Ë', + 'ì' => 'Ì', + 'í' => 'Í', + 'î' => 'Î', + 'ï' => 'Ï', + 'ð' => 'Ð', + 'ñ' => 'Ñ', + 'ò' => 'Ò', + 'ó' => 'Ó', + 'ô' => 'Ô', + 'õ' => 'Õ', + 'ö' => 'Ö', + 'ø' => 'Ø', + 'ù' => 'Ù', + 'ú' => 'Ú', + 'û' => 'Û', + 'ü' => 'Ü', + 'ý' => 'Ý', + 'þ' => 'Þ', + 'ÿ' => 'Ÿ', + 'ā' => 'Ā', + 'ă' => 'Ă', + 'ą' => 'Ą', + 'ć' => 'Ć', + 'ĉ' => 'Ĉ', + 'ċ' => 'Ċ', + 'č' => 'Č', + 'ď' => 'Ď', + 'đ' => 'Đ', + 'ē' => 'Ē', + 'ĕ' => 'Ĕ', + 'ė' => 'Ė', + 'ę' => 'Ę', + 'ě' => 'Ě', + 'ĝ' => 'Ĝ', + 'ğ' => 'Ğ', + 'ġ' => 'Ġ', + 'ģ' => 'Ģ', + 'ĥ' => 'Ĥ', + 'ħ' => 'Ħ', + 'ĩ' => 'Ĩ', + 'ī' => 'Ī', + 'ĭ' => 'Ĭ', + 'į' => 'Į', + 'ı' => 'I', + 'ij' => 'IJ', + 'ĵ' => 'Ĵ', + 'ķ' => 'Ķ', + 'ĺ' => 'Ĺ', + 'ļ' => 'Ļ', + 'ľ' => 'Ľ', + 'ŀ' => 'Ŀ', + 'ł' => 'Ł', + 'ń' => 'Ń', + 'ņ' => 'Ņ', + 'ň' => 'Ň', + 'ŋ' => 'Ŋ', + 'ō' => 'Ō', + 'ŏ' => 'Ŏ', + 'ő' => 'Ő', + 'œ' => 'Œ', + 'ŕ' => 'Ŕ', + 'ŗ' => 'Ŗ', + 'ř' => 'Ř', + 'ś' => 'Ś', + 'ŝ' => 'Ŝ', + 'ş' => 'Ş', + 'š' => 'Š', + 'ţ' => 'Ţ', + 'ť' => 'Ť', + 'ŧ' => 'Ŧ', + 'ũ' => 'Ũ', + 'ū' => 'Ū', + 'ŭ' => 'Ŭ', + 'ů' => 'Ů', + 'ű' => 'Ű', + 'ų' => 'Ų', + 'ŵ' => 'Ŵ', + 'ŷ' => 'Ŷ', + 'ź' => 'Ź', + 'ż' => 'Ż', + 'ž' => 'Ž', + 'ſ' => 'S', + 'ƀ' => 'Ƀ', + 'ƃ' => 'Ƃ', + 'ƅ' => 'Ƅ', + 'ƈ' => 'Ƈ', + 'ƌ' => 'Ƌ', + 'ƒ' => 'Ƒ', + 'ƕ' => 'Ƕ', + 'ƙ' => 'Ƙ', + 'ƚ' => 'Ƚ', + 'ƞ' => 'Ƞ', + 'ơ' => 'Ơ', + 'ƣ' => 'Ƣ', + 'ƥ' => 'Ƥ', + 'ƨ' => 'Ƨ', + 'ƭ' => 'Ƭ', + 'ư' => 'Ư', + 'ƴ' => 'Ƴ', + 'ƶ' => 'Ƶ', + 'ƹ' => 'Ƹ', + 'ƽ' => 'Ƽ', + 'ƿ' => 'Ƿ', + 'Dž' => 'DŽ', + 'dž' => 'DŽ', + 'Lj' => 'LJ', + 'lj' => 'LJ', + 'Nj' => 'NJ', + 'nj' => 'NJ', + 'ǎ' => 'Ǎ', + 'ǐ' => 'Ǐ', + 'ǒ' => 'Ǒ', + 'ǔ' => 'Ǔ', + 'ǖ' => 'Ǖ', + 'ǘ' => 'Ǘ', + 'ǚ' => 'Ǚ', + 'ǜ' => 'Ǜ', + 'ǝ' => 'Ǝ', + 'ǟ' => 'Ǟ', + 'ǡ' => 'Ǡ', + 'ǣ' => 'Ǣ', + 'ǥ' => 'Ǥ', + 'ǧ' => 'Ǧ', + 'ǩ' => 'Ǩ', + 'ǫ' => 'Ǫ', + 'ǭ' => 'Ǭ', + 'ǯ' => 'Ǯ', + 'Dz' => 'DZ', + 'dz' => 'DZ', + 'ǵ' => 'Ǵ', + 'ǹ' => 'Ǹ', + 'ǻ' => 'Ǻ', + 'ǽ' => 'Ǽ', + 'ǿ' => 'Ǿ', + 'ȁ' => 'Ȁ', + 'ȃ' => 'Ȃ', + 'ȅ' => 'Ȅ', + 'ȇ' => 'Ȇ', + 'ȉ' => 'Ȉ', + 'ȋ' => 'Ȋ', + 'ȍ' => 'Ȍ', + 'ȏ' => 'Ȏ', + 'ȑ' => 'Ȑ', + 'ȓ' => 'Ȓ', + 'ȕ' => 'Ȕ', + 'ȗ' => 'Ȗ', + 'ș' => 'Ș', + 'ț' => 'Ț', + 'ȝ' => 'Ȝ', + 'ȟ' => 'Ȟ', + 'ȣ' => 'Ȣ', + 'ȥ' => 'Ȥ', + 'ȧ' => 'Ȧ', + 'ȩ' => 'Ȩ', + 'ȫ' => 'Ȫ', + 'ȭ' => 'Ȭ', + 'ȯ' => 'Ȯ', + 'ȱ' => 'Ȱ', + 'ȳ' => 'Ȳ', + 'ȼ' => 'Ȼ', + 'ȿ' => 'Ȿ', + 'ɀ' => 'Ɀ', + 'ɂ' => 'Ɂ', + 'ɇ' => 'Ɇ', + 'ɉ' => 'Ɉ', + 'ɋ' => 'Ɋ', + 'ɍ' => 'Ɍ', + 'ɏ' => 'Ɏ', + 'ɐ' => 'Ɐ', + 'ɑ' => 'Ɑ', + 'ɒ' => 'Ɒ', + 'ɓ' => 'Ɓ', + 'ɔ' => 'Ɔ', + 'ɖ' => 'Ɖ', + 'ɗ' => 'Ɗ', + 'ə' => 'Ə', + 'ɛ' => 'Ɛ', + 'ɜ' => 'Ɜ', + 'ɠ' => 'Ɠ', + 'ɡ' => 'Ɡ', + 'ɣ' => 'Ɣ', + 'ɥ' => 'Ɥ', + 'ɦ' => 'Ɦ', + 'ɨ' => 'Ɨ', + 'ɩ' => 'Ɩ', + 'ɫ' => 'Ɫ', + 'ɬ' => 'Ɬ', + 'ɯ' => 'Ɯ', + 'ɱ' => 'Ɱ', + 'ɲ' => 'Ɲ', + 'ɵ' => 'Ɵ', + 'ɽ' => 'Ɽ', + 'ʀ' => 'Ʀ', + 'ʃ' => 'Ʃ', + 'ʇ' => 'Ʇ', + 'ʈ' => 'Ʈ', + 'ʉ' => 'Ʉ', + 'ʊ' => 'Ʊ', + 'ʋ' => 'Ʋ', + 'ʌ' => 'Ʌ', + 'ʒ' => 'Ʒ', + 'ʞ' => 'Ʞ', + 'ͅ' => 'Ι', + 'ͱ' => 'Ͱ', + 'ͳ' => 'Ͳ', + 'ͷ' => 'Ͷ', + 'ͻ' => 'Ͻ', + 'ͼ' => 'Ͼ', + 'ͽ' => 'Ͽ', + 'ά' => 'Ά', + 'έ' => 'Έ', + 'ή' => 'Ή', + 'ί' => 'Ί', + 'α' => 'Α', + 'β' => 'Β', + 'γ' => 'Γ', + 'δ' => 'Δ', + 'ε' => 'Ε', + 'ζ' => 'Ζ', + 'η' => 'Η', + 'θ' => 'Θ', + 'ι' => 'Ι', + 'κ' => 'Κ', + 'λ' => 'Λ', + 'μ' => 'Μ', + 'ν' => 'Ν', + 'ξ' => 'Ξ', + 'ο' => 'Ο', + 'π' => 'Π', + 'ρ' => 'Ρ', + 'ς' => 'Σ', + 'σ' => 'Σ', + 'τ' => 'Τ', + 'υ' => 'Υ', + 'φ' => 'Φ', + 'χ' => 'Χ', + 'ψ' => 'Ψ', + 'ω' => 'Ω', + 'ϊ' => 'Ϊ', + 'ϋ' => 'Ϋ', + 'ό' => 'Ό', + 'ύ' => 'Ύ', + 'ώ' => 'Ώ', + 'ϐ' => 'Β', + 'ϑ' => 'Θ', + 'ϕ' => 'Φ', + 'ϖ' => 'Π', + 'ϗ' => 'Ϗ', + 'ϙ' => 'Ϙ', + 'ϛ' => 'Ϛ', + 'ϝ' => 'Ϝ', + 'ϟ' => 'Ϟ', + 'ϡ' => 'Ϡ', + 'ϣ' => 'Ϣ', + 'ϥ' => 'Ϥ', + 'ϧ' => 'Ϧ', + 'ϩ' => 'Ϩ', + 'ϫ' => 'Ϫ', + 'ϭ' => 'Ϭ', + 'ϯ' => 'Ϯ', + 'ϰ' => 'Κ', + 'ϱ' => 'Ρ', + 'ϲ' => 'Ϲ', + 'ϳ' => 'Ϳ', + 'ϵ' => 'Ε', + 'ϸ' => 'Ϸ', + 'ϻ' => 'Ϻ', + 'а' => 'А', + 'б' => 'Б', + 'в' => 'В', + 'г' => 'Г', + 'д' => 'Д', + 'е' => 'Е', + 'ж' => 'Ж', + 'з' => 'З', + 'и' => 'И', + 'й' => 'Й', + 'к' => 'К', + 'л' => 'Л', + 'м' => 'М', + 'н' => 'Н', + 'о' => 'О', + 'п' => 'П', + 'р' => 'Р', + 'с' => 'С', + 'т' => 'Т', + 'у' => 'У', + 'ф' => 'Ф', + 'х' => 'Х', + 'ц' => 'Ц', + 'ч' => 'Ч', + 'ш' => 'Ш', + 'щ' => 'Щ', + 'ъ' => 'Ъ', + 'ы' => 'Ы', + 'ь' => 'Ь', + 'э' => 'Э', + 'ю' => 'Ю', + 'я' => 'Я', + 'ѐ' => 'Ѐ', + 'ё' => 'Ё', + 'ђ' => 'Ђ', + 'ѓ' => 'Ѓ', + 'є' => 'Є', + 'ѕ' => 'Ѕ', + 'і' => 'І', + 'ї' => 'Ї', + 'ј' => 'Ј', + 'љ' => 'Љ', + 'њ' => 'Њ', + 'ћ' => 'Ћ', + 'ќ' => 'Ќ', + 'ѝ' => 'Ѝ', + 'ў' => 'Ў', + 'џ' => 'Џ', + 'ѡ' => 'Ѡ', + 'ѣ' => 'Ѣ', + 'ѥ' => 'Ѥ', + 'ѧ' => 'Ѧ', + 'ѩ' => 'Ѩ', + 'ѫ' => 'Ѫ', + 'ѭ' => 'Ѭ', + 'ѯ' => 'Ѯ', + 'ѱ' => 'Ѱ', + 'ѳ' => 'Ѳ', + 'ѵ' => 'Ѵ', + 'ѷ' => 'Ѷ', + 'ѹ' => 'Ѹ', + 'ѻ' => 'Ѻ', + 'ѽ' => 'Ѽ', + 'ѿ' => 'Ѿ', + 'ҁ' => 'Ҁ', + 'ҋ' => 'Ҋ', + 'ҍ' => 'Ҍ', + 'ҏ' => 'Ҏ', + 'ґ' => 'Ґ', + 'ғ' => 'Ғ', + 'ҕ' => 'Ҕ', + 'җ' => 'Җ', + 'ҙ' => 'Ҙ', + 'қ' => 'Қ', + 'ҝ' => 'Ҝ', + 'ҟ' => 'Ҟ', + 'ҡ' => 'Ҡ', + 'ң' => 'Ң', + 'ҥ' => 'Ҥ', + 'ҧ' => 'Ҧ', + 'ҩ' => 'Ҩ', + 'ҫ' => 'Ҫ', + 'ҭ' => 'Ҭ', + 'ү' => 'Ү', + 'ұ' => 'Ұ', + 'ҳ' => 'Ҳ', + 'ҵ' => 'Ҵ', + 'ҷ' => 'Ҷ', + 'ҹ' => 'Ҹ', + 'һ' => 'Һ', + 'ҽ' => 'Ҽ', + 'ҿ' => 'Ҿ', + 'ӂ' => 'Ӂ', + 'ӄ' => 'Ӄ', + 'ӆ' => 'Ӆ', + 'ӈ' => 'Ӈ', + 'ӊ' => 'Ӊ', + 'ӌ' => 'Ӌ', + 'ӎ' => 'Ӎ', + 'ӏ' => 'Ӏ', + 'ӑ' => 'Ӑ', + 'ӓ' => 'Ӓ', + 'ӕ' => 'Ӕ', + 'ӗ' => 'Ӗ', + 'ә' => 'Ә', + 'ӛ' => 'Ӛ', + 'ӝ' => 'Ӝ', + 'ӟ' => 'Ӟ', + 'ӡ' => 'Ӡ', + 'ӣ' => 'Ӣ', + 'ӥ' => 'Ӥ', + 'ӧ' => 'Ӧ', + 'ө' => 'Ө', + 'ӫ' => 'Ӫ', + 'ӭ' => 'Ӭ', + 'ӯ' => 'Ӯ', + 'ӱ' => 'Ӱ', + 'ӳ' => 'Ӳ', + 'ӵ' => 'Ӵ', + 'ӷ' => 'Ӷ', + 'ӹ' => 'Ӹ', + 'ӻ' => 'Ӻ', + 'ӽ' => 'Ӽ', + 'ӿ' => 'Ӿ', + 'ԁ' => 'Ԁ', + 'ԃ' => 'Ԃ', + 'ԅ' => 'Ԅ', + 'ԇ' => 'Ԇ', + 'ԉ' => 'Ԉ', + 'ԋ' => 'Ԋ', + 'ԍ' => 'Ԍ', + 'ԏ' => 'Ԏ', + 'ԑ' => 'Ԑ', + 'ԓ' => 'Ԓ', + 'ԕ' => 'Ԕ', + 'ԗ' => 'Ԗ', + 'ԙ' => 'Ԙ', + 'ԛ' => 'Ԛ', + 'ԝ' => 'Ԝ', + 'ԟ' => 'Ԟ', + 'ԡ' => 'Ԡ', + 'ԣ' => 'Ԣ', + 'ԥ' => 'Ԥ', + 'ԧ' => 'Ԧ', + 'ԩ' => 'Ԩ', + 'ԫ' => 'Ԫ', + 'ԭ' => 'Ԭ', + 'ԯ' => 'Ԯ', + 'ա' => 'Ա', + 'բ' => 'Բ', + 'գ' => 'Գ', + 'դ' => 'Դ', + 'ե' => 'Ե', + 'զ' => 'Զ', + 'է' => 'Է', + 'ը' => 'Ը', + 'թ' => 'Թ', + 'ժ' => 'Ժ', + 'ի' => 'Ի', + 'լ' => 'Լ', + 'խ' => 'Խ', + 'ծ' => 'Ծ', + 'կ' => 'Կ', + 'հ' => 'Հ', + 'ձ' => 'Ձ', + 'ղ' => 'Ղ', + 'ճ' => 'Ճ', + 'մ' => 'Մ', + 'յ' => 'Յ', + 'ն' => 'Ն', + 'շ' => 'Շ', + 'ո' => 'Ո', + 'չ' => 'Չ', + 'պ' => 'Պ', + 'ջ' => 'Ջ', + 'ռ' => 'Ռ', + 'ս' => 'Ս', + 'վ' => 'Վ', + 'տ' => 'Տ', + 'ր' => 'Ր', + 'ց' => 'Ց', + 'ւ' => 'Ւ', + 'փ' => 'Փ', + 'ք' => 'Ք', + 'օ' => 'Օ', + 'ֆ' => 'Ֆ', + 'ᵹ' => 'Ᵹ', + 'ᵽ' => 'Ᵽ', + 'ḁ' => 'Ḁ', + 'ḃ' => 'Ḃ', + 'ḅ' => 'Ḅ', + 'ḇ' => 'Ḇ', + 'ḉ' => 'Ḉ', + 'ḋ' => 'Ḋ', + 'ḍ' => 'Ḍ', + 'ḏ' => 'Ḏ', + 'ḑ' => 'Ḑ', + 'ḓ' => 'Ḓ', + 'ḕ' => 'Ḕ', + 'ḗ' => 'Ḗ', + 'ḙ' => 'Ḙ', + 'ḛ' => 'Ḛ', + 'ḝ' => 'Ḝ', + 'ḟ' => 'Ḟ', + 'ḡ' => 'Ḡ', + 'ḣ' => 'Ḣ', + 'ḥ' => 'Ḥ', + 'ḧ' => 'Ḧ', + 'ḩ' => 'Ḩ', + 'ḫ' => 'Ḫ', + 'ḭ' => 'Ḭ', + 'ḯ' => 'Ḯ', + 'ḱ' => 'Ḱ', + 'ḳ' => 'Ḳ', + 'ḵ' => 'Ḵ', + 'ḷ' => 'Ḷ', + 'ḹ' => 'Ḹ', + 'ḻ' => 'Ḻ', + 'ḽ' => 'Ḽ', + 'ḿ' => 'Ḿ', + 'ṁ' => 'Ṁ', + 'ṃ' => 'Ṃ', + 'ṅ' => 'Ṅ', + 'ṇ' => 'Ṇ', + 'ṉ' => 'Ṉ', + 'ṋ' => 'Ṋ', + 'ṍ' => 'Ṍ', + 'ṏ' => 'Ṏ', + 'ṑ' => 'Ṑ', + 'ṓ' => 'Ṓ', + 'ṕ' => 'Ṕ', + 'ṗ' => 'Ṗ', + 'ṙ' => 'Ṙ', + 'ṛ' => 'Ṛ', + 'ṝ' => 'Ṝ', + 'ṟ' => 'Ṟ', + 'ṡ' => 'Ṡ', + 'ṣ' => 'Ṣ', + 'ṥ' => 'Ṥ', + 'ṧ' => 'Ṧ', + 'ṩ' => 'Ṩ', + 'ṫ' => 'Ṫ', + 'ṭ' => 'Ṭ', + 'ṯ' => 'Ṯ', + 'ṱ' => 'Ṱ', + 'ṳ' => 'Ṳ', + 'ṵ' => 'Ṵ', + 'ṷ' => 'Ṷ', + 'ṹ' => 'Ṹ', + 'ṻ' => 'Ṻ', + 'ṽ' => 'Ṽ', + 'ṿ' => 'Ṿ', + 'ẁ' => 'Ẁ', + 'ẃ' => 'Ẃ', + 'ẅ' => 'Ẅ', + 'ẇ' => 'Ẇ', + 'ẉ' => 'Ẉ', + 'ẋ' => 'Ẋ', + 'ẍ' => 'Ẍ', + 'ẏ' => 'Ẏ', + 'ẑ' => 'Ẑ', + 'ẓ' => 'Ẓ', + 'ẕ' => 'Ẕ', + 'ẛ' => 'Ṡ', + 'ạ' => 'Ạ', + 'ả' => 'Ả', + 'ấ' => 'Ấ', + 'ầ' => 'Ầ', + 'ẩ' => 'Ẩ', + 'ẫ' => 'Ẫ', + 'ậ' => 'Ậ', + 'ắ' => 'Ắ', + 'ằ' => 'Ằ', + 'ẳ' => 'Ẳ', + 'ẵ' => 'Ẵ', + 'ặ' => 'Ặ', + 'ẹ' => 'Ẹ', + 'ẻ' => 'Ẻ', + 'ẽ' => 'Ẽ', + 'ế' => 'Ế', + 'ề' => 'Ề', + 'ể' => 'Ể', + 'ễ' => 'Ễ', + 'ệ' => 'Ệ', + 'ỉ' => 'Ỉ', + 'ị' => 'Ị', + 'ọ' => 'Ọ', + 'ỏ' => 'Ỏ', + 'ố' => 'Ố', + 'ồ' => 'Ồ', + 'ổ' => 'Ổ', + 'ỗ' => 'Ỗ', + 'ộ' => 'Ộ', + 'ớ' => 'Ớ', + 'ờ' => 'Ờ', + 'ở' => 'Ở', + 'ỡ' => 'Ỡ', + 'ợ' => 'Ợ', + 'ụ' => 'Ụ', + 'ủ' => 'Ủ', + 'ứ' => 'Ứ', + 'ừ' => 'Ừ', + 'ử' => 'Ử', + 'ữ' => 'Ữ', + 'ự' => 'Ự', + 'ỳ' => 'Ỳ', + 'ỵ' => 'Ỵ', + 'ỷ' => 'Ỷ', + 'ỹ' => 'Ỹ', + 'ỻ' => 'Ỻ', + 'ỽ' => 'Ỽ', + 'ỿ' => 'Ỿ', + 'ἀ' => 'Ἀ', + 'ἁ' => 'Ἁ', + 'ἂ' => 'Ἂ', + 'ἃ' => 'Ἃ', + 'ἄ' => 'Ἄ', + 'ἅ' => 'Ἅ', + 'ἆ' => 'Ἆ', + 'ἇ' => 'Ἇ', + 'ἐ' => 'Ἐ', + 'ἑ' => 'Ἑ', + 'ἒ' => 'Ἒ', + 'ἓ' => 'Ἓ', + 'ἔ' => 'Ἔ', + 'ἕ' => 'Ἕ', + 'ἠ' => 'Ἠ', + 'ἡ' => 'Ἡ', + 'ἢ' => 'Ἢ', + 'ἣ' => 'Ἣ', + 'ἤ' => 'Ἤ', + 'ἥ' => 'Ἥ', + 'ἦ' => 'Ἦ', + 'ἧ' => 'Ἧ', + 'ἰ' => 'Ἰ', + 'ἱ' => 'Ἱ', + 'ἲ' => 'Ἲ', + 'ἳ' => 'Ἳ', + 'ἴ' => 'Ἴ', + 'ἵ' => 'Ἵ', + 'ἶ' => 'Ἶ', + 'ἷ' => 'Ἷ', + 'ὀ' => 'Ὀ', + 'ὁ' => 'Ὁ', + 'ὂ' => 'Ὂ', + 'ὃ' => 'Ὃ', + 'ὄ' => 'Ὄ', + 'ὅ' => 'Ὅ', + 'ὑ' => 'Ὑ', + 'ὓ' => 'Ὓ', + 'ὕ' => 'Ὕ', + 'ὗ' => 'Ὗ', + 'ὠ' => 'Ὠ', + 'ὡ' => 'Ὡ', + 'ὢ' => 'Ὢ', + 'ὣ' => 'Ὣ', + 'ὤ' => 'Ὤ', + 'ὥ' => 'Ὥ', + 'ὦ' => 'Ὦ', + 'ὧ' => 'Ὧ', + 'ὰ' => 'Ὰ', + 'ά' => 'Ά', + 'ὲ' => 'Ὲ', + 'έ' => 'Έ', + 'ὴ' => 'Ὴ', + 'ή' => 'Ή', + 'ὶ' => 'Ὶ', + 'ί' => 'Ί', + 'ὸ' => 'Ὸ', + 'ό' => 'Ό', + 'ὺ' => 'Ὺ', + 'ύ' => 'Ύ', + 'ὼ' => 'Ὼ', + 'ώ' => 'Ώ', + 'ᾀ' => 'ᾈ', + 'ᾁ' => 'ᾉ', + 'ᾂ' => 'ᾊ', + 'ᾃ' => 'ᾋ', + 'ᾄ' => 'ᾌ', + 'ᾅ' => 'ᾍ', + 'ᾆ' => 'ᾎ', + 'ᾇ' => 'ᾏ', + 'ᾐ' => 'ᾘ', + 'ᾑ' => 'ᾙ', + 'ᾒ' => 'ᾚ', + 'ᾓ' => 'ᾛ', + 'ᾔ' => 'ᾜ', + 'ᾕ' => 'ᾝ', + 'ᾖ' => 'ᾞ', + 'ᾗ' => 'ᾟ', + 'ᾠ' => 'ᾨ', + 'ᾡ' => 'ᾩ', + 'ᾢ' => 'ᾪ', + 'ᾣ' => 'ᾫ', + 'ᾤ' => 'ᾬ', + 'ᾥ' => 'ᾭ', + 'ᾦ' => 'ᾮ', + 'ᾧ' => 'ᾯ', + 'ᾰ' => 'Ᾰ', + 'ᾱ' => 'Ᾱ', + 'ᾳ' => 'ᾼ', + 'ι' => 'Ι', + 'ῃ' => 'ῌ', + 'ῐ' => 'Ῐ', + 'ῑ' => 'Ῑ', + 'ῠ' => 'Ῠ', + 'ῡ' => 'Ῡ', + 'ῥ' => 'Ῥ', + 'ῳ' => 'ῼ', + 'ⅎ' => 'Ⅎ', + 'ⅰ' => 'Ⅰ', + 'ⅱ' => 'Ⅱ', + 'ⅲ' => 'Ⅲ', + 'ⅳ' => 'Ⅳ', + 'ⅴ' => 'Ⅴ', + 'ⅵ' => 'Ⅵ', + 'ⅶ' => 'Ⅶ', + 'ⅷ' => 'Ⅷ', + 'ⅸ' => 'Ⅸ', + 'ⅹ' => 'Ⅹ', + 'ⅺ' => 'Ⅺ', + 'ⅻ' => 'Ⅻ', + 'ⅼ' => 'Ⅼ', + 'ⅽ' => 'Ⅽ', + 'ⅾ' => 'Ⅾ', + 'ⅿ' => 'Ⅿ', + 'ↄ' => 'Ↄ', + 'ⓐ' => 'Ⓐ', + 'ⓑ' => 'Ⓑ', + 'ⓒ' => 'Ⓒ', + 'ⓓ' => 'Ⓓ', + 'ⓔ' => 'Ⓔ', + 'ⓕ' => 'Ⓕ', + 'ⓖ' => 'Ⓖ', + 'ⓗ' => 'Ⓗ', + 'ⓘ' => 'Ⓘ', + 'ⓙ' => 'Ⓙ', + 'ⓚ' => 'Ⓚ', + 'ⓛ' => 'Ⓛ', + 'ⓜ' => 'Ⓜ', + 'ⓝ' => 'Ⓝ', + 'ⓞ' => 'Ⓞ', + 'ⓟ' => 'Ⓟ', + 'ⓠ' => 'Ⓠ', + 'ⓡ' => 'Ⓡ', + 'ⓢ' => 'Ⓢ', + 'ⓣ' => 'Ⓣ', + 'ⓤ' => 'Ⓤ', + 'ⓥ' => 'Ⓥ', + 'ⓦ' => 'Ⓦ', + 'ⓧ' => 'Ⓧ', + 'ⓨ' => 'Ⓨ', + 'ⓩ' => 'Ⓩ', + 'ⰰ' => 'Ⰰ', + 'ⰱ' => 'Ⰱ', + 'ⰲ' => 'Ⰲ', + 'ⰳ' => 'Ⰳ', + 'ⰴ' => 'Ⰴ', + 'ⰵ' => 'Ⰵ', + 'ⰶ' => 'Ⰶ', + 'ⰷ' => 'Ⰷ', + 'ⰸ' => 'Ⰸ', + 'ⰹ' => 'Ⰹ', + 'ⰺ' => 'Ⰺ', + 'ⰻ' => 'Ⰻ', + 'ⰼ' => 'Ⰼ', + 'ⰽ' => 'Ⰽ', + 'ⰾ' => 'Ⰾ', + 'ⰿ' => 'Ⰿ', + 'ⱀ' => 'Ⱀ', + 'ⱁ' => 'Ⱁ', + 'ⱂ' => 'Ⱂ', + 'ⱃ' => 'Ⱃ', + 'ⱄ' => 'Ⱄ', + 'ⱅ' => 'Ⱅ', + 'ⱆ' => 'Ⱆ', + 'ⱇ' => 'Ⱇ', + 'ⱈ' => 'Ⱈ', + 'ⱉ' => 'Ⱉ', + 'ⱊ' => 'Ⱊ', + 'ⱋ' => 'Ⱋ', + 'ⱌ' => 'Ⱌ', + 'ⱍ' => 'Ⱍ', + 'ⱎ' => 'Ⱎ', + 'ⱏ' => 'Ⱏ', + 'ⱐ' => 'Ⱐ', + 'ⱑ' => 'Ⱑ', + 'ⱒ' => 'Ⱒ', + 'ⱓ' => 'Ⱓ', + 'ⱔ' => 'Ⱔ', + 'ⱕ' => 'Ⱕ', + 'ⱖ' => 'Ⱖ', + 'ⱗ' => 'Ⱗ', + 'ⱘ' => 'Ⱘ', + 'ⱙ' => 'Ⱙ', + 'ⱚ' => 'Ⱚ', + 'ⱛ' => 'Ⱛ', + 'ⱜ' => 'Ⱜ', + 'ⱝ' => 'Ⱝ', + 'ⱞ' => 'Ⱞ', + 'ⱡ' => 'Ⱡ', + 'ⱥ' => 'Ⱥ', + 'ⱦ' => 'Ⱦ', + 'ⱨ' => 'Ⱨ', + 'ⱪ' => 'Ⱪ', + 'ⱬ' => 'Ⱬ', + 'ⱳ' => 'Ⱳ', + 'ⱶ' => 'Ⱶ', + 'ⲁ' => 'Ⲁ', + 'ⲃ' => 'Ⲃ', + 'ⲅ' => 'Ⲅ', + 'ⲇ' => 'Ⲇ', + 'ⲉ' => 'Ⲉ', + 'ⲋ' => 'Ⲋ', + 'ⲍ' => 'Ⲍ', + 'ⲏ' => 'Ⲏ', + 'ⲑ' => 'Ⲑ', + 'ⲓ' => 'Ⲓ', + 'ⲕ' => 'Ⲕ', + 'ⲗ' => 'Ⲗ', + 'ⲙ' => 'Ⲙ', + 'ⲛ' => 'Ⲛ', + 'ⲝ' => 'Ⲝ', + 'ⲟ' => 'Ⲟ', + 'ⲡ' => 'Ⲡ', + 'ⲣ' => 'Ⲣ', + 'ⲥ' => 'Ⲥ', + 'ⲧ' => 'Ⲧ', + 'ⲩ' => 'Ⲩ', + 'ⲫ' => 'Ⲫ', + 'ⲭ' => 'Ⲭ', + 'ⲯ' => 'Ⲯ', + 'ⲱ' => 'Ⲱ', + 'ⲳ' => 'Ⲳ', + 'ⲵ' => 'Ⲵ', + 'ⲷ' => 'Ⲷ', + 'ⲹ' => 'Ⲹ', + 'ⲻ' => 'Ⲻ', + 'ⲽ' => 'Ⲽ', + 'ⲿ' => 'Ⲿ', + 'ⳁ' => 'Ⳁ', + 'ⳃ' => 'Ⳃ', + 'ⳅ' => 'Ⳅ', + 'ⳇ' => 'Ⳇ', + 'ⳉ' => 'Ⳉ', + 'ⳋ' => 'Ⳋ', + 'ⳍ' => 'Ⳍ', + 'ⳏ' => 'Ⳏ', + 'ⳑ' => 'Ⳑ', + 'ⳓ' => 'Ⳓ', + 'ⳕ' => 'Ⳕ', + 'ⳗ' => 'Ⳗ', + 'ⳙ' => 'Ⳙ', + 'ⳛ' => 'Ⳛ', + 'ⳝ' => 'Ⳝ', + 'ⳟ' => 'Ⳟ', + 'ⳡ' => 'Ⳡ', + 'ⳣ' => 'Ⳣ', + 'ⳬ' => 'Ⳬ', + 'ⳮ' => 'Ⳮ', + 'ⳳ' => 'Ⳳ', + 'ⴀ' => 'Ⴀ', + 'ⴁ' => 'Ⴁ', + 'ⴂ' => 'Ⴂ', + 'ⴃ' => 'Ⴃ', + 'ⴄ' => 'Ⴄ', + 'ⴅ' => 'Ⴅ', + 'ⴆ' => 'Ⴆ', + 'ⴇ' => 'Ⴇ', + 'ⴈ' => 'Ⴈ', + 'ⴉ' => 'Ⴉ', + 'ⴊ' => 'Ⴊ', + 'ⴋ' => 'Ⴋ', + 'ⴌ' => 'Ⴌ', + 'ⴍ' => 'Ⴍ', + 'ⴎ' => 'Ⴎ', + 'ⴏ' => 'Ⴏ', + 'ⴐ' => 'Ⴐ', + 'ⴑ' => 'Ⴑ', + 'ⴒ' => 'Ⴒ', + 'ⴓ' => 'Ⴓ', + 'ⴔ' => 'Ⴔ', + 'ⴕ' => 'Ⴕ', + 'ⴖ' => 'Ⴖ', + 'ⴗ' => 'Ⴗ', + 'ⴘ' => 'Ⴘ', + 'ⴙ' => 'Ⴙ', + 'ⴚ' => 'Ⴚ', + 'ⴛ' => 'Ⴛ', + 'ⴜ' => 'Ⴜ', + 'ⴝ' => 'Ⴝ', + 'ⴞ' => 'Ⴞ', + 'ⴟ' => 'Ⴟ', + 'ⴠ' => 'Ⴠ', + 'ⴡ' => 'Ⴡ', + 'ⴢ' => 'Ⴢ', + 'ⴣ' => 'Ⴣ', + 'ⴤ' => 'Ⴤ', + 'ⴥ' => 'Ⴥ', + 'ⴧ' => 'Ⴧ', + 'ⴭ' => 'Ⴭ', + 'ꙁ' => 'Ꙁ', + 'ꙃ' => 'Ꙃ', + 'ꙅ' => 'Ꙅ', + 'ꙇ' => 'Ꙇ', + 'ꙉ' => 'Ꙉ', + 'ꙋ' => 'Ꙋ', + 'ꙍ' => 'Ꙍ', + 'ꙏ' => 'Ꙏ', + 'ꙑ' => 'Ꙑ', + 'ꙓ' => 'Ꙓ', + 'ꙕ' => 'Ꙕ', + 'ꙗ' => 'Ꙗ', + 'ꙙ' => 'Ꙙ', + 'ꙛ' => 'Ꙛ', + 'ꙝ' => 'Ꙝ', + 'ꙟ' => 'Ꙟ', + 'ꙡ' => 'Ꙡ', + 'ꙣ' => 'Ꙣ', + 'ꙥ' => 'Ꙥ', + 'ꙧ' => 'Ꙧ', + 'ꙩ' => 'Ꙩ', + 'ꙫ' => 'Ꙫ', + 'ꙭ' => 'Ꙭ', + 'ꚁ' => 'Ꚁ', + 'ꚃ' => 'Ꚃ', + 'ꚅ' => 'Ꚅ', + 'ꚇ' => 'Ꚇ', + 'ꚉ' => 'Ꚉ', + 'ꚋ' => 'Ꚋ', + 'ꚍ' => 'Ꚍ', + 'ꚏ' => 'Ꚏ', + 'ꚑ' => 'Ꚑ', + 'ꚓ' => 'Ꚓ', + 'ꚕ' => 'Ꚕ', + 'ꚗ' => 'Ꚗ', + 'ꚙ' => 'Ꚙ', + 'ꚛ' => 'Ꚛ', + 'ꜣ' => 'Ꜣ', + 'ꜥ' => 'Ꜥ', + 'ꜧ' => 'Ꜧ', + 'ꜩ' => 'Ꜩ', + 'ꜫ' => 'Ꜫ', + 'ꜭ' => 'Ꜭ', + 'ꜯ' => 'Ꜯ', + 'ꜳ' => 'Ꜳ', + 'ꜵ' => 'Ꜵ', + 'ꜷ' => 'Ꜷ', + 'ꜹ' => 'Ꜹ', + 'ꜻ' => 'Ꜻ', + 'ꜽ' => 'Ꜽ', + 'ꜿ' => 'Ꜿ', + 'ꝁ' => 'Ꝁ', + 'ꝃ' => 'Ꝃ', + 'ꝅ' => 'Ꝅ', + 'ꝇ' => 'Ꝇ', + 'ꝉ' => 'Ꝉ', + 'ꝋ' => 'Ꝋ', + 'ꝍ' => 'Ꝍ', + 'ꝏ' => 'Ꝏ', + 'ꝑ' => 'Ꝑ', + 'ꝓ' => 'Ꝓ', + 'ꝕ' => 'Ꝕ', + 'ꝗ' => 'Ꝗ', + 'ꝙ' => 'Ꝙ', + 'ꝛ' => 'Ꝛ', + 'ꝝ' => 'Ꝝ', + 'ꝟ' => 'Ꝟ', + 'ꝡ' => 'Ꝡ', + 'ꝣ' => 'Ꝣ', + 'ꝥ' => 'Ꝥ', + 'ꝧ' => 'Ꝧ', + 'ꝩ' => 'Ꝩ', + 'ꝫ' => 'Ꝫ', + 'ꝭ' => 'Ꝭ', + 'ꝯ' => 'Ꝯ', + 'ꝺ' => 'Ꝺ', + 'ꝼ' => 'Ꝼ', + 'ꝿ' => 'Ꝿ', + 'ꞁ' => 'Ꞁ', + 'ꞃ' => 'Ꞃ', + 'ꞅ' => 'Ꞅ', + 'ꞇ' => 'Ꞇ', + 'ꞌ' => 'Ꞌ', + 'ꞑ' => 'Ꞑ', + 'ꞓ' => 'Ꞓ', + 'ꞗ' => 'Ꞗ', + 'ꞙ' => 'Ꞙ', + 'ꞛ' => 'Ꞛ', + 'ꞝ' => 'Ꞝ', + 'ꞟ' => 'Ꞟ', + 'ꞡ' => 'Ꞡ', + 'ꞣ' => 'Ꞣ', + 'ꞥ' => 'Ꞥ', + 'ꞧ' => 'Ꞧ', + 'ꞩ' => 'Ꞩ', + 'a' => 'A', + 'b' => 'B', + 'c' => 'C', + 'd' => 'D', + 'e' => 'E', + 'f' => 'F', + 'g' => 'G', + 'h' => 'H', + 'i' => 'I', + 'j' => 'J', + 'k' => 'K', + 'l' => 'L', + 'm' => 'M', + 'n' => 'N', + 'o' => 'O', + 'p' => 'P', + 'q' => 'Q', + 'r' => 'R', + 's' => 'S', + 't' => 'T', + 'u' => 'U', + 'v' => 'V', + 'w' => 'W', + 'x' => 'X', + 'y' => 'Y', + 'z' => 'Z', + '𐐨' => '𐐀', + '𐐩' => '𐐁', + '𐐪' => '𐐂', + '𐐫' => '𐐃', + '𐐬' => '𐐄', + '𐐭' => '𐐅', + '𐐮' => '𐐆', + '𐐯' => '𐐇', + '𐐰' => '𐐈', + '𐐱' => '𐐉', + '𐐲' => '𐐊', + '𐐳' => '𐐋', + '𐐴' => '𐐌', + '𐐵' => '𐐍', + '𐐶' => '𐐎', + '𐐷' => '𐐏', + '𐐸' => '𐐐', + '𐐹' => '𐐑', + '𐐺' => '𐐒', + '𐐻' => '𐐓', + '𐐼' => '𐐔', + '𐐽' => '𐐕', + '𐐾' => '𐐖', + '𐐿' => '𐐗', + '𐑀' => '𐐘', + '𐑁' => '𐐙', + '𐑂' => '𐐚', + '𐑃' => '𐐛', + '𐑄' => '𐐜', + '𐑅' => '𐐝', + '𐑆' => '𐐞', + '𐑇' => '𐐟', + '𐑈' => '𐐠', + '𐑉' => '𐐡', + '𐑊' => '𐐢', + '𐑋' => '𐐣', + '𐑌' => '𐐤', + '𐑍' => '𐐥', + '𐑎' => '𐐦', + '𐑏' => '𐐧', + '𑣀' => '𑢠', + '𑣁' => '𑢡', + '𑣂' => '𑢢', + '𑣃' => '𑢣', + '𑣄' => '𑢤', + '𑣅' => '𑢥', + '𑣆' => '𑢦', + '𑣇' => '𑢧', + '𑣈' => '𑢨', + '𑣉' => '𑢩', + '𑣊' => '𑢪', + '𑣋' => '𑢫', + '𑣌' => '𑢬', + '𑣍' => '𑢭', + '𑣎' => '𑢮', + '𑣏' => '𑢯', + '𑣐' => '𑢰', + '𑣑' => '𑢱', + '𑣒' => '𑢲', + '𑣓' => '𑢳', + '𑣔' => '𑢴', + '𑣕' => '𑢵', + '𑣖' => '𑢶', + '𑣗' => '𑢷', + '𑣘' => '𑢸', + '𑣙' => '𑢹', + '𑣚' => '𑢺', + '𑣛' => '𑢻', + '𑣜' => '𑢼', + '𑣝' => '𑢽', + '𑣞' => '𑢾', + '𑣟' => '𑢿', +); diff --git a/vendor/symfony/polyfill-mbstring/bootstrap.php b/vendor/symfony/polyfill-mbstring/bootstrap.php new file mode 100644 index 0000000..204a41b --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/bootstrap.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Mbstring as p; + +if (!function_exists('mb_strlen')) { + define('MB_CASE_UPPER', 0); + define('MB_CASE_LOWER', 1); + define('MB_CASE_TITLE', 2); + + function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); } + function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); } + function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); } + function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); } + function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); } + function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); } + function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); } + function mb_language($lang = null) { return p\Mbstring::mb_language($lang); } + function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); } + function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); } + function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); } + function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); } + function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); } + function mb_parse_str($s, &$result = array()) { parse_str($s, $result); } + function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); } + function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); } + function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); } + function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); } + function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); } + function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); } + function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); } + function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); } + function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); } + function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); } + function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); } + function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); } + function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); } + function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); } + function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); } + function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); } + function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); } + function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); } + function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); } + function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) { return p\Mbstring::mb_convert_variables($toEncoding, $fromEncoding, $a, $b, $c, $d, $e, $f); } +} +if (!function_exists('mb_chr')) { + function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); } + function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); } + function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); } +} + +if (!function_exists('mb_str_split')) { + function mb_str_split($string, $split_length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $split_length, $encoding); } +} diff --git a/vendor/symfony/polyfill-mbstring/composer.json b/vendor/symfony/polyfill-mbstring/composer.json new file mode 100644 index 0000000..c968074 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/composer.json @@ -0,0 +1,34 @@ +{ + "name": "symfony/polyfill-mbstring", + "type": "library", + "description": "Symfony polyfill for the Mbstring extension", + "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" }, + "files": [ "bootstrap.php" ] + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + } +} diff --git a/vendor/symfony/polyfill-php72/LICENSE b/vendor/symfony/polyfill-php72/LICENSE new file mode 100644 index 0000000..4cd8bdd --- /dev/null +++ b/vendor/symfony/polyfill-php72/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/polyfill-php72/Php72.php b/vendor/symfony/polyfill-php72/Php72.php new file mode 100644 index 0000000..d531e84 --- /dev/null +++ b/vendor/symfony/polyfill-php72/Php72.php @@ -0,0 +1,216 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php72; + +/** + * @author Nicolas Grekas + * @author Dariusz Rumiński + * + * @internal + */ +final class Php72 +{ + private static $hashMask; + + public static function utf8_encode($s) + { + $s .= $s; + $len = \strlen($s); + + for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) { + switch (true) { + case $s[$i] < "\x80": $s[$j] = $s[$i]; break; + case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break; + default: $s[$j] = "\xC3"; $s[++$j] = \chr(\ord($s[$i]) - 64); break; + } + } + + return substr($s, 0, $j); + } + + public static function utf8_decode($s) + { + $s = (string) $s; + $len = \strlen($s); + + for ($i = 0, $j = 0; $i < $len; ++$i, ++$j) { + switch ($s[$i] & "\xF0") { + case "\xC0": + case "\xD0": + $c = (\ord($s[$i] & "\x1F") << 6) | \ord($s[++$i] & "\x3F"); + $s[$j] = $c < 256 ? \chr($c) : '?'; + break; + + case "\xF0": + ++$i; + // no break + + case "\xE0": + $s[$j] = '?'; + $i += 2; + break; + + default: + $s[$j] = $s[$i]; + } + } + + return substr($s, 0, $j); + } + + public static function php_os_family() + { + if ('\\' === \DIRECTORY_SEPARATOR) { + return 'Windows'; + } + + $map = array( + 'Darwin' => 'Darwin', + 'DragonFly' => 'BSD', + 'FreeBSD' => 'BSD', + 'NetBSD' => 'BSD', + 'OpenBSD' => 'BSD', + 'Linux' => 'Linux', + 'SunOS' => 'Solaris', + ); + + return isset($map[PHP_OS]) ? $map[PHP_OS] : 'Unknown'; + } + + public static function spl_object_id($object) + { + if (null === self::$hashMask) { + self::initHashMask(); + } + if (null === $hash = spl_object_hash($object)) { + return; + } + + return self::$hashMask ^ hexdec(substr($hash, 16 - \PHP_INT_SIZE, \PHP_INT_SIZE)); + } + + public static function sapi_windows_vt100_support($stream, $enable = null) + { + if (!\is_resource($stream)) { + trigger_error('sapi_windows_vt100_support() expects parameter 1 to be resource, '.\gettype($stream).' given', E_USER_WARNING); + + return false; + } + + $meta = stream_get_meta_data($stream); + + if ('STDIO' !== $meta['stream_type']) { + trigger_error('sapi_windows_vt100_support() was not able to analyze the specified stream', E_USER_WARNING); + + return false; + } + + // We cannot actually disable vt100 support if it is set + if (false === $enable || !self::stream_isatty($stream)) { + return false; + } + + // The native function does not apply to stdin + $meta = array_map('strtolower', $meta); + $stdin = 'php://stdin' === $meta['uri'] || 'php://fd/0' === $meta['uri']; + + return !$stdin + && (false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM') + || 'Hyper' === getenv('TERM_PROGRAM')); + } + + public static function stream_isatty($stream) + { + if (!\is_resource($stream)) { + trigger_error('stream_isatty() expects parameter 1 to be resource, '.\gettype($stream).' given', E_USER_WARNING); + + return false; + } + + if ('\\' === \DIRECTORY_SEPARATOR) { + $stat = @fstat($stream); + // Check if formatted mode is S_IFCHR + return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; + } + + return \function_exists('posix_isatty') && @posix_isatty($stream); + } + + private static function initHashMask() + { + $obj = (object) array(); + self::$hashMask = -1; + + // check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below + $obFuncs = array('ob_clean', 'ob_end_clean', 'ob_flush', 'ob_end_flush', 'ob_get_contents', 'ob_get_flush'); + foreach (debug_backtrace(\PHP_VERSION_ID >= 50400 ? DEBUG_BACKTRACE_IGNORE_ARGS : false) as $frame) { + if (isset($frame['function'][0]) && !isset($frame['class']) && 'o' === $frame['function'][0] && \in_array($frame['function'], $obFuncs)) { + $frame['line'] = 0; + break; + } + } + if (!empty($frame['line'])) { + ob_start(); + debug_zval_dump($obj); + self::$hashMask = (int) substr(ob_get_clean(), 17); + } + + self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - \PHP_INT_SIZE, \PHP_INT_SIZE)); + } + + public static function mb_chr($code, $encoding = null) + { + if (0x80 > $code %= 0x200000) { + $s = \chr($code); + } elseif (0x800 > $code) { + $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); + } elseif (0x10000 > $code) { + $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } else { + $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } + + if ('UTF-8' !== $encoding) { + $s = mb_convert_encoding($s, $encoding, 'UTF-8'); + } + + return $s; + } + + public static function mb_ord($s, $encoding = null) + { + if (null == $encoding) { + $s = mb_convert_encoding($s, 'UTF-8'); + } elseif ('UTF-8' !== $encoding) { + $s = mb_convert_encoding($s, 'UTF-8', $encoding); + } + + if (1 === \strlen($s)) { + return \ord($s); + } + + $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; + if (0xF0 <= $code) { + return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; + } + if (0xE0 <= $code) { + return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; + } + if (0xC0 <= $code) { + return (($code - 0xC0) << 6) + $s[2] - 0x80; + } + + return $code; + } +} diff --git a/vendor/symfony/polyfill-php72/README.md b/vendor/symfony/polyfill-php72/README.md new file mode 100644 index 0000000..82c45f7 --- /dev/null +++ b/vendor/symfony/polyfill-php72/README.md @@ -0,0 +1,27 @@ +Symfony Polyfill / Php72 +======================== + +This component provides functions added to PHP 7.2 core: + +- [`spl_object_id`](https://php.net/spl_object_id) +- [`stream_isatty`](https://php.net/stream_isatty) + +On Windows only: + +- [`sapi_windows_vt100_support`](https://php.net/sapi_windows_vt100_support) + +Moved to core since 7.2 (was in the optional XML extension earlier): + +- [`utf8_encode`](https://php.net/utf8_encode) +- [`utf8_decode`](https://php.net/utf8_decode) + +Also, it provides a constant added to PHP 7.2: +- [`PHP_OS_FAMILY`](http://php.net/manual/en/reserved.constants.php#constant.php-os-family) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-php72/bootstrap.php b/vendor/symfony/polyfill-php72/bootstrap.php new file mode 100644 index 0000000..519056d --- /dev/null +++ b/vendor/symfony/polyfill-php72/bootstrap.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php72 as p; + +if (PHP_VERSION_ID < 70200) { + if ('\\' === DIRECTORY_SEPARATOR && !function_exists('sapi_windows_vt100_support')) { + function sapi_windows_vt100_support($stream, $enable = null) { return p\Php72::sapi_windows_vt100_support($stream, $enable); } + } + if (!function_exists('stream_isatty')) { + function stream_isatty($stream) { return p\Php72::stream_isatty($stream); } + } + if (!function_exists('utf8_encode')) { + function utf8_encode($s) { return p\Php72::utf8_encode($s); } + function utf8_decode($s) { return p\Php72::utf8_decode($s); } + } + if (!function_exists('spl_object_id')) { + function spl_object_id($s) { return p\Php72::spl_object_id($s); } + } + if (!defined('PHP_OS_FAMILY')) { + define('PHP_OS_FAMILY', p\Php72::php_os_family()); + } + if (!function_exists('mb_chr')) { + function mb_ord($s, $enc = null) { return p\Php72::mb_ord($s, $enc); } + function mb_chr($code, $enc = null) { return p\Php72::mb_chr($code, $enc); } + function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); } + } +} diff --git a/vendor/symfony/polyfill-php72/composer.json b/vendor/symfony/polyfill-php72/composer.json new file mode 100644 index 0000000..0d37167 --- /dev/null +++ b/vendor/symfony/polyfill-php72/composer.json @@ -0,0 +1,31 @@ +{ + "name": "symfony/polyfill-php72", + "type": "library", + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php72\\": "" }, + "files": [ "bootstrap.php" ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + } +} diff --git a/vendor/symfony/polyfill-php73/LICENSE b/vendor/symfony/polyfill-php73/LICENSE new file mode 100644 index 0000000..3f853aa --- /dev/null +++ b/vendor/symfony/polyfill-php73/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/polyfill-php73/Php73.php b/vendor/symfony/polyfill-php73/Php73.php new file mode 100644 index 0000000..7c99d19 --- /dev/null +++ b/vendor/symfony/polyfill-php73/Php73.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php73; + +/** + * @author Gabriel Caruso + * @author Ion Bazan + * + * @internal + */ +final class Php73 +{ + public static $startAt = 1533462603; + + /** + * @param bool $asNum + * + * @return array|float|int + */ + public static function hrtime($asNum = false) + { + $ns = microtime(false); + $s = substr($ns, 11) - self::$startAt; + $ns = 1E9 * (float) $ns; + + if ($asNum) { + $ns += $s * 1E9; + + return \PHP_INT_SIZE === 4 ? $ns : (int) $ns; + } + + return array($s, (int) $ns); + } +} diff --git a/vendor/symfony/polyfill-php73/README.md b/vendor/symfony/polyfill-php73/README.md new file mode 100644 index 0000000..b3ebbce --- /dev/null +++ b/vendor/symfony/polyfill-php73/README.md @@ -0,0 +1,18 @@ +Symfony Polyfill / Php73 +======================== + +This component provides functions added to PHP 7.3 core: + +- [`array_key_first`](https://php.net/array_key_first) +- [`array_key_last`](https://php.net/array_key_last) +- [`hrtime`](https://php.net/function.hrtime) +- [`is_countable`](https://php.net/is_countable) +- [`JsonException`](https://php.net/JsonException) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php b/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php new file mode 100644 index 0000000..673d100 --- /dev/null +++ b/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +class JsonException extends Exception +{ +} diff --git a/vendor/symfony/polyfill-php73/bootstrap.php b/vendor/symfony/polyfill-php73/bootstrap.php new file mode 100644 index 0000000..4c3f44f --- /dev/null +++ b/vendor/symfony/polyfill-php73/bootstrap.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php73 as p; + +if (PHP_VERSION_ID < 70300) { + if (!function_exists('is_countable')) { + function is_countable($var) { return is_array($var) || $var instanceof Countable || $var instanceof ResourceBundle || $var instanceof SimpleXmlElement; } + } + + if (!function_exists('hrtime')) { + require_once __DIR__.'/Php73.php'; + p\Php73::$startAt = (int) microtime(true); + function hrtime($asNum = false) { return p\Php73::hrtime($asNum); } + } + + if (!function_exists('array_key_first')) { + function array_key_first(array $array) { foreach ($array as $key => $value) { return $key; } } + } + + if (!function_exists('array_key_last')) { + function array_key_last(array $array) { end($array); return key($array); } + } +} diff --git a/vendor/symfony/polyfill-php73/composer.json b/vendor/symfony/polyfill-php73/composer.json new file mode 100644 index 0000000..cffa32f --- /dev/null +++ b/vendor/symfony/polyfill-php73/composer.json @@ -0,0 +1,32 @@ +{ + "name": "symfony/polyfill-php73", + "type": "library", + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php73\\": "" }, + "files": [ "bootstrap.php" ], + "classmap": [ "Resources/stubs" ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + } +} diff --git a/vendor/symfony/routing/.gitattributes b/vendor/symfony/routing/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/routing/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/routing/Annotation/Route.php b/vendor/symfony/routing/Annotation/Route.php new file mode 100644 index 0000000..4d5f618 --- /dev/null +++ b/vendor/symfony/routing/Annotation/Route.php @@ -0,0 +1,182 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Annotation; + +/** + * Annotation class for @Route(). + * + * @Annotation + * @Target({"CLASS", "METHOD"}) + * + * @author Fabien Potencier + */ +class Route +{ + private $path; + private $localizedPaths = []; + private $name; + private $requirements = []; + private $options = []; + private $defaults = []; + private $host; + private $methods = []; + private $schemes = []; + private $condition; + private $locale; + private $format; + private $utf8; + + /** + * @param array $data An array of key/value parameters + * + * @throws \BadMethodCallException + */ + public function __construct(array $data) + { + if (isset($data['localized_paths'])) { + throw new \BadMethodCallException(sprintf('Unknown property "localized_paths" on annotation "%s".', \get_class($this))); + } + + if (isset($data['value'])) { + $data[\is_array($data['value']) ? 'localized_paths' : 'path'] = $data['value']; + unset($data['value']); + } + + if (isset($data['path']) && \is_array($data['path'])) { + $data['localized_paths'] = $data['path']; + unset($data['path']); + } + + if (isset($data['locale'])) { + $data['defaults']['_locale'] = $data['locale']; + unset($data['locale']); + } + + if (isset($data['format'])) { + $data['defaults']['_format'] = $data['format']; + unset($data['format']); + } + + if (isset($data['utf8'])) { + $data['options']['utf8'] = filter_var($data['utf8'], FILTER_VALIDATE_BOOLEAN) ?: false; + unset($data['utf8']); + } + + foreach ($data as $key => $value) { + $method = 'set'.str_replace('_', '', $key); + if (!method_exists($this, $method)) { + throw new \BadMethodCallException(sprintf('Unknown property "%s" on annotation "%s".', $key, \get_class($this))); + } + $this->$method($value); + } + } + + public function setPath($path) + { + $this->path = $path; + } + + public function getPath() + { + return $this->path; + } + + public function setLocalizedPaths(array $localizedPaths) + { + $this->localizedPaths = $localizedPaths; + } + + public function getLocalizedPaths(): array + { + return $this->localizedPaths; + } + + public function setHost($pattern) + { + $this->host = $pattern; + } + + public function getHost() + { + return $this->host; + } + + public function setName($name) + { + $this->name = $name; + } + + public function getName() + { + return $this->name; + } + + public function setRequirements($requirements) + { + $this->requirements = $requirements; + } + + public function getRequirements() + { + return $this->requirements; + } + + public function setOptions($options) + { + $this->options = $options; + } + + public function getOptions() + { + return $this->options; + } + + public function setDefaults($defaults) + { + $this->defaults = $defaults; + } + + public function getDefaults() + { + return $this->defaults; + } + + public function setSchemes($schemes) + { + $this->schemes = \is_array($schemes) ? $schemes : [$schemes]; + } + + public function getSchemes() + { + return $this->schemes; + } + + public function setMethods($methods) + { + $this->methods = \is_array($methods) ? $methods : [$methods]; + } + + public function getMethods() + { + return $this->methods; + } + + public function setCondition($condition) + { + $this->condition = $condition; + } + + public function getCondition() + { + return $this->condition; + } +} diff --git a/vendor/symfony/routing/CHANGELOG.md b/vendor/symfony/routing/CHANGELOG.md new file mode 100644 index 0000000..f304a12 --- /dev/null +++ b/vendor/symfony/routing/CHANGELOG.md @@ -0,0 +1,268 @@ +CHANGELOG +========= + +5.0.0 +----- + + * removed `PhpGeneratorDumper` and `PhpMatcherDumper` + * removed `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options + * `Serializable` implementing methods for `Route` and `CompiledRoute` are final + * removed referencing service route loaders with a single colon + * Removed `ServiceRouterLoader` and `ObjectRouteLoader`. + +4.4.0 +----- + + * Deprecated `ServiceRouterLoader` in favor of `ContainerLoader`. + * Deprecated `ObjectRouteLoader` in favor of `ObjectLoader`. + * Added a way to exclude patterns of resources from being imported by the `import()` method + +4.3.0 +----- + + * added `CompiledUrlMatcher` and `CompiledUrlMatcherDumper` + * added `CompiledUrlGenerator` and `CompiledUrlGeneratorDumper` + * deprecated `PhpGeneratorDumper` and `PhpMatcherDumper` + * deprecated `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options + * `Serializable` implementing methods for `Route` and `CompiledRoute` are marked as `@internal` and `@final`. + Instead of overwriting them, use `__serialize` and `__unserialize` as extension points which are forward compatible + with the new serialization methods in PHP 7.4. + * exposed `utf8` Route option, defaults "locale" and "format" in configuration loaders and configurators + * added support for invokable service route loaders + +4.2.0 +----- + + * added fallback to cultureless locale for internationalized routes + +4.0.0 +----- + + * dropped support for using UTF-8 route patterns without using the `utf8` option + * dropped support for using UTF-8 route requirements without using the `utf8` option + +3.4.0 +----- + + * Added `NoConfigurationException`. + * Added the possibility to define a prefix for all routes of a controller via @Route(name="prefix_") + * Added support for prioritized routing loaders. + * Add matched and default parameters to redirect responses + * Added support for a `controller` keyword for configuring route controllers in YAML and XML configurations. + +3.3.0 +----- + + * [DEPRECATION] Class parameters have been deprecated and will be removed in 4.0. + * router.options.generator_class + * router.options.generator_base_class + * router.options.generator_dumper_class + * router.options.matcher_class + * router.options.matcher_base_class + * router.options.matcher_dumper_class + * router.options.matcher.cache_class + * router.options.generator.cache_class + +3.2.0 +----- + + * Added support for `bool`, `int`, `float`, `string`, `list` and `map` defaults in XML configurations. + * Added support for UTF-8 requirements + +2.8.0 +----- + + * allowed specifying a directory to recursively load all routing configuration files it contains + * Added ObjectRouteLoader and ServiceRouteLoader that allow routes to be loaded + by calling a method on an object/service. + * [DEPRECATION] Deprecated the hardcoded value for the `$referenceType` argument of the `UrlGeneratorInterface::generate` method. + Use the constants defined in the `UrlGeneratorInterface` instead. + + Before: + + ```php + $router->generate('blog_show', ['slug' => 'my-blog-post'], true); + ``` + + After: + + ```php + use Symfony\Component\Routing\Generator\UrlGeneratorInterface; + + $router->generate('blog_show', ['slug' => 'my-blog-post'], UrlGeneratorInterface::ABSOLUTE_URL); + ``` + +2.5.0 +----- + + * [DEPRECATION] The `ApacheMatcherDumper` and `ApacheUrlMatcher` were deprecated and + will be removed in Symfony 3.0, since the performance gains were minimal and + it's hard to replicate the behavior of PHP implementation. + +2.3.0 +----- + + * added RequestContext::getQueryString() + +2.2.0 +----- + + * [DEPRECATION] Several route settings have been renamed (the old ones will be removed in 3.0): + + * The `pattern` setting for a route has been deprecated in favor of `path` + * The `_scheme` and `_method` requirements have been moved to the `schemes` and `methods` settings + + Before: + + ```yaml + article_edit: + pattern: /article/{id} + requirements: { '_method': 'POST|PUT', '_scheme': 'https', 'id': '\d+' } + ``` + + ```xml + + POST|PUT + https + \d+ + + ``` + + ```php + $route = new Route(); + $route->setPattern('/article/{id}'); + $route->setRequirement('_method', 'POST|PUT'); + $route->setRequirement('_scheme', 'https'); + ``` + + After: + + ```yaml + article_edit: + path: /article/{id} + methods: [POST, PUT] + schemes: https + requirements: { 'id': '\d+' } + ``` + + ```xml + + \d+ + + ``` + + ```php + $route = new Route(); + $route->setPath('/article/{id}'); + $route->setMethods(['POST', 'PUT']); + $route->setSchemes('https'); + ``` + + * [BC BREAK] RouteCollection does not behave like a tree structure anymore but as + a flat array of Routes. So when using PHP to build the RouteCollection, you must + make sure to add routes to the sub-collection before adding it to the parent + collection (this is not relevant when using YAML or XML for Route definitions). + + Before: + + ```php + $rootCollection = new RouteCollection(); + $subCollection = new RouteCollection(); + $rootCollection->addCollection($subCollection); + $subCollection->add('foo', new Route('/foo')); + ``` + + After: + + ```php + $rootCollection = new RouteCollection(); + $subCollection = new RouteCollection(); + $subCollection->add('foo', new Route('/foo')); + $rootCollection->addCollection($subCollection); + ``` + + Also one must call `addCollection` from the bottom to the top hierarchy. + So the correct sequence is the following (and not the reverse): + + ```php + $childCollection->addCollection($grandchildCollection); + $rootCollection->addCollection($childCollection); + ``` + + * [DEPRECATION] The methods `RouteCollection::getParent()` and `RouteCollection::getRoot()` + have been deprecated and will be removed in Symfony 2.3. + * [BC BREAK] Misusing the `RouteCollection::addPrefix` method to add defaults, requirements + or options without adding a prefix is not supported anymore. So if you called `addPrefix` + with an empty prefix or `/` only (both have no relevance), like + `addPrefix('', $defaultsArray, $requirementsArray, $optionsArray)` + you need to use the new dedicated methods `addDefaults($defaultsArray)`, + `addRequirements($requirementsArray)` or `addOptions($optionsArray)` instead. + * [DEPRECATION] The `$options` parameter to `RouteCollection::addPrefix()` has been deprecated + because adding options has nothing to do with adding a path prefix. If you want to add options + to all child routes of a RouteCollection, you can use `addOptions()`. + * [DEPRECATION] The method `RouteCollection::getPrefix()` has been deprecated + because it suggested that all routes in the collection would have this prefix, which is + not necessarily true. On top of that, since there is no tree structure anymore, this method + is also useless. Don't worry about performance, prefix optimization for matching is still done + in the dumper, which was also improved in 2.2.0 to find even more grouping possibilities. + * [DEPRECATION] `RouteCollection::addCollection(RouteCollection $collection)` should now only be + used with a single parameter. The other params `$prefix`, `$default`, `$requirements` and `$options` + will still work, but have been deprecated. The `addPrefix` method should be used for this + use-case instead. + Before: `$parentCollection->addCollection($collection, '/prefix', [...], [...])` + After: + ```php + $collection->addPrefix('/prefix', [...], [...]); + $parentCollection->addCollection($collection); + ``` + * added support for the method default argument values when defining a @Route + * Adjacent placeholders without separator work now, e.g. `/{x}{y}{z}.{_format}`. + * Characters that function as separator between placeholders are now whitelisted + to fix routes with normal text around a variable, e.g. `/prefix{var}suffix`. + * [BC BREAK] The default requirement of a variable has been changed slightly. + Previously it disallowed the previous and the next char around a variable. Now + it disallows the slash (`/`) and the next char. Using the previous char added + no value and was problematic because the route `/index.{_format}` would be + matched by `/index.ht/ml`. + * The default requirement now uses possessive quantifiers when possible which + improves matching performance by up to 20% because it prevents backtracking + when it's not needed. + * The ConfigurableRequirementsInterface can now also be used to disable the requirements + check on URL generation completely by calling `setStrictRequirements(null)`. It + improves performance in production environment as you should know that params always + pass the requirements (otherwise it would break your link anyway). + * There is no restriction on the route name anymore. So non-alphanumeric characters + are now also allowed. + * [BC BREAK] `RouteCompilerInterface::compile(Route $route)` was made static + (only relevant if you implemented your own RouteCompiler). + * Added possibility to generate relative paths and network paths in the UrlGenerator, e.g. + "../parent-file" and "//example.com/dir/file". The third parameter in + `UrlGeneratorInterface::generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)` + now accepts more values and you should use the constants defined in `UrlGeneratorInterface` for + claritiy. The old method calls with a Boolean parameter will continue to work because they + equal the signature using the constants. + +2.1.0 +----- + + * added RequestMatcherInterface + * added RequestContext::fromRequest() + * the UrlMatcher does not throw a \LogicException anymore when the required + scheme is not the current one + * added TraceableUrlMatcher + * added the possibility to define options, default values and requirements + for placeholders in prefix, including imported routes + * added RouterInterface::getRouteCollection + * [BC BREAK] the UrlMatcher urldecodes the route parameters only once, they + were decoded twice before. Note that the `urldecode()` calls have been + changed for a single `rawurldecode()` in order to support `+` for input + paths. + * added RouteCollection::getRoot method to retrieve the root of a + RouteCollection tree + * [BC BREAK] made RouteCollection::setParent private which could not have + been used anyway without creating inconsistencies + * [BC BREAK] RouteCollection::remove also removes a route from parent + collections (not only from its children) + * added ConfigurableRequirementsInterface that allows to disable exceptions + (and generate empty URLs instead) when generating a route with an invalid + parameter value diff --git a/vendor/symfony/routing/CompiledRoute.php b/vendor/symfony/routing/CompiledRoute.php new file mode 100644 index 0000000..9ffd1b5 --- /dev/null +++ b/vendor/symfony/routing/CompiledRoute.php @@ -0,0 +1,173 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +/** + * CompiledRoutes are returned by the RouteCompiler class. + * + * @author Fabien Potencier + */ +class CompiledRoute implements \Serializable +{ + private $variables; + private $tokens; + private $staticPrefix; + private $regex; + private $pathVariables; + private $hostVariables; + private $hostRegex; + private $hostTokens; + + /** + * @param string $staticPrefix The static prefix of the compiled route + * @param string $regex The regular expression to use to match this route + * @param array $tokens An array of tokens to use to generate URL for this route + * @param array $pathVariables An array of path variables + * @param string|null $hostRegex Host regex + * @param array $hostTokens Host tokens + * @param array $hostVariables An array of host variables + * @param array $variables An array of variables (variables defined in the path and in the host patterns) + */ + public function __construct(string $staticPrefix, string $regex, array $tokens, array $pathVariables, string $hostRegex = null, array $hostTokens = [], array $hostVariables = [], array $variables = []) + { + $this->staticPrefix = $staticPrefix; + $this->regex = $regex; + $this->tokens = $tokens; + $this->pathVariables = $pathVariables; + $this->hostRegex = $hostRegex; + $this->hostTokens = $hostTokens; + $this->hostVariables = $hostVariables; + $this->variables = $variables; + } + + public function __serialize(): array + { + return [ + 'vars' => $this->variables, + 'path_prefix' => $this->staticPrefix, + 'path_regex' => $this->regex, + 'path_tokens' => $this->tokens, + 'path_vars' => $this->pathVariables, + 'host_regex' => $this->hostRegex, + 'host_tokens' => $this->hostTokens, + 'host_vars' => $this->hostVariables, + ]; + } + + /** + * @internal + */ + final public function serialize(): string + { + return serialize($this->__serialize()); + } + + public function __unserialize(array $data): void + { + $this->variables = $data['vars']; + $this->staticPrefix = $data['path_prefix']; + $this->regex = $data['path_regex']; + $this->tokens = $data['path_tokens']; + $this->pathVariables = $data['path_vars']; + $this->hostRegex = $data['host_regex']; + $this->hostTokens = $data['host_tokens']; + $this->hostVariables = $data['host_vars']; + } + + /** + * @internal + */ + final public function unserialize($serialized) + { + $this->__unserialize(unserialize($serialized, ['allowed_classes' => false])); + } + + /** + * Returns the static prefix. + * + * @return string The static prefix + */ + public function getStaticPrefix() + { + return $this->staticPrefix; + } + + /** + * Returns the regex. + * + * @return string The regex + */ + public function getRegex() + { + return $this->regex; + } + + /** + * Returns the host regex. + * + * @return string|null The host regex or null + */ + public function getHostRegex() + { + return $this->hostRegex; + } + + /** + * Returns the tokens. + * + * @return array The tokens + */ + public function getTokens() + { + return $this->tokens; + } + + /** + * Returns the host tokens. + * + * @return array The tokens + */ + public function getHostTokens() + { + return $this->hostTokens; + } + + /** + * Returns the variables. + * + * @return array The variables + */ + public function getVariables() + { + return $this->variables; + } + + /** + * Returns the path variables. + * + * @return array The variables + */ + public function getPathVariables() + { + return $this->pathVariables; + } + + /** + * Returns the host variables. + * + * @return array The variables + */ + public function getHostVariables() + { + return $this->hostVariables; + } +} diff --git a/vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php b/vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php new file mode 100644 index 0000000..7068825 --- /dev/null +++ b/vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Adds tagged routing.loader services to routing.resolver service. + * + * @author Fabien Potencier + */ +class RoutingResolverPass implements CompilerPassInterface +{ + use PriorityTaggedServiceTrait; + + private $resolverServiceId; + private $loaderTag; + + public function __construct(string $resolverServiceId = 'routing.resolver', string $loaderTag = 'routing.loader') + { + $this->resolverServiceId = $resolverServiceId; + $this->loaderTag = $loaderTag; + } + + public function process(ContainerBuilder $container) + { + if (false === $container->hasDefinition($this->resolverServiceId)) { + return; + } + + $definition = $container->getDefinition($this->resolverServiceId); + + foreach ($this->findAndSortTaggedServices($this->loaderTag, $container) as $id) { + $definition->addMethodCall('addLoader', [new Reference($id)]); + } + } +} diff --git a/vendor/symfony/routing/Exception/ExceptionInterface.php b/vendor/symfony/routing/Exception/ExceptionInterface.php new file mode 100644 index 0000000..22e72b1 --- /dev/null +++ b/vendor/symfony/routing/Exception/ExceptionInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * ExceptionInterface. + * + * @author Alexandre Salomé + */ +interface ExceptionInterface extends \Throwable +{ +} diff --git a/vendor/symfony/routing/Exception/InvalidParameterException.php b/vendor/symfony/routing/Exception/InvalidParameterException.php new file mode 100644 index 0000000..94d841f --- /dev/null +++ b/vendor/symfony/routing/Exception/InvalidParameterException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * Exception thrown when a parameter is not valid. + * + * @author Alexandre Salomé + */ +class InvalidParameterException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/routing/Exception/MethodNotAllowedException.php b/vendor/symfony/routing/Exception/MethodNotAllowedException.php new file mode 100644 index 0000000..b897081 --- /dev/null +++ b/vendor/symfony/routing/Exception/MethodNotAllowedException.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * The resource was found but the request method is not allowed. + * + * This exception should trigger an HTTP 405 response in your application code. + * + * @author Kris Wallsmith + */ +class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface +{ + protected $allowedMethods = []; + + public function __construct(array $allowedMethods, string $message = null, int $code = 0, \Throwable $previous = null) + { + $this->allowedMethods = array_map('strtoupper', $allowedMethods); + + parent::__construct($message, $code, $previous); + } + + /** + * Gets the allowed HTTP methods. + * + * @return array + */ + public function getAllowedMethods() + { + return $this->allowedMethods; + } +} diff --git a/vendor/symfony/routing/Exception/MissingMandatoryParametersException.php b/vendor/symfony/routing/Exception/MissingMandatoryParametersException.php new file mode 100644 index 0000000..57f3a40 --- /dev/null +++ b/vendor/symfony/routing/Exception/MissingMandatoryParametersException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * Exception thrown when a route cannot be generated because of missing + * mandatory parameters. + * + * @author Alexandre Salomé + */ +class MissingMandatoryParametersException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/routing/Exception/NoConfigurationException.php b/vendor/symfony/routing/Exception/NoConfigurationException.php new file mode 100644 index 0000000..333bc74 --- /dev/null +++ b/vendor/symfony/routing/Exception/NoConfigurationException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * Exception thrown when no routes are configured. + * + * @author Yonel Ceruto + */ +class NoConfigurationException extends ResourceNotFoundException +{ +} diff --git a/vendor/symfony/routing/Exception/ResourceNotFoundException.php b/vendor/symfony/routing/Exception/ResourceNotFoundException.php new file mode 100644 index 0000000..ccbca15 --- /dev/null +++ b/vendor/symfony/routing/Exception/ResourceNotFoundException.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * The resource was not found. + * + * This exception should trigger an HTTP 404 response in your application code. + * + * @author Kris Wallsmith + */ +class ResourceNotFoundException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/routing/Exception/RouteNotFoundException.php b/vendor/symfony/routing/Exception/RouteNotFoundException.php new file mode 100644 index 0000000..24ab0b4 --- /dev/null +++ b/vendor/symfony/routing/Exception/RouteNotFoundException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * Exception thrown when a route does not exist. + * + * @author Alexandre Salomé + */ +class RouteNotFoundException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/routing/Generator/CompiledUrlGenerator.php b/vendor/symfony/routing/Generator/CompiledUrlGenerator.php new file mode 100644 index 0000000..8c489f8 --- /dev/null +++ b/vendor/symfony/routing/Generator/CompiledUrlGenerator.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Routing\Exception\RouteNotFoundException; +use Symfony\Component\Routing\RequestContext; + +/** + * Generates URLs based on rules dumped by CompiledUrlGeneratorDumper. + */ +class CompiledUrlGenerator extends UrlGenerator +{ + private $compiledRoutes = []; + private $defaultLocale; + + public function __construct(array $compiledRoutes, RequestContext $context, LoggerInterface $logger = null, string $defaultLocale = null) + { + $this->compiledRoutes = $compiledRoutes; + $this->context = $context; + $this->logger = $logger; + $this->defaultLocale = $defaultLocale; + } + + public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) + { + $locale = $parameters['_locale'] + ?? $this->context->getParameter('_locale') + ?: $this->defaultLocale; + + if (null !== $locale) { + do { + if (($this->compiledRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) { + unset($parameters['_locale']); + $name .= '.'.$locale; + break; + } + } while (false !== $locale = strstr($locale, '_', true)); + } + + if (!isset($this->compiledRoutes[$name])) { + throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); + } + + list($variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes) = $this->compiledRoutes[$name]; + + return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes); + } +} diff --git a/vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php b/vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php new file mode 100644 index 0000000..568f7f7 --- /dev/null +++ b/vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator; + +/** + * ConfigurableRequirementsInterface must be implemented by URL generators that + * can be configured whether an exception should be generated when the parameters + * do not match the requirements. It is also possible to disable the requirements + * check for URL generation completely. + * + * The possible configurations and use-cases: + * - setStrictRequirements(true): Throw an exception for mismatching requirements. This + * is mostly useful in development environment. + * - setStrictRequirements(false): Don't throw an exception but return an empty string as URL for + * mismatching requirements and log the problem. Useful when you cannot control all + * params because they come from third party libs but don't want to have a 404 in + * production environment. It should log the mismatch so one can review it. + * - setStrictRequirements(null): Return the URL with the given parameters without + * checking the requirements at all. When generating a URL you should either trust + * your params or you validated them beforehand because otherwise it would break your + * link anyway. So in production environment you should know that params always pass + * the requirements. Thus this option allows to disable the check on URL generation for + * performance reasons (saving a preg_match for each requirement every time a URL is + * generated). + * + * @author Fabien Potencier + * @author Tobias Schultze + */ +interface ConfigurableRequirementsInterface +{ + /** + * Enables or disables the exception on incorrect parameters. + * Passing null will deactivate the requirements check completely. + */ + public function setStrictRequirements(?bool $enabled); + + /** + * Returns whether to throw an exception on incorrect parameters. + * Null means the requirements check is deactivated completely. + * + * @return bool|null + */ + public function isStrictRequirements(); +} diff --git a/vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php b/vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php new file mode 100644 index 0000000..e90a40a --- /dev/null +++ b/vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator\Dumper; + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; + +/** + * CompiledUrlGeneratorDumper creates a PHP array to be used with CompiledUrlGenerator. + * + * @author Fabien Potencier + * @author Tobias Schultze + * @author Nicolas Grekas + */ +class CompiledUrlGeneratorDumper extends GeneratorDumper +{ + public function getCompiledRoutes(): array + { + $compiledRoutes = []; + foreach ($this->getRoutes()->all() as $name => $route) { + $compiledRoute = $route->compile(); + + $compiledRoutes[$name] = [ + $compiledRoute->getVariables(), + $route->getDefaults(), + $route->getRequirements(), + $compiledRoute->getTokens(), + $compiledRoute->getHostTokens(), + $route->getSchemes(), + ]; + } + + return $compiledRoutes; + } + + /** + * {@inheritdoc} + */ + public function dump(array $options = []) + { + return <<generateDeclaredRoutes()} +]; + +EOF; + } + + /** + * Generates PHP code representing an array of defined routes + * together with the routes properties (e.g. requirements). + */ + private function generateDeclaredRoutes(): string + { + $routes = ''; + foreach ($this->getCompiledRoutes() as $name => $properties) { + $routes .= sprintf("\n '%s' => %s,", $name, CompiledUrlMatcherDumper::export($properties)); + } + + return $routes; + } +} diff --git a/vendor/symfony/routing/Generator/Dumper/GeneratorDumper.php b/vendor/symfony/routing/Generator/Dumper/GeneratorDumper.php new file mode 100644 index 0000000..659c5ba --- /dev/null +++ b/vendor/symfony/routing/Generator/Dumper/GeneratorDumper.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator\Dumper; + +use Symfony\Component\Routing\RouteCollection; + +/** + * GeneratorDumper is the base class for all built-in generator dumpers. + * + * @author Fabien Potencier + */ +abstract class GeneratorDumper implements GeneratorDumperInterface +{ + private $routes; + + public function __construct(RouteCollection $routes) + { + $this->routes = $routes; + } + + /** + * {@inheritdoc} + */ + public function getRoutes() + { + return $this->routes; + } +} diff --git a/vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php b/vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php new file mode 100644 index 0000000..26daefc --- /dev/null +++ b/vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator\Dumper; + +use Symfony\Component\Routing\RouteCollection; + +/** + * GeneratorDumperInterface is the interface that all generator dumper classes must implement. + * + * @author Fabien Potencier + */ +interface GeneratorDumperInterface +{ + /** + * Dumps a set of routes to a string representation of executable code + * that can then be used to generate a URL of such a route. + * + * @return string Executable code + */ + public function dump(array $options = []); + + /** + * Gets the routes to dump. + * + * @return RouteCollection A RouteCollection instance + */ + public function getRoutes(); +} diff --git a/vendor/symfony/routing/Generator/UrlGenerator.php b/vendor/symfony/routing/Generator/UrlGenerator.php new file mode 100644 index 0000000..504dd32 --- /dev/null +++ b/vendor/symfony/routing/Generator/UrlGenerator.php @@ -0,0 +1,356 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Routing\Exception\InvalidParameterException; +use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; +use Symfony\Component\Routing\Exception\RouteNotFoundException; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; + +/** + * UrlGenerator can generate a URL or a path for any route in the RouteCollection + * based on the passed parameters. + * + * @author Fabien Potencier + * @author Tobias Schultze + */ +class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface +{ + private const QUERY_FRAGMENT_DECODED = [ + // RFC 3986 explicitly allows those in the query/fragment to reference other URIs unencoded + '%2F' => '/', + '%3F' => '?', + // reserved chars that have no special meaning for HTTP URIs in a query or fragment + // this excludes esp. "&", "=" and also "+" because PHP would treat it as a space (form-encoded) + '%40' => '@', + '%3A' => ':', + '%21' => '!', + '%3B' => ';', + '%2C' => ',', + '%2A' => '*', + ]; + + protected $routes; + protected $context; + + /** + * @var bool|null + */ + protected $strictRequirements = true; + + protected $logger; + + private $defaultLocale; + + /** + * This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL. + * + * PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars + * to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g. + * "?" and "#" (would be interpreted wrongly as query and fragment identifier), + * "'" and """ (are used as delimiters in HTML). + */ + protected $decodedChars = [ + // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning + // some webservers don't allow the slash in encoded form in the path for security reasons anyway + // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss + '%2F' => '/', + // the following chars are general delimiters in the URI specification but have only special meaning in the authority component + // so they can safely be used in the path in unencoded form + '%40' => '@', + '%3A' => ':', + // these chars are only sub-delimiters that have no predefined meaning and can therefore be used literally + // so URI producing applications can use these chars to delimit subcomponents in a path segment without being encoded for better readability + '%3B' => ';', + '%2C' => ',', + '%3D' => '=', + '%2B' => '+', + '%21' => '!', + '%2A' => '*', + '%7C' => '|', + ]; + + public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null, string $defaultLocale = null) + { + $this->routes = $routes; + $this->context = $context; + $this->logger = $logger; + $this->defaultLocale = $defaultLocale; + } + + /** + * {@inheritdoc} + */ + public function setContext(RequestContext $context) + { + $this->context = $context; + } + + /** + * {@inheritdoc} + */ + public function getContext() + { + return $this->context; + } + + /** + * {@inheritdoc} + */ + public function setStrictRequirements(?bool $enabled) + { + $this->strictRequirements = $enabled; + } + + /** + * {@inheritdoc} + */ + public function isStrictRequirements() + { + return $this->strictRequirements; + } + + /** + * {@inheritdoc} + */ + public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) + { + $route = null; + $locale = $parameters['_locale'] + ?? $this->context->getParameter('_locale') + ?: $this->defaultLocale; + + if (null !== $locale) { + do { + if (null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) { + unset($parameters['_locale']); + break; + } + } while (false !== $locale = strstr($locale, '_', true)); + } + + if (null === $route = $route ?? $this->routes->get($name)) { + throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); + } + + // the Route has a cache of its own and is not recompiled as long as it does not get modified + $compiledRoute = $route->compile(); + + return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens(), $route->getSchemes()); + } + + /** + * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route + * @throws InvalidParameterException When a parameter value for a placeholder is not correct because + * it does not match the requirement + * + * @return string + */ + protected function doGenerate(array $variables, array $defaults, array $requirements, array $tokens, array $parameters, string $name, int $referenceType, array $hostTokens, array $requiredSchemes = []) + { + $variables = array_flip($variables); + $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters); + + // all params must be given + if ($diff = array_diff_key($variables, $mergedParams)) { + throw new MissingMandatoryParametersException(sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', array_keys($diff)), $name)); + } + + $url = ''; + $optional = true; + $message = 'Parameter "{parameter}" for route "{route}" must match "{expected}" ("{given}" given) to generate a corresponding URL.'; + foreach ($tokens as $token) { + if ('variable' === $token[0]) { + $varName = $token[3]; + // variable is not important by default + $important = $token[5] ?? false; + + if (!$optional || $important || !\array_key_exists($varName, $defaults) || (null !== $mergedParams[$varName] && (string) $mergedParams[$varName] !== (string) $defaults[$varName])) { + // check requirement (while ignoring look-around patterns) + if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|strictRequirements) { + throw new InvalidParameterException(strtr($message, ['{parameter}' => $varName, '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$varName]])); + } + + if ($this->logger) { + $this->logger->error($message, ['parameter' => $varName, 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$varName]]); + } + + return ''; + } + + $url = $token[1].$mergedParams[$varName].$url; + $optional = false; + } + } else { + // static text + $url = $token[1].$url; + $optional = false; + } + } + + if ('' === $url) { + $url = '/'; + } + + // the contexts base URL is already encoded (see Symfony\Component\HttpFoundation\Request) + $url = strtr(rawurlencode($url), $this->decodedChars); + + // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3 + // so we need to encode them as they are not used for this purpose here + // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route + $url = strtr($url, ['/../' => '/%2E%2E/', '/./' => '/%2E/']); + if ('/..' === substr($url, -3)) { + $url = substr($url, 0, -2).'%2E%2E'; + } elseif ('/.' === substr($url, -2)) { + $url = substr($url, 0, -1).'%2E'; + } + + $schemeAuthority = ''; + $host = $this->context->getHost(); + $scheme = $this->context->getScheme(); + + if ($requiredSchemes) { + if (!\in_array($scheme, $requiredSchemes, true)) { + $referenceType = self::ABSOLUTE_URL; + $scheme = current($requiredSchemes); + } + } + + if ($hostTokens) { + $routeHost = ''; + foreach ($hostTokens as $token) { + if ('variable' === $token[0]) { + // check requirement (while ignoring look-around patterns) + if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|strictRequirements) { + throw new InvalidParameterException(strtr($message, ['{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]])); + } + + if ($this->logger) { + $this->logger->error($message, ['parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]]]); + } + + return ''; + } + + $routeHost = $token[1].$mergedParams[$token[3]].$routeHost; + } else { + $routeHost = $token[1].$routeHost; + } + } + + if ($routeHost !== $host) { + $host = $routeHost; + if (self::ABSOLUTE_URL !== $referenceType) { + $referenceType = self::NETWORK_PATH; + } + } + } + + if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) { + if ('' !== $host || ('' !== $scheme && 'http' !== $scheme && 'https' !== $scheme)) { + $port = ''; + if ('http' === $scheme && 80 !== $this->context->getHttpPort()) { + $port = ':'.$this->context->getHttpPort(); + } elseif ('https' === $scheme && 443 !== $this->context->getHttpsPort()) { + $port = ':'.$this->context->getHttpsPort(); + } + + $schemeAuthority = self::NETWORK_PATH === $referenceType || '' === $scheme ? '//' : "$scheme://"; + $schemeAuthority .= $host.$port; + } + } + + if (self::RELATIVE_PATH === $referenceType) { + $url = self::getRelativePath($this->context->getPathInfo(), $url); + } else { + $url = $schemeAuthority.$this->context->getBaseUrl().$url; + } + + // add a query string if needed + $extra = array_udiff_assoc(array_diff_key($parameters, $variables), $defaults, function ($a, $b) { + return $a == $b ? 0 : 1; + }); + + // extract fragment + $fragment = $defaults['_fragment'] ?? ''; + + if (isset($extra['_fragment'])) { + $fragment = $extra['_fragment']; + unset($extra['_fragment']); + } + + if ($extra && $query = http_build_query($extra, '', '&', PHP_QUERY_RFC3986)) { + $url .= '?'.strtr($query, self::QUERY_FRAGMENT_DECODED); + } + + if ('' !== $fragment) { + $url .= '#'.strtr(rawurlencode($fragment), self::QUERY_FRAGMENT_DECODED); + } + + return $url; + } + + /** + * Returns the target path as relative reference from the base path. + * + * Only the URIs path component (no schema, host etc.) is relevant and must be given, starting with a slash. + * Both paths must be absolute and not contain relative parts. + * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. + * Furthermore, they can be used to reduce the link size in documents. + * + * Example target paths, given a base path of "/a/b/c/d": + * - "/a/b/c/d" -> "" + * - "/a/b/c/" -> "./" + * - "/a/b/" -> "../" + * - "/a/b/c/other" -> "other" + * - "/a/x/y" -> "../../x/y" + * + * @param string $basePath The base path + * @param string $targetPath The target path + * + * @return string The relative target path + */ + public static function getRelativePath(string $basePath, string $targetPath) + { + if ($basePath === $targetPath) { + return ''; + } + + $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); + $targetDirs = explode('/', isset($targetPath[0]) && '/' === $targetPath[0] ? substr($targetPath, 1) : $targetPath); + array_pop($sourceDirs); + $targetFile = array_pop($targetDirs); + + foreach ($sourceDirs as $i => $dir) { + if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { + unset($sourceDirs[$i], $targetDirs[$i]); + } else { + break; + } + } + + $targetDirs[] = $targetFile; + $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs); + + // A reference to the same base directory or an empty subdirectory must be prefixed with "./". + // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used + // as the first segment of a relative-path reference, as it would be mistaken for a scheme name + // (see http://tools.ietf.org/html/rfc3986#section-4.2). + return '' === $path || '/' === $path[0] + || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) + ? "./$path" : $path; + } +} diff --git a/vendor/symfony/routing/Generator/UrlGeneratorInterface.php b/vendor/symfony/routing/Generator/UrlGeneratorInterface.php new file mode 100644 index 0000000..5890ffa --- /dev/null +++ b/vendor/symfony/routing/Generator/UrlGeneratorInterface.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator; + +use Symfony\Component\Routing\Exception\InvalidParameterException; +use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; +use Symfony\Component\Routing\Exception\RouteNotFoundException; +use Symfony\Component\Routing\RequestContextAwareInterface; + +/** + * UrlGeneratorInterface is the interface that all URL generator classes must implement. + * + * The constants in this interface define the different types of resource references that + * are declared in RFC 3986: http://tools.ietf.org/html/rfc3986 + * We are using the term "URL" instead of "URI" as this is more common in web applications + * and we do not need to distinguish them as the difference is mostly semantical and + * less technical. Generating URIs, i.e. representation-independent resource identifiers, + * is also possible. + * + * @author Fabien Potencier + * @author Tobias Schultze + */ +interface UrlGeneratorInterface extends RequestContextAwareInterface +{ + /** + * Generates an absolute URL, e.g. "http://example.com/dir/file". + */ + const ABSOLUTE_URL = 0; + + /** + * Generates an absolute path, e.g. "/dir/file". + */ + const ABSOLUTE_PATH = 1; + + /** + * Generates a relative path based on the current request path, e.g. "../parent-file". + * + * @see UrlGenerator::getRelativePath() + */ + const RELATIVE_PATH = 2; + + /** + * Generates a network path, e.g. "//example.com/dir/file". + * Such reference reuses the current scheme but specifies the host. + */ + const NETWORK_PATH = 3; + + /** + * Generates a URL or path for a specific route based on the given parameters. + * + * Parameters that reference placeholders in the route pattern will substitute them in the + * path or host. Extra params are added as query string to the URL. + * + * When the passed reference type cannot be generated for the route because it requires a different + * host or scheme than the current one, the method will return a more comprehensive reference + * that includes the required params. For example, when you call this method with $referenceType = ABSOLUTE_PATH + * but the route requires the https scheme whereas the current scheme is http, it will instead return an + * ABSOLUTE_URL with the https scheme and the current host. This makes sure the generated URL matches + * the route in any case. + * + * If there is no route with the given name, the generator must throw the RouteNotFoundException. + * + * The special parameter _fragment will be used as the document fragment suffixed to the final URL. + * + * @return string The generated URL + * + * @throws RouteNotFoundException If the named route doesn't exist + * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route + * @throws InvalidParameterException When a parameter value for a placeholder is not correct because + * it does not match the requirement + */ + public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH); +} diff --git a/vendor/symfony/routing/LICENSE b/vendor/symfony/routing/LICENSE new file mode 100644 index 0000000..a677f43 --- /dev/null +++ b/vendor/symfony/routing/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/routing/Loader/AnnotationClassLoader.php b/vendor/symfony/routing/Loader/AnnotationClassLoader.php new file mode 100644 index 0000000..0c52b12 --- /dev/null +++ b/vendor/symfony/routing/Loader/AnnotationClassLoader.php @@ -0,0 +1,332 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Doctrine\Common\Annotations\Reader; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\Config\Loader\LoaderResolverInterface; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Routing\Annotation\Route as RouteAnnotation; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * AnnotationClassLoader loads routing information from a PHP class and its methods. + * + * You need to define an implementation for the getRouteDefaults() method. Most of the + * time, this method should define some PHP callable to be called for the route + * (a controller in MVC speak). + * + * The @Route annotation can be set on the class (for global parameters), + * and on each method. + * + * The @Route annotation main value is the route path. The annotation also + * recognizes several parameters: requirements, options, defaults, schemes, + * methods, host, and name. The name parameter is mandatory. + * Here is an example of how you should be able to use it: + * /** + * * @Route("/Blog") + * * / + * class Blog + * { + * /** + * * @Route("/", name="blog_index") + * * / + * public function index() + * { + * } + * /** + * * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"}) + * * / + * public function show() + * { + * } + * } + * + * @author Fabien Potencier + */ +abstract class AnnotationClassLoader implements LoaderInterface +{ + protected $reader; + + /** + * @var string + */ + protected $routeAnnotationClass = 'Symfony\\Component\\Routing\\Annotation\\Route'; + + /** + * @var int + */ + protected $defaultRouteIndex = 0; + + public function __construct(Reader $reader) + { + $this->reader = $reader; + } + + /** + * Sets the annotation class to read route properties from. + */ + public function setRouteAnnotationClass(string $class) + { + $this->routeAnnotationClass = $class; + } + + /** + * Loads from annotations from a class. + * + * @param string $class A class name + * + * @return RouteCollection A RouteCollection instance + * + * @throws \InvalidArgumentException When route can't be parsed + */ + public function load($class, string $type = null) + { + if (!class_exists($class)) { + throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); + } + + $class = new \ReflectionClass($class); + if ($class->isAbstract()) { + throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class->getName())); + } + + $globals = $this->getGlobals($class); + + $collection = new RouteCollection(); + $collection->addResource(new FileResource($class->getFileName())); + + foreach ($class->getMethods() as $method) { + $this->defaultRouteIndex = 0; + foreach ($this->reader->getMethodAnnotations($method) as $annot) { + if ($annot instanceof $this->routeAnnotationClass) { + $this->addRoute($collection, $annot, $globals, $class, $method); + } + } + } + + if (0 === $collection->count() && $class->hasMethod('__invoke')) { + $globals = $this->resetGlobals(); + foreach ($this->reader->getClassAnnotations($class) as $annot) { + if ($annot instanceof $this->routeAnnotationClass) { + $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); + } + } + } + + return $collection; + } + + /** + * @param RouteAnnotation $annot or an object that exposes a similar interface + */ + protected function addRoute(RouteCollection $collection, $annot, array $globals, \ReflectionClass $class, \ReflectionMethod $method) + { + $name = $annot->getName(); + if (null === $name) { + $name = $this->getDefaultRouteName($class, $method); + } + $name = $globals['name'].$name; + + $requirements = $annot->getRequirements(); + + foreach ($requirements as $placeholder => $requirement) { + if (\is_int($placeholder)) { + throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s::%s()"?', $placeholder, $requirement, $name, $class->getName(), $method->getName())); + } + } + + $defaults = array_replace($globals['defaults'], $annot->getDefaults()); + $requirements = array_replace($globals['requirements'], $requirements); + $options = array_replace($globals['options'], $annot->getOptions()); + $schemes = array_merge($globals['schemes'], $annot->getSchemes()); + $methods = array_merge($globals['methods'], $annot->getMethods()); + + $host = $annot->getHost(); + if (null === $host) { + $host = $globals['host']; + } + + $condition = $annot->getCondition(); + if (null === $condition) { + $condition = $globals['condition']; + } + + $path = $annot->getLocalizedPaths() ?: $annot->getPath(); + $prefix = $globals['localized_paths'] ?: $globals['path']; + $paths = []; + + if (\is_array($path)) { + if (!\is_array($prefix)) { + foreach ($path as $locale => $localePath) { + $paths[$locale] = $prefix.$localePath; + } + } elseif ($missing = array_diff_key($prefix, $path)) { + throw new \LogicException(sprintf('Route to "%s" is missing paths for locale(s) "%s".', $class->name.'::'.$method->name, implode('", "', array_keys($missing)))); + } else { + foreach ($path as $locale => $localePath) { + if (!isset($prefix[$locale])) { + throw new \LogicException(sprintf('Route to "%s" with locale "%s" is missing a corresponding prefix in class "%s".', $method->name, $locale, $class->name)); + } + + $paths[$locale] = $prefix[$locale].$localePath; + } + } + } elseif (\is_array($prefix)) { + foreach ($prefix as $locale => $localePrefix) { + $paths[$locale] = $localePrefix.$path; + } + } else { + $paths[] = $prefix.$path; + } + + foreach ($method->getParameters() as $param) { + if (isset($defaults[$param->name]) || !$param->isDefaultValueAvailable()) { + continue; + } + foreach ($paths as $locale => $path) { + if (preg_match(sprintf('/\{%s(?:<.*?>)?\}/', preg_quote($param->name)), $path)) { + $defaults[$param->name] = $param->getDefaultValue(); + break; + } + } + } + + foreach ($paths as $locale => $path) { + $route = $this->createRoute($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition); + $this->configureRoute($route, $class, $method, $annot); + if (0 !== $locale) { + $route->setDefault('_locale', $locale); + $route->setDefault('_canonical_route', $name); + $collection->add($name.'.'.$locale, $route); + } else { + $collection->add($name, $route); + } + } + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + return \is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type); + } + + /** + * {@inheritdoc} + */ + public function setResolver(LoaderResolverInterface $resolver) + { + } + + /** + * {@inheritdoc} + */ + public function getResolver() + { + } + + /** + * Gets the default route name for a class method. + * + * @return string + */ + protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) + { + $name = str_replace('\\', '_', $class->name).'_'.$method->name; + $name = \function_exists('mb_strtolower') && preg_match('//u', $name) ? mb_strtolower($name, 'UTF-8') : strtolower($name); + if ($this->defaultRouteIndex > 0) { + $name .= '_'.$this->defaultRouteIndex; + } + ++$this->defaultRouteIndex; + + return $name; + } + + protected function getGlobals(\ReflectionClass $class) + { + $globals = $this->resetGlobals(); + + if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) { + if (null !== $annot->getName()) { + $globals['name'] = $annot->getName(); + } + + if (null !== $annot->getPath()) { + $globals['path'] = $annot->getPath(); + } + + $globals['localized_paths'] = $annot->getLocalizedPaths(); + + if (null !== $annot->getRequirements()) { + $globals['requirements'] = $annot->getRequirements(); + } + + if (null !== $annot->getOptions()) { + $globals['options'] = $annot->getOptions(); + } + + if (null !== $annot->getDefaults()) { + $globals['defaults'] = $annot->getDefaults(); + } + + if (null !== $annot->getSchemes()) { + $globals['schemes'] = $annot->getSchemes(); + } + + if (null !== $annot->getMethods()) { + $globals['methods'] = $annot->getMethods(); + } + + if (null !== $annot->getHost()) { + $globals['host'] = $annot->getHost(); + } + + if (null !== $annot->getCondition()) { + $globals['condition'] = $annot->getCondition(); + } + + foreach ($globals['requirements'] as $placeholder => $requirement) { + if (\is_int($placeholder)) { + throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" in "%s"?', $placeholder, $requirement, $class->getName())); + } + } + } + + return $globals; + } + + private function resetGlobals(): array + { + return [ + 'path' => null, + 'localized_paths' => [], + 'requirements' => [], + 'options' => [], + 'defaults' => [], + 'schemes' => [], + 'methods' => [], + 'host' => '', + 'condition' => '', + 'name' => '', + ]; + } + + protected function createRoute(string $path, array $defaults, array $requirements, array $options, ?string $host, array $schemes, array $methods, ?string $condition) + { + return new Route($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition); + } + + abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot); +} diff --git a/vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php b/vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php new file mode 100644 index 0000000..7e52f31 --- /dev/null +++ b/vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Config\Resource\DirectoryResource; +use Symfony\Component\Routing\RouteCollection; + +/** + * AnnotationDirectoryLoader loads routing information from annotations set + * on PHP classes and methods. + * + * @author Fabien Potencier + */ +class AnnotationDirectoryLoader extends AnnotationFileLoader +{ + /** + * Loads from annotations from a directory. + * + * @param string $path A directory path + * @param string|null $type The resource type + * + * @return RouteCollection A RouteCollection instance + * + * @throws \InvalidArgumentException When the directory does not exist or its routes cannot be parsed + */ + public function load($path, string $type = null) + { + if (!is_dir($dir = $this->locator->locate($path))) { + return parent::supports($path, $type) ? parent::load($path, $type) : new RouteCollection(); + } + + $collection = new RouteCollection(); + $collection->addResource(new DirectoryResource($dir, '/\.php$/')); + $files = iterator_to_array(new \RecursiveIteratorIterator( + new \RecursiveCallbackFilterIterator( + new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), + function (\SplFileInfo $current) { + return '.' !== substr($current->getBasename(), 0, 1); + } + ), + \RecursiveIteratorIterator::LEAVES_ONLY + )); + usort($files, function (\SplFileInfo $a, \SplFileInfo $b) { + return (string) $a > (string) $b ? 1 : -1; + }); + + foreach ($files as $file) { + if (!$file->isFile() || '.php' !== substr($file->getFilename(), -4)) { + continue; + } + + if ($class = $this->findClass($file)) { + $refl = new \ReflectionClass($class); + if ($refl->isAbstract()) { + continue; + } + + $collection->addCollection($this->loader->load($class, $type)); + } + } + + return $collection; + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + if ('annotation' === $type) { + return true; + } + + if ($type || !\is_string($resource)) { + return false; + } + + try { + return is_dir($this->locator->locate($resource)); + } catch (\Exception $e) { + return false; + } + } +} diff --git a/vendor/symfony/routing/Loader/AnnotationFileLoader.php b/vendor/symfony/routing/Loader/AnnotationFileLoader.php new file mode 100644 index 0000000..c183d77 --- /dev/null +++ b/vendor/symfony/routing/Loader/AnnotationFileLoader.php @@ -0,0 +1,143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Config\FileLocatorInterface; +use Symfony\Component\Config\Loader\FileLoader; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Routing\RouteCollection; + +/** + * AnnotationFileLoader loads routing information from annotations set + * on a PHP class and its methods. + * + * @author Fabien Potencier + */ +class AnnotationFileLoader extends FileLoader +{ + protected $loader; + + /** + * @throws \RuntimeException + */ + public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $loader) + { + if (!\function_exists('token_get_all')) { + throw new \LogicException('The Tokenizer extension is required for the routing annotation loaders.'); + } + + parent::__construct($locator); + + $this->loader = $loader; + } + + /** + * Loads from annotations from a file. + * + * @param string $file A PHP file path + * @param string|null $type The resource type + * + * @return RouteCollection|null A RouteCollection instance + * + * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed + */ + public function load($file, string $type = null) + { + $path = $this->locator->locate($file); + + $collection = new RouteCollection(); + if ($class = $this->findClass($path)) { + $refl = new \ReflectionClass($class); + if ($refl->isAbstract()) { + return null; + } + + $collection->addResource(new FileResource($path)); + $collection->addCollection($this->loader->load($class, $type)); + } + + gc_mem_caches(); + + return $collection; + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + return \is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'annotation' === $type); + } + + /** + * Returns the full class name for the first class in the file. + * + * @return string|false Full class name if found, false otherwise + */ + protected function findClass(string $file) + { + $class = false; + $namespace = false; + $tokens = token_get_all(file_get_contents($file)); + + if (1 === \count($tokens) && T_INLINE_HTML === $tokens[0][0]) { + throw new \InvalidArgumentException(sprintf('The file "%s" does not contain PHP code. Did you forgot to add the " 0; --$j) { + if (!isset($tokens[$j][1])) { + break; + } + + if (T_DOUBLE_COLON === $tokens[$j][0] || T_NEW === $tokens[$j][0]) { + $skipClassToken = true; + break; + } elseif (!\in_array($tokens[$j][0], [T_WHITESPACE, T_DOC_COMMENT, T_COMMENT])) { + break; + } + } + + if (!$skipClassToken) { + $class = true; + } + } + + if (T_NAMESPACE === $token[0]) { + $namespace = true; + } + } + + return false; + } +} diff --git a/vendor/symfony/routing/Loader/ClosureLoader.php b/vendor/symfony/routing/Loader/ClosureLoader.php new file mode 100644 index 0000000..cea5f9c --- /dev/null +++ b/vendor/symfony/routing/Loader/ClosureLoader.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\Routing\RouteCollection; + +/** + * ClosureLoader loads routes from a PHP closure. + * + * The Closure must return a RouteCollection instance. + * + * @author Fabien Potencier + */ +class ClosureLoader extends Loader +{ + /** + * Loads a Closure. + * + * @param \Closure $closure A Closure + * @param string|null $type The resource type + * + * @return RouteCollection A RouteCollection instance + */ + public function load($closure, string $type = null) + { + return $closure(); + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + return $resource instanceof \Closure && (!$type || 'closure' === $type); + } +} diff --git a/vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php b/vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php new file mode 100644 index 0000000..79c1100 --- /dev/null +++ b/vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * @author Nicolas Grekas + */ +class CollectionConfigurator +{ + use Traits\AddTrait; + use Traits\RouteTrait; + + private $parent; + private $parentConfigurator; + private $parentPrefixes; + + public function __construct(RouteCollection $parent, string $name, self $parentConfigurator = null, array $parentPrefixes = null) + { + $this->parent = $parent; + $this->name = $name; + $this->collection = new RouteCollection(); + $this->route = new Route(''); + $this->parentConfigurator = $parentConfigurator; // for GC control + $this->parentPrefixes = $parentPrefixes; + } + + public function __destruct() + { + if (null === $this->prefixes) { + $this->collection->addPrefix($this->route->getPath()); + } + + $this->parent->addCollection($this->collection); + } + + /** + * Creates a sub-collection. + */ + final public function collection(string $name = ''): self + { + return new self($this->collection, $this->name.$name, $this, $this->prefixes); + } + + /** + * Sets the prefix to add to the path of all child routes. + * + * @param string|array $prefix the prefix, or the localized prefixes + * + * @return $this + */ + final public function prefix($prefix): self + { + if (\is_array($prefix)) { + if (null === $this->parentPrefixes) { + // no-op + } elseif ($missing = array_diff_key($this->parentPrefixes, $prefix)) { + throw new \LogicException(sprintf('Collection "%s" is missing prefixes for locale(s) "%s".', $this->name, implode('", "', array_keys($missing)))); + } else { + foreach ($prefix as $locale => $localePrefix) { + if (!isset($this->parentPrefixes[$locale])) { + throw new \LogicException(sprintf('Collection "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $this->name, $locale)); + } + + $prefix[$locale] = $this->parentPrefixes[$locale].$localePrefix; + } + } + $this->prefixes = $prefix; + $this->route->setPath('/'); + } else { + $this->prefixes = null; + $this->route->setPath($prefix); + } + + return $this; + } + + private function createRoute(string $path): Route + { + return (clone $this->route)->setPath($path); + } +} diff --git a/vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php b/vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php new file mode 100644 index 0000000..f11b795 --- /dev/null +++ b/vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * @author Nicolas Grekas + */ +class ImportConfigurator +{ + use Traits\RouteTrait; + + private $parent; + + public function __construct(RouteCollection $parent, RouteCollection $route) + { + $this->parent = $parent; + $this->route = $route; + } + + public function __destruct() + { + $this->parent->addCollection($this->route); + } + + /** + * Sets the prefix to add to the path of all child routes. + * + * @param string|array $prefix the prefix, or the localized prefixes + * + * @return $this + */ + final public function prefix($prefix, bool $trailingSlashOnRoot = true): self + { + if (!\is_array($prefix)) { + $this->route->addPrefix($prefix); + if (!$trailingSlashOnRoot) { + $rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath(); + foreach ($this->route->all() as $route) { + if ($route->getPath() === $rootPath) { + $route->setPath(rtrim($rootPath, '/')); + } + } + } + } else { + foreach ($prefix as $locale => $localePrefix) { + $prefix[$locale] = trim(trim($localePrefix), '/'); + } + foreach ($this->route->all() as $name => $route) { + if (null === $locale = $route->getDefault('_locale')) { + $this->route->remove($name); + foreach ($prefix as $locale => $localePrefix) { + $localizedRoute = clone $route; + $localizedRoute->setDefault('_locale', $locale); + $localizedRoute->setDefault('_canonical_route', $name); + $localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); + $this->route->add($name.'.'.$locale, $localizedRoute); + } + } elseif (!isset($prefix[$locale])) { + throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale)); + } else { + $route->setPath($prefix[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); + $this->route->add($name, $route); + } + } + } + + return $this; + } + + /** + * Sets the prefix to add to the name of all child routes. + * + * @return $this + */ + final public function namePrefix(string $namePrefix): self + { + $this->route->addNamePrefix($namePrefix); + + return $this; + } +} diff --git a/vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php b/vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php new file mode 100644 index 0000000..e700f8d --- /dev/null +++ b/vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +use Symfony\Component\Routing\RouteCollection; + +/** + * @author Nicolas Grekas + */ +class RouteConfigurator +{ + use Traits\AddTrait; + use Traits\RouteTrait; + + private $parentConfigurator; + + public function __construct(RouteCollection $collection, $route, string $name = '', CollectionConfigurator $parentConfigurator = null, array $prefixes = null) + { + $this->collection = $collection; + $this->route = $route; + $this->name = $name; + $this->parentConfigurator = $parentConfigurator; // for GC control + $this->prefixes = $prefixes; + } +} diff --git a/vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php b/vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php new file mode 100644 index 0000000..8ed06f3 --- /dev/null +++ b/vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +use Symfony\Component\Routing\Loader\PhpFileLoader; +use Symfony\Component\Routing\RouteCollection; + +/** + * @author Nicolas Grekas + */ +class RoutingConfigurator +{ + use Traits\AddTrait; + + private $loader; + private $path; + private $file; + + public function __construct(RouteCollection $collection, PhpFileLoader $loader, string $path, string $file) + { + $this->collection = $collection; + $this->loader = $loader; + $this->path = $path; + $this->file = $file; + } + + /** + * @param string|string[]|null $exclude Glob patterns to exclude from the import + */ + final public function import($resource, string $type = null, bool $ignoreErrors = false, $exclude = null): ImportConfigurator + { + $this->loader->setCurrentDir(\dirname($this->path)); + + $imported = $this->loader->import($resource, $type, $ignoreErrors, $this->file, $exclude) ?: []; + if (!\is_array($imported)) { + return new ImportConfigurator($this->collection, $imported); + } + + $mergedCollection = new RouteCollection(); + foreach ($imported as $subCollection) { + $mergedCollection->addCollection($subCollection); + } + + return new ImportConfigurator($this->collection, $mergedCollection); + } + + final public function collection(string $name = ''): CollectionConfigurator + { + return new CollectionConfigurator($this->collection, $name); + } +} diff --git a/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php b/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php new file mode 100644 index 0000000..085fde4 --- /dev/null +++ b/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator\Traits; + +use Symfony\Component\Routing\Loader\Configurator\CollectionConfigurator; +use Symfony\Component\Routing\Loader\Configurator\RouteConfigurator; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +trait AddTrait +{ + /** + * @var RouteCollection + */ + private $collection; + + private $name = ''; + + private $prefixes; + + /** + * Adds a route. + * + * @param string|array $path the path, or the localized paths of the route + */ + final public function add(string $name, $path): RouteConfigurator + { + $paths = []; + $parentConfigurator = $this instanceof CollectionConfigurator ? $this : ($this instanceof RouteConfigurator ? $this->parentConfigurator : null); + + if (\is_array($path)) { + if (null === $this->prefixes) { + $paths = $path; + } elseif ($missing = array_diff_key($this->prefixes, $path)) { + throw new \LogicException(sprintf('Route "%s" is missing routes for locale(s) "%s".', $name, implode('", "', array_keys($missing)))); + } else { + foreach ($path as $locale => $localePath) { + if (!isset($this->prefixes[$locale])) { + throw new \LogicException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale)); + } + + $paths[$locale] = $this->prefixes[$locale].$localePath; + } + } + } elseif (null !== $this->prefixes) { + foreach ($this->prefixes as $locale => $prefix) { + $paths[$locale] = $prefix.$path; + } + } else { + $this->collection->add($this->name.$name, $route = $this->createRoute($path)); + + return new RouteConfigurator($this->collection, $route, $this->name, $parentConfigurator, $this->prefixes); + } + + $routes = new RouteCollection(); + + foreach ($paths as $locale => $path) { + $routes->add($name.'.'.$locale, $route = $this->createRoute($path)); + $this->collection->add($this->name.$name.'.'.$locale, $route); + $route->setDefault('_locale', $locale); + $route->setDefault('_canonical_route', $this->name.$name); + } + + return new RouteConfigurator($this->collection, $routes, $this->name, $parentConfigurator, $this->prefixes); + } + + /** + * Adds a route. + * + * @param string|array $path the path, or the localized paths of the route + */ + final public function __invoke(string $name, $path): RouteConfigurator + { + return $this->add($name, $path); + } + + private function createRoute(string $path): Route + { + return new Route($path); + } +} diff --git a/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php b/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php new file mode 100644 index 0000000..04009cd --- /dev/null +++ b/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php @@ -0,0 +1,163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator\Traits; + +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +trait RouteTrait +{ + /** + * @var RouteCollection|Route + */ + private $route; + + /** + * Adds defaults. + * + * @return $this + */ + final public function defaults(array $defaults): self + { + $this->route->addDefaults($defaults); + + return $this; + } + + /** + * Adds requirements. + * + * @return $this + */ + final public function requirements(array $requirements): self + { + $this->route->addRequirements($requirements); + + return $this; + } + + /** + * Adds options. + * + * @return $this + */ + final public function options(array $options): self + { + $this->route->addOptions($options); + + return $this; + } + + /** + * Whether paths should accept utf8 encoding. + * + * @return $this + */ + final public function utf8(bool $utf8 = true): self + { + $this->route->addOptions(['utf8' => $utf8]); + + return $this; + } + + /** + * Sets the condition. + * + * @return $this + */ + final public function condition(string $condition): self + { + $this->route->setCondition($condition); + + return $this; + } + + /** + * Sets the pattern for the host. + * + * @return $this + */ + final public function host(string $pattern): self + { + $this->route->setHost($pattern); + + return $this; + } + + /** + * Sets the schemes (e.g. 'https') this route is restricted to. + * So an empty array means that any scheme is allowed. + * + * @param string[] $schemes + * + * @return $this + */ + final public function schemes(array $schemes): self + { + $this->route->setSchemes($schemes); + + return $this; + } + + /** + * Sets the HTTP methods (e.g. 'POST') this route is restricted to. + * So an empty array means that any method is allowed. + * + * @param string[] $methods + * + * @return $this + */ + final public function methods(array $methods): self + { + $this->route->setMethods($methods); + + return $this; + } + + /** + * Adds the "_controller" entry to defaults. + * + * @param callable|string $controller a callable or parseable pseudo-callable + * + * @return $this + */ + final public function controller($controller): self + { + $this->route->addDefaults(['_controller' => $controller]); + + return $this; + } + + /** + * Adds the "_locale" entry to defaults. + * + * @return $this + */ + final public function locale(string $locale): self + { + $this->route->addDefaults(['_locale' => $locale]); + + return $this; + } + + /** + * Adds the "_format" entry to defaults. + * + * @return $this + */ + final public function format(string $format): self + { + $this->route->addDefaults(['_format' => $format]); + + return $this; + } +} diff --git a/vendor/symfony/routing/Loader/ContainerLoader.php b/vendor/symfony/routing/Loader/ContainerLoader.php new file mode 100644 index 0000000..92bf2a0 --- /dev/null +++ b/vendor/symfony/routing/Loader/ContainerLoader.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Psr\Container\ContainerInterface; + +/** + * A route loader that executes a service from a PSR-11 container to load the routes. + * + * @author Ryan Weaver + */ +class ContainerLoader extends ObjectLoader +{ + private $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + return 'service' === $type; + } + + /** + * {@inheritdoc} + */ + protected function getObject(string $id) + { + return $this->container->get($id); + } +} diff --git a/vendor/symfony/routing/Loader/DirectoryLoader.php b/vendor/symfony/routing/Loader/DirectoryLoader.php new file mode 100644 index 0000000..c0f3491 --- /dev/null +++ b/vendor/symfony/routing/Loader/DirectoryLoader.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Config\Loader\FileLoader; +use Symfony\Component\Config\Resource\DirectoryResource; +use Symfony\Component\Routing\RouteCollection; + +class DirectoryLoader extends FileLoader +{ + /** + * {@inheritdoc} + */ + public function load($file, string $type = null) + { + $path = $this->locator->locate($file); + + $collection = new RouteCollection(); + $collection->addResource(new DirectoryResource($path)); + + foreach (scandir($path) as $dir) { + if ('.' !== $dir[0]) { + $this->setCurrentDir($path); + $subPath = $path.'/'.$dir; + $subType = null; + + if (is_dir($subPath)) { + $subPath .= '/'; + $subType = 'directory'; + } + + $subCollection = $this->import($subPath, $subType, false, $path); + $collection->addCollection($subCollection); + } + } + + return $collection; + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + // only when type is forced to directory, not to conflict with AnnotationLoader + + return 'directory' === $type; + } +} diff --git a/vendor/symfony/routing/Loader/GlobFileLoader.php b/vendor/symfony/routing/Loader/GlobFileLoader.php new file mode 100644 index 0000000..780fb15 --- /dev/null +++ b/vendor/symfony/routing/Loader/GlobFileLoader.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Config\Loader\FileLoader; +use Symfony\Component\Routing\RouteCollection; + +/** + * GlobFileLoader loads files from a glob pattern. + * + * @author Nicolas Grekas + */ +class GlobFileLoader extends FileLoader +{ + /** + * {@inheritdoc} + */ + public function load($resource, string $type = null) + { + $collection = new RouteCollection(); + + foreach ($this->glob($resource, false, $globResource) as $path => $info) { + $collection->addCollection($this->import($path)); + } + + $collection->addResource($globResource); + + return $collection; + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + return 'glob' === $type; + } +} diff --git a/vendor/symfony/routing/Loader/ObjectLoader.php b/vendor/symfony/routing/Loader/ObjectLoader.php new file mode 100644 index 0000000..aefb829 --- /dev/null +++ b/vendor/symfony/routing/Loader/ObjectLoader.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Config\Loader\Loader; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Routing\RouteCollection; + +/** + * A route loader that calls a method on an object to load the routes. + * + * @author Ryan Weaver + */ +abstract class ObjectLoader extends Loader +{ + /** + * Returns the object that the method will be called on to load routes. + * + * For example, if your application uses a service container, + * the $id may be a service id. + * + * @return object + */ + abstract protected function getObject(string $id); + + /** + * Calls the object method that will load the routes. + * + * @param string $resource object_id::method + * @param string|null $type The resource type + * + * @return RouteCollection + */ + public function load($resource, string $type = null) + { + if (!preg_match('/^[^\:]+(?:::(?:[^\:]+))?$/', $resource)) { + throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the %s route loader: use the format "object_id::method" or "object_id" if your object class has an "__invoke" method.', $resource, \is_string($type) ? '"'.$type.'"' : 'object')); + } + + $parts = explode('::', $resource); + $method = $parts[1] ?? '__invoke'; + + $loaderObject = $this->getObject($parts[0]); + + if (!\is_object($loaderObject)) { + throw new \TypeError(sprintf('%s:getObject() must return an object: %s returned', \get_class($this), \gettype($loaderObject))); + } + + if (!\is_callable([$loaderObject, $method])) { + throw new \BadMethodCallException(sprintf('Method "%s" not found on "%s" when importing routing resource "%s"', $method, \get_class($loaderObject), $resource)); + } + + $routeCollection = $loaderObject->$method($this); + + if (!$routeCollection instanceof RouteCollection) { + $type = \is_object($routeCollection) ? \get_class($routeCollection) : \gettype($routeCollection); + + throw new \LogicException(sprintf('The %s::%s method must return a RouteCollection: %s returned', \get_class($loaderObject), $method, $type)); + } + + // make the object file tracked so that if it changes, the cache rebuilds + $this->addClassResource(new \ReflectionClass($loaderObject), $routeCollection); + + return $routeCollection; + } + + private function addClassResource(\ReflectionClass $class, RouteCollection $collection) + { + do { + if (is_file($class->getFileName())) { + $collection->addResource(new FileResource($class->getFileName())); + } + } while ($class = $class->getParentClass()); + } +} diff --git a/vendor/symfony/routing/Loader/PhpFileLoader.php b/vendor/symfony/routing/Loader/PhpFileLoader.php new file mode 100644 index 0000000..31fe88d --- /dev/null +++ b/vendor/symfony/routing/Loader/PhpFileLoader.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Config\Loader\FileLoader; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; +use Symfony\Component\Routing\RouteCollection; + +/** + * PhpFileLoader loads routes from a PHP file. + * + * The file must return a RouteCollection instance. + * + * @author Fabien Potencier + */ +class PhpFileLoader extends FileLoader +{ + /** + * Loads a PHP file. + * + * @param string $file A PHP file path + * @param string|null $type The resource type + * + * @return RouteCollection A RouteCollection instance + */ + public function load($file, string $type = null) + { + $path = $this->locator->locate($file); + $this->setCurrentDir(\dirname($path)); + + // the closure forbids access to the private scope in the included file + $loader = $this; + $load = \Closure::bind(static function ($file) use ($loader) { + return include $file; + }, null, ProtectedPhpFileLoader::class); + + $result = $load($path); + + if (\is_object($result) && \is_callable($result)) { + $collection = new RouteCollection(); + $result(new RoutingConfigurator($collection, $this, $path, $file)); + } else { + $collection = $result; + } + + $collection->addResource(new FileResource($path)); + + return $collection; + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + return \is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'php' === $type); + } +} + +/** + * @internal + */ +final class ProtectedPhpFileLoader extends PhpFileLoader +{ +} diff --git a/vendor/symfony/routing/Loader/XmlFileLoader.php b/vendor/symfony/routing/Loader/XmlFileLoader.php new file mode 100644 index 0000000..9d46cfd --- /dev/null +++ b/vendor/symfony/routing/Loader/XmlFileLoader.php @@ -0,0 +1,436 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Config\Loader\FileLoader; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Config\Util\XmlUtils; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * XmlFileLoader loads XML routing files. + * + * @author Fabien Potencier + * @author Tobias Schultze + */ +class XmlFileLoader extends FileLoader +{ + const NAMESPACE_URI = 'http://symfony.com/schema/routing'; + const SCHEME_PATH = '/schema/routing/routing-1.0.xsd'; + + /** + * Loads an XML file. + * + * @param string $file An XML file path + * @param string|null $type The resource type + * + * @return RouteCollection A RouteCollection instance + * + * @throws \InvalidArgumentException when the file cannot be loaded or when the XML cannot be + * parsed because it does not validate against the scheme + */ + public function load($file, string $type = null) + { + $path = $this->locator->locate($file); + + $xml = $this->loadFile($path); + + $collection = new RouteCollection(); + $collection->addResource(new FileResource($path)); + + // process routes and imports + foreach ($xml->documentElement->childNodes as $node) { + if (!$node instanceof \DOMElement) { + continue; + } + + $this->parseNode($collection, $node, $path, $file); + } + + return $collection; + } + + /** + * Parses a node from a loaded XML file. + * + * @param \DOMElement $node Element to parse + * @param string $path Full path of the XML file being processed + * @param string $file Loaded file name + * + * @throws \InvalidArgumentException When the XML is invalid + */ + protected function parseNode(RouteCollection $collection, \DOMElement $node, string $path, string $file) + { + if (self::NAMESPACE_URI !== $node->namespaceURI) { + return; + } + + switch ($node->localName) { + case 'route': + $this->parseRoute($collection, $node, $path); + break; + case 'import': + $this->parseImport($collection, $node, $path, $file); + break; + default: + throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path)); + } + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + return \is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'xml' === $type); + } + + /** + * Parses a route and adds it to the RouteCollection. + * + * @param \DOMElement $node Element to parse that represents a Route + * @param string $path Full path of the XML file being processed + * + * @throws \InvalidArgumentException When the XML is invalid + */ + protected function parseRoute(RouteCollection $collection, \DOMElement $node, string $path) + { + if ('' === $id = $node->getAttribute('id')) { + throw new \InvalidArgumentException(sprintf('The element in file "%s" must have an "id" attribute.', $path)); + } + + $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY); + $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY); + + list($defaults, $requirements, $options, $condition, $paths) = $this->parseConfigs($node, $path); + + if (!$paths && '' === $node->getAttribute('path')) { + throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "path" attribute or child nodes.', $path)); + } + + if ($paths && '' !== $node->getAttribute('path')) { + throw new \InvalidArgumentException(sprintf('The element in file "%s" must not have both a "path" attribute and child nodes.', $path)); + } + + if (!$paths) { + $route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition); + $collection->add($id, $route); + } else { + foreach ($paths as $locale => $p) { + $defaults['_locale'] = $locale; + $defaults['_canonical_route'] = $id; + $route = new Route($p, $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition); + $collection->add($id.'.'.$locale, $route); + } + } + } + + /** + * Parses an import and adds the routes in the resource to the RouteCollection. + * + * @param \DOMElement $node Element to parse that represents a Route + * @param string $path Full path of the XML file being processed + * @param string $file Loaded file name + * + * @throws \InvalidArgumentException When the XML is invalid + */ + protected function parseImport(RouteCollection $collection, \DOMElement $node, string $path, string $file) + { + if ('' === $resource = $node->getAttribute('resource')) { + throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "resource" attribute.', $path)); + } + + $type = $node->getAttribute('type'); + $prefix = $node->getAttribute('prefix'); + $host = $node->hasAttribute('host') ? $node->getAttribute('host') : null; + $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY) : null; + $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY) : null; + $trailingSlashOnRoot = $node->hasAttribute('trailing-slash-on-root') ? XmlUtils::phpize($node->getAttribute('trailing-slash-on-root')) : true; + + list($defaults, $requirements, $options, $condition, /* $paths */, $prefixes) = $this->parseConfigs($node, $path); + + if ('' !== $prefix && $prefixes) { + throw new \InvalidArgumentException(sprintf('The element in file "%s" must not have both a "prefix" attribute and child nodes.', $path)); + } + + $exclude = []; + foreach ($node->childNodes as $child) { + if ($child instanceof \DOMElement && $child->localName === $exclude && self::NAMESPACE_URI === $child->namespaceURI) { + $exclude[] = $child->nodeValue; + } + } + + if ($node->hasAttribute('exclude')) { + if ($exclude) { + throw new \InvalidArgumentException('You cannot use both the attribute "exclude" and tags at the same time.'); + } + $exclude = [$node->getAttribute('exclude')]; + } + + $this->setCurrentDir(\dirname($path)); + + /** @var RouteCollection[] $imported */ + $imported = $this->import($resource, ('' !== $type ? $type : null), false, $file, $exclude) ?: []; + + if (!\is_array($imported)) { + $imported = [$imported]; + } + + foreach ($imported as $subCollection) { + /* @var $subCollection RouteCollection */ + if ('' !== $prefix || !$prefixes) { + $subCollection->addPrefix($prefix); + if (!$trailingSlashOnRoot) { + $rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath(); + foreach ($subCollection->all() as $route) { + if ($route->getPath() === $rootPath) { + $route->setPath(rtrim($rootPath, '/')); + } + } + } + } else { + foreach ($prefixes as $locale => $localePrefix) { + $prefixes[$locale] = trim(trim($localePrefix), '/'); + } + foreach ($subCollection->all() as $name => $route) { + if (null === $locale = $route->getDefault('_locale')) { + $subCollection->remove($name); + foreach ($prefixes as $locale => $localePrefix) { + $localizedRoute = clone $route; + $localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); + $localizedRoute->setDefault('_locale', $locale); + $localizedRoute->setDefault('_canonical_route', $name); + $subCollection->add($name.'.'.$locale, $localizedRoute); + } + } elseif (!isset($prefixes[$locale])) { + throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix when imported in "%s".', $name, $locale, $path)); + } else { + $route->setPath($prefixes[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); + $subCollection->add($name, $route); + } + } + } + + if (null !== $host) { + $subCollection->setHost($host); + } + if (null !== $condition) { + $subCollection->setCondition($condition); + } + if (null !== $schemes) { + $subCollection->setSchemes($schemes); + } + if (null !== $methods) { + $subCollection->setMethods($methods); + } + $subCollection->addDefaults($defaults); + $subCollection->addRequirements($requirements); + $subCollection->addOptions($options); + + if ($namePrefix = $node->getAttribute('name-prefix')) { + $subCollection->addNamePrefix($namePrefix); + } + + $collection->addCollection($subCollection); + } + } + + /** + * Loads an XML file. + * + * @param string $file An XML file path + * + * @return \DOMDocument + * + * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors + * or when the XML structure is not as expected by the scheme - + * see validate() + */ + protected function loadFile(string $file) + { + return XmlUtils::loadFile($file, __DIR__.static::SCHEME_PATH); + } + + /** + * Parses the config elements (default, requirement, option). + * + * @throws \InvalidArgumentException When the XML is invalid + */ + private function parseConfigs(\DOMElement $node, string $path): array + { + $defaults = []; + $requirements = []; + $options = []; + $condition = null; + $prefixes = []; + $paths = []; + + /** @var \DOMElement $n */ + foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) { + if ($node !== $n->parentNode) { + continue; + } + + switch ($n->localName) { + case 'path': + $paths[$n->getAttribute('locale')] = trim($n->textContent); + break; + case 'prefix': + $prefixes[$n->getAttribute('locale')] = trim($n->textContent); + break; + case 'default': + if ($this->isElementValueNull($n)) { + $defaults[$n->getAttribute('key')] = null; + } else { + $defaults[$n->getAttribute('key')] = $this->parseDefaultsConfig($n, $path); + } + + break; + case 'requirement': + $requirements[$n->getAttribute('key')] = trim($n->textContent); + break; + case 'option': + $options[$n->getAttribute('key')] = XmlUtils::phpize(trim($n->textContent)); + break; + case 'condition': + $condition = trim($n->textContent); + break; + default: + throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path)); + } + } + + if ($controller = $node->getAttribute('controller')) { + if (isset($defaults['_controller'])) { + $name = $node->hasAttribute('id') ? sprintf('"%s"', $node->getAttribute('id')) : sprintf('the "%s" tag', $node->tagName); + + throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for %s.', $path, $name)); + } + + $defaults['_controller'] = $controller; + } + if ($node->hasAttribute('locale')) { + $defaults['_locale'] = $node->getAttribute('locale'); + } + if ($node->hasAttribute('format')) { + $defaults['_format'] = $node->getAttribute('format'); + } + if ($node->hasAttribute('utf8')) { + $options['utf8'] = XmlUtils::phpize($node->getAttribute('utf8')); + } + + return [$defaults, $requirements, $options, $condition, $paths, $prefixes]; + } + + /** + * Parses the "default" elements. + * + * @return array|bool|float|int|string|null The parsed value of the "default" element + */ + private function parseDefaultsConfig(\DOMElement $element, string $path) + { + if ($this->isElementValueNull($element)) { + return null; + } + + // Check for existing element nodes in the default element. There can + // only be a single element inside a default element. So this element + // (if one was found) can safely be returned. + foreach ($element->childNodes as $child) { + if (!$child instanceof \DOMElement) { + continue; + } + + if (self::NAMESPACE_URI !== $child->namespaceURI) { + continue; + } + + return $this->parseDefaultNode($child, $path); + } + + // If the default element doesn't contain a nested "bool", "int", "float", + // "string", "list", or "map" element, the element contents will be treated + // as the string value of the associated default option. + return trim($element->textContent); + } + + /** + * Recursively parses the value of a "default" element. + * + * @return array|bool|float|int|string The parsed value + * + * @throws \InvalidArgumentException when the XML is invalid + */ + private function parseDefaultNode(\DOMElement $node, string $path) + { + if ($this->isElementValueNull($node)) { + return null; + } + + switch ($node->localName) { + case 'bool': + return 'true' === trim($node->nodeValue) || '1' === trim($node->nodeValue); + case 'int': + return (int) trim($node->nodeValue); + case 'float': + return (float) trim($node->nodeValue); + case 'string': + return trim($node->nodeValue); + case 'list': + $list = []; + + foreach ($node->childNodes as $element) { + if (!$element instanceof \DOMElement) { + continue; + } + + if (self::NAMESPACE_URI !== $element->namespaceURI) { + continue; + } + + $list[] = $this->parseDefaultNode($element, $path); + } + + return $list; + case 'map': + $map = []; + + foreach ($node->childNodes as $element) { + if (!$element instanceof \DOMElement) { + continue; + } + + if (self::NAMESPACE_URI !== $element->namespaceURI) { + continue; + } + + $map[$element->getAttribute('key')] = $this->parseDefaultNode($element, $path); + } + + return $map; + default: + throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "bool", "int", "float", "string", "list", or "map".', $node->localName, $path)); + } + } + + private function isElementValueNull(\DOMElement $element): bool + { + $namespaceUri = 'http://www.w3.org/2001/XMLSchema-instance'; + + if (!$element->hasAttributeNS($namespaceUri, 'nil')) { + return false; + } + + return 'true' === $element->getAttributeNS($namespaceUri, 'nil') || '1' === $element->getAttributeNS($namespaceUri, 'nil'); + } +} diff --git a/vendor/symfony/routing/Loader/YamlFileLoader.php b/vendor/symfony/routing/Loader/YamlFileLoader.php new file mode 100644 index 0000000..3b47b20 --- /dev/null +++ b/vendor/symfony/routing/Loader/YamlFileLoader.php @@ -0,0 +1,285 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Config\Loader\FileLoader; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Yaml\Exception\ParseException; +use Symfony\Component\Yaml\Parser as YamlParser; +use Symfony\Component\Yaml\Yaml; + +/** + * YamlFileLoader loads Yaml routing files. + * + * @author Fabien Potencier + * @author Tobias Schultze + */ +class YamlFileLoader extends FileLoader +{ + private static $availableKeys = [ + 'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller', 'name_prefix', 'trailing_slash_on_root', 'locale', 'format', 'utf8', 'exclude', + ]; + private $yamlParser; + + /** + * Loads a Yaml file. + * + * @param string $file A Yaml file path + * @param string|null $type The resource type + * + * @return RouteCollection A RouteCollection instance + * + * @throws \InvalidArgumentException When a route can't be parsed because YAML is invalid + */ + public function load($file, string $type = null) + { + $path = $this->locator->locate($file); + + if (!stream_is_local($path)) { + throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $path)); + } + + if (!file_exists($path)) { + throw new \InvalidArgumentException(sprintf('File "%s" not found.', $path)); + } + + if (null === $this->yamlParser) { + $this->yamlParser = new YamlParser(); + } + + try { + $parsedConfig = $this->yamlParser->parseFile($path, Yaml::PARSE_CONSTANT); + } catch (ParseException $e) { + throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); + } + + $collection = new RouteCollection(); + $collection->addResource(new FileResource($path)); + + // empty file + if (null === $parsedConfig) { + return $collection; + } + + // not an array + if (!\is_array($parsedConfig)) { + throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path)); + } + + foreach ($parsedConfig as $name => $config) { + $this->validate($config, $name, $path); + + if (isset($config['resource'])) { + $this->parseImport($collection, $config, $path, $file); + } else { + $this->parseRoute($collection, $name, $config, $path); + } + } + + return $collection; + } + + /** + * {@inheritdoc} + */ + public function supports($resource, string $type = null) + { + return \is_string($resource) && \in_array(pathinfo($resource, PATHINFO_EXTENSION), ['yml', 'yaml'], true) && (!$type || 'yaml' === $type); + } + + /** + * Parses a route and adds it to the RouteCollection. + * + * @param string $name Route name + * @param array $config Route definition + * @param string $path Full path of the YAML file being processed + */ + protected function parseRoute(RouteCollection $collection, string $name, array $config, string $path) + { + $defaults = isset($config['defaults']) ? $config['defaults'] : []; + $requirements = isset($config['requirements']) ? $config['requirements'] : []; + $options = isset($config['options']) ? $config['options'] : []; + $host = isset($config['host']) ? $config['host'] : ''; + $schemes = isset($config['schemes']) ? $config['schemes'] : []; + $methods = isset($config['methods']) ? $config['methods'] : []; + $condition = isset($config['condition']) ? $config['condition'] : null; + + foreach ($requirements as $placeholder => $requirement) { + if (\is_int($placeholder)) { + throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s"?', $placeholder, $requirement, $name, $path)); + } + } + + if (isset($config['controller'])) { + $defaults['_controller'] = $config['controller']; + } + if (isset($config['locale'])) { + $defaults['_locale'] = $config['locale']; + } + if (isset($config['format'])) { + $defaults['_format'] = $config['format']; + } + if (isset($config['utf8'])) { + $options['utf8'] = $config['utf8']; + } + + if (\is_array($config['path'])) { + $route = new Route('', $defaults, $requirements, $options, $host, $schemes, $methods, $condition); + + foreach ($config['path'] as $locale => $path) { + $localizedRoute = clone $route; + $localizedRoute->setDefault('_locale', $locale); + $localizedRoute->setDefault('_canonical_route', $name); + $localizedRoute->setPath($path); + $collection->add($name.'.'.$locale, $localizedRoute); + } + } else { + $route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition); + $collection->add($name, $route); + } + } + + /** + * Parses an import and adds the routes in the resource to the RouteCollection. + * + * @param array $config Route definition + * @param string $path Full path of the YAML file being processed + * @param string $file Loaded file name + */ + protected function parseImport(RouteCollection $collection, array $config, string $path, string $file) + { + $type = isset($config['type']) ? $config['type'] : null; + $prefix = isset($config['prefix']) ? $config['prefix'] : ''; + $defaults = isset($config['defaults']) ? $config['defaults'] : []; + $requirements = isset($config['requirements']) ? $config['requirements'] : []; + $options = isset($config['options']) ? $config['options'] : []; + $host = isset($config['host']) ? $config['host'] : null; + $condition = isset($config['condition']) ? $config['condition'] : null; + $schemes = isset($config['schemes']) ? $config['schemes'] : null; + $methods = isset($config['methods']) ? $config['methods'] : null; + $trailingSlashOnRoot = $config['trailing_slash_on_root'] ?? true; + $exclude = $config['exclude'] ?? null; + + if (isset($config['controller'])) { + $defaults['_controller'] = $config['controller']; + } + if (isset($config['locale'])) { + $defaults['_locale'] = $config['locale']; + } + if (isset($config['format'])) { + $defaults['_format'] = $config['format']; + } + if (isset($config['utf8'])) { + $options['utf8'] = $config['utf8']; + } + + $this->setCurrentDir(\dirname($path)); + + $imported = $this->import($config['resource'], $type, false, $file, $exclude) ?: []; + + if (!\is_array($imported)) { + $imported = [$imported]; + } + + foreach ($imported as $subCollection) { + /* @var $subCollection RouteCollection */ + if (!\is_array($prefix)) { + $subCollection->addPrefix($prefix); + if (!$trailingSlashOnRoot) { + $rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath(); + foreach ($subCollection->all() as $route) { + if ($route->getPath() === $rootPath) { + $route->setPath(rtrim($rootPath, '/')); + } + } + } + } else { + foreach ($prefix as $locale => $localePrefix) { + $prefix[$locale] = trim(trim($localePrefix), '/'); + } + foreach ($subCollection->all() as $name => $route) { + if (null === $locale = $route->getDefault('_locale')) { + $subCollection->remove($name); + foreach ($prefix as $locale => $localePrefix) { + $localizedRoute = clone $route; + $localizedRoute->setDefault('_locale', $locale); + $localizedRoute->setDefault('_canonical_route', $name); + $localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); + $subCollection->add($name.'.'.$locale, $localizedRoute); + } + } elseif (!isset($prefix[$locale])) { + throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix when imported in "%s".', $name, $locale, $file)); + } else { + $route->setPath($prefix[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); + $subCollection->add($name, $route); + } + } + } + + if (null !== $host) { + $subCollection->setHost($host); + } + if (null !== $condition) { + $subCollection->setCondition($condition); + } + if (null !== $schemes) { + $subCollection->setSchemes($schemes); + } + if (null !== $methods) { + $subCollection->setMethods($methods); + } + $subCollection->addDefaults($defaults); + $subCollection->addRequirements($requirements); + $subCollection->addOptions($options); + + if (isset($config['name_prefix'])) { + $subCollection->addNamePrefix($config['name_prefix']); + } + + $collection->addCollection($subCollection); + } + } + + /** + * Validates the route configuration. + * + * @param array $config A resource config + * @param string $name The config key + * @param string $path The loaded file path + * + * @throws \InvalidArgumentException If one of the provided config keys is not supported, + * something is missing or the combination is nonsense + */ + protected function validate($config, string $name, string $path) + { + if (!\is_array($config)) { + throw new \InvalidArgumentException(sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path)); + } + if ($extraKeys = array_diff(array_keys($config), self::$availableKeys)) { + throw new \InvalidArgumentException(sprintf('The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', $path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys))); + } + if (isset($config['resource']) && isset($config['path'])) { + throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', $path, $name)); + } + if (!isset($config['resource']) && isset($config['type'])) { + throw new \InvalidArgumentException(sprintf('The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', $name, $path)); + } + if (!isset($config['resource']) && !isset($config['path'])) { + throw new \InvalidArgumentException(sprintf('You must define a "path" for the route "%s" in file "%s".', $name, $path)); + } + if (isset($config['controller']) && isset($config['defaults']['_controller'])) { + throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name)); + } + } +} diff --git a/vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd b/vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd new file mode 100644 index 0000000..8e61d03 --- /dev/null +++ b/vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/symfony/routing/Matcher/CompiledUrlMatcher.php b/vendor/symfony/routing/Matcher/CompiledUrlMatcher.php new file mode 100644 index 0000000..e15cda7 --- /dev/null +++ b/vendor/symfony/routing/Matcher/CompiledUrlMatcher.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; +use Symfony\Component\Routing\RequestContext; + +/** + * Matches URLs based on rules dumped by CompiledUrlMatcherDumper. + * + * @author Nicolas Grekas + */ +class CompiledUrlMatcher extends UrlMatcher +{ + use CompiledUrlMatcherTrait; + + public function __construct(array $compiledRoutes, RequestContext $context) + { + $this->context = $context; + list($this->matchHost, $this->staticRoutes, $this->regexpList, $this->dynamicRoutes, $this->checkCondition) = $compiledRoutes; + } +} diff --git a/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php b/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php new file mode 100644 index 0000000..936dd16 --- /dev/null +++ b/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php @@ -0,0 +1,501 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher\Dumper; + +use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * CompiledUrlMatcherDumper creates PHP arrays to be used with CompiledUrlMatcher. + * + * @author Fabien Potencier + * @author Tobias Schultze + * @author Arnaud Le Blanc + * @author Nicolas Grekas + */ +class CompiledUrlMatcherDumper extends MatcherDumper +{ + private $expressionLanguage; + private $signalingException; + + /** + * @var ExpressionFunctionProviderInterface[] + */ + private $expressionLanguageProviders = []; + + /** + * {@inheritdoc} + */ + public function dump(array $options = []) + { + return <<generateCompiledRoutes()}]; + +EOF; + } + + public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) + { + $this->expressionLanguageProviders[] = $provider; + } + + /** + * Generates the arrays for CompiledUrlMatcher's constructor. + */ + public function getCompiledRoutes(bool $forDump = false): array + { + // Group hosts by same-suffix, re-order when possible + $matchHost = false; + $routes = new StaticPrefixCollection(); + foreach ($this->getRoutes()->all() as $name => $route) { + if ($host = $route->getHost()) { + $matchHost = true; + $host = '/'.strtr(strrev($host), '}.{', '(/)'); + } + + $routes->addRoute($host ?: '/(.*)', [$name, $route]); + } + + if ($matchHost) { + $compiledRoutes = [true]; + $routes = $routes->populateCollection(new RouteCollection()); + } else { + $compiledRoutes = [false]; + $routes = $this->getRoutes(); + } + + list($staticRoutes, $dynamicRoutes) = $this->groupStaticRoutes($routes); + + $conditions = [null]; + $compiledRoutes[] = $this->compileStaticRoutes($staticRoutes, $conditions); + $chunkLimit = \count($dynamicRoutes); + + while (true) { + try { + $this->signalingException = new \RuntimeException('Compilation failed: regular expression is too large'); + $compiledRoutes = array_merge($compiledRoutes, $this->compileDynamicRoutes($dynamicRoutes, $matchHost, $chunkLimit, $conditions)); + + break; + } catch (\Exception $e) { + if (1 < $chunkLimit && $this->signalingException === $e) { + $chunkLimit = 1 + ($chunkLimit >> 1); + continue; + } + throw $e; + } + } + + if ($forDump) { + $compiledRoutes[2] = $compiledRoutes[4]; + } + unset($conditions[0]); + + if ($conditions) { + foreach ($conditions as $expression => $condition) { + $conditions[$expression] = "case {$condition}: return {$expression};"; + } + + $checkConditionCode = <<indent(implode("\n", $conditions), 3)} + } + } +EOF; + $compiledRoutes[4] = $forDump ? $checkConditionCode.",\n" : eval('return '.$checkConditionCode.';'); + } else { + $compiledRoutes[4] = $forDump ? " null, // \$checkCondition\n" : null; + } + + return $compiledRoutes; + } + + private function generateCompiledRoutes(): string + { + list($matchHost, $staticRoutes, $regexpCode, $dynamicRoutes, $checkConditionCode) = $this->getCompiledRoutes(true); + + $code = self::export($matchHost).', // $matchHost'."\n"; + + $code .= '[ // $staticRoutes'."\n"; + foreach ($staticRoutes as $path => $routes) { + $code .= sprintf(" %s => [\n", self::export($path)); + foreach ($routes as $route) { + $code .= sprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", ...array_map([__CLASS__, 'export'], $route)); + } + $code .= " ],\n"; + } + $code .= "],\n"; + + $code .= sprintf("[ // \$regexpList%s\n],\n", $regexpCode); + + $code .= '[ // $dynamicRoutes'."\n"; + foreach ($dynamicRoutes as $path => $routes) { + $code .= sprintf(" %s => [\n", self::export($path)); + foreach ($routes as $route) { + $code .= sprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", ...array_map([__CLASS__, 'export'], $route)); + } + $code .= " ],\n"; + } + $code .= "],\n"; + $code = preg_replace('/ => \[\n (\[.+?),\n \],/', ' => [$1],', $code); + + return $this->indent($code, 1).$checkConditionCode; + } + + /** + * Splits static routes from dynamic routes, so that they can be matched first, using a simple switch. + */ + private function groupStaticRoutes(RouteCollection $collection): array + { + $staticRoutes = $dynamicRegex = []; + $dynamicRoutes = new RouteCollection(); + + foreach ($collection->all() as $name => $route) { + $compiledRoute = $route->compile(); + $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); + $hostRegex = $compiledRoute->getHostRegex(); + $regex = $compiledRoute->getRegex(); + if ($hasTrailingSlash = '/' !== $route->getPath()) { + $pos = strrpos($regex, '$'); + $hasTrailingSlash = '/' === $regex[$pos - 1]; + $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); + } + + if (!$compiledRoute->getPathVariables()) { + $host = !$compiledRoute->getHostVariables() ? $route->getHost() : ''; + $url = $route->getPath(); + if ($hasTrailingSlash) { + $url = substr($url, 0, -1); + } + foreach ($dynamicRegex as list($hostRx, $rx, $prefix)) { + if (('' === $prefix || 0 === strpos($url, $prefix)) && (preg_match($rx, $url) || preg_match($rx, $url.'/')) && (!$host || !$hostRx || preg_match($hostRx, $host))) { + $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix]; + $dynamicRoutes->add($name, $route); + continue 2; + } + } + + $staticRoutes[$url][$name] = [$route, $hasTrailingSlash]; + } else { + $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix]; + $dynamicRoutes->add($name, $route); + } + } + + return [$staticRoutes, $dynamicRoutes]; + } + + /** + * Compiles static routes in a switch statement. + * + * Condition-less paths are put in a static array in the switch's default, with generic matching logic. + * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases. + * + * @throws \LogicException + */ + private function compileStaticRoutes(array $staticRoutes, array &$conditions): array + { + if (!$staticRoutes) { + return []; + } + $compiledRoutes = []; + + foreach ($staticRoutes as $url => $routes) { + $compiledRoutes[$url] = []; + foreach ($routes as $name => list($route, $hasTrailingSlash)) { + $compiledRoutes[$url][] = $this->compileRoute($route, $name, (!$route->compile()->getHostVariables() ? $route->getHost() : $route->compile()->getHostRegex()) ?: null, $hasTrailingSlash, false, $conditions); + } + } + + return $compiledRoutes; + } + + /** + * Compiles a regular expression followed by a switch statement to match dynamic routes. + * + * The regular expression matches both the host and the pathinfo at the same time. For stellar performance, + * it is built as a tree of patterns, with re-ordering logic to group same-prefix routes together when possible. + * + * Patterns are named so that we know which one matched (https://pcre.org/current/doc/html/pcre2syntax.html#SEC23). + * This name is used to "switch" to the additional logic required to match the final route. + * + * Condition-less paths are put in a static array in the switch's default, with generic matching logic. + * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases. + * + * Last but not least: + * - Because it is not possibe to mix unicode/non-unicode patterns in a single regexp, several of them can be generated. + * - The same regexp can be used several times when the logic in the switch rejects the match. When this happens, the + * matching-but-failing subpattern is blacklisted by replacing its name by "(*F)", which forces a failure-to-match. + * To ease this backlisting operation, the name of subpatterns is also the string offset where the replacement should occur. + */ + private function compileDynamicRoutes(RouteCollection $collection, bool $matchHost, int $chunkLimit, array &$conditions): array + { + if (!$collection->all()) { + return [[], [], '']; + } + $regexpList = []; + $code = ''; + $state = (object) [ + 'regexMark' => 0, + 'regex' => [], + 'routes' => [], + 'mark' => 0, + 'markTail' => 0, + 'hostVars' => [], + 'vars' => [], + ]; + $state->getVars = static function ($m) use ($state) { + if ('_route' === $m[1]) { + return '?:'; + } + + $state->vars[] = $m[1]; + + return ''; + }; + + $chunkSize = 0; + $prev = null; + $perModifiers = []; + foreach ($collection->all() as $name => $route) { + preg_match('#[a-zA-Z]*$#', $route->compile()->getRegex(), $rx); + if ($chunkLimit < ++$chunkSize || $prev !== $rx[0] && $route->compile()->getPathVariables()) { + $chunkSize = 1; + $routes = new RouteCollection(); + $perModifiers[] = [$rx[0], $routes]; + $prev = $rx[0]; + } + $routes->add($name, $route); + } + + foreach ($perModifiers as list($modifiers, $routes)) { + $prev = false; + $perHost = []; + foreach ($routes->all() as $name => $route) { + $regex = $route->compile()->getHostRegex(); + if ($prev !== $regex) { + $routes = new RouteCollection(); + $perHost[] = [$regex, $routes]; + $prev = $regex; + } + $routes->add($name, $route); + } + $prev = false; + $rx = '{^(?'; + $code .= "\n {$state->mark} => ".self::export($rx); + $startingMark = $state->mark; + $state->mark += \strlen($rx); + $state->regex = $rx; + + foreach ($perHost as list($hostRegex, $routes)) { + if ($matchHost) { + if ($hostRegex) { + preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $hostRegex, $rx); + $state->vars = []; + $hostRegex = '(?i:'.preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]).')\.'; + $state->hostVars = $state->vars; + } else { + $hostRegex = '(?:(?:[^./]*+\.)++)'; + $state->hostVars = []; + } + $state->mark += \strlen($rx = ($prev ? ')' : '')."|{$hostRegex}(?"); + $code .= "\n .".self::export($rx); + $state->regex .= $rx; + $prev = true; + } + + $tree = new StaticPrefixCollection(); + foreach ($routes->all() as $name => $route) { + preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $route->compile()->getRegex(), $rx); + + $state->vars = []; + $regex = preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]); + if ($hasTrailingSlash = '/' !== $regex && '/' === $regex[-1]) { + $regex = substr($regex, 0, -1); + } + $hasTrailingVar = (bool) preg_match('#\{\w+\}/?$#', $route->getPath()); + + $tree->addRoute($regex, [$name, $regex, $state->vars, $route, $hasTrailingSlash, $hasTrailingVar]); + } + + $code .= $this->compileStaticPrefixCollection($tree, $state, 0, $conditions); + } + if ($matchHost) { + $code .= "\n .')'"; + $state->regex .= ')'; + } + $rx = ")/?$}{$modifiers}"; + $code .= "\n .'{$rx}',"; + $state->regex .= $rx; + $state->markTail = 0; + + // if the regex is too large, throw a signaling exception to recompute with smaller chunk size + set_error_handler(function ($type, $message) { throw false !== strpos($message, $this->signalingException->getMessage()) ? $this->signalingException : new \ErrorException($message); }); + try { + preg_match($state->regex, ''); + } finally { + restore_error_handler(); + } + + $regexpList[$startingMark] = $state->regex; + } + + $state->routes[$state->mark][] = [null, null, null, null, false, false, 0]; + unset($state->getVars); + + return [$regexpList, $state->routes, $code]; + } + + /** + * Compiles a regexp tree of subpatterns that matches nested same-prefix routes. + * + * @param \stdClass $state A simple state object that keeps track of the progress of the compilation, + * and gathers the generated switch's "case" and "default" statements + */ + private function compileStaticPrefixCollection(StaticPrefixCollection $tree, \stdClass $state, int $prefixLen, array &$conditions): string + { + $code = ''; + $prevRegex = null; + $routes = $tree->getRoutes(); + + foreach ($routes as $i => $route) { + if ($route instanceof StaticPrefixCollection) { + $prevRegex = null; + $prefix = substr($route->getPrefix(), $prefixLen); + $state->mark += \strlen($rx = "|{$prefix}(?"); + $code .= "\n .".self::export($rx); + $state->regex .= $rx; + $code .= $this->indent($this->compileStaticPrefixCollection($route, $state, $prefixLen + \strlen($prefix), $conditions)); + $code .= "\n .')'"; + $state->regex .= ')'; + ++$state->markTail; + continue; + } + + list($name, $regex, $vars, $route, $hasTrailingSlash, $hasTrailingVar) = $route; + $compiledRoute = $route->compile(); + $vars = array_merge($state->hostVars, $vars); + + if ($compiledRoute->getRegex() === $prevRegex) { + $state->routes[$state->mark][] = $this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions); + continue; + } + + $state->mark += 3 + $state->markTail + \strlen($regex) - $prefixLen; + $state->markTail = 2 + \strlen($state->mark); + $rx = sprintf('|%s(*:%s)', substr($regex, $prefixLen), $state->mark); + $code .= "\n .".self::export($rx); + $state->regex .= $rx; + + $prevRegex = $compiledRoute->getRegex(); + $state->routes[$state->mark] = [$this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions)]; + } + + return $code; + } + + /** + * Compiles a single Route to PHP code used to match it against the path info. + */ + private function compileRoute(Route $route, string $name, $vars, bool $hasTrailingSlash, bool $hasTrailingVar, array &$conditions): array + { + $defaults = $route->getDefaults(); + + if (isset($defaults['_canonical_route'])) { + $name = $defaults['_canonical_route']; + unset($defaults['_canonical_route']); + } + + if ($condition = $route->getCondition()) { + $condition = $this->getExpressionLanguage()->compile($condition, ['context', 'request']); + $condition = $conditions[$condition] ?? $conditions[$condition] = (false !== strpos($condition, '$request') ? 1 : -1) * \count($conditions); + } else { + $condition = null; + } + + return [ + ['_route' => $name] + $defaults, + $vars, + array_flip($route->getMethods()) ?: null, + array_flip($route->getSchemes()) ?: null, + $hasTrailingSlash, + $hasTrailingVar, + $condition, + ]; + } + + private function getExpressionLanguage(): ExpressionLanguage + { + if (null === $this->expressionLanguage) { + if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { + throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); + } + $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); + } + + return $this->expressionLanguage; + } + + private function indent(string $code, int $level = 1): string + { + return preg_replace('/^./m', str_repeat(' ', $level).'$0', $code); + } + + /** + * @internal + */ + public static function export($value): string + { + if (null === $value) { + return 'null'; + } + if (!\is_array($value)) { + if (\is_object($value)) { + throw new \InvalidArgumentException('Symfony\Component\Routing\Route cannot contain objects.'); + } + + return str_replace("\n", '\'."\n".\'', var_export($value, true)); + } + if (!$value) { + return '[]'; + } + + $i = 0; + $export = '['; + + foreach ($value as $k => $v) { + if ($i === $k) { + ++$i; + } else { + $export .= self::export($k).' => '; + + if (\is_int($k) && $i < $k) { + $i = 1 + $k; + } + } + + $export .= self::export($v).', '; + } + + return substr_replace($export, ']', -2); + } +} diff --git a/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php b/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php new file mode 100644 index 0000000..c5980b1 --- /dev/null +++ b/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php @@ -0,0 +1,187 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher\Dumper; + +use Symfony\Component\Routing\Exception\MethodNotAllowedException; +use Symfony\Component\Routing\Exception\NoConfigurationException; +use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; +use Symfony\Component\Routing\RequestContext; + +/** + * @author Nicolas Grekas + * + * @internal + * + * @property RequestContext $context + */ +trait CompiledUrlMatcherTrait +{ + private $matchHost = false; + private $staticRoutes = []; + private $regexpList = []; + private $dynamicRoutes = []; + private $checkCondition; + + public function match(string $pathinfo): array + { + $allow = $allowSchemes = []; + if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) { + return $ret; + } + if ($allow) { + throw new MethodNotAllowedException(array_keys($allow)); + } + if (!$this instanceof RedirectableUrlMatcherInterface) { + throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); + } + if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], true)) { + // no-op + } elseif ($allowSchemes) { + redirect_scheme: + $scheme = $this->context->getScheme(); + $this->context->setScheme(key($allowSchemes)); + try { + if ($ret = $this->doMatch($pathinfo)) { + return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret; + } + } finally { + $this->context->setScheme($scheme); + } + } elseif ('/' !== $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') { + $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo.'/' : $trimmedPathinfo; + if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) { + return $this->redirect($pathinfo, $ret['_route']) + $ret; + } + if ($allowSchemes) { + goto redirect_scheme; + } + } + + throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); + } + + private function doMatch(string $pathinfo, array &$allow = [], array &$allowSchemes = []): array + { + $allow = $allowSchemes = []; + $pathinfo = rawurldecode($pathinfo) ?: '/'; + $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; + $context = $this->context; + $requestMethod = $canonicalMethod = $context->getMethod(); + + if ($this->matchHost) { + $host = strtolower($context->getHost()); + } + + if ('HEAD' === $requestMethod) { + $canonicalMethod = 'GET'; + } + $supportsRedirections = 'GET' === $canonicalMethod && $this instanceof RedirectableUrlMatcherInterface; + + foreach ($this->staticRoutes[$trimmedPathinfo] ?? [] as list($ret, $requiredHost, $requiredMethods, $requiredSchemes, $hasTrailingSlash, , $condition)) { + if ($condition && !($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { + continue; + } + + if ($requiredHost) { + if ('#' !== $requiredHost[0] ? $requiredHost !== $host : !preg_match($requiredHost, $host, $hostMatches)) { + continue; + } + if ('#' === $requiredHost[0] && $hostMatches) { + $hostMatches['_route'] = $ret['_route']; + $ret = $this->mergeDefaults($hostMatches, $ret); + } + } + + if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { + if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) { + return $allow = $allowSchemes = []; + } + continue; + } + + $hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]); + if ($hasRequiredScheme && $requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) { + $allow += $requiredMethods; + continue; + } + + if (!$hasRequiredScheme) { + $allowSchemes += $requiredSchemes; + continue; + } + + return $ret; + } + + $matchedPathinfo = $this->matchHost ? $host.'.'.$pathinfo : $pathinfo; + + foreach ($this->regexpList as $offset => $regex) { + while (preg_match($regex, $matchedPathinfo, $matches)) { + foreach ($this->dynamicRoutes[$m = (int) $matches['MARK']] as list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar, $condition)) { + if (null !== $condition) { + if (0 === $condition) { // marks the last route in the regexp + continue 3; + } + if (!($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { + continue; + } + } + + $hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar; + + if ($hasTrailingVar && ($hasTrailingSlash || (null === $n = $matches[\count($vars)] ?? null) || '/' !== ($n[-1] ?? '/')) && preg_match($regex, $this->matchHost ? $host.'.'.$trimmedPathinfo : $trimmedPathinfo, $n) && $m === (int) $n['MARK']) { + if ($hasTrailingSlash) { + $matches = $n; + } else { + $hasTrailingVar = false; + } + } + + if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { + if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) { + return $allow = $allowSchemes = []; + } + continue; + } + + foreach ($vars as $i => $v) { + if (isset($matches[1 + $i])) { + $ret[$v] = $matches[1 + $i]; + } + } + + if ($requiredSchemes && !isset($requiredSchemes[$context->getScheme()])) { + $allowSchemes += $requiredSchemes; + continue; + } + + if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) { + $allow += $requiredMethods; + continue; + } + + return $ret; + } + + $regex = substr_replace($regex, 'F', $m - $offset, 1 + \strlen($m)); + $offset += \strlen($m); + } + } + + if ('/' === $pathinfo && !$allow && !$allowSchemes) { + throw new NoConfigurationException(); + } + + return []; + } +} diff --git a/vendor/symfony/routing/Matcher/Dumper/MatcherDumper.php b/vendor/symfony/routing/Matcher/Dumper/MatcherDumper.php new file mode 100644 index 0000000..ea51ab4 --- /dev/null +++ b/vendor/symfony/routing/Matcher/Dumper/MatcherDumper.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher\Dumper; + +use Symfony\Component\Routing\RouteCollection; + +/** + * MatcherDumper is the abstract class for all built-in matcher dumpers. + * + * @author Fabien Potencier + */ +abstract class MatcherDumper implements MatcherDumperInterface +{ + private $routes; + + public function __construct(RouteCollection $routes) + { + $this->routes = $routes; + } + + /** + * {@inheritdoc} + */ + public function getRoutes() + { + return $this->routes; + } +} diff --git a/vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php b/vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php new file mode 100644 index 0000000..34aad92 --- /dev/null +++ b/vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher\Dumper; + +use Symfony\Component\Routing\RouteCollection; + +/** + * MatcherDumperInterface is the interface that all matcher dumper classes must implement. + * + * @author Fabien Potencier + */ +interface MatcherDumperInterface +{ + /** + * Dumps a set of routes to a string representation of executable code + * that can then be used to match a request against these routes. + * + * @return string Executable code + */ + public function dump(array $options = []); + + /** + * Gets the routes to dump. + * + * @return RouteCollection A RouteCollection instance + */ + public function getRoutes(); +} diff --git a/vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php b/vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php new file mode 100644 index 0000000..65b6c07 --- /dev/null +++ b/vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php @@ -0,0 +1,202 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher\Dumper; + +use Symfony\Component\Routing\RouteCollection; + +/** + * Prefix tree of routes preserving routes order. + * + * @author Frank de Jonge + * @author Nicolas Grekas + * + * @internal + */ +class StaticPrefixCollection +{ + private $prefix; + + /** + * @var string[] + */ + private $staticPrefixes = []; + + /** + * @var string[] + */ + private $prefixes = []; + + /** + * @var array[]|self[] + */ + private $items = []; + + public function __construct(string $prefix = '/') + { + $this->prefix = $prefix; + } + + public function getPrefix(): string + { + return $this->prefix; + } + + /** + * @return array[]|self[] + */ + public function getRoutes(): array + { + return $this->items; + } + + /** + * Adds a route to a group. + * + * @param array|self $route + */ + public function addRoute(string $prefix, $route) + { + list($prefix, $staticPrefix) = $this->getCommonPrefix($prefix, $prefix); + + for ($i = \count($this->items) - 1; 0 <= $i; --$i) { + $item = $this->items[$i]; + + list($commonPrefix, $commonStaticPrefix) = $this->getCommonPrefix($prefix, $this->prefixes[$i]); + + if ($this->prefix === $commonPrefix) { + // the new route and a previous one have no common prefix, let's see if they are exclusive to each others + + if ($this->prefix !== $staticPrefix && $this->prefix !== $this->staticPrefixes[$i]) { + // the new route and the previous one have exclusive static prefixes + continue; + } + + if ($this->prefix === $staticPrefix && $this->prefix === $this->staticPrefixes[$i]) { + // the new route and the previous one have no static prefix + break; + } + + if ($this->prefixes[$i] !== $this->staticPrefixes[$i] && $this->prefix === $this->staticPrefixes[$i]) { + // the previous route is non-static and has no static prefix + break; + } + + if ($prefix !== $staticPrefix && $this->prefix === $staticPrefix) { + // the new route is non-static and has no static prefix + break; + } + + continue; + } + + if ($item instanceof self && $this->prefixes[$i] === $commonPrefix) { + // the new route is a child of a previous one, let's nest it + $item->addRoute($prefix, $route); + } else { + // the new route and a previous one have a common prefix, let's merge them + $child = new self($commonPrefix); + list($child->prefixes[0], $child->staticPrefixes[0]) = $child->getCommonPrefix($this->prefixes[$i], $this->prefixes[$i]); + list($child->prefixes[1], $child->staticPrefixes[1]) = $child->getCommonPrefix($prefix, $prefix); + $child->items = [$this->items[$i], $route]; + + $this->staticPrefixes[$i] = $commonStaticPrefix; + $this->prefixes[$i] = $commonPrefix; + $this->items[$i] = $child; + } + + return; + } + + // No optimised case was found, in this case we simple add the route for possible + // grouping when new routes are added. + $this->staticPrefixes[] = $staticPrefix; + $this->prefixes[] = $prefix; + $this->items[] = $route; + } + + /** + * Linearizes back a set of nested routes into a collection. + */ + public function populateCollection(RouteCollection $routes): RouteCollection + { + foreach ($this->items as $route) { + if ($route instanceof self) { + $route->populateCollection($routes); + } else { + $routes->add(...$route); + } + } + + return $routes; + } + + /** + * Gets the full and static common prefixes between two route patterns. + * + * The static prefix stops at last at the first opening bracket. + */ + private function getCommonPrefix(string $prefix, string $anotherPrefix): array + { + $baseLength = \strlen($this->prefix); + $end = min(\strlen($prefix), \strlen($anotherPrefix)); + $staticLength = null; + set_error_handler([__CLASS__, 'handleError']); + + for ($i = $baseLength; $i < $end && $prefix[$i] === $anotherPrefix[$i]; ++$i) { + if ('(' === $prefix[$i]) { + $staticLength = $staticLength ?? $i; + for ($j = 1 + $i, $n = 1; $j < $end && 0 < $n; ++$j) { + if ($prefix[$j] !== $anotherPrefix[$j]) { + break 2; + } + if ('(' === $prefix[$j]) { + ++$n; + } elseif (')' === $prefix[$j]) { + --$n; + } elseif ('\\' === $prefix[$j] && (++$j === $end || $prefix[$j] !== $anotherPrefix[$j])) { + --$j; + break; + } + } + if (0 < $n) { + break; + } + if (('?' === ($prefix[$j] ?? '') || '?' === ($anotherPrefix[$j] ?? '')) && ($prefix[$j] ?? '') !== ($anotherPrefix[$j] ?? '')) { + break; + } + $subPattern = substr($prefix, $i, $j - $i); + if ($prefix !== $anotherPrefix && !preg_match('/^\(\[[^\]]++\]\+\+\)$/', $subPattern) && !preg_match('{(?> 6) && preg_match('//u', $prefix.' '.$anotherPrefix)) { + do { + // Prevent cutting in the middle of an UTF-8 characters + --$i; + } while (0b10 === (\ord($prefix[$i]) >> 6)); + } + + return [substr($prefix, 0, $i), substr($prefix, 0, $staticLength ?? $i)]; + } + + public static function handleError($type, $msg) + { + return false !== strpos($msg, 'Compilation failed: lookbehind assertion is not fixed length'); + } +} diff --git a/vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php b/vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php new file mode 100644 index 0000000..3cd7c81 --- /dev/null +++ b/vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +use Symfony\Component\Routing\Exception\ExceptionInterface; +use Symfony\Component\Routing\Exception\ResourceNotFoundException; + +/** + * @author Fabien Potencier + */ +abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface +{ + /** + * {@inheritdoc} + */ + public function match(string $pathinfo) + { + try { + return parent::match($pathinfo); + } catch (ResourceNotFoundException $e) { + if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], true)) { + throw $e; + } + + if ($this->allowSchemes) { + redirect_scheme: + $scheme = $this->context->getScheme(); + $this->context->setScheme(current($this->allowSchemes)); + try { + $ret = parent::match($pathinfo); + + return $this->redirect($pathinfo, $ret['_route'] ?? null, $this->context->getScheme()) + $ret; + } catch (ExceptionInterface $e2) { + throw $e; + } finally { + $this->context->setScheme($scheme); + } + } elseif ('/' === $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') { + throw $e; + } else { + try { + $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo.'/' : $trimmedPathinfo; + $ret = parent::match($pathinfo); + + return $this->redirect($pathinfo, $ret['_route'] ?? null) + $ret; + } catch (ExceptionInterface $e2) { + if ($this->allowSchemes) { + goto redirect_scheme; + } + throw $e; + } + } + } + } +} diff --git a/vendor/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php b/vendor/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php new file mode 100644 index 0000000..144945d --- /dev/null +++ b/vendor/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +/** + * RedirectableUrlMatcherInterface knows how to redirect the user. + * + * @author Fabien Potencier + */ +interface RedirectableUrlMatcherInterface +{ + /** + * Redirects the user to another URL. + * + * @param string $path The path info to redirect to + * @param string $route The route name that matched + * @param string|null $scheme The URL scheme (null to keep the current one) + * + * @return array An array of parameters + */ + public function redirect(string $path, string $route, string $scheme = null); +} diff --git a/vendor/symfony/routing/Matcher/RequestMatcherInterface.php b/vendor/symfony/routing/Matcher/RequestMatcherInterface.php new file mode 100644 index 0000000..0c193ff --- /dev/null +++ b/vendor/symfony/routing/Matcher/RequestMatcherInterface.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Exception\MethodNotAllowedException; +use Symfony\Component\Routing\Exception\NoConfigurationException; +use Symfony\Component\Routing\Exception\ResourceNotFoundException; + +/** + * RequestMatcherInterface is the interface that all request matcher classes must implement. + * + * @author Fabien Potencier + */ +interface RequestMatcherInterface +{ + /** + * Tries to match a request with a set of routes. + * + * If the matcher can not find information, it must throw one of the exceptions documented + * below. + * + * @return array An array of parameters + * + * @throws NoConfigurationException If no routing configuration could be found + * @throws ResourceNotFoundException If no matching resource could be found + * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed + */ + public function matchRequest(Request $request); +} diff --git a/vendor/symfony/routing/Matcher/TraceableUrlMatcher.php b/vendor/symfony/routing/Matcher/TraceableUrlMatcher.php new file mode 100644 index 0000000..627cd02 --- /dev/null +++ b/vendor/symfony/routing/Matcher/TraceableUrlMatcher.php @@ -0,0 +1,164 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Exception\ExceptionInterface; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * TraceableUrlMatcher helps debug path info matching by tracing the match. + * + * @author Fabien Potencier + */ +class TraceableUrlMatcher extends UrlMatcher +{ + const ROUTE_DOES_NOT_MATCH = 0; + const ROUTE_ALMOST_MATCHES = 1; + const ROUTE_MATCHES = 2; + + protected $traces; + + public function getTraces(string $pathinfo) + { + $this->traces = []; + + try { + $this->match($pathinfo); + } catch (ExceptionInterface $e) { + } + + return $this->traces; + } + + public function getTracesForRequest(Request $request) + { + $this->request = $request; + $traces = $this->getTraces($request->getPathInfo()); + $this->request = null; + + return $traces; + } + + protected function matchCollection(string $pathinfo, RouteCollection $routes) + { + // HEAD and GET are equivalent as per RFC + if ('HEAD' === $method = $this->context->getMethod()) { + $method = 'GET'; + } + $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface; + $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; + + foreach ($routes as $name => $route) { + $compiledRoute = $route->compile(); + $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); + $requiredMethods = $route->getMethods(); + + // check the static prefix of the URL first. Only use the more expensive preg_match when it matches + if ('' !== $staticPrefix && 0 !== strpos($trimmedPathinfo, $staticPrefix)) { + $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); + continue; + } + $regex = $compiledRoute->getRegex(); + + $pos = strrpos($regex, '$'); + $hasTrailingSlash = '/' === $regex[$pos - 1]; + $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); + + if (!preg_match($regex, $pathinfo, $matches)) { + // does it match without any requirements? + $r = new Route($route->getPath(), $route->getDefaults(), [], $route->getOptions()); + $cr = $r->compile(); + if (!preg_match($cr->getRegex(), $pathinfo)) { + $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); + + continue; + } + + foreach ($route->getRequirements() as $n => $regex) { + $r = new Route($route->getPath(), $route->getDefaults(), [$n => $regex], $route->getOptions()); + $cr = $r->compile(); + + if (\in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) { + $this->addTrace(sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route); + + continue 2; + } + } + + continue; + } + + $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); + + if ($hasTrailingVar && ($hasTrailingSlash || (null === $m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) { + if ($hasTrailingSlash) { + $matches = $m; + } else { + $hasTrailingVar = false; + } + } + + $hostMatches = []; + if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { + $this->addTrace(sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route); + continue; + } + + $status = $this->handleRouteRequirements($pathinfo, $name, $route); + + if (self::REQUIREMENT_MISMATCH === $status[0]) { + $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $route->getCondition()), self::ROUTE_ALMOST_MATCHES, $name, $route); + continue; + } + + if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { + if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) { + $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); + + return $this->allow = $this->allowSchemes = []; + } + $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); + continue; + } + + if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) { + $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes()); + $this->addTrace(sprintf('Scheme "%s" does not match any of the required schemes (%s)', $this->context->getScheme(), implode(', ', $route->getSchemes())), self::ROUTE_ALMOST_MATCHES, $name, $route); + continue; + } + + if ($requiredMethods && !\in_array($method, $requiredMethods)) { + $this->allow = array_merge($this->allow, $requiredMethods); + $this->addTrace(sprintf('Method "%s" does not match any of the required methods (%s)', $this->context->getMethod(), implode(', ', $requiredMethods)), self::ROUTE_ALMOST_MATCHES, $name, $route); + continue; + } + + $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); + + return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : [])); + } + + return []; + } + + private function addTrace(string $log, int $level = self::ROUTE_DOES_NOT_MATCH, string $name = null, Route $route = null) + { + $this->traces[] = [ + 'log' => $log, + 'name' => $name, + 'level' => $level, + 'path' => null !== $route ? $route->getPath() : null, + ]; + } +} diff --git a/vendor/symfony/routing/Matcher/UrlMatcher.php b/vendor/symfony/routing/Matcher/UrlMatcher.php new file mode 100644 index 0000000..4c76231 --- /dev/null +++ b/vendor/symfony/routing/Matcher/UrlMatcher.php @@ -0,0 +1,279 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Exception\MethodNotAllowedException; +use Symfony\Component\Routing\Exception\NoConfigurationException; +use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * UrlMatcher matches URL based on a set of routes. + * + * @author Fabien Potencier + */ +class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface +{ + const REQUIREMENT_MATCH = 0; + const REQUIREMENT_MISMATCH = 1; + const ROUTE_MATCH = 2; + + /** @var RequestContext */ + protected $context; + + /** + * Collects HTTP methods that would be allowed for the request. + */ + protected $allow = []; + + /** + * Collects URI schemes that would be allowed for the request. + * + * @internal + */ + protected $allowSchemes = []; + + protected $routes; + protected $request; + protected $expressionLanguage; + + /** + * @var ExpressionFunctionProviderInterface[] + */ + protected $expressionLanguageProviders = []; + + public function __construct(RouteCollection $routes, RequestContext $context) + { + $this->routes = $routes; + $this->context = $context; + } + + /** + * {@inheritdoc} + */ + public function setContext(RequestContext $context) + { + $this->context = $context; + } + + /** + * {@inheritdoc} + */ + public function getContext() + { + return $this->context; + } + + /** + * {@inheritdoc} + */ + public function match(string $pathinfo) + { + $this->allow = $this->allowSchemes = []; + + if ($ret = $this->matchCollection(rawurldecode($pathinfo) ?: '/', $this->routes)) { + return $ret; + } + + if ('/' === $pathinfo && !$this->allow && !$this->allowSchemes) { + throw new NoConfigurationException(); + } + + throw 0 < \count($this->allow) ? new MethodNotAllowedException(array_unique($this->allow)) : new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); + } + + /** + * {@inheritdoc} + */ + public function matchRequest(Request $request) + { + $this->request = $request; + + $ret = $this->match($request->getPathInfo()); + + $this->request = null; + + return $ret; + } + + public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) + { + $this->expressionLanguageProviders[] = $provider; + } + + /** + * Tries to match a URL with a set of routes. + * + * @param string $pathinfo The path info to be parsed + * + * @return array An array of parameters + * + * @throws NoConfigurationException If no routing configuration could be found + * @throws ResourceNotFoundException If the resource could not be found + * @throws MethodNotAllowedException If the resource was found but the request method is not allowed + */ + protected function matchCollection(string $pathinfo, RouteCollection $routes) + { + // HEAD and GET are equivalent as per RFC + if ('HEAD' === $method = $this->context->getMethod()) { + $method = 'GET'; + } + $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface; + $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; + + foreach ($routes as $name => $route) { + $compiledRoute = $route->compile(); + $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); + $requiredMethods = $route->getMethods(); + + // check the static prefix of the URL first. Only use the more expensive preg_match when it matches + if ('' !== $staticPrefix && 0 !== strpos($trimmedPathinfo, $staticPrefix)) { + continue; + } + $regex = $compiledRoute->getRegex(); + + $pos = strrpos($regex, '$'); + $hasTrailingSlash = '/' === $regex[$pos - 1]; + $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); + + if (!preg_match($regex, $pathinfo, $matches)) { + continue; + } + + $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); + + if ($hasTrailingVar && ($hasTrailingSlash || (null === $m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) { + if ($hasTrailingSlash) { + $matches = $m; + } else { + $hasTrailingVar = false; + } + } + + $hostMatches = []; + if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { + continue; + } + + $status = $this->handleRouteRequirements($pathinfo, $name, $route); + + if (self::REQUIREMENT_MISMATCH === $status[0]) { + continue; + } + + if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { + if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) { + return $this->allow = $this->allowSchemes = []; + } + continue; + } + + if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) { + $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes()); + continue; + } + + if ($requiredMethods && !\in_array($method, $requiredMethods)) { + $this->allow = array_merge($this->allow, $requiredMethods); + continue; + } + + return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : [])); + } + + return []; + } + + /** + * Returns an array of values to use as request attributes. + * + * As this method requires the Route object, it is not available + * in matchers that do not have access to the matched Route instance + * (like the PHP and Apache matcher dumpers). + * + * @return array An array of parameters + */ + protected function getAttributes(Route $route, string $name, array $attributes) + { + $defaults = $route->getDefaults(); + if (isset($defaults['_canonical_route'])) { + $name = $defaults['_canonical_route']; + unset($defaults['_canonical_route']); + } + $attributes['_route'] = $name; + + return $this->mergeDefaults($attributes, $defaults); + } + + /** + * Handles specific route requirements. + * + * @return array The first element represents the status, the second contains additional information + */ + protected function handleRouteRequirements(string $pathinfo, string $name, Route $route) + { + // expression condition + if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), ['context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)])) { + return [self::REQUIREMENT_MISMATCH, null]; + } + + return [self::REQUIREMENT_MATCH, null]; + } + + /** + * Get merged default parameters. + * + * @return array Merged default parameters + */ + protected function mergeDefaults(array $params, array $defaults) + { + foreach ($params as $key => $value) { + if (!\is_int($key) && null !== $value) { + $defaults[$key] = $value; + } + } + + return $defaults; + } + + protected function getExpressionLanguage() + { + if (null === $this->expressionLanguage) { + if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { + throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); + } + $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); + } + + return $this->expressionLanguage; + } + + /** + * @internal + */ + protected function createRequest(string $pathinfo): ?Request + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + return null; + } + + return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo, $this->context->getMethod(), $this->context->getParameters(), [], [], [ + 'SCRIPT_FILENAME' => $this->context->getBaseUrl(), + 'SCRIPT_NAME' => $this->context->getBaseUrl(), + ]); + } +} diff --git a/vendor/symfony/routing/Matcher/UrlMatcherInterface.php b/vendor/symfony/routing/Matcher/UrlMatcherInterface.php new file mode 100644 index 0000000..24f23e3 --- /dev/null +++ b/vendor/symfony/routing/Matcher/UrlMatcherInterface.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +use Symfony\Component\Routing\Exception\MethodNotAllowedException; +use Symfony\Component\Routing\Exception\NoConfigurationException; +use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\RequestContextAwareInterface; + +/** + * UrlMatcherInterface is the interface that all URL matcher classes must implement. + * + * @author Fabien Potencier + */ +interface UrlMatcherInterface extends RequestContextAwareInterface +{ + /** + * Tries to match a URL path with a set of routes. + * + * If the matcher can not find information, it must throw one of the exceptions documented + * below. + * + * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded) + * + * @return array An array of parameters + * + * @throws NoConfigurationException If no routing configuration could be found + * @throws ResourceNotFoundException If the resource could not be found + * @throws MethodNotAllowedException If the resource was found but the request method is not allowed + */ + public function match(string $pathinfo); +} diff --git a/vendor/symfony/routing/README.md b/vendor/symfony/routing/README.md new file mode 100644 index 0000000..88fb1fd --- /dev/null +++ b/vendor/symfony/routing/README.md @@ -0,0 +1,13 @@ +Routing Component +================= + +The Routing component maps an HTTP request to a set of configuration variables. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/routing/index.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/routing/RequestContext.php b/vendor/symfony/routing/RequestContext.php new file mode 100644 index 0000000..cb655f4 --- /dev/null +++ b/vendor/symfony/routing/RequestContext.php @@ -0,0 +1,305 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +use Symfony\Component\HttpFoundation\Request; + +/** + * Holds information about the current request. + * + * This class implements a fluent interface. + * + * @author Fabien Potencier + * @author Tobias Schultze + */ +class RequestContext +{ + private $baseUrl; + private $pathInfo; + private $method; + private $host; + private $scheme; + private $httpPort; + private $httpsPort; + private $queryString; + private $parameters = []; + + public function __construct(string $baseUrl = '', string $method = 'GET', string $host = 'localhost', string $scheme = 'http', int $httpPort = 80, int $httpsPort = 443, string $path = '/', string $queryString = '') + { + $this->setBaseUrl($baseUrl); + $this->setMethod($method); + $this->setHost($host); + $this->setScheme($scheme); + $this->setHttpPort($httpPort); + $this->setHttpsPort($httpsPort); + $this->setPathInfo($path); + $this->setQueryString($queryString); + } + + /** + * Updates the RequestContext information based on a HttpFoundation Request. + * + * @return $this + */ + public function fromRequest(Request $request) + { + $this->setBaseUrl($request->getBaseUrl()); + $this->setPathInfo($request->getPathInfo()); + $this->setMethod($request->getMethod()); + $this->setHost($request->getHost()); + $this->setScheme($request->getScheme()); + $this->setHttpPort($request->isSecure() || null === $request->getPort() ? $this->httpPort : $request->getPort()); + $this->setHttpsPort($request->isSecure() && null !== $request->getPort() ? $request->getPort() : $this->httpsPort); + $this->setQueryString($request->server->get('QUERY_STRING', '')); + + return $this; + } + + /** + * Gets the base URL. + * + * @return string The base URL + */ + public function getBaseUrl() + { + return $this->baseUrl; + } + + /** + * Sets the base URL. + * + * @return $this + */ + public function setBaseUrl(string $baseUrl) + { + $this->baseUrl = $baseUrl; + + return $this; + } + + /** + * Gets the path info. + * + * @return string The path info + */ + public function getPathInfo() + { + return $this->pathInfo; + } + + /** + * Sets the path info. + * + * @return $this + */ + public function setPathInfo(string $pathInfo) + { + $this->pathInfo = $pathInfo; + + return $this; + } + + /** + * Gets the HTTP method. + * + * The method is always an uppercased string. + * + * @return string The HTTP method + */ + public function getMethod() + { + return $this->method; + } + + /** + * Sets the HTTP method. + * + * @return $this + */ + public function setMethod(string $method) + { + $this->method = strtoupper($method); + + return $this; + } + + /** + * Gets the HTTP host. + * + * The host is always lowercased because it must be treated case-insensitive. + * + * @return string The HTTP host + */ + public function getHost() + { + return $this->host; + } + + /** + * Sets the HTTP host. + * + * @return $this + */ + public function setHost(string $host) + { + $this->host = strtolower($host); + + return $this; + } + + /** + * Gets the HTTP scheme. + * + * @return string The HTTP scheme + */ + public function getScheme() + { + return $this->scheme; + } + + /** + * Sets the HTTP scheme. + * + * @return $this + */ + public function setScheme(string $scheme) + { + $this->scheme = strtolower($scheme); + + return $this; + } + + /** + * Gets the HTTP port. + * + * @return int The HTTP port + */ + public function getHttpPort() + { + return $this->httpPort; + } + + /** + * Sets the HTTP port. + * + * @return $this + */ + public function setHttpPort(int $httpPort) + { + $this->httpPort = $httpPort; + + return $this; + } + + /** + * Gets the HTTPS port. + * + * @return int The HTTPS port + */ + public function getHttpsPort() + { + return $this->httpsPort; + } + + /** + * Sets the HTTPS port. + * + * @return $this + */ + public function setHttpsPort(int $httpsPort) + { + $this->httpsPort = $httpsPort; + + return $this; + } + + /** + * Gets the query string. + * + * @return string The query string without the "?" + */ + public function getQueryString() + { + return $this->queryString; + } + + /** + * Sets the query string. + * + * @return $this + */ + public function setQueryString(?string $queryString) + { + // string cast to be fault-tolerant, accepting null + $this->queryString = (string) $queryString; + + return $this; + } + + /** + * Returns the parameters. + * + * @return array The parameters + */ + public function getParameters() + { + return $this->parameters; + } + + /** + * Sets the parameters. + * + * @param array $parameters The parameters + * + * @return $this + */ + public function setParameters(array $parameters) + { + $this->parameters = $parameters; + + return $this; + } + + /** + * Gets a parameter value. + * + * @return mixed The parameter value or null if nonexistent + */ + public function getParameter(string $name) + { + return isset($this->parameters[$name]) ? $this->parameters[$name] : null; + } + + /** + * Checks if a parameter value is set for the given parameter. + * + * @return bool True if the parameter value is set, false otherwise + */ + public function hasParameter(string $name) + { + return \array_key_exists($name, $this->parameters); + } + + /** + * Sets a parameter value. + * + * @param mixed $parameter The parameter value + * + * @return $this + */ + public function setParameter(string $name, $parameter) + { + $this->parameters[$name] = $parameter; + + return $this; + } +} diff --git a/vendor/symfony/routing/RequestContextAwareInterface.php b/vendor/symfony/routing/RequestContextAwareInterface.php new file mode 100644 index 0000000..df5b9fc --- /dev/null +++ b/vendor/symfony/routing/RequestContextAwareInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +interface RequestContextAwareInterface +{ + /** + * Sets the request context. + */ + public function setContext(RequestContext $context); + + /** + * Gets the request context. + * + * @return RequestContext The context + */ + public function getContext(); +} diff --git a/vendor/symfony/routing/Route.php b/vendor/symfony/routing/Route.php new file mode 100644 index 0000000..3b4d04c --- /dev/null +++ b/vendor/symfony/routing/Route.php @@ -0,0 +1,547 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +/** + * A Route describes a route and its parameters. + * + * @author Fabien Potencier + * @author Tobias Schultze + */ +class Route implements \Serializable +{ + private $path = '/'; + private $host = ''; + private $schemes = []; + private $methods = []; + private $defaults = []; + private $requirements = []; + private $options = []; + private $condition = ''; + + /** + * @var CompiledRoute|null + */ + private $compiled; + + /** + * Constructor. + * + * Available options: + * + * * compiler_class: A class name able to compile this route instance (RouteCompiler by default) + * * utf8: Whether UTF-8 matching is enforced ot not + * + * @param string $path The path pattern to match + * @param array $defaults An array of default parameter values + * @param array $requirements An array of requirements for parameters (regexes) + * @param array $options An array of options + * @param string|null $host The host pattern to match + * @param string|string[] $schemes A required URI scheme or an array of restricted schemes + * @param string|string[] $methods A required HTTP method or an array of restricted methods + * @param string|null $condition A condition that should evaluate to true for the route to match + */ + public function __construct(string $path, array $defaults = [], array $requirements = [], array $options = [], ?string $host = '', $schemes = [], $methods = [], ?string $condition = '') + { + $this->setPath($path); + $this->addDefaults($defaults); + $this->addRequirements($requirements); + $this->setOptions($options); + $this->setHost($host); + $this->setSchemes($schemes); + $this->setMethods($methods); + $this->setCondition($condition); + } + + public function __serialize(): array + { + return [ + 'path' => $this->path, + 'host' => $this->host, + 'defaults' => $this->defaults, + 'requirements' => $this->requirements, + 'options' => $this->options, + 'schemes' => $this->schemes, + 'methods' => $this->methods, + 'condition' => $this->condition, + 'compiled' => $this->compiled, + ]; + } + + /** + * @internal + */ + final public function serialize(): string + { + return serialize($this->__serialize()); + } + + public function __unserialize(array $data): void + { + $this->path = $data['path']; + $this->host = $data['host']; + $this->defaults = $data['defaults']; + $this->requirements = $data['requirements']; + $this->options = $data['options']; + $this->schemes = $data['schemes']; + $this->methods = $data['methods']; + + if (isset($data['condition'])) { + $this->condition = $data['condition']; + } + if (isset($data['compiled'])) { + $this->compiled = $data['compiled']; + } + } + + /** + * @internal + */ + final public function unserialize($serialized) + { + $this->__unserialize(unserialize($serialized)); + } + + /** + * Returns the pattern for the path. + * + * @return string The path pattern + */ + public function getPath() + { + return $this->path; + } + + /** + * Sets the pattern for the path. + * + * This method implements a fluent interface. + * + * @return $this + */ + public function setPath(string $pattern) + { + if (false !== strpbrk($pattern, '?<')) { + $pattern = preg_replace_callback('#\{(\w++)(<.*?>)?(\?[^\}]*+)?\}#', function ($m) { + if (isset($m[3][0])) { + $this->setDefault($m[1], '?' !== $m[3] ? substr($m[3], 1) : null); + } + if (isset($m[2][0])) { + $this->setRequirement($m[1], substr($m[2], 1, -1)); + } + + return '{'.$m[1].'}'; + }, $pattern); + } + + // A pattern must start with a slash and must not have multiple slashes at the beginning because the + // generated path for this route would be confused with a network path, e.g. '//domain.com/path'. + $this->path = '/'.ltrim(trim($pattern), '/'); + $this->compiled = null; + + return $this; + } + + /** + * Returns the pattern for the host. + * + * @return string The host pattern + */ + public function getHost() + { + return $this->host; + } + + /** + * Sets the pattern for the host. + * + * This method implements a fluent interface. + * + * @return $this + */ + public function setHost(?string $pattern) + { + $this->host = (string) $pattern; + $this->compiled = null; + + return $this; + } + + /** + * Returns the lowercased schemes this route is restricted to. + * So an empty array means that any scheme is allowed. + * + * @return string[] The schemes + */ + public function getSchemes() + { + return $this->schemes; + } + + /** + * Sets the schemes (e.g. 'https') this route is restricted to. + * So an empty array means that any scheme is allowed. + * + * This method implements a fluent interface. + * + * @param string|string[] $schemes The scheme or an array of schemes + * + * @return $this + */ + public function setSchemes($schemes) + { + $this->schemes = array_map('strtolower', (array) $schemes); + $this->compiled = null; + + return $this; + } + + /** + * Checks if a scheme requirement has been set. + * + * @return bool true if the scheme requirement exists, otherwise false + */ + public function hasScheme(string $scheme) + { + return \in_array(strtolower($scheme), $this->schemes, true); + } + + /** + * Returns the uppercased HTTP methods this route is restricted to. + * So an empty array means that any method is allowed. + * + * @return string[] The methods + */ + public function getMethods() + { + return $this->methods; + } + + /** + * Sets the HTTP methods (e.g. 'POST') this route is restricted to. + * So an empty array means that any method is allowed. + * + * This method implements a fluent interface. + * + * @param string|string[] $methods The method or an array of methods + * + * @return $this + */ + public function setMethods($methods) + { + $this->methods = array_map('strtoupper', (array) $methods); + $this->compiled = null; + + return $this; + } + + /** + * Returns the options. + * + * @return array The options + */ + public function getOptions() + { + return $this->options; + } + + /** + * Sets the options. + * + * This method implements a fluent interface. + * + * @return $this + */ + public function setOptions(array $options) + { + $this->options = [ + 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', + ]; + + return $this->addOptions($options); + } + + /** + * Adds options. + * + * This method implements a fluent interface. + * + * @return $this + */ + public function addOptions(array $options) + { + foreach ($options as $name => $option) { + $this->options[$name] = $option; + } + $this->compiled = null; + + return $this; + } + + /** + * Sets an option value. + * + * This method implements a fluent interface. + * + * @param mixed $value The option value + * + * @return $this + */ + public function setOption(string $name, $value) + { + $this->options[$name] = $value; + $this->compiled = null; + + return $this; + } + + /** + * Get an option value. + * + * @return mixed The option value or null when not given + */ + public function getOption(string $name) + { + return isset($this->options[$name]) ? $this->options[$name] : null; + } + + /** + * Checks if an option has been set. + * + * @return bool true if the option is set, false otherwise + */ + public function hasOption(string $name) + { + return \array_key_exists($name, $this->options); + } + + /** + * Returns the defaults. + * + * @return array The defaults + */ + public function getDefaults() + { + return $this->defaults; + } + + /** + * Sets the defaults. + * + * This method implements a fluent interface. + * + * @param array $defaults The defaults + * + * @return $this + */ + public function setDefaults(array $defaults) + { + $this->defaults = []; + + return $this->addDefaults($defaults); + } + + /** + * Adds defaults. + * + * This method implements a fluent interface. + * + * @param array $defaults The defaults + * + * @return $this + */ + public function addDefaults(array $defaults) + { + foreach ($defaults as $name => $default) { + $this->defaults[$name] = $default; + } + $this->compiled = null; + + return $this; + } + + /** + * Gets a default value. + * + * @return mixed The default value or null when not given + */ + public function getDefault(string $name) + { + return isset($this->defaults[$name]) ? $this->defaults[$name] : null; + } + + /** + * Checks if a default value is set for the given variable. + * + * @return bool true if the default value is set, false otherwise + */ + public function hasDefault(string $name) + { + return \array_key_exists($name, $this->defaults); + } + + /** + * Sets a default value. + * + * @param mixed $default The default value + * + * @return $this + */ + public function setDefault(string $name, $default) + { + $this->defaults[$name] = $default; + $this->compiled = null; + + return $this; + } + + /** + * Returns the requirements. + * + * @return array The requirements + */ + public function getRequirements() + { + return $this->requirements; + } + + /** + * Sets the requirements. + * + * This method implements a fluent interface. + * + * @param array $requirements The requirements + * + * @return $this + */ + public function setRequirements(array $requirements) + { + $this->requirements = []; + + return $this->addRequirements($requirements); + } + + /** + * Adds requirements. + * + * This method implements a fluent interface. + * + * @param array $requirements The requirements + * + * @return $this + */ + public function addRequirements(array $requirements) + { + foreach ($requirements as $key => $regex) { + $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); + } + $this->compiled = null; + + return $this; + } + + /** + * Returns the requirement for the given key. + * + * @return string|null The regex or null when not given + */ + public function getRequirement(string $key) + { + return isset($this->requirements[$key]) ? $this->requirements[$key] : null; + } + + /** + * Checks if a requirement is set for the given key. + * + * @return bool true if a requirement is specified, false otherwise + */ + public function hasRequirement(string $key) + { + return \array_key_exists($key, $this->requirements); + } + + /** + * Sets a requirement for the given key. + * + * @return $this + */ + public function setRequirement(string $key, string $regex) + { + $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); + $this->compiled = null; + + return $this; + } + + /** + * Returns the condition. + * + * @return string The condition + */ + public function getCondition() + { + return $this->condition; + } + + /** + * Sets the condition. + * + * This method implements a fluent interface. + * + * @return $this + */ + public function setCondition(?string $condition) + { + $this->condition = (string) $condition; + $this->compiled = null; + + return $this; + } + + /** + * Compiles the route. + * + * @return CompiledRoute A CompiledRoute instance + * + * @throws \LogicException If the Route cannot be compiled because the + * path or host pattern is invalid + * + * @see RouteCompiler which is responsible for the compilation process + */ + public function compile() + { + if (null !== $this->compiled) { + return $this->compiled; + } + + $class = $this->getOption('compiler_class'); + + return $this->compiled = $class::compile($this); + } + + private function sanitizeRequirement(string $key, string $regex) + { + if ('' !== $regex && '^' === $regex[0]) { + $regex = (string) substr($regex, 1); // returns false for a single character + } + + if ('$' === substr($regex, -1)) { + $regex = substr($regex, 0, -1); + } + + if ('' === $regex) { + throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key)); + } + + return $regex; + } +} diff --git a/vendor/symfony/routing/RouteCollection.php b/vendor/symfony/routing/RouteCollection.php new file mode 100644 index 0000000..6c7bcf1 --- /dev/null +++ b/vendor/symfony/routing/RouteCollection.php @@ -0,0 +1,273 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +use Symfony\Component\Config\Resource\ResourceInterface; + +/** + * A RouteCollection represents a set of Route instances. + * + * When adding a route at the end of the collection, an existing route + * with the same name is removed first. So there can only be one route + * with a given name. + * + * @author Fabien Potencier + * @author Tobias Schultze + */ +class RouteCollection implements \IteratorAggregate, \Countable +{ + /** + * @var Route[] + */ + private $routes = []; + + /** + * @var array + */ + private $resources = []; + + public function __clone() + { + foreach ($this->routes as $name => $route) { + $this->routes[$name] = clone $route; + } + } + + /** + * Gets the current RouteCollection as an Iterator that includes all routes. + * + * It implements \IteratorAggregate. + * + * @see all() + * + * @return \ArrayIterator|Route[] An \ArrayIterator object for iterating over routes + */ + public function getIterator() + { + return new \ArrayIterator($this->routes); + } + + /** + * Gets the number of Routes in this collection. + * + * @return int The number of routes + */ + public function count() + { + return \count($this->routes); + } + + public function add(string $name, Route $route) + { + unset($this->routes[$name]); + + $this->routes[$name] = $route; + } + + /** + * Returns all routes in this collection. + * + * @return Route[] An array of routes + */ + public function all() + { + return $this->routes; + } + + /** + * Gets a route by name. + * + * @return Route|null A Route instance or null when not found + */ + public function get(string $name) + { + return isset($this->routes[$name]) ? $this->routes[$name] : null; + } + + /** + * Removes a route or an array of routes by name from the collection. + * + * @param string|string[] $name The route name or an array of route names + */ + public function remove($name) + { + foreach ((array) $name as $n) { + unset($this->routes[$n]); + } + } + + /** + * Adds a route collection at the end of the current set by appending all + * routes of the added collection. + */ + public function addCollection(self $collection) + { + // we need to remove all routes with the same names first because just replacing them + // would not place the new route at the end of the merged array + foreach ($collection->all() as $name => $route) { + unset($this->routes[$name]); + $this->routes[$name] = $route; + } + + foreach ($collection->getResources() as $resource) { + $this->addResource($resource); + } + } + + /** + * Adds a prefix to the path of all child routes. + */ + public function addPrefix(string $prefix, array $defaults = [], array $requirements = []) + { + $prefix = trim(trim($prefix), '/'); + + if ('' === $prefix) { + return; + } + + foreach ($this->routes as $route) { + $route->setPath('/'.$prefix.$route->getPath()); + $route->addDefaults($defaults); + $route->addRequirements($requirements); + } + } + + /** + * Adds a prefix to the name of all the routes within in the collection. + */ + public function addNamePrefix(string $prefix) + { + $prefixedRoutes = []; + + foreach ($this->routes as $name => $route) { + $prefixedRoutes[$prefix.$name] = $route; + if (null !== $name = $route->getDefault('_canonical_route')) { + $route->setDefault('_canonical_route', $prefix.$name); + } + } + + $this->routes = $prefixedRoutes; + } + + /** + * Sets the host pattern on all routes. + */ + public function setHost(?string $pattern, array $defaults = [], array $requirements = []) + { + foreach ($this->routes as $route) { + $route->setHost($pattern); + $route->addDefaults($defaults); + $route->addRequirements($requirements); + } + } + + /** + * Sets a condition on all routes. + * + * Existing conditions will be overridden. + */ + public function setCondition(?string $condition) + { + foreach ($this->routes as $route) { + $route->setCondition($condition); + } + } + + /** + * Adds defaults to all routes. + * + * An existing default value under the same name in a route will be overridden. + */ + public function addDefaults(array $defaults) + { + if ($defaults) { + foreach ($this->routes as $route) { + $route->addDefaults($defaults); + } + } + } + + /** + * Adds requirements to all routes. + * + * An existing requirement under the same name in a route will be overridden. + */ + public function addRequirements(array $requirements) + { + if ($requirements) { + foreach ($this->routes as $route) { + $route->addRequirements($requirements); + } + } + } + + /** + * Adds options to all routes. + * + * An existing option value under the same name in a route will be overridden. + */ + public function addOptions(array $options) + { + if ($options) { + foreach ($this->routes as $route) { + $route->addOptions($options); + } + } + } + + /** + * Sets the schemes (e.g. 'https') all child routes are restricted to. + * + * @param string|string[] $schemes The scheme or an array of schemes + */ + public function setSchemes($schemes) + { + foreach ($this->routes as $route) { + $route->setSchemes($schemes); + } + } + + /** + * Sets the HTTP methods (e.g. 'POST') all child routes are restricted to. + * + * @param string|string[] $methods The method or an array of methods + */ + public function setMethods($methods) + { + foreach ($this->routes as $route) { + $route->setMethods($methods); + } + } + + /** + * Returns an array of resources loaded to build this collection. + * + * @return ResourceInterface[] An array of resources + */ + public function getResources() + { + return array_values($this->resources); + } + + /** + * Adds a resource for this collection. If the resource already exists + * it is not added. + */ + public function addResource(ResourceInterface $resource) + { + $key = (string) $resource; + + if (!isset($this->resources[$key])) { + $this->resources[$key] = $resource; + } + } +} diff --git a/vendor/symfony/routing/RouteCollectionBuilder.php b/vendor/symfony/routing/RouteCollectionBuilder.php new file mode 100644 index 0000000..406e3c0 --- /dev/null +++ b/vendor/symfony/routing/RouteCollectionBuilder.php @@ -0,0 +1,359 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +use Symfony\Component\Config\Exception\LoaderLoadException; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\Config\Resource\ResourceInterface; + +/** + * Helps add and import routes into a RouteCollection. + * + * @author Ryan Weaver + */ +class RouteCollectionBuilder +{ + /** + * @var Route[]|RouteCollectionBuilder[] + */ + private $routes = []; + + private $loader; + private $defaults = []; + private $prefix; + private $host; + private $condition; + private $requirements = []; + private $options = []; + private $schemes; + private $methods; + private $resources = []; + + public function __construct(LoaderInterface $loader = null) + { + $this->loader = $loader; + } + + /** + * Import an external routing resource and returns the RouteCollectionBuilder. + * + * $routes->import('blog.yml', '/blog'); + * + * @param mixed $resource + * + * @return self + * + * @throws LoaderLoadException + */ + public function import($resource, string $prefix = '/', string $type = null) + { + /** @var RouteCollection[] $collections */ + $collections = $this->load($resource, $type); + + // create a builder from the RouteCollection + $builder = $this->createBuilder(); + + foreach ($collections as $collection) { + if (null === $collection) { + continue; + } + + foreach ($collection->all() as $name => $route) { + $builder->addRoute($route, $name); + } + + foreach ($collection->getResources() as $resource) { + $builder->addResource($resource); + } + } + + // mount into this builder + $this->mount($prefix, $builder); + + return $builder; + } + + /** + * Adds a route and returns it for future modification. + * + * @return Route + */ + public function add(string $path, string $controller, string $name = null) + { + $route = new Route($path); + $route->setDefault('_controller', $controller); + $this->addRoute($route, $name); + + return $route; + } + + /** + * Returns a RouteCollectionBuilder that can be configured and then added with mount(). + * + * @return self + */ + public function createBuilder() + { + return new self($this->loader); + } + + /** + * Add a RouteCollectionBuilder. + */ + public function mount(string $prefix, self $builder) + { + $builder->prefix = trim(trim($prefix), '/'); + $this->routes[] = $builder; + } + + /** + * Adds a Route object to the builder. + * + * @return $this + */ + public function addRoute(Route $route, string $name = null) + { + if (null === $name) { + // used as a flag to know which routes will need a name later + $name = '_unnamed_route_'.spl_object_hash($route); + } + + $this->routes[$name] = $route; + + return $this; + } + + /** + * Sets the host on all embedded routes (unless already set). + * + * @return $this + */ + public function setHost(?string $pattern) + { + $this->host = $pattern; + + return $this; + } + + /** + * Sets a condition on all embedded routes (unless already set). + * + * @return $this + */ + public function setCondition(?string $condition) + { + $this->condition = $condition; + + return $this; + } + + /** + * Sets a default value that will be added to all embedded routes (unless that + * default value is already set). + * + * @param mixed $value + * + * @return $this + */ + public function setDefault(string $key, $value) + { + $this->defaults[$key] = $value; + + return $this; + } + + /** + * Sets a requirement that will be added to all embedded routes (unless that + * requirement is already set). + * + * @param mixed $regex + * + * @return $this + */ + public function setRequirement(string $key, $regex) + { + $this->requirements[$key] = $regex; + + return $this; + } + + /** + * Sets an option that will be added to all embedded routes (unless that + * option is already set). + * + * @param mixed $value + * + * @return $this + */ + public function setOption(string $key, $value) + { + $this->options[$key] = $value; + + return $this; + } + + /** + * Sets the schemes on all embedded routes (unless already set). + * + * @param array|string $schemes + * + * @return $this + */ + public function setSchemes($schemes) + { + $this->schemes = $schemes; + + return $this; + } + + /** + * Sets the methods on all embedded routes (unless already set). + * + * @param array|string $methods + * + * @return $this + */ + public function setMethods($methods) + { + $this->methods = $methods; + + return $this; + } + + /** + * Adds a resource for this collection. + * + * @return $this + */ + private function addResource(ResourceInterface $resource): self + { + $this->resources[] = $resource; + + return $this; + } + + /** + * Creates the final RouteCollection and returns it. + * + * @return RouteCollection + */ + public function build() + { + $routeCollection = new RouteCollection(); + + foreach ($this->routes as $name => $route) { + if ($route instanceof Route) { + $route->setDefaults(array_merge($this->defaults, $route->getDefaults())); + $route->setOptions(array_merge($this->options, $route->getOptions())); + + foreach ($this->requirements as $key => $val) { + if (!$route->hasRequirement($key)) { + $route->setRequirement($key, $val); + } + } + + if (null !== $this->prefix) { + $route->setPath('/'.$this->prefix.$route->getPath()); + } + + if (!$route->getHost()) { + $route->setHost($this->host); + } + + if (!$route->getCondition()) { + $route->setCondition($this->condition); + } + + if (!$route->getSchemes()) { + $route->setSchemes($this->schemes); + } + + if (!$route->getMethods()) { + $route->setMethods($this->methods); + } + + // auto-generate the route name if it's been marked + if ('_unnamed_route_' === substr($name, 0, 15)) { + $name = $this->generateRouteName($route); + } + + $routeCollection->add($name, $route); + } else { + /* @var self $route */ + $subCollection = $route->build(); + if (null !== $this->prefix) { + $subCollection->addPrefix($this->prefix); + } + + $routeCollection->addCollection($subCollection); + } + } + + foreach ($this->resources as $resource) { + $routeCollection->addResource($resource); + } + + return $routeCollection; + } + + /** + * Generates a route name based on details of this route. + */ + private function generateRouteName(Route $route): string + { + $methods = implode('_', $route->getMethods()).'_'; + + $routeName = $methods.$route->getPath(); + $routeName = str_replace(['/', ':', '|', '-'], '_', $routeName); + $routeName = preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName); + + // Collapse consecutive underscores down into a single underscore. + $routeName = preg_replace('/_+/', '_', $routeName); + + return $routeName; + } + + /** + * Finds a loader able to load an imported resource and loads it. + * + * @param mixed $resource A resource + * @param string|null $type The resource type or null if unknown + * + * @return RouteCollection[] + * + * @throws LoaderLoadException If no loader is found + */ + private function load($resource, string $type = null): array + { + if (null === $this->loader) { + throw new \BadMethodCallException('Cannot import other routing resources: you must pass a LoaderInterface when constructing RouteCollectionBuilder.'); + } + + if ($this->loader->supports($resource, $type)) { + $collections = $this->loader->load($resource, $type); + + return \is_array($collections) ? $collections : [$collections]; + } + + if (null === $resolver = $this->loader->getResolver()) { + throw new LoaderLoadException($resource, null, null, null, $type); + } + + if (false === $loader = $resolver->resolve($resource, $type)) { + throw new LoaderLoadException($resource, null, null, null, $type); + } + + $collections = $loader->load($resource, $type); + + return \is_array($collections) ? $collections : [$collections]; + } +} diff --git a/vendor/symfony/routing/RouteCompiler.php b/vendor/symfony/routing/RouteCompiler.php new file mode 100644 index 0000000..59f3a32 --- /dev/null +++ b/vendor/symfony/routing/RouteCompiler.php @@ -0,0 +1,337 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +/** + * RouteCompiler compiles Route instances to CompiledRoute instances. + * + * @author Fabien Potencier + * @author Tobias Schultze + */ +class RouteCompiler implements RouteCompilerInterface +{ + const REGEX_DELIMITER = '#'; + + /** + * This string defines the characters that are automatically considered separators in front of + * optional placeholders (with default and no static text following). Such a single separator + * can be left out together with the optional placeholder from matching and generating URLs. + */ + const SEPARATORS = '/,;.:-_~+*=@|'; + + /** + * The maximum supported length of a PCRE subpattern name + * http://pcre.org/current/doc/html/pcre2pattern.html#SEC16. + * + * @internal + */ + const VARIABLE_MAXIMUM_LENGTH = 32; + + /** + * {@inheritdoc} + * + * @throws \InvalidArgumentException if a path variable is named _fragment + * @throws \LogicException if a variable is referenced more than once + * @throws \DomainException if a variable name starts with a digit or if it is too long to be successfully used as + * a PCRE subpattern + */ + public static function compile(Route $route) + { + $hostVariables = []; + $variables = []; + $hostRegex = null; + $hostTokens = []; + + if ('' !== $host = $route->getHost()) { + $result = self::compilePattern($route, $host, true); + + $hostVariables = $result['variables']; + $variables = $hostVariables; + + $hostTokens = $result['tokens']; + $hostRegex = $result['regex']; + } + + $path = $route->getPath(); + + $result = self::compilePattern($route, $path, false); + + $staticPrefix = $result['staticPrefix']; + + $pathVariables = $result['variables']; + + foreach ($pathVariables as $pathParam) { + if ('_fragment' === $pathParam) { + throw new \InvalidArgumentException(sprintf('Route pattern "%s" cannot contain "_fragment" as a path parameter.', $route->getPath())); + } + } + + $variables = array_merge($variables, $pathVariables); + + $tokens = $result['tokens']; + $regex = $result['regex']; + + return new CompiledRoute( + $staticPrefix, + $regex, + $tokens, + $pathVariables, + $hostRegex, + $hostTokens, + $hostVariables, + array_unique($variables) + ); + } + + private static function compilePattern(Route $route, string $pattern, bool $isHost): array + { + $tokens = []; + $variables = []; + $matches = []; + $pos = 0; + $defaultSeparator = $isHost ? '.' : '/'; + $useUtf8 = preg_match('//u', $pattern); + $needsUtf8 = $route->getOption('utf8'); + + if (!$needsUtf8 && $useUtf8 && preg_match('/[\x80-\xFF]/', $pattern)) { + throw new \LogicException(sprintf('Cannot use UTF-8 route patterns without setting the "utf8" option for route "%s".', $route->getPath())); + } + if (!$useUtf8 && $needsUtf8) { + throw new \LogicException(sprintf('Cannot mix UTF-8 requirements with non-UTF-8 pattern "%s".', $pattern)); + } + + // Match all variables enclosed in "{}" and iterate over them. But we only want to match the innermost variable + // in case of nested "{}", e.g. {foo{bar}}. This in ensured because \w does not match "{" or "}" itself. + preg_match_all('#\{(!)?(\w+)\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); + foreach ($matches as $match) { + $important = $match[1][1] >= 0; + $varName = $match[2][0]; + // get all static text preceding the current variable + $precedingText = substr($pattern, $pos, $match[0][1] - $pos); + $pos = $match[0][1] + \strlen($match[0][0]); + + if (!\strlen($precedingText)) { + $precedingChar = ''; + } elseif ($useUtf8) { + preg_match('/.$/u', $precedingText, $precedingChar); + $precedingChar = $precedingChar[0]; + } else { + $precedingChar = substr($precedingText, -1); + } + $isSeparator = '' !== $precedingChar && false !== strpos(static::SEPARATORS, $precedingChar); + + // A PCRE subpattern name must start with a non-digit. Also a PHP variable cannot start with a digit so the + // variable would not be usable as a Controller action argument. + if (preg_match('/^\d/', $varName)) { + throw new \DomainException(sprintf('Variable name "%s" cannot start with a digit in route pattern "%s". Please use a different name.', $varName, $pattern)); + } + if (\in_array($varName, $variables)) { + throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName)); + } + + if (\strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) { + throw new \DomainException(sprintf('Variable name "%s" cannot be longer than %s characters in route pattern "%s". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern)); + } + + if ($isSeparator && $precedingText !== $precedingChar) { + $tokens[] = ['text', substr($precedingText, 0, -\strlen($precedingChar))]; + } elseif (!$isSeparator && \strlen($precedingText) > 0) { + $tokens[] = ['text', $precedingText]; + } + + $regexp = $route->getRequirement($varName); + if (null === $regexp) { + $followingPattern = (string) substr($pattern, $pos); + // Find the next static character after the variable that functions as a separator. By default, this separator and '/' + // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all + // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are + // the same that will be matched. Example: new Route('/{page}.{_format}', ['_format' => 'html']) + // If {page} would also match the separating dot, {_format} would never match as {page} will eagerly consume everything. + // Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally + // part of {_format} when generating the URL, e.g. _format = 'mobile.html'. + $nextSeparator = self::findNextSeparator($followingPattern, $useUtf8); + $regexp = sprintf( + '[^%s%s]+', + preg_quote($defaultSeparator, self::REGEX_DELIMITER), + $defaultSeparator !== $nextSeparator && '' !== $nextSeparator ? preg_quote($nextSeparator, self::REGEX_DELIMITER) : '' + ); + if (('' !== $nextSeparator && !preg_match('#^\{\w+\}#', $followingPattern)) || '' === $followingPattern) { + // When we have a separator, which is disallowed for the variable, we can optimize the regex with a possessive + // quantifier. This prevents useless backtracking of PCRE and improves performance by 20% for matching those patterns. + // Given the above example, there is no point in backtracking into {page} (that forbids the dot) when a dot must follow + // after it. This optimization cannot be applied when the next char is no real separator or when the next variable is + // directly adjacent, e.g. '/{x}{y}'. + $regexp .= '+'; + } + } else { + if (!preg_match('//u', $regexp)) { + $useUtf8 = false; + } elseif (!$needsUtf8 && preg_match('/[\x80-\xFF]|(?= 0; --$i) { + $token = $tokens[$i]; + // variable is optional when it is not important and has a default value + if ('variable' === $token[0] && !($token[5] ?? false) && $route->hasDefault($token[3])) { + $firstOptional = $i; + } else { + break; + } + } + } + + // compute the matching regexp + $regexp = ''; + for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { + $regexp .= self::computeRegexp($tokens, $i, $firstOptional); + } + $regexp = self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'sD'.($isHost ? 'i' : ''); + + // enable Utf8 matching if really required + if ($needsUtf8) { + $regexp .= 'u'; + for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { + if ('variable' === $tokens[$i][0]) { + $tokens[$i][4] = true; + } + } + } + + return [ + 'staticPrefix' => self::determineStaticPrefix($route, $tokens), + 'regex' => $regexp, + 'tokens' => array_reverse($tokens), + 'variables' => $variables, + ]; + } + + /** + * Determines the longest static prefix possible for a route. + */ + private static function determineStaticPrefix(Route $route, array $tokens): string + { + if ('text' !== $tokens[0][0]) { + return ($route->hasDefault($tokens[0][3]) || '/' === $tokens[0][1]) ? '' : $tokens[0][1]; + } + + $prefix = $tokens[0][1]; + + if (isset($tokens[1][1]) && '/' !== $tokens[1][1] && false === $route->hasDefault($tokens[1][3])) { + $prefix .= $tokens[1][1]; + } + + return $prefix; + } + + /** + * Returns the next static character in the Route pattern that will serve as a separator (or the empty string when none available). + */ + private static function findNextSeparator(string $pattern, bool $useUtf8): string + { + if ('' == $pattern) { + // return empty string if pattern is empty or false (false which can be returned by substr) + return ''; + } + // first remove all placeholders from the pattern so we can find the next real static character + if ('' === $pattern = preg_replace('#\{\w+\}#', '', $pattern)) { + return ''; + } + if ($useUtf8) { + preg_match('/^./u', $pattern, $pattern); + } + + return false !== strpos(static::SEPARATORS, $pattern[0]) ? $pattern[0] : ''; + } + + /** + * Computes the regexp used to match a specific token. It can be static text or a subpattern. + * + * @param array $tokens The route tokens + * @param int $index The index of the current token + * @param int $firstOptional The index of the first optional token + * + * @return string The regexp pattern for a single token + */ + private static function computeRegexp(array $tokens, int $index, int $firstOptional): string + { + $token = $tokens[$index]; + if ('text' === $token[0]) { + // Text tokens + return preg_quote($token[1], self::REGEX_DELIMITER); + } else { + // Variable tokens + if (0 === $index && 0 === $firstOptional) { + // When the only token is an optional variable token, the separator is required + return sprintf('%s(?P<%s>%s)?', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]); + } else { + $regexp = sprintf('%s(?P<%s>%s)', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]); + if ($index >= $firstOptional) { + // Enclose each optional token in a subpattern to make it optional. + // "?:" means it is non-capturing, i.e. the portion of the subject string that + // matched the optional subpattern is not passed back. + $regexp = "(?:$regexp"; + $nbTokens = \count($tokens); + if ($nbTokens - 1 == $index) { + // Close the optional subpatterns + $regexp .= str_repeat(')?', $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0)); + } + } + + return $regexp; + } + } + } + + private static function transformCapturingGroupsToNonCapturings(string $regexp): string + { + for ($i = 0; $i < \strlen($regexp); ++$i) { + if ('\\' === $regexp[$i]) { + ++$i; + continue; + } + if ('(' !== $regexp[$i] || !isset($regexp[$i + 2])) { + continue; + } + if ('*' === $regexp[++$i] || '?' === $regexp[$i]) { + ++$i; + continue; + } + $regexp = substr_replace($regexp, '?:', $i, 0); + ++$i; + } + + return $regexp; + } +} diff --git a/vendor/symfony/routing/RouteCompilerInterface.php b/vendor/symfony/routing/RouteCompilerInterface.php new file mode 100644 index 0000000..ddfa7ca --- /dev/null +++ b/vendor/symfony/routing/RouteCompilerInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +/** + * RouteCompilerInterface is the interface that all RouteCompiler classes must implement. + * + * @author Fabien Potencier + */ +interface RouteCompilerInterface +{ + /** + * Compiles the current route instance. + * + * @return CompiledRoute A CompiledRoute instance + * + * @throws \LogicException If the Route cannot be compiled because the + * path or host pattern is invalid + */ + public static function compile(Route $route); +} diff --git a/vendor/symfony/routing/Router.php b/vendor/symfony/routing/Router.php new file mode 100644 index 0000000..031749b --- /dev/null +++ b/vendor/symfony/routing/Router.php @@ -0,0 +1,390 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Config\ConfigCacheFactory; +use Symfony\Component\Config\ConfigCacheFactoryInterface; +use Symfony\Component\Config\ConfigCacheInterface; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Generator\CompiledUrlGenerator; +use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface; +use Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper; +use Symfony\Component\Routing\Generator\Dumper\GeneratorDumperInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; +use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface; +use Symfony\Component\Routing\Matcher\RequestMatcherInterface; +use Symfony\Component\Routing\Matcher\UrlMatcherInterface; + +/** + * The Router class is an example of the integration of all pieces of the + * routing system for easier use. + * + * @author Fabien Potencier + */ +class Router implements RouterInterface, RequestMatcherInterface +{ + /** + * @var UrlMatcherInterface|null + */ + protected $matcher; + + /** + * @var UrlGeneratorInterface|null + */ + protected $generator; + + /** + * @var RequestContext + */ + protected $context; + + /** + * @var LoaderInterface + */ + protected $loader; + + /** + * @var RouteCollection|null + */ + protected $collection; + + /** + * @var mixed + */ + protected $resource; + + /** + * @var array + */ + protected $options = []; + + /** + * @var LoggerInterface|null + */ + protected $logger; + + /** + * @var string|null + */ + protected $defaultLocale; + + /** + * @var ConfigCacheFactoryInterface|null + */ + private $configCacheFactory; + + /** + * @var ExpressionFunctionProviderInterface[] + */ + private $expressionLanguageProviders = []; + + private static $cache = []; + + /** + * @param mixed $resource The main resource to load + */ + public function __construct(LoaderInterface $loader, $resource, array $options = [], RequestContext $context = null, LoggerInterface $logger = null, string $defaultLocale = null) + { + $this->loader = $loader; + $this->resource = $resource; + $this->logger = $logger; + $this->context = $context ?: new RequestContext(); + $this->setOptions($options); + $this->defaultLocale = $defaultLocale; + } + + /** + * Sets options. + * + * Available options: + * + * * cache_dir: The cache directory (or null to disable caching) + * * debug: Whether to enable debugging or not (false by default) + * * generator_class: The name of a UrlGeneratorInterface implementation + * * generator_dumper_class: The name of a GeneratorDumperInterface implementation + * * matcher_class: The name of a UrlMatcherInterface implementation + * * matcher_dumper_class: The name of a MatcherDumperInterface implementation + * * resource_type: Type hint for the main resource (optional) + * * strict_requirements: Configure strict requirement checking for generators + * implementing ConfigurableRequirementsInterface (default is true) + * + * @throws \InvalidArgumentException When unsupported option is provided + */ + public function setOptions(array $options) + { + $this->options = [ + 'cache_dir' => null, + 'debug' => false, + 'generator_class' => CompiledUrlGenerator::class, + 'generator_dumper_class' => CompiledUrlGeneratorDumper::class, + 'matcher_class' => CompiledUrlMatcher::class, + 'matcher_dumper_class' => CompiledUrlMatcherDumper::class, + 'resource_type' => null, + 'strict_requirements' => true, + ]; + + // check option names and live merge, if errors are encountered Exception will be thrown + $invalid = []; + foreach ($options as $key => $value) { + if (\array_key_exists($key, $this->options)) { + $this->options[$key] = $value; + } else { + $invalid[] = $key; + } + } + + if ($invalid) { + throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid))); + } + } + + /** + * Sets an option. + * + * @param mixed $value The value + * + * @throws \InvalidArgumentException + */ + public function setOption(string $key, $value) + { + if (!\array_key_exists($key, $this->options)) { + throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); + } + + $this->options[$key] = $value; + } + + /** + * Gets an option value. + * + * @return mixed The value + * + * @throws \InvalidArgumentException + */ + public function getOption(string $key) + { + if (!\array_key_exists($key, $this->options)) { + throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); + } + + return $this->options[$key]; + } + + /** + * {@inheritdoc} + */ + public function getRouteCollection() + { + if (null === $this->collection) { + $this->collection = $this->loader->load($this->resource, $this->options['resource_type']); + } + + return $this->collection; + } + + /** + * {@inheritdoc} + */ + public function setContext(RequestContext $context) + { + $this->context = $context; + + if (null !== $this->matcher) { + $this->getMatcher()->setContext($context); + } + if (null !== $this->generator) { + $this->getGenerator()->setContext($context); + } + } + + /** + * {@inheritdoc} + */ + public function getContext() + { + return $this->context; + } + + /** + * Sets the ConfigCache factory to use. + */ + public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory) + { + $this->configCacheFactory = $configCacheFactory; + } + + /** + * {@inheritdoc} + */ + public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) + { + return $this->getGenerator()->generate($name, $parameters, $referenceType); + } + + /** + * {@inheritdoc} + */ + public function match(string $pathinfo) + { + return $this->getMatcher()->match($pathinfo); + } + + /** + * {@inheritdoc} + */ + public function matchRequest(Request $request) + { + $matcher = $this->getMatcher(); + if (!$matcher instanceof RequestMatcherInterface) { + // fallback to the default UrlMatcherInterface + return $matcher->match($request->getPathInfo()); + } + + return $matcher->matchRequest($request); + } + + /** + * Gets the UrlMatcher or RequestMatcher instance associated with this Router. + * + * @return UrlMatcherInterface|RequestMatcherInterface + */ + public function getMatcher() + { + if (null !== $this->matcher) { + return $this->matcher; + } + + if (null === $this->options['cache_dir']) { + $routes = $this->getRouteCollection(); + $compiled = is_a($this->options['matcher_class'], CompiledUrlMatcher::class, true); + if ($compiled) { + $routes = (new CompiledUrlMatcherDumper($routes))->getCompiledRoutes(); + } + $this->matcher = new $this->options['matcher_class']($routes, $this->context); + if (method_exists($this->matcher, 'addExpressionLanguageProvider')) { + foreach ($this->expressionLanguageProviders as $provider) { + $this->matcher->addExpressionLanguageProvider($provider); + } + } + + return $this->matcher; + } + + $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/url_matching_routes.php', + function (ConfigCacheInterface $cache) { + $dumper = $this->getMatcherDumperInstance(); + if (method_exists($dumper, 'addExpressionLanguageProvider')) { + foreach ($this->expressionLanguageProviders as $provider) { + $dumper->addExpressionLanguageProvider($provider); + } + } + + $cache->write($dumper->dump(), $this->getRouteCollection()->getResources()); + } + ); + + return $this->matcher = new $this->options['matcher_class'](self::getCompiledRoutes($cache->getPath()), $this->context); + } + + /** + * Gets the UrlGenerator instance associated with this Router. + * + * @return UrlGeneratorInterface A UrlGeneratorInterface instance + */ + public function getGenerator() + { + if (null !== $this->generator) { + return $this->generator; + } + + if (null === $this->options['cache_dir']) { + $routes = $this->getRouteCollection(); + $compiled = is_a($this->options['generator_class'], CompiledUrlGenerator::class, true); + if ($compiled) { + $routes = (new CompiledUrlGeneratorDumper($routes))->getCompiledRoutes(); + } + $this->generator = new $this->options['generator_class']($routes, $this->context, $this->logger, $this->defaultLocale); + } else { + $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/url_generating_routes.php', + function (ConfigCacheInterface $cache) { + $dumper = $this->getGeneratorDumperInstance(); + + $cache->write($dumper->dump(), $this->getRouteCollection()->getResources()); + } + ); + + $this->generator = new $this->options['generator_class'](self::getCompiledRoutes($cache->getPath()), $this->context, $this->logger, $this->defaultLocale); + } + + if ($this->generator instanceof ConfigurableRequirementsInterface) { + $this->generator->setStrictRequirements($this->options['strict_requirements']); + } + + return $this->generator; + } + + public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) + { + $this->expressionLanguageProviders[] = $provider; + } + + /** + * @return GeneratorDumperInterface + */ + protected function getGeneratorDumperInstance() + { + return new $this->options['generator_dumper_class']($this->getRouteCollection()); + } + + /** + * @return MatcherDumperInterface + */ + protected function getMatcherDumperInstance() + { + return new $this->options['matcher_dumper_class']($this->getRouteCollection()); + } + + /** + * Provides the ConfigCache factory implementation, falling back to a + * default implementation if necessary. + */ + private function getConfigCacheFactory(): ConfigCacheFactoryInterface + { + if (null === $this->configCacheFactory) { + $this->configCacheFactory = new ConfigCacheFactory($this->options['debug']); + } + + return $this->configCacheFactory; + } + + private static function getCompiledRoutes(string $path): array + { + if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(ini_get('opcache.enable_cli'), FILTER_VALIDATE_BOOLEAN))) { + self::$cache = null; + } + + if (null === self::$cache) { + return require $path; + } + + if (isset(self::$cache[$path])) { + return self::$cache[$path]; + } + + return self::$cache[$path] = require $path; + } +} diff --git a/vendor/symfony/routing/RouterInterface.php b/vendor/symfony/routing/RouterInterface.php new file mode 100644 index 0000000..8a3e33d --- /dev/null +++ b/vendor/symfony/routing/RouterInterface.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\Matcher\UrlMatcherInterface; + +/** + * RouterInterface is the interface that all Router classes must implement. + * + * This interface is the concatenation of UrlMatcherInterface and UrlGeneratorInterface. + * + * @author Fabien Potencier + */ +interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface +{ + /** + * Gets the RouteCollection instance associated with this Router. + * + * WARNING: This method should never be used at runtime as it is SLOW. + * You might use it in a cache warmer though. + * + * @return RouteCollection A RouteCollection instance + */ + public function getRouteCollection(); +} diff --git a/vendor/symfony/routing/composer.json b/vendor/symfony/routing/composer.json new file mode 100644 index 0000000..1e039cb --- /dev/null +++ b/vendor/symfony/routing/composer.json @@ -0,0 +1,54 @@ +{ + "name": "symfony/routing", + "type": "library", + "description": "Symfony Routing Component", + "keywords": ["routing", "router", "URL", "URI"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5" + }, + "require-dev": { + "symfony/config": "^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "doctrine/annotations": "~1.2", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/config": "<5.0", + "symfony/dependency-injection": "<4.4", + "symfony/yaml": "<4.4" + }, + "suggest": { + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/yaml": "For using the YAML loader", + "symfony/expression-language": "For using expression matching", + "doctrine/annotations": "For using the annotation loader" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Routing\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/service-contracts/.gitignore b/vendor/symfony/service-contracts/.gitignore new file mode 100644 index 0000000..c49a5d8 --- /dev/null +++ b/vendor/symfony/service-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/vendor/symfony/service-contracts/LICENSE b/vendor/symfony/service-contracts/LICENSE new file mode 100644 index 0000000..3f853aa --- /dev/null +++ b/vendor/symfony/service-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/service-contracts/README.md b/vendor/symfony/service-contracts/README.md new file mode 100644 index 0000000..d033a43 --- /dev/null +++ b/vendor/symfony/service-contracts/README.md @@ -0,0 +1,9 @@ +Symfony Service Contracts +========================= + +A set of abstractions extracted out of the Symfony components. + +Can be used to build on semantics that the Symfony components proved useful - and +that already have battle tested implementations. + +See https://github.com/symfony/contracts/blob/master/README.md for more information. diff --git a/vendor/symfony/service-contracts/ResetInterface.php b/vendor/symfony/service-contracts/ResetInterface.php new file mode 100644 index 0000000..1af1075 --- /dev/null +++ b/vendor/symfony/service-contracts/ResetInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +/** + * Provides a way to reset an object to its initial state. + * + * When calling the "reset()" method on an object, it should be put back to its + * initial state. This usually means clearing any internal buffers and forwarding + * the call to internal dependencies. All properties of the object should be put + * back to the same state it had when it was first ready to use. + * + * This method could be called, for example, to recycle objects that are used as + * services, so that they can be used to handle several requests in the same + * process loop (note that we advise making your services stateless instead of + * implementing this interface when possible.) + */ +interface ResetInterface +{ + public function reset(); +} diff --git a/vendor/symfony/service-contracts/ServiceLocatorTrait.php b/vendor/symfony/service-contracts/ServiceLocatorTrait.php new file mode 100644 index 0000000..4ec6eb4 --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceLocatorTrait.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; + +/** + * A trait to help implement ServiceProviderInterface. + * + * @author Robin Chalas + * @author Nicolas Grekas + */ +trait ServiceLocatorTrait +{ + private $factories; + private $loading = []; + private $providedTypes; + + /** + * @param callable[] $factories + */ + public function __construct(array $factories) + { + $this->factories = $factories; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function has($id) + { + return isset($this->factories[$id]); + } + + /** + * {@inheritdoc} + */ + public function get($id) + { + if (!isset($this->factories[$id])) { + throw $this->createNotFoundException($id); + } + + if (isset($this->loading[$id])) { + $ids = array_values($this->loading); + $ids = \array_slice($this->loading, array_search($id, $ids)); + $ids[] = $id; + + throw $this->createCircularReferenceException($id, $ids); + } + + $this->loading[$id] = $id; + try { + return $this->factories[$id]($this); + } finally { + unset($this->loading[$id]); + } + } + + /** + * {@inheritdoc} + */ + public function getProvidedServices(): array + { + if (null === $this->providedTypes) { + $this->providedTypes = []; + + foreach ($this->factories as $name => $factory) { + if (!\is_callable($factory)) { + $this->providedTypes[$name] = '?'; + } else { + $type = (new \ReflectionFunction($factory))->getReturnType(); + + $this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '').$type->getName() : '?'; + } + } + } + + return $this->providedTypes; + } + + private function createNotFoundException(string $id): NotFoundExceptionInterface + { + if (!$alternatives = array_keys($this->factories)) { + $message = 'is empty...'; + } else { + $last = array_pop($alternatives); + if ($alternatives) { + $message = sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last); + } else { + $message = sprintf('only knows about the "%s" service.', $last); + } + } + + if ($this->loading) { + $message = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message); + } else { + $message = sprintf('Service "%s" not found: the current service locator %s', $id, $message); + } + + return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface { + }; + } + + private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface + { + return new class(sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface { + }; + } +} diff --git a/vendor/symfony/service-contracts/ServiceProviderInterface.php b/vendor/symfony/service-contracts/ServiceProviderInterface.php new file mode 100644 index 0000000..c60ad0b --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceProviderInterface.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +use Psr\Container\ContainerInterface; + +/** + * A ServiceProviderInterface exposes the identifiers and the types of services provided by a container. + * + * @author Nicolas Grekas + * @author Mateusz Sip + */ +interface ServiceProviderInterface extends ContainerInterface +{ + /** + * Returns an associative array of service types keyed by the identifiers provided by the current container. + * + * Examples: + * + * * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface + * * ['foo' => '?'] means the container provides service name "foo" of unspecified type + * * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null + * + * @return string[] The provided service types, keyed by service names + */ + public function getProvidedServices(): array; +} diff --git a/vendor/symfony/service-contracts/ServiceSubscriberInterface.php b/vendor/symfony/service-contracts/ServiceSubscriberInterface.php new file mode 100644 index 0000000..8bb320f --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceSubscriberInterface.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +/** + * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method. + * + * The getSubscribedServices method returns an array of service types required by such instances, + * optionally keyed by the service names used internally. Service types that start with an interrogation + * mark "?" are optional, while the other ones are mandatory service dependencies. + * + * The injected service locators SHOULD NOT allow access to any other services not specified by the method. + * + * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally. + * This interface does not dictate any injection method for these service locators, although constructor + * injection is recommended. + * + * @author Nicolas Grekas + */ +interface ServiceSubscriberInterface +{ + /** + * Returns an array of service types required by such instances, optionally keyed by the service names used internally. + * + * For mandatory dependencies: + * + * * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name + * internally to fetch a service which must implement Psr\Log\LoggerInterface. + * * ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name + * internally to fetch an iterable of Psr\Log\LoggerInterface instances. + * * ['Psr\Log\LoggerInterface'] is a shortcut for + * * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface'] + * + * otherwise: + * + * * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency + * * ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency + * * ['?Psr\Log\LoggerInterface'] is a shortcut for + * * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface'] + * + * @return array The required service types, optionally keyed by service names + */ + public static function getSubscribedServices(); +} diff --git a/vendor/symfony/service-contracts/ServiceSubscriberTrait.php b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php new file mode 100644 index 0000000..5d9d456 --- /dev/null +++ b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service; + +use Psr\Container\ContainerInterface; + +/** + * Implementation of ServiceSubscriberInterface that determines subscribed services from + * private method return types. Service ids are available as "ClassName::methodName". + * + * @author Kevin Bond + */ +trait ServiceSubscriberTrait +{ + /** @var ContainerInterface */ + protected $container; + + public static function getSubscribedServices(): array + { + static $services; + + if (null !== $services) { + return $services; + } + + $services = \is_callable(['parent', __FUNCTION__]) ? parent::getSubscribedServices() : []; + + foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { + if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { + continue; + } + + if (self::class === $method->getDeclaringClass()->name && ($returnType = $method->getReturnType()) && !$returnType->isBuiltin()) { + $services[self::class.'::'.$method->name] = '?'.$returnType->getName(); + } + } + + return $services; + } + + /** + * @required + */ + public function setContainer(ContainerInterface $container) + { + $this->container = $container; + + if (\is_callable(['parent', __FUNCTION__])) { + return parent::setContainer($container); + } + + return null; + } +} diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php new file mode 100644 index 0000000..5ed9149 --- /dev/null +++ b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Service\Test; + +use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; +use Symfony\Contracts\Service\ServiceLocatorTrait; + +abstract class ServiceLocatorTest extends TestCase +{ + protected function getServiceLocator(array $factories) + { + return new class($factories) implements ContainerInterface { + use ServiceLocatorTrait; + }; + } + + public function testHas() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return 'baz'; }, + function () { return 'dummy'; }, + ]); + + $this->assertTrue($locator->has('foo')); + $this->assertTrue($locator->has('bar')); + $this->assertFalse($locator->has('dummy')); + } + + public function testGet() + { + $locator = $this->getServiceLocator([ + 'foo' => function () { return 'bar'; }, + 'bar' => function () { return 'baz'; }, + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('baz', $locator->get('bar')); + } + + public function testGetDoesNotMemoize() + { + $i = 0; + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$i) { + ++$i; + + return 'bar'; + }, + ]); + + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame('bar', $locator->get('foo')); + $this->assertSame(2, $i); + } + + public function testThrowsOnUndefinedInternalService() + { + if (!$this->getExpectedException()) { + $this->expectException('Psr\Container\NotFoundExceptionInterface'); + $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.'); + } + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $locator->get('foo'); + } + + public function testThrowsOnCircularReference() + { + $this->expectException('Psr\Container\ContainerExceptionInterface'); + $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); + $locator = $this->getServiceLocator([ + 'foo' => function () use (&$locator) { return $locator->get('bar'); }, + 'bar' => function () use (&$locator) { return $locator->get('baz'); }, + 'baz' => function () use (&$locator) { return $locator->get('bar'); }, + ]); + + $locator->get('foo'); + } +} diff --git a/vendor/symfony/service-contracts/composer.json b/vendor/symfony/service-contracts/composer.json new file mode 100644 index 0000000..cbd491b --- /dev/null +++ b/vendor/symfony/service-contracts/composer.json @@ -0,0 +1,34 @@ +{ + "name": "symfony/service-contracts", + "type": "library", + "description": "Generic abstractions related to writing services", + "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "psr/container": "^1.0" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "autoload": { + "psr-4": { "Symfony\\Contracts\\Service\\": "" } + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + } +} diff --git a/vendor/symfony/var-dumper/.gitattributes b/vendor/symfony/var-dumper/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/var-dumper/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/var-dumper/CHANGELOG.md b/vendor/symfony/var-dumper/CHANGELOG.md new file mode 100644 index 0000000..94b1c17 --- /dev/null +++ b/vendor/symfony/var-dumper/CHANGELOG.md @@ -0,0 +1,53 @@ +CHANGELOG +========= + +4.4.0 +----- + + * added `VarDumperTestTrait::setUpVarDumper()` and `VarDumperTestTrait::tearDownVarDumper()` + to configure casters & flags to use in tests + * added `ImagineCaster` and infrastructure to dump images + * added the stamps of a message after it is dispatched in `TraceableMessageBus` and `MessengerDataCollector` collected data + * added `UuidCaster` + * made all casters final + * added support for the `NO_COLOR` env var (https://no-color.org/) + +4.3.0 +----- + + * added `DsCaster` to support dumping the contents of data structures from the Ds extension + +4.2.0 +----- + + * support selecting the format to use by setting the environment variable `VAR_DUMPER_FORMAT` to `html` or `cli` + +4.1.0 +----- + + * added a `ServerDumper` to send serialized Data clones to a server + * added a `ServerDumpCommand` and `DumpServer` to run a server collecting + and displaying dumps on a single place with multiple formats support + * added `CliDescriptor` and `HtmlDescriptor` descriptors for `server:dump` CLI and HTML formats support + +4.0.0 +----- + + * support for passing `\ReflectionClass` instances to the `Caster::castObject()` + method has been dropped, pass class names as strings instead + * the `Data::getRawData()` method has been removed + * the `VarDumperTestTrait::assertDumpEquals()` method expects a 3rd `$filter = 0` + argument and moves `$message = ''` argument at 4th position. + * the `VarDumperTestTrait::assertDumpMatchesFormat()` method expects a 3rd `$filter = 0` + argument and moves `$message = ''` argument at 4th position. + +3.4.0 +----- + + * added `AbstractCloner::setMinDepth()` function to ensure minimum tree depth + * deprecated `MongoCaster` + +2.7.0 +----- + + * deprecated `Cloner\Data::getLimitedClone()`. Use `withMaxDepth`, `withMaxItemsPerDepth` or `withRefHandles` instead. diff --git a/vendor/symfony/var-dumper/Caster/AmqpCaster.php b/vendor/symfony/var-dumper/Caster/AmqpCaster.php new file mode 100644 index 0000000..883d02b --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/AmqpCaster.php @@ -0,0 +1,212 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts Amqp related classes to array representation. + * + * @author Grégoire Pineau + * + * @final + */ +class AmqpCaster +{ + private static $flags = [ + AMQP_DURABLE => 'AMQP_DURABLE', + AMQP_PASSIVE => 'AMQP_PASSIVE', + AMQP_EXCLUSIVE => 'AMQP_EXCLUSIVE', + AMQP_AUTODELETE => 'AMQP_AUTODELETE', + AMQP_INTERNAL => 'AMQP_INTERNAL', + AMQP_NOLOCAL => 'AMQP_NOLOCAL', + AMQP_AUTOACK => 'AMQP_AUTOACK', + AMQP_IFEMPTY => 'AMQP_IFEMPTY', + AMQP_IFUNUSED => 'AMQP_IFUNUSED', + AMQP_MANDATORY => 'AMQP_MANDATORY', + AMQP_IMMEDIATE => 'AMQP_IMMEDIATE', + AMQP_MULTIPLE => 'AMQP_MULTIPLE', + AMQP_NOWAIT => 'AMQP_NOWAIT', + AMQP_REQUEUE => 'AMQP_REQUEUE', + ]; + + private static $exchangeTypes = [ + AMQP_EX_TYPE_DIRECT => 'AMQP_EX_TYPE_DIRECT', + AMQP_EX_TYPE_FANOUT => 'AMQP_EX_TYPE_FANOUT', + AMQP_EX_TYPE_TOPIC => 'AMQP_EX_TYPE_TOPIC', + AMQP_EX_TYPE_HEADERS => 'AMQP_EX_TYPE_HEADERS', + ]; + + public static function castConnection(\AMQPConnection $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'is_connected' => $c->isConnected(), + ]; + + // Recent version of the extension already expose private properties + if (isset($a["\x00AMQPConnection\x00login"])) { + return $a; + } + + // BC layer in the amqp lib + if (method_exists($c, 'getReadTimeout')) { + $timeout = $c->getReadTimeout(); + } else { + $timeout = $c->getTimeout(); + } + + $a += [ + $prefix.'is_connected' => $c->isConnected(), + $prefix.'login' => $c->getLogin(), + $prefix.'password' => $c->getPassword(), + $prefix.'host' => $c->getHost(), + $prefix.'vhost' => $c->getVhost(), + $prefix.'port' => $c->getPort(), + $prefix.'read_timeout' => $timeout, + ]; + + return $a; + } + + public static function castChannel(\AMQPChannel $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'is_connected' => $c->isConnected(), + $prefix.'channel_id' => $c->getChannelId(), + ]; + + // Recent version of the extension already expose private properties + if (isset($a["\x00AMQPChannel\x00connection"])) { + return $a; + } + + $a += [ + $prefix.'connection' => $c->getConnection(), + $prefix.'prefetch_size' => $c->getPrefetchSize(), + $prefix.'prefetch_count' => $c->getPrefetchCount(), + ]; + + return $a; + } + + public static function castQueue(\AMQPQueue $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'flags' => self::extractFlags($c->getFlags()), + ]; + + // Recent version of the extension already expose private properties + if (isset($a["\x00AMQPQueue\x00name"])) { + return $a; + } + + $a += [ + $prefix.'connection' => $c->getConnection(), + $prefix.'channel' => $c->getChannel(), + $prefix.'name' => $c->getName(), + $prefix.'arguments' => $c->getArguments(), + ]; + + return $a; + } + + public static function castExchange(\AMQPExchange $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'flags' => self::extractFlags($c->getFlags()), + ]; + + $type = isset(self::$exchangeTypes[$c->getType()]) ? new ConstStub(self::$exchangeTypes[$c->getType()], $c->getType()) : $c->getType(); + + // Recent version of the extension already expose private properties + if (isset($a["\x00AMQPExchange\x00name"])) { + $a["\x00AMQPExchange\x00type"] = $type; + + return $a; + } + + $a += [ + $prefix.'connection' => $c->getConnection(), + $prefix.'channel' => $c->getChannel(), + $prefix.'name' => $c->getName(), + $prefix.'type' => $type, + $prefix.'arguments' => $c->getArguments(), + ]; + + return $a; + } + + public static function castEnvelope(\AMQPEnvelope $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $deliveryMode = new ConstStub($c->getDeliveryMode().(2 === $c->getDeliveryMode() ? ' (persistent)' : ' (non-persistent)'), $c->getDeliveryMode()); + + // Recent version of the extension already expose private properties + if (isset($a["\x00AMQPEnvelope\x00body"])) { + $a["\0AMQPEnvelope\0delivery_mode"] = $deliveryMode; + + return $a; + } + + if (!($filter & Caster::EXCLUDE_VERBOSE)) { + $a += [$prefix.'body' => $c->getBody()]; + } + + $a += [ + $prefix.'delivery_tag' => $c->getDeliveryTag(), + $prefix.'is_redelivery' => $c->isRedelivery(), + $prefix.'exchange_name' => $c->getExchangeName(), + $prefix.'routing_key' => $c->getRoutingKey(), + $prefix.'content_type' => $c->getContentType(), + $prefix.'content_encoding' => $c->getContentEncoding(), + $prefix.'headers' => $c->getHeaders(), + $prefix.'delivery_mode' => $deliveryMode, + $prefix.'priority' => $c->getPriority(), + $prefix.'correlation_id' => $c->getCorrelationId(), + $prefix.'reply_to' => $c->getReplyTo(), + $prefix.'expiration' => $c->getExpiration(), + $prefix.'message_id' => $c->getMessageId(), + $prefix.'timestamp' => $c->getTimeStamp(), + $prefix.'type' => $c->getType(), + $prefix.'user_id' => $c->getUserId(), + $prefix.'app_id' => $c->getAppId(), + ]; + + return $a; + } + + private static function extractFlags(int $flags): ConstStub + { + $flagsArray = []; + + foreach (self::$flags as $value => $name) { + if ($flags & $value) { + $flagsArray[] = $name; + } + } + + if (!$flagsArray) { + $flagsArray = ['AMQP_NOPARAM']; + } + + return new ConstStub(implode('|', $flagsArray), $flags); + } +} diff --git a/vendor/symfony/var-dumper/Caster/ArgsStub.php b/vendor/symfony/var-dumper/Caster/ArgsStub.php new file mode 100644 index 0000000..591c7e2 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ArgsStub.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Represents a list of function arguments. + * + * @author Nicolas Grekas + */ +class ArgsStub extends EnumStub +{ + private static $parameters = []; + + public function __construct(array $args, string $function, ?string $class) + { + list($variadic, $params) = self::getParameters($function, $class); + + $values = []; + foreach ($args as $k => $v) { + $values[$k] = !is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v; + } + if (null === $params) { + parent::__construct($values, false); + + return; + } + if (\count($values) < \count($params)) { + $params = \array_slice($params, 0, \count($values)); + } elseif (\count($values) > \count($params)) { + $values[] = new EnumStub(array_splice($values, \count($params)), false); + $params[] = $variadic; + } + if (['...'] === $params) { + $this->dumpKeys = false; + $this->value = $values[0]->value; + } else { + $this->value = array_combine($params, $values); + } + } + + private static function getParameters(string $function, ?string $class): array + { + if (isset(self::$parameters[$k = $class.'::'.$function])) { + return self::$parameters[$k]; + } + + try { + $r = null !== $class ? new \ReflectionMethod($class, $function) : new \ReflectionFunction($function); + } catch (\ReflectionException $e) { + return [null, null]; + } + + $variadic = '...'; + $params = []; + foreach ($r->getParameters() as $v) { + $k = '$'.$v->name; + if ($v->isPassedByReference()) { + $k = '&'.$k; + } + if ($v->isVariadic()) { + $variadic .= $k; + } else { + $params[] = $k; + } + } + + return self::$parameters[$k] = [$variadic, $params]; + } +} diff --git a/vendor/symfony/var-dumper/Caster/Caster.php b/vendor/symfony/var-dumper/Caster/Caster.php new file mode 100644 index 0000000..5f3550f --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/Caster.php @@ -0,0 +1,170 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Helper for filtering out properties in casters. + * + * @author Nicolas Grekas + * + * @final + */ +class Caster +{ + const EXCLUDE_VERBOSE = 1; + const EXCLUDE_VIRTUAL = 2; + const EXCLUDE_DYNAMIC = 4; + const EXCLUDE_PUBLIC = 8; + const EXCLUDE_PROTECTED = 16; + const EXCLUDE_PRIVATE = 32; + const EXCLUDE_NULL = 64; + const EXCLUDE_EMPTY = 128; + const EXCLUDE_NOT_IMPORTANT = 256; + const EXCLUDE_STRICT = 512; + + const PREFIX_VIRTUAL = "\0~\0"; + const PREFIX_DYNAMIC = "\0+\0"; + const PREFIX_PROTECTED = "\0*\0"; + + /** + * Casts objects to arrays and adds the dynamic property prefix. + * + * @param bool $hasDebugInfo Whether the __debugInfo method exists on $obj or not + * + * @return array The array-cast of the object, with prefixed dynamic properties + */ + public static function castObject(object $obj, string $class, bool $hasDebugInfo = false): array + { + if ($hasDebugInfo) { + try { + $debugInfo = $obj->__debugInfo(); + } catch (\Exception $e) { + // ignore failing __debugInfo() + $hasDebugInfo = false; + } + } + + $a = $obj instanceof \Closure ? [] : (array) $obj; + + if ($obj instanceof \__PHP_Incomplete_Class) { + return $a; + } + + if ($a) { + static $publicProperties = []; + + $i = 0; + $prefixedKeys = []; + foreach ($a as $k => $v) { + if ("\0" !== ($k[0] ?? '')) { + if (!isset($publicProperties[$class])) { + foreach ((new \ReflectionClass($class))->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) { + $publicProperties[$class][$prop->name] = true; + } + } + if (!isset($publicProperties[$class][$k])) { + $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k; + } + } elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) { + $prefixedKeys[$i] = "\0".get_parent_class($class).'@anonymous'.strrchr($k, "\0"); + } + ++$i; + } + if ($prefixedKeys) { + $keys = array_keys($a); + foreach ($prefixedKeys as $i => $k) { + $keys[$i] = $k; + } + $a = array_combine($keys, $a); + } + } + + if ($hasDebugInfo && \is_array($debugInfo)) { + foreach ($debugInfo as $k => $v) { + if (!isset($k[0]) || "\0" !== $k[0]) { + $k = self::PREFIX_VIRTUAL.$k; + } + + unset($a[$k]); + $a[$k] = $v; + } + } + + return $a; + } + + /** + * Filters out the specified properties. + * + * By default, a single match in the $filter bit field filters properties out, following an "or" logic. + * When EXCLUDE_STRICT is set, an "and" logic is applied: all bits must match for a property to be removed. + * + * @param array $a The array containing the properties to filter + * @param int $filter A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out + * @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set + * @param int &$count Set to the number of removed properties + * + * @return array The filtered array + */ + public static function filter(array $a, int $filter, array $listedProperties = [], ?int &$count = 0): array + { + $count = 0; + + foreach ($a as $k => $v) { + $type = self::EXCLUDE_STRICT & $filter; + + if (null === $v) { + $type |= self::EXCLUDE_NULL & $filter; + $type |= self::EXCLUDE_EMPTY & $filter; + } elseif (false === $v || '' === $v || '0' === $v || 0 === $v || 0.0 === $v || [] === $v) { + $type |= self::EXCLUDE_EMPTY & $filter; + } + if ((self::EXCLUDE_NOT_IMPORTANT & $filter) && !\in_array($k, $listedProperties, true)) { + $type |= self::EXCLUDE_NOT_IMPORTANT; + } + if ((self::EXCLUDE_VERBOSE & $filter) && \in_array($k, $listedProperties, true)) { + $type |= self::EXCLUDE_VERBOSE; + } + + if (!isset($k[1]) || "\0" !== $k[0]) { + $type |= self::EXCLUDE_PUBLIC & $filter; + } elseif ('~' === $k[1]) { + $type |= self::EXCLUDE_VIRTUAL & $filter; + } elseif ('+' === $k[1]) { + $type |= self::EXCLUDE_DYNAMIC & $filter; + } elseif ('*' === $k[1]) { + $type |= self::EXCLUDE_PROTECTED & $filter; + } else { + $type |= self::EXCLUDE_PRIVATE & $filter; + } + + if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) { + unset($a[$k]); + ++$count; + } + } + + return $a; + } + + public static function castPhpIncompleteClass(\__PHP_Incomplete_Class $c, array $a, Stub $stub, bool $isNested): array + { + if (isset($a['__PHP_Incomplete_Class_Name'])) { + $stub->class .= '('.$a['__PHP_Incomplete_Class_Name'].')'; + unset($a['__PHP_Incomplete_Class_Name']); + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/ClassStub.php b/vendor/symfony/var-dumper/Caster/ClassStub.php new file mode 100644 index 0000000..758fe57 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ClassStub.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Represents a PHP class identifier. + * + * @author Nicolas Grekas + */ +class ClassStub extends ConstStub +{ + /** + * @param string $identifier A PHP identifier, e.g. a class, method, interface, etc. name + * @param callable $callable The callable targeted by the identifier when it is ambiguous or not a real PHP identifier + */ + public function __construct(string $identifier, $callable = null) + { + $this->value = $identifier; + + try { + if (null !== $callable) { + if ($callable instanceof \Closure) { + $r = new \ReflectionFunction($callable); + } elseif (\is_object($callable)) { + $r = [$callable, '__invoke']; + } elseif (\is_array($callable)) { + $r = $callable; + } elseif (false !== $i = strpos($callable, '::')) { + $r = [substr($callable, 0, $i), substr($callable, 2 + $i)]; + } else { + $r = new \ReflectionFunction($callable); + } + } elseif (0 < $i = strpos($identifier, '::') ?: strpos($identifier, '->')) { + $r = [substr($identifier, 0, $i), substr($identifier, 2 + $i)]; + } else { + $r = new \ReflectionClass($identifier); + } + + if (\is_array($r)) { + try { + $r = new \ReflectionMethod($r[0], $r[1]); + } catch (\ReflectionException $e) { + $r = new \ReflectionClass($r[0]); + } + } + + if (false !== strpos($identifier, "class@anonymous\0")) { + $this->value = $identifier = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:)[0-9a-fA-F]++/', function ($m) { + return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0]; + }, $identifier); + } + + if (null !== $callable && $r instanceof \ReflectionFunctionAbstract) { + $s = ReflectionCaster::castFunctionAbstract($r, [], new Stub(), true, Caster::EXCLUDE_VERBOSE); + $s = ReflectionCaster::getSignature($s); + + if ('()' === substr($identifier, -2)) { + $this->value = substr_replace($identifier, $s, -2); + } else { + $this->value .= $s; + } + } + } catch (\ReflectionException $e) { + return; + } finally { + if (0 < $i = strrpos($this->value, '\\')) { + $this->attr['ellipsis'] = \strlen($this->value) - $i; + $this->attr['ellipsis-type'] = 'class'; + $this->attr['ellipsis-tail'] = 1; + } + } + + if ($f = $r->getFileName()) { + $this->attr['file'] = $f; + $this->attr['line'] = $r->getStartLine(); + } + } + + public static function wrapCallable($callable) + { + if (\is_object($callable) || !\is_callable($callable)) { + return $callable; + } + + if (!\is_array($callable)) { + $callable = new static($callable, $callable); + } elseif (\is_string($callable[0])) { + $callable[0] = new static($callable[0], $callable); + } else { + $callable[1] = new static($callable[1], $callable); + } + + return $callable; + } +} diff --git a/vendor/symfony/var-dumper/Caster/ConstStub.php b/vendor/symfony/var-dumper/Caster/ConstStub.php new file mode 100644 index 0000000..8b01797 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ConstStub.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Represents a PHP constant and its value. + * + * @author Nicolas Grekas + */ +class ConstStub extends Stub +{ + public function __construct(string $name, $value = null) + { + $this->class = $name; + $this->value = 1 < \func_num_args() ? $value : $name; + } + + /** + * @return string + */ + public function __toString() + { + return (string) $this->value; + } +} diff --git a/vendor/symfony/var-dumper/Caster/CutArrayStub.php b/vendor/symfony/var-dumper/Caster/CutArrayStub.php new file mode 100644 index 0000000..0e4fb36 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/CutArrayStub.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +/** + * Represents a cut array. + * + * @author Nicolas Grekas + */ +class CutArrayStub extends CutStub +{ + public $preservedSubset; + + public function __construct(array $value, array $preservedKeys) + { + parent::__construct($value); + + $this->preservedSubset = array_intersect_key($value, array_flip($preservedKeys)); + $this->cut -= \count($this->preservedSubset); + } +} diff --git a/vendor/symfony/var-dumper/Caster/CutStub.php b/vendor/symfony/var-dumper/Caster/CutStub.php new file mode 100644 index 0000000..464c6db --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/CutStub.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Represents the main properties of a PHP variable, pre-casted by a caster. + * + * @author Nicolas Grekas + */ +class CutStub extends Stub +{ + public function __construct($value) + { + $this->value = $value; + + switch (\gettype($value)) { + case 'object': + $this->type = self::TYPE_OBJECT; + $this->class = \get_class($value); + + if ($value instanceof \Closure) { + ReflectionCaster::castClosure($value, [], $this, true, Caster::EXCLUDE_VERBOSE); + } + + $this->cut = -1; + break; + + case 'array': + $this->type = self::TYPE_ARRAY; + $this->class = self::ARRAY_ASSOC; + $this->cut = $this->value = \count($value); + break; + + case 'resource': + case 'unknown type': + case 'resource (closed)': + $this->type = self::TYPE_RESOURCE; + $this->handle = (int) $value; + if ('Unknown' === $this->class = @get_resource_type($value)) { + $this->class = 'Closed'; + } + $this->cut = -1; + break; + + case 'string': + $this->type = self::TYPE_STRING; + $this->class = preg_match('//u', $value) ? self::STRING_UTF8 : self::STRING_BINARY; + $this->cut = self::STRING_BINARY === $this->class ? \strlen($value) : mb_strlen($value, 'UTF-8'); + $this->value = ''; + break; + } + } +} diff --git a/vendor/symfony/var-dumper/Caster/DOMCaster.php b/vendor/symfony/var-dumper/Caster/DOMCaster.php new file mode 100644 index 0000000..98359ff --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/DOMCaster.php @@ -0,0 +1,304 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts DOM related classes to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class DOMCaster +{ + private static $errorCodes = [ + DOM_PHP_ERR => 'DOM_PHP_ERR', + DOM_INDEX_SIZE_ERR => 'DOM_INDEX_SIZE_ERR', + DOMSTRING_SIZE_ERR => 'DOMSTRING_SIZE_ERR', + DOM_HIERARCHY_REQUEST_ERR => 'DOM_HIERARCHY_REQUEST_ERR', + DOM_WRONG_DOCUMENT_ERR => 'DOM_WRONG_DOCUMENT_ERR', + DOM_INVALID_CHARACTER_ERR => 'DOM_INVALID_CHARACTER_ERR', + DOM_NO_DATA_ALLOWED_ERR => 'DOM_NO_DATA_ALLOWED_ERR', + DOM_NO_MODIFICATION_ALLOWED_ERR => 'DOM_NO_MODIFICATION_ALLOWED_ERR', + DOM_NOT_FOUND_ERR => 'DOM_NOT_FOUND_ERR', + DOM_NOT_SUPPORTED_ERR => 'DOM_NOT_SUPPORTED_ERR', + DOM_INUSE_ATTRIBUTE_ERR => 'DOM_INUSE_ATTRIBUTE_ERR', + DOM_INVALID_STATE_ERR => 'DOM_INVALID_STATE_ERR', + DOM_SYNTAX_ERR => 'DOM_SYNTAX_ERR', + DOM_INVALID_MODIFICATION_ERR => 'DOM_INVALID_MODIFICATION_ERR', + DOM_NAMESPACE_ERR => 'DOM_NAMESPACE_ERR', + DOM_INVALID_ACCESS_ERR => 'DOM_INVALID_ACCESS_ERR', + DOM_VALIDATION_ERR => 'DOM_VALIDATION_ERR', + ]; + + private static $nodeTypes = [ + XML_ELEMENT_NODE => 'XML_ELEMENT_NODE', + XML_ATTRIBUTE_NODE => 'XML_ATTRIBUTE_NODE', + XML_TEXT_NODE => 'XML_TEXT_NODE', + XML_CDATA_SECTION_NODE => 'XML_CDATA_SECTION_NODE', + XML_ENTITY_REF_NODE => 'XML_ENTITY_REF_NODE', + XML_ENTITY_NODE => 'XML_ENTITY_NODE', + XML_PI_NODE => 'XML_PI_NODE', + XML_COMMENT_NODE => 'XML_COMMENT_NODE', + XML_DOCUMENT_NODE => 'XML_DOCUMENT_NODE', + XML_DOCUMENT_TYPE_NODE => 'XML_DOCUMENT_TYPE_NODE', + XML_DOCUMENT_FRAG_NODE => 'XML_DOCUMENT_FRAG_NODE', + XML_NOTATION_NODE => 'XML_NOTATION_NODE', + XML_HTML_DOCUMENT_NODE => 'XML_HTML_DOCUMENT_NODE', + XML_DTD_NODE => 'XML_DTD_NODE', + XML_ELEMENT_DECL_NODE => 'XML_ELEMENT_DECL_NODE', + XML_ATTRIBUTE_DECL_NODE => 'XML_ATTRIBUTE_DECL_NODE', + XML_ENTITY_DECL_NODE => 'XML_ENTITY_DECL_NODE', + XML_NAMESPACE_DECL_NODE => 'XML_NAMESPACE_DECL_NODE', + ]; + + public static function castException(\DOMException $e, array $a, Stub $stub, bool $isNested) + { + $k = Caster::PREFIX_PROTECTED.'code'; + if (isset($a[$k], self::$errorCodes[$a[$k]])) { + $a[$k] = new ConstStub(self::$errorCodes[$a[$k]], $a[$k]); + } + + return $a; + } + + public static function castLength($dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'length' => $dom->length, + ]; + + return $a; + } + + public static function castImplementation($dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + Caster::PREFIX_VIRTUAL.'Core' => '1.0', + Caster::PREFIX_VIRTUAL.'XML' => '2.0', + ]; + + return $a; + } + + public static function castNode(\DOMNode $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'nodeName' => $dom->nodeName, + 'nodeValue' => new CutStub($dom->nodeValue), + 'nodeType' => new ConstStub(self::$nodeTypes[$dom->nodeType], $dom->nodeType), + 'parentNode' => new CutStub($dom->parentNode), + 'childNodes' => $dom->childNodes, + 'firstChild' => new CutStub($dom->firstChild), + 'lastChild' => new CutStub($dom->lastChild), + 'previousSibling' => new CutStub($dom->previousSibling), + 'nextSibling' => new CutStub($dom->nextSibling), + 'attributes' => $dom->attributes, + 'ownerDocument' => new CutStub($dom->ownerDocument), + 'namespaceURI' => $dom->namespaceURI, + 'prefix' => $dom->prefix, + 'localName' => $dom->localName, + 'baseURI' => $dom->baseURI ? new LinkStub($dom->baseURI) : $dom->baseURI, + 'textContent' => new CutStub($dom->textContent), + ]; + + return $a; + } + + public static function castNameSpaceNode(\DOMNameSpaceNode $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'nodeName' => $dom->nodeName, + 'nodeValue' => new CutStub($dom->nodeValue), + 'nodeType' => new ConstStub(self::$nodeTypes[$dom->nodeType], $dom->nodeType), + 'prefix' => $dom->prefix, + 'localName' => $dom->localName, + 'namespaceURI' => $dom->namespaceURI, + 'ownerDocument' => new CutStub($dom->ownerDocument), + 'parentNode' => new CutStub($dom->parentNode), + ]; + + return $a; + } + + public static function castDocument(\DOMDocument $dom, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $a += [ + 'doctype' => $dom->doctype, + 'implementation' => $dom->implementation, + 'documentElement' => new CutStub($dom->documentElement), + 'actualEncoding' => $dom->actualEncoding, + 'encoding' => $dom->encoding, + 'xmlEncoding' => $dom->xmlEncoding, + 'standalone' => $dom->standalone, + 'xmlStandalone' => $dom->xmlStandalone, + 'version' => $dom->version, + 'xmlVersion' => $dom->xmlVersion, + 'strictErrorChecking' => $dom->strictErrorChecking, + 'documentURI' => $dom->documentURI ? new LinkStub($dom->documentURI) : $dom->documentURI, + 'config' => $dom->config, + 'formatOutput' => $dom->formatOutput, + 'validateOnParse' => $dom->validateOnParse, + 'resolveExternals' => $dom->resolveExternals, + 'preserveWhiteSpace' => $dom->preserveWhiteSpace, + 'recover' => $dom->recover, + 'substituteEntities' => $dom->substituteEntities, + ]; + + if (!($filter & Caster::EXCLUDE_VERBOSE)) { + $formatOutput = $dom->formatOutput; + $dom->formatOutput = true; + $a += [Caster::PREFIX_VIRTUAL.'xml' => $dom->saveXML()]; + $dom->formatOutput = $formatOutput; + } + + return $a; + } + + public static function castCharacterData(\DOMCharacterData $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'data' => $dom->data, + 'length' => $dom->length, + ]; + + return $a; + } + + public static function castAttr(\DOMAttr $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'name' => $dom->name, + 'specified' => $dom->specified, + 'value' => $dom->value, + 'ownerElement' => $dom->ownerElement, + 'schemaTypeInfo' => $dom->schemaTypeInfo, + ]; + + return $a; + } + + public static function castElement(\DOMElement $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'tagName' => $dom->tagName, + 'schemaTypeInfo' => $dom->schemaTypeInfo, + ]; + + return $a; + } + + public static function castText(\DOMText $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'wholeText' => $dom->wholeText, + ]; + + return $a; + } + + public static function castTypeinfo(\DOMTypeinfo $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'typeName' => $dom->typeName, + 'typeNamespace' => $dom->typeNamespace, + ]; + + return $a; + } + + public static function castDomError(\DOMDomError $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'severity' => $dom->severity, + 'message' => $dom->message, + 'type' => $dom->type, + 'relatedException' => $dom->relatedException, + 'related_data' => $dom->related_data, + 'location' => $dom->location, + ]; + + return $a; + } + + public static function castLocator(\DOMLocator $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'lineNumber' => $dom->lineNumber, + 'columnNumber' => $dom->columnNumber, + 'offset' => $dom->offset, + 'relatedNode' => $dom->relatedNode, + 'uri' => $dom->uri ? new LinkStub($dom->uri, $dom->lineNumber) : $dom->uri, + ]; + + return $a; + } + + public static function castDocumentType(\DOMDocumentType $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'name' => $dom->name, + 'entities' => $dom->entities, + 'notations' => $dom->notations, + 'publicId' => $dom->publicId, + 'systemId' => $dom->systemId, + 'internalSubset' => $dom->internalSubset, + ]; + + return $a; + } + + public static function castNotation(\DOMNotation $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'publicId' => $dom->publicId, + 'systemId' => $dom->systemId, + ]; + + return $a; + } + + public static function castEntity(\DOMEntity $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'publicId' => $dom->publicId, + 'systemId' => $dom->systemId, + 'notationName' => $dom->notationName, + 'actualEncoding' => $dom->actualEncoding, + 'encoding' => $dom->encoding, + 'version' => $dom->version, + ]; + + return $a; + } + + public static function castProcessingInstruction(\DOMProcessingInstruction $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'target' => $dom->target, + 'data' => $dom->data, + ]; + + return $a; + } + + public static function castXPath(\DOMXPath $dom, array $a, Stub $stub, bool $isNested) + { + $a += [ + 'document' => $dom->document, + ]; + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/DateCaster.php b/vendor/symfony/var-dumper/Caster/DateCaster.php new file mode 100644 index 0000000..e36fbe3 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/DateCaster.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts DateTimeInterface related classes to array representation. + * + * @author Dany Maillard + * + * @final + */ +class DateCaster +{ + private const PERIOD_LIMIT = 3; + + public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, bool $isNested, int $filter) + { + $prefix = Caster::PREFIX_VIRTUAL; + $location = $d->getTimezone()->getLocation(); + $fromNow = (new \DateTime())->diff($d); + + $title = $d->format('l, F j, Y') + ."\n".self::formatInterval($fromNow).' from now' + .($location ? ($d->format('I') ? "\nDST On" : "\nDST Off") : '') + ; + + $a = []; + $a[$prefix.'date'] = new ConstStub(self::formatDateTime($d, $location ? ' e (P)' : ' P'), $title); + + $stub->class .= $d->format(' @U'); + + return $a; + } + + public static function castInterval(\DateInterval $interval, array $a, Stub $stub, bool $isNested, int $filter) + { + $now = new \DateTimeImmutable(); + $numberOfSeconds = $now->add($interval)->getTimestamp() - $now->getTimestamp(); + $title = number_format($numberOfSeconds, 0, '.', ' ').'s'; + + $i = [Caster::PREFIX_VIRTUAL.'interval' => new ConstStub(self::formatInterval($interval), $title)]; + + return $filter & Caster::EXCLUDE_VERBOSE ? $i : $i + $a; + } + + private static function formatInterval(\DateInterval $i): string + { + $format = '%R '; + + if (0 === $i->y && 0 === $i->m && ($i->h >= 24 || $i->i >= 60 || $i->s >= 60)) { + $i = date_diff($d = new \DateTime(), date_add(clone $d, $i)); // recalculate carry over points + $format .= 0 < $i->days ? '%ad ' : ''; + } else { + $format .= ($i->y ? '%yy ' : '').($i->m ? '%mm ' : '').($i->d ? '%dd ' : ''); + } + + $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:'.self::formatSeconds($i->s, substr($i->f, 2)) : ''; + $format = '%R ' === $format ? '0s' : $format; + + return $i->format(rtrim($format)); + } + + public static function castTimeZone(\DateTimeZone $timeZone, array $a, Stub $stub, bool $isNested, int $filter) + { + $location = $timeZone->getLocation(); + $formatted = (new \DateTime('now', $timeZone))->format($location ? 'e (P)' : 'P'); + $title = $location && \extension_loaded('intl') ? \Locale::getDisplayRegion('-'.$location['country_code']) : ''; + + $z = [Caster::PREFIX_VIRTUAL.'timezone' => new ConstStub($formatted, $title)]; + + return $filter & Caster::EXCLUDE_VERBOSE ? $z : $z + $a; + } + + public static function castPeriod(\DatePeriod $p, array $a, Stub $stub, bool $isNested, int $filter) + { + $dates = []; + foreach (clone $p as $i => $d) { + if (self::PERIOD_LIMIT === $i) { + $now = new \DateTimeImmutable(); + $dates[] = sprintf('%s more', ($end = $p->getEndDate()) + ? ceil(($end->format('U.u') - $d->format('U.u')) / ((int) $now->add($p->getDateInterval())->format('U.u') - (int) $now->format('U.u'))) + : $p->recurrences - $i + ); + break; + } + $dates[] = sprintf('%s) %s', $i + 1, self::formatDateTime($d)); + } + + $period = sprintf( + 'every %s, from %s (%s) %s', + self::formatInterval($p->getDateInterval()), + self::formatDateTime($p->getStartDate()), + $p->include_start_date ? 'included' : 'excluded', + ($end = $p->getEndDate()) ? 'to '.self::formatDateTime($end) : 'recurring '.$p->recurrences.' time/s' + ); + + $p = [Caster::PREFIX_VIRTUAL.'period' => new ConstStub($period, implode("\n", $dates))]; + + return $filter & Caster::EXCLUDE_VERBOSE ? $p : $p + $a; + } + + private static function formatDateTime(\DateTimeInterface $d, string $extra = ''): string + { + return $d->format('Y-m-d H:i:'.self::formatSeconds($d->format('s'), $d->format('u')).$extra); + } + + private static function formatSeconds(string $s, string $us): string + { + return sprintf('%02d.%s', $s, 0 === ($len = \strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us)); + } +} diff --git a/vendor/symfony/var-dumper/Caster/DoctrineCaster.php b/vendor/symfony/var-dumper/Caster/DoctrineCaster.php new file mode 100644 index 0000000..129b2cb --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/DoctrineCaster.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Doctrine\Common\Proxy\Proxy as CommonProxy; +use Doctrine\ORM\PersistentCollection; +use Doctrine\ORM\Proxy\Proxy as OrmProxy; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts Doctrine related classes to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class DoctrineCaster +{ + public static function castCommonProxy(CommonProxy $proxy, array $a, Stub $stub, bool $isNested) + { + foreach (['__cloner__', '__initializer__'] as $k) { + if (\array_key_exists($k, $a)) { + unset($a[$k]); + ++$stub->cut; + } + } + + return $a; + } + + public static function castOrmProxy(OrmProxy $proxy, array $a, Stub $stub, bool $isNested) + { + foreach (['_entityPersister', '_identifier'] as $k) { + if (\array_key_exists($k = "\0Doctrine\\ORM\\Proxy\\Proxy\0".$k, $a)) { + unset($a[$k]); + ++$stub->cut; + } + } + + return $a; + } + + public static function castPersistentCollection(PersistentCollection $coll, array $a, Stub $stub, bool $isNested) + { + foreach (['snapshot', 'association', 'typeClass'] as $k) { + if (\array_key_exists($k = "\0Doctrine\\ORM\\PersistentCollection\0".$k, $a)) { + $a[$k] = new CutStub($a[$k]); + } + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/DsCaster.php b/vendor/symfony/var-dumper/Caster/DsCaster.php new file mode 100644 index 0000000..b34b670 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/DsCaster.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Ds\Collection; +use Ds\Map; +use Ds\Pair; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts Ds extension classes to array representation. + * + * @author Jáchym Toušek + * + * @final + */ +class DsCaster +{ + public static function castCollection(Collection $c, array $a, Stub $stub, bool $isNested): array + { + $a[Caster::PREFIX_VIRTUAL.'count'] = $c->count(); + $a[Caster::PREFIX_VIRTUAL.'capacity'] = $c->capacity(); + + if (!$c instanceof Map) { + $a += $c->toArray(); + } + + return $a; + } + + public static function castMap(Map $c, array $a, Stub $stub, bool $isNested): array + { + foreach ($c as $k => $v) { + $a[] = new DsPairStub($k, $v); + } + + return $a; + } + + public static function castPair(Pair $c, array $a, Stub $stub, bool $isNested): array + { + foreach ($c->toArray() as $k => $v) { + $a[Caster::PREFIX_VIRTUAL.$k] = $v; + } + + return $a; + } + + public static function castPairStub(DsPairStub $c, array $a, Stub $stub, bool $isNested): array + { + if ($isNested) { + $stub->class = Pair::class; + $stub->value = null; + $stub->handle = 0; + + $a = $c->value; + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/DsPairStub.php b/vendor/symfony/var-dumper/Caster/DsPairStub.php new file mode 100644 index 0000000..a1dcc15 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/DsPairStub.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @author Nicolas Grekas + */ +class DsPairStub extends Stub +{ + public function __construct($key, $value) + { + $this->value = [ + Caster::PREFIX_VIRTUAL.'key' => $key, + Caster::PREFIX_VIRTUAL.'value' => $value, + ]; + } +} diff --git a/vendor/symfony/var-dumper/Caster/EnumStub.php b/vendor/symfony/var-dumper/Caster/EnumStub.php new file mode 100644 index 0000000..7a4e98a --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/EnumStub.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Represents an enumeration of values. + * + * @author Nicolas Grekas + */ +class EnumStub extends Stub +{ + public $dumpKeys = true; + + public function __construct(array $values, bool $dumpKeys = true) + { + $this->value = $values; + $this->dumpKeys = $dumpKeys; + } +} diff --git a/vendor/symfony/var-dumper/Caster/ExceptionCaster.php b/vendor/symfony/var-dumper/Caster/ExceptionCaster.php new file mode 100644 index 0000000..214026b --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ExceptionCaster.php @@ -0,0 +1,383 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; +use Symfony\Component\VarDumper\Cloner\Stub; +use Symfony\Component\VarDumper\Exception\ThrowingCasterException; + +/** + * Casts common Exception classes to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class ExceptionCaster +{ + public static $srcContext = 1; + public static $traceArgs = true; + public static $errorTypes = [ + E_DEPRECATED => 'E_DEPRECATED', + E_USER_DEPRECATED => 'E_USER_DEPRECATED', + E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR', + E_ERROR => 'E_ERROR', + E_WARNING => 'E_WARNING', + E_PARSE => 'E_PARSE', + E_NOTICE => 'E_NOTICE', + E_CORE_ERROR => 'E_CORE_ERROR', + E_CORE_WARNING => 'E_CORE_WARNING', + E_COMPILE_ERROR => 'E_COMPILE_ERROR', + E_COMPILE_WARNING => 'E_COMPILE_WARNING', + E_USER_ERROR => 'E_USER_ERROR', + E_USER_WARNING => 'E_USER_WARNING', + E_USER_NOTICE => 'E_USER_NOTICE', + E_STRICT => 'E_STRICT', + ]; + + private static $framesCache = []; + + public static function castError(\Error $e, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + return self::filterExceptionArray($stub->class, $a, "\0Error\0", $filter); + } + + public static function castException(\Exception $e, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + return self::filterExceptionArray($stub->class, $a, "\0Exception\0", $filter); + } + + public static function castErrorException(\ErrorException $e, array $a, Stub $stub, bool $isNested) + { + if (isset($a[$s = Caster::PREFIX_PROTECTED.'severity'], self::$errorTypes[$a[$s]])) { + $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]); + } + + return $a; + } + + public static function castThrowingCasterException(ThrowingCasterException $e, array $a, Stub $stub, bool $isNested) + { + $trace = Caster::PREFIX_VIRTUAL.'trace'; + $prefix = Caster::PREFIX_PROTECTED; + $xPrefix = "\0Exception\0"; + + if (isset($a[$xPrefix.'previous'], $a[$trace]) && $a[$xPrefix.'previous'] instanceof \Exception) { + $b = (array) $a[$xPrefix.'previous']; + $class = \get_class($a[$xPrefix.'previous']); + $class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; + self::traceUnshift($b[$xPrefix.'trace'], $class, $b[$prefix.'file'], $b[$prefix.'line']); + $a[$trace] = new TraceStub($b[$xPrefix.'trace'], false, 0, -\count($a[$trace]->value)); + } + + unset($a[$xPrefix.'previous'], $a[$prefix.'code'], $a[$prefix.'file'], $a[$prefix.'line']); + + return $a; + } + + public static function castSilencedErrorContext(SilencedErrorContext $e, array $a, Stub $stub, bool $isNested) + { + $sPrefix = "\0".SilencedErrorContext::class."\0"; + + if (!isset($a[$s = $sPrefix.'severity'])) { + return $a; + } + + if (isset(self::$errorTypes[$a[$s]])) { + $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]); + } + + $trace = [[ + 'file' => $a[$sPrefix.'file'], + 'line' => $a[$sPrefix.'line'], + ]]; + + if (isset($a[$sPrefix.'trace'])) { + $trace = array_merge($trace, $a[$sPrefix.'trace']); + } + + unset($a[$sPrefix.'file'], $a[$sPrefix.'line'], $a[$sPrefix.'trace']); + $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs); + + return $a; + } + + public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, bool $isNested) + { + if (!$isNested) { + return $a; + } + $stub->class = ''; + $stub->handle = 0; + $frames = $trace->value; + $prefix = Caster::PREFIX_VIRTUAL; + + $a = []; + $j = \count($frames); + if (0 > $i = $trace->sliceOffset) { + $i = max(0, $j + $i); + } + if (!isset($trace->value[$i])) { + return []; + } + $lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : ''; + $frames[] = ['function' => '']; + $collapse = false; + + for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) { + $f = $frames[$i]; + $call = isset($f['function']) ? (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'] : '???'; + + $frame = new FrameStub( + [ + 'object' => isset($f['object']) ? $f['object'] : null, + 'class' => isset($f['class']) ? $f['class'] : null, + 'type' => isset($f['type']) ? $f['type'] : null, + 'function' => isset($f['function']) ? $f['function'] : null, + ] + $frames[$i - 1], + false, + true + ); + $f = self::castFrameStub($frame, [], $frame, true); + if (isset($f[$prefix.'src'])) { + foreach ($f[$prefix.'src']->value as $label => $frame) { + if (0 === strpos($label, "\0~collapse=0")) { + if ($collapse) { + $label = substr_replace($label, '1', 11, 1); + } else { + $collapse = true; + } + } + $label = substr_replace($label, "title=Stack level $j.&", 2, 0); + } + $f = $frames[$i - 1]; + if ($trace->keepArgs && !empty($f['args']) && $frame instanceof EnumStub) { + $frame->value['arguments'] = new ArgsStub($f['args'], isset($f['function']) ? $f['function'] : null, isset($f['class']) ? $f['class'] : null); + } + } elseif ('???' !== $lastCall) { + $label = new ClassStub($lastCall); + if (isset($label->attr['ellipsis'])) { + $label->attr['ellipsis'] += 2; + $label = substr_replace($prefix, "ellipsis-type=class&ellipsis={$label->attr['ellipsis']}&ellipsis-tail=1&title=Stack level $j.", 2, 0).$label->value.'()'; + } else { + $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$label->value.'()'; + } + } else { + $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$lastCall; + } + $a[substr_replace($label, sprintf('separator=%s&', $frame instanceof EnumStub ? ' ' : ':'), 2, 0)] = $frame; + + $lastCall = $call; + } + if (null !== $trace->sliceLength) { + $a = \array_slice($a, 0, $trace->sliceLength, true); + } + + return $a; + } + + public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, bool $isNested) + { + if (!$isNested) { + return $a; + } + $f = $frame->value; + $prefix = Caster::PREFIX_VIRTUAL; + + if (isset($f['file'], $f['line'])) { + $cacheKey = $f; + unset($cacheKey['object'], $cacheKey['args']); + $cacheKey[] = self::$srcContext; + $cacheKey = implode('-', $cacheKey); + + if (isset(self::$framesCache[$cacheKey])) { + $a[$prefix.'src'] = self::$framesCache[$cacheKey]; + } else { + if (preg_match('/\((\d+)\)(?:\([\da-f]{32}\))? : (?:eval\(\)\'d code|runtime-created function)$/', $f['file'], $match)) { + $f['file'] = substr($f['file'], 0, -\strlen($match[0])); + $f['line'] = (int) $match[1]; + } + $src = $f['line']; + $srcKey = $f['file']; + $ellipsis = new LinkStub($srcKey, 0); + $srcAttr = 'collapse='.(int) $ellipsis->inVendor; + $ellipsisTail = isset($ellipsis->attr['ellipsis-tail']) ? $ellipsis->attr['ellipsis-tail'] : 0; + $ellipsis = isset($ellipsis->attr['ellipsis']) ? $ellipsis->attr['ellipsis'] : 0; + + if (file_exists($f['file']) && 0 <= self::$srcContext) { + if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) { + $template = isset($f['object']) ? $f['object'] : unserialize(sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class'])); + + $ellipsis = 0; + $templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : ''); + $templateInfo = $template->getDebugInfo(); + if (isset($templateInfo[$f['line']])) { + if (!method_exists($template, 'getSourceContext') || !file_exists($templatePath = $template->getSourceContext()->getPath())) { + $templatePath = null; + } + if ($templateSrc) { + $src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f); + $srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']]; + } + } + } + if ($srcKey == $f['file']) { + $src = self::extractSource(file_get_contents($f['file']), $f['line'], self::$srcContext, 'php', $f['file'], $f); + $srcKey .= ':'.$f['line']; + if ($ellipsis) { + $ellipsis += 1 + \strlen($f['line']); + } + } + $srcAttr .= sprintf('&separator= &file=%s&line=%d', rawurlencode($f['file']), $f['line']); + } else { + $srcAttr .= '&separator=:'; + } + $srcAttr .= $ellipsis ? '&ellipsis-type=path&ellipsis='.$ellipsis.'&ellipsis-tail='.$ellipsisTail : ''; + self::$framesCache[$cacheKey] = $a[$prefix.'src'] = new EnumStub(["\0~$srcAttr\0$srcKey" => $src]); + } + } + + unset($a[$prefix.'args'], $a[$prefix.'line'], $a[$prefix.'file']); + if ($frame->inTraceStub) { + unset($a[$prefix.'class'], $a[$prefix.'type'], $a[$prefix.'function']); + } + foreach ($a as $k => $v) { + if (!$v) { + unset($a[$k]); + } + } + if ($frame->keepArgs && !empty($f['args'])) { + $a[$prefix.'arguments'] = new ArgsStub($f['args'], $f['function'], $f['class']); + } + + return $a; + } + + private static function filterExceptionArray(string $xClass, array $a, string $xPrefix, int $filter): array + { + if (isset($a[$xPrefix.'trace'])) { + $trace = $a[$xPrefix.'trace']; + unset($a[$xPrefix.'trace']); // Ensures the trace is always last + } else { + $trace = []; + } + + if (!($filter & Caster::EXCLUDE_VERBOSE) && $trace) { + if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { + self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']); + } + $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs); + } + if (empty($a[$xPrefix.'previous'])) { + unset($a[$xPrefix.'previous']); + } + unset($a[$xPrefix.'string'], $a[Caster::PREFIX_DYNAMIC.'xdebug_message'], $a[Caster::PREFIX_DYNAMIC.'__destructorException']); + + if (isset($a[Caster::PREFIX_PROTECTED.'message']) && false !== strpos($a[Caster::PREFIX_PROTECTED.'message'], "class@anonymous\0")) { + $a[Caster::PREFIX_PROTECTED.'message'] = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:)[0-9a-fA-F]++/', function ($m) { + return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0]; + }, $a[Caster::PREFIX_PROTECTED.'message']); + } + + if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { + $a[Caster::PREFIX_PROTECTED.'file'] = new LinkStub($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']); + } + + return $a; + } + + private static function traceUnshift(array &$trace, ?string $class, string $file, int $line): void + { + if (isset($trace[0]['file'], $trace[0]['line']) && $trace[0]['file'] === $file && $trace[0]['line'] === $line) { + return; + } + array_unshift($trace, [ + 'function' => $class ? 'new '.$class : null, + 'file' => $file, + 'line' => $line, + ]); + } + + private static function extractSource(string $srcLines, int $line, int $srcContext, string $lang, ?string $file, array $frame): EnumStub + { + $srcLines = explode("\n", $srcLines); + $src = []; + + for ($i = $line - 1 - $srcContext; $i <= $line - 1 + $srcContext; ++$i) { + $src[] = (isset($srcLines[$i]) ? $srcLines[$i] : '')."\n"; + } + + if ($frame['function'] ?? false) { + $stub = new CutStub(new \stdClass()); + $stub->class = (isset($frame['class']) ? $frame['class'].$frame['type'] : '').$frame['function']; + $stub->type = Stub::TYPE_OBJECT; + $stub->attr['cut_hash'] = true; + $stub->attr['file'] = $frame['file']; + $stub->attr['line'] = $frame['line']; + + try { + $caller = isset($frame['class']) ? new \ReflectionMethod($frame['class'], $frame['function']) : new \ReflectionFunction($frame['function']); + $stub->class .= ReflectionCaster::getSignature(ReflectionCaster::castFunctionAbstract($caller, [], $stub, true, Caster::EXCLUDE_VERBOSE)); + + if ($f = $caller->getFileName()) { + $stub->attr['file'] = $f; + $stub->attr['line'] = $caller->getStartLine(); + } + } catch (\ReflectionException $e) { + // ignore fake class/function + } + + $srcLines = ["\0~separator=\0" => $stub]; + } else { + $stub = null; + $srcLines = []; + } + + $ltrim = 0; + do { + $pad = null; + for ($i = $srcContext << 1; $i >= 0; --$i) { + if (isset($src[$i][$ltrim]) && "\r" !== ($c = $src[$i][$ltrim]) && "\n" !== $c) { + if (null === $pad) { + $pad = $c; + } + if ((' ' !== $c && "\t" !== $c) || $pad !== $c) { + break; + } + } + } + ++$ltrim; + } while (0 > $i && null !== $pad); + + --$ltrim; + + foreach ($src as $i => $c) { + if ($ltrim) { + $c = isset($c[$ltrim]) && "\r" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, " \t"); + } + $c = substr($c, 0, -1); + if ($i !== $srcContext) { + $c = new ConstStub('default', $c); + } else { + $c = new ConstStub($c, $stub ? 'in '.$stub->class : ''); + if (null !== $file) { + $c->attr['file'] = $file; + $c->attr['line'] = $line; + } + } + $c->attr['lang'] = $lang; + $srcLines[sprintf("\0~separator=› &%d\0", $i + $line - $srcContext)] = $c; + } + + return new EnumStub($srcLines); + } +} diff --git a/vendor/symfony/var-dumper/Caster/FrameStub.php b/vendor/symfony/var-dumper/Caster/FrameStub.php new file mode 100644 index 0000000..8786755 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/FrameStub.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +/** + * Represents a single backtrace frame as returned by debug_backtrace() or Exception->getTrace(). + * + * @author Nicolas Grekas + */ +class FrameStub extends EnumStub +{ + public $keepArgs; + public $inTraceStub; + + public function __construct(array $frame, bool $keepArgs = true, bool $inTraceStub = false) + { + $this->value = $frame; + $this->keepArgs = $keepArgs; + $this->inTraceStub = $inTraceStub; + } +} diff --git a/vendor/symfony/var-dumper/Caster/GmpCaster.php b/vendor/symfony/var-dumper/Caster/GmpCaster.php new file mode 100644 index 0000000..b018cc7 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/GmpCaster.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts GMP objects to array representation. + * + * @author Hamza Amrouche + * @author Nicolas Grekas + * + * @final + */ +class GmpCaster +{ + public static function castGmp(\GMP $gmp, array $a, Stub $stub, bool $isNested, int $filter): array + { + $a[Caster::PREFIX_VIRTUAL.'value'] = new ConstStub(gmp_strval($gmp), gmp_strval($gmp)); + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/ImagineCaster.php b/vendor/symfony/var-dumper/Caster/ImagineCaster.php new file mode 100644 index 0000000..d1289da --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ImagineCaster.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Imagine\Image\ImageInterface; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @author Grégoire Pineau + */ +final class ImagineCaster +{ + public static function castImage(ImageInterface $c, array $a, Stub $stub, bool $isNested): array + { + $imgData = $c->get('png'); + if (\strlen($imgData) > 1 * 1000 * 1000) { + $a += [ + Caster::PREFIX_VIRTUAL.'image' => new ConstStub($c->getSize()), + ]; + } else { + $a += [ + Caster::PREFIX_VIRTUAL.'image' => new ImgStub($imgData, 'image/png', $c->getSize()), + ]; + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/ImgStub.php b/vendor/symfony/var-dumper/Caster/ImgStub.php new file mode 100644 index 0000000..05789fe --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ImgStub.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +/** + * @author Grégoire Pineau + */ +class ImgStub extends ConstStub +{ + public function __construct(string $data, string $contentType, string $size) + { + $this->value = ''; + $this->attr['img-data'] = $data; + $this->attr['img-size'] = $size; + $this->attr['content-type'] = $contentType; + } +} diff --git a/vendor/symfony/var-dumper/Caster/IntlCaster.php b/vendor/symfony/var-dumper/Caster/IntlCaster.php new file mode 100644 index 0000000..23b9d5d --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/IntlCaster.php @@ -0,0 +1,172 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @author Nicolas Grekas + * @author Jan Schädlich + * + * @final + */ +class IntlCaster +{ + public static function castMessageFormatter(\MessageFormatter $c, array $a, Stub $stub, bool $isNested) + { + $a += [ + Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), + Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), + ]; + + return self::castError($c, $a); + } + + public static function castNumberFormatter(\NumberFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $a += [ + Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), + Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), + ]; + + if ($filter & Caster::EXCLUDE_VERBOSE) { + $stub->cut += 3; + + return self::castError($c, $a); + } + + $a += [ + Caster::PREFIX_VIRTUAL.'attributes' => new EnumStub( + [ + 'PARSE_INT_ONLY' => $c->getAttribute(\NumberFormatter::PARSE_INT_ONLY), + 'GROUPING_USED' => $c->getAttribute(\NumberFormatter::GROUPING_USED), + 'DECIMAL_ALWAYS_SHOWN' => $c->getAttribute(\NumberFormatter::DECIMAL_ALWAYS_SHOWN), + 'MAX_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_INTEGER_DIGITS), + 'MIN_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_INTEGER_DIGITS), + 'INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::INTEGER_DIGITS), + 'MAX_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_FRACTION_DIGITS), + 'MIN_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_FRACTION_DIGITS), + 'FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::FRACTION_DIGITS), + 'MULTIPLIER' => $c->getAttribute(\NumberFormatter::MULTIPLIER), + 'GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::GROUPING_SIZE), + 'ROUNDING_MODE' => $c->getAttribute(\NumberFormatter::ROUNDING_MODE), + 'ROUNDING_INCREMENT' => $c->getAttribute(\NumberFormatter::ROUNDING_INCREMENT), + 'FORMAT_WIDTH' => $c->getAttribute(\NumberFormatter::FORMAT_WIDTH), + 'PADDING_POSITION' => $c->getAttribute(\NumberFormatter::PADDING_POSITION), + 'SECONDARY_GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::SECONDARY_GROUPING_SIZE), + 'SIGNIFICANT_DIGITS_USED' => $c->getAttribute(\NumberFormatter::SIGNIFICANT_DIGITS_USED), + 'MIN_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_SIGNIFICANT_DIGITS), + 'MAX_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_SIGNIFICANT_DIGITS), + 'LENIENT_PARSE' => $c->getAttribute(\NumberFormatter::LENIENT_PARSE), + ] + ), + Caster::PREFIX_VIRTUAL.'text_attributes' => new EnumStub( + [ + 'POSITIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_PREFIX), + 'POSITIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_SUFFIX), + 'NEGATIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_PREFIX), + 'NEGATIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_SUFFIX), + 'PADDING_CHARACTER' => $c->getTextAttribute(\NumberFormatter::PADDING_CHARACTER), + 'CURRENCY_CODE' => $c->getTextAttribute(\NumberFormatter::CURRENCY_CODE), + 'DEFAULT_RULESET' => $c->getTextAttribute(\NumberFormatter::DEFAULT_RULESET), + 'PUBLIC_RULESETS' => $c->getTextAttribute(\NumberFormatter::PUBLIC_RULESETS), + ] + ), + Caster::PREFIX_VIRTUAL.'symbols' => new EnumStub( + [ + 'DECIMAL_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL), + 'GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL), + 'PATTERN_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::PATTERN_SEPARATOR_SYMBOL), + 'PERCENT_SYMBOL' => $c->getSymbol(\NumberFormatter::PERCENT_SYMBOL), + 'ZERO_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::ZERO_DIGIT_SYMBOL), + 'DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::DIGIT_SYMBOL), + 'MINUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::MINUS_SIGN_SYMBOL), + 'PLUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::PLUS_SIGN_SYMBOL), + 'CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::CURRENCY_SYMBOL), + 'INTL_CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::INTL_CURRENCY_SYMBOL), + 'MONETARY_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_SEPARATOR_SYMBOL), + 'EXPONENTIAL_SYMBOL' => $c->getSymbol(\NumberFormatter::EXPONENTIAL_SYMBOL), + 'PERMILL_SYMBOL' => $c->getSymbol(\NumberFormatter::PERMILL_SYMBOL), + 'PAD_ESCAPE_SYMBOL' => $c->getSymbol(\NumberFormatter::PAD_ESCAPE_SYMBOL), + 'INFINITY_SYMBOL' => $c->getSymbol(\NumberFormatter::INFINITY_SYMBOL), + 'NAN_SYMBOL' => $c->getSymbol(\NumberFormatter::NAN_SYMBOL), + 'SIGNIFICANT_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL), + 'MONETARY_GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL), + ] + ), + ]; + + return self::castError($c, $a); + } + + public static function castIntlTimeZone(\IntlTimeZone $c, array $a, Stub $stub, bool $isNested) + { + $a += [ + Caster::PREFIX_VIRTUAL.'display_name' => $c->getDisplayName(), + Caster::PREFIX_VIRTUAL.'id' => $c->getID(), + Caster::PREFIX_VIRTUAL.'raw_offset' => $c->getRawOffset(), + ]; + + if ($c->useDaylightTime()) { + $a += [ + Caster::PREFIX_VIRTUAL.'dst_savings' => $c->getDSTSavings(), + ]; + } + + return self::castError($c, $a); + } + + public static function castIntlCalendar(\IntlCalendar $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $a += [ + Caster::PREFIX_VIRTUAL.'type' => $c->getType(), + Caster::PREFIX_VIRTUAL.'first_day_of_week' => $c->getFirstDayOfWeek(), + Caster::PREFIX_VIRTUAL.'minimal_days_in_first_week' => $c->getMinimalDaysInFirstWeek(), + Caster::PREFIX_VIRTUAL.'repeated_wall_time_option' => $c->getRepeatedWallTimeOption(), + Caster::PREFIX_VIRTUAL.'skipped_wall_time_option' => $c->getSkippedWallTimeOption(), + Caster::PREFIX_VIRTUAL.'time' => $c->getTime(), + Caster::PREFIX_VIRTUAL.'in_daylight_time' => $c->inDaylightTime(), + Caster::PREFIX_VIRTUAL.'is_lenient' => $c->isLenient(), + Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(), + ]; + + return self::castError($c, $a); + } + + public static function castIntlDateFormatter(\IntlDateFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $a += [ + Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), + Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), + Caster::PREFIX_VIRTUAL.'calendar' => $c->getCalendar(), + Caster::PREFIX_VIRTUAL.'time_zone_id' => $c->getTimeZoneId(), + Caster::PREFIX_VIRTUAL.'time_type' => $c->getTimeType(), + Caster::PREFIX_VIRTUAL.'date_type' => $c->getDateType(), + Caster::PREFIX_VIRTUAL.'calendar_object' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getCalendarObject()) : $c->getCalendarObject(), + Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(), + ]; + + return self::castError($c, $a); + } + + private static function castError(object $c, array $a): array + { + if ($errorCode = $c->getErrorCode()) { + $a += [ + Caster::PREFIX_VIRTUAL.'error_code' => $errorCode, + Caster::PREFIX_VIRTUAL.'error_message' => $c->getErrorMessage(), + ]; + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/LinkStub.php b/vendor/symfony/var-dumper/Caster/LinkStub.php new file mode 100644 index 0000000..6360716 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/LinkStub.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +/** + * Represents a file or a URL. + * + * @author Nicolas Grekas + */ +class LinkStub extends ConstStub +{ + public $inVendor = false; + + private static $vendorRoots; + private static $composerRoots; + + public function __construct($label, int $line = 0, $href = null) + { + $this->value = $label; + + if (null === $href) { + $href = $label; + } + if (!\is_string($href)) { + return; + } + if (0 === strpos($href, 'file://')) { + if ($href === $label) { + $label = substr($label, 7); + } + $href = substr($href, 7); + } elseif (false !== strpos($href, '://')) { + $this->attr['href'] = $href; + + return; + } + if (!file_exists($href)) { + return; + } + if ($line) { + $this->attr['line'] = $line; + } + if ($label !== $this->attr['file'] = realpath($href) ?: $href) { + return; + } + if ($composerRoot = $this->getComposerRoot($href, $this->inVendor)) { + $this->attr['ellipsis'] = \strlen($href) - \strlen($composerRoot) + 1; + $this->attr['ellipsis-type'] = 'path'; + $this->attr['ellipsis-tail'] = 1 + ($this->inVendor ? 2 + \strlen(implode('', \array_slice(explode(\DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0); + } elseif (3 < \count($ellipsis = explode(\DIRECTORY_SEPARATOR, $href))) { + $this->attr['ellipsis'] = 2 + \strlen(implode('', \array_slice($ellipsis, -2))); + $this->attr['ellipsis-type'] = 'path'; + $this->attr['ellipsis-tail'] = 1; + } + } + + private function getComposerRoot(string $file, bool &$inVendor) + { + if (null === self::$vendorRoots) { + self::$vendorRoots = []; + + foreach (get_declared_classes() as $class) { + if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) { + $r = new \ReflectionClass($class); + $v = \dirname($r->getFileName(), 2); + if (file_exists($v.'/composer/installed.json')) { + self::$vendorRoots[] = $v.\DIRECTORY_SEPARATOR; + } + } + } + } + $inVendor = false; + + if (isset(self::$composerRoots[$dir = \dirname($file)])) { + return self::$composerRoots[$dir]; + } + + foreach (self::$vendorRoots as $root) { + if ($inVendor = 0 === strpos($file, $root)) { + return $root; + } + } + + $parent = $dir; + while (!@file_exists($parent.'/composer.json')) { + if (!@file_exists($parent)) { + // open_basedir restriction in effect + break; + } + if ($parent === \dirname($parent)) { + return self::$composerRoots[$dir] = false; + } + + $parent = \dirname($parent); + } + + return self::$composerRoots[$dir] = $parent.\DIRECTORY_SEPARATOR; + } +} diff --git a/vendor/symfony/var-dumper/Caster/MemcachedCaster.php b/vendor/symfony/var-dumper/Caster/MemcachedCaster.php new file mode 100644 index 0000000..111b060 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/MemcachedCaster.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @author Jan Schädlich + * + * @final + */ +class MemcachedCaster +{ + private static $optionConstants; + private static $defaultOptions; + + public static function castMemcached(\Memcached $c, array $a, Stub $stub, bool $isNested) + { + $a += [ + Caster::PREFIX_VIRTUAL.'servers' => $c->getServerList(), + Caster::PREFIX_VIRTUAL.'options' => new EnumStub( + self::getNonDefaultOptions($c) + ), + ]; + + return $a; + } + + private static function getNonDefaultOptions(\Memcached $c): array + { + self::$defaultOptions = self::$defaultOptions ?? self::discoverDefaultOptions(); + self::$optionConstants = self::$optionConstants ?? self::getOptionConstants(); + + $nonDefaultOptions = []; + foreach (self::$optionConstants as $constantKey => $value) { + if (self::$defaultOptions[$constantKey] !== $option = $c->getOption($value)) { + $nonDefaultOptions[$constantKey] = $option; + } + } + + return $nonDefaultOptions; + } + + private static function discoverDefaultOptions(): array + { + $defaultMemcached = new \Memcached(); + $defaultMemcached->addServer('127.0.0.1', 11211); + + $defaultOptions = []; + self::$optionConstants = self::$optionConstants ?? self::getOptionConstants(); + + foreach (self::$optionConstants as $constantKey => $value) { + $defaultOptions[$constantKey] = $defaultMemcached->getOption($value); + } + + return $defaultOptions; + } + + private static function getOptionConstants(): array + { + $reflectedMemcached = new \ReflectionClass(\Memcached::class); + + $optionConstants = []; + foreach ($reflectedMemcached->getConstants() as $constantKey => $value) { + if (0 === strpos($constantKey, 'OPT_')) { + $optionConstants[$constantKey] = $value; + } + } + + return $optionConstants; + } +} diff --git a/vendor/symfony/var-dumper/Caster/PdoCaster.php b/vendor/symfony/var-dumper/Caster/PdoCaster.php new file mode 100644 index 0000000..4ba302b --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/PdoCaster.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts PDO related classes to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class PdoCaster +{ + private static $pdoAttributes = [ + 'CASE' => [ + \PDO::CASE_LOWER => 'LOWER', + \PDO::CASE_NATURAL => 'NATURAL', + \PDO::CASE_UPPER => 'UPPER', + ], + 'ERRMODE' => [ + \PDO::ERRMODE_SILENT => 'SILENT', + \PDO::ERRMODE_WARNING => 'WARNING', + \PDO::ERRMODE_EXCEPTION => 'EXCEPTION', + ], + 'TIMEOUT', + 'PREFETCH', + 'AUTOCOMMIT', + 'PERSISTENT', + 'DRIVER_NAME', + 'SERVER_INFO', + 'ORACLE_NULLS' => [ + \PDO::NULL_NATURAL => 'NATURAL', + \PDO::NULL_EMPTY_STRING => 'EMPTY_STRING', + \PDO::NULL_TO_STRING => 'TO_STRING', + ], + 'CLIENT_VERSION', + 'SERVER_VERSION', + 'STATEMENT_CLASS', + 'EMULATE_PREPARES', + 'CONNECTION_STATUS', + 'STRINGIFY_FETCHES', + 'DEFAULT_FETCH_MODE' => [ + \PDO::FETCH_ASSOC => 'ASSOC', + \PDO::FETCH_BOTH => 'BOTH', + \PDO::FETCH_LAZY => 'LAZY', + \PDO::FETCH_NUM => 'NUM', + \PDO::FETCH_OBJ => 'OBJ', + ], + ]; + + public static function castPdo(\PDO $c, array $a, Stub $stub, bool $isNested) + { + $attr = []; + $errmode = $c->getAttribute(\PDO::ATTR_ERRMODE); + $c->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + + foreach (self::$pdoAttributes as $k => $v) { + if (!isset($k[0])) { + $k = $v; + $v = []; + } + + try { + $attr[$k] = 'ERRMODE' === $k ? $errmode : $c->getAttribute(\constant('PDO::ATTR_'.$k)); + if ($v && isset($v[$attr[$k]])) { + $attr[$k] = new ConstStub($v[$attr[$k]], $attr[$k]); + } + } catch (\Exception $e) { + } + } + if (isset($attr[$k = 'STATEMENT_CLASS'][1])) { + if ($attr[$k][1]) { + $attr[$k][1] = new ArgsStub($attr[$k][1], '__construct', $attr[$k][0]); + } + $attr[$k][0] = new ClassStub($attr[$k][0]); + } + + $prefix = Caster::PREFIX_VIRTUAL; + $a += [ + $prefix.'inTransaction' => method_exists($c, 'inTransaction'), + $prefix.'errorInfo' => $c->errorInfo(), + $prefix.'attributes' => new EnumStub($attr), + ]; + + if ($a[$prefix.'inTransaction']) { + $a[$prefix.'inTransaction'] = $c->inTransaction(); + } else { + unset($a[$prefix.'inTransaction']); + } + + if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) { + unset($a[$prefix.'errorInfo']); + } + + $c->setAttribute(\PDO::ATTR_ERRMODE, $errmode); + + return $a; + } + + public static function castPdoStatement(\PDOStatement $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + $a[$prefix.'errorInfo'] = $c->errorInfo(); + + if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) { + unset($a[$prefix.'errorInfo']); + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/PgSqlCaster.php b/vendor/symfony/var-dumper/Caster/PgSqlCaster.php new file mode 100644 index 0000000..f9f3c6f --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/PgSqlCaster.php @@ -0,0 +1,156 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts pqsql resources to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class PgSqlCaster +{ + private static $paramCodes = [ + 'server_encoding', + 'client_encoding', + 'is_superuser', + 'session_authorization', + 'DateStyle', + 'TimeZone', + 'IntervalStyle', + 'integer_datetimes', + 'application_name', + 'standard_conforming_strings', + ]; + + private static $transactionStatus = [ + PGSQL_TRANSACTION_IDLE => 'PGSQL_TRANSACTION_IDLE', + PGSQL_TRANSACTION_ACTIVE => 'PGSQL_TRANSACTION_ACTIVE', + PGSQL_TRANSACTION_INTRANS => 'PGSQL_TRANSACTION_INTRANS', + PGSQL_TRANSACTION_INERROR => 'PGSQL_TRANSACTION_INERROR', + PGSQL_TRANSACTION_UNKNOWN => 'PGSQL_TRANSACTION_UNKNOWN', + ]; + + private static $resultStatus = [ + PGSQL_EMPTY_QUERY => 'PGSQL_EMPTY_QUERY', + PGSQL_COMMAND_OK => 'PGSQL_COMMAND_OK', + PGSQL_TUPLES_OK => 'PGSQL_TUPLES_OK', + PGSQL_COPY_OUT => 'PGSQL_COPY_OUT', + PGSQL_COPY_IN => 'PGSQL_COPY_IN', + PGSQL_BAD_RESPONSE => 'PGSQL_BAD_RESPONSE', + PGSQL_NONFATAL_ERROR => 'PGSQL_NONFATAL_ERROR', + PGSQL_FATAL_ERROR => 'PGSQL_FATAL_ERROR', + ]; + + private static $diagCodes = [ + 'severity' => PGSQL_DIAG_SEVERITY, + 'sqlstate' => PGSQL_DIAG_SQLSTATE, + 'message' => PGSQL_DIAG_MESSAGE_PRIMARY, + 'detail' => PGSQL_DIAG_MESSAGE_DETAIL, + 'hint' => PGSQL_DIAG_MESSAGE_HINT, + 'statement position' => PGSQL_DIAG_STATEMENT_POSITION, + 'internal position' => PGSQL_DIAG_INTERNAL_POSITION, + 'internal query' => PGSQL_DIAG_INTERNAL_QUERY, + 'context' => PGSQL_DIAG_CONTEXT, + 'file' => PGSQL_DIAG_SOURCE_FILE, + 'line' => PGSQL_DIAG_SOURCE_LINE, + 'function' => PGSQL_DIAG_SOURCE_FUNCTION, + ]; + + public static function castLargeObject($lo, array $a, Stub $stub, bool $isNested) + { + $a['seek position'] = pg_lo_tell($lo); + + return $a; + } + + public static function castLink($link, array $a, Stub $stub, bool $isNested) + { + $a['status'] = pg_connection_status($link); + $a['status'] = new ConstStub(PGSQL_CONNECTION_OK === $a['status'] ? 'PGSQL_CONNECTION_OK' : 'PGSQL_CONNECTION_BAD', $a['status']); + $a['busy'] = pg_connection_busy($link); + + $a['transaction'] = pg_transaction_status($link); + if (isset(self::$transactionStatus[$a['transaction']])) { + $a['transaction'] = new ConstStub(self::$transactionStatus[$a['transaction']], $a['transaction']); + } + + $a['pid'] = pg_get_pid($link); + $a['last error'] = pg_last_error($link); + $a['last notice'] = pg_last_notice($link); + $a['host'] = pg_host($link); + $a['port'] = pg_port($link); + $a['dbname'] = pg_dbname($link); + $a['options'] = pg_options($link); + $a['version'] = pg_version($link); + + foreach (self::$paramCodes as $v) { + if (false !== $s = pg_parameter_status($link, $v)) { + $a['param'][$v] = $s; + } + } + + $a['param']['client_encoding'] = pg_client_encoding($link); + $a['param'] = new EnumStub($a['param']); + + return $a; + } + + public static function castResult($result, array $a, Stub $stub, bool $isNested) + { + $a['num rows'] = pg_num_rows($result); + $a['status'] = pg_result_status($result); + if (isset(self::$resultStatus[$a['status']])) { + $a['status'] = new ConstStub(self::$resultStatus[$a['status']], $a['status']); + } + $a['command-completion tag'] = pg_result_status($result, PGSQL_STATUS_STRING); + + if (-1 === $a['num rows']) { + foreach (self::$diagCodes as $k => $v) { + $a['error'][$k] = pg_result_error_field($result, $v); + } + } + + $a['affected rows'] = pg_affected_rows($result); + $a['last OID'] = pg_last_oid($result); + + $fields = pg_num_fields($result); + + for ($i = 0; $i < $fields; ++$i) { + $field = [ + 'name' => pg_field_name($result, $i), + 'table' => sprintf('%s (OID: %s)', pg_field_table($result, $i), pg_field_table($result, $i, true)), + 'type' => sprintf('%s (OID: %s)', pg_field_type($result, $i), pg_field_type_oid($result, $i)), + 'nullable' => (bool) pg_field_is_null($result, $i), + 'storage' => pg_field_size($result, $i).' bytes', + 'display' => pg_field_prtlen($result, $i).' chars', + ]; + if (' (OID: )' === $field['table']) { + $field['table'] = null; + } + if ('-1 bytes' === $field['storage']) { + $field['storage'] = 'variable size'; + } elseif ('1 bytes' === $field['storage']) { + $field['storage'] = '1 byte'; + } + if ('1 chars' === $field['display']) { + $field['display'] = '1 char'; + } + $a['fields'][] = new EnumStub($field); + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php b/vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php new file mode 100644 index 0000000..e712019 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use ProxyManager\Proxy\ProxyInterface; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @author Nicolas Grekas + * + * @final + */ +class ProxyManagerCaster +{ + public static function castProxy(ProxyInterface $c, array $a, Stub $stub, bool $isNested) + { + if ($parent = get_parent_class($c)) { + $stub->class .= ' - '.$parent; + } + $stub->class .= '@proxy'; + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/RedisCaster.php b/vendor/symfony/var-dumper/Caster/RedisCaster.php new file mode 100644 index 0000000..a7ca8ec --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/RedisCaster.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts Redis class from ext-redis to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class RedisCaster +{ + private static $serializer = [ + \Redis::SERIALIZER_NONE => 'NONE', + \Redis::SERIALIZER_PHP => 'PHP', + 2 => 'IGBINARY', // Optional Redis::SERIALIZER_IGBINARY + ]; + + private static $mode = [ + \Redis::ATOMIC => 'ATOMIC', + \Redis::MULTI => 'MULTI', + \Redis::PIPELINE => 'PIPELINE', + ]; + + private static $compression = [ + 0 => 'NONE', // Redis::COMPRESSION_NONE + 1 => 'LZF', // Redis::COMPRESSION_LZF + ]; + + private static $failover = [ + \RedisCluster::FAILOVER_NONE => 'NONE', + \RedisCluster::FAILOVER_ERROR => 'ERROR', + \RedisCluster::FAILOVER_DISTRIBUTE => 'DISTRIBUTE', + \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES => 'DISTRIBUTE_SLAVES', + ]; + + public static function castRedis(\Redis $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + if (!$connected = $c->isConnected()) { + return $a + [ + $prefix.'isConnected' => $connected, + ]; + } + + $mode = $c->getMode(); + + return $a + [ + $prefix.'isConnected' => $connected, + $prefix.'host' => $c->getHost(), + $prefix.'port' => $c->getPort(), + $prefix.'auth' => $c->getAuth(), + $prefix.'mode' => isset(self::$mode[$mode]) ? new ConstStub(self::$mode[$mode], $mode) : $mode, + $prefix.'dbNum' => $c->getDbNum(), + $prefix.'timeout' => $c->getTimeout(), + $prefix.'lastError' => $c->getLastError(), + $prefix.'persistentId' => $c->getPersistentID(), + $prefix.'options' => self::getRedisOptions($c), + ]; + } + + public static function castRedisArray(\RedisArray $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + return $a + [ + $prefix.'hosts' => $c->_hosts(), + $prefix.'function' => ClassStub::wrapCallable($c->_function()), + $prefix.'lastError' => $c->getLastError(), + $prefix.'options' => self::getRedisOptions($c), + ]; + } + + public static function castRedisCluster(\RedisCluster $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + $failover = $c->getOption(\RedisCluster::OPT_SLAVE_FAILOVER); + + $a += [ + $prefix.'_masters' => $c->_masters(), + $prefix.'_redir' => $c->_redir(), + $prefix.'mode' => new ConstStub($c->getMode() ? 'MULTI' : 'ATOMIC', $c->getMode()), + $prefix.'lastError' => $c->getLastError(), + $prefix.'options' => self::getRedisOptions($c, [ + 'SLAVE_FAILOVER' => isset(self::$failover[$failover]) ? new ConstStub(self::$failover[$failover], $failover) : $failover, + ]), + ]; + + return $a; + } + + /** + * @param \Redis|\RedisArray|\RedisCluster $redis + */ + private static function getRedisOptions($redis, array $options = []): EnumStub + { + $serializer = $redis->getOption(\Redis::OPT_SERIALIZER); + if (\is_array($serializer)) { + foreach ($serializer as &$v) { + if (isset(self::$serializer[$v])) { + $v = new ConstStub(self::$serializer[$v], $v); + } + } + } elseif (isset(self::$serializer[$serializer])) { + $serializer = new ConstStub(self::$serializer[$serializer], $serializer); + } + + $compression = \defined('Redis::OPT_COMPRESSION') ? $redis->getOption(\Redis::OPT_COMPRESSION) : 0; + if (\is_array($compression)) { + foreach ($compression as &$v) { + if (isset(self::$compression[$v])) { + $v = new ConstStub(self::$compression[$v], $v); + } + } + } elseif (isset(self::$compression[$compression])) { + $compression = new ConstStub(self::$compression[$compression], $compression); + } + + $retry = \defined('Redis::OPT_SCAN') ? $redis->getOption(\Redis::OPT_SCAN) : 0; + if (\is_array($retry)) { + foreach ($retry as &$v) { + $v = new ConstStub($v ? 'RETRY' : 'NORETRY', $v); + } + } else { + $retry = new ConstStub($retry ? 'RETRY' : 'NORETRY', $retry); + } + + $options += [ + 'TCP_KEEPALIVE' => \defined('Redis::OPT_TCP_KEEPALIVE') ? $redis->getOption(\Redis::OPT_TCP_KEEPALIVE) : 0, + 'READ_TIMEOUT' => $redis->getOption(\Redis::OPT_READ_TIMEOUT), + 'COMPRESSION' => $compression, + 'SERIALIZER' => $serializer, + 'PREFIX' => $redis->getOption(\Redis::OPT_PREFIX), + 'SCAN' => $retry, + ]; + + return new EnumStub($options); + } +} diff --git a/vendor/symfony/var-dumper/Caster/ReflectionCaster.php b/vendor/symfony/var-dumper/Caster/ReflectionCaster.php new file mode 100644 index 0000000..94c2f3e --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ReflectionCaster.php @@ -0,0 +1,384 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts Reflector related classes to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class ReflectionCaster +{ + const UNSET_CLOSURE_FILE_INFO = ['Closure' => __CLASS__.'::unsetClosureFileInfo']; + + private static $extraMap = [ + 'docComment' => 'getDocComment', + 'extension' => 'getExtensionName', + 'isDisabled' => 'isDisabled', + 'isDeprecated' => 'isDeprecated', + 'isInternal' => 'isInternal', + 'isUserDefined' => 'isUserDefined', + 'isGenerator' => 'isGenerator', + 'isVariadic' => 'isVariadic', + ]; + + public static function castClosure(\Closure $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $prefix = Caster::PREFIX_VIRTUAL; + $c = new \ReflectionFunction($c); + + $a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter); + + if (false === strpos($c->name, '{closure}')) { + $stub->class = isset($a[$prefix.'class']) ? $a[$prefix.'class']->value.'::'.$c->name : $c->name; + unset($a[$prefix.'class']); + } + unset($a[$prefix.'extra']); + + $stub->class .= self::getSignature($a); + + if ($f = $c->getFileName()) { + $stub->attr['file'] = $f; + $stub->attr['line'] = $c->getStartLine(); + } + + unset($a[$prefix.'parameters']); + + if ($filter & Caster::EXCLUDE_VERBOSE) { + $stub->cut += ($c->getFileName() ? 2 : 0) + \count($a); + + return []; + } + + if ($f) { + $a[$prefix.'file'] = new LinkStub($f, $c->getStartLine()); + $a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine(); + } + + return $a; + } + + public static function unsetClosureFileInfo(\Closure $c, array $a) + { + unset($a[Caster::PREFIX_VIRTUAL.'file'], $a[Caster::PREFIX_VIRTUAL.'line']); + + return $a; + } + + public static function castGenerator(\Generator $c, array $a, Stub $stub, bool $isNested) + { + // Cannot create ReflectionGenerator based on a terminated Generator + try { + $reflectionGenerator = new \ReflectionGenerator($c); + } catch (\Exception $e) { + $a[Caster::PREFIX_VIRTUAL.'closed'] = true; + + return $a; + } + + return self::castReflectionGenerator($reflectionGenerator, $a, $stub, $isNested); + } + + public static function castType(\ReflectionType $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + $a += [ + $prefix.'name' => $c->getName(), + $prefix.'allowsNull' => $c->allowsNull(), + $prefix.'isBuiltin' => $c->isBuiltin(), + ]; + + return $a; + } + + public static function castReflectionGenerator(\ReflectionGenerator $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + if ($c->getThis()) { + $a[$prefix.'this'] = new CutStub($c->getThis()); + } + $function = $c->getFunction(); + $frame = [ + 'class' => isset($function->class) ? $function->class : null, + 'type' => isset($function->class) ? ($function->isStatic() ? '::' : '->') : null, + 'function' => $function->name, + 'file' => $c->getExecutingFile(), + 'line' => $c->getExecutingLine(), + ]; + if ($trace = $c->getTrace(DEBUG_BACKTRACE_IGNORE_ARGS)) { + $function = new \ReflectionGenerator($c->getExecutingGenerator()); + array_unshift($trace, [ + 'function' => 'yield', + 'file' => $function->getExecutingFile(), + 'line' => $function->getExecutingLine() - 1, + ]); + $trace[] = $frame; + $a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1); + } else { + $function = new FrameStub($frame, false, true); + $function = ExceptionCaster::castFrameStub($function, [], $function, true); + $a[$prefix.'executing'] = $function[$prefix.'src']; + } + + $a[Caster::PREFIX_VIRTUAL.'closed'] = false; + + return $a; + } + + public static function castClass(\ReflectionClass $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $prefix = Caster::PREFIX_VIRTUAL; + + if ($n = \Reflection::getModifierNames($c->getModifiers())) { + $a[$prefix.'modifiers'] = implode(' ', $n); + } + + self::addMap($a, $c, [ + 'extends' => 'getParentClass', + 'implements' => 'getInterfaceNames', + 'constants' => 'getConstants', + ]); + + foreach ($c->getProperties() as $n) { + $a[$prefix.'properties'][$n->name] = $n; + } + + foreach ($c->getMethods() as $n) { + $a[$prefix.'methods'][$n->name] = $n; + } + + if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) { + self::addExtra($a, $c); + } + + return $a; + } + + public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, array $a, Stub $stub, bool $isNested, int $filter = 0) + { + $prefix = Caster::PREFIX_VIRTUAL; + + self::addMap($a, $c, [ + 'returnsReference' => 'returnsReference', + 'returnType' => 'getReturnType', + 'class' => 'getClosureScopeClass', + 'this' => 'getClosureThis', + ]); + + if (isset($a[$prefix.'returnType'])) { + $v = $a[$prefix.'returnType']; + $v = $v->getName(); + $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType']->allowsNull() ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); + } + if (isset($a[$prefix.'class'])) { + $a[$prefix.'class'] = new ClassStub($a[$prefix.'class']); + } + if (isset($a[$prefix.'this'])) { + $a[$prefix.'this'] = new CutStub($a[$prefix.'this']); + } + + foreach ($c->getParameters() as $v) { + $k = '$'.$v->name; + if ($v->isVariadic()) { + $k = '...'.$k; + } + if ($v->isPassedByReference()) { + $k = '&'.$k; + } + $a[$prefix.'parameters'][$k] = $v; + } + if (isset($a[$prefix.'parameters'])) { + $a[$prefix.'parameters'] = new EnumStub($a[$prefix.'parameters']); + } + + if (!($filter & Caster::EXCLUDE_VERBOSE) && $v = $c->getStaticVariables()) { + foreach ($v as $k => &$v) { + if (\is_object($v)) { + $a[$prefix.'use']['$'.$k] = new CutStub($v); + } else { + $a[$prefix.'use']['$'.$k] = &$v; + } + } + unset($v); + $a[$prefix.'use'] = new EnumStub($a[$prefix.'use']); + } + + if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) { + self::addExtra($a, $c); + } + + return $a; + } + + public static function castMethod(\ReflectionMethod $c, array $a, Stub $stub, bool $isNested) + { + $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers())); + + return $a; + } + + public static function castParameter(\ReflectionParameter $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + + self::addMap($a, $c, [ + 'position' => 'getPosition', + 'isVariadic' => 'isVariadic', + 'byReference' => 'isPassedByReference', + 'allowsNull' => 'allowsNull', + ]); + + if ($v = $c->getType()) { + $a[$prefix.'typeHint'] = $v->getName(); + } + + if (isset($a[$prefix.'typeHint'])) { + $v = $a[$prefix.'typeHint']; + $a[$prefix.'typeHint'] = new ClassStub($v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); + } else { + unset($a[$prefix.'allowsNull']); + } + + try { + $a[$prefix.'default'] = $v = $c->getDefaultValue(); + if ($c->isDefaultValueConstant()) { + $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v); + } + if (null === $v) { + unset($a[$prefix.'allowsNull']); + } + } catch (\ReflectionException $e) { + } + + return $a; + } + + public static function castProperty(\ReflectionProperty $c, array $a, Stub $stub, bool $isNested) + { + $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers())); + self::addExtra($a, $c); + + return $a; + } + + public static function castReference(\ReflectionReference $c, array $a, Stub $stub, bool $isNested) + { + $a[Caster::PREFIX_VIRTUAL.'id'] = $c->getId(); + + return $a; + } + + public static function castExtension(\ReflectionExtension $c, array $a, Stub $stub, bool $isNested) + { + self::addMap($a, $c, [ + 'version' => 'getVersion', + 'dependencies' => 'getDependencies', + 'iniEntries' => 'getIniEntries', + 'isPersistent' => 'isPersistent', + 'isTemporary' => 'isTemporary', + 'constants' => 'getConstants', + 'functions' => 'getFunctions', + 'classes' => 'getClasses', + ]); + + return $a; + } + + public static function castZendExtension(\ReflectionZendExtension $c, array $a, Stub $stub, bool $isNested) + { + self::addMap($a, $c, [ + 'version' => 'getVersion', + 'author' => 'getAuthor', + 'copyright' => 'getCopyright', + 'url' => 'getURL', + ]); + + return $a; + } + + public static function getSignature(array $a) + { + $prefix = Caster::PREFIX_VIRTUAL; + $signature = ''; + + if (isset($a[$prefix.'parameters'])) { + foreach ($a[$prefix.'parameters']->value as $k => $param) { + $signature .= ', '; + if ($type = $param->getType()) { + if (!$param->isOptional() && $param->allowsNull()) { + $signature .= '?'; + } + $signature .= substr(strrchr('\\'.$type->getName(), '\\'), 1).' '; + } + $signature .= $k; + + if (!$param->isDefaultValueAvailable()) { + continue; + } + $v = $param->getDefaultValue(); + $signature .= ' = '; + + if ($param->isDefaultValueConstant()) { + $signature .= substr(strrchr('\\'.$param->getDefaultValueConstantName(), '\\'), 1); + } elseif (null === $v) { + $signature .= 'null'; + } elseif (\is_array($v)) { + $signature .= $v ? '[…'.\count($v).']' : '[]'; + } elseif (\is_string($v)) { + $signature .= 10 > \strlen($v) && false === strpos($v, '\\') ? "'{$v}'" : "'…".\strlen($v)."'"; + } elseif (\is_bool($v)) { + $signature .= $v ? 'true' : 'false'; + } else { + $signature .= $v; + } + } + } + $signature = (empty($a[$prefix.'returnsReference']) ? '' : '&').'('.substr($signature, 2).')'; + + if (isset($a[$prefix.'returnType'])) { + $signature .= ': '.substr(strrchr('\\'.$a[$prefix.'returnType'], '\\'), 1); + } + + return $signature; + } + + private static function addExtra(array &$a, \Reflector $c) + { + $x = isset($a[Caster::PREFIX_VIRTUAL.'extra']) ? $a[Caster::PREFIX_VIRTUAL.'extra']->value : []; + + if (method_exists($c, 'getFileName') && $m = $c->getFileName()) { + $x['file'] = new LinkStub($m, $c->getStartLine()); + $x['line'] = $c->getStartLine().' to '.$c->getEndLine(); + } + + self::addMap($x, $c, self::$extraMap, ''); + + if ($x) { + $a[Caster::PREFIX_VIRTUAL.'extra'] = new EnumStub($x); + } + } + + private static function addMap(array &$a, \Reflector $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL) + { + foreach ($map as $k => $m) { + if (method_exists($c, $m) && false !== ($m = $c->$m()) && null !== $m) { + $a[$prefix.$k] = $m instanceof \Reflector ? $m->name : $m; + } + } + } +} diff --git a/vendor/symfony/var-dumper/Caster/ResourceCaster.php b/vendor/symfony/var-dumper/Caster/ResourceCaster.php new file mode 100644 index 0000000..94ff5a9 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/ResourceCaster.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts common resource types to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class ResourceCaster +{ + public static function castCurl($h, array $a, Stub $stub, bool $isNested) + { + return curl_getinfo($h); + } + + public static function castDba($dba, array $a, Stub $stub, bool $isNested) + { + $list = dba_list(); + $a['file'] = $list[(int) $dba]; + + return $a; + } + + public static function castProcess($process, array $a, Stub $stub, bool $isNested) + { + return proc_get_status($process); + } + + public static function castStream($stream, array $a, Stub $stub, bool $isNested) + { + $a = stream_get_meta_data($stream) + static::castStreamContext($stream, $a, $stub, $isNested); + if (isset($a['uri'])) { + $a['uri'] = new LinkStub($a['uri']); + } + + return $a; + } + + public static function castStreamContext($stream, array $a, Stub $stub, bool $isNested) + { + return @stream_context_get_params($stream) ?: $a; + } + + public static function castGd($gd, array $a, Stub $stub, $isNested) + { + $a['size'] = imagesx($gd).'x'.imagesy($gd); + $a['trueColor'] = imageistruecolor($gd); + + return $a; + } + + public static function castMysqlLink($h, array $a, Stub $stub, bool $isNested) + { + $a['host'] = mysql_get_host_info($h); + $a['protocol'] = mysql_get_proto_info($h); + $a['server'] = mysql_get_server_info($h); + + return $a; + } + + public static function castOpensslX509($h, array $a, Stub $stub, bool $isNested) + { + $stub->cut = -1; + $info = openssl_x509_parse($h, false); + + $pin = openssl_pkey_get_public($h); + $pin = openssl_pkey_get_details($pin)['key']; + $pin = \array_slice(explode("\n", $pin), 1, -2); + $pin = base64_decode(implode('', $pin)); + $pin = base64_encode(hash('sha256', $pin, true)); + + $a += [ + 'subject' => new EnumStub(array_intersect_key($info['subject'], ['organizationName' => true, 'commonName' => true])), + 'issuer' => new EnumStub(array_intersect_key($info['issuer'], ['organizationName' => true, 'commonName' => true])), + 'expiry' => new ConstStub(date(\DateTime::ISO8601, $info['validTo_time_t']), $info['validTo_time_t']), + 'fingerprint' => new EnumStub([ + 'md5' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'md5')), 2, ':', true)), + 'sha1' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha1')), 2, ':', true)), + 'sha256' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha256')), 2, ':', true)), + 'pin-sha256' => new ConstStub($pin), + ]), + ]; + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/SplCaster.php b/vendor/symfony/var-dumper/Caster/SplCaster.php new file mode 100644 index 0000000..e6c5b17 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/SplCaster.php @@ -0,0 +1,228 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts SPL related classes to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class SplCaster +{ + private static $splFileObjectFlags = [ + \SplFileObject::DROP_NEW_LINE => 'DROP_NEW_LINE', + \SplFileObject::READ_AHEAD => 'READ_AHEAD', + \SplFileObject::SKIP_EMPTY => 'SKIP_EMPTY', + \SplFileObject::READ_CSV => 'READ_CSV', + ]; + + public static function castArrayObject(\ArrayObject $c, array $a, Stub $stub, bool $isNested) + { + return self::castSplArray($c, $a, $stub, $isNested); + } + + public static function castArrayIterator(\ArrayIterator $c, array $a, Stub $stub, bool $isNested) + { + return self::castSplArray($c, $a, $stub, $isNested); + } + + public static function castHeap(\Iterator $c, array $a, Stub $stub, $isNested) + { + $a += [ + Caster::PREFIX_VIRTUAL.'heap' => iterator_to_array(clone $c), + ]; + + return $a; + } + + public static function castDoublyLinkedList(\SplDoublyLinkedList $c, array $a, Stub $stub, bool $isNested) + { + $prefix = Caster::PREFIX_VIRTUAL; + $mode = $c->getIteratorMode(); + $c->setIteratorMode(\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\SplDoublyLinkedList::IT_MODE_DELETE); + + $a += [ + $prefix.'mode' => new ConstStub((($mode & \SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \SplDoublyLinkedList::IT_MODE_DELETE) ? 'IT_MODE_DELETE' : 'IT_MODE_KEEP'), $mode), + $prefix.'dllist' => iterator_to_array($c), + ]; + $c->setIteratorMode($mode); + + return $a; + } + + public static function castFileInfo(\SplFileInfo $c, array $a, Stub $stub, bool $isNested) + { + static $map = [ + 'path' => 'getPath', + 'filename' => 'getFilename', + 'basename' => 'getBasename', + 'pathname' => 'getPathname', + 'extension' => 'getExtension', + 'realPath' => 'getRealPath', + 'aTime' => 'getATime', + 'mTime' => 'getMTime', + 'cTime' => 'getCTime', + 'inode' => 'getInode', + 'size' => 'getSize', + 'perms' => 'getPerms', + 'owner' => 'getOwner', + 'group' => 'getGroup', + 'type' => 'getType', + 'writable' => 'isWritable', + 'readable' => 'isReadable', + 'executable' => 'isExecutable', + 'file' => 'isFile', + 'dir' => 'isDir', + 'link' => 'isLink', + 'linkTarget' => 'getLinkTarget', + ]; + + $prefix = Caster::PREFIX_VIRTUAL; + + if (false === $c->getPathname()) { + $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state'; + + return $a; + } + + foreach ($map as $key => $accessor) { + try { + $a[$prefix.$key] = $c->$accessor(); + } catch (\Exception $e) { + } + } + + if (isset($a[$prefix.'realPath'])) { + $a[$prefix.'realPath'] = new LinkStub($a[$prefix.'realPath']); + } + + if (isset($a[$prefix.'perms'])) { + $a[$prefix.'perms'] = new ConstStub(sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']); + } + + static $mapDate = ['aTime', 'mTime', 'cTime']; + foreach ($mapDate as $key) { + if (isset($a[$prefix.$key])) { + $a[$prefix.$key] = new ConstStub(date('Y-m-d H:i:s', $a[$prefix.$key]), $a[$prefix.$key]); + } + } + + return $a; + } + + public static function castFileObject(\SplFileObject $c, array $a, Stub $stub, bool $isNested) + { + static $map = [ + 'csvControl' => 'getCsvControl', + 'flags' => 'getFlags', + 'maxLineLen' => 'getMaxLineLen', + 'fstat' => 'fstat', + 'eof' => 'eof', + 'key' => 'key', + ]; + + $prefix = Caster::PREFIX_VIRTUAL; + + foreach ($map as $key => $accessor) { + try { + $a[$prefix.$key] = $c->$accessor(); + } catch (\Exception $e) { + } + } + + if (isset($a[$prefix.'flags'])) { + $flagsArray = []; + foreach (self::$splFileObjectFlags as $value => $name) { + if ($a[$prefix.'flags'] & $value) { + $flagsArray[] = $name; + } + } + $a[$prefix.'flags'] = new ConstStub(implode('|', $flagsArray), $a[$prefix.'flags']); + } + + if (isset($a[$prefix.'fstat'])) { + $a[$prefix.'fstat'] = new CutArrayStub($a[$prefix.'fstat'], ['dev', 'ino', 'nlink', 'rdev', 'blksize', 'blocks']); + } + + return $a; + } + + public static function castFixedArray(\SplFixedArray $c, array $a, Stub $stub, bool $isNested) + { + $a += [ + Caster::PREFIX_VIRTUAL.'storage' => $c->toArray(), + ]; + + return $a; + } + + public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $stub, bool $isNested) + { + $storage = []; + unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967 + + $clone = clone $c; + foreach ($clone as $obj) { + $storage[] = [ + 'object' => $obj, + 'info' => $clone->getInfo(), + ]; + } + + $a += [ + Caster::PREFIX_VIRTUAL.'storage' => $storage, + ]; + + return $a; + } + + public static function castOuterIterator(\OuterIterator $c, array $a, Stub $stub, bool $isNested) + { + $a[Caster::PREFIX_VIRTUAL.'innerIterator'] = $c->getInnerIterator(); + + return $a; + } + + public static function castWeakReference(\WeakReference $c, array $a, Stub $stub, bool $isNested) + { + $a[Caster::PREFIX_VIRTUAL.'object'] = $c->get(); + + return $a; + } + + private static function castSplArray($c, array $a, Stub $stub, bool $isNested): array + { + $prefix = Caster::PREFIX_VIRTUAL; + $class = $stub->class; + $flags = $c->getFlags(); + + if (!($flags & \ArrayObject::STD_PROP_LIST)) { + $c->setFlags(\ArrayObject::STD_PROP_LIST); + $a = Caster::castObject($c, $class); + $c->setFlags($flags); + } + $a += [ + $prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST), + $prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS), + ]; + if ($c instanceof \ArrayObject) { + $a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass()); + } + $a[$prefix.'storage'] = $c->getArrayCopy(); + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/StubCaster.php b/vendor/symfony/var-dumper/Caster/StubCaster.php new file mode 100644 index 0000000..32ead7c --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/StubCaster.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts a caster's Stub. + * + * @author Nicolas Grekas + * + * @final + */ +class StubCaster +{ + public static function castStub(Stub $c, array $a, Stub $stub, bool $isNested) + { + if ($isNested) { + $stub->type = $c->type; + $stub->class = $c->class; + $stub->value = $c->value; + $stub->handle = $c->handle; + $stub->cut = $c->cut; + $stub->attr = $c->attr; + + if (Stub::TYPE_REF === $c->type && !$c->class && \is_string($c->value) && !preg_match('//u', $c->value)) { + $stub->type = Stub::TYPE_STRING; + $stub->class = Stub::STRING_BINARY; + } + + $a = []; + } + + return $a; + } + + public static function castCutArray(CutArrayStub $c, array $a, Stub $stub, bool $isNested) + { + return $isNested ? $c->preservedSubset : $a; + } + + public static function cutInternals($obj, array $a, Stub $stub, bool $isNested) + { + if ($isNested) { + $stub->cut += \count($a); + + return []; + } + + return $a; + } + + public static function castEnum(EnumStub $c, array $a, Stub $stub, bool $isNested) + { + if ($isNested) { + $stub->class = $c->dumpKeys ? '' : null; + $stub->handle = 0; + $stub->value = null; + $stub->cut = $c->cut; + $stub->attr = $c->attr; + + $a = []; + + if ($c->value) { + foreach (array_keys($c->value) as $k) { + $keys[] = !isset($k[0]) || "\0" !== $k[0] ? Caster::PREFIX_VIRTUAL.$k : $k; + } + // Preserve references with array_combine() + $a = array_combine($keys, $c->value); + } + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/SymfonyCaster.php b/vendor/symfony/var-dumper/Caster/SymfonyCaster.php new file mode 100644 index 0000000..6b87bde --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/SymfonyCaster.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @final + */ +class SymfonyCaster +{ + private static $requestGetters = [ + 'pathInfo' => 'getPathInfo', + 'requestUri' => 'getRequestUri', + 'baseUrl' => 'getBaseUrl', + 'basePath' => 'getBasePath', + 'method' => 'getMethod', + 'format' => 'getRequestFormat', + ]; + + public static function castRequest(Request $request, array $a, Stub $stub, bool $isNested) + { + $clone = null; + + foreach (self::$requestGetters as $prop => $getter) { + $key = Caster::PREFIX_PROTECTED.$prop; + if (\array_key_exists($key, $a) && null === $a[$key]) { + if (null === $clone) { + $clone = clone $request; + } + $a[Caster::PREFIX_VIRTUAL.$prop] = $clone->{$getter}(); + } + } + + return $a; + } + + public static function castHttpClient($client, array $a, Stub $stub, bool $isNested) + { + $multiKey = sprintf("\0%s\0multi", \get_class($client)); + if (isset($a[$multiKey])) { + $a[$multiKey] = new CutStub($a[$multiKey]); + } + + return $a; + } + + public static function castHttpClientResponse($response, array $a, Stub $stub, bool $isNested) + { + $stub->cut += \count($a); + $a = []; + + foreach ($response->getInfo() as $k => $v) { + $a[Caster::PREFIX_VIRTUAL.$k] = $v; + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/TraceStub.php b/vendor/symfony/var-dumper/Caster/TraceStub.php new file mode 100644 index 0000000..5eea1c8 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/TraceStub.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Represents a backtrace as returned by debug_backtrace() or Exception->getTrace(). + * + * @author Nicolas Grekas + */ +class TraceStub extends Stub +{ + public $keepArgs; + public $sliceOffset; + public $sliceLength; + public $numberingOffset; + + public function __construct(array $trace, bool $keepArgs = true, int $sliceOffset = 0, int $sliceLength = null, int $numberingOffset = 0) + { + $this->value = $trace; + $this->keepArgs = $keepArgs; + $this->sliceOffset = $sliceOffset; + $this->sliceLength = $sliceLength; + $this->numberingOffset = $numberingOffset; + } +} diff --git a/vendor/symfony/var-dumper/Caster/UuidCaster.php b/vendor/symfony/var-dumper/Caster/UuidCaster.php new file mode 100644 index 0000000..b102774 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/UuidCaster.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Ramsey\Uuid\UuidInterface; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * @author Grégoire Pineau + */ +final class UuidCaster +{ + public static function castRamseyUuid(UuidInterface $c, array $a, Stub $stub, bool $isNested): array + { + $a += [ + Caster::PREFIX_VIRTUAL.'uuid' => (string) $c, + ]; + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Caster/XmlReaderCaster.php b/vendor/symfony/var-dumper/Caster/XmlReaderCaster.php new file mode 100644 index 0000000..1bca357 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/XmlReaderCaster.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts XmlReader class to array representation. + * + * @author Baptiste Clavié + * + * @final + */ +class XmlReaderCaster +{ + private static $nodeTypes = [ + \XMLReader::NONE => 'NONE', + \XMLReader::ELEMENT => 'ELEMENT', + \XMLReader::ATTRIBUTE => 'ATTRIBUTE', + \XMLReader::TEXT => 'TEXT', + \XMLReader::CDATA => 'CDATA', + \XMLReader::ENTITY_REF => 'ENTITY_REF', + \XMLReader::ENTITY => 'ENTITY', + \XMLReader::PI => 'PI (Processing Instruction)', + \XMLReader::COMMENT => 'COMMENT', + \XMLReader::DOC => 'DOC', + \XMLReader::DOC_TYPE => 'DOC_TYPE', + \XMLReader::DOC_FRAGMENT => 'DOC_FRAGMENT', + \XMLReader::NOTATION => 'NOTATION', + \XMLReader::WHITESPACE => 'WHITESPACE', + \XMLReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE', + \XMLReader::END_ELEMENT => 'END_ELEMENT', + \XMLReader::END_ENTITY => 'END_ENTITY', + \XMLReader::XML_DECLARATION => 'XML_DECLARATION', + ]; + + public static function castXmlReader(\XMLReader $reader, array $a, Stub $stub, bool $isNested) + { + $props = Caster::PREFIX_VIRTUAL.'parserProperties'; + $info = [ + 'localName' => $reader->localName, + 'prefix' => $reader->prefix, + 'nodeType' => new ConstStub(self::$nodeTypes[$reader->nodeType], $reader->nodeType), + 'depth' => $reader->depth, + 'isDefault' => $reader->isDefault, + 'isEmptyElement' => \XMLReader::NONE === $reader->nodeType ? null : $reader->isEmptyElement, + 'xmlLang' => $reader->xmlLang, + 'attributeCount' => $reader->attributeCount, + 'value' => $reader->value, + 'namespaceURI' => $reader->namespaceURI, + 'baseURI' => $reader->baseURI ? new LinkStub($reader->baseURI) : $reader->baseURI, + $props => [ + 'LOADDTD' => $reader->getParserProperty(\XMLReader::LOADDTD), + 'DEFAULTATTRS' => $reader->getParserProperty(\XMLReader::DEFAULTATTRS), + 'VALIDATE' => $reader->getParserProperty(\XMLReader::VALIDATE), + 'SUBST_ENTITIES' => $reader->getParserProperty(\XMLReader::SUBST_ENTITIES), + ], + ]; + + if ($info[$props] = Caster::filter($info[$props], Caster::EXCLUDE_EMPTY, [], $count)) { + $info[$props] = new EnumStub($info[$props]); + $info[$props]->cut = $count; + } + + $info = Caster::filter($info, Caster::EXCLUDE_EMPTY, [], $count); + // +2 because hasValue and hasAttributes are always filtered + $stub->cut += $count + 2; + + return $a + $info; + } +} diff --git a/vendor/symfony/var-dumper/Caster/XmlResourceCaster.php b/vendor/symfony/var-dumper/Caster/XmlResourceCaster.php new file mode 100644 index 0000000..edece30 --- /dev/null +++ b/vendor/symfony/var-dumper/Caster/XmlResourceCaster.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts XML resources to array representation. + * + * @author Nicolas Grekas + * + * @final + */ +class XmlResourceCaster +{ + private static $xmlErrors = [ + XML_ERROR_NONE => 'XML_ERROR_NONE', + XML_ERROR_NO_MEMORY => 'XML_ERROR_NO_MEMORY', + XML_ERROR_SYNTAX => 'XML_ERROR_SYNTAX', + XML_ERROR_NO_ELEMENTS => 'XML_ERROR_NO_ELEMENTS', + XML_ERROR_INVALID_TOKEN => 'XML_ERROR_INVALID_TOKEN', + XML_ERROR_UNCLOSED_TOKEN => 'XML_ERROR_UNCLOSED_TOKEN', + XML_ERROR_PARTIAL_CHAR => 'XML_ERROR_PARTIAL_CHAR', + XML_ERROR_TAG_MISMATCH => 'XML_ERROR_TAG_MISMATCH', + XML_ERROR_DUPLICATE_ATTRIBUTE => 'XML_ERROR_DUPLICATE_ATTRIBUTE', + XML_ERROR_JUNK_AFTER_DOC_ELEMENT => 'XML_ERROR_JUNK_AFTER_DOC_ELEMENT', + XML_ERROR_PARAM_ENTITY_REF => 'XML_ERROR_PARAM_ENTITY_REF', + XML_ERROR_UNDEFINED_ENTITY => 'XML_ERROR_UNDEFINED_ENTITY', + XML_ERROR_RECURSIVE_ENTITY_REF => 'XML_ERROR_RECURSIVE_ENTITY_REF', + XML_ERROR_ASYNC_ENTITY => 'XML_ERROR_ASYNC_ENTITY', + XML_ERROR_BAD_CHAR_REF => 'XML_ERROR_BAD_CHAR_REF', + XML_ERROR_BINARY_ENTITY_REF => 'XML_ERROR_BINARY_ENTITY_REF', + XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF => 'XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF', + XML_ERROR_MISPLACED_XML_PI => 'XML_ERROR_MISPLACED_XML_PI', + XML_ERROR_UNKNOWN_ENCODING => 'XML_ERROR_UNKNOWN_ENCODING', + XML_ERROR_INCORRECT_ENCODING => 'XML_ERROR_INCORRECT_ENCODING', + XML_ERROR_UNCLOSED_CDATA_SECTION => 'XML_ERROR_UNCLOSED_CDATA_SECTION', + XML_ERROR_EXTERNAL_ENTITY_HANDLING => 'XML_ERROR_EXTERNAL_ENTITY_HANDLING', + ]; + + public static function castXml($h, array $a, Stub $stub, bool $isNested) + { + $a['current_byte_index'] = xml_get_current_byte_index($h); + $a['current_column_number'] = xml_get_current_column_number($h); + $a['current_line_number'] = xml_get_current_line_number($h); + $a['error_code'] = xml_get_error_code($h); + + if (isset(self::$xmlErrors[$a['error_code']])) { + $a['error_code'] = new ConstStub(self::$xmlErrors[$a['error_code']], $a['error_code']); + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Cloner/AbstractCloner.php b/vendor/symfony/var-dumper/Cloner/AbstractCloner.php new file mode 100644 index 0000000..56b2384 --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/AbstractCloner.php @@ -0,0 +1,360 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +use Symfony\Component\VarDumper\Caster\Caster; +use Symfony\Component\VarDumper\Exception\ThrowingCasterException; + +/** + * AbstractCloner implements a generic caster mechanism for objects and resources. + * + * @author Nicolas Grekas + */ +abstract class AbstractCloner implements ClonerInterface +{ + public static $defaultCasters = [ + '__PHP_Incomplete_Class' => ['Symfony\Component\VarDumper\Caster\Caster', 'castPhpIncompleteClass'], + + 'Symfony\Component\VarDumper\Caster\CutStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'], + 'Symfony\Component\VarDumper\Caster\CutArrayStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castCutArray'], + 'Symfony\Component\VarDumper\Caster\ConstStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'], + 'Symfony\Component\VarDumper\Caster\EnumStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castEnum'], + + 'Closure' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClosure'], + 'Generator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castGenerator'], + 'ReflectionType' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castType'], + 'ReflectionGenerator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReflectionGenerator'], + 'ReflectionClass' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClass'], + 'ReflectionFunctionAbstract' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castFunctionAbstract'], + 'ReflectionMethod' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castMethod'], + 'ReflectionParameter' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castParameter'], + 'ReflectionProperty' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castProperty'], + 'ReflectionReference' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReference'], + 'ReflectionExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castExtension'], + 'ReflectionZendExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castZendExtension'], + + 'Doctrine\Common\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'Doctrine\Common\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castCommonProxy'], + 'Doctrine\ORM\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castOrmProxy'], + 'Doctrine\ORM\PersistentCollection' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castPersistentCollection'], + 'Doctrine\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + + 'DOMException' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castException'], + 'DOMStringList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], + 'DOMNameList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], + 'DOMImplementation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castImplementation'], + 'DOMImplementationList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], + 'DOMNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNode'], + 'DOMNameSpaceNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNameSpaceNode'], + 'DOMDocument' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocument'], + 'DOMNodeList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], + 'DOMNamedNodeMap' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], + 'DOMCharacterData' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castCharacterData'], + 'DOMAttr' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castAttr'], + 'DOMElement' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castElement'], + 'DOMText' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castText'], + 'DOMTypeinfo' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castTypeinfo'], + 'DOMDomError' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDomError'], + 'DOMLocator' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLocator'], + 'DOMDocumentType' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocumentType'], + 'DOMNotation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNotation'], + 'DOMEntity' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castEntity'], + 'DOMProcessingInstruction' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castProcessingInstruction'], + 'DOMXPath' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castXPath'], + + 'XMLReader' => ['Symfony\Component\VarDumper\Caster\XmlReaderCaster', 'castXmlReader'], + + 'ErrorException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castErrorException'], + 'Exception' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castException'], + 'Error' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castError'], + 'Symfony\Component\DependencyInjection\ContainerInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'Symfony\Component\EventDispatcher\EventDispatcherInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'Symfony\Component\HttpClient\CurlHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], + 'Symfony\Component\HttpClient\NativeHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], + 'Symfony\Component\HttpClient\Response\CurlResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], + 'Symfony\Component\HttpClient\Response\NativeResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], + 'Symfony\Component\HttpFoundation\Request' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castRequest'], + 'Symfony\Component\VarDumper\Exception\ThrowingCasterException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castThrowingCasterException'], + 'Symfony\Component\VarDumper\Caster\TraceStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castTraceStub'], + 'Symfony\Component\VarDumper\Caster\FrameStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castFrameStub'], + 'Symfony\Component\VarDumper\Cloner\AbstractCloner' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'Symfony\Component\ErrorHandler\Exception\SilencedErrorContext' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castSilencedErrorContext'], + + 'Imagine\Image\ImageInterface' => ['Symfony\Component\VarDumper\Caster\ImagineCaster', 'castImage'], + + 'Ramsey\Uuid\UuidInterface' => ['Symfony\Component\VarDumper\Caster\UuidCaster', 'castRamseyUuid'], + + 'ProxyManager\Proxy\ProxyInterface' => ['Symfony\Component\VarDumper\Caster\ProxyManagerCaster', 'castProxy'], + 'PHPUnit_Framework_MockObject_MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'PHPUnit\Framework\MockObject\MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'PHPUnit\Framework\MockObject\Stub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'Prophecy\Prophecy\ProphecySubjectInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + 'Mockery\MockInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], + + 'PDO' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdo'], + 'PDOStatement' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdoStatement'], + + 'AMQPConnection' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castConnection'], + 'AMQPChannel' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castChannel'], + 'AMQPQueue' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castQueue'], + 'AMQPExchange' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castExchange'], + 'AMQPEnvelope' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castEnvelope'], + + 'ArrayObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayObject'], + 'ArrayIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayIterator'], + 'SplDoublyLinkedList' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'], + 'SplFileInfo' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'], + 'SplFileObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'], + 'SplFixedArray' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFixedArray'], + 'SplHeap' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], + 'SplObjectStorage' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castObjectStorage'], + 'SplPriorityQueue' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], + 'OuterIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castOuterIterator'], + 'WeakReference' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castWeakReference'], + + 'Redis' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedis'], + 'RedisArray' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisArray'], + 'RedisCluster' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisCluster'], + + 'DateTimeInterface' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castDateTime'], + 'DateInterval' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castInterval'], + 'DateTimeZone' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castTimeZone'], + 'DatePeriod' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castPeriod'], + + 'GMP' => ['Symfony\Component\VarDumper\Caster\GmpCaster', 'castGmp'], + + 'MessageFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castMessageFormatter'], + 'NumberFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castNumberFormatter'], + 'IntlTimeZone' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlTimeZone'], + 'IntlCalendar' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlCalendar'], + 'IntlDateFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlDateFormatter'], + + 'Memcached' => ['Symfony\Component\VarDumper\Caster\MemcachedCaster', 'castMemcached'], + + 'Ds\Collection' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castCollection'], + 'Ds\Map' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castMap'], + 'Ds\Pair' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castPair'], + 'Symfony\Component\VarDumper\Caster\DsPairStub' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castPairStub'], + + ':curl' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'], + ':dba' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'], + ':dba persistent' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'], + ':gd' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'], + ':mysql link' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castMysqlLink'], + ':pgsql large object' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLargeObject'], + ':pgsql link' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'], + ':pgsql link persistent' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'], + ':pgsql result' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castResult'], + ':process' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castProcess'], + ':stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'], + ':OpenSSL X.509' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castOpensslX509'], + ':persistent stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'], + ':stream-context' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStreamContext'], + ':xml' => ['Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'], + ]; + + protected $maxItems = 2500; + protected $maxString = -1; + protected $minDepth = 1; + + private $casters = []; + private $prevErrorHandler; + private $classInfo = []; + private $filter = 0; + + /** + * @param callable[]|null $casters A map of casters + * + * @see addCasters + */ + public function __construct(array $casters = null) + { + if (null === $casters) { + $casters = static::$defaultCasters; + } + $this->addCasters($casters); + } + + /** + * Adds casters for resources and objects. + * + * Maps resources or objects types to a callback. + * Types are in the key, with a callable caster for value. + * Resource types are to be prefixed with a `:`, + * see e.g. static::$defaultCasters. + * + * @param callable[] $casters A map of casters + */ + public function addCasters(array $casters) + { + foreach ($casters as $type => $callback) { + $this->casters[$type][] = $callback; + } + } + + /** + * Sets the maximum number of items to clone past the minimum depth in nested structures. + */ + public function setMaxItems(int $maxItems) + { + $this->maxItems = $maxItems; + } + + /** + * Sets the maximum cloned length for strings. + */ + public function setMaxString(int $maxString) + { + $this->maxString = $maxString; + } + + /** + * Sets the minimum tree depth where we are guaranteed to clone all the items. After this + * depth is reached, only setMaxItems items will be cloned. + */ + public function setMinDepth(int $minDepth) + { + $this->minDepth = $minDepth; + } + + /** + * Clones a PHP variable. + * + * @param mixed $var Any PHP variable + * @param int $filter A bit field of Caster::EXCLUDE_* constants + * + * @return Data The cloned variable represented by a Data object + */ + public function cloneVar($var, int $filter = 0) + { + $this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) { + if (E_RECOVERABLE_ERROR === $type || E_USER_ERROR === $type) { + // Cloner never dies + throw new \ErrorException($msg, 0, $type, $file, $line); + } + + if ($this->prevErrorHandler) { + return ($this->prevErrorHandler)($type, $msg, $file, $line, $context); + } + + return false; + }); + $this->filter = $filter; + + if ($gc = gc_enabled()) { + gc_disable(); + } + try { + return new Data($this->doClone($var)); + } finally { + if ($gc) { + gc_enable(); + } + restore_error_handler(); + $this->prevErrorHandler = null; + } + } + + /** + * Effectively clones the PHP variable. + * + * @param mixed $var Any PHP variable + * + * @return array The cloned variable represented in an array + */ + abstract protected function doClone($var); + + /** + * Casts an object to an array representation. + * + * @param bool $isNested True if the object is nested in the dumped structure + * + * @return array The object casted as array + */ + protected function castObject(Stub $stub, bool $isNested) + { + $obj = $stub->value; + $class = $stub->class; + + if (isset($class[15]) && "\0" === $class[15] && 0 === strpos($class, "class@anonymous\x00")) { + $stub->class = get_parent_class($class).'@anonymous'; + } + if (isset($this->classInfo[$class])) { + list($i, $parents, $hasDebugInfo, $fileInfo) = $this->classInfo[$class]; + } else { + $i = 2; + $parents = [$class]; + $hasDebugInfo = method_exists($class, '__debugInfo'); + + foreach (class_parents($class) as $p) { + $parents[] = $p; + ++$i; + } + foreach (class_implements($class) as $p) { + $parents[] = $p; + ++$i; + } + $parents[] = '*'; + + $r = new \ReflectionClass($class); + $fileInfo = $r->isInternal() || $r->isSubclassOf(Stub::class) ? [] : [ + 'file' => $r->getFileName(), + 'line' => $r->getStartLine(), + ]; + + $this->classInfo[$class] = [$i, $parents, $hasDebugInfo, $fileInfo]; + } + + $stub->attr += $fileInfo; + $a = Caster::castObject($obj, $class, $hasDebugInfo); + + try { + while ($i--) { + if (!empty($this->casters[$p = $parents[$i]])) { + foreach ($this->casters[$p] as $callback) { + $a = $callback($obj, $a, $stub, $isNested, $this->filter); + } + } + } + } catch (\Exception $e) { + $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a; + } + + return $a; + } + + /** + * Casts a resource to an array representation. + * + * @param bool $isNested True if the object is nested in the dumped structure + * + * @return array The resource casted as array + */ + protected function castResource(Stub $stub, bool $isNested) + { + $a = []; + $res = $stub->value; + $type = $stub->class; + + try { + if (!empty($this->casters[':'.$type])) { + foreach ($this->casters[':'.$type] as $callback) { + $a = $callback($res, $a, $stub, $isNested, $this->filter); + } + } + } catch (\Exception $e) { + $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a; + } + + return $a; + } +} diff --git a/vendor/symfony/var-dumper/Cloner/ClonerInterface.php b/vendor/symfony/var-dumper/Cloner/ClonerInterface.php new file mode 100644 index 0000000..7ed287a --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/ClonerInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +/** + * @author Nicolas Grekas + */ +interface ClonerInterface +{ + /** + * Clones a PHP variable. + * + * @param mixed $var Any PHP variable + * + * @return Data The cloned variable represented by a Data object + */ + public function cloneVar($var); +} diff --git a/vendor/symfony/var-dumper/Cloner/Cursor.php b/vendor/symfony/var-dumper/Cloner/Cursor.php new file mode 100644 index 0000000..5b0542f --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/Cursor.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +/** + * Represents the current state of a dumper while dumping. + * + * @author Nicolas Grekas + */ +class Cursor +{ + const HASH_INDEXED = Stub::ARRAY_INDEXED; + const HASH_ASSOC = Stub::ARRAY_ASSOC; + const HASH_OBJECT = Stub::TYPE_OBJECT; + const HASH_RESOURCE = Stub::TYPE_RESOURCE; + + public $depth = 0; + public $refIndex = 0; + public $softRefTo = 0; + public $softRefCount = 0; + public $softRefHandle = 0; + public $hardRefTo = 0; + public $hardRefCount = 0; + public $hardRefHandle = 0; + public $hashType; + public $hashKey; + public $hashKeyIsBinary; + public $hashIndex = 0; + public $hashLength = 0; + public $hashCut = 0; + public $stop = false; + public $attr = []; + public $skipChildren = false; +} diff --git a/vendor/symfony/var-dumper/Cloner/Data.php b/vendor/symfony/var-dumper/Cloner/Data.php new file mode 100644 index 0000000..e907197 --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/Data.php @@ -0,0 +1,451 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +use Symfony\Component\VarDumper\Caster\Caster; +use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; + +/** + * @author Nicolas Grekas + */ +class Data implements \ArrayAccess, \Countable, \IteratorAggregate +{ + private $data; + private $position = 0; + private $key = 0; + private $maxDepth = 20; + private $maxItemsPerDepth = -1; + private $useRefHandles = -1; + private $context = []; + + /** + * @param array $data An array as returned by ClonerInterface::cloneVar() + */ + public function __construct(array $data) + { + $this->data = $data; + } + + /** + * @return string|null The type of the value + */ + public function getType() + { + $item = $this->data[$this->position][$this->key]; + + if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { + $item = $item->value; + } + if (!$item instanceof Stub) { + return \gettype($item); + } + if (Stub::TYPE_STRING === $item->type) { + return 'string'; + } + if (Stub::TYPE_ARRAY === $item->type) { + return 'array'; + } + if (Stub::TYPE_OBJECT === $item->type) { + return $item->class; + } + if (Stub::TYPE_RESOURCE === $item->type) { + return $item->class.' resource'; + } + + return null; + } + + /** + * @param array|bool $recursive Whether values should be resolved recursively or not + * + * @return string|int|float|bool|array|Data[]|null A native representation of the original value + */ + public function getValue($recursive = false) + { + $item = $this->data[$this->position][$this->key]; + + if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { + $item = $item->value; + } + if (!($item = $this->getStub($item)) instanceof Stub) { + return $item; + } + if (Stub::TYPE_STRING === $item->type) { + return $item->value; + } + + $children = $item->position ? $this->data[$item->position] : []; + + foreach ($children as $k => $v) { + if ($recursive && !($v = $this->getStub($v)) instanceof Stub) { + continue; + } + $children[$k] = clone $this; + $children[$k]->key = $k; + $children[$k]->position = $item->position; + + if ($recursive) { + if (Stub::TYPE_REF === $v->type && ($v = $this->getStub($v->value)) instanceof Stub) { + $recursive = (array) $recursive; + if (isset($recursive[$v->position])) { + continue; + } + $recursive[$v->position] = true; + } + $children[$k] = $children[$k]->getValue($recursive); + } + } + + return $children; + } + + /** + * @return int + */ + public function count() + { + return \count($this->getValue()); + } + + /** + * @return \Traversable + */ + public function getIterator() + { + if (!\is_array($value = $this->getValue())) { + throw new \LogicException(sprintf('%s object holds non-iterable type "%s".', self::class, \gettype($value))); + } + + yield from $value; + } + + public function __get(string $key) + { + if (null !== $data = $this->seek($key)) { + $item = $this->getStub($data->data[$data->position][$data->key]); + + return $item instanceof Stub || [] === $item ? $data : $item; + } + + return null; + } + + /** + * @return bool + */ + public function __isset(string $key) + { + return null !== $this->seek($key); + } + + /** + * @return bool + */ + public function offsetExists($key) + { + return $this->__isset($key); + } + + public function offsetGet($key) + { + return $this->__get($key); + } + + public function offsetSet($key, $value) + { + throw new \BadMethodCallException(self::class.' objects are immutable.'); + } + + public function offsetUnset($key) + { + throw new \BadMethodCallException(self::class.' objects are immutable.'); + } + + /** + * @return string + */ + public function __toString() + { + $value = $this->getValue(); + + if (!\is_array($value)) { + return (string) $value; + } + + return sprintf('%s (count=%d)', $this->getType(), \count($value)); + } + + /** + * Returns a depth limited clone of $this. + * + * @return static + */ + public function withMaxDepth(int $maxDepth) + { + $data = clone $this; + $data->maxDepth = (int) $maxDepth; + + return $data; + } + + /** + * Limits the number of elements per depth level. + * + * @return static + */ + public function withMaxItemsPerDepth(int $maxItemsPerDepth) + { + $data = clone $this; + $data->maxItemsPerDepth = (int) $maxItemsPerDepth; + + return $data; + } + + /** + * Enables/disables objects' identifiers tracking. + * + * @param bool $useRefHandles False to hide global ref. handles + * + * @return static + */ + public function withRefHandles(bool $useRefHandles) + { + $data = clone $this; + $data->useRefHandles = $useRefHandles ? -1 : 0; + + return $data; + } + + /** + * @return static + */ + public function withContext(array $context) + { + $data = clone $this; + $data->context = $context; + + return $data; + } + + /** + * Seeks to a specific key in nested data structures. + * + * @param string|int $key The key to seek to + * + * @return static|null Null if the key is not set + */ + public function seek($key) + { + $item = $this->data[$this->position][$this->key]; + + if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { + $item = $item->value; + } + if (!($item = $this->getStub($item)) instanceof Stub || !$item->position) { + return null; + } + $keys = [$key]; + + switch ($item->type) { + case Stub::TYPE_OBJECT: + $keys[] = Caster::PREFIX_DYNAMIC.$key; + $keys[] = Caster::PREFIX_PROTECTED.$key; + $keys[] = Caster::PREFIX_VIRTUAL.$key; + $keys[] = "\0$item->class\0$key"; + // no break + case Stub::TYPE_ARRAY: + case Stub::TYPE_RESOURCE: + break; + default: + return null; + } + + $data = null; + $children = $this->data[$item->position]; + + foreach ($keys as $key) { + if (isset($children[$key]) || \array_key_exists($key, $children)) { + $data = clone $this; + $data->key = $key; + $data->position = $item->position; + break; + } + } + + return $data; + } + + /** + * Dumps data with a DumperInterface dumper. + */ + public function dump(DumperInterface $dumper) + { + $refs = [0]; + $cursor = new Cursor(); + + if ($cursor->attr = $this->context[SourceContextProvider::class] ?? []) { + $cursor->attr['if_links'] = true; + $cursor->hashType = -1; + $dumper->dumpScalar($cursor, 'default', '^'); + $cursor->attr = ['if_links' => true]; + $dumper->dumpScalar($cursor, 'default', ' '); + $cursor->hashType = 0; + } + + $this->dumpItem($dumper, $cursor, $refs, $this->data[$this->position][$this->key]); + } + + /** + * Depth-first dumping of items. + * + * @param mixed $item A Stub object or the original value being dumped + */ + private function dumpItem(DumperInterface $dumper, Cursor $cursor, array &$refs, $item) + { + $cursor->refIndex = 0; + $cursor->softRefTo = $cursor->softRefHandle = $cursor->softRefCount = 0; + $cursor->hardRefTo = $cursor->hardRefHandle = $cursor->hardRefCount = 0; + $firstSeen = true; + + if (!$item instanceof Stub) { + $cursor->attr = []; + $type = \gettype($item); + if ($item && 'array' === $type) { + $item = $this->getStub($item); + } + } elseif (Stub::TYPE_REF === $item->type) { + if ($item->handle) { + if (!isset($refs[$r = $item->handle - (PHP_INT_MAX >> 1)])) { + $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0]; + } else { + $firstSeen = false; + } + $cursor->hardRefTo = $refs[$r]; + $cursor->hardRefHandle = $this->useRefHandles & $item->handle; + $cursor->hardRefCount = $item->refCount; + } + $cursor->attr = $item->attr; + $type = $item->class ?: \gettype($item->value); + $item = $this->getStub($item->value); + } + if ($item instanceof Stub) { + if ($item->refCount) { + if (!isset($refs[$r = $item->handle])) { + $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0]; + } else { + $firstSeen = false; + } + $cursor->softRefTo = $refs[$r]; + } + $cursor->softRefHandle = $this->useRefHandles & $item->handle; + $cursor->softRefCount = $item->refCount; + $cursor->attr = $item->attr; + $cut = $item->cut; + + if ($item->position && $firstSeen) { + $children = $this->data[$item->position]; + + if ($cursor->stop) { + if ($cut >= 0) { + $cut += \count($children); + } + $children = []; + } + } else { + $children = []; + } + switch ($item->type) { + case Stub::TYPE_STRING: + $dumper->dumpString($cursor, $item->value, Stub::STRING_BINARY === $item->class, $cut); + break; + + case Stub::TYPE_ARRAY: + $item = clone $item; + $item->type = $item->class; + $item->class = $item->value; + // no break + case Stub::TYPE_OBJECT: + case Stub::TYPE_RESOURCE: + $withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth; + $dumper->enterHash($cursor, $item->type, $item->class, $withChildren); + if ($withChildren) { + if ($cursor->skipChildren) { + $withChildren = false; + $cut = -1; + } else { + $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class); + } + } elseif ($children && 0 <= $cut) { + $cut += \count($children); + } + $cursor->skipChildren = false; + $dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut); + break; + + default: + throw new \RuntimeException(sprintf('Unexpected Stub type: %s', $item->type)); + } + } elseif ('array' === $type) { + $dumper->enterHash($cursor, Cursor::HASH_INDEXED, 0, false); + $dumper->leaveHash($cursor, Cursor::HASH_INDEXED, 0, false, 0); + } elseif ('string' === $type) { + $dumper->dumpString($cursor, $item, false, 0); + } else { + $dumper->dumpScalar($cursor, $type, $item); + } + } + + /** + * Dumps children of hash structures. + * + * @return int The final number of removed items + */ + private function dumpChildren(DumperInterface $dumper, Cursor $parentCursor, array &$refs, array $children, int $hashCut, int $hashType, bool $dumpKeys): int + { + $cursor = clone $parentCursor; + ++$cursor->depth; + $cursor->hashType = $hashType; + $cursor->hashIndex = 0; + $cursor->hashLength = \count($children); + $cursor->hashCut = $hashCut; + foreach ($children as $key => $child) { + $cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key); + $cursor->hashKey = $dumpKeys ? $key : null; + $this->dumpItem($dumper, $cursor, $refs, $child); + if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) { + $parentCursor->stop = true; + + return $hashCut >= 0 ? $hashCut + $cursor->hashLength - $cursor->hashIndex : $hashCut; + } + } + + return $hashCut; + } + + private function getStub($item) + { + if (!$item || !\is_array($item)) { + return $item; + } + + $stub = new Stub(); + $stub->type = Stub::TYPE_ARRAY; + foreach ($item as $stub->class => $stub->position) { + } + if (isset($item[0])) { + $stub->cut = $item[0]; + } + $stub->value = $stub->cut + ($stub->position ? \count($this->data[$stub->position]) : 0); + + return $stub; + } +} diff --git a/vendor/symfony/var-dumper/Cloner/DumperInterface.php b/vendor/symfony/var-dumper/Cloner/DumperInterface.php new file mode 100644 index 0000000..6d60b72 --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/DumperInterface.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +/** + * DumperInterface used by Data objects. + * + * @author Nicolas Grekas + */ +interface DumperInterface +{ + /** + * Dumps a scalar value. + * + * @param string $type The PHP type of the value being dumped + * @param string|int|float|bool $value The scalar value being dumped + */ + public function dumpScalar(Cursor $cursor, string $type, $value); + + /** + * Dumps a string. + * + * @param string $str The string being dumped + * @param bool $bin Whether $str is UTF-8 or binary encoded + * @param int $cut The number of characters $str has been cut by + */ + public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut); + + /** + * Dumps while entering an hash. + * + * @param int $type A Cursor::HASH_* const for the type of hash + * @param string|int $class The object class, resource type or array count + * @param bool $hasChild When the dump of the hash has child item + */ + public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild); + + /** + * Dumps while leaving an hash. + * + * @param int $type A Cursor::HASH_* const for the type of hash + * @param string|int $class The object class, resource type or array count + * @param bool $hasChild When the dump of the hash has child item + * @param int $cut The number of items the hash has been cut by + */ + public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut); +} diff --git a/vendor/symfony/var-dumper/Cloner/Stub.php b/vendor/symfony/var-dumper/Cloner/Stub.php new file mode 100644 index 0000000..7e9eb6d --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/Stub.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +/** + * Represents the main properties of a PHP variable. + * + * @author Nicolas Grekas + */ +class Stub +{ + const TYPE_REF = 1; + const TYPE_STRING = 2; + const TYPE_ARRAY = 3; + const TYPE_OBJECT = 4; + const TYPE_RESOURCE = 5; + + const STRING_BINARY = 1; + const STRING_UTF8 = 2; + + const ARRAY_ASSOC = 1; + const ARRAY_INDEXED = 2; + + public $type = self::TYPE_REF; + public $class = ''; + public $value; + public $cut = 0; + public $handle = 0; + public $refCount = 0; + public $position = 0; + public $attr = []; + + private static $defaultProperties = []; + + /** + * @internal + */ + public function __sleep(): array + { + $properties = []; + + if (!isset(self::$defaultProperties[$c = \get_class($this)])) { + self::$defaultProperties[$c] = get_class_vars($c); + + foreach ((new \ReflectionClass($c))->getStaticProperties() as $k => $v) { + unset(self::$defaultProperties[$c][$k]); + } + } + + foreach (self::$defaultProperties[$c] as $k => $v) { + if ($this->$k !== $v) { + $properties[] = $k; + } + } + + return $properties; + } +} diff --git a/vendor/symfony/var-dumper/Cloner/VarCloner.php b/vendor/symfony/var-dumper/Cloner/VarCloner.php new file mode 100644 index 0000000..4c653d6 --- /dev/null +++ b/vendor/symfony/var-dumper/Cloner/VarCloner.php @@ -0,0 +1,285 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Cloner; + +/** + * @author Nicolas Grekas + */ +class VarCloner extends AbstractCloner +{ + private static $gid; + private static $arrayCache = []; + + /** + * {@inheritdoc} + */ + protected function doClone($var) + { + $len = 1; // Length of $queue + $pos = 0; // Number of cloned items past the minimum depth + $refsCounter = 0; // Hard references counter + $queue = [[$var]]; // This breadth-first queue is the return value + $indexedArrays = []; // Map of queue indexes that hold numerically indexed arrays + $hardRefs = []; // Map of original zval ids to stub objects + $objRefs = []; // Map of original object handles to their stub object counterpart + $objects = []; // Keep a ref to objects to ensure their handle cannot be reused while cloning + $resRefs = []; // Map of original resource handles to their stub object counterpart + $values = []; // Map of stub objects' ids to original values + $maxItems = $this->maxItems; + $maxString = $this->maxString; + $minDepth = $this->minDepth; + $currentDepth = 0; // Current tree depth + $currentDepthFinalIndex = 0; // Final $queue index for current tree depth + $minimumDepthReached = 0 === $minDepth; // Becomes true when minimum tree depth has been reached + $cookie = (object) []; // Unique object used to detect hard references + $a = null; // Array cast for nested structures + $stub = null; // Stub capturing the main properties of an original item value + // or null if the original value is used directly + + if (!$gid = self::$gid) { + $gid = self::$gid = uniqid(mt_rand(), true); // Unique string used to detect the special $GLOBALS variable + } + $arrayStub = new Stub(); + $arrayStub->type = Stub::TYPE_ARRAY; + $fromObjCast = false; + + for ($i = 0; $i < $len; ++$i) { + // Detect when we move on to the next tree depth + if ($i > $currentDepthFinalIndex) { + ++$currentDepth; + $currentDepthFinalIndex = $len - 1; + if ($currentDepth >= $minDepth) { + $minimumDepthReached = true; + } + } + + $refs = $vals = $queue[$i]; + foreach ($vals as $k => $v) { + // $v is the original value or a stub object in case of hard references + + if (\PHP_VERSION_ID >= 70400) { + $zvalIsRef = null !== \ReflectionReference::fromArrayElement($vals, $k); + } else { + $refs[$k] = $cookie; + $zvalIsRef = $vals[$k] === $cookie; + } + + if ($zvalIsRef) { + $vals[$k] = &$stub; // Break hard references to make $queue completely + unset($stub); // independent from the original structure + if ($v instanceof Stub && isset($hardRefs[spl_object_id($v)])) { + $vals[$k] = $refs[$k] = $v; + if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) { + ++$v->value->refCount; + } + ++$v->refCount; + continue; + } + $refs[$k] = $vals[$k] = new Stub(); + $refs[$k]->value = $v; + $h = spl_object_id($refs[$k]); + $hardRefs[$h] = &$refs[$k]; + $values[$h] = $v; + $vals[$k]->handle = ++$refsCounter; + } + // Create $stub when the original value $v can not be used directly + // If $v is a nested structure, put that structure in array $a + switch (true) { + case null === $v: + case \is_bool($v): + case \is_int($v): + case \is_float($v): + continue 2; + + case \is_string($v): + if ('' === $v) { + continue 2; + } + if (!preg_match('//u', $v)) { + $stub = new Stub(); + $stub->type = Stub::TYPE_STRING; + $stub->class = Stub::STRING_BINARY; + if (0 <= $maxString && 0 < $cut = \strlen($v) - $maxString) { + $stub->cut = $cut; + $stub->value = substr($v, 0, -$cut); + } else { + $stub->value = $v; + } + } elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) { + $stub = new Stub(); + $stub->type = Stub::TYPE_STRING; + $stub->class = Stub::STRING_UTF8; + $stub->cut = $cut; + $stub->value = mb_substr($v, 0, $maxString, 'UTF-8'); + } else { + continue 2; + } + $a = null; + break; + + case \is_array($v): + if (!$v) { + continue 2; + } + $stub = $arrayStub; + $stub->class = Stub::ARRAY_INDEXED; + + $j = -1; + foreach ($v as $gk => $gv) { + if ($gk !== ++$j) { + $stub->class = Stub::ARRAY_ASSOC; + break; + } + } + $a = $v; + + if (Stub::ARRAY_ASSOC === $stub->class) { + // Copies of $GLOBALS have very strange behavior, + // let's detect them with some black magic + $a[$gid] = true; + + // Happens with copies of $GLOBALS + if (isset($v[$gid])) { + unset($v[$gid]); + $a = []; + foreach ($v as $gk => &$gv) { + $a[$gk] = &$gv; + } + unset($gv); + } else { + $a = $v; + } + } + break; + + case \is_object($v): + case $v instanceof \__PHP_Incomplete_Class: + if (empty($objRefs[$h = spl_object_id($v)])) { + $stub = new Stub(); + $stub->type = Stub::TYPE_OBJECT; + $stub->class = \get_class($v); + $stub->value = $v; + $stub->handle = $h; + $a = $this->castObject($stub, 0 < $i); + if ($v !== $stub->value) { + if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) { + break; + } + $stub->handle = $h = spl_object_id($stub->value); + } + $stub->value = null; + if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) { + $stub->cut = \count($a); + $a = null; + } + } + if (empty($objRefs[$h])) { + $objRefs[$h] = $stub; + $objects[] = $v; + } else { + $stub = $objRefs[$h]; + ++$stub->refCount; + $a = null; + } + break; + + default: // resource + if (empty($resRefs[$h = (int) $v])) { + $stub = new Stub(); + $stub->type = Stub::TYPE_RESOURCE; + if ('Unknown' === $stub->class = @get_resource_type($v)) { + $stub->class = 'Closed'; + } + $stub->value = $v; + $stub->handle = $h; + $a = $this->castResource($stub, 0 < $i); + $stub->value = null; + if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) { + $stub->cut = \count($a); + $a = null; + } + } + if (empty($resRefs[$h])) { + $resRefs[$h] = $stub; + } else { + $stub = $resRefs[$h]; + ++$stub->refCount; + $a = null; + } + break; + } + + if ($a) { + if (!$minimumDepthReached || 0 > $maxItems) { + $queue[$len] = $a; + $stub->position = $len++; + } elseif ($pos < $maxItems) { + if ($maxItems < $pos += \count($a)) { + $a = \array_slice($a, 0, $maxItems - $pos); + if ($stub->cut >= 0) { + $stub->cut += $pos - $maxItems; + } + } + $queue[$len] = $a; + $stub->position = $len++; + } elseif ($stub->cut >= 0) { + $stub->cut += \count($a); + $stub->position = 0; + } + } + + if ($arrayStub === $stub) { + if ($arrayStub->cut) { + $stub = [$arrayStub->cut, $arrayStub->class => $arrayStub->position]; + $arrayStub->cut = 0; + } elseif (isset(self::$arrayCache[$arrayStub->class][$arrayStub->position])) { + $stub = self::$arrayCache[$arrayStub->class][$arrayStub->position]; + } else { + self::$arrayCache[$arrayStub->class][$arrayStub->position] = $stub = [$arrayStub->class => $arrayStub->position]; + } + } + + if ($zvalIsRef) { + $refs[$k]->value = $stub; + } else { + $vals[$k] = $stub; + } + } + + if ($fromObjCast) { + $fromObjCast = false; + $refs = $vals; + $vals = []; + $j = -1; + foreach ($queue[$i] as $k => $v) { + foreach ([$k => true] as $gk => $gv) { + } + if ($gk !== $k) { + $vals = (object) $vals; + $vals->{$k} = $refs[++$j]; + $vals = (array) $vals; + } else { + $vals[$k] = $refs[++$j]; + } + } + } + + $queue[$i] = $vals; + } + + foreach ($values as $h => $v) { + $hardRefs[$h] = $v; + } + + return $queue; + } +} diff --git a/vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php b/vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php new file mode 100644 index 0000000..dc77d03 --- /dev/null +++ b/vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Command\Descriptor; + +use Symfony\Component\Console\Formatter\OutputFormatterStyle; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\CliDumper; + +/** + * Describe collected data clones for cli output. + * + * @author Maxime Steinhausser + * + * @final + */ +class CliDescriptor implements DumpDescriptorInterface +{ + private $dumper; + private $lastIdentifier; + private $supportsHref; + + public function __construct(CliDumper $dumper) + { + $this->dumper = $dumper; + $this->supportsHref = method_exists(OutputFormatterStyle::class, 'setHref'); + } + + public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void + { + $io = $output instanceof SymfonyStyle ? $output : new SymfonyStyle(new ArrayInput([]), $output); + $this->dumper->setColors($output->isDecorated()); + + $rows = [['date', date('r', $context['timestamp'])]]; + $lastIdentifier = $this->lastIdentifier; + $this->lastIdentifier = $clientId; + + $section = "Received from client #$clientId"; + if (isset($context['request'])) { + $request = $context['request']; + $this->lastIdentifier = $request['identifier']; + $section = sprintf('%s %s', $request['method'], $request['uri']); + if ($controller = $request['controller']) { + $rows[] = ['controller', rtrim($this->dumper->dump($controller, true), "\n")]; + } + } elseif (isset($context['cli'])) { + $this->lastIdentifier = $context['cli']['identifier']; + $section = '$ '.$context['cli']['command_line']; + } + + if ($this->lastIdentifier !== $lastIdentifier) { + $io->section($section); + } + + if (isset($context['source'])) { + $source = $context['source']; + $sourceInfo = sprintf('%s on line %d', $source['name'], $source['line']); + $fileLink = $source['file_link'] ?? null; + if ($this->supportsHref && $fileLink) { + $sourceInfo = sprintf('%s', $fileLink, $sourceInfo); + } + $rows[] = ['source', $sourceInfo]; + $file = $source['file_relative'] ?? $source['file']; + $rows[] = ['file', $file]; + } + + $io->table([], $rows); + + if (!$this->supportsHref && isset($fileLink)) { + $io->writeln(['Open source in your IDE/browser:', $fileLink]); + $io->newLine(); + } + + $this->dumper->dump($data); + $io->newLine(); + } +} diff --git a/vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php b/vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php new file mode 100644 index 0000000..267d27b --- /dev/null +++ b/vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Command\Descriptor; + +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\VarDumper\Cloner\Data; + +/** + * @author Maxime Steinhausser + */ +interface DumpDescriptorInterface +{ + public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void; +} diff --git a/vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php b/vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php new file mode 100644 index 0000000..35a203b --- /dev/null +++ b/vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Command\Descriptor; + +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\HtmlDumper; + +/** + * Describe collected data clones for html output. + * + * @author Maxime Steinhausser + * + * @final + */ +class HtmlDescriptor implements DumpDescriptorInterface +{ + private $dumper; + private $initialized = false; + + public function __construct(HtmlDumper $dumper) + { + $this->dumper = $dumper; + } + + public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void + { + if (!$this->initialized) { + $styles = file_get_contents(__DIR__.'/../../Resources/css/htmlDescriptor.css'); + $scripts = file_get_contents(__DIR__.'/../../Resources/js/htmlDescriptor.js'); + $output->writeln(""); + $this->initialized = true; + } + + $title = '-'; + if (isset($context['request'])) { + $request = $context['request']; + $controller = "{$this->dumper->dump($request['controller'], true, ['maxDepth' => 0])}"; + $title = sprintf('%s %s', $request['method'], $uri = $request['uri'], $uri); + $dedupIdentifier = $request['identifier']; + } elseif (isset($context['cli'])) { + $title = '$ '.$context['cli']['command_line']; + $dedupIdentifier = $context['cli']['identifier']; + } else { + $dedupIdentifier = uniqid('', true); + } + + $sourceDescription = ''; + if (isset($context['source'])) { + $source = $context['source']; + $projectDir = $source['project_dir'] ?? null; + $sourceDescription = sprintf('%s on line %d', $source['name'], $source['line']); + if (isset($source['file_link'])) { + $sourceDescription = sprintf('%s', $source['file_link'], $sourceDescription); + } + } + + $isoDate = $this->extractDate($context, 'c'); + $tags = array_filter([ + 'controller' => $controller ?? null, + 'project dir' => $projectDir ?? null, + ]); + + $output->writeln(<< +
    +
    +

    $title

    + +
    + {$this->renderTags($tags)} +
    +
    +

    + $sourceDescription +

    + {$this->dumper->dump($data, true)} +
    + +HTML + ); + } + + private function extractDate(array $context, string $format = 'r'): string + { + return date($format, $context['timestamp']); + } + + private function renderTags(array $tags): string + { + if (!$tags) { + return ''; + } + + $renderedTags = ''; + foreach ($tags as $key => $value) { + $renderedTags .= sprintf('
  • %s%s
  • ', $key, $value); + } + + return << +
      + $renderedTags +
    + +HTML; + } +} diff --git a/vendor/symfony/var-dumper/Command/ServerDumpCommand.php b/vendor/symfony/var-dumper/Command/ServerDumpCommand.php new file mode 100644 index 0000000..c8a61da --- /dev/null +++ b/vendor/symfony/var-dumper/Command/ServerDumpCommand.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Command\Descriptor\CliDescriptor; +use Symfony\Component\VarDumper\Command\Descriptor\DumpDescriptorInterface; +use Symfony\Component\VarDumper\Command\Descriptor\HtmlDescriptor; +use Symfony\Component\VarDumper\Dumper\CliDumper; +use Symfony\Component\VarDumper\Dumper\HtmlDumper; +use Symfony\Component\VarDumper\Server\DumpServer; + +/** + * Starts a dump server to collect and output dumps on a single place with multiple formats support. + * + * @author Maxime Steinhausser + * + * @final + */ +class ServerDumpCommand extends Command +{ + protected static $defaultName = 'server:dump'; + + private $server; + + /** @var DumpDescriptorInterface[] */ + private $descriptors; + + public function __construct(DumpServer $server, array $descriptors = []) + { + $this->server = $server; + $this->descriptors = $descriptors + [ + 'cli' => new CliDescriptor(new CliDumper()), + 'html' => new HtmlDescriptor(new HtmlDumper()), + ]; + + parent::__construct(); + } + + protected function configure() + { + $availableFormats = implode(', ', array_keys($this->descriptors)); + + $this + ->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format (%s)', $availableFormats), 'cli') + ->setDescription('Starts a dump server that collects and displays dumps in a single place') + ->setHelp(<<<'EOF' +%command.name% starts a dump server that collects and displays +dumps in a single place for debugging you application: + + php %command.full_name% + +You can consult dumped data in HTML format in your browser by providing the --format=html option +and redirecting the output to a file: + + php %command.full_name% --format="html" > dump.html + +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $format = $input->getOption('format'); + + if (!$descriptor = $this->descriptors[$format] ?? null) { + throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $format)); + } + + $errorIo = $io->getErrorStyle(); + $errorIo->title('Symfony Var Dumper Server'); + + $this->server->start(); + + $errorIo->success(sprintf('Server listening on %s', $this->server->getHost())); + $errorIo->comment('Quit the server with CONTROL-C.'); + + $this->server->listen(function (Data $data, array $context, int $clientId) use ($descriptor, $io) { + $descriptor->describe($io, $data, $context, $clientId); + }); + } +} diff --git a/vendor/symfony/var-dumper/Dumper/AbstractDumper.php b/vendor/symfony/var-dumper/Dumper/AbstractDumper.php new file mode 100644 index 0000000..1a00038 --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/AbstractDumper.php @@ -0,0 +1,204 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper; + +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Cloner\DumperInterface; + +/** + * Abstract mechanism for dumping a Data object. + * + * @author Nicolas Grekas + */ +abstract class AbstractDumper implements DataDumperInterface, DumperInterface +{ + const DUMP_LIGHT_ARRAY = 1; + const DUMP_STRING_LENGTH = 2; + const DUMP_COMMA_SEPARATOR = 4; + const DUMP_TRAILING_COMMA = 8; + + public static $defaultOutput = 'php://output'; + + protected $line = ''; + protected $lineDumper; + protected $outputStream; + protected $decimalPoint; // This is locale dependent + protected $indentPad = ' '; + protected $flags; + + private $charset = ''; + + /** + * @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput + * @param string|null $charset The default character encoding to use for non-UTF8 strings + * @param int $flags A bit field of static::DUMP_* constants to fine tune dumps representation + */ + public function __construct($output = null, string $charset = null, int $flags = 0) + { + $this->flags = $flags; + $this->setCharset($charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8'); + $this->decimalPoint = localeconv(); + $this->decimalPoint = $this->decimalPoint['decimal_point']; + $this->setOutput($output ?: static::$defaultOutput); + if (!$output && \is_string(static::$defaultOutput)) { + static::$defaultOutput = $this->outputStream; + } + } + + /** + * Sets the output destination of the dumps. + * + * @param callable|resource|string $output A line dumper callable, an opened stream or an output path + * + * @return callable|resource|string The previous output destination + */ + public function setOutput($output) + { + $prev = null !== $this->outputStream ? $this->outputStream : $this->lineDumper; + + if (\is_callable($output)) { + $this->outputStream = null; + $this->lineDumper = $output; + } else { + if (\is_string($output)) { + $output = fopen($output, 'wb'); + } + $this->outputStream = $output; + $this->lineDumper = [$this, 'echoLine']; + } + + return $prev; + } + + /** + * Sets the default character encoding to use for non-UTF8 strings. + * + * @return string The previous charset + */ + public function setCharset(string $charset) + { + $prev = $this->charset; + + $charset = strtoupper($charset); + $charset = null === $charset || 'UTF-8' === $charset || 'UTF8' === $charset ? 'CP1252' : $charset; + + $this->charset = $charset; + + return $prev; + } + + /** + * Sets the indentation pad string. + * + * @param string $pad A string that will be prepended to dumped lines, repeated by nesting level + * + * @return string The previous indent pad + */ + public function setIndentPad(string $pad) + { + $prev = $this->indentPad; + $this->indentPad = $pad; + + return $prev; + } + + /** + * Dumps a Data object. + * + * @param callable|resource|string|true|null $output A line dumper callable, an opened stream, an output path or true to return the dump + * + * @return string|null The dump as string when $output is true + */ + public function dump(Data $data, $output = null) + { + $this->decimalPoint = localeconv(); + $this->decimalPoint = $this->decimalPoint['decimal_point']; + + if ($locale = $this->flags & (self::DUMP_COMMA_SEPARATOR | self::DUMP_TRAILING_COMMA) ? setlocale(LC_NUMERIC, 0) : null) { + setlocale(LC_NUMERIC, 'C'); + } + + if ($returnDump = true === $output) { + $output = fopen('php://memory', 'r+b'); + } + if ($output) { + $prevOutput = $this->setOutput($output); + } + try { + $data->dump($this); + $this->dumpLine(-1); + + if ($returnDump) { + $result = stream_get_contents($output, -1, 0); + fclose($output); + + return $result; + } + } finally { + if ($output) { + $this->setOutput($prevOutput); + } + if ($locale) { + setlocale(LC_NUMERIC, $locale); + } + } + + return null; + } + + /** + * Dumps the current line. + * + * @param int $depth The recursive depth in the dumped structure for the line being dumped, + * or -1 to signal the end-of-dump to the line dumper callable + */ + protected function dumpLine(int $depth) + { + ($this->lineDumper)($this->line, $depth, $this->indentPad); + $this->line = ''; + } + + /** + * Generic line dumper callback. + */ + protected function echoLine(string $line, int $depth, string $indentPad) + { + if (-1 !== $depth) { + fwrite($this->outputStream, str_repeat($indentPad, $depth).$line."\n"); + } + } + + /** + * Converts a non-UTF-8 string to UTF-8. + * + * @return string|null The string converted to UTF-8 + */ + protected function utf8Encode(?string $s) + { + if (null === $s || preg_match('//u', $s)) { + return $s; + } + + if (!\function_exists('iconv')) { + throw new \RuntimeException('Unable to convert a non-UTF-8 string to UTF-8: required function iconv() does not exist. You should install ext-iconv or symfony/polyfill-iconv.'); + } + + if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) { + return $c; + } + if ('CP1252' !== $this->charset && false !== $c = @iconv('CP1252', 'UTF-8', $s)) { + return $c; + } + + return iconv('CP850', 'UTF-8', $s); + } +} diff --git a/vendor/symfony/var-dumper/Dumper/CliDumper.php b/vendor/symfony/var-dumper/Dumper/CliDumper.php new file mode 100644 index 0000000..326ce1d --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/CliDumper.php @@ -0,0 +1,636 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper; + +use Symfony\Component\VarDumper\Cloner\Cursor; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * CliDumper dumps variables for command line output. + * + * @author Nicolas Grekas + */ +class CliDumper extends AbstractDumper +{ + public static $defaultColors; + public static $defaultOutput = 'php://stdout'; + + protected $colors; + protected $maxStringWidth = 0; + protected $styles = [ + // See http://en.wikipedia.org/wiki/ANSI_escape_code#graphics + 'default' => '0;38;5;208', + 'num' => '1;38;5;38', + 'const' => '1;38;5;208', + 'str' => '1;38;5;113', + 'note' => '38;5;38', + 'ref' => '38;5;247', + 'public' => '', + 'protected' => '', + 'private' => '', + 'meta' => '38;5;170', + 'key' => '38;5;113', + 'index' => '38;5;38', + ]; + + protected static $controlCharsRx = '/[\x00-\x1F\x7F]+/'; + protected static $controlCharsMap = [ + "\t" => '\t', + "\n" => '\n', + "\v" => '\v', + "\f" => '\f', + "\r" => '\r', + "\033" => '\e', + ]; + + protected $collapseNextHash = false; + protected $expandNextHash = false; + + private $displayOptions = [ + 'fileLinkFormat' => null, + ]; + + private $handlesHrefGracefully; + + /** + * {@inheritdoc} + */ + public function __construct($output = null, string $charset = null, int $flags = 0) + { + parent::__construct($output, $charset, $flags); + + if ('\\' === \DIRECTORY_SEPARATOR && !$this->isWindowsTrueColor()) { + // Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI + $this->setStyles([ + 'default' => '31', + 'num' => '1;34', + 'const' => '1;31', + 'str' => '1;32', + 'note' => '34', + 'ref' => '1;30', + 'meta' => '35', + 'key' => '32', + 'index' => '34', + ]); + } + + $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l'; + } + + /** + * Enables/disables colored output. + */ + public function setColors(bool $colors) + { + $this->colors = $colors; + } + + /** + * Sets the maximum number of characters per line for dumped strings. + */ + public function setMaxStringWidth(int $maxStringWidth) + { + $this->maxStringWidth = $maxStringWidth; + } + + /** + * Configures styles. + * + * @param array $styles A map of style names to style definitions + */ + public function setStyles(array $styles) + { + $this->styles = $styles + $this->styles; + } + + /** + * Configures display options. + * + * @param array $displayOptions A map of display options to customize the behavior + */ + public function setDisplayOptions(array $displayOptions) + { + $this->displayOptions = $displayOptions + $this->displayOptions; + } + + /** + * {@inheritdoc} + */ + public function dumpScalar(Cursor $cursor, string $type, $value) + { + $this->dumpKey($cursor); + + $style = 'const'; + $attr = $cursor->attr; + + switch ($type) { + case 'default': + $style = 'default'; + break; + + case 'integer': + $style = 'num'; + break; + + case 'double': + $style = 'num'; + + switch (true) { + case INF === $value: $value = 'INF'; break; + case -INF === $value: $value = '-INF'; break; + case is_nan($value): $value = 'NAN'; break; + default: + $value = (string) $value; + if (false === strpos($value, $this->decimalPoint)) { + $value .= $this->decimalPoint.'0'; + } + break; + } + break; + + case 'NULL': + $value = 'null'; + break; + + case 'boolean': + $value = $value ? 'true' : 'false'; + break; + + default: + $attr += ['value' => $this->utf8Encode($value)]; + $value = $this->utf8Encode($type); + break; + } + + $this->line .= $this->style($style, $value, $attr); + + $this->endValue($cursor); + } + + /** + * {@inheritdoc} + */ + public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut) + { + $this->dumpKey($cursor); + $attr = $cursor->attr; + + if ($bin) { + $str = $this->utf8Encode($str); + } + if ('' === $str) { + $this->line .= '""'; + $this->endValue($cursor); + } else { + $attr += [ + 'length' => 0 <= $cut ? mb_strlen($str, 'UTF-8') + $cut : 0, + 'binary' => $bin, + ]; + $str = explode("\n", $str); + if (isset($str[1]) && !isset($str[2]) && !isset($str[1][0])) { + unset($str[1]); + $str[0] .= "\n"; + } + $m = \count($str) - 1; + $i = $lineCut = 0; + + if (self::DUMP_STRING_LENGTH & $this->flags) { + $this->line .= '('.$attr['length'].') '; + } + if ($bin) { + $this->line .= 'b'; + } + + if ($m) { + $this->line .= '"""'; + $this->dumpLine($cursor->depth); + } else { + $this->line .= '"'; + } + + foreach ($str as $str) { + if ($i < $m) { + $str .= "\n"; + } + if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = mb_strlen($str, 'UTF-8')) { + $str = mb_substr($str, 0, $this->maxStringWidth, 'UTF-8'); + $lineCut = $len - $this->maxStringWidth; + } + if ($m && 0 < $cursor->depth) { + $this->line .= $this->indentPad; + } + if ('' !== $str) { + $this->line .= $this->style('str', $str, $attr); + } + if ($i++ == $m) { + if ($m) { + if ('' !== $str) { + $this->dumpLine($cursor->depth); + if (0 < $cursor->depth) { + $this->line .= $this->indentPad; + } + } + $this->line .= '"""'; + } else { + $this->line .= '"'; + } + if ($cut < 0) { + $this->line .= '…'; + $lineCut = 0; + } elseif ($cut) { + $lineCut += $cut; + } + } + if ($lineCut) { + $this->line .= '…'.$lineCut; + $lineCut = 0; + } + + if ($i > $m) { + $this->endValue($cursor); + } else { + $this->dumpLine($cursor->depth); + } + } + } + } + + /** + * {@inheritdoc} + */ + public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild) + { + $this->dumpKey($cursor); + $attr = $cursor->attr; + + if ($this->collapseNextHash) { + $cursor->skipChildren = true; + $this->collapseNextHash = $hasChild = false; + } + + $class = $this->utf8Encode($class); + if (Cursor::HASH_OBJECT === $type) { + $prefix = $class && 'stdClass' !== $class ? $this->style('note', $class, $attr).(empty($attr['cut_hash']) ? ' {' : '') : '{'; + } elseif (Cursor::HASH_RESOURCE === $type) { + $prefix = $this->style('note', $class.' resource', $attr).($hasChild ? ' {' : ' '); + } else { + $prefix = $class && !(self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:'.$class, $attr).' [' : '['; + } + + if (($cursor->softRefCount || 0 < $cursor->softRefHandle) && empty($attr['cut_hash'])) { + $prefix .= $this->style('ref', (Cursor::HASH_RESOURCE === $type ? '@' : '#').(0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->softRefTo), ['count' => $cursor->softRefCount]); + } elseif ($cursor->hardRefTo && !$cursor->refIndex && $class) { + $prefix .= $this->style('ref', '&'.$cursor->hardRefTo, ['count' => $cursor->hardRefCount]); + } elseif (!$hasChild && Cursor::HASH_RESOURCE === $type) { + $prefix = substr($prefix, 0, -1); + } + + $this->line .= $prefix; + + if ($hasChild) { + $this->dumpLine($cursor->depth); + } + } + + /** + * {@inheritdoc} + */ + public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut) + { + if (empty($cursor->attr['cut_hash'])) { + $this->dumpEllipsis($cursor, $hasChild, $cut); + $this->line .= Cursor::HASH_OBJECT === $type ? '}' : (Cursor::HASH_RESOURCE !== $type ? ']' : ($hasChild ? '}' : '')); + } + + $this->endValue($cursor); + } + + /** + * Dumps an ellipsis for cut children. + * + * @param bool $hasChild When the dump of the hash has child item + * @param int $cut The number of items the hash has been cut by + */ + protected function dumpEllipsis(Cursor $cursor, $hasChild, $cut) + { + if ($cut) { + $this->line .= ' …'; + if (0 < $cut) { + $this->line .= $cut; + } + if ($hasChild) { + $this->dumpLine($cursor->depth + 1); + } + } + } + + /** + * Dumps a key in a hash structure. + */ + protected function dumpKey(Cursor $cursor) + { + if (null !== $key = $cursor->hashKey) { + if ($cursor->hashKeyIsBinary) { + $key = $this->utf8Encode($key); + } + $attr = ['binary' => $cursor->hashKeyIsBinary]; + $bin = $cursor->hashKeyIsBinary ? 'b' : ''; + $style = 'key'; + switch ($cursor->hashType) { + default: + case Cursor::HASH_INDEXED: + if (self::DUMP_LIGHT_ARRAY & $this->flags) { + break; + } + $style = 'index'; + // no break + case Cursor::HASH_ASSOC: + if (\is_int($key)) { + $this->line .= $this->style($style, $key).' => '; + } else { + $this->line .= $bin.'"'.$this->style($style, $key).'" => '; + } + break; + + case Cursor::HASH_RESOURCE: + $key = "\0~\0".$key; + // no break + case Cursor::HASH_OBJECT: + if (!isset($key[0]) || "\0" !== $key[0]) { + $this->line .= '+'.$bin.$this->style('public', $key).': '; + } elseif (0 < strpos($key, "\0", 1)) { + $key = explode("\0", substr($key, 1), 2); + + switch ($key[0][0]) { + case '+': // User inserted keys + $attr['dynamic'] = true; + $this->line .= '+'.$bin.'"'.$this->style('public', $key[1], $attr).'": '; + break 2; + case '~': + $style = 'meta'; + if (isset($key[0][1])) { + parse_str(substr($key[0], 1), $attr); + $attr += ['binary' => $cursor->hashKeyIsBinary]; + } + break; + case '*': + $style = 'protected'; + $bin = '#'.$bin; + break; + default: + $attr['class'] = $key[0]; + $style = 'private'; + $bin = '-'.$bin; + break; + } + + if (isset($attr['collapse'])) { + if ($attr['collapse']) { + $this->collapseNextHash = true; + } else { + $this->expandNextHash = true; + } + } + + $this->line .= $bin.$this->style($style, $key[1], $attr).(isset($attr['separator']) ? $attr['separator'] : ': '); + } else { + // This case should not happen + $this->line .= '-'.$bin.'"'.$this->style('private', $key, ['class' => '']).'": '; + } + break; + } + + if ($cursor->hardRefTo) { + $this->line .= $this->style('ref', '&'.($cursor->hardRefCount ? $cursor->hardRefTo : ''), ['count' => $cursor->hardRefCount]).' '; + } + } + } + + /** + * Decorates a value with some style. + * + * @param string $style The type of style being applied + * @param string $value The value being styled + * @param array $attr Optional context information + * + * @return string The value with style decoration + */ + protected function style($style, $value, $attr = []) + { + if (null === $this->colors) { + $this->colors = $this->supportsColors(); + } + + if (null === $this->handlesHrefGracefully) { + $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') && !getenv('KONSOLE_VERSION'); + } + + if (isset($attr['ellipsis'], $attr['ellipsis-type'])) { + $prefix = substr($value, 0, -$attr['ellipsis']); + if ('cli' === \PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\' === \DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && 0 === strpos($prefix, $_SERVER[$pwd])) { + $prefix = '.'.substr($prefix, \strlen($_SERVER[$pwd])); + } + if (!empty($attr['ellipsis-tail'])) { + $prefix .= substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']); + $value = substr($value, -$attr['ellipsis'] + $attr['ellipsis-tail']); + } else { + $value = substr($value, -$attr['ellipsis']); + } + + $value = $this->style('default', $prefix).$this->style($style, $value); + + goto href; + } + + $map = static::$controlCharsMap; + $startCchr = $this->colors ? "\033[m\033[{$this->styles['default']}m" : ''; + $endCchr = $this->colors ? "\033[m\033[{$this->styles[$style]}m" : ''; + $value = preg_replace_callback(static::$controlCharsRx, function ($c) use ($map, $startCchr, $endCchr) { + $s = $startCchr; + $c = $c[$i = 0]; + do { + $s .= isset($map[$c[$i]]) ? $map[$c[$i]] : sprintf('\x%02X', \ord($c[$i])); + } while (isset($c[++$i])); + + return $s.$endCchr; + }, $value, -1, $cchrCount); + + if ($this->colors) { + if ($cchrCount && "\033" === $value[0]) { + $value = substr($value, \strlen($startCchr)); + } else { + $value = "\033[{$this->styles[$style]}m".$value; + } + if ($cchrCount && $endCchr === substr($value, -\strlen($endCchr))) { + $value = substr($value, 0, -\strlen($endCchr)); + } else { + $value .= "\033[{$this->styles['default']}m"; + } + } + + href: + if ($this->colors && $this->handlesHrefGracefully) { + if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], isset($attr['line']) ? $attr['line'] : 0)) { + if ('note' === $style) { + $value .= "\033]8;;{$href}\033\\^\033]8;;\033\\"; + } else { + $attr['href'] = $href; + } + } + if (isset($attr['href'])) { + $value = "\033]8;;{$attr['href']}\033\\{$value}\033]8;;\033\\"; + } + } elseif ($attr['if_links'] ?? false) { + return ''; + } + + return $value; + } + + /** + * @return bool Tells if the current output stream supports ANSI colors or not + */ + protected function supportsColors() + { + if ($this->outputStream !== static::$defaultOutput) { + return $this->hasColorSupport($this->outputStream); + } + if (null !== static::$defaultColors) { + return static::$defaultColors; + } + if (isset($_SERVER['argv'][1])) { + $colors = $_SERVER['argv']; + $i = \count($colors); + while (--$i > 0) { + if (isset($colors[$i][5])) { + switch ($colors[$i]) { + case '--ansi': + case '--color': + case '--color=yes': + case '--color=force': + case '--color=always': + return static::$defaultColors = true; + + case '--no-ansi': + case '--color=no': + case '--color=none': + case '--color=never': + return static::$defaultColors = false; + } + } + } + } + + $h = stream_get_meta_data($this->outputStream) + ['wrapper_type' => null]; + $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'wb') : $this->outputStream; + + return static::$defaultColors = $this->hasColorSupport($h); + } + + /** + * {@inheritdoc} + */ + protected function dumpLine(int $depth, bool $endOfValue = false) + { + if ($this->colors) { + $this->line = sprintf("\033[%sm%s\033[m", $this->styles['default'], $this->line); + } + parent::dumpLine($depth); + } + + protected function endValue(Cursor $cursor) + { + if (-1 === $cursor->hashType) { + return; + } + + if (Stub::ARRAY_INDEXED === $cursor->hashType || Stub::ARRAY_ASSOC === $cursor->hashType) { + if (self::DUMP_TRAILING_COMMA & $this->flags && 0 < $cursor->depth) { + $this->line .= ','; + } elseif (self::DUMP_COMMA_SEPARATOR & $this->flags && 1 < $cursor->hashLength - $cursor->hashIndex) { + $this->line .= ','; + } + } + + $this->dumpLine($cursor->depth, true); + } + + /** + * Returns true if the stream supports colorization. + * + * Reference: Composer\XdebugHandler\Process::supportsColor + * https://github.com/composer/xdebug-handler + * + * @param mixed $stream A CLI output stream + */ + private function hasColorSupport($stream): bool + { + if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) { + return false; + } + + // Follow https://no-color.org/ + if (isset($_SERVER['NO_COLOR']) || false !== getenv('NO_COLOR')) { + return false; + } + + if ('Hyper' === getenv('TERM_PROGRAM')) { + return true; + } + + if (\DIRECTORY_SEPARATOR === '\\') { + return (\function_exists('sapi_windows_vt100_support') + && @sapi_windows_vt100_support($stream)) + || false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM'); + } + + return stream_isatty($stream); + } + + /** + * Returns true if the Windows terminal supports true color. + * + * Note that this does not check an output stream, but relies on environment + * variables from known implementations, or a PHP and Windows version that + * supports true color. + */ + private function isWindowsTrueColor(): bool + { + $result = 183 <= getenv('ANSICON_VER') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM') + || 'Hyper' === getenv('TERM_PROGRAM'); + + if (!$result) { + $version = sprintf( + '%s.%s.%s', + PHP_WINDOWS_VERSION_MAJOR, + PHP_WINDOWS_VERSION_MINOR, + PHP_WINDOWS_VERSION_BUILD + ); + $result = $version >= '10.0.15063'; + } + + return $result; + } + + private function getSourceLink(string $file, int $line) + { + if ($fmt = $this->displayOptions['fileLinkFormat']) { + return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : ($fmt->format($file, $line) ?: 'file://'.$file.'#L'.$line); + } + + return false; + } +} diff --git a/vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php b/vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php new file mode 100644 index 0000000..e7f8ccf --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper\ContextProvider; + +/** + * Tries to provide context on CLI. + * + * @author Maxime Steinhausser + */ +final class CliContextProvider implements ContextProviderInterface +{ + public function getContext(): ?array + { + if ('cli' !== \PHP_SAPI) { + return null; + } + + return [ + 'command_line' => $commandLine = implode(' ', $_SERVER['argv']), + 'identifier' => hash('crc32b', $commandLine.$_SERVER['REQUEST_TIME_FLOAT']), + ]; + } +} diff --git a/vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php b/vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php new file mode 100644 index 0000000..38ef3b0 --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper\ContextProvider; + +/** + * Interface to provide contextual data about dump data clones sent to a server. + * + * @author Maxime Steinhausser + */ +interface ContextProviderInterface +{ + /** + * @return array|null Context data or null if unable to provide any context + */ + public function getContext(): ?array; +} diff --git a/vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php b/vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php new file mode 100644 index 0000000..3684a47 --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper\ContextProvider; + +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\VarDumper\Caster\ReflectionCaster; +use Symfony\Component\VarDumper\Cloner\VarCloner; + +/** + * Tries to provide context from a request. + * + * @author Maxime Steinhausser + */ +final class RequestContextProvider implements ContextProviderInterface +{ + private $requestStack; + private $cloner; + + public function __construct(RequestStack $requestStack) + { + $this->requestStack = $requestStack; + $this->cloner = new VarCloner(); + $this->cloner->setMaxItems(0); + $this->cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO); + } + + public function getContext(): ?array + { + if (null === $request = $this->requestStack->getCurrentRequest()) { + return null; + } + + $controller = $request->attributes->get('_controller'); + + return [ + 'uri' => $request->getUri(), + 'method' => $request->getMethod(), + 'controller' => $controller ? $this->cloner->cloneVar($controller) : $controller, + 'identifier' => spl_object_hash($request), + ]; + } +} diff --git a/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php b/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php new file mode 100644 index 0000000..6f4caba --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper\ContextProvider; + +use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Dumper\HtmlDumper; +use Symfony\Component\VarDumper\VarDumper; +use Twig\Template; + +/** + * Tries to provide context from sources (class name, file, line, code excerpt, ...). + * + * @author Nicolas Grekas + * @author Maxime Steinhausser + */ +final class SourceContextProvider implements ContextProviderInterface +{ + private $limit; + private $charset; + private $projectDir; + private $fileLinkFormatter; + + public function __construct(string $charset = null, string $projectDir = null, FileLinkFormatter $fileLinkFormatter = null, int $limit = 9) + { + $this->charset = $charset; + $this->projectDir = $projectDir; + $this->fileLinkFormatter = $fileLinkFormatter; + $this->limit = $limit; + } + + public function getContext(): ?array + { + $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, $this->limit); + + $file = $trace[1]['file']; + $line = $trace[1]['line']; + $name = false; + $fileExcerpt = false; + + for ($i = 2; $i < $this->limit; ++$i) { + if (isset($trace[$i]['class'], $trace[$i]['function']) + && 'dump' === $trace[$i]['function'] + && VarDumper::class === $trace[$i]['class'] + ) { + $file = $trace[$i]['file'] ?? $file; + $line = $trace[$i]['line'] ?? $line; + + while (++$i < $this->limit) { + if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && 0 !== strpos($trace[$i]['function'], 'call_user_func')) { + $file = $trace[$i]['file']; + $line = $trace[$i]['line']; + + break; + } elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof Template) { + $template = $trace[$i]['object']; + $name = $template->getTemplateName(); + $src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : false); + $info = $template->getDebugInfo(); + if (isset($info[$trace[$i - 1]['line']])) { + $line = $info[$trace[$i - 1]['line']]; + $file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : null; + + if ($src) { + $src = explode("\n", $src); + $fileExcerpt = []; + + for ($i = max($line - 3, 1), $max = min($line + 3, \count($src)); $i <= $max; ++$i) { + $fileExcerpt[] = ''.$this->htmlEncode($src[$i - 1]).''; + } + + $fileExcerpt = '
      '.implode("\n", $fileExcerpt).'
    '; + } + } + break; + } + } + break; + } + } + + if (false === $name) { + $name = str_replace('\\', '/', $file); + $name = substr($name, strrpos($name, '/') + 1); + } + + $context = ['name' => $name, 'file' => $file, 'line' => $line]; + $context['file_excerpt'] = $fileExcerpt; + + if (null !== $this->projectDir) { + $context['project_dir'] = $this->projectDir; + if (0 === strpos($file, $this->projectDir)) { + $context['file_relative'] = ltrim(substr($file, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR); + } + } + + if ($this->fileLinkFormatter && $fileLink = $this->fileLinkFormatter->format($context['file'], $context['line'])) { + $context['file_link'] = $fileLink; + } + + return $context; + } + + private function htmlEncode(string $s): string + { + $html = ''; + + $dumper = new HtmlDumper(function ($line) use (&$html) { $html .= $line; }, $this->charset); + $dumper->setDumpHeader(''); + $dumper->setDumpBoundaries('', ''); + + $cloner = new VarCloner(); + $dumper->dump($cloner->cloneVar($s)); + + return substr(strip_tags($html), 1, -1); + } +} diff --git a/vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php b/vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php new file mode 100644 index 0000000..7638417 --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper; + +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; + +/** + * @author Kévin Thérage + */ +class ContextualizedDumper implements DataDumperInterface +{ + private $wrappedDumper; + private $contextProviders; + + /** + * @param ContextProviderInterface[] $contextProviders + */ + public function __construct(DataDumperInterface $wrappedDumper, array $contextProviders) + { + $this->wrappedDumper = $wrappedDumper; + $this->contextProviders = $contextProviders; + } + + public function dump(Data $data) + { + $context = []; + foreach ($this->contextProviders as $contextProvider) { + $context[\get_class($contextProvider)] = $contextProvider->getContext(); + } + + $this->wrappedDumper->dump($data->withContext($context)); + } +} diff --git a/vendor/symfony/var-dumper/Dumper/DataDumperInterface.php b/vendor/symfony/var-dumper/Dumper/DataDumperInterface.php new file mode 100644 index 0000000..b173bcc --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/DataDumperInterface.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper; + +use Symfony\Component\VarDumper\Cloner\Data; + +/** + * DataDumperInterface for dumping Data objects. + * + * @author Nicolas Grekas + */ +interface DataDumperInterface +{ + public function dump(Data $data); +} diff --git a/vendor/symfony/var-dumper/Dumper/HtmlDumper.php b/vendor/symfony/var-dumper/Dumper/HtmlDumper.php new file mode 100644 index 0000000..d89fecf --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/HtmlDumper.php @@ -0,0 +1,1004 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper; + +use Symfony\Component\VarDumper\Cloner\Cursor; +use Symfony\Component\VarDumper\Cloner\Data; + +/** + * HtmlDumper dumps variables as HTML. + * + * @author Nicolas Grekas + */ +class HtmlDumper extends CliDumper +{ + public static $defaultOutput = 'php://output'; + + protected static $themes = [ + 'dark' => [ + 'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', + 'num' => 'font-weight:bold; color:#1299DA', + 'const' => 'font-weight:bold', + 'str' => 'font-weight:bold; color:#56DB3A', + 'note' => 'color:#1299DA', + 'ref' => 'color:#A0A0A0', + 'public' => 'color:#FFFFFF', + 'protected' => 'color:#FFFFFF', + 'private' => 'color:#FFFFFF', + 'meta' => 'color:#B729D9', + 'key' => 'color:#56DB3A', + 'index' => 'color:#1299DA', + 'ellipsis' => 'color:#FF8400', + 'ns' => 'user-select:none;', + ], + 'light' => [ + 'default' => 'background:none; color:#CC7832; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', + 'num' => 'font-weight:bold; color:#1299DA', + 'const' => 'font-weight:bold', + 'str' => 'font-weight:bold; color:#629755;', + 'note' => 'color:#6897BB', + 'ref' => 'color:#6E6E6E', + 'public' => 'color:#262626', + 'protected' => 'color:#262626', + 'private' => 'color:#262626', + 'meta' => 'color:#B729D9', + 'key' => 'color:#789339', + 'index' => 'color:#1299DA', + 'ellipsis' => 'color:#CC7832', + 'ns' => 'user-select:none;', + ], + ]; + + protected $dumpHeader; + protected $dumpPrefix = '
    ';
    +    protected $dumpSuffix = '
    '; + protected $dumpId = 'sf-dump'; + protected $colors = true; + protected $headerIsDumped = false; + protected $lastDepth = -1; + protected $styles; + + private $displayOptions = [ + 'maxDepth' => 1, + 'maxStringLength' => 160, + 'fileLinkFormat' => null, + ]; + private $extraDisplayOptions = []; + + /** + * {@inheritdoc} + */ + public function __construct($output = null, string $charset = null, int $flags = 0) + { + AbstractDumper::__construct($output, $charset, $flags); + $this->dumpId = 'sf-dump-'.mt_rand(); + $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + $this->styles = static::$themes['dark'] ?? self::$themes['dark']; + } + + /** + * {@inheritdoc} + */ + public function setStyles(array $styles) + { + $this->headerIsDumped = false; + $this->styles = $styles + $this->styles; + } + + public function setTheme(string $themeName) + { + if (!isset(static::$themes[$themeName])) { + throw new \InvalidArgumentException(sprintf('Theme "%s" does not exist in class "%s".', $themeName, static::class)); + } + + $this->setStyles(static::$themes[$themeName]); + } + + /** + * Configures display options. + * + * @param array $displayOptions A map of display options to customize the behavior + */ + public function setDisplayOptions(array $displayOptions) + { + $this->headerIsDumped = false; + $this->displayOptions = $displayOptions + $this->displayOptions; + } + + /** + * Sets an HTML header that will be dumped once in the output stream. + * + * @param string $header An HTML string + */ + public function setDumpHeader($header) + { + $this->dumpHeader = $header; + } + + /** + * Sets an HTML prefix and suffix that will encapse every single dump. + * + * @param string $prefix The prepended HTML string + * @param string $suffix The appended HTML string + */ + public function setDumpBoundaries($prefix, $suffix) + { + $this->dumpPrefix = $prefix; + $this->dumpSuffix = $suffix; + } + + /** + * {@inheritdoc} + */ + public function dump(Data $data, $output = null, array $extraDisplayOptions = []) + { + $this->extraDisplayOptions = $extraDisplayOptions; + $result = parent::dump($data, $output); + $this->dumpId = 'sf-dump-'.mt_rand(); + + return $result; + } + + /** + * Dumps the HTML header. + */ + protected function getDumpHeader() + { + $this->headerIsDumped = null !== $this->outputStream ? $this->outputStream : $this->lineDumper; + + if (null !== $this->dumpHeader) { + return $this->dumpHeader; + } + + $line = str_replace('{$options}', json_encode($this->displayOptions, JSON_FORCE_OBJECT), <<<'EOHTML' +'.$this->dumpHeader; + } + + /** + * {@inheritdoc} + */ + public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut) + { + if ('' === $str && isset($cursor->attr['img-data'], $cursor->attr['content-type'])) { + $this->dumpKey($cursor); + $this->line .= $this->style('default', $cursor->attr['img-size'] ?? '', []).' '; + $this->endValue($cursor); + $this->line .= $this->indentPad; + $this->line .= sprintf('', $cursor->attr['content-type'], base64_encode($cursor->attr['img-data'])); + $this->endValue($cursor); + } else { + parent::dumpString($cursor, $str, $bin, $cut); + } + } + + /** + * {@inheritdoc} + */ + public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild) + { + if (Cursor::HASH_OBJECT === $type) { + $cursor->attr['depth'] = $cursor->depth; + } + parent::enterHash($cursor, $type, $class, false); + + if ($cursor->skipChildren) { + $cursor->skipChildren = false; + $eol = ' class=sf-dump-compact>'; + } elseif ($this->expandNextHash) { + $this->expandNextHash = false; + $eol = ' class=sf-dump-expanded>'; + } else { + $eol = '>'; + } + + if ($hasChild) { + $this->line .= 'refIndex) { + $r = Cursor::HASH_OBJECT !== $type ? 1 - (Cursor::HASH_RESOURCE !== $type) : 2; + $r .= $r && 0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->refIndex; + + $this->line .= sprintf(' id=%s-ref%s', $this->dumpId, $r); + } + $this->line .= $eol; + $this->dumpLine($cursor->depth); + } + } + + /** + * {@inheritdoc} + */ + public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut) + { + $this->dumpEllipsis($cursor, $hasChild, $cut); + if ($hasChild) { + $this->line .= ''; + } + parent::leaveHash($cursor, $type, $class, $hasChild, 0); + } + + /** + * {@inheritdoc} + */ + protected function style($style, $value, $attr = []) + { + if ('' === $value) { + return ''; + } + + $v = esc($value); + + if ('ref' === $style) { + if (empty($attr['count'])) { + return sprintf('%s', $v); + } + $r = ('#' !== $v[0] ? 1 - ('@' !== $v[0]) : 2).substr($value, 1); + + return sprintf('%s', $this->dumpId, $r, 1 + $attr['count'], $v); + } + + if ('const' === $style && isset($attr['value'])) { + $style .= sprintf(' title="%s"', esc(is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value']))); + } elseif ('public' === $style) { + $style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property'); + } elseif ('str' === $style && 1 < $attr['length']) { + $style .= sprintf(' title="%d%s characters"', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : ''); + } elseif ('note' === $style && 0 < ($attr['depth'] ?? 0) && false !== $c = strrpos($value, '\\')) { + $style .= ' title=""'; + $attr += [ + 'ellipsis' => \strlen($value) - $c, + 'ellipsis-type' => 'note', + 'ellipsis-tail' => 1, + ]; + } elseif ('protected' === $style) { + $style .= ' title="Protected property"'; + } elseif ('meta' === $style && isset($attr['title'])) { + $style .= sprintf(' title="%s"', esc($this->utf8Encode($attr['title']))); + } elseif ('private' === $style) { + $style .= sprintf(' title="Private property defined in class: `%s`"', esc($this->utf8Encode($attr['class']))); + } + $map = static::$controlCharsMap; + + if (isset($attr['ellipsis'])) { + $class = 'sf-dump-ellipsis'; + if (isset($attr['ellipsis-type'])) { + $class = sprintf('"%s sf-dump-ellipsis-%s"', $class, $attr['ellipsis-type']); + } + $label = esc(substr($value, -$attr['ellipsis'])); + $style = str_replace(' title="', " title=\"$v\n", $style); + $v = sprintf('%s', $class, substr($v, 0, -\strlen($label))); + + if (!empty($attr['ellipsis-tail'])) { + $tail = \strlen(esc(substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']))); + $v .= sprintf('%s%s', $class, substr($label, 0, $tail), substr($label, $tail)); + } else { + $v .= $label; + } + } + + $v = "".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) { + $s = $b = ''; + }, $v).''; + + if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], isset($attr['line']) ? $attr['line'] : 0)) { + $attr['href'] = $href; + } + if (isset($attr['href'])) { + $target = isset($attr['file']) ? '' : ' target="_blank"'; + $v = sprintf('%s', esc($this->utf8Encode($attr['href'])), $target, $v); + } + if (isset($attr['lang'])) { + $v = sprintf('%s', esc($attr['lang']), $v); + } + + return $v; + } + + /** + * {@inheritdoc} + */ + protected function dumpLine(int $depth, bool $endOfValue = false) + { + if (-1 === $this->lastDepth) { + $this->line = sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad).$this->line; + } + if ($this->headerIsDumped !== (null !== $this->outputStream ? $this->outputStream : $this->lineDumper)) { + $this->line = $this->getDumpHeader().$this->line; + } + + if (-1 === $depth) { + $args = ['"'.$this->dumpId.'"']; + if ($this->extraDisplayOptions) { + $args[] = json_encode($this->extraDisplayOptions, JSON_FORCE_OBJECT); + } + // Replace is for BC + $this->line .= sprintf(str_replace('"%s"', '%s', $this->dumpSuffix), implode(', ', $args)); + } + $this->lastDepth = $depth; + + $this->line = mb_convert_encoding($this->line, 'HTML-ENTITIES', 'UTF-8'); + + if (-1 === $depth) { + AbstractDumper::dumpLine(0); + } + AbstractDumper::dumpLine($depth); + } + + private function getSourceLink(string $file, int $line) + { + $options = $this->extraDisplayOptions + $this->displayOptions; + + if ($fmt = $options['fileLinkFormat']) { + return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line); + } + + return false; + } +} + +function esc($str) +{ + return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); +} diff --git a/vendor/symfony/var-dumper/Dumper/ServerDumper.php b/vendor/symfony/var-dumper/Dumper/ServerDumper.php new file mode 100644 index 0000000..94795bf --- /dev/null +++ b/vendor/symfony/var-dumper/Dumper/ServerDumper.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Dumper; + +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; +use Symfony\Component\VarDumper\Server\Connection; + +/** + * ServerDumper forwards serialized Data clones to a server. + * + * @author Maxime Steinhausser + */ +class ServerDumper implements DataDumperInterface +{ + private $connection; + private $wrappedDumper; + + /** + * @param string $host The server host + * @param DataDumperInterface|null $wrappedDumper A wrapped instance used whenever we failed contacting the server + * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name + */ + public function __construct(string $host, DataDumperInterface $wrappedDumper = null, array $contextProviders = []) + { + $this->connection = new Connection($host, $contextProviders); + $this->wrappedDumper = $wrappedDumper; + } + + public function getContextProviders(): array + { + return $this->connection->getContextProviders(); + } + + /** + * {@inheritdoc} + */ + public function dump(Data $data) + { + if (!$this->connection->write($data) && $this->wrappedDumper) { + $this->wrappedDumper->dump($data); + } + } +} diff --git a/vendor/symfony/var-dumper/Exception/ThrowingCasterException.php b/vendor/symfony/var-dumper/Exception/ThrowingCasterException.php new file mode 100644 index 0000000..122f0d3 --- /dev/null +++ b/vendor/symfony/var-dumper/Exception/ThrowingCasterException.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Exception; + +/** + * @author Nicolas Grekas + */ +class ThrowingCasterException extends \Exception +{ + /** + * @param \Throwable $prev The exception thrown from the caster + */ + public function __construct(\Throwable $prev) + { + parent::__construct('Unexpected '.\get_class($prev).' thrown from a caster: '.$prev->getMessage(), 0, $prev); + } +} diff --git a/vendor/symfony/var-dumper/LICENSE b/vendor/symfony/var-dumper/LICENSE new file mode 100644 index 0000000..cf8b3eb --- /dev/null +++ b/vendor/symfony/var-dumper/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/var-dumper/README.md b/vendor/symfony/var-dumper/README.md new file mode 100644 index 0000000..339f73e --- /dev/null +++ b/vendor/symfony/var-dumper/README.md @@ -0,0 +1,15 @@ +VarDumper Component +=================== + +The VarDumper component provides mechanisms for walking through any arbitrary +PHP variable. It provides a better `dump()` function that you can use instead +of `var_dump`. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/var_dumper/introduction.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/var-dumper/Resources/bin/var-dump-server b/vendor/symfony/var-dumper/Resources/bin/var-dump-server new file mode 100755 index 0000000..98c813a --- /dev/null +++ b/vendor/symfony/var-dumper/Resources/bin/var-dump-server @@ -0,0 +1,63 @@ +#!/usr/bin/env php + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Starts a dump server to collect and output dumps on a single place with multiple formats support. + * + * @author Maxime Steinhausser + */ + +use Psr\Log\LoggerInterface; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Logger\ConsoleLogger; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\VarDumper\Command\ServerDumpCommand; +use Symfony\Component\VarDumper\Server\DumpServer; + +function includeIfExists(string $file): bool +{ + return file_exists($file) && include $file; +} + +if ( + !includeIfExists(__DIR__ . '/../../../../autoload.php') && + !includeIfExists(__DIR__ . '/../../vendor/autoload.php') && + !includeIfExists(__DIR__ . '/../../../../../../vendor/autoload.php') +) { + fwrite(STDERR, 'Install dependencies using Composer.'.PHP_EOL); + exit(1); +} + +if (!class_exists(Application::class)) { + fwrite(STDERR, 'You need the "symfony/console" component in order to run the VarDumper server.'.PHP_EOL); + exit(1); +} + +$input = new ArgvInput(); +$output = new ConsoleOutput(); +$defaultHost = '127.0.0.1:9912'; +$host = $input->getParameterOption(['--host'], $_SERVER['VAR_DUMPER_SERVER'] ?? $defaultHost, true); +$logger = interface_exists(LoggerInterface::class) ? new ConsoleLogger($output->getErrorOutput()) : null; + +$app = new Application(); + +$app->getDefinition()->addOption( + new InputOption('--host', null, InputOption::VALUE_REQUIRED, 'The address the server should listen to', $defaultHost) +); + +$app->add($command = new ServerDumpCommand(new DumpServer($host, $logger))) + ->getApplication() + ->setDefaultCommand($command->getName(), true) + ->run($input, $output) +; diff --git a/vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css b/vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css new file mode 100644 index 0000000..8f706d6 --- /dev/null +++ b/vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css @@ -0,0 +1,130 @@ +body { + display: flex; + flex-direction: column-reverse; + justify-content: flex-end; + max-width: 1140px; + margin: auto; + padding: 15px; + word-wrap: break-word; + background-color: #F9F9F9; + color: #222; + font-family: Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.4; +} +p { + margin: 0; +} +a { + color: #218BC3; + text-decoration: none; +} +a:hover { + text-decoration: underline; +} +.text-small { + font-size: 12px !important; +} +article { + margin: 5px; + margin-bottom: 10px; +} +article > header > .row { + display: flex; + flex-direction: row; + align-items: baseline; + margin-bottom: 10px; +} +article > header > .row > .col { + flex: 1; + display: flex; + align-items: baseline; +} +article > header > .row > h2 { + font-size: 14px; + color: #222; + font-weight: normal; + font-family: "Lucida Console", monospace, sans-serif; + word-break: break-all; + margin: 20px 5px 0 0; + user-select: all; +} +article > header > .row > h2 > code { + white-space: nowrap; + user-select: none; + color: #cc2255; + background-color: #f7f7f9; + border: 1px solid #e1e1e8; + border-radius: 3px; + margin-right: 5px; + padding: 0 3px; +} +article > header > .row > time.col { + flex: 0; + text-align: right; + white-space: nowrap; + color: #999; + font-style: italic; +} +article > header ul.tags { + list-style: none; + padding: 0; + margin: 0; + font-size: 12px; +} +article > header ul.tags > li { + user-select: all; + margin-bottom: 2px; +} +article > header ul.tags > li > span.badge { + display: inline-block; + padding: .25em .4em; + margin-right: 5px; + border-radius: 4px; + background-color: #6c757d3b; + color: #524d4d; + font-size: 12px; + text-align: center; + font-weight: 700; + line-height: 1; + white-space: nowrap; + vertical-align: baseline; + user-select: none; +} +article > section.body { + border: 1px solid #d8d8d8; + background: #FFF; + padding: 10px; + border-radius: 3px; +} +pre.sf-dump { + border-radius: 3px; + margin-bottom: 0; +} +.hidden { + display: none !important; +} +.dumped-tag > .sf-dump { + display: inline-block; + margin: 0; + padding: 1px 5px; + line-height: 1.4; + vertical-align: top; + background-color: transparent; + user-select: auto; +} +.dumped-tag > pre.sf-dump, +.dumped-tag > .sf-dump-default { + color: #CC7832; + background: none; +} +.dumped-tag > .sf-dump .sf-dump-str { color: #629755; } +.dumped-tag > .sf-dump .sf-dump-private, +.dumped-tag > .sf-dump .sf-dump-protected, +.dumped-tag > .sf-dump .sf-dump-public { color: #262626; } +.dumped-tag > .sf-dump .sf-dump-note { color: #6897BB; } +.dumped-tag > .sf-dump .sf-dump-key { color: #789339; } +.dumped-tag > .sf-dump .sf-dump-ref { color: #6E6E6E; } +.dumped-tag > .sf-dump .sf-dump-ellipsis { color: #CC7832; max-width: 100em; } +.dumped-tag > .sf-dump .sf-dump-ellipsis-path { max-width: 5em; } +.dumped-tag > .sf-dump .sf-dump-ns { user-select: none; } diff --git a/vendor/symfony/var-dumper/Resources/functions/dump.php b/vendor/symfony/var-dumper/Resources/functions/dump.php new file mode 100644 index 0000000..e1543a8 --- /dev/null +++ b/vendor/symfony/var-dumper/Resources/functions/dump.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Component\VarDumper\VarDumper; + +if (!function_exists('dump')) { + /** + * @author Nicolas Grekas + */ + function dump($var, ...$moreVars) + { + VarDumper::dump($var); + + foreach ($moreVars as $v) { + VarDumper::dump($v); + } + + if (1 < func_num_args()) { + return func_get_args(); + } + + return $var; + } +} + +if (!function_exists('dd')) { + function dd(...$vars) + { + foreach ($vars as $v) { + VarDumper::dump($v); + } + + die(1); + } +} diff --git a/vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js b/vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js new file mode 100644 index 0000000..63101e5 --- /dev/null +++ b/vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js @@ -0,0 +1,10 @@ +document.addEventListener('DOMContentLoaded', function() { + let prev = null; + Array.from(document.getElementsByTagName('article')).reverse().forEach(function (article) { + const dedupId = article.dataset.dedupId; + if (dedupId === prev) { + article.getElementsByTagName('header')[0].classList.add('hidden'); + } + prev = dedupId; + }); +}); diff --git a/vendor/symfony/var-dumper/Server/Connection.php b/vendor/symfony/var-dumper/Server/Connection.php new file mode 100644 index 0000000..8b814cb --- /dev/null +++ b/vendor/symfony/var-dumper/Server/Connection.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Server; + +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; + +/** + * Forwards serialized Data clones to a server. + * + * @author Maxime Steinhausser + */ +class Connection +{ + private $host; + private $contextProviders; + private $socket; + + /** + * @param string $host The server host + * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name + */ + public function __construct(string $host, array $contextProviders = []) + { + if (false === strpos($host, '://')) { + $host = 'tcp://'.$host; + } + + $this->host = $host; + $this->contextProviders = $contextProviders; + } + + public function getContextProviders(): array + { + return $this->contextProviders; + } + + public function write(Data $data): bool + { + $socketIsFresh = !$this->socket; + if (!$this->socket = $this->socket ?: $this->createSocket()) { + return false; + } + + $context = ['timestamp' => microtime(true)]; + foreach ($this->contextProviders as $name => $provider) { + $context[$name] = $provider->getContext(); + } + $context = array_filter($context); + $encodedPayload = base64_encode(serialize([$data, $context]))."\n"; + + set_error_handler([self::class, 'nullErrorHandler']); + try { + if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) { + return true; + } + if (!$socketIsFresh) { + stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR); + fclose($this->socket); + $this->socket = $this->createSocket(); + } + if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) { + return true; + } + } finally { + restore_error_handler(); + } + + return false; + } + + private static function nullErrorHandler($t, $m) + { + // no-op + } + + private function createSocket() + { + set_error_handler([self::class, 'nullErrorHandler']); + try { + return stream_socket_client($this->host, $errno, $errstr, 3, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT); + } finally { + restore_error_handler(); + } + } +} diff --git a/vendor/symfony/var-dumper/Server/DumpServer.php b/vendor/symfony/var-dumper/Server/DumpServer.php new file mode 100644 index 0000000..ad920bd --- /dev/null +++ b/vendor/symfony/var-dumper/Server/DumpServer.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Server; + +use Psr\Log\LoggerInterface; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * A server collecting Data clones sent by a ServerDumper. + * + * @author Maxime Steinhausser + * + * @final + */ +class DumpServer +{ + private $host; + private $socket; + private $logger; + + public function __construct(string $host, LoggerInterface $logger = null) + { + if (false === strpos($host, '://')) { + $host = 'tcp://'.$host; + } + + $this->host = $host; + $this->logger = $logger; + } + + public function start(): void + { + if (!$this->socket = stream_socket_server($this->host, $errno, $errstr)) { + throw new \RuntimeException(sprintf('Server start failed on "%s": %s %s.', $this->host, $errstr, $errno)); + } + } + + public function listen(callable $callback): void + { + if (null === $this->socket) { + $this->start(); + } + + foreach ($this->getMessages() as $clientId => $message) { + $payload = @unserialize(base64_decode($message), ['allowed_classes' => [Data::class, Stub::class]]); + + // Impossible to decode the message, give up. + if (false === $payload) { + if ($this->logger) { + $this->logger->warning('Unable to decode a message from {clientId} client.', ['clientId' => $clientId]); + } + + continue; + } + + if (!\is_array($payload) || \count($payload) < 2 || !$payload[0] instanceof Data || !\is_array($payload[1])) { + if ($this->logger) { + $this->logger->warning('Invalid payload from {clientId} client. Expected an array of two elements (Data $data, array $context)', ['clientId' => $clientId]); + } + + continue; + } + + list($data, $context) = $payload; + + $callback($data, $context, $clientId); + } + } + + public function getHost(): string + { + return $this->host; + } + + private function getMessages(): iterable + { + $sockets = [(int) $this->socket => $this->socket]; + $write = []; + + while (true) { + $read = $sockets; + stream_select($read, $write, $write, null); + + foreach ($read as $stream) { + if ($this->socket === $stream) { + $stream = stream_socket_accept($this->socket); + $sockets[(int) $stream] = $stream; + } elseif (feof($stream)) { + unset($sockets[(int) $stream]); + fclose($stream); + } else { + yield (int) $stream => fgets($stream); + } + } + } + } +} diff --git a/vendor/symfony/var-dumper/Test/VarDumperTestTrait.php b/vendor/symfony/var-dumper/Test/VarDumperTestTrait.php new file mode 100644 index 0000000..258419c --- /dev/null +++ b/vendor/symfony/var-dumper/Test/VarDumperTestTrait.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Test; + +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Dumper\CliDumper; + +/** + * @author Nicolas Grekas + */ +trait VarDumperTestTrait +{ + /** + * @internal + */ + private $varDumperConfig = [ + 'casters' => [], + 'flags' => null, + ]; + + protected function setUpVarDumper(array $casters, int $flags = null): void + { + $this->varDumperConfig['casters'] = $casters; + $this->varDumperConfig['flags'] = $flags; + } + + /** + * @after + */ + protected function tearDownVarDumper(): void + { + $this->varDumperConfig['casters'] = []; + $this->varDumperConfig['flags'] = null; + } + + public function assertDumpEquals($expected, $data, int $filter = 0, string $message = '') + { + $this->assertSame($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message); + } + + public function assertDumpMatchesFormat($expected, $data, int $filter = 0, string $message = '') + { + $this->assertStringMatchesFormat($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message); + } + + /** + * @return string|null + */ + protected function getDump($data, $key = null, int $filter = 0): ?string + { + if (null === $flags = $this->varDumperConfig['flags']) { + $flags = getenv('DUMP_LIGHT_ARRAY') ? CliDumper::DUMP_LIGHT_ARRAY : 0; + $flags |= getenv('DUMP_STRING_LENGTH') ? CliDumper::DUMP_STRING_LENGTH : 0; + $flags |= getenv('DUMP_COMMA_SEPARATOR') ? CliDumper::DUMP_COMMA_SEPARATOR : 0; + } + + $cloner = new VarCloner(); + $cloner->addCasters($this->varDumperConfig['casters']); + $cloner->setMaxItems(-1); + $dumper = new CliDumper(null, null, $flags); + $dumper->setColors(false); + $data = $cloner->cloneVar($data, $filter)->withRefHandles(false); + if (null !== $key && null === $data = $data->seek($key)) { + return null; + } + + return rtrim($dumper->dump($data, true)); + } + + private function prepareExpectation($expected, int $filter): string + { + if (!\is_string($expected)) { + $expected = $this->getDump($expected, null, $filter); + } + + return rtrim($expected); + } +} diff --git a/vendor/symfony/var-dumper/VarDumper.php b/vendor/symfony/var-dumper/VarDumper.php new file mode 100644 index 0000000..d336d5d --- /dev/null +++ b/vendor/symfony/var-dumper/VarDumper.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper; + +use Symfony\Component\VarDumper\Caster\ReflectionCaster; +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Dumper\CliDumper; +use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; +use Symfony\Component\VarDumper\Dumper\ContextualizedDumper; +use Symfony\Component\VarDumper\Dumper\HtmlDumper; + +// Load the global dump() function +require_once __DIR__.'/Resources/functions/dump.php'; + +/** + * @author Nicolas Grekas + */ +class VarDumper +{ + private static $handler; + + public static function dump($var) + { + if (null === self::$handler) { + $cloner = new VarCloner(); + $cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO); + + if (isset($_SERVER['VAR_DUMPER_FORMAT'])) { + $dumper = 'html' === $_SERVER['VAR_DUMPER_FORMAT'] ? new HtmlDumper() : new CliDumper(); + } else { + $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg']) ? new CliDumper() : new HtmlDumper(); + } + + $dumper = new ContextualizedDumper($dumper, [new SourceContextProvider()]); + + self::$handler = function ($var) use ($cloner, $dumper) { + $dumper->dump($cloner->cloneVar($var)); + }; + } + + return (self::$handler)($var); + } + + public static function setHandler(callable $callable = null) + { + $prevHandler = self::$handler; + self::$handler = $callable; + + return $prevHandler; + } +} diff --git a/vendor/symfony/var-dumper/composer.json b/vendor/symfony/var-dumper/composer.json new file mode 100644 index 0000000..c7e668c --- /dev/null +++ b/vendor/symfony/var-dumper/composer.json @@ -0,0 +1,53 @@ +{ + "name": "symfony/var-dumper", + "type": "library", + "description": "Symfony mechanism for exploring and dumping PHP variables", + "keywords": ["dump", "debug"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^4.4|^5.0", + "symfony/process": "^4.4|^5.0", + "twig/twig": "^2.4|^3.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<4.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + }, + "autoload": { + "files": [ "Resources/functions/dump.php" ], + "psr-4": { "Symfony\\Component\\VarDumper\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} diff --git a/vendor/symfony/var-exporter/.gitattributes b/vendor/symfony/var-exporter/.gitattributes new file mode 100644 index 0000000..ebb9287 --- /dev/null +++ b/vendor/symfony/var-exporter/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.gitignore export-ignore diff --git a/vendor/symfony/var-exporter/CHANGELOG.md b/vendor/symfony/var-exporter/CHANGELOG.md new file mode 100644 index 0000000..9aa4a8b --- /dev/null +++ b/vendor/symfony/var-exporter/CHANGELOG.md @@ -0,0 +1,7 @@ +CHANGELOG +========= + +4.2.0 +----- + + * added the component diff --git a/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php b/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php new file mode 100644 index 0000000..4cebe44 --- /dev/null +++ b/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Exception; + +class ClassNotFoundException extends \Exception implements ExceptionInterface +{ + public function __construct(string $class, \Throwable $previous = null) + { + parent::__construct(sprintf('Class "%s" not found.', $class), 0, $previous); + } +} diff --git a/vendor/symfony/var-exporter/Exception/ExceptionInterface.php b/vendor/symfony/var-exporter/Exception/ExceptionInterface.php new file mode 100644 index 0000000..adfaed4 --- /dev/null +++ b/vendor/symfony/var-exporter/Exception/ExceptionInterface.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Exception; + +interface ExceptionInterface extends \Throwable +{ +} diff --git a/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php b/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php new file mode 100644 index 0000000..7ca4884 --- /dev/null +++ b/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Exception; + +class NotInstantiableTypeException extends \Exception implements ExceptionInterface +{ + public function __construct(string $type) + { + parent::__construct(sprintf('Type "%s" is not instantiable.', $type)); + } +} diff --git a/vendor/symfony/var-exporter/Instantiator.php b/vendor/symfony/var-exporter/Instantiator.php new file mode 100644 index 0000000..9fd8cf3 --- /dev/null +++ b/vendor/symfony/var-exporter/Instantiator.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter; + +use Symfony\Component\VarExporter\Exception\ExceptionInterface; +use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; +use Symfony\Component\VarExporter\Internal\Hydrator; +use Symfony\Component\VarExporter\Internal\Registry; + +/** + * A utility class to create objects without calling their constructor. + * + * @author Nicolas Grekas + */ +final class Instantiator +{ + /** + * Creates an object and sets its properties without calling its constructor nor any other methods. + * + * For example: + * + * // creates an empty instance of Foo + * Instantiator::instantiate(Foo::class); + * + * // creates a Foo instance and sets one of its properties + * Instantiator::instantiate(Foo::class, ['propertyName' => $propertyValue]); + * + * // creates a Foo instance and sets a private property defined on its parent Bar class + * Instantiator::instantiate(Foo::class, [], [ + * Bar::class => ['privateBarProperty' => $propertyValue], + * ]); + * + * Instances of ArrayObject, ArrayIterator and SplObjectHash can be created + * by using the special "\0" property name to define their internal value: + * + * // creates an SplObjectHash where $info1 is attached to $obj1, etc. + * Instantiator::instantiate(SplObjectStorage::class, ["\0" => [$obj1, $info1, $obj2, $info2...]]); + * + * // creates an ArrayObject populated with $inputArray + * Instantiator::instantiate(ArrayObject::class, ["\0" => [$inputArray]]); + * + * @param string $class The class of the instance to create + * @param array $properties The properties to set on the instance + * @param array $privateProperties The private properties to set on the instance, + * keyed by their declaring class + * + * @return object The created instance + * + * @throws ExceptionInterface When the instance cannot be created + */ + public static function instantiate(string $class, array $properties = [], array $privateProperties = []): object + { + $reflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class); + + if (Registry::$cloneable[$class]) { + $wrappedInstance = [clone Registry::$prototypes[$class]]; + } elseif (Registry::$instantiableWithoutConstructor[$class]) { + $wrappedInstance = [$reflector->newInstanceWithoutConstructor()]; + } elseif (null === Registry::$prototypes[$class]) { + throw new NotInstantiableTypeException($class); + } elseif ($reflector->implementsInterface('Serializable') && (\PHP_VERSION_ID < 70400 || !method_exists($class, '__unserialize'))) { + $wrappedInstance = [unserialize('C:'.\strlen($class).':"'.$class.'":0:{}')]; + } else { + $wrappedInstance = [unserialize('O:'.\strlen($class).':"'.$class.'":0:{}')]; + } + + if ($properties) { + $privateProperties[$class] = isset($privateProperties[$class]) ? $properties + $privateProperties[$class] : $properties; + } + + foreach ($privateProperties as $class => $properties) { + if (!$properties) { + continue; + } + foreach ($properties as $name => $value) { + // because they're also used for "unserialization", hydrators + // deal with array of instances, so we need to wrap values + $properties[$name] = [$value]; + } + (Hydrator::$hydrators[$class] ?? Hydrator::getHydrator($class))($properties, $wrappedInstance); + } + + return $wrappedInstance[0]; + } +} diff --git a/vendor/symfony/var-exporter/Internal/Exporter.php b/vendor/symfony/var-exporter/Internal/Exporter.php new file mode 100644 index 0000000..4d83a4b --- /dev/null +++ b/vendor/symfony/var-exporter/Internal/Exporter.php @@ -0,0 +1,407 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Internal; + +use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class Exporter +{ + /** + * Prepares an array of values for VarExporter. + * + * For performance this method is public and has no type-hints. + * + * @param array &$values + * @param \SplObjectStorage $objectsPool + * @param array &$refsPool + * @param int &$objectsCount + * @param bool &$valuesAreStatic + * + * @return array + * + * @throws NotInstantiableTypeException When a value cannot be serialized + */ + public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic): array + { + $refs = $values; + foreach ($values as $k => $value) { + if (\is_resource($value)) { + throw new NotInstantiableTypeException(get_resource_type($value).' resource'); + } + $refs[$k] = $objectsPool; + + if ($isRef = !$valueIsStatic = $values[$k] !== $objectsPool) { + $values[$k] = &$value; // Break hard references to make $values completely + unset($value); // independent from the original structure + $refs[$k] = $value = $values[$k]; + if ($value instanceof Reference && 0 > $value->id) { + $valuesAreStatic = false; + ++$value->count; + continue; + } + $refsPool[] = [&$refs[$k], $value, &$value]; + $refs[$k] = $values[$k] = new Reference(-\count($refsPool), $value); + } + + if (\is_array($value)) { + if ($value) { + $value = self::prepare($value, $objectsPool, $refsPool, $objectsCount, $valueIsStatic); + } + goto handle_value; + } elseif (!\is_object($value) && !$value instanceof \__PHP_Incomplete_Class) { + goto handle_value; + } + + $valueIsStatic = false; + if (isset($objectsPool[$value])) { + ++$objectsCount; + $value = new Reference($objectsPool[$value][0]); + goto handle_value; + } + + $class = \get_class($value); + $reflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class); + + if ($reflector->hasMethod('__serialize')) { + if (!$reflector->getMethod('__serialize')->isPublic()) { + throw new \Error(sprintf('Call to %s method %s::__serialize()', $reflector->getMethod('__serialize')->isProtected() ? 'protected' : 'private', $class)); + } + + if (!\is_array($properties = $value->__serialize())) { + throw new \Typerror($class.'::__serialize() must return an array'); + } + + goto prepare_value; + } + + $properties = []; + $sleep = null; + $arrayValue = (array) $value; + $proto = Registry::$prototypes[$class]; + + if (($value instanceof \ArrayIterator || $value instanceof \ArrayObject) && null !== $proto) { + // ArrayIterator and ArrayObject need special care because their "flags" + // option changes the behavior of the (array) casting operator. + $properties = self::getArrayObjectProperties($value, $arrayValue, $proto); + + // populates Registry::$prototypes[$class] with a new instance + Registry::getClassReflector($class, Registry::$instantiableWithoutConstructor[$class], Registry::$cloneable[$class]); + } elseif ($value instanceof \SplObjectStorage && Registry::$cloneable[$class] && null !== $proto) { + // By implementing Serializable, SplObjectStorage breaks + // internal references; let's deal with it on our own. + foreach (clone $value as $v) { + $properties[] = $v; + $properties[] = $value[$v]; + } + $properties = ['SplObjectStorage' => ["\0" => $properties]]; + } elseif ($value instanceof \Serializable || $value instanceof \__PHP_Incomplete_Class) { + ++$objectsCount; + $objectsPool[$value] = [$id = \count($objectsPool), serialize($value), [], 0]; + $value = new Reference($id); + goto handle_value; + } + + if (method_exists($class, '__sleep')) { + if (!\is_array($sleep = $value->__sleep())) { + trigger_error('serialize(): __sleep should return an array only containing the names of instance-variables to serialize', E_USER_NOTICE); + $value = null; + goto handle_value; + } + foreach ($sleep as $name) { + if (property_exists($value, $name) && !$reflector->hasProperty($name)) { + $arrayValue[$name] = $value->$name; + } + } + $sleep = array_flip($sleep); + } + + $proto = (array) $proto; + + foreach ($arrayValue as $name => $v) { + $i = 0; + $n = (string) $name; + if ('' === $n || "\0" !== $n[0]) { + $c = 'stdClass'; + } elseif ('*' === $n[1]) { + $n = substr($n, 3); + $c = $reflector->getProperty($n)->class; + if ('Error' === $c) { + $c = 'TypeError'; + } elseif ('Exception' === $c) { + $c = 'ErrorException'; + } + } else { + $i = strpos($n, "\0", 2); + $c = substr($n, 1, $i - 1); + $n = substr($n, 1 + $i); + } + if (null !== $sleep) { + if (!isset($sleep[$n]) || ($i && $c !== $class)) { + continue; + } + $sleep[$n] = false; + } + if (!\array_key_exists($name, $proto) || $proto[$name] !== $v || "\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) { + $properties[$c][$n] = $v; + } + } + if ($sleep) { + foreach ($sleep as $n => $v) { + if (false !== $v) { + trigger_error(sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $n), E_USER_NOTICE); + } + } + } + + prepare_value: + $objectsPool[$value] = [$id = \count($objectsPool)]; + $properties = self::prepare($properties, $objectsPool, $refsPool, $objectsCount, $valueIsStatic); + ++$objectsCount; + $objectsPool[$value] = [$id, $class, $properties, method_exists($class, '__unserialize') ? -$objectsCount : (method_exists($class, '__wakeup') ? $objectsCount : 0)]; + + $value = new Reference($id); + + handle_value: + if ($isRef) { + unset($value); // Break the hard reference created above + } elseif (!$valueIsStatic) { + $values[$k] = $value; + } + $valuesAreStatic = $valueIsStatic && $valuesAreStatic; + } + + return $values; + } + + public static function export($value, string $indent = '') + { + switch (true) { + case \is_int($value) || \is_float($value): return var_export($value, true); + case [] === $value: return '[]'; + case false === $value: return 'false'; + case true === $value: return 'true'; + case null === $value: return 'null'; + case '' === $value: return "''"; + } + + if ($value instanceof Reference) { + if (0 <= $value->id) { + return '$o['.$value->id.']'; + } + if (!$value->count) { + return self::export($value->value, $indent); + } + $value = -$value->id; + + return '&$r['.$value.']'; + } + $subIndent = $indent.' '; + + if (\is_string($value)) { + $code = sprintf("'%s'", addcslashes($value, "'\\")); + + $code = preg_replace_callback('/([\0\r\n]++)(.)/', function ($m) use ($subIndent) { + $m[1] = sprintf('\'."%s".\'', str_replace( + ["\0", "\r", "\n", '\n\\'], + ['\0', '\r', '\n', '\n"'."\n".$subIndent.'."\\'], + $m[1] + )); + + if ("'" === $m[2]) { + return substr($m[1], 0, -2); + } + + if ('n".\'' === substr($m[1], -4)) { + return substr_replace($m[1], "\n".$subIndent.".'".$m[2], -2); + } + + return $m[1].$m[2]; + }, $code, -1, $count); + + if ($count && 0 === strpos($code, "''.")) { + $code = substr($code, 3); + } + + return $code; + } + + if (\is_array($value)) { + $j = -1; + $code = ''; + foreach ($value as $k => $v) { + $code .= $subIndent; + if (!\is_int($k) || 1 !== $k - $j) { + $code .= self::export($k, $subIndent).' => '; + } + if (\is_int($k) && $k > $j) { + $j = $k; + } + $code .= self::export($v, $subIndent).",\n"; + } + + return "[\n".$code.$indent.']'; + } + + if ($value instanceof Values) { + $code = $subIndent."\$r = [],\n"; + foreach ($value->values as $k => $v) { + $code .= $subIndent.'$r['.$k.'] = '.self::export($v, $subIndent).",\n"; + } + + return "[\n".$code.$indent.']'; + } + + if ($value instanceof Registry) { + return self::exportRegistry($value, $indent, $subIndent); + } + + if ($value instanceof Hydrator) { + return self::exportHydrator($value, $indent, $subIndent); + } + + throw new \UnexpectedValueException(sprintf('Cannot export value of type "%s".', \is_object($value) ? \get_class($value) : \gettype($value))); + } + + private static function exportRegistry(Registry $value, string $indent, string $subIndent): string + { + $code = ''; + $serializables = []; + $seen = []; + $prototypesAccess = 0; + $factoriesAccess = 0; + $r = '\\'.Registry::class; + $j = -1; + + foreach ($value as $k => $class) { + if (':' === ($class[1] ?? null)) { + $serializables[$k] = $class; + continue; + } + if (!Registry::$instantiableWithoutConstructor[$class]) { + if (is_subclass_of($class, 'Serializable') && !method_exists($class, '__unserialize')) { + $serializables[$k] = 'C:'.\strlen($class).':"'.$class.'":0:{}'; + } else { + $serializables[$k] = 'O:'.\strlen($class).':"'.$class.'":0:{}'; + } + if (is_subclass_of($class, 'Throwable')) { + $eol = is_subclass_of($class, 'Error') ? "\0Error\0" : "\0Exception\0"; + $serializables[$k] = substr_replace($serializables[$k], '1:{s:'.(5 + \strlen($eol)).':"'.$eol.'trace";a:0:{}}', -4); + } + continue; + } + $code .= $subIndent.(1 !== $k - $j ? $k.' => ' : ''); + $j = $k; + $eol = ",\n"; + $c = '['.self::export($class).']'; + + if ($seen[$class] ?? false) { + if (Registry::$cloneable[$class]) { + ++$prototypesAccess; + $code .= 'clone $p'.$c; + } else { + ++$factoriesAccess; + $code .= '$f'.$c.'()'; + } + } else { + $seen[$class] = true; + if (Registry::$cloneable[$class]) { + $code .= 'clone ('.($prototypesAccess++ ? '$p' : '($p = &'.$r.'::$prototypes)').$c.' ?? '.$r.'::p'; + } else { + $code .= '('.($factoriesAccess++ ? '$f' : '($f = &'.$r.'::$factories)').$c.' ?? '.$r.'::f'; + $eol = '()'.$eol; + } + $code .= '('.substr($c, 1, -1).'))'; + } + $code .= $eol; + } + + if (1 === $prototypesAccess) { + $code = str_replace('($p = &'.$r.'::$prototypes)', $r.'::$prototypes', $code); + } + if (1 === $factoriesAccess) { + $code = str_replace('($f = &'.$r.'::$factories)', $r.'::$factories', $code); + } + if ('' !== $code) { + $code = "\n".$code.$indent; + } + + if ($serializables) { + $code = $r.'::unserialize(['.$code.'], '.self::export($serializables, $indent).')'; + } else { + $code = '['.$code.']'; + } + + return '$o = '.$code; + } + + private static function exportHydrator(Hydrator $value, string $indent, string $subIndent): string + { + $code = ''; + foreach ($value->properties as $class => $properties) { + $code .= $subIndent.' '.self::export($class).' => '.self::export($properties, $subIndent.' ').",\n"; + } + + $code = [ + self::export($value->registry, $subIndent), + self::export($value->values, $subIndent), + '' !== $code ? "[\n".$code.$subIndent.']' : '[]', + self::export($value->value, $subIndent), + self::export($value->wakeups, $subIndent), + ]; + + return '\\'.\get_class($value)."::hydrate(\n".$subIndent.implode(",\n".$subIndent, $code)."\n".$indent.')'; + } + + /** + * @param \ArrayIterator|\ArrayObject $value + * @param \ArrayIterator|\ArrayObject $proto + */ + private static function getArrayObjectProperties($value, array &$arrayValue, $proto): array + { + $reflector = $value instanceof \ArrayIterator ? 'ArrayIterator' : 'ArrayObject'; + $reflector = Registry::$reflectors[$reflector] ?? Registry::getClassReflector($reflector); + + $properties = [ + $arrayValue, + $reflector->getMethod('getFlags')->invoke($value), + $value instanceof \ArrayObject ? $reflector->getMethod('getIteratorClass')->invoke($value) : 'ArrayIterator', + ]; + + $reflector = $reflector->getMethod('setFlags'); + $reflector->invoke($proto, \ArrayObject::STD_PROP_LIST); + + if ($properties[1] & \ArrayObject::STD_PROP_LIST) { + $reflector->invoke($value, 0); + $properties[0] = (array) $value; + } else { + $reflector->invoke($value, \ArrayObject::STD_PROP_LIST); + $arrayValue = (array) $value; + } + $reflector->invoke($value, $properties[1]); + + if ([[], 0, 'ArrayIterator'] === $properties) { + $properties = []; + } else { + if ('ArrayIterator' === $properties[2]) { + unset($properties[2]); + } + $properties = [$reflector->class => ["\0" => $properties]]; + } + + return $properties; + } +} diff --git a/vendor/symfony/var-exporter/Internal/Hydrator.php b/vendor/symfony/var-exporter/Internal/Hydrator.php new file mode 100644 index 0000000..364d292 --- /dev/null +++ b/vendor/symfony/var-exporter/Internal/Hydrator.php @@ -0,0 +1,151 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Internal; + +use Symfony\Component\VarExporter\Exception\ClassNotFoundException; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class Hydrator +{ + public static $hydrators = []; + + public $registry; + public $values; + public $properties; + public $value; + public $wakeups; + + public function __construct(?Registry $registry, ?Values $values, array $properties, $value, array $wakeups) + { + $this->registry = $registry; + $this->values = $values; + $this->properties = $properties; + $this->value = $value; + $this->wakeups = $wakeups; + } + + public static function hydrate($objects, $values, $properties, $value, $wakeups) + { + foreach ($properties as $class => $vars) { + (self::$hydrators[$class] ?? self::getHydrator($class))($vars, $objects); + } + foreach ($wakeups as $k => $v) { + if (\is_array($v)) { + $objects[-$k]->__unserialize($v); + } else { + $objects[$v]->__wakeup(); + } + } + + return $value; + } + + public static function getHydrator($class) + { + if ('stdClass' === $class) { + return self::$hydrators[$class] = static function ($properties, $objects) { + foreach ($properties as $name => $values) { + foreach ($values as $i => $v) { + $objects[$i]->$name = $v; + } + } + }; + } + + if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) { + throw new ClassNotFoundException($class); + } + $classReflector = new \ReflectionClass($class); + + if (!$classReflector->isInternal()) { + return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, $class); + } + + if ($classReflector->name !== $class) { + return self::$hydrators[$classReflector->name] ?? self::getHydrator($classReflector->name); + } + + switch ($class) { + case 'ArrayIterator': + case 'ArrayObject': + $constructor = \Closure::fromCallable([$classReflector->getConstructor(), 'invokeArgs']); + + return self::$hydrators[$class] = static function ($properties, $objects) use ($constructor) { + foreach ($properties as $name => $values) { + if ("\0" !== $name) { + foreach ($values as $i => $v) { + $objects[$i]->$name = $v; + } + } + } + foreach ($properties["\0"] ?? [] as $i => $v) { + $constructor($objects[$i], $v); + } + }; + + case 'ErrorException': + return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, new class() extends \ErrorException { + }); + + case 'TypeError': + return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, new class() extends \Error { + }); + + case 'SplObjectStorage': + return self::$hydrators[$class] = static function ($properties, $objects) { + foreach ($properties as $name => $values) { + if ("\0" === $name) { + foreach ($values as $i => $v) { + for ($j = 0; $j < \count($v); ++$j) { + $objects[$i]->attach($v[$j], $v[++$j]); + } + } + continue; + } + foreach ($values as $i => $v) { + $objects[$i]->$name = $v; + } + } + }; + } + + $propertySetters = []; + foreach ($classReflector->getProperties() as $propertyReflector) { + if (!$propertyReflector->isStatic()) { + $propertyReflector->setAccessible(true); + $propertySetters[$propertyReflector->name] = \Closure::fromCallable([$propertyReflector, 'setValue']); + } + } + + if (!$propertySetters) { + return self::$hydrators[$class] = self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'); + } + + return self::$hydrators[$class] = static function ($properties, $objects) use ($propertySetters) { + foreach ($properties as $name => $values) { + if ($setValue = $propertySetters[$name] ?? null) { + foreach ($values as $i => $v) { + $setValue($objects[$i], $v); + } + continue; + } + foreach ($values as $i => $v) { + $objects[$i]->$name = $v; + } + } + }; + } +} diff --git a/vendor/symfony/var-exporter/Internal/Reference.php b/vendor/symfony/var-exporter/Internal/Reference.php new file mode 100644 index 0000000..e371c07 --- /dev/null +++ b/vendor/symfony/var-exporter/Internal/Reference.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Internal; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class Reference +{ + public $id; + public $value; + public $count = 0; + + public function __construct(int $id, $value = null) + { + $this->id = $id; + $this->value = $value; + } +} diff --git a/vendor/symfony/var-exporter/Internal/Registry.php b/vendor/symfony/var-exporter/Internal/Registry.php new file mode 100644 index 0000000..19d91c9 --- /dev/null +++ b/vendor/symfony/var-exporter/Internal/Registry.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Internal; + +use Symfony\Component\VarExporter\Exception\ClassNotFoundException; +use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class Registry +{ + public static $reflectors = []; + public static $prototypes = []; + public static $factories = []; + public static $cloneable = []; + public static $instantiableWithoutConstructor = []; + + public function __construct(array $classes) + { + foreach ($classes as $i => $class) { + $this->$i = $class; + } + } + + public static function unserialize($objects, $serializables) + { + $unserializeCallback = ini_set('unserialize_callback_func', __CLASS__.'::getClassReflector'); + + try { + foreach ($serializables as $k => $v) { + $objects[$k] = unserialize($v); + } + } finally { + ini_set('unserialize_callback_func', $unserializeCallback); + } + + return $objects; + } + + public static function p($class) + { + self::getClassReflector($class, true, true); + + return self::$prototypes[$class]; + } + + public static function f($class) + { + $reflector = self::$reflectors[$class] ?? self::getClassReflector($class, true, false); + + return self::$factories[$class] = \Closure::fromCallable([$reflector, 'newInstanceWithoutConstructor']); + } + + public static function getClassReflector($class, $instantiableWithoutConstructor = false, $cloneable = null) + { + if (!($isClass = class_exists($class)) && !interface_exists($class, false) && !trait_exists($class, false)) { + throw new ClassNotFoundException($class); + } + $reflector = new \ReflectionClass($class); + + if ($instantiableWithoutConstructor) { + $proto = $reflector->newInstanceWithoutConstructor(); + } elseif (!$isClass || $reflector->isAbstract()) { + throw new NotInstantiableTypeException($class); + } elseif ($reflector->name !== $class) { + $reflector = self::$reflectors[$name = $reflector->name] ?? self::getClassReflector($name, false, $cloneable); + self::$cloneable[$class] = self::$cloneable[$name]; + self::$instantiableWithoutConstructor[$class] = self::$instantiableWithoutConstructor[$name]; + self::$prototypes[$class] = self::$prototypes[$name]; + + return self::$reflectors[$class] = $reflector; + } else { + try { + $proto = $reflector->newInstanceWithoutConstructor(); + $instantiableWithoutConstructor = true; + } catch (\ReflectionException $e) { + $proto = $reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize') ? 'C:' : 'O:'; + if ('C:' === $proto && !$reflector->getMethod('unserialize')->isInternal()) { + $proto = null; + } elseif (false === $proto = @unserialize($proto.\strlen($class).':"'.$class.'":0:{}')) { + throw new NotInstantiableTypeException($class); + } + } + if (null !== $proto && !$proto instanceof \Throwable && !$proto instanceof \Serializable && !method_exists($class, '__sleep') && (\PHP_VERSION_ID < 70400 || !method_exists($class, '__serialize'))) { + try { + serialize($proto); + } catch (\Exception $e) { + throw new NotInstantiableTypeException($class, $e); + } + } + } + + if (null === $cloneable) { + if (($proto instanceof \Reflector || $proto instanceof \ReflectionGenerator || $proto instanceof \ReflectionType || $proto instanceof \IteratorIterator || $proto instanceof \RecursiveIteratorIterator) && (!$proto instanceof \Serializable && !method_exists($proto, '__wakeup') && (\PHP_VERSION_ID < 70400 || !method_exists($class, '__unserialize')))) { + throw new NotInstantiableTypeException($class); + } + + $cloneable = $reflector->isCloneable() && !$reflector->hasMethod('__clone'); + } + + self::$cloneable[$class] = $cloneable; + self::$instantiableWithoutConstructor[$class] = $instantiableWithoutConstructor; + self::$prototypes[$class] = $proto; + + if ($proto instanceof \Throwable) { + static $setTrace; + + if (null === $setTrace) { + $setTrace = [ + new \ReflectionProperty(\Error::class, 'trace'), + new \ReflectionProperty(\Exception::class, 'trace'), + ]; + $setTrace[0]->setAccessible(true); + $setTrace[1]->setAccessible(true); + $setTrace[0] = \Closure::fromCallable([$setTrace[0], 'setValue']); + $setTrace[1] = \Closure::fromCallable([$setTrace[1], 'setValue']); + } + + $setTrace[$proto instanceof \Exception]($proto, []); + } + + return self::$reflectors[$class] = $reflector; + } +} diff --git a/vendor/symfony/var-exporter/Internal/Values.php b/vendor/symfony/var-exporter/Internal/Values.php new file mode 100644 index 0000000..21ae04e --- /dev/null +++ b/vendor/symfony/var-exporter/Internal/Values.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter\Internal; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class Values +{ + public $values; + + public function __construct(array $values) + { + $this->values = $values; + } +} diff --git a/vendor/symfony/var-exporter/LICENSE b/vendor/symfony/var-exporter/LICENSE new file mode 100644 index 0000000..3f853aa --- /dev/null +++ b/vendor/symfony/var-exporter/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/var-exporter/README.md b/vendor/symfony/var-exporter/README.md new file mode 100644 index 0000000..bb13960 --- /dev/null +++ b/vendor/symfony/var-exporter/README.md @@ -0,0 +1,38 @@ +VarExporter Component +===================== + +The VarExporter component allows exporting any serializable PHP data structure to +plain PHP code. While doing so, it preserves all the semantics associated with +the serialization mechanism of PHP (`__wakeup`, `__sleep`, `Serializable`, +`__serialize`, `__unserialize`). + +It also provides an instantiator that allows creating and populating objects +without calling their constructor nor any other methods. + +The reason to use this component *vs* `serialize()` or +[igbinary](https://github.com/igbinary/igbinary) is performance: thanks to +OPcache, the resulting code is significantly faster and more memory efficient +than using `unserialize()` or `igbinary_unserialize()`. + +Unlike `var_export()`, this works on any serializable PHP value. + +It also provides a few improvements over `var_export()`/`serialize()`: + + * the output is PSR-2 compatible; + * the output can be re-indented without messing up with `\r` or `\n` in the data + * missing classes throw a `ClassNotFoundException` instead of being unserialized to + `PHP_Incomplete_Class` objects; + * references involving `SplObjectStorage`, `ArrayObject` or `ArrayIterator` + instances are preserved; + * `Reflection*`, `IteratorIterator` and `RecursiveIteratorIterator` classes + throw an exception when being serialized (their unserialized version is broken + anyway, see https://bugs.php.net/76737). + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/var_exporter.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/var-exporter/VarExporter.php b/vendor/symfony/var-exporter/VarExporter.php new file mode 100644 index 0000000..da9a8d4 --- /dev/null +++ b/vendor/symfony/var-exporter/VarExporter.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarExporter; + +use Symfony\Component\VarExporter\Exception\ExceptionInterface; +use Symfony\Component\VarExporter\Internal\Exporter; +use Symfony\Component\VarExporter\Internal\Hydrator; +use Symfony\Component\VarExporter\Internal\Registry; +use Symfony\Component\VarExporter\Internal\Values; + +/** + * Exports serializable PHP values to PHP code. + * + * VarExporter allows serializing PHP data structures to plain PHP code (like var_export()) + * while preserving all the semantics associated with serialize() (unlike var_export()). + * + * By leveraging OPcache, the generated PHP code is faster than doing the same with unserialize(). + * + * @author Nicolas Grekas + */ +final class VarExporter +{ + /** + * Exports a serializable PHP value to PHP code. + * + * @param mixed $value The value to export + * @param bool &$isStaticValue Set to true after execution if the provided value is static, false otherwise + * + * @return string The value exported as PHP code + * + * @throws ExceptionInterface When the provided value cannot be serialized + */ + public static function export($value, bool &$isStaticValue = null): string + { + $isStaticValue = true; + + if (!\is_object($value) && !(\is_array($value) && $value) && !$value instanceof \__PHP_Incomplete_Class && !\is_resource($value)) { + return Exporter::export($value); + } + + $objectsPool = new \SplObjectStorage(); + $refsPool = []; + $objectsCount = 0; + + try { + $value = Exporter::prepare([$value], $objectsPool, $refsPool, $objectsCount, $isStaticValue)[0]; + } finally { + $references = []; + foreach ($refsPool as $i => $v) { + if ($v[0]->count) { + $references[1 + $i] = $v[2]; + } + $v[0] = $v[1]; + } + } + + if ($isStaticValue) { + return Exporter::export($value); + } + + $classes = []; + $values = []; + $states = []; + foreach ($objectsPool as $i => $v) { + list(, $classes[], $values[], $wakeup) = $objectsPool[$v]; + if (0 < $wakeup) { + $states[$wakeup] = $i; + } elseif (0 > $wakeup) { + $states[-$wakeup] = [$i, array_pop($values)]; + $values[] = []; + } + } + ksort($states); + + $wakeups = [null]; + foreach ($states as $k => $v) { + if (\is_array($v)) { + $wakeups[-$v[0]] = $v[1]; + } else { + $wakeups[] = $v; + } + } + + if (null === $wakeups[0]) { + unset($wakeups[0]); + } + + $properties = []; + foreach ($values as $i => $vars) { + foreach ($vars as $class => $values) { + foreach ($values as $name => $v) { + $properties[$class][$name][$i] = $v; + } + } + } + + if ($classes || $references) { + $value = new Hydrator(new Registry($classes), $references ? new Values($references) : null, $properties, $value, $wakeups); + } else { + $isStaticValue = true; + } + + return Exporter::export($value); + } +} diff --git a/vendor/symfony/var-exporter/composer.json b/vendor/symfony/var-exporter/composer.json new file mode 100644 index 0000000..6ccfc63 --- /dev/null +++ b/vendor/symfony/var-exporter/composer.json @@ -0,0 +1,36 @@ +{ + "name": "symfony/var-exporter", + "type": "library", + "description": "A blend of var_export() + serialize() to turn any serializable data structure to plain PHP code", + "keywords": ["export", "serialize", "instantiate", "hydrate", "construct", "clone"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.2.5" + }, + "require-dev": { + "symfony/var-dumper": "^4.4|^5.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\VarExporter\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + } +} -- GitLab From 25329a991ec9c512ad85aeda83cb1edca97e8a5a Mon Sep 17 00:00:00 2001 From: MOAL Fleurian Date: Sat, 4 Jan 2020 04:58:16 +0100 Subject: [PATCH 2/4] ajout de 100 000 datas par fichier(pb memoire sinon) --- api/docker/php/conf.d/api-platform.dev.ini | 1 + api/src/DataFixtures/AppFixtures.php | 63 ++++++++++++++++++---- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/api/docker/php/conf.d/api-platform.dev.ini b/api/docker/php/conf.d/api-platform.dev.ini index 39b1cd4..440ab79 100644 --- a/api/docker/php/conf.d/api-platform.dev.ini +++ b/api/docker/php/conf.d/api-platform.dev.ini @@ -9,3 +9,4 @@ opcache.max_accelerated_files = 20000 opcache.memory_consumption = 256 realpath_cache_size = 4096K realpath_cache_ttl = 600 +memory_limit = 3G \ No newline at end of file diff --git a/api/src/DataFixtures/AppFixtures.php b/api/src/DataFixtures/AppFixtures.php index 788f73b..e1754ea 100644 --- a/api/src/DataFixtures/AppFixtures.php +++ b/api/src/DataFixtures/AppFixtures.php @@ -14,17 +14,60 @@ class AppFixtures extends Fixture { echo __DIR__; // create 20 products! Bam! - for ($i = 0; $i < 20; $i++) { - $product = new PropertySale(); - //$product->id = $i; - $product->price = 15; - $product->surface = 15; - $product->date = new DateTime('2012/12/12');; - $product->department = 'DPT'; - $product->region = 'RGN'; - $manager->persist($product); + for($annee = 2015;$annee<=2019;$annee++){ + echo "chargement des données de l'année ".$annee."\n\n"; + $file = fopen(__DIR__."/valeursfoncieres-".$annee.".txt","r"); + $cpt = 1; + $nbelt = 43; + $percent = 0; + $line = fgetcsv($file,1024,"|");//enleve la premiere ligne contenant le descriptif des ventes + while(!feof($file)){ + + $line = fgetcsv($file,1024,"|"); + // on ne prend en compte que les ventes, tout autre élément est ignoré car l'evenement peut influer sur le prix + // puisque le nombre de vente est tres supérieur aux autre type de mutation le résultat n'en sera affecté que de façon négligeable + if(strcmp($line[9],'Vente')==0 &&( strcmp($line[36],'Maison')==0 || strcmp($line[36],'Appartement')==0)){ + $propertysale = new PropertySale(); + $propertysale->price = 12;//doubleval($line[10]) + $propertysale->surface = 12;//$line[36] + + //$pieces = explode(" ", $line[8]); + $pieces2 = explode("/", $line[8]); + $propertysale->date = new DateTime($pieces2[2]. "-" . $pieces2[1] . "-" . $pieces2[0]); + $propertysale->department = $line[18]; + $propertysale->region = $line[18];//TODO : "la surface ne nous interresse pas dans ce projet, je le remplace par le type de local, il faudra remplacer le nom de la-dite variable" + $manager->persist($propertysale); + if($cpt++%1000==0){// on limite le nombre de données acquise pour éviter une surcharge mémoire => meme en allouant 2G de memoire a php, l'acquisition de 100 000 données n'était pas possible + echo (++$percent)."% done \n"; + if($percent == 100){ + fseek($file,0,SEEK_END); + } + } + + + } + + + } + fclose($file); + $manager->flush(); + } - $manager->flush(); + + //$propertysale->id = $i; + + /*for ($i = 0; $i < 20; $i++) { + $propertysale = new PropertySale(); + //$propertysale->id = $i; + $propertysale->price = 15; + $propertysale->surface = 15; + $propertysale->date = new DateTime('2012/12/12');; + $propertysale->department = 'DPT'; + $propertysale->region = 'RGN'; + $manager->persist($propertysale); + }*/ + + } } -- GitLab From a37285f3f81deca6905884352f6614952247e665 Mon Sep 17 00:00:00 2001 From: Florian Boulant Date: Sun, 5 Jan 2020 20:06:59 +0100 Subject: [PATCH 3/4] Remove vendor files from project --- vendor/autoload.php | 7 - vendor/bin/doctrine | 1 - vendor/bin/doctrine-dbal | 1 - vendor/bin/var-dump-server | 1 - vendor/composer/ClassLoader.php | 445 -- vendor/composer/LICENSE | 21 - vendor/composer/autoload_classmap.php | 11 - vendor/composer/autoload_files.php | 15 - vendor/composer/autoload_namespaces.php | 9 - vendor/composer/autoload_psr4.php | 50 - vendor/composer/autoload_real.php | 70 - vendor/composer/autoload_static.php | 255 -- vendor/composer/installed.json | 3078 -------------- vendor/doctrine/annotations/CHANGELOG.md | 162 - vendor/doctrine/annotations/LICENSE | 19 - vendor/doctrine/annotations/README.md | 17 - vendor/doctrine/annotations/composer.json | 43 - .../annotations/docs/en/annotations.rst | 223 - .../doctrine/annotations/docs/en/custom.rst | 341 -- vendor/doctrine/annotations/docs/en/index.rst | 90 - .../doctrine/annotations/docs/en/sidebar.rst | 6 - .../Common/Annotations/Annotation.php | 79 - .../Annotations/Annotation/Attribute.php | 47 - .../Annotations/Annotation/Attributes.php | 37 - .../Common/Annotations/Annotation/Enum.php | 84 - .../Annotation/IgnoreAnnotation.php | 54 - .../Annotations/Annotation/Required.php | 33 - .../Common/Annotations/Annotation/Target.php | 107 - .../Annotations/AnnotationException.php | 197 - .../Common/Annotations/AnnotationReader.php | 415 -- .../Common/Annotations/AnnotationRegistry.php | 174 - .../Common/Annotations/CachedReader.php | 262 -- .../Doctrine/Common/Annotations/DocLexer.php | 147 - .../Doctrine/Common/Annotations/DocParser.php | 1197 ------ .../Common/Annotations/FileCacheReader.php | 290 -- .../Common/Annotations/IndexedReader.php | 119 - .../Doctrine/Common/Annotations/PhpParser.php | 91 - .../Doctrine/Common/Annotations/Reader.php | 89 - .../Annotations/SimpleAnnotationReader.php | 127 - .../Common/Annotations/TokenParser.php | 194 - .../doctrine/annotations/phpbench.json.dist | 4 - vendor/doctrine/annotations/phpstan.neon | 14 - vendor/doctrine/cache/LICENSE | 19 - vendor/doctrine/cache/README.md | 10 - vendor/doctrine/cache/UPGRADE.md | 16 - vendor/doctrine/cache/composer.json | 52 - .../lib/Doctrine/Common/Cache/ApcCache.php | 105 - .../lib/Doctrine/Common/Cache/ApcuCache.php | 106 - .../lib/Doctrine/Common/Cache/ArrayCache.php | 113 - .../cache/lib/Doctrine/Common/Cache/Cache.php | 90 - .../Doctrine/Common/Cache/CacheProvider.php | 325 -- .../lib/Doctrine/Common/Cache/ChainCache.php | 187 - .../Doctrine/Common/Cache/ClearableCache.php | 21 - .../Common/Cache/CouchbaseBucketCache.php | 197 - .../Doctrine/Common/Cache/CouchbaseCache.php | 105 - .../Doctrine/Common/Cache/ExtMongoDBCache.php | 198 - .../lib/Doctrine/Common/Cache/FileCache.php | 281 -- .../Doctrine/Common/Cache/FilesystemCache.php | 102 - .../Doctrine/Common/Cache/FlushableCache.php | 18 - .../Doctrine/Common/Cache/InvalidCacheId.php | 25 - .../Common/Cache/LegacyMongoDBCache.php | 175 - .../Doctrine/Common/Cache/MemcacheCache.php | 104 - .../Doctrine/Common/Cache/MemcachedCache.php | 170 - .../Doctrine/Common/Cache/MongoDBCache.php | 112 - .../Common/Cache/MultiDeleteCache.php | 22 - .../Doctrine/Common/Cache/MultiGetCache.php | 23 - .../Common/Cache/MultiOperationCache.php | 12 - .../Doctrine/Common/Cache/MultiPutCache.php | 24 - .../Doctrine/Common/Cache/PhpFileCache.php | 118 - .../lib/Doctrine/Common/Cache/PredisCache.php | 143 - .../lib/Doctrine/Common/Cache/RedisCache.php | 181 - .../Doctrine/Common/Cache/SQLite3Cache.php | 206 - .../lib/Doctrine/Common/Cache/Version.php | 8 - .../lib/Doctrine/Common/Cache/VoidCache.php | 59 - .../Doctrine/Common/Cache/WinCacheCache.php | 106 - .../lib/Doctrine/Common/Cache/XcacheCache.php | 104 - .../Doctrine/Common/Cache/ZendDataCache.php | 69 - .../collections/.doctrine-project.json | 17 - vendor/doctrine/collections/CONTRIBUTING.md | 54 - vendor/doctrine/collections/LICENSE | 19 - vendor/doctrine/collections/README.md | 93 - vendor/doctrine/collections/composer.json | 42 - .../docs/en/derived-collections.rst | 26 - .../docs/en/expression-builder.rst | 173 - .../collections/docs/en/expressions.rst | 102 - vendor/doctrine/collections/docs/en/index.rst | 327 -- .../collections/docs/en/lazy-collections.rst | 26 - .../doctrine/collections/docs/en/sidebar.rst | 8 - .../Collections/AbstractLazyCollection.php | 354 -- .../Common/Collections/ArrayCollection.php | 429 -- .../Common/Collections/Collection.php | 296 -- .../Doctrine/Common/Collections/Criteria.php | 222 - .../Expr/ClosureExpressionVisitor.php | 257 -- .../Common/Collections/Expr/Comparison.php | 80 - .../Collections/Expr/CompositeExpression.php | 68 - .../Common/Collections/Expr/Expression.php | 14 - .../Collections/Expr/ExpressionVisitor.php | 55 - .../Common/Collections/Expr/Value.php | 33 - .../Common/Collections/ExpressionBuilder.php | 180 - .../Common/Collections/Selectable.php | 31 - vendor/doctrine/collections/psalm.xml.dist | 54 - vendor/doctrine/common/.doctrine-project.json | 18 - vendor/doctrine/common/.github/FUNDING.yml | 3 - vendor/doctrine/common/LICENSE | 19 - vendor/doctrine/common/README.md | 11 - vendor/doctrine/common/UPGRADE_TO_2_1 | 39 - vendor/doctrine/common/UPGRADE_TO_2_2 | 61 - vendor/doctrine/common/composer.json | 54 - vendor/doctrine/common/composer.lock | 3433 ---------------- vendor/doctrine/common/docs/en/index.rst | 10 - .../docs/en/reference/class-loading.rst | 242 -- vendor/doctrine/common/humbug.json.dist | 11 - .../lib/Doctrine/Common/ClassLoader.php | 267 -- .../lib/Doctrine/Common/CommonException.php | 13 - .../common/lib/Doctrine/Common/Comparable.php | 28 - .../common/lib/Doctrine/Common/Lexer.php | 25 - .../Common/Proxy/AbstractProxyFactory.php | 245 -- .../lib/Doctrine/Common/Proxy/Autoloader.php | 82 - .../Exception/InvalidArgumentException.php | 106 - .../Proxy/Exception/OutOfBoundsException.php | 26 - .../Common/Proxy/Exception/ProxyException.php | 15 - .../Exception/UnexpectedValueException.php | 72 - .../lib/Doctrine/Common/Proxy/Proxy.php | 74 - .../Doctrine/Common/Proxy/ProxyDefinition.php | 53 - .../Doctrine/Common/Proxy/ProxyGenerator.php | 1062 ----- .../lib/Doctrine/Common/Util/ClassUtils.php | 93 - .../common/lib/Doctrine/Common/Util/Debug.php | 167 - .../lib/Doctrine/Common/Util/Inflector.php | 19 - .../common/lib/Doctrine/Common/Version.php | 37 - vendor/doctrine/common/phpstan.neon.dist | 34 - .../data-fixtures/.doctrine-project.json | 24 - .../data-fixtures/.github/FUNDING.yml | 3 - vendor/doctrine/data-fixtures/CHANGELOG.md | 170 - vendor/doctrine/data-fixtures/LICENSE | 20 - vendor/doctrine/data-fixtures/README.md | 201 - vendor/doctrine/data-fixtures/UPGRADE | 17 - vendor/doctrine/data-fixtures/composer.json | 58 - .../Common/DataFixtures/AbstractFixture.php | 97 - .../DependentFixtureInterface.php | 19 - .../Listener/MongoDBReferenceListener.php | 56 - .../Event/Listener/ORMReferenceListener.php | 57 - .../Exception/CircularReferenceException.php | 11 - .../Executor/AbstractExecutor.php | 141 - .../DataFixtures/Executor/MongoDBExecutor.php | 67 - .../DataFixtures/Executor/ORMExecutor.php | 73 - .../DataFixtures/Executor/PHPCRExecutor.php | 62 - .../Common/DataFixtures/FixtureInterface.php | 18 - .../Doctrine/Common/DataFixtures/Loader.php | 438 -- .../DataFixtures/OrderedFixtureInterface.php | 20 - .../DataFixtures/ProxyReferenceRepository.php | 131 - .../DataFixtures/Purger/MongoDBPurger.php | 58 - .../Common/DataFixtures/Purger/ORMPurger.php | 271 -- .../DataFixtures/Purger/PHPCRPurger.php | 43 - .../DataFixtures/Purger/PurgerInterface.php | 18 - .../DataFixtures/ReferenceRepository.php | 255 -- .../DataFixtures/SharedFixtureInterface.php | 16 - .../DataFixtures/Sorter/TopologicalSorter.php | 179 - .../Common/DataFixtures/Sorter/Vertex.php | 34 - vendor/doctrine/data-fixtures/phpcs.xml.dist | 50 - vendor/doctrine/dbal/.doctrine-project.json | 55 - vendor/doctrine/dbal/LICENSE | 19 - vendor/doctrine/dbal/README.md | 46 - vendor/doctrine/dbal/SECURITY.md | 14 - vendor/doctrine/dbal/UPGRADE.md | 452 -- vendor/doctrine/dbal/bin/doctrine-dbal | 4 - vendor/doctrine/dbal/bin/doctrine-dbal.php | 57 - vendor/doctrine/dbal/composer.json | 66 - .../Doctrine/DBAL/Cache/ArrayStatement.php | 137 - .../Doctrine/DBAL/Cache/CacheException.php | 24 - .../Doctrine/DBAL/Cache/QueryCacheProfile.php | 121 - .../DBAL/Cache/ResultCacheStatement.php | 212 - .../dbal/lib/Doctrine/DBAL/ColumnCase.php | 32 - .../dbal/lib/Doctrine/DBAL/Configuration.php | 160 - .../dbal/lib/Doctrine/DBAL/Connection.php | 1685 -------- .../lib/Doctrine/DBAL/ConnectionException.php | 38 - .../Connections/MasterSlaveConnection.php | 377 -- .../dbal/lib/Doctrine/DBAL/DBALException.php | 294 -- .../dbal/lib/Doctrine/DBAL/Driver.php | 59 - .../DBAL/Driver/AbstractDB2Driver.php | 40 - .../DBAL/Driver/AbstractDriverException.php | 54 - .../DBAL/Driver/AbstractMySQLDriver.php | 218 - .../DBAL/Driver/AbstractOracleDriver.php | 97 - .../EasyConnectString.php | 121 - .../DBAL/Driver/AbstractPostgreSQLDriver.php | 138 - .../DBAL/Driver/AbstractSQLAnywhereDriver.php | 127 - .../DBAL/Driver/AbstractSQLServerDriver.php | 81 - .../DBAL/Driver/AbstractSQLiteDriver.php | 98 - .../lib/Doctrine/DBAL/Driver/Connection.php | 93 - .../Doctrine/DBAL/Driver/DriverException.php | 40 - .../Driver/DrizzlePDOMySql/Connection.php | 21 - .../DBAL/Driver/DrizzlePDOMySql/Driver.php | 59 - .../DBAL/Driver/ExceptionConverterDriver.php | 22 - .../DBAL/Driver/IBMDB2/DB2Connection.php | 186 - .../Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php | 49 - .../DBAL/Driver/IBMDB2/DB2Exception.php | 9 - .../DBAL/Driver/IBMDB2/DB2Statement.php | 454 -- .../Doctrine/DBAL/Driver/Mysqli/Driver.php | 29 - .../DBAL/Driver/Mysqli/MysqliConnection.php | 303 -- .../DBAL/Driver/Mysqli/MysqliException.php | 12 - .../DBAL/Driver/Mysqli/MysqliStatement.php | 453 -- .../lib/Doctrine/DBAL/Driver/OCI8/Driver.php | 54 - .../DBAL/Driver/OCI8/OCI8Connection.php | 241 -- .../DBAL/Driver/OCI8/OCI8Exception.php | 22 - .../DBAL/Driver/OCI8/OCI8Statement.php | 531 --- .../Doctrine/DBAL/Driver/PDOConnection.php | 115 - .../lib/Doctrine/DBAL/Driver/PDOException.php | 52 - .../Doctrine/DBAL/Driver/PDOIbm/Driver.php | 59 - .../Doctrine/DBAL/Driver/PDOMySql/Driver.php | 72 - .../Doctrine/DBAL/Driver/PDOOracle/Driver.php | 62 - .../Doctrine/DBAL/Driver/PDOPgSql/Driver.php | 118 - .../Doctrine/DBAL/Driver/PDOSqlite/Driver.php | 83 - .../DBAL/Driver/PDOSqlsrv/Connection.php | 54 - .../Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php | 93 - .../DBAL/Driver/PDOSqlsrv/Statement.php | 35 - .../lib/Doctrine/DBAL/Driver/PDOStatement.php | 228 -- .../DBAL/Driver/PingableConnection.php | 17 - .../Doctrine/DBAL/Driver/ResultStatement.php | 98 - .../DBAL/Driver/SQLAnywhere/Driver.php | 87 - .../SQLAnywhere/SQLAnywhereConnection.php | 215 - .../SQLAnywhere/SQLAnywhereException.php | 71 - .../SQLAnywhere/SQLAnywhereStatement.php | 364 -- .../Doctrine/DBAL/Driver/SQLSrv/Driver.php | 58 - .../DBAL/Driver/SQLSrv/LastInsertId.php | 28 - .../DBAL/Driver/SQLSrv/SQLSrvConnection.php | 197 - .../DBAL/Driver/SQLSrv/SQLSrvException.php | 43 - .../DBAL/Driver/SQLSrv/SQLSrvStatement.php | 426 -- .../DBAL/Driver/ServerInfoAwareConnection.php | 23 - .../lib/Doctrine/DBAL/Driver/Statement.php | 105 - .../DBAL/Driver/StatementIterator.php | 26 - .../dbal/lib/Doctrine/DBAL/DriverManager.php | 442 -- .../DBAL/Event/ConnectionEventArgs.php | 61 - .../DBAL/Event/Listeners/MysqlSessionInit.php | 58 - .../Event/Listeners/OracleSessionInit.php | 72 - .../DBAL/Event/Listeners/SQLSessionInit.php | 41 - .../SchemaAlterTableAddColumnEventArgs.php | 81 - .../SchemaAlterTableChangeColumnEventArgs.php | 81 - .../DBAL/Event/SchemaAlterTableEventArgs.php | 68 - .../SchemaAlterTableRemoveColumnEventArgs.php | 81 - .../SchemaAlterTableRenameColumnEventArgs.php | 96 - .../Event/SchemaColumnDefinitionEventArgs.php | 108 - .../SchemaCreateTableColumnEventArgs.php | 81 - .../DBAL/Event/SchemaCreateTableEventArgs.php | 96 - .../DBAL/Event/SchemaDropTableEventArgs.php | 69 - .../Doctrine/DBAL/Event/SchemaEventArgs.php | 32 - .../Event/SchemaIndexDefinitionEventArgs.php | 92 - .../dbal/lib/Doctrine/DBAL/Events.php | 31 - .../DBAL/Exception/ConnectionException.php | 10 - .../ConstraintViolationException.php | 10 - .../DatabaseObjectExistsException.php | 14 - .../DatabaseObjectNotFoundException.php | 14 - .../DBAL/Exception/DeadlockException.php | 10 - .../DBAL/Exception/DriverException.php | 60 - ...ForeignKeyConstraintViolationException.php | 10 - .../Exception/InvalidArgumentException.php | 19 - .../Exception/InvalidFieldNameException.php | 10 - .../Exception/LockWaitTimeoutException.php | 10 - .../Exception/NonUniqueFieldNameException.php | 10 - .../NotNullConstraintViolationException.php | 10 - .../DBAL/Exception/ReadOnlyException.php | 10 - .../DBAL/Exception/RetryableException.php | 10 - .../DBAL/Exception/ServerException.php | 10 - .../DBAL/Exception/SyntaxErrorException.php | 10 - .../DBAL/Exception/TableExistsException.php | 10 - .../DBAL/Exception/TableNotFoundException.php | 10 - .../UniqueConstraintViolationException.php | 10 - .../dbal/lib/Doctrine/DBAL/FetchMode.php | 71 - .../lib/Doctrine/DBAL/Id/TableGenerator.php | 145 - .../DBAL/Id/TableGeneratorSchemaVisitor.php | 71 - .../dbal/lib/Doctrine/DBAL/LockMode.php | 21 - .../lib/Doctrine/DBAL/Logging/DebugStack.php | 56 - .../Doctrine/DBAL/Logging/EchoSQLLogger.php | 37 - .../lib/Doctrine/DBAL/Logging/LoggerChain.php | 52 - .../lib/Doctrine/DBAL/Logging/SQLLogger.php | 27 - .../dbal/lib/Doctrine/DBAL/ParameterType.php | 58 - .../DBAL/Platforms/AbstractPlatform.php | 3633 ----------------- .../Doctrine/DBAL/Platforms/DB2Platform.php | 916 ----- .../DBAL/Platforms/DateIntervalUnit.php | 28 - .../DBAL/Platforms/DrizzlePlatform.php | 621 --- .../DBAL/Platforms/Keywords/DB2Keywords.php | 420 -- .../Platforms/Keywords/DrizzleKeywords.php | 326 -- .../DBAL/Platforms/Keywords/KeywordList.php | 54 - .../Platforms/Keywords/MariaDb102Keywords.php | 274 -- .../DBAL/Platforms/Keywords/MsSQLKeywords.php | 21 - .../Platforms/Keywords/MySQL57Keywords.php | 263 -- .../Platforms/Keywords/MySQL80Keywords.php | 65 - .../DBAL/Platforms/Keywords/MySQLKeywords.php | 265 -- .../Platforms/Keywords/OracleKeywords.php | 139 - .../Keywords/PostgreSQL100Keywords.php | 19 - .../Keywords/PostgreSQL91Keywords.php | 126 - .../Keywords/PostgreSQL92Keywords.php | 29 - .../Keywords/PostgreSQL94Keywords.php | 32 - .../Platforms/Keywords/PostgreSQLKeywords.php | 113 - .../Keywords/ReservedKeywordsValidator.php | 126 - .../Keywords/SQLAnywhere11Keywords.php | 39 - .../Keywords/SQLAnywhere12Keywords.php | 48 - .../Keywords/SQLAnywhere16Keywords.php | 39 - .../Keywords/SQLAnywhereKeywords.php | 262 -- .../Keywords/SQLServer2005Keywords.php | 39 - .../Keywords/SQLServer2008Keywords.php | 31 - .../Keywords/SQLServer2012Keywords.php | 37 - .../Platforms/Keywords/SQLServerKeywords.php | 209 - .../Platforms/Keywords/SQLiteKeywords.php | 147 - .../DBAL/Platforms/MariaDb1027Platform.php | 41 - .../DBAL/Platforms/MySQL57Platform.php | 71 - .../DBAL/Platforms/MySQL80Platform.php | 17 - .../Doctrine/DBAL/Platforms/MySqlPlatform.php | 1187 ------ .../DBAL/Platforms/OraclePlatform.php | 1206 ------ .../DBAL/Platforms/PostgreSQL100Platform.php | 33 - .../DBAL/Platforms/PostgreSQL91Platform.php | 46 - .../DBAL/Platforms/PostgreSQL92Platform.php | 69 - .../DBAL/Platforms/PostgreSQL94Platform.php | 41 - .../DBAL/Platforms/PostgreSqlPlatform.php | 1270 ------ .../DBAL/Platforms/SQLAnywhere11Platform.php | 26 - .../DBAL/Platforms/SQLAnywhere12Platform.php | 114 - .../DBAL/Platforms/SQLAnywhere16Platform.php | 39 - .../DBAL/Platforms/SQLAnywherePlatform.php | 1512 ------- .../DBAL/Platforms/SQLAzurePlatform.php | 33 - .../DBAL/Platforms/SQLServer2005Platform.php | 46 - .../DBAL/Platforms/SQLServer2008Platform.php | 117 - .../DBAL/Platforms/SQLServer2012Platform.php | 143 - .../DBAL/Platforms/SQLServerPlatform.php | 1695 -------- .../DBAL/Platforms/SqlitePlatform.php | 1199 ------ .../lib/Doctrine/DBAL/Platforms/TrimMode.php | 20 - .../Doctrine/DBAL/Portability/Connection.php | 132 - .../Doctrine/DBAL/Portability/Statement.php | 247 -- .../Query/Expression/CompositeExpression.php | 120 - .../Query/Expression/ExpressionBuilder.php | 298 -- .../lib/Doctrine/DBAL/Query/QueryBuilder.php | 1373 ------- .../Doctrine/DBAL/Query/QueryException.php | 35 - .../dbal/lib/Doctrine/DBAL/SQLParserUtils.php | 291 -- .../Doctrine/DBAL/SQLParserUtilsException.php | 31 - .../Doctrine/DBAL/Schema/AbstractAsset.php | 210 - .../DBAL/Schema/AbstractSchemaManager.php | 1135 ----- .../dbal/lib/Doctrine/DBAL/Schema/Column.php | 451 -- .../lib/Doctrine/DBAL/Schema/ColumnDiff.php | 55 - .../lib/Doctrine/DBAL/Schema/Comparator.php | 533 --- .../lib/Doctrine/DBAL/Schema/Constraint.php | 43 - .../Doctrine/DBAL/Schema/DB2SchemaManager.php | 227 - .../DBAL/Schema/DrizzleSchemaManager.php | 103 - .../DBAL/Schema/ForeignKeyConstraint.php | 393 -- .../lib/Doctrine/DBAL/Schema/Identifier.php | 27 - .../dbal/lib/Doctrine/DBAL/Schema/Index.php | 359 -- .../DBAL/Schema/MySqlSchemaManager.php | 351 -- .../DBAL/Schema/OracleSchemaManager.php | 406 -- .../DBAL/Schema/PostgreSqlSchemaManager.php | 507 --- .../DBAL/Schema/SQLAnywhereSchemaManager.php | 231 -- .../DBAL/Schema/SQLServerSchemaManager.php | 349 -- .../dbal/lib/Doctrine/DBAL/Schema/Schema.php | 475 --- .../lib/Doctrine/DBAL/Schema/SchemaConfig.php | 100 - .../lib/Doctrine/DBAL/Schema/SchemaDiff.php | 168 - .../Doctrine/DBAL/Schema/SchemaException.php | 183 - .../lib/Doctrine/DBAL/Schema/Sequence.php | 139 - .../DBAL/Schema/SqliteSchemaManager.php | 545 --- .../AbstractSchemaSynchronizer.php | 43 - .../Synchronizer/SchemaSynchronizer.php | 72 - .../SingleDatabaseSynchronizer.php | 157 - .../dbal/lib/Doctrine/DBAL/Schema/Table.php | 856 ---- .../lib/Doctrine/DBAL/Schema/TableDiff.php | 152 - .../dbal/lib/Doctrine/DBAL/Schema/View.php | 30 - .../DBAL/Schema/Visitor/AbstractVisitor.php | 47 - .../Visitor/CreateSchemaSqlCollector.php | 98 - .../Schema/Visitor/DropSchemaSqlCollector.php | 99 - .../Doctrine/DBAL/Schema/Visitor/Graphviz.php | 160 - .../DBAL/Schema/Visitor/NamespaceVisitor.php | 16 - .../Schema/Visitor/RemoveNamespacedAssets.php | 79 - .../DBAL/Schema/Visitor/SchemaDiffVisitor.php | 39 - .../Doctrine/DBAL/Schema/Visitor/Visitor.php | 46 - .../DBAL/Sharding/PoolingShardConnection.php | 249 -- .../DBAL/Sharding/PoolingShardManager.php | 101 - .../SQLAzureFederationsSynchronizer.php | 271 -- .../SQLAzure/SQLAzureShardManager.php | 208 - .../SQLAzure/Schema/MultiTenantVisitor.php | 148 - .../ShardChoser/MultiTenantShardChoser.php | 20 - .../DBAL/Sharding/ShardChoser/ShardChoser.php | 21 - .../Doctrine/DBAL/Sharding/ShardManager.php | 74 - .../DBAL/Sharding/ShardingException.php | 59 - .../dbal/lib/Doctrine/DBAL/Statement.php | 286 -- .../Tools/Console/Command/ImportCommand.php | 138 - .../Console/Command/ReservedWordsCommand.php | 181 - .../Tools/Console/Command/RunSqlCommand.php | 74 - .../DBAL/Tools/Console/ConsoleRunner.php | 86 - .../Tools/Console/Helper/ConnectionHelper.php | 45 - .../dbal/lib/Doctrine/DBAL/Tools/Dumper.php | 182 - .../DBAL/TransactionIsolationLevel.php | 32 - .../lib/Doctrine/DBAL/Types/ArrayType.php | 72 - .../lib/Doctrine/DBAL/Types/BigIntType.php | 44 - .../lib/Doctrine/DBAL/Types/BinaryType.php | 66 - .../dbal/lib/Doctrine/DBAL/Types/BlobType.php | 66 - .../lib/Doctrine/DBAL/Types/BooleanType.php | 52 - .../DBAL/Types/ConversionException.php | 109 - .../Doctrine/DBAL/Types/DateImmutableType.php | 70 - .../Doctrine/DBAL/Types/DateIntervalType.php | 87 - .../DBAL/Types/DateTimeImmutableType.php | 75 - .../lib/Doctrine/DBAL/Types/DateTimeType.php | 68 - .../DBAL/Types/DateTimeTzImmutableType.php | 70 - .../Doctrine/DBAL/Types/DateTimeTzType.php | 75 - .../dbal/lib/Doctrine/DBAL/Types/DateType.php | 62 - .../lib/Doctrine/DBAL/Types/DecimalType.php | 35 - .../lib/Doctrine/DBAL/Types/FloatType.php | 32 - .../dbal/lib/Doctrine/DBAL/Types/GuidType.php | 35 - .../lib/Doctrine/DBAL/Types/IntegerType.php | 44 - .../lib/Doctrine/DBAL/Types/JsonArrayType.php | 46 - .../dbal/lib/Doctrine/DBAL/Types/JsonType.php | 82 - .../lib/Doctrine/DBAL/Types/ObjectType.php | 71 - .../DBAL/Types/PhpDateTimeMappingType.php | 12 - .../DBAL/Types/PhpIntegerMappingType.php | 12 - .../Doctrine/DBAL/Types/SimpleArrayType.php | 67 - .../lib/Doctrine/DBAL/Types/SmallIntType.php | 44 - .../lib/Doctrine/DBAL/Types/StringType.php | 35 - .../dbal/lib/Doctrine/DBAL/Types/TextType.php | 37 - .../Doctrine/DBAL/Types/TimeImmutableType.php | 70 - .../dbal/lib/Doctrine/DBAL/Types/TimeType.php | 62 - .../dbal/lib/Doctrine/DBAL/Types/Type.php | 384 -- .../lib/Doctrine/DBAL/Types/TypeRegistry.php | 118 - .../dbal/lib/Doctrine/DBAL/Types/Types.php | 43 - .../DBAL/Types/VarDateTimeImmutableType.php | 67 - .../Doctrine/DBAL/Types/VarDateTimeType.php | 34 - .../dbal/lib/Doctrine/DBAL/Version.php | 33 - .../DBAL/VersionAwarePlatformDriver.php | 28 - .../doctrine-bundle/.github/FUNDING.yml | 3 - .../Command/CreateDatabaseDoctrineCommand.php | 114 - .../Command/DoctrineCommand.php | 90 - .../Command/DropDatabaseDoctrineCommand.php | 128 - .../Command/ImportMappingDoctrineCommand.php | 161 - .../ClearMetadataCacheDoctrineCommand.php | 37 - .../Proxy/ClearQueryCacheDoctrineCommand.php | 37 - .../Proxy/ClearResultCacheDoctrineCommand.php | 37 - .../Proxy/CollectionRegionDoctrineCommand.php | 33 - .../Proxy/ConvertMappingDoctrineCommand.php | 58 - .../Proxy/CreateSchemaDoctrineCommand.php | 38 - .../Command/Proxy/DelegateCommand.php | 96 - .../Command/Proxy/DoctrineCommandHelper.php | 41 - .../Proxy/DropSchemaDoctrineCommand.php | 37 - ...nsureProductionSettingsDoctrineCommand.php | 36 - .../EntityRegionCacheDoctrineCommand.php | 33 - .../Command/Proxy/ImportDoctrineCommand.php | 36 - .../Command/Proxy/InfoDoctrineCommand.php | 34 - .../Proxy/QueryRegionCacheDoctrineCommand.php | 33 - .../Command/Proxy/RunDqlDoctrineCommand.php | 53 - .../Command/Proxy/RunSqlDoctrineCommand.php | 43 - .../Proxy/UpdateSchemaDoctrineCommand.php | 37 - .../Command/Proxy/ValidateSchemaCommand.php | 36 - .../doctrine-bundle/ConnectionFactory.php | 134 - .../Controller/ProfilerController.php | 120 - .../DataCollector/DoctrineDataCollector.php | 260 -- .../Dbal/BlacklistSchemaAssetFilter.php | 29 - .../Dbal/Logging/BacktraceLogger.php | 23 - .../Dbal/RegexSchemaAssetFilter.php | 25 - .../Dbal/SchemaAssetsFilterManager.php | 31 - .../Compiler/DbalSchemaFilterPass.php | 51 - .../Compiler/DoctrineOrmMappingsPass.php | 152 - .../Compiler/EntityListenerPass.php | 144 - .../ServiceRepositoryCompilerPass.php | 32 - .../Compiler/WellKnownSchemaFilterPass.php | 59 - .../DependencyInjection/Configuration.php | 702 ---- .../DependencyInjection/DoctrineExtension.php | 870 ---- .../doctrine-bundle/DoctrineBundle.php | 137 - vendor/doctrine/doctrine-bundle/LICENSE | 13 - .../doctrine-bundle/ManagerConfigurator.php | 74 - .../Mapping/ClassMetadataCollection.php | 65 - .../ContainerEntityListenerResolver.php | 103 - .../Mapping/DisconnectedMetadataFactory.php | 204 - .../Mapping/EntityListenerServiceResolver.php | 14 - vendor/doctrine/doctrine-bundle/README.md | 24 - vendor/doctrine/doctrine-bundle/Registry.php | 75 - .../Repository/ContainerRepositoryFactory.php | 86 - .../Repository/ServiceEntityRepository.php | 41 - .../ServiceEntityRepositoryInterface.php | 10 - .../doctrine-bundle/Resources/config/dbal.xml | 105 - .../Resources/config/messenger.xml | 44 - .../doctrine-bundle/Resources/config/orm.xml | 213 - .../Resources/config/schema/doctrine-1.0.xsd | 271 -- .../Resources/views/Collector/db.html.twig | 528 --- .../views/Collector/explain.html.twig | 28 - .../Resources/views/Collector/icon.svg | 4 - .../Twig/DoctrineExtension.php | 203 - .../doctrine/doctrine-bundle/UPGRADE-1.11.md | 35 - .../doctrine/doctrine-bundle/UPGRADE-1.12.md | 17 - .../doctrine/doctrine-bundle/UPGRADE-2.0.md | 63 - .../doctrine/doctrine-bundle/UPGRADE-3.0.md | 8 - vendor/doctrine/doctrine-bundle/composer.json | 75 - .../doctrine/doctrine-bundle/phpcs.xml.dist | 53 - .../.github/FUNDING.yml | 3 - .../doctrine-fixtures-bundle/.gitignore | 3 - .../doctrine-fixtures-bundle/.travis.yml | 45 - .../doctrine-fixtures-bundle/CHANGELOG-3.1.md | 14 - .../LoadDataFixturesDoctrineCommand.php | 131 - .../CompilerPass/FixturesCompilerPass.php | 39 - .../DoctrineFixturesExtension.php | 29 - .../DoctrineFixturesBundle.php | 21 - .../doctrine-fixtures-bundle/Fixture.php | 15 - .../FixtureGroupInterface.php | 19 - .../doctrine/doctrine-fixtures-bundle/LICENSE | 13 - .../Loader/SymfonyFixturesLoader.php | 150 - .../ORMFixtureInterface.php | 14 - .../doctrine-fixtures-bundle/README.markdown | 7 - .../Resources/config/services.xml | 18 - .../Resources/doc/index.rst | 293 -- .../LoadDataFixturesDoctrineCommandTest.php | 43 - ...ndentOnRequiredConstructorArgsFixtures.php | 22 - .../FooBundle/DataFixtures/OtherFixtures.php | 22 - .../RequiredConstructorArgsFixtures.php | 20 - .../DataFixtures/WithDependenciesFixtures.php | 28 - .../Tests/Fixtures/FooBundle/FooBundle.php | 11 - .../Tests/IntegrationTest.php | 366 -- .../doctrine-fixtures-bundle/UPGRADE.md | 56 - .../doctrine-fixtures-bundle/composer.json | 49 - .../doctrine-fixtures-bundle/phpcs.xml.dist | 35 - .../doctrine-fixtures-bundle/phpunit.xml.dist | 24 - .../event-manager/.doctrine-project.json | 18 - vendor/doctrine/event-manager/LICENSE | 19 - vendor/doctrine/event-manager/README.md | 13 - vendor/doctrine/event-manager/composer.json | 50 - .../lib/Doctrine/Common/EventArgs.php | 45 - .../lib/Doctrine/Common/EventManager.php | 132 - .../lib/Doctrine/Common/EventSubscriber.php | 21 - vendor/doctrine/inflector/LICENSE | 19 - vendor/doctrine/inflector/README.md | 6 - vendor/doctrine/inflector/composer.json | 32 - vendor/doctrine/inflector/docs/en/index.rst | 125 - .../Doctrine/Common/Inflector/Inflector.php | 492 --- .../instantiator/.doctrine-project.json | 26 - .../doctrine/instantiator/.github/FUNDING.yml | 3 - vendor/doctrine/instantiator/CONTRIBUTING.md | 35 - vendor/doctrine/instantiator/LICENSE | 19 - vendor/doctrine/instantiator/README.md | 39 - vendor/doctrine/instantiator/composer.json | 47 - .../doctrine/instantiator/docs/en/index.rst | 68 - .../doctrine/instantiator/docs/en/sidebar.rst | 4 - vendor/doctrine/instantiator/phpbench.json | 4 - vendor/doctrine/instantiator/phpcs.xml.dist | 35 - .../doctrine/instantiator/phpstan.neon.dist | 19 - .../Exception/ExceptionInterface.php | 12 - .../Exception/InvalidArgumentException.php | 37 - .../Exception/UnexpectedValueException.php | 48 - .../Doctrine/Instantiator/Instantiator.php | 203 - .../Instantiator/InstantiatorInterface.php | 20 - vendor/doctrine/lexer/LICENSE | 19 - vendor/doctrine/lexer/README.md | 9 - vendor/doctrine/lexer/composer.json | 41 - .../Doctrine/Common/Lexer/AbstractLexer.php | 328 -- vendor/doctrine/orm/.scrutinizer.yml | 34 - vendor/doctrine/orm/LICENSE | 19 - vendor/doctrine/orm/README.md | 26 - vendor/doctrine/orm/SECURITY.md | 18 - vendor/doctrine/orm/UPGRADE.md | 865 ---- vendor/doctrine/orm/bin/doctrine | 4 - vendor/doctrine/orm/bin/doctrine-pear.php | 50 - vendor/doctrine/orm/bin/doctrine.bat | 9 - vendor/doctrine/orm/bin/doctrine.php | 69 - vendor/doctrine/orm/composer.json | 57 - vendor/doctrine/orm/composer.lock | 2744 ------------- vendor/doctrine/orm/docs/LICENSE.md | 363 -- vendor/doctrine/orm/docs/README.md | 18 - vendor/doctrine/orm/docs/bin/generate-docs.sh | 10 - .../orm/docs/bin/install-dependencies.sh | 2 - vendor/doctrine/orm/docs/en/Makefile | 89 - .../orm/docs/en/_exts/configurationblock.py | 93 - vendor/doctrine/orm/docs/en/conf.py | 201 - ...-conversion-using-custom-mapping-types.rst | 256 -- .../orm/docs/en/cookbook/aggregate-fields.rst | 376 -- .../docs/en/cookbook/custom-mapping-types.rst | 101 - .../docs/en/cookbook/decorator-pattern.rst | 273 -- .../docs/en/cookbook/dql-custom-walkers.rst | 217 - .../cookbook/dql-user-defined-functions.rst | 251 -- .../docs/en/cookbook/entities-in-session.rst | 68 - ...menting-arrayaccess-for-domain-objects.rst | 112 - ...nting-the-notify-changetracking-policy.rst | 72 - .../cookbook/implementing-wakeup-or-clone.rst | 78 - .../orm/docs/en/cookbook/mysql-enums.rst | 199 - .../resolve-target-entity-listener.rst | 142 - .../docs/en/cookbook/sql-table-prefixes.rst | 86 - .../strategy-cookbook-introduction.rst | 254 -- .../en/cookbook/validation-of-entities.rst | 137 - .../en/cookbook/working-with-datetime.rst | 197 - vendor/doctrine/orm/docs/en/index.rst | 128 - vendor/doctrine/orm/docs/en/make.bat | 113 - .../en/reference/advanced-configuration.rst | 470 --- .../en/reference/annotations-reference.rst | 1327 ------ .../orm/docs/en/reference/architecture.rst | 197 - .../docs/en/reference/association-mapping.rst | 1130 ----- .../orm/docs/en/reference/basic-mapping.rst | 504 --- .../docs/en/reference/batch-processing.rst | 196 - .../orm/docs/en/reference/best-practices.rst | 111 - .../orm/docs/en/reference/caching.rst | 477 --- .../en/reference/change-tracking-policies.rst | 151 - .../orm/docs/en/reference/configuration.rst | 144 - .../reference/dql-doctrine-query-language.rst | 1775 -------- .../doctrine/orm/docs/en/reference/events.rst | 989 ----- vendor/doctrine/orm/docs/en/reference/faq.rst | 233 -- .../orm/docs/en/reference/filters.rst | 93 - .../en/reference/improving-performance.rst | 73 - .../docs/en/reference/inheritance-mapping.rst | 606 --- .../orm/docs/en/reference/installation.rst | 4 - .../limitations-and-known-issues.rst | 203 - .../docs/en/reference/metadata-drivers.rst | 194 - .../orm/docs/en/reference/namingstrategy.rst | 137 - .../orm/docs/en/reference/native-sql.rst | 905 ---- .../orm/docs/en/reference/partial-objects.rst | 90 - .../orm/docs/en/reference/php-mapping.rst | 325 -- .../orm/docs/en/reference/query-builder.rst | 584 --- .../docs/en/reference/second-level-cache.rst | 731 ---- .../orm/docs/en/reference/security.rst | 151 - .../doctrine/orm/docs/en/reference/tools.rst | 520 --- .../transactions-and-concurrency.rst | 409 -- .../en/reference/unitofwork-associations.rst | 60 - .../orm/docs/en/reference/unitofwork.rst | 201 - .../reference/working-with-associations.rst | 728 ---- .../en/reference/working-with-objects.rst | 865 ---- .../orm/docs/en/reference/xml-mapping.rst | 782 ---- .../orm/docs/en/reference/yaml-mapping.rst | 158 - vendor/doctrine/orm/docs/en/sidebar.rst | 83 - vendor/doctrine/orm/docs/en/toc.rst | 86 - .../en/tutorials/composite-primary-keys.rst | 375 -- .../orm/docs/en/tutorials/embeddables.rst | 179 - .../en/tutorials/extra-lazy-associations.rst | 86 - .../en/tutorials/getting-started-database.rst | 27 - .../en/tutorials/getting-started-models.rst | 24 - .../orm/docs/en/tutorials/getting-started.rst | 1618 -------- .../en/tutorials/ordered-associations.rst | 110 - ...eld-association-mappings-in-subclasses.rst | 92 - .../orm/docs/en/tutorials/pagination.rst | 43 - .../working-with-indexed-associations.rst | 296 -- vendor/doctrine/orm/doctrine-mapping.xsd | 622 --- .../orm/lib/Doctrine/ORM/AbstractQuery.php | 1165 ------ .../doctrine/orm/lib/Doctrine/ORM/Cache.php | 178 - .../ORM/Cache/AssociationCacheEntry.php | 68 - .../Doctrine/ORM/Cache/CacheConfiguration.php | 128 - .../orm/lib/Doctrine/ORM/Cache/CacheEntry.php | 36 - .../lib/Doctrine/ORM/Cache/CacheException.php | 73 - .../lib/Doctrine/ORM/Cache/CacheFactory.php | 112 - .../orm/lib/Doctrine/ORM/Cache/CacheKey.php | 38 - .../ORM/Cache/CollectionCacheEntry.php | 59 - .../Doctrine/ORM/Cache/CollectionCacheKey.php | 66 - .../Doctrine/ORM/Cache/CollectionHydrator.php | 52 - .../Doctrine/ORM/Cache/ConcurrentRegion.php | 57 - .../lib/Doctrine/ORM/Cache/DefaultCache.php | 342 -- .../ORM/Cache/DefaultCacheFactory.php | 275 -- .../ORM/Cache/DefaultCollectionHydrator.php | 104 - .../ORM/Cache/DefaultEntityHydrator.php | 205 - .../Doctrine/ORM/Cache/DefaultQueryCache.php | 478 --- .../Doctrine/ORM/Cache/EntityCacheEntry.php | 88 - .../lib/Doctrine/ORM/Cache/EntityCacheKey.php | 57 - .../lib/Doctrine/ORM/Cache/EntityHydrator.php | 49 - .../orm/lib/Doctrine/ORM/Cache/Lock.php | 58 - .../lib/Doctrine/ORM/Cache/LockException.php | 32 - .../ORM/Cache/Logging/CacheLogger.php | 106 - .../ORM/Cache/Logging/CacheLoggerChain.php | 156 - .../Cache/Logging/StatisticsCacheLogger.php | 251 -- .../lib/Doctrine/ORM/Cache/MultiGetRegion.php | 42 - .../ORM/Cache/Persister/CachedPersister.php | 46 - .../AbstractCollectionPersister.php | 313 -- .../Collection/CachedCollectionPersister.php | 65 - ...rictReadWriteCachedCollectionPersister.php | 104 - .../ReadOnlyCachedCollectionPersister.php | 44 - .../ReadWriteCachedCollectionPersister.php | 134 - .../Entity/AbstractEntityPersister.php | 652 --- .../Entity/CachedEntityPersister.php | 47 - ...onStrictReadWriteCachedEntityPersister.php | 117 - .../Entity/ReadOnlyCachedEntityPersister.php | 41 - .../Entity/ReadWriteCachedEntityPersister.php | 143 - .../orm/lib/Doctrine/ORM/Cache/QueryCache.php | 62 - .../Doctrine/ORM/Cache/QueryCacheEntry.php | 64 - .../lib/Doctrine/ORM/Cache/QueryCacheKey.php | 71 - .../ORM/Cache/QueryCacheValidator.php | 40 - .../orm/lib/Doctrine/ORM/Cache/Region.php | 84 - .../Cache/Region/DefaultMultiGetRegion.php | 82 - .../ORM/Cache/Region/DefaultRegion.php | 166 - .../ORM/Cache/Region/FileLockRegion.php | 265 -- .../ORM/Cache/Region/UpdateTimestampCache.php | 42 - .../ORM/Cache/RegionsConfiguration.php | 134 - .../ORM/Cache/TimestampCacheEntry.php | 59 - .../Doctrine/ORM/Cache/TimestampCacheKey.php | 38 - .../Cache/TimestampQueryCacheValidator.php | 74 - .../Doctrine/ORM/Cache/TimestampRegion.php | 39 - .../orm/lib/Doctrine/ORM/Configuration.php | 920 ----- .../ORM/Decorator/EntityManagerDecorator.php | 278 -- .../orm/lib/Doctrine/ORM/EntityManager.php | 960 ----- .../Doctrine/ORM/EntityManagerInterface.php | 298 -- .../Doctrine/ORM/EntityNotFoundException.php | 51 - .../orm/lib/Doctrine/ORM/EntityRepository.php | 313 -- .../Doctrine/ORM/Event/LifecycleEventArgs.php | 54 - .../Doctrine/ORM/Event/ListenersInvoker.php | 120 - .../ORM/Event/LoadClassMetadataEventArgs.php | 46 - .../OnClassMetadataNotFoundEventArgs.php | 86 - .../Doctrine/ORM/Event/OnClearEventArgs.php | 86 - .../Doctrine/ORM/Event/OnFlushEventArgs.php | 61 - .../Doctrine/ORM/Event/PostFlushEventArgs.php | 58 - .../Doctrine/ORM/Event/PreFlushEventArgs.php | 58 - .../Doctrine/ORM/Event/PreUpdateEventArgs.php | 137 - .../doctrine/orm/lib/Doctrine/ORM/Events.php | 167 - .../Doctrine/ORM/Id/AbstractIdGenerator.php | 49 - .../lib/Doctrine/ORM/Id/AssignedGenerator.php | 66 - .../ORM/Id/BigIntegerIdentityGenerator.php | 66 - .../lib/Doctrine/ORM/Id/IdentityGenerator.php | 65 - .../lib/Doctrine/ORM/Id/SequenceGenerator.php | 132 - .../lib/Doctrine/ORM/Id/TableGenerator.php | 109 - .../orm/lib/Doctrine/ORM/Id/UuidGenerator.php | 42 - .../ORM/Internal/CommitOrderCalculator.php | 195 - .../Internal/Hydration/AbstractHydrator.php | 527 --- .../ORM/Internal/Hydration/ArrayHydrator.php | 307 -- .../Internal/Hydration/HydrationException.php | 105 - .../ORM/Internal/Hydration/IterableResult.php | 110 - .../ORM/Internal/Hydration/ObjectHydrator.php | 593 --- .../ORM/Internal/Hydration/ScalarHydrator.php | 54 - .../Hydration/SimpleObjectHydrator.php | 154 - .../Hydration/SingleScalarHydrator.php | 58 - .../ORM/Internal/HydrationCompleteHandler.php | 103 - .../Doctrine/ORM/LazyCriteriaCollection.php | 133 - .../lib/Doctrine/ORM/Mapping/Annotation.php | 24 - .../ORM/Mapping/AnsiQuoteStrategy.php | 96 - .../ORM/Mapping/AssociationOverride.php | 69 - .../ORM/Mapping/AssociationOverrides.php | 39 - .../ORM/Mapping/AttributeOverride.php | 46 - .../ORM/Mapping/AttributeOverrides.php | 39 - .../Mapping/Builder/AssociationBuilder.php | 244 -- .../Mapping/Builder/ClassMetadataBuilder.php | 553 --- .../ORM/Mapping/Builder/EmbeddedBuilder.php | 80 - .../Mapping/Builder/EntityListenerBuilder.php | 72 - .../ORM/Mapping/Builder/FieldBuilder.php | 296 -- .../Builder/ManyToManyAssociationBuilder.php | 101 - .../Builder/OneToManyAssociationBuilder.php | 70 - .../orm/lib/Doctrine/ORM/Mapping/Cache.php | 44 - .../ORM/Mapping/ChangeTrackingPolicy.php | 36 - .../Doctrine/ORM/Mapping/ClassMetadata.php | 29 - .../ORM/Mapping/ClassMetadataFactory.php | 797 ---- .../ORM/Mapping/ClassMetadataInfo.php | 3402 --------------- .../orm/lib/Doctrine/ORM/Mapping/Column.php | 76 - .../lib/Doctrine/ORM/Mapping/ColumnResult.php | 40 - .../ORM/Mapping/CustomIdGenerator.php | 32 - .../Mapping/DefaultEntityListenerResolver.php | 75 - .../ORM/Mapping/DefaultNamingStrategy.php | 94 - .../ORM/Mapping/DefaultQuoteStrategy.php | 164 - .../ORM/Mapping/DiscriminatorColumn.php | 54 - .../Doctrine/ORM/Mapping/DiscriminatorMap.php | 32 - .../ORM/Mapping/Driver/AnnotationDriver.php | 673 --- .../ORM/Mapping/Driver/DatabaseDriver.php | 557 --- .../Mapping/Driver/DoctrineAnnotations.php | 69 - .../ORM/Mapping/Driver/DriverChain.php | 31 - .../Doctrine/ORM/Mapping/Driver/PHPDriver.php | 31 - .../Mapping/Driver/SimplifiedXmlDriver.php | 43 - .../Mapping/Driver/SimplifiedYamlDriver.php | 43 - .../ORM/Mapping/Driver/StaticPHPDriver.php | 31 - .../Doctrine/ORM/Mapping/Driver/XmlDriver.php | 881 ---- .../ORM/Mapping/Driver/YamlDriver.php | 819 ---- .../lib/Doctrine/ORM/Mapping/Embeddable.php | 28 - .../orm/lib/Doctrine/ORM/Mapping/Embedded.php | 38 - .../orm/lib/Doctrine/ORM/Mapping/Entity.php | 37 - .../ORM/Mapping/EntityListenerResolver.php | 55 - .../Doctrine/ORM/Mapping/EntityListeners.php | 41 - .../lib/Doctrine/ORM/Mapping/EntityResult.php | 56 - .../lib/Doctrine/ORM/Mapping/FieldResult.php | 46 - .../Doctrine/ORM/Mapping/GeneratedValue.php | 36 - .../ORM/Mapping/HasLifecycleCallbacks.php | 28 - .../orm/lib/Doctrine/ORM/Mapping/Id.php | 28 - .../orm/lib/Doctrine/ORM/Mapping/Index.php | 47 - .../Doctrine/ORM/Mapping/InheritanceType.php | 36 - .../lib/Doctrine/ORM/Mapping/JoinColumn.php | 64 - .../lib/Doctrine/ORM/Mapping/JoinColumns.php | 32 - .../lib/Doctrine/ORM/Mapping/JoinTable.php | 47 - .../lib/Doctrine/ORM/Mapping/ManyToMany.php | 66 - .../lib/Doctrine/ORM/Mapping/ManyToOne.php | 51 - .../Doctrine/ORM/Mapping/MappedSuperclass.php | 32 - .../Doctrine/ORM/Mapping/MappingException.php | 823 ---- .../ORM/Mapping/NamedNativeQueries.php | 40 - .../Doctrine/ORM/Mapping/NamedNativeQuery.php | 61 - .../lib/Doctrine/ORM/Mapping/NamedQueries.php | 32 - .../lib/Doctrine/ORM/Mapping/NamedQuery.php | 37 - .../Doctrine/ORM/Mapping/NamingStrategy.php | 100 - .../lib/Doctrine/ORM/Mapping/OneToMany.php | 61 - .../orm/lib/Doctrine/ORM/Mapping/OneToOne.php | 61 - .../orm/lib/Doctrine/ORM/Mapping/OrderBy.php | 32 - .../orm/lib/Doctrine/ORM/Mapping/PostLoad.php | 28 - .../lib/Doctrine/ORM/Mapping/PostPersist.php | 28 - .../lib/Doctrine/ORM/Mapping/PostRemove.php | 28 - .../lib/Doctrine/ORM/Mapping/PostUpdate.php | 28 - .../orm/lib/Doctrine/ORM/Mapping/PreFlush.php | 28 - .../lib/Doctrine/ORM/Mapping/PrePersist.php | 28 - .../lib/Doctrine/ORM/Mapping/PreRemove.php | 28 - .../lib/Doctrine/ORM/Mapping/PreUpdate.php | 28 - .../Doctrine/ORM/Mapping/QuoteStrategy.php | 119 - .../Reflection/ReflectionPropertiesGetter.php | 163 - .../Mapping/ReflectionEmbeddedProperty.php | 101 - .../ORM/Mapping/SequenceGenerator.php | 42 - .../ORM/Mapping/SqlResultSetMapping.php | 54 - .../ORM/Mapping/SqlResultSetMappings.php | 40 - .../orm/lib/Doctrine/ORM/Mapping/Table.php | 52 - .../ORM/Mapping/UnderscoreNamingStrategy.php | 166 - .../Doctrine/ORM/Mapping/UniqueConstraint.php | 42 - .../orm/lib/Doctrine/ORM/Mapping/Version.php | 28 - .../orm/lib/Doctrine/ORM/NativeQuery.php | 92 - .../lib/Doctrine/ORM/NoResultException.php | 37 - .../Doctrine/ORM/NonUniqueResultException.php | 36 - .../orm/lib/Doctrine/ORM/ORMException.php | 333 -- .../ORM/ORMInvalidArgumentException.php | 272 -- .../Doctrine/ORM/OptimisticLockException.php | 91 - .../lib/Doctrine/ORM/PersistentCollection.php | 734 ---- .../AbstractCollectionPersister.php | 95 - .../Collection/CollectionPersister.php | 122 - .../Collection/ManyToManyPersister.php | 787 ---- .../Collection/OneToManyPersister.php | 291 -- .../AbstractEntityInheritancePersister.php | 99 - .../Entity/BasicEntityPersister.php | 2095 ---------- .../Entity/CachedPersisterContext.php | 102 - .../ORM/Persisters/Entity/EntityPersister.php | 330 -- .../Entity/JoinedSubclassPersister.php | 616 --- .../Entity/SingleTablePersister.php | 192 - .../ORM/Persisters/PersisterException.php | 40 - .../ORM/Persisters/SqlExpressionVisitor.php | 122 - .../ORM/Persisters/SqlValueVisitor.php | 128 - .../Doctrine/ORM/PessimisticLockException.php | 40 - .../orm/lib/Doctrine/ORM/Proxy/Autoloader.php | 29 - .../orm/lib/Doctrine/ORM/Proxy/Proxy.php | 34 - .../lib/Doctrine/ORM/Proxy/ProxyFactory.php | 213 - .../doctrine/orm/lib/Doctrine/ORM/Query.php | 794 ---- .../Doctrine/ORM/Query/AST/ASTException.php | 38 - .../ORM/Query/AST/AggregateExpression.php | 69 - .../ORM/Query/AST/ArithmeticExpression.php | 66 - .../ORM/Query/AST/ArithmeticFactor.php | 78 - .../Doctrine/ORM/Query/AST/ArithmeticTerm.php | 53 - .../ORM/Query/AST/BetweenExpression.php | 72 - .../ORM/Query/AST/CoalesceExpression.php | 55 - .../Query/AST/CollectionMemberExpression.php | 63 - .../ORM/Query/AST/ComparisonExpression.php | 72 - .../ORM/Query/AST/ConditionalExpression.php | 53 - .../ORM/Query/AST/ConditionalFactor.php | 58 - .../ORM/Query/AST/ConditionalPrimary.php | 66 - .../ORM/Query/AST/ConditionalTerm.php | 52 - .../Doctrine/ORM/Query/AST/DeleteClause.php | 58 - .../ORM/Query/AST/DeleteStatement.php | 58 - .../EmptyCollectionComparisonExpression.php | 58 - .../ORM/Query/AST/ExistsExpression.php | 58 - .../lib/Doctrine/ORM/Query/AST/FromClause.php | 54 - .../ORM/Query/AST/Functions/AbsFunction.php | 66 - .../ORM/Query/AST/Functions/AvgFunction.php | 54 - .../Query/AST/Functions/BitAndFunction.php | 66 - .../ORM/Query/AST/Functions/BitOrFunction.php | 66 - .../Query/AST/Functions/ConcatFunction.php | 85 - .../ORM/Query/AST/Functions/CountFunction.php | 54 - .../AST/Functions/CurrentDateFunction.php | 56 - .../AST/Functions/CurrentTimeFunction.php | 56 - .../Functions/CurrentTimestampFunction.php | 56 - .../Query/AST/Functions/DateAddFunction.php | 109 - .../Query/AST/Functions/DateDiffFunction.php | 66 - .../Query/AST/Functions/DateSubFunction.php | 85 - .../ORM/Query/AST/Functions/FunctionNode.php | 73 - .../Query/AST/Functions/IdentityFunction.php | 113 - .../Query/AST/Functions/LengthFunction.php | 63 - .../Query/AST/Functions/LocateFunction.php | 86 - .../ORM/Query/AST/Functions/LowerFunction.php | 63 - .../ORM/Query/AST/Functions/MaxFunction.php | 54 - .../ORM/Query/AST/Functions/MinFunction.php | 54 - .../ORM/Query/AST/Functions/ModFunction.php | 76 - .../ORM/Query/AST/Functions/SizeFunction.php | 125 - .../ORM/Query/AST/Functions/SqrtFunction.php | 66 - .../Query/AST/Functions/SubstringFunction.php | 91 - .../ORM/Query/AST/Functions/SumFunction.php | 54 - .../ORM/Query/AST/Functions/TrimFunction.php | 161 - .../ORM/Query/AST/Functions/UpperFunction.php | 63 - .../ORM/Query/AST/GeneralCaseExpression.php | 62 - .../Doctrine/ORM/Query/AST/GroupByClause.php | 53 - .../Doctrine/ORM/Query/AST/HavingClause.php | 53 - .../AST/IdentificationVariableDeclaration.php | 67 - .../Doctrine/ORM/Query/AST/InExpression.php | 67 - .../lib/Doctrine/ORM/Query/AST/IndexBy.php | 53 - .../Doctrine/ORM/Query/AST/InputParameter.php | 66 - .../ORM/Query/AST/InstanceOfExpression.php | 64 - .../orm/lib/Doctrine/ORM/Query/AST/Join.php | 70 - .../Query/AST/JoinAssociationDeclaration.php | 65 - .../AST/JoinAssociationPathExpression.php | 60 - .../ORM/Query/AST/JoinClassPathExpression.php | 59 - .../ORM/Query/AST/JoinVariableDeclaration.php | 61 - .../Doctrine/ORM/Query/AST/LikeExpression.php | 71 - .../lib/Doctrine/ORM/Query/AST/Literal.php | 55 - .../ORM/Query/AST/NewObjectExpression.php | 58 - .../orm/lib/Doctrine/ORM/Query/AST/Node.php | 103 - .../Query/AST/NullComparisonExpression.php | 58 - .../ORM/Query/AST/NullIfExpression.php | 62 - .../Doctrine/ORM/Query/AST/OrderByClause.php | 53 - .../Doctrine/ORM/Query/AST/OrderByItem.php | 75 - .../ORM/Query/AST/ParenthesisExpression.php | 51 - .../ORM/Query/AST/PartialObjectExpression.php | 43 - .../Doctrine/ORM/Query/AST/PathExpression.php | 81 - .../ORM/Query/AST/QuantifiedExpression.php | 81 - .../Query/AST/RangeVariableDeclaration.php | 67 - .../Doctrine/ORM/Query/AST/SelectClause.php | 60 - .../ORM/Query/AST/SelectExpression.php | 68 - .../ORM/Query/AST/SelectStatement.php | 80 - .../Query/AST/SimpleArithmeticExpression.php | 53 - .../ORM/Query/AST/SimpleCaseExpression.php | 69 - .../ORM/Query/AST/SimpleSelectClause.php | 60 - .../ORM/Query/AST/SimpleSelectExpression.php | 59 - .../ORM/Query/AST/SimpleWhenClause.php | 62 - .../lib/Doctrine/ORM/Query/AST/Subselect.php | 80 - .../ORM/Query/AST/SubselectFromClause.php | 53 - ...electIdentificationVariableDeclaration.php | 52 - .../Doctrine/ORM/Query/AST/UpdateClause.php | 65 - .../lib/Doctrine/ORM/Query/AST/UpdateItem.php | 62 - .../ORM/Query/AST/UpdateStatement.php | 58 - .../lib/Doctrine/ORM/Query/AST/WhenClause.php | 62 - .../Doctrine/ORM/Query/AST/WhereClause.php | 53 - .../ORM/Query/Exec/AbstractSqlExecutor.php | 86 - .../Query/Exec/MultiTableDeleteExecutor.php | 146 - .../Query/Exec/MultiTableUpdateExecutor.php | 205 - .../ORM/Query/Exec/SingleSelectExecutor.php | 52 - .../Exec/SingleTableDeleteUpdateExecutor.php | 57 - .../orm/lib/Doctrine/ORM/Query/Expr.php | 674 --- .../orm/lib/Doctrine/ORM/Query/Expr/Andx.php | 55 - .../orm/lib/Doctrine/ORM/Query/Expr/Base.php | 124 - .../Doctrine/ORM/Query/Expr/Comparison.php | 100 - .../lib/Doctrine/ORM/Query/Expr/Composite.php | 71 - .../orm/lib/Doctrine/ORM/Query/Expr/From.php | 92 - .../orm/lib/Doctrine/ORM/Query/Expr/Func.php | 78 - .../lib/Doctrine/ORM/Query/Expr/GroupBy.php | 50 - .../orm/lib/Doctrine/ORM/Query/Expr/Join.php | 145 - .../lib/Doctrine/ORM/Query/Expr/Literal.php | 50 - .../orm/lib/Doctrine/ORM/Query/Expr/Math.php | 107 - .../lib/Doctrine/ORM/Query/Expr/OrderBy.php | 104 - .../orm/lib/Doctrine/ORM/Query/Expr/Orx.php | 55 - .../lib/Doctrine/ORM/Query/Expr/Select.php | 55 - .../Doctrine/ORM/Query/Filter/SQLFilter.php | 155 - .../Doctrine/ORM/Query/FilterCollection.php | 225 - .../orm/lib/Doctrine/ORM/Query/Lexer.php | 222 - .../orm/lib/Doctrine/ORM/Query/Parameter.php | 122 - .../ORM/Query/ParameterTypeInferer.php | 72 - .../orm/lib/Doctrine/ORM/Query/Parser.php | 3539 ---------------- .../lib/Doctrine/ORM/Query/ParserResult.php | 145 - .../orm/lib/Doctrine/ORM/Query/Printer.php | 98 - .../lib/Doctrine/ORM/Query/QueryException.php | 270 -- .../ORM/Query/QueryExpressionVisitor.php | 224 - .../Doctrine/ORM/Query/ResultSetMapping.php | 586 --- .../ORM/Query/ResultSetMappingBuilder.php | 473 --- .../orm/lib/Doctrine/ORM/Query/SqlWalker.php | 2324 ----------- .../orm/lib/Doctrine/ORM/Query/TreeWalker.php | 479 --- .../Doctrine/ORM/Query/TreeWalkerAdapter.php | 440 -- .../Doctrine/ORM/Query/TreeWalkerChain.php | 575 --- .../ORM/Query/TreeWalkerChainIterator.php | 138 - .../orm/lib/Doctrine/ORM/QueryBuilder.php | 1513 ------- .../Repository/DefaultRepositoryFactory.php | 70 - .../ORM/Repository/RepositoryFactory.php | 41 - .../Tools/AttachEntityListenersListener.php | 79 - .../ClearCache/CollectionRegionCommand.php | 149 - .../ClearCache/EntityRegionCommand.php | 140 - .../Command/ClearCache/MetadataCommand.php | 112 - .../Command/ClearCache/QueryCommand.php | 111 - .../Command/ClearCache/QueryRegionCommand.php | 131 - .../Command/ClearCache/ResultCommand.php | 112 - .../Command/ConvertDoctrine1SchemaCommand.php | 214 - .../Console/Command/ConvertMappingCommand.php | 186 - .../EnsureProductionSettingsCommand.php | 78 - .../Command/GenerateEntitiesCommand.php | 147 - .../Command/GenerateProxiesCommand.php | 110 - .../Command/GenerateRepositoriesCommand.php | 119 - .../ORM/Tools/Console/Command/InfoCommand.php | 101 - .../Command/MappingDescribeCommand.php | 284 -- .../Tools/Console/Command/RunDqlCommand.php | 116 - .../Command/SchemaTool/AbstractCommand.php | 72 - .../Command/SchemaTool/CreateCommand.php | 90 - .../Command/SchemaTool/DropCommand.php | 130 - .../Command/SchemaTool/UpdateCommand.php | 159 - .../Console/Command/ValidateSchemaCommand.php | 100 - .../ORM/Tools/Console/ConsoleRunner.php | 143 - .../Console/Helper/EntityManagerHelper.php | 71 - .../ORM/Tools/Console/MetadataFilter.php | 102 - .../ORM/Tools/ConvertDoctrine1Schema.php | 344 -- .../ORM/Tools/DebugUnitOfWorkListener.php | 185 - .../DisconnectedClassMetadataFactory.php | 48 - .../Doctrine/ORM/Tools/EntityGenerator.php | 1906 --------- .../ORM/Tools/EntityRepositoryGenerator.php | 182 - .../Tools/Event/GenerateSchemaEventArgs.php | 71 - .../Event/GenerateSchemaTableEventArgs.php | 86 - .../Tools/Export/ClassMetadataExporter.php | 86 - .../Tools/Export/Driver/AbstractExporter.php | 275 -- .../Export/Driver/AnnotationExporter.php | 82 - .../ORM/Tools/Export/Driver/PhpExporter.php | 202 - .../ORM/Tools/Export/Driver/XmlExporter.php | 496 --- .../ORM/Tools/Export/Driver/YamlExporter.php | 268 -- .../ORM/Tools/Export/ExportException.php | 58 - .../Tools/Pagination/CountOutputWalker.php | 154 - .../ORM/Tools/Pagination/CountWalker.php | 94 - .../Pagination/LimitSubqueryOutputWalker.php | 605 --- .../Tools/Pagination/LimitSubqueryWalker.php | 177 - .../ORM/Tools/Pagination/Paginator.php | 289 -- .../Pagination/RowNumberOverFunction.php | 62 - .../ORM/Tools/Pagination/WhereInWalker.php | 184 - .../ORM/Tools/ResolveTargetEntityListener.php | 144 - .../orm/lib/Doctrine/ORM/Tools/SchemaTool.php | 913 ----- .../Doctrine/ORM/Tools/SchemaValidator.php | 273 -- .../orm/lib/Doctrine/ORM/Tools/Setup.php | 195 - .../orm/lib/Doctrine/ORM/Tools/ToolEvents.php | 42 - .../lib/Doctrine/ORM/Tools/ToolsException.php | 46 - .../ORM/TransactionRequiredException.php | 40 - .../ORM/UnexpectedResultException.php | 30 - .../orm/lib/Doctrine/ORM/UnitOfWork.php | 3628 ---------------- .../HierarchyDiscriminatorResolver.php | 41 - .../ORM/Utility/IdentifierFlattener.php | 102 - .../Doctrine/ORM/Utility/PersisterHelper.php | 135 - .../doctrine/orm/lib/Doctrine/ORM/Version.php | 57 - vendor/doctrine/orm/phpbench.json | 15 - vendor/doctrine/orm/phpstan.neon | 4 - .../persistence/.doctrine-project.json | 24 - vendor/doctrine/persistence/LICENSE | 19 - vendor/doctrine/persistence/README.md | 13 - vendor/doctrine/persistence/UPGRADE-1.2.md | 6 - vendor/doctrine/persistence/composer.json | 54 - .../Doctrine/Common/NotifyPropertyChanged.php | 31 - .../Persistence/AbstractManagerRegistry.php | 31 - .../Common/Persistence/ConnectionRegistry.php | 31 - .../Persistence/Event/LifecycleEventArgs.php | 31 - .../Event/LoadClassMetadataEventArgs.php | 31 - .../Persistence/Event/ManagerEventArgs.php | 31 - .../Persistence/Event/OnClearEventArgs.php | 31 - .../Persistence/Event/PreUpdateEventArgs.php | 31 - .../Common/Persistence/ManagerRegistry.php | 31 - .../Mapping/AbstractClassMetadataFactory.php | 31 - .../Persistence/Mapping/ClassMetadata.php | 31 - .../Mapping/ClassMetadataFactory.php | 31 - .../Mapping/Driver/AnnotationDriver.php | 31 - .../Mapping/Driver/DefaultFileLocator.php | 31 - .../Persistence/Mapping/Driver/FileDriver.php | 31 - .../Mapping/Driver/FileLocator.php | 31 - .../Mapping/Driver/MappingDriver.php | 31 - .../Mapping/Driver/MappingDriverChain.php | 31 - .../Persistence/Mapping/Driver/PHPDriver.php | 31 - .../Mapping/Driver/StaticPHPDriver.php | 31 - .../Mapping/Driver/SymfonyFileLocator.php | 31 - .../Persistence/Mapping/MappingException.php | 31 - .../Persistence/Mapping/ReflectionService.php | 31 - .../Mapping/RuntimeReflectionService.php | 31 - .../Mapping/StaticReflectionService.php | 31 - .../Common/Persistence/ObjectManager.php | 31 - .../Common/Persistence/ObjectManagerAware.php | 31 - .../Persistence/ObjectManagerDecorator.php | 31 - .../Common/Persistence/ObjectRepository.php | 31 - .../Common/Persistence/PersistentObject.php | 235 -- .../lib/Doctrine/Common/Persistence/Proxy.php | 31 - .../Common/PropertyChangedListener.php | 31 - .../Persistence/AbstractManagerRegistry.php | 251 -- .../Persistence/ConnectionRegistry.php | 43 - .../Persistence/Event/LifecycleEventArgs.php | 63 - .../Event/LoadClassMetadataEventArgs.php | 48 - .../Persistence/Event/ManagerEventArgs.php | 33 - .../Persistence/Event/OnClearEventArgs.php | 61 - .../Persistence/Event/PreUpdateEventArgs.php | 116 - .../Doctrine/Persistence/ManagerRegistry.php | 92 - .../Mapping/AbstractClassMetadataFactory.php | 420 -- .../Persistence/Mapping/ClassMetadata.php | 157 - .../Mapping/ClassMetadataFactory.php | 57 - .../Mapping/Driver/AnnotationDriver.php | 258 -- .../Mapping/Driver/DefaultFileLocator.php | 164 - .../Persistence/Mapping/Driver/FileDriver.php | 199 - .../Mapping/Driver/FileLocator.php | 57 - .../Mapping/Driver/MappingDriver.php | 41 - .../Mapping/Driver/MappingDriverChain.php | 149 - .../Persistence/Mapping/Driver/PHPDriver.php | 49 - .../Mapping/Driver/StaticPHPDriver.php | 134 - .../Mapping/Driver/SymfonyFileLocator.php | 233 -- .../Persistence/Mapping/MappingException.php | 98 - .../Persistence/Mapping/ReflectionService.php | 74 - .../Mapping/RuntimeReflectionService.php | 89 - .../Mapping/StaticReflectionService.php | 74 - .../Persistence/NotifyPropertyChanged.php | 25 - .../Doctrine/Persistence/ObjectManager.php | 160 - .../Persistence/ObjectManagerAware.php | 34 - .../Persistence/ObjectManagerDecorator.php | 120 - .../Doctrine/Persistence/ObjectRepository.php | 64 - .../Persistence/PropertyChangedListener.php | 26 - .../lib/Doctrine/Persistence/Proxy.php | 39 - vendor/doctrine/reflection/.scrutinizer.yml | 29 - vendor/doctrine/reflection/LICENSE | 19 - vendor/doctrine/reflection/README.md | 13 - vendor/doctrine/reflection/composer.json | 44 - vendor/doctrine/reflection/docs/en/index.rst | 22 - .../reflection/docs/en/reference/index.rst | 85 - .../doctrine/reflection/docs/en/sidebar.rst | 4 - .../Reflection/ClassFinderInterface.php | 18 - .../Common/Reflection/Psr0FindFile.php | 70 - .../ReflectionProviderInterface.php | 31 - .../RuntimePublicReflectionProperty.php | 57 - .../Reflection/StaticReflectionClass.php | 413 -- .../Reflection/StaticReflectionMethod.php | 344 -- .../Reflection/StaticReflectionParser.php | 328 -- .../Reflection/StaticReflectionProperty.php | 160 - vendor/doctrine/reflection/phpstan.neon | 6 - vendor/jdorn/sql-formatter/.gitignore | 1 - vendor/jdorn/sql-formatter/.travis.yml | 5 - vendor/jdorn/sql-formatter/LICENSE.txt | 21 - vendor/jdorn/sql-formatter/README.md | 185 - vendor/jdorn/sql-formatter/composer.json | 30 - vendor/jdorn/sql-formatter/composer.lock | 422 -- vendor/jdorn/sql-formatter/examples/cli.php | 17 - .../jdorn/sql-formatter/examples/examples.php | 270 -- .../jdorn/sql-formatter/lib/SqlFormatter.php | 1080 ----- vendor/jdorn/sql-formatter/phpunit.xml.dist | 20 - .../sql-formatter/tests/SqlFormatterTest.php | 197 - .../sql-formatter/tests/clihighlight.html | 809 ---- .../jdorn/sql-formatter/tests/compress.html | 77 - .../sql-formatter/tests/format-highlight.html | 809 ---- vendor/jdorn/sql-formatter/tests/format.html | 807 ---- .../jdorn/sql-formatter/tests/highlight.html | 262 -- .../jdorn/sql-formatter/tests/performance.php | 44 - vendor/jdorn/sql-formatter/tests/sql.sql | 261 -- vendor/psr/cache/CHANGELOG.md | 16 - vendor/psr/cache/LICENSE.txt | 19 - vendor/psr/cache/README.md | 9 - vendor/psr/cache/composer.json | 25 - vendor/psr/cache/src/CacheException.php | 10 - vendor/psr/cache/src/CacheItemInterface.php | 105 - .../psr/cache/src/CacheItemPoolInterface.php | 138 - .../cache/src/InvalidArgumentException.php | 13 - vendor/psr/container/.gitignore | 3 - vendor/psr/container/LICENSE | 21 - vendor/psr/container/README.md | 5 - vendor/psr/container/composer.json | 27 - .../src/ContainerExceptionInterface.php | 13 - .../psr/container/src/ContainerInterface.php | 37 - .../src/NotFoundExceptionInterface.php | 13 - vendor/psr/event-dispatcher/.editorconfig | 15 - vendor/psr/event-dispatcher/.gitignore | 2 - vendor/psr/event-dispatcher/LICENSE | 21 - vendor/psr/event-dispatcher/README.md | 6 - vendor/psr/event-dispatcher/composer.json | 26 - .../src/EventDispatcherInterface.php | 21 - .../src/ListenerProviderInterface.php | 19 - .../src/StoppableEventInterface.php | 26 - vendor/psr/log/.gitignore | 1 - vendor/psr/log/LICENSE | 19 - vendor/psr/log/Psr/Log/AbstractLogger.php | 128 - .../log/Psr/Log/InvalidArgumentException.php | 7 - vendor/psr/log/Psr/Log/LogLevel.php | 18 - .../psr/log/Psr/Log/LoggerAwareInterface.php | 18 - vendor/psr/log/Psr/Log/LoggerAwareTrait.php | 26 - vendor/psr/log/Psr/Log/LoggerInterface.php | 125 - vendor/psr/log/Psr/Log/LoggerTrait.php | 142 - vendor/psr/log/Psr/Log/NullLogger.php | 30 - .../log/Psr/Log/Test/LoggerInterfaceTest.php | 146 - vendor/psr/log/Psr/Log/Test/TestLogger.php | 147 - vendor/psr/log/README.md | 58 - vendor/psr/log/composer.json | 26 - vendor/symfony/cache-contracts/.gitignore | 3 - .../cache-contracts/CacheInterface.php | 57 - vendor/symfony/cache-contracts/CacheTrait.php | 76 - .../cache-contracts/CallbackInterface.php | 30 - .../symfony/cache-contracts/ItemInterface.php | 65 - vendor/symfony/cache-contracts/LICENSE | 19 - vendor/symfony/cache-contracts/README.md | 9 - .../TagAwareCacheInterface.php | 38 - vendor/symfony/cache-contracts/composer.json | 34 - vendor/symfony/cache/.gitattributes | 3 - .../symfony/cache/Adapter/AbstractAdapter.php | 195 - .../cache/Adapter/AbstractTagAwareAdapter.php | 323 -- .../cache/Adapter/AdapterInterface.php | 44 - vendor/symfony/cache/Adapter/ApcuAdapter.php | 122 - vendor/symfony/cache/Adapter/ArrayAdapter.php | 324 -- vendor/symfony/cache/Adapter/ChainAdapter.php | 329 -- .../symfony/cache/Adapter/DoctrineAdapter.php | 105 - .../cache/Adapter/FilesystemAdapter.php | 29 - .../Adapter/FilesystemTagAwareAdapter.php | 239 -- .../cache/Adapter/MemcachedAdapter.php | 335 -- vendor/symfony/cache/Adapter/NullAdapter.php | 154 - vendor/symfony/cache/Adapter/PdoAdapter.php | 469 --- .../symfony/cache/Adapter/PhpArrayAdapter.php | 432 -- .../symfony/cache/Adapter/PhpFilesAdapter.php | 330 -- vendor/symfony/cache/Adapter/ProxyAdapter.php | 265 -- vendor/symfony/cache/Adapter/Psr16Adapter.php | 86 - vendor/symfony/cache/Adapter/RedisAdapter.php | 30 - .../cache/Adapter/RedisTagAwareAdapter.php | 292 -- .../symfony/cache/Adapter/TagAwareAdapter.php | 425 -- .../Adapter/TagAwareAdapterInterface.php | 33 - .../cache/Adapter/TraceableAdapter.php | 299 -- .../Adapter/TraceableTagAwareAdapter.php | 38 - vendor/symfony/cache/CHANGELOG.md | 81 - vendor/symfony/cache/CacheItem.php | 190 - .../DataCollector/CacheDataCollector.php | 189 - .../CacheCollectorPass.php | 72 - .../CachePoolClearerPass.php | 48 - .../DependencyInjection/CachePoolPass.php | 222 - .../CachePoolPrunerPass.php | 60 - vendor/symfony/cache/DoctrineProvider.php | 114 - .../cache/Exception/CacheException.php | 25 - .../Exception/InvalidArgumentException.php | 25 - .../cache/Exception/LogicException.php | 25 - vendor/symfony/cache/LICENSE | 19 - vendor/symfony/cache/LockRegistry.php | 153 - .../cache/Marshaller/DefaultMarshaller.php | 99 - .../cache/Marshaller/DeflateMarshaller.php | 53 - .../cache/Marshaller/MarshallerInterface.php | 40 - .../cache/Marshaller/TagAwareMarshaller.php | 89 - vendor/symfony/cache/PruneableInterface.php | 23 - vendor/symfony/cache/Psr16Cache.php | 277 -- vendor/symfony/cache/README.md | 18 - vendor/symfony/cache/ResettableInterface.php | 21 - .../cache/Traits/AbstractAdapterTrait.php | 392 -- .../symfony/cache/Traits/ContractsTrait.php | 97 - .../cache/Traits/FilesystemCommonTrait.php | 183 - .../symfony/cache/Traits/FilesystemTrait.php | 124 - vendor/symfony/cache/Traits/ProxyTrait.php | 43 - .../cache/Traits/RedisClusterProxy.php | 63 - vendor/symfony/cache/Traits/RedisProxy.php | 65 - vendor/symfony/cache/Traits/RedisTrait.php | 511 --- vendor/symfony/cache/composer.json | 59 - vendor/symfony/config/.gitattributes | 3 - vendor/symfony/config/CHANGELOG.md | 116 - vendor/symfony/config/ConfigCache.php | 62 - vendor/symfony/config/ConfigCacheFactory.php | 47 - .../config/ConfigCacheFactoryInterface.php | 32 - .../symfony/config/ConfigCacheInterface.php | 49 - .../symfony/config/Definition/ArrayNode.php | 406 -- vendor/symfony/config/Definition/BaseNode.php | 543 --- .../symfony/config/Definition/BooleanNode.php | 55 - .../Builder/ArrayNodeDefinition.php | 546 --- .../Builder/BooleanNodeDefinition.php | 53 - .../Builder/BuilderAwareInterface.php | 25 - .../Definition/Builder/EnumNodeDefinition.php | 56 - .../config/Definition/Builder/ExprBuilder.php | 246 -- .../Builder/FloatNodeDefinition.php | 32 - .../Builder/IntegerNodeDefinition.php | 32 - .../Definition/Builder/MergeBuilder.php | 63 - .../config/Definition/Builder/NodeBuilder.php | 219 - .../Definition/Builder/NodeDefinition.php | 362 -- .../Builder/NodeParentInterface.php | 21 - .../Builder/NormalizationBuilder.php | 60 - .../Builder/NumericNodeDefinition.php | 73 - .../Builder/ParentNodeDefinitionInterface.php | 51 - .../Builder/ScalarNodeDefinition.php | 32 - .../config/Definition/Builder/TreeBuilder.php | 63 - .../Definition/Builder/ValidationBuilder.php | 44 - .../Builder/VariableNodeDefinition.php | 65 - .../Definition/ConfigurationInterface.php | 27 - .../Definition/Dumper/XmlReferenceDumper.php | 302 -- .../Definition/Dumper/YamlReferenceDumper.php | 242 -- vendor/symfony/config/Definition/EnumNode.php | 62 - .../Exception/DuplicateKeyException.php | 22 - .../config/Definition/Exception/Exception.php | 21 - .../Exception/ForbiddenOverwriteException.php | 22 - .../InvalidConfigurationException.php | 47 - .../Exception/InvalidDefinitionException.php | 21 - .../Exception/InvalidTypeException.php | 21 - .../Exception/UnsetKeyException.php | 22 - .../symfony/config/Definition/FloatNode.php | 51 - .../symfony/config/Definition/IntegerNode.php | 46 - .../config/Definition/NodeInterface.php | 100 - .../symfony/config/Definition/NumericNode.php | 64 - .../symfony/config/Definition/Processor.php | 95 - .../Definition/PrototypeNodeInterface.php | 25 - .../config/Definition/PrototypedArrayNode.php | 365 -- .../symfony/config/Definition/ScalarNode.php | 67 - .../config/Definition/VariableNode.php | 142 - ...LoaderImportCircularReferenceException.php | 27 - .../FileLocatorFileNotFoundException.php | 34 - .../config/Exception/LoaderLoadException.php | 109 - vendor/symfony/config/FileLocator.php | 94 - .../symfony/config/FileLocatorInterface.php | 34 - vendor/symfony/config/LICENSE | 19 - .../config/Loader/DelegatingLoader.php | 50 - vendor/symfony/config/Loader/FileLoader.php | 179 - .../symfony/config/Loader/GlobFileLoader.php | 36 - vendor/symfony/config/Loader/Loader.php | 78 - .../symfony/config/Loader/LoaderInterface.php | 50 - .../symfony/config/Loader/LoaderResolver.php | 68 - .../config/Loader/LoaderResolverInterface.php | 30 - vendor/symfony/config/README.md | 15 - .../Resource/ClassExistenceResource.php | 231 -- .../config/Resource/ComposerResource.php | 70 - .../config/Resource/DirectoryResource.php | 106 - .../config/Resource/FileExistenceResource.php | 62 - .../symfony/config/Resource/FileResource.php | 67 - .../symfony/config/Resource/GlobResource.php | 230 -- .../Resource/ReflectionClassResource.php | 220 - .../config/Resource/ResourceInterface.php | 33 - .../Resource/SelfCheckingResourceChecker.php | 36 - .../SelfCheckingResourceInterface.php | 30 - .../config/ResourceCheckerConfigCache.php | 188 - .../ResourceCheckerConfigCacheFactory.php | 44 - .../config/ResourceCheckerInterface.php | 45 - .../Util/Exception/InvalidXmlException.php | 21 - .../Util/Exception/XmlParsingException.php | 21 - vendor/symfony/config/Util/XmlUtils.php | 269 -- vendor/symfony/config/composer.json | 48 - vendor/symfony/console/.gitattributes | 3 - vendor/symfony/console/Application.php | 1187 ------ vendor/symfony/console/CHANGELOG.md | 178 - vendor/symfony/console/Command/Command.php | 642 --- .../symfony/console/Command/HelpCommand.php | 83 - .../symfony/console/Command/ListCommand.php | 89 - .../symfony/console/Command/LockableTrait.php | 69 - .../CommandLoader/CommandLoaderInterface.php | 42 - .../CommandLoader/ContainerCommandLoader.php | 63 - .../CommandLoader/FactoryCommandLoader.php | 62 - vendor/symfony/console/ConsoleEvents.php | 47 - .../AddConsoleCommandPass.php | 98 - .../Descriptor/ApplicationDescription.php | 143 - .../symfony/console/Descriptor/Descriptor.php | 104 - .../Descriptor/DescriptorInterface.php | 29 - .../console/Descriptor/JsonDescriptor.php | 156 - .../console/Descriptor/MarkdownDescriptor.php | 188 - .../console/Descriptor/TextDescriptor.php | 342 -- .../console/Descriptor/XmlDescriptor.php | 231 -- .../console/Event/ConsoleCommandEvent.php | 51 - .../console/Event/ConsoleErrorEvent.php | 58 - vendor/symfony/console/Event/ConsoleEvent.php | 67 - .../console/Event/ConsoleTerminateEvent.php | 43 - .../console/EventListener/ErrorListener.php | 95 - .../Exception/CommandNotFoundException.php | 43 - .../console/Exception/ExceptionInterface.php | 21 - .../Exception/InvalidArgumentException.php | 19 - .../Exception/InvalidOptionException.php | 21 - .../console/Exception/LogicException.php | 19 - .../Exception/NamespaceNotFoundException.php | 21 - .../console/Exception/RuntimeException.php | 19 - .../console/Formatter/OutputFormatter.php | 275 -- .../Formatter/OutputFormatterInterface.php | 58 - .../Formatter/OutputFormatterStyle.php | 196 - .../OutputFormatterStyleInterface.php | 52 - .../Formatter/OutputFormatterStyleStack.php | 110 - .../WrappableOutputFormatterInterface.php | 25 - .../console/Helper/DebugFormatterHelper.php | 107 - .../console/Helper/DescriptorHelper.php | 87 - vendor/symfony/console/Helper/Dumper.php | 64 - .../console/Helper/FormatterHelper.php | 96 - vendor/symfony/console/Helper/Helper.php | 132 - .../console/Helper/HelperInterface.php | 39 - vendor/symfony/console/Helper/HelperSet.php | 98 - .../console/Helper/InputAwareHelper.php | 33 - .../symfony/console/Helper/ProcessHelper.php | 144 - vendor/symfony/console/Helper/ProgressBar.php | 592 --- .../console/Helper/ProgressIndicator.php | 254 -- .../symfony/console/Helper/QuestionHelper.php | 485 --- .../console/Helper/SymfonyQuestionHelper.php | 96 - vendor/symfony/console/Helper/Table.php | 834 ---- vendor/symfony/console/Helper/TableCell.php | 68 - vendor/symfony/console/Helper/TableRows.php | 32 - .../symfony/console/Helper/TableSeparator.php | 25 - vendor/symfony/console/Helper/TableStyle.php | 364 -- vendor/symfony/console/Input/ArgvInput.php | 349 -- vendor/symfony/console/Input/ArrayInput.php | 202 - vendor/symfony/console/Input/Input.php | 201 - .../symfony/console/Input/InputArgument.php | 129 - .../console/Input/InputAwareInterface.php | 26 - .../symfony/console/Input/InputDefinition.php | 390 -- .../symfony/console/Input/InputInterface.php | 153 - vendor/symfony/console/Input/InputOption.php | 208 - .../Input/StreamableInputInterface.php | 37 - vendor/symfony/console/Input/StringInput.php | 68 - vendor/symfony/console/LICENSE | 19 - .../symfony/console/Logger/ConsoleLogger.php | 126 - .../symfony/console/Output/BufferedOutput.php | 45 - .../symfony/console/Output/ConsoleOutput.php | 159 - .../console/Output/ConsoleOutputInterface.php | 32 - .../console/Output/ConsoleSectionOutput.php | 143 - vendor/symfony/console/Output/NullOutput.php | 123 - vendor/symfony/console/Output/Output.php | 174 - .../console/Output/OutputInterface.php | 110 - .../symfony/console/Output/StreamOutput.php | 119 - .../console/Question/ChoiceQuestion.php | 182 - .../console/Question/ConfirmationQuestion.php | 57 - vendor/symfony/console/Question/Question.php | 282 -- vendor/symfony/console/README.md | 20 - .../console/Resources/bin/hiddeninput.exe | Bin 9216 -> 0 bytes vendor/symfony/console/Style/OutputStyle.php | 153 - .../symfony/console/Style/StyleInterface.php | 132 - vendor/symfony/console/Style/SymfonyStyle.php | 499 --- vendor/symfony/console/Terminal.php | 169 - .../console/Tester/ApplicationTester.php | 74 - .../symfony/console/Tester/CommandTester.php | 78 - vendor/symfony/console/Tester/TesterTrait.php | 178 - vendor/symfony/console/composer.json | 60 - .../dependency-injection/.gitattributes | 3 - vendor/symfony/dependency-injection/Alias.php | 133 - .../Argument/ArgumentInterface.php | 27 - .../Argument/BoundArgument.php | 62 - .../Argument/IteratorArgument.php | 22 - .../Argument/ReferenceSetArgumentTrait.php | 54 - .../Argument/RewindableGenerator.php | 46 - .../Argument/ServiceClosureArgument.php | 50 - .../Argument/ServiceLocator.php | 50 - .../Argument/ServiceLocatorArgument.php | 44 - .../Argument/TaggedIteratorArgument.php | 73 - .../symfony/dependency-injection/CHANGELOG.md | 248 -- .../dependency-injection/ChildDefinition.php | 124 - .../Compiler/AbstractRecursivePass.php | 223 - .../Compiler/AnalyzeServiceReferencesPass.php | 184 - .../Compiler/AutoAliasServicePass.php | 41 - .../Compiler/AutowirePass.php | 475 --- .../Compiler/AutowireRequiredMethodsPass.php | 84 - .../Compiler/CheckArgumentsValidityPass.php | 87 - .../Compiler/CheckCircularReferencesPass.php | 78 - .../Compiler/CheckDefinitionValidityPass.php | 90 - ...xceptionOnInvalidReferenceBehaviorPass.php | 88 - .../Compiler/CheckReferenceValidityPass.php | 43 - .../Compiler/CheckTypeDeclarationsPass.php | 245 -- .../Compiler/Compiler.php | 116 - .../Compiler/CompilerPassInterface.php | 27 - .../Compiler/DecoratorServicePass.php | 89 - .../Compiler/DefinitionErrorExceptionPass.php | 56 - .../Compiler/ExtensionCompilerPass.php | 37 - .../Compiler/InlineServiceDefinitionsPass.php | 217 - .../MergeExtensionConfigurationPass.php | 220 - .../Compiler/PassConfig.php | 266 -- .../Compiler/PriorityTaggedServiceTrait.php | 138 - .../Compiler/RegisterEnvVarProcessorsPass.php | 75 - .../Compiler/RegisterReverseContainerPass.php | 66 - .../RegisterServiceSubscribersPass.php | 122 - .../RemoveAbstractDefinitionsPass.php | 33 - .../Compiler/RemovePrivateAliasesPass.php | 39 - .../Compiler/RemoveUnusedDefinitionsPass.php | 90 - .../ReplaceAliasByActualDefinitionPass.php | 94 - .../Compiler/ResolveBindingsPass.php | 227 - .../Compiler/ResolveChildDefinitionsPass.php | 190 - .../Compiler/ResolveClassPass.php | 40 - .../Compiler/ResolveEnvPlaceholdersPass.php | 44 - .../Compiler/ResolveFactoryClassPass.php | 38 - .../Compiler/ResolveHotPathPass.php | 71 - .../ResolveInstanceofConditionalsPass.php | 168 - .../Compiler/ResolveInvalidReferencesPass.php | 136 - .../Compiler/ResolveNamedArgumentsPass.php | 112 - .../ResolveParameterPlaceHoldersPass.php | 87 - .../Compiler/ResolvePrivatesPass.php | 40 - .../ResolveReferencesToAliasesPass.php | 80 - .../ResolveServiceSubscribersPass.php | 52 - .../ResolveTaggedIteratorArgumentPass.php | 38 - .../Compiler/ServiceLocatorTagPass.php | 135 - .../Compiler/ServiceReferenceGraph.php | 98 - .../Compiler/ServiceReferenceGraphEdge.php | 99 - .../Compiler/ServiceReferenceGraphNode.php | 118 - .../Compiler/ValidateEnvPlaceholdersPass.php | 116 - .../Config/ContainerParametersResource.php | 50 - .../ContainerParametersResourceChecker.php | 52 - .../dependency-injection/Container.php | 447 -- .../ContainerAwareInterface.php | 25 - .../ContainerAwareTrait.php | 30 - .../dependency-injection/ContainerBuilder.php | 1611 -------- .../ContainerInterface.php | 96 - .../dependency-injection/Definition.php | 890 ---- .../dependency-injection/Dumper/Dumper.php | 29 - .../Dumper/DumperInterface.php | 27 - .../Dumper/GraphvizDumper.php | 251 -- .../dependency-injection/Dumper/PhpDumper.php | 2064 ---------- .../dependency-injection/Dumper/Preloader.php | 100 - .../dependency-injection/Dumper/XmlDumper.php | 374 -- .../Dumper/YamlDumper.php | 349 -- .../EnvVarLoaderInterface.php | 25 - .../dependency-injection/EnvVarProcessor.php | 280 -- .../EnvVarProcessorInterface.php | 40 - .../Exception/AutowiringFailedException.php | 72 - .../Exception/BadMethodCallException.php | 19 - .../Exception/EnvNotFoundException.php | 21 - .../Exception/EnvParameterException.php | 25 - .../Exception/ExceptionInterface.php | 24 - .../Exception/InvalidArgumentException.php | 21 - .../InvalidParameterTypeException.php | 26 - .../Exception/LogicException.php | 19 - .../Exception/OutOfBoundsException.php | 19 - .../ParameterCircularReferenceException.php | 34 - .../Exception/ParameterNotFoundException.php | 100 - .../Exception/RuntimeException.php | 21 - .../ServiceCircularReferenceException.php | 41 - .../Exception/ServiceNotFoundException.php | 67 - .../ExpressionLanguage.php | 40 - .../ExpressionLanguageProvider.php | 50 - .../ConfigurationExtensionInterface.php | 30 - .../Extension/Extension.php | 139 - .../Extension/ExtensionInterface.php | 52 - .../Extension/PrependExtensionInterface.php | 22 - vendor/symfony/dependency-injection/LICENSE | 19 - .../Instantiator/InstantiatorInterface.php | 34 - .../Instantiator/RealServiceInstantiator.php | 33 - .../LazyProxy/PhpDumper/DumperInterface.php | 43 - .../LazyProxy/PhpDumper/NullDumper.php | 48 - .../LazyProxy/ProxyHelper.php | 56 - .../Loader/ClosureLoader.php | 48 - .../Configurator/AbstractConfigurator.php | 87 - .../AbstractServiceConfigurator.php | 93 - .../Loader/Configurator/AliasConfigurator.php | 30 - .../Configurator/ContainerConfigurator.php | 132 - .../Configurator/DefaultsConfigurator.php | 69 - .../InlineServiceConfigurator.php | 36 - .../Configurator/InstanceofConfigurator.php | 49 - .../Configurator/ParametersConfigurator.php | 51 - .../Configurator/PrototypeConfigurator.php | 84 - .../Configurator/ReferenceConfigurator.php | 69 - .../Configurator/ServiceConfigurator.php | 72 - .../Configurator/ServicesConfigurator.php | 147 - .../Configurator/Traits/AbstractTrait.php | 28 - .../Configurator/Traits/ArgumentTrait.php | 42 - .../Traits/AutoconfigureTrait.php | 35 - .../Configurator/Traits/AutowireTrait.php | 27 - .../Loader/Configurator/Traits/BindTrait.php | 47 - .../Loader/Configurator/Traits/CallTrait.php | 35 - .../Loader/Configurator/Traits/ClassTrait.php | 27 - .../Configurator/Traits/ConfiguratorTrait.php | 29 - .../Configurator/Traits/DecorateTrait.php | 34 - .../Configurator/Traits/DeprecateTrait.php | 33 - .../Configurator/Traits/FactoryTrait.php | 37 - .../Loader/Configurator/Traits/FileTrait.php | 27 - .../Loader/Configurator/Traits/LazyTrait.php | 32 - .../Configurator/Traits/ParentTrait.php | 50 - .../Configurator/Traits/PropertyTrait.php | 27 - .../Configurator/Traits/PublicTrait.php | 35 - .../Loader/Configurator/Traits/ShareTrait.php | 27 - .../Configurator/Traits/SyntheticTrait.php | 28 - .../Loader/Configurator/Traits/TagTrait.php | 39 - .../Loader/DirectoryLoader.php | 54 - .../Loader/FileLoader.php | 225 - .../Loader/GlobFileLoader.php | 40 - .../Loader/IniFileLoader.php | 97 - .../Loader/PhpFileLoader.php | 80 - .../Loader/XmlFileLoader.php | 728 ---- .../Loader/YamlFileLoader.php | 872 ---- .../schema/dic/services/services-1.0.xsd | 305 -- .../dependency-injection/Parameter.php | 35 - .../ParameterBag/ContainerBag.php | 51 - .../ParameterBag/ContainerBagInterface.php | 57 - .../EnvPlaceholderParameterBag.php | 154 - .../ParameterBag/FrozenParameterBag.php | 68 - .../ParameterBag/ParameterBag.php | 286 -- .../ParameterBag/ParameterBagInterface.php | 108 - vendor/symfony/dependency-injection/README.md | 14 - .../dependency-injection/Reference.php | 47 - .../dependency-injection/ReverseContainer.php | 81 - .../dependency-injection/ServiceLocator.php | 145 - .../TaggedContainerInterface.php | 29 - .../dependency-injection/TypedReference.php | 47 - .../symfony/dependency-injection/Variable.php | 43 - .../dependency-injection/composer.json | 57 - vendor/symfony/doctrine-bridge/.gitattributes | 3 - vendor/symfony/doctrine-bridge/CHANGELOG.md | 114 - .../CacheWarmer/ProxyCacheWarmer.php | 69 - .../ContainerAwareEventManager.php | 174 - .../DataCollector/DoctrineDataCollector.php | 245 -- .../DataCollector/ObjectParameter.php | 54 - .../DataFixtures/ContainerAwareLoader.php | 46 - .../AbstractDoctrineExtension.php | 440 -- .../CompilerPass/DoctrineValidationPass.php | 61 - ...gisterEventListenersAndSubscribersPass.php | 149 - .../CompilerPass/RegisterMappingsPass.php | 237 -- .../Security/UserProvider/EntityFactory.php | 61 - .../Form/ChoiceList/DoctrineChoiceLoader.php | 150 - .../Form/ChoiceList/EntityLoaderInterface.php | 34 - .../Form/ChoiceList/IdReader.php | 121 - .../Form/ChoiceList/ORMQueryBuilderLoader.php | 104 - .../CollectionToArrayTransformer.php | 67 - .../Form/DoctrineOrmExtension.php | 38 - .../Form/DoctrineOrmTypeGuesser.php | 201 - .../MergeDoctrineCollectionListener.php | 52 - .../Form/Type/DoctrineType.php | 279 -- .../doctrine-bridge/Form/Type/EntityType.php | 98 - vendor/symfony/doctrine-bridge/LICENSE | 19 - .../doctrine-bridge/Logger/DbalLogger.php | 99 - .../doctrine-bridge/ManagerRegistry.php | 74 - .../Messenger/AbstractDoctrineMiddleware.php | 49 - ...rineClearEntityManagerWorkerSubscriber.php | 55 - .../DoctrineCloseConnectionMiddleware.php | 38 - .../DoctrinePingConnectionMiddleware.php | 48 - .../DoctrineTransactionMiddleware.php | 48 - .../PropertyInfo/DoctrineExtractor.php | 255 -- vendor/symfony/doctrine-bridge/README.md | 13 - .../RememberMe/DoctrineTokenProvider.php | 126 - .../Security/User/EntityUserProvider.php | 155 - .../Security/User/UserLoaderInterface.php | 37 - .../Test/DoctrineTestHelper.php | 99 - .../Test/TestRepositoryFactory.php | 65 - .../Validator/Constraints/UniqueEntity.php | 68 - .../Constraints/UniqueEntityValidator.php | 218 - .../Validator/DoctrineInitializer.php | 38 - .../Validator/DoctrineLoader.php | 140 - vendor/symfony/doctrine-bridge/composer.json | 80 - vendor/symfony/error-handler/.gitattributes | 3 - .../symfony/error-handler/BufferingLogger.php | 58 - vendor/symfony/error-handler/CHANGELOG.md | 8 - vendor/symfony/error-handler/Debug.php | 36 - .../error-handler/DebugClassLoader.php | 1074 ----- .../Error/ClassNotFoundError.php | 33 - .../error-handler/Error/FatalError.php | 88 - .../error-handler/Error/OutOfMemoryError.php | 16 - .../Error/UndefinedFunctionError.php | 33 - .../Error/UndefinedMethodError.php | 33 - .../ClassNotFoundErrorEnhancer.php | 193 - .../ErrorEnhancer/ErrorEnhancerInterface.php | 20 - .../UndefinedFunctionErrorEnhancer.php | 87 - .../UndefinedMethodErrorEnhancer.php | 69 - vendor/symfony/error-handler/ErrorHandler.php | 768 ---- .../ErrorRenderer/CliErrorRenderer.php | 46 - .../ErrorRenderer/ErrorRendererInterface.php | 27 - .../ErrorRenderer/HtmlErrorRenderer.php | 350 -- .../ErrorRenderer/SerializerErrorRenderer.php | 80 - .../Exception/FlattenException.php | 397 -- .../Exception/SilencedErrorContext.php | 67 - vendor/symfony/error-handler/LICENSE | 19 - vendor/symfony/error-handler/README.md | 12 - .../Resources/assets/css/error.css | 4 - .../Resources/assets/css/exception.css | 209 - .../Resources/assets/css/exception_full.css | 128 - .../Resources/assets/images/chevron-right.svg | 1 - .../assets/images/favicon.png.base64 | 1 - .../Resources/assets/images/icon-book.svg | 1 - .../assets/images/icon-minus-square-o.svg | 1 - .../assets/images/icon-minus-square.svg | 1 - .../assets/images/icon-plus-square-o.svg | 1 - .../assets/images/icon-plus-square.svg | 1 - .../Resources/assets/images/icon-support.svg | 1 - .../assets/images/symfony-ghost.svg.php | 1 - .../Resources/assets/images/symfony-logo.svg | 1 - .../Resources/assets/js/exception.js | 279 -- .../Resources/views/error.html.php | 20 - .../Resources/views/exception.html.php | 116 - .../Resources/views/exception_full.html.php | 43 - .../Resources/views/logs.html.php | 45 - .../Resources/views/trace.html.php | 40 - .../Resources/views/traces.html.php | 42 - .../Resources/views/traces_text.html.php | 43 - .../symfony/error-handler/ThrowableUtils.php | 35 - vendor/symfony/error-handler/composer.json | 39 - .../event-dispatcher-contracts/.gitignore | 3 - .../event-dispatcher-contracts/Event.php | 54 - .../EventDispatcherInterface.php | 31 - .../event-dispatcher-contracts/LICENSE | 19 - .../event-dispatcher-contracts/README.md | 9 - .../event-dispatcher-contracts/composer.json | 34 - .../symfony/event-dispatcher/.gitattributes | 3 - vendor/symfony/event-dispatcher/CHANGELOG.md | 75 - .../Debug/TraceableEventDispatcher.php | 363 -- .../Debug/WrappedListener.php | 127 - .../AddEventAliasesPass.php | 42 - .../RegisterListenersPass.php | 178 - .../event-dispatcher/EventDispatcher.php | 280 -- .../EventDispatcherInterface.php | 75 - .../EventSubscriberInterface.php | 46 - .../symfony/event-dispatcher/GenericEvent.php | 170 - .../ImmutableEventDispatcher.php | 91 - vendor/symfony/event-dispatcher/LICENSE | 19 - .../LegacyEventDispatcherProxy.php | 29 - vendor/symfony/event-dispatcher/README.md | 15 - vendor/symfony/event-dispatcher/composer.json | 54 - vendor/symfony/filesystem/.gitattributes | 3 - vendor/symfony/filesystem/CHANGELOG.md | 75 - .../Exception/ExceptionInterface.php | 21 - .../Exception/FileNotFoundException.php | 34 - .../filesystem/Exception/IOException.php | 39 - .../Exception/IOExceptionInterface.php | 27 - .../Exception/InvalidArgumentException.php | 19 - vendor/symfony/filesystem/Filesystem.php | 734 ---- vendor/symfony/filesystem/LICENSE | 19 - vendor/symfony/filesystem/README.md | 13 - vendor/symfony/filesystem/composer.json | 34 - vendor/symfony/finder/.gitattributes | 3 - vendor/symfony/finder/CHANGELOG.md | 79 - .../symfony/finder/Comparator/Comparator.php | 91 - .../finder/Comparator/DateComparator.php | 51 - .../finder/Comparator/NumberComparator.php | 79 - .../Exception/AccessDeniedException.php | 19 - .../Exception/DirectoryNotFoundException.php | 19 - vendor/symfony/finder/Finder.php | 793 ---- vendor/symfony/finder/Gitignore.php | 105 - vendor/symfony/finder/Glob.php | 111 - .../finder/Iterator/CustomFilterIterator.php | 61 - .../Iterator/DateRangeFilterIterator.php | 58 - .../Iterator/DepthRangeFilterIterator.php | 45 - .../ExcludeDirectoryFilterIterator.php | 87 - .../Iterator/FileTypeFilterIterator.php | 53 - .../Iterator/FilecontentFilterIterator.php | 58 - .../Iterator/FilenameFilterIterator.php | 47 - .../Iterator/MultiplePcreFilterIterator.php | 106 - .../finder/Iterator/PathFilterIterator.php | 56 - .../Iterator/RecursiveDirectoryIterator.php | 140 - .../Iterator/SizeRangeFilterIterator.php | 57 - .../finder/Iterator/SortableIterator.php | 101 - vendor/symfony/finder/LICENSE | 19 - vendor/symfony/finder/README.md | 14 - vendor/symfony/finder/SplFileInfo.php | 85 - vendor/symfony/finder/composer.json | 33 - .../symfony/framework-bundle/.gitattributes | 3 - vendor/symfony/framework-bundle/CHANGELOG.md | 413 -- .../AbstractPhpFileCacheWarmer.php | 87 - .../CacheWarmer/AnnotationsCacheWarmer.php | 102 - .../CacheWarmer/RouterCacheWarmer.php | 72 - .../CacheWarmer/SerializerCacheWarmer.php | 87 - .../CacheWarmer/TranslationsCacheWarmer.php | 67 - .../CacheWarmer/ValidatorCacheWarmer.php | 96 - .../framework-bundle/Command/AboutCommand.php | 144 - .../Command/AbstractConfigCommand.php | 141 - .../Command/AssetsInstallCommand.php | 283 -- .../Command/CacheClearCommand.php | 209 - .../Command/CachePoolClearCommand.php | 105 - .../Command/CachePoolDeleteCommand.php | 83 - .../Command/CachePoolListCommand.php | 64 - .../Command/CachePoolPruneCommand.php | 73 - .../Command/CacheWarmupCommand.php | 86 - .../Command/ConfigDebugCommand.php | 156 - .../Command/ConfigDumpReferenceCommand.php | 135 - .../Command/ContainerDebugCommand.php | 295 -- .../Command/ContainerLintCommand.php | 119 - .../Command/DebugAutowiringCommand.php | 161 - .../Command/EventDispatcherDebugCommand.php | 95 - .../Command/RouterDebugCommand.php | 123 - .../Command/RouterMatchCommand.php | 119 - .../Command/SecretsDecryptToLocalCommand.php | 90 - .../SecretsEncryptFromLocalCommand.php | 78 - .../Command/SecretsGenerateKeysCommand.php | 125 - .../Command/SecretsListCommand.php | 108 - .../Command/SecretsRemoveCommand.php | 82 - .../Command/SecretsSetCommand.php | 140 - .../Command/TranslationDebugCommand.php | 342 -- .../Command/TranslationUpdateCommand.php | 316 -- .../Command/WorkflowDumpCommand.php | 103 - .../Command/XliffLintCommand.php | 62 - .../Command/YamlLintCommand.php | 61 - .../framework-bundle/Console/Application.php | 221 - .../Console/Descriptor/Descriptor.php | 384 -- .../Console/Descriptor/JsonDescriptor.php | 420 -- .../Console/Descriptor/MarkdownDescriptor.php | 413 -- .../Console/Descriptor/TextDescriptor.php | 608 --- .../Console/Descriptor/XmlDescriptor.php | 570 --- .../Console/Helper/DescriptorHelper.php | 37 - .../Controller/AbstractController.php | 427 -- .../Controller/ControllerResolver.php | 47 - .../Controller/RedirectController.php | 179 - .../Controller/TemplateController.php | 70 - .../DataCollector/RouterDataCollector.php | 39 - .../AddAnnotationsCachedReaderPass.php | 42 - .../Compiler/AddDebugLogProcessorPass.php | 43 - .../AddExpressionLanguageProvidersPass.php | 38 - .../ContainerBuilderDebugDumpPass.php | 35 - .../Compiler/DataCollectorTranslatorPass.php | 35 - .../Compiler/LoggingTranslatorPass.php | 54 - .../Compiler/ProfilerPass.php | 58 - .../TestServiceContainerRealRefPass.php | 43 - .../TestServiceContainerWeakRefPass.php | 60 - .../Compiler/UnusedTagsPass.php | 100 - .../Compiler/WorkflowGuardListenerPass.php | 48 - .../DependencyInjection/Configuration.php | 1558 ------- .../FrameworkExtension.php | 1989 --------- .../SuggestMissingPackageSubscriber.php | 83 - .../framework-bundle/FrameworkBundle.php | 150 - .../framework-bundle/HttpCache/HttpCache.php | 72 - .../Kernel/MicroKernelTrait.php | 97 - .../framework-bundle/KernelBrowser.php | 206 - vendor/symfony/framework-bundle/LICENSE | 19 - vendor/symfony/framework-bundle/README.md | 10 - .../Resources/config/annotations.xml | 56 - .../Resources/config/assets.xml | 54 - .../Resources/config/cache.xml | 157 - .../Resources/config/cache_debug.xml | 15 - .../Resources/config/collectors.xml | 57 - .../Resources/config/console.xml | 232 -- .../Resources/config/debug.xml | 34 - .../Resources/config/debug_prod.xml | 31 - .../Resources/config/error_renderer.xml | 31 - .../framework-bundle/Resources/config/esi.xml | 17 - .../Resources/config/form.xml | 115 - .../Resources/config/form_csrf.xml | 20 - .../Resources/config/form_debug.xml | 31 - .../Resources/config/fragment_listener.xml | 16 - .../Resources/config/fragment_renderer.xml | 51 - .../Resources/config/http_client.xml | 33 - .../Resources/config/http_client_debug.xml | 12 - .../Resources/config/identity_translator.xml | 14 - .../Resources/config/lock.xml | 26 - .../Resources/config/mailer.xml | 46 - .../Resources/config/mailer_debug.xml | 13 - .../Resources/config/mailer_transports.xml | 50 - .../Resources/config/messenger.xml | 138 - .../Resources/config/messenger_debug.xml | 14 - .../Resources/config/mime_type.xml | 16 - .../Resources/config/notifier.xml | 93 - .../Resources/config/notifier_transports.xml | 33 - .../Resources/config/profiling.xml | 29 - .../Resources/config/property_access.xml | 18 - .../Resources/config/property_info.xml | 37 - .../Resources/config/request.xml | 15 - .../Resources/config/routing.xml | 118 - .../Resources/config/routing/errors.xml | 12 - .../Resources/config/schema/symfony-1.0.xsd | 560 --- .../Resources/config/secrets.xml | 18 - .../Resources/config/security_csrf.xml | 34 - .../Resources/config/serializer.xml | 175 - .../Resources/config/services.xml | 132 - .../Resources/config/session.xml | 75 - .../framework-bundle/Resources/config/ssi.xml | 17 - .../Resources/config/test.xml | 41 - .../Resources/config/translation.xml | 144 - .../Resources/config/translation_debug.xml | 21 - .../Resources/config/validator.xml | 75 - .../Resources/config/validator_debug.xml | 21 - .../framework-bundle/Resources/config/web.xml | 86 - .../Resources/config/web_link.xml | 14 - .../Resources/config/workflow.xml | 30 - .../Resources/views/Form/week_widget.html.php | 14 - .../AnnotatedRouteControllerLoader.php | 56 - .../Routing/DelegatingLoader.php | 89 - .../RedirectableCompiledUrlMatcher.php | 39 - .../Routing/RouteLoaderInterface.php | 19 - .../framework-bundle/Routing/Router.php | 189 - .../Secrets/AbstractVault.php | 49 - .../framework-bundle/Secrets/DotenvVault.php | 107 - .../framework-bundle/Secrets/SodiumVault.php | 220 - .../Test/BrowserKitAssertionsTrait.php | 159 - .../Test/DomCrawlerAssertionsTrait.php | 94 - .../framework-bundle/Test/KernelTestCase.php | 141 - .../Test/MailerAssertionsTrait.php | 131 - .../framework-bundle/Test/TestContainer.php | 152 - .../Test/WebTestAssertionsTrait.php | 18 - .../framework-bundle/Test/WebTestCase.php | 62 - .../Translation/Translator.php | 175 - vendor/symfony/framework-bundle/composer.json | 114 - vendor/symfony/http-foundation/.gitattributes | 3 - .../symfony/http-foundation/AcceptHeader.php | 165 - .../http-foundation/AcceptHeaderItem.php | 177 - .../http-foundation/BinaryFileResponse.php | 354 -- vendor/symfony/http-foundation/CHANGELOG.md | 247 -- vendor/symfony/http-foundation/Cookie.php | 302 -- .../Exception/ConflictingHeadersException.php | 21 - .../Exception/RequestExceptionInterface.php | 21 - .../SuspiciousOperationException.php | 20 - .../ExpressionRequestMatcher.php | 47 - .../File/Exception/AccessDeniedException.php | 25 - .../Exception/CannotWriteFileException.php | 21 - .../File/Exception/ExtensionFileException.php | 21 - .../File/Exception/FileException.php | 21 - .../File/Exception/FileNotFoundException.php | 25 - .../File/Exception/FormSizeFileException.php | 21 - .../File/Exception/IniSizeFileException.php | 21 - .../File/Exception/NoFileException.php | 21 - .../File/Exception/NoTmpDirFileException.php | 21 - .../File/Exception/PartialFileException.php | 21 - .../Exception/UnexpectedTypeException.php | 20 - .../File/Exception/UploadException.php | 21 - vendor/symfony/http-foundation/File/File.php | 130 - .../symfony/http-foundation/File/Stream.php | 28 - .../http-foundation/File/UploadedFile.php | 281 -- vendor/symfony/http-foundation/FileBag.php | 142 - vendor/symfony/http-foundation/HeaderBag.php | 288 -- .../symfony/http-foundation/HeaderUtils.php | 224 - vendor/symfony/http-foundation/IpUtils.php | 185 - .../symfony/http-foundation/JsonResponse.php | 215 - vendor/symfony/http-foundation/LICENSE | 19 - .../symfony/http-foundation/ParameterBag.php | 205 - vendor/symfony/http-foundation/README.md | 14 - .../http-foundation/RedirectResponse.php | 105 - vendor/symfony/http-foundation/Request.php | 2057 ---------- .../http-foundation/RequestMatcher.php | 188 - .../RequestMatcherInterface.php | 27 - .../symfony/http-foundation/RequestStack.php | 103 - vendor/symfony/http-foundation/Response.php | 1224 ------ .../http-foundation/ResponseHeaderBag.php | 293 -- vendor/symfony/http-foundation/ServerBag.php | 99 - .../Session/Attribute/AttributeBag.php | 148 - .../Attribute/AttributeBagInterface.php | 61 - .../Attribute/NamespacedAttributeBag.php | 157 - .../Session/Flash/AutoExpireFlashBag.php | 161 - .../Session/Flash/FlashBag.php | 152 - .../Session/Flash/FlashBagInterface.php | 88 - .../http-foundation/Session/Session.php | 268 -- .../Session/SessionBagInterface.php | 46 - .../Session/SessionBagProxy.php | 83 - .../Session/SessionInterface.php | 166 - .../http-foundation/Session/SessionUtils.php | 59 - .../Handler/AbstractSessionHandler.php | 141 - .../Handler/MemcachedSessionHandler.php | 119 - .../Handler/MigratingSessionHandler.php | 124 - .../Storage/Handler/MongoDbSessionHandler.php | 187 - .../Handler/NativeFileSessionHandler.php | 55 - .../Storage/Handler/NullSessionHandler.php | 76 - .../Storage/Handler/PdoSessionHandler.php | 899 ---- .../Storage/Handler/RedisSessionHandler.php | 120 - .../Storage/Handler/SessionHandlerFactory.php | 85 - .../Storage/Handler/StrictSessionHandler.php | 103 - .../Session/Storage/MetadataBag.php | 166 - .../Storage/MockArraySessionStorage.php | 252 -- .../Storage/MockFileSessionStorage.php | 148 - .../Session/Storage/NativeSessionStorage.php | 464 --- .../Storage/PhpBridgeSessionStorage.php | 64 - .../Session/Storage/Proxy/AbstractProxy.php | 118 - .../Storage/Proxy/SessionHandlerProxy.php | 101 - .../Storage/SessionStorageInterface.php | 131 - .../http-foundation/StreamedResponse.php | 135 - .../Constraint/RequestAttributeValueSame.php | 55 - .../Constraint/ResponseCookieValueSame.php | 85 - .../Test/Constraint/ResponseHasCookie.php | 77 - .../Test/Constraint/ResponseHasHeader.php | 53 - .../Test/Constraint/ResponseHeaderSame.php | 55 - .../Test/Constraint/ResponseIsRedirected.php | 56 - .../Test/Constraint/ResponseIsSuccessful.php | 56 - .../Constraint/ResponseStatusCodeSame.php | 63 - vendor/symfony/http-foundation/UrlHelper.php | 102 - vendor/symfony/http-foundation/composer.json | 39 - vendor/symfony/http-kernel/.gitattributes | 3 - vendor/symfony/http-kernel/Bundle/Bundle.php | 163 - .../http-kernel/Bundle/BundleInterface.php | 71 - vendor/symfony/http-kernel/CHANGELOG.md | 269 -- .../CacheClearer/CacheClearerInterface.php | 25 - .../CacheClearer/ChainCacheClearer.php | 39 - .../CacheClearer/Psr6CacheClearer.php | 58 - .../http-kernel/CacheWarmer/CacheWarmer.php | 32 - .../CacheWarmer/CacheWarmerAggregate.php | 120 - .../CacheWarmer/CacheWarmerInterface.php | 32 - .../CacheWarmer/WarmableInterface.php | 25 - .../http-kernel/Config/FileLocator.php | 46 - .../Controller/ArgumentResolver.php | 96 - .../ArgumentResolver/DefaultValueResolver.php | 40 - .../NotTaggedControllerValueResolver.php | 81 - .../RequestAttributeValueResolver.php | 40 - .../ArgumentResolver/RequestValueResolver.php | 40 - .../ArgumentResolver/ServiceValueResolver.php | 93 - .../ArgumentResolver/SessionValueResolver.php | 50 - .../TraceableValueResolver.php | 62 - .../VariadicValueResolver.php | 46 - .../Controller/ArgumentResolverInterface.php | 32 - .../ArgumentValueResolverInterface.php | 37 - .../ContainerControllerResolver.php | 76 - .../Controller/ControllerReference.php | 44 - .../Controller/ControllerResolver.php | 220 - .../ControllerResolverInterface.php | 41 - .../Controller/ErrorController.php | 62 - .../Controller/TraceableArgumentResolver.php | 44 - .../TraceableControllerResolver.php | 44 - .../ControllerMetadata/ArgumentMetadata.php | 107 - .../ArgumentMetadataFactory.php | 65 - .../ArgumentMetadataFactoryInterface.php | 27 - .../DataCollector/AjaxDataCollector.php | 40 - .../DataCollector/ConfigDataCollector.php | 306 -- .../DataCollector/DataCollector.php | 112 - .../DataCollector/DataCollectorInterface.php | 36 - .../DataCollector/DumpDataCollector.php | 290 -- .../DataCollector/EventDataCollector.php | 150 - .../DataCollector/ExceptionDataCollector.php | 114 - .../LateDataCollectorInterface.php | 25 - .../DataCollector/LoggerDataCollector.php | 282 -- .../DataCollector/MemoryDataCollector.php | 125 - .../DataCollector/RequestDataCollector.php | 458 --- .../DataCollector/RouterDataCollector.php | 108 - .../DataCollector/TimeDataCollector.php | 159 - .../http-kernel/Debug/FileLinkFormatter.php | 106 - .../Debug/TraceableEventDispatcher.php | 90 - .../AddAnnotatedClassesToCachePass.php | 144 - .../ConfigurableExtension.php | 42 - .../ControllerArgumentValueResolverPass.php | 64 - .../DependencyInjection/Extension.php | 44 - .../FragmentRendererPass.php | 63 - .../LazyLoadingFragmentHandler.php | 47 - .../DependencyInjection/LoggerPass.php | 41 - .../MergeExtensionConfigurationPass.php | 41 - ...RegisterControllerArgumentLocatorsPass.php | 200 - .../RegisterLocaleAwareServicesPass.php | 58 - ...oveEmptyControllerArgumentLocatorsPass.php | 70 - .../ResettableServicePass.php | 71 - .../DependencyInjection/ServicesResetter.php | 43 - .../Event/ControllerArgumentsEvent.php | 61 - .../http-kernel/Event/ControllerEvent.php | 48 - .../http-kernel/Event/ExceptionEvent.php | 76 - .../http-kernel/Event/FinishRequestEvent.php | 21 - .../symfony/http-kernel/Event/KernelEvent.php | 80 - .../http-kernel/Event/RequestEvent.php | 58 - .../http-kernel/Event/ResponseEvent.php | 47 - .../http-kernel/Event/TerminateEvent.php | 41 - .../symfony/http-kernel/Event/ViewEvent.php | 61 - .../EventListener/AbstractSessionListener.php | 148 - .../AbstractTestSessionListener.php | 114 - .../AddRequestFormatsListener.php | 52 - .../EventListener/DebugHandlersListener.php | 153 - .../DisallowRobotsIndexingListener.php | 43 - .../EventListener/DumpListener.php | 63 - .../EventListener/ErrorListener.php | 149 - .../EventListener/FragmentListener.php | 100 - .../EventListener/LocaleAwareListener.php | 77 - .../EventListener/LocaleListener.php | 88 - .../EventListener/ProfilerListener.php | 127 - .../EventListener/ResponseListener.php | 58 - .../EventListener/RouterListener.php | 175 - .../EventListener/SessionListener.php | 52 - .../StreamedResponseListener.php | 51 - .../EventListener/SurrogateListener.php | 67 - .../EventListener/TestSessionListener.php | 42 - .../EventListener/ValidateRequestListener.php | 55 - .../Exception/AccessDeniedHttpException.php | 29 - .../Exception/BadRequestHttpException.php | 28 - .../Exception/ConflictHttpException.php | 28 - ...ntrollerDoesNotReturnResponseException.php | 84 - .../Exception/GoneHttpException.php | 28 - .../http-kernel/Exception/HttpException.php | 51 - .../Exception/HttpExceptionInterface.php | 34 - .../Exception/LengthRequiredHttpException.php | 28 - .../MethodNotAllowedHttpException.php | 31 - .../Exception/NotAcceptableHttpException.php | 28 - .../Exception/NotFoundHttpException.php | 28 - .../PreconditionFailedHttpException.php | 28 - .../PreconditionRequiredHttpException.php | 30 - .../ServiceUnavailableHttpException.php | 33 - .../TooManyRequestsHttpException.php | 35 - .../Exception/UnauthorizedHttpException.php | 31 - .../UnprocessableEntityHttpException.php | 28 - .../UnsupportedMediaTypeHttpException.php | 28 - .../AbstractSurrogateFragmentRenderer.php | 108 - .../Fragment/EsiFragmentRenderer.php | 28 - .../http-kernel/Fragment/FragmentHandler.php | 111 - .../Fragment/FragmentRendererInterface.php | 40 - .../Fragment/HIncludeFragmentRenderer.php | 112 - .../Fragment/InlineFragmentRenderer.php | 145 - .../Fragment/RoutableFragmentRenderer.php | 86 - .../Fragment/SsiFragmentRenderer.php | 28 - .../HttpCache/AbstractSurrogate.php | 136 - vendor/symfony/http-kernel/HttpCache/Esi.php | 117 - .../http-kernel/HttpCache/HttpCache.php | 707 ---- .../HttpCache/ResponseCacheStrategy.php | 213 - .../ResponseCacheStrategyInterface.php | 37 - vendor/symfony/http-kernel/HttpCache/Ssi.php | 100 - .../symfony/http-kernel/HttpCache/Store.php | 460 --- .../http-kernel/HttpCache/StoreInterface.php | 81 - .../HttpCache/SubRequestHandler.php | 91 - .../HttpCache/SurrogateInterface.php | 87 - .../symfony/http-kernel/HttpClientKernel.php | 106 - vendor/symfony/http-kernel/HttpKernel.php | 282 -- .../symfony/http-kernel/HttpKernelBrowser.php | 199 - .../http-kernel/HttpKernelInterface.php | 42 - vendor/symfony/http-kernel/Kernel.php | 825 ---- vendor/symfony/http-kernel/KernelEvents.php | 103 - .../symfony/http-kernel/KernelInterface.php | 141 - vendor/symfony/http-kernel/LICENSE | 19 - .../http-kernel/Log/DebugLoggerInterface.php | 45 - vendor/symfony/http-kernel/Log/Logger.php | 106 - .../Profiler/FileProfilerStorage.php | 303 -- .../symfony/http-kernel/Profiler/Profile.php | 274 -- .../symfony/http-kernel/Profiler/Profiler.php | 253 -- .../Profiler/ProfilerStorageInterface.php | 60 - vendor/symfony/http-kernel/README.md | 16 - .../http-kernel/RebootableInterface.php | 30 - .../http-kernel/Resources/welcome.html.php | 119 - .../http-kernel/TerminableInterface.php | 32 - vendor/symfony/http-kernel/UriSigner.php | 103 - vendor/symfony/http-kernel/composer.json | 80 - vendor/symfony/mime/.gitattributes | 3 - vendor/symfony/mime/Address.php | 125 - vendor/symfony/mime/BodyRendererInterface.php | 20 - vendor/symfony/mime/CHANGELOG.md | 20 - vendor/symfony/mime/CharacterStream.php | 221 - vendor/symfony/mime/Crypto/SMime.php | 111 - vendor/symfony/mime/Crypto/SMimeEncrypter.php | 63 - vendor/symfony/mime/Crypto/SMimeSigner.php | 71 - .../AddMimeTypeGuesserPass.php | 46 - vendor/symfony/mime/Email.php | 599 --- .../mime/Encoder/AddressEncoderInterface.php | 28 - .../mime/Encoder/Base64ContentEncoder.php | 48 - vendor/symfony/mime/Encoder/Base64Encoder.php | 41 - .../mime/Encoder/Base64MimeHeaderEncoder.php | 43 - .../mime/Encoder/ContentEncoderInterface.php | 30 - .../mime/Encoder/EightBitContentEncoder.php | 35 - .../symfony/mime/Encoder/EncoderInterface.php | 26 - .../mime/Encoder/IdnAddressEncoder.php | 54 - .../Encoder/MimeHeaderEncoderInterface.php | 23 - .../symfony/mime/Encoder/QpContentEncoder.php | 64 - vendor/symfony/mime/Encoder/QpEncoder.php | 195 - .../mime/Encoder/QpMimeHeaderEncoder.php | 40 - .../symfony/mime/Encoder/Rfc2231Encoder.php | 50 - .../Exception/AddressEncoderException.php | 19 - .../mime/Exception/ExceptionInterface.php | 19 - .../Exception/InvalidArgumentException.php | 19 - .../symfony/mime/Exception/LogicException.php | 19 - .../mime/Exception/RfcComplianceException.php | 19 - .../mime/Exception/RuntimeException.php | 19 - .../mime/FileBinaryMimeTypeGuesser.php | 93 - .../symfony/mime/FileinfoMimeTypeGuesser.php | 63 - vendor/symfony/mime/Header/AbstractHeader.php | 279 -- vendor/symfony/mime/Header/DateHeader.php | 66 - .../symfony/mime/Header/HeaderInterface.php | 65 - vendor/symfony/mime/Header/Headers.php | 282 -- .../mime/Header/IdentificationHeader.php | 110 - vendor/symfony/mime/Header/MailboxHeader.php | 85 - .../symfony/mime/Header/MailboxListHeader.php | 136 - .../mime/Header/ParameterizedHeader.php | 174 - vendor/symfony/mime/Header/PathHeader.php | 62 - .../mime/Header/UnstructuredHeader.php | 69 - vendor/symfony/mime/LICENSE | 19 - vendor/symfony/mime/Message.php | 151 - vendor/symfony/mime/MessageConverter.php | 125 - .../symfony/mime/MimeTypeGuesserInterface.php | 37 - vendor/symfony/mime/MimeTypes.php | 3153 -------------- vendor/symfony/mime/MimeTypesInterface.php | 32 - .../mime/Part/AbstractMultipartPart.php | 99 - vendor/symfony/mime/Part/AbstractPart.php | 65 - vendor/symfony/mime/Part/DataPart.php | 161 - vendor/symfony/mime/Part/MessagePart.php | 62 - .../mime/Part/Multipart/AlternativePart.php | 25 - .../mime/Part/Multipart/DigestPart.php | 31 - .../mime/Part/Multipart/FormDataPart.php | 103 - .../symfony/mime/Part/Multipart/MixedPart.php | 25 - .../mime/Part/Multipart/RelatedPart.php | 55 - vendor/symfony/mime/Part/SMimePart.php | 116 - vendor/symfony/mime/Part/TextPart.php | 204 - vendor/symfony/mime/README.md | 13 - vendor/symfony/mime/RawMessage.php | 88 - .../mime/Resources/bin/update_mime_types.php | 166 - .../Test/Constraint/EmailAddressContains.php | 74 - .../Test/Constraint/EmailAttachmentCount.php | 59 - .../mime/Test/Constraint/EmailHasHeader.php | 57 - .../mime/Test/Constraint/EmailHeaderSame.php | 59 - .../Test/Constraint/EmailHtmlBodyContains.php | 56 - .../Test/Constraint/EmailTextBodyContains.php | 56 - vendor/symfony/mime/composer.json | 42 - vendor/symfony/polyfill-ctype/Ctype.php | 227 - vendor/symfony/polyfill-ctype/LICENSE | 19 - vendor/symfony/polyfill-ctype/README.md | 12 - vendor/symfony/polyfill-ctype/bootstrap.php | 26 - vendor/symfony/polyfill-ctype/composer.json | 34 - vendor/symfony/polyfill-intl-idn/Idn.php | 283 -- vendor/symfony/polyfill-intl-idn/LICENSE | 19 - vendor/symfony/polyfill-intl-idn/README.md | 12 - .../symfony/polyfill-intl-idn/bootstrap.php | 59 - .../symfony/polyfill-intl-idn/composer.json | 36 - vendor/symfony/polyfill-mbstring/LICENSE | 19 - vendor/symfony/polyfill-mbstring/Mbstring.php | 840 ---- vendor/symfony/polyfill-mbstring/README.md | 13 - .../Resources/unidata/lowerCase.php | 1096 ----- .../Resources/unidata/titleCaseRegexp.php | 5 - .../Resources/unidata/upperCase.php | 1104 ----- .../symfony/polyfill-mbstring/bootstrap.php | 62 - .../symfony/polyfill-mbstring/composer.json | 34 - vendor/symfony/polyfill-php72/LICENSE | 19 - vendor/symfony/polyfill-php72/Php72.php | 216 - vendor/symfony/polyfill-php72/README.md | 27 - vendor/symfony/polyfill-php72/bootstrap.php | 36 - vendor/symfony/polyfill-php72/composer.json | 31 - vendor/symfony/polyfill-php73/LICENSE | 19 - vendor/symfony/polyfill-php73/Php73.php | 43 - vendor/symfony/polyfill-php73/README.md | 18 - .../Resources/stubs/JsonException.php | 14 - vendor/symfony/polyfill-php73/bootstrap.php | 32 - vendor/symfony/polyfill-php73/composer.json | 32 - vendor/symfony/routing/.gitattributes | 3 - vendor/symfony/routing/Annotation/Route.php | 182 - vendor/symfony/routing/CHANGELOG.md | 268 -- vendor/symfony/routing/CompiledRoute.php | 173 - .../RoutingResolverPass.php | 49 - .../routing/Exception/ExceptionInterface.php | 21 - .../Exception/InvalidParameterException.php | 21 - .../Exception/MethodNotAllowedException.php | 41 - .../MissingMandatoryParametersException.php | 22 - .../Exception/NoConfigurationException.php | 21 - .../Exception/ResourceNotFoundException.php | 23 - .../Exception/RouteNotFoundException.php | 21 - .../Generator/CompiledUrlGenerator.php | 58 - .../ConfigurableRequirementsInterface.php | 53 - .../Dumper/CompiledUrlGeneratorDumper.php | 73 - .../Generator/Dumper/GeneratorDumper.php | 37 - .../Dumper/GeneratorDumperInterface.php | 37 - .../routing/Generator/UrlGenerator.php | 356 -- .../Generator/UrlGeneratorInterface.php | 82 - vendor/symfony/routing/LICENSE | 19 - .../routing/Loader/AnnotationClassLoader.php | 332 -- .../Loader/AnnotationDirectoryLoader.php | 93 - .../routing/Loader/AnnotationFileLoader.php | 143 - .../symfony/routing/Loader/ClosureLoader.php | 46 - .../Configurator/CollectionConfigurator.php | 93 - .../Configurator/ImportConfigurator.php | 93 - .../Loader/Configurator/RouteConfigurator.php | 34 - .../Configurator/RoutingConfigurator.php | 60 - .../Loader/Configurator/Traits/AddTrait.php | 90 - .../Loader/Configurator/Traits/RouteTrait.php | 163 - .../routing/Loader/ContainerLoader.php | 45 - .../routing/Loader/DirectoryLoader.php | 58 - .../symfony/routing/Loader/GlobFileLoader.php | 47 - .../symfony/routing/Loader/ObjectLoader.php | 84 - .../symfony/routing/Loader/PhpFileLoader.php | 75 - .../symfony/routing/Loader/XmlFileLoader.php | 436 -- .../symfony/routing/Loader/YamlFileLoader.php | 285 -- .../Loader/schema/routing/routing-1.0.xsd | 170 - .../routing/Matcher/CompiledUrlMatcher.php | 31 - .../Dumper/CompiledUrlMatcherDumper.php | 501 --- .../Dumper/CompiledUrlMatcherTrait.php | 187 - .../routing/Matcher/Dumper/MatcherDumper.php | 37 - .../Matcher/Dumper/MatcherDumperInterface.php | 37 - .../Matcher/Dumper/StaticPrefixCollection.php | 202 - .../Matcher/RedirectableUrlMatcher.php | 64 - .../RedirectableUrlMatcherInterface.php | 31 - .../Matcher/RequestMatcherInterface.php | 39 - .../routing/Matcher/TraceableUrlMatcher.php | 164 - vendor/symfony/routing/Matcher/UrlMatcher.php | 279 -- .../routing/Matcher/UrlMatcherInterface.php | 41 - vendor/symfony/routing/README.md | 13 - vendor/symfony/routing/RequestContext.php | 305 -- .../routing/RequestContextAwareInterface.php | 27 - vendor/symfony/routing/Route.php | 547 --- vendor/symfony/routing/RouteCollection.php | 273 -- .../routing/RouteCollectionBuilder.php | 359 -- vendor/symfony/routing/RouteCompiler.php | 337 -- .../routing/RouteCompilerInterface.php | 30 - vendor/symfony/routing/Router.php | 390 -- vendor/symfony/routing/RouterInterface.php | 35 - vendor/symfony/routing/composer.json | 54 - vendor/symfony/service-contracts/.gitignore | 3 - vendor/symfony/service-contracts/LICENSE | 19 - vendor/symfony/service-contracts/README.md | 9 - .../service-contracts/ResetInterface.php | 30 - .../service-contracts/ServiceLocatorTrait.php | 122 - .../ServiceProviderInterface.php | 36 - .../ServiceSubscriberInterface.php | 53 - .../ServiceSubscriberTrait.php | 63 - .../Test/ServiceLocatorTest.php | 92 - .../symfony/service-contracts/composer.json | 34 - vendor/symfony/var-dumper/.gitattributes | 3 - vendor/symfony/var-dumper/CHANGELOG.md | 53 - .../symfony/var-dumper/Caster/AmqpCaster.php | 212 - vendor/symfony/var-dumper/Caster/ArgsStub.php | 80 - vendor/symfony/var-dumper/Caster/Caster.php | 170 - .../symfony/var-dumper/Caster/ClassStub.php | 106 - .../symfony/var-dumper/Caster/ConstStub.php | 36 - .../var-dumper/Caster/CutArrayStub.php | 30 - vendor/symfony/var-dumper/Caster/CutStub.php | 64 - .../symfony/var-dumper/Caster/DOMCaster.php | 304 -- .../symfony/var-dumper/Caster/DateCaster.php | 122 - .../var-dumper/Caster/DoctrineCaster.php | 62 - vendor/symfony/var-dumper/Caster/DsCaster.php | 70 - .../symfony/var-dumper/Caster/DsPairStub.php | 28 - vendor/symfony/var-dumper/Caster/EnumStub.php | 30 - .../var-dumper/Caster/ExceptionCaster.php | 383 -- .../symfony/var-dumper/Caster/FrameStub.php | 30 - .../symfony/var-dumper/Caster/GmpCaster.php | 32 - .../var-dumper/Caster/ImagineCaster.php | 37 - vendor/symfony/var-dumper/Caster/ImgStub.php | 26 - .../symfony/var-dumper/Caster/IntlCaster.php | 172 - vendor/symfony/var-dumper/Caster/LinkStub.php | 108 - .../var-dumper/Caster/MemcachedCaster.php | 81 - .../symfony/var-dumper/Caster/PdoCaster.php | 122 - .../symfony/var-dumper/Caster/PgSqlCaster.php | 156 - .../var-dumper/Caster/ProxyManagerCaster.php | 33 - .../symfony/var-dumper/Caster/RedisCaster.php | 152 - .../var-dumper/Caster/ReflectionCaster.php | 384 -- .../var-dumper/Caster/ResourceCaster.php | 100 - .../symfony/var-dumper/Caster/SplCaster.php | 228 -- .../symfony/var-dumper/Caster/StubCaster.php | 84 - .../var-dumper/Caster/SymfonyCaster.php | 69 - .../symfony/var-dumper/Caster/TraceStub.php | 36 - .../symfony/var-dumper/Caster/UuidCaster.php | 30 - .../var-dumper/Caster/XmlReaderCaster.php | 79 - .../var-dumper/Caster/XmlResourceCaster.php | 63 - .../var-dumper/Cloner/AbstractCloner.php | 360 -- .../var-dumper/Cloner/ClonerInterface.php | 27 - vendor/symfony/var-dumper/Cloner/Cursor.php | 43 - vendor/symfony/var-dumper/Cloner/Data.php | 451 -- .../var-dumper/Cloner/DumperInterface.php | 56 - vendor/symfony/var-dumper/Cloner/Stub.php | 67 - .../symfony/var-dumper/Cloner/VarCloner.php | 285 -- .../Command/Descriptor/CliDescriptor.php | 88 - .../Descriptor/DumpDescriptorInterface.php | 23 - .../Command/Descriptor/HtmlDescriptor.php | 119 - .../var-dumper/Command/ServerDumpCommand.php | 99 - .../var-dumper/Dumper/AbstractDumper.php | 204 - .../symfony/var-dumper/Dumper/CliDumper.php | 636 --- .../ContextProvider/CliContextProvider.php | 32 - .../ContextProviderInterface.php | 25 - .../RequestContextProvider.php | 51 - .../ContextProvider/SourceContextProvider.php | 126 - .../Dumper/ContextualizedDumper.php | 43 - .../var-dumper/Dumper/DataDumperInterface.php | 24 - .../symfony/var-dumper/Dumper/HtmlDumper.php | 1004 ----- .../var-dumper/Dumper/ServerDumper.php | 53 - .../Exception/ThrowingCasterException.php | 26 - vendor/symfony/var-dumper/LICENSE | 19 - vendor/symfony/var-dumper/README.md | 15 - .../var-dumper/Resources/bin/var-dump-server | 63 - .../Resources/css/htmlDescriptor.css | 130 - .../var-dumper/Resources/functions/dump.php | 43 - .../var-dumper/Resources/js/htmlDescriptor.js | 10 - .../symfony/var-dumper/Server/Connection.php | 95 - .../symfony/var-dumper/Server/DumpServer.php | 107 - .../var-dumper/Test/VarDumperTestTrait.php | 87 - vendor/symfony/var-dumper/VarDumper.php | 60 - vendor/symfony/var-dumper/composer.json | 53 - vendor/symfony/var-exporter/.gitattributes | 3 - vendor/symfony/var-exporter/CHANGELOG.md | 7 - .../Exception/ClassNotFoundException.php | 20 - .../Exception/ExceptionInterface.php | 16 - .../NotInstantiableTypeException.php | 20 - vendor/symfony/var-exporter/Instantiator.php | 94 - .../var-exporter/Internal/Exporter.php | 407 -- .../var-exporter/Internal/Hydrator.php | 151 - .../var-exporter/Internal/Reference.php | 30 - .../var-exporter/Internal/Registry.php | 136 - .../symfony/var-exporter/Internal/Values.php | 27 - vendor/symfony/var-exporter/LICENSE | 19 - vendor/symfony/var-exporter/README.md | 38 - vendor/symfony/var-exporter/VarExporter.php | 114 - vendor/symfony/var-exporter/composer.json | 36 - 2282 files changed, 326956 deletions(-) delete mode 100644 vendor/autoload.php delete mode 120000 vendor/bin/doctrine delete mode 120000 vendor/bin/doctrine-dbal delete mode 120000 vendor/bin/var-dump-server delete mode 100644 vendor/composer/ClassLoader.php delete mode 100644 vendor/composer/LICENSE delete mode 100644 vendor/composer/autoload_classmap.php delete mode 100644 vendor/composer/autoload_files.php delete mode 100644 vendor/composer/autoload_namespaces.php delete mode 100644 vendor/composer/autoload_psr4.php delete mode 100644 vendor/composer/autoload_real.php delete mode 100644 vendor/composer/autoload_static.php delete mode 100644 vendor/composer/installed.json delete mode 100644 vendor/doctrine/annotations/CHANGELOG.md delete mode 100644 vendor/doctrine/annotations/LICENSE delete mode 100644 vendor/doctrine/annotations/README.md delete mode 100644 vendor/doctrine/annotations/composer.json delete mode 100644 vendor/doctrine/annotations/docs/en/annotations.rst delete mode 100644 vendor/doctrine/annotations/docs/en/custom.rst delete mode 100644 vendor/doctrine/annotations/docs/en/index.rst delete mode 100644 vendor/doctrine/annotations/docs/en/sidebar.rst delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php delete mode 100644 vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php delete mode 100644 vendor/doctrine/annotations/phpbench.json.dist delete mode 100644 vendor/doctrine/annotations/phpstan.neon delete mode 100644 vendor/doctrine/cache/LICENSE delete mode 100644 vendor/doctrine/cache/README.md delete mode 100644 vendor/doctrine/cache/UPGRADE.md delete mode 100644 vendor/doctrine/cache/composer.json delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcuCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ArrayCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ChainCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/CouchbaseBucketCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/CouchbaseCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ExtMongoDBCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/FilesystemCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/InvalidCacheId.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/LegacyMongoDBCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcacheCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcachedCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MongoDBCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiGetCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiOperationCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiPutCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/PhpFileCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/PredisCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/RedisCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/SQLite3Cache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/Version.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/VoidCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/WinCacheCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/XcacheCache.php delete mode 100644 vendor/doctrine/cache/lib/Doctrine/Common/Cache/ZendDataCache.php delete mode 100644 vendor/doctrine/collections/.doctrine-project.json delete mode 100644 vendor/doctrine/collections/CONTRIBUTING.md delete mode 100644 vendor/doctrine/collections/LICENSE delete mode 100644 vendor/doctrine/collections/README.md delete mode 100644 vendor/doctrine/collections/composer.json delete mode 100644 vendor/doctrine/collections/docs/en/derived-collections.rst delete mode 100644 vendor/doctrine/collections/docs/en/expression-builder.rst delete mode 100644 vendor/doctrine/collections/docs/en/expressions.rst delete mode 100644 vendor/doctrine/collections/docs/en/index.rst delete mode 100644 vendor/doctrine/collections/docs/en/lazy-collections.rst delete mode 100644 vendor/doctrine/collections/docs/en/sidebar.rst delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/AbstractLazyCollection.php delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ExpressionVisitor.php delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php delete mode 100644 vendor/doctrine/collections/lib/Doctrine/Common/Collections/Selectable.php delete mode 100644 vendor/doctrine/collections/psalm.xml.dist delete mode 100644 vendor/doctrine/common/.doctrine-project.json delete mode 100644 vendor/doctrine/common/.github/FUNDING.yml delete mode 100644 vendor/doctrine/common/LICENSE delete mode 100644 vendor/doctrine/common/README.md delete mode 100644 vendor/doctrine/common/UPGRADE_TO_2_1 delete mode 100644 vendor/doctrine/common/UPGRADE_TO_2_2 delete mode 100644 vendor/doctrine/common/composer.json delete mode 100644 vendor/doctrine/common/composer.lock delete mode 100644 vendor/doctrine/common/docs/en/index.rst delete mode 100644 vendor/doctrine/common/docs/en/reference/class-loading.rst delete mode 100644 vendor/doctrine/common/humbug.json.dist delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/ClassLoader.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/CommonException.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Comparable.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Lexer.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/Autoloader.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/InvalidArgumentException.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/OutOfBoundsException.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/ProxyException.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/Proxy.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyDefinition.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Util/ClassUtils.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Util/Inflector.php delete mode 100644 vendor/doctrine/common/lib/Doctrine/Common/Version.php delete mode 100644 vendor/doctrine/common/phpstan.neon.dist delete mode 100644 vendor/doctrine/data-fixtures/.doctrine-project.json delete mode 100644 vendor/doctrine/data-fixtures/.github/FUNDING.yml delete mode 100644 vendor/doctrine/data-fixtures/CHANGELOG.md delete mode 100644 vendor/doctrine/data-fixtures/LICENSE delete mode 100644 vendor/doctrine/data-fixtures/README.md delete mode 100644 vendor/doctrine/data-fixtures/UPGRADE delete mode 100644 vendor/doctrine/data-fixtures/composer.json delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/AbstractFixture.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/DependentFixtureInterface.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Event/Listener/MongoDBReferenceListener.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Event/Listener/ORMReferenceListener.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Exception/CircularReferenceException.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/AbstractExecutor.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/MongoDBExecutor.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/PHPCRExecutor.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/FixtureInterface.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Loader.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/OrderedFixtureInterface.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/ProxyReferenceRepository.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/MongoDBPurger.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/ORMPurger.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PHPCRPurger.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PurgerInterface.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/ReferenceRepository.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/SharedFixtureInterface.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Sorter/TopologicalSorter.php delete mode 100644 vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Sorter/Vertex.php delete mode 100644 vendor/doctrine/data-fixtures/phpcs.xml.dist delete mode 100644 vendor/doctrine/dbal/.doctrine-project.json delete mode 100644 vendor/doctrine/dbal/LICENSE delete mode 100644 vendor/doctrine/dbal/README.md delete mode 100644 vendor/doctrine/dbal/SECURITY.md delete mode 100644 vendor/doctrine/dbal/UPGRADE.md delete mode 100755 vendor/doctrine/dbal/bin/doctrine-dbal delete mode 100644 vendor/doctrine/dbal/bin/doctrine-dbal.php delete mode 100644 vendor/doctrine/dbal/composer.json delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ArrayStatement.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/CacheException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/QueryCacheProfile.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/ColumnCase.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Configuration.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/ConnectionException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Connections/MasterSlaveConnection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDB2Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDriverException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver/EasyConnectString.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractPostgreSQLDriver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLAnywhereDriver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLServerDriver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Connection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DriverException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ExceptionConverterDriver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Exception.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PingableConnection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ResultStatement.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/LastInsertId.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ServerInfoAwareConnection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Statement.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/StatementIterator.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/DriverManager.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/ConnectionEventArgs.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaEventArgs.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Events.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ConnectionException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ConstraintViolationException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DatabaseObjectExistsException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DatabaseObjectNotFoundException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DeadlockException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/DriverException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ForeignKeyConstraintViolationException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/InvalidArgumentException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/InvalidFieldNameException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/LockWaitTimeoutException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/NonUniqueFieldNameException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/NotNullConstraintViolationException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ReadOnlyException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/RetryableException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ServerException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/SyntaxErrorException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/TableExistsException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/TableNotFoundException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/UniqueConstraintViolationException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/FetchMode.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGenerator.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/LockMode.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/DebugStack.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/LoggerChain.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/SQLLogger.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/ParameterType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DB2Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DateIntervalUnit.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DrizzlePlatform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DrizzleKeywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/KeywordList.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MariaDb102Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MsSQLKeywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MySQL57Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MySQL80Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MySQLKeywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/OracleKeywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL100Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL91Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL92Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQL94Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/PostgreSQLKeywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/ReservedKeywordsValidator.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere11Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere12Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere16Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhereKeywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLServer2005Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLServer2008Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLServer2012Keywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLServerKeywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLiteKeywords.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MariaDb1027Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL57Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL80Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/OraclePlatform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL100Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL94Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere12Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere16Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAzurePlatform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2012Platform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/TrimMode.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Connection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Statement.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/CompositeExpression.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryBuilder.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtils.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtilsException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractAsset.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Column.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ColumnDiff.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Comparator.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Constraint.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DB2SchemaManager.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DrizzleSchemaManager.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Identifier.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLAnywhereSchemaManager.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Schema.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaConfig.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaDiff.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Sequence.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SingleDatabaseSynchronizer.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Table.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/TableDiff.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/View.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Graphviz.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/NamespaceVisitor.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/SchemaDiffVisitor.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Visitor.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardConnection.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardChoser/ShardChoser.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardManager.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardingException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Helper/ConnectionHelper.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Dumper.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/TransactionIsolationLevel.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ArrayType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BigIntType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BinaryType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BlobType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BooleanType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ConversionException.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateImmutableType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateIntervalType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeImmutableType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzImmutableType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DecimalType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/FloatType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/GuidType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/IntegerType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonArrayType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ObjectType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/PhpDateTimeMappingType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/PhpIntegerMappingType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SimpleArrayType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SmallIntType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/StringType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TextType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeImmutableType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TypeRegistry.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeImmutableType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeType.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/Version.php delete mode 100644 vendor/doctrine/dbal/lib/Doctrine/DBAL/VersionAwarePlatformDriver.php delete mode 100644 vendor/doctrine/doctrine-bundle/.github/FUNDING.yml delete mode 100644 vendor/doctrine/doctrine-bundle/Command/CreateDatabaseDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/DoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/DropDatabaseDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/ImportMappingDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/ClearMetadataCacheDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/ClearQueryCacheDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/ClearResultCacheDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/CollectionRegionDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/ConvertMappingDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/CreateSchemaDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/DelegateCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/DoctrineCommandHelper.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/DropSchemaDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/EnsureProductionSettingsDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/EntityRegionCacheDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/ImportDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/InfoDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/QueryRegionCacheDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/RunDqlDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/RunSqlDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/UpdateSchemaDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/Command/Proxy/ValidateSchemaCommand.php delete mode 100644 vendor/doctrine/doctrine-bundle/ConnectionFactory.php delete mode 100644 vendor/doctrine/doctrine-bundle/Controller/ProfilerController.php delete mode 100644 vendor/doctrine/doctrine-bundle/DataCollector/DoctrineDataCollector.php delete mode 100644 vendor/doctrine/doctrine-bundle/Dbal/BlacklistSchemaAssetFilter.php delete mode 100644 vendor/doctrine/doctrine-bundle/Dbal/Logging/BacktraceLogger.php delete mode 100644 vendor/doctrine/doctrine-bundle/Dbal/RegexSchemaAssetFilter.php delete mode 100644 vendor/doctrine/doctrine-bundle/Dbal/SchemaAssetsFilterManager.php delete mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DbalSchemaFilterPass.php delete mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DoctrineOrmMappingsPass.php delete mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/EntityListenerPass.php delete mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/ServiceRepositoryCompilerPass.php delete mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/WellKnownSchemaFilterPass.php delete mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/Configuration.php delete mode 100644 vendor/doctrine/doctrine-bundle/DependencyInjection/DoctrineExtension.php delete mode 100644 vendor/doctrine/doctrine-bundle/DoctrineBundle.php delete mode 100644 vendor/doctrine/doctrine-bundle/LICENSE delete mode 100644 vendor/doctrine/doctrine-bundle/ManagerConfigurator.php delete mode 100644 vendor/doctrine/doctrine-bundle/Mapping/ClassMetadataCollection.php delete mode 100644 vendor/doctrine/doctrine-bundle/Mapping/ContainerEntityListenerResolver.php delete mode 100644 vendor/doctrine/doctrine-bundle/Mapping/DisconnectedMetadataFactory.php delete mode 100644 vendor/doctrine/doctrine-bundle/Mapping/EntityListenerServiceResolver.php delete mode 100644 vendor/doctrine/doctrine-bundle/README.md delete mode 100644 vendor/doctrine/doctrine-bundle/Registry.php delete mode 100644 vendor/doctrine/doctrine-bundle/Repository/ContainerRepositoryFactory.php delete mode 100644 vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepository.php delete mode 100644 vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepositoryInterface.php delete mode 100644 vendor/doctrine/doctrine-bundle/Resources/config/dbal.xml delete mode 100644 vendor/doctrine/doctrine-bundle/Resources/config/messenger.xml delete mode 100644 vendor/doctrine/doctrine-bundle/Resources/config/orm.xml delete mode 100644 vendor/doctrine/doctrine-bundle/Resources/config/schema/doctrine-1.0.xsd delete mode 100644 vendor/doctrine/doctrine-bundle/Resources/views/Collector/db.html.twig delete mode 100644 vendor/doctrine/doctrine-bundle/Resources/views/Collector/explain.html.twig delete mode 100644 vendor/doctrine/doctrine-bundle/Resources/views/Collector/icon.svg delete mode 100644 vendor/doctrine/doctrine-bundle/Twig/DoctrineExtension.php delete mode 100644 vendor/doctrine/doctrine-bundle/UPGRADE-1.11.md delete mode 100644 vendor/doctrine/doctrine-bundle/UPGRADE-1.12.md delete mode 100644 vendor/doctrine/doctrine-bundle/UPGRADE-2.0.md delete mode 100644 vendor/doctrine/doctrine-bundle/UPGRADE-3.0.md delete mode 100644 vendor/doctrine/doctrine-bundle/composer.json delete mode 100644 vendor/doctrine/doctrine-bundle/phpcs.xml.dist delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/.github/FUNDING.yml delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/.gitignore delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/.travis.yml delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/CHANGELOG-3.1.md delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Command/LoadDataFixturesDoctrineCommand.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/CompilerPass/FixturesCompilerPass.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/DoctrineFixturesExtension.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/DoctrineFixturesBundle.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Fixture.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/FixtureGroupInterface.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/LICENSE delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Loader/SymfonyFixturesLoader.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/ORMFixtureInterface.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/README.markdown delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Resources/config/services.xml delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Resources/doc/index.rst delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/Command/LoadDataFixturesDoctrineCommandTest.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/DependentOnRequiredConstructorArgsFixtures.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/OtherFixtures.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/RequiredConstructorArgsFixtures.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/WithDependenciesFixtures.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/FooBundle.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/Tests/IntegrationTest.php delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/UPGRADE.md delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/composer.json delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/phpcs.xml.dist delete mode 100644 vendor/doctrine/doctrine-fixtures-bundle/phpunit.xml.dist delete mode 100644 vendor/doctrine/event-manager/.doctrine-project.json delete mode 100644 vendor/doctrine/event-manager/LICENSE delete mode 100644 vendor/doctrine/event-manager/README.md delete mode 100644 vendor/doctrine/event-manager/composer.json delete mode 100644 vendor/doctrine/event-manager/lib/Doctrine/Common/EventArgs.php delete mode 100644 vendor/doctrine/event-manager/lib/Doctrine/Common/EventManager.php delete mode 100644 vendor/doctrine/event-manager/lib/Doctrine/Common/EventSubscriber.php delete mode 100644 vendor/doctrine/inflector/LICENSE delete mode 100644 vendor/doctrine/inflector/README.md delete mode 100644 vendor/doctrine/inflector/composer.json delete mode 100644 vendor/doctrine/inflector/docs/en/index.rst delete mode 100644 vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php delete mode 100644 vendor/doctrine/instantiator/.doctrine-project.json delete mode 100644 vendor/doctrine/instantiator/.github/FUNDING.yml delete mode 100644 vendor/doctrine/instantiator/CONTRIBUTING.md delete mode 100644 vendor/doctrine/instantiator/LICENSE delete mode 100644 vendor/doctrine/instantiator/README.md delete mode 100644 vendor/doctrine/instantiator/composer.json delete mode 100644 vendor/doctrine/instantiator/docs/en/index.rst delete mode 100644 vendor/doctrine/instantiator/docs/en/sidebar.rst delete mode 100644 vendor/doctrine/instantiator/phpbench.json delete mode 100644 vendor/doctrine/instantiator/phpcs.xml.dist delete mode 100644 vendor/doctrine/instantiator/phpstan.neon.dist delete mode 100644 vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php delete mode 100644 vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php delete mode 100644 vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php delete mode 100644 vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php delete mode 100644 vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php delete mode 100644 vendor/doctrine/lexer/LICENSE delete mode 100644 vendor/doctrine/lexer/README.md delete mode 100644 vendor/doctrine/lexer/composer.json delete mode 100644 vendor/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php delete mode 100644 vendor/doctrine/orm/.scrutinizer.yml delete mode 100644 vendor/doctrine/orm/LICENSE delete mode 100644 vendor/doctrine/orm/README.md delete mode 100644 vendor/doctrine/orm/SECURITY.md delete mode 100644 vendor/doctrine/orm/UPGRADE.md delete mode 100755 vendor/doctrine/orm/bin/doctrine delete mode 100644 vendor/doctrine/orm/bin/doctrine-pear.php delete mode 100644 vendor/doctrine/orm/bin/doctrine.bat delete mode 100644 vendor/doctrine/orm/bin/doctrine.php delete mode 100644 vendor/doctrine/orm/composer.json delete mode 100644 vendor/doctrine/orm/composer.lock delete mode 100644 vendor/doctrine/orm/docs/LICENSE.md delete mode 100644 vendor/doctrine/orm/docs/README.md delete mode 100755 vendor/doctrine/orm/docs/bin/generate-docs.sh delete mode 100644 vendor/doctrine/orm/docs/bin/install-dependencies.sh delete mode 100644 vendor/doctrine/orm/docs/en/Makefile delete mode 100644 vendor/doctrine/orm/docs/en/_exts/configurationblock.py delete mode 100644 vendor/doctrine/orm/docs/en/conf.py delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/advanced-field-value-conversion-using-custom-mapping-types.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/aggregate-fields.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/custom-mapping-types.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/decorator-pattern.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/dql-custom-walkers.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/dql-user-defined-functions.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/entities-in-session.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/implementing-arrayaccess-for-domain-objects.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/implementing-the-notify-changetracking-policy.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/implementing-wakeup-or-clone.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/mysql-enums.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/resolve-target-entity-listener.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/sql-table-prefixes.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/strategy-cookbook-introduction.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/validation-of-entities.rst delete mode 100644 vendor/doctrine/orm/docs/en/cookbook/working-with-datetime.rst delete mode 100644 vendor/doctrine/orm/docs/en/index.rst delete mode 100644 vendor/doctrine/orm/docs/en/make.bat delete mode 100644 vendor/doctrine/orm/docs/en/reference/advanced-configuration.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/annotations-reference.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/architecture.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/association-mapping.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/basic-mapping.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/batch-processing.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/best-practices.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/caching.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/change-tracking-policies.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/configuration.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/dql-doctrine-query-language.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/events.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/faq.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/filters.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/improving-performance.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/inheritance-mapping.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/installation.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/limitations-and-known-issues.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/metadata-drivers.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/namingstrategy.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/native-sql.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/partial-objects.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/php-mapping.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/query-builder.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/second-level-cache.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/security.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/tools.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/transactions-and-concurrency.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/unitofwork-associations.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/unitofwork.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/working-with-associations.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/working-with-objects.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/xml-mapping.rst delete mode 100644 vendor/doctrine/orm/docs/en/reference/yaml-mapping.rst delete mode 100644 vendor/doctrine/orm/docs/en/sidebar.rst delete mode 100644 vendor/doctrine/orm/docs/en/toc.rst delete mode 100644 vendor/doctrine/orm/docs/en/tutorials/composite-primary-keys.rst delete mode 100644 vendor/doctrine/orm/docs/en/tutorials/embeddables.rst delete mode 100644 vendor/doctrine/orm/docs/en/tutorials/extra-lazy-associations.rst delete mode 100644 vendor/doctrine/orm/docs/en/tutorials/getting-started-database.rst delete mode 100644 vendor/doctrine/orm/docs/en/tutorials/getting-started-models.rst delete mode 100644 vendor/doctrine/orm/docs/en/tutorials/getting-started.rst delete mode 100644 vendor/doctrine/orm/docs/en/tutorials/ordered-associations.rst delete mode 100644 vendor/doctrine/orm/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst delete mode 100644 vendor/doctrine/orm/docs/en/tutorials/pagination.rst delete mode 100644 vendor/doctrine/orm/docs/en/tutorials/working-with-indexed-associations.rst delete mode 100644 vendor/doctrine/orm/doctrine-mapping.xsd delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/AssociationCacheEntry.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheConfiguration.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheEntry.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheFactory.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheKey.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheEntry.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheKey.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionHydrator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/ConcurrentRegion.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCache.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCacheFactory.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCollectionHydrator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultEntityHydrator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultQueryCache.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheEntry.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheKey.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityHydrator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Lock.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/LockException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLogger.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLoggerChain.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/StatisticsCacheLogger.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/MultiGetRegion.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/CachedPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/AbstractCollectionPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/CachedCollectionPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/NonStrictReadWriteCachedCollectionPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/AbstractEntityPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/CachedEntityPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/NonStrictReadWriteCachedEntityPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadOnlyCachedEntityPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCache.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheEntry.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheKey.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheValidator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultMultiGetRegion.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultRegion.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/FileLockRegion.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/UpdateTimestampCache.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/RegionsConfiguration.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheEntry.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheKey.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampQueryCacheValidator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampRegion.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Configuration.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Decorator/EntityManagerDecorator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/EntityManagerInterface.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/EntityNotFoundException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/LifecycleEventArgs.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/ListenersInvoker.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClassMetadataNotFoundEventArgs.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClearEventArgs.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnFlushEventArgs.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/PostFlushEventArgs.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreFlushEventArgs.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Events.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/AbstractIdGenerator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/AssignedGenerator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/BigIntegerIdentityGenerator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/IdentityGenerator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/SequenceGenerator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/TableGenerator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Id/UuidGenerator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/CommitOrderCalculator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/HydrationException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/IterableResult.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ScalarHydrator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Internal/HydrationCompleteHandler.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/LazyCriteriaCollection.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Annotation.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AnsiQuoteStrategy.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverride.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverrides.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverride.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverrides.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EmbeddedBuilder.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EntityListenerBuilder.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ManyToManyAssociationBuilder.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/OneToManyAssociationBuilder.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Cache.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ChangeTrackingPolicy.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadata.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Column.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ColumnResult.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/CustomIdGenerator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultEntityListenerResolver.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultNamingStrategy.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultQuoteStrategy.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorColumn.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorMap.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DriverChain.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/PHPDriver.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedXmlDriver.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedYamlDriver.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/StaticPHPDriver.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embeddable.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embedded.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Entity.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListenerResolver.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListeners.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityResult.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/FieldResult.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/GeneratedValue.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/HasLifecycleCallbacks.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Id.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Index.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/InheritanceType.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumn.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumns.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinTable.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToMany.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToOne.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappedSuperclass.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappingException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQueries.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQuery.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQueries.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQuery.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamingStrategy.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToMany.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToOne.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OrderBy.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostLoad.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostPersist.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostRemove.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostUpdate.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreFlush.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PrePersist.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreRemove.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreUpdate.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/QuoteStrategy.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Reflection/ReflectionPropertiesGetter.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ReflectionEmbeddedProperty.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SequenceGenerator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMapping.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMappings.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Table.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UnderscoreNamingStrategy.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UniqueConstraint.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Version.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/NativeQuery.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/NoResultException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/NonUniqueResultException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/ORMException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/ORMInvalidArgumentException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/OptimisticLockException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/PersistentCollection.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/AbstractCollectionPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/CollectionPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/OneToManyPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/CachedPersisterContext.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/EntityPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/PersisterException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlExpressionVisitor.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlValueVisitor.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/PessimisticLockException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Autoloader.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Proxy.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ASTException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/AggregateExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticFactor.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticTerm.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/BetweenExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CoalesceExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CollectionMemberExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ComparisonExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalFactor.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalPrimary.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalTerm.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteClause.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteStatement.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/EmptyCollectionComparisonExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ExistsExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/FromClause.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AbsFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AvgFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitAndFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitOrFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CountFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentDateFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimeFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimestampFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateDiffFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/FunctionNode.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/IdentityFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LengthFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LocateFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MaxFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MinFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ModFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SqrtFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SumFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GeneralCaseExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GroupByClause.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/HavingClause.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IdentificationVariableDeclaration.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IndexBy.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InputParameter.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InstanceOfExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Join.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationDeclaration.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationPathExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinClassPathExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinVariableDeclaration.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/LikeExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Literal.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NewObjectExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Node.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullComparisonExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullIfExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByClause.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByItem.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ParenthesisExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PartialObjectExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PathExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/QuantifiedExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/RangeVariableDeclaration.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectClause.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectStatement.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleArithmeticExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleCaseExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectClause.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectExpression.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleWhenClause.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Subselect.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectFromClause.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectIdentificationVariableDeclaration.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateClause.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateItem.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateStatement.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhenClause.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhereClause.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleSelectExecutor.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Andx.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Base.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Comparison.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Composite.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/From.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Func.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/GroupBy.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Join.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Literal.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Math.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/OrderBy.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Orx.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Select.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Filter/SQLFilter.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/FilterCollection.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Lexer.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parameter.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParameterTypeInferer.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParserResult.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/Printer.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryExpressionVisitor.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMapping.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalker.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerAdapter.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChain.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChainIterator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/QueryBuilder.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Repository/RepositoryFactory.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/AttachEntityListenersListener.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/CollectionRegionCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/EntityRegionCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/MetadataCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryRegionCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/AbstractCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ValidateSchemaCommand.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Helper/EntityManagerHelper.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/MetadataFilter.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DebugUnitOfWorkListener.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DisconnectedClassMetadataFactory.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityGenerator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityRepositoryGenerator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaEventArgs.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaTableEventArgs.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ClassMetadataExporter.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ExportException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountWalker.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/Paginator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/RowNumberOverFunction.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ResolveTargetEntityListener.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaTool.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaValidator.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Setup.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolEvents.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolsException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/TransactionRequiredException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/UnexpectedResultException.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Utility/HierarchyDiscriminatorResolver.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Utility/IdentifierFlattener.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Utility/PersisterHelper.php delete mode 100644 vendor/doctrine/orm/lib/Doctrine/ORM/Version.php delete mode 100644 vendor/doctrine/orm/phpbench.json delete mode 100644 vendor/doctrine/orm/phpstan.neon delete mode 100644 vendor/doctrine/persistence/.doctrine-project.json delete mode 100644 vendor/doctrine/persistence/LICENSE delete mode 100644 vendor/doctrine/persistence/README.md delete mode 100644 vendor/doctrine/persistence/UPGRADE-1.2.md delete mode 100644 vendor/doctrine/persistence/composer.json delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/NotifyPropertyChanged.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/AbstractManagerRegistry.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/ConnectionRegistry.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Event/LifecycleEventArgs.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Event/LoadClassMetadataEventArgs.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Event/ManagerEventArgs.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Event/OnClearEventArgs.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Event/PreUpdateEventArgs.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/ManagerRegistry.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/ClassMetadata.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/ClassMetadataFactory.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/DefaultFileLocator.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/FileDriver.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/FileLocator.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/MappingDriver.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/MappingDriverChain.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/PHPDriver.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/StaticPHPDriver.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/Driver/SymfonyFileLocator.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/MappingException.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/ReflectionService.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Mapping/StaticReflectionService.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/ObjectManager.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/ObjectManagerAware.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/ObjectManagerDecorator.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/ObjectRepository.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/PersistentObject.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Proxy.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Common/PropertyChangedListener.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/AbstractManagerRegistry.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/ConnectionRegistry.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/LifecycleEventArgs.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/LoadClassMetadataEventArgs.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/ManagerEventArgs.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/OnClearEventArgs.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/PreUpdateEventArgs.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/ManagerRegistry.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/AbstractClassMetadataFactory.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/ClassMetadata.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/ClassMetadataFactory.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/AnnotationDriver.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/DefaultFileLocator.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileDriver.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileLocator.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/MappingDriver.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/MappingDriverChain.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/PHPDriver.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/StaticPHPDriver.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/SymfonyFileLocator.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/MappingException.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/ReflectionService.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/RuntimeReflectionService.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/StaticReflectionService.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/NotifyPropertyChanged.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectManager.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectManagerAware.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectManagerDecorator.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectRepository.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/PropertyChangedListener.php delete mode 100644 vendor/doctrine/persistence/lib/Doctrine/Persistence/Proxy.php delete mode 100644 vendor/doctrine/reflection/.scrutinizer.yml delete mode 100644 vendor/doctrine/reflection/LICENSE delete mode 100644 vendor/doctrine/reflection/README.md delete mode 100644 vendor/doctrine/reflection/composer.json delete mode 100644 vendor/doctrine/reflection/docs/en/index.rst delete mode 100644 vendor/doctrine/reflection/docs/en/reference/index.rst delete mode 100644 vendor/doctrine/reflection/docs/en/sidebar.rst delete mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ClassFinderInterface.php delete mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/Psr0FindFile.php delete mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ReflectionProviderInterface.php delete mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/RuntimePublicReflectionProperty.php delete mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionClass.php delete mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionMethod.php delete mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionParser.php delete mode 100644 vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionProperty.php delete mode 100644 vendor/doctrine/reflection/phpstan.neon delete mode 100644 vendor/jdorn/sql-formatter/.gitignore delete mode 100644 vendor/jdorn/sql-formatter/.travis.yml delete mode 100644 vendor/jdorn/sql-formatter/LICENSE.txt delete mode 100644 vendor/jdorn/sql-formatter/README.md delete mode 100644 vendor/jdorn/sql-formatter/composer.json delete mode 100644 vendor/jdorn/sql-formatter/composer.lock delete mode 100644 vendor/jdorn/sql-formatter/examples/cli.php delete mode 100644 vendor/jdorn/sql-formatter/examples/examples.php delete mode 100644 vendor/jdorn/sql-formatter/lib/SqlFormatter.php delete mode 100644 vendor/jdorn/sql-formatter/phpunit.xml.dist delete mode 100644 vendor/jdorn/sql-formatter/tests/SqlFormatterTest.php delete mode 100644 vendor/jdorn/sql-formatter/tests/clihighlight.html delete mode 100644 vendor/jdorn/sql-formatter/tests/compress.html delete mode 100644 vendor/jdorn/sql-formatter/tests/format-highlight.html delete mode 100644 vendor/jdorn/sql-formatter/tests/format.html delete mode 100644 vendor/jdorn/sql-formatter/tests/highlight.html delete mode 100644 vendor/jdorn/sql-formatter/tests/performance.php delete mode 100644 vendor/jdorn/sql-formatter/tests/sql.sql delete mode 100644 vendor/psr/cache/CHANGELOG.md delete mode 100644 vendor/psr/cache/LICENSE.txt delete mode 100644 vendor/psr/cache/README.md delete mode 100644 vendor/psr/cache/composer.json delete mode 100644 vendor/psr/cache/src/CacheException.php delete mode 100644 vendor/psr/cache/src/CacheItemInterface.php delete mode 100644 vendor/psr/cache/src/CacheItemPoolInterface.php delete mode 100644 vendor/psr/cache/src/InvalidArgumentException.php delete mode 100644 vendor/psr/container/.gitignore delete mode 100644 vendor/psr/container/LICENSE delete mode 100644 vendor/psr/container/README.md delete mode 100644 vendor/psr/container/composer.json delete mode 100644 vendor/psr/container/src/ContainerExceptionInterface.php delete mode 100644 vendor/psr/container/src/ContainerInterface.php delete mode 100644 vendor/psr/container/src/NotFoundExceptionInterface.php delete mode 100644 vendor/psr/event-dispatcher/.editorconfig delete mode 100644 vendor/psr/event-dispatcher/.gitignore delete mode 100644 vendor/psr/event-dispatcher/LICENSE delete mode 100644 vendor/psr/event-dispatcher/README.md delete mode 100644 vendor/psr/event-dispatcher/composer.json delete mode 100644 vendor/psr/event-dispatcher/src/EventDispatcherInterface.php delete mode 100644 vendor/psr/event-dispatcher/src/ListenerProviderInterface.php delete mode 100644 vendor/psr/event-dispatcher/src/StoppableEventInterface.php delete mode 100644 vendor/psr/log/.gitignore delete mode 100644 vendor/psr/log/LICENSE delete mode 100644 vendor/psr/log/Psr/Log/AbstractLogger.php delete mode 100644 vendor/psr/log/Psr/Log/InvalidArgumentException.php delete mode 100644 vendor/psr/log/Psr/Log/LogLevel.php delete mode 100644 vendor/psr/log/Psr/Log/LoggerAwareInterface.php delete mode 100644 vendor/psr/log/Psr/Log/LoggerAwareTrait.php delete mode 100644 vendor/psr/log/Psr/Log/LoggerInterface.php delete mode 100644 vendor/psr/log/Psr/Log/LoggerTrait.php delete mode 100644 vendor/psr/log/Psr/Log/NullLogger.php delete mode 100644 vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php delete mode 100644 vendor/psr/log/Psr/Log/Test/TestLogger.php delete mode 100644 vendor/psr/log/README.md delete mode 100644 vendor/psr/log/composer.json delete mode 100644 vendor/symfony/cache-contracts/.gitignore delete mode 100644 vendor/symfony/cache-contracts/CacheInterface.php delete mode 100644 vendor/symfony/cache-contracts/CacheTrait.php delete mode 100644 vendor/symfony/cache-contracts/CallbackInterface.php delete mode 100644 vendor/symfony/cache-contracts/ItemInterface.php delete mode 100644 vendor/symfony/cache-contracts/LICENSE delete mode 100644 vendor/symfony/cache-contracts/README.md delete mode 100644 vendor/symfony/cache-contracts/TagAwareCacheInterface.php delete mode 100644 vendor/symfony/cache-contracts/composer.json delete mode 100644 vendor/symfony/cache/.gitattributes delete mode 100644 vendor/symfony/cache/Adapter/AbstractAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/AdapterInterface.php delete mode 100644 vendor/symfony/cache/Adapter/ApcuAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/ArrayAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/ChainAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/DoctrineAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/FilesystemAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/MemcachedAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/NullAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/PdoAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/PhpArrayAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/PhpFilesAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/ProxyAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/Psr16Adapter.php delete mode 100644 vendor/symfony/cache/Adapter/RedisAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/TagAwareAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php delete mode 100644 vendor/symfony/cache/Adapter/TraceableAdapter.php delete mode 100644 vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php delete mode 100644 vendor/symfony/cache/CHANGELOG.md delete mode 100644 vendor/symfony/cache/CacheItem.php delete mode 100644 vendor/symfony/cache/DataCollector/CacheDataCollector.php delete mode 100644 vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php delete mode 100644 vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php delete mode 100644 vendor/symfony/cache/DependencyInjection/CachePoolPass.php delete mode 100644 vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php delete mode 100644 vendor/symfony/cache/DoctrineProvider.php delete mode 100644 vendor/symfony/cache/Exception/CacheException.php delete mode 100644 vendor/symfony/cache/Exception/InvalidArgumentException.php delete mode 100644 vendor/symfony/cache/Exception/LogicException.php delete mode 100644 vendor/symfony/cache/LICENSE delete mode 100644 vendor/symfony/cache/LockRegistry.php delete mode 100644 vendor/symfony/cache/Marshaller/DefaultMarshaller.php delete mode 100644 vendor/symfony/cache/Marshaller/DeflateMarshaller.php delete mode 100644 vendor/symfony/cache/Marshaller/MarshallerInterface.php delete mode 100644 vendor/symfony/cache/Marshaller/TagAwareMarshaller.php delete mode 100644 vendor/symfony/cache/PruneableInterface.php delete mode 100644 vendor/symfony/cache/Psr16Cache.php delete mode 100644 vendor/symfony/cache/README.md delete mode 100644 vendor/symfony/cache/ResettableInterface.php delete mode 100644 vendor/symfony/cache/Traits/AbstractAdapterTrait.php delete mode 100644 vendor/symfony/cache/Traits/ContractsTrait.php delete mode 100644 vendor/symfony/cache/Traits/FilesystemCommonTrait.php delete mode 100644 vendor/symfony/cache/Traits/FilesystemTrait.php delete mode 100644 vendor/symfony/cache/Traits/ProxyTrait.php delete mode 100644 vendor/symfony/cache/Traits/RedisClusterProxy.php delete mode 100644 vendor/symfony/cache/Traits/RedisProxy.php delete mode 100644 vendor/symfony/cache/Traits/RedisTrait.php delete mode 100644 vendor/symfony/cache/composer.json delete mode 100644 vendor/symfony/config/.gitattributes delete mode 100644 vendor/symfony/config/CHANGELOG.md delete mode 100644 vendor/symfony/config/ConfigCache.php delete mode 100644 vendor/symfony/config/ConfigCacheFactory.php delete mode 100644 vendor/symfony/config/ConfigCacheFactoryInterface.php delete mode 100644 vendor/symfony/config/ConfigCacheInterface.php delete mode 100644 vendor/symfony/config/Definition/ArrayNode.php delete mode 100644 vendor/symfony/config/Definition/BaseNode.php delete mode 100644 vendor/symfony/config/Definition/BooleanNode.php delete mode 100644 vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php delete mode 100644 vendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php delete mode 100644 vendor/symfony/config/Definition/Builder/BuilderAwareInterface.php delete mode 100644 vendor/symfony/config/Definition/Builder/EnumNodeDefinition.php delete mode 100644 vendor/symfony/config/Definition/Builder/ExprBuilder.php delete mode 100644 vendor/symfony/config/Definition/Builder/FloatNodeDefinition.php delete mode 100644 vendor/symfony/config/Definition/Builder/IntegerNodeDefinition.php delete mode 100644 vendor/symfony/config/Definition/Builder/MergeBuilder.php delete mode 100644 vendor/symfony/config/Definition/Builder/NodeBuilder.php delete mode 100644 vendor/symfony/config/Definition/Builder/NodeDefinition.php delete mode 100644 vendor/symfony/config/Definition/Builder/NodeParentInterface.php delete mode 100644 vendor/symfony/config/Definition/Builder/NormalizationBuilder.php delete mode 100644 vendor/symfony/config/Definition/Builder/NumericNodeDefinition.php delete mode 100644 vendor/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php delete mode 100644 vendor/symfony/config/Definition/Builder/ScalarNodeDefinition.php delete mode 100644 vendor/symfony/config/Definition/Builder/TreeBuilder.php delete mode 100644 vendor/symfony/config/Definition/Builder/ValidationBuilder.php delete mode 100644 vendor/symfony/config/Definition/Builder/VariableNodeDefinition.php delete mode 100644 vendor/symfony/config/Definition/ConfigurationInterface.php delete mode 100644 vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.php delete mode 100644 vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.php delete mode 100644 vendor/symfony/config/Definition/EnumNode.php delete mode 100644 vendor/symfony/config/Definition/Exception/DuplicateKeyException.php delete mode 100644 vendor/symfony/config/Definition/Exception/Exception.php delete mode 100644 vendor/symfony/config/Definition/Exception/ForbiddenOverwriteException.php delete mode 100644 vendor/symfony/config/Definition/Exception/InvalidConfigurationException.php delete mode 100644 vendor/symfony/config/Definition/Exception/InvalidDefinitionException.php delete mode 100644 vendor/symfony/config/Definition/Exception/InvalidTypeException.php delete mode 100644 vendor/symfony/config/Definition/Exception/UnsetKeyException.php delete mode 100644 vendor/symfony/config/Definition/FloatNode.php delete mode 100644 vendor/symfony/config/Definition/IntegerNode.php delete mode 100644 vendor/symfony/config/Definition/NodeInterface.php delete mode 100644 vendor/symfony/config/Definition/NumericNode.php delete mode 100644 vendor/symfony/config/Definition/Processor.php delete mode 100644 vendor/symfony/config/Definition/PrototypeNodeInterface.php delete mode 100644 vendor/symfony/config/Definition/PrototypedArrayNode.php delete mode 100644 vendor/symfony/config/Definition/ScalarNode.php delete mode 100644 vendor/symfony/config/Definition/VariableNode.php delete mode 100644 vendor/symfony/config/Exception/FileLoaderImportCircularReferenceException.php delete mode 100644 vendor/symfony/config/Exception/FileLocatorFileNotFoundException.php delete mode 100644 vendor/symfony/config/Exception/LoaderLoadException.php delete mode 100644 vendor/symfony/config/FileLocator.php delete mode 100644 vendor/symfony/config/FileLocatorInterface.php delete mode 100644 vendor/symfony/config/LICENSE delete mode 100644 vendor/symfony/config/Loader/DelegatingLoader.php delete mode 100644 vendor/symfony/config/Loader/FileLoader.php delete mode 100644 vendor/symfony/config/Loader/GlobFileLoader.php delete mode 100644 vendor/symfony/config/Loader/Loader.php delete mode 100644 vendor/symfony/config/Loader/LoaderInterface.php delete mode 100644 vendor/symfony/config/Loader/LoaderResolver.php delete mode 100644 vendor/symfony/config/Loader/LoaderResolverInterface.php delete mode 100644 vendor/symfony/config/README.md delete mode 100644 vendor/symfony/config/Resource/ClassExistenceResource.php delete mode 100644 vendor/symfony/config/Resource/ComposerResource.php delete mode 100644 vendor/symfony/config/Resource/DirectoryResource.php delete mode 100644 vendor/symfony/config/Resource/FileExistenceResource.php delete mode 100644 vendor/symfony/config/Resource/FileResource.php delete mode 100644 vendor/symfony/config/Resource/GlobResource.php delete mode 100644 vendor/symfony/config/Resource/ReflectionClassResource.php delete mode 100644 vendor/symfony/config/Resource/ResourceInterface.php delete mode 100644 vendor/symfony/config/Resource/SelfCheckingResourceChecker.php delete mode 100644 vendor/symfony/config/Resource/SelfCheckingResourceInterface.php delete mode 100644 vendor/symfony/config/ResourceCheckerConfigCache.php delete mode 100644 vendor/symfony/config/ResourceCheckerConfigCacheFactory.php delete mode 100644 vendor/symfony/config/ResourceCheckerInterface.php delete mode 100644 vendor/symfony/config/Util/Exception/InvalidXmlException.php delete mode 100644 vendor/symfony/config/Util/Exception/XmlParsingException.php delete mode 100644 vendor/symfony/config/Util/XmlUtils.php delete mode 100644 vendor/symfony/config/composer.json delete mode 100644 vendor/symfony/console/.gitattributes delete mode 100644 vendor/symfony/console/Application.php delete mode 100644 vendor/symfony/console/CHANGELOG.md delete mode 100644 vendor/symfony/console/Command/Command.php delete mode 100644 vendor/symfony/console/Command/HelpCommand.php delete mode 100644 vendor/symfony/console/Command/ListCommand.php delete mode 100644 vendor/symfony/console/Command/LockableTrait.php delete mode 100644 vendor/symfony/console/CommandLoader/CommandLoaderInterface.php delete mode 100644 vendor/symfony/console/CommandLoader/ContainerCommandLoader.php delete mode 100644 vendor/symfony/console/CommandLoader/FactoryCommandLoader.php delete mode 100644 vendor/symfony/console/ConsoleEvents.php delete mode 100644 vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php delete mode 100644 vendor/symfony/console/Descriptor/ApplicationDescription.php delete mode 100644 vendor/symfony/console/Descriptor/Descriptor.php delete mode 100644 vendor/symfony/console/Descriptor/DescriptorInterface.php delete mode 100644 vendor/symfony/console/Descriptor/JsonDescriptor.php delete mode 100644 vendor/symfony/console/Descriptor/MarkdownDescriptor.php delete mode 100644 vendor/symfony/console/Descriptor/TextDescriptor.php delete mode 100644 vendor/symfony/console/Descriptor/XmlDescriptor.php delete mode 100644 vendor/symfony/console/Event/ConsoleCommandEvent.php delete mode 100644 vendor/symfony/console/Event/ConsoleErrorEvent.php delete mode 100644 vendor/symfony/console/Event/ConsoleEvent.php delete mode 100644 vendor/symfony/console/Event/ConsoleTerminateEvent.php delete mode 100644 vendor/symfony/console/EventListener/ErrorListener.php delete mode 100644 vendor/symfony/console/Exception/CommandNotFoundException.php delete mode 100644 vendor/symfony/console/Exception/ExceptionInterface.php delete mode 100644 vendor/symfony/console/Exception/InvalidArgumentException.php delete mode 100644 vendor/symfony/console/Exception/InvalidOptionException.php delete mode 100644 vendor/symfony/console/Exception/LogicException.php delete mode 100644 vendor/symfony/console/Exception/NamespaceNotFoundException.php delete mode 100644 vendor/symfony/console/Exception/RuntimeException.php delete mode 100644 vendor/symfony/console/Formatter/OutputFormatter.php delete mode 100644 vendor/symfony/console/Formatter/OutputFormatterInterface.php delete mode 100644 vendor/symfony/console/Formatter/OutputFormatterStyle.php delete mode 100644 vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php delete mode 100644 vendor/symfony/console/Formatter/OutputFormatterStyleStack.php delete mode 100644 vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php delete mode 100644 vendor/symfony/console/Helper/DebugFormatterHelper.php delete mode 100644 vendor/symfony/console/Helper/DescriptorHelper.php delete mode 100644 vendor/symfony/console/Helper/Dumper.php delete mode 100644 vendor/symfony/console/Helper/FormatterHelper.php delete mode 100644 vendor/symfony/console/Helper/Helper.php delete mode 100644 vendor/symfony/console/Helper/HelperInterface.php delete mode 100644 vendor/symfony/console/Helper/HelperSet.php delete mode 100644 vendor/symfony/console/Helper/InputAwareHelper.php delete mode 100644 vendor/symfony/console/Helper/ProcessHelper.php delete mode 100644 vendor/symfony/console/Helper/ProgressBar.php delete mode 100644 vendor/symfony/console/Helper/ProgressIndicator.php delete mode 100644 vendor/symfony/console/Helper/QuestionHelper.php delete mode 100644 vendor/symfony/console/Helper/SymfonyQuestionHelper.php delete mode 100644 vendor/symfony/console/Helper/Table.php delete mode 100644 vendor/symfony/console/Helper/TableCell.php delete mode 100644 vendor/symfony/console/Helper/TableRows.php delete mode 100644 vendor/symfony/console/Helper/TableSeparator.php delete mode 100644 vendor/symfony/console/Helper/TableStyle.php delete mode 100644 vendor/symfony/console/Input/ArgvInput.php delete mode 100644 vendor/symfony/console/Input/ArrayInput.php delete mode 100644 vendor/symfony/console/Input/Input.php delete mode 100644 vendor/symfony/console/Input/InputArgument.php delete mode 100644 vendor/symfony/console/Input/InputAwareInterface.php delete mode 100644 vendor/symfony/console/Input/InputDefinition.php delete mode 100644 vendor/symfony/console/Input/InputInterface.php delete mode 100644 vendor/symfony/console/Input/InputOption.php delete mode 100644 vendor/symfony/console/Input/StreamableInputInterface.php delete mode 100644 vendor/symfony/console/Input/StringInput.php delete mode 100644 vendor/symfony/console/LICENSE delete mode 100644 vendor/symfony/console/Logger/ConsoleLogger.php delete mode 100644 vendor/symfony/console/Output/BufferedOutput.php delete mode 100644 vendor/symfony/console/Output/ConsoleOutput.php delete mode 100644 vendor/symfony/console/Output/ConsoleOutputInterface.php delete mode 100644 vendor/symfony/console/Output/ConsoleSectionOutput.php delete mode 100644 vendor/symfony/console/Output/NullOutput.php delete mode 100644 vendor/symfony/console/Output/Output.php delete mode 100644 vendor/symfony/console/Output/OutputInterface.php delete mode 100644 vendor/symfony/console/Output/StreamOutput.php delete mode 100644 vendor/symfony/console/Question/ChoiceQuestion.php delete mode 100644 vendor/symfony/console/Question/ConfirmationQuestion.php delete mode 100644 vendor/symfony/console/Question/Question.php delete mode 100644 vendor/symfony/console/README.md delete mode 100644 vendor/symfony/console/Resources/bin/hiddeninput.exe delete mode 100644 vendor/symfony/console/Style/OutputStyle.php delete mode 100644 vendor/symfony/console/Style/StyleInterface.php delete mode 100644 vendor/symfony/console/Style/SymfonyStyle.php delete mode 100644 vendor/symfony/console/Terminal.php delete mode 100644 vendor/symfony/console/Tester/ApplicationTester.php delete mode 100644 vendor/symfony/console/Tester/CommandTester.php delete mode 100644 vendor/symfony/console/Tester/TesterTrait.php delete mode 100644 vendor/symfony/console/composer.json delete mode 100644 vendor/symfony/dependency-injection/.gitattributes delete mode 100644 vendor/symfony/dependency-injection/Alias.php delete mode 100644 vendor/symfony/dependency-injection/Argument/ArgumentInterface.php delete mode 100644 vendor/symfony/dependency-injection/Argument/BoundArgument.php delete mode 100644 vendor/symfony/dependency-injection/Argument/IteratorArgument.php delete mode 100644 vendor/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php delete mode 100644 vendor/symfony/dependency-injection/Argument/RewindableGenerator.php delete mode 100644 vendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php delete mode 100644 vendor/symfony/dependency-injection/Argument/ServiceLocator.php delete mode 100644 vendor/symfony/dependency-injection/Argument/ServiceLocatorArgument.php delete mode 100644 vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php delete mode 100644 vendor/symfony/dependency-injection/CHANGELOG.md delete mode 100644 vendor/symfony/dependency-injection/ChildDefinition.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/AutowirePass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/Compiler.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/CompilerPassInterface.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/PassConfig.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php delete mode 100644 vendor/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php delete mode 100644 vendor/symfony/dependency-injection/Config/ContainerParametersResource.php delete mode 100644 vendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php delete mode 100644 vendor/symfony/dependency-injection/Container.php delete mode 100644 vendor/symfony/dependency-injection/ContainerAwareInterface.php delete mode 100644 vendor/symfony/dependency-injection/ContainerAwareTrait.php delete mode 100644 vendor/symfony/dependency-injection/ContainerBuilder.php delete mode 100644 vendor/symfony/dependency-injection/ContainerInterface.php delete mode 100644 vendor/symfony/dependency-injection/Definition.php delete mode 100644 vendor/symfony/dependency-injection/Dumper/Dumper.php delete mode 100644 vendor/symfony/dependency-injection/Dumper/DumperInterface.php delete mode 100644 vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php delete mode 100644 vendor/symfony/dependency-injection/Dumper/PhpDumper.php delete mode 100644 vendor/symfony/dependency-injection/Dumper/Preloader.php delete mode 100644 vendor/symfony/dependency-injection/Dumper/XmlDumper.php delete mode 100644 vendor/symfony/dependency-injection/Dumper/YamlDumper.php delete mode 100644 vendor/symfony/dependency-injection/EnvVarLoaderInterface.php delete mode 100644 vendor/symfony/dependency-injection/EnvVarProcessor.php delete mode 100644 vendor/symfony/dependency-injection/EnvVarProcessorInterface.php delete mode 100644 vendor/symfony/dependency-injection/Exception/AutowiringFailedException.php delete mode 100644 vendor/symfony/dependency-injection/Exception/BadMethodCallException.php delete mode 100644 vendor/symfony/dependency-injection/Exception/EnvNotFoundException.php delete mode 100644 vendor/symfony/dependency-injection/Exception/EnvParameterException.php delete mode 100644 vendor/symfony/dependency-injection/Exception/ExceptionInterface.php delete mode 100644 vendor/symfony/dependency-injection/Exception/InvalidArgumentException.php delete mode 100644 vendor/symfony/dependency-injection/Exception/InvalidParameterTypeException.php delete mode 100644 vendor/symfony/dependency-injection/Exception/LogicException.php delete mode 100644 vendor/symfony/dependency-injection/Exception/OutOfBoundsException.php delete mode 100644 vendor/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php delete mode 100644 vendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php delete mode 100644 vendor/symfony/dependency-injection/Exception/RuntimeException.php delete mode 100644 vendor/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php delete mode 100644 vendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php delete mode 100644 vendor/symfony/dependency-injection/ExpressionLanguage.php delete mode 100644 vendor/symfony/dependency-injection/ExpressionLanguageProvider.php delete mode 100644 vendor/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php delete mode 100644 vendor/symfony/dependency-injection/Extension/Extension.php delete mode 100644 vendor/symfony/dependency-injection/Extension/ExtensionInterface.php delete mode 100644 vendor/symfony/dependency-injection/Extension/PrependExtensionInterface.php delete mode 100644 vendor/symfony/dependency-injection/LICENSE delete mode 100644 vendor/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php delete mode 100644 vendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php delete mode 100644 vendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php delete mode 100644 vendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php delete mode 100644 vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php delete mode 100644 vendor/symfony/dependency-injection/Loader/ClosureLoader.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php delete mode 100644 vendor/symfony/dependency-injection/Loader/DirectoryLoader.php delete mode 100644 vendor/symfony/dependency-injection/Loader/FileLoader.php delete mode 100644 vendor/symfony/dependency-injection/Loader/GlobFileLoader.php delete mode 100644 vendor/symfony/dependency-injection/Loader/IniFileLoader.php delete mode 100644 vendor/symfony/dependency-injection/Loader/PhpFileLoader.php delete mode 100644 vendor/symfony/dependency-injection/Loader/XmlFileLoader.php delete mode 100644 vendor/symfony/dependency-injection/Loader/YamlFileLoader.php delete mode 100644 vendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd delete mode 100644 vendor/symfony/dependency-injection/Parameter.php delete mode 100644 vendor/symfony/dependency-injection/ParameterBag/ContainerBag.php delete mode 100644 vendor/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php delete mode 100644 vendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php delete mode 100644 vendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php delete mode 100644 vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php delete mode 100644 vendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php delete mode 100644 vendor/symfony/dependency-injection/README.md delete mode 100644 vendor/symfony/dependency-injection/Reference.php delete mode 100644 vendor/symfony/dependency-injection/ReverseContainer.php delete mode 100644 vendor/symfony/dependency-injection/ServiceLocator.php delete mode 100644 vendor/symfony/dependency-injection/TaggedContainerInterface.php delete mode 100644 vendor/symfony/dependency-injection/TypedReference.php delete mode 100644 vendor/symfony/dependency-injection/Variable.php delete mode 100644 vendor/symfony/dependency-injection/composer.json delete mode 100644 vendor/symfony/doctrine-bridge/.gitattributes delete mode 100644 vendor/symfony/doctrine-bridge/CHANGELOG.md delete mode 100644 vendor/symfony/doctrine-bridge/CacheWarmer/ProxyCacheWarmer.php delete mode 100644 vendor/symfony/doctrine-bridge/ContainerAwareEventManager.php delete mode 100644 vendor/symfony/doctrine-bridge/DataCollector/DoctrineDataCollector.php delete mode 100644 vendor/symfony/doctrine-bridge/DataCollector/ObjectParameter.php delete mode 100644 vendor/symfony/doctrine-bridge/DataFixtures/ContainerAwareLoader.php delete mode 100644 vendor/symfony/doctrine-bridge/DependencyInjection/AbstractDoctrineExtension.php delete mode 100644 vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/DoctrineValidationPass.php delete mode 100644 vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php delete mode 100644 vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterMappingsPass.php delete mode 100644 vendor/symfony/doctrine-bridge/DependencyInjection/Security/UserProvider/EntityFactory.php delete mode 100644 vendor/symfony/doctrine-bridge/Form/ChoiceList/DoctrineChoiceLoader.php delete mode 100644 vendor/symfony/doctrine-bridge/Form/ChoiceList/EntityLoaderInterface.php delete mode 100644 vendor/symfony/doctrine-bridge/Form/ChoiceList/IdReader.php delete mode 100644 vendor/symfony/doctrine-bridge/Form/ChoiceList/ORMQueryBuilderLoader.php delete mode 100644 vendor/symfony/doctrine-bridge/Form/DataTransformer/CollectionToArrayTransformer.php delete mode 100644 vendor/symfony/doctrine-bridge/Form/DoctrineOrmExtension.php delete mode 100644 vendor/symfony/doctrine-bridge/Form/DoctrineOrmTypeGuesser.php delete mode 100644 vendor/symfony/doctrine-bridge/Form/EventListener/MergeDoctrineCollectionListener.php delete mode 100644 vendor/symfony/doctrine-bridge/Form/Type/DoctrineType.php delete mode 100644 vendor/symfony/doctrine-bridge/Form/Type/EntityType.php delete mode 100644 vendor/symfony/doctrine-bridge/LICENSE delete mode 100644 vendor/symfony/doctrine-bridge/Logger/DbalLogger.php delete mode 100644 vendor/symfony/doctrine-bridge/ManagerRegistry.php delete mode 100644 vendor/symfony/doctrine-bridge/Messenger/AbstractDoctrineMiddleware.php delete mode 100644 vendor/symfony/doctrine-bridge/Messenger/DoctrineClearEntityManagerWorkerSubscriber.php delete mode 100644 vendor/symfony/doctrine-bridge/Messenger/DoctrineCloseConnectionMiddleware.php delete mode 100644 vendor/symfony/doctrine-bridge/Messenger/DoctrinePingConnectionMiddleware.php delete mode 100644 vendor/symfony/doctrine-bridge/Messenger/DoctrineTransactionMiddleware.php delete mode 100644 vendor/symfony/doctrine-bridge/PropertyInfo/DoctrineExtractor.php delete mode 100644 vendor/symfony/doctrine-bridge/README.md delete mode 100644 vendor/symfony/doctrine-bridge/Security/RememberMe/DoctrineTokenProvider.php delete mode 100644 vendor/symfony/doctrine-bridge/Security/User/EntityUserProvider.php delete mode 100644 vendor/symfony/doctrine-bridge/Security/User/UserLoaderInterface.php delete mode 100644 vendor/symfony/doctrine-bridge/Test/DoctrineTestHelper.php delete mode 100644 vendor/symfony/doctrine-bridge/Test/TestRepositoryFactory.php delete mode 100644 vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntity.php delete mode 100644 vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntityValidator.php delete mode 100644 vendor/symfony/doctrine-bridge/Validator/DoctrineInitializer.php delete mode 100644 vendor/symfony/doctrine-bridge/Validator/DoctrineLoader.php delete mode 100644 vendor/symfony/doctrine-bridge/composer.json delete mode 100644 vendor/symfony/error-handler/.gitattributes delete mode 100644 vendor/symfony/error-handler/BufferingLogger.php delete mode 100644 vendor/symfony/error-handler/CHANGELOG.md delete mode 100644 vendor/symfony/error-handler/Debug.php delete mode 100644 vendor/symfony/error-handler/DebugClassLoader.php delete mode 100644 vendor/symfony/error-handler/Error/ClassNotFoundError.php delete mode 100644 vendor/symfony/error-handler/Error/FatalError.php delete mode 100644 vendor/symfony/error-handler/Error/OutOfMemoryError.php delete mode 100644 vendor/symfony/error-handler/Error/UndefinedFunctionError.php delete mode 100644 vendor/symfony/error-handler/Error/UndefinedMethodError.php delete mode 100644 vendor/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php delete mode 100644 vendor/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php delete mode 100644 vendor/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php delete mode 100644 vendor/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php delete mode 100644 vendor/symfony/error-handler/ErrorHandler.php delete mode 100644 vendor/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php delete mode 100644 vendor/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php delete mode 100644 vendor/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php delete mode 100644 vendor/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php delete mode 100644 vendor/symfony/error-handler/Exception/FlattenException.php delete mode 100644 vendor/symfony/error-handler/Exception/SilencedErrorContext.php delete mode 100644 vendor/symfony/error-handler/LICENSE delete mode 100644 vendor/symfony/error-handler/README.md delete mode 100644 vendor/symfony/error-handler/Resources/assets/css/error.css delete mode 100644 vendor/symfony/error-handler/Resources/assets/css/exception.css delete mode 100644 vendor/symfony/error-handler/Resources/assets/css/exception_full.css delete mode 100644 vendor/symfony/error-handler/Resources/assets/images/chevron-right.svg delete mode 100644 vendor/symfony/error-handler/Resources/assets/images/favicon.png.base64 delete mode 100644 vendor/symfony/error-handler/Resources/assets/images/icon-book.svg delete mode 100644 vendor/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg delete mode 100644 vendor/symfony/error-handler/Resources/assets/images/icon-minus-square.svg delete mode 100644 vendor/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg delete mode 100644 vendor/symfony/error-handler/Resources/assets/images/icon-plus-square.svg delete mode 100644 vendor/symfony/error-handler/Resources/assets/images/icon-support.svg delete mode 100644 vendor/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php delete mode 100644 vendor/symfony/error-handler/Resources/assets/images/symfony-logo.svg delete mode 100644 vendor/symfony/error-handler/Resources/assets/js/exception.js delete mode 100644 vendor/symfony/error-handler/Resources/views/error.html.php delete mode 100644 vendor/symfony/error-handler/Resources/views/exception.html.php delete mode 100644 vendor/symfony/error-handler/Resources/views/exception_full.html.php delete mode 100644 vendor/symfony/error-handler/Resources/views/logs.html.php delete mode 100644 vendor/symfony/error-handler/Resources/views/trace.html.php delete mode 100644 vendor/symfony/error-handler/Resources/views/traces.html.php delete mode 100644 vendor/symfony/error-handler/Resources/views/traces_text.html.php delete mode 100644 vendor/symfony/error-handler/ThrowableUtils.php delete mode 100644 vendor/symfony/error-handler/composer.json delete mode 100644 vendor/symfony/event-dispatcher-contracts/.gitignore delete mode 100644 vendor/symfony/event-dispatcher-contracts/Event.php delete mode 100644 vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php delete mode 100644 vendor/symfony/event-dispatcher-contracts/LICENSE delete mode 100644 vendor/symfony/event-dispatcher-contracts/README.md delete mode 100644 vendor/symfony/event-dispatcher-contracts/composer.json delete mode 100644 vendor/symfony/event-dispatcher/.gitattributes delete mode 100644 vendor/symfony/event-dispatcher/CHANGELOG.md delete mode 100644 vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php delete mode 100644 vendor/symfony/event-dispatcher/Debug/WrappedListener.php delete mode 100644 vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php delete mode 100644 vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php delete mode 100644 vendor/symfony/event-dispatcher/EventDispatcher.php delete mode 100644 vendor/symfony/event-dispatcher/EventDispatcherInterface.php delete mode 100644 vendor/symfony/event-dispatcher/EventSubscriberInterface.php delete mode 100644 vendor/symfony/event-dispatcher/GenericEvent.php delete mode 100644 vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php delete mode 100644 vendor/symfony/event-dispatcher/LICENSE delete mode 100644 vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php delete mode 100644 vendor/symfony/event-dispatcher/README.md delete mode 100644 vendor/symfony/event-dispatcher/composer.json delete mode 100644 vendor/symfony/filesystem/.gitattributes delete mode 100644 vendor/symfony/filesystem/CHANGELOG.md delete mode 100644 vendor/symfony/filesystem/Exception/ExceptionInterface.php delete mode 100644 vendor/symfony/filesystem/Exception/FileNotFoundException.php delete mode 100644 vendor/symfony/filesystem/Exception/IOException.php delete mode 100644 vendor/symfony/filesystem/Exception/IOExceptionInterface.php delete mode 100644 vendor/symfony/filesystem/Exception/InvalidArgumentException.php delete mode 100644 vendor/symfony/filesystem/Filesystem.php delete mode 100644 vendor/symfony/filesystem/LICENSE delete mode 100644 vendor/symfony/filesystem/README.md delete mode 100644 vendor/symfony/filesystem/composer.json delete mode 100644 vendor/symfony/finder/.gitattributes delete mode 100644 vendor/symfony/finder/CHANGELOG.md delete mode 100644 vendor/symfony/finder/Comparator/Comparator.php delete mode 100644 vendor/symfony/finder/Comparator/DateComparator.php delete mode 100644 vendor/symfony/finder/Comparator/NumberComparator.php delete mode 100644 vendor/symfony/finder/Exception/AccessDeniedException.php delete mode 100644 vendor/symfony/finder/Exception/DirectoryNotFoundException.php delete mode 100644 vendor/symfony/finder/Finder.php delete mode 100644 vendor/symfony/finder/Gitignore.php delete mode 100644 vendor/symfony/finder/Glob.php delete mode 100644 vendor/symfony/finder/Iterator/CustomFilterIterator.php delete mode 100644 vendor/symfony/finder/Iterator/DateRangeFilterIterator.php delete mode 100644 vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php delete mode 100644 vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php delete mode 100644 vendor/symfony/finder/Iterator/FileTypeFilterIterator.php delete mode 100644 vendor/symfony/finder/Iterator/FilecontentFilterIterator.php delete mode 100644 vendor/symfony/finder/Iterator/FilenameFilterIterator.php delete mode 100644 vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php delete mode 100644 vendor/symfony/finder/Iterator/PathFilterIterator.php delete mode 100644 vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php delete mode 100644 vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php delete mode 100644 vendor/symfony/finder/Iterator/SortableIterator.php delete mode 100644 vendor/symfony/finder/LICENSE delete mode 100644 vendor/symfony/finder/README.md delete mode 100644 vendor/symfony/finder/SplFileInfo.php delete mode 100644 vendor/symfony/finder/composer.json delete mode 100644 vendor/symfony/framework-bundle/.gitattributes delete mode 100644 vendor/symfony/framework-bundle/CHANGELOG.md delete mode 100644 vendor/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php delete mode 100644 vendor/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php delete mode 100644 vendor/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php delete mode 100644 vendor/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php delete mode 100644 vendor/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php delete mode 100644 vendor/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php delete mode 100644 vendor/symfony/framework-bundle/Command/AboutCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/AbstractConfigCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/AssetsInstallCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/CacheClearCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/CachePoolClearCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/CachePoolDeleteCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/CachePoolListCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/CachePoolPruneCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/CacheWarmupCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/ConfigDebugCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/ContainerDebugCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/ContainerLintCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/DebugAutowiringCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/RouterDebugCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/RouterMatchCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/SecretsListCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/SecretsRemoveCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/SecretsSetCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/TranslationDebugCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/TranslationUpdateCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/WorkflowDumpCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/XliffLintCommand.php delete mode 100644 vendor/symfony/framework-bundle/Command/YamlLintCommand.php delete mode 100644 vendor/symfony/framework-bundle/Console/Application.php delete mode 100644 vendor/symfony/framework-bundle/Console/Descriptor/Descriptor.php delete mode 100644 vendor/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php delete mode 100644 vendor/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php delete mode 100644 vendor/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php delete mode 100644 vendor/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php delete mode 100644 vendor/symfony/framework-bundle/Console/Helper/DescriptorHelper.php delete mode 100644 vendor/symfony/framework-bundle/Controller/AbstractController.php delete mode 100644 vendor/symfony/framework-bundle/Controller/ControllerResolver.php delete mode 100644 vendor/symfony/framework-bundle/Controller/RedirectController.php delete mode 100644 vendor/symfony/framework-bundle/Controller/TemplateController.php delete mode 100644 vendor/symfony/framework-bundle/DataCollector/RouterDataCollector.php delete mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php delete mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php delete mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php delete mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php delete mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php delete mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php delete mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php delete mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php delete mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php delete mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php delete mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php delete mode 100644 vendor/symfony/framework-bundle/DependencyInjection/Configuration.php delete mode 100644 vendor/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php delete mode 100644 vendor/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php delete mode 100644 vendor/symfony/framework-bundle/FrameworkBundle.php delete mode 100644 vendor/symfony/framework-bundle/HttpCache/HttpCache.php delete mode 100644 vendor/symfony/framework-bundle/Kernel/MicroKernelTrait.php delete mode 100644 vendor/symfony/framework-bundle/KernelBrowser.php delete mode 100644 vendor/symfony/framework-bundle/LICENSE delete mode 100644 vendor/symfony/framework-bundle/README.md delete mode 100644 vendor/symfony/framework-bundle/Resources/config/annotations.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/assets.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/cache.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/cache_debug.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/collectors.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/console.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/debug.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/debug_prod.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/error_renderer.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/esi.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/form.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/form_csrf.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/form_debug.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/fragment_listener.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/fragment_renderer.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/http_client.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/http_client_debug.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/identity_translator.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/lock.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/mailer.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/mailer_debug.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/mailer_transports.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/messenger.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/messenger_debug.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/mime_type.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/notifier.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/notifier_transports.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/profiling.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/property_access.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/property_info.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/request.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/routing.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/routing/errors.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd delete mode 100644 vendor/symfony/framework-bundle/Resources/config/secrets.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/security_csrf.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/serializer.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/services.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/session.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/ssi.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/test.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/translation.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/translation_debug.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/validator.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/validator_debug.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/web.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/web_link.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/config/workflow.xml delete mode 100644 vendor/symfony/framework-bundle/Resources/views/Form/week_widget.html.php delete mode 100644 vendor/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php delete mode 100644 vendor/symfony/framework-bundle/Routing/DelegatingLoader.php delete mode 100644 vendor/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php delete mode 100644 vendor/symfony/framework-bundle/Routing/RouteLoaderInterface.php delete mode 100644 vendor/symfony/framework-bundle/Routing/Router.php delete mode 100644 vendor/symfony/framework-bundle/Secrets/AbstractVault.php delete mode 100644 vendor/symfony/framework-bundle/Secrets/DotenvVault.php delete mode 100644 vendor/symfony/framework-bundle/Secrets/SodiumVault.php delete mode 100644 vendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php delete mode 100644 vendor/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php delete mode 100644 vendor/symfony/framework-bundle/Test/KernelTestCase.php delete mode 100644 vendor/symfony/framework-bundle/Test/MailerAssertionsTrait.php delete mode 100644 vendor/symfony/framework-bundle/Test/TestContainer.php delete mode 100644 vendor/symfony/framework-bundle/Test/WebTestAssertionsTrait.php delete mode 100644 vendor/symfony/framework-bundle/Test/WebTestCase.php delete mode 100644 vendor/symfony/framework-bundle/Translation/Translator.php delete mode 100644 vendor/symfony/framework-bundle/composer.json delete mode 100644 vendor/symfony/http-foundation/.gitattributes delete mode 100644 vendor/symfony/http-foundation/AcceptHeader.php delete mode 100644 vendor/symfony/http-foundation/AcceptHeaderItem.php delete mode 100644 vendor/symfony/http-foundation/BinaryFileResponse.php delete mode 100644 vendor/symfony/http-foundation/CHANGELOG.md delete mode 100644 vendor/symfony/http-foundation/Cookie.php delete mode 100644 vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php delete mode 100644 vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php delete mode 100644 vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php delete mode 100644 vendor/symfony/http-foundation/ExpressionRequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/FileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/NoFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/PartialFileException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php delete mode 100644 vendor/symfony/http-foundation/File/Exception/UploadException.php delete mode 100644 vendor/symfony/http-foundation/File/File.php delete mode 100644 vendor/symfony/http-foundation/File/Stream.php delete mode 100644 vendor/symfony/http-foundation/File/UploadedFile.php delete mode 100644 vendor/symfony/http-foundation/FileBag.php delete mode 100644 vendor/symfony/http-foundation/HeaderBag.php delete mode 100644 vendor/symfony/http-foundation/HeaderUtils.php delete mode 100644 vendor/symfony/http-foundation/IpUtils.php delete mode 100644 vendor/symfony/http-foundation/JsonResponse.php delete mode 100644 vendor/symfony/http-foundation/LICENSE delete mode 100644 vendor/symfony/http-foundation/ParameterBag.php delete mode 100644 vendor/symfony/http-foundation/README.md delete mode 100644 vendor/symfony/http-foundation/RedirectResponse.php delete mode 100644 vendor/symfony/http-foundation/Request.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcher.php delete mode 100644 vendor/symfony/http-foundation/RequestMatcherInterface.php delete mode 100644 vendor/symfony/http-foundation/RequestStack.php delete mode 100644 vendor/symfony/http-foundation/Response.php delete mode 100644 vendor/symfony/http-foundation/ResponseHeaderBag.php delete mode 100644 vendor/symfony/http-foundation/ServerBag.php delete mode 100644 vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php delete mode 100644 vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php delete mode 100644 vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php delete mode 100644 vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php delete mode 100644 vendor/symfony/http-foundation/Session/Flash/FlashBag.php delete mode 100644 vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php delete mode 100644 vendor/symfony/http-foundation/Session/Session.php delete mode 100644 vendor/symfony/http-foundation/Session/SessionBagInterface.php delete mode 100644 vendor/symfony/http-foundation/Session/SessionBagProxy.php delete mode 100644 vendor/symfony/http-foundation/Session/SessionInterface.php delete mode 100644 vendor/symfony/http-foundation/Session/SessionUtils.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/MetadataBag.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php delete mode 100644 vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php delete mode 100644 vendor/symfony/http-foundation/StreamedResponse.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php delete mode 100644 vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php delete mode 100644 vendor/symfony/http-foundation/UrlHelper.php delete mode 100644 vendor/symfony/http-foundation/composer.json delete mode 100644 vendor/symfony/http-kernel/.gitattributes delete mode 100644 vendor/symfony/http-kernel/Bundle/Bundle.php delete mode 100644 vendor/symfony/http-kernel/Bundle/BundleInterface.php delete mode 100644 vendor/symfony/http-kernel/CHANGELOG.md delete mode 100644 vendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.php delete mode 100644 vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php delete mode 100644 vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php delete mode 100644 vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php delete mode 100644 vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php delete mode 100644 vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php delete mode 100644 vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.php delete mode 100644 vendor/symfony/http-kernel/Config/FileLocator.php delete mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver.php delete mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php delete mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php delete mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php delete mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php delete mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php delete mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php delete mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php delete mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php delete mode 100644 vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php delete mode 100644 vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php delete mode 100644 vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php delete mode 100644 vendor/symfony/http-kernel/Controller/ControllerReference.php delete mode 100644 vendor/symfony/http-kernel/Controller/ControllerResolver.php delete mode 100644 vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php delete mode 100644 vendor/symfony/http-kernel/Controller/ErrorController.php delete mode 100644 vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php delete mode 100644 vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php delete mode 100644 vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php delete mode 100644 vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php delete mode 100644 vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php delete mode 100644 vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.php delete mode 100644 vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php delete mode 100644 vendor/symfony/http-kernel/DataCollector/DataCollector.php delete mode 100644 vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php delete mode 100644 vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php delete mode 100644 vendor/symfony/http-kernel/DataCollector/EventDataCollector.php delete mode 100644 vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php delete mode 100644 vendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php delete mode 100644 vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php delete mode 100644 vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php delete mode 100644 vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php delete mode 100644 vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php delete mode 100644 vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php delete mode 100644 vendor/symfony/http-kernel/Debug/FileLinkFormatter.php delete mode 100644 vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php delete mode 100644 vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php delete mode 100644 vendor/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php delete mode 100644 vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php delete mode 100644 vendor/symfony/http-kernel/DependencyInjection/Extension.php delete mode 100644 vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php delete mode 100644 vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php delete mode 100644 vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php delete mode 100644 vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php delete mode 100644 vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php delete mode 100644 vendor/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php delete mode 100644 vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php delete mode 100644 vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php delete mode 100644 vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php delete mode 100644 vendor/symfony/http-kernel/Event/ControllerArgumentsEvent.php delete mode 100644 vendor/symfony/http-kernel/Event/ControllerEvent.php delete mode 100644 vendor/symfony/http-kernel/Event/ExceptionEvent.php delete mode 100644 vendor/symfony/http-kernel/Event/FinishRequestEvent.php delete mode 100644 vendor/symfony/http-kernel/Event/KernelEvent.php delete mode 100644 vendor/symfony/http-kernel/Event/RequestEvent.php delete mode 100644 vendor/symfony/http-kernel/Event/ResponseEvent.php delete mode 100644 vendor/symfony/http-kernel/Event/TerminateEvent.php delete mode 100644 vendor/symfony/http-kernel/Event/ViewEvent.php delete mode 100644 vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/DumpListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/ErrorListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/FragmentListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/LocaleAwareListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/LocaleListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/ProfilerListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/ResponseListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/RouterListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/SessionListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/SurrogateListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/TestSessionListener.php delete mode 100644 vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php delete mode 100644 vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/BadRequestHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/ConflictHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php delete mode 100644 vendor/symfony/http-kernel/Exception/GoneHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/HttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/HttpExceptionInterface.php delete mode 100644 vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/NotFoundHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php delete mode 100644 vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php delete mode 100644 vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php delete mode 100644 vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.php delete mode 100644 vendor/symfony/http-kernel/Fragment/FragmentHandler.php delete mode 100644 vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php delete mode 100644 vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php delete mode 100644 vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php delete mode 100644 vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php delete mode 100644 vendor/symfony/http-kernel/Fragment/SsiFragmentRenderer.php delete mode 100644 vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php delete mode 100644 vendor/symfony/http-kernel/HttpCache/Esi.php delete mode 100644 vendor/symfony/http-kernel/HttpCache/HttpCache.php delete mode 100644 vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php delete mode 100644 vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php delete mode 100644 vendor/symfony/http-kernel/HttpCache/Ssi.php delete mode 100644 vendor/symfony/http-kernel/HttpCache/Store.php delete mode 100644 vendor/symfony/http-kernel/HttpCache/StoreInterface.php delete mode 100644 vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php delete mode 100644 vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php delete mode 100644 vendor/symfony/http-kernel/HttpClientKernel.php delete mode 100644 vendor/symfony/http-kernel/HttpKernel.php delete mode 100644 vendor/symfony/http-kernel/HttpKernelBrowser.php delete mode 100644 vendor/symfony/http-kernel/HttpKernelInterface.php delete mode 100644 vendor/symfony/http-kernel/Kernel.php delete mode 100644 vendor/symfony/http-kernel/KernelEvents.php delete mode 100644 vendor/symfony/http-kernel/KernelInterface.php delete mode 100644 vendor/symfony/http-kernel/LICENSE delete mode 100644 vendor/symfony/http-kernel/Log/DebugLoggerInterface.php delete mode 100644 vendor/symfony/http-kernel/Log/Logger.php delete mode 100644 vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php delete mode 100644 vendor/symfony/http-kernel/Profiler/Profile.php delete mode 100644 vendor/symfony/http-kernel/Profiler/Profiler.php delete mode 100644 vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php delete mode 100644 vendor/symfony/http-kernel/README.md delete mode 100644 vendor/symfony/http-kernel/RebootableInterface.php delete mode 100644 vendor/symfony/http-kernel/Resources/welcome.html.php delete mode 100644 vendor/symfony/http-kernel/TerminableInterface.php delete mode 100644 vendor/symfony/http-kernel/UriSigner.php delete mode 100644 vendor/symfony/http-kernel/composer.json delete mode 100644 vendor/symfony/mime/.gitattributes delete mode 100644 vendor/symfony/mime/Address.php delete mode 100644 vendor/symfony/mime/BodyRendererInterface.php delete mode 100644 vendor/symfony/mime/CHANGELOG.md delete mode 100644 vendor/symfony/mime/CharacterStream.php delete mode 100644 vendor/symfony/mime/Crypto/SMime.php delete mode 100644 vendor/symfony/mime/Crypto/SMimeEncrypter.php delete mode 100644 vendor/symfony/mime/Crypto/SMimeSigner.php delete mode 100644 vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php delete mode 100644 vendor/symfony/mime/Email.php delete mode 100644 vendor/symfony/mime/Encoder/AddressEncoderInterface.php delete mode 100644 vendor/symfony/mime/Encoder/Base64ContentEncoder.php delete mode 100644 vendor/symfony/mime/Encoder/Base64Encoder.php delete mode 100644 vendor/symfony/mime/Encoder/Base64MimeHeaderEncoder.php delete mode 100644 vendor/symfony/mime/Encoder/ContentEncoderInterface.php delete mode 100644 vendor/symfony/mime/Encoder/EightBitContentEncoder.php delete mode 100644 vendor/symfony/mime/Encoder/EncoderInterface.php delete mode 100644 vendor/symfony/mime/Encoder/IdnAddressEncoder.php delete mode 100644 vendor/symfony/mime/Encoder/MimeHeaderEncoderInterface.php delete mode 100644 vendor/symfony/mime/Encoder/QpContentEncoder.php delete mode 100644 vendor/symfony/mime/Encoder/QpEncoder.php delete mode 100644 vendor/symfony/mime/Encoder/QpMimeHeaderEncoder.php delete mode 100644 vendor/symfony/mime/Encoder/Rfc2231Encoder.php delete mode 100644 vendor/symfony/mime/Exception/AddressEncoderException.php delete mode 100644 vendor/symfony/mime/Exception/ExceptionInterface.php delete mode 100644 vendor/symfony/mime/Exception/InvalidArgumentException.php delete mode 100644 vendor/symfony/mime/Exception/LogicException.php delete mode 100644 vendor/symfony/mime/Exception/RfcComplianceException.php delete mode 100644 vendor/symfony/mime/Exception/RuntimeException.php delete mode 100644 vendor/symfony/mime/FileBinaryMimeTypeGuesser.php delete mode 100644 vendor/symfony/mime/FileinfoMimeTypeGuesser.php delete mode 100644 vendor/symfony/mime/Header/AbstractHeader.php delete mode 100644 vendor/symfony/mime/Header/DateHeader.php delete mode 100644 vendor/symfony/mime/Header/HeaderInterface.php delete mode 100644 vendor/symfony/mime/Header/Headers.php delete mode 100644 vendor/symfony/mime/Header/IdentificationHeader.php delete mode 100644 vendor/symfony/mime/Header/MailboxHeader.php delete mode 100644 vendor/symfony/mime/Header/MailboxListHeader.php delete mode 100644 vendor/symfony/mime/Header/ParameterizedHeader.php delete mode 100644 vendor/symfony/mime/Header/PathHeader.php delete mode 100644 vendor/symfony/mime/Header/UnstructuredHeader.php delete mode 100644 vendor/symfony/mime/LICENSE delete mode 100644 vendor/symfony/mime/Message.php delete mode 100644 vendor/symfony/mime/MessageConverter.php delete mode 100644 vendor/symfony/mime/MimeTypeGuesserInterface.php delete mode 100644 vendor/symfony/mime/MimeTypes.php delete mode 100644 vendor/symfony/mime/MimeTypesInterface.php delete mode 100644 vendor/symfony/mime/Part/AbstractMultipartPart.php delete mode 100644 vendor/symfony/mime/Part/AbstractPart.php delete mode 100644 vendor/symfony/mime/Part/DataPart.php delete mode 100644 vendor/symfony/mime/Part/MessagePart.php delete mode 100644 vendor/symfony/mime/Part/Multipart/AlternativePart.php delete mode 100644 vendor/symfony/mime/Part/Multipart/DigestPart.php delete mode 100644 vendor/symfony/mime/Part/Multipart/FormDataPart.php delete mode 100644 vendor/symfony/mime/Part/Multipart/MixedPart.php delete mode 100644 vendor/symfony/mime/Part/Multipart/RelatedPart.php delete mode 100644 vendor/symfony/mime/Part/SMimePart.php delete mode 100644 vendor/symfony/mime/Part/TextPart.php delete mode 100644 vendor/symfony/mime/README.md delete mode 100644 vendor/symfony/mime/RawMessage.php delete mode 100644 vendor/symfony/mime/Resources/bin/update_mime_types.php delete mode 100644 vendor/symfony/mime/Test/Constraint/EmailAddressContains.php delete mode 100644 vendor/symfony/mime/Test/Constraint/EmailAttachmentCount.php delete mode 100644 vendor/symfony/mime/Test/Constraint/EmailHasHeader.php delete mode 100644 vendor/symfony/mime/Test/Constraint/EmailHeaderSame.php delete mode 100644 vendor/symfony/mime/Test/Constraint/EmailHtmlBodyContains.php delete mode 100644 vendor/symfony/mime/Test/Constraint/EmailTextBodyContains.php delete mode 100644 vendor/symfony/mime/composer.json delete mode 100644 vendor/symfony/polyfill-ctype/Ctype.php delete mode 100644 vendor/symfony/polyfill-ctype/LICENSE delete mode 100644 vendor/symfony/polyfill-ctype/README.md delete mode 100644 vendor/symfony/polyfill-ctype/bootstrap.php delete mode 100644 vendor/symfony/polyfill-ctype/composer.json delete mode 100644 vendor/symfony/polyfill-intl-idn/Idn.php delete mode 100644 vendor/symfony/polyfill-intl-idn/LICENSE delete mode 100644 vendor/symfony/polyfill-intl-idn/README.md delete mode 100644 vendor/symfony/polyfill-intl-idn/bootstrap.php delete mode 100644 vendor/symfony/polyfill-intl-idn/composer.json delete mode 100644 vendor/symfony/polyfill-mbstring/LICENSE delete mode 100644 vendor/symfony/polyfill-mbstring/Mbstring.php delete mode 100644 vendor/symfony/polyfill-mbstring/README.md delete mode 100644 vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php delete mode 100644 vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php delete mode 100644 vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php delete mode 100644 vendor/symfony/polyfill-mbstring/bootstrap.php delete mode 100644 vendor/symfony/polyfill-mbstring/composer.json delete mode 100644 vendor/symfony/polyfill-php72/LICENSE delete mode 100644 vendor/symfony/polyfill-php72/Php72.php delete mode 100644 vendor/symfony/polyfill-php72/README.md delete mode 100644 vendor/symfony/polyfill-php72/bootstrap.php delete mode 100644 vendor/symfony/polyfill-php72/composer.json delete mode 100644 vendor/symfony/polyfill-php73/LICENSE delete mode 100644 vendor/symfony/polyfill-php73/Php73.php delete mode 100644 vendor/symfony/polyfill-php73/README.md delete mode 100644 vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php delete mode 100644 vendor/symfony/polyfill-php73/bootstrap.php delete mode 100644 vendor/symfony/polyfill-php73/composer.json delete mode 100644 vendor/symfony/routing/.gitattributes delete mode 100644 vendor/symfony/routing/Annotation/Route.php delete mode 100644 vendor/symfony/routing/CHANGELOG.md delete mode 100644 vendor/symfony/routing/CompiledRoute.php delete mode 100644 vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php delete mode 100644 vendor/symfony/routing/Exception/ExceptionInterface.php delete mode 100644 vendor/symfony/routing/Exception/InvalidParameterException.php delete mode 100644 vendor/symfony/routing/Exception/MethodNotAllowedException.php delete mode 100644 vendor/symfony/routing/Exception/MissingMandatoryParametersException.php delete mode 100644 vendor/symfony/routing/Exception/NoConfigurationException.php delete mode 100644 vendor/symfony/routing/Exception/ResourceNotFoundException.php delete mode 100644 vendor/symfony/routing/Exception/RouteNotFoundException.php delete mode 100644 vendor/symfony/routing/Generator/CompiledUrlGenerator.php delete mode 100644 vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php delete mode 100644 vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php delete mode 100644 vendor/symfony/routing/Generator/Dumper/GeneratorDumper.php delete mode 100644 vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php delete mode 100644 vendor/symfony/routing/Generator/UrlGenerator.php delete mode 100644 vendor/symfony/routing/Generator/UrlGeneratorInterface.php delete mode 100644 vendor/symfony/routing/LICENSE delete mode 100644 vendor/symfony/routing/Loader/AnnotationClassLoader.php delete mode 100644 vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php delete mode 100644 vendor/symfony/routing/Loader/AnnotationFileLoader.php delete mode 100644 vendor/symfony/routing/Loader/ClosureLoader.php delete mode 100644 vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php delete mode 100644 vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php delete mode 100644 vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php delete mode 100644 vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php delete mode 100644 vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php delete mode 100644 vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php delete mode 100644 vendor/symfony/routing/Loader/ContainerLoader.php delete mode 100644 vendor/symfony/routing/Loader/DirectoryLoader.php delete mode 100644 vendor/symfony/routing/Loader/GlobFileLoader.php delete mode 100644 vendor/symfony/routing/Loader/ObjectLoader.php delete mode 100644 vendor/symfony/routing/Loader/PhpFileLoader.php delete mode 100644 vendor/symfony/routing/Loader/XmlFileLoader.php delete mode 100644 vendor/symfony/routing/Loader/YamlFileLoader.php delete mode 100644 vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd delete mode 100644 vendor/symfony/routing/Matcher/CompiledUrlMatcher.php delete mode 100644 vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php delete mode 100644 vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php delete mode 100644 vendor/symfony/routing/Matcher/Dumper/MatcherDumper.php delete mode 100644 vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php delete mode 100644 vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php delete mode 100644 vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php delete mode 100644 vendor/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php delete mode 100644 vendor/symfony/routing/Matcher/RequestMatcherInterface.php delete mode 100644 vendor/symfony/routing/Matcher/TraceableUrlMatcher.php delete mode 100644 vendor/symfony/routing/Matcher/UrlMatcher.php delete mode 100644 vendor/symfony/routing/Matcher/UrlMatcherInterface.php delete mode 100644 vendor/symfony/routing/README.md delete mode 100644 vendor/symfony/routing/RequestContext.php delete mode 100644 vendor/symfony/routing/RequestContextAwareInterface.php delete mode 100644 vendor/symfony/routing/Route.php delete mode 100644 vendor/symfony/routing/RouteCollection.php delete mode 100644 vendor/symfony/routing/RouteCollectionBuilder.php delete mode 100644 vendor/symfony/routing/RouteCompiler.php delete mode 100644 vendor/symfony/routing/RouteCompilerInterface.php delete mode 100644 vendor/symfony/routing/Router.php delete mode 100644 vendor/symfony/routing/RouterInterface.php delete mode 100644 vendor/symfony/routing/composer.json delete mode 100644 vendor/symfony/service-contracts/.gitignore delete mode 100644 vendor/symfony/service-contracts/LICENSE delete mode 100644 vendor/symfony/service-contracts/README.md delete mode 100644 vendor/symfony/service-contracts/ResetInterface.php delete mode 100644 vendor/symfony/service-contracts/ServiceLocatorTrait.php delete mode 100644 vendor/symfony/service-contracts/ServiceProviderInterface.php delete mode 100644 vendor/symfony/service-contracts/ServiceSubscriberInterface.php delete mode 100644 vendor/symfony/service-contracts/ServiceSubscriberTrait.php delete mode 100644 vendor/symfony/service-contracts/Test/ServiceLocatorTest.php delete mode 100644 vendor/symfony/service-contracts/composer.json delete mode 100644 vendor/symfony/var-dumper/.gitattributes delete mode 100644 vendor/symfony/var-dumper/CHANGELOG.md delete mode 100644 vendor/symfony/var-dumper/Caster/AmqpCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/ArgsStub.php delete mode 100644 vendor/symfony/var-dumper/Caster/Caster.php delete mode 100644 vendor/symfony/var-dumper/Caster/ClassStub.php delete mode 100644 vendor/symfony/var-dumper/Caster/ConstStub.php delete mode 100644 vendor/symfony/var-dumper/Caster/CutArrayStub.php delete mode 100644 vendor/symfony/var-dumper/Caster/CutStub.php delete mode 100644 vendor/symfony/var-dumper/Caster/DOMCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/DateCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/DoctrineCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/DsCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/DsPairStub.php delete mode 100644 vendor/symfony/var-dumper/Caster/EnumStub.php delete mode 100644 vendor/symfony/var-dumper/Caster/ExceptionCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/FrameStub.php delete mode 100644 vendor/symfony/var-dumper/Caster/GmpCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/ImagineCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/ImgStub.php delete mode 100644 vendor/symfony/var-dumper/Caster/IntlCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/LinkStub.php delete mode 100644 vendor/symfony/var-dumper/Caster/MemcachedCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/PdoCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/PgSqlCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/RedisCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/ReflectionCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/ResourceCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/SplCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/StubCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/SymfonyCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/TraceStub.php delete mode 100644 vendor/symfony/var-dumper/Caster/UuidCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/XmlReaderCaster.php delete mode 100644 vendor/symfony/var-dumper/Caster/XmlResourceCaster.php delete mode 100644 vendor/symfony/var-dumper/Cloner/AbstractCloner.php delete mode 100644 vendor/symfony/var-dumper/Cloner/ClonerInterface.php delete mode 100644 vendor/symfony/var-dumper/Cloner/Cursor.php delete mode 100644 vendor/symfony/var-dumper/Cloner/Data.php delete mode 100644 vendor/symfony/var-dumper/Cloner/DumperInterface.php delete mode 100644 vendor/symfony/var-dumper/Cloner/Stub.php delete mode 100644 vendor/symfony/var-dumper/Cloner/VarCloner.php delete mode 100644 vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php delete mode 100644 vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php delete mode 100644 vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php delete mode 100644 vendor/symfony/var-dumper/Command/ServerDumpCommand.php delete mode 100644 vendor/symfony/var-dumper/Dumper/AbstractDumper.php delete mode 100644 vendor/symfony/var-dumper/Dumper/CliDumper.php delete mode 100644 vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php delete mode 100644 vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php delete mode 100644 vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php delete mode 100644 vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php delete mode 100644 vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php delete mode 100644 vendor/symfony/var-dumper/Dumper/DataDumperInterface.php delete mode 100644 vendor/symfony/var-dumper/Dumper/HtmlDumper.php delete mode 100644 vendor/symfony/var-dumper/Dumper/ServerDumper.php delete mode 100644 vendor/symfony/var-dumper/Exception/ThrowingCasterException.php delete mode 100644 vendor/symfony/var-dumper/LICENSE delete mode 100644 vendor/symfony/var-dumper/README.md delete mode 100755 vendor/symfony/var-dumper/Resources/bin/var-dump-server delete mode 100644 vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css delete mode 100644 vendor/symfony/var-dumper/Resources/functions/dump.php delete mode 100644 vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js delete mode 100644 vendor/symfony/var-dumper/Server/Connection.php delete mode 100644 vendor/symfony/var-dumper/Server/DumpServer.php delete mode 100644 vendor/symfony/var-dumper/Test/VarDumperTestTrait.php delete mode 100644 vendor/symfony/var-dumper/VarDumper.php delete mode 100644 vendor/symfony/var-dumper/composer.json delete mode 100644 vendor/symfony/var-exporter/.gitattributes delete mode 100644 vendor/symfony/var-exporter/CHANGELOG.md delete mode 100644 vendor/symfony/var-exporter/Exception/ClassNotFoundException.php delete mode 100644 vendor/symfony/var-exporter/Exception/ExceptionInterface.php delete mode 100644 vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php delete mode 100644 vendor/symfony/var-exporter/Instantiator.php delete mode 100644 vendor/symfony/var-exporter/Internal/Exporter.php delete mode 100644 vendor/symfony/var-exporter/Internal/Hydrator.php delete mode 100644 vendor/symfony/var-exporter/Internal/Reference.php delete mode 100644 vendor/symfony/var-exporter/Internal/Registry.php delete mode 100644 vendor/symfony/var-exporter/Internal/Values.php delete mode 100644 vendor/symfony/var-exporter/LICENSE delete mode 100644 vendor/symfony/var-exporter/README.md delete mode 100644 vendor/symfony/var-exporter/VarExporter.php delete mode 100644 vendor/symfony/var-exporter/composer.json diff --git a/vendor/autoload.php b/vendor/autoload.php deleted file mode 100644 index 21cc90a..0000000 --- a/vendor/autoload.php +++ /dev/null @@ -1,7 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Autoload; - -/** - * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. - * - * $loader = new \Composer\Autoload\ClassLoader(); - * - * // register classes with namespaces - * $loader->add('Symfony\Component', __DIR__.'/component'); - * $loader->add('Symfony', __DIR__.'/framework'); - * - * // activate the autoloader - * $loader->register(); - * - * // to enable searching the include path (eg. for PEAR packages) - * $loader->setUseIncludePath(true); - * - * In this example, if you try to use a class in the Symfony\Component - * namespace or one of its children (Symfony\Component\Console for instance), - * the autoloader will first look for the class under the component/ - * directory, and it will then fallback to the framework/ directory if not - * found before giving up. - * - * This class is loosely based on the Symfony UniversalClassLoader. - * - * @author Fabien Potencier - * @author Jordi Boggiano - * @see http://www.php-fig.org/psr/psr-0/ - * @see http://www.php-fig.org/psr/psr-4/ - */ -class ClassLoader -{ - // PSR-4 - private $prefixLengthsPsr4 = array(); - private $prefixDirsPsr4 = array(); - private $fallbackDirsPsr4 = array(); - - // PSR-0 - private $prefixesPsr0 = array(); - private $fallbackDirsPsr0 = array(); - - private $useIncludePath = false; - private $classMap = array(); - private $classMapAuthoritative = false; - private $missingClasses = array(); - private $apcuPrefix; - - public function getPrefixes() - { - if (!empty($this->prefixesPsr0)) { - return call_user_func_array('array_merge', $this->prefixesPsr0); - } - - return array(); - } - - public function getPrefixesPsr4() - { - return $this->prefixDirsPsr4; - } - - public function getFallbackDirs() - { - return $this->fallbackDirsPsr0; - } - - public function getFallbackDirsPsr4() - { - return $this->fallbackDirsPsr4; - } - - public function getClassMap() - { - return $this->classMap; - } - - /** - * @param array $classMap Class to filename map - */ - public function addClassMap(array $classMap) - { - if ($this->classMap) { - $this->classMap = array_merge($this->classMap, $classMap); - } else { - $this->classMap = $classMap; - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, either - * appending or prepending to the ones previously set for this prefix. - * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories - */ - public function add($prefix, $paths, $prepend = false) - { - if (!$prefix) { - if ($prepend) { - $this->fallbackDirsPsr0 = array_merge( - (array) $paths, - $this->fallbackDirsPsr0 - ); - } else { - $this->fallbackDirsPsr0 = array_merge( - $this->fallbackDirsPsr0, - (array) $paths - ); - } - - return; - } - - $first = $prefix[0]; - if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; - - return; - } - if ($prepend) { - $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, - $this->prefixesPsr0[$first][$prefix] - ); - } else { - $this->prefixesPsr0[$first][$prefix] = array_merge( - $this->prefixesPsr0[$first][$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, either - * appending or prepending to the ones previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories - * - * @throws \InvalidArgumentException - */ - public function addPsr4($prefix, $paths, $prepend = false) - { - if (!$prefix) { - // Register directories for the root namespace. - if ($prepend) { - $this->fallbackDirsPsr4 = array_merge( - (array) $paths, - $this->fallbackDirsPsr4 - ); - } else { - $this->fallbackDirsPsr4 = array_merge( - $this->fallbackDirsPsr4, - (array) $paths - ); - } - } elseif (!isset($this->prefixDirsPsr4[$prefix])) { - // Register directories for a new namespace. - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; - } elseif ($prepend) { - // Prepend directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, - $this->prefixDirsPsr4[$prefix] - ); - } else { - // Append directories for an already registered namespace. - $this->prefixDirsPsr4[$prefix] = array_merge( - $this->prefixDirsPsr4[$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of PSR-0 directories for a given prefix, - * replacing any others previously set for this prefix. - * - * @param string $prefix The prefix - * @param array|string $paths The PSR-0 base directories - */ - public function set($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr0 = (array) $paths; - } else { - $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; - } - } - - /** - * Registers a set of PSR-4 directories for a given namespace, - * replacing any others previously set for this namespace. - * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param array|string $paths The PSR-4 base directories - * - * @throws \InvalidArgumentException - */ - public function setPsr4($prefix, $paths) - { - if (!$prefix) { - $this->fallbackDirsPsr4 = (array) $paths; - } else { - $length = strlen($prefix); - if ('\\' !== $prefix[$length - 1]) { - throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); - } - $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; - } - } - - /** - * Turns on searching the include path for class files. - * - * @param bool $useIncludePath - */ - public function setUseIncludePath($useIncludePath) - { - $this->useIncludePath = $useIncludePath; - } - - /** - * Can be used to check if the autoloader uses the include path to check - * for classes. - * - * @return bool - */ - public function getUseIncludePath() - { - return $this->useIncludePath; - } - - /** - * Turns off searching the prefix and fallback directories for classes - * that have not been registered with the class map. - * - * @param bool $classMapAuthoritative - */ - public function setClassMapAuthoritative($classMapAuthoritative) - { - $this->classMapAuthoritative = $classMapAuthoritative; - } - - /** - * Should class lookup fail if not found in the current class map? - * - * @return bool - */ - public function isClassMapAuthoritative() - { - return $this->classMapAuthoritative; - } - - /** - * APCu prefix to use to cache found/not-found classes, if the extension is enabled. - * - * @param string|null $apcuPrefix - */ - public function setApcuPrefix($apcuPrefix) - { - $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; - } - - /** - * The APCu prefix in use, or null if APCu caching is not enabled. - * - * @return string|null - */ - public function getApcuPrefix() - { - return $this->apcuPrefix; - } - - /** - * Registers this instance as an autoloader. - * - * @param bool $prepend Whether to prepend the autoloader or not - */ - public function register($prepend = false) - { - spl_autoload_register(array($this, 'loadClass'), true, $prepend); - } - - /** - * Unregisters this instance as an autoloader. - */ - public function unregister() - { - spl_autoload_unregister(array($this, 'loadClass')); - } - - /** - * Loads the given class or interface. - * - * @param string $class The name of the class - * @return bool|null True if loaded, null otherwise - */ - public function loadClass($class) - { - if ($file = $this->findFile($class)) { - includeFile($file); - - return true; - } - } - - /** - * Finds the path to the file where the class is defined. - * - * @param string $class The name of the class - * - * @return string|false The path if found, false otherwise - */ - public function findFile($class) - { - // class map lookup - if (isset($this->classMap[$class])) { - return $this->classMap[$class]; - } - if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { - return false; - } - if (null !== $this->apcuPrefix) { - $file = apcu_fetch($this->apcuPrefix.$class, $hit); - if ($hit) { - return $file; - } - } - - $file = $this->findFileWithExtension($class, '.php'); - - // Search for Hack files if we are running on HHVM - if (false === $file && defined('HHVM_VERSION')) { - $file = $this->findFileWithExtension($class, '.hh'); - } - - if (null !== $this->apcuPrefix) { - apcu_add($this->apcuPrefix.$class, $file); - } - - if (false === $file) { - // Remember that this class does not exist. - $this->missingClasses[$class] = true; - } - - return $file; - } - - private function findFileWithExtension($class, $ext) - { - // PSR-4 lookup - $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; - - $first = $class[0]; - if (isset($this->prefixLengthsPsr4[$first])) { - $subPath = $class; - while (false !== $lastPos = strrpos($subPath, '\\')) { - $subPath = substr($subPath, 0, $lastPos); - $search = $subPath . '\\'; - if (isset($this->prefixDirsPsr4[$search])) { - $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); - foreach ($this->prefixDirsPsr4[$search] as $dir) { - if (file_exists($file = $dir . $pathEnd)) { - return $file; - } - } - } - } - } - - // PSR-4 fallback dirs - foreach ($this->fallbackDirsPsr4 as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { - return $file; - } - } - - // PSR-0 lookup - if (false !== $pos = strrpos($class, '\\')) { - // namespaced class name - $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) - . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); - } else { - // PEAR-like class name - $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; - } - - if (isset($this->prefixesPsr0[$first])) { - foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { - if (0 === strpos($class, $prefix)) { - foreach ($dirs as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - } - } - } - - // PSR-0 fallback dirs - foreach ($this->fallbackDirsPsr0 as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { - return $file; - } - } - - // PSR-0 include paths. - if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { - return $file; - } - - return false; - } -} - -/** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - */ -function includeFile($file) -{ - include $file; -} diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE deleted file mode 100644 index f27399a..0000000 --- a/vendor/composer/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ - -Copyright (c) Nils Adermann, Jordi Boggiano - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php deleted file mode 100644 index 0976ce8..0000000 --- a/vendor/composer/autoload_classmap.php +++ /dev/null @@ -1,11 +0,0 @@ - $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', - 'SqlFormatter' => $vendorDir . '/jdorn/sql-formatter/lib/SqlFormatter.php', -); diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php deleted file mode 100644 index 6fef1ad..0000000 --- a/vendor/composer/autoload_files.php +++ /dev/null @@ -1,15 +0,0 @@ - $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', - '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', - '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php', - 'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php', - '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', - '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php', -); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php deleted file mode 100644 index b7fc012..0000000 --- a/vendor/composer/autoload_namespaces.php +++ /dev/null @@ -1,9 +0,0 @@ - array($vendorDir . '/symfony/polyfill-php73'), - 'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'), - 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), - 'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'), - 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), - 'Symfony\\Contracts\\Service\\' => array($vendorDir . '/symfony/service-contracts'), - 'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'), - 'Symfony\\Contracts\\Cache\\' => array($vendorDir . '/symfony/cache-contracts'), - 'Symfony\\Component\\VarExporter\\' => array($vendorDir . '/symfony/var-exporter'), - 'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'), - 'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'), - 'Symfony\\Component\\Mime\\' => array($vendorDir . '/symfony/mime'), - 'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'), - 'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'), - 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'), - 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'), - 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'), - 'Symfony\\Component\\ErrorHandler\\' => array($vendorDir . '/symfony/error-handler'), - 'Symfony\\Component\\DependencyInjection\\' => array($vendorDir . '/symfony/dependency-injection'), - 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), - 'Symfony\\Component\\Config\\' => array($vendorDir . '/symfony/config'), - 'Symfony\\Component\\Cache\\' => array($vendorDir . '/symfony/cache'), - 'Symfony\\Bundle\\FrameworkBundle\\' => array($vendorDir . '/symfony/framework-bundle'), - 'Symfony\\Bridge\\Doctrine\\' => array($vendorDir . '/symfony/doctrine-bridge'), - 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), - 'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'), - 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), - 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'), - 'Doctrine\\Persistence\\' => array($vendorDir . '/doctrine/persistence/lib/Doctrine/Persistence'), - 'Doctrine\\ORM\\' => array($vendorDir . '/doctrine/orm/lib/Doctrine/ORM'), - 'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'), - 'Doctrine\\DBAL\\' => array($vendorDir . '/doctrine/dbal/lib/Doctrine/DBAL'), - 'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib/Doctrine/Common/Lexer'), - 'Doctrine\\Common\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Common/Inflector'), - 'Doctrine\\Common\\DataFixtures\\' => array($vendorDir . '/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures'), - 'Doctrine\\Common\\Collections\\' => array($vendorDir . '/doctrine/collections/lib/Doctrine/Common/Collections'), - 'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib/Doctrine/Common/Cache'), - 'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations'), - 'Doctrine\\Common\\' => array($vendorDir . '/doctrine/common/lib/Doctrine/Common', $vendorDir . '/doctrine/event-manager/lib/Doctrine/Common', $vendorDir . '/doctrine/persistence/lib/Doctrine/Common', $vendorDir . '/doctrine/reflection/lib/Doctrine/Common'), - 'Doctrine\\Bundle\\FixturesBundle\\' => array($vendorDir . '/doctrine/doctrine-fixtures-bundle'), - 'Doctrine\\Bundle\\DoctrineBundle\\' => array($vendorDir . '/doctrine/doctrine-bundle'), -); diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php deleted file mode 100644 index de8583e..0000000 --- a/vendor/composer/autoload_real.php +++ /dev/null @@ -1,70 +0,0 @@ -= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); - if ($useStaticLoader) { - require_once __DIR__ . '/autoload_static.php'; - - call_user_func(\Composer\Autoload\ComposerStaticInitd4f03afe1ff6c3294ecfb4f66aeebb22::getInitializer($loader)); - } else { - $map = require __DIR__ . '/autoload_namespaces.php'; - foreach ($map as $namespace => $path) { - $loader->set($namespace, $path); - } - - $map = require __DIR__ . '/autoload_psr4.php'; - foreach ($map as $namespace => $path) { - $loader->setPsr4($namespace, $path); - } - - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } - } - - $loader->register(true); - - if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInitd4f03afe1ff6c3294ecfb4f66aeebb22::$files; - } else { - $includeFiles = require __DIR__ . '/autoload_files.php'; - } - foreach ($includeFiles as $fileIdentifier => $file) { - composerRequired4f03afe1ff6c3294ecfb4f66aeebb22($fileIdentifier, $file); - } - - return $loader; - } -} - -function composerRequired4f03afe1ff6c3294ecfb4f66aeebb22($fileIdentifier, $file) -{ - if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - require $file; - - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - } -} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php deleted file mode 100644 index 2763690..0000000 --- a/vendor/composer/autoload_static.php +++ /dev/null @@ -1,255 +0,0 @@ - __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', - '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', - '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php', - 'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php', - '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', - '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php', - ); - - public static $prefixLengthsPsr4 = array ( - 'S' => - array ( - 'Symfony\\Polyfill\\Php73\\' => 23, - 'Symfony\\Polyfill\\Php72\\' => 23, - 'Symfony\\Polyfill\\Mbstring\\' => 26, - 'Symfony\\Polyfill\\Intl\\Idn\\' => 26, - 'Symfony\\Polyfill\\Ctype\\' => 23, - 'Symfony\\Contracts\\Service\\' => 26, - 'Symfony\\Contracts\\EventDispatcher\\' => 34, - 'Symfony\\Contracts\\Cache\\' => 24, - 'Symfony\\Component\\VarExporter\\' => 30, - 'Symfony\\Component\\VarDumper\\' => 28, - 'Symfony\\Component\\Routing\\' => 26, - 'Symfony\\Component\\Mime\\' => 23, - 'Symfony\\Component\\HttpKernel\\' => 29, - 'Symfony\\Component\\HttpFoundation\\' => 33, - 'Symfony\\Component\\Finder\\' => 25, - 'Symfony\\Component\\Filesystem\\' => 29, - 'Symfony\\Component\\EventDispatcher\\' => 34, - 'Symfony\\Component\\ErrorHandler\\' => 31, - 'Symfony\\Component\\DependencyInjection\\' => 38, - 'Symfony\\Component\\Console\\' => 26, - 'Symfony\\Component\\Config\\' => 25, - 'Symfony\\Component\\Cache\\' => 24, - 'Symfony\\Bundle\\FrameworkBundle\\' => 31, - 'Symfony\\Bridge\\Doctrine\\' => 24, - ), - 'P' => - array ( - 'Psr\\Log\\' => 8, - 'Psr\\EventDispatcher\\' => 20, - 'Psr\\Container\\' => 14, - 'Psr\\Cache\\' => 10, - ), - 'D' => - array ( - 'Doctrine\\Persistence\\' => 21, - 'Doctrine\\ORM\\' => 13, - 'Doctrine\\Instantiator\\' => 22, - 'Doctrine\\DBAL\\' => 14, - 'Doctrine\\Common\\Lexer\\' => 22, - 'Doctrine\\Common\\Inflector\\' => 26, - 'Doctrine\\Common\\DataFixtures\\' => 29, - 'Doctrine\\Common\\Collections\\' => 28, - 'Doctrine\\Common\\Cache\\' => 22, - 'Doctrine\\Common\\Annotations\\' => 28, - 'Doctrine\\Common\\' => 16, - 'Doctrine\\Bundle\\FixturesBundle\\' => 31, - 'Doctrine\\Bundle\\DoctrineBundle\\' => 31, - ), - ); - - public static $prefixDirsPsr4 = array ( - 'Symfony\\Polyfill\\Php73\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-php73', - ), - 'Symfony\\Polyfill\\Php72\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-php72', - ), - 'Symfony\\Polyfill\\Mbstring\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', - ), - 'Symfony\\Polyfill\\Intl\\Idn\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn', - ), - 'Symfony\\Polyfill\\Ctype\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', - ), - 'Symfony\\Contracts\\Service\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/service-contracts', - ), - 'Symfony\\Contracts\\EventDispatcher\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts', - ), - 'Symfony\\Contracts\\Cache\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/cache-contracts', - ), - 'Symfony\\Component\\VarExporter\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/var-exporter', - ), - 'Symfony\\Component\\VarDumper\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/var-dumper', - ), - 'Symfony\\Component\\Routing\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/routing', - ), - 'Symfony\\Component\\Mime\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/mime', - ), - 'Symfony\\Component\\HttpKernel\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/http-kernel', - ), - 'Symfony\\Component\\HttpFoundation\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/http-foundation', - ), - 'Symfony\\Component\\Finder\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/finder', - ), - 'Symfony\\Component\\Filesystem\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/filesystem', - ), - 'Symfony\\Component\\EventDispatcher\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/event-dispatcher', - ), - 'Symfony\\Component\\ErrorHandler\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/error-handler', - ), - 'Symfony\\Component\\DependencyInjection\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/dependency-injection', - ), - 'Symfony\\Component\\Console\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/console', - ), - 'Symfony\\Component\\Config\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/config', - ), - 'Symfony\\Component\\Cache\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/cache', - ), - 'Symfony\\Bundle\\FrameworkBundle\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/framework-bundle', - ), - 'Symfony\\Bridge\\Doctrine\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/doctrine-bridge', - ), - 'Psr\\Log\\' => - array ( - 0 => __DIR__ . '/..' . '/psr/log/Psr/Log', - ), - 'Psr\\EventDispatcher\\' => - array ( - 0 => __DIR__ . '/..' . '/psr/event-dispatcher/src', - ), - 'Psr\\Container\\' => - array ( - 0 => __DIR__ . '/..' . '/psr/container/src', - ), - 'Psr\\Cache\\' => - array ( - 0 => __DIR__ . '/..' . '/psr/cache/src', - ), - 'Doctrine\\Persistence\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/persistence/lib/Doctrine/Persistence', - ), - 'Doctrine\\ORM\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/orm/lib/Doctrine/ORM', - ), - 'Doctrine\\Instantiator\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/instantiator/src/Doctrine/Instantiator', - ), - 'Doctrine\\DBAL\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/dbal/lib/Doctrine/DBAL', - ), - 'Doctrine\\Common\\Lexer\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/lexer/lib/Doctrine/Common/Lexer', - ), - 'Doctrine\\Common\\Inflector\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/inflector/lib/Doctrine/Common/Inflector', - ), - 'Doctrine\\Common\\DataFixtures\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures', - ), - 'Doctrine\\Common\\Collections\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/collections/lib/Doctrine/Common/Collections', - ), - 'Doctrine\\Common\\Cache\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/cache/lib/Doctrine/Common/Cache', - ), - 'Doctrine\\Common\\Annotations\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations', - ), - 'Doctrine\\Common\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/common/lib/Doctrine/Common', - 1 => __DIR__ . '/..' . '/doctrine/event-manager/lib/Doctrine/Common', - 2 => __DIR__ . '/..' . '/doctrine/persistence/lib/Doctrine/Common', - 3 => __DIR__ . '/..' . '/doctrine/reflection/lib/Doctrine/Common', - ), - 'Doctrine\\Bundle\\FixturesBundle\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/doctrine-fixtures-bundle', - ), - 'Doctrine\\Bundle\\DoctrineBundle\\' => - array ( - 0 => __DIR__ . '/..' . '/doctrine/doctrine-bundle', - ), - ); - - public static $classMap = array ( - 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', - 'SqlFormatter' => __DIR__ . '/..' . '/jdorn/sql-formatter/lib/SqlFormatter.php', - ); - - public static function getInitializer(ClassLoader $loader) - { - return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInitd4f03afe1ff6c3294ecfb4f66aeebb22::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInitd4f03afe1ff6c3294ecfb4f66aeebb22::$prefixDirsPsr4; - $loader->classMap = ComposerStaticInitd4f03afe1ff6c3294ecfb4f66aeebb22::$classMap; - - }, null, ClassLoader::class); - } -} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json deleted file mode 100644 index 78a7c4b..0000000 --- a/vendor/composer/installed.json +++ /dev/null @@ -1,3078 +0,0 @@ -[ - { - "name": "doctrine/annotations", - "version": "v1.8.0", - "version_normalized": "1.8.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/904dca4eb10715b92569fbcd79e201d5c349b6bc", - "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc", - "shasum": "" - }, - "require": { - "doctrine/lexer": "1.*", - "php": "^7.1" - }, - "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "^7.5" - }, - "time": "2019-10-01T18:55:10+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "annotations", - "docblock", - "parser" - ] - }, - { - "name": "doctrine/cache", - "version": "1.10.0", - "version_normalized": "1.10.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "382e7f4db9a12dc6c19431743a2b096041bcdd62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/382e7f4db9a12dc6c19431743a2b096041bcdd62", - "reference": "382e7f4db9a12dc6c19431743a2b096041bcdd62", - "shasum": "" - }, - "require": { - "php": "~7.1" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "alcaeus/mongo-php-adapter": "^1.1", - "doctrine/coding-standard": "^6.0", - "mongodb/mongodb": "^1.1", - "phpunit/phpunit": "^7.0", - "predis/predis": "~1.0" - }, - "suggest": { - "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" - }, - "time": "2019-11-29T15:36:20+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", - "homepage": "https://www.doctrine-project.org/projects/cache.html", - "keywords": [ - "abstraction", - "apcu", - "cache", - "caching", - "couchdb", - "memcached", - "php", - "redis", - "xcache" - ] - }, - { - "name": "doctrine/collections", - "version": "1.6.4", - "version_normalized": "1.6.4.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/collections.git", - "reference": "6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7", - "reference": "6b1e4b2b66f6d6e49983cebfe23a21b7ccc5b0d7", - "shasum": "" - }, - "require": { - "php": "^7.1.3" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpstan/phpstan-shim": "^0.9.2", - "phpunit/phpunit": "^7.0", - "vimeo/psalm": "^3.2.2" - }, - "time": "2019-11-13T13:07:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", - "homepage": "https://www.doctrine-project.org/projects/collections.html", - "keywords": [ - "array", - "collections", - "iterators", - "php" - ] - }, - { - "name": "doctrine/common", - "version": "v2.11.0", - "version_normalized": "2.11.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/common.git", - "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", - "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.0", - "doctrine/cache": "^1.0", - "doctrine/collections": "^1.0", - "doctrine/event-manager": "^1.0", - "doctrine/inflector": "^1.0", - "doctrine/lexer": "^1.0", - "doctrine/persistence": "^1.1", - "doctrine/reflection": "^1.0", - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "^1.0", - "phpstan/phpstan": "^0.11", - "phpstan/phpstan-phpunit": "^0.11", - "phpunit/phpunit": "^7.0", - "squizlabs/php_codesniffer": "^3.0", - "symfony/phpunit-bridge": "^4.0.5" - }, - "time": "2019-09-10T10:10:14+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.11.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, persistence interfaces, proxies, event system and much more.", - "homepage": "https://www.doctrine-project.org/projects/common.html", - "keywords": [ - "common", - "doctrine", - "php" - ] - }, - { - "name": "doctrine/data-fixtures", - "version": "1.4.0", - "version_normalized": "1.4.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/data-fixtures.git", - "reference": "608a35a3b5bcc4214d116603095f8b0c51091592" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/608a35a3b5bcc4214d116603095f8b0c51091592", - "reference": "608a35a3b5bcc4214d116603095f8b0c51091592", - "shasum": "" - }, - "require": { - "doctrine/common": "^2.11", - "php": "^7.2" - }, - "conflict": { - "doctrine/phpcr-odm": "<1.3.0" - }, - "require-dev": { - "alcaeus/mongo-php-adapter": "^1.1", - "doctrine/coding-standard": "^6.0", - "doctrine/dbal": "^2.5.4", - "doctrine/mongodb-odm": "^1.3.0", - "doctrine/orm": "^2.5.4", - "phpunit/phpunit": "^7.0" - }, - "suggest": { - "alcaeus/mongo-php-adapter": "For using MongoDB ODM with PHP 7", - "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", - "doctrine/orm": "For loading ORM fixtures", - "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" - }, - "time": "2019-10-30T20:03:18+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\DataFixtures\\": "lib/Doctrine/Common/DataFixtures" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - } - ], - "description": "Data Fixtures for all Doctrine Object Managers", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "database" - ] - }, - { - "name": "doctrine/dbal", - "version": "v2.10.0", - "version_normalized": "2.10.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/dbal.git", - "reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/0c9a646775ef549eb0a213a4f9bd4381d9b4d934", - "reference": "0c9a646775ef549eb0a213a4f9bd4381d9b4d934", - "shasum": "" - }, - "require": { - "doctrine/cache": "^1.0", - "doctrine/event-manager": "^1.0", - "ext-pdo": "*", - "php": "^7.2" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "jetbrains/phpstorm-stubs": "^2019.1", - "phpstan/phpstan": "^0.11.3", - "phpunit/phpunit": "^8.4.1", - "symfony/console": "^2.0.5|^3.0|^4.0|^5.0" - }, - "suggest": { - "symfony/console": "For helpful console commands such as SQL execution and import of files." - }, - "time": "2019-11-03T16:50:43+00:00", - "bin": [ - "bin/doctrine-dbal" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.10.x-dev", - "dev-develop": "3.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\DBAL\\": "lib/Doctrine/DBAL" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - } - ], - "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", - "homepage": "https://www.doctrine-project.org/projects/dbal.html", - "keywords": [ - "abstraction", - "database", - "db2", - "dbal", - "mariadb", - "mssql", - "mysql", - "oci8", - "oracle", - "pdo", - "pgsql", - "postgresql", - "queryobject", - "sasql", - "sql", - "sqlanywhere", - "sqlite", - "sqlserver", - "sqlsrv" - ] - }, - { - "name": "doctrine/doctrine-bundle", - "version": "2.0.6", - "version_normalized": "2.0.6.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "0ef972d3b730f975c80db9fffa4b2a0258c91442" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/0ef972d3b730f975c80db9fffa4b2a0258c91442", - "reference": "0ef972d3b730f975c80db9fffa4b2a0258c91442", - "shasum": "" - }, - "require": { - "doctrine/dbal": "^2.9.0", - "doctrine/persistence": "^1.3.3", - "jdorn/sql-formatter": "^1.2.16", - "php": "^7.1", - "symfony/cache": "^4.3.3|^5.0", - "symfony/config": "^4.3.3|^5.0", - "symfony/console": "^3.4.30|^4.3.3|^5.0", - "symfony/dependency-injection": "^4.3.3|^5.0", - "symfony/doctrine-bridge": "^4.3.7|^5.0", - "symfony/framework-bundle": "^3.4.30|^4.3.3|^5.0", - "symfony/service-contracts": "^1.1.1|^2.0" - }, - "conflict": { - "doctrine/orm": "<2.6", - "twig/twig": "<1.34|>=2.0,<2.4" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "doctrine/orm": "^2.6", - "ocramius/proxy-manager": "^2.1", - "phpunit/phpunit": "^7.5", - "symfony/phpunit-bridge": "^4.2", - "symfony/property-info": "^4.3.3|^5.0", - "symfony/twig-bridge": "^3.4.30|^4.3.3|^5.0", - "symfony/validator": "^3.4.30|^4.3.3|^5.0", - "symfony/web-profiler-bundle": "^3.4.30|^4.3.3|^5.0", - "symfony/yaml": "^3.4.30|^4.3.3|^5.0", - "twig/twig": "^1.34|^2.12" - }, - "suggest": { - "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", - "symfony/web-profiler-bundle": "To use the data collector." - }, - "time": "2019-12-19T13:47:07+00:00", - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Bundle\\DoctrineBundle\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Doctrine Project", - "homepage": "http://www.doctrine-project.org/" - } - ], - "description": "Symfony DoctrineBundle", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "database", - "dbal", - "orm", - "persistence" - ] - }, - { - "name": "doctrine/doctrine-fixtures-bundle", - "version": "3.3.0", - "version_normalized": "3.3.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/DoctrineFixturesBundle.git", - "reference": "8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70", - "reference": "8f07fcfdac7f3591f3c4bf13a50cbae05f65ed70", - "shasum": "" - }, - "require": { - "doctrine/data-fixtures": "^1.3", - "doctrine/doctrine-bundle": "^1.11|^2.0", - "doctrine/orm": "^2.6.0", - "php": "^7.1", - "symfony/config": "^3.4|^4.3|^5.0", - "symfony/console": "^3.4|^4.3|^5.0", - "symfony/dependency-injection": "^3.4|^4.3|^5.0", - "symfony/doctrine-bridge": "^3.4|^4.1|^5.0", - "symfony/http-kernel": "^3.4|^4.3|^5.0" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpunit/phpunit": "^7.4", - "symfony/phpunit-bridge": "^4.1|^5.0" - }, - "time": "2019-11-13T15:46:58+00:00", - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "3.3.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Bundle\\FixturesBundle\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Doctrine Project", - "homepage": "http://www.doctrine-project.org" - }, - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - } - ], - "description": "Symfony DoctrineFixturesBundle", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "Fixture", - "persistence" - ] - }, - { - "name": "doctrine/event-manager", - "version": "1.1.0", - "version_normalized": "1.1.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/event-manager.git", - "reference": "629572819973f13486371cb611386eb17851e85c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/629572819973f13486371cb611386eb17851e85c", - "reference": "629572819973f13486371cb611386eb17851e85c", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "conflict": { - "doctrine/common": "<2.9@dev" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpunit/phpunit": "^7.0" - }, - "time": "2019-11-10T09:48:07+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", - "homepage": "https://www.doctrine-project.org/projects/event-manager.html", - "keywords": [ - "event", - "event dispatcher", - "event manager", - "event system", - "events" - ] - }, - { - "name": "doctrine/inflector", - "version": "1.3.1", - "version_normalized": "1.3.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/ec3a55242203ffa6a4b27c58176da97ff0a7aec1", - "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^6.2" - }, - "time": "2019-10-30T19:59:35+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Common String Manipulations with regard to casing and singular/plural rules.", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "inflection", - "pluralize", - "singularize", - "string" - ] - }, - { - "name": "doctrine/instantiator", - "version": "1.3.0", - "version_normalized": "1.3.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.13", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-shim": "^0.11", - "phpunit/phpunit": "^7.0" - }, - "time": "2019-10-21T16:45:58+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ] - }, - { - "name": "doctrine/lexer", - "version": "1.2.0", - "version_normalized": "1.2.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", - "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", - "shasum": "" - }, - "require": { - "php": "^7.2" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpstan/phpstan": "^0.11.8", - "phpunit/phpunit": "^8.2" - }, - "time": "2019-10-30T14:39:59+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ] - }, - { - "name": "doctrine/orm", - "version": "v2.7.0", - "version_normalized": "2.7.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/orm.git", - "reference": "4d763ca4c925f647b248b9fa01b5f47aa3685d62" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/4d763ca4c925f647b248b9fa01b5f47aa3685d62", - "reference": "4d763ca4c925f647b248b9fa01b5f47aa3685d62", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.8", - "doctrine/cache": "^1.9.1", - "doctrine/collections": "^1.5", - "doctrine/common": "^2.11", - "doctrine/dbal": "^2.9.3", - "doctrine/event-manager": "^1.1", - "doctrine/instantiator": "^1.3", - "doctrine/persistence": "^1.2", - "ext-pdo": "*", - "php": "^7.1", - "symfony/console": "^3.0|^4.0|^5.0" - }, - "require-dev": { - "doctrine/coding-standard": "^5.0", - "phpunit/phpunit": "^7.5", - "symfony/yaml": "^3.4|^4.0|^5.0" - }, - "suggest": { - "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" - }, - "time": "2019-11-19T08:38:05+00:00", - "bin": [ - "bin/doctrine" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\ORM\\": "lib/Doctrine/ORM" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "Object-Relational-Mapper for PHP", - "homepage": "https://www.doctrine-project.org/projects/orm.html", - "keywords": [ - "database", - "orm" - ] - }, - { - "name": "doctrine/persistence", - "version": "1.3.3", - "version_normalized": "1.3.3.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/persistence.git", - "reference": "99b196bbd4715a94fa100fac664a351ffa46d6a5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/99b196bbd4715a94fa100fac664a351ffa46d6a5", - "reference": "99b196bbd4715a94fa100fac664a351ffa46d6a5", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.0", - "doctrine/cache": "^1.0", - "doctrine/collections": "^1.0", - "doctrine/event-manager": "^1.0", - "doctrine/reflection": "^1.0", - "php": "^7.1" - }, - "conflict": { - "doctrine/common": "<2.10@dev" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpstan/phpstan": "^0.11", - "phpunit/phpunit": "^7.0" - }, - "time": "2019-12-13T10:43:02+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common", - "Doctrine\\Persistence\\": "lib/Doctrine/Persistence" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", - "homepage": "https://doctrine-project.org/projects/persistence.html", - "keywords": [ - "mapper", - "object", - "odm", - "orm", - "persistence" - ] - }, - { - "name": "doctrine/reflection", - "version": "v1.0.0", - "version_normalized": "1.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/reflection.git", - "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/reflection/zipball/02538d3f95e88eb397a5f86274deb2c6175c2ab6", - "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.0", - "ext-tokenizer": "*", - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "^4.0", - "doctrine/common": "^2.8", - "phpstan/phpstan": "^0.9.2", - "phpstan/phpstan-phpunit": "^0.9.4", - "phpunit/phpunit": "^7.0", - "squizlabs/php_codesniffer": "^3.0" - }, - "time": "2018-06-14T14:45:07+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "Doctrine Reflection component", - "homepage": "https://www.doctrine-project.org/projects/reflection.html", - "keywords": [ - "reflection" - ] - }, - { - "name": "jdorn/sql-formatter", - "version": "v1.2.17", - "version_normalized": "1.2.17.0", - "source": { - "type": "git", - "url": "https://github.com/jdorn/sql-formatter.git", - "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jdorn/sql-formatter/zipball/64990d96e0959dff8e059dfcdc1af130728d92bc", - "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc", - "shasum": "" - }, - "require": { - "php": ">=5.2.4" - }, - "require-dev": { - "phpunit/phpunit": "3.7.*" - }, - "time": "2014-01-12T16:20:24+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "classmap": [ - "lib" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jeremy Dorn", - "email": "jeremy@jeremydorn.com", - "homepage": "http://jeremydorn.com/" - } - ], - "description": "a PHP SQL highlighting library", - "homepage": "https://github.com/jdorn/sql-formatter/", - "keywords": [ - "highlight", - "sql" - ] - }, - { - "name": "psr/cache", - "version": "1.0.1", - "version_normalized": "1.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2016-08-06T20:24:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ] - }, - { - "name": "psr/container", - "version": "1.0.0", - "version_normalized": "1.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2017-02-14T16:28:37+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ] - }, - { - "name": "psr/event-dispatcher", - "version": "1.0.0", - "version_normalized": "1.0.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "time": "2019-01-08T18:20:26+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ] - }, - { - "name": "psr/log", - "version": "1.1.2", - "version_normalized": "1.1.2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", - "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "time": "2019-11-01T11:05:21+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ] - }, - { - "name": "symfony/cache", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/cache.git", - "reference": "6e8d978878ae5de705ec9fabbb6011cc18776bc9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/6e8d978878ae5de705ec9fabbb6011cc18776bc9", - "reference": "6e8d978878ae5de705ec9fabbb6011cc18776bc9", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "psr/cache": "~1.0", - "psr/log": "~1.0", - "symfony/cache-contracts": "^1.1.7|^2", - "symfony/service-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0" - }, - "conflict": { - "doctrine/dbal": "<2.5", - "symfony/dependency-injection": "<4.4", - "symfony/http-kernel": "<4.4", - "symfony/var-dumper": "<4.4" - }, - "provide": { - "psr/cache-implementation": "1.0", - "psr/simple-cache-implementation": "1.0", - "symfony/cache-implementation": "1.0" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/cache": "~1.6", - "doctrine/dbal": "~2.5", - "predis/predis": "~1.1", - "psr/simple-cache": "^1.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/var-dumper": "^4.4|^5.0" - }, - "time": "2019-12-12T13:03:32+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Cache\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Cache component with PSR-6, PSR-16, and tags", - "homepage": "https://symfony.com", - "keywords": [ - "caching", - "psr6" - ] - }, - { - "name": "symfony/cache-contracts", - "version": "v2.0.1", - "version_normalized": "2.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/cache-contracts.git", - "reference": "23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16", - "reference": "23ed8bfc1a4115feca942cb5f1aacdf3dcdf3c16", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "psr/cache": "^1.0" - }, - "suggest": { - "symfony/cache-implementation": "" - }, - "time": "2019-11-18T17:27:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Cache\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to caching", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ] - }, - { - "name": "symfony/config", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/config.git", - "reference": "7f930484966350906185ba0a604728f7898b7ba0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/7f930484966350906185ba0a604728f7898b7ba0", - "reference": "7f930484966350906185ba0a604728f7898b7ba0", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "symfony/filesystem": "^4.4|^5.0", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/finder": "<4.4" - }, - "require-dev": { - "symfony/event-dispatcher": "^4.4|^5.0", - "symfony/finder": "^4.4|^5.0", - "symfony/messenger": "^4.4|^5.0", - "symfony/service-contracts": "^1.1|^2", - "symfony/yaml": "^4.4|^5.0" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" - }, - "time": "2019-12-18T13:50:31+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Config\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Config Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/console", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "fe6e3cd889ca64172d7a742a2eb058541404ef47" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/fe6e3cd889ca64172d7a742a2eb058541404ef47", - "reference": "fe6e3cd889ca64172d7a742a2eb058541404ef47", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.8", - "symfony/service-contracts": "^1.1|^2" - }, - "conflict": { - "symfony/dependency-injection": "<4.4", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/event-dispatcher": "^4.4|^5.0", - "symfony/lock": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0", - "symfony/var-dumper": "^4.4|^5.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "time": "2019-12-17T13:20:22+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/dependency-injection", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "f9dbfbf487d08f60b1c83220edcd16559d1e40a2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f9dbfbf487d08f60b1c83220edcd16559d1e40a2", - "reference": "f9dbfbf487d08f60b1c83220edcd16559d1e40a2", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "psr/container": "^1.0", - "symfony/service-contracts": "^1.1.6|^2" - }, - "conflict": { - "symfony/config": "<5.0", - "symfony/finder": "<4.4", - "symfony/proxy-manager-bridge": "<4.4", - "symfony/yaml": "<4.4" - }, - "provide": { - "psr/container-implementation": "1.0", - "symfony/service-implementation": "1.0" - }, - "require-dev": { - "symfony/config": "^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/yaml": "^4.4|^5.0" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" - }, - "time": "2019-12-19T16:01:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\DependencyInjection\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony DependencyInjection Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/doctrine-bridge", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "0bdb2d31741cacacb95130d28fbac939c4d574f2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/0bdb2d31741cacacb95130d28fbac939c4d574f2", - "reference": "0bdb2d31741cacacb95130d28fbac939c4d574f2", - "shasum": "" - }, - "require": { - "doctrine/event-manager": "~1.0", - "doctrine/persistence": "^1.3", - "php": "^7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2" - }, - "conflict": { - "phpunit/phpunit": "<5.4.3", - "symfony/dependency-injection": "<4.4", - "symfony/form": "<5", - "symfony/http-kernel": "<5", - "symfony/messenger": "<4.4", - "symfony/property-info": "<5", - "symfony/security-bundle": "<5", - "symfony/security-core": "<5", - "symfony/validator": "<5.0.2" - }, - "require-dev": { - "doctrine/annotations": "~1.7", - "doctrine/cache": "~1.6", - "doctrine/collections": "~1.0", - "doctrine/data-fixtures": "1.0.*", - "doctrine/dbal": "~2.4", - "doctrine/orm": "^2.6.3", - "doctrine/reflection": "~1.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/form": "^5.0", - "symfony/http-kernel": "^5.0", - "symfony/messenger": "^4.4|^5.0", - "symfony/property-access": "^4.4|^5.0", - "symfony/property-info": "^5.0", - "symfony/proxy-manager-bridge": "^4.4|^5.0", - "symfony/security-core": "^5.0", - "symfony/stopwatch": "^4.4|^5.0", - "symfony/translation": "^4.4|^5.0", - "symfony/validator": "^5.0.2", - "symfony/var-dumper": "^4.4|^5.0" - }, - "suggest": { - "doctrine/data-fixtures": "", - "doctrine/dbal": "", - "doctrine/orm": "", - "symfony/form": "", - "symfony/property-info": "", - "symfony/validator": "" - }, - "time": "2019-12-19T12:10:29+00:00", - "type": "symfony-bridge", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Bridge\\Doctrine\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Doctrine Bridge", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/error-handler", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/error-handler.git", - "reference": "460863313bd3212d7c38e1b40602cbcfeeeea4a5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/460863313bd3212d7c38e1b40602cbcfeeeea4a5", - "reference": "460863313bd3212d7c38e1b40602cbcfeeeea4a5", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "psr/log": "^1.0", - "symfony/var-dumper": "^4.4|^5.0" - }, - "require-dev": { - "symfony/http-kernel": "^4.4|^5.0", - "symfony/serializer": "^4.4|^5.0" - }, - "time": "2019-12-16T14:48:47+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\ErrorHandler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony ErrorHandler Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/event-dispatcher", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "7b738a51645e10f864cc25c24d232fb03f37b475" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/7b738a51645e10f864cc25c24d232fb03f37b475", - "reference": "7b738a51645e10f864cc25c24d232fb03f37b475", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "symfony/event-dispatcher-contracts": "^2" - }, - "conflict": { - "symfony/dependency-injection": "<4.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/service-contracts": "^1.1|^2", - "symfony/stopwatch": "^4.4|^5.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "time": "2019-11-18T17:27:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v2.0.1", - "version_normalized": "2.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "af23c2584d4577d54661c434446fb8fbed6025dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/af23c2584d4577d54661c434446fb8fbed6025dd", - "reference": "af23c2584d4577d54661c434446fb8fbed6025dd", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "psr/event-dispatcher": "^1" - }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, - "time": "2019-11-18T17:27:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ] - }, - { - "name": "symfony/filesystem", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "1d71f670bc5a07b9ccc97dc44f932177a322d4e6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/1d71f670bc5a07b9ccc97dc44f932177a322d4e6", - "reference": "1d71f670bc5a07b9ccc97dc44f932177a322d4e6", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "symfony/polyfill-ctype": "~1.8" - }, - "time": "2019-11-26T23:25:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Filesystem Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/finder", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "17874dd8ab9a19422028ad56172fb294287a701b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/17874dd8ab9a19422028ad56172fb294287a701b", - "reference": "17874dd8ab9a19422028ad56172fb294287a701b", - "shasum": "" - }, - "require": { - "php": "^7.2.5" - }, - "time": "2019-11-18T17:27:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Finder Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/framework-bundle", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/framework-bundle.git", - "reference": "36e51776b231d8e224da4ce4c60079540acd1c55" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/36e51776b231d8e224da4ce4c60079540acd1c55", - "reference": "36e51776b231d8e224da4ce4c60079540acd1c55", - "shasum": "" - }, - "require": { - "ext-xml": "*", - "php": "^7.2.5", - "symfony/cache": "^4.4|^5.0", - "symfony/config": "^5.0", - "symfony/dependency-injection": "^5.0.1", - "symfony/error-handler": "^4.4.1|^5.0.1", - "symfony/filesystem": "^4.4|^5.0", - "symfony/finder": "^4.4|^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/http-kernel": "^5.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/routing": "^5.0" - }, - "conflict": { - "doctrine/persistence": "<1.3", - "phpdocumentor/reflection-docblock": "<3.0", - "phpdocumentor/type-resolver": "<0.2.1", - "phpunit/phpunit": "<5.4.3", - "symfony/asset": "<4.4", - "symfony/browser-kit": "<4.4", - "symfony/console": "<4.4", - "symfony/dom-crawler": "<4.4", - "symfony/dotenv": "<4.4", - "symfony/form": "<4.4", - "symfony/http-client": "<4.4", - "symfony/lock": "<4.4", - "symfony/mailer": "<4.4", - "symfony/messenger": "<4.4", - "symfony/mime": "<4.4", - "symfony/property-info": "<4.4", - "symfony/serializer": "<4.4", - "symfony/stopwatch": "<4.4", - "symfony/translation": "<5.0", - "symfony/twig-bridge": "<4.4", - "symfony/twig-bundle": "<4.4", - "symfony/validator": "<4.4", - "symfony/web-profiler-bundle": "<4.4", - "symfony/workflow": "<4.4" - }, - "require-dev": { - "doctrine/annotations": "~1.7", - "doctrine/cache": "~1.0", - "paragonie/sodium_compat": "^1.8", - "phpdocumentor/reflection-docblock": "^3.0|^4.0", - "symfony/asset": "^4.4|^5.0", - "symfony/browser-kit": "^4.4|^5.0", - "symfony/console": "^4.4|^5.0", - "symfony/css-selector": "^4.4|^5.0", - "symfony/dom-crawler": "^4.4|^5.0", - "symfony/dotenv": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/form": "^4.4|^5.0", - "symfony/http-client": "^4.4|^5.0", - "symfony/lock": "^4.4|^5.0", - "symfony/mailer": "^4.4|^5.0", - "symfony/messenger": "^4.4|^5.0", - "symfony/mime": "^4.4|^5.0", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/process": "^4.4|^5.0", - "symfony/property-info": "^4.4|^5.0", - "symfony/security-csrf": "^4.4|^5.0", - "symfony/security-http": "^4.4|^5.0", - "symfony/serializer": "^4.4|^5.0", - "symfony/stopwatch": "^4.4|^5.0", - "symfony/string": "~5.0.0", - "symfony/translation": "^5.0", - "symfony/twig-bundle": "^4.4|^5.0", - "symfony/validator": "^4.4|^5.0", - "symfony/web-link": "^4.4|^5.0", - "symfony/workflow": "^4.4|^5.0", - "symfony/yaml": "^4.4|^5.0", - "twig/twig": "^2.10|^3.0" - }, - "suggest": { - "ext-apcu": "For best performance of the system caches", - "symfony/console": "For using the console commands", - "symfony/form": "For using forms", - "symfony/property-info": "For using the property_info service", - "symfony/serializer": "For using the serializer service", - "symfony/validator": "For using validation", - "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering", - "symfony/yaml": "For using the debug:config and lint:yaml commands" - }, - "time": "2019-12-17T10:33:13+00:00", - "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Bundle\\FrameworkBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony FrameworkBundle", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/http-foundation", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "5dd7f6be6e62d86ba6f3154cf40e78936367978b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5dd7f6be6e62d86ba6f3154cf40e78936367978b", - "reference": "5dd7f6be6e62d86ba6f3154cf40e78936367978b", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "symfony/mime": "^4.4|^5.0", - "symfony/polyfill-mbstring": "~1.1" - }, - "require-dev": { - "predis/predis": "~1.0", - "symfony/expression-language": "^4.4|^5.0" - }, - "time": "2019-12-19T16:01:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony HttpFoundation Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/http-kernel", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-kernel.git", - "reference": "00ce30602f3f690e66a63c327743d7b26c723b2e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/00ce30602f3f690e66a63c327743d7b26c723b2e", - "reference": "00ce30602f3f690e66a63c327743d7b26c723b2e", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "psr/log": "~1.0", - "symfony/error-handler": "^4.4|^5.0", - "symfony/event-dispatcher": "^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-php73": "^1.9" - }, - "conflict": { - "symfony/browser-kit": "<4.4", - "symfony/cache": "<5.0", - "symfony/config": "<5.0", - "symfony/dependency-injection": "<4.4", - "symfony/doctrine-bridge": "<5.0", - "symfony/form": "<5.0", - "symfony/http-client": "<5.0", - "symfony/mailer": "<5.0", - "symfony/messenger": "<5.0", - "symfony/translation": "<5.0", - "symfony/twig-bridge": "<5.0", - "symfony/validator": "<5.0", - "twig/twig": "<2.4" - }, - "provide": { - "psr/log-implementation": "1.0" - }, - "require-dev": { - "psr/cache": "~1.0", - "symfony/browser-kit": "^4.4|^5.0", - "symfony/config": "^5.0", - "symfony/console": "^4.4|^5.0", - "symfony/css-selector": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/dom-crawler": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/finder": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0", - "symfony/routing": "^4.4|^5.0", - "symfony/stopwatch": "^4.4|^5.0", - "symfony/translation": "^4.4|^5.0", - "symfony/translation-contracts": "^1.1|^2", - "twig/twig": "^2.4|^3.0" - }, - "suggest": { - "symfony/browser-kit": "", - "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "" - }, - "time": "2019-12-19T18:35:03+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpKernel\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony HttpKernel Component", - "homepage": "https://symfony.com" - }, - { - "name": "symfony/mime", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/mime.git", - "reference": "0e6a4ced216e49d457eddcefb61132173a876d79" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/0e6a4ced216e49d457eddcefb61132173a876d79", - "reference": "0e6a4ced216e49d457eddcefb61132173a876d79", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "symfony/polyfill-intl-idn": "^1.10", - "symfony/polyfill-mbstring": "^1.0" - }, - "conflict": { - "symfony/mailer": "<4.4" - }, - "require-dev": { - "egulias/email-validator": "^2.1.10", - "symfony/dependency-injection": "^4.4|^5.0" - }, - "time": "2019-11-30T14:12:50+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Mime\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A library to manipulate MIME messages", - "homepage": "https://symfony.com", - "keywords": [ - "mime", - "mime-type" - ] - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.13.1", - "version_normalized": "1.13.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", - "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "time": "2019-11-27T13:56:44+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.13-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ] - }, - { - "name": "symfony/polyfill-intl-idn", - "version": "v1.13.1", - "version_normalized": "1.13.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6f9c239e61e1b0c9229a28ff89a812dc449c3d46", - "reference": "6f9c239e61e1b0c9229a28ff89a812dc449c3d46", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php72": "^1.9" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "time": "2019-11-27T13:56:44+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.13-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Intl\\Idn\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "idn", - "intl", - "polyfill", - "portable", - "shim" - ] - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.13.1", - "version_normalized": "1.13.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f", - "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "time": "2019-11-27T14:18:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.13-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ] - }, - { - "name": "symfony/polyfill-php72", - "version": "v1.13.1", - "version_normalized": "1.13.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "66fea50f6cb37a35eea048d75a7d99a45b586038" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/66fea50f6cb37a35eea048d75a7d99a45b586038", - "reference": "66fea50f6cb37a35eea048d75a7d99a45b586038", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "time": "2019-11-27T13:56:44+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.13-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ] - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.13.1", - "version_normalized": "1.13.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/4b0e2222c55a25b4541305a053013d5647d3a25f", - "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "time": "2019-11-27T16:25:15+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.13-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ] - }, - { - "name": "symfony/routing", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "120c5fa4f4ef5466cbb510ece8126e0007285301" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/120c5fa4f4ef5466cbb510ece8126e0007285301", - "reference": "120c5fa4f4ef5466cbb510ece8126e0007285301", - "shasum": "" - }, - "require": { - "php": "^7.2.5" - }, - "conflict": { - "symfony/config": "<5.0", - "symfony/dependency-injection": "<4.4", - "symfony/yaml": "<4.4" - }, - "require-dev": { - "doctrine/annotations": "~1.2", - "psr/log": "~1.0", - "symfony/config": "^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/yaml": "^4.4|^5.0" - }, - "suggest": { - "doctrine/annotations": "For using the annotation loader", - "symfony/config": "For using the all-in-one router or any loader", - "symfony/expression-language": "For using expression matching", - "symfony/http-foundation": "For using a Symfony Request object", - "symfony/yaml": "For using the YAML loader" - }, - "time": "2019-12-12T13:03:32+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\Routing\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Routing Component", - "homepage": "https://symfony.com", - "keywords": [ - "router", - "routing", - "uri", - "url" - ] - }, - { - "name": "symfony/service-contracts", - "version": "v2.0.1", - "version_normalized": "2.0.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "144c5e51266b281231e947b51223ba14acf1a749" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", - "reference": "144c5e51266b281231e947b51223ba14acf1a749", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "psr/container": "^1.0" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "time": "2019-11-18T17:27:11+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ] - }, - { - "name": "symfony/var-dumper", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-dumper.git", - "reference": "d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a", - "reference": "d7bc61d5d335fa9b1b91e14bb16861e8ca50f53a", - "shasum": "" - }, - "require": { - "php": "^7.2.5", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "phpunit/phpunit": "<5.4.3", - "symfony/console": "<4.4" - }, - "require-dev": { - "ext-iconv": "*", - "symfony/console": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0", - "twig/twig": "^2.4|^3.0" - }, - "suggest": { - "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", - "ext-intl": "To show region name in time zone dump", - "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" - }, - "time": "2019-12-18T13:50:31+00:00", - "bin": [ - "Resources/bin/var-dump-server" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "Resources/functions/dump.php" - ], - "psr-4": { - "Symfony\\Component\\VarDumper\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony mechanism for exploring and dumping PHP variables", - "homepage": "https://symfony.com", - "keywords": [ - "debug", - "dump" - ] - }, - { - "name": "symfony/var-exporter", - "version": "v5.0.2", - "version_normalized": "5.0.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-exporter.git", - "reference": "1b9653e68d5b701bf6d9c91bdd3660078c9f4f28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/1b9653e68d5b701bf6d9c91bdd3660078c9f4f28", - "reference": "1b9653e68d5b701bf6d9c91bdd3660078c9f4f28", - "shasum": "" - }, - "require": { - "php": "^7.2.5" - }, - "require-dev": { - "symfony/var-dumper": "^4.4|^5.0" - }, - "time": "2019-12-01T08:48:26+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Symfony\\Component\\VarExporter\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A blend of var_export() + serialize() to turn any serializable data structure to plain PHP code", - "homepage": "https://symfony.com", - "keywords": [ - "clone", - "construct", - "export", - "hydrate", - "instantiate", - "serialize" - ] - } -] diff --git a/vendor/doctrine/annotations/CHANGELOG.md b/vendor/doctrine/annotations/CHANGELOG.md deleted file mode 100644 index 0b0ba1a..0000000 --- a/vendor/doctrine/annotations/CHANGELOG.md +++ /dev/null @@ -1,162 +0,0 @@ -## Changelog - -### 1.6.1 - -This release fixes an issue in which annotations such as `@foo-bar` -and `@foo-` were incorrectly recognised as valid, and both erroneously -parsed as `@foo`. - -Any annotation with `@name-*` format will now silently be ignored, -allowing vendor-specific annotations to be prefixed with the tool -name. - -Total issues resolved: **3** - -- [165: Update the composer branch alias](https://github.com/doctrine/annotations/pull/165) thanks to @mikeSimonson -- [209: Change Annotation::value typehint to mixed](https://github.com/doctrine/annotations/pull/209) thanks to @malarzm -- [257: Skip parsing annotations containing dashes, such as `@Foo-bar`, or `@Foo-`](https://github.com/doctrine/annotations/pull/257) thanks to @Ocramius - -### 1.6.0 - -This release brings a new endpoint that make sure that you can't shoot yourself in the foot by calling ```registerLoader``` multiple times and a few tests improvements. - -Total issues resolved: **7** - -- [145: Memory leak in AnnotationRegistry::registerLoader() when called multiple times](https://github.com/doctrine/annotations/issues/145) thanks to @TriAnMan -- [146: Import error on @experimental Annotation](https://github.com/doctrine/annotations/issues/146) thanks to @aturki -- [147: Ignoring @experimental annotation used by Symfony 3.3 CacheAdapter](https://github.com/doctrine/annotations/pull/147) thanks to @aturki -- [151: Remove duplicate code in `DCOM58Test`](https://github.com/doctrine/annotations/pull/151) thanks to @tuanphpvn -- [161: Prevent loading class_exists multiple times](https://github.com/doctrine/annotations/pull/161) thanks to @jrjohnson -- [162: Add registerUniqueLoader to AnnotationRegistry](https://github.com/doctrine/annotations/pull/162) thanks to @jrjohnson -- [163: Use assertDirectoryExists and assertDirectoryNotExists](https://github.com/doctrine/annotations/pull/163) thanks to @carusogabriel - -Thanks to everyone involved in this release. - -### 1.5.0 - -This release increments the minimum supported PHP version to 7.1.0. - -Also, HHVM official support has been dropped. - -Some noticeable performance improvements to annotation autoloading -have been applied, making failed annotation autoloading less heavy -on the filesystem access. - -- [133: Add @throws annotation in AnnotationReader#__construct()](https://github.com/doctrine/annotations/issues/133) thanks to @SenseException -- [134: Require PHP 7.1, drop HHVM support](https://github.com/doctrine/annotations/issues/134) thanks to @lcobucci -- [135: Prevent the same loader from being registered twice](https://github.com/doctrine/annotations/issues/135) thanks to @jrjohnson -- [137: #135 optimise multiple class load attempts in AnnotationRegistry](https://github.com/doctrine/annotations/issues/137) thanks to @Ocramius - - -### 1.4.0 - -This release fix an issue were some annotations could be not loaded if the namespace in the use statement started with a backslash. -It also update the tests and drop the support for php 5.X - -- [115: Missing annotations with the latest composer version](https://github.com/doctrine/annotations/issues/115) thanks to @pascalporedda -- [120: Missing annotations with the latest composer version](https://github.com/doctrine/annotations/pull/120) thanks to @gnat42 -- [121: Adding a more detailed explanation of the test](https://github.com/doctrine/annotations/pull/121) thanks to @mikeSimonson -- [101: Test annotation parameters containing space](https://github.com/doctrine/annotations/pull/101) thanks to @mikeSimonson -- [111: Cleanup: move to correct phpunit assertions](https://github.com/doctrine/annotations/pull/111) thanks to @Ocramius -- [112: Removes support for PHP 5.x](https://github.com/doctrine/annotations/pull/112) thanks to @railto -- [113: bumped phpunit version to 5.7](https://github.com/doctrine/annotations/pull/113) thanks to @gabbydgab -- [114: Enhancement: Use SVG Travis build badge](https://github.com/doctrine/annotations/pull/114) thanks to @localheinz -- [118: Integrating PHPStan](https://github.com/doctrine/annotations/pull/118) thanks to @ondrejmirtes - -### 1.3.1 - 2016-12-30 - -This release fixes an issue with ignored annotations that were already -autoloaded, causing the `SimpleAnnotationReader` to pick them up -anyway. [#110](https://github.com/doctrine/annotations/pull/110) - -Additionally, an issue was fixed in the `CachedReader`, which was -not correctly checking the freshness of cached annotations when -traits were defined on a class. [#105](https://github.com/doctrine/annotations/pull/105) - -Total issues resolved: **2** - -- [105: Return single max timestamp](https://github.com/doctrine/annotations/pull/105) -- [110: setIgnoreNotImportedAnnotations(true) didn’t work for existing classes](https://github.com/doctrine/annotations/pull/110) - -### 1.3.0 - -This release introduces a PHP version bump. `doctrine/annotations` now requires PHP -5.6 or later to be installed. - -A series of additional improvements have been introduced: - - * support for PHP 7 "grouped use statements" - * support for ignoring entire namespace names - via `Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredNamespace()` and - `Doctrine\Common\Annotations\DocParser::setIgnoredAnnotationNamespaces()`. This will - allow you to ignore annotations from namespaces that you cannot autoload - * testing all parent classes and interfaces when checking if the annotation cache - in the `CachedReader` is fresh - * simplifying the cache keys used by the `CachedReader`: keys are no longer artificially - namespaced, since `Doctrine\Common\Cache` already supports that - * corrected parsing of multibyte strings when `mbstring.func_overload` is enabled - * corrected parsing of annotations when `"\t"` is put before the first annotation - in a docblock - * allow skipping non-imported annotations when a custom `DocParser` is passed to - the `AnnotationReader` constructor - -Total issues resolved: **15** - -- [45: DocParser can now ignore whole namespaces](https://github.com/doctrine/annotations/pull/45) -- [57: Switch to the docker-based infrastructure on Travis](https://github.com/doctrine/annotations/pull/57) -- [59: opcache.load_comments has been removed from PHP 7](https://github.com/doctrine/annotations/pull/59) -- [62: [CachedReader\ Test traits and parent class to see if cache is fresh](https://github.com/doctrine/annotations/pull/62) -- [65: Remove cache salt making key unnecessarily long](https://github.com/doctrine/annotations/pull/65) -- [66: Fix of incorrect parsing multibyte strings](https://github.com/doctrine/annotations/pull/66) -- [68: Annotations that are indented by tab are not processed.](https://github.com/doctrine/annotations/issues/68) -- [69: Support for Group Use Statements](https://github.com/doctrine/annotations/pull/69) -- [70: Allow tab character before first annotation in DocBlock](https://github.com/doctrine/annotations/pull/70) -- [74: Ignore not registered annotations fix](https://github.com/doctrine/annotations/pull/74) -- [92: Added tests for AnnotationRegistry class.](https://github.com/doctrine/annotations/pull/92) -- [96: Fix/#62 check trait and parent class ttl in annotations](https://github.com/doctrine/annotations/pull/96) -- [97: Feature - #45 - allow ignoring entire namespaces](https://github.com/doctrine/annotations/pull/97) -- [98: Enhancement/#65 remove cache salt from cached reader](https://github.com/doctrine/annotations/pull/98) -- [99: Fix - #70 - allow tab character before first annotation in docblock](https://github.com/doctrine/annotations/pull/99) - -### 1.2.4 - -Total issues resolved: **1** - -- [51: FileCacheReader::saveCacheFile::unlink fix](https://github.com/doctrine/annotations/pull/51) - -### 1.2.3 - -Total issues resolved: [**2**](https://github.com/doctrine/annotations/milestones/v1.2.3) - -- [49: #46 - applying correct `chmod()` to generated cache file](https://github.com/doctrine/annotations/pull/49) -- [50: Hotfix: match escaped quotes (revert #44)](https://github.com/doctrine/annotations/pull/50) - -### 1.2.2 - -Total issues resolved: **4** - -- [43: Exclude files from distribution with .gitattributes](https://github.com/doctrine/annotations/pull/43) -- [44: Update DocLexer.php](https://github.com/doctrine/annotations/pull/44) -- [46: A plain "file_put_contents" can cause havoc](https://github.com/doctrine/annotations/pull/46) -- [48: Deprecating the `FileCacheReader` in 1.2.2: will be removed in 2.0.0](https://github.com/doctrine/annotations/pull/48) - -### 1.2.1 - -Total issues resolved: **4** - -- [38: fixes doctrine/common#326](https://github.com/doctrine/annotations/pull/38) -- [39: Remove superfluous NS](https://github.com/doctrine/annotations/pull/39) -- [41: Warn if load_comments is not enabled.](https://github.com/doctrine/annotations/pull/41) -- [42: Clean up unused uses](https://github.com/doctrine/annotations/pull/42) - -### 1.2.0 - - * HHVM support - * Allowing dangling comma in annotations - * Excluded annotations are no longer autoloaded - * Importing namespaces also in traits - * Added support for `::class` 5.5-style constant, works also in 5.3 and 5.4 - -### 1.1.0 - - * Add Exception when ZendOptimizer+ or Opcache is configured to drop comments diff --git a/vendor/doctrine/annotations/LICENSE b/vendor/doctrine/annotations/LICENSE deleted file mode 100644 index 5e781fc..0000000 --- a/vendor/doctrine/annotations/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006-2013 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/doctrine/annotations/README.md b/vendor/doctrine/annotations/README.md deleted file mode 100644 index a53b91f..0000000 --- a/vendor/doctrine/annotations/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Doctrine Annotations - -[![Build Status](https://travis-ci.org/doctrine/annotations.svg?branch=master)](https://travis-ci.org/doctrine/annotations) -[![Dependency Status](https://www.versioneye.com/package/php--doctrine--annotations/badge.png)](https://www.versioneye.com/package/php--doctrine--annotations) -[![Reference Status](https://www.versioneye.com/php/doctrine:annotations/reference_badge.svg)](https://www.versioneye.com/php/doctrine:annotations/references) -[![Total Downloads](https://poser.pugx.org/doctrine/annotations/downloads.png)](https://packagist.org/packages/doctrine/annotations) -[![Latest Stable Version](https://poser.pugx.org/doctrine/annotations/v/stable.png)](https://packagist.org/packages/doctrine/annotations) - -Docblock Annotations Parser library (extracted from [Doctrine Common](https://github.com/doctrine/common)). - -## Documentation - -See the [doctrine-project website](https://www.doctrine-project.org/projects/doctrine-annotations/en/latest/index.html). - -## Changelog - -See [CHANGELOG.md](CHANGELOG.md). diff --git a/vendor/doctrine/annotations/composer.json b/vendor/doctrine/annotations/composer.json deleted file mode 100644 index 36fd562..0000000 --- a/vendor/doctrine/annotations/composer.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "doctrine/annotations", - "type": "library", - "description": "Docblock Annotations Parser", - "keywords": ["annotations", "docblock", "parser"], - "homepage": "http://www.doctrine-project.org", - "license": "MIT", - "authors": [ - {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, - {"name": "Roman Borschel", "email": "roman@code-factory.org"}, - {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, - {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, - {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} - ], - "require": { - "php": "^7.1", - "doctrine/lexer": "1.*" - }, - "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "^7.5" - }, - "config": { - "sort-packages": true - }, - "autoload": { - "psr-4": { "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" } - }, - "autoload-dev": { - "psr-4": { - "Doctrine\\Performance\\Common\\Annotations\\": "tests/Doctrine/Performance/Common/Annotations", - "Doctrine\\Tests\\Common\\Annotations\\": "tests/Doctrine/Tests/Common/Annotations" - }, - "files": [ - "tests/Doctrine/Tests/Common/Annotations/Fixtures/SingleClassLOC1000.php" - ] - }, - "extra": { - "branch-alias": { - "dev-master": "1.7.x-dev" - } - } -} diff --git a/vendor/doctrine/annotations/docs/en/annotations.rst b/vendor/doctrine/annotations/docs/en/annotations.rst deleted file mode 100644 index 99da3e2..0000000 --- a/vendor/doctrine/annotations/docs/en/annotations.rst +++ /dev/null @@ -1,223 +0,0 @@ -Handling Annotations -==================== - -There are several different approaches to handling annotations in PHP. Doctrine Annotations -maps docblock annotations to PHP classes. Because not all docblock annotations are used -for metadata purposes a filter is applied to ignore or skip classes that are not Doctrine annotations. - -Take a look at the following code snippet: - -.. code-block:: php - - namespace MyProject\Entities; - - use Doctrine\ORM\Mapping AS ORM; - use Symfony\Component\Validation\Constraints AS Assert; - - /** - * @author Benjamin Eberlei - * @ORM\Entity - * @MyProject\Annotations\Foobarable - */ - class User - { - /** - * @ORM\Id @ORM\Column @ORM\GeneratedValue - * @dummy - * @var int - */ - private $id; - - /** - * @ORM\Column(type="string") - * @Assert\NotEmpty - * @Assert\Email - * @var string - */ - private $email; - } - -In this snippet you can see a variety of different docblock annotations: - -- Documentation annotations such as ``@var`` and ``@author``. These annotations are on a blacklist and never considered for throwing an exception due to wrongly used annotations. -- Annotations imported through use statements. The statement ``use Doctrine\ORM\Mapping AS ORM`` makes all classes under that namespace available as ``@ORM\ClassName``. Same goes for the import of ``@Assert``. -- The ``@dummy`` annotation. It is not a documentation annotation and not blacklisted. For Doctrine Annotations it is not entirely clear how to handle this annotation. Depending on the configuration an exception (unknown annotation) will be thrown when parsing this annotation. -- The fully qualified annotation ``@MyProject\Annotations\Foobarable``. This is transformed directly into the given class name. - -How are these annotations loaded? From looking at the code you could guess that the ORM Mapping, Assert Validation and the fully qualified annotation can just be loaded using -the defined PHP autoloaders. This is not the case however: For error handling reasons every check for class existence inside the AnnotationReader sets the second parameter $autoload -of ``class_exists($name, $autoload)`` to false. To work flawlessly the AnnotationReader requires silent autoloaders which many autoloaders are not. Silent autoloading is NOT -part of the `PSR-0 specification `_ for autoloading. - -This is why Doctrine Annotations uses its own autoloading mechanism through a global registry. If you are wondering about the annotation registry being global, -there is no other way to solve the architectural problems of autoloading annotation classes in a straightforward fashion. Additionally if you think about PHP -autoloading then you recognize it is a global as well. - -To anticipate the configuration section, making the above PHP class work with Doctrine Annotations requires this setup: - -.. code-block:: php - - use Doctrine\Common\Annotations\AnnotationReader; - use Doctrine\Common\Annotations\AnnotationRegistry; - - AnnotationRegistry::registerFile("/path/to/doctrine/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php"); - AnnotationRegistry::registerAutoloadNamespace("Symfony\Component\Validator\Constraint", "/path/to/symfony/src"); - AnnotationRegistry::registerAutoloadNamespace("MyProject\Annotations", "/path/to/myproject/src"); - - $reader = new AnnotationReader(); - AnnotationReader::addGlobalIgnoredName('dummy'); - -The second block with the annotation registry calls registers all the three different annotation namespaces that are used. -Doctrine saves all its annotations in a single file, that is why ``AnnotationRegistry#registerFile`` is used in contrast to -``AnnotationRegistry#registerAutoloadNamespace`` which creates a PSR-0 compatible loading mechanism for class to file names. - -In the third block, we create the actual AnnotationReader instance. Note that we also add "dummy" to the global list of annotations -for which we do not throw exceptions. Setting this is necessary in our example case, otherwise ``@dummy`` would trigger an exception to -be thrown during the parsing of the docblock of ``MyProject\Entities\User#id``. - -Setup and Configuration ------------------------ - -To use the annotations library is simple, you just need to create a new ``AnnotationReader`` instance: - -.. code-block:: php - - $reader = new \Doctrine\Common\Annotations\AnnotationReader(); - -This creates a simple annotation reader with no caching other than in memory (in php arrays). -Since parsing docblocks can be expensive you should cache this process by using -a caching reader. - -You can use a file caching reader: - -.. code-block:: php - - use Doctrine\Common\Annotations\FileCacheReader; - use Doctrine\Common\Annotations\AnnotationReader; - - $reader = new FileCacheReader( - new AnnotationReader(), - "/path/to/cache", - $debug = true - ); - -If you set the debug flag to true the cache reader will check for changes in the original files, which -is very important during development. If you don't set it to true you have to delete the directory to clear the cache. -This gives faster performance, however should only be used in production, because of its inconvenience -during development. - -You can also use one of the ``Doctrine\Common\Cache\Cache`` cache implementations to cache the annotations: - -.. code-block:: php - - use Doctrine\Common\Annotations\AnnotationReader; - use Doctrine\Common\Annotations\CachedReader; - use Doctrine\Common\Cache\ApcCache; - - $reader = new CachedReader( - new AnnotationReader(), - new ApcCache(), - $debug = true - ); - -The debug flag is used here as well to invalidate the cache files when the PHP class with annotations changed -and should be used during development. - -.. warning :: - - The AnnotationReader works and caches under the - assumption that all annotations of a doc-block are processed at - once. That means that annotation classes that do not exist and - aren't loaded and cannot be autoloaded (using the AnnotationRegistry) would never be visible and not - accessible if a cache is used unless the cache is cleared and the - annotations requested again, this time with all annotations - defined. - -By default the annotation reader returns a list of annotations with numeric indexes. If you want your annotations -to be indexed by their class name you can wrap the reader in an IndexedReader: - -.. code-block:: php - - use Doctrine\Common\Annotations\AnnotationReader; - use Doctrine\Common\Annotations\IndexedReader; - - $reader = new IndexedReader(new AnnotationReader()); - -.. warning:: - - You should never wrap the indexed reader inside a cached reader only the other way around. This way you can re-use - the cache with indexed or numeric keys, otherwise your code may experience failures due to caching in an numerical - or indexed format. - -Registering Annotations -~~~~~~~~~~~~~~~~~~~~~~~ - -As explained in the Introduction Doctrine Annotations uses its own autoloading mechanism to determine if a -given annotation has a corresponding PHP class that can be autoloaded. For Annotation Autoloading you have -to configure the ``Doctrine\Common\Annotations\AnnotationRegistry``. There are three different mechanisms -to configure annotation autoloading: - -- Calling ``AnnotationRegistry#registerFile($file)`` to register a file that contains one or more Annotation classes. -- Calling ``AnnotationRegistry#registerNamespace($namespace, $dirs = null)`` to register that the given namespace - contains annotations and that their base directory is located at the given $dirs or in the include path if NULL is passed. - The given directories should *NOT* be the directory where classes of the namespace are in, but the base directory - of the root namespace. The AnnotationRegistry uses a namespace to directory separator approach to resolve the correct path. -- Calling ``AnnotationRegistry#registerLoader($callable)`` to register an autoloader callback. The callback accepts the - class as first and only parameter and has to return true if the corresponding file was found and included. - -.. note:: - - Loaders have to fail silently, if a class is not found even if it matches for example the namespace prefix of that loader. - Never is a loader to throw a warning or exception if the loading failed otherwise parsing doc block annotations will become - a huge pain. - -A sample loader callback could look like: - -.. code-block:: php - - use Doctrine\Common\Annotations\AnnotationRegistry; - use Symfony\Component\ClassLoader\UniversalClassLoader; - - AnnotationRegistry::registerLoader(function($class) { - $file = str_replace("\\", DIRECTORY_SEPARATOR, $class) . ".php"; - - if (file_exists("/my/base/path/" . $file)) { - // file exists makes sure that the loader fails silently - require "/my/base/path/" . $file; - } - }); - - $loader = new UniversalClassLoader(); - AnnotationRegistry::registerLoader(array($loader, "loadClass")); - - -Ignoring missing exceptions -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -By default an exception is thrown from the AnnotationReader if an annotation was found that: - -- Is not part of the blacklist of ignored "documentation annotations". -- Was not imported through a use statement -- Is not a fully qualified class that exists - -You can disable this behavior for specific names if your docblocks do not follow strict requirements: - -.. code-block:: php - - $reader = new \Doctrine\Common\Annotations\AnnotationReader(); - AnnotationReader::addGlobalIgnoredName('foo'); - -PHP Imports -~~~~~~~~~~~ - -By default the annotation reader parses the use-statement of a php file to gain access to the import rules -and register them for the annotation processing. Only if you are using PHP Imports you can validate the correct -usage of annotations and throw exceptions if you misspelled an annotation. This mechanism is enabled by default. - -To ease the upgrade path, we still allow you to disable this mechanism. Note however that we will remove this -in future versions: - -.. code-block:: php - - $reader = new \Doctrine\Common\Annotations\AnnotationReader(); - $reader->setEnabledPhpImports(false); diff --git a/vendor/doctrine/annotations/docs/en/custom.rst b/vendor/doctrine/annotations/docs/en/custom.rst deleted file mode 100644 index 860c6e6..0000000 --- a/vendor/doctrine/annotations/docs/en/custom.rst +++ /dev/null @@ -1,341 +0,0 @@ -Custom Annotation Classes -========================= - -If you want to define your own annotations you just have to group them in a namespace and register this namespace -in the AnnotationRegistry. Annotation classes have to contain a class-level docblock with the text ``@Annotation``: - -.. code-block:: php - - namespace MyCompany\Annotations; - - /** @Annotation */ - class Bar - { - // some code - } - -Inject annotation values ------------------------- - -The annotation parser check if the annotation constructor has arguments, -if so then we will pass the value array, otherwise will try to inject values into public properties directly: - - -.. code-block:: php - - namespace MyCompany\Annotations; - - /** - * @Annotation - * - * Some Annotation using a constructor - */ - class Bar - { - private $foo; - - public function __construct(array $values) - { - $this->foo = $values['foo']; - } - } - - /** - * @Annotation - * - * Some Annotation without a constructor - */ - class Foo - { - public $bar; - } - -Annotation Target ------------------ - -``@Target`` indicates the kinds of class element to which an annotation type is applicable. -Then you could define one or more targets: - -- ``CLASS`` Allowed in the class docblock -- ``PROPERTY`` Allowed in the property docblock -- ``METHOD`` Allowed in the method docblock -- ``ALL`` Allowed in the class, property and method docblock -- ``ANNOTATION`` Allowed inside other annotations - -If the annotations is not allowed in the current context you got an ``AnnotationException`` - -.. code-block:: php - - namespace MyCompany\Annotations; - - /** - * @Annotation - * @Target({"METHOD","PROPERTY"}) - */ - class Bar - { - // some code - } - - /** - * @Annotation - * @Target("CLASS") - */ - class Foo - { - // some code - } - -Attribute types ---------------- - -Annotation parser check the given parameters using the phpdoc annotation ``@var``, -The data type could be validated using the ``@var`` annotation on the annotation properties -or using the annotations ``@Attributes`` and ``@Attribute``. - -If the data type not match you got an ``AnnotationException`` - -.. code-block:: php - - namespace MyCompany\Annotations; - - /** - * @Annotation - * @Target({"METHOD","PROPERTY"}) - */ - class Bar - { - /** @var mixed */ - public $mixed; - - /** @var boolean */ - public $boolean; - - /** @var bool */ - public $bool; - - /** @var float */ - public $float; - - /** @var string */ - public $string; - - /** @var integer */ - public $integer; - - /** @var array */ - public $array; - - /** @var SomeAnnotationClass */ - public $annotation; - - /** @var array */ - public $arrayOfIntegers; - - /** @var array */ - public $arrayOfAnnotations; - } - - /** - * @Annotation - * @Target({"METHOD","PROPERTY"}) - * @Attributes({ - * @Attribute("stringProperty", type = "string"), - * @Attribute("annotProperty", type = "SomeAnnotationClass"), - * }) - */ - class Foo - { - public function __construct(array $values) - { - $this->stringProperty = $values['stringProperty']; - $this->annotProperty = $values['annotProperty']; - } - - // some code - } - -Annotation Required -------------------- - -``@Required`` indicates that the field must be specified when the annotation is used. -If it is not used you get an ``AnnotationException`` stating that this value can not be null. - -Declaring a required field: - -.. code-block:: php - - /** - * @Annotation - * @Target("ALL") - */ - class Foo - { - /** @Required */ - public $requiredField; - } - -Usage: - -.. code-block:: php - - /** @Foo(requiredField="value") */ - public $direction; // Valid - - /** @Foo */ - public $direction; // Required field missing, throws an AnnotationException - - -Enumerated values ------------------ - -- An annotation property marked with ``@Enum`` is a field that accept a fixed set of scalar values. -- You should use ``@Enum`` fields any time you need to represent fixed values. -- The annotation parser check the given value and throws an ``AnnotationException`` if the value not match. - - -Declaring an enumerated property: - -.. code-block:: php - - /** - * @Annotation - * @Target("ALL") - */ - class Direction - { - /** - * @Enum({"NORTH", "SOUTH", "EAST", "WEST"}) - */ - public $value; - } - -Annotation usage: - -.. code-block:: php - - /** @Direction("NORTH") */ - public $direction; // Valid value - - /** @Direction("NORTHEAST") */ - public $direction; // Invalid value, throws an AnnotationException - - -Constants ---------- - -The use of constants and class constants are available on the annotations parser. - -The following usage are allowed: - -.. code-block:: php - - namespace MyCompany\Entity; - - use MyCompany\Annotations\Foo; - use MyCompany\Annotations\Bar; - use MyCompany\Entity\SomeClass; - - /** - * @Foo(PHP_EOL) - * @Bar(Bar::FOO) - * @Foo({SomeClass::FOO, SomeClass::BAR}) - * @Bar({SomeClass::FOO_KEY = SomeClass::BAR_VALUE}) - */ - class User - { - } - - -Be careful with constants and the cache ! - -.. note:: - - The cached reader will not re-evaluate each time an annotation is loaded from cache. - When a constant is changed the cache must be cleaned. - - -Usage ------ - -Using the library API is simple. Using the annotations described in the previous section -you can now annotate other classes with your annotations: - -.. code-block:: php - - namespace MyCompany\Entity; - - use MyCompany\Annotations\Foo; - use MyCompany\Annotations\Bar; - - /** - * @Foo(bar="foo") - * @Bar(foo="bar") - */ - class User - { - } - -Now we can write a script to get the annotations above: - -.. code-block:: php - - $reflClass = new ReflectionClass('MyCompany\Entity\User'); - $classAnnotations = $reader->getClassAnnotations($reflClass); - - foreach ($classAnnotations AS $annot) { - if ($annot instanceof \MyCompany\Annotations\Foo) { - echo $annot->bar; // prints "foo"; - } else if ($annot instanceof \MyCompany\Annotations\Bar) { - echo $annot->foo; // prints "bar"; - } - } - -You have a complete API for retrieving annotation class instances -from a class, property or method docblock: - - -Reader API -~~~~~~~~~~ - -Access all annotations of a class -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getClassAnnotations(\ReflectionClass $class); - -Access one annotation of a class -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getClassAnnotation(\ReflectionClass $class, $annotationName); - -Access all annotations of a method -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getMethodAnnotations(\ReflectionMethod $method); - -Access one annotation of a method -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getMethodAnnotation(\ReflectionMethod $method, $annotationName); - -Access all annotations of a property -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getPropertyAnnotations(\ReflectionProperty $property); - -Access one annotation of a property -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: php - - public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName); diff --git a/vendor/doctrine/annotations/docs/en/index.rst b/vendor/doctrine/annotations/docs/en/index.rst deleted file mode 100644 index 3ac6703..0000000 --- a/vendor/doctrine/annotations/docs/en/index.rst +++ /dev/null @@ -1,90 +0,0 @@ -Introduction -============ - -Doctrine Annotations offers to implement custom annotation -functionality for PHP classes. - -.. code-block:: php - - class Foo - { - /** - * @MyAnnotation(myProperty="value") - */ - private $bar; - } - -Annotations aren't implemented in PHP itself which is why -this component offers a way to use the PHP doc-blocks as a -place for the well known annotation syntax using the -``@`` char. - -Annotations in Doctrine are used for the ORM -configuration to build the class mapping, but it can -be used in other projects for other purposes too. - -Installation -============ - -You can install the Annotation component with composer: - -.. code-block:: - -   $ composer require doctrine/annotations - -Create an annotation class -========================== - -An annotation class is a representation of the later -used annotation configuration in classes. The annotation -class of the previous example looks like this: - -.. code-block:: php - - /** - * @Annotation - */ - final class MyAnnotation - { - public $myProperty; - } - -The annotation class is declared as an annotation by -``@Annotation``. - -:ref:`Read more about custom annotations. ` - -Reading annotations -=================== - -The access to the annotations happens by reflection of the class -containing them. There are multiple reader-classes implementing the -``Doctrine\Common\Annotations\Reader`` interface, that can -access the annotations of a class. A common one is -``Doctrine\Common\Annotations\AnnotationReader``: - -.. code-block:: php - - $reflectionClass = new ReflectionClass(Foo::class); - $property = $reflectionClass->getProperty('bar'); - - $reader = new AnnotationReader(); - $myAnnotation = $reader->getPropertyAnnotation($property, 'bar'); - - echo $myAnnotation->myProperty; // result: "value" - -A reader has multiple methods to access the annotations -of a class. - -:ref:`Read more about handling annotations. ` - -IDE Support ------------ - -Some IDEs already provide support for annotations: - -- Eclipse via the `Symfony2 Plugin `_ -- PHPStorm via the `PHP Annotations Plugin `_ or the `Symfony2 Plugin `_ - -.. _Read more about handling annotations.: annotations -.. _Read more about custom annotations.: custom diff --git a/vendor/doctrine/annotations/docs/en/sidebar.rst b/vendor/doctrine/annotations/docs/en/sidebar.rst deleted file mode 100644 index 6f5d13c..0000000 --- a/vendor/doctrine/annotations/docs/en/sidebar.rst +++ /dev/null @@ -1,6 +0,0 @@ -.. toctree:: - :depth: 3 - - index - annotations - custom diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php deleted file mode 100644 index a79a0f8..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php +++ /dev/null @@ -1,79 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations; - -/** - * Annotations class. - * - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -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. - * - * @throws \BadMethodCallException - */ - 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 Unknown property name. - * @param mixed $value Property value. - * - * @throws \BadMethodCallException - */ - public function __set($name, $value) - { - throw new \BadMethodCallException( - sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this)) - ); - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php deleted file mode 100644 index dbef6df..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php +++ /dev/null @@ -1,47 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations\Annotation; - -/** - * Annotation that can be used to signal to the parser - * to check the attribute type during the parsing process. - * - * @author Fabio B. Silva - * - * @Annotation - */ -final class Attribute -{ - /** - * @var string - */ - public $name; - - /** - * @var string - */ - public $type; - - /** - * @var boolean - */ - public $required = false; -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php deleted file mode 100644 index 53134e3..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php +++ /dev/null @@ -1,37 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations\Annotation; - -/** - * Annotation that can be used to signal to the parser - * to check the types of all declared attributes during the parsing process. - * - * @author Fabio B. Silva - * - * @Annotation - */ -final class Attributes -{ - /** - * @var array - */ - public $value; -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php deleted file mode 100644 index 82f6241..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php +++ /dev/null @@ -1,84 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations\Annotation; - -/** - * Annotation that can be used to signal to the parser - * to check the available values during the parsing process. - * - * @since 2.4 - * @author Fabio B. Silva - * - * @Annotation - * @Attributes({ - * @Attribute("value", required = true, type = "array"), - * @Attribute("literal", required = false, type = "array") - * }) - */ -final class Enum -{ - /** - * @var array - */ - public $value; - - /** - * Literal target declaration. - * - * @var array - */ - public $literal; - - /** - * Annotation constructor. - * - * @param array $values - * - * @throws \InvalidArgumentException - */ - public function __construct(array $values) - { - if ( ! isset($values['literal'])) { - $values['literal'] = []; - } - - foreach ($values['value'] as $var) { - if( ! is_scalar($var)) { - throw new \InvalidArgumentException(sprintf( - '@Enum supports only scalar values "%s" given.', - is_object($var) ? get_class($var) : gettype($var) - )); - } - } - - foreach ($values['literal'] as $key => $var) { - if( ! in_array($key, $values['value'])) { - throw new \InvalidArgumentException(sprintf( - 'Undefined enumerator value "%s" for literal "%s".', - $key , $var - )); - } - } - - $this->value = $values['value']; - $this->literal = $values['literal']; - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php deleted file mode 100644 index 85ec3d6..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php +++ /dev/null @@ -1,54 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations\Annotation; - -/** - * Annotation that can be used to signal to the parser to ignore specific - * annotations during the parsing process. - * - * @Annotation - * @author Johannes M. Schmitt - */ -final class IgnoreAnnotation -{ - /** - * @var array - */ - public $names; - - /** - * Constructor. - * - * @param array $values - * - * @throws \RuntimeException - */ - public function __construct(array $values) - { - if (is_string($values['value'])) { - $values['value'] = [$values['value']]; - } - if (!is_array($values['value'])) { - throw new \RuntimeException(sprintf('@IgnoreAnnotation expects either a string name, or an array of strings, but got %s.', json_encode($values['value']))); - } - - $this->names = $values['value']; - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php deleted file mode 100644 index d67f960..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php +++ /dev/null @@ -1,33 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations\Annotation; - -/** - * Annotation that can be used to signal to the parser - * to check if that attribute is required during the parsing process. - * - * @author Fabio B. Silva - * - * @Annotation - */ -final class Required -{ -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php deleted file mode 100644 index a52972b..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php +++ /dev/null @@ -1,107 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations\Annotation; - -/** - * Annotation that can be used to signal to the parser - * to check the annotation target during the parsing process. - * - * @author Fabio B. Silva - * - * @Annotation - */ -final class Target -{ - const TARGET_CLASS = 1; - const TARGET_METHOD = 2; - const TARGET_PROPERTY = 4; - const TARGET_ANNOTATION = 8; - const TARGET_ALL = 15; - - /** - * @var array - */ - private static $map = [ - 'ALL' => self::TARGET_ALL, - 'CLASS' => self::TARGET_CLASS, - 'METHOD' => self::TARGET_METHOD, - 'PROPERTY' => self::TARGET_PROPERTY, - 'ANNOTATION' => self::TARGET_ANNOTATION, - ]; - - /** - * @var array - */ - public $value; - - /** - * Targets as bitmask. - * - * @var integer - */ - public $targets; - - /** - * Literal target declaration. - * - * @var integer - */ - public $literal; - - /** - * Annotation constructor. - * - * @param array $values - * - * @throws \InvalidArgumentException - */ - public function __construct(array $values) - { - if (!isset($values['value'])){ - $values['value'] = null; - } - if (is_string($values['value'])){ - $values['value'] = [$values['value']]; - } - if (!is_array($values['value'])){ - throw new \InvalidArgumentException( - sprintf('@Target expects either a string value, or an array of strings, "%s" given.', - is_object($values['value']) ? get_class($values['value']) : gettype($values['value']) - ) - ); - } - - $bitmask = 0; - foreach ($values['value'] as $literal) { - if(!isset(self::$map[$literal])){ - throw new \InvalidArgumentException( - sprintf('Invalid Target "%s". Available targets: [%s]', - $literal, implode(', ', array_keys(self::$map))) - ); - } - $bitmask |= self::$map[$literal]; - } - - $this->targets = $bitmask; - $this->value = $values['value']; - $this->literal = implode(', ', $this->value); - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php deleted file mode 100644 index d06fe66..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php +++ /dev/null @@ -1,197 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations; - -/** - * Description of AnnotationException - * - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -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); - } - - /** - * Creates a new AnnotationException describing an error which occurred during - * the creation of the annotation. - * - * @since 2.2 - * - * @param string $message - * - * @return AnnotationException - */ - public static function creationError($message) - { - return new self('[Creation Error] ' . $message); - } - - /** - * Creates a new AnnotationException describing a type error. - * - * @since 1.1 - * - * @param string $message - * - * @return AnnotationException - */ - public static function typeError($message) - { - return new self('[Type Error] ' . $message); - } - - /** - * Creates a new AnnotationException describing a constant semantical error. - * - * @since 2.3 - * - * @param string $identifier - * @param string $context - * - * @return AnnotationException - */ - public static function semanticalErrorConstants($identifier, $context = null) - { - return self::semanticalError(sprintf( - "Couldn't find constant %s%s.", - $identifier, - $context ? ', ' . $context : '' - )); - } - - /** - * Creates a new AnnotationException describing an type error of an attribute. - * - * @since 2.2 - * - * @param string $attributeName - * @param string $annotationName - * @param string $context - * @param string $expected - * @param mixed $actual - * - * @return AnnotationException - */ - public static function attributeTypeError($attributeName, $annotationName, $context, $expected, $actual) - { - return self::typeError(sprintf( - 'Attribute "%s" of @%s declared on %s expects %s, but got %s.', - $attributeName, - $annotationName, - $context, - $expected, - is_object($actual) ? 'an instance of ' . get_class($actual) : gettype($actual) - )); - } - - /** - * Creates a new AnnotationException describing an required error of an attribute. - * - * @since 2.2 - * - * @param string $attributeName - * @param string $annotationName - * @param string $context - * @param string $expected - * - * @return AnnotationException - */ - public static function requiredError($attributeName, $annotationName, $context, $expected) - { - return self::typeError(sprintf( - 'Attribute "%s" of @%s declared on %s expects %s. This value should not be null.', - $attributeName, - $annotationName, - $context, - $expected - )); - } - - /** - * Creates a new AnnotationException describing a invalid enummerator. - * - * @since 2.4 - * - * @param string $attributeName - * @param string $annotationName - * @param string $context - * @param array $available - * @param mixed $given - * - * @return AnnotationException - */ - public static function enumeratorError($attributeName, $annotationName, $context, $available, $given) - { - return new self(sprintf( - '[Enum Error] Attribute "%s" of @%s declared on %s accept only [%s], but got %s.', - $attributeName, - $annotationName, - $context, - implode(', ', $available), - is_object($given) ? get_class($given) : $given - )); - } - - /** - * @return AnnotationException - */ - public static function optimizerPlusSaveComments() - { - return new self( - "You have to enable opcache.save_comments=1 or zend_optimizerplus.save_comments=1." - ); - } - - /** - * @return AnnotationException - */ - public static function optimizerPlusLoadComments() - { - return new self( - "You have to enable opcache.load_comments=1 or zend_optimizerplus.load_comments=1." - ); - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php deleted file mode 100644 index 0b90429..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php +++ /dev/null @@ -1,415 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations; - -use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation; -use Doctrine\Common\Annotations\Annotation\Target; -use ReflectionClass; -use ReflectionMethod; -use ReflectionProperty; - -/** - * A reader for docblock annotations. - * - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Johannes M. Schmitt - */ -class AnnotationReader implements Reader -{ - /** - * Global map for imports. - * - * @var array - */ - private static $globalImports = [ - 'ignoreannotation' => 'Doctrine\Common\Annotations\Annotation\IgnoreAnnotation', - ]; - - /** - * A list with annotations that are not causing exceptions when not resolved to an annotation class. - * - * The names are case sensitive. - * - * @var array - */ - private static $globalIgnoredNames = [ - // Annotation tags - 'Annotation' => true, 'Attribute' => true, 'Attributes' => true, - /* Can we enable this? 'Enum' => true, */ - 'Required' => true, - 'Target' => true, - // Widely used tags (but not existent in phpdoc) - 'fix' => true , 'fixme' => true, - 'override' => true, - // PHPDocumentor 1 tags - 'abstract'=> true, 'access'=> true, - 'code' => true, - 'deprec'=> true, - 'endcode' => true, 'exception'=> true, - 'final'=> true, - 'ingroup' => true, 'inheritdoc'=> true, 'inheritDoc'=> true, - 'magic' => true, - 'name'=> true, - 'toc' => true, 'tutorial'=> true, - 'private' => true, - 'static'=> true, 'staticvar'=> true, 'staticVar'=> true, - 'throw' => true, - // PHPDocumentor 2 tags. - 'api' => true, 'author'=> true, - 'category'=> true, 'copyright'=> true, - 'deprecated'=> true, - 'example'=> true, - 'filesource'=> true, - 'global'=> true, - 'ignore'=> true, /* Can we enable this? 'index' => true, */ 'internal'=> true, - 'license'=> true, 'link'=> true, - 'method' => true, - 'package'=> true, 'param'=> true, 'property' => true, 'property-read' => true, 'property-write' => true, - 'return'=> true, - 'see'=> true, 'since'=> true, 'source' => true, 'subpackage'=> true, - 'throws'=> true, 'todo'=> true, 'TODO'=> true, - 'usedby'=> true, 'uses' => true, - 'var'=> true, 'version'=> true, - // PHPUnit tags - 'codeCoverageIgnore' => true, 'codeCoverageIgnoreStart' => true, 'codeCoverageIgnoreEnd' => true, - // PHPCheckStyle - 'SuppressWarnings' => true, - // PHPStorm - 'noinspection' => true, - // PEAR - 'package_version' => true, - // PlantUML - 'startuml' => true, 'enduml' => true, - // Symfony 3.3 Cache Adapter - 'experimental' => true, - // Slevomat Coding Standard - 'phpcsSuppress' => true, - // PHP CodeSniffer - 'codingStandardsIgnoreStart' => true, - 'codingStandardsIgnoreEnd' => true, - ]; - - /** - * A list with annotations that are not causing exceptions when not resolved to an annotation class. - * - * The names are case sensitive. - * - * @var array - */ - private static $globalIgnoredNamespaces = []; - - /** - * Add a new annotation to the globally ignored annotation names with regard to exception handling. - * - * @param string $name - */ - static public function addGlobalIgnoredName($name) - { - self::$globalIgnoredNames[$name] = true; - } - - /** - * Add a new annotation to the globally ignored annotation namespaces with regard to exception handling. - * - * @param string $namespace - */ - static public function addGlobalIgnoredNamespace($namespace) - { - self::$globalIgnoredNamespaces[$namespace] = true; - } - - /** - * Annotations parser. - * - * @var \Doctrine\Common\Annotations\DocParser - */ - private $parser; - - /** - * Annotations parser used to collect parsing metadata. - * - * @var \Doctrine\Common\Annotations\DocParser - */ - private $preParser; - - /** - * PHP parser used to collect imports. - * - * @var \Doctrine\Common\Annotations\PhpParser - */ - private $phpParser; - - /** - * In-memory cache mechanism to store imported annotations per class. - * - * @var array - */ - private $imports = []; - - /** - * In-memory cache mechanism to store ignored annotations per class. - * - * @var array - */ - private $ignoredAnnotationNames = []; - - /** - * Constructor. - * - * Initializes a new AnnotationReader. - * - * @param DocParser $parser - * - * @throws AnnotationException - */ - public function __construct(DocParser $parser = null) - { - if (extension_loaded('Zend Optimizer+') && (ini_get('zend_optimizerplus.save_comments') === "0" || ini_get('opcache.save_comments') === "0")) { - throw AnnotationException::optimizerPlusSaveComments(); - } - - if (extension_loaded('Zend OPcache') && ini_get('opcache.save_comments') == 0) { - throw AnnotationException::optimizerPlusSaveComments(); - } - - AnnotationRegistry::registerFile(__DIR__ . '/Annotation/IgnoreAnnotation.php'); - - $this->parser = $parser ?: new DocParser(); - - $this->preParser = new DocParser; - - $this->preParser->setImports(self::$globalImports); - $this->preParser->setIgnoreNotImportedAnnotations(true); - $this->preParser->setIgnoredAnnotationNames(self::$globalIgnoredNames); - - $this->phpParser = new PhpParser; - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotations(ReflectionClass $class) - { - $this->parser->setTarget(Target::TARGET_CLASS); - $this->parser->setImports($this->getClassImports($class)); - $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); - $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); - - return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName()); - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotation(ReflectionClass $class, $annotationName) - { - $annotations = $this->getClassAnnotations($class); - - foreach ($annotations as $annotation) { - if ($annotation instanceof $annotationName) { - return $annotation; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotations(ReflectionProperty $property) - { - $class = $property->getDeclaringClass(); - $context = 'property ' . $class->getName() . "::\$" . $property->getName(); - - $this->parser->setTarget(Target::TARGET_PROPERTY); - $this->parser->setImports($this->getPropertyImports($property)); - $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); - $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); - - return $this->parser->parse($property->getDocComment(), $context); - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) - { - $annotations = $this->getPropertyAnnotations($property); - - foreach ($annotations as $annotation) { - if ($annotation instanceof $annotationName) { - return $annotation; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotations(ReflectionMethod $method) - { - $class = $method->getDeclaringClass(); - $context = 'method ' . $class->getName() . '::' . $method->getName() . '()'; - - $this->parser->setTarget(Target::TARGET_METHOD); - $this->parser->setImports($this->getMethodImports($method)); - $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); - $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); - - return $this->parser->parse($method->getDocComment(), $context); - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotation(ReflectionMethod $method, $annotationName) - { - $annotations = $this->getMethodAnnotations($method); - - foreach ($annotations as $annotation) { - if ($annotation instanceof $annotationName) { - return $annotation; - } - } - - return null; - } - - /** - * Returns the ignored annotations for the given class. - * - * @param \ReflectionClass $class - * - * @return array - */ - private function getIgnoredAnnotationNames(ReflectionClass $class) - { - $name = $class->getName(); - if (isset($this->ignoredAnnotationNames[$name])) { - return $this->ignoredAnnotationNames[$name]; - } - - $this->collectParsingMetadata($class); - - return $this->ignoredAnnotationNames[$name]; - } - - /** - * Retrieves imports. - * - * @param \ReflectionClass $class - * - * @return array - */ - private function getClassImports(ReflectionClass $class) - { - $name = $class->getName(); - if (isset($this->imports[$name])) { - return $this->imports[$name]; - } - - $this->collectParsingMetadata($class); - - return $this->imports[$name]; - } - - /** - * Retrieves imports for methods. - * - * @param \ReflectionMethod $method - * - * @return array - */ - private function getMethodImports(ReflectionMethod $method) - { - $class = $method->getDeclaringClass(); - $classImports = $this->getClassImports($class); - - $traitImports = []; - - foreach ($class->getTraits() as $trait) { - if ($trait->hasMethod($method->getName()) - && $trait->getFileName() === $method->getFileName() - ) { - $traitImports = array_merge($traitImports, $this->phpParser->parseClass($trait)); - } - } - - return array_merge($classImports, $traitImports); - } - - /** - * Retrieves imports for properties. - * - * @param \ReflectionProperty $property - * - * @return array - */ - private function getPropertyImports(ReflectionProperty $property) - { - $class = $property->getDeclaringClass(); - $classImports = $this->getClassImports($class); - - $traitImports = []; - - foreach ($class->getTraits() as $trait) { - if ($trait->hasProperty($property->getName())) { - $traitImports = array_merge($traitImports, $this->phpParser->parseClass($trait)); - } - } - - return array_merge($classImports, $traitImports); - } - - /** - * Collects parsing metadata for a given class. - * - * @param \ReflectionClass $class - */ - private function collectParsingMetadata(ReflectionClass $class) - { - $ignoredAnnotationNames = self::$globalIgnoredNames; - $annotations = $this->preParser->parse($class->getDocComment(), 'class ' . $class->name); - - foreach ($annotations as $annotation) { - if ($annotation instanceof IgnoreAnnotation) { - foreach ($annotation->names AS $annot) { - $ignoredAnnotationNames[$annot] = true; - } - } - } - - $name = $class->getName(); - - $this->imports[$name] = array_merge( - self::$globalImports, - $this->phpParser->parseClass($class), - ['__NAMESPACE__' => $class->getNamespaceName()] - ); - - $this->ignoredAnnotationNames[$name] = $ignoredAnnotationNames; - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php deleted file mode 100644 index 13abaf5..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php +++ /dev/null @@ -1,174 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations; - -final class AnnotationRegistry -{ - /** - * A map of namespaces to use for autoloading purposes based on a PSR-0 convention. - * - * Contains the namespace as key and an array of directories as value. If the value is NULL - * the include path is used for checking for the corresponding file. - * - * This autoloading mechanism does not utilize the PHP autoloading but implements autoloading on its own. - * - * @var string[][]|string[]|null[] - */ - static private $autoloadNamespaces = []; - - /** - * A map of autoloader callables. - * - * @var callable[] - */ - static private $loaders = []; - - /** - * An array of classes which cannot be found - * - * @var null[] indexed by class name - */ - static private $failedToAutoload = []; - - public static function reset() : void - { - self::$autoloadNamespaces = []; - self::$loaders = []; - self::$failedToAutoload = []; - } - - /** - * Registers file. - * - * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 - * autoloading should be deferred to the globally registered autoloader by then. For now, - * use @example AnnotationRegistry::registerLoader('class_exists') - */ - public static function registerFile(string $file) : void - { - require_once $file; - } - - /** - * Adds a namespace with one or many directories to look for files or null for the include path. - * - * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm. - * - * @param string $namespace - * @param string|array|null $dirs - * - * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 - * autoloading should be deferred to the globally registered autoloader by then. For now, - * use @example AnnotationRegistry::registerLoader('class_exists') - */ - public static function registerAutoloadNamespace(string $namespace, $dirs = null) : void - { - self::$autoloadNamespaces[$namespace] = $dirs; - } - - /** - * Registers multiple namespaces. - * - * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm. - * - * @param string[][]|string[]|null[] $namespaces indexed by namespace name - * - * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 - * autoloading should be deferred to the globally registered autoloader by then. For now, - * use @example AnnotationRegistry::registerLoader('class_exists') - */ - public static function registerAutoloadNamespaces(array $namespaces) : void - { - self::$autoloadNamespaces = \array_merge(self::$autoloadNamespaces, $namespaces); - } - - /** - * Registers an autoloading callable for annotations, much like spl_autoload_register(). - * - * NOTE: These class loaders HAVE to be silent when a class was not found! - * IMPORTANT: Loaders have to return true if they loaded a class that could contain the searched annotation class. - * - * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 - * autoloading should be deferred to the globally registered autoloader by then. For now, - * use @example AnnotationRegistry::registerLoader('class_exists') - */ - public static function registerLoader(callable $callable) : void - { - // Reset our static cache now that we have a new loader to work with - self::$failedToAutoload = []; - self::$loaders[] = $callable; - } - - /** - * Registers an autoloading callable for annotations, if it is not already registered - * - * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 - */ - public static function registerUniqueLoader(callable $callable) : void - { - if ( ! in_array($callable, self::$loaders, true) ) { - self::registerLoader($callable); - } - } - - /** - * Autoloads an annotation class silently. - */ - public static function loadAnnotationClass(string $class) : bool - { - if (\class_exists($class, false)) { - return true; - } - - if (\array_key_exists($class, self::$failedToAutoload)) { - return false; - } - - foreach (self::$autoloadNamespaces AS $namespace => $dirs) { - if (\strpos($class, $namespace) === 0) { - $file = \str_replace('\\', \DIRECTORY_SEPARATOR, $class) . '.php'; - - if ($dirs === null) { - if ($path = stream_resolve_include_path($file)) { - require $path; - return true; - } - } else { - foreach((array) $dirs AS $dir) { - if (is_file($dir . \DIRECTORY_SEPARATOR . $file)) { - require $dir . \DIRECTORY_SEPARATOR . $file; - return true; - } - } - } - } - } - - foreach (self::$loaders AS $loader) { - if ($loader($class) === true) { - return true; - } - } - - self::$failedToAutoload[$class] = null; - - return false; - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php deleted file mode 100644 index 674b66b..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php +++ /dev/null @@ -1,262 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations; - -use Doctrine\Common\Cache\Cache; -use ReflectionClass; - -/** - * A cache aware annotation reader. - * - * @author Johannes M. Schmitt - * @author Benjamin Eberlei - */ -final class CachedReader implements Reader -{ - /** - * @var Reader - */ - private $delegate; - - /** - * @var Cache - */ - private $cache; - - /** - * @var boolean - */ - private $debug; - - /** - * @var array - */ - private $loadedAnnotations = []; - - /** - * Constructor. - * - * @param Reader $reader - * @param Cache $cache - * @param bool $debug - */ - public function __construct(Reader $reader, Cache $cache, $debug = false) - { - $this->delegate = $reader; - $this->cache = $cache; - $this->debug = (boolean) $debug; - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotations(ReflectionClass $class) - { - $cacheKey = $class->getName(); - - if (isset($this->loadedAnnotations[$cacheKey])) { - return $this->loadedAnnotations[$cacheKey]; - } - - if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { - $annots = $this->delegate->getClassAnnotations($class); - $this->saveToCache($cacheKey, $annots); - } - - return $this->loadedAnnotations[$cacheKey] = $annots; - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotation(ReflectionClass $class, $annotationName) - { - foreach ($this->getClassAnnotations($class) as $annot) { - if ($annot instanceof $annotationName) { - return $annot; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotations(\ReflectionProperty $property) - { - $class = $property->getDeclaringClass(); - $cacheKey = $class->getName().'$'.$property->getName(); - - if (isset($this->loadedAnnotations[$cacheKey])) { - return $this->loadedAnnotations[$cacheKey]; - } - - if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { - $annots = $this->delegate->getPropertyAnnotations($property); - $this->saveToCache($cacheKey, $annots); - } - - return $this->loadedAnnotations[$cacheKey] = $annots; - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) - { - foreach ($this->getPropertyAnnotations($property) as $annot) { - if ($annot instanceof $annotationName) { - return $annot; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotations(\ReflectionMethod $method) - { - $class = $method->getDeclaringClass(); - $cacheKey = $class->getName().'#'.$method->getName(); - - if (isset($this->loadedAnnotations[$cacheKey])) { - return $this->loadedAnnotations[$cacheKey]; - } - - if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { - $annots = $this->delegate->getMethodAnnotations($method); - $this->saveToCache($cacheKey, $annots); - } - - return $this->loadedAnnotations[$cacheKey] = $annots; - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) - { - foreach ($this->getMethodAnnotations($method) as $annot) { - if ($annot instanceof $annotationName) { - return $annot; - } - } - - return null; - } - - /** - * Clears loaded annotations. - * - * @return void - */ - public function clearLoadedAnnotations() - { - $this->loadedAnnotations = []; - } - - /** - * Fetches a value from the cache. - * - * @param string $cacheKey The cache key. - * @param ReflectionClass $class The related class. - * - * @return mixed The cached value or false when the value is not in cache. - */ - private function fetchFromCache($cacheKey, ReflectionClass $class) - { - if (($data = $this->cache->fetch($cacheKey)) !== false) { - if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) { - return $data; - } - } - - return false; - } - - /** - * Saves a value to the cache. - * - * @param string $cacheKey The cache key. - * @param mixed $value The value. - * - * @return void - */ - private function saveToCache($cacheKey, $value) - { - $this->cache->save($cacheKey, $value); - if ($this->debug) { - $this->cache->save('[C]'.$cacheKey, time()); - } - } - - /** - * Checks if the cache is fresh. - * - * @param string $cacheKey - * @param ReflectionClass $class - * - * @return boolean - */ - private function isCacheFresh($cacheKey, ReflectionClass $class) - { - if (null === $lastModification = $this->getLastModification($class)) { - return true; - } - - return $this->cache->fetch('[C]'.$cacheKey) >= $lastModification; - } - - /** - * Returns the time the class was last modified, testing traits and parents - * - * @param ReflectionClass $class - * @return int - */ - private function getLastModification(ReflectionClass $class) - { - $filename = $class->getFileName(); - $parent = $class->getParentClass(); - - return max(array_merge( - [$filename ? filemtime($filename) : 0], - array_map([$this, 'getTraitLastModificationTime'], $class->getTraits()), - array_map([$this, 'getLastModification'], $class->getInterfaces()), - $parent ? [$this->getLastModification($parent)] : [] - )); - } - - /** - * @param ReflectionClass $reflectionTrait - * @return int - */ - private function getTraitLastModificationTime(ReflectionClass $reflectionTrait) - { - $fileName = $reflectionTrait->getFileName(); - - return max(array_merge( - [$fileName ? filemtime($fileName) : 0], - array_map([$this, 'getTraitLastModificationTime'], $reflectionTrait->getTraits()) - )); - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php deleted file mode 100644 index 8182f6c..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php +++ /dev/null @@ -1,147 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations; - -use Doctrine\Common\Lexer\AbstractLexer; - -/** - * Simple lexer for docblock annotations. - * - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Johannes M. Schmitt - */ -final class DocLexer extends AbstractLexer -{ - const T_NONE = 1; - const T_INTEGER = 2; - const T_STRING = 3; - const T_FLOAT = 4; - - // All tokens that are also identifiers should be >= 100 - const T_IDENTIFIER = 100; - 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; - const T_NULL = 111; - const T_COLON = 112; - const T_MINUS = 113; - - /** - * @var array - */ - protected $noCase = [ - '@' => self::T_AT, - ',' => self::T_COMMA, - '(' => self::T_OPEN_PARENTHESIS, - ')' => self::T_CLOSE_PARENTHESIS, - '{' => self::T_OPEN_CURLY_BRACES, - '}' => self::T_CLOSE_CURLY_BRACES, - '=' => self::T_EQUALS, - ':' => self::T_COLON, - '-' => self::T_MINUS, - '\\' => self::T_NAMESPACE_SEPARATOR - ]; - - /** - * @var array - */ - protected $withCase = [ - 'true' => self::T_TRUE, - 'false' => self::T_FALSE, - 'null' => self::T_NULL - ]; - - /** - * Whether the next token starts immediately, or if there were - * non-captured symbols before that - */ - public function nextTokenIsAdjacent() : bool - { - return $this->token === null - || ($this->lookahead !== null - && ($this->lookahead['position'] - $this->token['position']) === strlen($this->token['value'])); - } - - /** - * {@inheritdoc} - */ - protected function getCatchablePatterns() - { - return [ - '[a-z_\\\][a-z0-9_\:\\\]*[a-z_][a-z0-9_]*', - '(?:[+-]?[0-9]+(?:[\.][0-9]+)*)(?:[eE][+-]?[0-9]+)?', - '"(?:""|[^"])*+"', - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNonCatchablePatterns() - { - return ['\s+', '\*+', '(.)']; - } - - /** - * {@inheritdoc} - */ - protected function getType(&$value) - { - $type = self::T_NONE; - - if ($value[0] === '"') { - $value = str_replace('""', '"', substr($value, 1, strlen($value) - 2)); - - return self::T_STRING; - } - - if (isset($this->noCase[$value])) { - return $this->noCase[$value]; - } - - if ($value[0] === '_' || $value[0] === '\\' || ctype_alpha($value[0])) { - return self::T_IDENTIFIER; - } - - $lowerValue = strtolower($value); - - if (isset($this->withCase[$lowerValue])) { - return $this->withCase[$lowerValue]; - } - - // Checking numeric value - if (is_numeric($value)) { - return (strpos($value, '.') !== false || stripos($value, 'e') !== false) - ? self::T_FLOAT : self::T_INTEGER; - } - - return $type; - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php deleted file mode 100644 index f076f36..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php +++ /dev/null @@ -1,1197 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations; - -use Doctrine\Common\Annotations\Annotation\Attribute; -use ReflectionClass; -use Doctrine\Common\Annotations\Annotation\Enum; -use Doctrine\Common\Annotations\Annotation\Target; -use Doctrine\Common\Annotations\Annotation\Attributes; - -/** - * A parser for docblock annotations. - * - * It is strongly discouraged to change the default annotation parsing process. - * - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Johannes M. Schmitt - * @author Fabio B. Silva - */ -final class DocParser -{ - /** - * An array of all valid tokens for a class name. - * - * @var array - */ - private static $classIdentifiers = [ - DocLexer::T_IDENTIFIER, - DocLexer::T_TRUE, - DocLexer::T_FALSE, - DocLexer::T_NULL - ]; - - /** - * The lexer. - * - * @var \Doctrine\Common\Annotations\DocLexer - */ - private $lexer; - - /** - * Current target context. - * - * @var integer - */ - private $target; - - /** - * Doc parser used to collect annotation target. - * - * @var \Doctrine\Common\Annotations\DocParser - */ - private static $metadataParser; - - /** - * Flag to control if the current annotation is nested or not. - * - * @var boolean - */ - private $isNestedAnnotation = false; - - /** - * Hashmap containing all use-statements that are to be used when parsing - * the given doc block. - * - * @var array - */ - private $imports = []; - - /** - * This hashmap is used internally to cache results of class_exists() - * look-ups. - * - * @var array - */ - private $classExists = []; - - /** - * Whether annotations that have not been imported should be ignored. - * - * @var boolean - */ - private $ignoreNotImportedAnnotations = false; - - /** - * An array of default namespaces if operating in simple mode. - * - * @var string[] - */ - private $namespaces = []; - - /** - * A list with annotations that are not causing exceptions when not resolved to an annotation class. - * - * The names must be the raw names as used in the class, not the fully qualified - * class names. - * - * @var bool[] indexed by annotation name - */ - private $ignoredAnnotationNames = []; - - /** - * A list with annotations in namespaced format - * that are not causing exceptions when not resolved to an annotation class. - * - * @var bool[] indexed by namespace name - */ - private $ignoredAnnotationNamespaces = []; - - /** - * @var string - */ - private $context = ''; - - /** - * Hash-map for caching annotation metadata. - * - * @var array - */ - private static $annotationMetadata = [ - 'Doctrine\Common\Annotations\Annotation\Target' => [ - 'is_annotation' => true, - 'has_constructor' => true, - 'properties' => [], - 'targets_literal' => 'ANNOTATION_CLASS', - 'targets' => Target::TARGET_CLASS, - 'default_property' => 'value', - 'attribute_types' => [ - 'value' => [ - 'required' => false, - 'type' =>'array', - 'array_type'=>'string', - 'value' =>'array' - ] - ], - ], - 'Doctrine\Common\Annotations\Annotation\Attribute' => [ - 'is_annotation' => true, - 'has_constructor' => false, - 'targets_literal' => 'ANNOTATION_ANNOTATION', - 'targets' => Target::TARGET_ANNOTATION, - 'default_property' => 'name', - 'properties' => [ - 'name' => 'name', - 'type' => 'type', - 'required' => 'required' - ], - 'attribute_types' => [ - 'value' => [ - 'required' => true, - 'type' =>'string', - 'value' =>'string' - ], - 'type' => [ - 'required' =>true, - 'type' =>'string', - 'value' =>'string' - ], - 'required' => [ - 'required' =>false, - 'type' =>'boolean', - 'value' =>'boolean' - ] - ], - ], - 'Doctrine\Common\Annotations\Annotation\Attributes' => [ - 'is_annotation' => true, - 'has_constructor' => false, - 'targets_literal' => 'ANNOTATION_CLASS', - 'targets' => Target::TARGET_CLASS, - 'default_property' => 'value', - 'properties' => [ - 'value' => 'value' - ], - 'attribute_types' => [ - 'value' => [ - 'type' =>'array', - 'required' =>true, - 'array_type'=>'Doctrine\Common\Annotations\Annotation\Attribute', - 'value' =>'array' - ] - ], - ], - 'Doctrine\Common\Annotations\Annotation\Enum' => [ - 'is_annotation' => true, - 'has_constructor' => true, - 'targets_literal' => 'ANNOTATION_PROPERTY', - 'targets' => Target::TARGET_PROPERTY, - 'default_property' => 'value', - 'properties' => [ - 'value' => 'value' - ], - 'attribute_types' => [ - 'value' => [ - 'type' => 'array', - 'required' => true, - ], - 'literal' => [ - 'type' => 'array', - 'required' => false, - ], - ], - ], - ]; - - /** - * Hash-map for handle types declaration. - * - * @var array - */ - private static $typeMap = [ - 'float' => 'double', - 'bool' => 'boolean', - // allow uppercase Boolean in honor of George Boole - 'Boolean' => 'boolean', - 'int' => 'integer', - ]; - - /** - * Constructs a new DocParser. - */ - public function __construct() - { - $this->lexer = new DocLexer; - } - - /** - * Sets the annotation names that are ignored during the parsing process. - * - * The names are supposed to be the raw names as used in the class, not the - * fully qualified class names. - * - * @param bool[] $names indexed by annotation name - * - * @return void - */ - public function setIgnoredAnnotationNames(array $names) - { - $this->ignoredAnnotationNames = $names; - } - - /** - * Sets the annotation namespaces that are ignored during the parsing process. - * - * @param bool[] $ignoredAnnotationNamespaces indexed by annotation namespace name - * - * @return void - */ - public function setIgnoredAnnotationNamespaces($ignoredAnnotationNamespaces) - { - $this->ignoredAnnotationNamespaces = $ignoredAnnotationNamespaces; - } - - /** - * Sets ignore on not-imported annotations. - * - * @param boolean $bool - * - * @return void - */ - public function setIgnoreNotImportedAnnotations($bool) - { - $this->ignoreNotImportedAnnotations = (boolean) $bool; - } - - /** - * Sets the default namespaces. - * - * @param string $namespace - * - * @return void - * - * @throws \RuntimeException - */ - public function addNamespace($namespace) - { - if ($this->imports) { - throw new \RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); - } - - $this->namespaces[] = $namespace; - } - - /** - * Sets the imports. - * - * @param array $imports - * - * @return void - * - * @throws \RuntimeException - */ - public function setImports(array $imports) - { - if ($this->namespaces) { - throw new \RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); - } - - $this->imports = $imports; - } - - /** - * Sets current target context as bitmask. - * - * @param integer $target - * - * @return void - */ - public function setTarget($target) - { - $this->target = $target; - } - - /** - * Parses the given docblock string for annotations. - * - * @param string $input 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($input, $context = '') - { - $pos = $this->findInitialTokenPosition($input); - if ($pos === null) { - return []; - } - - $this->context = $context; - - $this->lexer->setInput(trim(substr($input, $pos), '* /')); - $this->lexer->moveNext(); - - return $this->Annotations(); - } - - /** - * Finds the first valid annotation - * - * @param string $input The docblock string to parse - * - * @return int|null - */ - private function findInitialTokenPosition($input) - { - $pos = 0; - - // search for first valid annotation - while (($pos = strpos($input, '@', $pos)) !== false) { - $preceding = substr($input, $pos - 1, 1); - - // if the @ is preceded by a space, a tab or * it is valid - if ($pos === 0 || $preceding === ' ' || $preceding === '*' || $preceding === "\t") { - return $pos; - } - - $pos++; - } - - return null; - } - - /** - * Attempts to match the given token with the current lookahead token. - * If they match, updates the lookahead token; otherwise raises a syntax error. - * - * @param integer $token Type of token. - * - * @return boolean True if tokens match; false otherwise. - */ - private function match($token) - { - if ( ! $this->lexer->isNextToken($token) ) { - $this->syntaxError($this->lexer->getLiteral($token)); - } - - return $this->lexer->moveNext(); - } - - /** - * Attempts to match the current lookahead token with any of the given tokens. - * - * If any of them matches, this method updates the lookahead token; otherwise - * a syntax error is raised. - * - * @param array $tokens - * - * @return boolean - */ - private function matchAny(array $tokens) - { - if ( ! $this->lexer->isNextTokenAny($tokens)) { - $this->syntaxError(implode(' or ', array_map([$this->lexer, 'getLiteral'], $tokens))); - } - - return $this->lexer->moveNext(); - } - - /** - * Generates a new syntax error. - * - * @param string $expected Expected string. - * @param array|null $token Optional token. - * - * @return void - * - * @throws AnnotationException - */ - private function syntaxError($expected, $token = null) - { - if ($token === null) { - $token = $this->lexer->lookahead; - } - - $message = sprintf('Expected %s, got ', $expected); - $message .= ($this->lexer->lookahead === null) - ? 'end of string' - : sprintf("'%s' at position %s", $token['value'], $token['position']); - - if (strlen($this->context)) { - $message .= ' in ' . $this->context; - } - - $message .= '.'; - - throw AnnotationException::syntaxError($message); - } - - /** - * Attempts to check if a class exists or not. This never goes through the PHP autoloading mechanism - * but uses the {@link AnnotationRegistry} to load classes. - * - * @param string $fqcn - * - * @return boolean - */ - private function classExists($fqcn) - { - if (isset($this->classExists[$fqcn])) { - return $this->classExists[$fqcn]; - } - - // first check if the class already exists, maybe loaded through another AnnotationReader - if (class_exists($fqcn, false)) { - return $this->classExists[$fqcn] = true; - } - - // final check, does this class exist? - return $this->classExists[$fqcn] = AnnotationRegistry::loadAnnotationClass($fqcn); - } - - /** - * Collects parsing metadata for a given annotation class - * - * @param string $name The annotation name - * - * @return void - */ - private function collectAnnotationMetadata($name) - { - if (self::$metadataParser === null) { - self::$metadataParser = new self(); - - self::$metadataParser->setIgnoreNotImportedAnnotations(true); - self::$metadataParser->setIgnoredAnnotationNames($this->ignoredAnnotationNames); - self::$metadataParser->setImports([ - 'enum' => 'Doctrine\Common\Annotations\Annotation\Enum', - 'target' => 'Doctrine\Common\Annotations\Annotation\Target', - 'attribute' => 'Doctrine\Common\Annotations\Annotation\Attribute', - 'attributes' => 'Doctrine\Common\Annotations\Annotation\Attributes' - ]); - - AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Enum.php'); - AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Target.php'); - AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attribute.php'); - AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attributes.php'); - } - - $class = new \ReflectionClass($name); - $docComment = $class->getDocComment(); - - // Sets default values for annotation metadata - $metadata = [ - 'default_property' => null, - 'has_constructor' => (null !== $constructor = $class->getConstructor()) && $constructor->getNumberOfParameters() > 0, - 'properties' => [], - 'property_types' => [], - 'attribute_types' => [], - 'targets_literal' => null, - 'targets' => Target::TARGET_ALL, - 'is_annotation' => false !== strpos($docComment, '@Annotation'), - ]; - - // verify that the class is really meant to be an annotation - if ($metadata['is_annotation']) { - self::$metadataParser->setTarget(Target::TARGET_CLASS); - - foreach (self::$metadataParser->parse($docComment, 'class @' . $name) as $annotation) { - if ($annotation instanceof Target) { - $metadata['targets'] = $annotation->targets; - $metadata['targets_literal'] = $annotation->literal; - - continue; - } - - if ($annotation instanceof Attributes) { - foreach ($annotation->value as $attribute) { - $this->collectAttributeTypeMetadata($metadata, $attribute); - } - } - } - - // if not has a constructor will inject values into public properties - if (false === $metadata['has_constructor']) { - // collect all public properties - foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { - $metadata['properties'][$property->name] = $property->name; - - if (false === ($propertyComment = $property->getDocComment())) { - continue; - } - - $attribute = new Attribute(); - - $attribute->required = (false !== strpos($propertyComment, '@Required')); - $attribute->name = $property->name; - $attribute->type = (false !== strpos($propertyComment, '@var') && preg_match('/@var\s+([^\s]+)/',$propertyComment, $matches)) - ? $matches[1] - : 'mixed'; - - $this->collectAttributeTypeMetadata($metadata, $attribute); - - // checks if the property has @Enum - if (false !== strpos($propertyComment, '@Enum')) { - $context = 'property ' . $class->name . "::\$" . $property->name; - - self::$metadataParser->setTarget(Target::TARGET_PROPERTY); - - foreach (self::$metadataParser->parse($propertyComment, $context) as $annotation) { - if ( ! $annotation instanceof Enum) { - continue; - } - - $metadata['enum'][$property->name]['value'] = $annotation->value; - $metadata['enum'][$property->name]['literal'] = ( ! empty($annotation->literal)) - ? $annotation->literal - : $annotation->value; - } - } - } - - // choose the first property as default property - $metadata['default_property'] = reset($metadata['properties']); - } - } - - self::$annotationMetadata[$name] = $metadata; - } - - /** - * Collects parsing metadata for a given attribute. - * - * @param array $metadata - * @param Attribute $attribute - * - * @return void - */ - private function collectAttributeTypeMetadata(&$metadata, Attribute $attribute) - { - // handle internal type declaration - $type = self::$typeMap[$attribute->type] ?? $attribute->type; - - // handle the case if the property type is mixed - if ('mixed' === $type) { - return; - } - - // Evaluate type - switch (true) { - // Checks if the property has array - case (false !== $pos = strpos($type, '<')): - $arrayType = substr($type, $pos + 1, -1); - $type = 'array'; - - if (isset(self::$typeMap[$arrayType])) { - $arrayType = self::$typeMap[$arrayType]; - } - - $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType; - break; - - // Checks if the property has type[] - case (false !== $pos = strrpos($type, '[')): - $arrayType = substr($type, 0, $pos); - $type = 'array'; - - if (isset(self::$typeMap[$arrayType])) { - $arrayType = self::$typeMap[$arrayType]; - } - - $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType; - break; - } - - $metadata['attribute_types'][$attribute->name]['type'] = $type; - $metadata['attribute_types'][$attribute->name]['value'] = $attribute->type; - $metadata['attribute_types'][$attribute->name]['required'] = $attribute->required; - } - - /** - * Annotations ::= Annotation {[ "*" ]* [Annotation]}* - * - * @return array - */ - private function Annotations() - { - $annotations = []; - - while (null !== $this->lexer->lookahead) { - if (DocLexer::T_AT !== $this->lexer->lookahead['type']) { - $this->lexer->moveNext(); - continue; - } - - // make sure the @ is preceded by non-catchable pattern - if (null !== $this->lexer->token && $this->lexer->lookahead['position'] === $this->lexer->token['position'] + strlen($this->lexer->token['value'])) { - $this->lexer->moveNext(); - continue; - } - - // make sure the @ is followed by either a namespace separator, or - // an identifier token - if ((null === $peek = $this->lexer->glimpse()) - || (DocLexer::T_NAMESPACE_SEPARATOR !== $peek['type'] && !in_array($peek['type'], self::$classIdentifiers, true)) - || $peek['position'] !== $this->lexer->lookahead['position'] + 1) { - $this->lexer->moveNext(); - continue; - } - - $this->isNestedAnnotation = false; - if (false !== $annot = $this->Annotation()) { - $annotations[] = $annot; - } - } - - return $annotations; - } - - /** - * Annotation ::= "@" AnnotationName MethodCall - * AnnotationName ::= QualifiedName | SimpleName - * QualifiedName ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleName - * NameSpacePart ::= identifier | null | false | true - * SimpleName ::= identifier | null | false | true - * - * @return mixed False if it is not a valid annotation. - * - * @throws AnnotationException - */ - private function Annotation() - { - $this->match(DocLexer::T_AT); - - // check if we have an annotation - $name = $this->Identifier(); - - if ($this->lexer->isNextToken(DocLexer::T_MINUS) - && $this->lexer->nextTokenIsAdjacent() - ) { - // Annotations with dashes, such as "@foo-" or "@foo-bar", are to be discarded - return false; - } - - // only process names which are not fully qualified, yet - // fully qualified names must start with a \ - $originalName = $name; - - if ('\\' !== $name[0]) { - $pos = strpos($name, '\\'); - $alias = (false === $pos)? $name : substr($name, 0, $pos); - $found = false; - $loweredAlias = strtolower($alias); - - if ($this->namespaces) { - foreach ($this->namespaces as $namespace) { - if ($this->classExists($namespace.'\\'.$name)) { - $name = $namespace.'\\'.$name; - $found = true; - break; - } - } - } elseif (isset($this->imports[$loweredAlias])) { - $found = true; - $name = (false !== $pos) - ? $this->imports[$loweredAlias] . substr($name, $pos) - : $this->imports[$loweredAlias]; - } elseif ( ! isset($this->ignoredAnnotationNames[$name]) - && isset($this->imports['__NAMESPACE__']) - && $this->classExists($this->imports['__NAMESPACE__'] . '\\' . $name) - ) { - $name = $this->imports['__NAMESPACE__'].'\\'.$name; - $found = true; - } elseif (! isset($this->ignoredAnnotationNames[$name]) && $this->classExists($name)) { - $found = true; - } - - if ( ! $found) { - if ($this->isIgnoredAnnotation($name)) { - return false; - } - - throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation?', $name, $this->context)); - } - } - - $name = ltrim($name,'\\'); - - if ( ! $this->classExists($name)) { - throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s does not exist, or could not be auto-loaded.', $name, $this->context)); - } - - // at this point, $name contains the fully qualified class name of the - // annotation, and it is also guaranteed that this class exists, and - // that it is loaded - - - // collects the metadata annotation only if there is not yet - if ( ! isset(self::$annotationMetadata[$name])) { - $this->collectAnnotationMetadata($name); - } - - // verify that the class is really meant to be an annotation and not just any ordinary class - if (self::$annotationMetadata[$name]['is_annotation'] === false) { - if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$originalName])) { - return false; - } - - throw AnnotationException::semanticalError(sprintf('The class "%s" is not annotated with @Annotation. Are you sure this class can be used as annotation? If so, then you need to add @Annotation to the _class_ doc comment of "%s". If it is indeed no annotation, then you need to add @IgnoreAnnotation("%s") to the _class_ doc comment of %s.', $name, $name, $originalName, $this->context)); - } - - //if target is nested annotation - $target = $this->isNestedAnnotation ? Target::TARGET_ANNOTATION : $this->target; - - // Next will be nested - $this->isNestedAnnotation = true; - - //if annotation does not support current target - if (0 === (self::$annotationMetadata[$name]['targets'] & $target) && $target) { - throw AnnotationException::semanticalError( - sprintf('Annotation @%s is not allowed to be declared on %s. You may only use this annotation on these code elements: %s.', - $originalName, $this->context, self::$annotationMetadata[$name]['targets_literal']) - ); - } - - $values = $this->MethodCall(); - - if (isset(self::$annotationMetadata[$name]['enum'])) { - // checks all declared attributes - foreach (self::$annotationMetadata[$name]['enum'] as $property => $enum) { - // checks if the attribute is a valid enumerator - if (isset($values[$property]) && ! in_array($values[$property], $enum['value'])) { - throw AnnotationException::enumeratorError($property, $name, $this->context, $enum['literal'], $values[$property]); - } - } - } - - // checks all declared attributes - foreach (self::$annotationMetadata[$name]['attribute_types'] as $property => $type) { - if ($property === self::$annotationMetadata[$name]['default_property'] - && !isset($values[$property]) && isset($values['value'])) { - $property = 'value'; - } - - // handle a not given attribute or null value - if (!isset($values[$property])) { - if ($type['required']) { - throw AnnotationException::requiredError($property, $originalName, $this->context, 'a(n) '.$type['value']); - } - - continue; - } - - if ($type['type'] === 'array') { - // handle the case of a single value - if ( ! is_array($values[$property])) { - $values[$property] = [$values[$property]]; - } - - // checks if the attribute has array type declaration, such as "array" - if (isset($type['array_type'])) { - foreach ($values[$property] as $item) { - if (gettype($item) !== $type['array_type'] && !$item instanceof $type['array_type']) { - throw AnnotationException::attributeTypeError($property, $originalName, $this->context, 'either a(n) '.$type['array_type'].', or an array of '.$type['array_type'].'s', $item); - } - } - } - } elseif (gettype($values[$property]) !== $type['type'] && !$values[$property] instanceof $type['type']) { - throw AnnotationException::attributeTypeError($property, $originalName, $this->context, 'a(n) '.$type['value'], $values[$property]); - } - } - - // check if the annotation expects values via the constructor, - // or directly injected into public properties - if (self::$annotationMetadata[$name]['has_constructor'] === true) { - return new $name($values); - } - - $instance = new $name(); - - foreach ($values as $property => $value) { - if (!isset(self::$annotationMetadata[$name]['properties'][$property])) { - if ('value' !== $property) { - throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not have a property named "%s". Available properties: %s', $originalName, $this->context, $property, implode(', ', self::$annotationMetadata[$name]['properties']))); - } - - // handle the case if the property has no annotations - if ( ! $property = self::$annotationMetadata[$name]['default_property']) { - throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not accept any values, but got %s.', $originalName, $this->context, json_encode($values))); - } - } - - $instance->{$property} = $value; - } - - return $instance; - } - - /** - * MethodCall ::= ["(" [Values] ")"] - * - * @return array - */ - private function MethodCall() - { - $values = []; - - if ( ! $this->lexer->isNextToken(DocLexer::T_OPEN_PARENTHESIS)) { - return $values; - } - - $this->match(DocLexer::T_OPEN_PARENTHESIS); - - if ( ! $this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) { - $values = $this->Values(); - } - - $this->match(DocLexer::T_CLOSE_PARENTHESIS); - - return $values; - } - - /** - * Values ::= Array | Value {"," Value}* [","] - * - * @return array - */ - private function Values() - { - $values = [$this->Value()]; - - while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { - $this->match(DocLexer::T_COMMA); - - if ($this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) { - break; - } - - $token = $this->lexer->lookahead; - $value = $this->Value(); - - if ( ! is_object($value) && ! is_array($value)) { - $this->syntaxError('Value', $token); - } - - $values[] = $value; - } - - foreach ($values as $k => $value) { - if (is_object($value) && $value instanceof \stdClass) { - $values[$value->name] = $value->value; - } else if ( ! isset($values['value'])){ - $values['value'] = $value; - } else { - if ( ! is_array($values['value'])) { - $values['value'] = [$values['value']]; - } - - $values['value'][] = $value; - } - - unset($values[$k]); - } - - return $values; - } - - /** - * Constant ::= integer | string | float | boolean - * - * @return mixed - * - * @throws AnnotationException - */ - private function Constant() - { - $identifier = $this->Identifier(); - - if ( ! defined($identifier) && false !== strpos($identifier, '::') && '\\' !== $identifier[0]) { - list($className, $const) = explode('::', $identifier); - - $pos = strpos($className, '\\'); - $alias = (false === $pos) ? $className : substr($className, 0, $pos); - $found = false; - $loweredAlias = strtolower($alias); - - switch (true) { - case !empty ($this->namespaces): - foreach ($this->namespaces as $ns) { - if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) { - $className = $ns.'\\'.$className; - $found = true; - break; - } - } - break; - - case isset($this->imports[$loweredAlias]): - $found = true; - $className = (false !== $pos) - ? $this->imports[$loweredAlias] . substr($className, $pos) - : $this->imports[$loweredAlias]; - break; - - default: - if(isset($this->imports['__NAMESPACE__'])) { - $ns = $this->imports['__NAMESPACE__']; - - if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) { - $className = $ns.'\\'.$className; - $found = true; - } - } - break; - } - - if ($found) { - $identifier = $className . '::' . $const; - } - } - - // checks if identifier ends with ::class, \strlen('::class') === 7 - $classPos = stripos($identifier, '::class'); - if ($classPos === strlen($identifier) - 7) { - return substr($identifier, 0, $classPos); - } - - if (!defined($identifier)) { - throw AnnotationException::semanticalErrorConstants($identifier, $this->context); - } - - return constant($identifier); - } - - /** - * Identifier ::= string - * - * @return string - */ - private function Identifier() - { - // check if we have an annotation - if ( ! $this->lexer->isNextTokenAny(self::$classIdentifiers)) { - $this->syntaxError('namespace separator or identifier'); - } - - $this->lexer->moveNext(); - - $className = $this->lexer->token['value']; - - while ( - null !== $this->lexer->lookahead && - $this->lexer->lookahead['position'] === ($this->lexer->token['position'] + strlen($this->lexer->token['value'])) && - $this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR) - ) { - $this->match(DocLexer::T_NAMESPACE_SEPARATOR); - $this->matchAny(self::$classIdentifiers); - - $className .= '\\' . $this->lexer->token['value']; - } - - return $className; - } - - /** - * Value ::= PlainValue | FieldAssignment - * - * @return mixed - */ - private function Value() - { - $peek = $this->lexer->glimpse(); - - if (DocLexer::T_EQUALS === $peek['type']) { - return $this->FieldAssignment(); - } - - return $this->PlainValue(); - } - - /** - * PlainValue ::= integer | string | float | boolean | Array | Annotation - * - * @return mixed - */ - private function PlainValue() - { - if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) { - return $this->Arrayx(); - } - - if ($this->lexer->isNextToken(DocLexer::T_AT)) { - return $this->Annotation(); - } - - if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { - return $this->Constant(); - } - - switch ($this->lexer->lookahead['type']) { - case DocLexer::T_STRING: - $this->match(DocLexer::T_STRING); - return $this->lexer->token['value']; - - case DocLexer::T_INTEGER: - $this->match(DocLexer::T_INTEGER); - return (int)$this->lexer->token['value']; - - case DocLexer::T_FLOAT: - $this->match(DocLexer::T_FLOAT); - return (float)$this->lexer->token['value']; - - case DocLexer::T_TRUE: - $this->match(DocLexer::T_TRUE); - return true; - - case DocLexer::T_FALSE: - $this->match(DocLexer::T_FALSE); - return false; - - case DocLexer::T_NULL: - $this->match(DocLexer::T_NULL); - return null; - - default: - $this->syntaxError('PlainValue'); - } - } - - /** - * FieldAssignment ::= FieldName "=" PlainValue - * FieldName ::= identifier - * - * @return \stdClass - */ - private function FieldAssignment() - { - $this->match(DocLexer::T_IDENTIFIER); - $fieldName = $this->lexer->token['value']; - - $this->match(DocLexer::T_EQUALS); - - $item = new \stdClass(); - $item->name = $fieldName; - $item->value = $this->PlainValue(); - - return $item; - } - - /** - * Array ::= "{" ArrayEntry {"," ArrayEntry}* [","] "}" - * - * @return array - */ - private function Arrayx() - { - $array = $values = []; - - $this->match(DocLexer::T_OPEN_CURLY_BRACES); - - // If the array is empty, stop parsing and return. - if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) { - $this->match(DocLexer::T_CLOSE_CURLY_BRACES); - - return $array; - } - - $values[] = $this->ArrayEntry(); - - while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { - $this->match(DocLexer::T_COMMA); - - // optional trailing comma - if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) { - break; - } - - $values[] = $this->ArrayEntry(); - } - - $this->match(DocLexer::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 | Constant - * Key ::= string | integer | Constant - * - * @return array - */ - private function ArrayEntry() - { - $peek = $this->lexer->glimpse(); - - if (DocLexer::T_EQUALS === $peek['type'] - || DocLexer::T_COLON === $peek['type']) { - - if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { - $key = $this->Constant(); - } else { - $this->matchAny([DocLexer::T_INTEGER, DocLexer::T_STRING]); - $key = $this->lexer->token['value']; - } - - $this->matchAny([DocLexer::T_EQUALS, DocLexer::T_COLON]); - - return [$key, $this->PlainValue()]; - } - - return [null, $this->Value()]; - } - - /** - * Checks whether the given $name matches any ignored annotation name or namespace - * - * @param string $name - * - * @return bool - */ - private function isIgnoredAnnotation($name) - { - if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) { - return true; - } - - foreach (array_keys($this->ignoredAnnotationNamespaces) as $ignoredAnnotationNamespace) { - $ignoredAnnotationNamespace = rtrim($ignoredAnnotationNamespace, '\\') . '\\'; - - if (0 === stripos(rtrim($name, '\\') . '\\', $ignoredAnnotationNamespace)) { - return true; - } - } - - return false; - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php deleted file mode 100644 index 40141af..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php +++ /dev/null @@ -1,290 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations; - -/** - * File cache reader for annotations. - * - * @author Johannes M. Schmitt - * @author Benjamin Eberlei - * - * @deprecated the FileCacheReader is deprecated and will be removed - * in version 2.0.0 of doctrine/annotations. Please use the - * {@see \Doctrine\Common\Annotations\CachedReader} instead. - */ -class FileCacheReader implements Reader -{ - /** - * @var Reader - */ - private $reader; - - /** - * @var string - */ - private $dir; - - /** - * @var bool - */ - private $debug; - - /** - * @var array - */ - private $loadedAnnotations = []; - - /** - * @var array - */ - private $classNameHashes = []; - - /** - * @var int - */ - private $umask; - - /** - * Constructor. - * - * @param Reader $reader - * @param string $cacheDir - * @param boolean $debug - * - * @throws \InvalidArgumentException - */ - public function __construct(Reader $reader, $cacheDir, $debug = false, $umask = 0002) - { - if ( ! is_int($umask)) { - throw new \InvalidArgumentException(sprintf( - 'The parameter umask must be an integer, was: %s', - gettype($umask) - )); - } - - $this->reader = $reader; - $this->umask = $umask; - - if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777 & (~$this->umask), true)) { - throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $cacheDir)); - } - - $this->dir = rtrim($cacheDir, '\\/'); - $this->debug = $debug; - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotations(\ReflectionClass $class) - { - if ( ! isset($this->classNameHashes[$class->name])) { - $this->classNameHashes[$class->name] = sha1($class->name); - } - $key = $this->classNameHashes[$class->name]; - - if (isset($this->loadedAnnotations[$key])) { - return $this->loadedAnnotations[$key]; - } - - $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; - if (!is_file($path)) { - $annot = $this->reader->getClassAnnotations($class); - $this->saveCacheFile($path, $annot); - return $this->loadedAnnotations[$key] = $annot; - } - - if ($this->debug - && (false !== $filename = $class->getFileName()) - && filemtime($path) < filemtime($filename)) { - @unlink($path); - - $annot = $this->reader->getClassAnnotations($class); - $this->saveCacheFile($path, $annot); - return $this->loadedAnnotations[$key] = $annot; - } - - return $this->loadedAnnotations[$key] = include $path; - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotations(\ReflectionProperty $property) - { - $class = $property->getDeclaringClass(); - if ( ! isset($this->classNameHashes[$class->name])) { - $this->classNameHashes[$class->name] = sha1($class->name); - } - $key = $this->classNameHashes[$class->name].'$'.$property->getName(); - - if (isset($this->loadedAnnotations[$key])) { - return $this->loadedAnnotations[$key]; - } - - $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; - if (!is_file($path)) { - $annot = $this->reader->getPropertyAnnotations($property); - $this->saveCacheFile($path, $annot); - return $this->loadedAnnotations[$key] = $annot; - } - - if ($this->debug - && (false !== $filename = $class->getFilename()) - && filemtime($path) < filemtime($filename)) { - @unlink($path); - - $annot = $this->reader->getPropertyAnnotations($property); - $this->saveCacheFile($path, $annot); - return $this->loadedAnnotations[$key] = $annot; - } - - return $this->loadedAnnotations[$key] = include $path; - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotations(\ReflectionMethod $method) - { - $class = $method->getDeclaringClass(); - if ( ! isset($this->classNameHashes[$class->name])) { - $this->classNameHashes[$class->name] = sha1($class->name); - } - $key = $this->classNameHashes[$class->name].'#'.$method->getName(); - - if (isset($this->loadedAnnotations[$key])) { - return $this->loadedAnnotations[$key]; - } - - $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; - if (!is_file($path)) { - $annot = $this->reader->getMethodAnnotations($method); - $this->saveCacheFile($path, $annot); - return $this->loadedAnnotations[$key] = $annot; - } - - if ($this->debug - && (false !== $filename = $class->getFilename()) - && filemtime($path) < filemtime($filename)) { - @unlink($path); - - $annot = $this->reader->getMethodAnnotations($method); - $this->saveCacheFile($path, $annot); - return $this->loadedAnnotations[$key] = $annot; - } - - return $this->loadedAnnotations[$key] = include $path; - } - - /** - * Saves the cache file. - * - * @param string $path - * @param mixed $data - * - * @return void - */ - private function saveCacheFile($path, $data) - { - if (!is_writable($this->dir)) { - throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable. Both, the webserver and the console user need access. You can manage access rights for multiple users with "chmod +a". If your system does not support this, check out the acl package.', $this->dir)); - } - - $tempfile = tempnam($this->dir, uniqid('', true)); - - if (false === $tempfile) { - throw new \RuntimeException(sprintf('Unable to create tempfile in directory: %s', $this->dir)); - } - - @chmod($tempfile, 0666 & (~$this->umask)); - - $written = file_put_contents($tempfile, 'umask)); - - if (false === rename($tempfile, $path)) { - @unlink($tempfile); - throw new \RuntimeException(sprintf('Unable to rename %s to %s', $tempfile, $path)); - } - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotation(\ReflectionClass $class, $annotationName) - { - $annotations = $this->getClassAnnotations($class); - - foreach ($annotations as $annotation) { - if ($annotation instanceof $annotationName) { - return $annotation; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) - { - $annotations = $this->getMethodAnnotations($method); - - foreach ($annotations as $annotation) { - if ($annotation instanceof $annotationName) { - return $annotation; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) - { - $annotations = $this->getPropertyAnnotations($property); - - foreach ($annotations as $annotation) { - if ($annotation instanceof $annotationName) { - return $annotation; - } - } - - return null; - } - - /** - * Clears loaded annotations. - * - * @return void - */ - public function clearLoadedAnnotations() - { - $this->loadedAnnotations = []; - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php deleted file mode 100644 index 4e8c3c8..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php +++ /dev/null @@ -1,119 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations; - -/** - * Allows the reader to be used in-place of Doctrine's reader. - * - * @author Johannes M. Schmitt - */ -class IndexedReader implements Reader -{ - /** - * @var Reader - */ - private $delegate; - - /** - * Constructor. - * - * @param Reader $reader - */ - public function __construct(Reader $reader) - { - $this->delegate = $reader; - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotations(\ReflectionClass $class) - { - $annotations = []; - foreach ($this->delegate->getClassAnnotations($class) as $annot) { - $annotations[get_class($annot)] = $annot; - } - - return $annotations; - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotation(\ReflectionClass $class, $annotation) - { - return $this->delegate->getClassAnnotation($class, $annotation); - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotations(\ReflectionMethod $method) - { - $annotations = []; - foreach ($this->delegate->getMethodAnnotations($method) as $annot) { - $annotations[get_class($annot)] = $annot; - } - - return $annotations; - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotation(\ReflectionMethod $method, $annotation) - { - return $this->delegate->getMethodAnnotation($method, $annotation); - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotations(\ReflectionProperty $property) - { - $annotations = []; - foreach ($this->delegate->getPropertyAnnotations($property) as $annot) { - $annotations[get_class($annot)] = $annot; - } - - return $annotations; - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotation(\ReflectionProperty $property, $annotation) - { - return $this->delegate->getPropertyAnnotation($property, $annotation); - } - - /** - * Proxies all methods to the delegate. - * - * @param string $method - * @param array $args - * - * @return mixed - */ - public function __call($method, $args) - { - return call_user_func_array([$this->delegate, $method], $args); - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php deleted file mode 100644 index ec87181..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php +++ /dev/null @@ -1,91 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations; - -use SplFileObject; - -/** - * Parses a file for namespaces/use/class declarations. - * - * @author Fabien Potencier - * @author Christian Kaps - */ -final class PhpParser -{ - /** - * Parses a class. - * - * @param \ReflectionClass $class A ReflectionClass object. - * - * @return array A list with use statements in the form (Alias => FQN). - */ - public function parseClass(\ReflectionClass $class) - { - if (method_exists($class, 'getUseStatements')) { - return $class->getUseStatements(); - } - - if (false === $filename = $class->getFileName()) { - return []; - } - - $content = $this->getFileContent($filename, $class->getStartLine()); - - if (null === $content) { - return []; - } - - $namespace = preg_quote($class->getNamespaceName()); - $content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content); - $tokenizer = new TokenParser('parseUseStatements($class->getNamespaceName()); - - return $statements; - } - - /** - * Gets the content of the file right up to the given line number. - * - * @param string $filename The name of the file to load. - * @param integer $lineNumber The number of lines to read from file. - * - * @return string|null The content of the file or null if the file does not exist. - */ - private function getFileContent($filename, $lineNumber) - { - if ( ! is_file($filename)) { - return null; - } - - $content = ''; - $lineCnt = 0; - $file = new SplFileObject($filename); - while (!$file->eof()) { - if ($lineCnt++ == $lineNumber) { - break; - } - - $content .= $file->fgets(); - } - - return $content; - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php deleted file mode 100644 index 4774f87..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php +++ /dev/null @@ -1,89 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations; - -/** - * Interface for annotation readers. - * - * @author Johannes M. Schmitt - */ -interface Reader -{ - /** - * Gets the annotations applied to a class. - * - * @param \ReflectionClass $class The ReflectionClass of the class from which - * the class annotations should be read. - * - * @return array An array of Annotations. - */ - function getClassAnnotations(\ReflectionClass $class); - - /** - * Gets a class annotation. - * - * @param \ReflectionClass $class The ReflectionClass of the class from which - * the class annotations should be read. - * @param string $annotationName The name of the annotation. - * - * @return object|null The Annotation or NULL, if the requested annotation does not exist. - */ - function getClassAnnotation(\ReflectionClass $class, $annotationName); - - /** - * Gets the annotations applied to a method. - * - * @param \ReflectionMethod $method The ReflectionMethod of the method from which - * the annotations should be read. - * - * @return array An array of Annotations. - */ - function getMethodAnnotations(\ReflectionMethod $method); - - /** - * Gets a method annotation. - * - * @param \ReflectionMethod $method The ReflectionMethod to read the annotations from. - * @param string $annotationName The name of the annotation. - * - * @return object|null The Annotation or NULL, if the requested annotation does not exist. - */ - function getMethodAnnotation(\ReflectionMethod $method, $annotationName); - - /** - * Gets the annotations applied to a property. - * - * @param \ReflectionProperty $property The ReflectionProperty of the property - * from which the annotations should be read. - * - * @return array An array of Annotations. - */ - function getPropertyAnnotations(\ReflectionProperty $property); - - /** - * Gets a property annotation. - * - * @param \ReflectionProperty $property The ReflectionProperty to read the annotations from. - * @param string $annotationName The name of the annotation. - * - * @return object|null The Annotation or NULL, if the requested annotation does not exist. - */ - function getPropertyAnnotation(\ReflectionProperty $property, $annotationName); -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php deleted file mode 100644 index d4757ee..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php +++ /dev/null @@ -1,127 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations; - -/** - * Simple Annotation Reader. - * - * This annotation reader is intended to be used in projects where you have - * full-control over all annotations that are available. - * - * @since 2.2 - * @author Johannes M. Schmitt - * @author Fabio B. Silva - */ -class SimpleAnnotationReader implements Reader -{ - /** - * @var DocParser - */ - private $parser; - - /** - * Constructor. - * - * Initializes a new SimpleAnnotationReader. - */ - public function __construct() - { - $this->parser = new DocParser(); - $this->parser->setIgnoreNotImportedAnnotations(true); - } - - /** - * Adds a namespace in which we will look for annotations. - * - * @param string $namespace - * - * @return void - */ - public function addNamespace($namespace) - { - $this->parser->addNamespace($namespace); - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotations(\ReflectionClass $class) - { - return $this->parser->parse($class->getDocComment(), 'class '.$class->getName()); - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotations(\ReflectionMethod $method) - { - return $this->parser->parse($method->getDocComment(), 'method '.$method->getDeclaringClass()->name.'::'.$method->getName().'()'); - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotations(\ReflectionProperty $property) - { - return $this->parser->parse($property->getDocComment(), 'property '.$property->getDeclaringClass()->name.'::$'.$property->getName()); - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotation(\ReflectionClass $class, $annotationName) - { - foreach ($this->getClassAnnotations($class) as $annot) { - if ($annot instanceof $annotationName) { - return $annot; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) - { - foreach ($this->getMethodAnnotations($method) as $annot) { - if ($annot instanceof $annotationName) { - return $annot; - } - } - - return null; - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) - { - foreach ($this->getPropertyAnnotations($property) as $annot) { - if ($annot instanceof $annotationName) { - return $annot; - } - } - - return null; - } -} diff --git a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php b/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php deleted file mode 100644 index 03d9320..0000000 --- a/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php +++ /dev/null @@ -1,194 +0,0 @@ -. - */ - -namespace Doctrine\Common\Annotations; - -/** - * Parses a file for namespaces/use/class declarations. - * - * @author Fabien Potencier - * @author Christian Kaps - */ -class TokenParser -{ - /** - * The token list. - * - * @var array - */ - private $tokens; - - /** - * The number of tokens. - * - * @var int - */ - private $numTokens; - - /** - * The current array pointer. - * - * @var int - */ - private $pointer = 0; - - /** - * @param string $contents - */ - public function __construct($contents) - { - $this->tokens = token_get_all($contents); - - // The PHP parser sets internal compiler globals for certain things. Annoyingly, the last docblock comment it - // saw gets stored in doc_comment. When it comes to compile the next thing to be include()d this stored - // doc_comment becomes owned by the first thing the compiler sees in the file that it considers might have a - // docblock. If the first thing in the file is a class without a doc block this would cause calls to - // getDocBlock() on said class to return our long lost doc_comment. Argh. - // To workaround, cause the parser to parse an empty docblock. Sure getDocBlock() will return this, but at least - // it's harmless to us. - token_get_all("numTokens = count($this->tokens); - } - - /** - * Gets the next non whitespace and non comment token. - * - * @param boolean $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped. - * If FALSE then only whitespace and normal comments are skipped. - * - * @return array|null The token if exists, null otherwise. - */ - public function next($docCommentIsComment = TRUE) - { - for ($i = $this->pointer; $i < $this->numTokens; $i++) { - $this->pointer++; - if ($this->tokens[$i][0] === T_WHITESPACE || - $this->tokens[$i][0] === T_COMMENT || - ($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT)) { - - continue; - } - - return $this->tokens[$i]; - } - - return null; - } - - /** - * Parses a single use statement. - * - * @return array A list with all found class names for a use statement. - */ - public function parseUseStatement() - { - - $groupRoot = ''; - $class = ''; - $alias = ''; - $statements = []; - $explicitAlias = false; - while (($token = $this->next())) { - $isNameToken = $token[0] === T_STRING || $token[0] === T_NS_SEPARATOR; - if (!$explicitAlias && $isNameToken) { - $class .= $token[1]; - $alias = $token[1]; - } else if ($explicitAlias && $isNameToken) { - $alias .= $token[1]; - } else if ($token[0] === T_AS) { - $explicitAlias = true; - $alias = ''; - } else if ($token === ',') { - $statements[strtolower($alias)] = $groupRoot . $class; - $class = ''; - $alias = ''; - $explicitAlias = false; - } else if ($token === ';') { - $statements[strtolower($alias)] = $groupRoot . $class; - break; - } else if ($token === '{' ) { - $groupRoot = $class; - $class = ''; - } else if ($token === '}' ) { - continue; - } else { - break; - } - } - - return $statements; - } - - /** - * Gets all use statements. - * - * @param string $namespaceName The namespace name of the reflected class. - * - * @return array A list with all found use statements. - */ - public function parseUseStatements($namespaceName) - { - $statements = []; - while (($token = $this->next())) { - if ($token[0] === T_USE) { - $statements = array_merge($statements, $this->parseUseStatement()); - continue; - } - if ($token[0] !== T_NAMESPACE || $this->parseNamespace() != $namespaceName) { - continue; - } - - // Get fresh array for new namespace. This is to prevent the parser to collect the use statements - // for a previous namespace with the same name. This is the case if a namespace is defined twice - // or if a namespace with the same name is commented out. - $statements = []; - } - - return $statements; - } - - /** - * Gets the namespace. - * - * @return string The found namespace. - */ - public function parseNamespace() - { - $name = ''; - while (($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR)) { - $name .= $token[1]; - } - - return $name; - } - - /** - * Gets the class name. - * - * @return string The found class name. - */ - public function parseClass() - { - // Namespaces and class names are tokenized the same: T_STRINGs - // separated by T_NS_SEPARATOR so we can use one function to provide - // both. - return $this->parseNamespace(); - } -} diff --git a/vendor/doctrine/annotations/phpbench.json.dist b/vendor/doctrine/annotations/phpbench.json.dist deleted file mode 100644 index 35edde9..0000000 --- a/vendor/doctrine/annotations/phpbench.json.dist +++ /dev/null @@ -1,4 +0,0 @@ -{ - "bootstrap": "tests/Doctrine/Performance/Common/bootstrap.php", - "path": "tests/Doctrine/Performance/Common/Annotations" -} diff --git a/vendor/doctrine/annotations/phpstan.neon b/vendor/doctrine/annotations/phpstan.neon deleted file mode 100644 index bac7f83..0000000 --- a/vendor/doctrine/annotations/phpstan.neon +++ /dev/null @@ -1,14 +0,0 @@ -parameters: - autoload_files: - - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Annotations/DocParserTest.php - excludes_analyse: - - %currentWorkingDirectory%/tests/*/Fixtures/* - - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Annotations/ReservedKeywordsClasses.php - - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM58Entity.php - - %currentWorkingDirectory%/tests/Doctrine/Tests/DoctrineTestCase.php - polluteScopeWithLoopInitialAssignments: true - ignoreErrors: - - '#Class Doctrine_Tests_Common_Annotations_Fixtures_ClassNoNamespaceNoComment not found#' - - '#Instantiated class Doctrine_Tests_Common_Annotations_Fixtures_ClassNoNamespaceNoComment not found#' - - '#Property Doctrine\\Tests\\Common\\Annotations\\DummyClassNonAnnotationProblem::\$foo has unknown class#' - - '#Call to an undefined method ReflectionClass::getUseStatements\(\)#' diff --git a/vendor/doctrine/cache/LICENSE b/vendor/doctrine/cache/LICENSE deleted file mode 100644 index 8c38cc1..0000000 --- a/vendor/doctrine/cache/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006-2015 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/doctrine/cache/README.md b/vendor/doctrine/cache/README.md deleted file mode 100644 index bf9a7fe..0000000 --- a/vendor/doctrine/cache/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Doctrine Cache - -[![Build Status](https://img.shields.io/travis/doctrine/cache/master.svg?style=flat-square)](http://travis-ci.org/doctrine/cache) -[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/doctrine/cache/master.svg?style=flat-square)](https://scrutinizer-ci.com/g/doctrine/cache/?branch=master) -[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/doctrine/cache/master.svg?style=flat-square)](https://scrutinizer-ci.com/g/doctrine/cache/?branch=master) - -[![Latest Stable Version](https://img.shields.io/packagist/v/doctrine/cache.svg?style=flat-square)](https://packagist.org/packages/doctrine/cache) -[![Total Downloads](https://img.shields.io/packagist/dt/doctrine/cache.svg?style=flat-square)](https://packagist.org/packages/doctrine/cache) - -Cache component extracted from the Doctrine Common project. [Documentation](https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/caching.html) diff --git a/vendor/doctrine/cache/UPGRADE.md b/vendor/doctrine/cache/UPGRADE.md deleted file mode 100644 index e1f8a50..0000000 --- a/vendor/doctrine/cache/UPGRADE.md +++ /dev/null @@ -1,16 +0,0 @@ -# Upgrade to 1.4 - -## Minor BC Break: `Doctrine\Common\Cache\FileCache#$extension` is now `private`. - -If you need to override the value of `Doctrine\Common\Cache\FileCache#$extension`, then use the -second parameter of `Doctrine\Common\Cache\FileCache#__construct()` instead of overriding -the property in your own implementation. - -## Minor BC Break: file based caches paths changed - -`Doctrine\Common\Cache\FileCache`, `Doctrine\Common\Cache\PhpFileCache` and -`Doctrine\Common\Cache\FilesystemCache` are using a different cache paths structure. - -If you rely on warmed up caches for deployments, consider that caches generated -with `doctrine/cache` `<1.4` are not compatible with the new directory structure, -and will be ignored. diff --git a/vendor/doctrine/cache/composer.json b/vendor/doctrine/cache/composer.json deleted file mode 100644 index d72c1e0..0000000 --- a/vendor/doctrine/cache/composer.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "doctrine/cache", - "type": "library", - "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", - "keywords": [ - "php", - "cache", - "caching", - "abstraction", - "redis", - "memcached", - "couchdb", - "xcache", - "apcu" - ], - "homepage": "https://www.doctrine-project.org/projects/cache.html", - "license": "MIT", - "authors": [ - {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, - {"name": "Roman Borschel", "email": "roman@code-factory.org"}, - {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, - {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, - {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} - ], - "require": { - "php": "~7.1" - }, - "require-dev": { - "alcaeus/mongo-php-adapter": "^1.1", - "mongodb/mongodb": "^1.1", - "phpunit/phpunit": "^7.0", - "predis/predis": "~1.0", - "doctrine/coding-standard": "^6.0" - }, - "suggest": { - "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "autoload": { - "psr-4": { "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" } - }, - "autoload-dev": { - "psr-4": { "Doctrine\\Tests\\": "tests/Doctrine/Tests" } - }, - "extra": { - "branch-alias": { - "dev-master": "1.9.x-dev" - } - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcCache.php deleted file mode 100644 index 138d49a..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcCache.php +++ /dev/null @@ -1,105 +0,0 @@ -= 50500) { - $info['num_hits'] = $info['num_hits'] ?? $info['nhits']; - $info['num_misses'] = $info['num_misses'] ?? $info['nmisses']; - $info['start_time'] = $info['start_time'] ?? $info['stime']; - } - - return [ - Cache::STATS_HITS => $info['num_hits'], - Cache::STATS_MISSES => $info['num_misses'], - Cache::STATS_UPTIME => $info['start_time'], - Cache::STATS_MEMORY_USAGE => $info['mem_size'], - Cache::STATS_MEMORY_AVAILABLE => $sma['avail_mem'], - ]; - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcuCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcuCache.php deleted file mode 100644 index a725213..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ApcuCache.php +++ /dev/null @@ -1,106 +0,0 @@ - $info['num_hits'], - Cache::STATS_MISSES => $info['num_misses'], - Cache::STATS_UPTIME => $info['start_time'], - Cache::STATS_MEMORY_USAGE => $info['mem_size'], - Cache::STATS_MEMORY_AVAILABLE => $sma['avail_mem'], - ]; - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ArrayCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ArrayCache.php deleted file mode 100644 index 1beb709..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ArrayCache.php +++ /dev/null @@ -1,113 +0,0 @@ -upTime = time(); - } - - /** - * {@inheritdoc} - */ - protected function doFetch($id) - { - if (! $this->doContains($id)) { - $this->missesCount += 1; - - return false; - } - - $this->hitsCount += 1; - - return $this->data[$id][0]; - } - - /** - * {@inheritdoc} - */ - protected function doContains($id) - { - if (! isset($this->data[$id])) { - return false; - } - - $expiration = $this->data[$id][1]; - - if ($expiration && $expiration < time()) { - $this->doDelete($id); - - return false; - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - $this->data[$id] = [$data, $lifeTime ? time() + $lifeTime : false]; - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doDelete($id) - { - unset($this->data[$id]); - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doFlush() - { - $this->data = []; - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - return [ - Cache::STATS_HITS => $this->hitsCount, - Cache::STATS_MISSES => $this->missesCount, - Cache::STATS_UPTIME => $this->upTime, - Cache::STATS_MEMORY_USAGE => null, - Cache::STATS_MEMORY_AVAILABLE => null, - ]; - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php deleted file mode 100644 index 4569744..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Cache.php +++ /dev/null @@ -1,90 +0,0 @@ -hits - * Number of keys that have been requested and found present. - * - * - misses - * Number of items that have been requested and not found. - * - * - uptime - * Time that the server is running. - * - * - memory_usage - * Memory used by this server to store items. - * - * - memory_available - * Memory allowed to use for storage. - * - * @return array|null An associative array with server's statistics if available, NULL otherwise. - */ - public function getStats(); -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php deleted file mode 100644 index 43d414f..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CacheProvider.php +++ /dev/null @@ -1,325 +0,0 @@ -namespace = (string) $namespace; - $this->namespaceVersion = null; - } - - /** - * Retrieves the namespace that prefixes all cache ids. - * - * @return string - */ - public function getNamespace() - { - return $this->namespace; - } - - /** - * {@inheritdoc} - */ - public function fetch($id) - { - return $this->doFetch($this->getNamespacedId($id)); - } - - /** - * {@inheritdoc} - */ - public function fetchMultiple(array $keys) - { - if (empty($keys)) { - return []; - } - - // note: the array_combine() is in place to keep an association between our $keys and the $namespacedKeys - $namespacedKeys = array_combine($keys, array_map([$this, 'getNamespacedId'], $keys)); - $items = $this->doFetchMultiple($namespacedKeys); - $foundItems = []; - - // no internal array function supports this sort of mapping: needs to be iterative - // this filters and combines keys in one pass - foreach ($namespacedKeys as $requestedKey => $namespacedKey) { - if (! isset($items[$namespacedKey]) && ! array_key_exists($namespacedKey, $items)) { - continue; - } - - $foundItems[$requestedKey] = $items[$namespacedKey]; - } - - return $foundItems; - } - - /** - * {@inheritdoc} - */ - public function saveMultiple(array $keysAndValues, $lifetime = 0) - { - $namespacedKeysAndValues = []; - foreach ($keysAndValues as $key => $value) { - $namespacedKeysAndValues[$this->getNamespacedId($key)] = $value; - } - - return $this->doSaveMultiple($namespacedKeysAndValues, $lifetime); - } - - /** - * {@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 deleteMultiple(array $keys) - { - return $this->doDeleteMultiple(array_map([$this, 'getNamespacedId'], $keys)); - } - - /** - * {@inheritdoc} - */ - public function delete($id) - { - return $this->doDelete($this->getNamespacedId($id)); - } - - /** - * {@inheritdoc} - */ - public function getStats() - { - return $this->doGetStats(); - } - - /** - * {@inheritDoc} - */ - public function flushAll() - { - return $this->doFlush(); - } - - /** - * {@inheritDoc} - */ - public function deleteAll() - { - $namespaceCacheKey = $this->getNamespaceCacheKey(); - $namespaceVersion = $this->getNamespaceVersion() + 1; - - if ($this->doSave($namespaceCacheKey, $namespaceVersion)) { - $this->namespaceVersion = $namespaceVersion; - - return true; - } - - return false; - } - - /** - * Prefixes the passed id with the configured namespace value. - * - * @param string $id The id to namespace. - * - * @return string The namespaced id. - */ - private function getNamespacedId(string $id) : string - { - $namespaceVersion = $this->getNamespaceVersion(); - - return sprintf('%s[%s][%s]', $this->namespace, $id, $namespaceVersion); - } - - /** - * Returns the namespace cache key. - */ - private function getNamespaceCacheKey() : string - { - return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace); - } - - /** - * Returns the namespace version. - */ - private function getNamespaceVersion() : int - { - if ($this->namespaceVersion !== null) { - return $this->namespaceVersion; - } - - $namespaceCacheKey = $this->getNamespaceCacheKey(); - $this->namespaceVersion = (int) $this->doFetch($namespaceCacheKey) ?: 1; - - return $this->namespaceVersion; - } - - /** - * Default implementation of doFetchMultiple. Each driver that supports multi-get should owerwrite it. - * - * @param array $keys Array of keys to retrieve from cache - * - * @return array Array of values retrieved for the given keys. - */ - protected function doFetchMultiple(array $keys) - { - $returnValues = []; - - foreach ($keys as $key) { - $item = $this->doFetch($key); - if ($item === false && ! $this->doContains($key)) { - continue; - } - - $returnValues[$key] = $item; - } - - return $returnValues; - } - - /** - * Fetches an entry from the cache. - * - * @param string $id The id of the cache entry to fetch. - * - * @return mixed|false The cached data or FALSE, if no cache entry exists for the given id. - */ - abstract protected function doFetch($id); - - /** - * Tests if an entry exists in the cache. - * - * @param string $id The cache id of the entry to check for. - * - * @return bool TRUE if a cache entry exists for the given cache id, FALSE otherwise. - */ - abstract protected function doContains($id); - - /** - * Default implementation of doSaveMultiple. Each driver that supports multi-put should override it. - * - * @param array $keysAndValues Array of keys and values to save in cache - * @param int $lifetime The lifetime. If != 0, sets a specific lifetime for these - * cache entries (0 => infinite lifeTime). - * - * @return bool TRUE if the operation was successful, FALSE if it wasn't. - */ - protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) - { - $success = true; - - foreach ($keysAndValues as $key => $value) { - if ($this->doSave($key, $value, $lifetime)) { - continue; - } - - $success = false; - } - - return $success; - } - - /** - * 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 bool TRUE if the entry was successfully stored in the cache, FALSE otherwise. - */ - abstract protected function doSave($id, $data, $lifeTime = 0); - - /** - * Default implementation of doDeleteMultiple. Each driver that supports multi-delete should override it. - * - * @param array $keys Array of keys to delete from cache - * - * @return bool TRUE if the operation was successful, FALSE if it wasn't - */ - protected function doDeleteMultiple(array $keys) - { - $success = true; - - foreach ($keys as $key) { - if ($this->doDelete($key)) { - continue; - } - - $success = false; - } - - return $success; - } - - /** - * Deletes a cache entry. - * - * @param string $id The cache id. - * - * @return bool TRUE if the cache entry was successfully deleted, FALSE otherwise. - */ - abstract protected function doDelete($id); - - /** - * Flushes all cache entries. - * - * @return bool TRUE if the cache entries were successfully flushed, FALSE otherwise. - */ - abstract protected function doFlush(); - - /** - * Retrieves cached information from the data store. - * - * @return array|null An associative array with server's statistics if available, NULL otherwise. - */ - abstract protected function doGetStats(); -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ChainCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ChainCache.php deleted file mode 100644 index e9762a2..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ChainCache.php +++ /dev/null @@ -1,187 +0,0 @@ -cacheProviders = $cacheProviders instanceof Traversable - ? iterator_to_array($cacheProviders, false) - : array_values($cacheProviders); - } - - /** - * {@inheritDoc} - */ - public function setNamespace($namespace) - { - parent::setNamespace($namespace); - - foreach ($this->cacheProviders as $cacheProvider) { - $cacheProvider->setNamespace($namespace); - } - } - - /** - * {@inheritDoc} - */ - protected function doFetch($id) - { - foreach ($this->cacheProviders as $key => $cacheProvider) { - if ($cacheProvider->doContains($id)) { - $value = $cacheProvider->doFetch($id); - - // We populate all the previous cache layers (that are assumed to be faster) - for ($subKey = $key - 1; $subKey >= 0; $subKey--) { - $this->cacheProviders[$subKey]->doSave($id, $value); - } - - return $value; - } - } - - return false; - } - - /** - * {@inheritdoc} - */ - protected function doFetchMultiple(array $keys) - { - /** @var CacheProvider[] $traversedProviders */ - $traversedProviders = []; - $keysCount = count($keys); - $fetchedValues = []; - - foreach ($this->cacheProviders as $key => $cacheProvider) { - $fetchedValues = $cacheProvider->doFetchMultiple($keys); - - // We populate all the previous cache layers (that are assumed to be faster) - if (count($fetchedValues) === $keysCount) { - foreach ($traversedProviders as $previousCacheProvider) { - $previousCacheProvider->doSaveMultiple($fetchedValues); - } - - return $fetchedValues; - } - - $traversedProviders[] = $cacheProvider; - } - - return $fetchedValues; - } - - /** - * {@inheritDoc} - */ - protected function doContains($id) - { - foreach ($this->cacheProviders as $cacheProvider) { - if ($cacheProvider->doContains($id)) { - return true; - } - } - - return false; - } - - /** - * {@inheritDoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - $stored = true; - - foreach ($this->cacheProviders as $cacheProvider) { - $stored = $cacheProvider->doSave($id, $data, $lifeTime) && $stored; - } - - return $stored; - } - - /** - * {@inheritdoc} - */ - protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) - { - $stored = true; - - foreach ($this->cacheProviders as $cacheProvider) { - $stored = $cacheProvider->doSaveMultiple($keysAndValues, $lifetime) && $stored; - } - - return $stored; - } - - /** - * {@inheritDoc} - */ - protected function doDelete($id) - { - $deleted = true; - - foreach ($this->cacheProviders as $cacheProvider) { - $deleted = $cacheProvider->doDelete($id) && $deleted; - } - - return $deleted; - } - - /** - * {@inheritdoc} - */ - protected function doDeleteMultiple(array $keys) - { - $deleted = true; - - foreach ($this->cacheProviders as $cacheProvider) { - $deleted = $cacheProvider->doDeleteMultiple($keys) && $deleted; - } - - return $deleted; - } - - /** - * {@inheritDoc} - */ - protected function doFlush() - { - $flushed = true; - - foreach ($this->cacheProviders as $cacheProvider) { - $flushed = $cacheProvider->doFlush() && $flushed; - } - - return $flushed; - } - - /** - * {@inheritDoc} - */ - protected function doGetStats() - { - // We return all the stats from all adapters - $stats = []; - - foreach ($this->cacheProviders as $cacheProvider) { - $stats[] = $cacheProvider->doGetStats(); - } - - return $stats; - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php deleted file mode 100644 index b94618e..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ClearableCache.php +++ /dev/null @@ -1,21 +0,0 @@ -bucket = $bucket; - } - - /** - * {@inheritdoc} - */ - protected function doFetch($id) - { - $id = $this->normalizeKey($id); - - try { - $document = $this->bucket->get($id); - } catch (Exception $e) { - return false; - } - - if ($document instanceof Document && $document->value !== false) { - return unserialize($document->value); - } - - return false; - } - - /** - * {@inheritdoc} - */ - protected function doContains($id) - { - $id = $this->normalizeKey($id); - - try { - $document = $this->bucket->get($id); - } catch (Exception $e) { - return false; - } - - if ($document instanceof Document) { - return ! $document->error; - } - - return false; - } - - /** - * {@inheritdoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - $id = $this->normalizeKey($id); - - $lifeTime = $this->normalizeExpiry($lifeTime); - - try { - $encoded = serialize($data); - - $document = $this->bucket->upsert($id, $encoded, [ - 'expiry' => (int) $lifeTime, - ]); - } catch (Exception $e) { - return false; - } - - if ($document instanceof Document) { - return ! $document->error; - } - - return false; - } - - /** - * {@inheritdoc} - */ - protected function doDelete($id) - { - $id = $this->normalizeKey($id); - - try { - $document = $this->bucket->remove($id); - } catch (Exception $e) { - return $e->getCode() === self::KEY_NOT_FOUND; - } - - if ($document instanceof Document) { - return ! $document->error; - } - - return false; - } - - /** - * {@inheritdoc} - */ - protected function doFlush() - { - $manager = $this->bucket->manager(); - - // Flush does not return with success or failure, and must be enabled per bucket on the server. - // Store a marker item so that we will know if it was successful. - $this->doSave(__METHOD__, true, 60); - - $manager->flush(); - - if ($this->doContains(__METHOD__)) { - $this->doDelete(__METHOD__); - - return false; - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - $manager = $this->bucket->manager(); - $stats = $manager->info(); - $nodes = $stats['nodes']; - $node = $nodes[0]; - $interestingStats = $node['interestingStats']; - - return [ - Cache::STATS_HITS => $interestingStats['get_hits'], - Cache::STATS_MISSES => $interestingStats['cmd_get'] - $interestingStats['get_hits'], - Cache::STATS_UPTIME => $node['uptime'], - Cache::STATS_MEMORY_USAGE => $interestingStats['mem_used'], - Cache::STATS_MEMORY_AVAILABLE => $node['memoryFree'], - ]; - } - - private function normalizeKey(string $id) : string - { - $normalized = substr($id, 0, self::MAX_KEY_LENGTH); - - if ($normalized === false) { - return $id; - } - - return $normalized; - } - - /** - * Expiry treated as a unix timestamp instead of an offset if expiry is greater than 30 days. - * - * @src https://developer.couchbase.com/documentation/server/4.1/developer-guide/expiry.html - */ - private function normalizeExpiry(int $expiry) : int - { - if ($expiry > self::THIRTY_DAYS_IN_SECONDS) { - return time() + $expiry; - } - - return $expiry; - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CouchbaseCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CouchbaseCache.php deleted file mode 100644 index 2c62c2e..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/CouchbaseCache.php +++ /dev/null @@ -1,105 +0,0 @@ -couchbase = $couchbase; - } - - /** - * Gets the Couchbase instance used by the cache. - * - * @return Couchbase|null - */ - public function getCouchbase() - { - return $this->couchbase; - } - - /** - * {@inheritdoc} - */ - protected function doFetch($id) - { - return $this->couchbase->get($id) ?: false; - } - - /** - * {@inheritdoc} - */ - protected function doContains($id) - { - return $this->couchbase->get($id) !== null; - } - - /** - * {@inheritdoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - if ($lifeTime > 30 * 24 * 3600) { - $lifeTime = time() + $lifeTime; - } - - return $this->couchbase->set($id, $data, (int) $lifeTime); - } - - /** - * {@inheritdoc} - */ - protected function doDelete($id) - { - return $this->couchbase->delete($id); - } - - /** - * {@inheritdoc} - */ - protected function doFlush() - { - return $this->couchbase->flush(); - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - $stats = $this->couchbase->getStats(); - $servers = $this->couchbase->getServers(); - $server = explode(':', $servers[0]); - $key = $server[0] . ':11210'; - $stats = $stats[$key]; - - return [ - Cache::STATS_HITS => $stats['get_hits'], - Cache::STATS_MISSES => $stats['get_misses'], - Cache::STATS_UPTIME => $stats['uptime'], - Cache::STATS_MEMORY_USAGE => $stats['bytes'], - Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'], - ]; - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ExtMongoDBCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ExtMongoDBCache.php deleted file mode 100644 index b06f862..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ExtMongoDBCache.php +++ /dev/null @@ -1,198 +0,0 @@ -collection = $collection->withOptions(['typeMap' => null]); - $this->database = new Database($collection->getManager(), $collection->getDatabaseName()); - } - - /** - * {@inheritdoc} - */ - protected function doFetch($id) - { - $document = $this->collection->findOne(['_id' => $id], [MongoDBCache::DATA_FIELD, MongoDBCache::EXPIRATION_FIELD]); - - if ($document === null) { - return false; - } - - if ($this->isExpired($document)) { - $this->createExpirationIndex(); - $this->doDelete($id); - - return false; - } - - return unserialize($document[MongoDBCache::DATA_FIELD]->getData()); - } - - /** - * {@inheritdoc} - */ - protected function doContains($id) - { - $document = $this->collection->findOne(['_id' => $id], [MongoDBCache::EXPIRATION_FIELD]); - - if ($document === null) { - return false; - } - - if ($this->isExpired($document)) { - $this->createExpirationIndex(); - $this->doDelete($id); - - return false; - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - try { - $this->collection->updateOne( - ['_id' => $id], - [ - '$set' => [ - MongoDBCache::EXPIRATION_FIELD => ($lifeTime > 0 ? new UTCDateTime((time() + $lifeTime) * 1000): null), - MongoDBCache::DATA_FIELD => new Binary(serialize($data), Binary::TYPE_GENERIC), - ], - ], - ['upsert' => true] - ); - } catch (Exception $e) { - return false; - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doDelete($id) - { - try { - $this->collection->deleteOne(['_id' => $id]); - } catch (Exception $e) { - return false; - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doFlush() - { - try { - // Use remove() in lieu of drop() to maintain any collection indexes - $this->collection->deleteMany([]); - } catch (Exception $e) { - return false; - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - $uptime = null; - $memoryUsage = null; - - try { - $serverStatus = $this->database->command([ - 'serverStatus' => 1, - 'locks' => 0, - 'metrics' => 0, - 'recordStats' => 0, - 'repl' => 0, - ])->toArray()[0]; - $uptime = $serverStatus['uptime'] ?? null; - } catch (Exception $e) { - } - - try { - $collStats = $this->database->command(['collStats' => $this->collection->getCollectionName()])->toArray()[0]; - $memoryUsage = $collStats['size'] ?? null; - } catch (Exception $e) { - } - - return [ - Cache::STATS_HITS => null, - Cache::STATS_MISSES => null, - Cache::STATS_UPTIME => $uptime, - Cache::STATS_MEMORY_USAGE => $memoryUsage, - Cache::STATS_MEMORY_AVAILABLE => null, - ]; - } - - /** - * Check if the document is expired. - */ - private function isExpired(BSONDocument $document) : bool - { - return isset($document[MongoDBCache::EXPIRATION_FIELD]) && - $document[MongoDBCache::EXPIRATION_FIELD] instanceof UTCDateTime && - $document[MongoDBCache::EXPIRATION_FIELD]->toDateTime() < new DateTime(); - } - - private function createExpirationIndex() : void - { - if ($this->expirationIndexCreated) { - return; - } - - $this->collection->createIndex([MongoDBCache::EXPIRATION_FIELD => 1], ['background' => true, 'expireAfterSeconds' => 0]); - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php deleted file mode 100644 index 4b48520..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FileCache.php +++ /dev/null @@ -1,281 +0,0 @@ -umask = $umask; - - if (! $this->createPathIfNeeded($directory)) { - throw new InvalidArgumentException(sprintf( - 'The directory "%s" does not exist and could not be created.', - $directory - )); - } - - if (! is_writable($directory)) { - throw new InvalidArgumentException(sprintf( - 'The directory "%s" is not writable.', - $directory - )); - } - - // YES, this needs to be *after* createPathIfNeeded() - $this->directory = realpath($directory); - $this->extension = (string) $extension; - - $this->directoryStringLength = strlen($this->directory); - $this->extensionStringLength = strlen($this->extension); - $this->isRunningOnWindows = defined('PHP_WINDOWS_VERSION_BUILD'); - } - - /** - * Gets the cache directory. - * - * @return string - */ - public function getDirectory() - { - return $this->directory; - } - - /** - * Gets the cache file extension. - * - * @return string - */ - public function getExtension() - { - return $this->extension; - } - - /** - * @param string $id - * - * @return string - */ - protected function getFilename($id) - { - $hash = hash('sha256', $id); - - // This ensures that the filename is unique and that there are no invalid chars in it. - if ($id === '' - || ((strlen($id) * 2 + $this->extensionStringLength) > 255) - || ($this->isRunningOnWindows && ($this->directoryStringLength + 4 + strlen($id) * 2 + $this->extensionStringLength) > 258) - ) { - // Most filesystems have a limit of 255 chars for each path component. On Windows the the whole path is limited - // to 260 chars (including terminating null char). Using long UNC ("\\?\" prefix) does not work with the PHP API. - // And there is a bug in PHP (https://bugs.php.net/bug.php?id=70943) with path lengths of 259. - // So if the id in hex representation would surpass the limit, we use the hash instead. The prefix prevents - // collisions between the hash and bin2hex. - $filename = '_' . $hash; - } else { - $filename = bin2hex($id); - } - - return $this->directory - . DIRECTORY_SEPARATOR - . substr($hash, 0, 2) - . DIRECTORY_SEPARATOR - . $filename - . $this->extension; - } - - /** - * {@inheritdoc} - */ - protected function doDelete($id) - { - $filename = $this->getFilename($id); - - return @unlink($filename) || ! file_exists($filename); - } - - /** - * {@inheritdoc} - */ - protected function doFlush() - { - foreach ($this->getIterator() as $name => $file) { - if ($file->isDir()) { - // Remove the intermediate directories which have been created to balance the tree. It only takes effect - // if the directory is empty. If several caches share the same directory but with different file extensions, - // the other ones are not removed. - @rmdir($name); - } elseif ($this->isFilenameEndingWithExtension($name)) { - // If an extension is set, only remove files which end with the given extension. - // If no extension is set, we have no other choice than removing everything. - @unlink($name); - } - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - $usage = 0; - foreach ($this->getIterator() as $name => $file) { - if ($file->isDir() || ! $this->isFilenameEndingWithExtension($name)) { - continue; - } - - $usage += $file->getSize(); - } - - $free = disk_free_space($this->directory); - - return [ - Cache::STATS_HITS => null, - Cache::STATS_MISSES => null, - Cache::STATS_UPTIME => null, - Cache::STATS_MEMORY_USAGE => $usage, - Cache::STATS_MEMORY_AVAILABLE => $free, - ]; - } - - /** - * Create path if needed. - * - * @return bool TRUE on success or if path already exists, FALSE if path cannot be created. - */ - private function createPathIfNeeded(string $path) : bool - { - if (! is_dir($path)) { - if (@mkdir($path, 0777 & (~$this->umask), true) === false && ! is_dir($path)) { - return false; - } - } - - return true; - } - - /** - * Writes a string content to file in an atomic way. - * - * @param string $filename Path to the file where to write the data. - * @param string $content The content to write - * - * @return bool TRUE on success, FALSE if path cannot be created, if path is not writable or an any other error. - */ - protected function writeFile(string $filename, string $content) : bool - { - $filepath = pathinfo($filename, PATHINFO_DIRNAME); - - if (! $this->createPathIfNeeded($filepath)) { - return false; - } - - if (! is_writable($filepath)) { - return false; - } - - $tmpFile = tempnam($filepath, 'swap'); - @chmod($tmpFile, 0666 & (~$this->umask)); - - if (file_put_contents($tmpFile, $content) !== false) { - @chmod($tmpFile, 0666 & (~$this->umask)); - if (@rename($tmpFile, $filename)) { - return true; - } - - @unlink($tmpFile); - } - - return false; - } - - private function getIterator() : Iterator - { - return new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($this->directory, FilesystemIterator::SKIP_DOTS), - RecursiveIteratorIterator::CHILD_FIRST - ); - } - - /** - * @param string $name The filename - */ - private function isFilenameEndingWithExtension(string $name) : bool - { - return $this->extension === '' - || strrpos($name, $this->extension) === (strlen($name) - $this->extensionStringLength); - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FilesystemCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FilesystemCache.php deleted file mode 100644 index 8f34c9c..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FilesystemCache.php +++ /dev/null @@ -1,102 +0,0 @@ -getFilename($id); - - if (! is_file($filename)) { - return false; - } - - $resource = fopen($filename, 'r'); - $line = fgets($resource); - - if ($line !== false) { - $lifetime = (int) $line; - } - - if ($lifetime !== 0 && $lifetime < time()) { - fclose($resource); - - return false; - } - - while (($line = fgets($resource)) !== false) { - $data .= $line; - } - - fclose($resource); - - return unserialize($data); - } - - /** - * {@inheritdoc} - */ - protected function doContains($id) - { - $lifetime = -1; - $filename = $this->getFilename($id); - - if (! is_file($filename)) { - return false; - } - - $resource = fopen($filename, 'r'); - $line = fgets($resource); - - if ($line !== false) { - $lifetime = (int) $line; - } - - fclose($resource); - - return $lifetime === 0 || $lifetime > time(); - } - - /** - * {@inheritdoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - if ($lifeTime > 0) { - $lifeTime = time() + $lifeTime; - } - - $data = serialize($data); - $filename = $this->getFilename($id); - - return $this->writeFile($filename, $lifeTime . PHP_EOL . $data); - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php deleted file mode 100644 index ee7ce98..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/FlushableCache.php +++ /dev/null @@ -1,18 +0,0 @@ -collection = $collection; - } - - /** - * {@inheritdoc} - */ - protected function doFetch($id) - { - $document = $this->collection->findOne(['_id' => $id], [MongoDBCache::DATA_FIELD, MongoDBCache::EXPIRATION_FIELD]); - - if ($document === null) { - return false; - } - - if ($this->isExpired($document)) { - $this->createExpirationIndex(); - $this->doDelete($id); - - return false; - } - - return unserialize($document[MongoDBCache::DATA_FIELD]->bin); - } - - /** - * {@inheritdoc} - */ - protected function doContains($id) - { - $document = $this->collection->findOne(['_id' => $id], [MongoDBCache::EXPIRATION_FIELD]); - - if ($document === null) { - return false; - } - - if ($this->isExpired($document)) { - $this->createExpirationIndex(); - $this->doDelete($id); - - return false; - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - try { - $result = $this->collection->update( - ['_id' => $id], - [ - '$set' => [ - MongoDBCache::EXPIRATION_FIELD => ($lifeTime > 0 ? new MongoDate(time() + $lifeTime) : null), - MongoDBCache::DATA_FIELD => new MongoBinData(serialize($data), MongoBinData::BYTE_ARRAY), - ], - ], - ['upsert' => true, 'multiple' => false] - ); - } catch (MongoCursorException $e) { - return false; - } - - return ($result['ok'] ?? 1) == 1; - } - - /** - * {@inheritdoc} - */ - protected function doDelete($id) - { - $result = $this->collection->remove(['_id' => $id]); - - return ($result['ok'] ?? 1) == 1; - } - - /** - * {@inheritdoc} - */ - protected function doFlush() - { - // Use remove() in lieu of drop() to maintain any collection indexes - $result = $this->collection->remove(); - - return ($result['ok'] ?? 1) == 1; - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - $serverStatus = $this->collection->db->command([ - 'serverStatus' => 1, - 'locks' => 0, - 'metrics' => 0, - 'recordStats' => 0, - 'repl' => 0, - ]); - - $collStats = $this->collection->db->command(['collStats' => 1]); - - return [ - Cache::STATS_HITS => null, - Cache::STATS_MISSES => null, - Cache::STATS_UPTIME => $serverStatus['uptime'] ?? null, - Cache::STATS_MEMORY_USAGE => $collStats['size'] ?? null, - Cache::STATS_MEMORY_AVAILABLE => null, - ]; - } - - /** - * Check if the document is expired. - * - * @param array $document - */ - private function isExpired(array $document) : bool - { - return isset($document[MongoDBCache::EXPIRATION_FIELD]) && - $document[MongoDBCache::EXPIRATION_FIELD] instanceof MongoDate && - $document[MongoDBCache::EXPIRATION_FIELD]->sec < time(); - } - - private function createExpirationIndex() : void - { - if ($this->expirationIndexCreated) { - return; - } - - $this->expirationIndexCreated = true; - $this->collection->createIndex([MongoDBCache::EXPIRATION_FIELD => 1], ['background' => true, 'expireAfterSeconds' => 0]); - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcacheCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcacheCache.php deleted file mode 100644 index 42bbd2c..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcacheCache.php +++ /dev/null @@ -1,104 +0,0 @@ -memcache = $memcache; - } - - /** - * Gets the memcache instance used by the cache. - * - * @return Memcache|null - */ - public function getMemcache() - { - return $this->memcache; - } - - /** - * {@inheritdoc} - */ - protected function doFetch($id) - { - return $this->memcache->get($id); - } - - /** - * {@inheritdoc} - */ - protected function doContains($id) - { - $flags = null; - $this->memcache->get($id, $flags); - - //if memcache has changed the value of "flags", it means the value exists - return $flags !== null; - } - - /** - * {@inheritdoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - if ($lifeTime > 30 * 24 * 3600) { - $lifeTime = time() + $lifeTime; - } - - return $this->memcache->set($id, $data, 0, (int) $lifeTime); - } - - /** - * {@inheritdoc} - */ - protected function doDelete($id) - { - // Memcache::delete() returns false if entry does not exist - return $this->memcache->delete($id) || ! $this->doContains($id); - } - - /** - * {@inheritdoc} - */ - protected function doFlush() - { - return $this->memcache->flush(); - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - $stats = $this->memcache->getStats(); - - return [ - Cache::STATS_HITS => $stats['get_hits'], - Cache::STATS_MISSES => $stats['get_misses'], - Cache::STATS_UPTIME => $stats['uptime'], - Cache::STATS_MEMORY_USAGE => $stats['bytes'], - Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'], - ]; - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcachedCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcachedCache.php deleted file mode 100644 index da966ae..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MemcachedCache.php +++ /dev/null @@ -1,170 +0,0 @@ -memcached = $memcached; - } - - /** - * Gets the memcached instance used by the cache. - * - * @return Memcached|null - */ - public function getMemcached() - { - return $this->memcached; - } - - /** - * {@inheritdoc} - */ - protected function doFetch($id) - { - return $this->memcached->get($id); - } - - /** - * {@inheritdoc} - */ - protected function doFetchMultiple(array $keys) - { - return $this->memcached->getMulti($keys) ?: []; - } - - /** - * {@inheritdoc} - */ - protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) - { - foreach (array_keys($keysAndValues) as $id) { - $this->validateCacheId($id); - } - - if ($lifetime > 30 * 24 * 3600) { - $lifetime = time() + $lifetime; - } - - return $this->memcached->setMulti($keysAndValues, $lifetime); - } - - /** - * {@inheritdoc} - */ - protected function doContains($id) - { - $this->memcached->get($id); - - return $this->memcached->getResultCode() === Memcached::RES_SUCCESS; - } - - /** - * {@inheritdoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - $this->validateCacheId($id); - - if ($lifeTime > 30 * 24 * 3600) { - $lifeTime = time() + $lifeTime; - } - - return $this->memcached->set($id, $data, (int) $lifeTime); - } - - /** - * {@inheritdoc} - */ - protected function doDeleteMultiple(array $keys) - { - return $this->memcached->deleteMulti($keys) - || $this->memcached->getResultCode() === Memcached::RES_NOTFOUND; - } - - /** - * {@inheritdoc} - */ - protected function doDelete($id) - { - return $this->memcached->delete($id) - || $this->memcached->getResultCode() === Memcached::RES_NOTFOUND; - } - - /** - * {@inheritdoc} - */ - protected function doFlush() - { - return $this->memcached->flush(); - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - $stats = $this->memcached->getStats(); - $servers = $this->memcached->getServerList(); - $key = $servers[0]['host'] . ':' . $servers[0]['port']; - $stats = $stats[$key]; - - return [ - Cache::STATS_HITS => $stats['get_hits'], - Cache::STATS_MISSES => $stats['get_misses'], - Cache::STATS_UPTIME => $stats['uptime'], - Cache::STATS_MEMORY_USAGE => $stats['bytes'], - Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'], - ]; - } - - /** - * Validate the cache id - * - * @see https://github.com/memcached/memcached/blob/1.5.12/doc/protocol.txt#L41-L49 - * - * @param string $id - * - * @return void - * - * @throws InvalidCacheId - */ - private function validateCacheId($id) - { - if (strlen($id) > self::CACHE_ID_MAX_LENGTH) { - throw InvalidCacheId::exceedsMaxLength($id, self::CACHE_ID_MAX_LENGTH); - } - - if (strpos($id, ' ') !== false) { - throw InvalidCacheId::containsUnauthorizedCharacter($id, ' '); - } - - if (preg_match('/[\t\r\n]/', $id) === 1) { - throw InvalidCacheId::containsControlCharacter($id); - } - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MongoDBCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MongoDBCache.php deleted file mode 100644 index 861e4dd..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MongoDBCache.php +++ /dev/null @@ -1,112 +0,0 @@ -provider = new LegacyMongoDBCache($collection); - } elseif ($collection instanceof Collection) { - $this->provider = new ExtMongoDBCache($collection); - } else { - throw new InvalidArgumentException('Invalid collection given - expected a MongoCollection or MongoDB\Collection instance'); - } - } - - /** - * {@inheritdoc} - */ - protected function doFetch($id) - { - return $this->provider->doFetch($id); - } - - /** - * {@inheritdoc} - */ - protected function doContains($id) - { - return $this->provider->doContains($id); - } - - /** - * {@inheritdoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - return $this->provider->doSave($id, $data, $lifeTime); - } - - /** - * {@inheritdoc} - */ - protected function doDelete($id) - { - return $this->provider->doDelete($id); - } - - /** - * {@inheritdoc} - */ - protected function doFlush() - { - return $this->provider->doFlush(); - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - return $this->provider->doGetStats(); - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php deleted file mode 100644 index d099d47..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/MultiDeleteCache.php +++ /dev/null @@ -1,22 +0,0 @@ - infinite lifeTime). - * - * @return bool TRUE if the operation was successful, FALSE if it wasn't. - */ - public function saveMultiple(array $keysAndValues, $lifetime = 0); -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/PhpFileCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/PhpFileCache.php deleted file mode 100644 index c061999..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/PhpFileCache.php +++ /dev/null @@ -1,118 +0,0 @@ -includeFileForId($id); - - if ($value === null) { - return false; - } - - if ($value['lifetime'] !== 0 && $value['lifetime'] < time()) { - return false; - } - - return $value['data']; - } - - /** - * {@inheritdoc} - */ - protected function doContains($id) - { - $value = $this->includeFileForId($id); - - if ($value === null) { - return false; - } - - return $value['lifetime'] === 0 || $value['lifetime'] > time(); - } - - /** - * {@inheritdoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - if ($lifeTime > 0) { - $lifeTime = time() + $lifeTime; - } - - $filename = $this->getFilename($id); - - $value = [ - 'lifetime' => $lifeTime, - 'data' => $data, - ]; - - if (is_object($data) && method_exists($data, '__set_state')) { - $value = var_export($value, true); - $code = sprintf('writeFile($filename, $code); - } - - /** - * @return array|null - */ - private function includeFileForId(string $id) : ?array - { - $fileName = $this->getFilename($id); - - // note: error suppression is still faster than `file_exists`, `is_file` and `is_readable` - set_error_handler(self::$emptyErrorHandler); - - $value = include $fileName; - - restore_error_handler(); - - if (! isset($value['lifetime'])) { - return null; - } - - return $value; - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/PredisCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/PredisCache.php deleted file mode 100644 index 6430d52..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/PredisCache.php +++ /dev/null @@ -1,143 +0,0 @@ -client = $client; - } - - /** - * {@inheritdoc} - */ - protected function doFetch($id) - { - $result = $this->client->get($id); - if ($result === null) { - return false; - } - - return unserialize($result); - } - - /** - * {@inheritdoc} - */ - protected function doFetchMultiple(array $keys) - { - $fetchedItems = call_user_func_array([$this->client, 'mget'], $keys); - - return array_map('unserialize', array_filter(array_combine($keys, $fetchedItems))); - } - - /** - * {@inheritdoc} - */ - protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) - { - if ($lifetime) { - $success = true; - - // Keys have lifetime, use SETEX for each of them - foreach ($keysAndValues as $key => $value) { - $response = (string) $this->client->setex($key, $lifetime, serialize($value)); - - if ($response == 'OK') { - continue; - } - - $success = false; - } - - return $success; - } - - // No lifetime, use MSET - $response = $this->client->mset(array_map(static function ($value) { - return serialize($value); - }, $keysAndValues)); - - return (string) $response == 'OK'; - } - - /** - * {@inheritdoc} - */ - protected function doContains($id) - { - return (bool) $this->client->exists($id); - } - - /** - * {@inheritdoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - $data = serialize($data); - if ($lifeTime > 0) { - $response = $this->client->setex($id, $lifeTime, $data); - } else { - $response = $this->client->set($id, $data); - } - - return $response === true || $response == 'OK'; - } - - /** - * {@inheritdoc} - */ - protected function doDelete($id) - { - return $this->client->del($id) >= 0; - } - - /** - * {@inheritdoc} - */ - protected function doDeleteMultiple(array $keys) - { - return $this->client->del($keys) >= 0; - } - - /** - * {@inheritdoc} - */ - protected function doFlush() - { - $response = $this->client->flushdb(); - - return $response === true || $response == 'OK'; - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - $info = $this->client->info(); - - return [ - Cache::STATS_HITS => $info['Stats']['keyspace_hits'], - Cache::STATS_MISSES => $info['Stats']['keyspace_misses'], - Cache::STATS_UPTIME => $info['Server']['uptime_in_seconds'], - Cache::STATS_MEMORY_USAGE => $info['Memory']['used_memory'], - Cache::STATS_MEMORY_AVAILABLE => false, - ]; - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/RedisCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/RedisCache.php deleted file mode 100644 index 3245705..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/RedisCache.php +++ /dev/null @@ -1,181 +0,0 @@ -setOption(Redis::OPT_SERIALIZER, $this->getSerializerValue()); - $this->redis = $redis; - } - - /** - * Gets the redis instance used by the cache. - * - * @return Redis|null - */ - public function getRedis() - { - return $this->redis; - } - - /** - * {@inheritdoc} - */ - protected function doFetch($id) - { - return $this->redis->get($id); - } - - /** - * {@inheritdoc} - */ - protected function doFetchMultiple(array $keys) - { - $fetchedItems = array_combine($keys, $this->redis->mget($keys)); - - // Redis mget returns false for keys that do not exist. So we need to filter those out unless it's the real data. - $keysToFilter = array_keys(array_filter($fetchedItems, static function ($item) : bool { - return $item === false; - })); - - if ($keysToFilter) { - $multi = $this->redis->multi(Redis::PIPELINE); - foreach ($keysToFilter as $key) { - $multi->exists($key); - } - $existItems = array_filter($multi->exec()); - $missedItemKeys = array_diff_key($keysToFilter, $existItems); - $fetchedItems = array_diff_key($fetchedItems, array_fill_keys($missedItemKeys, true)); - } - - return $fetchedItems; - } - - /** - * {@inheritdoc} - */ - protected function doSaveMultiple(array $keysAndValues, $lifetime = 0) - { - if ($lifetime) { - // Keys have lifetime, use SETEX for each of them - $multi = $this->redis->multi(Redis::PIPELINE); - foreach ($keysAndValues as $key => $value) { - $multi->setex($key, $lifetime, $value); - } - $succeeded = array_filter($multi->exec()); - - return count($succeeded) == count($keysAndValues); - } - - // No lifetime, use MSET - return (bool) $this->redis->mset($keysAndValues); - } - - /** - * {@inheritdoc} - */ - protected function doContains($id) - { - $exists = $this->redis->exists($id); - - if (is_bool($exists)) { - return $exists; - } - - return $exists > 0; - } - - /** - * {@inheritdoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - if ($lifeTime > 0) { - return $this->redis->setex($id, $lifeTime, $data); - } - - return $this->redis->set($id, $data); - } - - /** - * {@inheritdoc} - */ - protected function doDelete($id) - { - return $this->redis->del($id) >= 0; - } - - /** - * {@inheritdoc} - */ - protected function doDeleteMultiple(array $keys) - { - return $this->redis->del($keys) >= 0; - } - - /** - * {@inheritdoc} - */ - protected function doFlush() - { - return $this->redis->flushDB(); - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - $info = $this->redis->info(); - - return [ - Cache::STATS_HITS => $info['keyspace_hits'], - Cache::STATS_MISSES => $info['keyspace_misses'], - Cache::STATS_UPTIME => $info['uptime_in_seconds'], - Cache::STATS_MEMORY_USAGE => $info['used_memory'], - Cache::STATS_MEMORY_AVAILABLE => false, - ]; - } - - /** - * Returns the serializer constant to use. If Redis is compiled with - * igbinary support, that is used. Otherwise the default PHP serializer is - * used. - * - * @return int One of the Redis::SERIALIZER_* constants - */ - protected function getSerializerValue() - { - if (defined('Redis::SERIALIZER_IGBINARY') && extension_loaded('igbinary')) { - return Redis::SERIALIZER_IGBINARY; - } - - return Redis::SERIALIZER_PHP; - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/SQLite3Cache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/SQLite3Cache.php deleted file mode 100644 index 56deb07..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/SQLite3Cache.php +++ /dev/null @@ -1,206 +0,0 @@ -sqlite = $sqlite; - $this->table = (string) $table; - - $this->ensureTableExists(); - } - - private function ensureTableExists() : void - { - $this->sqlite->exec( - sprintf( - 'CREATE TABLE IF NOT EXISTS %s(%s TEXT PRIMARY KEY NOT NULL, %s BLOB, %s INTEGER)', - $this->table, - static::ID_FIELD, - static::DATA_FIELD, - static::EXPIRATION_FIELD - ) - ); - } - - /** - * {@inheritdoc} - */ - protected function doFetch($id) - { - $item = $this->findById($id); - - if (! $item) { - return false; - } - - return unserialize($item[self::DATA_FIELD]); - } - - /** - * {@inheritdoc} - */ - protected function doContains($id) - { - return $this->findById($id, false) !== null; - } - - /** - * {@inheritdoc} - */ - protected function doSave($id, $data, $lifeTime = 0) - { - $statement = $this->sqlite->prepare(sprintf( - 'INSERT OR REPLACE INTO %s (%s) VALUES (:id, :data, :expire)', - $this->table, - implode(',', $this->getFields()) - )); - - $statement->bindValue(':id', $id); - $statement->bindValue(':data', serialize($data), SQLITE3_BLOB); - $statement->bindValue(':expire', $lifeTime > 0 ? time() + $lifeTime : null); - - return $statement->execute() instanceof SQLite3Result; - } - - /** - * {@inheritdoc} - */ - protected function doDelete($id) - { - [$idField] = $this->getFields(); - - $statement = $this->sqlite->prepare(sprintf( - 'DELETE FROM %s WHERE %s = :id', - $this->table, - $idField - )); - - $statement->bindValue(':id', $id); - - return $statement->execute() instanceof SQLite3Result; - } - - /** - * {@inheritdoc} - */ - protected function doFlush() - { - return $this->sqlite->exec(sprintf('DELETE FROM %s', $this->table)); - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - // no-op. - } - - /** - * Find a single row by ID. - * - * @param mixed $id - * - * @return array|null - */ - private function findById($id, bool $includeData = true) : ?array - { - [$idField] = $fields = $this->getFields(); - - if (! $includeData) { - $key = array_search(static::DATA_FIELD, $fields); - unset($fields[$key]); - } - - $statement = $this->sqlite->prepare(sprintf( - 'SELECT %s FROM %s WHERE %s = :id LIMIT 1', - implode(',', $fields), - $this->table, - $idField - )); - - $statement->bindValue(':id', $id, SQLITE3_TEXT); - - $item = $statement->execute()->fetchArray(SQLITE3_ASSOC); - - if ($item === false) { - return null; - } - - if ($this->isExpired($item)) { - $this->doDelete($id); - - return null; - } - - return $item; - } - - /** - * Gets an array of the fields in our table. - * - * @return array - */ - private function getFields() : array - { - return [static::ID_FIELD, static::DATA_FIELD, static::EXPIRATION_FIELD]; - } - - /** - * Check if the item is expired. - * - * @param array $item - */ - private function isExpired(array $item) : bool - { - return isset($item[static::EXPIRATION_FIELD]) && - $item[self::EXPIRATION_FIELD] !== null && - $item[self::EXPIRATION_FIELD] < time(); - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Version.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Version.php deleted file mode 100644 index 834b5b7..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/Version.php +++ /dev/null @@ -1,8 +0,0 @@ - $info['total_hit_count'], - Cache::STATS_MISSES => $info['total_miss_count'], - Cache::STATS_UPTIME => $info['total_cache_uptime'], - Cache::STATS_MEMORY_USAGE => $meminfo['memory_total'], - Cache::STATS_MEMORY_AVAILABLE => $meminfo['memory_free'], - ]; - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/XcacheCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/XcacheCache.php deleted file mode 100644 index 9b3a485..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/XcacheCache.php +++ /dev/null @@ -1,104 +0,0 @@ -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); - } - - /** - * {@inheritdoc} - */ - protected function doFlush() - { - $this->checkAuthorization(); - - xcache_clear_cache(XC_TYPE_VAR); - - return true; - } - - /** - * Checks that xcache.admin.enable_auth is Off. - * - * @return void - * - * @throws BadMethodCallException When xcache.admin.enable_auth is On. - */ - protected function checkAuthorization() - { - 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.' - ); - } - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - $this->checkAuthorization(); - - $info = xcache_info(XC_TYPE_VAR, 0); - - return [ - Cache::STATS_HITS => $info['hits'], - Cache::STATS_MISSES => $info['misses'], - Cache::STATS_UPTIME => null, - Cache::STATS_MEMORY_USAGE => $info['size'], - Cache::STATS_MEMORY_AVAILABLE => $info['avail'], - ]; - } -} diff --git a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ZendDataCache.php b/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ZendDataCache.php deleted file mode 100644 index a6b67ef..0000000 --- a/vendor/doctrine/cache/lib/Doctrine/Common/Cache/ZendDataCache.php +++ /dev/null @@ -1,69 +0,0 @@ -getNamespace(); - if (empty($namespace)) { - return zend_shm_cache_clear(); - } - - return zend_shm_cache_clear($namespace); - } - - /** - * {@inheritdoc} - */ - protected function doGetStats() - { - return null; - } -} diff --git a/vendor/doctrine/collections/.doctrine-project.json b/vendor/doctrine/collections/.doctrine-project.json deleted file mode 100644 index 57d2fef..0000000 --- a/vendor/doctrine/collections/.doctrine-project.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "active": true, - "name": "Collections", - "slug": "collections", - "docsSlug": "doctrine-collections", - "versions": [ - { - "name": "master", - "branchName": "master", - "slug": "latest", - "aliases": [ - "current", - "stable" - ] - } - ] -} diff --git a/vendor/doctrine/collections/CONTRIBUTING.md b/vendor/doctrine/collections/CONTRIBUTING.md deleted file mode 100644 index 83437da..0000000 --- a/vendor/doctrine/collections/CONTRIBUTING.md +++ /dev/null @@ -1,54 +0,0 @@ -# Contribute to Doctrine - -Thank you for contributing to Doctrine! - -Before we can merge your Pull-Request here are some guidelines that you need to follow. -These guidelines exist not to annoy you, but to keep the code base clean, -unified and future proof. - -## We only accept PRs to "master" - -Our branching strategy is "everything to master first", even -bugfixes and we then merge them into the stable branches. You should only -open pull requests against the master branch. Otherwise we cannot accept the PR. - -There is one exception to the rule, when we merged a bug into some stable branches -we do occasionally accept pull requests that merge the same bug fix into earlier -branches. - -## Coding Standard - -We use the [Doctrine Coding Standard](https://github.com/doctrine/coding-standard). - -## Unit-Tests - -Please try to add a test for your pull-request. - -* If you want to contribute new functionality add unit- or functional tests - depending on the scope of the feature. - -You can run the unit-tests by calling ``vendor/bin/phpunit`` from the root of the project. -It will run all the project tests. - -In order to do that, you will need a fresh copy of doctrine/collections, and you -will have to run a composer installation in the project: - -```sh -git clone git@github.com:doctrine/collections.git -cd collections -curl -sS https://getcomposer.org/installer | php -- -./composer.phar install -``` - -## Travis - -We automatically run your pull request through [Travis CI](https://www.travis-ci.org) -against supported PHP versions. If you break the tests, we cannot merge your code, -so please make sure that your code is working before opening up a Pull-Request. - -## Getting merged - -Please allow us time to review your pull requests. We will give our best to review -everything as fast as possible, but cannot always live up to our own expectations. - -Thank you very much again for your contribution! diff --git a/vendor/doctrine/collections/LICENSE b/vendor/doctrine/collections/LICENSE deleted file mode 100644 index 5e781fc..0000000 --- a/vendor/doctrine/collections/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006-2013 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/doctrine/collections/README.md b/vendor/doctrine/collections/README.md deleted file mode 100644 index 95fcdf8..0000000 --- a/vendor/doctrine/collections/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# Doctrine Collections - -[![Build Status](https://travis-ci.org/doctrine/collections.svg?branch=master)](https://travis-ci.org/doctrine/collections) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/collections/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/collections/?branch=master) -[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/collections/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/collections/?branch=master) - -Collections Abstraction library - -## Changelog - -### v1.6.1 - -This release, combined with the release of [`doctrine/collections` `v1.6.1`](https://github.com/doctrine/collections/releases/tag/v1.6.1), -fixes an issue where parsing annotations was not possible -for classes within `doctrine/collections`. - -Specifically, `v1.6.0` introduced Psalm-specific annotations -such as (for example) `@template` and `@template-implements`, -which were both incorrectly recognized as `@template`. - -`@template` has therefore been removed, and instead we use -the prefixed `@psalm-template`, which is no longer parsed -by `doctrine/collections` `v1.6.1` - -Total issues resolved: **1** - -- [186: Use `@psalm-template` annotation to avoid clashes](https://github.com/doctrine/collections/pull/186) thanks to @muglug - -### v1.6.0 - -This release bumps the minimum required PHP version to 7.1.3. - -Following improvements were introduced: - - * `ArrayCollection#filter()` now allows filtering by key, value or both. - * When using the `ClosureExpressionVisitor` over objects with a defined - accessor and property, the accessor is prioritised. - * Updated testing tools and coding standards, autoloading, which also - led to marginal performance improvements - * Introduced generic type docblock declarations from [psalm](https://github.com/vimeo/psalm), - which should allow users to declare `/** @var Collection */` - in their code, and leverage the type propagation deriving from that. - -Total issues resolved: **16** - -- [127: Use PSR-4](https://github.com/doctrine/collections/pull/127) thanks to @Nyholm -- [129: Remove space in method declaration](https://github.com/doctrine/collections/pull/129) thanks to @bounoable -- [130: Update build to add PHPCS and PHPStan](https://github.com/doctrine/collections/pull/130) thanks to @lcobucci -- [131: ClosureExpressionVisitor > Don't duplicate the accessor when the field already starts with it](https://github.com/doctrine/collections/pull/131) thanks to @ruudk -- [139: Apply Doctrine CS 2.1](https://github.com/doctrine/collections/pull/139) thanks to @Majkl578 -- [142: CS 4.0, version composer.lock, merge stages](https://github.com/doctrine/collections/pull/142) thanks to @Majkl578 -- [144: Update to PHPUnit 7](https://github.com/doctrine/collections/pull/144) thanks to @carusogabriel -- [146: Update changelog for v1.4.0 and v1.5.0](https://github.com/doctrine/collections/pull/146) thanks to @GromNaN -- [154: Update index.rst](https://github.com/doctrine/collections/pull/154) thanks to @chraiet -- [158: Extract Selectable method into own documentation section](https://github.com/doctrine/collections/pull/158) thanks to @SenseException -- [160: Update homepage](https://github.com/doctrine/collections/pull/160) thanks to @Majkl578 -- [165: Allow `ArrayCollection#filter()` to filter by key, value or both](https://github.com/doctrine/collections/issues/165) thanks to @0x13a -- [167: Allow `ArrayCollection#filter()` to filter by key and also value](https://github.com/doctrine/collections/pull/167) thanks to @0x13a -- [175: CI: Test against PHP 7.4snapshot instead of nightly (8.0)](https://github.com/doctrine/collections/pull/175) thanks to @Majkl578 -- [177: Generify collections using Psalm](https://github.com/doctrine/collections/pull/177) thanks to @nschoellhorn -- [178: Updated doctrine/coding-standard to 6.0](https://github.com/doctrine/collections/pull/178) thanks to @patrickjahns - -### v1.5.0 - -* [Require PHP 7.1+](https://github.com/doctrine/collections/pull/105) -* [Drop HHVM support](https://github.com/doctrine/collections/pull/118) - -### v1.4.0 - -* [Require PHP 5.6+](https://github.com/doctrine/collections/pull/105) -* [Add `ArrayCollection::createFrom()`](https://github.com/doctrine/collections/pull/91) -* [Support non-camel-case naming](https://github.com/doctrine/collections/pull/57) -* [Comparison `START_WITH`, `END_WITH`](https://github.com/doctrine/collections/pull/78) -* [Comparison `MEMBER_OF`](https://github.com/doctrine/collections/pull/66) -* [Add Contributing guide](https://github.com/doctrine/collections/pull/103) - -### v1.3.0 - -* [Explicit casting of first and max results in criteria API](https://github.com/doctrine/collections/pull/26) -* [Keep keys when using `ArrayCollection#matching()` with sorting](https://github.com/doctrine/collections/pull/49) -* [Made `AbstractLazyCollection#$initialized` protected for extensibility](https://github.com/doctrine/collections/pull/52) - -### v1.2.0 - -* Add a new ``AbstractLazyCollection`` - -### v1.1.0 - -* Deprecated ``Comparison::IS``, because it's only there for SQL semantics. - These are fixed in the ORM instead. -* Add ``Comparison::CONTAINS`` to perform partial string matches: - - $criteria->andWhere($criteria->expr()->contains('property', 'Foo')); diff --git a/vendor/doctrine/collections/composer.json b/vendor/doctrine/collections/composer.json deleted file mode 100644 index 828a7d2..0000000 --- a/vendor/doctrine/collections/composer.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "doctrine/collections", - "type": "library", - "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.", - "keywords": [ - "php", - "collections", - "array", - "iterators" - ], - "homepage": "https://www.doctrine-project.org/projects/collections.html", - "license": "MIT", - "authors": [ - {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, - {"name": "Roman Borschel", "email": "roman@code-factory.org"}, - {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, - {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, - {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} - ], - "require": { - "php": "^7.1.3" - }, - "require-dev": { - "phpunit/phpunit": "^7.0", - "doctrine/coding-standard": "^6.0", - "phpstan/phpstan-shim": "^0.9.2", - "vimeo/psalm": "^3.2.2" - }, - "autoload": { - "psr-4": { "Doctrine\\Common\\Collections\\": "lib/Doctrine/Common/Collections" } - }, - "autoload-dev": { - "psr-4": { - "Doctrine\\Tests\\": "tests/Doctrine/Tests" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - } -} diff --git a/vendor/doctrine/collections/docs/en/derived-collections.rst b/vendor/doctrine/collections/docs/en/derived-collections.rst deleted file mode 100644 index 03d9da5..0000000 --- a/vendor/doctrine/collections/docs/en/derived-collections.rst +++ /dev/null @@ -1,26 +0,0 @@ -Derived Collections -=================== - -You can create custom collection classes by extending the -``Doctrine\Common\Collections\ArrayCollection`` class. If the -``__construct`` semantics are different from the default ``ArrayCollection`` -you can override the ``createFrom`` method: - -.. code-block:: php - final class DerivedArrayCollection extends ArrayCollection - { - /** @var \stdClass */ - private $foo; - - public function __construct(\stdClass $foo, array $elements = []) - { - $this->foo = $foo; - - parent::__construct($elements); - } - - protected function createFrom(array $elements) : self - { - return new static($this->foo, $elements); - } - } diff --git a/vendor/doctrine/collections/docs/en/expression-builder.rst b/vendor/doctrine/collections/docs/en/expression-builder.rst deleted file mode 100644 index ad4055b..0000000 --- a/vendor/doctrine/collections/docs/en/expression-builder.rst +++ /dev/null @@ -1,173 +0,0 @@ -Expression Builder -================== - -The Expression Builder is a convenient fluent interface for -building expressions to be used with the ``Doctrine\Common\Collections\Criteria`` -class: - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $criteria = new Criteria(); - $criteria->where($expressionBuilder->eq('name', 'jwage')); - $criteria->orWhere($expressionBuilder->eq('name', 'romanb')); - - $collection->matching($criteria); - -The ``ExpressionBuilder`` has the following API: - -andX ----- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->andX( - $expressionBuilder->eq('foo', 1), - $expressionBuilder->eq('bar', 1) - ); - - $collection->matching(new Criteria($expression)); - -orX ---- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->orX( - $expressionBuilder->eq('foo', 1), - $expressionBuilder->eq('bar', 1) - ); - - $collection->matching(new Criteria($expression)); - -eq ---- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->eq('foo', 1); - - $collection->matching(new Criteria($expression)); - -gt ---- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->gt('foo', 1); - - $collection->matching(new Criteria($expression)); - -lt ---- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->lt('foo', 1); - - $collection->matching(new Criteria($expression)); - -gte ---- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->gte('foo', 1); - - $collection->matching(new Criteria($expression)); - -lte ---- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->lte('foo', 1); - - $collection->matching(new Criteria($expression)); - -neq ---- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->neq('foo', 1); - - $collection->matching(new Criteria($expression)); - -isNull ------- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->isNull('foo'); - - $collection->matching(new Criteria($expression)); - -in ---- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->in('foo', ['value1', 'value2']); - - $collection->matching(new Criteria($expression)); - -notIn ------ - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->notIn('foo', ['value1', 'value2']); - - $collection->matching(new Criteria($expression)); - -contains --------- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->contains('foo', 'value1'); - - $collection->matching(new Criteria($expression)); - -memberOf --------- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->memberOf('foo', ['value1', 'value2']); - - $collection->matching(new Criteria($expression)); - -startsWith ----------- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->startsWith('foo', 'hello'); - - $collection->matching(new Criteria($expression)); - -endsWith --------- - -.. code-block:: php - $expressionBuilder = Criteria::expr(); - - $expression = $expressionBuilder->endsWith('foo', 'world'); - - $collection->matching(new Criteria($expression)); diff --git a/vendor/doctrine/collections/docs/en/expressions.rst b/vendor/doctrine/collections/docs/en/expressions.rst deleted file mode 100644 index db943b2..0000000 --- a/vendor/doctrine/collections/docs/en/expressions.rst +++ /dev/null @@ -1,102 +0,0 @@ -Expressions -=========== - -The ``Doctrine\Common\Collections\Expr\Comparison`` class -can be used to create expressions to be used with the -``Doctrine\Common\Collections\Criteria`` class. It has the -following operator constants: - -- ``Comparison::EQ`` -- ``Comparison::NEQ`` -- ``Comparison::LT`` -- ``Comparison::LTE`` -- ``Comparison::GT`` -- ``Comparison::GTE`` -- ``Comparison::IS`` -- ``Comparison::IN`` -- ``Comparison::NIN`` -- ``Comparison::CONTAINS`` -- ``Comparison::MEMBER_OF`` -- ``Comparison::STARTS_WITH`` -- ``Comparison::ENDS_WITH`` - -The ``Doctrine\Common\Collections\Criteria`` class has the following -API to be used with expressions: - -where ------ - -Sets the where expression to evaluate when this Criteria is searched for. - -.. code-block:: php - $expr = new Comparison('key', Comparison::EQ, 'value'); - - $criteria->where($expr); - -andWhere --------- - -Appends the where expression to evaluate when this Criteria is searched for -using an AND with previous expression. - -.. code-block:: php - $expr = new Comparison('key', Comparison::EQ, 'value'); - - $criteria->andWhere($expr); - -orWhere -------- - -Appends the where expression to evaluate when this Criteria is searched for -using an OR with previous expression. - -.. code-block:: php - $expr1 = new Comparison('key', Comparison::EQ, 'value1'); - $expr2 = new Comparison('key', Comparison::EQ, 'value2'); - - $criteria->where($expr1); - $criteria->orWhere($expr2); - -orderBy -------- - -Sets the ordering of the result of this Criteria. - -.. code-block:: php - $criteria->orderBy(['name' => Criteria::ASC]); - -setFirstResult --------------- - -Set the number of first result that this Criteria should return. - -.. code-block:: php - $criteria->setFirstResult(0); - -getFirstResult --------------- - -Gets the current first result option of this Criteria. - -.. code-block:: php - $criteria->setFirstResult(10); - - echo $criteria->getFirstResult(); // 10 - -setMaxResults -------------- - -Sets the max results that this Criteria should return. - -.. code-block:: php - $criteria->setMaxResults(20); - -getMaxResults -------------- - -Gets the current max results option of this Criteria. - -.. code-block:: php - $criteria->setMaxResults(20); - - echo $criteria->getMaxResults(); // 20 diff --git a/vendor/doctrine/collections/docs/en/index.rst b/vendor/doctrine/collections/docs/en/index.rst deleted file mode 100644 index 447f76e..0000000 --- a/vendor/doctrine/collections/docs/en/index.rst +++ /dev/null @@ -1,327 +0,0 @@ -Introduction -============ - -Doctrine Collections is a library that contains classes for working with -arrays of data. Here is an example using the simple -``Doctrine\Common\Collections\ArrayCollection`` class: - -.. code-block:: php - filter(function($count) { - return $count > 1; - }); // [2, 3] - -Collection Methods -================== - -Doctrine Collections provides an interface named ``Doctrine\Common\Collections\Collection`` -that resembles the nature of a regular PHP array. That is, -it is essentially an **ordered map** 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 preferable. -To use an external iterator simply use the foreach language construct to -iterate over the collection, which calls ``getIterator()`` internally, or -explicitly retrieve an iterator though ``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. - -The methods available on the interface are: - -add ---- - -Adds an element at the end of the collection. - -.. code-block:: php - $collection->add('test'); - -clear ------ - -Clears the collection, removing all elements. - -.. code-block:: php - $collection->clear(); - -contains --------- - -Checks whether an element is contained in the collection. This is an O(n) operation, where n is the size of the collection. - -.. code-block:: php - $collection = new Collection(['test']); - - $contains = $collection->contains('test'); // true - -containsKey ------------ - -Checks whether the collection contains an element with the specified key/index. - -.. code-block:: php - $collection = new Collection(['test' => true]); - - $contains = $collection->containsKey('test'); // true - -current -------- - -Gets the element of the collection at the current iterator position. - -.. code-block:: php - $collection = new Collection(['first', 'second', 'third']); - - $current = $collection->current(); // first - -get ---- - -Gets the element at the specified key/index. - -.. code-block:: php - $collection = new Collection([ - 'key' => 'value', - ]); - - $value = $collection->get('key'); // value - -getKeys -------- - -Gets all keys/indices of the collection. - -.. code-block:: php - $collection = new Collection(['a', 'b', 'c']); - - $keys = $collection->getKeys(); // [0, 1, 2] - -getValues ---------- - -Gets all values of the collection. - -.. code-block:: php - $collection = new Collection([ - 'key1' => 'value1', - 'key2' => 'value2', - 'key3' => 'value3', - ]); - - $values = $collection->getValues(); // ['value1', 'value2', 'value3'] - -isEmpty -------- - -Checks whether the collection is empty (contains no elements). - -.. code-block:: php - $collection = new Collection(['a', 'b', 'c']); - - $isEmpty = $collection->isEmpty(); // false - -first ------ - -Sets the internal iterator to the first element in the collection and returns this element. - -.. code-block:: php - $collection = new Collection(['first', 'second', 'third']); - - $first = $collection->first(); // first - -exists ------- - -Tests for the existence of an element that satisfies the given predicate. - -.. code-block:: php - $collection = new Collection(['first', 'second', 'third']); - - $exists = $collection->exists(function($key, $value) { - return $value === 'first'; - }); // true - -filter ------- - -Returns all the elements of this collection that satisfy the predicate. The order of the elements is preserved. - -.. code-block:: php - $collection = new ArrayCollection([1, 2, 3]); - - $filteredCollection = $collection->filter(function($count) { - return $count > 1; - }); // [2, 3] - -forAll ------- - -Tests whether the given predicate holds for all elements of this collection. - -.. code-block:: php - $collection = new ArrayCollection([1, 2, 3]); - - $forAll = $collection->forAll(function($key, $value) { - return $value > 1; - }); // false - -indexOf -------- - -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. - -.. code-block:: php - $collection = new ArrayCollection([1, 2, 3]); - - $indexOf = $collection->indexOf(3); // 2 - -key ---- - -Gets the key/index of the element at the current iterator position. - -.. code-block:: php - $collection = new ArrayCollection([1, 2, 3]); - - $collection->next(); - - $key = $collection->key(); // 1 - -last ----- - -Sets the internal iterator to the last element in the collection and returns this element. - -.. code-block:: php - $collection = new ArrayCollection([1, 2, 3]); - - $last = $collection->last(); // 3 - -map ---- - -Applies the given function to each element in the collection and returns a new collection with the elements returned by the function. - -.. code-block:: php - $collection = new ArrayCollection([1, 2, 3]); - - $mappedCollection = $collection->map(function($value) { - return $value + 1; - }); // [2, 3, 4] - -next ----- - -Moves the internal iterator position to the next element and returns this element. - -.. code-block:: php - $collection = new ArrayCollection([1, 2, 3]); - - $next = $collection->next(); // 2 - -partition ---------- - -Partitions this collection in two collections according to a predicate. Keys are preserved in the resulting collections. - -.. code-block:: php - $collection = new ArrayCollection([1, 2, 3]); - - $mappedCollection = $collection->partition(function($key, $value) { - return $value > 1 - }); // [[2, 3], [1]] - -remove ------- - -Removes the element at the specified index from the collection. - -.. code-block:: php - $collection = new ArrayCollection([1, 2, 3]); - - $collection->remove(0); // [2, 3] - -removeElement -------------- - -Removes the specified element from the collection, if it is found. - -.. code-block:: php - $collection = new ArrayCollection([1, 2, 3]); - - $collection->removeElement(3); // [1, 2] - -set ---- - -Sets an element in the collection at the specified key/index. - -.. code-block:: php - $collection = new ArrayCollection(); - - $collection->set('name', 'jwage'); - -slice ------ - -Extracts 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. - -.. code-block:: php - $collection = new ArrayCollection([0, 1, 2, 3, 4, 5]); - - $slice = $collection->slice(1, 2); // [1, 2] - -toArray -------- - -Gets a native PHP array representation of the collection. - -.. code-block:: php - $collection = new ArrayCollection([0, 1, 2, 3, 4, 5]); - - $array = $collection->toArray(); // [0, 1, 2, 3, 4, 5] - -Selectable Methods -================== - -Some Doctrine Collections, like ``Doctrine\Common\Collections\ArrayCollection``, -implement an interface named ``Doctrine\Common\Collections\Selectable`` -that offers the usage of a powerful expressions API, where conditions -can be applied to a collection to get a result with matching elements -only. - -matching --------- - -Selects all elements from a selectable that match the expression and -returns a new collection containing these elements. - -.. code-block:: php - use Doctrine\Common\Collections\Criteria; - use Doctrine\Common\Collections\Expr\Comparison; - - $collection = new ArrayCollection([ - [ - 'name' => 'jwage', - ], - [ - 'name' => 'romanb', - ], - ]); - - $expr = new Comparison('name', '=', 'jwage'); - - $criteria = new Criteria(); - - $criteria->where($expr); - - $matched = $collection->matching($criteria); // ['jwage'] - -You can read more about expressions :ref:`here `. diff --git a/vendor/doctrine/collections/docs/en/lazy-collections.rst b/vendor/doctrine/collections/docs/en/lazy-collections.rst deleted file mode 100644 index b9cafb6..0000000 --- a/vendor/doctrine/collections/docs/en/lazy-collections.rst +++ /dev/null @@ -1,26 +0,0 @@ -Lazy Collections -================ - -To create a lazy collection you can extend the -``Doctrine\Common\Collections\AbstractLazyCollection`` class -and define the ``doInitialize`` method. Here is an example where -we lazily query the database for a collection of user records: - -.. code-block:: php - use Doctrine\DBAL\Connection; - - class UsersLazyCollection extends AbstractLazyCollection - { - /** @var Connection */ - private $connection; - - public function __construct(Connection $connection) - { - $this->connection = $connection; - } - - protected function doInitialize() : void - { - $this->collection = $this->connection->fetchAll('SELECT * FROM users'); - } - } diff --git a/vendor/doctrine/collections/docs/en/sidebar.rst b/vendor/doctrine/collections/docs/en/sidebar.rst deleted file mode 100644 index 69279a0..0000000 --- a/vendor/doctrine/collections/docs/en/sidebar.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. toctree:: - :depth: 3 - - index - expressions - expression-builder - derived-collections - lazy-collections diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/AbstractLazyCollection.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/AbstractLazyCollection.php deleted file mode 100644 index cfdd144..0000000 --- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/AbstractLazyCollection.php +++ /dev/null @@ -1,354 +0,0 @@ - - */ -abstract class AbstractLazyCollection implements Collection -{ - /** - * The backed collection to use - * - * @psalm-var Collection - * @var Collection - */ - protected $collection; - - /** @var bool */ - protected $initialized = false; - - /** - * {@inheritDoc} - */ - public function count() - { - $this->initialize(); - - return $this->collection->count(); - } - - /** - * {@inheritDoc} - */ - public function add($element) - { - $this->initialize(); - - return $this->collection->add($element); - } - - /** - * {@inheritDoc} - */ - public function clear() - { - $this->initialize(); - $this->collection->clear(); - } - - /** - * {@inheritDoc} - */ - public function contains($element) - { - $this->initialize(); - - return $this->collection->contains($element); - } - - /** - * {@inheritDoc} - */ - public function isEmpty() - { - $this->initialize(); - - return $this->collection->isEmpty(); - } - - /** - * {@inheritDoc} - */ - public function remove($key) - { - $this->initialize(); - - return $this->collection->remove($key); - } - - /** - * {@inheritDoc} - */ - public function removeElement($element) - { - $this->initialize(); - - return $this->collection->removeElement($element); - } - - /** - * {@inheritDoc} - */ - public function containsKey($key) - { - $this->initialize(); - - return $this->collection->containsKey($key); - } - - /** - * {@inheritDoc} - */ - public function get($key) - { - $this->initialize(); - - return $this->collection->get($key); - } - - /** - * {@inheritDoc} - */ - public function getKeys() - { - $this->initialize(); - - return $this->collection->getKeys(); - } - - /** - * {@inheritDoc} - */ - public function getValues() - { - $this->initialize(); - - return $this->collection->getValues(); - } - - /** - * {@inheritDoc} - */ - public function set($key, $value) - { - $this->initialize(); - $this->collection->set($key, $value); - } - - /** - * {@inheritDoc} - */ - public function toArray() - { - $this->initialize(); - - return $this->collection->toArray(); - } - - /** - * {@inheritDoc} - */ - public function first() - { - $this->initialize(); - - return $this->collection->first(); - } - - /** - * {@inheritDoc} - */ - public function last() - { - $this->initialize(); - - return $this->collection->last(); - } - - /** - * {@inheritDoc} - */ - public function key() - { - $this->initialize(); - - return $this->collection->key(); - } - - /** - * {@inheritDoc} - */ - public function current() - { - $this->initialize(); - - return $this->collection->current(); - } - - /** - * {@inheritDoc} - */ - public function next() - { - $this->initialize(); - - return $this->collection->next(); - } - - /** - * {@inheritDoc} - */ - public function exists(Closure $p) - { - $this->initialize(); - - return $this->collection->exists($p); - } - - /** - * {@inheritDoc} - */ - public function filter(Closure $p) - { - $this->initialize(); - - return $this->collection->filter($p); - } - - /** - * {@inheritDoc} - */ - public function forAll(Closure $p) - { - $this->initialize(); - - return $this->collection->forAll($p); - } - - /** - * {@inheritDoc} - */ - public function map(Closure $func) - { - $this->initialize(); - - return $this->collection->map($func); - } - - /** - * {@inheritDoc} - */ - public function partition(Closure $p) - { - $this->initialize(); - - return $this->collection->partition($p); - } - - /** - * {@inheritDoc} - */ - public function indexOf($element) - { - $this->initialize(); - - return $this->collection->indexOf($element); - } - - /** - * {@inheritDoc} - */ - public function slice($offset, $length = null) - { - $this->initialize(); - - return $this->collection->slice($offset, $length); - } - - /** - * {@inheritDoc} - */ - public function getIterator() - { - $this->initialize(); - - return $this->collection->getIterator(); - } - - /** - * {@inheritDoc} - */ - public function offsetExists($offset) - { - $this->initialize(); - - return $this->collection->offsetExists($offset); - } - - /** - * {@inheritDoc} - */ - public function offsetGet($offset) - { - $this->initialize(); - - return $this->collection->offsetGet($offset); - } - - /** - * {@inheritDoc} - */ - public function offsetSet($offset, $value) - { - $this->initialize(); - $this->collection->offsetSet($offset, $value); - } - - /** - * {@inheritDoc} - */ - public function offsetUnset($offset) - { - $this->initialize(); - $this->collection->offsetUnset($offset); - } - - /** - * Is the lazy collection already initialized? - * - * @return bool - */ - public function isInitialized() - { - return $this->initialized; - } - - /** - * Initialize the collection - * - * @return void - */ - protected function initialize() - { - if ($this->initialized) { - return; - } - - $this->doInitialize(); - $this->initialized = true; - } - - /** - * Do the initialization logic - * - * @return void - */ - abstract protected function doInitialize(); -} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php deleted file mode 100644 index 46f68d4..0000000 --- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php +++ /dev/null @@ -1,429 +0,0 @@ - - * @template-implements Selectable - */ -class ArrayCollection implements Collection, Selectable -{ - /** - * An array containing the entries of this collection. - * - * @psalm-var array - * @var array - */ - private $elements; - - /** - * Initializes a new ArrayCollection. - * - * @param array $elements - * - * @psalm-param array $elements - */ - public function __construct(array $elements = []) - { - $this->elements = $elements; - } - - /** - * {@inheritDoc} - */ - public function toArray() - { - return $this->elements; - } - - /** - * {@inheritDoc} - */ - public function first() - { - return reset($this->elements); - } - - /** - * Creates a new instance from the specified elements. - * - * This method is provided for derived classes to specify how a new - * instance should be created when constructor semantics have changed. - * - * @param array $elements Elements. - * - * @return static - * - * @psalm-param array $elements - * @psalm-return static - */ - protected function createFrom(array $elements) - { - return new static($elements); - } - - /** - * {@inheritDoc} - */ - public function last() - { - return end($this->elements); - } - - /** - * {@inheritDoc} - */ - public function key() - { - return key($this->elements); - } - - /** - * {@inheritDoc} - */ - public function next() - { - return next($this->elements); - } - - /** - * {@inheritDoc} - */ - public function current() - { - return current($this->elements); - } - - /** - * {@inheritDoc} - */ - public function remove($key) - { - if (! isset($this->elements[$key]) && ! array_key_exists($key, $this->elements)) { - return null; - } - - $removed = $this->elements[$key]; - unset($this->elements[$key]); - - return $removed; - } - - /** - * {@inheritDoc} - */ - public function removeElement($element) - { - $key = array_search($element, $this->elements, true); - - if ($key === false) { - return false; - } - - unset($this->elements[$key]); - - return true; - } - - /** - * Required by interface ArrayAccess. - * - * {@inheritDoc} - */ - public function offsetExists($offset) - { - return $this->containsKey($offset); - } - - /** - * Required by interface ArrayAccess. - * - * {@inheritDoc} - */ - public function offsetGet($offset) - { - return $this->get($offset); - } - - /** - * Required by interface ArrayAccess. - * - * {@inheritDoc} - */ - public function offsetSet($offset, $value) - { - if (! isset($offset)) { - $this->add($value); - - return; - } - - $this->set($offset, $value); - } - - /** - * Required by interface ArrayAccess. - * - * {@inheritDoc} - */ - public function offsetUnset($offset) - { - $this->remove($offset); - } - - /** - * {@inheritDoc} - */ - public function containsKey($key) - { - return isset($this->elements[$key]) || array_key_exists($key, $this->elements); - } - - /** - * {@inheritDoc} - */ - public function contains($element) - { - return in_array($element, $this->elements, true); - } - - /** - * {@inheritDoc} - */ - public function exists(Closure $p) - { - foreach ($this->elements as $key => $element) { - if ($p($key, $element)) { - return true; - } - } - - return false; - } - - /** - * {@inheritDoc} - */ - public function indexOf($element) - { - return array_search($element, $this->elements, true); - } - - /** - * {@inheritDoc} - */ - public function get($key) - { - return $this->elements[$key] ?? null; - } - - /** - * {@inheritDoc} - */ - public function getKeys() - { - return array_keys($this->elements); - } - - /** - * {@inheritDoc} - */ - public function getValues() - { - return array_values($this->elements); - } - - /** - * {@inheritDoc} - */ - public function count() - { - return count($this->elements); - } - - /** - * {@inheritDoc} - */ - public function set($key, $value) - { - $this->elements[$key] = $value; - } - - /** - * {@inheritDoc} - */ - public function add($element) - { - $this->elements[] = $element; - - return true; - } - - /** - * {@inheritDoc} - */ - public function isEmpty() - { - return empty($this->elements); - } - - /** - * Required by interface IteratorAggregate. - * - * {@inheritDoc} - */ - public function getIterator() - { - return new ArrayIterator($this->elements); - } - - /** - * {@inheritDoc} - * - * @return static - * - * @psalm-template U - * @psalm-param Closure(T=):U $func - * @psalm-return static - */ - public function map(Closure $func) - { - return $this->createFrom(array_map($func, $this->elements)); - } - - /** - * {@inheritDoc} - * - * @return static - * - * @psalm-return static - */ - public function filter(Closure $p) - { - return $this->createFrom(array_filter($this->elements, $p, ARRAY_FILTER_USE_BOTH)); - } - - /** - * {@inheritDoc} - */ - public function forAll(Closure $p) - { - foreach ($this->elements as $key => $element) { - if (! $p($key, $element)) { - return false; - } - } - - return true; - } - - /** - * {@inheritDoc} - */ - public function partition(Closure $p) - { - $matches = $noMatches = []; - - foreach ($this->elements as $key => $element) { - if ($p($key, $element)) { - $matches[$key] = $element; - } else { - $noMatches[$key] = $element; - } - } - - return [$this->createFrom($matches), $this->createFrom($noMatches)]; - } - - /** - * Returns a string representation of this object. - * - * @return string - */ - public function __toString() - { - return self::class . '@' . spl_object_hash($this); - } - - /** - * {@inheritDoc} - */ - public function clear() - { - $this->elements = []; - } - - /** - * {@inheritDoc} - */ - public function slice($offset, $length = null) - { - return array_slice($this->elements, $offset, $length, true); - } - - /** - * {@inheritDoc} - */ - public function matching(Criteria $criteria) - { - $expr = $criteria->getWhereExpression(); - $filtered = $this->elements; - - if ($expr) { - $visitor = new ClosureExpressionVisitor(); - $filter = $visitor->dispatch($expr); - $filtered = array_filter($filtered, $filter); - } - - $orderings = $criteria->getOrderings(); - - if ($orderings) { - $next = null; - foreach (array_reverse($orderings) as $field => $ordering) { - $next = ClosureExpressionVisitor::sortByField($field, $ordering === Criteria::DESC ? -1 : 1, $next); - } - - uasort($filtered, $next); - } - - $offset = $criteria->getFirstResult(); - $length = $criteria->getMaxResults(); - - if ($offset || $length) { - $filtered = array_slice($filtered, (int) $offset, $length); - } - - return $this->createFrom($filtered); - } -} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php deleted file mode 100644 index adf4a3b..0000000 --- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Collection.php +++ /dev/null @@ -1,296 +0,0 @@ -ordered map 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 preferable. - * 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. - * - * @psalm-template TKey of array-key - * @psalm-template T - * @template-extends IteratorAggregate - * @template-extends ArrayAccess - */ -interface Collection extends Countable, IteratorAggregate, ArrayAccess -{ - /** - * Adds an element at the end of the collection. - * - * @param mixed $element The element to add. - * - * @return true Always TRUE. - * - * @psalm-param T $element - */ - public function add($element); - - /** - * Clears the collection, removing all elements. - * - * @return void - */ - public 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 bool TRUE if the collection contains the element, FALSE otherwise. - * - * @psalm-param T $element - */ - public function contains($element); - - /** - * Checks whether the collection is empty (contains no elements). - * - * @return bool TRUE if the collection is empty, FALSE otherwise. - */ - public function isEmpty(); - - /** - * Removes the element at the specified index from the collection. - * - * @param string|int $key The key/index of the element to remove. - * - * @return mixed The removed element or NULL, if the collection did not contain the element. - * - * @psalm-param TKey $key - * @psalm-return T|null - */ - public function remove($key); - - /** - * Removes the specified element from the collection, if it is found. - * - * @param mixed $element The element to remove. - * - * @return bool TRUE if this collection contained the specified element, FALSE otherwise. - * - * @psalm-param T $element - */ - public function removeElement($element); - - /** - * Checks whether the collection contains an element with the specified key/index. - * - * @param string|int $key The key/index to check for. - * - * @return bool TRUE if the collection contains an element with the specified key/index, - * FALSE otherwise. - * - * @psalm-param TKey $key - */ - public function containsKey($key); - - /** - * Gets the element at the specified key/index. - * - * @param string|int $key The key/index of the element to retrieve. - * - * @return mixed - * - * @psalm-param TKey $key - * @psalm-return T|null - */ - public function get($key); - - /** - * Gets all keys/indices of the collection. - * - * @return int[]|string[] The keys/indices of the collection, in the order of the corresponding - * elements in the collection. - * - * @psalm-return TKey[] - */ - public 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. - * - * @psalm-return T[] - */ - public function getValues(); - - /** - * Sets an element in the collection at the specified key/index. - * - * @param string|int $key The key/index of the element to set. - * @param mixed $value The element to set. - * - * @return void - * - * @psalm-param TKey $key - * @psalm-param T $value - */ - public function set($key, $value); - - /** - * Gets a native PHP array representation of the collection. - * - * @return array - * - * @psalm-return array - */ - public function toArray(); - - /** - * Sets the internal iterator to the first element in the collection and returns this element. - * - * @return mixed - * - * @psalm-return T|false - */ - public function first(); - - /** - * Sets the internal iterator to the last element in the collection and returns this element. - * - * @return mixed - * - * @psalm-return T|false - */ - public function last(); - - /** - * Gets the key/index of the element at the current iterator position. - * - * @return int|string - * - * @psalm-return TKey - */ - public function key(); - - /** - * Gets the element of the collection at the current iterator position. - * - * @return mixed - * - * @psalm-return T|false - */ - public function current(); - - /** - * Moves the internal iterator position to the next element and returns this element. - * - * @return mixed - * - * @psalm-return T|false - */ - public function next(); - - /** - * Tests for the existence of an element that satisfies the given predicate. - * - * @param Closure $p The predicate. - * - * @return bool TRUE if the predicate is TRUE for at least one element, FALSE otherwise. - * - * @psalm-param Closure(TKey=, T=):bool $p - */ - public 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. - * - * @psalm-param Closure(T=):bool $p - * @psalm-return Collection - */ - public function filter(Closure $p); - - /** - * Tests whether the given predicate p holds for all elements of this collection. - * - * @param Closure $p The predicate. - * - * @return bool TRUE, if the predicate yields TRUE for all elements, FALSE otherwise. - * - * @psalm-param Closure(TKey=, T=):bool $p - */ - public 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. - * - * @return Collection - * - * @psalm-template U - * @psalm-param Closure(T=):U $func - * @psalm-return Collection - */ - public 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 Collection[] 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. - * - * @psalm-param Closure(TKey=, T=):bool $p - * @psalm-return array{0: Collection, 1: Collection} - */ - public 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 int|string|bool The key/index of the element or FALSE if the element was not found. - * - * @psalm-param T $element - * @psalm-return TKey|false - */ - public function indexOf($element); - - /** - * Extracts 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 The offset to start from. - * @param int|null $length The maximum number of elements to return, or null for no limit. - * - * @return array - * - * @psalm-return array - */ - public function slice($offset, $length = null); -} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php deleted file mode 100644 index 6ddaf5e..0000000 --- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Criteria.php +++ /dev/null @@ -1,222 +0,0 @@ -expression = $expression; - - $this->setFirstResult($firstResult); - $this->setMaxResults($maxResults); - - if ($orderings === null) { - return; - } - - $this->orderBy($orderings); - } - - /** - * Sets the where expression to evaluate when this Criteria is searched for. - * - * @return Criteria - */ - public function where(Expression $expression) - { - $this->expression = $expression; - - return $this; - } - - /** - * Appends the where expression to evaluate when this Criteria is searched for - * using an AND with previous expression. - * - * @return Criteria - */ - public function andWhere(Expression $expression) - { - if ($this->expression === null) { - return $this->where($expression); - } - - $this->expression = new CompositeExpression( - CompositeExpression::TYPE_AND, - [$this->expression, $expression] - ); - - return $this; - } - - /** - * Appends the where expression to evaluate when this Criteria is searched for - * using an OR with previous expression. - * - * @return Criteria - */ - public function orWhere(Expression $expression) - { - if ($this->expression === null) { - return $this->where($expression); - } - - $this->expression = new CompositeExpression( - CompositeExpression::TYPE_OR, - [$this->expression, $expression] - ); - - return $this; - } - - /** - * Gets the expression attached to this Criteria. - * - * @return Expression|null - */ - public function getWhereExpression() - { - return $this->expression; - } - - /** - * Gets the current orderings of this Criteria. - * - * @return string[] - */ - public function getOrderings() - { - return $this->orderings; - } - - /** - * Sets the ordering of the result of this Criteria. - * - * Keys are field and values are the order, being either ASC or DESC. - * - * @see Criteria::ASC - * @see Criteria::DESC - * - * @param string[] $orderings - * - * @return Criteria - */ - public function orderBy(array $orderings) - { - $this->orderings = array_map( - static function (string $ordering) : string { - return strtoupper($ordering) === Criteria::ASC ? Criteria::ASC : Criteria::DESC; - }, - $orderings - ); - - return $this; - } - - /** - * Gets the current first result option of this Criteria. - * - * @return int|null - */ - public function getFirstResult() - { - return $this->firstResult; - } - - /** - * Set the number of first result that this Criteria should return. - * - * @param int|null $firstResult The value to set. - * - * @return Criteria - */ - public function setFirstResult($firstResult) - { - $this->firstResult = $firstResult === null ? null : (int) $firstResult; - - return $this; - } - - /** - * Gets maxResults. - * - * @return int|null - */ - public function getMaxResults() - { - return $this->maxResults; - } - - /** - * Sets maxResults. - * - * @param int|null $maxResults The value to set. - * - * @return Criteria - */ - public function setMaxResults($maxResults) - { - $this->maxResults = $maxResults === null ? null : (int) $maxResults; - - return $this; - } -} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php deleted file mode 100644 index 43e5cf1..0000000 --- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php +++ /dev/null @@ -1,257 +0,0 @@ -$accessor(); - } - } - - if (preg_match('/^is[A-Z]+/', $field) === 1 && method_exists($object, $field)) { - return $object->$field(); - } - - // __call should be triggered for get. - $accessor = $accessors[0] . $field; - - if (method_exists($object, '__call')) { - return $object->$accessor(); - } - - if ($object instanceof ArrayAccess) { - return $object[$field]; - } - - if (isset($object->$field)) { - return $object->$field; - } - - // camelcase field name to support different variable naming conventions - $ccField = preg_replace_callback('/_(.?)/', static function ($matches) { - return strtoupper($matches[1]); - }, $field); - - foreach ($accessors as $accessor) { - $accessor .= $ccField; - - if (method_exists($object, $accessor)) { - return $object->$accessor(); - } - } - - return $object->$field; - } - - /** - * Helper for sorting arrays of objects based on multiple fields + orientations. - * - * @param string $name - * @param int $orientation - * - * @return Closure - */ - public static function sortByField($name, $orientation = 1, ?Closure $next = null) - { - if (! $next) { - $next = static function () : int { - return 0; - }; - } - - return static function ($a, $b) use ($name, $next, $orientation) : int { - $aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name); - - $bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name); - - if ($aValue === $bValue) { - return $next($a, $b); - } - - return ($aValue > $bValue ? 1 : -1) * $orientation; - }; - } - - /** - * {@inheritDoc} - */ - public function walkComparison(Comparison $comparison) - { - $field = $comparison->getField(); - $value = $comparison->getValue()->getValue(); // shortcut for walkValue() - - switch ($comparison->getOperator()) { - case Comparison::EQ: - return static function ($object) use ($field, $value) : bool { - return ClosureExpressionVisitor::getObjectFieldValue($object, $field) === $value; - }; - - case Comparison::NEQ: - return static function ($object) use ($field, $value) : bool { - return ClosureExpressionVisitor::getObjectFieldValue($object, $field) !== $value; - }; - - case Comparison::LT: - return static function ($object) use ($field, $value) : bool { - return ClosureExpressionVisitor::getObjectFieldValue($object, $field) < $value; - }; - - case Comparison::LTE: - return static function ($object) use ($field, $value) : bool { - return ClosureExpressionVisitor::getObjectFieldValue($object, $field) <= $value; - }; - - case Comparison::GT: - return static function ($object) use ($field, $value) : bool { - return ClosureExpressionVisitor::getObjectFieldValue($object, $field) > $value; - }; - - case Comparison::GTE: - return static function ($object) use ($field, $value) : bool { - return ClosureExpressionVisitor::getObjectFieldValue($object, $field) >= $value; - }; - - case Comparison::IN: - return static function ($object) use ($field, $value) : bool { - return in_array(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value, true); - }; - - case Comparison::NIN: - return static function ($object) use ($field, $value) : bool { - return ! in_array(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value, true); - }; - - case Comparison::CONTAINS: - return static function ($object) use ($field, $value) { - return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) !== false; - }; - - case Comparison::MEMBER_OF: - return static function ($object) use ($field, $value) : bool { - $fieldValues = ClosureExpressionVisitor::getObjectFieldValue($object, $field); - - if (! is_array($fieldValues)) { - $fieldValues = iterator_to_array($fieldValues); - } - - return in_array($value, $fieldValues, true); - }; - - case Comparison::STARTS_WITH: - return static function ($object) use ($field, $value) : bool { - return strpos(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value) === 0; - }; - - case Comparison::ENDS_WITH: - return static function ($object) use ($field, $value) : bool { - return $value === substr(ClosureExpressionVisitor::getObjectFieldValue($object, $field), -strlen($value)); - }; - - default: - throw new RuntimeException('Unknown comparison operator: ' . $comparison->getOperator()); - } - } - - /** - * {@inheritDoc} - */ - public function walkValue(Value $value) - { - return $value->getValue(); - } - - /** - * {@inheritDoc} - */ - public function walkCompositeExpression(CompositeExpression $expr) - { - $expressionList = []; - - foreach ($expr->getExpressionList() as $child) { - $expressionList[] = $this->dispatch($child); - } - - switch ($expr->getType()) { - case CompositeExpression::TYPE_AND: - return $this->andExpressions($expressionList); - case CompositeExpression::TYPE_OR: - return $this->orExpressions($expressionList); - default: - throw new RuntimeException('Unknown composite ' . $expr->getType()); - } - } - - /** - * @param array $expressions - */ - private function andExpressions(array $expressions) : callable - { - return static function ($object) use ($expressions) : bool { - foreach ($expressions as $expression) { - if (! $expression($object)) { - return false; - } - } - - return true; - }; - } - - /** - * @param array $expressions - */ - private function orExpressions(array $expressions) : callable - { - return static function ($object) use ($expressions) : bool { - foreach ($expressions as $expression) { - if ($expression($object)) { - return true; - } - } - - return false; - }; - } -} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php deleted file mode 100644 index 13e193c..0000000 --- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Comparison.php +++ /dev/null @@ -1,80 +0,0 @@ -'; - public const LT = '<'; - public const LTE = '<='; - public const GT = '>'; - public const GTE = '>='; - public const IS = '='; // no difference with EQ - public const IN = 'IN'; - public const NIN = 'NIN'; - public const CONTAINS = 'CONTAINS'; - public const MEMBER_OF = 'MEMBER_OF'; - public const STARTS_WITH = 'STARTS_WITH'; - public const ENDS_WITH = 'ENDS_WITH'; - - /** @var string */ - private $field; - - /** @var string */ - private $op; - - /** @var Value */ - private $value; - - /** - * @param string $field - * @param string $operator - * @param mixed $value - */ - public function __construct($field, $operator, $value) - { - if (! ($value instanceof Value)) { - $value = new Value($value); - } - - $this->field = $field; - $this->op = $operator; - $this->value = $value; - } - - /** - * @return string - */ - public function getField() - { - return $this->field; - } - - /** - * @return Value - */ - public function getValue() - { - return $this->value; - } - - /** - * @return string - */ - public function getOperator() - { - return $this->op; - } - - /** - * {@inheritDoc} - */ - public function visit(ExpressionVisitor $visitor) - { - return $visitor->walkComparison($this); - } -} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php deleted file mode 100644 index e1f7114..0000000 --- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/CompositeExpression.php +++ /dev/null @@ -1,68 +0,0 @@ -type = $type; - - foreach ($expressions as $expr) { - if ($expr instanceof Value) { - throw new RuntimeException('Values are not supported expressions as children of and/or expressions.'); - } - if (! ($expr instanceof Expression)) { - throw new RuntimeException('No expression given to CompositeExpression.'); - } - - $this->expressions[] = $expr; - } - } - - /** - * Returns the list of expressions nested in this composite. - * - * @return Expression[] - */ - public function getExpressionList() - { - return $this->expressions; - } - - /** - * @return string - */ - public function getType() - { - return $this->type; - } - - /** - * {@inheritDoc} - */ - public function visit(ExpressionVisitor $visitor) - { - return $visitor->walkCompositeExpression($this); - } -} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php deleted file mode 100644 index f40d529..0000000 --- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Expression.php +++ /dev/null @@ -1,14 +0,0 @@ -walkComparison($expr); - case $expr instanceof Value: - return $this->walkValue($expr); - case $expr instanceof CompositeExpression: - return $this->walkCompositeExpression($expr); - default: - throw new RuntimeException('Unknown Expression ' . get_class($expr)); - } - } -} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php deleted file mode 100644 index 0830286..0000000 --- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/Expr/Value.php +++ /dev/null @@ -1,33 +0,0 @@ -value = $value; - } - - /** - * @return mixed - */ - public function getValue() - { - return $this->value; - } - - /** - * {@inheritDoc} - */ - public function visit(ExpressionVisitor $visitor) - { - return $visitor->walkValue($this); - } -} diff --git a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php b/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php deleted file mode 100644 index 4c0f5fd..0000000 --- a/vendor/doctrine/collections/lib/Doctrine/Common/Collections/ExpressionBuilder.php +++ /dev/null @@ -1,180 +0,0 @@ - - */ - public function matching(Criteria $criteria); -} diff --git a/vendor/doctrine/collections/psalm.xml.dist b/vendor/doctrine/collections/psalm.xml.dist deleted file mode 100644 index 8c5b066..0000000 --- a/vendor/doctrine/collections/psalm.xml.dist +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/doctrine/common/.doctrine-project.json b/vendor/doctrine/common/.doctrine-project.json deleted file mode 100644 index d29ce6d..0000000 --- a/vendor/doctrine/common/.doctrine-project.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "active": true, - "name": "Common", - "slug": "common", - "docsSlug": "doctrine-common", - "versions": [ - { - "name": "master", - "branchName": "master", - "slug": "latest" - }, - { - "name": "2.11", - "branchName": "2.11", - "current": true - } - ] -} diff --git a/vendor/doctrine/common/.github/FUNDING.yml b/vendor/doctrine/common/.github/FUNDING.yml deleted file mode 100644 index af1c7e7..0000000 --- a/vendor/doctrine/common/.github/FUNDING.yml +++ /dev/null @@ -1,3 +0,0 @@ -patreon: phpdoctrine -tidelift: packagist/doctrine%2Fcommon -custom: https://www.doctrine-project.org/sponsorship.html diff --git a/vendor/doctrine/common/LICENSE b/vendor/doctrine/common/LICENSE deleted file mode 100644 index 8c38cc1..0000000 --- a/vendor/doctrine/common/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006-2015 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/doctrine/common/README.md b/vendor/doctrine/common/README.md deleted file mode 100644 index 5cffb1a..0000000 --- a/vendor/doctrine/common/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Doctrine Common - -[![Build Status](https://secure.travis-ci.org/doctrine/common.png)](https://travis-ci.org/doctrine/common) - -The Doctrine Common project is a library that provides extensions to core PHP functionality. - -## More resources: - -* [Website](https://www.doctrine-project.org/) -* [Documentation](https://www.doctrine-project.org/projects/doctrine-common/en/latest/) -* [Downloads](https://github.com/doctrine/common/releases) diff --git a/vendor/doctrine/common/UPGRADE_TO_2_1 b/vendor/doctrine/common/UPGRADE_TO_2_1 deleted file mode 100644 index 891a2e5..0000000 --- a/vendor/doctrine/common/UPGRADE_TO_2_1 +++ /dev/null @@ -1,39 +0,0 @@ -This document details all the possible changes that you should investigate when updating -your project from Doctrine Common 2.0.x to 2.1 - -## AnnotationReader changes - -The annotation reader was heavily refactored between 2.0 and 2.1-RC1. In theory the operation of the new reader should be backwards compatible, but it has to be setup differently to work that way: - - $reader = new \Doctrine\Common\Annotations\AnnotationReader(); - $reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\'); - // new code necessary starting here - $reader->setIgnoreNotImportedAnnotations(true); - $reader->setEnableParsePhpImports(false); - $reader = new \Doctrine\Common\Annotations\CachedReader( - new \Doctrine\Common\Annotations\IndexedReader($reader), new ArrayCache() - ); - -## Annotation Base class or @Annotation - -Beginning after 2.1-RC2 you have to either extend ``Doctrine\Common\Annotations\Annotation`` or add @Annotation to your annotations class-level docblock, otherwise the class will simply be ignored. - -## Removed methods on AnnotationReader - -* AnnotationReader::setAutoloadAnnotations() -* AnnotationReader::getAutoloadAnnotations() -* AnnotationReader::isAutoloadAnnotations() - -## AnnotationRegistry - -Autoloading through the PHP autoloader is removed from the 2.1 AnnotationReader. Instead you have to use the global AnnotationRegistry for loading purposes: - - \Doctrine\Common\Annotations\AnnotationRegistry::registerFile($fileWithAnnotations); - \Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespace($namespace, $dirs = null); - \Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespaces($namespaces); - \Doctrine\Common\Annotations\AnnotationRegistry::registerLoader($callable); - -The $callable for registering a loader accepts a class as first and only parameter and must try to silently autoload it. On success true has to be returned. -The registerAutoloadNamespace function registers a PSR-0 compatible silent autoloader for all classes with the given namespace in the given directories. -If null is passed as directory the include path will be used. - diff --git a/vendor/doctrine/common/UPGRADE_TO_2_2 b/vendor/doctrine/common/UPGRADE_TO_2_2 deleted file mode 100644 index 1d93a13..0000000 --- a/vendor/doctrine/common/UPGRADE_TO_2_2 +++ /dev/null @@ -1,61 +0,0 @@ -This document details all the possible changes that you should investigate when -updating your project from Doctrine Common 2.1 to 2.2: - -## Annotation Changes - -- AnnotationReader::setIgnoreNotImportedAnnotations has been removed, you need to - add ignore annotation names which are supposed to be ignored via - AnnotationReader::addGlobalIgnoredName - -- AnnotationReader::setAutoloadAnnotations was deprecated by the AnnotationRegistry - in 2.1 and has been removed in 2.2 - -- AnnotationReader::setEnableParsePhpImports was added to ease transition to the new - annotation mechanism in 2.1 and is removed in 2.2 - -- AnnotationReader::isParsePhpImportsEnabled is removed (see above) - -- AnnotationReader::setDefaultAnnotationNamespace was deprecated in favor of explicit - configuration in 2.1 and will be removed in 2.2 (for isolated projects where you - have full-control over _all_ available annotations, we offer a dedicated reader - class ``SimpleAnnotationReader``) - -- AnnotationReader::setAnnotationCreationFunction was deprecated in 2.1 and will be - removed in 2.2. We only offer two creation mechanisms which cannot be changed - anymore to allow the same reader instance to work with all annotations regardless - of which library they are coming from. - -- AnnotationReader::setAnnotationNamespaceAlias was deprecated in 2.1 and will be - removed in 2.2 (see setDefaultAnnotationNamespace) - -- If you use a class as annotation which has not the @Annotation marker in it's - class block, we will now throw an exception instead of silently ignoring it. You - can however still achieve the previous behavior using the @IgnoreAnnotation, or - AnnotationReader::addGlobalIgnoredName (the exception message will contain detailed - instructions when you run into this problem). - -## Cache Changes - -- Renamed old AbstractCache to CacheProvider - -- Dropped the support to the following functions of all cache providers: - - - CacheProvider::deleteByWildcard - - - CacheProvider::deleteByRegEx - - - CacheProvider::deleteByPrefix - - - CacheProvider::deleteBySuffix - -- CacheProvider::deleteAll will not remove ALL entries, it will only mark them as invalid - -- CacheProvider::flushAll will remove ALL entries, namespaced or not - -- Added support to MemcachedCache - -- Added support to WincacheCache - -## ClassLoader Changes - -- ClassLoader::fileExistsInIncludePath() no longer exists. Use the native stream_resolve_include_path() PHP function \ No newline at end of file diff --git a/vendor/doctrine/common/composer.json b/vendor/doctrine/common/composer.json deleted file mode 100644 index ea158a2..0000000 --- a/vendor/doctrine/common/composer.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "doctrine/common", - "type": "library", - "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, persistence interfaces, proxies, event system and much more.", - "keywords": [ - "php", - "common", - "doctrine" - ], - "homepage": "https://www.doctrine-project.org/projects/common.html", - "license": "MIT", - "authors": [ - {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, - {"name": "Roman Borschel", "email": "roman@code-factory.org"}, - {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, - {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, - {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}, - {"name": "Marco Pivetta", "email": "ocramius@gmail.com"} - ], - "require": { - "php": "^7.1", - "doctrine/inflector": "^1.0", - "doctrine/cache": "^1.0", - "doctrine/collections": "^1.0", - "doctrine/lexer": "^1.0", - "doctrine/annotations": "^1.0", - "doctrine/event-manager": "^1.0", - "doctrine/reflection": "^1.0", - "doctrine/persistence": "^1.1" - }, - "require-dev": { - "phpstan/phpstan": "^0.11", - "phpstan/phpstan-phpunit": "^0.11", - "phpunit/phpunit": "^7.0", - "doctrine/coding-standard": "^1.0", - "squizlabs/php_codesniffer": "^3.0", - "symfony/phpunit-bridge": "^4.0.5" - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "autoload-dev": { - "psr-4": { - "Doctrine\\Tests\\": "tests/Doctrine/Tests" - } - }, - "extra": { - "branch-alias": { - "dev-master": "2.11.x-dev" - } - } -} diff --git a/vendor/doctrine/common/composer.lock b/vendor/doctrine/common/composer.lock deleted file mode 100644 index a5bb7ef..0000000 --- a/vendor/doctrine/common/composer.lock +++ /dev/null @@ -1,3433 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "40bcfe4c5277cdfa06868ad21fd26d85", - "packages": [ - { - "name": "doctrine/annotations", - "version": "v1.6.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", - "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", - "shasum": "" - }, - "require": { - "doctrine/lexer": "1.*", - "php": "^7.1" - }, - "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "^6.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "time": "2017-12-06T07:11:42+00:00" - }, - { - "name": "doctrine/cache", - "version": "v1.8.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/d768d58baee9a4862ca783840eca1b9add7a7f57", - "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57", - "shasum": "" - }, - "require": { - "php": "~7.1" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "alcaeus/mongo-php-adapter": "^1.1", - "doctrine/coding-standard": "^4.0", - "mongodb/mongodb": "^1.1", - "phpunit/phpunit": "^7.0", - "predis/predis": "~1.0" - }, - "suggest": { - "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Caching library offering an object-oriented API for many cache backends", - "homepage": "https://www.doctrine-project.org", - "keywords": [ - "cache", - "caching" - ], - "time": "2018-08-21T18:01:43+00:00" - }, - { - "name": "doctrine/collections", - "version": "v1.5.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/collections.git", - "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/a01ee38fcd999f34d9bfbcee59dbda5105449cbf", - "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "~0.1@dev", - "phpunit/phpunit": "^5.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Collections\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Collections Abstraction library", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "array", - "collections", - "iterator" - ], - "time": "2017-07-22T10:37:32+00:00" - }, - { - "name": "doctrine/event-manager", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/event-manager.git", - "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/a520bc093a0170feeb6b14e9d83f3a14452e64b3", - "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "conflict": { - "doctrine/common": "<2.9@dev" - }, - "require-dev": { - "doctrine/coding-standard": "^4.0", - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "Doctrine Event Manager component", - "homepage": "https://www.doctrine-project.org/projects/event-manager.html", - "keywords": [ - "event", - "eventdispatcher", - "eventmanager" - ], - "time": "2018-06-11T11:59:03+00:00" - }, - { - "name": "doctrine/inflector", - "version": "v1.3.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "5527a48b7313d15261292c149e55e26eae771b0a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", - "reference": "5527a48b7313d15261292c149e55e26eae771b0a", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^6.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Common String Manipulations with regard to casing and singular/plural rules.", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "inflection", - "pluralize", - "singularize", - "string" - ], - "time": "2018-01-09T20:05:19+00:00" - }, - { - "name": "doctrine/lexer", - "version": "v1.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Lexer\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "lexer", - "parser" - ], - "time": "2014-09-09T13:34:57+00:00" - }, - { - "name": "doctrine/persistence", - "version": "v1.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/persistence.git", - "reference": "c0f1c17602afc18b4cbd8e1c8125f264c9cf7d38" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/c0f1c17602afc18b4cbd8e1c8125f264c9cf7d38", - "reference": "c0f1c17602afc18b4cbd8e1c8125f264c9cf7d38", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.0", - "doctrine/cache": "^1.0", - "doctrine/collections": "^1.0", - "doctrine/event-manager": "^1.0", - "doctrine/reflection": "^1.0", - "php": "^7.1" - }, - "conflict": { - "doctrine/common": "<2.10@dev" - }, - "require-dev": { - "doctrine/coding-standard": "^5.0", - "phpstan/phpstan": "^0.8", - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", - "homepage": "https://doctrine-project.org/projects/persistence.html", - "keywords": [ - "mapper", - "object", - "odm", - "orm", - "persistence" - ], - "time": "2018-11-21T00:33:13+00:00" - }, - { - "name": "doctrine/reflection", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/reflection.git", - "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/reflection/zipball/02538d3f95e88eb397a5f86274deb2c6175c2ab6", - "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.0", - "ext-tokenizer": "*", - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "^4.0", - "doctrine/common": "^2.8", - "phpstan/phpstan": "^0.9.2", - "phpstan/phpstan-phpunit": "^0.9.4", - "phpunit/phpunit": "^7.0", - "squizlabs/php_codesniffer": "^3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "Doctrine Reflection component", - "homepage": "https://www.doctrine-project.org/projects/reflection.html", - "keywords": [ - "reflection" - ], - "time": "2018-06-14T14:45:07+00:00" - } - ], - "packages-dev": [ - { - "name": "composer/xdebug-handler", - "version": "1.3.2", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "d17708133b6c276d6e42ef887a877866b909d892" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/d17708133b6c276d6e42ef887a877866b909d892", - "reference": "d17708133b6c276d6e42ef887a877866b909d892", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0", - "psr/log": "^1.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "time": "2019-01-28T20:25:53+00:00" - }, - { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v0.4.4", - "source": { - "type": "git", - "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", - "reference": "2e41850d5f7797cbb1af7b030d245b3b24e63a08" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/2e41850d5f7797cbb1af7b030d245b3b24e63a08", - "reference": "2e41850d5f7797cbb1af7b030d245b3b24e63a08", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0", - "php": "^5.3|^7", - "squizlabs/php_codesniffer": "*" - }, - "require-dev": { - "composer/composer": "*", - "wimg/php-compatibility": "^8.0" - }, - "suggest": { - "dealerdirect/qa-tools": "All the PHP QA tools you'll need" - }, - "type": "composer-plugin", - "extra": { - "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Franck Nijhof", - "email": "f.nijhof@dealerdirect.nl", - "homepage": "http://workingatdealerdirect.eu", - "role": "Developer" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://workingatdealerdirect.eu", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "time": "2017-12-06T16:27:17+00:00" - }, - { - "name": "doctrine/coding-standard", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/coding-standard.git", - "reference": "d0af8acc36d69f315d550eef78a9607bba24a6da" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/coding-standard/zipball/d0af8acc36d69f315d550eef78a9607bba24a6da", - "reference": "d0af8acc36d69f315d550eef78a9607bba24a6da", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.2", - "php": "^7.1", - "squizlabs/php_codesniffer": "~3.0" - }, - "type": "phpcodesniffer-standard", - "extra": { - "branch-alias": { - "dev-master": "0.1-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Sniffs\\": "lib/Doctrine/Sniffs" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Steve Müller", - "email": "st.mueller@dzh-online.de" - } - ], - "description": "Doctrine Coding Standard", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "code", - "coding", - "cs", - "doctrine", - "sniffer", - "standard", - "style" - ], - "time": "2017-08-20T01:30:16+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "a2c590166b2133a4633738648b6b064edae0814a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a", - "reference": "a2c590166b2133a4633738648b6b064edae0814a", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.13", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-shim": "^0.11", - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "time": "2019-03-17T17:37:11+00:00" - }, - { - "name": "jean85/pretty-package-versions", - "version": "1.2", - "source": { - "type": "git", - "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/75c7effcf3f77501d0e0caa75111aff4daa0dd48", - "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48", - "shasum": "" - }, - "require": { - "ocramius/package-versions": "^1.2.0", - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Jean85\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alessandro Lai", - "email": "alessandro.lai85@gmail.com" - } - ], - "description": "A wrapper for ocramius/package-versions to get pretty versions strings", - "keywords": [ - "composer", - "package", - "release", - "versions" - ], - "time": "2018-06-13T13:22:40+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.9.3", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea", - "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "replace": { - "myclabs/deep-copy": "self.version" - }, - "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, - "files": [ - "src/DeepCopy/deep_copy.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "time": "2019-08-09T12:45:53+00:00" - }, - { - "name": "nette/bootstrap", - "version": "v2.4.6", - "source": { - "type": "git", - "url": "https://github.com/nette/bootstrap.git", - "reference": "268816e3f1bb7426c3a4ceec2bd38a036b532543" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/bootstrap/zipball/268816e3f1bb7426c3a4ceec2bd38a036b532543", - "reference": "268816e3f1bb7426c3a4ceec2bd38a036b532543", - "shasum": "" - }, - "require": { - "nette/di": "~2.4.7", - "nette/utils": "~2.4", - "php": ">=5.6.0" - }, - "conflict": { - "nette/nette": "<2.2" - }, - "require-dev": { - "latte/latte": "~2.2", - "nette/application": "~2.3", - "nette/caching": "~2.3", - "nette/database": "~2.3", - "nette/forms": "~2.3", - "nette/http": "~2.4.0", - "nette/mail": "~2.3", - "nette/robot-loader": "^2.4.2 || ^3.0", - "nette/safe-stream": "~2.2", - "nette/security": "~2.3", - "nette/tester": "~2.0", - "tracy/tracy": "^2.4.1" - }, - "suggest": { - "nette/robot-loader": "to use Configurator::createRobotLoader()", - "tracy/tracy": "to use Configurator::enableTracy()" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "? Nette Bootstrap: the simple way to configure and bootstrap your Nette application.", - "homepage": "https://nette.org", - "keywords": [ - "bootstrapping", - "configurator", - "nette" - ], - "time": "2018-05-17T12:52:20+00:00" - }, - { - "name": "nette/di", - "version": "v2.4.15", - "source": { - "type": "git", - "url": "https://github.com/nette/di.git", - "reference": "d0561b8f77e8ef2ed6d83328860e16c81a5a8649" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/di/zipball/d0561b8f77e8ef2ed6d83328860e16c81a5a8649", - "reference": "d0561b8f77e8ef2ed6d83328860e16c81a5a8649", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "nette/neon": "^2.3.3 || ~3.0.0", - "nette/php-generator": "^2.6.1 || ^3.0.0", - "nette/utils": "^2.5.0 || ~3.0.0", - "php": ">=5.6.0" - }, - "conflict": { - "nette/bootstrap": "<2.4", - "nette/nette": "<2.2" - }, - "require-dev": { - "nette/tester": "^2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.4-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "? Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP 7.1 features.", - "homepage": "https://nette.org", - "keywords": [ - "compiled", - "di", - "dic", - "factory", - "ioc", - "nette", - "static" - ], - "time": "2019-01-30T13:26:05+00:00" - }, - { - "name": "nette/finder", - "version": "v2.5.0", - "source": { - "type": "git", - "url": "https://github.com/nette/finder.git", - "reference": "6be1b83ea68ac558aff189d640abe242e0306fe2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/finder/zipball/6be1b83ea68ac558aff189d640abe242e0306fe2", - "reference": "6be1b83ea68ac558aff189d640abe242e0306fe2", - "shasum": "" - }, - "require": { - "nette/utils": "^2.4 || ~3.0.0", - "php": ">=7.1" - }, - "conflict": { - "nette/nette": "<2.2" - }, - "require-dev": { - "nette/tester": "^2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.5-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "🔍 Nette Finder: find files and directories with an intuitive API.", - "homepage": "https://nette.org", - "keywords": [ - "filesystem", - "glob", - "iterator", - "nette" - ], - "time": "2019-02-28T18:13:25+00:00" - }, - { - "name": "nette/neon", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/nette/neon.git", - "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/neon/zipball/cbff32059cbdd8720deccf9e9eace6ee516f02eb", - "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "ext-json": "*", - "php": ">=7.0" - }, - "require-dev": { - "nette/tester": "^2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "🍸 Nette NEON: encodes and decodes NEON file format.", - "homepage": "http://ne-on.org", - "keywords": [ - "export", - "import", - "neon", - "nette", - "yaml" - ], - "time": "2019-02-05T21:30:40+00:00" - }, - { - "name": "nette/php-generator", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/nette/php-generator.git", - "reference": "9de4e093a130f7a1bd175198799ebc0efbac6924" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/php-generator/zipball/9de4e093a130f7a1bd175198799ebc0efbac6924", - "reference": "9de4e093a130f7a1bd175198799ebc0efbac6924", - "shasum": "" - }, - "require": { - "nette/utils": "^2.4.2 || ~3.0.0", - "php": ">=7.1" - }, - "conflict": { - "nette/nette": "<2.2" - }, - "require-dev": { - "nette/tester": "^2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "? Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.3 features.", - "homepage": "https://nette.org", - "keywords": [ - "code", - "nette", - "php", - "scaffolding" - ], - "time": "2018-11-27T19:00:14+00:00" - }, - { - "name": "nette/robot-loader", - "version": "v3.1.1", - "source": { - "type": "git", - "url": "https://github.com/nette/robot-loader.git", - "reference": "3e8d75d6d976e191bdf46752ca40a286671219d2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/robot-loader/zipball/3e8d75d6d976e191bdf46752ca40a286671219d2", - "reference": "3e8d75d6d976e191bdf46752ca40a286671219d2", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "nette/finder": "^2.3 || ^3.0", - "nette/utils": "^2.4 || ^3.0", - "php": ">=5.6.0" - }, - "conflict": { - "nette/nette": "<2.2" - }, - "require-dev": { - "nette/tester": "^2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "? Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.", - "homepage": "https://nette.org", - "keywords": [ - "autoload", - "class", - "interface", - "nette", - "trait" - ], - "time": "2019-03-01T20:23:02+00:00" - }, - { - "name": "nette/utils", - "version": "v2.5.3", - "source": { - "type": "git", - "url": "https://github.com/nette/utils.git", - "reference": "17b9f76f2abd0c943adfb556e56f2165460b15ce" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/17b9f76f2abd0c943adfb556e56f2165460b15ce", - "reference": "17b9f76f2abd0c943adfb556e56f2165460b15ce", - "shasum": "" - }, - "require": { - "php": ">=5.6.0" - }, - "conflict": { - "nette/nette": "<2.2" - }, - "require-dev": { - "nette/tester": "~2.0", - "tracy/tracy": "^2.3" - }, - "suggest": { - "ext-gd": "to use Image", - "ext-iconv": "to use Strings::webalize() and toAscii()", - "ext-intl": "for script transliteration in Strings::webalize() and toAscii()", - "ext-json": "to use Nette\\Utils\\Json", - "ext-mbstring": "to use Strings::lower() etc...", - "ext-xml": "to use Strings::length() etc. when mbstring is not available" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.5-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ], - "files": [ - "src/loader.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "? Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", - "homepage": "https://nette.org", - "keywords": [ - "array", - "core", - "datetime", - "images", - "json", - "nette", - "paginator", - "password", - "slugify", - "string", - "unicode", - "utf-8", - "utility", - "validation" - ], - "time": "2018-09-18T10:22:16+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.2.1", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "5221f49a608808c1e4d436df32884cbc1b821ac0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/5221f49a608808c1e4d436df32884cbc1b821ac0", - "reference": "5221f49a608808c1e4d436df32884cbc1b821ac0", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.5 || ^7.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "time": "2019-02-16T20:54:15+00:00" - }, - { - "name": "ocramius/package-versions", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/Ocramius/PackageVersions.git", - "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", - "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0.0", - "php": "^7.1.0" - }, - "require-dev": { - "composer/composer": "^1.6.3", - "doctrine/coding-standard": "^5.0.1", - "ext-zip": "*", - "infection/infection": "^0.7.1", - "phpunit/phpunit": "^7.0.0" - }, - "type": "composer-plugin", - "extra": { - "class": "PackageVersions\\Installer", - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "PackageVersions\\": "src/PackageVersions" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "time": "2019-02-21T12:16:21+00:00" - }, - { - "name": "phar-io/manifest", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "phar-io/version": "^2.0", - "php": "^5.6 || ^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2018-07-08T19:23:20+00:00" - }, - { - "name": "phar-io/version", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "time": "2018-07-08T19:19:57+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "^4.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "time": "2017-09-11T18:02:19+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "4.3.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", - "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", - "shasum": "" - }, - "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "doctrine/instantiator": "~1.0.5", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-04-30T17:48:53+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "0.4.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", - "shasum": "" - }, - "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "time": "2017-07-14T14:27:02+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "1.8.1", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76", - "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" - }, - "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2019-06-13T12:50:23+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "0.3.1", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "2cc49f47c69b023eaf05b48e6529389893b13d74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/2cc49f47c69b023eaf05b48e6529389893b13d74", - "reference": "2cc49f47c69b023eaf05b48e6529389893b13d74", - "shasum": "" - }, - "require": { - "php": "~7.1" - }, - "require-dev": { - "consistence/coding-standard": "^2.0.0", - "jakub-onderka/php-parallel-lint": "^0.9.2", - "phing/phing": "^2.16.0", - "phpstan/phpstan": "^0.10", - "phpunit/phpunit": "^6.3", - "slevomat/coding-standard": "^3.3.0", - "symfony/process": "^3.4 || ^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.3-dev" - } - }, - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "time": "2019-01-14T12:26:23+00:00" - }, - { - "name": "phpstan/phpstan", - "version": "0.11.3", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "e4644b4a8fd393c346f1137305fb2f76a7dc20a7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e4644b4a8fd393c346f1137305fb2f76a7dc20a7", - "reference": "e4644b4a8fd393c346f1137305fb2f76a7dc20a7", - "shasum": "" - }, - "require": { - "composer/xdebug-handler": "^1.3.0", - "jean85/pretty-package-versions": "^1.0.3", - "nette/bootstrap": "^2.4 || ^3.0", - "nette/di": "^2.4.7 || ^3.0", - "nette/robot-loader": "^3.0.1", - "nette/utils": "^2.4.5 || ^3.0", - "nikic/php-parser": "^4.0.2", - "php": "~7.1", - "phpstan/phpdoc-parser": "^0.3", - "symfony/console": "~3.2 || ~4.0", - "symfony/finder": "~3.2 || ~4.0" - }, - "conflict": { - "symfony/console": "3.4.16 || 4.1.5" - }, - "require-dev": { - "brianium/paratest": "^2.0", - "consistence/coding-standard": "^3.5", - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4", - "ext-intl": "*", - "ext-mysqli": "*", - "ext-soap": "*", - "ext-zip": "*", - "jakub-onderka/php-parallel-lint": "^1.0", - "localheinz/composer-normalize": "^1.1.0", - "phing/phing": "^2.16.0", - "phpstan/phpstan-deprecation-rules": "^0.11", - "phpstan/phpstan-php-parser": "^0.11", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-strict-rules": "^0.11", - "phpunit/phpunit": "^7.0", - "slevomat/coding-standard": "^4.7.2", - "squizlabs/php_codesniffer": "^3.3.2" - }, - "bin": [ - "bin/phpstan" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.11-dev" - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": [ - "src/", - "build/PHPStan" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", - "time": "2019-03-10T16:25:30+00:00" - }, - { - "name": "phpstan/phpstan-phpunit", - "version": "0.11", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "70c22d44b96a21a4952fc13021a5a63cc83f5c81" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/70c22d44b96a21a4952fc13021a5a63cc83f5c81", - "reference": "70c22d44b96a21a4952fc13021a5a63cc83f5c81", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.0", - "php": "~7.1", - "phpstan/phpdoc-parser": "^0.3", - "phpstan/phpstan": "^0.11" - }, - "conflict": { - "phpunit/phpunit": "<7.0" - }, - "require-dev": { - "consistence/coding-standard": "^3.0.1", - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4", - "jakub-onderka/php-parallel-lint": "^1.0", - "phing/phing": "^2.16.0", - "phpstan/phpstan-strict-rules": "^0.11", - "phpunit/phpunit": "^7.0", - "satooshi/php-coveralls": "^1.0", - "slevomat/coding-standard": "^4.5.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.11-dev" - } - }, - "autoload": { - "psr-4": { - "PHPStan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPUnit extensions and rules for PHPStan", - "time": "2018-12-22T14:05:04+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "6.1.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-xmlwriter": "*", - "php": "^7.1", - "phpunit/php-file-iterator": "^2.0", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.0", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.1 || ^4.0", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "suggest": { - "ext-xdebug": "^2.6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2018-10-31T16:06:48+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "050bedf145a257b1ff02746c31894800e5122946" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", - "reference": "050bedf145a257b1ff02746c31894800e5122946", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2018-09-13T20:33:42+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21T13:50:34+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "2.1.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2019-06-07T04:22:29+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "3.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e899757bb3df5ff6e95089132f32cd59aac2220a", - "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2019-07-25T05:29:42+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "7.5.15", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "d79c053d972856b8b941bb233e39dc521a5093f0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d79c053d972856b8b941bb233e39dc521a5093f0", - "reference": "d79c053d972856b8b941bb233e39dc521a5093f0", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.1", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "myclabs/deep-copy": "^1.7", - "phar-io/manifest": "^1.0.2", - "phar-io/version": "^2.0", - "php": "^7.1", - "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^6.0.7", - "phpunit/php-file-iterator": "^2.0.1", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1", - "sebastian/comparator": "^3.0", - "sebastian/diff": "^3.0", - "sebastian/environment": "^4.0", - "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^2.0", - "sebastian/version": "^2.0.1" - }, - "conflict": { - "phpunit/phpunit-mock-objects": "*" - }, - "require-dev": { - "ext-pdo": "*" - }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*", - "phpunit/php-invoker": "^2.0" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "7.5-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2019-08-21T07:05:16+00:00" - }, - { - "name": "psr/log", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2018-11-20T15:27:04+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" - }, - { - "name": "sebastian/comparator", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", - "shasum": "" - }, - "require": { - "php": "^7.1", - "sebastian/diff": "^3.0", - "sebastian/exporter": "^3.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2018-07-12T15:12:46+00:00" - }, - { - "name": "sebastian/diff", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.0", - "symfony/process": "^2 || ^3.3 || ^4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "time": "2019-02-04T06:01:07+00:00" - }, - { - "name": "sebastian/environment", - "version": "4.2.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404", - "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.5" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "time": "2019-05-05T09:05:15+00:00" - }, - { - "name": "sebastian/exporter", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "06a9a5947f47b3029d76118eb5c22802e5869687" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/06a9a5947f47b3029d76118eb5c22802e5869687", - "reference": "06a9a5947f47b3029d76118eb5c22802e5869687", - "shasum": "" - }, - "require": { - "php": "^7.0", - "sebastian/recursion-context": "^3.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "time": "2019-08-11T12:43:14+00:00" - }, - { - "name": "sebastian/global-state", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "time": "2017-04-27T15:39:26+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "shasum": "" - }, - "require": { - "php": "^7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-08-03T12:35:26+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "773f97c67f28de00d397be301821b06708fca0be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", - "reference": "773f97c67f28de00d397be301821b06708fca0be", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29T09:07:27+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03T06:23:57+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", - "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2018-10-04T04:07:39+00:00" - }, - { - "name": "sebastian/version", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.4.0", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "379deb987e26c7cd103a7b387aea178baec96e48" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/379deb987e26c7cd103a7b387aea178baec96e48", - "reference": "379deb987e26c7cd103a7b387aea178baec96e48", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", - "keywords": [ - "phpcs", - "standards" - ], - "time": "2018-12-19T23:57:18+00:00" - }, - { - "name": "symfony/console", - "version": "v4.2.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "9dc2299a016497f9ee620be94524e6c0af0280a9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/9dc2299a016497f9ee620be94524e6c0af0280a9", - "reference": "9dc2299a016497f9ee620be94524e6c0af0280a9", - "shasum": "" - }, - "require": { - "php": "^7.1.3", - "symfony/contracts": "^1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/process": "<3.3" - }, - "provide": { - "psr/log-implementation": "1.0" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~3.4|~4.0", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.4|~4.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2019-02-23T15:17:42+00:00" - }, - { - "name": "symfony/contracts", - "version": "v1.0.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/contracts.git", - "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/contracts/zipball/1aa7ab2429c3d594dd70689604b5cf7421254cdf", - "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf", - "shasum": "" - }, - "require": { - "php": "^7.1.3" - }, - "require-dev": { - "psr/cache": "^1.0", - "psr/container": "^1.0" - }, - "suggest": { - "psr/cache": "When using the Cache contracts", - "psr/container": "When using the Service contracts", - "symfony/cache-contracts-implementation": "", - "symfony/service-contracts-implementation": "", - "symfony/translation-contracts-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\": "" - }, - "exclude-from-classmap": [ - "**/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A set of abstractions extracted out of the Symfony components", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "time": "2018-12-05T08:06:11+00:00" - }, - { - "name": "symfony/finder", - "version": "v4.2.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "267b7002c1b70ea80db0833c3afe05f0fbde580a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/267b7002c1b70ea80db0833c3afe05f0fbde580a", - "reference": "267b7002c1b70ea80db0833c3afe05f0fbde580a", - "shasum": "" - }, - "require": { - "php": "^7.1.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Finder Component", - "homepage": "https://symfony.com", - "time": "2019-02-23T15:42:05+00:00" - }, - { - "name": "symfony/phpunit-bridge", - "version": "v4.2.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "2cc651a38fcb831a405c14fcb76fcb00320e7ee8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/2cc651a38fcb831a405c14fcb76fcb00320e7ee8", - "reference": "2cc651a38fcb831a405c14fcb76fcb00320e7ee8", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "conflict": { - "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" - }, - "suggest": { - "symfony/debug": "For tracking deprecated interfaces usages at runtime with DebugClassLoader" - }, - "bin": [ - "bin/simple-phpunit" - ], - "type": "symfony-bridge", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - }, - "thanks": { - "name": "phpunit/phpunit", - "url": "https://github.com/sebastianbergmann/phpunit" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Bridge\\PhpUnit\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony PHPUnit Bridge", - "homepage": "https://symfony.com", - "time": "2019-02-18T06:49:49+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.12.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "550ebaac289296ce228a706d0867afc34687e3f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", - "reference": "550ebaac289296ce228a706d0867afc34687e3f4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.12-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "time": "2019-08-06T08:03:45+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.10.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", - "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "time": "2018-09-21T13:07:52+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.1.3", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", - "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "role": "Developer", - "email": "arne@blankerts.de" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "time": "2019-06-13T22:48:21+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.5.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4", - "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0", - "symfony/polyfill-ctype": "^1.8" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "time": "2019-08-24T08:43:50+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^7.1" - }, - "platform-dev": [] -} diff --git a/vendor/doctrine/common/docs/en/index.rst b/vendor/doctrine/common/docs/en/index.rst deleted file mode 100644 index 7550d8b..0000000 --- a/vendor/doctrine/common/docs/en/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -Common Documentation -==================== - -Welcome to the Doctrine Common Library documentation. - -.. toctree:: - :depth: 2 - :glob: - - * diff --git a/vendor/doctrine/common/docs/en/reference/class-loading.rst b/vendor/doctrine/common/docs/en/reference/class-loading.rst deleted file mode 100644 index e193b46..0000000 --- a/vendor/doctrine/common/docs/en/reference/class-loading.rst +++ /dev/null @@ -1,242 +0,0 @@ -Class Loading -============= - -Class loading is an essential part of any PHP application that -makes heavy use of classes and interfaces. Unfortunately, a lot of -people and projects spend a lot of time and effort on custom and -specialized class loading strategies. It can quickly become a pain -to understand what is going on when using multiple libraries and/or -frameworks, each with its own way to do class loading. Class -loading should be simple and it is an ideal candidate for -convention over configuration. - -Overview --------- - -The Doctrine Common ClassLoader implements a simple and efficient -approach to class loading that is easy to understand and use. The -implementation is based on the widely used and accepted convention -of mapping namespace and class names to a directory structure. This -approach is used for example by Symfony2, the Zend Framework and of -course, Doctrine. - -For example, the following class: - -.. code-block:: php - - register(); - $dbalLoader->register(); - $ormLoader->register(); - -Do not be afraid of using multiple class loaders. Due to the -efficient class loading design you will not incur much overhead -from using many class loaders. Take a look at the implementation of -``ClassLoader#loadClass`` to see how simple and efficient the class -loading is. The iteration over the installed class loaders happens -in C (with the exception of using ``ClassLoader::classExists``). - -A ClassLoader can be used in the following other variations, -however, these are rarely used/needed: - - -- If only the second argument is not supplied, the class loader - will be responsible for the namespace prefix given in the first - argument and it will rely on the PHP include_path. - -- If only the first argument is not supplied, the class loader - will be responsible for *all* classes and it will try to look up - *all* classes starting at the directory given as the second - argument. - -- If both arguments are not supplied, the class loader will be - responsible for *all* classes and it will rely on the PHP - include_path. - - -File Extension --------------- - -By default, a ClassLoader uses the ``.php`` file extension for all -class files. You can change this behavior, for example to use a -ClassLoader to load classes from a library that uses the -".class.php" convention (but it must nevertheless adhere to the -directory structure convention!): - -.. code-block:: php - - setFileExtension('.class.php'); - $customLoader->register(); - -Namespace Separator -------------------- - -By default, a ClassLoader uses the ``\`` namespace separator. You -can change this behavior, for example to use a ClassLoader to load -legacy Zend Framework classes that still use the underscore "_" -separator: - -.. code-block:: php - - setNamespaceSeparator('_'); - $zend1Loader->register(); - -Failing Silently and class_exists ----------------------------------- - -A lot of class/autoloaders these days try to fail silently when a -class file is not found. For the most part this is necessary in -order to support using ``class_exists('ClassName', true)`` which is -supposed to return a boolean value but triggers autoloading. This -is a bad thing as it basically forces class loaders to fail -silently, which in turn requires costly file_exists or fopen calls -for each class being loaded, even though in at least 99% of the -cases this is not necessary (compare the number of -class_exists(..., true) invocations to the total number of classes -being loaded in a request). - -The Doctrine Common ClassLoader does not fail silently, by design. -It therefore does not need any costly checks for file existence. A -ClassLoader is always responsible for all classes with a certain -namespace prefix and if a class is requested to be loaded and can -not be found this is considered to be a fatal error. This also -means that using class_exists(..., true) to check for class -existence when using a Doctrine Common ClassLoader is not possible -but this is not a bad thing. What class\_exists(..., true) actually -means is two things: 1) Check whether the class is already -defined/exists (i.e. class_exists(..., false)) and if not 2) check -whether a class file can be loaded for that class. In the Doctrine -Common ClassLoader the two responsibilities of loading a class and -checking for its existence are separated, which can be observed by -the existence of the two methods ``loadClass`` and -``canLoadClass``. Thereby ``loadClass`` does not invoke -``canLoadClass`` internally, by design. However, you are free to -use it yourself to check whether a class can be loaded and the -following code snippet is thus equivalent to class\_exists(..., -true): - -.. code-block:: php - - canLoadClass('Foo')) { - // ... - } - -The only problem with this is that it is inconvenient as you need -to have a reference to the class loaders around (and there are -often multiple class loaders in use). Therefore, a simpler -alternative exists for the cases in which you really want to ask -all installed class loaders whether they can load the class: -``ClassLoader::classExists($className)``: - -.. code-block:: php - - ClassLoader 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 include_path. - * - * @author Roman Borschel - * @since 2.0 - * - * @deprecated The ClassLoader is deprecated and will be removed in version 3.0 of doctrine/common. - */ -class ClassLoader -{ - /** - * PHP file extension. - * - * @var string - */ - protected $fileExtension = '.php'; - - /** - * Current namespace. - * - * @var string|null - */ - protected $namespace; - - /** - * Current include path. - * - * @var string|null - */ - protected $includePath; - - /** - * PHP namespace separator. - * - * @var string - */ - protected $namespaceSeparator = '\\'; - - /** - * Creates a new ClassLoader 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|null $ns The namespace of the classes to load. - * @param string|null $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. - * - * @return void - */ - 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|null $includePath - * - * @return void - */ - public function setIncludePath($includePath) - { - $this->includePath = $includePath; - } - - /** - * Gets the base include path for all class files in the namespace of this ClassLoader. - * - * @return string|null - */ - public function getIncludePath() - { - return $this->includePath; - } - - /** - * Sets the file extension of class files in the namespace of this ClassLoader. - * - * @param string $fileExtension - * - * @return void - */ - 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. - * - * @return void - */ - public function register() - { - spl_autoload_register([$this, 'loadClass']); - } - - /** - * Removes this ClassLoader from the SPL autoload stack. - * - * @return void - */ - public function unregister() - { - spl_autoload_unregister([$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 (self::typeExists($className)) { - return true; - } - - if ( ! $this->canLoadClass($className)) { - return false; - } - - require($this->includePath !== null ? $this->includePath . DIRECTORY_SEPARATOR : '') - . str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className) - . $this->fileExtension; - - return self::typeExists($className); - } - - /** - * 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; - } - - $file = str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className) . $this->fileExtension; - - if ($this->includePath !== null) { - return is_file($this->includePath . DIRECTORY_SEPARATOR . $file); - } - - return (false !== stream_resolve_include_path($file)); - } - - /** - * 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 ClassLoader, {@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 ClassLoader, 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) - { - return self::typeExists($className, true); - } - - /** - * Gets the ClassLoader 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 ClassLoader|null The ClassLoader for the class or NULL if no such ClassLoader exists. - */ - public static function getClassLoader($className) - { - foreach (spl_autoload_functions() as $loader) { - if (is_array($loader) - && ($classLoader = reset($loader)) - && $classLoader instanceof ClassLoader - && $classLoader->canLoadClass($className) - ) { - return $classLoader; - } - } - - return null; - } - - /** - * Checks whether a given type exists - * - * @param string $type - * @param bool $autoload - * - * @return bool - */ - private static function typeExists($type, $autoload = false) - { - return class_exists($type, $autoload) - || interface_exists($type, $autoload) - || trait_exists($type, $autoload); - } -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/CommonException.php b/vendor/doctrine/common/lib/Doctrine/Common/CommonException.php deleted file mode 100644 index bf60621..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/CommonException.php +++ /dev/null @@ -1,13 +0,0 @@ - - * @author Guilherme Blanco - */ -interface Comparable -{ - /** - * Compares the current object to the passed $other. - * - * Returns 0 if they are semantically equal, 1 if the other object - * is less than the current one, or -1 if its more than the current one. - * - * This method should not check for identity using ===, only for semantical equality for example - * when two different DateTime instances point to the exact same Date + TZ. - * - * @param mixed $other - * - * @return int - */ - public function compareTo($other); -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Lexer.php b/vendor/doctrine/common/lib/Doctrine/Common/Lexer.php deleted file mode 100644 index 8f92c26..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/Lexer.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @author Jonathan Wage - * @author Roman Borschel - * - * @deprecated Use Doctrine\Common\Lexer\AbstractLexer from doctrine/lexer package instead. - */ -abstract class Lexer extends AbstractLexer -{ -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php deleted file mode 100644 index 00879fc..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php +++ /dev/null @@ -1,245 +0,0 @@ - - * - * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. - */ -abstract class AbstractProxyFactory -{ - /** - * Never autogenerate a proxy and rely that it was generated by some - * process before deployment. - * - * @var integer - */ - const AUTOGENERATE_NEVER = 0; - - /** - * Always generates a new proxy in every request. - * - * This is only sane during development. - * - * @var integer - */ - const AUTOGENERATE_ALWAYS = 1; - - /** - * Autogenerate the proxy class when the proxy file does not exist. - * - * This strategy causes a file exists call whenever any proxy is used the - * first time in a request. - * - * @var integer - */ - const AUTOGENERATE_FILE_NOT_EXISTS = 2; - - /** - * Generate the proxy classes using eval(). - * - * This strategy is only sane for development, and even then it gives me - * the creeps a little. - * - * @var integer - */ - const AUTOGENERATE_EVAL = 3; - - private const AUTOGENERATE_MODES = [ - self::AUTOGENERATE_NEVER, - self::AUTOGENERATE_ALWAYS, - self::AUTOGENERATE_FILE_NOT_EXISTS, - self::AUTOGENERATE_EVAL, - ]; - - /** - * @var \Doctrine\Common\Persistence\Mapping\ClassMetadataFactory - */ - private $metadataFactory; - - /** - * @var \Doctrine\Common\Proxy\ProxyGenerator the proxy generator responsible for creating the proxy classes/files. - */ - private $proxyGenerator; - - /** - * @var int Whether to automatically (re)generate proxy classes. - */ - private $autoGenerate; - - /** - * @var \Doctrine\Common\Proxy\ProxyDefinition[] - */ - private $definitions = []; - - /** - * @param \Doctrine\Common\Proxy\ProxyGenerator $proxyGenerator - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadataFactory $metadataFactory - * @param bool|int $autoGenerate - * - * @throws \Doctrine\Common\Proxy\Exception\InvalidArgumentException When auto generate mode is not valid. - */ - public function __construct(ProxyGenerator $proxyGenerator, ClassMetadataFactory $metadataFactory, $autoGenerate) - { - $this->proxyGenerator = $proxyGenerator; - $this->metadataFactory = $metadataFactory; - $this->autoGenerate = (int) $autoGenerate; - - if ( ! in_array($this->autoGenerate, self::AUTOGENERATE_MODES, true)) { - throw InvalidArgumentException::invalidAutoGenerateMode($autoGenerate); - } - } - - /** - * Gets a reference proxy instance for the entity of the given type and identified by - * the given identifier. - * - * @param string $className - * @param array $identifier - * - * @return \Doctrine\Common\Proxy\Proxy - * - * @throws \Doctrine\Common\Proxy\Exception\OutOfBoundsException - */ - public function getProxy($className, array $identifier) - { - $definition = isset($this->definitions[$className]) - ? $this->definitions[$className] - : $this->getProxyDefinition($className); - $fqcn = $definition->proxyClassName; - $proxy = new $fqcn($definition->initializer, $definition->cloner); - - foreach ($definition->identifierFields as $idField) { - if ( ! isset($identifier[$idField])) { - throw OutOfBoundsException::missingPrimaryKeyValue($className, $idField); - } - - $definition->reflectionFields[$idField]->setValue($proxy, $identifier[$idField]); - } - - return $proxy; - } - - /** - * Generates proxy classes for all given classes. - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata[] $classes The classes (ClassMetadata instances) - * for which to generate proxies. - * @param string $proxyDir The target directory of the proxy classes. If not specified, the - * directory configured on the Configuration of the EntityManager used - * by this factory is used. - * @return int Number of generated proxies. - */ - public function generateProxyClasses(array $classes, $proxyDir = null) - { - $generated = 0; - - foreach ($classes as $class) { - if ($this->skipClass($class)) { - continue; - } - - $proxyFileName = $this->proxyGenerator->getProxyFileName($class->getName(), $proxyDir); - - $this->proxyGenerator->generateProxyClass($class, $proxyFileName); - - $generated += 1; - } - - return $generated; - } - - /** - * Reset initialization/cloning logic for an un-initialized proxy - * - * @param \Doctrine\Common\Proxy\Proxy $proxy - * - * @return \Doctrine\Common\Proxy\Proxy - * - * @throws \Doctrine\Common\Proxy\Exception\InvalidArgumentException - */ - public function resetUninitializedProxy(Proxy $proxy) - { - if ($proxy->__isInitialized()) { - throw InvalidArgumentException::unitializedProxyExpected($proxy); - } - - $className = ClassUtils::getClass($proxy); - $definition = isset($this->definitions[$className]) - ? $this->definitions[$className] - : $this->getProxyDefinition($className); - - $proxy->__setInitializer($definition->initializer); - $proxy->__setCloner($definition->cloner); - - return $proxy; - } - - /** - * Get a proxy definition for the given class name. - * - * @param string $className - * - * @return ProxyDefinition - */ - private function getProxyDefinition($className) - { - $classMetadata = $this->metadataFactory->getMetadataFor($className); - $className = $classMetadata->getName(); // aliases and case sensitivity - - $this->definitions[$className] = $this->createProxyDefinition($className); - $proxyClassName = $this->definitions[$className]->proxyClassName; - - if ( ! class_exists($proxyClassName, false)) { - $fileName = $this->proxyGenerator->getProxyFileName($className); - - switch ($this->autoGenerate) { - case self::AUTOGENERATE_NEVER: - require $fileName; - break; - - case self::AUTOGENERATE_FILE_NOT_EXISTS: - if ( ! file_exists($fileName)) { - $this->proxyGenerator->generateProxyClass($classMetadata, $fileName); - } - require $fileName; - break; - - case self::AUTOGENERATE_ALWAYS: - $this->proxyGenerator->generateProxyClass($classMetadata, $fileName); - require $fileName; - break; - - case self::AUTOGENERATE_EVAL: - $this->proxyGenerator->generateProxyClass($classMetadata, false); - break; - } - } - - return $this->definitions[$className]; - } - - /** - * Determine if this class should be skipped during proxy generation. - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $metadata - * - * @return bool - */ - abstract protected function skipClass(ClassMetadata $metadata); - - /** - * @param string $className - * - * @return ProxyDefinition - */ - abstract protected function createProxyDefinition($className); -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Autoloader.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Autoloader.php deleted file mode 100644 index f5a08d7..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Autoloader.php +++ /dev/null @@ -1,82 +0,0 @@ - - * - * @internal - * - * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. - */ -class Autoloader -{ - /** - * Resolves proxy class name to a filename based on the following pattern. - * - * 1. Remove Proxy namespace from class name. - * 2. Remove namespace separators from remaining class name. - * 3. Return PHP filename from proxy-dir with the result from 2. - * - * @param string $proxyDir - * @param string $proxyNamespace - * @param string $className - * - * @return string - * - * @throws InvalidArgumentException - */ - public static function resolveFile($proxyDir, $proxyNamespace, $className) - { - if (0 !== strpos($className, $proxyNamespace)) { - throw InvalidArgumentException::notProxyClass($className, $proxyNamespace); - } - - // remove proxy namespace from class name - $classNameRelativeToProxyNamespace = substr($className, strlen($proxyNamespace)); - - // remove namespace separators from remaining class name - $fileName = str_replace('\\', '', $classNameRelativeToProxyNamespace); - - return $proxyDir . DIRECTORY_SEPARATOR . $fileName . '.php'; - } - - /** - * Registers and returns autoloader callback for the given proxy dir and namespace. - * - * @param string $proxyDir - * @param string $proxyNamespace - * @param callable|null $notFoundCallback Invoked when the proxy file is not found. - * - * @return \Closure - * - * @throws InvalidArgumentException - */ - public static function register($proxyDir, $proxyNamespace, $notFoundCallback = null) - { - $proxyNamespace = ltrim($proxyNamespace, '\\'); - - if ( ! (null === $notFoundCallback || is_callable($notFoundCallback))) { - throw InvalidArgumentException::invalidClassNotFoundCallback($notFoundCallback); - } - - $autoloader = function ($className) use ($proxyDir, $proxyNamespace, $notFoundCallback) { - if (0 === strpos($className, $proxyNamespace)) { - $file = Autoloader::resolveFile($proxyDir, $proxyNamespace, $className); - - if ($notFoundCallback && ! file_exists($file)) { - call_user_func($notFoundCallback, $proxyDir, $proxyNamespace, $className); - } - - require $file; - } - }; - - spl_autoload_register($autoloader); - - return $autoloader; - } -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/InvalidArgumentException.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/InvalidArgumentException.php deleted file mode 100644 index bab3d70..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,106 +0,0 @@ - - * - * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. - */ -class InvalidArgumentException extends BaseInvalidArgumentException implements ProxyException -{ - /** - * @return self - */ - public static function proxyDirectoryRequired() - { - return new self('You must configure a proxy directory. See docs for details'); - } - - /** - * @param string $className - * @param string $proxyNamespace - * - * @return self - */ - public static function notProxyClass($className, $proxyNamespace) - { - return new self(sprintf('The class "%s" is not part of the proxy namespace "%s"', $className, $proxyNamespace)); - } - - /** - * @param string $name - * - * @return self - */ - public static function invalidPlaceholder($name) - { - return new self(sprintf('Provided placeholder for "%s" must be either a string or a valid callable', $name)); - } - - /** - * @return self - */ - public static function proxyNamespaceRequired() - { - return new self('You must configure a proxy namespace'); - } - - /** - * @param Proxy $proxy - * - * @return self - */ - public static function unitializedProxyExpected(Proxy $proxy) - { - return new self(sprintf('Provided proxy of type "%s" must not be initialized.', get_class($proxy))); - } - - /** - * @param mixed $callback - * - * @return self - */ - public static function invalidClassNotFoundCallback($callback) - { - $type = is_object($callback) ? get_class($callback) : gettype($callback); - - return new self(sprintf('Invalid \$notFoundCallback given: must be a callable, "%s" given', $type)); - } - - /** - * @param string $className - * - * @return self - */ - public static function classMustNotBeAbstract($className) - { - return new self(sprintf('Unable to create a proxy for an abstract class "%s".', $className)); - } - - /** - * @param string $className - * - * @return self - */ - public static function classMustNotBeFinal($className) - { - return new self(sprintf('Unable to create a proxy for a final class "%s".', $className)); - } - - /** - * @param mixed $value - * - * @return self - */ - public static function invalidAutoGenerateMode($value) : self - { - return new self(sprintf('Invalid auto generate mode "%s" given.', $value)); - } -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/OutOfBoundsException.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/OutOfBoundsException.php deleted file mode 100644 index df40268..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/OutOfBoundsException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. - */ -class OutOfBoundsException extends BaseOutOfBoundsException implements ProxyException -{ - /** - * @param string $className - * @param string $idField - * - * @return self - */ - public static function missingPrimaryKeyValue($className, $idField) - { - return new self(sprintf("Missing value for primary key %s on %s", $idField, $className)); - } -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/ProxyException.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/ProxyException.php deleted file mode 100644 index 751f9a9..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/ProxyException.php +++ /dev/null @@ -1,15 +0,0 @@ - - * - * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. - */ -interface ProxyException -{ -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php deleted file mode 100644 index f3e7c18..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Exception/UnexpectedValueException.php +++ /dev/null @@ -1,72 +0,0 @@ - - * - * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. - */ -class UnexpectedValueException extends BaseUnexpectedValueException implements ProxyException -{ - /** - * @param string $proxyDirectory - * - * @return self - */ - public static function proxyDirectoryNotWritable($proxyDirectory) - { - return new self(sprintf('Your proxy directory "%s" must be writable', $proxyDirectory)); - } - - /** - * @param string $className - * @param string $methodName - * @param string $parameterName - * @param \Exception|null $previous - * - * @return self - */ - public static function invalidParameterTypeHint( - $className, - $methodName, - $parameterName, - \Exception $previous = null - ) { - return new self( - sprintf( - 'The type hint of parameter "%s" in method "%s" in class "%s" is invalid.', - $parameterName, - $methodName, - $className - ), - 0, - $previous - ); - } - - /** - * @param string $className - * @param string $methodName - * @param \Exception|null $previous - * - * @return self - */ - public static function invalidReturnTypeHint($className, $methodName, \Exception $previous = null) - { - return new self( - sprintf( - 'The return type of method "%s" in class "%s" is invalid.', - $methodName, - $className - ), - 0, - $previous - ); - } -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Proxy.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Proxy.php deleted file mode 100644 index 1e76b71..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/Proxy.php +++ /dev/null @@ -1,74 +0,0 @@ - - * @author Marco Pivetta - * @since 2.4 - * - * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. - */ -interface Proxy extends BaseProxy -{ - /** - * Marks the proxy as initialized or not. - * - * @param boolean $initialized - * - * @return void - */ - public function __setInitialized($initialized); - - /** - * Sets the initializer callback to be used when initializing the proxy. That - * initializer should accept 3 parameters: $proxy, $method and $params. Those - * are respectively the proxy object that is being initialized, the method name - * that triggered initialization and the parameters passed to that method. - * - * @param Closure|null $initializer - * - * @return void - */ - public function __setInitializer(Closure $initializer = null); - - /** - * Retrieves the initializer callback used to initialize the proxy. - * - * @see __setInitializer - * - * @return Closure|null - */ - public function __getInitializer(); - - /** - * Sets the callback to be used when cloning the proxy. That initializer should accept - * a single parameter, which is the cloned proxy instance itself. - * - * @param Closure|null $cloner - * - * @return void - */ - public function __setCloner(Closure $cloner = null); - - /** - * Retrieves the callback to be used when cloning the proxy. - * - * @see __setCloner - * - * @return Closure|null - */ - public function __getCloner(); - - /** - * Retrieves the list of lazy loaded properties for a given proxy - * - * @return array Keys are the property names, and values are the default values - * for those properties. - */ - public function __getLazyProperties(); -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyDefinition.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyDefinition.php deleted file mode 100644 index cb13cec..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyDefinition.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. - */ -class ProxyDefinition -{ - /** - * @var string - */ - public $proxyClassName; - - /** - * @var array - */ - public $identifierFields; - - /** - * @var \ReflectionProperty[] - */ - public $reflectionFields; - - /** - * @var callable - */ - public $initializer; - - /** - * @var callable - */ - public $cloner; - - /** - * @param string $proxyClassName - * @param array $identifierFields - * @param array $reflectionFields - * @param callable $initializer - * @param callable $cloner - */ - public function __construct($proxyClassName, array $identifierFields, array $reflectionFields, $initializer, $cloner) - { - $this->proxyClassName = $proxyClassName; - $this->identifierFields = $identifierFields; - $this->reflectionFields = $reflectionFields; - $this->initializer = $initializer; - $this->cloner = $cloner; - } -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php b/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php deleted file mode 100644 index c8da39b..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/Proxy/ProxyGenerator.php +++ /dev/null @@ -1,1062 +0,0 @@ - - * @since 2.4 - * - * @deprecated The Doctrine\Common\Proxy component is deprecated, please use ocramius/proxy-manager instead. - */ -class ProxyGenerator -{ - /** - * Used to match very simple id methods that don't need - * to be decorated since the identifier is known. - */ - const PATTERN_MATCH_ID_METHOD = '((public\s+)?(function\s+%s\s*\(\)\s*)\s*(?::\s*\??\s*\\\\?[a-z_\x7f-\xff][\w\x7f-\xff]*(?:\\\\[a-z_\x7f-\xff][\w\x7f-\xff]*)*\s*)?{\s*return\s*\$this->%s;\s*})i'; - - /** - * The namespace that contains all proxy classes. - * - * @var string - */ - private $proxyNamespace; - - /** - * The directory that contains all proxy classes. - * - * @var string - */ - private $proxyDirectory; - - /** - * Map of callables used to fill in placeholders set in the template. - * - * @var string[]|callable[] - */ - protected $placeholders = [ - 'baseProxyInterface' => Proxy::class, - 'additionalProperties' => '', - ]; - - /** - * Template used as a blueprint to generate proxies. - * - * @var string - */ - protected $proxyClassTemplate = '; - -/** - * DO NOT EDIT THIS FILE - IT WAS CREATED BY DOCTRINE\'S PROXY GENERATOR - */ -class extends \ implements \ -{ - /** - * @var \Closure the callback responsible for loading properties in the proxy object. This callback is called with - * three parameters, being respectively the proxy object to be initialized, the method that triggered the - * initialization process and an array of ordered parameters that were passed to that method. - * - * @see \Doctrine\Common\Proxy\Proxy::__setInitializer - */ - public $__initializer__; - - /** - * @var \Closure the callback responsible of loading properties that need to be copied in the cloned object - * - * @see \Doctrine\Common\Proxy\Proxy::__setCloner - */ - public $__cloner__; - - /** - * @var boolean flag indicating if this object was already initialized - * - * @see \Doctrine\Common\Persistence\Proxy::__isInitialized - */ - public $__isInitialized__ = false; - - /** - * @var array properties to be lazy loaded, with keys being the property - * names and values being their default values - * - * @see \Doctrine\Common\Proxy\Proxy::__getLazyProperties - */ - public static $lazyPropertiesDefaults = []; - - - - - - - - - - - - - - - - - - /** - * Forces initialization of the proxy - */ - public function __load() - { - $this->__initializer__ && $this->__initializer__->__invoke($this, \'__load\', []); - } - - /** - * {@inheritDoc} - * @internal generated method: use only when explicitly handling proxy specific loading logic - */ - public function __isInitialized() - { - return $this->__isInitialized__; - } - - /** - * {@inheritDoc} - * @internal generated method: use only when explicitly handling proxy specific loading logic - */ - public function __setInitialized($initialized) - { - $this->__isInitialized__ = $initialized; - } - - /** - * {@inheritDoc} - * @internal generated method: use only when explicitly handling proxy specific loading logic - */ - public function __setInitializer(\Closure $initializer = null) - { - $this->__initializer__ = $initializer; - } - - /** - * {@inheritDoc} - * @internal generated method: use only when explicitly handling proxy specific loading logic - */ - public function __getInitializer() - { - return $this->__initializer__; - } - - /** - * {@inheritDoc} - * @internal generated method: use only when explicitly handling proxy specific loading logic - */ - public function __setCloner(\Closure $cloner = null) - { - $this->__cloner__ = $cloner; - } - - /** - * {@inheritDoc} - * @internal generated method: use only when explicitly handling proxy specific cloning logic - */ - public function __getCloner() - { - return $this->__cloner__; - } - - /** - * {@inheritDoc} - * @internal generated method: use only when explicitly handling proxy specific loading logic - * @static - */ - public function __getLazyProperties() - { - return self::$lazyPropertiesDefaults; - } - - -} -'; - - /** - * Initializes a new instance of the ProxyFactory class that is - * connected to the given EntityManager. - * - * @param string $proxyDirectory The directory to use for the proxy classes. It must exist. - * @param string $proxyNamespace The namespace to use for the proxy classes. - * - * @throws InvalidArgumentException - */ - public function __construct($proxyDirectory, $proxyNamespace) - { - if ( ! $proxyDirectory) { - throw InvalidArgumentException::proxyDirectoryRequired(); - } - - if ( ! $proxyNamespace) { - throw InvalidArgumentException::proxyNamespaceRequired(); - } - - $this->proxyDirectory = $proxyDirectory; - $this->proxyNamespace = $proxyNamespace; - } - - /** - * Sets a placeholder to be replaced in the template. - * - * @param string $name - * @param string|callable $placeholder - * - * @throws InvalidArgumentException - */ - public function setPlaceholder($name, $placeholder) - { - if ( ! is_string($placeholder) && ! is_callable($placeholder)) { - throw InvalidArgumentException::invalidPlaceholder($name); - } - - $this->placeholders[$name] = $placeholder; - } - - /** - * Sets the base template used to create proxy classes. - * - * @param string $proxyClassTemplate - */ - public function setProxyClassTemplate($proxyClassTemplate) - { - $this->proxyClassTemplate = (string) $proxyClassTemplate; - } - - /** - * Generates a proxy class file. - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class Metadata for the original class. - * @param string|bool $fileName Filename (full path) for the generated class. If none is given, eval() is used. - * - * @throws InvalidArgumentException - * @throws UnexpectedValueException - */ - public function generateProxyClass(ClassMetadata $class, $fileName = false) - { - $this->verifyClassCanBeProxied($class); - - preg_match_all('(<([a-zA-Z]+)>)', $this->proxyClassTemplate, $placeholderMatches); - - $placeholderMatches = array_combine($placeholderMatches[0], $placeholderMatches[1]); - $placeholders = []; - - foreach ($placeholderMatches as $placeholder => $name) { - $placeholders[$placeholder] = isset($this->placeholders[$name]) - ? $this->placeholders[$name] - : [$this, 'generate' . $name]; - } - - foreach ($placeholders as & $placeholder) { - if (is_callable($placeholder)) { - $placeholder = call_user_func($placeholder, $class); - } - } - - $proxyCode = strtr($this->proxyClassTemplate, $placeholders); - - if ( ! $fileName) { - $proxyClassName = $this->generateNamespace($class) . '\\' . $this->generateProxyShortClassName($class); - - if ( ! class_exists($proxyClassName)) { - eval(substr($proxyCode, 5)); - } - - return; - } - - $parentDirectory = dirname($fileName); - - if ( ! is_dir($parentDirectory) && (false === @mkdir($parentDirectory, 0775, true))) { - throw UnexpectedValueException::proxyDirectoryNotWritable($this->proxyDirectory); - } - - if ( ! is_writable($parentDirectory)) { - throw UnexpectedValueException::proxyDirectoryNotWritable($this->proxyDirectory); - } - - $tmpFileName = $fileName . '.' . uniqid('', true); - - file_put_contents($tmpFileName, $proxyCode); - @chmod($tmpFileName, 0664); - rename($tmpFileName, $fileName); - } - - /** - * @param ClassMetadata $class - * - * @throws InvalidArgumentException - */ - private function verifyClassCanBeProxied(ClassMetadata $class) - { - if ($class->getReflectionClass()->isFinal()) { - throw InvalidArgumentException::classMustNotBeFinal($class->getName()); - } - - if ($class->getReflectionClass()->isAbstract()) { - throw InvalidArgumentException::classMustNotBeAbstract($class->getName()); - } - } - - /** - * Generates the proxy short class name to be used in the template. - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return string - */ - private function generateProxyShortClassName(ClassMetadata $class) - { - $proxyClassName = ClassUtils::generateProxyClassName($class->getName(), $this->proxyNamespace); - $parts = explode('\\', strrev($proxyClassName), 2); - - return strrev($parts[0]); - } - - /** - * Generates the proxy namespace. - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return string - */ - private function generateNamespace(ClassMetadata $class) - { - $proxyClassName = ClassUtils::generateProxyClassName($class->getName(), $this->proxyNamespace); - $parts = explode('\\', strrev($proxyClassName), 2); - - return strrev($parts[1]); - } - - /** - * Generates the original class name. - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return string - */ - private function generateClassName(ClassMetadata $class) - { - return ltrim($class->getName(), '\\'); - } - - /** - * Generates the array representation of lazy loaded public properties and their default values. - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return string - */ - private function generateLazyPropertiesDefaults(ClassMetadata $class) - { - $lazyPublicProperties = $this->getLazyLoadedPublicProperties($class); - $values = []; - - foreach ($lazyPublicProperties as $key => $value) { - $values[] = var_export($key, true) . ' => ' . var_export($value, true); - } - - return implode(', ', $values); - } - - /** - * Generates the constructor code (un-setting public lazy loaded properties, setting identifier field values). - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return string - */ - private function generateConstructorImpl(ClassMetadata $class) - { - $constructorImpl = <<<'EOT' - /** - * @param \Closure $initializer - * @param \Closure $cloner - */ - public function __construct($initializer = null, $cloner = null) - { - -EOT; - $toUnset = []; - - foreach ($this->getLazyLoadedPublicProperties($class) as $lazyPublicProperty => $unused) { - $toUnset[] = '$this->' . $lazyPublicProperty; - } - - $constructorImpl .= (empty($toUnset) ? '' : ' unset(' . implode(', ', $toUnset) . ");\n") - . <<<'EOT' - - $this->__initializer__ = $initializer; - $this->__cloner__ = $cloner; - } -EOT; - - return $constructorImpl; - } - - /** - * Generates the magic getter invoked when lazy loaded public properties are requested. - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return string - */ - private function generateMagicGet(ClassMetadata $class) - { - $lazyPublicProperties = array_keys($this->getLazyLoadedPublicProperties($class)); - $reflectionClass = $class->getReflectionClass(); - $hasParentGet = false; - $returnReference = ''; - $inheritDoc = ''; - - if ($reflectionClass->hasMethod('__get')) { - $hasParentGet = true; - $inheritDoc = '{@inheritDoc}'; - - if ($reflectionClass->getMethod('__get')->returnsReference()) { - $returnReference = '& '; - } - } - - if (empty($lazyPublicProperties) && ! $hasParentGet) { - return ''; - } - - $magicGet = <<__getLazyProperties())) { - $this->__initializer__ && $this->__initializer__->__invoke($this, '__get', [$name]); - - return $this->$name; - } - - -EOT; - } - - if ($hasParentGet) { - $magicGet .= <<<'EOT' - $this->__initializer__ && $this->__initializer__->__invoke($this, '__get', [$name]); - - return parent::__get($name); - -EOT; - } else { - $magicGet .= <<<'EOT' - trigger_error(sprintf('Undefined property: %s::$%s', __CLASS__, $name), E_USER_NOTICE); - -EOT; - } - - $magicGet .= " }"; - - return $magicGet; - } - - /** - * Generates the magic setter (currently unused). - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return string - */ - private function generateMagicSet(ClassMetadata $class) - { - $lazyPublicProperties = $this->getLazyLoadedPublicProperties($class); - $hasParentSet = $class->getReflectionClass()->hasMethod('__set'); - - if (empty($lazyPublicProperties) && ! $hasParentSet) { - return ''; - } - - $inheritDoc = $hasParentSet ? '{@inheritDoc}' : ''; - $magicSet = <<__getLazyProperties())) { - $this->__initializer__ && $this->__initializer__->__invoke($this, '__set', [$name, $value]); - - $this->$name = $value; - - return; - } - - -EOT; - } - - if ($hasParentSet) { - $magicSet .= <<<'EOT' - $this->__initializer__ && $this->__initializer__->__invoke($this, '__set', [$name, $value]); - - return parent::__set($name, $value); -EOT; - } else { - $magicSet .= " \$this->\$name = \$value;"; - } - - $magicSet .= "\n }"; - - return $magicSet; - } - - /** - * Generates the magic issetter invoked when lazy loaded public properties are checked against isset(). - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return string - */ - private function generateMagicIsset(ClassMetadata $class) - { - $lazyPublicProperties = array_keys($this->getLazyLoadedPublicProperties($class)); - $hasParentIsset = $class->getReflectionClass()->hasMethod('__isset'); - - if (empty($lazyPublicProperties) && ! $hasParentIsset) { - return ''; - } - - $inheritDoc = $hasParentIsset ? '{@inheritDoc}' : ''; - $magicIsset = <<__getLazyProperties())) { - $this->__initializer__ && $this->__initializer__->__invoke($this, '__isset', [$name]); - - return isset($this->$name); - } - - -EOT; - } - - if ($hasParentIsset) { - $magicIsset .= <<<'EOT' - $this->__initializer__ && $this->__initializer__->__invoke($this, '__isset', [$name]); - - return parent::__isset($name); - -EOT; - } else { - $magicIsset .= " return false;"; - } - - return $magicIsset . "\n }"; - } - - /** - * Generates implementation for the `__sleep` method of proxies. - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return string - */ - private function generateSleepImpl(ClassMetadata $class) - { - $hasParentSleep = $class->getReflectionClass()->hasMethod('__sleep'); - $inheritDoc = $hasParentSleep ? '{@inheritDoc}' : ''; - $sleepImpl = <<__isInitialized__) { - $properties = array_diff($properties, array_keys($this->__getLazyProperties())); - } - - return $properties; - } -EOT; - } - - $allProperties = ['__isInitialized__']; - - /* @var $prop \ReflectionProperty */ - foreach ($class->getReflectionClass()->getProperties() as $prop) { - if ($prop->isStatic()) { - continue; - } - - $allProperties[] = $prop->isPrivate() - ? "\0" . $prop->getDeclaringClass()->getName() . "\0" . $prop->getName() - : $prop->getName(); - } - - $lazyPublicProperties = array_keys($this->getLazyLoadedPublicProperties($class)); - $protectedProperties = array_diff($allProperties, $lazyPublicProperties); - - foreach ($allProperties as &$property) { - $property = var_export($property, true); - } - - foreach ($protectedProperties as &$property) { - $property = var_export($property, true); - } - - $allProperties = implode(', ', $allProperties); - $protectedProperties = implode(', ', $protectedProperties); - - return $sleepImpl . <<__isInitialized__) { - return [$allProperties]; - } - - return [$protectedProperties]; - } -EOT; - } - - /** - * Generates implementation for the `__wakeup` method of proxies. - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return string - */ - private function generateWakeupImpl(ClassMetadata $class) - { - $unsetPublicProperties = []; - $hasWakeup = $class->getReflectionClass()->hasMethod('__wakeup'); - - foreach (array_keys($this->getLazyLoadedPublicProperties($class)) as $lazyPublicProperty) { - $unsetPublicProperties[] = '$this->' . $lazyPublicProperty; - } - - $shortName = $this->generateProxyShortClassName($class); - $inheritDoc = $hasWakeup ? '{@inheritDoc}' : ''; - $wakeupImpl = <<__isInitialized__) { - \$this->__initializer__ = function ($shortName \$proxy) { - \$proxy->__setInitializer(null); - \$proxy->__setCloner(null); - - \$existingProperties = get_object_vars(\$proxy); - - foreach (\$proxy->__getLazyProperties() as \$property => \$defaultValue) { - if ( ! array_key_exists(\$property, \$existingProperties)) { - \$proxy->\$property = \$defaultValue; - } - } - }; - -EOT; - - if ( ! empty($unsetPublicProperties)) { - $wakeupImpl .= "\n unset(" . implode(', ', $unsetPublicProperties) . ");"; - } - - $wakeupImpl .= "\n }"; - - if ($hasWakeup) { - $wakeupImpl .= "\n parent::__wakeup();"; - } - - $wakeupImpl .= "\n }"; - - return $wakeupImpl; - } - - /** - * Generates implementation for the `__clone` method of proxies. - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return string - */ - private function generateCloneImpl(ClassMetadata $class) - { - $hasParentClone = $class->getReflectionClass()->hasMethod('__clone'); - $inheritDoc = $hasParentClone ? '{@inheritDoc}' : ''; - $callParentClone = $hasParentClone ? "\n parent::__clone();\n" : ''; - - return <<__cloner__ && \$this->__cloner__->__invoke(\$this, '__clone', []); -$callParentClone } -EOT; - } - - /** - * Generates decorated methods by picking those available in the parent class. - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return string - */ - private function generateMethods(ClassMetadata $class) - { - $methods = ''; - $methodNames = []; - $reflectionMethods = $class->getReflectionClass()->getMethods(\ReflectionMethod::IS_PUBLIC); - $skippedMethods = [ - '__sleep' => true, - '__clone' => true, - '__wakeup' => true, - '__get' => true, - '__set' => true, - '__isset' => true, - ]; - - foreach ($reflectionMethods as $method) { - $name = $method->getName(); - - if ($method->isConstructor() || - isset($skippedMethods[strtolower($name)]) || - isset($methodNames[$name]) || - $method->isFinal() || - $method->isStatic() || - ( ! $method->isPublic()) - ) { - continue; - } - - $methodNames[$name] = true; - $methods .= "\n /**\n" - . " * {@inheritDoc}\n" - . " */\n" - . ' public function '; - - if ($method->returnsReference()) { - $methods .= '&'; - } - - $methods .= $name . '(' . $this->buildParametersString($method->getParameters()) . ')'; - $methods .= $this->getMethodReturnType($method); - $methods .= "\n" . ' {' . "\n"; - - if ($this->isShortIdentifierGetter($method, $class)) { - $identifier = lcfirst(substr($name, 3)); - $fieldType = $class->getTypeOfField($identifier); - $cast = in_array($fieldType, ['integer', 'smallint']) ? '(int) ' : ''; - - $methods .= ' if ($this->__isInitialized__ === false) {' . "\n"; - $methods .= ' '; - $methods .= $this->shouldProxiedMethodReturn($method) ? 'return ' : ''; - $methods .= $cast . ' parent::' . $method->getName() . "();\n"; - $methods .= ' }' . "\n\n"; - } - - $invokeParamsString = implode(', ', $this->getParameterNamesForInvoke($method->getParameters())); - $callParamsString = implode(', ', $this->getParameterNamesForParentCall($method->getParameters())); - - $methods .= "\n \$this->__initializer__ " - . "&& \$this->__initializer__->__invoke(\$this, " . var_export($name, true) - . ", [" . $invokeParamsString . "]);" - . "\n\n " - . ($this->shouldProxiedMethodReturn($method) ? 'return ' : '') - . "parent::" . $name . '(' . $callParamsString . ');' - . "\n" . ' }' . "\n"; - } - - return $methods; - } - - /** - * Generates the Proxy file name. - * - * @param string $className - * @param string $baseDirectory Optional base directory for proxy file name generation. - * If not specified, the directory configured on the Configuration of the - * EntityManager will be used by this factory. - * - * @return string - */ - public function getProxyFileName($className, $baseDirectory = null) - { - $baseDirectory = $baseDirectory ?: $this->proxyDirectory; - - return rtrim($baseDirectory, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . Proxy::MARKER - . str_replace('\\', '', $className) . '.php'; - } - - /** - * Checks if the method is a short identifier getter. - * - * What does this mean? For proxy objects the identifier is already known, - * however accessing the getter for this identifier usually triggers the - * lazy loading, leading to a query that may not be necessary if only the - * ID is interesting for the userland code (for example in views that - * generate links to the entity, but do not display anything else). - * - * @param \ReflectionMethod $method - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return boolean - */ - private function isShortIdentifierGetter($method, ClassMetadata $class) - { - $identifier = lcfirst(substr($method->getName(), 3)); - $startLine = $method->getStartLine(); - $endLine = $method->getEndLine(); - $cheapCheck = ( - $method->getNumberOfParameters() == 0 - && substr($method->getName(), 0, 3) == 'get' - && in_array($identifier, $class->getIdentifier(), true) - && $class->hasField($identifier) - && (($endLine - $startLine) <= 4) - ); - - if ($cheapCheck) { - $code = file($method->getFileName()); - $code = trim(implode(' ', array_slice($code, $startLine - 1, $endLine - $startLine + 1))); - - $pattern = sprintf(self::PATTERN_MATCH_ID_METHOD, $method->getName(), $identifier); - - if (preg_match($pattern, $code)) { - return true; - } - } - - return false; - } - - /** - * Generates the list of public properties to be lazy loaded, with their default values. - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $class - * - * @return mixed[] - */ - private function getLazyLoadedPublicProperties(ClassMetadata $class) - { - $defaultProperties = $class->getReflectionClass()->getDefaultProperties(); - $properties = []; - - foreach ($class->getReflectionClass()->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { - $name = $property->getName(); - - if (($class->hasField($name) || $class->hasAssociation($name)) && ! $class->isIdentifier($name)) { - $properties[$name] = $defaultProperties[$name]; - } - } - - return $properties; - } - - /** - * @param \ReflectionParameter[] $parameters - * - * @return string - */ - private function buildParametersString(array $parameters) - { - $parameterDefinitions = []; - - /* @var $param \ReflectionParameter */ - foreach ($parameters as $param) { - $parameterDefinition = ''; - - if ($parameterType = $this->getParameterType($param)) { - $parameterDefinition .= $parameterType . ' '; - } - - if ($param->isPassedByReference()) { - $parameterDefinition .= '&'; - } - - if ($param->isVariadic()) { - $parameterDefinition .= '...'; - } - - $parameterDefinition .= '$' . $param->getName(); - - if ($param->isDefaultValueAvailable()) { - $parameterDefinition .= ' = ' . var_export($param->getDefaultValue(), true); - } - - $parameterDefinitions[] = $parameterDefinition; - } - - return implode(', ', $parameterDefinitions); - } - - /** - * @param \ReflectionParameter $parameter - * - * @return string|null - */ - private function getParameterType(\ReflectionParameter $parameter) - { - if ( ! $parameter->hasType()) { - return null; - } - - return $this->formatType($parameter->getType(), $parameter->getDeclaringFunction(), $parameter); - } - - /** - * @param \ReflectionParameter[] $parameters - * - * @return string[] - */ - private function getParameterNamesForInvoke(array $parameters) - { - return array_map( - function (\ReflectionParameter $parameter) { - return '$' . $parameter->getName(); - }, - $parameters - ); - } - - /** - * @param \ReflectionParameter[] $parameters - * - * @return string[] - */ - private function getParameterNamesForParentCall(array $parameters) - { - return array_map( - function (\ReflectionParameter $parameter) { - $name = ''; - - if ($parameter->isVariadic()) { - $name .= '...'; - } - - $name .= '$' . $parameter->getName(); - - return $name; - }, - $parameters - ); - } - - /** - * @param \ReflectionMethod $method - * - * @return string - */ - private function getMethodReturnType(\ReflectionMethod $method) - { - if ( ! $method->hasReturnType()) { - return ''; - } - - return ': ' . $this->formatType($method->getReturnType(), $method); - } - - /** - * @param \ReflectionMethod $method - * - * @return bool - */ - private function shouldProxiedMethodReturn(\ReflectionMethod $method) - { - if ( ! $method->hasReturnType()) { - return true; - } - - return 'void' !== strtolower($this->formatType($method->getReturnType(), $method)); - } - - /** - * @param \ReflectionType $type - * @param \ReflectionMethod $method - * @param \ReflectionParameter|null $parameter - * - * @return string - */ - private function formatType( - \ReflectionType $type, - \ReflectionMethod $method, - \ReflectionParameter $parameter = null - ) { - $name = $type->getName(); - $nameLower = strtolower($name); - - if ('self' === $nameLower) { - $name = $method->getDeclaringClass()->getName(); - } - - if ('parent' === $nameLower) { - $name = $method->getDeclaringClass()->getParentClass()->getName(); - } - - if ( ! $type->isBuiltin() && ! class_exists($name) && ! interface_exists($name)) { - if (null !== $parameter) { - throw UnexpectedValueException::invalidParameterTypeHint( - $method->getDeclaringClass()->getName(), - $method->getName(), - $parameter->getName() - ); - } - - throw UnexpectedValueException::invalidReturnTypeHint( - $method->getDeclaringClass()->getName(), - $method->getName() - ); - } - - if ( ! $type->isBuiltin()) { - $name = '\\' . $name; - } - - if ($type->allowsNull() - && (null === $parameter || ! $parameter->isDefaultValueAvailable() || null !== $parameter->getDefaultValue()) - ) { - $name = '?' . $name; - } - - return $name; - } -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Util/ClassUtils.php b/vendor/doctrine/common/lib/Doctrine/Common/Util/ClassUtils.php deleted file mode 100644 index e3d24cf..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/Util/ClassUtils.php +++ /dev/null @@ -1,93 +0,0 @@ - - * @author Johannes Schmitt - * - * @deprecated The ClassUtils class is deprecated. - */ -class ClassUtils -{ - /** - * Gets the real class name of a class name that could be a proxy. - * - * @param string $class - * - * @return string - */ - public static function getRealClass($class) - { - if (false === $pos = strrpos($class, '\\' . Proxy::MARKER . '\\')) { - return $class; - } - - return substr($class, $pos + Proxy::MARKER_LENGTH + 2); - } - - /** - * Gets the real class name of an object (even if its a proxy). - * - * @param object $object - * - * @return string - */ - public static function getClass($object) - { - return self::getRealClass(get_class($object)); - } - - /** - * Gets the real parent class name of a class or object. - * - * @param string $className - * - * @return string - */ - public static function getParentClass($className) - { - return get_parent_class(self::getRealClass($className)); - } - - /** - * Creates a new reflection class. - * - * @param string $class - * - * @return \ReflectionClass - */ - public static function newReflectionClass($class) - { - return new \ReflectionClass(self::getRealClass($class)); - } - - /** - * Creates a new reflection object. - * - * @param object $object - * - * @return \ReflectionClass - */ - public static function newReflectionObject($object) - { - return self::newReflectionClass(self::getClass($object)); - } - - /** - * Given a class name and a proxy namespace returns the proxy name. - * - * @param string $className - * @param string $proxyNamespace - * - * @return string - */ - public static function generateProxyClassName($className, $proxyNamespace) - { - return rtrim($proxyNamespace, '\\') . '\\' . Proxy::MARKER . '\\' . ltrim($className, '\\'); - } -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php b/vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php deleted file mode 100644 index a37282a..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/Util/Debug.php +++ /dev/null @@ -1,167 +0,0 @@ - - * @author Jonathan Wage - * @author Roman Borschel - * @author Giorgio Sironi - * - * @deprecated The Debug class is deprecated, please use symfony/var-dumper instead. - */ -final class Debug -{ - /** - * Private constructor (prevents instantiation). - */ - private function __construct() - { - } - - /** - * Prints a dump of the public, protected and private properties of $var. - * - * @link https://xdebug.org/ - * - * @param mixed $var The variable to dump. - * @param integer $maxDepth The maximum nesting level for object properties. - * @param boolean $stripTags Whether output should strip HTML tags. - * @param boolean $echo Send the dumped value to the output buffer - * - * @return string - */ - public static function dump($var, $maxDepth = 2, $stripTags = true, $echo = true) - { - $html = ini_get('html_errors'); - - if ($html !== true) { - ini_set('html_errors', true); - } - - 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(); - - $dumpText = ($stripTags ? strip_tags(html_entity_decode($dump)) : $dump); - - ini_set('html_errors', $html); - - if ($echo) { - echo $dumpText; - } - - return $dumpText; - } - - /** - * @param mixed $var - * @param int $maxDepth - * - * @return mixed - */ - public static function export($var, $maxDepth) - { - $return = null; - $isObj = is_object($var); - - if ($var instanceof Collection) { - $var = $var->toArray(); - } - - if ( ! $maxDepth) { - return is_object($var) ? get_class($var) - : (is_array($var) ? 'Array(' . count($var) . ')' : $var); - } - - if (is_array($var)) { - $return = []; - - foreach ($var as $k => $v) { - $return[$k] = self::export($v, $maxDepth - 1); - } - - return $return; - } - - if ( ! $isObj) { - return $var; - } - - $return = new \stdClass(); - if ($var instanceof \DateTimeInterface) { - $return->__CLASS__ = get_class($var); - $return->date = $var->format('c'); - $return->timezone = $var->getTimezone()->getName(); - - return $return; - } - - $return->__CLASS__ = ClassUtils::getClass($var); - - if ($var instanceof Proxy) { - $return->__IS_PROXY__ = true; - $return->__PROXY_INITIALIZED__ = $var->__isInitialized(); - } - - if ($var instanceof \ArrayObject || $var instanceof \ArrayIterator) { - $return->__STORAGE__ = self::export($var->getArrayCopy(), $maxDepth - 1); - } - - return self::fillReturnWithClassAttributes($var, $return, $maxDepth); - } - - /** - * Fill the $return variable with class attributes - * Based on obj2array function from {@see https://secure.php.net/manual/en/function.get-object-vars.php#47075} - * - * @param object $var - * @param \stdClass $return - * @param int $maxDepth - * - * @return mixed - */ - private static function fillReturnWithClassAttributes($var, \stdClass $return, $maxDepth) - { - $clone = (array) $var; - - foreach (array_keys($clone) as $key) { - $aux = explode("\0", $key); - $name = end($aux); - if ($aux[0] === '') { - $name .= ':' . ($aux[1] === '*' ? 'protected' : $aux[1] . ':private'); - } - $return->$name = self::export($clone[$key], $maxDepth - 1); - ; - } - - return $return; - } - - /** - * Returns a string representation of an object. - * - * @param object $obj - * - * @return string - */ - public static function toString($obj) - { - return method_exists($obj, '__toString') ? (string) $obj : get_class($obj) . '@' . spl_object_hash($obj); - } -} diff --git a/vendor/doctrine/common/lib/Doctrine/Common/Util/Inflector.php b/vendor/doctrine/common/lib/Doctrine/Common/Util/Inflector.php deleted file mode 100644 index f41c54a..0000000 --- a/vendor/doctrine/common/lib/Doctrine/Common/Util/Inflector.php +++ /dev/null @@ -1,19 +0,0 @@ - - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * - * @deprecated The Version class is deprecated, please refrain from checking the version of doctrine/common. - */ -class Version -{ - /** - * Current Doctrine Version. - */ - const VERSION = '2.11.0'; - - /** - * Compares a Doctrine version with the current one. - * - * @param string $version Doctrine version to compare. - * - * @return int -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); - } -} diff --git a/vendor/doctrine/common/phpstan.neon.dist b/vendor/doctrine/common/phpstan.neon.dist deleted file mode 100644 index 47a8c2e..0000000 --- a/vendor/doctrine/common/phpstan.neon.dist +++ /dev/null @@ -1,34 +0,0 @@ -parameters: - level: 3 - paths: - - %currentWorkingDirectory%/lib - - %currentWorkingDirectory%/tests - autoload_directories: - - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/ClassLoaderTest - excludes_analyse: - - %currentWorkingDirectory%/lib/vendor/doctrine-build-common - - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/InvalidReturnTypeClass.php - - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/InvalidTypeHintClass.php - - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/SerializedClass.php - - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/VariadicTypeHintClass.php - ignoreErrors: - - '#Access to an undefined property Doctrine\\Common\\Proxy\\Proxy::\$publicField#' - - - message: '#^Result of method Doctrine\\Tests\\Common\\Proxy\\LazyLoadableObjectWithVoid::(adding|incrementing)AndReturningVoid\(\) \(void\) is used\.$#' - path: '%currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/ProxyLogicVoidReturnTypeTest.php' - - - message: '#^Property Doctrine\\Tests\\Common\\Proxy\\ProxyLogicTest::\$initializerCallbackMock \(callable&PHPUnit\\Framework\\MockObject\\MockObject\) does not accept PHPUnit\\Framework\\MockObject\\MockObject&stdClass\.$#' - path: '%currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/ProxyLogicTest.php' - - - message: '#^Call to an undefined method PHPUnit\\Framework\\MockObject\\MockObject(&stdClass)?::(load|getName)\(\)\.$#' - path: '%currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/ProxyLogicTest.php' - - - message: '#^Access to an undefined property Doctrine\\Common\\Proxy\\Proxy&Doctrine\\Tests\\Common\\Proxy\\LazyLoadableObject::\$non_existing_property\.$#' - path: '%currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/ProxyLogicTest.php' - - - message: '#^Property Doctrine\\Tests\\Common\\Proxy\\ProxyLogicVoidReturnTypeTest::\$initializerCallbackMock \(callable&PHPUnit\\Framework\\MockObject\\MockObject\) does not accept PHPUnit\\Framework\\MockObject\\MockObject&stdClass\.$#' - path: '%currentWorkingDirectory%/tests/Doctrine/Tests/Common/Proxy/ProxyLogicVoidReturnTypeTest.php' - -includes: - - vendor/phpstan/phpstan-phpunit/extension.neon - - vendor/phpstan/phpstan-phpunit/rules.neon diff --git a/vendor/doctrine/data-fixtures/.doctrine-project.json b/vendor/doctrine/data-fixtures/.doctrine-project.json deleted file mode 100644 index 06747ff..0000000 --- a/vendor/doctrine/data-fixtures/.doctrine-project.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "active": true, - "name": "Data fixtures", - "slug": "data-fixtures", - "docsSlug": "doctrine-data-fixtures", - "versions": [ - { - "name": "1.4", - "branchName": "master", - "slug": "latest", - "upcoming": true - }, - { - "name": "1.3", - "branchName": "1.3", - "slug": "1.3", - "current": true, - "aliases": [ - "current", - "stable" - ] - } - ] -} diff --git a/vendor/doctrine/data-fixtures/.github/FUNDING.yml b/vendor/doctrine/data-fixtures/.github/FUNDING.yml deleted file mode 100644 index 43c81de..0000000 --- a/vendor/doctrine/data-fixtures/.github/FUNDING.yml +++ /dev/null @@ -1,3 +0,0 @@ -patreon: phpdoctrine -tidelift: packagist/doctrine%2Fdata-fixtures -custom: https://www.doctrine-project.org/sponsorship.html diff --git a/vendor/doctrine/data-fixtures/CHANGELOG.md b/vendor/doctrine/data-fixtures/CHANGELOG.md deleted file mode 100644 index 8bae0c9..0000000 --- a/vendor/doctrine/data-fixtures/CHANGELOG.md +++ /dev/null @@ -1,170 +0,0 @@ -# Change Log -All notable changes to this project will be documented in this file. -This project adheres to [Semantic Versioning](http://semver.org/). - -## [1.3.0] - 2017-11-27 - -### Fixed - - [248: Rename example classes names for consistency](https://github.com/doctrine/data-fixtures/pull/248) - @Kwadz - - [253: Fix syntax highlighting on README](https://github.com/doctrine/data-fixtures/pull/253) - @fefas - - [269: Remove tabs](https://github.com/doctrine/data-fixtures/pull/269) - @garak - -### Changed - - [266: Bump PHP requirement to 7.1](https://github.com/doctrine/data-fixtures/pull/266) - @alcaeus - -### Added - - [255: Added handling of PHPCR documents on method `getIdentifier()`](https://github.com/doctrine/data-fixtures/pull/255) - @aemaething - - [274: Hook point to control creating fixtures objects](https://github.com/doctrine/data-fixtures/pull/274) - @weaverryan - -### Fixed - - [572: Only show generated migration in verbose mode](https://github.com/doctrine/migrations/pull/572) - @alcaeus - -## [1.6.0] - 2017-11-09 - -### Fixed - - [536: Fix typo in exception message](https://github.com/doctrine/migrations/pull/536) - @mantiz - - [545: Allow nullable custom template](https://github.com/doctrine/migrations/pull/545) - @PapsOu - - [560: Fix `--dry-run` and `--write-sql` with `addSql`](https://github.com/doctrine/migrations/pull/560) - @mikeSimonson - - [569: Allow using absolute paths for custom template](https://github.com/doctrine/migrations/pull/569) - @alcaeus - -### Changed - - [537: Require PHP 7.1](https://github.com/doctrine/migrations/pull/537) - @lcobucci - - [563: Remove copyright headers](https://github.com/doctrine/migrations/pull/563) - @mikeSimonson - - [534: Change RecursiveRegexFinder to follow Symlinks](https://github.com/doctrine/migrations/pull/534) - @burci - -### Added - - [506: Add migration events](https://github.com/doctrine/migrations/pull/506) - @chrisguitarguy - - [509: Add delta in migrate command](https://github.com/doctrine/migrations/pull/509) - @Safranil - - [535: Allow changing migration class template in generate command](https://github.com/doctrine/migrations/pull/535) - @PapsOu - - [542: Enable phpcs to ensure coding style](https://github.com/doctrine/migrations/pull/542) - @lcobucci - - [562: Allow providing a path for file dump](https://github.com/doctrine/migrations/pull/562) - @mikeSimonson - - [565: Allow Symfony 4](https://github.com/doctrine/migrations/565) - @weaverryan - - [568: Add `ConfigurationHelperInterface` to allow overriding internal class](https://github.com/doctrine/migrations/pull/568) - @alcaeus - - [571: Allow changing migration class template in diff command](https://github.com/doctrine/migrations/pull/571) - @alcaeus - -## [1.5.0] - 2016-12-25 - -### Fixed - - [447: Fix typo in error code](https://github.com/doctrine/migrations/pull/447) thanks to @funivan - - [448: Removed unused import](https://github.com/doctrine/migrations/pull/448) thanks to @localheinz - - [451: Case insensitive method calls and types](https://github.com/doctrine/migrations/pull/451) thanks to @localheinz - - [449: Use the class keyword](https://github.com/doctrine/migrations/pull/449) thanks to @localheinz - - [453: Use better assertions](https://github.com/doctrine/migrations/pull/453) thanks to @localheinz - - [452: Fix the visibility of the AbstractTest](https://github.com/doctrine/migrations/pull/452) thanks to @localheinz - - [450: Use the short array syntax](https://github.com/doctrine/migrations/pull/450) thanks to @localheinz - - [464: Clean the github autogenerated zip archive](https://github.com/doctrine/migrations/pull/464) thanks to @mlocati - - [457: Fix an issue where the migration wheren't sorted propely](https://github.com/doctrine/migrations/pull/457) thanks to @JHGitty, @Charles68 - - [451: Case insensitive method calls and types](https://github.com/doctrine/migrations/pull/451) thanks to @localheinz - - [471: Fix loading the configuration from a php file](https://github.com/doctrine/migrations/pull/471) thanks to @aaa2000 - - [451: Case insensitive method calls and types](https://github.com/doctrine/migrations/pull/451) thanks to @localheinz - - [472: Change comment marker a cross platform one ](https://github.com/doctrine/migrations/pull/472) thanks to @aaa2000 - - [476: Add test for the execute command](https://github.com/doctrine/migrations/pull/476) thanks to @chrisguitarguy - - [470: Case insensitive method calls and types](https://github.com/doctrine/migrations/pull/470) thanks to @abacaphiliac - - [489: Better help message in the execute command](https://github.com/doctrine/migrations/pull/489) thanks to @eko - - [500: Updating the dev dependencies](https://github.com/doctrine/migrations/pull/500) thanks to @mikeSimonson - - [501: Fix a bug in a rarely used message call](https://github.com/doctrine/migrations/pull/501) thanks to @Seldaek - -### Changed - - [478: Changed the default generated version number to UTC](https://github.com/doctrine/migrations/pull/446) thanks to @c960657 - - [479: Explicitly connecting to support master slave connections](https://github.com/doctrine/migrations/pull/479) thanks to @chrisguitarguy - - [482: Use strict comparaison in the generated migrations](https://github.com/doctrine/migrations/pull/482) thanks to @tifabien - -### Added - - [470: Add uptodate command](https://github.com/doctrine/migrations/pull/470) thanks to @abacaphiliac - - [477: Add parameters to the output of the dry run migrations](https://github.com/doctrine/migrations/pull/477) thanks to @chrisguitarguy - - [497: Show the content of the generated file on the console](https://github.com/doctrine/migrations/pull/497) thanks to @ErikTrapman - - [480: Don't prompt the user for confirmation when there is nothing to do](https://github.com/doctrine/migrations/pull/480) thanks to @chrisguitarguy - - -## [1.4.1] - 2016-03-14 -### Fixed - - [439: Add missing dependency in the phar build](https://github.com/doctrine/migrations/pull/439) - - -## [1.4.0] - 2016-02-23 -### Added - - [431: Formatted diffs](https://github.com/doctrine/migrations/pull/431) - - [437: Allowing to set the column name from config too](https://github.com/doctrine/migrations/pull/437) - -## [1.3.1] - 2016-02-23 -### Fixed - - [433: Fix: ExecuteCommand by making sure that it autoload the versions](https://github.com/doctrine/migrations/pull/433) - - [434: Fixing an issue in the order at which some configuration key are loaded](https://github.com/doctrine/migrations/pull/434) - -### Changed - - [429: code refactoring for clarity](https://github.com/doctrine/migrations/pull/429) - - [428: code refactoring for clarity](https://github.com/doctrine/migrations/pull/428) - -### Added - - [425: ProxyManager ~2.0 is also compatible with migrations](https://github.com/doctrine/migrations/pull/425) - - -## [1.3.0] - 2016-01-23 -### Fixed - - [421: Fix issue with some method when the migrations were not loaded](https://github.com/doctrine/migrations/pull/421) - - [405: Correcting composer constraints: allowing PHP 7, dropping 5.4 support](https://github.com/doctrine/migrations/pull/405) - - [406: putting the composer.json back in the archive](https://github.com/doctrine/migrations/pull/406) - -### Changed - - [233: Separate Configuration Objects from Configuration File Loading](https://github.com/doctrine/migrations/issues/233) - - [407: Replacing the Schema by a proxy](https://github.com/doctrine/migrations/pull/407) - - [422: Refactor the getConnection into a chainloader](https://github.com/doctrine/migrations/pull/422) - - [Dropped the support for php 5.4](https://github.com/doctrine/migrations/pull/393) - - [Again make the phar more than 3 times smaller](https://github.com/doctrine/migrations/pull/396) - -### Added - - [404: add possibility to read doctrine's config/cli-config.php](https://github.com/doctrine/migrations/pull/404) - - [409: Add a failing test case for an edge case with the write-sql option](https://github.com/doctrine/migrations/pull/409) - - [424: Adding a regression test for the configuration](https://github.com/doctrine/migrations/pull/424) - - [391: Give the possibility to override the Migration template](https://github.com/doctrine/migrations/pull/391) - -## [1.2.2] - 2016-01-07 -### Fixed - - [Fix the write-sql option in the version class too](https://github.com/doctrine/migrations/commit/91043f742da8506ab7115a1d14247ce26375f6f5) - -## [1.2.1] - 2015-12-23 -### Fixed - - [Fix the write-sql option](https://github.com/doctrine/migrations/pull/400) - -## [1.2.0] - 2015-12-15 -### Fixed - - [fix "all migrated versions shown as unavailable executed" ](https://github.com/doctrine/migrations/commit/875849e2a80d37dc8bf5dd0663e464b6789e3b56) - - [Prevent the use of 0 as migration name as it is used internally and conflict](http://github.com/doctrine/migrations/commit/5df49c5ad5dc2265401a54a3b9e6ecb3e7cda8d0) - - [composer: drop symfony/console from suggested packages, since it's required package](http://github.com/doctrine/migrations/commit/d263c7bfac7188009ab0717ed5aa6577e80) - - [fix spaces and complete missing file-docblocks](http://github.com/doctrine/migrations/commit/4b68a69c3e35492b36ec140ebb216cdb80ffe655) - - [RecursiveDirectoryIterator don't obtain some order of the file list.](http://github.com/doctrine/migrations/commit/ed95c05c14381e64404f1135763fcc9b65317b96) - - [Fix the yml parser issue with unescaped backslash in double quoted string](http://github.com/doctrine/migrations/commit/af3cce7d2e490ead821fcbdb54b4772b4913ee1d) - -### Changed - - [Adding compression to the generation of the phar](http://github.com/doctrine/migrations/commit/70730ff8655f0be89ce0f06d1e279930d7eb2550) - - [tests: move autoload of tests to composer](http://github.com/doctrine/migrations/commit/3a4f8368e4b7b95d2e6c51c26f6dc41bb05a5ce5) - - [travis: drop PHP 7.0 from allowed failures, it passes well](http://github.com/doctrine/migrations/commit/57ec2f071a7a840c554058b77f2089893d06ba23) - - [Revert the use of exec to run sql queries](http://github.com/doctrine/migrations/commit/0af6e6e705b905a56cbed26cb5c17faad4c2c04f) - -### Added - - [Adding a little script to prepare and generate the phar](http://github.com/doctrine/migrations/commit/3a8ef413e7f8a42d4e0f3d32d30601b26fb27e60) - - [Configuration: check if migration class exists added](http://github.com/doctrine/migrations/commit/a53d7c83b319341c985d2a21950e260fa55b0b8d) - - [Made composer.json compatible with SF 3.0](http://github.com/doctrine/migrations/commit/4e909f2e661a8414a3e04ce987a09c9e849cd13f) - - [Added configurable version column name](http://github.com/doctrine/migrations/commit/02ddf4318b84a20bb0e3486acfc6e6f41cc63426) - -## [1.1.0] - 2015-09-29 -### Fixed - - [Switch unexisting tag to ](http://github.com/doctrine/migrations/commit/93a81ff0dcc858de4df5c17d97f2f24b3bfa3c36) - - [Ensure that Yaml::parse return an array as it can apparently return a string](http://github.com/doctrine/migrations/commit/1499f0cc3e5f5b20a510ba8f0779d5c68a9e5084) - - [Avoid uploading code coverage to Scrutinizer for HHVM and PHP 7](http://github.com/doctrine/migrations/commit/d47d65021dcb711480bf27f6d0bbba138e220f12) - - [Improve the Travis configuration by persisting the composer cache](http://github.com/doctrine/migrations/commit/bda0509b479ae6605b8fa749b0999b4ce2ff8c04) - - [Keep the license file in the downloadable archives](https://github.com/doctrine/migrations/commit/dfbee38e004899bc078d5d47b13bea53799fca1e#diff-fc723d30b02a4cca7a534518111c1a66) - -### Changed - - [Use short array syntax](http://github.com/doctrine/migrations/commit/50a6e18c95ff617325229a4a649d65c1a11445bc) - - [composer: use PSR-4 autoload](http://github.com/doctrine/migrations/commit/7fb8d301b2f4d4a564433165e0604b7d34013844) - - [refactoring the configuration loading](http://github.com/doctrine/migrations/commit/e95b277111c74cfe65eb959d4471f45a815e1ece) - - [Drop support for php 5.3](https://github.com/doctrine/migrations/commit/0e60856a10e8b510daa612fe25f6245aece77e68) - - [compressing the phar so that it's half the size now](https://github.com/doctrine/migrations/commit/70730ff8655f0be89ce0f06d1e279930d7eb2550) - -### Added - - [Added the ability to auto create migrations in a folder by month and year](http://github.com/doctrine/migrations/commit/0b8e40868e12a36de7f689add61857b9ba29c4bc) - - [Set default name for configuration helper](http://github.com/doctrine/migrations/commit/1f3592f2f126a022db275192f17b8d5c01f19822) - - [Added ability to load config from php array or json files.](http://github.com/doctrine/migrations/commit/8cf01d623f9eb3728ba86c22970347107a8f0be7) - - [Added the possibility to inject the OutputWriter after instantiation](https://github.com/doctrine/migrations/pull/342) - - [Added the --allow-no-migration option to avoid throwing an exception if no migrations are found](https://github.com/doctrine/migrations/commit/a9ec86faa3a3f7f592a633af43b6ef6c9f358239#diff-0a4648a19ba565cda76b349e89552a9b) diff --git a/vendor/doctrine/data-fixtures/LICENSE b/vendor/doctrine/data-fixtures/LICENSE deleted file mode 100644 index 2336c7f..0000000 --- a/vendor/doctrine/data-fixtures/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2006-2015 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/vendor/doctrine/data-fixtures/README.md b/vendor/doctrine/data-fixtures/README.md deleted file mode 100644 index cabb7e2..0000000 --- a/vendor/doctrine/data-fixtures/README.md +++ /dev/null @@ -1,201 +0,0 @@ -# Doctrine Data Fixtures Extension - -[![Build Status](https://travis-ci.org/doctrine/data-fixtures.svg?branch=master)](https://travis-ci.org/doctrine/data-fixtures) - -This extension aims to provide a simple way to manage and execute the loading of data fixtures -for the [Doctrine ORM or ODM](http://www.doctrine-project.org/). You can write fixture classes -by implementing the [`Doctrine\Common\DataFixtures\FixtureInterface`](lib/Doctrine/Common/DataFixtures/FixtureInterface.php) interface: - -```php -namespace MyDataFixtures; - -use Doctrine\Common\Persistence\ObjectManager; -use Doctrine\Common\DataFixtures\FixtureInterface; - -class UserFixtureLoader implements FixtureInterface -{ - public function load(ObjectManager $manager) - { - $user = new User(); - $user->setUsername('jwage'); - $user->setPassword('test'); - - $manager->persist($user); - $manager->flush(); - } -} -``` - -Now you can begin adding the fixtures to a loader instance: - -```php -use Doctrine\Common\DataFixtures\Loader; -use MyDataFixtures\UserDataLoader; - -$loader = new Loader(); -$loader->addFixture(new UserDataLoader()); -``` - -You can load a set of fixtures from a directory as well: - -```php -$loader->loadFromDirectory('/path/to/MyDataFixtures'); -``` - -Or you can load a set of fixtures from a file: - -```php -$loader->loadFromFile('/path/to/MyDataFixtures/MyFixture1.php'); -``` - -You can get the added fixtures using the getFixtures() method: - -```php -$fixtures = $loader->getFixtures(); -``` - -Now you can easily execute the fixtures: - -```php -use Doctrine\Common\DataFixtures\Executor\ORMExecutor; -use Doctrine\Common\DataFixtures\Purger\ORMPurger; - -$purger = new ORMPurger(); -$executor = new ORMExecutor($em, $purger); -$executor->execute($loader->getFixtures()); -``` - -If you want to append the fixtures instead of purging before loading then pass true -to the 2nd argument of execute: - -```php -$executor->execute($loader->getFixtures(), true); -``` - -## Sharing objects between fixtures - -In case if fixture objects have relations to other fixtures, it is now possible -to easily add a reference to that object by name and later reference it to form -a relation. Here is an example fixtures for **Role** and **User** relation - -```php -namespace MyDataFixtures; - -use Doctrine\Common\DataFixtures\AbstractFixture; -use Doctrine\Common\Persistence\ObjectManager; - -class UserRoleDataLoader extends AbstractFixture -{ - public function load(ObjectManager $manager) - { - $adminRole = new Role(); - $adminRole->setName('admin'); - - $anonymousRole = new Role(); - $anonymousRole->setName('anonymous'); - - $manager->persist($adminRole); - $manager->persist($anonymousRole); - $manager->flush(); - - // store reference to admin role for User relation to Role - $this->addReference('admin-role', $adminRole); - } -} -``` - -And the **User** data loading fixture: - -```php -namespace MyDataFixtures; - -use Doctrine\Common\DataFixtures\AbstractFixture; -use Doctrine\Common\Persistence\ObjectManager; - -class UserDataLoader extends AbstractFixture -{ - public function load(ObjectManager $manager) - { - $user = new User(); - $user->setUsername('jwage'); - $user->setPassword('test'); - $user->setRole( - $this->getReference('admin-role') // load the stored reference - ); - - $manager->persist($user); - $manager->flush(); - - // store reference of admin-user for other Fixtures - $this->addReference('admin-user', $user); - } -} -``` - -## Fixture ordering -**Notice** that the fixture loading order is important! To handle it manually -implement one of the following interfaces: - -### OrderedFixtureInterface - -Set the order manually: - -```php -namespace MyDataFixtures; - -use Doctrine\Common\DataFixtures\AbstractFixture; -use Doctrine\Common\DataFixtures\OrderedFixtureInterface; -use Doctrine\Common\Persistence\ObjectManager; - -class MyFixture extends AbstractFixture implements OrderedFixtureInterface -{ - public function load(ObjectManager $manager) - {} - - public function getOrder() - { - return 10; // number in which order to load fixtures - } -} -``` - -### DependentFixtureInterface - -Provide an array of fixture class names: - -```php -namespace MyDataFixtures; - -use Doctrine\Common\DataFixtures\AbstractFixture; -use Doctrine\Common\DataFixtures\DependentFixtureInterface; -use Doctrine\Common\Persistence\ObjectManager; - -class MyFixture extends AbstractFixture implements DependentFixtureInterface -{ - public function load(ObjectManager $manager) - {} - - public function getDependencies() - { - return array('MyDataFixtures\MyOtherFixture'); // fixture classes fixture is dependent on - } -} - -class MyOtherFixture extends AbstractFixture -{ - public function load(ObjectManager $manager) - {} -} -``` - -**Notice** the ordering is relevant to Loader class. - -## Running the tests: - -Phpunit is included in the dev requirements of this package. - -To setup and run tests follow these steps: - -- go to the root directory of data-fixtures -- run: **composer install --dev** -- run: **vendor/bin/phpunit** diff --git a/vendor/doctrine/data-fixtures/UPGRADE b/vendor/doctrine/data-fixtures/UPGRADE deleted file mode 100644 index dba81ad..0000000 --- a/vendor/doctrine/data-fixtures/UPGRADE +++ /dev/null @@ -1,17 +0,0 @@ -# Between v1.0.0-ALPHA1 and v1.0.0-ALPHA2 - -The FixtureInterface was changed from - - interface FixtureInterface - { - load($manager); - } - -to - - use Doctrine\Common\Persistence\ObjectManager; - - interface FixtureInterface - { - load(ObjectManager $manager); - } diff --git a/vendor/doctrine/data-fixtures/composer.json b/vendor/doctrine/data-fixtures/composer.json deleted file mode 100644 index cebc0a9..0000000 --- a/vendor/doctrine/data-fixtures/composer.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "doctrine/data-fixtures", - "type": "library", - "description": "Data Fixtures for all Doctrine Object Managers", - "keywords": [ - "database" - ], - "homepage": "http://www.doctrine-project.org", - "license": "MIT", - "authors": [ - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - } - ], - "require": { - "php": "^7.2", - "doctrine/common": "^2.11" - }, - "conflict": { - "doctrine/phpcr-odm": "<1.3.0" - }, - "require-dev": { - "alcaeus/mongo-php-adapter": "^1.1", - "doctrine/coding-standard": "^6.0", - "doctrine/dbal": "^2.5.4", - "doctrine/mongodb-odm": "^1.3.0", - "doctrine/orm": "^2.5.4", - "phpunit/phpunit": "^7.0" - }, - "suggest": { - "alcaeus/mongo-php-adapter": "For using MongoDB ODM with PHP 7", - "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", - "doctrine/orm": "For loading ORM fixtures", - "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" - }, - "config": { - "platform": { - "ext-mongo": "1.6.16" - }, - "sort-packages": true - }, - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\DataFixtures\\": "lib/Doctrine/Common/DataFixtures" - } - }, - "autoload-dev": { - "psr-4": { - "Doctrine\\Tests\\": "tests/Doctrine/Tests" - } - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/AbstractFixture.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/AbstractFixture.php deleted file mode 100644 index 732c4ca..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/AbstractFixture.php +++ /dev/null @@ -1,97 +0,0 @@ -referenceRepository = $referenceRepository; - } - - /** - * Set the reference entry identified by $name - * and referenced to managed $object. If $name - * already is set, it overrides it - * - * @see Doctrine\Common\DataFixtures\ReferenceRepository::setReference - * - * @param string $name - * @param object $object - managed object - * - * @return void - */ - public function setReference($name, $object) - { - $this->referenceRepository->setReference($name, $object); - } - - /** - * Set the reference entry identified by $name - * and referenced to managed $object. If $name - * already is set, it throws a - * BadMethodCallException exception - * - * @see Doctrine\Common\DataFixtures\ReferenceRepository::addReference - * - * @param string $name - * @param object $object - managed object - * - * @return void - * - * @throws BadMethodCallException - if repository already has a reference by $name. - */ - public function addReference($name, $object) - { - $this->referenceRepository->addReference($name, $object); - } - - /** - * Loads an object using stored reference - * named by $name - * - * @see Doctrine\Common\DataFixtures\ReferenceRepository::getReference - * - * @param string $name - * - * @return object - */ - public function getReference($name) - { - return $this->referenceRepository->getReference($name); - } - - /** - * Check if an object is stored using reference - * named by $name - * - * @see Doctrine\Common\DataFixtures\ReferenceRepository::hasReference - * - * @param string $name - * - * @return bool - */ - public function hasReference($name) - { - return $this->referenceRepository->hasReference($name); - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/DependentFixtureInterface.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/DependentFixtureInterface.php deleted file mode 100644 index 5cac450..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/DependentFixtureInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -referenceRepository = $referenceRepository; - } - - /** - * {@inheritdoc} - */ - public function getSubscribedEvents() - { - return ['postPersist']; - } - - /** - * Populates identities for stored references - */ - public function postPersist(LifecycleEventArgs $args) - { - $object = $args->getDocument(); - - $names = $this->referenceRepository->getReferenceNames($object); - if ($names === false) { - return; - } - - foreach ($names as $name) { - $identity = $args->getDocumentManager() - ->getUnitOfWork() - ->getDocumentIdentifier($object); - - $this->referenceRepository->setReferenceIdentity($name, $identity); - } - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Event/Listener/ORMReferenceListener.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Event/Listener/ORMReferenceListener.php deleted file mode 100644 index ba43e37..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Event/Listener/ORMReferenceListener.php +++ /dev/null @@ -1,57 +0,0 @@ -referenceRepository = $referenceRepository; - } - - /** - * {@inheritdoc} - */ - public function getSubscribedEvents() - { - // would be better to use onClear, but it is supported only in 2.1 - return ['postPersist']; - } - - /** - * Populates identities for stored references - */ - public function postPersist(LifecycleEventArgs $args) - { - $object = $args->getEntity(); - - $names = $this->referenceRepository->getReferenceNames($object); - if ($names === false) { - return; - } - - foreach ($names as $name) { - $identity = $args->getEntityManager() - ->getUnitOfWork() - ->getEntityIdentifier($object); - - $this->referenceRepository->setReferenceIdentity($name, $identity); - } - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Exception/CircularReferenceException.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Exception/CircularReferenceException.php deleted file mode 100644 index 005df34..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Exception/CircularReferenceException.php +++ /dev/null @@ -1,11 +0,0 @@ -referenceRepository = new ReferenceRepository($manager); - } - - /** - * @return ReferenceRepository - */ - public function getReferenceRepository() - { - return $this->referenceRepository; - } - - public function setReferenceRepository(ReferenceRepository $referenceRepository) - { - $this->referenceRepository = $referenceRepository; - } - - /** - * Sets the Purger instance to use for this executor instance. - */ - public function setPurger(PurgerInterface $purger) - { - $this->purger = $purger; - } - - /** - * @return PurgerInterface - */ - public function getPurger() - { - return $this->purger; - } - - /** - * Set the logger callable to execute with the log() method. - * - * @param callable $logger - */ - public function setLogger($logger) - { - $this->logger = $logger; - } - - /** - * Logs a message using the logger. - * - * @param string $message - */ - public function log($message) - { - $logger = $this->logger; - $logger($message); - } - - /** - * Load a fixture with the given persistence manager. - */ - public function load(ObjectManager $manager, FixtureInterface $fixture) - { - if ($this->logger) { - $prefix = ''; - if ($fixture instanceof OrderedFixtureInterface) { - $prefix = sprintf('[%d] ', $fixture->getOrder()); - } - $this->log('loading ' . $prefix . get_class($fixture)); - } - // additionally pass the instance of reference repository to shared fixtures - if ($fixture instanceof SharedFixtureInterface) { - $fixture->setReferenceRepository($this->referenceRepository); - } - $fixture->load($manager); - $manager->clear(); - } - - /** - * Purges the database before loading. - * - * @throws Exception if the purger is not defined. - */ - public function purge() - { - if ($this->purger === null) { - throw new Exception('Doctrine\Common\DataFixtures\Purger\PurgerInterface instance is required if you want to purge the database before loading your data fixtures.'); - } - if ($this->logger) { - $this->log('purging database'); - } - $this->purger->purge(); - } - - /** - * Executes the given array of data fixtures. - * - * @param array $fixtures Array of fixtures to execute. - * @param bool $append Whether to append the data fixtures or purge the database before loading. - */ - abstract public function execute(array $fixtures, $append = false); -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/MongoDBExecutor.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/MongoDBExecutor.php deleted file mode 100644 index b0fe707..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/MongoDBExecutor.php +++ /dev/null @@ -1,67 +0,0 @@ -dm = $dm; - if ($purger !== null) { - $this->purger = $purger; - $this->purger->setDocumentManager($dm); - } - parent::__construct($dm); - $this->listener = new MongoDBReferenceListener($this->referenceRepository); - $dm->getEventManager()->addEventSubscriber($this->listener); - } - - /** - * Retrieve the DocumentManager instance this executor instance is using. - * - * @return DocumentManager - */ - public function getObjectManager() - { - return $this->dm; - } - - /** @inheritDoc */ - public function setReferenceRepository(ReferenceRepository $referenceRepository) - { - $this->dm->getEventManager()->removeEventListener( - $this->listener->getSubscribedEvents(), - $this->listener - ); - - $this->referenceRepository = $referenceRepository; - $this->listener = new MongoDBReferenceListener($this->referenceRepository); - $this->dm->getEventManager()->addEventSubscriber($this->listener); - } - - /** @inheritDoc */ - public function execute(array $fixtures, $append = false) - { - if ($append === false) { - $this->purge(); - } - foreach ($fixtures as $fixture) { - $this->load($this->dm, $fixture); - } - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php deleted file mode 100644 index 246c0ef..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php +++ /dev/null @@ -1,73 +0,0 @@ -em = $em; - if ($purger !== null) { - $this->purger = $purger; - $this->purger->setEntityManager($em); - } - parent::__construct($em); - $this->listener = new ORMReferenceListener($this->referenceRepository); - $em->getEventManager()->addEventSubscriber($this->listener); - } - - /** - * Retrieve the EntityManagerInterface instance this executor instance is using. - * - * @return EntityManagerInterface - */ - public function getObjectManager() - { - return $this->em; - } - - /** @inheritDoc */ - public function setReferenceRepository(ReferenceRepository $referenceRepository) - { - $this->em->getEventManager()->removeEventListener( - $this->listener->getSubscribedEvents(), - $this->listener - ); - - $this->referenceRepository = $referenceRepository; - $this->listener = new ORMReferenceListener($this->referenceRepository); - $this->em->getEventManager()->addEventSubscriber($this->listener); - } - - /** @inheritDoc */ - public function execute(array $fixtures, $append = false) - { - $executor = $this; - $this->em->transactional(static function (EntityManagerInterface $em) use ($executor, $fixtures, $append) { - if ($append === false) { - $executor->purge(); - } - foreach ($fixtures as $fixture) { - $executor->load($em, $fixture); - } - }); - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/PHPCRExecutor.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/PHPCRExecutor.php deleted file mode 100644 index e30b365..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/PHPCRExecutor.php +++ /dev/null @@ -1,62 +0,0 @@ -dm = $dm; - if ($purger === null) { - return; - } - - $purger->setDocumentManager($dm); - $this->setPurger($purger); - } - - public function getObjectManager() - { - return $this->dm; - } - - /** @inheritDoc */ - public function execute(array $fixtures, $append = false) - { - $that = $this; - - $function = static function ($dm) use ($append, $that, $fixtures) { - if ($append === false) { - $that->purge(); - } - - foreach ($fixtures as $fixture) { - $that->load($dm, $fixture); - } - }; - - if (method_exists($this->dm, 'transactional')) { - $this->dm->transactional($function); - } else { - $function($this->dm); - } - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/FixtureInterface.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/FixtureInterface.php deleted file mode 100644 index 3cc3fc7..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/FixtureInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -loadFromIterator($iterator); - } - - /** - * Find fixtures classes in a given file and load them. - * - * @param string $fileName File to find fixture classes in. - * - * @return array $fixtures Array of loaded fixture object instances. - */ - public function loadFromFile($fileName) - { - if (! is_readable($fileName)) { - throw new InvalidArgumentException(sprintf('"%s" does not exist or is not readable', $fileName)); - } - - $iterator = new ArrayIterator([new SplFileInfo($fileName)]); - - return $this->loadFromIterator($iterator); - } - - /** - * Has fixture? - * - * @param FixtureInterface $fixture - * - * @return bool - */ - public function hasFixture($fixture) - { - return isset($this->fixtures[get_class($fixture)]); - } - - /** - * Get a specific fixture instance - * - * @param string $className - * - * @return FixtureInterface - */ - public function getFixture($className) - { - if (! isset($this->fixtures[$className])) { - throw new InvalidArgumentException(sprintf( - '"%s" is not a registered fixture', - $className - )); - } - - return $this->fixtures[$className]; - } - - /** - * Add a fixture object instance to the loader. - */ - public function addFixture(FixtureInterface $fixture) - { - $fixtureClass = get_class($fixture); - - if (isset($this->fixtures[$fixtureClass])) { - return; - } - - if ($fixture instanceof OrderedFixtureInterface && $fixture instanceof DependentFixtureInterface) { - throw new InvalidArgumentException(sprintf( - 'Class "%s" can\'t implement "%s" and "%s" at the same time.', - get_class($fixture), - 'OrderedFixtureInterface', - 'DependentFixtureInterface' - )); - } - - $this->fixtures[$fixtureClass] = $fixture; - - if ($fixture instanceof OrderedFixtureInterface) { - $this->orderFixturesByNumber = true; - } elseif ($fixture instanceof DependentFixtureInterface) { - $this->orderFixturesByDependencies = true; - foreach ($fixture->getDependencies() as $class) { - if (! class_exists($class)) { - continue; - } - - $this->addFixture($this->createFixture($class)); - } - } - } - - /** - * Returns the array of data fixtures to execute. - * - * @return array $fixtures - */ - public function getFixtures() - { - $this->orderedFixtures = []; - - if ($this->orderFixturesByNumber) { - $this->orderFixturesByNumber(); - } - - if ($this->orderFixturesByDependencies) { - $this->orderFixturesByDependencies(); - } - - if (! $this->orderFixturesByNumber && ! $this->orderFixturesByDependencies) { - $this->orderedFixtures = $this->fixtures; - } - - return $this->orderedFixtures; - } - - /** - * Check if a given fixture is transient and should not be considered a data fixtures - * class. - * - * @return bool - */ - public function isTransient($className) - { - $rc = new ReflectionClass($className); - if ($rc->isAbstract()) { - return true; - } - - $interfaces = class_implements($className); - - return ! in_array(FixtureInterface::class, $interfaces); - } - - /** - * Creates the fixture object from the class. - * - * @param string $class - * - * @return FixtureInterface - */ - protected function createFixture($class) - { - return new $class(); - } - - /** - * Orders fixtures by number - * - * @return void - * - * @todo maybe there is a better way to handle reordering - */ - private function orderFixturesByNumber() - { - $this->orderedFixtures = $this->fixtures; - usort($this->orderedFixtures, static function ($a, $b) { - if ($a instanceof OrderedFixtureInterface && $b instanceof OrderedFixtureInterface) { - if ($a->getOrder() === $b->getOrder()) { - return 0; - } - - return $a->getOrder() < $b->getOrder() ? -1 : 1; - } - - if ($a instanceof OrderedFixtureInterface) { - return $a->getOrder() === 0 ? 0 : 1; - } - - if ($b instanceof OrderedFixtureInterface) { - return $b->getOrder() === 0 ? 0 : -1; - } - - return 0; - }); - } - - /** - * Orders fixtures by dependencies - * - * @return void - */ - private function orderFixturesByDependencies() - { - $sequenceForClasses = []; - - // If fixtures were already ordered by number then we need - // to remove classes which are not instances of OrderedFixtureInterface - // in case fixtures implementing DependentFixtureInterface exist. - // This is because, in that case, the method orderFixturesByDependencies - // will handle all fixtures which are not instances of - // OrderedFixtureInterface - if ($this->orderFixturesByNumber) { - $count = count($this->orderedFixtures); - - for ($i = 0; $i < $count; ++$i) { - if ($this->orderedFixtures[$i] instanceof OrderedFixtureInterface) { - continue; - } - - unset($this->orderedFixtures[$i]); - } - } - - // First we determine which classes has dependencies and which don't - foreach ($this->fixtures as $fixture) { - $fixtureClass = get_class($fixture); - - if ($fixture instanceof OrderedFixtureInterface) { - continue; - } - - if ($fixture instanceof DependentFixtureInterface) { - $dependenciesClasses = $fixture->getDependencies(); - - $this->validateDependencies($dependenciesClasses); - - if (! is_array($dependenciesClasses) || empty($dependenciesClasses)) { - throw new InvalidArgumentException(sprintf('Method "%s" in class "%s" must return an array of classes which are dependencies for the fixture, and it must be NOT empty.', 'getDependencies', $fixtureClass)); - } - - if (in_array($fixtureClass, $dependenciesClasses)) { - throw new InvalidArgumentException(sprintf('Class "%s" can\'t have itself as a dependency', $fixtureClass)); - } - - // We mark this class as unsequenced - $sequenceForClasses[$fixtureClass] = -1; - } else { - // This class has no dependencies, so we assign 0 - $sequenceForClasses[$fixtureClass] = 0; - } - } - - // Now we order fixtures by sequence - $sequence = 1; - $lastCount = -1; - - while (($count = count($unsequencedClasses = $this->getUnsequencedClasses($sequenceForClasses))) > 0 && $count !== $lastCount) { - foreach ($unsequencedClasses as $key => $class) { - $fixture = $this->fixtures[$class]; - $dependencies = $fixture->getDependencies(); - $unsequencedDependencies = $this->getUnsequencedClasses($sequenceForClasses, $dependencies); - - if (count($unsequencedDependencies) !== 0) { - continue; - } - - $sequenceForClasses[$class] = $sequence++; - } - - $lastCount = $count; - } - - $orderedFixtures = []; - - // If there're fixtures unsequenced left and they couldn't be sequenced, - // it means we have a circular reference - if ($count > 0) { - $msg = 'Classes "%s" have produced a CircularReferenceException. '; - $msg .= 'An example of this problem would be the following: Class C has class B as its dependency. '; - $msg .= 'Then, class B has class A has its dependency. Finally, class A has class C as its dependency. '; - $msg .= 'This case would produce a CircularReferenceException.'; - - throw new CircularReferenceException(sprintf($msg, implode(',', $unsequencedClasses))); - } else { - // We order the classes by sequence - asort($sequenceForClasses); - - foreach ($sequenceForClasses as $class => $sequence) { - // If fixtures were ordered - $orderedFixtures[] = $this->fixtures[$class]; - } - } - - $this->orderedFixtures = array_merge($this->orderedFixtures, $orderedFixtures); - } - - private function validateDependencies($dependenciesClasses) - { - $loadedFixtureClasses = array_keys($this->fixtures); - - foreach ($dependenciesClasses as $class) { - if (! in_array($class, $loadedFixtureClasses)) { - throw new RuntimeException(sprintf('Fixture "%s" was declared as a dependency, but it should be added in fixture loader first.', $class)); - } - } - - return true; - } - - private function getUnsequencedClasses($sequences, $classes = null) - { - $unsequencedClasses = []; - - if ($classes === null) { - $classes = array_keys($sequences); - } - - foreach ($classes as $class) { - if ($sequences[$class] !== -1) { - continue; - } - - $unsequencedClasses[] = $class; - } - - return $unsequencedClasses; - } - - /** - * Load fixtures from files contained in iterator. - * - * @param Iterator $iterator Iterator over files from which fixtures should be loaded. - * - * @return array $fixtures Array of loaded fixture object instances. - */ - private function loadFromIterator(Iterator $iterator) - { - $includedFiles = []; - foreach ($iterator as $file) { - $fileName = $file->getBasename($this->fileExtension); - if ($fileName === $file->getBasename()) { - continue; - } - - $sourceFile = realpath($file->getPathName()); - require_once $sourceFile; - $includedFiles[] = $sourceFile; - } - - $fixtures = []; - $declared = get_declared_classes(); - // Make the declared classes order deterministic - sort($declared); - - foreach ($declared as $className) { - $reflClass = new ReflectionClass($className); - $sourceFile = $reflClass->getFileName(); - - if (! in_array($sourceFile, $includedFiles) || $this->isTransient($className)) { - continue; - } - - $fixture = $this->createFixture($className); - $fixtures[] = $fixture; - $this->addFixture($fixture); - } - - return $fixtures; - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/OrderedFixtureInterface.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/OrderedFixtureInterface.php deleted file mode 100644 index e595926..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/OrderedFixtureInterface.php +++ /dev/null @@ -1,20 +0,0 @@ -getManager()->getUnitOfWork(); - $simpleReferences = []; - - foreach ($this->getReferences() as $name => $reference) { - $className = $this->getRealClass(get_class($reference)); - - $simpleReferences[$name] = [$className, $this->getIdentifier($reference, $unitOfWork)]; - } - - return json_encode([ - 'references' => $simpleReferences, - 'identities' => $this->getIdentities(), - ]); - } - - /** - * Unserialize reference repository - * - * @param string $serializedData Serialized data - */ - public function unserialize($serializedData) - { - $repositoryData = json_decode($serializedData, true); - $references = $repositoryData['references']; - - foreach ($references as $name => $proxyReference) { - $this->setReference( - $name, - $this->getManager()->getReference( - $proxyReference[0], // entity class name - $proxyReference[1] // identifiers - ) - ); - } - - $identities = $repositoryData['identities']; - - foreach ($identities as $name => $identity) { - $this->setReferenceIdentity($name, $identity); - } - } - - /** - * Load data fixture reference repository - * - * @param string $baseCacheName Base cache name - * - * @return bool - */ - public function load($baseCacheName) - { - $filename = $baseCacheName . '.ser'; - - if (! file_exists($filename)) { - return false; - } - - $serializedData = file_get_contents($filename); - - if ($serializedData === false) { - return false; - } - - $this->unserialize($serializedData); - - return true; - } - - /** - * Save data fixture reference repository - * - * @param string $baseCacheName Base cache name - */ - public function save($baseCacheName) - { - $serializedData = $this->serialize(); - - file_put_contents($baseCacheName . '.ser', $serializedData); - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/MongoDBPurger.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/MongoDBPurger.php deleted file mode 100644 index d7d2bfe..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/MongoDBPurger.php +++ /dev/null @@ -1,58 +0,0 @@ -dm = $dm; - } - - /** - * Set the DocumentManager instance this purger instance should use. - */ - public function setDocumentManager(DocumentManager $dm) - { - $this->dm = $dm; - } - - /** - * Retrieve the DocumentManager instance this purger instance is using. - * - * @return DocumentManager - */ - public function getObjectManager() - { - return $this->dm; - } - - /** @inheritDoc */ - public function purge() - { - $metadatas = $this->dm->getMetadataFactory()->getAllMetadata(); - foreach ($metadatas as $metadata) { - if ($metadata->isMappedSuperclass) { - continue; - } - - $this->dm->getDocumentCollection($metadata->name)->drop(); - } - $this->dm->getSchemaManager()->ensureIndexes(); - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/ORMPurger.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/ORMPurger.php deleted file mode 100644 index 6aa2410..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/ORMPurger.php +++ /dev/null @@ -1,271 +0,0 @@ -em = $em; - $this->excluded = $excluded; - } - - /** - * Set the purge mode - * - * @param int $mode - * - * @return void - */ - public function setPurgeMode($mode) - { - $this->purgeMode = $mode; - } - - /** - * Get the purge mode - * - * @return int - */ - public function getPurgeMode() - { - return $this->purgeMode; - } - - /** - * Set the EntityManagerInterface instance this purger instance should use. - */ - public function setEntityManager(EntityManagerInterface $em) - { - $this->em = $em; - } - - /** - * Retrieve the EntityManagerInterface instance this purger instance is using. - * - * @return EntityManagerInterface - */ - public function getObjectManager() - { - return $this->em; - } - - /** @inheritDoc */ - public function purge() - { - $classes = []; - - foreach ($this->em->getMetadataFactory()->getAllMetadata() as $metadata) { - if ($metadata->isMappedSuperclass || (isset($metadata->isEmbeddedClass) && $metadata->isEmbeddedClass)) { - continue; - } - - $classes[] = $metadata; - } - - $commitOrder = $this->getCommitOrder($this->em, $classes); - - // Get platform parameters - $platform = $this->em->getConnection()->getDatabasePlatform(); - - // Drop association tables first - $orderedTables = $this->getAssociationTables($commitOrder, $platform); - - // Drop tables in reverse commit order - for ($i = count($commitOrder) - 1; $i >= 0; --$i) { - $class = $commitOrder[$i]; - - if ((isset($class->isEmbeddedClass) && $class->isEmbeddedClass) || - $class->isMappedSuperclass || - ($class->isInheritanceTypeSingleTable() && $class->name !== $class->rootEntityName) - ) { - continue; - } - - $orderedTables[] = $this->getTableName($class, $platform); - } - - $connection = $this->em->getConnection(); - $filterExpr = $connection->getConfiguration()->getFilterSchemaAssetsExpression(); - $emptyFilterExpression = empty($filterExpr); - - $schemaAssetsFilter = method_exists($connection->getConfiguration(), 'getSchemaAssetsFilter') ? $connection->getConfiguration()->getSchemaAssetsFilter() : null; - - foreach ($orderedTables as $tbl) { - // If we have a filter expression, check it and skip if necessary - if (! $emptyFilterExpression && ! preg_match($filterExpr, $tbl)) { - continue; - } - - // If the table is excluded, skip it as well - if (array_search($tbl, $this->excluded) !== false) { - continue; - } - - // Support schema asset filters as presented in - if (is_callable($schemaAssetsFilter) && ! $schemaAssetsFilter($tbl)) { - continue; - } - - if ($this->purgeMode === self::PURGE_MODE_DELETE) { - $connection->executeUpdate('DELETE FROM ' . $tbl); - } else { - $connection->executeUpdate($platform->getTruncateTableSQL($tbl, true)); - } - } - } - - /** - * @param ClassMetadata[] $classes - * - * @return ClassMetadata[] - */ - private function getCommitOrder(EntityManagerInterface $em, array $classes) - { - $sorter = new TopologicalSorter(); - - foreach ($classes as $class) { - if (! $sorter->hasNode($class->name)) { - $sorter->addNode($class->name, $class); - } - - // $class before its parents - foreach ($class->parentClasses as $parentClass) { - $parentClass = $em->getClassMetadata($parentClass); - $parentClassName = $parentClass->getName(); - - if (! $sorter->hasNode($parentClassName)) { - $sorter->addNode($parentClassName, $parentClass); - } - - $sorter->addDependency($class->name, $parentClassName); - } - - foreach ($class->associationMappings as $assoc) { - if (! $assoc['isOwningSide']) { - continue; - } - - /** @var ClassMetadata $targetClass */ - $targetClass = $em->getClassMetadata($assoc['targetEntity']); - $targetClassName = $targetClass->getName(); - - if (! $sorter->hasNode($targetClassName)) { - $sorter->addNode($targetClassName, $targetClass); - } - - // add dependency ($targetClass before $class) - $sorter->addDependency($targetClassName, $class->name); - - // parents of $targetClass before $class, too - foreach ($targetClass->parentClasses as $parentClass) { - $parentClass = $em->getClassMetadata($parentClass); - $parentClassName = $parentClass->getName(); - - if (! $sorter->hasNode($parentClassName)) { - $sorter->addNode($parentClassName, $parentClass); - } - - $sorter->addDependency($parentClassName, $class->name); - } - } - } - - return array_reverse($sorter->sort()); - } - - /** - * @param array $classes - * - * @return array - */ - private function getAssociationTables(array $classes, AbstractPlatform $platform) - { - $associationTables = []; - - foreach ($classes as $class) { - foreach ($class->associationMappings as $assoc) { - if (! $assoc['isOwningSide'] || $assoc['type'] !== ClassMetadata::MANY_TO_MANY) { - continue; - } - - $associationTables[] = $this->getJoinTableName($assoc, $class, $platform); - } - } - - return $associationTables; - } - - /** - * @param ClassMetadata $class - * @param AbstractPlatform $platform - * - * @return string - */ - private function getTableName($class, $platform) - { - if (isset($class->table['schema']) && ! method_exists($class, 'getSchemaName')) { - return $class->table['schema'] . '.' . $this->em->getConfiguration()->getQuoteStrategy()->getTableName($class, $platform); - } - - return $this->em->getConfiguration()->getQuoteStrategy()->getTableName($class, $platform); - } - - /** - * @param array $association - * @param ClassMetadata $class - * @param AbstractPlatform $platform - * - * @return string - */ - private function getJoinTableName($assoc, $class, $platform) - { - if (isset($assoc['joinTable']['schema']) && ! method_exists($class, 'getSchemaName')) { - return $assoc['joinTable']['schema'] . '.' . $this->em->getConfiguration()->getQuoteStrategy()->getJoinTableName($assoc, $class, $platform); - } - - return $this->em->getConfiguration()->getQuoteStrategy()->getJoinTableName($assoc, $class, $platform); - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PHPCRPurger.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PHPCRPurger.php deleted file mode 100644 index 800f519..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PHPCRPurger.php +++ /dev/null @@ -1,43 +0,0 @@ -dm = $dm; - } - - public function setDocumentManager(DocumentManager $dm) - { - $this->dm = $dm; - } - - public function getObjectManager() - { - return $this->dm; - } - - /** - * @inheritDoc - */ - public function purge() - { - $session = $this->dm->getPhpcrSession(); - NodeHelper::purgeWorkspace($session); - $session->save(); - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PurgerInterface.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PurgerInterface.php deleted file mode 100644 index c41ea50..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Purger/PurgerInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -manager = $manager; - } - - /** - * Get identifier for a unit of work - * - * @param object $reference Reference object - * @param object $uow Unit of work - * - * @return array - */ - protected function getIdentifier($reference, $uow) - { - // In case Reference is not yet managed in UnitOfWork - if (! $this->hasIdentifier($reference)) { - $class = $this->manager->getClassMetadata(get_class($reference)); - - return $class->getIdentifierValues($reference); - } - - // Dealing with ORM UnitOfWork - if (method_exists($uow, 'getEntityIdentifier')) { - return $uow->getEntityIdentifier($reference); - } - - // PHPCR ODM UnitOfWork - if ($this->manager instanceof PhpcrDocumentManager) { - return $uow->getDocumentId($reference); - } - - // ODM UnitOfWork - return $uow->getDocumentIdentifier($reference); - } - - /** - * Set the reference entry identified by $name - * and referenced to $reference. If $name - * already is set, it overrides it - * - * @param string $name - * @param object $reference - */ - public function setReference($name, $reference) - { - $this->references[$name] = $reference; - - if (! $this->hasIdentifier($reference)) { - return; - } - - // in case if reference is set after flush, store its identity - $uow = $this->manager->getUnitOfWork(); - $this->identities[$name] = $this->getIdentifier($reference, $uow); - } - - /** - * Store the identifier of a reference - * - * @param string $name - * @param mixed $identity - */ - public function setReferenceIdentity($name, $identity) - { - $this->identities[$name] = $identity; - } - - /** - * Set the reference entry identified by $name - * and referenced to managed $object. $name must - * not be set yet - * - * Notice: in case if identifier is generated after - * the record is inserted, be sure tu use this method - * after $object is flushed - * - * @param string $name - * @param object $object - managed object - * - * @return void - * - * @throws BadMethodCallException - if repository already has a reference by $name. - */ - public function addReference($name, $object) - { - if (isset($this->references[$name])) { - throw new BadMethodCallException(sprintf('Reference to "%s" already exists, use method setReference in order to override it', $name)); - } - - $this->setReference($name, $object); - } - - /** - * Loads an object using stored reference - * named by $name - * - * @param string $name - * - * @return object - * - * @throws OutOfBoundsException - if repository does not exist. - */ - public function getReference($name) - { - if (! $this->hasReference($name)) { - throw new OutOfBoundsException(sprintf('Reference to "%s" does not exist', $name)); - } - - $reference = $this->references[$name]; - $meta = $this->manager->getClassMetadata(get_class($reference)); - - if (! $this->manager->contains($reference) && isset($this->identities[$name])) { - $reference = $this->manager->getReference( - $meta->name, - $this->identities[$name] - ); - $this->references[$name] = $reference; // already in identity map - } - - return $reference; - } - - /** - * Check if an object is stored using reference - * named by $name - * - * @param string $name - * - * @return bool - */ - public function hasReference($name) - { - return isset($this->references[$name]); - } - - /** - * Searches for reference names in the - * list of stored references - * - * @param object $reference - * - * @return array - */ - public function getReferenceNames($reference) - { - return array_keys($this->references, $reference, true); - } - - /** - * Checks if reference has identity stored - * - * @param string $name - */ - public function hasIdentity($name) - { - return array_key_exists($name, $this->identities); - } - - /** - * Get all stored identities - * - * @return array - */ - public function getIdentities() - { - return $this->identities; - } - - /** - * Get all stored references - * - * @return array - */ - public function getReferences() - { - return $this->references; - } - - /** - * Get object manager - * - * @return ObjectManager - */ - public function getManager() - { - return $this->manager; - } - - /** - * Checks if object has identifier already in unit of work. - * - * @param string $reference - * - * @return bool - */ - private function hasIdentifier($reference) - { - // in case if reference is set after flush, store its identity - $uow = $this->manager->getUnitOfWork(); - - if ($this->manager instanceof PhpcrDocumentManager) { - return $uow->contains($reference); - } - - return $uow->isInIdentityMap($reference); - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/SharedFixtureInterface.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/SharedFixtureInterface.php deleted file mode 100644 index f58b4c3..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/SharedFixtureInterface.php +++ /dev/null @@ -1,16 +0,0 @@ -allowCyclicDependencies = $allowCyclicDependencies; - } - - /** - * Adds a new node (vertex) to the graph, assigning its hash and value. - * - * @param string $hash - * - * @return void - */ - public function addNode($hash, ClassMetadata $node) - { - $this->nodeList[$hash] = new Vertex($node); - } - - /** - * Checks the existence of a node in the graph. - * - * @param string $hash - * - * @return bool - */ - public function hasNode($hash) - { - return isset($this->nodeList[$hash]); - } - - /** - * Adds a new dependency (edge) to the graph using their hashes. - * - * @param string $fromHash - * @param string $toHash - * - * @return void - */ - public function addDependency($fromHash, $toHash) - { - $definition = $this->nodeList[$fromHash]; - - $definition->dependencyList[] = $toHash; - } - - /** - * Return a valid order list of all current nodes. - * The desired topological sorting is the postorder of these searches. - * - * Note: Highly performance-sensitive method. - * - * @return array - * - * @throws RuntimeException - * @throws CircularReferenceException - */ - public function sort() - { - foreach ($this->nodeList as $definition) { - if ($definition->state !== Vertex::NOT_VISITED) { - continue; - } - - $this->visit($definition); - } - - $sortedList = $this->sortedNodeList; - - $this->nodeList = []; - $this->sortedNodeList = []; - - return $sortedList; - } - - /** - * Visit a given node definition for reordering. - * - * Note: Highly performance-sensitive method. - * - * @throws RuntimeException - * @throws CircularReferenceException - */ - private function visit(Vertex $definition) - { - $definition->state = Vertex::IN_PROGRESS; - - foreach ($definition->dependencyList as $dependency) { - if (! isset($this->nodeList[$dependency])) { - throw new RuntimeException(sprintf( - 'Fixture "%s" has a dependency of fixture "%s", but it not listed to be loaded.', - get_class($definition->value), - $dependency - )); - } - - $childDefinition = $this->nodeList[$dependency]; - - // allow self referencing classes - if ($definition === $childDefinition) { - continue; - } - - switch ($childDefinition->state) { - case Vertex::VISITED: - break; - case Vertex::IN_PROGRESS: - if (! $this->allowCyclicDependencies) { - throw new CircularReferenceException( - sprintf( - 'Graph contains cyclic dependency between the classes "%s" and' - . ' "%s". An example of this problem would be the following: ' - . 'Class C has class B as its dependency. Then, class B has class A has its dependency. ' - . 'Finally, class A has class C as its dependency.', - $definition->value->getName(), - $childDefinition->value->getName() - ) - ); - } - break; - case Vertex::NOT_VISITED: - $this->visit($childDefinition); - } - } - - $definition->state = Vertex::VISITED; - - $this->sortedNodeList[] = $definition->value; - } -} diff --git a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Sorter/Vertex.php b/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Sorter/Vertex.php deleted file mode 100644 index feee46c..0000000 --- a/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Sorter/Vertex.php +++ /dev/null @@ -1,34 +0,0 @@ -value = $value; - } -} diff --git a/vendor/doctrine/data-fixtures/phpcs.xml.dist b/vendor/doctrine/data-fixtures/phpcs.xml.dist deleted file mode 100644 index 1a5fe7e..0000000 --- a/vendor/doctrine/data-fixtures/phpcs.xml.dist +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - lib - tests - - - - - - - - - - - - - - tests/* - - - - lib/Doctrine/Common/DataFixtures/AbstractFixture.php - lib/Doctrine/Common/DataFixtures/Executor/AbstractExecutor.php - - - - lib/Doctrine/Common/DataFixtures/Exception/CircularReferenceException.php - - - - lib/Doctrine/Common/DataFixtures/DependentFixtureInterface.php - lib/Doctrine/Common/DataFixtures/FixtureInterface.php - lib/Doctrine/Common/DataFixtures/Purger/PurgerInterface.php - lib/Doctrine/Common/DataFixtures/OrderedFixtureInterface.php - lib/Doctrine/Common/DataFixtures/SharedFixtureInterface.php - - - - tests/* - - diff --git a/vendor/doctrine/dbal/.doctrine-project.json b/vendor/doctrine/dbal/.doctrine-project.json deleted file mode 100644 index 7b97cb4..0000000 --- a/vendor/doctrine/dbal/.doctrine-project.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "active": true, - "name": "Database Abstraction Layer", - "shortName": "DBAL", - "slug": "dbal", - "docsSlug": "doctrine-dbal", - "versions": [ - { - "name": "3.0", - "branchName": "develop", - "slug": "latest", - "upcoming": true - }, - { - "name": "2.10", - "branchName": "master", - "slug": "2.10", - "upcoming": true - }, - { - "name": "2.9", - "branchName": "2.9", - "slug": "2.9", - "current": true, - "aliases": [ - "current", - "stable" - ] - }, - { - "name": "2.8", - "branchName": "2.8", - "slug": "2.8", - "maintained": false - }, - { - "name": "2.7", - "branchName": "2.7", - "slug": "2.7", - "maintained": false - }, - { - "name": "2.6", - "branchName": "2.6", - "slug": "2.6", - "maintained": false - }, - { - "name": "2.5", - "branchName": "2.5", - "slug": "2.5", - "maintained": false - } - ] -} diff --git a/vendor/doctrine/dbal/LICENSE b/vendor/doctrine/dbal/LICENSE deleted file mode 100644 index e8fdec4..0000000 --- a/vendor/doctrine/dbal/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006-2018 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/doctrine/dbal/README.md b/vendor/doctrine/dbal/README.md deleted file mode 100644 index 7495d20..0000000 --- a/vendor/doctrine/dbal/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# Doctrine DBAL - -| [Master][Master] | [2.9][2.9] | [Develop][develop] | -|:----------------:|:----------:|:------------------:| -| [![Build status][Master image]][Master] | [![Build status][2.9 image]][2.9] | [![Build status][develop image]][develop] | -| [![Build Status][ContinuousPHP image]][ContinuousPHP] | [![Build Status][ContinuousPHP 2.9 image]][ContinuousPHP] | [![Build Status][ContinuousPHP develop image]][ContinuousPHP] | -| [![Code Coverage][Coverage image]][Scrutinizer Master] | [![Code Coverage][Coverage 2.9 image]][Scrutinizer 2.9] | [![Code Coverage][Coverage develop image]][Scrutinizer develop] | -| [![Code Quality][Quality image]][Scrutinizer Master] | [![Code Quality][Quality 2.9 image]][Scrutinizer 2.9] | [![Code Quality][Quality develop image]][Scrutinizer develop] | -| [![AppVeyor][AppVeyor master image]][AppVeyor master] | [![AppVeyor][AppVeyor 2.9 image]][AppVeyor 2.9] | [![AppVeyor][AppVeyor develop image]][AppVeyor develop] | - -Powerful database abstraction layer with many features for database schema introspection, schema management and PDO abstraction. - -## More resources: - -* [Website](http://www.doctrine-project.org/projects/dbal.html) -* [Documentation](http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/) -* [Issue Tracker](https://github.com/doctrine/dbal/issues) - - [Master image]: https://img.shields.io/travis/doctrine/dbal/master.svg?style=flat-square - [Coverage image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/dbal/master.svg?style=flat-square - [Quality image]: https://img.shields.io/scrutinizer/g/doctrine/dbal/master.svg?style=flat-square - [ContinuousPHP image]: https://img.shields.io/continuousphp/git-hub/doctrine/dbal/master.svg?style=flat-square - [Master]: https://travis-ci.org/doctrine/dbal - [Scrutinizer Master]: https://scrutinizer-ci.com/g/doctrine/dbal/ - [AppVeyor master]: https://ci.appveyor.com/project/doctrine/dbal/branch/master - [AppVeyor master image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/master?svg=true - [ContinuousPHP]: https://continuousphp.com/git-hub/doctrine/dbal - - [2.9 image]: https://img.shields.io/travis/doctrine/dbal/2.9.svg?style=flat-square - [Coverage 2.9 image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/dbal/2.9.svg?style=flat-square - [Quality 2.9 image]: https://img.shields.io/scrutinizer/g/doctrine/dbal/2.9.svg?style=flat-square - [ContinuousPHP 2.9 image]: https://img.shields.io/continuousphp/git-hub/doctrine/dbal/2.9.svg?style=flat-square - [2.9]: https://github.com/doctrine/dbal/tree/2.9 - [Scrutinizer 2.9]: https://scrutinizer-ci.com/g/doctrine/dbal/?branch=2.9 - [AppVeyor 2.9]: https://ci.appveyor.com/project/doctrine/dbal/branch/2.9 - [AppVeyor 2.9 image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/2.9?svg=true - - [develop]: https://github.com/doctrine/dbal/tree/develop - [develop image]: https://img.shields.io/travis/doctrine/dbal/develop.svg?style=flat-square - [Coverage develop image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/dbal/develop.svg?style=flat-square - [Quality develop image]: https://img.shields.io/scrutinizer/g/doctrine/dbal/develop.svg?style=flat-square - [ContinuousPHP develop image]: https://img.shields.io/continuousphp/git-hub/doctrine/dbal/develop.svg?style=flat-square - [develop]: https://github.com/doctrine/dbal/tree/develop - [Scrutinizer develop]: https://scrutinizer-ci.com/g/doctrine/dbal/?branch=develop - [AppVeyor develop]: https://ci.appveyor.com/project/doctrine/dbal/branch/develop - [AppVeyor develop image]: https://ci.appveyor.com/api/projects/status/i88kitq8qpbm0vie/branch/develop?svg=true diff --git a/vendor/doctrine/dbal/SECURITY.md b/vendor/doctrine/dbal/SECURITY.md deleted file mode 100644 index e18f0dd..0000000 --- a/vendor/doctrine/dbal/SECURITY.md +++ /dev/null @@ -1,14 +0,0 @@ -Security -======== - -The Doctrine library is operating very close to your database and as such needs -to handle and make assumptions about SQL injection vulnerabilities. - -It is vital that you understand how Doctrine approaches security, because -we cannot protect you from SQL injection. - -Please read the documentation chapter on Security in Doctrine DBAL to -understand the assumptions we make. - -- [Latest security.rst page on Github](https://github.com/doctrine/dbal/blob/master/docs/en/reference/security.rst) -- [Security Page in rendered documentation](http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/security.html) diff --git a/vendor/doctrine/dbal/UPGRADE.md b/vendor/doctrine/dbal/UPGRADE.md deleted file mode 100644 index 205bf99..0000000 --- a/vendor/doctrine/dbal/UPGRADE.md +++ /dev/null @@ -1,452 +0,0 @@ -# Upgrade to 2.10 - -## Deprecated `Doctrine\DBAL\Event\ConnectionEventArgs` methods - -The usage of the `getDriver()`, `getDatabasePlatform()` and `getSchemaManager()` methods of the `ConnectionEventArgs` class has been deprecated. Obtain the underlying connection via `getConnection()` and call the corresponding methods on the connection instance. - -## Deprecated `Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs` methods - -The usage of the `getDatabasePlatform()` method of the `SchemaColumnDefinitionEventArgs` class has been deprecated. Obtain the underlying connection via `getConnection()` and call the corresponding method on the connection instance. - -## Deprecated `Doctrine\DBAL\Connection` methods - -The usage of the `getHost()`, `getPort()`, `getUsername()` and `getPassword()` methods of the `Connection` class has been deprecated as they leak implementation details. - -## Deprecated array of statements in `addSql()` of `SchemaEventArgs`-based classes. - -Passing multiple SQL statements as an array to `SchemaAlterTableAddColumnEventArgs::addSql()` and the same method in other `SchemaEventArgs`-based classes is deprecated. Pass each statement as an individual argument instead. - -## Deprecated calling `AbstractSchemaManager::tablesExist()` with a string argument. - -Instead of passing a string, pass a one-element array. - -## Deprecated calling `OracleSchemaManager::createDatabase()` without an argument or by passing NULL. - -In order to create a database, always pass the database name. - -## Deprecated unused schema manager methods. - -The following methods have been deprecated as unused: - -- `AbstractSchemaManager::_getPortableFunctionsList()`, -- `AbstractSchemaManager::_getPortableFunctionDefinition()`, -- `OracleSchemaManager::_getPortableFunctionDefinition()`, -- `SqliteSchemaManager::_getPortableTableIndexDefinition()`. - -# Deprecations in `Doctrine\DBAL\Driver` - -- The usage of NULL to indicate empty `$username` or `$password` when calling `connect()` is deprecated. Use an empty string instead. - -## Deprecated `Doctrine\DBAL\Platforms::_getAlterTableIndexForeignKeySQL()` - -Method `Doctrine\DBAL\Platforms::_getAlterTableIndexForeignKeySQL()` has been deprecated as no longer used. - -## Deprecated `Doctrine\DBAL\Driver\OCI8\OCI8Statement::$_PARAM` - -Property `Doctrine\DBAL\Driver\OCI8\OCI8Statement::$_PARAM` has been deprecated as not used. - -## Deprecated `Doctrine\DBAL\Driver::getName()` - -Relying on the name of the driver is discouraged. For referencing the driver, use its class name. - -## Deprecated usage of user-provided `PDO` instance - -The usage of user-provided `PDO` instance is deprecated. The known use cases are: - -1. **Persistent PDO connections.** DBAL 3.0 will supported establishing persistent connections, therefore, providing a pre-created persistent PDO connection will be no longer needed. -2. **Sharing `PDO` instance between DBAL and legacy components.** In order to share a PDO instance, initialize the connection in DBAL and access it using `Connection::getWrappedConnection()->getWrappedConnection()`. - -## MINOR BC BREAK: Default values are no longer handled as SQL expressions - -They are converted to SQL literals (e.g. escaped). Clients must now specify default values in their initial form, not in the form of an SQL literal (e.g. escaped). - -Before: - - $column->setDefault('Foo\\\\Bar\\\\Baz'); - -After: - - $column->setDefault('Foo\\Bar\\Baz'); - -## Deprecated `Type::*` constants - -The constants for built-in types have been moved from `Doctrine\DBAL\Types\Type` to a separate class `Doctrine\DBAL\Types\Types`. - -Some of the constants were renamed in the process: -* `TARRAY`-> `ARRAY` -* `DATE` -> `DATE_MUTABLE` -* `DATETIME` -> `DATETIME_MUTABLE` -* `DATETIMETZ` -> `DATETIMETZ_MUTABLE` -* `TIME` -> `TIME_MUTABLE` - -## Deprecated `SQLSrvStatement::LAST_INSERT_ID_SQL` constant - -The `Doctrine\DBAL\Driver\SQLSrv\SQLSrvStatement::LAST_INSERT_ID_SQL` constant has been deprecated and will be made private in 3.0. - -## Deprecated `SQLParserUtils` constants - -The constants in `Doctrine\DBAL\SQLParserUtils` have been deprecated and will be made private in 3.0. - -## Deprecated `LoggerChain::addLogger` method - -The `Doctrine\DBAL\Logging\LoggerChain::addLogger` method has been deprecated. Inject list of loggers via constructor instead. - -# Upgrade to 2.9 - -## Deprecated `Statement::fetchColumn()` with an invalid index - -Calls to `Statement::fetchColumn()` with an invalid column index currently return `NULL`. In the future, such calls will result in a exception. - -## Deprecated `Configuration::getFilterSchemaAssetsExpression()`, `::setFilterSchemaAssetsExpression()` and `AbstractSchemaManager::getFilterSchemaAssetsExpression()`. - -Regular expression-based filters are hard to extend by combining together. Instead, you may use callback-based filers via `::getSchemaAssetsFilter()` and `::getSchemaAssetsFilter()`. Callbacks can use regular expressions internally. - -## Deprecated `Doctrine\DBAL\Types\Type::getDefaultLength()` - -This method was never used by DBAL internally. It is now deprecated and will be removed in DBAL 3.0. - -## Deprecated `Doctrine\DBAL\Types\Type::__toString()` - -Relying on string representation is discouraged and will be removed in DBAL 3.0. - -## Deprecated `NULL` value of `$offset` in LIMIT queries - -The `NULL` value of the `$offset` argument in `AbstractPlatform::(do)?ModifyLimitQuery()` methods is deprecated. If explicitly used in the method call, the absence of the offset should be indicated with a `0`. - -## Deprecated dbal:import CLI command - -The `dbal:import` CLI command has been deprecated since it only works with PDO-based drivers by relying on a non-documented behavior of the extension, and it's impossible to make it work with other drivers. -Please use other database client applications for import, e.g.: - - * For MySQL and MariaDB: `mysql [dbname] < data.sql`. - * For PostgreSQL: `psql [dbname] < data.sql`. - * For SQLite: `sqlite3 /path/to/file.db < data.sql`. - -# Upgrade to 2.8 - -## Deprecated usage of DB-generated UUIDs - -The format of DB-generated UUIDs is inconsistent across supported platforms and therefore is not portable. Some of the platforms produce UUIDv1, some produce UUIDv4, some produce the values which are not even UUID. - -Unless UUIDs are used in stored procedures which DBAL doesn't support, there's no real benefit of DB-generated UUIDs comparing to the application-generated ones. - -Use a PHP library (e.g. [ramsey/uuid](https://packagist.org/packages/ramsey/uuid)) to generate UUIDs on the application side. - -## Deprecated usage of binary fields whose length exceeds the platform maximum - -- The usage of binary fields whose length exceeds the maximum field size on a given platform is deprecated. - Use binary fields of a size which fits all target platforms, or use blob explicitly instead. - -## Removed dependency on doctrine/common - -The dependency on doctrine/common package has been removed. -DBAL now depends on doctrine/cache and doctrine/event-manager instead. -If you are using any other component from doctrine/common package, -you will have to add an explicit dependency to your composer.json. - -## Corrected exception thrown by ``Doctrine\DBAL\Platforms\SQLAnywhere16Platform::getAdvancedIndexOptionsSQL()`` - -This method now throws SPL ``UnexpectedValueException`` instead of accidentally throwing ``Doctrine\Common\Proxy\Exception\UnexpectedValueException``. - -# Upgrade to 2.7 - -## Doctrine\DBAL\Platforms\AbstractPlatform::DATE_INTERVAL_UNIT_* constants deprecated - -``Doctrine\DBAL\Platforms\AbstractPlatform::DATE_INTERVAL_UNIT_*`` constants were moved into ``Doctrine\DBAL\Platforms\DateIntervalUnit`` class without the ``DATE_INTERVAL_UNIT_`` prefix. - -## Doctrine\DBAL\Platforms\AbstractPlatform::TRIM_* constants deprecated - -``Doctrine\DBAL\Platforms\AbstractPlatform::TRIM_*`` constants were moved into ``Doctrine\DBAL\Platforms\TrimMode`` class without the ``TRIM_`` prefix. - -## Doctrine\DBAL\Connection::TRANSACTION_* constants deprecated - -``Doctrine\DBAL\Connection::TRANSACTION_*`` were moved into ``Doctrine\DBAL\TransactionIsolationLevel`` class without the ``TRANSACTION_`` prefix. - -## DEPRECATION: direct usage of the PDO APIs in the DBAL API - -1. When calling `Doctrine\DBAL\Driver\Statement` methods, instead of `PDO::PARAM_*` constants, `Doctrine\DBAL\ParameterType` constants should be used. -2. When calling `Doctrine\DBAL\Driver\ResultStatement` methods, instead of `PDO::FETCH_*` constants, `Doctrine\DBAL\FetchMode` constants should be used. -3. When configuring `Doctrine\DBAL\Portability\Connection`, instead of `PDO::CASE_*` constants, `Doctrine\DBAL\ColumnCase` constants should be used. -4. Usage of `PDO::PARAM_INPUT_OUTPUT` in `Doctrine\DBAL\Driver\Statement::bindValue()` is deprecated. -5. Usage of `PDO::FETCH_FUNC` in `Doctrine\DBAL\Driver\ResultStatement::fetch()` is deprecated. -6. Calls to `\PDOStatement` methods on a `\Doctrine\DBAL\Driver\PDOStatement` instance (e.g. `fetchObject()`) are deprecated. - -# Upgrade to 2.6 - -## MINOR BC BREAK: `fetch()` and `fetchAll()` method signatures in `Doctrine\DBAL\Driver\ResultStatement` - -1. ``Doctrine\DBAL\Driver\ResultStatement::fetch()`` now has 3 arguments instead of 1, respecting -``PDO::fetch()`` signature. - -Before: - - Doctrine\DBAL\Driver\ResultStatement::fetch($fetchMode); - -After: - - Doctrine\DBAL\Driver\ResultStatement::fetch($fetchMode, $cursorOrientation, $cursorOffset); - -2. ``Doctrine\DBAL\Driver\ResultStatement::fetchAll()`` now has 3 arguments instead of 1, respecting -``PDO::fetchAll()`` signature. - -Before: - - Doctrine\DBAL\Driver\ResultStatement::fetchAll($fetchMode); - -After: - - Doctrine\DBAL\Driver\ResultStatement::fetch($fetchMode, $fetchArgument, $ctorArgs); - - -## MINOR BC BREAK: URL-style DSN with percentage sign in password - -URL-style DSNs (e.g. ``mysql://foo@bar:localhost/db``) are now assumed to be percent-encoded -in order to allow certain special characters in usernames, paswords and database names. If -you are using a URL-style DSN and have a username, password or database name containing a -percentage sign, you need to update your DSN. If your password is, say, ``foo%foo``, it -should be encoded as ``foo%25foo``. - -# Upgrade to 2.5.1 - -## MINOR BC BREAK: Doctrine\DBAL\Schema\Table - -When adding indexes to ``Doctrine\DBAL\Schema\Table`` via ``addIndex()`` or ``addUniqueIndex()``, -duplicate indexes are not silently ignored/dropped anymore (based on semantics, not naming!). -Duplicate indexes are considered indexes that pass ``isFullfilledBy()`` or ``overrules()`` -in ``Doctrine\DBAL\Schema\Index``. -This is required to make the index renaming feature introduced in 2.5.0 work properly and avoid -issues in the ORM schema tool / DBAL schema manager which pretends users from updating -their schemas and migrate to DBAL 2.5.*. -Additionally it offers more flexibility in declaring indexes for the user and potentially fixes -related issues in the ORM. -With this change, the responsibility to decide which index is a "duplicate" is completely deferred -to the user. -Please also note that adding foreign key constraints to a table via ``addForeignKeyConstraint()``, -``addUnnamedForeignKeyConstraint()`` or ``addNamedForeignKeyConstraint()`` now first checks if an -appropriate index is already present and avoids adding an additional auto-generated one eventually. - -# Upgrade to 2.5 - -## BC BREAK: time type resets date fields to UNIX epoch - -When mapping `time` type field to PHP's `DateTime` instance all unused date fields are -reset to UNIX epoch (i.e. 1970-01-01). This might break any logic which relies on comparing -`DateTime` instances with date fields set to the current date. - -Use `!` format prefix (see http://php.net/manual/en/datetime.createfromformat.php) for parsing -time strings to prevent having different date fields when comparing user input and `DateTime` -instances as mapped by Doctrine. - -## BC BREAK: Doctrine\DBAL\Schema\Table - -The methods ``addIndex()`` and ``addUniqueIndex()`` in ``Doctrine\DBAL\Schema\Table`` -have an additional, optional parameter. If you override these methods, you should -add this new parameter to the declaration of your overridden methods. - -## BC BREAK: Doctrine\DBAL\Connection - -The visibility of the property ``$_platform`` in ``Doctrine\DBAL\Connection`` -was changed from protected to private. If you have subclassed ``Doctrine\DBAL\Connection`` -in your application and accessed ``$_platform`` directly, you have to change the code -portions to use ``getDatabasePlatform()`` instead to retrieve the underlying database -platform. -The reason for this change is the new automatic platform version detection feature, -which lazily evaluates the appropriate platform class to use for the underlying database -server version at runtime. -Please also note, that calling ``getDatabasePlatform()`` now needs to establish a connection -in order to evaluate the appropriate platform class if ``Doctrine\DBAL\Connection`` is not -already connected. Under the following circumstances, it is not possible anymore to retrieve -the platform instance from the connection object without having to do a real connect: - -1. ``Doctrine\DBAL\Connection`` was instantiated without the ``platform`` connection parameter. -2. ``Doctrine\DBAL\Connection`` was instantiated without the ``serverVersion`` connection parameter. -3. The underlying driver is "version aware" and can provide different platform instances - for different versions. -4. The underlying driver connection is "version aware" and can provide the database server - version without having to query for it. - -If one of the above conditions is NOT met, there is no need for ``Doctrine\DBAL\Connection`` -to do a connect when calling ``getDatabasePlatform()``. - -## datetime Type uses date_create() as fallback - -Before 2.5 the DateTime type always required a specific format, defined in -`$platform->getDateTimeFormatString()`, which could cause quite some troubles -on platforms that had various microtime precision formats. Starting with 2.5 -whenever the parsing of a date fails with the predefined platform format, -the `date_create()` function will be used to parse the date. - -This could cause some troubles when your date format is weird and not parsed -correctly by `date_create`, however since databases are rather strict on dates -there should be no problem. - -## Support for pdo_ibm driver removed - -The ``pdo_ibm`` driver is buggy and does not work well with Doctrine. Therefore it will no -longer be supported and has been removed from the ``Doctrine\DBAL\DriverManager`` drivers -map. It is highly encouraged to to use `ibm_db2` driver instead if you want to connect -to an IBM DB2 database as it is much more stable and secure. - -If for some reason you have to utilize the ``pdo_ibm`` driver you can still use the `driverClass` -connection parameter to explicitly specify the ``Doctrine\DBAL\Driver\PDOIbm\Driver`` class. -However be aware that you are doing this at your own risk and it will not be guaranteed that -Doctrine will work as expected. - -# Upgrade to 2.4 - -## Doctrine\DBAL\Schema\Constraint - -If you have custom classes that implement the constraint interface, you have to implement -an additional method ``getQuotedColumns`` now. This method is used to build proper constraint -SQL for columns that need to be quoted, like keywords reserved by the specific platform used. -The method has to return the same values as ``getColumns`` only that those column names that -need quotation have to be returned quoted for the given platform. - -# Upgrade to 2.3 - -## Oracle Session Init now sets Numeric Character - -Before 2.3 the Oracle Session Init did not care about the numeric character of the Session. -This could lead to problems on non english locale systems that required a comma as a floating -point seperator in Oracle. Since 2.3, using the Oracle Session Init on connection start the -client session will be altered to set the numeric character to ".,": - - ALTER SESSION SET NLS_NUMERIC_CHARACTERS = '.,' - -See [DBAL-345](http://www.doctrine-project.org/jira/browse/DBAL-345) for more details. - -## Doctrine\DBAL\Connection and Doctrine\DBAL\Statement - -The query related methods including but not limited to executeQuery, exec, query, and executeUpdate -now wrap the driver exceptions such as PDOException with DBALException to add more debugging -information such as the executed SQL statement, and any bound parameters. - -If you want to retrieve the driver specific exception, you can retrieve it by calling the -``getPrevious()`` method on DBALException. - -Before: - - catch(\PDOException $ex) { - // ... - } - -After: - - catch(\Doctrine\DBAL\DBALException $ex) { - $pdoException = $ex->getPrevious(); - // ... - } - -## Doctrine\DBAL\Connection#setCharsetSQL() removed - -This method only worked on MySQL and it is considered unsafe on MySQL to use SET NAMES UTF-8 instead -of setting the charset directly on connection already. Replace this behavior with the -connection charset option: - -Before: - - $conn = DriverManager::getConnection(array(..)); - $conn->setCharset('UTF8'); - -After: - - $conn = DriverManager::getConnection(array('charset' => 'UTF8', ..)); - -## Doctrine\DBAL\Schema\Table#renameColumn() removed - -Doctrine\DBAL\Schema\Table#renameColumn() was removed, because it drops and recreates -the column instead. There is no fix available, because a schema diff -cannot reliably detect if a column was renamed or one column was created -and another one dropped. - -You should use explicit SQL ALTER TABLE statements to change columns names. - -## Schema Filter paths - -The Filter Schema assets expression is not wrapped in () anymore for the regexp automatically. - -Before: - - $config->setFilterSchemaAssetsExpression('foo'); - -After: - - $config->setFilterSchemaAssetsExpression('(foo)'); - -## Creating MySQL Tables now defaults to UTF-8 - -If you are creating a new MySQL Table through the Doctrine API, charset/collate are -now set to 'utf8'/'utf8_unicode_ci' by default. Previously the MySQL server defaults were used. - -# Upgrade to 2.2 - -## Doctrine\DBAL\Connection#insert and Doctrine\DBAL\Connection#update - -Both methods now accept an optional last parameter $types with binding types of the values passed. -This can potentially break child classes that have overwritten one of these methods. - -## Doctrine\DBAL\Connection#executeQuery - -Doctrine\DBAL\Connection#executeQuery() got a new last parameter "QueryCacheProfile $qcp" - -## Doctrine\DBAL\Driver\Statement split - -The Driver statement was split into a ResultStatement and the normal statement extending from it. -This separates the configuration and the retrieval API from a statement. - -## MsSql Platform/SchemaManager renamed - -The MsSqlPlatform was renamed to SQLServerPlatform, the MsSqlSchemaManager was renamed -to SQLServerSchemaManager. - -## Cleanup SQLServer Platform version mess - -DBAL 2.1 and before were actually only compatible to SQL Server 2008, not earlier versions. -Still other parts of the platform did use old features instead of newly introduced datatypes -in SQL Server 2005. Starting with DBAL 2.2 you can pick the Doctrine abstraction exactly -matching your SQL Server version. - -The PDO SqlSrv driver now uses the new `SQLServer2008Platform` as default platform. -This platform uses new features of SQL Server as of version 2008. This also includes a switch -in the used fields for "text" and "blob" field types to: - - "text" => "VARCHAR(MAX)" - "blob" => "VARBINARY(MAX)" - -Additionally `SQLServerPlatform` in DBAL 2.1 and before used "DATE", "TIME" and "DATETIME2" for dates. -This types are only available since version 2008 and the introduction of an explicit -SQLServer 2008 platform makes this dependency explicit. - -An `SQLServer2005Platform` was also introduced to differentiate the features between -versions 2003, earlier and 2005. - -With this change the `SQLServerPlatform` now throws an exception for using limit queries -with an offset, since SQLServer 2003 and lower do not support this feature. - -To use the old SQL Server Platform, because you are using SQL Server 2003 and below use -the following configuration code: - - use Doctrine\DBAL\DriverManager; - use Doctrine\DBAL\Platforms\SQLServerPlatform; - use Doctrine\DBAL\Platforms\SQLServer2005Platform; - - // You are using SQL Server 2003 or earlier - $conn = DriverManager::getConnection(array( - 'driver' => 'pdo_sqlsrv', - 'platform' => new SQLServerPlatform() - // .. additional parameters - )); - - // You are using SQL Server 2005 - $conn = DriverManager::getConnection(array( - 'driver' => 'pdo_sqlsrv', - 'platform' => new SQLServer2005Platform() - // .. additional parameters - )); - - // You are using SQL Server 2008 - $conn = DriverManager::getConnection(array( - 'driver' => 'pdo_sqlsrv', - // 2008 is default platform - // .. additional parameters - )); diff --git a/vendor/doctrine/dbal/bin/doctrine-dbal b/vendor/doctrine/dbal/bin/doctrine-dbal deleted file mode 100755 index 0531527..0000000 --- a/vendor/doctrine/dbal/bin/doctrine-dbal +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env php -data = $data; - if (! count($data)) { - return; - } - - $this->columnCount = count($data[0]); - } - - /** - * {@inheritdoc} - */ - public function closeCursor() - { - unset($this->data); - } - - /** - * {@inheritdoc} - */ - public function columnCount() - { - return $this->columnCount; - } - - /** - * {@inheritdoc} - */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) - { - if ($arg2 !== null || $arg3 !== null) { - throw new InvalidArgumentException('Caching layer does not support 2nd/3rd argument to setFetchMode()'); - } - - $this->defaultFetchMode = $fetchMode; - - return true; - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - $data = $this->fetchAll(); - - return new ArrayIterator($data); - } - - /** - * {@inheritdoc} - */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) - { - if (! isset($this->data[$this->num])) { - return false; - } - - $row = $this->data[$this->num++]; - $fetchMode = $fetchMode ?: $this->defaultFetchMode; - - if ($fetchMode === FetchMode::ASSOCIATIVE) { - return $row; - } - - if ($fetchMode === FetchMode::NUMERIC) { - return array_values($row); - } - - if ($fetchMode === FetchMode::MIXED) { - return array_merge($row, array_values($row)); - } - - if ($fetchMode === FetchMode::COLUMN) { - return reset($row); - } - - throw new InvalidArgumentException('Invalid fetch-style given for fetching result.'); - } - - /** - * {@inheritdoc} - */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) - { - $rows = []; - while ($row = $this->fetch($fetchMode)) { - $rows[] = $row; - } - - return $rows; - } - - /** - * {@inheritdoc} - */ - public function fetchColumn($columnIndex = 0) - { - $row = $this->fetch(FetchMode::NUMERIC); - - // TODO: verify that return false is the correct behavior - return $row[$columnIndex] ?? false; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/CacheException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/CacheException.php deleted file mode 100644 index 636c948..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/CacheException.php +++ /dev/null @@ -1,24 +0,0 @@ -lifetime = $lifetime; - $this->cacheKey = $cacheKey; - $this->resultCacheDriver = $resultCache; - } - - /** - * @return Cache|null - */ - public function getResultCacheDriver() - { - return $this->resultCacheDriver; - } - - /** - * @return int - */ - public function getLifetime() - { - return $this->lifetime; - } - - /** - * @return string - * - * @throws CacheException - */ - public function getCacheKey() - { - if ($this->cacheKey === null) { - throw CacheException::noCacheKey(); - } - - return $this->cacheKey; - } - - /** - * Generates the real cache key from query, params, types and connection parameters. - * - * @param string $query - * @param mixed[] $params - * @param int[]|string[] $types - * @param mixed[] $connectionParams - * - * @return string[] - */ - public function generateCacheKeys($query, $params, $types, array $connectionParams = []) - { - $realCacheKey = 'query=' . $query . - '¶ms=' . serialize($params) . - '&types=' . serialize($types) . - '&connectionParams=' . hash('sha256', serialize($connectionParams)); - - // should the key be automatically generated using the inputs or is the cache key set? - if ($this->cacheKey === null) { - $cacheKey = sha1($realCacheKey); - } else { - $cacheKey = $this->cacheKey; - } - - return [$cacheKey, $realCacheKey]; - } - - /** - * @return \Doctrine\DBAL\Cache\QueryCacheProfile - */ - public function setResultCacheDriver(Cache $cache) - { - return new QueryCacheProfile($this->lifetime, $this->cacheKey, $cache); - } - - /** - * @param string|null $cacheKey - * - * @return \Doctrine\DBAL\Cache\QueryCacheProfile - */ - public function setCacheKey($cacheKey) - { - return new QueryCacheProfile($this->lifetime, $cacheKey, $this->resultCacheDriver); - } - - /** - * @param int $lifetime - * - * @return \Doctrine\DBAL\Cache\QueryCacheProfile - */ - public function setLifetime($lifetime) - { - return new QueryCacheProfile($lifetime, $this->cacheKey, $this->resultCacheDriver); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php deleted file mode 100644 index f04c852..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Cache/ResultCacheStatement.php +++ /dev/null @@ -1,212 +0,0 @@ -statement = $stmt; - $this->resultCache = $resultCache; - $this->cacheKey = $cacheKey; - $this->realKey = $realKey; - $this->lifetime = $lifetime; - } - - /** - * {@inheritdoc} - */ - public function closeCursor() - { - $this->statement->closeCursor(); - if (! $this->emptied || $this->data === null) { - return true; - } - - $data = $this->resultCache->fetch($this->cacheKey); - if (! $data) { - $data = []; - } - $data[$this->realKey] = $this->data; - - $this->resultCache->save($this->cacheKey, $data, $this->lifetime); - unset($this->data); - - return true; - } - - /** - * {@inheritdoc} - */ - public function columnCount() - { - return $this->statement->columnCount(); - } - - /** - * {@inheritdoc} - */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) - { - $this->defaultFetchMode = $fetchMode; - - return true; - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - $data = $this->fetchAll(); - - return new ArrayIterator($data); - } - - /** - * {@inheritdoc} - */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) - { - if ($this->data === null) { - $this->data = []; - } - - $row = $this->statement->fetch(FetchMode::ASSOCIATIVE); - - if ($row) { - $this->data[] = $row; - - $fetchMode = $fetchMode ?: $this->defaultFetchMode; - - if ($fetchMode === FetchMode::ASSOCIATIVE) { - return $row; - } - - if ($fetchMode === FetchMode::NUMERIC) { - return array_values($row); - } - - if ($fetchMode === FetchMode::MIXED) { - return array_merge($row, array_values($row)); - } - - if ($fetchMode === FetchMode::COLUMN) { - return reset($row); - } - - throw new InvalidArgumentException('Invalid fetch-style given for caching result.'); - } - - $this->emptied = true; - - return false; - } - - /** - * {@inheritdoc} - */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) - { - $data = $this->statement->fetchAll($fetchMode, $fetchArgument, $ctorArgs); - - if ($fetchMode === FetchMode::COLUMN) { - foreach ($data as $key => $value) { - $data[$key] = [$value]; - } - } - - $this->data = $data; - $this->emptied = true; - - return $this->data; - } - - /** - * {@inheritdoc} - */ - public function fetchColumn($columnIndex = 0) - { - $row = $this->fetch(FetchMode::NUMERIC); - - // TODO: verify that return false is the correct behavior - return $row[$columnIndex] ?? false; - } - - /** - * 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 int The number of rows. - */ - public function rowCount() - { - assert($this->statement instanceof Statement); - - return $this->statement->rowCount(); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/ColumnCase.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/ColumnCase.php deleted file mode 100644 index 872d3ed..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/ColumnCase.php +++ /dev/null @@ -1,32 +0,0 @@ -_attributes['sqlLogger'] = $logger; - } - - /** - * Gets the SQL logger that is used. - * - * @return SQLLogger|null - */ - public function getSQLLogger() - { - return $this->_attributes['sqlLogger'] ?? null; - } - - /** - * Gets the cache driver implementation that is used for query result caching. - * - * @return Cache|null - */ - public function getResultCacheImpl() - { - return $this->_attributes['resultCacheImpl'] ?? null; - } - - /** - * Sets the cache driver implementation that is used for query result caching. - * - * @return void - */ - public function setResultCacheImpl(Cache $cacheImpl) - { - $this->_attributes['resultCacheImpl'] = $cacheImpl; - } - - /** - * Sets the filter schema assets expression. - * - * Only include tables/sequences matching the filter expression regexp in - * schema instances generated for the active connection when calling - * {AbstractSchemaManager#createSchema()}. - * - * @deprecated Use Configuration::setSchemaAssetsFilter() instead - * - * @param string $filterExpression - * - * @return void - */ - public function setFilterSchemaAssetsExpression($filterExpression) - { - $this->_attributes['filterSchemaAssetsExpression'] = $filterExpression; - if ($filterExpression) { - $this->_attributes['filterSchemaAssetsExpressionCallable'] = $this->buildSchemaAssetsFilterFromExpression($filterExpression); - } else { - $this->_attributes['filterSchemaAssetsExpressionCallable'] = null; - } - } - - /** - * Returns filter schema assets expression. - * - * @deprecated Use Configuration::getSchemaAssetsFilter() instead - * - * @return string|null - */ - public function getFilterSchemaAssetsExpression() - { - return $this->_attributes['filterSchemaAssetsExpression'] ?? null; - } - - /** - * @param string $filterExpression - */ - private function buildSchemaAssetsFilterFromExpression($filterExpression) : callable - { - return static function ($assetName) use ($filterExpression) { - if ($assetName instanceof AbstractAsset) { - $assetName = $assetName->getName(); - } - - return preg_match($filterExpression, $assetName); - }; - } - - /** - * Sets the callable to use to filter schema assets. - */ - public function setSchemaAssetsFilter(?callable $callable = null) : ?callable - { - $this->_attributes['filterSchemaAssetsExpression'] = null; - - return $this->_attributes['filterSchemaAssetsExpressionCallable'] = $callable; - } - - /** - * Returns the callable to use to filter schema assets. - */ - public function getSchemaAssetsFilter() : ?callable - { - return $this->_attributes['filterSchemaAssetsExpressionCallable'] ?? null; - } - - /** - * Sets the default auto-commit mode for connections. - * - * If a connection is in auto-commit mode, then all its SQL statements will be executed and committed as individual - * transactions. Otherwise, its SQL statements are grouped into transactions that are terminated by a call to either - * the method commit or the method rollback. By default, new connections are in auto-commit mode. - * - * @see getAutoCommit - * - * @param bool $autoCommit True to enable auto-commit mode; false to disable it. - */ - public function setAutoCommit($autoCommit) - { - $this->_attributes['autoCommit'] = (bool) $autoCommit; - } - - /** - * Returns the default auto-commit mode for connections. - * - * @see setAutoCommit - * - * @return bool True if auto-commit mode is enabled by default for connections, false otherwise. - */ - public function getAutoCommit() - { - return $this->_attributes['autoCommit'] ?? true; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php deleted file mode 100644 index ee6c086..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php +++ /dev/null @@ -1,1685 +0,0 @@ -_driver = $driver; - $this->params = $params; - - if (isset($params['pdo'])) { - $this->_conn = $params['pdo']; - $this->isConnected = true; - unset($this->params['pdo']); - } - - if (isset($params['platform'])) { - if (! $params['platform'] instanceof Platforms\AbstractPlatform) { - throw DBALException::invalidPlatformType($params['platform']); - } - - $this->platform = $params['platform']; - } - - // 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; - - $this->_expr = new Query\Expression\ExpressionBuilder($this); - - $this->autoCommit = $config->getAutoCommit(); - } - - /** - * Gets the parameters used during instantiation. - * - * @return mixed[] - */ - public function getParams() - { - return $this->params; - } - - /** - * Gets the name of the database this Connection is connected to. - * - * @return string - */ - public function getDatabase() - { - return $this->_driver->getDatabase($this); - } - - /** - * Gets the hostname of the currently connected database. - * - * @deprecated - * - * @return string|null - */ - public function getHost() - { - return $this->params['host'] ?? null; - } - - /** - * Gets the port of the currently connected database. - * - * @deprecated - * - * @return mixed - */ - public function getPort() - { - return $this->params['port'] ?? null; - } - - /** - * Gets the username used by this connection. - * - * @deprecated - * - * @return string|null - */ - public function getUsername() - { - return $this->params['user'] ?? null; - } - - /** - * Gets the password used by this connection. - * - * @deprecated - * - * @return string|null - */ - public function getPassword() - { - return $this->params['password'] ?? null; - } - - /** - * Gets the DBAL driver instance. - * - * @return Driver - */ - public function getDriver() - { - return $this->_driver; - } - - /** - * Gets the Configuration used by the Connection. - * - * @return Configuration - */ - public function getConfiguration() - { - return $this->_config; - } - - /** - * Gets the EventManager used by the Connection. - * - * @return EventManager - */ - public function getEventManager() - { - return $this->_eventManager; - } - - /** - * Gets the DatabasePlatform for the connection. - * - * @return AbstractPlatform - * - * @throws DBALException - */ - public function getDatabasePlatform() - { - if ($this->platform === null) { - $this->detectDatabasePlatform(); - } - - return $this->platform; - } - - /** - * Gets the ExpressionBuilder for the connection. - * - * @return ExpressionBuilder - */ - public function getExpressionBuilder() - { - return $this->_expr; - } - - /** - * Establishes the connection with the database. - * - * @return bool TRUE if the connection was successfully established, FALSE if - * the connection is already open. - */ - public function connect() - { - if ($this->isConnected) { - return false; - } - - $driverOptions = $this->params['driverOptions'] ?? []; - $user = $this->params['user'] ?? null; - $password = $this->params['password'] ?? null; - - $this->_conn = $this->_driver->connect($this->params, $user, $password, $driverOptions); - $this->isConnected = true; - - $this->transactionNestingLevel = 0; - - if ($this->autoCommit === false) { - $this->beginTransaction(); - } - - if ($this->_eventManager->hasListeners(Events::postConnect)) { - $eventArgs = new Event\ConnectionEventArgs($this); - $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); - } - - return true; - } - - /** - * Detects and sets the database platform. - * - * Evaluates custom platform class and version in order to set the correct platform. - * - * @throws DBALException If an invalid platform was specified for this connection. - */ - private function detectDatabasePlatform() - { - $version = $this->getDatabasePlatformVersion(); - - if ($version !== null) { - assert($this->_driver instanceof VersionAwarePlatformDriver); - - $this->platform = $this->_driver->createDatabasePlatformForVersion($version); - } else { - $this->platform = $this->_driver->getDatabasePlatform(); - } - - $this->platform->setEventManager($this->_eventManager); - } - - /** - * Returns the version of the related platform if applicable. - * - * Returns null if either the driver is not capable to create version - * specific platform instances, no explicit server version was specified - * or the underlying driver connection cannot determine the platform - * version without having to query it (performance reasons). - * - * @return string|null - * - * @throws Exception - */ - private function getDatabasePlatformVersion() - { - // Driver does not support version specific platforms. - if (! $this->_driver instanceof VersionAwarePlatformDriver) { - return null; - } - - // Explicit platform version requested (supersedes auto-detection). - if (isset($this->params['serverVersion'])) { - return $this->params['serverVersion']; - } - - // If not connected, we need to connect now to determine the platform version. - if ($this->_conn === null) { - try { - $this->connect(); - } catch (Throwable $originalException) { - if (empty($this->params['dbname'])) { - throw $originalException; - } - - // The database to connect to might not yet exist. - // Retry detection without database name connection parameter. - $databaseName = $this->params['dbname']; - $this->params['dbname'] = null; - - try { - $this->connect(); - } catch (Throwable $fallbackException) { - // Either the platform does not support database-less connections - // or something else went wrong. - // Reset connection parameters and rethrow the original exception. - $this->params['dbname'] = $databaseName; - - throw $originalException; - } - - // Reset connection parameters. - $this->params['dbname'] = $databaseName; - $serverVersion = $this->getServerVersion(); - - // Close "temporary" connection to allow connecting to the real database again. - $this->close(); - - return $serverVersion; - } - } - - return $this->getServerVersion(); - } - - /** - * Returns the database server version if the underlying driver supports it. - * - * @return string|null - */ - private function getServerVersion() - { - $connection = $this->getWrappedConnection(); - - // Automatic platform version detection. - if ($connection instanceof ServerInfoAwareConnection && ! $connection->requiresQueryForServerVersion()) { - return $connection->getServerVersion(); - } - - // Unable to detect platform version. - return null; - } - - /** - * Returns the current auto-commit mode for this connection. - * - * @see setAutoCommit - * - * @return bool True if auto-commit mode is currently enabled for this connection, false otherwise. - */ - public function isAutoCommit() - { - return $this->autoCommit === true; - } - - /** - * Sets auto-commit mode for this connection. - * - * If a connection is in auto-commit mode, then all its SQL statements will be executed and committed as individual - * transactions. Otherwise, its SQL statements are grouped into transactions that are terminated by a call to either - * the method commit or the method rollback. By default, new connections are in auto-commit mode. - * - * NOTE: If this method is called during a transaction and the auto-commit mode is changed, the transaction is - * committed. If this method is called and the auto-commit mode is not changed, the call is a no-op. - * - * @see isAutoCommit - * - * @param bool $autoCommit True to enable auto-commit mode; false to disable it. - */ - public function setAutoCommit($autoCommit) - { - $autoCommit = (bool) $autoCommit; - - // Mode not changed, no-op. - if ($autoCommit === $this->autoCommit) { - return; - } - - $this->autoCommit = $autoCommit; - - // Commit all currently active transactions if any when switching auto-commit mode. - if ($this->isConnected !== true || $this->transactionNestingLevel === 0) { - return; - } - - $this->commitAll(); - } - - /** - * Sets the fetch mode. - * - * @param int $fetchMode - * - * @return void - */ - public function setFetchMode($fetchMode) - { - $this->defaultFetchMode = $fetchMode; - } - - /** - * 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 mixed[] $params The query parameters. - * @param int[]|string[] $types The query parameter types. - * - * @return mixed[]|false False is returned if no rows are found. - * - * @throws DBALException - */ - public function fetchAssoc($statement, array $params = [], array $types = []) - { - return $this->executeQuery($statement, $params, $types)->fetch(FetchMode::ASSOCIATIVE); - } - - /** - * Prepares and executes an SQL query and returns the first row of the result - * as a numerically indexed array. - * - * @param string $statement The SQL query to be executed. - * @param mixed[] $params The prepared statement params. - * @param int[]|string[] $types The query parameter types. - * - * @return mixed[]|false False is returned if no rows are found. - */ - public function fetchArray($statement, array $params = [], array $types = []) - { - return $this->executeQuery($statement, $params, $types)->fetch(FetchMode::NUMERIC); - } - - /** - * Prepares and executes an SQL query and returns the value of a single column - * of the first row of the result. - * - * @param string $statement The SQL query to be executed. - * @param mixed[] $params The prepared statement params. - * @param int $column The 0-indexed column number to retrieve. - * @param int[]|string[] $types The query parameter types. - * - * @return mixed|false False is returned if no rows are found. - * - * @throws DBALException - */ - public function fetchColumn($statement, array $params = [], $column = 0, array $types = []) - { - return $this->executeQuery($statement, $params, $types)->fetchColumn($column); - } - - /** - * Whether an actual connection to the database is established. - * - * @return bool - */ - public function isConnected() - { - return $this->isConnected; - } - - /** - * Checks whether a transaction is currently active. - * - * @return bool TRUE if a transaction is currently active, FALSE otherwise. - */ - public function isTransactionActive() - { - return $this->transactionNestingLevel > 0; - } - - /** - * Adds identifier condition to the query components - * - * @param mixed[] $identifier Map of key columns to their values - * @param string[] $columns Column names - * @param mixed[] $values Column values - * @param string[] $conditions Key conditions - * - * @throws DBALException - */ - private function addIdentifierCondition( - array $identifier, - array &$columns, - array &$values, - array &$conditions - ) : void { - $platform = $this->getDatabasePlatform(); - - foreach ($identifier as $columnName => $value) { - if ($value === null) { - $conditions[] = $platform->getIsNullExpression($columnName); - continue; - } - - $columns[] = $columnName; - $values[] = $value; - $conditions[] = $columnName . ' = ?'; - } - } - - /** - * Executes an SQL DELETE statement on a table. - * - * Table expression and columns are not escaped and are not safe for user-input. - * - * @param string $tableExpression The expression of the table on which to delete. - * @param mixed[] $identifier The deletion criteria. An associative array containing column-value pairs. - * @param int[]|string[] $types The types of identifiers. - * - * @return int The number of affected rows. - * - * @throws DBALException - * @throws InvalidArgumentException - */ - public function delete($tableExpression, array $identifier, array $types = []) - { - if (empty($identifier)) { - throw InvalidArgumentException::fromEmptyCriteria(); - } - - $columns = $values = $conditions = []; - - $this->addIdentifierCondition($identifier, $columns, $values, $conditions); - - return $this->executeUpdate( - 'DELETE FROM ' . $tableExpression . ' WHERE ' . implode(' AND ', $conditions), - $values, - is_string(key($types)) ? $this->extractTypeValues($columns, $types) : $types - ); - } - - /** - * Closes the connection. - * - * @return void - */ - public function close() - { - $this->_conn = null; - - $this->isConnected = false; - } - - /** - * Sets the transaction isolation level. - * - * @param int $level The level to set. - * - * @return int - */ - public function setTransactionIsolation($level) - { - $this->transactionIsolationLevel = $level; - - return $this->executeUpdate($this->getDatabasePlatform()->getSetTransactionIsolationSQL($level)); - } - - /** - * Gets the currently active transaction isolation level. - * - * @return int The current transaction isolation level. - */ - public function getTransactionIsolation() - { - if ($this->transactionIsolationLevel === null) { - $this->transactionIsolationLevel = $this->getDatabasePlatform()->getDefaultTransactionIsolationLevel(); - } - - return $this->transactionIsolationLevel; - } - - /** - * Executes an SQL UPDATE statement on a table. - * - * Table expression and columns are not escaped and are not safe for user-input. - * - * @param string $tableExpression The expression of the table to update quoted or unquoted. - * @param mixed[] $data An associative array containing column-value pairs. - * @param mixed[] $identifier The update criteria. An associative array containing column-value pairs. - * @param int[]|string[] $types Types of the merged $data and $identifier arrays in that order. - * - * @return int The number of affected rows. - * - * @throws DBALException - */ - public function update($tableExpression, array $data, array $identifier, array $types = []) - { - $columns = $values = $conditions = $set = []; - - foreach ($data as $columnName => $value) { - $columns[] = $columnName; - $values[] = $value; - $set[] = $columnName . ' = ?'; - } - - $this->addIdentifierCondition($identifier, $columns, $values, $conditions); - - if (is_string(key($types))) { - $types = $this->extractTypeValues($columns, $types); - } - - $sql = 'UPDATE ' . $tableExpression . ' SET ' . implode(', ', $set) - . ' WHERE ' . implode(' AND ', $conditions); - - return $this->executeUpdate($sql, $values, $types); - } - - /** - * Inserts a table row with specified data. - * - * Table expression and columns are not escaped and are not safe for user-input. - * - * @param string $tableExpression The expression of the table to insert data into, quoted or unquoted. - * @param mixed[] $data An associative array containing column-value pairs. - * @param int[]|string[] $types Types of the inserted data. - * - * @return int The number of affected rows. - * - * @throws DBALException - */ - public function insert($tableExpression, array $data, array $types = []) - { - if (empty($data)) { - return $this->executeUpdate('INSERT INTO ' . $tableExpression . ' () VALUES ()'); - } - - $columns = []; - $values = []; - $set = []; - - foreach ($data as $columnName => $value) { - $columns[] = $columnName; - $values[] = $value; - $set[] = '?'; - } - - return $this->executeUpdate( - 'INSERT INTO ' . $tableExpression . ' (' . implode(', ', $columns) . ')' . - ' VALUES (' . implode(', ', $set) . ')', - $values, - is_string(key($types)) ? $this->extractTypeValues($columns, $types) : $types - ); - } - - /** - * Extract ordered type list from an ordered column list and type map. - * - * @param int[]|string[] $columnList - * @param int[]|string[] $types - * - * @return int[]|string[] - */ - private function extractTypeValues(array $columnList, array $types) - { - $typeValues = []; - - foreach ($columnList as $columnIndex => $columnName) { - $typeValues[] = $types[$columnName] ?? ParameterType::STRING; - } - - return $typeValues; - } - - /** - * Quotes 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->getDatabasePlatform()->quoteIdentifier($str); - } - - /** - * {@inheritDoc} - */ - public function quote($input, $type = null) - { - $connection = $this->getWrappedConnection(); - - [$value, $bindingType] = $this->getBindingInfo($input, $type); - - return $connection->quote($value, $bindingType); - } - - /** - * Prepares and executes an SQL query and returns the result as an associative array. - * - * @param string $sql The SQL query. - * @param mixed[] $params The query parameters. - * @param int[]|string[] $types The query parameter types. - * - * @return mixed[] - */ - public function fetchAll($sql, array $params = [], $types = []) - { - return $this->executeQuery($sql, $params, $types)->fetchAll(); - } - - /** - * Prepares an SQL statement. - * - * @param string $statement The SQL statement to prepare. - * - * @return DriverStatement The prepared statement. - * - * @throws DBALException - */ - public function prepare($statement) - { - try { - $stmt = new Statement($statement, $this); - } catch (Throwable $ex) { - throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $statement); - } - - $stmt->setFetchMode($this->defaultFetchMode); - - return $stmt; - } - - /** - * Executes an, optionally parametrized, SQL query. - * - * If the query is parametrized, a prepared statement is used. - * If an SQLLogger is configured, the execution is logged. - * - * @param string $query The SQL query to execute. - * @param mixed[] $params The parameters to bind to the query, if any. - * @param int[]|string[] $types The types the previous parameters are in. - * @param QueryCacheProfile|null $qcp The query cache profile, optional. - * - * @return ResultStatement The executed statement. - * - * @throws DBALException - */ - public function executeQuery($query, array $params = [], $types = [], ?QueryCacheProfile $qcp = null) - { - if ($qcp !== null) { - return $this->executeCacheQuery($query, $params, $types, $qcp); - } - - $connection = $this->getWrappedConnection(); - - $logger = $this->_config->getSQLLogger(); - if ($logger) { - $logger->startQuery($query, $params, $types); - } - - try { - if ($params) { - [$query, $params, $types] = SQLParserUtils::expandListParameters($query, $params, $types); - - $stmt = $connection->prepare($query); - if ($types) { - $this->_bindTypedValues($stmt, $params, $types); - $stmt->execute(); - } else { - $stmt->execute($params); - } - } else { - $stmt = $connection->query($query); - } - } catch (Throwable $ex) { - throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $query, $this->resolveParams($params, $types)); - } - - $stmt->setFetchMode($this->defaultFetchMode); - - if ($logger) { - $logger->stopQuery(); - } - - return $stmt; - } - - /** - * Executes a caching query. - * - * @param string $query The SQL query to execute. - * @param mixed[] $params The parameters to bind to the query, if any. - * @param int[]|string[] $types The types the previous parameters are in. - * @param QueryCacheProfile $qcp The query cache profile. - * - * @return ResultStatement - * - * @throws CacheException - */ - public function executeCacheQuery($query, $params, $types, QueryCacheProfile $qcp) - { - $resultCache = $qcp->getResultCacheDriver() ?? $this->_config->getResultCacheImpl(); - - if ($resultCache === null) { - throw CacheException::noResultDriverConfigured(); - } - - $connectionParams = $this->getParams(); - unset($connectionParams['platform']); - - [$cacheKey, $realKey] = $qcp->generateCacheKeys($query, $params, $types, $connectionParams); - - // fetch the row pointers entry - $data = $resultCache->fetch($cacheKey); - - if ($data !== false) { - // is the real key part of this row pointers map or is the cache only pointing to other cache keys? - if (isset($data[$realKey])) { - $stmt = new ArrayStatement($data[$realKey]); - } elseif (array_key_exists($realKey, $data)) { - $stmt = new ArrayStatement([]); - } - } - - if (! isset($stmt)) { - $stmt = new ResultCacheStatement($this->executeQuery($query, $params, $types), $resultCache, $cacheKey, $realKey, $qcp->getLifetime()); - } - - $stmt->setFetchMode($this->defaultFetchMode); - - return $stmt; - } - - /** - * Executes an, optionally parametrized, 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 mixed[] $params The parameters, if any. - * @param Closure $function The transformation function that is applied on each row. - * The function receives a single parameter, 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 = []; - $stmt = $this->executeQuery($query, $params); - - while ($row = $stmt->fetch()) { - $result[] = $function($row); - } - - $stmt->closeCursor(); - - return $result; - } - - /** - * Executes an SQL statement, returning a result set as a Statement object. - * - * @return \Doctrine\DBAL\Driver\Statement - * - * @throws DBALException - */ - public function query() - { - $connection = $this->getWrappedConnection(); - - $args = func_get_args(); - - $logger = $this->_config->getSQLLogger(); - if ($logger) { - $logger->startQuery($args[0]); - } - - try { - $statement = $connection->query(...$args); - } catch (Throwable $ex) { - throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $args[0]); - } - - $statement->setFetchMode($this->defaultFetchMode); - - if ($logger) { - $logger->stopQuery(); - } - - return $statement; - } - - /** - * 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 mixed[] $params The query parameters. - * @param int[]|string[] $types The parameter types. - * - * @return int The number of affected rows. - * - * @throws DBALException - */ - public function executeUpdate($query, array $params = [], array $types = []) - { - $connection = $this->getWrappedConnection(); - - $logger = $this->_config->getSQLLogger(); - if ($logger) { - $logger->startQuery($query, $params, $types); - } - - try { - if ($params) { - [$query, $params, $types] = SQLParserUtils::expandListParameters($query, $params, $types); - - $stmt = $connection->prepare($query); - - if ($types) { - $this->_bindTypedValues($stmt, $params, $types); - $stmt->execute(); - } else { - $stmt->execute($params); - } - $result = $stmt->rowCount(); - } else { - $result = $connection->exec($query); - } - } catch (Throwable $ex) { - throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $query, $this->resolveParams($params, $types)); - } - - if ($logger) { - $logger->stopQuery(); - } - - return $result; - } - - /** - * Executes an SQL statement and return the number of affected rows. - * - * @param string $statement - * - * @return int The number of affected rows. - * - * @throws DBALException - */ - public function exec($statement) - { - $connection = $this->getWrappedConnection(); - - $logger = $this->_config->getSQLLogger(); - if ($logger) { - $logger->startQuery($statement); - } - - try { - $result = $connection->exec($statement); - } catch (Throwable $ex) { - throw DBALException::driverExceptionDuringQuery($this->_driver, $ex, $statement); - } - - if ($logger) { - $logger->stopQuery(); - } - - return $result; - } - - /** - * Returns the current transaction nesting level. - * - * @return int The nesting level. A value of 0 means there's no active transaction. - */ - public function getTransactionNestingLevel() - { - return $this->transactionNestingLevel; - } - - /** - * Fetches the SQLSTATE associated with the last database operation. - * - * @return string|null The last error code. - */ - public function errorCode() - { - return $this->getWrappedConnection()->errorCode(); - } - - /** - * {@inheritDoc} - */ - public function errorInfo() - { - return $this->getWrappedConnection()->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|null $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) - { - return $this->getWrappedConnection()->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. - * - * @return mixed The value returned by $func - * - * @throws Exception - * @throws Throwable - */ - public function transactional(Closure $func) - { - $this->beginTransaction(); - try { - $res = $func($this); - $this->commit(); - - return $res; - } catch (Exception $e) { - $this->rollBack(); - throw $e; - } catch (Throwable $e) { - $this->rollBack(); - throw $e; - } - } - - /** - * Sets if nested transactions should use savepoints. - * - * @param bool $nestTransactionsWithSavepoints - * - * @return void - * - * @throws ConnectionException - */ - public function setNestTransactionsWithSavepoints($nestTransactionsWithSavepoints) - { - if ($this->transactionNestingLevel > 0) { - throw ConnectionException::mayNotAlterNestedTransactionWithSavepointsInTransaction(); - } - - if (! $this->getDatabasePlatform()->supportsSavepoints()) { - throw ConnectionException::savepointsNotSupported(); - } - - $this->nestTransactionsWithSavepoints = (bool) $nestTransactionsWithSavepoints; - } - - /** - * Gets if nested transactions should use savepoints. - * - * @return bool - */ - 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; - } - - /** - * {@inheritDoc} - */ - public function beginTransaction() - { - $connection = $this->getWrappedConnection(); - - ++$this->transactionNestingLevel; - - $logger = $this->_config->getSQLLogger(); - - if ($this->transactionNestingLevel === 1) { - if ($logger) { - $logger->startQuery('"START TRANSACTION"'); - } - - $connection->beginTransaction(); - - if ($logger) { - $logger->stopQuery(); - } - } elseif ($this->nestTransactionsWithSavepoints) { - if ($logger) { - $logger->startQuery('"SAVEPOINT"'); - } - $this->createSavepoint($this->_getNestedTransactionSavePointName()); - if ($logger) { - $logger->stopQuery(); - } - } - - return true; - } - - /** - * {@inheritDoc} - * - * @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(); - } - - $result = true; - - $connection = $this->getWrappedConnection(); - - $logger = $this->_config->getSQLLogger(); - - if ($this->transactionNestingLevel === 1) { - if ($logger) { - $logger->startQuery('"COMMIT"'); - } - - $result = $connection->commit(); - - if ($logger) { - $logger->stopQuery(); - } - } elseif ($this->nestTransactionsWithSavepoints) { - if ($logger) { - $logger->startQuery('"RELEASE SAVEPOINT"'); - } - $this->releaseSavepoint($this->_getNestedTransactionSavePointName()); - if ($logger) { - $logger->stopQuery(); - } - } - - --$this->transactionNestingLevel; - - if ($this->autoCommit !== false || $this->transactionNestingLevel !== 0) { - return $result; - } - - $this->beginTransaction(); - - return $result; - } - - /** - * Commits all current nesting transactions. - */ - private function commitAll() - { - while ($this->transactionNestingLevel !== 0) { - if ($this->autoCommit === false && $this->transactionNestingLevel === 1) { - // When in no auto-commit mode, the last nesting commit immediately starts a new transaction. - // Therefore we need to do the final commit here and then leave to avoid an infinite loop. - $this->commit(); - - return; - } - - $this->commit(); - } - } - - /** - * Cancels any database changes done during the current transaction. - * - * @throws ConnectionException If the rollback operation failed. - */ - public function rollBack() - { - if ($this->transactionNestingLevel === 0) { - throw ConnectionException::noActiveTransaction(); - } - - $connection = $this->getWrappedConnection(); - - $logger = $this->_config->getSQLLogger(); - - if ($this->transactionNestingLevel === 1) { - if ($logger) { - $logger->startQuery('"ROLLBACK"'); - } - $this->transactionNestingLevel = 0; - $connection->rollBack(); - $this->isRollbackOnly = false; - if ($logger) { - $logger->stopQuery(); - } - - if ($this->autoCommit === false) { - $this->beginTransaction(); - } - } elseif ($this->nestTransactionsWithSavepoints) { - if ($logger) { - $logger->startQuery('"ROLLBACK TO SAVEPOINT"'); - } - $this->rollbackSavepoint($this->_getNestedTransactionSavePointName()); - --$this->transactionNestingLevel; - if ($logger) { - $logger->stopQuery(); - } - } else { - $this->isRollbackOnly = true; - --$this->transactionNestingLevel; - } - } - - /** - * Creates a new savepoint. - * - * @param string $savepoint The name of the savepoint to create. - * - * @return void - * - * @throws ConnectionException - */ - public function createSavepoint($savepoint) - { - if (! $this->getDatabasePlatform()->supportsSavepoints()) { - throw ConnectionException::savepointsNotSupported(); - } - - $this->getWrappedConnection()->exec($this->platform->createSavePoint($savepoint)); - } - - /** - * Releases the given savepoint. - * - * @param string $savepoint The name of the savepoint to release. - * - * @return void - * - * @throws ConnectionException - */ - public function releaseSavepoint($savepoint) - { - if (! $this->getDatabasePlatform()->supportsSavepoints()) { - throw ConnectionException::savepointsNotSupported(); - } - - if (! $this->platform->supportsReleaseSavepoints()) { - return; - } - - $this->getWrappedConnection()->exec($this->platform->releaseSavePoint($savepoint)); - } - - /** - * Rolls back to the given savepoint. - * - * @param string $savepoint The name of the savepoint to rollback to. - * - * @return void - * - * @throws ConnectionException - */ - public function rollbackSavepoint($savepoint) - { - if (! $this->getDatabasePlatform()->supportsSavepoints()) { - throw ConnectionException::savepointsNotSupported(); - } - - $this->getWrappedConnection()->exec($this->platform->rollbackSavePoint($savepoint)); - } - - /** - * Gets the wrapped driver connection. - * - * @return DriverConnection - */ - 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 AbstractSchemaManager - */ - public function getSchemaManager() - { - if ($this->_schemaManager === null) { - $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. - * - * @return void - * - * @throws ConnectionException If no transaction is active. - */ - public function setRollbackOnly() - { - if ($this->transactionNestingLevel === 0) { - throw ConnectionException::noActiveTransaction(); - } - $this->isRollbackOnly = true; - } - - /** - * Checks whether the current transaction is marked for rollback only. - * - * @return bool - * - * @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->getDatabasePlatform()); - } - - /** - * 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->getDatabasePlatform()); - } - - /** - * 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. - * - * @internal Duck-typing used on the $stmt parameter to support driver statements as well as - * raw PDOStatement instances. - * - * @param \Doctrine\DBAL\Driver\Statement $stmt The statement to bind the values to. - * @param mixed[] $params The map/list of named/positional parameters. - * @param int[]|string[] $types The parameter types (PDO binding types or DBAL mapping types). - * - * @return void - */ - 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 = array_key_exists(0, $types) ? -1 : 0; - $bindIndex = 1; - foreach ($params as $value) { - $typeIndex = $bindIndex + $typeOffset; - if (isset($types[$typeIndex])) { - $type = $types[$typeIndex]; - [$value, $bindingType] = $this->getBindingInfo($value, $type); - $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]; - [$value, $bindingType] = $this->getBindingInfo($value, $type); - $stmt->bindValue($name, $value, $bindingType); - } else { - $stmt->bindValue($name, $value); - } - } - } - } - - /** - * Gets the binding type of a given type. The given type can be a PDO or DBAL mapping type. - * - * @param mixed $value The value to bind. - * @param int|string|null $type The type to bind (PDO or DBAL). - * - * @return mixed[] [0] => the (escaped) value, [1] => the binding type. - */ - private function getBindingInfo($value, $type) - { - if (is_string($type)) { - $type = Type::getType($type); - } - if ($type instanceof Type) { - $value = $type->convertToDatabaseValue($value, $this->getDatabasePlatform()); - $bindingType = $type->getBindingType(); - } else { - $bindingType = $type; - } - - return [$value, $bindingType]; - } - - /** - * Resolves the parameters to a format which can be displayed. - * - * @internal This is a purely internal method. If you rely on this method, you are advised to - * copy/paste the code as this method may change, or be removed without prior notice. - * - * @param mixed[] $params - * @param int[]|string[] $types - * - * @return mixed[] - */ - public function resolveParams(array $params, array $types) - { - $resolvedParams = []; - - // Check whether parameters are positional or named. Mixing is not allowed, just like in PDO. - if (is_int(key($params))) { - // Positional parameters - $typeOffset = array_key_exists(0, $types) ? -1 : 0; - $bindIndex = 1; - foreach ($params as $value) { - $typeIndex = $bindIndex + $typeOffset; - if (isset($types[$typeIndex])) { - $type = $types[$typeIndex]; - [$value] = $this->getBindingInfo($value, $type); - $resolvedParams[$bindIndex] = $value; - } else { - $resolvedParams[$bindIndex] = $value; - } - ++$bindIndex; - } - } else { - // Named parameters - foreach ($params as $name => $value) { - if (isset($types[$name])) { - $type = $types[$name]; - [$value] = $this->getBindingInfo($value, $type); - $resolvedParams[$name] = $value; - } else { - $resolvedParams[$name] = $value; - } - } - } - - return $resolvedParams; - } - - /** - * Creates a new instance of a SQL query builder. - * - * @return QueryBuilder - */ - public function createQueryBuilder() - { - return new Query\QueryBuilder($this); - } - - /** - * Ping the server - * - * When the server is not available the method returns FALSE. - * It is responsibility of the developer to handle this case - * and abort the request or reconnect manually: - * - * @return bool - * - * @example - * - * if ($conn->ping() === false) { - * $conn->close(); - * $conn->connect(); - * } - * - * It is undefined if the underlying driver attempts to reconnect - * or disconnect when the connection is not available anymore - * as long it returns TRUE when a reconnect succeeded and - * FALSE when the connection was dropped. - */ - public function ping() - { - $connection = $this->getWrappedConnection(); - - if ($connection instanceof PingableConnection) { - return $connection->ping(); - } - - try { - $this->query($this->getDatabasePlatform()->getDummySelectSQL()); - - return true; - } catch (DBALException $e) { - return false; - } - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/ConnectionException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/ConnectionException.php deleted file mode 100644 index d3d11bc..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/ConnectionException.php +++ /dev/null @@ -1,38 +0,0 @@ -executeQuery("DELETE FROM table"); - * - * Be aware that Connection#executeQuery is a method specifically for READ - * operations only. - * - * This connection is limited to slave operations using the - * Connection#executeQuery operation only, because it wouldn't be compatible - * with the ORM or SchemaManager code otherwise. Both use all the other - * operations in a context where writes could happen to a slave, which makes - * this restricted approach necessary. - * - * You can manually connect to the master at any time by calling: - * - * $conn->connect('master'); - * - * Instantiation through the DriverManager looks like: - * - * @example - * - * $conn = DriverManager::getConnection(array( - * 'wrapperClass' => 'Doctrine\DBAL\Connections\MasterSlaveConnection', - * 'driver' => 'pdo_mysql', - * 'master' => array('user' => '', 'password' => '', 'host' => '', 'dbname' => ''), - * 'slaves' => array( - * array('user' => 'slave1', 'password', 'host' => '', 'dbname' => ''), - * array('user' => 'slave2', 'password', 'host' => '', 'dbname' => ''), - * ) - * )); - * - * You can also pass 'driverOptions' and any other documented option to each of this drivers to pass additional information. - */ -class MasterSlaveConnection extends Connection -{ - /** - * Master and slave connection (one of the randomly picked slaves). - * - * @var DriverConnection[]|null[] - */ - protected $connections = ['master' => null, 'slave' => null]; - - /** - * You can keep the slave connection and then switch back to it - * during the request if you know what you are doing. - * - * @var bool - */ - protected $keepSlave = false; - - /** - * Creates Master Slave Connection. - * - * @param mixed[] $params - * - * @throws InvalidArgumentException - */ - public function __construct(array $params, Driver $driver, ?Configuration $config = null, ?EventManager $eventManager = null) - { - if (! isset($params['slaves'], $params['master'])) { - throw new InvalidArgumentException('master or slaves configuration missing'); - } - if (count($params['slaves']) === 0) { - throw new InvalidArgumentException('You have to configure at least one slaves.'); - } - - $params['master']['driver'] = $params['driver']; - foreach ($params['slaves'] as $slaveKey => $slave) { - $params['slaves'][$slaveKey]['driver'] = $params['driver']; - } - - $this->keepSlave = (bool) ($params['keepSlave'] ?? false); - - parent::__construct($params, $driver, $config, $eventManager); - } - - /** - * Checks if the connection is currently towards the master or not. - * - * @return bool - */ - public function isConnectedToMaster() - { - return $this->_conn !== null && $this->_conn === $this->connections['master']; - } - - /** - * {@inheritDoc} - */ - public function connect($connectionName = null) - { - $requestedConnectionChange = ($connectionName !== null); - $connectionName = $connectionName ?: 'slave'; - - if ($connectionName !== 'slave' && $connectionName !== 'master') { - throw new InvalidArgumentException('Invalid option to connect(), only master or slave allowed.'); - } - - // If we have a connection open, and this is not an explicit connection - // change request, then abort right here, because we are already done. - // This prevents writes to the slave in case of "keepSlave" option enabled. - if ($this->_conn !== null && ! $requestedConnectionChange) { - return false; - } - - $forceMasterAsSlave = false; - - if ($this->getTransactionNestingLevel() > 0) { - $connectionName = 'master'; - $forceMasterAsSlave = true; - } - - if (isset($this->connections[$connectionName])) { - $this->_conn = $this->connections[$connectionName]; - - if ($forceMasterAsSlave && ! $this->keepSlave) { - $this->connections['slave'] = $this->_conn; - } - - return false; - } - - if ($connectionName === 'master') { - $this->connections['master'] = $this->_conn = $this->connectTo($connectionName); - - // Set slave connection to master to avoid invalid reads - if (! $this->keepSlave) { - $this->connections['slave'] = $this->connections['master']; - } - } else { - $this->connections['slave'] = $this->_conn = $this->connectTo($connectionName); - } - - if ($this->_eventManager->hasListeners(Events::postConnect)) { - $eventArgs = new ConnectionEventArgs($this); - $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); - } - - return true; - } - - /** - * Connects to a specific connection. - * - * @param string $connectionName - * - * @return DriverConnection - */ - protected function connectTo($connectionName) - { - $params = $this->getParams(); - - $driverOptions = $params['driverOptions'] ?? []; - - $connectionParams = $this->chooseConnectionConfiguration($connectionName, $params); - - $user = $connectionParams['user'] ?? null; - $password = $connectionParams['password'] ?? null; - - return $this->_driver->connect($connectionParams, $user, $password, $driverOptions); - } - - /** - * @param string $connectionName - * @param mixed[] $params - * - * @return mixed - */ - protected function chooseConnectionConfiguration($connectionName, $params) - { - if ($connectionName === 'master') { - return $params['master']; - } - - $config = $params['slaves'][array_rand($params['slaves'])]; - - if (! isset($config['charset']) && isset($params['master']['charset'])) { - $config['charset'] = $params['master']['charset']; - } - - return $config; - } - - /** - * {@inheritDoc} - */ - public function executeUpdate($query, array $params = [], array $types = []) - { - $this->connect('master'); - - return parent::executeUpdate($query, $params, $types); - } - - /** - * {@inheritDoc} - */ - public function beginTransaction() - { - $this->connect('master'); - - return parent::beginTransaction(); - } - - /** - * {@inheritDoc} - */ - public function commit() - { - $this->connect('master'); - - return parent::commit(); - } - - /** - * {@inheritDoc} - */ - public function rollBack() - { - $this->connect('master'); - - return parent::rollBack(); - } - - /** - * {@inheritDoc} - */ - public function delete($tableName, array $identifier, array $types = []) - { - $this->connect('master'); - - return parent::delete($tableName, $identifier, $types); - } - - /** - * {@inheritDoc} - */ - public function close() - { - unset($this->connections['master'], $this->connections['slave']); - - parent::close(); - - $this->_conn = null; - $this->connections = ['master' => null, 'slave' => null]; - } - - /** - * {@inheritDoc} - */ - public function update($tableName, array $data, array $identifier, array $types = []) - { - $this->connect('master'); - - return parent::update($tableName, $data, $identifier, $types); - } - - /** - * {@inheritDoc} - */ - public function insert($tableName, array $data, array $types = []) - { - $this->connect('master'); - - return parent::insert($tableName, $data, $types); - } - - /** - * {@inheritDoc} - */ - public function exec($statement) - { - $this->connect('master'); - - return parent::exec($statement); - } - - /** - * {@inheritDoc} - */ - public function createSavepoint($savepoint) - { - $this->connect('master'); - - parent::createSavepoint($savepoint); - } - - /** - * {@inheritDoc} - */ - public function releaseSavepoint($savepoint) - { - $this->connect('master'); - - parent::releaseSavepoint($savepoint); - } - - /** - * {@inheritDoc} - */ - public function rollbackSavepoint($savepoint) - { - $this->connect('master'); - - parent::rollbackSavepoint($savepoint); - } - - /** - * {@inheritDoc} - */ - public function query() - { - $this->connect('master'); - assert($this->_conn instanceof DriverConnection); - - $args = func_get_args(); - - $logger = $this->getConfiguration()->getSQLLogger(); - if ($logger) { - $logger->startQuery($args[0]); - } - - $statement = $this->_conn->query(...$args); - - $statement->setFetchMode($this->defaultFetchMode); - - if ($logger) { - $logger->stopQuery(); - } - - return $statement; - } - - /** - * {@inheritDoc} - */ - public function prepare($statement) - { - $this->connect('master'); - - return parent::prepare($statement); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php deleted file mode 100644 index 4961af2..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php +++ /dev/null @@ -1,294 +0,0 @@ -getMessage(); - - return static::wrapException($driver, $driverEx, $msg); - } - - /** - * @return self - */ - public static function driverException(Driver $driver, Throwable $driverEx) - { - return static::wrapException($driver, $driverEx, 'An exception occurred in driver: ' . $driverEx->getMessage()); - } - - /** - * @return self - */ - private static function wrapException(Driver $driver, Throwable $driverEx, $msg) - { - if ($driverEx instanceof DriverException) { - return $driverEx; - } - if ($driver instanceof ExceptionConverterDriver && $driverEx instanceof DriverExceptionInterface) { - return $driver->convertException($msg, $driverEx); - } - - return new self($msg, 0, $driverEx); - } - - /** - * Returns a human-readable representation of an array of parameters. - * This properly handles binary data by returning a hex representation. - * - * @param mixed[] $params - * - * @return string - */ - private static function formatParameters(array $params) - { - return '[' . implode(', ', array_map(static function ($param) { - if (is_resource($param)) { - return (string) $param; - } - - $json = @json_encode($param); - - if (! is_string($json) || $json === 'null' && is_string($param)) { - // JSON encoding failed, this is not a UTF-8 string. - return sprintf('"%s"', preg_replace('/.{2}/', '\\x$0', bin2hex($param))); - } - - return $json; - }, $params)) . ']'; - } - - /** - * @param string $wrapperClass - * - * @return \Doctrine\DBAL\DBALException - */ - public static function invalidWrapperClass($wrapperClass) - { - return new self("The given 'wrapperClass' " . $wrapperClass . ' has to be a ' . - 'subtype of \Doctrine\DBAL\Connection.'); - } - - /** - * @param string $driverClass - * - * @return \Doctrine\DBAL\DBALException - */ - public static function invalidDriverClass($driverClass) - { - return new self("The given 'driverClass' " . $driverClass . ' has to implement the ' . Driver::class . ' interface.'); - } - - /** - * @param string $tableName - * - * @return \Doctrine\DBAL\DBALException - */ - public static function invalidTableName($tableName) - { - return new self('Invalid table name specified: ' . $tableName); - } - - /** - * @param string $tableName - * - * @return \Doctrine\DBAL\DBALException - */ - public static function noColumnsSpecifiedForTable($tableName) - { - return new self('No columns specified for table ' . $tableName); - } - - /** - * @return \Doctrine\DBAL\DBALException - */ - public static function limitOffsetInvalid() - { - return new self('Invalid Offset in Limit Query, it has to be larger than or equal to 0.'); - } - - /** - * @param string $name - * - * @return \Doctrine\DBAL\DBALException - */ - public static function typeExists($name) - { - return new self('Type ' . $name . ' already exists.'); - } - - /** - * @param string $name - * - * @return \Doctrine\DBAL\DBALException - */ - public static function unknownColumnType($name) - { - return new self('Unknown column type "' . $name . '" requested. Any Doctrine type that you use has ' . - 'to be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list of all the ' . - 'known types with \Doctrine\DBAL\Types\Type::getTypesMap(). If this error occurs during database ' . - 'introspection then you might have forgotten to register all database types for a Doctrine Type. Use ' . - 'AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement ' . - 'Type#getMappedDatabaseTypes(). If the type name is empty you might ' . - 'have a problem with the cache or forgot some mapping information.'); - } - - /** - * @param string $name - * - * @return \Doctrine\DBAL\DBALException - */ - public static function typeNotFound($name) - { - return new self('Type to be overwritten ' . $name . ' does not exist.'); - } - - public static function typeNotRegistered(Type $type) : self - { - return new self(sprintf('Type of the class %s@%s is not registered.', get_class($type), spl_object_hash($type))); - } - - public static function typeAlreadyRegistered(Type $type) : self - { - return new self( - sprintf('Type of the class %s@%s is already registered.', get_class($type), spl_object_hash($type)) - ); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver.php deleted file mode 100644 index 57493e6..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver.php +++ /dev/null @@ -1,59 +0,0 @@ -getParams(); - - return $params['dbname']; - } - - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new DB2Platform(); - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(Connection $conn) - { - return new DB2SchemaManager($conn); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDriverException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDriverException.php deleted file mode 100644 index d9af92d..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractDriverException.php +++ /dev/null @@ -1,54 +0,0 @@ -errorCode = $errorCode; - $this->sqlState = $sqlState; - } - - /** - * {@inheritdoc} - */ - public function getErrorCode() - { - return $this->errorCode; - } - - /** - * {@inheritdoc} - */ - public function getSQLState() - { - return $this->sqlState; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php deleted file mode 100644 index c46ddc6..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php +++ /dev/null @@ -1,218 +0,0 @@ -getErrorCode()) { - case '1213': - return new Exception\DeadlockException($message, $exception); - case '1205': - return new Exception\LockWaitTimeoutException($message, $exception); - case '1050': - return new Exception\TableExistsException($message, $exception); - - case '1051': - case '1146': - return new Exception\TableNotFoundException($message, $exception); - - case '1216': - case '1217': - case '1451': - case '1452': - case '1701': - return new Exception\ForeignKeyConstraintViolationException($message, $exception); - - case '1062': - case '1557': - case '1569': - case '1586': - return new Exception\UniqueConstraintViolationException($message, $exception); - - case '1054': - case '1166': - case '1611': - return new Exception\InvalidFieldNameException($message, $exception); - - case '1052': - case '1060': - case '1110': - return new Exception\NonUniqueFieldNameException($message, $exception); - - case '1064': - case '1149': - case '1287': - case '1341': - case '1342': - case '1343': - case '1344': - case '1382': - case '1479': - case '1541': - case '1554': - case '1626': - return new Exception\SyntaxErrorException($message, $exception); - - case '1044': - case '1045': - case '1046': - case '1049': - case '1095': - case '1142': - case '1143': - case '1227': - case '1370': - case '1429': - case '2002': - case '2005': - return new Exception\ConnectionException($message, $exception); - - case '1048': - case '1121': - case '1138': - case '1171': - case '1252': - case '1263': - case '1364': - case '1566': - return new Exception\NotNullConstraintViolationException($message, $exception); - } - - return new Exception\DriverException($message, $exception); - } - - /** - * {@inheritdoc} - * - * @throws DBALException - */ - public function createDatabasePlatformForVersion($version) - { - $mariadb = stripos($version, 'mariadb') !== false; - if ($mariadb && version_compare($this->getMariaDbMysqlVersionNumber($version), '10.2.7', '>=')) { - return new MariaDb1027Platform(); - } - - if (! $mariadb) { - $oracleMysqlVersion = $this->getOracleMysqlVersionNumber($version); - if (version_compare($oracleMysqlVersion, '8', '>=')) { - return new MySQL80Platform(); - } - if (version_compare($oracleMysqlVersion, '5.7.9', '>=')) { - return new MySQL57Platform(); - } - } - - return $this->getDatabasePlatform(); - } - - /** - * Get a normalized 'version number' from the server string - * returned by Oracle MySQL servers. - * - * @param string $versionString Version string returned by the driver, i.e. '5.7.10' - * - * @throws DBALException - */ - private function getOracleMysqlVersionNumber(string $versionString) : string - { - if (! preg_match( - '/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?/', - $versionString, - $versionParts - )) { - throw DBALException::invalidPlatformVersionSpecified( - $versionString, - '..' - ); - } - $majorVersion = $versionParts['major']; - $minorVersion = $versionParts['minor'] ?? 0; - $patchVersion = $versionParts['patch'] ?? null; - - if ($majorVersion === '5' && $minorVersion === '7' && $patchVersion === null) { - $patchVersion = '9'; - } - - return $majorVersion . '.' . $minorVersion . '.' . $patchVersion; - } - - /** - * Detect MariaDB server version, including hack for some mariadb distributions - * that starts with the prefix '5.5.5-' - * - * @param string $versionString Version string as returned by mariadb server, i.e. '5.5.5-Mariadb-10.0.8-xenial' - * - * @throws DBALException - */ - private function getMariaDbMysqlVersionNumber(string $versionString) : string - { - if (! preg_match( - '/^(?:5\.5\.5-)?(mariadb-)?(?P\d+)\.(?P\d+)\.(?P\d+)/i', - $versionString, - $versionParts - )) { - throw DBALException::invalidPlatformVersionSpecified( - $versionString, - '^(?:5\.5\.5-)?(mariadb-)?..' - ); - } - - return $versionParts['major'] . '.' . $versionParts['minor'] . '.' . $versionParts['patch']; - } - - /** - * {@inheritdoc} - */ - public function getDatabase(Connection $conn) - { - $params = $conn->getParams(); - - return $params['dbname'] ?? $conn->query('SELECT DATABASE()')->fetchColumn(); - } - - /** - * {@inheritdoc} - * - * @return MySqlPlatform - */ - public function getDatabasePlatform() - { - return new MySqlPlatform(); - } - - /** - * {@inheritdoc} - * - * @return MySqlSchemaManager - */ - public function getSchemaManager(Connection $conn) - { - return new MySqlSchemaManager($conn); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php deleted file mode 100644 index dcbaaf0..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php +++ /dev/null @@ -1,97 +0,0 @@ -getErrorCode()) { - case '1': - case '2299': - case '38911': - return new Exception\UniqueConstraintViolationException($message, $exception); - - case '904': - return new Exception\InvalidFieldNameException($message, $exception); - - case '918': - case '960': - return new Exception\NonUniqueFieldNameException($message, $exception); - - case '923': - return new Exception\SyntaxErrorException($message, $exception); - - case '942': - return new Exception\TableNotFoundException($message, $exception); - - case '955': - return new Exception\TableExistsException($message, $exception); - - case '1017': - case '12545': - return new Exception\ConnectionException($message, $exception); - - case '1400': - return new Exception\NotNullConstraintViolationException($message, $exception); - - case '2266': - case '2291': - case '2292': - return new Exception\ForeignKeyConstraintViolationException($message, $exception); - } - - return new Exception\DriverException($message, $exception); - } - - /** - * {@inheritdoc} - */ - public function getDatabase(Connection $conn) - { - $params = $conn->getParams(); - - return $params['user']; - } - - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new OraclePlatform(); - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(Connection $conn) - { - return new OracleSchemaManager($conn); - } - - /** - * Returns an appropriate Easy Connect String for the given parameters. - * - * @param mixed[] $params The connection parameters to return the Easy Connect String for. - * - * @return string - */ - protected function getEasyConnectString(array $params) - { - return (string) EasyConnectString::fromConnectionParameters($params); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver/EasyConnectString.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver/EasyConnectString.php deleted file mode 100644 index 01f648b..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractOracleDriver/EasyConnectString.php +++ /dev/null @@ -1,121 +0,0 @@ -string = $string; - } - - public function __toString() : string - { - return $this->string; - } - - /** - * Creates the object from an array representation - * - * @param mixed[] $params - */ - public static function fromArray(array $params) : self - { - return new self(self::renderParams($params)); - } - - /** - * Creates the object from the given DBAL connection parameters. - * - * @param mixed[] $params - */ - public static function fromConnectionParameters(array $params) : self - { - if (! empty($params['connectstring'])) { - return new self($params['connectstring']); - } - - if (empty($params['host'])) { - return new self($params['dbname'] ?? ''); - } - - $connectData = []; - - if (isset($params['servicename']) || isset($params['dbname'])) { - $serviceKey = 'SID'; - - if (! empty($params['service'])) { - $serviceKey = 'SERVICE_NAME'; - } - - $serviceName = $params['servicename'] ?? $params['dbname']; - - $connectData[$serviceKey] = $serviceName; - } - - if (! empty($params['instancename'])) { - $connectData['INSTANCE_NAME'] = $params['instancename']; - } - - if (! empty($params['pooled'])) { - $connectData['SERVER'] = 'POOLED'; - } - - return self::fromArray([ - 'DESCRIPTION' => [ - 'ADDRESS' => [ - 'PROTOCOL' => 'TCP', - 'HOST' => $params['host'], - 'PORT' => $params['port'] ?? 1521, - ], - 'CONNECT_DATA' => $connectData, - ], - ]); - } - - /** - * @param mixed[] $params - */ - private static function renderParams(array $params) : string - { - $chunks = []; - - foreach ($params as $key => $value) { - $string = self::renderValue($value); - - if ($string === '') { - continue; - } - - $chunks[] = sprintf('(%s=%s)', $key, $string); - } - - return implode('', $chunks); - } - - /** - * @param mixed $value - */ - private static function renderValue($value) : string - { - if (is_array($value)) { - return self::renderParams($value); - } - - return (string) $value; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractPostgreSQLDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractPostgreSQLDriver.php deleted file mode 100644 index 916d924..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractPostgreSQLDriver.php +++ /dev/null @@ -1,138 +0,0 @@ -getSQLState()) { - case '40001': - case '40P01': - return new Exception\DeadlockException($message, $exception); - case '0A000': - // Foreign key constraint violations during a TRUNCATE operation - // are considered "feature not supported" in PostgreSQL. - if (strpos($exception->getMessage(), 'truncate') !== false) { - return new Exception\ForeignKeyConstraintViolationException($message, $exception); - } - - break; - case '23502': - return new Exception\NotNullConstraintViolationException($message, $exception); - - case '23503': - return new Exception\ForeignKeyConstraintViolationException($message, $exception); - - case '23505': - return new Exception\UniqueConstraintViolationException($message, $exception); - - case '42601': - return new Exception\SyntaxErrorException($message, $exception); - - case '42702': - return new Exception\NonUniqueFieldNameException($message, $exception); - - case '42703': - return new Exception\InvalidFieldNameException($message, $exception); - - case '42P01': - return new Exception\TableNotFoundException($message, $exception); - - case '42P07': - return new Exception\TableExistsException($message, $exception); - - case '7': - // In some case (mainly connection errors) the PDO exception does not provide a SQLSTATE via its code. - // The exception code is always set to 7 here. - // We have to match against the SQLSTATE in the error message in these cases. - if (strpos($exception->getMessage(), 'SQLSTATE[08006]') !== false) { - return new Exception\ConnectionException($message, $exception); - } - - break; - } - - return new Exception\DriverException($message, $exception); - } - - /** - * {@inheritdoc} - */ - public function createDatabasePlatformForVersion($version) - { - if (! preg_match('/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?/', $version, $versionParts)) { - throw DBALException::invalidPlatformVersionSpecified( - $version, - '..' - ); - } - - $majorVersion = $versionParts['major']; - $minorVersion = $versionParts['minor'] ?? 0; - $patchVersion = $versionParts['patch'] ?? 0; - $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion; - - switch (true) { - case version_compare($version, '10.0', '>='): - return new PostgreSQL100Platform(); - case version_compare($version, '9.4', '>='): - return new PostgreSQL94Platform(); - case version_compare($version, '9.2', '>='): - return new PostgreSQL92Platform(); - case version_compare($version, '9.1', '>='): - return new PostgreSQL91Platform(); - default: - return new PostgreSqlPlatform(); - } - } - - /** - * {@inheritdoc} - */ - public function getDatabase(Connection $conn) - { - $params = $conn->getParams(); - - return $params['dbname'] ?? $conn->query('SELECT CURRENT_DATABASE()')->fetchColumn(); - } - - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new PostgreSqlPlatform(); - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(Connection $conn) - { - return new PostgreSqlSchemaManager($conn); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLAnywhereDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLAnywhereDriver.php deleted file mode 100644 index 88f26ce..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLAnywhereDriver.php +++ /dev/null @@ -1,127 +0,0 @@ -getErrorCode()) { - case '-306': - case '-307': - case '-684': - return new Exception\DeadlockException($message, $exception); - case '-210': - case '-1175': - case '-1281': - return new Exception\LockWaitTimeoutException($message, $exception); - case '-100': - case '-103': - case '-832': - return new Exception\ConnectionException($message, $exception); - case '-143': - return new Exception\InvalidFieldNameException($message, $exception); - case '-193': - case '-196': - return new Exception\UniqueConstraintViolationException($message, $exception); - case '-194': - case '-198': - return new Exception\ForeignKeyConstraintViolationException($message, $exception); - case '-144': - return new Exception\NonUniqueFieldNameException($message, $exception); - case '-184': - case '-195': - return new Exception\NotNullConstraintViolationException($message, $exception); - case '-131': - return new Exception\SyntaxErrorException($message, $exception); - case '-110': - return new Exception\TableExistsException($message, $exception); - case '-141': - case '-1041': - return new Exception\TableNotFoundException($message, $exception); - } - - return new Exception\DriverException($message, $exception); - } - - /** - * {@inheritdoc} - */ - public function createDatabasePlatformForVersion($version) - { - if (! preg_match( - '/^(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?)?/', - $version, - $versionParts - )) { - throw DBALException::invalidPlatformVersionSpecified( - $version, - '...' - ); - } - - $majorVersion = $versionParts['major']; - $minorVersion = $versionParts['minor'] ?? 0; - $patchVersion = $versionParts['patch'] ?? 0; - $buildVersion = $versionParts['build'] ?? 0; - $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion . '.' . $buildVersion; - - switch (true) { - case version_compare($version, '16', '>='): - return new SQLAnywhere16Platform(); - case version_compare($version, '12', '>='): - return new SQLAnywhere12Platform(); - case version_compare($version, '11', '>='): - return new SQLAnywhere11Platform(); - default: - return new SQLAnywherePlatform(); - } - } - - /** - * {@inheritdoc} - */ - public function getDatabase(Connection $conn) - { - $params = $conn->getParams(); - - return $params['dbname'] ?? $conn->query('SELECT DB_NAME()')->fetchColumn(); - } - - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new SQLAnywhere12Platform(); - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(Connection $conn) - { - return new SQLAnywhereSchemaManager($conn); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLServerDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLServerDriver.php deleted file mode 100644 index 421d82b..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLServerDriver.php +++ /dev/null @@ -1,81 +0,0 @@ -\d+)(?:\.(?P\d+)(?:\.(?P\d+)(?:\.(?P\d+))?)?)?/', - $version, - $versionParts - )) { - throw DBALException::invalidPlatformVersionSpecified( - $version, - '...' - ); - } - - $majorVersion = $versionParts['major']; - $minorVersion = $versionParts['minor'] ?? 0; - $patchVersion = $versionParts['patch'] ?? 0; - $buildVersion = $versionParts['build'] ?? 0; - $version = $majorVersion . '.' . $minorVersion . '.' . $patchVersion . '.' . $buildVersion; - - switch (true) { - case version_compare($version, '11.00.2100', '>='): - return new SQLServer2012Platform(); - case version_compare($version, '10.00.1600', '>='): - return new SQLServer2008Platform(); - case version_compare($version, '9.00.1399', '>='): - return new SQLServer2005Platform(); - default: - return new SQLServerPlatform(); - } - } - - /** - * {@inheritdoc} - */ - public function getDatabase(Connection $conn) - { - $params = $conn->getParams(); - - return $params['dbname'] ?? $conn->query('SELECT DB_NAME()')->fetchColumn(); - } - - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new SQLServer2008Platform(); - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(Connection $conn) - { - return new SQLServerSchemaManager($conn); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php deleted file mode 100644 index 582f7ca..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractSQLiteDriver.php +++ /dev/null @@ -1,98 +0,0 @@ -getMessage(), 'database is locked') !== false) { - return new Exception\LockWaitTimeoutException($message, $exception); - } - - if (strpos($exception->getMessage(), 'must be unique') !== false || - strpos($exception->getMessage(), 'is not unique') !== false || - strpos($exception->getMessage(), 'are not unique') !== false || - strpos($exception->getMessage(), 'UNIQUE constraint failed') !== false - ) { - return new Exception\UniqueConstraintViolationException($message, $exception); - } - - if (strpos($exception->getMessage(), 'may not be NULL') !== false || - strpos($exception->getMessage(), 'NOT NULL constraint failed') !== false - ) { - return new Exception\NotNullConstraintViolationException($message, $exception); - } - - if (strpos($exception->getMessage(), 'no such table:') !== false) { - return new Exception\TableNotFoundException($message, $exception); - } - - if (strpos($exception->getMessage(), 'already exists') !== false) { - return new Exception\TableExistsException($message, $exception); - } - - if (strpos($exception->getMessage(), 'has no column named') !== false) { - return new Exception\InvalidFieldNameException($message, $exception); - } - - if (strpos($exception->getMessage(), 'ambiguous column name') !== false) { - return new Exception\NonUniqueFieldNameException($message, $exception); - } - - if (strpos($exception->getMessage(), 'syntax error') !== false) { - return new Exception\SyntaxErrorException($message, $exception); - } - - if (strpos($exception->getMessage(), 'attempt to write a readonly database') !== false) { - return new Exception\ReadOnlyException($message, $exception); - } - - if (strpos($exception->getMessage(), 'unable to open database file') !== false) { - return new Exception\ConnectionException($message, $exception); - } - - return new Exception\DriverException($message, $exception); - } - - /** - * {@inheritdoc} - */ - public function getDatabase(Connection $conn) - { - $params = $conn->getParams(); - - return $params['path'] ?? null; - } - - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new SqlitePlatform(); - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(Connection $conn) - { - return new SqliteSchemaManager($conn); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Connection.php deleted file mode 100644 index 1574581..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Connection.php +++ /dev/null @@ -1,93 +0,0 @@ -constructPdoDsn($params), - $username, - $password, - $driverOptions - ); - } - - /** - * {@inheritdoc} - */ - public function createDatabasePlatformForVersion($version) - { - return $this->getDatabasePlatform(); - } - - /** - * {@inheritdoc} - */ - public function getDatabasePlatform() - { - return new DrizzlePlatform(); - } - - /** - * {@inheritdoc} - */ - public function getSchemaManager(\Doctrine\DBAL\Connection $conn) - { - return new DrizzleSchemaManager($conn); - } - - /** - * {@inheritdoc} - * - * @deprecated - */ - public function getName() - { - return 'drizzle_pdo_mysql'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ExceptionConverterDriver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ExceptionConverterDriver.php deleted file mode 100644 index 9b79e24..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ExceptionConverterDriver.php +++ /dev/null @@ -1,22 +0,0 @@ -conn = $conn; - } - - /** - * {@inheritdoc} - */ - public function getServerVersion() - { - /** @var stdClass $serverInfo */ - $serverInfo = db2_server_info($this->conn); - - return $serverInfo->DBMS_VER; - } - - /** - * {@inheritdoc} - */ - public function requiresQueryForServerVersion() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function prepare($sql) - { - $stmt = @db2_prepare($this->conn, $sql); - if (! $stmt) { - throw new DB2Exception(db2_stmt_errormsg()); - } - - return new DB2Statement($stmt); - } - - /** - * {@inheritdoc} - */ - public function query() - { - $args = func_get_args(); - $sql = $args[0]; - $stmt = $this->prepare($sql); - $stmt->execute(); - - return $stmt; - } - - /** - * {@inheritdoc} - */ - public function quote($input, $type = ParameterType::STRING) - { - $input = db2_escape_string($input); - - if ($type === ParameterType::INTEGER) { - return $input; - } - - return "'" . $input . "'"; - } - - /** - * {@inheritdoc} - */ - public function exec($statement) - { - $stmt = @db2_exec($this->conn, $statement); - - if ($stmt === false) { - throw new DB2Exception(db2_stmt_errormsg()); - } - - return db2_num_rows($stmt); - } - - /** - * {@inheritdoc} - */ - public function lastInsertId($name = null) - { - return db2_last_insert_id($this->conn); - } - - /** - * {@inheritdoc} - */ - public function beginTransaction() - { - db2_autocommit($this->conn, DB2_AUTOCOMMIT_OFF); - } - - /** - * {@inheritdoc} - */ - public function commit() - { - if (! db2_commit($this->conn)) { - throw new DB2Exception(db2_conn_errormsg($this->conn)); - } - db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON); - } - - /** - * {@inheritdoc} - */ - public function rollBack() - { - if (! db2_rollback($this->conn)) { - throw new DB2Exception(db2_conn_errormsg($this->conn)); - } - db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON); - } - - /** - * {@inheritdoc} - */ - public function errorCode() - { - return db2_conn_error($this->conn); - } - - /** - * {@inheritdoc} - */ - public function errorInfo() - { - return [ - 0 => db2_conn_errormsg($this->conn), - 1 => $this->errorCode(), - ]; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php deleted file mode 100644 index fe79fe6..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php +++ /dev/null @@ -1,49 +0,0 @@ -stmt = $stmt; - } - - /** - * {@inheritdoc} - */ - public function bindValue($param, $value, $type = ParameterType::STRING) - { - return $this->bindParam($param, $value, $type); - } - - /** - * {@inheritdoc} - */ - public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null) - { - switch ($type) { - case ParameterType::INTEGER: - $this->bind($column, $variable, DB2_PARAM_IN, DB2_LONG); - break; - - case ParameterType::LARGE_OBJECT: - if (isset($this->lobs[$column])) { - [, $handle] = $this->lobs[$column]; - fclose($handle); - } - - $handle = $this->createTemporaryFile(); - $path = stream_get_meta_data($handle)['uri']; - - $this->bind($column, $path, DB2_PARAM_FILE, DB2_BINARY); - - $this->lobs[$column] = [&$variable, $handle]; - break; - - default: - $this->bind($column, $variable, DB2_PARAM_IN, DB2_CHAR); - break; - } - - return true; - } - - /** - * @param int $position Parameter position - * @param mixed $variable - * - * @throws DB2Exception - */ - private function bind($position, &$variable, int $parameterType, int $dataType) : void - { - $this->bindParam[$position] =& $variable; - - if (! db2_bind_param($this->stmt, $position, 'variable', $parameterType, $dataType)) { - throw new DB2Exception(db2_stmt_errormsg()); - } - } - - /** - * {@inheritdoc} - */ - public function closeCursor() - { - $this->bindParam = []; - - if (! db2_free_result($this->stmt)) { - return false; - } - - $this->result = false; - - return true; - } - - /** - * {@inheritdoc} - */ - public function columnCount() - { - return db2_num_fields($this->stmt) ?: 0; - } - - /** - * {@inheritdoc} - */ - public function errorCode() - { - return db2_stmt_error(); - } - - /** - * {@inheritdoc} - */ - public function errorInfo() - { - return [ - db2_stmt_errormsg(), - db2_stmt_error(), - ]; - } - - /** - * {@inheritdoc} - */ - public function execute($params = null) - { - if ($params === null) { - ksort($this->bindParam); - - $params = []; - - foreach ($this->bindParam as $column => $value) { - $params[] = $value; - } - } - - foreach ($this->lobs as [$source, $target]) { - if (is_resource($source)) { - $this->copyStreamToStream($source, $target); - - continue; - } - - $this->writeStringToStream($source, $target); - } - - $retval = db2_execute($this->stmt, $params); - - foreach ($this->lobs as [, $handle]) { - fclose($handle); - } - - $this->lobs = []; - - if ($retval === false) { - throw new DB2Exception(db2_stmt_errormsg()); - } - - $this->result = true; - - return $retval; - } - - /** - * {@inheritdoc} - */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) - { - $this->defaultFetchMode = $fetchMode; - $this->defaultFetchClass = $arg2 ?: $this->defaultFetchClass; - $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; - - return true; - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - return new StatementIterator($this); - } - - /** - * {@inheritdoc} - */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) - { - // do not try fetching from the statement if it's not expected to contain result - // in order to prevent exceptional situation - if (! $this->result) { - return false; - } - - $fetchMode = $fetchMode ?: $this->defaultFetchMode; - switch ($fetchMode) { - case FetchMode::COLUMN: - return $this->fetchColumn(); - - case FetchMode::MIXED: - return db2_fetch_both($this->stmt); - - case FetchMode::ASSOCIATIVE: - return db2_fetch_assoc($this->stmt); - - case FetchMode::CUSTOM_OBJECT: - $className = $this->defaultFetchClass; - $ctorArgs = $this->defaultFetchClassCtorArgs; - - if (func_num_args() >= 2) { - $args = func_get_args(); - $className = $args[1]; - $ctorArgs = $args[2] ?? []; - } - - $result = db2_fetch_object($this->stmt); - - if ($result instanceof stdClass) { - $result = $this->castObject($result, $className, $ctorArgs); - } - - return $result; - - case FetchMode::NUMERIC: - return db2_fetch_array($this->stmt); - - case FetchMode::STANDARD_OBJECT: - return db2_fetch_object($this->stmt); - - default: - throw new DB2Exception('Given Fetch-Style ' . $fetchMode . ' is not supported.'); - } - } - - /** - * {@inheritdoc} - */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) - { - $rows = []; - - switch ($fetchMode) { - case FetchMode::CUSTOM_OBJECT: - while (($row = $this->fetch(...func_get_args())) !== false) { - $rows[] = $row; - } - break; - case FetchMode::COLUMN: - while (($row = $this->fetchColumn()) !== false) { - $rows[] = $row; - } - break; - default: - while (($row = $this->fetch($fetchMode)) !== false) { - $rows[] = $row; - } - } - - return $rows; - } - - /** - * {@inheritdoc} - */ - public function fetchColumn($columnIndex = 0) - { - $row = $this->fetch(FetchMode::NUMERIC); - - if ($row === false) { - return false; - } - - return $row[$columnIndex] ?? null; - } - - /** - * {@inheritdoc} - */ - public function rowCount() - { - return @db2_num_rows($this->stmt) ? : 0; - } - - /** - * Casts a stdClass object to the given class name mapping its' properties. - * - * @param stdClass $sourceObject Object to cast from. - * @param string|object $destinationClass Name of the class or class instance to cast to. - * @param mixed[] $ctorArgs Arguments to use for constructing the destination class instance. - * - * @return object - * - * @throws DB2Exception - */ - private function castObject(stdClass $sourceObject, $destinationClass, array $ctorArgs = []) - { - if (! is_string($destinationClass)) { - if (! is_object($destinationClass)) { - throw new DB2Exception(sprintf( - 'Destination class has to be of type string or object, %s given.', - gettype($destinationClass) - )); - } - } else { - $destinationClass = new ReflectionClass($destinationClass); - $destinationClass = $destinationClass->newInstanceArgs($ctorArgs); - } - - $sourceReflection = new ReflectionObject($sourceObject); - $destinationClassReflection = new ReflectionObject($destinationClass); - /** @var ReflectionProperty[] $destinationProperties */ - $destinationProperties = array_change_key_case($destinationClassReflection->getProperties(), CASE_LOWER); - - foreach ($sourceReflection->getProperties() as $sourceProperty) { - $sourceProperty->setAccessible(true); - - $name = $sourceProperty->getName(); - $value = $sourceProperty->getValue($sourceObject); - - // Try to find a case-matching property. - if ($destinationClassReflection->hasProperty($name)) { - $destinationProperty = $destinationClassReflection->getProperty($name); - - $destinationProperty->setAccessible(true); - $destinationProperty->setValue($destinationClass, $value); - - continue; - } - - $name = strtolower($name); - - // Try to find a property without matching case. - // Fallback for the driver returning either all uppercase or all lowercase column names. - if (isset($destinationProperties[$name])) { - $destinationProperty = $destinationProperties[$name]; - - $destinationProperty->setAccessible(true); - $destinationProperty->setValue($destinationClass, $value); - - continue; - } - - $destinationClass->$name = $value; - } - - return $destinationClass; - } - - /** - * @return resource - * - * @throws DB2Exception - */ - private function createTemporaryFile() - { - $handle = @tmpfile(); - - if ($handle === false) { - throw new DB2Exception('Could not create temporary file: ' . error_get_last()['message']); - } - - return $handle; - } - - /** - * @param resource $source - * @param resource $target - * - * @throws DB2Exception - */ - private function copyStreamToStream($source, $target) : void - { - if (@stream_copy_to_stream($source, $target) === false) { - throw new DB2Exception('Could not copy source stream to temporary file: ' . error_get_last()['message']); - } - } - - /** - * @param resource $target - * - * @throws DB2Exception - */ - private function writeStringToStream(string $string, $target) : void - { - if (@fwrite($target, $string) === false) { - throw new DB2Exception('Could not write string to temporary file: ' . error_get_last()['message']); - } - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/Driver.php deleted file mode 100644 index 1166e8d..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/Driver.php +++ /dev/null @@ -1,29 +0,0 @@ -conn = mysqli_init(); - - $this->setSecureConnection($params); - $this->setDriverOptions($driverOptions); - - set_error_handler(static function () { - }); - try { - if (! $this->conn->real_connect($params['host'], $username, $password, $dbname, $port, $socket, $flags)) { - throw new MysqliException($this->conn->connect_error, $this->conn->sqlstate ?? 'HY000', $this->conn->connect_errno); - } - } finally { - restore_error_handler(); - } - - if (! isset($params['charset'])) { - return; - } - - $this->conn->set_charset($params['charset']); - } - - /** - * Retrieves mysqli native resource handle. - * - * Could be used if part of your application is not using DBAL. - * - * @return mysqli - */ - public function getWrappedResourceHandle() - { - return $this->conn; - } - - /** - * {@inheritdoc} - * - * The server version detection includes a special case for MariaDB - * to support '5.5.5-' prefixed versions introduced in Maria 10+ - * - * @link https://jira.mariadb.org/browse/MDEV-4088 - */ - public function getServerVersion() - { - $serverInfos = $this->conn->get_server_info(); - if (stripos($serverInfos, 'mariadb') !== false) { - return $serverInfos; - } - - $majorVersion = floor($this->conn->server_version / 10000); - $minorVersion = floor(($this->conn->server_version - $majorVersion * 10000) / 100); - $patchVersion = floor($this->conn->server_version - $majorVersion * 10000 - $minorVersion * 100); - - return $majorVersion . '.' . $minorVersion . '.' . $patchVersion; - } - - /** - * {@inheritdoc} - */ - public function requiresQueryForServerVersion() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function prepare($prepareString) - { - return new MysqliStatement($this->conn, $prepareString); - } - - /** - * {@inheritdoc} - */ - public function query() - { - $args = func_get_args(); - $sql = $args[0]; - $stmt = $this->prepare($sql); - $stmt->execute(); - - return $stmt; - } - - /** - * {@inheritdoc} - */ - public function quote($input, $type = ParameterType::STRING) - { - return "'" . $this->conn->escape_string($input) . "'"; - } - - /** - * {@inheritdoc} - */ - public function exec($statement) - { - if ($this->conn->query($statement) === false) { - throw new MysqliException($this->conn->error, $this->conn->sqlstate, $this->conn->errno); - } - - return $this->conn->affected_rows; - } - - /** - * {@inheritdoc} - */ - public function lastInsertId($name = null) - { - return $this->conn->insert_id; - } - - /** - * {@inheritdoc} - */ - public function beginTransaction() - { - $this->conn->query('START TRANSACTION'); - - return true; - } - - /** - * {@inheritdoc} - */ - public function commit() - { - return $this->conn->commit(); - } - - /** - * {@inheritdoc}non-PHPdoc) - */ - public function rollBack() - { - return $this->conn->rollback(); - } - - /** - * {@inheritdoc} - */ - public function errorCode() - { - return $this->conn->errno; - } - - /** - * {@inheritdoc} - */ - public function errorInfo() - { - return $this->conn->error; - } - - /** - * Apply the driver options to the connection. - * - * @param mixed[] $driverOptions - * - * @throws MysqliException When one of of the options is not supported. - * @throws MysqliException When applying doesn't work - e.g. due to incorrect value. - */ - private function setDriverOptions(array $driverOptions = []) - { - $supportedDriverOptions = [ - MYSQLI_OPT_CONNECT_TIMEOUT, - MYSQLI_OPT_LOCAL_INFILE, - MYSQLI_INIT_COMMAND, - MYSQLI_READ_DEFAULT_FILE, - MYSQLI_READ_DEFAULT_GROUP, - ]; - - if (defined('MYSQLI_SERVER_PUBLIC_KEY')) { - $supportedDriverOptions[] = MYSQLI_SERVER_PUBLIC_KEY; - } - - $exceptionMsg = "%s option '%s' with value '%s'"; - - foreach ($driverOptions as $option => $value) { - if ($option === static::OPTION_FLAGS) { - continue; - } - - if (! in_array($option, $supportedDriverOptions, true)) { - throw new MysqliException( - sprintf($exceptionMsg, 'Unsupported', $option, $value) - ); - } - - if (@mysqli_options($this->conn, $option, $value)) { - continue; - } - - $msg = sprintf($exceptionMsg, 'Failed to set', $option, $value); - $msg .= sprintf(', error: %s (%d)', mysqli_error($this->conn), mysqli_errno($this->conn)); - - throw new MysqliException( - $msg, - $this->conn->sqlstate, - $this->conn->errno - ); - } - } - - /** - * Pings the server and re-connects when `mysqli.reconnect = 1` - * - * @return bool - */ - public function ping() - { - return $this->conn->ping(); - } - - /** - * Establish a secure connection - * - * @param mixed[] $params - * - * @throws MysqliException - */ - private function setSecureConnection(array $params) - { - if (! isset($params['ssl_key']) && - ! isset($params['ssl_cert']) && - ! isset($params['ssl_ca']) && - ! isset($params['ssl_capath']) && - ! isset($params['ssl_cipher']) - ) { - return; - } - - $this->conn->ssl_set( - $params['ssl_key'] ?? null, - $params['ssl_cert'] ?? null, - $params['ssl_ca'] ?? null, - $params['ssl_capath'] ?? null, - $params['ssl_cipher'] ?? null - ); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliException.php deleted file mode 100644 index 1fa0c90..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/Mysqli/MysqliException.php +++ /dev/null @@ -1,12 +0,0 @@ - 's', - ParameterType::BINARY => 's', - ParameterType::BOOLEAN => 'i', - ParameterType::NULL => 's', - ParameterType::INTEGER => 'i', - ParameterType::LARGE_OBJECT => 'b', - ]; - - /** @var mysqli */ - protected $_conn; - - /** @var mysqli_stmt */ - protected $_stmt; - - /** @var string[]|false|null */ - protected $_columnNames; - - /** @var mixed[] */ - protected $_rowBindedValues = []; - - /** @var mixed[] */ - protected $_bindedValues; - - /** @var string */ - protected $types; - - /** - * Contains ref values for bindValue(). - * - * @var mixed[] - */ - protected $_values = []; - - /** @var int */ - protected $_defaultFetchMode = FetchMode::MIXED; - - /** - * Indicates whether the statement is in the state when fetching results is possible - * - * @var bool - */ - private $result = false; - - /** - * @param string $prepareString - * - * @throws MysqliException - */ - public function __construct(mysqli $conn, $prepareString) - { - $this->_conn = $conn; - - $stmt = $conn->prepare($prepareString); - - if ($stmt === false) { - throw new MysqliException($this->_conn->error, $this->_conn->sqlstate, $this->_conn->errno); - } - - $this->_stmt = $stmt; - - $paramCount = $this->_stmt->param_count; - if (0 >= $paramCount) { - return; - } - - $this->types = str_repeat('s', $paramCount); - $this->_bindedValues = array_fill(1, $paramCount, null); - } - - /** - * {@inheritdoc} - */ - public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null) - { - assert(is_int($column)); - - if (! isset(self::$_paramTypeMap[$type])) { - throw new MysqliException(sprintf("Unknown type: '%s'", $type)); - } - - $this->_bindedValues[$column] =& $variable; - $this->types[$column - 1] = self::$_paramTypeMap[$type]; - - return true; - } - - /** - * {@inheritdoc} - */ - public function bindValue($param, $value, $type = ParameterType::STRING) - { - assert(is_int($param)); - - if (! isset(self::$_paramTypeMap[$type])) { - throw new MysqliException(sprintf("Unknown type: '%s'", $type)); - } - - $this->_values[$param] = $value; - $this->_bindedValues[$param] =& $this->_values[$param]; - $this->types[$param - 1] = self::$_paramTypeMap[$type]; - - return true; - } - - /** - * {@inheritdoc} - */ - public function execute($params = null) - { - if ($this->_bindedValues !== null) { - if ($params !== null) { - if (! $this->bindUntypedValues($params)) { - throw new MysqliException($this->_stmt->error, $this->_stmt->errno); - } - } else { - $this->bindTypedParameters(); - } - } - - if (! $this->_stmt->execute()) { - throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); - } - - if ($this->_columnNames === null) { - $meta = $this->_stmt->result_metadata(); - if ($meta !== false) { - $fields = $meta->fetch_fields(); - assert(is_array($fields)); - - $columnNames = []; - foreach ($fields as $col) { - $columnNames[] = $col->name; - } - - $meta->free(); - - $this->_columnNames = $columnNames; - } else { - $this->_columnNames = false; - } - } - - if ($this->_columnNames !== false) { - // Store result of every execution which has it. Otherwise it will be impossible - // to execute a new statement in case if the previous one has non-fetched rows - // @link http://dev.mysql.com/doc/refman/5.7/en/commands-out-of-sync.html - $this->_stmt->store_result(); - - // Bind row values _after_ storing the result. Otherwise, if mysqli is compiled with libmysql, - // it will have to allocate as much memory as it may be needed for the given column type - // (e.g. for a LONGBLOB field it's 4 gigabytes) - // @link https://bugs.php.net/bug.php?id=51386#1270673122 - // - // Make sure that the values are bound after each execution. Otherwise, if closeCursor() has been - // previously called on the statement, the values are unbound making the statement unusable. - // - // It's also important that row values are bound after _each_ call to store_result(). Otherwise, - // if mysqli is compiled with libmysql, subsequently fetched string values will get truncated - // to the length of the ones fetched during the previous execution. - $this->_rowBindedValues = array_fill(0, count($this->_columnNames), null); - - $refs = []; - foreach ($this->_rowBindedValues as $key => &$value) { - $refs[$key] =& $value; - } - - if (! $this->_stmt->bind_result(...$refs)) { - throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); - } - } - - $this->result = true; - - return true; - } - - /** - * Binds parameters with known types previously bound to the statement - */ - private function bindTypedParameters() - { - $streams = $values = []; - $types = $this->types; - - foreach ($this->_bindedValues as $parameter => $value) { - if (! isset($types[$parameter - 1])) { - $types[$parameter - 1] = static::$_paramTypeMap[ParameterType::STRING]; - } - - if ($types[$parameter - 1] === static::$_paramTypeMap[ParameterType::LARGE_OBJECT]) { - if (is_resource($value)) { - if (get_resource_type($value) !== 'stream') { - throw new InvalidArgumentException('Resources passed with the LARGE_OBJECT parameter type must be stream resources.'); - } - $streams[$parameter] = $value; - $values[$parameter] = null; - continue; - } - - $types[$parameter - 1] = static::$_paramTypeMap[ParameterType::STRING]; - } - - $values[$parameter] = $value; - } - - if (! $this->_stmt->bind_param($types, ...$values)) { - throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); - } - - $this->sendLongData($streams); - } - - /** - * Handle $this->_longData after regular query parameters have been bound - * - * @throws MysqliException - */ - private function sendLongData($streams) - { - foreach ($streams as $paramNr => $stream) { - while (! feof($stream)) { - $chunk = fread($stream, 8192); - - if ($chunk === false) { - throw new MysqliException("Failed reading the stream resource for parameter offset ${paramNr}."); - } - - if (! $this->_stmt->send_long_data($paramNr - 1, $chunk)) { - throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); - } - } - } - } - - /** - * Binds a array of values to bound parameters. - * - * @param mixed[] $values - * - * @return bool - */ - private function bindUntypedValues(array $values) - { - $params = []; - $types = str_repeat('s', count($values)); - - foreach ($values as &$v) { - $params[] =& $v; - } - - return $this->_stmt->bind_param($types, ...$params); - } - - /** - * @return mixed[]|false|null - */ - private function _fetch() - { - $ret = $this->_stmt->fetch(); - - if ($ret === true) { - $values = []; - foreach ($this->_rowBindedValues as $v) { - $values[] = $v; - } - - return $values; - } - - return $ret; - } - - /** - * {@inheritdoc} - */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) - { - // do not try fetching from the statement if it's not expected to contain result - // in order to prevent exceptional situation - if (! $this->result) { - return false; - } - - $fetchMode = $fetchMode ?: $this->_defaultFetchMode; - - if ($fetchMode === FetchMode::COLUMN) { - return $this->fetchColumn(); - } - - $values = $this->_fetch(); - - if ($values === null) { - return false; - } - - if ($values === false) { - throw new MysqliException($this->_stmt->error, $this->_stmt->sqlstate, $this->_stmt->errno); - } - - if ($fetchMode === FetchMode::NUMERIC) { - return $values; - } - - assert(is_array($this->_columnNames)); - $assoc = array_combine($this->_columnNames, $values); - assert(is_array($assoc)); - - switch ($fetchMode) { - case FetchMode::ASSOCIATIVE: - return $assoc; - - case FetchMode::MIXED: - return $assoc + $values; - - case FetchMode::STANDARD_OBJECT: - return (object) $assoc; - - default: - throw new MysqliException(sprintf("Unknown fetch type '%s'", $fetchMode)); - } - } - - /** - * {@inheritdoc} - */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) - { - $fetchMode = $fetchMode ?: $this->_defaultFetchMode; - - $rows = []; - - if ($fetchMode === FetchMode::COLUMN) { - while (($row = $this->fetchColumn()) !== false) { - $rows[] = $row; - } - } else { - while (($row = $this->fetch($fetchMode)) !== false) { - $rows[] = $row; - } - } - - return $rows; - } - - /** - * {@inheritdoc} - */ - public function fetchColumn($columnIndex = 0) - { - $row = $this->fetch(FetchMode::NUMERIC); - - if ($row === false) { - return false; - } - - return $row[$columnIndex] ?? null; - } - - /** - * {@inheritdoc} - */ - public function errorCode() - { - return $this->_stmt->errno; - } - - /** - * {@inheritdoc} - */ - public function errorInfo() - { - return $this->_stmt->error; - } - - /** - * {@inheritdoc} - */ - public function closeCursor() - { - $this->_stmt->free_result(); - $this->result = false; - - return true; - } - - /** - * {@inheritdoc} - */ - public function rowCount() - { - if ($this->_columnNames === false) { - return $this->_stmt->affected_rows; - } - - return $this->_stmt->num_rows; - } - - /** - * {@inheritdoc} - */ - public function columnCount() - { - return $this->_stmt->field_count; - } - - /** - * {@inheritdoc} - */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) - { - $this->_defaultFetchMode = $fetchMode; - - return true; - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - return new StatementIterator($this); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/Driver.php deleted file mode 100644 index edda32d..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/Driver.php +++ /dev/null @@ -1,54 +0,0 @@ -_constructDsn($params), - $params['charset'] ?? '', - $params['sessionMode'] ?? OCI_DEFAULT, - $params['persistent'] ?? false - ); - } catch (OCI8Exception $e) { - throw DBALException::driverException($this, $e); - } - } - - /** - * Constructs the Oracle DSN. - * - * @param mixed[] $params - * - * @return string The DSN. - */ - protected function _constructDsn(array $params) - { - return $this->getEasyConnectString($params); - } - - /** - * {@inheritdoc} - * - * @deprecated - */ - public function getName() - { - return 'oci8'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php deleted file mode 100644 index c185793..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php +++ /dev/null @@ -1,241 +0,0 @@ -dbh = $dbh; - } - - /** - * {@inheritdoc} - * - * @throws UnexpectedValueException If the version string returned by the database server - * does not contain a parsable version number. - */ - public function getServerVersion() - { - $version = oci_server_version($this->dbh); - - if ($version === false) { - throw OCI8Exception::fromErrorInfo(oci_error($this->dbh)); - } - - if (! preg_match('/\s+(\d+\.\d+\.\d+\.\d+\.\d+)\s+/', $version, $matches)) { - throw new UnexpectedValueException( - sprintf( - 'Unexpected database version string "%s". Cannot parse an appropriate version number from it. ' . - 'Please report this database version string to the Doctrine team.', - $version - ) - ); - } - - return $matches[1]; - } - - /** - * {@inheritdoc} - */ - public function requiresQueryForServerVersion() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function prepare($prepareString) - { - return new OCI8Statement($this->dbh, $prepareString, $this); - } - - /** - * {@inheritdoc} - */ - public function query() - { - $args = func_get_args(); - $sql = $args[0]; - //$fetchMode = $args[1]; - $stmt = $this->prepare($sql); - $stmt->execute(); - - return $stmt; - } - - /** - * {@inheritdoc} - */ - public function quote($value, $type = ParameterType::STRING) - { - if (is_int($value) || is_float($value)) { - return $value; - } - $value = str_replace("'", "''", $value); - - return "'" . addcslashes($value, "\000\n\r\\\032") . "'"; - } - - /** - * {@inheritdoc} - */ - public function exec($statement) - { - $stmt = $this->prepare($statement); - $stmt->execute(); - - return $stmt->rowCount(); - } - - /** - * {@inheritdoc} - */ - public function lastInsertId($name = null) - { - if ($name === null) { - return false; - } - - $sql = 'SELECT ' . $name . '.CURRVAL FROM DUAL'; - $stmt = $this->query($sql); - $result = $stmt->fetchColumn(); - - if ($result === false) { - throw new OCI8Exception('lastInsertId failed: Query was executed but no result was returned.'); - } - - return (int) $result; - } - - /** - * Returns the current execution mode. - * - * @return int - */ - public function getExecuteMode() - { - return $this->executeMode; - } - - /** - * {@inheritdoc} - */ - public function beginTransaction() - { - $this->executeMode = OCI_NO_AUTO_COMMIT; - - return true; - } - - /** - * {@inheritdoc} - */ - public function commit() - { - if (! oci_commit($this->dbh)) { - throw OCI8Exception::fromErrorInfo($this->errorInfo()); - } - $this->executeMode = OCI_COMMIT_ON_SUCCESS; - - return true; - } - - /** - * {@inheritdoc} - */ - public function rollBack() - { - if (! oci_rollback($this->dbh)) { - throw OCI8Exception::fromErrorInfo($this->errorInfo()); - } - $this->executeMode = OCI_COMMIT_ON_SUCCESS; - - return true; - } - - /** - * {@inheritdoc} - */ - public function errorCode() - { - $error = oci_error($this->dbh); - if ($error !== false) { - $error = $error['code']; - } - - return $error; - } - - /** - * {@inheritdoc} - */ - public function errorInfo() - { - $error = oci_error($this->dbh); - - if ($error === false) { - return []; - } - - return $error; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php deleted file mode 100644 index af3a9d1..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php +++ /dev/null @@ -1,22 +0,0 @@ - OCI_BOTH, - FetchMode::ASSOCIATIVE => OCI_ASSOC, - FetchMode::NUMERIC => OCI_NUM, - FetchMode::COLUMN => OCI_NUM, - ]; - - /** @var int */ - protected $_defaultFetchMode = FetchMode::MIXED; - - /** @var string[] */ - protected $_paramMap = []; - - /** - * Holds references to bound parameter values. - * - * This is a new requirement for PHP7's oci8 extension that prevents bound values from being garbage collected. - * - * @var mixed[] - */ - private $boundValues = []; - - /** - * Indicates whether the statement is in the state when fetching results is possible - * - * @var bool - */ - private $result = false; - - /** - * Creates a new OCI8Statement that uses the given connection handle and SQL statement. - * - * @param resource $dbh The connection handle. - * @param string $query The SQL query. - */ - public function __construct($dbh, $query, OCI8Connection $conn) - { - [$query, $paramMap] = self::convertPositionalToNamedPlaceholders($query); - - $stmt = oci_parse($dbh, $query); - assert(is_resource($stmt)); - - $this->_sth = $stmt; - $this->_dbh = $dbh; - $this->_paramMap = $paramMap; - $this->_conn = $conn; - } - - /** - * Converts positional (?) into named placeholders (:param). - * - * 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. - * - * @param string $statement The SQL statement to convert. - * - * @return mixed[] [0] => the statement value (string), [1] => the paramMap value (array). - * - * @throws OCI8Exception - * - * @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. - */ - public static function convertPositionalToNamedPlaceholders($statement) - { - $fragmentOffset = $tokenOffset = 0; - $fragments = $paramMap = []; - $currentLiteralDelimiter = null; - - do { - if (! $currentLiteralDelimiter) { - $result = self::findPlaceholderOrOpeningQuote( - $statement, - $tokenOffset, - $fragmentOffset, - $fragments, - $currentLiteralDelimiter, - $paramMap - ); - } else { - $result = self::findClosingQuote($statement, $tokenOffset, $currentLiteralDelimiter); - } - } while ($result); - - if ($currentLiteralDelimiter) { - throw new OCI8Exception(sprintf( - 'The statement contains non-terminated string literal starting at offset %d', - $tokenOffset - 1 - )); - } - - $fragments[] = substr($statement, $fragmentOffset); - $statement = implode('', $fragments); - - return [$statement, $paramMap]; - } - - /** - * Finds next placeholder or opening quote. - * - * @param string $statement The SQL statement to parse - * @param string $tokenOffset The offset to start searching from - * @param int $fragmentOffset The offset to build the next fragment from - * @param string[] $fragments Fragments of the original statement not containing placeholders - * @param string|null $currentLiteralDelimiter The delimiter of the current string literal - * or NULL if not currently in a literal - * @param array $paramMap Mapping of the original parameter positions to their named replacements - * - * @return bool Whether the token was found - */ - private static function findPlaceholderOrOpeningQuote( - $statement, - &$tokenOffset, - &$fragmentOffset, - &$fragments, - &$currentLiteralDelimiter, - &$paramMap - ) { - $token = self::findToken($statement, $tokenOffset, '/[?\'"]/'); - - if (! $token) { - return false; - } - - if ($token === '?') { - $position = count($paramMap) + 1; - $param = ':param' . $position; - $fragments[] = substr($statement, $fragmentOffset, $tokenOffset - $fragmentOffset); - $fragments[] = $param; - $paramMap[$position] = $param; - $tokenOffset += 1; - $fragmentOffset = $tokenOffset; - - return true; - } - - $currentLiteralDelimiter = $token; - ++$tokenOffset; - - return true; - } - - /** - * Finds closing quote - * - * @param string $statement The SQL statement to parse - * @param string $tokenOffset The offset to start searching from - * @param string $currentLiteralDelimiter The delimiter of the current string literal - * - * @return bool Whether the token was found - */ - private static function findClosingQuote( - $statement, - &$tokenOffset, - &$currentLiteralDelimiter - ) { - $token = self::findToken( - $statement, - $tokenOffset, - '/' . preg_quote($currentLiteralDelimiter, '/') . '/' - ); - - if (! $token) { - return false; - } - - $currentLiteralDelimiter = false; - ++$tokenOffset; - - return true; - } - - /** - * Finds the token described by regex starting from the given offset. Updates the offset with the position - * where the token was found. - * - * @param string $statement The SQL statement to parse - * @param int $offset The offset to start searching from - * @param string $regex The regex containing token pattern - * - * @return string|null Token or NULL if not found - */ - private static function findToken($statement, &$offset, $regex) - { - if (preg_match($regex, $statement, $matches, PREG_OFFSET_CAPTURE, $offset)) { - $offset = $matches[0][1]; - - return $matches[0][0]; - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function bindValue($param, $value, $type = ParameterType::STRING) - { - return $this->bindParam($param, $value, $type, null); - } - - /** - * {@inheritdoc} - */ - public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null) - { - $column = $this->_paramMap[$column]; - - if ($type === ParameterType::LARGE_OBJECT) { - $lob = oci_new_descriptor($this->_dbh, OCI_D_LOB); - - $class = 'OCI-Lob'; - assert($lob instanceof $class); - - $lob->writeTemporary($variable, OCI_TEMP_BLOB); - - $variable =& $lob; - } - - $this->boundValues[$column] =& $variable; - - return oci_bind_by_name( - $this->_sth, - $column, - $variable, - $length ?? -1, - $this->convertParameterType($type) - ); - } - - /** - * Converts DBAL parameter type to oci8 parameter type - */ - private function convertParameterType(int $type) : int - { - switch ($type) { - case ParameterType::BINARY: - return OCI_B_BIN; - - case ParameterType::LARGE_OBJECT: - return OCI_B_BLOB; - - default: - return SQLT_CHR; - } - } - - /** - * {@inheritdoc} - */ - public function closeCursor() - { - // not having the result means there's nothing to close - if (! $this->result) { - return true; - } - - oci_cancel($this->_sth); - - $this->result = false; - - return true; - } - - /** - * {@inheritdoc} - */ - public function columnCount() - { - return oci_num_fields($this->_sth) ?: 0; - } - - /** - * {@inheritdoc} - */ - public function errorCode() - { - $error = oci_error($this->_sth); - if ($error !== false) { - $error = $error['code']; - } - - return $error; - } - - /** - * {@inheritdoc} - */ - public function errorInfo() - { - $error = oci_error($this->_sth); - - if ($error === false) { - return []; - } - - return $error; - } - - /** - * {@inheritdoc} - */ - public function execute($params = null) - { - if ($params) { - $hasZeroIndex = array_key_exists(0, $params); - - foreach ($params as $key => $val) { - if ($hasZeroIndex && is_int($key)) { - $this->bindValue($key + 1, $val); - } else { - $this->bindValue($key, $val); - } - } - } - - $ret = @oci_execute($this->_sth, $this->_conn->getExecuteMode()); - if (! $ret) { - throw OCI8Exception::fromErrorInfo($this->errorInfo()); - } - - $this->result = true; - - return $ret; - } - - /** - * {@inheritdoc} - */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) - { - $this->_defaultFetchMode = $fetchMode; - - return true; - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - return new StatementIterator($this); - } - - /** - * {@inheritdoc} - */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) - { - // do not try fetching from the statement if it's not expected to contain result - // in order to prevent exceptional situation - if (! $this->result) { - return false; - } - - $fetchMode = $fetchMode ?: $this->_defaultFetchMode; - - if ($fetchMode === FetchMode::COLUMN) { - return $this->fetchColumn(); - } - - if ($fetchMode === FetchMode::STANDARD_OBJECT) { - return oci_fetch_object($this->_sth); - } - - if (! isset(self::$fetchModeMap[$fetchMode])) { - throw new InvalidArgumentException('Invalid fetch style: ' . $fetchMode); - } - - return oci_fetch_array( - $this->_sth, - self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | OCI_RETURN_LOBS - ); - } - - /** - * {@inheritdoc} - */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) - { - $fetchMode = $fetchMode ?: $this->_defaultFetchMode; - - $result = []; - - if ($fetchMode === FetchMode::STANDARD_OBJECT) { - while ($row = $this->fetch($fetchMode)) { - $result[] = $row; - } - - return $result; - } - - if (! isset(self::$fetchModeMap[$fetchMode])) { - throw new InvalidArgumentException('Invalid fetch style: ' . $fetchMode); - } - - if (self::$fetchModeMap[$fetchMode] === OCI_BOTH) { - while ($row = $this->fetch($fetchMode)) { - $result[] = $row; - } - } else { - $fetchStructure = OCI_FETCHSTATEMENT_BY_ROW; - - if ($fetchMode === FetchMode::COLUMN) { - $fetchStructure = OCI_FETCHSTATEMENT_BY_COLUMN; - } - - // do not try fetching from the statement if it's not expected to contain result - // in order to prevent exceptional situation - if (! $this->result) { - return []; - } - - oci_fetch_all( - $this->_sth, - $result, - 0, - -1, - self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | $fetchStructure | OCI_RETURN_LOBS - ); - - if ($fetchMode === FetchMode::COLUMN) { - $result = $result[0]; - } - } - - return $result; - } - - /** - * {@inheritdoc} - */ - public function fetchColumn($columnIndex = 0) - { - // do not try fetching from the statement if it's not expected to contain result - // in order to prevent exceptional situation - if (! $this->result) { - return false; - } - - $row = oci_fetch_array($this->_sth, OCI_NUM | OCI_RETURN_NULLS | OCI_RETURN_LOBS); - - if ($row === false) { - return false; - } - - return $row[$columnIndex] ?? null; - } - - /** - * {@inheritdoc} - */ - public function rowCount() - { - return oci_num_rows($this->_sth) ?: 0; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php deleted file mode 100644 index 336542e..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php +++ /dev/null @@ -1,115 +0,0 @@ -setAttribute(PDO::ATTR_STATEMENT_CLASS, [PDOStatement::class, []]); - $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - } catch (\PDOException $exception) { - throw new PDOException($exception); - } - } - - /** - * {@inheritdoc} - */ - public function exec($statement) - { - try { - return parent::exec($statement); - } catch (\PDOException $exception) { - throw new PDOException($exception); - } - } - - /** - * {@inheritdoc} - */ - public function getServerVersion() - { - return PDO::getAttribute(PDO::ATTR_SERVER_VERSION); - } - - /** - * {@inheritdoc} - */ - public function prepare($prepareString, $driverOptions = []) - { - try { - return parent::prepare($prepareString, $driverOptions); - } catch (\PDOException $exception) { - throw new PDOException($exception); - } - } - - /** - * {@inheritdoc} - */ - public function query() - { - $args = func_get_args(); - - try { - $stmt = parent::query(...$args); - assert($stmt instanceof \PDOStatement); - - return $stmt; - } catch (\PDOException $exception) { - throw new PDOException($exception); - } - } - - /** - * {@inheritdoc} - */ - public function quote($input, $type = ParameterType::STRING) - { - return parent::quote($input, $type); - } - - /** - * {@inheritdoc} - */ - public function lastInsertId($name = null) - { - try { - if ($name === null) { - return parent::lastInsertId(); - } - - return parent::lastInsertId($name); - } catch (\PDOException $exception) { - throw new PDOException($exception); - } - } - - /** - * {@inheritdoc} - */ - public function requiresQueryForServerVersion() - { - return false; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOException.php deleted file mode 100644 index 277d7a6..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOException.php +++ /dev/null @@ -1,52 +0,0 @@ -getMessage(), 0, $exception); - - $this->code = $exception->getCode(); - $this->errorInfo = $exception->errorInfo; - $this->errorCode = $exception->errorInfo[1] ?? $exception->getCode(); - $this->sqlState = $exception->errorInfo[0] ?? $exception->getCode(); - } - - /** - * {@inheritdoc} - */ - public function getErrorCode() - { - return $this->errorCode; - } - - /** - * {@inheritdoc} - */ - public function getSQLState() - { - return $this->sqlState; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php deleted file mode 100644 index 12fb14e..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOIbm/Driver.php +++ /dev/null @@ -1,59 +0,0 @@ -_constructPdoDsn($params), - $username, - $password, - $driverOptions - ); - } - - /** - * Constructs the IBM PDO DSN. - * - * @param mixed[] $params - * - * @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; - } - - /** - * {@inheritdoc} - * - * @deprecated - */ - public function getName() - { - return 'pdo_ibm'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php deleted file mode 100644 index dcd4ff5..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php +++ /dev/null @@ -1,72 +0,0 @@ -constructPdoDsn($params), - $username, - $password, - $driverOptions - ); - } catch (PDOException $e) { - throw DBALException::driverException($this, $e); - } - - return $conn; - } - - /** - * Constructs the MySql PDO DSN. - * - * @param mixed[] $params - * - * @return string The DSN. - */ - protected function constructPdoDsn(array $params) - { - $dsn = 'mysql:'; - if (isset($params['host']) && $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'] . ';'; - } - if (isset($params['charset'])) { - $dsn .= 'charset=' . $params['charset'] . ';'; - } - - return $dsn; - } - - /** - * {@inheritdoc} - * - * @deprecated - */ - public function getName() - { - return 'pdo_mysql'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php deleted file mode 100644 index f1239ea..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOOracle/Driver.php +++ /dev/null @@ -1,62 +0,0 @@ -constructPdoDsn($params), - $username, - $password, - $driverOptions - ); - } catch (PDOException $e) { - throw DBALException::driverException($this, $e); - } - } - - /** - * Constructs the Oracle PDO DSN. - * - * @param mixed[] $params - * - * @return string The DSN. - */ - private function constructPdoDsn(array $params) - { - $dsn = 'oci:dbname=' . $this->getEasyConnectString($params); - - if (isset($params['charset'])) { - $dsn .= ';charset=' . $params['charset']; - } - - return $dsn; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'pdo_oracle'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php deleted file mode 100644 index f25cd5c..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php +++ /dev/null @@ -1,118 +0,0 @@ -_constructPdoDsn($params), - $username, - $password, - $driverOptions - ); - - if (defined('PDO::PGSQL_ATTR_DISABLE_PREPARES') - && (! isset($driverOptions[PDO::PGSQL_ATTR_DISABLE_PREPARES]) - || $driverOptions[PDO::PGSQL_ATTR_DISABLE_PREPARES] === true - ) - ) { - $pdo->setAttribute(PDO::PGSQL_ATTR_DISABLE_PREPARES, true); - } - - /* defining client_encoding via SET NAMES to avoid inconsistent DSN support - * - the 'client_encoding' connection param only works with postgres >= 9.1 - * - passing client_encoding via the 'options' param breaks pgbouncer support - */ - if (isset($params['charset'])) { - $pdo->exec('SET NAMES \'' . $params['charset'] . '\''); - } - - return $pdo; - } catch (PDOException $e) { - throw DBALException::driverException($this, $e); - } - } - - /** - * Constructs the Postgres PDO DSN. - * - * @param mixed[] $params - * - * @return string The DSN. - */ - private function _constructPdoDsn(array $params) - { - $dsn = 'pgsql:'; - - if (isset($params['host']) && $params['host'] !== '') { - $dsn .= 'host=' . $params['host'] . ';'; - } - - if (isset($params['port']) && $params['port'] !== '') { - $dsn .= 'port=' . $params['port'] . ';'; - } - - if (isset($params['dbname'])) { - $dsn .= 'dbname=' . $params['dbname'] . ';'; - } elseif (isset($params['default_dbname'])) { - $dsn .= 'dbname=' . $params['default_dbname'] . ';'; - } else { - // Used for temporary connections to allow operations like dropping the database currently connected to. - // Connecting without an explicit database does not work, therefore "postgres" database is used - // as it is mostly present in every server setup. - $dsn .= 'dbname=postgres;'; - } - - if (isset($params['sslmode'])) { - $dsn .= 'sslmode=' . $params['sslmode'] . ';'; - } - - if (isset($params['sslrootcert'])) { - $dsn .= 'sslrootcert=' . $params['sslrootcert'] . ';'; - } - - if (isset($params['sslcert'])) { - $dsn .= 'sslcert=' . $params['sslcert'] . ';'; - } - - if (isset($params['sslkey'])) { - $dsn .= 'sslkey=' . $params['sslkey'] . ';'; - } - - if (isset($params['sslcrl'])) { - $dsn .= 'sslcrl=' . $params['sslcrl'] . ';'; - } - - if (isset($params['application_name'])) { - $dsn .= 'application_name=' . $params['application_name'] . ';'; - } - - return $dsn; - } - - /** - * {@inheritdoc} - * - * @deprecated - */ - public function getName() - { - return 'pdo_pgsql'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php deleted file mode 100644 index d08c6a2..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlite/Driver.php +++ /dev/null @@ -1,83 +0,0 @@ - ['callback' => [SqlitePlatform::class, 'udfSqrt'], 'numArgs' => 1], - 'mod' => ['callback' => [SqlitePlatform::class, 'udfMod'], 'numArgs' => 2], - 'locate' => ['callback' => [SqlitePlatform::class, 'udfLocate'], 'numArgs' => -1], - ]; - - /** - * {@inheritdoc} - */ - public function connect(array $params, $username = null, $password = null, array $driverOptions = []) - { - if (isset($driverOptions['userDefinedFunctions'])) { - $this->_userDefinedFunctions = array_merge( - $this->_userDefinedFunctions, - $driverOptions['userDefinedFunctions'] - ); - unset($driverOptions['userDefinedFunctions']); - } - - try { - $pdo = new PDOConnection( - $this->_constructPdoDsn($params), - $username, - $password, - $driverOptions - ); - } catch (PDOException $ex) { - throw DBALException::driverException($this, $ex); - } - - foreach ($this->_userDefinedFunctions as $fn => $data) { - $pdo->sqliteCreateFunction($fn, $data['callback'], $data['numArgs']); - } - - return $pdo; - } - - /** - * Constructs the Sqlite PDO DSN. - * - * @param mixed[] $params - * - * @return string The DSN. - */ - protected function _constructPdoDsn(array $params) - { - $dsn = 'sqlite:'; - if (isset($params['path'])) { - $dsn .= $params['path']; - } elseif (isset($params['memory'])) { - $dsn .= ':memory:'; - } - - return $dsn; - } - - /** - * {@inheritdoc} - * - * @deprecated - */ - public function getName() - { - return 'pdo_sqlite'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php deleted file mode 100644 index bd38944..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php +++ /dev/null @@ -1,54 +0,0 @@ -setAttribute(PDO::ATTR_STATEMENT_CLASS, [Statement::class, []]); - } - - /** - * {@inheritDoc} - */ - public function lastInsertId($name = null) - { - if ($name === null) { - return parent::lastInsertId($name); - } - - $stmt = $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?'); - $stmt->execute([$name]); - - return $stmt->fetchColumn(); - } - - /** - * {@inheritDoc} - */ - public function quote($value, $type = ParameterType::STRING) - { - $val = parent::quote($value, $type); - - // Fix for a driver version terminating all values with null byte - if (strpos($val, "\0") !== false) { - $val = substr($val, 0, -1); - } - - return $val; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php deleted file mode 100644 index 6d6c484..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php +++ /dev/null @@ -1,93 +0,0 @@ - $value) { - if (is_int($option)) { - $pdoOptions[$option] = $value; - } else { - $dsnOptions[$option] = $value; - } - } - - return new Connection( - $this->_constructPdoDsn($params, $dsnOptions), - $username, - $password, - $pdoOptions - ); - } - - /** - * Constructs the Sqlsrv PDO DSN. - * - * @param mixed[] $params - * @param string[] $connectionOptions - * - * @return string The DSN. - */ - private function _constructPdoDsn(array $params, array $connectionOptions) - { - $dsn = 'sqlsrv:server='; - - if (isset($params['host'])) { - $dsn .= $params['host']; - } - - if (isset($params['port']) && ! empty($params['port'])) { - $dsn .= ',' . $params['port']; - } - - if (isset($params['dbname'])) { - $connectionOptions['Database'] = $params['dbname']; - } - - if (isset($params['MultipleActiveResultSets'])) { - $connectionOptions['MultipleActiveResultSets'] = $params['MultipleActiveResultSets'] ? 'true' : 'false'; - } - - return $dsn . $this->getConnectionOptionsDsn($connectionOptions); - } - - /** - * Converts a connection options array to the DSN - * - * @param string[] $connectionOptions - */ - private function getConnectionOptionsDsn(array $connectionOptions) : string - { - $connectionOptionsDsn = ''; - - foreach ($connectionOptions as $paramName => $paramValue) { - $connectionOptionsDsn .= sprintf(';%s=%s', $paramName, $paramValue); - } - - return $connectionOptionsDsn; - } - - /** - * {@inheritdoc} - * - * @deprecated - */ - public function getName() - { - return 'pdo_sqlsrv'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php deleted file mode 100644 index 6803bb1..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php +++ /dev/null @@ -1,35 +0,0 @@ -bindParam($param, $value, $type); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php deleted file mode 100644 index 5be4f2c..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php +++ /dev/null @@ -1,228 +0,0 @@ - PDO::PARAM_NULL, - ParameterType::INTEGER => PDO::PARAM_INT, - ParameterType::STRING => PDO::PARAM_STR, - ParameterType::BINARY => PDO::PARAM_LOB, - ParameterType::LARGE_OBJECT => PDO::PARAM_LOB, - ParameterType::BOOLEAN => PDO::PARAM_BOOL, - ]; - - private const FETCH_MODE_MAP = [ - FetchMode::ASSOCIATIVE => PDO::FETCH_ASSOC, - FetchMode::NUMERIC => PDO::FETCH_NUM, - FetchMode::MIXED => PDO::FETCH_BOTH, - FetchMode::STANDARD_OBJECT => PDO::FETCH_OBJ, - FetchMode::COLUMN => PDO::FETCH_COLUMN, - FetchMode::CUSTOM_OBJECT => PDO::FETCH_CLASS, - ]; - - /** - * Protected constructor. - */ - protected function __construct() - { - } - - /** - * {@inheritdoc} - */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) - { - $fetchMode = $this->convertFetchMode($fetchMode); - - // This thin wrapper is necessary to shield against the weird signature - // of PDOStatement::setFetchMode(): even if the second and third - // parameters are optional, PHP will not let us remove it from this - // declaration. - try { - if ($arg2 === null && $arg3 === null) { - return parent::setFetchMode($fetchMode); - } - - if ($arg3 === null) { - return parent::setFetchMode($fetchMode, $arg2); - } - - return parent::setFetchMode($fetchMode, $arg2, $arg3); - } catch (\PDOException $exception) { - throw new PDOException($exception); - } - } - - /** - * {@inheritdoc} - */ - public function bindValue($param, $value, $type = ParameterType::STRING) - { - $type = $this->convertParamType($type); - - try { - return parent::bindValue($param, $value, $type); - } catch (\PDOException $exception) { - throw new PDOException($exception); - } - } - - /** - * {@inheritdoc} - */ - public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null, $driverOptions = null) - { - $type = $this->convertParamType($type); - - try { - return parent::bindParam($column, $variable, $type, ...array_slice(func_get_args(), 3)); - } catch (\PDOException $exception) { - throw new PDOException($exception); - } - } - - /** - * {@inheritdoc} - */ - public function closeCursor() - { - try { - return parent::closeCursor(); - } catch (\PDOException $exception) { - // Exceptions not allowed by the interface. - // In case driver implementations do not adhere to the interface, silence exceptions here. - return true; - } - } - - /** - * {@inheritdoc} - */ - public function execute($params = null) - { - try { - return parent::execute($params); - } catch (\PDOException $exception) { - throw new PDOException($exception); - } - } - - /** - * {@inheritdoc} - */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) - { - $args = func_get_args(); - - if (isset($args[0])) { - $args[0] = $this->convertFetchMode($args[0]); - } - - try { - return parent::fetch(...$args); - } catch (\PDOException $exception) { - throw new PDOException($exception); - } - } - - /** - * {@inheritdoc} - */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) - { - $args = func_get_args(); - - if (isset($args[0])) { - $args[0] = $this->convertFetchMode($args[0]); - } - - if ($fetchMode === null && $fetchArgument === null && $ctorArgs === null) { - $args = []; - } elseif ($fetchArgument === null && $ctorArgs === null) { - $args = [$fetchMode]; - } elseif ($ctorArgs === null) { - $args = [$fetchMode, $fetchArgument]; - } else { - $args = [$fetchMode, $fetchArgument, $ctorArgs]; - } - - try { - $data = parent::fetchAll(...$args); - assert(is_array($data)); - - return $data; - } catch (\PDOException $exception) { - throw new PDOException($exception); - } - } - - /** - * {@inheritdoc} - */ - public function fetchColumn($columnIndex = 0) - { - try { - return parent::fetchColumn($columnIndex); - } catch (\PDOException $exception) { - throw new PDOException($exception); - } - } - - /** - * Converts DBAL parameter type to PDO parameter type - * - * @param int $type Parameter type - */ - private function convertParamType(int $type) : int - { - if (! isset(self::PARAM_TYPE_MAP[$type])) { - // TODO: next major: throw an exception - @trigger_error(sprintf( - 'Using a PDO parameter type (%d given) is deprecated and will cause an error in Doctrine 3.0', - $type - ), E_USER_DEPRECATED); - - return $type; - } - - return self::PARAM_TYPE_MAP[$type]; - } - - /** - * Converts DBAL fetch mode to PDO fetch mode - * - * @param int $fetchMode Fetch mode - */ - private function convertFetchMode(int $fetchMode) : int - { - if (! isset(self::FETCH_MODE_MAP[$fetchMode])) { - // TODO: next major: throw an exception - @trigger_error(sprintf( - 'Using a PDO fetch mode or their combination (%d given)' . - ' is deprecated and will cause an error in Doctrine 3.0', - $fetchMode - ), E_USER_DEPRECATED); - - return $fetchMode; - } - - return self::FETCH_MODE_MAP[$fetchMode]; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PingableConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PingableConnection.php deleted file mode 100644 index 06bfb9a..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PingableConnection.php +++ /dev/null @@ -1,17 +0,0 @@ -buildDsn( - $params['host'] ?? null, - $params['port'] ?? null, - $params['server'] ?? null, - $params['dbname'] ?? null, - $username, - $password, - $driverOptions - ), - $params['persistent'] ?? false - ); - } catch (SQLAnywhereException $e) { - throw DBALException::driverException($this, $e); - } - } - - /** - * {@inheritdoc} - * - * @deprecated - */ - public function getName() - { - return 'sqlanywhere'; - } - - /** - * Build the connection string for given connection parameters and driver options. - * - * @param string $host Host address to connect to. - * @param int $port Port to use for the connection (default to SQL Anywhere standard port 2638). - * @param string $server Database server name on the host to connect to. - * SQL Anywhere allows multiple database server instances on the same host, - * therefore specifying the server instance name to use is mandatory. - * @param string $dbname Name of the database on the server instance to connect to. - * @param string $username User name to use for connection authentication. - * @param string $password Password to use for connection authentication. - * @param mixed[] $driverOptions Additional parameters to use for the connection. - * - * @return string - */ - private function buildDsn($host, $port, $server, $dbname, $username = null, $password = null, array $driverOptions = []) - { - $host = $host ?: 'localhost'; - $port = $port ?: 2638; - - if (! empty($server)) { - $server = ';ServerName=' . $server; - } - - return 'HOST=' . $host . ':' . $port . - $server . - ';DBN=' . $dbname . - ';UID=' . $username . - ';PWD=' . $password . - ';' . implode( - ';', - array_map(static function ($key, $value) { - return $key . '=' . $value; - }, array_keys($driverOptions), $driverOptions) - ); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php deleted file mode 100644 index d477820..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereConnection.php +++ /dev/null @@ -1,215 +0,0 @@ -connection = $persistent ? @sasql_pconnect($dsn) : @sasql_connect($dsn); - - if (! is_resource($this->connection)) { - throw SQLAnywhereException::fromSQLAnywhereError(); - } - - // Disable PHP warnings on error. - if (! sasql_set_option($this->connection, 'verbose_errors', false)) { - throw SQLAnywhereException::fromSQLAnywhereError($this->connection); - } - - // Enable auto committing by default. - if (! sasql_set_option($this->connection, 'auto_commit', 'on')) { - throw SQLAnywhereException::fromSQLAnywhereError($this->connection); - } - } - - /** - * {@inheritdoc} - * - * @throws SQLAnywhereException - */ - public function beginTransaction() - { - if (! sasql_set_option($this->connection, 'auto_commit', 'off')) { - throw SQLAnywhereException::fromSQLAnywhereError($this->connection); - } - - return true; - } - - /** - * {@inheritdoc} - * - * @throws SQLAnywhereException - */ - public function commit() - { - if (! sasql_commit($this->connection)) { - throw SQLAnywhereException::fromSQLAnywhereError($this->connection); - } - - $this->endTransaction(); - - return true; - } - - /** - * {@inheritdoc} - */ - public function errorCode() - { - return sasql_errorcode($this->connection); - } - - /** - * {@inheritdoc} - */ - public function errorInfo() - { - return sasql_error($this->connection); - } - - /** - * {@inheritdoc} - */ - public function exec($statement) - { - if (sasql_real_query($this->connection, $statement) === false) { - throw SQLAnywhereException::fromSQLAnywhereError($this->connection); - } - - return sasql_affected_rows($this->connection); - } - - /** - * {@inheritdoc} - */ - public function getServerVersion() - { - $version = $this->query("SELECT PROPERTY('ProductVersion')")->fetchColumn(); - - assert(is_string($version)); - - return $version; - } - - /** - * {@inheritdoc} - */ - public function lastInsertId($name = null) - { - if ($name === null) { - return sasql_insert_id($this->connection); - } - - return $this->query('SELECT ' . $name . '.CURRVAL')->fetchColumn(); - } - - /** - * {@inheritdoc} - */ - public function prepare($prepareString) - { - return new SQLAnywhereStatement($this->connection, $prepareString); - } - - /** - * {@inheritdoc} - */ - public function query() - { - $args = func_get_args(); - $stmt = $this->prepare($args[0]); - - $stmt->execute(); - - return $stmt; - } - - /** - * {@inheritdoc} - */ - public function quote($input, $type = ParameterType::STRING) - { - if (is_int($input) || is_float($input)) { - return $input; - } - - return "'" . sasql_escape_string($this->connection, $input) . "'"; - } - - /** - * {@inheritdoc} - */ - public function requiresQueryForServerVersion() - { - return true; - } - - /** - * {@inheritdoc} - * - * @throws SQLAnywhereException - */ - public function rollBack() - { - if (! sasql_rollback($this->connection)) { - throw SQLAnywhereException::fromSQLAnywhereError($this->connection); - } - - $this->endTransaction(); - - return true; - } - - /** - * Ends transactional mode and enables auto commit again. - * - * @return bool Whether or not ending transactional mode succeeded. - * - * @throws SQLAnywhereException - */ - private function endTransaction() - { - if (! sasql_set_option($this->connection, 'auto_commit', 'on')) { - throw SQLAnywhereException::fromSQLAnywhereError($this->connection); - } - - return true; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereException.php deleted file mode 100644 index 0f8bc3e..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereException.php +++ /dev/null @@ -1,71 +0,0 @@ -conn = $conn; - $this->stmt = sasql_prepare($conn, $sql); - - if (! is_resource($this->stmt)) { - throw SQLAnywhereException::fromSQLAnywhereError($conn); - } - } - - /** - * {@inheritdoc} - * - * @throws SQLAnywhereException - */ - public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null) - { - switch ($type) { - case ParameterType::INTEGER: - case ParameterType::BOOLEAN: - $type = 'i'; - break; - - case ParameterType::LARGE_OBJECT: - $type = 'b'; - break; - - case ParameterType::NULL: - case ParameterType::STRING: - case ParameterType::BINARY: - $type = 's'; - break; - - default: - throw new SQLAnywhereException('Unknown type: ' . $type); - } - - $this->boundValues[$column] =& $variable; - - if (! sasql_stmt_bind_param_ex($this->stmt, $column - 1, $variable, $type, $variable === null)) { - throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt); - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function bindValue($param, $value, $type = ParameterType::STRING) - { - return $this->bindParam($param, $value, $type); - } - - /** - * {@inheritdoc} - * - * @throws SQLAnywhereException - */ - public function closeCursor() - { - if (! sasql_stmt_reset($this->stmt)) { - throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt); - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function columnCount() - { - return sasql_stmt_field_count($this->stmt); - } - - /** - * {@inheritdoc} - */ - public function errorCode() - { - return sasql_stmt_errno($this->stmt); - } - - /** - * {@inheritdoc} - */ - public function errorInfo() - { - return sasql_stmt_error($this->stmt); - } - - /** - * {@inheritdoc} - * - * @throws SQLAnywhereException - */ - public function execute($params = null) - { - if (is_array($params)) { - $hasZeroIndex = array_key_exists(0, $params); - - foreach ($params as $key => $val) { - if ($hasZeroIndex && is_int($key)) { - $this->bindValue($key + 1, $val); - } else { - $this->bindValue($key, $val); - } - } - } - - if (! sasql_stmt_execute($this->stmt)) { - throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt); - } - - $this->result = sasql_stmt_result_metadata($this->stmt); - - return true; - } - - /** - * {@inheritdoc} - * - * @throws SQLAnywhereException - */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) - { - if (! is_resource($this->result)) { - return false; - } - - $fetchMode = $fetchMode ?: $this->defaultFetchMode; - - switch ($fetchMode) { - case FetchMode::COLUMN: - return $this->fetchColumn(); - - case FetchMode::ASSOCIATIVE: - return sasql_fetch_assoc($this->result); - - case FetchMode::MIXED: - return sasql_fetch_array($this->result, SASQL_BOTH); - - case FetchMode::CUSTOM_OBJECT: - $className = $this->defaultFetchClass; - $ctorArgs = $this->defaultFetchClassCtorArgs; - - if (func_num_args() >= 2) { - $args = func_get_args(); - $className = $args[1]; - $ctorArgs = $args[2] ?? []; - } - - $result = sasql_fetch_object($this->result); - - if ($result instanceof stdClass) { - $result = $this->castObject($result, $className, $ctorArgs); - } - - return $result; - - case FetchMode::NUMERIC: - return sasql_fetch_row($this->result); - - case FetchMode::STANDARD_OBJECT: - return sasql_fetch_object($this->result); - - default: - throw new SQLAnywhereException('Fetch mode is not supported: ' . $fetchMode); - } - } - - /** - * {@inheritdoc} - */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) - { - $rows = []; - - switch ($fetchMode) { - case FetchMode::CUSTOM_OBJECT: - while (($row = $this->fetch(...func_get_args())) !== false) { - $rows[] = $row; - } - break; - - case FetchMode::COLUMN: - while (($row = $this->fetchColumn()) !== false) { - $rows[] = $row; - } - break; - - default: - while (($row = $this->fetch($fetchMode)) !== false) { - $rows[] = $row; - } - } - - return $rows; - } - - /** - * {@inheritdoc} - */ - public function fetchColumn($columnIndex = 0) - { - $row = $this->fetch(FetchMode::NUMERIC); - - if ($row === false) { - return false; - } - - return $row[$columnIndex] ?? null; - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - return new StatementIterator($this); - } - - /** - * {@inheritdoc} - */ - public function rowCount() - { - return sasql_stmt_affected_rows($this->stmt); - } - - /** - * {@inheritdoc} - */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) - { - $this->defaultFetchMode = $fetchMode; - $this->defaultFetchClass = $arg2 ?: $this->defaultFetchClass; - $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; - } - - /** - * Casts a stdClass object to the given class name mapping its' properties. - * - * @param stdClass $sourceObject Object to cast from. - * @param string|object $destinationClass Name of the class or class instance to cast to. - * @param mixed[] $ctorArgs Arguments to use for constructing the destination class instance. - * - * @return object - * - * @throws SQLAnywhereException - */ - private function castObject(stdClass $sourceObject, $destinationClass, array $ctorArgs = []) - { - if (! is_string($destinationClass)) { - if (! is_object($destinationClass)) { - throw new SQLAnywhereException(sprintf( - 'Destination class has to be of type string or object, %s given.', - gettype($destinationClass) - )); - } - } else { - $destinationClass = new ReflectionClass($destinationClass); - $destinationClass = $destinationClass->newInstanceArgs($ctorArgs); - } - - $sourceReflection = new ReflectionObject($sourceObject); - $destinationClassReflection = new ReflectionObject($destinationClass); - - foreach ($sourceReflection->getProperties() as $sourceProperty) { - $sourceProperty->setAccessible(true); - - $name = $sourceProperty->getName(); - $value = $sourceProperty->getValue($sourceObject); - - if ($destinationClassReflection->hasProperty($name)) { - $destinationProperty = $destinationClassReflection->getProperty($name); - - $destinationProperty->setAccessible(true); - $destinationProperty->setValue($destinationClass, $value); - } else { - $destinationClass->$name = $value; - } - } - - return $destinationClass; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php deleted file mode 100644 index 848ab5e..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/Driver.php +++ /dev/null @@ -1,58 +0,0 @@ -id = $id; - } - - /** - * @return int - */ - public function getId() - { - return $this->id; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php deleted file mode 100644 index 35ad913..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php +++ /dev/null @@ -1,197 +0,0 @@ -conn = $conn; - $this->lastInsertId = new LastInsertId(); - } - - /** - * {@inheritdoc} - */ - public function getServerVersion() - { - $serverInfo = sqlsrv_server_info($this->conn); - - return $serverInfo['SQLServerVersion']; - } - - /** - * {@inheritdoc} - */ - public function requiresQueryForServerVersion() - { - return false; - } - - /** - * {@inheritDoc} - */ - public function prepare($sql) - { - return new SQLSrvStatement($this->conn, $sql, $this->lastInsertId); - } - - /** - * {@inheritDoc} - */ - public function query() - { - $args = func_get_args(); - $sql = $args[0]; - $stmt = $this->prepare($sql); - $stmt->execute(); - - return $stmt; - } - - /** - * {@inheritDoc} - */ - public function quote($value, $type = ParameterType::STRING) - { - if (is_int($value)) { - return $value; - } - - if (is_float($value)) { - return sprintf('%F', $value); - } - - return "'" . str_replace("'", "''", $value) . "'"; - } - - /** - * {@inheritDoc} - */ - public function exec($statement) - { - $stmt = sqlsrv_query($this->conn, $statement); - - if ($stmt === false) { - throw SQLSrvException::fromSqlSrvErrors(); - } - - $rowsAffected = sqlsrv_rows_affected($stmt); - - if ($rowsAffected === false) { - throw SQLSrvException::fromSqlSrvErrors(); - } - - return $rowsAffected; - } - - /** - * {@inheritDoc} - */ - public function lastInsertId($name = null) - { - if ($name !== null) { - $stmt = $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?'); - $stmt->execute([$name]); - } else { - $stmt = $this->query('SELECT @@IDENTITY'); - } - - return $stmt->fetchColumn(); - } - - /** - * {@inheritDoc} - */ - public function beginTransaction() - { - if (! sqlsrv_begin_transaction($this->conn)) { - throw SQLSrvException::fromSqlSrvErrors(); - } - } - - /** - * {@inheritDoc} - */ - public function commit() - { - if (! sqlsrv_commit($this->conn)) { - throw SQLSrvException::fromSqlSrvErrors(); - } - } - - /** - * {@inheritDoc} - */ - public function rollBack() - { - if (! sqlsrv_rollback($this->conn)) { - throw SQLSrvException::fromSqlSrvErrors(); - } - } - - /** - * {@inheritDoc} - */ - public function errorCode() - { - $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); - if ($errors) { - return $errors[0]['code']; - } - - return false; - } - - /** - * {@inheritDoc} - */ - public function errorInfo() - { - return (array) sqlsrv_errors(SQLSRV_ERR_ERRORS); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php deleted file mode 100644 index 1c1e8c4..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php +++ /dev/null @@ -1,43 +0,0 @@ - SQLSRV_FETCH_BOTH, - FetchMode::ASSOCIATIVE => SQLSRV_FETCH_ASSOC, - FetchMode::NUMERIC => SQLSRV_FETCH_NUMERIC, - ]; - - /** - * The name of the default class to instantiate when fetching class instances. - * - * @var string - */ - private $defaultFetchClass = '\stdClass'; - - /** - * The constructor arguments for the default class to instantiate when fetching class instances. - * - * @var mixed[] - */ - private $defaultFetchClassCtorArgs = []; - - /** - * The fetch style. - * - * @var int - */ - private $defaultFetchMode = FetchMode::MIXED; - - /** - * The last insert ID. - * - * @var LastInsertId|null - */ - private $lastInsertId; - - /** - * Indicates whether the statement is in the state when fetching results is possible - * - * @var bool - */ - private $result = false; - - /** - * Append to any INSERT query to retrieve the last insert id. - * - * @deprecated This constant has been deprecated and will be made private in 3.0 - */ - public const LAST_INSERT_ID_SQL = ';SELECT SCOPE_IDENTITY() AS LastInsertId;'; - - /** - * @param resource $conn - * @param string $sql - */ - public function __construct($conn, $sql, ?LastInsertId $lastInsertId = null) - { - $this->conn = $conn; - $this->sql = $sql; - - if (stripos($sql, 'INSERT INTO ') !== 0) { - return; - } - - $this->sql .= self::LAST_INSERT_ID_SQL; - $this->lastInsertId = $lastInsertId; - } - - /** - * {@inheritdoc} - */ - public function bindValue($param, $value, $type = ParameterType::STRING) - { - if (! is_numeric($param)) { - throw new SQLSrvException( - 'sqlsrv does not support named parameters to queries, use question mark (?) placeholders instead.' - ); - } - - $this->variables[$param] = $value; - $this->types[$param] = $type; - } - - /** - * {@inheritdoc} - */ - public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null) - { - if (! is_numeric($column)) { - throw new SQLSrvException('sqlsrv does not support named parameters to queries, use question mark (?) placeholders instead.'); - } - - $this->variables[$column] =& $variable; - $this->types[$column] = $type; - - // unset the statement resource if it exists as the new one will need to be bound to the new variable - $this->stmt = null; - } - - /** - * {@inheritdoc} - */ - public function closeCursor() - { - // not having the result means there's nothing to close - if ($this->stmt === null || ! $this->result) { - return true; - } - - // emulate it by fetching and discarding rows, similarly to what PDO does in this case - // @link http://php.net/manual/en/pdostatement.closecursor.php - // @link https://github.com/php/php-src/blob/php-7.0.11/ext/pdo/pdo_stmt.c#L2075 - // deliberately do not consider multiple result sets, since doctrine/dbal doesn't support them - while (sqlsrv_fetch($this->stmt)) { - } - - $this->result = false; - - return true; - } - - /** - * {@inheritdoc} - */ - public function columnCount() - { - if ($this->stmt === null) { - return 0; - } - - return sqlsrv_num_fields($this->stmt) ?: 0; - } - - /** - * {@inheritdoc} - */ - public function errorCode() - { - $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); - if ($errors) { - return $errors[0]['code']; - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function errorInfo() - { - return (array) sqlsrv_errors(SQLSRV_ERR_ERRORS); - } - - /** - * {@inheritdoc} - */ - public function execute($params = null) - { - if ($params) { - $hasZeroIndex = array_key_exists(0, $params); - - foreach ($params as $key => $val) { - if ($hasZeroIndex && is_int($key)) { - $this->bindValue($key + 1, $val); - } else { - $this->bindValue($key, $val); - } - } - } - - if (! $this->stmt) { - $this->stmt = $this->prepare(); - } - - if (! sqlsrv_execute($this->stmt)) { - throw SQLSrvException::fromSqlSrvErrors(); - } - - if ($this->lastInsertId) { - sqlsrv_next_result($this->stmt); - sqlsrv_fetch($this->stmt); - $this->lastInsertId->setId(sqlsrv_get_field($this->stmt, 0)); - } - - $this->result = true; - } - - /** - * Prepares SQL Server statement resource - * - * @return resource - * - * @throws SQLSrvException - */ - private function prepare() - { - $params = []; - - foreach ($this->variables as $column => &$variable) { - switch ($this->types[$column]) { - case ParameterType::LARGE_OBJECT: - $params[$column - 1] = [ - &$variable, - SQLSRV_PARAM_IN, - SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY), - SQLSRV_SQLTYPE_VARBINARY('max'), - ]; - break; - - case ParameterType::BINARY: - $params[$column - 1] = [ - &$variable, - SQLSRV_PARAM_IN, - SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY), - ]; - break; - - default: - $params[$column - 1] =& $variable; - break; - } - } - - $stmt = sqlsrv_prepare($this->conn, $this->sql, $params); - - if (! $stmt) { - throw SQLSrvException::fromSqlSrvErrors(); - } - - return $stmt; - } - - /** - * {@inheritdoc} - */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) - { - $this->defaultFetchMode = $fetchMode; - $this->defaultFetchClass = $arg2 ?: $this->defaultFetchClass; - $this->defaultFetchClassCtorArgs = $arg3 ? (array) $arg3 : $this->defaultFetchClassCtorArgs; - - return true; - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - return new StatementIterator($this); - } - - /** - * {@inheritdoc} - * - * @throws SQLSrvException - */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) - { - // do not try fetching from the statement if it's not expected to contain result - // in order to prevent exceptional situation - if ($this->stmt === null || ! $this->result) { - return false; - } - - $args = func_get_args(); - $fetchMode = $fetchMode ?: $this->defaultFetchMode; - - if ($fetchMode === FetchMode::COLUMN) { - return $this->fetchColumn(); - } - - if (isset(self::$fetchMap[$fetchMode])) { - return sqlsrv_fetch_array($this->stmt, self::$fetchMap[$fetchMode]) ?: false; - } - - if (in_array($fetchMode, [FetchMode::STANDARD_OBJECT, FetchMode::CUSTOM_OBJECT], true)) { - $className = $this->defaultFetchClass; - $ctorArgs = $this->defaultFetchClassCtorArgs; - - if (count($args) >= 2) { - $className = $args[1]; - $ctorArgs = $args[2] ?? []; - } - - return sqlsrv_fetch_object($this->stmt, $className, $ctorArgs) ?: false; - } - - throw new SQLSrvException('Fetch mode is not supported!'); - } - - /** - * {@inheritdoc} - */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) - { - $rows = []; - - switch ($fetchMode) { - case FetchMode::CUSTOM_OBJECT: - while (($row = $this->fetch(...func_get_args())) !== false) { - $rows[] = $row; - } - break; - - case FetchMode::COLUMN: - while (($row = $this->fetchColumn()) !== false) { - $rows[] = $row; - } - break; - - default: - while (($row = $this->fetch($fetchMode)) !== false) { - $rows[] = $row; - } - } - - return $rows; - } - - /** - * {@inheritdoc} - */ - public function fetchColumn($columnIndex = 0) - { - $row = $this->fetch(FetchMode::NUMERIC); - - if ($row === false) { - return false; - } - - return $row[$columnIndex] ?? null; - } - - /** - * {@inheritdoc} - */ - public function rowCount() - { - if ($this->stmt === null) { - return 0; - } - - return sqlsrv_rows_affected($this->stmt) ?: 0; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ServerInfoAwareConnection.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ServerInfoAwareConnection.php deleted file mode 100644 index c97a60f..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/ServerInfoAwareConnection.php +++ /dev/null @@ -1,23 +0,0 @@ -bindValue(), - * the variable is bound as a reference and will only be evaluated at the time - * that PDOStatement->execute() is called. - * - * As mentioned above, the named parameters are not natively supported by the mysqli driver, use executeQuery(), - * fetchAll(), fetchArray(), fetchColumn(), fetchAssoc() methods to have the named parameter emulated by doctrine. - * - * 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 $column 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 int $type Explicit data type for the parameter using the {@link \Doctrine\DBAL\ParameterType} - * 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. - * @param int|null $length You must specify maxlength when using an OUT bind - * so that PHP allocates enough memory to hold the returned value. - * - * @return bool TRUE on success or FALSE on failure. - */ - public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null); - - /** - * Fetches the SQLSTATE associated with the last operation on the statement handle. - * - * @see Doctrine_Adapter_Interface::errorCode() - * - * @return string|int|bool The error code string. - */ - public function errorCode(); - - /** - * Fetches extended error information associated with the last operation on the statement handle. - * - * @return mixed[] The error info array. - */ - public 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 mixed[]|null $params An array of values with as many elements as there are - * bound parameters in the SQL statement being executed. - * - * @return bool TRUE on success or FALSE on failure. - */ - public function execute($params = null); - - /** - * 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 int The number of rows. - */ - public function rowCount(); -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/StatementIterator.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/StatementIterator.php deleted file mode 100644 index 6b3307d..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/StatementIterator.php +++ /dev/null @@ -1,26 +0,0 @@ -statement = $statement; - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - while (($result = $this->statement->fetch()) !== false) { - yield $result; - } - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/DriverManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/DriverManager.php deleted file mode 100644 index 6888d73..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/DriverManager.php +++ /dev/null @@ -1,442 +0,0 @@ - PDOMySQLDriver::class, - 'pdo_sqlite' => PDOSQLiteDriver::class, - 'pdo_pgsql' => PDOPgSQLDriver::class, - 'pdo_oci' => PDOOCIDriver::class, - 'oci8' => OCI8Driver::class, - 'ibm_db2' => DB2Driver::class, - 'pdo_sqlsrv' => PDOSQLSrvDriver::class, - 'mysqli' => MySQLiDriver::class, - 'drizzle_pdo_mysql' => DrizzlePDOMySQLDriver::class, - 'sqlanywhere' => SQLAnywhereDriver::class, - 'sqlsrv' => SQLSrvDriver::class, - ]; - - /** - * List of URL schemes from a database URL and their mappings to driver. - * - * @var string[] - */ - private static $driverSchemeAliases = [ - 'db2' => 'ibm_db2', - 'mssql' => 'pdo_sqlsrv', - 'mysql' => 'pdo_mysql', - 'mysql2' => 'pdo_mysql', // Amazon RDS, for some weird reason - 'postgres' => 'pdo_pgsql', - 'postgresql' => 'pdo_pgsql', - 'pgsql' => 'pdo_pgsql', - 'sqlite' => 'pdo_sqlite', - 'sqlite3' => 'pdo_sqlite', - ]; - - /** - * 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_oci (unstable) - * pdo_sqlsrv - * pdo_sqlsrv - * mysqli - * sqlanywhere - * sqlsrv - * ibm_db2 (unstable) - * drizzle_pdo_mysql - * - * OR 'driverClass' that contains the full class name (with namespace) of the - * driver class to instantiate. - * - * Other (optional) parameters: - * - * user (string): - * The username to use when connecting. - * - * password (string): - * The password to use when connecting. - * - * driverOptions (array): - * Any additional driver-specific options for the driver. These are just passed - * through to the driver. - * - * pdo: - * You can pass an existing PDO instance through this parameter. The PDO - * instance will be wrapped in a Doctrine\DBAL\Connection. - * - * wrapperClass: - * You may specify a custom wrapper class through the 'wrapperClass' - * parameter but this class MUST inherit from Doctrine\DBAL\Connection. - * - * driverClass: - * The driver class to use. - * - * @param mixed[] $params The parameters. - * @param Configuration|null $config The configuration to use. - * @param EventManager|null $eventManager The event manager to use. - * - * @throws DBALException - */ - public static function getConnection( - array $params, - ?Configuration $config = null, - ?EventManager $eventManager = null - ) : Connection { - // create default config and event manager, if not set - if (! $config) { - $config = new Configuration(); - } - if (! $eventManager) { - $eventManager = new EventManager(); - } - - $params = self::parseDatabaseUrl($params); - - // URL support for MasterSlaveConnection - if (isset($params['master'])) { - $params['master'] = self::parseDatabaseUrl($params['master']); - } - - if (isset($params['slaves'])) { - foreach ($params['slaves'] as $key => $slaveParams) { - $params['slaves'][$key] = self::parseDatabaseUrl($slaveParams); - } - } - - // URL support for PoolingShardConnection - if (isset($params['global'])) { - $params['global'] = self::parseDatabaseUrl($params['global']); - } - - if (isset($params['shards'])) { - foreach ($params['shards'] as $key => $shardParams) { - $params['shards'][$key] = self::parseDatabaseUrl($shardParams); - } - } - - // check for existing pdo object - if (isset($params['pdo']) && ! $params['pdo'] instanceof PDO) { - throw DBALException::invalidPdoInstance(); - } - - 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); - } - - $className = $params['driverClass'] ?? self::$_driverMap[$params['driver']]; - - $driver = new $className(); - - $wrapperClass = Connection::class; - if (isset($params['wrapperClass'])) { - if (! is_subclass_of($params['wrapperClass'], $wrapperClass)) { - throw DBALException::invalidWrapperClass($params['wrapperClass']); - } - - $wrapperClass = $params['wrapperClass']; - } - - return new $wrapperClass($params, $driver, $config, $eventManager); - } - - /** - * Returns the list of supported drivers. - * - * @return string[] - */ - public static function getAvailableDrivers() : array - { - return array_keys(self::$_driverMap); - } - - /** - * Checks the list of parameters. - * - * @param mixed[] $params The list of parameters. - * - * @throws DBALException - */ - private static function _checkParams(array $params) : void - { - // check existence 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(Driver::class, class_implements($params['driverClass'], true))) { - throw DBALException::invalidDriverClass($params['driverClass']); - } - } - - /** - * Normalizes the given connection URL path. - * - * @return string The normalized connection URL path - */ - private static function normalizeDatabaseUrlPath(string $urlPath) : string - { - // Trim leading slash from URL path. - return substr($urlPath, 1); - } - - /** - * Extracts parts from a database URL, if present, and returns an - * updated list of parameters. - * - * @param mixed[] $params The list of parameters. - * - * @return mixed[] A modified list of parameters with info from a database - * URL extracted into indidivual parameter parts. - * - * @throws DBALException - */ - private static function parseDatabaseUrl(array $params) : array - { - if (! isset($params['url'])) { - return $params; - } - - // (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid - $url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $params['url']); - assert(is_string($url)); - - $url = parse_url($url); - - if ($url === false) { - throw new DBALException('Malformed parameter "url".'); - } - - $url = array_map('rawurldecode', $url); - - // If we have a connection URL, we have to unset the default PDO instance connection parameter (if any) - // as we cannot merge connection details from the URL into the PDO instance (URL takes precedence). - unset($params['pdo']); - - $params = self::parseDatabaseUrlScheme($url, $params); - - if (isset($url['host'])) { - $params['host'] = $url['host']; - } - if (isset($url['port'])) { - $params['port'] = $url['port']; - } - if (isset($url['user'])) { - $params['user'] = $url['user']; - } - if (isset($url['pass'])) { - $params['password'] = $url['pass']; - } - - $params = self::parseDatabaseUrlPath($url, $params); - $params = self::parseDatabaseUrlQuery($url, $params); - - return $params; - } - - /** - * Parses the given connection URL and resolves the given connection parameters. - * - * Assumes that the connection URL scheme is already parsed and resolved into the given connection parameters - * via {@link parseDatabaseUrlScheme}. - * - * @see parseDatabaseUrlScheme - * - * @param mixed[] $url The URL parts to evaluate. - * @param mixed[] $params The connection parameters to resolve. - * - * @return mixed[] The resolved connection parameters. - */ - private static function parseDatabaseUrlPath(array $url, array $params) : array - { - if (! isset($url['path'])) { - return $params; - } - - $url['path'] = self::normalizeDatabaseUrlPath($url['path']); - - // If we do not have a known DBAL driver, we do not know any connection URL path semantics to evaluate - // and therefore treat the path as regular DBAL connection URL path. - if (! isset($params['driver'])) { - return self::parseRegularDatabaseUrlPath($url, $params); - } - - if (strpos($params['driver'], 'sqlite') !== false) { - return self::parseSqliteDatabaseUrlPath($url, $params); - } - - return self::parseRegularDatabaseUrlPath($url, $params); - } - - /** - * Parses the query part of the given connection URL and resolves the given connection parameters. - * - * @param mixed[] $url The connection URL parts to evaluate. - * @param mixed[] $params The connection parameters to resolve. - * - * @return mixed[] The resolved connection parameters. - */ - private static function parseDatabaseUrlQuery(array $url, array $params) : array - { - if (! isset($url['query'])) { - return $params; - } - - $query = []; - - parse_str($url['query'], $query); // simply ingest query as extra params, e.g. charset or sslmode - - return array_merge($params, $query); // parse_str wipes existing array elements - } - - /** - * Parses the given regular connection URL and resolves the given connection parameters. - * - * Assumes that the "path" URL part is already normalized via {@link normalizeDatabaseUrlPath}. - * - * @see normalizeDatabaseUrlPath - * - * @param mixed[] $url The regular connection URL parts to evaluate. - * @param mixed[] $params The connection parameters to resolve. - * - * @return mixed[] The resolved connection parameters. - */ - private static function parseRegularDatabaseUrlPath(array $url, array $params) : array - { - $params['dbname'] = $url['path']; - - return $params; - } - - /** - * Parses the given SQLite connection URL and resolves the given connection parameters. - * - * Assumes that the "path" URL part is already normalized via {@link normalizeDatabaseUrlPath}. - * - * @see normalizeDatabaseUrlPath - * - * @param mixed[] $url The SQLite connection URL parts to evaluate. - * @param mixed[] $params The connection parameters to resolve. - * - * @return mixed[] The resolved connection parameters. - */ - private static function parseSqliteDatabaseUrlPath(array $url, array $params) : array - { - if ($url['path'] === ':memory:') { - $params['memory'] = true; - - return $params; - } - - $params['path'] = $url['path']; // pdo_sqlite driver uses 'path' instead of 'dbname' key - - return $params; - } - - /** - * Parses the scheme part from given connection URL and resolves the given connection parameters. - * - * @param mixed[] $url The connection URL parts to evaluate. - * @param mixed[] $params The connection parameters to resolve. - * - * @return mixed[] The resolved connection parameters. - * - * @throws DBALException If parsing failed or resolution is not possible. - */ - private static function parseDatabaseUrlScheme(array $url, array $params) : array - { - if (isset($url['scheme'])) { - // The requested driver from the URL scheme takes precedence - // over the default custom driver from the connection parameters (if any). - unset($params['driverClass']); - - // URL schemes must not contain underscores, but dashes are ok - $driver = str_replace('-', '_', $url['scheme']); - assert(is_string($driver)); - - // The requested driver from the URL scheme takes precedence over the - // default driver from the connection parameters. If the driver is - // an alias (e.g. "postgres"), map it to the actual name ("pdo-pgsql"). - // Otherwise, let checkParams decide later if the driver exists. - $params['driver'] = self::$driverSchemeAliases[$driver] ?? $driver; - - return $params; - } - - // If a schemeless connection URL is given, we require a default driver or default custom driver - // as connection parameter. - if (! isset($params['driverClass']) && ! isset($params['driver'])) { - throw DBALException::driverRequired($params['url']); - } - - return $params; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/ConnectionEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/ConnectionEventArgs.php deleted file mode 100644 index 5c71992..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/ConnectionEventArgs.php +++ /dev/null @@ -1,61 +0,0 @@ -connection = $connection; - } - - /** - * @return Connection - */ - public function getConnection() - { - return $this->connection; - } - - /** - * @deprecated Use ConnectionEventArgs::getConnection() and Connection::getDriver() instead. - * - * @return Driver - */ - public function getDriver() - { - return $this->connection->getDriver(); - } - - /** - * @deprecated Use ConnectionEventArgs::getConnection() and Connection::getDatabasePlatform() instead. - * - * @return AbstractPlatform - */ - public function getDatabasePlatform() - { - return $this->connection->getDatabasePlatform(); - } - - /** - * @deprecated Use ConnectionEventArgs::getConnection() and Connection::getSchemaManager() instead. - * - * @return AbstractSchemaManager - */ - public function getSchemaManager() - { - return $this->connection->getSchemaManager(); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php deleted file mode 100644 index 9e72290..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php +++ /dev/null @@ -1,58 +0,0 @@ -charset = $charset; - $this->collation = $collation; - } - - /** - * @return void - */ - public function postConnect(ConnectionEventArgs $args) - { - $collation = $this->collation ? ' COLLATE ' . $this->collation : ''; - $args->getConnection()->executeUpdate('SET NAMES ' . $this->charset . $collation); - } - - /** - * {@inheritdoc} - */ - public function getSubscribedEvents() - { - return [Events::postConnect]; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php deleted file mode 100644 index 19f2b3f..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php +++ /dev/null @@ -1,72 +0,0 @@ - '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', - 'NLS_NUMERIC_CHARACTERS' => '.,', - ]; - - /** - * @param string[] $oracleSessionVars - */ - public function __construct(array $oracleSessionVars = []) - { - $this->_defaultSessionVars = array_merge($this->_defaultSessionVars, $oracleSessionVars); - } - - /** - * @return void - */ - public function postConnect(ConnectionEventArgs $args) - { - if (! count($this->_defaultSessionVars)) { - return; - } - - array_change_key_case($this->_defaultSessionVars, CASE_UPPER); - $vars = []; - foreach ($this->_defaultSessionVars as $option => $value) { - if ($option === 'CURRENT_SCHEMA') { - $vars[] = $option . ' = ' . $value; - } else { - $vars[] = $option . " = '" . $value . "'"; - } - } - $sql = 'ALTER SESSION SET ' . implode(' ', $vars); - $args->getConnection()->executeUpdate($sql); - } - - /** - * {@inheritdoc} - */ - public function getSubscribedEvents() - { - return [Events::postConnect]; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php deleted file mode 100644 index ea63cab..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php +++ /dev/null @@ -1,41 +0,0 @@ -sql = $sql; - } - - /** - * @return void - */ - public function postConnect(ConnectionEventArgs $args) - { - $conn = $args->getConnection(); - $conn->exec($this->sql); - } - - /** - * {@inheritdoc} - */ - public function getSubscribedEvents() - { - return [Events::postConnect]; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php deleted file mode 100644 index ff86a93..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php +++ /dev/null @@ -1,81 +0,0 @@ -column = $column; - $this->tableDiff = $tableDiff; - $this->platform = $platform; - } - - /** - * @return Column - */ - public function getColumn() - { - return $this->column; - } - - /** - * @return TableDiff - */ - public function getTableDiff() - { - return $this->tableDiff; - } - - /** - * @return AbstractPlatform - */ - public function getPlatform() - { - return $this->platform; - } - - /** - * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. - * - * @param string|string[] $sql - * - * @return \Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs - */ - public function addSql($sql) - { - $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); - - return $this; - } - - /** - * @return string[] - */ - public function getSql() - { - return $this->sql; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php deleted file mode 100644 index 354eb68..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php +++ /dev/null @@ -1,81 +0,0 @@ -columnDiff = $columnDiff; - $this->tableDiff = $tableDiff; - $this->platform = $platform; - } - - /** - * @return ColumnDiff - */ - public function getColumnDiff() - { - return $this->columnDiff; - } - - /** - * @return TableDiff - */ - public function getTableDiff() - { - return $this->tableDiff; - } - - /** - * @return AbstractPlatform - */ - public function getPlatform() - { - return $this->platform; - } - - /** - * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. - * - * @param string|string[] $sql - * - * @return \Doctrine\DBAL\Event\SchemaAlterTableChangeColumnEventArgs - */ - public function addSql($sql) - { - $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); - - return $this; - } - - /** - * @return string[] - */ - public function getSql() - { - return $this->sql; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php deleted file mode 100644 index b10bc7a..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php +++ /dev/null @@ -1,68 +0,0 @@ -tableDiff = $tableDiff; - $this->platform = $platform; - } - - /** - * @return TableDiff - */ - public function getTableDiff() - { - return $this->tableDiff; - } - - /** - * @return AbstractPlatform - */ - public function getPlatform() - { - return $this->platform; - } - - /** - * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. - * - * @param string|string[] $sql - * - * @return \Doctrine\DBAL\Event\SchemaAlterTableEventArgs - */ - public function addSql($sql) - { - $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); - - return $this; - } - - /** - * @return string[] - */ - public function getSql() - { - return $this->sql; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php deleted file mode 100644 index 6e3d6a7..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php +++ /dev/null @@ -1,81 +0,0 @@ -column = $column; - $this->tableDiff = $tableDiff; - $this->platform = $platform; - } - - /** - * @return Column - */ - public function getColumn() - { - return $this->column; - } - - /** - * @return TableDiff - */ - public function getTableDiff() - { - return $this->tableDiff; - } - - /** - * @return AbstractPlatform - */ - public function getPlatform() - { - return $this->platform; - } - - /** - * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. - * - * @param string|string[] $sql - * - * @return \Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs - */ - public function addSql($sql) - { - $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); - - return $this; - } - - /** - * @return string[] - */ - public function getSql() - { - return $this->sql; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php deleted file mode 100644 index 27e2825..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php +++ /dev/null @@ -1,96 +0,0 @@ -oldColumnName = $oldColumnName; - $this->column = $column; - $this->tableDiff = $tableDiff; - $this->platform = $platform; - } - - /** - * @return string - */ - public function getOldColumnName() - { - return $this->oldColumnName; - } - - /** - * @return Column - */ - public function getColumn() - { - return $this->column; - } - - /** - * @return TableDiff - */ - public function getTableDiff() - { - return $this->tableDiff; - } - - /** - * @return AbstractPlatform - */ - public function getPlatform() - { - return $this->platform; - } - - /** - * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. - * - * @param string|string[] $sql - * - * @return \Doctrine\DBAL\Event\SchemaAlterTableRenameColumnEventArgs - */ - public function addSql($sql) - { - $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); - - return $this; - } - - /** - * @return string[] - */ - public function getSql() - { - return $this->sql; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php deleted file mode 100644 index 80d9abe..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php +++ /dev/null @@ -1,108 +0,0 @@ -tableColumn = $tableColumn; - $this->table = $table; - $this->database = $database; - $this->connection = $connection; - } - - /** - * Allows to clear the column which means the column will be excluded from - * tables column list. - * - * @return \Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs - */ - public function setColumn(?Column $column = null) - { - $this->column = $column; - - return $this; - } - - /** - * @return Column|null - */ - public function getColumn() - { - return $this->column; - } - - /** - * @return mixed[] - */ - public function getTableColumn() - { - return $this->tableColumn; - } - - /** - * @return string - */ - public function getTable() - { - return $this->table; - } - - /** - * @return string - */ - public function getDatabase() - { - return $this->database; - } - - /** - * @return Connection - */ - public function getConnection() - { - return $this->connection; - } - - /** - * @deprecated Use SchemaColumnDefinitionEventArgs::getConnection() and Connection::getDatabasePlatform() instead. - * - * @return AbstractPlatform - */ - public function getDatabasePlatform() - { - return $this->connection->getDatabasePlatform(); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php deleted file mode 100644 index 6d78aae..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php +++ /dev/null @@ -1,81 +0,0 @@ -column = $column; - $this->table = $table; - $this->platform = $platform; - } - - /** - * @return Column - */ - public function getColumn() - { - return $this->column; - } - - /** - * @return Table - */ - public function getTable() - { - return $this->table; - } - - /** - * @return AbstractPlatform - */ - public function getPlatform() - { - return $this->platform; - } - - /** - * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. - * - * @param string|string[] $sql - * - * @return \Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs - */ - public function addSql($sql) - { - $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); - - return $this; - } - - /** - * @return string[] - */ - public function getSql() - { - return $this->sql; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php deleted file mode 100644 index 927a4e4..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php +++ /dev/null @@ -1,96 +0,0 @@ -table = $table; - $this->columns = $columns; - $this->options = $options; - $this->platform = $platform; - } - - /** - * @return Table - */ - public function getTable() - { - return $this->table; - } - - /** - * @return mixed[][] - */ - public function getColumns() - { - return $this->columns; - } - - /** - * @return mixed[] - */ - public function getOptions() - { - return $this->options; - } - - /** - * @return AbstractPlatform - */ - public function getPlatform() - { - return $this->platform; - } - - /** - * Passing multiple SQL statements as an array is deprecated. Pass each statement as an individual argument instead. - * - * @param string|string[] $sql - * - * @return \Doctrine\DBAL\Event\SchemaCreateTableEventArgs - */ - public function addSql($sql) - { - $this->sql = array_merge($this->sql, is_array($sql) ? $sql : func_get_args()); - - return $this; - } - - /** - * @return string[] - */ - public function getSql() - { - return $this->sql; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php deleted file mode 100644 index 3870497..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php +++ /dev/null @@ -1,69 +0,0 @@ -table = $table; - $this->platform = $platform; - } - - /** - * @return string|Table - */ - public function getTable() - { - return $this->table; - } - - /** - * @return AbstractPlatform - */ - public function getPlatform() - { - return $this->platform; - } - - /** - * @param string $sql - * - * @return \Doctrine\DBAL\Event\SchemaDropTableEventArgs - */ - public function setSql($sql) - { - $this->sql = $sql; - - return $this; - } - - /** - * @return string|null - */ - public function getSql() - { - return $this->sql; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaEventArgs.php deleted file mode 100644 index 0db0689..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaEventArgs.php +++ /dev/null @@ -1,32 +0,0 @@ -preventDefault = true; - - return $this; - } - - /** - * @return bool - */ - public function isDefaultPrevented() - { - return $this->preventDefault; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php deleted file mode 100644 index 317f352..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php +++ /dev/null @@ -1,92 +0,0 @@ -tableIndex = $tableIndex; - $this->table = $table; - $this->connection = $connection; - } - - /** - * Allows to clear the index which means the index will be excluded from tables index list. - * - * @return SchemaIndexDefinitionEventArgs - */ - public function setIndex(?Index $index = null) - { - $this->index = $index; - - return $this; - } - - /** - * @return Index|null - */ - public function getIndex() - { - return $this->index; - } - - /** - * @return mixed[] - */ - public function getTableIndex() - { - return $this->tableIndex; - } - - /** - * @return string - */ - public function getTable() - { - return $this->table; - } - - /** - * @return Connection - */ - public function getConnection() - { - return $this->connection; - } - - /** - * @return AbstractPlatform - */ - public function getDatabasePlatform() - { - return $this->connection->getDatabasePlatform(); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Events.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Events.php deleted file mode 100644 index 5398d0f..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Events.php +++ /dev/null @@ -1,31 +0,0 @@ -driverException = $driverException; - } - - /** - * Returns the driver specific error code if given. - * - * Returns null if no error code was given by the driver. - * - * @return int|string|null - */ - public function getErrorCode() - { - return $this->driverException->getErrorCode(); - } - - /** - * Returns the SQLSTATE the driver was in at the time the error occurred, if given. - * - * Returns null if no SQLSTATE was given by the driver. - * - * @return string|null - */ - public function getSQLState() - { - return $this->driverException->getSQLState(); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ForeignKeyConstraintViolationException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ForeignKeyConstraintViolationException.php deleted file mode 100644 index 48d736f..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Exception/ForeignKeyConstraintViolationException.php +++ /dev/null @@ -1,10 +0,0 @@ -getParams(); - if ($params['driver'] === 'pdo_sqlite') { - throw new DBALException('Cannot use TableGenerator with SQLite.'); - } - $this->conn = DriverManager::getConnection($params, $conn->getConfiguration(), $conn->getEventManager()); - $this->generatorTableName = $generatorTableName; - } - - /** - * Generates the next unused value for the given sequence name. - * - * @param string $sequenceName - * - * @return int - * - * @throws DBALException - */ - public function nextValue($sequenceName) - { - if (isset($this->sequences[$sequenceName])) { - $value = $this->sequences[$sequenceName]['value']; - $this->sequences[$sequenceName]['value']++; - if ($this->sequences[$sequenceName]['value'] >= $this->sequences[$sequenceName]['max']) { - unset($this->sequences[$sequenceName]); - } - - return $value; - } - - $this->conn->beginTransaction(); - - try { - $platform = $this->conn->getDatabasePlatform(); - $sql = 'SELECT sequence_value, sequence_increment_by' - . ' FROM ' . $platform->appendLockHint($this->generatorTableName, LockMode::PESSIMISTIC_WRITE) - . ' WHERE sequence_name = ? ' . $platform->getWriteLockSQL(); - $stmt = $this->conn->executeQuery($sql, [$sequenceName]); - $row = $stmt->fetch(FetchMode::ASSOCIATIVE); - - if ($row !== false) { - $row = array_change_key_case($row, CASE_LOWER); - - $value = $row['sequence_value']; - $value++; - - if ($row['sequence_increment_by'] > 1) { - $this->sequences[$sequenceName] = [ - 'value' => $value, - 'max' => $row['sequence_value'] + $row['sequence_increment_by'], - ]; - } - - $sql = 'UPDATE ' . $this->generatorTableName . ' ' . - 'SET sequence_value = sequence_value + sequence_increment_by ' . - 'WHERE sequence_name = ? AND sequence_value = ?'; - $rows = $this->conn->executeUpdate($sql, [$sequenceName, $row['sequence_value']]); - - if ($rows !== 1) { - throw new DBALException('Race-condition detected while updating sequence. Aborting generation'); - } - } else { - $this->conn->insert( - $this->generatorTableName, - ['sequence_name' => $sequenceName, 'sequence_value' => 1, 'sequence_increment_by' => 1] - ); - $value = 1; - } - - $this->conn->commit(); - } catch (Throwable $e) { - $this->conn->rollBack(); - throw new DBALException('Error occurred while generating ID with TableGenerator, aborted generation: ' . $e->getMessage(), 0, $e); - } - - return $value; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php deleted file mode 100644 index 3ec22f3..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php +++ /dev/null @@ -1,71 +0,0 @@ -generatorTableName = $generatorTableName; - } - - /** - * {@inheritdoc} - */ - public function acceptSchema(Schema $schema) - { - $table = $schema->createTable($this->generatorTableName); - $table->addColumn('sequence_name', 'string'); - $table->addColumn('sequence_value', 'integer', ['default' => 1]); - $table->addColumn('sequence_increment_by', 'integer', ['default' => 1]); - } - - /** - * {@inheritdoc} - */ - public function acceptTable(Table $table) - { - } - - /** - * {@inheritdoc} - */ - public function acceptColumn(Table $table, Column $column) - { - } - - /** - * {@inheritdoc} - */ - public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) - { - } - - /** - * {@inheritdoc} - */ - public function acceptIndex(Table $table, Index $index) - { - } - - /** - * {@inheritdoc} - */ - public function acceptSequence(Sequence $sequence) - { - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/LockMode.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/LockMode.php deleted file mode 100644 index 14e8143..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/LockMode.php +++ /dev/null @@ -1,21 +0,0 @@ -enabled) { - return; - } - - $this->start = microtime(true); - $this->queries[++$this->currentQuery] = ['sql' => $sql, 'params' => $params, 'types' => $types, 'executionMS' => 0]; - } - - /** - * {@inheritdoc} - */ - public function stopQuery() - { - if (! $this->enabled) { - return; - } - - $this->queries[$this->currentQuery]['executionMS'] = microtime(true) - $this->start; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php deleted file mode 100644 index 657abb4..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/EchoSQLLogger.php +++ /dev/null @@ -1,37 +0,0 @@ -loggers = $loggers; - } - - /** - * Adds a logger in the chain. - * - * @deprecated Inject list of loggers via constructor instead - * - * @return void - */ - public function addLogger(SQLLogger $logger) - { - $this->loggers[] = $logger; - } - - /** - * {@inheritdoc} - */ - public function startQuery($sql, ?array $params = null, ?array $types = null) - { - foreach ($this->loggers as $logger) { - $logger->startQuery($sql, $params, $types); - } - } - - /** - * {@inheritdoc} - */ - public function stopQuery() - { - foreach ($this->loggers as $logger) { - $logger->stopQuery(); - } - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/SQLLogger.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/SQLLogger.php deleted file mode 100644 index 2e94611..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Logging/SQLLogger.php +++ /dev/null @@ -1,27 +0,0 @@ -_eventManager = $eventManager; - } - - /** - * Gets the EventManager used by the Platform. - * - * @return EventManager - */ - public function getEventManager() - { - return $this->_eventManager; - } - - /** - * Returns the SQL snippet that declares a boolean column. - * - * @param mixed[] $columnDef - * - * @return string - */ - abstract public function getBooleanTypeDeclarationSQL(array $columnDef); - - /** - * Returns the SQL snippet that declares a 4 byte integer column. - * - * @param mixed[] $columnDef - * - * @return string - */ - abstract public function getIntegerTypeDeclarationSQL(array $columnDef); - - /** - * Returns the SQL snippet that declares an 8 byte integer column. - * - * @param mixed[] $columnDef - * - * @return string - */ - abstract public function getBigIntTypeDeclarationSQL(array $columnDef); - - /** - * Returns the SQL snippet that declares a 2 byte integer column. - * - * @param mixed[] $columnDef - * - * @return string - */ - abstract public function getSmallIntTypeDeclarationSQL(array $columnDef); - - /** - * Returns the SQL snippet that declares common properties of an integer column. - * - * @param mixed[] $columnDef - * - * @return string - */ - abstract protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef); - - /** - * Lazy load Doctrine Type Mappings. - * - * @return void - */ - abstract protected function initializeDoctrineTypeMappings(); - - /** - * Initializes Doctrine Type Mappings with the platform defaults - * and with all additional type mappings. - * - * @return void - */ - private function initializeAllDoctrineTypeMappings() - { - $this->initializeDoctrineTypeMappings(); - - foreach (Type::getTypesMap() as $typeName => $className) { - foreach (Type::getType($typeName)->getMappedDatabaseTypes($this) as $dbType) { - $this->doctrineTypeMapping[$dbType] = $typeName; - } - } - } - - /** - * Returns the SQL snippet used to declare a VARCHAR column type. - * - * @param mixed[] $field - * - * @return string - */ - public function getVarcharTypeDeclarationSQL(array $field) - { - if (! isset($field['length'])) { - $field['length'] = $this->getVarcharDefaultLength(); - } - - $fixed = $field['fixed'] ?? false; - - $maxLength = $fixed - ? $this->getCharMaxLength() - : $this->getVarcharMaxLength(); - - if ($field['length'] > $maxLength) { - return $this->getClobTypeDeclarationSQL($field); - } - - return $this->getVarcharTypeDeclarationSQLSnippet($field['length'], $fixed); - } - - /** - * Returns the SQL snippet used to declare a BINARY/VARBINARY column type. - * - * @param mixed[] $field The column definition. - * - * @return string - */ - public function getBinaryTypeDeclarationSQL(array $field) - { - if (! isset($field['length'])) { - $field['length'] = $this->getBinaryDefaultLength(); - } - - $fixed = $field['fixed'] ?? false; - - $maxLength = $this->getBinaryMaxLength(); - - if ($field['length'] > $maxLength) { - if ($maxLength > 0) { - @trigger_error(sprintf( - 'Binary field length %d is greater than supported by the platform (%d). Reduce the field length or use a BLOB field instead.', - $field['length'], - $maxLength - ), E_USER_DEPRECATED); - } - - return $this->getBlobTypeDeclarationSQL($field); - } - - return $this->getBinaryTypeDeclarationSQLSnippet($field['length'], $fixed); - } - - /** - * Returns the SQL snippet to declare a GUID/UUID field. - * - * By default this maps directly to a CHAR(36) and only maps to more - * special datatypes when the underlying databases support this datatype. - * - * @param mixed[] $field - * - * @return string - */ - public function getGuidTypeDeclarationSQL(array $field) - { - $field['length'] = 36; - $field['fixed'] = true; - - return $this->getVarcharTypeDeclarationSQL($field); - } - - /** - * Returns the SQL snippet to declare a JSON field. - * - * By default this maps directly to a CLOB and only maps to more - * special datatypes when the underlying databases support this datatype. - * - * @param mixed[] $field - * - * @return string - */ - public function getJsonTypeDeclarationSQL(array $field) - { - return $this->getClobTypeDeclarationSQL($field); - } - - /** - * @param int $length - * @param bool $fixed - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) - { - throw DBALException::notSupported('VARCHARs not supported by Platform.'); - } - - /** - * Returns the SQL snippet used to declare a BINARY/VARBINARY column type. - * - * @param int $length The length of the column. - * @param bool $fixed Whether the column length is fixed. - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) - { - throw DBALException::notSupported('BINARY/VARBINARY column types are not supported by this platform.'); - } - - /** - * Returns the SQL snippet used to declare a CLOB column type. - * - * @param mixed[] $field - * - * @return string - */ - abstract public function getClobTypeDeclarationSQL(array $field); - - /** - * Returns the SQL Snippet used to declare a BLOB column type. - * - * @param mixed[] $field - * - * @return string - */ - abstract public function getBlobTypeDeclarationSQL(array $field); - - /** - * Gets the name of the platform. - * - * @return string - */ - abstract public function getName(); - - /** - * Registers a doctrine type to be used in conjunction with a column type of this platform. - * - * @param string $dbType - * @param string $doctrineType - * - * @throws DBALException If the type is not found. - */ - public function registerDoctrineTypeMapping($dbType, $doctrineType) - { - if ($this->doctrineTypeMapping === null) { - $this->initializeAllDoctrineTypeMappings(); - } - - if (! Types\Type::hasType($doctrineType)) { - throw DBALException::typeNotFound($doctrineType); - } - - $dbType = strtolower($dbType); - $this->doctrineTypeMapping[$dbType] = $doctrineType; - - $doctrineType = Type::getType($doctrineType); - - if (! $doctrineType->requiresSQLCommentHint($this)) { - return; - } - - $this->markDoctrineTypeCommented($doctrineType); - } - - /** - * Gets the Doctrine type that is mapped for the given database column type. - * - * @param string $dbType - * - * @return string - * - * @throws DBALException - */ - public function getDoctrineTypeMapping($dbType) - { - if ($this->doctrineTypeMapping === null) { - $this->initializeAllDoctrineTypeMappings(); - } - - $dbType = strtolower($dbType); - - if (! isset($this->doctrineTypeMapping[$dbType])) { - throw new DBALException('Unknown database type ' . $dbType . ' requested, ' . static::class . ' may not support it.'); - } - - return $this->doctrineTypeMapping[$dbType]; - } - - /** - * Checks if a database type is currently supported by this platform. - * - * @param string $dbType - * - * @return bool - */ - public function hasDoctrineTypeMappingFor($dbType) - { - if ($this->doctrineTypeMapping === null) { - $this->initializeAllDoctrineTypeMappings(); - } - - $dbType = strtolower($dbType); - - return isset($this->doctrineTypeMapping[$dbType]); - } - - /** - * Initializes the Doctrine Type comments instance variable for in_array() checks. - * - * @return void - */ - protected function initializeCommentedDoctrineTypes() - { - $this->doctrineTypeComments = []; - - foreach (Type::getTypesMap() as $typeName => $className) { - $type = Type::getType($typeName); - - if (! $type->requiresSQLCommentHint($this)) { - continue; - } - - $this->doctrineTypeComments[] = $typeName; - } - } - - /** - * Is it necessary for the platform to add a parsable type comment to allow reverse engineering the given type? - * - * @return bool - */ - public function isCommentedDoctrineType(Type $doctrineType) - { - if ($this->doctrineTypeComments === null) { - $this->initializeCommentedDoctrineTypes(); - } - - assert(is_array($this->doctrineTypeComments)); - - return in_array($doctrineType->getName(), $this->doctrineTypeComments); - } - - /** - * Marks this type as to be commented in ALTER TABLE and CREATE TABLE statements. - * - * @param string|Type $doctrineType - * - * @return void - */ - public function markDoctrineTypeCommented($doctrineType) - { - if ($this->doctrineTypeComments === null) { - $this->initializeCommentedDoctrineTypes(); - } - - assert(is_array($this->doctrineTypeComments)); - - $this->doctrineTypeComments[] = $doctrineType instanceof Type ? $doctrineType->getName() : $doctrineType; - } - - /** - * Gets the comment to append to a column comment that helps parsing this type in reverse engineering. - * - * @return string - */ - public function getDoctrineTypeComment(Type $doctrineType) - { - return '(DC2Type:' . $doctrineType->getName() . ')'; - } - - /** - * Gets the comment of a passed column modified by potential doctrine type comment hints. - * - * @return string|null - */ - protected function getColumnComment(Column $column) - { - $comment = $column->getComment(); - - if ($this->isCommentedDoctrineType($column->getType())) { - $comment .= $this->getDoctrineTypeComment($column->getType()); - } - - return $comment; - } - - /** - * 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 char field. - */ - public function getCharMaxLength() : int - { - return $this->getVarcharMaxLength(); - } - - /** - * Gets the maximum length of a varchar field. - * - * @return int - */ - public function getVarcharMaxLength() - { - return 4000; - } - - /** - * Gets the default length of a varchar field. - * - * @return int - */ - public function getVarcharDefaultLength() - { - return 255; - } - - /** - * Gets the maximum length of a binary field. - * - * @return int - */ - public function getBinaryMaxLength() - { - return 4000; - } - - /** - * Gets the default length of a binary field. - * - * @return int - */ - public function getBinaryDefaultLength() - { - return 255; - } - - /** - * Gets all SQL wildcard characters of the platform. - * - * @return string[] - */ - public function getWildcards() - { - return ['%', '_']; - } - - /** - * Returns the regular expression operator. - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getRegexpExpression() - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Returns the global unique identifier expression. - * - * @deprecated Use application-generated UUIDs instead - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getGuidExpression() - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Returns the SQL snippet to get 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 SQL snippet to get 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|int $column The column to use. - * - * @return string Generated SQL including a COUNT aggregate function. - */ - public function getCountExpression($column) - { - return 'COUNT(' . $column . ')'; - } - - /** - * Returns the SQL snippet to get 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 SQL snippet to get the lowest value of a column. - * - * @param string $column The column to use. - * - * @return string Generated SQL including a MIN aggregate function. - */ - public function getMinExpression($column) - { - return 'MIN(' . $column . ')'; - } - - /** - * Returns the SQL snippet to get the total sum of a column. - * - * @param string $column The column to use. - * - * @return string Generated SQL including a SUM aggregate function. - */ - public function getSumExpression($column) - { - return 'SUM(' . $column . ')'; - } - - // scalar functions - - /** - * Returns the SQL snippet to get the md5 sum of a field. - * - * Note: Not SQL92, but common functionality. - * - * @param string $column - * - * @return string - */ - public function getMd5Expression($column) - { - return 'MD5(' . $column . ')'; - } - - /** - * Returns the SQL snippet to get the length of a text field. - * - * @param string $column - * - * @return string - */ - public function getLengthExpression($column) - { - return 'LENGTH(' . $column . ')'; - } - - /** - * Returns the SQL snippet to get the squared value of a column. - * - * @param string $column The column to use. - * - * @return string Generated SQL including an SQRT aggregate function. - */ - public function getSqrtExpression($column) - { - return 'SQRT(' . $column . ')'; - } - - /** - * Returns the SQL snippet to round a numeric field to the number of decimals specified. - * - * @param string $column - * @param int $decimals - * - * @return string - */ - public function getRoundExpression($column, $decimals = 0) - { - return 'ROUND(' . $column . ', ' . $decimals . ')'; - } - - /** - * Returns the SQL snippet to get 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 . ')'; - } - - /** - * Returns the SQL snippet to trim a string. - * - * @param string $str The expression to apply the trim to. - * @param int $mode The position of the trim (leading/trailing/both). - * @param string|bool $char The char to trim, has to be quoted already. Defaults to space. - * - * @return string - */ - public function getTrimExpression($str, $mode = TrimMode::UNSPECIFIED, $char = false) - { - $expression = ''; - - switch ($mode) { - case TrimMode::LEADING: - $expression = 'LEADING '; - break; - - case TrimMode::TRAILING: - $expression = 'TRAILING '; - break; - - case TrimMode::BOTH: - $expression = 'BOTH '; - break; - } - - if ($char !== false) { - $expression .= $char . ' '; - } - - if ($mode || $char !== false) { - $expression .= 'FROM '; - } - - return 'TRIM(' . $expression . $str . ')'; - } - - /** - * Returns the SQL snippet to trim trailing space characters from the expression. - * - * @param string $str Literal string or column name. - * - * @return string - */ - public function getRtrimExpression($str) - { - return 'RTRIM(' . $str . ')'; - } - - /** - * Returns the SQL snippet to trim leading space characters from the expression. - * - * @param string $str Literal string or column name. - * - * @return string - */ - public function getLtrimExpression($str) - { - return 'LTRIM(' . $str . ')'; - } - - /** - * Returns the SQL snippet to change all characters from the expression 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 . ')'; - } - - /** - * Returns the SQL snippet to change all characters from the expression 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 SQL snippet to get the position of the first occurrence of substring $substr in string $str. - * - * @param string $str Literal string. - * @param string $substr Literal string to find. - * @param int|false $startPos Position to start at, beginning of string by default. - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getLocateExpression($str, $substr, $startPos = false) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Returns the SQL snippet to get the current system date. - * - * @return string - */ - public function getNowExpression() - { - return 'NOW()'; - } - - /** - * Returns a SQL snippet 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 int $from Where to start the substring portion. - * @param int|null $length The substring portion length. - * - * @return string - */ - public function getSubstringExpression($value, $from, $length = null) - { - if ($length === null) { - return 'SUBSTRING(' . $value . ' FROM ' . $from . ')'; - } - - return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $length . ')'; - } - - /** - * Returns a SQL snippet to concatenate the given expressions. - * - * Accepts an arbitrary number of string parameters. Each parameter must contain an expression. - * - * @return string - */ - public function getConcatExpression() - { - return implode(' || ', func_get_args()); - } - - /** - * Returns the SQL for a logical not. - * - * Example: - * - * $q = new Doctrine_Query(); - * $e = $q->expr; - * $q->select('*')->from('table') - * ->where($e->eq('id', $e->not('null')); - * - * - * @param string $expression - * - * @return string The logical expression. - */ - public function getNotExpression($expression) - { - return 'NOT(' . $expression . ')'; - } - - /** - * Returns the SQL that checks if an expression is null. - * - * @param string $expression The expression that should be compared to null. - * - * @return string The logical expression. - */ - public function getIsNullExpression($expression) - { - return $expression . ' IS NULL'; - } - - /** - * Returns the SQL that checks if an expression is not null. - * - * @param string $expression The expression that should be compared to null. - * - * @return string The logical expression. - */ - public function getIsNotNullExpression($expression) - { - return $expression . ' IS NOT NULL'; - } - - /** - * Returns the 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 The logical expression. - */ - public function getBetweenExpression($expression, $value1, $value2) - { - return $expression . ' BETWEEN ' . $value1 . ' AND ' . $value2; - } - - /** - * Returns the SQL to get the arccosine of a value. - * - * @param string $value - * - * @return string - */ - public function getAcosExpression($value) - { - return 'ACOS(' . $value . ')'; - } - - /** - * Returns the SQL to get the sine of a value. - * - * @param string $value - * - * @return string - */ - public function getSinExpression($value) - { - return 'SIN(' . $value . ')'; - } - - /** - * Returns the SQL to get the PI value. - * - * @return string - */ - public function getPiExpression() - { - return 'PI()'; - } - - /** - * Returns the SQL to get the cosine of a value. - * - * @param string $value - * - * @return string - */ - public function getCosExpression($value) - { - return 'COS(' . $value . ')'; - } - - /** - * Returns the SQL to calculate the difference in days between the two passed dates. - * - * Computes diff = date1 - date2. - * - * @param string $date1 - * @param string $date2 - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateDiffExpression($date1, $date2) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Returns the SQL to add the number of given seconds to a date. - * - * @param string $date - * @param int $seconds - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateAddSecondsExpression($date, $seconds) - { - return $this->getDateArithmeticIntervalExpression($date, '+', $seconds, DateIntervalUnit::SECOND); - } - - /** - * Returns the SQL to subtract the number of given seconds from a date. - * - * @param string $date - * @param int $seconds - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateSubSecondsExpression($date, $seconds) - { - return $this->getDateArithmeticIntervalExpression($date, '-', $seconds, DateIntervalUnit::SECOND); - } - - /** - * Returns the SQL to add the number of given minutes to a date. - * - * @param string $date - * @param int $minutes - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateAddMinutesExpression($date, $minutes) - { - return $this->getDateArithmeticIntervalExpression($date, '+', $minutes, DateIntervalUnit::MINUTE); - } - - /** - * Returns the SQL to subtract the number of given minutes from a date. - * - * @param string $date - * @param int $minutes - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateSubMinutesExpression($date, $minutes) - { - return $this->getDateArithmeticIntervalExpression($date, '-', $minutes, DateIntervalUnit::MINUTE); - } - - /** - * Returns the SQL to add the number of given hours to a date. - * - * @param string $date - * @param int $hours - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateAddHourExpression($date, $hours) - { - return $this->getDateArithmeticIntervalExpression($date, '+', $hours, DateIntervalUnit::HOUR); - } - - /** - * Returns the SQL to subtract the number of given hours to a date. - * - * @param string $date - * @param int $hours - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateSubHourExpression($date, $hours) - { - return $this->getDateArithmeticIntervalExpression($date, '-', $hours, DateIntervalUnit::HOUR); - } - - /** - * Returns the SQL to add the number of given days to a date. - * - * @param string $date - * @param int $days - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateAddDaysExpression($date, $days) - { - return $this->getDateArithmeticIntervalExpression($date, '+', $days, DateIntervalUnit::DAY); - } - - /** - * Returns the SQL to subtract the number of given days to a date. - * - * @param string $date - * @param int $days - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateSubDaysExpression($date, $days) - { - return $this->getDateArithmeticIntervalExpression($date, '-', $days, DateIntervalUnit::DAY); - } - - /** - * Returns the SQL to add the number of given weeks to a date. - * - * @param string $date - * @param int $weeks - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateAddWeeksExpression($date, $weeks) - { - return $this->getDateArithmeticIntervalExpression($date, '+', $weeks, DateIntervalUnit::WEEK); - } - - /** - * Returns the SQL to subtract the number of given weeks from a date. - * - * @param string $date - * @param int $weeks - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateSubWeeksExpression($date, $weeks) - { - return $this->getDateArithmeticIntervalExpression($date, '-', $weeks, DateIntervalUnit::WEEK); - } - - /** - * Returns the SQL to add the number of given months to a date. - * - * @param string $date - * @param int $months - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateAddMonthExpression($date, $months) - { - return $this->getDateArithmeticIntervalExpression($date, '+', $months, DateIntervalUnit::MONTH); - } - - /** - * Returns the SQL to subtract the number of given months to a date. - * - * @param string $date - * @param int $months - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateSubMonthExpression($date, $months) - { - return $this->getDateArithmeticIntervalExpression($date, '-', $months, DateIntervalUnit::MONTH); - } - - /** - * Returns the SQL to add the number of given quarters to a date. - * - * @param string $date - * @param int $quarters - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateAddQuartersExpression($date, $quarters) - { - return $this->getDateArithmeticIntervalExpression($date, '+', $quarters, DateIntervalUnit::QUARTER); - } - - /** - * Returns the SQL to subtract the number of given quarters from a date. - * - * @param string $date - * @param int $quarters - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateSubQuartersExpression($date, $quarters) - { - return $this->getDateArithmeticIntervalExpression($date, '-', $quarters, DateIntervalUnit::QUARTER); - } - - /** - * Returns the SQL to add the number of given years to a date. - * - * @param string $date - * @param int $years - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateAddYearsExpression($date, $years) - { - return $this->getDateArithmeticIntervalExpression($date, '+', $years, DateIntervalUnit::YEAR); - } - - /** - * Returns the SQL to subtract the number of given years from a date. - * - * @param string $date - * @param int $years - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateSubYearsExpression($date, $years) - { - return $this->getDateArithmeticIntervalExpression($date, '-', $years, DateIntervalUnit::YEAR); - } - - /** - * Returns the SQL for a date arithmetic expression. - * - * @param string $date The column or literal representing a date to perform the arithmetic operation on. - * @param string $operator The arithmetic operator (+ or -). - * @param int $interval The interval that shall be calculated into the date. - * @param string $unit The unit of the interval that shall be calculated into the date. - * One of the DATE_INTERVAL_UNIT_* constants. - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Returns the SQL bit AND comparison expression. - * - * @param string $value1 - * @param string $value2 - * - * @return string - */ - public function getBitAndComparisonExpression($value1, $value2) - { - return '(' . $value1 . ' & ' . $value2 . ')'; - } - - /** - * Returns the SQL bit OR comparison expression. - * - * @param string $value1 - * @param string $value2 - * - * @return string - */ - public function getBitOrComparisonExpression($value1, $value2) - { - return '(' . $value1 . ' | ' . $value2 . ')'; - } - - /** - * Returns the FOR UPDATE expression. - * - * @return string - */ - 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 The FROM clause to append the hint for the given lock mode to. - * @param int|null $lockMode One of the Doctrine\DBAL\LockMode::* constants. If null is given, nothing will - * be appended to the FROM clause. - * - * @return string - */ - public function appendLockHint($fromClause, $lockMode) - { - return $fromClause; - } - - /** - * Returns the SQL snippet to append to any SELECT statement which locks rows in shared read lock. - * - * This defaults to the ANSI 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(); - } - - /** - * Returns 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 ANSI SQL standard. - * - * @return string - */ - public function getWriteLockSQL() - { - return $this->getForUpdateSQL(); - } - - /** - * Returns the SQL snippet to drop an existing database. - * - * @param string $database The name of the database that should be dropped. - * - * @return string - */ - public function getDropDatabaseSQL($database) - { - return 'DROP DATABASE ' . $database; - } - - /** - * Returns the SQL snippet to drop an existing table. - * - * @param Table|string $table - * - * @return string - * - * @throws InvalidArgumentException - */ - public function getDropTableSQL($table) - { - $tableArg = $table; - - if ($table instanceof Table) { - $table = $table->getQuotedName($this); - } - - if (! is_string($table)) { - throw new InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); - } - - if ($this->_eventManager !== null && $this->_eventManager->hasListeners(Events::onSchemaDropTable)) { - $eventArgs = new SchemaDropTableEventArgs($tableArg, $this); - $this->_eventManager->dispatchEvent(Events::onSchemaDropTable, $eventArgs); - - if ($eventArgs->isDefaultPrevented()) { - $sql = $eventArgs->getSql(); - - if ($sql === null) { - throw new UnexpectedValueException('Default implementation of DROP TABLE was overridden with NULL'); - } - - return $sql; - } - } - - return 'DROP TABLE ' . $table; - } - - /** - * Returns the SQL to safely drop a temporary table WITHOUT implicitly committing an open transaction. - * - * @param Table|string $table - * - * @return string - */ - public function getDropTemporaryTableSQL($table) - { - return $this->getDropTableSQL($table); - } - - /** - * Returns the SQL to drop an index from a table. - * - * @param Index|string $index - * @param Table|string $table - * - * @return string - * - * @throws InvalidArgumentException - */ - public function getDropIndexSQL($index, $table = null) - { - if ($index instanceof Index) { - $index = $index->getQuotedName($this); - } elseif (! is_string($index)) { - throw new InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); - } - - return 'DROP INDEX ' . $index; - } - - /** - * Returns the SQL to drop a constraint. - * - * @param Constraint|string $constraint - * @param Table|string $table - * - * @return string - */ - public function getDropConstraintSQL($constraint, $table) - { - if (! $constraint instanceof Constraint) { - $constraint = new Identifier($constraint); - } - - if (! $table instanceof Table) { - $table = new Identifier($table); - } - - $constraint = $constraint->getQuotedName($this); - $table = $table->getQuotedName($this); - - return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $constraint; - } - - /** - * Returns the SQL to drop a foreign key. - * - * @param ForeignKeyConstraint|string $foreignKey - * @param Table|string $table - * - * @return string - */ - public function getDropForeignKeySQL($foreignKey, $table) - { - if (! $foreignKey instanceof ForeignKeyConstraint) { - $foreignKey = new Identifier($foreignKey); - } - - if (! $table instanceof Table) { - $table = new Identifier($table); - } - - $foreignKey = $foreignKey->getQuotedName($this); - $table = $table->getQuotedName($this); - - return 'ALTER TABLE ' . $table . ' DROP FOREIGN KEY ' . $foreignKey; - } - - /** - * Returns the SQL statement(s) to create a table with the specified name, columns and constraints - * on this platform. - * - * @param int $createFlags - * - * @return string[] The sequence of SQL statements. - * - * @throws DBALException - * @throws InvalidArgumentException - */ - 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->getQuotedName($this); - $options = $table->getOptions(); - $options['uniqueConstraints'] = []; - $options['indexes'] = []; - $options['primary'] = []; - - if (($createFlags&self::CREATE_INDEXES) > 0) { - foreach ($table->getIndexes() as $index) { - /** @var $index Index */ - if ($index->isPrimary()) { - $options['primary'] = $index->getQuotedColumns($this); - $options['primary_index'] = $index; - } else { - $options['indexes'][$index->getQuotedName($this)] = $index; - } - } - } - - $columnSql = []; - $columns = []; - - foreach ($table->getColumns() as $column) { - if ($this->_eventManager !== null && $this->_eventManager->hasListeners(Events::onSchemaCreateTableColumn)) { - $eventArgs = new SchemaCreateTableColumnEventArgs($column, $table, $this); - $this->_eventManager->dispatchEvent(Events::onSchemaCreateTableColumn, $eventArgs); - - $columnSql = array_merge($columnSql, $eventArgs->getSql()); - - if ($eventArgs->isDefaultPrevented()) { - continue; - } - } - - $columnData = $column->toArray(); - $columnData['name'] = $column->getQuotedName($this); - $columnData['version'] = $column->hasPlatformOption('version') ? $column->getPlatformOption('version') : false; - $columnData['comment'] = $this->getColumnComment($column); - - if ($columnData['type'] instanceof Types\StringType && $columnData['length'] === null) { - $columnData['length'] = 255; - } - - if (in_array($column->getName(), $options['primary'])) { - $columnData['primary'] = true; - } - - $columns[$columnData['name']] = $columnData; - } - - if (($createFlags&self::CREATE_FOREIGNKEYS) > 0) { - $options['foreignKeys'] = []; - foreach ($table->getForeignKeys() as $fkConstraint) { - $options['foreignKeys'][] = $fkConstraint; - } - } - - if ($this->_eventManager !== null && $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) { - $eventArgs = new SchemaCreateTableEventArgs($table, $columns, $options, $this); - $this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs); - - if ($eventArgs->isDefaultPrevented()) { - return array_merge($eventArgs->getSql(), $columnSql); - } - } - - $sql = $this->_getCreateTableSQL($tableName, $columns, $options); - if ($this->supportsCommentOnStatement()) { - if ($table->hasOption('comment')) { - $sql[] = $this->getCommentOnTableSQL($tableName, $table->getOption('comment')); - } - foreach ($table->getColumns() as $column) { - $comment = $this->getColumnComment($column); - - if ($comment === null || $comment === '') { - continue; - } - - $sql[] = $this->getCommentOnColumnSQL($tableName, $column->getQuotedName($this), $comment); - } - } - - return array_merge($sql, $columnSql); - } - - protected function getCommentOnTableSQL(string $tableName, ?string $comment) : string - { - $tableName = new Identifier($tableName); - - return sprintf( - 'COMMENT ON TABLE %s IS %s', - $tableName->getQuotedName($this), - $this->quoteStringLiteral((string) $comment) - ); - } - - /** - * @param string $tableName - * @param string $columnName - * @param string|null $comment - * - * @return string - */ - public function getCommentOnColumnSQL($tableName, $columnName, $comment) - { - $tableName = new Identifier($tableName); - $columnName = new Identifier($columnName); - - return sprintf( - 'COMMENT ON COLUMN %s.%s IS %s', - $tableName->getQuotedName($this), - $columnName->getQuotedName($this), - $this->quoteStringLiteral((string) $comment) - ); - } - - /** - * Returns the SQL to create inline comment on a column. - * - * @param string $comment - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getInlineColumnCommentSQL($comment) - { - if (! $this->supportsInlineColumnComments()) { - throw DBALException::notSupported(__METHOD__); - } - - return 'COMMENT ' . $this->quoteStringLiteral($comment); - } - - /** - * Returns the SQL used to create a table. - * - * @param string $tableName - * @param mixed[][] $columns - * @param mixed[] $options - * - * @return string[] - */ - protected function _getCreateTableSQL($tableName, array $columns, array $options = []) - { - $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; - } - - /** - * @return string - */ - public function getCreateTemporaryTableSnippetSQL() - { - return 'CREATE TEMPORARY TABLE'; - } - - /** - * Returns the SQL to create a sequence on this platform. - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getCreateSequenceSQL(Sequence $sequence) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Returns the SQL to change a sequence on this platform. - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getAlterSequenceSQL(Sequence $sequence) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Returns the SQL to create a constraint on a table on this platform. - * - * @param Table|string $table - * - * @return string - * - * @throws InvalidArgumentException - */ - public function getCreateConstraintSQL(Constraint $constraint, $table) - { - if ($table instanceof Table) { - $table = $table->getQuotedName($this); - } - - $query = 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $constraint->getQuotedName($this); - - $columnList = '(' . implode(', ', $constraint->getQuotedColumns($this)) . ')'; - - $referencesClause = ''; - if ($constraint instanceof 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().' - ); - } - } elseif ($constraint instanceof ForeignKeyConstraint) { - $query .= ' FOREIGN KEY'; - - $referencesClause = ' REFERENCES ' . $constraint->getQuotedForeignTableName($this) . - ' (' . implode(', ', $constraint->getQuotedForeignColumns($this)) . ')'; - } - $query .= ' ' . $columnList . $referencesClause; - - return $query; - } - - /** - * Returns the SQL to create an index on a table on this platform. - * - * @param Table|string $table The name of the table on which the index is to be created. - * - * @return string - * - * @throws InvalidArgumentException - */ - public function getCreateIndexSQL(Index $index, $table) - { - if ($table instanceof Table) { - $table = $table->getQuotedName($this); - } - $name = $index->getQuotedName($this); - $columns = $index->getColumns(); - - if (count($columns) === 0) { - throw new InvalidArgumentException("Incomplete definition. 'columns' required."); - } - - if ($index->isPrimary()) { - return $this->getCreatePrimaryKeySQL($index, $table); - } - - $query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $table; - $query .= ' (' . $this->getIndexFieldDeclarationListSQL($index) . ')' . $this->getPartialIndexSQL($index); - - return $query; - } - - /** - * Adds condition for partial index. - * - * @return string - */ - protected function getPartialIndexSQL(Index $index) - { - if ($this->supportsPartialIndexes() && $index->hasOption('where')) { - return ' WHERE ' . $index->getOption('where'); - } - - return ''; - } - - /** - * Adds additional flags for index generation. - * - * @return string - */ - protected function getCreateIndexSQLFlags(Index $index) - { - return $index->isUnique() ? 'UNIQUE ' : ''; - } - - /** - * Returns the SQL to create an unnamed primary key constraint. - * - * @param Table|string $table - * - * @return string - */ - public function getCreatePrimaryKeySQL(Index $index, $table) - { - if ($table instanceof Table) { - $table = $table->getQuotedName($this); - } - - return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index) . ')'; - } - - /** - * Returns the SQL to create a named schema. - * - * @param string $schemaName - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getCreateSchemaSQL($schemaName) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * 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. This also detects identifier - * chains separated by dot and quotes them independently. - * - * 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 The identifier name to be quoted. - * - * @return string The quoted identifier string. - */ - public function quoteIdentifier($str) - { - if (strpos($str, '.') !== false) { - $parts = array_map([$this, 'quoteSingleIdentifier'], explode('.', $str)); - - return implode('.', $parts); - } - - return $this->quoteSingleIdentifier($str); - } - - /** - * Quotes a single identifier (no dot chain separation). - * - * @param string $str The identifier name to be quoted. - * - * @return string The quoted identifier string. - */ - public function quoteSingleIdentifier($str) - { - $c = $this->getIdentifierQuoteCharacter(); - - return $c . str_replace($c, $c . $c, $str) . $c; - } - - /** - * Returns the SQL to create a new foreign key. - * - * @param ForeignKeyConstraint $foreignKey The foreign key constraint. - * @param Table|string $table The name of the table on which the foreign key is to be created. - * - * @return string - */ - public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table) - { - if ($table instanceof Table) { - $table = $table->getQuotedName($this); - } - - return 'ALTER TABLE ' . $table . ' ADD ' . $this->getForeignKeyDeclarationSQL($foreignKey); - } - - /** - * Gets the SQL statements for altering an existing table. - * - * This method returns an array of SQL statements, since some platforms need several statements. - * - * @return string[] - * - * @throws DBALException If not supported on this platform. - */ - public function getAlterTableSQL(TableDiff $diff) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * @param mixed[] $columnSql - * - * @return bool - */ - protected function onSchemaAlterTableAddColumn(Column $column, TableDiff $diff, &$columnSql) - { - if ($this->_eventManager === null) { - return false; - } - - if (! $this->_eventManager->hasListeners(Events::onSchemaAlterTableAddColumn)) { - return false; - } - - $eventArgs = new SchemaAlterTableAddColumnEventArgs($column, $diff, $this); - $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableAddColumn, $eventArgs); - - $columnSql = array_merge($columnSql, $eventArgs->getSql()); - - return $eventArgs->isDefaultPrevented(); - } - - /** - * @param string[] $columnSql - * - * @return bool - */ - protected function onSchemaAlterTableRemoveColumn(Column $column, TableDiff $diff, &$columnSql) - { - if ($this->_eventManager === null) { - return false; - } - - if (! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRemoveColumn)) { - return false; - } - - $eventArgs = new SchemaAlterTableRemoveColumnEventArgs($column, $diff, $this); - $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableRemoveColumn, $eventArgs); - - $columnSql = array_merge($columnSql, $eventArgs->getSql()); - - return $eventArgs->isDefaultPrevented(); - } - - /** - * @param string[] $columnSql - * - * @return bool - */ - protected function onSchemaAlterTableChangeColumn(ColumnDiff $columnDiff, TableDiff $diff, &$columnSql) - { - if ($this->_eventManager === null) { - return false; - } - - if (! $this->_eventManager->hasListeners(Events::onSchemaAlterTableChangeColumn)) { - return false; - } - - $eventArgs = new SchemaAlterTableChangeColumnEventArgs($columnDiff, $diff, $this); - $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableChangeColumn, $eventArgs); - - $columnSql = array_merge($columnSql, $eventArgs->getSql()); - - return $eventArgs->isDefaultPrevented(); - } - - /** - * @param string $oldColumnName - * @param string[] $columnSql - * - * @return bool - */ - protected function onSchemaAlterTableRenameColumn($oldColumnName, Column $column, TableDiff $diff, &$columnSql) - { - if ($this->_eventManager === null) { - return false; - } - - if (! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRenameColumn)) { - return false; - } - - $eventArgs = new SchemaAlterTableRenameColumnEventArgs($oldColumnName, $column, $diff, $this); - $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableRenameColumn, $eventArgs); - - $columnSql = array_merge($columnSql, $eventArgs->getSql()); - - return $eventArgs->isDefaultPrevented(); - } - - /** - * @param string[] $sql - * - * @return bool - */ - protected function onSchemaAlterTable(TableDiff $diff, &$sql) - { - if ($this->_eventManager === null) { - return false; - } - - if (! $this->_eventManager->hasListeners(Events::onSchemaAlterTable)) { - return false; - } - - $eventArgs = new SchemaAlterTableEventArgs($diff, $this); - $this->_eventManager->dispatchEvent(Events::onSchemaAlterTable, $eventArgs); - - $sql = array_merge($sql, $eventArgs->getSql()); - - return $eventArgs->isDefaultPrevented(); - } - - /** - * @return string[] - */ - protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) - { - $tableName = $diff->getName($this)->getQuotedName($this); - - $sql = []; - if ($this->supportsForeignKeyConstraints()) { - foreach ($diff->removedForeignKeys as $foreignKey) { - $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName); - } - foreach ($diff->changedForeignKeys as $foreignKey) { - $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName); - } - } - - foreach ($diff->removedIndexes as $index) { - $sql[] = $this->getDropIndexSQL($index, $tableName); - } - foreach ($diff->changedIndexes as $index) { - $sql[] = $this->getDropIndexSQL($index, $tableName); - } - - return $sql; - } - - /** - * @return string[] - */ - protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) - { - $sql = []; - $newName = $diff->getNewName(); - - if ($newName !== false) { - $tableName = $newName->getQuotedName($this); - } else { - $tableName = $diff->getName($this)->getQuotedName($this); - } - - if ($this->supportsForeignKeyConstraints()) { - foreach ($diff->addedForeignKeys as $foreignKey) { - $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); - } - - foreach ($diff->changedForeignKeys as $foreignKey) { - $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); - } - } - - foreach ($diff->addedIndexes as $index) { - $sql[] = $this->getCreateIndexSQL($index, $tableName); - } - - foreach ($diff->changedIndexes as $index) { - $sql[] = $this->getCreateIndexSQL($index, $tableName); - } - - foreach ($diff->renamedIndexes as $oldIndexName => $index) { - $oldIndexName = new Identifier($oldIndexName); - $sql = array_merge( - $sql, - $this->getRenameIndexSQL($oldIndexName->getQuotedName($this), $index, $tableName) - ); - } - - return $sql; - } - - /** - * Returns the SQL for renaming an index on a table. - * - * @param string $oldIndexName The name of the index to rename from. - * @param Index $index The definition of the index to rename to. - * @param string $tableName The table to rename the given index on. - * - * @return string[] The sequence of SQL statements for renaming the given index. - */ - protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) - { - return [ - $this->getDropIndexSQL($oldIndexName, $tableName), - $this->getCreateIndexSQL($index, $tableName), - ]; - } - - /** - * Common code for alter table statement generation that updates the changed Index and Foreign Key definitions. - * - * @deprecated - * - * @return string[] - */ - protected function _getAlterTableIndexForeignKeySQL(TableDiff $diff) - { - return array_merge($this->getPreAlterTableIndexForeignKeySQL($diff), $this->getPostAlterTableIndexForeignKeySQL($diff)); - } - - /** - * Gets declaration of a number of fields in bulk. - * - * @param mixed[][] $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 = []; - - foreach ($fields as $fieldName => $field) { - $queryFields[] = $this->getColumnDeclarationSQL($fieldName, $field); - } - - return implode(', ', $queryFields); - } - - /** - * Obtains DBMS specific SQL code portion needed to declare a generic type - * field to be used in statements like CREATE TABLE. - * - * @param string $name The name the field to be declared. - * @param mixed[] $field An 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; - - if ($this->supportsInlineColumnComments() && isset($field['comment']) && $field['comment'] !== '') { - $columnDef .= ' ' . $this->getInlineColumnCommentSQL($field['comment']); - } - } - - return $name . ' ' . $columnDef; - } - - /** - * Returns the SQL snippet that declares a floating point column of arbitrary precision. - * - * @param mixed[] $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'] . ')'; - } - - /** - * Obtains DBMS specific SQL code portion needed to set a default value - * declaration to be used in statements like CREATE TABLE. - * - * @param mixed[] $field The field definition array. - * - * @return string DBMS specific SQL code portion needed to set a default value. - */ - public function getDefaultValueDeclarationSQL($field) - { - if (! isset($field['default'])) { - return empty($field['notnull']) ? ' DEFAULT NULL' : ''; - } - - $default = $field['default']; - - if (! isset($field['type'])) { - return " DEFAULT '" . $default . "'"; - } - - $type = $field['type']; - - if ($type instanceof Types\PhpIntegerMappingType) { - return ' DEFAULT ' . $default; - } - - if ($type instanceof Types\PhpDateTimeMappingType && $default === $this->getCurrentTimestampSQL()) { - return ' DEFAULT ' . $this->getCurrentTimestampSQL(); - } - - if ($type instanceof Types\TimeType && $default === $this->getCurrentTimeSQL()) { - return ' DEFAULT ' . $this->getCurrentTimeSQL(); - } - - if ($type instanceof Types\DateType && $default === $this->getCurrentDateSQL()) { - return ' DEFAULT ' . $this->getCurrentDateSQL(); - } - - if ($type instanceof Types\BooleanType) { - return " DEFAULT '" . $this->convertBooleans($default) . "'"; - } - - return ' DEFAULT ' . $this->quoteStringLiteral($default); - } - - /** - * Obtains DBMS specific SQL code portion needed to set a CHECK constraint - * declaration to be used in statements like CREATE TABLE. - * - * @param string[]|mixed[][] $definition The check definition. - * - * @return string DBMS specific SQL code portion needed to set a CHECK constraint. - */ - public function getCheckDeclarationSQL(array $definition) - { - $constraints = []; - 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); - } - - /** - * Obtains DBMS specific SQL code portion needed to set a unique - * constraint declaration to be used in statements like CREATE TABLE. - * - * @param string $name The name of the unique constraint. - * @param Index $index The index definition. - * - * @return string DBMS specific SQL code portion needed to set a constraint. - * - * @throws InvalidArgumentException - */ - public function getUniqueConstraintDeclarationSQL($name, Index $index) - { - $columns = $index->getColumns(); - $name = new Identifier($name); - - if (count($columns) === 0) { - throw new InvalidArgumentException("Incomplete definition. 'columns' required."); - } - - return 'CONSTRAINT ' . $name->getQuotedName($this) . ' UNIQUE (' - . $this->getIndexFieldDeclarationListSQL($index) - . ')' . $this->getPartialIndexSQL($index); - } - - /** - * Obtains DBMS specific SQL code portion needed to set an index - * declaration to be used in statements like CREATE TABLE. - * - * @param string $name The name of the index. - * @param Index $index The index definition. - * - * @return string DBMS specific SQL code portion needed to set an index. - * - * @throws InvalidArgumentException - */ - public function getIndexDeclarationSQL($name, Index $index) - { - $columns = $index->getColumns(); - $name = new Identifier($name); - - if (count($columns) === 0) { - throw new InvalidArgumentException("Incomplete definition. 'columns' required."); - } - - return $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name->getQuotedName($this) . ' (' - . $this->getIndexFieldDeclarationListSQL($index) - . ')' . $this->getPartialIndexSQL($index); - } - - /** - * Obtains 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. - * - * @param mixed[] $columnDef - * - * @return string - */ - public function getCustomTypeDeclarationSQL(array $columnDef) - { - return $columnDef['columnDefinition']; - } - - /** - * Obtains DBMS specific SQL code portion needed to set an index - * declaration to be used in statements like CREATE TABLE. - * - * @param mixed[]|Index $columnsOrIndex array declaration is deprecated, prefer passing Index to this method - */ - public function getIndexFieldDeclarationListSQL($columnsOrIndex) : string - { - if ($columnsOrIndex instanceof Index) { - return implode(', ', $columnsOrIndex->getQuotedColumns($this)); - } - - if (! is_array($columnsOrIndex)) { - throw new InvalidArgumentException('Fields argument should be an Index or array.'); - } - - $ret = []; - - foreach ($columnsOrIndex as $column => $definition) { - if (is_array($definition)) { - $ret[] = $column; - } else { - $ret[] = $definition; - } - } - - return implode(', ', $ret); - } - - /** - * Returns 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; - } - - /** - * 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. - * - * @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; - } - - /** - * Returns the FOREIGN KEY query section dealing with non-standard options - * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... - * - * @param ForeignKeyConstraint $foreignKey The 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 the given referential action in uppercase if valid, otherwise throws an exception. - * - * @param string $action The foreign key referential action. - * - * @return string - * - * @throws InvalidArgumentException If unknown referential action given. - */ - public function getForeignKeyReferentialActionSQL($action) - { - $upper = strtoupper($action); - switch ($upper) { - case 'CASCADE': - case 'SET NULL': - case 'NO ACTION': - case 'RESTRICT': - case 'SET DEFAULT': - return $upper; - default: - throw new InvalidArgumentException('Invalid foreign key action: ' . $upper); - } - } - - /** - * Obtains DBMS specific SQL code portion needed to set the FOREIGN KEY constraint - * of a field declaration to be used in statements like CREATE TABLE. - * - * @return string - * - * @throws InvalidArgumentException - */ - public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint $foreignKey) - { - $sql = ''; - if (strlen($foreignKey->getName())) { - $sql .= 'CONSTRAINT ' . $foreignKey->getQuotedName($this) . ' '; - } - $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."); - } - - return $sql . implode(', ', $foreignKey->getQuotedLocalColumns($this)) - . ') REFERENCES ' - . $foreignKey->getQuotedForeignTableName($this) . ' (' - . implode(', ', $foreignKey->getQuotedForeignColumns($this)) . ')'; - } - - /** - * Obtains 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'; - } - - /** - * Obtains 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 The 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 ''; - } - - /** - * Obtains 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 The 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 $this->supportsColumnCollation() ? 'COLLATE ' . $collation : ''; - } - - /** - * Whether the platform prefers sequences for ID generation. - * Subclasses should override this method to return TRUE if they prefer sequences. - * - * @return bool - */ - 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 bool - */ - 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). - * - * Note: if the input is not a boolean the original input might be returned. - * - * There are two contexts when converting booleans: Literals and Prepared Statements. - * This method should handle the literal case - * - * @param mixed $item A boolean or an array of them. - * - * @return mixed A boolean database value or an array of them. - */ - public function convertBooleans($item) - { - if (is_array($item)) { - foreach ($item as $k => $value) { - if (! is_bool($value)) { - continue; - } - - $item[$k] = (int) $value; - } - } elseif (is_bool($item)) { - $item = (int) $item; - } - - return $item; - } - - /** - * Some platforms have boolean literals that needs to be correctly converted - * - * The default conversion tries to convert value into bool "(bool)$item" - * - * @param mixed $item - * - * @return bool|null - */ - public function convertFromBoolean($item) - { - return $item === null ? null: (bool) $item; - } - - /** - * This method should handle the prepared statements case. When there is no - * distinction, it's OK to use the same method. - * - * Note: if the input is not a boolean the original input might be returned. - * - * @param mixed $item A boolean or an array of them. - * - * @return mixed A boolean database value or an array of them. - */ - public function convertBooleansToDatabaseValue($item) - { - return $this->convertBooleans($item); - } - - /** - * Returns the SQL specific for the platform to get the current date. - * - * @return string - */ - public function getCurrentDateSQL() - { - return 'CURRENT_DATE'; - } - - /** - * Returns the SQL specific for the platform to get the current time. - * - * @return string - */ - public function getCurrentTimeSQL() - { - return 'CURRENT_TIME'; - } - - /** - * Returns the SQL specific for the platform to get the current timestamp - * - * @return string - */ - public function getCurrentTimestampSQL() - { - return 'CURRENT_TIMESTAMP'; - } - - /** - * Returns the SQL for a given transaction isolation level Connection constant. - * - * @param int $level - * - * @return string - * - * @throws InvalidArgumentException - */ - protected function _getTransactionIsolationLevelSQL($level) - { - switch ($level) { - case TransactionIsolationLevel::READ_UNCOMMITTED: - return 'READ UNCOMMITTED'; - case TransactionIsolationLevel::READ_COMMITTED: - return 'READ COMMITTED'; - case TransactionIsolationLevel::REPEATABLE_READ: - return 'REPEATABLE READ'; - case TransactionIsolationLevel::SERIALIZABLE: - return 'SERIALIZABLE'; - default: - throw new InvalidArgumentException('Invalid isolation level:' . $level); - } - } - - /** - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getListDatabasesSQL() - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Returns the SQL statement for retrieving the namespaces defined in the database. - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getListNamespacesSQL() - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * @param string $database - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getListSequencesSQL($database) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * @param string $table - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getListTableConstraintsSQL($table) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * @param string $table - * @param string|null $database - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getListTableColumnsSQL($table, $database = null) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getListTablesSQL() - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getListUsersSQL() - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Returns the SQL to list all views of a database or user. - * - * @param string $database - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getListViewsSQL($database) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Returns the list of indexes for the current database. - * - * The current database parameter is optional but will always be passed - * when using the SchemaManager API and is the database the given table is in. - * - * Attention: Some platforms only support currentDatabase when they - * are connected with that database. Cross-database information schema - * requests may be impossible. - * - * @param string $table - * @param string $currentDatabase - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getListTableIndexesSQL($table, $currentDatabase = null) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * @param string $table - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getListTableForeignKeysSQL($table) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * @param string $name - * @param string $sql - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getCreateViewSQL($name, $sql) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * @param string $name - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDropViewSQL($name) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Returns the SQL snippet to drop an existing sequence. - * - * @param Sequence|string $sequence - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDropSequenceSQL($sequence) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * @param string $sequenceName - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getSequenceNextValSQL($sequenceName) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Returns the SQL to create a new database. - * - * @param string $database The name of the database that should be created. - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getCreateDatabaseSQL($database) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Returns the SQL to set the transaction isolation level. - * - * @param int $level - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getSetTransactionIsolationSQL($level) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Obtains DBMS specific SQL to be used to create datetime fields in - * statements like CREATE TABLE. - * - * @param mixed[] $fieldDeclaration - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Obtains DBMS specific SQL to be used to create datetime with timezone offset fields. - * - * @param mixed[] $fieldDeclaration - * - * @return string - */ - public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) - { - return $this->getDateTimeTypeDeclarationSQL($fieldDeclaration); - } - - /** - * Obtains DBMS specific SQL to be used to create date fields in statements - * like CREATE TABLE. - * - * @param mixed[] $fieldDeclaration - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDateTypeDeclarationSQL(array $fieldDeclaration) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Obtains DBMS specific SQL to be used to create time fields in statements - * like CREATE TABLE. - * - * @param mixed[] $fieldDeclaration - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getTimeTypeDeclarationSQL(array $fieldDeclaration) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * @param mixed[] $fieldDeclaration - * - * @return string - */ - public function getFloatDeclarationSQL(array $fieldDeclaration) - { - return 'DOUBLE PRECISION'; - } - - /** - * Gets the default transaction isolation level of the platform. - * - * @see TransactionIsolationLevel - * - * @return int The default isolation level. - */ - public function getDefaultTransactionIsolationLevel() - { - return TransactionIsolationLevel::READ_COMMITTED; - } - - /* supports*() methods */ - - /** - * Whether the platform supports sequences. - * - * @return bool - */ - public function supportsSequences() - { - return false; - } - - /** - * Whether the platform supports identity columns. - * - * Identity columns are columns that receive an auto-generated value from the - * database on insert of a row. - * - * @return bool - */ - public function supportsIdentityColumns() - { - return false; - } - - /** - * Whether the platform emulates identity columns through sequences. - * - * Some platforms that do not support identity columns natively - * but support sequences can emulate identity columns by using - * sequences. - * - * @return bool - */ - public function usesSequenceEmulatedIdentityColumns() - { - return false; - } - - /** - * Returns the name of the sequence for a particular identity column in a particular table. - * - * @see usesSequenceEmulatedIdentityColumns - * - * @param string $tableName The name of the table to return the sequence name for. - * @param string $columnName The name of the identity column in the table to return the sequence name for. - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getIdentitySequenceName($tableName, $columnName) - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Whether the platform supports indexes. - * - * @return bool - */ - public function supportsIndexes() - { - return true; - } - - /** - * Whether the platform supports partial indexes. - * - * @return bool - */ - public function supportsPartialIndexes() - { - return false; - } - - /** - * Whether the platform supports indexes with column length definitions. - */ - public function supportsColumnLengthIndexes() : bool - { - return false; - } - - /** - * Whether the platform supports altering tables. - * - * @return bool - */ - public function supportsAlterTable() - { - return true; - } - - /** - * Whether the platform supports transactions. - * - * @return bool - */ - public function supportsTransactions() - { - return true; - } - - /** - * Whether the platform supports savepoints. - * - * @return bool - */ - public function supportsSavepoints() - { - return true; - } - - /** - * Whether the platform supports releasing savepoints. - * - * @return bool - */ - public function supportsReleaseSavepoints() - { - return $this->supportsSavepoints(); - } - - /** - * Whether the platform supports primary key constraints. - * - * @return bool - */ - public function supportsPrimaryConstraints() - { - return true; - } - - /** - * Whether the platform supports foreign key constraints. - * - * @return bool - */ - public function supportsForeignKeyConstraints() - { - return true; - } - - /** - * Whether this platform supports onUpdate in foreign key constraints. - * - * @return bool - */ - public function supportsForeignKeyOnUpdate() - { - return $this->supportsForeignKeyConstraints(); - } - - /** - * Whether the platform supports database schemas. - * - * @return bool - */ - public function supportsSchemas() - { - return false; - } - - /** - * Whether this platform can emulate schemas. - * - * Platforms that either support or emulate schemas don't automatically - * filter a schema for the namespaced elements in {@link - * AbstractManager#createSchema}. - * - * @return bool - */ - public function canEmulateSchemas() - { - return false; - } - - /** - * Returns the default schema name. - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - public function getDefaultSchemaName() - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Whether this platform supports create database. - * - * 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 bool - */ - public function supportsGettingAffectedRows() - { - return true; - } - - /** - * Whether this platform support to add inline column comments as postfix. - * - * @return bool - */ - public function supportsInlineColumnComments() - { - return false; - } - - /** - * Whether this platform support the proprietary syntax "COMMENT ON asset". - * - * @return bool - */ - public function supportsCommentOnStatement() - { - return false; - } - - /** - * Does this platform have native guid type. - * - * @return bool - */ - public function hasNativeGuidType() - { - return false; - } - - /** - * Does this platform have native JSON type. - * - * @return bool - */ - public function hasNativeJsonType() - { - return false; - } - - /** - * @deprecated - * - * @todo Remove in 3.0 - */ - public function getIdentityColumnNullInsertSQL() - { - return ''; - } - - /** - * Whether this platform supports views. - * - * @return bool - */ - public function supportsViews() - { - return true; - } - - /** - * Does this platform support column collation? - * - * @return bool - */ - public function supportsColumnCollation() - { - return false; - } - - /** - * 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'; - } - - /** - * Adds an driver-specific LIMIT clause to the query. - * - * @param string $query - * @param int|null $limit - * @param int|null $offset - * - * @return string - * - * @throws DBALException - */ - final public function modifyLimitQuery($query, $limit, $offset = null) - { - if ($limit !== null) { - $limit = (int) $limit; - } - - $offset = (int) $offset; - - if ($offset < 0) { - throw new DBALException(sprintf( - 'Offset must be a positive integer or zero, %d given', - $offset - )); - } - - if ($offset > 0 && ! $this->supportsLimitOffset()) { - throw new DBALException(sprintf( - 'Platform %s does not support offset values in limit queries.', - $this->getName() - )); - } - - return $this->doModifyLimitQuery($query, $limit, $offset); - } - - /** - * Adds an platform-specific LIMIT clause to the query. - * - * @param string $query - * @param int|null $limit - * @param int|null $offset - * - * @return string - */ - protected function doModifyLimitQuery($query, $limit, $offset) - { - if ($limit !== null) { - $query .= ' LIMIT ' . $limit; - } - - if ($offset > 0) { - $query .= ' OFFSET ' . $offset; - } - - return $query; - } - - /** - * Whether the database platform support offsets in modify limit clauses. - * - * @return bool - */ - public function supportsLimitOffset() - { - return true; - } - - /** - * 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 $schemaElementName - * - * @return string - */ - public function fixSchemaElementName($schemaElementName) - { - return $schemaElementName; - } - - /** - * Maximum length of any given database identifier, like tables or column names. - * - * @return int - */ - public function getMaxIdentifierLength() - { - return 63; - } - - /** - * Returns the insert SQL for an empty insert statement. - * - * @param string $tableName - * @param string $identifierColumnName - * - * @return string - */ - public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName) - { - return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (null)'; - } - - /** - * Generates 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) - { - $tableIdentifier = new Identifier($tableName); - - return 'TRUNCATE ' . $tableIdentifier->getQuotedName($this); - } - - /** - * This is for test reasons, many vendors have special requirements for dummy statements. - * - * @return string - */ - public function getDummySelectSQL() - { - $expression = func_num_args() > 0 ? func_get_arg(0) : '1'; - - return sprintf('SELECT %s', $expression); - } - - /** - * Returns the SQL to create a new savepoint. - * - * @param string $savepoint - * - * @return string - */ - public function createSavePoint($savepoint) - { - return 'SAVEPOINT ' . $savepoint; - } - - /** - * Returns the SQL to release a savepoint. - * - * @param string $savepoint - * - * @return string - */ - public function releaseSavePoint($savepoint) - { - return 'RELEASE SAVEPOINT ' . $savepoint; - } - - /** - * Returns the SQL to rollback a savepoint. - * - * @param string $savepoint - * - * @return string - */ - public function rollbackSavePoint($savepoint) - { - return 'ROLLBACK TO SAVEPOINT ' . $savepoint; - } - - /** - * Returns the keyword list instance of this platform. - * - * @return KeywordList - * - * @throws DBALException If no keyword list is specified. - */ - final public function getReservedKeywordsList() - { - // Check for an existing instantiation of the keywords class. - if ($this->_keywords) { - return $this->_keywords; - } - - $class = $this->getReservedKeywordsClass(); - $keywords = new $class(); - if (! $keywords instanceof KeywordList) { - throw DBALException::notSupported(__METHOD__); - } - - // Store the instance so it doesn't need to be generated on every request. - $this->_keywords = $keywords; - - return $keywords; - } - - /** - * Returns the class name of the reserved keywords list. - * - * @return string - * - * @throws DBALException If not supported on this platform. - */ - protected function getReservedKeywordsClass() - { - throw DBALException::notSupported(__METHOD__); - } - - /** - * Quotes a literal string. - * This method is NOT meant to fix SQL injections! - * It is only meant to escape this platform's string literal - * quote character inside the given literal string. - * - * @param string $str The literal string to be quoted. - * - * @return string The quoted literal string. - */ - public function quoteStringLiteral($str) - { - $c = $this->getStringLiteralQuoteCharacter(); - - return $c . str_replace($c, $c . $c, $str) . $c; - } - - /** - * Gets the character used for string literal quoting. - * - * @return string - */ - public function getStringLiteralQuoteCharacter() - { - return "'"; - } - - /** - * Escapes metacharacters in a string intended to be used with a LIKE - * operator. - * - * @param string $inputString a literal, unquoted string - * @param string $escapeChar should be reused by the caller in the LIKE - * expression. - */ - final public function escapeStringForLike(string $inputString, string $escapeChar) : string - { - return preg_replace( - '~([' . preg_quote($this->getLikeWildcardCharacters() . $escapeChar, '~') . '])~u', - addcslashes($escapeChar, '\\') . '$1', - $inputString - ); - } - - protected function getLikeWildcardCharacters() : string - { - return '%_'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DB2Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DB2Platform.php deleted file mode 100644 index 25d4163..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DB2Platform.php +++ /dev/null @@ -1,916 +0,0 @@ -getCharMaxLength(); - } - - return parent::getVarcharTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - public function getBlobTypeDeclarationSQL(array $field) - { - // todo blob(n) with $field['length']; - return 'BLOB(1M)'; - } - - /** - * {@inheritDoc} - */ - public function initializeDoctrineTypeMappings() - { - $this->doctrineTypeMapping = [ - 'smallint' => 'smallint', - 'bigint' => 'bigint', - 'integer' => 'integer', - 'time' => 'time', - 'date' => 'date', - 'varchar' => 'string', - 'character' => 'string', - 'varbinary' => 'binary', - 'binary' => 'binary', - 'clob' => 'text', - 'blob' => 'blob', - 'decimal' => 'decimal', - 'double' => 'float', - 'real' => 'float', - 'timestamp' => 'datetime', - ]; - } - - /** - * {@inheritdoc} - */ - public function isCommentedDoctrineType(Type $doctrineType) - { - if ($doctrineType->getName() === Types::BOOLEAN) { - // We require a commented boolean type in order to distinguish between boolean and smallint - // as both (have to) map to the same native type. - return true; - } - - return parent::isCommentedDoctrineType($doctrineType); - } - - /** - * {@inheritDoc} - */ - protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) - { - return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(254)') - : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); - } - - /** - * {@inheritdoc} - */ - protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) - { - return $this->getVarcharTypeDeclarationSQLSnippet($length, $fixed) . ' FOR BIT DATA'; - } - - /** - * {@inheritDoc} - */ - public function getClobTypeDeclarationSQL(array $field) - { - // todo clob(n) with $field['length']; - return 'CLOB(1M)'; - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'db2'; - } - - /** - * {@inheritDoc} - */ - public function getBooleanTypeDeclarationSQL(array $columnDef) - { - return 'SMALLINT'; - } - - /** - * {@inheritDoc} - */ - public function getIntegerTypeDeclarationSQL(array $columnDef) - { - return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); - } - - /** - * {@inheritDoc} - */ - public function getBigIntTypeDeclarationSQL(array $columnDef) - { - return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); - } - - /** - * {@inheritDoc} - */ - public function getSmallIntTypeDeclarationSQL(array $columnDef) - { - return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); - } - - /** - * {@inheritDoc} - */ - protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) - { - $autoinc = ''; - if (! empty($columnDef['autoincrement'])) { - $autoinc = ' GENERATED BY DEFAULT AS IDENTITY'; - } - - return $autoinc; - } - - /** - * {@inheritdoc} - */ - public function getBitAndComparisonExpression($value1, $value2) - { - return 'BITAND(' . $value1 . ', ' . $value2 . ')'; - } - - /** - * {@inheritdoc} - */ - public function getBitOrComparisonExpression($value1, $value2) - { - return 'BITOR(' . $value1 . ', ' . $value2 . ')'; - } - - /** - * {@inheritdoc} - */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) - { - switch ($unit) { - case DateIntervalUnit::WEEK: - $interval *= 7; - $unit = DateIntervalUnit::DAY; - break; - - case DateIntervalUnit::QUARTER: - $interval *= 3; - $unit = DateIntervalUnit::MONTH; - break; - } - - return $date . ' ' . $operator . ' ' . $interval . ' ' . $unit; - } - - /** - * {@inheritdoc} - */ - public function getDateDiffExpression($date1, $date2) - { - return 'DAYS(' . $date1 . ') - DAYS(' . $date2 . ')'; - } - - /** - * {@inheritDoc} - */ - public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) - { - if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] === true) { - return 'TIMESTAMP(0) WITH DEFAULT'; - } - - return 'TIMESTAMP(0)'; - } - - /** - * {@inheritDoc} - */ - public function getDateTypeDeclarationSQL(array $fieldDeclaration) - { - return 'DATE'; - } - - /** - * {@inheritDoc} - */ - public function getTimeTypeDeclarationSQL(array $fieldDeclaration) - { - return 'TIME'; - } - - /** - * {@inheritdoc} - */ - public function getTruncateTableSQL($tableName, $cascade = false) - { - $tableIdentifier = new Identifier($tableName); - - return 'TRUNCATE ' . $tableIdentifier->getQuotedName($this) . ' IMMEDIATE'; - } - - /** - * This code fragment is originally from the Zend_Db_Adapter_Db2 class, but has been edited. - * - * @param string $table - * @param string $database - * - * @return string - */ - public function getListTableColumnsSQL($table, $database = null) - { - $table = $this->quoteStringLiteral($table); - - // We do the funky subquery and join syscat.columns.default this crazy way because - // as of db2 v10, the column is CLOB(64k) and the distinct operator won't allow a CLOB, - // it wants shorter stuff like a varchar. - return " - SELECT - cols.default, - subq.* - FROM ( - SELECT DISTINCT - c.tabschema, - c.tabname, - c.colname, - c.colno, - c.typename, - c.nulls, - c.length, - c.scale, - c.identity, - tc.type AS tabconsttype, - c.remarks AS comment, - k.colseq, - CASE - WHEN c.generated = 'D' THEN 1 - ELSE 0 - END AS autoincrement - 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 - ) subq - JOIN syscat.columns cols - ON subq.tabschema = cols.tabschema - AND subq.tabname = cols.tabname - AND subq.colno = cols.colno - ORDER BY subq.colno - '; - } - - /** - * {@inheritDoc} - */ - public function getListTablesSQL() - { - return "SELECT NAME FROM SYSIBM.SYSTABLES WHERE TYPE = 'T'"; - } - - /** - * {@inheritDoc} - */ - public function getListViewsSQL($database) - { - return 'SELECT NAME, TEXT FROM SYSIBM.SYSVIEWS'; - } - - /** - * {@inheritDoc} - */ - public function getListTableIndexesSQL($table, $currentDatabase = null) - { - $table = $this->quoteStringLiteral($table); - - return "SELECT idx.INDNAME AS key_name, - idxcol.COLNAME AS column_name, - CASE - WHEN idx.UNIQUERULE = 'P' THEN 1 - ELSE 0 - END AS primary, - CASE - WHEN idx.UNIQUERULE = 'D' THEN 1 - ELSE 0 - END AS non_unique - FROM SYSCAT.INDEXES AS idx - JOIN SYSCAT.INDEXCOLUSE AS idxcol - ON idx.INDSCHEMA = idxcol.INDSCHEMA AND idx.INDNAME = idxcol.INDNAME - WHERE idx.TABNAME = UPPER(" . $table . ') - ORDER BY idxcol.COLSEQ ASC'; - } - - /** - * {@inheritDoc} - */ - public function getListTableForeignKeysSQL($table) - { - $table = $this->quoteStringLiteral($table); - - return "SELECT fkcol.COLNAME AS local_column, - fk.REFTABNAME AS foreign_table, - pkcol.COLNAME AS foreign_column, - fk.CONSTNAME AS index_name, - CASE - WHEN fk.UPDATERULE = 'R' THEN 'RESTRICT' - ELSE NULL - END AS on_update, - CASE - WHEN fk.DELETERULE = 'C' THEN 'CASCADE' - WHEN fk.DELETERULE = 'N' THEN 'SET NULL' - WHEN fk.DELETERULE = 'R' THEN 'RESTRICT' - ELSE NULL - END AS on_delete - FROM SYSCAT.REFERENCES AS fk - JOIN SYSCAT.KEYCOLUSE AS fkcol - ON fk.CONSTNAME = fkcol.CONSTNAME - AND fk.TABSCHEMA = fkcol.TABSCHEMA - AND fk.TABNAME = fkcol.TABNAME - JOIN SYSCAT.KEYCOLUSE AS pkcol - ON fk.REFKEYNAME = pkcol.CONSTNAME - AND fk.REFTABSCHEMA = pkcol.TABSCHEMA - AND fk.REFTABNAME = pkcol.TABNAME - WHERE fk.TABNAME = UPPER(" . $table . ') - ORDER BY fkcol.COLSEQ ASC'; - } - - /** - * {@inheritDoc} - */ - public function getCreateViewSQL($name, $sql) - { - return 'CREATE VIEW ' . $name . ' AS ' . $sql; - } - - /** - * {@inheritDoc} - */ - public function getDropViewSQL($name) - { - return 'DROP VIEW ' . $name; - } - - /** - * {@inheritDoc} - */ - public function getCreateDatabaseSQL($database) - { - return 'CREATE DATABASE ' . $database; - } - - /** - * {@inheritDoc} - */ - public function getDropDatabaseSQL($database) - { - return 'DROP DATABASE ' . $database; - } - - /** - * {@inheritDoc} - */ - public function supportsCreateDropDatabase() - { - return false; - } - - /** - * {@inheritDoc} - */ - public function supportsReleaseSavepoints() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function supportsCommentOnStatement() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function getCurrentDateSQL() - { - return 'CURRENT DATE'; - } - - /** - * {@inheritDoc} - */ - public function getCurrentTimeSQL() - { - return 'CURRENT TIME'; - } - - /** - * {@inheritDoc} - */ - public function getCurrentTimestampSQL() - { - return 'CURRENT TIMESTAMP'; - } - - /** - * {@inheritDoc} - */ - public function getIndexDeclarationSQL($name, Index $index) - { - // Index declaration in statements like CREATE TABLE is not supported. - throw DBALException::notSupported(__METHOD__); - } - - /** - * {@inheritDoc} - */ - protected function _getCreateTableSQL($tableName, array $columns, array $options = []) - { - $indexes = []; - if (isset($options['indexes'])) { - $indexes = $options['indexes']; - } - $options['indexes'] = []; - - $sqls = parent::_getCreateTableSQL($tableName, $columns, $options); - - foreach ($indexes as $definition) { - $sqls[] = $this->getCreateIndexSQL($definition, $tableName); - } - - return $sqls; - } - - /** - * {@inheritDoc} - */ - public function getAlterTableSQL(TableDiff $diff) - { - $sql = []; - $columnSql = []; - $commentsSQL = []; - - $queryParts = []; - foreach ($diff->addedColumns as $column) { - if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { - continue; - } - - $columnDef = $column->toArray(); - $queryPart = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); - - // Adding non-nullable columns to a table requires a default value to be specified. - if (! empty($columnDef['notnull']) && - ! isset($columnDef['default']) && - empty($columnDef['autoincrement']) - ) { - $queryPart .= ' WITH DEFAULT'; - } - - $queryParts[] = $queryPart; - - $comment = $this->getColumnComment($column); - - if ($comment === null || $comment === '') { - continue; - } - - $commentsSQL[] = $this->getCommentOnColumnSQL( - $diff->getName($this)->getQuotedName($this), - $column->getQuotedName($this), - $comment - ); - } - - foreach ($diff->removedColumns as $column) { - if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { - continue; - } - - $queryParts[] = 'DROP COLUMN ' . $column->getQuotedName($this); - } - - foreach ($diff->changedColumns as $columnDiff) { - if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { - continue; - } - - if ($columnDiff->hasChanged('comment')) { - $commentsSQL[] = $this->getCommentOnColumnSQL( - $diff->getName($this)->getQuotedName($this), - $columnDiff->column->getQuotedName($this), - $this->getColumnComment($columnDiff->column) - ); - - if (count($columnDiff->changedProperties) === 1) { - continue; - } - } - - $this->gatherAlterColumnSQL($diff->getName($this), $columnDiff, $sql, $queryParts); - } - - foreach ($diff->renamedColumns as $oldColumnName => $column) { - if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { - continue; - } - - $oldColumnName = new Identifier($oldColumnName); - - $queryParts[] = 'RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . - ' TO ' . $column->getQuotedName($this); - } - - $tableSql = []; - - if (! $this->onSchemaAlterTable($diff, $tableSql)) { - if (count($queryParts) > 0) { - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(' ', $queryParts); - } - - // Some table alteration operations require a table reorganization. - if (! empty($diff->removedColumns) || ! empty($diff->changedColumns)) { - $sql[] = "CALL SYSPROC.ADMIN_CMD ('REORG TABLE " . $diff->getName($this)->getQuotedName($this) . "')"; - } - - $sql = array_merge($sql, $commentsSQL); - - $newName = $diff->getNewName(); - - if ($newName !== false) { - $sql[] = sprintf( - 'RENAME TABLE %s TO %s', - $diff->getName($this)->getQuotedName($this), - $newName->getQuotedName($this) - ); - } - - $sql = array_merge( - $this->getPreAlterTableIndexForeignKeySQL($diff), - $sql, - $this->getPostAlterTableIndexForeignKeySQL($diff) - ); - } - - return array_merge($sql, $tableSql, $columnSql); - } - - /** - * Gathers the table alteration SQL for a given column diff. - * - * @param Identifier $table The table to gather the SQL for. - * @param ColumnDiff $columnDiff The column diff to evaluate. - * @param string[] $sql The sequence of table alteration statements to fill. - * @param mixed[] $queryParts The sequence of column alteration clauses to fill. - */ - private function gatherAlterColumnSQL(Identifier $table, ColumnDiff $columnDiff, array &$sql, array &$queryParts) - { - $alterColumnClauses = $this->getAlterColumnClausesSQL($columnDiff); - - if (empty($alterColumnClauses)) { - return; - } - - // If we have a single column alteration, we can append the clause to the main query. - if (count($alterColumnClauses) === 1) { - $queryParts[] = current($alterColumnClauses); - - return; - } - - // We have multiple alterations for the same column, - // so we need to trigger a complete ALTER TABLE statement - // for each ALTER COLUMN clause. - foreach ($alterColumnClauses as $alterColumnClause) { - $sql[] = 'ALTER TABLE ' . $table->getQuotedName($this) . ' ' . $alterColumnClause; - } - } - - /** - * Returns the ALTER COLUMN SQL clauses for altering a column described by the given column diff. - * - * @param ColumnDiff $columnDiff The column diff to evaluate. - * - * @return string[] - */ - private function getAlterColumnClausesSQL(ColumnDiff $columnDiff) - { - $column = $columnDiff->column->toArray(); - - $alterClause = 'ALTER COLUMN ' . $columnDiff->column->getQuotedName($this); - - if ($column['columnDefinition']) { - return [$alterClause . ' ' . $column['columnDefinition']]; - } - - $clauses = []; - - if ($columnDiff->hasChanged('type') || - $columnDiff->hasChanged('length') || - $columnDiff->hasChanged('precision') || - $columnDiff->hasChanged('scale') || - $columnDiff->hasChanged('fixed') - ) { - $clauses[] = $alterClause . ' SET DATA TYPE ' . $column['type']->getSQLDeclaration($column, $this); - } - - if ($columnDiff->hasChanged('notnull')) { - $clauses[] = $column['notnull'] ? $alterClause . ' SET NOT NULL' : $alterClause . ' DROP NOT NULL'; - } - - if ($columnDiff->hasChanged('default')) { - if (isset($column['default'])) { - $defaultClause = $this->getDefaultValueDeclarationSQL($column); - - if ($defaultClause) { - $clauses[] = $alterClause . ' SET' . $defaultClause; - } - } else { - $clauses[] = $alterClause . ' DROP DEFAULT'; - } - } - - return $clauses; - } - - /** - * {@inheritDoc} - */ - protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) - { - $sql = []; - $table = $diff->getName($this)->getQuotedName($this); - - foreach ($diff->removedIndexes as $remKey => $remIndex) { - foreach ($diff->addedIndexes as $addKey => $addIndex) { - if ($remIndex->getColumns() === $addIndex->getColumns()) { - if ($remIndex->isPrimary()) { - $sql[] = 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; - } elseif ($remIndex->isUnique()) { - $sql[] = 'ALTER TABLE ' . $table . ' DROP UNIQUE ' . $remIndex->getQuotedName($this); - } else { - $sql[] = $this->getDropIndexSQL($remIndex, $table); - } - - $sql[] = $this->getCreateIndexSQL($addIndex, $table); - - unset($diff->removedIndexes[$remKey], $diff->addedIndexes[$addKey]); - - break; - } - } - } - - $sql = array_merge($sql, parent::getPreAlterTableIndexForeignKeySQL($diff)); - - return $sql; - } - - /** - * {@inheritdoc} - */ - protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) - { - if (strpos($tableName, '.') !== false) { - [$schema] = explode('.', $tableName); - $oldIndexName = $schema . '.' . $oldIndexName; - } - - return ['RENAME INDEX ' . $oldIndexName . ' TO ' . $index->getQuotedName($this)]; - } - - /** - * {@inheritDoc} - */ - public function getDefaultValueDeclarationSQL($field) - { - if (! empty($field['autoincrement'])) { - return ''; - } - - if (isset($field['version']) && $field['version']) { - if ((string) $field['type'] !== 'DateTime') { - $field['default'] = '1'; - } - } - - return parent::getDefaultValueDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName) - { - return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (DEFAULT)'; - } - - /** - * {@inheritDoc} - */ - public function getCreateTemporaryTableSnippetSQL() - { - return 'DECLARE GLOBAL TEMPORARY TABLE'; - } - - /** - * {@inheritDoc} - */ - public function getTemporaryTableName($tableName) - { - return 'SESSION.' . $tableName; - } - - /** - * {@inheritDoc} - */ - protected function doModifyLimitQuery($query, $limit, $offset = null) - { - $where = []; - - if ($offset > 0) { - $where[] = sprintf('db22.DC_ROWNUM >= %d', $offset + 1); - } - - if ($limit !== null) { - $where[] = sprintf('db22.DC_ROWNUM <= %d', $offset + $limit); - } - - if (empty($where)) { - return $query; - } - - // Todo OVER() needs ORDER BY data! - return sprintf( - 'SELECT db22.* FROM (SELECT db21.*, ROW_NUMBER() OVER() AS DC_ROWNUM FROM (%s) db21) db22 WHERE %s', - $query, - implode(' AND ', $where) - ); - } - - /** - * {@inheritDoc} - */ - public function getLocateExpression($str, $substr, $startPos = false) - { - if ($startPos === false) { - return 'LOCATE(' . $substr . ', ' . $str . ')'; - } - - return 'LOCATE(' . $substr . ', ' . $str . ', ' . $startPos . ')'; - } - - /** - * {@inheritDoc} - */ - public function getSubstringExpression($value, $from, $length = null) - { - if ($length === null) { - return 'SUBSTR(' . $value . ', ' . $from . ')'; - } - - return 'SUBSTR(' . $value . ', ' . $from . ', ' . $length . ')'; - } - - /** - * {@inheritDoc} - */ - public function supportsIdentityColumns() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function prefersIdentityColumns() - { - return true; - } - - /** - * {@inheritDoc} - * - * DB2 returns all column names in SQL result sets in uppercase. - */ - public function getSQLResultCasing($column) - { - return strtoupper($column); - } - - /** - * {@inheritDoc} - */ - public function getForUpdateSQL() - { - return ' WITH RR USE AND KEEP UPDATE LOCKS'; - } - - /** - * {@inheritDoc} - */ - public function getDummySelectSQL() - { - $expression = func_num_args() > 0 ? func_get_arg(0) : '1'; - - return sprintf('SELECT %s FROM sysibm.sysdummy1', $expression); - } - - /** - * {@inheritDoc} - * - * 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. - */ - public function supportsSavepoints() - { - return false; - } - - /** - * {@inheritDoc} - */ - protected function getReservedKeywordsClass() - { - return Keywords\DB2Keywords::class; - } - - public function getListTableCommentsSQL(string $table) : string - { - return sprintf( - <<<'SQL' -SELECT REMARKS - FROM SYSIBM.SYSTABLES - WHERE NAME = UPPER( %s ) -SQL - , - $this->quoteStringLiteral($table) - ); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DateIntervalUnit.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DateIntervalUnit.php deleted file mode 100644 index ec97d0e..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/DateIntervalUnit.php +++ /dev/null @@ -1,28 +0,0 @@ -_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) - { - $autoinc = ''; - if (! empty($columnDef['autoincrement'])) { - $autoinc = ' AUTO_INCREMENT'; - } - - return $autoinc; - } - - /** - * {@inheritDoc} - */ - public function getBigIntTypeDeclarationSQL(array $field) - { - return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - public function getSmallIntTypeDeclarationSQL(array $field) - { - return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) - { - return $length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'; - } - - /** - * {@inheritdoc} - */ - protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) - { - return 'VARBINARY(' . ($length ?: 255) . ')'; - } - - /** - * {@inheritDoc} - */ - protected function initializeDoctrineTypeMappings() - { - $this->doctrineTypeMapping = [ - 'boolean' => 'boolean', - 'varchar' => 'string', - 'varbinary' => 'binary', - 'integer' => 'integer', - 'blob' => 'blob', - 'decimal' => 'decimal', - 'datetime' => 'datetime', - 'date' => 'date', - 'time' => 'time', - 'text' => 'text', - 'timestamp' => 'datetime', - 'double' => 'float', - 'bigint' => 'bigint', - ]; - } - - /** - * {@inheritDoc} - */ - public function getClobTypeDeclarationSQL(array $field) - { - return 'TEXT'; - } - - /** - * {@inheritDoc} - */ - public function getBlobTypeDeclarationSQL(array $field) - { - return 'BLOB'; - } - - /** - * {@inheritDoc} - */ - public function getCreateDatabaseSQL($name) - { - return 'CREATE DATABASE ' . $name; - } - - /** - * {@inheritDoc} - */ - public function getDropDatabaseSQL($name) - { - return 'DROP DATABASE ' . $name; - } - - /** - * {@inheritDoc} - */ - protected function _getCreateTableSQL($tableName, array $columns, array $options = []) - { - $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 . ') '; - $query .= $this->buildTableOptions($options); - $query .= $this->buildPartitionOptions($options); - - $sql = [$query]; - - if (isset($options['foreignKeys'])) { - foreach ((array) $options['foreignKeys'] as $definition) { - $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); - } - } - - return $sql; - } - - /** - * Build SQL for table options - * - * @param mixed[] $options - * - * @return string - */ - private function buildTableOptions(array $options) - { - if (isset($options['table_options'])) { - return $options['table_options']; - } - - $tableOptions = []; - - // Collate - if (! isset($options['collate'])) { - $options['collate'] = 'utf8_unicode_ci'; - } - - $tableOptions[] = sprintf('COLLATE %s', $options['collate']); - - // Engine - if (! isset($options['engine'])) { - $options['engine'] = 'InnoDB'; - } - - $tableOptions[] = sprintf('ENGINE = %s', $options['engine']); - - // Auto increment - if (isset($options['auto_increment'])) { - $tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']); - } - - // Comment - if (isset($options['comment'])) { - $comment = trim($options['comment'], " '"); - - $tableOptions[] = sprintf('COMMENT = %s ', $this->quoteStringLiteral($comment)); - } - - // Row format - if (isset($options['row_format'])) { - $tableOptions[] = sprintf('ROW_FORMAT = %s', $options['row_format']); - } - - return implode(' ', $tableOptions); - } - - /** - * Build SQL for partition options. - * - * @param mixed[] $options - * - * @return string - */ - private function buildPartitionOptions(array $options) - { - return isset($options['partition_options']) - ? ' ' . $options['partition_options'] - : ''; - } - - /** - * {@inheritDoc} - */ - public function getListDatabasesSQL() - { - return "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE CATALOG_NAME='LOCAL'"; - } - - /** - * {@inheritDoc} - */ - protected function getReservedKeywordsClass() - { - return Keywords\DrizzleKeywords::class; - } - - /** - * {@inheritDoc} - */ - public function getListTablesSQL() - { - return "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE' AND TABLE_SCHEMA=DATABASE()"; - } - - /** - * {@inheritDoc} - */ - public function getListTableColumnsSQL($table, $database = null) - { - if ($database) { - $databaseSQL = $this->quoteStringLiteral($database); - } else { - $databaseSQL = 'DATABASE()'; - } - - return 'SELECT COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT, IS_NULLABLE, IS_AUTO_INCREMENT, CHARACTER_MAXIMUM_LENGTH, COLUMN_DEFAULT,' . - ' NUMERIC_PRECISION, NUMERIC_SCALE, COLLATION_NAME' . - ' FROM DATA_DICTIONARY.COLUMNS' . - ' WHERE TABLE_SCHEMA=' . $databaseSQL . ' AND TABLE_NAME = ' . $this->quoteStringLiteral($table); - } - - /** - * {@inheritDoc} - */ - public function getListTableForeignKeysSQL($table, $database = null) - { - if ($database) { - $databaseSQL = $this->quoteStringLiteral($database); - } else { - $databaseSQL = 'DATABASE()'; - } - - return 'SELECT CONSTRAINT_NAME, CONSTRAINT_COLUMNS, REFERENCED_TABLE_NAME, REFERENCED_TABLE_COLUMNS, UPDATE_RULE, DELETE_RULE' . - ' FROM DATA_DICTIONARY.FOREIGN_KEYS' . - ' WHERE CONSTRAINT_SCHEMA=' . $databaseSQL . ' AND CONSTRAINT_TABLE=' . $this->quoteStringLiteral($table); - } - - /** - * {@inheritDoc} - */ - public function getListTableIndexesSQL($table, $database = null) - { - if ($database) { - $databaseSQL = $this->quoteStringLiteral($database); - } else { - $databaseSQL = 'DATABASE()'; - } - - return "SELECT INDEX_NAME AS 'key_name', COLUMN_NAME AS 'column_name', IS_USED_IN_PRIMARY AS 'primary', IS_UNIQUE=0 AS 'non_unique'" . - ' FROM DATA_DICTIONARY.INDEX_PARTS' . - ' WHERE TABLE_SCHEMA=' . $databaseSQL . ' AND TABLE_NAME=' . $this->quoteStringLiteral($table); - } - - /** - * {@inheritDoc} - */ - public function prefersIdentityColumns() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function supportsIdentityColumns() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function supportsInlineColumnComments() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function supportsViews() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function supportsColumnCollation() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function getDropIndexSQL($index, $table = null) - { - if ($index instanceof Index) { - $indexName = $index->getQuotedName($this); - } elseif (is_string($index)) { - $indexName = $index; - } else { - throw new InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); - } - - if ($table instanceof Table) { - $table = $table->getQuotedName($this); - } elseif (! is_string($table)) { - throw new InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); - } - - if ($index instanceof Index && $index->isPrimary()) { - // drizzle primary keys are always named "PRIMARY", - // so we cannot use them in statements because of them being keyword. - return $this->getDropPrimaryKeySQL($table); - } - - return 'DROP INDEX ' . $indexName . ' ON ' . $table; - } - - /** - * {@inheritDoc} - */ - protected function getDropPrimaryKeySQL($table) - { - return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; - } - - /** - * {@inheritDoc} - */ - public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) - { - if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] === true) { - return 'TIMESTAMP'; - } - - return 'DATETIME'; - } - - /** - * {@inheritDoc} - */ - public function getTimeTypeDeclarationSQL(array $fieldDeclaration) - { - return 'TIME'; - } - - /** - * {@inheritDoc} - */ - public function getDateTypeDeclarationSQL(array $fieldDeclaration) - { - return 'DATE'; - } - - /** - * {@inheritDoc} - */ - public function getAlterTableSQL(TableDiff $diff) - { - $columnSql = []; - $queryParts = []; - - $newName = $diff->getNewName(); - - if ($newName !== false) { - $queryParts[] = 'RENAME TO ' . $newName->getQuotedName($this); - } - - foreach ($diff->addedColumns as $column) { - if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { - continue; - } - - $columnArray = $column->toArray(); - $columnArray['comment'] = $this->getColumnComment($column); - $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); - } - - foreach ($diff->removedColumns as $column) { - if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { - continue; - } - - $queryParts[] = 'DROP ' . $column->getQuotedName($this); - } - - foreach ($diff->changedColumns as $columnDiff) { - if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { - continue; - } - - $column = $columnDiff->column; - $columnArray = $column->toArray(); - - // Do not generate column alteration clause if type is binary and only fixed property has changed. - // Drizzle only supports binary type columns with variable length. - // Avoids unnecessary table alteration statements. - if ($columnArray['type'] instanceof BinaryType && - $columnDiff->hasChanged('fixed') && - count($columnDiff->changedProperties) === 1 - ) { - continue; - } - - $columnArray['comment'] = $this->getColumnComment($column); - $queryParts[] = 'CHANGE ' . ($columnDiff->getOldColumnName()->getQuotedName($this)) . ' ' - . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); - } - - foreach ($diff->renamedColumns as $oldColumnName => $column) { - if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { - continue; - } - - $oldColumnName = new Identifier($oldColumnName); - - $columnArray = $column->toArray(); - $columnArray['comment'] = $this->getColumnComment($column); - $queryParts[] = 'CHANGE ' . $oldColumnName->getQuotedName($this) . ' ' - . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); - } - - $sql = []; - $tableSql = []; - - if (! $this->onSchemaAlterTable($diff, $tableSql)) { - if (count($queryParts) > 0) { - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(', ', $queryParts); - } - $sql = array_merge( - $this->getPreAlterTableIndexForeignKeySQL($diff), - $sql, - $this->getPostAlterTableIndexForeignKeySQL($diff) - ); - } - - return array_merge($sql, $tableSql, $columnSql); - } - - /** - * {@inheritDoc} - */ - public function getDropTemporaryTableSQL($table) - { - if ($table instanceof Table) { - $table = $table->getQuotedName($this); - } elseif (! is_string($table)) { - throw new InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); - } - - return 'DROP TEMPORARY TABLE ' . $table; - } - - /** - * {@inheritDoc} - */ - public function convertBooleans($item) - { - if (is_array($item)) { - foreach ($item as $key => $value) { - if (! is_bool($value) && ! is_numeric($value)) { - continue; - } - - $item[$key] = $value ? 'true' : 'false'; - } - } elseif (is_bool($item) || is_numeric($item)) { - $item = $item ? 'true' : 'false'; - } - - return $item; - } - - /** - * {@inheritDoc} - */ - public function getLocateExpression($str, $substr, $startPos = false) - { - if ($startPos === false) { - return 'LOCATE(' . $substr . ', ' . $str . ')'; - } - - return 'LOCATE(' . $substr . ', ' . $str . ', ' . $startPos . ')'; - } - - /** - * {@inheritDoc} - * - * @deprecated Use application-generated UUIDs instead - */ - public function getGuidExpression() - { - return 'UUID()'; - } - - /** - * {@inheritDoc} - */ - public function getRegexpExpression() - { - return 'RLIKE'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php deleted file mode 100644 index 8533f57..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php +++ /dev/null @@ -1,420 +0,0 @@ -keywords === null) { - $this->initializeKeywords(); - } - - return isset($this->keywords[strtoupper($word)]); - } - - /** - * @return void - */ - protected function initializeKeywords() - { - $this->keywords = array_flip(array_map('strtoupper', $this->getKeywords())); - } - - /** - * Returns the list of keywords. - * - * @return string[] - */ - abstract protected function getKeywords(); - - /** - * Returns the name of this keyword list. - * - * @return string - */ - abstract public function getName(); -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MariaDb102Keywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MariaDb102Keywords.php deleted file mode 100644 index 1b31c76..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/MariaDb102Keywords.php +++ /dev/null @@ -1,274 +0,0 @@ -keywordLists = $keywordLists; - } - - /** - * @return string[] - */ - public function getViolations() - { - return $this->violations; - } - - /** - * @param string $word - * - * @return string[] - */ - private function isReservedWord($word) - { - if ($word[0] === '`') { - $word = str_replace('`', '', $word); - } - - $keywordLists = []; - foreach ($this->keywordLists as $keywordList) { - if (! $keywordList->isKeyword($word)) { - continue; - } - - $keywordLists[] = $keywordList->getName(); - } - - return $keywordLists; - } - - /** - * @param string $asset - * @param string[] $violatedPlatforms - * - * @return void - */ - private function addViolation($asset, $violatedPlatforms) - { - if (! $violatedPlatforms) { - return; - } - - $this->violations[] = $asset . ' keyword violations: ' . implode(', ', $violatedPlatforms); - } - - /** - * {@inheritdoc} - */ - public function acceptColumn(Table $table, Column $column) - { - $this->addViolation( - 'Table ' . $table->getName() . ' column ' . $column->getName(), - $this->isReservedWord($column->getName()) - ); - } - - /** - * {@inheritdoc} - */ - public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) - { - } - - /** - * {@inheritdoc} - */ - public function acceptIndex(Table $table, Index $index) - { - } - - /** - * {@inheritdoc} - */ - public function acceptSchema(Schema $schema) - { - } - - /** - * {@inheritdoc} - */ - public function acceptSequence(Sequence $sequence) - { - } - - /** - * {@inheritdoc} - */ - public function acceptTable(Table $table) - { - $this->addViolation( - 'Table ' . $table->getName(), - $this->isReservedWord($table->getName()) - ); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere11Keywords.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere11Keywords.php deleted file mode 100644 index 09513c5..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/Keywords/SQLAnywhere11Keywords.php +++ /dev/null @@ -1,39 +0,0 @@ -doctrineTypeMapping['json'] = Types::JSON; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL57Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL57Platform.php deleted file mode 100644 index 1db7d66..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL57Platform.php +++ /dev/null @@ -1,71 +0,0 @@ -getQuotedName($this)]; - } - - /** - * {@inheritdoc} - */ - protected function getReservedKeywordsClass() - { - return Keywords\MySQL57Keywords::class; - } - - /** - * {@inheritdoc} - */ - protected function initializeDoctrineTypeMappings() - { - parent::initializeDoctrineTypeMappings(); - - $this->doctrineTypeMapping['json'] = Types::JSON; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL80Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL80Platform.php deleted file mode 100644 index f6d4be9..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySQL80Platform.php +++ /dev/null @@ -1,17 +0,0 @@ - 0) { - $query .= ' OFFSET ' . $offset; - } - } elseif ($offset > 0) { - // 2^64-1 is the maximum of unsigned BIGINT, the biggest limit possible - $query .= ' LIMIT 18446744073709551615 OFFSET ' . $offset; - } - - return $query; - } - - /** - * {@inheritDoc} - */ - public function getIdentifierQuoteCharacter() - { - return '`'; - } - - /** - * {@inheritDoc} - */ - public function getRegexpExpression() - { - return 'RLIKE'; - } - - /** - * {@inheritDoc} - * - * @deprecated Use application-generated UUIDs instead - */ - public function getGuidExpression() - { - return 'UUID()'; - } - - /** - * {@inheritDoc} - */ - public function getLocateExpression($str, $substr, $startPos = false) - { - if ($startPos === false) { - return 'LOCATE(' . $substr . ', ' . $str . ')'; - } - - return 'LOCATE(' . $substr . ', ' . $str . ', ' . $startPos . ')'; - } - - /** - * {@inheritDoc} - */ - public function getConcatExpression() - { - return sprintf('CONCAT(%s)', implode(', ', func_get_args())); - } - - /** - * {@inheritdoc} - */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) - { - $function = $operator === '+' ? 'DATE_ADD' : 'DATE_SUB'; - - return $function . '(' . $date . ', INTERVAL ' . $interval . ' ' . $unit . ')'; - } - - /** - * {@inheritDoc} - */ - public function getDateDiffExpression($date1, $date2) - { - return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; - } - - /** - * {@inheritDoc} - */ - public function getListDatabasesSQL() - { - return 'SHOW DATABASES'; - } - - /** - * {@inheritDoc} - */ - public function getListTableConstraintsSQL($table) - { - return 'SHOW INDEX FROM ' . $table; - } - - /** - * {@inheritDoc} - * - * Two approaches to listing the table indexes. The information_schema is - * preferred, because it doesn't cause problems with SQL keywords such as "order" or "table". - */ - public function getListTableIndexesSQL($table, $currentDatabase = null) - { - if ($currentDatabase) { - $currentDatabase = $this->quoteStringLiteral($currentDatabase); - $table = $this->quoteStringLiteral($table); - - return 'SELECT NON_UNIQUE AS Non_Unique, INDEX_NAME AS Key_name, COLUMN_NAME AS Column_Name,' . - ' SUB_PART AS Sub_Part, INDEX_TYPE AS Index_Type' . - ' FROM information_schema.STATISTICS WHERE TABLE_NAME = ' . $table . - ' AND TABLE_SCHEMA = ' . $currentDatabase . - ' ORDER BY SEQ_IN_INDEX ASC'; - } - - return 'SHOW INDEX FROM ' . $table; - } - - /** - * {@inheritDoc} - */ - public function getListViewsSQL($database) - { - $database = $this->quoteStringLiteral($database); - - return 'SELECT * FROM information_schema.VIEWS WHERE TABLE_SCHEMA = ' . $database; - } - - /** - * {@inheritDoc} - */ - public function getListTableForeignKeysSQL($table, $database = null) - { - $table = $this->quoteStringLiteral($table); - - if ($database !== null) { - $database = $this->quoteStringLiteral($database); - } - - $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; - - $databaseNameSql = $database ?? 'DATABASE()'; - - $sql .= ' AND k.table_schema = ' . $databaseNameSql . ' /*!50116 AND c.constraint_schema = ' . $databaseNameSql . ' */'; - $sql .= ' AND k.`REFERENCED_COLUMN_NAME` is not NULL'; - - return $sql; - } - - /** - * {@inheritDoc} - */ - public function getCreateViewSQL($name, $sql) - { - return 'CREATE VIEW ' . $name . ' AS ' . $sql; - } - - /** - * {@inheritDoc} - */ - public function getDropViewSQL($name) - { - return 'DROP VIEW ' . $name; - } - - /** - * {@inheritDoc} - */ - protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) - { - return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') - : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); - } - - /** - * {@inheritdoc} - */ - protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) - { - return $fixed ? 'BINARY(' . ($length ?: 255) . ')' : 'VARBINARY(' . ($length ?: 255) . ')'; - } - - /** - * Gets the SQL snippet used to declare a CLOB column type. - * TINYTEXT : 2 ^ 8 - 1 = 255 - * TEXT : 2 ^ 16 - 1 = 65535 - * MEDIUMTEXT : 2 ^ 24 - 1 = 16777215 - * LONGTEXT : 2 ^ 32 - 1 = 4294967295 - * - * {@inheritDoc} - */ - public function getClobTypeDeclarationSQL(array $field) - { - if (! empty($field['length']) && is_numeric($field['length'])) { - $length = $field['length']; - - if ($length <= static::LENGTH_LIMIT_TINYTEXT) { - return 'TINYTEXT'; - } - - if ($length <= static::LENGTH_LIMIT_TEXT) { - return 'TEXT'; - } - - if ($length <= static::LENGTH_LIMIT_MEDIUMTEXT) { - return 'MEDIUMTEXT'; - } - } - - return 'LONGTEXT'; - } - - /** - * {@inheritDoc} - */ - public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) - { - if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] === true) { - return 'TIMESTAMP'; - } - - return 'DATETIME'; - } - - /** - * {@inheritDoc} - */ - public function getDateTypeDeclarationSQL(array $fieldDeclaration) - { - return 'DATE'; - } - - /** - * {@inheritDoc} - */ - public function getTimeTypeDeclarationSQL(array $fieldDeclaration) - { - return 'TIME'; - } - - /** - * {@inheritDoc} - */ - 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. - * - * @deprecated Deprecated since version 2.5, Use {@link self::getColumnCollationDeclarationSQL()} instead. - * - * @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 $this->getColumnCollationDeclarationSQL($collation); - } - - /** - * {@inheritDoc} - * - * MySql prefers "autoincrement" identity columns since sequences can only - * be emulated with a table. - */ - public function prefersIdentityColumns() - { - return true; - } - - /** - * {@inheritDoc} - * - * MySql supports this through AUTO_INCREMENT columns. - */ - public function supportsIdentityColumns() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function supportsInlineColumnComments() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function supportsColumnCollation() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function getListTablesSQL() - { - return "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"; - } - - /** - * {@inheritDoc} - */ - public function getListTableColumnsSQL($table, $database = null) - { - $table = $this->quoteStringLiteral($table); - - if ($database) { - $database = $this->quoteStringLiteral($database); - } else { - $database = 'DATABASE()'; - } - - return 'SELECT COLUMN_NAME AS Field, COLUMN_TYPE AS Type, IS_NULLABLE AS `Null`, ' . - 'COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS Extra, COLUMN_COMMENT AS Comment, ' . - 'CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS Collation ' . - 'FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ' . $database . ' AND TABLE_NAME = ' . $table . - ' ORDER BY ORDINAL_POSITION ASC'; - } - - public function getListTableMetadataSQL(string $table, ?string $database = null) : string - { - return sprintf( - <<<'SQL' -SELECT ENGINE, AUTO_INCREMENT, TABLE_COLLATION, TABLE_COMMENT, CREATE_OPTIONS -FROM information_schema.TABLES -WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = %s AND TABLE_NAME = %s -SQL - , - $database ? $this->quoteStringLiteral($database) : 'DATABASE()', - $this->quoteStringLiteral($table) - ); - } - - /** - * {@inheritDoc} - */ - public function getCreateDatabaseSQL($name) - { - return 'CREATE DATABASE ' . $name; - } - - /** - * {@inheritDoc} - */ - public function getDropDatabaseSQL($name) - { - return 'DROP DATABASE ' . $name; - } - - /** - * {@inheritDoc} - */ - protected function _getCreateTableSQL($tableName, array $columns, array $options = []) - { - $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 . ') '; - $query .= $this->buildTableOptions($options); - $query .= $this->buildPartitionOptions($options); - - $sql = [$query]; - $engine = 'INNODB'; - - if (isset($options['engine'])) { - $engine = strtoupper(trim($options['engine'])); - } - - // Propagate foreign key constraints only for InnoDB. - if (isset($options['foreignKeys']) && $engine === 'INNODB') { - foreach ((array) $options['foreignKeys'] as $definition) { - $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); - } - } - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function getDefaultValueDeclarationSQL($field) - { - // Unset the default value if the given field definition does not allow default values. - if ($field['type'] instanceof TextType || $field['type'] instanceof BlobType) { - $field['default'] = null; - } - - return parent::getDefaultValueDeclarationSQL($field); - } - - /** - * Build SQL for table options - * - * @param mixed[] $options - * - * @return string - */ - private function buildTableOptions(array $options) - { - if (isset($options['table_options'])) { - return $options['table_options']; - } - - $tableOptions = []; - - // Charset - if (! isset($options['charset'])) { - $options['charset'] = 'utf8'; - } - - $tableOptions[] = sprintf('DEFAULT CHARACTER SET %s', $options['charset']); - - // Collate - if (! isset($options['collate'])) { - $options['collate'] = $options['charset'] . '_unicode_ci'; - } - - $tableOptions[] = $this->getColumnCollationDeclarationSQL($options['collate']); - - // Engine - if (! isset($options['engine'])) { - $options['engine'] = 'InnoDB'; - } - - $tableOptions[] = sprintf('ENGINE = %s', $options['engine']); - - // Auto increment - if (isset($options['auto_increment'])) { - $tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']); - } - - // Comment - if (isset($options['comment'])) { - $tableOptions[] = sprintf('COMMENT = %s ', $this->quoteStringLiteral($options['comment'])); - } - - // Row format - if (isset($options['row_format'])) { - $tableOptions[] = sprintf('ROW_FORMAT = %s', $options['row_format']); - } - - return implode(' ', $tableOptions); - } - - /** - * Build SQL for partition options. - * - * @param mixed[] $options - * - * @return string - */ - private function buildPartitionOptions(array $options) - { - return isset($options['partition_options']) - ? ' ' . $options['partition_options'] - : ''; - } - - /** - * {@inheritDoc} - */ - public function getAlterTableSQL(TableDiff $diff) - { - $columnSql = []; - $queryParts = []; - $newName = $diff->getNewName(); - - if ($newName !== false) { - $queryParts[] = 'RENAME TO ' . $newName->getQuotedName($this); - } - - foreach ($diff->addedColumns as $column) { - if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { - continue; - } - - $columnArray = $column->toArray(); - $columnArray['comment'] = $this->getColumnComment($column); - $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); - } - - foreach ($diff->removedColumns as $column) { - if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { - continue; - } - - $queryParts[] = 'DROP ' . $column->getQuotedName($this); - } - - foreach ($diff->changedColumns as $columnDiff) { - if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { - continue; - } - - $column = $columnDiff->column; - $columnArray = $column->toArray(); - - // Don't propagate default value changes for unsupported column types. - if ($columnDiff->hasChanged('default') && - count($columnDiff->changedProperties) === 1 && - ($columnArray['type'] instanceof TextType || $columnArray['type'] instanceof BlobType) - ) { - continue; - } - - $columnArray['comment'] = $this->getColumnComment($column); - $queryParts[] = 'CHANGE ' . ($columnDiff->getOldColumnName()->getQuotedName($this)) . ' ' - . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); - } - - foreach ($diff->renamedColumns as $oldColumnName => $column) { - if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { - continue; - } - - $oldColumnName = new Identifier($oldColumnName); - $columnArray = $column->toArray(); - $columnArray['comment'] = $this->getColumnComment($column); - $queryParts[] = 'CHANGE ' . $oldColumnName->getQuotedName($this) . ' ' - . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); - } - - if (isset($diff->addedIndexes['primary'])) { - $keyColumns = array_unique(array_values($diff->addedIndexes['primary']->getColumns())); - $queryParts[] = 'ADD PRIMARY KEY (' . implode(', ', $keyColumns) . ')'; - unset($diff->addedIndexes['primary']); - } elseif (isset($diff->changedIndexes['primary'])) { - // Necessary in case the new primary key includes a new auto_increment column - foreach ($diff->changedIndexes['primary']->getColumns() as $columnName) { - if (isset($diff->addedColumns[$columnName]) && $diff->addedColumns[$columnName]->getAutoincrement()) { - $keyColumns = array_unique(array_values($diff->changedIndexes['primary']->getColumns())); - $queryParts[] = 'DROP PRIMARY KEY'; - $queryParts[] = 'ADD PRIMARY KEY (' . implode(', ', $keyColumns) . ')'; - unset($diff->changedIndexes['primary']); - break; - } - } - } - - $sql = []; - $tableSql = []; - - if (! $this->onSchemaAlterTable($diff, $tableSql)) { - if (count($queryParts) > 0) { - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(', ', $queryParts); - } - $sql = array_merge( - $this->getPreAlterTableIndexForeignKeySQL($diff), - $sql, - $this->getPostAlterTableIndexForeignKeySQL($diff) - ); - } - - return array_merge($sql, $tableSql, $columnSql); - } - - /** - * {@inheritDoc} - */ - protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) - { - $sql = []; - $table = $diff->getName($this)->getQuotedName($this); - - foreach ($diff->changedIndexes as $changedIndex) { - $sql = array_merge($sql, $this->getPreAlterTableAlterPrimaryKeySQL($diff, $changedIndex)); - } - - foreach ($diff->removedIndexes as $remKey => $remIndex) { - $sql = array_merge($sql, $this->getPreAlterTableAlterPrimaryKeySQL($diff, $remIndex)); - - foreach ($diff->addedIndexes as $addKey => $addIndex) { - if ($remIndex->getColumns() === $addIndex->getColumns()) { - $indexClause = 'INDEX ' . $addIndex->getName(); - - if ($addIndex->isPrimary()) { - $indexClause = 'PRIMARY KEY'; - } elseif ($addIndex->isUnique()) { - $indexClause = 'UNIQUE INDEX ' . $addIndex->getName(); - } - - $query = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $remIndex->getName() . ', '; - $query .= 'ADD ' . $indexClause; - $query .= ' (' . $this->getIndexFieldDeclarationListSQL($addIndex) . ')'; - - $sql[] = $query; - - unset($diff->removedIndexes[$remKey], $diff->addedIndexes[$addKey]); - - break; - } - } - } - - $engine = 'INNODB'; - - if ($diff->fromTable instanceof Table && $diff->fromTable->hasOption('engine')) { - $engine = strtoupper(trim($diff->fromTable->getOption('engine'))); - } - - // Suppress foreign key constraint propagation on non-supporting engines. - if ($engine !== 'INNODB') { - $diff->addedForeignKeys = []; - $diff->changedForeignKeys = []; - $diff->removedForeignKeys = []; - } - - $sql = array_merge( - $sql, - $this->getPreAlterTableAlterIndexForeignKeySQL($diff), - parent::getPreAlterTableIndexForeignKeySQL($diff), - $this->getPreAlterTableRenameIndexForeignKeySQL($diff) - ); - - return $sql; - } - - /** - * @return string[] - */ - private function getPreAlterTableAlterPrimaryKeySQL(TableDiff $diff, Index $index) - { - $sql = []; - - if (! $index->isPrimary() || ! $diff->fromTable instanceof Table) { - return $sql; - } - - $tableName = $diff->getName($this)->getQuotedName($this); - - // Dropping primary keys requires to unset autoincrement attribute on the particular column first. - foreach ($index->getColumns() as $columnName) { - if (! $diff->fromTable->hasColumn($columnName)) { - continue; - } - - $column = $diff->fromTable->getColumn($columnName); - - if ($column->getAutoincrement() !== true) { - continue; - } - - $column->setAutoincrement(false); - - $sql[] = 'ALTER TABLE ' . $tableName . ' MODIFY ' . - $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); - - // original autoincrement information might be needed later on by other parts of the table alteration - $column->setAutoincrement(true); - } - - return $sql; - } - - /** - * @param TableDiff $diff The table diff to gather the SQL for. - * - * @return string[] - */ - private function getPreAlterTableAlterIndexForeignKeySQL(TableDiff $diff) - { - $sql = []; - $table = $diff->getName($this)->getQuotedName($this); - - foreach ($diff->changedIndexes as $changedIndex) { - // Changed primary key - if (! $changedIndex->isPrimary() || ! ($diff->fromTable instanceof Table)) { - continue; - } - - foreach ($diff->fromTable->getPrimaryKeyColumns() as $columnName) { - $column = $diff->fromTable->getColumn($columnName); - - // Check if an autoincrement column was dropped from the primary key. - if (! $column->getAutoincrement() || in_array($columnName, $changedIndex->getColumns())) { - continue; - } - - // The autoincrement attribute needs to be removed from the dropped column - // before we can drop and recreate the primary key. - $column->setAutoincrement(false); - - $sql[] = 'ALTER TABLE ' . $table . ' MODIFY ' . - $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); - - // Restore the autoincrement attribute as it might be needed later on - // by other parts of the table alteration. - $column->setAutoincrement(true); - } - } - - return $sql; - } - - /** - * @param TableDiff $diff The table diff to gather the SQL for. - * - * @return string[] - */ - protected function getPreAlterTableRenameIndexForeignKeySQL(TableDiff $diff) - { - $sql = []; - $tableName = $diff->getName($this)->getQuotedName($this); - - foreach ($this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) as $foreignKey) { - if (in_array($foreignKey, $diff->changedForeignKeys, true)) { - continue; - } - - $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName); - } - - return $sql; - } - - /** - * Returns the remaining foreign key constraints that require one of the renamed indexes. - * - * "Remaining" here refers to the diff between the foreign keys currently defined in the associated - * table and the foreign keys to be removed. - * - * @param TableDiff $diff The table diff to evaluate. - * - * @return ForeignKeyConstraint[] - */ - private function getRemainingForeignKeyConstraintsRequiringRenamedIndexes(TableDiff $diff) - { - if (empty($diff->renamedIndexes) || ! $diff->fromTable instanceof Table) { - return []; - } - - $foreignKeys = []; - /** @var ForeignKeyConstraint[] $remainingForeignKeys */ - $remainingForeignKeys = array_diff_key( - $diff->fromTable->getForeignKeys(), - $diff->removedForeignKeys - ); - - foreach ($remainingForeignKeys as $foreignKey) { - foreach ($diff->renamedIndexes as $index) { - if ($foreignKey->intersectsIndexColumns($index)) { - $foreignKeys[] = $foreignKey; - - break; - } - } - } - - return $foreignKeys; - } - - /** - * {@inheritdoc} - */ - protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) - { - return array_merge( - parent::getPostAlterTableIndexForeignKeySQL($diff), - $this->getPostAlterTableRenameIndexForeignKeySQL($diff) - ); - } - - /** - * @param TableDiff $diff The table diff to gather the SQL for. - * - * @return string[] - */ - protected function getPostAlterTableRenameIndexForeignKeySQL(TableDiff $diff) - { - $sql = []; - $newName = $diff->getNewName(); - - if ($newName !== false) { - $tableName = $newName->getQuotedName($this); - } else { - $tableName = $diff->getName($this)->getQuotedName($this); - } - - foreach ($this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) as $foreignKey) { - if (in_array($foreignKey, $diff->changedForeignKeys, true)) { - continue; - } - - $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); - } - - return $sql; - } - - /** - * {@inheritDoc} - */ - protected function getCreateIndexSQLFlags(Index $index) - { - $type = ''; - if ($index->isUnique()) { - $type .= 'UNIQUE '; - } elseif ($index->hasFlag('fulltext')) { - $type .= 'FULLTEXT '; - } elseif ($index->hasFlag('spatial')) { - $type .= 'SPATIAL '; - } - - return $type; - } - - /** - * {@inheritDoc} - */ - public function getIntegerTypeDeclarationSQL(array $field) - { - return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - public function getBigIntTypeDeclarationSQL(array $field) - { - return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - public function getSmallIntTypeDeclarationSQL(array $field) - { - return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritdoc} - */ - public function getFloatDeclarationSQL(array $field) - { - return 'DOUBLE PRECISION' . $this->getUnsignedDeclaration($field); - } - - /** - * {@inheritdoc} - */ - public function getDecimalTypeDeclarationSQL(array $columnDef) - { - return parent::getDecimalTypeDeclarationSQL($columnDef) . $this->getUnsignedDeclaration($columnDef); - } - - /** - * Get unsigned declaration for a column. - * - * @param mixed[] $columnDef - * - * @return string - */ - private function getUnsignedDeclaration(array $columnDef) - { - return ! empty($columnDef['unsigned']) ? ' UNSIGNED' : ''; - } - - /** - * {@inheritDoc} - */ - protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) - { - $autoinc = ''; - if (! empty($columnDef['autoincrement'])) { - $autoinc = ' AUTO_INCREMENT'; - } - - return $this->getUnsignedDeclaration($columnDef) . $autoinc; - } - - /** - * {@inheritDoc} - */ - public function getColumnCharsetDeclarationSQL($charset) - { - return 'CHARACTER SET ' . $charset; - } - - /** - * {@inheritDoc} - */ - public function getColumnCollationDeclarationSQL($collation) - { - return 'COLLATE ' . $this->quoteSingleIdentifier($collation); - } - - /** - * {@inheritDoc} - */ - public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) - { - $query = ''; - if ($foreignKey->hasOption('match')) { - $query .= ' MATCH ' . $foreignKey->getOption('match'); - } - $query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey); - - return $query; - } - - /** - * {@inheritDoc} - */ - public function getDropIndexSQL($index, $table = null) - { - if ($index instanceof Index) { - $indexName = $index->getQuotedName($this); - } elseif (is_string($index)) { - $indexName = $index; - } else { - throw new InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); - } - - if ($table instanceof Table) { - $table = $table->getQuotedName($this); - } elseif (! is_string($table)) { - throw new InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); - } - - if ($index instanceof Index && $index->isPrimary()) { - // mysql primary keys are always named "PRIMARY", - // so we cannot use them in statements because of them being keyword. - return $this->getDropPrimaryKeySQL($table); - } - - return 'DROP INDEX ' . $indexName . ' ON ' . $table; - } - - /** - * @param string $table - * - * @return string - */ - protected function getDropPrimaryKeySQL($table) - { - return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; - } - - /** - * {@inheritDoc} - */ - public function getSetTransactionIsolationSQL($level) - { - return 'SET SESSION TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level); - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'mysql'; - } - - /** - * {@inheritDoc} - */ - public function getReadLockSQL() - { - return 'LOCK IN SHARE MODE'; - } - - /** - * {@inheritDoc} - */ - protected function initializeDoctrineTypeMappings() - { - $this->doctrineTypeMapping = [ - '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' => 'float', - 'double' => 'float', - 'real' => 'float', - 'decimal' => 'decimal', - 'numeric' => 'decimal', - 'year' => 'date', - 'longblob' => 'blob', - 'blob' => 'blob', - 'mediumblob' => 'blob', - 'tinyblob' => 'blob', - 'binary' => 'binary', - 'varbinary' => 'binary', - 'set' => 'simple_array', - ]; - } - - /** - * {@inheritDoc} - */ - public function getVarcharMaxLength() - { - return 65535; - } - - /** - * {@inheritdoc} - */ - public function getBinaryMaxLength() - { - return 65535; - } - - /** - * {@inheritDoc} - */ - protected function getReservedKeywordsClass() - { - return Keywords\MySQLKeywords::class; - } - - /** - * {@inheritDoc} - * - * MySQL commits a transaction implicitly when DROP TABLE is executed, however not - * if DROP TEMPORARY TABLE is executed. - */ - public function getDropTemporaryTableSQL($table) - { - if ($table instanceof Table) { - $table = $table->getQuotedName($this); - } elseif (! is_string($table)) { - throw new InvalidArgumentException('getDropTemporaryTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); - } - - return 'DROP TEMPORARY TABLE ' . $table; - } - - /** - * Gets the SQL Snippet used to declare a BLOB column type. - * TINYBLOB : 2 ^ 8 - 1 = 255 - * BLOB : 2 ^ 16 - 1 = 65535 - * MEDIUMBLOB : 2 ^ 24 - 1 = 16777215 - * LONGBLOB : 2 ^ 32 - 1 = 4294967295 - * - * {@inheritDoc} - */ - public function getBlobTypeDeclarationSQL(array $field) - { - if (! empty($field['length']) && is_numeric($field['length'])) { - $length = $field['length']; - - if ($length <= static::LENGTH_LIMIT_TINYBLOB) { - return 'TINYBLOB'; - } - - if ($length <= static::LENGTH_LIMIT_BLOB) { - return 'BLOB'; - } - - if ($length <= static::LENGTH_LIMIT_MEDIUMBLOB) { - return 'MEDIUMBLOB'; - } - } - - return 'LONGBLOB'; - } - - /** - * {@inheritdoc} - */ - public function quoteStringLiteral($str) - { - $str = str_replace('\\', '\\\\', $str); // MySQL requires backslashes to be escaped aswell. - - return parent::quoteStringLiteral($str); - } - - /** - * {@inheritdoc} - */ - public function getDefaultTransactionIsolationLevel() - { - return TransactionIsolationLevel::REPEATABLE_READ; - } - - /** - * {@inheritdoc} - */ - public function supportsColumnLengthIndexes() : bool - { - return true; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/OraclePlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/OraclePlatform.php deleted file mode 100644 index 21b13a2..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/OraclePlatform.php +++ /dev/null @@ -1,1206 +0,0 @@ -getBitAndComparisonExpression($value1, $value2) - . '+' . $value2 . ')'; - } - - /** - * {@inheritDoc} - * - * 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()} - */ - public function getCreateSequenceSQL(Sequence $sequence) - { - return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . - ' START WITH ' . $sequence->getInitialValue() . - ' MINVALUE ' . $sequence->getInitialValue() . - ' INCREMENT BY ' . $sequence->getAllocationSize() . - $this->getSequenceCacheSQL($sequence); - } - - /** - * {@inheritDoc} - */ - public function getAlterSequenceSQL(Sequence $sequence) - { - return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . - ' INCREMENT BY ' . $sequence->getAllocationSize() - . $this->getSequenceCacheSQL($sequence); - } - - /** - * Cache definition for sequences - * - * @return string - */ - private function getSequenceCacheSQL(Sequence $sequence) - { - if ($sequence->getCache() === 0) { - return ' NOCACHE'; - } - - if ($sequence->getCache() === 1) { - return ' NOCACHE'; - } - - if ($sequence->getCache() > 1) { - return ' CACHE ' . $sequence->getCache(); - } - - return ''; - } - - /** - * {@inheritDoc} - */ - public function getSequenceNextValSQL($sequenceName) - { - return 'SELECT ' . $sequenceName . '.nextval FROM DUAL'; - } - - /** - * {@inheritDoc} - */ - public function getSetTransactionIsolationSQL($level) - { - return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level); - } - - /** - * {@inheritDoc} - */ - protected function _getTransactionIsolationLevelSQL($level) - { - switch ($level) { - case TransactionIsolationLevel::READ_UNCOMMITTED: - return 'READ UNCOMMITTED'; - case TransactionIsolationLevel::READ_COMMITTED: - return 'READ COMMITTED'; - case TransactionIsolationLevel::REPEATABLE_READ: - case TransactionIsolationLevel::SERIALIZABLE: - return 'SERIALIZABLE'; - default: - return parent::_getTransactionIsolationLevelSQL($level); - } - } - - /** - * {@inheritDoc} - */ - public function getBooleanTypeDeclarationSQL(array $field) - { - return 'NUMBER(1)'; - } - - /** - * {@inheritDoc} - */ - public function getIntegerTypeDeclarationSQL(array $field) - { - return 'NUMBER(10)'; - } - - /** - * {@inheritDoc} - */ - public function getBigIntTypeDeclarationSQL(array $field) - { - return 'NUMBER(20)'; - } - - /** - * {@inheritDoc} - */ - public function getSmallIntTypeDeclarationSQL(array $field) - { - return 'NUMBER(5)'; - } - - /** - * {@inheritDoc} - */ - public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) - { - return 'TIMESTAMP(0)'; - } - - /** - * {@inheritDoc} - */ - public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) - { - return 'TIMESTAMP(0) WITH TIME ZONE'; - } - - /** - * {@inheritDoc} - */ - public function getDateTypeDeclarationSQL(array $fieldDeclaration) - { - return 'DATE'; - } - - /** - * {@inheritDoc} - */ - public function getTimeTypeDeclarationSQL(array $fieldDeclaration) - { - return 'DATE'; - } - - /** - * {@inheritDoc} - */ - protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) - { - return ''; - } - - /** - * {@inheritDoc} - */ - protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) - { - return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(2000)') - : ($length ? 'VARCHAR2(' . $length . ')' : 'VARCHAR2(4000)'); - } - - /** - * {@inheritdoc} - */ - protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) - { - return 'RAW(' . ($length ?: $this->getBinaryMaxLength()) . ')'; - } - - /** - * {@inheritdoc} - */ - public function getBinaryMaxLength() - { - return 2000; - } - - /** - * {@inheritDoc} - */ - public function getClobTypeDeclarationSQL(array $field) - { - return 'CLOB'; - } - - /** - * {@inheritDoc} - */ - public function getListDatabasesSQL() - { - return 'SELECT username FROM all_users'; - } - - /** - * {@inheritDoc} - */ - public function getListSequencesSQL($database) - { - $database = $this->normalizeIdentifier($database); - $database = $this->quoteStringLiteral($database->getName()); - - return 'SELECT sequence_name, min_value, increment_by FROM sys.all_sequences ' . - 'WHERE SEQUENCE_OWNER = ' . $database; - } - - /** - * {@inheritDoc} - */ - protected function _getCreateTableSQL($table, array $columns, array $options = []) - { - $indexes = $options['indexes'] ?? []; - $options['indexes'] = []; - $sql = parent::_getCreateTableSQL($table, $columns, $options); - - foreach ($columns as $name => $column) { - if (isset($column['sequence'])) { - $sql[] = $this->getCreateSequenceSQL($column['sequence']); - } - - if (! isset($column['autoincrement']) || ! $column['autoincrement'] && - (! isset($column['autoinc']) || ! $column['autoinc'])) { - continue; - } - - $sql = array_merge($sql, $this->getCreateAutoincrementSql($name, $table)); - } - - if (isset($indexes) && ! empty($indexes)) { - foreach ($indexes as $index) { - $sql[] = $this->getCreateIndexSQL($index, $table); - } - } - - return $sql; - } - - /** - * {@inheritDoc} - * - * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaOracleReader.html - */ - public function getListTableIndexesSQL($table, $currentDatabase = null) - { - $table = $this->normalizeIdentifier($table); - $table = $this->quoteStringLiteral($table->getName()); - - return "SELECT uind_col.index_name AS name, - ( - SELECT uind.index_type - FROM user_indexes uind - WHERE uind.index_name = uind_col.index_name - ) AS type, - decode( - ( - SELECT uind.uniqueness - FROM user_indexes uind - WHERE uind.index_name = uind_col.index_name - ), - '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.index_name = uind_col.index_name - ) AS is_primary - FROM user_ind_columns uind_col - WHERE uind_col.table_name = " . $table . ' - ORDER BY uind_col.column_position ASC'; - } - - /** - * {@inheritDoc} - */ - public function getListTablesSQL() - { - return 'SELECT * FROM sys.user_tables'; - } - - /** - * {@inheritDoc} - */ - public function getListViewsSQL($database) - { - return 'SELECT view_name, text FROM sys.user_views'; - } - - /** - * {@inheritDoc} - */ - public function getCreateViewSQL($name, $sql) - { - return 'CREATE VIEW ' . $name . ' AS ' . $sql; - } - - /** - * {@inheritDoc} - */ - public function getDropViewSQL($name) - { - return 'DROP VIEW ' . $name; - } - - /** - * @param string $name - * @param string $table - * @param int $start - * - * @return string[] - */ - public function getCreateAutoincrementSql($name, $table, $start = 1) - { - $tableIdentifier = $this->normalizeIdentifier($table); - $quotedTableName = $tableIdentifier->getQuotedName($this); - $unquotedTableName = $tableIdentifier->getName(); - - $nameIdentifier = $this->normalizeIdentifier($name); - $quotedName = $nameIdentifier->getQuotedName($this); - $unquotedName = $nameIdentifier->getName(); - - $sql = []; - - $autoincrementIdentifierName = $this->getAutoincrementIdentifierName($tableIdentifier); - - $idx = new Index($autoincrementIdentifierName, [$quotedName], true, true); - - $sql[] = 'DECLARE - constraints_Count NUMBER; -BEGIN - SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = \'' . $unquotedTableName . '\' AND CONSTRAINT_TYPE = \'P\'; - IF constraints_Count = 0 OR constraints_Count = \'\' THEN - EXECUTE IMMEDIATE \'' . $this->getCreateConstraintSQL($idx, $quotedTableName) . '\'; - END IF; -END;'; - - $sequenceName = $this->getIdentitySequenceName( - $tableIdentifier->isQuoted() ? $quotedTableName : $unquotedTableName, - $nameIdentifier->isQuoted() ? $quotedName : $unquotedName - ); - $sequence = new Sequence($sequenceName, $start); - $sql[] = $this->getCreateSequenceSQL($sequence); - - $sql[] = 'CREATE TRIGGER ' . $autoincrementIdentifierName . ' - BEFORE INSERT - ON ' . $quotedTableName . ' - FOR EACH ROW -DECLARE - last_Sequence NUMBER; - last_InsertID NUMBER; -BEGIN - SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $quotedName . ' FROM DUAL; - IF (:NEW.' . $quotedName . ' IS NULL OR :NEW.' . $quotedName . ' = 0) THEN - SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $quotedName . ' FROM DUAL; - ELSE - SELECT NVL(Last_Number, 0) INTO last_Sequence - FROM User_Sequences - WHERE Sequence_Name = \'' . $sequence->getName() . '\'; - SELECT :NEW.' . $quotedName . ' 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; - } - - /** - * Returns the SQL statements to drop the autoincrement for the given table name. - * - * @param string $table The table name to drop the autoincrement for. - * - * @return string[] - */ - public function getDropAutoincrementSql($table) - { - $table = $this->normalizeIdentifier($table); - $autoincrementIdentifierName = $this->getAutoincrementIdentifierName($table); - $identitySequenceName = $this->getIdentitySequenceName( - $table->isQuoted() ? $table->getQuotedName($this) : $table->getName(), - '' - ); - - return [ - 'DROP TRIGGER ' . $autoincrementIdentifierName, - $this->getDropSequenceSQL($identitySequenceName), - $this->getDropConstraintSQL($autoincrementIdentifierName, $table->getQuotedName($this)), - ]; - } - - /** - * Normalizes the given identifier. - * - * Uppercases the given identifier if it is not quoted by intention - * to reflect Oracle's internal auto uppercasing strategy of unquoted identifiers. - * - * @param string $name The identifier to normalize. - * - * @return Identifier The normalized identifier. - */ - private function normalizeIdentifier($name) - { - $identifier = new Identifier($name); - - return $identifier->isQuoted() ? $identifier : new Identifier(strtoupper($name)); - } - - /** - * Returns the autoincrement primary key identifier name for the given table identifier. - * - * Quotes the autoincrement primary key identifier name - * if the given table name is quoted by intention. - * - * @param Identifier $table The table identifier to return the autoincrement primary key identifier name for. - * - * @return string - */ - private function getAutoincrementIdentifierName(Identifier $table) - { - $identifierName = $table->getName() . '_AI_PK'; - - return $table->isQuoted() - ? $this->quoteSingleIdentifier($identifierName) - : $identifierName; - } - - /** - * {@inheritDoc} - */ - public function getListTableForeignKeysSQL($table) - { - $table = $this->normalizeIdentifier($table); - $table = $this->quoteStringLiteral($table->getName()); - - return "SELECT alc.constraint_name, - alc.DELETE_RULE, - cols.column_name \"local_column\", - cols.position, - ( - SELECT r_cols.table_name - FROM user_cons_columns r_cols - WHERE alc.r_constraint_name = r_cols.constraint_name - AND r_cols.position = cols.position - ) AS \"references_table\", - ( - SELECT r_cols.column_name - FROM user_cons_columns r_cols - WHERE alc.r_constraint_name = r_cols.constraint_name - AND r_cols.position = cols.position - ) AS \"foreign_column\" - FROM user_cons_columns cols - JOIN user_constraints alc - ON alc.constraint_name = cols.constraint_name - AND alc.constraint_type = 'R' - AND alc.table_name = " . $table . ' - ORDER BY cols.constraint_name ASC, cols.position ASC'; - } - - /** - * {@inheritDoc} - */ - public function getListTableConstraintsSQL($table) - { - $table = $this->normalizeIdentifier($table); - $table = $this->quoteStringLiteral($table->getName()); - - return 'SELECT * FROM user_constraints WHERE table_name = ' . $table; - } - - /** - * {@inheritDoc} - */ - public function getListTableColumnsSQL($table, $database = null) - { - $table = $this->normalizeIdentifier($table); - $table = $this->quoteStringLiteral($table->getName()); - - $tabColumnsTableName = 'user_tab_columns'; - $colCommentsTableName = 'user_col_comments'; - $tabColumnsOwnerCondition = ''; - $colCommentsOwnerCondition = ''; - - if ($database !== null && $database !== '/') { - $database = $this->normalizeIdentifier($database); - $database = $this->quoteStringLiteral($database->getName()); - $tabColumnsTableName = 'all_tab_columns'; - $colCommentsTableName = 'all_col_comments'; - $tabColumnsOwnerCondition = ' AND c.owner = ' . $database; - $colCommentsOwnerCondition = ' AND d.OWNER = c.OWNER'; - } - - return sprintf( - <<<'SQL' -SELECT c.*, - ( - SELECT d.comments - FROM %s d - WHERE d.TABLE_NAME = c.TABLE_NAME%s - AND d.COLUMN_NAME = c.COLUMN_NAME - ) AS comments -FROM %s c -WHERE c.table_name = %s%s -ORDER BY c.column_id -SQL - , - $colCommentsTableName, - $colCommentsOwnerCondition, - $tabColumnsTableName, - $table, - $tabColumnsOwnerCondition - ); - } - - /** - * {@inheritDoc} - */ - public function getDropSequenceSQL($sequence) - { - if ($sequence instanceof Sequence) { - $sequence = $sequence->getQuotedName($this); - } - - return 'DROP SEQUENCE ' . $sequence; - } - - /** - * {@inheritDoc} - */ - public function getDropForeignKeySQL($foreignKey, $table) - { - if (! $foreignKey instanceof ForeignKeyConstraint) { - $foreignKey = new Identifier($foreignKey); - } - - if (! $table instanceof Table) { - $table = new Identifier($table); - } - - $foreignKey = $foreignKey->getQuotedName($this); - $table = $table->getQuotedName($this); - - return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey; - } - - /** - * {@inheritdoc} - */ - public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) - { - $referentialAction = null; - - if ($foreignKey->hasOption('onDelete')) { - $referentialAction = $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete')); - } - - return $referentialAction ? ' ON DELETE ' . $referentialAction : ''; - } - - /** - * {@inheritdoc} - */ - public function getForeignKeyReferentialActionSQL($action) - { - $action = strtoupper($action); - - switch ($action) { - case 'RESTRICT': // RESTRICT is not supported, therefore falling back to NO ACTION. - case 'NO ACTION': - // NO ACTION cannot be declared explicitly, - // therefore returning empty string to indicate to OMIT the referential clause. - return ''; - - case 'CASCADE': - case 'SET NULL': - return $action; - - default: - // SET DEFAULT is not supported, throw exception instead. - throw new InvalidArgumentException('Invalid foreign key action: ' . $action); - } - } - - /** - * {@inheritDoc} - */ - public function getDropDatabaseSQL($database) - { - return 'DROP USER ' . $database . ' CASCADE'; - } - - /** - * {@inheritDoc} - */ - public function getAlterTableSQL(TableDiff $diff) - { - $sql = []; - $commentsSQL = []; - $columnSql = []; - - $fields = []; - - foreach ($diff->addedColumns as $column) { - if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { - continue; - } - - $fields[] = $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); - $comment = $this->getColumnComment($column); - - if (! $comment) { - continue; - } - - $commentsSQL[] = $this->getCommentOnColumnSQL( - $diff->getName($this)->getQuotedName($this), - $column->getQuotedName($this), - $comment - ); - } - - if (count($fields)) { - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ADD (' . implode(', ', $fields) . ')'; - } - - $fields = []; - foreach ($diff->changedColumns as $columnDiff) { - if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { - continue; - } - - $column = $columnDiff->column; - - // Do not generate column alteration clause if type is binary and only fixed property has changed. - // Oracle only supports binary type columns with variable length. - // Avoids unnecessary table alteration statements. - if ($column->getType() instanceof BinaryType && - $columnDiff->hasChanged('fixed') && - count($columnDiff->changedProperties) === 1 - ) { - continue; - } - - $columnHasChangedComment = $columnDiff->hasChanged('comment'); - - /** - * Do not add query part if only comment has changed - */ - if (! ($columnHasChangedComment && count($columnDiff->changedProperties) === 1)) { - $columnInfo = $column->toArray(); - - if (! $columnDiff->hasChanged('notnull')) { - unset($columnInfo['notnull']); - } - - $fields[] = $column->getQuotedName($this) . $this->getColumnDeclarationSQL('', $columnInfo); - } - - if (! $columnHasChangedComment) { - continue; - } - - $commentsSQL[] = $this->getCommentOnColumnSQL( - $diff->getName($this)->getQuotedName($this), - $column->getQuotedName($this), - $this->getColumnComment($column) - ); - } - - if (count($fields)) { - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' MODIFY (' . implode(', ', $fields) . ')'; - } - - foreach ($diff->renamedColumns as $oldColumnName => $column) { - if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { - continue; - } - - $oldColumnName = new Identifier($oldColumnName); - - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . - ' RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . ' TO ' . $column->getQuotedName($this); - } - - $fields = []; - foreach ($diff->removedColumns as $column) { - if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { - continue; - } - - $fields[] = $column->getQuotedName($this); - } - - if (count($fields)) { - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' DROP (' . implode(', ', $fields) . ')'; - } - - $tableSql = []; - - if (! $this->onSchemaAlterTable($diff, $tableSql)) { - $sql = array_merge($sql, $commentsSQL); - - $newName = $diff->getNewName(); - - if ($newName !== false) { - $sql[] = sprintf( - 'ALTER TABLE %s RENAME TO %s', - $diff->getName($this)->getQuotedName($this), - $newName->getQuotedName($this) - ); - } - - $sql = array_merge( - $this->getPreAlterTableIndexForeignKeySQL($diff), - $sql, - $this->getPostAlterTableIndexForeignKeySQL($diff) - ); - } - - return array_merge($sql, $tableSql, $columnSql); - } - - /** - * {@inheritdoc} - */ - public function getColumnDeclarationSQL($name, array $field) - { - if (isset($field['columnDefinition'])) { - $columnDef = $this->getCustomTypeDeclarationSQL($field); - } else { - $default = $this->getDefaultValueDeclarationSQL($field); - - $notnull = ''; - - if (isset($field['notnull'])) { - $notnull = $field['notnull'] ? ' NOT NULL' : ' 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 . $default . $notnull . $unique . $check; - } - - return $name . ' ' . $columnDef; - } - - /** - * {@inheritdoc} - */ - protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) - { - if (strpos($tableName, '.') !== false) { - [$schema] = explode('.', $tableName); - $oldIndexName = $schema . '.' . $oldIndexName; - } - - return ['ALTER INDEX ' . $oldIndexName . ' RENAME TO ' . $index->getQuotedName($this)]; - } - - /** - * {@inheritDoc} - */ - public function prefersSequences() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function usesSequenceEmulatedIdentityColumns() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function getIdentitySequenceName($tableName, $columnName) - { - $table = new Identifier($tableName); - - // No usage of column name to preserve BC compatibility with <2.5 - $identitySequenceName = $table->getName() . '_SEQ'; - - if ($table->isQuoted()) { - $identitySequenceName = '"' . $identitySequenceName . '"'; - } - - $identitySequenceIdentifier = $this->normalizeIdentifier($identitySequenceName); - - return $identitySequenceIdentifier->getQuotedName($this); - } - - /** - * {@inheritDoc} - */ - public function supportsCommentOnStatement() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'oracle'; - } - - /** - * {@inheritDoc} - */ - protected function doModifyLimitQuery($query, $limit, $offset = null) - { - if ($limit === null && $offset <= 0) { - return $query; - } - - if (preg_match('/^\s*SELECT/i', $query)) { - if (! preg_match('/\sFROM\s/i', $query)) { - $query .= ' FROM dual'; - } - - $columns = ['a.*']; - - if ($offset > 0) { - $columns[] = 'ROWNUM AS doctrine_rownum'; - } - - $query = sprintf('SELECT %s FROM (%s) a', implode(', ', $columns), $query); - - if ($limit !== null) { - $query .= sprintf(' WHERE ROWNUM <= %d', $offset + $limit); - } - - if ($offset > 0) { - $query = sprintf('SELECT * FROM (%s) WHERE doctrine_rownum >= %d', $query, $offset + 1); - } - } - - return $query; - } - - /** - * {@inheritDoc} - * - * Oracle returns all column names in SQL result sets in uppercase. - */ - public function getSQLResultCasing($column) - { - return strtoupper($column); - } - - /** - * {@inheritDoc} - */ - public function getCreateTemporaryTableSnippetSQL() - { - return 'CREATE GLOBAL TEMPORARY TABLE'; - } - - /** - * {@inheritDoc} - */ - public function getDateTimeTzFormatString() - { - return 'Y-m-d H:i:sP'; - } - - /** - * {@inheritDoc} - */ - public function getDateFormatString() - { - return 'Y-m-d 00:00:00'; - } - - /** - * {@inheritDoc} - */ - public function getTimeFormatString() - { - return '1900-01-01 H:i:s'; - } - - /** - * {@inheritDoc} - */ - public function fixSchemaElementName($schemaElementName) - { - if (strlen($schemaElementName) > 30) { - // Trim it - return substr($schemaElementName, 0, 30); - } - - return $schemaElementName; - } - - /** - * {@inheritDoc} - */ - public function getMaxIdentifierLength() - { - return 30; - } - - /** - * {@inheritDoc} - */ - public function supportsSequences() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function supportsForeignKeyOnUpdate() - { - return false; - } - - /** - * {@inheritDoc} - */ - public function supportsReleaseSavepoints() - { - return false; - } - - /** - * {@inheritDoc} - */ - public function getTruncateTableSQL($tableName, $cascade = false) - { - $tableIdentifier = new Identifier($tableName); - - return 'TRUNCATE TABLE ' . $tableIdentifier->getQuotedName($this); - } - - /** - * {@inheritDoc} - */ - public function getDummySelectSQL() - { - $expression = func_num_args() > 0 ? func_get_arg(0) : '1'; - - return sprintf('SELECT %s FROM DUAL', $expression); - } - - /** - * {@inheritDoc} - */ - protected function initializeDoctrineTypeMappings() - { - $this->doctrineTypeMapping = [ - 'integer' => 'integer', - 'number' => 'integer', - 'pls_integer' => 'boolean', - 'binary_integer' => 'boolean', - 'varchar' => 'string', - 'varchar2' => 'string', - 'nvarchar2' => 'string', - 'char' => 'string', - 'nchar' => 'string', - 'date' => 'date', - 'timestamp' => 'datetime', - 'timestamptz' => 'datetimetz', - 'float' => 'float', - 'binary_float' => 'float', - 'binary_double' => 'float', - 'long' => 'string', - 'clob' => 'text', - 'nclob' => 'text', - 'raw' => 'binary', - 'long raw' => 'blob', - 'rowid' => 'string', - 'urowid' => 'string', - 'blob' => 'blob', - ]; - } - - /** - * {@inheritDoc} - */ - public function releaseSavePoint($savepoint) - { - return ''; - } - - /** - * {@inheritDoc} - */ - protected function getReservedKeywordsClass() - { - return Keywords\OracleKeywords::class; - } - - /** - * {@inheritDoc} - */ - public function getBlobTypeDeclarationSQL(array $field) - { - return 'BLOB'; - } - - public function getListTableCommentsSQL(string $table, ?string $database = null) : string - { - $tableCommentsName = 'user_tab_comments'; - $ownerCondition = ''; - - if ($database !== null && $database !== '/') { - $tableCommentsName = 'all_tab_comments'; - $ownerCondition = ' AND owner = ' . $this->quoteStringLiteral($this->normalizeIdentifier($database)->getName()); - } - - return sprintf( - <<<'SQL' -SELECT comments FROM %s WHERE table_name = %s%s -SQL - , - $tableCommentsName, - $this->quoteStringLiteral($this->normalizeIdentifier($table)->getName()), - $ownerCondition - ); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL100Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL100Platform.php deleted file mode 100644 index cfb079f..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL100Platform.php +++ /dev/null @@ -1,33 +0,0 @@ -quoteStringLiteral($database) . " - AND sequence_schema NOT LIKE 'pg\_%' - AND sequence_schema != 'information_schema'"; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php deleted file mode 100644 index f558409..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL91Platform.php +++ /dev/null @@ -1,46 +0,0 @@ -quoteSingleIdentifier($collation); - } - - /** - * {@inheritDoc} - */ - public function getListTableColumnsSQL($table, $database = null) - { - $sql = parent::getListTableColumnsSQL($table, $database); - $parts = explode('AS complete_type,', $sql, 2); - - return $parts[0] . 'AS complete_type, (SELECT tc.collcollate FROM pg_catalog.pg_collation tc WHERE tc.oid = a.attcollation) AS collation,' . $parts[1]; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php deleted file mode 100644 index 1703056..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL92Platform.php +++ /dev/null @@ -1,69 +0,0 @@ -doctrineTypeMapping['json'] = Types::JSON; - } - - /** - * {@inheritdoc} - */ - public function getCloseActiveDatabaseConnectionsSQL($database) - { - return sprintf( - 'SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = %s', - $this->quoteStringLiteral($database) - ); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL94Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL94Platform.php deleted file mode 100644 index fb559de..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSQL94Platform.php +++ /dev/null @@ -1,41 +0,0 @@ -doctrineTypeMapping['jsonb'] = Types::JSON; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php deleted file mode 100644 index e570dc0..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php +++ /dev/null @@ -1,1270 +0,0 @@ - [ - 't', - 'true', - 'y', - 'yes', - 'on', - '1', - ], - 'false' => [ - 'f', - 'false', - 'n', - 'no', - 'off', - '0', - ], - ]; - - /** - * PostgreSQL has different behavior with some drivers - * with regard to how booleans have to be handled. - * - * Enables use of 'true'/'false' or otherwise 1 and 0 instead. - * - * @param bool $flag - */ - public function setUseBooleanTrueFalseStrings($flag) - { - $this->useBooleanTrueFalseStrings = (bool) $flag; - } - - /** - * {@inheritDoc} - */ - public function getSubstringExpression($value, $from, $length = null) - { - if ($length === null) { - return 'SUBSTRING(' . $value . ' FROM ' . $from . ')'; - } - - return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $length . ')'; - } - - /** - * {@inheritDoc} - */ - public function getNowExpression() - { - return 'LOCALTIMESTAMP(0)'; - } - - /** - * {@inheritDoc} - */ - public function getRegexpExpression() - { - return 'SIMILAR TO'; - } - - /** - * {@inheritDoc} - */ - 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'; - } - - return 'POSITION(' . $substr . ' IN ' . $str . ')'; - } - - /** - * {@inheritdoc} - */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) - { - if ($unit === DateIntervalUnit::QUARTER) { - $interval *= 3; - $unit = DateIntervalUnit::MONTH; - } - - return '(' . $date . ' ' . $operator . ' (' . $interval . " || ' " . $unit . "')::interval)"; - } - - /** - * {@inheritDoc} - */ - public function getDateDiffExpression($date1, $date2) - { - return '(DATE(' . $date1 . ')-DATE(' . $date2 . '))'; - } - - /** - * {@inheritDoc} - */ - public function supportsSequences() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function supportsSchemas() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function getDefaultSchemaName() - { - return 'public'; - } - - /** - * {@inheritDoc} - */ - public function supportsIdentityColumns() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function supportsPartialIndexes() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function usesSequenceEmulatedIdentityColumns() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function getIdentitySequenceName($tableName, $columnName) - { - return $tableName . '_' . $columnName . '_seq'; - } - - /** - * {@inheritDoc} - */ - public function supportsCommentOnStatement() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function prefersSequences() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function hasNativeGuidType() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function getListDatabasesSQL() - { - return 'SELECT datname FROM pg_database'; - } - - /** - * {@inheritDoc} - */ - public function getListNamespacesSQL() - { - return "SELECT schema_name AS nspname - FROM information_schema.schemata - WHERE schema_name NOT LIKE 'pg\_%' - AND schema_name != 'information_schema'"; - } - - /** - * {@inheritDoc} - */ - public function getListSequencesSQL($database) - { - return "SELECT sequence_name AS relname, - sequence_schema AS schemaname - FROM information_schema.sequences - WHERE sequence_schema NOT LIKE 'pg\_%' - AND sequence_schema != 'information_schema'"; - } - - /** - * {@inheritDoc} - */ - public function getListTablesSQL() - { - return "SELECT quote_ident(table_name) AS table_name, - table_schema AS schema_name - FROM information_schema.tables - WHERE table_schema NOT LIKE 'pg\_%' - AND table_schema != 'information_schema' - AND table_name != 'geometry_columns' - AND table_name != 'spatial_ref_sys' - AND table_type != 'VIEW'"; - } - - /** - * {@inheritDoc} - */ - public function getListViewsSQL($database) - { - return 'SELECT quote_ident(table_name) AS viewname, - table_schema AS schemaname, - view_definition AS definition - FROM information_schema.views - WHERE view_definition IS NOT NULL'; - } - - /** - * {@inheritDoc} - */ - public function getListTableForeignKeysSQL($table, $database = null) - { - return 'SELECT quote_ident(r.conname) as 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, pg_catalog.pg_namespace n - WHERE ' . $this->getTableWhereClause($table) . " AND n.oid = c.relnamespace - ) - AND r.contype = 'f'"; - } - - /** - * {@inheritDoc} - */ - public function getCreateViewSQL($name, $sql) - { - return 'CREATE VIEW ' . $name . ' AS ' . $sql; - } - - /** - * {@inheritDoc} - */ - public function getDropViewSQL($name) - { - return 'DROP VIEW ' . $name; - } - - /** - * {@inheritDoc} - */ - public function getListTableConstraintsSQL($table) - { - $table = new Identifier($table); - $table = $this->quoteStringLiteral($table->getName()); - - return sprintf( - <<<'SQL' -SELECT - quote_ident(relname) as relname -FROM - pg_class -WHERE oid IN ( - SELECT indexrelid - FROM pg_index, pg_class - WHERE pg_class.relname = %s - AND pg_class.oid = pg_index.indrelid - AND (indisunique = 't' OR indisprimary = 't') - ) -SQL - , - $table - ); - } - - /** - * {@inheritDoc} - * - * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html - */ - public function getListTableIndexesSQL($table, $currentDatabase = null) - { - return 'SELECT quote_ident(relname) as relname, pg_index.indisunique, pg_index.indisprimary, - pg_index.indkey, pg_index.indrelid, - pg_get_expr(indpred, indrelid) AS where - FROM pg_class, pg_index - WHERE oid IN ( - SELECT indexrelid - FROM pg_index si, pg_class sc, pg_namespace sn - WHERE ' . $this->getTableWhereClause($table, 'sc', 'sn') . ' AND sc.oid=si.indrelid AND sc.relnamespace = sn.oid - ) AND pg_index.indexrelid = oid'; - } - - /** - * @param string $table - * @param string $classAlias - * @param string $namespaceAlias - * - * @return string - */ - private function getTableWhereClause($table, $classAlias = 'c', $namespaceAlias = 'n') - { - $whereClause = $namespaceAlias . ".nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast') AND "; - if (strpos($table, '.') !== false) { - [$schema, $table] = explode('.', $table); - $schema = $this->quoteStringLiteral($schema); - } else { - $schema = "ANY(string_to_array((select replace(replace(setting,'\"\$user\"',user),' ','') from pg_catalog.pg_settings where name = 'search_path'),','))"; - } - - $table = new Identifier($table); - $table = $this->quoteStringLiteral($table->getName()); - - return $whereClause . sprintf( - '%s.relname = %s AND %s.nspname = %s', - $classAlias, - $table, - $namespaceAlias, - $schema - ); - } - - /** - * {@inheritDoc} - */ - public function getListTableColumnsSQL($table, $database = null) - { - return "SELECT - a.attnum, - quote_ident(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.oid = a.atttypid) 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_get_expr(adbin, adrelid) - FROM pg_attrdef - WHERE c.oid = pg_attrdef.adrelid - AND pg_attrdef.adnum=a.attnum - ) AS default, - (SELECT pg_description.description - FROM pg_description WHERE pg_description.objoid = c.oid AND a.attnum = pg_description.objsubid - ) AS comment - FROM pg_attribute a, pg_class c, pg_type t, pg_namespace n - WHERE " . $this->getTableWhereClause($table, 'c', 'n') . ' - AND a.attnum > 0 - AND a.attrelid = c.oid - AND a.atttypid = t.oid - AND n.oid = c.relnamespace - ORDER BY a.attnum'; - } - - /** - * {@inheritDoc} - */ - public function getCreateDatabaseSQL($name) - { - return 'CREATE DATABASE ' . $name; - } - - /** - * Returns the SQL statement for disallowing new connections on the given database. - * - * This is useful to force DROP DATABASE operations which could fail because of active connections. - * - * @param string $database The name of the database to disallow new connections for. - * - * @return string - */ - public function getDisallowDatabaseConnectionsSQL($database) - { - return "UPDATE pg_database SET datallowconn = 'false' WHERE datname = " . $this->quoteStringLiteral($database); - } - - /** - * Returns the SQL statement for closing currently active connections on the given database. - * - * This is useful to force DROP DATABASE operations which could fail because of active connections. - * - * @param string $database The name of the database to close currently active connections for. - * - * @return string - */ - public function getCloseActiveDatabaseConnectionsSQL($database) - { - return 'SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE datname = ' - . $this->quoteStringLiteral($database); - } - - /** - * {@inheritDoc} - */ - public function getAdvancedForeignKeyOptionsSQL(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) - || ($foreignKey->hasOption('deferred') && $foreignKey->getOption('deferred') !== false) - ) { - $query .= ' INITIALLY DEFERRED'; - } else { - $query .= ' INITIALLY IMMEDIATE'; - } - - return $query; - } - - /** - * {@inheritDoc} - */ - public function getAlterTableSQL(TableDiff $diff) - { - $sql = []; - $commentsSQL = []; - $columnSql = []; - - foreach ($diff->addedColumns as $column) { - if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { - continue; - } - - $query = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; - - $comment = $this->getColumnComment($column); - - if ($comment === null || $comment === '') { - continue; - } - - $commentsSQL[] = $this->getCommentOnColumnSQL( - $diff->getName($this)->getQuotedName($this), - $column->getQuotedName($this), - $comment - ); - } - - foreach ($diff->removedColumns as $column) { - if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { - continue; - } - - $query = 'DROP ' . $column->getQuotedName($this); - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; - } - - foreach ($diff->changedColumns as $columnDiff) { - /** @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ - if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { - continue; - } - - if ($this->isUnchangedBinaryColumn($columnDiff)) { - continue; - } - - $oldColumnName = $columnDiff->getOldColumnName()->getQuotedName($this); - $column = $columnDiff->column; - - if ($columnDiff->hasChanged('type') || $columnDiff->hasChanged('precision') || $columnDiff->hasChanged('scale') || $columnDiff->hasChanged('fixed')) { - $type = $column->getType(); - - // SERIAL/BIGSERIAL are not "real" types and we can't alter a column to that type - $columnDefinition = $column->toArray(); - $columnDefinition['autoincrement'] = false; - - // here was a server version check before, but DBAL API does not support this anymore. - $query = 'ALTER ' . $oldColumnName . ' TYPE ' . $type->getSQLDeclaration($columnDefinition, $this); - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; - } - - if ($columnDiff->hasChanged('default') || $this->typeChangeBreaksDefaultValue($columnDiff)) { - $defaultClause = $column->getDefault() === null - ? ' DROP DEFAULT' - : ' SET' . $this->getDefaultValueDeclarationSQL($column->toArray()); - $query = 'ALTER ' . $oldColumnName . $defaultClause; - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; - } - - if ($columnDiff->hasChanged('notnull')) { - $query = 'ALTER ' . $oldColumnName . ' ' . ($column->getNotnull() ? 'SET' : 'DROP') . ' NOT NULL'; - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; - } - - if ($columnDiff->hasChanged('autoincrement')) { - if ($column->getAutoincrement()) { - // add autoincrement - $seqName = $this->getIdentitySequenceName($diff->name, $oldColumnName); - - $sql[] = 'CREATE SEQUENCE ' . $seqName; - $sql[] = "SELECT setval('" . $seqName . "', (SELECT MAX(" . $oldColumnName . ') FROM ' . $diff->getName($this)->getQuotedName($this) . '))'; - $query = 'ALTER ' . $oldColumnName . " SET DEFAULT nextval('" . $seqName . "')"; - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $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->getName($this)->getQuotedName($this) . ' ' . $query; - } - } - - $newComment = $this->getColumnComment($column); - $oldComment = $this->getOldColumnComment($columnDiff); - - if ($columnDiff->hasChanged('comment') || ($columnDiff->fromColumn !== null && $oldComment !== $newComment)) { - $commentsSQL[] = $this->getCommentOnColumnSQL( - $diff->getName($this)->getQuotedName($this), - $column->getQuotedName($this), - $newComment - ); - } - - if (! $columnDiff->hasChanged('length')) { - continue; - } - - $query = 'ALTER ' . $oldColumnName . ' TYPE ' . $column->getType()->getSQLDeclaration($column->toArray(), $this); - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; - } - - foreach ($diff->renamedColumns as $oldColumnName => $column) { - if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { - continue; - } - - $oldColumnName = new Identifier($oldColumnName); - - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . - ' RENAME COLUMN ' . $oldColumnName->getQuotedName($this) . ' TO ' . $column->getQuotedName($this); - } - - $tableSql = []; - - if (! $this->onSchemaAlterTable($diff, $tableSql)) { - $sql = array_merge($sql, $commentsSQL); - - $newName = $diff->getNewName(); - - if ($newName !== false) { - $sql[] = sprintf( - 'ALTER TABLE %s RENAME TO %s', - $diff->getName($this)->getQuotedName($this), - $newName->getQuotedName($this) - ); - } - - $sql = array_merge( - $this->getPreAlterTableIndexForeignKeySQL($diff), - $sql, - $this->getPostAlterTableIndexForeignKeySQL($diff) - ); - } - - return array_merge($sql, $tableSql, $columnSql); - } - - /** - * Checks whether a given column diff is a logically unchanged binary type column. - * - * Used to determine whether a column alteration for a binary type column can be skipped. - * Doctrine's {@link \Doctrine\DBAL\Types\BinaryType} and {@link \Doctrine\DBAL\Types\BlobType} - * are mapped to the same database column type on this platform as this platform - * does not have a native VARBINARY/BINARY column type. Therefore the {@link \Doctrine\DBAL\Schema\Comparator} - * might detect differences for binary type columns which do not have to be propagated - * to database as there actually is no difference at database level. - * - * @param ColumnDiff $columnDiff The column diff to check against. - * - * @return bool True if the given column diff is an unchanged binary type column, false otherwise. - */ - private function isUnchangedBinaryColumn(ColumnDiff $columnDiff) - { - $columnType = $columnDiff->column->getType(); - - if (! $columnType instanceof BinaryType && ! $columnType instanceof BlobType) { - return false; - } - - $fromColumn = $columnDiff->fromColumn instanceof Column ? $columnDiff->fromColumn : null; - - if ($fromColumn) { - $fromColumnType = $fromColumn->getType(); - - if (! $fromColumnType instanceof BinaryType && ! $fromColumnType instanceof BlobType) { - return false; - } - - return count(array_diff($columnDiff->changedProperties, ['type', 'length', 'fixed'])) === 0; - } - - if ($columnDiff->hasChanged('type')) { - return false; - } - - return count(array_diff($columnDiff->changedProperties, ['length', 'fixed'])) === 0; - } - - /** - * {@inheritdoc} - */ - protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) - { - if (strpos($tableName, '.') !== false) { - [$schema] = explode('.', $tableName); - $oldIndexName = $schema . '.' . $oldIndexName; - } - - return ['ALTER INDEX ' . $oldIndexName . ' RENAME TO ' . $index->getQuotedName($this)]; - } - - /** - * {@inheritdoc} - */ - public function getCommentOnColumnSQL($tableName, $columnName, $comment) - { - $tableName = new Identifier($tableName); - $columnName = new Identifier($columnName); - $comment = $comment === null ? 'NULL' : $this->quoteStringLiteral($comment); - - return sprintf( - 'COMMENT ON COLUMN %s.%s IS %s', - $tableName->getQuotedName($this), - $columnName->getQuotedName($this), - $comment - ); - } - - /** - * {@inheritDoc} - */ - public function getCreateSequenceSQL(Sequence $sequence) - { - return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . - ' INCREMENT BY ' . $sequence->getAllocationSize() . - ' MINVALUE ' . $sequence->getInitialValue() . - ' START ' . $sequence->getInitialValue() . - $this->getSequenceCacheSQL($sequence); - } - - /** - * {@inheritDoc} - */ - public function getAlterSequenceSQL(Sequence $sequence) - { - return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . - ' INCREMENT BY ' . $sequence->getAllocationSize() . - $this->getSequenceCacheSQL($sequence); - } - - /** - * Cache definition for sequences - * - * @return string - */ - private function getSequenceCacheSQL(Sequence $sequence) - { - if ($sequence->getCache() > 1) { - return ' CACHE ' . $sequence->getCache(); - } - - return ''; - } - - /** - * {@inheritDoc} - */ - public function getDropSequenceSQL($sequence) - { - if ($sequence instanceof Sequence) { - $sequence = $sequence->getQuotedName($this); - } - - return 'DROP SEQUENCE ' . $sequence . ' CASCADE'; - } - - /** - * {@inheritDoc} - */ - public function getCreateSchemaSQL($schemaName) - { - return 'CREATE SCHEMA ' . $schemaName; - } - - /** - * {@inheritDoc} - */ - public function getDropForeignKeySQL($foreignKey, $table) - { - return $this->getDropConstraintSQL($foreignKey, $table); - } - - /** - * {@inheritDoc} - */ - protected function _getCreateTableSQL($tableName, array $columns, array $options = []) - { - $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; - } - - /** - * Converts a single boolean value. - * - * First converts the value to its native PHP boolean type - * and passes it to the given callback function to be reconverted - * into any custom representation. - * - * @param mixed $value The value to convert. - * @param callable $callback The callback function to use for converting the real boolean value. - * - * @return mixed - * - * @throws UnexpectedValueException - */ - private function convertSingleBooleanValue($value, $callback) - { - if ($value === null) { - return $callback(null); - } - - if (is_bool($value) || is_numeric($value)) { - return $callback((bool) $value); - } - - if (! is_string($value)) { - return $callback(true); - } - - /** - * Better safe than sorry: http://php.net/in_array#106319 - */ - if (in_array(strtolower(trim($value)), $this->booleanLiterals['false'], true)) { - return $callback(false); - } - - if (in_array(strtolower(trim($value)), $this->booleanLiterals['true'], true)) { - return $callback(true); - } - - throw new UnexpectedValueException("Unrecognized boolean literal '${value}'"); - } - - /** - * Converts one or multiple boolean values. - * - * First converts the value(s) to their native PHP boolean type - * and passes them to the given callback function to be reconverted - * into any custom representation. - * - * @param mixed $item The value(s) to convert. - * @param callable $callback The callback function to use for converting the real boolean value(s). - * - * @return mixed - */ - private function doConvertBooleans($item, $callback) - { - if (is_array($item)) { - foreach ($item as $key => $value) { - $item[$key] = $this->convertSingleBooleanValue($value, $callback); - } - - return $item; - } - - return $this->convertSingleBooleanValue($item, $callback); - } - - /** - * {@inheritDoc} - * - * Postgres wants boolean values converted to the strings 'true'/'false'. - */ - public function convertBooleans($item) - { - if (! $this->useBooleanTrueFalseStrings) { - return parent::convertBooleans($item); - } - - return $this->doConvertBooleans( - $item, - static function ($boolean) { - if ($boolean === null) { - return 'NULL'; - } - - return $boolean === true ? 'true' : 'false'; - } - ); - } - - /** - * {@inheritDoc} - */ - public function convertBooleansToDatabaseValue($item) - { - if (! $this->useBooleanTrueFalseStrings) { - return parent::convertBooleansToDatabaseValue($item); - } - - return $this->doConvertBooleans( - $item, - static function ($boolean) { - return $boolean === null ? null : (int) $boolean; - } - ); - } - - /** - * {@inheritDoc} - */ - public function convertFromBoolean($item) - { - if (in_array(strtolower($item), $this->booleanLiterals['false'], true)) { - return false; - } - - return parent::convertFromBoolean($item); - } - - /** - * {@inheritDoc} - */ - public function getSequenceNextValSQL($sequenceName) - { - return "SELECT NEXTVAL('" . $sequenceName . "')"; - } - - /** - * {@inheritDoc} - */ - public function getSetTransactionIsolationSQL($level) - { - return 'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL ' - . $this->_getTransactionIsolationLevelSQL($level); - } - - /** - * {@inheritDoc} - */ - public function getBooleanTypeDeclarationSQL(array $field) - { - return 'BOOLEAN'; - } - - /** - * {@inheritDoc} - */ - public function getIntegerTypeDeclarationSQL(array $field) - { - if (! empty($field['autoincrement'])) { - return 'SERIAL'; - } - - return 'INT'; - } - - /** - * {@inheritDoc} - */ - public function getBigIntTypeDeclarationSQL(array $field) - { - if (! empty($field['autoincrement'])) { - return 'BIGSERIAL'; - } - - return 'BIGINT'; - } - - /** - * {@inheritDoc} - */ - public function getSmallIntTypeDeclarationSQL(array $field) - { - return 'SMALLINT'; - } - - /** - * {@inheritDoc} - */ - public function getGuidTypeDeclarationSQL(array $field) - { - return 'UUID'; - } - - /** - * {@inheritDoc} - */ - public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) - { - return 'TIMESTAMP(0) WITHOUT TIME ZONE'; - } - - /** - * {@inheritDoc} - */ - public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) - { - return 'TIMESTAMP(0) WITH TIME ZONE'; - } - - /** - * {@inheritDoc} - */ - public function getDateTypeDeclarationSQL(array $fieldDeclaration) - { - return 'DATE'; - } - - /** - * {@inheritDoc} - */ - public function getTimeTypeDeclarationSQL(array $fieldDeclaration) - { - return 'TIME(0) WITHOUT TIME ZONE'; - } - - /** - * {@inheritDoc} - * - * @deprecated Use application-generated UUIDs instead - */ - public function getGuidExpression() - { - return 'UUID_GENERATE_V4()'; - } - - /** - * {@inheritDoc} - */ - protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) - { - return ''; - } - - /** - * {@inheritDoc} - */ - protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) - { - return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') - : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); - } - - /** - * {@inheritdoc} - */ - protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) - { - return 'BYTEA'; - } - - /** - * {@inheritDoc} - */ - public function getClobTypeDeclarationSQL(array $field) - { - return 'TEXT'; - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'postgresql'; - } - - /** - * {@inheritDoc} - * - * PostgreSQL returns all column names in SQL result sets in lowercase. - */ - public function getSQLResultCasing($column) - { - return strtolower($column); - } - - /** - * {@inheritDoc} - */ - public function getDateTimeTzFormatString() - { - return 'Y-m-d H:i:sO'; - } - - /** - * {@inheritDoc} - */ - public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName) - { - return 'INSERT INTO ' . $quotedTableName . ' (' . $quotedIdentifierColumnName . ') VALUES (DEFAULT)'; - } - - /** - * {@inheritDoc} - */ - public function getTruncateTableSQL($tableName, $cascade = false) - { - $tableIdentifier = new Identifier($tableName); - $sql = 'TRUNCATE ' . $tableIdentifier->getQuotedName($this); - - if ($cascade) { - $sql .= ' CASCADE'; - } - - return $sql; - } - - /** - * {@inheritDoc} - */ - public function getReadLockSQL() - { - return 'FOR SHARE'; - } - - /** - * {@inheritDoc} - */ - protected function initializeDoctrineTypeMappings() - { - $this->doctrineTypeMapping = [ - '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', - 'tsvector' => 'text', - 'varchar' => 'string', - 'interval' => 'string', - '_varchar' => 'string', - 'char' => 'string', - 'bpchar' => 'string', - 'inet' => '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', - 'uuid' => 'guid', - 'bytea' => 'blob', - ]; - } - - /** - * {@inheritDoc} - */ - public function getVarcharMaxLength() - { - return 65535; - } - - /** - * {@inheritdoc} - */ - public function getBinaryMaxLength() - { - return 0; - } - - /** - * {@inheritdoc} - */ - public function getBinaryDefaultLength() - { - return 0; - } - - /** - * {@inheritDoc} - */ - protected function getReservedKeywordsClass() - { - return Keywords\PostgreSQLKeywords::class; - } - - /** - * {@inheritDoc} - */ - public function getBlobTypeDeclarationSQL(array $field) - { - return 'BYTEA'; - } - - /** - * {@inheritdoc} - */ - public function getDefaultValueDeclarationSQL($field) - { - if ($this->isSerialField($field)) { - return ''; - } - - return parent::getDefaultValueDeclarationSQL($field); - } - - /** - * @param mixed[] $field - */ - private function isSerialField(array $field) : bool - { - return isset($field['type'], $field['autoincrement']) - && $field['autoincrement'] === true - && $this->isNumericType($field['type']); - } - - /** - * Check whether the type of a column is changed in a way that invalidates the default value for the column - */ - private function typeChangeBreaksDefaultValue(ColumnDiff $columnDiff) : bool - { - if (! $columnDiff->fromColumn) { - return $columnDiff->hasChanged('type'); - } - - $oldTypeIsNumeric = $this->isNumericType($columnDiff->fromColumn->getType()); - $newTypeIsNumeric = $this->isNumericType($columnDiff->column->getType()); - - // default should not be changed when switching between numeric types and the default comes from a sequence - return $columnDiff->hasChanged('type') - && ! ($oldTypeIsNumeric && $newTypeIsNumeric && $columnDiff->column->getAutoincrement()); - } - - private function isNumericType(Type $type) : bool - { - return $type instanceof IntegerType || $type instanceof BigIntType; - } - - private function getOldColumnComment(ColumnDiff $columnDiff) : ?string - { - return $columnDiff->fromColumn ? $this->getColumnComment($columnDiff->fromColumn) : null; - } - - public function getListTableMetadataSQL(string $table, ?string $schema = null) : string - { - if ($schema !== null) { - $table = $schema . '.' . $table; - } - - return sprintf( - <<<'SQL' -SELECT obj_description(%s::regclass) AS table_comment; -SQL - , - $this->quoteStringLiteral($table) - ); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php deleted file mode 100644 index a46ae93..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere11Platform.php +++ /dev/null @@ -1,26 +0,0 @@ -getQuotedName($this) . - ' INCREMENT BY ' . $sequence->getAllocationSize() . - ' START WITH ' . $sequence->getInitialValue() . - ' MINVALUE ' . $sequence->getInitialValue(); - } - - /** - * {@inheritdoc} - */ - public function getAlterSequenceSQL(Sequence $sequence) - { - return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . - ' INCREMENT BY ' . $sequence->getAllocationSize(); - } - - /** - * {@inheritdoc} - */ - public function getDateTimeTzFormatString() - { - return 'Y-m-d H:i:s.uP'; - } - - /** - * {@inheritdoc} - */ - public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) - { - return 'TIMESTAMP WITH TIME ZONE'; - } - - /** - * {@inheritdoc} - */ - public function getDropSequenceSQL($sequence) - { - if ($sequence instanceof Sequence) { - $sequence = $sequence->getQuotedName($this); - } - - return 'DROP SEQUENCE ' . $sequence; - } - - /** - * {@inheritdoc} - */ - public function getListSequencesSQL($database) - { - return 'SELECT sequence_name, increment_by, start_with, min_value FROM SYS.SYSSEQUENCE'; - } - - /** - * {@inheritdoc} - */ - public function getSequenceNextValSQL($sequenceName) - { - return 'SELECT ' . $sequenceName . '.NEXTVAL'; - } - - /** - * {@inheritdoc} - */ - public function supportsSequences() - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function getAdvancedIndexOptionsSQL(Index $index) - { - if (! $index->isPrimary() && $index->isUnique() && $index->hasFlag('with_nulls_not_distinct')) { - return ' WITH NULLS NOT DISTINCT' . parent::getAdvancedIndexOptionsSQL($index); - } - - return parent::getAdvancedIndexOptionsSQL($index); - } - - /** - * {@inheritdoc} - */ - protected function getReservedKeywordsClass() - { - return Keywords\SQLAnywhere12Keywords::class; - } - - /** - * {@inheritDoc} - */ - protected function initializeDoctrineTypeMappings() - { - parent::initializeDoctrineTypeMappings(); - $this->doctrineTypeMapping['timestamp with time zone'] = 'datetime'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere16Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere16Platform.php deleted file mode 100644 index 35d4238..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywhere16Platform.php +++ /dev/null @@ -1,39 +0,0 @@ -hasFlag('with_nulls_distinct') && $index->hasFlag('with_nulls_not_distinct')) { - throw new UnexpectedValueException( - 'An Index can either have a "with_nulls_distinct" or "with_nulls_not_distinct" flag but not both.' - ); - } - - if (! $index->isPrimary() && $index->isUnique() && $index->hasFlag('with_nulls_distinct')) { - return ' WITH NULLS DISTINCT' . parent::getAdvancedIndexOptionsSQL($index); - } - - return parent::getAdvancedIndexOptionsSQL($index); - } - - /** - * {@inheritdoc} - */ - protected function getReservedKeywordsClass() - { - return Keywords\SQLAnywhere16Keywords::class; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php deleted file mode 100644 index 6e3b2fc..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php +++ /dev/null @@ -1,1512 +0,0 @@ -getMaxIdentifierLength(); - - if (strlen($schemaElementName) > $maxIdentifierLength) { - return substr($schemaElementName, 0, $maxIdentifierLength); - } - - return $schemaElementName; - } - - /** - * {@inheritdoc} - */ - public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) - { - $query = ''; - - if ($foreignKey->hasOption('match')) { - $query = ' MATCH ' . $this->getForeignKeyMatchClauseSQL($foreignKey->getOption('match')); - } - - $query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey); - - if ($foreignKey->hasOption('check_on_commit') && (bool) $foreignKey->getOption('check_on_commit')) { - $query .= ' CHECK ON COMMIT'; - } - - if ($foreignKey->hasOption('clustered') && (bool) $foreignKey->getOption('clustered')) { - $query .= ' CLUSTERED'; - } - - if ($foreignKey->hasOption('for_olap_workload') && (bool) $foreignKey->getOption('for_olap_workload')) { - $query .= ' FOR OLAP WORKLOAD'; - } - - return $query; - } - - /** - * {@inheritdoc} - */ - public function getAlterTableSQL(TableDiff $diff) - { - $sql = []; - $columnSql = []; - $commentsSQL = []; - $tableSql = []; - $alterClauses = []; - - foreach ($diff->addedColumns as $column) { - if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { - continue; - } - - $alterClauses[] = $this->getAlterTableAddColumnClause($column); - - $comment = $this->getColumnComment($column); - - if ($comment === null || $comment === '') { - continue; - } - - $commentsSQL[] = $this->getCommentOnColumnSQL( - $diff->getName($this)->getQuotedName($this), - $column->getQuotedName($this), - $comment - ); - } - - foreach ($diff->removedColumns as $column) { - if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { - continue; - } - - $alterClauses[] = $this->getAlterTableRemoveColumnClause($column); - } - - foreach ($diff->changedColumns as $columnDiff) { - if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { - continue; - } - - $alterClause = $this->getAlterTableChangeColumnClause($columnDiff); - - if ($alterClause !== null) { - $alterClauses[] = $alterClause; - } - - if (! $columnDiff->hasChanged('comment')) { - continue; - } - - $column = $columnDiff->column; - - $commentsSQL[] = $this->getCommentOnColumnSQL( - $diff->getName($this)->getQuotedName($this), - $column->getQuotedName($this), - $this->getColumnComment($column) - ); - } - - foreach ($diff->renamedColumns as $oldColumnName => $column) { - if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { - continue; - } - - $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' . - $this->getAlterTableRenameColumnClause($oldColumnName, $column); - } - - if (! $this->onSchemaAlterTable($diff, $tableSql)) { - if (! empty($alterClauses)) { - $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' . implode(', ', $alterClauses); - } - - $sql = array_merge($sql, $commentsSQL); - - $newName = $diff->getNewName(); - - if ($newName !== false) { - $sql[] = $this->getAlterTableClause($diff->getName($this)) . ' ' . - $this->getAlterTableRenameTableClause($newName); - } - - $sql = array_merge( - $this->getPreAlterTableIndexForeignKeySQL($diff), - $sql, - $this->getPostAlterTableIndexForeignKeySQL($diff) - ); - } - - return array_merge($sql, $tableSql, $columnSql); - } - - /** - * Returns the SQL clause for creating a column in a table alteration. - * - * @param Column $column The column to add. - * - * @return string - */ - protected function getAlterTableAddColumnClause(Column $column) - { - return 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); - } - - /** - * Returns the SQL clause for altering a table. - * - * @param Identifier $tableName The quoted name of the table to alter. - * - * @return string - */ - protected function getAlterTableClause(Identifier $tableName) - { - return 'ALTER TABLE ' . $tableName->getQuotedName($this); - } - - /** - * Returns the SQL clause for dropping a column in a table alteration. - * - * @param Column $column The column to drop. - * - * @return string - */ - protected function getAlterTableRemoveColumnClause(Column $column) - { - return 'DROP ' . $column->getQuotedName($this); - } - - /** - * Returns the SQL clause for renaming a column in a table alteration. - * - * @param string $oldColumnName The quoted name of the column to rename. - * @param Column $column The column to rename to. - * - * @return string - */ - protected function getAlterTableRenameColumnClause($oldColumnName, Column $column) - { - $oldColumnName = new Identifier($oldColumnName); - - return 'RENAME ' . $oldColumnName->getQuotedName($this) . ' TO ' . $column->getQuotedName($this); - } - - /** - * Returns the SQL clause for renaming a table in a table alteration. - * - * @param Identifier $newTableName The quoted name of the table to rename to. - * - * @return string - */ - protected function getAlterTableRenameTableClause(Identifier $newTableName) - { - return 'RENAME ' . $newTableName->getQuotedName($this); - } - - /** - * Returns the SQL clause for altering a column in a table alteration. - * - * This method returns null in case that only the column comment has changed. - * Changes in column comments have to be handled differently. - * - * @param ColumnDiff $columnDiff The diff of the column to alter. - * - * @return string|null - */ - protected function getAlterTableChangeColumnClause(ColumnDiff $columnDiff) - { - $column = $columnDiff->column; - - // Do not return alter clause if only comment has changed. - if (! ($columnDiff->hasChanged('comment') && count($columnDiff->changedProperties) === 1)) { - $columnAlterationClause = 'ALTER ' . - $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); - - if ($columnDiff->hasChanged('default') && $column->getDefault() === null) { - $columnAlterationClause .= ', ALTER ' . $column->getQuotedName($this) . ' DROP DEFAULT'; - } - - return $columnAlterationClause; - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function getBigIntTypeDeclarationSQL(array $columnDef) - { - $columnDef['integer_type'] = 'BIGINT'; - - return $this->_getCommonIntegerTypeDeclarationSQL($columnDef); - } - - /** - * {@inheritdoc} - */ - public function getBinaryDefaultLength() - { - return 1; - } - - /** - * {@inheritdoc} - */ - public function getBinaryMaxLength() - { - return 32767; - } - - /** - * {@inheritdoc} - */ - public function getBlobTypeDeclarationSQL(array $field) - { - return 'LONG BINARY'; - } - - /** - * {@inheritdoc} - * - * BIT type columns require an explicit NULL declaration - * in SQL Anywhere if they shall be nullable. - * Otherwise by just omitting the NOT NULL clause, - * SQL Anywhere will declare them NOT NULL nonetheless. - */ - public function getBooleanTypeDeclarationSQL(array $columnDef) - { - $nullClause = isset($columnDef['notnull']) && (bool) $columnDef['notnull'] === false ? ' NULL' : ''; - - return 'BIT' . $nullClause; - } - - /** - * {@inheritdoc} - */ - public function getClobTypeDeclarationSQL(array $field) - { - return 'TEXT'; - } - - /** - * {@inheritdoc} - */ - public function getCommentOnColumnSQL($tableName, $columnName, $comment) - { - $tableName = new Identifier($tableName); - $columnName = new Identifier($columnName); - $comment = $comment === null ? 'NULL' : $this->quoteStringLiteral($comment); - - return sprintf( - 'COMMENT ON COLUMN %s.%s IS %s', - $tableName->getQuotedName($this), - $columnName->getQuotedName($this), - $comment - ); - } - - /** - * {@inheritdoc} - */ - public function getConcatExpression() - { - return 'STRING(' . implode(', ', (array) func_get_args()) . ')'; - } - - /** - * {@inheritdoc} - */ - public function getCreateConstraintSQL(Constraint $constraint, $table) - { - if ($constraint instanceof ForeignKeyConstraint) { - return $this->getCreateForeignKeySQL($constraint, $table); - } - - if ($table instanceof Table) { - $table = $table->getQuotedName($this); - } - - return 'ALTER TABLE ' . $table . - ' ADD ' . $this->getTableConstraintDeclarationSQL($constraint, $constraint->getQuotedName($this)); - } - - /** - * {@inheritdoc} - */ - public function getCreateDatabaseSQL($database) - { - $database = new Identifier($database); - - return "CREATE DATABASE '" . $database->getName() . "'"; - } - - /** - * {@inheritdoc} - * - * Appends SQL Anywhere specific flags if given. - */ - public function getCreateIndexSQL(Index $index, $table) - { - return parent::getCreateIndexSQL($index, $table) . $this->getAdvancedIndexOptionsSQL($index); - } - - /** - * {@inheritdoc} - */ - public function getCreatePrimaryKeySQL(Index $index, $table) - { - if ($table instanceof Table) { - $table = $table->getQuotedName($this); - } - - return 'ALTER TABLE ' . $table . ' ADD ' . $this->getPrimaryKeyDeclarationSQL($index); - } - - /** - * {@inheritdoc} - */ - public function getCreateTemporaryTableSnippetSQL() - { - return 'CREATE ' . $this->getTemporaryTableSQL() . ' TABLE'; - } - - /** - * {@inheritdoc} - */ - public function getCreateViewSQL($name, $sql) - { - return 'CREATE VIEW ' . $name . ' AS ' . $sql; - } - - /** - * {@inheritdoc} - */ - public function getCurrentDateSQL() - { - return 'CURRENT DATE'; - } - - /** - * {@inheritdoc} - */ - public function getCurrentTimeSQL() - { - return 'CURRENT TIME'; - } - - /** - * {@inheritdoc} - */ - public function getCurrentTimestampSQL() - { - return 'CURRENT TIMESTAMP'; - } - - /** - * {@inheritdoc} - */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) - { - $factorClause = ''; - - if ($operator === '-') { - $factorClause = '-1 * '; - } - - return 'DATEADD(' . $unit . ', ' . $factorClause . $interval . ', ' . $date . ')'; - } - - /** - * {@inheritdoc} - */ - public function getDateDiffExpression($date1, $date2) - { - return 'DATEDIFF(day, ' . $date2 . ', ' . $date1 . ')'; - } - - /** - * {@inheritdoc} - */ - public function getDateTimeFormatString() - { - return 'Y-m-d H:i:s.u'; - } - - /** - * {@inheritdoc} - */ - public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) - { - return 'DATETIME'; - } - - /** - * {@inheritdoc} - */ - public function getDateTimeTzFormatString() - { - return $this->getDateTimeFormatString(); - } - - /** - * {@inheritdoc} - */ - public function getDateTypeDeclarationSQL(array $fieldDeclaration) - { - return 'DATE'; - } - - /** - * {@inheritdoc} - */ - public function getDefaultTransactionIsolationLevel() - { - return TransactionIsolationLevel::READ_UNCOMMITTED; - } - - /** - * {@inheritdoc} - */ - public function getDropDatabaseSQL($database) - { - $database = new Identifier($database); - - return "DROP DATABASE '" . $database->getName() . "'"; - } - - /** - * {@inheritdoc} - */ - public function getDropIndexSQL($index, $table = null) - { - if ($index instanceof Index) { - $index = $index->getQuotedName($this); - } - - if (! is_string($index)) { - throw new InvalidArgumentException( - 'SQLAnywherePlatform::getDropIndexSQL() expects $index parameter to be string or ' . Index::class . '.' - ); - } - - if (! isset($table)) { - return 'DROP INDEX ' . $index; - } - - if ($table instanceof Table) { - $table = $table->getQuotedName($this); - } - - if (! is_string($table)) { - throw new InvalidArgumentException( - 'SQLAnywherePlatform::getDropIndexSQL() expects $table parameter to be string or ' . Index::class . '.' - ); - } - - return 'DROP INDEX ' . $table . '.' . $index; - } - - /** - * {@inheritdoc} - */ - public function getDropViewSQL($name) - { - return 'DROP VIEW ' . $name; - } - - /** - * {@inheritdoc} - */ - public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint $foreignKey) - { - $sql = ''; - $foreignKeyName = $foreignKey->getName(); - $localColumns = $foreignKey->getQuotedLocalColumns($this); - $foreignColumns = $foreignKey->getQuotedForeignColumns($this); - $foreignTableName = $foreignKey->getQuotedForeignTableName($this); - - if (! empty($foreignKeyName)) { - $sql .= 'CONSTRAINT ' . $foreignKey->getQuotedName($this) . ' '; - } - - if (empty($localColumns)) { - throw new InvalidArgumentException("Incomplete definition. 'local' required."); - } - - if (empty($foreignColumns)) { - throw new InvalidArgumentException("Incomplete definition. 'foreign' required."); - } - - if (empty($foreignTableName)) { - throw new InvalidArgumentException("Incomplete definition. 'foreignTable' required."); - } - - if ($foreignKey->hasOption('notnull') && (bool) $foreignKey->getOption('notnull')) { - $sql .= 'NOT NULL '; - } - - return $sql . - 'FOREIGN KEY (' . $this->getIndexFieldDeclarationListSQL($localColumns) . ') ' . - 'REFERENCES ' . $foreignKey->getQuotedForeignTableName($this) . - ' (' . $this->getIndexFieldDeclarationListSQL($foreignColumns) . ')'; - } - - /** - * Returns foreign key MATCH clause for given type. - * - * @param int $type The foreign key match type - * - * @return string - * - * @throws InvalidArgumentException If unknown match type given. - */ - public function getForeignKeyMatchClauseSQL($type) - { - switch ((int) $type) { - case self::FOREIGN_KEY_MATCH_SIMPLE: - return 'SIMPLE'; - - break; - case self::FOREIGN_KEY_MATCH_FULL: - return 'FULL'; - - break; - case self::FOREIGN_KEY_MATCH_SIMPLE_UNIQUE: - return 'UNIQUE SIMPLE'; - - break; - case self::FOREIGN_KEY_MATCH_FULL_UNIQUE: - return 'UNIQUE FULL'; - default: - throw new InvalidArgumentException('Invalid foreign key match type: ' . $type); - } - } - - /** - * {@inheritdoc} - */ - public function getForeignKeyReferentialActionSQL($action) - { - // NO ACTION is not supported, therefore falling back to RESTRICT. - if (strtoupper($action) === 'NO ACTION') { - return 'RESTRICT'; - } - - return parent::getForeignKeyReferentialActionSQL($action); - } - - /** - * {@inheritdoc} - */ - public function getForUpdateSQL() - { - return ''; - } - - /** - * {@inheritdoc} - * - * @deprecated Use application-generated UUIDs instead - */ - public function getGuidExpression() - { - return 'NEWID()'; - } - - /** - * {@inheritdoc} - */ - public function getGuidTypeDeclarationSQL(array $field) - { - return 'UNIQUEIDENTIFIER'; - } - - /** - * {@inheritdoc} - */ - public function getIndexDeclarationSQL($name, Index $index) - { - // Index declaration in statements like CREATE TABLE is not supported. - throw DBALException::notSupported(__METHOD__); - } - - /** - * {@inheritdoc} - */ - public function getIntegerTypeDeclarationSQL(array $columnDef) - { - $columnDef['integer_type'] = 'INT'; - - return $this->_getCommonIntegerTypeDeclarationSQL($columnDef); - } - - /** - * {@inheritdoc} - */ - public function getListDatabasesSQL() - { - return 'SELECT db_name(number) AS name FROM sa_db_list()'; - } - - /** - * {@inheritdoc} - */ - public function getListTableColumnsSQL($table, $database = null) - { - $user = 'USER_NAME()'; - - if (strpos($table, '.') !== false) { - [$user, $table] = explode('.', $table); - $user = $this->quoteStringLiteral($user); - } - - return sprintf( - <<<'SQL' -SELECT col.column_name, - COALESCE(def.user_type_name, def.domain_name) AS 'type', - def.declared_width AS 'length', - def.scale, - CHARINDEX('unsigned', def.domain_name) AS 'unsigned', - IF col.nulls = 'Y' THEN 0 ELSE 1 ENDIF AS 'notnull', - col."default", - def.is_autoincrement AS 'autoincrement', - rem.remarks AS 'comment' -FROM sa_describe_query('SELECT * FROM "%s"') AS def -JOIN SYS.SYSTABCOL AS col -ON col.table_id = def.base_table_id AND col.column_id = def.base_column_id -LEFT JOIN SYS.SYSREMARK AS rem -ON col.object_id = rem.object_id -WHERE def.base_owner_name = %s -ORDER BY def.base_column_id ASC -SQL - , - $table, - $user - ); - } - - /** - * {@inheritdoc} - * - * @todo Where is this used? Which information should be retrieved? - */ - public function getListTableConstraintsSQL($table) - { - $user = ''; - - if (strpos($table, '.') !== false) { - [$user, $table] = explode('.', $table); - $user = $this->quoteStringLiteral($user); - $table = $this->quoteStringLiteral($table); - } else { - $table = $this->quoteStringLiteral($table); - } - - return sprintf( - <<<'SQL' -SELECT con.* -FROM SYS.SYSCONSTRAINT AS con -JOIN SYS.SYSTAB AS tab ON con.table_object_id = tab.object_id -WHERE tab.table_name = %s -AND tab.creator = USER_ID(%s) -SQL - , - $table, - $user - ); - } - - /** - * {@inheritdoc} - */ - public function getListTableForeignKeysSQL($table) - { - $user = ''; - - if (strpos($table, '.') !== false) { - [$user, $table] = explode('.', $table); - $user = $this->quoteStringLiteral($user); - $table = $this->quoteStringLiteral($table); - } else { - $table = $this->quoteStringLiteral($table); - } - - return sprintf( - <<<'SQL' -SELECT fcol.column_name AS local_column, - ptbl.table_name AS foreign_table, - pcol.column_name AS foreign_column, - idx.index_name, - IF fk.nulls = 'N' - THEN 1 - ELSE NULL - ENDIF AS notnull, - CASE ut.referential_action - WHEN 'C' THEN 'CASCADE' - WHEN 'D' THEN 'SET DEFAULT' - WHEN 'N' THEN 'SET NULL' - WHEN 'R' THEN 'RESTRICT' - ELSE NULL - END AS on_update, - CASE dt.referential_action - WHEN 'C' THEN 'CASCADE' - WHEN 'D' THEN 'SET DEFAULT' - WHEN 'N' THEN 'SET NULL' - WHEN 'R' THEN 'RESTRICT' - ELSE NULL - END AS on_delete, - IF fk.check_on_commit = 'Y' - THEN 1 - ELSE NULL - ENDIF AS check_on_commit, -- check_on_commit flag - IF ftbl.clustered_index_id = idx.index_id - THEN 1 - ELSE NULL - ENDIF AS 'clustered', -- clustered flag - IF fk.match_type = 0 - THEN NULL - ELSE fk.match_type - ENDIF AS 'match', -- match option - IF pidx.max_key_distance = 1 - THEN 1 - ELSE NULL - ENDIF AS for_olap_workload -- for_olap_workload flag -FROM SYS.SYSFKEY AS fk -JOIN SYS.SYSIDX AS idx -ON fk.foreign_table_id = idx.table_id -AND fk.foreign_index_id = idx.index_id -JOIN SYS.SYSPHYSIDX pidx -ON idx.table_id = pidx.table_id -AND idx.phys_index_id = pidx.phys_index_id -JOIN SYS.SYSTAB AS ptbl -ON fk.primary_table_id = ptbl.table_id -JOIN SYS.SYSTAB AS ftbl -ON fk.foreign_table_id = ftbl.table_id -JOIN SYS.SYSIDXCOL AS idxcol -ON idx.table_id = idxcol.table_id -AND idx.index_id = idxcol.index_id -JOIN SYS.SYSTABCOL AS pcol -ON ptbl.table_id = pcol.table_id -AND idxcol.primary_column_id = pcol.column_id -JOIN SYS.SYSTABCOL AS fcol -ON ftbl.table_id = fcol.table_id -AND idxcol.column_id = fcol.column_id -LEFT JOIN SYS.SYSTRIGGER ut -ON fk.foreign_table_id = ut.foreign_table_id -AND fk.foreign_index_id = ut.foreign_key_id -AND ut.event = 'C' -LEFT JOIN SYS.SYSTRIGGER dt -ON fk.foreign_table_id = dt.foreign_table_id -AND fk.foreign_index_id = dt.foreign_key_id -AND dt.event = 'D' -WHERE ftbl.table_name = %s -AND ftbl.creator = USER_ID(%s) -ORDER BY fk.foreign_index_id ASC, idxcol.sequence ASC -SQL - , - $table, - $user - ); - } - - /** - * {@inheritdoc} - */ - public function getListTableIndexesSQL($table, $currentDatabase = null) - { - $user = ''; - - if (strpos($table, '.') !== false) { - [$user, $table] = explode('.', $table); - $user = $this->quoteStringLiteral($user); - $table = $this->quoteStringLiteral($table); - } else { - $table = $this->quoteStringLiteral($table); - } - - return sprintf( - <<<'SQL' -SELECT idx.index_name AS key_name, - IF idx.index_category = 1 - THEN 1 - ELSE 0 - ENDIF AS 'primary', - col.column_name, - IF idx."unique" IN(1, 2, 5) - THEN 0 - ELSE 1 - ENDIF AS non_unique, - IF tbl.clustered_index_id = idx.index_id - THEN 1 - ELSE NULL - ENDIF AS 'clustered', -- clustered flag - IF idx."unique" = 5 - THEN 1 - ELSE NULL - ENDIF AS with_nulls_not_distinct, -- with_nulls_not_distinct flag - IF pidx.max_key_distance = 1 - THEN 1 - ELSE NULL - ENDIF AS for_olap_workload -- for_olap_workload flag -FROM SYS.SYSIDX AS idx -JOIN SYS.SYSPHYSIDX pidx -ON idx.table_id = pidx.table_id -AND idx.phys_index_id = pidx.phys_index_id -JOIN SYS.SYSIDXCOL AS idxcol -ON idx.table_id = idxcol.table_id AND idx.index_id = idxcol.index_id -JOIN SYS.SYSTABCOL AS col -ON idxcol.table_id = col.table_id AND idxcol.column_id = col.column_id -JOIN SYS.SYSTAB AS tbl -ON idx.table_id = tbl.table_id -WHERE tbl.table_name = %s -AND tbl.creator = USER_ID(%s) -AND idx.index_category != 2 -- exclude indexes implicitly created by foreign key constraints -ORDER BY idx.index_id ASC, idxcol.sequence ASC -SQL - , - $table, - $user - ); - } - - /** - * {@inheritdoc} - */ - public function getListTablesSQL() - { - return "SELECT tbl.table_name - FROM SYS.SYSTAB AS tbl - JOIN SYS.SYSUSER AS usr ON tbl.creator = usr.user_id - JOIN dbo.SYSOBJECTS AS obj ON tbl.object_id = obj.id - WHERE tbl.table_type IN(1, 3) -- 'BASE', 'GBL TEMP' - AND usr.user_name NOT IN('SYS', 'dbo', 'rs_systabgroup') -- exclude system users - AND obj.type = 'U' -- user created tables only - ORDER BY tbl.table_name ASC"; - } - - /** - * {@inheritdoc} - * - * @todo Where is this used? Which information should be retrieved? - */ - public function getListUsersSQL() - { - return 'SELECT * FROM SYS.SYSUSER ORDER BY user_name ASC'; - } - - /** - * {@inheritdoc} - */ - public function getListViewsSQL($database) - { - return "SELECT tbl.table_name, v.view_def - FROM SYS.SYSVIEW v - JOIN SYS.SYSTAB tbl ON v.view_object_id = tbl.object_id - JOIN SYS.SYSUSER usr ON tbl.creator = usr.user_id - JOIN dbo.SYSOBJECTS obj ON tbl.object_id = obj.id - WHERE usr.user_name NOT IN('SYS', 'dbo', 'rs_systabgroup') -- exclude system users - ORDER BY tbl.table_name ASC"; - } - - /** - * {@inheritdoc} - */ - public function getLocateExpression($str, $substr, $startPos = false) - { - if ($startPos === false) { - return 'LOCATE(' . $str . ', ' . $substr . ')'; - } - - return 'LOCATE(' . $str . ', ' . $substr . ', ' . $startPos . ')'; - } - - /** - * {@inheritdoc} - */ - public function getMaxIdentifierLength() - { - return 128; - } - - /** - * {@inheritdoc} - */ - public function getMd5Expression($column) - { - return 'HASH(' . $column . ", 'MD5')"; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'sqlanywhere'; - } - - /** - * Obtain DBMS specific SQL code portion needed to set a primary key - * declaration to be used in statements like ALTER TABLE. - * - * @param Index $index Index definition - * @param string $name Name of the primary key - * - * @return string DBMS specific SQL code portion needed to set a primary key - * - * @throws InvalidArgumentException If the given index is not a primary key. - */ - public function getPrimaryKeyDeclarationSQL(Index $index, $name = null) - { - if (! $index->isPrimary()) { - throw new InvalidArgumentException( - 'Can only create primary key declarations with getPrimaryKeyDeclarationSQL()' - ); - } - - return $this->getTableConstraintDeclarationSQL($index, $name); - } - - /** - * {@inheritdoc} - */ - public function getSetTransactionIsolationSQL($level) - { - return 'SET TEMPORARY OPTION isolation_level = ' . $this->_getTransactionIsolationLevelSQL($level); - } - - /** - * {@inheritdoc} - */ - public function getSmallIntTypeDeclarationSQL(array $columnDef) - { - $columnDef['integer_type'] = 'SMALLINT'; - - return $this->_getCommonIntegerTypeDeclarationSQL($columnDef); - } - - /** - * Returns the SQL statement for starting an existing database. - * - * In SQL Anywhere you can start and stop databases on a - * database server instance. - * This is a required statement after having created a new database - * as it has to be explicitly started to be usable. - * SQL Anywhere does not automatically start a database after creation! - * - * @param string $database Name of the database to start. - * - * @return string - */ - public function getStartDatabaseSQL($database) - { - $database = new Identifier($database); - - return "START DATABASE '" . $database->getName() . "' AUTOSTOP OFF"; - } - - /** - * Returns the SQL statement for stopping a running database. - * - * In SQL Anywhere you can start and stop databases on a - * database server instance. - * This is a required statement before dropping an existing database - * as it has to be explicitly stopped before it can be dropped. - * - * @param string $database Name of the database to stop. - * - * @return string - */ - public function getStopDatabaseSQL($database) - { - $database = new Identifier($database); - - return 'STOP DATABASE "' . $database->getName() . '" UNCONDITIONALLY'; - } - - /** - * {@inheritdoc} - */ - public function getSubstringExpression($value, $from, $length = null) - { - if ($length === null) { - return 'SUBSTRING(' . $value . ', ' . $from . ')'; - } - - return 'SUBSTRING(' . $value . ', ' . $from . ', ' . $length . ')'; - } - - /** - * {@inheritdoc} - */ - public function getTemporaryTableSQL() - { - return 'GLOBAL TEMPORARY'; - } - - /** - * {@inheritdoc} - */ - public function getTimeFormatString() - { - return 'H:i:s.u'; - } - - /** - * {@inheritdoc} - */ - public function getTimeTypeDeclarationSQL(array $fieldDeclaration) - { - return 'TIME'; - } - - /** - * {@inheritdoc} - */ - public function getTrimExpression($str, $pos = TrimMode::UNSPECIFIED, $char = false) - { - if (! $char) { - switch ($pos) { - case TrimMode::LEADING: - return $this->getLtrimExpression($str); - case TrimMode::TRAILING: - return $this->getRtrimExpression($str); - default: - return 'TRIM(' . $str . ')'; - } - } - - $pattern = "'%[^' + " . $char . " + ']%'"; - - switch ($pos) { - case TrimMode::LEADING: - return 'SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))'; - case TrimMode::TRAILING: - return 'REVERSE(SUBSTR(REVERSE(' . $str . '), PATINDEX(' . $pattern . ', REVERSE(' . $str . '))))'; - default: - return 'REVERSE(SUBSTR(REVERSE(SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))), ' . - 'PATINDEX(' . $pattern . ', REVERSE(SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))))))'; - } - } - - /** - * {@inheritdoc} - */ - public function getTruncateTableSQL($tableName, $cascade = false) - { - $tableIdentifier = new Identifier($tableName); - - return 'TRUNCATE TABLE ' . $tableIdentifier->getQuotedName($this); - } - - /** - * {@inheritdoc} - */ - public function getUniqueConstraintDeclarationSQL($name, Index $index) - { - if ($index->isPrimary()) { - throw new InvalidArgumentException( - 'Cannot create primary key constraint declarations with getUniqueConstraintDeclarationSQL().' - ); - } - - if (! $index->isUnique()) { - throw new InvalidArgumentException( - 'Can only create unique constraint declarations, no common index declarations with ' . - 'getUniqueConstraintDeclarationSQL().' - ); - } - - return $this->getTableConstraintDeclarationSQL($index, $name); - } - - /** - * {@inheritdoc} - */ - public function getVarcharDefaultLength() - { - return 1; - } - - /** - * {@inheritdoc} - */ - public function getVarcharMaxLength() - { - return 32767; - } - - /** - * {@inheritdoc} - */ - public function hasNativeGuidType() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function prefersIdentityColumns() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function supportsCommentOnStatement() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function supportsIdentityColumns() - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) - { - $unsigned = ! empty($columnDef['unsigned']) ? 'UNSIGNED ' : ''; - $autoincrement = ! empty($columnDef['autoincrement']) ? ' IDENTITY' : ''; - - return $unsigned . $columnDef['integer_type'] . $autoincrement; - } - - /** - * {@inheritdoc} - */ - protected function _getCreateTableSQL($tableName, array $columns, array $options = []) - { - $columnListSql = $this->getColumnDeclarationListSQL($columns); - $indexSql = []; - - if (! empty($options['uniqueConstraints'])) { - foreach ((array) $options['uniqueConstraints'] as $name => $definition) { - $columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition); - } - } - - if (! empty($options['indexes'])) { - /** @var Index $index */ - foreach ((array) $options['indexes'] as $index) { - $indexSql[] = $this->getCreateIndexSQL($index, $tableName); - } - } - - if (! empty($options['primary'])) { - $flags = ''; - - if (isset($options['primary_index']) && $options['primary_index']->hasFlag('clustered')) { - $flags = ' CLUSTERED '; - } - - $columnListSql .= ', PRIMARY KEY' . $flags . ' (' . implode(', ', array_unique(array_values((array) $options['primary']))) . ')'; - } - - if (! empty($options['foreignKeys'])) { - foreach ((array) $options['foreignKeys'] as $definition) { - $columnListSql .= ', ' . $this->getForeignKeyDeclarationSQL($definition); - } - } - - $query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql; - $check = $this->getCheckDeclarationSQL($columns); - - if (! empty($check)) { - $query .= ', ' . $check; - } - - $query .= ')'; - - return array_merge([$query], $indexSql); - } - - /** - * {@inheritdoc} - */ - protected function _getTransactionIsolationLevelSQL($level) - { - switch ($level) { - case TransactionIsolationLevel::READ_UNCOMMITTED: - return 0; - case TransactionIsolationLevel::READ_COMMITTED: - return 1; - case TransactionIsolationLevel::REPEATABLE_READ: - return 2; - case TransactionIsolationLevel::SERIALIZABLE: - return 3; - default: - throw new InvalidArgumentException('Invalid isolation level:' . $level); - } - } - - /** - * {@inheritdoc} - */ - protected function doModifyLimitQuery($query, $limit, $offset) - { - $limitOffsetClause = $this->getTopClauseSQL($limit, $offset); - - if ($limitOffsetClause === '') { - return $query; - } - - if (! preg_match('/^\s*(SELECT\s+(DISTINCT\s+)?)(.*)/i', $query, $matches)) { - return $query; - } - - return $matches[1] . $limitOffsetClause . ' ' . $matches[3]; - } - - private function getTopClauseSQL(?int $limit, ?int $offset) : string - { - if ($offset > 0) { - return sprintf('TOP %s START AT %d', $limit ?? 'ALL', $offset + 1); - } - - return $limit === null ? '' : 'TOP ' . $limit; - } - - /** - * Return the INDEX query section dealing with non-standard - * SQL Anywhere options. - * - * @param Index $index Index definition - * - * @return string - */ - protected function getAdvancedIndexOptionsSQL(Index $index) - { - $sql = ''; - - if (! $index->isPrimary() && $index->hasFlag('for_olap_workload')) { - $sql .= ' FOR OLAP WORKLOAD'; - } - - return $sql; - } - - /** - * {@inheritdoc} - */ - protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) - { - return $fixed - ? 'BINARY(' . ($length ?: $this->getBinaryDefaultLength()) . ')' - : 'VARBINARY(' . ($length ?: $this->getBinaryDefaultLength()) . ')'; - } - - /** - * Returns the SQL snippet for creating a table constraint. - * - * @param Constraint $constraint The table constraint to create the SQL snippet for. - * @param string|null $name The table constraint name to use if any. - * - * @return string - * - * @throws InvalidArgumentException If the given table constraint type is not supported by this method. - */ - protected function getTableConstraintDeclarationSQL(Constraint $constraint, $name = null) - { - if ($constraint instanceof ForeignKeyConstraint) { - return $this->getForeignKeyDeclarationSQL($constraint); - } - - if (! $constraint instanceof Index) { - throw new InvalidArgumentException('Unsupported constraint type: ' . get_class($constraint)); - } - - if (! $constraint->isPrimary() && ! $constraint->isUnique()) { - throw new InvalidArgumentException( - 'Can only create primary, unique or foreign key constraint declarations, no common index declarations ' . - 'with getTableConstraintDeclarationSQL().' - ); - } - - $constraintColumns = $constraint->getQuotedColumns($this); - - if (empty($constraintColumns)) { - throw new InvalidArgumentException("Incomplete definition. 'columns' required."); - } - - $sql = ''; - $flags = ''; - - if (! empty($name)) { - $name = new Identifier($name); - $sql .= 'CONSTRAINT ' . $name->getQuotedName($this) . ' '; - } - - if ($constraint->hasFlag('clustered')) { - $flags = 'CLUSTERED '; - } - - if ($constraint->isPrimary()) { - return $sql . 'PRIMARY KEY ' . $flags . '(' . $this->getIndexFieldDeclarationListSQL($constraintColumns) . ')'; - } - - return $sql . 'UNIQUE ' . $flags . '(' . $this->getIndexFieldDeclarationListSQL($constraintColumns) . ')'; - } - - /** - * {@inheritdoc} - */ - protected function getCreateIndexSQLFlags(Index $index) - { - $type = ''; - if ($index->hasFlag('virtual')) { - $type .= 'VIRTUAL '; - } - - if ($index->isUnique()) { - $type .= 'UNIQUE '; - } - - if ($index->hasFlag('clustered')) { - $type .= 'CLUSTERED '; - } - - return $type; - } - - /** - * {@inheritdoc} - */ - protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) - { - return ['ALTER INDEX ' . $oldIndexName . ' ON ' . $tableName . ' RENAME TO ' . $index->getQuotedName($this)]; - } - - /** - * {@inheritdoc} - */ - protected function getReservedKeywordsClass() - { - return Keywords\SQLAnywhereKeywords::class; - } - - /** - * {@inheritdoc} - */ - protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) - { - return $fixed - ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(' . $this->getVarcharDefaultLength() . ')') - : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(' . $this->getVarcharDefaultLength() . ')'); - } - - /** - * {@inheritdoc} - */ - protected function initializeDoctrineTypeMappings() - { - $this->doctrineTypeMapping = [ - 'char' => 'string', - 'long nvarchar' => 'text', - 'long varchar' => 'text', - 'nchar' => 'string', - 'ntext' => 'text', - 'nvarchar' => 'string', - 'text' => 'text', - 'uniqueidentifierstr' => 'guid', - 'varchar' => 'string', - 'xml' => 'text', - 'bigint' => 'bigint', - 'unsigned bigint' => 'bigint', - 'bit' => 'boolean', - 'decimal' => 'decimal', - 'double' => 'float', - 'float' => 'float', - 'int' => 'integer', - 'integer' => 'integer', - 'unsigned int' => 'integer', - 'numeric' => 'decimal', - 'smallint' => 'smallint', - 'unsigned smallint' => 'smallint', - 'tinyint' => 'smallint', - 'unsigned tinyint' => 'smallint', - 'money' => 'decimal', - 'smallmoney' => 'decimal', - 'long varbit' => 'text', - 'varbit' => 'string', - 'date' => 'date', - 'datetime' => 'datetime', - 'smalldatetime' => 'datetime', - 'time' => 'time', - 'timestamp' => 'datetime', - 'binary' => 'binary', - 'image' => 'blob', - 'long binary' => 'blob', - 'uniqueidentifier' => 'guid', - 'varbinary' => 'binary', - ]; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAzurePlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAzurePlatform.php deleted file mode 100644 index a104848..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLAzurePlatform.php +++ /dev/null @@ -1,33 +0,0 @@ -hasOption('azure.federatedOnColumnName')) { - $distributionName = $table->getOption('azure.federatedOnDistributionName'); - $columnName = $table->getOption('azure.federatedOnColumnName'); - $stmt = ' FEDERATED ON (' . $distributionName . ' = ' . $columnName . ')'; - - $sql[0] .= $stmt; - } - - return $sql; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php deleted file mode 100644 index 1026a93..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2005Platform.php +++ /dev/null @@ -1,46 +0,0 @@ -doctrineTypeMapping['datetime2'] = 'datetime'; - $this->doctrineTypeMapping['date'] = 'date'; - $this->doctrineTypeMapping['time'] = 'time'; - $this->doctrineTypeMapping['datetimeoffset'] = 'datetimetz'; - } - - /** - * {@inheritdoc} - * - * Returns Microsoft SQL Server 2008 specific keywords class - */ - protected function getReservedKeywordsClass() - { - return Keywords\SQLServer2008Keywords::class; - } - - protected function getLikeWildcardCharacters() : string - { - return parent::getLikeWildcardCharacters() . '[]^'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2012Platform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2012Platform.php deleted file mode 100644 index 009a37d..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServer2012Platform.php +++ /dev/null @@ -1,143 +0,0 @@ -getQuotedName($this) . - ' INCREMENT BY ' . $sequence->getAllocationSize(); - } - - /** - * {@inheritdoc} - */ - public function getCreateSequenceSQL(Sequence $sequence) - { - return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . - ' START WITH ' . $sequence->getInitialValue() . - ' INCREMENT BY ' . $sequence->getAllocationSize() . - ' MINVALUE ' . $sequence->getInitialValue(); - } - - /** - * {@inheritdoc} - */ - public function getDropSequenceSQL($sequence) - { - if ($sequence instanceof Sequence) { - $sequence = $sequence->getQuotedName($this); - } - - return 'DROP SEQUENCE ' . $sequence; - } - - /** - * {@inheritdoc} - */ - public function getListSequencesSQL($database) - { - return 'SELECT seq.name, - CAST( - seq.increment AS VARCHAR(MAX) - ) AS increment, -- CAST avoids driver error for sql_variant type - CAST( - seq.start_value AS VARCHAR(MAX) - ) AS start_value -- CAST avoids driver error for sql_variant type - FROM sys.sequences AS seq'; - } - - /** - * {@inheritdoc} - */ - public function getSequenceNextValSQL($sequenceName) - { - return 'SELECT NEXT VALUE FOR ' . $sequenceName; - } - - /** - * {@inheritdoc} - */ - public function supportsSequences() - { - return true; - } - - /** - * {@inheritdoc} - * - * Returns Microsoft SQL Server 2012 specific keywords class - */ - protected function getReservedKeywordsClass() - { - return Keywords\SQLServer2012Keywords::class; - } - - /** - * {@inheritdoc} - */ - protected function doModifyLimitQuery($query, $limit, $offset = null) - { - if ($limit === null && $offset <= 0) { - return $query; - } - - // Queries using OFFSET... FETCH MUST have an ORDER BY clause - // Find the position of the last instance of ORDER BY and ensure it is not within a parenthetical statement - // but can be in a newline - $matches = []; - $matchesCount = preg_match_all('/[\\s]+order\\s+by\\s/im', $query, $matches, PREG_OFFSET_CAPTURE); - $orderByPos = false; - if ($matchesCount > 0) { - $orderByPos = $matches[0][($matchesCount - 1)][1]; - } - - if ($orderByPos === false - || substr_count($query, '(', $orderByPos) - substr_count($query, ')', $orderByPos) - ) { - if (preg_match('/^SELECT\s+DISTINCT/im', $query)) { - // SQL Server won't let us order by a non-selected column in a DISTINCT query, - // so we have to do this madness. This says, order by the first column in the - // result. SQL Server's docs say that a nonordered query's result order is non- - // deterministic anyway, so this won't do anything that a bunch of update and - // deletes to the table wouldn't do anyway. - $query .= ' ORDER BY 1'; - } else { - // In another DBMS, we could do ORDER BY 0, but SQL Server gets angry if you - // use constant expressions in the order by list. - $query .= ' ORDER BY (SELECT 0)'; - } - } - - if ($offset === null) { - $offset = 0; - } - - // This looks somewhat like MYSQL, but limit/offset are in inverse positions - // Supposedly SQL:2008 core standard. - // Per TSQL spec, FETCH NEXT n ROWS ONLY is not valid without OFFSET n ROWS. - $query .= ' OFFSET ' . (int) $offset . ' ROWS'; - - if ($limit !== null) { - $query .= ' FETCH NEXT ' . (int) $limit . ' ROWS ONLY'; - } - - return $query; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php deleted file mode 100644 index a37f7c9..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php +++ /dev/null @@ -1,1695 +0,0 @@ -getConvertExpression('date', 'GETDATE()'); - } - - /** - * {@inheritdoc} - */ - public function getCurrentTimeSQL() - { - return $this->getConvertExpression('time', 'GETDATE()'); - } - - /** - * Returns an expression that converts an expression of one data type to another. - * - * @param string $dataType The target native data type. Alias data types cannot be used. - * @param string $expression The SQL expression to convert. - * - * @return string - */ - private function getConvertExpression($dataType, $expression) - { - return sprintf('CONVERT(%s, %s)', $dataType, $expression); - } - - /** - * {@inheritdoc} - */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) - { - $factorClause = ''; - - if ($operator === '-') { - $factorClause = '-1 * '; - } - - return 'DATEADD(' . $unit . ', ' . $factorClause . $interval . ', ' . $date . ')'; - } - - /** - * {@inheritDoc} - */ - public function getDateDiffExpression($date1, $date2) - { - return 'DATEDIFF(day, ' . $date2 . ',' . $date1 . ')'; - } - - /** - * {@inheritDoc} - * - * Microsoft SQL Server prefers "autoincrement" identity columns - * since sequences can only be emulated with a table. - */ - public function prefersIdentityColumns() - { - return true; - } - - /** - * {@inheritDoc} - * - * Microsoft SQL Server supports this through AUTO_INCREMENT columns. - */ - public function supportsIdentityColumns() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function supportsReleaseSavepoints() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function supportsSchemas() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function getDefaultSchemaName() - { - return 'dbo'; - } - - /** - * {@inheritDoc} - */ - public function supportsColumnCollation() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function hasNativeGuidType() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function getCreateDatabaseSQL($name) - { - return 'CREATE DATABASE ' . $name; - } - - /** - * {@inheritDoc} - */ - public function getDropDatabaseSQL($name) - { - return 'DROP DATABASE ' . $name; - } - - /** - * {@inheritDoc} - */ - public function supportsCreateDropDatabase() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function getCreateSchemaSQL($schemaName) - { - return 'CREATE SCHEMA ' . $schemaName; - } - - /** - * {@inheritDoc} - */ - public function getDropForeignKeySQL($foreignKey, $table) - { - if (! $foreignKey instanceof ForeignKeyConstraint) { - $foreignKey = new Identifier($foreignKey); - } - - if (! $table instanceof Table) { - $table = new Identifier($table); - } - - $foreignKey = $foreignKey->getQuotedName($this); - $table = $table->getQuotedName($this); - - return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey; - } - - /** - * {@inheritDoc} - */ - public function getDropIndexSQL($index, $table = null) - { - if ($index instanceof Index) { - $index = $index->getQuotedName($this); - } elseif (! 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; - } - - if ($table instanceof Table) { - $table = $table->getQuotedName($this); - } - - return sprintf( - <<getCommentOnTableSQL($tableName, $tableComment); - } - - // @todo does other code breaks because of this? - // force primary keys to be not null - foreach ($columns as &$column) { - if (isset($column['primary']) && $column['primary']) { - $column['notnull'] = true; - } - - // Build default constraints SQL statements. - if (isset($column['default'])) { - $defaultConstraintsSql[] = 'ALTER TABLE ' . $tableName . - ' ADD' . $this->getDefaultConstraintDeclarationSQL($tableName, $column); - } - - if (empty($column['comment']) && ! is_numeric($column['comment'])) { - continue; - } - - $commentsSql[] = $this->getCreateColumnCommentSQL($tableName, $column['name'], $column['comment']); - } - - $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'])) { - $flags = ''; - if (isset($options['primary_index']) && $options['primary_index']->hasFlag('nonclustered')) { - $flags = ' NONCLUSTERED'; - } - $columnListSql .= ', PRIMARY KEY' . $flags . ' (' . 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 array_merge($sql, $commentsSql, $defaultConstraintsSql); - } - - /** - * {@inheritDoc} - */ - public function getCreatePrimaryKeySQL(Index $index, $table) - { - if ($table instanceof Table) { - $identifier = $table->getQuotedName($this); - } else { - $identifier = $table; - } - - $sql = 'ALTER TABLE ' . $identifier . ' ADD PRIMARY KEY'; - - if ($index->hasFlag('nonclustered')) { - $sql .= ' NONCLUSTERED'; - } - - return $sql . ' (' . $this->getIndexFieldDeclarationListSQL($index) . ')'; - } - - /** - * Returns the SQL statement for creating a column comment. - * - * SQL Server does not support native column comments, - * therefore the extended properties functionality is used - * as a workaround to store them. - * The property name used to store column comments is "MS_Description" - * which provides compatibility with SQL Server Management Studio, - * as column comments are stored in the same property there when - * specifying a column's "Description" attribute. - * - * @param string $tableName The quoted table name to which the column belongs. - * @param string $columnName The quoted column name to create the comment for. - * @param string|null $comment The column's comment. - * - * @return string - */ - protected function getCreateColumnCommentSQL($tableName, $columnName, $comment) - { - if (strpos($tableName, '.') !== false) { - [$schemaSQL, $tableSQL] = explode('.', $tableName); - $schemaSQL = $this->quoteStringLiteral($schemaSQL); - $tableSQL = $this->quoteStringLiteral($tableSQL); - } else { - $schemaSQL = "'dbo'"; - $tableSQL = $this->quoteStringLiteral($tableName); - } - - return $this->getAddExtendedPropertySQL( - 'MS_Description', - $comment, - 'SCHEMA', - $schemaSQL, - 'TABLE', - $tableSQL, - 'COLUMN', - $columnName - ); - } - - /** - * Returns the SQL snippet for declaring a default constraint. - * - * @param string $table Name of the table to return the default constraint declaration for. - * @param mixed[] $column Column definition. - * - * @return string - * - * @throws InvalidArgumentException - */ - public function getDefaultConstraintDeclarationSQL($table, array $column) - { - if (! isset($column['default'])) { - throw new InvalidArgumentException("Incomplete column definition. 'default' required."); - } - - $columnName = new Identifier($column['name']); - - return ' CONSTRAINT ' . - $this->generateDefaultConstraintName($table, $column['name']) . - $this->getDefaultValueDeclarationSQL($column) . - ' FOR ' . $columnName->getQuotedName($this); - } - - /** - * {@inheritDoc} - */ - public function getUniqueConstraintDeclarationSQL($name, Index $index) - { - $constraint = parent::getUniqueConstraintDeclarationSQL($name, $index); - - $constraint = $this->_appendUniqueConstraintDefinition($constraint, $index); - - return $constraint; - } - - /** - * {@inheritDoc} - */ - public function getCreateIndexSQL(Index $index, $table) - { - $constraint = parent::getCreateIndexSQL($index, $table); - - if ($index->isUnique() && ! $index->isPrimary()) { - $constraint = $this->_appendUniqueConstraintDefinition($constraint, $index); - } - - return $constraint; - } - - /** - * {@inheritDoc} - */ - protected function getCreateIndexSQLFlags(Index $index) - { - $type = ''; - if ($index->isUnique()) { - $type .= 'UNIQUE '; - } - - if ($index->hasFlag('clustered')) { - $type .= 'CLUSTERED '; - } elseif ($index->hasFlag('nonclustered')) { - $type .= 'NONCLUSTERED '; - } - - return $type; - } - - /** - * Extend unique key constraint with required filters - * - * @param string $sql - * - * @return string - */ - private function _appendUniqueConstraintDefinition($sql, Index $index) - { - $fields = []; - - foreach ($index->getQuotedColumns($this) as $field) { - $fields[] = $field . ' IS NOT NULL'; - } - - return $sql . ' WHERE ' . implode(' AND ', $fields); - } - - /** - * {@inheritDoc} - */ - public function getAlterTableSQL(TableDiff $diff) - { - $queryParts = []; - $sql = []; - $columnSql = []; - $commentsSql = []; - - foreach ($diff->addedColumns as $column) { - if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { - continue; - } - - $columnDef = $column->toArray(); - $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); - - if (isset($columnDef['default'])) { - $queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column); - } - - $comment = $this->getColumnComment($column); - - if (empty($comment) && ! is_numeric($comment)) { - continue; - } - - $commentsSql[] = $this->getCreateColumnCommentSQL( - $diff->name, - $column->getQuotedName($this), - $comment - ); - } - - foreach ($diff->removedColumns as $column) { - if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { - continue; - } - - $queryParts[] = 'DROP COLUMN ' . $column->getQuotedName($this); - } - - foreach ($diff->changedColumns as $columnDiff) { - if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { - continue; - } - - $column = $columnDiff->column; - $comment = $this->getColumnComment($column); - $hasComment = ! empty($comment) || is_numeric($comment); - - if ($columnDiff->fromColumn instanceof Column) { - $fromComment = $this->getColumnComment($columnDiff->fromColumn); - $hasFromComment = ! empty($fromComment) || is_numeric($fromComment); - - if ($hasFromComment && $hasComment && $fromComment !== $comment) { - $commentsSql[] = $this->getAlterColumnCommentSQL( - $diff->name, - $column->getQuotedName($this), - $comment - ); - } elseif ($hasFromComment && ! $hasComment) { - $commentsSql[] = $this->getDropColumnCommentSQL($diff->name, $column->getQuotedName($this)); - } elseif ($hasComment) { - $commentsSql[] = $this->getCreateColumnCommentSQL( - $diff->name, - $column->getQuotedName($this), - $comment - ); - } - } - - // Do not add query part if only comment has changed. - if ($columnDiff->hasChanged('comment') && count($columnDiff->changedProperties) === 1) { - continue; - } - - $requireDropDefaultConstraint = $this->alterColumnRequiresDropDefaultConstraint($columnDiff); - - if ($requireDropDefaultConstraint) { - $queryParts[] = $this->getAlterTableDropDefaultConstraintClause( - $diff->name, - $columnDiff->oldColumnName - ); - } - - $columnDef = $column->toArray(); - - $queryParts[] = 'ALTER COLUMN ' . - $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); - - if (! isset($columnDef['default']) || (! $requireDropDefaultConstraint && ! $columnDiff->hasChanged('default'))) { - continue; - } - - $queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column); - } - - foreach ($diff->renamedColumns as $oldColumnName => $column) { - if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { - continue; - } - - $oldColumnName = new Identifier($oldColumnName); - - $sql[] = "sp_RENAME '" . - $diff->getName($this)->getQuotedName($this) . '.' . $oldColumnName->getQuotedName($this) . - "', '" . $column->getQuotedName($this) . "', 'COLUMN'"; - - // Recreate default constraint with new column name if necessary (for future reference). - if ($column->getDefault() === null) { - continue; - } - - $queryParts[] = $this->getAlterTableDropDefaultConstraintClause( - $diff->name, - $oldColumnName->getQuotedName($this) - ); - $queryParts[] = $this->getAlterTableAddDefaultConstraintClause($diff->name, $column); - } - - $tableSql = []; - - if ($this->onSchemaAlterTable($diff, $tableSql)) { - return array_merge($tableSql, $columnSql); - } - - foreach ($queryParts as $query) { - $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . $query; - } - - $sql = array_merge($sql, $commentsSql); - - $newName = $diff->getNewName(); - - if ($newName !== false) { - $sql[] = "sp_RENAME '" . $diff->getName($this)->getQuotedName($this) . "', '" . $newName->getName() . "'"; - - /** - * Rename table's default constraints names - * to match the new table name. - * This is necessary to ensure that the default - * constraints can be referenced in future table - * alterations as the table name is encoded in - * default constraints' names. - */ - $sql[] = "DECLARE @sql NVARCHAR(MAX) = N''; " . - "SELECT @sql += N'EXEC sp_rename N''' + dc.name + ''', N''' " . - "+ REPLACE(dc.name, '" . $this->generateIdentifierName($diff->name) . "', " . - "'" . $this->generateIdentifierName($newName->getName()) . "') + ''', ''OBJECT'';' " . - 'FROM sys.default_constraints dc ' . - 'JOIN sys.tables tbl ON dc.parent_object_id = tbl.object_id ' . - "WHERE tbl.name = '" . $newName->getName() . "';" . - 'EXEC sp_executesql @sql'; - } - - $sql = array_merge( - $this->getPreAlterTableIndexForeignKeySQL($diff), - $sql, - $this->getPostAlterTableIndexForeignKeySQL($diff) - ); - - return array_merge($sql, $tableSql, $columnSql); - } - - /** - * Returns the SQL clause for adding a default constraint in an ALTER TABLE statement. - * - * @param string $tableName The name of the table to generate the clause for. - * @param Column $column The column to generate the clause for. - * - * @return string - */ - private function getAlterTableAddDefaultConstraintClause($tableName, Column $column) - { - $columnDef = $column->toArray(); - $columnDef['name'] = $column->getQuotedName($this); - - return 'ADD' . $this->getDefaultConstraintDeclarationSQL($tableName, $columnDef); - } - - /** - * Returns the SQL clause for dropping an existing default constraint in an ALTER TABLE statement. - * - * @param string $tableName The name of the table to generate the clause for. - * @param string $columnName The name of the column to generate the clause for. - * - * @return string - */ - private function getAlterTableDropDefaultConstraintClause($tableName, $columnName) - { - return 'DROP CONSTRAINT ' . $this->generateDefaultConstraintName($tableName, $columnName); - } - - /** - * Checks whether a column alteration requires dropping its default constraint first. - * - * Different to other database vendors SQL Server implements column default values - * as constraints and therefore changes in a column's default value as well as changes - * in a column's type require dropping the default constraint first before being to - * alter the particular column to the new definition. - * - * @param ColumnDiff $columnDiff The column diff to evaluate. - * - * @return bool True if the column alteration requires dropping its default constraint first, false otherwise. - */ - private function alterColumnRequiresDropDefaultConstraint(ColumnDiff $columnDiff) - { - // We can only decide whether to drop an existing default constraint - // if we know the original default value. - if (! $columnDiff->fromColumn instanceof Column) { - return false; - } - - // We only need to drop an existing default constraint if we know the - // column was defined with a default value before. - if ($columnDiff->fromColumn->getDefault() === null) { - return false; - } - - // We need to drop an existing default constraint if the column was - // defined with a default value before and it has changed. - if ($columnDiff->hasChanged('default')) { - return true; - } - - // We need to drop an existing default constraint if the column was - // defined with a default value before and the native column type has changed. - return $columnDiff->hasChanged('type') || $columnDiff->hasChanged('fixed'); - } - - /** - * Returns the SQL statement for altering a column comment. - * - * SQL Server does not support native column comments, - * therefore the extended properties functionality is used - * as a workaround to store them. - * The property name used to store column comments is "MS_Description" - * which provides compatibility with SQL Server Management Studio, - * as column comments are stored in the same property there when - * specifying a column's "Description" attribute. - * - * @param string $tableName The quoted table name to which the column belongs. - * @param string $columnName The quoted column name to alter the comment for. - * @param string|null $comment The column's comment. - * - * @return string - */ - protected function getAlterColumnCommentSQL($tableName, $columnName, $comment) - { - if (strpos($tableName, '.') !== false) { - [$schemaSQL, $tableSQL] = explode('.', $tableName); - $schemaSQL = $this->quoteStringLiteral($schemaSQL); - $tableSQL = $this->quoteStringLiteral($tableSQL); - } else { - $schemaSQL = "'dbo'"; - $tableSQL = $this->quoteStringLiteral($tableName); - } - - return $this->getUpdateExtendedPropertySQL( - 'MS_Description', - $comment, - 'SCHEMA', - $schemaSQL, - 'TABLE', - $tableSQL, - 'COLUMN', - $columnName - ); - } - - /** - * Returns the SQL statement for dropping a column comment. - * - * SQL Server does not support native column comments, - * therefore the extended properties functionality is used - * as a workaround to store them. - * The property name used to store column comments is "MS_Description" - * which provides compatibility with SQL Server Management Studio, - * as column comments are stored in the same property there when - * specifying a column's "Description" attribute. - * - * @param string $tableName The quoted table name to which the column belongs. - * @param string $columnName The quoted column name to drop the comment for. - * - * @return string - */ - protected function getDropColumnCommentSQL($tableName, $columnName) - { - if (strpos($tableName, '.') !== false) { - [$schemaSQL, $tableSQL] = explode('.', $tableName); - $schemaSQL = $this->quoteStringLiteral($schemaSQL); - $tableSQL = $this->quoteStringLiteral($tableSQL); - } else { - $schemaSQL = "'dbo'"; - $tableSQL = $this->quoteStringLiteral($tableName); - } - - return $this->getDropExtendedPropertySQL( - 'MS_Description', - 'SCHEMA', - $schemaSQL, - 'TABLE', - $tableSQL, - 'COLUMN', - $columnName - ); - } - - /** - * {@inheritdoc} - */ - protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) - { - return [sprintf( - "EXEC sp_RENAME N'%s.%s', N'%s', N'INDEX'", - $tableName, - $oldIndexName, - $index->getQuotedName($this) - ), - ]; - } - - /** - * Returns the SQL statement for adding an extended property to a database object. - * - * @link http://msdn.microsoft.com/en-us/library/ms180047%28v=sql.90%29.aspx - * - * @param string $name The name of the property to add. - * @param string|null $value The value of the property to add. - * @param string|null $level0Type The type of the object at level 0 the property belongs to. - * @param string|null $level0Name The name of the object at level 0 the property belongs to. - * @param string|null $level1Type The type of the object at level 1 the property belongs to. - * @param string|null $level1Name The name of the object at level 1 the property belongs to. - * @param string|null $level2Type The type of the object at level 2 the property belongs to. - * @param string|null $level2Name The name of the object at level 2 the property belongs to. - * - * @return string - */ - public function getAddExtendedPropertySQL( - $name, - $value = null, - $level0Type = null, - $level0Name = null, - $level1Type = null, - $level1Name = null, - $level2Type = null, - $level2Name = null - ) { - return 'EXEC sp_addextendedproperty ' . - 'N' . $this->quoteStringLiteral($name) . ', N' . $this->quoteStringLiteral((string) $value) . ', ' . - 'N' . $this->quoteStringLiteral((string) $level0Type) . ', ' . $level0Name . ', ' . - 'N' . $this->quoteStringLiteral((string) $level1Type) . ', ' . $level1Name . ', ' . - 'N' . $this->quoteStringLiteral((string) $level2Type) . ', ' . $level2Name; - } - - /** - * Returns the SQL statement for dropping an extended property from a database object. - * - * @link http://technet.microsoft.com/en-gb/library/ms178595%28v=sql.90%29.aspx - * - * @param string $name The name of the property to drop. - * @param string|null $level0Type The type of the object at level 0 the property belongs to. - * @param string|null $level0Name The name of the object at level 0 the property belongs to. - * @param string|null $level1Type The type of the object at level 1 the property belongs to. - * @param string|null $level1Name The name of the object at level 1 the property belongs to. - * @param string|null $level2Type The type of the object at level 2 the property belongs to. - * @param string|null $level2Name The name of the object at level 2 the property belongs to. - * - * @return string - */ - public function getDropExtendedPropertySQL( - $name, - $level0Type = null, - $level0Name = null, - $level1Type = null, - $level1Name = null, - $level2Type = null, - $level2Name = null - ) { - return 'EXEC sp_dropextendedproperty ' . - 'N' . $this->quoteStringLiteral($name) . ', ' . - 'N' . $this->quoteStringLiteral((string) $level0Type) . ', ' . $level0Name . ', ' . - 'N' . $this->quoteStringLiteral((string) $level1Type) . ', ' . $level1Name . ', ' . - 'N' . $this->quoteStringLiteral((string) $level2Type) . ', ' . $level2Name; - } - - /** - * Returns the SQL statement for updating an extended property of a database object. - * - * @link http://msdn.microsoft.com/en-us/library/ms186885%28v=sql.90%29.aspx - * - * @param string $name The name of the property to update. - * @param string|null $value The value of the property to update. - * @param string|null $level0Type The type of the object at level 0 the property belongs to. - * @param string|null $level0Name The name of the object at level 0 the property belongs to. - * @param string|null $level1Type The type of the object at level 1 the property belongs to. - * @param string|null $level1Name The name of the object at level 1 the property belongs to. - * @param string|null $level2Type The type of the object at level 2 the property belongs to. - * @param string|null $level2Name The name of the object at level 2 the property belongs to. - * - * @return string - */ - public function getUpdateExtendedPropertySQL( - $name, - $value = null, - $level0Type = null, - $level0Name = null, - $level1Type = null, - $level1Name = null, - $level2Type = null, - $level2Name = null - ) { - return 'EXEC sp_updateextendedproperty ' . - 'N' . $this->quoteStringLiteral($name) . ', N' . $this->quoteStringLiteral((string) $value) . ', ' . - 'N' . $this->quoteStringLiteral((string) $level0Type) . ', ' . $level0Name . ', ' . - 'N' . $this->quoteStringLiteral((string) $level1Type) . ', ' . $level1Name . ', ' . - 'N' . $this->quoteStringLiteral((string) $level2Type) . ', ' . $level2Name; - } - - /** - * {@inheritDoc} - */ - public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName) - { - return 'INSERT INTO ' . $quotedTableName . ' DEFAULT VALUES'; - } - - /** - * {@inheritDoc} - */ - public function getListTablesSQL() - { - // "sysdiagrams" table must be ignored as it's internal SQL Server table for Database Diagrams - // Category 2 must be ignored as it is "MS SQL Server 'pseudo-system' object[s]" for replication - return "SELECT name FROM sysobjects WHERE type = 'U' AND name != 'sysdiagrams' AND category != 2 ORDER BY name"; - } - - /** - * {@inheritDoc} - */ - public function getListTableColumnsSQL($table, $database = null) - { - return "SELECT col.name, - type.name AS type, - col.max_length AS length, - ~col.is_nullable AS notnull, - def.definition AS [default], - col.scale, - col.precision, - col.is_identity AS autoincrement, - col.collation_name AS collation, - CAST(prop.value AS NVARCHAR(MAX)) AS comment -- CAST avoids driver error for sql_variant type - FROM sys.columns AS col - JOIN sys.types AS type - ON col.user_type_id = type.user_type_id - JOIN sys.objects AS obj - ON col.object_id = obj.object_id - JOIN sys.schemas AS scm - ON obj.schema_id = scm.schema_id - LEFT JOIN sys.default_constraints def - ON col.default_object_id = def.object_id - AND col.object_id = def.parent_object_id - LEFT JOIN sys.extended_properties AS prop - ON obj.object_id = prop.major_id - AND col.column_id = prop.minor_id - AND prop.name = 'MS_Description' - WHERE obj.type = 'U' - AND " . $this->getTableWhereClause($table, 'scm.name', 'obj.name'); - } - - /** - * {@inheritDoc} - */ - 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 ' . - $this->getTableWhereClause($table, 'SCHEMA_NAME (f.schema_id)', 'OBJECT_NAME (f.parent_object_id)'); - } - - /** - * {@inheritDoc} - */ - public function getListTableIndexesSQL($table, $currentDatabase = null) - { - return "SELECT idx.name AS key_name, - col.name AS column_name, - ~idx.is_unique AS non_unique, - idx.is_primary_key AS [primary], - CASE idx.type - WHEN '1' THEN 'clustered' - WHEN '2' THEN 'nonclustered' - ELSE NULL - END AS flags - FROM sys.tables AS tbl - JOIN sys.schemas AS scm ON tbl.schema_id = scm.schema_id - JOIN sys.indexes AS idx ON tbl.object_id = idx.object_id - JOIN sys.index_columns AS idxcol ON idx.object_id = idxcol.object_id AND idx.index_id = idxcol.index_id - JOIN sys.columns AS col ON idxcol.object_id = col.object_id AND idxcol.column_id = col.column_id - WHERE " . $this->getTableWhereClause($table, 'scm.name', 'tbl.name') . ' - ORDER BY idx.index_id ASC, idxcol.key_ordinal ASC'; - } - - /** - * {@inheritDoc} - */ - public function getCreateViewSQL($name, $sql) - { - return 'CREATE VIEW ' . $name . ' AS ' . $sql; - } - - /** - * {@inheritDoc} - */ - public function getListViewsSQL($database) - { - return "SELECT name FROM sysobjects WHERE type = 'V' ORDER BY name"; - } - - /** - * Returns the where clause to filter schema and table name in a query. - * - * @param string $table The full qualified name of the table. - * @param string $schemaColumn The name of the column to compare the schema to in the where clause. - * @param string $tableColumn The name of the column to compare the table to in the where clause. - * - * @return string - */ - private function getTableWhereClause($table, $schemaColumn, $tableColumn) - { - if (strpos($table, '.') !== false) { - [$schema, $table] = explode('.', $table); - $schema = $this->quoteStringLiteral($schema); - $table = $this->quoteStringLiteral($table); - } else { - $schema = 'SCHEMA_NAME()'; - $table = $this->quoteStringLiteral($table); - } - - return sprintf('(%s = %s AND %s = %s)', $tableColumn, $table, $schemaColumn, $schema); - } - - /** - * {@inheritDoc} - */ - public function getDropViewSQL($name) - { - return 'DROP VIEW ' . $name; - } - - /** - * {@inheritDoc} - * - * @deprecated Use application-generated UUIDs instead - */ - public function getGuidExpression() - { - return 'NEWID()'; - } - - /** - * {@inheritDoc} - */ - public function getLocateExpression($str, $substr, $startPos = false) - { - if ($startPos === false) { - return 'CHARINDEX(' . $substr . ', ' . $str . ')'; - } - - return 'CHARINDEX(' . $substr . ', ' . $str . ', ' . $startPos . ')'; - } - - /** - * {@inheritDoc} - */ - public function getModExpression($expression1, $expression2) - { - return $expression1 . ' % ' . $expression2; - } - - /** - * {@inheritDoc} - */ - public function getTrimExpression($str, $pos = TrimMode::UNSPECIFIED, $char = false) - { - if (! $char) { - switch ($pos) { - case TrimMode::LEADING: - $trimFn = 'LTRIM'; - break; - - case TrimMode::TRAILING: - $trimFn = 'RTRIM'; - break; - - default: - return 'LTRIM(RTRIM(' . $str . '))'; - } - - return $trimFn . '(' . $str . ')'; - } - - /** Original query used to get those expressions - declare @c varchar(100) = 'xxxBarxxx', @trim_char char(1) = 'x'; - declare @pat varchar(10) = '%[^' + @trim_char + ']%'; - select @c as string - , @trim_char as trim_char - , stuff(@c, 1, patindex(@pat, @c) - 1, null) as trim_leading - , reverse(stuff(reverse(@c), 1, patindex(@pat, reverse(@c)) - 1, null)) as trim_trailing - , reverse(stuff(reverse(stuff(@c, 1, patindex(@pat, @c) - 1, null)), 1, patindex(@pat, reverse(stuff(@c, 1, patindex(@pat, @c) - 1, null))) - 1, null)) as trim_both; - */ - $pattern = "'%[^' + " . $char . " + ']%'"; - - if ($pos === TrimMode::LEADING) { - return 'stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null)'; - } - - if ($pos === TrimMode::TRAILING) { - return 'reverse(stuff(reverse(' . $str . '), 1, patindex(' . $pattern . ', reverse(' . $str . ')) - 1, null))'; - } - - return 'reverse(stuff(reverse(stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null)), 1, patindex(' . $pattern . ', reverse(stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null))) - 1, null))'; - } - - /** - * {@inheritDoc} - */ - public function getConcatExpression() - { - $args = func_get_args(); - - return '(' . implode(' + ', $args) . ')'; - } - - /** - * {@inheritDoc} - */ - public function getListDatabasesSQL() - { - return 'SELECT * FROM sys.databases'; - } - - /** - * {@inheritDoc} - */ - public function getListNamespacesSQL() - { - return "SELECT name FROM sys.schemas WHERE name NOT IN('guest', 'INFORMATION_SCHEMA', 'sys')"; - } - - /** - * {@inheritDoc} - */ - public function getSubstringExpression($value, $from, $length = null) - { - if ($length !== null) { - return 'SUBSTRING(' . $value . ', ' . $from . ', ' . $length . ')'; - } - - return 'SUBSTRING(' . $value . ', ' . $from . ', LEN(' . $value . ') - ' . $from . ' + 1)'; - } - - /** - * {@inheritDoc} - */ - public function getLengthExpression($column) - { - return 'LEN(' . $column . ')'; - } - - /** - * {@inheritDoc} - */ - public function getSetTransactionIsolationSQL($level) - { - return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level); - } - - /** - * {@inheritDoc} - */ - public function getIntegerTypeDeclarationSQL(array $field) - { - return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - public function getBigIntTypeDeclarationSQL(array $field) - { - return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - public function getSmallIntTypeDeclarationSQL(array $field) - { - return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - public function getGuidTypeDeclarationSQL(array $field) - { - return 'UNIQUEIDENTIFIER'; - } - - /** - * {@inheritDoc} - */ - protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) - { - return $fixed ? ($length ? 'NCHAR(' . $length . ')' : 'CHAR(255)') : ($length ? 'NVARCHAR(' . $length . ')' : 'NVARCHAR(255)'); - } - - /** - * {@inheritdoc} - */ - protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) - { - return $fixed ? 'BINARY(' . ($length ?: 255) . ')' : 'VARBINARY(' . ($length ?: 255) . ')'; - } - - /** - * {@inheritdoc} - */ - public function getBinaryMaxLength() - { - return 8000; - } - - /** - * {@inheritDoc} - */ - public function getClobTypeDeclarationSQL(array $field) - { - return 'VARCHAR(MAX)'; - } - - /** - * {@inheritDoc} - */ - protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) - { - return ! empty($columnDef['autoincrement']) ? ' IDENTITY' : ''; - } - - /** - * {@inheritDoc} - */ - public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) - { - return 'DATETIME'; - } - - /** - * {@inheritDoc} - */ - public function getDateTypeDeclarationSQL(array $fieldDeclaration) - { - return 'DATETIME'; - } - - /** - * {@inheritDoc} - */ - public function getTimeTypeDeclarationSQL(array $fieldDeclaration) - { - return 'DATETIME'; - } - - /** - * {@inheritDoc} - */ - public function getBooleanTypeDeclarationSQL(array $field) - { - return 'BIT'; - } - - /** - * {@inheritDoc} - */ - protected function doModifyLimitQuery($query, $limit, $offset = null) - { - $where = []; - - if ($offset > 0) { - $where[] = sprintf('doctrine_rownum >= %d', $offset + 1); - } - - if ($limit !== null) { - $where[] = sprintf('doctrine_rownum <= %d', $offset + $limit); - $top = sprintf('TOP %d', $offset + $limit); - } else { - $top = 'TOP 9223372036854775807'; - } - - if (empty($where)) { - return $query; - } - - // We'll find a SELECT or SELECT distinct and prepend TOP n to it - // Even if the TOP n is very large, the use of a CTE will - // allow the SQL Server query planner to optimize it so it doesn't - // actually scan the entire range covered by the TOP clause. - if (! preg_match('/^(\s*SELECT\s+(?:DISTINCT\s+)?)(.*)$/is', $query, $matches)) { - return $query; - } - - $query = $matches[1] . $top . ' ' . $matches[2]; - - if (stristr($query, 'ORDER BY')) { - // Inner order by is not valid in SQL Server for our purposes - // unless it's in a TOP N subquery. - $query = $this->scrubInnerOrderBy($query); - } - - // Build a new limited query around the original, using a CTE - return sprintf( - 'WITH dctrn_cte AS (%s) ' - . 'SELECT * FROM (' - . 'SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM dctrn_cte' - . ') AS doctrine_tbl ' - . 'WHERE %s ORDER BY doctrine_rownum ASC', - $query, - implode(' AND ', $where) - ); - } - - /** - * Remove ORDER BY clauses in subqueries - they're not supported by SQL Server. - * Caveat: will leave ORDER BY in TOP N subqueries. - * - * @param string $query - * - * @return string - */ - private function scrubInnerOrderBy($query) - { - $count = substr_count(strtoupper($query), 'ORDER BY'); - $offset = 0; - - while ($count-- > 0) { - $orderByPos = stripos($query, ' ORDER BY', $offset); - if ($orderByPos === false) { - break; - } - - $qLen = strlen($query); - $parenCount = 0; - $currentPosition = $orderByPos; - - while ($parenCount >= 0 && $currentPosition < $qLen) { - if ($query[$currentPosition] === '(') { - $parenCount++; - } elseif ($query[$currentPosition] === ')') { - $parenCount--; - } - - $currentPosition++; - } - - if ($this->isOrderByInTopNSubquery($query, $orderByPos)) { - // If the order by clause is in a TOP N subquery, do not remove - // it and continue iteration from the current position. - $offset = $currentPosition; - continue; - } - - if ($currentPosition >= $qLen - 1) { - continue; - } - - $query = substr($query, 0, $orderByPos) . substr($query, $currentPosition - 1); - $offset = $orderByPos; - } - - return $query; - } - - /** - * Check an ORDER BY clause to see if it is in a TOP N query or subquery. - * - * @param string $query The query - * @param int $currentPosition Start position of ORDER BY clause - * - * @return bool true if ORDER BY is in a TOP N query, false otherwise - */ - private function isOrderByInTopNSubquery($query, $currentPosition) - { - // Grab query text on the same nesting level as the ORDER BY clause we're examining. - $subQueryBuffer = ''; - $parenCount = 0; - - // If $parenCount goes negative, we've exited the subquery we're examining. - // If $currentPosition goes negative, we've reached the beginning of the query. - while ($parenCount >= 0 && $currentPosition >= 0) { - if ($query[$currentPosition] === '(') { - $parenCount--; - } elseif ($query[$currentPosition] === ')') { - $parenCount++; - } - - // Only yank query text on the same nesting level as the ORDER BY clause. - $subQueryBuffer = ($parenCount === 0 ? $query[$currentPosition] : ' ') . $subQueryBuffer; - - $currentPosition--; - } - - return (bool) preg_match('/SELECT\s+(DISTINCT\s+)?TOP\s/i', $subQueryBuffer); - } - - /** - * {@inheritDoc} - */ - public function supportsLimitOffset() - { - return false; - } - - /** - * {@inheritDoc} - */ - public function convertBooleans($item) - { - if (is_array($item)) { - foreach ($item as $key => $value) { - if (! is_bool($value) && ! is_numeric($value)) { - continue; - } - - $item[$key] = $value ? 1 : 0; - } - } elseif (is_bool($item) || is_numeric($item)) { - $item = $item ? 1 : 0; - } - - return $item; - } - - /** - * {@inheritDoc} - */ - public function getCreateTemporaryTableSnippetSQL() - { - return 'CREATE TABLE'; - } - - /** - * {@inheritDoc} - */ - public function getTemporaryTableName($tableName) - { - return '#' . $tableName; - } - - /** - * {@inheritDoc} - */ - public function getDateTimeFormatString() - { - return 'Y-m-d H:i:s.000'; - } - - /** - * {@inheritDoc} - */ - public function getDateFormatString() - { - return 'Y-m-d H:i:s.000'; - } - - /** - * {@inheritDoc} - */ - public function getTimeFormatString() - { - return 'Y-m-d H:i:s.000'; - } - - /** - * {@inheritDoc} - */ - public function getDateTimeTzFormatString() - { - return $this->getDateTimeFormatString(); - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'mssql'; - } - - /** - * {@inheritDoc} - */ - protected function initializeDoctrineTypeMappings() - { - $this->doctrineTypeMapping = [ - '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', - 'smalldatetime' => 'datetime', - 'datetime' => 'datetime', - 'char' => 'string', - 'varchar' => 'string', - 'text' => 'text', - 'nchar' => 'string', - 'nvarchar' => 'string', - 'ntext' => 'text', - 'binary' => 'binary', - 'varbinary' => 'binary', - 'image' => 'blob', - 'uniqueidentifier' => 'guid', - ]; - } - - /** - * {@inheritDoc} - */ - public function createSavePoint($savepoint) - { - return 'SAVE TRANSACTION ' . $savepoint; - } - - /** - * {@inheritDoc} - */ - public function releaseSavePoint($savepoint) - { - return ''; - } - - /** - * {@inheritDoc} - */ - public function rollbackSavePoint($savepoint) - { - return 'ROLLBACK TRANSACTION ' . $savepoint; - } - - /** - * {@inheritdoc} - */ - public function getForeignKeyReferentialActionSQL($action) - { - // RESTRICT is not supported, therefore falling back to NO ACTION. - if (strtoupper($action) === 'RESTRICT') { - return 'NO ACTION'; - } - - return parent::getForeignKeyReferentialActionSQL($action); - } - - /** - * {@inheritDoc} - */ - public function appendLockHint($fromClause, $lockMode) - { - switch (true) { - case $lockMode === LockMode::NONE: - return $fromClause . ' WITH (NOLOCK)'; - - case $lockMode === LockMode::PESSIMISTIC_READ: - return $fromClause . ' WITH (HOLDLOCK, ROWLOCK)'; - - case $lockMode === LockMode::PESSIMISTIC_WRITE: - return $fromClause . ' WITH (UPDLOCK, ROWLOCK)'; - - default: - return $fromClause; - } - } - - /** - * {@inheritDoc} - */ - public function getForUpdateSQL() - { - return ' '; - } - - /** - * {@inheritDoc} - */ - protected function getReservedKeywordsClass() - { - return Keywords\SQLServerKeywords::class; - } - - /** - * {@inheritDoc} - */ - public function quoteSingleIdentifier($str) - { - return '[' . str_replace(']', '][', $str) . ']'; - } - - /** - * {@inheritDoc} - */ - public function getTruncateTableSQL($tableName, $cascade = false) - { - $tableIdentifier = new Identifier($tableName); - - return 'TRUNCATE TABLE ' . $tableIdentifier->getQuotedName($this); - } - - /** - * {@inheritDoc} - */ - public function getBlobTypeDeclarationSQL(array $field) - { - return 'VARBINARY(MAX)'; - } - - /** - * {@inheritdoc} - * - * Modifies column declaration order as it differs in Microsoft SQL Server. - */ - public function getColumnDeclarationSQL($name, array $field) - { - if (isset($field['columnDefinition'])) { - $columnDef = $this->getCustomTypeDeclarationSQL($field); - } else { - $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 . $collation . $notnull . $unique . $check; - } - - return $name . ' ' . $columnDef; - } - - /** - * Returns a unique default constraint name for a table and column. - * - * @param string $table Name of the table to generate the unique default constraint name for. - * @param string $column Name of the column in the table to generate the unique default constraint name for. - * - * @return string - */ - private function generateDefaultConstraintName($table, $column) - { - return 'DF_' . $this->generateIdentifierName($table) . '_' . $this->generateIdentifierName($column); - } - - /** - * Returns a hash value for a given identifier. - * - * @param string $identifier Identifier to generate a hash value for. - * - * @return string - */ - private function generateIdentifierName($identifier) - { - // Always generate name for unquoted identifiers to ensure consistency. - $identifier = new Identifier($identifier); - - return strtoupper(dechex(crc32($identifier->getName()))); - } - - protected function getCommentOnTableSQL(string $tableName, ?string $comment) : string - { - return sprintf( - <<<'SQL' -EXEC sys.sp_addextendedproperty @name=N'MS_Description', - @value=N%s, @level0type=N'SCHEMA', @level0name=N'dbo', - @level1type=N'TABLE', @level1name=N%s -SQL - , - $this->quoteStringLiteral((string) $comment), - $this->quoteStringLiteral($tableName) - ); - } - - public function getListTableMetadataSQL(string $table) : string - { - return sprintf( - <<<'SQL' -SELECT - p.value AS [table_comment] -FROM - sys.tables AS tbl - INNER JOIN sys.extended_properties AS p ON p.major_id=tbl.object_id AND p.minor_id=0 AND p.class=1 -WHERE - (tbl.name=N%s and SCHEMA_NAME(tbl.schema_id)=N'dbo' and p.name=N'MS_Description') -SQL - , - $this->quoteStringLiteral($table) - ); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php deleted file mode 100644 index 02d2482..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php +++ /dev/null @@ -1,1199 +0,0 @@ -_getTransactionIsolationLevelSQL($level); - } - - /** - * {@inheritDoc} - */ - public function prefersIdentityColumns() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function getBooleanTypeDeclarationSQL(array $field) - { - return 'BOOLEAN'; - } - - /** - * {@inheritDoc} - */ - public function getIntegerTypeDeclarationSQL(array $field) - { - return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - public function getBigIntTypeDeclarationSQL(array $field) - { - // SQLite autoincrement is implicit for INTEGER PKs, but not for BIGINT fields. - if (! empty($field['autoincrement'])) { - return $this->getIntegerTypeDeclarationSQL($field); - } - - return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - public function getTinyIntTypeDeclarationSql(array $field) - { - // SQLite autoincrement is implicit for INTEGER PKs, but not for TINYINT fields. - if (! empty($field['autoincrement'])) { - return $this->getIntegerTypeDeclarationSQL($field); - } - - return 'TINYINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - public function getSmallIntTypeDeclarationSQL(array $field) - { - // SQLite autoincrement is implicit for INTEGER PKs, but not for SMALLINT fields. - if (! empty($field['autoincrement'])) { - return $this->getIntegerTypeDeclarationSQL($field); - } - - return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - public function getMediumIntTypeDeclarationSql(array $field) - { - // SQLite autoincrement is implicit for INTEGER PKs, but not for MEDIUMINT fields. - if (! empty($field['autoincrement'])) { - return $this->getIntegerTypeDeclarationSQL($field); - } - - return 'MEDIUMINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); - } - - /** - * {@inheritDoc} - */ - public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) - { - return 'DATETIME'; - } - - /** - * {@inheritDoc} - */ - public function getDateTypeDeclarationSQL(array $fieldDeclaration) - { - return 'DATE'; - } - - /** - * {@inheritDoc} - */ - public function getTimeTypeDeclarationSQL(array $fieldDeclaration) - { - return 'TIME'; - } - - /** - * {@inheritDoc} - */ - protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) - { - // sqlite autoincrement is only possible for the primary key - if (! empty($columnDef['autoincrement'])) { - return ' PRIMARY KEY AUTOINCREMENT'; - } - - return ! empty($columnDef['unsigned']) ? ' UNSIGNED' : ''; - } - - /** - * {@inheritDoc} - */ - public function getForeignKeyDeclarationSQL(ForeignKeyConstraint $foreignKey) - { - return parent::getForeignKeyDeclarationSQL(new ForeignKeyConstraint( - $foreignKey->getQuotedLocalColumns($this), - str_replace('.', '__', $foreignKey->getQuotedForeignTableName($this)), - $foreignKey->getQuotedForeignColumns($this), - $foreignKey->getName(), - $foreignKey->getOptions() - )); - } - - /** - * {@inheritDoc} - */ - protected function _getCreateTableSQL($name, array $columns, array $options = []) - { - $name = str_replace('.', '__', $name); - $queryFields = $this->getColumnDeclarationListSQL($columns); - - if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) { - foreach ($options['uniqueConstraints'] as $name => $definition) { - $queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition); - } - } - - $queryFields .= $this->getNonAutoincrementPrimaryKeyDefinition($columns, $options); - - if (isset($options['foreignKeys'])) { - foreach ($options['foreignKeys'] as $foreignKey) { - $queryFields .= ', ' . $this->getForeignKeyDeclarationSQL($foreignKey); - } - } - - $tableComment = ''; - if (isset($options['comment'])) { - $comment = trim($options['comment'], " '"); - - $tableComment = $this->getInlineTableCommentSQL($comment); - } - - $query = ['CREATE TABLE ' . $name . ' ' . $tableComment . '(' . $queryFields . ')']; - - if (isset($options['alter']) && $options['alter'] === true) { - return $query; - } - - if (isset($options['indexes']) && ! empty($options['indexes'])) { - foreach ($options['indexes'] as $indexDef) { - $query[] = $this->getCreateIndexSQL($indexDef, $name); - } - } - - if (isset($options['unique']) && ! empty($options['unique'])) { - foreach ($options['unique'] as $indexDef) { - $query[] = $this->getCreateIndexSQL($indexDef, $name); - } - } - - return $query; - } - - /** - * Generate a PRIMARY KEY definition if no autoincrement value is used - * - * @param mixed[][] $columns - * @param mixed[] $options - */ - private function getNonAutoincrementPrimaryKeyDefinition(array $columns, array $options) : string - { - if (empty($options['primary'])) { - return ''; - } - - $keyColumns = array_unique(array_values($options['primary'])); - - foreach ($keyColumns as $keyColumn) { - if (! empty($columns[$keyColumn]['autoincrement'])) { - return ''; - } - } - - return ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; - } - - /** - * {@inheritDoc} - */ - protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) - { - return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') - : ($length ? 'VARCHAR(' . $length . ')' : 'TEXT'); - } - - /** - * {@inheritdoc} - */ - protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) - { - return 'BLOB'; - } - - /** - * {@inheritdoc} - */ - public function getBinaryMaxLength() - { - return 0; - } - - /** - * {@inheritdoc} - */ - public function getBinaryDefaultLength() - { - return 0; - } - - /** - * {@inheritDoc} - */ - public function getClobTypeDeclarationSQL(array $field) - { - return 'CLOB'; - } - - /** - * {@inheritDoc} - */ - public function getListTableConstraintsSQL($table) - { - $table = str_replace('.', '__', $table); - - return sprintf( - "SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name = %s AND sql NOT NULL ORDER BY name", - $this->quoteStringLiteral($table) - ); - } - - /** - * {@inheritDoc} - */ - public function getListTableColumnsSQL($table, $currentDatabase = null) - { - $table = str_replace('.', '__', $table); - - return sprintf('PRAGMA table_info(%s)', $this->quoteStringLiteral($table)); - } - - /** - * {@inheritDoc} - */ - public function getListTableIndexesSQL($table, $currentDatabase = null) - { - $table = str_replace('.', '__', $table); - - return sprintf('PRAGMA index_list(%s)', $this->quoteStringLiteral($table)); - } - - /** - * {@inheritDoc} - */ - public function getListTablesSQL() - { - return "SELECT name FROM sqlite_master WHERE type = 'table' AND name != 'sqlite_sequence' AND name != 'geometry_columns' AND name != 'spatial_ref_sys' " - . 'UNION ALL SELECT name FROM sqlite_temp_master ' - . "WHERE type = 'table' ORDER BY name"; - } - - /** - * {@inheritDoc} - */ - public function getListViewsSQL($database) - { - return "SELECT name, sql FROM sqlite_master WHERE type='view' AND sql NOT NULL"; - } - - /** - * {@inheritDoc} - */ - public function getCreateViewSQL($name, $sql) - { - return 'CREATE VIEW ' . $name . ' AS ' . $sql; - } - - /** - * {@inheritDoc} - */ - public function getDropViewSQL($name) - { - return 'DROP VIEW ' . $name; - } - - /** - * {@inheritDoc} - */ - public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) - { - $query = parent::getAdvancedForeignKeyOptionsSQL($foreignKey); - - $query .= ($foreignKey->hasOption('deferrable') && $foreignKey->getOption('deferrable') !== false ? ' ' : ' NOT ') . 'DEFERRABLE'; - $query .= ' INITIALLY ' . ($foreignKey->hasOption('deferred') && $foreignKey->getOption('deferred') !== false ? 'DEFERRED' : 'IMMEDIATE'); - - return $query; - } - - /** - * {@inheritDoc} - */ - public function supportsIdentityColumns() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function supportsColumnCollation() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function supportsInlineColumnComments() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return 'sqlite'; - } - - /** - * {@inheritDoc} - */ - public function getTruncateTableSQL($tableName, $cascade = false) - { - $tableIdentifier = new Identifier($tableName); - $tableName = str_replace('.', '__', $tableIdentifier->getQuotedName($this)); - - return 'DELETE FROM ' . $tableName; - } - - /** - * User-defined function for Sqlite that is used with PDO::sqliteCreateFunction(). - * - * @param int|float $value - * - * @return float - */ - public static function udfSqrt($value) - { - return sqrt($value); - } - - /** - * User-defined function for Sqlite that implements MOD(a, b). - * - * @param int $a - * @param int $b - * - * @return int - */ - public static function udfMod($a, $b) - { - return $a % $b; - } - - /** - * @param string $str - * @param string $substr - * @param int $offset - * - * @return int - */ - public static function udfLocate($str, $substr, $offset = 0) - { - // SQL's LOCATE function works on 1-based positions, while PHP's strpos works on 0-based positions. - // So we have to make them compatible if an offset is given. - if ($offset > 0) { - $offset -= 1; - } - - $pos = strpos($str, $substr, $offset); - - if ($pos !== false) { - return $pos + 1; - } - - return 0; - } - - /** - * {@inheritDoc} - */ - public function getForUpdateSql() - { - return ''; - } - - /** - * {@inheritDoc} - */ - public function getInlineColumnCommentSQL($comment) - { - return '--' . str_replace("\n", "\n--", $comment) . "\n"; - } - - private function getInlineTableCommentSQL(string $comment) : string - { - return $this->getInlineColumnCommentSQL($comment); - } - - /** - * {@inheritDoc} - */ - protected function initializeDoctrineTypeMappings() - { - $this->doctrineTypeMapping = [ - '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', - 'longvarchar' => 'string', - 'varchar2' => 'string', - 'nvarchar' => 'string', - 'image' => 'string', - 'ntext' => 'string', - 'char' => 'string', - 'date' => 'date', - 'datetime' => 'datetime', - 'timestamp' => 'datetime', - 'time' => 'time', - 'float' => 'float', - 'double' => 'float', - 'double precision' => 'float', - 'real' => 'float', - 'decimal' => 'decimal', - 'numeric' => 'decimal', - 'blob' => 'blob', - ]; - } - - /** - * {@inheritDoc} - */ - protected function getReservedKeywordsClass() - { - return Keywords\SQLiteKeywords::class; - } - - /** - * {@inheritDoc} - */ - protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) - { - if (! $diff->fromTable instanceof Table) { - throw new DBALException('Sqlite platform requires for alter table the table diff with reference to original table schema'); - } - - $sql = []; - foreach ($diff->fromTable->getIndexes() as $index) { - if ($index->isPrimary()) { - continue; - } - - $sql[] = $this->getDropIndexSQL($index, $diff->name); - } - - return $sql; - } - - /** - * {@inheritDoc} - */ - protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) - { - if (! $diff->fromTable instanceof Table) { - throw new DBALException('Sqlite platform requires for alter table the table diff with reference to original table schema'); - } - - $sql = []; - $tableName = $diff->getNewName(); - - if ($tableName === false) { - $tableName = $diff->getName($this); - } - - foreach ($this->getIndexesInAlteredTable($diff) as $index) { - if ($index->isPrimary()) { - continue; - } - - $sql[] = $this->getCreateIndexSQL($index, $tableName->getQuotedName($this)); - } - - return $sql; - } - - /** - * {@inheritDoc} - */ - protected function doModifyLimitQuery($query, $limit, $offset) - { - if ($limit === null && $offset > 0) { - return $query . ' LIMIT -1 OFFSET ' . $offset; - } - - return parent::doModifyLimitQuery($query, $limit, $offset); - } - - /** - * {@inheritDoc} - */ - public function getBlobTypeDeclarationSQL(array $field) - { - return 'BLOB'; - } - - /** - * {@inheritDoc} - */ - public function getTemporaryTableName($tableName) - { - $tableName = str_replace('.', '__', $tableName); - - return $tableName; - } - - /** - * {@inheritDoc} - * - * Sqlite Platform emulates schema by underscoring each dot and generating tables - * into the default database. - * - * This hack is implemented to be able to use SQLite as testdriver when - * using schema supporting databases. - */ - public function canEmulateSchemas() - { - return true; - } - - /** - * {@inheritDoc} - */ - public function supportsForeignKeyConstraints() - { - return false; - } - - /** - * {@inheritDoc} - */ - public function getCreatePrimaryKeySQL(Index $index, $table) - { - throw new DBALException('Sqlite platform does not support alter primary key.'); - } - - /** - * {@inheritdoc} - */ - public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table) - { - throw new DBALException('Sqlite platform does not support alter foreign key.'); - } - - /** - * {@inheritdoc} - */ - public function getDropForeignKeySQL($foreignKey, $table) - { - throw new DBALException('Sqlite platform does not support alter foreign key.'); - } - - /** - * {@inheritDoc} - */ - public function getCreateConstraintSQL(Constraint $constraint, $table) - { - throw new DBALException('Sqlite platform does not support alter constraint.'); - } - - /** - * {@inheritDoc} - */ - public function getCreateTableSQL(Table $table, $createFlags = null) - { - $createFlags = $createFlags ?? self::CREATE_INDEXES | self::CREATE_FOREIGNKEYS; - - return parent::getCreateTableSQL($table, $createFlags); - } - - /** - * {@inheritDoc} - */ - public function getListTableForeignKeysSQL($table, $database = null) - { - $table = str_replace('.', '__', $table); - - return sprintf('PRAGMA foreign_key_list(%s)', $this->quoteStringLiteral($table)); - } - - /** - * {@inheritDoc} - */ - public function getAlterTableSQL(TableDiff $diff) - { - $sql = $this->getSimpleAlterTableSQL($diff); - if ($sql !== false) { - return $sql; - } - - $fromTable = $diff->fromTable; - if (! $fromTable instanceof Table) { - throw new DBALException('Sqlite platform requires for alter table the table diff with reference to original table schema'); - } - - $table = clone $fromTable; - - $columns = []; - $oldColumnNames = []; - $newColumnNames = []; - $columnSql = []; - - foreach ($table->getColumns() as $columnName => $column) { - $columnName = strtolower($columnName); - $columns[$columnName] = $column; - $oldColumnNames[$columnName] = $newColumnNames[$columnName] = $column->getQuotedName($this); - } - - foreach ($diff->removedColumns as $columnName => $column) { - if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { - continue; - } - - $columnName = strtolower($columnName); - if (! isset($columns[$columnName])) { - continue; - } - - unset( - $columns[$columnName], - $oldColumnNames[$columnName], - $newColumnNames[$columnName] - ); - } - - foreach ($diff->renamedColumns as $oldColumnName => $column) { - if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { - continue; - } - - $oldColumnName = strtolower($oldColumnName); - if (isset($columns[$oldColumnName])) { - unset($columns[$oldColumnName]); - } - - $columns[strtolower($column->getName())] = $column; - - if (! isset($newColumnNames[$oldColumnName])) { - continue; - } - - $newColumnNames[$oldColumnName] = $column->getQuotedName($this); - } - - foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { - if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { - continue; - } - - if (isset($columns[$oldColumnName])) { - unset($columns[$oldColumnName]); - } - - $columns[strtolower($columnDiff->column->getName())] = $columnDiff->column; - - if (! isset($newColumnNames[$oldColumnName])) { - continue; - } - - $newColumnNames[$oldColumnName] = $columnDiff->column->getQuotedName($this); - } - - foreach ($diff->addedColumns as $columnName => $column) { - if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { - continue; - } - - $columns[strtolower($columnName)] = $column; - } - - $sql = []; - $tableSql = []; - if (! $this->onSchemaAlterTable($diff, $tableSql)) { - $dataTable = new Table('__temp__' . $table->getName()); - - $newTable = new Table($table->getQuotedName($this), $columns, $this->getPrimaryIndexInAlteredTable($diff), $this->getForeignKeysInAlteredTable($diff), 0, $table->getOptions()); - $newTable->addOption('alter', true); - - $sql = $this->getPreAlterTableIndexForeignKeySQL($diff); - //$sql = array_merge($sql, $this->getCreateTableSQL($dataTable, 0)); - $sql[] = sprintf('CREATE TEMPORARY TABLE %s AS SELECT %s FROM %s', $dataTable->getQuotedName($this), implode(', ', $oldColumnNames), $table->getQuotedName($this)); - $sql[] = $this->getDropTableSQL($fromTable); - - $sql = array_merge($sql, $this->getCreateTableSQL($newTable)); - $sql[] = sprintf('INSERT INTO %s (%s) SELECT %s FROM %s', $newTable->getQuotedName($this), implode(', ', $newColumnNames), implode(', ', $oldColumnNames), $dataTable->getQuotedName($this)); - $sql[] = $this->getDropTableSQL($dataTable); - - $newName = $diff->getNewName(); - - if ($newName !== false) { - $sql[] = sprintf( - 'ALTER TABLE %s RENAME TO %s', - $newTable->getQuotedName($this), - $newName->getQuotedName($this) - ); - } - - $sql = array_merge($sql, $this->getPostAlterTableIndexForeignKeySQL($diff)); - } - - return array_merge($sql, $tableSql, $columnSql); - } - - /** - * @return string[]|false - */ - private function getSimpleAlterTableSQL(TableDiff $diff) - { - // Suppress changes on integer type autoincrement columns. - foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { - if (! $columnDiff->fromColumn instanceof Column || - ! $columnDiff->column instanceof Column || - ! $columnDiff->column->getAutoincrement() || - ! $columnDiff->column->getType() instanceof Types\IntegerType - ) { - continue; - } - - if (! $columnDiff->hasChanged('type') && $columnDiff->hasChanged('unsigned')) { - unset($diff->changedColumns[$oldColumnName]); - - continue; - } - - $fromColumnType = $columnDiff->fromColumn->getType(); - - if (! ($fromColumnType instanceof Types\SmallIntType) && ! ($fromColumnType instanceof Types\BigIntType)) { - continue; - } - - unset($diff->changedColumns[$oldColumnName]); - } - - if (! empty($diff->renamedColumns) || ! empty($diff->addedForeignKeys) || ! empty($diff->addedIndexes) - || ! empty($diff->changedColumns) || ! empty($diff->changedForeignKeys) || ! empty($diff->changedIndexes) - || ! empty($diff->removedColumns) || ! empty($diff->removedForeignKeys) || ! empty($diff->removedIndexes) - || ! empty($diff->renamedIndexes) - ) { - return false; - } - - $table = new Table($diff->name); - - $sql = []; - $tableSql = []; - $columnSql = []; - - foreach ($diff->addedColumns as $column) { - if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { - continue; - } - - $field = array_merge(['unique' => null, 'autoincrement' => null, 'default' => null], $column->toArray()); - $type = $field['type']; - switch (true) { - case isset($field['columnDefinition']) || $field['autoincrement'] || $field['unique']: - case $type instanceof Types\DateTimeType && $field['default'] === $this->getCurrentTimestampSQL(): - case $type instanceof Types\DateType && $field['default'] === $this->getCurrentDateSQL(): - case $type instanceof Types\TimeType && $field['default'] === $this->getCurrentTimeSQL(): - return false; - } - - $field['name'] = $column->getQuotedName($this); - if ($type instanceof Types\StringType && $field['length'] === null) { - $field['length'] = 255; - } - - $sql[] = 'ALTER TABLE ' . $table->getQuotedName($this) . ' ADD COLUMN ' . $this->getColumnDeclarationSQL($field['name'], $field); - } - - if (! $this->onSchemaAlterTable($diff, $tableSql)) { - if ($diff->newName !== false) { - $newTable = new Identifier($diff->newName); - $sql[] = 'ALTER TABLE ' . $table->getQuotedName($this) . ' RENAME TO ' . $newTable->getQuotedName($this); - } - } - - return array_merge($sql, $tableSql, $columnSql); - } - - /** - * @return string[] - */ - private function getColumnNamesInAlteredTable(TableDiff $diff) - { - $columns = []; - - foreach ($diff->fromTable->getColumns() as $columnName => $column) { - $columns[strtolower($columnName)] = $column->getName(); - } - - foreach ($diff->removedColumns as $columnName => $column) { - $columnName = strtolower($columnName); - if (! isset($columns[$columnName])) { - continue; - } - - unset($columns[$columnName]); - } - - foreach ($diff->renamedColumns as $oldColumnName => $column) { - $columnName = $column->getName(); - $columns[strtolower($oldColumnName)] = $columnName; - $columns[strtolower($columnName)] = $columnName; - } - - foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { - $columnName = $columnDiff->column->getName(); - $columns[strtolower($oldColumnName)] = $columnName; - $columns[strtolower($columnName)] = $columnName; - } - - foreach ($diff->addedColumns as $column) { - $columnName = $column->getName(); - $columns[strtolower($columnName)] = $columnName; - } - - return $columns; - } - - /** - * @return Index[] - */ - private function getIndexesInAlteredTable(TableDiff $diff) - { - $indexes = $diff->fromTable->getIndexes(); - $columnNames = $this->getColumnNamesInAlteredTable($diff); - - foreach ($indexes as $key => $index) { - foreach ($diff->renamedIndexes as $oldIndexName => $renamedIndex) { - if (strtolower($key) !== strtolower($oldIndexName)) { - continue; - } - - unset($indexes[$key]); - } - - $changed = false; - $indexColumns = []; - foreach ($index->getColumns() as $columnName) { - $normalizedColumnName = strtolower($columnName); - if (! isset($columnNames[$normalizedColumnName])) { - unset($indexes[$key]); - continue 2; - } - - $indexColumns[] = $columnNames[$normalizedColumnName]; - if ($columnName === $columnNames[$normalizedColumnName]) { - continue; - } - - $changed = true; - } - - if (! $changed) { - continue; - } - - $indexes[$key] = new Index($index->getName(), $indexColumns, $index->isUnique(), $index->isPrimary(), $index->getFlags()); - } - - foreach ($diff->removedIndexes as $index) { - $indexName = strtolower($index->getName()); - if (! strlen($indexName) || ! isset($indexes[$indexName])) { - continue; - } - - unset($indexes[$indexName]); - } - - foreach (array_merge($diff->changedIndexes, $diff->addedIndexes, $diff->renamedIndexes) as $index) { - $indexName = strtolower($index->getName()); - if (strlen($indexName)) { - $indexes[$indexName] = $index; - } else { - $indexes[] = $index; - } - } - - return $indexes; - } - - /** - * @return ForeignKeyConstraint[] - */ - private function getForeignKeysInAlteredTable(TableDiff $diff) - { - $foreignKeys = $diff->fromTable->getForeignKeys(); - $columnNames = $this->getColumnNamesInAlteredTable($diff); - - foreach ($foreignKeys as $key => $constraint) { - $changed = false; - $localColumns = []; - foreach ($constraint->getLocalColumns() as $columnName) { - $normalizedColumnName = strtolower($columnName); - if (! isset($columnNames[$normalizedColumnName])) { - unset($foreignKeys[$key]); - continue 2; - } - - $localColumns[] = $columnNames[$normalizedColumnName]; - if ($columnName === $columnNames[$normalizedColumnName]) { - continue; - } - - $changed = true; - } - - if (! $changed) { - continue; - } - - $foreignKeys[$key] = new ForeignKeyConstraint($localColumns, $constraint->getForeignTableName(), $constraint->getForeignColumns(), $constraint->getName(), $constraint->getOptions()); - } - - foreach ($diff->removedForeignKeys as $constraint) { - if (! $constraint instanceof ForeignKeyConstraint) { - $constraint = new Identifier($constraint); - } - - $constraintName = strtolower($constraint->getName()); - if (! strlen($constraintName) || ! isset($foreignKeys[$constraintName])) { - continue; - } - - unset($foreignKeys[$constraintName]); - } - - foreach (array_merge($diff->changedForeignKeys, $diff->addedForeignKeys) as $constraint) { - $constraintName = strtolower($constraint->getName()); - if (strlen($constraintName)) { - $foreignKeys[$constraintName] = $constraint; - } else { - $foreignKeys[] = $constraint; - } - } - - return $foreignKeys; - } - - /** - * @return Index[] - */ - private function getPrimaryIndexInAlteredTable(TableDiff $diff) - { - $primaryIndex = []; - - foreach ($this->getIndexesInAlteredTable($diff) as $index) { - if (! $index->isPrimary()) { - continue; - } - - $primaryIndex = [$index->getName() => $index]; - } - - return $primaryIndex; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/TrimMode.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/TrimMode.php deleted file mode 100644 index 0a4b6ea..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/TrimMode.php +++ /dev/null @@ -1,20 +0,0 @@ -getParams(); - if (isset($params['portability'])) { - if ($this->getDatabasePlatform()->getName() === 'oracle') { - $params['portability'] &= self::PORTABILITY_ORACLE; - } elseif ($this->getDatabasePlatform()->getName() === 'postgresql') { - $params['portability'] &= self::PORTABILITY_POSTGRESQL; - } elseif ($this->getDatabasePlatform()->getName() === 'sqlite') { - $params['portability'] &= self::PORTABILITY_SQLITE; - } elseif ($this->getDatabasePlatform()->getName() === 'drizzle') { - $params['portability'] &= self::PORTABILITY_DRIZZLE; - } elseif ($this->getDatabasePlatform()->getName() === 'sqlanywhere') { - $params['portability'] &= self::PORTABILITY_SQLANYWHERE; - } elseif ($this->getDatabasePlatform()->getName() === 'db2') { - $params['portability'] &= self::PORTABILITY_DB2; - } elseif ($this->getDatabasePlatform()->getName() === 'mssql') { - $params['portability'] &= self::PORTABILITY_SQLSRV; - } else { - $params['portability'] &= self::PORTABILITY_OTHERVENDORS; - } - $this->portability = $params['portability']; - } - - if (isset($params['fetch_case']) && $this->portability & self::PORTABILITY_FIX_CASE) { - if ($this->_conn instanceof PDOConnection) { - // make use of c-level support for case handling - $this->_conn->setAttribute(PDO::ATTR_CASE, $params['fetch_case']); - } else { - $this->case = $params['fetch_case'] === ColumnCase::LOWER ? CASE_LOWER : CASE_UPPER; - } - } - } - - return $ret; - } - - /** - * @return int - */ - public function getPortability() - { - return $this->portability; - } - - /** - * @return int - */ - public function getFetchCase() - { - return $this->case; - } - - /** - * {@inheritdoc} - */ - public function executeQuery($query, array $params = [], $types = [], ?QueryCacheProfile $qcp = null) - { - $stmt = new Statement(parent::executeQuery($query, $params, $types, $qcp), $this); - $stmt->setFetchMode($this->defaultFetchMode); - - return $stmt; - } - - /** - * {@inheritdoc} - */ - public function prepare($statement) - { - $stmt = new Statement(parent::prepare($statement), $this); - $stmt->setFetchMode($this->defaultFetchMode); - - return $stmt; - } - - /** - * {@inheritdoc} - */ - public function query() - { - $connection = $this->getWrappedConnection(); - - $stmt = $connection->query(...func_get_args()); - $stmt = new Statement($stmt, $this); - $stmt->setFetchMode($this->defaultFetchMode); - - return $stmt; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Statement.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Statement.php deleted file mode 100644 index 514b3be..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Portability/Statement.php +++ /dev/null @@ -1,247 +0,0 @@ -Statement and applies portability measures. - * - * @param DriverStatement|ResultStatement $stmt - */ - public function __construct($stmt, Connection $conn) - { - $this->stmt = $stmt; - $this->portability = $conn->getPortability(); - $this->case = $conn->getFetchCase(); - } - - /** - * {@inheritdoc} - */ - public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null) - { - assert($this->stmt instanceof DriverStatement); - - return $this->stmt->bindParam($column, $variable, $type, $length); - } - - /** - * {@inheritdoc} - */ - public function bindValue($param, $value, $type = ParameterType::STRING) - { - assert($this->stmt instanceof DriverStatement); - - return $this->stmt->bindValue($param, $value, $type); - } - - /** - * {@inheritdoc} - */ - public function closeCursor() - { - return $this->stmt->closeCursor(); - } - - /** - * {@inheritdoc} - */ - public function columnCount() - { - return $this->stmt->columnCount(); - } - - /** - * {@inheritdoc} - */ - public function errorCode() - { - assert($this->stmt instanceof DriverStatement); - - return $this->stmt->errorCode(); - } - - /** - * {@inheritdoc} - */ - public function errorInfo() - { - assert($this->stmt instanceof DriverStatement); - - return $this->stmt->errorInfo(); - } - - /** - * {@inheritdoc} - */ - public function execute($params = null) - { - assert($this->stmt instanceof DriverStatement); - - return $this->stmt->execute($params); - } - - /** - * {@inheritdoc} - */ - public function setFetchMode($fetchMode, $arg1 = null, $arg2 = null) - { - $this->defaultFetchMode = $fetchMode; - - return $this->stmt->setFetchMode($fetchMode, $arg1, $arg2); - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - return new StatementIterator($this); - } - - /** - * {@inheritdoc} - */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) - { - $fetchMode = $fetchMode ?: $this->defaultFetchMode; - - $row = $this->stmt->fetch($fetchMode); - - $iterateRow = $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM); - $fixCase = $this->case !== null - && ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED) - && ($this->portability & Connection::PORTABILITY_FIX_CASE); - - $row = $this->fixRow($row, $iterateRow, $fixCase); - - return $row; - } - - /** - * {@inheritdoc} - */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) - { - $fetchMode = $fetchMode ?: $this->defaultFetchMode; - - if ($fetchArgument) { - $rows = $this->stmt->fetchAll($fetchMode, $fetchArgument); - } else { - $rows = $this->stmt->fetchAll($fetchMode); - } - - $iterateRow = $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM); - $fixCase = $this->case !== null - && ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED) - && ($this->portability & Connection::PORTABILITY_FIX_CASE); - - if (! $iterateRow && ! $fixCase) { - return $rows; - } - - if ($fetchMode === FetchMode::COLUMN) { - foreach ($rows as $num => $row) { - $rows[$num] = [$row]; - } - } - - foreach ($rows as $num => $row) { - $rows[$num] = $this->fixRow($row, $iterateRow, $fixCase); - } - - if ($fetchMode === FetchMode::COLUMN) { - foreach ($rows as $num => $row) { - $rows[$num] = $row[0]; - } - } - - return $rows; - } - - /** - * @param mixed $row - * @param int $iterateRow - * @param bool $fixCase - * - * @return mixed - */ - protected function fixRow($row, $iterateRow, $fixCase) - { - if (! $row) { - return $row; - } - - if ($fixCase) { - $row = array_change_key_case($row, $this->case); - } - - if ($iterateRow) { - foreach ($row as $k => $v) { - if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $v === '') { - $row[$k] = null; - } elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($v)) { - $row[$k] = rtrim($v); - } - } - } - - return $row; - } - - /** - * {@inheritdoc} - */ - public function fetchColumn($columnIndex = 0) - { - $value = $this->stmt->fetchColumn($columnIndex); - - if ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) { - if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $value === '') { - $value = null; - } elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($value)) { - $value = rtrim($value); - } - } - - return $value; - } - - /** - * {@inheritdoc} - */ - public function rowCount() - { - assert($this->stmt instanceof DriverStatement); - - return $this->stmt->rowCount(); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/CompositeExpression.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/CompositeExpression.php deleted file mode 100644 index 443d71b..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/CompositeExpression.php +++ /dev/null @@ -1,120 +0,0 @@ -type = $type; - - $this->addMultiple($parts); - } - - /** - * Adds multiple parts to composite expression. - * - * @param self[]|string[] $parts - * - * @return \Doctrine\DBAL\Query\Expression\CompositeExpression - */ - public function addMultiple(array $parts = []) - { - foreach ($parts as $part) { - $this->add($part); - } - - return $this; - } - - /** - * Adds an expression to composite expression. - * - * @param mixed $part - * - * @return \Doctrine\DBAL\Query\Expression\CompositeExpression - */ - public function add($part) - { - if (empty($part)) { - return $this; - } - - if ($part instanceof self && count($part) === 0) { - return $this; - } - - $this->parts[] = $part; - - return $this; - } - - /** - * Retrieves the amount of expressions on composite expression. - * - * @return int - */ - public function count() - { - return count($this->parts); - } - - /** - * Retrieves the string representation of this composite expression. - * - * @return string - */ - public function __toString() - { - if ($this->count() === 1) { - return (string) $this->parts[0]; - } - - return '(' . implode(') ' . $this->type . ' (', $this->parts) . ')'; - } - - /** - * Returns the type of this composite expression (AND/OR). - * - * @return string - */ - public function getType() - { - return $this->type; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php deleted file mode 100644 index dfcc31e..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php +++ /dev/null @@ -1,298 +0,0 @@ -'; - public const LT = '<'; - public const LTE = '<='; - public const GT = '>'; - public const GTE = '>='; - - /** - * The DBAL Connection. - * - * @var Connection - */ - private $connection; - - /** - * Initializes a new ExpressionBuilder. - * - * @param Connection $connection The DBAL Connection. - */ - public function __construct(Connection $connection) - { - $this->connection = $connection; - } - - /** - * Creates a conjunction of the given boolean expressions. - * - * Example: - * - * [php] - * // (u.type = ?) AND (u.role = ?) - * $expr->andX('u.type = ?', 'u.role = ?')); - * - * @param mixed $x Optional clause. Defaults = null, but requires - * at least one defined when converting to string. - * - * @return CompositeExpression - */ - public function andX($x = null) - { - return new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); - } - - /** - * Creates a disjunction of the given boolean expressions. - * - * Example: - * - * [php] - * // (u.type = ?) OR (u.role = ?) - * $qb->where($qb->expr()->orX('u.type = ?', 'u.role = ?')); - * - * @param mixed $x Optional clause. Defaults = null, but requires - * at least one defined when converting to string. - * - * @return CompositeExpression - */ - public function orX($x = null) - { - return new CompositeExpression(CompositeExpression::TYPE_OR, func_get_args()); - } - - /** - * Creates a comparison expression. - * - * @param mixed $x The left expression. - * @param string $operator One of the ExpressionBuilder::* constants. - * @param mixed $y The right expression. - * - * @return string - */ - public function comparison($x, $operator, $y) - { - return $x . ' ' . $operator . ' ' . $y; - } - - /** - * Creates an equality comparison expression with the given arguments. - * - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a = . Example: - * - * [php] - * // u.id = ? - * $expr->eq('u.id', '?'); - * - * @param mixed $x The left expression. - * @param mixed $y The right expression. - * - * @return string - */ - public function eq($x, $y) - { - return $this->comparison($x, self::EQ, $y); - } - - /** - * Creates a non equality comparison expression with the given arguments. - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a <> . Example: - * - * [php] - * // u.id <> 1 - * $q->where($q->expr()->neq('u.id', '1')); - * - * @param mixed $x The left expression. - * @param mixed $y The right expression. - * - * @return string - */ - public function neq($x, $y) - { - return $this->comparison($x, self::NEQ, $y); - } - - /** - * Creates a lower-than comparison expression with the given arguments. - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a < . Example: - * - * [php] - * // u.id < ? - * $q->where($q->expr()->lt('u.id', '?')); - * - * @param mixed $x The left expression. - * @param mixed $y The right expression. - * - * @return string - */ - public function lt($x, $y) - { - return $this->comparison($x, self::LT, $y); - } - - /** - * Creates a lower-than-equal comparison expression with the given arguments. - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a <= . Example: - * - * [php] - * // u.id <= ? - * $q->where($q->expr()->lte('u.id', '?')); - * - * @param mixed $x The left expression. - * @param mixed $y The right expression. - * - * @return string - */ - public function lte($x, $y) - { - return $this->comparison($x, self::LTE, $y); - } - - /** - * Creates a greater-than comparison expression with the given arguments. - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a > . Example: - * - * [php] - * // u.id > ? - * $q->where($q->expr()->gt('u.id', '?')); - * - * @param mixed $x The left expression. - * @param mixed $y The right expression. - * - * @return string - */ - public function gt($x, $y) - { - return $this->comparison($x, self::GT, $y); - } - - /** - * Creates a greater-than-equal comparison expression with the given arguments. - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a >= . Example: - * - * [php] - * // u.id >= ? - * $q->where($q->expr()->gte('u.id', '?')); - * - * @param mixed $x The left expression. - * @param mixed $y The right expression. - * - * @return string - */ - public function gte($x, $y) - { - return $this->comparison($x, self::GTE, $y); - } - - /** - * Creates an IS NULL expression with the given arguments. - * - * @param string $x The field in string format to be restricted by IS NULL. - * - * @return string - */ - public function isNull($x) - { - return $x . ' IS NULL'; - } - - /** - * Creates an IS NOT NULL expression with the given arguments. - * - * @param string $x The field in string format to be restricted by IS NOT NULL. - * - * @return string - */ - public function isNotNull($x) - { - return $x . ' IS NOT NULL'; - } - - /** - * Creates a LIKE() comparison expression with the given arguments. - * - * @param string $x Field in string format to be inspected by LIKE() comparison. - * @param mixed $y Argument to be used in LIKE() comparison. - * - * @return string - */ - public function like($x, $y/*, ?string $escapeChar = null */) - { - return $this->comparison($x, 'LIKE', $y) . - (func_num_args() >= 3 ? sprintf(' ESCAPE %s', func_get_arg(2)) : ''); - } - - /** - * Creates a NOT LIKE() comparison expression with the given arguments. - * - * @param string $x Field in string format to be inspected by NOT LIKE() comparison. - * @param mixed $y Argument to be used in NOT LIKE() comparison. - * - * @return string - */ - public function notLike($x, $y/*, ?string $escapeChar = null */) - { - return $this->comparison($x, 'NOT LIKE', $y) . - (func_num_args() >= 3 ? sprintf(' ESCAPE %s', func_get_arg(2)) : ''); - } - - /** - * Creates a IN () comparison expression with the given arguments. - * - * @param string $x The field in string format to be inspected by IN() comparison. - * @param string|string[] $y The placeholder or the array of values to be used by IN() comparison. - * - * @return string - */ - public function in($x, $y) - { - return $this->comparison($x, 'IN', '(' . implode(', ', (array) $y) . ')'); - } - - /** - * Creates a NOT IN () comparison expression with the given arguments. - * - * @param string $x The field in string format to be inspected by NOT IN() comparison. - * @param string|string[] $y The placeholder or the array of values to be used by NOT IN() comparison. - * - * @return string - */ - public function notIn($x, $y) - { - return $this->comparison($x, 'NOT IN', '(' . implode(', ', (array) $y) . ')'); - } - - /** - * Quotes a given input parameter. - * - * @param mixed $input The parameter to be quoted. - * @param int|null $type The type of the parameter. - * - * @return string - */ - public function literal($input, $type = null) - { - return $this->connection->quote($input, $type); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryBuilder.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryBuilder.php deleted file mode 100644 index 587e266..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryBuilder.php +++ /dev/null @@ -1,1373 +0,0 @@ - [], - 'distinct' => false, - 'from' => [], - 'join' => [], - 'set' => [], - 'where' => null, - 'groupBy' => [], - 'having' => null, - 'orderBy' => [], - 'values' => [], - ]; - - /** - * The array of SQL parts collected. - * - * @var mixed[] - */ - private $sqlParts = self::SQL_PARTS_DEFAULTS; - - /** - * The complete SQL string for this query. - * - * @var string - */ - private $sql; - - /** - * The query parameters. - * - * @var mixed[] - */ - private $params = []; - - /** - * The parameter type map of this query. - * - * @var int[]|string[] - */ - private $paramTypes = []; - - /** - * The type of query this is. Can be select, update or delete. - * - * @var int - */ - private $type = self::SELECT; - - /** - * The state of the query object. Can be dirty or clean. - * - * @var int - */ - private $state = self::STATE_CLEAN; - - /** - * The index of the first result to retrieve. - * - * @var int - */ - private $firstResult = null; - - /** - * The maximum number of results to retrieve. - * - * @var int - */ - private $maxResults = null; - - /** - * The counter of bound parameters used with {@see bindValue). - * - * @var int - */ - private $boundCounter = 0; - - /** - * Initializes a new QueryBuilder. - * - * @param Connection $connection The DBAL Connection. - */ - public function __construct(Connection $connection) - { - $this->connection = $connection; - } - - /** - * Gets an ExpressionBuilder used for object-oriented construction of query expressions. - * This producer method is intended for convenient inline usage. Example: - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u') - * ->from('users', 'u') - * ->where($qb->expr()->eq('u.id', 1)); - * - * - * For more complex expression construction, consider storing the expression - * builder object in a local variable. - * - * @return ExpressionBuilder - */ - public function expr() - { - return $this->connection->getExpressionBuilder(); - } - - /** - * Gets the type of the currently built query. - * - * @return int - */ - public function getType() - { - return $this->type; - } - - /** - * Gets the associated DBAL Connection for this query builder. - * - * @return Connection - */ - public function getConnection() - { - return $this->connection; - } - - /** - * Gets the state of this query builder instance. - * - * @return int Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN. - */ - public function getState() - { - return $this->state; - } - - /** - * Executes this query using the bound parameters and their types. - * - * Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate} - * for insert, update and delete statements. - * - * @return Statement|int - */ - public function execute() - { - if ($this->type === self::SELECT) { - return $this->connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes); - } - - return $this->connection->executeUpdate($this->getSQL(), $this->params, $this->paramTypes); - } - - /** - * Gets the complete SQL string formed by the current specifications of this QueryBuilder. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u') - * echo $qb->getSQL(); // SELECT u FROM User u - * - * - * @return string The SQL query string. - */ - public function getSQL() - { - if ($this->sql !== null && $this->state === self::STATE_CLEAN) { - return $this->sql; - } - - switch ($this->type) { - case self::INSERT: - $sql = $this->getSQLForInsert(); - break; - case self::DELETE: - $sql = $this->getSQLForDelete(); - break; - - case self::UPDATE: - $sql = $this->getSQLForUpdate(); - break; - - case self::SELECT: - default: - $sql = $this->getSQLForSelect(); - break; - } - - $this->state = self::STATE_CLEAN; - $this->sql = $sql; - - return $sql; - } - - /** - * Sets a query parameter for the query being constructed. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u') - * ->from('users', 'u') - * ->where('u.id = :user_id') - * ->setParameter(':user_id', 1); - * - * - * @param string|int $key The parameter position or name. - * @param mixed $value The parameter value. - * @param string|int|null $type One of the {@link \Doctrine\DBAL\ParameterType} constants. - * - * @return $this This QueryBuilder instance. - */ - public function setParameter($key, $value, $type = null) - { - if ($type !== null) { - $this->paramTypes[$key] = $type; - } - - $this->params[$key] = $value; - - return $this; - } - - /** - * Sets a collection of query parameters for the query being constructed. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u') - * ->from('users', 'u') - * ->where('u.id = :user_id1 OR u.id = :user_id2') - * ->setParameters(array( - * ':user_id1' => 1, - * ':user_id2' => 2 - * )); - * - * - * @param mixed[] $params The query parameters to set. - * @param int[]|string[] $types The query parameters types to set. - * - * @return $this This QueryBuilder instance. - */ - public function setParameters(array $params, array $types = []) - { - $this->paramTypes = $types; - $this->params = $params; - - return $this; - } - - /** - * Gets all defined query parameters for the query being constructed indexed by parameter index or name. - * - * @return mixed[] The currently defined query parameters indexed by parameter index or name. - */ - public function getParameters() - { - return $this->params; - } - - /** - * Gets a (previously set) query parameter of the query being constructed. - * - * @param mixed $key The key (index or name) of the bound parameter. - * - * @return mixed The value of the bound parameter. - */ - public function getParameter($key) - { - return $this->params[$key] ?? null; - } - - /** - * Gets all defined query parameter types for the query being constructed indexed by parameter index or name. - * - * @return int[]|string[] The currently defined query parameter types indexed by parameter index or name. - */ - public function getParameterTypes() - { - return $this->paramTypes; - } - - /** - * Gets a (previously set) query parameter type of the query being constructed. - * - * @param mixed $key The key (index or name) of the bound parameter type. - * - * @return mixed The value of the bound parameter type. - */ - public function getParameterType($key) - { - return $this->paramTypes[$key] ?? null; - } - - /** - * Sets the position of the first result to retrieve (the "offset"). - * - * @param int $firstResult The first result to return. - * - * @return $this This QueryBuilder instance. - */ - public function setFirstResult($firstResult) - { - $this->state = self::STATE_DIRTY; - $this->firstResult = $firstResult; - - return $this; - } - - /** - * Gets the position of the first result the query object was set to retrieve (the "offset"). - * Returns NULL if {@link setFirstResult} was not applied to this QueryBuilder. - * - * @return int The position of the first result. - */ - public function getFirstResult() - { - return $this->firstResult; - } - - /** - * Sets the maximum number of results to retrieve (the "limit"). - * - * @param int $maxResults The maximum number of results to retrieve. - * - * @return $this This QueryBuilder instance. - */ - public function setMaxResults($maxResults) - { - $this->state = self::STATE_DIRTY; - $this->maxResults = $maxResults; - - return $this; - } - - /** - * Gets the maximum number of results the query object was set to retrieve (the "limit"). - * Returns NULL if {@link setMaxResults} was not applied to this query builder. - * - * @return int The maximum number of results. - */ - public function getMaxResults() - { - return $this->maxResults; - } - - /** - * Either appends to or replaces a single, generic query part. - * - * The available parts are: 'select', 'from', 'set', 'where', - * 'groupBy', 'having' and 'orderBy'. - * - * @param string $sqlPartName - * @param mixed $sqlPart - * @param bool $append - * - * @return $this This QueryBuilder instance. - */ - public function add($sqlPartName, $sqlPart, $append = false) - { - $isArray = is_array($sqlPart); - $isMultiple = is_array($this->sqlParts[$sqlPartName]); - - if ($isMultiple && ! $isArray) { - $sqlPart = [$sqlPart]; - } - - $this->state = self::STATE_DIRTY; - - if ($append) { - if ($sqlPartName === 'orderBy' || $sqlPartName === 'groupBy' || $sqlPartName === 'select' || $sqlPartName === 'set') { - foreach ($sqlPart as $part) { - $this->sqlParts[$sqlPartName][] = $part; - } - } elseif ($isArray && is_array($sqlPart[key($sqlPart)])) { - $key = key($sqlPart); - $this->sqlParts[$sqlPartName][$key][] = $sqlPart[$key]; - } elseif ($isMultiple) { - $this->sqlParts[$sqlPartName][] = $sqlPart; - } else { - $this->sqlParts[$sqlPartName] = $sqlPart; - } - - return $this; - } - - $this->sqlParts[$sqlPartName] = $sqlPart; - - return $this; - } - - /** - * Specifies an item that is to be returned in the query result. - * Replaces any previously specified selections, if any. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u.id', 'p.id') - * ->from('users', 'u') - * ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id'); - * - * - * @param mixed $select The selection expressions. - * - * @return $this This QueryBuilder instance. - */ - public function select($select = null) - { - $this->type = self::SELECT; - - if (empty($select)) { - return $this; - } - - $selects = is_array($select) ? $select : func_get_args(); - - return $this->add('select', $selects); - } - - /** - * Adds DISTINCT to the query. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u.id') - * ->distinct() - * ->from('users', 'u') - * - * - * @return $this This QueryBuilder instance. - */ - public function distinct() : self - { - $this->sqlParts['distinct'] = true; - - return $this; - } - - /** - * Adds an item that is to be returned in the query result. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u.id') - * ->addSelect('p.id') - * ->from('users', 'u') - * ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id'); - * - * - * @param mixed $select The selection expression. - * - * @return $this This QueryBuilder instance. - */ - public function addSelect($select = null) - { - $this->type = self::SELECT; - - if (empty($select)) { - return $this; - } - - $selects = is_array($select) ? $select : func_get_args(); - - return $this->add('select', $selects, true); - } - - /** - * Turns the query being built into a bulk delete query that ranges over - * a certain table. - * - * - * $qb = $conn->createQueryBuilder() - * ->delete('users', 'u') - * ->where('u.id = :user_id') - * ->setParameter(':user_id', 1); - * - * - * @param string $delete The table whose rows are subject to the deletion. - * @param string $alias The table alias used in the constructed query. - * - * @return $this This QueryBuilder instance. - */ - public function delete($delete = null, $alias = null) - { - $this->type = self::DELETE; - - if (! $delete) { - return $this; - } - - return $this->add('from', [ - 'table' => $delete, - 'alias' => $alias, - ]); - } - - /** - * Turns the query being built into a bulk update query that ranges over - * a certain table - * - * - * $qb = $conn->createQueryBuilder() - * ->update('counters', 'c') - * ->set('c.value', 'c.value + 1') - * ->where('c.id = ?'); - * - * - * @param string $update The table whose rows are subject to the update. - * @param string $alias The table alias used in the constructed query. - * - * @return $this This QueryBuilder instance. - */ - public function update($update = null, $alias = null) - { - $this->type = self::UPDATE; - - if (! $update) { - return $this; - } - - return $this->add('from', [ - 'table' => $update, - 'alias' => $alias, - ]); - } - - /** - * Turns the query being built into an insert query that inserts into - * a certain table - * - * - * $qb = $conn->createQueryBuilder() - * ->insert('users') - * ->values( - * array( - * 'name' => '?', - * 'password' => '?' - * ) - * ); - * - * - * @param string $insert The table into which the rows should be inserted. - * - * @return $this This QueryBuilder instance. - */ - public function insert($insert = null) - { - $this->type = self::INSERT; - - if (! $insert) { - return $this; - } - - return $this->add('from', ['table' => $insert]); - } - - /** - * Creates and adds a query root corresponding to the table identified by the - * given alias, forming a cartesian product with any existing query roots. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u.id') - * ->from('users', 'u') - * - * - * @param string $from The table. - * @param string|null $alias The alias of the table. - * - * @return $this This QueryBuilder instance. - */ - public function from($from, $alias = null) - { - return $this->add('from', [ - 'table' => $from, - 'alias' => $alias, - ], true); - } - - /** - * Creates and adds a join to the query. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u.name') - * ->from('users', 'u') - * ->join('u', 'phonenumbers', 'p', 'p.is_primary = 1'); - * - * - * @param string $fromAlias The alias that points to a from clause. - * @param string $join The table name to join. - * @param string $alias The alias of the join table. - * @param string $condition The condition for the join. - * - * @return $this This QueryBuilder instance. - */ - public function join($fromAlias, $join, $alias, $condition = null) - { - return $this->innerJoin($fromAlias, $join, $alias, $condition); - } - - /** - * Creates and adds a join to the query. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u.name') - * ->from('users', 'u') - * ->innerJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1'); - * - * - * @param string $fromAlias The alias that points to a from clause. - * @param string $join The table name to join. - * @param string $alias The alias of the join table. - * @param string $condition The condition for the join. - * - * @return $this This QueryBuilder instance. - */ - public function innerJoin($fromAlias, $join, $alias, $condition = null) - { - return $this->add('join', [ - $fromAlias => [ - 'joinType' => 'inner', - 'joinTable' => $join, - 'joinAlias' => $alias, - 'joinCondition' => $condition, - ], - ], true); - } - - /** - * Creates and adds a left join to the query. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u.name') - * ->from('users', 'u') - * ->leftJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1'); - * - * - * @param string $fromAlias The alias that points to a from clause. - * @param string $join The table name to join. - * @param string $alias The alias of the join table. - * @param string $condition The condition for the join. - * - * @return $this This QueryBuilder instance. - */ - public function leftJoin($fromAlias, $join, $alias, $condition = null) - { - return $this->add('join', [ - $fromAlias => [ - 'joinType' => 'left', - 'joinTable' => $join, - 'joinAlias' => $alias, - 'joinCondition' => $condition, - ], - ], true); - } - - /** - * Creates and adds a right join to the query. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u.name') - * ->from('users', 'u') - * ->rightJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1'); - * - * - * @param string $fromAlias The alias that points to a from clause. - * @param string $join The table name to join. - * @param string $alias The alias of the join table. - * @param string $condition The condition for the join. - * - * @return $this This QueryBuilder instance. - */ - public function rightJoin($fromAlias, $join, $alias, $condition = null) - { - return $this->add('join', [ - $fromAlias => [ - 'joinType' => 'right', - 'joinTable' => $join, - 'joinAlias' => $alias, - 'joinCondition' => $condition, - ], - ], true); - } - - /** - * Sets a new value for a column in a bulk update query. - * - * - * $qb = $conn->createQueryBuilder() - * ->update('counters', 'c') - * ->set('c.value', 'c.value + 1') - * ->where('c.id = ?'); - * - * - * @param string $key The column to set. - * @param string $value The value, expression, placeholder, etc. - * - * @return $this This QueryBuilder instance. - */ - public function set($key, $value) - { - return $this->add('set', $key . ' = ' . $value, true); - } - - /** - * Specifies one or more restrictions to the query result. - * Replaces any previously specified restrictions, if any. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('c.value') - * ->from('counters', 'c') - * ->where('c.id = ?'); - * - * // You can optionally programatically build and/or expressions - * $qb = $conn->createQueryBuilder(); - * - * $or = $qb->expr()->orx(); - * $or->add($qb->expr()->eq('c.id', 1)); - * $or->add($qb->expr()->eq('c.id', 2)); - * - * $qb->update('counters', 'c') - * ->set('c.value', 'c.value + 1') - * ->where($or); - * - * - * @param mixed $predicates The restriction predicates. - * - * @return $this This QueryBuilder instance. - */ - public function where($predicates) - { - if (! (func_num_args() === 1 && $predicates instanceof CompositeExpression)) { - $predicates = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); - } - - return $this->add('where', $predicates); - } - - /** - * Adds one or more restrictions to the query results, forming a logical - * conjunction with any previously specified restrictions. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u') - * ->from('users', 'u') - * ->where('u.username LIKE ?') - * ->andWhere('u.is_active = 1'); - * - * - * @see where() - * - * @param mixed $where The query restrictions. - * - * @return $this This QueryBuilder instance. - */ - public function andWhere($where) - { - $args = func_get_args(); - $where = $this->getQueryPart('where'); - - if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_AND) { - $where->addMultiple($args); - } else { - array_unshift($args, $where); - $where = new CompositeExpression(CompositeExpression::TYPE_AND, $args); - } - - return $this->add('where', $where, true); - } - - /** - * Adds one or more restrictions to the query results, forming a logical - * disjunction with any previously specified restrictions. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u.name') - * ->from('users', 'u') - * ->where('u.id = 1') - * ->orWhere('u.id = 2'); - * - * - * @see where() - * - * @param mixed $where The WHERE statement. - * - * @return $this This QueryBuilder instance. - */ - public function orWhere($where) - { - $args = func_get_args(); - $where = $this->getQueryPart('where'); - - if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_OR) { - $where->addMultiple($args); - } else { - array_unshift($args, $where); - $where = new CompositeExpression(CompositeExpression::TYPE_OR, $args); - } - - return $this->add('where', $where, true); - } - - /** - * Specifies a grouping over the results of the query. - * Replaces any previously specified groupings, if any. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u.name') - * ->from('users', 'u') - * ->groupBy('u.id'); - * - * - * @param mixed $groupBy The grouping expression. - * - * @return $this This QueryBuilder instance. - */ - public function groupBy($groupBy) - { - if (empty($groupBy)) { - return $this; - } - - $groupBy = is_array($groupBy) ? $groupBy : func_get_args(); - - return $this->add('groupBy', $groupBy, false); - } - - /** - * Adds a grouping expression to the query. - * - * - * $qb = $conn->createQueryBuilder() - * ->select('u.name') - * ->from('users', 'u') - * ->groupBy('u.lastLogin') - * ->addGroupBy('u.createdAt'); - * - * - * @param mixed $groupBy The grouping expression. - * - * @return $this This QueryBuilder instance. - */ - public function addGroupBy($groupBy) - { - if (empty($groupBy)) { - return $this; - } - - $groupBy = is_array($groupBy) ? $groupBy : func_get_args(); - - return $this->add('groupBy', $groupBy, true); - } - - /** - * Sets a value for a column in an insert query. - * - * - * $qb = $conn->createQueryBuilder() - * ->insert('users') - * ->values( - * array( - * 'name' => '?' - * ) - * ) - * ->setValue('password', '?'); - * - * - * @param string $column The column into which the value should be inserted. - * @param string $value The value that should be inserted into the column. - * - * @return $this This QueryBuilder instance. - */ - public function setValue($column, $value) - { - $this->sqlParts['values'][$column] = $value; - - return $this; - } - - /** - * Specifies values for an insert query indexed by column names. - * Replaces any previous values, if any. - * - * - * $qb = $conn->createQueryBuilder() - * ->insert('users') - * ->values( - * array( - * 'name' => '?', - * 'password' => '?' - * ) - * ); - * - * - * @param mixed[] $values The values to specify for the insert query indexed by column names. - * - * @return $this This QueryBuilder instance. - */ - public function values(array $values) - { - return $this->add('values', $values); - } - - /** - * Specifies a restriction over the groups of the query. - * Replaces any previous having restrictions, if any. - * - * @param mixed $having The restriction over the groups. - * - * @return $this This QueryBuilder instance. - */ - public function having($having) - { - if (! (func_num_args() === 1 && $having instanceof CompositeExpression)) { - $having = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); - } - - return $this->add('having', $having); - } - - /** - * Adds a restriction over the groups of the query, forming a logical - * conjunction with any existing having restrictions. - * - * @param mixed $having The restriction to append. - * - * @return $this This QueryBuilder instance. - */ - public function andHaving($having) - { - $args = func_get_args(); - $having = $this->getQueryPart('having'); - - if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_AND) { - $having->addMultiple($args); - } else { - array_unshift($args, $having); - $having = new CompositeExpression(CompositeExpression::TYPE_AND, $args); - } - - return $this->add('having', $having); - } - - /** - * Adds a restriction over the groups of the query, forming a logical - * disjunction with any existing having restrictions. - * - * @param mixed $having The restriction to add. - * - * @return $this This QueryBuilder instance. - */ - public function orHaving($having) - { - $args = func_get_args(); - $having = $this->getQueryPart('having'); - - if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_OR) { - $having->addMultiple($args); - } else { - array_unshift($args, $having); - $having = new CompositeExpression(CompositeExpression::TYPE_OR, $args); - } - - return $this->add('having', $having); - } - - /** - * Specifies an ordering for the query results. - * Replaces any previously specified orderings, if any. - * - * @param string $sort The ordering expression. - * @param string $order The ordering direction. - * - * @return $this This QueryBuilder instance. - */ - public function orderBy($sort, $order = null) - { - return $this->add('orderBy', $sort . ' ' . (! $order ? 'ASC' : $order), false); - } - - /** - * Adds an ordering to the query results. - * - * @param string $sort The ordering expression. - * @param string $order The ordering direction. - * - * @return $this This QueryBuilder instance. - */ - public function addOrderBy($sort, $order = null) - { - return $this->add('orderBy', $sort . ' ' . (! $order ? 'ASC' : $order), true); - } - - /** - * Gets a query part by its name. - * - * @param string $queryPartName - * - * @return mixed - */ - public function getQueryPart($queryPartName) - { - return $this->sqlParts[$queryPartName]; - } - - /** - * Gets all query parts. - * - * @return mixed[] - */ - public function getQueryParts() - { - return $this->sqlParts; - } - - /** - * Resets SQL parts. - * - * @param string[]|null $queryPartNames - * - * @return $this This QueryBuilder instance. - */ - public function resetQueryParts($queryPartNames = null) - { - if ($queryPartNames === null) { - $queryPartNames = array_keys($this->sqlParts); - } - - foreach ($queryPartNames as $queryPartName) { - $this->resetQueryPart($queryPartName); - } - - return $this; - } - - /** - * Resets a single SQL part. - * - * @param string $queryPartName - * - * @return $this This QueryBuilder instance. - */ - public function resetQueryPart($queryPartName) - { - $this->sqlParts[$queryPartName] = self::SQL_PARTS_DEFAULTS[$queryPartName]; - - $this->state = self::STATE_DIRTY; - - return $this; - } - - /** - * @return string - * - * @throws QueryException - */ - private function getSQLForSelect() - { - $query = 'SELECT ' . ($this->sqlParts['distinct'] ? 'DISTINCT ' : '') . - implode(', ', $this->sqlParts['select']); - - $query .= ($this->sqlParts['from'] ? ' FROM ' . implode(', ', $this->getFromClauses()) : '') - . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '') - . ($this->sqlParts['groupBy'] ? ' GROUP BY ' . implode(', ', $this->sqlParts['groupBy']) : '') - . ($this->sqlParts['having'] !== null ? ' HAVING ' . ((string) $this->sqlParts['having']) : '') - . ($this->sqlParts['orderBy'] ? ' ORDER BY ' . implode(', ', $this->sqlParts['orderBy']) : ''); - - if ($this->isLimitQuery()) { - return $this->connection->getDatabasePlatform()->modifyLimitQuery( - $query, - $this->maxResults, - $this->firstResult - ); - } - - return $query; - } - - /** - * @return string[] - */ - private function getFromClauses() - { - $fromClauses = []; - $knownAliases = []; - - // Loop through all FROM clauses - foreach ($this->sqlParts['from'] as $from) { - if ($from['alias'] === null) { - $tableSql = $from['table']; - $tableReference = $from['table']; - } else { - $tableSql = $from['table'] . ' ' . $from['alias']; - $tableReference = $from['alias']; - } - - $knownAliases[$tableReference] = true; - - $fromClauses[$tableReference] = $tableSql . $this->getSQLForJoins($tableReference, $knownAliases); - } - - $this->verifyAllAliasesAreKnown($knownAliases); - - return $fromClauses; - } - - /** - * @param string[] $knownAliases - * - * @throws QueryException - */ - private function verifyAllAliasesAreKnown(array $knownAliases) - { - foreach ($this->sqlParts['join'] as $fromAlias => $joins) { - if (! isset($knownAliases[$fromAlias])) { - throw QueryException::unknownAlias($fromAlias, array_keys($knownAliases)); - } - } - } - - /** - * @return bool - */ - private function isLimitQuery() - { - return $this->maxResults !== null || $this->firstResult !== null; - } - - /** - * Converts this instance into an INSERT string in SQL. - * - * @return string - */ - private function getSQLForInsert() - { - return 'INSERT INTO ' . $this->sqlParts['from']['table'] . - ' (' . implode(', ', array_keys($this->sqlParts['values'])) . ')' . - ' VALUES(' . implode(', ', $this->sqlParts['values']) . ')'; - } - - /** - * Converts this instance into an UPDATE string in SQL. - * - * @return string - */ - private function getSQLForUpdate() - { - $table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : ''); - - return 'UPDATE ' . $table - . ' SET ' . implode(', ', $this->sqlParts['set']) - . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : ''); - } - - /** - * Converts this instance into a DELETE string in SQL. - * - * @return string - */ - private function getSQLForDelete() - { - $table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : ''); - - return 'DELETE FROM ' . $table . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : ''); - } - - /** - * Gets a string representation of this QueryBuilder which corresponds to - * the final SQL query being constructed. - * - * @return string The string representation of this QueryBuilder. - */ - public function __toString() - { - return $this->getSQL(); - } - - /** - * Creates a new named parameter and bind the value $value to it. - * - * This method provides a shortcut for PDOStatement::bindValue - * when using prepared statements. - * - * The parameter $value specifies the value that you want to bind. If - * $placeholder is not provided bindValue() will automatically create a - * placeholder for you. An automatic placeholder will be of the name - * ':dcValue1', ':dcValue2' etc. - * - * For more information see {@link http://php.net/pdostatement-bindparam} - * - * Example: - * - * $value = 2; - * $q->eq( 'id', $q->bindValue( $value ) ); - * $stmt = $q->executeQuery(); // executed with 'id = 2' - * - * - * @link http://www.zetacomponents.org - * - * @param mixed $value - * @param mixed $type - * @param string $placeHolder The name to bind with. The string must start with a colon ':'. - * - * @return string the placeholder name used. - */ - public function createNamedParameter($value, $type = ParameterType::STRING, $placeHolder = null) - { - if ($placeHolder === null) { - $this->boundCounter++; - $placeHolder = ':dcValue' . $this->boundCounter; - } - $this->setParameter(substr($placeHolder, 1), $value, $type); - - return $placeHolder; - } - - /** - * Creates a new positional parameter and bind the given value to it. - * - * Attention: If you are using positional parameters with the query builder you have - * to be very careful to bind all parameters in the order they appear in the SQL - * statement , otherwise they get bound in the wrong order which can lead to serious - * bugs in your code. - * - * Example: - * - * $qb = $conn->createQueryBuilder(); - * $qb->select('u.*') - * ->from('users', 'u') - * ->where('u.username = ' . $qb->createPositionalParameter('Foo', ParameterType::STRING)) - * ->orWhere('u.username = ' . $qb->createPositionalParameter('Bar', ParameterType::STRING)) - * - * - * @param mixed $value - * @param int $type - * - * @return string - */ - public function createPositionalParameter($value, $type = ParameterType::STRING) - { - $this->boundCounter++; - $this->setParameter($this->boundCounter, $value, $type); - - return '?'; - } - - /** - * @param string $fromAlias - * @param string[] $knownAliases - * - * @return string - * - * @throws QueryException - */ - private function getSQLForJoins($fromAlias, array &$knownAliases) - { - $sql = ''; - - if (isset($this->sqlParts['join'][$fromAlias])) { - foreach ($this->sqlParts['join'][$fromAlias] as $join) { - if (array_key_exists($join['joinAlias'], $knownAliases)) { - throw QueryException::nonUniqueAlias($join['joinAlias'], array_keys($knownAliases)); - } - $sql .= ' ' . strtoupper($join['joinType']) - . ' JOIN ' . $join['joinTable'] . ' ' . $join['joinAlias'] - . ' ON ' . ((string) $join['joinCondition']); - $knownAliases[$join['joinAlias']] = true; - } - - foreach ($this->sqlParts['join'][$fromAlias] as $join) { - $sql .= $this->getSQLForJoins($join['joinAlias'], $knownAliases); - } - } - - return $sql; - } - - /** - * Deep clone of all expression objects in the SQL parts. - * - * @return void - */ - public function __clone() - { - foreach ($this->sqlParts as $part => $elements) { - if (is_array($this->sqlParts[$part])) { - foreach ($this->sqlParts[$part] as $idx => $element) { - if (! is_object($element)) { - continue; - } - - $this->sqlParts[$part][$idx] = clone $element; - } - } elseif (is_object($elements)) { - $this->sqlParts[$part] = clone $elements; - } - } - - foreach ($this->params as $name => $param) { - if (! is_object($param)) { - continue; - } - - $this->params[$name] = clone $param; - } - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryException.php deleted file mode 100644 index 3fcb3b4..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Query/QueryException.php +++ /dev/null @@ -1,35 +0,0 @@ - $type) { - ++$bindIndex; - - if ($type !== Connection::PARAM_INT_ARRAY && $type !== Connection::PARAM_STR_ARRAY) { - continue; - } - - if ($isPositional) { - $name = $bindIndex; - } - - $arrayPositions[$name] = false; - } - - if (( ! $arrayPositions && $isPositional)) { - return [$query, $params, $types]; - } - - if ($isPositional) { - $paramOffset = 0; - $queryOffset = 0; - $params = array_values($params); - $types = array_values($types); - - $paramPos = self::getPositionalPlaceholderPositions($query); - - foreach ($paramPos as $needle => $needlePos) { - if (! isset($arrayPositions[$needle])) { - continue; - } - - $needle += $paramOffset; - $needlePos += $queryOffset; - $count = count($params[$needle]); - - $params = array_merge( - array_slice($params, 0, $needle), - $params[$needle], - array_slice($params, $needle + 1) - ); - - $types = array_merge( - array_slice($types, 0, $needle), - $count ? - // array needles are at {@link \Doctrine\DBAL\ParameterType} constants - // + {@link Doctrine\DBAL\Connection::ARRAY_PARAM_OFFSET} - array_fill(0, $count, $types[$needle] - Connection::ARRAY_PARAM_OFFSET) : - [], - array_slice($types, $needle + 1) - ); - - $expandStr = $count ? implode(', ', array_fill(0, $count, '?')) : 'NULL'; - $query = substr($query, 0, $needlePos) . $expandStr . substr($query, $needlePos + 1); - - $paramOffset += ($count - 1); // Grows larger by number of parameters minus the replaced needle. - $queryOffset += (strlen($expandStr) - 1); - } - - return [$query, $params, $types]; - } - - $queryOffset = 0; - $typesOrd = []; - $paramsOrd = []; - - $paramPos = self::getNamedPlaceholderPositions($query); - - foreach ($paramPos as $pos => $paramName) { - $paramLen = strlen($paramName) + 1; - $value = static::extractParam($paramName, $params, true); - - if (! isset($arrayPositions[$paramName]) && ! isset($arrayPositions[':' . $paramName])) { - $pos += $queryOffset; - $queryOffset -= ($paramLen - 1); - $paramsOrd[] = $value; - $typesOrd[] = static::extractParam($paramName, $types, false, ParameterType::STRING); - $query = substr($query, 0, $pos) . '?' . substr($query, ($pos + $paramLen)); - - continue; - } - - $count = count($value); - $expandStr = $count > 0 ? implode(', ', array_fill(0, $count, '?')) : 'NULL'; - - foreach ($value as $val) { - $paramsOrd[] = $val; - $typesOrd[] = static::extractParam($paramName, $types, false) - Connection::ARRAY_PARAM_OFFSET; - } - - $pos += $queryOffset; - $queryOffset += (strlen($expandStr) - $paramLen); - $query = substr($query, 0, $pos) . $expandStr . substr($query, ($pos + $paramLen)); - } - - return [$query, $paramsOrd, $typesOrd]; - } - - /** - * Slice the SQL statement around pairs of quotes and - * return string fragments of SQL outside of quoted literals. - * Each fragment is captured as a 2-element array: - * - * 0 => matched fragment string, - * 1 => offset of fragment in $statement - * - * @param string $statement - * - * @return mixed[][] - */ - private static function getUnquotedStatementFragments($statement) - { - $literal = self::ESCAPED_SINGLE_QUOTED_TEXT . '|' . - self::ESCAPED_DOUBLE_QUOTED_TEXT . '|' . - self::ESCAPED_BACKTICK_QUOTED_TEXT . '|' . - self::ESCAPED_BRACKET_QUOTED_TEXT; - $expression = sprintf('/((.+(?i:ARRAY)\\[.+\\])|([^\'"`\\[]+))(?:%s)?/s', $literal); - - preg_match_all($expression, $statement, $fragments, PREG_OFFSET_CAPTURE); - - return $fragments[1]; - } - - /** - * @param string $paramName The name of the parameter (without a colon in front) - * @param mixed $paramsOrTypes A hash of parameters or types - * @param bool $isParam - * @param mixed $defaultValue An optional default value. If omitted, an exception is thrown - * - * @return mixed - * - * @throws SQLParserUtilsException - */ - private static function extractParam($paramName, $paramsOrTypes, $isParam, $defaultValue = null) - { - if (array_key_exists($paramName, $paramsOrTypes)) { - return $paramsOrTypes[$paramName]; - } - - // Hash keys can be prefixed with a colon for compatibility - if (array_key_exists(':' . $paramName, $paramsOrTypes)) { - return $paramsOrTypes[':' . $paramName]; - } - - if ($defaultValue !== null) { - return $defaultValue; - } - - if ($isParam) { - throw SQLParserUtilsException::missingParam($paramName); - } - - throw SQLParserUtilsException::missingType($paramName); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtilsException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtilsException.php deleted file mode 100644 index a500ed5..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/SQLParserUtilsException.php +++ /dev/null @@ -1,31 +0,0 @@ - Table($tableName)); if you want to rename the table, you have to make sure - */ -abstract class AbstractAsset -{ - /** @var string */ - protected $_name; - - /** - * Namespace of the asset. If none isset the default namespace is assumed. - * - * @var string|null - */ - protected $_namespace = null; - - /** @var bool */ - protected $_quoted = false; - - /** - * Sets the name of this asset. - * - * @param string $name - * - * @return void - */ - protected function _setName($name) - { - if ($this->isIdentifierQuoted($name)) { - $this->_quoted = true; - $name = $this->trimQuotes($name); - } - if (strpos($name, '.') !== false) { - $parts = explode('.', $name); - $this->_namespace = $parts[0]; - $name = $parts[1]; - } - $this->_name = $name; - } - - /** - * Is this asset in the default namespace? - * - * @param string $defaultNamespaceName - * - * @return bool - */ - public function isInDefaultNamespace($defaultNamespaceName) - { - return $this->_namespace === $defaultNamespaceName || $this->_namespace === null; - } - - /** - * Gets the namespace name of this asset. - * - * If NULL is returned this means the default namespace is used. - * - * @return string|null - */ - public function getNamespaceName() - { - return $this->_namespace; - } - - /** - * The shortest name is stripped of the default namespace. All other - * namespaced elements are returned as full-qualified names. - * - * @param string|null $defaultNamespaceName - * - * @return string - */ - public function getShortestName($defaultNamespaceName) - { - $shortestName = $this->getName(); - if ($this->_namespace === $defaultNamespaceName) { - $shortestName = $this->_name; - } - - return strtolower($shortestName); - } - - /** - * The normalized name is full-qualified and lowerspaced. Lowerspacing is - * actually wrong, but we have to do it to keep our sanity. If you are - * using database objects that only differentiate in the casing (FOO vs - * Foo) then you will NOT be able to use Doctrine Schema abstraction. - * - * Every non-namespaced element is prefixed with the default namespace - * name which is passed as argument to this method. - * - * @param string $defaultNamespaceName - * - * @return string - */ - public function getFullQualifiedName($defaultNamespaceName) - { - $name = $this->getName(); - if (! $this->_namespace) { - $name = $defaultNamespaceName . '.' . $name; - } - - return strtolower($name); - } - - /** - * Checks if this asset's name is quoted. - * - * @return bool - */ - public function isQuoted() - { - return $this->_quoted; - } - - /** - * Checks if this identifier is quoted. - * - * @param string $identifier - * - * @return bool - */ - protected function isIdentifierQuoted($identifier) - { - return isset($identifier[0]) && ($identifier[0] === '`' || $identifier[0] === '"' || $identifier[0] === '['); - } - - /** - * Trim quotes from the identifier. - * - * @param string $identifier - * - * @return string - */ - protected function trimQuotes($identifier) - { - return str_replace(['`', '"', '[', ']'], '', $identifier); - } - - /** - * Returns the name of this schema asset. - * - * @return string - */ - public function getName() - { - if ($this->_namespace) { - return $this->_namespace . '.' . $this->_name; - } - - return $this->_name; - } - - /** - * Gets the quoted representation of this asset but only if it was defined with one. Otherwise - * return the plain unquoted value as inserted. - * - * @return string - */ - public function getQuotedName(AbstractPlatform $platform) - { - $keywords = $platform->getReservedKeywordsList(); - $parts = explode('.', $this->getName()); - foreach ($parts as $k => $v) { - $parts[$k] = $this->_quoted || $keywords->isKeyword($v) ? $platform->quoteIdentifier($v) : $v; - } - - return implode('.', $parts); - } - - /** - * Generates 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 string[] $columnNames - * @param string $prefix - * @param int $maxSize - * - * @return string - */ - protected function _generateIdentifierName($columnNames, $prefix = '', $maxSize = 30) - { - $hash = implode('', array_map(static function ($column) { - return dechex(crc32($column)); - }, $columnNames)); - - return strtoupper(substr($prefix . '_' . $hash, 0, $maxSize)); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php deleted file mode 100644 index 8e4ffa5..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/AbstractSchemaManager.php +++ /dev/null @@ -1,1135 +0,0 @@ -_conn = $conn; - $this->_platform = $platform ?: $this->_conn->getDatabasePlatform(); - } - - /** - * Returns the associated platform. - * - * @return AbstractPlatform - */ - public function getDatabasePlatform() - { - return $this->_platform; - } - - /** - * Tries 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. - * - * - * $result = $sm->tryMethod('dropView', 'view_name'); - * - * - * @return mixed - */ - public function tryMethod() - { - $args = func_get_args(); - $method = $args[0]; - unset($args[0]); - $args = array_values($args); - - $callback = [$this, $method]; - assert(is_callable($callback)); - - try { - return call_user_func_array($callback, $args); - } catch (Throwable $e) { - return false; - } - } - - /** - * Lists the available databases for this connection. - * - * @return string[] - */ - public function listDatabases() - { - $sql = $this->_platform->getListDatabasesSQL(); - - $databases = $this->_conn->fetchAll($sql); - - return $this->_getPortableDatabasesList($databases); - } - - /** - * Returns a list of all namespaces in the current database. - * - * @return string[] - */ - public function listNamespaceNames() - { - $sql = $this->_platform->getListNamespacesSQL(); - - $namespaces = $this->_conn->fetchAll($sql); - - return $this->getPortableNamespacesList($namespaces); - } - - /** - * Lists the available sequences for this connection. - * - * @param string|null $database - * - * @return Sequence[] - */ - public function listSequences($database = null) - { - if ($database === null) { - $database = $this->_conn->getDatabase(); - } - $sql = $this->_platform->getListSequencesSQL($database); - - $sequences = $this->_conn->fetchAll($sql); - - return $this->filterAssetNames($this->_getPortableSequencesList($sequences)); - } - - /** - * Lists 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 across different RDBMS. Use - * {@see listTableIndexes($tableName)} to retrieve the primary key - * of a table. Where a RDBMS specifies more details, these are held - * in the platformDetails array. - * - * @param string $table The name of the table. - * @param string|null $database - * - * @return Column[] - */ - public function listTableColumns($table, $database = null) - { - if (! $database) { - $database = $this->_conn->getDatabase(); - } - - $sql = $this->_platform->getListTableColumnsSQL($table, $database); - - $tableColumns = $this->_conn->fetchAll($sql); - - return $this->_getPortableTableColumnList($table, $database, $tableColumns); - } - - /** - * Lists 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[] - */ - public function listTableIndexes($table) - { - $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); - - $tableIndexes = $this->_conn->fetchAll($sql); - - return $this->_getPortableTableIndexesList($tableIndexes, $table); - } - - /** - * Returns true if all the given tables exist. - * - * The usage of a string $tableNames is deprecated. Pass a one-element array instead. - * - * @param string|string[] $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()))); - } - - /** - * Returns a list of all tables in the current database. - * - * @return string[] - */ - public function listTableNames() - { - $sql = $this->_platform->getListTablesSQL(); - - $tables = $this->_conn->fetchAll($sql); - $tableNames = $this->_getPortableTablesList($tables); - - return $this->filterAssetNames($tableNames); - } - - /** - * Filters asset names if they are configured to return only a subset of all - * the found elements. - * - * @param mixed[] $assetNames - * - * @return mixed[] - */ - protected function filterAssetNames($assetNames) - { - $filter = $this->_conn->getConfiguration()->getSchemaAssetsFilter(); - if (! $filter) { - return $assetNames; - } - - return array_values(array_filter($assetNames, $filter)); - } - - /** - * @deprecated Use Configuration::getSchemaAssetsFilter() instead - * - * @return string|null - */ - protected function getFilterSchemaAssetsExpression() - { - return $this->_conn->getConfiguration()->getFilterSchemaAssetsExpression(); - } - - /** - * Lists the tables for this connection. - * - * @return Table[] - */ - public function listTables() - { - $tableNames = $this->listTableNames(); - - $tables = []; - foreach ($tableNames as $tableName) { - $tables[] = $this->listTableDetails($tableName); - } - - return $tables; - } - - /** - * @param string $tableName - * - * @return Table - */ - public function listTableDetails($tableName) - { - $columns = $this->listTableColumns($tableName); - $foreignKeys = []; - if ($this->_platform->supportsForeignKeyConstraints()) { - $foreignKeys = $this->listTableForeignKeys($tableName); - } - $indexes = $this->listTableIndexes($tableName); - - return new Table($tableName, $columns, $indexes, $foreignKeys); - } - - /** - * Lists 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); - } - - /** - * Lists the foreign keys for the given table. - * - * @param string $table The name of the table. - * @param string|null $database - * - * @return ForeignKeyConstraint[] - */ - public function listTableForeignKeys($table, $database = null) - { - if ($database === null) { - $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. - * - * @return void - */ - public function dropDatabase($database) - { - $this->_execSql($this->_platform->getDropDatabaseSQL($database)); - } - - /** - * Drops the given table. - * - * @param string $tableName The name of the table to drop. - * - * @return void - */ - public function dropTable($tableName) - { - $this->_execSql($this->_platform->getDropTableSQL($tableName)); - } - - /** - * Drops the index from the given table. - * - * @param Index|string $index The name of the index. - * @param Table|string $table The name of the table. - * - * @return void - */ - public function dropIndex($index, $table) - { - if ($index instanceof Index) { - $index = $index->getQuotedName($this->_platform); - } - - $this->_execSql($this->_platform->getDropIndexSQL($index, $table)); - } - - /** - * Drops the constraint from the given table. - * - * @param Table|string $table The name of the table. - * - * @return void - */ - public function dropConstraint(Constraint $constraint, $table) - { - $this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table)); - } - - /** - * Drops a foreign key from a table. - * - * @param ForeignKeyConstraint|string $foreignKey The name of the foreign key. - * @param Table|string $table The name of the table with the foreign key. - * - * @return void - */ - 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. - * - * @return void - */ - public function dropSequence($name) - { - $this->_execSql($this->_platform->getDropSequenceSQL($name)); - } - - /** - * Drops a view. - * - * @param string $name The name of the view. - * - * @return void - */ - 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. - * - * @return void - */ - public function createDatabase($database) - { - $this->_execSql($this->_platform->getCreateDatabaseSQL($database)); - } - - /** - * Creates a new table. - * - * @return void - */ - public function createTable(Table $table) - { - $createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS; - $this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags)); - } - - /** - * Creates a new sequence. - * - * @param Sequence $sequence - * - * @return void - * - * @throws ConnectionException If something fails at database level. - */ - public function createSequence($sequence) - { - $this->_execSql($this->_platform->getCreateSequenceSQL($sequence)); - } - - /** - * Creates a constraint on a table. - * - * @param Table|string $table - * - * @return void - */ - public function createConstraint(Constraint $constraint, $table) - { - $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table)); - } - - /** - * Creates a new index on a table. - * - * @param Table|string $table The name of the table on which the index is to be created. - * - * @return void - */ - public function createIndex(Index $index, $table) - { - $this->_execSql($this->_platform->getCreateIndexSQL($index, $table)); - } - - /** - * Creates a new foreign key. - * - * @param ForeignKeyConstraint $foreignKey The ForeignKey instance. - * @param Table|string $table The name of the table on which the foreign key is to be created. - * - * @return void - */ - public function createForeignKey(ForeignKeyConstraint $foreignKey, $table) - { - $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table)); - } - - /** - * Creates a new view. - * - * @return void - */ - public function createView(View $view) - { - $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql())); - } - - /* dropAndCreate*() Methods */ - - /** - * Drops and creates a constraint. - * - * @see dropConstraint() - * @see createConstraint() - * - * @param Table|string $table - * - * @return void - */ - public function dropAndCreateConstraint(Constraint $constraint, $table) - { - $this->tryMethod('dropConstraint', $constraint, $table); - $this->createConstraint($constraint, $table); - } - - /** - * Drops and creates a new index on a table. - * - * @param Table|string $table The name of the table on which the index is to be created. - * - * @return void - */ - public function dropAndCreateIndex(Index $index, $table) - { - $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table); - $this->createIndex($index, $table); - } - - /** - * Drops and creates a new foreign key. - * - * @param ForeignKeyConstraint $foreignKey An associative array that defines properties of the foreign key to be created. - * @param Table|string $table The name of the table on which the foreign key is to be created. - * - * @return void - */ - public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table) - { - $this->tryMethod('dropForeignKey', $foreignKey, $table); - $this->createForeignKey($foreignKey, $table); - } - - /** - * Drops and create a new sequence. - * - * @return void - * - * @throws ConnectionException If something fails at database level. - */ - public function dropAndCreateSequence(Sequence $sequence) - { - $this->tryMethod('dropSequence', $sequence->getQuotedName($this->_platform)); - $this->createSequence($sequence); - } - - /** - * Drops and creates a new table. - * - * @return void - */ - public function dropAndCreateTable(Table $table) - { - $this->tryMethod('dropTable', $table->getQuotedName($this->_platform)); - $this->createTable($table); - } - - /** - * Drops and creates a new database. - * - * @param string $database The name of the database to create. - * - * @return void - */ - public function dropAndCreateDatabase($database) - { - $this->tryMethod('dropDatabase', $database); - $this->createDatabase($database); - } - - /** - * Drops and creates a new view. - * - * @return void - */ - public function dropAndCreateView(View $view) - { - $this->tryMethod('dropView', $view->getQuotedName($this->_platform)); - $this->createView($view); - } - - /* alterTable() Methods */ - - /** - * Alters an existing tables schema. - * - * @return void - */ - public function alterTable(TableDiff $tableDiff) - { - $queries = $this->_platform->getAlterTableSQL($tableDiff); - if (! is_array($queries) || ! count($queries)) { - return; - } - - foreach ($queries as $ddlQuery) { - $this->_execSql($ddlQuery); - } - } - - /** - * Renames a given table to another name. - * - * @param string $name The current name of the table. - * @param string $newName The new name of the table. - * - * @return void - */ - 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 - */ - - /** - * @param mixed[] $databases - * - * @return string[] - */ - protected function _getPortableDatabasesList($databases) - { - $list = []; - foreach ($databases as $value) { - $value = $this->_getPortableDatabaseDefinition($value); - - if (! $value) { - continue; - } - - $list[] = $value; - } - - return $list; - } - - /** - * Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition. - * - * @param mixed[][] $namespaces The list of namespace names in the native DBMS data definition. - * - * @return string[] - */ - protected function getPortableNamespacesList(array $namespaces) - { - $namespacesList = []; - - foreach ($namespaces as $namespace) { - $namespacesList[] = $this->getPortableNamespaceDefinition($namespace); - } - - return $namespacesList; - } - - /** - * @param mixed $database - * - * @return mixed - */ - protected function _getPortableDatabaseDefinition($database) - { - return $database; - } - - /** - * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition. - * - * @param mixed[] $namespace The native DBMS namespace definition. - * - * @return mixed - */ - protected function getPortableNamespaceDefinition(array $namespace) - { - return $namespace; - } - - /** - * @deprecated - * - * @param mixed[][] $functions - * - * @return mixed[][] - */ - protected function _getPortableFunctionsList($functions) - { - $list = []; - foreach ($functions as $value) { - $value = $this->_getPortableFunctionDefinition($value); - - if (! $value) { - continue; - } - - $list[] = $value; - } - - return $list; - } - - /** - * @deprecated - * - * @param mixed[] $function - * - * @return mixed - */ - protected function _getPortableFunctionDefinition($function) - { - return $function; - } - - /** - * @param mixed[][] $triggers - * - * @return mixed[][] - */ - protected function _getPortableTriggersList($triggers) - { - $list = []; - foreach ($triggers as $value) { - $value = $this->_getPortableTriggerDefinition($value); - - if (! $value) { - continue; - } - - $list[] = $value; - } - - return $list; - } - - /** - * @param mixed[] $trigger - * - * @return mixed - */ - protected function _getPortableTriggerDefinition($trigger) - { - return $trigger; - } - - /** - * @param mixed[][] $sequences - * - * @return Sequence[] - */ - protected function _getPortableSequencesList($sequences) - { - $list = []; - - foreach ($sequences as $value) { - $list[] = $this->_getPortableSequenceDefinition($value); - } - - return $list; - } - - /** - * @param mixed[] $sequence - * - * @return Sequence - * - * @throws DBALException - */ - 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 string $table The name of the table. - * @param string $database - * @param mixed[][] $tableColumns - * - * @return Column[] - */ - protected function _getPortableTableColumnList($table, $database, $tableColumns) - { - $eventManager = $this->_platform->getEventManager(); - - $list = []; - foreach ($tableColumns as $tableColumn) { - $column = null; - $defaultPrevented = false; - - if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) { - $eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn, $table, $database, $this->_conn); - $eventManager->dispatchEvent(Events::onSchemaColumnDefinition, $eventArgs); - - $defaultPrevented = $eventArgs->isDefaultPrevented(); - $column = $eventArgs->getColumn(); - } - - if (! $defaultPrevented) { - $column = $this->_getPortableTableColumnDefinition($tableColumn); - } - - if (! $column) { - continue; - } - - $name = strtolower($column->getQuotedName($this->_platform)); - $list[$name] = $column; - } - - return $list; - } - - /** - * Gets Table Column Definition. - * - * @param mixed[] $tableColumn - * - * @return Column - */ - abstract protected function _getPortableTableColumnDefinition($tableColumn); - - /** - * Aggregates and groups the index results according to the required data result. - * - * @param mixed[][] $tableIndexRows - * @param string|null $tableName - * - * @return Index[] - */ - protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null) - { - $result = []; - foreach ($tableIndexRows as $tableIndex) { - $indexName = $keyName = $tableIndex['key_name']; - if ($tableIndex['primary']) { - $keyName = 'primary'; - } - $keyName = strtolower($keyName); - - if (! isset($result[$keyName])) { - $options = [ - 'lengths' => [], - ]; - - if (isset($tableIndex['where'])) { - $options['where'] = $tableIndex['where']; - } - - $result[$keyName] = [ - 'name' => $indexName, - 'columns' => [], - 'unique' => ! $tableIndex['non_unique'], - 'primary' => $tableIndex['primary'], - 'flags' => $tableIndex['flags'] ?? [], - 'options' => $options, - ]; - } - - $result[$keyName]['columns'][] = $tableIndex['column_name']; - $result[$keyName]['options']['lengths'][] = $tableIndex['length'] ?? null; - } - - $eventManager = $this->_platform->getEventManager(); - - $indexes = []; - foreach ($result as $indexKey => $data) { - $index = null; - $defaultPrevented = false; - - if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) { - $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn); - $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs); - - $defaultPrevented = $eventArgs->isDefaultPrevented(); - $index = $eventArgs->getIndex(); - } - - if (! $defaultPrevented) { - $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags'], $data['options']); - } - - if (! $index) { - continue; - } - - $indexes[$indexKey] = $index; - } - - return $indexes; - } - - /** - * @param mixed[][] $tables - * - * @return string[] - */ - protected function _getPortableTablesList($tables) - { - $list = []; - foreach ($tables as $value) { - $value = $this->_getPortableTableDefinition($value); - - if (! $value) { - continue; - } - - $list[] = $value; - } - - return $list; - } - - /** - * @param mixed $table - * - * @return string - */ - protected function _getPortableTableDefinition($table) - { - return $table; - } - - /** - * @param mixed[][] $users - * - * @return string[][] - */ - protected function _getPortableUsersList($users) - { - $list = []; - foreach ($users as $value) { - $value = $this->_getPortableUserDefinition($value); - - if (! $value) { - continue; - } - - $list[] = $value; - } - - return $list; - } - - /** - * @param string[] $user - * - * @return string[] - */ - protected function _getPortableUserDefinition($user) - { - return $user; - } - - /** - * @param mixed[][] $views - * - * @return View[] - */ - protected function _getPortableViewsList($views) - { - $list = []; - foreach ($views as $value) { - $view = $this->_getPortableViewDefinition($value); - - if (! $view) { - continue; - } - - $viewName = strtolower($view->getQuotedName($this->_platform)); - $list[$viewName] = $view; - } - - return $list; - } - - /** - * @param mixed[] $view - * - * @return View|false - */ - protected function _getPortableViewDefinition($view) - { - return false; - } - - /** - * @param mixed[][] $tableForeignKeys - * - * @return ForeignKeyConstraint[] - */ - protected function _getPortableTableForeignKeysList($tableForeignKeys) - { - $list = []; - - foreach ($tableForeignKeys as $value) { - $list[] = $this->_getPortableTableForeignKeyDefinition($value); - } - - return $list; - } - - /** - * @param mixed $tableForeignKey - * - * @return ForeignKeyConstraint - */ - protected function _getPortableTableForeignKeyDefinition($tableForeignKey) - { - return $tableForeignKey; - } - - /** - * @param string[]|string $sql - * - * @return void - */ - protected function _execSql($sql) - { - foreach ((array) $sql as $query) { - $this->_conn->executeUpdate($query); - } - } - - /** - * Creates a schema instance for the current database. - * - * @return Schema - */ - public function createSchema() - { - $namespaces = []; - - if ($this->_platform->supportsSchemas()) { - $namespaces = $this->listNamespaceNames(); - } - - $sequences = []; - - if ($this->_platform->supportsSequences()) { - $sequences = $this->listSequences(); - } - - $tables = $this->listTables(); - - return new Schema($tables, $sequences, $this->createSchemaConfig(), $namespaces); - } - - /** - * Creates the configuration for this schema. - * - * @return SchemaConfig - */ - public function createSchemaConfig() - { - $schemaConfig = new SchemaConfig(); - $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength()); - - $searchPaths = $this->getSchemaSearchPaths(); - if (isset($searchPaths[0])) { - $schemaConfig->setName($searchPaths[0]); - } - - $params = $this->_conn->getParams(); - if (! isset($params['defaultTableOptions'])) { - $params['defaultTableOptions'] = []; - } - if (! isset($params['defaultTableOptions']['charset']) && isset($params['charset'])) { - $params['defaultTableOptions']['charset'] = $params['charset']; - } - $schemaConfig->setDefaultTableOptions($params['defaultTableOptions']); - - return $schemaConfig; - } - - /** - * The search path for namespaces in the currently connected database. - * - * The first entry is usually the default namespace in the Schema. All - * further namespaces contain tables/sequences which can also be addressed - * with a short, not full-qualified name. - * - * For databases that don't support subschema/namespaces this method - * returns the name of the currently connected database. - * - * @return string[] - */ - public function getSchemaSearchPaths() - { - return [$this->_conn->getDatabase()]; - } - - /** - * Given a table comment this method tries to extract a typehint for Doctrine Type, or returns - * the type given as default. - * - * @param string|null $comment - * @param string $currentType - * - * @return string - */ - public function extractDoctrineTypeFromComment($comment, $currentType) - { - if ($comment !== null && preg_match('(\(DC2Type:(((?!\)).)+)\))', $comment, $match)) { - return $match[1]; - } - - return $currentType; - } - - /** - * @param string|null $comment - * @param string|null $type - * - * @return string|null - */ - public function removeDoctrineTypeFromComment($comment, $type) - { - if ($comment === null) { - return null; - } - - return str_replace('(DC2Type:' . $type . ')', '', $comment); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Column.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Column.php deleted file mode 100644 index 56c39c1..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Column.php +++ /dev/null @@ -1,451 +0,0 @@ -_setName($columnName); - $this->setType($type); - $this->setOptions($options); - } - - /** - * @param mixed[] $options - * - * @return Column - */ - public function setOptions(array $options) - { - foreach ($options as $name => $value) { - $method = 'set' . $name; - if (! method_exists($this, $method)) { - // next major: throw an exception - @trigger_error(sprintf( - 'The "%s" column option is not supported,' . - ' setting it is deprecated and will cause an error in Doctrine 3.0', - $name - ), E_USER_DEPRECATED); - - continue; - } - $this->$method($value); - } - - return $this; - } - - /** - * @return Column - */ - public function setType(Type $type) - { - $this->_type = $type; - - return $this; - } - - /** - * @param int|null $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) - { - if (! is_numeric($precision)) { - $precision = 10; // defaults to 10 when no valid precision is given. - } - - $this->_precision = (int) $precision; - - return $this; - } - - /** - * @param int $scale - * - * @return Column - */ - public function setScale($scale) - { - if (! is_numeric($scale)) { - $scale = 0; - } - - $this->_scale = (int) $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 mixed[] $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 $value - * - * @return Column - */ - public function setColumnDefinition($value) - { - $this->_columnDefinition = $value; - - return $this; - } - - /** - * @return Type - */ - public function getType() - { - return $this->_type; - } - - /** - * @return int|null - */ - public function getLength() - { - return $this->_length; - } - - /** - * @return int - */ - public function getPrecision() - { - return $this->_precision; - } - - /** - * @return int - */ - public function getScale() - { - return $this->_scale; - } - - /** - * @return bool - */ - public function getUnsigned() - { - return $this->_unsigned; - } - - /** - * @return bool - */ - public function getFixed() - { - return $this->_fixed; - } - - /** - * @return bool - */ - public function getNotnull() - { - return $this->_notnull; - } - - /** - * @return string|null - */ - public function getDefault() - { - return $this->_default; - } - - /** - * @return mixed[] - */ - public function getPlatformOptions() - { - return $this->_platformOptions; - } - - /** - * @param string $name - * - * @return bool - */ - public function hasPlatformOption($name) - { - return isset($this->_platformOptions[$name]); - } - - /** - * @param string $name - * - * @return mixed - */ - public function getPlatformOption($name) - { - return $this->_platformOptions[$name]; - } - - /** - * @return string|null - */ - public function getColumnDefinition() - { - return $this->_columnDefinition; - } - - /** - * @return bool - */ - public function getAutoincrement() - { - return $this->_autoincrement; - } - - /** - * @param bool $flag - * - * @return Column - */ - public function setAutoincrement($flag) - { - $this->_autoincrement = $flag; - - return $this; - } - - /** - * @param string|null $comment - * - * @return Column - */ - public function setComment($comment) - { - $this->_comment = $comment; - - return $this; - } - - /** - * @return string|null - */ - public function getComment() - { - return $this->_comment; - } - - /** - * @param string $name - * @param mixed $value - * - * @return Column - */ - public function setCustomSchemaOption($name, $value) - { - $this->_customSchemaOptions[$name] = $value; - - return $this; - } - - /** - * @param string $name - * - * @return bool - */ - public function hasCustomSchemaOption($name) - { - return isset($this->_customSchemaOptions[$name]); - } - - /** - * @param string $name - * - * @return mixed - */ - public function getCustomSchemaOption($name) - { - return $this->_customSchemaOptions[$name]; - } - - /** - * @param mixed[] $customSchemaOptions - * - * @return Column - */ - public function setCustomSchemaOptions(array $customSchemaOptions) - { - $this->_customSchemaOptions = $customSchemaOptions; - - return $this; - } - - /** - * @return mixed[] - */ - public function getCustomSchemaOptions() - { - return $this->_customSchemaOptions; - } - - /** - * @return mixed[] - */ - public function toArray() - { - return array_merge([ - '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, - 'comment' => $this->_comment, - ], $this->_platformOptions, $this->_customSchemaOptions); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ColumnDiff.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ColumnDiff.php deleted file mode 100644 index 1589f98..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ColumnDiff.php +++ /dev/null @@ -1,55 +0,0 @@ -oldColumnName = $oldColumnName; - $this->column = $column; - $this->changedProperties = $changedProperties; - $this->fromColumn = $fromColumn; - } - - /** - * @param string $propertyName - * - * @return bool - */ - public function hasChanged($propertyName) - { - return in_array($propertyName, $this->changedProperties); - } - - /** - * @return Identifier - */ - public function getOldColumnName() - { - $quote = $this->fromColumn && $this->fromColumn->isQuoted(); - - return new Identifier($this->oldColumnName, $quote); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Comparator.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Comparator.php deleted file mode 100644 index 9ccaa9a..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Comparator.php +++ /dev/null @@ -1,533 +0,0 @@ -compare($fromSchema, $toSchema); - } - - /** - * Returns a SchemaDiff object containing the differences between the schemas $fromSchema and $toSchema. - * - * The returned differences 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. - * - * @return SchemaDiff - */ - public function compare(Schema $fromSchema, Schema $toSchema) - { - $diff = new SchemaDiff(); - $diff->fromSchema = $fromSchema; - - $foreignKeysToTable = []; - - foreach ($toSchema->getNamespaces() as $namespace) { - if ($fromSchema->hasNamespace($namespace)) { - continue; - } - - $diff->newNamespaces[$namespace] = $namespace; - } - - foreach ($fromSchema->getNamespaces() as $namespace) { - if ($toSchema->hasNamespace($namespace)) { - continue; - } - - $diff->removedNamespaces[$namespace] = $namespace; - } - - foreach ($toSchema->getTables() as $table) { - $tableName = $table->getShortestName($toSchema->getName()); - if (! $fromSchema->hasTable($tableName)) { - $diff->newTables[$tableName] = $toSchema->getTable($tableName); - } else { - $tableDifferences = $this->diffTable($fromSchema->getTable($tableName), $toSchema->getTable($tableName)); - if ($tableDifferences !== false) { - $diff->changedTables[$tableName] = $tableDifferences; - } - } - } - - /* Check if there are tables removed */ - foreach ($fromSchema->getTables() as $table) { - $tableName = $table->getShortestName($fromSchema->getName()); - - $table = $fromSchema->getTable($tableName); - 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] = []; - } - $foreignKeysToTable[$foreignTable][] = $foreignKey; - } - } - - foreach ($diff->removedTables as $tableName => $table) { - if (! isset($foreignKeysToTable[$tableName])) { - continue; - } - - $diff->orphanedForeignKeys = array_merge($diff->orphanedForeignKeys, $foreignKeysToTable[$tableName]); - - // deleting duplicated foreign keys present on both on the orphanedForeignKey - // and the removedForeignKeys from changedTables - foreach ($foreignKeysToTable[$tableName] as $foreignKey) { - // strtolower the table name to make if compatible with getShortestName - $localTableName = strtolower($foreignKey->getLocalTableName()); - if (! isset($diff->changedTables[$localTableName])) { - continue; - } - - foreach ($diff->changedTables[$localTableName]->removedForeignKeys as $key => $removedForeignKey) { - assert($removedForeignKey instanceof ForeignKeyConstraint); - - // We check if the key is from the removed table if not we skip. - if ($tableName !== strtolower($removedForeignKey->getForeignTableName())) { - continue; - } - unset($diff->changedTables[$localTableName]->removedForeignKeys[$key]); - } - } - } - - foreach ($toSchema->getSequences() as $sequence) { - $sequenceName = $sequence->getShortestName($toSchema->getName()); - if (! $fromSchema->hasSequence($sequenceName)) { - if (! $this->isAutoIncrementSequenceInSchema($fromSchema, $sequence)) { - $diff->newSequences[] = $sequence; - } - } else { - if ($this->diffSequence($sequence, $fromSchema->getSequence($sequenceName))) { - $diff->changedSequences[] = $toSchema->getSequence($sequenceName); - } - } - } - - foreach ($fromSchema->getSequences() as $sequence) { - if ($this->isAutoIncrementSequenceInSchema($toSchema, $sequence)) { - continue; - } - - $sequenceName = $sequence->getShortestName($fromSchema->getName()); - - if ($toSchema->hasSequence($sequenceName)) { - continue; - } - - $diff->removedSequences[] = $sequence; - } - - return $diff; - } - - /** - * @param Schema $schema - * @param Sequence $sequence - * - * @return bool - */ - private function isAutoIncrementSequenceInSchema($schema, $sequence) - { - foreach ($schema->getTables() as $table) { - if ($sequence->isAutoIncrementsFor($table)) { - return true; - } - } - - return false; - } - - /** - * @return bool - */ - public function diffSequence(Sequence $sequence1, Sequence $sequence2) - { - if ($sequence1->getAllocationSize() !== $sequence2->getAllocationSize()) { - return true; - } - - return $sequence1->getInitialValue() !== $sequence2->getInitialValue(); - } - - /** - * Returns the difference between the tables $table1 and $table2. - * - * If there are no differences this method returns the boolean false. - * - * @return TableDiff|false - */ - public function diffTable(Table $table1, Table $table2) - { - $changes = 0; - $tableDifferences = new TableDiff($table1->getName()); - $tableDifferences->fromTable = $table1; - - $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)) { - continue; - } - - $tableDifferences->addedColumns[$columnName] = $column; - $changes++; - } - /* See if there are any removed fields in table 2 */ - foreach ($table1Columns as $columnName => $column) { - // See if column is removed in table 2. - if (! $table2->hasColumn($columnName)) { - $tableDifferences->removedColumns[$columnName] = $column; - $changes++; - continue; - } - - // See if column has changed properties in table 2. - $changedProperties = $this->diffColumn($column, $table2->getColumn($columnName)); - - if (empty($changedProperties)) { - continue; - } - - $columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties); - $columnDiff->fromColumn = $column; - $tableDifferences->changedColumns[$column->getName()] = $columnDiff; - $changes++; - } - - $this->detectColumnRenamings($tableDifferences); - - $table1Indexes = $table1->getIndexes(); - $table2Indexes = $table2->getIndexes(); - - /* See if all the indexes in table 1 exist in table 2 */ - foreach ($table2Indexes as $indexName => $index) { - if (($index->isPrimary() && $table1->hasPrimaryKey()) || $table1->hasIndex($indexName)) { - continue; - } - - $tableDifferences->addedIndexes[$indexName] = $index; - $changes++; - } - /* See if there are any removed indexes in table 2 */ - foreach ($table1Indexes as $indexName => $index) { - // See if index is removed in table 2. - if (($index->isPrimary() && ! $table2->hasPrimaryKey()) || - ! $index->isPrimary() && ! $table2->hasIndex($indexName) - ) { - $tableDifferences->removedIndexes[$indexName] = $index; - $changes++; - continue; - } - - // See if index has changed in table 2. - $table2Index = $index->isPrimary() ? $table2->getPrimaryKey() : $table2->getIndex($indexName); - assert($table2Index instanceof Index); - - if (! $this->diffIndex($index, $table2Index)) { - continue; - } - - $tableDifferences->changedIndexes[$indexName] = $table2Index; - $changes++; - } - - $this->detectIndexRenamings($tableDifferences); - - $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], $toFkeys[$key2]); - } else { - if (strtolower($constraint1->getName()) === strtolower($constraint2->getName())) { - $tableDifferences->changedForeignKeys[] = $constraint2; - $changes++; - unset($fromFkeys[$key1], $toFkeys[$key2]); - } - } - } - } - - foreach ($fromFkeys as $constraint1) { - $tableDifferences->removedForeignKeys[] = $constraint1; - $changes++; - } - - foreach ($toFkeys as $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 ambiguities between different possibilities should not lead to renaming at all. - * - * @return void - */ - private function detectColumnRenamings(TableDiff $tableDifferences) - { - $renameCandidates = []; - foreach ($tableDifferences->addedColumns as $addedColumnName => $addedColumn) { - foreach ($tableDifferences->removedColumns as $removedColumn) { - if (count($this->diffColumn($addedColumn, $removedColumn)) !== 0) { - continue; - } - - $renameCandidates[$addedColumn->getName()][] = [$removedColumn, $addedColumn, $addedColumnName]; - } - } - - foreach ($renameCandidates as $candidateColumns) { - if (count($candidateColumns) !== 1) { - continue; - } - - [$removedColumn, $addedColumn] = $candidateColumns[0]; - $removedColumnName = strtolower($removedColumn->getName()); - $addedColumnName = strtolower($addedColumn->getName()); - - if (isset($tableDifferences->renamedColumns[$removedColumnName])) { - continue; - } - - $tableDifferences->renamedColumns[$removedColumnName] = $addedColumn; - unset( - $tableDifferences->addedColumns[$addedColumnName], - $tableDifferences->removedColumns[$removedColumnName] - ); - } - } - - /** - * Try to find indexes that only changed their name, rename operations maybe cheaper than add/drop - * however ambiguities between different possibilities should not lead to renaming at all. - * - * @return void - */ - private function detectIndexRenamings(TableDiff $tableDifferences) - { - $renameCandidates = []; - - // Gather possible rename candidates by comparing each added and removed index based on semantics. - foreach ($tableDifferences->addedIndexes as $addedIndexName => $addedIndex) { - foreach ($tableDifferences->removedIndexes as $removedIndex) { - if ($this->diffIndex($addedIndex, $removedIndex)) { - continue; - } - - $renameCandidates[$addedIndex->getName()][] = [$removedIndex, $addedIndex, $addedIndexName]; - } - } - - foreach ($renameCandidates as $candidateIndexes) { - // If the current rename candidate contains exactly one semantically equal index, - // we can safely rename it. - // Otherwise it is unclear if a rename action is really intended, - // therefore we let those ambiguous indexes be added/dropped. - if (count($candidateIndexes) !== 1) { - continue; - } - - [$removedIndex, $addedIndex] = $candidateIndexes[0]; - - $removedIndexName = strtolower($removedIndex->getName()); - $addedIndexName = strtolower($addedIndex->getName()); - - if (isset($tableDifferences->renamedIndexes[$removedIndexName])) { - continue; - } - - $tableDifferences->renamedIndexes[$removedIndexName] = $addedIndex; - unset( - $tableDifferences->addedIndexes[$addedIndexName], - $tableDifferences->removedIndexes[$removedIndexName] - ); - } - } - - /** - * @return bool - */ - public function diffForeignKey(ForeignKeyConstraint $key1, ForeignKeyConstraint $key2) - { - if (array_map('strtolower', $key1->getUnquotedLocalColumns()) !== array_map('strtolower', $key2->getUnquotedLocalColumns())) { - return true; - } - - if (array_map('strtolower', $key1->getUnquotedForeignColumns()) !== array_map('strtolower', $key2->getUnquotedForeignColumns())) { - return true; - } - - if ($key1->getUnqualifiedForeignTableName() !== $key2->getUnqualifiedForeignTableName()) { - return true; - } - - if ($key1->onUpdate() !== $key2->onUpdate()) { - return true; - } - - return $key1->onDelete() !== $key2->onDelete(); - } - - /** - * Returns the difference between the fields $field1 and $field2. - * - * If there are differences this method returns $field2, otherwise the - * boolean false. - * - * @return string[] - */ - public function diffColumn(Column $column1, Column $column2) - { - $properties1 = $column1->toArray(); - $properties2 = $column2->toArray(); - - $changedProperties = []; - - if (get_class($properties1['type']) !== get_class($properties2['type'])) { - $changedProperties[] = 'type'; - } - - foreach (['notnull', 'unsigned', 'autoincrement'] as $property) { - if ($properties1[$property] === $properties2[$property]) { - continue; - } - - $changedProperties[] = $property; - } - - // This is a very nasty hack to make comparator work with the legacy json_array type, which should be killed in v3 - if ($this->isALegacyJsonComparison($properties1['type'], $properties2['type'])) { - array_shift($changedProperties); - - $changedProperties[] = 'comment'; - } - - // Null values need to be checked additionally as they tell whether to create or drop a default value. - // null != 0, null != false, null != '' etc. This affects platform's table alteration SQL generation. - if (($properties1['default'] === null) !== ($properties2['default'] === null) - || $properties1['default'] != $properties2['default']) { - $changedProperties[] = 'default'; - } - - if (($properties1['type'] instanceof Types\StringType && ! $properties1['type'] instanceof Types\GuidType) || - $properties1['type'] instanceof Types\BinaryType - ) { - // check if value of length is set at all, default value assumed otherwise. - $length1 = $properties1['length'] ?: 255; - $length2 = $properties2['length'] ?: 255; - if ($length1 !== $length2) { - $changedProperties[] = 'length'; - } - - if ($properties1['fixed'] !== $properties2['fixed']) { - $changedProperties[] = 'fixed'; - } - } elseif ($properties1['type'] instanceof Types\DecimalType) { - if (($properties1['precision'] ?: 10) !== ($properties2['precision'] ?: 10)) { - $changedProperties[] = 'precision'; - } - if ($properties1['scale'] !== $properties2['scale']) { - $changedProperties[] = 'scale'; - } - } - - // A null value and an empty string are actually equal for a comment so they should not trigger a change. - if ($properties1['comment'] !== $properties2['comment'] && - ! ($properties1['comment'] === null && $properties2['comment'] === '') && - ! ($properties2['comment'] === null && $properties1['comment'] === '') - ) { - $changedProperties[] = 'comment'; - } - - $customOptions1 = $column1->getCustomSchemaOptions(); - $customOptions2 = $column2->getCustomSchemaOptions(); - - foreach (array_merge(array_keys($customOptions1), array_keys($customOptions2)) as $key) { - if (! array_key_exists($key, $properties1) || ! array_key_exists($key, $properties2)) { - $changedProperties[] = $key; - } elseif ($properties1[$key] !== $properties2[$key]) { - $changedProperties[] = $key; - } - } - - $platformOptions1 = $column1->getPlatformOptions(); - $platformOptions2 = $column2->getPlatformOptions(); - - foreach (array_keys(array_intersect_key($platformOptions1, $platformOptions2)) as $key) { - if ($properties1[$key] === $properties2[$key]) { - continue; - } - - $changedProperties[] = $key; - } - - return array_unique($changedProperties); - } - - /** - * TODO: kill with fire on v3.0 - * - * @deprecated - */ - private function isALegacyJsonComparison(Types\Type $one, Types\Type $other) : bool - { - if (! $one instanceof Types\JsonType || ! $other instanceof Types\JsonType) { - return false; - } - - return ( ! $one instanceof Types\JsonArrayType && $other instanceof Types\JsonArrayType) - || ( ! $other instanceof Types\JsonArrayType && $one instanceof Types\JsonArrayType); - } - - /** - * 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. - * - * @return bool - */ - public function diffIndex(Index $index1, Index $index2) - { - return ! ($index1->isFullfilledBy($index2) && $index2->isFullfilledBy($index1)); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Constraint.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Constraint.php deleted file mode 100644 index 65e239e..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Constraint.php +++ /dev/null @@ -1,43 +0,0 @@ -_platform->getListTablesSQL(); - $sql .= ' AND CREATOR = UPPER(' . $this->_conn->quote($this->_conn->getUsername()) . ')'; - - $tables = $this->_conn->fetchAll($sql); - - return $this->filterAssetNames($this->_getPortableTablesList($tables)); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableColumnDefinition($tableColumn) - { - $tableColumn = array_change_key_case($tableColumn, CASE_LOWER); - - $length = null; - $fixed = null; - $scale = false; - $precision = false; - - $default = null; - - if ($tableColumn['default'] !== null && $tableColumn['default'] !== 'NULL') { - $default = $tableColumn['default']; - - if (preg_match('/^\'(.*)\'$/s', $default, $matches)) { - $default = str_replace("''", "'", $matches[1]); - } - } - - $type = $this->_platform->getDoctrineTypeMapping($tableColumn['typename']); - - if (isset($tableColumn['comment'])) { - $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); - $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); - } - - 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 = [ - 'length' => $length, - 'unsigned' => false, - 'fixed' => (bool) $fixed, - 'default' => $default, - 'autoincrement' => (bool) $tableColumn['autoincrement'], - 'notnull' => (bool) ($tableColumn['nulls'] === 'N'), - 'scale' => null, - 'precision' => null, - 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== '' - ? $tableColumn['comment'] - : null, - 'platformOptions' => [], - ]; - - if ($scale !== null && $precision !== null) { - $options['scale'] = $scale; - $options['precision'] = $precision; - } - - return new Column($tableColumn['colname'], Type::getType($type), $options); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTablesList($tables) - { - $tableNames = []; - foreach ($tables as $tableRow) { - $tableRow = array_change_key_case($tableRow, CASE_LOWER); - $tableNames[] = $tableRow['name']; - } - - return $tableNames; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null) - { - foreach ($tableIndexRows as &$tableIndexRow) { - $tableIndexRow = array_change_key_case($tableIndexRow, CASE_LOWER); - $tableIndexRow['primary'] = (bool) $tableIndexRow['primary']; - } - - return parent::_getPortableTableIndexesList($tableIndexRows, $tableName); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableForeignKeyDefinition($tableForeignKey) - { - return new ForeignKeyConstraint( - $tableForeignKey['local_columns'], - $tableForeignKey['foreign_table'], - $tableForeignKey['foreign_columns'], - $tableForeignKey['name'], - $tableForeignKey['options'] - ); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableForeignKeysList($tableForeignKeys) - { - $foreignKeys = []; - - foreach ($tableForeignKeys as $tableForeignKey) { - $tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER); - - if (! isset($foreignKeys[$tableForeignKey['index_name']])) { - $foreignKeys[$tableForeignKey['index_name']] = [ - 'local_columns' => [$tableForeignKey['local_column']], - 'foreign_table' => $tableForeignKey['foreign_table'], - 'foreign_columns' => [$tableForeignKey['foreign_column']], - 'name' => $tableForeignKey['index_name'], - 'options' => [ - 'onUpdate' => $tableForeignKey['on_update'], - 'onDelete' => $tableForeignKey['on_delete'], - ], - ]; - } else { - $foreignKeys[$tableForeignKey['index_name']]['local_columns'][] = $tableForeignKey['local_column']; - $foreignKeys[$tableForeignKey['index_name']]['foreign_columns'][] = $tableForeignKey['foreign_column']; - } - } - - return parent::_getPortableTableForeignKeysList($foreignKeys); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableForeignKeyRuleDef($def) - { - if ($def === 'C') { - return 'CASCADE'; - } - - if ($def === 'N') { - return 'SET NULL'; - } - - return null; - } - - /** - * {@inheritdoc} - */ - 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); - } - - public function listTableDetails($tableName) : Table - { - $table = parent::listTableDetails($tableName); - - /** @var DB2Platform $platform */ - $platform = $this->_platform; - $sql = $platform->getListTableCommentsSQL($tableName); - - $tableOptions = $this->_conn->fetchAssoc($sql); - $table->addOption('comment', $tableOptions['REMARKS']); - - return $table; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DrizzleSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DrizzleSchemaManager.php deleted file mode 100644 index c334db2..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/DrizzleSchemaManager.php +++ /dev/null @@ -1,103 +0,0 @@ -_platform->getDoctrineTypeMapping($dbType); - $type = $this->extractDoctrineTypeFromComment($tableColumn['COLUMN_COMMENT'], $type); - $tableColumn['COLUMN_COMMENT'] = $this->removeDoctrineTypeFromComment($tableColumn['COLUMN_COMMENT'], $type); - - $options = [ - 'notnull' => ! (bool) $tableColumn['IS_NULLABLE'], - 'length' => (int) $tableColumn['CHARACTER_MAXIMUM_LENGTH'], - 'default' => $tableColumn['COLUMN_DEFAULT'] ?? null, - 'autoincrement' => (bool) $tableColumn['IS_AUTO_INCREMENT'], - 'scale' => (int) $tableColumn['NUMERIC_SCALE'], - 'precision' => (int) $tableColumn['NUMERIC_PRECISION'], - 'comment' => isset($tableColumn['COLUMN_COMMENT']) && $tableColumn['COLUMN_COMMENT'] !== '' - ? $tableColumn['COLUMN_COMMENT'] - : null, - ]; - - $column = new Column($tableColumn['COLUMN_NAME'], Type::getType($type), $options); - - if (! empty($tableColumn['COLLATION_NAME'])) { - $column->setPlatformOption('collation', $tableColumn['COLLATION_NAME']); - } - - return $column; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableDatabaseDefinition($database) - { - return $database['SCHEMA_NAME']; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableDefinition($table) - { - return $table['TABLE_NAME']; - } - - /** - * {@inheritdoc} - */ - public function _getPortableTableForeignKeyDefinition($tableForeignKey) - { - $columns = []; - foreach (explode(',', $tableForeignKey['CONSTRAINT_COLUMNS']) as $value) { - $columns[] = trim($value, ' `'); - } - - $refColumns = []; - foreach (explode(',', $tableForeignKey['REFERENCED_TABLE_COLUMNS']) as $value) { - $refColumns[] = trim($value, ' `'); - } - - return new ForeignKeyConstraint( - $columns, - $tableForeignKey['REFERENCED_TABLE_NAME'], - $refColumns, - $tableForeignKey['CONSTRAINT_NAME'], - [ - 'onUpdate' => $tableForeignKey['UPDATE_RULE'], - 'onDelete' => $tableForeignKey['DELETE_RULE'], - ] - ); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableIndexesList($tableIndexes, $tableName = null) - { - $indexes = []; - foreach ($tableIndexes as $k) { - $k['primary'] = (bool) $k['primary']; - $indexes[] = $k; - } - - return parent::_getPortableTableIndexesList($indexes, $tableName); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php deleted file mode 100644 index 3c6585e..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/ForeignKeyConstraint.php +++ /dev/null @@ -1,393 +0,0 @@ - Identifier) - * - * @var Identifier[] - */ - protected $_localColumnNames; - - /** - * Table or asset identifier instance of the referenced table name the foreign key constraint is associated with. - * - * @var Table|Identifier - */ - protected $_foreignTableName; - - /** - * Asset identifier instances of the referenced table column names the foreign key constraint is associated with. - * array($columnName => Identifier) - * - * @var Identifier[] - */ - protected $_foreignColumnNames; - - /** - * Options associated with the foreign key constraint. - * - * @var mixed[] - */ - protected $_options; - - /** - * Initializes the foreign key constraint. - * - * @param string[] $localColumnNames Names of the referencing table columns. - * @param Table|string $foreignTableName Referenced table. - * @param string[] $foreignColumnNames Names of the referenced table columns. - * @param string|null $name Name of the foreign key constraint. - * @param mixed[] $options Options associated with the foreign key constraint. - */ - public function __construct(array $localColumnNames, $foreignTableName, array $foreignColumnNames, $name = null, array $options = []) - { - if ($name !== null) { - $this->_setName($name); - } - - $this->_localColumnNames = $this->createIdentifierMap($localColumnNames); - - if ($foreignTableName instanceof Table) { - $this->_foreignTableName = $foreignTableName; - } else { - $this->_foreignTableName = new Identifier($foreignTableName); - } - - $this->_foreignColumnNames = $this->createIdentifierMap($foreignColumnNames); - $this->_options = $options; - } - - /** - * @param string[] $names - * - * @return Identifier[] - */ - private function createIdentifierMap(array $names) : array - { - $identifiers = []; - - foreach ($names as $name) { - $identifiers[$name] = new Identifier($name); - } - - return $identifiers; - } - - /** - * Returns the name of the referencing table - * the foreign key constraint is associated with. - * - * @return string - */ - public function getLocalTableName() - { - return $this->_localTable->getName(); - } - - /** - * Sets the Table instance of the referencing table - * the foreign key constraint is associated with. - * - * @param Table $table Instance of the referencing table. - * - * @return void - */ - public function setLocalTable(Table $table) - { - $this->_localTable = $table; - } - - /** - * @return Table - */ - public function getLocalTable() - { - return $this->_localTable; - } - - /** - * Returns the names of the referencing table columns - * the foreign key constraint is associated with. - * - * @return string[] - */ - public function getLocalColumns() - { - return array_keys($this->_localColumnNames); - } - - /** - * Returns the quoted representation of the referencing table column names - * the foreign key constraint is associated with. - * - * But only if they were defined with one or the referencing table column name - * is a keyword reserved by the platform. - * Otherwise the plain unquoted value as inserted is returned. - * - * @param AbstractPlatform $platform The platform to use for quotation. - * - * @return string[] - */ - public function getQuotedLocalColumns(AbstractPlatform $platform) - { - $columns = []; - - foreach ($this->_localColumnNames as $column) { - $columns[] = $column->getQuotedName($platform); - } - - return $columns; - } - - /** - * Returns unquoted representation of local table column names for comparison with other FK - * - * @return string[] - */ - public function getUnquotedLocalColumns() - { - return array_map([$this, 'trimQuotes'], $this->getLocalColumns()); - } - - /** - * Returns unquoted representation of foreign table column names for comparison with other FK - * - * @return string[] - */ - public function getUnquotedForeignColumns() - { - return array_map([$this, 'trimQuotes'], $this->getForeignColumns()); - } - - /** - * {@inheritdoc} - * - * @see getLocalColumns - */ - public function getColumns() - { - return $this->getLocalColumns(); - } - - /** - * Returns the quoted representation of the referencing table column names - * the foreign key constraint is associated with. - * - * But only if they were defined with one or the referencing table column name - * is a keyword reserved by the platform. - * Otherwise the plain unquoted value as inserted is returned. - * - * @see getQuotedLocalColumns - * - * @param AbstractPlatform $platform The platform to use for quotation. - * - * @return string[] - */ - public function getQuotedColumns(AbstractPlatform $platform) - { - return $this->getQuotedLocalColumns($platform); - } - - /** - * Returns the name of the referenced table - * the foreign key constraint is associated with. - * - * @return string - */ - public function getForeignTableName() - { - return $this->_foreignTableName->getName(); - } - - /** - * Returns the non-schema qualified foreign table name. - * - * @return string - */ - public function getUnqualifiedForeignTableName() - { - $name = $this->_foreignTableName->getName(); - $position = strrpos($name, '.'); - - if ($position !== false) { - $name = substr($name, $position); - } - - return strtolower($name); - } - - /** - * Returns the quoted representation of the referenced table name - * the foreign key constraint is associated with. - * - * But only if it was defined with one or the referenced table name - * is a keyword reserved by the platform. - * Otherwise the plain unquoted value as inserted is returned. - * - * @param AbstractPlatform $platform The platform to use for quotation. - * - * @return string - */ - public function getQuotedForeignTableName(AbstractPlatform $platform) - { - return $this->_foreignTableName->getQuotedName($platform); - } - - /** - * Returns the names of the referenced table columns - * the foreign key constraint is associated with. - * - * @return string[] - */ - public function getForeignColumns() - { - return array_keys($this->_foreignColumnNames); - } - - /** - * Returns the quoted representation of the referenced table column names - * the foreign key constraint is associated with. - * - * But only if they were defined with one or the referenced table column name - * is a keyword reserved by the platform. - * Otherwise the plain unquoted value as inserted is returned. - * - * @param AbstractPlatform $platform The platform to use for quotation. - * - * @return string[] - */ - public function getQuotedForeignColumns(AbstractPlatform $platform) - { - $columns = []; - - foreach ($this->_foreignColumnNames as $column) { - $columns[] = $column->getQuotedName($platform); - } - - return $columns; - } - - /** - * Returns whether or not a given option - * is associated with the foreign key constraint. - * - * @param string $name Name of the option to check. - * - * @return bool - */ - public function hasOption($name) - { - return isset($this->_options[$name]); - } - - /** - * Returns an option associated with the foreign key constraint. - * - * @param string $name Name of the option the foreign key constraint is associated with. - * - * @return mixed - */ - public function getOption($name) - { - return $this->_options[$name]; - } - - /** - * Returns the options associated with the foreign key constraint. - * - * @return mixed[] - */ - public function getOptions() - { - return $this->_options; - } - - /** - * Returns the referential action for UPDATE operations - * on the referenced table the foreign key constraint is associated with. - * - * @return string|null - */ - public function onUpdate() - { - return $this->onEvent('onUpdate'); - } - - /** - * Returns the referential action for DELETE operations - * on the referenced table the foreign key constraint is associated with. - * - * @return string|null - */ - public function onDelete() - { - return $this->onEvent('onDelete'); - } - - /** - * Returns the referential action for a given database operation - * on the referenced table the foreign key constraint is associated with. - * - * @param string $event Name of the database operation/event to return the referential action for. - * - * @return string|null - */ - private function onEvent($event) - { - if (isset($this->_options[$event])) { - $onEvent = strtoupper($this->_options[$event]); - - if (! in_array($onEvent, ['NO ACTION', 'RESTRICT'])) { - return $onEvent; - } - } - - return false; - } - - /** - * Checks whether this foreign key constraint intersects the given index columns. - * - * Returns `true` if at least one of this foreign key's local columns - * matches one of the given index's columns, `false` otherwise. - * - * @param Index $index The index to be checked against. - * - * @return bool - */ - public function intersectsIndexColumns(Index $index) - { - foreach ($index->getColumns() as $indexColumn) { - foreach ($this->_localColumnNames as $localColumn) { - if (strtolower($indexColumn) === strtolower($localColumn->getName())) { - return true; - } - } - } - - return false; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Identifier.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Identifier.php deleted file mode 100644 index f34465e..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Identifier.php +++ /dev/null @@ -1,27 +0,0 @@ -_setName($identifier); - - if (! $quote || $this->_quoted) { - return; - } - - $this->_setName('"' . $this->getName() . '"'); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php deleted file mode 100644 index 7a31c78..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Index.php +++ /dev/null @@ -1,359 +0,0 @@ - Identifier) - * - * @var Identifier[] - */ - protected $_columns = []; - - /** @var bool */ - protected $_isUnique = false; - - /** @var bool */ - protected $_isPrimary = false; - - /** - * Platform specific flags for indexes. - * array($flagName => true) - * - * @var true[] - */ - protected $_flags = []; - - /** - * Platform specific options - * - * @todo $_flags should eventually be refactored into options - * @var mixed[] - */ - private $options = []; - - /** - * @param string $indexName - * @param string[] $columns - * @param bool $isUnique - * @param bool $isPrimary - * @param string[] $flags - * @param mixed[] $options - */ - public function __construct($indexName, array $columns, $isUnique = false, $isPrimary = false, array $flags = [], array $options = []) - { - $isUnique = $isUnique || $isPrimary; - - $this->_setName($indexName); - $this->_isUnique = $isUnique; - $this->_isPrimary = $isPrimary; - $this->options = $options; - - foreach ($columns as $column) { - $this->_addColumn($column); - } - foreach ($flags as $flag) { - $this->addFlag($flag); - } - } - - /** - * @param string $column - * - * @return void - * - * @throws InvalidArgumentException - */ - protected function _addColumn($column) - { - if (! is_string($column)) { - throw new InvalidArgumentException('Expecting a string as Index Column'); - } - - $this->_columns[$column] = new Identifier($column); - } - - /** - * {@inheritdoc} - */ - public function getColumns() - { - return array_keys($this->_columns); - } - - /** - * {@inheritdoc} - */ - public function getQuotedColumns(AbstractPlatform $platform) - { - $subParts = $platform->supportsColumnLengthIndexes() && $this->hasOption('lengths') - ? $this->getOption('lengths') : []; - - $columns = []; - - foreach ($this->_columns as $column) { - $length = array_shift($subParts); - - $quotedColumn = $column->getQuotedName($platform); - - if ($length !== null) { - $quotedColumn .= '(' . $length . ')'; - } - - $columns[] = $quotedColumn; - } - - return $columns; - } - - /** - * @return string[] - */ - public function getUnquotedColumns() - { - return array_map([$this, 'trimQuotes'], $this->getColumns()); - } - - /** - * Is the index neither unique nor primary key? - * - * @return bool - */ - public function isSimpleIndex() - { - return ! $this->_isPrimary && ! $this->_isUnique; - } - - /** - * @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 = $this->trimQuotes(strtolower($columnName)); - $indexColumns = array_map('strtolower', $this->getUnquotedColumns()); - - return array_search($columnName, $indexColumns) === $pos; - } - - /** - * Checks if this index exactly spans the given column names in the correct order. - * - * @param string[] $columnNames - * - * @return bool - */ - public function spansColumns(array $columnNames) - { - $columns = $this->getColumns(); - $numberOfColumns = count($columns); - $sameColumns = true; - - for ($i = 0; $i < $numberOfColumns; $i++) { - if (isset($columnNames[$i]) && $this->trimQuotes(strtolower($columns[$i])) === $this->trimQuotes(strtolower($columnNames[$i]))) { - continue; - } - - $sameColumns = false; - } - - return $sameColumns; - } - - /** - * Checks if the other index already fulfills all the indexing and constraint needs of the current one. - * - * @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->samePartialIndex($other)) { - return false; - } - - if (! $this->hasSameColumnLengths($other)) { - return false; - } - - if (! $this->isUnique() && ! $this->isPrimary()) { - // this is a special case: If the current key is neither primary or unique, any unique 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 fulfill the requirements of just an - // index that has no constraints. - return true; - } - - if ($other->isPrimary() !== $this->isPrimary()) { - return false; - } - - return $other->isUnique() === $this->isUnique(); - } - - return false; - } - - /** - * Detects if the other index is a non-unique, non primary index that can be overwritten by this one. - * - * @return bool - */ - public function overrules(Index $other) - { - if ($other->isPrimary()) { - return false; - } - - if ($this->isSimpleIndex() && $other->isUnique()) { - return false; - } - - return $this->spansColumns($other->getColumns()) && ($this->isPrimary() || $this->isUnique()) && $this->samePartialIndex($other); - } - - /** - * Returns platform specific flags for indexes. - * - * @return string[] - */ - public function getFlags() - { - return array_keys($this->_flags); - } - - /** - * Adds Flag for an index that translates to platform specific handling. - * - * @param string $flag - * - * @return Index - * - * @example $index->addFlag('CLUSTERED') - */ - public function addFlag($flag) - { - $this->_flags[strtolower($flag)] = true; - - return $this; - } - - /** - * Does this index have a specific flag? - * - * @param string $flag - * - * @return bool - */ - public function hasFlag($flag) - { - return isset($this->_flags[strtolower($flag)]); - } - - /** - * Removes a flag. - * - * @param string $flag - * - * @return void - */ - public function removeFlag($flag) - { - unset($this->_flags[strtolower($flag)]); - } - - /** - * @param string $name - * - * @return bool - */ - public function hasOption($name) - { - return isset($this->options[strtolower($name)]); - } - - /** - * @param string $name - * - * @return mixed - */ - public function getOption($name) - { - return $this->options[strtolower($name)]; - } - - /** - * @return mixed[] - */ - public function getOptions() - { - return $this->options; - } - - /** - * Return whether the two indexes have the same partial index - * - * @return bool - */ - private function samePartialIndex(Index $other) - { - if ($this->hasOption('where') && $other->hasOption('where') && $this->getOption('where') === $other->getOption('where')) { - return true; - } - - return ! $this->hasOption('where') && ! $other->hasOption('where'); - } - - /** - * Returns whether the index has the same column lengths as the other - */ - private function hasSameColumnLengths(self $other) : bool - { - $filter = static function (?int $length) : bool { - return $length !== null; - }; - - return array_filter($this->options['lengths'] ?? [], $filter) - === array_filter($other->options['lengths'] ?? [], $filter); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php deleted file mode 100644 index 9522faf..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php +++ /dev/null @@ -1,351 +0,0 @@ - "\0", - "\\'" => "'", - '\\"' => '"', - '\\b' => "\b", - '\\n' => "\n", - '\\r' => "\r", - '\\t' => "\t", - '\\Z' => "\x1a", - '\\\\' => '\\', - '\\%' => '%', - '\\_' => '_', - - // Internally, MariaDB escapes single quotes using the standard syntax - "''" => "'", - ]; - - /** - * {@inheritdoc} - */ - protected function _getPortableViewDefinition($view) - { - return new View($view['TABLE_NAME'], $view['VIEW_DEFINITION']); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableDefinition($table) - { - return array_shift($table); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableUserDefinition($user) - { - return [ - 'user' => $user['User'], - 'password' => $user['Password'], - ]; - } - - /** - * {@inheritdoc} - */ - 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; - } - if (strpos($v['index_type'], 'FULLTEXT') !== false) { - $v['flags'] = ['FULLTEXT']; - } elseif (strpos($v['index_type'], 'SPATIAL') !== false) { - $v['flags'] = ['SPATIAL']; - } - $v['length'] = isset($v['sub_part']) ? (int) $v['sub_part'] : null; - - $tableIndexes[$k] = $v; - } - - return parent::_getPortableTableIndexesList($tableIndexes, $tableName); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableDatabaseDefinition($database) - { - return $database['Database']; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableColumnDefinition($tableColumn) - { - $tableColumn = array_change_key_case($tableColumn, CASE_LOWER); - - $dbType = strtolower($tableColumn['type']); - $dbType = strtok($dbType, '(), '); - assert(is_string($dbType)); - - $length = $tableColumn['length'] ?? strtok('(), '); - - $fixed = null; - - if (! isset($tableColumn['name'])) { - $tableColumn['name'] = ''; - } - - $scale = null; - $precision = null; - - $type = $this->_platform->getDoctrineTypeMapping($dbType); - - // In cases where not connected to a database DESCRIBE $table does not return 'Comment' - if (isset($tableColumn['comment'])) { - $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); - $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); - } - - switch ($dbType) { - case 'char': - case 'binary': - $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 'tinytext': - $length = MySqlPlatform::LENGTH_LIMIT_TINYTEXT; - break; - case 'text': - $length = MySqlPlatform::LENGTH_LIMIT_TEXT; - break; - case 'mediumtext': - $length = MySqlPlatform::LENGTH_LIMIT_MEDIUMTEXT; - break; - case 'tinyblob': - $length = MySqlPlatform::LENGTH_LIMIT_TINYBLOB; - break; - case 'blob': - $length = MySqlPlatform::LENGTH_LIMIT_BLOB; - break; - case 'mediumblob': - $length = MySqlPlatform::LENGTH_LIMIT_MEDIUMBLOB; - break; - case 'tinyint': - case 'smallint': - case 'mediumint': - case 'int': - case 'integer': - case 'bigint': - case 'year': - $length = null; - break; - } - - if ($this->_platform instanceof MariaDb1027Platform) { - $columnDefault = $this->getMariaDb1027ColumnDefault($this->_platform, $tableColumn['default']); - } else { - $columnDefault = $tableColumn['default']; - } - - $options = [ - 'length' => $length !== null ? (int) $length : null, - 'unsigned' => strpos($tableColumn['type'], 'unsigned') !== false, - 'fixed' => (bool) $fixed, - 'default' => $columnDefault, - 'notnull' => $tableColumn['null'] !== 'YES', - 'scale' => null, - 'precision' => null, - 'autoincrement' => strpos($tableColumn['extra'], 'auto_increment') !== false, - 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== '' - ? $tableColumn['comment'] - : null, - ]; - - if ($scale !== null && $precision !== null) { - $options['scale'] = (int) $scale; - $options['precision'] = (int) $precision; - } - - $column = new Column($tableColumn['field'], Type::getType($type), $options); - - if (isset($tableColumn['characterset'])) { - $column->setPlatformOption('charset', $tableColumn['characterset']); - } - if (isset($tableColumn['collation'])) { - $column->setPlatformOption('collation', $tableColumn['collation']); - } - - return $column; - } - - /** - * Return Doctrine/Mysql-compatible column default values for MariaDB 10.2.7+ servers. - * - * - Since MariaDb 10.2.7 column defaults stored in information_schema are now quoted - * to distinguish them from expressions (see MDEV-10134). - * - CURRENT_TIMESTAMP, CURRENT_TIME, CURRENT_DATE are stored in information_schema - * as current_timestamp(), currdate(), currtime() - * - Quoted 'NULL' is not enforced by Maria, it is technically possible to have - * null in some circumstances (see https://jira.mariadb.org/browse/MDEV-14053) - * - \' is always stored as '' in information_schema (normalized) - * - * @link https://mariadb.com/kb/en/library/information-schema-columns-table/ - * @link https://jira.mariadb.org/browse/MDEV-13132 - * - * @param string|null $columnDefault default value as stored in information_schema for MariaDB >= 10.2.7 - */ - private function getMariaDb1027ColumnDefault(MariaDb1027Platform $platform, ?string $columnDefault) : ?string - { - if ($columnDefault === 'NULL' || $columnDefault === null) { - return null; - } - - if (preg_match('/^\'(.*)\'$/', $columnDefault, $matches)) { - return strtr($matches[1], self::MARIADB_ESCAPE_SEQUENCES); - } - - switch ($columnDefault) { - case 'current_timestamp()': - return $platform->getCurrentTimestampSQL(); - case 'curdate()': - return $platform->getCurrentDateSQL(); - case 'curtime()': - return $platform->getCurrentTimeSQL(); - } - - return $columnDefault; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableForeignKeysList($tableForeignKeys) - { - $list = []; - foreach ($tableForeignKeys as $value) { - $value = array_change_key_case($value, CASE_LOWER); - if (! isset($list[$value['constraint_name']])) { - if (! isset($value['delete_rule']) || $value['delete_rule'] === 'RESTRICT') { - $value['delete_rule'] = null; - } - if (! isset($value['update_rule']) || $value['update_rule'] === 'RESTRICT') { - $value['update_rule'] = null; - } - - $list[$value['constraint_name']] = [ - 'name' => $value['constraint_name'], - 'local' => [], - 'foreign' => [], - 'foreignTable' => $value['referenced_table_name'], - 'onDelete' => $value['delete_rule'], - 'onUpdate' => $value['update_rule'], - ]; - } - $list[$value['constraint_name']]['local'][] = $value['column_name']; - $list[$value['constraint_name']]['foreign'][] = $value['referenced_column_name']; - } - - $result = []; - foreach ($list as $constraint) { - $result[] = new ForeignKeyConstraint( - array_values($constraint['local']), - $constraint['foreignTable'], - array_values($constraint['foreign']), - $constraint['name'], - [ - 'onDelete' => $constraint['onDelete'], - 'onUpdate' => $constraint['onUpdate'], - ] - ); - } - - return $result; - } - - public function listTableDetails($tableName) - { - $table = parent::listTableDetails($tableName); - - /** @var MySqlPlatform $platform */ - $platform = $this->_platform; - $sql = $platform->getListTableMetadataSQL($tableName); - - $tableOptions = $this->_conn->fetchAssoc($sql); - - if ($tableOptions === false) { - return $table; - } - - $table->addOption('engine', $tableOptions['ENGINE']); - - if ($tableOptions['TABLE_COLLATION'] !== null) { - $table->addOption('collation', $tableOptions['TABLE_COLLATION']); - } - - if ($tableOptions['AUTO_INCREMENT'] !== null) { - $table->addOption('autoincrement', $tableOptions['AUTO_INCREMENT']); - } - - $table->addOption('comment', $tableOptions['TABLE_COMMENT']); - $table->addOption('create_options', $this->parseCreateOptions($tableOptions['CREATE_OPTIONS'])); - - return $table; - } - - /** - * @return string[]|true[] - */ - private function parseCreateOptions(?string $string) : array - { - $options = []; - - if ($string === null || $string === '') { - return $options; - } - - foreach (explode(' ', $string) as $pair) { - $parts = explode('=', $pair, 2); - - $options[$parts[0]] = $parts[1] ?? true; - } - - return $options; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php deleted file mode 100644 index afe610d..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/OracleSchemaManager.php +++ /dev/null @@ -1,406 +0,0 @@ -getPrevious(); - assert($exception instanceof Throwable); - - if (! $exception instanceof DriverException) { - throw $exception; - } - - // If we have a error code 1940 (ORA-01940), the drop database operation failed - // because of active connections on the database. - // To force dropping the database, we first have to close all active connections - // on that database and issue the drop database operation again. - if ($exception->getErrorCode() !== 1940) { - throw $exception; - } - - $this->killUserSessions($database); - - parent::dropDatabase($database); - } - } - - /** - * {@inheritdoc} - */ - protected function _getPortableViewDefinition($view) - { - $view = array_change_key_case($view, CASE_LOWER); - - return new View($this->getQuotedIdentifierName($view['view_name']), $view['text']); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableUserDefinition($user) - { - $user = array_change_key_case($user, CASE_LOWER); - - return [ - 'user' => $user['username'], - ]; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableDefinition($table) - { - $table = array_change_key_case($table, CASE_LOWER); - - return $this->getQuotedIdentifierName($table['table_name']); - } - - /** - * {@inheritdoc} - * - * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html - */ - protected function _getPortableTableIndexesList($tableIndexes, $tableName = null) - { - $indexBuffer = []; - foreach ($tableIndexes as $tableIndex) { - $tableIndex = array_change_key_case($tableIndex, CASE_LOWER); - - $keyName = strtolower($tableIndex['name']); - $buffer = []; - - 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']; - } - $buffer['key_name'] = $keyName; - $buffer['column_name'] = $this->getQuotedIdentifierName($tableIndex['column_name']); - $indexBuffer[] = $buffer; - } - - return parent::_getPortableTableIndexesList($indexBuffer, $tableName); - } - - /** - * {@inheritdoc} - */ - 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'; - } - } - - $unsigned = $fixed = $precision = $scale = $length = null; - - if (! isset($tableColumn['column_name'])) { - $tableColumn['column_name'] = ''; - } - - // Default values returned from database sometimes have trailing spaces. - $tableColumn['data_default'] = trim($tableColumn['data_default']); - - if ($tableColumn['data_default'] === '' || $tableColumn['data_default'] === 'NULL') { - $tableColumn['data_default'] = null; - } - - if ($tableColumn['data_default'] !== null) { - // Default values returned from database are represented as literal expressions - if (preg_match('/^\'(.*)\'$/s', $tableColumn['data_default'], $matches)) { - $tableColumn['data_default'] = str_replace("''", "'", $matches[1]); - } - } - - if ($tableColumn['data_precision'] !== null) { - $precision = (int) $tableColumn['data_precision']; - } - - if ($tableColumn['data_scale'] !== null) { - $scale = (int) $tableColumn['data_scale']; - } - - $type = $this->_platform->getDoctrineTypeMapping($dbType); - $type = $this->extractDoctrineTypeFromComment($tableColumn['comments'], $type); - $tableColumn['comments'] = $this->removeDoctrineTypeFromComment($tableColumn['comments'], $type); - - switch ($dbType) { - case 'number': - if ($precision === 20 && $scale === 0) { - $type = 'bigint'; - } elseif ($precision === 5 && $scale === 0) { - $type = 'smallint'; - } elseif ($precision === 1 && $scale === 0) { - $type = 'boolean'; - } elseif ($scale > 0) { - $type = 'decimal'; - } - - break; - case 'varchar': - case 'varchar2': - case 'nvarchar2': - $length = $tableColumn['char_length']; - $fixed = false; - break; - case 'char': - case 'nchar': - $length = $tableColumn['char_length']; - $fixed = true; - break; - } - - $options = [ - 'notnull' => (bool) ($tableColumn['nullable'] === 'N'), - 'fixed' => (bool) $fixed, - 'unsigned' => (bool) $unsigned, - 'default' => $tableColumn['data_default'], - 'length' => $length, - 'precision' => $precision, - 'scale' => $scale, - 'comment' => isset($tableColumn['comments']) && $tableColumn['comments'] !== '' - ? $tableColumn['comments'] - : null, - ]; - - return new Column($this->getQuotedIdentifierName($tableColumn['column_name']), Type::getType($type), $options); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableForeignKeysList($tableForeignKeys) - { - $list = []; - foreach ($tableForeignKeys as $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']] = [ - 'name' => $this->getQuotedIdentifierName($value['constraint_name']), - 'local' => [], - 'foreign' => [], - 'foreignTable' => $value['references_table'], - 'onDelete' => $value['delete_rule'], - ]; - } - - $localColumn = $this->getQuotedIdentifierName($value['local_column']); - $foreignColumn = $this->getQuotedIdentifierName($value['foreign_column']); - - $list[$value['constraint_name']]['local'][$value['position']] = $localColumn; - $list[$value['constraint_name']]['foreign'][$value['position']] = $foreignColumn; - } - - $result = []; - foreach ($list as $constraint) { - $result[] = new ForeignKeyConstraint( - array_values($constraint['local']), - $this->getQuotedIdentifierName($constraint['foreignTable']), - array_values($constraint['foreign']), - $this->getQuotedIdentifierName($constraint['name']), - ['onDelete' => $constraint['onDelete']] - ); - } - - return $result; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableSequenceDefinition($sequence) - { - $sequence = array_change_key_case($sequence, CASE_LOWER); - - return new Sequence( - $this->getQuotedIdentifierName($sequence['sequence_name']), - (int) $sequence['increment_by'], - (int) $sequence['min_value'] - ); - } - - /** - * {@inheritdoc} - * - * @deprecated - */ - protected function _getPortableFunctionDefinition($function) - { - $function = array_change_key_case($function, CASE_LOWER); - - return $function['name']; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableDatabaseDefinition($database) - { - $database = array_change_key_case($database, CASE_LOWER); - - return $database['username']; - } - - /** - * {@inheritdoc} - * - * Calling this method without an argument or by passing NULL is deprecated. - */ - public function createDatabase($database = null) - { - if ($database === null) { - $database = $this->_conn->getDatabase(); - } - - $params = $this->_conn->getParams(); - $username = $database; - $password = $params['password']; - - $query = 'CREATE USER ' . $username . ' IDENTIFIED BY ' . $password; - $this->_conn->executeUpdate($query); - - $query = 'GRANT DBA TO ' . $username; - $this->_conn->executeUpdate($query); - } - - /** - * @param string $table - * - * @return bool - */ - public function dropAutoincrement($table) - { - assert($this->_platform instanceof OraclePlatform); - - $sql = $this->_platform->getDropAutoincrementSql($table); - foreach ($sql as $query) { - $this->_conn->executeUpdate($query); - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function dropTable($name) - { - $this->tryMethod('dropAutoincrement', $name); - - parent::dropTable($name); - } - - /** - * Returns the quoted representation of the given identifier name. - * - * Quotes non-uppercase identifiers explicitly to preserve case - * and thus make references to the particular identifier work. - * - * @param string $identifier The identifier to quote. - * - * @return string The quoted identifier. - */ - private function getQuotedIdentifierName($identifier) - { - if (preg_match('/[a-z]/', $identifier)) { - return $this->_platform->quoteIdentifier($identifier); - } - - return $identifier; - } - - /** - * Kills sessions connected with the given user. - * - * This is useful to force DROP USER operations which could fail because of active user sessions. - * - * @param string $user The name of the user to kill sessions for. - * - * @return void - */ - private function killUserSessions($user) - { - $sql = <<_conn->fetchAll($sql, [strtoupper($user)]); - - foreach ($activeUserSessions as $activeUserSession) { - $activeUserSession = array_change_key_case($activeUserSession, CASE_LOWER); - - $this->_execSql( - sprintf( - "ALTER SYSTEM KILL SESSION '%s, %s' IMMEDIATE", - $activeUserSession['sid'], - $activeUserSession['serial#'] - ) - ); - } - } - - public function listTableDetails($tableName) : Table - { - $table = parent::listTableDetails($tableName); - - /** @var OraclePlatform $platform */ - $platform = $this->_platform; - $sql = $platform->getListTableCommentsSQL($tableName); - - $tableOptions = $this->_conn->fetchAssoc($sql); - $table->addOption('comment', $tableOptions['COMMENTS']); - - return $table; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php deleted file mode 100644 index e9608e7..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php +++ /dev/null @@ -1,507 +0,0 @@ -_conn->executeQuery("SELECT nspname FROM pg_namespace WHERE nspname !~ '^pg_.*' AND nspname != 'information_schema'"); - - return $statement->fetchAll(FetchMode::COLUMN); - } - - /** - * Returns an array of schema search paths. - * - * This is a PostgreSQL only function. - * - * @return string[] - */ - public function getSchemaSearchPaths() - { - $params = $this->_conn->getParams(); - $schema = explode(',', $this->_conn->fetchColumn('SHOW search_path')); - - if (isset($params['user'])) { - $schema = str_replace('"$user"', $params['user'], $schema); - } - - return array_map('trim', $schema); - } - - /** - * Gets names of all existing schemas in the current users search path. - * - * This is a PostgreSQL only function. - * - * @return string[] - */ - public function getExistingSchemaSearchPaths() - { - if ($this->existingSchemaPaths === null) { - $this->determineExistingSchemaSearchPaths(); - } - - return $this->existingSchemaPaths; - } - - /** - * Sets or resets the order of the existing schemas in the current search path of the user. - * - * This is a PostgreSQL only function. - * - * @return void - */ - public function determineExistingSchemaSearchPaths() - { - $names = $this->getSchemaNames(); - $paths = $this->getSchemaSearchPaths(); - - $this->existingSchemaPaths = array_filter($paths, static function ($v) use ($names) { - return in_array($v, $names); - }); - } - - /** - * {@inheritdoc} - */ - public function dropDatabase($database) - { - try { - parent::dropDatabase($database); - } catch (DriverException $exception) { - // If we have a SQLSTATE 55006, the drop database operation failed - // because of active connections on the database. - // To force dropping the database, we first have to close all active connections - // on that database and issue the drop database operation again. - if ($exception->getSQLState() !== '55006') { - throw $exception; - } - - assert($this->_platform instanceof PostgreSqlPlatform); - - $this->_execSql( - [ - $this->_platform->getDisallowDatabaseConnectionsSQL($database), - $this->_platform->getCloseActiveDatabaseConnectionsSQL($database), - ] - ); - - parent::dropDatabase($database); - } - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableForeignKeyDefinition($tableForeignKey) - { - $onUpdate = null; - $onDelete = null; - $localColumns = []; - $foreignColumns = []; - $foreignTable = null; - - if (preg_match('(ON UPDATE ([a-zA-Z0-9]+( (NULL|ACTION|DEFAULT))?))', $tableForeignKey['condef'], $match)) { - $onUpdate = $match[1]; - } - if (preg_match('(ON DELETE ([a-zA-Z0-9]+( (NULL|ACTION|DEFAULT))?))', $tableForeignKey['condef'], $match)) { - $onDelete = $match[1]; - } - - if (preg_match('/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)/', $tableForeignKey['condef'], $values)) { - // PostgreSQL returns identifiers that are keywords with quotes, we need them later, don't get - // the idea to trim them here. - $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'], - ['onUpdate' => $onUpdate, 'onDelete' => $onDelete] - ); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTriggerDefinition($trigger) - { - return $trigger['trigger_name']; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableViewDefinition($view) - { - return new View($view['schemaname'] . '.' . $view['viewname'], $view['definition']); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableUserDefinition($user) - { - return [ - 'user' => $user['usename'], - 'password' => $user['passwd'], - ]; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableDefinition($table) - { - $schemas = $this->getExistingSchemaSearchPaths(); - $firstSchema = array_shift($schemas); - - if ($table['schema_name'] === $firstSchema) { - return $table['table_name']; - } - - return $table['schema_name'] . '.' . $table['table_name']; - } - - /** - * {@inheritdoc} - * - * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html - */ - protected function _getPortableTableIndexesList($tableIndexes, $tableName = null) - { - $buffer = []; - foreach ($tableIndexes as $row) { - $colNumbers = array_map('intval', explode(' ', $row['indkey'])); - $columnNameSql = sprintf( - 'SELECT attnum, attname FROM pg_attribute WHERE attrelid=%d AND attnum IN (%s) ORDER BY attnum ASC', - $row['indrelid'], - implode(' ,', $colNumbers) - ); - - $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']) { - continue; - } - - $buffer[] = [ - 'key_name' => $row['relname'], - 'column_name' => trim($colRow['attname']), - 'non_unique' => ! $row['indisunique'], - 'primary' => $row['indisprimary'], - 'where' => $row['where'], - ]; - } - } - } - - return parent::_getPortableTableIndexesList($buffer, $tableName); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableDatabaseDefinition($database) - { - return $database['datname']; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableSequencesList($sequences) - { - $sequenceDefinitions = []; - - foreach ($sequences as $sequence) { - if ($sequence['schemaname'] !== 'public') { - $sequenceName = $sequence['schemaname'] . '.' . $sequence['relname']; - } else { - $sequenceName = $sequence['relname']; - } - - $sequenceDefinitions[$sequenceName] = $sequence; - } - - $list = []; - - foreach ($this->filterAssetNames(array_keys($sequenceDefinitions)) as $sequenceName) { - $list[] = $this->_getPortableSequenceDefinition($sequenceDefinitions[$sequenceName]); - } - - return $list; - } - - /** - * {@inheritdoc} - */ - protected function getPortableNamespaceDefinition(array $namespace) - { - return $namespace['nspname']; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableSequenceDefinition($sequence) - { - if ($sequence['schemaname'] !== 'public') { - $sequenceName = $sequence['schemaname'] . '.' . $sequence['relname']; - } else { - $sequenceName = $sequence['relname']; - } - - if (! isset($sequence['increment_by'], $sequence['min_value'])) { - /** @var string[] $data */ - $data = $this->_conn->fetchAssoc('SELECT min_value, increment_by FROM ' . $this->_platform->quoteIdentifier($sequenceName)); - - $sequence += $data; - } - - return new Sequence($sequenceName, (int) $sequence['increment_by'], (int) $sequence['min_value']); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableColumnDefinition($tableColumn) - { - $tableColumn = array_change_key_case($tableColumn, CASE_LOWER); - - if (strtolower($tableColumn['type']) === 'varchar' || strtolower($tableColumn['type']) === 'bpchar') { - // get length from varchar definition - $length = preg_replace('~.*\(([0-9]*)\).*~', '$1', $tableColumn['complete_type']); - $tableColumn['length'] = $length; - } - - $matches = []; - - $autoincrement = false; - if (preg_match("/^nextval\('(.*)'(::.*)?\)$/", $tableColumn['default'], $matches)) { - $tableColumn['sequence'] = $matches[1]; - $tableColumn['default'] = null; - $autoincrement = true; - } - - if (preg_match("/^['(](.*)[')]::/", $tableColumn['default'], $matches)) { - $tableColumn['default'] = $matches[1]; - } elseif (preg_match('/^NULL::/', $tableColumn['default'])) { - $tableColumn['default'] = null; - } - - $length = $tableColumn['length'] ?? null; - if ($length === '-1' && isset($tableColumn['atttypmod'])) { - $length = $tableColumn['atttypmod'] - 4; - } - if ((int) $length <= 0) { - $length = null; - } - $fixed = null; - - if (! isset($tableColumn['name'])) { - $tableColumn['name'] = ''; - } - - $precision = null; - $scale = null; - $jsonb = null; - - $dbType = strtolower($tableColumn['type']); - if (strlen($tableColumn['domain_type']) && ! $this->_platform->hasDoctrineTypeMappingFor($tableColumn['type'])) { - $dbType = strtolower($tableColumn['domain_type']); - $tableColumn['complete_type'] = $tableColumn['domain_complete_type']; - } - - $type = $this->_platform->getDoctrineTypeMapping($dbType); - $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); - $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); - - switch ($dbType) { - case 'smallint': - case 'int2': - $tableColumn['default'] = $this->fixVersion94NegativeNumericDefaultValue($tableColumn['default']); - $length = null; - break; - case 'int': - case 'int4': - case 'integer': - $tableColumn['default'] = $this->fixVersion94NegativeNumericDefaultValue($tableColumn['default']); - $length = null; - break; - case 'bigint': - case 'int8': - $tableColumn['default'] = $this->fixVersion94NegativeNumericDefaultValue($tableColumn['default']); - $length = null; - break; - case 'bool': - case 'boolean': - if ($tableColumn['default'] === 'true') { - $tableColumn['default'] = true; - } - - if ($tableColumn['default'] === 'false') { - $tableColumn['default'] = false; - } - - $length = null; - break; - case 'text': - case '_varchar': - case 'varchar': - $tableColumn['default'] = $this->parseDefaultExpression($tableColumn['default']); - $fixed = false; - break; - case 'interval': - $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': - $tableColumn['default'] = $this->fixVersion94NegativeNumericDefaultValue($tableColumn['default']); - - 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; - - // PostgreSQL 9.4+ only - case 'jsonb': - $jsonb = true; - break; - } - - if ($tableColumn['default'] && preg_match("('([^']+)'::)", $tableColumn['default'], $match)) { - $tableColumn['default'] = $match[1]; - } - - $options = [ - 'length' => $length, - 'notnull' => (bool) $tableColumn['isnotnull'], - 'default' => $tableColumn['default'], - 'precision' => $precision, - 'scale' => $scale, - 'fixed' => $fixed, - 'unsigned' => false, - 'autoincrement' => $autoincrement, - 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== '' - ? $tableColumn['comment'] - : null, - ]; - - $column = new Column($tableColumn['field'], Type::getType($type), $options); - - if (isset($tableColumn['collation']) && ! empty($tableColumn['collation'])) { - $column->setPlatformOption('collation', $tableColumn['collation']); - } - - if (in_array($column->getType()->getName(), [Types::JSON_ARRAY, Types::JSON], true)) { - $column->setPlatformOption('jsonb', $jsonb); - } - - return $column; - } - - /** - * PostgreSQL 9.4 puts parentheses around negative numeric default values that need to be stripped eventually. - * - * @param mixed $defaultValue - * - * @return mixed - */ - private function fixVersion94NegativeNumericDefaultValue($defaultValue) - { - if (strpos($defaultValue, '(') === 0) { - return trim($defaultValue, '()'); - } - - return $defaultValue; - } - - /** - * Parses a default value expression as given by PostgreSQL - */ - private function parseDefaultExpression(?string $default) : ?string - { - if ($default === null) { - return $default; - } - - return str_replace("''", "'", $default); - } - - public function listTableDetails($tableName) : Table - { - $table = parent::listTableDetails($tableName); - - /** @var PostgreSqlPlatform $platform */ - $platform = $this->_platform; - $sql = $platform->getListTableMetadataSQL($tableName); - - $tableOptions = $this->_conn->fetchAssoc($sql); - - $table->addOption('comment', $tableOptions['table_comment']); - - return $table; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLAnywhereSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLAnywhereSchemaManager.php deleted file mode 100644 index c169a6e..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLAnywhereSchemaManager.php +++ /dev/null @@ -1,231 +0,0 @@ -startDatabase($database); - } - - /** - * {@inheritdoc} - * - * Tries stopping a database before dropping - * as SQL Anywhere needs a database to be stopped - * before it can be dropped. - * - * @see stopDatabase - */ - public function dropDatabase($database) - { - $this->tryMethod('stopDatabase', $database); - parent::dropDatabase($database); - } - - /** - * Starts a database. - * - * @param string $database The name of the database to start. - */ - public function startDatabase($database) - { - assert($this->_platform instanceof SQLAnywherePlatform); - $this->_execSql($this->_platform->getStartDatabaseSQL($database)); - } - - /** - * Stops a database. - * - * @param string $database The name of the database to stop. - */ - public function stopDatabase($database) - { - assert($this->_platform instanceof SQLAnywherePlatform); - $this->_execSql($this->_platform->getStopDatabaseSQL($database)); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableDatabaseDefinition($database) - { - return $database['name']; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableSequenceDefinition($sequence) - { - return new Sequence($sequence['sequence_name'], $sequence['increment_by'], $sequence['start_with']); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableColumnDefinition($tableColumn) - { - $type = $this->_platform->getDoctrineTypeMapping($tableColumn['type']); - $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); - $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); - $precision = null; - $scale = null; - $fixed = false; - $default = null; - - if ($tableColumn['default'] !== null) { - // Strip quotes from default value. - $default = preg_replace(["/^'(.*)'$/", "/''/"], ['$1', "'"], $tableColumn['default']); - - if ($default === 'autoincrement') { - $default = null; - } - } - - switch ($tableColumn['type']) { - case 'binary': - case 'char': - case 'nchar': - $fixed = true; - } - - switch ($type) { - case 'decimal': - case 'float': - $precision = $tableColumn['length']; - $scale = $tableColumn['scale']; - } - - return new Column( - $tableColumn['column_name'], - Type::getType($type), - [ - 'length' => $type === 'string' ? $tableColumn['length'] : null, - 'precision' => $precision, - 'scale' => $scale, - 'unsigned' => (bool) $tableColumn['unsigned'], - 'fixed' => $fixed, - 'notnull' => (bool) $tableColumn['notnull'], - 'default' => $default, - 'autoincrement' => (bool) $tableColumn['autoincrement'], - 'comment' => isset($tableColumn['comment']) && $tableColumn['comment'] !== '' - ? $tableColumn['comment'] - : null, - ] - ); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableDefinition($table) - { - return $table['table_name']; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableForeignKeyDefinition($tableForeignKey) - { - return new ForeignKeyConstraint( - $tableForeignKey['local_columns'], - $tableForeignKey['foreign_table'], - $tableForeignKey['foreign_columns'], - $tableForeignKey['name'], - $tableForeignKey['options'] - ); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableForeignKeysList($tableForeignKeys) - { - $foreignKeys = []; - - foreach ($tableForeignKeys as $tableForeignKey) { - if (! isset($foreignKeys[$tableForeignKey['index_name']])) { - $foreignKeys[$tableForeignKey['index_name']] = [ - 'local_columns' => [$tableForeignKey['local_column']], - 'foreign_table' => $tableForeignKey['foreign_table'], - 'foreign_columns' => [$tableForeignKey['foreign_column']], - 'name' => $tableForeignKey['index_name'], - 'options' => [ - 'notnull' => $tableForeignKey['notnull'], - 'match' => $tableForeignKey['match'], - 'onUpdate' => $tableForeignKey['on_update'], - 'onDelete' => $tableForeignKey['on_delete'], - 'check_on_commit' => $tableForeignKey['check_on_commit'], - 'clustered' => $tableForeignKey['clustered'], - 'for_olap_workload' => $tableForeignKey['for_olap_workload'], - ], - ]; - } else { - $foreignKeys[$tableForeignKey['index_name']]['local_columns'][] = $tableForeignKey['local_column']; - $foreignKeys[$tableForeignKey['index_name']]['foreign_columns'][] = $tableForeignKey['foreign_column']; - } - } - - return parent::_getPortableTableForeignKeysList($foreignKeys); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null) - { - foreach ($tableIndexRows as &$tableIndex) { - $tableIndex['primary'] = (bool) $tableIndex['primary']; - $tableIndex['flags'] = []; - - if ($tableIndex['clustered']) { - $tableIndex['flags'][] = 'clustered'; - } - - if ($tableIndex['with_nulls_not_distinct']) { - $tableIndex['flags'][] = 'with_nulls_not_distinct'; - } - - if (! $tableIndex['for_olap_workload']) { - continue; - } - - $tableIndex['flags'][] = 'for_olap_workload'; - } - - return parent::_getPortableTableIndexesList($tableIndexRows, $tableName); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableViewDefinition($view) - { - $definition = preg_replace('/^.*\s+as\s+SELECT(.*)/i', 'SELECT$1', $view['view_def']); - assert(is_string($definition)); - - return new View($view['table_name'], $definition); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php deleted file mode 100644 index 35cdc45..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php +++ /dev/null @@ -1,349 +0,0 @@ -getPrevious(); - assert($exception instanceof Throwable); - - if (! $exception instanceof DriverException) { - throw $exception; - } - - // If we have a error code 3702, the drop database operation failed - // because of active connections on the database. - // To force dropping the database, we first have to close all active connections - // on that database and issue the drop database operation again. - if ($exception->getErrorCode() !== 3702) { - throw $exception; - } - - $this->closeActiveDatabaseConnections($database); - - parent::dropDatabase($database); - } - } - - /** - * {@inheritdoc} - */ - protected function _getPortableSequenceDefinition($sequence) - { - return new Sequence($sequence['name'], (int) $sequence['increment'], (int) $sequence['start_value']); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableColumnDefinition($tableColumn) - { - $dbType = strtok($tableColumn['type'], '(), '); - assert(is_string($dbType)); - - $fixed = null; - $length = (int) $tableColumn['length']; - $default = $tableColumn['default']; - - if (! isset($tableColumn['name'])) { - $tableColumn['name'] = ''; - } - - if ($default !== null) { - $default = $this->parseDefaultExpression($default); - } - - switch ($dbType) { - case 'nchar': - case 'nvarchar': - case 'ntext': - // Unicode data requires 2 bytes per character - $length /= 2; - break; - case 'varchar': - // TEXT type is returned as VARCHAR(MAX) with a length of -1 - if ($length === -1) { - $dbType = 'text'; - } - break; - } - - if ($dbType === 'char' || $dbType === 'nchar' || $dbType === 'binary') { - $fixed = true; - } - - $type = $this->_platform->getDoctrineTypeMapping($dbType); - $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); - $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); - - $options = [ - 'length' => $length === 0 || ! in_array($type, ['text', 'string']) ? null : $length, - 'unsigned' => false, - 'fixed' => (bool) $fixed, - 'default' => $default, - 'notnull' => (bool) $tableColumn['notnull'], - 'scale' => $tableColumn['scale'], - 'precision' => $tableColumn['precision'], - 'autoincrement' => (bool) $tableColumn['autoincrement'], - 'comment' => $tableColumn['comment'] !== '' ? $tableColumn['comment'] : null, - ]; - - $column = new Column($tableColumn['name'], Type::getType($type), $options); - - if (isset($tableColumn['collation']) && $tableColumn['collation'] !== 'NULL') { - $column->setPlatformOption('collation', $tableColumn['collation']); - } - - return $column; - } - - private function parseDefaultExpression(string $value) : ?string - { - while (preg_match('/^\((.*)\)$/s', $value, $matches)) { - $value = $matches[1]; - } - - if ($value === 'NULL') { - return null; - } - - if (preg_match('/^\'(.*)\'$/s', $value, $matches)) { - $value = str_replace("''", "'", $matches[1]); - } - - if ($value === 'getdate()') { - return $this->_platform->getCurrentTimestampSQL(); - } - - return $value; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableForeignKeysList($tableForeignKeys) - { - $foreignKeys = []; - - foreach ($tableForeignKeys as $tableForeignKey) { - if (! isset($foreignKeys[$tableForeignKey['ForeignKey']])) { - $foreignKeys[$tableForeignKey['ForeignKey']] = [ - 'local_columns' => [$tableForeignKey['ColumnName']], - 'foreign_table' => $tableForeignKey['ReferenceTableName'], - 'foreign_columns' => [$tableForeignKey['ReferenceColumnName']], - 'name' => $tableForeignKey['ForeignKey'], - 'options' => [ - 'onUpdate' => str_replace('_', ' ', $tableForeignKey['update_referential_action_desc']), - 'onDelete' => str_replace('_', ' ', $tableForeignKey['delete_referential_action_desc']), - ], - ]; - } else { - $foreignKeys[$tableForeignKey['ForeignKey']]['local_columns'][] = $tableForeignKey['ColumnName']; - $foreignKeys[$tableForeignKey['ForeignKey']]['foreign_columns'][] = $tableForeignKey['ReferenceColumnName']; - } - } - - return parent::_getPortableTableForeignKeysList($foreignKeys); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null) - { - foreach ($tableIndexRows as &$tableIndex) { - $tableIndex['non_unique'] = (bool) $tableIndex['non_unique']; - $tableIndex['primary'] = (bool) $tableIndex['primary']; - $tableIndex['flags'] = $tableIndex['flags'] ? [$tableIndex['flags']] : null; - } - - return parent::_getPortableTableIndexesList($tableIndexRows, $tableName); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableForeignKeyDefinition($tableForeignKey) - { - return new ForeignKeyConstraint( - $tableForeignKey['local_columns'], - $tableForeignKey['foreign_table'], - $tableForeignKey['foreign_columns'], - $tableForeignKey['name'], - $tableForeignKey['options'] - ); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableDefinition($table) - { - if (isset($table['schema_name']) && $table['schema_name'] !== 'dbo') { - return $table['schema_name'] . '.' . $table['name']; - } - - return $table['name']; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableDatabaseDefinition($database) - { - return $database['name']; - } - - /** - * {@inheritdoc} - */ - protected function getPortableNamespaceDefinition(array $namespace) - { - return $namespace['name']; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableViewDefinition($view) - { - // @todo - return new View($view['name'], ''); - } - - /** - * {@inheritdoc} - */ - public function listTableIndexes($table) - { - $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); - - try { - $tableIndexes = $this->_conn->fetchAll($sql); - } catch (PDOException $e) { - if ($e->getCode() === 'IMSSP') { - return []; - } - - throw $e; - } catch (DBALException $e) { - if (strpos($e->getMessage(), 'SQLSTATE [01000, 15472]') === 0) { - return []; - } - - throw $e; - } - - return $this->_getPortableTableIndexesList($tableIndexes, $table); - } - - /** - * {@inheritdoc} - */ - public function alterTable(TableDiff $tableDiff) - { - if (count($tableDiff->removedColumns) > 0) { - foreach ($tableDiff->removedColumns as $col) { - $columnConstraintSql = $this->getColumnConstraintSQL($tableDiff->name, $col->getName()); - foreach ($this->_conn->fetchAll($columnConstraintSql) as $constraint) { - $this->_conn->exec( - sprintf( - 'ALTER TABLE %s DROP CONSTRAINT %s', - $tableDiff->name, - $constraint['Name'] - ) - ); - } - } - } - - parent::alterTable($tableDiff); - } - - /** - * Returns the SQL to retrieve the constraints for a given column. - * - * @param string $table - * @param string $column - * - * @return string - */ - private function getColumnConstraintSQL($table, $column) - { - return "SELECT SysObjects.[Name] - FROM SysObjects INNER JOIN (SELECT [Name],[ID] FROM SysObjects WHERE XType = 'U') AS Tab - ON Tab.[ID] = Sysobjects.[Parent_Obj] - INNER JOIN sys.default_constraints DefCons ON DefCons.[object_id] = Sysobjects.[ID] - INNER JOIN SysColumns Col ON Col.[ColID] = DefCons.[parent_column_id] AND Col.[ID] = Tab.[ID] - WHERE Col.[Name] = " . $this->_conn->quote($column) . ' AND Tab.[Name] = ' . $this->_conn->quote($table) . ' - ORDER BY Col.[Name]'; - } - - /** - * Closes currently active connections on the given database. - * - * This is useful to force DROP DATABASE operations which could fail because of active connections. - * - * @param string $database The name of the database to close currently active connections for. - * - * @return void - */ - private function closeActiveDatabaseConnections($database) - { - $database = new Identifier($database); - - $this->_execSql( - sprintf( - 'ALTER DATABASE %s SET SINGLE_USER WITH ROLLBACK IMMEDIATE', - $database->getQuotedName($this->_platform) - ) - ); - } - - /** - * @param string $tableName - */ - public function listTableDetails($tableName) : Table - { - $table = parent::listTableDetails($tableName); - - /** @var SQLServerPlatform $platform */ - $platform = $this->_platform; - $sql = $platform->getListTableMetadataSQL($tableName); - - $tableOptions = $this->_conn->fetchAssoc($sql); - - if ($tableOptions !== false) { - $table->addOption('comment', $tableOptions['table_comment']); - } - - return $table; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Schema.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Schema.php deleted file mode 100644 index 5d74665..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Schema.php +++ /dev/null @@ -1,475 +0,0 @@ -_schemaConfig = $schemaConfig; - $this->_setName($schemaConfig->getName() ?: 'public'); - - foreach ($namespaces as $namespace) { - $this->createNamespace($namespace); - } - - foreach ($tables as $table) { - $this->_addTable($table); - } - - foreach ($sequences as $sequence) { - $this->_addSequence($sequence); - } - } - - /** - * @return bool - */ - public function hasExplicitForeignKeyIndexes() - { - return $this->_schemaConfig->hasExplicitForeignKeyIndexes(); - } - - /** - * @return void - * - * @throws SchemaException - */ - protected function _addTable(Table $table) - { - $namespaceName = $table->getNamespaceName(); - $tableName = $table->getFullQualifiedName($this->getName()); - - if (isset($this->_tables[$tableName])) { - throw SchemaException::tableAlreadyExists($tableName); - } - - if ($namespaceName !== null - && ! $table->isInDefaultNamespace($this->getName()) - && ! $this->hasNamespace($namespaceName)) { - $this->createNamespace($namespaceName); - } - - $this->_tables[$tableName] = $table; - $table->setSchemaConfig($this->_schemaConfig); - } - - /** - * @return void - * - * @throws SchemaException - */ - protected function _addSequence(Sequence $sequence) - { - $namespaceName = $sequence->getNamespaceName(); - $seqName = $sequence->getFullQualifiedName($this->getName()); - - if (isset($this->_sequences[$seqName])) { - throw SchemaException::sequenceAlreadyExists($seqName); - } - - if ($namespaceName !== null - && ! $sequence->isInDefaultNamespace($this->getName()) - && ! $this->hasNamespace($namespaceName)) { - $this->createNamespace($namespaceName); - } - - $this->_sequences[$seqName] = $sequence; - } - - /** - * Returns the namespaces of this schema. - * - * @return string[] A list of namespace names. - */ - public function getNamespaces() - { - return $this->namespaces; - } - - /** - * Gets all tables of this schema. - * - * @return Table[] - */ - public function getTables() - { - return $this->_tables; - } - - /** - * @param string $tableName - * - * @return Table - * - * @throws SchemaException - */ - public function getTable($tableName) - { - $tableName = $this->getFullQualifiedAssetName($tableName); - if (! isset($this->_tables[$tableName])) { - throw SchemaException::tableDoesNotExist($tableName); - } - - return $this->_tables[$tableName]; - } - - /** - * @param string $name - * - * @return string - */ - private function getFullQualifiedAssetName($name) - { - $name = $this->getUnquotedAssetName($name); - - if (strpos($name, '.') === false) { - $name = $this->getName() . '.' . $name; - } - - return strtolower($name); - } - - /** - * Returns the unquoted representation of a given asset name. - * - * @param string $assetName Quoted or unquoted representation of an asset name. - * - * @return string - */ - private function getUnquotedAssetName($assetName) - { - if ($this->isIdentifierQuoted($assetName)) { - return $this->trimQuotes($assetName); - } - - return $assetName; - } - - /** - * Does this schema have a namespace with the given name? - * - * @param string $namespaceName - * - * @return bool - */ - public function hasNamespace($namespaceName) - { - $namespaceName = strtolower($this->getUnquotedAssetName($namespaceName)); - - return isset($this->namespaces[$namespaceName]); - } - - /** - * Does this schema have a table with the given name? - * - * @param string $tableName - * - * @return bool - */ - public function hasTable($tableName) - { - $tableName = $this->getFullQualifiedAssetName($tableName); - - return isset($this->_tables[$tableName]); - } - - /** - * Gets all table names, prefixed with a schema name, even the default one if present. - * - * @return string[] - */ - public function getTableNames() - { - return array_keys($this->_tables); - } - - /** - * @param string $sequenceName - * - * @return bool - */ - public function hasSequence($sequenceName) - { - $sequenceName = $this->getFullQualifiedAssetName($sequenceName); - - return isset($this->_sequences[$sequenceName]); - } - - /** - * @param string $sequenceName - * - * @return Sequence - * - * @throws SchemaException - */ - public function getSequence($sequenceName) - { - $sequenceName = $this->getFullQualifiedAssetName($sequenceName); - if (! $this->hasSequence($sequenceName)) { - throw SchemaException::sequenceDoesNotExist($sequenceName); - } - - return $this->_sequences[$sequenceName]; - } - - /** - * @return Sequence[] - */ - public function getSequences() - { - return $this->_sequences; - } - - /** - * Creates a new namespace. - * - * @param string $namespaceName The name of the namespace to create. - * - * @return \Doctrine\DBAL\Schema\Schema This schema instance. - * - * @throws SchemaException - */ - public function createNamespace($namespaceName) - { - $unquotedNamespaceName = strtolower($this->getUnquotedAssetName($namespaceName)); - - if (isset($this->namespaces[$unquotedNamespaceName])) { - throw SchemaException::namespaceAlreadyExists($unquotedNamespaceName); - } - - $this->namespaces[$unquotedNamespaceName] = $namespaceName; - - return $this; - } - - /** - * Creates a new table. - * - * @param string $tableName - * - * @return Table - */ - public function createTable($tableName) - { - $table = new Table($tableName); - $this->_addTable($table); - - foreach ($this->_schemaConfig->getDefaultTableOptions() as $name => $value) { - $table->addOption($name, $value); - } - - return $table; - } - - /** - * Renames a table. - * - * @param string $oldTableName - * @param string $newTableName - * - * @return \Doctrine\DBAL\Schema\Schema - */ - public function renameTable($oldTableName, $newTableName) - { - $table = $this->getTable($oldTableName); - $table->_setName($newTableName); - - $this->dropTable($oldTableName); - $this->_addTable($table); - - return $this; - } - - /** - * Drops a table from the schema. - * - * @param string $tableName - * - * @return \Doctrine\DBAL\Schema\Schema - */ - public function dropTable($tableName) - { - $tableName = $this->getFullQualifiedAssetName($tableName); - $this->getTable($tableName); - unset($this->_tables[$tableName]); - - return $this; - } - - /** - * Creates 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 \Doctrine\DBAL\Schema\Schema - */ - public function dropSequence($sequenceName) - { - $sequenceName = $this->getFullQualifiedAssetName($sequenceName); - unset($this->_sequences[$sequenceName]); - - return $this; - } - - /** - * Returns an array of necessary SQL queries to create the schema on the given platform. - * - * @return string[] - */ - public function toSql(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. - * - * @return string[] - */ - public function toDropSql(AbstractPlatform $platform) - { - $dropSqlCollector = new DropSchemaSqlCollector($platform); - $this->visit($dropSqlCollector); - - return $dropSqlCollector->getQueries(); - } - - /** - * @return string[] - */ - public function getMigrateToSql(Schema $toSchema, AbstractPlatform $platform) - { - $comparator = new Comparator(); - $schemaDiff = $comparator->compare($this, $toSchema); - - return $schemaDiff->toSql($platform); - } - - /** - * @return string[] - */ - public function getMigrateFromSql(Schema $fromSchema, AbstractPlatform $platform) - { - $comparator = new Comparator(); - $schemaDiff = $comparator->compare($fromSchema, $this); - - return $schemaDiff->toSql($platform); - } - - /** - * @return void - */ - public function visit(Visitor $visitor) - { - $visitor->acceptSchema($this); - - if ($visitor instanceof NamespaceVisitor) { - foreach ($this->namespaces as $namespace) { - $visitor->acceptNamespace($namespace); - } - } - - 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; - } - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaConfig.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaConfig.php deleted file mode 100644 index b8c3502..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaConfig.php +++ /dev/null @@ -1,100 +0,0 @@ -hasExplicitForeignKeyIndexes; - } - - /** - * @param bool $flag - * - * @return void - */ - public function setExplicitForeignKeyIndexes($flag) - { - $this->hasExplicitForeignKeyIndexes = (bool) $flag; - } - - /** - * @param int $length - * - * @return void - */ - public function setMaxIdentifierLength($length) - { - $this->maxIdentifierLength = (int) $length; - } - - /** - * @return int - */ - public function getMaxIdentifierLength() - { - return $this->maxIdentifierLength; - } - - /** - * Gets the default namespace of schema objects. - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Sets the default namespace name of schema objects. - * - * @param string $name The value to set. - * - * @return void - */ - public function setName($name) - { - $this->name = $name; - } - - /** - * Gets the default options that are passed to Table instances created with - * Schema#createTable(). - * - * @return mixed[] - */ - public function getDefaultTableOptions() - { - return $this->defaultTableOptions; - } - - /** - * @param mixed[] $defaultTableOptions - * - * @return void - */ - public function setDefaultTableOptions(array $defaultTableOptions) - { - $this->defaultTableOptions = $defaultTableOptions; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaDiff.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaDiff.php deleted file mode 100644 index 69bf125..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaDiff.php +++ /dev/null @@ -1,168 +0,0 @@ -newTables = $newTables; - $this->changedTables = $changedTables; - $this->removedTables = $removedTables; - $this->fromSchema = $fromSchema; - } - - /** - * 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. - * - * @return string[] - */ - public function toSaveSql(AbstractPlatform $platform) - { - return $this->_toSql($platform, true); - } - - /** - * @return string[] - */ - public function toSql(AbstractPlatform $platform) - { - return $this->_toSql($platform, false); - } - - /** - * @param bool $saveMode - * - * @return string[] - */ - protected function _toSql(AbstractPlatform $platform, $saveMode = false) - { - $sql = []; - - if ($platform->supportsSchemas()) { - foreach ($this->newNamespaces as $newNamespace) { - $sql[] = $platform->getCreateSchemaSQL($newNamespace); - } - } - - if ($platform->supportsForeignKeyConstraints() && $saveMode === false) { - foreach ($this->orphanedForeignKeys as $orphanedForeignKey) { - $sql[] = $platform->getDropForeignKeySQL($orphanedForeignKey, $orphanedForeignKey->getLocalTable()); - } - } - - if ($platform->supportsSequences() === true) { - foreach ($this->changedSequences as $sequence) { - $sql[] = $platform->getAlterSequenceSQL($sequence); - } - - if ($saveMode === false) { - foreach ($this->removedSequences as $sequence) { - $sql[] = $platform->getDropSequenceSQL($sequence); - } - } - - foreach ($this->newSequences as $sequence) { - $sql[] = $platform->getCreateSequenceSQL($sequence); - } - } - - $foreignKeySql = []; - foreach ($this->newTables as $table) { - $sql = array_merge( - $sql, - $platform->getCreateTableSQL($table, AbstractPlatform::CREATE_INDEXES) - ); - - if (! $platform->supportsForeignKeyConstraints()) { - continue; - } - - 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; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaException.php deleted file mode 100644 index 213d218..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SchemaException.php +++ /dev/null @@ -1,183 +0,0 @@ -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.' - ); - } - - /** - * @param string $changeName - * - * @return \Doctrine\DBAL\Schema\SchemaException - */ - public static function alterTableChangeNotSupported($changeName) - { - return new self( - sprintf("Alter table change not supported, given '%s'", $changeName) - ); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Sequence.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Sequence.php deleted file mode 100644 index 8889101..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Sequence.php +++ /dev/null @@ -1,139 +0,0 @@ -_setName($name); - $this->setAllocationSize($allocationSize); - $this->setInitialValue($initialValue); - $this->cache = $cache; - } - - /** - * @return int - */ - public function getAllocationSize() - { - return $this->allocationSize; - } - - /** - * @return int - */ - public function getInitialValue() - { - return $this->initialValue; - } - - /** - * @return int|null - */ - public function getCache() - { - return $this->cache; - } - - /** - * @param int $allocationSize - * - * @return \Doctrine\DBAL\Schema\Sequence - */ - public function setAllocationSize($allocationSize) - { - $this->allocationSize = (int) $allocationSize ?: 1; - - return $this; - } - - /** - * @param int $initialValue - * - * @return \Doctrine\DBAL\Schema\Sequence - */ - public function setInitialValue($initialValue) - { - $this->initialValue = (int) $initialValue ?: 1; - - return $this; - } - - /** - * @param int $cache - * - * @return \Doctrine\DBAL\Schema\Sequence - */ - public function setCache($cache) - { - $this->cache = $cache; - - return $this; - } - - /** - * Checks if this sequence is an autoincrement sequence for a given table. - * - * This is used inside the comparator to not report sequences as missing, - * when the "from" schema implicitly creates the sequences. - * - * @return bool - */ - public function isAutoIncrementsFor(Table $table) - { - $primaryKey = $table->getPrimaryKey(); - - if ($primaryKey === null) { - return false; - } - - $pkColumns = $primaryKey->getColumns(); - - if (count($pkColumns) !== 1) { - return false; - } - - $column = $table->getColumn($pkColumns[0]); - - if (! $column->getAutoincrement()) { - return false; - } - - $sequenceName = $this->getShortestName($table->getNamespaceName()); - $tableName = $table->getShortestName($table->getNamespaceName()); - $tableSequenceName = sprintf('%s_%s_seq', $tableName, $column->getShortestName($table->getNamespaceName())); - - return $tableSequenceName === $sequenceName; - } - - /** - * @return void - */ - public function visit(Visitor $visitor) - { - $visitor->acceptSequence($this); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php deleted file mode 100644 index ac75801..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php +++ /dev/null @@ -1,545 +0,0 @@ -_conn->getParams(); - $driver = $params['driver']; - $options = [ - 'driver' => $driver, - 'path' => $database, - ]; - $conn = DriverManager::getConnection($options); - $conn->connect(); - $conn->close(); - } - - /** - * {@inheritdoc} - */ - public function renameTable($name, $newName) - { - $tableDiff = new TableDiff($name); - $tableDiff->fromTable = $this->listTableDetails($name); - $tableDiff->newName = $newName; - $this->alterTable($tableDiff); - } - - /** - * {@inheritdoc} - */ - public function createForeignKey(ForeignKeyConstraint $foreignKey, $table) - { - $tableDiff = $this->getTableDiffForAlterForeignKey($table); - $tableDiff->addedForeignKeys[] = $foreignKey; - - $this->alterTable($tableDiff); - } - - /** - * {@inheritdoc} - */ - public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table) - { - $tableDiff = $this->getTableDiffForAlterForeignKey($table); - $tableDiff->changedForeignKeys[] = $foreignKey; - - $this->alterTable($tableDiff); - } - - /** - * {@inheritdoc} - */ - public function dropForeignKey($foreignKey, $table) - { - $tableDiff = $this->getTableDiffForAlterForeignKey($table); - $tableDiff->removedForeignKeys[] = $foreignKey; - - $this->alterTable($tableDiff); - } - - /** - * {@inheritdoc} - */ - public function listTableForeignKeys($table, $database = null) - { - if ($database === null) { - $database = $this->_conn->getDatabase(); - } - $sql = $this->_platform->getListTableForeignKeysSQL($table, $database); - $tableForeignKeys = $this->_conn->fetchAll($sql); - - if (! empty($tableForeignKeys)) { - $createSql = $this->getCreateTableSQL($table); - - if ($createSql !== null && preg_match_all( - '# - (?:CONSTRAINT\s+([^\s]+)\s+)? - (?:FOREIGN\s+KEY[^\)]+\)\s*)? - REFERENCES\s+[^\s]+\s+(?:\([^\)]+\))? - (?: - [^,]*? - (NOT\s+DEFERRABLE|DEFERRABLE) - (?:\s+INITIALLY\s+(DEFERRED|IMMEDIATE))? - )?#isx', - $createSql, - $match - )) { - $names = array_reverse($match[1]); - $deferrable = array_reverse($match[2]); - $deferred = array_reverse($match[3]); - } else { - $names = $deferrable = $deferred = []; - } - - foreach ($tableForeignKeys as $key => $value) { - $id = $value['id']; - $tableForeignKeys[$key]['constraint_name'] = isset($names[$id]) && $names[$id] !== '' ? $names[$id] : $id; - $tableForeignKeys[$key]['deferrable'] = isset($deferrable[$id]) && strtolower($deferrable[$id]) === 'deferrable'; - $tableForeignKeys[$key]['deferred'] = isset($deferred[$id]) && strtolower($deferred[$id]) === 'deferred'; - } - } - - return $this->_getPortableTableForeignKeysList($tableForeignKeys); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableDefinition($table) - { - return $table['name']; - } - - /** - * {@inheritdoc} - * - * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html - */ - protected function _getPortableTableIndexesList($tableIndexes, $tableName = null) - { - $indexBuffer = []; - - // fetch primary - $stmt = $this->_conn->executeQuery(sprintf( - 'PRAGMA TABLE_INFO (%s)', - $this->_conn->quote($tableName) - )); - $indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE); - - usort($indexArray, static function ($a, $b) { - if ($a['pk'] === $b['pk']) { - return $a['cid'] - $b['cid']; - } - - return $a['pk'] - $b['pk']; - }); - foreach ($indexArray as $indexColumnRow) { - if ($indexColumnRow['pk'] === '0') { - continue; - } - - $indexBuffer[] = [ - 'key_name' => 'primary', - 'primary' => true, - 'non_unique' => false, - 'column_name' => $indexColumnRow['name'], - ]; - } - - // fetch regular indexes - foreach ($tableIndexes as $tableIndex) { - // Ignore indexes with reserved names, e.g. autoindexes - if (strpos($tableIndex['name'], 'sqlite_') === 0) { - continue; - } - - $keyName = $tableIndex['name']; - $idx = []; - $idx['key_name'] = $keyName; - $idx['primary'] = false; - $idx['non_unique'] = ! $tableIndex['unique']; - - $stmt = $this->_conn->executeQuery(sprintf( - 'PRAGMA INDEX_INFO (%s)', - $this->_conn->quote($keyName) - )); - $indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE); - - foreach ($indexArray as $indexColumnRow) { - $idx['column_name'] = $indexColumnRow['name']; - $indexBuffer[] = $idx; - } - } - - return parent::_getPortableTableIndexesList($indexBuffer, $tableName); - } - - /** - * {@inheritdoc} - * - * @deprecated - */ - protected function _getPortableTableIndexDefinition($tableIndex) - { - return [ - 'name' => $tableIndex['name'], - 'unique' => (bool) $tableIndex['unique'], - ]; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableColumnList($table, $database, $tableColumns) - { - $list = parent::_getPortableTableColumnList($table, $database, $tableColumns); - - // find column with autoincrement - $autoincrementColumn = null; - $autoincrementCount = 0; - - foreach ($tableColumns as $tableColumn) { - if ($tableColumn['pk'] === '0') { - continue; - } - - $autoincrementCount++; - if ($autoincrementColumn !== null || strtolower($tableColumn['type']) !== 'integer') { - continue; - } - - $autoincrementColumn = $tableColumn['name']; - } - - if ($autoincrementCount === 1 && $autoincrementColumn !== null) { - foreach ($list as $column) { - if ($autoincrementColumn !== $column->getName()) { - continue; - } - - $column->setAutoincrement(true); - } - } - - // inspect column collation and comments - $createSql = $this->getCreateTableSQL($table) ?? ''; - - foreach ($list as $columnName => $column) { - $type = $column->getType(); - - if ($type instanceof StringType || $type instanceof TextType) { - $column->setPlatformOption('collation', $this->parseColumnCollationFromSQL($columnName, $createSql) ?: 'BINARY'); - } - - $comment = $this->parseColumnCommentFromSQL($columnName, $createSql); - - if ($comment === null) { - continue; - } - - $type = $this->extractDoctrineTypeFromComment($comment, ''); - - if ($type !== '') { - $column->setType(Type::getType($type)); - - $comment = $this->removeDoctrineTypeFromComment($comment, $type); - } - - $column->setComment($comment); - } - - return $list; - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableColumnDefinition($tableColumn) - { - $parts = explode('(', $tableColumn['type']); - $tableColumn['type'] = trim($parts[0]); - if (isset($parts[1])) { - $length = trim($parts[1], ')'); - $tableColumn['length'] = $length; - } - - $dbType = strtolower($tableColumn['type']); - $length = $tableColumn['length'] ?? null; - $unsigned = false; - - if (strpos($dbType, ' unsigned') !== false) { - $dbType = str_replace(' unsigned', '', $dbType); - $unsigned = true; - } - - $fixed = false; - $type = $this->_platform->getDoctrineTypeMapping($dbType); - $default = $tableColumn['dflt_value']; - if ($default === 'NULL') { - $default = null; - } - - if ($default !== null) { - // SQLite returns the default value as a literal expression, so we need to parse it - if (preg_match('/^\'(.*)\'$/s', $default, $matches)) { - $default = str_replace("''", "'", $matches[1]); - } - } - - $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': - if (isset($tableColumn['length'])) { - if (strpos($tableColumn['length'], ',') === false) { - $tableColumn['length'] .= ',0'; - } - [$precision, $scale] = array_map('trim', explode(',', $tableColumn['length'])); - } - $length = null; - break; - } - - $options = [ - 'length' => $length, - 'unsigned' => (bool) $unsigned, - 'fixed' => $fixed, - 'notnull' => $notnull, - 'default' => $default, - 'precision' => $precision, - 'scale' => $scale, - 'autoincrement' => false, - ]; - - return new Column($tableColumn['name'], Type::getType($type), $options); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableViewDefinition($view) - { - return new View($view['name'], $view['sql']); - } - - /** - * {@inheritdoc} - */ - protected function _getPortableTableForeignKeysList($tableForeignKeys) - { - $list = []; - foreach ($tableForeignKeys as $value) { - $value = array_change_key_case($value, CASE_LOWER); - $name = $value['constraint_name']; - if (! isset($list[$name])) { - if (! isset($value['on_delete']) || $value['on_delete'] === 'RESTRICT') { - $value['on_delete'] = null; - } - if (! isset($value['on_update']) || $value['on_update'] === 'RESTRICT') { - $value['on_update'] = null; - } - - $list[$name] = [ - 'name' => $name, - 'local' => [], - 'foreign' => [], - 'foreignTable' => $value['table'], - 'onDelete' => $value['on_delete'], - 'onUpdate' => $value['on_update'], - 'deferrable' => $value['deferrable'], - 'deferred'=> $value['deferred'], - ]; - } - $list[$name]['local'][] = $value['from']; - $list[$name]['foreign'][] = $value['to']; - } - - $result = []; - foreach ($list as $constraint) { - $result[] = new ForeignKeyConstraint( - array_values($constraint['local']), - $constraint['foreignTable'], - array_values($constraint['foreign']), - $constraint['name'], - [ - 'onDelete' => $constraint['onDelete'], - 'onUpdate' => $constraint['onUpdate'], - 'deferrable' => $constraint['deferrable'], - 'deferred'=> $constraint['deferred'], - ] - ); - } - - return $result; - } - - /** - * @param Table|string $table - * - * @return TableDiff - * - * @throws DBALException - */ - private function getTableDiffForAlterForeignKey($table) - { - if (! $table instanceof Table) { - $tableDetails = $this->tryMethod('listTableDetails', $table); - - if ($tableDetails === false) { - throw new DBALException(sprintf('Sqlite schema manager requires to modify foreign keys table definition "%s".', $table)); - } - - $table = $tableDetails; - } - - $tableDiff = new TableDiff($table->getName()); - $tableDiff->fromTable = $table; - - return $tableDiff; - } - - private function parseColumnCollationFromSQL(string $column, string $sql) : ?string - { - $pattern = '{(?:\W' . preg_quote($column) . '\W|\W' . preg_quote($this->_platform->quoteSingleIdentifier($column)) - . '\W)[^,(]+(?:\([^()]+\)[^,]*)?(?:(?:DEFAULT|CHECK)\s*(?:\(.*?\))?[^,]*)*COLLATE\s+["\']?([^\s,"\')]+)}is'; - - if (preg_match($pattern, $sql, $match) !== 1) { - return null; - } - - return $match[1]; - } - - private function parseTableCommentFromSQL(string $table, string $sql) : ?string - { - $pattern = '/\s* # Allow whitespace characters at start of line -CREATE\sTABLE # Match "CREATE TABLE" -(?:\W"' . preg_quote($this->_platform->quoteSingleIdentifier($table), '/') . '"\W|\W' . preg_quote($table, '/') - . '\W) # Match table name (quoted and unquoted) -( # Start capture - (?:\s*--[^\n]*\n?)+ # Capture anything that starts with whitespaces followed by -- until the end of the line(s) -)/ix'; - - if (preg_match($pattern, $sql, $match) !== 1) { - return null; - } - - $comment = preg_replace('{^\s*--}m', '', rtrim($match[1], "\n")); - - return $comment === '' ? null : $comment; - } - - private function parseColumnCommentFromSQL(string $column, string $sql) : ?string - { - $pattern = '{[\s(,](?:\W' . preg_quote($this->_platform->quoteSingleIdentifier($column)) . '\W|\W' . preg_quote($column) - . '\W)(?:\(.*?\)|[^,(])*?,?((?:(?!\n))(?:\s*--[^\n]*\n?)+)}i'; - - if (preg_match($pattern, $sql, $match) !== 1) { - return null; - } - - $comment = preg_replace('{^\s*--}m', '', rtrim($match[1], "\n")); - - return $comment === '' ? null : $comment; - } - - private function getCreateTableSQL(string $table) : ?string - { - return $this->_conn->fetchColumn( - <<<'SQL' -SELECT sql - FROM ( - SELECT * - FROM sqlite_master - UNION ALL - SELECT * - FROM sqlite_temp_master - ) -WHERE type = 'table' -AND name = ? -SQL - , - [$table] - ) ?: null; - } - - /** - * @param string $tableName - */ - public function listTableDetails($tableName) : Table - { - $table = parent::listTableDetails($tableName); - - $tableCreateSql = $this->getCreateTableSQL($tableName) ?? ''; - - $comment = $this->parseTableCommentFromSQL($tableName, $tableCreateSql); - - if ($comment !== null) { - $table->addOption('comment', $comment); - } - - return $table; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php deleted file mode 100644 index b597b8d..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php +++ /dev/null @@ -1,43 +0,0 @@ -conn = $conn; - } - - /** - * @param string[] $sql - */ - protected function processSqlSafely(array $sql) - { - foreach ($sql as $s) { - try { - $this->conn->exec($s); - } catch (Throwable $e) { - } - } - } - - /** - * @param string[] $sql - */ - protected function processSql(array $sql) - { - foreach ($sql as $s) { - $this->conn->exec($s); - } - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php deleted file mode 100644 index 3e7beea..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php +++ /dev/null @@ -1,72 +0,0 @@ -platform = $conn->getDatabasePlatform(); - } - - /** - * {@inheritdoc} - */ - public function getCreateSchema(Schema $createSchema) - { - return $createSchema->toSql($this->platform); - } - - /** - * {@inheritdoc} - */ - public function getUpdateSchema(Schema $toSchema, $noDrops = false) - { - $comparator = new Comparator(); - $sm = $this->conn->getSchemaManager(); - - $fromSchema = $sm->createSchema(); - $schemaDiff = $comparator->compare($fromSchema, $toSchema); - - if ($noDrops) { - return $schemaDiff->toSaveSql($this->platform); - } - - return $schemaDiff->toSql($this->platform); - } - - /** - * {@inheritdoc} - */ - public function getDropSchema(Schema $dropSchema) - { - $visitor = new DropSchemaSqlCollector($this->platform); - $sm = $this->conn->getSchemaManager(); - - $fullSchema = $sm->createSchema(); - - foreach ($fullSchema->getTables() as $table) { - if ($dropSchema->hasTable($table->getName())) { - $visitor->acceptTable($table); - } - - foreach ($table->getForeignKeys() as $foreignKey) { - if (! $dropSchema->hasTable($table->getName())) { - continue; - } - - if (! $dropSchema->hasTable($foreignKey->getForeignTableName())) { - continue; - } - - $visitor->acceptForeignKey($table, $foreignKey); - } - } - - if (! $this->platform->supportsSequences()) { - return $visitor->getQueries(); - } - - foreach ($dropSchema->getSequences() as $sequence) { - $visitor->acceptSequence($sequence); - } - - foreach ($dropSchema->getTables() as $table) { - $primaryKey = $table->getPrimaryKey(); - - if ($primaryKey === null) { - continue; - } - - $columns = $primaryKey->getColumns(); - - if (count($columns) > 1) { - continue; - } - - $checkSequence = $table->getName() . '_' . $columns[0] . '_seq'; - if (! $fullSchema->hasSequence($checkSequence)) { - continue; - } - - $visitor->acceptSequence($fullSchema->getSequence($checkSequence)); - } - - return $visitor->getQueries(); - } - - /** - * {@inheritdoc} - */ - public function getDropAllSchema() - { - $sm = $this->conn->getSchemaManager(); - $visitor = new DropSchemaSqlCollector($this->platform); - - $schema = $sm->createSchema(); - $schema->visit($visitor); - - return $visitor->getQueries(); - } - - /** - * {@inheritdoc} - */ - public function createSchema(Schema $createSchema) - { - $this->processSql($this->getCreateSchema($createSchema)); - } - - /** - * {@inheritdoc} - */ - public function updateSchema(Schema $toSchema, $noDrops = false) - { - $this->processSql($this->getUpdateSchema($toSchema, $noDrops)); - } - - /** - * {@inheritdoc} - */ - public function dropSchema(Schema $dropSchema) - { - $this->processSqlSafely($this->getDropSchema($dropSchema)); - } - - /** - * {@inheritdoc} - */ - public function dropAllSchema() - { - $this->processSql($this->getDropAllSchema()); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Table.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Table.php deleted file mode 100644 index 8e61332..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Table.php +++ /dev/null @@ -1,856 +0,0 @@ - [], - ]; - - /** @var SchemaConfig|null */ - protected $_schemaConfig = null; - - /** - * @param string $tableName - * @param Column[] $columns - * @param Index[] $indexes - * @param ForeignKeyConstraint[] $fkConstraints - * @param int $idGeneratorType - * @param mixed[] $options - * - * @throws DBALException - */ - public function __construct($tableName, array $columns = [], array $indexes = [], array $fkConstraints = [], $idGeneratorType = 0, array $options = []) - { - if (strlen($tableName) === 0) { - throw DBALException::invalidTableName($tableName); - } - - $this->_setName($tableName); - - foreach ($columns as $column) { - $this->_addColumn($column); - } - - foreach ($indexes as $idx) { - $this->_addIndex($idx); - } - - foreach ($fkConstraints as $constraint) { - $this->_addForeignKeyConstraint($constraint); - } - - $this->_options = array_merge($this->_options, $options); - } - - /** - * @return void - */ - public function setSchemaConfig(SchemaConfig $schemaConfig) - { - $this->_schemaConfig = $schemaConfig; - } - - /** - * @return int - */ - protected function _getMaxIdentifierLength() - { - if ($this->_schemaConfig instanceof SchemaConfig) { - return $this->_schemaConfig->getMaxIdentifierLength(); - } - - return 63; - } - - /** - * Sets the Primary Key. - * - * @param string[] $columnNames - * @param string|false $indexName - * - * @return self - */ - public function setPrimaryKey(array $columnNames, $indexName = false) - { - $this->_addIndex($this->_createIndex($columnNames, $indexName ?: 'primary', true, true)); - - foreach ($columnNames as $columnName) { - $column = $this->getColumn($columnName); - $column->setNotnull(true); - } - - return $this; - } - - /** - * @param string[] $columnNames - * @param string|null $indexName - * @param string[] $flags - * @param mixed[] $options - * - * @return self - */ - public function addIndex(array $columnNames, $indexName = null, array $flags = [], array $options = []) - { - if ($indexName === null) { - $indexName = $this->_generateIdentifierName( - array_merge([$this->getName()], $columnNames), - 'idx', - $this->_getMaxIdentifierLength() - ); - } - - return $this->_addIndex($this->_createIndex($columnNames, $indexName, false, false, $flags, $options)); - } - - /** - * Drops the primary key from this table. - * - * @return void - */ - public function dropPrimaryKey() - { - $this->dropIndex($this->_primaryKeyName); - $this->_primaryKeyName = false; - } - - /** - * Drops an index from this table. - * - * @param string $indexName The index name. - * - * @return void - * - * @throws SchemaException If the index does not exist. - */ - public function dropIndex($indexName) - { - $indexName = $this->normalizeIdentifier($indexName); - if (! $this->hasIndex($indexName)) { - throw SchemaException::indexDoesNotExist($indexName, $this->_name); - } - unset($this->_indexes[$indexName]); - } - - /** - * @param string[] $columnNames - * @param string|null $indexName - * @param mixed[] $options - * - * @return self - */ - public function addUniqueIndex(array $columnNames, $indexName = null, array $options = []) - { - if ($indexName === null) { - $indexName = $this->_generateIdentifierName( - array_merge([$this->getName()], $columnNames), - 'uniq', - $this->_getMaxIdentifierLength() - ); - } - - return $this->_addIndex($this->_createIndex($columnNames, $indexName, true, false, [], $options)); - } - - /** - * Renames an index. - * - * @param string $oldIndexName The name of the index to rename from. - * @param string|null $newIndexName The name of the index to rename to. - * If null is given, the index name will be auto-generated. - * - * @return self This table instance. - * - * @throws SchemaException If no index exists for the given current name - * or if an index with the given new name already exists on this table. - */ - public function renameIndex($oldIndexName, $newIndexName = null) - { - $oldIndexName = $this->normalizeIdentifier($oldIndexName); - $normalizedNewIndexName = $this->normalizeIdentifier($newIndexName); - - if ($oldIndexName === $normalizedNewIndexName) { - return $this; - } - - if (! $this->hasIndex($oldIndexName)) { - throw SchemaException::indexDoesNotExist($oldIndexName, $this->_name); - } - - if ($this->hasIndex($normalizedNewIndexName)) { - throw SchemaException::indexAlreadyExists($normalizedNewIndexName, $this->_name); - } - - $oldIndex = $this->_indexes[$oldIndexName]; - - if ($oldIndex->isPrimary()) { - $this->dropPrimaryKey(); - - return $this->setPrimaryKey($oldIndex->getColumns(), $newIndexName ?? false); - } - - unset($this->_indexes[$oldIndexName]); - - if ($oldIndex->isUnique()) { - return $this->addUniqueIndex($oldIndex->getColumns(), $newIndexName, $oldIndex->getOptions()); - } - - return $this->addIndex($oldIndex->getColumns(), $newIndexName, $oldIndex->getFlags(), $oldIndex->getOptions()); - } - - /** - * Checks if an index begins in the order of the given columns. - * - * @param string[] $columnNames - * - * @return bool - */ - public function columnsAreIndexed(array $columnNames) - { - foreach ($this->getIndexes() as $index) { - /** @var $index Index */ - if ($index->spansColumns($columnNames)) { - return true; - } - } - - return false; - } - - /** - * @param string[] $columnNames - * @param string $indexName - * @param bool $isUnique - * @param bool $isPrimary - * @param string[] $flags - * @param mixed[] $options - * - * @return Index - * - * @throws SchemaException - */ - private function _createIndex(array $columnNames, $indexName, $isUnique, $isPrimary, array $flags = [], array $options = []) - { - if (preg_match('(([^a-zA-Z0-9_]+))', $this->normalizeIdentifier($indexName))) { - throw SchemaException::indexNameInvalid($indexName); - } - - foreach ($columnNames as $columnName) { - if (! $this->hasColumn($columnName)) { - throw SchemaException::columnDoesNotExist($columnName, $this->_name); - } - } - - return new Index($indexName, $columnNames, $isUnique, $isPrimary, $flags, $options); - } - - /** - * @param string $columnName - * @param string $typeName - * @param mixed[] $options - * - * @return Column - */ - public function addColumn($columnName, $typeName, array $options = []) - { - $column = new Column($columnName, Type::getType($typeName), $options); - - $this->_addColumn($column); - - return $column; - } - - /** - * Renames a Column. - * - * @deprecated - * - * @param string $oldColumnName - * @param string $newColumnName - * - * @throws DBALException - */ - public function renameColumn($oldColumnName, $newColumnName) - { - throw new DBALException('Table#renameColumn() was removed, because it drops and recreates ' . - 'the column instead. There is no fix available, because a schema diff cannot reliably detect if a ' . - 'column was renamed or one column was created and another one dropped.'); - } - - /** - * Change Column Details. - * - * @param string $columnName - * @param mixed[] $options - * - * @return self - */ - public function changeColumn($columnName, array $options) - { - $column = $this->getColumn($columnName); - $column->setOptions($options); - - return $this; - } - - /** - * Drops a Column from the Table. - * - * @param string $columnName - * - * @return self - */ - public function dropColumn($columnName) - { - $columnName = $this->normalizeIdentifier($columnName); - unset($this->_columns[$columnName]); - - return $this; - } - - /** - * Adds a foreign key constraint. - * - * Name is inferred from the local columns. - * - * @param Table|string $foreignTable Table schema instance or table name - * @param string[] $localColumnNames - * @param string[] $foreignColumnNames - * @param mixed[] $options - * @param string|null $constraintName - * - * @return self - */ - public function addForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options = [], $constraintName = null) - { - $constraintName = $constraintName ?: $this->_generateIdentifierName(array_merge((array) $this->getName(), $localColumnNames), 'fk', $this->_getMaxIdentifierLength()); - - return $this->addNamedForeignKeyConstraint($constraintName, $foreignTable, $localColumnNames, $foreignColumnNames, $options); - } - - /** - * Adds a foreign key constraint. - * - * Name is to be generated by the database itself. - * - * @deprecated Use {@link addForeignKeyConstraint} - * - * @param Table|string $foreignTable Table schema instance or table name - * @param string[] $localColumnNames - * @param string[] $foreignColumnNames - * @param mixed[] $options - * - * @return self - */ - public function addUnnamedForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options = []) - { - return $this->addForeignKeyConstraint($foreignTable, $localColumnNames, $foreignColumnNames, $options); - } - - /** - * Adds a foreign key constraint with a given name. - * - * @deprecated Use {@link addForeignKeyConstraint} - * - * @param string $name - * @param Table|string $foreignTable Table schema instance or table name - * @param string[] $localColumnNames - * @param string[] $foreignColumnNames - * @param mixed[] $options - * - * @return self - * - * @throws SchemaException - */ - public function addNamedForeignKeyConstraint($name, $foreignTable, array $localColumnNames, array $foreignColumnNames, array $options = []) - { - if ($foreignTable instanceof Table) { - foreach ($foreignColumnNames as $columnName) { - if (! $foreignTable->hasColumn($columnName)) { - throw SchemaException::columnDoesNotExist($columnName, $foreignTable->getName()); - } - } - } - - foreach ($localColumnNames as $columnName) { - if (! $this->hasColumn($columnName)) { - throw SchemaException::columnDoesNotExist($columnName, $this->_name); - } - } - - $constraint = new ForeignKeyConstraint( - $localColumnNames, - $foreignTable, - $foreignColumnNames, - $name, - $options - ); - $this->_addForeignKeyConstraint($constraint); - - return $this; - } - - /** - * @param string $name - * @param mixed $value - * - * @return self - */ - public function addOption($name, $value) - { - $this->_options[$name] = $value; - - return $this; - } - - /** - * @return void - * - * @throws SchemaException - */ - protected function _addColumn(Column $column) - { - $columnName = $column->getName(); - $columnName = $this->normalizeIdentifier($columnName); - - if (isset($this->_columns[$columnName])) { - throw SchemaException::columnAlreadyExists($this->getName(), $columnName); - } - - $this->_columns[$columnName] = $column; - } - - /** - * Adds an index to the table. - * - * @return self - * - * @throws SchemaException - */ - protected function _addIndex(Index $indexCandidate) - { - $indexName = $indexCandidate->getName(); - $indexName = $this->normalizeIdentifier($indexName); - $replacedImplicitIndexes = []; - - foreach ($this->implicitIndexes as $name => $implicitIndex) { - if (! $implicitIndex->isFullfilledBy($indexCandidate) || ! isset($this->_indexes[$name])) { - continue; - } - - $replacedImplicitIndexes[] = $name; - } - - if ((isset($this->_indexes[$indexName]) && ! in_array($indexName, $replacedImplicitIndexes, true)) || - ($this->_primaryKeyName !== false && $indexCandidate->isPrimary()) - ) { - throw SchemaException::indexAlreadyExists($indexName, $this->_name); - } - - foreach ($replacedImplicitIndexes as $name) { - unset($this->_indexes[$name], $this->implicitIndexes[$name]); - } - - if ($indexCandidate->isPrimary()) { - $this->_primaryKeyName = $indexName; - } - - $this->_indexes[$indexName] = $indexCandidate; - - return $this; - } - - /** - * @return void - */ - 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 = $this->normalizeIdentifier($name); - - $this->_fkConstraints[$name] = $constraint; - - // add an explicit index on the foreign key columns. If there is already an index that fulfils 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 computation overhead in this case, however no duplicate indexes are ever added (based on columns). - $indexName = $this->_generateIdentifierName( - array_merge([$this->getName()], $constraint->getColumns()), - 'idx', - $this->_getMaxIdentifierLength() - ); - $indexCandidate = $this->_createIndex($constraint->getColumns(), $indexName, false, false); - - foreach ($this->_indexes as $existingIndex) { - if ($indexCandidate->isFullfilledBy($existingIndex)) { - return; - } - } - - $this->_addIndex($indexCandidate); - $this->implicitIndexes[$this->normalizeIdentifier($indexName)] = $indexCandidate; - } - - /** - * Returns whether this table has a foreign key constraint with the given name. - * - * @param string $constraintName - * - * @return bool - */ - public function hasForeignKey($constraintName) - { - $constraintName = $this->normalizeIdentifier($constraintName); - - return isset($this->_fkConstraints[$constraintName]); - } - - /** - * Returns the foreign key constraint with the given name. - * - * @param string $constraintName The constraint name. - * - * @return ForeignKeyConstraint - * - * @throws SchemaException If the foreign key does not exist. - */ - public function getForeignKey($constraintName) - { - $constraintName = $this->normalizeIdentifier($constraintName); - if (! $this->hasForeignKey($constraintName)) { - throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name); - } - - return $this->_fkConstraints[$constraintName]; - } - - /** - * Removes the foreign key constraint with the given name. - * - * @param string $constraintName The constraint name. - * - * @return void - * - * @throws SchemaException - */ - public function removeForeignKey($constraintName) - { - $constraintName = $this->normalizeIdentifier($constraintName); - if (! $this->hasForeignKey($constraintName)) { - throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name); - } - - unset($this->_fkConstraints[$constraintName]); - } - - /** - * Returns ordered list of columns (primary keys are first, then foreign keys, then the rest) - * - * @return Column[] - */ - public function getColumns() - { - $primaryKey = $this->getPrimaryKey(); - $primaryKeyColumns = []; - - if ($primaryKey !== null) { - $primaryKeyColumns = $this->filterColumns($primaryKey->getColumns()); - } - - return array_merge($primaryKeyColumns, $this->getForeignKeyColumns(), $this->_columns); - } - - /** - * Returns foreign key columns - * - * @return Column[] - */ - private function getForeignKeyColumns() - { - $foreignKeyColumns = []; - foreach ($this->getForeignKeys() as $foreignKey) { - $foreignKeyColumns = array_merge($foreignKeyColumns, $foreignKey->getColumns()); - } - - return $this->filterColumns($foreignKeyColumns); - } - - /** - * Returns only columns that have specified names - * - * @param string[] $columnNames - * - * @return Column[] - */ - private function filterColumns(array $columnNames) - { - return array_filter($this->_columns, static function ($columnName) use ($columnNames) { - return in_array($columnName, $columnNames, true); - }, ARRAY_FILTER_USE_KEY); - } - - /** - * Returns whether this table has a Column with the given name. - * - * @param string $columnName The column name. - * - * @return bool - */ - public function hasColumn($columnName) - { - $columnName = $this->normalizeIdentifier($columnName); - - return isset($this->_columns[$columnName]); - } - - /** - * Returns the Column with the given name. - * - * @param string $columnName The column name. - * - * @return Column - * - * @throws SchemaException If the column does not exist. - */ - public function getColumn($columnName) - { - $columnName = $this->normalizeIdentifier($columnName); - if (! $this->hasColumn($columnName)) { - throw SchemaException::columnDoesNotExist($columnName, $this->_name); - } - - return $this->_columns[$columnName]; - } - - /** - * Returns the primary key. - * - * @return Index|null The primary key, or null if this Table has no primary key. - */ - public function getPrimaryKey() - { - if (! $this->hasPrimaryKey()) { - return null; - } - - return $this->getIndex($this->_primaryKeyName); - } - - /** - * Returns the primary key columns. - * - * @return string[] - * - * @throws DBALException - */ - public function getPrimaryKeyColumns() - { - $primaryKey = $this->getPrimaryKey(); - - if ($primaryKey === null) { - throw new DBALException('Table ' . $this->getName() . ' has no primary key.'); - } - - return $primaryKey->getColumns(); - } - - /** - * Returns whether this table has a primary key. - * - * @return bool - */ - public function hasPrimaryKey() - { - return $this->_primaryKeyName && $this->hasIndex($this->_primaryKeyName); - } - - /** - * Returns whether this table has an Index with the given name. - * - * @param string $indexName The index name. - * - * @return bool - */ - public function hasIndex($indexName) - { - $indexName = $this->normalizeIdentifier($indexName); - - return isset($this->_indexes[$indexName]); - } - - /** - * Returns the Index with the given name. - * - * @param string $indexName The index name. - * - * @return Index - * - * @throws SchemaException If the index does not exist. - */ - public function getIndex($indexName) - { - $indexName = $this->normalizeIdentifier($indexName); - if (! $this->hasIndex($indexName)) { - throw SchemaException::indexDoesNotExist($indexName, $this->_name); - } - - return $this->_indexes[$indexName]; - } - - /** - * @return Index[] - */ - public function getIndexes() - { - return $this->_indexes; - } - - /** - * Returns the foreign key constraints. - * - * @return ForeignKeyConstraint[] - */ - public function getForeignKeys() - { - return $this->_fkConstraints; - } - - /** - * @param string $name - * - * @return bool - */ - public function hasOption($name) - { - return isset($this->_options[$name]); - } - - /** - * @param string $name - * - * @return mixed - */ - public function getOption($name) - { - return $this->_options[$name]; - } - - /** - * @return mixed[] - */ - public function getOptions() - { - return $this->_options; - } - - /** - * @return void - */ - 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. - * - * @return void - */ - 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); - } - } - - /** - * Normalizes a given identifier. - * - * Trims quotes and lowercases the given identifier. - * - * @param string|null $identifier The identifier to normalize. - * - * @return string The normalized identifier. - */ - private function normalizeIdentifier($identifier) - { - if ($identifier === null) { - return ''; - } - - return $this->trimQuotes(strtolower($identifier)); - } - - public function setComment(?string $comment) : self - { - // For keeping backward compatibility with MySQL in previous releases, table comments are stored as options. - $this->addOption('comment', $comment); - - return $this; - } - - public function getComment() : ?string - { - return $this->_options['comment'] ?? null; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/TableDiff.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/TableDiff.php deleted file mode 100644 index 1ff2c0a..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/TableDiff.php +++ /dev/null @@ -1,152 +0,0 @@ -name = $tableName; - $this->addedColumns = $addedColumns; - $this->changedColumns = $changedColumns; - $this->removedColumns = $removedColumns; - $this->addedIndexes = $addedIndexes; - $this->changedIndexes = $changedIndexes; - $this->removedIndexes = $removedIndexes; - $this->fromTable = $fromTable; - } - - /** - * @param AbstractPlatform $platform The platform to use for retrieving this table diff's name. - * - * @return Identifier - */ - public function getName(AbstractPlatform $platform) - { - return new Identifier( - $this->fromTable instanceof Table ? $this->fromTable->getQuotedName($platform) : $this->name - ); - } - - /** - * @return Identifier|false - */ - public function getNewName() - { - if ($this->newName === false) { - return false; - } - - return new Identifier($this->newName); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/View.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/View.php deleted file mode 100644 index ac8d6cb..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/View.php +++ /dev/null @@ -1,30 +0,0 @@ -_setName($name); - $this->sql = $sql; - } - - /** - * @return string - */ - public function getSql() - { - return $this->sql; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php deleted file mode 100644 index 4716904..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/AbstractVisitor.php +++ /dev/null @@ -1,47 +0,0 @@ -platform = $platform; - } - - /** - * {@inheritdoc} - */ - public function acceptNamespace($namespaceName) - { - if (! $this->platform->supportsSchemas()) { - return; - } - - $this->createNamespaceQueries[] = $this->platform->getCreateSchemaSQL($namespaceName); - } - - /** - * {@inheritdoc} - */ - public function acceptTable(Table $table) - { - $this->createTableQueries = array_merge($this->createTableQueries, $this->platform->getCreateTableSQL($table)); - } - - /** - * {@inheritdoc} - */ - public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) - { - if (! $this->platform->supportsForeignKeyConstraints()) { - return; - } - - $this->createFkConstraintQueries[] = $this->platform->getCreateForeignKeySQL($fkConstraint, $localTable); - } - - /** - * {@inheritdoc} - */ - public function acceptSequence(Sequence $sequence) - { - $this->createSequenceQueries[] = $this->platform->getCreateSequenceSQL($sequence); - } - - /** - * @return void - */ - public function resetQueries() - { - $this->createNamespaceQueries = []; - $this->createTableQueries = []; - $this->createSequenceQueries = []; - $this->createFkConstraintQueries = []; - } - - /** - * Gets all queries collected so far. - * - * @return string[] - */ - public function getQueries() - { - return array_merge( - $this->createNamespaceQueries, - $this->createTableQueries, - $this->createSequenceQueries, - $this->createFkConstraintQueries - ); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php deleted file mode 100644 index 81e2023..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php +++ /dev/null @@ -1,99 +0,0 @@ -platform = $platform; - $this->clearQueries(); - } - - /** - * {@inheritdoc} - */ - public function acceptTable(Table $table) - { - $this->tables->attach($table); - } - - /** - * {@inheritdoc} - */ - public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) - { - if (strlen($fkConstraint->getName()) === 0) { - throw SchemaException::namedForeignKeyRequired($localTable, $fkConstraint); - } - - $this->constraints->attach($fkConstraint, $localTable); - } - - /** - * {@inheritdoc} - */ - public function acceptSequence(Sequence $sequence) - { - $this->sequences->attach($sequence); - } - - /** - * @return void - */ - public function clearQueries() - { - $this->constraints = new SplObjectStorage(); - $this->sequences = new SplObjectStorage(); - $this->tables = new SplObjectStorage(); - } - - /** - * @return string[] - */ - public function getQueries() - { - $sql = []; - - /** @var ForeignKeyConstraint $fkConstraint */ - foreach ($this->constraints as $fkConstraint) { - $localTable = $this->constraints[$fkConstraint]; - $sql[] = $this->platform->getDropForeignKeySQL($fkConstraint, $localTable); - } - - /** @var Sequence $sequence */ - foreach ($this->sequences as $sequence) { - $sql[] = $this->platform->getDropSequenceSQL($sequence); - } - - /** @var Table $table */ - foreach ($this->tables as $table) { - $sql[] = $this->platform->getDropTableSQL($table); - } - - return $sql; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Graphviz.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Graphviz.php deleted file mode 100644 index d5e94cf..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/Graphviz.php +++ /dev/null @@ -1,160 +0,0 @@ -output .= $this->createNodeRelation( - $fkConstraint->getLocalTableName() . ':col' . current($fkConstraint->getLocalColumns()) . ':se', - $fkConstraint->getForeignTableName() . ':col' . current($fkConstraint->getForeignColumns()) . ':se', - [ - 'dir' => 'back', - 'arrowtail' => 'dot', - 'arrowhead' => 'normal', - ] - ); - } - - /** - * {@inheritdoc} - */ - public function acceptSchema(Schema $schema) - { - $this->output = 'digraph "' . $schema->getName() . '" {' . "\n"; - $this->output .= 'splines = true;' . "\n"; - $this->output .= 'overlap = false;' . "\n"; - $this->output .= 'outputorder=edgesfirst;' . "\n"; - $this->output .= 'mindist = 0.6;' . "\n"; - $this->output .= 'sep = .2;' . "\n"; - } - - /** - * {@inheritdoc} - */ - public function acceptTable(Table $table) - { - $this->output .= $this->createNode( - $table->getName(), - [ - 'label' => $this->createTableLabel($table), - 'shape' => 'plaintext', - ] - ); - } - - /** - * @return string - */ - private function createTableLabel(Table $table) - { - // Start the table - $label = '<'; - - // The title - $label .= ''; - - // The attributes block - foreach ($table->getColumns() as $column) { - $columnLabel = $column->getName(); - - $label .= ''; - $label .= ''; - $label .= ''; - } - - // End the table - $label .= '
    ' . $table->getName() . '
    '; - $label .= '' . $columnLabel . ''; - $label .= '' . strtolower($column->getType()) . ''; - - $primaryKey = $table->getPrimaryKey(); - - if ($primaryKey !== null && in_array($column->getName(), $primaryKey->getColumns())) { - $label .= "\xe2\x9c\xb7"; - } - $label .= '
    >'; - - return $label; - } - - /** - * @param string $name - * @param string[] $options - * - * @return string - */ - private function createNode($name, $options) - { - $node = $name . ' ['; - foreach ($options as $key => $value) { - $node .= $key . '=' . $value . ' '; - } - $node .= "]\n"; - - return $node; - } - - /** - * @param string $node1 - * @param string $node2 - * @param string[] $options - * - * @return string - */ - private function createNodeRelation($node1, $node2, $options) - { - $relation = $node1 . ' -> ' . $node2 . ' ['; - foreach ($options as $key => $value) { - $relation .= $key . '=' . $value . ' '; - } - $relation .= "]\n"; - - return $relation; - } - - /** - * Get Graphviz Output - * - * @return string - */ - public function getOutput() - { - return $this->output . '}'; - } - - /** - * Writes dot language output to a file. This should usually be a *.dot file. - * - * You have to convert the output into a viewable format. For example use "neato" on linux systems - * and execute: - * - * neato -Tpng -o er.png er.dot - * - * @param string $filename - * - * @return void - */ - public function write($filename) - { - file_put_contents($filename, $this->getOutput()); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/NamespaceVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/NamespaceVisitor.php deleted file mode 100644 index 186fe1b..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/NamespaceVisitor.php +++ /dev/null @@ -1,16 +0,0 @@ -schema = $schema; - } - - /** - * {@inheritdoc} - */ - public function acceptTable(Table $table) - { - if ($table->isInDefaultNamespace($this->schema->getName())) { - return; - } - - $this->schema->dropTable($table->getName()); - } - - /** - * {@inheritdoc} - */ - public function acceptSequence(Sequence $sequence) - { - if ($sequence->isInDefaultNamespace($this->schema->getName())) { - return; - } - - $this->schema->dropSequence($sequence->getName()); - } - - /** - * {@inheritdoc} - */ - public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) - { - // The table may already be deleted in a previous - // RemoveNamespacedAssets#acceptTable call. Removing Foreign keys that - // point to nowhere. - if (! $this->schema->hasTable($fkConstraint->getForeignTableName())) { - $localTable->removeForeignKey($fkConstraint->getName()); - - return; - } - - $foreignTable = $this->schema->getTable($fkConstraint->getForeignTableName()); - if ($foreignTable->isInDefaultNamespace($this->schema->getName())) { - return; - } - - $localTable->removeForeignKey($fkConstraint->getName()); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/SchemaDiffVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/SchemaDiffVisitor.php deleted file mode 100644 index 5ec843d..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Schema/Visitor/SchemaDiffVisitor.php +++ /dev/null @@ -1,39 +0,0 @@ - "client" to the ShardChoser interface. - * - An exception is thrown if trying to switch shards during an open - * transaction. - * - * Instantiation through the DriverManager looks like: - * - * @example - * - * $conn = DriverManager::getConnection(array( - * 'wrapperClass' => 'Doctrine\DBAL\Sharding\PoolingShardConnection', - * 'driver' => 'pdo_mysql', - * 'global' => array('user' => '', 'password' => '', 'host' => '', 'dbname' => ''), - * 'shards' => array( - * array('id' => 1, 'user' => 'slave1', 'password', 'host' => '', 'dbname' => ''), - * array('id' => 2, 'user' => 'slave2', 'password', 'host' => '', 'dbname' => ''), - * ), - * 'shardChoser' => 'Doctrine\DBAL\Sharding\ShardChoser\MultiTenantShardChoser', - * )); - * $shardManager = $conn->getShardManager(); - * $shardManager->selectGlobal(); - * $shardManager->selectShard($value); - */ -class PoolingShardConnection extends Connection -{ - /** @var DriverConnection[] */ - private $activeConnections = []; - - /** @var string|int|null */ - private $activeShardId; - - /** @var mixed[] */ - private $connectionParameters = []; - - /** - * {@inheritDoc} - * - * @throws InvalidArgumentException - */ - public function __construct(array $params, Driver $driver, ?Configuration $config = null, ?EventManager $eventManager = null) - { - if (! isset($params['global'], $params['shards'])) { - throw new InvalidArgumentException("Connection Parameters require 'global' and 'shards' configurations."); - } - - if (! isset($params['shardChoser'])) { - throw new InvalidArgumentException("Missing Shard Choser configuration 'shardChoser'"); - } - - if (is_string($params['shardChoser'])) { - $params['shardChoser'] = new $params['shardChoser'](); - } - - if (! ($params['shardChoser'] instanceof ShardChoser)) { - throw new InvalidArgumentException("The 'shardChoser' configuration is not a valid instance of Doctrine\DBAL\Sharding\ShardChoser\ShardChoser"); - } - - $this->connectionParameters[0] = array_merge($params, $params['global']); - - foreach ($params['shards'] as $shard) { - if (! isset($shard['id'])) { - throw new InvalidArgumentException("Missing 'id' for one configured shard. Please specify a unique shard-id."); - } - - if (! is_numeric($shard['id']) || $shard['id'] < 1) { - throw new InvalidArgumentException('Shard Id has to be a non-negative number.'); - } - - if (isset($this->connectionParameters[$shard['id']])) { - throw new InvalidArgumentException('Shard ' . $shard['id'] . ' is duplicated in the configuration.'); - } - - $this->connectionParameters[$shard['id']] = array_merge($params, $shard); - } - - parent::__construct($params, $driver, $config, $eventManager); - } - - /** - * Get active shard id. - * - * @return string|int|null - */ - public function getActiveShardId() - { - return $this->activeShardId; - } - - /** - * {@inheritdoc} - */ - public function getParams() - { - return $this->activeShardId ? $this->connectionParameters[$this->activeShardId] : $this->connectionParameters[0]; - } - - /** - * {@inheritdoc} - */ - public function getHost() - { - $params = $this->getParams(); - - return $params['host'] ?? parent::getHost(); - } - - /** - * {@inheritdoc} - */ - public function getPort() - { - $params = $this->getParams(); - - return $params['port'] ?? parent::getPort(); - } - - /** - * {@inheritdoc} - */ - public function getUsername() - { - $params = $this->getParams(); - - return $params['user'] ?? parent::getUsername(); - } - - /** - * {@inheritdoc} - */ - public function getPassword() - { - $params = $this->getParams(); - - return $params['password'] ?? parent::getPassword(); - } - - /** - * Connects to a given shard. - * - * @param string|int|null $shardId - * - * @return bool - * - * @throws ShardingException - */ - public function connect($shardId = null) - { - if ($shardId === null && $this->_conn) { - return false; - } - - if ($shardId !== null && $shardId === $this->activeShardId) { - return false; - } - - if ($this->getTransactionNestingLevel() > 0) { - throw new ShardingException('Cannot switch shard when transaction is active.'); - } - - $activeShardId = $this->activeShardId = (int) $shardId; - - if (isset($this->activeConnections[$activeShardId])) { - $this->_conn = $this->activeConnections[$activeShardId]; - - return false; - } - - $this->_conn = $this->activeConnections[$activeShardId] = $this->connectTo($activeShardId); - - if ($this->_eventManager->hasListeners(Events::postConnect)) { - $eventArgs = new ConnectionEventArgs($this); - $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); - } - - return true; - } - - /** - * Connects to a specific connection. - * - * @param string|int $shardId - * - * @return \Doctrine\DBAL\Driver\Connection - */ - protected function connectTo($shardId) - { - $params = $this->getParams(); - - $driverOptions = $params['driverOptions'] ?? []; - - $connectionParams = $this->connectionParameters[$shardId]; - - $user = $connectionParams['user'] ?? null; - $password = $connectionParams['password'] ?? null; - - return $this->_driver->connect($connectionParams, $user, $password, $driverOptions); - } - - /** - * @param string|int|null $shardId - * - * @return bool - */ - public function isConnected($shardId = null) - { - if ($shardId === null) { - return $this->_conn !== null; - } - - return isset($this->activeConnections[$shardId]); - } - - /** - * @return void - */ - public function close() - { - $this->_conn = null; - $this->activeConnections = []; - $this->activeShardId = null; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php deleted file mode 100644 index 5edc56b..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/PoolingShardManager.php +++ /dev/null @@ -1,101 +0,0 @@ -getParams(); - $this->conn = $conn; - $this->choser = $params['shardChoser']; - } - - /** - * {@inheritDoc} - */ - public function selectGlobal() - { - $this->conn->connect(0); - $this->currentDistributionValue = null; - } - - /** - * {@inheritDoc} - */ - public function selectShard($distributionValue) - { - $shardId = $this->choser->pickShard($distributionValue, $this->conn); - $this->conn->connect($shardId); - $this->currentDistributionValue = $distributionValue; - } - - /** - * {@inheritDoc} - */ - public function getCurrentDistributionValue() - { - return $this->currentDistributionValue; - } - - /** - * {@inheritDoc} - */ - public function getShards() - { - $params = $this->conn->getParams(); - $shards = []; - - foreach ($params['shards'] as $shard) { - $shards[] = ['id' => $shard['id']]; - } - - return $shards; - } - - /** - * {@inheritDoc} - * - * @throws RuntimeException - */ - public function queryAll($sql, array $params, array $types) - { - $shards = $this->getShards(); - if (! $shards) { - throw new RuntimeException('No shards found.'); - } - - $result = []; - $oldDistribution = $this->getCurrentDistributionValue(); - - foreach ($shards as $shard) { - $this->conn->connect($shard['id']); - foreach ($this->conn->fetchAll($sql, $params, $types) as $row) { - $result[] = $row; - } - } - - if ($oldDistribution === null) { - $this->selectGlobal(); - } else { - $this->selectShard($oldDistribution); - } - - return $result; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php deleted file mode 100644 index 417f674..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php +++ /dev/null @@ -1,271 +0,0 @@ -shardManager = $shardManager; - $this->synchronizer = $sync ?: new SingleDatabaseSynchronizer($conn); - } - - /** - * {@inheritdoc} - */ - public function getCreateSchema(Schema $createSchema) - { - $sql = []; - - [$global, $federation] = $this->partitionSchema($createSchema); - - $globalSql = $this->synchronizer->getCreateSchema($global); - if ($globalSql) { - $sql[] = "-- Create Root Federation\n" . - 'USE FEDERATION ROOT WITH RESET;'; - $sql = array_merge($sql, $globalSql); - } - - $federationSql = $this->synchronizer->getCreateSchema($federation); - - if ($federationSql) { - $defaultValue = $this->getFederationTypeDefaultValue(); - - $sql[] = $this->getCreateFederationStatement(); - $sql[] = 'USE FEDERATION ' . $this->shardManager->getFederationName() . ' (' . $this->shardManager->getDistributionKey() . ' = ' . $defaultValue . ') WITH RESET, FILTERING = OFF;'; - $sql = array_merge($sql, $federationSql); - } - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function getUpdateSchema(Schema $toSchema, $noDrops = false) - { - return $this->work($toSchema, static function ($synchronizer, $schema) use ($noDrops) { - return $synchronizer->getUpdateSchema($schema, $noDrops); - }); - } - - /** - * {@inheritdoc} - */ - public function getDropSchema(Schema $dropSchema) - { - return $this->work($dropSchema, static function ($synchronizer, $schema) { - return $synchronizer->getDropSchema($schema); - }); - } - - /** - * {@inheritdoc} - */ - public function createSchema(Schema $createSchema) - { - $this->processSql($this->getCreateSchema($createSchema)); - } - - /** - * {@inheritdoc} - */ - public function updateSchema(Schema $toSchema, $noDrops = false) - { - $this->processSql($this->getUpdateSchema($toSchema, $noDrops)); - } - - /** - * {@inheritdoc} - */ - public function dropSchema(Schema $dropSchema) - { - $this->processSqlSafely($this->getDropSchema($dropSchema)); - } - - /** - * {@inheritdoc} - */ - public function getDropAllSchema() - { - $this->shardManager->selectGlobal(); - $globalSql = $this->synchronizer->getDropAllSchema(); - - if ($globalSql) { - $sql[] = "-- Work on Root Federation\nUSE FEDERATION ROOT WITH RESET;"; - $sql = array_merge($sql, $globalSql); - } - - $shards = $this->shardManager->getShards(); - foreach ($shards as $shard) { - $this->shardManager->selectShard($shard['rangeLow']); - - $federationSql = $this->synchronizer->getDropAllSchema(); - if (! $federationSql) { - continue; - } - - $sql[] = '-- Work on Federation ID ' . $shard['id'] . "\n" . - 'USE FEDERATION ' . $this->shardManager->getFederationName() . ' (' . $this->shardManager->getDistributionKey() . ' = ' . $shard['rangeLow'] . ') WITH RESET, FILTERING = OFF;'; - $sql = array_merge($sql, $federationSql); - } - - $sql[] = 'USE FEDERATION ROOT WITH RESET;'; - $sql[] = 'DROP FEDERATION ' . $this->shardManager->getFederationName(); - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function dropAllSchema() - { - $this->processSqlSafely($this->getDropAllSchema()); - } - - /** - * @return Schema[] - */ - private function partitionSchema(Schema $schema) - { - return [ - $this->extractSchemaFederation($schema, false), - $this->extractSchemaFederation($schema, true), - ]; - } - - /** - * @param bool $isFederation - * - * @return Schema - * - * @throws RuntimeException - */ - private function extractSchemaFederation(Schema $schema, $isFederation) - { - $partitionedSchema = clone $schema; - - foreach ($partitionedSchema->getTables() as $table) { - if ($isFederation) { - $table->addOption(self::FEDERATION_DISTRIBUTION_NAME, $this->shardManager->getDistributionKey()); - } - - if ($table->hasOption(self::FEDERATION_TABLE_FEDERATED) !== $isFederation) { - $partitionedSchema->dropTable($table->getName()); - } else { - foreach ($table->getForeignKeys() as $fk) { - $foreignTable = $schema->getTable($fk->getForeignTableName()); - if ($foreignTable->hasOption(self::FEDERATION_TABLE_FEDERATED) !== $isFederation) { - throw new RuntimeException('Cannot have foreign key between global/federation.'); - } - } - } - } - - return $partitionedSchema; - } - - /** - * Work on the Global/Federation based on currently existing shards and - * perform the given operation on the underlying schema synchronizer given - * the different partitioned schema instances. - * - * @return string[] - */ - private function work(Schema $schema, Closure $operation) - { - [$global, $federation] = $this->partitionSchema($schema); - $sql = []; - - $this->shardManager->selectGlobal(); - $globalSql = $operation($this->synchronizer, $global); - - if ($globalSql) { - $sql[] = "-- Work on Root Federation\nUSE FEDERATION ROOT WITH RESET;"; - $sql = array_merge($sql, $globalSql); - } - - $shards = $this->shardManager->getShards(); - - foreach ($shards as $shard) { - $this->shardManager->selectShard($shard['rangeLow']); - - $federationSql = $operation($this->synchronizer, $federation); - if (! $federationSql) { - continue; - } - - $sql[] = '-- Work on Federation ID ' . $shard['id'] . "\n" . - 'USE FEDERATION ' . $this->shardManager->getFederationName() . ' (' . $this->shardManager->getDistributionKey() . ' = ' . $shard['rangeLow'] . ') WITH RESET, FILTERING = OFF;'; - $sql = array_merge($sql, $federationSql); - } - - return $sql; - } - - /** - * @return string - */ - private function getFederationTypeDefaultValue() - { - $federationType = Type::getType($this->shardManager->getDistributionType()); - - switch ($federationType->getName()) { - case Types::GUID: - $defaultValue = '00000000-0000-0000-0000-000000000000'; - break; - case Types::INTEGER: - case Types::SMALLINT: - case Types::BIGINT: - $defaultValue = '0'; - break; - default: - $defaultValue = ''; - break; - } - - return $defaultValue; - } - - /** - * @return string - */ - private function getCreateFederationStatement() - { - $federationType = Type::getType($this->shardManager->getDistributionType()); - $federationTypeSql = $federationType->getSQLDeclaration([], $this->conn->getDatabasePlatform()); - - return "--Create Federation\n" . - 'CREATE FEDERATION ' . $this->shardManager->getFederationName() . ' (' . $this->shardManager->getDistributionKey() . ' ' . $federationTypeSql . ' RANGE)'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php deleted file mode 100644 index d8178ee..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php +++ /dev/null @@ -1,208 +0,0 @@ -conn = $conn; - $params = $conn->getParams(); - - if (! isset($params['sharding']['federationName'])) { - throw ShardingException::missingDefaultFederationName(); - } - - if (! isset($params['sharding']['distributionKey'])) { - throw ShardingException::missingDefaultDistributionKey(); - } - - if (! isset($params['sharding']['distributionType'])) { - throw ShardingException::missingDistributionType(); - } - - $this->federationName = $params['sharding']['federationName']; - $this->distributionKey = $params['sharding']['distributionKey']; - $this->distributionType = $params['sharding']['distributionType']; - $this->filteringEnabled = (bool) ($params['sharding']['filteringEnabled'] ?? false); - } - - /** - * Gets the name of the federation. - * - * @return string - */ - public function getFederationName() - { - return $this->federationName; - } - - /** - * Gets the distribution key. - * - * @return string - */ - public function getDistributionKey() - { - return $this->distributionKey; - } - - /** - * Gets the Doctrine Type name used for the distribution. - * - * @return string - */ - public function getDistributionType() - { - return $this->distributionType; - } - - /** - * Sets Enabled/Disable filtering on the fly. - * - * @param bool $flag - * - * @return void - */ - public function setFilteringEnabled($flag) - { - $this->filteringEnabled = (bool) $flag; - } - - /** - * {@inheritDoc} - */ - public function selectGlobal() - { - if ($this->conn->isTransactionActive()) { - throw ShardingException::activeTransaction(); - } - - $sql = 'USE FEDERATION ROOT WITH RESET'; - $this->conn->exec($sql); - $this->currentDistributionValue = null; - } - - /** - * {@inheritDoc} - */ - public function selectShard($distributionValue) - { - if ($this->conn->isTransactionActive()) { - throw ShardingException::activeTransaction(); - } - - $platform = $this->conn->getDatabasePlatform(); - $sql = sprintf( - 'USE FEDERATION %s (%s = %s) WITH RESET, FILTERING = %s;', - $platform->quoteIdentifier($this->federationName), - $platform->quoteIdentifier($this->distributionKey), - $this->conn->quote($distributionValue), - ($this->filteringEnabled ? 'ON' : 'OFF') - ); - - $this->conn->exec($sql); - $this->currentDistributionValue = $distributionValue; - } - - /** - * {@inheritDoc} - */ - public function getCurrentDistributionValue() - { - return $this->currentDistributionValue; - } - - /** - * {@inheritDoc} - */ - public function getShards() - { - $sql = 'SELECT member_id as id, - distribution_name as distribution_key, - CAST(range_low AS CHAR) AS rangeLow, - CAST(range_high AS CHAR) AS rangeHigh - FROM sys.federation_member_distributions d - INNER JOIN sys.federations f ON f.federation_id = d.federation_id - WHERE f.name = ' . $this->conn->quote($this->federationName); - - return $this->conn->fetchAll($sql); - } - - /** - * {@inheritDoc} - */ - public function queryAll($sql, array $params = [], array $types = []) - { - $shards = $this->getShards(); - if (! $shards) { - throw new RuntimeException('No shards found for ' . $this->federationName); - } - - $result = []; - $oldDistribution = $this->getCurrentDistributionValue(); - - foreach ($shards as $shard) { - $this->selectShard($shard['rangeLow']); - foreach ($this->conn->fetchAll($sql, $params, $types) as $row) { - $result[] = $row; - } - } - - if ($oldDistribution === null) { - $this->selectGlobal(); - } else { - $this->selectShard($oldDistribution); - } - - return $result; - } - - /** - * Splits Federation at a given distribution value. - * - * @param mixed $splitDistributionValue - * - * @return void - */ - public function splitFederation($splitDistributionValue) - { - $type = Type::getType($this->distributionType); - - $sql = 'ALTER FEDERATION ' . $this->getFederationName() . ' ' . - 'SPLIT AT (' . $this->getDistributionKey() . ' = ' . - $this->conn->quote($splitDistributionValue, $type->getBindingType()) . ')'; - $this->conn->exec($sql); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php deleted file mode 100644 index a83b401..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php +++ /dev/null @@ -1,148 +0,0 @@ -excludedTables = $excludedTables; - $this->tenantColumnName = $tenantColumnName; - $this->distributionName = $distributionName ?: $tenantColumnName; - } - - /** - * {@inheritdoc} - */ - public function acceptTable(Table $table) - { - if (in_array($table->getName(), $this->excludedTables)) { - return; - } - - $table->addColumn($this->tenantColumnName, $this->tenantColumnType, [ - 'default' => "federation_filtering_value('" . $this->distributionName . "')", - ]); - - $clusteredIndex = $this->getClusteredIndex($table); - - $indexColumns = $clusteredIndex->getColumns(); - $indexColumns[] = $this->tenantColumnName; - - if ($clusteredIndex->isPrimary()) { - $table->dropPrimaryKey(); - $table->setPrimaryKey($indexColumns); - } else { - $table->dropIndex($clusteredIndex->getName()); - $table->addIndex($indexColumns, $clusteredIndex->getName()); - $table->getIndex($clusteredIndex->getName())->addFlag('clustered'); - } - } - - /** - * @param Table $table - * - * @return Index - * - * @throws RuntimeException - */ - private function getClusteredIndex($table) - { - foreach ($table->getIndexes() as $index) { - if ($index->isPrimary() && ! $index->hasFlag('nonclustered')) { - return $index; - } - - if ($index->hasFlag('clustered')) { - return $index; - } - } - throw new RuntimeException('No clustered index found on table ' . $table->getName()); - } - - /** - * {@inheritdoc} - */ - public function acceptSchema(Schema $schema) - { - } - - /** - * {@inheritdoc} - */ - public function acceptColumn(Table $table, Column $column) - { - } - - /** - * {@inheritdoc} - */ - public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) - { - } - - /** - * {@inheritdoc} - */ - public function acceptIndex(Table $table, Index $index) - { - } - - /** - * {@inheritdoc} - */ - public function acceptSequence(Sequence $sequence) - { - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php deleted file mode 100644 index 584e815..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php +++ /dev/null @@ -1,20 +0,0 @@ -Statement for the given SQL and Connection. - * - * @param string $sql The SQL of the statement. - * @param Connection $conn 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 string|int $name The name or position of the parameter. - * @param mixed $value The value of the parameter. - * @param mixed $type Either a PDO binding type or a DBAL mapping type name or instance. - * - * @return bool TRUE on success, FALSE on failure. - */ - public function bindValue($name, $value, $type = ParameterType::STRING) - { - $this->params[$name] = $value; - $this->types[$name] = $type; - 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; - } - - return $this->stmt->bindValue($name, $value, $bindingType); - } - - 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|int $name The name or position of the parameter. - * @param mixed $var The reference to the variable to bind. - * @param int $type The PDO binding type. - * @param int|null $length Must be specified when using an OUT bind - * so that PHP allocates enough memory to hold the returned value. - * - * @return bool TRUE on success, FALSE on failure. - */ - public function bindParam($name, &$var, $type = ParameterType::STRING, $length = null) - { - $this->params[$name] = $var; - $this->types[$name] = $type; - - return $this->stmt->bindParam($name, $var, $type, $length); - } - - /** - * Executes the statement with the currently bound parameters. - * - * @param mixed[]|null $params - * - * @return bool TRUE on success, FALSE on failure. - * - * @throws DBALException - */ - public function execute($params = null) - { - if (is_array($params)) { - $this->params = $params; - } - - $logger = $this->conn->getConfiguration()->getSQLLogger(); - if ($logger) { - $logger->startQuery($this->sql, $this->params, $this->types); - } - - try { - $stmt = $this->stmt->execute($params); - } catch (Throwable $ex) { - if ($logger) { - $logger->stopQuery(); - } - throw DBALException::driverExceptionDuringQuery( - $this->conn->getDriver(), - $ex, - $this->sql, - $this->conn->resolveParams($this->params, $this->types) - ); - } - - if ($logger) { - $logger->stopQuery(); - } - $this->params = []; - $this->types = []; - - return $stmt; - } - - /** - * Closes the cursor, freeing the database resources used by this statement. - * - * @return bool TRUE on success, FALSE on failure. - */ - public function closeCursor() - { - return $this->stmt->closeCursor(); - } - - /** - * Returns the number of columns in the result set. - * - * @return int - */ - public function columnCount() - { - return $this->stmt->columnCount(); - } - - /** - * Fetches the SQLSTATE associated with the last operation on the statement. - * - * @return string|int|bool - */ - public function errorCode() - { - return $this->stmt->errorCode(); - } - - /** - * {@inheritDoc} - */ - public function errorInfo() - { - return $this->stmt->errorInfo(); - } - - /** - * {@inheritdoc} - */ - public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) - { - if ($arg2 === null) { - return $this->stmt->setFetchMode($fetchMode); - } - - if ($arg3 === null) { - return $this->stmt->setFetchMode($fetchMode, $arg2); - } - - return $this->stmt->setFetchMode($fetchMode, $arg2, $arg3); - } - - /** - * Required by interface IteratorAggregate. - * - * {@inheritdoc} - */ - public function getIterator() - { - return $this->stmt; - } - - /** - * {@inheritdoc} - */ - public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) - { - return $this->stmt->fetch($fetchMode); - } - - /** - * {@inheritdoc} - */ - public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) - { - if ($fetchArgument) { - return $this->stmt->fetchAll($fetchMode, $fetchArgument); - } - - return $this->stmt->fetchAll($fetchMode); - } - - /** - * {@inheritDoc} - */ - public function fetchColumn($columnIndex = 0) - { - return $this->stmt->fetchColumn($columnIndex); - } - - /** - * Returns the number of rows affected by the last execution of this statement. - * - * @return int 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; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php deleted file mode 100644 index 0cd2999..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php +++ /dev/null @@ -1,138 +0,0 @@ -setName('dbal:import') - ->setDescription('Import SQL file(s) directly to Database.') - ->setDefinition([new InputArgument( - 'file', - InputArgument::REQUIRED | InputArgument::IS_ARRAY, - 'File path(s) of SQL to be executed.' - ), - ]) - ->setHelp(<<getHelper('db')->getConnection(); - - $fileNames = $input->getArgument('file'); - - if ($fileNames === null) { - return 0; - } - - foreach ((array) $fileNames as $fileName) { - $filePath = realpath($fileName); - - // Phar compatibility. - if ($filePath === false) { - $filePath = $fileName; - } - - if (! file_exists($filePath)) { - throw new InvalidArgumentException( - sprintf("SQL file '%s' does not exist.", $filePath) - ); - } - - if (! is_readable($filePath)) { - throw new InvalidArgumentException( - sprintf("SQL file '%s' does not have read permissions.", $filePath) - ); - } - - $output->write(sprintf("Processing file '%s'... ", $filePath)); - $sql = @file_get_contents($filePath); - - if ($sql === false) { - throw new RuntimeException( - sprintf("Unable to read SQL file '%s': %s", $filePath, error_get_last()['message']) - ); - } - - if ($conn instanceof PDOConnection) { - // PDO Drivers - try { - $lines = 0; - - $stmt = $conn->prepare($sql); - assert($stmt instanceof PDOStatement); - - $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) { - $error = $stmt->errorInfo(); - - $output->write('error!' . PHP_EOL); - - throw new RuntimeException($error[2], $error[0]); - } - - $output->writeln('OK!' . PHP_EOL); - - $stmt->closeCursor(); - } - } - - return 0; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php deleted file mode 100644 index 2e0c48a..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php +++ /dev/null @@ -1,181 +0,0 @@ - MySQLKeywords::class, - 'mysql57' => MySQL57Keywords::class, - 'mysql80' => MySQL80Keywords::class, - 'sqlserver' => SQLServerKeywords::class, - 'sqlserver2005' => SQLServer2005Keywords::class, - 'sqlserver2008' => SQLServer2008Keywords::class, - 'sqlserver2012' => SQLServer2012Keywords::class, - 'sqlite' => SQLiteKeywords::class, - 'pgsql' => PostgreSQLKeywords::class, - 'pgsql91' => PostgreSQL91Keywords::class, - 'pgsql92' => PostgreSQL92Keywords::class, - 'oracle' => OracleKeywords::class, - 'db2' => DB2Keywords::class, - 'sqlanywhere' => SQLAnywhereKeywords::class, - 'sqlanywhere11' => SQLAnywhere11Keywords::class, - 'sqlanywhere12' => SQLAnywhere12Keywords::class, - 'sqlanywhere16' => SQLAnywhere16Keywords::class, - ]; - - /** - * If you want to add or replace a keywords list use this command. - * - * @param string $name - * @param string $class - * - * @return void - */ - public function setKeywordListClass($name, $class) - { - $this->keywordListClasses[$name] = $class; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setName('dbal:reserved-words') - ->setDescription('Checks if the current database contains identifiers that are reserved.') - ->setDefinition([new InputOption( - 'list', - 'l', - InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, - 'Keyword-List name.' - ), - ]) - ->setHelp(<<%command.full_name% - -If you want to check against specific dialects you can -pass them to the command: - - %command.full_name% -l mysql -l pgsql - -The following keyword lists are currently shipped with Doctrine: - - * mysql - * mysql57 - * mysql80 - * pgsql - * pgsql92 - * sqlite - * oracle - * sqlserver - * sqlserver2005 - * sqlserver2008 - * sqlserver2012 - * sqlanywhere - * sqlanywhere11 - * sqlanywhere12 - * sqlanywhere16 - * db2 (Not checked by default) -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - /** @var Connection $conn */ - $conn = $this->getHelper('db')->getConnection(); - - $keywordLists = (array) $input->getOption('list'); - if (! $keywordLists) { - $keywordLists = [ - 'mysql', - 'mysql57', - 'mysql80', - 'pgsql', - 'pgsql92', - 'sqlite', - 'oracle', - 'sqlserver', - 'sqlserver2005', - 'sqlserver2008', - 'sqlserver2012', - 'sqlanywhere', - 'sqlanywhere11', - 'sqlanywhere12', - 'sqlanywhere16', - ]; - } - - $keywords = []; - foreach ($keywordLists as $keywordList) { - if (! isset($this->keywordListClasses[$keywordList])) { - throw new InvalidArgumentException( - "There exists no keyword list with name '" . $keywordList . "'. " . - 'Known lists: ' . implode(', ', array_keys($this->keywordListClasses)) - ); - } - $class = $this->keywordListClasses[$keywordList]; - $keywords[] = new $class(); - } - - $output->write('Checking keyword violations for ' . implode(', ', $keywordLists) . '...', true); - - $schema = $conn->getSchemaManager()->createSchema(); - $visitor = new ReservedKeywordsValidator($keywords); - $schema->visit($visitor); - - $violations = $visitor->getViolations(); - if (count($violations) !== 0) { - $output->write('There are ' . count($violations) . ' reserved keyword violations in your database schema:', true); - foreach ($violations as $violation) { - $output->write(' - ' . $violation, true); - } - - return 1; - } - - $output->write('No reserved keywords violations have been found!', true); - - return 0; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php deleted file mode 100644 index b479bae..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php +++ /dev/null @@ -1,74 +0,0 @@ -setName('dbal:run-sql') - ->setDescription('Executes arbitrary SQL directly from the command line.') - ->setDefinition([ - new InputArgument('sql', InputArgument::REQUIRED, 'The SQL statement to execute.'), - new InputOption('depth', null, InputOption::VALUE_REQUIRED, 'Dumping depth of result set.', 7), - new InputOption('force-fetch', null, InputOption::VALUE_NONE, 'Forces fetching the result.'), - ]) - ->setHelp(<<getHelper('db')->getConnection(); - - $sql = $input->getArgument('sql'); - - if ($sql === null) { - throw new RuntimeException("Argument 'SQL' is required in order to execute this command correctly."); - } - - assert(is_string($sql)); - - $depth = $input->getOption('depth'); - - if (! is_numeric($depth)) { - throw new LogicException("Option 'depth' must contains an integer value"); - } - - if (stripos($sql, 'select') === 0 || $input->getOption('force-fetch')) { - $resultSet = $conn->fetchAll($sql); - } else { - $resultSet = $conn->executeUpdate($sql); - } - - $output->write(Dumper::dump($resultSet, (int) $depth)); - - return 0; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php deleted file mode 100644 index 520a9af..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Console/ConsoleRunner.php +++ /dev/null @@ -1,86 +0,0 @@ - new ConnectionHelper($connection), - ]); - } - - /** - * Runs console with the given helperset. - * - * @param Command[] $commands - * - * @return void - */ - public static function run(HelperSet $helperSet, $commands = []) - { - $cli = new Application('Doctrine Command Line Interface', Version::VERSION); - - $cli->setCatchExceptions(true); - $cli->setHelperSet($helperSet); - - self::addCommands($cli); - - $cli->addCommands($commands); - $cli->run(); - } - - /** - * @return void - */ - public static function addCommands(Application $cli) - { - $cli->addCommands([ - new RunSqlCommand(), - new ImportCommand(), - new ReservedWordsCommand(), - ]); - } - - /** - * Prints the instructions to create a configuration file - */ - public static function printCliConfigTemplate() - { - echo <<<'HELP' -You are missing a "cli-config.php" or "config/cli-config.php" file in your -project, which is required to get the Doctrine-DBAL Console working. You can use the -following sample as a template: - -_connection = $connection; - } - - /** - * Retrieves the Doctrine database Connection. - * - * @return Connection - */ - public function getConnection() - { - return $this->_connection; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'connection'; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Dumper.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Dumper.php deleted file mode 100644 index 3668efb..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Tools/Dumper.php +++ /dev/null @@ -1,182 +0,0 @@ -toArray(); - } - - if ($maxDepth === 0) { - return is_object($var) ? get_class($var) - : (is_array($var) ? 'Array(' . count($var) . ')' : $var); - } - - if (is_array($var)) { - $return = []; - - foreach ($var as $k => $v) { - $return[$k] = self::export($v, $maxDepth - 1); - } - - return $return; - } - - if (! $isObj) { - return $var; - } - - $return = new stdClass(); - if ($var instanceof DateTimeInterface) { - $return->__CLASS__ = get_class($var); - $return->date = $var->format('c'); - $return->timezone = $var->getTimezone()->getName(); - - return $return; - } - - $return->__CLASS__ = self::getClass($var); - - if ($var instanceof Proxy) { - $return->__IS_PROXY__ = true; - $return->__PROXY_INITIALIZED__ = $var->__isInitialized(); - } - - if ($var instanceof ArrayObject || $var instanceof ArrayIterator) { - $return->__STORAGE__ = self::export($var->getArrayCopy(), $maxDepth - 1); - } - - return self::fillReturnWithClassAttributes($var, $return, $maxDepth); - } - - /** - * Fill the $return variable with class attributes - * Based on obj2array function from {@see https://secure.php.net/manual/en/function.get-object-vars.php#47075} - * - * @param object $var - * - * @return mixed - */ - private static function fillReturnWithClassAttributes($var, stdClass $return, int $maxDepth) - { - $clone = (array) $var; - - foreach (array_keys($clone) as $key) { - $aux = explode("\0", $key); - $name = end($aux); - if ($aux[0] === '') { - $name .= ':' . ($aux[1] === '*' ? 'protected' : $aux[1] . ':private'); - } - $return->$name = self::export($clone[$key], $maxDepth - 1); - } - - return $return; - } - - /** - * @param object $object - */ - private static function getClass($object) : string - { - $class = get_class($object); - - if (! class_exists(Proxy::class)) { - return $class; - } - - $pos = strrpos($class, '\\' . Proxy::MARKER . '\\'); - - if ($pos === false) { - return $class; - } - - return substr($class, $pos + strlen(Proxy::MARKER) + 2); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/TransactionIsolationLevel.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/TransactionIsolationLevel.php deleted file mode 100644 index 4e35639..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/TransactionIsolationLevel.php +++ /dev/null @@ -1,32 +0,0 @@ -getClobTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToDatabaseValue($value, AbstractPlatform $platform) - { - // @todo 3.0 - $value === null check to save real NULL in database - return serialize($value); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null) { - return null; - } - - $value = is_resource($value) ? stream_get_contents($value) : $value; - - set_error_handler(function (int $code, string $message) : bool { - throw ConversionException::conversionFailedUnserialization($this->getName(), $message); - }); - - try { - return unserialize($value); - } finally { - restore_error_handler(); - } - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return Types::ARRAY; - } - - /** - * {@inheritdoc} - */ - public function requiresSQLCommentHint(AbstractPlatform $platform) - { - return true; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BigIntType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BigIntType.php deleted file mode 100644 index 69cd534..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BigIntType.php +++ /dev/null @@ -1,44 +0,0 @@ -getBigIntTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function getBindingType() - { - return ParameterType::STRING; - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - return $value === null ? null : (string) $value; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BinaryType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BinaryType.php deleted file mode 100644 index d604b3b..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BinaryType.php +++ /dev/null @@ -1,66 +0,0 @@ -getBinaryTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null) { - return null; - } - - if (is_string($value)) { - $fp = fopen('php://temp', 'rb+'); - assert(is_resource($fp)); - fwrite($fp, $value); - fseek($fp, 0); - $value = $fp; - } - - if (! is_resource($value)) { - throw ConversionException::conversionFailed($value, Types::BINARY); - } - - return $value; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return Types::BINARY; - } - - /** - * {@inheritdoc} - */ - public function getBindingType() - { - return ParameterType::BINARY; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BlobType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BlobType.php deleted file mode 100644 index e4bb22f..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BlobType.php +++ /dev/null @@ -1,66 +0,0 @@ -getBlobTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null) { - return null; - } - - if (is_string($value)) { - $fp = fopen('php://temp', 'rb+'); - assert(is_resource($fp)); - fwrite($fp, $value); - fseek($fp, 0); - $value = $fp; - } - - if (! is_resource($value)) { - throw ConversionException::conversionFailed($value, Types::BLOB); - } - - return $value; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return Types::BLOB; - } - - /** - * {@inheritdoc} - */ - public function getBindingType() - { - return ParameterType::LARGE_OBJECT; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BooleanType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BooleanType.php deleted file mode 100644 index bf9be9b..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/BooleanType.php +++ /dev/null @@ -1,52 +0,0 @@ -getBooleanTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToDatabaseValue($value, AbstractPlatform $platform) - { - return $platform->convertBooleansToDatabaseValue($value); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - return $platform->convertFromBoolean($value); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return Types::BOOLEAN; - } - - /** - * {@inheritdoc} - */ - public function getBindingType() - { - return ParameterType::BOOLEAN; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ConversionException.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ConversionException.php deleted file mode 100644 index b9f8a82..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ConversionException.php +++ /dev/null @@ -1,109 +0,0 @@ - 32 ? substr($value, 0, 20) . '...' : $value; - - return new self('Could not convert database value "' . $value . '" to Doctrine Type ' . $toType); - } - - /** - * Thrown when a Database to Doctrine Type Conversion fails and we can make a statement - * about the expected format. - * - * @param string $value - * @param string $toType - * @param string $expectedFormat - * - * @return \Doctrine\DBAL\Types\ConversionException - */ - public static function conversionFailedFormat($value, $toType, $expectedFormat, ?Throwable $previous = null) - { - $value = strlen($value) > 32 ? substr($value, 0, 20) . '...' : $value; - - return new self( - 'Could not convert database value "' . $value . '" to Doctrine Type ' . - $toType . '. Expected format: ' . $expectedFormat, - 0, - $previous - ); - } - - /** - * Thrown when the PHP value passed to the converter was not of the expected type. - * - * @param mixed $value - * @param string $toType - * @param string[] $possibleTypes - * - * @return \Doctrine\DBAL\Types\ConversionException - */ - public static function conversionFailedInvalidType($value, $toType, array $possibleTypes) - { - $actualType = is_object($value) ? get_class($value) : gettype($value); - - if (is_scalar($value)) { - return new self(sprintf( - "Could not convert PHP value '%s' of type '%s' to type '%s'. Expected one of the following types: %s", - $value, - $actualType, - $toType, - implode(', ', $possibleTypes) - )); - } - - return new self(sprintf( - "Could not convert PHP value of type '%s' to type '%s'. Expected one of the following types: %s", - $actualType, - $toType, - implode(', ', $possibleTypes) - )); - } - - public static function conversionFailedSerialization($value, $format, $error) - { - $actualType = is_object($value) ? get_class($value) : gettype($value); - - return new self(sprintf( - "Could not convert PHP type '%s' to '%s', as an '%s' error was triggered by the serialization", - $actualType, - $format, - $error - )); - } - - public static function conversionFailedUnserialization(string $format, string $error) : self - { - return new self(sprintf( - "Could not convert database value to '%s' as an error was triggered by the unserialization: '%s'", - $format, - $error - )); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateImmutableType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateImmutableType.php deleted file mode 100644 index a4c5d26..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateImmutableType.php +++ /dev/null @@ -1,70 +0,0 @@ -format($platform->getDateFormatString()); - } - - throw ConversionException::conversionFailedInvalidType( - $value, - $this->getName(), - ['null', DateTimeImmutable::class] - ); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null || $value instanceof DateTimeImmutable) { - return $value; - } - - $dateTime = DateTimeImmutable::createFromFormat('!' . $platform->getDateFormatString(), $value); - - if (! $dateTime) { - throw ConversionException::conversionFailedFormat( - $value, - $this->getName(), - $platform->getDateFormatString() - ); - } - - return $dateTime; - } - - /** - * {@inheritdoc} - */ - public function requiresSQLCommentHint(AbstractPlatform $platform) - { - return true; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateIntervalType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateIntervalType.php deleted file mode 100644 index 96a446e..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateIntervalType.php +++ /dev/null @@ -1,87 +0,0 @@ -getVarcharTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToDatabaseValue($value, AbstractPlatform $platform) - { - if ($value === null) { - return null; - } - - if ($value instanceof DateInterval) { - return $value->format(self::FORMAT); - } - - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateInterval']); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null || $value instanceof DateInterval) { - return $value; - } - - $negative = false; - - if (isset($value[0]) && ($value[0] === '+' || $value[0] === '-')) { - $negative = $value[0] === '-'; - $value = substr($value, 1); - } - - try { - $interval = new DateInterval($value); - - if ($negative) { - $interval->invert = 1; - } - - return $interval; - } catch (Throwable $exception) { - throw ConversionException::conversionFailedFormat($value, $this->getName(), self::FORMAT, $exception); - } - } - - /** - * {@inheritdoc} - */ - public function requiresSQLCommentHint(AbstractPlatform $platform) - { - return true; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeImmutableType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeImmutableType.php deleted file mode 100644 index 51960a8..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeImmutableType.php +++ /dev/null @@ -1,75 +0,0 @@ -format($platform->getDateTimeFormatString()); - } - - throw ConversionException::conversionFailedInvalidType( - $value, - $this->getName(), - ['null', DateTimeImmutable::class] - ); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null || $value instanceof DateTimeImmutable) { - return $value; - } - - $dateTime = DateTimeImmutable::createFromFormat($platform->getDateTimeFormatString(), $value); - - if (! $dateTime) { - $dateTime = date_create_immutable($value); - } - - if (! $dateTime) { - throw ConversionException::conversionFailedFormat( - $value, - $this->getName(), - $platform->getDateTimeFormatString() - ); - } - - return $dateTime; - } - - /** - * {@inheritdoc} - */ - public function requiresSQLCommentHint(AbstractPlatform $platform) - { - return true; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php deleted file mode 100644 index 65071a6..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php +++ /dev/null @@ -1,68 +0,0 @@ -getDateTimeTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToDatabaseValue($value, AbstractPlatform $platform) - { - if ($value === null) { - return $value; - } - - if ($value instanceof DateTimeInterface) { - return $value->format($platform->getDateTimeFormatString()); - } - - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateTime']); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null || $value instanceof DateTimeInterface) { - return $value; - } - - $val = DateTime::createFromFormat($platform->getDateTimeFormatString(), $value); - - if (! $val) { - $val = date_create($value); - } - - if (! $val) { - throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateTimeFormatString()); - } - - return $val; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzImmutableType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzImmutableType.php deleted file mode 100644 index b888624..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzImmutableType.php +++ /dev/null @@ -1,70 +0,0 @@ -format($platform->getDateTimeTzFormatString()); - } - - throw ConversionException::conversionFailedInvalidType( - $value, - $this->getName(), - ['null', DateTimeImmutable::class] - ); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null || $value instanceof DateTimeImmutable) { - return $value; - } - - $dateTime = DateTimeImmutable::createFromFormat($platform->getDateTimeTzFormatString(), $value); - - if (! $dateTime) { - throw ConversionException::conversionFailedFormat( - $value, - $this->getName(), - $platform->getDateTimeTzFormatString() - ); - } - - return $dateTime; - } - - /** - * {@inheritdoc} - */ - public function requiresSQLCommentHint(AbstractPlatform $platform) - { - return true; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzType.php deleted file mode 100644 index 6240da8..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeTzType.php +++ /dev/null @@ -1,75 +0,0 @@ -getDateTimeTzTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToDatabaseValue($value, AbstractPlatform $platform) - { - if ($value === null) { - return $value; - } - - if ($value instanceof DateTimeInterface) { - return $value->format($platform->getDateTimeTzFormatString()); - } - - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateTime']); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null || $value instanceof DateTimeInterface) { - return $value; - } - - $val = DateTime::createFromFormat($platform->getDateTimeTzFormatString(), $value); - if (! $val) { - throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateTimeTzFormatString()); - } - - return $val; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateType.php deleted file mode 100644 index 15d9362..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateType.php +++ /dev/null @@ -1,62 +0,0 @@ -getDateTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToDatabaseValue($value, AbstractPlatform $platform) - { - if ($value === null) { - return $value; - } - - if ($value instanceof DateTimeInterface) { - return $value->format($platform->getDateFormatString()); - } - - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateTime']); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null || $value instanceof DateTimeInterface) { - return $value; - } - - $val = DateTime::createFromFormat('!' . $platform->getDateFormatString(), $value); - if (! $val) { - throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateFormatString()); - } - - return $val; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DecimalType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DecimalType.php deleted file mode 100644 index b2d37f0..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DecimalType.php +++ /dev/null @@ -1,35 +0,0 @@ -getDecimalTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - return $value; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/FloatType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/FloatType.php deleted file mode 100644 index 4988d72..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/FloatType.php +++ /dev/null @@ -1,32 +0,0 @@ -getFloatDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - return $value === null ? null : (float) $value; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/GuidType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/GuidType.php deleted file mode 100644 index dd45165..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/GuidType.php +++ /dev/null @@ -1,35 +0,0 @@ -getGuidTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return Types::GUID; - } - - /** - * {@inheritdoc} - */ - public function requiresSQLCommentHint(AbstractPlatform $platform) - { - return ! $platform->hasNativeGuidType(); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/IntegerType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/IntegerType.php deleted file mode 100644 index d7ab8fd..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/IntegerType.php +++ /dev/null @@ -1,44 +0,0 @@ -getIntegerTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - return $value === null ? null : (int) $value; - } - - /** - * {@inheritdoc} - */ - public function getBindingType() - { - return ParameterType::INTEGER; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonArrayType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonArrayType.php deleted file mode 100644 index bc468fb..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/JsonArrayType.php +++ /dev/null @@ -1,46 +0,0 @@ -getJsonTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToDatabaseValue($value, AbstractPlatform $platform) - { - if ($value === null) { - return null; - } - - $encoded = json_encode($value); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw ConversionException::conversionFailedSerialization($value, 'json', json_last_error_msg()); - } - - return $encoded; - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null || $value === '') { - return null; - } - - if (is_resource($value)) { - $value = stream_get_contents($value); - } - - $val = json_decode($value, true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw ConversionException::conversionFailed($value, $this->getName()); - } - - return $val; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return Types::JSON; - } - - /** - * {@inheritdoc} - */ - public function requiresSQLCommentHint(AbstractPlatform $platform) - { - return ! $platform->hasNativeJsonType(); - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ObjectType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ObjectType.php deleted file mode 100644 index 82b1a75..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/ObjectType.php +++ /dev/null @@ -1,71 +0,0 @@ -getClobTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToDatabaseValue($value, AbstractPlatform $platform) - { - return serialize($value); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null) { - return null; - } - - $value = is_resource($value) ? stream_get_contents($value) : $value; - - set_error_handler(function (int $code, string $message) : bool { - throw ConversionException::conversionFailedUnserialization($this->getName(), $message); - }); - - try { - return unserialize($value); - } finally { - restore_error_handler(); - } - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return Types::OBJECT; - } - - /** - * {@inheritdoc} - */ - public function requiresSQLCommentHint(AbstractPlatform $platform) - { - return true; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/PhpDateTimeMappingType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/PhpDateTimeMappingType.php deleted file mode 100644 index 4565850..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/PhpDateTimeMappingType.php +++ /dev/null @@ -1,12 +0,0 @@ -getClobTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToDatabaseValue($value, AbstractPlatform $platform) - { - if (! $value) { - return null; - } - - return implode(',', $value); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null) { - return []; - } - - $value = is_resource($value) ? stream_get_contents($value) : $value; - - return explode(',', $value); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return Types::SIMPLE_ARRAY; - } - - /** - * {@inheritdoc} - */ - public function requiresSQLCommentHint(AbstractPlatform $platform) - { - return true; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SmallIntType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SmallIntType.php deleted file mode 100644 index 5fa3cb7..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SmallIntType.php +++ /dev/null @@ -1,44 +0,0 @@ -getSmallIntTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - return $value === null ? null : (int) $value; - } - - /** - * {@inheritdoc} - */ - public function getBindingType() - { - return ParameterType::INTEGER; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/StringType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/StringType.php deleted file mode 100644 index e0d1a55..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/StringType.php +++ /dev/null @@ -1,35 +0,0 @@ -getVarcharTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function getDefaultLength(AbstractPlatform $platform) - { - return $platform->getVarcharDefaultLength(); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return Types::STRING; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TextType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TextType.php deleted file mode 100644 index 76dd7c4..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TextType.php +++ /dev/null @@ -1,37 +0,0 @@ -getClobTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - return is_resource($value) ? stream_get_contents($value) : $value; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return Types::TEXT; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeImmutableType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeImmutableType.php deleted file mode 100644 index cc43769..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeImmutableType.php +++ /dev/null @@ -1,70 +0,0 @@ -format($platform->getTimeFormatString()); - } - - throw ConversionException::conversionFailedInvalidType( - $value, - $this->getName(), - ['null', DateTimeImmutable::class] - ); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null || $value instanceof DateTimeImmutable) { - return $value; - } - - $dateTime = DateTimeImmutable::createFromFormat('!' . $platform->getTimeFormatString(), $value); - - if (! $dateTime) { - throw ConversionException::conversionFailedFormat( - $value, - $this->getName(), - $platform->getTimeFormatString() - ); - } - - return $dateTime; - } - - /** - * {@inheritdoc} - */ - public function requiresSQLCommentHint(AbstractPlatform $platform) - { - return true; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeType.php deleted file mode 100644 index 1eeb2c0..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TimeType.php +++ /dev/null @@ -1,62 +0,0 @@ -getTimeTypeDeclarationSQL($fieldDeclaration); - } - - /** - * {@inheritdoc} - */ - public function convertToDatabaseValue($value, AbstractPlatform $platform) - { - if ($value === null) { - return $value; - } - - if ($value instanceof DateTimeInterface) { - return $value->format($platform->getTimeFormatString()); - } - - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateTime']); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null || $value instanceof DateTimeInterface) { - return $value; - } - - $val = DateTime::createFromFormat('!' . $platform->getTimeFormatString(), $value); - if (! $val) { - throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getTimeFormatString()); - } - - return $val; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php deleted file mode 100644 index ac7ab7b..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Type.php +++ /dev/null @@ -1,384 +0,0 @@ - ArrayType::class, - Types::BIGINT => BigIntType::class, - Types::BINARY => BinaryType::class, - Types::BLOB => BlobType::class, - Types::BOOLEAN => BooleanType::class, - Types::DATE_MUTABLE => DateType::class, - Types::DATE_IMMUTABLE => DateImmutableType::class, - Types::DATEINTERVAL => DateIntervalType::class, - Types::DATETIME_MUTABLE => DateTimeType::class, - Types::DATETIME_IMMUTABLE => DateTimeImmutableType::class, - Types::DATETIMETZ_MUTABLE => DateTimeTzType::class, - Types::DATETIMETZ_IMMUTABLE => DateTimeTzImmutableType::class, - Types::DECIMAL => DecimalType::class, - Types::FLOAT => FloatType::class, - Types::GUID => GuidType::class, - Types::INTEGER => IntegerType::class, - Types::JSON => JsonType::class, - Types::JSON_ARRAY => JsonArrayType::class, - Types::OBJECT => ObjectType::class, - Types::SIMPLE_ARRAY => SimpleArrayType::class, - Types::SMALLINT => SmallIntType::class, - Types::STRING => StringType::class, - Types::TEXT => TextType::class, - Types::TIME_MUTABLE => TimeType::class, - Types::TIME_IMMUTABLE => TimeImmutableType::class, - ]; - - /** @var TypeRegistry|null */ - private static $typeRegistry; - - /** - * @internal Do not instantiate directly - use {@see Type::addType()} method instead. - */ - final public 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. - * - * @deprecated Rely on information provided by the platform instead. - * - * @return int|null - */ - public function getDefaultLength(AbstractPlatform $platform) - { - return null; - } - - /** - * Gets the SQL declaration snippet for a field of this type. - * - * @param mixed[] $fieldDeclaration The field declaration. - * @param AbstractPlatform $platform The currently used database platform. - * - * @return string - */ - abstract public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform); - - /** - * Gets the name of this type. - * - * @return string - * - * @todo Needed? - */ - abstract public function getName(); - - /** - * @internal This method is only to be used within DBAL for forward compatibility purposes. Do not use directly. - */ - final public static function getTypeRegistry() : TypeRegistry - { - if (self::$typeRegistry === null) { - self::$typeRegistry = self::createTypeRegistry(); - } - - return self::$typeRegistry; - } - - private static function createTypeRegistry() : TypeRegistry - { - $registry = new TypeRegistry(); - - foreach (self::BUILTIN_TYPES_MAP as $name => $class) { - $registry->register($name, new $class()); - } - - return $registry; - } - - /** - * Factory method to create type instances. - * Type instances are implemented as flyweights. - * - * @param string $name The name of the type (as returned by getName()). - * - * @return \Doctrine\DBAL\Types\Type - * - * @throws DBALException - */ - public static function getType($name) - { - return self::getTypeRegistry()->get($name); - } - - /** - * Adds a custom type to the type map. - * - * @param string $name The name of the type. This should correspond to what getName() returns. - * @param string $className The class name of the custom type. - * - * @return void - * - * @throws DBALException - */ - public static function addType($name, $className) - { - self::getTypeRegistry()->register($name, new $className()); - } - - /** - * Checks if exists support for a type. - * - * @param string $name The name of the type. - * - * @return bool TRUE if type is supported; FALSE otherwise. - */ - public static function hasType($name) - { - return self::getTypeRegistry()->has($name); - } - - /** - * Overrides an already defined type to use a different implementation. - * - * @param string $name - * @param string $className - * - * @return void - * - * @throws DBALException - */ - public static function overrideType($name, $className) - { - self::getTypeRegistry()->override($name, new $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 {@link \Doctrine\DBAL\ParameterType} constants. - * - * @return int - */ - public function getBindingType() - { - return ParameterType::STRING; - } - - /** - * Gets the types array map which holds all registered types and the corresponding - * type class - * - * @return string[] - */ - public static function getTypesMap() - { - return array_map( - static function (Type $type) : string { - return get_class($type); - }, - self::getTypeRegistry()->getMap() - ); - } - - /** - * @deprecated Relying on string representation is discouraged and will be removed in DBAL 3.0. - * - * @return string - */ - public function __toString() - { - $type = static::class; - $position = strrpos($type, '\\'); - - if ($position !== false) { - $type = substr($type, $position); - } - - return str_replace('Type', '', $type); - } - - /** - * Does working with this column require SQL conversion functions? - * - * This is a metadata function that is required for example in the ORM. - * Usage of {@link convertToDatabaseValueSQL} and - * {@link convertToPHPValueSQL} works for any type and mostly - * does nothing. This method can additionally be used for optimization purposes. - * - * @return bool - */ - public function canRequireSQLConversion() - { - return false; - } - - /** - * Modifies the SQL expression (identifier, parameter) to convert to a database value. - * - * @param string $sqlExpr - * - * @return string - */ - public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform) - { - return $sqlExpr; - } - - /** - * Modifies the SQL expression (identifier, parameter) to convert to a PHP value. - * - * @param string $sqlExpr - * @param AbstractPlatform $platform - * - * @return string - */ - public function convertToPHPValueSQL($sqlExpr, $platform) - { - return $sqlExpr; - } - - /** - * Gets an array of database types that map to this Doctrine type. - * - * @return string[] - */ - public function getMappedDatabaseTypes(AbstractPlatform $platform) - { - return []; - } - - /** - * If this Doctrine Type maps to an already mapped database type, - * reverse schema engineering can't tell them apart. You need to mark - * one of those types as commented, which will have Doctrine use an SQL - * comment to typehint the actual Doctrine Type. - * - * @return bool - */ - public function requiresSQLCommentHint(AbstractPlatform $platform) - { - return false; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TypeRegistry.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TypeRegistry.php deleted file mode 100644 index 7e8093c..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/TypeRegistry.php +++ /dev/null @@ -1,118 +0,0 @@ - Map of type names and their corresponding flyweight objects. */ - private $instances = []; - - /** - * Finds a type by the given name. - * - * @throws DBALException - */ - public function get(string $name) : Type - { - if (! isset($this->instances[$name])) { - throw DBALException::unknownColumnType($name); - } - - return $this->instances[$name]; - } - - /** - * Finds a name for the given type. - * - * @throws DBALException - */ - public function lookupName(Type $type) : string - { - $name = $this->findTypeName($type); - - if ($name === null) { - throw DBALException::typeNotRegistered($type); - } - - return $name; - } - - /** - * Checks if there is a type of the given name. - */ - public function has(string $name) : bool - { - return isset($this->instances[$name]); - } - - /** - * Registers a custom type to the type map. - * - * @throws DBALException - */ - public function register(string $name, Type $type) : void - { - if (isset($this->instances[$name])) { - throw DBALException::typeExists($name); - } - - if ($this->findTypeName($type) !== null) { - throw DBALException::typeAlreadyRegistered($type); - } - - $this->instances[$name] = $type; - } - - /** - * Overrides an already defined type to use a different implementation. - * - * @throws DBALException - */ - public function override(string $name, Type $type) : void - { - if (! isset($this->instances[$name])) { - throw DBALException::typeNotFound($name); - } - - if (! in_array($this->findTypeName($type), [$name, null], true)) { - throw DBALException::typeAlreadyRegistered($type); - } - - $this->instances[$name] = $type; - } - - /** - * Gets the map of all registered types and their corresponding type instances. - * - * @internal - * - * @return array - */ - public function getMap() : array - { - return $this->instances; - } - - private function findTypeName(Type $type) : ?string - { - $name = array_search($type, $this->instances, true); - - if ($name === false) { - return null; - } - - return $name; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php deleted file mode 100644 index f8d0cf9..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php +++ /dev/null @@ -1,43 +0,0 @@ -format($platform->getDateTimeFormatString()); - } - - throw ConversionException::conversionFailedInvalidType( - $value, - $this->getName(), - ['null', DateTimeImmutable::class] - ); - } - - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null || $value instanceof DateTimeImmutable) { - return $value; - } - - $dateTime = date_create_immutable($value); - - if (! $dateTime) { - throw ConversionException::conversionFailed($value, $this->getName()); - } - - return $dateTime; - } - - /** - * {@inheritdoc} - */ - public function requiresSQLCommentHint(AbstractPlatform $platform) - { - return true; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeType.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeType.php deleted file mode 100644 index 1d9dbd3..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/VarDateTimeType.php +++ /dev/null @@ -1,34 +0,0 @@ - 0 it is necessary to use this type. - */ -class VarDateTimeType extends DateTimeType -{ - /** - * {@inheritdoc} - */ - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if ($value === null || $value instanceof DateTime) { - return $value; - } - - $val = date_create($value); - if (! $val) { - throw ConversionException::conversionFailed($value, $this->getName()); - } - - return $val; - } -} diff --git a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Version.php b/vendor/doctrine/dbal/lib/Doctrine/DBAL/Version.php deleted file mode 100644 index 2b1c0f2..0000000 --- a/vendor/doctrine/dbal/lib/Doctrine/DBAL/Version.php +++ /dev/null @@ -1,33 +0,0 @@ -setName('doctrine:database:create') - ->setDescription('Creates the configured database') - ->addOption('shard', null, InputOption::VALUE_REQUIRED, 'The shard connection to use for this command') - ->addOption('connection', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command') - ->addOption('if-not-exists', null, InputOption::VALUE_NONE, 'Don\'t trigger an error, when the database already exists') - ->setHelp(<<%command.name% command creates the default connections database: - - php %command.full_name% - -You can also optionally specify the name of a connection to create the database for: - - php %command.full_name% --connection=default -EOT - ); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $connectionName = $input->getOption('connection'); - if (empty($connectionName)) { - $connectionName = $this->getDoctrine()->getDefaultConnectionName(); - } - $connection = $this->getDoctrineConnection($connectionName); - - $ifNotExists = $input->getOption('if-not-exists'); - - $params = $connection->getParams(); - if (isset($params['master'])) { - $params = $params['master']; - } - - // Cannot inject `shard` option in parent::getDoctrineConnection - // cause it will try to connect to a non-existing database - if (isset($params['shards'])) { - $shards = $params['shards']; - // Default select global - $params = array_merge($params, $params['global']); - unset($params['global']['dbname'], $params['global']['path'], $params['global']['url']); - if ($input->getOption('shard')) { - foreach ($shards as $i => $shard) { - if ($shard['id'] === (int) $input->getOption('shard')) { - // Select sharded database - $params = array_merge($params, $shard); - unset($params['shards'][$i]['dbname'], $params['shards'][$i]['path'], $params['shards'][$i]['url'], $params['id']); - break; - } - } - } - } - - $hasPath = isset($params['path']); - $name = $hasPath ? $params['path'] : (isset($params['dbname']) ? $params['dbname'] : false); - if (! $name) { - throw new InvalidArgumentException("Connection does not contain a 'path' or 'dbname' parameter and cannot be created."); - } - // Need to get rid of _every_ occurrence of dbname from connection configuration and we have already extracted all relevant info from url - unset($params['dbname'], $params['path'], $params['url']); - - $tmpConnection = DriverManager::getConnection($params); - $tmpConnection->connect($input->getOption('shard')); - $shouldNotCreateDatabase = $ifNotExists && in_array($name, $tmpConnection->getSchemaManager()->listDatabases()); - - // Only quote if we don't have a path - if (! $hasPath) { - $name = $tmpConnection->getDatabasePlatform()->quoteSingleIdentifier($name); - } - - $error = false; - try { - if ($shouldNotCreateDatabase) { - $output->writeln(sprintf('Database %s for connection named %s already exists. Skipped.', $name, $connectionName)); - } else { - $tmpConnection->getSchemaManager()->createDatabase($name); - $output->writeln(sprintf('Created database %s for connection named %s', $name, $connectionName)); - } - } catch (Exception $e) { - $output->writeln(sprintf('Could not create database %s for connection named %s', $name, $connectionName)); - $output->writeln(sprintf('%s', $e->getMessage())); - $error = true; - } - - $tmpConnection->close(); - - return $error ? 1 : 0; - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/DoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/DoctrineCommand.php deleted file mode 100644 index 02ffc23..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/DoctrineCommand.php +++ /dev/null @@ -1,90 +0,0 @@ -doctrine = $doctrine; - } - - /** - * get a doctrine entity generator - * - * @return EntityGenerator - */ - protected function getEntityGenerator() - { - $entityGenerator = new EntityGenerator(); - $entityGenerator->setGenerateAnnotations(false); - $entityGenerator->setGenerateStubMethods(true); - $entityGenerator->setRegenerateEntityIfExists(false); - $entityGenerator->setUpdateEntityIfExists(true); - $entityGenerator->setNumSpaces(4); - $entityGenerator->setAnnotationPrefix('ORM\\'); - - return $entityGenerator; - } - - /** - * Get a doctrine entity manager by symfony name. - * - * @param string $name - * @param int|null $shardId - * - * @return EntityManager - */ - protected function getEntityManager($name, $shardId = null) - { - $manager = $this->getDoctrine()->getManager($name); - - if ($shardId) { - if (! $manager->getConnection() instanceof PoolingShardConnection) { - throw new LogicException(sprintf("Connection of EntityManager '%s' must implement shards configuration.", $name)); - } - - $manager->getConnection()->connect($shardId); - } - - return $manager; - } - - /** - * Get a doctrine dbal connection by symfony name. - * - * @param string $name - * - * @return Connection - */ - protected function getDoctrineConnection($name) - { - return $this->getDoctrine()->getConnection($name); - } - - /** - * @return ManagerRegistry - */ - protected function getDoctrine() - { - return $this->doctrine; - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/DropDatabaseDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/DropDatabaseDoctrineCommand.php deleted file mode 100644 index 13c0272..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/DropDatabaseDoctrineCommand.php +++ /dev/null @@ -1,128 +0,0 @@ -setName('doctrine:database:drop') - ->setDescription('Drops the configured database') - ->addOption('shard', null, InputOption::VALUE_REQUIRED, 'The shard connection to use for this command') - ->addOption('connection', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command') - ->addOption('if-exists', null, InputOption::VALUE_NONE, 'Don\'t trigger an error, when the database doesn\'t exist') - ->addOption('force', null, InputOption::VALUE_NONE, 'Set this parameter to execute this action') - ->setHelp(<<%command.name% command drops the default connections database: - - php %command.full_name% - -The --force parameter has to be used to actually drop the database. - -You can also optionally specify the name of a connection to drop the database for: - - php %command.full_name% --connection=default - -Be careful: All data in a given database will be lost when executing this command. -EOT - ); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $connectionName = $input->getOption('connection'); - if (empty($connectionName)) { - $connectionName = $this->getDoctrine()->getDefaultConnectionName(); - } - $connection = $this->getDoctrineConnection($connectionName); - - $ifExists = $input->getOption('if-exists'); - - $params = $connection->getParams(); - if (isset($params['master'])) { - $params = $params['master']; - } - - if (isset($params['shards'])) { - $shards = $params['shards']; - // Default select global - $params = array_merge($params, $params['global']); - if ($input->getOption('shard')) { - foreach ($shards as $shard) { - if ($shard['id'] === (int) $input->getOption('shard')) { - // Select sharded database - $params = $shard; - unset($params['id']); - break; - } - } - } - } - - $name = isset($params['path']) ? $params['path'] : (isset($params['dbname']) ? $params['dbname'] : false); - if (! $name) { - throw new InvalidArgumentException("Connection does not contain a 'path' or 'dbname' parameter and cannot be dropped."); - } - unset($params['dbname'], $params['url']); - - if (! $input->getOption('force')) { - $output->writeln('ATTENTION: This operation should not be executed in a production environment.'); - $output->writeln(''); - $output->writeln(sprintf('Would drop the database %s for connection named %s.', $name, $connectionName)); - $output->writeln('Please run the operation with --force to execute'); - $output->writeln('All data will be lost!'); - - return self::RETURN_CODE_NO_FORCE; - } - - // Reopen connection without database name set - // as some vendors do not allow dropping the database connected to. - $connection->close(); - $connection = DriverManager::getConnection($params); - $shouldDropDatabase = ! $ifExists || in_array($name, $connection->getSchemaManager()->listDatabases()); - - // Only quote if we don't have a path - if (! isset($params['path'])) { - $name = $connection->getDatabasePlatform()->quoteSingleIdentifier($name); - } - - try { - if ($shouldDropDatabase) { - $connection->getSchemaManager()->dropDatabase($name); - $output->writeln(sprintf('Dropped database %s for connection named %s', $name, $connectionName)); - } else { - $output->writeln(sprintf('Database %s for connection named %s doesn\'t exist. Skipped.', $name, $connectionName)); - } - - return 0; - } catch (Exception $e) { - $output->writeln(sprintf('Could not drop database %s for connection named %s', $name, $connectionName)); - $output->writeln(sprintf('%s', $e->getMessage())); - - return self::RETURN_CODE_NOT_DROP; - } - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/ImportMappingDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/ImportMappingDoctrineCommand.php deleted file mode 100644 index 79c326e..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/ImportMappingDoctrineCommand.php +++ /dev/null @@ -1,161 +0,0 @@ -bundles = $bundles; - } - - /** - * {@inheritDoc} - */ - protected function configure() - { - $this - ->setName('doctrine:mapping:import') - ->addArgument('name', InputArgument::REQUIRED, 'The bundle or namespace to import the mapping information to') - ->addArgument('mapping-type', InputArgument::OPTIONAL, 'The mapping type to export the imported mapping information to') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command') - ->addOption('shard', null, InputOption::VALUE_REQUIRED, 'The shard connection to use for this command') - ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be mapped.') - ->addOption('force', null, InputOption::VALUE_NONE, 'Force to overwrite existing mapping files.') - ->addOption('path', null, InputOption::VALUE_REQUIRED, 'The path where the files would be generated (not used when a bundle is passed).') - ->setDescription('Imports mapping information from an existing database') - ->setHelp(<<%command.name% command imports mapping information -from an existing database: - -Generate annotation mappings into the src/ directory using App as the namespace: -php %command.full_name% App\\\Entity annotation --path=src/Entity - -Generate xml mappings into the config/doctrine/ directory using App as the namespace: -php %command.full_name% App\\\Entity xml --path=config/doctrine - -Generate XML mappings into a bundle: -php %command.full_name% "MyCustomBundle" xml - -You can also optionally specify which entity manager to import from with the ---em option: - -php %command.full_name% "MyCustomBundle" xml --em=default - -If you don't want to map every entity that can be found in the database, use the ---filter option. It will try to match the targeted mapped entity with the -provided pattern string. - -php %command.full_name% "MyCustomBundle" xml --filter=MyMatchedEntity - -Use the --force option, if you want to override existing mapping files: - -php %command.full_name% "MyCustomBundle" xml --force -EOT - ); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $type = $input->getArgument('mapping-type') ?: 'xml'; - if ($type === 'yaml') { - $type = 'yml'; - } - - $namespaceOrBundle = $input->getArgument('name'); - if (isset($this->bundles[$namespaceOrBundle])) { - $bundle = $this->getApplication()->getKernel()->getBundle($namespaceOrBundle); - $namespace = $bundle->getNamespace() . '\Entity'; - - $destPath = $bundle->getPath(); - if ($type === 'annotation') { - $destPath .= '/Entity'; - } else { - $destPath .= '/Resources/config/doctrine'; - } - } else { - // assume a namespace has been passed - $namespace = $namespaceOrBundle; - $destPath = $input->getOption('path'); - if ($destPath === null) { - throw new InvalidArgumentException('The --path option is required when passing a namespace (e.g. --path=src). If you intended to pass a bundle name, check your spelling.'); - } - } - - $cme = new ClassMetadataExporter(); - $exporter = $cme->getExporter($type); - $exporter->setOverwriteExistingFiles($input->getOption('force')); - - if ($type === 'annotation') { - $entityGenerator = $this->getEntityGenerator(); - $exporter->setEntityGenerator($entityGenerator); - } - - $em = $this->getEntityManager($input->getOption('em'), $input->getOption('shard')); - - $databaseDriver = new DatabaseDriver($em->getConnection()->getSchemaManager()); - $em->getConfiguration()->setMetadataDriverImpl($databaseDriver); - - $emName = $input->getOption('em'); - $emName = $emName ? $emName : 'default'; - - $cmf = new DisconnectedClassMetadataFactory(); - $cmf->setEntityManager($em); - $metadata = $cmf->getAllMetadata(); - $metadata = MetadataFilter::filter($metadata, $input->getOption('filter')); - if ($metadata) { - $output->writeln(sprintf('Importing mapping information from "%s" entity manager', $emName)); - foreach ($metadata as $class) { - $className = $class->name; - $class->name = $namespace . '\\' . $className; - if ($type === 'annotation') { - $path = $destPath . '/' . str_replace('\\', '.', $className) . '.php'; - } else { - $path = $destPath . '/' . str_replace('\\', '.', $className) . '.orm.' . $type; - } - $output->writeln(sprintf(' > writing %s', $path)); - $code = $exporter->exportClassMetadata($class); - $dir = dirname($path); - if (! is_dir($dir)) { - mkdir($dir, 0775, true); - } - file_put_contents($path, $code); - chmod($path, 0664); - } - - return 0; - } - - $output->writeln('Database does not have any mapping information.'); - $output->writeln(''); - - return 1; - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearMetadataCacheDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearMetadataCacheDoctrineCommand.php deleted file mode 100644 index 68a213e..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearMetadataCacheDoctrineCommand.php +++ /dev/null @@ -1,37 +0,0 @@ -setName('doctrine:cache:clear-metadata') - ->setDescription('Clears all metadata cache for an entity manager') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearQueryCacheDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearQueryCacheDoctrineCommand.php deleted file mode 100644 index 0c9bed8..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearQueryCacheDoctrineCommand.php +++ /dev/null @@ -1,37 +0,0 @@ -setName('doctrine:cache:clear-query') - ->setDescription('Clears all query cache for an entity manager') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearResultCacheDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearResultCacheDoctrineCommand.php deleted file mode 100644 index 985b1b8..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/ClearResultCacheDoctrineCommand.php +++ /dev/null @@ -1,37 +0,0 @@ -setName('doctrine:cache:clear-result') - ->setDescription('Clears result cache for an entity manager') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/CollectionRegionDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/CollectionRegionDoctrineCommand.php deleted file mode 100644 index c5df015..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/CollectionRegionDoctrineCommand.php +++ /dev/null @@ -1,33 +0,0 @@ -setName('doctrine:cache:clear-collection-region') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/ConvertMappingDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/ConvertMappingDoctrineCommand.php deleted file mode 100644 index 7060d7f..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/ConvertMappingDoctrineCommand.php +++ /dev/null @@ -1,58 +0,0 @@ -setName('doctrine:mapping:convert') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } - - /** - * @param string $toType - * @param string $destPath - * - * @return AbstractExporter - */ - protected function getExporter($toType, $destPath) - { - /** @var AbstractExporter $exporter */ - $exporter = parent::getExporter($toType, $destPath); - if ($exporter instanceof XmlExporter) { - $exporter->setExtension('.orm.xml'); - } elseif ($exporter instanceof YamlExporter) { - $exporter->setExtension('.orm.yml'); - } - - return $exporter; - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/CreateSchemaDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/CreateSchemaDoctrineCommand.php deleted file mode 100644 index 937ffea..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/CreateSchemaDoctrineCommand.php +++ /dev/null @@ -1,38 +0,0 @@ -setName('doctrine:schema:create') - ->setDescription('Executes (or dumps) the SQL needed to generate the database schema') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/DelegateCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/DelegateCommand.php deleted file mode 100644 index c7f8fa7..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/DelegateCommand.php +++ /dev/null @@ -1,96 +0,0 @@ -isVersionCompatible(); - } - - /** - * @param string $entityManagerName - * - * @return Command - */ - protected function wrapCommand($entityManagerName) - { - if (! $this->isVersionCompatible()) { - throw new RuntimeException(sprintf('"%s" requires doctrine-orm "%s" or newer', $this->getName(), $this->getMinimalVersion())); - } - - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $entityManagerName); - $this->command->setApplication($this->getApplication()); - - return $this->command; - } - - /** - * {@inheritDoc} - */ - protected function configure() - { - if ($this->isVersionCompatible()) { - $this->command = $this->createCommand(); - - $this->setHelp($this->command->getHelp()); - $this->setDefinition($this->command->getDefinition()); - $this->setDescription($this->command->getDescription()); - } - - $this->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - return $this->wrapCommand($input->getOption('em'))->execute($input, $output); - } - - /** - * {@inheritDoc} - */ - protected function interact(InputInterface $input, OutputInterface $output) - { - $this->wrapCommand($input->getOption('em'))->interact($input, $output); - } - - /** - * {@inheritDoc} - */ - protected function initialize(InputInterface $input, OutputInterface $output) - { - $this->wrapCommand($input->getOption('em'))->initialize($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/DoctrineCommandHelper.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/DoctrineCommandHelper.php deleted file mode 100644 index fee03f9..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/DoctrineCommandHelper.php +++ /dev/null @@ -1,41 +0,0 @@ -getKernel()->getContainer()->get('doctrine')->getManager($emName); - $helperSet = $application->getHelperSet(); - $helperSet->set(new ConnectionHelper($em->getConnection()), 'db'); - $helperSet->set(new EntityManagerHelper($em), 'em'); - } - - /** - * Convenience method to push the helper sets of a given connection into the application. - * - * @param string $connName - */ - public static function setApplicationConnection(Application $application, $connName) - { - $connection = $application->getKernel()->getContainer()->get('doctrine')->getConnection($connName); - $helperSet = $application->getHelperSet(); - $helperSet->set(new ConnectionHelper($connection), 'db'); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/DropSchemaDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/DropSchemaDoctrineCommand.php deleted file mode 100644 index 6ef60c2..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/DropSchemaDoctrineCommand.php +++ /dev/null @@ -1,37 +0,0 @@ -setName('doctrine:schema:drop') - ->setDescription('Executes (or dumps) the SQL needed to drop the current database schema') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/EnsureProductionSettingsDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/EnsureProductionSettingsDoctrineCommand.php deleted file mode 100644 index f173d01..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/EnsureProductionSettingsDoctrineCommand.php +++ /dev/null @@ -1,36 +0,0 @@ -setName('doctrine:ensure-production-settings') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/EntityRegionCacheDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/EntityRegionCacheDoctrineCommand.php deleted file mode 100644 index 55ea3b8..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/EntityRegionCacheDoctrineCommand.php +++ /dev/null @@ -1,33 +0,0 @@ -setName('doctrine:cache:clear-entity-region') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/ImportDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/ImportDoctrineCommand.php deleted file mode 100644 index cc04abf..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/ImportDoctrineCommand.php +++ /dev/null @@ -1,36 +0,0 @@ -setName('doctrine:database:import') - ->addOption('connection', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationConnection($this->getApplication(), $input->getOption('connection')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/InfoDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/InfoDoctrineCommand.php deleted file mode 100644 index efc60b8..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/InfoDoctrineCommand.php +++ /dev/null @@ -1,34 +0,0 @@ -setName('doctrine:mapping:info') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/QueryRegionCacheDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/QueryRegionCacheDoctrineCommand.php deleted file mode 100644 index b7b761b..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/QueryRegionCacheDoctrineCommand.php +++ /dev/null @@ -1,33 +0,0 @@ -setName('doctrine:cache:clear-query-region') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/RunDqlDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/RunDqlDoctrineCommand.php deleted file mode 100644 index dc7d71d..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/RunDqlDoctrineCommand.php +++ /dev/null @@ -1,53 +0,0 @@ -setName('doctrine:query:dql') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command') - ->setHelp(<<%command.name% command executes the given DQL query and -outputs the results: - -php %command.full_name% "SELECT u FROM UserBundle:User u" - -You can also optional specify some additional options like what type of -hydration to use when executing the query: - -php %command.full_name% "SELECT u FROM UserBundle:User u" --hydrate=array - -Additionally you can specify the first result and maximum amount of results to -show: - -php %command.full_name% "SELECT u FROM UserBundle:User u" --first-result=0 --max-result=30 -EOT - ); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/RunSqlDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/RunSqlDoctrineCommand.php deleted file mode 100644 index edcc782..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/RunSqlDoctrineCommand.php +++ /dev/null @@ -1,43 +0,0 @@ -setName('doctrine:query:sql') - ->addOption('connection', null, InputOption::VALUE_OPTIONAL, 'The connection to use for this command') - ->setHelp(<<%command.name% command executes the given SQL query and -outputs the results: - -php %command.full_name% "SELECT * FROM users" -EOT - ); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationConnection($this->getApplication(), $input->getOption('connection')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/UpdateSchemaDoctrineCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/UpdateSchemaDoctrineCommand.php deleted file mode 100644 index 98f80cd..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/UpdateSchemaDoctrineCommand.php +++ /dev/null @@ -1,37 +0,0 @@ -setName('doctrine:schema:update') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Command/Proxy/ValidateSchemaCommand.php b/vendor/doctrine/doctrine-bundle/Command/Proxy/ValidateSchemaCommand.php deleted file mode 100644 index 801dd74..0000000 --- a/vendor/doctrine/doctrine-bundle/Command/Proxy/ValidateSchemaCommand.php +++ /dev/null @@ -1,36 +0,0 @@ -setName('doctrine:schema:validate') - ->addOption('em', null, InputOption::VALUE_OPTIONAL, 'The entity manager to use for this command'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - DoctrineCommandHelper::setApplicationEntityManager($this->getApplication(), $input->getOption('em')); - - return parent::execute($input, $output); - } -} diff --git a/vendor/doctrine/doctrine-bundle/ConnectionFactory.php b/vendor/doctrine/doctrine-bundle/ConnectionFactory.php deleted file mode 100644 index fdceb74..0000000 --- a/vendor/doctrine/doctrine-bundle/ConnectionFactory.php +++ /dev/null @@ -1,134 +0,0 @@ -typesConfig = $typesConfig; - } - - /** - * Create a connection by name. - * - * @param mixed[] $params - * @param string[]|Type[] $mappingTypes - * - * @return Connection - */ - public function createConnection(array $params, Configuration $config = null, EventManager $eventManager = null, array $mappingTypes = []) - { - if (! $this->initialized) { - $this->initializeTypes(); - } - - if (! isset($params['pdo']) && ! isset($params['charset'])) { - $wrapperClass = null; - if (isset($params['wrapperClass'])) { - if (! is_subclass_of($params['wrapperClass'], Connection::class)) { - throw DBALException::invalidWrapperClass($params['wrapperClass']); - } - - $wrapperClass = $params['wrapperClass']; - $params['wrapperClass'] = null; - } - - $connection = DriverManager::getConnection($params, $config, $eventManager); - $params = $connection->getParams(); - $driver = $connection->getDriver(); - - if ($driver instanceof AbstractMySQLDriver) { - $params['charset'] = 'utf8mb4'; - - if (! isset($params['defaultTableOptions']['collate'])) { - $params['defaultTableOptions']['collate'] = 'utf8mb4_unicode_ci'; - } - } else { - $params['charset'] = 'utf8'; - } - - if ($wrapperClass !== null) { - $params['wrapperClass'] = $wrapperClass; - } else { - $wrapperClass = Connection::class; - } - - $connection = new $wrapperClass($params, $driver, $config, $eventManager); - } else { - $connection = DriverManager::getConnection($params, $config, $eventManager); - } - - if (! empty($mappingTypes)) { - $platform = $this->getDatabasePlatform($connection); - foreach ($mappingTypes as $dbType => $doctrineType) { - $platform->registerDoctrineTypeMapping($dbType, $doctrineType); - } - } - - return $connection; - } - - /** - * Try to get the database platform. - * - * This could fail if types should be registered to an predefined/unused connection - * and the platform version is unknown. - * For details have a look at DoctrineBundle issue #673. - * - * @return AbstractPlatform - * - * @throws DBALException - */ - private function getDatabasePlatform(Connection $connection) - { - try { - return $connection->getDatabasePlatform(); - } catch (DriverException $driverException) { - throw new DBALException( - 'An exception occured while establishing a connection to figure out your platform version.' . PHP_EOL . - "You can circumvent this by setting a 'server_version' configuration value" . PHP_EOL . PHP_EOL . - 'For further information have a look at:' . PHP_EOL . - 'https://github.com/doctrine/DoctrineBundle/issues/673', - 0, - $driverException - ); - } - } - - /** - * initialize the types - */ - private function initializeTypes() - { - foreach ($this->typesConfig as $typeName => $typeConfig) { - if (Type::hasType($typeName)) { - Type::overrideType($typeName, $typeConfig['class']); - } else { - Type::addType($typeName, $typeConfig['class']); - } - } - - $this->initialized = true; - } -} diff --git a/vendor/doctrine/doctrine-bundle/Controller/ProfilerController.php b/vendor/doctrine/doctrine-bundle/Controller/ProfilerController.php deleted file mode 100644 index 1549d8a..0000000 --- a/vendor/doctrine/doctrine-bundle/Controller/ProfilerController.php +++ /dev/null @@ -1,120 +0,0 @@ -container = $container; - } - - /** - * Renders the profiler panel for the given token. - * - * @param string $token The profiler token - * @param string $connectionName - * @param int $query - * - * @return Response A Response instance - */ - public function explainAction($token, $connectionName, $query) - { - /** @var Profiler $profiler */ - $profiler = $this->container->get('profiler'); - $profiler->disable(); - - $profile = $profiler->loadProfile($token); - $queries = $profile->getCollector('db')->getQueries(); - - if (! isset($queries[$connectionName][$query])) { - return new Response('This query does not exist.'); - } - - $query = $queries[$connectionName][$query]; - if (! $query['explainable']) { - return new Response('This query cannot be explained.'); - } - - /** @var Connection $connection */ - $connection = $this->container->get('doctrine')->getConnection($connectionName); - try { - $platform = $connection->getDatabasePlatform(); - if ($platform instanceof SqlitePlatform) { - $results = $this->explainSQLitePlatform($connection, $query); - } elseif ($platform instanceof SQLServerPlatform) { - $results = $this->explainSQLServerPlatform($connection, $query); - } else { - $results = $this->explainOtherPlatform($connection, $query); - } - } catch (Exception $e) { - return new Response('This query cannot be explained.'); - } - - return new Response($this->container->get('twig')->render('@Doctrine/Collector/explain.html.twig', [ - 'data' => $results, - 'query' => $query, - ])); - } - - private function explainSQLitePlatform(Connection $connection, $query) - { - $params = $query['params']; - - if ($params instanceof Data) { - $params = $params->getValue(true); - } - - return $connection->executeQuery('EXPLAIN QUERY PLAN ' . $query['sql'], $params, $query['types']) - ->fetchAll(PDO::FETCH_ASSOC); - } - - private function explainSQLServerPlatform(Connection $connection, $query) - { - if (stripos($query['sql'], 'SELECT') === 0) { - $sql = 'SET STATISTICS PROFILE ON; ' . $query['sql'] . '; SET STATISTICS PROFILE OFF;'; - } else { - $sql = 'SET SHOWPLAN_TEXT ON; GO; SET NOEXEC ON; ' . $query['sql'] . '; SET NOEXEC OFF; GO; SET SHOWPLAN_TEXT OFF;'; - } - - $params = $query['params']; - - if ($params instanceof Data) { - $params = $params->getValue(true); - } - - $stmt = $connection->executeQuery($sql, $params, $query['types']); - $stmt->nextRowset(); - - return $stmt->fetchAll(PDO::FETCH_ASSOC); - } - - private function explainOtherPlatform(Connection $connection, $query) - { - $params = $query['params']; - - if ($params instanceof Data) { - $params = $params->getValue(true); - } - - return $connection->executeQuery('EXPLAIN ' . $query['sql'], $params, $query['types']) - ->fetchAll(PDO::FETCH_ASSOC); - } -} diff --git a/vendor/doctrine/doctrine-bundle/DataCollector/DoctrineDataCollector.php b/vendor/doctrine/doctrine-bundle/DataCollector/DoctrineDataCollector.php deleted file mode 100644 index 5d332a0..0000000 --- a/vendor/doctrine/doctrine-bundle/DataCollector/DoctrineDataCollector.php +++ /dev/null @@ -1,260 +0,0 @@ -registry = $registry; - - parent::__construct($registry); - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, Throwable $exception = null) - { - parent::collect($request, $response, $exception); - - $errors = []; - $entities = []; - $caches = [ - 'enabled' => false, - 'log_enabled' => false, - 'counts' => [ - 'puts' => 0, - 'hits' => 0, - 'misses' => 0, - ], - 'regions' => [ - 'puts' => [], - 'hits' => [], - 'misses' => [], - ], - ]; - - /** @var EntityManager $em */ - foreach ($this->registry->getManagers() as $name => $em) { - $entities[$name] = []; - /** @var ClassMetadataFactory $factory */ - $factory = $em->getMetadataFactory(); - $validator = new SchemaValidator($em); - - /** @var ClassMetadataInfo $class */ - foreach ($factory->getLoadedMetadata() as $class) { - if (isset($entities[$name][$class->getName()])) { - continue; - } - - $classErrors = $validator->validateClass($class); - $entities[$name][$class->getName()] = $class->getName(); - - if (empty($classErrors)) { - continue; - } - - $errors[$name][$class->getName()] = $classErrors; - } - - /** @var Configuration $emConfig */ - $emConfig = $em->getConfiguration(); - $slcEnabled = $emConfig->isSecondLevelCacheEnabled(); - - if (! $slcEnabled) { - continue; - } - - $caches['enabled'] = true; - - /** @var $cacheConfiguration \Doctrine\ORM\Cache\CacheConfiguration */ - /** @var CacheLoggerChain $cacheLoggerChain */ - $cacheConfiguration = $emConfig->getSecondLevelCacheConfiguration(); - $cacheLoggerChain = $cacheConfiguration->getCacheLogger(); - - if (! $cacheLoggerChain || ! $cacheLoggerChain->getLogger('statistics')) { - continue; - } - - /** @var StatisticsCacheLogger $cacheLoggerStats */ - $cacheLoggerStats = $cacheLoggerChain->getLogger('statistics'); - $caches['log_enabled'] = true; - - $caches['counts']['puts'] += $cacheLoggerStats->getPutCount(); - $caches['counts']['hits'] += $cacheLoggerStats->getHitCount(); - $caches['counts']['misses'] += $cacheLoggerStats->getMissCount(); - - foreach ($cacheLoggerStats->getRegionsPut() as $key => $value) { - if (! isset($caches['regions']['puts'][$key])) { - $caches['regions']['puts'][$key] = 0; - } - - $caches['regions']['puts'][$key] += $value; - } - - foreach ($cacheLoggerStats->getRegionsHit() as $key => $value) { - if (! isset($caches['regions']['hits'][$key])) { - $caches['regions']['hits'][$key] = 0; - } - - $caches['regions']['hits'][$key] += $value; - } - - foreach ($cacheLoggerStats->getRegionsMiss() as $key => $value) { - if (! isset($caches['regions']['misses'][$key])) { - $caches['regions']['misses'][$key] = 0; - } - - $caches['regions']['misses'][$key] += $value; - } - } - - // Might be good idea to replicate this block in doctrine bridge so we can drop this from here after some time. - // This code is compatible with such change, because cloneVar is supposed to check if input is already cloned. - foreach ($this->data['queries'] as &$queries) { - foreach ($queries as &$query) { - $query['params'] = $this->cloneVar($query['params']); - // To be removed when the required minimum version of symfony/doctrine-bridge is >= 4.4 - $query['runnable'] = $query['runnable'] ?? true; - } - } - - $this->data['entities'] = $entities; - $this->data['errors'] = $errors; - $this->data['caches'] = $caches; - $this->groupedQueries = null; - } - - public function getEntities() - { - return $this->data['entities']; - } - - public function getMappingErrors() - { - return $this->data['errors']; - } - - public function getCacheHitsCount() - { - return $this->data['caches']['counts']['hits']; - } - - public function getCachePutsCount() - { - return $this->data['caches']['counts']['puts']; - } - - public function getCacheMissesCount() - { - return $this->data['caches']['counts']['misses']; - } - - public function getCacheEnabled() - { - return $this->data['caches']['enabled']; - } - - public function getCacheRegions() - { - return $this->data['caches']['regions']; - } - - public function getCacheCounts() - { - return $this->data['caches']['counts']; - } - - public function getInvalidEntityCount() - { - if ($this->invalidEntityCount === null) { - $this->invalidEntityCount = array_sum(array_map('count', $this->data['errors'])); - } - - return $this->invalidEntityCount; - } - - public function getGroupedQueries() - { - if ($this->groupedQueries !== null) { - return $this->groupedQueries; - } - - $this->groupedQueries = []; - $totalExecutionMS = 0; - foreach ($this->data['queries'] as $connection => $queries) { - $connectionGroupedQueries = []; - foreach ($queries as $i => $query) { - $key = $query['sql']; - if (! isset($connectionGroupedQueries[$key])) { - $connectionGroupedQueries[$key] = $query; - $connectionGroupedQueries[$key]['executionMS'] = 0; - $connectionGroupedQueries[$key]['count'] = 0; - $connectionGroupedQueries[$key]['index'] = $i; // "Explain query" relies on query index in 'queries'. - } - $connectionGroupedQueries[$key]['executionMS'] += $query['executionMS']; - $connectionGroupedQueries[$key]['count']++; - $totalExecutionMS += $query['executionMS']; - } - usort($connectionGroupedQueries, static function ($a, $b) { - if ($a['executionMS'] === $b['executionMS']) { - return 0; - } - - return $a['executionMS'] < $b['executionMS'] ? 1 : -1; - }); - $this->groupedQueries[$connection] = $connectionGroupedQueries; - } - - foreach ($this->groupedQueries as $connection => $queries) { - foreach ($queries as $i => $query) { - $this->groupedQueries[$connection][$i]['executionPercent'] = - $this->executionTimePercentage($query['executionMS'], $totalExecutionMS); - } - } - - return $this->groupedQueries; - } - - private function executionTimePercentage($executionTimeMS, $totalExecutionTimeMS) - { - if ($totalExecutionTimeMS === 0.0 || $totalExecutionTimeMS === 0) { - return 0; - } - - return $executionTimeMS / $totalExecutionTimeMS * 100; - } - - public function getGroupedQueryCount() - { - $count = 0; - foreach ($this->getGroupedQueries() as $connectionGroupedQueries) { - $count += count($connectionGroupedQueries); - } - - return $count; - } -} diff --git a/vendor/doctrine/doctrine-bundle/Dbal/BlacklistSchemaAssetFilter.php b/vendor/doctrine/doctrine-bundle/Dbal/BlacklistSchemaAssetFilter.php deleted file mode 100644 index 493e5fb..0000000 --- a/vendor/doctrine/doctrine-bundle/Dbal/BlacklistSchemaAssetFilter.php +++ /dev/null @@ -1,29 +0,0 @@ -blacklist = $blacklist; - } - - public function __invoke($assetName) : bool - { - if ($assetName instanceof AbstractAsset) { - $assetName = $assetName->getName(); - } - - return ! in_array($assetName, $this->blacklist, true); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Dbal/Logging/BacktraceLogger.php b/vendor/doctrine/doctrine-bundle/Dbal/Logging/BacktraceLogger.php deleted file mode 100644 index 9cd2949..0000000 --- a/vendor/doctrine/doctrine-bundle/Dbal/Logging/BacktraceLogger.php +++ /dev/null @@ -1,23 +0,0 @@ -queries[$this->currentQuery]['backtrace'] = $backtrace; - } -} diff --git a/vendor/doctrine/doctrine-bundle/Dbal/RegexSchemaAssetFilter.php b/vendor/doctrine/doctrine-bundle/Dbal/RegexSchemaAssetFilter.php deleted file mode 100644 index 2a9cbf9..0000000 --- a/vendor/doctrine/doctrine-bundle/Dbal/RegexSchemaAssetFilter.php +++ /dev/null @@ -1,25 +0,0 @@ -filterExpression = $filterExpression; - } - - public function __invoke($assetName) : bool - { - if ($assetName instanceof AbstractAsset) { - $assetName = $assetName->getName(); - } - - return preg_match($this->filterExpression, $assetName); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Dbal/SchemaAssetsFilterManager.php b/vendor/doctrine/doctrine-bundle/Dbal/SchemaAssetsFilterManager.php deleted file mode 100644 index 7389a4e..0000000 --- a/vendor/doctrine/doctrine-bundle/Dbal/SchemaAssetsFilterManager.php +++ /dev/null @@ -1,31 +0,0 @@ -schemaAssetFilters = $schemaAssetFilters; - } - - public function __invoke($assetName) : bool - { - foreach ($this->schemaAssetFilters as $schemaAssetFilter) { - if ($schemaAssetFilter($assetName) === false) { - return false; - } - } - - return true; - } -} diff --git a/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DbalSchemaFilterPass.php b/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DbalSchemaFilterPass.php deleted file mode 100644 index 7b53544..0000000 --- a/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DbalSchemaFilterPass.php +++ /dev/null @@ -1,51 +0,0 @@ -findTaggedServiceIds('doctrine.dbal.schema_filter'); - - $connectionFilters = []; - foreach ($filters as $id => $tagAttributes) { - foreach ($tagAttributes as $attributes) { - $name = isset($attributes['connection']) ? $attributes['connection'] : $container->getParameter('doctrine.default_connection'); - - if (! isset($connectionFilters[$name])) { - $connectionFilters[$name] = []; - } - - $connectionFilters[$name][] = new Reference($id); - } - } - - foreach ($connectionFilters as $name => $references) { - $configurationId = sprintf('doctrine.dbal.%s_connection.configuration', $name); - - if (! $container->hasDefinition($configurationId)) { - continue; - } - - $definition = new ChildDefinition('doctrine.dbal.schema_asset_filter_manager'); - $definition->setArgument(0, $references); - - $id = sprintf('doctrine.dbal.%s_schema_asset_filter_manager', $name); - $container->setDefinition($id, $definition); - $container->findDefinition($configurationId) - ->addMethodCall('setSchemaAssetsFilter', [new Reference($id)]); - } - } -} diff --git a/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DoctrineOrmMappingsPass.php b/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DoctrineOrmMappingsPass.php deleted file mode 100644 index 56e5eca..0000000 --- a/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/DoctrineOrmMappingsPass.php +++ /dev/null @@ -1,152 +0,0 @@ -findTaggedServiceIds('doctrine.orm.entity_listener'); - - $lazyServiceReferencesByResolver = []; - - foreach ($resolvers as $id => $tagAttributes) { - foreach ($tagAttributes as $attributes) { - $name = isset($attributes['entity_manager']) ? $attributes['entity_manager'] : $container->getParameter('doctrine.default_entity_manager'); - $entityManager = sprintf('doctrine.orm.%s_entity_manager', $name); - - if (! $container->hasDefinition($entityManager)) { - continue; - } - - $resolverId = sprintf('doctrine.orm.%s_entity_listener_resolver', $name); - - if (! $container->has($resolverId)) { - continue; - } - - $resolver = $container->findDefinition($resolverId); - $resolver->setPublic(true); - - if (isset($attributes['entity']) && isset($attributes['event'])) { - $this->attachToListener($container, $name, $this->getConcreteDefinitionClass($container->findDefinition($id), $container, $id), $attributes); - } - - $resolverClass = $this->getResolverClass($resolver, $container, $resolverId); - $resolverSupportsLazyListeners = is_a($resolverClass, EntityListenerServiceResolver::class, true); - - $lazyByAttribute = isset($attributes['lazy']) && $attributes['lazy']; - if ($lazyByAttribute && ! $resolverSupportsLazyListeners) { - throw new InvalidArgumentException(sprintf( - 'Lazy-loaded entity listeners can only be resolved by a resolver implementing %s.', - EntityListenerServiceResolver::class - )); - } - - if (! isset($attributes['lazy']) && $resolverSupportsLazyListeners || $lazyByAttribute) { - $listener = $container->findDefinition($id); - - if ($listener->isAbstract()) { - throw new InvalidArgumentException(sprintf('The service "%s" must not be abstract as this entity listener is lazy-loaded.', $id)); - } - - $resolver->addMethodCall('registerService', [$this->getConcreteDefinitionClass($listener, $container, $id), $id]); - - // if the resolver uses the default class we will use a service locator for all listeners - if ($resolverClass === ContainerEntityListenerResolver::class) { - if (! isset($lazyServiceReferencesByResolver[$resolverId])) { - $lazyServiceReferencesByResolver[$resolverId] = []; - } - $lazyServiceReferencesByResolver[$resolverId][$id] = new Reference($id); - } else { - $listener->setPublic(true); - } - } else { - $resolver->addMethodCall('register', [new Reference($id)]); - } - } - } - - foreach ($lazyServiceReferencesByResolver as $resolverId => $listenerReferences) { - $container->findDefinition($resolverId)->setArgument(0, ServiceLocatorTagPass::register($container, $listenerReferences)); - } - } - - private function attachToListener(ContainerBuilder $container, $name, string $class, array $attributes) - { - $listenerId = sprintf('doctrine.orm.%s_listeners.attach_entity_listeners', $name); - - if (! $container->has($listenerId)) { - return; - } - - $args = [ - $attributes['entity'], - $class, - $attributes['event'], - ]; - - if (isset($attributes['method'])) { - $args[] = $attributes['method']; - } elseif (! method_exists($class, $attributes['event']) && method_exists($class, '__invoke')) { - $args[] = '__invoke'; - } - - $container->findDefinition($listenerId)->addMethodCall('addEntityListener', $args); - } - - private function getResolverClass(Definition $resolver, ContainerBuilder $container, string $id) : string - { - $resolverClass = $this->getConcreteDefinitionClass($resolver, $container, $id); - - if (substr($resolverClass, 0, 1) === '%') { - // resolve container parameter first - $resolverClass = $container->getParameterBag()->resolveValue($resolverClass); - } - - return $resolverClass; - } - - private function getConcreteDefinitionClass(Definition $definition, ContainerBuilder $container, string $id) : string - { - $class = $definition->getClass(); - if ($class) { - return $class; - } - - while ($definition instanceof ChildDefinition) { - $definition = $container->findDefinition($definition->getParent()); - - $class = $definition->getClass(); - if ($class) { - return $class; - } - } - - throw new InvalidArgumentException(sprintf('The service "%s" must define its class.', $id)); - } -} diff --git a/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/ServiceRepositoryCompilerPass.php b/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/ServiceRepositoryCompilerPass.php deleted file mode 100644 index 9881557..0000000 --- a/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/ServiceRepositoryCompilerPass.php +++ /dev/null @@ -1,32 +0,0 @@ -hasDefinition('doctrine.orm.container_repository_factory')) { - return; - } - - $locatorDef = $container->getDefinition('doctrine.orm.container_repository_factory'); - - $repoServiceIds = array_keys($container->findTaggedServiceIds(self::REPOSITORY_SERVICE_TAG)); - - $repoReferences = array_map(static function ($id) { - return new Reference($id); - }, $repoServiceIds); - - $ref = ServiceLocatorTagPass::register($container, array_combine($repoServiceIds, $repoReferences)); - $locatorDef->replaceArgument(0, $ref); - } -} diff --git a/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/WellKnownSchemaFilterPass.php b/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/WellKnownSchemaFilterPass.php deleted file mode 100644 index 8680df0..0000000 --- a/vendor/doctrine/doctrine-bundle/DependencyInjection/Compiler/WellKnownSchemaFilterPass.php +++ /dev/null @@ -1,59 +0,0 @@ -getDefinitions() as $definition) { - if ($definition->isAbstract() || $definition->isSynthetic()) { - continue; - } - - switch ($definition->getClass()) { - case PdoAdapter::class: - $blacklist[] = $definition->getArguments()[3]['db_table'] ?? 'cache_items'; - break; - - case PdoSessionHandler::class: - $blacklist[] = $definition->getArguments()[1]['db_table'] ?? 'sessions'; - break; - - case PdoStore::class: - $blacklist[] = $definition->getArguments()[1]['db_table'] ?? 'lock_keys'; - break; - - case Connection::class: - $blacklist[] = $definition->getArguments()[0]['table_name'] ?? 'messenger_messages'; - break; - } - } - - if (! $blacklist) { - return; - } - - $definition = $container->getDefinition('doctrine.dbal.well_known_schema_asset_filter'); - $definition->replaceArgument(0, $blacklist); - - foreach (array_keys($container->getParameter('doctrine.connections')) as $name) { - $definition->addTag('doctrine.dbal.schema_filter', ['connection' => $name]); - } - } -} diff --git a/vendor/doctrine/doctrine-bundle/DependencyInjection/Configuration.php b/vendor/doctrine/doctrine-bundle/DependencyInjection/Configuration.php deleted file mode 100644 index dac5a1b..0000000 --- a/vendor/doctrine/doctrine-bundle/DependencyInjection/Configuration.php +++ /dev/null @@ -1,702 +0,0 @@ -debug = (bool) $debug; - } - - /** - * {@inheritDoc} - */ - public function getConfigTreeBuilder() : TreeBuilder - { - $treeBuilder = new TreeBuilder('doctrine'); - $rootNode = $treeBuilder->getRootNode(); - - $this->addDbalSection($rootNode); - $this->addOrmSection($rootNode); - - return $treeBuilder; - } - - /** - * Add DBAL section to configuration tree - */ - private function addDbalSection(ArrayNodeDefinition $node) - { - $node - ->children() - ->arrayNode('dbal') - ->beforeNormalization() - ->ifTrue(static function ($v) { - return is_array($v) && ! array_key_exists('connections', $v) && ! array_key_exists('connection', $v); - }) - ->then(static function ($v) { - // Key that should not be rewritten to the connection config - $excludedKeys = ['default_connection' => true, 'types' => true, 'type' => true]; - $connection = []; - foreach ($v as $key => $value) { - if (isset($excludedKeys[$key])) { - continue; - } - $connection[$key] = $v[$key]; - unset($v[$key]); - } - $v['default_connection'] = isset($v['default_connection']) ? (string) $v['default_connection'] : 'default'; - $v['connections'] = [$v['default_connection'] => $connection]; - - return $v; - }) - ->end() - ->children() - ->scalarNode('default_connection')->end() - ->end() - ->fixXmlConfig('type') - ->children() - ->arrayNode('types') - ->useAttributeAsKey('name') - ->prototype('array') - ->beforeNormalization() - ->ifString() - ->then(static function ($v) { - return ['class' => $v]; - }) - ->end() - ->children() - ->scalarNode('class')->isRequired()->end() - ->booleanNode('commented')->setDeprecated()->end() - ->end() - ->end() - ->end() - ->end() - ->fixXmlConfig('connection') - ->append($this->getDbalConnectionsNode()) - ->end(); - } - - /** - * Return the dbal connections node - * - * @return ArrayNodeDefinition - */ - private function getDbalConnectionsNode() - { - $treeBuilder = new TreeBuilder('connections'); - $node = $treeBuilder->getRootNode(); - - /** @var ArrayNodeDefinition $connectionNode */ - $connectionNode = $node - ->requiresAtLeastOneElement() - ->useAttributeAsKey('name') - ->prototype('array'); - - $this->configureDbalDriverNode($connectionNode); - - $connectionNode - ->fixXmlConfig('option') - ->fixXmlConfig('mapping_type') - ->fixXmlConfig('slave') - ->fixXmlConfig('shard') - ->fixXmlConfig('default_table_option') - ->children() - ->scalarNode('driver')->defaultValue('pdo_mysql')->end() - ->scalarNode('platform_service')->end() - ->booleanNode('auto_commit')->end() - ->scalarNode('schema_filter')->end() - ->booleanNode('logging')->defaultValue($this->debug)->end() - ->booleanNode('profiling')->defaultValue($this->debug)->end() - ->booleanNode('profiling_collect_backtrace') - ->defaultValue(false) - ->info('Enables collecting backtraces when profiling is enabled') - ->end() - ->scalarNode('server_version')->end() - ->scalarNode('driver_class')->end() - ->scalarNode('wrapper_class')->end() - ->scalarNode('shard_manager_class')->end() - ->scalarNode('shard_choser')->end() - ->scalarNode('shard_choser_service')->end() - ->booleanNode('keep_slave')->end() - ->arrayNode('options') - ->useAttributeAsKey('key') - ->prototype('variable')->end() - ->end() - ->arrayNode('mapping_types') - ->useAttributeAsKey('name') - ->prototype('scalar')->end() - ->end() - ->arrayNode('default_table_options') - ->info("This option is used by the schema-tool and affects generated SQL. Possible keys include 'charset','collate', and 'engine'.") - ->useAttributeAsKey('name') - ->prototype('scalar')->end() - ->end() - ->end(); - - $slaveNode = $connectionNode - ->children() - ->arrayNode('slaves') - ->useAttributeAsKey('name') - ->prototype('array'); - $this->configureDbalDriverNode($slaveNode); - - $shardNode = $connectionNode - ->children() - ->arrayNode('shards') - ->prototype('array') - ->children() - ->integerNode('id') - ->min(1) - ->isRequired() - ->end() - ->end(); - $this->configureDbalDriverNode($shardNode); - - return $node; - } - - /** - * Adds config keys related to params processed by the DBAL drivers - * - * These keys are available for slave configurations too. - */ - private function configureDbalDriverNode(ArrayNodeDefinition $node) - { - $node - ->children() - ->scalarNode('url')->info('A URL with connection information; any parameter value parsed from this string will override explicitly set parameters')->end() - ->scalarNode('dbname')->end() - ->scalarNode('host')->defaultValue('localhost')->end() - ->scalarNode('port')->defaultNull()->end() - ->scalarNode('user')->defaultValue('root')->end() - ->scalarNode('password')->defaultNull()->end() - ->scalarNode('application_name')->end() - ->scalarNode('charset')->end() - ->scalarNode('path')->end() - ->booleanNode('memory')->end() - ->scalarNode('unix_socket')->info('The unix socket to use for MySQL')->end() - ->booleanNode('persistent')->info('True to use as persistent connection for the ibm_db2 driver')->end() - ->scalarNode('protocol')->info('The protocol to use for the ibm_db2 driver (default to TCPIP if ommited)')->end() - ->booleanNode('service') - ->info('True to use SERVICE_NAME as connection parameter instead of SID for Oracle') - ->end() - ->scalarNode('servicename') - ->info( - 'Overrules dbname parameter if given and used as SERVICE_NAME or SID connection parameter ' . - 'for Oracle depending on the service parameter.' - ) - ->end() - ->scalarNode('sessionMode') - ->info('The session mode to use for the oci8 driver') - ->end() - ->scalarNode('server') - ->info('The name of a running database server to connect to for SQL Anywhere.') - ->end() - ->scalarNode('default_dbname') - ->info( - 'Override the default database (postgres) to connect to for PostgreSQL connexion.' - ) - ->end() - ->scalarNode('sslmode') - ->info( - 'Determines whether or with what priority a SSL TCP/IP connection will be negotiated with ' . - 'the server for PostgreSQL.' - ) - ->end() - ->scalarNode('sslrootcert') - ->info( - 'The name of a file containing SSL certificate authority (CA) certificate(s). ' . - 'If the file exists, the server\'s certificate will be verified to be signed by one of these authorities.' - ) - ->end() - ->scalarNode('sslcert') - ->info( - 'The path to the SSL client certificate file for PostgreSQL.' - ) - ->end() - ->scalarNode('sslkey') - ->info( - 'The path to the SSL client key file for PostgreSQL.' - ) - ->end() - ->scalarNode('sslcrl') - ->info( - 'The file name of the SSL certificate revocation list for PostgreSQL.' - ) - ->end() - ->booleanNode('pooled')->info('True to use a pooled server with the oci8/pdo_oracle driver')->end() - ->booleanNode('MultipleActiveResultSets')->info('Configuring MultipleActiveResultSets for the pdo_sqlsrv driver')->end() - ->booleanNode('use_savepoints')->info('Use savepoints for nested transactions')->end() - ->scalarNode('instancename') - ->info( - 'Optional parameter, complete whether to add the INSTANCE_NAME parameter in the connection.' . - ' It is generally used to connect to an Oracle RAC server to select the name' . - ' of a particular instance.' - ) - ->end() - ->scalarNode('connectstring') - ->info( - 'Complete Easy Connect connection descriptor, see https://docs.oracle.com/database/121/NETAG/naming.htm.' . - 'When using this option, you will still need to provide the user and password parameters, but the other ' . - 'parameters will no longer be used. Note that when using this parameter, the getHost and getPort methods' . - ' from Doctrine\DBAL\Connection will no longer function as expected.' - ) - ->end() - ->end() - ->beforeNormalization() - ->ifTrue(static function ($v) { - return ! isset($v['sessionMode']) && isset($v['session_mode']); - }) - ->then(static function ($v) { - $v['sessionMode'] = $v['session_mode']; - unset($v['session_mode']); - - return $v; - }) - ->end() - ->beforeNormalization() - ->ifTrue(static function ($v) { - return ! isset($v['MultipleActiveResultSets']) && isset($v['multiple_active_result_sets']); - }) - ->then(static function ($v) { - $v['MultipleActiveResultSets'] = $v['multiple_active_result_sets']; - unset($v['multiple_active_result_sets']); - - return $v; - }) - ->end(); - } - - /** - * Add the ORM section to configuration tree - */ - private function addOrmSection(ArrayNodeDefinition $node) - { - $node - ->children() - ->arrayNode('orm') - ->beforeNormalization() - ->ifTrue(static function ($v) { - if (! empty($v) && ! class_exists(EntityManager::class)) { - throw new LogicException('The doctrine/orm package is required when the doctrine.orm config is set.'); - } - - return $v === null || (is_array($v) && ! array_key_exists('entity_managers', $v) && ! array_key_exists('entity_manager', $v)); - }) - ->then(static function ($v) { - $v = (array) $v; - // Key that should not be rewritten to the connection config - $excludedKeys = [ - 'default_entity_manager' => true, - 'auto_generate_proxy_classes' => true, - 'proxy_dir' => true, - 'proxy_namespace' => true, - 'resolve_target_entities' => true, - 'resolve_target_entity' => true, - ]; - $entityManager = []; - foreach ($v as $key => $value) { - if (isset($excludedKeys[$key])) { - continue; - } - $entityManager[$key] = $v[$key]; - unset($v[$key]); - } - $v['default_entity_manager'] = isset($v['default_entity_manager']) ? (string) $v['default_entity_manager'] : 'default'; - $v['entity_managers'] = [$v['default_entity_manager'] => $entityManager]; - - return $v; - }) - ->end() - ->children() - ->scalarNode('default_entity_manager')->end() - ->scalarNode('auto_generate_proxy_classes')->defaultValue(false) - ->info('Auto generate mode possible values are: "NEVER", "ALWAYS", "FILE_NOT_EXISTS", "EVAL"') - ->validate() - ->ifTrue(function ($v) { - $generationModes = $this->getAutoGenerateModes(); - - if (is_int($v) && in_array($v, $generationModes['values']/*array(0, 1, 2, 3)*/)) { - return false; - } - if (is_bool($v)) { - return false; - } - if (is_string($v)) { - if (in_array(strtoupper($v), $generationModes['names']/*array('NEVER', 'ALWAYS', 'FILE_NOT_EXISTS', 'EVAL')*/)) { - return false; - } - } - - return true; - }) - ->thenInvalid('Invalid auto generate mode value %s') - ->end() - ->validate() - ->ifString() - ->then(static function ($v) { - return constant('Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_' . strtoupper($v)); - }) - ->end() - ->end() - ->scalarNode('proxy_dir')->defaultValue('%kernel.cache_dir%/doctrine/orm/Proxies')->end() - ->scalarNode('proxy_namespace')->defaultValue('Proxies')->end() - ->end() - ->fixXmlConfig('entity_manager') - ->append($this->getOrmEntityManagersNode()) - ->fixXmlConfig('resolve_target_entity', 'resolve_target_entities') - ->append($this->getOrmTargetEntityResolverNode()) - ->end() - ->end(); - } - - /** - * Return ORM target entity resolver node - * - * @return NodeDefinition - */ - private function getOrmTargetEntityResolverNode() - { - $treeBuilder = new TreeBuilder('resolve_target_entities'); - $node = $treeBuilder->getRootNode(); - - $node - ->useAttributeAsKey('interface') - ->prototype('scalar') - ->cannotBeEmpty() - ->end(); - - return $node; - } - - /** - * Return ORM entity listener node - * - * @return NodeDefinition - */ - private function getOrmEntityListenersNode() - { - $treeBuilder = new TreeBuilder('entity_listeners'); - $node = $treeBuilder->getRootNode(); - - $normalizer = static function ($mappings) { - $entities = []; - - foreach ($mappings as $entityClass => $mapping) { - $listeners = []; - - foreach ($mapping as $listenerClass => $listenerEvent) { - $events = []; - - foreach ($listenerEvent as $eventType => $eventMapping) { - if ($eventMapping === null) { - $eventMapping = [null]; - } - - foreach ($eventMapping as $method) { - $events[] = [ - 'type' => $eventType, - 'method' => $method, - ]; - } - } - - $listeners[] = [ - 'class' => $listenerClass, - 'event' => $events, - ]; - } - - $entities[] = [ - 'class' => $entityClass, - 'listener' => $listeners, - ]; - } - - return ['entities' => $entities]; - }; - - $node - ->beforeNormalization() - // Yaml normalization - ->ifTrue(static function ($v) { - return is_array(reset($v)) && is_string(key(reset($v))); - }) - ->then($normalizer) - ->end() - ->fixXmlConfig('entity', 'entities') - ->children() - ->arrayNode('entities') - ->useAttributeAsKey('class') - ->prototype('array') - ->fixXmlConfig('listener') - ->children() - ->arrayNode('listeners') - ->useAttributeAsKey('class') - ->prototype('array') - ->fixXmlConfig('event') - ->children() - ->arrayNode('events') - ->prototype('array') - ->children() - ->scalarNode('type')->end() - ->scalarNode('method')->defaultNull()->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end(); - - return $node; - } - - /** - * Return ORM entity manager node - * - * @return ArrayNodeDefinition - */ - private function getOrmEntityManagersNode() - { - $treeBuilder = new TreeBuilder('entity_managers'); - $node = $treeBuilder->getRootNode(); - - $node - ->requiresAtLeastOneElement() - ->useAttributeAsKey('name') - ->prototype('array') - ->addDefaultsIfNotSet() - ->append($this->getOrmCacheDriverNode('query_cache_driver')) - ->append($this->getOrmCacheDriverNode('metadata_cache_driver')) - ->append($this->getOrmCacheDriverNode('result_cache_driver')) - ->append($this->getOrmEntityListenersNode()) - ->children() - ->scalarNode('connection')->end() - ->scalarNode('class_metadata_factory_name')->defaultValue('Doctrine\ORM\Mapping\ClassMetadataFactory')->end() - ->scalarNode('default_repository_class')->defaultValue('Doctrine\ORM\EntityRepository')->end() - ->scalarNode('auto_mapping')->defaultFalse()->end() - ->scalarNode('naming_strategy')->defaultValue('doctrine.orm.naming_strategy.default')->end() - ->scalarNode('quote_strategy')->defaultValue('doctrine.orm.quote_strategy.default')->end() - ->scalarNode('entity_listener_resolver')->defaultNull()->end() - ->scalarNode('repository_factory')->defaultValue('doctrine.orm.container_repository_factory')->end() - ->end() - ->children() - ->arrayNode('second_level_cache') - ->children() - ->append($this->getOrmCacheDriverNode('region_cache_driver')) - ->scalarNode('region_lock_lifetime')->defaultValue(60)->end() - ->booleanNode('log_enabled')->defaultValue($this->debug)->end() - ->scalarNode('region_lifetime')->defaultValue(0)->end() - ->booleanNode('enabled')->defaultValue(true)->end() - ->scalarNode('factory')->end() - ->end() - ->fixXmlConfig('region') - ->children() - ->arrayNode('regions') - ->useAttributeAsKey('name') - ->prototype('array') - ->children() - ->append($this->getOrmCacheDriverNode('cache_driver')) - ->scalarNode('lock_path')->defaultValue('%kernel.cache_dir%/doctrine/orm/slc/filelock')->end() - ->scalarNode('lock_lifetime')->defaultValue(60)->end() - ->scalarNode('type')->defaultValue('default')->end() - ->scalarNode('lifetime')->defaultValue(0)->end() - ->scalarNode('service')->end() - ->scalarNode('name')->end() - ->end() - ->end() - ->end() - ->end() - ->fixXmlConfig('logger') - ->children() - ->arrayNode('loggers') - ->useAttributeAsKey('name') - ->prototype('array') - ->children() - ->scalarNode('name')->end() - ->scalarNode('service')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->fixXmlConfig('hydrator') - ->children() - ->arrayNode('hydrators') - ->useAttributeAsKey('name') - ->prototype('scalar')->end() - ->end() - ->end() - ->fixXmlConfig('mapping') - ->children() - ->arrayNode('mappings') - ->useAttributeAsKey('name') - ->prototype('array') - ->beforeNormalization() - ->ifString() - ->then(static function ($v) { - return ['type' => $v]; - }) - ->end() - ->treatNullLike([]) - ->treatFalseLike(['mapping' => false]) - ->performNoDeepMerging() - ->children() - ->scalarNode('mapping')->defaultValue(true)->end() - ->scalarNode('type')->end() - ->scalarNode('dir')->end() - ->scalarNode('alias')->end() - ->scalarNode('prefix')->end() - ->booleanNode('is_bundle')->end() - ->end() - ->end() - ->end() - ->arrayNode('dql') - ->fixXmlConfig('string_function') - ->fixXmlConfig('numeric_function') - ->fixXmlConfig('datetime_function') - ->children() - ->arrayNode('string_functions') - ->useAttributeAsKey('name') - ->prototype('scalar')->end() - ->end() - ->arrayNode('numeric_functions') - ->useAttributeAsKey('name') - ->prototype('scalar')->end() - ->end() - ->arrayNode('datetime_functions') - ->useAttributeAsKey('name') - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->end() - ->fixXmlConfig('filter') - ->children() - ->arrayNode('filters') - ->info('Register SQL Filters in the entity manager') - ->useAttributeAsKey('name') - ->prototype('array') - ->beforeNormalization() - ->ifString() - ->then(static function ($v) { - return ['class' => $v]; - }) - ->end() - ->beforeNormalization() - // The content of the XML node is returned as the "value" key so we need to rename it - ->ifTrue(static function ($v) { - return is_array($v) && isset($v['value']); - }) - ->then(static function ($v) { - $v['class'] = $v['value']; - unset($v['value']); - - return $v; - }) - ->end() - ->fixXmlConfig('parameter') - ->children() - ->scalarNode('class')->isRequired()->end() - ->booleanNode('enabled')->defaultFalse()->end() - ->arrayNode('parameters') - ->useAttributeAsKey('name') - ->prototype('variable')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end(); - - return $node; - } - - /** - * Return a ORM cache driver node for an given entity manager - * - * @param string $name - * - * @return ArrayNodeDefinition - */ - private function getOrmCacheDriverNode($name) - { - $treeBuilder = new TreeBuilder($name); - $node = $treeBuilder->getRootNode(); - - $node - ->addDefaultsIfNotSet() - ->beforeNormalization() - ->ifString() - ->then(static function ($v) : array { - return ['type' => $v]; - }) - ->end() - ->children() - ->scalarNode('type')->defaultNull()->end() - ->scalarNode('id')->end() - ->scalarNode('pool')->end() - ->end(); - - return $node; - } - - /** - * Find proxy auto generate modes for their names and int values - * - * @return array - */ - private function getAutoGenerateModes() - { - $constPrefix = 'AUTOGENERATE_'; - $prefixLen = strlen($constPrefix); - $refClass = new ReflectionClass('Doctrine\Common\Proxy\AbstractProxyFactory'); - $constsArray = $refClass->getConstants(); - $namesArray = []; - $valuesArray = []; - - foreach ($constsArray as $key => $value) { - if (strpos($key, $constPrefix) !== 0) { - continue; - } - - $namesArray[] = substr($key, $prefixLen); - $valuesArray[] = (int) $value; - } - - return [ - 'names' => $namesArray, - 'values' => $valuesArray, - ]; - } -} diff --git a/vendor/doctrine/doctrine-bundle/DependencyInjection/DoctrineExtension.php b/vendor/doctrine/doctrine-bundle/DependencyInjection/DoctrineExtension.php deleted file mode 100644 index 1a95a72..0000000 --- a/vendor/doctrine/doctrine-bundle/DependencyInjection/DoctrineExtension.php +++ /dev/null @@ -1,870 +0,0 @@ -getConfiguration($configs, $container); - $config = $this->processConfiguration($configuration, $configs); - - if (! empty($config['dbal'])) { - $this->dbalLoad($config['dbal'], $container); - - $this->loadMessengerServices($container); - } - - if (empty($config['orm'])) { - return; - } - - if (empty($config['dbal'])) { - throw new LogicException('Configuring the ORM layer requires to configure the DBAL layer as well.'); - } - - $this->ormLoad($config['orm'], $container); - } - - /** - * Loads the DBAL configuration. - * - * Usage example: - * - * - * - * @param array $config An array of configuration settings - * @param ContainerBuilder $container A ContainerBuilder instance - */ - protected function dbalLoad(array $config, ContainerBuilder $container) - { - $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); - $loader->load('dbal.xml'); - - if (empty($config['default_connection'])) { - $keys = array_keys($config['connections']); - $config['default_connection'] = reset($keys); - } - - $this->defaultConnection = $config['default_connection']; - - $container->setAlias('database_connection', sprintf('doctrine.dbal.%s_connection', $this->defaultConnection)); - $container->getAlias('database_connection')->setPublic(true); - $container->setAlias('doctrine.dbal.event_manager', new Alias(sprintf('doctrine.dbal.%s_connection.event_manager', $this->defaultConnection), false)); - - $container->setParameter('doctrine.dbal.connection_factory.types', $config['types']); - - $connections = []; - - foreach (array_keys($config['connections']) as $name) { - $connections[$name] = sprintf('doctrine.dbal.%s_connection', $name); - } - - $container->setParameter('doctrine.connections', $connections); - $container->setParameter('doctrine.default_connection', $this->defaultConnection); - - foreach ($config['connections'] as $name => $connection) { - $this->loadDbalConnection($name, $connection, $container); - } - } - - /** - * Loads a configured DBAL connection. - * - * @param string $name The name of the connection - * @param array $connection A dbal connection configuration. - * @param ContainerBuilder $container A ContainerBuilder instance - */ - protected function loadDbalConnection($name, array $connection, ContainerBuilder $container) - { - $configuration = $container->setDefinition(sprintf('doctrine.dbal.%s_connection.configuration', $name), new ChildDefinition('doctrine.dbal.connection.configuration')); - $logger = null; - if ($connection['logging']) { - $logger = new Reference('doctrine.dbal.logger'); - } - unset($connection['logging']); - - if ($connection['profiling']) { - $profilingAbstractId = $connection['profiling_collect_backtrace'] ? - 'doctrine.dbal.logger.backtrace' : - 'doctrine.dbal.logger.profiling'; - - $profilingLoggerId = $profilingAbstractId . '.' . $name; - $container->setDefinition($profilingLoggerId, new ChildDefinition($profilingAbstractId)); - $profilingLogger = new Reference($profilingLoggerId); - $container->getDefinition('data_collector.doctrine')->addMethodCall('addLogger', [$name, $profilingLogger]); - - if ($logger !== null) { - $chainLogger = new ChildDefinition('doctrine.dbal.logger.chain'); - $chainLogger->addMethodCall('addLogger', [$profilingLogger]); - - $loggerId = 'doctrine.dbal.logger.chain.' . $name; - $container->setDefinition($loggerId, $chainLogger); - $logger = new Reference($loggerId); - } else { - $logger = $profilingLogger; - } - } - unset($connection['profiling'], $connection['profiling_collect_backtrace']); - - if (isset($connection['auto_commit'])) { - $configuration->addMethodCall('setAutoCommit', [$connection['auto_commit']]); - } - - unset($connection['auto_commit']); - - if (isset($connection['schema_filter']) && $connection['schema_filter']) { - $definition = new Definition(RegexSchemaAssetFilter::class, [$connection['schema_filter']]); - $definition->addTag('doctrine.dbal.schema_filter', ['connection' => $name]); - $container->setDefinition(sprintf('doctrine.dbal.%s_regex_schema_filter', $name), $definition); - } - - unset($connection['schema_filter']); - - if ($logger) { - $configuration->addMethodCall('setSQLLogger', [$logger]); - } - - // event manager - $container->setDefinition(sprintf('doctrine.dbal.%s_connection.event_manager', $name), new ChildDefinition('doctrine.dbal.connection.event_manager')); - - // connection - $options = $this->getConnectionOptions($connection); - - $def = $container - ->setDefinition(sprintf('doctrine.dbal.%s_connection', $name), new ChildDefinition('doctrine.dbal.connection')) - ->setPublic(true) - ->setArguments([ - $options, - new Reference(sprintf('doctrine.dbal.%s_connection.configuration', $name)), - new Reference(sprintf('doctrine.dbal.%s_connection.event_manager', $name)), - $connection['mapping_types'], - ]); - - // Set class in case "wrapper_class" option was used to assist IDEs - if (isset($options['wrapperClass'])) { - $def->setClass($options['wrapperClass']); - } - - if (! empty($connection['use_savepoints'])) { - $def->addMethodCall('setNestTransactionsWithSavepoints', [$connection['use_savepoints']]); - } - - // Create a shard_manager for this connection - if (! isset($options['shards'])) { - return; - } - - $shardManagerDefinition = new Definition($options['shardManagerClass'], [new Reference(sprintf('doctrine.dbal.%s_connection', $name))]); - $container->setDefinition(sprintf('doctrine.dbal.%s_shard_manager', $name), $shardManagerDefinition); - } - - protected function getConnectionOptions($connection) - { - $options = $connection; - - if (isset($options['platform_service'])) { - $options['platform'] = new Reference($options['platform_service']); - unset($options['platform_service']); - } - unset($options['mapping_types']); - - if (isset($options['shard_choser_service'])) { - $options['shard_choser'] = new Reference($options['shard_choser_service']); - unset($options['shard_choser_service']); - } - - foreach ([ - 'options' => 'driverOptions', - 'driver_class' => 'driverClass', - 'wrapper_class' => 'wrapperClass', - 'keep_slave' => 'keepSlave', - 'shard_choser' => 'shardChoser', - 'shard_manager_class' => 'shardManagerClass', - 'server_version' => 'serverVersion', - 'default_table_options' => 'defaultTableOptions', - ] as $old => $new) { - if (! isset($options[$old])) { - continue; - } - - $options[$new] = $options[$old]; - unset($options[$old]); - } - - if (! empty($options['slaves']) && ! empty($options['shards'])) { - throw new InvalidArgumentException('Sharding and master-slave connection cannot be used together'); - } - - if (! empty($options['slaves'])) { - $nonRewrittenKeys = [ - 'driver' => true, - 'driverOptions' => true, - 'driverClass' => true, - 'wrapperClass' => true, - 'keepSlave' => true, - 'shardChoser' => true, - 'platform' => true, - 'slaves' => true, - 'master' => true, - 'shards' => true, - 'serverVersion' => true, - 'defaultTableOptions' => true, - // included by safety but should have been unset already - 'logging' => true, - 'profiling' => true, - 'mapping_types' => true, - 'platform_service' => true, - ]; - foreach ($options as $key => $value) { - if (isset($nonRewrittenKeys[$key])) { - continue; - } - $options['master'][$key] = $value; - unset($options[$key]); - } - if (empty($options['wrapperClass'])) { - // Change the wrapper class only if the user does not already forced using a custom one. - $options['wrapperClass'] = 'Doctrine\\DBAL\\Connections\\MasterSlaveConnection'; - } - } else { - unset($options['slaves']); - } - - if (! empty($options['shards'])) { - $nonRewrittenKeys = [ - 'driver' => true, - 'driverOptions' => true, - 'driverClass' => true, - 'wrapperClass' => true, - 'keepSlave' => true, - 'shardChoser' => true, - 'platform' => true, - 'slaves' => true, - 'global' => true, - 'shards' => true, - 'serverVersion' => true, - 'defaultTableOptions' => true, - // included by safety but should have been unset already - 'logging' => true, - 'profiling' => true, - 'mapping_types' => true, - 'platform_service' => true, - ]; - foreach ($options as $key => $value) { - if (isset($nonRewrittenKeys[$key])) { - continue; - } - $options['global'][$key] = $value; - unset($options[$key]); - } - if (empty($options['wrapperClass'])) { - // Change the wrapper class only if the user does not already forced using a custom one. - $options['wrapperClass'] = 'Doctrine\\DBAL\\Sharding\\PoolingShardConnection'; - } - if (empty($options['shardManagerClass'])) { - // Change the shard manager class only if the user does not already forced using a custom one. - $options['shardManagerClass'] = 'Doctrine\\DBAL\\Sharding\\PoolingShardManager'; - } - } else { - unset($options['shards']); - } - - return $options; - } - - /** - * Loads the Doctrine ORM configuration. - * - * Usage example: - * - * - * - * @param array $config An array of configuration settings - * @param ContainerBuilder $container A ContainerBuilder instance - */ - protected function ormLoad(array $config, ContainerBuilder $container) - { - if (! class_exists(UnitOfWork::class)) { - throw new LogicException('To configure the ORM layer, you must first install the doctrine/orm package.'); - } - - $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); - $loader->load('orm.xml'); - - if (class_exists(AbstractType::class)) { - $container->getDefinition('form.type.entity')->addTag('kernel.reset', ['method' => 'reset']); - } - - $entityManagers = []; - foreach (array_keys($config['entity_managers']) as $name) { - $entityManagers[$name] = sprintf('doctrine.orm.%s_entity_manager', $name); - } - $container->setParameter('doctrine.entity_managers', $entityManagers); - - if (empty($config['default_entity_manager'])) { - $tmp = array_keys($entityManagers); - $config['default_entity_manager'] = reset($tmp); - } - $container->setParameter('doctrine.default_entity_manager', $config['default_entity_manager']); - - $options = ['auto_generate_proxy_classes', 'proxy_dir', 'proxy_namespace']; - foreach ($options as $key) { - $container->setParameter('doctrine.orm.' . $key, $config[$key]); - } - - $container->setAlias('doctrine.orm.entity_manager', sprintf('doctrine.orm.%s_entity_manager', $config['default_entity_manager'])); - $container->getAlias('doctrine.orm.entity_manager')->setPublic(true); - - $config['entity_managers'] = $this->fixManagersAutoMappings($config['entity_managers'], $container->getParameter('kernel.bundles')); - - foreach ($config['entity_managers'] as $name => $entityManager) { - $entityManager['name'] = $name; - $this->loadOrmEntityManager($entityManager, $container); - - if (interface_exists(PropertyInfoExtractorInterface::class)) { - $this->loadPropertyInfoExtractor($name, $container); - } - - $this->loadValidatorLoader($name, $container); - } - - if ($config['resolve_target_entities']) { - $def = $container->findDefinition('doctrine.orm.listeners.resolve_target_entity'); - foreach ($config['resolve_target_entities'] as $name => $implementation) { - $def->addMethodCall('addResolveTargetEntity', [ - $name, - $implementation, - [], - ]); - } - - $def->addTag('doctrine.event_subscriber'); - } - - $container->registerForAutoconfiguration(ServiceEntityRepositoryInterface::class) - ->addTag(ServiceRepositoryCompilerPass::REPOSITORY_SERVICE_TAG); - } - - /** - * Loads a configured ORM entity manager. - * - * @param array $entityManager A configured ORM entity manager. - * @param ContainerBuilder $container A ContainerBuilder instance - */ - protected function loadOrmEntityManager(array $entityManager, ContainerBuilder $container) - { - $ormConfigDef = $container->setDefinition(sprintf('doctrine.orm.%s_configuration', $entityManager['name']), new ChildDefinition('doctrine.orm.configuration')); - - $this->loadOrmEntityManagerMappingInformation($entityManager, $ormConfigDef, $container); - $this->loadOrmCacheDrivers($entityManager, $container); - - if (isset($entityManager['entity_listener_resolver']) && $entityManager['entity_listener_resolver']) { - $container->setAlias(sprintf('doctrine.orm.%s_entity_listener_resolver', $entityManager['name']), $entityManager['entity_listener_resolver']); - } else { - $definition = new Definition('%doctrine.orm.entity_listener_resolver.class%'); - $definition->addArgument(new Reference('service_container')); - $container->setDefinition(sprintf('doctrine.orm.%s_entity_listener_resolver', $entityManager['name']), $definition); - } - - $methods = [ - 'setMetadataCacheImpl' => new Reference(sprintf('doctrine.orm.%s_metadata_cache', $entityManager['name'])), - 'setQueryCacheImpl' => new Reference(sprintf('doctrine.orm.%s_query_cache', $entityManager['name'])), - 'setResultCacheImpl' => new Reference(sprintf('doctrine.orm.%s_result_cache', $entityManager['name'])), - 'setMetadataDriverImpl' => new Reference('doctrine.orm.' . $entityManager['name'] . '_metadata_driver'), - 'setProxyDir' => '%doctrine.orm.proxy_dir%', - 'setProxyNamespace' => '%doctrine.orm.proxy_namespace%', - 'setAutoGenerateProxyClasses' => '%doctrine.orm.auto_generate_proxy_classes%', - 'setClassMetadataFactoryName' => $entityManager['class_metadata_factory_name'], - 'setDefaultRepositoryClassName' => $entityManager['default_repository_class'], - 'setNamingStrategy' => new Reference($entityManager['naming_strategy']), - 'setQuoteStrategy' => new Reference($entityManager['quote_strategy']), - 'setEntityListenerResolver' => new Reference(sprintf('doctrine.orm.%s_entity_listener_resolver', $entityManager['name'])), - ]; - - $listenerId = sprintf('doctrine.orm.%s_listeners.attach_entity_listeners', $entityManager['name']); - $listenerDef = $container->setDefinition($listenerId, new Definition('%doctrine.orm.listeners.attach_entity_listeners.class%')); - $listenerTagParams = ['event' => 'loadClassMetadata']; - if (isset($entityManager['connection'])) { - $listenerTagParams['connection'] = $entityManager['connection']; - } - $listenerDef->addTag('doctrine.event_listener', $listenerTagParams); - - if (isset($entityManager['second_level_cache'])) { - $this->loadOrmSecondLevelCache($entityManager, $ormConfigDef, $container); - } - - if ($entityManager['repository_factory']) { - $methods['setRepositoryFactory'] = new Reference($entityManager['repository_factory']); - } - - foreach ($methods as $method => $arg) { - $ormConfigDef->addMethodCall($method, [$arg]); - } - - foreach ($entityManager['hydrators'] as $name => $class) { - $ormConfigDef->addMethodCall('addCustomHydrationMode', [$name, $class]); - } - - if (! empty($entityManager['dql'])) { - foreach ($entityManager['dql']['string_functions'] as $name => $function) { - $ormConfigDef->addMethodCall('addCustomStringFunction', [$name, $function]); - } - foreach ($entityManager['dql']['numeric_functions'] as $name => $function) { - $ormConfigDef->addMethodCall('addCustomNumericFunction', [$name, $function]); - } - foreach ($entityManager['dql']['datetime_functions'] as $name => $function) { - $ormConfigDef->addMethodCall('addCustomDatetimeFunction', [$name, $function]); - } - } - - $enabledFilters = []; - $filtersParameters = []; - foreach ($entityManager['filters'] as $name => $filter) { - $ormConfigDef->addMethodCall('addFilter', [$name, $filter['class']]); - if ($filter['enabled']) { - $enabledFilters[] = $name; - } - if (! $filter['parameters']) { - continue; - } - - $filtersParameters[$name] = $filter['parameters']; - } - - $managerConfiguratorName = sprintf('doctrine.orm.%s_manager_configurator', $entityManager['name']); - $container - ->setDefinition($managerConfiguratorName, new ChildDefinition('doctrine.orm.manager_configurator.abstract')) - ->replaceArgument(0, $enabledFilters) - ->replaceArgument(1, $filtersParameters); - - if (! isset($entityManager['connection'])) { - $entityManager['connection'] = $this->defaultConnection; - } - - $container - ->setDefinition(sprintf('doctrine.orm.%s_entity_manager', $entityManager['name']), new ChildDefinition('doctrine.orm.entity_manager.abstract')) - ->setPublic(true) - ->setArguments([ - new Reference(sprintf('doctrine.dbal.%s_connection', $entityManager['connection'])), - new Reference(sprintf('doctrine.orm.%s_configuration', $entityManager['name'])), - ]) - ->setConfigurator([new Reference($managerConfiguratorName), 'configure']); - - $container->setAlias( - sprintf('doctrine.orm.%s_entity_manager.event_manager', $entityManager['name']), - new Alias(sprintf('doctrine.dbal.%s_connection.event_manager', $entityManager['connection']), false) - ); - - if (! isset($entityManager['entity_listeners'])) { - return; - } - - if (! isset($listenerDef)) { - throw new InvalidArgumentException('Entity listeners configuration requires doctrine-orm 2.5.0 or newer'); - } - - $entities = $entityManager['entity_listeners']['entities']; - - foreach ($entities as $entityListenerClass => $entity) { - foreach ($entity['listeners'] as $listenerClass => $listener) { - foreach ($listener['events'] as $listenerEvent) { - $listenerEventName = $listenerEvent['type']; - $listenerMethod = $listenerEvent['method']; - - $listenerDef->addMethodCall('addEntityListener', [ - $entityListenerClass, - $listenerClass, - $listenerEventName, - $listenerMethod, - ]); - } - } - } - } - - /** - * Loads an ORM entity managers bundle mapping information. - * - * There are two distinct configuration possibilities for mapping information: - * - * 1. Specify a bundle and optionally details where the entity and mapping information reside. - * 2. Specify an arbitrary mapping location. - * - * @param array $entityManager A configured ORM entity manager - * @param Definition $ormConfigDef A Definition instance - * @param ContainerBuilder $container A ContainerBuilder instance - * - * @example - * - * doctrine.orm: - * mappings: - * MyBundle1: ~ - * MyBundle2: yml - * MyBundle3: { type: annotation, dir: Entities/ } - * MyBundle4: { type: xml, dir: Resources/config/doctrine/mapping } - * MyBundle5: - * type: yml - * dir: bundle-mappings/ - * alias: BundleAlias - * arbitrary_key: - * type: xml - * dir: %kernel.project_dir%/src/vendor/DoctrineExtensions/lib/DoctrineExtensions/Entities - * prefix: DoctrineExtensions\Entities\ - * alias: DExt - * - * In the case of bundles everything is really optional (which leads to autodetection for this bundle) but - * in the mappings key everything except alias is a required argument. - */ - protected function loadOrmEntityManagerMappingInformation(array $entityManager, Definition $ormConfigDef, ContainerBuilder $container) - { - // reset state of drivers and alias map. They are only used by this methods and children. - $this->drivers = []; - $this->aliasMap = []; - - $this->loadMappingInformation($entityManager, $container); - $this->registerMappingDrivers($entityManager, $container); - - $ormConfigDef->addMethodCall('setEntityNamespaces', [$this->aliasMap]); - } - - /** - * Loads an ORM second level cache bundle mapping information. - * - * @param array $entityManager A configured ORM entity manager - * @param Definition $ormConfigDef A Definition instance - * @param ContainerBuilder $container A ContainerBuilder instance - * - * @example - * entity_managers: - * default: - * second_level_cache: - * region_cache_driver: apc - * log_enabled: true - * regions: - * my_service_region: - * type: service - * service : "my_service_region" - * - * my_query_region: - * lifetime: 300 - * cache_driver: array - * type: filelock - * - * my_entity_region: - * lifetime: 600 - * cache_driver: - * type: apc - */ - protected function loadOrmSecondLevelCache(array $entityManager, Definition $ormConfigDef, ContainerBuilder $container) - { - $driverId = null; - $enabled = $entityManager['second_level_cache']['enabled']; - - if (isset($entityManager['second_level_cache']['region_cache_driver'])) { - $driverName = 'second_level_cache.region_cache_driver'; - $driverMap = $entityManager['second_level_cache']['region_cache_driver']; - $driverId = $this->loadCacheDriver($driverName, $entityManager['name'], $driverMap, $container); - } - - $configId = sprintf('doctrine.orm.%s_second_level_cache.cache_configuration', $entityManager['name']); - $regionsId = sprintf('doctrine.orm.%s_second_level_cache.regions_configuration', $entityManager['name']); - $driverId = $driverId ?: sprintf('doctrine.orm.%s_second_level_cache.region_cache_driver', $entityManager['name']); - $configDef = $container->setDefinition($configId, new Definition('%doctrine.orm.second_level_cache.cache_configuration.class%')); - $regionsDef = $container->setDefinition($regionsId, new Definition('%doctrine.orm.second_level_cache.regions_configuration.class%')); - - $slcFactoryId = sprintf('doctrine.orm.%s_second_level_cache.default_cache_factory', $entityManager['name']); - $factoryClass = isset($entityManager['second_level_cache']['factory']) ? $entityManager['second_level_cache']['factory'] : '%doctrine.orm.second_level_cache.default_cache_factory.class%'; - - $definition = new Definition($factoryClass, [new Reference($regionsId), new Reference($driverId)]); - - $slcFactoryDef = $container - ->setDefinition($slcFactoryId, $definition); - - if (isset($entityManager['second_level_cache']['regions'])) { - foreach ($entityManager['second_level_cache']['regions'] as $name => $region) { - $regionRef = null; - $regionType = $region['type']; - - if ($regionType === 'service') { - $regionId = sprintf('doctrine.orm.%s_second_level_cache.region.%s', $entityManager['name'], $name); - $regionRef = new Reference($region['service']); - - $container->setAlias($regionId, new Alias($region['service'], false)); - } - - if ($regionType === 'default' || $regionType === 'filelock') { - $regionId = sprintf('doctrine.orm.%s_second_level_cache.region.%s', $entityManager['name'], $name); - $driverName = sprintf('second_level_cache.region.%s_driver', $name); - $driverMap = $region['cache_driver']; - $driverId = $this->loadCacheDriver($driverName, $entityManager['name'], $driverMap, $container); - $regionRef = new Reference($regionId); - - $container - ->setDefinition($regionId, new Definition('%doctrine.orm.second_level_cache.default_region.class%')) - ->setArguments([$name, new Reference($driverId), $region['lifetime']]); - } - - if ($regionType === 'filelock') { - $regionId = sprintf('doctrine.orm.%s_second_level_cache.region.%s_filelock', $entityManager['name'], $name); - - $container - ->setDefinition($regionId, new Definition('%doctrine.orm.second_level_cache.filelock_region.class%')) - ->setArguments([$regionRef, $region['lock_path'], $region['lock_lifetime']]); - - $regionRef = new Reference($regionId); - $regionsDef->addMethodCall('getLockLifetime', [$name, $region['lock_lifetime']]); - } - - $regionsDef->addMethodCall('setLifetime', [$name, $region['lifetime']]); - $slcFactoryDef->addMethodCall('setRegion', [$regionRef]); - } - } - - if ($entityManager['second_level_cache']['log_enabled']) { - $loggerChainId = sprintf('doctrine.orm.%s_second_level_cache.logger_chain', $entityManager['name']); - $loggerStatsId = sprintf('doctrine.orm.%s_second_level_cache.logger_statistics', $entityManager['name']); - $loggerChaingDef = $container->setDefinition($loggerChainId, new Definition('%doctrine.orm.second_level_cache.logger_chain.class%')); - $loggerStatsDef = $container->setDefinition($loggerStatsId, new Definition('%doctrine.orm.second_level_cache.logger_statistics.class%')); - - $loggerChaingDef->addMethodCall('setLogger', ['statistics', $loggerStatsDef]); - $configDef->addMethodCall('setCacheLogger', [$loggerChaingDef]); - - foreach ($entityManager['second_level_cache']['loggers'] as $name => $logger) { - $loggerId = sprintf('doctrine.orm.%s_second_level_cache.logger.%s', $entityManager['name'], $name); - $loggerRef = new Reference($logger['service']); - - $container->setAlias($loggerId, new Alias($logger['service'], false)); - $loggerChaingDef->addMethodCall('setLogger', [$name, $loggerRef]); - } - } - - $configDef->addMethodCall('setCacheFactory', [$slcFactoryDef]); - $configDef->addMethodCall('setRegionsConfiguration', [$regionsDef]); - $ormConfigDef->addMethodCall('setSecondLevelCacheEnabled', [$enabled]); - $ormConfigDef->addMethodCall('setSecondLevelCacheConfiguration', [$configDef]); - } - - /** - * {@inheritDoc} - */ - protected function getObjectManagerElementName($name) : string - { - return 'doctrine.orm.' . $name; - } - - protected function getMappingObjectDefaultName() : string - { - return 'Entity'; - } - - /** - * {@inheritDoc} - */ - protected function getMappingResourceConfigDirectory() : string - { - return 'Resources/config/doctrine'; - } - - /** - * {@inheritDoc} - */ - protected function getMappingResourceExtension() : string - { - return 'orm'; - } - - /** - * {@inheritDoc} - */ - protected function loadCacheDriver($cacheName, $objectManagerName, array $cacheDriver, ContainerBuilder $container) : string - { - $serviceId = null; - $aliasId = $this->getObjectManagerElementName(sprintf('%s_%s', $objectManagerName, $cacheName)); - - switch ($cacheDriver['type'] ?? 'pool') { - case 'service': - $serviceId = $cacheDriver['id']; - break; - - case 'pool': - $serviceId = $this->createPoolCacheDefinition($container, $cacheDriver['pool'] ?? $this->createArrayAdapterCachePool($container, $objectManagerName, $cacheName)); - break; - - case 'provider': - $serviceId = sprintf('doctrine_cache.providers.%s', $cacheDriver['cache_provider']); - break; - - default: - throw new \InvalidArgumentException(sprintf( - 'Unknown cache of type "%s" configured for cache "%s" in entity manager "%s".', - $cacheDriver['type'], - $cacheName, - $objectManagerName - )); - } - - $container->setAlias($aliasId, new Alias($serviceId, false)); - - return $aliasId; - } - - /** - * Loads a configured entity managers cache drivers. - * - * @param array $entityManager A configured ORM entity manager. - * @param ContainerBuilder $container A ContainerBuilder instance - */ - protected function loadOrmCacheDrivers(array $entityManager, ContainerBuilder $container) - { - $this->loadCacheDriver('metadata_cache', $entityManager['name'], $entityManager['metadata_cache_driver'], $container); - $this->loadCacheDriver('result_cache', $entityManager['name'], $entityManager['result_cache_driver'], $container); - $this->loadCacheDriver('query_cache', $entityManager['name'], $entityManager['query_cache_driver'], $container); - } - - /** - * Loads a property info extractor for each defined entity manager. - * - * @param string $entityManagerName - */ - private function loadPropertyInfoExtractor($entityManagerName, ContainerBuilder $container) - { - $propertyExtractorDefinition = $container->register(sprintf('doctrine.orm.%s_entity_manager.property_info_extractor', $entityManagerName), DoctrineExtractor::class); - $argumentId = sprintf('doctrine.orm.%s_entity_manager', $entityManagerName); - - $propertyExtractorDefinition->addArgument(new Reference($argumentId)); - - $propertyExtractorDefinition->addTag('property_info.list_extractor', ['priority' => -1001]); - $propertyExtractorDefinition->addTag('property_info.type_extractor', ['priority' => -999]); - $propertyExtractorDefinition->addTag('property_info.access_extractor', ['priority' => -999]); - } - - /** - * Loads a validator loader for each defined entity manager. - */ - private function loadValidatorLoader(string $entityManagerName, ContainerBuilder $container) : void - { - $validatorLoaderDefinition = $container->register(sprintf('doctrine.orm.%s_entity_manager.validator_loader', $entityManagerName), DoctrineLoader::class); - $validatorLoaderDefinition->addArgument(new Reference(sprintf('doctrine.orm.%s_entity_manager', $entityManagerName))); - - $validatorLoaderDefinition->addTag('validator.auto_mapper', ['priority' => -100]); - } - - /** - * @param array $objectManager - * @param string $cacheName - */ - public function loadObjectManagerCacheDriver(array $objectManager, ContainerBuilder $container, $cacheName) - { - $this->loadCacheDriver($cacheName, $objectManager['name'], $objectManager[$cacheName . '_driver'], $container); - } - - /** - * {@inheritDoc} - */ - public function getXsdValidationBasePath() : string - { - return __DIR__ . '/../Resources/config/schema'; - } - - /** - * {@inheritDoc} - */ - public function getNamespace() : string - { - return 'http://symfony.com/schema/dic/doctrine'; - } - - /** - * {@inheritDoc} - */ - public function getConfiguration(array $config, ContainerBuilder $container) : Configuration - { - return new Configuration($container->getParameter('kernel.debug')); - } - - protected function getMetadataDriverClass(string $driverType) : string - { - return '%' . $this->getObjectManagerElementName('metadata.' . $driverType . '.class%'); - } - - private function loadMessengerServices(ContainerBuilder $container) : void - { - // If the Messenger component is installed and the doctrine transaction middleware is available, wire it: - if (! interface_exists(MessageBusInterface::class) || ! class_exists(DoctrineTransactionMiddleware::class)) { - return; - } - - $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); - $loader->load('messenger.xml'); - - if (! class_exists(DoctrineClearEntityManagerWorkerSubscriber::class)) { - $container->removeDefinition('doctrine.orm.messenger.event_subscriber.doctrine_clear_entity_manager'); - } - - if (! class_exists(DoctrineTransportFactory::class)) { - return; - } - - $transportFactoryDefinition = $container->getDefinition('messenger.transport.doctrine.factory'); - $transportFactoryDefinition->addTag('messenger.transport_factory'); - } - - private function createPoolCacheDefinition(ContainerBuilder $container, string $poolName) : string - { - $serviceId = sprintf('doctrine.orm.cache.provider.%s', $poolName); - - $definition = $container->register($serviceId, DoctrineProvider::class); - $definition->addArgument(new Reference($poolName)); - $definition->setPrivate(true); - - return $serviceId; - } - - private function createArrayAdapterCachePool(ContainerBuilder $container, string $objectManagerName, string $cacheName) : string - { - $id = sprintf('cache.doctrine.orm.%s.%s', $objectManagerName, str_replace('_cache', '', $cacheName)); - - $poolDefinition = $container->register($id, ArrayAdapter::class); - $poolDefinition->addTag('cache.pool'); - $container->setDefinition($id, $poolDefinition); - - return $id; - } -} diff --git a/vendor/doctrine/doctrine-bundle/DoctrineBundle.php b/vendor/doctrine/doctrine-bundle/DoctrineBundle.php deleted file mode 100644 index f19a1e5..0000000 --- a/vendor/doctrine/doctrine-bundle/DoctrineBundle.php +++ /dev/null @@ -1,137 +0,0 @@ -addCompilerPass(new RegisterEventListenersAndSubscribersPass('doctrine.connections', 'doctrine.dbal.%s_connection.event_manager', 'doctrine'), PassConfig::TYPE_BEFORE_OPTIMIZATION); - - if ($container->hasExtension('security')) { - $container->getExtension('security')->addUserProviderFactory(new EntityFactory('entity', 'doctrine.orm.security.user.provider')); - } - - $container->addCompilerPass(new DoctrineValidationPass('orm')); - $container->addCompilerPass(new EntityListenerPass()); - $container->addCompilerPass(new ServiceRepositoryCompilerPass()); - $container->addCompilerPass(new WellKnownSchemaFilterPass()); - $container->addCompilerPass(new DbalSchemaFilterPass()); - } - - /** - * {@inheritDoc} - */ - public function boot() - { - // Register an autoloader for proxies to avoid issues when unserializing them - // when the ORM is used. - if (! $this->container->hasParameter('doctrine.orm.proxy_namespace')) { - return; - } - - $namespace = $this->container->getParameter('doctrine.orm.proxy_namespace'); - $dir = $this->container->getParameter('doctrine.orm.proxy_dir'); - $proxyGenerator = null; - - if ($this->container->getParameter('doctrine.orm.auto_generate_proxy_classes')) { - // See https://github.com/symfony/symfony/pull/3419 for usage of references - $container = &$this->container; - - $proxyGenerator = static function ($proxyDir, $proxyNamespace, $class) use (&$container) { - $originalClassName = ClassUtils::getRealClass($class); - /** @var Registry $registry */ - $registry = $container->get('doctrine'); - - // Tries to auto-generate the proxy file - /** @var EntityManager $em */ - foreach ($registry->getManagers() as $em) { - if (! $em->getConfiguration()->getAutoGenerateProxyClasses()) { - continue; - } - - $metadataFactory = $em->getMetadataFactory(); - - if ($metadataFactory->isTransient($originalClassName)) { - continue; - } - - $classMetadata = $metadataFactory->getMetadataFor($originalClassName); - - $em->getProxyFactory()->generateProxyClasses([$classMetadata]); - - clearstatcache(true, Autoloader::resolveFile($proxyDir, $proxyNamespace, $class)); - - break; - } - }; - } - - $this->autoloader = Autoloader::register($dir, $namespace, $proxyGenerator); - } - - /** - * {@inheritDoc} - */ - public function shutdown() - { - if ($this->autoloader !== null) { - spl_autoload_unregister($this->autoloader); - $this->autoloader = null; - } - - // Clear all entity managers to clear references to entities for GC - if ($this->container->hasParameter('doctrine.entity_managers')) { - foreach ($this->container->getParameter('doctrine.entity_managers') as $id) { - if (! $this->container->initialized($id)) { - continue; - } - - $this->container->get($id)->clear(); - } - } - - // Close all connections to avoid reaching too many connections in the process when booting again later (tests) - if (! $this->container->hasParameter('doctrine.connections')) { - return; - } - - foreach ($this->container->getParameter('doctrine.connections') as $id) { - if (! $this->container->initialized($id)) { - continue; - } - - $this->container->get($id)->close(); - } - } - - /** - * {@inheritDoc} - */ - public function registerCommands(Application $application) - { - } -} diff --git a/vendor/doctrine/doctrine-bundle/LICENSE b/vendor/doctrine/doctrine-bundle/LICENSE deleted file mode 100644 index 655a5ce..0000000 --- a/vendor/doctrine/doctrine-bundle/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2011 Fabien Potencier, Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/doctrine/doctrine-bundle/ManagerConfigurator.php b/vendor/doctrine/doctrine-bundle/ManagerConfigurator.php deleted file mode 100644 index 6143890..0000000 --- a/vendor/doctrine/doctrine-bundle/ManagerConfigurator.php +++ /dev/null @@ -1,74 +0,0 @@ -enabledFilters = $enabledFilters; - $this->filtersParameters = $filtersParameters; - } - - /** - * Create a connection by name. - */ - public function configure(EntityManagerInterface $entityManager) - { - $this->enableFilters($entityManager); - } - - /** - * Enables filters for a given entity manager - */ - private function enableFilters(EntityManagerInterface $entityManager) - { - if (empty($this->enabledFilters)) { - return; - } - - $filterCollection = $entityManager->getFilters(); - foreach ($this->enabledFilters as $filter) { - $filterObject = $filterCollection->enable($filter); - if ($filterObject === null) { - continue; - } - - $this->setFilterParameters($filter, $filterObject); - } - } - - /** - * Sets default parameters for a given filter - * - * @param string $name Filter name - * @param SQLFilter $filter Filter object - */ - private function setFilterParameters($name, SQLFilter $filter) - { - if (empty($this->filtersParameters[$name])) { - return; - } - - $parameters = $this->filtersParameters[$name]; - foreach ($parameters as $paramName => $paramValue) { - $filter->setParameter($paramName, $paramValue); - } - } -} diff --git a/vendor/doctrine/doctrine-bundle/Mapping/ClassMetadataCollection.php b/vendor/doctrine/doctrine-bundle/Mapping/ClassMetadataCollection.php deleted file mode 100644 index c65b47f..0000000 --- a/vendor/doctrine/doctrine-bundle/Mapping/ClassMetadataCollection.php +++ /dev/null @@ -1,65 +0,0 @@ -metadata = $metadata; - } - - /** - * @return ClassMetadata[] - */ - public function getMetadata() - { - return $this->metadata; - } - - /** - * @param string $path - */ - public function setPath($path) - { - $this->path = $path; - } - - /** - * @return string - */ - public function getPath() - { - return $this->path; - } - - /** - * @param string $namespace - */ - public function setNamespace($namespace) - { - $this->namespace = $namespace; - } - - /** - * @return string - */ - public function getNamespace() - { - return $this->namespace; - } -} diff --git a/vendor/doctrine/doctrine-bundle/Mapping/ContainerEntityListenerResolver.php b/vendor/doctrine/doctrine-bundle/Mapping/ContainerEntityListenerResolver.php deleted file mode 100644 index 9645838..0000000 --- a/vendor/doctrine/doctrine-bundle/Mapping/ContainerEntityListenerResolver.php +++ /dev/null @@ -1,103 +0,0 @@ -container = $container; - } - - /** - * {@inheritdoc} - */ - public function clear($className = null) - { - if ($className === null) { - $this->instances = []; - - return; - } - - $className = $this->normalizeClassName($className); - - unset($this->instances[$className]); - } - - /** - * {@inheritdoc} - */ - public function register($object) - { - if (! is_object($object)) { - throw new InvalidArgumentException(sprintf('An object was expected, but got "%s".', gettype($object))); - } - - $className = $this->normalizeClassName(get_class($object)); - - $this->instances[$className] = $object; - } - - /** - * {@inheritdoc} - */ - public function registerService($className, $serviceId) - { - $this->serviceIds[$this->normalizeClassName($className)] = $serviceId; - } - - /** - * {@inheritdoc} - */ - public function resolve($className) - { - $className = $this->normalizeClassName($className); - - if (! isset($this->instances[$className])) { - if (isset($this->serviceIds[$className])) { - $this->instances[$className] = $this->resolveService($this->serviceIds[$className]); - } else { - $this->instances[$className] = new $className(); - } - } - - return $this->instances[$className]; - } - - /** - * @return object - */ - private function resolveService(string $serviceId) - { - if (! $this->container->has($serviceId)) { - throw new RuntimeException(sprintf('There is no service named "%s"', $serviceId)); - } - - return $this->container->get($serviceId); - } - - private function normalizeClassName(string $className) : string - { - return trim($className, '\\'); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Mapping/DisconnectedMetadataFactory.php b/vendor/doctrine/doctrine-bundle/Mapping/DisconnectedMetadataFactory.php deleted file mode 100644 index 163259d..0000000 --- a/vendor/doctrine/doctrine-bundle/Mapping/DisconnectedMetadataFactory.php +++ /dev/null @@ -1,204 +0,0 @@ -registry = $registry; - } - - /** - * Gets the metadata of all classes of a bundle. - * - * @param BundleInterface $bundle A BundleInterface instance - * - * @return ClassMetadataCollection A ClassMetadataCollection instance - * - * @throws RuntimeException When bundle does not contain mapped entities. - */ - public function getBundleMetadata(BundleInterface $bundle) - { - $namespace = $bundle->getNamespace(); - $metadata = $this->getMetadataForNamespace($namespace); - if (! $metadata->getMetadata()) { - throw new RuntimeException(sprintf('Bundle "%s" does not contain any mapped entities.', $bundle->getName())); - } - - $path = $this->getBasePathForClass($bundle->getName(), $bundle->getNamespace(), $bundle->getPath()); - - $metadata->setPath($path); - $metadata->setNamespace($bundle->getNamespace()); - - return $metadata; - } - - /** - * Gets the metadata of a class. - * - * @param string $class A class name - * @param string $path The path where the class is stored (if known) - * - * @return ClassMetadataCollection A ClassMetadataCollection instance - * - * @throws MappingException When class is not valid entity or mapped superclass. - */ - public function getClassMetadata($class, $path = null) - { - $metadata = $this->getMetadataForClass($class); - if (! $metadata->getMetadata()) { - throw MappingException::classIsNotAValidEntityOrMappedSuperClass($class); - } - - $this->findNamespaceAndPathForMetadata($metadata, $path); - - return $metadata; - } - - /** - * Gets the metadata of all classes of a namespace. - * - * @param string $namespace A namespace name - * @param string $path The path where the class is stored (if known) - * - * @return ClassMetadataCollection A ClassMetadataCollection instance - * - * @throws RuntimeException When namespace not contain mapped entities. - */ - public function getNamespaceMetadata($namespace, $path = null) - { - $metadata = $this->getMetadataForNamespace($namespace); - if (! $metadata->getMetadata()) { - throw new RuntimeException(sprintf('Namespace "%s" does not contain any mapped entities.', $namespace)); - } - - $this->findNamespaceAndPathForMetadata($metadata, $path); - - return $metadata; - } - - /** - * Find and configure path and namespace for the metadata collection. - * - * @param string|null $path - * - * @throws RuntimeException When unable to determine the path. - */ - public function findNamespaceAndPathForMetadata(ClassMetadataCollection $metadata, $path = null) - { - $all = $metadata->getMetadata(); - if (class_exists($all[0]->name)) { - $r = new ReflectionClass($all[0]->name); - $path = $this->getBasePathForClass($r->getName(), $r->getNamespaceName(), dirname($r->getFilename())); - $ns = $r->getNamespaceName(); - } elseif ($path) { - // Get namespace by removing the last component of the FQCN - $nsParts = explode('\\', $all[0]->name); - array_pop($nsParts); - $ns = implode('\\', $nsParts); - } else { - throw new RuntimeException(sprintf('Unable to determine where to save the "%s" class (use the --path option).', $all[0]->name)); - } - - $metadata->setPath($path); - $metadata->setNamespace($ns); - } - - /** - * Get a base path for a class - * - * @param string $name class name - * @param string $namespace class namespace - * @param string $path class path - * - * @return string - * - * @throws RuntimeException When base path not found. - */ - private function getBasePathForClass($name, $namespace, $path) - { - $namespace = str_replace('\\', '/', $namespace); - $search = str_replace('\\', '/', $path); - $destination = str_replace('/' . $namespace, '', $search, $c); - - if ($c !== 1) { - throw new RuntimeException(sprintf('Can\'t find base path for "%s" (path: "%s", destination: "%s").', $name, $path, $destination)); - } - - return $destination; - } - - /** - * @param string $namespace - * - * @return ClassMetadataCollection - */ - private function getMetadataForNamespace($namespace) - { - $metadata = []; - foreach ($this->getAllMetadata() as $m) { - if (strpos($m->name, $namespace) !== 0) { - continue; - } - - $metadata[] = $m; - } - - return new ClassMetadataCollection($metadata); - } - - /** - * @param string $entity - * - * @return ClassMetadataCollection - */ - private function getMetadataForClass($entity) - { - foreach ($this->registry->getManagers() as $em) { - $cmf = new DisconnectedClassMetadataFactory(); - $cmf->setEntityManager($em); - - if (! $cmf->isTransient($entity)) { - return new ClassMetadataCollection([$cmf->getMetadataFor($entity)]); - } - } - - return new ClassMetadataCollection([]); - } - - /** - * @return ClassMetadata[] - */ - private function getAllMetadata() - { - $metadata = []; - foreach ($this->registry->getManagers() as $em) { - $cmf = new DisconnectedClassMetadataFactory(); - $cmf->setEntityManager($em); - foreach ($cmf->getAllMetadata() as $m) { - $metadata[] = $m; - } - } - - return $metadata; - } -} diff --git a/vendor/doctrine/doctrine-bundle/Mapping/EntityListenerServiceResolver.php b/vendor/doctrine/doctrine-bundle/Mapping/EntityListenerServiceResolver.php deleted file mode 100644 index 3cb4960..0000000 --- a/vendor/doctrine/doctrine-bundle/Mapping/EntityListenerServiceResolver.php +++ /dev/null @@ -1,14 +0,0 @@ -container = $container; - - parent::__construct('ORM', $connections, $entityManagers, $defaultConnection, $defaultEntityManager, 'Doctrine\ORM\Proxy\Proxy'); - } - - /** - * Resolves a registered namespace alias to the full namespace. - * - * This method looks for the alias in all registered entity managers. - * - * @see Configuration::getEntityNamespace - * - * @param string $alias The alias - * - * @return string The full namespace - */ - public function getAliasNamespace($alias) - { - foreach (array_keys($this->getManagers()) as $name) { - try { - return $this->getManager($name)->getConfiguration()->getEntityNamespace($alias); - } catch (ORMException $e) { - } - } - - throw ORMException::unknownEntityNamespace($alias); - } - - public function reset() : void - { - foreach ($this->getManagerNames() as $managerName => $serviceId) { - $this->resetOrClearManager($managerName, $serviceId); - } - } - - private function resetOrClearManager(string $managerName, string $serviceId) : void - { - if (! $this->container->initialized($serviceId)) { - return; - } - - $manager = $this->container->get($serviceId); - - if (! $manager instanceof LazyLoadingInterface) { - $manager->clear(); - - return; - } - - $this->resetManager($managerName); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Repository/ContainerRepositoryFactory.php b/vendor/doctrine/doctrine-bundle/Repository/ContainerRepositoryFactory.php deleted file mode 100644 index b16427b..0000000 --- a/vendor/doctrine/doctrine-bundle/Repository/ContainerRepositoryFactory.php +++ /dev/null @@ -1,86 +0,0 @@ -container = $container; - } - - /** - * {@inheritdoc} - */ - public function getRepository(EntityManagerInterface $entityManager, $entityName) - { - $metadata = $entityManager->getClassMetadata($entityName); - $repositoryServiceId = $metadata->customRepositoryClassName; - - $customRepositoryName = $metadata->customRepositoryClassName; - if ($customRepositoryName !== null) { - // fetch from the container - if ($this->container && $this->container->has($customRepositoryName)) { - $repository = $this->container->get($customRepositoryName); - - if (! $repository instanceof ObjectRepository) { - throw new RuntimeException(sprintf('The service "%s" must implement ObjectRepository (or extend a base class, like ServiceEntityRepository).', $repositoryServiceId)); - } - - return $repository; - } - - // if not in the container but the class/id implements the interface, throw an error - if (is_a($customRepositoryName, ServiceEntityRepositoryInterface::class, true)) { - throw new RuntimeException(sprintf('The "%s" entity repository implements "%s", but its service could not be found. Make sure the service exists and is tagged with "%s".', $customRepositoryName, ServiceEntityRepositoryInterface::class, ServiceRepositoryCompilerPass::REPOSITORY_SERVICE_TAG)); - } - - if (! class_exists($customRepositoryName)) { - throw new RuntimeException(sprintf('The "%s" entity has a repositoryClass set to "%s", but this is not a valid class. Check your class naming. If this is meant to be a service id, make sure this service exists and is tagged with "%s".', $metadata->name, $customRepositoryName, ServiceRepositoryCompilerPass::REPOSITORY_SERVICE_TAG)); - } - - // allow the repository to be created below - } - - return $this->getOrCreateRepository($entityManager, $metadata); - } - - private function getOrCreateRepository(EntityManagerInterface $entityManager, ClassMetadata $metadata) - { - $repositoryHash = $metadata->getName() . spl_object_hash($entityManager); - if (isset($this->managedRepositories[$repositoryHash])) { - return $this->managedRepositories[$repositoryHash]; - } - - $repositoryClassName = $metadata->customRepositoryClassName ?: $entityManager->getConfiguration()->getDefaultRepositoryClassName(); - - return $this->managedRepositories[$repositoryHash] = new $repositoryClassName($entityManager, $metadata); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepository.php b/vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepository.php deleted file mode 100644 index 987d0b0..0000000 --- a/vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepository.php +++ /dev/null @@ -1,41 +0,0 @@ -getManagerForClass($entityClass); - - if ($manager === null) { - throw new LogicException(sprintf( - 'Could not find the entity manager for class "%s". Check your Doctrine configuration to make sure it is configured to load this entity’s metadata.', - $entityClass - )); - } - - parent::__construct($manager, $manager->getClassMetadata($entityClass)); - } -} diff --git a/vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepositoryInterface.php b/vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepositoryInterface.php deleted file mode 100644 index fe9ce4d..0000000 --- a/vendor/doctrine/doctrine-bundle/Repository/ServiceEntityRepositoryInterface.php +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - Doctrine\DBAL\Logging\LoggerChain - Doctrine\DBAL\Logging\DebugStack - Symfony\Bridge\Doctrine\Logger\DbalLogger - Doctrine\DBAL\Configuration - Doctrine\Bundle\DoctrineBundle\DataCollector\DoctrineDataCollector - Symfony\Bridge\Doctrine\ContainerAwareEventManager - Doctrine\Bundle\DoctrineBundle\ConnectionFactory - Doctrine\DBAL\Event\Listeners\MysqlSessionInit - Doctrine\DBAL\Event\Listeners\OracleSessionInit - Doctrine\Bundle\DoctrineBundle\Registry - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %doctrine.dbal.connection_factory.types% - - - - - - - - - - - - - - - %doctrine.connections% - %doctrine.entity_managers% - %doctrine.default_connection% - %doctrine.default_entity_manager% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/doctrine/doctrine-bundle/Resources/config/messenger.xml b/vendor/doctrine/doctrine-bundle/Resources/config/messenger.xml deleted file mode 100644 index f6ae1cf..0000000 --- a/vendor/doctrine/doctrine-bundle/Resources/config/messenger.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/doctrine/doctrine-bundle/Resources/config/orm.xml b/vendor/doctrine/doctrine-bundle/Resources/config/orm.xml deleted file mode 100644 index 929fba7..0000000 --- a/vendor/doctrine/doctrine-bundle/Resources/config/orm.xml +++ /dev/null @@ -1,213 +0,0 @@ - - - - - - Doctrine\ORM\Configuration - Doctrine\ORM\EntityManager - Doctrine\Bundle\DoctrineBundle\ManagerConfigurator - - - Doctrine\Common\Cache\ArrayCache - Doctrine\Common\Cache\ApcCache - Doctrine\Common\Cache\MemcacheCache - localhost - 11211 - Memcache - Doctrine\Common\Cache\MemcachedCache - localhost - 11211 - Memcached - Doctrine\Common\Cache\RedisCache - localhost - 6379 - Redis - Doctrine\Common\Cache\XcacheCache - Doctrine\Common\Cache\WinCacheCache - Doctrine\Common\Cache\ZendDataCache - - - Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain - Doctrine\ORM\Mapping\Driver\AnnotationDriver - Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver - Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver - Doctrine\ORM\Mapping\Driver\PHPDriver - Doctrine\ORM\Mapping\Driver\StaticPHPDriver - - - Symfony\Bridge\Doctrine\CacheWarmer\ProxyCacheWarmer - - - Symfony\Bridge\Doctrine\Form\DoctrineOrmTypeGuesser - - - Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator - Symfony\Bridge\Doctrine\Validator\DoctrineInitializer - - - Symfony\Bridge\Doctrine\Security\User\EntityUserProvider - - - Doctrine\ORM\Tools\ResolveTargetEntityListener - Doctrine\ORM\Tools\AttachEntityListenersListener - - - Doctrine\ORM\Mapping\DefaultNamingStrategy - Doctrine\ORM\Mapping\UnderscoreNamingStrategy - - - Doctrine\ORM\Mapping\DefaultQuoteStrategy - Doctrine\ORM\Mapping\AnsiQuoteStrategy - - - Doctrine\Bundle\DoctrineBundle\Mapping\ContainerEntityListenerResolver - - - Doctrine\ORM\Cache\DefaultCacheFactory - Doctrine\ORM\Cache\Region\DefaultRegion - Doctrine\ORM\Cache\Region\FileLockRegion - Doctrine\ORM\Cache\Logging\CacheLoggerChain - Doctrine\ORM\Cache\Logging\StatisticsCacheLogger - Doctrine\ORM\Cache\CacheConfiguration - Doctrine\ORM\Cache\RegionsConfiguration - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CASE_LOWER - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %kernel.bundles% - - - - - diff --git a/vendor/doctrine/doctrine-bundle/Resources/config/schema/doctrine-1.0.xsd b/vendor/doctrine/doctrine-bundle/Resources/config/schema/doctrine-1.0.xsd deleted file mode 100644 index 58bab75..0000000 --- a/vendor/doctrine/doctrine-bundle/Resources/config/schema/doctrine-1.0.xsd +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/doctrine/doctrine-bundle/Resources/views/Collector/db.html.twig b/vendor/doctrine/doctrine-bundle/Resources/views/Collector/db.html.twig deleted file mode 100644 index 9dc79f6..0000000 --- a/vendor/doctrine/doctrine-bundle/Resources/views/Collector/db.html.twig +++ /dev/null @@ -1,528 +0,0 @@ -{% extends request.isXmlHttpRequest ? '@WebProfiler/Profiler/ajax_layout.html.twig' : '@WebProfiler/Profiler/layout.html.twig' %} - -{% import _self as helper %} - -{% block toolbar %} - {% if collector.querycount > 0 or collector.invalidEntityCount > 0 %} - - {% set profiler_markup_version = profiler_markup_version|default(1) %} - - {% set icon %} - {% if profiler_markup_version == 1 %} - - Database - {{ collector.querycount }} - {% if collector.querycount > 0 %} - in {{ '%0.2f'|format(collector.time * 1000) }} ms - {% endif %} - {% if collector.invalidEntityCount > 0 %} - {{ collector.invalidEntityCount }} - {% endif %} - - {% else %} - - {% set status = collector.invalidEntityCount > 0 ? 'red' : collector.querycount > 50 ? 'yellow' %} - - {{ include('@Doctrine/Collector/icon.svg') }} - - {% if collector.querycount == 0 and collector.invalidEntityCount > 0 %} - {{ collector.invalidEntityCount }} - errors - {% else %} - {{ collector.querycount }} - - in - {{ '%0.2f'|format(collector.time * 1000) }} - ms - - {% endif %} - - {% endif %} - {% endset %} - - {% set text %} -
    - Database Queries - {{ collector.querycount }} -
    -
    - Query time - {{ '%0.2f'|format(collector.time * 1000) }} ms -
    -
    - Invalid entities - {{ collector.invalidEntityCount }} -
    - {% if collector.cacheEnabled %} -
    - Cache hits - {{ collector.cacheHitsCount }} -
    -
    - Cache misses - {{ collector.cacheMissesCount }} -
    -
    - Cache puts - {{ collector.cachePutsCount }} -
    - {% else %} -
    - Second Level Cache - disabled -
    - {% endif %} - {% endset %} - - {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: status|default('') }) }} - - {% endif %} -{% endblock %} - -{% block menu %} - {% set profiler_markup_version = profiler_markup_version|default(1) %} - - {% if profiler_markup_version == 1 %} - - - - Doctrine - - {{ collector.querycount }} - {{ '%0.0f'|format(collector.time * 1000) }} ms - - - - {% else %} - - - {{ include('@Doctrine/Collector/icon.svg') }} - Doctrine - {% if collector.invalidEntityCount %} - - {{ collector.invalidEntityCount }} - - {% endif %} - - - {% endif %} -{% endblock %} - -{% block panel %} - {% set profiler_markup_version = profiler_markup_version|default(1) %} - - {% if 'explain' == page %} - {{ render(controller('DoctrineBundle:Profiler:explain', { - token: token, - panel: 'db', - connectionName: request.query.get('connection'), - query: request.query.get('query') - })) }} - {% else %} - {{ block('queries') }} - {% endif %} -{% endblock %} - -{% block queries %} - - - {% if profiler_markup_version > 1 %} -

    Query Metrics

    - -
    -
    - {{ collector.querycount }} - Database Queries -
    - -
    - {{ collector.groupedQueryCount }} - Different statements -
    - -
    - {{ '%0.2f'|format(collector.time * 1000) }} ms - Query time -
    - -
    - {{ collector.invalidEntityCount }} - Invalid entities -
    - - {% if collector.cacheEnabled %} -
    - {{ collector.cacheHitsCount }} - Cache hits -
    -
    - {{ collector.cacheMissesCount }} - Cache misses -
    -
    - {{ collector.cachePutsCount }} - Cache puts -
    - {% endif %} -
    - {% endif %} - - {% set group_queries = request.query.getBoolean('group') %} - {% if group_queries %} -

    Grouped Statements

    -

    Show all queries

    - {% else %} -

    Queries

    -

    Group similar statements

    - {% endif %} - - {% for connection, queries in collector.queries %} - {% if collector.connections|length > 1 %} -

    {{ connection }} connection

    - {% endif %} - - {% if queries is empty %} -
    -

    No database queries were performed.

    -
    - {% else %} - {% if group_queries %} - {% set queries = collector.groupedQueries[connection] %} - {% endif %} - - - - {% if group_queries %} - - - {% else %} - - - {% endif %} - - - - - {% for i, query in queries %} - {% set i = group_queries ? query.index : i %} - - {% if group_queries %} - - - {% else %} - - - {% endif %} - - - {% endfor %} - -
    TimeCount#TimeInfo
    - - {{ '%0.2f'|format(query.executionMS * 1000) }} ms
    ({{ '%0.2f'|format(query.executionPercent) }}%)
    -
    {{ query.count }}{{ loop.index }}{{ '%0.2f'|format(query.executionMS * 1000) }} ms - {{ query.sql|doctrine_pretty_query(highlight_only = true) }} - -
    - Parameters: {{ profiler_dump(query.params, 2) }} -
    - -
    - View formatted query - - {% if query.runnable %} -    - View runnable query - {% endif %} - - {% if query.explainable %} -    - Explain query - {% endif %} - - {% if query.backtrace is defined %} -    - View query backtrace - {% endif %} -
    - - - - {% if query.runnable %} - - {% endif %} - - {% if query.explainable %} -
    - {% endif %} - - {% if query.backtrace is defined %} - - {% endif %} -
    - {% endif %} - {% endfor %} - -

    Database Connections

    - - {% if not collector.connections %} -
    -

    There are no configured database connections.

    -
    - {% else %} - {{ helper.render_simple_table('Name', 'Service', collector.connections) }} - {% endif %} - -

    Entity Managers

    - - {% if not collector.managers %} -
    -

    There are no configured entity managers.

    -
    - {% else %} - {{ helper.render_simple_table('Name', 'Service', collector.managers) }} - {% endif %} - -

    Second Level Cache

    - - {% if not collector.cacheEnabled %} -
    -

    Second Level Cache is not enabled.

    -
    - {% else %} - {% if not collector.cacheCounts %} -
    -

    Second level cache information is not available.

    -
    - {% else %} - {% if profiler_markup_version == 1 %} - {{ helper.render_simple_table('Key', 'Value', collector.cacheCounts) }} - {% else %} -
    -
    - {{ collector.cacheCounts.hits }} - Hits -
    - -
    - {{ collector.cacheCounts.misses }} - Misses -
    - -
    - {{ collector.cacheCounts.puts }} - Puts -
    -
    - {% endif %} - - {% if collector.cacheRegions.hits %} -

    Number of cache hits

    - {{ helper.render_simple_table('Region', 'Hits', collector.cacheRegions.hits) }} - {% endif %} - - {% if collector.cacheRegions.misses %} -

    Number of cache misses

    - {{ helper.render_simple_table('Region', 'Misses', collector.cacheRegions.misses) }} - {% endif %} - - {% if collector.cacheRegions.puts %} -

    Number of cache puts

    - {{ helper.render_simple_table('Region', 'Puts', collector.cacheRegions.puts) }} - {% endif %} - {% endif %} - {% endif %} - -

    Entities Mapping

    - - {% for manager, classes in collector.entities %} - {% if collector.managers|length > 1 %} -

    {{ manager }} entity manager

    - {% endif %} - - {% if classes is empty %} -
    -

    No loaded entities.

    -
    - {% else %} - - - - - - - - - {% for class in classes %} - {% set contains_errors = collector.mappingErrors[manager] is defined and collector.mappingErrors[manager][class] is defined %} - - - - - {% endfor %} - -
    ClassMapping errors
    {{ class }} - {% if contains_errors %} -
      - {% for error in collector.mappingErrors[manager][class] %} -
    • {{ error }}
    • - {% endfor %} -
    - {% else %} - No errors. - {% endif %} -
    - {% endif %} - {% endfor %} - - -{% endblock %} - -{% macro render_simple_table(label1, label2, data) %} - - - - - - - - - {% for key, value in data %} - - - - - {% endfor %} - -
    {{ label1 }}{{ label2 }}
    {{ key }}{{ value }}
    -{% endmacro %} diff --git a/vendor/doctrine/doctrine-bundle/Resources/views/Collector/explain.html.twig b/vendor/doctrine/doctrine-bundle/Resources/views/Collector/explain.html.twig deleted file mode 100644 index 3b2dd7f..0000000 --- a/vendor/doctrine/doctrine-bundle/Resources/views/Collector/explain.html.twig +++ /dev/null @@ -1,28 +0,0 @@ -{% if data[0]|length > 1 %} - {# The platform returns a table for the explanation (e.g. MySQL), display all columns #} - - - - {% for label in data[0]|keys %} - - {% endfor %} - - - - {% for row in data %} - - {% for key, item in row %} - - {% endfor %} - - {% endfor %} - -
    {{ label }}
    {{ item|replace({',': ', '}) }}
    -{% else %} - {# The Platform returns a single column for a textual explanation (e.g. PostgreSQL), display all lines #} -
    -        {%- for row in data -%}
    -            {{ row|first }}{{ "\n" }}
    -        {%- endfor -%}
    -    
    -{% endif %} diff --git a/vendor/doctrine/doctrine-bundle/Resources/views/Collector/icon.svg b/vendor/doctrine/doctrine-bundle/Resources/views/Collector/icon.svg deleted file mode 100644 index 49fb528..0000000 --- a/vendor/doctrine/doctrine-bundle/Resources/views/Collector/icon.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/vendor/doctrine/doctrine-bundle/Twig/DoctrineExtension.php b/vendor/doctrine/doctrine-bundle/Twig/DoctrineExtension.php deleted file mode 100644 index b06ac94..0000000 --- a/vendor/doctrine/doctrine-bundle/Twig/DoctrineExtension.php +++ /dev/null @@ -1,203 +0,0 @@ - ['html']]), - new TwigFilter('doctrine_replace_query_parameters', [$this, 'replaceQueryParameters']), - ]; - } - - /** - * Get the possible combinations of elements from the given array - * - * @param array $elements - * @param int $combinationsLevel - * - * @return array - */ - private function getPossibleCombinations(array $elements, $combinationsLevel) - { - $baseCount = count($elements); - $result = []; - - if ($combinationsLevel === 1) { - foreach ($elements as $element) { - $result[] = [$element]; - } - - return $result; - } - - $nextLevelElements = $this->getPossibleCombinations($elements, $combinationsLevel - 1); - - foreach ($nextLevelElements as $nextLevelElement) { - $lastElement = $nextLevelElement[$combinationsLevel - 2]; - $found = false; - - foreach ($elements as $key => $element) { - if ($element === $lastElement) { - $found = true; - continue; - } - - if ($found !== true || $key >= $baseCount) { - continue; - } - - $tmp = $nextLevelElement; - $newCombination = array_slice($tmp, 0); - $newCombination[] = $element; - $result[] = array_slice($newCombination, 0); - } - } - - return $result; - } - - /** - * Escape parameters of a SQL query - * DON'T USE THIS FUNCTION OUTSIDE ITS INTENDED SCOPE - * - * @internal - * - * @param mixed $parameter - * - * @return string - */ - public static function escapeFunction($parameter) - { - $result = $parameter; - - switch (true) { - // Check if result is non-unicode string using PCRE_UTF8 modifier - case is_string($result) && ! preg_match('//u', $result): - $result = '0x' . strtoupper(bin2hex($result)); - break; - - case is_string($result): - $result = "'" . addslashes($result) . "'"; - break; - - case is_array($result): - foreach ($result as &$value) { - $value = static::escapeFunction($value); - } - - $result = implode(', ', $result); - break; - - case is_object($result): - $result = addslashes((string) $result); - break; - - case $result === null: - $result = 'NULL'; - break; - - case is_bool($result): - $result = $result ? '1' : '0'; - break; - } - - return $result; - } - - /** - * Return a query with the parameters replaced - * - * @param string $query - * @param array|Data $parameters - * - * @return string - */ - public function replaceQueryParameters($query, $parameters) - { - if ($parameters instanceof Data) { - $parameters = $parameters->getValue(true); - } - - $i = 0; - - if (! array_key_exists(0, $parameters) && array_key_exists(1, $parameters)) { - $i = 1; - } - - return preg_replace_callback( - '/\?|((?([^"]*+)<\/pre>/Us', '\1', $html); - } else { - $html = SqlFormatter::format($sql); - $html = preg_replace('/
    ([^"]*+)<\/pre>/Us', '
    \2
    ', $html); - } - - return $html; - } - - /** - * Get the name of the extension - * - * @return string - */ - public function getName() - { - return 'doctrine_extension'; - } -} diff --git a/vendor/doctrine/doctrine-bundle/UPGRADE-1.11.md b/vendor/doctrine/doctrine-bundle/UPGRADE-1.11.md deleted file mode 100644 index a2fc073..0000000 --- a/vendor/doctrine/doctrine-bundle/UPGRADE-1.11.md +++ /dev/null @@ -1,35 +0,0 @@ -UPGRADE FROM 1.10 to 1.11 -========================= - -PHP and Symfony version support -------------------------------- - - * Support for PHP 5.5, 5.6 and 7.0 was dropped - * Support for unsupported Symfony versions was dropped. The bundle now supports - Symfony 3.4 LTS and 4.1 or newer. - * Support for Twig 1.34 and below as well as 2.4 and below (for 2.x) releases - was dropped. - -Commands --------- - - * Deprecated instantiating `Doctrine\Bundle\DoctrineBundle\Command` without a - `ManagerRegistry` instance. - * Deprecated `setContainer` and `getContainer` in - `Doctrine\Bundle\DoctrineBundle\Command`. - * `Doctrine\Bundle\DoctrineBundle\Command` no longer implements - `ContainerAwareInterface`. - -Mapping -------- - - * Renamed `ContainerAwareEntityListenerResolver` to - `ContainerEntityListenerResolver`. - -Types ------ - - * Marking types as commented in the configuration is deprecated. Instead, mark - them commented using the `requiresSQLCommentHint()` method of the type. - * The `commented` configuration option for types will be dropped in a future - release. You should avoid using it. diff --git a/vendor/doctrine/doctrine-bundle/UPGRADE-1.12.md b/vendor/doctrine/doctrine-bundle/UPGRADE-1.12.md deleted file mode 100644 index c180996..0000000 --- a/vendor/doctrine/doctrine-bundle/UPGRADE-1.12.md +++ /dev/null @@ -1,17 +0,0 @@ -UPGRADE FROM 1.11 to 1.12 -========================= - -Deprecation of DoctrineCacheBundle ----------------------------------- - -With DoctrineCacheBundle [being deprecated](https://github.com/doctrine/DoctrineCacheBundle/issues/156), -configuring caches through it has been deprecated. If you are using anything -other than the `pool` or `id` cache types, please update your configuration to -either use symfony/cache through the `pool` type or configure your cache -services manually and use the `service` type. - -Service aliases ---------------- - - * Deprecated the `Symfony\Bridge\Doctrine\RegistryInterface` and `Doctrine\Bundle\DoctrineBundle\Registry` service alias, use `Doctrine\Common\Persistence\ManagerRegistry` instead. - * Deprecated the `Doctrine\Common\Persistence\ObjectManager` service alias, use `Doctrine\ORM\EntityManagerInterface` instead. diff --git a/vendor/doctrine/doctrine-bundle/UPGRADE-2.0.md b/vendor/doctrine/doctrine-bundle/UPGRADE-2.0.md deleted file mode 100644 index 82aee80..0000000 --- a/vendor/doctrine/doctrine-bundle/UPGRADE-2.0.md +++ /dev/null @@ -1,63 +0,0 @@ -UPGRADE FROM 1.x to 2.0 -======================= - -PHP and Symfony version support -------------------------------- - - * Support for PHP 5.5, 5.6 and 7.0 was dropped - * Support for unsupported Symfony versions was dropped. The bundle now supports - Symfony 3.4 LTS and 4.1 or newer. - * Support for Twig 1.34 and below as well as 2.4 and below (for 2.x) releases - was dropped. - * When no charset parameter is defined, it now defaults to `utf8mb4` on the - MySQL platform and to `utf8` on all other platforms. - -Commands --------- - - * `Doctrine\Bundle\DoctrineBundle\Command` requires a `ManagerRegistry` - instance when instantiating. - * Dropped `setContainer` and `getContainer` in - `Doctrine\Bundle\DoctrineBundle\Command`. - * `Doctrine\Bundle\DoctrineBundle\Command` no longer implements - `ContainerAwareInterface`. - * `Doctrine\Bundle\DoctrineBundle\Command\GenerateEntitiesDoctrineCommand` was - dropped in favour of the MakerBundle. - -Deprecation of DoctrineCacheBundle ----------------------------------- - -Configuring caches through DoctrineCacheBundle is no longer possible. Please use -symfony/cache through the `pool` type or configure your cache services manually -and use the `service` type. - -Mapping -------- - - * Dropped `ContainerAwareEntityListenerResolver`, use - `ContainerEntityListenerResolver` instead. - -Registry --------- - - * `Registry` no longer implements `Symfony\Bridge\Doctrine\RegistryInterface`. - * Removed all deprecated entity manager specific methods from the registry. - -Service aliases ---------------- - - * The `Symfony\Bridge\Doctrine\RegistryInterface` interface is no longer aliased - to the `doctrine` service, use `Doctrine\Common\Persistence\ManagerRegistry` - instead. - * The `Doctrine\Common\Persistence\ObjectManager` interface is no longer - aliased to the `doctrine.orm.entity_manager` service, use - `Doctrine\ORM\EntityManagerInterface` instead. - -Types ------ - - * Marking types as commented in the configuration is no longer supported. - Instead, mark them commented using the `requiresSQLCommentHint()` method of - the type. - * The `commented` configuration option for types will be dropped in a future - release. You should not use it. diff --git a/vendor/doctrine/doctrine-bundle/UPGRADE-3.0.md b/vendor/doctrine/doctrine-bundle/UPGRADE-3.0.md deleted file mode 100644 index 03ee914..0000000 --- a/vendor/doctrine/doctrine-bundle/UPGRADE-3.0.md +++ /dev/null @@ -1,8 +0,0 @@ -UPGRADE FROM 2.x to 3.0 -======================= - -Types ------ - - * The `commented` configuration option for types is no longer supported and - deprecated. diff --git a/vendor/doctrine/doctrine-bundle/composer.json b/vendor/doctrine/doctrine-bundle/composer.json deleted file mode 100644 index bed6ef9..0000000 --- a/vendor/doctrine/doctrine-bundle/composer.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "name": "doctrine/doctrine-bundle", - "type": "symfony-bundle", - "description": "Symfony DoctrineBundle", - "keywords": ["DBAL", "ORM", "Database", "Persistence"], - "homepage": "http://www.doctrine-project.org", - "license": "MIT", - "minimum-stability": "dev", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - }, - { - "name": "Doctrine Project", - "homepage": "http://www.doctrine-project.org/" - } - ], - "require": { - "php": "^7.1", - "doctrine/dbal": "^2.9.0", - "doctrine/persistence": "^1.3.3", - "jdorn/sql-formatter": "^1.2.16", - "symfony/cache": "^4.3.3|^5.0", - "symfony/config": "^4.3.3|^5.0", - "symfony/console": "^3.4.30|^4.3.3|^5.0", - "symfony/dependency-injection": "^4.3.3|^5.0", - "symfony/doctrine-bridge": "^4.3.7|^5.0", - "symfony/framework-bundle": "^3.4.30|^4.3.3|^5.0", - "symfony/service-contracts": "^1.1.1|^2.0" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "doctrine/orm": "^2.6", - "ocramius/proxy-manager": "^2.1", - "phpunit/phpunit": "^7.5", - "symfony/phpunit-bridge": "^4.2", - "symfony/property-info": "^4.3.3|^5.0", - "symfony/twig-bridge": "^3.4.30|^4.3.3|^5.0", - "symfony/validator": "^3.4.30|^4.3.3|^5.0", - "symfony/yaml": "^3.4.30|^4.3.3|^5.0", - "twig/twig": "^1.34|^2.12", - "symfony/web-profiler-bundle": "^3.4.30|^4.3.3|^5.0" - }, - "config": { - "sort-packages": true - }, - "conflict": { - "doctrine/orm": "<2.6", - "twig/twig": "<1.34|>=2.0,<2.4" - }, - "suggest": { - "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", - "symfony/web-profiler-bundle": "To use the data collector." - }, - "autoload": { - "psr-4": { "Doctrine\\Bundle\\DoctrineBundle\\": "" } - }, - "autoload-dev": { - "psr-4": { "": "Tests/DependencyInjection" } - }, - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - } -} diff --git a/vendor/doctrine/doctrine-bundle/phpcs.xml.dist b/vendor/doctrine/doctrine-bundle/phpcs.xml.dist deleted file mode 100644 index c91a02d..0000000 --- a/vendor/doctrine/doctrine-bundle/phpcs.xml.dist +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - . - vendor/* - - - - - - - - - - - - - - - - - Tests/* - - - Tests/* - - - Tests/DependencyInjection/Fixtures/* - - - DependencyInjection/* - Twig/DoctrineExtension.php - Tests/* - - - DependencyInjection/* - Twig/DoctrineExtension.php - Tests/* - - - DependencyInjection/* - Twig/DoctrineExtension.php - Tests/* - - diff --git a/vendor/doctrine/doctrine-fixtures-bundle/.github/FUNDING.yml b/vendor/doctrine/doctrine-fixtures-bundle/.github/FUNDING.yml deleted file mode 100644 index 3c0102b..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/.github/FUNDING.yml +++ /dev/null @@ -1,3 +0,0 @@ -patreon: phpdoctrine -tidelift: packagist/doctrine%2Fdoctrine-fixtures-bundle -custom: https://www.doctrine-project.org/sponsorship.html diff --git a/vendor/doctrine/doctrine-fixtures-bundle/.gitignore b/vendor/doctrine/doctrine-fixtures-bundle/.gitignore deleted file mode 100644 index 2b1bf5a..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -.phpcs-cache diff --git a/vendor/doctrine/doctrine-fixtures-bundle/.travis.yml b/vendor/doctrine/doctrine-fixtures-bundle/.travis.yml deleted file mode 100644 index 284ebee..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/.travis.yml +++ /dev/null @@ -1,45 +0,0 @@ -language: php -sudo: false -cache: - directories: - - $HOME/.composer/cache/files - -php: - - 7.1 - - 7.2 - - 7.3 - - 7.4snapshot - -jobs: - include: - # Minimum supported PHP and Symfony version - - stage: test - php: 7.1 - env: DEPENDENCIES="minimum" - - # Test LTS version we support - - stage: test - php: 7.3 - env: DEPENDENCIES="symfony/lts:v3" - - - stage: test - php: 7.3 - env: DEPENDENCIES="dev" - - # Run phpcs - - stage: Code Quality - php: 7.2 - env: CODING_STANDARDS - script: - - vendor/bin/phpcs - -before_install: - - if [ "$DEPENDENCIES" = "minimum" ]; then COMPOSER_FLAGS="--prefer-stable --prefer-lowest"; fi; - - if [ "$DEPENDENCIES" = "dev" ]; then composer config minimum-stability dev; fi; - - if [[ $DEPENDENCIES == *"/"* ]]; then composer require --no-update $DEPENDENCIES; fi; - -install: - - travis_retry composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction - -script: - - vendor/bin/phpunit diff --git a/vendor/doctrine/doctrine-fixtures-bundle/CHANGELOG-3.1.md b/vendor/doctrine/doctrine-fixtures-bundle/CHANGELOG-3.1.md deleted file mode 100644 index 7f8d2fc..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/CHANGELOG-3.1.md +++ /dev/null @@ -1,14 +0,0 @@ -CHANGELOG for 3.1.x -=================== - -This changelog references the relevant changes (bug and security fixes) done in -3.1 minor versions. - -3.1.0 (2018-12-21) ------------------- - - - [270: Show the name of the database being purged when loading fixtures](https://github.com/doctrine/DoctrineFixturesBundle/pull/270) thanks to @alcaeus - - [265: Drop support for PHP < 7.1 and older versions of data-fixtures](https://github.com/doctrine/DoctrineFixturesBundle/pull/265) thanks to @alcaeus - - [260: Add fixture groups via a static method interface or service tags](https://github.com/doctrine/DoctrineFixturesBundle/pull/260) thanks to @weaverryan - - [269: Apply Doctrine Coding Standard](https://github.com/doctrine/DoctrineFixturesBundle/pull/269) thanks to @carusogabriel - - [219: Dynamic namespace](https://github.com/doctrine/DoctrineFixturesBundle/issues/219) thanks to @MassiveHiggsField diff --git a/vendor/doctrine/doctrine-fixtures-bundle/Command/LoadDataFixturesDoctrineCommand.php b/vendor/doctrine/doctrine-fixtures-bundle/Command/LoadDataFixturesDoctrineCommand.php deleted file mode 100644 index 87f7604..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/Command/LoadDataFixturesDoctrineCommand.php +++ /dev/null @@ -1,131 +0,0 @@ -fixturesLoader = $fixturesLoader; - } - - // phpcs:ignore SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingReturnTypeHint - protected function configure() - { - $this - ->setName('doctrine:fixtures:load') - ->setDescription('Load data fixtures to your database') - ->addOption('append', null, InputOption::VALUE_NONE, 'Append the data fixtures instead of deleting all data from the database first.') - ->addOption('group', null, InputOption::VALUE_IS_ARRAY|InputOption::VALUE_REQUIRED, 'Only load fixtures that belong to this group') - ->addOption('em', null, InputOption::VALUE_REQUIRED, 'The entity manager to use for this command.') - ->addOption('shard', null, InputOption::VALUE_REQUIRED, 'The shard connection to use for this command.') - ->addOption('purge-with-truncate', null, InputOption::VALUE_NONE, 'Purge data by using a database-level TRUNCATE statement') - ->setHelp(<<%command.name% command loads data fixtures from your application: - - php %command.full_name% - -Fixtures are services that are tagged with doctrine.fixture.orm. - -If you want to append the fixtures instead of flushing the database first you can use the --append option: - - php %command.full_name% --append - -By default Doctrine Data Fixtures uses DELETE statements to drop the existing rows from the database. -If you want to use a TRUNCATE statement instead you can use the --purge-with-truncate flag: - - php %command.full_name% --purge-with-truncate - -To execute only fixtures that live in a certain group, use: - - php %command.full_name% --group=group1 - -EOT - ); - } - - /** - * @return int - */ - // phpcs:ignore SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingReturnTypeHint - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - $em = $this->getDoctrine()->getManager($input->getOption('em')); - - if (! $input->getOption('append')) { - if (! $ui->confirm(sprintf('Careful, database "%s" will be purged. Do you want to continue?', $em->getConnection()->getDatabase()), ! $input->isInteractive())) { - return 0; - } - } - - if ($input->getOption('shard')) { - if (! $em->getConnection() instanceof PoolingShardConnection) { - throw new LogicException(sprintf( - 'Connection of EntityManager "%s" must implement shards configuration.', - $input->getOption('em') - )); - } - - $em->getConnection()->connect($input->getOption('shard')); - } - - $groups = $input->getOption('group'); - $fixtures = $this->fixturesLoader->getFixtures($groups); - if (! $fixtures) { - $message = 'Could not find any fixture services to load'; - - if (! empty($groups)) { - $message .= sprintf(' in the groups (%s)', implode(', ', $groups)); - } - - $ui->error($message . '.'); - - return 1; - } - $purger = new ORMPurger($em); - $purger->setPurgeMode($input->getOption('purge-with-truncate') ? ORMPurger::PURGE_MODE_TRUNCATE : ORMPurger::PURGE_MODE_DELETE); - $executor = new ORMExecutor($em, $purger); - $executor->setLogger(static function ($message) use ($ui) : void { - $ui->text(sprintf(' > %s', $message)); - }); - $executor->execute($fixtures, $input->getOption('append')); - - return 0; - } -} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/CompilerPass/FixturesCompilerPass.php b/vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/CompilerPass/FixturesCompilerPass.php deleted file mode 100644 index 5fc5b4a..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/CompilerPass/FixturesCompilerPass.php +++ /dev/null @@ -1,39 +0,0 @@ -getDefinition('doctrine.fixtures.loader'); - $taggedServices = $container->findTaggedServiceIds(self::FIXTURE_TAG); - - $fixtures = []; - foreach ($taggedServices as $serviceId => $tags) { - $groups = []; - foreach ($tags as $tagData) { - if (! isset($tagData['group'])) { - continue; - } - - $groups[] = $tagData['group']; - } - - $fixtures[] = [ - 'fixture' => new Reference($serviceId), - 'groups' => $groups, - ]; - } - - $definition->addMethodCall('addFixtures', [$fixtures]); - } -} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/DoctrineFixturesExtension.php b/vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/DoctrineFixturesExtension.php deleted file mode 100644 index 0dd4beb..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/DependencyInjection/DoctrineFixturesExtension.php +++ /dev/null @@ -1,29 +0,0 @@ -load('services.xml'); - - $container->registerForAutoconfiguration(ORMFixtureInterface::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - } -} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/DoctrineFixturesBundle.php b/vendor/doctrine/doctrine-fixtures-bundle/DoctrineFixturesBundle.php deleted file mode 100644 index 256fc74..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/DoctrineFixturesBundle.php +++ /dev/null @@ -1,21 +0,0 @@ -addCompilerPass(new FixturesCompilerPass()); - } -} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/Fixture.php b/vendor/doctrine/doctrine-fixtures-bundle/Fixture.php deleted file mode 100644 index 3fb0cee..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/Fixture.php +++ /dev/null @@ -1,15 +0,0 @@ -> */ - private $groupsFixtureMapping = []; - - /** - * @internal - */ - public function addFixtures(array $fixtures) : void - { - // Because parent::addFixture may call $this->createFixture - // we cannot call $this->addFixture in this loop - foreach ($fixtures as $fixture) { - $class = get_class($fixture['fixture']); - $this->loadedFixtures[$class] = $fixture['fixture']; - $this->addGroupsFixtureMapping($class, $fixture['groups']); - } - - // Now that all fixtures are in the $this->loadedFixtures array, - // it is safe to call $this->addFixture in this loop - foreach ($this->loadedFixtures as $fixture) { - $this->addFixture($fixture); - } - } - - public function addFixture(FixtureInterface $fixture) : void - { - $class = get_class($fixture); - $this->loadedFixtures[$class] = $fixture; - - $reflection = new ReflectionClass($fixture); - $this->addGroupsFixtureMapping($class, [$reflection->getShortName()]); - - if ($fixture instanceof FixtureGroupInterface) { - $this->addGroupsFixtureMapping($class, $fixture::getGroups()); - } - - parent::addFixture($fixture); - } - - /** - * Overridden to not allow new fixture classes to be instantiated. - * - * @param string $class - */ - protected function createFixture($class) : FixtureInterface - { - /* - * We don't actually need to create the fixture. We just - * return the one that already exists. - */ - - if (! isset($this->loadedFixtures[$class])) { - throw new LogicException(sprintf( - 'The "%s" fixture class is trying to be loaded, but is not available. Make sure this class is defined as a service and tagged with "%s".', - $class, - FixturesCompilerPass::FIXTURE_TAG - )); - } - - return $this->loadedFixtures[$class]; - } - - /** - * Returns the array of data fixtures to execute. - * - * @param string[] $groups - * - * @return FixtureInterface[] - */ - public function getFixtures(array $groups = []) : array - { - $fixtures = parent::getFixtures(); - - if (empty($groups)) { - return $fixtures; - } - - $filteredFixtures = []; - foreach ($fixtures as $fixture) { - foreach ($groups as $group) { - $fixtureClass = get_class($fixture); - if (isset($this->groupsFixtureMapping[$group][$fixtureClass])) { - $filteredFixtures[$fixtureClass] = $fixture; - continue 2; - } - } - } - - foreach ($filteredFixtures as $fixture) { - $this->validateDependencies($filteredFixtures, $fixture); - } - - return array_values($filteredFixtures); - } - - /** - * Generates an array of the groups and their fixtures - * - * @param string[] $groups - */ - private function addGroupsFixtureMapping(string $className, array $groups) : void - { - foreach ($groups as $group) { - $this->groupsFixtureMapping[$group][$className] = true; - } - } - - /** - * @param string[] $fixtures An array of fixtures with class names as keys - * - * @throws RuntimeException - */ - private function validateDependencies(array $fixtures, FixtureInterface $fixture) : void - { - if (! $fixture instanceof DependentFixtureInterface) { - return; - } - - $dependenciesClasses = $fixture->getDependencies(); - - foreach ($dependenciesClasses as $class) { - if (! array_key_exists($class, $fixtures)) { - throw new RuntimeException(sprintf('Fixture "%s" was declared as a dependency for fixture "%s", but it was not included in any of the loaded fixture groups.', $class, get_class($fixture))); - } - } - } -} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/ORMFixtureInterface.php b/vendor/doctrine/doctrine-fixtures-bundle/ORMFixtureInterface.php deleted file mode 100644 index 59260d9..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/ORMFixtureInterface.php +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/vendor/doctrine/doctrine-fixtures-bundle/Resources/doc/index.rst b/vendor/doctrine/doctrine-fixtures-bundle/Resources/doc/index.rst deleted file mode 100644 index 06bcb90..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/Resources/doc/index.rst +++ /dev/null @@ -1,293 +0,0 @@ -DoctrineFixturesBundle -====================== - -Fixtures are used to load a "fake" set of data into a database that can then -be used for testing or to help give you some interesting data while you're -developing your application. This bundle makes creating fixtures *easy*, and -supports the `ORM`_ (MySQL, PostgreSQL, SQLite, etc.). - -Installation ------------- - -In Symfony 4 or higher applications that use `Symfony Flex`_, open a command -console, enter your project directory and run the following command: - -.. code-block:: terminal - - $ composer require --dev orm-fixtures - -Starting from Symfony 4.0, Flex should be used by default and register the -bundle for you, and in that case you can skip to the next section and start -writing fixtures. - -In Symfony 3 applications (or when not using Symfony Flex), run this other -command instead: - -.. code-block:: terminal - - $ composer require --dev doctrine/doctrine-fixtures-bundle - -You will also need to enable the bundle. In Symfony 3 and earlier applications, -update the ``AppKernel`` class:: - - // app/AppKernel.php - - // ... - // registerBundles() - if (in_array($this->getEnvironment(), ['dev', 'test'], true)) { - // ... - $bundles[] = new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(); - } - -Writing Fixtures ----------------- - -Data fixtures are PHP classes where you create objects and persist them to the -database. - -Imagine that you want to add some ``Product`` objects to your database. No problem! -Create a fixtures class and start adding products:: - - // src/DataFixtures/AppFixtures.php - namespace App\DataFixtures; - - use App\Entity\Product; - use Doctrine\Bundle\FixturesBundle\Fixture; - use Doctrine\Common\Persistence\ObjectManager; - - class AppFixtures extends Fixture - { - public function load(ObjectManager $manager) - { - // create 20 products! Bam! - for ($i = 0; $i < 20; $i++) { - $product = new Product(); - $product->setName('product '.$i); - $product->setPrice(mt_rand(10, 100)); - $manager->persist($product); - } - - $manager->flush(); - } - } - -.. tip:: - - You can also create multiple fixtures classes. See :ref:`multiple-files`. - -Loading Fixtures ----------------- - -Once your fixtures have been written, load them by executing this command: - -.. code-block:: terminal - - # when using the ORM - $ php bin/console doctrine:fixtures:load - -.. caution:: - - By default the ``load`` command **purges the database**, removing all data - from every table. To append your fixtures' data add the ``--append`` option. - -This command looks for all services tagged with ``doctrine.fixture.orm``. If you're -using the `default service configuration`_, any class that implements ``ORMFixtureInterface`` -(for example, those extending from ``Fixture``) will automatically be registered -with this tag. - -To see other options for the command, run: - -.. code-block:: terminal - - $ php bin/console doctrine:fixtures:load --help - -Accessing Services from the Fixtures ------------------------------------- - -In some cases you may need to access your application's services inside a fixtures -class. No problem! Your fixtures class is a service, so you can use normal dependency -injection:: - - // src/DataFixtures/AppFixtures.php - use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; - - // ... - private $encoder; - - public function __construct(UserPasswordEncoderInterface $encoder) - { - $this->encoder = $encoder; - } - - // ... - public function load(ObjectManager $manager) - { - $user = new User(); - $user->setUsername('admin'); - - $password = $this->encoder->encodePassword($user, 'pass_1234'); - $user->setPassword($password); - - $manager->persist($user); - $manager->flush(); - } - -You can also access the container via the ``$this->container`` property. -But remember that not *all* services (i.e. private services) can be accessed -directly via the container. - -.. _multiple-files: - -Splitting Fixtures into Separate Files --------------------------------------- - -In most applications, creating all your fixtures in just one class is fine. -This class may end up being a bit long, but it's worth it because having one -file helps keeping things simple. - -If you do decide to split your fixtures into separate files, Symfony helps you -solve the two most common issues: sharing objects between fixtures and loading -the fixtures in order. - -Sharing Objects between Fixtures -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When using multiple fixtures files, you can reuse PHP objects across different -files thanks to the **object references**. Use the ``addReference()`` method to -give a name to any object and then, use the ``getReference()`` method to get the -exact same object via its name:: - - // src/DataFixtures/UserFixtures.php - // ... - class UserFixtures extends Fixture - { - public const ADMIN_USER_REFERENCE = 'admin-user'; - - public function load(ObjectManager $manager) - { - $userAdmin = new User('admin', 'pass_1234'); - $manager->persist($userAdmin); - $manager->flush(); - - // other fixtures can get this object using the UserFixtures::ADMIN_USER_REFERENCE constant - $this->addReference(self::ADMIN_USER_REFERENCE, $userAdmin); - } - } - - // src/DataFixtures/GroupFixtures.php - // ... - class GroupFixtures extends Fixture - { - public function load(ObjectManager $manager) - { - $userGroup = new Group('administrators'); - // this reference returns the User object created in UserFixtures - $userGroup->addUser($this->getReference(UserFixtures::ADMIN_USER_REFERENCE)); - - $manager->persist($userGroup); - $manager->flush(); - } - } - -The only caveat of using references is that fixtures need to be loaded in a -certain order (in this example, if the ``Group`` fixtures are load before the -``User`` fixtures, you'll see an error). By default Doctrine loads the fixture -files in alphabetical order, but you can control their order as explained in the -next section. - -Loading the Fixture Files in Order -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Instead of defining the exact order in which all fixture files must be loaded, -Doctrine uses a smarter approach to ensure that some fixtures are loaded before -others. Implement the ``DependentFixtureInterface`` and add a new -``getDependencies()`` method to your fixtures class. This will return -an array of the fixture classes that must be loaded before this one:: - - // src/DataFixtures/UserFixtures.php - namespace App\DataFixtures; - - // ... - class UserFixtures extends Fixture - { - public function load(ObjectManager $manager) - { - // ... - } - } - - // src/DataFixtures/GroupFixtures.php - namespace App\DataFixtures; - // ... - use App\DataFixtures\UserFixtures; - use Doctrine\Common\DataFixtures\DependentFixtureInterface; - - class GroupFixtures extends Fixture implements DependentFixtureInterface - { - public function load(ObjectManager $manager) - { - // ... - } - - public function getDependencies() - { - return array( - UserFixtures::class, - ); - } - } - -Fixture Groups: Only Executing Some Fixtures --------------------------------------------- - -By default, *all* of your fixture classes are executed. If you only want -to execute *some* of your fixture classes, you can organize them into -groups. - -The simplest way to organize a fixture class into a group is to -make your fixture implement ``FixtureGroupInterface``: - -.. code-block:: diff - - // src/DataFixtures/UserFixtures.php - - + use Doctrine\Bundle\FixturesBundle\FixtureGroupInterface; - - - class UserFixtures extends Fixture - + class UserFixtures extends Fixture implements FixtureGroupInterface - { - // ... - - + public static function getGroups(): array - + { - + return ['group1', 'group2']; - + } - } - -To execute all of your fixtures for a given group, pass the ``--group`` -option: - -.. code-block:: terminal - - $ php bin/console doctrine:fixtures:load --group=group1 - - # or to execute multiple groups - $ php bin/console doctrine:fixtures:load --group=group1 --group=group2 - -Alternatively, instead of implementing the ``FixtureGroupInterface``, -you can also tag your service with ``doctrine.fixture.orm`` and add -an extra ``group`` option set to a group your fixture should belong to. - -Regardless of groups defined in the fixture or the service definition, the -fixture loader always adds the short name of the class as a separate group so -you can load a single fixture at a time. In the example above, you can load the -fixture using the ``UserFixtures`` group: - -.. code-block:: terminal - - $ php bin/console doctrine:fixtures:load --group=UserFixtures - -.. _`ORM`: https://symfony.com/doc/current/doctrine.html -.. _`installation chapter`: https://getcomposer.org/doc/00-intro.md -.. _`Symfony Flex`: https://symfony.com/doc/current/setup/flex.html -.. _`default service configuration`: https://symfony.com/doc/current/service_container.html#service-container-services-load-example diff --git a/vendor/doctrine/doctrine-fixtures-bundle/Tests/Command/LoadDataFixturesDoctrineCommandTest.php b/vendor/doctrine/doctrine-fixtures-bundle/Tests/Command/LoadDataFixturesDoctrineCommandTest.php deleted file mode 100644 index 39b53a5..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/Tests/Command/LoadDataFixturesDoctrineCommandTest.php +++ /dev/null @@ -1,43 +0,0 @@ -expectExceptionMessage('Argument 1 passed to Doctrine\Bundle\DoctrineBundle\Command\DoctrineCommand::__construct() must be an instance of Doctrine\Common\Persistence\ManagerRegistry, null given'); - - throw $e; - } - } - - /** - * @doesNotPerformAssertions - */ - public function testInstantiatingWithManagerRegistry() : void - { - $registry = $this->createMock(ManagerRegistry::class); - $loader = new SymfonyFixturesLoader(new Container()); - - new LoadDataFixturesDoctrineCommand($loader, $registry); - } -} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/DependentOnRequiredConstructorArgsFixtures.php b/vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/DependentOnRequiredConstructorArgsFixtures.php deleted file mode 100644 index 7fc6b2b..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/Tests/Fixtures/FooBundle/DataFixtures/DependentOnRequiredConstructorArgsFixtures.php +++ /dev/null @@ -1,22 +0,0 @@ -addServices(static function (ContainerBuilder $c) : void { - $c->autowire(OtherFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - $c->autowire(WithDependenciesFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); - }); - $kernel->boot(); - $container = $kernel->getContainer(); - - /** @var ContainerAwareLoader $loader */ - $loader = $container->get('test.doctrine.fixtures.loader'); - - $actualFixtures = $loader->getFixtures(); - $this->assertCount(2, $actualFixtures); - $actualFixtureClasses = array_map(static function ($fixture) { - return get_class($fixture); - }, $actualFixtures); - - $this->assertSame([ - OtherFixtures::class, - WithDependenciesFixtures::class, - ], $actualFixtureClasses); - $this->assertInstanceOf(WithDependenciesFixtures::class, $actualFixtures[1]); - } - - public function testFixturesLoaderWhenFixtureHasDepdencenyThatIsNotYetLoaded() : void - { - // See https://github.com/doctrine/DoctrineFixturesBundle/issues/215 - - $kernel = new IntegrationTestKernel('dev', true); - $kernel->addServices(static function (ContainerBuilder $c) : void { - $c->autowire(WithDependenciesFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - $c->autowire(OtherFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); - }); - $kernel->boot(); - $container = $kernel->getContainer(); - - /** @var ContainerAwareLoader $loader */ - $loader = $container->get('test.doctrine.fixtures.loader'); - - $actualFixtures = $loader->getFixtures(); - $this->assertCount(2, $actualFixtures); - $actualFixtureClasses = array_map(static function ($fixture) { - return get_class($fixture); - }, $actualFixtures); - - $this->assertSame([ - OtherFixtures::class, - WithDependenciesFixtures::class, - ], $actualFixtureClasses); - $this->assertInstanceOf(WithDependenciesFixtures::class, $actualFixtures[1]); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage The getDependencies() method returned a class (Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\RequiredConstructorArgsFixtures) that has required constructor arguments. Upgrade to "doctrine/data-fixtures" version 1.3 or higher to support this. - */ - public function testExceptionWithDependenciesWithRequiredArguments() : void - { - // see https://github.com/doctrine/data-fixtures/pull/274 - // When that is merged, this test will only run when using - // an older version of that library. - if (method_exists(Loader::class, 'createFixture')) { - $this->markTestSkipped(); - } - - $kernel = new IntegrationTestKernel('dev', true); - $kernel->addServices(static function (ContainerBuilder $c) : void { - $c->autowire(DependentOnRequiredConstructorArgsFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - $c->autowire(RequiredConstructorArgsFixtures::class) - ->setArgument(0, 'foo') - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); - }); - $kernel->boot(); - $container = $kernel->getContainer(); - - /** @var ContainerAwareLoader $loader */ - $loader = $container->get('test.doctrine.fixtures.loader'); - - $loader->getFixtures(); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage The "Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\RequiredConstructorArgsFixtures" fixture class is trying to be loaded, but is not available. Make sure this class is defined as a service and tagged with "doctrine.fixture.orm". - */ - public function testExceptionIfDependentFixtureNotWired() : void - { - // only runs on newer versions of doctrine/data-fixtures - if (! method_exists(Loader::class, 'createFixture')) { - $this->markTestSkipped(); - } - - $kernel = new IntegrationTestKernel('dev', true); - $kernel->addServices(static function (ContainerBuilder $c) : void { - $c->autowire(DependentOnRequiredConstructorArgsFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); - }); - $kernel->boot(); - $container = $kernel->getContainer(); - - /** @var ContainerAwareLoader $loader */ - $loader = $container->get('test.doctrine.fixtures.loader'); - - $loader->getFixtures(); - } - - public function testFixturesLoaderWithGroupsOptionViaInterface() : void - { - $kernel = new IntegrationTestKernel('dev', true); - $kernel->addServices(static function (ContainerBuilder $c) : void { - // has a "staging" group via the getGroups() method - $c->autowire(OtherFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - // no getGroups() method - $c->autowire(WithDependenciesFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); - }); - $kernel->boot(); - $container = $kernel->getContainer(); - - /** @var ContainerAwareLoader $loader */ - $loader = $container->get('test.doctrine.fixtures.loader'); - - $actualFixtures = $loader->getFixtures(['staging']); - $this->assertCount(1, $actualFixtures); - $actualFixtureClasses = array_map(static function ($fixture) { - return get_class($fixture); - }, $actualFixtures); - - $this->assertSame([ - OtherFixtures::class, - ], $actualFixtureClasses); - $this->assertInstanceOf(OtherFixtures::class, $actualFixtures[0]); - } - - public function testFixturesLoaderWithGroupsOptionViaTag() : void - { - $kernel = new IntegrationTestKernel('dev', true); - $kernel->addServices(static function (ContainerBuilder $c) : void { - // has a "staging" group via the getGroups() method - $c->autowire(OtherFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG, ['group' => 'group1']) - ->addTag(FixturesCompilerPass::FIXTURE_TAG, ['group' => 'group2']); - - // no getGroups() method - $c->autowire(WithDependenciesFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG, ['group' => 'group2']); - - $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); - }); - $kernel->boot(); - $container = $kernel->getContainer(); - - /** @var ContainerAwareLoader $loader */ - $loader = $container->get('test.doctrine.fixtures.loader'); - - $this->assertCount(1, $loader->getFixtures(['staging'])); - $this->assertCount(1, $loader->getFixtures(['group1'])); - $this->assertCount(2, $loader->getFixtures(['group2'])); - $this->assertCount(0, $loader->getFixtures(['group3'])); - } - - public function testLoadFixturesViaGroupWithMissingDependency() : void - { - $kernel = new IntegrationTestKernel('dev', true); - $kernel->addServices(static function (ContainerBuilder $c) : void { - // has a "staging" group via the getGroups() method - $c->autowire(OtherFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - // no getGroups() method - $c->autowire(WithDependenciesFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); - }); - $kernel->boot(); - $container = $kernel->getContainer(); - - /** @var ContainerAwareLoader $loader */ - $loader = $container->get('test.doctrine.fixtures.loader'); - - $this->expectException(RuntimeException::class); - $this->expectExceptionMessage('Fixture "Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\OtherFixtures" was declared as a dependency for fixture "Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\WithDependenciesFixtures", but it was not included in any of the loaded fixture groups.'); - - $loader->getFixtures(['missingDependencyGroup']); - } - - public function testLoadFixturesViaGroupWithFulfilledDependency() : void - { - $kernel = new IntegrationTestKernel('dev', true); - $kernel->addServices(static function (ContainerBuilder $c) : void { - // has a "staging" group via the getGroups() method - $c->autowire(OtherFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - // no getGroups() method - $c->autowire(WithDependenciesFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); - }); - $kernel->boot(); - $container = $kernel->getContainer(); - - /** @var ContainerAwareLoader $loader */ - $loader = $container->get('test.doctrine.fixtures.loader'); - - $actualFixtures = $loader->getFixtures(['fulfilledDependencyGroup']); - - $this->assertCount(2, $actualFixtures); - $actualFixtureClasses = array_map(static function ($fixture) { - return get_class($fixture); - }, $actualFixtures); - - $this->assertSame([ - OtherFixtures::class, - WithDependenciesFixtures::class, - ], $actualFixtureClasses); - } - - public function testLoadFixturesByShortName() : void - { - $kernel = new IntegrationTestKernel('dev', true); - $kernel->addServices(static function (ContainerBuilder $c) : void { - // has a "staging" group via the getGroups() method - $c->autowire(OtherFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - // no getGroups() method - $c->autowire(WithDependenciesFixtures::class) - ->addTag(FixturesCompilerPass::FIXTURE_TAG); - - $c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true)); - }); - $kernel->boot(); - $container = $kernel->getContainer(); - - /** @var ContainerAwareLoader $loader */ - $loader = $container->get('test.doctrine.fixtures.loader'); - - $actualFixtures = $loader->getFixtures(['OtherFixtures']); - - $this->assertCount(1, $actualFixtures); - $actualFixtureClasses = array_map(static function ($fixture) { - return get_class($fixture); - }, $actualFixtures); - - $this->assertSame([ - OtherFixtures::class, - ], $actualFixtureClasses); - } -} - -class IntegrationTestKernel extends Kernel -{ - /** @var callable */ - private $servicesCallback; - - /** @var int */ - private $randomKey; - - public function __construct(string $environment, bool $debug) - { - $this->randomKey = rand(100, 999); - - parent::__construct($environment, $debug); - } - - protected function getContainerClass() : string - { - return 'test' . $this->randomKey . parent::getContainerClass(); - } - - public function registerBundles() : array - { - return [ - new DoctrineFixturesBundle(), - new FooBundle(), - ]; - } - - public function addServices(callable $callback) : void - { - $this->servicesCallback = $callback; - } - - public function registerContainerConfiguration(LoaderInterface $loader) : void - { - $loader->load(function (ContainerBuilder $c) : void { - if (! $c->hasDefinition('kernel')) { - $c->register('kernel', static::class) - ->setSynthetic(true) - ->setPublic(true); - } - - $c->register('doctrine', ManagerRegistry::class); - - $callback = $this->servicesCallback; - $callback($c); - - $c->addObjectResource($this); - }); - } - - public function getCacheDir() : string - { - return sys_get_temp_dir() . '/doctrine_fixtures_bundle' . $this->randomKey; - } - - public function getLogDir() : string - { - return sys_get_temp_dir(); - } -} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/UPGRADE.md b/vendor/doctrine/doctrine-fixtures-bundle/UPGRADE.md deleted file mode 100644 index f602be1..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/UPGRADE.md +++ /dev/null @@ -1,56 +0,0 @@ -UPGRADE to 3.0 -============== - -* The automatic loading of fixtures in a directory (e.g. - AppBundle\DataFixtures\ORM) was removed. Instead, register - your fixture classes as services and tag them with `doctrine.fixture.orm`, - like this: -```yaml -# src/AppBundle/Resources/config/dataFixture.yml -services: - _defaults: - tags: ['doctrine.fixture.orm'] - autowire: true # if you need dependency injection, see next bullet point - - AppBundle\DataFixtures\ORM\: - resource: '../../DataFixtures/ORM/*' -``` - - This will happen automatically if you're using the Symfony 3.3 - or higher **default service configuration** and your fixture classes - extend the normal ``Doctrine\Bundle\FixturesBundle\Fixture`` class, - or implement the new ``Doctrine\Bundle\FixturesBundle\ORMFixtureInterface``. - -* The base ``Fixture`` class no longer implements ``ContainerAwareInterface`` - and so no longer have a ``$this->container`` property. You *can* manually - implement this interface. Or, a better idea is to update your fixtures - to use dependency injection: - -```diff -class MyFixture extends Fixture -{ -+ private $someService; - -+ public function __construct(SomeService $someService) -+ { -+ $this->someService = $someService; -+ } - - public function load(ObjectManager $manager) - { -- $this->container->get('some_service')->someMethod(); -+ $this->someService->someMethod(); - } -} -``` - -* The base ``Fixture`` class no longer implements ``DependentFixtureInterface``. - If you want to have a ``getDependencies()`` method, be sure to implement - this interface explicitly: - -```diff -+ use Doctrine\Common\DataFixtures\DependentFixtureInterface; - -- class MyFixture extends Fixture -+ class MyFixture extends Fixture implements DependentFixtureInterface -``` diff --git a/vendor/doctrine/doctrine-fixtures-bundle/composer.json b/vendor/doctrine/doctrine-fixtures-bundle/composer.json deleted file mode 100644 index 65d3385..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/composer.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "doctrine/doctrine-fixtures-bundle", - "type": "symfony-bundle", - "description": "Symfony DoctrineFixturesBundle", - "keywords": ["Persistence", "Fixture"], - "homepage": "http://www.doctrine-project.org", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Doctrine Project", - "homepage": "http://www.doctrine-project.org" - }, - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - } - ], - "require": { - "php": "^7.1", - "doctrine/data-fixtures": "^1.3", - "doctrine/doctrine-bundle": "^1.11|^2.0", - "doctrine/orm": "^2.6.0", - "symfony/doctrine-bridge": "^3.4|^4.1|^5.0", - "symfony/config": "^3.4|^4.3|^5.0", - "symfony/console": "^3.4|^4.3|^5.0", - "symfony/dependency-injection": "^3.4|^4.3|^5.0", - "symfony/http-kernel": "^3.4|^4.3|^5.0" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpunit/phpunit": "^7.4", - "symfony/phpunit-bridge": "^4.1|^5.0" - }, - "autoload": { - "psr-4": { "Doctrine\\Bundle\\FixturesBundle\\": "" } - }, - "config": { - "sort-packages": true - }, - "extra": { - "branch-alias": { - "dev-master": "3.3.x-dev" - } - } -} diff --git a/vendor/doctrine/doctrine-fixtures-bundle/phpcs.xml.dist b/vendor/doctrine/doctrine-fixtures-bundle/phpcs.xml.dist deleted file mode 100644 index 6c6a537..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/phpcs.xml.dist +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - . - /vendor - - - - - - - - - - FixtureGroupInterface.php - ORMFixtureInterface.php - - - Loader/SymfonyFixturesLoader.php - - - Tests/IntegrationTest.php - - - Tests/IntegrationTest.php - - diff --git a/vendor/doctrine/doctrine-fixtures-bundle/phpunit.xml.dist b/vendor/doctrine/doctrine-fixtures-bundle/phpunit.xml.dist deleted file mode 100644 index 716bd48..0000000 --- a/vendor/doctrine/doctrine-fixtures-bundle/phpunit.xml.dist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - ./Tests - - - - - - . - - ./Resources - ./Tests - ./vendor - - - - - - - - diff --git a/vendor/doctrine/event-manager/.doctrine-project.json b/vendor/doctrine/event-manager/.doctrine-project.json deleted file mode 100644 index f6feb43..0000000 --- a/vendor/doctrine/event-manager/.doctrine-project.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "active": true, - "name": "Event Manager", - "slug": "event-manager", - "docsSlug": "doctrine-event-manager", - "versions": [ - { - "name": "1.0", - "branchName": "master", - "slug": "latest", - "current": true, - "aliases": [ - "current", - "stable" - ] - } - ] -} diff --git a/vendor/doctrine/event-manager/LICENSE b/vendor/doctrine/event-manager/LICENSE deleted file mode 100644 index 8c38cc1..0000000 --- a/vendor/doctrine/event-manager/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006-2015 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/doctrine/event-manager/README.md b/vendor/doctrine/event-manager/README.md deleted file mode 100644 index 3aee6b6..0000000 --- a/vendor/doctrine/event-manager/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Doctrine Event Manager - -[![Build Status](https://travis-ci.org/doctrine/event-manager.svg)](https://travis-ci.org/doctrine/event-manager) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/event-manager/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/event-manager/?branch=master) -[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/event-manager/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/event-manager/?branch=master) - -The Doctrine Event Manager is a library that provides a simple event system. - -## More resources: - -* [Website](https://www.doctrine-project.org/) -* [Documentation](https://www.doctrine-project.org/projects/doctrine-event-manager/en/latest/) -* [Downloads](https://github.com/doctrine/event-manager/releases) diff --git a/vendor/doctrine/event-manager/composer.json b/vendor/doctrine/event-manager/composer.json deleted file mode 100644 index c0d3a84..0000000 --- a/vendor/doctrine/event-manager/composer.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "doctrine/event-manager", - "type": "library", - "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", - "keywords": [ - "events", - "event", - "event dispatcher", - "event manager", - "event system" - ], - "homepage": "https://www.doctrine-project.org/projects/event-manager.html", - "license": "MIT", - "authors": [ - {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, - {"name": "Roman Borschel", "email": "roman@code-factory.org"}, - {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, - {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, - {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}, - {"name": "Marco Pivetta", "email": "ocramius@gmail.com"} - ], - "require": { - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpunit/phpunit": "^7.0" - }, - "conflict": { - "doctrine/common": "<2.9@dev" - }, - "config": { - "sort-packages": true - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "autoload-dev": { - "psr-4": { - "Doctrine\\Tests\\": "tests/Doctrine/Tests" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - } -} diff --git a/vendor/doctrine/event-manager/lib/Doctrine/Common/EventArgs.php b/vendor/doctrine/event-manager/lib/Doctrine/Common/EventArgs.php deleted file mode 100644 index 9b9cc05..0000000 --- a/vendor/doctrine/event-manager/lib/Doctrine/Common/EventArgs.php +++ /dev/null @@ -1,45 +0,0 @@ - => - * - * @var object[][] - */ - private $_listeners = []; - - /** - * 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|null $eventArgs The event arguments to pass to the event handlers/listeners. - * If not supplied, the single empty EventArgs instance is used. - * - * @return void - */ - public function dispatchEvent($eventName, ?EventArgs $eventArgs = null) - { - if (! isset($this->_listeners[$eventName])) { - return; - } - - $eventArgs = $eventArgs ?? EventArgs::getEmptyInstance(); - - foreach ($this->_listeners[$eventName] as $listener) { - $listener->$eventName($eventArgs); - } - } - - /** - * Gets the listeners of a specific event or all listeners. - * - * @param string|null $event The name of the event. - * - * @return object[]|object[][] 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 bool TRUE if the specified event has any listeners, FALSE otherwise. - */ - public function hasListeners($event) - { - return ! empty($this->_listeners[$event]); - } - - /** - * Adds an event listener that listens on the specified events. - * - * @param string|string[] $events The event(s) to listen on. - * @param object $listener The listener object. - * - * @return void - */ - 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|string[] $events - * @param object $listener - * - * @return void - */ - public function removeEventListener($events, $listener) - { - // Picks the hash code related to that listener - $hash = spl_object_hash($listener); - - foreach ((array) $events as $event) { - unset($this->_listeners[$event][$hash]); - } - } - - /** - * Adds an EventSubscriber. The subscriber is asked for all the events it is - * interested in and added as a listener for these events. - * - * @param EventSubscriber $subscriber The subscriber. - * - * @return void - */ - public function addEventSubscriber(EventSubscriber $subscriber) - { - $this->addEventListener($subscriber->getSubscribedEvents(), $subscriber); - } - - /** - * Removes an EventSubscriber. The subscriber is asked for all the events it is - * interested in and removed as a listener for these events. - * - * @param EventSubscriber $subscriber The subscriber. - * - * @return void - */ - public function removeEventSubscriber(EventSubscriber $subscriber) - { - $this->removeEventListener($subscriber->getSubscribedEvents(), $subscriber); - } -} diff --git a/vendor/doctrine/event-manager/lib/Doctrine/Common/EventSubscriber.php b/vendor/doctrine/event-manager/lib/Doctrine/Common/EventSubscriber.php deleted file mode 100644 index 7d5e2ea..0000000 --- a/vendor/doctrine/event-manager/lib/Doctrine/Common/EventSubscriber.php +++ /dev/null @@ -1,21 +0,0 @@ - '\1ables']); - Inflector::rules('plural', [ - 'rules' => ['/^(inflect)ors$/i' => '\1ables'], - 'uninflected' => ['dontinflectme'], - 'irregular' => ['red' => 'redlings'] - ]); - -The arguments for the ``rules`` method are: - -- ``$type`` - The type of inflection, either ``plural`` or ``singular`` -- ``$rules`` - An array of rules to be added. -- ``$reset`` - If true, will unset default inflections for all new rules that are being defined in $rules. - -Reset -===== - -Clears Inflectors inflected value caches, and resets the inflection -rules to the initial values. - -.. code-block:: php - - Inflector::reset(); - -Slugify -======= - -You can easily use the Inflector to create a slug from a string of text -by using the `tableize`_ method and replacing underscores with hyphens: - -.. code-block:: php - - public static function slugify(string $text) : string - { - return str_replace('_', '-', Inflector::tableize($text)); - } diff --git a/vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php b/vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php deleted file mode 100644 index 35b5c68..0000000 --- a/vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php +++ /dev/null @@ -1,492 +0,0 @@ -. - */ - -namespace Doctrine\Common\Inflector; - -/** - * 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. - * - * Pluralize & Singularize implementation are borrowed from CakePHP with some modifications. - * - * @link www.doctrine-project.org - * @since 1.0 - * @author Konsta Vesterinen - * @author Jonathan H. Wage - */ -class Inflector -{ - /** - * Plural inflector rules. - * - * @var string[][] - */ - private static $plural = array( - 'rules' => array( - '/(s)tatus$/i' => '\1\2tatuses', - '/(quiz)$/i' => '\1zes', - '/^(ox)$/i' => '\1\2en', - '/([m|l])ouse$/i' => '\1ice', - '/(matr|vert|ind)(ix|ex)$/i' => '\1ices', - '/(x|ch|ss|sh)$/i' => '\1es', - '/([^aeiouy]|qu)y$/i' => '\1ies', - '/(hive|gulf)$/i' => '\1s', - '/(?:([^f])fe|([lr])f)$/i' => '\1\2ves', - '/sis$/i' => 'ses', - '/([ti])um$/i' => '\1a', - '/(c)riterion$/i' => '\1riteria', - '/(p)erson$/i' => '\1eople', - '/(m)an$/i' => '\1en', - '/(c)hild$/i' => '\1hildren', - '/(f)oot$/i' => '\1eet', - '/(buffal|her|potat|tomat|volcan)o$/i' => '\1\2oes', - '/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us$/i' => '\1i', - '/us$/i' => 'uses', - '/(alias)$/i' => '\1es', - '/(analys|ax|cris|test|thes)is$/i' => '\1es', - '/s$/' => 's', - '/^$/' => '', - '/$/' => 's', - ), - 'uninflected' => array( - '.*[nrlm]ese', - '.*deer', - '.*fish', - '.*measles', - '.*ois', - '.*pox', - '.*sheep', - 'people', - 'cookie', - 'police', - ), - 'irregular' => array( - 'atlas' => 'atlases', - 'axe' => 'axes', - 'beef' => 'beefs', - 'brother' => 'brothers', - 'cafe' => 'cafes', - 'canvas' => 'canvases', - 'chateau' => 'chateaux', - 'niveau' => 'niveaux', - 'child' => 'children', - 'cookie' => 'cookies', - 'corpus' => 'corpuses', - 'cow' => 'cows', - 'criterion' => 'criteria', - 'curriculum' => 'curricula', - 'demo' => 'demos', - 'domino' => 'dominoes', - 'echo' => 'echoes', - 'foot' => 'feet', - 'fungus' => 'fungi', - 'ganglion' => 'ganglions', - 'gas' => 'gases', - 'genie' => 'genies', - 'genus' => 'genera', - 'goose' => 'geese', - 'graffito' => 'graffiti', - 'hippopotamus' => 'hippopotami', - 'hoof' => 'hoofs', - 'human' => 'humans', - 'iris' => 'irises', - 'larva' => 'larvae', - 'leaf' => 'leaves', - 'loaf' => 'loaves', - 'man' => 'men', - 'medium' => 'media', - 'memorandum' => 'memoranda', - 'money' => 'monies', - 'mongoose' => 'mongooses', - 'motto' => 'mottoes', - 'move' => 'moves', - 'mythos' => 'mythoi', - 'niche' => 'niches', - 'nucleus' => 'nuclei', - 'numen' => 'numina', - 'occiput' => 'occiputs', - 'octopus' => 'octopuses', - 'opus' => 'opuses', - 'ox' => 'oxen', - 'passerby' => 'passersby', - 'penis' => 'penises', - 'person' => 'people', - 'plateau' => 'plateaux', - 'runner-up' => 'runners-up', - 'sex' => 'sexes', - 'soliloquy' => 'soliloquies', - 'son-in-law' => 'sons-in-law', - 'syllabus' => 'syllabi', - 'testis' => 'testes', - 'thief' => 'thieves', - 'tooth' => 'teeth', - 'tornado' => 'tornadoes', - 'trilby' => 'trilbys', - 'turf' => 'turfs', - 'valve' => 'valves', - 'volcano' => 'volcanoes', - ) - ); - - /** - * Singular inflector rules. - * - * @var string[][] - */ - private static $singular = array( - 'rules' => array( - '/(s)tatuses$/i' => '\1\2tatus', - '/^(.*)(menu)s$/i' => '\1\2', - '/(quiz)zes$/i' => '\\1', - '/(matr)ices$/i' => '\1ix', - '/(vert|ind)ices$/i' => '\1ex', - '/^(ox)en/i' => '\1', - '/(alias)(es)*$/i' => '\1', - '/(buffal|her|potat|tomat|volcan)oes$/i' => '\1o', - '/(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$/i' => '\1us', - '/([ftw]ax)es/i' => '\1', - '/(analys|ax|cris|test|thes)es$/i' => '\1is', - '/(shoe|slave)s$/i' => '\1', - '/(o)es$/i' => '\1', - '/ouses$/' => 'ouse', - '/([^a])uses$/' => '\1us', - '/([m|l])ice$/i' => '\1ouse', - '/(x|ch|ss|sh)es$/i' => '\1', - '/(m)ovies$/i' => '\1\2ovie', - '/(s)eries$/i' => '\1\2eries', - '/([^aeiouy]|qu)ies$/i' => '\1y', - '/([lr])ves$/i' => '\1f', - '/(tive)s$/i' => '\1', - '/(hive)s$/i' => '\1', - '/(drive)s$/i' => '\1', - '/(dive)s$/i' => '\1', - '/(olive)s$/i' => '\1', - '/([^fo])ves$/i' => '\1fe', - '/(^analy)ses$/i' => '\1sis', - '/(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis', - '/(c)riteria$/i' => '\1riterion', - '/([ti])a$/i' => '\1um', - '/(p)eople$/i' => '\1\2erson', - '/(m)en$/i' => '\1an', - '/(c)hildren$/i' => '\1\2hild', - '/(f)eet$/i' => '\1oot', - '/(n)ews$/i' => '\1\2ews', - '/eaus$/' => 'eau', - '/^(.*us)$/' => '\\1', - '/s$/i' => '', - ), - 'uninflected' => array( - '.*[nrlm]ese', - '.*deer', - '.*fish', - '.*measles', - '.*ois', - '.*pox', - '.*sheep', - '.*ss', - 'data', - 'police', - 'pants', - 'clothes', - ), - 'irregular' => array( - 'abuses' => 'abuse', - 'avalanches' => 'avalanche', - 'caches' => 'cache', - 'criteria' => 'criterion', - 'curves' => 'curve', - 'emphases' => 'emphasis', - 'foes' => 'foe', - 'geese' => 'goose', - 'graves' => 'grave', - 'hoaxes' => 'hoax', - 'media' => 'medium', - 'neuroses' => 'neurosis', - 'waves' => 'wave', - 'oases' => 'oasis', - 'valves' => 'valve', - ) - ); - - /** - * Words that should not be inflected. - * - * @var array - */ - private static $uninflected = array( - '.*?media', 'Amoyese', 'audio', 'bison', 'Borghese', 'bream', 'breeches', - 'britches', 'buffalo', 'cantus', 'carp', 'chassis', 'clippers', 'cod', 'coitus', 'compensation', 'Congoese', - 'contretemps', 'coreopsis', 'corps', 'data', 'debris', 'deer', 'diabetes', 'djinn', 'education', 'eland', - 'elk', 'emoji', 'equipment', 'evidence', 'Faroese', 'feedback', 'fish', 'flounder', 'Foochowese', - 'Furniture', 'furniture', 'gallows', 'Genevese', 'Genoese', 'Gilbertese', 'gold', - 'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings', 'jackanapes', 'jedi', - 'Kiplingese', 'knowledge', 'Kongoese', 'love', 'Lucchese', 'Luggage', 'mackerel', 'Maltese', 'metadata', - 'mews', 'moose', 'mumps', 'Nankingese', 'news', 'nexus', 'Niasese', 'nutrition', 'offspring', - 'Pekingese', 'Piedmontese', 'pincers', 'Pistoiese', 'plankton', 'pliers', 'pokemon', 'police', 'Portuguese', - 'proceedings', 'rabies', 'rain', 'rhinoceros', 'rice', 'salmon', 'Sarawakese', 'scissors', 'sea[- ]bass', - 'series', 'Shavese', 'shears', 'sheep', 'siemens', 'species', 'staff', 'swine', 'traffic', - 'trousers', 'trout', 'tuna', 'us', 'Vermontese', 'Wenchowese', 'wheat', 'whiting', 'wildebeest', 'Yengeese' - ); - - /** - * Method cache array. - * - * @var array - */ - private static $cache = array(); - - /** - * The initial state of Inflector so reset() works. - * - * @var array - */ - private static $initialState = array(); - - /** - * Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'. - */ - public static function tableize(string $word) : string - { - return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $word)); - } - - /** - * Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'. - */ - public static function classify(string $word) : string - { - return str_replace([' ', '_', '-'], '', ucwords($word, ' _-')); - } - - /** - * Camelizes a word. This uses the classify() method and turns the first character to lowercase. - */ - public static function camelize(string $word) : string - { - return lcfirst(self::classify($word)); - } - - /** - * Uppercases words with configurable delimeters between words. - * - * Takes a string and capitalizes all of the words, like PHP's built-in - * ucwords function. This extends that behavior, however, by allowing the - * word delimeters to be configured, rather than only separating on - * whitespace. - * - * Here is an example: - * - * - * - * - * @param string $string The string to operate on. - * @param string $delimiters A list of word separators. - * - * @return string The string with all delimeter-separated words capitalized. - */ - public static function ucwords(string $string, string $delimiters = " \n\t\r\0\x0B-") : string - { - return ucwords($string, $delimiters); - } - - /** - * Clears Inflectors inflected value caches, and resets the inflection - * rules to the initial values. - */ - public static function reset() : void - { - if (empty(self::$initialState)) { - self::$initialState = get_class_vars('Inflector'); - - return; - } - - foreach (self::$initialState as $key => $val) { - if ($key !== 'initialState') { - self::${$key} = $val; - } - } - } - - /** - * Adds custom inflection $rules, of either 'plural' or 'singular' $type. - * - * ### Usage: - * - * {{{ - * Inflector::rules('plural', array('/^(inflect)or$/i' => '\1ables')); - * Inflector::rules('plural', array( - * 'rules' => array('/^(inflect)ors$/i' => '\1ables'), - * 'uninflected' => array('dontinflectme'), - * 'irregular' => array('red' => 'redlings') - * )); - * }}} - * - * @param string $type The type of inflection, either 'plural' or 'singular' - * @param array|iterable $rules An array of rules to be added. - * @param boolean $reset If true, will unset default inflections for all - * new rules that are being defined in $rules. - * - * @return void - */ - public static function rules(string $type, iterable $rules, bool $reset = false) : void - { - foreach ($rules as $rule => $pattern) { - if ( ! is_array($pattern)) { - continue; - } - - if ($reset) { - self::${$type}[$rule] = $pattern; - } else { - self::${$type}[$rule] = ($rule === 'uninflected') - ? array_merge($pattern, self::${$type}[$rule]) - : $pattern + self::${$type}[$rule]; - } - - unset($rules[$rule], self::${$type}['cache' . ucfirst($rule)]); - - if (isset(self::${$type}['merged'][$rule])) { - unset(self::${$type}['merged'][$rule]); - } - - if ($type === 'plural') { - self::$cache['pluralize'] = self::$cache['tableize'] = array(); - } elseif ($type === 'singular') { - self::$cache['singularize'] = array(); - } - } - - self::${$type}['rules'] = $rules + self::${$type}['rules']; - } - - /** - * Returns a word in plural form. - * - * @param string $word The word in singular form. - * - * @return string The word in plural form. - */ - public static function pluralize(string $word) : string - { - if (isset(self::$cache['pluralize'][$word])) { - return self::$cache['pluralize'][$word]; - } - - if (!isset(self::$plural['merged']['irregular'])) { - self::$plural['merged']['irregular'] = self::$plural['irregular']; - } - - if (!isset(self::$plural['merged']['uninflected'])) { - self::$plural['merged']['uninflected'] = array_merge(self::$plural['uninflected'], self::$uninflected); - } - - if (!isset(self::$plural['cacheUninflected']) || !isset(self::$plural['cacheIrregular'])) { - self::$plural['cacheUninflected'] = '(?:' . implode('|', self::$plural['merged']['uninflected']) . ')'; - self::$plural['cacheIrregular'] = '(?:' . implode('|', array_keys(self::$plural['merged']['irregular'])) . ')'; - } - - if (preg_match('/(.*)\\b(' . self::$plural['cacheIrregular'] . ')$/i', $word, $regs)) { - self::$cache['pluralize'][$word] = $regs[1] . $word[0] . substr(self::$plural['merged']['irregular'][strtolower($regs[2])], 1); - - return self::$cache['pluralize'][$word]; - } - - if (preg_match('/^(' . self::$plural['cacheUninflected'] . ')$/i', $word, $regs)) { - self::$cache['pluralize'][$word] = $word; - - return $word; - } - - foreach (self::$plural['rules'] as $rule => $replacement) { - if (preg_match($rule, $word)) { - self::$cache['pluralize'][$word] = preg_replace($rule, $replacement, $word); - - return self::$cache['pluralize'][$word]; - } - } - } - - /** - * Returns a word in singular form. - * - * @param string $word The word in plural form. - * - * @return string The word in singular form. - */ - public static function singularize(string $word) : string - { - if (isset(self::$cache['singularize'][$word])) { - return self::$cache['singularize'][$word]; - } - - if (!isset(self::$singular['merged']['uninflected'])) { - self::$singular['merged']['uninflected'] = array_merge( - self::$singular['uninflected'], - self::$uninflected - ); - } - - if (!isset(self::$singular['merged']['irregular'])) { - self::$singular['merged']['irregular'] = array_merge( - self::$singular['irregular'], - array_flip(self::$plural['irregular']) - ); - } - - if (!isset(self::$singular['cacheUninflected']) || !isset(self::$singular['cacheIrregular'])) { - self::$singular['cacheUninflected'] = '(?:' . implode('|', self::$singular['merged']['uninflected']) . ')'; - self::$singular['cacheIrregular'] = '(?:' . implode('|', array_keys(self::$singular['merged']['irregular'])) . ')'; - } - - if (preg_match('/(.*)\\b(' . self::$singular['cacheIrregular'] . ')$/i', $word, $regs)) { - self::$cache['singularize'][$word] = $regs[1] . $word[0] . substr(self::$singular['merged']['irregular'][strtolower($regs[2])], 1); - - return self::$cache['singularize'][$word]; - } - - if (preg_match('/^(' . self::$singular['cacheUninflected'] . ')$/i', $word, $regs)) { - self::$cache['singularize'][$word] = $word; - - return $word; - } - - foreach (self::$singular['rules'] as $rule => $replacement) { - if (preg_match($rule, $word)) { - self::$cache['singularize'][$word] = preg_replace($rule, $replacement, $word); - - return self::$cache['singularize'][$word]; - } - } - - self::$cache['singularize'][$word] = $word; - - return $word; - } -} diff --git a/vendor/doctrine/instantiator/.doctrine-project.json b/vendor/doctrine/instantiator/.doctrine-project.json deleted file mode 100644 index 4fe86ee..0000000 --- a/vendor/doctrine/instantiator/.doctrine-project.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "active": true, - "name": "Instantiator", - "slug": "instantiator", - "docsSlug": "doctrine-instantiator", - "codePath": "/src", - "versions": [ - { - "name": "1.1", - "branchName": "master", - "slug": "latest", - "aliases": [ - "current", - "stable" - ], - "maintained": true, - "current": true - }, - { - "name": "1.0", - "branchName": "1.0.x", - "slug": "1.0" - } - ] -} - diff --git a/vendor/doctrine/instantiator/.github/FUNDING.yml b/vendor/doctrine/instantiator/.github/FUNDING.yml deleted file mode 100644 index 9a35064..0000000 --- a/vendor/doctrine/instantiator/.github/FUNDING.yml +++ /dev/null @@ -1,3 +0,0 @@ -patreon: phpdoctrine -tidelift: packagist/doctrine%2Finstantiator -custom: https://www.doctrine-project.org/sponsorship.html diff --git a/vendor/doctrine/instantiator/CONTRIBUTING.md b/vendor/doctrine/instantiator/CONTRIBUTING.md deleted file mode 100644 index c1a2c42..0000000 --- a/vendor/doctrine/instantiator/CONTRIBUTING.md +++ /dev/null @@ -1,35 +0,0 @@ -# Contributing - - * Follow the [Doctrine Coding Standard](https://github.com/doctrine/coding-standard) - * The project will follow strict [object calisthenics](http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php) - * Any contribution must provide tests for additional introduced conditions - * Any un-confirmed issue needs a failing test case before being accepted - * Pull requests must be sent from a new hotfix/feature branch, not from `master`. - -## Installation - -To install the project and run the tests, you need to clone it first: - -```sh -$ git clone git://github.com/doctrine/instantiator.git -``` - -You will then need to run a composer installation: - -```sh -$ cd Instantiator -$ curl -s https://getcomposer.org/installer | php -$ php composer.phar update -``` - -## Testing - -The PHPUnit version to be used is the one installed as a dev- dependency via composer: - -```sh -$ ./vendor/bin/phpunit -``` - -Accepted coverage for new contributions is 80%. Any contribution not satisfying this requirement -won't be merged. - diff --git a/vendor/doctrine/instantiator/LICENSE b/vendor/doctrine/instantiator/LICENSE deleted file mode 100644 index 4d983d1..0000000 --- a/vendor/doctrine/instantiator/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2014 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/doctrine/instantiator/README.md b/vendor/doctrine/instantiator/README.md deleted file mode 100644 index eff5a0c..0000000 --- a/vendor/doctrine/instantiator/README.md +++ /dev/null @@ -1,39 +0,0 @@ -# Instantiator - -This library provides a way of avoiding usage of constructors when instantiating PHP classes. - -[![Build Status](https://travis-ci.org/doctrine/instantiator.svg?branch=master)](https://travis-ci.org/doctrine/instantiator) -[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/instantiator/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/instantiator/?branch=master) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/instantiator/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/instantiator/?branch=master) -[![Dependency Status](https://www.versioneye.com/package/php--doctrine--instantiator/badge.svg)](https://www.versioneye.com/package/php--doctrine--instantiator) - -[![Latest Stable Version](https://poser.pugx.org/doctrine/instantiator/v/stable.png)](https://packagist.org/packages/doctrine/instantiator) -[![Latest Unstable Version](https://poser.pugx.org/doctrine/instantiator/v/unstable.png)](https://packagist.org/packages/doctrine/instantiator) - -## Installation - -The suggested installation method is via [composer](https://getcomposer.org/): - -```sh -php composer.phar require "doctrine/instantiator:~1.0.3" -``` - -## Usage - -The instantiator is able to create new instances of any class without using the constructor or any API of the class -itself: - -```php -$instantiator = new \Doctrine\Instantiator\Instantiator(); - -$instance = $instantiator->instantiate(\My\ClassName\Here::class); -``` - -## Contributing - -Please read the [CONTRIBUTING.md](CONTRIBUTING.md) contents if you wish to help out! - -## Credits - -This library was migrated from [ocramius/instantiator](https://github.com/Ocramius/Instantiator), which -has been donated to the doctrine organization, and which is now deprecated in favour of this package. diff --git a/vendor/doctrine/instantiator/composer.json b/vendor/doctrine/instantiator/composer.json deleted file mode 100644 index 9002a91..0000000 --- a/vendor/doctrine/instantiator/composer.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "doctrine/instantiator", - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "type": "library", - "license": "MIT", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "instantiate", - "constructor" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "require": { - "php": "^7.1" - }, - "require-dev": { - "ext-phar": "*", - "ext-pdo": "*", - "doctrine/coding-standard": "^6.0", - "phpbench/phpbench": "^0.13", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-shim": "^0.11", - "phpunit/phpunit": "^7.0" - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "autoload-dev": { - "psr-0": { - "DoctrineTest\\InstantiatorPerformance\\": "tests", - "DoctrineTest\\InstantiatorTest\\": "tests", - "DoctrineTest\\InstantiatorTestAsset\\": "tests" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - } -} diff --git a/vendor/doctrine/instantiator/docs/en/index.rst b/vendor/doctrine/instantiator/docs/en/index.rst deleted file mode 100644 index 0c85da0..0000000 --- a/vendor/doctrine/instantiator/docs/en/index.rst +++ /dev/null @@ -1,68 +0,0 @@ -Introduction -============ - -This library provides a way of avoiding usage of constructors when instantiating PHP classes. - -Installation -============ - -The suggested installation method is via `composer`_: - -.. code-block:: console - - $ composer require doctrine/instantiator - -Usage -===== - -The instantiator is able to create new instances of any class without -using the constructor or any API of the class itself: - -.. code-block:: php - - instantiate(User::class); - -Contributing -============ - -- Follow the `Doctrine Coding Standard`_ -- The project will follow strict `object calisthenics`_ -- Any contribution must provide tests for additional introduced - conditions -- Any un-confirmed issue needs a failing test case before being - accepted -- Pull requests must be sent from a new hotfix/feature branch, not from - ``master``. - -Testing -======= - -The PHPUnit version to be used is the one installed as a dev- dependency -via composer: - -.. code-block:: console - - $ ./vendor/bin/phpunit - -Accepted coverage for new contributions is 80%. Any contribution not -satisfying this requirement won’t be merged. - -Credits -======= - -This library was migrated from `ocramius/instantiator`_, which has been -donated to the doctrine organization, and which is now deprecated in -favour of this package. - -.. _composer: https://getcomposer.org/ -.. _CONTRIBUTING.md: CONTRIBUTING.md -.. _ocramius/instantiator: https://github.com/Ocramius/Instantiator -.. _Doctrine Coding Standard: https://github.com/doctrine/coding-standard -.. _object calisthenics: http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php diff --git a/vendor/doctrine/instantiator/docs/en/sidebar.rst b/vendor/doctrine/instantiator/docs/en/sidebar.rst deleted file mode 100644 index 0c36479..0000000 --- a/vendor/doctrine/instantiator/docs/en/sidebar.rst +++ /dev/null @@ -1,4 +0,0 @@ -.. toctree:: - :depth: 3 - - index diff --git a/vendor/doctrine/instantiator/phpbench.json b/vendor/doctrine/instantiator/phpbench.json deleted file mode 100644 index fce5dd6..0000000 --- a/vendor/doctrine/instantiator/phpbench.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "bootstrap": "vendor/autoload.php", - "path": "tests/DoctrineTest/InstantiatorPerformance" -} diff --git a/vendor/doctrine/instantiator/phpcs.xml.dist b/vendor/doctrine/instantiator/phpcs.xml.dist deleted file mode 100644 index 1fcac4a..0000000 --- a/vendor/doctrine/instantiator/phpcs.xml.dist +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - src - tests - - - - - - - - - - tests/DoctrineTest/InstantiatorTestAsset/AbstractClassAsset.php - - - - src/Doctrine/Instantiator/Exception/UnexpectedValueException.php - src/Doctrine/Instantiator/Exception/InvalidArgumentException.php - - - - src/Doctrine/Instantiator/Exception/ExceptionInterface.php - src/Doctrine/Instantiator/InstantiatorInterface.php - - diff --git a/vendor/doctrine/instantiator/phpstan.neon.dist b/vendor/doctrine/instantiator/phpstan.neon.dist deleted file mode 100644 index ecc38ef..0000000 --- a/vendor/doctrine/instantiator/phpstan.neon.dist +++ /dev/null @@ -1,19 +0,0 @@ -includes: - - vendor/phpstan/phpstan-phpunit/extension.neon - - vendor/phpstan/phpstan-phpunit/rules.neon - -parameters: - level: max - paths: - - src - - tests - - ignoreErrors: - - - message: '#::__construct\(\) does not call parent constructor from#' - path: '*/tests/DoctrineTest/InstantiatorTestAsset/*.php' - - # dynamic properties confuse static analysis - - - message: '#Access to an undefined property object::\$foo\.#' - path: '*/tests/DoctrineTest/InstantiatorTest/InstantiatorTest.php' diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php deleted file mode 100644 index e6a5195..0000000 --- a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php +++ /dev/null @@ -1,12 +0,0 @@ -= 50400 && trait_exists($className)) { - return new self(sprintf('The provided type "%s" is a trait, and can not be instantiated', $className)); - } - - return new self(sprintf('The provided class "%s" does not exist', $className)); - } - - public static function fromAbstractClass(ReflectionClass $reflectionClass) : self - { - return new self(sprintf( - 'The provided class "%s" is abstract, and can not be instantiated', - $reflectionClass->getName() - )); - } -} diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php deleted file mode 100644 index d946731..0000000 --- a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php +++ /dev/null @@ -1,48 +0,0 @@ -getName() - ), - 0, - $exception - ); - } - - public static function fromUncleanUnSerialization( - ReflectionClass $reflectionClass, - string $errorString, - int $errorCode, - string $errorFile, - int $errorLine - ) : self { - return new self( - sprintf( - 'Could not produce an instance of "%s" via un-serialization, since an error was triggered ' - . 'in file "%s" at line "%d"', - $reflectionClass->getName(), - $errorFile, - $errorLine - ), - 0, - new Exception($errorString, $errorCode) - ); - } -} diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php deleted file mode 100644 index 9c67862..0000000 --- a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php +++ /dev/null @@ -1,203 +0,0 @@ -buildAndCacheFromFactory($className); - } - - /** - * Builds the requested object and caches it in static properties for performance - * - * @return object - */ - private function buildAndCacheFromFactory(string $className) - { - $factory = self::$cachedInstantiators[$className] = $this->buildFactory($className); - $instance = $factory(); - - if ($this->isSafeToClone(new ReflectionClass($instance))) { - self::$cachedCloneables[$className] = clone $instance; - } - - return $instance; - } - - /** - * Builds a callable capable of instantiating the given $className without - * invoking its constructor. - * - * @throws InvalidArgumentException - * @throws UnexpectedValueException - * @throws ReflectionException - */ - private function buildFactory(string $className) : callable - { - $reflectionClass = $this->getReflectionClass($className); - - if ($this->isInstantiableViaReflection($reflectionClass)) { - return [$reflectionClass, 'newInstanceWithoutConstructor']; - } - - $serializedString = sprintf( - '%s:%d:"%s":0:{}', - is_subclass_of($className, Serializable::class) ? self::SERIALIZATION_FORMAT_USE_UNSERIALIZER : self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER, - strlen($className), - $className - ); - - $this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString); - - return static function () use ($serializedString) { - return unserialize($serializedString); - }; - } - - /** - * @throws InvalidArgumentException - * @throws ReflectionException - */ - private function getReflectionClass(string $className) : ReflectionClass - { - if (! class_exists($className)) { - throw InvalidArgumentException::fromNonExistingClass($className); - } - - $reflection = new ReflectionClass($className); - - if ($reflection->isAbstract()) { - throw InvalidArgumentException::fromAbstractClass($reflection); - } - - return $reflection; - } - - /** - * @throws UnexpectedValueException - */ - private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, string $serializedString) : void - { - set_error_handler(static function (int $code, string $message, string $file, int $line) use ($reflectionClass, &$error) : bool { - $error = UnexpectedValueException::fromUncleanUnSerialization( - $reflectionClass, - $message, - $code, - $file, - $line - ); - - return true; - }); - - try { - $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString); - } finally { - restore_error_handler(); - } - - if ($error) { - throw $error; - } - } - - /** - * @throws UnexpectedValueException - */ - private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, string $serializedString) : void - { - try { - unserialize($serializedString); - } catch (Exception $exception) { - throw UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception); - } - } - - private function isInstantiableViaReflection(ReflectionClass $reflectionClass) : bool - { - return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal()); - } - - /** - * Verifies whether the given class is to be considered internal - */ - private function hasInternalAncestors(ReflectionClass $reflectionClass) : bool - { - do { - if ($reflectionClass->isInternal()) { - return true; - } - - $reflectionClass = $reflectionClass->getParentClass(); - } while ($reflectionClass); - - return false; - } - - /** - * Checks if a class is cloneable - * - * Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects. - */ - private function isSafeToClone(ReflectionClass $reflection) : bool - { - return $reflection->isCloneable() - && ! $reflection->hasMethod('__clone') - && ! $reflection->isSubclassOf(ArrayIterator::class); - } -} diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php deleted file mode 100644 index 95299f4..0000000 --- a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php +++ /dev/null @@ -1,20 +0,0 @@ -input = $input; - $this->tokens = []; - - $this->reset(); - $this->scan($input); - } - - /** - * Resets the lexer. - * - * @return void - */ - public function reset() - { - $this->lookahead = null; - $this->token = null; - $this->peek = 0; - $this->position = 0; - } - - /** - * Resets the peek pointer to 0. - * - * @return void - */ - public function resetPeek() - { - $this->peek = 0; - } - - /** - * Resets the lexer position on the input to the given position. - * - * @param int $position Position to place the lexical scanner. - * - * @return void - */ - public function resetPosition($position = 0) - { - $this->position = $position; - } - - /** - * Retrieve the original lexer's input until a given position. - * - * @param int $position - * - * @return string - */ - public function getInputUntilPosition($position) - { - return substr($this->input, 0, $position); - } - - /** - * Checks whether a given token matches the current lookahead. - * - * @param int|string $token - * - * @return bool - */ - public function isNextToken($token) - { - return $this->lookahead !== null && $this->lookahead['type'] === $token; - } - - /** - * Checks whether any of the given tokens matches the current lookahead. - * - * @param array $tokens - * - * @return bool - */ - public function isNextTokenAny(array $tokens) - { - return $this->lookahead !== null && in_array($this->lookahead['type'], $tokens, true); - } - - /** - * Moves to the next token in the input string. - * - * @return bool - */ - 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 string $type The token type to skip until. - * - * @return void - */ - 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 int|string $token - * - * @return bool - */ - 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++]; - } - - 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. - * - * @return void - */ - protected function scan($input) - { - if (! isset($this->regex)) { - $this->regex = sprintf( - '/(%s)|%s/%s', - implode(')|(', $this->getCatchablePatterns()), - implode('|', $this->getNonCatchablePatterns()), - $this->getModifiers() - ); - } - - $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; - $matches = preg_split($this->regex, $input, -1, $flags); - - if ($matches === false) { - // Work around https://bugs.php.net/78122 - $matches = [[$input, 0]]; - } - - foreach ($matches as $match) { - // Must remain before 'value' assignment since it can change content - $type = $this->getType($match[0]); - - $this->tokens[] = [ - 'value' => $match[0], - 'type' => $type, - 'position' => $match[1], - ]; - } - } - - /** - * Gets the literal for a given token. - * - * @param int|string $token - * - * @return int|string - */ - public function getLiteral($token) - { - $className = static::class; - $reflClass = new ReflectionClass($className); - $constants = $reflClass->getConstants(); - - foreach ($constants as $name => $value) { - if ($value === $token) { - return $className . '::' . $name; - } - } - - return $token; - } - - /** - * Regex modifiers - * - * @return string - */ - protected function getModifiers() - { - return 'iu'; - } - - /** - * 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 int|string|null - */ - abstract protected function getType(&$value); -} diff --git a/vendor/doctrine/orm/.scrutinizer.yml b/vendor/doctrine/orm/.scrutinizer.yml deleted file mode 100644 index d05c72c..0000000 --- a/vendor/doctrine/orm/.scrutinizer.yml +++ /dev/null @@ -1,34 +0,0 @@ -build: - nodes: - analysis: - environment: - php: - version: 7.1 - cache: - disabled: false - directories: - - ~/.composer/cache - - project_setup: - override: true - tests: - override: - - php-scrutinizer-run - -before_commands: - - "composer install --no-dev --prefer-source" - -tools: - external_code_coverage: - timeout: 3600 - -filter: - excluded_paths: - - docs - - tools - -build_failure_conditions: - - 'elements.rating(<= C).new.exists' # No new classes/methods with a rating of C or worse allowed - - 'issues.severity(>= MAJOR).new.exists' # New issues of major or higher severity - - 'project.metric_change("scrutinizer.test_coverage", < 0)' # Code Coverage decreased from previous inspection - - 'patches.label("Unused Use Statements").new.exists' # No new unused imports patches allowed diff --git a/vendor/doctrine/orm/LICENSE b/vendor/doctrine/orm/LICENSE deleted file mode 100644 index 8c38cc1..0000000 --- a/vendor/doctrine/orm/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006-2015 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/doctrine/orm/README.md b/vendor/doctrine/orm/README.md deleted file mode 100644 index 7f935fc..0000000 --- a/vendor/doctrine/orm/README.md +++ /dev/null @@ -1,26 +0,0 @@ -| [Master][Master] | [2.5][2.5] | -|:----------------:|:----------:| -| [![Build status][Master image]][Master] | [![Build status][2.5 image]][2.5] | -| [![Coverage Status][Master coverage image]][Master coverage] | [![Coverage Status][2.5 coverage image]][2.5 coverage] | - -Doctrine 2 is an object-relational mapper (ORM) for PHP 7.1+ that provides transparent persistence -for PHP objects. It sits on top of a powerful database abstraction layer (DBAL). One of its key features -is the option to write database queries in a proprietary object oriented SQL dialect called Doctrine Query Language (DQL), -inspired by Hibernate's HQL. This provides developers with a powerful alternative to SQL that maintains flexibility -without requiring unnecessary code duplication. - - -## More resources: - -* [Website](http://www.doctrine-project.org) -* [Documentation](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/index.html) - - - [Master image]: https://img.shields.io/travis/doctrine/orm/master.svg?style=flat-square - [Master]: https://travis-ci.org/doctrine/orm - [Master coverage image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/orm/master.svg?style=flat-square - [Master coverage]: https://scrutinizer-ci.com/g/doctrine/orm/?branch=master - [2.5 image]: https://img.shields.io/travis/doctrine/orm/2.5.svg?style=flat-square - [2.5]: https://github.com/doctrine/orm/tree/2.5 - [2.5 coverage image]: https://img.shields.io/scrutinizer/coverage/g/doctrine/orm/2.5.svg?style=flat-square - [2.5 coverage]: https://scrutinizer-ci.com/g/doctrine/orm/?branch=2.5 diff --git a/vendor/doctrine/orm/SECURITY.md b/vendor/doctrine/orm/SECURITY.md deleted file mode 100644 index 0789963..0000000 --- a/vendor/doctrine/orm/SECURITY.md +++ /dev/null @@ -1,18 +0,0 @@ -Security -======== - -The Doctrine library is operating very close to your database and as such needs -to handle and make assumptions about SQL injection vulnerabilities. - -It is vital that you understand how Doctrine approaches security, because -we cannot protect you from SQL injection. - -Please read the documentation chapter on Security in Doctrine DBAL and ORM to -understand the assumptions we make. - -- [DBAL Security Page](https://github.com/doctrine/dbal/blob/master/docs/en/reference/security.rst) -- [ORM Security Page](https://github.com/doctrine/orm/blob/master/docs/en/reference/security.rst) - -If you find a Security bug in Doctrine, please report it on Jira and change the -Security Level to "Security Issues". It will be visible to Doctrine Core -developers and you only. diff --git a/vendor/doctrine/orm/UPGRADE.md b/vendor/doctrine/orm/UPGRADE.md deleted file mode 100644 index c6c6eaa..0000000 --- a/vendor/doctrine/orm/UPGRADE.md +++ /dev/null @@ -1,865 +0,0 @@ -# Upgrade to 2.7 - -## Added `Doctrine\ORM\AbstractQuery#enableResultCache()` and `Doctrine\ORM\AbstractQuery#disableResultCache()` methods - -Method `Doctrine\ORM\AbstractQuery#useResultCache()` which could be used for both enabling and disabling the cache -(depending on passed flag) was split into two. - -## Minor BC BREAK: paginator output walkers aren't be called anymore on sub-queries for queries without max results - -To optimize DB interaction, `Doctrine\ORM\Tools\Pagination\Paginator` no longer fetches identifiers to be able to -perform the pagination with join collections when max results isn't set in the query. - -## Deprecated number unaware `Doctrine\ORM\Mapping\UnderscoreNamingStrategy` - -In the last patch of the `v2.6.x` series, we fixed a bug that was not converting names properly when they had numbers -(e.g.: `base64Encoded` was wrongly converted to `base64encoded` instead of `base64_encoded`). - -In order to not break BC we've introduced a way to enable the fixed behavior using a boolean constructor argument. This -argument will be removed in 3.0 and the default behavior will be the fixed one. - -## Deprecated: `Doctrine\ORM\AbstractQuery#useResultCache()` - -Method `Doctrine\ORM\AbstractQuery#useResultCache()` is deprecated because it is split into `enableResultCache()` -and `disableResultCache()`. It will be removed in 3.0. - -## Deprecated code generators and related console commands - -These console commands have been deprecated: - - * `orm:convert-mapping` - * `orm:generate:entities` - * `orm:generate-repositories` - -These classes have been deprecated: - - * `Doctrine\ORM\Tools\EntityGenerator` - * `Doctrine\ORM\Tools\EntityRepositoryGenerator` - -Whole Doctrine\ORM\Tools\Export namespace with all its members have been deprecated as well. - -## Deprecated `Doctrine\ORM\Proxy\Proxy` marker interface - -Proxy objects in Doctrine ORM 3.0 will no longer implement `Doctrine\ORM\Proxy\Proxy` nor -`Doctrine\Common\Persistence\Proxy`: instead, they implement -`ProxyManager\Proxy\GhostObjectInterface`. - -These related classes have been deprecated: - - * `Doctrine\ORM\Proxy\ProxyFactory` - * `Doctrine\ORM\Proxy\Autoloader` - we suggest using the composer autoloader instead - -These methods have been deprecated: - - * `Doctrine\ORM\Configuration#getAutoGenerateProxyClasses()` - * `Doctrine\ORM\Configuration#getProxyDir()` - * `Doctrine\ORM\Configuration#getProxyNamespace()` - -## Deprecated `Doctrine\ORM\Version` - -The `Doctrine\ORM\Version` class is now deprecated and will be removed in Doctrine ORM 3.0: -please refrain from checking the ORM version at runtime or use -[ocramius/package-versions](https://github.com/Ocramius/PackageVersions/). - -## Deprecated `EntityManager#merge()` and `EntityManager#detach()` methods - -Merge and detach semantics were a poor fit for the PHP "share-nothing" architecture. -In addition to that, merging/detaching caused multiple issues with data integrity -in the managed entity graph, which was constantly spawning more edge-case bugs/scenarios. - -The following API methods were therefore deprecated: - -* `EntityManager#merge()` -* `EntityManager#detach()` -* `UnitOfWork#merge()` -* `UnitOfWork#detach()` - -Users are encouraged to migrate `EntityManager#detach()` calls to `EntityManager#clear()`. - -In order to maintain performance on batch processing jobs, it is endorsed to enable -the second level cache (http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/second-level-cache.html) -on entities that are frequently reused across multiple `EntityManager#clear()` calls. - -An alternative to `EntityManager#merge()` will not be provided by ORM 3.0, since the merging -semantics should be part of the business domain rather than the persistence domain of an -application. If your application relies heavily on CRUD-alike interactions and/or `PATCH` -restful operations, you should look at alternatives such as [JMSSerializer](https://github.com/schmittjoh/serializer). - -## Extending `EntityManager` is deprecated - -Final keyword will be added to the `EntityManager::class` in Doctrine ORM 3.0 in order to ensure that EntityManager - is not used as valid extension point. Valid extension point should be EntityManagerInterface. - -## Deprecated `EntityManager#clear($entityName)` - -If your code relies on clearing a single entity type via `EntityManager#clear($entityName)`, -the signature has been changed to `EntityManager#clear()`. - -The main reason is that partial clears caused multiple issues with data integrity -in the managed entity graph, which was constantly spawning more edge-case bugs/scenarios. - -## Deprecated `EntityManager#flush($entity)` and `EntityManager#flush($entities)` - -If your code relies on single entity flushing optimisations via -`EntityManager#flush($entity)`, the signature has been changed to -`EntityManager#flush()`. - -Said API was affected by multiple data integrity bugs due to the fact -that change tracking was being restricted upon a subset of the managed -entities. The ORM cannot support committing subsets of the managed -entities while also guaranteeing data integrity, therefore this -utility was removed. - -The `flush()` semantics will remain the same, but the change tracking will be performed -on all entities managed by the unit of work, and not just on the provided -`$entity` or `$entities`, as the parameter is now completely ignored. - -The same applies to `UnitOfWork#commit($entity)`, which will simply be -`UnitOfWork#commit()`. - -If you would still like to perform batching operations over small `UnitOfWork` -instances, it is suggested to follow these paths instead: - - * eagerly use `EntityManager#clear()` in conjunction with a specific second level - cache configuration (see http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/second-level-cache.html) - * use an explicit change tracking policy (see http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/change-tracking-policies.html) - -## Deprecated `YAML` mapping drivers. - -If your code relies on `YamlDriver` or `SimpleYamlDriver`, you **MUST** change to -annotation or XML drivers instead. - -## Deprecated: `Doctrine\ORM\EntityManagerInterface#copy()` - -Method `Doctrine\ORM\EntityManagerInterface#copy()` never got its implementation and is deprecated. -It will be removed in 3.0. - -# Upgrade to 2.6 - -## Added `Doctrine\ORM\EntityRepository::count()` method - -`Doctrine\ORM\EntityRepository::count()` has been added. This new method has different -signature than `Countable::count()` (required parameter) and therefore are not compatible. -If your repository implemented the `Countable` interface, you will have to use -`$repository->count([])` instead and not implement `Countable` interface anymore. - -## Minor BC BREAK: `Doctrine\ORM\Tools\Console\ConsoleRunner` is now final - -Since it's just an utilitarian class and should not be inherited. - -## Minor BC BREAK: removed `Doctrine\ORM\Query\QueryException::associationPathInverseSideNotSupported()` - -Method `Doctrine\ORM\Query\QueryException::associationPathInverseSideNotSupported()` -now has a required parameter `$pathExpr`. - -## Minor BC BREAK: removed `Doctrine\ORM\Query\Parser#isInternalFunction()` - -Method `Doctrine\ORM\Query\Parser#isInternalFunction()` was removed because -the distinction between internal function and user defined DQL was removed. -[#6500](https://github.com/doctrine/orm/pull/6500) - -## Minor BC BREAK: removed `Doctrine\ORM\ORMException#overwriteInternalDQLFunctionNotAllowed()` - -Method `Doctrine\ORM\Query\Parser#overwriteInternalDQLFunctionNotAllowed()` was -removed because of the choice to allow users to overwrite internal functions, ie -`AVG`, `SUM`, `COUNT`, `MIN` and `MAX`. [#6500](https://github.com/doctrine/orm/pull/6500) - -## PHP 7.1 is now required - -Doctrine 2.6 now requires PHP 7.1 or newer. - -As a consequence, automatic cache setup in Doctrine\ORM\Tools\Setup::create*Configuration() was changed: -- APCu extension (ext-apcu) will now be used instead of abandoned APC (ext-apc). -- Memcached extension (ext-memcached) will be used instead of obsolete Memcache (ext-memcache). -- XCache support was dropped as it doesn't work with PHP 7. - -# Upgrade to 2.5 - -## Minor BC BREAK: removed `Doctrine\ORM\Query\SqlWalker#walkCaseExpression()` - -Method `Doctrine\ORM\Query\SqlWalker#walkCaseExpression()` was unused and part -of the internal API of the ORM, so it was removed. [#5600](https://github.com/doctrine/orm/pull/5600). - -## Minor BC BREAK: removed $className parameter on `AbstractEntityInheritancePersister#getSelectJoinColumnSQL()` - -As `$className` parameter was not used in the method, it was safely removed. - -## Minor BC BREAK: query cache key time is now a float - -As of 2.5.5, the `QueryCacheEntry#time` property will contain a float value -instead of an integer in order to have more precision and also to be consistent -with the `TimestampCacheEntry#time`. - -## Minor BC BREAK: discriminator map must now include all non-transient classes - -It is now required that you declare the root of an inheritance in the -discriminator map. - -When declaring an inheritance map, it was previously possible to skip the root -of the inheritance in the discriminator map. This was actually a validation -mistake by Doctrine2 and led to problems when trying to persist instances of -that class. - -If you don't plan to persist instances some classes in your inheritance, then -either: - - - make those classes `abstract` - - map those classes as `MappedSuperclass` - -## Minor BC BREAK: ``EntityManagerInterface`` instead of ``EntityManager`` in type-hints - -As of 2.5, classes requiring the ``EntityManager`` in any method signature will now require -an ``EntityManagerInterface`` instead. -If you are extending any of the following classes, then you need to check following -signatures: - -- ``Doctrine\ORM\Tools\DebugUnitOfWorkListener#dumpIdentityMap(EntityManagerInterface $em)`` -- ``Doctrine\ORM\Mapping\ClassMetadataFactory#setEntityManager(EntityManagerInterface $em)`` - -## Minor BC BREAK: Custom Hydrators API change - -As of 2.5, `AbstractHydrator` does not enforce the usage of cache as part of -API, and now provides you a clean API for column information through the method -`hydrateColumnInfo($column)`. -Cache variable being passed around by reference is no longer needed since -Hydrators are per query instantiated since Doctrine 2.4. - -## Minor BC BREAK: Entity based ``EntityManager#clear()`` calls follow cascade detach - -Whenever ``EntityManager#clear()`` method gets called with a given entity class -name, until 2.4, it was only detaching the specific requested entity. -As of 2.5, ``EntityManager`` will follow configured cascades, providing a better -memory management since associations will be garbage collected, optimizing -resources consumption on long running jobs. - -## BC BREAK: NamingStrategy interface changes - -1. A new method ``embeddedFieldToColumnName($propertyName, $embeddedColumnName)`` - -This method generates the column name for fields of embedded objects. If you implement your custom NamingStrategy, you -now also need to implement this new method. - -2. A change to method ``joinColumnName()`` to include the $className - -## Updates on entities scheduled for deletion are no longer processed - -In Doctrine 2.4, if you modified properties of an entity scheduled for deletion, UnitOfWork would -produce an UPDATE statement to be executed right before the DELETE statement. The entity in question -was therefore present in ``UnitOfWork#entityUpdates``, which means that ``preUpdate`` and ``postUpdate`` -listeners were (quite pointlessly) called. In ``preFlush`` listeners, it used to be possible to undo -the scheduled deletion for updated entities (by calling ``persist()`` if the entity was found in both -``entityUpdates`` and ``entityDeletions``). This does not work any longer, because the entire changeset -calculation logic is optimized away. - -## Minor BC BREAK: Default lock mode changed from LockMode::NONE to null in method signatures - -A misconception concerning default lock mode values in method signatures lead to unexpected behaviour -in SQL statements on SQL Server. With a default lock mode of ``LockMode::NONE`` throughout the -method signatures in ORM, the table lock hint ``WITH (NOLOCK)`` was appended to all locking related -queries by default. This could result in unpredictable results because an explicit ``WITH (NOLOCK)`` -table hint tells SQL Server to run a specific query in transaction isolation level READ UNCOMMITTED -instead of the default READ COMMITTED transaction isolation level. -Therefore there now is a distinction between ``LockMode::NONE`` and ``null`` to be able to tell -Doctrine whether to add table lock hints to queries by intention or not. To achieve this, the following -method signatures have been changed to declare ``$lockMode = null`` instead of ``$lockMode = LockMode::NONE``: - -- ``Doctrine\ORM\Cache\Persister\AbstractEntityPersister#getSelectSQL()`` -- ``Doctrine\ORM\Cache\Persister\AbstractEntityPersister#load()`` -- ``Doctrine\ORM\Cache\Persister\AbstractEntityPersister#refresh()`` -- ``Doctrine\ORM\Decorator\EntityManagerDecorator#find()`` -- ``Doctrine\ORM\EntityManager#find()`` -- ``Doctrine\ORM\EntityRepository#find()`` -- ``Doctrine\ORM\Persisters\BasicEntityPersister#getSelectSQL()`` -- ``Doctrine\ORM\Persisters\BasicEntityPersister#load()`` -- ``Doctrine\ORM\Persisters\BasicEntityPersister#refresh()`` -- ``Doctrine\ORM\Persisters\EntityPersister#getSelectSQL()`` -- ``Doctrine\ORM\Persisters\EntityPersister#load()`` -- ``Doctrine\ORM\Persisters\EntityPersister#refresh()`` -- ``Doctrine\ORM\Persisters\JoinedSubclassPersister#getSelectSQL()`` - -You should update signatures for these methods if you have subclassed one of the above classes. -Please also check the calling code of these methods in your application and update if necessary. - -**Note:** -This in fact is really a minor BC BREAK and should not have any affect on database vendors -other than SQL Server because it is the only one that supports and therefore cares about -``LockMode::NONE``. It's really just a FIX for SQL Server environments using ORM. - -## Minor BC BREAK: `__clone` method not called anymore when entities are instantiated via metadata API - -As of PHP 5.6, instantiation of new entities is deferred to the -[`doctrine/instantiator`](https://github.com/doctrine/instantiator) library, which will avoid calling `__clone` -or any public API on instantiated objects. - -## BC BREAK: `Doctrine\ORM\Repository\DefaultRepositoryFactory` is now `final` - -Please implement the `Doctrine\ORM\Repository\RepositoryFactory` interface instead of extending -the `Doctrine\ORM\Repository\DefaultRepositoryFactory`. - -## BC BREAK: New object expression DQL queries now respects user provided aliasing and not return consumed fields - -When executing DQL queries with new object expressions, instead of returning DTOs numerically indexes, it will now respect user provided aliases. Consider the following query: - - SELECT new UserDTO(u.id,u.name) as user,new AddressDTO(a.street,a.postalCode) as address, a.id as addressId FROM User u INNER JOIN u.addresses a WITH a.isPrimary = true - -Previously, your result would be similar to this: - - array( - 0=>array( - 0=>{UserDTO object}, - 1=>{AddressDTO object}, - 2=>{u.id scalar}, - 3=>{u.name scalar}, - 4=>{a.street scalar}, - 5=>{a.postalCode scalar}, - 'addressId'=>{a.id scalar}, - ), - ... - ) - -From now on, the resultset will look like this: - - array( - 0=>array( - 'user'=>{UserDTO object}, - 'address'=>{AddressDTO object}, - 'addressId'=>{a.id scalar} - ), - ... - ) - -## Minor BC BREAK: added second parameter $indexBy in EntityRepository#createQueryBuilder method signature - -Added way to access the underlying QueryBuilder#from() method's 'indexBy' parameter when using EntityRepository#createQueryBuilder() - -# Upgrade to 2.4 - -## BC BREAK: Compatibility Bugfix in PersistentCollection#matching() - -In Doctrine 2.3 it was possible to use the new ``matching($criteria)`` -functionality by adding constraints for assocations based on ID: - - Criteria::expr()->eq('association', $assocation->getId()); - -This functionality does not work on InMemory collections however, because -in memory criteria compares object values based on reference. -As of 2.4 the above code will throw an exception. You need to change -offending code to pass the ``$assocation`` reference directly: - - Criteria::expr()->eq('association', $assocation); - -## Composer is now the default autoloader - -The test suite now runs with composer autoloading. Support for PEAR, and tarball autoloading is deprecated. -Support for GIT submodules is removed. - -## OnFlush and PostFlush event always called - -Before 2.4 the postFlush and onFlush events were only called when there were -actually entities that changed. Now these events are called no matter if there -are entities in the UoW or changes are found. - -## Parenthesis are now considered in arithmetic expression - -Before 2.4 parenthesis are not considered in arithmetic primary expression. -That's conceptually wrong, since it might result in wrong values. For example: - -The DQL: - - SELECT 100 / ( 2 * 2 ) FROM MyEntity - -Before 2.4 it generates the SQL: - - SELECT 100 / 2 * 2 FROM my_entity - -Now parenthesis are considered, the previous DQL will generate: - - SELECT 100 / (2 * 2) FROM my_entity - -# Upgrade to 2.3 - -## Auto Discriminator Map breaks userland implementations with Listener - -The new feature to detect discriminator maps automatically when none -are provided breaks userland implementations doing this with a -listener in ``loadClassMetadata`` event. - -## EntityManager#find() not calls EntityRepository#find() anymore - -Previous to 2.3, calling ``EntityManager#find()`` would be delegated to -``EntityRepository#find()``. This has lead to some unexpected behavior in the -core of Doctrine when people have overwritten the find method in their -repositories. That is why this behavior has been reversed in 2.3, and -``EntityRepository#find()`` calls ``EntityManager#find()`` instead. - -## EntityGenerator add*() method generation - -When generating an add*() method for a collection the EntityGenerator will now not -use the Type-Hint to get the singular for the collection name, but use the field-name -and strip a trailing "s" character if there is one. - -## Merge copies non persisted properties too - -When merging an entity in UoW not only mapped properties are copied, but also others. - -## Query, QueryBuilder and NativeQuery parameters *BC break* - -From now on, parameters in queries is an ArrayCollection instead of a simple array. -This affects heavily the usage of setParameters(), because it will not append anymore -parameters to query, but will actually override the already defined ones. -Whenever you are retrieving a parameter (ie. $query->getParameter(1)), you will -receive an instance of Query\Parameter, which contains the methods "getName", -"getValue" and "getType". Parameters are also only converted to when necessary, and -not when they are set. - -Also, related functions were affected: - -* execute($parameters, $hydrationMode) the argument $parameters can be either an key=>value array or an ArrayCollection instance -* iterate($parameters, $hydrationMode) the argument $parameters can be either an key=>value array or an ArrayCollection instance -* setParameters($parameters) the argument $parameters can be either an key=>value array or an ArrayCollection instance -* getParameters() now returns ArrayCollection instead of array -* getParameter($key) now returns Parameter instance instead of parameter value - -## Query TreeWalker method renamed - -Internal changes were made to DQL and SQL generation. If you have implemented your own TreeWalker, -you probably need to update it. The method walkJoinVariableDeclaration is now named walkJoin. - -## New methods in TreeWalker interface *BC break* - -Two methods getQueryComponents() and setQueryComponent() were added to the TreeWalker interface and all its implementations -including TreeWalkerAdapter, TreeWalkerChain and SqlWalker. If you have your own implementation not inheriting from one of the -above you must implement these new methods. - -## Metadata Drivers - -Metadata drivers have been rewritten to reuse code from Doctrine\Common. Anyone who is using the -`Doctrine\ORM\Mapping\Driver\Driver` interface should instead refer to -`Doctrine\Common\Persistence\Mapping\Driver\MappingDriver`. Same applies to -`Doctrine\ORM\Mapping\Driver\AbstractFileDriver`: you should now refer to -`Doctrine\Common\Persistence\Mapping\Driver\FileDriver`. - -Also, following mapping drivers have been deprecated, please use their replacements in Doctrine\Common as listed: - - * `Doctrine\ORM\Mapping\Driver\DriverChain` => `Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain` - * `Doctrine\ORM\Mapping\Driver\PHPDriver` => `Doctrine\Common\Persistence\Mapping\Driver\PHPDriver` - * `Doctrine\ORM\Mapping\Driver\StaticPHPDriver` => `Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver` - -# Upgrade to 2.2 - -## ResultCache implementation rewritten - -The result cache is completely rewritten and now works on the database result level, not inside the ORM AbstractQuery -anymore. This means that for result cached queries the hydration will now always be performed again, regardless of -the hydration mode. Affected areas are: - -1. Fixes the problem that entities coming from the result cache were not registered in the UnitOfWork - leading to problems during EntityManager#flush. Calls to EntityManager#merge are not necessary anymore. -2. Affects the array hydrator which now includes the overhead of hydration compared to caching the final result. - -The API is backwards compatible however most of the getter methods on the `AbstractQuery` object are now -deprecated in favor of calling AbstractQuery#getQueryCacheProfile(). This method returns a `Doctrine\DBAL\Cache\QueryCacheProfile` -instance with access to result cache driver, lifetime and cache key. - - -## EntityManager#getPartialReference() creates read-only entity - -Entities returned from EntityManager#getPartialReference() are now marked as read-only if they -haven't been in the identity map before. This means objects of this kind never lead to changes -in the UnitOfWork. - - -## Fields omitted in a partial DQL query or a native query are never updated - -Fields of an entity that are not returned from a partial DQL Query or native SQL query -will never be updated through an UPDATE statement. - - -## Removed support for onUpdate in @JoinColumn - -The onUpdate foreign key handling makes absolutely no sense in an ORM. Additionally Oracle doesn't even support it. Support for it is removed. - - -## Changes in Annotation Handling - -There have been some changes to the annotation handling in Common 2.2 again, that affect how people with old configurations -from 2.0 have to configure the annotation driver if they don't use `Configuration::newDefaultAnnotationDriver()`: - - // Register the ORM Annotations in the AnnotationRegistry - AnnotationRegistry::registerFile('path/to/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php'); - - $reader = new \Doctrine\Common\Annotations\SimpleAnnotationReader(); - $reader->addNamespace('Doctrine\ORM\Mapping'); - $reader = new \Doctrine\Common\Annotations\CachedReader($reader, new ArrayCache()); - - $driver = new AnnotationDriver($reader, (array)$paths); - - $config->setMetadataDriverImpl($driver); - - -## Scalar mappings can now be omitted from DQL result - -You are now allowed to mark scalar SELECT expressions as HIDDEN an they are not hydrated anymore. -Example: - -SELECT u, SUM(a.id) AS HIDDEN numArticles FROM User u LEFT JOIN u.Articles a ORDER BY numArticles DESC HAVING numArticles > 10 - -Your result will be a collection of Users, and not an array with key 0 as User object instance and "numArticles" as the number of articles per user - - -## Map entities as scalars in DQL result - -When hydrating to array or even a mixed result in object hydrator, previously you had the 0 index holding you entity instance. -You are now allowed to alias this, providing more flexibility for you code. -Example: - -SELECT u AS user FROM User u - -Will now return a collection of arrays with index "user" pointing to the User object instance. - - -## Performance optimizations - -Thousands of lines were completely reviewed and optimized for best performance. -Removed redundancy and improved code readability made now internal Doctrine code easier to understand. -Also, Doctrine 2.2 now is around 10-15% faster than 2.1. - -## EntityManager#find(null) - -Previously EntityManager#find(null) returned null. It now throws an exception. - -# Upgrade to 2.1 - -## Interface for EntityRepository - -The EntityRepository now has an interface Doctrine\Common\Persistence\ObjectRepository. This means that your classes that override EntityRepository and extend find(), findOneBy() or findBy() must be adjusted to follow this interface. - -## AnnotationReader changes - -The annotation reader was heavily refactored between 2.0 and 2.1-RC1. In theory the operation of the new reader should be backwards compatible, but it has to be setup differently to work that way: - - // new call to the AnnotationRegistry - \Doctrine\Common\Annotations\AnnotationRegistry::registerFile('/doctrine-src/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php'); - - $reader = new \Doctrine\Common\Annotations\AnnotationReader(); - $reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\'); - // new code necessary starting here - $reader->setIgnoreNotImportedAnnotations(true); - $reader->setEnableParsePhpImports(false); - $reader = new \Doctrine\Common\Annotations\CachedReader( - new \Doctrine\Common\Annotations\IndexedReader($reader), new ArrayCache() - ); - -This is already done inside the ``$config->newDefaultAnnotationDriver``, so everything should automatically work if you are using this method. You can verify if everything still works by executing a console command such as schema-validate that loads all metadata into memory. - -# Update from 2.0-BETA3 to 2.0-BETA4 - -## XML Driver element demoted to attribute - -We changed how the XML Driver allows to define the change-tracking-policy. The working case is now: - - - -# Update from 2.0-BETA2 to 2.0-BETA3 - -## Serialization of Uninitialized Proxies - -As of Beta3 you can now serialize uninitialized proxies, an exception will only be thrown when -trying to access methods on the unserialized proxy as long as it has not been re-attached to the -EntityManager using `EntityManager#merge()`. See this example: - - $proxy = $em->getReference('User', 1); - - $serializedProxy = serialize($proxy); - $detachedProxy = unserialized($serializedProxy); - - echo $em->contains($detachedProxy); // FALSE - - try { - $detachedProxy->getId(); // uninitialized detached proxy - } catch(Exception $e) { - - } - $attachedProxy = $em->merge($detachedProxy); - echo $attackedProxy->getId(); // works! - -## Changed SQL implementation of Postgres and Oracle DateTime types - -The DBAL Type "datetime" included the Timezone Offset in both Postgres and Oracle. As of this version they are now -generated without Timezone (TIMESTAMP WITHOUT TIME ZONE instead of TIMESTAMP WITH TIME ZONE). -See [this comment to Ticket DBAL-22](http://www.doctrine-project.org/jira/browse/DBAL-22?focusedCommentId=13396&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_13396) -for more details as well as migration issues for PostgreSQL and Oracle. - -Both Postgres and Oracle will throw Exceptions during hydration of Objects with "DateTime" fields unless migration steps are taken! - -## Removed multi-dot/deep-path expressions in DQL - -The support for implicit joins in DQL through the multi-dot/Deep Path Expressions -was dropped. For example: - - SELECT u FROM User u WHERE u.group.name = ?1 - -See the "u.group.id" here is using multi dots (deep expression) to walk -through the graph of objects and properties. Internally the DQL parser -would rewrite these queries to: - - SELECT u FROM User u JOIN u.group g WHERE g.name = ?1 - -This explicit notation will be the only supported notation as of now. The internal -handling of multi-dots in the DQL Parser was very complex, error prone in edge cases -and required special treatment for several features we added. Additionally -it had edge cases that could not be solved without making the DQL Parser -even much more complex. For this reason we will drop the support for the -deep path expressions to increase maintainability and overall performance -of the DQL parsing process. This will benefit any DQL query being parsed, -even those not using deep path expressions. - -Note that the generated SQL of both notations is exactly the same! You -don't loose anything through this. - -## Default Allocation Size for Sequences - -The default allocation size for sequences has been changed from 10 to 1. This step was made -to not cause confusion with users and also because it is partly some kind of premature optimization. - -# Update from 2.0-BETA1 to 2.0-BETA2 - -There are no backwards incompatible changes in this release. - -# Upgrade from 2.0-ALPHA4 to 2.0-BETA1 - -## EntityRepository deprecates access to protected variables - -Instead of accessing protected variables for the EntityManager in -a custom EntityRepository it is now required to use the getter methods -for all the three instance variables: - -* `$this->_em` now accessible through `$this->getEntityManager()` -* `$this->_class` now accessible through `$this->getClassMetadata()` -* `$this->_entityName` now accessible through `$this->getEntityName()` - -Important: For Beta 2 the protected visibility of these three properties will be -changed to private! - -## Console migrated to Symfony Console - -The Doctrine CLI has been replaced by Symfony Console Configuration - -Instead of having to specify: - - [php] - $cliConfig = new CliConfiguration(); - $cliConfig->setAttribute('em', $entityManager); - -You now have to configure the script like: - - [php] - $helperSet = new \Symfony\Components\Console\Helper\HelperSet(array( - 'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()), - 'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) - )); - -## Console: No need for Mapping Paths anymore - -In previous versions you had to specify the --from and --from-path options -to show where your mapping paths are from the console. However this information -is already known from the Mapping Driver configuration, so the requirement -for this options were dropped. - -Instead for each console command all the entities are loaded and to -restrict the operation to one or more sub-groups you can use the --filter flag. - -## AnnotationDriver is not a default mapping driver anymore - -In conjunction with the recent changes to Console we realized that the -annotations driver being a default metadata driver lead to lots of glue -code in the console components to detect where entities lie and how to load -them for batch updates like SchemaTool and other commands. However the -annotations driver being a default driver does not really help that much -anyways. - -Therefore we decided to break backwards compatibility in this issue and drop -the support for Annotations as Default Driver and require our users to -specify the driver explicitly (which allows us to ask for the path to all -entities). - -If you are using the annotations metadata driver as default driver, you -have to add the following lines to your bootstrap code: - - $driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Entities")); - $config->setMetadataDriverImpl($driverImpl); - -You have to specify the path to your entities as either string of a single -path or array of multiple paths -to your entities. This information will be used by all console commands to -access all entities. - -Xml and Yaml Drivers work as before! - - -## New inversedBy attribute - -It is now *mandatory* that the owning side of a bidirectional association specifies the -'inversedBy' attribute that points to the name of the field on the inverse side that completes -the association. Example: - - [php] - // BEFORE (ALPHA4 AND EARLIER) - class User - { - //... - /** @OneToOne(targetEntity="Address", mappedBy="user") */ - private $address; - //... - } - class Address - { - //... - /** @OneToOne(targetEntity="User") */ - private $user; - //... - } - - // SINCE BETA1 - // User class DOES NOT CHANGE - class Address - { - //... - /** @OneToOne(targetEntity="User", inversedBy="address") */ - private $user; - //... - } - -Thus, the inversedBy attribute is the counterpart to the mappedBy attribute. This change -was necessary to enable some simplifications and further performance improvements. We -apologize for the inconvenience. - -## Default Property for Field Mappings - -The "default" option for database column defaults has been removed. If desired, database column defaults can -be implemented by using the columnDefinition attribute of the @Column annotation (or the appropriate XML and YAML equivalents). -Prefer PHP default values, if possible. - -## Selecting Partial Objects - -Querying for partial objects now has a new syntax. The old syntax to query for partial objects -now has a different meaning. This is best illustrated by an example. If you previously -had a DQL query like this: - - [sql] - SELECT u.id, u.name FROM User u - -Since BETA1, simple state field path expressions in the select clause are used to select -object fields as plain scalar values (something that was not possible before). -To achieve the same result as previously (that is, a partial object with only id and name populated) -you need to use the following, explicit syntax: - - [sql] - SELECT PARTIAL u.{id,name} FROM User u - -## XML Mapping Driver - -The 'inheritance-type' attribute changed to take last bit of ClassMetadata constant names, i.e. -NONE, SINGLE_TABLE, INHERITANCE_TYPE_JOINED - -## YAML Mapping Driver - -The way to specify lifecycle callbacks in YAML Mapping driver was changed to allow for multiple callbacks -per event. The Old syntax ways: - - [yaml] - lifecycleCallbacks: - doStuffOnPrePersist: prePersist - doStuffOnPostPersist: postPersist - -The new syntax is: - - [yaml] - lifecycleCallbacks: - prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ] - postPersist: [ doStuffOnPostPersist ] - -## PreUpdate Event Listeners - -Event Listeners listening to the 'preUpdate' event can only affect the primitive values of entity changesets -by using the API on the `PreUpdateEventArgs` instance passed to the preUpdate listener method. Any changes -to the state of the entitys properties won't affect the database UPDATE statement anymore. This gives drastic -performance benefits for the preUpdate event. - -## Collection API - -The Collection interface in the Common package has been updated with some missing methods -that were present only on the default implementation, ArrayCollection. Custom collection -implementations need to be updated to adhere to the updated interface. - -# Upgrade from 2.0-ALPHA3 to 2.0-ALPHA4 - -## CLI Controller changes - -CLI main object changed its name and namespace. Renamed from Doctrine\ORM\Tools\Cli to Doctrine\Common\Cli\CliController. -Doctrine\Common\Cli\CliController now only deals with namespaces. Ready to go, Core, Dbal and Orm are available and you can subscribe new tasks by retrieving the namespace and including new task. Example: - - [php] - $cli->getNamespace('Core')->addTask('my-example', '\MyProject\Tools\Cli\Tasks\MyExampleTask'); - - -## CLI Tasks documentation - -Tasks have implemented a new way to build documentation. Although it is still possible to define the help manually by extending the basicHelp and extendedHelp, they are now optional. -With new required method AbstractTask::buildDocumentation, its implementation defines the TaskDocumentation instance (accessible through AbstractTask::getDocumentation()), basicHelp and extendedHelp are now not necessary to be implemented. - -## Changes in Method Signatures - - * A bunch of Methods on both Doctrine\DBAL\Platforms\AbstractPlatform and Doctrine\DBAL\Schema\AbstractSchemaManager - have changed quite significantly by adopting the new Schema instance objects. - -## Renamed Methods - - * Doctrine\ORM\AbstractQuery::setExpireResultCache() -> expireResultCache() - * Doctrine\ORM\Query::setExpireQueryCache() -> expireQueryCache() - -## SchemaTool Changes - - * "doctrine schema-tool --drop" now always drops the complete database instead of - only those tables defined by the current database model. The previous method had - problems when foreign keys of orphaned tables pointed to tables that were scheduled - for deletion. - * Use "doctrine schema-tool --update" to get a save incremental update for your - database schema without deleting any unused tables, sequences or foreign keys. - * Use "doctrine schema-tool --complete-update" to do a full incremental update of - your schema. -# Upgrade from 2.0-ALPHA2 to 2.0-ALPHA3 - -This section details the changes made to Doctrine 2.0-ALPHA3 to make it easier for you -to upgrade your projects to use this version. - -## CLI Changes - -The $args variable used in the cli-config.php for configuring the Doctrine CLI has been renamed to $globalArguments. - -## Proxy class changes - -You are now required to make supply some minimalist configuration with regards to proxy objects. That involves 2 new configuration options. First, the directory where generated proxy classes should be placed needs to be specified. Secondly, you need to configure the namespace used for proxy classes. The following snippet shows an example: - - [php] - // step 1: configure directory for proxy classes - // $config instanceof Doctrine\ORM\Configuration - $config->setProxyDir('/path/to/myproject/lib/MyProject/Generated/Proxies'); - $config->setProxyNamespace('MyProject\Generated\Proxies'); - -Note that proxy classes behave exactly like any other classes when it comes to class loading. Therefore you need to make sure the proxy classes can be loaded by some class loader. If you place the generated proxy classes in a namespace and directory under your projects class files, like in the example above, it would be sufficient to register the MyProject namespace on a class loader. Since the proxy classes are contained in that namespace and adhere to the standards for class loading, no additional work is required. -Generating the proxy classes into a namespace within your class library is the recommended setup. - -Entities with initialized proxy objects can now be serialized and unserialized properly from within the same application. - -For more details refer to the Configuration section of the manual. - -## Removed allowPartialObjects configuration option - -The allowPartialObjects configuration option together with the `Configuration#getAllowPartialObjects` and `Configuration#setAllowPartialObjects` methods have been removed. -The new behavior is as if the option were set to FALSE all the time, basically disallowing partial objects globally. However, you can still use the `Query::HINT_FORCE_PARTIAL_LOAD` query hint to force a query to return partial objects for optimization purposes. - -## Renamed Methods - -* Doctrine\ORM\Configuration#getCacheDir() to getProxyDir() -* Doctrine\ORM\Configuration#setCacheDir($dir) to setProxyDir($dir) diff --git a/vendor/doctrine/orm/bin/doctrine b/vendor/doctrine/orm/bin/doctrine deleted file mode 100755 index c359ca7..0000000 --- a/vendor/doctrine/orm/bin/doctrine +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env php -. - */ - -require_once 'Doctrine/Common/ClassLoader.php'; - -$classLoader = new \Doctrine\Common\ClassLoader('Doctrine'); -$classLoader->register(); - -$classLoader = new \Doctrine\Common\ClassLoader('Symfony'); -$classLoader->register(); - -$configFile = getcwd() . DIRECTORY_SEPARATOR . 'cli-config.php'; - -$helperSet = null; -if (file_exists($configFile)) { - if ( ! is_readable($configFile)) { - trigger_error( - 'Configuration file [' . $configFile . '] does not have read permission.', E_USER_ERROR - ); - } - - require $configFile; - - foreach ($GLOBALS as $helperSetCandidate) { - if ($helperSetCandidate instanceof \Symfony\Component\Console\Helper\HelperSet) { - $helperSet = $helperSetCandidate; - break; - } - } -} - -$helperSet = ($helperSet) ?: new \Symfony\Component\Console\Helper\HelperSet(); - -\Doctrine\ORM\Tools\Console\ConsoleRunner::run($helperSet); diff --git a/vendor/doctrine/orm/bin/doctrine.bat b/vendor/doctrine/orm/bin/doctrine.bat deleted file mode 100644 index a9e8cee..0000000 --- a/vendor/doctrine/orm/bin/doctrine.bat +++ /dev/null @@ -1,9 +0,0 @@ -@echo off - -if "%PHPBIN%" == "" set PHPBIN=@php_bin@ -if not exist "%PHPBIN%" if "%PHP_PEAR_PHP_BIN%" neq "" goto USE_PEAR_PATH -GOTO RUN -:USE_PEAR_PATH -set PHPBIN=%PHP_PEAR_PHP_BIN% -:RUN -"%PHPBIN%" "@bin_dir@\doctrine" %* diff --git a/vendor/doctrine/orm/bin/doctrine.php b/vendor/doctrine/orm/bin/doctrine.php deleted file mode 100644 index 81d4e7b..0000000 --- a/vendor/doctrine/orm/bin/doctrine.php +++ /dev/null @@ -1,69 +0,0 @@ -. - */ - -use Symfony\Component\Console\Helper\HelperSet; -use Doctrine\ORM\Tools\Console\ConsoleRunner; - -$autoloadFiles = [ - __DIR__ . '/../vendor/autoload.php', - __DIR__ . '/../../../autoload.php' -]; - -foreach ($autoloadFiles as $autoloadFile) { - if (file_exists($autoloadFile)) { - require_once $autoloadFile; - break; - } -} - -$directories = [getcwd(), getcwd() . DIRECTORY_SEPARATOR . 'config']; - -$configFile = null; -foreach ($directories as $directory) { - $configFile = $directory . DIRECTORY_SEPARATOR . 'cli-config.php'; - - if (file_exists($configFile)) { - break; - } -} - -if ( ! file_exists($configFile)) { - ConsoleRunner::printCliConfigTemplate(); - exit(1); -} - -if ( ! is_readable($configFile)) { - echo 'Configuration file [' . $configFile . '] does not have read permission.' . "\n"; - exit(1); -} - -$commands = []; - -$helperSet = require $configFile; - -if ( ! ($helperSet instanceof HelperSet)) { - foreach ($GLOBALS as $helperSetCandidate) { - if ($helperSetCandidate instanceof HelperSet) { - $helperSet = $helperSetCandidate; - break; - } - } -} - -ConsoleRunner::run($helperSet, $commands); diff --git a/vendor/doctrine/orm/composer.json b/vendor/doctrine/orm/composer.json deleted file mode 100644 index c74e9cf..0000000 --- a/vendor/doctrine/orm/composer.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "name": "doctrine/orm", - "type": "library", - "description": "Object-Relational-Mapper for PHP", - "keywords": ["orm", "database"], - "homepage": "https://www.doctrine-project.org/projects/orm.html", - "license": "MIT", - "authors": [ - {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, - {"name": "Roman Borschel", "email": "roman@code-factory.org"}, - {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, - {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, - {"name": "Marco Pivetta", "email": "ocramius@gmail.com"} - ], - "config": { - "sort-packages": true - }, - "require": { - "php": "^7.1", - "ext-pdo": "*", - "doctrine/annotations": "^1.8", - "doctrine/cache": "^1.9.1", - "doctrine/collections": "^1.5", - "doctrine/common": "^2.11", - "doctrine/dbal": "^2.9.3", - "doctrine/event-manager": "^1.1", - "doctrine/instantiator": "^1.3", - "doctrine/persistence": "^1.2", - "symfony/console": "^3.0|^4.0|^5.0" - }, - "require-dev": { - "doctrine/coding-standard": "^5.0", - "phpunit/phpunit": "^7.5", - "symfony/yaml": "^3.4|^4.0|^5.0" - }, - "suggest": { - "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" - }, - "autoload": { - "psr-4": { "Doctrine\\ORM\\": "lib/Doctrine/ORM" } - }, - "autoload-dev": { - "psr-4": { - "Doctrine\\Tests\\": "tests/Doctrine/Tests", - "Doctrine\\Performance\\": "tests/Doctrine/Performance" - } - }, - "bin": ["bin/doctrine"], - "extra": { - "branch-alias": { - "dev-master": "2.7.x-dev" - } - }, - "archive": { - "exclude": ["!vendor", "tests", "*phpunit.xml", ".travis.yml", "build.xml", "build.properties", "composer.phar", "vendor/satooshi", "lib/vendor", "*.swp"] - } -} diff --git a/vendor/doctrine/orm/composer.lock b/vendor/doctrine/orm/composer.lock deleted file mode 100644 index fc220d2..0000000 --- a/vendor/doctrine/orm/composer.lock +++ /dev/null @@ -1,2744 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "4e24e01f599825550170acce0dda0b49", - "packages": [ - { - "name": "doctrine/annotations", - "version": "v1.8.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/904dca4eb10715b92569fbcd79e201d5c349b6bc", - "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc", - "shasum": "" - }, - "require": { - "doctrine/lexer": "1.*", - "php": "^7.1" - }, - "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "^7.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "time": "2019-10-01T18:55:10+00:00" - }, - { - "name": "doctrine/cache", - "version": "1.9.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "89a5c76c39c292f7798f964ab3c836c3f8192a55" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/89a5c76c39c292f7798f964ab3c836c3f8192a55", - "reference": "89a5c76c39c292f7798f964ab3c836c3f8192a55", - "shasum": "" - }, - "require": { - "php": "~7.1" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "alcaeus/mongo-php-adapter": "^1.1", - "doctrine/coding-standard": "^6.0", - "mongodb/mongodb": "^1.1", - "phpunit/phpunit": "^7.0", - "predis/predis": "~1.0" - }, - "suggest": { - "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", - "homepage": "https://www.doctrine-project.org/projects/cache.html", - "keywords": [ - "abstraction", - "apcu", - "cache", - "caching", - "couchdb", - "memcached", - "php", - "redis", - "riak", - "xcache" - ], - "time": "2019-11-15T14:31:57+00:00" - }, - { - "name": "doctrine/collections", - "version": "v1.5.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/collections.git", - "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/a01ee38fcd999f34d9bfbcee59dbda5105449cbf", - "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "~0.1@dev", - "phpunit/phpunit": "^5.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Collections\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Collections Abstraction library", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "array", - "collections", - "iterator" - ], - "time": "2017-07-22T10:37:32+00:00" - }, - { - "name": "doctrine/common", - "version": "v2.11.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/common.git", - "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", - "reference": "b8ca1dcf6b0dc8a2af7a09baac8d0c48345df4ff", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.0", - "doctrine/cache": "^1.0", - "doctrine/collections": "^1.0", - "doctrine/event-manager": "^1.0", - "doctrine/inflector": "^1.0", - "doctrine/lexer": "^1.0", - "doctrine/persistence": "^1.1", - "doctrine/reflection": "^1.0", - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "^1.0", - "phpstan/phpstan": "^0.11", - "phpstan/phpstan-phpunit": "^0.11", - "phpunit/phpunit": "^7.0", - "squizlabs/php_codesniffer": "^3.0", - "symfony/phpunit-bridge": "^4.0.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.11.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, persistence interfaces, proxies, event system and much more.", - "homepage": "https://www.doctrine-project.org/projects/common.html", - "keywords": [ - "common", - "doctrine", - "php" - ], - "time": "2019-09-10T10:10:14+00:00" - }, - { - "name": "doctrine/dbal", - "version": "v2.9.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/dbal.git", - "reference": "7345cd59edfa2036eb0fa4264b77ae2576842035" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/7345cd59edfa2036eb0fa4264b77ae2576842035", - "reference": "7345cd59edfa2036eb0fa4264b77ae2576842035", - "shasum": "" - }, - "require": { - "doctrine/cache": "^1.0", - "doctrine/event-manager": "^1.0", - "ext-pdo": "*", - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "^5.0", - "jetbrains/phpstorm-stubs": "^2018.1.2", - "phpstan/phpstan": "^0.10.1", - "phpunit/phpunit": "^7.4", - "symfony/console": "^2.0.5|^3.0|^4.0", - "symfony/phpunit-bridge": "^3.4.5|^4.0.5" - }, - "suggest": { - "symfony/console": "For helpful console commands such as SQL execution and import of files." - }, - "bin": [ - "bin/doctrine-dbal" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.9.x-dev", - "dev-develop": "3.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\DBAL\\": "lib/Doctrine/DBAL" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - } - ], - "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", - "homepage": "https://www.doctrine-project.org/projects/dbal.html", - "keywords": [ - "abstraction", - "database", - "dbal", - "mysql", - "persistence", - "pgsql", - "php", - "queryobject" - ], - "time": "2019-11-02T22:19:34+00:00" - }, - { - "name": "doctrine/event-manager", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/event-manager.git", - "reference": "629572819973f13486371cb611386eb17851e85c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/629572819973f13486371cb611386eb17851e85c", - "reference": "629572819973f13486371cb611386eb17851e85c", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "conflict": { - "doctrine/common": "<2.9@dev" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", - "homepage": "https://www.doctrine-project.org/projects/event-manager.html", - "keywords": [ - "event", - "event dispatcher", - "event manager", - "event system", - "events" - ], - "time": "2019-11-10T09:48:07+00:00" - }, - { - "name": "doctrine/inflector", - "version": "1.3.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/ec3a55242203ffa6a4b27c58176da97ff0a7aec1", - "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^6.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Common String Manipulations with regard to casing and singular/plural rules.", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "inflection", - "pluralize", - "singularize", - "string" - ], - "time": "2019-10-30T19:59:35+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.13", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-shim": "^0.11", - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "time": "2019-10-21T16:45:58+00:00" - }, - { - "name": "doctrine/lexer", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "^4.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "time": "2019-06-08T11:03:04+00:00" - }, - { - "name": "doctrine/persistence", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/persistence.git", - "reference": "43526ae63312942e5316100bb3ed589ba1aba491" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/43526ae63312942e5316100bb3ed589ba1aba491", - "reference": "43526ae63312942e5316100bb3ed589ba1aba491", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.0", - "doctrine/cache": "^1.0", - "doctrine/collections": "^1.0", - "doctrine/event-manager": "^1.0", - "doctrine/reflection": "^1.0", - "php": "^7.1" - }, - "conflict": { - "doctrine/common": "<2.10@dev" - }, - "require-dev": { - "doctrine/coding-standard": "^5.0", - "phpstan/phpstan": "^0.8", - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", - "homepage": "https://doctrine-project.org/projects/persistence.html", - "keywords": [ - "mapper", - "object", - "odm", - "orm", - "persistence" - ], - "time": "2019-04-23T12:39:21+00:00" - }, - { - "name": "doctrine/reflection", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/reflection.git", - "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/reflection/zipball/02538d3f95e88eb397a5f86274deb2c6175c2ab6", - "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.0", - "ext-tokenizer": "*", - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "^4.0", - "doctrine/common": "^2.8", - "phpstan/phpstan": "^0.9.2", - "phpstan/phpstan-phpunit": "^0.9.4", - "phpunit/phpunit": "^7.0", - "squizlabs/php_codesniffer": "^3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "Doctrine Reflection component", - "homepage": "https://www.doctrine-project.org/projects/reflection.html", - "keywords": [ - "reflection" - ], - "time": "2018-06-14T14:45:07+00:00" - }, - { - "name": "psr/log", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", - "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2019-11-01T11:05:21+00:00" - }, - { - "name": "symfony/console", - "version": "v3.4.35", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "17b154f932c5874cdbda6d05796b6490eec9f9f7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/17b154f932c5874cdbda6d05796b6490eec9f9f7", - "reference": "17b154f932c5874cdbda6d05796b6490eec9f9f7", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/debug": "~2.8|~3.0|~4.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/process": "<3.3" - }, - "provide": { - "psr/log-implementation": "1.0" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.3|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.3|~4.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2019-11-13T07:12:39+00:00" - }, - { - "name": "symfony/debug", - "version": "v3.4.35", - "source": { - "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "f72e33fdb1170b326e72c3157f0cd456351dd086" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/f72e33fdb1170b326e72c3157f0cd456351dd086", - "reference": "f72e33fdb1170b326e72c3157f0cd456351dd086", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" - }, - "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Debug Component", - "homepage": "https://symfony.com", - "time": "2019-10-24T15:33:53+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.12.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", - "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.12-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "time": "2019-08-06T08:03:45+00:00" - } - ], - "packages-dev": [ - { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v0.5.0", - "source": { - "type": "git", - "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", - "reference": "e749410375ff6fb7a040a68878c656c2e610b132" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/e749410375ff6fb7a040a68878c656c2e610b132", - "reference": "e749410375ff6fb7a040a68878c656c2e610b132", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0", - "php": "^5.3|^7", - "squizlabs/php_codesniffer": "^2|^3" - }, - "require-dev": { - "composer/composer": "*", - "phpcompatibility/php-compatibility": "^9.0", - "sensiolabs/security-checker": "^4.1.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "time": "2018-10-26T13:21:45+00:00" - }, - { - "name": "doctrine/coding-standard", - "version": "5.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/coding-standard.git", - "reference": "9017efe98b47329cbd895d43f596747c8ef27307" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/coding-standard/zipball/9017efe98b47329cbd895d43f596747c8ef27307", - "reference": "9017efe98b47329cbd895d43f596747c8ef27307", - "shasum": "" - }, - "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5.0", - "php": "^7.1", - "slevomat/coding-standard": "^4.8.0", - "squizlabs/php_codesniffer": "^3.3.2" - }, - "type": "phpcodesniffer-standard", - "extra": { - "branch-alias": { - "dev-master": "5.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Sniffs\\": "lib/Doctrine/Sniffs" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Steve Müller", - "email": "st.mueller@dzh-online.de" - } - ], - "description": "The Doctrine Coding Standard is a set of PHPCS rules applied to all Doctrine projects.", - "homepage": "https://www.doctrine-project.org/projects/coding-standard.html", - "keywords": [ - "checks", - "code", - "coding", - "cs", - "doctrine", - "rules", - "sniffer", - "sniffs", - "standard", - "style" - ], - "time": "2019-01-31T13:22:30+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.9.3", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea", - "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "replace": { - "myclabs/deep-copy": "self.version" - }, - "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, - "files": [ - "src/DeepCopy/deep_copy.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "time": "2019-08-09T12:45:53+00:00" - }, - { - "name": "phar-io/manifest", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", - "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "phar-io/version": "^2.0", - "php": "^5.6 || ^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2018-07-08T19:23:20+00:00" - }, - { - "name": "phar-io/version", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", - "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "time": "2018-07-08T19:19:57+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", - "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "~6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "time": "2018-08-07T13:53:10+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "4.3.2", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/b83ff7cfcfee7827e1e78b637a5904fe6a96698e", - "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e", - "shasum": "" - }, - "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", - "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", - "webmozart/assert": "^1.0" - }, - "require-dev": { - "doctrine/instantiator": "^1.0.5", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-09-12T14:27:41+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", - "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", - "shasum": "" - }, - "require": { - "php": "^7.1", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "^7.1", - "mockery/mockery": "~1", - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2019-08-22T18:11:29+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "1.9.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203", - "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" - }, - "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" - } - ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2019-10-03T11:07:50+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "6.1.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-xmlwriter": "*", - "php": "^7.1", - "phpunit/php-file-iterator": "^2.0", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.0", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.1 || ^4.0", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "suggest": { - "ext-xdebug": "^2.6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2018-10-31T16:06:48+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "050bedf145a257b1ff02746c31894800e5122946" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", - "reference": "050bedf145a257b1ff02746c31894800e5122946", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2018-09-13T20:33:42+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2015-06-21T13:50:34+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "2.1.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2019-06-07T04:22:29+00:00" - }, - { - "name": "phpunit/php-token-stream", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff", - "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2019-09-17T06:23:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "7.5.17", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "4c92a15296e58191a4cd74cff3b34fc8e374174a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/4c92a15296e58191a4cd74cff3b34fc8e374174a", - "reference": "4c92a15296e58191a4cd74cff3b34fc8e374174a", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.1", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "myclabs/deep-copy": "^1.7", - "phar-io/manifest": "^1.0.2", - "phar-io/version": "^2.0", - "php": "^7.1", - "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^6.0.7", - "phpunit/php-file-iterator": "^2.0.1", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1", - "sebastian/comparator": "^3.0", - "sebastian/diff": "^3.0", - "sebastian/environment": "^4.0", - "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^2.0", - "sebastian/version": "^2.0.1" - }, - "conflict": { - "phpunit/phpunit-mock-objects": "*" - }, - "require-dev": { - "ext-pdo": "*" - }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*", - "phpunit/php-invoker": "^2.0" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "7.5-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2019-10-28T10:37:36+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" - }, - { - "name": "sebastian/comparator", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", - "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", - "shasum": "" - }, - "require": { - "php": "^7.1", - "sebastian/diff": "^3.0", - "sebastian/exporter": "^3.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2018-07-12T15:12:46+00:00" - }, - { - "name": "sebastian/diff", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.0", - "symfony/process": "^2 || ^3.3 || ^4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "time": "2019-02-04T06:01:07+00:00" - }, - { - "name": "sebastian/environment", - "version": "4.2.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404", - "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.5" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "time": "2019-05-05T09:05:15+00:00" - }, - { - "name": "sebastian/exporter", - "version": "3.1.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", - "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", - "shasum": "" - }, - "require": { - "php": "^7.0", - "sebastian/recursion-context": "^3.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "time": "2019-09-14T09:02:43+00:00" - }, - { - "name": "sebastian/global-state", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "time": "2017-04-27T15:39:26+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "shasum": "" - }, - "require": { - "php": "^7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-08-03T12:35:26+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "1.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "773f97c67f28de00d397be301821b06708fca0be" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", - "reference": "773f97c67f28de00d397be301821b06708fca0be", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29T09:07:27+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "shasum": "" - }, - "require": { - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03T06:23:57+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", - "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2018-10-04T04:07:39+00:00" - }, - { - "name": "sebastian/version", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" - }, - { - "name": "slevomat/coding-standard", - "version": "4.8.7", - "source": { - "type": "git", - "url": "https://github.com/slevomat/coding-standard.git", - "reference": "bff96313d8c7c2ba57a4edb13c1c141df8988c58" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/bff96313d8c7c2ba57a4edb13c1c141df8988c58", - "reference": "bff96313d8c7c2ba57a4edb13c1c141df8988c58", - "shasum": "" - }, - "require": { - "php": "^7.1", - "squizlabs/php_codesniffer": "^3.4.0" - }, - "require-dev": { - "jakub-onderka/php-parallel-lint": "1.0.0", - "phing/phing": "2.16.1", - "phpstan/phpstan": "0.9.2", - "phpstan/phpstan-phpunit": "0.9.4", - "phpstan/phpstan-strict-rules": "0.9", - "phpunit/phpunit": "7.5.1" - }, - "type": "phpcodesniffer-standard", - "autoload": { - "psr-4": { - "SlevomatCodingStandard\\": "SlevomatCodingStandard" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", - "time": "2019-01-03T13:15:50+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.5.2", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "65b12cdeaaa6cd276d4c3033a95b9b88b12701e7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/65b12cdeaaa6cd276d4c3033a95b9b88b12701e7", - "reference": "65b12cdeaaa6cd276d4c3033a95b9b88b12701e7", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards" - ], - "time": "2019-10-28T04:36:32+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.12.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "550ebaac289296ce228a706d0867afc34687e3f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", - "reference": "550ebaac289296ce228a706d0867afc34687e3f4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.12-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "time": "2019-08-06T08:03:45+00:00" - }, - { - "name": "symfony/yaml", - "version": "v3.4.35", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "dab657db15207879217fc81df4f875947bf68804" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/dab657db15207879217fc81df4f875947bf68804", - "reference": "dab657db15207879217fc81df4f875947bf68804", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/console": "<3.4" - }, - "require-dev": { - "symfony/console": "~3.4|~4.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2019-10-24T15:33:53+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.1.3", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", - "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "role": "Developer", - "email": "arne@blankerts.de" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "time": "2019-06-13T22:48:21+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.5.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4", - "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0", - "symfony/polyfill-ctype": "^1.8" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "time": "2019-08-24T08:43:50+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^7.1", - "ext-pdo": "*" - }, - "platform-dev": [] -} diff --git a/vendor/doctrine/orm/docs/LICENSE.md b/vendor/doctrine/orm/docs/LICENSE.md deleted file mode 100644 index 1bf8659..0000000 --- a/vendor/doctrine/orm/docs/LICENSE.md +++ /dev/null @@ -1,363 +0,0 @@ -The Doctrine2 documentation is licensed under [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_US) - -Creative Commons Legal Code - -Attribution-NonCommercial-ShareAlike 3.0 Unported - - CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE - LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN - ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS - INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES - REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR - DAMAGES RESULTING FROM ITS USE. - -License - -THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE -COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY -COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS -AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. - -BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE -TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY -BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS -CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND -CONDITIONS. - -1. Definitions - - a. "Adaptation" means a work based upon the Work, or upon the Work and - other pre-existing works, such as a translation, adaptation, - derivative work, arrangement of music or other alterations of a - literary or artistic work, or phonogram or performance and includes - cinematographic adaptations or any other form in which the Work may be - recast, transformed, or adapted including in any form recognizably - derived from the original, except that a work that constitutes a - Collection will not be considered an Adaptation for the purpose of - this License. For the avoidance of doubt, where the Work is a musical - work, performance or phonogram, the synchronization of the Work in - timed-relation with a moving image ("synching") will be considered an - Adaptation for the purpose of this License. - b. "Collection" means a collection of literary or artistic works, such as - encyclopedias and anthologies, or performances, phonograms or - broadcasts, or other works or subject matter other than works listed - in Section 1(g) below, which, by reason of the selection and - arrangement of their contents, constitute intellectual creations, in - which the Work is included in its entirety in unmodified form along - with one or more other contributions, each constituting separate and - independent works in themselves, which together are assembled into a - collective whole. A work that constitutes a Collection will not be - considered an Adaptation (as defined above) for the purposes of this - License. - c. "Distribute" means to make available to the public the original and - copies of the Work or Adaptation, as appropriate, through sale or - other transfer of ownership. - d. "License Elements" means the following high-level license attributes - as selected by Licensor and indicated in the title of this License: - Attribution, Noncommercial, ShareAlike. - e. "Licensor" means the individual, individuals, entity or entities that - offer(s) the Work under the terms of this License. - f. "Original Author" means, in the case of a literary or artistic work, - the individual, individuals, entity or entities who created the Work - or if no individual or entity can be identified, the publisher; and in - addition (i) in the case of a performance the actors, singers, - musicians, dancers, and other persons who act, sing, deliver, declaim, - play in, interpret or otherwise perform literary or artistic works or - expressions of folklore; (ii) in the case of a phonogram the producer - being the person or legal entity who first fixes the sounds of a - performance or other sounds; and, (iii) in the case of broadcasts, the - organization that transmits the broadcast. - g. "Work" means the literary and/or artistic work offered under the terms - of this License including without limitation any production in the - literary, scientific and artistic domain, whatever may be the mode or - form of its expression including digital form, such as a book, - pamphlet and other writing; a lecture, address, sermon or other work - of the same nature; a dramatic or dramatico-musical work; a - choreographic work or entertainment in dumb show; a musical - composition with or without words; a cinematographic work to which are - assimilated works expressed by a process analogous to cinematography; - a work of drawing, painting, architecture, sculpture, engraving or - lithography; a photographic work to which are assimilated works - expressed by a process analogous to photography; a work of applied - art; an illustration, map, plan, sketch or three-dimensional work - relative to geography, topography, architecture or science; a - performance; a broadcast; a phonogram; a compilation of data to the - extent it is protected as a copyrightable work; or a work performed by - a variety or circus performer to the extent it is not otherwise - considered a literary or artistic work. - h. "You" means an individual or entity exercising rights under this - License who has not previously violated the terms of this License with - respect to the Work, or who has received express permission from the - Licensor to exercise rights under this License despite a previous - violation. - i. "Publicly Perform" means to perform public recitations of the Work and - to communicate to the public those public recitations, by any means or - process, including by wire or wireless means or public digital - performances; to make available to the public Works in such a way that - members of the public may access these Works from a place and at a - place individually chosen by them; to perform the Work to the public - by any means or process and the communication to the public of the - performances of the Work, including by public digital performance; to - broadcast and rebroadcast the Work by any means including signs, - sounds or images. - j. "Reproduce" means to make copies of the Work by any means including - without limitation by sound or visual recordings and the right of - fixation and reproducing fixations of the Work, including storage of a - protected performance or phonogram in digital form or other electronic - medium. - -2. Fair Dealing Rights. Nothing in this License is intended to reduce, -limit, or restrict any uses free from copyright or rights arising from -limitations or exceptions that are provided for in connection with the -copyright protection under copyright law or other applicable laws. - -3. License Grant. Subject to the terms and conditions of this License, -Licensor hereby grants You a worldwide, royalty-free, non-exclusive, -perpetual (for the duration of the applicable copyright) license to -exercise the rights in the Work as stated below: - - a. to Reproduce the Work, to incorporate the Work into one or more - Collections, and to Reproduce the Work as incorporated in the - Collections; - b. to create and Reproduce Adaptations provided that any such Adaptation, - including any translation in any medium, takes reasonable steps to - clearly label, demarcate or otherwise identify that changes were made - to the original Work. For example, a translation could be marked "The - original work was translated from English to Spanish," or a - modification could indicate "The original work has been modified."; - c. to Distribute and Publicly Perform the Work including as incorporated - in Collections; and, - d. to Distribute and Publicly Perform Adaptations. - -The above rights may be exercised in all media and formats whether now -known or hereafter devised. The above rights include the right to make -such modifications as are technically necessary to exercise the rights in -other media and formats. Subject to Section 8(f), all rights not expressly -granted by Licensor are hereby reserved, including but not limited to the -rights described in Section 4(e). - -4. Restrictions. The license granted in Section 3 above is expressly made -subject to and limited by the following restrictions: - - a. You may Distribute or Publicly Perform the Work only under the terms - of this License. You must include a copy of, or the Uniform Resource - Identifier (URI) for, this License with every copy of the Work You - Distribute or Publicly Perform. You may not offer or impose any terms - on the Work that restrict the terms of this License or the ability of - the recipient of the Work to exercise the rights granted to that - recipient under the terms of the License. You may not sublicense the - Work. You must keep intact all notices that refer to this License and - to the disclaimer of warranties with every copy of the Work You - Distribute or Publicly Perform. When You Distribute or Publicly - Perform the Work, You may not impose any effective technological - measures on the Work that restrict the ability of a recipient of the - Work from You to exercise the rights granted to that recipient under - the terms of the License. This Section 4(a) applies to the Work as - incorporated in a Collection, but this does not require the Collection - apart from the Work itself to be made subject to the terms of this - License. If You create a Collection, upon notice from any Licensor You - must, to the extent practicable, remove from the Collection any credit - as required by Section 4(d), as requested. If You create an - Adaptation, upon notice from any Licensor You must, to the extent - practicable, remove from the Adaptation any credit as required by - Section 4(d), as requested. - b. You may Distribute or Publicly Perform an Adaptation only under: (i) - the terms of this License; (ii) a later version of this License with - the same License Elements as this License; (iii) a Creative Commons - jurisdiction license (either this or a later license version) that - contains the same License Elements as this License (e.g., - Attribution-NonCommercial-ShareAlike 3.0 US) ("Applicable License"). - You must include a copy of, or the URI, for Applicable License with - every copy of each Adaptation You Distribute or Publicly Perform. You - may not offer or impose any terms on the Adaptation that restrict the - terms of the Applicable License or the ability of the recipient of the - Adaptation to exercise the rights granted to that recipient under the - terms of the Applicable License. You must keep intact all notices that - refer to the Applicable License and to the disclaimer of warranties - with every copy of the Work as included in the Adaptation You - Distribute or Publicly Perform. When You Distribute or Publicly - Perform the Adaptation, You may not impose any effective technological - measures on the Adaptation that restrict the ability of a recipient of - the Adaptation from You to exercise the rights granted to that - recipient under the terms of the Applicable License. This Section 4(b) - applies to the Adaptation as incorporated in a Collection, but this - does not require the Collection apart from the Adaptation itself to be - made subject to the terms of the Applicable License. - c. You may not exercise any of the rights granted to You in Section 3 - above in any manner that is primarily intended for or directed toward - commercial advantage or private monetary compensation. The exchange of - the Work for other copyrighted works by means of digital file-sharing - or otherwise shall not be considered to be intended for or directed - toward commercial advantage or private monetary compensation, provided - there is no payment of any monetary compensation in con-nection with - the exchange of copyrighted works. - d. If You Distribute, or Publicly Perform the Work or any Adaptations or - Collections, You must, unless a request has been made pursuant to - Section 4(a), keep intact all copyright notices for the Work and - provide, reasonable to the medium or means You are utilizing: (i) the - name of the Original Author (or pseudonym, if applicable) if supplied, - and/or if the Original Author and/or Licensor designate another party - or parties (e.g., a sponsor institute, publishing entity, journal) for - attribution ("Attribution Parties") in Licensor's copyright notice, - terms of service or by other reasonable means, the name of such party - or parties; (ii) the title of the Work if supplied; (iii) to the - extent reasonably practicable, the URI, if any, that Licensor - specifies to be associated with the Work, unless such URI does not - refer to the copyright notice or licensing information for the Work; - and, (iv) consistent with Section 3(b), in the case of an Adaptation, - a credit identifying the use of the Work in the Adaptation (e.g., - "French translation of the Work by Original Author," or "Screenplay - based on original Work by Original Author"). The credit required by - this Section 4(d) may be implemented in any reasonable manner; - provided, however, that in the case of a Adaptation or Collection, at - a minimum such credit will appear, if a credit for all contributing - authors of the Adaptation or Collection appears, then as part of these - credits and in a manner at least as prominent as the credits for the - other contributing authors. For the avoidance of doubt, You may only - use the credit required by this Section for the purpose of attribution - in the manner set out above and, by exercising Your rights under this - License, You may not implicitly or explicitly assert or imply any - connection with, sponsorship or endorsement by the Original Author, - Licensor and/or Attribution Parties, as appropriate, of You or Your - use of the Work, without the separate, express prior written - permission of the Original Author, Licensor and/or Attribution - Parties. - e. For the avoidance of doubt: - - i. Non-waivable Compulsory License Schemes. In those jurisdictions in - which the right to collect royalties through any statutory or - compulsory licensing scheme cannot be waived, the Licensor - reserves the exclusive right to collect such royalties for any - exercise by You of the rights granted under this License; - ii. Waivable Compulsory License Schemes. In those jurisdictions in - which the right to collect royalties through any statutory or - compulsory licensing scheme can be waived, the Licensor reserves - the exclusive right to collect such royalties for any exercise by - You of the rights granted under this License if Your exercise of - such rights is for a purpose or use which is otherwise than - noncommercial as permitted under Section 4(c) and otherwise waives - the right to collect royalties through any statutory or compulsory - licensing scheme; and, - iii. Voluntary License Schemes. The Licensor reserves the right to - collect royalties, whether individually or, in the event that the - Licensor is a member of a collecting society that administers - voluntary licensing schemes, via that society, from any exercise - by You of the rights granted under this License that is for a - purpose or use which is otherwise than noncommercial as permitted - under Section 4(c). - f. Except as otherwise agreed in writing by the Licensor or as may be - otherwise permitted by applicable law, if You Reproduce, Distribute or - Publicly Perform the Work either by itself or as part of any - Adaptations or Collections, You must not distort, mutilate, modify or - take other derogatory action in relation to the Work which would be - prejudicial to the Original Author's honor or reputation. Licensor - agrees that in those jurisdictions (e.g. Japan), in which any exercise - of the right granted in Section 3(b) of this License (the right to - make Adaptations) would be deemed to be a distortion, mutilation, - modification or other derogatory action prejudicial to the Original - Author's honor and reputation, the Licensor will waive or not assert, - as appropriate, this Section, to the fullest extent permitted by the - applicable national law, to enable You to reasonably exercise Your - right under Section 3(b) of this License (right to make Adaptations) - but not otherwise. - -5. Representations, Warranties and Disclaimer - -UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING AND TO THE -FULLEST EXTENT PERMITTED BY APPLICABLE LAW, LICENSOR OFFERS THE WORK AS-IS -AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE -WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT -LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, -ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT -DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED -WARRANTIES, SO THIS EXCLUSION MAY NOT APPLY TO YOU. - -6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE -LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR -ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES -ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS -BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -7. Termination - - a. This License and the rights granted hereunder will terminate - automatically upon any breach by You of the terms of this License. - Individuals or entities who have received Adaptations or Collections - from You under this License, however, will not have their licenses - terminated provided such individuals or entities remain in full - compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will - survive any termination of this License. - b. Subject to the above terms and conditions, the license granted here is - perpetual (for the duration of the applicable copyright in the Work). - Notwithstanding the above, Licensor reserves the right to release the - Work under different license terms or to stop distributing the Work at - any time; provided, however that any such election will not serve to - withdraw this License (or any other license that has been, or is - required to be, granted under the terms of this License), and this - License will continue in full force and effect unless terminated as - stated above. - -8. Miscellaneous - - a. Each time You Distribute or Publicly Perform the Work or a Collection, - the Licensor offers to the recipient a license to the Work on the same - terms and conditions as the license granted to You under this License. - b. Each time You Distribute or Publicly Perform an Adaptation, Licensor - offers to the recipient a license to the original Work on the same - terms and conditions as the license granted to You under this License. - c. If any provision of this License is invalid or unenforceable under - applicable law, it shall not affect the validity or enforceability of - the remainder of the terms of this License, and without further action - by the parties to this agreement, such provision shall be reformed to - the minimum extent necessary to make such provision valid and - enforceable. - d. No term or provision of this License shall be deemed waived and no - breach consented to unless such waiver or consent shall be in writing - and signed by the party to be charged with such waiver or consent. - e. This License constitutes the entire agreement between the parties with - respect to the Work licensed here. There are no understandings, - agreements or representations with respect to the Work not specified - here. Licensor shall not be bound by any additional provisions that - may appear in any communication from You. This License may not be - modified without the mutual written agreement of the Licensor and You. - f. The rights granted under, and the subject matter referenced, in this - License were drafted utilizing the terminology of the Berne Convention - for the Protection of Literary and Artistic Works (as amended on - September 28, 1979), the Rome Convention of 1961, the WIPO Copyright - Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 - and the Universal Copyright Convention (as revised on July 24, 1971). - These rights and subject matter take effect in the relevant - jurisdiction in which the License terms are sought to be enforced - according to the corresponding provisions of the implementation of - those treaty provisions in the applicable national law. If the - standard suite of rights granted under applicable copyright law - includes additional rights not granted under this License, such - additional rights are deemed to be included in the License; this - License is not intended to restrict the license of any rights under - applicable law. - - -Creative Commons Notice - - Creative Commons is not a party to this License, and makes no warranty - whatsoever in connection with the Work. Creative Commons will not be - liable to You or any party on any legal theory for any damages - whatsoever, including without limitation any general, special, - incidental or consequential damages arising in connection to this - license. Notwithstanding the foregoing two (2) sentences, if Creative - Commons has expressly identified itself as the Licensor hereunder, it - shall have all rights and obligations of Licensor. - - Except for the limited purpose of indicating to the public that the - Work is licensed under the CCPL, Creative Commons does not authorize - the use by either party of the trademark "Creative Commons" or any - related trademark or logo of Creative Commons without the prior - written consent of Creative Commons. Any permitted use will be in - compliance with Creative Commons' then-current trademark usage - guidelines, as may be published on its website or otherwise made - available upon request from time to time. For the avoidance of doubt, - this trademark restriction does not form part of this License. - - Creative Commons may be contacted at http://creativecommons.org/. - diff --git a/vendor/doctrine/orm/docs/README.md b/vendor/doctrine/orm/docs/README.md deleted file mode 100644 index 4a7ca34..0000000 --- a/vendor/doctrine/orm/docs/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Doctrine ORM Documentation - -## How to Generate: -Using Ubuntu 14.04 LTS: - -1. Run ./bin/install-dependencies.sh -2. Run ./bin/generate-docs.sh - -It will generate the documentation into the build directory of the checkout. - - -## Theme issues - -If you get a "Theme error", check if the `en/_theme` subdirectory is empty, -in which case you will need to run: - -1. git submodule init -2. git submodule update diff --git a/vendor/doctrine/orm/docs/bin/generate-docs.sh b/vendor/doctrine/orm/docs/bin/generate-docs.sh deleted file mode 100755 index 7d06d2a..0000000 --- a/vendor/doctrine/orm/docs/bin/generate-docs.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -EXECPATH=`dirname $0` -cd $EXECPATH -cd .. - -rm build -Rf -sphinx-build en build - -sphinx-build -b latex en build/pdf -rubber --into build/pdf --pdf build/pdf/Doctrine2ORM.tex \ No newline at end of file diff --git a/vendor/doctrine/orm/docs/bin/install-dependencies.sh b/vendor/doctrine/orm/docs/bin/install-dependencies.sh deleted file mode 100644 index 9ee43bd..0000000 --- a/vendor/doctrine/orm/docs/bin/install-dependencies.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -sudo apt-get update && sudo apt-get install -y python2.7 python-sphinx python-pygments \ No newline at end of file diff --git a/vendor/doctrine/orm/docs/en/Makefile b/vendor/doctrine/orm/docs/en/Makefile deleted file mode 100644 index a6f6fce..0000000 --- a/vendor/doctrine/orm/docs/en/Makefile +++ /dev/null @@ -1,89 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Doctrine2ORM.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Doctrine2ORM.qhc" - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ - "run these through (pdf)latex." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/vendor/doctrine/orm/docs/en/_exts/configurationblock.py b/vendor/doctrine/orm/docs/en/_exts/configurationblock.py deleted file mode 100644 index 36ca61f..0000000 --- a/vendor/doctrine/orm/docs/en/_exts/configurationblock.py +++ /dev/null @@ -1,93 +0,0 @@ -#Copyright (c) 2010 Fabien Potencier -# -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is furnished -#to do so, subject to the following conditions: -# -#The above copyright notice and this permission notice shall be included in all -#copies or substantial portions of the Software. -# -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -from docutils.parsers.rst import Directive, directives -from docutils import nodes -from string import upper - -class configurationblock(nodes.General, nodes.Element): - pass - -class ConfigurationBlock(Directive): - has_content = True - required_arguments = 0 - optional_arguments = 0 - final_argument_whitespace = True - option_spec = {} - formats = { - 'html': 'HTML', - 'xml': 'XML', - 'php': 'PHP', - 'yaml': 'YAML', - 'jinja': 'Twig', - 'html+jinja': 'Twig', - 'jinja+html': 'Twig', - 'php+html': 'PHP', - 'html+php': 'PHP', - 'ini': 'INI', - 'php-annotations': 'Annotations', - } - - def run(self): - env = self.state.document.settings.env - - node = nodes.Element() - node.document = self.state.document - self.state.nested_parse(self.content, self.content_offset, node) - - entries = [] - for i, child in enumerate(node): - if isinstance(child, nodes.literal_block): - # add a title (the language name) before each block - #targetid = "configuration-block-%d" % env.new_serialno('configuration-block') - #targetnode = nodes.target('', '', ids=[targetid]) - #targetnode.append(child) - - innernode = nodes.emphasis(self.formats[child['language']], self.formats[child['language']]) - - para = nodes.paragraph() - para += [innernode, child] - - entry = nodes.list_item('') - entry.append(para) - entries.append(entry) - - resultnode = configurationblock() - resultnode.append(nodes.bullet_list('', *entries)) - - return [resultnode] - -def visit_configurationblock_html(self, node): - self.body.append(self.starttag(node, 'div', CLASS='configuration-block')) - -def depart_configurationblock_html(self, node): - self.body.append('\n') - -def visit_configurationblock_latex(self, node): - pass - -def depart_configurationblock_latex(self, node): - pass - -def setup(app): - app.add_node(configurationblock, - html=(visit_configurationblock_html, depart_configurationblock_html), - latex=(visit_configurationblock_latex, depart_configurationblock_latex)) - app.add_directive('configuration-block', ConfigurationBlock) diff --git a/vendor/doctrine/orm/docs/en/conf.py b/vendor/doctrine/orm/docs/en/conf.py deleted file mode 100644 index deafa6e..0000000 --- a/vendor/doctrine/orm/docs/en/conf.py +++ /dev/null @@ -1,201 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Doctrine 2 ORM documentation build configuration file, created by -# sphinx-quickstart on Fri Dec 3 18:10:24 2010. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os, datetime - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.append(os.path.abspath('_exts')) - -# -- General configuration ----------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['configurationblock'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'Doctrine 2 ORM' -copyright = u'2010-%y, Doctrine Project Team'.format(datetime.date.today) - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '2' -# The full version, including alpha/beta/rc tags. -release = '2' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -language = 'en' - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = ['_build'] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -show_authors = True - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -html_theme = 'doctrine' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ['_theme'] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_use_modindex = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'Doctrine2ORMdoc' - - -# -- Options for LaTeX output -------------------------------------------------- - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'Doctrine2ORM.tex', u'Doctrine 2 ORM Documentation', - u'Doctrine Project Team', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_use_modindex = True - -primary_domain = "dcorm" - -def linkcode_resolve(domain, info): - if domain == 'dcorm': - return 'http://' - return None diff --git a/vendor/doctrine/orm/docs/en/cookbook/advanced-field-value-conversion-using-custom-mapping-types.rst b/vendor/doctrine/orm/docs/en/cookbook/advanced-field-value-conversion-using-custom-mapping-types.rst deleted file mode 100644 index f735d99..0000000 --- a/vendor/doctrine/orm/docs/en/cookbook/advanced-field-value-conversion-using-custom-mapping-types.rst +++ /dev/null @@ -1,256 +0,0 @@ -Advanced field value conversion using custom mapping types -========================================================== - -.. sectionauthor:: Jan Sorgalla - -When creating entities, you sometimes have the need to transform field values -before they are saved to the database. In Doctrine you can use Custom Mapping -Types to solve this (see: :ref:`reference-basic-mapping-custom-mapping-types`). - -There are several ways to achieve this: converting the value inside the Type -class, converting the value on the database-level or a combination of both. - -This article describes the third way by implementing the MySQL specific column -type `Point `_. - -The ``Point`` type is part of the `Spatial extension `_ -of MySQL and enables you to store a single location in a coordinate space by -using x and y coordinates. You can use the Point type to store a -longitude/latitude pair to represent a geographic location. - -The entity ----------- - -We create a simple entity with a field ``$point`` which holds a value object -``Point`` representing the latitude and longitude of the position. - -The entity class: - -.. code-block:: php - - point = $point; - } - - /** - * @return \Geo\ValueObject\Point - */ - public function getPoint() - { - return $this->point; - } - - /** - * @param string $address - */ - public function setAddress($address) - { - $this->address = $address; - } - - /** - * @return string - */ - public function getAddress() - { - return $this->address; - } - } - -We use the custom type ``point`` in the ``@Column`` docblock annotation of the -``$point`` field. We will create this custom mapping type in the next chapter. - -The point class: - -.. code-block:: php - - latitude = $latitude; - $this->longitude = $longitude; - } - - /** - * @return float - */ - public function getLatitude() - { - return $this->latitude; - } - - /** - * @return float - */ - public function getLongitude() - { - return $this->longitude; - } - } - -The mapping type ----------------- - -Now we're going to create the ``point`` type and implement all required methods. - -.. code-block:: php - - getLongitude(), $value->getLatitude()); - } - - return $value; - } - - public function canRequireSQLConversion() - { - return true; - } - - public function convertToPHPValueSQL($sqlExpr, AbstractPlatform $platform) - { - return sprintf('AsText(%s)', $sqlExpr); - } - - public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform) - { - return sprintf('PointFromText(%s)', $sqlExpr); - } - } - -We do a 2-step conversion here. In the first step, we convert the ``Point`` -object into a string representation before saving to the database (in the -``convertToDatabaseValue`` method) and back into an object after fetching the -value from the database (in the ``convertToPHPValue`` method). - -The format of the string representation format is called -`Well-known text (WKT) `_. -The advantage of this format is, that it is both human readable and parsable by MySQL. - -Internally, MySQL stores geometry values in a binary format that is not -identical to the WKT format. So, we need to let MySQL transform the WKT -representation into its internal format. - -This is where the ``convertToPHPValueSQL`` and ``convertToDatabaseValueSQL`` -methods come into play. - -This methods wrap a sql expression (the WKT representation of the Point) into -MySQL functions `ST_PointFromText `_ -and `ST_AsText `_ -which convert WKT strings to and from the internal format of MySQL. - -.. note:: - - When using DQL queries, the ``convertToPHPValueSQL`` and - ``convertToDatabaseValueSQL`` methods only apply to identification variables - and path expressions in SELECT clauses. Expressions in WHERE clauses are - **not** wrapped! - - If you want to use Point values in WHERE clauses, you have to implement a - :doc:`user defined function ` for - ``PointFromText``. - -Example usage -------------- - -.. code-block:: php - - getConnection()->getDatabasePlatform()->registerDoctrineTypeMapping('point', 'point'); - - // Store a Location object - use Geo\Entity\Location; - use Geo\ValueObject\Point; - - $location = new Location(); - - $location->setAddress('1600 Amphitheatre Parkway, Mountain View, CA'); - $location->setPoint(new Point(37.4220761, -122.0845187)); - - $em->persist($location); - $em->flush(); - $em->clear(); - - // Fetch the Location object - $query = $em->createQuery("SELECT l FROM Geo\Entity\Location l WHERE l.address = '1600 Amphitheatre Parkway, Mountain View, CA'"); - $location = $query->getSingleResult(); - - /* @var Geo\ValueObject\Point */ - $point = $location->getPoint(); diff --git a/vendor/doctrine/orm/docs/en/cookbook/aggregate-fields.rst b/vendor/doctrine/orm/docs/en/cookbook/aggregate-fields.rst deleted file mode 100644 index 7e5a89d..0000000 --- a/vendor/doctrine/orm/docs/en/cookbook/aggregate-fields.rst +++ /dev/null @@ -1,376 +0,0 @@ -Aggregate Fields -================ - -.. sectionauthor:: Benjamin Eberlei - -You will often come across the requirement to display aggregate -values of data that can be computed by using the MIN, MAX, COUNT or -SUM SQL functions. For any ORM this is a tricky issue -traditionally. Doctrine 2 offers several ways to get access to -these values and this article will describe all of them from -different perspectives. - -You will see that aggregate fields can become very explicit -features in your domain model and how this potentially complex -business rules can be easily tested. - -An example model ----------------- - -Say you want to model a bank account and all their entries. Entries -into the account can either be of positive or negative money -values. Each account has a credit limit and the account is never -allowed to have a balance below that value. - -For simplicity we live in a world were money is composed of -integers only. Also we omit the receiver/sender name, stated reason -for transfer and the execution date. These all would have to be -added on the ``Entry`` object. - -Our entities look like: - -.. code-block:: php - - no = $no; - $this->maxCredit = $maxCredit; - $this->entries = new \Doctrine\Common\Collections\ArrayCollection(); - } - } - - /** - * @Entity - */ - class Entry - { - /** @Id @GeneratedValue @Column(type="integer") */ - private $id; - - /** - * @ManyToOne(targetEntity="Account", inversedBy="entries") - */ - private $account; - - /** - * @Column(type="integer") - */ - private $amount; - - public function __construct($account, $amount) - { - $this->account = $account; - $this->amount = $amount; - // more stuff here, from/to whom, stated reason, execution date and such - } - - public function getAmount() - { - return $this->amount; - } - } - -Using DQL ---------- - -The Doctrine Query Language allows you to select for aggregate -values computed from fields of your Domain Model. You can select -the current balance of your account by calling: - -.. code-block:: php - - createQuery($dql) - ->setParameter(1, $myAccountId) - ->getSingleScalarResult(); - -The ``$em`` variable in this (and forthcoming) example holds the -Doctrine ``EntityManager``. We create a query for the SUM of all -amounts (negative amounts are withdraws) and retrieve them as a -single scalar result, essentially return only the first column of -the first row. - -This approach is simple and powerful, however it has a serious -drawback. We have to execute a specific query for the balance -whenever we need it. - -To implement a powerful domain model we would rather have access to -the balance from our ``Account`` entity during all times (even if -the Account was not persisted in the database before!). - -Also an additional requirement is the max credit per ``Account`` -rule. - -We cannot reliably enforce this rule in our ``Account`` entity with -the DQL retrieval of the balance. There are many different ways to -retrieve accounts. We cannot guarantee that we can execute the -aggregation query for all these use-cases, let alone that a -userland programmer checks this balance against newly added -entries. - -Using your Domain Model ------------------------ - -``Account`` and all the ``Entry`` instances are connected through a -collection, which means we can compute this value at runtime: - -.. code-block:: php - - entries as $entry) { - $balance += $entry->getAmount(); - } - return $balance; - } - } - -Now we can always call ``Account::getBalance()`` to access the -current account balance. - -To enforce the max credit rule we have to implement the "Aggregate -Root" pattern as described in Eric Evans book on Domain Driven -Design. Described with one sentence, an aggregate root controls the -instance creation, access and manipulation of its children. - -In our case we want to enforce that new entries can only added to -the ``Account`` by using a designated method. The ``Account`` is -the aggregate root of this relation. We can also enforce the -correctness of the bi-directional ``Account`` <-> ``Entry`` -relation with this method: - -.. code-block:: php - - assertAcceptEntryAllowed($amount); - - $e = new Entry($this, $amount); - $this->entries[] = $e; - return $e; - } - } - -Now look at the following test-code for our entities: - -.. code-block:: php - - assertEquals(0, $account->getBalance()); - - $account->addEntry(500); - $this->assertEquals(500, $account->getBalance()); - - $account->addEntry(-700); - $this->assertEquals(-200, $account->getBalance()); - } - - public function testExceedMaxLimit() - { - $account = new Account("123456", $maxCredit = 200); - - $this->setExpectedException("Exception"); - $account->addEntry(-1000); - } - } - -To enforce our rule we can now implement the assertion in -``Account::addEntry``: - -.. code-block:: php - - getBalance() + $amount; - $allowedMinimalBalance = ($this->maxCredit * -1); - if ($futureBalance < $allowedMinimalBalance) { - throw new Exception("Credit Limit exceeded, entry is not allowed!"); - } - } - } - -We haven't talked to the entity manager for persistence of our -account example before. You can call -``EntityManager::persist($account)`` and then -``EntityManager::flush()`` at any point to save the account to the -database. All the nested ``Entry`` objects are automatically -flushed to the database also. - -.. code-block:: php - - addEntry(500); - $account->addEntry(-200); - $em->persist($account); - $em->flush(); - -The current implementation has a considerable drawback. To get the -balance, we have to initialize the complete ``Account::$entries`` -collection, possibly a very large one. This can considerably hurt -the performance of your application. - -Using an Aggregate Field ------------------------- - -To overcome the previously mentioned issue (initializing the whole -entries collection) we want to add an aggregate field called -"balance" on the Account and adjust the code in -``Account::getBalance()`` and ``Account:addEntry()``: - -.. code-block:: php - - balance; - } - - public function addEntry($amount) - { - $this->assertAcceptEntryAllowed($amount); - - $e = new Entry($this, $amount); - $this->entries[] = $e; - $this->balance += $amount; - return $e; - } - } - -This is a very simple change, but all the tests still pass. Our -account entities return the correct balance. Now calling the -``Account::getBalance()`` method will not occur the overhead of -loading all entries anymore. Adding a new Entry to the -``Account::$entities`` will also not initialize the collection -internally. - -Adding a new entry is therefore very performant and explicitly -hooked into the domain model. It will only update the account with -the current balance and insert the new entry into the database. - -Tackling Race Conditions with Aggregate Fields ----------------------------------------------- - -Whenever you denormalize your database schema race-conditions can -potentially lead to inconsistent state. See this example: - -.. code-block:: php - - find('Bank\Entities\Account', $accId); - - // request 2 account - $account2 = $em->find('Bank\Entities\Account', $accId); - - $account1->addEntry(-200); - $account2->addEntry(-200); - - // now request 1 and 2 both flush the changes. - -The aggregate field ``Account::$balance`` is now -200, however the -SUM over all entries amounts yields -400. A violation of our max -credit rule. - -You can use both optimistic or pessimistic locking to safe-guard -your aggregate fields against this kind of race-conditions. Reading -Eric Evans DDD carefully he mentions that the "Aggregate Root" -(Account in our example) needs a locking mechanism. - -Optimistic locking is as easy as adding a version column: - -.. code-block:: php - - find('Bank\Entities\Account', $accId, LockMode::PESSIMISTIC_READ); - -Keeping Updates and Deletes in Sync ------------------------------------ - -The example shown in this article does not allow changes to the -value in ``Entry``, which considerably simplifies the effort to -keep ``Account::$balance`` in sync. If your use-case allows fields -to be updated or related entities to be removed you have to -encapsulate this logic in your "Aggregate Root" entity and adjust -the aggregate field accordingly. - -Conclusion ----------- - -This article described how to obtain aggregate values using DQL or -your domain model. It showed how you can easily add an aggregate -field that offers serious performance benefits over iterating all -the related objects that make up an aggregate value. Finally I -showed how you can ensure that your aggregate fields do not get out -of sync due to race-conditions and concurrent access. - - diff --git a/vendor/doctrine/orm/docs/en/cookbook/custom-mapping-types.rst b/vendor/doctrine/orm/docs/en/cookbook/custom-mapping-types.rst deleted file mode 100644 index d9e3856..0000000 --- a/vendor/doctrine/orm/docs/en/cookbook/custom-mapping-types.rst +++ /dev/null @@ -1,101 +0,0 @@ -Custom Mapping Types -==================== - -Doctrine allows you to create new mapping types. This can come in -handy when you're missing a specific mapping type or when you want -to replace the existing implementation of a mapping type. - -In order to create a new mapping type you need to subclass -``Doctrine\DBAL\Types\Type`` and implement/override the methods as -you wish. Here is an example skeleton of such a custom type class: - -.. code-block:: php - - getConnection(); - $conn->getDatabasePlatform()->registerDoctrineTypeMapping('db_mytype', 'mytype'); - -When registering the custom types in the configuration you specify a unique -name for the mapping type and map that to the corresponding fully qualified -class name. Now the new type can be used when mapping columns: - -.. code-block:: php - - - -This recipe will show you a simple example of how you can use -Doctrine 2 to persist an implementation of the -`Decorator Pattern `_ - -Component ---------- - -The ``Component`` class needs to be persisted, so it's going to -be an ``Entity``. As the top of the inheritance hierarchy, it's going -to have to define the persistent inheritance. For this example, we -will use Single Table Inheritance, but Class Table Inheritance -would work as well. In the discriminator map, we will define two -concrete subclasses, ``ConcreteComponent`` and ``ConcreteDecorator``. - -.. code-block:: php - - id; - } - - /** - * Set name - * @param string $name - */ - public function setName($name) - { - $this->name = $name; - } - - /** - * Get name - * @return string $name - */ - public function getName() - { - return $this->name; - } - - } - -ConcreteComponent ------------------ - -The ``ConcreteComponent`` class is pretty simple and doesn't do much -more than extend the abstract ``Component`` class (only for the -purpose of keeping this example simple). - -.. code-block:: php - - setDecorates($c); - } - - /** - * (non-PHPdoc) - * @see Test.Component::getName() - */ - public function getName() - { - return 'Decorated ' . $this->getDecorates()->getName(); - } - - /** - * the component being decorated - * @return Component - */ - protected function getDecorates() - { - return $this->decorates; - } - - /** - * sets the component being decorated - * @param Component $c - */ - protected function setDecorates(Component $c) - { - $this->decorates = $c; - } - - } - -All operations on the ``Decorator`` (i.e. persist, remove, etc) will -cascade from the ``Decorator`` to the ``Component``. This means that -when we persist a ``Decorator``, Doctrine will take care of -persisting the chain of decorated objects for us. A ``Decorator`` can -be treated exactly as a ``Component`` when it comes time to -persisting it. - -The ``Decorator's`` constructor accepts an instance of a -``Component``, as defined by the ``Decorator`` pattern. The -setDecorates/getDecorates methods have been defined as protected to -hide the fact that a ``Decorator`` is decorating a ``Component`` and -keeps the ``Component`` interface and the ``Decorator`` interface -identical. - -To illustrate the intended result of the ``Decorator`` pattern, the -getName() method has been overridden to append a string to the -``Component's`` getName() method. - -ConcreteDecorator ------------------ - -The final class required to complete a simple implementation of the -Decorator pattern is the ``ConcreteDecorator``. In order to further -illustrate how the ``Decorator`` can alter data as it moves through -the chain of decoration, a new field, "special", has been added to -this class. The getName() has been overridden and appends the value -of the getSpecial() method to its return value. - -.. code-block:: php - - special = $special; - } - - /** - * Get special - * @return string $special - */ - public function getSpecial() - { - return $this->special; - } - - /** - * (non-PHPdoc) - * @see Test.Component::getName() - */ - public function getName() - { - return '[' . $this->getSpecial() - . '] ' . parent::getName(); - } - - } - -Examples --------- - -Here is an example of how to persist and retrieve your decorated -objects - -.. code-block:: php - - setName('Test Component 1'); - $em->persist($c); // assigned unique ID = 1 - - // create a new concrete decorator - $c = new ConcreteComponent(); - $c->setName('Test Component 2'); - - $d = new ConcreteDecorator($c); - $d->setSpecial('Really'); - $em->persist($d); - // assigns c as unique ID = 2, and d as unique ID = 3 - - $em->flush(); - - $c = $em->find('Test\Component', 1); - $d = $em->find('Test\Component', 3); - - echo get_class($c); - // prints: Test\Component\ConcreteComponent - - echo $c->getName(); - // prints: Test Component 1 - - echo get_class($d) - // prints: Test\Component\ConcreteDecorator - - echo $d->getName(); - // prints: [Really] Decorated Test Component 2 - diff --git a/vendor/doctrine/orm/docs/en/cookbook/dql-custom-walkers.rst b/vendor/doctrine/orm/docs/en/cookbook/dql-custom-walkers.rst deleted file mode 100644 index e840126..0000000 --- a/vendor/doctrine/orm/docs/en/cookbook/dql-custom-walkers.rst +++ /dev/null @@ -1,217 +0,0 @@ -Extending DQL in Doctrine 2: Custom AST Walkers -=============================================== - -.. sectionauthor:: Benjamin Eberlei - -The Doctrine Query Language (DQL) is a proprietary sql-dialect that -substitutes tables and columns for Entity names and their fields. -Using DQL you write a query against the database using your -entities. With the help of the metadata you can write very concise, -compact and powerful queries that are then translated into SQL by -the Doctrine ORM. - -In Doctrine 1 the DQL language was not implemented using a real -parser. This made modifications of the DQL by the user impossible. -Doctrine 2 in contrast has a real parser for the DQL language, -which transforms the DQL statement into an -`Abstract Syntax Tree `_ -and generates the appropriate SQL statement for it. Since this -process is deterministic Doctrine heavily caches the SQL that is -generated from any given DQL query, which reduces the performance -overhead of the parsing process to zero. - -You can modify the Abstract syntax tree by hooking into DQL parsing -process by adding a Custom Tree Walker. A walker is an interface -that walks each node of the Abstract syntax tree, thereby -generating the SQL statement. - -There are two types of custom tree walkers that you can hook into -the DQL parser: - - -- An output walker. This one actually generates the SQL, and there - is only ever one of them. We implemented the default SqlWalker - implementation for it. -- A tree walker. There can be many tree walkers, they cannot - generate the sql, however they can modify the AST before its - rendered to sql. - -Now this is all awfully technical, so let me come to some use-cases -fast to keep you motivated. Using walker implementation you can for -example: - - -- Modify the AST to generate a Count Query to be used with a - paginator for any given DQL query. -- Modify the Output Walker to generate vendor-specific SQL - (instead of ANSI). -- Modify the AST to add additional where clauses for specific - entities (example ACL, country-specific content...) -- Modify the Output walker to pretty print the SQL for debugging - purposes. - -In this cookbook-entry I will show examples on the first two -points. There are probably much more use-cases. - -Generic count query for pagination ----------------------------------- - -Say you have a blog and posts all with one category and one author. -A query for the front-page or any archive page might look something -like: - -.. code-block:: sql - - SELECT p, c, a FROM BlogPost p JOIN p.category c JOIN p.author a WHERE ... - -Now in this query the blog post is the root entity, meaning its the -one that is hydrated directly from the query and returned as an -array of blog posts. In contrast the comment and author are loaded -for deeper use in the object tree. - -A pagination for this query would want to approximate the number of -posts that match the WHERE clause of this query to be able to -predict the number of pages to show to the user. A draft of the DQL -query for pagination would look like: - -.. code-block:: sql - - SELECT count(DISTINCT p.id) FROM BlogPost p JOIN p.category c JOIN p.author a WHERE ... - -Now you could go and write each of these queries by hand, or you -can use a tree walker to modify the AST for you. Lets see how the -API would look for this use-case: - -.. code-block:: php - - createQuery($dql); - $query->setFirstResult( ($pageNum-1) * 20)->setMaxResults(20); - - $totalResults = Paginate::count($query); - $results = $query->getResult(); - -The ``Paginate::count(Query $query)`` looks like: - -.. code-block:: php - - setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('DoctrineExtensions\Paginate\CountSqlWalker')); - $countQuery->setFirstResult(null)->setMaxResults(null); - - return $countQuery->getSingleScalarResult(); - } - } - -It clones the query, resets the limit clause first and max results -and registers the ``CountSqlWalker`` custom tree walker which -will modify the AST to execute a count query. The walkers -implementation is: - -.. code-block:: php - - _getQueryComponents() as $dqlAlias => $qComp) { - if ($qComp['parent'] === null && $qComp['nestingLevel'] == 0) { - $parent = $qComp; - $parentName = $dqlAlias; - break; - } - } - - $pathExpression = new PathExpression( - PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $parentName, - $parent['metadata']->getSingleIdentifierFieldName() - ); - $pathExpression->type = PathExpression::TYPE_STATE_FIELD; - - $AST->selectClause->selectExpressions = array( - new SelectExpression( - new AggregateExpression('count', $pathExpression, true), null - ) - ); - } - } - -This will delete any given select expressions and replace them with -a distinct count query for the root entities primary key. This will -only work if your entity has only one identifier field (composite -keys won't work). - -Modify the Output Walker to generate Vendor specific SQL --------------------------------------------------------- - -Most RMDBS have vendor-specific features for optimizing select -query execution plans. You can write your own output walker to -introduce certain keywords using the Query Hint API. A query hint -can be set via ``Query::setHint($name, $value)`` as shown in the -previous example with the ``HINT_CUSTOM_TREE_WALKERS`` query hint. - -We will implement a custom Output Walker that allows to specify the -SQL\_NO\_CACHE query hint. - -.. code-block:: php - - createQuery($dql); - $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'DoctrineExtensions\Query\MysqlWalker'); - $query->setHint("mysqlWalker.sqlNoCache", true); - $results = $query->getResult(); - -Our ``MysqlWalker`` will extend the default ``SqlWalker``. We will -modify the generation of the SELECT clause, adding the -SQL\_NO\_CACHE on those queries that need it: - -.. code-block:: php - - getQuery()->getHint('mysqlWalker.sqlNoCache') === true) { - if ($selectClause->isDistinct) { - $sql = str_replace('SELECT DISTINCT', 'SELECT DISTINCT SQL_NO_CACHE', $sql); - } else { - $sql = str_replace('SELECT', 'SELECT SQL_NO_CACHE', $sql); - } - } - - return $sql; - } - } - -Writing extensions to the Output Walker requires a very deep -understanding of the DQL Parser and Walkers, but may offer your -huge benefits with using vendor specific features. This would still -allow you write DQL queries instead of NativeQueries to make use of -vendor specific features. - diff --git a/vendor/doctrine/orm/docs/en/cookbook/dql-user-defined-functions.rst b/vendor/doctrine/orm/docs/en/cookbook/dql-user-defined-functions.rst deleted file mode 100644 index 5c9b3e5..0000000 --- a/vendor/doctrine/orm/docs/en/cookbook/dql-user-defined-functions.rst +++ /dev/null @@ -1,251 +0,0 @@ -DQL User Defined Functions -========================== - -.. sectionauthor:: Benjamin Eberlei - -By default DQL supports a limited subset of all the vendor-specific -SQL functions common between all the vendors. However in many cases -once you have decided on a specific database vendor, you will never -change it during the life of your project. This decision for a -specific vendor potentially allows you to make use of powerful SQL -features that are unique to the vendor. - -It is worth to mention that Doctrine 2 also allows you to handwrite -your SQL instead of extending the DQL parser. Extending DQL is sort of an -advanced extension point. You can map arbitrary SQL to your objects -and gain access to vendor specific functionalities using the -``EntityManager#createNativeQuery()`` API as described in -the :doc:`Native Query <../reference/native-sql>` chapter. - - -The DQL Parser has hooks to register functions that can then be -used in your DQL queries and transformed into SQL, allowing to -extend Doctrines Query capabilities to the vendors strength. This -post explains the User-Defined Functions API (UDF) of the Dql -Parser and shows some examples to give you some hints how you would -extend DQL. - -There are three types of functions in DQL, those that return a -numerical value, those that return a string and those that return a -Date. Your custom method has to be registered as either one of -those. The return type information is used by the DQL parser to -check possible syntax errors during the parsing process, for -example using a string function return value in a math expression. - -Registering your own DQL functions ----------------------------------- - -You can register your functions adding them to the ORM -configuration: - -.. code-block:: php - - addCustomStringFunction($name, $class); - $config->addCustomNumericFunction($name, $class); - $config->addCustomDatetimeFunction($name, $class); - - $em = EntityManager::create($dbParams, $config); - -The ``$name`` is the name the function will be referred to in the -DQL query. ``$class`` is a string of a class-name which has to -extend ``Doctrine\ORM\Query\Node\FunctionNode``. This is a class -that offers all the necessary API and methods to implement a UDF. - -Instead of providing the function class name, you can also provide -a callable that returns the function object: - -.. code-block:: php - - addCustomStringFunction($name, function () { - return new MyCustomFunction(); - }); - -In this post we will implement some MySql specific Date calculation -methods, which are quite handy in my opinion: - -Date Diff ---------- - -`Mysql's DateDiff function `_ -takes two dates as argument and calculates the difference in days -with ``date1-date2``. - -The DQL parser is a top-down recursive descent parser to generate -the Abstract-Syntax Tree (AST) and uses a TreeWalker approach to -generate the appropriate SQL from the AST. This makes reading the -Parser/TreeWalker code manageable in a finite amount of time. - -The ``FunctionNode`` class I referred to earlier requires you to -implement two methods, one for the parsing process (obviously) -called ``parse`` and one for the TreeWalker process called -``getSql()``. I show you the code for the DateDiff method and -discuss it step by step: - -.. code-block:: php - - match(Lexer::T_IDENTIFIER); // (2) - $parser->match(Lexer::T_OPEN_PARENTHESIS); // (3) - $this->firstDateExpression = $parser->ArithmeticPrimary(); // (4) - $parser->match(Lexer::T_COMMA); // (5) - $this->secondDateExpression = $parser->ArithmeticPrimary(); // (6) - $parser->match(Lexer::T_CLOSE_PARENTHESIS); // (3) - } - - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - return 'DATEDIFF(' . - $this->firstDateExpression->dispatch($sqlWalker) . ', ' . - $this->secondDateExpression->dispatch($sqlWalker) . - ')'; // (7) - } - } - -The Parsing process of the DATEDIFF function is going to find two -expressions the date1 and the date2 values, whose AST Node -representations will be saved in the variables of the DateDiff -FunctionNode instance at (1). - -The parse() method has to cut the function call "DATEDIFF" and its -argument into pieces. Since the parser detects the function using a -lookahead the T\_IDENTIFIER of the function name has to be taken -from the stack (2), followed by a detection of the arguments in -(4)-(6). The opening and closing parenthesis have to be detected -also. This happens during the Parsing process and leads to the -generation of a DateDiff FunctionNode somewhere in the AST of the -dql statement. - -The ``ArithmeticPrimary`` method call is the most common -denominator of valid EBNF tokens taken from the -`DQL EBNF grammar `_ -that matches our requirements for valid input into the DateDiff Dql -function. Picking the right tokens for your methods is a tricky -business, but the EBNF grammar is pretty helpful finding it, as is -looking at the Parser source code. - -Now in the TreeWalker process we have to pick up this node and -generate SQL from it, which apparently is quite easy looking at the -code in (7). Since we don't know which type of AST Node the first -and second Date expression are we are just dispatching them back to -the SQL Walker to generate SQL from and then wrap our DATEDIFF -function call around this output. - -Now registering this DateDiff FunctionNode with the ORM using: - -.. code-block:: php - - addCustomStringFunction('DATEDIFF', 'DoctrineExtensions\Query\MySql\DateDiff'); - -We can do fancy stuff like: - -.. code-block:: sql - - SELECT p FROM DoctrineExtensions\Query\BlogPost p WHERE DATEDIFF(CURRENT_TIME(), p.created) < 7 - -Date Add --------- - -Often useful it the ability to do some simple date calculations in -your DQL query using -`MySql's DATE_ADD function `_. - -I'll skip the blah and show the code for this function: - -.. code-block:: php - - match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->firstDateExpression = $parser->ArithmeticPrimary(); - - $parser->match(Lexer::T_COMMA); - $parser->match(Lexer::T_IDENTIFIER); - - $this->intervalExpression = $parser->ArithmeticPrimary(); - - $parser->match(Lexer::T_IDENTIFIER); - - /* @var $lexer Lexer */ - $lexer = $parser->getLexer(); - $this->unit = $lexer->token['value']; - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } - - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - return 'DATE_ADD(' . - $this->firstDateExpression->dispatch($sqlWalker) . ', INTERVAL ' . - $this->intervalExpression->dispatch($sqlWalker) . ' ' . $this->unit . - ')'; - } - } - -The only difference compared to the DATEDIFF here is, we -additionally need the ``Lexer`` to access the value of the -``T_IDENTIFIER`` token for the Date Interval unit, for example the -MONTH in: - -.. code-block:: sql - - SELECT p FROM DoctrineExtensions\Query\BlogPost p WHERE DATE_ADD(CURRENT_TIME(), INTERVAL 4 MONTH) > p.created - -The above method now only supports the specification using -``INTERVAL``, to also allow a real date in DATE\_ADD we need to add -some decision logic to the parsing process (makes up for a nice -exercise). - -Now as you see, the Parsing process doesn't catch all the possible -SQL errors, here we don't match for all the valid inputs for the -interval unit. However where necessary we rely on the database -vendors SQL parser to show us further errors in the parsing -process, for example if the Unit would not be one of the supported -values by MySql. - -Conclusion ----------- - -Now that you all know how you can implement vendor specific SQL -functionalities in DQL, we would be excited to see user extensions -that add vendor specific function packages, for example more math -functions, XML + GIS Support, Hashing functions and so on. - -For 2.0 we will come with the current set of functions, however for -a future version we will re-evaluate if we can abstract even more -vendor sql functions and extend the DQL languages scope. - -Code for this Extension to DQL and other Doctrine Extensions can be -found -`in the GitHub DoctrineExtensions repository `_. - - diff --git a/vendor/doctrine/orm/docs/en/cookbook/entities-in-session.rst b/vendor/doctrine/orm/docs/en/cookbook/entities-in-session.rst deleted file mode 100644 index 664cff5..0000000 --- a/vendor/doctrine/orm/docs/en/cookbook/entities-in-session.rst +++ /dev/null @@ -1,68 +0,0 @@ -Entities in the Session -======================= - -There are several use-cases to save entities in the session, for example: - -1. User object -2. Multi-step forms - -To achieve this with Doctrine you have to pay attention to some details to get -this working. - -Merging entity into an EntityManager ------------------------------------- - -In Doctrine an entity objects has to be "managed" by an EntityManager to be -updateable. Entities saved into the session are not managed in the next request -anymore. This means that you have to register these entities with an -EntityManager again if you want to change them or use them as part of -references between other entities. You can achieve this by calling -``EntityManager#merge()``. - -For a representative User object the code to get turn an instance from -the session into a managed Doctrine object looks like this: - -.. code-block:: php - - merge($user); - } - -.. note:: - - A frequent mistake is not to get the merged user object from the return - value of ``EntityManager#merge()``. The entity object passed to merge is - not necessarily the same object that is returned from the method. - -Serializing entity into the session ------------------------------------ - -Entities that are serialized into the session normally contain references to -other entities as well. Think of the user entity has a reference to his -articles, groups, photos or many other different entities. If you serialize -this object into the session then you don't want to serialize the related -entities as well. This is why you should call ``EntityManager#detach()`` on this -object or implement the __sleep() magic method on your entity. - -.. code-block:: php - - find("User", 1); - $em->detach($user); - $_SESSION['user'] = $user; - -.. note:: - - When you called detach on your objects they get "unmanaged" with that - entity manager. This means you cannot use them as part of write operations - during ``EntityManager#flush()`` anymore in this request. - diff --git a/vendor/doctrine/orm/docs/en/cookbook/implementing-arrayaccess-for-domain-objects.rst b/vendor/doctrine/orm/docs/en/cookbook/implementing-arrayaccess-for-domain-objects.rst deleted file mode 100644 index 4eb2b71..0000000 --- a/vendor/doctrine/orm/docs/en/cookbook/implementing-arrayaccess-for-domain-objects.rst +++ /dev/null @@ -1,112 +0,0 @@ -Implementing ArrayAccess for Domain Objects -=========================================== - -.. sectionauthor:: Roman Borschel (roman@code-factory.org) - -This recipe will show you how to implement ArrayAccess for your -domain objects in order to allow more uniform access, for example -in templates. In these examples we will implement ArrayAccess on a -`Layer Supertype `_ -for all our domain objects. - -Option 1 --------- - -In this implementation we will make use of PHPs highly dynamic -nature to dynamically access properties of a subtype in a supertype -at runtime. Note that this implementation has 2 main caveats: - - -- It will not work with private fields -- It will not go through any getters/setters - -.. code-block:: php - - $offset); - } - - public function offsetSet($offset, $value) { - $this->$offset = $value; - } - - public function offsetGet($offset) { - return $this->$offset; - } - - public function offsetUnset($offset) { - $this->$offset = null; - } - } - -Option 2 --------- - -In this implementation we will dynamically invoke getters/setters. -Again we use PHPs dynamic nature to invoke methods on a subtype -from a supertype at runtime. This implementation has the following -caveats: - - -- It relies on a naming convention -- The semantics of offsetExists can differ -- offsetUnset will not work with typehinted setters - -.. code-block:: php - - {"get$offset"}(); - return $value !== null; - } - - public function offsetSet($offset, $value) { - $this->{"set$offset"}($value); - } - - public function offsetGet($offset) { - return $this->{"get$offset"}(); - } - - public function offsetUnset($offset) { - $this->{"set$offset"}(null); - } - } - -Read-only ---------- - -You can slightly tweak option 1 or option 2 in order to make array -access read-only. This will also circumvent some of the caveats of -each option. Simply make offsetSet and offsetUnset throw an -exception (i.e. BadMethodCallException). - -.. code-block:: php - - `_ -for all our domain objects. - -Implementing NotifyPropertyChanged ----------------------------------- - -The NOTIFY policy is based on the assumption that the entities -notify interested listeners of changes to their properties. For -that purpose, a class that wants to use this policy needs to -implement the ``NotifyPropertyChanged`` interface from the -``Doctrine\Common`` namespace. - -.. code-block:: php - - listeners[] = $listener; - } - - /** Notifies listeners of a change. */ - protected function onPropertyChanged($propName, $oldValue, $newValue) { - if ($this->listeners) { - foreach ($this->listeners as $listener) { - $listener->propertyChanged($this, $propName, $oldValue, $newValue); - } - } - } - } - -Then, in each property setter of concrete, derived domain classes, -you need to invoke onPropertyChanged as follows to notify -listeners: - -.. code-block:: php - - data) { // check: is it actually modified? - $this->onPropertyChanged('data', $this->data, $data); - $this->data = $data; - } - } - } - -The check whether the new value is different from the old one is -not mandatory but recommended. That way you can avoid unnecessary -updates and also have full control over when you consider a -property changed. - - diff --git a/vendor/doctrine/orm/docs/en/cookbook/implementing-wakeup-or-clone.rst b/vendor/doctrine/orm/docs/en/cookbook/implementing-wakeup-or-clone.rst deleted file mode 100644 index 1ae1775..0000000 --- a/vendor/doctrine/orm/docs/en/cookbook/implementing-wakeup-or-clone.rst +++ /dev/null @@ -1,78 +0,0 @@ -Implementing Wakeup or Clone -============================ - -.. sectionauthor:: Roman Borschel (roman@code-factory.org) - -As explained in the -`restrictions for entity classes in the manual `_, -it is usually not allowed for an entity to implement ``__wakeup`` -or ``__clone``, because Doctrine makes special use of them. -However, it is quite easy to make use of these methods in a safe -way by guarding the custom wakeup or clone code with an entity -identity check, as demonstrated in the following sections. - -Safely implementing __wakeup ----------------------------- - -To safely implement ``__wakeup``, simply enclose your -implementation code in an identity check as follows: - -.. code-block:: php - - id) { - // ... Your code here as normal ... - } - // otherwise do nothing, do NOT throw an exception! - } - - //... - } - -Safely implementing __clone ---------------------------- - -Safely implementing ``__clone`` is pretty much the same: - -.. code-block:: php - - id) { - // ... Your code here as normal ... - } - // otherwise do nothing, do NOT throw an exception! - } - - //... - } - -Summary -------- - -As you have seen, it is quite easy to safely make use of -``__wakeup`` and ``__clone`` in your entities without adding any -really Doctrine-specific or Doctrine-dependant code. - -These implementations are possible and safe because when Doctrine -invokes these methods, the entities never have an identity (yet). -Furthermore, it is possibly a good idea to check for the identity -in your code anyway, since it's rarely the case that you want to -unserialize or clone an entity with no identity. - - diff --git a/vendor/doctrine/orm/docs/en/cookbook/mysql-enums.rst b/vendor/doctrine/orm/docs/en/cookbook/mysql-enums.rst deleted file mode 100644 index 1765ecc..0000000 --- a/vendor/doctrine/orm/docs/en/cookbook/mysql-enums.rst +++ /dev/null @@ -1,199 +0,0 @@ -Mysql Enums -=========== - -The type system of Doctrine 2 consists of flyweights, which means there is only -one instance of any given type. Additionally types do not contain state. Both -assumptions make it rather complicated to work with the Enum Type of MySQL that -is used quite a lot by developers. - -When using Enums with a non-tweaked Doctrine 2 application you will get -errors from the Schema-Tool commands due to the unknown database type "enum". -By default Doctrine does not map the MySQL enum type to a Doctrine type. -This is because Enums contain state (their allowed values) and Doctrine -types don't. - -This cookbook entry shows two possible solutions to work with MySQL enums. -But first a word of warning. The MySQL Enum type has considerable downsides: - -- Adding new values requires to rebuild the whole table, which can take hours - depending on the size. -- Enums are ordered in the way the values are specified, not in their "natural" order. -- Enums validation mechanism for allowed values is not necessarily good, - specifying invalid values leads to an empty enum for the default MySQL error - settings. You can easily replicate the "allow only some values" requirement - in your Doctrine entities. - -Solution 1: Mapping to Varchars -------------------------------- - -You can map ENUMs to varchars. You can register MySQL ENUMs to map to Doctrine -varchars. This way Doctrine always resolves ENUMs to Doctrine varchars. It -will even detect this match correctly when using SchemaTool update commands. - -.. code-block:: php - - getConnection(); - $conn->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string'); - -In this case you have to ensure that each varchar field that is an enum in the -database only gets passed the allowed values. You can easily enforce this in your -entities: - -.. code-block:: php - - status = $status; - } - } - -If you want to actively create enums through the Doctrine Schema-Tool by using -the **columnDefinition** attribute. - -.. code-block:: php - - values); - - return "ENUM(".implode(", ", $values).")"; - } - - public function convertToPHPValue($value, AbstractPlatform $platform) - { - return $value; - } - - public function convertToDatabaseValue($value, AbstractPlatform $platform) - { - if (!in_array($value, $this->values)) { - throw new \InvalidArgumentException("Invalid '".$this->name."' value."); - } - return $value; - } - - public function getName() - { - return $this->name; - } - - public function requiresSQLCommentHint(AbstractPlatform $platform) - { - return true; - } - } - -With this base class you can define an enum as easily as: - -.. code-block:: php - - addResolveTargetEntity('Acme\\InvoiceModule\\Model\\InvoiceSubjectInterface', 'Acme\\CustomerModule\\Entity\\Customer', array()); - - // Add the ResolveTargetEntityListener - $evm->addEventListener(Doctrine\ORM\Events::loadClassMetadata, $rtel); - - $em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config, $evm); - -Final Thoughts --------------- - -With the ``ResolveTargetEntityListener``, we are able to decouple our -bundles, keeping them usable by themselves, but still being able to -define relationships between different objects. By using this method, -I've found my bundles end up being easier to maintain independently. - - diff --git a/vendor/doctrine/orm/docs/en/cookbook/sql-table-prefixes.rst b/vendor/doctrine/orm/docs/en/cookbook/sql-table-prefixes.rst deleted file mode 100644 index 5ea5879..0000000 --- a/vendor/doctrine/orm/docs/en/cookbook/sql-table-prefixes.rst +++ /dev/null @@ -1,86 +0,0 @@ -SQL-Table Prefixes -================== - -This recipe is intended as an example of implementing a -loadClassMetadata listener to provide a Table Prefix option for -your application. The method used below is not a hack, but fully -integrates into the Doctrine system, all SQL generated will include -the appropriate table prefix. - -In most circumstances it is desirable to separate different -applications into individual databases, but in certain cases, it -may be beneficial to have a table prefix for your Entities to -separate them from other vendor products in the same database. - -Implementing the listener -------------------------- - -The listener in this example has been set up with the -DoctrineExtensions namespace. You create this file in your -library/DoctrineExtensions directory, but will need to set up -appropriate autoloaders. - -.. code-block:: php - - prefix = (string) $prefix; - } - - public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) - { - $classMetadata = $eventArgs->getClassMetadata(); - - if (!$classMetadata->isInheritanceTypeSingleTable() || $classMetadata->getName() === $classMetadata->rootEntityName) { - $classMetadata->setPrimaryTable([ - 'name' => $this->prefix . $classMetadata->getTableName() - ]); - } - - foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) { - if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY && $mapping['isOwningSide']) { - $mappedTableName = $mapping['joinTable']['name']; - $classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName; - } - } - } - - } - -Telling the EntityManager about our listener --------------------------------------------- - -A listener of this type must be set up before the EntityManager has -been initialised, otherwise an Entity might be created or cached -before the prefix has been set. - -.. note:: - - If you set this listener up, be aware that you will need - to clear your caches and drop then recreate your database schema. - - -.. code-block:: php - - addEventListener(\Doctrine\ORM\Events::loadClassMetadata, $tablePrefix); - - $em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config, $evm); - - diff --git a/vendor/doctrine/orm/docs/en/cookbook/strategy-cookbook-introduction.rst b/vendor/doctrine/orm/docs/en/cookbook/strategy-cookbook-introduction.rst deleted file mode 100644 index b434a9d..0000000 --- a/vendor/doctrine/orm/docs/en/cookbook/strategy-cookbook-introduction.rst +++ /dev/null @@ -1,254 +0,0 @@ -Strategy-Pattern -================ - -This recipe will give you a short introduction on how to design -similar entities without using expensive (i.e. slow) inheritance -but with not more than *the well-known strategy pattern* event -listeners - -Scenario / Problem ------------------- - -Given a Content-Management-System, we probably want to add / edit -some so-called "blocks" and "panels". What are they for? - - -- A block might be a registration form, some text content, a table - with information. A good example might also be a small calendar. -- A panel is by definition a block that can itself contain blocks. - A good example for a panel might be a sidebar box: You could easily - add a small calendar into it. - -So, in this scenario, when building your CMS, you will surely add -lots of blocks and panels to your pages and you will find yourself -highly uncomfortable because of the following: - - -- Every existing page needs to know about the panels it contains - - therefore, you'll have an association to your panels. But if you've - got several types of panels - what do you do? Add an association to - every panel-type? This wouldn't be flexible. You might be tempted - to add an AbstractPanelEntity and an AbstractBlockEntity that use - class inheritance. Your page could then only confer to the - AbstractPanelType and Doctrine 2 would do the rest for you, i.e. - load the right entities. But - you'll for sure have lots of panels - and blocks, and even worse, you'd have to edit the discriminator - map *manually* every time you or another developer implements a new - block / entity. This would tear down any effort of modular - programming. - -Therefore, we need something that's far more flexible. - -Solution --------- - -The solution itself is pretty easy. We will have one base class -that will be loaded via the page and that has specific behaviour - -a Block class might render the front-end and even the backend, for -example. Now, every block that you'll write might look different or -need different data - therefore, we'll offer an API to these -methods but internally, we use a strategy that exactly knows what -to do. - -First of all, we need to make sure that we have an interface that -contains every needed action. Such actions would be rendering the -front-end or the backend, solving dependencies (blocks that are -supposed to be placed in the sidebar could refuse to be placed in -the middle of your page, for example). - -Such an interface could look like this: - - -.. code-block:: php - - blockStrategy. Will not be persisted by Doctrine 2. - * - * @var BlockStrategyInterface - */ - protected $strategyInstance; - - /** - * Returns the strategy that is used for this blockitem. - * - * The strategy itself defines how this block can be rendered etc. - * - * @return string - */ - public function getStrategyClassName() { - return $this->strategyClassName; - } - - /** - * Returns the instantiated strategy - * - * @return BlockStrategyInterface - */ - public function getStrategyInstance() { - return $this->strategyInstance; - } - - /** - * Sets the strategy this block / panel should work as. Make sure that you've used - * this method before persisting the block! - * - * @param BlockStrategyInterface $strategy - */ - public function setStrategy(BlockStrategyInterface $strategy) { - $this->strategyInstance = $strategy; - $this->strategyClassName = get_class($strategy); - $strategy->setBlockEntity($this); - } - -Now, the important point is that $strategyClassName is a Doctrine 2 -field, i.e. Doctrine will persist this value. This is only the -class name of your strategy and not an instance! - -Finishing your strategy pattern, we hook into the Doctrine postLoad -event and check whether a block has been loaded. If so, you will -initialize it - i.e. get the strategies classname, create an -instance of it and set it via setStrategyBlock(). - -This might look like this: - -.. code-block:: php - - view = $view; - } - - public function getSubscribedEvents() { - return array(ORM\Events::postLoad); - } - - public function postLoad(ORM\Event\LifecycleEventArgs $args) { - $blockItem = $args->getEntity(); - - // Both blocks and panels are instances of Block\AbstractBlock - if ($blockItem instanceof Block\AbstractBlock) { - $strategy = $blockItem->getStrategyClassName(); - $strategyInstance = new $strategy(); - if (null !== $blockItem->getConfig()) { - $strategyInstance->setConfig($blockItem->getConfig()); - } - $strategyInstance->setView($this->view); - $blockItem->setStrategy($strategyInstance); - } - } - } - -In this example, even some variables are set - like a view object -or a specific configuration object. - - diff --git a/vendor/doctrine/orm/docs/en/cookbook/validation-of-entities.rst b/vendor/doctrine/orm/docs/en/cookbook/validation-of-entities.rst deleted file mode 100644 index dd10b8b..0000000 --- a/vendor/doctrine/orm/docs/en/cookbook/validation-of-entities.rst +++ /dev/null @@ -1,137 +0,0 @@ -Validation of Entities -====================== - -.. sectionauthor:: Benjamin Eberlei - -Doctrine 2 does not ship with any internal validators, the reason -being that we think all the frameworks out there already ship with -quite decent ones that can be integrated into your Domain easily. -What we offer are hooks to execute any kind of validation. - -.. note:: - - You don't need to validate your entities in the lifecycle - events. Its only one of many options. Of course you can also - perform validations in value setters or any other method of your - entities that are used in your code. - - -Entities can register lifecycle event methods with Doctrine that -are called on different occasions. For validation we would need to -hook into the events called before persisting and updating. Even -though we don't support validation out of the box, the -implementation is even simpler than in Doctrine 1 and you will get -the additional benefit of being able to re-use your validation in -any other part of your domain. - -Say we have an ``Order`` with several ``OrderLine`` instances. We -never want to allow any customer to order for a larger sum than he -is allowed to: - -.. code-block:: php - - customer->getOrderLimit(); - - $amount = 0; - foreach ($this->orderLines as $line) { - $amount += $line->getAmount(); - } - - if ($amount > $orderLimit) { - throw new CustomerOrderLimitExceededException(); - } - } - } - -Now this is some pretty important piece of business logic in your -code, enforcing it at any time is important so that customers with -a unknown reputation don't owe your business too much money. - -We can enforce this constraint in any of the metadata drivers. -First Annotations: - -.. code-block:: php - - - - - - - - - - -YAML needs some little change yet, to allow multiple lifecycle -events for one method, this will happen before Beta 1 though. - -Now validation is performed whenever you call -``EntityManager#persist($order)`` or when you call -``EntityManager#flush()`` and an order is about to be updated. Any -Exception that happens in the lifecycle callbacks will be caught by -the EntityManager and the current transaction is rolled back. - -Of course you can do any type of primitive checks, not null, -email-validation, string size, integer and date ranges in your -validation callbacks. - -.. code-block:: php - - plannedShipDate instanceof DateTime)) { - throw new ValidateException(); - } - - if ($this->plannedShipDate->format('U') < time()) { - throw new ValidateException(); - } - - if ($this->customer == null) { - throw new OrderRequiresCustomerException(); - } - } - } - -What is nice about lifecycle events is, you can also re-use the -methods at other places in your domain, for example in combination -with your form library. Additionally there is no limitation in the -number of methods you register on one particular event, i.e. you -can register multiple methods for validation in "PrePersist" or -"PreUpdate" or mix and share them in any combinations between those -two events. - -There is no limit to what you can and can't validate in -"PrePersist" and "PreUpdate" as long as you don't create new entity -instances. This was already discussed in the previous blog post on -the Versionable extension, which requires another type of event -called "onFlush". - -Further readings: :ref:`reference-events-lifecycle-events` diff --git a/vendor/doctrine/orm/docs/en/cookbook/working-with-datetime.rst b/vendor/doctrine/orm/docs/en/cookbook/working-with-datetime.rst deleted file mode 100644 index f599b83..0000000 --- a/vendor/doctrine/orm/docs/en/cookbook/working-with-datetime.rst +++ /dev/null @@ -1,197 +0,0 @@ -Working with DateTime Instances -=============================== - -There are many nitty gritty details when working with PHPs DateTime instances. You have to know their inner -workings pretty well not to make mistakes with date handling. This cookbook entry holds several -interesting pieces of information on how to work with PHP DateTime instances in Doctrine 2. - -DateTime changes are detected by Reference -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When calling ``EntityManager#flush()`` Doctrine computes the changesets of all the currently managed entities -and saves the differences to the database. In case of object properties (@Column(type="datetime") or @Column(type="object")) -these comparisons are always made **BY REFERENCE**. That means the following change will **NOT** be saved into the database: - -.. code-block:: php - - updated->modify("now"); - } - } - -The way to go would be: - -.. code-block:: php - - updated = new \DateTime("now"); - } - } - -Default Timezone Gotcha -~~~~~~~~~~~~~~~~~~~~~~~ - -By default Doctrine assumes that you are working with a default timezone. Each DateTime instance that -is created by Doctrine will be assigned the timezone that is currently the default, either through -the ``date.timezone`` ini setting or by calling ``date_default_timezone_set()``. - -This is very important to handle correctly if your application runs on different servers or is moved from one to another server -(with different timezone settings). You have to make sure that the timezone is the correct one -on all this systems. - -Handling different Timezones with the DateTime Type -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you first come across the requirement to save different timezones you may be still optimistic about how -to manage this mess, -however let me crush your expectations fast. There is not a single database out there (supported by Doctrine 2) -that supports timezones correctly. Correctly here means that you can cover all the use-cases that -can come up with timezones. If you don't believe me you should read up on `Storing DateTime -in Databases `_. - -The problem is simple. Not a single database vendor saves the timezone, only the differences to UTC. -However with frequent daylight saving and political timezone changes you can have a UTC offset that moves -in different offset directions depending on the real location. - -The solution for this dilemma is simple. Don't use timezones with DateTime and Doctrine 2. However there is a workaround -that even allows correct date-time handling with timezones: - -1. Always convert any DateTime instance to UTC. -2. Only set Timezones for displaying purposes -3. Save the Timezone in the Entity for persistence. - -Say we have an application for an international postal company and employees insert events regarding postal-package -around the world, in their current timezones. To determine the exact time an event occurred means to save both -the UTC time at the time of the booking and the timezone the event happened in. - -.. code-block:: php - - setTimezone(self::getUtc()); - } - - return parent::convertToDatabaseValue($value, $platform); - } - - public function convertToPHPValue($value, AbstractPlatform $platform) - { - if (null === $value || $value instanceof \DateTime) { - return $value; - } - - $converted = \DateTime::createFromFormat( - $platform->getDateTimeFormatString(), - $value, - self::getUtc() - ); - - if (! $converted) { - throw ConversionException::conversionFailedFormat( - $value, - $this->getName(), - $platform->getDateTimeFormatString() - ); - } - - return $converted; - } - - private static function getUtc(): \DateTimeZone - { - return self::$utc ?: self::$utc = new \DateTimeZone('UTC'); - } - } - -This database type makes sure that every DateTime instance is always saved in UTC, relative -to the current timezone that the passed DateTime instance has. - -To actually use this new type instead of the default ``datetime`` type, you need to run following -code before bootstrapping the ORM: - -.. code-block:: php - - localized = true; - $this->created = $createDate; - $this->timezone = $createDate->getTimeZone()->getName(); - } - - public function getCreated() - { - if (!$this->localized) { - $this->created->setTimeZone(new \DateTimeZone($this->timezone)); - } - return $this->created; - } - } - -This snippet makes use of the previously discussed "changeset by reference only" property of -objects. That means a new DateTime will only be used during updating if the reference -changes between retrieval and flush operation. This means we can easily go and modify -the instance by setting the previous local timezone. diff --git a/vendor/doctrine/orm/docs/en/index.rst b/vendor/doctrine/orm/docs/en/index.rst deleted file mode 100644 index 0cea054..0000000 --- a/vendor/doctrine/orm/docs/en/index.rst +++ /dev/null @@ -1,128 +0,0 @@ -Welcome to Doctrine 2 ORM's documentation! -========================================== - -The Doctrine documentation is comprised of tutorials, a reference section and -cookbook articles that explain different parts of the Object Relational mapper. - -Doctrine DBAL and Doctrine Common both have their own documentation. - -Getting Help ------------- - -If this documentation is not helping to answer questions you have about -Doctrine ORM don't panic. You can get help from different sources: - -- There is a :doc:`FAQ ` with answers to frequent questions. -- The `Doctrine Mailing List `_ -- Slack chat room `#orm `_ -- Report a bug on `GitHub `_. -- On `Twitter `_ with ``#doctrine2`` -- On `StackOverflow `_ - -If you need more structure over the different topics you can browse the :doc:`table -of contents `. - -Getting Started ---------------- - -* **Tutorial**: - :doc:`Getting Started with Doctrine ` - -* **Setup**: - :doc:`Installation & Configuration ` - -Mapping Objects onto a Database -------------------------------- - -* **Mapping**: - :doc:`Objects ` | - :doc:`Associations ` | - :doc:`Inheritance ` - -* **Drivers**: - :doc:`Docblock Annotations ` | - :doc:`XML ` | - :doc:`YAML ` | - :doc:`PHP ` - -Working with Objects --------------------- - -* **Basic Reference**: - :doc:`Entities ` | - :doc:`Associations ` | - :doc:`Events ` - -* **Query Reference**: - :doc:`DQL ` | - :doc:`QueryBuilder ` | - :doc:`Native SQL ` - -* **Internals**: - :doc:`Internals explained ` | - :doc:`Associations ` - -Advanced Topics ---------------- - -* :doc:`Architecture ` -* :doc:`Advanced Configuration ` -* :doc:`Limitations and known issues ` -* :doc:`Commandline Tools ` -* :doc:`Transactions and Concurrency ` -* :doc:`Filters ` -* :doc:`NamingStrategy ` -* :doc:`Improving Performance ` -* :doc:`Caching ` -* :doc:`Partial Objects ` -* :doc:`Change Tracking Policies ` -* :doc:`Best Practices ` -* :doc:`Metadata Drivers ` -* :doc:`Batch Processing ` -* :doc:`Second Level Cache ` - -Tutorials ---------- - -* :doc:`Indexed associations ` -* :doc:`Extra Lazy Associations ` -* :doc:`Composite Primary Keys ` -* :doc:`Ordered associations ` -* :doc:`Pagination ` -* :doc:`Override Field/Association Mappings In Subclasses ` -* :doc:`Embeddables ` - -Changelogs ----------- - -* `Upgrade `_ - -Cookbook --------- - -* **Patterns**: - :doc:`Aggregate Fields ` | - :doc:`Decorator Pattern ` | - :doc:`Strategy Pattern ` - -* **DQL Extension Points**: - :doc:`DQL Custom Walkers ` | - :doc:`DQL User-Defined-Functions ` - -* **Implementation**: - :doc:`Array Access ` | - :doc:`Notify ChangeTracking Example ` | - :doc:`Using Wakeup Or Clone ` | - :doc:`Working with DateTime ` | - :doc:`Validation ` | - :doc:`Entities in the Session ` | - :doc:`Keeping your Modules independent ` - -* **Hidden Gems** - :doc:`Prefixing Table Name ` - -* **Custom Datatypes** - :doc:`MySQL Enums ` - :doc:`Advanced Field Value Conversion ` - -.. include:: toc.rst diff --git a/vendor/doctrine/orm/docs/en/make.bat b/vendor/doctrine/orm/docs/en/make.bat deleted file mode 100644 index 53c40c9..0000000 --- a/vendor/doctrine/orm/docs/en/make.bat +++ /dev/null @@ -1,113 +0,0 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -set SPHINXBUILD=sphinx-build -set BUILDDIR=_build -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^` where ^ is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. changes to make an overview over all changed/added/deprecated items - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Doctrine2ORM.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Doctrine2ORM.ghc - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -:end diff --git a/vendor/doctrine/orm/docs/en/reference/advanced-configuration.rst b/vendor/doctrine/orm/docs/en/reference/advanced-configuration.rst deleted file mode 100644 index 0ddb6ef..0000000 --- a/vendor/doctrine/orm/docs/en/reference/advanced-configuration.rst +++ /dev/null @@ -1,470 +0,0 @@ -Advanced Configuration -====================== - -The configuration of the EntityManager requires a -``Doctrine\ORM\Configuration`` instance as well as some database -connection parameters. This example shows all the potential -steps of configuration. - -.. code-block:: php - - setMetadataCacheImpl($cache); - $driverImpl = $config->newDefaultAnnotationDriver('/path/to/lib/MyProject/Entities'); - $config->setMetadataDriverImpl($driverImpl); - $config->setQueryCacheImpl($cache); - $config->setProxyDir('/path/to/myproject/lib/MyProject/Proxies'); - $config->setProxyNamespace('MyProject\Proxies'); - - if ($applicationMode == "development") { - $config->setAutoGenerateProxyClasses(true); - } else { - $config->setAutoGenerateProxyClasses(false); - } - - $connectionOptions = array( - 'driver' => 'pdo_sqlite', - 'path' => 'database.sqlite' - ); - - $em = EntityManager::create($connectionOptions, $config); - -.. note:: - - Do not use Doctrine without a metadata and query cache! - Doctrine is optimized for working with caches. The main - parts in Doctrine that are optimized for caching are the metadata - mapping information with the metadata cache and the DQL to SQL - conversions with the query cache. These 2 caches require only an - absolute minimum of memory yet they heavily improve the runtime - performance of Doctrine. The recommended cache driver to use with - Doctrine is `APC `_. APC provides you with - an opcode-cache (which is highly recommended anyway) and a very - fast in-memory cache storage that you can use for the metadata and - query caches as seen in the previous code snippet. - -Configuration Options ---------------------- - -The following sections describe all the configuration options -available on a ``Doctrine\ORM\Configuration`` instance. - -Proxy Directory (***REQUIRED***) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: php - - setProxyDir($dir); - $config->getProxyDir(); - -Gets or sets the directory where Doctrine generates any proxy -classes. For a detailed explanation on proxy classes and how they -are used in Doctrine, refer to the "Proxy Objects" section further -down. - -Proxy Namespace (***REQUIRED***) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: php - - setProxyNamespace($namespace); - $config->getProxyNamespace(); - -Gets or sets the namespace to use for generated proxy classes. For -a detailed explanation on proxy classes and how they are used in -Doctrine, refer to the "Proxy Objects" section further down. - -Metadata Driver (***REQUIRED***) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: php - - setMetadataDriverImpl($driver); - $config->getMetadataDriverImpl(); - -Gets or sets the metadata driver implementation that is used by -Doctrine to acquire the object-relational metadata for your -classes. - -There are currently 4 available implementations: - - -- ``Doctrine\ORM\Mapping\Driver\AnnotationDriver`` -- ``Doctrine\ORM\Mapping\Driver\XmlDriver`` -- ``Doctrine\ORM\Mapping\Driver\YamlDriver`` -- ``Doctrine\ORM\Mapping\Driver\DriverChain`` - -Throughout the most part of this manual the AnnotationDriver is -used in the examples. For information on the usage of the XmlDriver -or YamlDriver please refer to the dedicated chapters -``XML Mapping`` and ``YAML Mapping``. - -The annotation driver can be configured with a factory method on -the ``Doctrine\ORM\Configuration``: - -.. code-block:: php - - newDefaultAnnotationDriver('/path/to/lib/MyProject/Entities'); - $config->setMetadataDriverImpl($driverImpl); - -The path information to the entities is required for the annotation -driver, because otherwise mass-operations on all entities through -the console could not work correctly. All of metadata drivers -accept either a single directory as a string or an array of -directories. With this feature a single driver can support multiple -directories of Entities. - -Metadata Cache (***RECOMMENDED***) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: php - - setMetadataCacheImpl($cache); - $config->getMetadataCacheImpl(); - -Gets or sets the cache implementation to use for caching metadata -information, that is, all the information you supply via -annotations, xml or yaml, so that they do not need to be parsed and -loaded from scratch on every single request which is a waste of -resources. The cache implementation must implement the -``Doctrine\Common\Cache\Cache`` interface. - -Usage of a metadata cache is highly recommended. - -The recommended implementations for production are: - - -- ``Doctrine\Common\Cache\ApcCache`` -- ``Doctrine\Common\Cache\ApcuCache`` -- ``Doctrine\Common\Cache\MemcacheCache`` -- ``Doctrine\Common\Cache\XcacheCache`` -- ``Doctrine\Common\Cache\RedisCache`` - -For development you should use the -``Doctrine\Common\Cache\ArrayCache`` which only caches data on a -per-request basis. - -Query Cache (***RECOMMENDED***) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: php - - setQueryCacheImpl($cache); - $config->getQueryCacheImpl(); - -Gets or sets the cache implementation to use for caching DQL -queries, that is, the result of a DQL parsing process that includes -the final SQL as well as meta information about how to process the -SQL result set of a query. Note that the query cache does not -affect query results. You do not get stale data. This is a pure -optimization cache without any negative side-effects (except some -minimal memory usage in your cache). - -Usage of a query cache is highly recommended. - -The recommended implementations for production are: - - -- ``Doctrine\Common\Cache\ApcCache`` -- ``Doctrine\Common\Cache\ApcuCache`` -- ``Doctrine\Common\Cache\MemcacheCache`` -- ``Doctrine\Common\Cache\XcacheCache`` -- ``Doctrine\Common\Cache\RedisCache`` - -For development you should use the -``Doctrine\Common\Cache\ArrayCache`` which only caches data on a -per-request basis. - -SQL Logger (***Optional***) -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: php - - setSQLLogger($logger); - $config->getSQLLogger(); - -Gets or sets the logger to use for logging all SQL statements -executed by Doctrine. The logger class must implement the -``Doctrine\DBAL\Logging\SQLLogger`` interface. A simple default -implementation that logs to the standard output using ``echo`` and -``var_dump`` can be found at -``Doctrine\DBAL\Logging\EchoSQLLogger``. - -Auto-generating Proxy Classes (***OPTIONAL***) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Proxy classes can either be generated manually through the Doctrine -Console or automatically at runtime by Doctrine. The configuration -option that controls this behavior is: - -.. code-block:: php - - setAutoGenerateProxyClasses($mode); - -Possible values for ``$mode`` are: - -- ``Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_NEVER`` - -Never autogenerate a proxy. You will need to generate the proxies -manually, for this use the Doctrine Console like so: - -.. code-block:: php - - $ ./doctrine orm:generate-proxies - -When you do this in a development environment, -be aware that you may get class/file not found errors if certain proxies -are not yet generated. You may also get failing lazy-loads if new -methods were added to the entity class that are not yet in the proxy class. -In such a case, simply use the Doctrine Console to (re)generate the -proxy classes. - -- ``Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_ALWAYS`` - -Always generates a new proxy in every request and writes it to disk. - -- ``Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS`` - -Generate the proxy class when the proxy file does not exist. -This strategy causes a file exists call whenever any proxy is -used the first time in a request. - -- ``Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_EVAL`` - -Generate the proxy classes and evaluate them on the fly via eval(), -avoiding writing the proxies to disk. -This strategy is only sane for development. - -In a production environment, it is highly recommended to use -AUTOGENERATE_NEVER to allow for optimal performances. The other -options are interesting in development environment. - -Before v2.4, ``setAutoGenerateProxyClasses`` would accept a boolean -value. This is still possible, ``FALSE`` being equivalent to -AUTOGENERATE_NEVER and ``TRUE`` to AUTOGENERATE_ALWAYS. - -Development vs Production Configuration ---------------------------------------- - -You should code your Doctrine2 bootstrapping with two different -runtime models in mind. There are some serious benefits of using -APC or Memcache in production. In development however this will -frequently give you fatal errors, when you change your entities and -the cache still keeps the outdated metadata. That is why we -recommend the ``ArrayCache`` for development. - -Furthermore you should have the Auto-generating Proxy Classes -option to true in development and to false in production. If this -option is set to ``TRUE`` it can seriously hurt your script -performance if several proxy classes are re-generated during script -execution. Filesystem calls of that magnitude can even slower than -all the database queries Doctrine issues. Additionally writing a -proxy sets an exclusive file lock which can cause serious -performance bottlenecks in systems with regular concurrent -requests. - -Connection Options ------------------- - -The ``$connectionOptions`` passed as the first argument to -``EntityManager::create()`` has to be either an array or an -instance of ``Doctrine\DBAL\Connection``. If an array is passed it -is directly passed along to the DBAL Factory -``Doctrine\DBAL\DriverManager::getConnection()``. The DBAL -configuration is explained in the -`DBAL section `_. - -Proxy Objects -------------- - -A proxy object is an object that is put in place or used instead of -the "real" object. A proxy object can add behavior to the object -being proxied without that object being aware of it. In Doctrine 2, -proxy objects are used to realize several features but mainly for -transparent lazy-loading. - -Proxy objects with their lazy-loading facilities help to keep the -subset of objects that are already in memory connected to the rest -of the objects. This is an essential property as without it there -would always be fragile partial objects at the outer edges of your -object graph. - -Doctrine 2 implements a variant of the proxy pattern where it -generates classes that extend your entity classes and adds -lazy-loading capabilities to them. Doctrine can then give you an -instance of such a proxy class whenever you request an object of -the class being proxied. This happens in two situations: - -Reference Proxies -~~~~~~~~~~~~~~~~~ - -The method ``EntityManager#getReference($entityName, $identifier)`` -lets you obtain a reference to an entity for which the identifier -is known, without loading that entity from the database. This is -useful, for example, as a performance enhancement, when you want to -establish an association to an entity for which you have the -identifier. You could simply do this: - -.. code-block:: php - - getReference('MyProject\Model\Item', $itemId); - $cart->addItem($item); - -Here, we added an Item to a Cart without loading the Item from the -database. If you invoke any method on the Item instance, it would -fully initialize its state transparently from the database. Here -$item is actually an instance of the proxy class that was generated -for the Item class but your code does not need to care. In fact it -**should not care**. Proxy objects should be transparent to your -code. - -Association proxies -~~~~~~~~~~~~~~~~~~~ - -The second most important situation where Doctrine uses proxy -objects is when querying for objects. Whenever you query for an -object that has a single-valued association to another object that -is configured LAZY, without joining that association in the same -query, Doctrine puts proxy objects in place where normally the -associated object would be. Just like other proxies it will -transparently initialize itself on first access. - -.. note:: - - Joining an association in a DQL or native query - essentially means eager loading of that association in that query. - This will override the 'fetch' option specified in the mapping for - that association, but only for that query. - - -Generating Proxy classes -~~~~~~~~~~~~~~~~~~~~~~~~ - -In a production environment, it is highly recommended to use -``AUTOGENERATE_NEVER`` to allow for optimal performances. -However you will be required to generate the proxies manually -using the Doctrine Console: - -.. code-block:: php - - $ ./doctrine orm:generate-proxies - -The other options are interesting in development environment: - -- ``AUTOGENERATE_ALWAYS`` will require you to create and configure - a proxy directory. Proxies will be generated and written to file - on each request, so any modification to your code will be acknowledged. - -- ``AUTOGENERATE_FILE_NOT_EXISTS`` will not overwrite an existing - proxy file. If your code changes, you will need to regenerate the - proxies manually. - -- ``AUTOGENERATE_EVAL`` will regenerate each proxy on each request, - but without writing them to disk. - -Autoloading Proxies -------------------- - -When you deserialize proxy objects from the session or any other storage -it is necessary to have an autoloading mechanism in place for these classes. -For implementation reasons Proxy class names are not PSR-0 compliant. This -means that you have to register a special autoloader for these classes: - -.. code-block:: php - - addDriver($xmlDriver, 'Doctrine\Tests\Models\Company'); - $chain->addDriver($yamlDriver, 'Doctrine\Tests\ORM\Mapping'); - -Based on the namespace of the entity the loading of entities is -delegated to the appropriate driver. The chain semantics come from -the fact that the driver loops through all namespaces and matches -the entity class name against the namespace using a -``strpos() === 0`` call. This means you need to order the drivers -correctly if sub-namespaces use different metadata driver -implementations. - - -Default Repository (***OPTIONAL***) ------------------------------------ - -Specifies the FQCN of a subclass of the EntityRepository. -That will be available for all entities without a custom repository class. - -.. code-block:: php - - setDefaultRepositoryClassName($fqcn); - $config->getDefaultRepositoryClassName(); - -The default value is ``Doctrine\ORM\EntityRepository``. -Any repository class must be a subclass of EntityRepository otherwise you got an ORMException - -Setting up the Console ----------------------- - -Doctrine uses the Symfony Console component for generating the command -line interface. You can take a look at the ``vendor/bin/doctrine.php`` -script and the ``Doctrine\ORM\Tools\Console\ConsoleRunner`` command -for inspiration how to setup the cli. - -In general the required code looks like this: - -.. code-block:: php - - setCatchExceptions(true); - $cli->setHelperSet($helperSet); - Doctrine\ORM\Tools\Console\ConsoleRunner::addCommands($cli); - $cli->run(); - diff --git a/vendor/doctrine/orm/docs/en/reference/annotations-reference.rst b/vendor/doctrine/orm/docs/en/reference/annotations-reference.rst deleted file mode 100644 index 20381da..0000000 --- a/vendor/doctrine/orm/docs/en/reference/annotations-reference.rst +++ /dev/null @@ -1,1327 +0,0 @@ -Annotations Reference -===================== - -You've probably used docblock annotations in some form already, -most likely to provide documentation metadata for a tool like -``PHPDocumentor`` (@author, @link, ...). Docblock annotations are a -tool to embed metadata inside the documentation section which can -then be processed by some tool. Doctrine 2 generalizes the concept -of docblock annotations so that they can be used for any kind of -metadata and so that it is easy to define new docblock annotations. -In order to allow more involved annotation values and to reduce the -chances of clashes with other docblock annotations, the Doctrine 2 -docblock annotations feature an alternative syntax that is heavily -inspired by the Annotation syntax introduced in Java 5. - -The implementation of these enhanced docblock annotations is -located in the ``Doctrine\Common\Annotations`` namespace and -therefore part of the Common package. Doctrine 2 docblock -annotations support namespaces and nested annotations among other -things. The Doctrine 2 ORM defines its own set of docblock -annotations for supplying object-relational mapping metadata. - -.. note:: - - If you're not comfortable with the concept of docblock - annotations, don't worry, as mentioned earlier Doctrine 2 provides - XML and YAML alternatives and you could easily implement your own - favourite mechanism for defining ORM metadata. - -In this chapter a reference of every Doctrine 2 Annotation is given -with short explanations on their context and usage. - -Index ------ - -- :ref:`@Column ` -- :ref:`@ColumnResult ` -- :ref:`@Cache ` -- :ref:`@ChangeTrackingPolicy ` -- :ref:`@CustomIdGenerator ` -- :ref:`@DiscriminatorColumn ` -- :ref:`@DiscriminatorMap ` -- :ref:`@Embeddable ` -- :ref:`@Embedded ` -- :ref:`@Entity ` -- :ref:`@EntityResult ` -- :ref:`@FieldResult ` -- :ref:`@GeneratedValue ` -- :ref:`@HasLifecycleCallbacks ` -- :ref:`@Index ` -- :ref:`@Id ` -- :ref:`@InheritanceType ` -- :ref:`@JoinColumn ` -- :ref:`@JoinColumns ` -- :ref:`@JoinTable ` -- :ref:`@ManyToOne ` -- :ref:`@ManyToMany ` -- :ref:`@MappedSuperclass ` -- :ref:`@NamedNativeQuery ` -- :ref:`@OneToOne ` -- :ref:`@OneToMany ` -- :ref:`@OrderBy ` -- :ref:`@PostLoad ` -- :ref:`@PostPersist ` -- :ref:`@PostRemove ` -- :ref:`@PostUpdate ` -- :ref:`@PrePersist ` -- :ref:`@PreRemove ` -- :ref:`@PreUpdate ` -- :ref:`@SequenceGenerator ` -- :ref:`@SqlResultSetMapping ` -- :ref:`@Table ` -- :ref:`@UniqueConstraint ` -- :ref:`@Version ` - -Reference ---------- - -.. _annref_column: - -@Column -~~~~~~~ - -Marks an annotated instance variable as "persistent". It has to be -inside the instance variables PHP DocBlock comment. Any value hold -inside this variable will be saved to and loaded from the database -as part of the lifecycle of the instance variables entity-class. - -Required attributes: - -- **type**: Name of the Doctrine Type which is converted between PHP - and Database representation. - -Optional attributes: - -- **name**: By default the property name is used for the database - column name also, however the 'name' attribute allows you to - determine the column name. - -- **length**: Used by the "string" type to determine its maximum - length in the database. Doctrine does not validate the length of a - string values for you. - -- **precision**: The precision for a decimal (exact numeric) column - (applies only for decimal column), which is the maximum number of - digits that are stored for the values. - -- **scale**: The scale for a decimal (exact numeric) column (applies - only for decimal column), which represents the number of digits - to the right of the decimal point and must not be greater than - *precision*. - -- **unique**: Boolean value to determine if the value of the column - should be unique across all rows of the underlying entities table. - -- **nullable**: Determines if NULL values allowed for this column. If not specified, default value is false. - -- **options**: Array of additional options: - - - ``default``: The default value to set for the column if no value - is supplied. - - - ``unsigned``: Boolean value to determine if the column should - be capable of representing only non-negative integers - (applies only for integer column and might not be supported by - all vendors). - - - ``fixed``: Boolean value to determine if the specified length of - a string column should be fixed or varying (applies only for - string/binary column and might not be supported by all vendors). - - - ``comment``: The comment of the column in the schema (might not - be supported by all vendors). - - - ``collation``: The collation of the column (only supported by Drizzle, Mysql, PostgreSQL>=9.1, Sqlite and SQLServer). - - - ``check``: Adds a check constraint type to the column (might not - be supported by all vendors). - -- **columnDefinition**: DDL SQL snippet that starts after the column - name and specifies the complete (non-portable!) column definition. - This attribute allows to make use of advanced RMDBS features. - However you should make careful use of this feature and the - consequences. SchemaTool will not detect changes on the column correctly - anymore if you use "columnDefinition". - - Additionally you should remember that the "type" - attribute still handles the conversion between PHP and Database - values. If you use this attribute on a column that is used for - joins between tables you should also take a look at - :ref:`@JoinColumn `. - -.. note:: - - For more detailed information on each attribute, please refer to - the DBAL ``Schema-Representation`` documentation. - -Examples: - -.. code-block:: php - - ` -can be found in the configuration section. - -Example: - -.. code-block:: php - - ` and :ref:`@GeneratedValue(strategy="CUSTOM") ` are specified. - -Required attributes: - -- **class**: name of the class which should extend Doctrine\ORM\Id\AbstractIdGenerator - -Example: - -.. code-block:: php - - ` -annotation to establish the relationship between the two classes. - -.. code-block:: php - - = 2.1) Specifies that this entity is marked as read only and not - considered for change-tracking. Entities of this type can be persisted - and removed though. - -Example: - -.. code-block:: php - - `. This -annotation is optional and only has meaning when used in -conjunction with @Id. - -If this annotation is not specified with @Id the NONE strategy is -used as default. - -Optional attributes: - - -- **strategy**: Set the name of the identifier generation strategy. - Valid values are AUTO, SEQUENCE, TABLE, IDENTITY, UUID, CUSTOM and NONE. - If not specified, default value is AUTO. - -Example: - -.. code-block:: php - - ` annotation on -the entity-class level. It provides a hint to the SchemaTool to -generate a database index on the specified table columns. It only -has meaning in the SchemaTool schema generation context. - -Required attributes: - - -- **name**: Name of the Index -- **columns**: Array of columns. - -Optional attributes: - -- **options**: Array of platform specific options: - - - ``where``: SQL WHERE condition to be used for partial indexes. It will - only have effect on supported platforms. - -Basic example: - -.. code-block:: php - - ` and -:ref:`@DiscriminatorColumn ` annotations. - -Examples: - -.. code-block:: php - - `, :ref:`@OneToOne ` fields -and in the Context of :ref:`@JoinTable ` nested inside -a @ManyToMany. This annotation is not required. If it is not -specified the attributes *name* and *referencedColumnName* are -inferred from the table and primary key names. - -Required attributes: - - -- **name**: Column name that holds the foreign key identifier for - this relation. In the context of @JoinTable it specifies the column - name in the join table. -- **referencedColumnName**: Name of the primary key identifier that - is used for joining of this relation. - -Optional attributes: - - -- **unique**: Determines whether this relation is exclusive between the - affected entities and should be enforced as such on the database - constraint level. Defaults to false. -- **nullable**: Determine whether the related entity is required, or if - null is an allowed state for the relation. Defaults to true. -- **onDelete**: Cascade Action (Database-level) -- **columnDefinition**: DDL SQL snippet that starts after the column - name and specifies the complete (non-portable!) column definition. - This attribute enables the use of advanced RMDBS features. Using - this attribute on @JoinColumn is necessary if you need slightly - different column definitions for joining columns, for example - regarding NULL/NOT NULL defaults. However by default a - "columnDefinition" attribute on :ref:`@Column ` also sets - the related @JoinColumn's columnDefinition. This is necessary to - make foreign keys work. - -Example: - -.. code-block:: php - - ` or :ref:`@OneToOne ` -relation with an entity that has multiple identifiers. - -.. _annref_jointable: - -@JoinTable -~~~~~~~~~~~~~~ - -Using :ref:`@OneToMany ` or -:ref:`@ManyToMany ` on the owning side of the relation -requires to specify the @JoinTable annotation which describes the -details of the database join table. If you do not specify -@JoinTable on these relations reasonable mapping defaults apply -using the affected table and the column names. - -Optional attributes: - - -- **name**: Database name of the join-table -- **joinColumns**: An array of @JoinColumn annotations describing the - join-relation between the owning entities table and the join table. -- **inverseJoinColumns**: An array of @JoinColumn annotations - describing the join-relation between the inverse entities table and - the join table. - -Example: - -.. code-block:: php - - ` is an -additional, optional annotation that has reasonable default -configuration values using the table and names of the two related -entities. - -Required attributes: - - -- **targetEntity**: FQCN of the referenced target entity. Can be the - unqualified class name if both classes are in the same namespace. - *IMPORTANT:* No leading backslash! - -Optional attributes: - - -- **mappedBy**: This option specifies the property name on the - targetEntity that is the owning side of this relation. It is a - required attribute for the inverse side of a relationship. -- **inversedBy**: The inversedBy attribute designates the field in the - entity that is the inverse side of the relationship. -- **cascade**: Cascade Option -- **fetch**: One of LAZY, EXTRA_LAZY or EAGER -- **indexBy**: Index the collection by a field on the target entity. - -.. note:: - - For ManyToMany bidirectional relationships either side may - be the owning side (the side that defines the @JoinTable and/or - does not make use of the mappedBy attribute, thus using a default - join table). - -Example: - -.. code-block:: php - - `. - -Optional attributes: - - -- **repositoryClass**: (>= 2.2) Specifies the FQCN of a subclass of the EntityRepository. - That will be inherited for all subclasses of that Mapped Superclass. - -Example: - -.. code-block:: php - - ` with one additional option which can -be specified. The configuration defaults for -:ref:`@JoinColumn ` using the target entity table and -primary key column names apply here too. - -Required attributes: - - -- **targetEntity**: FQCN of the referenced target entity. Can be the - unqualified class name if both classes are in the same namespace. - *IMPORTANT:* No leading backslash! - -Optional attributes: - - -- **cascade**: Cascade Option -- **fetch**: One of LAZY or EAGER -- **orphanRemoval**: Boolean that specifies if orphans, inverse - OneToOne entities that are not connected to any owning instance, - should be removed by Doctrine. Defaults to false. -- **inversedBy**: The inversedBy attribute designates the field in the - entity that is the inverse side of the relationship. - -Example: - -.. code-block:: php - - ` or :ref:`@OneToMany ` -annotation to specify by which criteria the collection should be -retrieved from the database by using an ORDER BY clause. - -This annotation requires a single non-attributed value with an DQL -snippet: - -Example: - -.. code-block:: php - - = 2.5) Name of the schema the table lies in. - -Example: - -.. code-block:: php - - ` annotation on -the entity-class level. It allows to hint the SchemaTool to -generate a database unique constraint on the specified table -columns. It only has meaning in the SchemaTool schema generation -context. - -Required attributes: - - -- **name**: Name of the Index -- **columns**: Array of columns. - -Optional attributes: - -- **options**: Array of platform specific options: - - - ``where``: SQL WHERE condition to be used for partial indexes. It will - only have effect on supported platforms. - -Basic example: - -.. code-block:: php - - ` -scenario. It only works on :ref:`@Column ` annotations that have -the type ``integer`` or ``datetime``. Combining ``@Version`` with -:ref:`@Id ` is not supported. - -Example: - -.. code-block:: php - - `. -- An entity class must not implement ``__wakeup`` or - :doc:`do so safely <../cookbook/implementing-wakeup-or-clone>`. - Also consider implementing - `Serializable `_ - instead. -- Any two entity classes in a class hierarchy that inherit - directly or indirectly from one another must not have a mapped - property with the same name. That is, if B inherits from A then B - must not have a mapped field with the same name as an already - mapped field that is inherited from A. -- An entity cannot make use of func_get_args() to implement variable parameters. - Generated proxies do not support this for performance reasons and your code might - actually fail to work when violating this restriction. - -Entities support inheritance, polymorphic associations, and -polymorphic queries. Both abstract and concrete classes can be -entities. Entities may extend non-entity classes as well as entity -classes, and non-entity classes may extend entity classes. - -.. note:: - - The constructor of an entity is only ever invoked when - *you* construct a new instance with the *new* keyword. Doctrine - never calls entity constructors, thus you are free to use them as - you wish and even have it require arguments of any type. - - -Entity states -~~~~~~~~~~~~~ - -An entity instance can be characterized as being NEW, MANAGED, -DETACHED or REMOVED. - - -- A NEW entity instance has no persistent identity, and is not yet - associated with an EntityManager and a UnitOfWork (i.e. those just - created with the "new" operator). -- A MANAGED entity instance is an instance with a persistent - identity that is associated with an EntityManager and whose - persistence is thus managed. -- A DETACHED entity instance is an instance with a persistent - identity that is not (or no longer) associated with an - EntityManager and a UnitOfWork. -- A REMOVED entity instance is an instance with a persistent - identity, associated with an EntityManager, that will be removed - from the database upon transaction commit. - -.. _architecture_persistent_fields: - -Persistent fields -~~~~~~~~~~~~~~~~~ - -The persistent state of an entity is represented by instance -variables. An instance variable must be directly accessed only from -within the methods of the entity by the entity instance itself. -Instance variables must not be accessed by clients of the entity. -The state of the entity is available to clients only through the -entity’s methods, i.e. accessor methods (getter/setter methods) or -other business methods. - -Collection-valued persistent fields and properties must be defined -in terms of the ``Doctrine\Common\Collections\Collection`` -interface. The collection implementation type may be used by the -application to initialize fields or properties before the entity is -made persistent. Once the entity becomes managed (or detached), -subsequent access must be through the interface type. - -Serializing entities -~~~~~~~~~~~~~~~~~~~~ - -Serializing entities can be problematic and is not really -recommended, at least not as long as an entity instance still holds -references to proxy objects or is still managed by an -EntityManager. If you intend to serialize (and unserialize) entity -instances that still hold references to proxy objects you may run -into problems with private properties because of technical -limitations. Proxy objects implement ``__sleep`` and it is not -possible for ``__sleep`` to return names of private properties in -parent classes. On the other hand it is not a solution for proxy -objects to implement ``Serializable`` because Serializable does not -work well with any potential cyclic object references (at least we -did not find a way yet, if you did, please contact us). - -The EntityManager -~~~~~~~~~~~~~~~~~ - -The ``EntityManager`` class is a central access point to the ORM -functionality provided by Doctrine 2. The ``EntityManager`` API is -used to manage the persistence of your objects and to query for -persistent objects. - -Transactional write-behind -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -An ``EntityManager`` and the underlying ``UnitOfWork`` employ a -strategy called "transactional write-behind" that delays the -execution of SQL statements in order to execute them in the most -efficient way and to execute them at the end of a transaction so -that all write locks are quickly released. You should see Doctrine -as a tool to synchronize your in-memory objects with the database -in well defined units of work. Work with your objects and modify -them as usual and when you're done call ``EntityManager#flush()`` -to make your changes persistent. - -The Unit of Work -~~~~~~~~~~~~~~~~ - -Internally an ``EntityManager`` uses a ``UnitOfWork``, which is a -typical implementation of the -`Unit of Work pattern `_, -to keep track of all the things that need to be done the next time -``flush`` is invoked. You usually do not directly interact with a -``UnitOfWork`` but with the ``EntityManager`` instead. - - diff --git a/vendor/doctrine/orm/docs/en/reference/association-mapping.rst b/vendor/doctrine/orm/docs/en/reference/association-mapping.rst deleted file mode 100644 index 6347d89..0000000 --- a/vendor/doctrine/orm/docs/en/reference/association-mapping.rst +++ /dev/null @@ -1,1130 +0,0 @@ -Association Mapping -=================== - -This chapter explains mapping associations between objects. - -Instead of working with foreign keys in your code, you will always work with -references to objects instead and Doctrine will convert those references -to foreign keys internally. - -- A reference to a single object is represented by a foreign key. -- A collection of objects is represented by many foreign keys pointing to the object holding the collection - -This chapter is split into three different sections. - -- A list of all the possible association mapping use-cases is given. -- :ref:`association_mapping_defaults` are explained that simplify the use-case examples. -- :ref:`collections` are introduced that contain entities in associations. - -One tip for working with relations is to read the relation from left to right, where the left word refers to the current Entity. For example: - -- OneToMany - One instance of the current Entity has Many instances (references) to the refered Entity. -- ManyToOne - Many instances of the current Entity refer to One instance of the refered Entity. -- OneToOne - One instance of the current Entity refers to One instance of the refered Entity. - -See below for all the possible relations. - -An association is considered to be unidirectional if only one side of the association has -a property referring to the other side. - -To gain a full understanding of associations you should also read about :doc:`owning and -inverse sides of associations ` - -Many-To-One, Unidirectional ---------------------------- - -A many-to-one association is the most common association between objects. Example: Many Users have One Address: - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - .. code-block:: yaml - - User: - type: entity - manyToOne: - address: - targetEntity: Address - joinColumn: - name: address_id - referencedColumnName: id - - -.. note:: - - The above ``@JoinColumn`` is optional as it would default - to ``address_id`` and ``id`` anyways. You can omit it and let it - use the defaults. - -Generated MySQL Schema: - -.. code-block:: sql - - CREATE TABLE User ( - id INT AUTO_INCREMENT NOT NULL, - address_id INT DEFAULT NULL, - PRIMARY KEY(id) - ) ENGINE = InnoDB; - - CREATE TABLE Address ( - id INT AUTO_INCREMENT NOT NULL, - PRIMARY KEY(id) - ) ENGINE = InnoDB; - - ALTER TABLE User ADD FOREIGN KEY (address_id) REFERENCES Address(id); - -One-To-One, Unidirectional --------------------------- - -Here is an example of a one-to-one association with a ``Product`` entity that -references one ``Shipment`` entity. - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - .. code-block:: yaml - - Product: - type: entity - oneToOne: - shipment: - targetEntity: Shipment - joinColumn: - name: shipment_id - referencedColumnName: id - -Note that the @JoinColumn is not really necessary in this example, -as the defaults would be the same. - -Generated MySQL Schema: - -.. code-block:: sql - - CREATE TABLE Product ( - id INT AUTO_INCREMENT NOT NULL, - shipment_id INT DEFAULT NULL, - UNIQUE INDEX UNIQ_6FBC94267FE4B2B (shipment_id), - PRIMARY KEY(id) - ) ENGINE = InnoDB; - CREATE TABLE Shipment ( - id INT AUTO_INCREMENT NOT NULL, - PRIMARY KEY(id) - ) ENGINE = InnoDB; - ALTER TABLE Product ADD FOREIGN KEY (shipment_id) REFERENCES Shipment(id); - -One-To-One, Bidirectional -------------------------- - -Here is a one-to-one relationship between a ``Customer`` and a -``Cart``. The ``Cart`` has a reference back to the ``Customer`` so -it is bidirectional. - -Here we see the ``mappedBy`` and ``inversedBy`` annotations for the first time. -They are used to tell Doctrine which property on the other side refers to the -object. - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - - - - .. code-block:: yaml - - Customer: - oneToOne: - cart: - targetEntity: Cart - mappedBy: customer - Cart: - oneToOne: - customer: - targetEntity: Customer - inversedBy: cart - joinColumn: - name: customer_id - referencedColumnName: id - -Note that the @JoinColumn is not really necessary in this example, -as the defaults would be the same. - -Generated MySQL Schema: - -.. code-block:: sql - - CREATE TABLE Cart ( - id INT AUTO_INCREMENT NOT NULL, - customer_id INT DEFAULT NULL, - PRIMARY KEY(id) - ) ENGINE = InnoDB; - CREATE TABLE Customer ( - id INT AUTO_INCREMENT NOT NULL, - PRIMARY KEY(id) - ) ENGINE = InnoDB; - ALTER TABLE Cart ADD FOREIGN KEY (customer_id) REFERENCES Customer(id); - -We had a choice of sides on which to place the ``inversedBy`` attribute. Because it -is on the ``Cart``, that is the owning side of the relation, and thus holds the -foreign key. - -One-To-One, Self-referencing ----------------------------- - -You can define a self-referencing one-to-one relationships like -below. - -.. code-block:: php - - features = new ArrayCollection(); - } - } - - /** @Entity */ - class Feature - { - // ... - /** - * Many features have one product. This is the owning side. - * @ManyToOne(targetEntity="Product", inversedBy="features") - * @JoinColumn(name="product_id", referencedColumnName="id") - */ - private $product; - // ... - } - - .. code-block:: xml - - - - - - - - - - - - - .. code-block:: yaml - - Product: - type: entity - oneToMany: - features: - targetEntity: Feature - mappedBy: product - Feature: - type: entity - manyToOne: - product: - targetEntity: Product - inversedBy: features - joinColumn: - name: product_id - referencedColumnName: id - -Note that the @JoinColumn is not really necessary in this example, -as the defaults would be the same. - -Generated MySQL Schema: - -.. code-block:: sql - - CREATE TABLE Product ( - id INT AUTO_INCREMENT NOT NULL, - PRIMARY KEY(id) - ) ENGINE = InnoDB; - CREATE TABLE Feature ( - id INT AUTO_INCREMENT NOT NULL, - product_id INT DEFAULT NULL, - PRIMARY KEY(id) - ) ENGINE = InnoDB; - ALTER TABLE Feature ADD FOREIGN KEY (product_id) REFERENCES Product(id); - -One-To-Many, Unidirectional with Join Table -------------------------------------------- - -A unidirectional one-to-many association can be mapped through a -join table. From Doctrine's point of view, it is simply mapped as a -unidirectional many-to-many whereby a unique constraint on one of -the join columns enforces the one-to-many cardinality. - -The following example sets up such a unidirectional one-to-many association: - -.. configuration-block:: - - .. code-block:: php - - phonenumbers = new \Doctrine\Common\Collections\ArrayCollection(); - } - - // ... - } - - /** @Entity */ - class Phonenumber - { - // ... - } - - .. code-block:: xml - - - - - - - - - - - - - - - - - .. code-block:: yaml - - User: - type: entity - manyToMany: - phonenumbers: - targetEntity: Phonenumber - joinTable: - name: users_phonenumbers - joinColumns: - user_id: - referencedColumnName: id - inverseJoinColumns: - phonenumber_id: - referencedColumnName: id - unique: true - - -Generates the following MySQL Schema: - -.. code-block:: sql - - CREATE TABLE User ( - id INT AUTO_INCREMENT NOT NULL, - PRIMARY KEY(id) - ) ENGINE = InnoDB; - - CREATE TABLE users_phonenumbers ( - user_id INT NOT NULL, - phonenumber_id INT NOT NULL, - UNIQUE INDEX users_phonenumbers_phonenumber_id_uniq (phonenumber_id), - PRIMARY KEY(user_id, phonenumber_id) - ) ENGINE = InnoDB; - - CREATE TABLE Phonenumber ( - id INT AUTO_INCREMENT NOT NULL, - PRIMARY KEY(id) - ) ENGINE = InnoDB; - - ALTER TABLE users_phonenumbers ADD FOREIGN KEY (user_id) REFERENCES User(id); - ALTER TABLE users_phonenumbers ADD FOREIGN KEY (phonenumber_id) REFERENCES Phonenumber(id); - -One-To-Many, Self-referencing ------------------------------ - -You can also setup a one-to-many association that is -self-referencing. In this example we setup a hierarchy of -``Category`` objects by creating a self referencing relationship. -This effectively models a hierarchy of categories and from the -database perspective is known as an adjacency list approach. - -.. configuration-block:: - - .. code-block:: php - - children = new \Doctrine\Common\Collections\ArrayCollection(); - } - } - - .. code-block:: xml - - - - - - - - - .. code-block:: yaml - - Category: - type: entity - oneToMany: - children: - targetEntity: Category - mappedBy: parent - manyToOne: - parent: - targetEntity: Category - inversedBy: children - -Note that the @JoinColumn is not really necessary in this example, -as the defaults would be the same. - -Generated MySQL Schema: - -.. code-block:: sql - - CREATE TABLE Category ( - id INT AUTO_INCREMENT NOT NULL, - parent_id INT DEFAULT NULL, - PRIMARY KEY(id) - ) ENGINE = InnoDB; - ALTER TABLE Category ADD FOREIGN KEY (parent_id) REFERENCES Category(id); - -Many-To-Many, Unidirectional ----------------------------- - -Real many-to-many associations are less common. The following -example shows a unidirectional association between User and Group -entities: - -.. configuration-block:: - - .. code-block:: php - - groups = new \Doctrine\Common\Collections\ArrayCollection(); - } - } - - /** @Entity */ - class Group - { - // ... - } - - .. code-block:: xml - - - - - - - - - - - - - - - - - .. code-block:: yaml - - User: - type: entity - manyToMany: - groups: - targetEntity: Group - joinTable: - name: users_groups - joinColumns: - user_id: - referencedColumnName: id - inverseJoinColumns: - group_id: - referencedColumnName: id - -Generated MySQL Schema: - -.. code-block:: sql - - CREATE TABLE User ( - id INT AUTO_INCREMENT NOT NULL, - PRIMARY KEY(id) - ) ENGINE = InnoDB; - CREATE TABLE users_groups ( - user_id INT NOT NULL, - group_id INT NOT NULL, - PRIMARY KEY(user_id, group_id) - ) ENGINE = InnoDB; - CREATE TABLE Group ( - id INT AUTO_INCREMENT NOT NULL, - PRIMARY KEY(id) - ) ENGINE = InnoDB; - ALTER TABLE users_groups ADD FOREIGN KEY (user_id) REFERENCES User(id); - ALTER TABLE users_groups ADD FOREIGN KEY (group_id) REFERENCES Group(id); - -.. note:: - - Why are many-to-many associations less common? Because - frequently you want to associate additional attributes with an - association, in which case you introduce an association class. - Consequently, the direct many-to-many association disappears and is - replaced by one-to-many/many-to-one associations between the 3 - participating classes. - -Many-To-Many, Bidirectional ---------------------------- - -Here is a similar many-to-many relationship as above except this -one is bidirectional. - -.. configuration-block:: - - .. code-block:: php - - groups = new \Doctrine\Common\Collections\ArrayCollection(); - } - - // ... - } - - /** @Entity */ - class Group - { - // ... - /** - * Many Groups have Many Users. - * @ManyToMany(targetEntity="User", mappedBy="groups") - */ - private $users; - - public function __construct() { - $this->users = new \Doctrine\Common\Collections\ArrayCollection(); - } - - // ... - } - - .. code-block:: xml - - - - - - - - - - - - - - - - - - - - - .. code-block:: yaml - - User: - type: entity - manyToMany: - groups: - targetEntity: Group - inversedBy: users - joinTable: - name: users_groups - joinColumns: - user_id: - referencedColumnName: id - inverseJoinColumns: - group_id: - referencedColumnName: id - - Group: - type: entity - manyToMany: - users: - targetEntity: User - mappedBy: groups - -The MySQL schema is exactly the same as for the Many-To-Many -uni-directional case above. - -Owning and Inverse Side on a ManyToMany Association -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For Many-To-Many associations you can chose which entity is the -owning and which the inverse side. There is a very simple semantic -rule to decide which side is more suitable to be the owning side -from a developers perspective. You only have to ask yourself which -entity is responsible for the connection management, and pick that -as the owning side. - -Take an example of two entities ``Article`` and ``Tag``. Whenever -you want to connect an Article to a Tag and vice-versa, it is -mostly the Article that is responsible for this relation. Whenever -you add a new article, you want to connect it with existing or new -tags. Your "Create Article" form will probably support this notion -and allow specifying the tags directly. This is why you should pick -the Article as owning side, as it makes the code more -understandable: - -.. code-block:: php - - addArticle($this); // synchronously updating inverse side - $this->tags[] = $tag; - } - } - - class Tag - { - private $articles; - - public function addArticle(Article $article) - { - $this->articles[] = $article; - } - } - -This allows to group the tag adding on the ``Article`` side of the -association: - -.. code-block:: php - - addTag($tagA); - $article->addTag($tagB); - -Many-To-Many, Self-referencing ------------------------------- - -You can even have a self-referencing many-to-many association. A -common scenario is where a ``User`` has friends and the target -entity of that relationship is a ``User`` so it is self -referencing. In this example it is bidirectional so ``User`` has a -field named ``$friendsWithMe`` and ``$myFriends``. - -.. code-block:: php - - friendsWithMe = new \Doctrine\Common\Collections\ArrayCollection(); - $this->myFriends = new \Doctrine\Common\Collections\ArrayCollection(); - } - - // ... - } - -Generated MySQL Schema: - -.. code-block:: sql - - CREATE TABLE User ( - id INT AUTO_INCREMENT NOT NULL, - PRIMARY KEY(id) - ) ENGINE = InnoDB; - CREATE TABLE friends ( - user_id INT NOT NULL, - friend_user_id INT NOT NULL, - PRIMARY KEY(user_id, friend_user_id) - ) ENGINE = InnoDB; - ALTER TABLE friends ADD FOREIGN KEY (user_id) REFERENCES User(id); - ALTER TABLE friends ADD FOREIGN KEY (friend_user_id) REFERENCES User(id); - -.. _association_mapping_defaults: - -Mapping Defaults ----------------- - -The ``@JoinColumn`` and ``@JoinTable`` definitions are usually optional and have -sensible default values. The defaults for a join column in a -one-to-one/many-to-one association is as follows: - -:: - - name: "_id" - referencedColumnName: "id" - -As an example, consider this mapping: - -.. configuration-block:: - - .. code-block:: php - - - - - - - - .. code-block:: yaml - - Product: - type: entity - oneToOne: - shipment: - targetEntity: Shipment - -This is essentially the same as the following, more verbose, -mapping: - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - .. code-block:: yaml - - Product: - type: entity - oneToOne: - shipment: - targetEntity: Shipment - joinColumn: - name: shipment_id - referencedColumnName: id - -The @JoinTable definition used for many-to-many mappings has -similar defaults. As an example, consider this mapping: - -.. configuration-block:: - - .. code-block:: php - - - - - - - - .. code-block:: yaml - - User: - type: entity - manyToMany: - groups: - targetEntity: Group - -This is essentially the same as the following, more verbose, mapping: - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - - - - - - - - .. code-block:: yaml - - User: - type: entity - manyToMany: - groups: - targetEntity: Group - joinTable: - name: User_Group - joinColumns: - User_id: - referencedColumnName: id - inverseJoinColumns: - Group_id: - referencedColumnName: id - -In that case, the name of the join table defaults to a combination -of the simple, unqualified class names of the participating -classes, separated by an underscore character. The names of the -join columns default to the simple, unqualified class name of the -targeted class followed by "\_id". The referencedColumnName always -defaults to "id", just as in one-to-one or many-to-one mappings. - -If you accept these defaults, you can reduce the mapping code to a -minimum. - -.. _collections: - -Collections ------------ - -Unfortunately, PHP arrays, while being great for many things, are missing -features that make them suitable for lazy loading in the context of an ORM. -This is why in all the examples of many-valued associations in this manual we -will make use of a ``Collection`` interface and its -default implementation ``ArrayCollection`` that are both defined in the -``Doctrine\Common\Collections`` namespace. A collection implements -the PHP interfaces ``ArrayAccess``, ``Traversable`` and ``Countable``. - -.. note:: - - The Collection interface and ArrayCollection class, - like everything else in the Doctrine namespace, are neither part of - the ORM, nor the DBAL, it is a plain PHP class that has no outside - dependencies apart from dependencies on PHP itself (and the SPL). - Therefore using this class in your model and elsewhere - does not introduce a coupling to the ORM. - -Initializing Collections ------------------------- - -You should always initialize the collections of your ``@OneToMany`` -and ``@ManyToMany`` associations in the constructor of your entities: - -.. code-block:: php - - groups = new ArrayCollection(); - } - - public function getGroups() - { - return $this->groups; - } - } - -The following code will then work even if the Entity hasn't -been associated with an EntityManager yet: - -.. code-block:: php - - getGroups()->add($group); diff --git a/vendor/doctrine/orm/docs/en/reference/basic-mapping.rst b/vendor/doctrine/orm/docs/en/reference/basic-mapping.rst deleted file mode 100644 index 91a8fef..0000000 --- a/vendor/doctrine/orm/docs/en/reference/basic-mapping.rst +++ /dev/null @@ -1,504 +0,0 @@ -Basic Mapping -============= - -This guide explains the basic mapping of entities and properties. -After working through this guide you should know: - -- How to create PHP objects that can be saved to the database with Doctrine; -- How to configure the mapping between columns on tables and properties on - entities; -- What Doctrine mapping types are; -- Defining primary keys and how identifiers are generated by Doctrine; -- How quoting of reserved symbols works in Doctrine. - -Mapping of associations will be covered in the next chapter on -:doc:`Association Mapping `. - -Guide Assumptions ------------------ - -You should have already :doc:`installed and configure ` -Doctrine. - -Creating Classes for the Database ---------------------------------- - -Every PHP object that you want to save in the database using Doctrine -is called an "Entity". The term "Entity" describes objects -that have an identity over many independent requests. This identity is -usually achieved by assigning a unique identifier to an entity. -In this tutorial the following ``Message`` PHP class will serve as the -example Entity: - -.. code-block:: php - - ` -- :doc:`XML ` -- :doc:`YAML ` -- :doc:`PHP code ` - -This manual will usually show mapping metadata via docblock annotations, though -many examples also show the equivalent configuration in YAML and XML. - -.. note:: - - All metadata drivers perform equally. Once the metadata of a class has been - read from the source (annotations, xml or yaml) it is stored in an instance - of the ``Doctrine\ORM\Mapping\ClassMetadata`` class and these instances are - stored in the metadata cache. If you're not using a metadata cache (not - recommended!) then the XML driver is the fastest. - -Marking our ``Message`` class as an entity for Doctrine is straightforward: - -.. configuration-block:: - - .. code-block:: php - - - - - - - - .. code-block:: yaml - - Message: - type: entity - # ... - -With no additional information, Doctrine expects the entity to be saved -into a table with the same name as the class in our case ``Message``. -You can change this by configuring information about the table: - -.. configuration-block:: - - .. code-block:: php - - - - - - - - .. code-block:: yaml - - Message: - type: entity - table: message - # ... - -Now the class ``Message`` will be saved and fetched from the table ``message``. - -Property Mapping ----------------- - -The next step after marking a PHP class as an entity is mapping its properties -to columns in a table. - -To configure a property use the ``@Column`` docblock annotation. The ``type`` -attribute specifies the :ref:`Doctrine Mapping Type ` -to use for the field. If the type is not specified, ``string`` is used as the -default. - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - .. code-block:: yaml - - Message: - type: entity - fields: - id: - type: integer - text: - length: 140 - postedAt: - type: datetime - column: posted_at - -When we don't explicitly specify a column name via the ``name`` option, Doctrine -assumes the field name is also the column name. This means that: - -* the ``id`` property will map to the column ``id`` using the type ``integer``; -* the ``text`` property will map to the column ``text`` with the default mapping type ``string``; -* the ``postedAt`` property will map to the ``posted_at`` column with the ``datetime`` type. - -The Column annotation has some more attributes. Here is a complete -list: - -- ``type``: (optional, defaults to 'string') The mapping type to - use for the column. -- ``name``: (optional, defaults to field name) The name of the - column in the database. -- ``length``: (optional, default 255) The length of the column in - the database. (Applies only if a string-valued column is used). -- ``unique``: (optional, default FALSE) Whether the column is a - unique key. -- ``nullable``: (optional, default FALSE) Whether the database - column is nullable. -- ``precision``: (optional, default 0) The precision for a decimal - (exact numeric) column (applies only for decimal column), - which is the maximum number of digits that are stored for the values. -- ``scale``: (optional, default 0) The scale for a decimal (exact - numeric) column (applies only for decimal column), which represents - the number of digits to the right of the decimal point and must - not be greater than *precision*. -- ``columnDefinition``: (optional) Allows to define a custom - DDL snippet that is used to create the column. Warning: This normally - confuses the SchemaTool to always detect the column as changed. -- ``options``: (optional) Key-value pairs of options that get passed - to the underlying database platform when generating DDL statements. - -.. _reference-mapping-types: - -Doctrine Mapping Types ----------------------- - -The ``type`` option used in the ``@Column`` accepts any of the existing -Doctrine types or even your own custom types. A Doctrine type defines -the conversion between PHP and SQL types, independent from the database vendor -you are using. All Mapping Types that ship with Doctrine are fully portable -between the supported database systems. - -As an example, the Doctrine Mapping Type ``string`` defines the -mapping from a PHP string to a SQL VARCHAR (or VARCHAR2 etc. -depending on the RDBMS brand). Here is a quick overview of the -built-in mapping types: - -- ``string``: Type that maps a SQL VARCHAR to a PHP string. -- ``integer``: Type that maps a SQL INT to a PHP integer. -- ``smallint``: Type that maps a database SMALLINT to a PHP - integer. -- ``bigint``: Type that maps a database BIGINT to a PHP string. -- ``boolean``: Type that maps a SQL boolean or equivalent (TINYINT) to a PHP boolean. -- ``decimal``: Type that maps a SQL DECIMAL to a PHP string. -- ``date``: Type that maps a SQL DATETIME to a PHP DateTime - object. -- ``time``: Type that maps a SQL TIME to a PHP DateTime object. -- ``datetime``: Type that maps a SQL DATETIME/TIMESTAMP to a PHP - DateTime object. -- ``datetimetz``: Type that maps a SQL DATETIME/TIMESTAMP to a PHP - DateTime object with timezone. -- ``text``: Type that maps a SQL CLOB to a PHP string. -- ``object``: Type that maps a SQL CLOB to a PHP object using - ``serialize()`` and ``unserialize()`` -- ``array``: Type that maps a SQL CLOB to a PHP array using - ``serialize()`` and ``unserialize()`` -- ``simple_array``: Type that maps a SQL CLOB to a PHP array using - ``implode()`` and ``explode()``, with a comma as delimiter. *IMPORTANT* - Only use this type if you are sure that your values cannot contain a ",". -- ``json_array``: Type that maps a SQL CLOB to a PHP array using - ``json_encode()`` and ``json_decode()`` -- ``float``: Type that maps a SQL Float (Double Precision) to a - PHP double. *IMPORTANT*: Works only with locale settings that use - decimal points as separator. -- ``guid``: Type that maps a database GUID/UUID to a PHP string. Defaults to - varchar but uses a specific type if the platform supports it. -- ``blob``: Type that maps a SQL BLOB to a PHP resource stream - -A cookbook article shows how to define :doc:`your own custom mapping types -<../cookbook/custom-mapping-types>`. - -.. note:: - - DateTime and Object types are compared by reference, not by value. Doctrine - updates this values if the reference changes and therefore behaves as if - these objects are immutable value objects. - -.. warning:: - - All Date types assume that you are exclusively using the default timezone - set by `date_default_timezone_set() `_ - or by the php.ini configuration ``date.timezone``. Working with - different timezones will cause troubles and unexpected behavior. - - If you need specific timezone handling you have to handle this - in your domain, converting all the values back and forth from UTC. - There is also a :doc:`cookbook entry <../cookbook/working-with-datetime>` - on working with datetimes that gives hints for implementing - multi timezone applications. - -Identifiers / Primary Keys --------------------------- - -Every entity class must have an identifier/primary key. You can select -the field that serves as the identifier with the ``@Id`` -annotation. - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - - .. code-block:: yaml - - Message: - type: entity - id: - id: - type: integer - generator: - strategy: AUTO - fields: - # fields here - -In most cases using the automatic generator strategy (``@GeneratedValue``) is -what you want. It defaults to the identifier generation mechanism your current -database vendor prefers: AUTO_INCREMENT with MySQL, SERIAL with PostgreSQL, -Sequences with Oracle and so on. - -Identifier Generation Strategies -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The previous example showed how to use the default identifier -generation strategy without knowing the underlying database with -the AUTO-detection strategy. It is also possible to specify the -identifier generation strategy more explicitly, which allows you to -make use of some additional features. - -Here is the list of possible generation strategies: - -- ``AUTO`` (default): Tells Doctrine to pick the strategy that is - preferred by the used database platform. The preferred strategies - are IDENTITY for MySQL, SQLite, MsSQL and SQL Anywhere and SEQUENCE - for Oracle and PostgreSQL. This strategy provides full portability. -- ``SEQUENCE``: Tells Doctrine to use a database sequence for ID - generation. This strategy does currently not provide full - portability. Sequences are supported by Oracle, PostgreSql and - SQL Anywhere. -- ``IDENTITY``: Tells Doctrine to use special identity columns in - the database that generate a value on insertion of a row. This - strategy does currently not provide full portability and is - supported by the following platforms: MySQL/SQLite/SQL Anywhere - (AUTO\_INCREMENT), MSSQL (IDENTITY) and PostgreSQL (SERIAL). -- ``UUID``: Tells Doctrine to use the built-in Universally Unique Identifier - generator. This strategy provides full portability. -- ``TABLE``: Tells Doctrine to use a separate table for ID - generation. This strategy provides full portability. - ***This strategy is not yet implemented!*** -- ``NONE``: Tells Doctrine that the identifiers are assigned (and - thus generated) by your code. The assignment must take place before - a new entity is passed to ``EntityManager#persist``. NONE is the - same as leaving off the @GeneratedValue entirely. -- ``CUSTOM``: With this option, you can use the ``@CustomIdGenerator`` annotation. - It will allow you to pass a :doc:`class of your own to generate the identifiers.<_annref_customidgenerator>` - -Sequence Generator -^^^^^^^^^^^^^^^^^^ - -The Sequence Generator can currently be used in conjunction with -Oracle or Postgres and allows some additional configuration options -besides specifying the sequence's name: - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - - .. code-block:: yaml - - Message: - type: entity - id: - id: - type: integer - generator: - strategy: SEQUENCE - sequenceGenerator: - sequenceName: message_seq - allocationSize: 100 - initialValue: 1 - -The initial value specifies at which value the sequence should -start. - -The allocationSize is a powerful feature to optimize INSERT -performance of Doctrine. The allocationSize specifies by how much -values the sequence is incremented whenever the next value is -retrieved. If this is larger than 1 (one) Doctrine can generate -identifier values for the allocationSizes amount of entities. In -the above example with ``allocationSize=100`` Doctrine 2 would only -need to access the sequence once to generate the identifiers for -100 new entities. - -*The default allocationSize for a @SequenceGenerator is currently 10.* - -.. caution:: - - The allocationSize is detected by SchemaTool and - transformed into an "INCREMENT BY " clause in the CREATE SEQUENCE - statement. For a database schema created manually (and not - SchemaTool) you have to make sure that the allocationSize - configuration option is never larger than the actual sequences - INCREMENT BY value, otherwise you may get duplicate keys. - - -.. note:: - - It is possible to use strategy="AUTO" and at the same time - specifying a @SequenceGenerator. In such a case, your custom - sequence settings are used in the case where the preferred strategy - of the underlying platform is SEQUENCE, such as for Oracle and - PostgreSQL. - - -Composite Keys -~~~~~~~~~~~~~~ - -With Doctrine 2 you can use composite primary keys, using ``@Id`` on more then -one column. Some restrictions exist opposed to using a single identifier in -this case: The use of the ``@GeneratedValue`` annotation is not supported, -which means you can only use composite keys if you generate the primary key -values yourself before calling ``EntityManager#persist()`` on the entity. - -More details on composite primary keys are discussed in a :doc:`dedicated tutorial -<../tutorials/composite-primary-keys>`. - -Quoting Reserved Words ----------------------- - -Sometimes it is necessary to quote a column or table name because of reserved -word conflicts. Doctrine does not quote identifiers automatically, because it -leads to more problems than it would solve. Quoting tables and column names -needs to be done explicitly using ticks in the definition. - -.. code-block:: php - - setQuoteStrategy(new AnsiQuoteStrategy()); diff --git a/vendor/doctrine/orm/docs/en/reference/batch-processing.rst b/vendor/doctrine/orm/docs/en/reference/batch-processing.rst deleted file mode 100644 index e238516..0000000 --- a/vendor/doctrine/orm/docs/en/reference/batch-processing.rst +++ /dev/null @@ -1,196 +0,0 @@ -Batch Processing -================ - -This chapter shows you how to accomplish bulk inserts, updates and -deletes with Doctrine in an efficient way. The main problem with -bulk operations is usually not to run out of memory and this is -especially what the strategies presented here provide help with. - -.. warning:: - - An ORM tool is not primarily well-suited for mass - inserts, updates or deletions. Every RDBMS has its own, most - effective way of dealing with such operations and if the options - outlined below are not sufficient for your purposes we recommend - you use the tools for your particular RDBMS for these bulk - operations. - - -.. note:: - - Having an SQL logger enabled when processing batches can have a serious impact on performance and resource usage. - To avoid that you should disable it in the DBAL configuration: -.. code-block:: php - - getConnection()->getConfiguration()->setSQLLogger(null); - -Bulk Inserts ------------- - -Bulk inserts in Doctrine are best performed in batches, taking -advantage of the transactional write-behind behavior of an -``EntityManager``. The following code shows an example for -inserting 10000 objects with a batch size of 20. You may need to -experiment with the batch size to find the size that works best for -you. Larger batch sizes mean more prepared statement reuse -internally but also mean more work during ``flush``. - -.. code-block:: php - - setStatus('user'); - $user->setUsername('user' . $i); - $user->setName('Mr.Smith-' . $i); - $em->persist($user); - if (($i % $batchSize) === 0) { - $em->flush(); - $em->clear(); // Detaches all objects from Doctrine! - } - } - $em->flush(); //Persist objects that did not make up an entire batch - $em->clear(); - -Bulk Updates ------------- - -There are 2 possibilities for bulk updates with Doctrine. - -DQL UPDATE -~~~~~~~~~~ - -The by far most efficient way for bulk updates is to use a DQL -UPDATE query. Example: - -.. code-block:: php - - createQuery('update MyProject\Model\Manager m set m.salary = m.salary * 0.9'); - $numUpdated = $q->execute(); - -Iterating results -~~~~~~~~~~~~~~~~~ - -An alternative solution for bulk updates is to use the -``Query#iterate()`` facility to iterate over the query results step -by step instead of loading the whole result into memory at once. -The following example shows how to do this, combining the iteration -with the batching strategy that was already used for bulk inserts: - -.. code-block:: php - - createQuery('select u from MyProject\Model\User u'); - $iterableResult = $q->iterate(); - foreach ($iterableResult as $row) { - $user = $row[0]; - $user->increaseCredit(); - $user->calculateNewBonuses(); - if (($i % $batchSize) === 0) { - $em->flush(); // Executes all updates. - $em->clear(); // Detaches all objects from Doctrine! - } - ++$i; - } - $em->flush(); - -.. note:: - - Iterating results is not possible with queries that - fetch-join a collection-valued association. The nature of such SQL - result sets is not suitable for incremental hydration. - -.. note:: - - Results may be fully buffered by the database client/ connection allocating - additional memory not visible to the PHP process. For large sets this - may easily kill the process for no apparent reason. - - -Bulk Deletes ------------- - -There are two possibilities for bulk deletes with Doctrine. You can -either issue a single DQL DELETE query or you can iterate over -results removing them one at a time. - -DQL DELETE -~~~~~~~~~~ - -The by far most efficient way for bulk deletes is to use a DQL -DELETE query. - -Example: - -.. code-block:: php - - createQuery('delete from MyProject\Model\Manager m where m.salary > 100000'); - $numDeleted = $q->execute(); - -Iterating results -~~~~~~~~~~~~~~~~~ - -An alternative solution for bulk deletes is to use the -``Query#iterate()`` facility to iterate over the query results step -by step instead of loading the whole result into memory at once. -The following example shows how to do this: - -.. code-block:: php - - createQuery('select u from MyProject\Model\User u'); - $iterableResult = $q->iterate(); - while (($row = $iterableResult->next()) !== false) { - $em->remove($row[0]); - if (($i % $batchSize) === 0) { - $em->flush(); // Executes all deletions. - $em->clear(); // Detaches all objects from Doctrine! - } - ++$i; - } - $em->flush(); - -.. note:: - - Iterating results is not possible with queries that - fetch-join a collection-valued association. The nature of such SQL - result sets is not suitable for incremental hydration. - - -Iterating Large Results for Data-Processing -------------------------------------------- - -You can use the ``iterate()`` method just to iterate over a large -result and no UPDATE or DELETE intention. The ``IterableResult`` -instance returned from ``$query->iterate()`` implements the -Iterator interface so you can process a large result without memory -problems using the following approach: - -.. code-block:: php - - _em->createQuery('select u from MyProject\Model\User u'); - $iterableResult = $q->iterate(); - foreach ($iterableResult as $row) { - // do stuff with the data in the row, $row[0] is always the object - - // detach from Doctrine, so that it can be Garbage-Collected immediately - $this->_em->detach($row[0]); - } - -.. note:: - - Iterating results is not possible with queries that - fetch-join a collection-valued association. The nature of such SQL - result sets is not suitable for incremental hydration. - - - diff --git a/vendor/doctrine/orm/docs/en/reference/best-practices.rst b/vendor/doctrine/orm/docs/en/reference/best-practices.rst deleted file mode 100644 index 256ee53..0000000 --- a/vendor/doctrine/orm/docs/en/reference/best-practices.rst +++ /dev/null @@ -1,111 +0,0 @@ -Best Practices -============== - -The best practices mentioned here that affect database -design generally refer to best practices when working with Doctrine -and do not necessarily reflect best practices for database design -in general. - -Constrain relationships as much as possible -------------------------------------------- - -It is important to constrain relationships as much as possible. -This means: - - -- Impose a traversal direction (avoid bidirectional associations - if possible) -- Eliminate nonessential associations - -This has several benefits: - - -- Reduced coupling in your domain model -- Simpler code in your domain model (no need to maintain - bidirectionality properly) -- Less work for Doctrine - -Avoid composite keys --------------------- - -Even though Doctrine fully supports composite keys it is best not -to use them if possible. Composite keys require additional work by -Doctrine and thus have a higher probability of errors. - -Use events judiciously ----------------------- - -The event system of Doctrine is great and fast. Even though making -heavy use of events, especially lifecycle events, can have a -negative impact on the performance of your application. Thus you -should use events judiciously. - -Use cascades judiciously ------------------------- - -Automatic cascades of the persist/remove/merge/etc. operations are -very handy but should be used wisely. Do NOT simply add all -cascades to all associations. Think about which cascades actually -do make sense for you for a particular association, given the -scenarios it is most likely used in. - -Don't use special characters ----------------------------- - -Avoid using any non-ASCII characters in class, field, table or -column names. Doctrine itself is not unicode-safe in many places -and will not be until PHP itself is fully unicode-aware. - -Don't use identifier quoting ----------------------------- - -Identifier quoting is a workaround for using reserved words that -often causes problems in edge cases. Do not use identifier quoting -and avoid using reserved words as table or column names. - -Initialize collections in the constructor ------------------------------------------ - -It is recommended best practice to initialize any business -collections in entities in the constructor. Example: - -.. code-block:: php - - addresses = new ArrayCollection; - $this->articles = new ArrayCollection; - } - } - -Don't map foreign keys to fields in an entity ---------------------------------------------- - -Foreign keys have no meaning whatsoever in an object model. Foreign -keys are how a relational database establishes relationships. Your -object model establishes relationships through object references. -Thus mapping foreign keys to object fields heavily leaks details of -the relational model into the object model, something you really -should not do. - -Use explicit transaction demarcation ------------------------------------- - -While Doctrine will automatically wrap all DML operations in a -transaction on flush(), it is considered best practice to -explicitly set the transaction boundaries yourself. Otherwise every -single query is wrapped in a small transaction (Yes, SELECT -queries, too) since you can not talk to your database outside of a -transaction. While such short transactions for read-only (SELECT) -queries generally don't have any noticeable performance impact, it -is still preferable to use fewer, well-defined transactions that -are established through explicit transaction boundaries. - - diff --git a/vendor/doctrine/orm/docs/en/reference/caching.rst b/vendor/doctrine/orm/docs/en/reference/caching.rst deleted file mode 100644 index 4c07e16..0000000 --- a/vendor/doctrine/orm/docs/en/reference/caching.rst +++ /dev/null @@ -1,477 +0,0 @@ -Caching -======= - -Doctrine provides cache drivers in the ``Common`` package for some -of the most popular caching implementations such as APC, Memcache -and Xcache. We also provide an ``ArrayCache`` driver which stores -the data in a PHP array. Obviously, when using ``ArrayCache``, the -cache does not persist between requests, but this is useful for -testing in a development environment. - -Cache Drivers -------------- - -The cache drivers follow a simple interface that is defined in -``Doctrine\Common\Cache\Cache``. All the cache drivers extend a -base class ``Doctrine\Common\Cache\CacheProvider`` which implements -this interface. - -The interface defines the following public methods for you to implement: - - -- fetch($id) - Fetches an entry from the cache -- contains($id) - Test if an entry exists in the cache -- save($id, $data, $lifeTime = false) - Puts data into the cache for x seconds. 0 = infinite time -- delete($id) - Deletes a cache entry - -Each driver extends the ``CacheProvider`` class which defines a few -abstract protected methods that each of the drivers must -implement: - - -- doFetch($id) -- doContains($id) -- doSave($id, $data, $lifeTime = false) -- doDelete($id) - -The public methods ``fetch()``, ``contains()`` etc. use the -above protected methods which are implemented by the drivers. The -code is organized this way so that the protected methods in the -drivers do the raw interaction with the cache implementation and -the ``CacheProvider`` can build custom functionality on top of -these methods. - -This documentation does not cover every single cache driver included -with Doctrine. For an up-to-date-list, see the -`cache directory on GitHub `_. - -APC -~~~ - -In order to use the APC cache driver you must have it compiled and -enabled in your php.ini. You can read about APC -`in the PHP Documentation `_. It will give -you a little background information about what it is and how you -can use it as well as how to install it. - -Below is a simple example of how you could use the APC cache driver -by itself. - -.. code-block:: php - - save('cache_id', 'my_data'); - -APCu -~~~~ - -In order to use the APCu cache driver you must have it compiled and -enabled in your php.ini. You can read about APCu -`in the PHP Documentation `_. It will give -you a little background information about what it is and how you -can use it as well as how to install it. - -Below is a simple example of how you could use the APCu cache driver -by itself. - -.. code-block:: php - - save('cache_id', 'my_data'); - -Memcache -~~~~~~~~ - -In order to use the Memcache cache driver you must have it compiled -and enabled in your php.ini. You can read about Memcache -`on the PHP website `_. It will -give you a little background information about what it is and how -you can use it as well as how to install it. - -Below is a simple example of how you could use the Memcache cache -driver by itself. - -.. code-block:: php - - connect('memcache_host', 11211); - - $cacheDriver = new \Doctrine\Common\Cache\MemcacheCache(); - $cacheDriver->setMemcache($memcache); - $cacheDriver->save('cache_id', 'my_data'); - -Memcached -~~~~~~~~~ - -Memcached is a more recent and complete alternative extension to -Memcache. - -In order to use the Memcached cache driver you must have it compiled -and enabled in your php.ini. You can read about Memcached -`on the PHP website `_. It will -give you a little background information about what it is and how -you can use it as well as how to install it. - -Below is a simple example of how you could use the Memcached cache -driver by itself. - -.. code-block:: php - - addServer('memcache_host', 11211); - - $cacheDriver = new \Doctrine\Common\Cache\MemcachedCache(); - $cacheDriver->setMemcached($memcached); - $cacheDriver->save('cache_id', 'my_data'); - -Xcache -~~~~~~ - -In order to use the Xcache cache driver you must have it compiled -and enabled in your php.ini. You can read about Xcache -`here `_. It will give you a little -background information about what it is and how you can use it as -well as how to install it. - -Below is a simple example of how you could use the Xcache cache -driver by itself. - -.. code-block:: php - - save('cache_id', 'my_data'); - -Redis -~~~~~ - -In order to use the Redis cache driver you must have it compiled -and enabled in your php.ini. You can read about what Redis is -`from here `_. Also check -`A PHP extension for Redis `_ for how you can use -and install the Redis PHP extension. - -Below is a simple example of how you could use the Redis cache -driver by itself. - -.. code-block:: php - - connect('redis_host', 6379); - - $cacheDriver = new \Doctrine\Common\Cache\RedisCache(); - $cacheDriver->setRedis($redis); - $cacheDriver->save('cache_id', 'my_data'); - -Using Cache Drivers -------------------- - -In this section we'll describe how you can fully utilize the API of -the cache drivers to save data to a cache, check if some cached data -exists, fetch the cached data and delete the cached data. We'll use the -``ArrayCache`` implementation as our example here. - -.. code-block:: php - - save('cache_id', 'my_data'); - -The ``save()`` method accepts three arguments which are described -below: - - -- ``$id`` - The cache id -- ``$data`` - The cache entry/data. -- ``$lifeTime`` - The lifetime. If != false, sets a specific - lifetime for this cache entry (null => infinite lifeTime). - -You can save any type of data whether it be a string, array, -object, etc. - -.. code-block:: php - - 'value1', - 'key2' => 'value2' - ); - $cacheDriver->save('my_array', $array); - -Checking -~~~~~~~~ - -Checking whether cached data exists is very simple: just use the -``contains()`` method. It accepts a single argument which is the ID -of the cache entry. - -.. code-block:: php - - contains('cache_id')) { - echo 'cache exists'; - } else { - echo 'cache does not exist'; - } - -Fetching -~~~~~~~~ - -Now if you want to retrieve some cache entry you can use the -``fetch()`` method. It also accepts a single argument just like -``contains()`` which is again the ID of the cache entry. - -.. code-block:: php - - fetch('my_array'); - -Deleting -~~~~~~~~ - -As you might guess, deleting is just as easy as saving, checking -and fetching. You can delete by an individual ID, or you can -delete all entries. - -By Cache ID -^^^^^^^^^^^ - -.. code-block:: php - - delete('my_array'); - -All -^^^ - -If you simply want to delete all cache entries you can do so with -the ``deleteAll()`` method. - -.. code-block:: php - - deleteAll(); - -Namespaces -~~~~~~~~~~ - -If you heavily use caching in your application and use it in -multiple parts of your application, or use it in different -applications on the same server you may have issues with cache -naming collisions. This can be worked around by using namespaces. -You can set the namespace a cache driver should use by using the -``setNamespace()`` method. - -.. code-block:: php - - setNamespace('my_namespace_'); - -.. _integrating-with-the-orm: - -Integrating with the ORM ------------------------- - -The Doctrine ORM package is tightly integrated with the cache -drivers to allow you to improve the performance of various aspects of -Doctrine by simply making some additional configurations and -method calls. - -Query Cache -~~~~~~~~~~~ - -It is highly recommended that in a production environment you cache -the transformation of a DQL query to its SQL counterpart. It -doesn't make sense to do this parsing multiple times as it doesn't -change unless you alter the DQL query. - -This can be done by configuring the query cache implementation to -use on your ORM configuration. - -.. code-block:: php - - setQueryCacheImpl(new \Doctrine\Common\Cache\ApcuCache()); - -Result Cache -~~~~~~~~~~~~ - -The result cache can be used to cache the results of your queries -so that we don't have to query the database or hydrate the data -again after the first time. You just need to configure the result -cache implementation. - -.. code-block:: php - - setResultCacheImpl(new \Doctrine\Common\Cache\ApcuCache()); - -Now when you're executing DQL queries you can configure them to use -the result cache. - -.. code-block:: php - - createQuery('select u from \Entities\User u'); - $query->useResultCache(true); - -You can also configure an individual query to use a different -result cache driver. - -.. code-block:: php - - setResultCacheDriver(new \Doctrine\Common\Cache\ApcuCache()); - -.. note:: - - Setting the result cache driver on the query will - automatically enable the result cache for the query. If you want to - disable it pass false to ``useResultCache()``. - - :: - - useResultCache(false); - - -If you want to set the time the cache has to live you can use the -``setResultCacheLifetime()`` method. - -.. code-block:: php - - setResultCacheLifetime(3600); - -The ID used to store the result set cache is a hash which is -automatically generated for you if you don't set a custom ID -yourself with the ``setResultCacheId()`` method. - -.. code-block:: php - - setResultCacheId('my_custom_id'); - -You can also set the lifetime and cache ID by passing the values as -the second and third argument to ``useResultCache()``. - -.. code-block:: php - - useResultCache(true, 3600, 'my_custom_id'); - -Metadata Cache -~~~~~~~~~~~~~~ - -Your class metadata can be parsed from a few different sources like -YAML, XML, Annotations, etc. Instead of parsing this information on -each request we should cache it using one of the cache drivers. - -Just like the query and result cache we need to configure it -first. - -.. code-block:: php - - setMetadataCacheImpl(new \Doctrine\Common\Cache\ApcuCache()); - -Now the metadata information will only be parsed once and stored in -the cache driver. - -Clearing the Cache ------------------- - -We've already shown you how you can use the API of the -cache drivers to manually delete cache entries. For your -convenience we offer command line tasks to help you with -clearing the query, result and metadata cache. - -From the Doctrine command line you can run the following commands: - -To clear the query cache use the ``orm:clear-cache:query`` task. - -.. code-block:: php - - $ ./doctrine orm:clear-cache:query - -To clear the metadata cache use the ``orm:clear-cache:metadata`` task. - -.. code-block:: php - - $ ./doctrine orm:clear-cache:metadata - -To clear the result cache use the ``orm:clear-cache:result`` task. - -.. code-block:: php - - $ ./doctrine orm:clear-cache:result - -All these tasks accept a ``--flush`` option to flush the entire -contents of the cache instead of invalidating the entries. - -Cache Chaining --------------- - -A common pattern is to use a static cache to store data that is -requested many times in a single PHP request. Even though this data -may be stored in a fast memory cache, often that cache is over a -network link leading to sizable network traffic. - -The ChainCache class allows multiple caches to be registered at once. -For example, a per-request ArrayCache can be used first, followed by -a (relatively) slower MemcacheCache if the ArrayCache misses. -ChainCache automatically handles pushing data up to faster caches in -the chain and clearing data in the entire stack when it is deleted. - -A ChainCache takes a simple array of CacheProviders in the order that -they should be used. - -.. code-block:: php - - $arrayCache = new \Doctrine\Common\Cache\ArrayCache(); - $memcache = new Memcache(); - $memcache->connect('memcache_host', 11211); - $chainCache = new \Doctrine\Common\Cache\ChainCache([ - $arrayCache, - $memcache, - ]); - -ChainCache itself extends the CacheProvider interface, so it is -possible to create chains of chains. While this may seem like an easy -way to build a simple high-availability cache, ChainCache does not -implement any exception handling so using it as a high-availability -mechanism is not recommended. - -Cache Slams ------------ - -Something to be careful of when using the cache drivers is -"cache slams". Imagine you have a heavily trafficked website with some -code that checks for the existence of a cache record and if it does -not exist it generates the information and saves it to the cache. -Now, if 100 requests were issued all at the same time and each one -sees the cache does not exist and they all try to insert the same -cache entry it could lock up APC, Xcache, etc. and cause problems. -Ways exist to work around this, like pre-populating your cache and -not letting your users' requests populate the cache. - -You can read more about cache slams -`in this blog post `_. - - diff --git a/vendor/doctrine/orm/docs/en/reference/change-tracking-policies.rst b/vendor/doctrine/orm/docs/en/reference/change-tracking-policies.rst deleted file mode 100644 index d0f0998..0000000 --- a/vendor/doctrine/orm/docs/en/reference/change-tracking-policies.rst +++ /dev/null @@ -1,151 +0,0 @@ -Change Tracking Policies -======================== - -Change tracking is the process of determining what has changed in -managed entities since the last time they were synchronized with -the database. - -Doctrine provides 3 different change tracking policies, each having -its particular advantages and disadvantages. The change tracking -policy can be defined on a per-class basis (or more precisely, -per-hierarchy). - -Deferred Implicit -~~~~~~~~~~~~~~~~~ - -The deferred implicit policy is the default change tracking policy -and the most convenient one. With this policy, Doctrine detects the -changes by a property-by-property comparison at commit time and -also detects changes to entities or new entities that are -referenced by other managed entities ("persistence by -reachability"). Although the most convenient policy, it can have -negative effects on performance if you are dealing with large units -of work (see "Understanding the Unit of Work"). Since Doctrine -can't know what has changed, it needs to check all managed entities -for changes every time you invoke EntityManager#flush(), making -this operation rather costly. - -Deferred Explicit -~~~~~~~~~~~~~~~~~ - -The deferred explicit policy is similar to the deferred implicit -policy in that it detects changes through a property-by-property -comparison at commit time. The difference is that Doctrine 2 only -considers entities that have been explicitly marked for change detection -through a call to EntityManager#persist(entity) or through a save -cascade. All other entities are skipped. This policy therefore -gives improved performance for larger units of work while -sacrificing the behavior of "automatic dirty checking". - -Therefore, flush() operations are potentially cheaper with this -policy. The negative aspect this has is that if you have a rather -large application and you pass your objects through several layers -for processing purposes and business tasks you may need to track -yourself which entities have changed on the way so you can pass -them to EntityManager#persist(). - -This policy can be configured as follows: - -.. code-block:: php - - _listeners[] = $listener; - } - } - -Then, in each property setter of this class or derived classes, you -need to notify all the ``PropertyChangedListener`` instances. As an -example we add a convenience method on ``MyEntity`` that shows this -behaviour: - -.. code-block:: php - - _listeners) { - foreach ($this->_listeners as $listener) { - $listener->propertyChanged($this, $propName, $oldValue, $newValue); - } - } - } - - public function setData($data) - { - if ($data != $this->data) { - $this->_onPropertyChanged('data', $this->data, $data); - $this->data = $data; - } - } - } - -You have to invoke ``_onPropertyChanged`` inside every method that -changes the persistent state of ``MyEntity``. - -The check whether the new value is different from the old one is -not mandatory but recommended. That way you also have full control -over when you consider a property changed. - -The negative point of this policy is obvious: You need implement an -interface and write some plumbing code. But also note that we tried -hard to keep this notification functionality abstract. Strictly -speaking, it has nothing to do with the persistence layer and the -Doctrine ORM or DBAL. You may find that property notification -events come in handy in many other scenarios as well. As mentioned -earlier, the ``Doctrine\Common`` namespace is not that evil and -consists solely of very small classes and interfaces that have -almost no external dependencies (none to the DBAL and none to the -ORM) and that you can easily take with you should you want to swap -out the persistence layer. This change tracking policy does not -introduce a dependency on the Doctrine DBAL/ORM or the persistence -layer. - -The positive point and main advantage of this policy is its -effectiveness. It has the best performance characteristics of the 3 -policies with larger units of work and a flush() operation is very -cheap when nothing has changed. - - diff --git a/vendor/doctrine/orm/docs/en/reference/configuration.rst b/vendor/doctrine/orm/docs/en/reference/configuration.rst deleted file mode 100644 index 38775af..0000000 --- a/vendor/doctrine/orm/docs/en/reference/configuration.rst +++ /dev/null @@ -1,144 +0,0 @@ -Installation and Configuration -============================== - -Doctrine can be installed with `Composer `_. - -Define the following requirement in your ``composer.json`` file: - -:: - - { - "require": { - "doctrine/orm": "*" - } - } - -Then call ``composer install`` from your command line. If you don't know -how Composer works, check out their `Getting Started `_ to set up. - -Class loading -------------- - -Autoloading is taken care of by Composer. You just have to include the composer autoload file in your project: - -.. code-block:: php - - 'pdo_mysql', - 'user' => 'root', - 'password' => '', - 'dbname' => 'foo', - ); - - $config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode); - $entityManager = EntityManager::create($dbParams, $config); - -Or if you prefer XML: - -.. code-block:: php - - ` section. - -.. note:: - - You can learn more about the database connection configuration in the - `Doctrine DBAL connection configuration reference `_. - -Setting up the Commandline Tool -------------------------------- - -Doctrine ships with a number of command line tools that are very helpful -during development. You can call this command from the Composer binary -directory: - -.. code-block:: sh - - $ php vendor/bin/doctrine - -You need to register your applications EntityManager to the console tool -to make use of the tasks by creating a ``cli-config.php`` file with the -following content: - -On Doctrine 2.4 and above: - -.. code-block:: php - - new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()), - 'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) - )); diff --git a/vendor/doctrine/orm/docs/en/reference/dql-doctrine-query-language.rst b/vendor/doctrine/orm/docs/en/reference/dql-doctrine-query-language.rst deleted file mode 100644 index 5a38101..0000000 --- a/vendor/doctrine/orm/docs/en/reference/dql-doctrine-query-language.rst +++ /dev/null @@ -1,1775 +0,0 @@ -Doctrine Query Language -=========================== - -DQL stands for Doctrine Query Language and is an Object -Query Language derivative that is very similar to the Hibernate -Query Language (HQL) or the Java Persistence Query Language (JPQL). - -In essence, DQL provides powerful querying capabilities over your -object model. Imagine all your objects lying around in some storage -(like an object database). When writing DQL queries, think about -querying that storage to pick a certain subset of your objects. - -.. note:: - - A common mistake for beginners is to mistake DQL for - being just some form of SQL and therefore trying to use table names - and column names or join arbitrary tables together in a query. You - need to think about DQL as a query language for your object model, - not for your relational schema. - - -DQL is case in-sensitive, except for namespace, class and field -names, which are case sensitive. - -Types of DQL queries --------------------- - -DQL as a query language has SELECT, UPDATE and DELETE constructs -that map to their corresponding SQL statement types. INSERT -statements are not allowed in DQL, because entities and their -relations have to be introduced into the persistence context -through ``EntityManager#persist()`` to ensure consistency of your -object model. - -DQL SELECT statements are a very powerful way of retrieving parts -of your domain model that are not accessible via associations. -Additionally they allow you to retrieve entities and their associations -in one single SQL select statement which can make a huge difference -in performance compared to using several queries. - -DQL UPDATE and DELETE statements offer a way to execute bulk -changes on the entities of your domain model. This is often -necessary when you cannot load all the affected entities of a bulk -update into memory. - -SELECT queries --------------- - -DQL SELECT clause -~~~~~~~~~~~~~~~~~ - -Here is an example that selects all users with an age > 20: - -.. code-block:: php - - createQuery('SELECT u FROM MyProject\Model\User u WHERE u.age > 20'); - $users = $query->getResult(); - -Lets examine the query: - - -- ``u`` is a so called identification variable or alias that - refers to the ``MyProject\Model\User`` class. By placing this alias - in the SELECT clause we specify that we want all instances of the - User class that are matched by this query to appear in the query - result. -- The FROM keyword is always followed by a fully-qualified class - name which in turn is followed by an identification variable or - alias for that class name. This class designates a root of our - query from which we can navigate further via joins (explained - later) and path expressions. -- The expression ``u.age`` in the WHERE clause is a path - expression. Path expressions in DQL are easily identified by the - use of the '.' operator that is used for constructing paths. The - path expression ``u.age`` refers to the ``age`` field on the User - class. - -The result of this query would be a list of User objects where all -users are older than 20. - -Result format -~~~~~~~~~~~~~ -The composition of the expressions in the SELECT clause also -influences the nature of the query result. There are three -cases: - -**All objects** - -.. code-block:: sql - - SELECT u, p, n FROM Users u... - -In this case, the result will be an array of User objects because of -the FROM clause, with children ``p`` and ``n`` hydrated because of -their inclusion in the SELECT clause. - -**All scalars** - -.. code-block:: sql - - SELECT u.name, u.address FROM Users u... - -In this case, the result will be an array of arrays. In the example -above, each element of the result array would be an array of the -scalar name and address values. - -You can select scalars from any entity in the query. - -**Mixed** - -.. code-block:: sql - - SELECT u, p.quantity FROM Users u... - -Here, the result will again be an array of arrays, with each element -being an array made up of a User object and the scalar value -``p.quantity``. - -Multiple FROM clauses are allowed, which would cause the result -array elements to cycle through the classes included in the -multiple FROM clauses. - -.. note:: - - You cannot select other entities unless you also select the - root of the selection (which is the first entity in FROM). - - For example, ``SELECT p,n FROM Users u...`` would be wrong because - ``u`` is not part of the SELECT - - Doctrine throws an exception if you violate this constraint. - - -Joins -~~~~~ - -A SELECT query can contain joins. There are 2 types of JOINs: -"Regular" Joins and "Fetch" Joins. - -**Regular Joins**: Used to limit the results and/or compute -aggregate values. - -**Fetch Joins**: In addition to the uses of regular joins: Used to -fetch related entities and include them in the hydrated result of a -query. - -There is no special DQL keyword that distinguishes a regular join -from a fetch join. A join (be it an inner or outer join) becomes a -"fetch join" as soon as fields of the joined entity appear in the -SELECT part of the DQL query outside of an aggregate function. -Otherwise its a "regular join". - -Example: - -Regular join of the address: - -.. code-block:: php - - createQuery("SELECT u FROM User u JOIN u.address a WHERE a.city = 'Berlin'"); - $users = $query->getResult(); - -Fetch join of the address: - -.. code-block:: php - - createQuery("SELECT u, a FROM User u JOIN u.address a WHERE a.city = 'Berlin'"); - $users = $query->getResult(); - -When Doctrine hydrates a query with fetch-join it returns the class -in the FROM clause on the root level of the result array. In the -previous example an array of User instances is returned and the -address of each user is fetched and hydrated into the -``User#address`` variable. If you access the address Doctrine does -not need to lazy load the association with another query. - -.. note:: - - Doctrine allows you to walk all the associations between - all the objects in your domain model. Objects that were not already - loaded from the database are replaced with lazy load proxy - instances. Non-loaded Collections are also replaced by lazy-load - instances that fetch all the contained objects upon first access. - However relying on the lazy-load mechanism leads to many small - queries executed against the database, which can significantly - affect the performance of your application. **Fetch Joins** are the - solution to hydrate most or all of the entities that you need in a - single SELECT query. - - -Named and Positional Parameters -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -DQL supports both named and positional parameters, however in -contrast to many SQL dialects positional parameters are specified -with numbers, for example "?1", "?2" and so on. Named parameters -are specified with ":name1", ":name2" and so on. - -When referencing the parameters in ``Query#setParameter($param, $value)`` -both named and positional parameters are used **without** their prefixes. - -DQL SELECT Examples -~~~~~~~~~~~~~~~~~~~ - -This section contains a large set of DQL queries and some -explanations of what is happening. The actual result also depends -on the hydration mode. - -Hydrate all User entities: - -.. code-block:: php - - createQuery('SELECT u FROM MyProject\Model\User u'); - $users = $query->getResult(); // array of User objects - -Retrieve the IDs of all CmsUsers: - -.. code-block:: php - - createQuery('SELECT u.id FROM CmsUser u'); - $ids = $query->getResult(); // array of CmsUser ids - -Retrieve the IDs of all users that have written an article: - -.. code-block:: php - - createQuery('SELECT DISTINCT u.id FROM CmsArticle a JOIN a.user u'); - $ids = $query->getResult(); // array of CmsUser ids - -Retrieve all articles and sort them by the name of the articles -users instance: - -.. code-block:: php - - createQuery('SELECT a FROM CmsArticle a JOIN a.user u ORDER BY u.name ASC'); - $articles = $query->getResult(); // array of CmsArticle objects - -Retrieve the Username and Name of a CmsUser: - -.. code-block:: php - - createQuery('SELECT u.username, u.name FROM CmsUser u'); - $users = $query->getResult(); // array of CmsUser username and name values - echo $users[0]['username']; - -Retrieve a ForumUser and his single associated entity: - -.. code-block:: php - - createQuery('SELECT u, a FROM ForumUser u JOIN u.avatar a'); - $users = $query->getResult(); // array of ForumUser objects with the avatar association loaded - echo get_class($users[0]->getAvatar()); - -Retrieve a CmsUser and fetch join all the phonenumbers he has: - -.. code-block:: php - - createQuery('SELECT u, p FROM CmsUser u JOIN u.phonenumbers p'); - $users = $query->getResult(); // array of CmsUser objects with the phonenumbers association loaded - $phonenumbers = $users[0]->getPhonenumbers(); - -Hydrate a result in Ascending: - -.. code-block:: php - - createQuery('SELECT u FROM ForumUser u ORDER BY u.id ASC'); - $users = $query->getResult(); // array of ForumUser objects - -Or in Descending Order: - -.. code-block:: php - - createQuery('SELECT u FROM ForumUser u ORDER BY u.id DESC'); - $users = $query->getResult(); // array of ForumUser objects - -Using Aggregate Functions: - -.. code-block:: php - - createQuery('SELECT COUNT(u.id) FROM Entities\User u'); - $count = $query->getSingleScalarResult(); - - $query = $em->createQuery('SELECT u, count(g.id) FROM Entities\User u JOIN u.groups g GROUP BY u.id'); - $result = $query->getResult(); - -With WHERE Clause and Positional Parameter: - -.. code-block:: php - - createQuery('SELECT u FROM ForumUser u WHERE u.id = ?1'); - $query->setParameter(1, 321); - $users = $query->getResult(); // array of ForumUser objects - -With WHERE Clause and Named Parameter: - -.. code-block:: php - - createQuery('SELECT u FROM ForumUser u WHERE u.username = :name'); - $query->setParameter('name', 'Bob'); - $users = $query->getResult(); // array of ForumUser objects - -With Nested Conditions in WHERE Clause: - -.. code-block:: php - - createQuery('SELECT u FROM ForumUser u WHERE (u.username = :name OR u.username = :name2) AND u.id = :id'); - $query->setParameters(array( - 'name' => 'Bob', - 'name2' => 'Alice', - 'id' => 321, - )); - $users = $query->getResult(); // array of ForumUser objects - -With COUNT DISTINCT: - -.. code-block:: php - - createQuery('SELECT COUNT(DISTINCT u.name) FROM CmsUser'); - $users = $query->getResult(); // array of ForumUser objects - -With Arithmetic Expression in WHERE clause: - -.. code-block:: php - - createQuery('SELECT u FROM CmsUser u WHERE ((u.id + 5000) * u.id + 3) < 10000000'); - $users = $query->getResult(); // array of ForumUser objects - -Retrieve user entities with Arithmetic Expression in ORDER clause, using the ``HIDDEN`` keyword: - -.. code-block:: php - - createQuery('SELECT u, u.posts_count + u.likes_count AS HIDDEN score FROM CmsUser u ORDER BY score'); - $users = $query->getResult(); // array of User objects - -Using a LEFT JOIN to hydrate all user-ids and optionally associated -article-ids: - -.. code-block:: php - - createQuery('SELECT u.id, a.id as article_id FROM CmsUser u LEFT JOIN u.articles a'); - $results = $query->getResult(); // array of user ids and every article_id for each user - -Restricting a JOIN clause by additional conditions specified by -WITH: - -.. code-block:: php - - createQuery("SELECT u FROM CmsUser u LEFT JOIN u.articles a WITH a.topic LIKE :foo"); - $query->setParameter('foo', '%foo%'); - $users = $query->getResult(); - -Using several Fetch JOINs: - -.. code-block:: php - - createQuery('SELECT u, a, p, c FROM CmsUser u JOIN u.articles a JOIN u.phonenumbers p JOIN a.comments c'); - $users = $query->getResult(); - -BETWEEN in WHERE clause: - -.. code-block:: php - - createQuery('SELECT u.name FROM CmsUser u WHERE u.id BETWEEN ?1 AND ?2'); - $query->setParameter(1, 123); - $query->setParameter(2, 321); - $usernames = $query->getResult(); - -DQL Functions in WHERE clause: - -.. code-block:: php - - createQuery("SELECT u.name FROM CmsUser u WHERE TRIM(u.name) = 'someone'"); - $usernames = $query->getResult(); - -IN() Expression: - -.. code-block:: php - - createQuery('SELECT u.name FROM CmsUser u WHERE u.id IN(46)'); - $usernames = $query->getResult(); - - $query = $em->createQuery('SELECT u FROM CmsUser u WHERE u.id IN (1, 2)'); - $users = $query->getResult(); - - $query = $em->createQuery('SELECT u FROM CmsUser u WHERE u.id NOT IN (1)'); - $users = $query->getResult(); - -CONCAT() DQL Function: - -.. code-block:: php - - createQuery("SELECT u.id FROM CmsUser u WHERE CONCAT(u.name, 's') = ?1"); - $query->setParameter(1, 'Jess'); - $ids = $query->getResult(); - - $query = $em->createQuery('SELECT CONCAT(u.id, u.name) FROM CmsUser u WHERE u.id = ?1'); - $query->setParameter(1, 321); - $idUsernames = $query->getResult(); - -EXISTS in WHERE clause with correlated Subquery - -.. code-block:: php - - createQuery('SELECT u.id FROM CmsUser u WHERE EXISTS (SELECT p.phonenumber FROM CmsPhonenumber p WHERE p.user = u.id)'); - $ids = $query->getResult(); - -Get all users who are members of $group. - -.. code-block:: php - - createQuery('SELECT u.id FROM CmsUser u WHERE :groupId MEMBER OF u.groups'); - $query->setParameter('groupId', $group); - $ids = $query->getResult(); - -Get all users that have more than 1 phonenumber - -.. code-block:: php - - createQuery('SELECT u FROM CmsUser u WHERE SIZE(u.phonenumbers) > 1'); - $users = $query->getResult(); - -Get all users that have no phonenumber - -.. code-block:: php - - createQuery('SELECT u FROM CmsUser u WHERE u.phonenumbers IS EMPTY'); - $users = $query->getResult(); - -Get all instances of a specific type, for use with inheritance -hierarchies: - -.. versionadded:: 2.1 - -.. code-block:: php - - createQuery('SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF Doctrine\Tests\Models\Company\CompanyEmployee'); - $query = $em->createQuery('SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u INSTANCE OF ?1'); - $query = $em->createQuery('SELECT u FROM Doctrine\Tests\Models\Company\CompanyPerson u WHERE u NOT INSTANCE OF ?1'); - -Get all users visible on a given website that have chosen certain gender: - -.. versionadded:: 2.2 - -.. code-block:: php - - createQuery('SELECT u FROM User u WHERE u.gender IN (SELECT IDENTITY(agl.gender) FROM Site s JOIN s.activeGenderList agl WHERE s.id = ?1)'); - -.. versionadded:: 2.4 - -Starting with 2.4, the IDENTITY() DQL function also works for composite primary keys: - -.. code-block:: php - - createQuery("SELECT IDENTITY(c.location, 'latitude') AS latitude, IDENTITY(c.location, 'longitude') AS longitude FROM Checkpoint c WHERE c.user = ?1"); - -Joins between entities without associations were not possible until version -2.4, where you can generate an arbitrary join with the following syntax: - -.. code-block:: php - - createQuery('SELECT u FROM User u JOIN Blacklist b WITH u.email = b.email'); - -.. note:: - The differences between WHERE, WITH and HAVING clauses may be - confusing. - - - WHERE is applied to the results of an entire query - - WITH is applied to a join as an additional condition. For - arbitrary joins (SELECT f, b FROM Foo f, Bar b WITH f.id = b.id) - the WITH is required, even if it is 1 = 1 - - HAVING is applied to the results of a query after - aggregation (GROUP BY) - - -Partial Object Syntax -^^^^^^^^^^^^^^^^^^^^^ - -By default when you run a DQL query in Doctrine and select only a -subset of the fields for a given entity, you do not receive objects -back. Instead, you receive only arrays as a flat rectangular result -set, similar to how you would if you were just using SQL directly -and joining some data. - -If you want to select partial objects you can use the ``partial`` -DQL keyword: - -.. code-block:: php - - createQuery('SELECT partial u.{id, username} FROM CmsUser u'); - $users = $query->getResult(); // array of partially loaded CmsUser objects - -You use the partial syntax when joining as well: - -.. code-block:: php - - createQuery('SELECT partial u.{id, username}, partial a.{id, name} FROM CmsUser u JOIN u.articles a'); - $users = $query->getResult(); // array of partially loaded CmsUser objects - -"NEW" Operator Syntax -^^^^^^^^^^^^^^^^^^^^^ - -.. versionadded:: 2.4 - -Using the ``NEW`` operator you can construct Data Transfer Objects (DTOs) directly from DQL queries. - -- When using ``SELECT NEW`` you don't need to specify a mapped entity. -- You can specify any PHP class, it only requires that the constructor of this class matches the ``NEW`` statement. -- This approach involves determining exactly which columns you really need, - and instantiating a data-transfer object that contains a constructor with those arguments. - -If you want to select data-transfer objects you should create a class: - -.. code-block:: php - - createQuery('SELECT NEW CustomerDTO(c.name, e.email, a.city) FROM Customer c JOIN c.email e JOIN c.address a'); - $users = $query->getResult(); // array of CustomerDTO - -.. code-block:: php - - createQuery('SELECT NEW CustomerDTO(c.name, e.email, a.city, SUM(o.value)) FROM Customer c JOIN c.email e JOIN c.address a JOIN c.orders o GROUP BY c'); - $users = $query->getResult(); // array of CustomerDTO - -Note that you can only pass scalar expressions to the constructor. - -Using INDEX BY -~~~~~~~~~~~~~~ - -The INDEX BY construct is nothing that directly translates into SQL -but that affects object and array hydration. After each FROM and -JOIN clause you specify by which field this class should be indexed -in the result. By default a result is incremented by numerical keys -starting with 0. However with INDEX BY you can specify any other -column to be the key of your result, it really only makes sense -with primary or unique fields though: - -.. code-block:: sql - - SELECT u.id, u.status, upper(u.name) nameUpper FROM User u INDEX BY u.id - JOIN u.phonenumbers p INDEX BY p.phonenumber - -Returns an array of the following kind, indexed by both user-id -then phonenumber-id: - -.. code-block:: php - - array - 0 => - array - 1 => - object(stdClass)[299] - public '__CLASS__' => string 'Doctrine\Tests\Models\CMS\CmsUser' (length=33) - public 'id' => int 1 - .. - 'nameUpper' => string 'ROMANB' (length=6) - 1 => - array - 2 => - object(stdClass)[298] - public '__CLASS__' => string 'Doctrine\Tests\Models\CMS\CmsUser' (length=33) - public 'id' => int 2 - ... - 'nameUpper' => string 'JWAGE' (length=5) - -UPDATE queries --------------- - -DQL not only allows to select your Entities using field names, you -can also execute bulk updates on a set of entities using an -DQL-UPDATE query. The Syntax of an UPDATE query works as expected, -as the following example shows: - -.. code-block:: sql - - UPDATE MyProject\Model\User u SET u.password = 'new' WHERE u.id IN (1, 2, 3) - -References to related entities are only possible in the WHERE -clause and using sub-selects. - -.. warning:: - - DQL UPDATE statements are ported directly into a - Database UPDATE statement and therefore bypass any locking scheme, events - and do not increment the version column. Entities that are already - loaded into the persistence context will *NOT* be synced with the - updated database state. It is recommended to call - ``EntityManager#clear()`` and retrieve new instances of any - affected entity. - - -DELETE queries --------------- - -DELETE queries can also be specified using DQL and their syntax is -as simple as the UPDATE syntax: - -.. code-block:: sql - - DELETE MyProject\Model\User u WHERE u.id = 4 - -The same restrictions apply for the reference of related entities. - -.. warning:: - - DQL DELETE statements are ported directly into a - Database DELETE statement and therefore bypass any events and checks for the - version column if they are not explicitly added to the WHERE clause - of the query. Additionally Deletes of specified entities are *NOT* - cascaded to related entities even if specified in the metadata. - - -Functions, Operators, Aggregates --------------------------------- -It is possible to wrap both fields and identification values into -aggregation and DQL functions. Numerical fields can be part of -computations using mathematical operations. - -DQL Functions -~~~~~~~~~~~~~ - -The following functions are supported in SELECT, WHERE and HAVING -clauses: - - -- IDENTITY(single\_association\_path\_expression [, fieldMapping]) - Retrieve the foreign key column of association of the owning side -- ABS(arithmetic\_expression) -- CONCAT(str1, str2) -- CURRENT\_DATE() - Return the current date -- CURRENT\_TIME() - Returns the current time -- CURRENT\_TIMESTAMP() - Returns a timestamp of the current date - and time. -- LENGTH(str) - Returns the length of the given string -- LOCATE(needle, haystack [, offset]) - Locate the first - occurrence of the substring in the string. -- LOWER(str) - returns the string lowercased. -- MOD(a, b) - Return a MOD b. -- SIZE(collection) - Return the number of elements in the - specified collection -- SQRT(q) - Return the square-root of q. -- SUBSTRING(str, start [, length]) - Return substring of given - string. -- TRIM([LEADING \| TRAILING \| BOTH] ['trchar' FROM] str) - Trim - the string by the given trim char, defaults to whitespaces. -- UPPER(str) - Return the upper-case of the given string. -- DATE_ADD(date, value, unit) - Add the given time to a given date. (Supported units are SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR) -- DATE_SUB(date, value, unit) - Subtract the given time from a given date. (Supported units are SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR) -- DATE_DIFF(date1, date2) - Calculate the difference in days between date1-date2. - -Arithmetic operators -~~~~~~~~~~~~~~~~~~~~ - -You can do math in DQL using numeric values, for example: - -.. code-block:: sql - - SELECT person.salary * 1.5 FROM CompanyPerson person WHERE person.salary < 100000 - -Aggregate Functions -~~~~~~~~~~~~~~~~~~~ - -The following aggregate functions are allowed in SELECT and GROUP -BY clauses: AVG, COUNT, MIN, MAX, SUM - -Other Expressions -~~~~~~~~~~~~~~~~~ - -DQL offers a wide-range of additional expressions that are known -from SQL, here is a list of all the supported constructs: - - -- ``ALL/ANY/SOME`` - Used in a WHERE clause followed by a - sub-select this works like the equivalent constructs in SQL. -- ``BETWEEN a AND b`` and ``NOT BETWEEN a AND b`` can be used to - match ranges of arithmetic values. -- ``IN (x1, x2, ...)`` and ``NOT IN (x1, x2, ..)`` can be used to - match a set of given values. -- ``LIKE ..`` and ``NOT LIKE ..`` match parts of a string or text - using % as a wildcard. -- ``IS NULL`` and ``IS NOT NULL`` to check for null values -- ``EXISTS`` and ``NOT EXISTS`` in combination with a sub-select - -Adding your own functions to the DQL language -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -By default DQL comes with functions that are part of a large basis -of underlying databases. However you will most likely choose a -database platform at the beginning of your project and most likely -never change it. For this cases you can easily extend the DQL -parser with own specialized platform functions. - -You can register custom DQL functions in your ORM Configuration: - -.. code-block:: php - - addCustomStringFunction($name, $class); - $config->addCustomNumericFunction($name, $class); - $config->addCustomDatetimeFunction($name, $class); - - $em = EntityManager::create($dbParams, $config); - -The functions have to return either a string, numeric or datetime -value depending on the registered function type. As an example we -will add a MySQL specific FLOOR() functionality. All the given -classes have to implement the base class : - -.. code-block:: php - - walkSimpleArithmeticExpression( - $this->simpleArithmeticExpression - ) . ')'; - } - - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } - } - -We will register the function by calling and can then use it: - -.. code-block:: php - - getConfiguration(); - $config->registerNumericFunction('FLOOR', 'MyProject\Query\MysqlFloor'); - - $dql = "SELECT FLOOR(person.salary * 1.75) FROM CompanyPerson person"; - -Querying Inherited Classes --------------------------- - -This section demonstrates how you can query inherited classes and -what type of results to expect. - -Single Table -~~~~~~~~~~~~ - -`Single Table Inheritance `_ -is an inheritance mapping strategy where all classes of a hierarchy -are mapped to a single database table. In order to distinguish -which row represents which type in the hierarchy a so-called -discriminator column is used. - -First we need to setup an example set of entities to use. In this -scenario it is a generic Person and Employee example: - -.. code-block:: php - - setName('test'); - $employee->setDepartment('testing'); - $em->persist($employee); - $em->flush(); - -Now lets run a simple query to retrieve the ``Employee`` we just -created: - -.. code-block:: sql - - SELECT e FROM Entities\Employee e WHERE e.name = 'test' - -If we check the generated SQL you will notice it has some special -conditions added to ensure that we will only get back ``Employee`` -entities: - -.. code-block:: sql - - SELECT p0_.id AS id0, p0_.name AS name1, p0_.department AS department2, - p0_.discr AS discr3 FROM Person p0_ - WHERE (p0_.name = ?) AND p0_.discr IN ('employee') - -Class Table Inheritance -~~~~~~~~~~~~~~~~~~~~~~~ - -`Class Table Inheritance `_ -is an inheritance mapping strategy where each class in a hierarchy -is mapped to several tables: its own table and the tables of all -parent classes. The table of a child class is linked to the table -of a parent class through a foreign key constraint. Doctrine 2 -implements this strategy through the use of a discriminator column -in the topmost table of the hierarchy because this is the easiest -way to achieve polymorphic queries with Class Table Inheritance. - -The example for class table inheritance is the same as single -table, you just need to change the inheritance type from -``SINGLE_TABLE`` to ``JOINED``: - -.. code-block:: php - - createQuery('select u from MyProject\Model\User u'); - - // example2: using setDQL - $q = $em->createQuery(); - $q->setDQL('select u from MyProject\Model\User u'); - -Query Result Formats -~~~~~~~~~~~~~~~~~~~~ - -The format in which the result of a DQL SELECT query is returned -can be influenced by a so-called ``hydration mode``. A hydration -mode specifies a particular way in which a SQL result set is -transformed. Each hydration mode has its own dedicated method on -the Query class. Here they are: - - -- ``Query#getResult()``: Retrieves a collection of objects. The - result is either a plain collection of objects (pure) or an array - where the objects are nested in the result rows (mixed). -- ``Query#getSingleResult()``: Retrieves a single object. If the - result contains more than one object, an ``NonUniqueResultException`` - is thrown. If the result contains no objects, an ``NoResultException`` - is thrown. The pure/mixed distinction does not apply. -- ``Query#getOneOrNullResult()``: Retrieve a single object. If the - result contains more than one object, a ``NonUniqueResultException`` - is thrown. If no object is found null will be returned. -- ``Query#getArrayResult()``: Retrieves an array graph (a nested - array) that is largely interchangeable with the object graph - generated by ``Query#getResult()`` for read-only purposes. - - .. note:: - - An array graph can differ from the corresponding object - graph in certain scenarios due to the difference of the identity - semantics between arrays and objects. - - - -- ``Query#getScalarResult()``: Retrieves a flat/rectangular result - set of scalar values that can contain duplicate data. The - pure/mixed distinction does not apply. -- ``Query#getSingleScalarResult()``: Retrieves a single scalar - value from the result returned by the dbms. If the result contains - more than a single scalar value, an exception is thrown. The - pure/mixed distinction does not apply. - -Instead of using these methods, you can alternatively use the -general-purpose method -``Query#execute(array $params = array(), $hydrationMode = Query::HYDRATE_OBJECT)``. -Using this method you can directly supply the hydration mode as the -second parameter via one of the Query constants. In fact, the -methods mentioned earlier are just convenient shortcuts for the -execute method. For example, the method ``Query#getResult()`` -internally invokes execute, passing in ``Query::HYDRATE_OBJECT`` as -the hydration mode. - -The use of the methods mentioned earlier is generally preferred as -it leads to more concise code. - -Pure and Mixed Results -~~~~~~~~~~~~~~~~~~~~~~ - -The nature of a result returned by a DQL SELECT query retrieved -through ``Query#getResult()`` or ``Query#getArrayResult()`` can be -of 2 forms: **pure** and **mixed**. In the previous simple -examples, you already saw a "pure" query result, with only objects. -By default, the result type is **pure** but -**as soon as scalar values, such as aggregate values or other scalar values that do not belong to an entity, appear in the SELECT part of the DQL query, the result becomes mixed**. -A mixed result has a different structure than a pure result in -order to accommodate for the scalar values. - -A pure result usually looks like this: - -.. code-block:: php - - $dql = "SELECT u FROM User u"; - - array - [0] => Object - [1] => Object - [2] => Object - ... - -A mixed result on the other hand has the following general -structure: - -.. code-block:: php - - $dql = "SELECT u, 'some scalar string', count(g.id) AS num FROM User u JOIN u.groups g GROUP BY u.id"; - - array - [0] - [0] => Object - [1] => "some scalar string" - ['num'] => 42 - // ... more scalar values, either indexed numerically or with a name - [1] - [0] => Object - [1] => "some scalar string" - ['num'] => 42 - // ... more scalar values, either indexed numerically or with a name - -To better understand mixed results, consider the following DQL -query: - -.. code-block:: sql - - SELECT u, UPPER(u.name) nameUpper FROM MyProject\Model\User u - -This query makes use of the ``UPPER`` DQL function that returns a -scalar value and because there is now a scalar value in the SELECT -clause, we get a mixed result. - -Conventions for mixed results are as follows: - - -- The object fetched in the FROM clause is always positioned with the key '0'. -- Every scalar without a name is numbered in the order given in the query, starting with 1. -- Every aliased scalar is given with its alias-name as the key. The case of the name is kept. -- If several objects are fetched from the FROM clause they alternate every row. - - -Here is how the result could look like: - -.. code-block:: php - - array - array - [0] => User (Object) - ['nameUpper'] => "ROMAN" - array - [0] => User (Object) - ['nameUpper'] => "JONATHAN" - ... - -And here is how you would access it in PHP code: - -.. code-block:: php - - getName(); - echo "Name UPPER: " . $row['nameUpper']; - } - -Fetching Multiple FROM Entities -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you fetch multiple entities that are listed in the FROM clause then the hydration -will return the rows iterating the different top-level entities. - -.. code-block:: php - - $dql = "SELECT u, g FROM User u, Group g"; - - array - [0] => Object (User) - [1] => Object (Group) - [2] => Object (User) - [3] => Object (Group) - - -Hydration Modes -~~~~~~~~~~~~~~~ - -Each of the Hydration Modes makes assumptions about how the result -is returned to user land. You should know about all the details to -make best use of the different result formats: - -The constants for the different hydration modes are: - - -- Query::HYDRATE\_OBJECT -- Query::HYDRATE\_ARRAY -- Query::HYDRATE\_SCALAR -- Query::HYDRATE\_SINGLE\_SCALAR - -Object Hydration -^^^^^^^^^^^^^^^^ - -Object hydration hydrates the result set into the object graph: - -.. code-block:: php - - createQuery('SELECT u FROM CmsUser u'); - $users = $query->getResult(Query::HYDRATE_OBJECT); - -Sometimes the behavior in the object hydrator can be confusing, which is -why we are listing as many of the assumptions here for reference: - -- Objects fetched in a FROM clause are returned as a Set, that means every - object is only ever included in the resulting array once. This is the case - even when using JOIN or GROUP BY in ways that return the same row for an - object multiple times. If the hydrator sees the same object multiple times, - then it makes sure it is only returned once. - -- If an object is already in memory from a previous query of any kind, then - then the previous object is used, even if the database may contain more - recent data. Data from the database is discarded. This even happens if the - previous object is still an unloaded proxy. - -This list might be incomplete. - -Array Hydration -^^^^^^^^^^^^^^^ - -You can run the same query with array hydration and the result set -is hydrated into an array that represents the object graph: - -.. code-block:: php - - createQuery('SELECT u FROM CmsUser u'); - $users = $query->getResult(Query::HYDRATE_ARRAY); - -You can use the ``getArrayResult()`` shortcut as well: - -.. code-block:: php - - getArrayResult(); - -Scalar Hydration -^^^^^^^^^^^^^^^^ - -If you want to return a flat rectangular result set instead of an -object graph you can use scalar hydration: - -.. code-block:: php - - createQuery('SELECT u FROM CmsUser u'); - $users = $query->getResult(Query::HYDRATE_SCALAR); - echo $users[0]['u_id']; - -The following assumptions are made about selected fields using -Scalar Hydration: - - -1. Fields from classes are prefixed by the DQL alias in the result. - A query of the kind 'SELECT u.name ..' returns a key 'u\_name' in - the result rows. - -Single Scalar Hydration -^^^^^^^^^^^^^^^^^^^^^^^ - -If you have a query which returns just a single scalar value you can use -single scalar hydration: - -.. code-block:: php - - createQuery('SELECT COUNT(a.id) FROM CmsUser u LEFT JOIN u.articles a WHERE u.username = ?1 GROUP BY u.id'); - $query->setParameter(1, 'jwage'); - $numArticles = $query->getResult(Query::HYDRATE_SINGLE_SCALAR); - -You can use the ``getSingleScalarResult()`` shortcut as well: - -.. code-block:: php - - getSingleScalarResult(); - -Custom Hydration Modes -^^^^^^^^^^^^^^^^^^^^^^ - -You can easily add your own custom hydration modes by first -creating a class which extends ``AbstractHydrator``: - -.. code-block:: php - - _stmt->fetchAll(PDO::FETCH_ASSOC); - } - } - -Next you just need to add the class to the ORM configuration: - -.. code-block:: php - - getConfiguration()->addCustomHydrationMode('CustomHydrator', 'MyProject\Hydrators\CustomHydrator'); - -Now the hydrator is ready to be used in your queries: - -.. code-block:: php - - createQuery('SELECT u FROM CmsUser u'); - $results = $query->getResult('CustomHydrator'); - -Iterating Large Result Sets -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There are situations when a query you want to execute returns a -very large result-set that needs to be processed. All the -previously described hydration modes completely load a result-set -into memory which might not be feasible with large result sets. See -the `Batch Processing `_ section on details how -to iterate large result sets. - -Functions -~~~~~~~~~ - -The following methods exist on the ``AbstractQuery`` which both -``Query`` and ``NativeQuery`` extend from. - -Parameters -^^^^^^^^^^ - -Prepared Statements that use numerical or named wildcards require -additional parameters to be executable against the database. To -pass parameters to the query the following methods can be used: - - -- ``AbstractQuery::setParameter($param, $value)`` - Set the - numerical or named wildcard to the given value. -- ``AbstractQuery::setParameters(array $params)`` - Set an array - of parameter key-value pairs. -- ``AbstractQuery::getParameter($param)`` -- ``AbstractQuery::getParameters()`` - -Both named and positional parameters are passed to these methods without their ? or : prefix. - -Cache related API -^^^^^^^^^^^^^^^^^ - -You can cache query results based either on all variables that -define the result (SQL, Hydration Mode, Parameters and Hints) or on -user-defined cache keys. However by default query results are not -cached at all. You have to enable the result cache on a per query -basis. The following example shows a complete workflow using the -Result Cache API: - -.. code-block:: php - - createQuery('SELECT u FROM MyProject\Model\User u WHERE u.id = ?1'); - $query->setParameter(1, 12); - - $query->setResultCacheDriver(new ApcCache()); - - $query->useResultCache(true) - ->setResultCacheLifeTime($seconds = 3600); - - $result = $query->getResult(); // cache miss - - $query->expireResultCache(true); - $result = $query->getResult(); // forced expire, cache miss - - $query->setResultCacheId('my_query_result'); - $result = $query->getResult(); // saved in given result cache id. - - // or call useResultCache() with all parameters: - $query->useResultCache(true, $seconds = 3600, 'my_query_result'); - $result = $query->getResult(); // cache hit! - - // Introspection - $queryCacheProfile = $query->getQueryCacheProfile(); - $cacheDriver = $query->getResultCacheDriver(); - $lifetime = $query->getLifetime(); - $key = $query->getCacheKey(); - -.. note:: - - You can set the Result Cache Driver globally on the - ``Doctrine\ORM\Configuration`` instance so that it is passed to - every ``Query`` and ``NativeQuery`` instance. - - -Query Hints -^^^^^^^^^^^ - -You can pass hints to the query parser and hydrators by using the -``AbstractQuery::setHint($name, $value)`` method. Currently there -exist mostly internal query hints that are not be consumed in -userland. However the following few hints are to be used in -userland: - - -- Query::HINT\_FORCE\_PARTIAL\_LOAD - Allows to hydrate objects - although not all their columns are fetched. This query hint can be - used to handle memory consumption problems with large result-sets - that contain char or binary data. Doctrine has no way of implicitly - reloading this data. Partially loaded objects have to be passed to - ``EntityManager::refresh()`` if they are to be reloaded fully from - the database. -- Query::HINT\_REFRESH - This query is used internally by - ``EntityManager::refresh()`` and can be used in userland as well. - If you specify this hint and a query returns the data for an entity - that is already managed by the UnitOfWork, the fields of the - existing entity will be refreshed. In normal operation a result-set - that loads data of an already existing entity is discarded in favor - of the already existing entity. -- Query::HINT\_CUSTOM\_TREE\_WALKERS - An array of additional - ``Doctrine\ORM\Query\TreeWalker`` instances that are attached to - the DQL query parsing process. - -Query Cache (DQL Query Only) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Parsing a DQL query and converting it into a SQL query against the -underlying database platform obviously has some overhead in -contrast to directly executing Native SQL queries. That is why -there is a dedicated Query Cache for caching the DQL parser -results. In combination with the use of wildcards you can reduce -the number of parsed queries in production to zero. - -The Query Cache Driver is passed from the -``Doctrine\ORM\Configuration`` instance to each -``Doctrine\ORM\Query`` instance by default and is also enabled by -default. This also means you don't regularly need to fiddle with -the parameters of the Query Cache, however if you do there are -several methods to interact with it: - - -- ``Query::setQueryCacheDriver($driver)`` - Allows to set a Cache - instance -- ``Query::setQueryCacheLifeTime($seconds = 3600)`` - Set lifetime - of the query caching. -- ``Query::expireQueryCache($bool)`` - Enforce the expiring of the - query cache if set to true. -- ``Query::getExpireQueryCache()`` -- ``Query::getQueryCacheDriver()`` -- ``Query::getQueryCacheLifeTime()`` - -First and Max Result Items (DQL Query Only) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -You can limit the number of results returned from a DQL query as -well as specify the starting offset, Doctrine then uses a strategy -of manipulating the select query to return only the requested -number of results: - - -- ``Query::setMaxResults($maxResults)`` -- ``Query::setFirstResult($offset)`` - -.. note:: - - If your query contains a fetch-joined collection - specifying the result limit methods are not working as you would - expect. Set Max Results restricts the number of database result - rows, however in the case of fetch-joined collections one root - entity might appear in many rows, effectively hydrating less than - the specified number of results. - -.. _dql-temporarily-change-fetch-mode: - -Temporarily change fetch mode in DQL -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -While normally all your associations are marked as lazy or extra lazy you will have cases where you are using DQL and don't want to -fetch join a second, third or fourth level of entities into your result, because of the increased cost of the SQL JOIN. You -can mark a many-to-one or one-to-one association as fetched temporarily to batch fetch these entities using a WHERE .. IN query. - -.. code-block:: php - - createQuery("SELECT u FROM MyProject\User u"); - $query->setFetchMode("MyProject\User", "address", \Doctrine\ORM\Mapping\ClassMetadata::FETCH_EAGER); - $query->execute(); - -Given that there are 10 users and corresponding addresses in the database the executed queries will look something like: - -.. code-block:: sql - - SELECT * FROM users; - SELECT * FROM address WHERE id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); - -.. note:: - Changing the fetch mode during a query mostly makes sense for one-to-one and many-to-one relations. In that case, - all the necessary IDs are available after the root entity (``user`` in the above example) has been loaded. So, one - query per association can be executed to fetch all the referred-to entities (``address``). - - For one-to-many relations, changing the fetch mode to eager will cause to execute one query **for every root entity - loaded**. This gives no improvement over the ``lazy`` fetch mode which will also initialize the associations on - a one-by-one basis once they are accessed. - - -EBNF ----- - -The following context-free grammar, written in an EBNF variant, -describes the Doctrine Query Language. You can consult this grammar -whenever you are unsure about what is possible with DQL or what the -correct syntax for a particular query should be. - -Document syntax: -~~~~~~~~~~~~~~~~ - - -- non-terminals begin with an upper case character -- terminals begin with a lower case character -- parentheses (...) are used for grouping -- square brackets [...] are used for defining an optional part, - e.g. zero or one time -- curly brackets {...} are used for repetition, e.g. zero or more - times -- double quotation marks "..." define a terminal string -- a vertical bar \| represents an alternative - -Terminals -~~~~~~~~~ - - -- identifier (name, email, ...) must match ``[a-z_][a-z0-9_]*`` -- fully_qualified_name (Doctrine\Tests\Models\CMS\CmsUser) matches PHP's fully qualified class names -- aliased_name (CMS:CmsUser) uses two identifiers, one for the namespace alias and one for the class inside it -- string ('foo', 'bar''s house', '%ninja%', ...) -- char ('/', '\\', ' ', ...) -- integer (-1, 0, 1, 34, ...) -- float (-0.23, 0.007, 1.245342E+8, ...) -- boolean (false, true) - -Query Language -~~~~~~~~~~~~~~ - -.. code-block:: php - - QueryLanguage ::= SelectStatement | UpdateStatement | DeleteStatement - -Statements -~~~~~~~~~~ - -.. code-block:: php - - SelectStatement ::= SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] - UpdateStatement ::= UpdateClause [WhereClause] - DeleteStatement ::= DeleteClause [WhereClause] - -Identifiers -~~~~~~~~~~~ - -.. code-block:: php - - /* Alias Identification usage (the "u" of "u.name") */ - IdentificationVariable ::= identifier - - /* Alias Identification declaration (the "u" of "FROM User u") */ - AliasIdentificationVariable :: = identifier - - /* identifier that must be a class name (the "User" of "FROM User u"), possibly as a fully qualified class name or namespace-aliased */ - AbstractSchemaName ::= fully_qualified_name | aliased_name | identifier - - /* Alias ResultVariable declaration (the "total" of "COUNT(*) AS total") */ - AliasResultVariable = identifier - - /* ResultVariable identifier usage of mapped field aliases (the "total" of "COUNT(*) AS total") */ - ResultVariable = identifier - - /* identifier that must be a field (the "name" of "u.name") */ - /* This is responsible to know if the field exists in Object, no matter if it's a relation or a simple field */ - FieldIdentificationVariable ::= identifier - - /* identifier that must be a collection-valued association field (to-many) (the "Phonenumbers" of "u.Phonenumbers") */ - CollectionValuedAssociationField ::= FieldIdentificationVariable - - /* identifier that must be a single-valued association field (to-one) (the "Group" of "u.Group") */ - SingleValuedAssociationField ::= FieldIdentificationVariable - - /* identifier that must be an embedded class state field */ - EmbeddedClassStateField ::= FieldIdentificationVariable - - /* identifier that must be a simple state field (name, email, ...) (the "name" of "u.name") */ - /* The difference between this and FieldIdentificationVariable is only semantical, because it points to a single field (not mapping to a relation) */ - SimpleStateField ::= FieldIdentificationVariable - -Path Expressions -~~~~~~~~~~~~~~~~ - -.. code-block:: php - - /* "u.Group" or "u.Phonenumbers" declarations */ - JoinAssociationPathExpression ::= IdentificationVariable "." (CollectionValuedAssociationField | SingleValuedAssociationField) - - /* "u.Group" or "u.Phonenumbers" usages */ - AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression - - /* "u.name" or "u.Group" */ - SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression - - /* "u.name" or "u.Group.name" */ - StateFieldPathExpression ::= IdentificationVariable "." StateField - - /* "u.Group" */ - SingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField - - /* "u.Group.Permissions" */ - CollectionValuedPathExpression ::= IdentificationVariable "." CollectionValuedAssociationField - - /* "name" */ - StateField ::= {EmbeddedClassStateField "."}* SimpleStateField - -Clauses -~~~~~~~ - -.. code-block:: php - - SelectClause ::= "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression}* - SimpleSelectClause ::= "SELECT" ["DISTINCT"] SimpleSelectExpression - UpdateClause ::= "UPDATE" AbstractSchemaName ["AS"] AliasIdentificationVariable "SET" UpdateItem {"," UpdateItem}* - DeleteClause ::= "DELETE" ["FROM"] AbstractSchemaName ["AS"] AliasIdentificationVariable - FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}* - SubselectFromClause ::= "FROM" SubselectIdentificationVariableDeclaration {"," SubselectIdentificationVariableDeclaration}* - WhereClause ::= "WHERE" ConditionalExpression - HavingClause ::= "HAVING" ConditionalExpression - GroupByClause ::= "GROUP" "BY" GroupByItem {"," GroupByItem}* - OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}* - Subselect ::= SimpleSelectClause SubselectFromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] - -Items -~~~~~ - -.. code-block:: php - - UpdateItem ::= SingleValuedPathExpression "=" NewValue - OrderByItem ::= (SimpleArithmeticExpression | SingleValuedPathExpression | ScalarExpression | ResultVariable | FunctionDeclaration) ["ASC" | "DESC"] - GroupByItem ::= IdentificationVariable | ResultVariable | SingleValuedPathExpression - NewValue ::= SimpleArithmeticExpression | "NULL" - -From, Join and Index by -~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: php - - IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {Join}* - SubselectIdentificationVariableDeclaration ::= IdentificationVariableDeclaration - RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable - JoinAssociationDeclaration ::= JoinAssociationPathExpression ["AS"] AliasIdentificationVariable [IndexBy] - Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" (JoinAssociationDeclaration | RangeVariableDeclaration) ["WITH" ConditionalExpression] - IndexBy ::= "INDEX" "BY" StateFieldPathExpression - -Select Expressions -~~~~~~~~~~~~~~~~~~ - -.. code-block:: php - - SelectExpression ::= (IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | PartialObjectExpression | "(" Subselect ")" | CaseExpression | NewObjectExpression) [["AS"] ["HIDDEN"] AliasResultVariable] - SimpleSelectExpression ::= (StateFieldPathExpression | IdentificationVariable | FunctionDeclaration | AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] AliasResultVariable] - PartialObjectExpression ::= "PARTIAL" IdentificationVariable "." PartialFieldSet - PartialFieldSet ::= "{" SimpleStateField {"," SimpleStateField}* "}" - NewObjectExpression ::= "NEW" AbstractSchemaName "(" NewObjectArg {"," NewObjectArg}* ")" - NewObjectArg ::= ScalarExpression | "(" Subselect ")" - -Conditional Expressions -~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: php - - ConditionalExpression ::= ConditionalTerm {"OR" ConditionalTerm}* - ConditionalTerm ::= ConditionalFactor {"AND" ConditionalFactor}* - ConditionalFactor ::= ["NOT"] ConditionalPrimary - ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")" - SimpleConditionalExpression ::= ComparisonExpression | BetweenExpression | LikeExpression | - InExpression | NullComparisonExpression | ExistsExpression | - EmptyCollectionComparisonExpression | CollectionMemberExpression | - InstanceOfExpression - - -Collection Expressions -~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: php - - EmptyCollectionComparisonExpression ::= CollectionValuedPathExpression "IS" ["NOT"] "EMPTY" - CollectionMemberExpression ::= EntityExpression ["NOT"] "MEMBER" ["OF"] CollectionValuedPathExpression - -Literal Values -~~~~~~~~~~~~~~ - -.. code-block:: php - - Literal ::= string | char | integer | float | boolean - InParameter ::= Literal | InputParameter - -Input Parameter -~~~~~~~~~~~~~~~ - -.. code-block:: php - - InputParameter ::= PositionalParameter | NamedParameter - PositionalParameter ::= "?" integer - NamedParameter ::= ":" string - -Arithmetic Expressions -~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: php - - ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")" - SimpleArithmeticExpression ::= ArithmeticTerm {("+" | "-") ArithmeticTerm}* - ArithmeticTerm ::= ArithmeticFactor {("*" | "/") ArithmeticFactor}* - ArithmeticFactor ::= [("+" | "-")] ArithmeticPrimary - ArithmeticPrimary ::= SingleValuedPathExpression | Literal | "(" SimpleArithmeticExpression ")" - | FunctionsReturningNumerics | AggregateExpression | FunctionsReturningStrings - | FunctionsReturningDatetime | IdentificationVariable | ResultVariable - | InputParameter | CaseExpression - -Scalar and Type Expressions -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: php - - ScalarExpression ::= SimpleArithmeticExpression | StringPrimary | DateTimePrimary | StateFieldPathExpression | BooleanPrimary | CaseExpression | InstanceOfExpression - StringExpression ::= StringPrimary | ResultVariable | "(" Subselect ")" - StringPrimary ::= StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression | CaseExpression - BooleanExpression ::= BooleanPrimary | "(" Subselect ")" - BooleanPrimary ::= StateFieldPathExpression | boolean | InputParameter - EntityExpression ::= SingleValuedAssociationPathExpression | SimpleEntityExpression - SimpleEntityExpression ::= IdentificationVariable | InputParameter - DatetimeExpression ::= DatetimePrimary | "(" Subselect ")" - DatetimePrimary ::= StateFieldPathExpression | InputParameter | FunctionsReturningDatetime | AggregateExpression - -.. note:: - - Parts of CASE expressions are not yet implemented. - -Aggregate Expressions -~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: php - - AggregateExpression ::= ("AVG" | "MAX" | "MIN" | "SUM" | "COUNT") "(" ["DISTINCT"] SimpleArithmeticExpression ")" - -Case Expressions -~~~~~~~~~~~~~~~~ - -.. code-block:: php - - CaseExpression ::= GeneralCaseExpression | SimpleCaseExpression | CoalesceExpression | NullifExpression - GeneralCaseExpression ::= "CASE" WhenClause {WhenClause}* "ELSE" ScalarExpression "END" - WhenClause ::= "WHEN" ConditionalExpression "THEN" ScalarExpression - SimpleCaseExpression ::= "CASE" CaseOperand SimpleWhenClause {SimpleWhenClause}* "ELSE" ScalarExpression "END" - CaseOperand ::= StateFieldPathExpression | TypeDiscriminator - SimpleWhenClause ::= "WHEN" ScalarExpression "THEN" ScalarExpression - CoalesceExpression ::= "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")" - NullifExpression ::= "NULLIF" "(" ScalarExpression "," ScalarExpression ")" - -Other Expressions -~~~~~~~~~~~~~~~~~ - -QUANTIFIED/BETWEEN/COMPARISON/LIKE/NULL/EXISTS - -.. code-block:: php - - QuantifiedExpression ::= ("ALL" | "ANY" | "SOME") "(" Subselect ")" - BetweenExpression ::= ArithmeticExpression ["NOT"] "BETWEEN" ArithmeticExpression "AND" ArithmeticExpression - ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression ) - InExpression ::= SingleValuedPathExpression ["NOT"] "IN" "(" (InParameter {"," InParameter}* | Subselect) ")" - InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (InstanceOfParameter | "(" InstanceOfParameter {"," InstanceOfParameter}* ")") - InstanceOfParameter ::= AbstractSchemaName | InputParameter - LikeExpression ::= StringExpression ["NOT"] "LIKE" StringPrimary ["ESCAPE" char] - NullComparisonExpression ::= (InputParameter | NullIfExpression | CoalesceExpression | AggregateExpression | FunctionDeclaration | IdentificationVariable | SingleValuedPathExpression | ResultVariable) "IS" ["NOT"] "NULL" - ExistsExpression ::= ["NOT"] "EXISTS" "(" Subselect ")" - ComparisonOperator ::= "=" | "<" | "<=" | "<>" | ">" | ">=" | "!=" - -Functions -~~~~~~~~~ - -.. code-block:: php - - FunctionDeclaration ::= FunctionsReturningStrings | FunctionsReturningNumerics | FunctionsReturningDateTime - - FunctionsReturningNumerics ::= - "LENGTH" "(" StringPrimary ")" | - "LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" | - "ABS" "(" SimpleArithmeticExpression ")" | - "SQRT" "(" SimpleArithmeticExpression ")" | - "MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" | - "SIZE" "(" CollectionValuedPathExpression ")" | - "DATE_DIFF" "(" ArithmeticPrimary "," ArithmeticPrimary ")" | - "BIT_AND" "(" ArithmeticPrimary "," ArithmeticPrimary ")" | - "BIT_OR" "(" ArithmeticPrimary "," ArithmeticPrimary ")" - - FunctionsReturningDateTime ::= - "CURRENT_DATE" | - "CURRENT_TIME" | - "CURRENT_TIMESTAMP" | - "DATE_ADD" "(" ArithmeticPrimary "," ArithmeticPrimary "," StringPrimary ")" | - "DATE_SUB" "(" ArithmeticPrimary "," ArithmeticPrimary "," StringPrimary ")" - - FunctionsReturningStrings ::= - "CONCAT" "(" StringPrimary "," StringPrimary ")" | - "SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")" | - "TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")" | - "LOWER" "(" StringPrimary ")" | - "UPPER" "(" StringPrimary ")" | - "IDENTITY" "(" SingleValuedAssociationPathExpression {"," string} ")" - - diff --git a/vendor/doctrine/orm/docs/en/reference/events.rst b/vendor/doctrine/orm/docs/en/reference/events.rst deleted file mode 100644 index 9bcafe4..0000000 --- a/vendor/doctrine/orm/docs/en/reference/events.rst +++ /dev/null @@ -1,989 +0,0 @@ -Events -====== - -Doctrine 2 features a lightweight event system that is part of the -Common package. Doctrine uses it to dispatch system events, mainly -:ref:`lifecycle events `. -You can also use it for your own custom events. - -The Event System ----------------- - -The event system is controlled by the ``EventManager``. It is the -central point of Doctrine's event listener system. Listeners are -registered on the manager and events are dispatched through the -manager. - -.. code-block:: php - - addEventListener(array(self::preFoo, self::postFoo), $this); - } - - public function preFoo(EventArgs $e) - { - $this->preFooInvoked = true; - } - - public function postFoo(EventArgs $e) - { - $this->postFooInvoked = true; - } - } - - // Create a new instance - $test = new TestEvent($evm); - -Events can be dispatched by using the ``dispatchEvent()`` method. - -.. code-block:: php - - dispatchEvent(TestEvent::preFoo); - $evm->dispatchEvent(TestEvent::postFoo); - -You can easily remove a listener with the ``removeEventListener()`` -method. - -.. code-block:: php - - removeEventListener(array(self::preFoo, self::postFoo), $this); - -The Doctrine 2 event system also has a simple concept of event -subscribers. We can define a simple ``TestEventSubscriber`` class -which implements the ``\Doctrine\Common\EventSubscriber`` interface -and implements a ``getSubscribedEvents()`` method which returns an -array of events it should be subscribed to. - -.. code-block:: php - - preFooInvoked = true; - } - - public function getSubscribedEvents() - { - return array(TestEvent::preFoo); - } - } - - $eventSubscriber = new TestEventSubscriber(); - $evm->addEventSubscriber($eventSubscriber); - -.. note:: - - The array to return in the ``getSubscribedEvents`` method is a simple array - with the values being the event names. The subscriber must have a method - that is named exactly like the event. - -Now when you dispatch an event, any event subscribers will be -notified for that event. - -.. code-block:: php - - dispatchEvent(TestEvent::preFoo); - -Now you can test the ``$eventSubscriber`` instance to see if the -``preFoo()`` method was invoked. - -.. code-block:: php - - preFooInvoked) { - echo 'pre foo invoked!'; - } - -Naming convention -~~~~~~~~~~~~~~~~~ - -Events being used with the Doctrine 2 EventManager are best named -with camelcase and the value of the corresponding constant should -be the name of the constant itself, even with spelling. This has -several reasons: - - -- It is easy to read. -- Simplicity. -- Each method within an EventSubscriber is named after the - corresponding constant's value. If the constant's name and value differ - it contradicts the intention of using the constant and makes your code - harder to maintain. - -An example for a correct notation can be found in the example -``TestEvent`` above. - -.. _reference-events-lifecycle-events: - -Lifecycle Events ----------------- - -The EntityManager and UnitOfWork trigger a bunch of events during -the life-time of their registered entities. - - -- preRemove - The preRemove event occurs for a given entity before - the respective EntityManager remove operation for that entity is - executed. It is not called for a DQL DELETE statement. -- postRemove - The postRemove event occurs for an entity after the - entity has been deleted. It will be invoked after the database - delete operations. It is not called for a DQL DELETE statement. -- prePersist - The prePersist event occurs for a given entity - before the respective EntityManager persist operation for that - entity is executed. It should be noted that this event is only triggered on - *initial* persist of an entity (i.e. it does not trigger on future updates). -- postPersist - The postPersist event occurs for an entity after - the entity has been made persistent. It will be invoked after the - database insert operations. Generated primary key values are - available in the postPersist event. -- preUpdate - The preUpdate event occurs before the database - update operations to entity data. It is not called for a DQL UPDATE statement - nor when the computed changeset is empty. -- postUpdate - The postUpdate event occurs after the database - update operations to entity data. It is not called for a DQL UPDATE statement. -- postLoad - The postLoad event occurs for an entity after the - entity has been loaded into the current EntityManager from the - database or after the refresh operation has been applied to it. -- loadClassMetadata - The loadClassMetadata event occurs after the - mapping metadata for a class has been loaded from a mapping source - (annotations/xml/yaml). This event is not a lifecycle callback. -- onClassMetadataNotFound - Loading class metadata for a particular - requested class name failed. Manipulating the given event args instance - allows providing fallback metadata even when no actual metadata exists - or could be found. This event is not a lifecycle callback. -- preFlush - The preFlush event occurs at the very beginning of a flush - operation. -- onFlush - The onFlush event occurs after the change-sets of all - managed entities are computed. This event is not a lifecycle - callback. -- postFlush - The postFlush event occurs at the end of a flush operation. This - event is not a lifecycle callback. -- onClear - The onClear event occurs when the EntityManager#clear() operation is - invoked, after all references to entities have been removed from the unit of - work. This event is not a lifecycle callback. - -.. warning:: - - Note that, when using ``Doctrine\ORM\AbstractQuery#iterate()``, ``postLoad`` - events will be executed immediately after objects are being hydrated, and therefore - associations are not guaranteed to be initialized. It is not safe to combine - usage of ``Doctrine\ORM\AbstractQuery#iterate()`` and ``postLoad`` event - handlers. - -.. warning:: - - Note that the postRemove event or any events triggered after an entity removal - can receive an uninitializable proxy in case you have configured an entity to - cascade remove relations. In this case, you should load yourself the proxy in - the associated pre event. - -You can access the Event constants from the ``Events`` class in the -ORM package. - -.. code-block:: php - - createdAt = date('Y-m-d H:i:s'); - } - - /** @PrePersist */ - public function doOtherStuffOnPrePersist() - { - $this->value = 'changed from prePersist callback!'; - } - - /** @PostPersist */ - public function doStuffOnPostPersist() - { - $this->value = 'changed from postPersist callback!'; - } - - /** @PostLoad */ - public function doStuffOnPostLoad() - { - $this->value = 'changed from postLoad callback!'; - } - - /** @PreUpdate */ - public function doStuffOnPreUpdate() - { - $this->value = 'changed from preUpdate callback!'; - } - } - -Note that the methods set as lifecycle callbacks need to be public and, -when using these annotations, you have to apply the -``@HasLifecycleCallbacks`` marker annotation on the entity class. - -If you want to register lifecycle callbacks from YAML or XML you -can do it with the following. - -.. code-block:: yaml - - User: - type: entity - fields: - # ... - name: - type: string(50) - lifecycleCallbacks: - prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersist ] - postPersist: [ doStuffOnPostPersist ] - -In YAML the ``key`` of the lifecycleCallbacks entry is the event that you -are triggering on and the value is the method (or methods) to call. The allowed -event types are the ones listed in the previous Lifecycle Events section. - -XML would look something like this: - -.. code-block:: xml - - - - - - - - - - - - - - - - -In XML the ``type`` of the lifecycle-callback entry is the event that you -are triggering on and the ``method`` is the method to call. The allowed event -types are the ones listed in the previous Lifecycle Events section. - -When using YAML or XML you need to remember to create public methods to match the -callback names you defined. E.g. in these examples ``doStuffOnPrePersist()``, -``doOtherStuffOnPrePersist()`` and ``doStuffOnPostPersist()`` methods need to be -defined on your ``User`` model. - -.. code-block:: php - - hasChangedField('username')) { - // Do something when the username is changed. - } - } - } - -Listening and subscribing to Lifecycle Events ---------------------------------------------- - -Lifecycle event listeners are much more powerful than the simple -lifecycle callbacks that are defined on the entity classes. They -sit at a level above the entities and allow you to implement re-usable -behaviors across different entity classes. - -Note that they require much more detailed knowledge about the inner -workings of the EntityManager and UnitOfWork. Please read the -:ref:`reference-events-implementing-listeners` section carefully if you -are trying to write your own listener. - -For event subscribers, there are no surprises. They declare the -lifecycle events in their ``getSubscribedEvents`` method and provide -public methods that expect the relevant arguments. - -A lifecycle event listener looks like the following: - -.. code-block:: php - - getObject(); - $entityManager = $args->getObjectManager(); - - // perhaps you only want to act on some "Product" entity - if ($entity instanceof Product) { - // do something with the Product - } - } - } - -A lifecycle event subscriber may look like this: - -.. code-block:: php - - getObject(); - $entityManager = $args->getObjectManager(); - - // perhaps you only want to act on some "Product" entity - if ($entity instanceof Product) { - // do something with the Product - } - } - -.. note:: - - Lifecycle events are triggered for all entities. It is the responsibility - of the listeners and subscribers to check if the entity is of a type - it wants to handle. - -To register an event listener or subscriber, you have to hook it into the -EventManager that is passed to the EntityManager factory: - -.. code-block:: php - - addEventListener(array(Events::preUpdate), new MyEventListener()); - $eventManager->addEventSubscriber(new MyEventSubscriber()); - - $entityManager = EntityManager::create($dbOpts, $config, $eventManager); - -You can also retrieve the event manager instance after the -EntityManager was created: - -.. code-block:: php - - getEventManager()->addEventListener(array(Events::preUpdate), new MyEventListener()); - $entityManager->getEventManager()->addEventSubscriber(new MyEventSubscriber()); - -.. _reference-events-implementing-listeners: - -Implementing Event Listeners ----------------------------- - -This section explains what is and what is not allowed during -specific lifecycle events of the UnitOfWork. Although you get -passed the EntityManager in all of these events, you have to follow -these restrictions very carefully since operations in the wrong -event may produce lots of different errors, such as inconsistent -data and lost updates/persists/removes. - -For the described events that are also lifecycle callback events -the restrictions apply as well, with the additional restriction -that (prior to version 2.4) you do not have access to the -EntityManager or UnitOfWork APIs inside these events. - -prePersist -~~~~~~~~~~ - -There are two ways for the ``prePersist`` event to be triggered. -One is obviously when you call ``EntityManager#persist()``. The -event is also called for all cascaded associations. - -There is another way for ``prePersist`` to be called, inside the -``flush()`` method when changes to associations are computed and -this association is marked as cascade persist. Any new entity found -during this operation is also persisted and ``prePersist`` called -on it. This is called "persistence by reachability". - -In both cases you get passed a ``LifecycleEventArgs`` instance -which has access to the entity and the entity manager. - -The following restrictions apply to ``prePersist``: - - -- If you are using a PrePersist Identity Generator such as - sequences the ID value will *NOT* be available within any - PrePersist events. -- Doctrine will not recognize changes made to relations in a prePersist - event. This includes modifications to - collections such as additions, removals or replacement. - -preRemove -~~~~~~~~~ - -The ``preRemove`` event is called on every entity when its passed -to the ``EntityManager#remove()`` method. It is cascaded for all -associations that are marked as cascade delete. - -There are no restrictions to what methods can be called inside the -``preRemove`` event, except when the remove method itself was -called during a flush operation. - -preFlush -~~~~~~~~ - -``preFlush`` is called at ``EntityManager#flush()`` before -anything else. ``EntityManager#flush()`` should not be called inside -its listeners, since `preFlush` event is dispatched in it, which would -result in infinite loop. - -.. code-block:: php - - getEntityManager(); - $uow = $em->getUnitOfWork(); - - foreach ($uow->getScheduledEntityInsertions() as $entity) { - - } - - foreach ($uow->getScheduledEntityUpdates() as $entity) { - - } - - foreach ($uow->getScheduledEntityDeletions() as $entity) { - - } - - foreach ($uow->getScheduledCollectionDeletions() as $col) { - - } - - foreach ($uow->getScheduledCollectionUpdates() as $col) { - - } - } - } - -The following restrictions apply to the onFlush event: - - -- If you create and persist a new entity in ``onFlush``, then - calling ``EntityManager#persist()`` is not enough. - You have to execute an additional call to - ``$unitOfWork->computeChangeSet($classMetadata, $entity)``. -- Changing primitive fields or associations requires you to - explicitly trigger a re-computation of the changeset of the - affected entity. This can be done by calling - ``$unitOfWork->recomputeSingleEntityChangeSet($classMetadata, $entity)``. - -postFlush -~~~~~~~~~ - -``postFlush`` is called at the end of ``EntityManager#flush()``. -``EntityManager#flush()`` can **NOT** be called safely inside its listeners. - -.. code-block:: php - - getEntity() instanceof User) { - if ($eventArgs->hasChangedField('name') && $eventArgs->getNewValue('name') == 'Alice') { - $eventArgs->setNewValue('name', 'Bob'); - } - } - } - } - -You could also use this listener to implement validation of all the -fields that have changed. This is more efficient than using a -lifecycle callback when there are expensive validations to call: - -.. code-block:: php - - getEntity() instanceof Account) { - if ($eventArgs->hasChangedField('creditCard')) { - $this->validateCreditCard($eventArgs->getNewValue('creditCard')); - } - } - } - - private function validateCreditCard($no) - { - // throw an exception to interrupt flush event. Transaction will be rolled back. - } - } - -Restrictions for this event: - - -- Changes to associations of the passed entities are not - recognized by the flush operation anymore. -- Changes to fields of the passed entities are not recognized by - the flush operation anymore, use the computed change-set passed to - the event to modify primitive field values, e.g. use - ``$eventArgs->setNewValue($field, $value);`` as in the Alice to Bob example above. -- Any calls to ``EntityManager#persist()`` or - ``EntityManager#remove()``, even in combination with the UnitOfWork - API are strongly discouraged and don't work as expected outside the - flush operation. - -postUpdate, postRemove, postPersist -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The three post events are called inside ``EntityManager#flush()``. -Changes in here are not relevant to the persistence in the -database, but you can use these events to alter non-persistable items, -like non-mapped fields, logging or even associated classes that are -not directly mapped by Doctrine. - -postLoad -~~~~~~~~ - -This event is called after an entity is constructed by the -EntityManager. - -Entity listeners ----------------- - -.. versionadded:: 2.4 - -An entity listener is a lifecycle listener class used for an entity. - -- The entity listener's mapping may be applied to an entity class or mapped superclass. -- An entity listener is defined by mapping the entity class with the corresponding mapping. - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - .. code-block:: yaml - - MyProject\Entity\User: - type: entity - entityListeners: - UserListener: - # .... - -.. _reference-entity-listeners: - -Entity listeners class -~~~~~~~~~~~~~~~~~~~~~~ - -An ``Entity Listener`` could be any class, by default it should be a class with a no-arg constructor. - -- Different from :ref:`reference-events-implementing-listeners` an ``Entity Listener`` is invoked just to the specified entity -- An entity listener method receives two arguments, the entity instance and the lifecycle event. -- The callback method can be defined by naming convention or specifying a method mapping. -- When a listener mapping is not given the parser will use the naming convention to look for a matching method, - e.g. it will look for a public ``preUpdate()`` method if you are listening to the ``preUpdate`` event. -- When a listener mapping is given the parser will not look for any methods using the naming convention. - -.. code-block:: php - - - - - - - - - - - - - - - - - - - - - - .. code-block:: yaml - - MyProject\Entity\User: - type: entity - entityListeners: - UserListener: - preFlush: [preFlushHandler] - postLoad: [postLoadHandler] - - postPersist: [postPersistHandler] - prePersist: [prePersistHandler] - - postUpdate: [postUpdateHandler] - preUpdate: [preUpdateHandler] - - postRemove: [postRemoveHandler] - preRemove: [preRemoveHandler] - # .... - -.. note:: - - The order of execution of multiple methods for the same event (e.g. multiple @PrePersist) is not guaranteed. - - -Entity listeners resolver -~~~~~~~~~~~~~~~~~~~~~~~~~~ -Doctrine invokes the listener resolver to get the listener instance. - -- A resolver allows you register a specific entity listener instance. -- You can also implement your own resolver by extending ``Doctrine\ORM\Mapping\DefaultEntityListenerResolver`` or implementing ``Doctrine\ORM\Mapping\EntityListenerResolver`` - -Specifying an entity listener instance : - -.. code-block:: php - - service = $service; - } - - public function preUpdate(User $user, PreUpdateEventArgs $event) - { - $this->service->doSomething($user); - } - } - - // register a entity listener. - $listener = $container->get('user_listener'); - $em->getConfiguration()->getEntityListenerResolver()->register($listener); - -Implementing your own resolver : - -.. code-block:: php - - container = $container; - } - - public function resolve($className) - { - // resolve the service id by the given class name; - $id = 'user_listener'; - - return $this->container->get($id); - } - } - - // Configure the listener resolver only before instantiating the EntityManager - $configurations->setEntityListenerResolver(new MyEntityListenerResolver); - EntityManager::create(.., $configurations, ..); - -Load ClassMetadata Event ------------------------- - -When the mapping information for an entity is read, it is populated -in to a ``ClassMetadataInfo`` instance. You can hook in to this -process and manipulate the instance. - -.. code-block:: php - - getMetadataFactory(); - $evm = $em->getEventManager(); - $evm->addEventListener(Events::loadClassMetadata, $test); - - class TestEvent - { - public function loadClassMetadata(\Doctrine\ORM\Event\LoadClassMetadataEventArgs $eventArgs) - { - $classMetadata = $eventArgs->getClassMetadata(); - $fieldMapping = array( - 'fieldName' => 'about', - 'type' => 'string', - 'length' => 255 - ); - $classMetadata->mapField($fieldMapping); - } - } - - diff --git a/vendor/doctrine/orm/docs/en/reference/faq.rst b/vendor/doctrine/orm/docs/en/reference/faq.rst deleted file mode 100644 index ca7784e..0000000 --- a/vendor/doctrine/orm/docs/en/reference/faq.rst +++ /dev/null @@ -1,233 +0,0 @@ -Frequently Asked Questions -========================== - -.. note:: - - This FAQ is a work in progress. We will add lots of questions and not answer them right away just to remember - what is often asked. If you stumble across an unanswered question please write a mail to the mailing-list or - join the #doctrine channel on Freenode IRC. - -Database Schema ---------------- - -How do I set the charset and collation for MySQL tables? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can't set these values inside the annotations, yml or xml mapping files. To make a database -work with the default charset and collation you should configure MySQL to use it as default charset, -or create the database with charset and collation details. This way they get inherited to all newly -created database tables and columns. - -Entity Classes --------------- - -How can I add default values to a column? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Doctrine does not support to set the default values in columns through the "DEFAULT" keyword in SQL. -This is not necessary however, you can just use your class properties as default values. These are then used -upon insert: - -.. code-block:: php - - class User - { - const STATUS_DISABLED = 0; - const STATUS_ENABLED = 1; - - private $algorithm = "sha1"; - private $status = self:STATUS_DISABLED; - } - -. - -Mapping -------- - -Why do I get exceptions about unique constraint failures during ``$em->flush()``? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Doctrine does not check if you are re-adding entities with a primary key that already exists -or adding entities to a collection twice. You have to check for both conditions yourself -in the code before calling ``$em->flush()`` if you know that unique constraint failures -can occur. - -In `Symfony2 `_ for example there is a Unique Entity Validator -to achieve this task. - -For collections you can check with ``$collection->contains($entity)`` if an entity is already -part of this collection. For a FETCH=LAZY collection this will initialize the collection, -however for FETCH=EXTRA_LAZY this method will use SQL to determine if this entity is already -part of the collection. - -Associations ------------- - -What is wrong when I get an InvalidArgumentException "A new entity was found through the relationship.."? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This exception is thrown during ``EntityManager#flush()`` when there exists an object in the identity map -that contains a reference to an object that Doctrine does not know about. Say for example you grab -a "User"-entity from the database with a specific id and set a completely new object into one of the associations -of the User object. If you then call ``EntityManager#flush()`` without letting Doctrine know about -this new object using ``EntityManager#persist($newObject)`` you will see this exception. - -You can solve this exception by: - -* Calling ``EntityManager#persist($newObject)`` on the new object -* Using cascade=persist on the association that contains the new object - -How can I filter an association? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Natively you can't filter associations in 2.0 and 2.1. You should use DQL queries to query for the filtered set of entities. - -I call clear() on a One-To-Many collection but the entities are not deleted -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This is an expected behavior that has to do with the inverse/owning side handling of Doctrine. -By definition a One-To-Many association is on the inverse side, that means changes to it -will not be recognized by Doctrine. - -If you want to perform the equivalent of the clear operation you have to iterate the -collection and set the owning side many-to-one reference to NULL as well to detach all entities -from the collection. This will trigger the appropriate UPDATE statements on the database. - -How can I add columns to a many-to-many table? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The many-to-many association is only supporting foreign keys in the table definition -To work with many-to-many tables containing extra columns you have to use the -foreign keys as primary keys feature of Doctrine introduced in version 2.1. - -See :doc:`the tutorial on composite primary keys for more information<../tutorials/composite-primary-keys>`. - - -How can i paginate fetch-joined collections? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you are issuing a DQL statement that fetches a collection as well you cannot easily iterate -over this collection using a LIMIT statement (or vendor equivalent). - -Doctrine does not offer a solution for this out of the box but there are several extensions -that do: - -* `DoctrineExtensions `_ -* `Pagerfanta `_ - -Why does pagination not work correctly with fetch joins? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Pagination in Doctrine uses a LIMIT clause (or vendor equivalent) to restrict the results. -However when fetch-joining this is not returning the correct number of results since joining -with a one-to-many or many-to-many association multiplies the number of rows by the number -of associated entities. - -See the previous question for a solution to this task. - -Inheritance ------------ - -Can I use Inheritance with Doctrine 2? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Yes, you can use Single- or Joined-Table Inheritance in Doctrine 2. - -See the documentation chapter on :doc:`inheritance mapping ` for -the details. - -Why does Doctrine not create proxy objects for my inheritance hierarchy? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you set a many-to-one or one-to-one association target-entity to any parent class of -an inheritance hierarchy Doctrine does not know what PHP class the foreign is actually of. -To find this out it has to execute a SQL query to look this information up in the database. - -EntityGenerator ---------------- - -Why does the EntityGenerator not do X? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The EntityGenerator is not a full fledged code-generator that solves all tasks. Code-Generation -is not a first-class priority in Doctrine 2 anymore (compared to Doctrine 1). The EntityGenerator -is supposed to kick-start you, but not towards 100%. - -Why does the EntityGenerator not generate inheritance correctly? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Just from the details of the discriminator map the EntityGenerator cannot guess the inheritance hierarchy. -This is why the generation of inherited entities does not fully work. You have to adjust some additional -code to get this one working correctly. - -Performance ------------ - -Why is an extra SQL query executed every time I fetch an entity with a one-to-one relation? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If Doctrine detects that you are fetching an inverse side one-to-one association -it has to execute an additional query to load this object, because it cannot know -if there is no such object (setting null) or if it should set a proxy and which id this proxy has. - -To solve this problem currently a query has to be executed to find out this information. - -Doctrine Query Language ------------------------ - -What is DQL? -~~~~~~~~~~~~ - -DQL stands for Doctrine Query Language, a query language that very much looks like SQL -but has some important benefits when using Doctrine: - -- It uses class names and fields instead of tables and columns, separating concerns between backend and your object model. -- It utilizes the metadata defined to offer a range of shortcuts when writing. For example you do not have to specify the ON clause of joins, since Doctrine already knows about them. -- It adds some functionality that is related to object management and transforms them into SQL. - -It also has some drawbacks of course: - -- The syntax is slightly different to SQL so you have to learn and remember the differences. -- To be vendor independent it can only implement a subset of all the existing SQL dialects. Vendor specific functionality and optimizations cannot be used through DQL unless implemented by you explicitly. -- For some DQL constructs subselects are used which are known to be slow in MySQL. - -Can I sort by a function (for example ORDER BY RAND()) in DQL? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -No, it is not supported to sort by function in DQL. If you need this functionality you should either -use a native-query or come up with another solution. As a side note: Sorting with ORDER BY RAND() is painfully slow -starting with 1000 rows. - -Is it better to write DQL or to generate it with the query builder? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The purpose of the ``QueryBuilder`` is to generate DQL dynamically, -which is useful when you have optional filters, conditional joins, etc. - -But the ``QueryBuilder`` is not an alternative to DQL, it actually generates DQL -queries at runtime, which are then interpreted by Doctrine. This means that -using the ``QueryBuilder`` to build and run a query is actually always slower -than only running the corresponding DQL query. - -So if you only need to generate a query and bind parameters to it, -you should use plain DQL, as this is a simpler and much more readable solution. -You should only use the ``QueryBuilder`` when you can't achieve what you want to do with a DQL query. - -A Query fails, how can I debug it? ----------------------------------- - -First, if you are using the QueryBuilder you can use -``$queryBuilder->getDQL()`` to get the DQL string of this query. The -corresponding SQL you can get from the Query instance by calling -``$query->getSQL()``. - -.. code-block:: php - - createQuery($dql); - var_dump($query->getSQL()); - - $qb = $entityManager->createQueryBuilder(); - $qb->select('u')->from('User', 'u'); - var_dump($qb->getDQL()); diff --git a/vendor/doctrine/orm/docs/en/reference/filters.rst b/vendor/doctrine/orm/docs/en/reference/filters.rst deleted file mode 100644 index 8783526..0000000 --- a/vendor/doctrine/orm/docs/en/reference/filters.rst +++ /dev/null @@ -1,93 +0,0 @@ -Filters -======= - -.. versionadded:: 2.2 - -Doctrine 2.2 features a filter system that allows the developer to add SQL to -the conditional clauses of queries, regardless the place where the SQL is -generated (e.g. from a DQL query, or by loading associated entities). - -The filter functionality works on SQL level. Whether a SQL query is generated -in a Persister, during lazy loading, in extra lazy collections or from DQL. -Each time the system iterates over all the enabled filters, adding a new SQL -part as a filter returns. - -By adding SQL to the conditional clauses of queries, the filter system filters -out rows belonging to the entities at the level of the SQL result set. This -means that the filtered entities are never hydrated (which can be expensive). - - -Example filter class --------------------- -Throughout this document the example ``MyLocaleFilter`` class will be used to -illustrate how the filter feature works. A filter class must extend the base -``Doctrine\ORM\Query\Filter\SQLFilter`` class and implement the ``addFilterConstraint`` -method. The method receives the ``ClassMetadata`` of the filtered entity and the -table alias of the SQL table of the entity. - -.. note:: - - In the case of joined or single table inheritance, you always get passed the ClassMetadata of the - inheritance root. This is necessary to avoid edge cases that would break the SQL when applying the filters. - -Parameters for the query should be set on the filter object by -``SQLFilter#setParameter()``. Only parameters set via this function can be used -in filters. The ``SQLFilter#getParameter()`` function takes care of the -proper quoting of parameters. - -.. code-block:: php - - reflClass->implementsInterface('LocaleAware')) { - return ""; - } - - return $targetTableAlias.'.locale = ' . $this->getParameter('locale'); // getParameter applies quoting automatically - } - } - - -Configuration -------------- -Filter classes are added to the configuration as following: - -.. code-block:: php - - addFilter("locale", "\Doctrine\Tests\ORM\Functional\MyLocaleFilter"); - - -The ``Configuration#addFilter()`` method takes a name for the filter and the name of the -class responsible for the actual filtering. - - -Disabling/Enabling Filters and Setting Parameters ---------------------------------------------------- -Filters can be disabled and enabled via the ``FilterCollection`` which is -stored in the ``EntityManager``. The ``FilterCollection#enable($name)`` method -will retrieve the filter object. You can set the filter parameters on that -object. - -.. code-block:: php - - getFilters()->enable("locale"); - $filter->setParameter('locale', 'en'); - - // Disable it - $filter = $em->getFilters()->disable("locale"); - -.. warning:: - Disabling and enabling filters has no effect on managed entities. If you - want to refresh or reload an object after having modified a filter or the - FilterCollection, then you should clear the EntityManager and re-fetch your - entities, having the new rules for filtering applied. diff --git a/vendor/doctrine/orm/docs/en/reference/improving-performance.rst b/vendor/doctrine/orm/docs/en/reference/improving-performance.rst deleted file mode 100644 index d7ed74f..0000000 --- a/vendor/doctrine/orm/docs/en/reference/improving-performance.rst +++ /dev/null @@ -1,73 +0,0 @@ -Improving Performance -===================== - -Bytecode Cache --------------- - -It is highly recommended to make use of a bytecode cache like OPcache. -A bytecode cache removes the need for parsing PHP code on every -request and can greatly improve performance. - - "If you care about performance and don't use a bytecode - cache then you don't really care about performance. Please get one - and start using it." - - *Stas Malyshev, Core Contributor to PHP and Zend Employee* - - -Metadata and Query caches -------------------------- - -As already mentioned earlier in the chapter about configuring -Doctrine, it is strongly discouraged to use Doctrine without a -Metadata and Query cache (preferably with APC or Memcache as the -cache driver). Operating Doctrine without these caches means -Doctrine will need to load your mapping information on every single -request and has to parse each DQL query on every single request. -This is a waste of resources. - -See :ref:`integrating-with-the-orm` - -Alternative Query Result Formats --------------------------------- - -Make effective use of the available alternative query result -formats like nested array graphs or pure scalar results, especially -in scenarios where data is loaded for read-only purposes. - -Read-Only Entities ------------------- - -Starting with Doctrine 2.1 you can mark entities as read only (See metadata mapping -references for details). This means that the entity marked as read only is never considered -for updates, which means when you call flush on the EntityManager these entities are skipped -even if properties changed. Read-Only allows to persist new entities of a kind and remove existing -ones, they are just not considered for updates. - -See :ref:`annref_entity` - -Extra-Lazy Collections ----------------------- - -If entities hold references to large collections you will get performance and memory problems initializing them. -To solve this issue you can use the EXTRA_LAZY fetch-mode feature for collections. See the :doc:`tutorial <../tutorials/extra-lazy-associations>` -for more information on how this fetch mode works. - -Temporarily change fetch mode in DQL ------------------------------------- - -See :ref:`dql-temporarily-change-fetch-mode` - - -Apply Best Practices --------------------- - -A lot of the points mentioned in the Best Practices chapter will -also positively affect the performance of Doctrine. - -See :doc:`Best Practices ` - -Change Tracking policies ------------------------- - -See: :doc:`Change Tracking Policies ` diff --git a/vendor/doctrine/orm/docs/en/reference/inheritance-mapping.rst b/vendor/doctrine/orm/docs/en/reference/inheritance-mapping.rst deleted file mode 100644 index 4d21ac7..0000000 --- a/vendor/doctrine/orm/docs/en/reference/inheritance-mapping.rst +++ /dev/null @@ -1,606 +0,0 @@ -Inheritance Mapping -=================== - -Mapped Superclasses -------------------- - -A mapped superclass is an abstract or concrete class that provides -persistent entity state and mapping information for its subclasses, -but which is not itself an entity. Typically, the purpose of such a -mapped superclass is to define state and mapping information that -is common to multiple entity classes. - -Mapped superclasses, just as regular, non-mapped classes, can -appear in the middle of an otherwise mapped inheritance hierarchy -(through Single Table Inheritance or Class Table Inheritance). - -.. note:: - - A mapped superclass cannot be an entity, it is not query-able and - persistent relationships defined by a mapped superclass must be - unidirectional (with an owning side only). This means that One-To-Many - associations are not possible on a mapped superclass at all. - Furthermore Many-To-Many associations are only possible if the - mapped superclass is only used in exactly one entity at the moment. - For further support of inheritance, the single or - joined table inheritance features have to be used. - - -Example: - -.. code-block:: php - - `_ -is an inheritance mapping strategy where all classes of a hierarchy -are mapped to a single database table. In order to distinguish -which row represents which type in the hierarchy a so-called -discriminator column is used. - -Example: - -.. configuration-block:: - - .. code-block:: php - - `_ -is an inheritance mapping strategy where each class in a hierarchy -is mapped to several tables: its own table and the tables of all -parent classes. The table of a child class is linked to the table -of a parent class through a foreign key constraint. Doctrine 2 -implements this strategy through the use of a discriminator column -in the topmost table of the hierarchy because this is the easiest -way to achieve polymorphic queries with Class Table Inheritance. - -Example: - -.. code-block:: php - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .. code-block:: yaml - - # user mapping - MyProject\Model\User: - type: mappedSuperclass - # other fields mapping - manyToOne: - address: - targetEntity: Address - joinColumn: - name: address_id - referencedColumnName: id - cascade: [ persist, merge ] - manyToMany: - groups: - targetEntity: Group - joinTable: - name: users_groups - joinColumns: - user_id: - referencedColumnName: id - inverseJoinColumns: - group_id: - referencedColumnName: id - cascade: [ persist, merge, detach ] - - # admin mapping - MyProject\Model\Admin: - type: entity - associationOverride: - address: - joinColumn: - adminaddress_id: - name: adminaddress_id - referencedColumnName: id - groups: - joinTable: - name: users_admingroups - joinColumns: - adminuser_id: - referencedColumnName: id - inverseJoinColumns: - admingroup_id: - referencedColumnName: id - - -Things to note: - -- The "association override" specifies the overrides base on the property name. -- This feature is available for all kind of associations. (OneToOne, OneToMany, ManyToOne, ManyToMany) -- The association type *CANNOT* be changed. -- The override could redefine the joinTables or joinColumns depending on the association type. -- The override could redefine inversedBy to reference more than one extended entity. -- The override could redefine fetch to modify the fetch strategy of the extended entity. - -Attribute Override -~~~~~~~~~~~~~~~~~~~~ -Override the mapping of a field. - -Could be used by an entity that extends a mapped superclass to override a field mapping defined by the mapped superclass. - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .. code-block:: yaml - - # user mapping - MyProject\Model\User: - type: mappedSuperclass - id: - id: - type: integer - column: user_id - length: 150 - generator: - strategy: AUTO - fields: - name: - type: string - column: user_name - length: 250 - nullable: true - unique: false - #other fields mapping - - - # guest mapping - MyProject\Model\Guest: - type: entity - attributeOverride: - id: - column: guest_id - type: integer - length: 140 - name: - column: guest_name - type: string - length: 240 - nullable: false - unique: true - -Things to note: - -- The "attribute override" specifies the overrides base on the property name. -- The column type *CANNOT* be changed. If the column type is not equal you get a ``MappingException`` -- The override can redefine all the columns except the type. - -Query the Type --------------- - -It may happen that the entities of a special type should be queried. Because there -is no direct access to the discriminator column, Doctrine provides the -``INSTANCE OF`` construct. - -The following example shows how to use ``INSTANCE OF``. There is a three level hierarchy -with a base entity ``NaturalPerson`` which is extended by ``Staff`` which in turn -is extended by ``Technician``. - -Querying for the staffs without getting any technicians can be achieved by this DQL: - -.. code-block:: php - - createQuery("SELECT staff FROM MyProject\Model\Staff staff WHERE staff NOT INSTANCE OF MyProject\Model\Technician"); - $staffs = $query->getResult(); diff --git a/vendor/doctrine/orm/docs/en/reference/installation.rst b/vendor/doctrine/orm/docs/en/reference/installation.rst deleted file mode 100644 index fec8378..0000000 --- a/vendor/doctrine/orm/docs/en/reference/installation.rst +++ /dev/null @@ -1,4 +0,0 @@ -Installation -============ - -The installation chapter has moved to :doc:`Installation and Configuration `_. diff --git a/vendor/doctrine/orm/docs/en/reference/limitations-and-known-issues.rst b/vendor/doctrine/orm/docs/en/reference/limitations-and-known-issues.rst deleted file mode 100644 index 143d53b..0000000 --- a/vendor/doctrine/orm/docs/en/reference/limitations-and-known-issues.rst +++ /dev/null @@ -1,203 +0,0 @@ -Limitations and Known Issues -============================ - -We try to make using Doctrine2 a very pleasant experience. -Therefore we think it is very important to be honest about the -current limitations to our users. Much like every other piece of -software Doctrine2 is not perfect and far from feature complete. -This section should give you an overview of current limitations of -Doctrine 2 as well as critical known issues that you should know -about. - -Current Limitations -------------------- - -There is a set of limitations that exist currently which might be -solved in the future. Any of this limitations now stated has at -least one ticket in the Tracker and is discussed for future -releases. - -Join-Columns with non-primary keys -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -It is not possible to use join columns pointing to non-primary keys. Doctrine will think these are the primary -keys and create lazy-loading proxies with the data, which can lead to unexpected results. Doctrine can for performance -reasons not validate the correctness of this settings at runtime but only through the Validate Schema command. - -Mapping Arrays to a Join Table -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Related to the previous limitation with "Foreign Keys as -Identifier" you might be interested in mapping the same table -structure as given above to an array. However this is not yet -possible either. See the following example: - -.. code-block:: sql - - CREATE TABLE product ( - id INTEGER, - name VARCHAR, - PRIMARY KEY(id) - ); - - CREATE TABLE product_attributes ( - product_id INTEGER, - attribute_name VARCHAR, - attribute_value VARCHAR, - PRIMARY KEY (product_id, attribute_name) - ); - -This schema should be mapped to a Product Entity as follows: - -.. code-block:: php - - class Product - { - private $id; - private $name; - private $attributes = array(); - } - -Where the ``attribute_name`` column contains the key and -``attribute_value`` contains the value of each array element in -``$attributes``. - -The feature request for persistence of primitive value arrays -`is described in the DDC-298 ticket `_. - -Cascade Merge with Bi-directional Associations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There are two bugs now that concern the use of cascade merge in combination with bi-directional associations. -Make sure to study the behavior of cascade merge if you are using it: - -- `DDC-875 `_ Merge can sometimes add the same entity twice into a collection -- `DDC-763 `_ Cascade merge on associated entities can insert too many rows through "Persistence by Reachability" - -Custom Persisters -~~~~~~~~~~~~~~~~~ - -A Persister in Doctrine is an object that is responsible for the -hydration and write operations of an entity against the database. -Currently there is no way to overwrite the persister implementation -for a given entity, however there are several use-cases that can -benefit from custom persister implementations: - -- `Add Upsert Support `_ -- `Evaluate possible ways in which stored-procedures can be used `_ - -Persist Keys of Collections -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -PHP Arrays are ordered hash-maps and so should be the -``Doctrine\Common\Collections\Collection`` interface. We plan to -evaluate a feature that optionally persists and hydrates the keys -of a Collection instance. - -`Ticket DDC-213 `_ - -Mapping many tables to one entity -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -It is not possible to map several equally looking tables onto one -entity. For example if you have a production and an archive table -of a certain business concept then you cannot have both tables map -to the same entity. - -Behaviors -~~~~~~~~~ - -Doctrine 2 will **never** include a behavior system like Doctrine 1 -in the core library. We don't think behaviors add more value than -they cost pain and debugging hell. Please see the many different -blog posts we have written on this topics: - -- `Doctrine2 "Behaviors" in a Nutshell `_ -- `A re-usable Versionable behavior for Doctrine2 `_ -- `Write your own ORM on top of Doctrine2 `_ -- `Doctrine 2 Behavioral Extensions `_ - -Doctrine 2 has enough hooks and extension points so that **you** can -add whatever you want on top of it. None of this will ever become -core functionality of Doctrine2 however, you will have to rely on -third party extensions for magical behaviors. - -Nested Set -~~~~~~~~~~ - -NestedSet was offered as a behavior in Doctrine 1 and will not be -included in the core of Doctrine 2. However there are already two -extensions out there that offer support for Nested Set with -Doctrine 2: - - -- `Doctrine2 Hierarchical-Structural Behavior `_ -- `Doctrine2 NestedSet `_ - -Known Issues ------------- - -The Known Issues section describes critical/blocker bugs and other -issues that are either complicated to fix, not fixable due to -backwards compatibility issues or where no simple fix exists (yet). -We don't plan to add every bug in the tracker there, just those -issues that can potentially cause nightmares or pain of any sort. - -See bugs, improvement and feature requests on `Github issues `_. - -Identifier Quoting and Legacy Databases -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For compatibility reasons between all the supported vendors and -edge case problems Doctrine 2 does **NOT** do automatic identifier -quoting. This can lead to problems when trying to get -legacy-databases to work with Doctrine 2. - - -- You can quote column-names as described in the - :doc:`Basic-Mapping ` section. -- You cannot quote join column names. -- You cannot use non [a-zA-Z0-9\_]+ characters, they will break - several SQL statements. - -Having problems with these kind of column names? Many databases -support all CRUD operations on views that semantically map to -certain tables. You can create views for all your problematic -tables and column names to avoid the legacy quoting nightmare. - -Microsoft SQL Server and Doctrine "datetime" -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Doctrine assumes that you use ``DateTime2`` data-types. If your legacy database contains DateTime -datatypes then you have to add your own data-type (see Basic Mapping for an example). - -MySQL with MyISAM tables -~~~~~~~~~~~~~~~~~~~~~~~~ - -Doctrine cannot provide atomic operations when calling ``EntityManager#flush()`` if one -of the tables involved uses the storage engine MyISAM. You must use InnoDB or -other storage engines that support transactions if you need integrity. - -Entities, Proxies and Reflection -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Using methods for Reflection on entities can be prone to error, when the entity -is actually a proxy the following methods will not work correctly: - -- ``new ReflectionClass`` -- ``new ReflectionObject`` -- ``get_class()`` -- ``get_parent_class()`` - -This is why ``Doctrine\Common\Util\ClassUtils`` class exists that has similar -methods, which resolve the proxy problem beforehand. - -.. code-block:: php - - getReference('Acme\Book'); - - $reflection = ClassUtils::newReflectionClass($bookProxy); - $class = ClassUtils::getClass($bookProxy)¸ diff --git a/vendor/doctrine/orm/docs/en/reference/metadata-drivers.rst b/vendor/doctrine/orm/docs/en/reference/metadata-drivers.rst deleted file mode 100644 index 5162dee..0000000 --- a/vendor/doctrine/orm/docs/en/reference/metadata-drivers.rst +++ /dev/null @@ -1,194 +0,0 @@ -Metadata Drivers -================ - -The heart of an object relational mapper is the mapping information -that glues everything together. It instructs the EntityManager how -it should behave when dealing with the different entities. - -Core Metadata Drivers ---------------------- - -Doctrine provides a few different ways for you to specify your -metadata: - - -- **XML files** (XmlDriver) -- **Class DocBlock Annotations** (AnnotationDriver) -- **YAML files** (YamlDriver) -- **PHP Code in files or static functions** (PhpDriver) - -Something important to note about the above drivers is they are all -an intermediate step to the same end result. The mapping -information is populated to ``Doctrine\ORM\Mapping\ClassMetadata`` -instances. So in the end, Doctrine only ever has to work with the -API of the ``ClassMetadata`` class to get mapping information for -an entity. - -.. note:: - - The populated ``ClassMetadata`` instances are also cached - so in a production environment the parsing and populating only ever - happens once. You can configure the metadata cache implementation - using the ``setMetadataCacheImpl()`` method on the - ``Doctrine\ORM\Configuration`` class: - - .. code-block:: php - - getConfiguration()->setMetadataCacheImpl(new ApcuCache()); - - -If you want to use one of the included core metadata drivers you -just need to configure it. All the drivers are in the -``Doctrine\ORM\Mapping\Driver`` namespace: - -.. code-block:: php - - getConfiguration()->setMetadataDriverImpl($driver); - -Implementing Metadata Drivers ------------------------------ - -In addition to the included metadata drivers you can very easily -implement your own. All you need to do is define a class which -implements the ``Driver`` interface: - -.. code-block:: php - - _loadMappingFile($file); - - // populate ClassMetadataInfo instance from $data - } - - /** - * {@inheritdoc} - */ - protected function _loadMappingFile($file) - { - // parse contents of $file and return php data structure - } - } - -.. note:: - - When using the ``AbstractFileDriver`` it requires that you - only have one entity defined per file and the file named after the - class described inside where namespace separators are replaced by - periods. So if you have an entity named ``Entities\User`` and you - wanted to write a mapping file for your driver above you would need - to name the file ``Entities.User.dcm.ext`` for it to be - recognized. - - -Now you can use your ``MyMetadataDriver`` implementation by setting -it with the ``setMetadataDriverImpl()`` method: - -.. code-block:: php - - getConfiguration()->setMetadataDriverImpl($driver); - -ClassMetadata -------------- - -The last piece you need to know and understand about metadata in -Doctrine 2 is the API of the ``ClassMetadata`` classes. You need to -be familiar with them in order to implement your own drivers but -more importantly to retrieve mapping information for a certain -entity when needed. - -You have all the methods you need to manually specify the mapping -information instead of using some mapping file to populate it from. -The base ``ClassMetadataInfo`` class is responsible for only data -storage and is not meant for runtime use. It does not require that -the class actually exists yet so it is useful for describing some -entity before it exists and using that information to generate for -example the entities themselves. The class ``ClassMetadata`` -extends ``ClassMetadataInfo`` and adds some functionality required -for runtime usage and requires that the PHP class is present and -can be autoloaded. - -You can read more about the API of the ``ClassMetadata`` classes in -the PHP Mapping chapter. - -Getting ClassMetadata Instances -------------------------------- - -If you want to get the ``ClassMetadata`` instance for an entity in -your project to programmatically use some mapping information to -generate some HTML or something similar you can retrieve it through -the ``ClassMetadataFactory``: - -.. code-block:: php - - getMetadataFactory(); - $class = $cmf->getMetadataFor('MyEntityName'); - -Now you can learn about the entity and use the data stored in the -``ClassMetadata`` instance to get all mapped fields for example and -iterate over them: - -.. code-block:: php - - fieldMappings as $fieldMapping) { - echo $fieldMapping['fieldName'] . "\n"; - } - - diff --git a/vendor/doctrine/orm/docs/en/reference/namingstrategy.rst b/vendor/doctrine/orm/docs/en/reference/namingstrategy.rst deleted file mode 100644 index 23aa573..0000000 --- a/vendor/doctrine/orm/docs/en/reference/namingstrategy.rst +++ /dev/null @@ -1,137 +0,0 @@ -Implementing a NamingStrategy -============================== - -.. versionadded:: 2.3 - -Using a naming strategy you can provide rules for generating database identifiers, -column or table names when the column or table name is not given. This feature helps -reduce the verbosity of the mapping document, eliminating repetitive noise (eg: ``TABLE_``). - -Configuring a naming strategy ------------------------------ -The default strategy used by Doctrine is quite minimal. - -By default the ``Doctrine\ORM\Mapping\DefaultNamingStrategy`` -uses the simple class name and the attribute names to generate tables and columns. - -You can specify a different strategy by calling ``Doctrine\ORM\Configuration#setNamingStrategy()``: - -.. code-block:: php - - setNamingStrategy($namingStrategy); - -Underscore naming strategy ---------------------------- - -``\Doctrine\ORM\Mapping\UnderscoreNamingStrategy`` is a built-in strategy. - -.. code-block:: php - - setNamingStrategy($namingStrategy); - -For SomeEntityName the strategy will generate the table SOME_ENTITY_NAME with the -``CASE_UPPER`` option, or some_entity_name with the ``CASE_LOWER`` option. - -Naming strategy interface -------------------------- -The interface ``Doctrine\ORM\Mapping\NamingStrategy`` allows you to specify -a naming strategy for database tables and columns. - -.. code-block:: php - - referenceColumnName(); - } - public function joinTableName($sourceEntity, $targetEntity, $propertyName = null) - { - return strtolower($this->classToTableName($sourceEntity) . '_' . - $this->classToTableName($targetEntity)); - } - public function joinKeyColumnName($entityName, $referencedColumnName = null) - { - return strtolower($this->classToTableName($entityName) . '_' . - ($referencedColumnName ?: $this->referenceColumnName())); - } - } diff --git a/vendor/doctrine/orm/docs/en/reference/native-sql.rst b/vendor/doctrine/orm/docs/en/reference/native-sql.rst deleted file mode 100644 index 1676a8f..0000000 --- a/vendor/doctrine/orm/docs/en/reference/native-sql.rst +++ /dev/null @@ -1,905 +0,0 @@ -Native SQL -========== - -With ``NativeQuery`` you can execute native SELECT SQL statements -and map the results to Doctrine entities or any other result format -supported by Doctrine. - -In order to make this mapping possible, you need to describe -to Doctrine what columns in the result map to which entity property. -This description is represented by a ``ResultSetMapping`` object. - -With this feature you can map arbitrary SQL code to objects, such as highly -vendor-optimized SQL or stored-procedures. - -Writing ``ResultSetMapping`` from scratch is complex, but there is a convenience -wrapper around it called a ``ResultSetMappingBuilder``. It can generate -the mappings for you based on Entities and even generates the ``SELECT`` -clause based on this information for you. - -.. note:: - - If you want to execute DELETE, UPDATE or INSERT statements - the Native SQL API cannot be used and will probably throw errors. - Use ``EntityManager#getConnection()`` to access the native database - connection and call the ``executeUpdate()`` method for these - queries. - -The NativeQuery class ---------------------- - -To create a ``NativeQuery`` you use the method -``EntityManager#createNativeQuery($sql, $resultSetMapping)``. As you can see in -the signature of this method, it expects 2 ingredients: The SQL you want to -execute and the ``ResultSetMapping`` that describes how the results will be -mapped. - -Once you obtained an instance of a ``NativeQuery``, you can bind parameters to -it with the same API that ``Query`` has and execute it. - -.. code-block:: php - - createNativeQuery('SELECT id, name, discr FROM users WHERE name = ?', $rsm); - $query->setParameter(1, 'romanb'); - - $users = $query->getResult(); - -ResultSetMappingBuilder ------------------------ - -An easy start into ResultSet mapping is the ``ResultSetMappingBuilder`` object. -This has several benefits: - -- The builder takes care of automatically updating your ``ResultSetMapping`` - when the fields or associations change on the metadata of an entity. -- You can generate the required ``SELECT`` expression for a builder - by converting it to a string. -- The API is much simpler than the usual ``ResultSetMapping`` API. - -One downside is that the builder API does not yet support entities -with inheritance hierarchies. - -.. code-block:: php - - addRootEntityFromClassMetadata('MyProject\User', 'u'); - $rsm->addJoinedEntityFromClassMetadata('MyProject\Address', 'a', 'u', 'address', array('id' => 'address_id')); - -The builder extends the ``ResultSetMapping`` class and as such has all the functionality of it as well. - -.. versionadded:: 2.4 - -Starting with Doctrine ORM 2.4 you can generate the ``SELECT`` clause -from a ``ResultSetMappingBuilder``. You can either cast the builder -object to ``(string)`` and the DQL aliases are used as SQL table aliases -or use the ``generateSelectClause($tableAliases)`` method and pass -a mapping from DQL alias (key) to SQL alias (value) - -.. code-block:: php - - generateSelectClause(array( - 'u' => 't1', - 'g' => 't2' - )); - $sql = "SELECT " . $selectClause . " FROM users t1 JOIN groups t2 ON t1.group_id = t2.id"; - - -The ResultSetMapping --------------------- - -Understanding the ``ResultSetMapping`` is the key to using a -``NativeQuery``. A Doctrine result can contain the following -components: - - -- Entity results. These represent root result elements. -- Joined entity results. These represent joined entities in - associations of root entity results. -- Field results. These represent a column in the result set that - maps to a field of an entity. A field result always belongs to an - entity result or joined entity result. -- Scalar results. These represent scalar values in the result set - that will appear in each result row. Adding scalar results to a - ResultSetMapping can also cause the overall result to become - **mixed** (see DQL - Doctrine Query Language) if the same - ResultSetMapping also contains entity results. -- Meta results. These represent columns that contain - meta-information, such as foreign keys and discriminator columns. - When querying for objects (``getResult()``), all meta columns of - root entities or joined entities must be present in the SQL query - and mapped accordingly using ``ResultSetMapping#addMetaResult``. - -.. note:: - - It might not surprise you that Doctrine uses - ``ResultSetMapping`` internally when you create DQL queries. As - the query gets parsed and transformed to SQL, Doctrine fills a - ``ResultSetMapping`` that describes how the results should be - processed by the hydration routines. - - -We will now look at each of the result types that can appear in a -ResultSetMapping in detail. - -Entity results -~~~~~~~~~~~~~~ - -An entity result describes an entity type that appears as a root -element in the transformed result. You add an entity result through -``ResultSetMapping#addEntityResult()``. Let's take a look at the -method signature in detail: - -.. code-block:: php - - addEntityResult('User', 'u'); - $rsm->addFieldResult('u', 'id', 'id'); - $rsm->addFieldResult('u', 'name', 'name'); - - $query = $this->_em->createNativeQuery('SELECT id, name FROM users WHERE name = ?', $rsm); - $query->setParameter(1, 'romanb'); - - $users = $query->getResult(); - -The result would look like this: - -.. code-block:: php - - array( - [0] => User (Object) - ) - -Note that this would be a partial object if the entity has more -fields than just id and name. In the example above the column and -field names are identical but that is not necessary, of course. -Also note that the query string passed to createNativeQuery is -**real native SQL**. Doctrine does not touch this SQL in any way. - -In the previous basic example, a User had no relations and the -table the class is mapped to owns no foreign keys. The next example -assumes User has a unidirectional or bidirectional one-to-one -association to a CmsAddress, where the User is the owning side and -thus owns the foreign key. - -.. code-block:: php - - addEntityResult('User', 'u'); - $rsm->addFieldResult('u', 'id', 'id'); - $rsm->addFieldResult('u', 'name', 'name'); - $rsm->addMetaResult('u', 'address_id', 'address_id'); - - $query = $this->_em->createNativeQuery('SELECT id, name, address_id FROM users WHERE name = ?', $rsm); - $query->setParameter(1, 'romanb'); - - $users = $query->getResult(); - -Foreign keys are used by Doctrine for lazy-loading purposes when -querying for objects. In the previous example, each user object in -the result will have a proxy (a "ghost") in place of the address -that contains the address\_id. When the ghost proxy is accessed, it -loads itself based on this key. - -Consequently, associations that are *fetch-joined* do not require -the foreign keys to be present in the SQL result set, only -associations that are lazy. - -.. code-block:: php - - addEntityResult('User', 'u'); - $rsm->addFieldResult('u', 'id', 'id'); - $rsm->addFieldResult('u', 'name', 'name'); - $rsm->addJoinedEntityResult('Address' , 'a', 'u', 'address'); - $rsm->addFieldResult('a', 'address_id', 'id'); - $rsm->addFieldResult('a', 'street', 'street'); - $rsm->addFieldResult('a', 'city', 'city'); - - $sql = 'SELECT u.id, u.name, a.id AS address_id, a.street, a.city FROM users u ' . - 'INNER JOIN address a ON u.address_id = a.id WHERE u.name = ?'; - $query = $this->_em->createNativeQuery($sql, $rsm); - $query->setParameter(1, 'romanb'); - - $users = $query->getResult(); - -In this case the nested entity ``Address`` is registered with the -``ResultSetMapping#addJoinedEntityResult`` method, which notifies -Doctrine that this entity is not hydrated at the root level, but as -a joined entity somewhere inside the object graph. In this case we -specify the alias 'u' as third parameter and ``address`` as fourth -parameter, which means the ``Address`` is hydrated into the -``User::$address`` property. - -If a fetched entity is part of a mapped hierarchy that requires a -discriminator column, this column must be present in the result set -as a meta column so that Doctrine can create the appropriate -concrete type. This is shown in the following example where we -assume that there are one or more subclasses that extend User and -either Class Table Inheritance or Single Table Inheritance is used -to map the hierarchy (both use a discriminator column). - -.. code-block:: php - - addEntityResult('User', 'u'); - $rsm->addFieldResult('u', 'id', 'id'); - $rsm->addFieldResult('u', 'name', 'name'); - $rsm->addMetaResult('u', 'discr', 'discr'); // discriminator column - $rsm->setDiscriminatorColumn('u', 'discr'); - - $query = $this->_em->createNativeQuery('SELECT id, name, discr FROM users WHERE name = ?', $rsm); - $query->setParameter(1, 'romanb'); - - $users = $query->getResult(); - -Note that in the case of Class Table Inheritance, an example as -above would result in partial objects if any objects in the result -are actually a subtype of User. When using DQL, Doctrine -automatically includes the necessary joins for this mapping -strategy but with native SQL it is your responsibility. - -Named Native Query ------------------- - -You can also map a native query using a named native query mapping. - -To achieve that, you must describe the SQL resultset structure -using named native query (and sql resultset mappings if is a several resultset mappings). - -Like named query, a named native query can be defined at class level or in a XML or YAML file. - - -A resultSetMapping parameter is defined in @NamedNativeQuery, -it represents the name of a defined @SqlResultSetMapping. - -.. configuration-block:: - - .. code-block:: php - - - - - - SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM users u INNER JOIN addresses a ON u.id = a.user_id INNER JOIN phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username - - - - - - - - - - - - - - - - - - - - .. code-block:: yaml - - MyProject\Model\User: - type: entity - namedNativeQueries: - fetchMultipleJoinsEntityResults: - name: fetchMultipleJoinsEntityResults - resultSetMapping: mappingMultipleJoinsEntityResults - query: SELECT u.id AS u_id, u.name AS u_name, u.status AS u_status, a.id AS a_id, a.zip AS a_zip, a.country AS a_country, COUNT(p.phonenumber) AS numphones FROM users u INNER JOIN addresses a ON u.id = a.user_id INNER JOIN phonenumbers p ON u.id = p.user_id GROUP BY u.id, u.name, u.status, u.username, a.id, a.zip, a.country ORDER BY u.username - sqlResultSetMappings: - mappingMultipleJoinsEntityResults: - name: mappingMultipleJoinsEntityResults - columnResult: - 0: - name: numphones - entityResult: - 0: - entityClass: __CLASS__ - fieldResult: - 0: - name: id - column: u_id - 1: - name: name - column: u_name - 2: - name: status - column: u_status - 1: - entityClass: Address - fieldResult: - 0: - name: id - column: a_id - 1: - name: zip - column: a_zip - 2: - name: country - column: a_country - - -Things to note: - - The resultset mapping declares the entities retrieved by this native query. - - Each field of the entity is bound to a SQL alias (or column name). - - All fields of the entity including the ones of subclasses - and the foreign key columns of related entities have to be present in the SQL query. - - Field definitions are optional provided that they map to the same - column name as the one declared on the class property. - - ``__CLASS__`` is an alias for the mapped class - - -In the above example, -the ``fetchJoinedAddress`` named query use the joinMapping result set mapping. -This mapping returns 2 entities, User and Address, each property is declared and associated to a column name, -actually the column name retrieved by the query. - -Let's now see an implicit declaration of the property / column. - -.. configuration-block:: - - .. code-block:: php - - - - - - SELECT * FROM addresses - - - - - - - - - - .. code-block:: yaml - - MyProject\Model\Address: - type: entity - namedNativeQueries: - findAll: - resultSetMapping: mappingFindAll - query: SELECT * FROM addresses - sqlResultSetMappings: - mappingFindAll: - name: mappingFindAll - entityResult: - address: - entityClass: Address - - -In this example, we only describe the entity member of the result set mapping. -The property / column mappings is done using the entity mapping values. -In this case the model property is bound to the model_txt column. -If the association to a related entity involve a composite primary key, -a @FieldResult element should be used for each foreign key column. -The @FieldResult name is composed of the property name for the relationship, -followed by a dot ("."), followed by the name or the field or property of the primary key. - - -.. configuration-block:: - - .. code-block:: php - - - - - - SELECT u.id, u.name, u.status, a.id AS a_id, a.country AS a_country, a.zip AS a_zip, a.city AS a_city FROM users u INNER JOIN addresses a ON u.id = a.user_id WHERE u.username = ? - - - - - - - - - - - - - - - - - - .. code-block:: yaml - - MyProject\Model\User: - type: entity - namedNativeQueries: - fetchJoinedAddress: - name: fetchJoinedAddress - resultSetMapping: mappingJoinedAddress - query: SELECT u.id, u.name, u.status, a.id AS a_id, a.country AS a_country, a.zip AS a_zip, a.city AS a_city FROM users u INNER JOIN addresses a ON u.id = a.user_id WHERE u.username = ? - sqlResultSetMappings: - mappingJoinedAddress: - entityResult: - 0: - entityClass: __CLASS__ - fieldResult: - 0: - name: id - 1: - name: name - 2: - name: status - 3: - name: address.id - column: a_id - 4: - name: address.zip - column: a_zip - 5: - name: address.city - column: a_city - 6: - name: address.country - column: a_country - - - -If you retrieve a single entity and if you use the default mapping, -you can use the resultClass attribute instead of resultSetMapping: - -.. configuration-block:: - - .. code-block:: php - - - - - - SELECT * FROM addresses WHERE id = ? - - - - - .. code-block:: yaml - - MyProject\Model\Address: - type: entity - namedNativeQueries: - findAll: - name: findAll - resultClass: Address - query: SELECT * FROM addresses - - -In some of your native queries, you'll have to return scalar values, -for example when building report queries. -You can map them in the @SqlResultsetMapping through @ColumnResult. -You actually can even mix, entities and scalar returns in the same native query (this is probably not that common though). - -.. configuration-block:: - - .. code-block:: php - - - - - SELECT COUNT(*) AS count FROM addresses - - - - - - - - - .. code-block:: yaml - - MyProject\Model\Address: - type: entity - namedNativeQueries: - count: - name: count - resultSetMapping: mappingCount - query: SELECT COUNT(*) AS count FROM addresses - sqlResultSetMappings: - mappingCount: - name: mappingCount - columnResult: - count: - name: count diff --git a/vendor/doctrine/orm/docs/en/reference/partial-objects.rst b/vendor/doctrine/orm/docs/en/reference/partial-objects.rst deleted file mode 100644 index 396eecc..0000000 --- a/vendor/doctrine/orm/docs/en/reference/partial-objects.rst +++ /dev/null @@ -1,90 +0,0 @@ -Partial Objects -=============== - -A partial object is an object whose state is not fully initialized -after being reconstituted from the database and that is -disconnected from the rest of its data. The following section will -describe why partial objects are problematic and what the approach -of Doctrine2 to this problem is. - -.. note:: - - The partial object problem in general does not apply to - methods or queries where you do not retrieve the query result as - objects. Examples are: ``Query#getArrayResult()``, - ``Query#getScalarResult()``, ``Query#getSingleScalarResult()``, - etc. - -.. warning:: - - Use of partial objects is tricky. Fields that are not retrieved - from the database will not be updated by the UnitOfWork even if they - get changed in your objects. You can only promote a partial object - to a fully-loaded object by calling ``EntityManager#refresh()`` - or a DQL query with the refresh flag. - - -What is the problem? --------------------- - -In short, partial objects are problematic because they are usually -objects with broken invariants. As such, code that uses these -partial objects tends to be very fragile and either needs to "know" -which fields or methods can be safely accessed or add checks around -every field access or method invocation. The same holds true for -the internals, i.e. the method implementations, of such objects. -You usually simply assume the state you need in the method is -available, after all you properly constructed this object before -you pushed it into the database, right? These blind assumptions can -quickly lead to null reference errors when working with such -partial objects. - -It gets worse with the scenario of an optional association (0..1 to -1). When the associated field is NULL, you don't know whether this -object does not have an associated object or whether it was simply -not loaded when the owning object was loaded from the database. - -These are reasons why many ORMs do not allow partial objects at all -and instead you always have to load an object with all its fields -(associations being proxied). One secure way to allow partial -objects is if the programming language/platform allows the ORM tool -to hook deeply into the object and instrument it in such a way that -individual fields (not only associations) can be loaded lazily on -first access. This is possible in Java, for example, through -bytecode instrumentation. In PHP though this is not possible, so -there is no way to have "secure" partial objects in an ORM with -transparent persistence. - -Doctrine, by default, does not allow partial objects. That means, -any query that only selects partial object data and wants to -retrieve the result as objects (i.e. ``Query#getResult()``) will -raise an exception telling you that partial objects are dangerous. -If you want to force a query to return you partial objects, -possibly as a performance tweak, you can use the ``partial`` -keyword as follows: - -.. code-block:: php - - createQuery("select partial u.{id,name} from MyApp\Domain\User u"); - -You can also get a partial reference instead of a proxy reference by -calling: - -.. code-block:: php - - getPartialReference('MyApp\Domain\User', 1); - -Partial references are objects with only the identifiers set as they -are passed to the second argument of the ``getPartialReference()`` method. -All other fields are null. - -When should I force partial objects? ------------------------------------- - -Mainly for optimization purposes, but be careful of premature -optimization as partial objects lead to potentially more fragile -code. - - diff --git a/vendor/doctrine/orm/docs/en/reference/php-mapping.rst b/vendor/doctrine/orm/docs/en/reference/php-mapping.rst deleted file mode 100644 index 78a7214..0000000 --- a/vendor/doctrine/orm/docs/en/reference/php-mapping.rst +++ /dev/null @@ -1,325 +0,0 @@ -PHP Mapping -=========== - -Doctrine 2 also allows you to provide the ORM metadata in the form -of plain PHP code using the ``ClassMetadata`` API. You can write -the code in PHP files or inside of a static function named -``loadMetadata($class)`` on the entity class itself. - -PHP Files ---------- - -If you wish to write your mapping information inside PHP files that -are named after the entity and included to populate the metadata -for an entity you can do so by using the ``PHPDriver``: - -.. code-block:: php - - getConfiguration()->setMetadataDriverImpl($driver); - -Now imagine we had an entity named ``Entities\User`` and we wanted -to write a mapping file for it using the above configured -``PHPDriver`` instance: - -.. code-block:: php - - mapField(array( - 'id' => true, - 'fieldName' => 'id', - 'type' => 'integer' - )); - - $metadata->mapField(array( - 'fieldName' => 'username', - 'type' => 'string', - 'options' => array( - 'fixed' => true, - 'comment' => "User's login name" - ) - )); - - $metadata->mapField(array( - 'fieldName' => 'login_count', - 'type' => 'integer', - 'nullable' => false, - 'options' => array( - 'unsigned' => true, - 'default' => 0 - ) - )); - -Now we can easily retrieve the populated ``ClassMetadata`` instance -where the ``PHPDriver`` includes the file and the -``ClassMetadataFactory`` caches it for later retrieval: - -.. code-block:: php - - getClassMetadata('Entities\User'); - // or - $class = $em->getMetadataFactory()->getMetadataFor('Entities\User'); - -Static Function ---------------- - -In addition to the PHP files you can also specify your mapping -information inside of a static function defined on the entity class -itself. This is useful for cases where you want to keep your entity -and mapping information together but don't want to use annotations. -For this you just need to use the ``StaticPHPDriver``: - -.. code-block:: php - - getConfiguration()->setMetadataDriverImpl($driver); - -Now you just need to define a static function named -``loadMetadata($metadata)`` on your entity: - -.. code-block:: php - - mapField(array( - 'id' => true, - 'fieldName' => 'id', - 'type' => 'integer' - )); - - $metadata->mapField(array( - 'fieldName' => 'username', - 'type' => 'string' - )); - } - } - -ClassMetadataBuilder --------------------- - -To ease the use of the ClassMetadata API (which is very raw) there is a ``ClassMetadataBuilder`` that you can use. - -.. code-block:: php - - createField('id', 'integer')->isPrimaryKey()->generatedValue()->build(); - $builder->addField('username', 'string'); - } - } - -The API of the ClassMetadataBuilder has the following methods with a fluent interface: - -- ``addField($name, $type, array $mapping)`` -- ``setMappedSuperclass()`` -- ``setReadOnly()`` -- ``setCustomRepositoryClass($className)`` -- ``setTable($name)`` -- ``addIndex(array $columns, $indexName)`` -- ``addUniqueConstraint(array $columns, $constraintName)`` -- ``addNamedQuery($name, $dqlQuery)`` -- ``setJoinedTableInheritance()`` -- ``setSingleTableInheritance()`` -- ``setDiscriminatorColumn($name, $type = 'string', $length = 255)`` -- ``addDiscriminatorMapClass($name, $class)`` -- ``setChangeTrackingPolicyDeferredExplicit()`` -- ``setChangeTrackingPolicyNotify()`` -- ``addLifecycleEvent($methodName, $event)`` -- ``addManyToOne($name, $targetEntity, $inversedBy = null)`` -- ``addInverseOneToOne($name, $targetEntity, $mappedBy)`` -- ``addOwningOneToOne($name, $targetEntity, $inversedBy = null)`` -- ``addOwningManyToMany($name, $targetEntity, $inversedBy = null)`` -- ``addInverseManyToMany($name, $targetEntity, $mappedBy)`` -- ``addOneToMany($name, $targetEntity, $mappedBy)`` - -It also has several methods that create builders (which are necessary for advanced mappings): - -- ``createField($name, $type)`` returns a ``FieldBuilder`` instance -- ``createManyToOne($name, $targetEntity)`` returns an ``AssociationBuilder`` instance -- ``createOneToOne($name, $targetEntity)`` returns an ``AssociationBuilder`` instance -- ``createManyToMany($name, $targetEntity)`` returns an ``ManyToManyAssociationBuilder`` instance -- ``createOneToMany($name, $targetEntity)`` returns an ``OneToManyAssociationBuilder`` instance - -ClassMetadataInfo API ---------------------- - -The ``ClassMetadataInfo`` class is the base data object for storing -the mapping metadata for a single entity. It contains all the -getters and setters you need populate and retrieve information for -an entity. - -General Setters -~~~~~~~~~~~~~~~ - - -- ``setTableName($tableName)`` -- ``setPrimaryTable(array $primaryTableDefinition)`` -- ``setCustomRepositoryClass($repositoryClassName)`` -- ``setIdGeneratorType($generatorType)`` -- ``setIdGenerator($generator)`` -- ``setSequenceGeneratorDefinition(array $definition)`` -- ``setChangeTrackingPolicy($policy)`` -- ``setIdentifier(array $identifier)`` - -Inheritance Setters -~~~~~~~~~~~~~~~~~~~ - - -- ``setInheritanceType($type)`` -- ``setSubclasses(array $subclasses)`` -- ``setParentClasses(array $classNames)`` -- ``setDiscriminatorColumn($columnDef)`` -- ``setDiscriminatorMap(array $map)`` - -Field Mapping Setters -~~~~~~~~~~~~~~~~~~~~~ - - -- ``mapField(array $mapping)`` -- ``mapOneToOne(array $mapping)`` -- ``mapOneToMany(array $mapping)`` -- ``mapManyToOne(array $mapping)`` -- ``mapManyToMany(array $mapping)`` - -Lifecycle Callback Setters -~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -- ``addLifecycleCallback($callback, $event)`` -- ``setLifecycleCallbacks(array $callbacks)`` - -Versioning Setters -~~~~~~~~~~~~~~~~~~ - - -- ``setVersionMapping(array &$mapping)`` -- ``setVersioned($bool)`` -- ``setVersionField()`` - -General Getters -~~~~~~~~~~~~~~~ - - -- ``getTableName()`` -- ``getSchemaName()`` -- ``getTemporaryIdTableName()`` - -Identifier Getters -~~~~~~~~~~~~~~~~~~ - - -- ``getIdentifierColumnNames()`` -- ``usesIdGenerator()`` -- ``isIdentifier($fieldName)`` -- ``isIdGeneratorIdentity()`` -- ``isIdGeneratorSequence()`` -- ``isIdGeneratorTable()`` -- ``isIdentifierNatural()`` -- ``getIdentifierFieldNames()`` -- ``getSingleIdentifierFieldName()`` -- ``getSingleIdentifierColumnName()`` - -Inheritance Getters -~~~~~~~~~~~~~~~~~~~ - - -- ``isInheritanceTypeNone()`` -- ``isInheritanceTypeJoined()`` -- ``isInheritanceTypeSingleTable()`` -- ``isInheritanceTypeTablePerClass()`` -- ``isInheritedField($fieldName)`` -- ``isInheritedAssociation($fieldName)`` - -Change Tracking Getters -~~~~~~~~~~~~~~~~~~~~~~~ - - -- ``isChangeTrackingDeferredExplicit()`` -- ``isChangeTrackingDeferredImplicit()`` -- ``isChangeTrackingNotify()`` - -Field & Association Getters -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -- ``isUniqueField($fieldName)`` -- ``isNullable($fieldName)`` -- ``getColumnName($fieldName)`` -- ``getFieldMapping($fieldName)`` -- ``getAssociationMapping($fieldName)`` -- ``getAssociationMappings()`` -- ``getFieldName($columnName)`` -- ``hasField($fieldName)`` -- ``getColumnNames(array $fieldNames = null)`` -- ``getTypeOfField($fieldName)`` -- ``getTypeOfColumn($columnName)`` -- ``hasAssociation($fieldName)`` -- ``isSingleValuedAssociation($fieldName)`` -- ``isCollectionValuedAssociation($fieldName)`` - -Lifecycle Callback Getters -~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -- ``hasLifecycleCallbacks($lifecycleEvent)`` -- ``getLifecycleCallbacks($event)`` - -ClassMetadata API ------------------ - -The ``ClassMetadata`` class extends ``ClassMetadataInfo`` and adds -the runtime functionality required by Doctrine. It adds a few extra -methods related to runtime reflection for working with the entities -themselves. - - -- ``getReflectionClass()`` -- ``getReflectionProperties()`` -- ``getReflectionProperty($name)`` -- ``getSingleIdReflectionProperty()`` -- ``getIdentifierValues($entity)`` -- ``setIdentifierValues($entity, $id)`` -- ``setFieldValue($entity, $field, $value)`` -- ``getFieldValue($entity, $field)`` - - diff --git a/vendor/doctrine/orm/docs/en/reference/query-builder.rst b/vendor/doctrine/orm/docs/en/reference/query-builder.rst deleted file mode 100644 index 91833ae..0000000 --- a/vendor/doctrine/orm/docs/en/reference/query-builder.rst +++ /dev/null @@ -1,584 +0,0 @@ -The QueryBuilder -================ - -A ``QueryBuilder`` provides an API that is designed for -conditionally constructing a DQL query in several steps. - -It provides a set of classes and methods that is able to -programmatically build queries, and also provides a fluent API. -This means that you can change between one methodology to the other -as you want, or just pick a preferred one. - -.. note:: - - The ``QueryBuilder`` is not an abstraction of DQL, but merely a tool to dynamically build it. - You should still use plain DQL when you can, as it is simpler and more readable. - More about this in the :doc:`FAQ `_. - -Constructing a new QueryBuilder object -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The same way you build a normal Query, you build a ``QueryBuilder`` -object. Here is an example of how to build a ``QueryBuilder`` -object: - -.. code-block:: php - - createQueryBuilder(); - -An instance of QueryBuilder has several informative methods. One -good example is to inspect what type of object the -``QueryBuilder`` is. - -.. code-block:: php - - getType(); // Prints: 0 - -There're currently 3 possible return values for ``getType()``: - - -- ``QueryBuilder::SELECT``, which returns value 0 -- ``QueryBuilder::DELETE``, returning value 1 -- ``QueryBuilder::UPDATE``, which returns value 2 - -It is possible to retrieve the associated ``EntityManager`` of the -current ``QueryBuilder``, its DQL and also a ``Query`` object when -you finish building your DQL. - -.. code-block:: php - - getEntityManager(); - - // example4: retrieve the DQL string of what was defined in QueryBuilder - $dql = $qb->getDql(); - - // example5: retrieve the associated Query object with the processed DQL - $q = $qb->getQuery(); - -Internally, ``QueryBuilder`` works with a DQL cache to increase -performance. Any changes that may affect the generated DQL actually -modifies the state of ``QueryBuilder`` to a stage we call -STATE\_DIRTY. One ``QueryBuilder`` can be in two different states: - - -- ``QueryBuilder::STATE_CLEAN``, which means DQL haven't been - altered since last retrieval or nothing were added since its - instantiation -- ``QueryBuilder::STATE_DIRTY``, means DQL query must (and will) - be processed on next retrieval - -Working with QueryBuilder -~~~~~~~~~~~~~~~~~~~~~~~~~ - - -High level API methods -^^^^^^^^^^^^^^^^^^^^^^ - -The most straightforward way to build a dynamic query with the ``QueryBuilder`` is by taking -advantage of Helper methods. For all base code, there is a set of -useful methods to simplify a programmer's life. To illustrate how -to work with them, here is the same example 6 re-written using -``QueryBuilder`` helper methods: - -.. code-block:: php - - select('u') - ->from('User', 'u') - ->where('u.id = ?1') - ->orderBy('u.name', 'ASC'); - -``QueryBuilder`` helper methods are considered the standard way to -use the ``QueryBuilder``. The ``$qb->expr()->*`` methods can help you -build conditional expressions dynamically. Here is a converted example 8 to -suggested way to build queries with dynamic conditions: - -.. code-block:: php - - select(array('u')) // string 'u' is converted to array internally - ->from('User', 'u') - ->where($qb->expr()->orX( - $qb->expr()->eq('u.id', '?1'), - $qb->expr()->like('u.nickname', '?2') - )) - ->orderBy('u.surname', 'ASC'); - -Here is a complete list of helper methods available in ``QueryBuilder``: - -.. code-block:: php - - select('u') - // Example - $qb->select(array('u', 'p')) - // Example - $qb->select($qb->expr()->select('u', 'p')) - public function select($select = null); - - // addSelect does not override previous calls to select - // - // Example - $qb->select('u'); - // ->addSelect('p.area_code'); - public function addSelect($select = null); - - // Example - $qb->delete('User', 'u') - public function delete($delete = null, $alias = null); - - // Example - $qb->update('Group', 'g') - public function update($update = null, $alias = null); - - // Example - $qb->set('u.firstName', $qb->expr()->literal('Arnold')) - // Example - $qb->set('u.numChilds', 'u.numChilds + ?1') - // Example - $qb->set('u.numChilds', $qb->expr()->sum('u.numChilds', '?1')) - public function set($key, $value); - - // Example - $qb->from('Phonenumber', 'p') - // Example - $qb->from('Phonenumber', 'p', 'p.id') - public function from($from, $alias, $indexBy = null); - - // Example - $qb->join('u.Group', 'g', Expr\Join::WITH, $qb->expr()->eq('u.status_id', '?1')) - // Example - $qb->join('u.Group', 'g', 'WITH', 'u.status = ?1') - // Example - $qb->join('u.Group', 'g', 'WITH', 'u.status = ?1', 'g.id') - public function join($join, $alias, $conditionType = null, $condition = null, $indexBy = null); - - // Example - $qb->innerJoin('u.Group', 'g', Expr\Join::WITH, $qb->expr()->eq('u.status_id', '?1')) - // Example - $qb->innerJoin('u.Group', 'g', 'WITH', 'u.status = ?1') - // Example - $qb->innerJoin('u.Group', 'g', 'WITH', 'u.status = ?1', 'g.id') - public function innerJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null); - - // Example - $qb->leftJoin('u.Phonenumbers', 'p', Expr\Join::WITH, $qb->expr()->eq('p.area_code', 55)) - // Example - $qb->leftJoin('u.Phonenumbers', 'p', 'WITH', 'p.area_code = 55') - // Example - $qb->leftJoin('u.Phonenumbers', 'p', 'WITH', 'p.area_code = 55', 'p.id') - public function leftJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null); - - // NOTE: ->where() overrides all previously set conditions - // - // Example - $qb->where('u.firstName = ?1', $qb->expr()->eq('u.surname', '?2')) - // Example - $qb->where($qb->expr()->andX($qb->expr()->eq('u.firstName', '?1'), $qb->expr()->eq('u.surname', '?2'))) - // Example - $qb->where('u.firstName = ?1 AND u.surname = ?2') - public function where($where); - - // NOTE: ->andWhere() can be used directly, without any ->where() before - // - // Example - $qb->andWhere($qb->expr()->orX($qb->expr()->lte('u.age', 40), 'u.numChild = 0')) - public function andWhere($where); - - // Example - $qb->orWhere($qb->expr()->between('u.id', 1, 10)); - public function orWhere($where); - - // NOTE: -> groupBy() overrides all previously set grouping conditions - // - // Example - $qb->groupBy('u.id') - public function groupBy($groupBy); - - // Example - $qb->addGroupBy('g.name') - public function addGroupBy($groupBy); - - // NOTE: -> having() overrides all previously set having conditions - // - // Example - $qb->having('u.salary >= ?1') - // Example - $qb->having($qb->expr()->gte('u.salary', '?1')) - public function having($having); - - // Example - $qb->andHaving($qb->expr()->gt($qb->expr()->count('u.numChild'), 0)) - public function andHaving($having); - - // Example - $qb->orHaving($qb->expr()->lte('g.managerLevel', '100')) - public function orHaving($having); - - // NOTE: -> orderBy() overrides all previously set ordering conditions - // - // Example - $qb->orderBy('u.surname', 'DESC') - public function orderBy($sort, $order = null); - - // Example - $qb->addOrderBy('u.firstName') - public function addOrderBy($sort, $order = null); // Default $order = 'ASC' - } - -Binding parameters to your query -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Doctrine supports dynamic binding of parameters to your query, -similar to preparing queries. You can use both strings and numbers -as placeholders, although both have a slightly different syntax. -Additionally, you must make your choice: Mixing both styles is not -allowed. Binding parameters can simply be achieved as follows: - -.. code-block:: php - - select('u') - ->from('User', 'u') - ->where('u.id = ?1') - ->orderBy('u.name', 'ASC') - ->setParameter(1, 100); // Sets ?1 to 100, and thus we will fetch a user with u.id = 100 - -You are not forced to enumerate your placeholders as the -alternative syntax is available: - -.. code-block:: php - - select('u') - ->from('User', 'u') - ->where('u.id = :identifier') - ->orderBy('u.name', 'ASC') - ->setParameter('identifier', 100); // Sets :identifier to 100, and thus we will fetch a user with u.id = 100 - -Note that numeric placeholders start with a ? followed by a number -while the named placeholders start with a : followed by a string. - -Calling ``setParameter()`` automatically infers which type you are setting as -value. This works for integers, arrays of strings/integers, DateTime instances -and for managed entities. If you want to set a type explicitly you can call -the third argument to ``setParameter()`` explicitly. It accepts either a PDO -type or a DBAL Type name for conversion. - -If you've got several parameters to bind to your query, you can -also use setParameters() instead of setParameter() with the -following syntax: - -.. code-block:: php - - setParameters(array(1 => 'value for ?1', 2 => 'value for ?2')); - -Getting already bound parameters is easy - simply use the above -mentioned syntax with "getParameter()" or "getParameters()": - -.. code-block:: php - - getParameters(); - // $params instanceof \Doctrine\Common\Collections\ArrayCollection - - // Equivalent to - $param = $qb->getParameter(1); - // $param instanceof \Doctrine\ORM\Query\Parameter - -Note: If you try to get a parameter that was not bound yet, -getParameter() simply returns NULL. - -The API of a Query Parameter is: - -.. code-block:: php - - namespace Doctrine\ORM\Query; - - class Parameter - { - public function getName(); - public function getValue(); - public function getType(); - public function setValue($value, $type = null); - } - -Limiting the Result -^^^^^^^^^^^^^^^^^^^ - -To limit a result the query builder has some methods in common with -the Query object which can be retrieved from ``EntityManager#createQuery()``. - -.. code-block:: php - - add('select', 'u') - ->add('from', 'User u') - ->add('orderBy', 'u.name ASC') - ->setFirstResult( $offset ) - ->setMaxResults( $limit ); - -Executing a Query -^^^^^^^^^^^^^^^^^ - -The QueryBuilder is a builder object only - it has no means of actually -executing the Query. Additionally a set of parameters such as query hints -cannot be set on the QueryBuilder itself. This is why you always have to convert -a querybuilder instance into a Query object: - -.. code-block:: php - - getQuery(); - - // Set additional Query options - $query->setQueryHint('foo', 'bar'); - $query->useResultCache('my_cache_id'); - - // Execute Query - $result = $query->getResult(); - $single = $query->getSingleResult(); - $array = $query->getArrayResult(); - $scalar = $query->getScalarResult(); - $singleScalar = $query->getSingleScalarResult(); - -The Expr class -^^^^^^^^^^^^^^ - -To workaround some of the issues that ``add()`` method may cause, -Doctrine created a class that can be considered as a helper for -building expressions. This class is called ``Expr``, which provides a -set of useful methods to help build expressions: - -.. code-block:: php - - add('select', new Expr\Select(array('u'))) - ->add('from', new Expr\From('User', 'u')) - ->add('where', $qb->expr()->orX( - $qb->expr()->eq('u.id', '?1'), - $qb->expr()->like('u.nickname', '?2') - )) - ->add('orderBy', new Expr\OrderBy('u.name', 'ASC')); - -Although it still sounds complex, the ability to programmatically -create conditions are the main feature of ``Expr``. Here it is a -complete list of supported helper methods available: - -.. code-block:: php - - expr()->andX($cond1 [, $condN])->add(...)->... - public function andX($x = null); // Returns Expr\AndX instance - - // Example - $qb->expr()->orX($cond1 [, $condN])->add(...)->... - public function orX($x = null); // Returns Expr\OrX instance - - - /** Comparison objects **/ - - // Example - $qb->expr()->eq('u.id', '?1') => u.id = ?1 - public function eq($x, $y); // Returns Expr\Comparison instance - - // Example - $qb->expr()->neq('u.id', '?1') => u.id <> ?1 - public function neq($x, $y); // Returns Expr\Comparison instance - - // Example - $qb->expr()->lt('u.id', '?1') => u.id < ?1 - public function lt($x, $y); // Returns Expr\Comparison instance - - // Example - $qb->expr()->lte('u.id', '?1') => u.id <= ?1 - public function lte($x, $y); // Returns Expr\Comparison instance - - // Example - $qb->expr()->gt('u.id', '?1') => u.id > ?1 - public function gt($x, $y); // Returns Expr\Comparison instance - - // Example - $qb->expr()->gte('u.id', '?1') => u.id >= ?1 - public function gte($x, $y); // Returns Expr\Comparison instance - - // Example - $qb->expr()->isNull('u.id') => u.id IS NULL - public function isNull($x); // Returns string - - // Example - $qb->expr()->isNotNull('u.id') => u.id IS NOT NULL - public function isNotNull($x); // Returns string - - - /** Arithmetic objects **/ - - // Example - $qb->expr()->prod('u.id', '2') => u.id * 2 - public function prod($x, $y); // Returns Expr\Math instance - - // Example - $qb->expr()->diff('u.id', '2') => u.id - 2 - public function diff($x, $y); // Returns Expr\Math instance - - // Example - $qb->expr()->sum('u.id', '2') => u.id + 2 - public function sum($x, $y); // Returns Expr\Math instance - - // Example - $qb->expr()->quot('u.id', '2') => u.id / 2 - public function quot($x, $y); // Returns Expr\Math instance - - - /** Pseudo-function objects **/ - - // Example - $qb->expr()->exists($qb2->getDql()) - public function exists($subquery); // Returns Expr\Func instance - - // Example - $qb->expr()->all($qb2->getDql()) - public function all($subquery); // Returns Expr\Func instance - - // Example - $qb->expr()->some($qb2->getDql()) - public function some($subquery); // Returns Expr\Func instance - - // Example - $qb->expr()->any($qb2->getDql()) - public function any($subquery); // Returns Expr\Func instance - - // Example - $qb->expr()->not($qb->expr()->eq('u.id', '?1')) - public function not($restriction); // Returns Expr\Func instance - - // Example - $qb->expr()->in('u.id', array(1, 2, 3)) - // Make sure that you do NOT use something similar to $qb->expr()->in('value', array('stringvalue')) as this will cause Doctrine to throw an Exception. - // Instead, use $qb->expr()->in('value', array('?1')) and bind your parameter to ?1 (see section above) - public function in($x, $y); // Returns Expr\Func instance - - // Example - $qb->expr()->notIn('u.id', '2') - public function notIn($x, $y); // Returns Expr\Func instance - - // Example - $qb->expr()->like('u.firstname', $qb->expr()->literal('Gui%')) - public function like($x, $y); // Returns Expr\Comparison instance - - // Example - $qb->expr()->notLike('u.firstname', $qb->expr()->literal('Gui%')) - public function notLike($x, $y); // Returns Expr\Comparison instance - - // Example - $qb->expr()->between('u.id', '1', '10') - public function between($val, $x, $y); // Returns Expr\Func - - - /** Function objects **/ - - // Example - $qb->expr()->trim('u.firstname') - public function trim($x); // Returns Expr\Func - - // Example - $qb->expr()->concat('u.firstname', $qb->expr()->concat($qb->expr()->literal(' '), 'u.lastname')) - public function concat($x, $y); // Returns Expr\Func - - // Example - $qb->expr()->substring('u.firstname', 0, 1) - public function substring($x, $from, $len); // Returns Expr\Func - - // Example - $qb->expr()->lower('u.firstname') - public function lower($x); // Returns Expr\Func - - // Example - $qb->expr()->upper('u.firstname') - public function upper($x); // Returns Expr\Func - - // Example - $qb->expr()->length('u.firstname') - public function length($x); // Returns Expr\Func - - // Example - $qb->expr()->avg('u.age') - public function avg($x); // Returns Expr\Func - - // Example - $qb->expr()->max('u.age') - public function max($x); // Returns Expr\Func - - // Example - $qb->expr()->min('u.age') - public function min($x); // Returns Expr\Func - - // Example - $qb->expr()->abs('u.currentBalance') - public function abs($x); // Returns Expr\Func - - // Example - $qb->expr()->sqrt('u.currentBalance') - public function sqrt($x); // Returns Expr\Func - - // Example - $qb->expr()->count('u.firstname') - public function count($x); // Returns Expr\Func - - // Example - $qb->expr()->countDistinct('u.surname') - public function countDistinct($x); // Returns Expr\Func - } - -Adding a Criteria to a Query -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -You can also add a :ref:`filtering-collections` to a QueryBuilder by -using ``addCriteria``: - -.. code-block:: php - - orderBy(['firstName', 'ASC']); - - // $qb instanceof QueryBuilder - $qb->addCriteria($criteria); - // then execute your query like normal - -Low Level API -^^^^^^^^^^^^^ - -Now we will describe the low level method of creating queries. -It may be useful to work at this level for optimization purposes, -but most of the time it is preferred to work at a higher level of -abstraction. - -All helper methods in ``QueryBuilder`` actually rely on a single -one: ``add()``. This method is responsible of building every piece -of DQL. It takes 3 parameters: ``$dqlPartName``, ``$dqlPart`` and -``$append`` (default=false) - - -- ``$dqlPartName``: Where the ``$dqlPart`` should be placed. - Possible values: select, from, where, groupBy, having, orderBy -- ``$dqlPart``: What should be placed in ``$dqlPartName``. Accepts - a string or any instance of ``Doctrine\ORM\Query\Expr\*`` -- ``$append``: Optional flag (default=false) if the ``$dqlPart`` - should override all previously defined items in ``$dqlPartName`` or - not (no effect on the ``where`` and ``having`` DQL query parts, - which always override all previously defined items) - -- - -.. code-block:: php - - add('select', 'u') - ->add('from', 'User u') - ->add('where', 'u.id = ?1') - ->add('orderBy', 'u.name ASC'); - -Expr\* classes -^^^^^^^^^^^^^^ - -When you call ``add()`` with string, it internally evaluates to an -instance of ``Doctrine\ORM\Query\Expr\Expr\*`` class. Here is the -same query of example 6 written using -``Doctrine\ORM\Query\Expr\Expr\*`` classes: - -.. code-block:: php - - add('select', new Expr\Select(array('u'))) - ->add('from', new Expr\From('User', 'u')) - ->add('where', new Expr\Comparison('u.id', '=', '?1')) - ->add('orderBy', new Expr\OrderBy('u.name', 'ASC')); - diff --git a/vendor/doctrine/orm/docs/en/reference/second-level-cache.rst b/vendor/doctrine/orm/docs/en/reference/second-level-cache.rst deleted file mode 100644 index 8a0b4c2..0000000 --- a/vendor/doctrine/orm/docs/en/reference/second-level-cache.rst +++ /dev/null @@ -1,731 +0,0 @@ -The Second Level Cache -====================== - -.. note:: - - The second level cache functionality is marked as experimental for now. It - is a very complex feature and we cannot guarantee yet that it works stable - in all cases. - -The Second Level Cache is designed to reduce the amount of necessary database access. -It sits between your application and the database to avoid the number of database hits as much as possible. - -When turned on, entities will be first searched in cache and if they are not found, -a database query will be fired and then the entity result will be stored in a cache provider. - -There are some flavors of caching available, but is better to cache read-only data. - -Be aware that caches are not aware of changes made to the persistent store by another application. -They can, however, be configured to regularly expire cached data. - - -Caching Regions ---------------- - -Second level cache does not store instances of an entity, instead it caches only entity identifier and values. -Each entity class, collection association and query has its region, where values of each instance are stored. - -Caching Regions are specific region into the cache provider that might store entities, collection or queries. -Each cache region resides in a specific cache namespace and has its own lifetime configuration. - -Notice that when caching collection and queries only identifiers are stored. -The entity values will be stored in its own region - -Something like below for an entity region : - -.. code-block:: php - - ['id'=> 1, 'name' => 'FooBar', 'associationName'=>null], - 'region_name:entity_2_hash' => ['id'=> 2, 'name' => 'Foo', 'associationName'=>['id'=>11]], - 'region_name:entity_3_hash' => ['id'=> 3, 'name' => 'Bar', 'associationName'=>['id'=>22]] - ]; - - -If the entity holds a collection that also needs to be cached. -An collection region could look something like : - -.. code-block:: php - - ['ownerId'=> 1, 'list' => [1, 2, 3]], - 'region_name:entity_2_coll_assoc_name_hash' => ['ownerId'=> 2, 'list' => [2, 3]], - 'region_name:entity_3_coll_assoc_name_hash' => ['ownerId'=> 3, 'list' => [2, 4]] - ]; - -A query region might be something like : - -.. code-block:: php - - ['list' => [1, 2, 3]], - 'region_name:query_2_hash' => ['list' => [2, 3]], - 'region_name:query_3_hash' => ['list' => [2, 4]] - ]; - - -.. note:: - - The following data structures represents now the cache will looks like, this is not actual cached data. - - -.. _reference-second-level-cache-regions: - -Cache Regions -------------- - -``Doctrine\ORM\Cache\Region\DefaultRegion`` It's the default implementation. - A simplest cache region compatible with all doctrine-cache drivers but does not support locking. - -``Doctrine\ORM\Cache\Region`` and ``Doctrine\ORM\Cache\ConcurrentRegion`` -Defines contracts that should be implemented by a cache provider. - -It allows you to provide your own cache implementation that might take advantage of specific cache driver. - -If you want to support locking for ``READ_WRITE`` strategies you should implement ``ConcurrentRegion``; ``CacheRegion`` otherwise. - - -Cache region -~~~~~~~~~~~~ - -Defines a contract for accessing a particular region. - -``Doctrine\ORM\Cache\Region`` - -Defines a contract for accessing a particular cache region. - -`See API Doc `_. - -Concurrent cache region -~~~~~~~~~~~~~~~~~~~~~~~ - -A ``Doctrine\ORM\Cache\ConcurrentRegion`` is designed to store concurrently managed data region. -By default, Doctrine provides a very simple implementation based on file locks ``Doctrine\ORM\Cache\Region\FileLockRegion``. - -If you want to use an ``READ_WRITE`` cache, you should consider providing your own cache region. - -``Doctrine\ORM\Cache\ConcurrentRegion`` - -Defines contract for concurrently managed data region. - -`See API Doc `_. - -Timestamp region -~~~~~~~~~~~~~~~~ - -``Doctrine\ORM\Cache\TimestampRegion`` - -Tracks the timestamps of the most recent updates to particular entity. - -`See API Doc `_. - -.. _reference-second-level-cache-mode: - -Caching mode ------------- - -* ``READ_ONLY`` (DEFAULT) - - * Can do reads, inserts and deletes, cannot perform updates or employ any locks. - * Useful for data that is read frequently but never updated. - * Best performer. - * It is Simple. - -* ``NONSTRICT_READ_WRITE`` - - * Read Write Cache doesn’t employ any locks but can do reads, inserts, updates and deletes. - * Good if the application needs to update data rarely. - - -* ``READ_WRITE`` - - * Read Write cache employs locks before update/delete. - * Use if data needs to be updated. - * Slowest strategy. - * To use it a the cache region implementation must support locking. - - -Built-in cached persisters -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Cached persisters are responsible to access cache regions. - - +-----------------------+-------------------------------------------------------------------------------------------+ - | Cache Usage | Persister | - +=======================+===========================================================================================+ - | READ_ONLY | Doctrine\\ORM\\Cache\\Persister\\Entity\\ReadOnlyCachedEntityPersister | - +-----------------------+-------------------------------------------------------------------------------------------+ - | READ_WRITE | Doctrine\\ORM\\Cache\\Persister\\Entity\\ReadWriteCachedEntityPersister | - +-----------------------+-------------------------------------------------------------------------------------------+ - | NONSTRICT_READ_WRITE | Doctrine\\ORM\\Cache\\Persister\\Entity\\NonStrictReadWriteCachedEntityPersister | - +-----------------------+-------------------------------------------------------------------------------------------+ - | READ_ONLY | Doctrine\\ORM\\Cache\\Persister\\Collection\\ReadOnlyCachedCollectionPersister | - +-----------------------+-------------------------------------------------------------------------------------------+ - | READ_WRITE | Doctrine\\ORM\\Cache\\Persister\\Collection\\ReadWriteCachedCollectionPersister | - +-----------------------+-------------------------------------------------------------------------------------------+ - | NONSTRICT_READ_WRITE | Doctrine\\ORM\\Cache\\Persister\\Collection\\NonStrictReadWriteCachedCollectionPersister | - +-----------------------+-------------------------------------------------------------------------------------------+ - -Configuration -------------- -Doctrine allows you to specify configurations and some points of extension for the second-level-cache - - -Enable Second Level Cache -~~~~~~~~~~~~~~~~~~~~~~~~~ - -To enable the second-level-cache, you should provide a cache factory -``\Doctrine\ORM\Cache\DefaultCacheFactory`` is the default implementation. - -.. code-block:: php - - setSecondLevelCacheEnabled(); - - // Cache factory - $config->getSecondLevelCacheConfiguration() - ->setCacheFactory($factory); - - -Cache Factory -~~~~~~~~~~~~~ - -Cache Factory is the main point of extension. - -It allows you to provide a specific implementation of the following components : - -* ``QueryCache`` Store and retrieve query cache results. -* ``CachedEntityPersister`` Store and retrieve entity results. -* ``CachedCollectionPersister`` Store and retrieve query results. -* ``EntityHydrator`` Transform an entity into a cache entry and cache entry into entities -* ``CollectionHydrator`` Transform a collection into a cache entry and cache entry into collection - -`See API Doc `_. - -Region Lifetime -~~~~~~~~~~~~~~~ - -To specify a default lifetime for all regions or specify a different lifetime for a specific region. - -.. code-block:: php - - getSecondLevelCacheConfiguration(); - $regionConfig = $cacheConfig->getRegionsConfiguration(); - - // Cache Region lifetime - $regionConfig->setLifetime('my_entity_region', 3600); // Time to live for a specific region; In seconds - $regionConfig->setDefaultLifetime(7200); // Default time to live; In seconds - - -Cache Log -~~~~~~~~~ -By providing a cache logger you should be able to get information about all cache operations such as hits, misses and puts. - -``\Doctrine\ORM\Cache\Logging\StatisticsCacheLogger`` is a built-in implementation that provides basic statistics. - - .. code-block:: php - - setSecondLevelCacheEnabled(true); - $config->getSecondLevelCacheConfiguration() - ->setCacheLogger($logger); - - - // Collect cache statistics - - // Get the number of entries successfully retrieved from a specific region. - $logger->getRegionHitCount('my_entity_region'); - - // Get the number of cached entries *not* found in a specific region. - $logger->getRegionMissCount('my_entity_region'); - - // Get the number of cacheable entries put in cache. - $logger->getRegionPutCount('my_entity_region'); - - // Get the total number of put in all regions. - $logger->getPutCount(); - - // Get the total number of entries successfully retrieved from all regions. - $logger->getHitCount(); - - // Get the total number of cached entries *not* found in all regions. - $logger->getMissCount(); - -If you want to get more information you should implement ``\Doctrine\ORM\Cache\Logging\CacheLogger``. -and collect all information you want. - -`See API Doc `_. - - -Entity cache definition ------------------------ -* Entity cache configuration allows you to define the caching strategy and region for an entity. - - * ``usage`` Specifies the caching strategy: ``READ_ONLY``, ``NONSTRICT_READ_WRITE``, ``READ_WRITE``. see :ref:`reference-second-level-cache-mode` - * ``region`` Optional value that specifies the name of the second level cache region. - - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - - - - .. code-block:: yaml - - Country: - type: entity - cache: - usage : READ_ONLY - region : my_entity_region - id: - id: - type: integer - id: true - generator: - strategy: IDENTITY - fields: - name: - type: string - - -Association cache definition ----------------------------- -The most common use case is to cache entities. But we can also cache relationships. -It caches the primary keys of association and cache each element will be cached into its region. - - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - - - - - - - - - - - - - - - - - - - .. code-block:: yaml - - State: - type: entity - cache: - usage : NONSTRICT_READ_WRITE - id: - id: - type: integer - id: true - generator: - strategy: IDENTITY - fields: - name: - type: string - - manyToOne: - state: - targetEntity: Country - joinColumns: - country_id: - referencedColumnName: id - cache: - usage : NONSTRICT_READ_WRITE - - oneToMany: - cities: - targetEntity:City - mappedBy: state - cache: - usage : NONSTRICT_READ_WRITE - - -> Note: for this to work, the target entity must also be marked as cacheable. - -Cache usage -~~~~~~~~~~~ - -Basic entity cache - -.. code-block:: php - - persist(new Country($name)); - $em->flush(); // Hit database to insert the row and put into cache - - $em->clear(); // Clear entity manager - - $country1 = $em->find('Country', 1); // Retrieve item from cache - - $country->setName("New Name"); - $em->persist($country); - $em->flush(); // Hit database to update the row and update cache - - $em->clear(); // Clear entity manager - - $country2 = $em->find('Country', 1); // Retrieve item from cache - // Notice that $country1 and $country2 are not the same instance. - - -Association cache - -.. code-block:: php - - persist(new State($name, $country)); - $em->flush(); - - // Clear entity manager - $em->clear(); - - // Retrieve item from cache - $state = $em->find('State', 1); - - // Hit database to update the row and update cache entry - $state->setName("New Name"); - $em->persist($state); - $em->flush(); - - // Create a new collection item - $city = new City($name, $state); - $state->addCity($city); - - // Hit database to insert new collection item, - // put entity and collection cache into cache. - $em->persist($city); - $em->persist($state); - $em->flush(); - - // Clear entity manager - $em->clear(); - - // Retrieve item from cache - $state = $em->find('State', 1); - - // Retrieve association from cache - $country = $state->getCountry(); - - // Retrieve collection from cache - $cities = $state->getCities(); - - echo $country->getName(); - echo $state->getName(); - - // Retrieve each collection item from cache - foreach ($cities as $city) { - echo $city->getName(); - } - -.. note:: - - Notice that all entities should be marked as cacheable. - -Using the query cache ---------------------- - -The second level cache stores the entities, associations and collections. -The query cache stores the results of the query but as identifiers, entity values are actually stored in the 2nd level cache. - -.. note:: - - Query cache should always be used in conjunction with the second-level-cache for those entities which should be cached. - -.. code-block:: php - - createQuery('SELECT c FROM Country c ORDER BY c.name') - ->setCacheable(true) - ->getResult(); - - $em->clear() - - // Check if query result is valid and load entities from cache - $result2 = $em->createQuery('SELECT c FROM Country c ORDER BY c.name') - ->setCacheable(true) - ->getResult(); - -Cache mode -~~~~~~~~~~ - -The Cache Mode controls how a particular query interacts with the second-level cache: - -* ``Cache::MODE_GET`` - May read items from the cache, but will not add items. -* ``Cache::MODE_PUT`` - Will never read items from the cache, but will add items to the cache as it reads them from the database. -* ``Cache::MODE_NORMAL`` - May read items from the cache, and add items to the cache. -* ``Cache::MODE_REFRESH`` - The query will never read items from the cache, but will refresh items to the cache as it reads them from the database. - -.. code-block:: php - - createQuery('SELECT c FROM Country c ORDER BY c.name') - ->setCacheMode(Cache::MODE_GET) - ->setCacheable(true) - ->getResult(); - -.. note:: - - The the default query cache mode is ```Cache::MODE_NORMAL``` - -DELETE / UPDATE queries -~~~~~~~~~~~~~~~~~~~~~~~ - -DQL UPDATE / DELETE statements are ported directly into a database and bypass the second-level cache, -Entities that are already cached will NOT be invalidated. -However the cached data could be evicted using the cache API or an special query hint. - - -Execute the ``UPDATE`` and invalidate ``all cache entries`` using ``Query::HINT_CACHE_EVICT`` - -.. code-block:: php - - _em->createQuery("UPDATE Entity\Country u SET u.name = 'unknown' WHERE u.id = 1") - ->setHint(Query::HINT_CACHE_EVICT, true) - ->execute(); - - -Execute the ``UPDATE`` and invalidate ``all cache entries`` using the cache API - -.. code-block:: php - - _em->createQuery("UPDATE Entity\Country u SET u.name = 'unknown' WHERE u.id = 1") - ->execute(); - // Invoke Cache API - $em->getCache()->evictEntityRegion('Entity\Country'); - - -Execute the ``UPDATE`` and invalidate ``a specific cache entry`` using the cache API - -.. code-block:: php - - _em->createQuery("UPDATE Entity\Country u SET u.name = 'unknown' WHERE u.id = 1") - ->execute(); - // Invoke Cache API - $em->getCache()->evictEntity('Entity\Country', 1); - -Using the repository query cache --------------------------------- - -As well as ``Query Cache`` all persister queries store only identifier values for an individual query. -All persister use a single timestamps cache region keeps track of the last update for each persister, -When a query is loaded from cache, the timestamp region is checked for the last update for that persister. -Using the last update timestamps as part of the query key invalidate the cache key when an update occurs. - -.. code-block:: php - - getRepository('Entity\Country')->findAll(); - - // load from query and entities from cache.. - $entities = $em->getRepository('Entity\Country')->findAll(); - - // update the timestamp cache region for Country - $em->persist(new Country('zombieland')); - $em->flush(); - $em->clear(); - - // Reload from database. - // At this point the query cache key if not logger valid, the select goes straight - $entities = $em->getRepository('Entity\Country')->findAll(); - -Cache API ---------- - -Caches are not aware of changes made by another application. -However, you can use the cache API to check / invalidate cache entries. - -.. code-block:: php - - getCache(); - - $cache->containsEntity('Entity\State', 1) // Check if the cache exists - $cache->evictEntity('Entity\State', 1); // Remove an entity from cache - $cache->evictEntityRegion('Entity\State'); // Remove all entities from cache - - $cache->containsCollection('Entity\State', 'cities', 1); // Check if the cache exists - $cache->evictCollection('Entity\State', 'cities', 1); // Remove an entity collection from cache - $cache->evictCollectionRegion('Entity\State', 'cities'); // Remove all collections from cache - -Limitations ------------ - -Composite primary key -~~~~~~~~~~~~~~~~~~~~~ - -Composite primary key are supported by second level cache, -however when one of the keys is an association the cached entity should always be retrieved using the association identifier. -For performance reasons the cache API does not extract from composite primary key. - -.. code-block:: php - - find('Article', 1); - - // Supported - /* @var $article Article */ - $article = $em->find('Article', $article); - - // Supported - $id = array('source' => 1, 'target' => 2); - $reference = $em->find('Reference', $id); - - // NOT Supported - $id = array('source' => new Article(1), 'target' => new Article(2)); - $reference = $em->find('Reference', $id); - -Distributed environments -~~~~~~~~~~~~~~~~~~~~~~~~ - -Some cache driver are not meant to be used in a distributed environment. -Load-balancer for distributing workloads across multiple computing resources -should be used in conjunction with distributed caching system such as memcached, redis, riak ... - -Caches should be used with care when using a load-balancer if you don't share the cache. -While using APC or any file based cache update occurred in a specific machine would not reflect to the cache in other machines. - - -Paginator -~~~~~~~~~ - -Count queries generated by ``Doctrine\ORM\Tools\Pagination\Paginator`` are not cached by second-level cache. -Although entities and query result are cached count queries will hit the database every time. diff --git a/vendor/doctrine/orm/docs/en/reference/security.rst b/vendor/doctrine/orm/docs/en/reference/security.rst deleted file mode 100644 index 0101e86..0000000 --- a/vendor/doctrine/orm/docs/en/reference/security.rst +++ /dev/null @@ -1,151 +0,0 @@ -Security -======== - -The Doctrine library is operating very close to your database and as such needs -to handle and make assumptions about SQL injection vulnerabilities. - -It is vital that you understand how Doctrine approaches security, because -we cannot protect you from SQL injection. - -Please also read the documentation chapter on Security in Doctrine DBAL. This -page only handles Security issues in the ORM. - -- `DBAL Security Page ` - -If you find a Security bug in Doctrine, please report it on Jira and change the -Security Level to "Security Issues". It will be visible to Doctrine Core -developers and you only. - -User input and Doctrine ORM ---------------------------- - -The ORM is much better at protecting against SQL injection than the DBAL alone. -You can consider the following APIs to be safe from SQL injection: - -- ``\Doctrine\ORM\EntityManager#find()`` and ``getReference()``. -- All values on Objects inserted and updated through ``Doctrine\ORM\EntityManager#persist()`` -- All find methods on ``Doctrine\ORM\EntityRepository``. -- User Input set to DQL Queries or QueryBuilder methods through - - ``setParameter()`` or variants - - ``setMaxResults()`` - - ``setFirstResult()`` -- Queries through the Criteria API on ``Doctrine\ORM\PersistentCollection`` and - ``Doctrine\ORM\EntityRepository``. - -You are **NOT** safe from SQL injection when using user input with: - -- Expression API of ``Doctrine\ORM\QueryBuilder`` -- Concatenating user input into DQL SELECT, UPDATE or DELETE statements or - Native SQL. - -This means SQL injections can only occur with Doctrine ORM when working with -Query Objects of any kind. The safe rule is to always use prepared statement -parameters for user objects when using a Query object. - -.. warning:: - - Insecure code follows, don't copy paste this. - -The following example shows insecure DQL usage: - -.. code-block:: php - - createQuery($dql); - $query->setParameter(1, $_GET['status']); - - -Preventing Mass Assignment Vulnerabilities ------------------------------------------- - -ORMs are very convenient for CRUD applications and Doctrine is no exception. -However CRUD apps are often vulnerable to mass assignment security problems -when implemented naively. - -Doctrine is not vulnerable to this problem out of the box, but you can easily -make your entities vulnerable to mass assignment when you add methods of -the kind ``updateFromArray()`` or ``updateFromJson()`` to them. A vulnerable -entity might look like this: - -.. code-block:: php - - $value) { - $this->$key = $value; - } - } - } - -Now the possiblity of mass-asignment exists on this entity and can -be exploited by attackers to set the "isAdmin" flag to true on any -object when you pass the whole request data to this method like: - -.. code-block:: php - - fromArray($_POST); - - $entityManager->persist($entity); - $entityManager->flush(); - -You can spot this problem in this very simple example easily. However -in combination with frameworks and form libraries it might not be -so obvious when this issue arises. Be careful to avoid this -kind of mistake. - -How to fix this problem? You should always have a whitelist -of allowed key to set via mass assignment functions. - -.. code-block:: php - - public function fromArray(array $userInput, $allowedFields = array()) - { - foreach ($userInput as $key => $value) { - if (in_array($key, $allowedFields)) { - $this->$key = $value; - } - } - } diff --git a/vendor/doctrine/orm/docs/en/reference/tools.rst b/vendor/doctrine/orm/docs/en/reference/tools.rst deleted file mode 100644 index 3b6cf33..0000000 --- a/vendor/doctrine/orm/docs/en/reference/tools.rst +++ /dev/null @@ -1,520 +0,0 @@ -Tools -===== - -Doctrine Console ----------------- - -The Doctrine Console is a Command Line Interface tool for simplifying common -administration tasks during the development of a project that uses Doctrine 2. - -Take a look at the :doc:`Installation and Configuration ` -chapter for more information how to setup the console command. - -Display Help Information -~~~~~~~~~~~~~~~~~~~~~~~~ - -Type ``php vendor/bin/doctrine`` on the command line and you should see an -overview of the available commands or use the --help flag to get -information on the available commands. If you want to know more -about the use of generate entities for example, you can call: - -.. code-block:: php - - $> php vendor/bin/doctrine orm:generate-entities --help - - -Configuration -~~~~~~~~~~~~~ - -Whenever the ``doctrine`` command line tool is invoked, it can -access all Commands that were registered by developer. There is no -auto-detection mechanism at work. The Doctrine binary -already registers all the commands that currently ship with -Doctrine DBAL and ORM. If you want to use additional commands you -have to register them yourself. - -All the commands of the Doctrine Console require access to the ``EntityManager`` -or ``DBAL`` Connection. You have to inject them into the console application -using so called Helper-Sets. This requires either the ``db`` -or the ``em`` helpers to be defined in order to work correctly. - -Whenever you invoke the Doctrine binary the current folder is searched for a -``cli-config.php`` file. This file contains the project specific configuration: - -.. code-block:: php - - new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($conn) - )); - $cli->setHelperSet($helperSet); - -When dealing with the ORM package, the EntityManagerHelper is -required: - -.. code-block:: php - - new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) - )); - $cli->setHelperSet($helperSet); - -The HelperSet instance has to be generated in a separate file (i.e. -``cli-config.php``) that contains typical Doctrine bootstrap code -and predefines the needed HelperSet attributes mentioned above. A -sample ``cli-config.php`` file looks as follows: - -.. code-block:: php - - new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()), - 'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) - )); - -It is important to define a correct HelperSet that Doctrine binary -script will ultimately use. The Doctrine Binary will automatically -find the first instance of HelperSet in the global variable -namespace and use this. - -.. note:: - - You have to adjust this snippet for your specific application or framework - and use their facilities to access the Doctrine EntityManager and - Connection Resources. - -Command Overview -~~~~~~~~~~~~~~~~ - -The following Commands are currently available: - - -- ``help`` Displays help for a command (?) -- ``list`` Lists commands -- ``dbal:import`` Import SQL file(s) directly to Database. -- ``dbal:run-sql`` Executes arbitrary SQL directly from the - command line. -- ``orm:clear-cache:metadata`` Clear all metadata cache of the - various cache drivers. -- ``orm:clear-cache:query`` Clear all query cache of the various - cache drivers. -- ``orm:clear-cache:result`` Clear result cache of the various - cache drivers. -- ``orm:convert-d1-schema`` Converts Doctrine 1.X schema into a - Doctrine 2.X schema. -- ``orm:convert-mapping`` Convert mapping information between - supported formats. -- ``orm:ensure-production-settings`` Verify that Doctrine is - properly configured for a production environment. -- ``orm:generate-entities`` Generate entity classes and method - stubs from your mapping information. -- ``orm:generate-proxies`` Generates proxy classes for entity - classes. -- ``orm:generate-repositories`` Generate repository classes from - your mapping information. -- ``orm:run-dql`` Executes arbitrary DQL directly from the command - line. -- ``orm:schema-tool:create`` Processes the schema and either - create it directly on EntityManager Storage Connection or generate - the SQL output. -- ``orm:schema-tool:drop`` Processes the schema and either drop - the database schema of EntityManager Storage Connection or generate - the SQL output. -- ``orm:schema-tool:update`` Processes the schema and either - update the database schema of EntityManager Storage Connection or - generate the SQL output. - -For these commands are also available aliases: - - -- ``orm:convert:d1-schema`` is alias for ``orm:convert-d1-schema``. -- ``orm:convert:mapping`` is alias for ``orm:convert-mapping``. -- ``orm:generate:entities`` is alias for ``orm:generate-entities``. -- ``orm:generate:proxies`` is alias for ``orm:generate-proxies``. -- ``orm:generate:repositories`` is alias for ``orm:generate-repositories``. - -.. note:: - - Console also supports auto completion, for example, instead of - ``orm:clear-cache:query`` you can use just ``o:c:q``. - -Database Schema Generation --------------------------- - -.. note:: - - SchemaTool can do harm to your database. It will drop or alter - tables, indexes, sequences and such. Please use this tool with - caution in development and not on a production server. It is meant - for helping you develop your Database Schema, but NOT with - migrating schema from A to B in production. A safe approach would - be generating the SQL on development server and saving it into SQL - Migration files that are executed manually on the production - server. - - SchemaTool assumes your Doctrine Project uses the given database on - its own. Update and Drop commands will mess with other tables if - they are not related to the current project that is using Doctrine. - Please be careful! - - -To generate your database schema from your Doctrine mapping files -you can use the ``SchemaTool`` class or the ``schema-tool`` Console -Command. - -When using the SchemaTool class directly, create your schema using -the ``createSchema()`` method. First create an instance of the -``SchemaTool`` and pass it an instance of the ``EntityManager`` -that you want to use to create the schema. This method receives an -array of ``ClassMetadataInfo`` instances. - -.. code-block:: php - - getClassMetadata('Entities\User'), - $em->getClassMetadata('Entities\Profile') - ); - $tool->createSchema($classes); - -To drop the schema you can use the ``dropSchema()`` method. - -.. code-block:: php - - dropSchema($classes); - -This drops all the tables that are currently used by your metadata -model. When you are changing your metadata a lot during development -you might want to drop the complete database instead of only the -tables of the current model to clean up with orphaned tables. - -.. code-block:: php - - dropSchema($classes, \Doctrine\ORM\Tools\SchemaTool::DROP_DATABASE); - -You can also use database introspection to update your schema -easily with the ``updateSchema()`` method. It will compare your -existing database schema to the passed array of -``ClassMetadataInfo`` instances. - -.. code-block:: php - - updateSchema($classes); - -If you want to use this functionality from the command line you can -use the ``schema-tool`` command. - -To create the schema use the ``create`` command: - -.. code-block:: php - - $ php doctrine orm:schema-tool:create - -To drop the schema use the ``drop`` command: - -.. code-block:: php - - $ php doctrine orm:schema-tool:drop - -If you want to drop and then recreate the schema then use both -options: - -.. code-block:: php - - $ php doctrine orm:schema-tool:drop - $ php doctrine orm:schema-tool:create - -As you would think, if you want to update your schema use the -``update`` command: - -.. code-block:: php - - $ php doctrine orm:schema-tool:update - -All of the above commands also accept a ``--dump-sql`` option that -will output the SQL for the ran operation. - -.. code-block:: php - - $ php doctrine orm:schema-tool:create --dump-sql - -Before using the orm:schema-tool commands, remember to configure -your cli-config.php properly. - -Entity Generation ------------------ - -Generate entity classes and method stubs from your mapping information. - -.. code-block:: php - - $ php doctrine orm:generate-entities - $ php doctrine orm:generate-entities --update-entities - $ php doctrine orm:generate-entities --regenerate-entities - -This command is not suited for constant usage. It is a little helper and does -not support all the mapping edge cases very well. You still have to put work -in your entities after using this command. - -It is possible to use the EntityGenerator on code that you have already written. It will -not be lost. The EntityGenerator will only append new code to your -file and will not delete the old code. However this approach may still be prone -to error and we suggest you use code repositories such as GIT or SVN to make -backups of your code. - -It makes sense to generate the entity code if you are using entities as Data -Access Objects only and don't put much additional logic on them. If you are -however putting much more logic on the entities you should refrain from using -the entity-generator and code your entities manually. - -.. note:: - - Even if you specified Inheritance options in your - XML or YAML Mapping files the generator cannot generate the base and - child classes for you correctly, because it doesn't know which - class is supposed to extend which. You have to adjust the entity - code manually for inheritance to work! - - -Convert Mapping Information ---------------------------- - -Convert mapping information between supported formats. - -This is an **execute one-time** command. It should not be necessary for -you to call this method multiple times, especially when using the ``--from-database`` -flag. - -Converting an existing database schema into mapping files only solves about 70-80% -of the necessary mapping information. Additionally the detection from an existing -database cannot detect inverse associations, inheritance types, -entities with foreign keys as primary keys and many of the -semantical operations on associations such as cascade. - -.. note:: - - There is no need to convert YAML or XML mapping files to annotations - every time you make changes. All mapping drivers are first class citizens - in Doctrine 2 and can be used as runtime mapping for the ORM. See the - docs on XML and YAML Mapping for an example how to register this metadata - drivers as primary mapping source. - -To convert some mapping information between the various supported -formats you can use the ``ClassMetadataExporter`` to get exporter -instances for the different formats: - -.. code-block:: php - - getExporter('yml', '/path/to/export/yml'); - -Now you can export some ``ClassMetadata`` instances: - -.. code-block:: php - - getClassMetadata('Entities\User'), - $em->getClassMetadata('Entities\Profile') - ); - $exporter->setMetadata($classes); - $exporter->export(); - -This functionality is also available from the command line to -convert your loaded mapping information to another format. The -``orm:convert-mapping`` command accepts two arguments, the type to -convert to and the path to generate it: - -.. code-block:: php - - $ php doctrine orm:convert-mapping xml /path/to/mapping-path-converted-to-xml - -Reverse Engineering -------------------- - -You can use the ``DatabaseDriver`` to reverse engineer a database -to an array of ``ClassMetadataInfo`` instances and generate YAML, -XML, etc. from them. - -.. note:: - - Reverse Engineering is a **one-time** process that can get you started with a project. - Converting an existing database schema into mapping files only detects about 70-80% - of the necessary mapping information. Additionally the detection from an existing - database cannot detect inverse associations, inheritance types, - entities with foreign keys as primary keys and many of the - semantical operations on associations such as cascade. - -First you need to retrieve the metadata instances with the -``DatabaseDriver``: - -.. code-block:: php - - getConfiguration()->setMetadataDriverImpl( - new \Doctrine\ORM\Mapping\Driver\DatabaseDriver( - $em->getConnection()->getSchemaManager() - ) - ); - - $cmf = new \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory(); - $cmf->setEntityManager($em); - $metadata = $cmf->getAllMetadata(); - -Now you can get an exporter instance and export the loaded metadata -to yml: - -.. code-block:: php - - getExporter('yml', '/path/to/export/yml'); - $exporter->setMetadata($metadata); - $exporter->export(); - -You can also reverse engineer a database using the -``orm:convert-mapping`` command: - -.. code-block:: php - - $ php doctrine orm:convert-mapping --from-database yml /path/to/mapping-path-converted-to-yml - -.. note:: - - Reverse Engineering is not always working perfectly - depending on special cases. It will only detect Many-To-One - relations (even if they are One-To-One) and will try to create - entities from Many-To-Many tables. It also has problems with naming - of foreign keys that have multiple column names. Any Reverse - Engineered Database-Schema needs considerable manual work to become - a useful domain model. - - -Runtime vs Development Mapping Validation ------------------------------------------ - -For performance reasons Doctrine 2 has to skip some of the -necessary validation of metadata mappings. You have to execute -this validation in your development workflow to verify the -associations are correctly defined. - -You can either use the Doctrine Command Line Tool: - -.. code-block:: php - - doctrine orm:validate-schema - -Or you can trigger the validation manually: - -.. code-block:: php - - validateMapping(); - - if (count($errors) > 0) { - // Lots of errors! - echo implode("\n\n", $errors); - } - -If the mapping is invalid the errors array contains a positive -number of elements with error messages. - -.. warning:: - - One mapping option that is not validated is the use of the referenced column name. - It has to point to the equivalent primary key otherwise Doctrine will not work. - -.. note:: - - One common error is to use a backlash in front of the - fully-qualified class-name. Whenever a FQCN is represented inside a - string (such as in your mapping definitions) you have to drop the - prefix backslash. PHP does this with ``get_class()`` or Reflection - methods for backwards compatibility reasons. - - -Adding own commands -------------------- - -You can also add your own commands on-top of the Doctrine supported -tools if you are using a manually built console script. - -To include a new command on Doctrine Console, you need to do modify the -``doctrine.php`` file a little: - -.. code-block:: php - - setCatchExceptions(true); - $cli->setHelperSet($helperSet); - - // Register All Doctrine Commands - ConsoleRunner::addCommands($cli); - - // Register your own command - $cli->addCommand(new \MyProject\Tools\Console\Commands\MyCustomCommand); - - // Runs console application - $cli->run(); - -Additionally, include multiple commands (and overriding previously -defined ones) is possible through the command: - -.. code-block:: php - - addCommands(array( - new \MyProject\Tools\Console\Commands\MyCustomCommand(), - new \MyProject\Tools\Console\Commands\SomethingCommand(), - new \MyProject\Tools\Console\Commands\AnotherCommand(), - new \MyProject\Tools\Console\Commands\OneMoreCommand(), - )); - - -Re-use console application --------------------------- - -You are also able to retrieve and re-use the default console application. -Just call ``ConsoleRunner::createApplication(...)`` with an appropriate -HelperSet, like it is described in the configuration section. - -.. code-block:: php - - run(); - diff --git a/vendor/doctrine/orm/docs/en/reference/transactions-and-concurrency.rst b/vendor/doctrine/orm/docs/en/reference/transactions-and-concurrency.rst deleted file mode 100644 index 5ce0852..0000000 --- a/vendor/doctrine/orm/docs/en/reference/transactions-and-concurrency.rst +++ /dev/null @@ -1,409 +0,0 @@ -Transactions and Concurrency -============================ - -.. _transactions-and-concurrency_transaction-demarcation: - -Transaction Demarcation ------------------------ - -Transaction demarcation is the task of defining your transaction -boundaries. Proper transaction demarcation is very important -because if not done properly it can negatively affect the -performance of your application. Many databases and database -abstraction layers like PDO by default operate in auto-commit mode, -which means that every single SQL statement is wrapped in a small -transaction. Without any explicit transaction demarcation from your -side, this quickly results in poor performance because transactions -are not cheap. - -For the most part, Doctrine 2 already takes care of proper -transaction demarcation for you: All the write operations -(INSERT/UPDATE/DELETE) are queued until ``EntityManager#flush()`` -is invoked which wraps all of these changes in a single -transaction. - -However, Doctrine 2 also allows (and encourages) you to take over -and control transaction demarcation yourself. - -These are two ways to deal with transactions when using the -Doctrine ORM and are now described in more detail. - -.. _transactions-and-concurrency_approach-implicitly: - -Approach 1: Implicitly -~~~~~~~~~~~~~~~~~~~~~~ - -The first approach is to use the implicit transaction handling -provided by the Doctrine ORM EntityManager. Given the following -code snippet, without any explicit transaction demarcation: - -.. code-block:: php - - setName('George'); - $em->persist($user); - $em->flush(); - -Since we do not do any custom transaction demarcation in the above -code, ``EntityManager#flush()`` will begin and commit/rollback a -transaction. This behavior is made possible by the aggregation of -the DML operations by the Doctrine ORM and is sufficient if all the -data manipulation that is part of a unit of work happens through -the domain model and thus the ORM. - -.. _transactions-and-concurrency_approach-explicitly: - -Approach 2: Explicitly -~~~~~~~~~~~~~~~~~~~~~~ - -The explicit alternative is to use the ``Doctrine\DBAL\Connection`` -API directly to control the transaction boundaries. The code then -looks like this: - -.. code-block:: php - - getConnection()->beginTransaction(); // suspend auto-commit - try { - //... do some work - $user = new User; - $user->setName('George'); - $em->persist($user); - $em->flush(); - $em->getConnection()->commit(); - } catch (Exception $e) { - $em->getConnection()->rollBack(); - throw $e; - } - -Explicit transaction demarcation is required when you want to -include custom DBAL operations in a unit of work or when you want -to make use of some methods of the ``EntityManager`` API that -require an active transaction. Such methods will throw a -``TransactionRequiredException`` to inform you of that -requirement. - -A more convenient alternative for explicit transaction demarcation is the use -of provided control abstractions in the form of -``Connection#transactional($func)`` and ``EntityManager#transactional($func)``. -When used, these control abstractions ensure that you never forget to rollback -the transaction, in addition to the obvious code reduction. An example that is -functionally equivalent to the previously shown code looks as follows: - -.. code-block:: php - - transactional(function($em) { - //... do some work - $user = new User; - $user->setName('George'); - $em->persist($user); - }); - -.. warning:: - - For historical reasons, ``EntityManager#transactional($func)`` will return - ``true`` whenever the return value of ``$func`` is loosely false. - Some examples of this include ``array()``, ``"0"``, ``""``, ``0``, and - ``null``. - -The difference between ``Connection#transactional($func)`` and -``EntityManager#transactional($func)`` is that the latter -abstraction flushes the ``EntityManager`` prior to transaction -commit and rolls back the transaction when an -exception occurs. - -.. _transactions-and-concurrency_exception-handling: - -Exception Handling -~~~~~~~~~~~~~~~~~~ - -When using implicit transaction demarcation and an exception occurs -during ``EntityManager#flush()``, the transaction is automatically -rolled back and the ``EntityManager`` closed. - -When using explicit transaction demarcation and an exception -occurs, the transaction should be rolled back immediately and the -``EntityManager`` closed by invoking ``EntityManager#close()`` and -subsequently discarded, as demonstrated in the example above. This -can be handled elegantly by the control abstractions shown earlier. -Note that when catching ``Exception`` you should generally re-throw -the exception. If you intend to recover from some exceptions, catch -them explicitly in earlier catch blocks (but do not forget to -rollback the transaction and close the ``EntityManager`` there as -well). All other best practices of exception handling apply -similarly (i.e. either log or re-throw, not both, etc.). - -As a result of this procedure, all previously managed or removed -instances of the ``EntityManager`` become detached. The state of -the detached objects will be the state at the point at which the -transaction was rolled back. The state of the objects is in no way -rolled back and thus the objects are now out of synch with the -database. The application can continue to use the detached objects, -knowing that their state is potentially no longer accurate. - -If you intend to start another unit of work after an exception has -occurred you should do that with a new ``EntityManager``. - -.. _transactions-and-concurrency_locking-support: - -Locking Support ---------------- - -Doctrine 2 offers support for Pessimistic- and Optimistic-locking -strategies natively. This allows to take very fine-grained control -over what kind of locking is required for your Entities in your -application. - -.. _transactions-and-concurrency_optimistic-locking: - -Optimistic Locking -~~~~~~~~~~~~~~~~~~ - -Database transactions are fine for concurrency control during a -single request. However, a database transaction should not span -across requests, the so-called "user think time". Therefore a -long-running "business transaction" that spans multiple requests -needs to involve several database transactions. Thus, database -transactions alone can no longer control concurrency during such a -long-running business transaction. Concurrency control becomes the -partial responsibility of the application itself. - -Doctrine has integrated support for automatic optimistic locking -via a version field. In this approach any entity that should be -protected against concurrent modifications during long-running -business transactions gets a version field that is either a simple -number (mapping type: integer) or a timestamp (mapping type: -datetime). When changes to such an entity are persisted at the end -of a long-running conversation the version of the entity is -compared to the version in the database and if they don't match, an -``OptimisticLockException`` is thrown, indicating that the entity -has been modified by someone else already. - -You designate a version field in an entity as follows. In this -example we'll use an integer. - -.. configuration-block:: - - .. code-block:: php - - - - - - - - .. code-block:: yaml - - User: - type: entity - fields: - version: - type: integer - version: true - -Alternatively a datetime type can be used (which maps to a SQL -timestamp or datetime): - -.. configuration-block:: - - .. code-block:: php - - - - - - - - .. code-block:: yaml - - User: - type: entity - fields: - version: - type: datetime - version: true - -Version numbers (not timestamps) should however be preferred as -they can not potentially conflict in a highly concurrent -environment, unlike timestamps where this is a possibility, -depending on the resolution of the timestamp on the particular -database platform. - -When a version conflict is encountered during -``EntityManager#flush()``, an ``OptimisticLockException`` is thrown -and the active transaction rolled back (or marked for rollback). -This exception can be caught and handled. Potential responses to an -OptimisticLockException are to present the conflict to the user or -to refresh or reload objects in a new transaction and then retrying -the transaction. - -With PHP promoting a share-nothing architecture, the time between -showing an update form and actually modifying the entity can in the -worst scenario be as long as your applications session timeout. If -changes happen to the entity in that time frame you want to know -directly when retrieving the entity that you will hit an optimistic -locking exception: - -You can always verify the version of an entity during a request -either when calling ``EntityManager#find()``: - -.. code-block:: php - - find('User', $theEntityId, LockMode::OPTIMISTIC, $expectedVersion); - - // do the work - - $em->flush(); - } catch(OptimisticLockException $e) { - echo "Sorry, but someone else has already changed this entity. Please apply the changes again!"; - } - -Or you can use ``EntityManager#lock()`` to find out: - -.. code-block:: php - - find('User', $theEntityId); - - try { - // assert version - $em->lock($entity, LockMode::OPTIMISTIC, $expectedVersion); - - } catch(OptimisticLockException $e) { - echo "Sorry, but someone else has already changed this entity. Please apply the changes again!"; - } - -Important Implementation Notes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -You can easily get the optimistic locking workflow wrong if you -compare the wrong versions. Say you have Alice and Bob editing a -hypothetical blog post: - -- Alice reads the headline of the blog post being "Foo", at - optimistic lock version 1 (GET Request) -- Bob reads the headline of the blog post being "Foo", at - optimistic lock version 1 (GET Request) -- Bob updates the headline to "Bar", upgrading the optimistic lock - version to 2 (POST Request of a Form) -- Alice updates the headline to "Baz", ... (POST Request of a - Form) - -Now at the last stage of this scenario the blog post has to be read -again from the database before Alice's headline can be applied. At -this point you will want to check if the blog post is still at -version 1 (which it is not in this scenario). - -Using optimistic locking correctly, you *have* to add the version -as an additional hidden field (or into the SESSION for more -safety). Otherwise you cannot verify the version is still the one -being originally read from the database when Alice performed her -GET request for the blog post. If this happens you might see lost -updates you wanted to prevent with Optimistic Locking. - -See the example code, The form (GET Request): - -.. code-block:: php - - find('BlogPost', 123456); - - echo ''; - echo ''; - -And the change headline action (POST Request): - -.. code-block:: php - - find('BlogPost', $postId, \Doctrine\DBAL\LockMode::OPTIMISTIC, $postVersion); - -.. _transactions-and-concurrency_pessimistic-locking: - -Pessimistic Locking -~~~~~~~~~~~~~~~~~~~ - -Doctrine 2 supports Pessimistic Locking at the database level. No -attempt is being made to implement pessimistic locking inside -Doctrine, rather vendor-specific and ANSI-SQL commands are used to -acquire row-level locks. Every Entity can be part of a pessimistic -lock, there is no special metadata required to use this feature. - -However for Pessimistic Locking to work you have to disable the -Auto-Commit Mode of your Database and start a transaction around -your pessimistic lock use-case using the "Approach 2: Explicit -Transaction Demarcation" described above. Doctrine 2 will throw an -Exception if you attempt to acquire an pessimistic lock and no -transaction is running. - -Doctrine 2 currently supports two pessimistic lock modes: - - -- Pessimistic Write - (``Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE``), locks the - underlying database rows for concurrent Read and Write Operations. -- Pessimistic Read (``Doctrine\DBAL\LockMode::PESSIMISTIC_READ``), - locks other concurrent requests that attempt to update or lock rows - in write mode. - -You can use pessimistic locks in three different scenarios: - - -1. Using - ``EntityManager#find($className, $id, \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE)`` - or - ``EntityManager#find($className, $id, \Doctrine\DBAL\LockMode::PESSIMISTIC_READ)`` -2. Using - ``EntityManager#lock($entity, \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE)`` - or - ``EntityManager#lock($entity, \Doctrine\DBAL\LockMode::PESSIMISTIC_READ)`` -3. Using - ``Query#setLockMode(\Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE)`` - or - ``Query#setLockMode(\Doctrine\DBAL\LockMode::PESSIMISTIC_READ)`` - - diff --git a/vendor/doctrine/orm/docs/en/reference/unitofwork-associations.rst b/vendor/doctrine/orm/docs/en/reference/unitofwork-associations.rst deleted file mode 100644 index c9ccf73..0000000 --- a/vendor/doctrine/orm/docs/en/reference/unitofwork-associations.rst +++ /dev/null @@ -1,60 +0,0 @@ -Association Updates: Owning Side and Inverse Side -================================================= - -When mapping bidirectional associations it is important to -understand the concept of the owning and inverse sides. The -following general rules apply: - -- Relationships may be bidirectional or unidirectional. -- A bidirectional relationship has both an owning side and an inverse side -- A unidirectional relationship only has an owning side. -- Doctrine will **only** check the owning side of an association for changes. - -Bidirectional Associations --------------------------- - -The following rules apply to **bidirectional** associations: - -- The inverse side has to have the ``mappedBy`` attribute of the OneToOne, - OneToMany, or ManyToMany mapping declaration. The mappedBy - attribute contains the name of the association-field on the owning side. -- The owning side has to have the ``inversedBy`` attribute of the - OneToOne, ManyToOne, or ManyToMany mapping declaration. - The inversedBy attribute contains the name of the association-field - on the inverse-side. -- ManyToOne is always the owning side of a bidirectional association. -- OneToMany is always the inverse side of a bidirectional association. -- The owning side of a OneToOne association is the entity with the table - containing the foreign key. -- You can pick the owning side of a many-to-many association yourself. - -Important concepts ------------------- - -**Doctrine will only check the owning side of an association for changes.** - -To fully understand this, remember how bidirectional associations -are maintained in the object world. There are 2 references on each -side of the association and these 2 references both represent the -same association but can change independently of one another. Of -course, in a correct application the semantics of the bidirectional -association are properly maintained by the application developer -(that's his responsibility). Doctrine needs to know which of these -two in-memory references is the one that should be persisted and -which not. This is what the owning/inverse concept is mainly used -for. - -**Changes made only to the inverse side of an association are ignored. Make sure to update both sides of a bidirectional association (or at least the owning side, from Doctrine's point of view)** - -The owning side of a bidirectional association is the side Doctrine -"looks at" when determining the state of the association, and -consequently whether there is anything to do to update the -association in the database. - -.. note:: - - "Owning side" and "inverse side" are technical concepts of - the ORM technology, not concepts of your domain model. What you - consider as the owning side in your domain model can be different - from what the owning side is for Doctrine. These are unrelated. - diff --git a/vendor/doctrine/orm/docs/en/reference/unitofwork.rst b/vendor/doctrine/orm/docs/en/reference/unitofwork.rst deleted file mode 100644 index b060c46..0000000 --- a/vendor/doctrine/orm/docs/en/reference/unitofwork.rst +++ /dev/null @@ -1,201 +0,0 @@ -Doctrine Internals explained -============================ - -Object relational mapping is a complex topic and sufficiently understanding how Doctrine works internally helps you use its full power. - -How Doctrine keeps track of Objects ------------------------------------ - -Doctrine uses the Identity Map pattern to track objects. Whenever you fetch an -object from the database, Doctrine will keep a reference to this object inside -its UnitOfWork. The array holding all the entity references is two-levels deep -and has the keys "root entity name" and "id". Since Doctrine allows composite -keys the id is a sorted, serialized version of all the key columns. - -This allows Doctrine room for optimizations. If you call the EntityManager and -ask for an entity with a specific ID twice, it will return the same instance: - -.. code-block:: php - - public function testIdentityMap() - { - $objectA = $this->entityManager->find('EntityName', 1); - $objectB = $this->entityManager->find('EntityName', 1); - - $this->assertSame($objectA, $objectB) - } - -Only one SELECT query will be fired against the database here. In the second -``EntityManager#find()`` call Doctrine will check the identity map first and -doesn't need to make that database roundtrip. - -Even if you get a proxy object first then fetch the object by the same id you -will still end up with the same reference: - -.. code-block:: php - - public function testIdentityMapReference() - { - $objectA = $this->entityManager->getReference('EntityName', 1); - // check for proxyinterface - $this->assertInstanceOf('Doctrine\ORM\Proxy\Proxy', $objectA); - - $objectB = $this->entityManager->find('EntityName', 1); - - $this->assertSame($objectA, $objectB) - } - -The identity map being indexed by primary keys only allows shortcuts when you -ask for objects by primary key. Assume you have the following ``persons`` -table: - -:: - - id | name - ------------- - 1 | Benjamin - 2 | Bud - -Take the following example where two -consecutive calls are made against a repository to fetch an entity by a set of -criteria: - -.. code-block:: php - - public function testIdentityMapRepositoryFindBy() - { - $repository = $this->entityManager->getRepository('Person'); - $objectA = $repository->findOneBy(array('name' => 'Benjamin')); - $objectB = $repository->findOneBy(array('name' => 'Benjamin')); - - $this->assertSame($objectA, $objectB); - } - -This query will still return the same references and `$objectA` and `$objectB` -are indeed referencing the same object. However when checking your SQL logs you -will realize that two queries have been executed against the database. Doctrine -only knows objects by id, so a query for different criteria has to go to the -database, even if it was executed just before. - -But instead of creating a second Person object Doctrine first gets the primary -key from the row and check if it already has an object inside the UnitOfWork -with that primary key. In our example it finds an object and decides to return -this instead of creating a new one. - -The identity map has a second use-case. When you call ``EntityManager#flush`` -Doctrine will ask the identity map for all objects that are currently managed. -This means you don't have to call ``EntityManager#persist`` over and over again -to pass known objects to the EntityManager. This is a NO-OP for known entities, -but leads to much code written that is confusing to other developers. - -The following code WILL update your database with the changes made to the -``Person`` object, even if you did not call ``EntityManager#persist``: - -.. code-block:: php - - find("Person", 1); - $user->setName("Guilherme"); - $entityManager->flush(); - -How Doctrine Detects Changes ----------------------------- - -Doctrine is a data-mapper that tries to achieve persistence-ignorance (PI). -This means you map php objects into a relational database that don't -necessarily know about the database at all. A natural question would now be, -"how does Doctrine even detect objects have changed?". - -For this Doctrine keeps a second map inside the UnitOfWork. Whenever you fetch -an object from the database Doctrine will keep a copy of all the properties and -associations inside the UnitOfWork. Because variables in the PHP language are -subject to "copy-on-write" the memory usage of a PHP request that only reads -objects from the database is the same as if Doctrine did not keep this variable -copy. Only if you start changing variables PHP will create new variables internally -that consume new memory. - -Now whenever you call ``EntityManager#flush`` Doctrine will iterate over the -Identity Map and for each object compares the original property and association -values with the values that are currently set on the object. If changes are -detected then the object is queued for a SQL UPDATE operation. Only the fields -that actually changed are updated. - -This process has an obvious performance impact. The larger the size of the -UnitOfWork is, the longer this computation takes. There are several ways to -optimize the performance of the Flush Operation: - -- Mark entities as read only. These entities can only be inserted or removed, - but are never updated. They are omitted in the changeset calculation. -- Temporarily mark entities as read only. If you have a very large UnitOfWork - but know that a large set of entities has not changed, just mark them as read - only with ``$entityManager->getUnitOfWork()->markReadOnly($entity)``. -- Flush only a single entity with ``$entityManager->flush($entity)``. -- Use :doc:`Change Tracking Policies ` to use more - explicit strategies of notifying the UnitOfWork what objects/properties - changed. - - -Query Internals ---------------- - -The different ORM Layers ------------------------- - -Doctrine ships with a set of layers with different responsibilities. This -section gives a short explanation of each layer. - -Hydration -~~~~~~~~~ - -Responsible for creating a final result from a raw database statement and a -result-set mapping object. The developer can choose which kind of result he -wishes to be hydrated. Default result-types include: - -- SQL to Entities -- SQL to structured Arrays -- SQL to simple scalar result arrays -- SQL to a single result variable - -Hydration to entities and arrays is one of the most complex parts of Doctrine -algorithm-wise. It can build results with for example: - -- Single table selects -- Joins with n:1 or 1:n cardinality, grouping belonging to the same parent. -- Mixed results of objects and scalar values -- Hydration of results by a given scalar value as key. - -Persisters -~~~~~~~~~~ - -tbr - -UnitOfWork -~~~~~~~~~~ - -tbr - -ResultSetMapping -~~~~~~~~~~~~~~~~ - -tbr - -DQL Parser -~~~~~~~~~~ - -tbr - -SQLWalker -~~~~~~~~~ - -tbr - -EntityManager -~~~~~~~~~~~~~ - -tbr - -ClassMetadataFactory -~~~~~~~~~~~~~~~~~~~~ - -tbr - diff --git a/vendor/doctrine/orm/docs/en/reference/working-with-associations.rst b/vendor/doctrine/orm/docs/en/reference/working-with-associations.rst deleted file mode 100644 index ab588e4..0000000 --- a/vendor/doctrine/orm/docs/en/reference/working-with-associations.rst +++ /dev/null @@ -1,728 +0,0 @@ -Working with Associations -========================= - -Associations between entities are represented just like in regular -object-oriented PHP code using references to other objects or -collections of objects. - -Changes to associations in your code are not synchronized to the -database directly, only when calling ``EntityManager#flush()``. - -There are other concepts you should know about when working -with associations in Doctrine: - -- If an entity is removed from a collection, the association is - removed, not the entity itself. A collection of entities always - only represents the association to the containing entities, not the - entity itself. -- When a bidirectional association is updated, Doctrine only checks - on one of both sides for these changes. This is called the :doc:`owning side ` - of the association. -- A property with a reference to many entities has to be instances of the - ``Doctrine\Common\Collections\Collection`` interface. - -Association Example Entities ----------------------------- - -We will use a simple comment system with Users and Comments as -entities to show examples of association management. See the PHP -docblocks of each association in the following example for -information about its type and if it's the owning or inverse side. - -.. code-block:: php - - commentsRead; - } - - public function setFirstComment(Comment $c) { - $this->firstComment = $c; - } - } - -The interaction code would then look like in the following snippet -(``$em`` here is an instance of the EntityManager): - -.. code-block:: php - - find('User', $userId); - - // unidirectional many to many - $comment = $em->find('Comment', $readCommentId); - $user->getReadComments()->add($comment); - - $em->flush(); - - // unidirectional many to one - $myFirstComment = new Comment(); - $user->setFirstComment($myFirstComment); - - $em->persist($myFirstComment); - $em->flush(); - -In the case of bi-directional associations you have to update the -fields on both sides: - -.. code-block:: php - - commentsAuthored; - } - - public function getFavoriteComments() { - return $this->favorites; - } - } - - class Comment - { - // ... - - public function getUserFavorites() { - return $this->userFavorites; - } - - public function setAuthor(User $author = null) { - $this->author = $author; - } - } - - // Many-to-Many - $user->getFavorites()->add($favoriteComment); - $favoriteComment->getUserFavorites()->add($user); - - $em->flush(); - - // Many-To-One / One-To-Many Bidirectional - $newComment = new Comment(); - $user->getAuthoredComments()->add($newComment); - $newComment->setAuthor($user); - - $em->persist($newComment); - $em->flush(); - -Notice how always both sides of the bidirectional association are -updated. The previous unidirectional associations were simpler to -handle. - -Removing Associations ---------------------- - -Removing an association between two entities is similarly -straight-forward. There are two strategies to do so, by key and by -element. Here are some examples: - -.. code-block:: php - - getComments()->removeElement($comment); - $comment->setAuthor(null); - - $user->getFavorites()->removeElement($comment); - $comment->getUserFavorites()->removeElement($user); - - // Remove by Key - $user->getComments()->remove($ithComment); - $comment->setAuthor(null); - -You need to call ``$em->flush()`` to make persist these changes in -the database permanently. - -Notice how both sides of the bidirectional association are always -updated. Unidirectional associations are consequently simpler to -handle. - -Also note that if you use type-hinting in your methods, you will -have to specify a nullable type, i.e. ``setAddress(?Address $address)``, -otherwise ``setAddress(null)`` will fail to remove the association. -Another way to deal with this is to provide a special method, like -``removeAddress()``. This can also provide better encapsulation as -it hides the internal meaning of not having an address. - -When working with collections, keep in mind that a Collection is -essentially an ordered map (just like a PHP array). That is why the -``remove`` operation accepts an index/key. ``removeElement`` is a -separate method that has O(n) complexity using ``array_search``, -where n is the size of the map. - -.. note:: - - Since Doctrine always only looks at the owning side of a - bidirectional association for updates, it is not necessary for - write operations that an inverse collection of a bidirectional - one-to-many or many-to-many association is updated. This knowledge - can often be used to improve performance by avoiding the loading of - the inverse collection. - - -You can also clear the contents of a whole collection using the -``Collections::clear()`` method. You should be aware that using -this method can lead to a straight and optimized database delete or -update call during the flush operation that is not aware of -entities that have been re-added to the collection. - -Say you clear a collection of tags by calling -``$post->getTags()->clear();`` and then call -``$post->getTags()->add($tag)``. This will not recognize the tag having -already been added previously and will consequently issue two separate database -calls. - -Association Management Methods ------------------------------- - -It is generally a good idea to encapsulate proper association -management inside the entity classes. This makes it easier to use -the class correctly and can encapsulate details about how the -association is maintained. - -The following code shows updates to the previous User and Comment -example that encapsulate much of the association management code: - -.. code-block:: php - - commentsRead[] = $comment; - } - - public function addComment(Comment $comment) { - if (count($this->commentsAuthored) == 0) { - $this->setFirstComment($comment); - } - $this->comments[] = $comment; - $comment->setAuthor($this); - } - - private function setFirstComment(Comment $c) { - $this->firstComment = $c; - } - - public function addFavorite(Comment $comment) { - $this->favorites->add($comment); - $comment->addUserFavorite($this); - } - - public function removeFavorite(Comment $comment) { - $this->favorites->removeElement($comment); - $comment->removeUserFavorite($this); - } - } - - class Comment - { - // .. - - public function addUserFavorite(User $user) { - $this->userFavorites[] = $user; - } - - public function removeUserFavorite(User $user) { - $this->userFavorites->removeElement($user); - } - } - -You will notice that ``addUserFavorite`` and ``removeUserFavorite`` -do not call ``addFavorite`` and ``removeFavorite``, thus the -bidirectional association is strictly-speaking still incomplete. -However if you would naively add the ``addFavorite`` in -``addUserFavorite``, you end up with an infinite loop, so more work -is needed. As you can see, proper bidirectional association -management in plain OOP is a non-trivial task and encapsulating all -the details inside the classes can be challenging. - -.. note:: - - If you want to make sure that your collections are perfectly - encapsulated you should not return them from a - ``getCollectionName()`` method directly, but call - ``$collection->toArray()``. This way a client programmer for the - entity cannot circumvent the logic you implement on your entity for - association management. For example: - - -.. code-block:: php - - commentsRead->toArray(); - } - } - -This will however always initialize the collection, with all the -performance penalties given the size. In some scenarios of large -collections it might even be a good idea to completely hide the -read access behind methods on the EntityRepository. - -There is no single, best way for association management. It greatly -depends on the requirements of your concrete domain model as well -as your preferences. - -Synchronizing Bidirectional Collections ---------------------------------------- - -In the case of Many-To-Many associations you as the developer have the -responsibility of keeping the collections on the owning and inverse side -in sync when you apply changes to them. Doctrine can only -guarantee a consistent state for the hydration, not for your client -code. - -Using the User-Comment entities from above, a very simple example -can show the possible caveats you can encounter: - -.. code-block:: php - - getFavorites()->add($favoriteComment); - // not calling $favoriteComment->getUserFavorites()->add($user); - - $user->getFavorites()->contains($favoriteComment); // TRUE - $favoriteComment->getUserFavorites()->contains($user); // FALSE - -There are two approaches to handle this problem in your code: - - -1. Ignore updating the inverse side of bidirectional collections, - BUT never read from them in requests that changed their state. In - the next request Doctrine hydrates the consistent collection state - again. -2. Always keep the bidirectional collections in sync through - association management methods. Reads of the Collections directly - after changes are consistent then. - -.. _transitive-persistence: - -Transitive persistence / Cascade Operations -------------------------------------------- - -Doctrine 2 provides a mechanism for transitive persistence through cascading of certain operations. -Each association to another entity or a collection of -entities can be configured to automatically cascade the following operations to the associated entities: -``persist``, ``remove``, ``merge``, ``detach``, ``refresh`` or ``all``. - -The main use case for ``cascade: persist`` is to avoid "exposing" associated entities to your PHP application. -Continuing with the User-Comment example of this chapter, this is how the creation of a new user and a new -comment might look like in your controller (without ``cascade: persist``): - -.. code-block:: php - - addComment($myFirstComment); - - $em->persist($user); - $em->persist($myFirstComment); // required, if `cascade: persist` is not set - $em->flush(); - -Note that the Comment entity is instantiated right here in the controller. -To avoid this, ``cascade: persist`` allows you to "hide" the Comment entity from the controller, -only accessing it through the User entity: - -.. code-block:: php - - id = User::new(); - $this->comments = new ArrayCollection(); - } - - public function comment(string $text, DateTimeInterface $time) : void - { - $newComment = Comment::create($text, $time); - $newComment->setUser($this); - $this->comments->add($newComment); - } - - // ... - } - -If you then set up the cascading to the ``User#commentsAuthored`` property... - -.. code-block:: php - - comment('Lorem ipsum', new DateTime()); - - $em->persist($user); - $em->flush(); - -.. note:: - - The idea of ``cascade: persist`` is not to save you any lines of code in the controller. - If you instantiate the comment object in the controller (i.e. don't set up the user entity as shown above), - even with ``cascade: persist`` you still have to call ``$myFirstComment->setUser($user);``. - -Thanks to ``cascade: remove``, you can easily delete a user and all linked comments without having to loop through them: - -.. code-block:: php - - find('User', $deleteUserId); - - $em->remove($user); - $em->flush(); - -.. note:: - - Cascade operations are performed in memory. That means collections and related entities - are fetched into memory (even if they are marked as lazy) when - the cascade operation is about to be performed. This approach allows - entity lifecycle events to be performed for each of these operations. - - However, pulling object graphs into memory on cascade can cause considerable performance - overhead, especially when the cascaded collections are large. Make sure - to weigh the benefits and downsides of each cascade operation that you define. - - To rely on the database level cascade operations for the delete operation instead, you can - configure each join column with :doc:`the onDelete option `. - -Even though automatic cascading is convenient, it should be used -with care. Do not blindly apply ``cascade=all`` to all associations as -it will unnecessarily degrade the performance of your application. -For each cascade operation that gets activated, Doctrine also -applies that operation to the association, be it single or -collection valued. - -Persistence by Reachability: Cascade Persist -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There are additional semantics that apply to the Cascade Persist -operation. During each ``flush()`` operation Doctrine detects if there -are new entities in any collection and three possible cases can -happen: - - -1. New entities in a collection marked as ``cascade: persist`` will be - directly persisted by Doctrine. -2. New entities in a collection not marked as ``cascade: persist`` will - produce an Exception and rollback the ``flush()`` operation. -3. Collections without new entities are skipped. - -This concept is called Persistence by Reachability: New entities -that are found on already managed entities are automatically -persisted as long as the association is defined as ``cascade: persist``. - -Orphan Removal --------------- - -There is another concept of cascading that is relevant only when removing entities -from collections. If an Entity of type ``A`` contains references to privately -owned Entities ``B`` then if the reference from ``A`` to ``B`` is removed the -entity ``B`` should also be removed, because it is not used anymore. - -OrphanRemoval works with one-to-one, one-to-many and many-to-many associations. - -.. note:: - - When using the ``orphanRemoval=true`` option Doctrine makes the assumption - that the entities are privately owned and will **NOT** be reused by other entities. - If you neglect this assumption your entities will get deleted by Doctrine even if - you assigned the orphaned entity to another one. - -As a better example consider an Addressbook application where you have Contacts, Addresses -and StandingData: - -.. code-block:: php - - addresses = new ArrayCollection(); - } - - public function newStandingData(StandingData $sd) - { - $this->standingData = $sd; - } - - public function removeAddress($pos) - { - unset($this->addresses[$pos]); - } - } - -Now two examples of what happens when you remove the references: - -.. code-block:: php - - find("Addressbook\Contact", $contactId); - $contact->newStandingData(new StandingData("Firstname", "Lastname", "Street")); - $contact->removeAddress(1); - - $em->flush(); - -In this case you have not only changed the ``Contact`` entity itself but -you have also removed the references for standing data and as well as one -address reference. When flush is called not only are the references removed -but both the old standing data and the one address entity are also deleted -from the database. - -.. _filtering-collections: - -Filtering Collections ---------------------- - -Collections have a filtering API that allows to slice parts of data from -a collection. If the collection has not been loaded from the database yet, -the filtering API can work on the SQL level to make optimized access to -large collections. - -.. code-block:: php - - find('Group', $groupId); - $userCollection = $group->getUsers(); - - $criteria = Criteria::create() - ->where(Criteria::expr()->eq("birthday", "1982-02-17")) - ->orderBy(array("username" => Criteria::ASC)) - ->setFirstResult(0) - ->setMaxResults(20) - ; - - $birthdayUsers = $userCollection->matching($criteria); - -.. tip:: - - You can move the access of slices of collections into dedicated methods of - an entity. For example ``Group#getTodaysBirthdayUsers()``. - -The Criteria has a limited matching language that works both on the -SQL and on the PHP collection level. This means you can use collection matching -interchangeably, independent of in-memory or sql-backed collections. - -.. code-block:: php - - find('CMS\Article', 1234); - $article->setHeadline('Hello World dude!'); - - $article2 = $entityManager->find('CMS\Article', 1234); - echo $article2->getHeadline(); - -In this case the Article is accessed from the entity manager twice, -but modified in between. Doctrine 2 realizes this and will only -ever give you access to one instance of the Article with ID 1234, -no matter how often do you retrieve it from the EntityManager and -even no matter what kind of Query method you are using (find, -Repository Finder or DQL). This is called "Identity Map" pattern, -which means Doctrine keeps a map of each entity and ids that have -been retrieved per PHP request and keeps returning you the same -instances. - -In the previous example the echo prints "Hello World dude!" to the -screen. You can even verify that ``$article`` and ``$article2`` are -indeed pointing to the same instance by running the following -code: - -.. code-block:: php - - comments = new ArrayCollection(); - } - - public function getAuthor() { return $this->author; } - public function getComments() { return $this->comments; } - } - - $article = $em->find('Article', 1); - -This code only retrieves the ``Article`` instance with id 1 executing -a single SELECT statement against the articles table in the database. -You can still access the associated properties author and comments -and the associated objects they contain. - -This works by utilizing the lazy loading pattern. Instead of -passing you back a real Author instance and a collection of -comments Doctrine will create proxy instances for you. Only if you -access these proxies for the first time they will go through the -EntityManager and load their state from the database. - -This lazy-loading process happens behind the scenes, hidden from -your code. See the following code: - -.. code-block:: php - - find('Article', 1); - - // accessing a method of the user instance triggers the lazy-load - echo "Author: " . $article->getAuthor()->getName() . "\n"; - - // Lazy Loading Proxies pass instanceof tests: - if ($article->getAuthor() instanceof User) { - // a User Proxy is a generated "UserProxy" class - } - - // accessing the comments as an iterator triggers the lazy-load - // retrieving ALL the comments of this article from the database - // using a single SELECT statement - foreach ($article->getComments() as $comment) { - echo $comment->getText() . "\n\n"; - } - - // Article::$comments passes instanceof tests for the Collection interface - // But it will NOT pass for the ArrayCollection interface - if ($article->getComments() instanceof \Doctrine\Common\Collections\Collection) { - echo "This will always be true!"; - } - -A slice of the generated proxy classes code looks like the -following piece of code. A real proxy class override ALL public -methods along the lines of the ``getName()`` method shown below: - -.. code-block:: php - - _load(); - return parent::getName(); - } - // .. other public methods of User - } - -.. warning:: - - Traversing the object graph for parts that are lazy-loaded will - easily trigger lots of SQL queries and will perform badly if used - to heavily. Make sure to use DQL to fetch-join all the parts of the - object-graph that you need as efficiently as possible. - - -Persisting entities -------------------- - -An entity can be made persistent by passing it to the -``EntityManager#persist($entity)`` method. By applying the persist -operation on some entity, that entity becomes MANAGED, which means -that its persistence is from now on managed by an EntityManager. As -a result the persistent state of such an entity will subsequently -be properly synchronized with the database when -``EntityManager#flush()`` is invoked. - -.. note:: - - Invoking the ``persist`` method on an entity does NOT - cause an immediate SQL INSERT to be issued on the database. - Doctrine applies a strategy called "transactional write-behind", - which means that it will delay most SQL commands until - ``EntityManager#flush()`` is invoked which will then issue all - necessary SQL statements to synchronize your objects with the - database in the most efficient way and a single, short transaction, - taking care of maintaining referential integrity. - - -Example: - -.. code-block:: php - - setName('Mr.Right'); - $em->persist($user); - $em->flush(); - -.. note:: - - Generated entity identifiers / primary keys are - guaranteed to be available after the next successful flush - operation that involves the entity in question. You can not rely on - a generated identifier to be available directly after invoking - ``persist``. The inverse is also true. You can not rely on a - generated identifier being not available after a failed flush - operation. - - -The semantics of the persist operation, applied on an entity X, are -as follows: - - -- If X is a new entity, it becomes managed. The entity X will be - entered into the database as a result of the flush operation. -- If X is a preexisting managed entity, it is ignored by the - persist operation. However, the persist operation is cascaded to - entities referenced by X, if the relationships from X to these - other entities are mapped with cascade=PERSIST or cascade=ALL (see - ":ref:`transitive-persistence`"). -- If X is a removed entity, it becomes managed. -- If X is a detached entity, an exception will be thrown on - flush. - -Removing entities ------------------ - -An entity can be removed from persistent storage by passing it to -the ``EntityManager#remove($entity)`` method. By applying the -``remove`` operation on some entity, that entity becomes REMOVED, -which means that its persistent state will be deleted once -``EntityManager#flush()`` is invoked. - -.. note:: - - Just like ``persist``, invoking ``remove`` on an entity - does NOT cause an immediate SQL DELETE to be issued on the - database. The entity will be deleted on the next invocation of - ``EntityManager#flush()`` that involves that entity. This - means that entities scheduled for removal can still be queried - for and appear in query and collection results. See - the section on :ref:`Database and UnitOfWork Out-Of-Sync ` - for more information. - - -Example: - -.. code-block:: php - - remove($user); - $em->flush(); - -The semantics of the remove operation, applied to an entity X are -as follows: - - -- If X is a new entity, it is ignored by the remove operation. - However, the remove operation is cascaded to entities referenced by - X, if the relationship from X to these other entities is mapped - with cascade=REMOVE or cascade=ALL (see ":ref:`transitive-persistence`"). -- If X is a managed entity, the remove operation causes it to - become removed. The remove operation is cascaded to entities - referenced by X, if the relationships from X to these other - entities is mapped with cascade=REMOVE or cascade=ALL (see - ":ref:`transitive-persistence`"). -- If X is a detached entity, an InvalidArgumentException will be - thrown. -- If X is a removed entity, it is ignored by the remove operation. -- A removed entity X will be removed from the database as a result - of the flush operation. - -After an entity has been removed its in-memory state is the same as -before the removal, except for generated identifiers. - -Removing an entity will also automatically delete any existing -records in many-to-many join tables that link this entity. The -action taken depends on the value of the ``@joinColumn`` mapping -attribute "onDelete". Either Doctrine issues a dedicated ``DELETE`` -statement for records of each join table or it depends on the -foreign key semantics of onDelete="CASCADE". - -Deleting an object with all its associated objects can be achieved -in multiple ways with very different performance impacts. - - -1. If an association is marked as ``CASCADE=REMOVE`` Doctrine 2 - will fetch this association. If its a Single association it will - pass this entity to - ´EntityManager#remove()``. If the association is a collection, Doctrine will loop over all its elements and pass them to``EntityManager#remove()\`. - In both cases the cascade remove semantics are applied recursively. - For large object graphs this removal strategy can be very costly. -2. Using a DQL ``DELETE`` statement allows you to delete multiple - entities of a type with a single command and without hydrating - these entities. This can be very efficient to delete large object - graphs from the database. -3. Using foreign key semantics ``onDelete="CASCADE"`` can force the - database to remove all associated objects internally. This strategy - is a bit tricky to get right but can be very powerful and fast. You - should be aware however that using strategy 1 (``CASCADE=REMOVE``) - completely by-passes any foreign key ``onDelete=CASCADE`` option, - because Doctrine will fetch and remove all associated entities - explicitly nevertheless. - -Detaching entities ------------------- - -An entity is detached from an EntityManager and thus no longer -managed by invoking the ``EntityManager#detach($entity)`` method on -it or by cascading the detach operation to it. Changes made to the -detached entity, if any (including removal of the entity), will not -be synchronized to the database after the entity has been -detached. - -Doctrine will not hold on to any references to a detached entity. - -Example: - -.. code-block:: php - - detach($entity); - -The semantics of the detach operation, applied to an entity X are -as follows: - - -- If X is a managed entity, the detach operation causes it to - become detached. The detach operation is cascaded to entities - referenced by X, if the relationships from X to these other - entities is mapped with cascade=DETACH or cascade=ALL (see - ":ref:`transitive-persistence`"). Entities which previously referenced X - will continue to reference X. -- If X is a new or detached entity, it is ignored by the detach - operation. -- If X is a removed entity, the detach operation is cascaded to - entities referenced by X, if the relationships from X to these - other entities is mapped with cascade=DETACH or cascade=ALL (see - ":ref:`transitive-persistence`"). Entities which previously referenced X - will continue to reference X. - -There are several situations in which an entity is detached -automatically without invoking the ``detach`` method: - - -- When ``EntityManager#clear()`` is invoked, all entities that are - currently managed by the EntityManager instance become detached. -- When serializing an entity. The entity retrieved upon subsequent - unserialization will be detached (This is the case for all entities - that are serialized and stored in some cache, i.e. when using the - Query Result Cache). - -The ``detach`` operation is usually not as frequently needed and -used as ``persist`` and ``remove``. - -Merging entities ----------------- - -Merging entities refers to the merging of (usually detached) -entities into the context of an EntityManager so that they become -managed again. To merge the state of an entity into an -EntityManager use the ``EntityManager#merge($entity)`` method. The -state of the passed entity will be merged into a managed copy of -this entity and this copy will subsequently be returned. - -Example: - -.. code-block:: php - - merge($detachedEntity); - // $entity now refers to the fully managed copy returned by the merge operation. - // The EntityManager $em now manages the persistence of $entity as usual. - -.. note:: - - When you want to serialize/unserialize entities you - have to make all entity properties protected, never private. The - reason for this is, if you serialize a class that was a proxy - instance before, the private variables won't be serialized and a - PHP Notice is thrown. - - -The semantics of the merge operation, applied to an entity X, are -as follows: - - -- If X is a detached entity, the state of X is copied onto a - pre-existing managed entity instance X' of the same identity. -- If X is a new entity instance, a new managed copy X' will be - created and the state of X is copied onto this managed instance. -- If X is a removed entity instance, an InvalidArgumentException - will be thrown. -- If X is a managed entity, it is ignored by the merge operation, - however, the merge operation is cascaded to entities referenced by - relationships from X if these relationships have been mapped with - the cascade element value MERGE or ALL (see ":ref:`transitive-persistence`"). -- For all entities Y referenced by relationships from X having the - cascade element value MERGE or ALL, Y is merged recursively as Y'. - For all such Y referenced by X, X' is set to reference Y'. (Note - that if X is managed then X is the same object as X'.) -- If X is an entity merged to X', with a reference to another - entity Y, where cascade=MERGE or cascade=ALL is not specified, then - navigation of the same association from X' yields a reference to a - managed object Y' with the same persistent identity as Y. - -The ``merge`` operation will throw an ``OptimisticLockException`` -if the entity being merged uses optimistic locking through a -version field and the versions of the entity being merged and the -managed copy don't match. This usually means that the entity has -been modified while being detached. - -The ``merge`` operation is usually not as frequently needed and -used as ``persist`` and ``remove``. The most common scenario for -the ``merge`` operation is to reattach entities to an EntityManager -that come from some cache (and are therefore detached) and you want -to modify and persist such an entity. - -.. warning:: - - If you need to perform multiple merges of entities that share certain subparts - of their object-graphs and cascade merge, then you have to call ``EntityManager#clear()`` between the - successive calls to ``EntityManager#merge()``. Otherwise you might end up with - multiple copies of the "same" object in the database, however with different ids. - -.. note:: - - If you load some detached entities from a cache and you do - not need to persist or delete them or otherwise make use of them - without the need for persistence services there is no need to use - ``merge``. I.e. you can simply pass detached objects from a cache - directly to the view. - - -Synchronization with the Database ---------------------------------- - -The state of persistent entities is synchronized with the database -on flush of an ``EntityManager`` which commits the underlying -``UnitOfWork``. The synchronization involves writing any updates to -persistent entities and their relationships to the database. -Thereby bidirectional relationships are persisted based on the -references held by the owning side of the relationship as explained -in the Association Mapping chapter. - -When ``EntityManager#flush()`` is called, Doctrine inspects all -managed, new and removed entities and will perform the following -operations. - -.. _workingobjects_database_uow_outofsync: - -Effects of Database and UnitOfWork being Out-Of-Sync -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -As soon as you begin to change the state of entities, call persist or remove the -contents of the UnitOfWork and the database will drive out of sync. They can -only be synchronized by calling ``EntityManager#flush()``. This section -describes the effects of database and UnitOfWork being out of sync. - -- Entities that are scheduled for removal can still be queried from the database. - They are returned from DQL and Repository queries and are visible in collections. -- Entities that are passed to ``EntityManager#persist`` do not turn up in query - results. -- Entities that have changed will not be overwritten with the state from the database. - This is because the identity map will detect the construction of an already existing - entity and assumes its the most up to date version. - -``EntityManager#flush()`` is never called implicitly by Doctrine. You always have to trigger it manually. - -Synchronizing New and Managed Entities -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The flush operation applies to a managed entity with the following -semantics: - - -- The entity itself is synchronized to the database using a SQL - UPDATE statement, only if at least one persistent field has - changed. -- No SQL updates are executed if the entity did not change. - -The flush operation applies to a new entity with the following -semantics: - - -- The entity itself is synchronized to the database using a SQL - INSERT statement. - -For all (initialized) relationships of the new or managed entity -the following semantics apply to each associated entity X: - - -- If X is new and persist operations are configured to cascade on - the relationship, X will be persisted. -- If X is new and no persist operations are configured to cascade - on the relationship, an exception will be thrown as this indicates - a programming error. -- If X is removed and persist operations are configured to cascade - on the relationship, an exception will be thrown as this indicates - a programming error (X would be re-persisted by the cascade). -- If X is detached and persist operations are configured to - cascade on the relationship, an exception will be thrown (This is - semantically the same as passing X to persist()). - -Synchronizing Removed Entities -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The flush operation applies to a removed entity by deleting its -persistent state from the database. No cascade options are relevant -for removed entities on flush, the cascade remove option is already -executed during ``EntityManager#remove($entity)``. - -The size of a Unit of Work -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The size of a Unit of Work mainly refers to the number of managed -entities at a particular point in time. - -The cost of flushing -~~~~~~~~~~~~~~~~~~~~ - -How costly a flush operation is, mainly depends on two factors: - - -- The size of the EntityManager's current UnitOfWork. -- The configured change tracking policies - -You can get the size of a UnitOfWork as follows: - -.. code-block:: php - - getUnitOfWork()->size(); - -The size represents the number of managed entities in the Unit of -Work. This size affects the performance of flush() operations due -to change tracking (see "Change Tracking Policies") and, of course, -memory consumption, so you may want to check it from time to time -during development. - -.. note:: - - Do not invoke ``flush`` after every change to an entity - or every single invocation of persist/remove/merge/... This is an - anti-pattern and unnecessarily reduces the performance of your - application. Instead, form units of work that operate on your - objects and call ``flush`` when you are done. While serving a - single HTTP request there should be usually no need for invoking - ``flush`` more than 0-2 times. - - -Direct access to a Unit of Work -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can get direct access to the Unit of Work by calling -``EntityManager#getUnitOfWork()``. This will return the UnitOfWork -instance the EntityManager is currently using. - -.. code-block:: php - - getUnitOfWork(); - -.. note:: - - Directly manipulating a UnitOfWork is not recommended. - When working directly with the UnitOfWork API, respect methods - marked as INTERNAL by not using them and carefully read the API - documentation. - - -Entity State -~~~~~~~~~~~~ - -As outlined in the architecture overview an entity can be in one of -four possible states: NEW, MANAGED, REMOVED, DETACHED. If you -explicitly need to find out what the current state of an entity is -in the context of a certain ``EntityManager`` you can ask the -underlying ``UnitOfWork``: - -.. code-block:: php - - getUnitOfWork()->getEntityState($entity)) { - case UnitOfWork::STATE_MANAGED: - ... - case UnitOfWork::STATE_REMOVED: - ... - case UnitOfWork::STATE_DETACHED: - ... - case UnitOfWork::STATE_NEW: - ... - } - -An entity is in MANAGED state if it is associated with an -``EntityManager`` and it is not REMOVED. - -An entity is in REMOVED state after it has been passed to -``EntityManager#remove()`` until the next flush operation of the -same EntityManager. A REMOVED entity is still associated with an -``EntityManager`` until the next flush operation. - -An entity is in DETACHED state if it has persistent state and -identity but is currently not associated with an -``EntityManager``. - -An entity is in NEW state if has no persistent state and identity -and is not associated with an ``EntityManager`` (for example those -just created via the "new" operator). - -Querying --------- - -Doctrine 2 provides the following ways, in increasing level of -power and flexibility, to query for persistent objects. You should -always start with the simplest one that suits your needs. - -By Primary Key -~~~~~~~~~~~~~~ - -The most basic way to query for a persistent object is by its -identifier / primary key using the -``EntityManager#find($entityName, $id)`` method. Here is an -example: - -.. code-block:: php - - find('MyProject\Domain\User', $id); - -The return value is either the found entity instance or null if no -instance could be found with the given identifier. - -Essentially, ``EntityManager#find()`` is just a shortcut for the -following: - -.. code-block:: php - - getRepository('MyProject\Domain\User')->find($id); - -``EntityManager#getRepository($entityName)`` returns a repository -object which provides many ways to retrieve entities of the -specified type. By default, the repository instance is of type -``Doctrine\ORM\EntityRepository``. You can also use custom -repository classes as shown later. - -By Simple Conditions -~~~~~~~~~~~~~~~~~~~~ - -To query for one or more entities based on several conditions that -form a logical conjunction, use the ``findBy`` and ``findOneBy`` -methods on a repository as follows: - -.. code-block:: php - - getRepository('MyProject\Domain\User')->findBy(array('age' => 20)); - - // All users that are 20 years old and have a surname of 'Miller' - $users = $em->getRepository('MyProject\Domain\User')->findBy(array('age' => 20, 'surname' => 'Miller')); - - // A single user by its nickname - $user = $em->getRepository('MyProject\Domain\User')->findOneBy(array('nickname' => 'romanb')); - -You can also load by owning side associations through the repository: - -.. code-block:: php - - find('MyProject\Domain\Phonenumber', 1234); - $user = $em->getRepository('MyProject\Domain\User')->findOneBy(array('phone' => $number->getId())); - -The ``EntityRepository#findBy()`` method additionally accepts orderings, limit and offset as second to fourth parameters: - -.. code-block:: php - - getRepository('MyProject\Domain\User')->findBy(array('age' => 20), array('name' => 'ASC'), 10, 0); - -If you pass an array of values Doctrine will convert the query into a WHERE field IN (..) query automatically: - -.. code-block:: php - - getRepository('MyProject\Domain\User')->findBy(array('age' => array(20, 30, 40))); - // translates roughly to: SELECT * FROM users WHERE age IN (20, 30, 40) - -An EntityRepository also provides a mechanism for more concise -calls through its use of ``__call``. Thus, the following two -examples are equivalent: - -.. code-block:: php - - getRepository('MyProject\Domain\User')->findOneBy(array('nickname' => 'romanb')); - - // A single user by its nickname (__call magic) - $user = $em->getRepository('MyProject\Domain\User')->findOneByNickname('romanb'); - -Additionally, you can just count the result of the provided conditions when you don't really need the data: - -.. code-block:: php - - getRepository('MyProject\Domain\User')->count(['nickname' => 'nonexistent']); - -By Criteria -~~~~~~~~~~~ - -.. versionadded:: 2.3 - -The Repository implement the ``Doctrine\Common\Collections\Selectable`` -interface. That means you can build ``Doctrine\Common\Collections\Criteria`` -and pass them to the ``matching($criteria)`` method. - -See section `Filtering collections` of chapter :doc:`Working with Associations ` - -By Eager Loading -~~~~~~~~~~~~~~~~ - -Whenever you query for an entity that has persistent associations -and these associations are mapped as EAGER, they will automatically -be loaded together with the entity being queried and is thus -immediately available to your application. - -By Lazy Loading -~~~~~~~~~~~~~~~ - -Whenever you have a managed entity instance at hand, you can -traverse and use any associations of that entity that are -configured LAZY as if they were in-memory already. Doctrine will -automatically load the associated objects on demand through the -concept of lazy-loading. - -By DQL -~~~~~~ - -The most powerful and flexible method to query for persistent -objects is the Doctrine Query Language, an object query language. -DQL enables you to query for persistent objects in the language of -objects. DQL understands classes, fields, inheritance and -associations. DQL is syntactically very similar to the familiar SQL -but *it is not SQL*. - -A DQL query is represented by an instance of the -``Doctrine\ORM\Query`` class. You create a query using -``EntityManager#createQuery($dql)``. Here is a simple example: - -.. code-block:: php - - createQuery("select u from MyDomain\Model\User u where u.age >= 20 and u.age <= 30"); - $users = $q->getResult(); - -Note that this query contains no knowledge about the relational -schema, only about the object model. DQL supports positional as -well as named parameters, many functions, (fetch) joins, -aggregates, subqueries and much more. Detailed information about -DQL and its syntax as well as the Doctrine class can be found in -:doc:`the dedicated chapter `. -For programmatically building up queries based on conditions that -are only known at runtime, Doctrine provides the special -``Doctrine\ORM\QueryBuilder`` class. While this a powerful tool, -it also brings more complexity to your code compared to plain DQL, -so you should only use it when you need it. More information on -constructing queries with a QueryBuilder can be found -:doc:`in Query Builder chapter `. - -By Native Queries -~~~~~~~~~~~~~~~~~ - -As an alternative to DQL or as a fallback for special SQL -statements native queries can be used. Native queries are built by -using a hand-crafted SQL query and a ResultSetMapping that -describes how the SQL result set should be transformed by Doctrine. -More information about native queries can be found in -:doc:`the dedicated chapter `. - -Custom Repositories -~~~~~~~~~~~~~~~~~~~ - -By default the EntityManager returns a default implementation of -``Doctrine\ORM\EntityRepository`` when you call -``EntityManager#getRepository($entityClass)``. You can overwrite -this behaviour by specifying the class name of your own Entity -Repository in the Annotation, XML or YAML metadata. In large -applications that require lots of specialized DQL queries using a -custom repository is one recommended way of grouping these queries -in a central location. - -.. code-block:: php - - _em->createQuery('SELECT u FROM MyDomain\Model\User u WHERE u.status = "admin"') - ->getResult(); - } - } - -You can access your repository now by calling: - -.. code-block:: php - - getRepository('MyDomain\Model\User')->getAllAdminUsers(); - - diff --git a/vendor/doctrine/orm/docs/en/reference/xml-mapping.rst b/vendor/doctrine/orm/docs/en/reference/xml-mapping.rst deleted file mode 100644 index f57ee46..0000000 --- a/vendor/doctrine/orm/docs/en/reference/xml-mapping.rst +++ /dev/null @@ -1,782 +0,0 @@ -XML Mapping -=========== - -The XML mapping driver enables you to provide the ORM metadata in -form of XML documents. - -The XML driver is backed by an XML Schema document that describes -the structure of a mapping document. The most recent version of the -XML Schema document is available online at -`https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd `_. -In order to point to the latest version of the document of a -particular stable release branch, just append the release number, -i.e.: doctrine-mapping-2.0.xsd The most convenient way to work with -XML mapping files is to use an IDE/editor that can provide -code-completion based on such an XML Schema document. The following -is an outline of a XML mapping document with the proper xmlns/xsi -setup for the latest code in trunk. - -.. code-block:: xml - - - - ... - - - -The XML mapping document of a class is loaded on-demand the first -time it is requested and subsequently stored in the metadata cache. -In order to work, this requires certain conventions: - - -- Each entity/mapped superclass must get its own dedicated XML - mapping document. -- The name of the mapping document must consist of the fully - qualified name of the class, where namespace separators are - replaced by dots (.). For example an Entity with the fully - qualified class-name "MyProject" would require a mapping file - "MyProject.Entities.User.dcm.xml" unless the extension is changed. -- All mapping documents should get the extension ".dcm.xml" to - identify it as a Doctrine mapping file. This is more of a - convention and you are not forced to do this. You can change the - file extension easily enough. - -.. code-block:: php - - setFileExtension('.xml'); - -It is recommended to put all XML mapping documents in a single -folder but you can spread the documents over several folders if you -want to. In order to tell the XmlDriver where to look for your -mapping documents, supply an array of paths as the first argument -of the constructor, like this: - -.. code-block:: php - - setMetadataDriverImpl($driver); - -.. warning:: - - Note that Doctrine ORM does not modify any settings for ``libxml``, - therefore, external XML entities may or may not be enabled or - configured correctly. - XML mappings are not XXE/XEE attack vectors since they are not - related with user input, but it is recommended that you do not - use external XML entities in your mapping files to avoid running - into unexpected behaviour. - -Simplified XML Driver -~~~~~~~~~~~~~~~~~~~~~ - -The Symfony project sponsored a driver that simplifies usage of the XML Driver. -The changes between the original driver are: - -1. File Extension is .orm.xml -2. Filenames are shortened, "MyProject\Entities\User" will become User.orm.xml -3. You can add a global file and add multiple entities in this file. - -Configuration of this client works a little bit different: - -.. code-block:: php - - 'MyProject\Entities', - '/path/to/files2' => 'OtherProject\Entities' - ); - $driver = new \Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver($namespaces); - $driver->setGlobalBasename('global'); // global.orm.xml - -Example -------- - -As a quick start, here is a small example document that makes use -of several common elements: - -.. code-block:: xml - - // Doctrine.Tests.ORM.Mapping.User.dcm.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Be aware that class-names specified in the XML files should be -fully qualified. - -XML-Element Reference ---------------------- - -The XML-Element reference explains all the tags and attributes that -the Doctrine Mapping XSD Schema defines. You should read the -Basic-, Association- and Inheritance Mapping chapters to understand -what each of this definitions means in detail. - -Defining an Entity -~~~~~~~~~~~~~~~~~~ - -Each XML Mapping File contains the definition of one entity, -specified as the ```` element as a direct child of the -```` element: - -.. code-block:: xml - - - - - - - -Required attributes: - - -- name - The fully qualified class-name of the entity. - -Optional attributes: - - -- **table** - The Table-Name to be used for this entity. Otherwise the - Unqualified Class-Name is used by default. -- **repository-class** - The fully qualified class-name of an - alternative ``Doctrine\ORM\EntityRepository`` implementation to be - used with this entity. -- **inheritance-type** - The type of inheritance, defaults to none. A - more detailed description follows in the - *Defining Inheritance Mappings* section. -- **read-only** - (>= 2.1) Specifies that this entity is marked as read only and not - considered for change-tracking. Entities of this type can be persisted - and removed though. -- **schema** - (>= 2.5) The schema the table lies in, for platforms that support schemas - -Defining Fields -~~~~~~~~~~~~~~~ - -Each entity class can contain zero to infinite fields that are -managed by Doctrine. You can define them using the ```` -element as a children to the ```` element. The field -element is only used for primitive types that are not the ID of the -entity. For the ID mapping you have to use the ```` element. - -.. code-block:: xml - - - - - - - - - - - - - - - - -Required attributes: - - -- name - The name of the Property/Field on the given Entity PHP - class. - -Optional attributes: - - -- type - The ``Doctrine\DBAL\Types\Type`` name, defaults to - "string" -- column - Name of the column in the database, defaults to the - field name. -- length - The length of the given type, for use with strings - only. -- unique - Should this field contain a unique value across the - table? Defaults to false. -- nullable - Should this field allow NULL as a value? Defaults to - false. -- version - Should this field be used for optimistic locking? Only - works on fields with type integer or datetime. -- scale - Scale of a decimal type. -- precision - Precision of a decimal type. -- options - Array of additional options: - - - default - The default value to set for the column if no value - is supplied. - - unsigned - Boolean value to determine if the column should - be capable of representing only non-negative integers - (applies only for integer column and might not be supported by - all vendors). - - fixed - Boolean value to determine if the specified length of - a string column should be fixed or varying (applies only for - string/binary column and might not be supported by all vendors). - - comment - The comment of the column in the schema (might not - be supported by all vendors). - - customSchemaOptions - Array of additional schema options - which are mostly vendor specific. -- column-definition - Optional alternative SQL representation for - this column. This definition begin after the field-name and has to - specify the complete column definition. Using this feature will - turn this field dirty for Schema-Tool update commands at all - times. - -.. note:: - - For more detailed information on each attribute, please refer to - the DBAL ``Schema-Representation`` documentation. - -Defining Identity and Generator Strategies -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -An entity has to have at least one ```` element. For -composite keys you can specify more than one id-element, however -surrogate keys are recommended for use with Doctrine 2. The Id -field allows to define properties of the identifier and allows a -subset of the ```` element attributes: - -.. code-block:: xml - - - - - -Required attributes: - - -- name - The name of the Property/Field on the given Entity PHP - class. -- type - The ``Doctrine\DBAL\Types\Type`` name, preferably - "string" or "integer". - -Optional attributes: - - -- column - Name of the column in the database, defaults to the - field name. - -Using the simplified definition above Doctrine will use no -identifier strategy for this entity. That means you have to -manually set the identifier before calling -``EntityManager#persist($entity)``. This is the so called -``NONE`` strategy. - -If you want to switch the identifier generation strategy you have -to nest a ```` element inside the id-element. This of -course only works for surrogate keys. For composite keys you always -have to use the ``NONE`` strategy. - -.. code-block:: xml - - - - - - - -The following values are allowed for the ```` strategy -attribute: - - -- AUTO - Automatic detection of the identifier strategy based on - the preferred solution of the database vendor. -- IDENTITY - Use of a IDENTIFY strategy such as Auto-Increment IDs - available to Doctrine AFTER the INSERT statement has been executed. -- SEQUENCE - Use of a database sequence to retrieve the - entity-ids. This is possible before the INSERT statement is - executed. - -If you are using the SEQUENCE strategy you can define an additional -element to describe the sequence: - -.. code-block:: xml - - - - - - - - -Required attributes for ````: - - -- sequence-name - The name of the sequence - -Optional attributes for ````: - - -- allocation-size - By how much steps should the sequence be - incremented when a value is retrieved. Defaults to 1 -- initial-value - What should the initial value of the sequence - be. - - **NOTE** - - If you want to implement a cross-vendor compatible application you - have to specify and additionally define the - element, if Doctrine chooses the sequence strategy for a - platform. - - -Defining a Mapped Superclass -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Sometimes you want to define a class that multiple entities inherit -from, which itself is not an entity however. The chapter on -*Inheritance Mapping* describes a Mapped Superclass in detail. You -can define it in XML using the ```` tag. - -.. code-block:: xml - - - - - - - - -Required attributes: - - -- name - Class name of the mapped superclass. - -You can nest any number of ```` and unidirectional -```` or ```` associations inside a -mapped superclass. - -Defining Inheritance Mappings -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There are currently two inheritance persistence strategies that you -can choose from when defining entities that inherit from each -other. Single Table inheritance saves the fields of the complete -inheritance hierarchy in a single table, joined table inheritance -creates a table for each entity combining the fields using join -conditions. - -You can specify the inheritance type in the ```` element -and then use the ```` and -```` attributes. - -.. code-block:: xml - - - - - - - - - - -The allowed values for inheritance-type attribute are ``JOINED`` or -``SINGLE_TABLE``. - -.. note:: - - All inheritance related definitions have to be defined on the root - entity of the hierarchy. - - -Defining Lifecycle Callbacks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can define the lifecycle callback methods on your entities -using the ```` element: - -.. code-block:: xml - - - - - - - - -Defining One-To-One Relations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can define One-To-One Relations/Associations using the -```` element. The required and optional attributes -depend on the associations being on the inverse or owning side. - -For the inverse side the mapping is as simple as: - -.. code-block:: xml - - - - - -Required attributes for inverse One-To-One: - - -- field - Name of the property/field on the entity's PHP class. -- target-entity - Name of the entity associated entity class. If - this is not qualified the namespace of the current class is - prepended. *IMPORTANT:* No leading backslash! -- mapped-by - Name of the field on the owning side (here Address - entity) that contains the owning side association. - -For the owning side this mapping would look like: - -.. code-block:: xml - - - - - -Required attributes for owning One-to-One: - - -- field - Name of the property/field on the entity's PHP class. -- target-entity - Name of the entity associated entity class. If - this is not qualified the namespace of the current class is - prepended. *IMPORTANT:* No leading backslash! - -Optional attributes for owning One-to-One: - - -- inversed-by - If the association is bidirectional the - inversed-by attribute has to be specified with the name of the - field on the inverse entity that contains the back-reference. -- orphan-removal - If true, the inverse side entity is always - deleted when the owning side entity is. Defaults to false. -- fetch - Either LAZY or EAGER, defaults to LAZY. This attribute - makes only sense on the owning side, the inverse side *ALWAYS* has - to use the ``FETCH`` strategy. - -The definition for the owning side relies on a bunch of mapping -defaults for the join column names. Without the nested -```` element Doctrine assumes to foreign key to be -called ``user_id`` on the Address Entities table. This is because -the ``MyProject\Address`` entity is the owning side of this -association, which means it contains the foreign key. - -The completed explicitly defined mapping is: - -.. code-block:: xml - - - - - - - -Defining Many-To-One Associations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The many-to-one association is *ALWAYS* the owning side of any -bidirectional association. This simplifies the mapping compared to -the one-to-one case. The minimal mapping for this association looks -like: - -.. code-block:: xml - - - - - -Required attributes: - - -- field - Name of the property/field on the entity's PHP class. -- target-entity - Name of the entity associated entity class. If - this is not qualified the namespace of the current class is - prepended. *IMPORTANT:* No leading backslash! - -Optional attributes: - - -- inversed-by - If the association is bidirectional the - inversed-by attribute has to be specified with the name of the - field on the inverse entity that contains the back-reference. -- orphan-removal - If true the entity on the inverse side is - always deleted when the owning side entity is and it is not - connected to any other owning side entity anymore. Defaults to - false. -- fetch - Either LAZY or EAGER, defaults to LAZY. - -This definition relies on a bunch of mapping defaults with regards -to the naming of the join-column/foreign key. The explicitly -defined mapping includes a ```` tag nested inside -the many-to-one association tag: - -.. code-block:: xml - - - - - - - -The join-column attribute ``name`` specifies the column name of the -foreign key and the ``referenced-column-name`` attribute specifies -the name of the primary key column on the User entity. - -Defining One-To-Many Associations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The one-to-many association is *ALWAYS* the inverse side of any -association. There exists no such thing as a uni-directional -one-to-many association, which means this association only ever -exists for bi-directional associations. - -.. code-block:: xml - - - - - -Required attributes: - - -- field - Name of the property/field on the entity's PHP class. -- target-entity - Name of the entity associated entity class. If - this is not qualified the namespace of the current class is - prepended. *IMPORTANT:* No leading backslash! -- mapped-by - Name of the field on the owning side (here - Phonenumber entity) that contains the owning side association. - -Optional attributes: - - -- fetch - Either LAZY, EXTRA_LAZY or EAGER, defaults to LAZY. -- index-by: Index the collection by a field on the target entity. - -Defining Many-To-Many Associations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -From all the associations the many-to-many has the most complex -definition. When you rely on the mapping defaults you can omit many -definitions and rely on their implicit values. - -.. code-block:: xml - - - - - -Required attributes: - - -- field - Name of the property/field on the entity's PHP class. -- target-entity - Name of the entity associated entity class. If - this is not qualified the namespace of the current class is - prepended. *IMPORTANT:* No leading backslash! - -Optional attributes: - - -- mapped-by - Name of the field on the owning side that contains - the owning side association if the defined many-to-many association - is on the inverse side. -- inversed-by - If the association is bidirectional the - inversed-by attribute has to be specified with the name of the - field on the inverse entity that contains the back-reference. -- fetch - Either LAZY, EXTRA_LAZY or EAGER, defaults to LAZY. -- index-by: Index the collection by a field on the target entity. - -The mapping defaults would lead to a join-table with the name -"User\_Group" being created that contains two columns "user\_id" -and "group\_id". The explicit definition of this mapping would be: - -.. code-block:: xml - - - - - - - - - - - - - - -Here both the ```` and ```` -tags are necessary to tell Doctrine for which side the specified -join-columns apply. These are nested inside a ```` -attribute which allows to specify the table name of the -many-to-many join-table. - -Cascade Element -~~~~~~~~~~~~~~~ - -Doctrine allows cascading of several UnitOfWork operations to -related entities. You can specify the cascade operations in the -```` element inside any of the association mapping -tags. - -.. code-block:: xml - - - - - - - - - -Besides ```` the following operations can be -specified by their respective tags: - - -- ```` -- ```` -- ```` -- ```` - -Join Column Element -~~~~~~~~~~~~~~~~~~~ - -In any explicitly defined association mapping you will need the -```` tag. It defines how the foreign key and primary -key names are called that are used for joining two entities. - -Required attributes: - - -- name - The column name of the foreign key. -- referenced-column-name - The column name of the associated - entities primary key - -Optional attributes: - - -- unique - If the join column should contain a UNIQUE constraint. - This makes sense for Many-To-Many join-columns only to simulate a - one-to-many unidirectional using a join-table. -- nullable - should the join column be nullable, defaults to true. -- on-delete - Foreign Key Cascade action to perform when entity is - deleted, defaults to NO ACTION/RESTRICT but can be set to - "CASCADE". - -Defining Order of To-Many Associations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can require one-to-many or many-to-many associations to be -retrieved using an additional ``ORDER BY``. - -.. code-block:: xml - - - - - - - - - -Defining Indexes or Unique Constraints -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To define additional indexes or unique constraints on the entities -table you can use the ```` and -```` elements: - -.. code-block:: xml - - - - - - - - - - - - - -You have to specify the column and not the entity-class field names -in the index and unique-constraint definitions. - -Derived Entities ID syntax -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If the primary key of an entity contains a foreign key to another entity we speak of a derived -entity relationship. You can define this in XML with the "association-key" attribute in the ```` tag. - -.. code-block:: xml - - - - - - - - - - - - - diff --git a/vendor/doctrine/orm/docs/en/reference/yaml-mapping.rst b/vendor/doctrine/orm/docs/en/reference/yaml-mapping.rst deleted file mode 100644 index 8199406..0000000 --- a/vendor/doctrine/orm/docs/en/reference/yaml-mapping.rst +++ /dev/null @@ -1,158 +0,0 @@ -YAML Mapping -============ - -.. note:: - The YAML driver is deprecated and will be removed in version 3.0. - It is strongly recommended to switch to one of the other mappings. - -The YAML mapping driver enables you to provide the ORM metadata in -form of YAML documents. - -The YAML mapping document of a class is loaded on-demand the first -time it is requested and subsequently stored in the metadata cache. -In order to work, this requires certain conventions: - - -- Each entity/mapped superclass must get its own dedicated YAML - mapping document. -- The name of the mapping document must consist of the fully - qualified name of the class, where namespace separators are - replaced by dots (.). -- All mapping documents should get the extension ".dcm.yml" to - identify it as a Doctrine mapping file. This is more of a - convention and you are not forced to do this. You can change the - file extension easily enough. - -.. code-block:: php - - setFileExtension('.yml'); - -It is recommended to put all YAML mapping documents in a single -folder but you can spread the documents over several folders if you -want to. In order to tell the YamlDriver where to look for your -mapping documents, supply an array of paths as the first argument -of the constructor, like this: - -.. code-block:: php - - setMetadataDriverImpl($driver); - -Simplified YAML Driver -~~~~~~~~~~~~~~~~~~~~~~ - -The Symfony project sponsored a driver that simplifies usage of the YAML Driver. -The changes between the original driver are: - -- File Extension is .orm.yml -- Filenames are shortened, "MyProject\\Entities\\User" will become User.orm.yml -- You can add a global file and add multiple entities in this file. - -Configuration of this client works a little bit different: - -.. code-block:: php - - 'MyProject\Entities', - '/path/to/files2' => 'OtherProject\Entities' - ); - $driver = new \Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver($namespaces); - $driver->setGlobalBasename('global'); // global.orm.yml - -Example -------- - -As a quick start, here is a small example document that makes use -of several common elements: - -.. code-block:: yaml - - # Doctrine.Tests.ORM.Mapping.User.dcm.yml - Doctrine\Tests\ORM\Mapping\User: - type: entity - repositoryClass: Doctrine\Tests\ORM\Mapping\UserRepository - table: cms_users - schema: schema_name # The schema the table lies in, for platforms that support schemas (Optional, >= 2.5) - readOnly: true - indexes: - name_index: - columns: [ name ] - id: - id: - type: integer - generator: - strategy: AUTO - fields: - name: - type: string - length: 50 - email: - type: string - length: 32 - column: user_email - unique: true - options: - fixed: true - comment: User's email address - loginCount: - type: integer - column: login_count - nullable: false - options: - unsigned: true - default: 0 - oneToOne: - address: - targetEntity: Address - joinColumn: - name: address_id - referencedColumnName: id - onDelete: CASCADE - oneToMany: - phonenumbers: - targetEntity: Phonenumber - mappedBy: user - cascade: ["persist", "merge"] - manyToMany: - groups: - targetEntity: Group - joinTable: - name: cms_users_groups - joinColumns: - user_id: - referencedColumnName: id - inverseJoinColumns: - group_id: - referencedColumnName: id - lifecycleCallbacks: - prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ] - postPersist: [ doStuffOnPostPersist ] - -Be aware that class-names specified in the YAML files should be -fully qualified. - -Reference -~~~~~~~~~~~~~~~~~~~~~~ - -Unique Constraints ------------------- - -It is possible to define unique constraints by the following declaration: - -.. code-block:: yaml - - # ECommerceProduct.orm.yml - ECommerceProduct: - type: entity - fields: - # definition of some fields - uniqueConstraints: - search_idx: - columns: [ name, email ] - diff --git a/vendor/doctrine/orm/docs/en/sidebar.rst b/vendor/doctrine/orm/docs/en/sidebar.rst deleted file mode 100644 index 03d130c..0000000 --- a/vendor/doctrine/orm/docs/en/sidebar.rst +++ /dev/null @@ -1,83 +0,0 @@ -.. toc:: - - .. tocheader:: Tutorials - - .. toctree:: - :depth: 3 - - tutorials/getting-started - tutorials/getting-started-database - tutorials/getting-started-models - tutorials/working-with-indexed-associations - tutorials/extra-lazy-associations - tutorials/composite-primary-keys - tutorials/ordered-associations - tutorials/override-field-association-mappings-in-subclasses - tutorials/pagination - tutorials/embeddables - -.. toc:: - - .. tocheader:: Reference - - .. toctree:: - :depth: 3 - - reference/architecture - reference/configuration - reference/faq - reference/basic-mapping - reference/association-mapping - reference/inheritance-mapping - reference/working-with-objects - reference/working-with-associations - reference/events - reference/unitofwork - reference/unitofwork-associations - reference/transactions-and-concurrency - reference/batch-processing - reference/dql-doctrine-query-language - reference/query-builder - reference/native-sql - reference/change-tracking-policies - reference/partial-objects - reference/xml-mapping - reference/yaml-mapping - reference/annotations-reference - reference/php-mapping - reference/caching - reference/improving-performance - reference/tools - reference/metadata-drivers - reference/best-practices - reference/limitations-and-known-issues - tutorials/pagination - reference/filters - reference/namingstrategy - reference/advanced-configuration - reference/second-level-cache - reference/security - -.. toc:: - - .. tocheader:: Cookbook - - .. toctree:: - :depth: 3 - - cookbook/aggregate-fields - cookbook/custom-mapping-types - cookbook/decorator-pattern - cookbook/dql-custom-walkers - cookbook/dql-user-defined-functions - cookbook/implementing-arrayaccess-for-domain-objects - cookbook/implementing-the-notify-changetracking-policy - cookbook/implementing-wakeup-or-clone - cookbook/resolve-target-entity-listener - cookbook/sql-table-prefixes - cookbook/strategy-cookbook-introduction - cookbook/validation-of-entities - cookbook/working-with-datetime - cookbook/mysql-enums - cookbook/advanced-field-value-conversion-using-custom-mapping-types - cookbook/entities-in-session diff --git a/vendor/doctrine/orm/docs/en/toc.rst b/vendor/doctrine/orm/docs/en/toc.rst deleted file mode 100644 index 2309d56..0000000 --- a/vendor/doctrine/orm/docs/en/toc.rst +++ /dev/null @@ -1,86 +0,0 @@ -Welcome to Doctrine 2 ORM's documentation! -========================================== - -Tutorials ---------- - -.. toctree:: - :maxdepth: 1 - - tutorials/getting-started - tutorials/getting-started-database - tutorials/getting-started-models - tutorials/working-with-indexed-associations - tutorials/extra-lazy-associations - tutorials/composite-primary-keys - tutorials/ordered-associations - tutorials/override-field-association-mappings-in-subclasses - tutorials/pagination.rst - tutorials/embeddables.rst - -Reference Guide ---------------- - -.. toctree:: - :maxdepth: 1 - :numbered: - - reference/architecture - reference/configuration.rst - reference/faq - reference/basic-mapping - reference/association-mapping - reference/inheritance-mapping - reference/working-with-objects - reference/working-with-associations - reference/events - reference/unitofwork - reference/unitofwork-associations - reference/transactions-and-concurrency - reference/batch-processing - reference/dql-doctrine-query-language - reference/query-builder - reference/native-sql - reference/change-tracking-policies - reference/partial-objects - reference/xml-mapping - reference/yaml-mapping - reference/annotations-reference - reference/php-mapping - reference/caching - reference/improving-performance - reference/tools - reference/metadata-drivers - reference/best-practices - reference/limitations-and-known-issues - tutorials/pagination - reference/filters - reference/namingstrategy - reference/advanced-configuration - reference/second-level-cache - reference/security - - -Cookbook --------- - -.. toctree:: - :maxdepth: 1 - - cookbook/aggregate-fields - cookbook/custom-mapping-types - cookbook/decorator-pattern - cookbook/dql-custom-walkers - cookbook/dql-user-defined-functions - cookbook/implementing-arrayaccess-for-domain-objects - cookbook/implementing-the-notify-changetracking-policy - cookbook/implementing-wakeup-or-clone - cookbook/resolve-target-entity-listener - cookbook/sql-table-prefixes - cookbook/strategy-cookbook-introduction - cookbook/validation-of-entities - cookbook/working-with-datetime - cookbook/mysql-enums - cookbook/advanced-field-value-conversion-using-custom-mapping-types - cookbook/entities-in-session - diff --git a/vendor/doctrine/orm/docs/en/tutorials/composite-primary-keys.rst b/vendor/doctrine/orm/docs/en/tutorials/composite-primary-keys.rst deleted file mode 100644 index ef164c9..0000000 --- a/vendor/doctrine/orm/docs/en/tutorials/composite-primary-keys.rst +++ /dev/null @@ -1,375 +0,0 @@ -Composite and Foreign Keys as Primary Key -========================================= - -.. versionadded:: 2.1 - -Doctrine 2 supports composite primary keys natively. Composite keys are a very powerful relational database concept -and we took good care to make sure Doctrine 2 supports as many of the composite primary key use-cases. -For Doctrine 2.0 composite keys of primitive data-types are supported, for Doctrine 2.1 even foreign keys as -primary keys are supported. - -This tutorial shows how the semantics of composite primary keys work and how they map to the database. - -General Considerations -~~~~~~~~~~~~~~~~~~~~~~ - -Every entity with a composite key cannot use an id generator other than "NONE". That means -the ID fields have to have their values set before you call ``EntityManager#persist($entity)``. - -Primitive Types only -~~~~~~~~~~~~~~~~~~~~ - -Even in version 2.0 you can have composite keys as long as they only consist of the primitive types -``integer`` and ``string``. Suppose you want to create a database of cars and use the model-name -and year of production as primary keys: - -.. configuration-block:: - - .. code-block:: php - - name = $name; - $this->year = $year; - } - - public function getModelName() - { - return $this->name; - } - - public function getYearOfProduction() - { - return $this->year; - } - } - - .. code-block:: xml - - - - - - - - - - - .. code-block:: yaml - - VehicleCatalogue\Model\Car: - type: entity - id: - name: - type: string - year: - type: integer - -Now you can use this entity: - -.. code-block:: php - - persist($car); - $em->flush(); - -And for querying you can use arrays to both DQL and EntityRepositories: - -.. code-block:: php - - find("VehicleCatalogue\Model\Car", array("name" => "Audi A8", "year" => 2010)); - - $dql = "SELECT c FROM VehicleCatalogue\Model\Car c WHERE c.id = ?1"; - $audi = $em->createQuery($dql) - ->setParameter(1, array("name" => "Audi A8", "year" => 2010)) - ->getSingleResult(); - -You can also use this entity in associations. Doctrine will then generate two foreign keys one for ``name`` -and to ``year`` to the related entities. - -.. note:: - - This example shows how you can nicely solve the requirement for existing - values before ``EntityManager#persist()``: By adding them as mandatory values for the constructor. - -Identity through foreign Entities -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. note:: - - Identity through foreign entities is only supported with Doctrine 2.1 - -There are tons of use-cases where the identity of an Entity should be determined by the entity -of one or many parent entities. - -- Dynamic Attributes of an Entity (for example Article). Each Article has many - attributes with primary key "article_id" and "attribute_name". -- Address object of a Person, the primary key of the address is "user_id". This is not a case of a composite primary - key, but the identity is derived through a foreign entity and a foreign key. -- Join Tables with metadata can be modelled as Entity, for example connections between two articles - with a little description and a score. - -The semantics of mapping identity through foreign entities are easy: - -- Only allowed on Many-To-One or One-To-One associations. -- Plug an ``@Id`` annotation onto every association. -- Set an attribute ``association-key`` with the field name of the association in XML. -- Set a key ``associationKey:`` with the field name of the association in YAML. - -Use-Case 1: Dynamic Attributes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -We keep up the example of an Article with arbitrary attributes, the mapping looks like this: - -.. configuration-block:: - - .. code-block:: php - - attributes[$name] = new ArticleAttribute($name, $value, $this); - } - } - - /** - * @Entity - */ - class ArticleAttribute - { - /** @Id @ManyToOne(targetEntity="Article", inversedBy="attributes") */ - private $article; - - /** @Id @Column(type="string") */ - private $attribute; - - /** @Column(type="string") */ - private $value; - - public function __construct($name, $value, $article) - { - $this->attribute = $name; - $this->value = $value; - $this->article = $article; - } - } - - .. code-block:: xml - - - - - - - - - - - - - - - .. code-block:: yaml - - Application\Model\ArticleAttribute: - type: entity - id: - article: - associationKey: true - attribute: - type: string - fields: - value: - type: string - manyToOne: - article: - targetEntity: Article - inversedBy: attributes - - -Use-Case 2: Simple Derived Identity -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Sometimes you have the requirement that two objects are related by a One-To-One association -and that the dependent class should re-use the primary key of the class it depends on. -One good example for this is a user-address relationship: - -.. configuration-block:: - - .. code-block:: php - - customer = $customer; - $this->items = new ArrayCollection(); - $this->created = new \DateTime("now"); - } - } - - /** @Entity */ - class Product - { - /** @Id @Column(type="integer") @GeneratedValue */ - private $id; - - /** @Column(type="string") */ - private $name; - - /** @Column(type="decimal") */ - private $currentPrice; - - public function getCurrentPrice() - { - return $this->currentPrice; - } - } - - /** @Entity */ - class OrderItem - { - /** @Id @ManyToOne(targetEntity="Order") */ - private $order; - - /** @Id @ManyToOne(targetEntity="Product") */ - private $product; - - /** @Column(type="integer") */ - private $amount = 1; - - /** @Column(type="decimal") */ - private $offeredPrice; - - public function __construct(Order $order, Product $product, $amount = 1) - { - $this->order = $order; - $this->product = $product; - $this->offeredPrice = $product->getCurrentPrice(); - } - } - - -Performance Considerations -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Using composite keys always comes with a performance hit compared to using entities with -a simple surrogate key. This performance impact is mostly due to additional PHP code that is -necessary to handle this kind of keys, most notably when using derived identifiers. - -On the SQL side there is not much overhead as no additional or unexpected queries have to be -executed to manage entities with derived foreign keys. diff --git a/vendor/doctrine/orm/docs/en/tutorials/embeddables.rst b/vendor/doctrine/orm/docs/en/tutorials/embeddables.rst deleted file mode 100644 index 483e58d..0000000 --- a/vendor/doctrine/orm/docs/en/tutorials/embeddables.rst +++ /dev/null @@ -1,179 +0,0 @@ -Separating Concerns using Embeddables -------------------------------------- - -Embeddables are classes which are not entities themselves, but are embedded -in entities and can also be queried in DQL. You'll mostly want to use them -to reduce duplication or separating concerns. Value objects such as date range -or address are the primary use case for this feature. - -.. note:: - - Embeddables can only contain properties with basic ``@Column`` mapping. - -For the purposes of this tutorial, we will assume that you have a ``User`` -class in your application and you would like to store an address in -the ``User`` class. We will model the ``Address`` class as an embeddable -instead of simply adding the respective columns to the ``User`` class. - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - - - - - - .. code-block:: yaml - - User: - type: entity - embedded: - address: - class: Address - - Address: - type: embeddable - fields: - street: { type: string } - postalCode: { type: string } - city: { type: string } - country: { type: string } - -In terms of your database schema, Doctrine will automatically inline all -columns from the ``Address`` class into the table of the ``User`` class, -just as if you had declared them directly there. - -Initializing embeddables ------------------------- - -In case all fields in the embeddable are ``nullable``, you might want -to initialize the embeddable, to avoid getting a null value instead of -the embedded object. - -.. code-block:: php - - public function __construct() - { - $this->address = new Address(); - } - -Column Prefixing ----------------- - -By default, Doctrine names your columns by prefixing them, using the value -object name. - -Following the example above, your columns would be named as ``address_street``, -``address_postalCode``... - -You can change this behaviour to meet your needs by changing the -``columnPrefix`` attribute in the ``@Embedded`` notation. - -The following example shows you how to set your prefix to ``myPrefix_``: - -.. configuration-block:: - - .. code-block:: php - - - - - - .. code-block:: yaml - - User: - type: entity - embedded: - address: - class: Address - columnPrefix: myPrefix_ - -To have Doctrine drop the prefix and use the value object's property name -directly, set ``columnPrefix=false`` (``use-column-prefix="false"`` for XML): - -.. configuration-block:: - - .. code-block:: php - - - - - - -DQL ---- - -You can also use mapped fields of embedded classes in DQL queries, just -as if they were declared in the ``User`` class: - -.. code-block:: sql - - SELECT u FROM User u WHERE u.address.city = :myCity - diff --git a/vendor/doctrine/orm/docs/en/tutorials/extra-lazy-associations.rst b/vendor/doctrine/orm/docs/en/tutorials/extra-lazy-associations.rst deleted file mode 100644 index 4452d68..0000000 --- a/vendor/doctrine/orm/docs/en/tutorials/extra-lazy-associations.rst +++ /dev/null @@ -1,86 +0,0 @@ -Extra Lazy Associations -======================= - -.. versionadded:: 2.1 - -In many cases associations between entities can get pretty large. Even in a simple scenario like a blog. -where posts can be commented, you always have to assume that a post draws hundreds of comments. -In Doctrine 2.0 if you accessed an association it would always get loaded completely into memory. This -can lead to pretty serious performance problems, if your associations contain several hundreds or thousands -of entities. - -With Doctrine 2.1 a feature called **Extra Lazy** is introduced for associations. Associations -are marked as **Lazy** by default, which means the whole collection object for an association is populated -the first time its accessed. If you mark an association as extra lazy the following methods on collections -can be called without triggering a full load of the collection: - -- ``Collection#contains($entity)`` -- ``Collection#containsKey($key)`` (available with Doctrine 2.5) -- ``Collection#count()`` -- ``Collection#get($key)`` (available with Doctrine 2.4) -- ``Collection#slice($offset, $length = null)`` - -For each of the above methods the following semantics apply: - -- For each call, if the Collection is not yet loaded, issue a straight SELECT statement against the database. -- For each call, if the collection is already loaded, fallback to the default functionality for lazy collections. No additional SELECT statements are executed. - -Additionally even with Doctrine 2.0 the following methods do not trigger the collection load: - -- ``Collection#add($entity)`` -- ``Collection#offsetSet($key, $entity)`` - ArrayAccess with no specific key ``$coll[] = $entity``, it does - not work when setting specific keys like ``$coll[0] = $entity``. - -With extra lazy collections you can now not only add entities to large collections but also paginate them -easily using a combination of ``count`` and ``slice``. - - -Enabling Extra-Lazy Associations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The mapping configuration is simple. Instead of using the default value of ``fetch="LAZY"`` you have to -switch to extra lazy as shown in these examples: - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - - .. code-block:: yaml - - Doctrine\Tests\Models\CMS\CmsGroup: - type: entity - # ... - manyToMany: - users: - targetEntity: CmsUser - mappedBy: groups - fetch: EXTRA_LAZY - diff --git a/vendor/doctrine/orm/docs/en/tutorials/getting-started-database.rst b/vendor/doctrine/orm/docs/en/tutorials/getting-started-database.rst deleted file mode 100644 index 5a4883f..0000000 --- a/vendor/doctrine/orm/docs/en/tutorials/getting-started-database.rst +++ /dev/null @@ -1,27 +0,0 @@ -Getting Started: Database First -=============================== - -.. note:: *Development Workflows* - - When you :doc:`Code First `, you - start with developing Objects and then map them onto your database. When - you :doc:`Model First `, you are modelling your application using tools (for - example UML) and generate database schema and PHP code from this model. - When you have a Database First, you already have a database schema - and generate the corresponding PHP code from it. - -.. note:: - - This getting started guide is in development. - -Development of new applications often starts with an existing database schema. -When the database schema is the starting point for your application, then -development is said to use the *Database First* approach to Doctrine. - -In this workflow you would modify the database schema first and then -regenerate the PHP code to use with this schema. You need a flexible -code-generator for this task and up to Doctrine 2.2, the code generator hasn't -been flexible enough to achieve this. - -We spinned off a subproject, Doctrine CodeGenerator, that will fill this gap and -allow you to do *Database First* development. diff --git a/vendor/doctrine/orm/docs/en/tutorials/getting-started-models.rst b/vendor/doctrine/orm/docs/en/tutorials/getting-started-models.rst deleted file mode 100644 index 01b7187..0000000 --- a/vendor/doctrine/orm/docs/en/tutorials/getting-started-models.rst +++ /dev/null @@ -1,24 +0,0 @@ -Getting Started: Model First -============================ - -.. note:: *Development Workflows* - - When you :doc:`Code First `, you - start with developing Objects and then map them onto your database. When - you Model First, you are modelling your application using tools (for - example UML) and generate database schema and PHP code from this model. - When you have a :doc:`Database First `, then you already have a database schema - and generate the corresponding PHP code from it. - -.. note:: - - This getting started guide is in development. - -There are applications when you start with a high-level description of the -model using modelling tools such as UML. Modelling tools could also be Excel, -XML or CSV files that describe the model in some structured way. If your -application is using a modelling tool, then the development workflow is said to -be a *Model First* approach to Doctrine2. - -In this workflow you always change the model description and then regenerate -both PHP code and database schema from this model. diff --git a/vendor/doctrine/orm/docs/en/tutorials/getting-started.rst b/vendor/doctrine/orm/docs/en/tutorials/getting-started.rst deleted file mode 100644 index 52190e5..0000000 --- a/vendor/doctrine/orm/docs/en/tutorials/getting-started.rst +++ /dev/null @@ -1,1618 +0,0 @@ -Getting Started with Doctrine -============================= - -This guide covers getting started with the Doctrine ORM. After working -through the guide you should know: - -- How to install and configure Doctrine by connecting it to a database -- Mapping PHP objects to database tables -- Generating a database schema from PHP objects -- Using the ``EntityManager`` to insert, update, delete and find - objects in the database. - -Guide Assumptions ------------------ - -This guide is designed for beginners that haven't worked with Doctrine ORM -before. There are some prerequisites for the tutorial that have to be -installed: - -- PHP (latest stable version) -- Composer Package Manager (`Install Composer - `_) - -The code of this tutorial is `available on Github `_. - -.. note:: - - This tutorial assumes you work with **Doctrine 2.6** and above. - Some of the code will not work with lower versions. - -What is Doctrine? ------------------ - -Doctrine 2 is an `object-relational mapper (ORM) `_ -for PHP 7.1+ that provides transparent persistence for PHP objects. It uses the Data Mapper -pattern at the heart, aiming for a complete separation of your domain/business -logic from the persistence in a relational database management system. - -The benefit of Doctrine for the programmer is the ability to focus -on the object-oriented business logic and worry about persistence only -as a secondary problem. This doesn't mean persistence is downplayed by Doctrine -2, however it is our belief that there are considerable benefits for -object-oriented programming if persistence and entities are kept -separated. - -What are Entities? -~~~~~~~~~~~~~~~~~~ - -Entities are PHP Objects that can be identified over many requests -by a unique identifier or primary key. These classes don't need to extend any -abstract base class or interface. An entity class must not be final -or contain final methods. Additionally it must not implement -**clone** nor **wakeup**, unless it :doc:`does so safely <../cookbook/implementing-wakeup-or-clone>`. - -An entity contains persistable properties. A persistable property -is an instance variable of the entity that is saved into and retrieved from the database -by Doctrine's data mapping capabilities. - -An Example Model: Bug Tracker ------------------------------ - -For this Getting Started Guide for Doctrine we will implement the -Bug Tracker domain model from the -`Zend_Db_Table `_ -documentation. Reading their documentation we can extract the -requirements: - -- A Bug has a description, creation date, status, reporter and - engineer -- A Bug can occur on different Products (platforms) -- A Product has a name. -- Bug reporters and engineers are both Users of the system. -- A User can create new Bugs. -- The assigned engineer can close a Bug. -- A User can see all his reported or assigned Bugs. -- Bugs can be paginated through a list-view. - -Project Setup -------------- - -Create a new empty folder for this tutorial project, for example -``doctrine2-tutorial`` and create a new file ``composer.json`` inside -that directory with the following contents: - -:: - - { - "require": { - "doctrine/orm": "^2.6.2", - "symfony/yaml": "2.*" - }, - "autoload": { - "psr-0": {"": "src/"} - } - } - - -Install Doctrine using the Composer Dependency Management tool, by calling: - -:: - - $ composer install - -This will install the packages Doctrine Common, Doctrine DBAL, Doctrine ORM, -into the ``vendor`` directory. - -Add the following directories: -:: - - doctrine2-tutorial - |-- config - | `-- xml - | `-- yaml - `-- src - -.. note:: - The YAML driver is deprecated and will be removed in version 3.0. - It is strongly recommended to switch to one of the other mappings. - -Obtaining the EntityManager ---------------------------- - -Doctrine's public interface is through the ``EntityManager``. This class -provides access points to the complete lifecycle management for your entities, -and transforms entities from and back to persistence. You have to -configure and create it to use your entities with Doctrine 2. I -will show the configuration steps and then discuss them step by -step: - -.. code-block:: php - - 'pdo_sqlite', - 'path' => __DIR__ . '/db.sqlite', - ); - - // obtaining the entity manager - $entityManager = EntityManager::create($conn, $config); - -.. note:: - The YAML driver is deprecated and will be removed in version 3.0. - It is strongly recommended to switch to one of the other mappings. - -.. note:: - It is recommended not to use the SimpleAnnotationReader because its - usage will be removed for version 3.0. - -The ``require_once`` statement sets up the class autoloading for Doctrine and -its dependencies using Composer's autoloader. - -The second block consists of the instantiation of the ORM -``Configuration`` object using the Setup helper. It assumes a bunch -of defaults that you don't have to bother about for now. You can -read up on the configuration details in the -:doc:`reference chapter on configuration <../reference/configuration>`. - -The third block shows the configuration options required to connect to -a database. In this case, we'll use a file-based SQLite database. All the -configuration options for all the shipped drivers are given in the -`DBAL Configuration section of the manual `_. - -The last block shows how the ``EntityManager`` is obtained from a -factory method. - -Generating the Database Schema ------------------------------- - -Doctrine has a command-line interface that allows you to access the SchemaTool, -a component that can generate a relational database schema based entirely on the -defined entity classes and their metadata. For this tool to work, a -``cli-config.php`` file must exist in the project root directory: - -.. code-block:: php - - id; - } - - public function getName() - { - return $this->name; - } - - public function setName($name) - { - $this->name = $name; - } - } - -When creating entity classes, all of the fields should be ``protected`` or ``private`` -(not ``public``), with getter and setter methods for each one (except ``$id``). -The use of mutators allows Doctrine to hook into calls which -manipulate the entities in ways that it could not if you just -directly set the values with ``entity#field = foo;`` - -The id field has no setter since, generally speaking, your code -should not set this value since it represents a database id value. -(Note that Doctrine itself can still set the value using the -Reflection API instead of a defined setter function.) - -The next step for persistence with Doctrine is to describe the -structure of the ``Product`` entity to Doctrine using a metadata -language. The metadata language describes how entities, their -properties and references should be persisted and what constraints -should be applied to them. - -Metadata for an Entity can be configured using DocBlock annotations directly -in the Entity class itself, or in an external XML or YAML file. This Getting -Started guide will demonstrate metadata mappings using all three methods, -but you only need to choose one. - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - - - - -.. note:: - The YAML driver is deprecated and will be removed in version 3.0. - It is strongly recommended to switch to one of the other mappings. - - .. code-block:: yaml - - # config/yaml/Product.dcm.yml - Product: - type: entity - table: products - id: - id: - type: integer - generator: - strategy: AUTO - fields: - name: - type: string - -The top-level ``entity`` definition specifies information about -the class and table name. The primitive type ``Product#name`` is -defined as a ``field`` attribute. The ``id`` property is defined with -the ``id`` tag. It has a ``generator`` tag nested inside, which -specifies that the primary key generation mechanism should automatically -use the database platform's native id generation strategy (for -example, AUTO INCREMENT in the case of MySql, or Sequences in the -case of PostgreSql and Oracle). - -Now that we have defined our first entity and its metadata, -let's update the database schema: - -:: - - $ vendor/bin/doctrine orm:schema-tool:update --force --dump-sql - -Specifying both flags ``--force`` and ``--dump-sql`` will cause the DDL -statements to be executed and then printed to the screen. - -Now, we'll create a new script to insert products into the database: - -.. code-block:: php - - - require_once "bootstrap.php"; - - $newProductName = $argv[1]; - - $product = new Product(); - $product->setName($newProductName); - - $entityManager->persist($product); - $entityManager->flush(); - - echo "Created Product with ID " . $product->getId() . "\n"; - -Call this script from the command-line to see how new products are created: - -:: - - $ php create_product.php ORM - $ php create_product.php DBAL - -What is happening here? Using the ``Product`` class is pretty standard OOP. -The interesting bits are the use of the ``EntityManager`` service. To -notify the EntityManager that a new entity should be inserted into the database, -you have to call ``persist()``. To initiate a transaction to actually *perform* -the insertion, you have to explicitly call ``flush()`` on the ``EntityManager``. - -This distinction between persist and flush is what allows the aggregation of -all database writes (INSERT, UPDATE, DELETE) into one single transaction, which -is executed when ``flush()`` is called. Using this approach, the write-performance -is significantly better than in a scenario in which writes are performed on -each entity in isolation. - -Next, we'll fetch a list of all the Products in the database. Let's create a -new script for this: - -.. code-block:: php - - getRepository('Product'); - $products = $productRepository->findAll(); - - foreach ($products as $product) { - echo sprintf("-%s\n", $product->getName()); - } - -The ``EntityManager#getRepository()`` method can create a finder object (called -a repository) for every type of entity. It is provided by Doctrine and contains -some finder methods like ``findAll()``. - -Let's continue by creating a script to display the name of a product based on its ID: - -.. code-block:: php - - - require_once "bootstrap.php"; - - $id = $argv[1]; - $product = $entityManager->find('Product', $id); - - if ($product === null) { - echo "No product found.\n"; - exit(1); - } - - echo sprintf("-%s\n", $product->getName()); - -Next we'll update a product's name, given its id. This simple example will -help demonstrate Doctrine's implementation of the UnitOfWork pattern. Doctrine -keeps track of all the entities that were retrieved from the Entity Manager, -and can detect when any of those entities' properties have been modified. -As a result, rather than needing to call ``persist($entity)`` for each individual -entity whose properties were changed, a single call to ``flush()`` at the end of a -request is sufficient to update the database for all of the modified entities. - -.. code-block:: php - - - require_once "bootstrap.php"; - - $id = $argv[1]; - $newName = $argv[2]; - - $product = $entityManager->find('Product', $id); - - if ($product === null) { - echo "Product $id does not exist.\n"; - exit(1); - } - - $product->setName($newName); - - $entityManager->flush(); - -After calling this script on one of the existing products, you can verify the -product name changed by calling the ``show_product.php`` script. - -Adding Bug and User Entities ----------------------------- - -We continue with the bug tracker example by creating the ``Bug`` and ``User`` -classes. We'll store them in ``src/Bug.php`` and ``src/User.php``, respectively. - -.. code-block:: php - - id; - } - - public function getDescription() - { - return $this->description; - } - - public function setDescription($description) - { - $this->description = $description; - } - - public function setCreated(DateTime $created) - { - $this->created = $created; - } - - public function getCreated() - { - return $this->created; - } - - public function setStatus($status) - { - $this->status = $status; - } - - public function getStatus() - { - return $this->status; - } - } - -.. code-block:: php - - id; - } - - public function getName() - { - return $this->name; - } - - public function setName($name) - { - $this->name = $name; - } - } - -All of the properties we've seen so far are of simple types (integer, string, -and datetime). But now, we'll add properties that will store objects of -specific *entity types* in order to model the relationships between different -entities. - -At the database level, relationships between entities are represented by foreign -keys. But with Doctrine, you'll never have to (and never should) work with -the foreign keys directly. You should only work with objects that represent -foreign keys through their own identities. - -For every foreign key you either have a Doctrine ManyToOne or OneToOne -association. On the inverse sides of these foreign keys you can have -OneToMany associations. Obviously you can have ManyToMany associations -that connect two tables with each other through a join table with -two foreign keys. - -Now that you know the basics about references in Doctrine, we can extend the -domain model to match the requirements: - -.. code-block:: php - - products = new ArrayCollection(); - } - } - -.. code-block:: php - - reportedBugs = new ArrayCollection(); - $this->assignedBugs = new ArrayCollection(); - } - } - -.. note:: - - Whenever an entity is created from the database, a ``Collection`` - implementation of the type ``PersistentCollection`` will be injected into - your entity instead of an ``ArrayCollection``. This helps Doctrine ORM - understand the changes that have happened to the collection that are - noteworthy for persistence. - -.. warning:: - - Lazy load proxies always contain an instance of - Doctrine's EntityManager and all its dependencies. Therefore a - var\_dump() will possibly dump a very large recursive structure - which is impossible to render and read. You have to use - ``Doctrine\Common\Util\Debug::dump()`` to restrict the dumping to a - human readable level. Additionally you should be aware that dumping - the EntityManager to a Browser may take several minutes, and the - Debug::dump() method just ignores any occurrences of it in Proxy - instances. - -Because we only work with collections for the references we must be -careful to implement a bidirectional reference in the domain model. -The concept of owning or inverse side of a relation is central to -this notion and should always be kept in mind. The following -assumptions are made about relations and have to be followed to be -able to work with Doctrine 2. These assumptions are not unique to -Doctrine 2 but are best practices in handling database relations -and Object-Relational Mapping. - -- In a one-to-one relation, the entity holding the foreign key of - the related entity on its own database table is *always* the owning - side of the relation. -- In a many-to-one relation, the Many-side is the owning side by - default because it holds the foreign key. Accordingly, the One-side - is the inverse side by default. -- In a many-to-one relation, the One-side can only be the owning side if - the relation is implemented as a ManyToMany with a join table, and the - One-side is restricted to allow only UNIQUE values per database constraint. -- In a many-to-many relation, both sides can be the owning side of - the relation. However, in a bi-directional many-to-many relation, - only one side is allowed to be the owning side. -- Changes to Collections are saved or updated, when the entity on - the *owning* side of the collection is saved or updated. -- Saving an Entity at the inverse side of a relation never - triggers a persist operation to changes to the collection. - -.. note:: - - Consistency of bi-directional references on the inverse side of a - relation have to be managed in userland application code. Doctrine - cannot magically update your collections to be consistent. - - -In the case of Users and Bugs we have references back and forth to -the assigned and reported bugs from a user, making this relation -bi-directional. We have to change the code to ensure consistency of -the bi-directional reference: - -.. code-block:: php - - assignedToBug($this); - $this->engineer = $engineer; - } - - public function setReporter(User $reporter) - { - $reporter->addReportedBug($this); - $this->reporter = $reporter; - } - - public function getEngineer() - { - return $this->engineer; - } - - public function getReporter() - { - return $this->reporter; - } - } - -.. code-block:: php - - reportedBugs[] = $bug; - } - - public function assignedToBug(Bug $bug) - { - $this->assignedBugs[] = $bug; - } - } - -I chose to name the inverse methods in past-tense, which should -indicate that the actual assigning has already taken place and the -methods are only used for ensuring consistency of the references. -This approach is my personal preference, you can choose whatever -method to make this work. - -You can see from ``User#addReportedBug()`` and -``User#assignedToBug()`` that using this method in userland alone -would not add the Bug to the collection of the owning side in -``Bug#reporter`` or ``Bug#engineer``. Using these methods and -calling Doctrine for persistence would not update the Collections' -representation in the database. - -Only using ``Bug#setEngineer()`` or ``Bug#setReporter()`` -correctly saves the relation information. - -The ``Bug#reporter`` and ``Bug#engineer`` properties are -Many-To-One relations, which point to a User. In a normalized -relational model, the foreign key is saved on the Bug's table, hence -in our object-relation model the Bug is at the owning side of the -relation. You should always make sure that the use-cases of your -domain model should drive which side is an inverse or owning one in -your Doctrine mapping. In our example, whenever a new bug is saved -or an engineer is assigned to the bug, we don't want to update the -User to persist the reference, but the Bug. This is the case with -the Bug being at the owning side of the relation. - -Bugs reference Products by a uni-directional ManyToMany relation in -the database that points from Bugs to Products. - -.. code-block:: php - - products[] = $product; - } - - public function getProducts() - { - return $this->products; - } - } - -We are now finished with the domain model given the requirements. -Lets add metadata mappings for the ``Bug`` entity, as we did for -the ``Product`` before: - -.. configuration-block:: - .. code-block:: php - - - - - - - - - - - - - - - - - - - - -.. note:: - The YAML driver is deprecated and will be removed in version 3.0. - It is strongly recommended to switch to one of the other mappings. - - .. code-block:: yaml - - # config/yaml/Bug.dcm.yml - Bug: - type: entity - table: bugs - id: - id: - type: integer - generator: - strategy: AUTO - fields: - description: - type: text - created: - type: datetime - status: - type: string - manyToOne: - reporter: - targetEntity: User - inversedBy: reportedBugs - engineer: - targetEntity: User - inversedBy: assignedBugs - manyToMany: - products: - targetEntity: Product - - -Here we have the entity, id and primitive type definitions. -For the "created" field we have used the ``datetime`` type, -which translates the YYYY-mm-dd HH:mm:ss database format -into a PHP DateTime instance and back. - -After the field definitions, the two qualified references to the -user entity are defined. They are created by the ``many-to-one`` -tag. The class name of the related entity has to be specified with -the ``target-entity`` attribute, which is enough information for -the database mapper to access the foreign-table. Since -``reporter`` and ``engineer`` are on the owning side of a -bi-directional relation, we also have to specify the ``inversed-by`` -attribute. They have to point to the field names on the inverse -side of the relationship. We will see in the next example that the ``inversed-by`` -attribute has a counterpart ``mapped-by`` which makes that -the inverse side. - -The last definition is for the ``Bug#products`` collection. It -holds all products where the specific bug occurs. Again -you have to define the ``target-entity`` and ``field`` attributes -on the ``many-to-many`` tag. - -Finally, we'll add metadata mappings for the ``User`` entity. - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - - - - - - - -.. note:: - The YAML driver is deprecated and will be removed in version 3.0. - It is strongly recommended to switch to one of the other mappings. - - .. code-block:: yaml - - # config/yaml/User.dcm.yml - User: - type: entity - table: users - id: - id: - type: integer - generator: - strategy: AUTO - fields: - name: - type: string - oneToMany: - reportedBugs: - targetEntity: Bug - mappedBy: reporter - assignedBugs: - targetEntity: Bug - mappedBy: engineer - -Here are some new things to mention about the ``one-to-many`` tags. -Remember that we discussed about the inverse and owning side. Now -both reportedBugs and assignedBugs are inverse relations, which -means the join details have already been defined on the owning -side. Therefore we only have to specify the property on the Bug -class that holds the owning sides. - -Update your database schema by running: -:: - - $ vendor/bin/doctrine orm:schema-tool:update --force - - -Implementing more Requirements ------------------------------- - -So far, we've seen the most basic features of the metadata definition language. -To explore additional functionality, let's first create new ``User`` entities: - -.. code-block:: php - - setName($newUsername); - - $entityManager->persist($user); - $entityManager->flush(); - - echo "Created User with ID " . $user->getId() . "\n"; - -Now call: - -:: - - $ php create_user.php beberlei - -We now have the necessary data to create a new Bug entity: - -.. code-block:: php - - - require_once "bootstrap.php"; - - $reporterId = $argv[1]; - $engineerId = $argv[2]; - $productIds = explode(",", $argv[3]); - - $reporter = $entityManager->find("User", $reporterId); - $engineer = $entityManager->find("User", $engineerId); - if (!$reporter || !$engineer) { - echo "No reporter and/or engineer found for the given id(s).\n"; - exit(1); - } - - $bug = new Bug(); - $bug->setDescription("Something does not work!"); - $bug->setCreated(new DateTime("now")); - $bug->setStatus("OPEN"); - - foreach ($productIds as $productId) { - $product = $entityManager->find("Product", $productId); - $bug->assignToProduct($product); - } - - $bug->setReporter($reporter); - $bug->setEngineer($engineer); - - $entityManager->persist($bug); - $entityManager->flush(); - - echo "Your new Bug Id: ".$bug->getId()."\n"; - -Since we only have one user and product, probably with the ID of 1, we can -call this script as follows: - -:: - - php create_bug.php 1 1 1 - -See how simple it is to relate a Bug, Reporter, Engineer and Products? -Also recall that thanks to the UnitOfWork pattern, Doctrine will detect -these relations and update all of the modified entities in the database -automatically when ``flush()`` is called. - -Queries for Application Use-Cases ---------------------------------- - -List of Bugs -~~~~~~~~~~~~ - -Using the previous examples we can fill up the database quite a -bit. However, we now need to discuss how to query the underlying -mapper for the required view representations. When opening the -application, bugs can be paginated through a list-view, which is -the first read-only use-case: - -.. code-block:: php - - createQuery($dql); - $query->setMaxResults(30); - $bugs = $query->getResult(); - - foreach ($bugs as $bug) { - echo $bug->getDescription()." - ".$bug->getCreated()->format('d.m.Y')."\n"; - echo " Reported by: ".$bug->getReporter()->getName()."\n"; - echo " Assigned to: ".$bug->getEngineer()->getName()."\n"; - foreach ($bug->getProducts() as $product) { - echo " Platform: ".$product->getName()."\n"; - } - echo "\n"; - } - -The DQL Query in this example fetches the 30 most recent bugs with -their respective engineer and reporter in one single SQL statement. -The console output of this script is then: - -:: - - Something does not work! - 02.04.2010 - Reported by: beberlei - Assigned to: beberlei - Platform: My Product - -.. note:: - - **DQL is not SQL** - - You may wonder why we start writing SQL at the beginning of this - use-case. Don't we use an ORM to get rid of all the endless - hand-writing of SQL? Doctrine introduces DQL which is best - described as **object-query-language** and is a dialect of - `OQL `_ and - similar to `HQL `_ or - `JPQL `_. - It does not know the concept of columns and tables, but only those - of Entity-Class and property. Using the Metadata we defined before - it allows for very short distinctive and powerful queries. - - - An important reason why DQL is favourable to the Query API of most - ORMs is its similarity to SQL. The DQL language allows query - constructs that most ORMs don't: GROUP BY even with HAVING, - Sub-selects, Fetch-Joins of nested classes, mixed results with - entities and scalar data such as COUNT() results and much more. - Using DQL you should seldom come to the point where you want to - throw your ORM into the dumpster, because it doesn't support some - the more powerful SQL concepts. - - If you need to build your query dynamically, you can use the ``QueryBuilder`` retrieved - by calling ``$entityManager->createQueryBuilder()``. There are more - details about this in the relevant part of the documentation. - - - As a last resort you can still use Native SQL and a description of the - result set to retrieve entities from the database. DQL boils down to a - Native SQL statement and a ``ResultSetMapping`` instance itself. Using - Native SQL you could even use stored procedures for data retrieval, or - make use of advanced non-portable database queries like PostgreSql's - recursive queries. - - -Array Hydration of the Bug List -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In the previous use-case we retrieved the results as their -respective object instances. We are not limited to retrieving -objects only from Doctrine however. For a simple list view like the -previous one we only need read access to our entities and can -switch the hydration from objects to simple PHP arrays instead. - -Hydration can be an expensive process so only retrieving what you need can -yield considerable performance benefits for read-only requests. - -Implementing the same list view as before using array hydration we -can rewrite our code: - -.. code-block:: php - - createQuery($dql); - $bugs = $query->getArrayResult(); - - foreach ($bugs as $bug) { - echo $bug['description'] . " - " . $bug['created']->format('d.m.Y')."\n"; - echo " Reported by: ".$bug['reporter']['name']."\n"; - echo " Assigned to: ".$bug['engineer']['name']."\n"; - foreach ($bug['products'] as $product) { - echo " Platform: ".$product['name']."\n"; - } - echo "\n"; - } - -There is one significant difference in the DQL query however, we -have to add an additional fetch-join for the products connected to -a bug. The resulting SQL query for this single select statement is -pretty large, however still more efficient to retrieve compared to -hydrating objects. - -Find by Primary Key -~~~~~~~~~~~~~~~~~~~ - -The next Use-Case is displaying a Bug by primary key. This could be -done using DQL as in the previous example with a where clause, -however there is a convenience method on the ``EntityManager`` that -handles loading by primary key, which we have already seen in the -write scenarios: - -.. code-block:: php - - - require_once "bootstrap.php"; - - $theBugId = $argv[1]; - - $bug = $entityManager->find("Bug", (int)$theBugId); - - echo "Bug: ".$bug->getDescription()."\n"; - echo "Engineer: ".$bug->getEngineer()->getName()."\n"; - -The output of the engineer’s name is fetched from the database! What is happening? - -Since we only retrieved the bug by primary key both the engineer and reporter -are not immediately loaded from the database but are replaced by LazyLoading -proxies. These proxies will load behind the scenes, when the first method -is called on them. - -Sample code of this proxy generated code can be found in the specified Proxy -Directory, it looks like: - -.. code-block:: php - - _load(); - return parent::addReportedBug($bug); - } - - public function assignedToBug($bug) - { - $this->_load(); - return parent::assignedToBug($bug); - } - } - -See how upon each method call the proxy is lazily loaded from the -database? - -The call prints: - -:: - - $ php show_bug.php 1 - Bug: Something does not work! - Engineer: beberlei - -.. warning:: - - Lazy loading additional data can be very convenient but the additional - queries create an overhead. If you know that certain fields will always - (or usually) be required by the query then you will get better performance - by explicitly retrieving them all in the first query. - - -Dashboard of the User ---------------------- - -For the next use-case we want to retrieve the dashboard view, a -list of all open bugs the user reported or was assigned to. This -will be achieved using DQL again, this time with some WHERE clauses -and usage of bound parameters: - -.. code-block:: php - - - require_once "bootstrap.php"; - - $theUserId = $argv[1]; - - $dql = "SELECT b, e, r FROM Bug b JOIN b.engineer e JOIN b.reporter r ". - "WHERE b.status = 'OPEN' AND (e.id = ?1 OR r.id = ?1) ORDER BY b.created DESC"; - - $myBugs = $entityManager->createQuery($dql) - ->setParameter(1, $theUserId) - ->setMaxResults(15) - ->getResult(); - - echo "You have created or assigned to " . count($myBugs) . " open bugs:\n\n"; - - foreach ($myBugs as $bug) { - echo $bug->getId() . " - " . $bug->getDescription()."\n"; - } - -Number of Bugs --------------- - -Until now we only retrieved entities or their array representation. -Doctrine also supports the retrieval of non-entities through DQL. -These values are called "scalar result values" and may even be -aggregate values using COUNT, SUM, MIN, MAX or AVG functions. - -We will need this knowledge to retrieve the number of open bugs -grouped by product: - -.. code-block:: php - - createQuery($dql)->getScalarResult(); - - foreach ($productBugs as $productBug) { - echo $productBug['name']." has " . $productBug['openBugs'] . " open bugs!\n"; - } - -Updating Entities ------------------ - -There is a single use-case missing from the requirements, Engineers -should be able to close a bug. This looks like: - -.. code-block:: php - - status = "CLOSE"; - } - } - -.. code-block:: php - - - require_once "bootstrap.php"; - - $theBugId = $argv[1]; - - $bug = $entityManager->find("Bug", (int)$theBugId); - $bug->close(); - - $entityManager->flush(); - -When retrieving the Bug from the database it is inserted into the -IdentityMap inside the UnitOfWork of Doctrine. This means your Bug -with exactly this id can only exist once during the whole request -no matter how often you call ``EntityManager#find()``. It even -detects entities that are hydrated using DQL and are already -present in the Identity Map. - -When flush is called the EntityManager loops over all the entities -in the identity map and performs a comparison between the values -originally retrieved from the database and those values the entity -currently has. If at least one of these properties is different the -entity is scheduled for an UPDATE against the database. Only the -changed columns are updated, which offers a pretty good performance -improvement compared to updating all the properties. - -Entity Repositories -------------------- - -For now we have not discussed how to separate the Doctrine query logic from your model. -In Doctrine 1 there was the concept of ``Doctrine_Table`` instances for this -separation. The similar concept in Doctrine2 is called Entity Repositories, integrating -the `repository pattern `_ at the heart of Doctrine. - -Every Entity uses a default repository by default and offers a bunch of convenience -methods that you can use to query for instances of that Entity. Take for example -our Product entity. If we wanted to Query by name, we can use: - -.. code-block:: php - - getRepository('Product') - ->findOneBy(array('name' => $productName)); - -The method ``findOneBy()`` takes an array of fields or association keys and the values to match against. - -If you want to find all entities matching a condition you can use ``findBy()``, for -example querying for all closed bugs: - -.. code-block:: php - - getRepository('Bug') - ->findBy(array('status' => 'CLOSED')); - - foreach ($bugs as $bug) { - // do stuff - } - -Compared to DQL these query methods are falling short of functionality very fast. -Doctrine offers you a convenient way to extend the functionalities of the default ``EntityRepository`` -and put all the specialized DQL query logic on it. For this you have to create a subclass -of ``Doctrine\ORM\EntityRepository``, in our case a ``BugRepository`` and group all -the previously discussed query functionality in it: - -.. code-block:: php - - getEntityManager()->createQuery($dql); - $query->setMaxResults($number); - return $query->getResult(); - } - - public function getRecentBugsArray($number = 30) - { - $dql = "SELECT b, e, r, p FROM Bug b JOIN b.engineer e ". - "JOIN b.reporter r JOIN b.products p ORDER BY b.created DESC"; - $query = $this->getEntityManager()->createQuery($dql); - $query->setMaxResults($number); - return $query->getArrayResult(); - } - - public function getUsersBugs($userId, $number = 15) - { - $dql = "SELECT b, e, r FROM Bug b JOIN b.engineer e JOIN b.reporter r ". - "WHERE b.status = 'OPEN' AND e.id = ?1 OR r.id = ?1 ORDER BY b.created DESC"; - - return $this->getEntityManager()->createQuery($dql) - ->setParameter(1, $userId) - ->setMaxResults($number) - ->getResult(); - } - - public function getOpenBugsByProduct() - { - $dql = "SELECT p.id, p.name, count(b.id) AS openBugs FROM Bug b ". - "JOIN b.products p WHERE b.status = 'OPEN' GROUP BY p.id"; - return $this->getEntityManager()->createQuery($dql)->getScalarResult(); - } - } - -To be able to use this query logic through ``$this->getEntityManager()->getRepository('Bug')`` -we have to adjust the metadata slightly. - -.. configuration-block:: - - .. code-block:: php - - - - - - - - -.. note:: - The YAML driver is deprecated and will be removed in version 3.0. - It is strongly recommended to switch to one of the other mappings. - - .. code-block:: yaml - - Bug: - type: entity - repositoryClass: BugRepository - -Now we can remove our query logic in all the places and instead use them through the EntityRepository. -As an example here is the code of the first use case "List of Bugs": - -.. code-block:: php - - getRepository('Bug')->getRecentBugs(); - - foreach ($bugs as $bug) { - echo $bug->getDescription()." - ".$bug->getCreated()->format('d.m.Y')."\n"; - echo " Reported by: ".$bug->getReporter()->getName()."\n"; - echo " Assigned to: ".$bug->getEngineer()->getName()."\n"; - foreach ($bug->getProducts() as $product) { - echo " Platform: ".$product->getName()."\n"; - } - echo "\n"; - } - -Using EntityRepositories you can avoid coupling your model with specific query logic. -You can also re-use query logic easily throughout your application. - -The method ``count()`` takes an array of fields or association keys and the values to match against. -This provides you with a convenient and lightweight way to count a resultset when you don't need to -deal with it: - -.. code-block:: php - - getRepository(Product::class) - ->count(['name' => $productName]); - -Conclusion ----------- - -This tutorial is over here, I hope you had fun. Additional content -will be added to this tutorial incrementally, topics will include: - -- More on Association Mappings -- Lifecycle Events triggered in the UnitOfWork -- Ordering of Collections - -Additional details on all the topics discussed here can be found in -the respective manual chapters. diff --git a/vendor/doctrine/orm/docs/en/tutorials/ordered-associations.rst b/vendor/doctrine/orm/docs/en/tutorials/ordered-associations.rst deleted file mode 100644 index cb0e64a..0000000 --- a/vendor/doctrine/orm/docs/en/tutorials/ordered-associations.rst +++ /dev/null @@ -1,110 +0,0 @@ -Ordering To-Many Associations ------------------------------ - -There are use-cases when you'll want to sort collections when they are -retrieved from the database. In userland you do this as long as you -haven't initially saved an entity with its associations into the -database. To retrieve a sorted collection from the database you can -use the ``@OrderBy`` annotation with a collection that specifies -a DQL snippet that is appended to all queries with this -collection. - -Additional to any ``@OneToMany`` or ``@ManyToMany`` annotation you -can specify the ``@OrderBy`` in the following way: - -.. configuration-block:: - - .. code-block:: php - - - - - - - - - - - - .. code-block:: yaml - - User: - type: entity - manyToMany: - groups: - orderBy: { 'name': 'ASC' } - targetEntity: Group - joinTable: - name: users_groups - joinColumns: - user_id: - referencedColumnName: id - inverseJoinColumns: - group_id: - referencedColumnName: id - -The DQL Snippet in OrderBy is only allowed to consist of -unqualified, unquoted field names and of an optional ASC/DESC -positional statement. Multiple Fields are separated by a comma (,). -The referenced field names have to exist on the ``targetEntity`` -class of the ``@ManyToMany`` or ``@OneToMany`` annotation. - -The semantics of this feature can be described as follows: - - -- ``@OrderBy`` acts as an implicit ORDER BY clause for the given - fields, that is appended to all the explicitly given ORDER BY - items. -- All collections of the ordered type are always retrieved in an - ordered fashion. -- To keep the database impact low, these implicit ORDER BY items - are only added to a DQL Query if the collection is fetch joined in - the DQL query. - -Given our previously defined example, the following would not add -ORDER BY, since g is not fetch joined: - -.. code-block:: sql - - SELECT u FROM User u JOIN u.groups g WHERE SIZE(g) > 10 - -However the following: - -.. code-block:: sql - - SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 - -...would internally be rewritten to: - -.. code-block:: sql - - SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 ORDER BY g.name ASC - -You can reverse the order with an explicit DQL ORDER BY: - -.. code-block:: sql - - SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 ORDER BY g.name DESC - -...is internally rewritten to: - -.. code-block:: sql - - SELECT u, g FROM User u JOIN u.groups g WHERE u.id = 10 ORDER BY g.name DESC, g.name ASC - - diff --git a/vendor/doctrine/orm/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst b/vendor/doctrine/orm/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst deleted file mode 100644 index de9f0d9..0000000 --- a/vendor/doctrine/orm/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst +++ /dev/null @@ -1,92 +0,0 @@ -Override Field Association Mappings In Subclasses -------------------------------------------------- - -Sometimes there is a need to persist entities but override all or part of the -mapping metadata. Sometimes also the mapping to override comes from entities -using traits where the traits have mapping metadata. -This tutorial explains how to override mapping metadata, -i.e. attributes and associations metadata in particular. The example here shows -the overriding of a class that uses a trait but is similar when extending a base -class as shown at the end of this tutorial. - -Suppose we have a class ExampleEntityWithOverride. This class uses trait ExampleTrait: - -.. code-block:: php - - `). diff --git a/vendor/doctrine/orm/docs/en/tutorials/pagination.rst b/vendor/doctrine/orm/docs/en/tutorials/pagination.rst deleted file mode 100644 index 3971383..0000000 --- a/vendor/doctrine/orm/docs/en/tutorials/pagination.rst +++ /dev/null @@ -1,43 +0,0 @@ -Pagination -========== - -.. versionadded:: 2.2 - -Starting with version 2.2 Doctrine ships with a Paginator for DQL queries. It -has a very simple API and implements the SPL interfaces ``Countable`` and -``IteratorAggregate``. - -.. code-block:: php - - createQuery($dql) - ->setFirstResult(0) - ->setMaxResults(100); - - $paginator = new Paginator($query, $fetchJoinCollection = true); - - $c = count($paginator); - foreach ($paginator as $post) { - echo $post->getHeadline() . "\n"; - } - -Paginating Doctrine queries is not as simple as you might think in the -beginning. If you have complex fetch-join scenarios with one-to-many or -many-to-many associations using the "default" LIMIT functionality of database -vendors is not sufficient to get the correct results. - -By default the pagination extension does the following steps to compute the -correct result: - -- Perform a Count query using `DISTINCT` keyword. -- Perform a Limit Subquery with `DISTINCT` to find all ids of the entity in from on the current page. -- Perform a WHERE IN query to get all results for the current page. - -This behavior is only necessary if you actually fetch join a to-many -collection. You can disable this behavior by setting the -``$fetchJoinCollection`` flag to ``false``; in that case only 2 instead of the 3 queries -described are executed. We hope to automate the detection for this in -the future. diff --git a/vendor/doctrine/orm/docs/en/tutorials/working-with-indexed-associations.rst b/vendor/doctrine/orm/docs/en/tutorials/working-with-indexed-associations.rst deleted file mode 100644 index 0381764..0000000 --- a/vendor/doctrine/orm/docs/en/tutorials/working-with-indexed-associations.rst +++ /dev/null @@ -1,296 +0,0 @@ -Working with Indexed Associations -================================= - -.. note:: - - This feature is available from version 2.1 of Doctrine. - -Doctrine 2 collections are modelled after PHPs native arrays. PHP arrays are an ordered hashmap, but in -the first version of Doctrine keys retrieved from the database were always numerical unless ``INDEX BY`` -was used. Starting with Doctrine 2.1 you can index your collections by a value in the related entity. -This is a first step towards full ordered hashmap support through the Doctrine ORM. -The feature works like an implicit ``INDEX BY`` for the selected association but has several -downsides also: - -- You have to manage both the key and field if you want to change the index by field value. -- On each request the keys are regenerated from the field value, and not from the previous collection key. -- Values of the Index-By keys are never considered during persistence. They only exist for accessing purposes. -- Fields that are used for the index by feature **HAVE** to be unique in the database. The behavior for multiple entities - with the same index-by field value is undefined. - -As an example we will design a simple stock exchange list view. The domain consists of the entity ``Stock`` -and ``Market`` where each Stock has a symbol and is traded on a single market. Instead of having a numerical -list of stocks traded on a market they will be indexed by their symbol, which is unique across all markets. - -Mapping Indexed Associations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can map indexed associations by adding: - - * ``indexBy`` attribute to any ``@OneToMany`` or ``@ManyToMany`` annotation. - * ``index-by`` attribute to any ```` or ```` xml element. - * ``indexBy:`` key-value pair to any association defined in ``manyToMany:`` or ``oneToMany:`` YAML mapping files. - -The code and mappings for the Market entity looks like this: - -.. configuration-block:: - .. code-block:: php - - name = $name; - $this->stocks = new ArrayCollection(); - } - - public function getId() - { - return $this->id; - } - - public function getName() - { - return $this->name; - } - - public function addStock(Stock $stock) - { - $this->stocks[$stock->getSymbol()] = $stock; - } - - public function getStock($symbol) - { - if (!isset($this->stocks[$symbol])) { - throw new \InvalidArgumentException("Symbol is not traded on this market."); - } - - return $this->stocks[$symbol]; - } - - public function getStocks() - { - return $this->stocks->toArray(); - } - } - - .. code-block:: xml - - - - - - - - - - - - - - - - .. code-block:: yaml - - Doctrine\Tests\Models\StockExchange\Market: - type: entity - id: - id: - type: integer - generator: - strategy: AUTO - fields: - name: - type:string - oneToMany: - stocks: - targetEntity: Stock - mappedBy: market - indexBy: symbol - -Inside the ``addStock()`` method you can see how we directly set the key of the association to the symbol, -so that we can work with the indexed association directly after invoking ``addStock()``. Inside ``getStock($symbol)`` -we pick a stock traded on the particular market by symbol. If this stock doesn't exist an exception is thrown. - -The ``Stock`` entity doesn't contain any special instructions that are new, but for completeness -here are the code and mappings for it: - -.. configuration-block:: - .. code-block:: php - - symbol = $symbol; - $this->market = $market; - $market->addStock($this); - } - - public function getSymbol() - { - return $this->symbol; - } - } - - .. code-block:: xml - - - - - - - - - - - - - - - .. code-block:: yaml - - Doctrine\Tests\Models\StockExchange\Stock: - type: entity - id: - id: - type: integer - generator: - strategy: AUTO - fields: - symbol: - type: string - manyToOne: - market: - targetEntity: Market - inversedBy: stocks - -Querying indexed associations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Now that we defined the stocks collection to be indexed by symbol, we can take a look at some code -that makes use of the indexing. - -First we will populate our database with two example stocks traded on a single market: - -.. code-block:: php - - persist($market); - $em->persist($stock1); - $em->persist($stock2); - $em->flush(); - -This code is not particular interesting since the indexing feature is not yet used. In a new request we could -now query for the market: - -.. code-block:: php - - find("Doctrine\Tests\Models\StockExchange\Market", $marketId); - - // Access the stocks by symbol now: - $stock = $market->getStock($symbol); - - echo $stock->getSymbol(); // will print "AAPL" - -The implementation of ``Market::addStock()``, in combination with ``indexBy``, allows us to access the collection -consistently by the Stock symbol. It does not matter if Stock is managed by Doctrine or not. - -The same applies to DQL queries: The ``indexBy`` configuration acts as implicit "INDEX BY" to a join association. - -.. code-block:: php - - createQuery($dql) - ->setParameter(1, $marketId) - ->getSingleResult(); - - // Access the stocks by symbol now: - $stock = $market->getStock($symbol); - - echo $stock->getSymbol(); // will print "AAPL" - -If you want to use ``INDEX BY`` explicitly on an indexed association you are free to do so. Additionally, -indexed associations also work with the ``Collection::slice()`` functionality, even if the association's fetch mode is -LAZY or EXTRA_LAZY. - -Outlook into the Future -~~~~~~~~~~~~~~~~~~~~~~~ - -For the inverse side of a many-to-many associations there will be a way to persist the keys and the order -as a third and fourth parameter into the join table. This feature is discussed in `DDC-213 `_ -This feature cannot be implemented for one-to-many associations, because they are never the owning side. - diff --git a/vendor/doctrine/orm/doctrine-mapping.xsd b/vendor/doctrine/orm/doctrine-mapping.xsd deleted file mode 100644 index 561b062..0000000 --- a/vendor/doctrine/orm/doctrine-mapping.xsd +++ /dev/null @@ -1,622 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php b/vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php deleted file mode 100644 index 2240366..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/AbstractQuery.php +++ /dev/null @@ -1,1165 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -use Doctrine\Common\Persistence\Mapping\MappingException; -use Doctrine\Common\Util\ClassUtils; -use Doctrine\Common\Collections\Collection; -use Doctrine\Common\Collections\ArrayCollection; - -use Doctrine\ORM\Mapping\MappingException as ORMMappingException; -use Doctrine\ORM\Query\Parameter; -use Doctrine\ORM\Cache\QueryCacheKey; -use Doctrine\DBAL\Cache\QueryCacheProfile; - -/** - * Base contract for ORM queries. Base class for Query and NativeQuery. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Konsta Vesterinen - */ -abstract class AbstractQuery -{ - /* Hydration mode constants */ - - /** - * Hydrates an object graph. This is the default behavior. - */ - const HYDRATE_OBJECT = 1; - - /** - * Hydrates an array graph. - */ - const HYDRATE_ARRAY = 2; - - /** - * Hydrates a flat, rectangular result set with scalar values. - */ - const HYDRATE_SCALAR = 3; - - /** - * Hydrates a single scalar value. - */ - const HYDRATE_SINGLE_SCALAR = 4; - - /** - * Very simple object hydrator (optimized for performance). - */ - const HYDRATE_SIMPLEOBJECT = 5; - - /** - * The parameter map of this query. - * - * @var ArrayCollection|Parameter[] - */ - protected $parameters; - - /** - * The user-specified ResultSetMapping to use. - * - * @var \Doctrine\ORM\Query\ResultSetMapping - */ - protected $_resultSetMapping; - - /** - * The entity manager used by this query object. - * - * @var EntityManagerInterface - */ - protected $_em; - - /** - * The map of query hints. - * - * @var array - */ - protected $_hints = []; - - /** - * The hydration mode. - * - * @var string|int - */ - protected $_hydrationMode = self::HYDRATE_OBJECT; - - /** - * @var \Doctrine\DBAL\Cache\QueryCacheProfile - */ - protected $_queryCacheProfile; - - /** - * Whether or not expire the result cache. - * - * @var boolean - */ - protected $_expireResultCache = false; - - /** - * @var \Doctrine\DBAL\Cache\QueryCacheProfile - */ - protected $_hydrationCacheProfile; - - /** - * Whether to use second level cache, if available. - * - * @var boolean - */ - protected $cacheable = false; - - /** - * @var boolean - */ - protected $hasCache = false; - - /** - * Second level cache region name. - * - * @var string|null - */ - protected $cacheRegion; - - /** - * Second level query cache mode. - * - * @var integer|null - */ - protected $cacheMode; - - /** - * @var \Doctrine\ORM\Cache\Logging\CacheLogger|null - */ - protected $cacheLogger; - - /** - * @var integer - */ - protected $lifetime = 0; - - /** - * Initializes a new instance of a class derived from AbstractQuery. - * - * @param \Doctrine\ORM\EntityManagerInterface $em - */ - public function __construct(EntityManagerInterface $em) - { - $this->_em = $em; - $this->parameters = new ArrayCollection(); - $this->_hints = $em->getConfiguration()->getDefaultQueryHints(); - $this->hasCache = $this->_em->getConfiguration()->isSecondLevelCacheEnabled(); - - if ($this->hasCache) { - $this->cacheLogger = $em->getConfiguration() - ->getSecondLevelCacheConfiguration() - ->getCacheLogger(); - } - } - - /** - * Enable/disable second level query (result) caching for this query. - * - * @param boolean $cacheable - * - * @return static This query instance. - */ - public function setCacheable($cacheable) - { - $this->cacheable = (boolean) $cacheable; - - return $this; - } - - /** - * @return boolean TRUE if the query results are enable for second level cache, FALSE otherwise. - */ - public function isCacheable() - { - return $this->cacheable; - } - - /** - * @param string $cacheRegion - * - * @return static This query instance. - */ - public function setCacheRegion($cacheRegion) - { - $this->cacheRegion = (string) $cacheRegion; - - return $this; - } - - /** - * Obtain the name of the second level query cache region in which query results will be stored - * - * @return string|null The cache region name; NULL indicates the default region. - */ - public function getCacheRegion() - { - return $this->cacheRegion; - } - - /** - * @return boolean TRUE if the query cache and second level cache are enabled, FALSE otherwise. - */ - protected function isCacheEnabled() - { - return $this->cacheable && $this->hasCache; - } - - /** - * @return integer - */ - public function getLifetime() - { - return $this->lifetime; - } - - /** - * Sets the life-time for this query into second level cache. - * - * @param integer $lifetime - * - * @return \Doctrine\ORM\AbstractQuery This query instance. - */ - public function setLifetime($lifetime) - { - $this->lifetime = (integer) $lifetime; - - return $this; - } - - /** - * @return integer - */ - public function getCacheMode() - { - return $this->cacheMode; - } - - /** - * @param integer $cacheMode - * - * @return \Doctrine\ORM\AbstractQuery This query instance. - */ - public function setCacheMode($cacheMode) - { - $this->cacheMode = (integer) $cacheMode; - - return $this; - } - - /** - * Gets the SQL query that corresponds to this query object. - * The returned SQL syntax depends on the connection driver that is used - * by this query object at the time of this method call. - * - * @return string SQL query - */ - abstract public function getSQL(); - - /** - * Retrieves the associated EntityManager of this Query instance. - * - * @return \Doctrine\ORM\EntityManager - */ - public function getEntityManager() - { - return $this->_em; - } - - /** - * Frees the resources used by the query object. - * - * Resets Parameters, Parameter Types and Query Hints. - * - * @return void - */ - public function free() - { - $this->parameters = new ArrayCollection(); - - $this->_hints = $this->_em->getConfiguration()->getDefaultQueryHints(); - } - - /** - * Get all defined parameters. - * - * @return ArrayCollection The defined query parameters. - */ - public function getParameters() - { - return $this->parameters; - } - - /** - * Gets a query parameter. - * - * @param mixed $key The key (index or name) of the bound parameter. - * - * @return Query\Parameter|null The value of the bound parameter, or NULL if not available. - */ - public function getParameter($key) - { - $filteredParameters = $this->parameters->filter( - function (Query\Parameter $parameter) use ($key) : bool { - $parameterName = $parameter->getName(); - - return $key === $parameterName || (string) $key === (string) $parameterName; - } - ); - - return ! $filteredParameters->isEmpty() ? $filteredParameters->first() : null; - } - - /** - * Sets a collection of query parameters. - * - * @param ArrayCollection|mixed[] $parameters - * - * @return static This query instance. - */ - public function setParameters($parameters) - { - // BC compatibility with 2.3- - if (is_array($parameters)) { - $parameterCollection = new ArrayCollection(); - - foreach ($parameters as $key => $value) { - $parameterCollection->add(new Parameter($key, $value)); - } - - $parameters = $parameterCollection; - } - - $this->parameters = $parameters; - - return $this; - } - - /** - * Sets a query parameter. - * - * @param string|int $key The parameter position or name. - * @param mixed $value The parameter value. - * @param string|null $type The parameter type. If specified, the given value will be run through - * the type conversion of this type. This is usually not needed for - * strings and numeric types. - * - * @return static This query instance. - */ - public function setParameter($key, $value, $type = null) - { - $existingParameter = $this->getParameter($key); - - if ($existingParameter !== null) { - $existingParameter->setValue($value, $type); - - return $this; - } - - $this->parameters->add(new Parameter($key, $value, $type)); - - return $this; - } - - /** - * Processes an individual parameter value. - * - * @param mixed $value - * - * @return array|string - * - * @throws \Doctrine\ORM\ORMInvalidArgumentException - */ - public function processParameterValue($value) - { - if (is_scalar($value)) { - return $value; - } - - if ($value instanceof Collection) { - $value = $value->toArray(); - } - - if (is_array($value)) { - foreach ($value as $key => $paramValue) { - $paramValue = $this->processParameterValue($paramValue); - $value[$key] = is_array($paramValue) ? reset($paramValue) : $paramValue; - } - - return $value; - } - - if ($value instanceof Mapping\ClassMetadata) { - return $value->name; - } - - if (! is_object($value)) { - return $value; - } - - try { - $value = $this->_em->getUnitOfWork()->getSingleIdentifierValue($value); - - if ($value === null) { - throw ORMInvalidArgumentException::invalidIdentifierBindingEntity(); - } - } catch (MappingException | ORMMappingException $e) { - // Silence any mapping exceptions. These can occur if the object in - // question is not a mapped entity, in which case we just don't do - // any preparation on the value. - } - - return $value; - } - - /** - * Sets the ResultSetMapping that should be used for hydration. - * - * @param \Doctrine\ORM\Query\ResultSetMapping $rsm - * - * @return static This query instance. - */ - public function setResultSetMapping(Query\ResultSetMapping $rsm) - { - $this->translateNamespaces($rsm); - $this->_resultSetMapping = $rsm; - - return $this; - } - - /** - * Gets the ResultSetMapping used for hydration. - * - * @return \Doctrine\ORM\Query\ResultSetMapping - */ - protected function getResultSetMapping() - { - return $this->_resultSetMapping; - } - - /** - * Allows to translate entity namespaces to full qualified names. - * - * @param Query\ResultSetMapping $rsm - * - * @return void - */ - private function translateNamespaces(Query\ResultSetMapping $rsm) - { - $translate = function ($alias) { - return $this->_em->getClassMetadata($alias)->getName(); - }; - - $rsm->aliasMap = array_map($translate, $rsm->aliasMap); - $rsm->declaringClasses = array_map($translate, $rsm->declaringClasses); - } - - /** - * Set a cache profile for hydration caching. - * - * If no result cache driver is set in the QueryCacheProfile, the default - * result cache driver is used from the configuration. - * - * Important: Hydration caching does NOT register entities in the - * UnitOfWork when retrieved from the cache. Never use result cached - * entities for requests that also flush the EntityManager. If you want - * some form of caching with UnitOfWork registration you should use - * {@see AbstractQuery::setResultCacheProfile()}. - * - * @example - * $lifetime = 100; - * $resultKey = "abc"; - * $query->setHydrationCacheProfile(new QueryCacheProfile()); - * $query->setHydrationCacheProfile(new QueryCacheProfile($lifetime, $resultKey)); - * - * @param \Doctrine\DBAL\Cache\QueryCacheProfile $profile - * - * @return static This query instance. - */ - public function setHydrationCacheProfile(QueryCacheProfile $profile = null) - { - if ($profile !== null && ! $profile->getResultCacheDriver()) { - $resultCacheDriver = $this->_em->getConfiguration()->getHydrationCacheImpl(); - $profile = $profile->setResultCacheDriver($resultCacheDriver); - } - - $this->_hydrationCacheProfile = $profile; - - return $this; - } - - /** - * @return \Doctrine\DBAL\Cache\QueryCacheProfile - */ - public function getHydrationCacheProfile() - { - return $this->_hydrationCacheProfile; - } - - /** - * Set a cache profile for the result cache. - * - * If no result cache driver is set in the QueryCacheProfile, the default - * result cache driver is used from the configuration. - * - * @param \Doctrine\DBAL\Cache\QueryCacheProfile $profile - * - * @return static This query instance. - */ - public function setResultCacheProfile(QueryCacheProfile $profile = null) - { - if ($profile !== null && ! $profile->getResultCacheDriver()) { - $resultCacheDriver = $this->_em->getConfiguration()->getResultCacheImpl(); - $profile = $profile->setResultCacheDriver($resultCacheDriver); - } - - $this->_queryCacheProfile = $profile; - - return $this; - } - - /** - * Defines a cache driver to be used for caching result sets and implicitly enables caching. - * - * @param \Doctrine\Common\Cache\Cache|null $resultCacheDriver Cache driver - * - * @return static This query instance. - * - * @throws ORMException - */ - public function setResultCacheDriver($resultCacheDriver = null) - { - if ($resultCacheDriver !== null && ! ($resultCacheDriver instanceof \Doctrine\Common\Cache\Cache)) { - throw ORMException::invalidResultCacheDriver(); - } - - $this->_queryCacheProfile = $this->_queryCacheProfile - ? $this->_queryCacheProfile->setResultCacheDriver($resultCacheDriver) - : new QueryCacheProfile(0, null, $resultCacheDriver); - - return $this; - } - - /** - * Returns the cache driver used for caching result sets. - * - * @deprecated - * - * @return \Doctrine\Common\Cache\Cache Cache driver - */ - public function getResultCacheDriver() - { - if ($this->_queryCacheProfile && $this->_queryCacheProfile->getResultCacheDriver()) { - return $this->_queryCacheProfile->getResultCacheDriver(); - } - - return $this->_em->getConfiguration()->getResultCacheImpl(); - } - - /** - * Set whether or not to cache the results of this query and if so, for - * how long and which ID to use for the cache entry. - * - * @deprecated 2.7 Use {@see enableResultCache} and {@see disableResultCache} instead. - * - * @param bool $useCache - * @param int $lifetime - * @param string $resultCacheId - * - * @return static This query instance. - */ - public function useResultCache($useCache, $lifetime = null, $resultCacheId = null) - { - return $useCache - ? $this->enableResultCache($lifetime, $resultCacheId) - : $this->disableResultCache(); - } - - /** - * Enables caching of the results of this query, for given or default amount of seconds - * and optionally specifies which ID to use for the cache entry. - * - * @param int|null $lifetime How long the cache entry is valid, in seconds. - * @param string|null $resultCacheId ID to use for the cache entry. - * - * @return static This query instance. - */ - public function enableResultCache(?int $lifetime = null, ?string $resultCacheId = null) : self - { - $this->setResultCacheLifetime($lifetime); - $this->setResultCacheId($resultCacheId); - - return $this; - } - - /** - * Disables caching of the results of this query. - * - * @return static This query instance. - */ - public function disableResultCache() : self - { - $this->_queryCacheProfile = null; - - return $this; - } - - /** - * Defines how long the result cache will be active before expire. - * - * @param integer $lifetime How long the cache entry is valid. - * - * @return static This query instance. - */ - public function setResultCacheLifetime($lifetime) - { - $lifetime = ($lifetime !== null) ? (int) $lifetime : 0; - - $this->_queryCacheProfile = $this->_queryCacheProfile - ? $this->_queryCacheProfile->setLifetime($lifetime) - : new QueryCacheProfile($lifetime, null, $this->_em->getConfiguration()->getResultCacheImpl()); - - return $this; - } - - /** - * Retrieves the lifetime of resultset cache. - * - * @deprecated - * - * @return integer - */ - public function getResultCacheLifetime() - { - return $this->_queryCacheProfile ? $this->_queryCacheProfile->getLifetime() : 0; - } - - /** - * Defines if the result cache is active or not. - * - * @param boolean $expire Whether or not to force resultset cache expiration. - * - * @return static This query instance. - */ - public function expireResultCache($expire = true) - { - $this->_expireResultCache = $expire; - - return $this; - } - - /** - * Retrieves if the resultset cache is active or not. - * - * @return boolean - */ - public function getExpireResultCache() - { - return $this->_expireResultCache; - } - - /** - * @return QueryCacheProfile - */ - public function getQueryCacheProfile() - { - return $this->_queryCacheProfile; - } - - /** - * Change the default fetch mode of an association for this query. - * - * $fetchMode can be one of ClassMetadata::FETCH_EAGER or ClassMetadata::FETCH_LAZY - * - * @param string $class - * @param string $assocName - * @param int $fetchMode - * - * @return static This query instance. - */ - public function setFetchMode($class, $assocName, $fetchMode) - { - if ($fetchMode !== Mapping\ClassMetadata::FETCH_EAGER) { - $fetchMode = Mapping\ClassMetadata::FETCH_LAZY; - } - - $this->_hints['fetchMode'][$class][$assocName] = $fetchMode; - - return $this; - } - - /** - * Defines the processing mode to be used during hydration / result set transformation. - * - * @param string|int $hydrationMode Doctrine processing mode to be used during hydration process. - * One of the Query::HYDRATE_* constants. - * - * @return static This query instance. - */ - public function setHydrationMode($hydrationMode) - { - $this->_hydrationMode = $hydrationMode; - - return $this; - } - - /** - * Gets the hydration mode currently used by the query. - * - * @return string|int - */ - public function getHydrationMode() - { - return $this->_hydrationMode; - } - - /** - * Gets the list of results for the query. - * - * Alias for execute(null, $hydrationMode = HYDRATE_OBJECT). - * - * @param string|int $hydrationMode - * - * @return mixed - */ - public function getResult($hydrationMode = self::HYDRATE_OBJECT) - { - return $this->execute(null, $hydrationMode); - } - - /** - * Gets the array of results for the query. - * - * Alias for execute(null, HYDRATE_ARRAY). - * - * @return array - */ - public function getArrayResult() - { - return $this->execute(null, self::HYDRATE_ARRAY); - } - - /** - * Gets the scalar results for the query. - * - * Alias for execute(null, HYDRATE_SCALAR). - * - * @return array - */ - public function getScalarResult() - { - return $this->execute(null, self::HYDRATE_SCALAR); - } - - /** - * Get exactly one result or null. - * - * @param string|int $hydrationMode - * - * @return mixed - * - * @throws NonUniqueResultException - */ - public function getOneOrNullResult($hydrationMode = null) - { - try { - $result = $this->execute(null, $hydrationMode); - } catch (NoResultException $e) { - return null; - } - - - if ($this->_hydrationMode !== self::HYDRATE_SINGLE_SCALAR && ! $result) { - return null; - } - - if ( ! is_array($result)) { - return $result; - } - - if (count($result) > 1) { - throw new NonUniqueResultException; - } - - return array_shift($result); - } - - /** - * Gets the single result of the query. - * - * Enforces the presence as well as the uniqueness of the result. - * - * If the result is not unique, a NonUniqueResultException is thrown. - * If there is no result, a NoResultException is thrown. - * - * @param string|int $hydrationMode - * - * @return mixed - * - * @throws NonUniqueResultException If the query result is not unique. - * @throws NoResultException If the query returned no result and hydration mode is not HYDRATE_SINGLE_SCALAR. - */ - public function getSingleResult($hydrationMode = null) - { - $result = $this->execute(null, $hydrationMode); - - if ($this->_hydrationMode !== self::HYDRATE_SINGLE_SCALAR && ! $result) { - throw new NoResultException; - } - - if ( ! is_array($result)) { - return $result; - } - - if (count($result) > 1) { - throw new NonUniqueResultException; - } - - return array_shift($result); - } - - /** - * Gets the single scalar result of the query. - * - * Alias for getSingleResult(HYDRATE_SINGLE_SCALAR). - * - * @return mixed The scalar result. - * - * @throws NoResultException If the query returned no result. - * @throws NonUniqueResultException If the query result is not unique. - */ - public function getSingleScalarResult() - { - return $this->getSingleResult(self::HYDRATE_SINGLE_SCALAR); - } - - /** - * Sets a query hint. If the hint name is not recognized, it is silently ignored. - * - * @param string $name The name of the hint. - * @param mixed $value The value of the hint. - * - * @return static This query instance. - */ - public function setHint($name, $value) - { - $this->_hints[$name] = $value; - - return $this; - } - - /** - * Gets the value of a query hint. If the hint name is not recognized, FALSE is returned. - * - * @param string $name The name of the hint. - * - * @return mixed The value of the hint or FALSE, if the hint name is not recognized. - */ - public function getHint($name) - { - return isset($this->_hints[$name]) ? $this->_hints[$name] : false; - } - - /** - * Check if the query has a hint - * - * @param string $name The name of the hint - * - * @return bool False if the query does not have any hint - */ - public function hasHint($name) - { - return isset($this->_hints[$name]); - } - - /** - * Return the key value map of query hints that are currently set. - * - * @return array - */ - public function getHints() - { - return $this->_hints; - } - - /** - * Executes the query and returns an IterableResult that can be used to incrementally - * iterate over the result. - * - * @param ArrayCollection|array|null $parameters The query parameters. - * @param string|int|null $hydrationMode The hydration mode to use. - * - * @return \Doctrine\ORM\Internal\Hydration\IterableResult - */ - public function iterate($parameters = null, $hydrationMode = null) - { - if ($hydrationMode !== null) { - $this->setHydrationMode($hydrationMode); - } - - if ( ! empty($parameters)) { - $this->setParameters($parameters); - } - - $rsm = $this->getResultSetMapping(); - $stmt = $this->_doExecute(); - - return $this->_em->newHydrator($this->_hydrationMode)->iterate($stmt, $rsm, $this->_hints); - } - - /** - * Executes the query. - * - * @param ArrayCollection|array|null $parameters Query parameters. - * @param string|int|null $hydrationMode Processing mode to be used during the hydration process. - * - * @return mixed - */ - public function execute($parameters = null, $hydrationMode = null) - { - if ($this->cacheable && $this->isCacheEnabled()) { - return $this->executeUsingQueryCache($parameters, $hydrationMode); - } - - return $this->executeIgnoreQueryCache($parameters, $hydrationMode); - } - - /** - * Execute query ignoring second level cache. - * - * @param ArrayCollection|array|null $parameters - * @param string|int|null $hydrationMode - * - * @return mixed - */ - private function executeIgnoreQueryCache($parameters = null, $hydrationMode = null) - { - if ($hydrationMode !== null) { - $this->setHydrationMode($hydrationMode); - } - - if ( ! empty($parameters)) { - $this->setParameters($parameters); - } - - $setCacheEntry = function() {}; - - if ($this->_hydrationCacheProfile !== null) { - list($cacheKey, $realCacheKey) = $this->getHydrationCacheId(); - - $queryCacheProfile = $this->getHydrationCacheProfile(); - $cache = $queryCacheProfile->getResultCacheDriver(); - $result = $cache->fetch($cacheKey); - - if (isset($result[$realCacheKey])) { - return $result[$realCacheKey]; - } - - if ( ! $result) { - $result = []; - } - - $setCacheEntry = function($data) use ($cache, $result, $cacheKey, $realCacheKey, $queryCacheProfile) { - $result[$realCacheKey] = $data; - - $cache->save($cacheKey, $result, $queryCacheProfile->getLifetime()); - }; - } - - $stmt = $this->_doExecute(); - - if (is_numeric($stmt)) { - $setCacheEntry($stmt); - - return $stmt; - } - - $rsm = $this->getResultSetMapping(); - $data = $this->_em->newHydrator($this->_hydrationMode)->hydrateAll($stmt, $rsm, $this->_hints); - - $setCacheEntry($data); - - return $data; - } - - /** - * Load from second level cache or executes the query and put into cache. - * - * @param ArrayCollection|array|null $parameters - * @param string|int|null $hydrationMode - * - * @return mixed - */ - private function executeUsingQueryCache($parameters = null, $hydrationMode = null) - { - $rsm = $this->getResultSetMapping(); - $queryCache = $this->_em->getCache()->getQueryCache($this->cacheRegion); - $queryKey = new QueryCacheKey( - $this->getHash(), - $this->lifetime, - $this->cacheMode ?: Cache::MODE_NORMAL, - $this->getTimestampKey() - ); - - $result = $queryCache->get($queryKey, $rsm, $this->_hints); - - if ($result !== null) { - if ($this->cacheLogger) { - $this->cacheLogger->queryCacheHit($queryCache->getRegion()->getName(), $queryKey); - } - - return $result; - } - - $result = $this->executeIgnoreQueryCache($parameters, $hydrationMode); - $cached = $queryCache->put($queryKey, $rsm, $result, $this->_hints); - - if ($this->cacheLogger) { - $this->cacheLogger->queryCacheMiss($queryCache->getRegion()->getName(), $queryKey); - - if ($cached) { - $this->cacheLogger->queryCachePut($queryCache->getRegion()->getName(), $queryKey); - } - } - - return $result; - } - - /** - * @return \Doctrine\ORM\Cache\TimestampCacheKey|null - */ - private function getTimestampKey() - { - $entityName = reset($this->_resultSetMapping->aliasMap); - - if (empty($entityName)) { - return null; - } - - $metadata = $this->_em->getClassMetadata($entityName); - - return new Cache\TimestampCacheKey($metadata->rootEntityName); - } - - /** - * Get the result cache id to use to store the result set cache entry. - * Will return the configured id if it exists otherwise a hash will be - * automatically generated for you. - * - * @return array ($key, $hash) - */ - protected function getHydrationCacheId() - { - $parameters = []; - - foreach ($this->getParameters() as $parameter) { - $parameters[$parameter->getName()] = $this->processParameterValue($parameter->getValue()); - } - - $sql = $this->getSQL(); - $queryCacheProfile = $this->getHydrationCacheProfile(); - $hints = $this->getHints(); - $hints['hydrationMode'] = $this->getHydrationMode(); - - ksort($hints); - - return $queryCacheProfile->generateCacheKeys($sql, $parameters, $hints); - } - - /** - * Set the result cache id to use to store the result set cache entry. - * If this is not explicitly set by the developer then a hash is automatically - * generated for you. - * - * @param string $id - * - * @return static This query instance. - */ - public function setResultCacheId($id) - { - $this->_queryCacheProfile = $this->_queryCacheProfile - ? $this->_queryCacheProfile->setCacheKey($id) - : new QueryCacheProfile(0, $id, $this->_em->getConfiguration()->getResultCacheImpl()); - - return $this; - } - - /** - * Get the result cache id to use to store the result set cache entry if set. - * - * @deprecated - * - * @return string - */ - public function getResultCacheId() - { - return $this->_queryCacheProfile ? $this->_queryCacheProfile->getCacheKey() : null; - } - - /** - * Executes the query and returns a the resulting Statement object. - * - * @return \Doctrine\DBAL\Driver\Statement The executed database statement that holds the results. - */ - abstract protected function _doExecute(); - - /** - * Cleanup Query resource when clone is called. - * - * @return void - */ - public function __clone() - { - $this->parameters = new ArrayCollection(); - - $this->_hints = []; - $this->_hints = $this->_em->getConfiguration()->getDefaultQueryHints(); - } - - /** - * Generates a string of currently query to use for the cache second level cache. - * - * @return string - */ - protected function getHash() - { - $query = $this->getSQL(); - $hints = $this->getHints(); - $params = array_map(function(Parameter $parameter) { - // Small optimization - // Does not invoke processParameterValue for scalar values - if (is_scalar($value = $parameter->getValue())) { - return $value; - } - - return $this->processParameterValue($value); - }, $this->parameters->getValues()); - - ksort($hints); - - return sha1($query . '-' . serialize($params) . '-' . serialize($hints)); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache.php deleted file mode 100644 index 3da7c05..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache.php +++ /dev/null @@ -1,178 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -/** - * Provides an API for querying/managing the second level cache regions. - * - * @since 2.5 - * @author Fabio B. Silva - */ -interface Cache -{ - const DEFAULT_QUERY_REGION_NAME = 'query_cache_region'; - - const DEFAULT_TIMESTAMP_REGION_NAME = 'timestamp_cache_region'; - - /** - * May read items from the cache, but will not add items. - */ - const MODE_GET = 1; - - /** - * Will never read items from the cache, - * but will add items to the cache as it reads them from the database. - */ - const MODE_PUT = 2; - - /** - * May read items from the cache, and add items to the cache. - */ - const MODE_NORMAL = 3; - - /** - * The query will never read items from the cache, - * but will refresh items to the cache as it reads them from the database. - */ - const MODE_REFRESH = 4; - - /** - * @param string $className The entity class. - * - * @return \Doctrine\ORM\Cache\Region|null - */ - public function getEntityCacheRegion($className); - - /** - * @param string $className The entity class. - * @param string $association The field name that represents the association. - * - * @return \Doctrine\ORM\Cache\Region|null - */ - public function getCollectionCacheRegion($className, $association); - - /** - * Determine whether the cache contains data for the given entity "instance". - * - * @param string $className The entity class. - * @param mixed $identifier The entity identifier - * - * @return boolean true if the underlying cache contains corresponding data; false otherwise. - */ - public function containsEntity($className, $identifier); - - /** - * Evicts the entity data for a particular entity "instance". - * - * @param string $className The entity class. - * @param mixed $identifier The entity identifier. - * - * @return void - */ - public function evictEntity($className, $identifier); - - /** - * Evicts all entity data from the given region. - * - * @param string $className The entity metadata. - * - * @return void - */ - public function evictEntityRegion($className); - - /** - * Evict data from all entity regions. - * - * @return void - */ - public function evictEntityRegions(); - - /** - * Determine whether the cache contains data for the given collection. - * - * @param string $className The entity class. - * @param string $association The field name that represents the association. - * @param mixed $ownerIdentifier The identifier of the owning entity. - * - * @return boolean true if the underlying cache contains corresponding data; false otherwise. - */ - public function containsCollection($className, $association, $ownerIdentifier); - - /** - * Evicts the cache data for the given identified collection instance. - * - * @param string $className The entity class. - * @param string $association The field name that represents the association. - * @param mixed $ownerIdentifier The identifier of the owning entity. - * - * @return void - */ - public function evictCollection($className, $association, $ownerIdentifier); - - /** - * Evicts all entity data from the given region. - * - * @param string $className The entity class. - * @param string $association The field name that represents the association. - * - * @return void - */ - public function evictCollectionRegion($className, $association); - - /** - * Evict data from all collection regions. - * - * @return void - */ - public function evictCollectionRegions(); - - /** - * Determine whether the cache contains data for the given query. - * - * @param string $regionName The cache name given to the query. - * - * @return boolean true if the underlying cache contains corresponding data; false otherwise. - */ - public function containsQuery($regionName); - - /** - * Evicts all cached query results under the given name, or default query cache if the region name is NULL. - * - * @param string|null $regionName The cache name associated to the queries being cached. - */ - public function evictQueryRegion($regionName = null); - - /** - * Evict data from all query regions. - * - * @return void - */ - public function evictQueryRegions(); - - /** - * Get query cache by region name or create a new one if none exist. - * - * @param string|null $regionName Query cache region name, or default query cache if the region name is NULL. - * - * @return \Doctrine\ORM\Cache\QueryCache The Query Cache associated with the region name. - */ - public function getQueryCache($regionName = null); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/AssociationCacheEntry.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/AssociationCacheEntry.php deleted file mode 100644 index dae5e60..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/AssociationCacheEntry.php +++ /dev/null @@ -1,68 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Association cache entry - * - * @since 2.5 - * @author Fabio B. Silva - */ -class AssociationCacheEntry implements CacheEntry -{ - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var array The entity identifier - */ - public $identifier; - - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var string The entity class name - */ - public $class; - - /** - * @param string $class The entity class. - * @param array $identifier The entity identifier. - */ - public function __construct($class, array $identifier) - { - $this->class = $class; - $this->identifier = $identifier; - } - - /** - * Creates a new AssociationCacheEntry - * - * This method allow Doctrine\Common\Cache\PhpFileCache compatibility - * - * @param array $values array containing property values - * - * @return AssociationCacheEntry - */ - public static function __set_state(array $values) - { - return new self($values['class'], $values['identifier']); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheConfiguration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheConfiguration.php deleted file mode 100644 index eb3ec42..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheConfiguration.php +++ /dev/null @@ -1,128 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -use Doctrine\ORM\Cache\Logging\CacheLogger; - -/** - * Configuration container for second-level cache. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class CacheConfiguration -{ - /** - * @var \Doctrine\ORM\Cache\CacheFactory|null - */ - private $cacheFactory; - - /** - * @var \Doctrine\ORM\Cache\RegionsConfiguration|null - */ - private $regionsConfig; - - /** - * @var \Doctrine\ORM\Cache\Logging\CacheLogger|null - */ - private $cacheLogger; - - /** - * @var \Doctrine\ORM\Cache\QueryCacheValidator|null - */ - private $queryValidator; - - /** - * @return \Doctrine\ORM\Cache\CacheFactory|null - */ - public function getCacheFactory() - { - return $this->cacheFactory; - } - - /** - * @param \Doctrine\ORM\Cache\CacheFactory $factory - * - * @return void - */ - public function setCacheFactory(CacheFactory $factory) - { - $this->cacheFactory = $factory; - } - - /** - * @return \Doctrine\ORM\Cache\Logging\CacheLogger|null - */ - public function getCacheLogger() - { - return $this->cacheLogger; - } - - /** - * @param \Doctrine\ORM\Cache\Logging\CacheLogger $logger - */ - public function setCacheLogger(CacheLogger $logger) - { - $this->cacheLogger = $logger; - } - - /** - * @return \Doctrine\ORM\Cache\RegionsConfiguration - */ - public function getRegionsConfiguration() - { - if ($this->regionsConfig === null) { - $this->regionsConfig = new RegionsConfiguration(); - } - - return $this->regionsConfig; - } - - /** - * @param \Doctrine\ORM\Cache\RegionsConfiguration $regionsConfig - */ - public function setRegionsConfiguration(RegionsConfiguration $regionsConfig) - { - $this->regionsConfig = $regionsConfig; - } - - /** - * @return \Doctrine\ORM\Cache\QueryCacheValidator - */ - public function getQueryValidator() - { - if ($this->queryValidator === null) { - $this->queryValidator = new TimestampQueryCacheValidator( - $this->cacheFactory->getTimestampRegion() - ); - } - - return $this->queryValidator; - } - - /** - * @param \Doctrine\ORM\Cache\QueryCacheValidator $validator - */ - public function setQueryValidator(QueryCacheValidator $validator) - { - $this->queryValidator = $validator; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheEntry.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheEntry.php deleted file mode 100644 index c34b0ff..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheEntry.php +++ /dev/null @@ -1,36 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Cache entry interface - * - * IMPORTANT NOTE: - * - * Fields of classes that implement CacheEntry are public for performance reason. - * - * @since 2.5 - * @author Fabio B. Silva - */ -interface CacheEntry -{ - -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheException.php deleted file mode 100644 index 315a8aa..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheException.php +++ /dev/null @@ -1,73 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -use Doctrine\ORM\ORMException; - -/** - * Exception for cache. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class CacheException extends ORMException -{ - /** - * @param string $sourceEntity - * @param string $fieldName - * - * @return \Doctrine\ORM\Cache\CacheException - */ - public static function updateReadOnlyCollection($sourceEntity, $fieldName) - { - return new self(sprintf('Cannot update a readonly collection "%s#%s"', $sourceEntity, $fieldName)); - } - - /** - * @param string $entityName - * - * @return \Doctrine\ORM\Cache\CacheException - */ - public static function updateReadOnlyEntity($entityName) - { - return new self(sprintf('Cannot update a readonly entity "%s"', $entityName)); - } - - /** - * @param string $entityName - * - * @return \Doctrine\ORM\Cache\CacheException - */ - public static function nonCacheableEntity($entityName) - { - return new self(sprintf('Entity "%s" not configured as part of the second-level cache.', $entityName)); - } - - /** - * @param string $entityName - * @param string $field - * - * @return CacheException - */ - public static function nonCacheableEntityAssociation($entityName, $field) - { - return new self(sprintf('Entity association field "%s#%s" not configured as part of the second-level cache.', $entityName, $field)); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheFactory.php deleted file mode 100644 index b915100..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheFactory.php +++ /dev/null @@ -1,112 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Persisters\Collection\CollectionPersister; -use Doctrine\ORM\Persisters\Entity\EntityPersister; - -/** - * Contract for building second level cache regions components. - * - * @since 2.5 - * @author Fabio B. Silva - */ -interface CacheFactory -{ - /** - * Build an entity persister for the given entity metadata. - * - * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. - * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $persister The entity persister that will be cached. - * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. - * - * @return \Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister - */ - public function buildCachedEntityPersister(EntityManagerInterface $em, EntityPersister $persister, ClassMetadata $metadata); - - /** - * Build a collection persister for the given relation mapping. - * - * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. - * @param \Doctrine\ORM\Persisters\Collection\CollectionPersister $persister The collection persister that will be cached. - * @param array $mapping The association mapping. - * - * @return \Doctrine\ORM\Cache\Persister\Collection\CachedCollectionPersister - */ - public function buildCachedCollectionPersister(EntityManagerInterface $em, CollectionPersister $persister, array $mapping); - - /** - * Build a query cache based on the given region name - * - * @param \Doctrine\ORM\EntityManagerInterface $em The Entity manager. - * @param string $regionName The region name. - * - * @return \Doctrine\ORM\Cache\QueryCache The built query cache. - */ - public function buildQueryCache(EntityManagerInterface $em, $regionName = null); - - /** - * Build an entity hydrator - * - * @param \Doctrine\ORM\EntityManagerInterface $em The Entity manager. - * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. - * - * @return \Doctrine\ORM\Cache\EntityHydrator The built entity hydrator. - */ - public function buildEntityHydrator(EntityManagerInterface $em, ClassMetadata $metadata); - - /** - * Build a collection hydrator - * - * @param \Doctrine\ORM\EntityManagerInterface $em The Entity manager. - * @param array $mapping The association mapping. - * - * @return \Doctrine\ORM\Cache\CollectionHydrator The built collection hydrator. - */ - public function buildCollectionHydrator(EntityManagerInterface $em, array $mapping); - - /** - * Build a cache region - * - * @param array $cache The cache configuration. - * - * @return \Doctrine\ORM\Cache\Region The cache region. - */ - public function getRegion(array $cache); - - /** - * Build timestamp cache region - * - * @return \Doctrine\ORM\Cache\TimestampRegion The timestamp region. - */ - public function getTimestampRegion(); - - /** - * Build \Doctrine\ORM\Cache - * - * @param EntityManagerInterface $entityManager - * - * @return \Doctrine\ORM\Cache - */ - public function createCache(EntityManagerInterface $entityManager); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheKey.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheKey.php deleted file mode 100644 index 1641c99..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CacheKey.php +++ /dev/null @@ -1,38 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Defines entity / collection / query key to be stored in the cache region. - * Allows multiple roles to be stored in the same cache region. - * - * @since 2.5 - * @author Fabio B. Silva - */ -abstract class CacheKey -{ - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var string Unique identifier - */ - public $hash; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheEntry.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheEntry.php deleted file mode 100644 index b3a1def..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheEntry.php +++ /dev/null @@ -1,59 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Collection cache entry - * - * @since 2.5 - * @author Fabio B. Silva - */ -class CollectionCacheEntry implements CacheEntry -{ - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var CacheKey[] The list of entity identifiers hold by the collection - */ - public $identifiers; - - /** - * @param CacheKey[] $identifiers List of entity identifiers hold by the collection - */ - public function __construct(array $identifiers) - { - $this->identifiers = $identifiers; - } - - /** - * Creates a new CollectionCacheEntry - * - * This method allows for Doctrine\Common\Cache\PhpFileCache compatibility - * - * @param array $values array containing property values - * - * @return CollectionCacheEntry - */ - public static function __set_state(array $values) - { - return new self($values['identifiers']); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheKey.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheKey.php deleted file mode 100644 index 6b63145..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionCacheKey.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Defines entity collection roles to be stored in the cache region. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class CollectionCacheKey extends CacheKey -{ - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var array The owner entity identifier - */ - public $ownerIdentifier; - - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var string The owner entity class - */ - public $entityClass; - - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var string The association name - */ - public $association; - - /** - * @param string $entityClass The entity class. - * @param string $association The field name that represents the association. - * @param array $ownerIdentifier The identifier of the owning entity. - */ - public function __construct($entityClass, $association, array $ownerIdentifier) - { - ksort($ownerIdentifier); - - $this->ownerIdentifier = $ownerIdentifier; - $this->entityClass = (string) $entityClass; - $this->association = (string) $association; - $this->hash = str_replace('\\', '.', strtolower($entityClass)) . '_' . implode(' ', $ownerIdentifier) . '__' . $association; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionHydrator.php deleted file mode 100644 index 04cdde1..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/CollectionHydrator.php +++ /dev/null @@ -1,52 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -use Doctrine\ORM\PersistentCollection; -use Doctrine\ORM\Mapping\ClassMetadata; - -/** - * Hydrator cache entry for collections - * - * @since 2.5 - * @author Fabio B. Silva - */ -interface CollectionHydrator -{ - /** - * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. - * @param \Doctrine\ORM\Cache\CollectionCacheKey $key The cached collection key. - * @param array|\Doctrine\Common\Collections\Collection $collection The collection. - * - * @return \Doctrine\ORM\Cache\CollectionCacheEntry - */ - public function buildCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, $collection); - - /** - * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The owning entity metadata. - * @param \Doctrine\ORM\Cache\CollectionCacheKey $key The cached collection key. - * @param \Doctrine\ORM\Cache\CollectionCacheEntry $entry The cached collection entry. - * @param \Doctrine\ORM\PersistentCollection $collection The collection to load the cache into. - * - * @return array - */ - public function loadCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, CollectionCacheEntry $entry, PersistentCollection $collection); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/ConcurrentRegion.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/ConcurrentRegion.php deleted file mode 100644 index 12da6d6..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/ConcurrentRegion.php +++ /dev/null @@ -1,57 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Defines contract for concurrently managed data region. - * It should be able to lock an specific cache entry in an atomic operation. - * - * When a entry is locked another process should not be able to read or write the entry. - * All evict operation should not consider locks, even though an entry is locked evict should be able to delete the entry and its lock. - * - * @since 2.5 - * @author Fabio B. Silva - */ -interface ConcurrentRegion extends Region -{ - /** - * Attempts to read lock the mapping for the given key. - * - * @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to lock. - * - * @return \Doctrine\ORM\Cache\Lock A lock instance or NULL if the lock already exists. - * - * @throws \Doctrine\ORM\Cache\LockException Indicates a problem accessing the region. - */ - public function lock(CacheKey $key); - - /** - * Attempts to read unlock the mapping for the given key. - * - * @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to unlock. - * @param \Doctrine\ORM\Cache\Lock $lock The lock previously obtained from {@link readLock} - * - * @return void - * - * @throws \Doctrine\ORM\Cache\LockException Indicates a problem accessing the region. - */ - public function unlock(CacheKey $key, Lock $lock); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCache.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCache.php deleted file mode 100644 index 80fbd81..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCache.php +++ /dev/null @@ -1,342 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -use Doctrine\ORM\Cache; -use Doctrine\Common\Util\ClassUtils; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Cache\Persister\CachedPersister; -use Doctrine\ORM\ORMInvalidArgumentException; - -/** - * Provides an API for querying/managing the second level cache regions. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class DefaultCache implements Cache -{ - /** - * @var \Doctrine\ORM\EntityManagerInterface - */ - private $em; - - /** - * @var \Doctrine\ORM\UnitOfWork - */ - private $uow; - - /** - * @var \Doctrine\ORM\Cache\CacheFactory - */ - private $cacheFactory; - - /** - * @var \Doctrine\ORM\Cache\QueryCache[] - */ - private $queryCaches = []; - - /** - * @var \Doctrine\ORM\Cache\QueryCache - */ - private $defaultQueryCache; - - /** - * {@inheritdoc} - */ - public function __construct(EntityManagerInterface $em) - { - $this->em = $em; - $this->uow = $em->getUnitOfWork(); - $this->cacheFactory = $em->getConfiguration() - ->getSecondLevelCacheConfiguration() - ->getCacheFactory(); - } - - /** - * {@inheritdoc} - */ - public function getEntityCacheRegion($className) - { - $metadata = $this->em->getClassMetadata($className); - $persister = $this->uow->getEntityPersister($metadata->rootEntityName); - - if ( ! ($persister instanceof CachedPersister)) { - return null; - } - - return $persister->getCacheRegion(); - } - - /** - * {@inheritdoc} - */ - public function getCollectionCacheRegion($className, $association) - { - $metadata = $this->em->getClassMetadata($className); - $persister = $this->uow->getCollectionPersister($metadata->getAssociationMapping($association)); - - if ( ! ($persister instanceof CachedPersister)) { - return null; - } - - return $persister->getCacheRegion(); - } - - /** - * {@inheritdoc} - */ - public function containsEntity($className, $identifier) - { - $metadata = $this->em->getClassMetadata($className); - $persister = $this->uow->getEntityPersister($metadata->rootEntityName); - - if ( ! ($persister instanceof CachedPersister)) { - return false; - } - - return $persister->getCacheRegion()->contains($this->buildEntityCacheKey($metadata, $identifier)); - } - - /** - * {@inheritdoc} - */ - public function evictEntity($className, $identifier) - { - $metadata = $this->em->getClassMetadata($className); - $persister = $this->uow->getEntityPersister($metadata->rootEntityName); - - if ( ! ($persister instanceof CachedPersister)) { - return; - } - - $persister->getCacheRegion()->evict($this->buildEntityCacheKey($metadata, $identifier)); - } - - /** - * {@inheritdoc} - */ - public function evictEntityRegion($className) - { - $metadata = $this->em->getClassMetadata($className); - $persister = $this->uow->getEntityPersister($metadata->rootEntityName); - - if ( ! ($persister instanceof CachedPersister)) { - return; - } - - $persister->getCacheRegion()->evictAll(); - } - - /** - * {@inheritdoc} - */ - public function evictEntityRegions() - { - $metadatas = $this->em->getMetadataFactory()->getAllMetadata(); - - foreach ($metadatas as $metadata) { - $persister = $this->uow->getEntityPersister($metadata->rootEntityName); - - if ( ! ($persister instanceof CachedPersister)) { - continue; - } - - $persister->getCacheRegion()->evictAll(); - } - } - - /** - * {@inheritdoc} - */ - public function containsCollection($className, $association, $ownerIdentifier) - { - $metadata = $this->em->getClassMetadata($className); - $persister = $this->uow->getCollectionPersister($metadata->getAssociationMapping($association)); - - if ( ! ($persister instanceof CachedPersister)) { - return false; - } - - return $persister->getCacheRegion()->contains($this->buildCollectionCacheKey($metadata, $association, $ownerIdentifier)); - } - - /** - * {@inheritdoc} - */ - public function evictCollection($className, $association, $ownerIdentifier) - { - $metadata = $this->em->getClassMetadata($className); - $persister = $this->uow->getCollectionPersister($metadata->getAssociationMapping($association)); - - if ( ! ($persister instanceof CachedPersister)) { - return; - } - - $persister->getCacheRegion()->evict($this->buildCollectionCacheKey($metadata, $association, $ownerIdentifier)); - } - - /** - * {@inheritdoc} - */ - public function evictCollectionRegion($className, $association) - { - $metadata = $this->em->getClassMetadata($className); - $persister = $this->uow->getCollectionPersister($metadata->getAssociationMapping($association)); - - if ( ! ($persister instanceof CachedPersister)) { - return; - } - - $persister->getCacheRegion()->evictAll(); - } - - /** - * {@inheritdoc} - */ - public function evictCollectionRegions() - { - $metadatas = $this->em->getMetadataFactory()->getAllMetadata(); - - foreach ($metadatas as $metadata) { - - foreach ($metadata->associationMappings as $association) { - - if ( ! $association['type'] & ClassMetadata::TO_MANY) { - continue; - } - - $persister = $this->uow->getCollectionPersister($association); - - if ( ! ($persister instanceof CachedPersister)) { - continue; - } - - $persister->getCacheRegion()->evictAll(); - } - } - } - - /** - * {@inheritdoc} - */ - public function containsQuery($regionName) - { - return isset($this->queryCaches[$regionName]); - } - - /** - * {@inheritdoc} - */ - public function evictQueryRegion($regionName = null) - { - if ($regionName === null && $this->defaultQueryCache !== null) { - $this->defaultQueryCache->clear(); - - return; - } - - if (isset($this->queryCaches[$regionName])) { - $this->queryCaches[$regionName]->clear(); - } - } - - /** - * {@inheritdoc} - */ - public function evictQueryRegions() - { - $this->getQueryCache()->clear(); - - foreach ($this->queryCaches as $queryCache) { - $queryCache->clear(); - } - } - - /** - * {@inheritdoc} - */ - public function getQueryCache($regionName = null) - { - if ($regionName === null) { - return $this->defaultQueryCache ?: - $this->defaultQueryCache = $this->cacheFactory->buildQueryCache($this->em); - } - - if ( ! isset($this->queryCaches[$regionName])) { - $this->queryCaches[$regionName] = $this->cacheFactory->buildQueryCache($this->em, $regionName); - } - - return $this->queryCaches[$regionName]; - } - - /** - * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. - * @param mixed $identifier The entity identifier. - * - * @return \Doctrine\ORM\Cache\EntityCacheKey - */ - private function buildEntityCacheKey(ClassMetadata $metadata, $identifier) - { - if ( ! is_array($identifier)) { - $identifier = $this->toIdentifierArray($metadata, $identifier); - } - - return new EntityCacheKey($metadata->rootEntityName, $identifier); - } - - /** - * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. - * @param string $association The field name that represents the association. - * @param mixed $ownerIdentifier The identifier of the owning entity. - * - * @return \Doctrine\ORM\Cache\CollectionCacheKey - */ - private function buildCollectionCacheKey(ClassMetadata $metadata, $association, $ownerIdentifier) - { - if ( ! is_array($ownerIdentifier)) { - $ownerIdentifier = $this->toIdentifierArray($metadata, $ownerIdentifier); - } - - return new CollectionCacheKey($metadata->rootEntityName, $association, $ownerIdentifier); - } - - /** - * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. - * @param mixed $identifier The entity identifier. - * - * @return array - */ - private function toIdentifierArray(ClassMetadata $metadata, $identifier) - { - if (is_object($identifier) && $this->em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($identifier))) { - $identifier = $this->uow->getSingleIdentifierValue($identifier); - - if ($identifier === null) { - throw ORMInvalidArgumentException::invalidIdentifierBindingEntity(); - } - } - - return [$metadata->identifier[0] => $identifier]; - } - -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCacheFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCacheFactory.php deleted file mode 100644 index bfc6aa2..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCacheFactory.php +++ /dev/null @@ -1,275 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -use Doctrine\Common\Cache\Cache as CacheAdapter; -use Doctrine\Common\Cache\CacheProvider; -use Doctrine\Common\Cache\MultiGetCache; -use Doctrine\ORM\Cache; -use Doctrine\ORM\Cache\Persister\Collection\NonStrictReadWriteCachedCollectionPersister; -use Doctrine\ORM\Cache\Persister\Collection\ReadOnlyCachedCollectionPersister; -use Doctrine\ORM\Cache\Persister\Collection\ReadWriteCachedCollectionPersister; -use Doctrine\ORM\Cache\Persister\Entity\NonStrictReadWriteCachedEntityPersister; -use Doctrine\ORM\Cache\Persister\Entity\ReadOnlyCachedEntityPersister; -use Doctrine\ORM\Cache\Persister\Entity\ReadWriteCachedEntityPersister; -use Doctrine\ORM\Cache\Region\DefaultMultiGetRegion; -use Doctrine\ORM\Cache\Region\DefaultRegion; -use Doctrine\ORM\Cache\Region\FileLockRegion; -use Doctrine\ORM\Cache\Region\UpdateTimestampCache; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Persisters\Collection\CollectionPersister; -use Doctrine\ORM\Persisters\Entity\EntityPersister; - -/** - * @since 2.5 - * @author Fabio B. Silva - */ -class DefaultCacheFactory implements CacheFactory -{ - /** - * @var CacheAdapter - */ - private $cache; - - /** - * @var \Doctrine\ORM\Cache\RegionsConfiguration - */ - private $regionsConfig; - - /** - * @var \Doctrine\ORM\Cache\TimestampRegion|null - */ - private $timestampRegion; - - /** - * @var \Doctrine\ORM\Cache\Region[] - */ - private $regions = []; - - /** - * @var string|null - */ - private $fileLockRegionDirectory; - - /** - * @param RegionsConfiguration $cacheConfig - * @param CacheAdapter $cache - */ - public function __construct(RegionsConfiguration $cacheConfig, CacheAdapter $cache) - { - $this->cache = $cache; - $this->regionsConfig = $cacheConfig; - } - - /** - * @param string $fileLockRegionDirectory - */ - public function setFileLockRegionDirectory($fileLockRegionDirectory) - { - $this->fileLockRegionDirectory = (string) $fileLockRegionDirectory; - } - - /** - * @return string - */ - public function getFileLockRegionDirectory() - { - return $this->fileLockRegionDirectory; - } - - /** - * @param \Doctrine\ORM\Cache\Region $region - */ - public function setRegion(Region $region) - { - $this->regions[$region->getName()] = $region; - } - - /** - * @param \Doctrine\ORM\Cache\TimestampRegion $region - */ - public function setTimestampRegion(TimestampRegion $region) - { - $this->timestampRegion = $region; - } - - /** - * {@inheritdoc} - */ - public function buildCachedEntityPersister(EntityManagerInterface $em, EntityPersister $persister, ClassMetadata $metadata) - { - $region = $this->getRegion($metadata->cache); - $usage = $metadata->cache['usage']; - - if ($usage === ClassMetadata::CACHE_USAGE_READ_ONLY) { - return new ReadOnlyCachedEntityPersister($persister, $region, $em, $metadata); - } - - if ($usage === ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE) { - return new NonStrictReadWriteCachedEntityPersister($persister, $region, $em, $metadata); - } - - if ($usage === ClassMetadata::CACHE_USAGE_READ_WRITE) { - return new ReadWriteCachedEntityPersister($persister, $region, $em, $metadata); - } - - throw new \InvalidArgumentException(sprintf("Unrecognized access strategy type [%s]", $usage)); - } - - /** - * {@inheritdoc} - */ - public function buildCachedCollectionPersister(EntityManagerInterface $em, CollectionPersister $persister, array $mapping) - { - $usage = $mapping['cache']['usage']; - $region = $this->getRegion($mapping['cache']); - - if ($usage === ClassMetadata::CACHE_USAGE_READ_ONLY) { - return new ReadOnlyCachedCollectionPersister($persister, $region, $em, $mapping); - } - - if ($usage === ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE) { - return new NonStrictReadWriteCachedCollectionPersister($persister, $region, $em, $mapping); - } - - if ($usage === ClassMetadata::CACHE_USAGE_READ_WRITE) { - return new ReadWriteCachedCollectionPersister($persister, $region, $em, $mapping); - } - - throw new \InvalidArgumentException(sprintf("Unrecognized access strategy type [%s]", $usage)); - } - - /** - * {@inheritdoc} - */ - public function buildQueryCache(EntityManagerInterface $em, $regionName = null) - { - return new DefaultQueryCache( - $em, - $this->getRegion( - [ - 'region' => $regionName ?: Cache::DEFAULT_QUERY_REGION_NAME, - 'usage' => ClassMetadata::CACHE_USAGE_NONSTRICT_READ_WRITE - ] - ) - ); - } - - /** - * {@inheritdoc} - */ - public function buildCollectionHydrator(EntityManagerInterface $em, array $mapping) - { - return new DefaultCollectionHydrator($em); - } - - /** - * {@inheritdoc} - */ - public function buildEntityHydrator(EntityManagerInterface $em, ClassMetadata $metadata) - { - return new DefaultEntityHydrator($em); - } - - /** - * {@inheritdoc} - */ - public function getRegion(array $cache) - { - if (isset($this->regions[$cache['region']])) { - return $this->regions[$cache['region']]; - } - - $name = $cache['region']; - $cacheAdapter = $this->createRegionCache($name); - $lifetime = $this->regionsConfig->getLifetime($cache['region']); - - $region = ($cacheAdapter instanceof MultiGetCache) - ? new DefaultMultiGetRegion($name, $cacheAdapter, $lifetime) - : new DefaultRegion($name, $cacheAdapter, $lifetime); - - if ($cache['usage'] === ClassMetadata::CACHE_USAGE_READ_WRITE) { - - if ( - '' === $this->fileLockRegionDirectory || - null === $this->fileLockRegionDirectory - ) { - throw new \LogicException( - 'If you want to use a "READ_WRITE" cache an implementation of "Doctrine\ORM\Cache\ConcurrentRegion" is required, ' . - 'The default implementation provided by doctrine is "Doctrine\ORM\Cache\Region\FileLockRegion" if you want to use it please provide a valid directory, DefaultCacheFactory#setFileLockRegionDirectory(). ' - ); - } - - $directory = $this->fileLockRegionDirectory . DIRECTORY_SEPARATOR . $cache['region']; - $region = new FileLockRegion($region, $directory, $this->regionsConfig->getLockLifetime($cache['region'])); - } - - return $this->regions[$cache['region']] = $region; - } - - /** - * @param string $name - * - * @return CacheAdapter - */ - private function createRegionCache($name) - { - $cacheAdapter = clone $this->cache; - - if (!$cacheAdapter instanceof CacheProvider) { - return $cacheAdapter; - } - - $namespace = $cacheAdapter->getNamespace(); - - if ('' !== $namespace) { - $namespace .= ':'; - } - - $cacheAdapter->setNamespace($namespace . $name); - - return $cacheAdapter; - } - - /** - * {@inheritdoc} - */ - public function getTimestampRegion() - { - if ($this->timestampRegion === null) { - $name = Cache::DEFAULT_TIMESTAMP_REGION_NAME; - $lifetime = $this->regionsConfig->getLifetime($name); - - $this->timestampRegion = new UpdateTimestampCache($name, clone $this->cache, $lifetime); - } - - return $this->timestampRegion; - } - - /** - * {@inheritdoc} - */ - public function createCache(EntityManagerInterface $em) - { - return new DefaultCache($em); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCollectionHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCollectionHydrator.php deleted file mode 100644 index f12ccf5..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultCollectionHydrator.php +++ /dev/null @@ -1,104 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -use Doctrine\ORM\Query; -use Doctrine\ORM\PersistentCollection; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\EntityManagerInterface; - -/** - * Default hydrator cache for collections - * - * @since 2.5 - * @author Fabio B. Silva - */ -class DefaultCollectionHydrator implements CollectionHydrator -{ - /** - * @var \Doctrine\ORM\EntityManagerInterface - */ - private $em; - - /** - * @var \Doctrine\ORM\UnitOfWork - */ - private $uow; - - /** - * @var array - */ - private static $hints = [Query::HINT_CACHE_ENABLED => true]; - - /** - * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. - */ - public function __construct(EntityManagerInterface $em) - { - $this->em = $em; - $this->uow = $em->getUnitOfWork(); - } - - /** - * {@inheritdoc} - */ - public function buildCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, $collection) - { - $data = []; - - foreach ($collection as $index => $entity) { - $data[$index] = new EntityCacheKey($metadata->rootEntityName, $this->uow->getEntityIdentifier($entity)); - } - - return new CollectionCacheEntry($data); - } - - /** - * {@inheritdoc} - */ - public function loadCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key, CollectionCacheEntry $entry, PersistentCollection $collection) - { - $assoc = $metadata->associationMappings[$key->association]; - /* @var $targetPersister \Doctrine\ORM\Cache\Persister\CachedPersister */ - $targetPersister = $this->uow->getEntityPersister($assoc['targetEntity']); - $targetRegion = $targetPersister->getCacheRegion(); - $list = []; - - $entityEntries = $targetRegion->getMultiple($entry); - - if ($entityEntries === null) { - return null; - } - - /* @var $entityEntries \Doctrine\ORM\Cache\EntityCacheEntry[] */ - foreach ($entityEntries as $index => $entityEntry) { - $list[$index] = $this->uow->createEntity($entityEntry->class, $entityEntry->resolveAssociationEntries($this->em), self::$hints); - } - - array_walk($list, function($entity, $index) use ($collection) { - $collection->hydrateSet($index, $entity); - }); - - $this->uow->hydrationComplete(); - - return $list; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultEntityHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultEntityHydrator.php deleted file mode 100644 index 62f7620..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultEntityHydrator.php +++ /dev/null @@ -1,205 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -use Doctrine\Common\Util\ClassUtils; - -use Doctrine\ORM\Query; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Utility\IdentifierFlattener; - -/** - * Default hydrator cache for entities - * - * @since 2.5 - * @author Fabio B. Silva - */ -class DefaultEntityHydrator implements EntityHydrator -{ - /** - * @var \Doctrine\ORM\EntityManagerInterface - */ - private $em; - - /** - * @var \Doctrine\ORM\UnitOfWork - */ - private $uow; - - /** - * The IdentifierFlattener used for manipulating identifiers - * - * @var \Doctrine\ORM\Utility\IdentifierFlattener - */ - private $identifierFlattener; - - /** - * @var array - */ - private static $hints = [Query::HINT_CACHE_ENABLED => true]; - - /** - * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. - */ - public function __construct(EntityManagerInterface $em) - { - $this->em = $em; - $this->uow = $em->getUnitOfWork(); - $this->identifierFlattener = new IdentifierFlattener($em->getUnitOfWork(), $em->getMetadataFactory()); - } - - /** - * {@inheritdoc} - */ - public function buildCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, $entity) - { - $data = $this->uow->getOriginalEntityData($entity); - $data = array_merge($data, $metadata->getIdentifierValues($entity)); // why update has no identifier values ? - - if ($metadata->isVersioned) { - $data[$metadata->versionField] = $metadata->getFieldValue($entity, $metadata->versionField); - } - - foreach ($metadata->associationMappings as $name => $assoc) { - if ( ! isset($data[$name])) { - continue; - } - - if ( ! ($assoc['type'] & ClassMetadata::TO_ONE)) { - unset($data[$name]); - - continue; - } - - if ( ! isset($assoc['cache'])) { - $targetClassMetadata = $this->em->getClassMetadata($assoc['targetEntity']); - $owningAssociation = ( ! $assoc['isOwningSide']) - ? $targetClassMetadata->associationMappings[$assoc['mappedBy']] - : $assoc; - $associationIds = $this->identifierFlattener->flattenIdentifier( - $targetClassMetadata, - $targetClassMetadata->getIdentifierValues($data[$name]) - ); - - unset($data[$name]); - - foreach ($associationIds as $fieldName => $fieldValue) { - if (isset($targetClassMetadata->fieldMappings[$fieldName])) { - $fieldMapping = $targetClassMetadata->fieldMappings[$fieldName]; - - $data[$owningAssociation['targetToSourceKeyColumns'][$fieldMapping['columnName']]] = $fieldValue; - - continue; - } - - $targetAssoc = $targetClassMetadata->associationMappings[$fieldName]; - - foreach($assoc['targetToSourceKeyColumns'] as $referencedColumn => $localColumn) { - if (isset($targetAssoc['sourceToTargetKeyColumns'][$referencedColumn])) { - $data[$localColumn] = $fieldValue; - } - } - } - - continue; - } - - if ( ! isset($assoc['id'])) { - $targetClass = ClassUtils::getClass($data[$name]); - $targetId = $this->uow->getEntityIdentifier($data[$name]); - $data[$name] = new AssociationCacheEntry($targetClass, $targetId); - - continue; - } - - // handle association identifier - $targetId = is_object($data[$name]) && $this->uow->isInIdentityMap($data[$name]) - ? $this->uow->getEntityIdentifier($data[$name]) - : $data[$name]; - - // @TODO - fix it ! - // handle UnitOfWork#createEntity hash generation - if ( ! is_array($targetId)) { - $data[reset($assoc['joinColumnFieldNames'])] = $targetId; - - $targetEntity = $this->em->getClassMetadata($assoc['targetEntity']); - $targetId = [$targetEntity->identifier[0] => $targetId]; - } - - $data[$name] = new AssociationCacheEntry($assoc['targetEntity'], $targetId); - } - - return new EntityCacheEntry($metadata->name, $data); - } - - /** - * {@inheritdoc} - */ - public function loadCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, EntityCacheEntry $entry, $entity = null) - { - $data = $entry->data; - $hints = self::$hints; - - if ($entity !== null) { - $hints[Query::HINT_REFRESH] = true; - $hints[Query::HINT_REFRESH_ENTITY] = $entity; - } - - foreach ($metadata->associationMappings as $name => $assoc) { - if ( ! isset($assoc['cache']) || ! isset($data[$name])) { - continue; - } - - $assocClass = $data[$name]->class; - $assocId = $data[$name]->identifier; - $isEagerLoad = ($assoc['fetch'] === ClassMetadata::FETCH_EAGER || ($assoc['type'] === ClassMetadata::ONE_TO_ONE && ! $assoc['isOwningSide'])); - - if ( ! $isEagerLoad) { - $data[$name] = $this->em->getReference($assocClass, $assocId); - - continue; - } - - $assocMetadata = $this->em->getClassMetadata($assoc['targetEntity']); - $assocKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocId); - $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']); - $assocRegion = $assocPersister->getCacheRegion(); - $assocEntry = $assocRegion->get($assocKey); - - if ($assocEntry === null) { - return null; - } - - $data[$name] = $this->uow->createEntity($assocEntry->class, $assocEntry->resolveAssociationEntries($this->em), $hints); - } - - if ($entity !== null) { - $this->uow->registerManaged($entity, $key->identifier, $data); - } - - $result = $this->uow->createEntity($entry->class, $data, $hints); - - $this->uow->hydrationComplete(); - - return $result; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultQueryCache.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultQueryCache.php deleted file mode 100644 index 866ea0d..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/DefaultQueryCache.php +++ /dev/null @@ -1,478 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\ORM\Cache\Persister\CachedPersister; -use Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Query\ResultSetMapping; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\PersistentCollection; -use Doctrine\Common\Proxy\Proxy; -use Doctrine\ORM\Cache; -use Doctrine\ORM\Query; -use function assert; - -/** - * Default query cache implementation. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class DefaultQueryCache implements QueryCache -{ - /** - * @var \Doctrine\ORM\EntityManagerInterface - */ - private $em; - - /** - * @var \Doctrine\ORM\UnitOfWork - */ - private $uow; - - /** - * @var \Doctrine\ORM\Cache\Region - */ - private $region; - - /** - * @var \Doctrine\ORM\Cache\QueryCacheValidator - */ - private $validator; - - /** - * @var \Doctrine\ORM\Cache\Logging\CacheLogger - */ - protected $cacheLogger; - - /** - * @var array - */ - private static $hints = [Query::HINT_CACHE_ENABLED => true]; - - /** - * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. - * @param \Doctrine\ORM\Cache\Region $region The query region. - */ - public function __construct(EntityManagerInterface $em, Region $region) - { - $cacheConfig = $em->getConfiguration()->getSecondLevelCacheConfiguration(); - - $this->em = $em; - $this->region = $region; - $this->uow = $em->getUnitOfWork(); - $this->cacheLogger = $cacheConfig->getCacheLogger(); - $this->validator = $cacheConfig->getQueryValidator(); - } - - /** - * {@inheritdoc} - */ - public function get(QueryCacheKey $key, ResultSetMapping $rsm, array $hints = []) - { - if ( ! ($key->cacheMode & Cache::MODE_GET)) { - return null; - } - - $cacheEntry = $this->region->get($key); - - if ( ! $cacheEntry instanceof QueryCacheEntry) { - return null; - } - - if ( ! $this->validator->isValid($key, $cacheEntry)) { - $this->region->evict($key); - - return null; - } - - $result = []; - $entityName = reset($rsm->aliasMap); - $hasRelation = ! empty($rsm->relationMap); - $persister = $this->uow->getEntityPersister($entityName); - assert($persister instanceof CachedEntityPersister); - - $region = $persister->getCacheRegion(); - $regionName = $region->getName(); - - $cm = $this->em->getClassMetadata($entityName); - - $generateKeys = static function (array $entry) use ($cm) : EntityCacheKey { - return new EntityCacheKey($cm->rootEntityName, $entry['identifier']); - }; - - $cacheKeys = new CollectionCacheEntry(array_map($generateKeys, $cacheEntry->result)); - $entries = $region->getMultiple($cacheKeys) ?? []; - - // @TODO - move to cache hydration component - foreach ($cacheEntry->result as $index => $entry) { - $entityEntry = $entries[$index] ?? null; - - if (! $entityEntry instanceof EntityCacheEntry) { - if ($this->cacheLogger !== null) { - $this->cacheLogger->entityCacheMiss($regionName, $cacheKeys->identifiers[$index]); - } - - return null; - } - - if ($this->cacheLogger !== null) { - $this->cacheLogger->entityCacheHit($regionName, $cacheKeys->identifiers[$index]); - } - - if ( ! $hasRelation) { - $result[$index] = $this->uow->createEntity($entityEntry->class, $entityEntry->resolveAssociationEntries($this->em), self::$hints); - - continue; - } - - $data = $entityEntry->data; - - foreach ($entry['associations'] as $name => $assoc) { - $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']); - assert($assocPersister instanceof CachedEntityPersister); - - $assocRegion = $assocPersister->getCacheRegion(); - $assocMetadata = $this->em->getClassMetadata($assoc['targetEntity']); - - if ($assoc['type'] & ClassMetadata::TO_ONE) { - - if (($assocEntry = $assocRegion->get($assocKey = new EntityCacheKey($assocMetadata->rootEntityName, $assoc['identifier']))) === null) { - - if ($this->cacheLogger !== null) { - $this->cacheLogger->entityCacheMiss($assocRegion->getName(), $assocKey); - } - - $this->uow->hydrationComplete(); - - return null; - } - - $data[$name] = $this->uow->createEntity($assocEntry->class, $assocEntry->resolveAssociationEntries($this->em), self::$hints); - - if ($this->cacheLogger !== null) { - $this->cacheLogger->entityCacheHit($assocRegion->getName(), $assocKey); - } - - continue; - } - - if ( ! isset($assoc['list']) || empty($assoc['list'])) { - continue; - } - - $generateKeys = function ($id) use ($assocMetadata): EntityCacheKey { - return new EntityCacheKey($assocMetadata->rootEntityName, $id); - }; - - $collection = new PersistentCollection($this->em, $assocMetadata, new ArrayCollection()); - $assocKeys = new CollectionCacheEntry(array_map($generateKeys, $assoc['list'])); - $assocEntries = $assocRegion->getMultiple($assocKeys); - - foreach ($assoc['list'] as $assocIndex => $assocId) { - $assocEntry = is_array($assocEntries) && array_key_exists($assocIndex, $assocEntries) ? $assocEntries[$assocIndex] : null; - - if ($assocEntry === null) { - if ($this->cacheLogger !== null) { - $this->cacheLogger->entityCacheMiss($assocRegion->getName(), $assocKeys->identifiers[$assocIndex]); - } - - $this->uow->hydrationComplete(); - - return null; - } - - $element = $this->uow->createEntity($assocEntry->class, $assocEntry->resolveAssociationEntries($this->em), self::$hints); - - $collection->hydrateSet($assocIndex, $element); - - if ($this->cacheLogger !== null) { - $this->cacheLogger->entityCacheHit($assocRegion->getName(), $assocKeys->identifiers[$assocIndex]); - } - } - - $data[$name] = $collection; - - $collection->setInitialized(true); - } - - foreach ($data as $fieldName => $unCachedAssociationData) { - // In some scenarios, such as EAGER+ASSOCIATION+ID+CACHE, the - // cache key information in `$cacheEntry` will not contain details - // for fields that are associations. - // - // This means that `$data` keys for some associations that may - // actually not be cached will not be converted to actual association - // data, yet they contain L2 cache AssociationCacheEntry objects. - // - // We need to unwrap those associations into proxy references, - // since we don't have actual data for them except for identifiers. - if ($unCachedAssociationData instanceof AssociationCacheEntry) { - $data[$fieldName] = $this->em->getReference( - $unCachedAssociationData->class, - $unCachedAssociationData->identifier - ); - } - } - - $result[$index] = $this->uow->createEntity($entityEntry->class, $data, self::$hints); - } - - $this->uow->hydrationComplete(); - - return $result; - } - - /** - * {@inheritdoc} - */ - public function put(QueryCacheKey $key, ResultSetMapping $rsm, $result, array $hints = []) - { - if ($rsm->scalarMappings) { - throw new CacheException("Second level cache does not support scalar results."); - } - - if (count($rsm->entityMappings) > 1) { - throw new CacheException("Second level cache does not support multiple root entities."); - } - - if ( ! $rsm->isSelect) { - throw new CacheException("Second-level cache query supports only select statements."); - } - - if (isset($hints[Query::HINT_FORCE_PARTIAL_LOAD]) && $hints[Query::HINT_FORCE_PARTIAL_LOAD]) { - throw new CacheException("Second level cache does not support partial entities."); - } - - if ( ! ($key->cacheMode & Cache::MODE_PUT)) { - return false; - } - - $data = []; - $entityName = reset($rsm->aliasMap); - $rootAlias = key($rsm->aliasMap); - $persister = $this->uow->getEntityPersister($entityName); - - if (! $persister instanceof CachedEntityPersister) { - throw CacheException::nonCacheableEntity($entityName); - } - - $region = $persister->getCacheRegion(); - - foreach ($result as $index => $entity) { - $identifier = $this->uow->getEntityIdentifier($entity); - $entityKey = new EntityCacheKey($entityName, $identifier); - - if (($key->cacheMode & Cache::MODE_REFRESH) || ! $region->contains($entityKey)) { - // Cancel put result if entity put fail - if ( ! $persister->storeEntityCache($entity, $entityKey)) { - return false; - } - } - - $data[$index]['identifier'] = $identifier; - $data[$index]['associations'] = []; - - // @TODO - move to cache hydration components - foreach ($rsm->relationMap as $alias => $name) { - $parentAlias = $rsm->parentAliasMap[$alias]; - $parentClass = $rsm->aliasMap[$parentAlias]; - $metadata = $this->em->getClassMetadata($parentClass); - $assoc = $metadata->associationMappings[$name]; - $assocValue = $this->getAssociationValue($rsm, $alias, $entity); - - if ($assocValue === null) { - continue; - } - - // root entity association - if ($rootAlias === $parentAlias) { - // Cancel put result if association put fail - if ( ($assocInfo = $this->storeAssociationCache($key, $assoc, $assocValue)) === null) { - return false; - } - - $data[$index]['associations'][$name] = $assocInfo; - - continue; - } - - // store single nested association - if ( ! is_array($assocValue)) { - // Cancel put result if association put fail - if ($this->storeAssociationCache($key, $assoc, $assocValue) === null) { - return false; - } - - continue; - } - - // store array of nested association - foreach ($assocValue as $aVal) { - // Cancel put result if association put fail - if ($this->storeAssociationCache($key, $assoc, $aVal) === null) { - return false; - } - } - } - } - - return $this->region->put($key, new QueryCacheEntry($data)); - } - - /** - * @param \Doctrine\ORM\Cache\QueryCacheKey $key - * @param array $assoc - * @param mixed $assocValue - * - * @return array|null - */ - private function storeAssociationCache(QueryCacheKey $key, array $assoc, $assocValue) - { - $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']); - $assocMetadata = $assocPersister->getClassMetadata(); - $assocRegion = $assocPersister->getCacheRegion(); - - // Handle *-to-one associations - if ($assoc['type'] & ClassMetadata::TO_ONE) { - $assocIdentifier = $this->uow->getEntityIdentifier($assocValue); - $entityKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocIdentifier); - - if ( ! $assocValue instanceof Proxy && ($key->cacheMode & Cache::MODE_REFRESH) || ! $assocRegion->contains($entityKey)) { - // Entity put fail - if ( ! $assocPersister->storeEntityCache($assocValue, $entityKey)) { - return null; - } - } - - return [ - 'targetEntity' => $assocMetadata->rootEntityName, - 'identifier' => $assocIdentifier, - 'type' => $assoc['type'] - ]; - } - - // Handle *-to-many associations - $list = []; - - foreach ($assocValue as $assocItemIndex => $assocItem) { - $assocIdentifier = $this->uow->getEntityIdentifier($assocItem); - $entityKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocIdentifier); - - if (($key->cacheMode & Cache::MODE_REFRESH) || ! $assocRegion->contains($entityKey)) { - // Entity put fail - if ( ! $assocPersister->storeEntityCache($assocItem, $entityKey)) { - return null; - } - } - - $list[$assocItemIndex] = $assocIdentifier; - } - - return [ - 'targetEntity' => $assocMetadata->rootEntityName, - 'type' => $assoc['type'], - 'list' => $list, - ]; - } - - /** - * @param \Doctrine\ORM\Query\ResultSetMapping $rsm - * @param string $assocAlias - * @param object $entity - * - * @return array|object - */ - private function getAssociationValue(ResultSetMapping $rsm, $assocAlias, $entity) - { - $path = []; - $alias = $assocAlias; - - while (isset($rsm->parentAliasMap[$alias])) { - $parent = $rsm->parentAliasMap[$alias]; - $field = $rsm->relationMap[$alias]; - $class = $rsm->aliasMap[$parent]; - - array_unshift($path, [ - 'field' => $field, - 'class' => $class - ] - ); - - $alias = $parent; - } - - return $this->getAssociationPathValue($entity, $path); - } - - /** - * @param mixed $value - * @param array $path - * - * @return array|object|null - */ - private function getAssociationPathValue($value, array $path) - { - $mapping = array_shift($path); - $metadata = $this->em->getClassMetadata($mapping['class']); - $assoc = $metadata->associationMappings[$mapping['field']]; - $value = $metadata->getFieldValue($value, $mapping['field']); - - if ($value === null) { - return null; - } - - if (empty($path)) { - return $value; - } - - // Handle *-to-one associations - if ($assoc['type'] & ClassMetadata::TO_ONE) { - return $this->getAssociationPathValue($value, $path); - } - - $values = []; - - foreach ($value as $item) { - $values[] = $this->getAssociationPathValue($item, $path); - } - - return $values; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - return $this->region->evictAll(); - } - - /** - * {@inheritdoc} - */ - public function getRegion() - { - return $this->region; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheEntry.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheEntry.php deleted file mode 100644 index 155618b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheEntry.php +++ /dev/null @@ -1,88 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -use Doctrine\ORM\EntityManagerInterface; - -/** - * Entity cache entry - * - * @since 2.5 - * @author Fabio B. Silva - */ -class EntityCacheEntry implements CacheEntry -{ - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var array The entity map data - */ - public $data; - - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var string The entity class name - */ - public $class; - - /** - * @param string $class The entity class. - * @param array $data The entity data. - */ - public function __construct($class, array $data) - { - $this->class = $class; - $this->data = $data; - } - - /** - * Creates a new EntityCacheEntry - * - * This method allow Doctrine\Common\Cache\PhpFileCache compatibility - * - * @param array $values array containing property values - * - * @return EntityCacheEntry - */ - public static function __set_state(array $values) - { - return new self($values['class'], $values['data']); - } - - /** - * Retrieves the entity data resolving cache entries - * - * @param \Doctrine\ORM\EntityManagerInterface $em - * - * @return array - */ - public function resolveAssociationEntries(EntityManagerInterface $em) - { - return array_map(function($value) use ($em) { - if ( ! ($value instanceof AssociationCacheEntry)) { - return $value; - } - - return $em->getReference($value->class, $value->identifier); - }, $this->data); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheKey.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheKey.php deleted file mode 100644 index 281e610..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityCacheKey.php +++ /dev/null @@ -1,57 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Defines entity classes roles to be stored in the cache region. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class EntityCacheKey extends CacheKey -{ - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var array The entity identifier - */ - public $identifier; - - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var string The entity class name - */ - public $entityClass; - - /** - * @param string $entityClass The entity class name. In a inheritance hierarchy it should always be the root entity class. - * @param array $identifier The entity identifier - */ - public function __construct($entityClass, array $identifier) - { - ksort($identifier); - - $this->identifier = $identifier; - $this->entityClass = $entityClass; - $this->hash = str_replace('\\', '.', strtolower($entityClass) . '_' . implode(' ', $identifier)); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityHydrator.php deleted file mode 100644 index 05a394d..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/EntityHydrator.php +++ /dev/null @@ -1,49 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -use Doctrine\ORM\Mapping\ClassMetadata; - -/** - * Hydrator cache entry for entities - * - * @since 2.5 - * @author Fabio B. Silva - */ -interface EntityHydrator -{ - /** - * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. - * @param \Doctrine\ORM\Cache\EntityCacheKey $key The entity cache key. - * @param object $entity The entity. - * - * @return \Doctrine\ORM\Cache\EntityCacheEntry - */ - public function buildCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, $entity); - - /** - * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. - * @param \Doctrine\ORM\Cache\EntityCacheKey $key The entity cache key. - * @param \Doctrine\ORM\Cache\EntityCacheEntry $entry The entity cache entry. - * @param object $entity The entity to load the cache into. If not specified, a new entity is created. - */ - public function loadCacheEntry(ClassMetadata $metadata, EntityCacheKey $key, EntityCacheEntry $entry, $entity = null); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Lock.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Lock.php deleted file mode 100644 index 60f7d6c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Lock.php +++ /dev/null @@ -1,58 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Cache Lock - * - * @since 2.5 - * @author Fabio B. Silva - */ -class Lock -{ - /** - * @var string - */ - public $value; - - /** - * @var integer - */ - public $time; - - /** - * @param string $value - * @param integer $time - */ - public function __construct($value, $time = null) - { - $this->value = $value; - $this->time = $time ? : time(); - } - - /** - * @return \Doctrine\ORM\Cache\Lock - */ - public static function createLockRead() - { - return new self(uniqid(time(), true)); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/LockException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/LockException.php deleted file mode 100644 index d4c7624..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/LockException.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Lock exception for cache. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class LockException extends CacheException -{ - -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLogger.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLogger.php deleted file mode 100644 index bdae4ee..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLogger.php +++ /dev/null @@ -1,106 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Logging; - -use Doctrine\ORM\Cache\CollectionCacheKey; -use Doctrine\ORM\Cache\EntityCacheKey; -use Doctrine\ORM\Cache\QueryCacheKey; - -/** - * Interface for logging. - * - * @since 2.5 - * @author Fabio B. Silva - */ -interface CacheLogger -{ - /** - * Log an entity put into second level cache. - * - * @param string $regionName The name of the cache region. - * @param \Doctrine\ORM\Cache\EntityCacheKey $key The cache key of the entity. - */ - public function entityCachePut($regionName, EntityCacheKey $key); - - /** - * Log an entity get from second level cache resulted in a hit. - * - * @param string $regionName The name of the cache region. - * @param \Doctrine\ORM\Cache\EntityCacheKey $key The cache key of the entity. - */ - public function entityCacheHit($regionName, EntityCacheKey $key); - - /** - * Log an entity get from second level cache resulted in a miss. - * - * @param string $regionName The name of the cache region. - * @param \Doctrine\ORM\Cache\EntityCacheKey $key The cache key of the entity. - */ - public function entityCacheMiss($regionName, EntityCacheKey $key); - - /** - * Log an entity put into second level cache. - * - * @param string $regionName The name of the cache region. - * @param \Doctrine\ORM\Cache\CollectionCacheKey $key The cache key of the collection. - */ - public function collectionCachePut($regionName, CollectionCacheKey $key); - - /** - * Log an entity get from second level cache resulted in a hit. - * - * @param string $regionName The name of the cache region. - * @param \Doctrine\ORM\Cache\CollectionCacheKey $key The cache key of the collection. - */ - public function collectionCacheHit($regionName, CollectionCacheKey $key); - - /** - * Log an entity get from second level cache resulted in a miss. - * - * @param string $regionName The name of the cache region. - * @param \Doctrine\ORM\Cache\CollectionCacheKey $key The cache key of the collection. - */ - public function collectionCacheMiss($regionName, CollectionCacheKey $key); - - /** - * Log a query put into the query cache. - * - * @param string $regionName The name of the cache region. - * @param \Doctrine\ORM\Cache\QueryCacheKey $key The cache key of the query. - */ - public function queryCachePut($regionName, QueryCacheKey $key); - - /** - * Log a query get from the query cache resulted in a hit. - * - * @param string $regionName The name of the cache region. - * @param \Doctrine\ORM\Cache\QueryCacheKey $key The cache key of the query. - */ - public function queryCacheHit($regionName, QueryCacheKey $key); - - /** - * Log a query get from the query cache resulted in a miss. - * - * @param string $regionName The name of the cache region. - * @param \Doctrine\ORM\Cache\QueryCacheKey $key The cache key of the query. - */ - public function queryCacheMiss($regionName, QueryCacheKey $key); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLoggerChain.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLoggerChain.php deleted file mode 100644 index 28a8125..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/CacheLoggerChain.php +++ /dev/null @@ -1,156 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Logging; - -use Doctrine\ORM\Cache\CollectionCacheKey; -use Doctrine\ORM\Cache\EntityCacheKey; -use Doctrine\ORM\Cache\QueryCacheKey; - -/** - * Cache logger chain - * - * @since 2.5 - * @author Fabio B. Silva - */ -class CacheLoggerChain implements CacheLogger -{ - /** - * @var array<\Doctrine\ORM\Cache\Logging\CacheLogger> - */ - private $loggers = []; - - /** - * @param string $name - * @param \Doctrine\ORM\Cache\Logging\CacheLogger $logger - */ - public function setLogger($name, CacheLogger $logger) - { - $this->loggers[$name] = $logger; - } - - /** - * @param string $name - * - * @return \Doctrine\ORM\Cache\Logging\CacheLogger|null - */ - public function getLogger($name) - { - return isset($this->loggers[$name]) ? $this->loggers[$name] : null; - } - - /** - * @return array<\Doctrine\ORM\Cache\Logging\CacheLogger> - */ - public function getLoggers() - { - return $this->loggers; - } - - /** - * {@inheritdoc} - */ - public function collectionCacheHit($regionName, CollectionCacheKey $key) - { - foreach ($this->loggers as $logger) { - $logger->collectionCacheHit($regionName, $key); - } - } - - /** - * {@inheritdoc} - */ - public function collectionCacheMiss($regionName, CollectionCacheKey $key) - { - foreach ($this->loggers as $logger) { - $logger->collectionCacheMiss($regionName, $key); - } - } - - /** - * {@inheritdoc} - */ - public function collectionCachePut($regionName, CollectionCacheKey $key) - { - foreach ($this->loggers as $logger) { - $logger->collectionCachePut($regionName, $key); - } - } - - /** - * {@inheritdoc} - */ - public function entityCacheHit($regionName, EntityCacheKey $key) - { - foreach ($this->loggers as $logger) { - $logger->entityCacheHit($regionName, $key); - } - } - - /** - * {@inheritdoc} - */ - public function entityCacheMiss($regionName, EntityCacheKey $key) - { - foreach ($this->loggers as $logger) { - $logger->entityCacheMiss($regionName, $key); - } - } - - /** - * {@inheritdoc} - */ - public function entityCachePut($regionName, EntityCacheKey $key) - { - foreach ($this->loggers as $logger) { - $logger->entityCachePut($regionName, $key); - } - } - - /** - * {@inheritdoc} - */ - public function queryCacheHit($regionName, QueryCacheKey $key) - { - foreach ($this->loggers as $logger) { - $logger->queryCacheHit($regionName, $key); - } - } - - /** - * {@inheritdoc} - */ - public function queryCacheMiss($regionName, QueryCacheKey $key) - { - foreach ($this->loggers as $logger) { - $logger->queryCacheMiss($regionName, $key); - } - } - - /** - * {@inheritdoc} - */ - public function queryCachePut($regionName, QueryCacheKey $key) - { - foreach ($this->loggers as $logger) { - $logger->queryCachePut($regionName, $key); - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/StatisticsCacheLogger.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/StatisticsCacheLogger.php deleted file mode 100644 index 122e353..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Logging/StatisticsCacheLogger.php +++ /dev/null @@ -1,251 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Logging; - -use Doctrine\ORM\Cache\CollectionCacheKey; -use Doctrine\ORM\Cache\EntityCacheKey; -use Doctrine\ORM\Cache\QueryCacheKey; - -/** - * Provide basic second level cache statistics. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class StatisticsCacheLogger implements CacheLogger -{ - /** - * @var array - */ - private $cacheMissCountMap = []; - - /** - * @var array - */ - private $cacheHitCountMap = []; - - /** - * @var array - */ - private $cachePutCountMap = []; - - /** - * {@inheritdoc} - */ - public function collectionCacheMiss($regionName, CollectionCacheKey $key) - { - $this->cacheMissCountMap[$regionName] = isset($this->cacheMissCountMap[$regionName]) - ? $this->cacheMissCountMap[$regionName] + 1 - : 1; - } - - /** - * {@inheritdoc} - */ - public function collectionCacheHit($regionName, CollectionCacheKey $key) - { - $this->cacheHitCountMap[$regionName] = isset($this->cacheHitCountMap[$regionName]) - ? $this->cacheHitCountMap[$regionName] + 1 - : 1; - } - - /** - * {@inheritdoc} - */ - public function collectionCachePut($regionName, CollectionCacheKey $key) - { - $this->cachePutCountMap[$regionName] = isset($this->cachePutCountMap[$regionName]) - ? $this->cachePutCountMap[$regionName] + 1 - : 1; - } - - /** - * {@inheritdoc} - */ - public function entityCacheMiss($regionName, EntityCacheKey $key) - { - $this->cacheMissCountMap[$regionName] = isset($this->cacheMissCountMap[$regionName]) - ? $this->cacheMissCountMap[$regionName] + 1 - : 1; - } - - /** - * {@inheritdoc} - */ - public function entityCacheHit($regionName, EntityCacheKey $key) - { - $this->cacheHitCountMap[$regionName] = isset($this->cacheHitCountMap[$regionName]) - ? $this->cacheHitCountMap[$regionName] + 1 - : 1; - } - - /** - * {@inheritdoc} - */ - public function entityCachePut($regionName, EntityCacheKey $key) - { - $this->cachePutCountMap[$regionName] = isset($this->cachePutCountMap[$regionName]) - ? $this->cachePutCountMap[$regionName] + 1 - : 1; - } - - /** - * {@inheritdoc} - */ - public function queryCacheHit($regionName, QueryCacheKey $key) - { - $this->cacheHitCountMap[$regionName] = isset($this->cacheHitCountMap[$regionName]) - ? $this->cacheHitCountMap[$regionName] + 1 - : 1; - } - - /** - * {@inheritdoc} - */ - public function queryCacheMiss($regionName, QueryCacheKey $key) - { - $this->cacheMissCountMap[$regionName] = isset($this->cacheMissCountMap[$regionName]) - ? $this->cacheMissCountMap[$regionName] + 1 - : 1; - } - - /** - * {@inheritdoc} - */ - public function queryCachePut($regionName, QueryCacheKey $key) - { - $this->cachePutCountMap[$regionName] = isset($this->cachePutCountMap[$regionName]) - ? $this->cachePutCountMap[$regionName] + 1 - : 1; - } - - /** - * Get the number of entries successfully retrieved from cache. - * - * @param string $regionName The name of the cache region. - * - * @return integer - */ - public function getRegionHitCount($regionName) - { - return isset($this->cacheHitCountMap[$regionName]) ? $this->cacheHitCountMap[$regionName] : 0; - } - - /** - * Get the number of cached entries *not* found in cache. - * - * @param string $regionName The name of the cache region. - * - * @return integer - */ - public function getRegionMissCount($regionName) - { - return isset($this->cacheMissCountMap[$regionName]) ? $this->cacheMissCountMap[$regionName] : 0; - } - - /** - * Get the number of cacheable entries put in cache. - * - * @param string $regionName The name of the cache region. - * - * @return integer - */ - public function getRegionPutCount($regionName) - { - return isset($this->cachePutCountMap[$regionName]) ? $this->cachePutCountMap[$regionName] : 0; - } - - /** - * @return array - */ - public function getRegionsMiss() - { - return $this->cacheMissCountMap; - } - - /** - * @return array - */ - public function getRegionsHit() - { - return $this->cacheHitCountMap; - } - - /** - * @return array - */ - public function getRegionsPut() - { - return $this->cachePutCountMap; - } - - /** - * Clear region statistics - * - * @param string $regionName The name of the cache region. - */ - public function clearRegionStats($regionName) - { - $this->cachePutCountMap[$regionName] = 0; - $this->cacheHitCountMap[$regionName] = 0; - $this->cacheMissCountMap[$regionName] = 0; - } - - /** - * Clear all statistics - */ - public function clearStats() - { - $this->cachePutCountMap = []; - $this->cacheHitCountMap = []; - $this->cacheMissCountMap = []; - } - - /** - * Get the total number of put in cache. - * - * @return integer - */ - public function getPutCount() - { - return array_sum($this->cachePutCountMap); - } - - /** - * Get the total number of entries successfully retrieved from cache. - * - * @return integer - */ - public function getHitCount() - { - return array_sum($this->cacheHitCountMap); - } - - /** - * Get the total number of cached entries *not* found in cache. - * - * @return integer - */ - public function getMissCount() - { - return array_sum($this->cacheMissCountMap); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/MultiGetRegion.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/MultiGetRegion.php deleted file mode 100644 index be32b08..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/MultiGetRegion.php +++ /dev/null @@ -1,42 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Defines a region that supports multi-get reading. - * - * With one method call we can get multiple items. - * - * @since 2.5 - * @author Asmir Mustafic - */ -interface MultiGetRegion -{ - /** - * Get all items from the cache identified by $keys. - * It returns NULL if some elements can not be found. - * - * @param CollectionCacheEntry $collection The collection of the items to be retrieved. - * - * @return CacheEntry[]|null The cached entries or NULL if one or more entries can not be found - */ - public function getMultiple(CollectionCacheEntry $collection); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/CachedPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/CachedPersister.php deleted file mode 100644 index 89afd32..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/CachedPersister.php +++ /dev/null @@ -1,46 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Persister; - -/** - * Interface for persister that support second level cache. - * - * @since 2.5 - * @author Fabio B. Silva - */ -interface CachedPersister -{ - /** - * Perform whatever processing is encapsulated here after completion of the transaction. - */ - public function afterTransactionComplete(); - - /** - * Perform whatever processing is encapsulated here after completion of the rolled-back. - */ - public function afterTransactionRolledBack(); - - /** - * Gets the The region access. - * - * @return \Doctrine\ORM\Cache\Region - */ - public function getCacheRegion(); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/AbstractCollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/AbstractCollectionPersister.php deleted file mode 100644 index 7a10d17..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/AbstractCollectionPersister.php +++ /dev/null @@ -1,313 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Persister\Collection; - -use Doctrine\Common\Collections\Criteria; -use Doctrine\ORM\Cache\EntityCacheKey; -use Doctrine\ORM\Cache\CollectionCacheKey; -use Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister; -use Doctrine\ORM\Persisters\Collection\CollectionPersister; -use Doctrine\ORM\PersistentCollection; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Cache\Region; -use Doctrine\Common\Util\ClassUtils; - -/** - * @author Fabio B. Silva - * @author Guilherme Blanco - * @since 2.5 - */ -abstract class AbstractCollectionPersister implements CachedCollectionPersister -{ - /** - * @var \Doctrine\ORM\UnitOfWork - */ - protected $uow; - - /** - * @var \Doctrine\ORM\Mapping\ClassMetadataFactory - */ - protected $metadataFactory; - - /** - * @var \Doctrine\ORM\Persisters\Collection\CollectionPersister - */ - protected $persister; - - /** - * @var \Doctrine\ORM\Mapping\ClassMetadata - */ - protected $sourceEntity; - - /** - * @var \Doctrine\ORM\Mapping\ClassMetadata - */ - protected $targetEntity; - - /** - * @var array - */ - protected $association; - - /** - * @var array - */ - protected $queuedCache = []; - - /** - * @var \Doctrine\ORM\Cache\Region - */ - protected $region; - - /** - * @var string - */ - protected $regionName; - - /** - * @var \Doctrine\ORM\Cache\CollectionHydrator - */ - protected $hydrator; - - /** - * @var \Doctrine\ORM\Cache\Logging\CacheLogger - */ - protected $cacheLogger; - - /** - * @param \Doctrine\ORM\Persisters\Collection\CollectionPersister $persister The collection persister that will be cached. - * @param \Doctrine\ORM\Cache\Region $region The collection region. - * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. - * @param array $association The association mapping. - */ - public function __construct(CollectionPersister $persister, Region $region, EntityManagerInterface $em, array $association) - { - $configuration = $em->getConfiguration(); - $cacheConfig = $configuration->getSecondLevelCacheConfiguration(); - $cacheFactory = $cacheConfig->getCacheFactory(); - - $this->region = $region; - $this->persister = $persister; - $this->association = $association; - $this->regionName = $region->getName(); - $this->uow = $em->getUnitOfWork(); - $this->metadataFactory = $em->getMetadataFactory(); - $this->cacheLogger = $cacheConfig->getCacheLogger(); - $this->hydrator = $cacheFactory->buildCollectionHydrator($em, $association); - $this->sourceEntity = $em->getClassMetadata($association['sourceEntity']); - $this->targetEntity = $em->getClassMetadata($association['targetEntity']); - } - - /** - * {@inheritdoc} - */ - public function getCacheRegion() - { - return $this->region; - } - - /** - * {@inheritdoc} - */ - public function getSourceEntityMetadata() - { - return $this->sourceEntity; - } - - /** - * {@inheritdoc} - */ - public function getTargetEntityMetadata() - { - return $this->targetEntity; - } - - /** - * @param \Doctrine\ORM\PersistentCollection $collection - * @param \Doctrine\ORM\Cache\CollectionCacheKey $key - * - * @return \Doctrine\ORM\PersistentCollection|null - */ - public function loadCollectionCache(PersistentCollection $collection, CollectionCacheKey $key) - { - if (($cache = $this->region->get($key)) === null) { - return null; - } - - if (($cache = $this->hydrator->loadCacheEntry($this->sourceEntity, $key, $cache, $collection)) === null) { - return null; - } - - return $cache; - } - - /** - * {@inheritdoc} - */ - public function storeCollectionCache(CollectionCacheKey $key, $elements) - { - /* @var $targetPersister CachedEntityPersister */ - $associationMapping = $this->sourceEntity->associationMappings[$key->association]; - $targetPersister = $this->uow->getEntityPersister($this->targetEntity->rootEntityName); - $targetRegion = $targetPersister->getCacheRegion(); - $targetHydrator = $targetPersister->getEntityHydrator(); - - // Only preserve ordering if association configured it - if ( ! (isset($associationMapping['indexBy']) && $associationMapping['indexBy'])) { - // Elements may be an array or a Collection - $elements = array_values(is_array($elements) ? $elements : $elements->getValues()); - } - - $entry = $this->hydrator->buildCacheEntry($this->targetEntity, $key, $elements); - - foreach ($entry->identifiers as $index => $entityKey) { - if ($targetRegion->contains($entityKey)) { - continue; - } - - $class = $this->targetEntity; - $className = ClassUtils::getClass($elements[$index]); - - if ($className !== $this->targetEntity->name) { - $class = $this->metadataFactory->getMetadataFor($className); - } - - $entity = $elements[$index]; - $entityEntry = $targetHydrator->buildCacheEntry($class, $entityKey, $entity); - - $targetRegion->put($entityKey, $entityEntry); - } - - $cached = $this->region->put($key, $entry); - - if ($this->cacheLogger && $cached) { - $this->cacheLogger->collectionCachePut($this->regionName, $key); - } - } - - /** - * {@inheritdoc} - */ - public function contains(PersistentCollection $collection, $element) - { - return $this->persister->contains($collection, $element); - } - - /** - * {@inheritdoc} - */ - public function containsKey(PersistentCollection $collection, $key) - { - return $this->persister->containsKey($collection, $key); - } - - /** - * {@inheritdoc} - */ - public function count(PersistentCollection $collection) - { - $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); - $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId); - $entry = $this->region->get($key); - - if ($entry !== null) { - return count($entry->identifiers); - } - - return $this->persister->count($collection); - } - - /** - * {@inheritdoc} - */ - public function get(PersistentCollection $collection, $index) - { - return $this->persister->get($collection, $index); - } - - /** - * {@inheritdoc} - */ - public function removeElement(PersistentCollection $collection, $element) - { - if ($persisterResult = $this->persister->removeElement($collection, $element)) { - $this->evictCollectionCache($collection); - $this->evictElementCache($this->sourceEntity->rootEntityName, $collection->getOwner()); - $this->evictElementCache($this->targetEntity->rootEntityName, $element); - } - - return $persisterResult; - } - - /** - * {@inheritdoc} - */ - public function slice(PersistentCollection $collection, $offset, $length = null) - { - return $this->persister->slice($collection, $offset, $length); - } - - /** - * {@inheritDoc} - */ - public function loadCriteria(PersistentCollection $collection, Criteria $criteria) - { - return $this->persister->loadCriteria($collection, $criteria); - } - - /** - * Clears cache entries related to the current collection - * - * @param PersistentCollection $collection - */ - protected function evictCollectionCache(PersistentCollection $collection) - { - $key = new CollectionCacheKey( - $this->sourceEntity->rootEntityName, - $this->association['fieldName'], - $this->uow->getEntityIdentifier($collection->getOwner()) - ); - - $this->region->evict($key); - - if ($this->cacheLogger) { - $this->cacheLogger->collectionCachePut($this->regionName, $key); - } - } - - /** - * @param string $targetEntity - * @param object $element - */ - protected function evictElementCache($targetEntity, $element) - { - /* @var $targetPersister CachedEntityPersister */ - $targetPersister = $this->uow->getEntityPersister($targetEntity); - $targetRegion = $targetPersister->getCacheRegion(); - $key = new EntityCacheKey($targetEntity, $this->uow->getEntityIdentifier($element)); - - $targetRegion->evict($key); - - if ($this->cacheLogger) { - $this->cacheLogger->entityCachePut($targetRegion->getName(), $key); - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/CachedCollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/CachedCollectionPersister.php deleted file mode 100644 index 5722027..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/CachedCollectionPersister.php +++ /dev/null @@ -1,65 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Persister\Collection; - -use Doctrine\ORM\Cache\CollectionCacheKey; -use Doctrine\ORM\Cache\Persister\CachedPersister; -use Doctrine\ORM\Persisters\Collection\CollectionPersister; -use Doctrine\ORM\PersistentCollection; - -/** - * Interface for second level cache collection persisters. - * - * @author Fabio B. Silva - * @since 2.5 - */ -interface CachedCollectionPersister extends CachedPersister, CollectionPersister -{ - /** - * @return \Doctrine\ORM\Mapping\ClassMetadata - */ - public function getSourceEntityMetadata(); - - /** - * @return \Doctrine\ORM\Mapping\ClassMetadata - */ - public function getTargetEntityMetadata(); - - /** - * Loads a collection from cache - * - * @param \Doctrine\ORM\PersistentCollection $collection - * @param \Doctrine\ORM\Cache\CollectionCacheKey $key - * - * @return \Doctrine\ORM\PersistentCollection|null - */ - public function loadCollectionCache(PersistentCollection $collection, CollectionCacheKey $key); - - /** - * Stores a collection into cache - * - * @param \Doctrine\ORM\Cache\CollectionCacheKey $key - * @param array|\Doctrine\Common\Collections\Collection $elements - * - * @return void - */ - public function storeCollectionCache(CollectionCacheKey $key, $elements); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/NonStrictReadWriteCachedCollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/NonStrictReadWriteCachedCollectionPersister.php deleted file mode 100644 index fbd46f6..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/NonStrictReadWriteCachedCollectionPersister.php +++ /dev/null @@ -1,104 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Persister\Collection; - -use Doctrine\ORM\Cache\CollectionCacheKey; -use Doctrine\ORM\PersistentCollection; - -/** - * @author Fabio B. Silva - * @since 2.5 - */ -class NonStrictReadWriteCachedCollectionPersister extends AbstractCollectionPersister -{ - /** - * {@inheritdoc} - */ - public function afterTransactionComplete() - { - if (isset($this->queuedCache['update'])) { - foreach ($this->queuedCache['update'] as $item) { - $this->storeCollectionCache($item['key'], $item['list']); - } - } - - if (isset($this->queuedCache['delete'])) { - foreach ($this->queuedCache['delete'] as $key) { - $this->region->evict($key); - } - } - - $this->queuedCache = []; - } - - /** - * {@inheritdoc} - */ - public function afterTransactionRolledBack() - { - $this->queuedCache = []; - } - - /** - * {@inheritdoc} - */ - public function delete(PersistentCollection $collection) - { - $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); - $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId); - - $this->persister->delete($collection); - - $this->queuedCache['delete'][spl_object_hash($collection)] = $key; - } - - /** - * {@inheritdoc} - */ - public function update(PersistentCollection $collection) - { - $isInitialized = $collection->isInitialized(); - $isDirty = $collection->isDirty(); - - if ( ! $isInitialized && ! $isDirty) { - return; - } - - $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); - $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId); - - // Invalidate non initialized collections OR ordered collection - if ($isDirty && ! $isInitialized || isset($this->association['orderBy'])) { - $this->persister->update($collection); - - $this->queuedCache['delete'][spl_object_hash($collection)] = $key; - - return; - } - - $this->persister->update($collection); - - $this->queuedCache['update'][spl_object_hash($collection)] = [ - 'key' => $key, - 'list' => $collection - ]; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php deleted file mode 100644 index dfc816c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadOnlyCachedCollectionPersister.php +++ /dev/null @@ -1,44 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Persister\Collection; - -use Doctrine\ORM\PersistentCollection; -use Doctrine\ORM\Cache\CacheException; -use Doctrine\Common\Util\ClassUtils; - -/** - * @author Fabio B. Silva - * @since 2.5 - */ -class ReadOnlyCachedCollectionPersister extends NonStrictReadWriteCachedCollectionPersister -{ - /** - * {@inheritdoc} - */ - public function update(PersistentCollection $collection) - { - if ($collection->isDirty() && $collection->getSnapshot()) { - throw CacheException::updateReadOnlyCollection(ClassUtils::getClass($collection->getOwner()), $this->association['fieldName']); - } - - parent::update($collection); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php deleted file mode 100644 index 74bb044..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Collection/ReadWriteCachedCollectionPersister.php +++ /dev/null @@ -1,134 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Persister\Collection; - -use Doctrine\ORM\Persisters\Collection\CollectionPersister; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Cache\CollectionCacheKey; -use Doctrine\ORM\Cache\ConcurrentRegion; -use Doctrine\ORM\PersistentCollection; - -/** - * @author Fabio B. Silva - * @since 2.5 - */ -class ReadWriteCachedCollectionPersister extends AbstractCollectionPersister -{ - /** - * @param \Doctrine\ORM\Persisters\Collection\CollectionPersister $persister The collection persister that will be cached. - * @param \Doctrine\ORM\Cache\ConcurrentRegion $region The collection region. - * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. - * @param array $association The association mapping. - */ - public function __construct(CollectionPersister $persister, ConcurrentRegion $region, EntityManagerInterface $em, array $association) - { - parent::__construct($persister, $region, $em, $association); - } - - /** - * {@inheritdoc} - */ - public function afterTransactionComplete() - { - if (isset($this->queuedCache['update'])) { - foreach ($this->queuedCache['update'] as $item) { - $this->region->evict($item['key']); - } - } - - if (isset($this->queuedCache['delete'])) { - foreach ($this->queuedCache['delete'] as $item) { - $this->region->evict($item['key']); - } - } - - $this->queuedCache = []; - } - - /** - * {@inheritdoc} - */ - public function afterTransactionRolledBack() - { - if (isset($this->queuedCache['update'])) { - foreach ($this->queuedCache['update'] as $item) { - $this->region->evict($item['key']); - } - } - - if (isset($this->queuedCache['delete'])) { - foreach ($this->queuedCache['delete'] as $item) { - $this->region->evict($item['key']); - } - } - - $this->queuedCache = []; - } - - /** - * {@inheritdoc} - */ - public function delete(PersistentCollection $collection) - { - $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); - $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId); - $lock = $this->region->lock($key); - - $this->persister->delete($collection); - - if ($lock === null) { - return; - } - - $this->queuedCache['delete'][spl_object_hash($collection)] = [ - 'key' => $key, - 'lock' => $lock - ]; - } - - /** - * {@inheritdoc} - */ - public function update(PersistentCollection $collection) - { - $isInitialized = $collection->isInitialized(); - $isDirty = $collection->isDirty(); - - if ( ! $isInitialized && ! $isDirty) { - return; - } - - $this->persister->update($collection); - - $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); - $key = new CollectionCacheKey($this->sourceEntity->rootEntityName, $this->association['fieldName'], $ownerId); - $lock = $this->region->lock($key); - - if ($lock === null) { - return; - } - - $this->queuedCache['update'][spl_object_hash($collection)] = [ - 'key' => $key, - 'lock' => $lock - ]; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/AbstractEntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/AbstractEntityPersister.php deleted file mode 100644 index 0548412..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/AbstractEntityPersister.php +++ /dev/null @@ -1,652 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Persister\Entity; - -use Doctrine\ORM\Cache; -use Doctrine\ORM\Cache\Region; -use Doctrine\ORM\Cache\EntityCacheKey; -use Doctrine\ORM\Cache\CollectionCacheKey; -use Doctrine\ORM\Cache\TimestampCacheKey; -use Doctrine\ORM\Cache\QueryCacheKey; -use Doctrine\ORM\Cache\Persister\CachedPersister; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\PersistentCollection; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Persisters\Entity\EntityPersister; - -use Doctrine\Common\Util\ClassUtils; -use Doctrine\Common\Collections\Criteria; - -/** - * @author Fabio B. Silva - * @since 2.5 - */ -abstract class AbstractEntityPersister implements CachedEntityPersister -{ - /** - * @var \Doctrine\ORM\UnitOfWork - */ - protected $uow; - - /** - * @var \Doctrine\ORM\Mapping\ClassMetadataFactory - */ - protected $metadataFactory; - - /** - * @var \Doctrine\ORM\Persisters\Entity\EntityPersister - */ - protected $persister; - - /** - * @var \Doctrine\ORM\Mapping\ClassMetadata - */ - protected $class; - - /** - * @var array - */ - protected $queuedCache = []; - - /** - * @var \Doctrine\ORM\Cache\Region - */ - protected $region; - - /** - * @var \Doctrine\ORM\Cache\TimestampRegion - */ - protected $timestampRegion; - - /** - * @var \Doctrine\ORM\Cache\TimestampCacheKey - */ - protected $timestampKey; - - /** - * @var \Doctrine\ORM\Cache\EntityHydrator - */ - protected $hydrator; - - /** - * @var \Doctrine\ORM\Cache - */ - protected $cache; - - /** - * @var \Doctrine\ORM\Cache\Logging\CacheLogger - */ - protected $cacheLogger; - - /** - * @var string - */ - protected $regionName; - - /** - * Associations configured as FETCH_EAGER, as well as all inverse one-to-one associations. - * - * @var array|null - */ - protected $joinedAssociations; - - /** - * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $persister The entity persister to cache. - * @param \Doctrine\ORM\Cache\Region $region The entity cache region. - * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. - * @param \Doctrine\ORM\Mapping\ClassMetadata $class The entity metadata. - */ - public function __construct(EntityPersister $persister, Region $region, EntityManagerInterface $em, ClassMetadata $class) - { - $configuration = $em->getConfiguration(); - $cacheConfig = $configuration->getSecondLevelCacheConfiguration(); - $cacheFactory = $cacheConfig->getCacheFactory(); - - $this->class = $class; - $this->region = $region; - $this->persister = $persister; - $this->cache = $em->getCache(); - $this->regionName = $region->getName(); - $this->uow = $em->getUnitOfWork(); - $this->metadataFactory = $em->getMetadataFactory(); - $this->cacheLogger = $cacheConfig->getCacheLogger(); - $this->timestampRegion = $cacheFactory->getTimestampRegion(); - $this->hydrator = $cacheFactory->buildEntityHydrator($em, $class); - $this->timestampKey = new TimestampCacheKey($this->class->rootEntityName); - } - - /** - * {@inheritdoc} - */ - public function addInsert($entity) - { - $this->persister->addInsert($entity); - } - - /** - * {@inheritdoc} - */ - public function getInserts() - { - return $this->persister->getInserts(); - } - - /** - * {@inheritdoc} - */ - public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, array $orderBy = null) - { - return $this->persister->getSelectSQL($criteria, $assoc, $lockMode, $limit, $offset, $orderBy); - } - - /** - * {@inheritDoc} - */ - public function getCountSQL($criteria = []) - { - return $this->persister->getCountSQL($criteria); - } - - /** - * {@inheritdoc} - */ - public function getInsertSQL() - { - return $this->persister->getInsertSQL(); - } - - /** - * {@inheritdoc} - */ - public function getResultSetMapping() - { - return $this->persister->getResultSetMapping(); - } - - /** - * {@inheritdoc} - */ - public function getSelectConditionStatementSQL($field, $value, $assoc = null, $comparison = null) - { - return $this->persister->getSelectConditionStatementSQL($field, $value, $assoc, $comparison); - } - - /** - * {@inheritdoc} - */ - public function exists($entity, Criteria $extraConditions = null) - { - if (null === $extraConditions) { - $key = new EntityCacheKey($this->class->rootEntityName, $this->class->getIdentifierValues($entity)); - - if ($this->region->contains($key)) { - return true; - } - } - - return $this->persister->exists($entity, $extraConditions); - } - - /** - * {@inheritdoc} - */ - public function getCacheRegion() - { - return $this->region; - } - - /** - * @return \Doctrine\ORM\Cache\EntityHydrator - */ - public function getEntityHydrator() - { - return $this->hydrator; - } - - /** - * {@inheritdoc} - */ - public function storeEntityCache($entity, EntityCacheKey $key) - { - $class = $this->class; - $className = ClassUtils::getClass($entity); - - if ($className !== $this->class->name) { - $class = $this->metadataFactory->getMetadataFor($className); - } - - $entry = $this->hydrator->buildCacheEntry($class, $key, $entity); - $cached = $this->region->put($key, $entry); - - if ($this->cacheLogger && $cached) { - $this->cacheLogger->entityCachePut($this->regionName, $key); - } - - return $cached; - } - - /** - * @param object $entity - */ - private function storeJoinedAssociations($entity) - { - if ($this->joinedAssociations === null) { - $associations = []; - - foreach ($this->class->associationMappings as $name => $assoc) { - if (isset($assoc['cache']) && - ($assoc['type'] & ClassMetadata::TO_ONE) && - ($assoc['fetch'] === ClassMetadata::FETCH_EAGER || ! $assoc['isOwningSide'])) { - - $associations[] = $name; - } - } - - $this->joinedAssociations = $associations; - } - - foreach ($this->joinedAssociations as $name) { - $assoc = $this->class->associationMappings[$name]; - $assocEntity = $this->class->getFieldValue($entity, $name); - - if ($assocEntity === null) { - continue; - } - - $assocId = $this->uow->getEntityIdentifier($assocEntity); - $assocMetadata = $this->metadataFactory->getMetadataFor($assoc['targetEntity']); - $assocKey = new EntityCacheKey($assocMetadata->rootEntityName, $assocId); - $assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']); - - $assocPersister->storeEntityCache($assocEntity, $assocKey); - } - } - - /** - * Generates a string of currently query - * - * @param array $query - * @param string $criteria - * @param array $orderBy - * @param integer $limit - * @param integer $offset - * - * @return string - */ - protected function getHash($query, $criteria, array $orderBy = null, $limit = null, $offset = null) - { - list($params) = ($criteria instanceof Criteria) - ? $this->persister->expandCriteriaParameters($criteria) - : $this->persister->expandParameters($criteria); - - return sha1($query . serialize($params) . serialize($orderBy) . $limit . $offset); - } - - /** - * {@inheritdoc} - */ - public function expandParameters($criteria) - { - return $this->persister->expandParameters($criteria); - } - - /** - * {@inheritdoc} - */ - public function expandCriteriaParameters(Criteria $criteria) - { - return $this->persister->expandCriteriaParameters($criteria); - } - - /** - * {@inheritdoc} - */ - public function getClassMetadata() - { - return $this->persister->getClassMetadata(); - } - - /** - * {@inheritdoc} - */ - public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null) - { - return $this->persister->getManyToManyCollection($assoc, $sourceEntity, $offset, $limit); - } - - /** - * {@inheritdoc} - */ - public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null) - { - return $this->persister->getOneToManyCollection($assoc, $sourceEntity, $offset, $limit); - } - - /** - * {@inheritdoc} - */ - public function getOwningTable($fieldName) - { - return $this->persister->getOwningTable($fieldName); - } - - /** - * {@inheritdoc} - */ - public function executeInserts() - { - $this->queuedCache['insert'] = $this->persister->getInserts(); - - return $this->persister->executeInserts(); - } - - /** - * {@inheritdoc} - */ - public function load(array $criteria, $entity = null, $assoc = null, array $hints = [], $lockMode = null, $limit = null, array $orderBy = null) - { - if ($entity !== null || $assoc !== null || ! empty($hints) || $lockMode !== null) { - return $this->persister->load($criteria, $entity, $assoc, $hints, $lockMode, $limit, $orderBy); - } - - //handle only EntityRepository#findOneBy - $query = $this->persister->getSelectSQL($criteria, null, null, $limit, null, $orderBy); - $hash = $this->getHash($query, $criteria, null, null, null); - $rsm = $this->getResultSetMapping(); - $queryKey = new QueryCacheKey($hash, 0, Cache::MODE_NORMAL, $this->timestampKey); - $queryCache = $this->cache->getQueryCache($this->regionName); - $result = $queryCache->get($queryKey, $rsm); - - if ($result !== null) { - if ($this->cacheLogger) { - $this->cacheLogger->queryCacheHit($this->regionName, $queryKey); - } - - return $result[0]; - } - - if (($result = $this->persister->load($criteria, $entity, $assoc, $hints, $lockMode, $limit, $orderBy)) === null) { - return null; - } - - $cached = $queryCache->put($queryKey, $rsm, [$result]); - - if ($this->cacheLogger) { - if ($result) { - $this->cacheLogger->queryCacheMiss($this->regionName, $queryKey); - } - - if ($cached) { - $this->cacheLogger->queryCachePut($this->regionName, $queryKey); - } - } - - return $result; - } - - /** - * {@inheritdoc} - */ - public function loadAll(array $criteria = [], array $orderBy = null, $limit = null, $offset = null) - { - $query = $this->persister->getSelectSQL($criteria, null, null, $limit, $offset, $orderBy); - $hash = $this->getHash($query, $criteria, null, null, null); - $rsm = $this->getResultSetMapping(); - $queryKey = new QueryCacheKey($hash, 0, Cache::MODE_NORMAL, $this->timestampKey); - $queryCache = $this->cache->getQueryCache($this->regionName); - $result = $queryCache->get($queryKey, $rsm); - - if ($result !== null) { - if ($this->cacheLogger) { - $this->cacheLogger->queryCacheHit($this->regionName, $queryKey); - } - - return $result; - } - - $result = $this->persister->loadAll($criteria, $orderBy, $limit, $offset); - $cached = $queryCache->put($queryKey, $rsm, $result); - - if ($this->cacheLogger) { - if ($result) { - $this->cacheLogger->queryCacheMiss($this->regionName, $queryKey); - } - - if ($cached) { - $this->cacheLogger->queryCachePut($this->regionName, $queryKey); - } - } - - return $result; - } - - /** - * {@inheritdoc} - */ - public function loadById(array $identifier, $entity = null) - { - $cacheKey = new EntityCacheKey($this->class->rootEntityName, $identifier); - $cacheEntry = $this->region->get($cacheKey); - $class = $this->class; - - if ($cacheEntry !== null) { - if ($cacheEntry->class !== $this->class->name) { - $class = $this->metadataFactory->getMetadataFor($cacheEntry->class); - } - - $cachedEntity = $this->hydrator->loadCacheEntry($class, $cacheKey, $cacheEntry, $entity); - - if ($cachedEntity !== null) { - if ($this->cacheLogger) { - $this->cacheLogger->entityCacheHit($this->regionName, $cacheKey); - } - - return $cachedEntity; - } - } - - $entity = $this->persister->loadById($identifier, $entity); - - if ($entity === null) { - return null; - } - - $class = $this->class; - $className = ClassUtils::getClass($entity); - - if ($className !== $this->class->name) { - $class = $this->metadataFactory->getMetadataFor($className); - } - - $cacheEntry = $this->hydrator->buildCacheEntry($class, $cacheKey, $entity); - $cached = $this->region->put($cacheKey, $cacheEntry); - - if ($cached && (null === $this->joinedAssociations || $this->joinedAssociations)) { - $this->storeJoinedAssociations($entity); - } - - if ($this->cacheLogger) { - if ($cached) { - $this->cacheLogger->entityCachePut($this->regionName, $cacheKey); - } - - $this->cacheLogger->entityCacheMiss($this->regionName, $cacheKey); - } - - return $entity; - } - - /** - * {@inheritDoc} - */ - public function count($criteria = []) - { - return $this->persister->count($criteria); - } - - /** - * {@inheritdoc} - */ - public function loadCriteria(Criteria $criteria) - { - $orderBy = $criteria->getOrderings(); - $limit = $criteria->getMaxResults(); - $offset = $criteria->getFirstResult(); - $query = $this->persister->getSelectSQL($criteria); - $hash = $this->getHash($query, $criteria, $orderBy, $limit, $offset); - $rsm = $this->getResultSetMapping(); - $queryKey = new QueryCacheKey($hash, 0, Cache::MODE_NORMAL, $this->timestampKey); - $queryCache = $this->cache->getQueryCache($this->regionName); - $cacheResult = $queryCache->get($queryKey, $rsm); - - if ($cacheResult !== null) { - if ($this->cacheLogger) { - $this->cacheLogger->queryCacheHit($this->regionName, $queryKey); - } - - return $cacheResult; - } - - $result = $this->persister->loadCriteria($criteria); - $cached = $queryCache->put($queryKey, $rsm, $result); - - if ($this->cacheLogger) { - if ($result) { - $this->cacheLogger->queryCacheMiss($this->regionName, $queryKey); - } - - if ($cached) { - $this->cacheLogger->queryCachePut($this->regionName, $queryKey); - } - } - - return $result; - } - - /** - * {@inheritdoc} - */ - public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll) - { - $persister = $this->uow->getCollectionPersister($assoc); - $hasCache = ($persister instanceof CachedPersister); - $key = null; - - if ( ! $hasCache) { - return $this->persister->loadManyToManyCollection($assoc, $sourceEntity, $coll); - } - - $ownerId = $this->uow->getEntityIdentifier($coll->getOwner()); - $key = $this->buildCollectionCacheKey($assoc, $ownerId); - $list = $persister->loadCollectionCache($coll, $key); - - if ($list !== null) { - if ($this->cacheLogger) { - $this->cacheLogger->collectionCacheHit($persister->getCacheRegion()->getName(), $key); - } - - return $list; - } - - $list = $this->persister->loadManyToManyCollection($assoc, $sourceEntity, $coll); - - $persister->storeCollectionCache($key, $list); - - if ($this->cacheLogger) { - $this->cacheLogger->collectionCacheMiss($persister->getCacheRegion()->getName(), $key); - } - - return $list; - } - - /** - * {@inheritdoc} - */ - public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll) - { - $persister = $this->uow->getCollectionPersister($assoc); - $hasCache = ($persister instanceof CachedPersister); - - if ( ! $hasCache) { - return $this->persister->loadOneToManyCollection($assoc, $sourceEntity, $coll); - } - - $ownerId = $this->uow->getEntityIdentifier($coll->getOwner()); - $key = $this->buildCollectionCacheKey($assoc, $ownerId); - $list = $persister->loadCollectionCache($coll, $key); - - if ($list !== null) { - if ($this->cacheLogger) { - $this->cacheLogger->collectionCacheHit($persister->getCacheRegion()->getName(), $key); - } - - return $list; - } - - $list = $this->persister->loadOneToManyCollection($assoc, $sourceEntity, $coll); - - $persister->storeCollectionCache($key, $list); - - if ($this->cacheLogger) { - $this->cacheLogger->collectionCacheMiss($persister->getCacheRegion()->getName(), $key); - } - - return $list; - } - - /** - * {@inheritdoc} - */ - public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifier = []) - { - return $this->persister->loadOneToOneEntity($assoc, $sourceEntity, $identifier); - } - - /** - * {@inheritdoc} - */ - public function lock(array $criteria, $lockMode) - { - $this->persister->lock($criteria, $lockMode); - } - - /** - * {@inheritdoc} - */ - public function refresh(array $id, $entity, $lockMode = null) - { - $this->persister->refresh($id, $entity, $lockMode); - } - - /** - * @param array $association - * @param array $ownerId - * - * @return CollectionCacheKey - */ - protected function buildCollectionCacheKey(array $association, $ownerId) - { - /** @var ClassMetadata $metadata */ - $metadata = $this->metadataFactory->getMetadataFor($association['sourceEntity']); - - return new CollectionCacheKey($metadata->rootEntityName, $association['fieldName'], $ownerId); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/CachedEntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/CachedEntityPersister.php deleted file mode 100644 index 8958270..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/CachedEntityPersister.php +++ /dev/null @@ -1,47 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Persister\Entity; - -use Doctrine\ORM\Cache\EntityCacheKey; -use Doctrine\ORM\Cache\Persister\CachedPersister; -use Doctrine\ORM\Persisters\Entity\EntityPersister; - -/** - * Interface for second level cache entity persisters. - * - * @author Fabio B. Silva - * @since 2.5 - */ -interface CachedEntityPersister extends CachedPersister, EntityPersister -{ - /** - * @return \Doctrine\ORM\Cache\EntityHydrator - */ - public function getEntityHydrator(); - - /** - * @param object $entity - * @param \Doctrine\ORM\Cache\EntityCacheKey $key - * - * @return boolean - */ - public function storeEntityCache($entity, EntityCacheKey $key); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/NonStrictReadWriteCachedEntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/NonStrictReadWriteCachedEntityPersister.php deleted file mode 100644 index a284467..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/NonStrictReadWriteCachedEntityPersister.php +++ /dev/null @@ -1,117 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Persister\Entity; - -use Doctrine\ORM\Cache\EntityCacheKey; - -/** - * Specific non-strict read/write cached entity persister - * - * @author Fabio B. Silva - * @author Guilherme Blanco - * @since 2.5 - */ -class NonStrictReadWriteCachedEntityPersister extends AbstractEntityPersister -{ - /** - * {@inheritdoc} - */ - public function afterTransactionComplete() - { - $isChanged = false; - - if (isset($this->queuedCache['insert'])) { - foreach ($this->queuedCache['insert'] as $entity) { - $isChanged = $this->updateCache($entity, $isChanged); - } - } - - if (isset($this->queuedCache['update'])) { - foreach ($this->queuedCache['update'] as $entity) { - $isChanged = $this->updateCache($entity, $isChanged); - } - } - - if (isset($this->queuedCache['delete'])) { - foreach ($this->queuedCache['delete'] as $key) { - $this->region->evict($key); - - $isChanged = true; - } - } - - if ($isChanged) { - $this->timestampRegion->update($this->timestampKey); - } - - $this->queuedCache = []; - } - - /** - * {@inheritdoc} - */ - public function afterTransactionRolledBack() - { - $this->queuedCache = []; - } - - /** - * {@inheritdoc} - */ - public function delete($entity) - { - $key = new EntityCacheKey($this->class->rootEntityName, $this->uow->getEntityIdentifier($entity)); - $deleted = $this->persister->delete($entity); - - if ($deleted) { - $this->region->evict($key); - } - - $this->queuedCache['delete'][] = $key; - - return $deleted; - } - - /** - * {@inheritdoc} - */ - public function update($entity) - { - $this->persister->update($entity); - - $this->queuedCache['update'][] = $entity; - } - - private function updateCache($entity, $isChanged) - { - $class = $this->metadataFactory->getMetadataFor(get_class($entity)); - $key = new EntityCacheKey($class->rootEntityName, $this->uow->getEntityIdentifier($entity)); - $entry = $this->hydrator->buildCacheEntry($class, $key, $entity); - $cached = $this->region->put($key, $entry); - $isChanged = $isChanged ?: $cached; - - if ($this->cacheLogger && $cached) { - $this->cacheLogger->entityCachePut($this->regionName, $key); - } - - return $isChanged; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadOnlyCachedEntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadOnlyCachedEntityPersister.php deleted file mode 100644 index ce93d7b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadOnlyCachedEntityPersister.php +++ /dev/null @@ -1,41 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Persister\Entity; - -use Doctrine\ORM\Cache\CacheException; -use Doctrine\Common\Util\ClassUtils; - -/** - * Specific read-only region entity persister - * - * @author Fabio B. Silva - * @since 2.5 - */ -class ReadOnlyCachedEntityPersister extends NonStrictReadWriteCachedEntityPersister -{ - /** - * {@inheritdoc} - */ - public function update($entity) - { - throw CacheException::updateReadOnlyEntity(ClassUtils::getClass($entity)); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php deleted file mode 100644 index 79a4c8c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Persister/Entity/ReadWriteCachedEntityPersister.php +++ /dev/null @@ -1,143 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Persister\Entity; - -use Doctrine\ORM\Persisters\Entity\EntityPersister; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Cache\ConcurrentRegion; -use Doctrine\ORM\Cache\EntityCacheKey; - -/** - * Specific read-write entity persister - * - * @author Fabio B. Silva - * @author Guilherme Blanco - * @since 2.5 - */ -class ReadWriteCachedEntityPersister extends AbstractEntityPersister -{ - /** - * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $persister The entity persister to cache. - * @param \Doctrine\ORM\Cache\ConcurrentRegion $region The entity cache region. - * @param \Doctrine\ORM\EntityManagerInterface $em The entity manager. - * @param \Doctrine\ORM\Mapping\ClassMetadata $class The entity metadata. - */ - public function __construct(EntityPersister $persister, ConcurrentRegion $region, EntityManagerInterface $em, ClassMetadata $class) - { - parent::__construct($persister, $region, $em, $class); - } - - /** - * {@inheritdoc} - */ - public function afterTransactionComplete() - { - $isChanged = true; - - if (isset($this->queuedCache['update'])) { - foreach ($this->queuedCache['update'] as $item) { - $this->region->evict($item['key']); - - $isChanged = true; - } - } - - if (isset($this->queuedCache['delete'])) { - foreach ($this->queuedCache['delete'] as $item) { - $this->region->evict($item['key']); - - $isChanged = true; - } - } - - if ($isChanged) { - $this->timestampRegion->update($this->timestampKey); - } - - $this->queuedCache = []; - } - - /** - * {@inheritdoc} - */ - public function afterTransactionRolledBack() - { - if (isset($this->queuedCache['update'])) { - foreach ($this->queuedCache['update'] as $item) { - $this->region->evict($item['key']); - } - } - - if (isset($this->queuedCache['delete'])) { - foreach ($this->queuedCache['delete'] as $item) { - $this->region->evict($item['key']); - } - } - - $this->queuedCache = []; - } - - /** - * {@inheritdoc} - */ - public function delete($entity) - { - $key = new EntityCacheKey($this->class->rootEntityName, $this->uow->getEntityIdentifier($entity)); - $lock = $this->region->lock($key); - $deleted = $this->persister->delete($entity); - - if ($deleted) { - $this->region->evict($key); - } - - if ($lock === null) { - return $deleted; - } - - $this->queuedCache['delete'][] = [ - 'lock' => $lock, - 'key' => $key - ]; - - return $deleted; - } - - /** - * {@inheritdoc} - */ - public function update($entity) - { - $key = new EntityCacheKey($this->class->rootEntityName, $this->uow->getEntityIdentifier($entity)); - $lock = $this->region->lock($key); - - $this->persister->update($entity); - - if ($lock === null) { - return; - } - - $this->queuedCache['update'][] = [ - 'lock' => $lock, - 'key' => $key - ]; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCache.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCache.php deleted file mode 100644 index de24962..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCache.php +++ /dev/null @@ -1,62 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -use Doctrine\ORM\Query\ResultSetMapping; - -/** - * Defines the contract for caches capable of storing query results. - * These caches should only concern themselves with storing the matching result ids. - * - * @since 2.5 - * @author Fabio B. Silva - */ -interface QueryCache -{ - /** - * @return boolean - */ - public function clear(); - - /** - * @param \Doctrine\ORM\Cache\QueryCacheKey $key - * @param \Doctrine\ORM\Query\ResultSetMapping $rsm - * @param mixed $result - * @param array $hints - * - * @return boolean - */ - public function put(QueryCacheKey $key, ResultSetMapping $rsm, $result, array $hints = []); - - /** - * @param \Doctrine\ORM\Cache\QueryCacheKey $key - * @param \Doctrine\ORM\Query\ResultSetMapping $rsm - * @param array $hints - * - * @return array|null - */ - public function get(QueryCacheKey $key, ResultSetMapping $rsm, array $hints = []); - - /** - * @return \Doctrine\ORM\Cache\Region - */ - public function getRegion(); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheEntry.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheEntry.php deleted file mode 100644 index b6af393..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheEntry.php +++ /dev/null @@ -1,64 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Query cache entry - * - * @since 2.5 - * @author Fabio B. Silva - */ -class QueryCacheEntry implements CacheEntry -{ - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var array List of entity identifiers - */ - public $result; - - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var float Time creation of this cache entry - */ - public $time; - - /** - * @param array $result - * @param float $time - */ - public function __construct($result, $time = null) - { - $this->result = $result; - $this->time = $time ?: microtime(true); - } - - /** - * @param array $values - * - * @return QueryCacheEntry - */ - public static function __set_state(array $values) - { - return new self($values['result'], $values['time']); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheKey.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheKey.php deleted file mode 100644 index 0e072a3..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheKey.php +++ /dev/null @@ -1,71 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -use Doctrine\ORM\Cache; - -/** - * A cache key that identifies a particular query. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class QueryCacheKey extends CacheKey -{ - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var integer Cache key lifetime - */ - public $lifetime; - - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var integer Cache mode (Doctrine\ORM\Cache::MODE_*) - */ - public $cacheMode; - - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var TimestampCacheKey|null - */ - public $timestampKey; - - /** - * @param string $hash Result cache id - * @param integer $lifetime Query lifetime - * @param int $cacheMode Query cache mode - * @param TimestampCacheKey|null $timestampKey - */ - public function __construct( - $hash, - $lifetime = 0, - $cacheMode = Cache::MODE_NORMAL, - TimestampCacheKey $timestampKey = null - ) { - $this->hash = $hash; - $this->lifetime = $lifetime; - $this->cacheMode = $cacheMode; - $this->timestampKey = $timestampKey; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheValidator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheValidator.php deleted file mode 100644 index 682a41e..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/QueryCacheValidator.php +++ /dev/null @@ -1,40 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Cache query validator interface. - * - * @since 2.5 - * @author Fabio B. Silva - */ -interface QueryCacheValidator -{ - /** - * Checks if the query entry is valid - * - * @param \Doctrine\ORM\Cache\QueryCacheKey $key - * @param \Doctrine\ORM\Cache\QueryCacheEntry $entry - * - * @return boolean - */ - public function isValid(QueryCacheKey $key, QueryCacheEntry $entry); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region.php deleted file mode 100644 index 3bffbbc..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region.php +++ /dev/null @@ -1,84 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Defines a contract for accessing a particular named region. - * - * @since 2.5 - * @author Fabio B. Silva - */ -interface Region extends MultiGetRegion -{ - /** - * Retrieve the name of this region. - * - * @return string The region name - */ - public function getName(); - - /** - * Determine whether this region contains data for the given key. - * - * @param \Doctrine\ORM\Cache\CacheKey $key The cache key - * - * @return boolean TRUE if the underlying cache contains corresponding data; FALSE otherwise. - */ - public function contains(CacheKey $key); - - /** - * Get an item from the cache. - * - * @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to be retrieved. - * - * @return \Doctrine\ORM\Cache\CacheEntry|null The cached entry or NULL - * - * @throws \Doctrine\ORM\Cache\CacheException Indicates a problem accessing the item or region. - */ - public function get(CacheKey $key); - - /** - * Put an item into the cache. - * - * @param \Doctrine\ORM\Cache\CacheKey $key The key under which to cache the item. - * @param \Doctrine\ORM\Cache\CacheEntry $entry The entry to cache. - * @param \Doctrine\ORM\Cache\Lock $lock The lock previously obtained. - * - * @throws \Doctrine\ORM\Cache\CacheException Indicates a problem accessing the region. - */ - public function put(CacheKey $key, CacheEntry $entry, Lock $lock = null); - - /** - * Remove an item from the cache. - * - * @param \Doctrine\ORM\Cache\CacheKey $key The key under which to cache the item. - * - * @throws \Doctrine\ORM\Cache\CacheException Indicates a problem accessing the region. - */ - public function evict(CacheKey $key); - - /** - * Remove all contents of this particular cache region. - * - * @throws \Doctrine\ORM\Cache\CacheException Indicates problem accessing the region. - */ - public function evictAll(); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultMultiGetRegion.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultMultiGetRegion.php deleted file mode 100644 index 7b5f28e..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultMultiGetRegion.php +++ /dev/null @@ -1,82 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Region; - -use Doctrine\Common\Cache\MultiGetCache; -use Doctrine\ORM\Cache\CacheEntry; -use Doctrine\ORM\Cache\CollectionCacheEntry; - -/** - * A cache region that enables the retrieval of multiple elements with one call - * - * @since 2.5 - * @author Asmir Mustafic - */ -class DefaultMultiGetRegion extends DefaultRegion -{ - /** - * Note that the multiple type is due to doctrine/cache not integrating the MultiGetCache interface - * in its signature due to BC in 1.x - * - * @var MultiGetCache|\Doctrine\Common\Cache\Cache - */ - protected $cache; - - /** - * {@inheritDoc} - * - * @param MultiGetCache $cache - */ - public function __construct($name, MultiGetCache $cache, $lifetime = 0) - { - /* @var $cache \Doctrine\Common\Cache\Cache */ - parent::__construct($name, $cache, $lifetime); - } - - /** - * {@inheritdoc} - */ - public function getMultiple(CollectionCacheEntry $collection) - { - $keysToRetrieve = []; - - foreach ($collection->identifiers as $index => $key) { - $keysToRetrieve[$index] = $this->getCacheEntryKey($key); - } - - $items = $this->cache->fetchMultiple($keysToRetrieve); - if (count($items) !== count($keysToRetrieve)) { - return null; - } - - $returnableItems = []; - - foreach ($keysToRetrieve as $index => $key) { - if (! $items[$key] instanceof CacheEntry) { - return null; - } - - $returnableItems[$index] = $items[$key]; - } - - return $returnableItems; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultRegion.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultRegion.php deleted file mode 100644 index ab069ce..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/DefaultRegion.php +++ /dev/null @@ -1,166 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Region; - -use Doctrine\Common\Cache\Cache as CacheAdapter; -use Doctrine\Common\Cache\ClearableCache; -use Doctrine\ORM\Cache\CacheEntry; -use Doctrine\ORM\Cache\CacheKey; -use Doctrine\ORM\Cache\CollectionCacheEntry; -use Doctrine\ORM\Cache\Lock; -use Doctrine\ORM\Cache\Region; - -/** - * The simplest cache region compatible with all doctrine-cache drivers. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class DefaultRegion implements Region -{ - const REGION_KEY_SEPARATOR = '_'; - - /** - * @var CacheAdapter - */ - protected $cache; - - /** - * @var string - */ - protected $name; - - /** - * @var integer - */ - protected $lifetime = 0; - - /** - * @param string $name - * @param CacheAdapter $cache - * @param integer $lifetime - */ - public function __construct($name, CacheAdapter $cache, $lifetime = 0) - { - $this->cache = $cache; - $this->name = (string) $name; - $this->lifetime = (integer) $lifetime; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - /** - * @return \Doctrine\Common\Cache\CacheProvider - */ - public function getCache() - { - return $this->cache; - } - - /** - * {@inheritdoc} - */ - public function contains(CacheKey $key) - { - return $this->cache->contains($this->getCacheEntryKey($key)); - } - - /** - * {@inheritdoc} - */ - public function get(CacheKey $key) - { - $entry = $this->cache->fetch($this->getCacheEntryKey($key)); - - if (! $entry instanceof CacheEntry) { - return null; - } - - return $entry; - } - - /** - * {@inheritdoc} - */ - public function getMultiple(CollectionCacheEntry $collection) - { - $result = []; - - foreach ($collection->identifiers as $key) { - $entryKey = $this->getCacheEntryKey($key); - $entryValue = $this->cache->fetch($entryKey); - - if (! $entryValue instanceof CacheEntry) { - return null; - } - - $result[] = $entryValue; - } - - return $result; - } - - /** - * @param CacheKey $key - * @return string - */ - protected function getCacheEntryKey(CacheKey $key) - { - return $this->name . self::REGION_KEY_SEPARATOR . $key->hash; - } - - /** - * {@inheritdoc} - */ - public function put(CacheKey $key, CacheEntry $entry, Lock $lock = null) - { - return $this->cache->save($this->getCacheEntryKey($key), $entry, $this->lifetime); - } - - /** - * {@inheritdoc} - */ - public function evict(CacheKey $key) - { - return $this->cache->delete($this->getCacheEntryKey($key)); - } - - /** - * {@inheritdoc} - */ - public function evictAll() - { - if (! $this->cache instanceof ClearableCache) { - throw new \BadMethodCallException(sprintf( - 'Clearing all cache entries is not supported by the supplied cache adapter of type %s', - get_class($this->cache) - )); - } - - return $this->cache->deleteAll(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/FileLockRegion.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/FileLockRegion.php deleted file mode 100644 index 880d9da..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/FileLockRegion.php +++ /dev/null @@ -1,265 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Region; - -use Doctrine\ORM\Cache\CollectionCacheEntry; -use Doctrine\ORM\Cache\Lock; -use Doctrine\ORM\Cache\Region; -use Doctrine\ORM\Cache\CacheKey; -use Doctrine\ORM\Cache\CacheEntry; -use Doctrine\ORM\Cache\ConcurrentRegion; - -/** - * Very naive concurrent region, based on file locks. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class FileLockRegion implements ConcurrentRegion -{ - const LOCK_EXTENSION = 'lock'; - - /** - * var \Doctrine\ORM\Cache\Region - */ - private $region; - - /** - * @var string - */ - private $directory; - - /** - * var integer - */ - private $lockLifetime; - - /** - * @param \Doctrine\ORM\Cache\Region $region - * @param string $directory - * @param string $lockLifetime - * - * @throws \InvalidArgumentException - */ - public function __construct(Region $region, $directory, $lockLifetime) - { - if ( ! is_dir($directory) && ! @mkdir($directory, 0775, true)) { - throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $directory)); - } - - if ( ! is_writable($directory)) { - throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable.', $directory)); - } - - $this->region = $region; - $this->directory = $directory; - $this->lockLifetime = $lockLifetime; - } - - /** - * @param \Doctrine\ORM\Cache\CacheKey $key - * @param \Doctrine\ORM\Cache\Lock $lock - * - * @return boolean - */ - private function isLocked(CacheKey $key, Lock $lock = null) - { - $filename = $this->getLockFileName($key); - - if ( ! is_file($filename)) { - return false; - } - - $time = $this->getLockTime($filename); - $content = $this->getLockContent($filename); - - if ( ! $content || ! $time) { - @unlink($filename); - - return false; - } - - if ($lock && $content === $lock->value) { - return false; - } - - // outdated lock - if (($time + $this->lockLifetime) <= time()) { - @unlink($filename); - - return false; - } - - return true; - } - - /** - * @param \Doctrine\ORM\Cache\CacheKey $key - * - * @return string - */ - private function getLockFileName(CacheKey $key) - { - return $this->directory . DIRECTORY_SEPARATOR . $key->hash . '.' . self::LOCK_EXTENSION; - } - - /** - * @param string $filename - * - * @return string - */ - private function getLockContent($filename) - { - return @file_get_contents($filename); - } - - /** - * @param string $filename - * - * @return integer - */ - private function getLockTime($filename) - { - return @fileatime($filename); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->region->getName(); - } - - /** - * {@inheritdoc} - */ - public function contains(CacheKey $key) - { - if ($this->isLocked($key)) { - return false; - } - - return $this->region->contains($key); - } - - /** - * {@inheritdoc} - */ - public function get(CacheKey $key) - { - if ($this->isLocked($key)) { - return null; - } - - return $this->region->get($key); - } - - /** - * {@inheritdoc} - */ - public function getMultiple(CollectionCacheEntry $collection) - { - if (array_filter(array_map([$this, 'isLocked'], $collection->identifiers))) { - return null; - } - - return $this->region->getMultiple($collection); - } - - /** - * {@inheritdoc} - */ - public function put(CacheKey $key, CacheEntry $entry, Lock $lock = null) - { - if ($this->isLocked($key, $lock)) { - return false; - } - - return $this->region->put($key, $entry); - } - - /** - * {@inheritdoc} - */ - public function evict(CacheKey $key) - { - if ($this->isLocked($key)) { - @unlink($this->getLockFileName($key)); - } - - return $this->region->evict($key); - } - - /** - * {@inheritdoc} - */ - public function evictAll() - { - // The check below is necessary because on some platforms glob returns false - // when nothing matched (even though no errors occurred) - $filenames = glob(sprintf("%s/*.%s" , $this->directory, self::LOCK_EXTENSION)); - - if ($filenames) { - foreach ($filenames as $filename) { - @unlink($filename); - } - } - - return $this->region->evictAll(); - } - - /** - * {@inheritdoc} - */ - public function lock(CacheKey $key) - { - if ($this->isLocked($key)) { - return null; - } - - $lock = Lock::createLockRead(); - $filename = $this->getLockFileName($key); - - if ( ! @file_put_contents($filename, $lock->value, LOCK_EX)) { - return null; - } - chmod($filename, 0664); - - return $lock; - } - - /** - * {@inheritdoc} - */ - public function unlock(CacheKey $key, Lock $lock) - { - if ($this->isLocked($key, $lock)) { - return false; - } - - if ( ! @unlink($this->getLockFileName($key))) { - return false; - } - - return true; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/UpdateTimestampCache.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/UpdateTimestampCache.php deleted file mode 100644 index dfdf906..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/Region/UpdateTimestampCache.php +++ /dev/null @@ -1,42 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache\Region; - -use Doctrine\ORM\Cache\TimestampCacheEntry; -use Doctrine\ORM\Cache\TimestampRegion; -use Doctrine\ORM\Cache\CacheKey; - -/** - * Tracks the timestamps of the most recent updates to particular keys. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class UpdateTimestampCache extends DefaultRegion implements TimestampRegion -{ - /** - * {@inheritdoc} - */ - public function update(CacheKey $key) - { - $this->put($key, new TimestampCacheEntry); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/RegionsConfiguration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/RegionsConfiguration.php deleted file mode 100644 index d79c5b1..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/RegionsConfiguration.php +++ /dev/null @@ -1,134 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Cache regions configuration - * - * @since 2.5 - * @author Fabio B. Silva - */ -class RegionsConfiguration -{ - /** - * @var array - */ - private $lifetimes = []; - - /** - * @var array - */ - private $lockLifetimes = []; - - /** - * @var integer - */ - private $defaultLifetime; - - /** - * @var integer - */ - private $defaultLockLifetime; - - /** - * @param integer $defaultLifetime - * @param integer $defaultLockLifetime - */ - public function __construct($defaultLifetime = 3600, $defaultLockLifetime = 60) - { - $this->defaultLifetime = (integer) $defaultLifetime; - $this->defaultLockLifetime = (integer) $defaultLockLifetime; - } - - /** - * @return integer - */ - public function getDefaultLifetime() - { - return $this->defaultLifetime; - } - - /** - * @param integer $defaultLifetime - */ - public function setDefaultLifetime($defaultLifetime) - { - $this->defaultLifetime = (integer) $defaultLifetime; - } - - /** - * @return integer - */ - public function getDefaultLockLifetime() - { - return $this->defaultLockLifetime; - } - - /** - * @param integer $defaultLockLifetime - */ - public function setDefaultLockLifetime($defaultLockLifetime) - { - $this->defaultLockLifetime = (integer) $defaultLockLifetime; - } - - /** - * @param string $regionName - * - * @return integer - */ - public function getLifetime($regionName) - { - return isset($this->lifetimes[$regionName]) - ? $this->lifetimes[$regionName] - : $this->defaultLifetime; - } - - /** - * @param string $name - * @param integer $lifetime - */ - public function setLifetime($name, $lifetime) - { - $this->lifetimes[$name] = (integer) $lifetime; - } - - /** - * @param string $regionName - * - * @return integer - */ - public function getLockLifetime($regionName) - { - return isset($this->lockLifetimes[$regionName]) - ? $this->lockLifetimes[$regionName] - : $this->defaultLockLifetime; - } - - /** - * @param string $name - * @param integer $lifetime - */ - public function setLockLifetime($name, $lifetime) - { - $this->lockLifetimes[$name] = (integer) $lifetime; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheEntry.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheEntry.php deleted file mode 100644 index 0b7ce0b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheEntry.php +++ /dev/null @@ -1,59 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Timestamp cache entry - * - * @since 2.5 - * @author Fabio B. Silva - */ -class TimestampCacheEntry implements CacheEntry -{ - /** - * READ-ONLY: Public only for performance reasons, it should be considered immutable. - * - * @var float - */ - public $time; - - /** - * @param float $time - */ - public function __construct($time = null) - { - $this->time = $time ? (float) $time : microtime(true); - } - - /** - * Creates a new TimestampCacheEntry - * - * This method allow Doctrine\Common\Cache\PhpFileCache compatibility - * - * @param array $values array containing property values - * - * @return TimestampCacheEntry - */ - public static function __set_state(array $values) - { - return new self($values['time']); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheKey.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheKey.php deleted file mode 100644 index dfa7227..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampCacheKey.php +++ /dev/null @@ -1,38 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * A key that identifies a timestamped space. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class TimestampCacheKey extends CacheKey -{ - /** - * @param string $space Result cache id - */ - public function __construct($space) - { - $this->hash = (string) $space; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampQueryCacheValidator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampQueryCacheValidator.php deleted file mode 100644 index c6404d3..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampQueryCacheValidator.php +++ /dev/null @@ -1,74 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * @since 2.5 - * @author Fabio B. Silva - */ -class TimestampQueryCacheValidator implements QueryCacheValidator -{ - /** - * @var TimestampRegion - */ - private $timestampRegion; - - /** - * @param TimestampRegion $timestampRegion - */ - public function __construct(TimestampRegion $timestampRegion) - { - $this->timestampRegion = $timestampRegion; - } - - /** - * {@inheritdoc} - */ - public function isValid(QueryCacheKey $key, QueryCacheEntry $entry) - { - if ($this->regionUpdated($key, $entry)) { - return false; - } - - if ($key->lifetime == 0) { - return true; - } - - return ($entry->time + $key->lifetime) > microtime(true); - } - - /** - * @param QueryCacheKey $key - * @param QueryCacheEntry $entry - * - * @return bool - */ - private function regionUpdated(QueryCacheKey $key, QueryCacheEntry $entry) - { - if ($key->timestampKey === null) { - return false; - } - - $timestamp = $this->timestampRegion->get($key->timestampKey); - - return $timestamp && $timestamp->time > $entry->time; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampRegion.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampRegion.php deleted file mode 100644 index 9e0c25c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Cache/TimestampRegion.php +++ /dev/null @@ -1,39 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Cache; - -/** - * Defines the contract for a cache region which will specifically be used to store entity "update timestamps". - * - * @since 2.5 - * @author Fabio B. Silva - */ -interface TimestampRegion extends Region -{ - /** - * Update an specific key into the cache region. - * - * @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to update the timestamp. - * - * @throws \Doctrine\ORM\Cache\LockException Indicates a problem accessing the region. - */ - public function update(CacheKey $key); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Configuration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Configuration.php deleted file mode 100644 index c036d67..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Configuration.php +++ /dev/null @@ -1,920 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -use Doctrine\Common\Annotations\AnnotationReader; -use Doctrine\Common\Annotations\AnnotationRegistry; -use Doctrine\Common\Annotations\CachedReader; -use Doctrine\Common\Annotations\SimpleAnnotationReader; -use Doctrine\Common\Cache\ArrayCache; -use Doctrine\Common\Cache\Cache as CacheDriver; -use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver; -use Doctrine\Common\Persistence\ObjectRepository; -use Doctrine\Common\Proxy\AbstractProxyFactory; -use Doctrine\ORM\Cache\CacheConfiguration; -use Doctrine\ORM\Mapping\ClassMetadataFactory; -use Doctrine\ORM\Mapping\DefaultEntityListenerResolver; -use Doctrine\ORM\Mapping\DefaultNamingStrategy; -use Doctrine\ORM\Mapping\DefaultQuoteStrategy; -use Doctrine\ORM\Mapping\Driver\AnnotationDriver; -use Doctrine\ORM\Mapping\EntityListenerResolver; -use Doctrine\ORM\Mapping\NamingStrategy; -use Doctrine\ORM\Mapping\QuoteStrategy; -use Doctrine\ORM\Repository\DefaultRepositoryFactory; -use Doctrine\ORM\Repository\RepositoryFactory; - -/** - * Configuration container for all configuration options of Doctrine. - * It combines all configuration options from DBAL & ORM. - * - * Internal note: When adding a new configuration option just write a getter/setter pair. - * - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Configuration extends \Doctrine\DBAL\Configuration -{ - /** - * Sets the directory where Doctrine generates any necessary proxy class files. - * - * @param string $dir - * - * @return void - */ - public function setProxyDir($dir) - { - $this->_attributes['proxyDir'] = $dir; - } - - /** - * Gets the directory where Doctrine generates any necessary proxy class files. - * - * @return string|null - * - * @deprecated 2.7 We're switch to `ocramius/proxy-manager` and this method isn't applicable any longer - * @see https://github.com/Ocramius/ProxyManager - */ - public function getProxyDir() - { - return isset($this->_attributes['proxyDir']) - ? $this->_attributes['proxyDir'] - : null; - } - - /** - * Gets the strategy for automatically generating proxy classes. - * - * @return int Possible values are constants of Doctrine\Common\Proxy\AbstractProxyFactory. - * - * @deprecated 2.7 We're switch to `ocramius/proxy-manager` and this method isn't applicable any longer - * @see https://github.com/Ocramius/ProxyManager - */ - public function getAutoGenerateProxyClasses() - { - return isset($this->_attributes['autoGenerateProxyClasses']) - ? $this->_attributes['autoGenerateProxyClasses'] - : AbstractProxyFactory::AUTOGENERATE_ALWAYS; - } - - /** - * Sets the strategy for automatically generating proxy classes. - * - * @param boolean|int $autoGenerate Possible values are constants of Doctrine\Common\Proxy\AbstractProxyFactory. - * True is converted to AUTOGENERATE_ALWAYS, false to AUTOGENERATE_NEVER. - * - * @return void - */ - public function setAutoGenerateProxyClasses($autoGenerate) - { - $this->_attributes['autoGenerateProxyClasses'] = (int) $autoGenerate; - } - - /** - * Gets the namespace where proxy classes reside. - * - * @return string|null - * - * @deprecated 2.7 We're switch to `ocramius/proxy-manager` and this method isn't applicable any longer - * @see https://github.com/Ocramius/ProxyManager - */ - public function getProxyNamespace() - { - return isset($this->_attributes['proxyNamespace']) - ? $this->_attributes['proxyNamespace'] - : null; - } - - /** - * Sets the namespace where proxy classes reside. - * - * @param string $ns - * - * @return void - */ - public function setProxyNamespace($ns) - { - $this->_attributes['proxyNamespace'] = $ns; - } - - /** - * Sets the cache driver implementation that is used for metadata caching. - * - * @param MappingDriver $driverImpl - * - * @return void - * - * @todo Force parameter to be a Closure to ensure lazy evaluation - * (as soon as a metadata cache is in effect, the driver never needs to initialize). - */ - public function setMetadataDriverImpl(MappingDriver $driverImpl) - { - $this->_attributes['metadataDriverImpl'] = $driverImpl; - } - - /** - * Adds a new default annotation driver with a correctly configured annotation reader. If $useSimpleAnnotationReader - * is true, the notation `@Entity` will work, otherwise, the notation `@ORM\Entity` will be supported. - * - * @param array $paths - * @param bool $useSimpleAnnotationReader - * - * @return AnnotationDriver - */ - public function newDefaultAnnotationDriver($paths = [], $useSimpleAnnotationReader = true) - { - AnnotationRegistry::registerFile(__DIR__ . '/Mapping/Driver/DoctrineAnnotations.php'); - - if ($useSimpleAnnotationReader) { - // Register the ORM Annotations in the AnnotationRegistry - $reader = new SimpleAnnotationReader(); - $reader->addNamespace('Doctrine\ORM\Mapping'); - $cachedReader = new CachedReader($reader, new ArrayCache()); - - return new AnnotationDriver($cachedReader, (array) $paths); - } - - return new AnnotationDriver( - new CachedReader(new AnnotationReader(), new ArrayCache()), - (array) $paths - ); - } - - /** - * Adds a namespace under a certain alias. - * - * @param string $alias - * @param string $namespace - * - * @return void - */ - public function addEntityNamespace($alias, $namespace) - { - $this->_attributes['entityNamespaces'][$alias] = $namespace; - } - - /** - * Resolves a registered namespace alias to the full namespace. - * - * @param string $entityNamespaceAlias - * - * @return string - * - * @throws ORMException - */ - public function getEntityNamespace($entityNamespaceAlias) - { - if ( ! isset($this->_attributes['entityNamespaces'][$entityNamespaceAlias])) { - throw ORMException::unknownEntityNamespace($entityNamespaceAlias); - } - - return trim($this->_attributes['entityNamespaces'][$entityNamespaceAlias], '\\'); - } - - /** - * Sets the entity alias map. - * - * @param array $entityNamespaces - * - * @return void - */ - public function setEntityNamespaces(array $entityNamespaces) - { - $this->_attributes['entityNamespaces'] = $entityNamespaces; - } - - /** - * Retrieves the list of registered entity namespace aliases. - * - * @return array - */ - public function getEntityNamespaces() - { - return $this->_attributes['entityNamespaces']; - } - - /** - * Gets the cache driver implementation that is used for the mapping metadata. - * - * @return MappingDriver|null - * - * @throws ORMException - */ - public function getMetadataDriverImpl() - { - return isset($this->_attributes['metadataDriverImpl']) - ? $this->_attributes['metadataDriverImpl'] - : null; - } - - /** - * Gets the cache driver implementation that is used for the query cache (SQL cache). - * - * @return \Doctrine\Common\Cache\Cache|null - */ - public function getQueryCacheImpl() - { - return isset($this->_attributes['queryCacheImpl']) - ? $this->_attributes['queryCacheImpl'] - : null; - } - - /** - * Sets the cache driver implementation that is used for the query cache (SQL cache). - * - * @param \Doctrine\Common\Cache\Cache $cacheImpl - * - * @return void - */ - public function setQueryCacheImpl(CacheDriver $cacheImpl) - { - $this->_attributes['queryCacheImpl'] = $cacheImpl; - } - - /** - * Gets the cache driver implementation that is used for the hydration cache (SQL cache). - * - * @return \Doctrine\Common\Cache\Cache|null - */ - public function getHydrationCacheImpl() - { - return isset($this->_attributes['hydrationCacheImpl']) - ? $this->_attributes['hydrationCacheImpl'] - : null; - } - - /** - * Sets the cache driver implementation that is used for the hydration cache (SQL cache). - * - * @param \Doctrine\Common\Cache\Cache $cacheImpl - * - * @return void - */ - public function setHydrationCacheImpl(CacheDriver $cacheImpl) - { - $this->_attributes['hydrationCacheImpl'] = $cacheImpl; - } - - /** - * Gets the cache driver implementation that is used for metadata caching. - * - * @return \Doctrine\Common\Cache\Cache|null - */ - public function getMetadataCacheImpl() - { - return isset($this->_attributes['metadataCacheImpl']) - ? $this->_attributes['metadataCacheImpl'] - : null; - } - - /** - * Sets the cache driver implementation that is used for metadata caching. - * - * @param \Doctrine\Common\Cache\Cache $cacheImpl - * - * @return void - */ - public function setMetadataCacheImpl(CacheDriver $cacheImpl) - { - $this->_attributes['metadataCacheImpl'] = $cacheImpl; - } - - /** - * Adds a named DQL query to the configuration. - * - * @param string $name The name of the query. - * @param string $dql The DQL query string. - * - * @return void - */ - public function addNamedQuery($name, $dql) - { - $this->_attributes['namedQueries'][$name] = $dql; - } - - /** - * Gets a previously registered named DQL query. - * - * @param string $name The name of the query. - * - * @return string The DQL query. - * - * @throws ORMException - */ - public function getNamedQuery($name) - { - if ( ! isset($this->_attributes['namedQueries'][$name])) { - throw ORMException::namedQueryNotFound($name); - } - - return $this->_attributes['namedQueries'][$name]; - } - - /** - * Adds a named native query to the configuration. - * - * @param string $name The name of the query. - * @param string $sql The native SQL query string. - * @param Query\ResultSetMapping $rsm The ResultSetMapping used for the results of the SQL query. - * - * @return void - */ - public function addNamedNativeQuery($name, $sql, Query\ResultSetMapping $rsm) - { - $this->_attributes['namedNativeQueries'][$name] = [$sql, $rsm]; - } - - /** - * Gets the components of a previously registered named native query. - * - * @param string $name The name of the query. - * - * @return array A tuple with the first element being the SQL string and the second - * element being the ResultSetMapping. - * - * @throws ORMException - */ - public function getNamedNativeQuery($name) - { - if ( ! isset($this->_attributes['namedNativeQueries'][$name])) { - throw ORMException::namedNativeQueryNotFound($name); - } - - return $this->_attributes['namedNativeQueries'][$name]; - } - - /** - * Ensures that this Configuration instance contains settings that are - * suitable for a production environment. - * - * @return void - * - * @throws ORMException If a configuration setting has a value that is not - * suitable for a production environment. - */ - public function ensureProductionSettings() - { - $queryCacheImpl = $this->getQueryCacheImpl(); - - if ( ! $queryCacheImpl) { - throw ORMException::queryCacheNotConfigured(); - } - - if ($queryCacheImpl instanceof ArrayCache) { - throw ORMException::queryCacheUsesNonPersistentCache($queryCacheImpl); - } - - $metadataCacheImpl = $this->getMetadataCacheImpl(); - - if ( ! $metadataCacheImpl) { - throw ORMException::metadataCacheNotConfigured(); - } - - if ($metadataCacheImpl instanceof ArrayCache) { - throw ORMException::metadataCacheUsesNonPersistentCache($metadataCacheImpl); - } - - if ($this->getAutoGenerateProxyClasses()) { - throw ORMException::proxyClassesAlwaysRegenerating(); - } - } - - /** - * Registers a custom DQL function that produces a string value. - * Such a function can then be used in any DQL statement in any place where string - * functions are allowed. - * - * DQL function names are case-insensitive. - * - * @param string $name Function name. - * @param string|callable $className Class name or a callable that returns the function. - * - * @return void - */ - public function addCustomStringFunction($name, $className) - { - $this->_attributes['customStringFunctions'][strtolower($name)] = $className; - } - - /** - * Gets the implementation class name of a registered custom string DQL function. - * - * @param string $name - * - * @return string|null - */ - public function getCustomStringFunction($name) - { - $name = strtolower($name); - - return isset($this->_attributes['customStringFunctions'][$name]) - ? $this->_attributes['customStringFunctions'][$name] - : null; - } - - /** - * Sets a map of custom DQL string functions. - * - * Keys must be function names and values the FQCN of the implementing class. - * The function names will be case-insensitive in DQL. - * - * Any previously added string functions are discarded. - * - * @param array $functions The map of custom DQL string functions. - * - * @return void - */ - public function setCustomStringFunctions(array $functions) - { - foreach ($functions as $name => $className) { - $this->addCustomStringFunction($name, $className); - } - } - - /** - * Registers a custom DQL function that produces a numeric value. - * Such a function can then be used in any DQL statement in any place where numeric - * functions are allowed. - * - * DQL function names are case-insensitive. - * - * @param string $name Function name. - * @param string|callable $className Class name or a callable that returns the function. - * - * @return void - */ - public function addCustomNumericFunction($name, $className) - { - $this->_attributes['customNumericFunctions'][strtolower($name)] = $className; - } - - /** - * Gets the implementation class name of a registered custom numeric DQL function. - * - * @param string $name - * - * @return string|null - */ - public function getCustomNumericFunction($name) - { - $name = strtolower($name); - - return isset($this->_attributes['customNumericFunctions'][$name]) - ? $this->_attributes['customNumericFunctions'][$name] - : null; - } - - /** - * Sets a map of custom DQL numeric functions. - * - * Keys must be function names and values the FQCN of the implementing class. - * The function names will be case-insensitive in DQL. - * - * Any previously added numeric functions are discarded. - * - * @param array $functions The map of custom DQL numeric functions. - * - * @return void - */ - public function setCustomNumericFunctions(array $functions) - { - foreach ($functions as $name => $className) { - $this->addCustomNumericFunction($name, $className); - } - } - - /** - * Registers a custom DQL function that produces a date/time value. - * Such a function can then be used in any DQL statement in any place where date/time - * functions are allowed. - * - * DQL function names are case-insensitive. - * - * @param string $name Function name. - * @param string|callable $className Class name or a callable that returns the function. - * - * @return void - */ - public function addCustomDatetimeFunction($name, $className) - { - $this->_attributes['customDatetimeFunctions'][strtolower($name)] = $className; - } - - /** - * Gets the implementation class name of a registered custom date/time DQL function. - * - * @param string $name - * - * @return string|null - */ - public function getCustomDatetimeFunction($name) - { - $name = strtolower($name); - - return isset($this->_attributes['customDatetimeFunctions'][$name]) - ? $this->_attributes['customDatetimeFunctions'][$name] - : null; - } - - /** - * Sets a map of custom DQL date/time functions. - * - * Keys must be function names and values the FQCN of the implementing class. - * The function names will be case-insensitive in DQL. - * - * Any previously added date/time functions are discarded. - * - * @param array $functions The map of custom DQL date/time functions. - * - * @return void - */ - public function setCustomDatetimeFunctions(array $functions) - { - foreach ($functions as $name => $className) { - $this->addCustomDatetimeFunction($name, $className); - } - } - - /** - * Sets the custom hydrator modes in one pass. - * - * @param array $modes An array of ($modeName => $hydrator). - * - * @return void - */ - public function setCustomHydrationModes($modes) - { - $this->_attributes['customHydrationModes'] = []; - - foreach ($modes as $modeName => $hydrator) { - $this->addCustomHydrationMode($modeName, $hydrator); - } - } - - /** - * Gets the hydrator class for the given hydration mode name. - * - * @param string $modeName The hydration mode name. - * - * @return string|null The hydrator class name. - */ - public function getCustomHydrationMode($modeName) - { - return isset($this->_attributes['customHydrationModes'][$modeName]) - ? $this->_attributes['customHydrationModes'][$modeName] - : null; - } - - /** - * Adds a custom hydration mode. - * - * @param string $modeName The hydration mode name. - * @param string $hydrator The hydrator class name. - * - * @return void - */ - public function addCustomHydrationMode($modeName, $hydrator) - { - $this->_attributes['customHydrationModes'][$modeName] = $hydrator; - } - - /** - * Sets a class metadata factory. - * - * @param string $cmfName - * - * @return void - */ - public function setClassMetadataFactoryName($cmfName) - { - $this->_attributes['classMetadataFactoryName'] = $cmfName; - } - - /** - * @return string - */ - public function getClassMetadataFactoryName() - { - if ( ! isset($this->_attributes['classMetadataFactoryName'])) { - $this->_attributes['classMetadataFactoryName'] = ClassMetadataFactory::class; - } - - return $this->_attributes['classMetadataFactoryName']; - } - - /** - * Adds a filter to the list of possible filters. - * - * @param string $name The name of the filter. - * @param string $className The class name of the filter. - */ - public function addFilter($name, $className) - { - $this->_attributes['filters'][$name] = $className; - } - - /** - * Gets the class name for a given filter name. - * - * @param string $name The name of the filter. - * - * @return string The class name of the filter, or null if it is not - * defined. - */ - public function getFilterClassName($name) - { - return isset($this->_attributes['filters'][$name]) - ? $this->_attributes['filters'][$name] - : null; - } - - /** - * Sets default repository class. - * - * @since 2.2 - * - * @param string $className - * - * @return void - * - * @throws ORMException If not is a \Doctrine\Common\Persistence\ObjectRepository - */ - public function setDefaultRepositoryClassName($className) - { - $reflectionClass = new \ReflectionClass($className); - - if ( ! $reflectionClass->implementsInterface(ObjectRepository::class)) { - throw ORMException::invalidEntityRepository($className); - } - - $this->_attributes['defaultRepositoryClassName'] = $className; - } - - /** - * Get default repository class. - * - * @since 2.2 - * - * @return string - */ - public function getDefaultRepositoryClassName() - { - return isset($this->_attributes['defaultRepositoryClassName']) - ? $this->_attributes['defaultRepositoryClassName'] - : EntityRepository::class; - } - - /** - * Sets naming strategy. - * - * @since 2.3 - * - * @param NamingStrategy $namingStrategy - * - * @return void - */ - public function setNamingStrategy(NamingStrategy $namingStrategy) - { - $this->_attributes['namingStrategy'] = $namingStrategy; - } - - /** - * Gets naming strategy.. - * - * @since 2.3 - * - * @return NamingStrategy - */ - public function getNamingStrategy() - { - if ( ! isset($this->_attributes['namingStrategy'])) { - $this->_attributes['namingStrategy'] = new DefaultNamingStrategy(); - } - - return $this->_attributes['namingStrategy']; - } - - /** - * Sets quote strategy. - * - * @since 2.3 - * - * @param \Doctrine\ORM\Mapping\QuoteStrategy $quoteStrategy - * - * @return void - */ - public function setQuoteStrategy(QuoteStrategy $quoteStrategy) - { - $this->_attributes['quoteStrategy'] = $quoteStrategy; - } - - /** - * Gets quote strategy. - * - * @since 2.3 - * - * @return \Doctrine\ORM\Mapping\QuoteStrategy - */ - public function getQuoteStrategy() - { - if ( ! isset($this->_attributes['quoteStrategy'])) { - $this->_attributes['quoteStrategy'] = new DefaultQuoteStrategy(); - } - - return $this->_attributes['quoteStrategy']; - } - - /** - * Set the entity listener resolver. - * - * @since 2.4 - * @param \Doctrine\ORM\Mapping\EntityListenerResolver $resolver - */ - public function setEntityListenerResolver(EntityListenerResolver $resolver) - { - $this->_attributes['entityListenerResolver'] = $resolver; - } - - /** - * Get the entity listener resolver. - * - * @since 2.4 - * @return \Doctrine\ORM\Mapping\EntityListenerResolver - */ - public function getEntityListenerResolver() - { - if ( ! isset($this->_attributes['entityListenerResolver'])) { - $this->_attributes['entityListenerResolver'] = new DefaultEntityListenerResolver(); - } - - return $this->_attributes['entityListenerResolver']; - } - - /** - * Set the entity repository factory. - * - * @since 2.4 - * @param \Doctrine\ORM\Repository\RepositoryFactory $repositoryFactory - */ - public function setRepositoryFactory(RepositoryFactory $repositoryFactory) - { - $this->_attributes['repositoryFactory'] = $repositoryFactory; - } - - /** - * Get the entity repository factory. - * - * @since 2.4 - * @return \Doctrine\ORM\Repository\RepositoryFactory - */ - public function getRepositoryFactory() - { - return isset($this->_attributes['repositoryFactory']) - ? $this->_attributes['repositoryFactory'] - : new DefaultRepositoryFactory(); - } - - /** - * @since 2.5 - * - * @return boolean - */ - public function isSecondLevelCacheEnabled() - { - return isset($this->_attributes['isSecondLevelCacheEnabled']) - ? $this->_attributes['isSecondLevelCacheEnabled'] - : false; - } - - /** - * @since 2.5 - * - * @param boolean $flag - * - * @return void - */ - public function setSecondLevelCacheEnabled($flag = true) - { - $this->_attributes['isSecondLevelCacheEnabled'] = (boolean) $flag; - } - - /** - * @since 2.5 - * - * @param \Doctrine\ORM\Cache\CacheConfiguration $cacheConfig - * - * @return void - */ - public function setSecondLevelCacheConfiguration(CacheConfiguration $cacheConfig) - { - $this->_attributes['secondLevelCacheConfiguration'] = $cacheConfig; - } - - /** - * @since 2.5 - * - * @return \Doctrine\ORM\Cache\CacheConfiguration|null - */ - public function getSecondLevelCacheConfiguration() - { - if ( ! isset($this->_attributes['secondLevelCacheConfiguration']) && $this->isSecondLevelCacheEnabled()) { - $this->_attributes['secondLevelCacheConfiguration'] = new CacheConfiguration(); - } - - return isset($this->_attributes['secondLevelCacheConfiguration']) - ? $this->_attributes['secondLevelCacheConfiguration'] - : null; - } - - /** - * Returns query hints, which will be applied to every query in application - * - * @since 2.5 - * - * @return array - */ - public function getDefaultQueryHints() - { - return isset($this->_attributes['defaultQueryHints']) ? $this->_attributes['defaultQueryHints'] : []; - } - - /** - * Sets array of query hints, which will be applied to every query in application - * - * @since 2.5 - * - * @param array $defaultQueryHints - */ - public function setDefaultQueryHints(array $defaultQueryHints) - { - $this->_attributes['defaultQueryHints'] = $defaultQueryHints; - } - - /** - * Gets the value of a default query hint. If the hint name is not recognized, FALSE is returned. - * - * @since 2.5 - * - * @param string $name The name of the hint. - * - * @return mixed The value of the hint or FALSE, if the hint name is not recognized. - */ - public function getDefaultQueryHint($name) - { - return isset($this->_attributes['defaultQueryHints'][$name]) - ? $this->_attributes['defaultQueryHints'][$name] - : false; - } - - /** - * Sets a default query hint. If the hint name is not recognized, it is silently ignored. - * - * @since 2.5 - * - * @param string $name The name of the hint. - * @param mixed $value The value of the hint. - */ - public function setDefaultQueryHint($name, $value) - { - $this->_attributes['defaultQueryHints'][$name] = $value; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Decorator/EntityManagerDecorator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Decorator/EntityManagerDecorator.php deleted file mode 100644 index 69cc6f5..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Decorator/EntityManagerDecorator.php +++ /dev/null @@ -1,278 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Decorator; - -use Doctrine\ORM\Query\ResultSetMapping; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\Common\Persistence\ObjectManagerDecorator; - -/** - * Base class for EntityManager decorators - * - * @since 2.4 - * @author Lars Strojny wrapped = $wrapped; - } - - /** - * {@inheritdoc} - */ - public function getConnection() - { - return $this->wrapped->getConnection(); - } - - /** - * {@inheritdoc} - */ - public function getExpressionBuilder() - { - return $this->wrapped->getExpressionBuilder(); - } - - /** - * {@inheritdoc} - */ - public function beginTransaction() - { - return $this->wrapped->beginTransaction(); - } - - /** - * {@inheritdoc} - */ - public function transactional($func) - { - return $this->wrapped->transactional($func); - } - - /** - * {@inheritdoc} - */ - public function commit() - { - return $this->wrapped->commit(); - } - - /** - * {@inheritdoc} - */ - public function rollback() - { - return $this->wrapped->rollback(); - } - - /** - * {@inheritdoc} - */ - public function createQuery($dql = '') - { - return $this->wrapped->createQuery($dql); - } - - /** - * {@inheritdoc} - */ - public function createNamedQuery($name) - { - return $this->wrapped->createNamedQuery($name); - } - - /** - * {@inheritdoc} - */ - public function createNativeQuery($sql, ResultSetMapping $rsm) - { - return $this->wrapped->createNativeQuery($sql, $rsm); - } - - /** - * {@inheritdoc} - */ - public function createNamedNativeQuery($name) - { - return $this->wrapped->createNamedNativeQuery($name); - } - - /** - * {@inheritdoc} - */ - public function createQueryBuilder() - { - return $this->wrapped->createQueryBuilder(); - } - - /** - * {@inheritdoc} - */ - public function getReference($entityName, $id) - { - return $this->wrapped->getReference($entityName, $id); - } - - /** - * {@inheritdoc} - */ - public function getPartialReference($entityName, $identifier) - { - return $this->wrapped->getPartialReference($entityName, $identifier); - } - - /** - * {@inheritdoc} - */ - public function close() - { - return $this->wrapped->close(); - } - - /** - * {@inheritdoc} - */ - public function copy($entity, $deep = false) - { - return $this->wrapped->copy($entity, $deep); - } - - /** - * {@inheritdoc} - */ - public function lock($entity, $lockMode, $lockVersion = null) - { - return $this->wrapped->lock($entity, $lockMode, $lockVersion); - } - - /** - * {@inheritdoc} - */ - public function find($entityName, $id, $lockMode = null, $lockVersion = null) - { - return $this->wrapped->find($entityName, $id, $lockMode, $lockVersion); - } - - /** - * {@inheritdoc} - */ - public function flush($entity = null) - { - return $this->wrapped->flush($entity); - } - - /** - * {@inheritdoc} - */ - public function getEventManager() - { - return $this->wrapped->getEventManager(); - } - - /** - * {@inheritdoc} - */ - public function getConfiguration() - { - return $this->wrapped->getConfiguration(); - } - - /** - * {@inheritdoc} - */ - public function isOpen() - { - return $this->wrapped->isOpen(); - } - - /** - * {@inheritdoc} - */ - public function getUnitOfWork() - { - return $this->wrapped->getUnitOfWork(); - } - - /** - * {@inheritdoc} - */ - public function getHydrator($hydrationMode) - { - return $this->wrapped->getHydrator($hydrationMode); - } - - /** - * {@inheritdoc} - */ - public function newHydrator($hydrationMode) - { - return $this->wrapped->newHydrator($hydrationMode); - } - - /** - * {@inheritdoc} - */ - public function getProxyFactory() - { - return $this->wrapped->getProxyFactory(); - } - - /** - * {@inheritdoc} - */ - public function getFilters() - { - return $this->wrapped->getFilters(); - } - - /** - * {@inheritdoc} - */ - public function isFiltersStateClean() - { - return $this->wrapped->isFiltersStateClean(); - } - - /** - * {@inheritdoc} - */ - public function hasFilters() - { - return $this->wrapped->hasFilters(); - } - - /** - * {@inheritdoc} - */ - public function getCache() - { - return $this->wrapped->getCache(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php b/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php deleted file mode 100644 index 0752f0e..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php +++ /dev/null @@ -1,960 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -use Doctrine\Common\EventManager; -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\DriverManager; -use Doctrine\DBAL\LockMode; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Query\ResultSetMapping; -use Doctrine\ORM\Proxy\ProxyFactory; -use Doctrine\ORM\Query\FilterCollection; -use Doctrine\Common\Util\ClassUtils; -use Throwable; -use const E_USER_DEPRECATED; -use function trigger_error; - -/** - * The EntityManager is the central access point to ORM functionality. - * - * It is a facade to all different ORM subsystems such as UnitOfWork, - * Query Language and Repository API. Instantiation is done through - * the static create() method. The quickest way to obtain a fully - * configured EntityManager is: - * - * use Doctrine\ORM\Tools\Setup; - * use Doctrine\ORM\EntityManager; - * - * $paths = array('/path/to/entity/mapping/files'); - * - * $config = Setup::createAnnotationMetadataConfiguration($paths); - * $dbParams = array('driver' => 'pdo_sqlite', 'memory' => true); - * $entityManager = EntityManager::create($dbParams, $config); - * - * For more information see - * {@link http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/configuration.html} - * - * You should never attempt to inherit from the EntityManager: Inheritance - * is not a valid extension point for the EntityManager. Instead you - * should take a look at the {@see \Doctrine\ORM\Decorator\EntityManagerDecorator} - * and wrap your entity manager in a decorator. - * - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -/* final */class EntityManager implements EntityManagerInterface -{ - /** - * The used Configuration. - * - * @var \Doctrine\ORM\Configuration - */ - private $config; - - /** - * The database connection used by the EntityManager. - * - * @var \Doctrine\DBAL\Connection - */ - private $conn; - - /** - * The metadata factory, used to retrieve the ORM metadata of entity classes. - * - * @var \Doctrine\ORM\Mapping\ClassMetadataFactory - */ - private $metadataFactory; - - /** - * The UnitOfWork used to coordinate object-level transactions. - * - * @var \Doctrine\ORM\UnitOfWork - */ - private $unitOfWork; - - /** - * The event manager that is the central point of the event system. - * - * @var \Doctrine\Common\EventManager - */ - private $eventManager; - - /** - * The proxy factory used to create dynamic proxies. - * - * @var \Doctrine\ORM\Proxy\ProxyFactory - */ - private $proxyFactory; - - /** - * The repository factory used to create dynamic repositories. - * - * @var \Doctrine\ORM\Repository\RepositoryFactory - */ - private $repositoryFactory; - - /** - * The expression builder instance used to generate query expressions. - * - * @var \Doctrine\ORM\Query\Expr - */ - private $expressionBuilder; - - /** - * Whether the EntityManager is closed or not. - * - * @var bool - */ - private $closed = false; - - /** - * Collection of query filters. - * - * @var \Doctrine\ORM\Query\FilterCollection - */ - private $filterCollection; - - /** - * @var \Doctrine\ORM\Cache The second level cache regions API. - */ - private $cache; - - /** - * Creates a new EntityManager that operates on the given database connection - * and uses the given Configuration and EventManager implementations. - * - * @param \Doctrine\DBAL\Connection $conn - * @param \Doctrine\ORM\Configuration $config - * @param \Doctrine\Common\EventManager $eventManager - */ - protected function __construct(Connection $conn, Configuration $config, EventManager $eventManager) - { - $this->conn = $conn; - $this->config = $config; - $this->eventManager = $eventManager; - - $metadataFactoryClassName = $config->getClassMetadataFactoryName(); - - $this->metadataFactory = new $metadataFactoryClassName; - $this->metadataFactory->setEntityManager($this); - $this->metadataFactory->setCacheDriver($this->config->getMetadataCacheImpl()); - - $this->repositoryFactory = $config->getRepositoryFactory(); - $this->unitOfWork = new UnitOfWork($this); - $this->proxyFactory = new ProxyFactory( - $this, - $config->getProxyDir(), - $config->getProxyNamespace(), - $config->getAutoGenerateProxyClasses() - ); - - if ($config->isSecondLevelCacheEnabled()) { - $cacheConfig = $config->getSecondLevelCacheConfiguration(); - $cacheFactory = $cacheConfig->getCacheFactory(); - $this->cache = $cacheFactory->createCache($this); - } - } - - /** - * {@inheritDoc} - */ - public function getConnection() - { - return $this->conn; - } - - /** - * Gets the metadata factory used to gather the metadata of classes. - * - * @return \Doctrine\ORM\Mapping\ClassMetadataFactory - */ - public function getMetadataFactory() - { - return $this->metadataFactory; - } - - /** - * {@inheritDoc} - */ - public function getExpressionBuilder() - { - if ($this->expressionBuilder === null) { - $this->expressionBuilder = new Query\Expr; - } - - return $this->expressionBuilder; - } - - /** - * {@inheritDoc} - */ - public function beginTransaction() - { - $this->conn->beginTransaction(); - } - - /** - * {@inheritDoc} - */ - public function getCache() - { - return $this->cache; - } - - /** - * {@inheritDoc} - */ - public function transactional($func) - { - if (!is_callable($func)) { - throw new \InvalidArgumentException('Expected argument of type "callable", got "' . gettype($func) . '"'); - } - - $this->conn->beginTransaction(); - - try { - $return = call_user_func($func, $this); - - $this->flush(); - $this->conn->commit(); - - return $return ?: true; - } catch (Throwable $e) { - $this->close(); - $this->conn->rollBack(); - - throw $e; - } - } - - /** - * {@inheritDoc} - */ - public function commit() - { - $this->conn->commit(); - } - - /** - * {@inheritDoc} - */ - public function rollback() - { - $this->conn->rollBack(); - } - - /** - * Returns the ORM metadata descriptor for a class. - * - * The class name must be the fully-qualified class name without a leading backslash - * (as it is returned by get_class($obj)) or an aliased class name. - * - * Examples: - * MyProject\Domain\User - * sales:PriceRequest - * - * Internal note: Performance-sensitive method. - * - * @param string $className - * - * @return \Doctrine\ORM\Mapping\ClassMetadata - */ - public function getClassMetadata($className) - { - return $this->metadataFactory->getMetadataFor($className); - } - - /** - * {@inheritDoc} - */ - public function createQuery($dql = '') - { - $query = new Query($this); - - if ( ! empty($dql)) { - $query->setDQL($dql); - } - - return $query; - } - - /** - * {@inheritDoc} - */ - public function createNamedQuery($name) - { - return $this->createQuery($this->config->getNamedQuery($name)); - } - - /** - * {@inheritDoc} - */ - public function createNativeQuery($sql, ResultSetMapping $rsm) - { - $query = new NativeQuery($this); - - $query->setSQL($sql); - $query->setResultSetMapping($rsm); - - return $query; - } - - /** - * {@inheritDoc} - */ - public function createNamedNativeQuery($name) - { - list($sql, $rsm) = $this->config->getNamedNativeQuery($name); - - return $this->createNativeQuery($sql, $rsm); - } - - /** - * {@inheritDoc} - */ - public function createQueryBuilder() - { - return new QueryBuilder($this); - } - - /** - * Flushes all changes to objects that have been queued up to now to the database. - * This effectively synchronizes the in-memory state of managed objects with the - * database. - * - * If an entity is explicitly passed to this method only this entity and - * the cascade-persist semantics + scheduled inserts/removals are synchronized. - * - * @param null|object|array $entity - * - * @return void - * - * @throws \Doctrine\ORM\OptimisticLockException If a version check on an entity that - * makes use of optimistic locking fails. - * @throws ORMException - */ - public function flush($entity = null) - { - if ($entity !== null) { - @trigger_error( - 'Calling ' . __METHOD__ . '() with any arguments to flush specific entities is deprecated and will not be supported in Doctrine ORM 3.0.', - E_USER_DEPRECATED - ); - } - - $this->errorIfClosed(); - - $this->unitOfWork->commit($entity); - } - - /** - * Finds an Entity by its identifier. - * - * @param string $entityName The class name of the entity to find. - * @param mixed $id The identity of the entity to find. - * @param integer|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants - * or NULL if no specific lock mode should be used - * during the search. - * @param integer|null $lockVersion The version of the entity to find when using - * optimistic locking. - * - * @return object|null The entity instance or NULL if the entity can not be found. - * - * @throws OptimisticLockException - * @throws ORMInvalidArgumentException - * @throws TransactionRequiredException - * @throws ORMException - */ - public function find($entityName, $id, $lockMode = null, $lockVersion = null) - { - $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\')); - - if ($lockMode !== null) { - $this->checkLockRequirements($lockMode, $class); - } - - if ( ! is_array($id)) { - if ($class->isIdentifierComposite) { - throw ORMInvalidArgumentException::invalidCompositeIdentifier(); - } - - $id = [$class->identifier[0] => $id]; - } - - foreach ($id as $i => $value) { - if (is_object($value) && $this->metadataFactory->hasMetadataFor(ClassUtils::getClass($value))) { - $id[$i] = $this->unitOfWork->getSingleIdentifierValue($value); - - if ($id[$i] === null) { - throw ORMInvalidArgumentException::invalidIdentifierBindingEntity(); - } - } - } - - $sortedId = []; - - foreach ($class->identifier as $identifier) { - if ( ! isset($id[$identifier])) { - throw ORMException::missingIdentifierField($class->name, $identifier); - } - - $sortedId[$identifier] = $id[$identifier]; - unset($id[$identifier]); - } - - if ($id) { - throw ORMException::unrecognizedIdentifierFields($class->name, array_keys($id)); - } - - $unitOfWork = $this->getUnitOfWork(); - - // Check identity map first - if (($entity = $unitOfWork->tryGetById($sortedId, $class->rootEntityName)) !== false) { - if ( ! ($entity instanceof $class->name)) { - return null; - } - - switch (true) { - case LockMode::OPTIMISTIC === $lockMode: - $this->lock($entity, $lockMode, $lockVersion); - break; - - case LockMode::NONE === $lockMode: - case LockMode::PESSIMISTIC_READ === $lockMode: - case LockMode::PESSIMISTIC_WRITE === $lockMode: - $persister = $unitOfWork->getEntityPersister($class->name); - $persister->refresh($sortedId, $entity, $lockMode); - break; - } - - return $entity; // Hit! - } - - $persister = $unitOfWork->getEntityPersister($class->name); - - switch (true) { - case LockMode::OPTIMISTIC === $lockMode: - $entity = $persister->load($sortedId); - - $unitOfWork->lock($entity, $lockMode, $lockVersion); - - return $entity; - - case LockMode::PESSIMISTIC_READ === $lockMode: - case LockMode::PESSIMISTIC_WRITE === $lockMode: - return $persister->load($sortedId, null, null, [], $lockMode); - - default: - return $persister->loadById($sortedId); - } - } - - /** - * {@inheritDoc} - */ - public function getReference($entityName, $id) - { - $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\')); - - if ( ! is_array($id)) { - $id = [$class->identifier[0] => $id]; - } - - $sortedId = []; - - foreach ($class->identifier as $identifier) { - if ( ! isset($id[$identifier])) { - throw ORMException::missingIdentifierField($class->name, $identifier); - } - - $sortedId[$identifier] = $id[$identifier]; - unset($id[$identifier]); - } - - if ($id) { - throw ORMException::unrecognizedIdentifierFields($class->name, array_keys($id)); - } - - // Check identity map first, if its already in there just return it. - if (($entity = $this->unitOfWork->tryGetById($sortedId, $class->rootEntityName)) !== false) { - return ($entity instanceof $class->name) ? $entity : null; - } - - if ($class->subClasses) { - return $this->find($entityName, $sortedId); - } - - $entity = $this->proxyFactory->getProxy($class->name, $sortedId); - - $this->unitOfWork->registerManaged($entity, $sortedId, []); - - return $entity; - } - - /** - * {@inheritDoc} - */ - public function getPartialReference($entityName, $identifier) - { - $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\')); - - // Check identity map first, if its already in there just return it. - if (($entity = $this->unitOfWork->tryGetById($identifier, $class->rootEntityName)) !== false) { - return ($entity instanceof $class->name) ? $entity : null; - } - - if ( ! is_array($identifier)) { - $identifier = [$class->identifier[0] => $identifier]; - } - - $entity = $class->newInstance(); - - $class->setIdentifierValues($entity, $identifier); - - $this->unitOfWork->registerManaged($entity, $identifier, []); - $this->unitOfWork->markReadOnly($entity); - - return $entity; - } - - /** - * Clears the EntityManager. All entities that are currently managed - * by this EntityManager become detached. - * - * @param string|null $entityName if given, only entities of this type will get detached - * - * @return void - * - * @throws ORMInvalidArgumentException if a non-null non-string value is given - * @throws \Doctrine\Common\Persistence\Mapping\MappingException if a $entityName is given, but that entity is not - * found in the mappings - */ - public function clear($entityName = null) - { - if (null !== $entityName && ! is_string($entityName)) { - throw ORMInvalidArgumentException::invalidEntityName($entityName); - } - - if ($entityName !== null) { - @trigger_error( - 'Calling ' . __METHOD__ . '() with any arguments to clear specific entities is deprecated and will not be supported in Doctrine ORM 3.0.', - E_USER_DEPRECATED - ); - } - - $this->unitOfWork->clear( - null === $entityName - ? null - : $this->metadataFactory->getMetadataFor($entityName)->getName() - ); - } - - /** - * {@inheritDoc} - */ - public function close() - { - $this->clear(); - - $this->closed = true; - } - - /** - * Tells the EntityManager to make an instance managed and persistent. - * - * The entity will be entered into the database at or before transaction - * commit or as a result of the flush operation. - * - * NOTE: The persist operation always considers entities that are not yet known to - * this EntityManager as NEW. Do not pass detached entities to the persist operation. - * - * @param object $entity The instance to make managed and persistent. - * - * @return void - * - * @throws ORMInvalidArgumentException - * @throws ORMException - */ - public function persist($entity) - { - if ( ! is_object($entity)) { - throw ORMInvalidArgumentException::invalidObject('EntityManager#persist()', $entity); - } - - $this->errorIfClosed(); - - $this->unitOfWork->persist($entity); - } - - /** - * Removes an entity instance. - * - * A removed entity will be removed from the database at or before transaction commit - * or as a result of the flush operation. - * - * @param object $entity The entity instance to remove. - * - * @return void - * - * @throws ORMInvalidArgumentException - * @throws ORMException - */ - public function remove($entity) - { - if ( ! is_object($entity)) { - throw ORMInvalidArgumentException::invalidObject('EntityManager#remove()', $entity); - } - - $this->errorIfClosed(); - - $this->unitOfWork->remove($entity); - } - - /** - * Refreshes the persistent state of an entity from the database, - * overriding any local changes that have not yet been persisted. - * - * @param object $entity The entity to refresh. - * - * @return void - * - * @throws ORMInvalidArgumentException - * @throws ORMException - */ - public function refresh($entity) - { - if ( ! is_object($entity)) { - throw ORMInvalidArgumentException::invalidObject('EntityManager#refresh()', $entity); - } - - $this->errorIfClosed(); - - $this->unitOfWork->refresh($entity); - } - - /** - * Detaches an entity from the EntityManager, causing a managed entity to - * become detached. Unflushed changes made to the entity if any - * (including removal of the entity), will not be synchronized to the database. - * Entities which previously referenced the detached entity will continue to - * reference it. - * - * @param object $entity The entity to detach. - * - * @return void - * - * @throws ORMInvalidArgumentException - * - * @deprecated 2.7 This method is being removed from the ORM and won't have any replacement - */ - public function detach($entity) - { - @trigger_error('Method ' . __METHOD__ . '() is deprecated and will be removed in Doctrine ORM 3.0.', E_USER_DEPRECATED); - - if ( ! is_object($entity)) { - throw ORMInvalidArgumentException::invalidObject('EntityManager#detach()', $entity); - } - - $this->unitOfWork->detach($entity); - } - - /** - * Merges the state of a detached entity into the persistence context - * of this EntityManager and returns the managed copy of the entity. - * The entity passed to merge will not become associated/managed with this EntityManager. - * - * @param object $entity The detached entity to merge into the persistence context. - * - * @return object The managed copy of the entity. - * - * @throws ORMInvalidArgumentException - * @throws ORMException - * - * @deprecated 2.7 This method is being removed from the ORM and won't have any replacement - */ - public function merge($entity) - { - @trigger_error('Method ' . __METHOD__ . '() is deprecated and will be removed in Doctrine ORM 3.0.', E_USER_DEPRECATED); - - if ( ! is_object($entity)) { - throw ORMInvalidArgumentException::invalidObject('EntityManager#merge()', $entity); - } - - $this->errorIfClosed(); - - return $this->unitOfWork->merge($entity); - } - - /** - * {@inheritDoc} - */ - public function copy($entity, $deep = false) - { - @trigger_error('Method ' . __METHOD__ . '() is deprecated and will be removed in Doctrine ORM 3.0.', E_USER_DEPRECATED); - - throw new \BadMethodCallException("Not implemented."); - } - - /** - * {@inheritDoc} - */ - public function lock($entity, $lockMode, $lockVersion = null) - { - $this->unitOfWork->lock($entity, $lockMode, $lockVersion); - } - - /** - * Gets the repository for an entity class. - * - * @param string $entityName The name of the entity. - * - * @return \Doctrine\Common\Persistence\ObjectRepository|\Doctrine\ORM\EntityRepository The repository class. - */ - public function getRepository($entityName) - { - return $this->repositoryFactory->getRepository($this, $entityName); - } - - /** - * Determines whether an entity instance is managed in this EntityManager. - * - * @param object $entity - * - * @return boolean TRUE if this EntityManager currently manages the given entity, FALSE otherwise. - */ - public function contains($entity) - { - return $this->unitOfWork->isScheduledForInsert($entity) - || $this->unitOfWork->isInIdentityMap($entity) - && ! $this->unitOfWork->isScheduledForDelete($entity); - } - - /** - * {@inheritDoc} - */ - public function getEventManager() - { - return $this->eventManager; - } - - /** - * {@inheritDoc} - */ - public function getConfiguration() - { - return $this->config; - } - - /** - * Throws an exception if the EntityManager is closed or currently not active. - * - * @return void - * - * @throws ORMException If the EntityManager is closed. - */ - private function errorIfClosed() - { - if ($this->closed) { - throw ORMException::entityManagerClosed(); - } - } - - /** - * {@inheritDoc} - */ - public function isOpen() - { - return (!$this->closed); - } - - /** - * {@inheritDoc} - */ - public function getUnitOfWork() - { - return $this->unitOfWork; - } - - /** - * {@inheritDoc} - */ - public function getHydrator($hydrationMode) - { - return $this->newHydrator($hydrationMode); - } - - /** - * {@inheritDoc} - */ - public function newHydrator($hydrationMode) - { - switch ($hydrationMode) { - case Query::HYDRATE_OBJECT: - return new Internal\Hydration\ObjectHydrator($this); - - case Query::HYDRATE_ARRAY: - return new Internal\Hydration\ArrayHydrator($this); - - case Query::HYDRATE_SCALAR: - return new Internal\Hydration\ScalarHydrator($this); - - case Query::HYDRATE_SINGLE_SCALAR: - return new Internal\Hydration\SingleScalarHydrator($this); - - case Query::HYDRATE_SIMPLEOBJECT: - return new Internal\Hydration\SimpleObjectHydrator($this); - - default: - if (($class = $this->config->getCustomHydrationMode($hydrationMode)) !== null) { - return new $class($this); - } - } - - throw ORMException::invalidHydrationMode($hydrationMode); - } - - /** - * {@inheritDoc} - */ - public function getProxyFactory() - { - return $this->proxyFactory; - } - - /** - * {@inheritDoc} - */ - public function initializeObject($obj) - { - $this->unitOfWork->initializeObject($obj); - } - - /** - * Factory method to create EntityManager instances. - * - * @param array|Connection $connection An array with the connection parameters or an existing Connection instance. - * @param Configuration $config The Configuration instance to use. - * @param EventManager $eventManager The EventManager instance to use. - * - * @return EntityManager The created EntityManager. - * - * @throws \InvalidArgumentException - * @throws ORMException - */ - public static function create($connection, Configuration $config, EventManager $eventManager = null) - { - if ( ! $config->getMetadataDriverImpl()) { - throw ORMException::missingMappingDriverImpl(); - } - - $connection = static::createConnection($connection, $config, $eventManager); - - return new EntityManager($connection, $config, $connection->getEventManager()); - } - - /** - * Factory method to create Connection instances. - * - * @param array|Connection $connection An array with the connection parameters or an existing Connection instance. - * @param Configuration $config The Configuration instance to use. - * @param EventManager $eventManager The EventManager instance to use. - * - * @return Connection - * - * @throws \InvalidArgumentException - * @throws ORMException - */ - protected static function createConnection($connection, Configuration $config, EventManager $eventManager = null) - { - if (is_array($connection)) { - return DriverManager::getConnection($connection, $config, $eventManager ?: new EventManager()); - } - - if ( ! $connection instanceof Connection) { - throw new \InvalidArgumentException( - sprintf( - 'Invalid $connection argument of type %s given%s.', - is_object($connection) ? get_class($connection) : gettype($connection), - is_object($connection) ? '' : ': "' . $connection . '"' - ) - ); - } - - if ($eventManager !== null && $connection->getEventManager() !== $eventManager) { - throw ORMException::mismatchedEventManager(); - } - - return $connection; - } - - /** - * {@inheritDoc} - */ - public function getFilters() - { - if (null === $this->filterCollection) { - $this->filterCollection = new FilterCollection($this); - } - - return $this->filterCollection; - } - - /** - * {@inheritDoc} - */ - public function isFiltersStateClean() - { - return null === $this->filterCollection || $this->filterCollection->isClean(); - } - - /** - * {@inheritDoc} - */ - public function hasFilters() - { - return null !== $this->filterCollection; - } - - /** - * @param int $lockMode - * @param ClassMetadata $class - * @throws OptimisticLockException - * @throws TransactionRequiredException - */ - private function checkLockRequirements(int $lockMode, ClassMetadata $class): void - { - switch ($lockMode) { - case LockMode::OPTIMISTIC: - if (!$class->isVersioned) { - throw OptimisticLockException::notVersioned($class->name); - } - break; - case LockMode::PESSIMISTIC_READ: - case LockMode::PESSIMISTIC_WRITE: - if (!$this->getConnection()->isTransactionActive()) { - throw TransactionRequiredException::transactionRequired(); - } - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManagerInterface.php b/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManagerInterface.php deleted file mode 100644 index c96aa67..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManagerInterface.php +++ /dev/null @@ -1,298 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -use Doctrine\Common\Persistence\ObjectManager; -use Doctrine\ORM\Query\ResultSetMapping; - -/** - * EntityManager interface - * - * @since 2.4 - * @author Lars Strojny - * - * @method Mapping\ClassMetadata getClassMetadata($className) - */ -interface EntityManagerInterface extends ObjectManager -{ - /** - * Returns the cache API for managing the second level cache regions or NULL if the cache is not enabled. - * - * @return \Doctrine\ORM\Cache|null - */ - public function getCache(); - - /** - * Gets the database connection object used by the EntityManager. - * - * @return \Doctrine\DBAL\Connection - */ - public function getConnection(); - - /** - * Gets an ExpressionBuilder used for object-oriented construction of query expressions. - * - * Example: - * - * - * $qb = $em->createQueryBuilder(); - * $expr = $em->getExpressionBuilder(); - * $qb->select('u')->from('User', 'u') - * ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2))); - * - * - * @return \Doctrine\ORM\Query\Expr - */ - public function getExpressionBuilder(); - - /** - * Starts a transaction on the underlying database connection. - * - * @return void - */ - public function beginTransaction(); - - /** - * Executes a function in a transaction. - * - * The function gets passed this EntityManager instance as an (optional) parameter. - * - * {@link flush} is invoked prior to transaction commit. - * - * If an exception occurs during execution of the function or flushing or transaction commit, - * the transaction is rolled back, the EntityManager closed and the exception re-thrown. - * - * @param callable $func The function to execute transactionally. - * - * @return mixed The non-empty value returned from the closure or true instead. - */ - public function transactional($func); - - /** - * Commits a transaction on the underlying database connection. - * - * @return void - */ - public function commit(); - - /** - * Performs a rollback on the underlying database connection. - * - * @return void - */ - public function rollback(); - - /** - * Creates a new Query object. - * - * @param string $dql The DQL string. - * - * @return Query - */ - public function createQuery($dql = ''); - - /** - * Creates a Query from a named query. - * - * @param string $name - * - * @return Query - */ - public function createNamedQuery($name); - - /** - * Creates a native SQL query. - * - * @param string $sql - * @param ResultSetMapping $rsm The ResultSetMapping to use. - * - * @return NativeQuery - */ - public function createNativeQuery($sql, ResultSetMapping $rsm); - - /** - * Creates a NativeQuery from a named native query. - * - * @param string $name - * - * @return NativeQuery - */ - public function createNamedNativeQuery($name); - - /** - * Create a QueryBuilder instance - * - * @return QueryBuilder - */ - public function createQueryBuilder(); - - /** - * Gets a reference to the entity identified by the given type and identifier - * without actually loading it, if the entity is not yet loaded. - * - * @param string $entityName The name of the entity type. - * @param mixed $id The entity identifier. - * - * @return object|null The entity reference. - * - * @throws ORMException - */ - public function getReference($entityName, $id); - - /** - * Gets a partial reference to the entity identified by the given type and identifier - * without actually loading it, if the entity is not yet loaded. - * - * The returned reference may be a partial object if the entity is not yet loaded/managed. - * If it is a partial object it will not initialize the rest of the entity state on access. - * Thus you can only ever safely access the identifier of an entity obtained through - * this method. - * - * The use-cases for partial references involve maintaining bidirectional associations - * without loading one side of the association or to update an entity without loading it. - * Note, however, that in the latter case the original (persistent) entity data will - * never be visible to the application (especially not event listeners) as it will - * never be loaded in the first place. - * - * @param string $entityName The name of the entity type. - * @param mixed $identifier The entity identifier. - * - * @return object|null The (partial) entity reference. - */ - public function getPartialReference($entityName, $identifier); - - /** - * Closes the EntityManager. All entities that are currently managed - * by this EntityManager become detached. The EntityManager may no longer - * be used after it is closed. - * - * @return void - */ - public function close(); - - /** - * Creates a copy of the given entity. Can create a shallow or a deep copy. - * - * @deprecated 2.7 This method is being removed from the ORM and won't have any replacement - * - * @param object $entity The entity to copy. - * @param boolean $deep FALSE for a shallow copy, TRUE for a deep copy. - * - * @return object The new entity. - * - * @throws \BadMethodCallException - */ - public function copy($entity, $deep = false); - - /** - * Acquire a lock on the given entity. - * - * @param object $entity - * @param int $lockMode - * @param int|null $lockVersion - * - * @return void - * - * @throws OptimisticLockException - * @throws PessimisticLockException - */ - public function lock($entity, $lockMode, $lockVersion = null); - - /** - * Gets the EventManager used by the EntityManager. - * - * @return \Doctrine\Common\EventManager - */ - public function getEventManager(); - - /** - * Gets the Configuration used by the EntityManager. - * - * @return Configuration - */ - public function getConfiguration(); - - /** - * Check if the Entity manager is open or closed. - * - * @return bool - */ - public function isOpen(); - - /** - * Gets the UnitOfWork used by the EntityManager to coordinate operations. - * - * @return UnitOfWork - */ - public function getUnitOfWork(); - - /** - * Gets a hydrator for the given hydration mode. - * - * This method caches the hydrator instances which is used for all queries that don't - * selectively iterate over the result. - * - * @deprecated - * - * @param string|int $hydrationMode - * - * @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator - */ - public function getHydrator($hydrationMode); - - /** - * Create a new instance for the given hydration mode. - * - * @param string|int $hydrationMode - * - * @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator - * - * @throws ORMException - */ - public function newHydrator($hydrationMode); - - /** - * Gets the proxy factory used by the EntityManager to create entity proxies. - * - * @return \Doctrine\ORM\Proxy\ProxyFactory - */ - public function getProxyFactory(); - - /** - * Gets the enabled filters. - * - * @return \Doctrine\ORM\Query\FilterCollection The active filter collection. - */ - public function getFilters(); - - /** - * Checks whether the state of the filter collection is clean. - * - * @return boolean True, if the filter collection is clean. - */ - public function isFiltersStateClean(); - - /** - * Checks whether the Entity Manager has filters. - * - * @return boolean True, if the EM has a filter collection. - */ - public function hasFilters(); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/EntityNotFoundException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/EntityNotFoundException.php deleted file mode 100644 index 5b21e15..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/EntityNotFoundException.php +++ /dev/null @@ -1,51 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -/** - * Exception thrown when a Proxy fails to retrieve an Entity result. - * - * @author robo - * @since 2.0 - */ -class EntityNotFoundException extends ORMException -{ - /** - * Static constructor. - * - * @param string $className - * @param string[] $id - * - * @return self - */ - public static function fromClassNameAndIdentifier($className, array $id) - { - $ids = []; - - foreach ($id as $key => $value) { - $ids[] = $key . '(' . $value . ')'; - } - - - return new self( - 'Entity of type \'' . $className . '\'' . ($ids ? ' for IDs ' . implode(', ', $ids) : '') . ' was not found' - ); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php b/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php deleted file mode 100644 index 8a7c814..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php +++ /dev/null @@ -1,313 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -use Doctrine\Common\Inflector\Inflector; -use Doctrine\ORM\Query\ResultSetMappingBuilder; -use Doctrine\Common\Persistence\ObjectRepository; -use Doctrine\Common\Collections\Selectable; -use Doctrine\Common\Collections\Criteria; - -/** - * An EntityRepository serves as a repository for entities with generic as well as - * business specific methods for retrieving entities. - * - * This class is designed for inheritance and users can subclass this class to - * write their own repositories with business-specific methods to locate entities. - * - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class EntityRepository implements ObjectRepository, Selectable -{ - /** - * @var string - */ - protected $_entityName; - - /** - * @var EntityManager - */ - protected $_em; - - /** - * @var \Doctrine\ORM\Mapping\ClassMetadata - */ - protected $_class; - - /** - * Initializes a new EntityRepository. - */ - public function __construct(EntityManagerInterface $em, Mapping\ClassMetadata $class) - { - $this->_entityName = $class->name; - $this->_em = $em; - $this->_class = $class; - } - - /** - * Creates a new QueryBuilder instance that is prepopulated for this entity name. - * - * @param string $alias - * @param string $indexBy The index for the from. - * - * @return QueryBuilder - */ - public function createQueryBuilder($alias, $indexBy = null) - { - return $this->_em->createQueryBuilder() - ->select($alias) - ->from($this->_entityName, $alias, $indexBy); - } - - /** - * Creates a new result set mapping builder for this entity. - * - * The column naming strategy is "INCREMENT". - * - * @param string $alias - * - * @return ResultSetMappingBuilder - */ - public function createResultSetMappingBuilder($alias) - { - $rsm = new ResultSetMappingBuilder($this->_em, ResultSetMappingBuilder::COLUMN_RENAMING_INCREMENT); - $rsm->addRootEntityFromClassMetadata($this->_entityName, $alias); - - return $rsm; - } - - /** - * Creates a new Query instance based on a predefined metadata named query. - * - * @param string $queryName - * - * @return Query - */ - public function createNamedQuery($queryName) - { - return $this->_em->createQuery($this->_class->getNamedQuery($queryName)); - } - - /** - * Creates a native SQL query. - * - * @param string $queryName - * - * @return NativeQuery - */ - public function createNativeNamedQuery($queryName) - { - $queryMapping = $this->_class->getNamedNativeQuery($queryName); - $rsm = new Query\ResultSetMappingBuilder($this->_em); - $rsm->addNamedNativeQueryMapping($this->_class, $queryMapping); - - return $this->_em->createNativeQuery($queryMapping['query'], $rsm); - } - - /** - * Clears the repository, causing all managed entities to become detached. - * - * @return void - */ - public function clear() - { - $this->_em->clear($this->_class->rootEntityName); - } - - /** - * Finds an entity by its primary key / identifier. - * - * @param mixed $id The identifier. - * @param int|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants - * or NULL if no specific lock mode should be used - * during the search. - * @param int|null $lockVersion The lock version. - * - * @return object|null The entity instance or NULL if the entity can not be found. - */ - public function find($id, $lockMode = null, $lockVersion = null) - { - return $this->_em->find($this->_entityName, $id, $lockMode, $lockVersion); - } - - /** - * Finds all entities in the repository. - * - * @return array The entities. - */ - public function findAll() - { - return $this->findBy([]); - } - - /** - * Finds entities by a set of criteria. - * - * @param array $criteria - * @param array|null $orderBy - * @param int|null $limit - * @param int|null $offset - * - * @return array The objects. - */ - public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) - { - $persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName); - - return $persister->loadAll($criteria, $orderBy, $limit, $offset); - } - - /** - * Finds a single entity by a set of criteria. - * - * @param array $criteria - * @param array|null $orderBy - * - * @return object|null The entity instance or NULL if the entity can not be found. - */ - public function findOneBy(array $criteria, array $orderBy = null) - { - $persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName); - - return $persister->load($criteria, null, null, [], null, 1, $orderBy); - } - - /** - * Counts entities by a set of criteria. - * - * @todo Add this method to `ObjectRepository` interface in the next major release - * - * @param array $criteria - * - * @return int The cardinality of the objects that match the given criteria. - */ - public function count(array $criteria) - { - return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->count($criteria); - } - - /** - * Adds support for magic method calls. - * - * @param string $method - * @param array $arguments - * - * @return mixed The returned value from the resolved method. - * - * @throws ORMException - * @throws \BadMethodCallException If the method called is invalid - */ - public function __call($method, $arguments) - { - if (0 === strpos($method, 'findBy')) { - return $this->resolveMagicCall('findBy', substr($method, 6), $arguments); - } - - if (0 === strpos($method, 'findOneBy')) { - return $this->resolveMagicCall('findOneBy', substr($method, 9), $arguments); - } - - if (0 === strpos($method, 'countBy')) { - return $this->resolveMagicCall('count', substr($method, 7), $arguments); - } - - throw new \BadMethodCallException( - "Undefined method '$method'. The method name must start with ". - "either findBy, findOneBy or countBy!" - ); - } - - /** - * @return string - */ - protected function getEntityName() - { - return $this->_entityName; - } - - /** - * @return string - */ - public function getClassName() - { - return $this->getEntityName(); - } - - /** - * @return EntityManager - */ - protected function getEntityManager() - { - return $this->_em; - } - - /** - * @return Mapping\ClassMetadata - */ - protected function getClassMetadata() - { - return $this->_class; - } - - /** - * Select all elements from a selectable that match the expression and - * return a new collection containing these elements. - * - * @param \Doctrine\Common\Collections\Criteria $criteria - * - * @return \Doctrine\Common\Collections\Collection - */ - public function matching(Criteria $criteria) - { - $persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName); - - return new LazyCriteriaCollection($persister, $criteria); - } - - /** - * Resolves a magic method call to the proper existent method at `EntityRepository`. - * - * @param string $method The method to call - * @param string $by The property name used as condition - * @param array $arguments The arguments to pass at method call - * - * @throws ORMException If the method called is invalid or the requested field/association does not exist - * - * @return mixed - */ - private function resolveMagicCall($method, $by, array $arguments) - { - if (! $arguments) { - throw ORMException::findByRequiresParameter($method . $by); - } - - $fieldName = lcfirst(Inflector::classify($by)); - - if (! ($this->_class->hasField($fieldName) || $this->_class->hasAssociation($fieldName))) { - throw ORMException::invalidMagicCall($this->_entityName, $fieldName, $method . $by); - } - - return $this->$method([$fieldName => $arguments[0]], ...array_slice($arguments, 1)); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/LifecycleEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/LifecycleEventArgs.php deleted file mode 100644 index c7eb80b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/LifecycleEventArgs.php +++ /dev/null @@ -1,54 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Event; - -use Doctrine\Common\Persistence\Event\LifecycleEventArgs as BaseLifecycleEventArgs; - -/** - * Lifecycle Events are triggered by the UnitOfWork during lifecycle transitions - * of entities. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class LifecycleEventArgs extends BaseLifecycleEventArgs -{ - /** - * Retrieves associated Entity. - * - * @return object - */ - public function getEntity() - { - return $this->getObject(); - } - - /** - * Retrieves associated EntityManager. - * - * @return \Doctrine\ORM\EntityManager - */ - public function getEntityManager() - { - return $this->getObjectManager(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/ListenersInvoker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/ListenersInvoker.php deleted file mode 100644 index 7be8d48..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/ListenersInvoker.php +++ /dev/null @@ -1,120 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Event; - -use Doctrine\Common\EventArgs; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadata; - -/** - * A method invoker based on entity lifecycle. - * - * @author Fabio B. Silva - * @since 2.4 - */ -class ListenersInvoker -{ - const INVOKE_NONE = 0; - const INVOKE_LISTENERS = 1; - const INVOKE_CALLBACKS = 2; - const INVOKE_MANAGER = 4; - - /** - * @var \Doctrine\ORM\Mapping\EntityListenerResolver The Entity listener resolver. - */ - private $resolver; - - /** - * The EventManager used for dispatching events. - * - * @var \Doctrine\Common\EventManager - */ - private $eventManager; - - /** - * Initializes a new ListenersInvoker instance. - * - * @param EntityManagerInterface $em - */ - public function __construct(EntityManagerInterface $em) - { - $this->eventManager = $em->getEventManager(); - $this->resolver = $em->getConfiguration()->getEntityListenerResolver(); - } - - /** - * Get the subscribed event systems - * - * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. - * @param string $eventName The entity lifecycle event. - * - * @return integer Bitmask of subscribed event systems. - */ - public function getSubscribedSystems(ClassMetadata $metadata, $eventName) - { - $invoke = self::INVOKE_NONE; - - if (isset($metadata->lifecycleCallbacks[$eventName])) { - $invoke |= self::INVOKE_CALLBACKS; - } - - if (isset($metadata->entityListeners[$eventName])) { - $invoke |= self::INVOKE_LISTENERS; - } - - if ($this->eventManager->hasListeners($eventName)) { - $invoke |= self::INVOKE_MANAGER; - } - - return $invoke; - } - - /** - * Dispatches the lifecycle event of the given entity. - * - * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. - * @param string $eventName The entity lifecycle event. - * @param object $entity The Entity on which the event occurred. - * @param \Doctrine\Common\EventArgs $event The Event args. - * @param integer $invoke Bitmask to invoke listeners. - */ - public function invoke(ClassMetadata $metadata, $eventName, $entity, EventArgs $event, $invoke) - { - if ($invoke & self::INVOKE_CALLBACKS) { - foreach ($metadata->lifecycleCallbacks[$eventName] as $callback) { - $entity->$callback($event); - } - } - - if ($invoke & self::INVOKE_LISTENERS) { - foreach ($metadata->entityListeners[$eventName] as $listener) { - $class = $listener['class']; - $method = $listener['method']; - $instance = $this->resolver->resolve($class); - - $instance->$method($entity, $event); - } - } - - if ($invoke & self::INVOKE_MANAGER) { - $this->eventManager->dispatchEvent($eventName, $event); - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php deleted file mode 100644 index 5df698d..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/LoadClassMetadataEventArgs.php +++ /dev/null @@ -1,46 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Event; - -use Doctrine\Common\Persistence\Event\LoadClassMetadataEventArgs as BaseLoadClassMetadataEventArgs; - -/** - * Class that holds event arguments for a loadMetadata event. - * - * @author Jonathan H. Wage - * @since 2.0 - * - * Note: method annotations are used instead of method overrides (due to BC policy) - * - * @method __construct(\Doctrine\ORM\Mapping\ClassMetadata $classMetadata, \Doctrine\ORM\EntityManager $objectManager) - * @method \Doctrine\ORM\Mapping\ClassMetadata getClassMetadata() - */ -class LoadClassMetadataEventArgs extends BaseLoadClassMetadataEventArgs -{ - /** - * Retrieve associated EntityManager. - * - * @return \Doctrine\ORM\EntityManager - */ - public function getEntityManager() - { - return $this->getObjectManager(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClassMetadataNotFoundEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClassMetadataNotFoundEventArgs.php deleted file mode 100644 index a044a7e..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClassMetadataNotFoundEventArgs.php +++ /dev/null @@ -1,86 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Event; - -use Doctrine\Common\Persistence\Event\ManagerEventArgs; -use Doctrine\Common\Persistence\Mapping\ClassMetadata; -use Doctrine\Common\Persistence\ObjectManager; - -/** - * Class that holds event arguments for a `onClassMetadataNotFound` event. - * - * This object is mutable by design, allowing callbacks having access to it to set the - * found metadata in it, and therefore "cancelling" a `onClassMetadataNotFound` event - * - * @author Marco Pivetta - * @since 2.5 - */ -class OnClassMetadataNotFoundEventArgs extends ManagerEventArgs -{ - /** - * @var string - */ - private $className; - - /** - * @var ClassMetadata|null - */ - private $foundMetadata; - - /** - * Constructor. - * - * @param string $className - * @param ObjectManager $objectManager - */ - public function __construct($className, ObjectManager $objectManager) - { - $this->className = (string) $className; - - parent::__construct($objectManager); - } - - /** - * @param ClassMetadata|null $classMetadata - */ - public function setFoundMetadata(ClassMetadata $classMetadata = null) - { - $this->foundMetadata = $classMetadata; - } - - /** - * @return ClassMetadata|null - */ - public function getFoundMetadata() - { - return $this->foundMetadata; - } - - /** - * Retrieve class name for which a failed metadata fetch attempt was executed - * - * @return string - */ - public function getClassName() - { - return $this->className; - } -} - diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClearEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClearEventArgs.php deleted file mode 100644 index dd827c7..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnClearEventArgs.php +++ /dev/null @@ -1,86 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Event; - -use Doctrine\ORM\EntityManagerInterface; - -/** - * Provides event arguments for the onClear event. - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.org - * @since 2.0 - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class OnClearEventArgs extends \Doctrine\Common\EventArgs -{ - /** - * @var EntityManagerInterface - */ - private $em; - - /** - * @var string - */ - private $entityClass; - - /** - * Constructor. - * - * @param EntityManagerInterface $em - * @param string|null $entityClass Optional entity class. - */ - public function __construct(EntityManagerInterface $em, $entityClass = null) - { - $this->em = $em; - $this->entityClass = $entityClass; - } - - /** - * Retrieves associated EntityManager. - * - * @return \Doctrine\ORM\EntityManager - */ - public function getEntityManager() - { - return $this->em; - } - - /** - * Name of the entity class that is cleared, or empty if all are cleared. - * - * @return string|null - */ - public function getEntityClass() - { - return $this->entityClass; - } - - /** - * Checks if event clears all entities. - * - * @return bool - */ - public function clearsAllEntities() - { - return ($this->entityClass === null); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnFlushEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnFlushEventArgs.php deleted file mode 100644 index 6a9c7c7..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/OnFlushEventArgs.php +++ /dev/null @@ -1,61 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Event; - -use Doctrine\Common\EventArgs; -use Doctrine\ORM\EntityManagerInterface; - -/** - * Provides event arguments for the preFlush event. - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.org - * @since 2.0 - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class OnFlushEventArgs extends EventArgs -{ - /** - * @var EntityManagerInterface - */ - private $em; - - /** - * Constructor. - * - * @param EntityManagerInterface $em - */ - public function __construct(EntityManagerInterface $em) - { - $this->em = $em; - } - - /** - * Retrieve associated EntityManager. - * - * @return \Doctrine\ORM\EntityManager - */ - public function getEntityManager() - { - return $this->em; - } - -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PostFlushEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PostFlushEventArgs.php deleted file mode 100644 index 860f2d3..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PostFlushEventArgs.php +++ /dev/null @@ -1,58 +0,0 @@ -. - */ -namespace Doctrine\ORM\Event; - -use Doctrine\Common\EventArgs; -use Doctrine\ORM\EntityManagerInterface; - -/** - * Provides event arguments for the postFlush event. - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.org - * @since 2.0 - * @author Daniel Freudenberger - */ -class PostFlushEventArgs extends EventArgs -{ - /** - * @var \Doctrine\ORM\EntityManager - */ - private $em; - - /** - * Constructor. - * - * @param EntityManagerInterface $em - */ - public function __construct(EntityManagerInterface $em) - { - $this->em = $em; - } - - /** - * Retrieves associated EntityManager. - * - * @return \Doctrine\ORM\EntityManager - */ - public function getEntityManager() - { - return $this->em; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreFlushEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreFlushEventArgs.php deleted file mode 100644 index d01a926..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreFlushEventArgs.php +++ /dev/null @@ -1,58 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Event; - -use Doctrine\Common\EventArgs; -use Doctrine\ORM\EntityManagerInterface; - -/** - * Provides event arguments for the preFlush event. - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.com - * @since 2.0 - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class PreFlushEventArgs extends EventArgs -{ - /** - * @var \Doctrine\ORM\EntityManager - */ - private $em; - - /** - * Constructor. - * - * @param EntityManagerInterface $em - */ - public function __construct(EntityManagerInterface $em) - { - $this->em = $em; - } - - /** - * @return \Doctrine\ORM\EntityManager - */ - public function getEntityManager() - { - return $this->em; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php deleted file mode 100644 index d9a9f9d..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php +++ /dev/null @@ -1,137 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Event; - -use Doctrine\ORM\EntityManagerInterface; - -/** - * Class that holds event arguments for a preInsert/preUpdate event. - * - * @author Guilherme Blanco - * @author Roman Borschel - * @author Benjamin Eberlei - * @since 2.0 - */ -class PreUpdateEventArgs extends LifecycleEventArgs -{ - /** - * @var array - */ - private $entityChangeSet; - - /** - * Constructor. - * - * @param object $entity - * @param EntityManagerInterface $em - * @param array $changeSet - */ - public function __construct($entity, EntityManagerInterface $em, array &$changeSet) - { - parent::__construct($entity, $em); - - $this->entityChangeSet = &$changeSet; - } - - /** - * Retrieves entity changeset. - * - * @return array - */ - public function getEntityChangeSet() - { - return $this->entityChangeSet; - } - - /** - * Checks if field has a changeset. - * - * @param string $field - * - * @return boolean - */ - public function hasChangedField($field) - { - return isset($this->entityChangeSet[$field]); - } - - /** - * Gets the old value of the changeset of the changed field. - * - * @param string $field - * - * @return mixed - */ - public function getOldValue($field) - { - $this->assertValidField($field); - - return $this->entityChangeSet[$field][0]; - } - - /** - * Gets the new value of the changeset of the changed field. - * - * @param string $field - * - * @return mixed - */ - public function getNewValue($field) - { - $this->assertValidField($field); - - return $this->entityChangeSet[$field][1]; - } - - /** - * Sets the new value of this field. - * - * @param string $field - * @param mixed $value - * - * @return void - */ - public function setNewValue($field, $value) - { - $this->assertValidField($field); - - $this->entityChangeSet[$field][1] = $value; - } - - /** - * Asserts the field exists in changeset. - * - * @param string $field - * - * @return void - * - * @throws \InvalidArgumentException - */ - private function assertValidField($field) - { - if ( ! isset($this->entityChangeSet[$field])) { - throw new \InvalidArgumentException(sprintf( - 'Field "%s" is not a valid field of the entity "%s" in PreUpdateEventArgs.', - $field, - get_class($this->getEntity()) - )); - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Events.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Events.php deleted file mode 100644 index e16b47a..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Events.php +++ /dev/null @@ -1,167 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -/** - * Container for all ORM events. - * - * This class cannot be instantiated. - * - * @author Roman Borschel - * @since 2.0 - */ -final class Events -{ - /** - * Private constructor. This class is not meant to be instantiated. - */ - private function __construct() - { - } - - /** - * The preRemove event occurs for a given entity before the respective - * EntityManager remove operation for that entity is executed. - * - * This is an entity lifecycle event. - * - * @var string - */ - const preRemove = 'preRemove'; - - /** - * The postRemove event occurs for an entity after the entity has - * been deleted. It will be invoked after the database delete operations. - * - * This is an entity lifecycle event. - * - * @var string - */ - const postRemove = 'postRemove'; - - /** - * The prePersist event occurs for a given entity before the respective - * EntityManager persist operation for that entity is executed. - * - * This is an entity lifecycle event. - * - * @var string - */ - const prePersist = 'prePersist'; - - /** - * The postPersist event occurs for an entity after the entity has - * been made persistent. It will be invoked after the database insert operations. - * Generated primary key values are available in the postPersist event. - * - * This is an entity lifecycle event. - * - * @var string - */ - const postPersist = 'postPersist'; - - /** - * The preUpdate event occurs before the database update operations to - * entity data. - * - * This is an entity lifecycle event. - * - * @var string - */ - const preUpdate = 'preUpdate'; - - /** - * The postUpdate event occurs after the database update operations to - * entity data. - * - * This is an entity lifecycle event. - * - * @var string - */ - const postUpdate = 'postUpdate'; - - /** - * The postLoad event occurs for an entity after the entity has been loaded - * into the current EntityManager from the database or after the refresh operation - * has been applied to it. - * - * Note that the postLoad event occurs for an entity before any associations have been - * initialized. Therefore it is not safe to access associations in a postLoad callback - * or event handler. - * - * This is an entity lifecycle event. - * - * @var string - */ - const postLoad = 'postLoad'; - - /** - * The loadClassMetadata event occurs after the mapping metadata for a class - * has been loaded from a mapping source (annotations/xml/yaml). - * - * @var string - */ - const loadClassMetadata = 'loadClassMetadata'; - - /** - * The onClassMetadataNotFound event occurs whenever loading metadata for a class - * failed. - * - * @var string - */ - const onClassMetadataNotFound = 'onClassMetadataNotFound'; - - /** - * The preFlush event occurs when the EntityManager#flush() operation is invoked, - * but before any changes to managed entities have been calculated. This event is - * always raised right after EntityManager#flush() call. - */ - const preFlush = 'preFlush'; - - /** - * The onFlush event occurs when the EntityManager#flush() operation is invoked, - * after any changes to managed entities have been determined but before any - * actual database operations are executed. The event is only raised if there is - * actually something to do for the underlying UnitOfWork. If nothing needs to be done, - * the onFlush event is not raised. - * - * @var string - */ - const onFlush = 'onFlush'; - - /** - * The postFlush event occurs when the EntityManager#flush() operation is invoked and - * after all actual database operations are executed successfully. The event is only raised if there is - * actually something to do for the underlying UnitOfWork. If nothing needs to be done, - * the postFlush event is not raised. The event won't be raised if an error occurs during the - * flush operation. - * - * @var string - */ - const postFlush = 'postFlush'; - - /** - * The onClear event occurs when the EntityManager#clear() operation is invoked, - * after all references to entities have been removed from the unit of work. - * - * @var string - */ - const onClear = 'onClear'; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/AbstractIdGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/AbstractIdGenerator.php deleted file mode 100644 index 9e2e226..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/AbstractIdGenerator.php +++ /dev/null @@ -1,49 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Id; - -use Doctrine\ORM\EntityManager; - -abstract class AbstractIdGenerator -{ - /** - * Generates an identifier for an entity. - * - * @param EntityManager $em - * @param object|null $entity - * @return mixed - */ - abstract public function generate(EntityManager $em, $entity); - - /** - * Gets whether this generator is a post-insert generator which means that - * {@link generate()} must be called after the entity has been inserted - * into the database. - * - * By default, this method returns FALSE. Generators that have this requirement - * must override this method and return TRUE. - * - * @return boolean - */ - public function isPostInsertGenerator() - { - return false; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/AssignedGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/AssignedGenerator.php deleted file mode 100644 index 691eaee..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/AssignedGenerator.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Id; - -use Doctrine\ORM\EntityManager; -use Doctrine\ORM\ORMException; - -/** - * Special generator for application-assigned identifiers (doesn't really generate anything). - * - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class AssignedGenerator extends AbstractIdGenerator -{ - /** - * Returns the identifier assigned to the given entity. - * - * {@inheritDoc} - * - * @throws \Doctrine\ORM\ORMException - */ - public function generate(EntityManager $em, $entity) - { - $class = $em->getClassMetadata(get_class($entity)); - $idFields = $class->getIdentifierFieldNames(); - $identifier = []; - - foreach ($idFields as $idField) { - $value = $class->getFieldValue($entity, $idField); - - if ( ! isset($value)) { - throw ORMException::entityMissingAssignedIdForField($entity, $idField); - } - - if (isset($class->associationMappings[$idField])) { - // NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced. - $value = $em->getUnitOfWork()->getSingleIdentifierValue($value); - } - - $identifier[$idField] = $value; - } - - return $identifier; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/BigIntegerIdentityGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/BigIntegerIdentityGenerator.php deleted file mode 100644 index 01d139f..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/BigIntegerIdentityGenerator.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Id; - -use Doctrine\ORM\EntityManager; - -/** - * Id generator that obtains IDs from special "identity" columns. These are columns - * that automatically get a database-generated, auto-incremented identifier on INSERT. - * This generator obtains the last insert id after such an insert. - */ -class BigIntegerIdentityGenerator extends AbstractIdGenerator -{ - /** - * The name of the sequence to pass to lastInsertId(), if any. - * - * @var string - */ - private $sequenceName; - - /** - * Constructor. - * - * @param string|null $sequenceName The name of the sequence to pass to lastInsertId() - * to obtain the last generated identifier within the current - * database session/connection, if any. - */ - public function __construct($sequenceName = null) - { - $this->sequenceName = $sequenceName; - } - - /** - * {@inheritDoc} - */ - public function generate(EntityManager $em, $entity) - { - return (string) $em->getConnection()->lastInsertId($this->sequenceName); - } - - /** - * {@inheritDoc} - */ - public function isPostInsertGenerator() - { - return true; - } -} - diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/IdentityGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/IdentityGenerator.php deleted file mode 100644 index b9f68c6..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/IdentityGenerator.php +++ /dev/null @@ -1,65 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Id; - -use Doctrine\ORM\EntityManager; - -/** - * Id generator that obtains IDs from special "identity" columns. These are columns - * that automatically get a database-generated, auto-incremented identifier on INSERT. - * This generator obtains the last insert id after such an insert. - */ -class IdentityGenerator extends AbstractIdGenerator -{ - /** - * The name of the sequence to pass to lastInsertId(), if any. - * - * @var string - */ - private $sequenceName; - - /** - * Constructor. - * - * @param string|null $sequenceName The name of the sequence to pass to lastInsertId() - * to obtain the last generated identifier within the current - * database session/connection, if any. - */ - public function __construct($sequenceName = null) - { - $this->sequenceName = $sequenceName; - } - - /** - * {@inheritDoc} - */ - public function generate(EntityManager $em, $entity) - { - return (int) $em->getConnection()->lastInsertId($this->sequenceName); - } - - /** - * {@inheritdoc} - */ - public function isPostInsertGenerator() - { - return true; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/SequenceGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/SequenceGenerator.php deleted file mode 100644 index 9d8e9eb..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/SequenceGenerator.php +++ /dev/null @@ -1,132 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Id; - -use Doctrine\ORM\EntityManager; -use Serializable; - -/** - * Represents an ID generator that uses a database sequence. - * - * @since 2.0 - * @author Roman Borschel - */ -class SequenceGenerator extends AbstractIdGenerator implements Serializable -{ - /** - * The allocation size of the sequence. - * - * @var int - */ - private $_allocationSize; - - /** - * The name of the sequence. - * - * @var string - */ - private $_sequenceName; - - /** - * @var int - */ - private $_nextValue = 0; - - /** - * @var int|null - */ - private $_maxValue = null; - - /** - * Initializes a new sequence generator. - * - * @param string $sequenceName The name of the sequence. - * @param integer $allocationSize The allocation size of the sequence. - */ - public function __construct($sequenceName, $allocationSize) - { - $this->_sequenceName = $sequenceName; - $this->_allocationSize = $allocationSize; - } - - /** - * {@inheritDoc} - */ - public function generate(EntityManager $em, $entity) - { - if ($this->_maxValue === null || $this->_nextValue == $this->_maxValue) { - // Allocate new values - $conn = $em->getConnection(); - $sql = $conn->getDatabasePlatform()->getSequenceNextValSQL($this->_sequenceName); - - // Using `query` to force usage of the master server in MasterSlaveConnection - $this->_nextValue = (int) $conn->query($sql)->fetchColumn(); - $this->_maxValue = $this->_nextValue + $this->_allocationSize; - } - - return $this->_nextValue++; - } - - /** - * Gets the maximum value of the currently allocated bag of values. - * - * @return integer|null - */ - public function getCurrentMaxValue() - { - return $this->_maxValue; - } - - /** - * Gets the next value that will be returned by generate(). - * - * @return integer - */ - public function getNextValue() - { - return $this->_nextValue; - } - - /** - * @return string - */ - public function serialize() - { - return serialize( - [ - 'allocationSize' => $this->_allocationSize, - 'sequenceName' => $this->_sequenceName - ] - ); - } - - /** - * @param string $serialized - * - * @return void - */ - public function unserialize($serialized) - { - $array = unserialize($serialized); - - $this->_sequenceName = $array['sequenceName']; - $this->_allocationSize = $array['allocationSize']; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/TableGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/TableGenerator.php deleted file mode 100644 index 02385f5..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/TableGenerator.php +++ /dev/null @@ -1,109 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Id; - -use Doctrine\ORM\EntityManager; - -/** - * Id generator that uses a single-row database table and a hi/lo algorithm. - * - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class TableGenerator extends AbstractIdGenerator -{ - /** - * @var string - */ - private $_tableName; - - /** - * @var string - */ - private $_sequenceName; - - /** - * @var int - */ - private $_allocationSize; - - /** - * @var int|null - */ - private $_nextValue; - - /** - * @var int|null - */ - private $_maxValue; - - /** - * @param string $tableName - * @param string $sequenceName - * @param int $allocationSize - */ - public function __construct($tableName, $sequenceName = 'default', $allocationSize = 10) - { - $this->_tableName = $tableName; - $this->_sequenceName = $sequenceName; - $this->_allocationSize = $allocationSize; - } - - /** - * {@inheritDoc} - */ - public function generate( - EntityManager $em, $entity) - { - if ($this->_maxValue === null || $this->_nextValue == $this->_maxValue) { - // Allocate new values - $conn = $em->getConnection(); - - if ($conn->getTransactionNestingLevel() === 0) { - // use select for update - $sql = $conn->getDatabasePlatform()->getTableHiLoCurrentValSql($this->_tableName, $this->_sequenceName); - $currentLevel = $conn->fetchColumn($sql); - - if ($currentLevel != null) { - $this->_nextValue = $currentLevel; - $this->_maxValue = $this->_nextValue + $this->_allocationSize; - - $updateSql = $conn->getDatabasePlatform()->getTableHiLoUpdateNextValSql( - $this->_tableName, $this->_sequenceName, $this->_allocationSize - ); - - if ($conn->executeUpdate($updateSql, [1 => $currentLevel, 2 => $currentLevel+1]) !== 1) { - // no affected rows, concurrency issue, throw exception - } - } else { - // no current level returned, TableGenerator seems to be broken, throw exception - } - } else { - // only table locks help here, implement this or throw exception? - // or do we want to work with table locks exclusively? - } - } - - return $this->_nextValue++; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/UuidGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Id/UuidGenerator.php deleted file mode 100644 index 7cac5cc..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Id/UuidGenerator.php +++ /dev/null @@ -1,42 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Id; - -use Doctrine\ORM\EntityManager; - -/** - * Represents an ID generator that uses the database UUID expression - * - * @since 2.3 - * @author Maarten de Keizer - */ -class UuidGenerator extends AbstractIdGenerator -{ - /** - * {@inheritDoc} - */ - public function generate(EntityManager $em, $entity) - { - $conn = $em->getConnection(); - $sql = 'SELECT ' . $conn->getDatabasePlatform()->getGuidExpression(); - - return $conn->query($sql)->fetchColumn(0); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/CommitOrderCalculator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/CommitOrderCalculator.php deleted file mode 100644 index 30b9caa..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/CommitOrderCalculator.php +++ /dev/null @@ -1,195 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Internal; - -/** - * CommitOrderCalculator implements topological sorting, which is an ordering - * algorithm for directed graphs (DG) and/or directed acyclic graphs (DAG) by - * using a depth-first searching (DFS) to traverse the graph built in memory. - * This algorithm have a linear running time based on nodes (V) and dependency - * between the nodes (E), resulting in a computational complexity of O(V + E). - * - * @since 2.0 - * @author Guilherme Blanco - * @author Roman Borschel - */ -class CommitOrderCalculator -{ - const NOT_VISITED = 0; - const IN_PROGRESS = 1; - const VISITED = 2; - - /** - * Matrix of nodes (aka. vertex). - * Keys are provided hashes and values are the node definition objects. - * - * The node state definition contains the following properties: - * - * - state (integer) - * Whether the node is NOT_VISITED or IN_PROGRESS - * - * - value (object) - * Actual node value - * - * - dependencyList (array) - * Map of node dependencies defined as hashes. - * - * @var array<\stdClass> - */ - private $nodeList = []; - - /** - * Volatile variable holding calculated nodes during sorting process. - * - * @var array - */ - private $sortedNodeList = []; - - /** - * Checks for node (vertex) existence in graph. - * - * @param string $hash - * - * @return boolean - */ - public function hasNode($hash) - { - return isset($this->nodeList[$hash]); - } - - /** - * Adds a new node (vertex) to the graph, assigning its hash and value. - * - * @param string $hash - * @param object $node - * - * @return void - */ - public function addNode($hash, $node) - { - $vertex = new \stdClass(); - - $vertex->hash = $hash; - $vertex->state = self::NOT_VISITED; - $vertex->value = $node; - $vertex->dependencyList = []; - - $this->nodeList[$hash] = $vertex; - } - - /** - * Adds a new dependency (edge) to the graph using their hashes. - * - * @param string $fromHash - * @param string $toHash - * @param integer $weight - * - * @return void - */ - public function addDependency($fromHash, $toHash, $weight) - { - $vertex = $this->nodeList[$fromHash]; - $edge = new \stdClass(); - - $edge->from = $fromHash; - $edge->to = $toHash; - $edge->weight = $weight; - - $vertex->dependencyList[$toHash] = $edge; - } - - /** - * Return a valid order list of all current nodes. - * The desired topological sorting is the reverse post order of these searches. - * - * {@internal Highly performance-sensitive method.} - * - * @return array - */ - public function sort() - { - foreach ($this->nodeList as $vertex) { - if ($vertex->state !== self::NOT_VISITED) { - continue; - } - - $this->visit($vertex); - } - - $sortedList = $this->sortedNodeList; - - $this->nodeList = []; - $this->sortedNodeList = []; - - return array_reverse($sortedList); - } - - /** - * Visit a given node definition for reordering. - * - * {@internal Highly performance-sensitive method.} - * - * @param \stdClass $vertex - */ - private function visit($vertex) - { - $vertex->state = self::IN_PROGRESS; - - foreach ($vertex->dependencyList as $edge) { - $adjacentVertex = $this->nodeList[$edge->to]; - - switch ($adjacentVertex->state) { - case self::VISITED: - // Do nothing, since node was already visited - break; - - case self::IN_PROGRESS: - if (isset($adjacentVertex->dependencyList[$vertex->hash]) && - $adjacentVertex->dependencyList[$vertex->hash]->weight < $edge->weight) { - - // If we have some non-visited dependencies in the in-progress dependency, we - // need to visit them before adding the node. - foreach ($adjacentVertex->dependencyList as $adjacentEdge) { - $adjacentEdgeVertex = $this->nodeList[$adjacentEdge->to]; - - if ($adjacentEdgeVertex->state === self::NOT_VISITED) { - $this->visit($adjacentEdgeVertex); - } - } - - $adjacentVertex->state = self::VISITED; - - $this->sortedNodeList[] = $adjacentVertex->value; - } - break; - - case self::NOT_VISITED: - $this->visit($adjacentVertex); - } - } - - if ($vertex->state !== self::VISITED) { - $vertex->state = self::VISITED; - - $this->sortedNodeList[] = $vertex->value; - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php deleted file mode 100644 index 8a9c0f4..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php +++ /dev/null @@ -1,527 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Internal\Hydration; - -use Doctrine\DBAL\Types\Type; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Events; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Tools\Pagination\LimitSubqueryWalker; -use PDO; -use function array_map; -use function in_array; - -/** - * Base class for all hydrators. A hydrator is a class that provides some form - * of transformation of an SQL result set into another structure. - * - * @since 2.0 - * @author Konsta Vesterinen - * @author Roman Borschel - * @author Guilherme Blanco - */ -abstract class AbstractHydrator -{ - /** - * The ResultSetMapping. - * - * @var \Doctrine\ORM\Query\ResultSetMapping - */ - protected $_rsm; - - /** - * The EntityManager instance. - * - * @var EntityManagerInterface - */ - protected $_em; - - /** - * The dbms Platform instance. - * - * @var \Doctrine\DBAL\Platforms\AbstractPlatform - */ - protected $_platform; - - /** - * The UnitOfWork of the associated EntityManager. - * - * @var \Doctrine\ORM\UnitOfWork - */ - protected $_uow; - - /** - * Local ClassMetadata cache to avoid going to the EntityManager all the time. - * - * @var array - */ - protected $_metadataCache = []; - - /** - * The cache used during row-by-row hydration. - * - * @var array - */ - protected $_cache = []; - - /** - * The statement that provides the data to hydrate. - * - * @var \Doctrine\DBAL\Driver\Statement - */ - protected $_stmt; - - /** - * The query hints. - * - * @var array - */ - protected $_hints; - - /** - * Initializes a new instance of a class derived from AbstractHydrator. - * - * @param EntityManagerInterface $em The EntityManager to use. - */ - public function __construct(EntityManagerInterface $em) - { - $this->_em = $em; - $this->_platform = $em->getConnection()->getDatabasePlatform(); - $this->_uow = $em->getUnitOfWork(); - } - - /** - * Initiates a row-by-row hydration. - * - * @param object $stmt - * @param object $resultSetMapping - * @param array $hints - * - * @return IterableResult - */ - public function iterate($stmt, $resultSetMapping, array $hints = []) - { - $this->_stmt = $stmt; - $this->_rsm = $resultSetMapping; - $this->_hints = $hints; - - $evm = $this->_em->getEventManager(); - - $evm->addEventListener([Events::onClear], $this); - - $this->prepare(); - - return new IterableResult($this); - } - - /** - * Hydrates all rows returned by the passed statement instance at once. - * - * @param object $stmt - * @param object $resultSetMapping - * @param array $hints - * - * @return array - */ - public function hydrateAll($stmt, $resultSetMapping, array $hints = []) - { - $this->_stmt = $stmt; - $this->_rsm = $resultSetMapping; - $this->_hints = $hints; - - $this->_em->getEventManager()->addEventListener([Events::onClear], $this); - - $this->prepare(); - - $result = $this->hydrateAllData(); - - $this->cleanup(); - - return $result; - } - - /** - * Hydrates a single row returned by the current statement instance during - * row-by-row hydration with {@link iterate()}. - * - * @return mixed - */ - public function hydrateRow() - { - $row = $this->_stmt->fetch(PDO::FETCH_ASSOC); - - if ( ! $row) { - $this->cleanup(); - - return false; - } - - $result = []; - - $this->hydrateRowData($row, $result); - - return $result; - } - - /** - * When executed in a hydrate() loop we have to clear internal state to - * decrease memory consumption. - * - * @param mixed $eventArgs - * - * @return void - */ - public function onClear($eventArgs) - { - } - - /** - * Executes one-time preparation tasks, once each time hydration is started - * through {@link hydrateAll} or {@link iterate()}. - * - * @return void - */ - protected function prepare() - { - } - - /** - * Executes one-time cleanup tasks at the end of a hydration that was initiated - * through {@link hydrateAll} or {@link iterate()}. - * - * @return void - */ - protected function cleanup() - { - $this->_stmt->closeCursor(); - - $this->_stmt = null; - $this->_rsm = null; - $this->_cache = []; - $this->_metadataCache = []; - - $this - ->_em - ->getEventManager() - ->removeEventListener([Events::onClear], $this); - } - - /** - * Hydrates a single row from the current statement instance. - * - * Template method. - * - * @param array $data The row data. - * @param array $result The result to fill. - * - * @return void - * - * @throws HydrationException - */ - protected function hydrateRowData(array $data, array &$result) - { - throw new HydrationException("hydrateRowData() not implemented by this hydrator."); - } - - /** - * Hydrates all rows from the current statement instance at once. - * - * @return array - */ - abstract protected function hydrateAllData(); - - /** - * Processes a row of the result set. - * - * Used for identity-based hydration (HYDRATE_OBJECT and HYDRATE_ARRAY). - * Puts the elements of a result row into a new array, grouped by the dql alias - * they belong to. The column names in the result set are mapped to their - * field names during this procedure as well as any necessary conversions on - * the values applied. Scalar values are kept in a specific key 'scalars'. - * - * @param array $data SQL Result Row. - * @param array &$id Dql-Alias => ID-Hash. - * @param array &$nonemptyComponents Does this DQL-Alias has at least one non NULL value? - * - * @return array An array with all the fields (name => value) of the data row, - * grouped by their component alias. - */ - protected function gatherRowData(array $data, array &$id, array &$nonemptyComponents) - { - $rowData = ['data' => []]; - - foreach ($data as $key => $value) { - if (($cacheKeyInfo = $this->hydrateColumnInfo($key)) === null) { - continue; - } - - $fieldName = $cacheKeyInfo['fieldName']; - - switch (true) { - case (isset($cacheKeyInfo['isNewObjectParameter'])): - $argIndex = $cacheKeyInfo['argIndex']; - $objIndex = $cacheKeyInfo['objIndex']; - $type = $cacheKeyInfo['type']; - $value = $type->convertToPHPValue($value, $this->_platform); - - $rowData['newObjects'][$objIndex]['class'] = $cacheKeyInfo['class']; - $rowData['newObjects'][$objIndex]['args'][$argIndex] = $value; - break; - - case (isset($cacheKeyInfo['isScalar'])): - $type = $cacheKeyInfo['type']; - $value = $type->convertToPHPValue($value, $this->_platform); - - $rowData['scalars'][$fieldName] = $value; - break; - - //case (isset($cacheKeyInfo['isMetaColumn'])): - default: - $dqlAlias = $cacheKeyInfo['dqlAlias']; - $type = $cacheKeyInfo['type']; - - // If there are field name collisions in the child class, then we need - // to only hydrate if we are looking at the correct discriminator value - if (isset($cacheKeyInfo['discriminatorColumn'], $data[$cacheKeyInfo['discriminatorColumn']]) - && ! in_array((string) $data[$cacheKeyInfo['discriminatorColumn']], $cacheKeyInfo['discriminatorValues'], true) - ) { - break; - } - - // in an inheritance hierarchy the same field could be defined several times. - // We overwrite this value so long we don't have a non-null value, that value we keep. - // Per definition it cannot be that a field is defined several times and has several values. - if (isset($rowData['data'][$dqlAlias][$fieldName])) { - break; - } - - $rowData['data'][$dqlAlias][$fieldName] = $type - ? $type->convertToPHPValue($value, $this->_platform) - : $value; - - if ($cacheKeyInfo['isIdentifier'] && $value !== null) { - $id[$dqlAlias] .= '|' . $value; - $nonemptyComponents[$dqlAlias] = true; - } - break; - } - } - - return $rowData; - } - - /** - * Processes a row of the result set. - * - * Used for HYDRATE_SCALAR. This is a variant of _gatherRowData() that - * simply converts column names to field names and properly converts the - * values according to their types. The resulting row has the same number - * of elements as before. - * - * @param array $data - * - * @return array The processed row. - */ - protected function gatherScalarRowData(&$data) - { - $rowData = []; - - foreach ($data as $key => $value) { - if (($cacheKeyInfo = $this->hydrateColumnInfo($key)) === null) { - continue; - } - - $fieldName = $cacheKeyInfo['fieldName']; - - // WARNING: BC break! We know this is the desired behavior to type convert values, but this - // erroneous behavior exists since 2.0 and we're forced to keep compatibility. - if (! isset($cacheKeyInfo['isScalar'])) { - $type = $cacheKeyInfo['type']; - $value = $type ? $type->convertToPHPValue($value, $this->_platform) : $value; - - $fieldName = $cacheKeyInfo['dqlAlias'] . '_' . $fieldName; - } - - $rowData[$fieldName] = $value; - } - - return $rowData; - } - - /** - * Retrieve column information from ResultSetMapping. - * - * @param string $key Column name - * - * @return array|null - */ - protected function hydrateColumnInfo($key) - { - if (isset($this->_cache[$key])) { - return $this->_cache[$key]; - } - - switch (true) { - // NOTE: Most of the times it's a field mapping, so keep it first!!! - case (isset($this->_rsm->fieldMappings[$key])): - $classMetadata = $this->getClassMetadata($this->_rsm->declaringClasses[$key]); - $fieldName = $this->_rsm->fieldMappings[$key]; - $fieldMapping = $classMetadata->fieldMappings[$fieldName]; - $ownerMap = $this->_rsm->columnOwnerMap[$key]; - $columnInfo = [ - 'isIdentifier' => \in_array($fieldName, $classMetadata->identifier, true), - 'fieldName' => $fieldName, - 'type' => Type::getType($fieldMapping['type']), - 'dqlAlias' => $ownerMap, - ]; - - // the current discriminator value must be saved in order to disambiguate fields hydration, - // should there be field name collisions - if ($classMetadata->parentClasses && isset($this->_rsm->discriminatorColumns[$ownerMap])) { - return $this->_cache[$key] = \array_merge( - $columnInfo, - [ - 'discriminatorColumn' => $this->_rsm->discriminatorColumns[$ownerMap], - 'discriminatorValue' => $classMetadata->discriminatorValue, - 'discriminatorValues' => $this->getDiscriminatorValues($classMetadata), - ] - ); - } - - return $this->_cache[$key] = $columnInfo; - - case (isset($this->_rsm->newObjectMappings[$key])): - // WARNING: A NEW object is also a scalar, so it must be declared before! - $mapping = $this->_rsm->newObjectMappings[$key]; - - return $this->_cache[$key] = [ - 'isScalar' => true, - 'isNewObjectParameter' => true, - 'fieldName' => $this->_rsm->scalarMappings[$key], - 'type' => Type::getType($this->_rsm->typeMappings[$key]), - 'argIndex' => $mapping['argIndex'], - 'objIndex' => $mapping['objIndex'], - 'class' => new \ReflectionClass($mapping['className']), - ]; - - case isset($this->_rsm->scalarMappings[$key], $this->_hints[LimitSubqueryWalker::FORCE_DBAL_TYPE_CONVERSION]): - return $this->_cache[$key] = [ - 'fieldName' => $this->_rsm->scalarMappings[$key], - 'type' => Type::getType($this->_rsm->typeMappings[$key]), - 'dqlAlias' => '', - ]; - case (isset($this->_rsm->scalarMappings[$key])): - return $this->_cache[$key] = [ - 'isScalar' => true, - 'fieldName' => $this->_rsm->scalarMappings[$key], - 'type' => Type::getType($this->_rsm->typeMappings[$key]), - ]; - - case (isset($this->_rsm->metaMappings[$key])): - // Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns). - $fieldName = $this->_rsm->metaMappings[$key]; - $dqlAlias = $this->_rsm->columnOwnerMap[$key]; - $type = isset($this->_rsm->typeMappings[$key]) - ? Type::getType($this->_rsm->typeMappings[$key]) - : null; - - // Cache metadata fetch - $this->getClassMetadata($this->_rsm->aliasMap[$dqlAlias]); - - return $this->_cache[$key] = [ - 'isIdentifier' => isset($this->_rsm->isIdentifierColumn[$dqlAlias][$key]), - 'isMetaColumn' => true, - 'fieldName' => $fieldName, - 'type' => $type, - 'dqlAlias' => $dqlAlias, - ]; - } - - // this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2 - // maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping. - return null; - } - - /** - * @return string[] - */ - private function getDiscriminatorValues(ClassMetadata $classMetadata) : array - { - $values = array_map( - function (string $subClass) : string { - return (string) $this->getClassMetadata($subClass)->discriminatorValue; - }, - $classMetadata->subClasses - ); - - $values[] = (string) $classMetadata->discriminatorValue; - - return $values; - } - - /** - * Retrieve ClassMetadata associated to entity class name. - * - * @param string $className - * - * @return \Doctrine\ORM\Mapping\ClassMetadata - */ - protected function getClassMetadata($className) - { - if ( ! isset($this->_metadataCache[$className])) { - $this->_metadataCache[$className] = $this->_em->getClassMetadata($className); - } - - return $this->_metadataCache[$className]; - } - - /** - * Register entity as managed in UnitOfWork. - * - * @param ClassMetadata $class - * @param object $entity - * @param array $data - * - * @return void - * - * @todo The "$id" generation is the same of UnitOfWork#createEntity. Remove this duplication somehow - */ - protected function registerManaged(ClassMetadata $class, $entity, array $data) - { - if ($class->isIdentifierComposite) { - $id = []; - - foreach ($class->identifier as $fieldName) { - $id[$fieldName] = isset($class->associationMappings[$fieldName]) - ? $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']] - : $data[$fieldName]; - } - } else { - $fieldName = $class->identifier[0]; - $id = [ - $fieldName => isset($class->associationMappings[$fieldName]) - ? $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']] - : $data[$fieldName] - ]; - } - - $this->_em->getUnitOfWork()->registerManaged($entity, $id, $data); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php deleted file mode 100644 index c26b99b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php +++ /dev/null @@ -1,307 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Internal\Hydration; - -use PDO; -use Doctrine\ORM\Mapping\ClassMetadata; - -/** - * The ArrayHydrator produces a nested array "graph" that is often (not always) - * interchangeable with the corresponding object graph for read-only access. - * - * @since 2.0 - * @author Roman Borschel - * @author Guilherme Blanco - */ -class ArrayHydrator extends AbstractHydrator -{ - /** - * @var array - */ - private $_rootAliases = []; - - /** - * @var bool - */ - private $_isSimpleQuery = false; - - /** - * @var array - */ - private $_identifierMap = []; - - /** - * @var array - */ - private $_resultPointers = []; - - /** - * @var array - */ - private $_idTemplate = []; - - /** - * @var int - */ - private $_resultCounter = 0; - - /** - * {@inheritdoc} - */ - protected function prepare() - { - $this->_isSimpleQuery = count($this->_rsm->aliasMap) <= 1; - - foreach ($this->_rsm->aliasMap as $dqlAlias => $className) { - $this->_identifierMap[$dqlAlias] = []; - $this->_resultPointers[$dqlAlias] = []; - $this->_idTemplate[$dqlAlias] = ''; - } - } - - /** - * {@inheritdoc} - */ - protected function hydrateAllData() - { - $result = []; - - while ($data = $this->_stmt->fetch(PDO::FETCH_ASSOC)) { - $this->hydrateRowData($data, $result); - } - - return $result; - } - - /** - * {@inheritdoc} - */ - protected function hydrateRowData(array $row, array &$result) - { - // 1) Initialize - $id = $this->_idTemplate; // initialize the id-memory - $nonemptyComponents = []; - $rowData = $this->gatherRowData($row, $id, $nonemptyComponents); - - // 2) Now hydrate the data found in the current row. - foreach ($rowData['data'] as $dqlAlias => $data) { - $index = false; - - if (isset($this->_rsm->parentAliasMap[$dqlAlias])) { - // It's a joined result - - $parent = $this->_rsm->parentAliasMap[$dqlAlias]; - $path = $parent . '.' . $dqlAlias; - - // missing parent data, skipping as RIGHT JOIN hydration is not supported. - if ( ! isset($nonemptyComponents[$parent]) ) { - continue; - } - - // Get a reference to the right element in the result tree. - // This element will get the associated element attached. - if ($this->_rsm->isMixed && isset($this->_rootAliases[$parent])) { - $first = reset($this->_resultPointers); - // TODO: Exception if $key === null ? - $baseElement =& $this->_resultPointers[$parent][key($first)]; - } else if (isset($this->_resultPointers[$parent])) { - $baseElement =& $this->_resultPointers[$parent]; - } else { - unset($this->_resultPointers[$dqlAlias]); // Ticket #1228 - - continue; - } - - $relationAlias = $this->_rsm->relationMap[$dqlAlias]; - $parentClass = $this->_metadataCache[$this->_rsm->aliasMap[$parent]]; - $relation = $parentClass->associationMappings[$relationAlias]; - - // Check the type of the relation (many or single-valued) - if ( ! ($relation['type'] & ClassMetadata::TO_ONE)) { - $oneToOne = false; - - if ( ! isset($baseElement[$relationAlias])) { - $baseElement[$relationAlias] = []; - } - - if (isset($nonemptyComponents[$dqlAlias])) { - $indexExists = isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]); - $index = $indexExists ? $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false; - $indexIsValid = $index !== false ? isset($baseElement[$relationAlias][$index]) : false; - - if ( ! $indexExists || ! $indexIsValid) { - $element = $data; - - if (isset($this->_rsm->indexByMap[$dqlAlias])) { - $baseElement[$relationAlias][$row[$this->_rsm->indexByMap[$dqlAlias]]] = $element; - } else { - $baseElement[$relationAlias][] = $element; - } - - end($baseElement[$relationAlias]); - - $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = key($baseElement[$relationAlias]); - } - } - } else { - $oneToOne = true; - - if ( - ( ! isset($nonemptyComponents[$dqlAlias])) && - ( ! isset($baseElement[$relationAlias])) - ) { - $baseElement[$relationAlias] = null; - } else if ( ! isset($baseElement[$relationAlias])) { - $baseElement[$relationAlias] = $data; - } - } - - $coll =& $baseElement[$relationAlias]; - - if (is_array($coll)) { - $this->updateResultPointer($coll, $index, $dqlAlias, $oneToOne); - } - } else { - // It's a root result element - - $this->_rootAliases[$dqlAlias] = true; // Mark as root - $entityKey = $this->_rsm->entityMappings[$dqlAlias] ?: 0; - - // if this row has a NULL value for the root result id then make it a null result. - if ( ! isset($nonemptyComponents[$dqlAlias]) ) { - $result[] = $this->_rsm->isMixed - ? [$entityKey => null] - : null; - - $resultKey = $this->_resultCounter; - ++$this->_resultCounter; - - continue; - } - - // Check for an existing element - if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) { - $element = $this->_rsm->isMixed - ? [$entityKey => $data] - : $data; - - if (isset($this->_rsm->indexByMap[$dqlAlias])) { - $resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]]; - $result[$resultKey] = $element; - } else { - $resultKey = $this->_resultCounter; - $result[] = $element; - - ++$this->_resultCounter; - } - - $this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $resultKey; - } else { - $index = $this->_identifierMap[$dqlAlias][$id[$dqlAlias]]; - $resultKey = $index; - } - - $this->updateResultPointer($result, $index, $dqlAlias, false); - } - } - - if ( ! isset($resultKey)) { - $this->_resultCounter++; - } - - // Append scalar values to mixed result sets - if (isset($rowData['scalars'])) { - if ( ! isset($resultKey)) { - // this only ever happens when no object is fetched (scalar result only) - $resultKey = isset($this->_rsm->indexByMap['scalars']) - ? $row[$this->_rsm->indexByMap['scalars']] - : $this->_resultCounter - 1; - } - - foreach ($rowData['scalars'] as $name => $value) { - $result[$resultKey][$name] = $value; - } - } - - // Append new object to mixed result sets - if (isset($rowData['newObjects'])) { - if ( ! isset($resultKey)) { - $resultKey = $this->_resultCounter - 1; - } - - $scalarCount = (isset($rowData['scalars'])? count($rowData['scalars']): 0); - - foreach ($rowData['newObjects'] as $objIndex => $newObject) { - $class = $newObject['class']; - $args = $newObject['args']; - $obj = $class->newInstanceArgs($args); - - if (count($args) == $scalarCount || ($scalarCount == 0 && count($rowData['newObjects']) == 1)) { - $result[$resultKey] = $obj; - - continue; - } - - $result[$resultKey][$objIndex] = $obj; - } - } - } - - /** - * Updates the result pointer for an Entity. The result pointers point to the - * last seen instance of each Entity type. This is used for graph construction. - * - * @param array $coll The element. - * @param boolean|integer $index Index of the element in the collection. - * @param string $dqlAlias - * @param boolean $oneToOne Whether it is a single-valued association or not. - * - * @return void - */ - private function updateResultPointer(array &$coll, $index, $dqlAlias, $oneToOne) - { - if ($coll === null) { - unset($this->_resultPointers[$dqlAlias]); // Ticket #1228 - - return; - } - - if ($oneToOne) { - $this->_resultPointers[$dqlAlias] =& $coll; - - return; - } - - if ($index !== false) { - $this->_resultPointers[$dqlAlias] =& $coll[$index]; - - return; - } - - if ( ! $coll) { - return; - } - - end($coll); - $this->_resultPointers[$dqlAlias] =& $coll[key($coll)]; - - return; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/HydrationException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/HydrationException.php deleted file mode 100644 index 9caf03d..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/HydrationException.php +++ /dev/null @@ -1,105 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Internal\Hydration; - -class HydrationException extends \Doctrine\ORM\ORMException -{ - /** - * @return HydrationException - */ - public static function nonUniqueResult() - { - return new self("The result returned by the query was not unique."); - } - - /** - * @param string $alias - * @param string $parentAlias - * - * @return HydrationException - */ - public static function parentObjectOfRelationNotFound($alias, $parentAlias) - { - return new self("The parent object of entity result with alias '$alias' was not found." - . " The parent alias is '$parentAlias'."); - } - - /** - * @param string $dqlAlias - * - * @return HydrationException - */ - public static function emptyDiscriminatorValue($dqlAlias) - { - return new self("The DQL alias '" . $dqlAlias . "' contains an entity ". - "of an inheritance hierarchy with an empty discriminator value. This means " . - "that the database contains inconsistent data with an empty " . - "discriminator value in a table row." - ); - } - - /** - * @since 2.3 - * - * @param string $entityName - * @param string $discrColumnName - * @param string $dqlAlias - * - * @return HydrationException - */ - public static function missingDiscriminatorColumn($entityName, $discrColumnName, $dqlAlias) - { - return new self(sprintf( - 'The discriminator column "%s" is missing for "%s" using the DQL alias "%s".', - $discrColumnName, $entityName, $dqlAlias - )); - } - - /** - * @since 2.3 - * - * @param string $entityName - * @param string $discrColumnName - * @param string $dqlAlias - * - * @return HydrationException - */ - public static function missingDiscriminatorMetaMappingColumn($entityName, $discrColumnName, $dqlAlias) - { - return new self(sprintf( - 'The meta mapping for the discriminator column "%s" is missing for "%s" using the DQL alias "%s".', - $discrColumnName, $entityName, $dqlAlias - )); - } - - /** - * @param string $discrValue - * @param array $discrMap - * - * @return HydrationException - */ - public static function invalidDiscriminatorValue($discrValue, $discrMap) - { - return new self(sprintf( - 'The discriminator value "%s" is invalid. It must be one of "%s".', - $discrValue, implode('", "', $discrMap) - )); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/IterableResult.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/IterableResult.php deleted file mode 100644 index 1774ca0..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/IterableResult.php +++ /dev/null @@ -1,110 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Internal\Hydration; - -/** - * Represents a result structure that can be iterated over, hydrating row-by-row - * during the iteration. An IterableResult is obtained by AbstractHydrator#iterate(). - * - * @author robo - * @since 2.0 - */ -class IterableResult implements \Iterator -{ - /** - * @var \Doctrine\ORM\Internal\Hydration\AbstractHydrator - */ - private $_hydrator; - - /** - * @var boolean - */ - private $_rewinded = false; - - /** - * @var integer - */ - private $_key = -1; - - /** - * @var object|null - */ - private $_current = null; - - /** - * @param \Doctrine\ORM\Internal\Hydration\AbstractHydrator $hydrator - */ - public function __construct($hydrator) - { - $this->_hydrator = $hydrator; - } - - /** - * @return void - * - * @throws HydrationException - */ - public function rewind() - { - if ($this->_rewinded == true) { - throw new HydrationException("Can only iterate a Result once."); - } else { - $this->_current = $this->next(); - $this->_rewinded = true; - } - } - - /** - * Gets the next set of results. - * - * @return array|false - */ - public function next() - { - $this->_current = $this->_hydrator->hydrateRow(); - $this->_key++; - - return $this->_current; - } - - /** - * @return mixed - */ - public function current() - { - return $this->_current; - } - - /** - * @return int - */ - public function key() - { - return $this->_key; - } - - /** - * @return bool - */ - public function valid() - { - return ($this->_current!=false); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php deleted file mode 100644 index 5048216..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php +++ /dev/null @@ -1,593 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Internal\Hydration; - -use Doctrine\ORM\UnitOfWork; -use PDO; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\PersistentCollection; -use Doctrine\ORM\Query; -use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\ORM\Proxy\Proxy; - -/** - * The ObjectHydrator constructs an object graph out of an SQL result set. - * - * Internal note: Highly performance-sensitive code. - * - * @since 2.0 - * @author Roman Borschel - * @author Guilherme Blanco - * @author Fabio B. Silva - */ -class ObjectHydrator extends AbstractHydrator -{ - /** - * @var array - */ - private $identifierMap = []; - - /** - * @var array - */ - private $resultPointers = []; - - /** - * @var array - */ - private $idTemplate = []; - - /** - * @var integer - */ - private $resultCounter = 0; - - /** - * @var array - */ - private $rootAliases = []; - - /** - * @var array - */ - private $initializedCollections = []; - - /** - * @var array - */ - private $existingCollections = []; - - /** - * {@inheritdoc} - */ - protected function prepare() - { - if ( ! isset($this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD])) { - $this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD] = true; - } - - foreach ($this->_rsm->aliasMap as $dqlAlias => $className) { - $this->identifierMap[$dqlAlias] = []; - $this->idTemplate[$dqlAlias] = ''; - - // Remember which associations are "fetch joined", so that we know where to inject - // collection stubs or proxies and where not. - if ( ! isset($this->_rsm->relationMap[$dqlAlias])) { - continue; - } - - $parent = $this->_rsm->parentAliasMap[$dqlAlias]; - - if ( ! isset($this->_rsm->aliasMap[$parent])) { - throw HydrationException::parentObjectOfRelationNotFound($dqlAlias, $parent); - } - - $sourceClassName = $this->_rsm->aliasMap[$parent]; - $sourceClass = $this->getClassMetadata($sourceClassName); - $assoc = $sourceClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]]; - - $this->_hints['fetched'][$parent][$assoc['fieldName']] = true; - - if ($assoc['type'] === ClassMetadata::MANY_TO_MANY) { - continue; - } - - // Mark any non-collection opposite sides as fetched, too. - if ($assoc['mappedBy']) { - $this->_hints['fetched'][$dqlAlias][$assoc['mappedBy']] = true; - - continue; - } - - // handle fetch-joined owning side bi-directional one-to-one associations - if ($assoc['inversedBy']) { - $class = $this->getClassMetadata($className); - $inverseAssoc = $class->associationMappings[$assoc['inversedBy']]; - - if ( ! ($inverseAssoc['type'] & ClassMetadata::TO_ONE)) { - continue; - } - - $this->_hints['fetched'][$dqlAlias][$inverseAssoc['fieldName']] = true; - } - } - } - - /** - * {@inheritdoc} - */ - protected function cleanup() - { - $eagerLoad = (isset($this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD])) && $this->_hints[UnitOfWork::HINT_DEFEREAGERLOAD] == true; - - parent::cleanup(); - - $this->identifierMap = - $this->initializedCollections = - $this->existingCollections = - $this->resultPointers = []; - - if ($eagerLoad) { - $this->_uow->triggerEagerLoads(); - } - - $this->_uow->hydrationComplete(); - } - - /** - * {@inheritdoc} - */ - protected function hydrateAllData() - { - $result = []; - - while ($row = $this->_stmt->fetch(PDO::FETCH_ASSOC)) { - $this->hydrateRowData($row, $result); - } - - // Take snapshots from all newly initialized collections - foreach ($this->initializedCollections as $coll) { - $coll->takeSnapshot(); - } - - return $result; - } - - /** - * Initializes a related collection. - * - * @param object $entity The entity to which the collection belongs. - * @param ClassMetadata $class - * @param string $fieldName The name of the field on the entity that holds the collection. - * @param string $parentDqlAlias Alias of the parent fetch joining this collection. - * - * @return \Doctrine\ORM\PersistentCollection - */ - private function initRelatedCollection($entity, $class, $fieldName, $parentDqlAlias) - { - $oid = spl_object_hash($entity); - $relation = $class->associationMappings[$fieldName]; - $value = $class->reflFields[$fieldName]->getValue($entity); - - if ($value === null || is_array($value)) { - $value = new ArrayCollection((array) $value); - } - - if ( ! $value instanceof PersistentCollection) { - $value = new PersistentCollection( - $this->_em, $this->_metadataCache[$relation['targetEntity']], $value - ); - $value->setOwner($entity, $relation); - - $class->reflFields[$fieldName]->setValue($entity, $value); - $this->_uow->setOriginalEntityProperty($oid, $fieldName, $value); - - $this->initializedCollections[$oid . $fieldName] = $value; - } else if ( - isset($this->_hints[Query::HINT_REFRESH]) || - isset($this->_hints['fetched'][$parentDqlAlias][$fieldName]) && - ! $value->isInitialized() - ) { - // Is already PersistentCollection, but either REFRESH or FETCH-JOIN and UNINITIALIZED! - $value->setDirty(false); - $value->setInitialized(true); - $value->unwrap()->clear(); - - $this->initializedCollections[$oid . $fieldName] = $value; - } else { - // Is already PersistentCollection, and DON'T REFRESH or FETCH-JOIN! - $this->existingCollections[$oid . $fieldName] = $value; - } - - return $value; - } - - /** - * Gets an entity instance. - * - * @param array $data The instance data. - * @param string $dqlAlias The DQL alias of the entity's class. - * - * @return object The entity. - * - * @throws HydrationException - */ - private function getEntity(array $data, $dqlAlias) - { - $className = $this->_rsm->aliasMap[$dqlAlias]; - - if (isset($this->_rsm->discriminatorColumns[$dqlAlias])) { - $fieldName = $this->_rsm->discriminatorColumns[$dqlAlias]; - - if ( ! isset($this->_rsm->metaMappings[$fieldName])) { - throw HydrationException::missingDiscriminatorMetaMappingColumn($className, $fieldName, $dqlAlias); - } - - $discrColumn = $this->_rsm->metaMappings[$fieldName]; - - if ( ! isset($data[$discrColumn])) { - throw HydrationException::missingDiscriminatorColumn($className, $discrColumn, $dqlAlias); - } - - if ($data[$discrColumn] === "") { - throw HydrationException::emptyDiscriminatorValue($dqlAlias); - } - - $discrMap = $this->_metadataCache[$className]->discriminatorMap; - $discriminatorValue = (string) $data[$discrColumn]; - - if ( ! isset($discrMap[$discriminatorValue])) { - throw HydrationException::invalidDiscriminatorValue($discriminatorValue, array_keys($discrMap)); - } - - $className = $discrMap[$discriminatorValue]; - - unset($data[$discrColumn]); - } - - if (isset($this->_hints[Query::HINT_REFRESH_ENTITY]) && isset($this->rootAliases[$dqlAlias])) { - $this->registerManaged($this->_metadataCache[$className], $this->_hints[Query::HINT_REFRESH_ENTITY], $data); - } - - $this->_hints['fetchAlias'] = $dqlAlias; - - return $this->_uow->createEntity($className, $data, $this->_hints); - } - - /** - * @param string $className - * @param array $data - * - * @return mixed - */ - private function getEntityFromIdentityMap($className, array $data) - { - // TODO: Abstract this code and UnitOfWork::createEntity() equivalent? - $class = $this->_metadataCache[$className]; - - /* @var $class ClassMetadata */ - if ($class->isIdentifierComposite) { - $idHash = ''; - - foreach ($class->identifier as $fieldName) { - $idHash .= ' ' . (isset($class->associationMappings[$fieldName]) - ? $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']] - : $data[$fieldName]); - } - - return $this->_uow->tryGetByIdHash(ltrim($idHash), $class->rootEntityName); - } else if (isset($class->associationMappings[$class->identifier[0]])) { - return $this->_uow->tryGetByIdHash($data[$class->associationMappings[$class->identifier[0]]['joinColumns'][0]['name']], $class->rootEntityName); - } - - return $this->_uow->tryGetByIdHash($data[$class->identifier[0]], $class->rootEntityName); - } - - /** - * Hydrates a single row in an SQL result set. - * - * @internal - * First, the data of the row is split into chunks where each chunk contains data - * that belongs to a particular component/class. Afterwards, all these chunks - * are processed, one after the other. For each chunk of class data only one of the - * following code paths is executed: - * - * Path A: The data chunk belongs to a joined/associated object and the association - * is collection-valued. - * Path B: The data chunk belongs to a joined/associated object and the association - * is single-valued. - * Path C: The data chunk belongs to a root result element/object that appears in the topmost - * level of the hydrated result. A typical example are the objects of the type - * specified by the FROM clause in a DQL query. - * - * @param array $row The data of the row to process. - * @param array $result The result array to fill. - * - * @return void - */ - protected function hydrateRowData(array $row, array &$result) - { - // Initialize - $id = $this->idTemplate; // initialize the id-memory - $nonemptyComponents = []; - // Split the row data into chunks of class data. - $rowData = $this->gatherRowData($row, $id, $nonemptyComponents); - - // reset result pointers for each data row - $this->resultPointers = []; - - // Hydrate the data chunks - foreach ($rowData['data'] as $dqlAlias => $data) { - $entityName = $this->_rsm->aliasMap[$dqlAlias]; - - if (isset($this->_rsm->parentAliasMap[$dqlAlias])) { - // It's a joined result - - $parentAlias = $this->_rsm->parentAliasMap[$dqlAlias]; - // we need the $path to save into the identifier map which entities were already - // seen for this parent-child relationship - $path = $parentAlias . '.' . $dqlAlias; - - // We have a RIGHT JOIN result here. Doctrine cannot hydrate RIGHT JOIN Object-Graphs - if ( ! isset($nonemptyComponents[$parentAlias])) { - // TODO: Add special case code where we hydrate the right join objects into identity map at least - continue; - } - - $parentClass = $this->_metadataCache[$this->_rsm->aliasMap[$parentAlias]]; - $relationField = $this->_rsm->relationMap[$dqlAlias]; - $relation = $parentClass->associationMappings[$relationField]; - $reflField = $parentClass->reflFields[$relationField]; - - // Get a reference to the parent object to which the joined element belongs. - if ($this->_rsm->isMixed && isset($this->rootAliases[$parentAlias])) { - $objectClass = $this->resultPointers[$parentAlias]; - $parentObject = $objectClass[key($objectClass)]; - } else if (isset($this->resultPointers[$parentAlias])) { - $parentObject = $this->resultPointers[$parentAlias]; - } else { - // Parent object of relation not found, mark as not-fetched again - $element = $this->getEntity($data, $dqlAlias); - - // Update result pointer and provide initial fetch data for parent - $this->resultPointers[$dqlAlias] = $element; - $rowData['data'][$parentAlias][$relationField] = $element; - - // Mark as not-fetched again - unset($this->_hints['fetched'][$parentAlias][$relationField]); - continue; - } - - $oid = spl_object_hash($parentObject); - - // Check the type of the relation (many or single-valued) - if ( ! ($relation['type'] & ClassMetadata::TO_ONE)) { - // PATH A: Collection-valued association - $reflFieldValue = $reflField->getValue($parentObject); - - if (isset($nonemptyComponents[$dqlAlias])) { - $collKey = $oid . $relationField; - if (isset($this->initializedCollections[$collKey])) { - $reflFieldValue = $this->initializedCollections[$collKey]; - } else if ( ! isset($this->existingCollections[$collKey])) { - $reflFieldValue = $this->initRelatedCollection($parentObject, $parentClass, $relationField, $parentAlias); - } - - $indexExists = isset($this->identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]]); - $index = $indexExists ? $this->identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] : false; - $indexIsValid = $index !== false ? isset($reflFieldValue[$index]) : false; - - if ( ! $indexExists || ! $indexIsValid) { - if (isset($this->existingCollections[$collKey])) { - // Collection exists, only look for the element in the identity map. - if ($element = $this->getEntityFromIdentityMap($entityName, $data)) { - $this->resultPointers[$dqlAlias] = $element; - } else { - unset($this->resultPointers[$dqlAlias]); - } - } else { - $element = $this->getEntity($data, $dqlAlias); - - if (isset($this->_rsm->indexByMap[$dqlAlias])) { - $indexValue = $row[$this->_rsm->indexByMap[$dqlAlias]]; - $reflFieldValue->hydrateSet($indexValue, $element); - $this->identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] = $indexValue; - } else { - $reflFieldValue->hydrateAdd($element); - $reflFieldValue->last(); - $this->identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] = $reflFieldValue->key(); - } - // Update result pointer - $this->resultPointers[$dqlAlias] = $element; - } - } else { - // Update result pointer - $this->resultPointers[$dqlAlias] = $reflFieldValue[$index]; - } - } else if ( ! $reflFieldValue) { - $this->initRelatedCollection($parentObject, $parentClass, $relationField, $parentAlias); - } else if ($reflFieldValue instanceof PersistentCollection && $reflFieldValue->isInitialized() === false) { - $reflFieldValue->setInitialized(true); - } - - } else { - // PATH B: Single-valued association - $reflFieldValue = $reflField->getValue($parentObject); - - if ( ! $reflFieldValue || isset($this->_hints[Query::HINT_REFRESH]) || ($reflFieldValue instanceof Proxy && !$reflFieldValue->__isInitialized__)) { - // we only need to take action if this value is null, - // we refresh the entity or its an uninitialized proxy. - if (isset($nonemptyComponents[$dqlAlias])) { - $element = $this->getEntity($data, $dqlAlias); - $reflField->setValue($parentObject, $element); - $this->_uow->setOriginalEntityProperty($oid, $relationField, $element); - $targetClass = $this->_metadataCache[$relation['targetEntity']]; - - if ($relation['isOwningSide']) { - // TODO: Just check hints['fetched'] here? - // If there is an inverse mapping on the target class its bidirectional - if ($relation['inversedBy']) { - $inverseAssoc = $targetClass->associationMappings[$relation['inversedBy']]; - if ($inverseAssoc['type'] & ClassMetadata::TO_ONE) { - $targetClass->reflFields[$inverseAssoc['fieldName']]->setValue($element, $parentObject); - $this->_uow->setOriginalEntityProperty(spl_object_hash($element), $inverseAssoc['fieldName'], $parentObject); - } - } else if ($parentClass === $targetClass && $relation['mappedBy']) { - // Special case: bi-directional self-referencing one-one on the same class - $targetClass->reflFields[$relationField]->setValue($element, $parentObject); - } - } else { - // For sure bidirectional, as there is no inverse side in unidirectional mappings - $targetClass->reflFields[$relation['mappedBy']]->setValue($element, $parentObject); - $this->_uow->setOriginalEntityProperty(spl_object_hash($element), $relation['mappedBy'], $parentObject); - } - // Update result pointer - $this->resultPointers[$dqlAlias] = $element; - } else { - $this->_uow->setOriginalEntityProperty($oid, $relationField, null); - $reflField->setValue($parentObject, null); - } - // else leave $reflFieldValue null for single-valued associations - } else { - // Update result pointer - $this->resultPointers[$dqlAlias] = $reflFieldValue; - } - } - } else { - // PATH C: Its a root result element - $this->rootAliases[$dqlAlias] = true; // Mark as root alias - $entityKey = $this->_rsm->entityMappings[$dqlAlias] ?: 0; - - // if this row has a NULL value for the root result id then make it a null result. - if ( ! isset($nonemptyComponents[$dqlAlias]) ) { - if ($this->_rsm->isMixed) { - $result[] = [$entityKey => null]; - } else { - $result[] = null; - } - $resultKey = $this->resultCounter; - ++$this->resultCounter; - continue; - } - - // check for existing result from the iterations before - if ( ! isset($this->identifierMap[$dqlAlias][$id[$dqlAlias]])) { - $element = $this->getEntity($data, $dqlAlias); - - if ($this->_rsm->isMixed) { - $element = [$entityKey => $element]; - } - - if (isset($this->_rsm->indexByMap[$dqlAlias])) { - $resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]]; - - if (isset($this->_hints['collection'])) { - $this->_hints['collection']->hydrateSet($resultKey, $element); - } - - $result[$resultKey] = $element; - } else { - $resultKey = $this->resultCounter; - ++$this->resultCounter; - - if (isset($this->_hints['collection'])) { - $this->_hints['collection']->hydrateAdd($element); - } - - $result[] = $element; - } - - $this->identifierMap[$dqlAlias][$id[$dqlAlias]] = $resultKey; - - // Update result pointer - $this->resultPointers[$dqlAlias] = $element; - - } else { - // Update result pointer - $index = $this->identifierMap[$dqlAlias][$id[$dqlAlias]]; - $this->resultPointers[$dqlAlias] = $result[$index]; - $resultKey = $index; - } - } - - if (isset($this->_hints[Query::HINT_INTERNAL_ITERATION]) && $this->_hints[Query::HINT_INTERNAL_ITERATION]) { - $this->_uow->hydrationComplete(); - } - } - - if ( ! isset($resultKey) ) { - $this->resultCounter++; - } - - // Append scalar values to mixed result sets - if (isset($rowData['scalars'])) { - if ( ! isset($resultKey) ) { - $resultKey = (isset($this->_rsm->indexByMap['scalars'])) - ? $row[$this->_rsm->indexByMap['scalars']] - : $this->resultCounter - 1; - } - - foreach ($rowData['scalars'] as $name => $value) { - $result[$resultKey][$name] = $value; - } - } - - // Append new object to mixed result sets - if (isset($rowData['newObjects'])) { - if ( ! isset($resultKey) ) { - $resultKey = $this->resultCounter - 1; - } - - - $scalarCount = (isset($rowData['scalars'])? count($rowData['scalars']): 0); - - foreach ($rowData['newObjects'] as $objIndex => $newObject) { - $class = $newObject['class']; - $args = $newObject['args']; - $obj = $class->newInstanceArgs($args); - - if ($scalarCount == 0 && count($rowData['newObjects']) == 1 ) { - $result[$resultKey] = $obj; - - continue; - } - - $result[$resultKey][$objIndex] = $obj; - } - } - } - - /** - * When executed in a hydrate() loop we may have to clear internal state to - * decrease memory consumption. - * - * @param mixed $eventArgs - * - * @return void - */ - public function onClear($eventArgs) - { - parent::onClear($eventArgs); - - $aliases = array_keys($this->identifierMap); - - $this->identifierMap = array_fill_keys($aliases, []); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ScalarHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ScalarHydrator.php deleted file mode 100644 index 093e89c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ScalarHydrator.php +++ /dev/null @@ -1,54 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Internal\Hydration; - -/** - * Hydrator that produces flat, rectangular results of scalar data. - * The created result is almost the same as a regular SQL result set, except - * that column names are mapped to field names and data type conversions take place. - * - * @since 2.0 - * @author Roman Borschel - * @author Guilherme Blanco - */ -class ScalarHydrator extends AbstractHydrator -{ - /** - * {@inheritdoc} - */ - protected function hydrateAllData() - { - $result = []; - - while ($data = $this->_stmt->fetch(\PDO::FETCH_ASSOC)) { - $this->hydrateRowData($data, $result); - } - - return $result; - } - - /** - * {@inheritdoc} - */ - protected function hydrateRowData(array $data, array &$result) - { - $result[] = $this->gatherScalarRowData($data); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php deleted file mode 100644 index bf2beab..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php +++ /dev/null @@ -1,154 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Internal\Hydration; - -use PDO; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Query; - -class SimpleObjectHydrator extends AbstractHydrator -{ - /** - * @var ClassMetadata - */ - private $class; - - /** - * {@inheritdoc} - */ - protected function prepare() - { - if (count($this->_rsm->aliasMap) !== 1) { - throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping that contains more than one object result."); - } - - if ($this->_rsm->scalarMappings) { - throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping that contains scalar mappings."); - } - - $this->class = $this->getClassMetadata(reset($this->_rsm->aliasMap)); - } - - /** - * {@inheritdoc} - */ - protected function cleanup() - { - parent::cleanup(); - - $this->_uow->triggerEagerLoads(); - $this->_uow->hydrationComplete(); - } - - /** - * {@inheritdoc} - */ - protected function hydrateAllData() - { - $result = []; - - while ($row = $this->_stmt->fetch(PDO::FETCH_ASSOC)) { - $this->hydrateRowData($row, $result); - } - - $this->_em->getUnitOfWork()->triggerEagerLoads(); - - return $result; - } - - /** - * {@inheritdoc} - */ - protected function hydrateRowData(array $sqlResult, array &$result) - { - $entityName = $this->class->name; - $data = []; - - // We need to find the correct entity class name if we have inheritance in resultset - if ($this->class->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) { - $discrColumnName = $this->_platform->getSQLResultCasing($this->class->discriminatorColumn['name']); - - // Find mapped discriminator column from the result set. - if ($metaMappingDiscrColumnName = array_search($discrColumnName, $this->_rsm->metaMappings)) { - $discrColumnName = $metaMappingDiscrColumnName; - } - - if ( ! isset($sqlResult[$discrColumnName])) { - throw HydrationException::missingDiscriminatorColumn($entityName, $discrColumnName, key($this->_rsm->aliasMap)); - } - - if ($sqlResult[$discrColumnName] === '') { - throw HydrationException::emptyDiscriminatorValue(key($this->_rsm->aliasMap)); - } - - $discrMap = $this->class->discriminatorMap; - - if ( ! isset($discrMap[$sqlResult[$discrColumnName]])) { - throw HydrationException::invalidDiscriminatorValue($sqlResult[$discrColumnName], array_keys($discrMap)); - } - - $entityName = $discrMap[$sqlResult[$discrColumnName]]; - - unset($sqlResult[$discrColumnName]); - } - - foreach ($sqlResult as $column => $value) { - // An ObjectHydrator should be used instead of SimpleObjectHydrator - if (isset($this->_rsm->relationMap[$column])) { - throw new \Exception(sprintf('Unable to retrieve association information for column "%s"', $column)); - } - - $cacheKeyInfo = $this->hydrateColumnInfo($column); - - if ( ! $cacheKeyInfo) { - continue; - } - - // Check if value is null before conversion (because some types convert null to something else) - $valueIsNull = null === $value; - - // Convert field to a valid PHP value - if (isset($cacheKeyInfo['type'])) { - $type = $cacheKeyInfo['type']; - $value = $type->convertToPHPValue($value, $this->_platform); - } - - $fieldName = $cacheKeyInfo['fieldName']; - - // Prevent overwrite in case of inherit classes using same property name (See AbstractHydrator) - if ( ! isset($data[$fieldName]) || ! $valueIsNull) { - $data[$fieldName] = $value; - } - } - - if (isset($this->_hints[Query::HINT_REFRESH_ENTITY])) { - $this->registerManaged($this->class, $this->_hints[Query::HINT_REFRESH_ENTITY], $data); - } - - $uow = $this->_em->getUnitOfWork(); - $entity = $uow->createEntity($entityName, $data, $this->_hints); - - $result[] = $entity; - - if (isset($this->_hints[Query::HINT_INTERNAL_ITERATION]) && $this->_hints[Query::HINT_INTERNAL_ITERATION]) { - $this->_uow->hydrationComplete(); - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php deleted file mode 100644 index b9caeb1..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php +++ /dev/null @@ -1,58 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Internal\Hydration; - -use Doctrine\ORM\NoResultException; -use Doctrine\ORM\NonUniqueResultException; - -/** - * Hydrator that hydrates a single scalar value from the result set. - * - * @since 2.0 - * @author Roman Borschel - * @author Guilherme Blanco - */ -class SingleScalarHydrator extends AbstractHydrator -{ - /** - * {@inheritdoc} - */ - protected function hydrateAllData() - { - $data = $this->_stmt->fetchAll(\PDO::FETCH_ASSOC); - $numRows = count($data); - - if ($numRows === 0) { - throw new NoResultException(); - } - - if ($numRows > 1) { - throw new NonUniqueResultException('The query returned multiple rows. Change the query or use a different result function like getScalarResult().'); - } - - if (count($data[key($data)]) > 1) { - throw new NonUniqueResultException('The query returned a row containing multiple columns. Change the query or use a different result function like getScalarResult().'); - } - - $result = $this->gatherScalarRowData($data[key($data)]); - - return array_shift($result); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/HydrationCompleteHandler.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/HydrationCompleteHandler.php deleted file mode 100644 index 72a0c70..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/HydrationCompleteHandler.php +++ /dev/null @@ -1,103 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Internal; - -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Event\LifecycleEventArgs; -use Doctrine\ORM\Event\ListenersInvoker; -use Doctrine\ORM\Events; -use Doctrine\ORM\Mapping\ClassMetadata; - -/** - * Class, which can handle completion of hydration cycle and produce some of tasks. - * In current implementation triggers deferred postLoad event. - * - * @author Artur Eshenbrener - * @since 2.5 - */ -final class HydrationCompleteHandler -{ - /** - * @var ListenersInvoker - */ - private $listenersInvoker; - - /** - * @var EntityManagerInterface - */ - private $em; - - /** - * @var array[] - */ - private $deferredPostLoadInvocations = []; - - /** - * Constructor for this object - * - * @param ListenersInvoker $listenersInvoker - * @param EntityManagerInterface $em - */ - public function __construct(ListenersInvoker $listenersInvoker, EntityManagerInterface $em) - { - $this->listenersInvoker = $listenersInvoker; - $this->em = $em; - } - - /** - * Method schedules invoking of postLoad entity to the very end of current hydration cycle. - * - * @param ClassMetadata $class - * @param object $entity - */ - public function deferPostLoadInvoking(ClassMetadata $class, $entity) - { - $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postLoad); - - if ($invoke === ListenersInvoker::INVOKE_NONE) { - return; - } - - $this->deferredPostLoadInvocations[] = [$class, $invoke, $entity]; - } - - /** - * This method should me called after any hydration cycle completed. - * - * Method fires all deferred invocations of postLoad events - */ - public function hydrationComplete() - { - $toInvoke = $this->deferredPostLoadInvocations; - $this->deferredPostLoadInvocations = []; - - foreach ($toInvoke as $classAndEntity) { - list($class, $invoke, $entity) = $classAndEntity; - - $this->listenersInvoker->invoke( - $class, - Events::postLoad, - $entity, - new LifecycleEventArgs($entity, $this->em), - $invoke - ); - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/LazyCriteriaCollection.php b/vendor/doctrine/orm/lib/Doctrine/ORM/LazyCriteriaCollection.php deleted file mode 100644 index ad0238f..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/LazyCriteriaCollection.php +++ /dev/null @@ -1,133 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -use Doctrine\Common\Collections\AbstractLazyCollection; -use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Criteria; -use Doctrine\Common\Collections\Selectable; -use Doctrine\ORM\Persisters\Entity\BasicEntityPersister; -use Doctrine\ORM\Persisters\Entity\EntityPersister; - -/** - * A lazy collection that allow a fast count when using criteria object - * Once count gets executed once without collection being initialized, result - * is cached and returned on subsequent calls until collection gets loaded, - * then returning the number of loaded results. - * - * @since 2.5 - * @author Guilherme Blanco - * @author Michaël Gallego - */ -class LazyCriteriaCollection extends AbstractLazyCollection implements Selectable -{ - /** - * @var BasicEntityPersister - */ - protected $entityPersister; - - /** - * @var Criteria - */ - protected $criteria; - - /** - * @var integer|null - */ - private $count; - - /** - * @param EntityPersister $entityPersister - * @param Criteria $criteria - */ - public function __construct(EntityPersister $entityPersister, Criteria $criteria) - { - $this->entityPersister = $entityPersister; - $this->criteria = $criteria; - } - - /** - * Do an efficient count on the collection - * - * @return integer - */ - public function count() - { - if ($this->isInitialized()) { - return $this->collection->count(); - } - - // Return cached result in case count query was already executed - if ($this->count !== null) { - return $this->count; - } - - return $this->count = $this->entityPersister->count($this->criteria); - } - - /** - * check if collection is empty without loading it - * - * @return boolean TRUE if the collection is empty, FALSE otherwise. - */ - public function isEmpty() - { - if ($this->isInitialized()) { - return $this->collection->isEmpty(); - } - - return !$this->count(); - } - - /** - * Do an optimized search of an element - * - * @param object $element - * - * @return bool - */ - public function contains($element) - { - if ($this->isInitialized()) { - return $this->collection->contains($element); - } - - return $this->entityPersister->exists($element, $this->criteria); - } - - /** - * {@inheritDoc} - */ - public function matching(Criteria $criteria) - { - $this->initialize(); - - return $this->collection->matching($criteria); - } - - /** - * {@inheritDoc} - */ - protected function doInitialize() - { - $elements = $this->entityPersister->loadCriteria($this->criteria); - $this->collection = new ArrayCollection($elements); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Annotation.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Annotation.php deleted file mode 100644 index 19374ff..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Annotation.php +++ /dev/null @@ -1,24 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -interface Annotation -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AnsiQuoteStrategy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AnsiQuoteStrategy.php deleted file mode 100644 index d18c8be..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AnsiQuoteStrategy.php +++ /dev/null @@ -1,96 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -use Doctrine\DBAL\Platforms\AbstractPlatform; - -/** - * ANSI compliant quote strategy, this strategy does not apply any quote. - * To use this strategy all mapped tables and columns should be ANSI compliant. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class AnsiQuoteStrategy implements QuoteStrategy -{ - /** - * {@inheritdoc} - */ - public function getColumnName($fieldName, ClassMetadata $class, AbstractPlatform $platform) - { - return $class->fieldMappings[$fieldName]['columnName']; - } - - /** - * {@inheritdoc} - */ - public function getTableName(ClassMetadata $class, AbstractPlatform $platform) - { - return $class->table['name']; - } - - /** - * {@inheritdoc} - */ - public function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform) - { - return $definition['sequenceName']; - } - - /** - * {@inheritdoc} - */ - public function getJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform) - { - return $joinColumn['name']; - } - - /** - * {@inheritdoc} - */ - public function getReferencedJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform) - { - return $joinColumn['referencedColumnName']; - } - - /** - * {@inheritdoc} - */ - public function getJoinTableName(array $association, ClassMetadata $class, AbstractPlatform $platform) - { - return $association['joinTable']['name']; - } - - /** - * {@inheritdoc} - */ - public function getIdentifierColumnNames(ClassMetadata $class, AbstractPlatform $platform) - { - return $class->identifier; - } - - /** - * {@inheritdoc} - */ - public function getColumnAlias($columnName, $counter, AbstractPlatform $platform, ClassMetadata $class = null) - { - return $platform->getSQLResultCasing($columnName . '_' . $counter); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverride.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverride.php deleted file mode 100644 index e208b16..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverride.php +++ /dev/null @@ -1,69 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * This annotation is used to override association mapping of property for an entity relationship. - * - * @author Fabio B. Silva - * @since 2.3 - * - * @Annotation - * @Target("ANNOTATION") - */ -final class AssociationOverride implements Annotation -{ - /** - * The name of the relationship property whose mapping is being overridden. - * - * @var string - */ - public $name; - - /** - * The join column that is being mapped to the persistent attribute. - * - * @var array<\Doctrine\ORM\Mapping\JoinColumn> - */ - public $joinColumns; - - /** - * The join table that maps the relationship. - * - * @var \Doctrine\ORM\Mapping\JoinTable - */ - public $joinTable; - - /** - * The name of the association-field on the inverse-side. - * - * @var string - */ - public $inversedBy; - - /** - * The fetching strategy to use for the association. - * - * @var string - * - * @Enum({"LAZY", "EAGER", "EXTRA_LAZY"}) - */ - public $fetch; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverrides.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverrides.php deleted file mode 100644 index 217c9e4..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AssociationOverrides.php +++ /dev/null @@ -1,39 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * This annotation is used to override association mappings of relationship properties. - * - * @author Fabio B. Silva - * @since 2.3 - * - * @Annotation - * @Target("CLASS") - */ -final class AssociationOverrides implements Annotation -{ - /** - * Mapping overrides of relationship properties. - * - * @var array<\Doctrine\ORM\Mapping\AssociationOverride> - */ - public $value; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverride.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverride.php deleted file mode 100644 index f86d3a1..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverride.php +++ /dev/null @@ -1,46 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * This annotation is used to override the mapping of a entity property. - * - * @author Fabio B. Silva - * @since 2.3 - * - * @Annotation - * @Target("ANNOTATION") - */ -final class AttributeOverride implements Annotation -{ - /** - * The name of the property whose mapping is being overridden. - * - * @var string - */ - public $name; - - /** - * The column definition. - * - * @var \Doctrine\ORM\Mapping\Column - */ - public $column; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverrides.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverrides.php deleted file mode 100644 index 63b2cc6..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/AttributeOverrides.php +++ /dev/null @@ -1,39 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * This annotation is used to override the mapping of a entity property. - * - * @author Fabio B. Silva - * @since 2.3 - * - * @Annotation - * @Target("CLASS") - */ -final class AttributeOverrides implements Annotation -{ - /** - * One or more field or property mapping overrides. - * - * @var array<\Doctrine\ORM\Mapping\AttributeOverride> - */ - public $value; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php deleted file mode 100644 index 7f4fddc..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php +++ /dev/null @@ -1,244 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Builder; - -use Doctrine\ORM\Mapping\ClassMetadata; - -class AssociationBuilder -{ - /** - * @var ClassMetadataBuilder - */ - protected $builder; - - /** - * @var array - */ - protected $mapping; - - /** - * @var array|null - */ - protected $joinColumns; - - /** - * @var int - */ - protected $type; - - /** - * @param ClassMetadataBuilder $builder - * @param array $mapping - * @param int $type - */ - public function __construct(ClassMetadataBuilder $builder, array $mapping, $type) - { - $this->builder = $builder; - $this->mapping = $mapping; - $this->type = $type; - } - - /** - * @param string $fieldName - * - * @return AssociationBuilder - */ - public function mappedBy($fieldName) - { - $this->mapping['mappedBy'] = $fieldName; - - return $this; - } - - /** - * @param string $fieldName - * - * @return AssociationBuilder - */ - public function inversedBy($fieldName) - { - $this->mapping['inversedBy'] = $fieldName; - - return $this; - } - - /** - * @return AssociationBuilder - */ - public function cascadeAll() - { - $this->mapping['cascade'] = ["ALL"]; - - return $this; - } - - /** - * @return AssociationBuilder - */ - public function cascadePersist() - { - $this->mapping['cascade'][] = "persist"; - - return $this; - } - - /** - * @return AssociationBuilder - */ - public function cascadeRemove() - { - $this->mapping['cascade'][] = "remove"; - - return $this; - } - - /** - * @return AssociationBuilder - */ - public function cascadeMerge() - { - $this->mapping['cascade'][] = "merge"; - - return $this; - } - - /** - * @return AssociationBuilder - */ - public function cascadeDetach() - { - $this->mapping['cascade'][] = "detach"; - - return $this; - } - - /** - * @return AssociationBuilder - */ - public function cascadeRefresh() - { - $this->mapping['cascade'][] = "refresh"; - - return $this; - } - - /** - * @return AssociationBuilder - */ - public function fetchExtraLazy() - { - $this->mapping['fetch'] = ClassMetadata::FETCH_EXTRA_LAZY; - - return $this; - } - - /** - * @return AssociationBuilder - */ - public function fetchEager() - { - $this->mapping['fetch'] = ClassMetadata::FETCH_EAGER; - - return $this; - } - - /** - * @return AssociationBuilder - */ - public function fetchLazy() - { - $this->mapping['fetch'] = ClassMetadata::FETCH_LAZY; - - return $this; - } - - /** - * Add Join Columns. - * - * @param string $columnName - * @param string $referencedColumnName - * @param bool $nullable - * @param bool $unique - * @param string|null $onDelete - * @param string|null $columnDef - * - * @return AssociationBuilder - */ - public function addJoinColumn($columnName, $referencedColumnName, $nullable = true, $unique = false, $onDelete = null, $columnDef = null) - { - $this->joinColumns[] = [ - 'name' => $columnName, - 'referencedColumnName' => $referencedColumnName, - 'nullable' => $nullable, - 'unique' => $unique, - 'onDelete' => $onDelete, - 'columnDefinition' => $columnDef, - ]; - - return $this; - } - - /** - * Sets field as primary key. - * - * @return self - */ - public function makePrimaryKey() - { - $this->mapping['id'] = true; - - return $this; - } - - /** - * Removes orphan entities when detached from their parent. - * - * @return self - */ - public function orphanRemoval() - { - $this->mapping['orphanRemoval'] = true; - - return $this; - } - - /** - * @return ClassMetadataBuilder - * - * @throws \InvalidArgumentException - */ - public function build() - { - $mapping = $this->mapping; - if ($this->joinColumns) { - $mapping['joinColumns'] = $this->joinColumns; - } - $cm = $this->builder->getClassMetadata(); - if ($this->type == ClassMetadata::MANY_TO_ONE) { - $cm->mapManyToOne($mapping); - } else if ($this->type == ClassMetadata::ONE_TO_ONE) { - $cm->mapOneToOne($mapping); - } else { - throw new \InvalidArgumentException("Type should be a ToOne Association here"); - } - - return $this->builder; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php deleted file mode 100644 index c08b374..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php +++ /dev/null @@ -1,553 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Builder; - -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\ClassMetadataInfo; - -/** - * Builder Object for ClassMetadata - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.com - * @since 2.2 - * @author Benjamin Eberlei - * @author Guilherme Blanco - */ -class ClassMetadataBuilder -{ - /** - * @var \Doctrine\ORM\Mapping\ClassMetadataInfo - */ - private $cm; - - /** - * @param \Doctrine\ORM\Mapping\ClassMetadataInfo $cm - */ - public function __construct(ClassMetadataInfo $cm) - { - $this->cm = $cm; - } - - /** - * @return ClassMetadata - */ - public function getClassMetadata() - { - return $this->cm; - } - - /** - * Marks the class as mapped superclass. - * - * @return ClassMetadataBuilder - */ - public function setMappedSuperClass() - { - $this->cm->isMappedSuperclass = true; - $this->cm->isEmbeddedClass = false; - - return $this; - } - - /** - * Marks the class as embeddable. - * - * @return ClassMetadataBuilder - */ - public function setEmbeddable() - { - $this->cm->isEmbeddedClass = true; - $this->cm->isMappedSuperclass = false; - - return $this; - } - - /** - * Adds and embedded class - * - * @param string $fieldName - * @param string $class - * @param string|null $columnPrefix - * - * @return $this - */ - public function addEmbedded($fieldName, $class, $columnPrefix = null) - { - $this->cm->mapEmbedded( - [ - 'fieldName' => $fieldName, - 'class' => $class, - 'columnPrefix' => $columnPrefix - ] - ); - - return $this; - } - - /** - * Sets custom Repository class name. - * - * @param string $repositoryClassName - * - * @return ClassMetadataBuilder - */ - public function setCustomRepositoryClass($repositoryClassName) - { - $this->cm->setCustomRepositoryClass($repositoryClassName); - - return $this; - } - - /** - * Marks class read only. - * - * @return ClassMetadataBuilder - */ - public function setReadOnly() - { - $this->cm->markReadOnly(); - - return $this; - } - - /** - * Sets the table name. - * - * @param string $name - * - * @return ClassMetadataBuilder - */ - public function setTable($name) - { - $this->cm->setPrimaryTable(['name' => $name]); - - return $this; - } - - /** - * Adds Index. - * - * @param array $columns - * @param string $name - * - * @return ClassMetadataBuilder - */ - public function addIndex(array $columns, $name) - { - if (!isset($this->cm->table['indexes'])) { - $this->cm->table['indexes'] = []; - } - - $this->cm->table['indexes'][$name] = ['columns' => $columns]; - - return $this; - } - - /** - * Adds Unique Constraint. - * - * @param array $columns - * @param string $name - * - * @return ClassMetadataBuilder - */ - public function addUniqueConstraint(array $columns, $name) - { - if ( ! isset($this->cm->table['uniqueConstraints'])) { - $this->cm->table['uniqueConstraints'] = []; - } - - $this->cm->table['uniqueConstraints'][$name] = ['columns' => $columns]; - - return $this; - } - - /** - * Adds named query. - * - * @param string $name - * @param string $dqlQuery - * - * @return ClassMetadataBuilder - */ - public function addNamedQuery($name, $dqlQuery) - { - $this->cm->addNamedQuery( - [ - 'name' => $name, - 'query' => $dqlQuery, - ] - ); - - return $this; - } - - /** - * Sets class as root of a joined table inheritance hierarchy. - * - * @return ClassMetadataBuilder - */ - public function setJoinedTableInheritance() - { - $this->cm->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_JOINED); - - return $this; - } - - /** - * Sets class as root of a single table inheritance hierarchy. - * - * @return ClassMetadataBuilder - */ - public function setSingleTableInheritance() - { - $this->cm->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE); - - return $this; - } - - /** - * Sets the discriminator column details. - * - * @param string $name - * @param string $type - * @param int $length - * - * @return ClassMetadataBuilder - */ - public function setDiscriminatorColumn($name, $type = 'string', $length = 255) - { - $this->cm->setDiscriminatorColumn( - [ - 'name' => $name, - 'type' => $type, - 'length' => $length, - ] - ); - - return $this; - } - - /** - * Adds a subclass to this inheritance hierarchy. - * - * @param string $name - * @param string $class - * - * @return ClassMetadataBuilder - */ - public function addDiscriminatorMapClass($name, $class) - { - $this->cm->addDiscriminatorMapClass($name, $class); - - return $this; - } - - /** - * Sets deferred explicit change tracking policy. - * - * @return ClassMetadataBuilder - */ - public function setChangeTrackingPolicyDeferredExplicit() - { - $this->cm->setChangeTrackingPolicy(ClassMetadata::CHANGETRACKING_DEFERRED_EXPLICIT); - - return $this; - } - - /** - * Sets notify change tracking policy. - * - * @return ClassMetadataBuilder - */ - public function setChangeTrackingPolicyNotify() - { - $this->cm->setChangeTrackingPolicy(ClassMetadata::CHANGETRACKING_NOTIFY); - - return $this; - } - - /** - * Adds lifecycle event. - * - * @param string $methodName - * @param string $event - * - * @return ClassMetadataBuilder - */ - public function addLifecycleEvent($methodName, $event) - { - $this->cm->addLifecycleCallback($methodName, $event); - - return $this; - } - - /** - * Adds Field. - * - * @param string $name - * @param string $type - * @param array $mapping - * - * @return ClassMetadataBuilder - */ - public function addField($name, $type, array $mapping = []) - { - $mapping['fieldName'] = $name; - $mapping['type'] = $type; - - $this->cm->mapField($mapping); - - return $this; - } - - /** - * Creates a field builder. - * - * @param string $name - * @param string $type - * - * @return FieldBuilder - */ - public function createField($name, $type) - { - return new FieldBuilder( - $this, - [ - 'fieldName' => $name, - 'type' => $type - ] - ); - } - - /** - * Creates an embedded builder. - * - * @param string $fieldName - * @param string $class - * - * @return EmbeddedBuilder - */ - public function createEmbedded($fieldName, $class) - { - return new EmbeddedBuilder( - $this, - [ - 'fieldName' => $fieldName, - 'class' => $class, - 'columnPrefix' => null - ] - ); - } - - /** - * Adds a simple many to one association, optionally with the inversed by field. - * - * @param string $name - * @param string $targetEntity - * @param string|null $inversedBy - * - * @return ClassMetadataBuilder - */ - public function addManyToOne($name, $targetEntity, $inversedBy = null) - { - $builder = $this->createManyToOne($name, $targetEntity); - - if ($inversedBy) { - $builder->inversedBy($inversedBy); - } - - return $builder->build(); - } - - /** - * Creates a ManyToOne Association Builder. - * - * Note: This method does not add the association, you have to call build() on the AssociationBuilder. - * - * @param string $name - * @param string $targetEntity - * - * @return AssociationBuilder - */ - public function createManyToOne($name, $targetEntity) - { - return new AssociationBuilder( - $this, - [ - 'fieldName' => $name, - 'targetEntity' => $targetEntity - ], - ClassMetadata::MANY_TO_ONE - ); - } - - /** - * Creates a OneToOne Association Builder. - * - * @param string $name - * @param string $targetEntity - * - * @return AssociationBuilder - */ - public function createOneToOne($name, $targetEntity) - { - return new AssociationBuilder( - $this, - [ - 'fieldName' => $name, - 'targetEntity' => $targetEntity - ], - ClassMetadata::ONE_TO_ONE - ); - } - - /** - * Adds simple inverse one-to-one association. - * - * @param string $name - * @param string $targetEntity - * @param string $mappedBy - * - * @return ClassMetadataBuilder - */ - public function addInverseOneToOne($name, $targetEntity, $mappedBy) - { - $builder = $this->createOneToOne($name, $targetEntity); - $builder->mappedBy($mappedBy); - - return $builder->build(); - } - - /** - * Adds simple owning one-to-one association. - * - * @param string $name - * @param string $targetEntity - * @param string|null $inversedBy - * - * @return ClassMetadataBuilder - */ - public function addOwningOneToOne($name, $targetEntity, $inversedBy = null) - { - $builder = $this->createOneToOne($name, $targetEntity); - - if ($inversedBy) { - $builder->inversedBy($inversedBy); - } - - return $builder->build(); - } - - /** - * Creates a ManyToMany Association Builder. - * - * @param string $name - * @param string $targetEntity - * - * @return ManyToManyAssociationBuilder - */ - public function createManyToMany($name, $targetEntity) - { - return new ManyToManyAssociationBuilder( - $this, - [ - 'fieldName' => $name, - 'targetEntity' => $targetEntity - ], - ClassMetadata::MANY_TO_MANY - ); - } - - /** - * Adds a simple owning many to many association. - * - * @param string $name - * @param string $targetEntity - * @param string|null $inversedBy - * - * @return ClassMetadataBuilder - */ - public function addOwningManyToMany($name, $targetEntity, $inversedBy = null) - { - $builder = $this->createManyToMany($name, $targetEntity); - - if ($inversedBy) { - $builder->inversedBy($inversedBy); - } - - return $builder->build(); - } - - /** - * Adds a simple inverse many to many association. - * - * @param string $name - * @param string $targetEntity - * @param string $mappedBy - * - * @return ClassMetadataBuilder - */ - public function addInverseManyToMany($name, $targetEntity, $mappedBy) - { - $builder = $this->createManyToMany($name, $targetEntity); - $builder->mappedBy($mappedBy); - - return $builder->build(); - } - - /** - * Creates a one to many association builder. - * - * @param string $name - * @param string $targetEntity - * - * @return OneToManyAssociationBuilder - */ - public function createOneToMany($name, $targetEntity) - { - return new OneToManyAssociationBuilder( - $this, - [ - 'fieldName' => $name, - 'targetEntity' => $targetEntity - ], - ClassMetadata::ONE_TO_MANY - ); - } - - /** - * Adds simple OneToMany association. - * - * @param string $name - * @param string $targetEntity - * @param string $mappedBy - * - * @return ClassMetadataBuilder - */ - public function addOneToMany($name, $targetEntity, $mappedBy) - { - $builder = $this->createOneToMany($name, $targetEntity); - $builder->mappedBy($mappedBy); - - return $builder->build(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EmbeddedBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EmbeddedBuilder.php deleted file mode 100644 index de8383c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EmbeddedBuilder.php +++ /dev/null @@ -1,80 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Builder; - -/** - * Embedded Builder - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.com - * @since 2.5 - * @author Guido Contreras Woda - */ -class EmbeddedBuilder -{ - /** - * @var ClassMetadataBuilder - */ - private $builder; - - /** - * @var array - */ - private $mapping; - - /** - * @param ClassMetadataBuilder $builder - * @param array $mapping - */ - public function __construct(ClassMetadataBuilder $builder, array $mapping) - { - $this->builder = $builder; - $this->mapping = $mapping; - } - - /** - * Sets the column prefix for all of the embedded columns. - * - * @param string $columnPrefix - * @return $this - */ - public function setColumnPrefix($columnPrefix) - { - $this->mapping['columnPrefix'] = $columnPrefix; - - return $this; - } - - /** - * Finalizes this embeddable and attach it to the ClassMetadata. - * - * Without this call an EmbeddedBuilder has no effect on the ClassMetadata. - * - * @return ClassMetadataBuilder - */ - public function build() - { - $cm = $this->builder->getClassMetadata(); - - $cm->mapEmbedded($this->mapping); - - return $this->builder; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EntityListenerBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EntityListenerBuilder.php deleted file mode 100644 index e962726..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/EntityListenerBuilder.php +++ /dev/null @@ -1,72 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Builder; - -use Doctrine\ORM\Mapping\MappingException; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Events; - -/** - * Builder for entity listeners. - * - * @since 2.4 - * @author Fabio B. Silva - */ -class EntityListenerBuilder -{ - /** - * @var array Hash-map to handle event names. - */ - static private $events = [ - Events::preRemove => true, - Events::postRemove => true, - Events::prePersist => true, - Events::postPersist => true, - Events::preUpdate => true, - Events::postUpdate => true, - Events::postLoad => true, - Events::preFlush => true - ]; - - /** - * Lookup the entity class to find methods that match to event lifecycle names - * - * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata. - * @param string $className The listener class name. - * - * @throws \Doctrine\ORM\Mapping\MappingException When the listener class not found. - */ - static public function bindEntityListener(ClassMetadata $metadata, $className) - { - $class = $metadata->fullyQualifiedClassName($className); - - if ( ! class_exists($class)) { - throw MappingException::entityListenerClassNotFound($class, $className); - } - - foreach (get_class_methods($class) as $method) { - if ( ! isset(self::$events[$method])) { - continue; - } - - $metadata->addEntityListener($method, $class, $method); - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php deleted file mode 100644 index d0128d4..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php +++ /dev/null @@ -1,296 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Builder; - -/** - * Field Builder - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.com - * @since 2.2 - * @author Benjamin Eberlei - */ -class FieldBuilder -{ - /** - * @var ClassMetadataBuilder - */ - private $builder; - - /** - * @var array - */ - private $mapping; - - /** - * @var bool - */ - private $version; - - /** - * @var string - */ - private $generatedValue; - - /** - * @var array - */ - private $sequenceDef; - - /** - * @var string|null - */ - private $customIdGenerator; - - /** - * @param ClassMetadataBuilder $builder - * @param array $mapping - */ - public function __construct(ClassMetadataBuilder $builder, array $mapping) - { - $this->builder = $builder; - $this->mapping = $mapping; - } - - /** - * Sets length. - * - * @param int $length - * - * @return FieldBuilder - */ - public function length($length) - { - $this->mapping['length'] = $length; - - return $this; - } - - /** - * Sets nullable. - * - * @param bool $flag - * - * @return FieldBuilder - */ - public function nullable($flag = true) - { - $this->mapping['nullable'] = (bool) $flag; - - return $this; - } - - /** - * Sets Unique. - * - * @param bool $flag - * - * @return FieldBuilder - */ - public function unique($flag = true) - { - $this->mapping['unique'] = (bool) $flag; - - return $this; - } - - /** - * Sets column name. - * - * @param string $name - * - * @return FieldBuilder - */ - public function columnName($name) - { - $this->mapping['columnName'] = $name; - - return $this; - } - - /** - * Sets Precision. - * - * @param int $p - * - * @return FieldBuilder - */ - public function precision($p) - { - $this->mapping['precision'] = $p; - - return $this; - } - - /** - * Sets scale. - * - * @param int $s - * - * @return FieldBuilder - */ - public function scale($s) - { - $this->mapping['scale'] = $s; - - return $this; - } - - /** - * Sets field as primary key. - * - * @deprecated Use makePrimaryKey() instead - * @return FieldBuilder - */ - public function isPrimaryKey() - { - return $this->makePrimaryKey(); - } - - /** - * Sets field as primary key. - * - * @return FieldBuilder - */ - public function makePrimaryKey() - { - $this->mapping['id'] = true; - - return $this; - } - - /** - * Sets an option. - * - * @param string $name - * @param mixed $value - * - * @return FieldBuilder - */ - public function option($name, $value) - { - $this->mapping['options'][$name] = $value; - - return $this; - } - - /** - * @param string $strategy - * - * @return FieldBuilder - */ - public function generatedValue($strategy = 'AUTO') - { - $this->generatedValue = $strategy; - - return $this; - } - - /** - * Sets field versioned. - * - * @return FieldBuilder - */ - public function isVersionField() - { - $this->version = true; - - return $this; - } - - /** - * Sets Sequence Generator. - * - * @param string $sequenceName - * @param int $allocationSize - * @param int $initialValue - * - * @return FieldBuilder - */ - public function setSequenceGenerator($sequenceName, $allocationSize = 1, $initialValue = 1) - { - $this->sequenceDef = [ - 'sequenceName' => $sequenceName, - 'allocationSize' => $allocationSize, - 'initialValue' => $initialValue, - ]; - - return $this; - } - - /** - * Sets column definition. - * - * @param string $def - * - * @return FieldBuilder - */ - public function columnDefinition($def) - { - $this->mapping['columnDefinition'] = $def; - - return $this; - } - - /** - * Set the FQCN of the custom ID generator. - * This class must extend \Doctrine\ORM\Id\AbstractIdGenerator. - * - * @param string $customIdGenerator - * - * @return $this - */ - public function setCustomIdGenerator($customIdGenerator) - { - $this->customIdGenerator = (string) $customIdGenerator; - - return $this; - } - - /** - * Finalizes this field and attach it to the ClassMetadata. - * - * Without this call a FieldBuilder has no effect on the ClassMetadata. - * - * @return ClassMetadataBuilder - */ - public function build() - { - $cm = $this->builder->getClassMetadata(); - if ($this->generatedValue) { - $cm->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $this->generatedValue)); - } - - if ($this->version) { - $cm->setVersionMapping($this->mapping); - } - - $cm->mapField($this->mapping); - if ($this->sequenceDef) { - $cm->setSequenceGeneratorDefinition($this->sequenceDef); - } - - if ($this->customIdGenerator) { - $cm->setCustomGeneratorDefinition(['class' => $this->customIdGenerator]); - } - - return $this->builder; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ManyToManyAssociationBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ManyToManyAssociationBuilder.php deleted file mode 100644 index a71859d..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/ManyToManyAssociationBuilder.php +++ /dev/null @@ -1,101 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Builder; - -/** - * ManyToMany Association Builder - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.com - * @since 2.0 - * @author Benjamin Eberlei - */ -class ManyToManyAssociationBuilder extends OneToManyAssociationBuilder -{ - /** - * @var string|null - */ - private $joinTableName; - - /** - * @var array - */ - private $inverseJoinColumns = []; - - /** - * @param string $name - * - * @return ManyToManyAssociationBuilder - */ - public function setJoinTable($name) - { - $this->joinTableName = $name; - - return $this; - } - - /** - * Adds Inverse Join Columns. - * - * @param string $columnName - * @param string $referencedColumnName - * @param bool $nullable - * @param bool $unique - * @param string|null $onDelete - * @param string|null $columnDef - * - * @return ManyToManyAssociationBuilder - */ - public function addInverseJoinColumn($columnName, $referencedColumnName, $nullable = true, $unique = false, $onDelete = null, $columnDef = null) - { - $this->inverseJoinColumns[] = [ - 'name' => $columnName, - 'referencedColumnName' => $referencedColumnName, - 'nullable' => $nullable, - 'unique' => $unique, - 'onDelete' => $onDelete, - 'columnDefinition' => $columnDef, - ]; - - return $this; - } - - /** - * @return ClassMetadataBuilder - */ - public function build() - { - $mapping = $this->mapping; - $mapping['joinTable'] = []; - if ($this->joinColumns) { - $mapping['joinTable']['joinColumns'] = $this->joinColumns; - } - if ($this->inverseJoinColumns) { - $mapping['joinTable']['inverseJoinColumns'] = $this->inverseJoinColumns; - } - if ($this->joinTableName) { - $mapping['joinTable']['name'] = $this->joinTableName; - } - $cm = $this->builder->getClassMetadata(); - $cm->mapManyToMany($mapping); - - return $this->builder; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/OneToManyAssociationBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/OneToManyAssociationBuilder.php deleted file mode 100644 index 347dfd0..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Builder/OneToManyAssociationBuilder.php +++ /dev/null @@ -1,70 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Builder; - -/** - * OneToMany Association Builder - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.com - * @since 2.0 - * @author Benjamin Eberlei - */ -class OneToManyAssociationBuilder extends AssociationBuilder -{ - /** - * @param array $fieldNames - * - * @return OneToManyAssociationBuilder - */ - public function setOrderBy(array $fieldNames) - { - $this->mapping['orderBy'] = $fieldNames; - - return $this; - } - - /** - * @param string $fieldName - * - * @return OneToManyAssociationBuilder - */ - public function setIndexBy($fieldName) - { - $this->mapping['indexBy'] = $fieldName; - - return $this; - } - - /** - * @return ClassMetadataBuilder - */ - public function build() - { - $mapping = $this->mapping; - if ($this->joinColumns) { - $mapping['joinColumns'] = $this->joinColumns; - } - $cm = $this->builder->getClassMetadata(); - $cm->mapOneToMany($mapping); - - return $this->builder; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Cache.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Cache.php deleted file mode 100644 index 3226b60..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Cache.php +++ /dev/null @@ -1,44 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * Caching to an entity or a collection. - * - * @author Fabio B. Silva - * @since 2.5 - * - * @Annotation - * @Target({"CLASS","PROPERTY"}) - */ -final class Cache implements Annotation -{ - /** - * @Enum({"READ_ONLY", "NONSTRICT_READ_WRITE", "READ_WRITE"}) - * - * @var string The concurrency strategy. - */ - public $usage = 'READ_ONLY'; - - /** - * @var string Cache region name. - */ - public $region; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ChangeTrackingPolicy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ChangeTrackingPolicy.php deleted file mode 100644 index 3657b76..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ChangeTrackingPolicy.php +++ /dev/null @@ -1,36 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("CLASS") - */ -final class ChangeTrackingPolicy implements Annotation -{ - /** - * The change tracking policy. - * - * @var string - * - * @Enum({"DEFERRED_IMPLICIT", "DEFERRED_EXPLICIT", "NOTIFY"}) - */ - public $value; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadata.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadata.php deleted file mode 100644 index a57f1e1..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadata.php +++ /dev/null @@ -1,29 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * {@inheritDoc} - * - * @todo remove or rename ClassMetadataInfo to ClassMetadata - */ -class ClassMetadata extends ClassMetadataInfo -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php deleted file mode 100644 index 8410ce5..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php +++ /dev/null @@ -1,797 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -use Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory; -use Doctrine\Common\Persistence\Mapping\ClassMetadata as ClassMetadataInterface; -use Doctrine\Common\Persistence\Mapping\ReflectionService; -use Doctrine\DBAL\Platforms; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Event\LoadClassMetadataEventArgs; -use Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs; -use Doctrine\ORM\Events; -use Doctrine\ORM\Id\BigIntegerIdentityGenerator; -use Doctrine\ORM\Id\IdentityGenerator; -use Doctrine\ORM\ORMException; -use ReflectionException; - -/** - * The ClassMetadataFactory is used to create ClassMetadata objects that contain all the - * metadata mapping information of a class which describes how a class should be mapped - * to a relational database. - * - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ClassMetadataFactory extends AbstractClassMetadataFactory -{ - /** - * @var EntityManagerInterface|null - */ - private $em; - - /** - * @var \Doctrine\DBAL\Platforms\AbstractPlatform - */ - private $targetPlatform; - - /** - * @var \Doctrine\Common\Persistence\Mapping\Driver\MappingDriver - */ - private $driver; - - /** - * @var \Doctrine\Common\EventManager - */ - private $evm; - - /** - * @var array - */ - private $embeddablesActiveNesting = []; - - /** - * {@inheritDoc} - */ - protected function loadMetadata($name) - { - $loaded = parent::loadMetadata($name); - - array_map([$this, 'resolveDiscriminatorValue'], array_map([$this, 'getMetadataFor'], $loaded)); - - return $loaded; - } - - /** - * @param EntityManagerInterface $em - */ - public function setEntityManager(EntityManagerInterface $em) - { - $this->em = $em; - } - - /** - * {@inheritDoc} - */ - protected function initialize() - { - $this->driver = $this->em->getConfiguration()->getMetadataDriverImpl(); - $this->evm = $this->em->getEventManager(); - $this->initialized = true; - } - - /** - * {@inheritDoc} - */ - protected function onNotFoundMetadata($className) - { - if (! $this->evm->hasListeners(Events::onClassMetadataNotFound)) { - return; - } - - $eventArgs = new OnClassMetadataNotFoundEventArgs($className, $this->em); - - $this->evm->dispatchEvent(Events::onClassMetadataNotFound, $eventArgs); - - return $eventArgs->getFoundMetadata(); - } - - /** - * {@inheritDoc} - */ - protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonSuperclassParents) - { - /* @var $class ClassMetadata */ - /* @var $parent ClassMetadata */ - if ($parent) { - $class->setInheritanceType($parent->inheritanceType); - $class->setDiscriminatorColumn($parent->discriminatorColumn); - $class->setIdGeneratorType($parent->generatorType); - $this->addInheritedFields($class, $parent); - $this->addInheritedRelations($class, $parent); - $this->addInheritedEmbeddedClasses($class, $parent); - $class->setIdentifier($parent->identifier); - $class->setVersioned($parent->isVersioned); - $class->setVersionField($parent->versionField); - $class->setDiscriminatorMap($parent->discriminatorMap); - $class->setLifecycleCallbacks($parent->lifecycleCallbacks); - $class->setChangeTrackingPolicy($parent->changeTrackingPolicy); - - if ( ! empty($parent->customGeneratorDefinition)) { - $class->setCustomGeneratorDefinition($parent->customGeneratorDefinition); - } - - if ($parent->isMappedSuperclass) { - $class->setCustomRepositoryClass($parent->customRepositoryClassName); - } - } - - // Invoke driver - try { - $this->driver->loadMetadataForClass($class->getName(), $class); - } catch (ReflectionException $e) { - throw MappingException::reflectionFailure($class->getName(), $e); - } - - // If this class has a parent the id generator strategy is inherited. - // However this is only true if the hierarchy of parents contains the root entity, - // if it consists of mapped superclasses these don't necessarily include the id field. - if ($parent && $rootEntityFound) { - $this->inheritIdGeneratorMapping($class, $parent); - } else { - $this->completeIdGeneratorMapping($class); - } - - if (!$class->isMappedSuperclass) { - foreach ($class->embeddedClasses as $property => $embeddableClass) { - - if (isset($embeddableClass['inherited'])) { - continue; - } - - if ( ! (isset($embeddableClass['class']) && $embeddableClass['class'])) { - throw MappingException::missingEmbeddedClass($property); - } - - if (isset($this->embeddablesActiveNesting[$embeddableClass['class']])) { - throw MappingException::infiniteEmbeddableNesting($class->name, $property); - } - - $this->embeddablesActiveNesting[$class->name] = true; - - $embeddableMetadata = $this->getMetadataFor($embeddableClass['class']); - - if ($embeddableMetadata->isEmbeddedClass) { - $this->addNestedEmbeddedClasses($embeddableMetadata, $class, $property); - } - - $identifier = $embeddableMetadata->getIdentifier(); - - if (! empty($identifier)) { - $this->inheritIdGeneratorMapping($class, $embeddableMetadata); - } - - $class->inlineEmbeddable($property, $embeddableMetadata); - - unset($this->embeddablesActiveNesting[$class->name]); - } - } - - if ($parent) { - if ($parent->isInheritanceTypeSingleTable()) { - $class->setPrimaryTable($parent->table); - } - - if ($parent) { - $this->addInheritedIndexes($class, $parent); - } - - if ($parent->cache) { - $class->cache = $parent->cache; - } - - if ($parent->containsForeignIdentifier) { - $class->containsForeignIdentifier = true; - } - - if ( ! empty($parent->namedQueries)) { - $this->addInheritedNamedQueries($class, $parent); - } - - if ( ! empty($parent->namedNativeQueries)) { - $this->addInheritedNamedNativeQueries($class, $parent); - } - - if ( ! empty($parent->sqlResultSetMappings)) { - $this->addInheritedSqlResultSetMappings($class, $parent); - } - - if ( ! empty($parent->entityListeners) && empty($class->entityListeners)) { - $class->entityListeners = $parent->entityListeners; - } - } - - $class->setParentClasses($nonSuperclassParents); - - if ($class->isRootEntity() && ! $class->isInheritanceTypeNone() && ! $class->discriminatorMap) { - $this->addDefaultDiscriminatorMap($class); - } - - if ($this->evm->hasListeners(Events::loadClassMetadata)) { - $eventArgs = new LoadClassMetadataEventArgs($class, $this->em); - $this->evm->dispatchEvent(Events::loadClassMetadata, $eventArgs); - } - - $this->validateRuntimeMetadata($class, $parent); - } - - /** - * Validate runtime metadata is correctly defined. - * - * @param ClassMetadata $class - * @param ClassMetadataInterface|null $parent - * - * @return void - * - * @throws MappingException - */ - protected function validateRuntimeMetadata($class, $parent) - { - if ( ! $class->reflClass ) { - // only validate if there is a reflection class instance - return; - } - - $class->validateIdentifier(); - $class->validateAssociations(); - $class->validateLifecycleCallbacks($this->getReflectionService()); - - // verify inheritance - if ( ! $class->isMappedSuperclass && !$class->isInheritanceTypeNone()) { - if ( ! $parent) { - if (count($class->discriminatorMap) == 0) { - throw MappingException::missingDiscriminatorMap($class->name); - } - if ( ! $class->discriminatorColumn) { - throw MappingException::missingDiscriminatorColumn($class->name); - } - } - } else if ($class->isMappedSuperclass && $class->name == $class->rootEntityName && (count($class->discriminatorMap) || $class->discriminatorColumn)) { - // second condition is necessary for mapped superclasses in the middle of an inheritance hierarchy - throw MappingException::noInheritanceOnMappedSuperClass($class->name); - } - } - - /** - * {@inheritDoc} - */ - protected function newClassMetadataInstance($className) - { - return new ClassMetadata($className, $this->em->getConfiguration()->getNamingStrategy()); - } - - /** - * Populates the discriminator value of the given metadata (if not set) by iterating over discriminator - * map classes and looking for a fitting one. - * - * @param ClassMetadata $metadata - * - * @return void - * - * @throws MappingException - */ - private function resolveDiscriminatorValue(ClassMetadata $metadata) - { - if ($metadata->discriminatorValue - || ! $metadata->discriminatorMap - || $metadata->isMappedSuperclass - || ! $metadata->reflClass - || $metadata->reflClass->isAbstract() - ) { - return; - } - - // minor optimization: avoid loading related metadata when not needed - foreach ($metadata->discriminatorMap as $discriminatorValue => $discriminatorClass) { - if ($discriminatorClass === $metadata->name) { - $metadata->discriminatorValue = $discriminatorValue; - - return; - } - } - - // iterate over discriminator mappings and resolve actual referenced classes according to existing metadata - foreach ($metadata->discriminatorMap as $discriminatorValue => $discriminatorClass) { - if ($metadata->name === $this->getMetadataFor($discriminatorClass)->getName()) { - $metadata->discriminatorValue = $discriminatorValue; - - return; - } - } - - throw MappingException::mappedClassNotPartOfDiscriminatorMap($metadata->name, $metadata->rootEntityName); - } - - /** - * Adds a default discriminator map if no one is given - * - * If an entity is of any inheritance type and does not contain a - * discriminator map, then the map is generated automatically. This process - * is expensive computation wise. - * - * The automatically generated discriminator map contains the lowercase short name of - * each class as key. - * - * @param \Doctrine\ORM\Mapping\ClassMetadata $class - * - * @throws MappingException - */ - private function addDefaultDiscriminatorMap(ClassMetadata $class) - { - $allClasses = $this->driver->getAllClassNames(); - $fqcn = $class->getName(); - $map = [$this->getShortName($class->name) => $fqcn]; - - $duplicates = []; - foreach ($allClasses as $subClassCandidate) { - if (is_subclass_of($subClassCandidate, $fqcn)) { - $shortName = $this->getShortName($subClassCandidate); - - if (isset($map[$shortName])) { - $duplicates[] = $shortName; - } - - $map[$shortName] = $subClassCandidate; - } - } - - if ($duplicates) { - throw MappingException::duplicateDiscriminatorEntry($class->name, $duplicates, $map); - } - - $class->setDiscriminatorMap($map); - } - - /** - * Gets the lower-case short name of a class. - * - * @param string $className - * - * @return string - */ - private function getShortName($className) - { - if (strpos($className, "\\") === false) { - return strtolower($className); - } - - $parts = explode("\\", $className); - - return strtolower(end($parts)); - } - - /** - * Adds inherited fields to the subclass mapping. - * - * @param \Doctrine\ORM\Mapping\ClassMetadata $subClass - * @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass - * - * @return void - */ - private function addInheritedFields(ClassMetadata $subClass, ClassMetadata $parentClass) - { - foreach ($parentClass->fieldMappings as $mapping) { - if ( ! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) { - $mapping['inherited'] = $parentClass->name; - } - if ( ! isset($mapping['declared'])) { - $mapping['declared'] = $parentClass->name; - } - $subClass->addInheritedFieldMapping($mapping); - } - foreach ($parentClass->reflFields as $name => $field) { - $subClass->reflFields[$name] = $field; - } - } - - /** - * Adds inherited association mappings to the subclass mapping. - * - * @param \Doctrine\ORM\Mapping\ClassMetadata $subClass - * @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass - * - * @return void - * - * @throws MappingException - */ - private function addInheritedRelations(ClassMetadata $subClass, ClassMetadata $parentClass) - { - foreach ($parentClass->associationMappings as $field => $mapping) { - if ($parentClass->isMappedSuperclass) { - if ($mapping['type'] & ClassMetadata::TO_MANY && !$mapping['isOwningSide']) { - throw MappingException::illegalToManyAssociationOnMappedSuperclass($parentClass->name, $field); - } - $mapping['sourceEntity'] = $subClass->name; - } - - //$subclassMapping = $mapping; - if ( ! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) { - $mapping['inherited'] = $parentClass->name; - } - if ( ! isset($mapping['declared'])) { - $mapping['declared'] = $parentClass->name; - } - $subClass->addInheritedAssociationMapping($mapping); - } - } - - private function addInheritedEmbeddedClasses(ClassMetadata $subClass, ClassMetadata $parentClass) - { - foreach ($parentClass->embeddedClasses as $field => $embeddedClass) { - if ( ! isset($embeddedClass['inherited']) && ! $parentClass->isMappedSuperclass) { - $embeddedClass['inherited'] = $parentClass->name; - } - if ( ! isset($embeddedClass['declared'])) { - $embeddedClass['declared'] = $parentClass->name; - } - - $subClass->embeddedClasses[$field] = $embeddedClass; - } - } - - /** - * Adds nested embedded classes metadata to a parent class. - * - * @param ClassMetadata $subClass Sub embedded class metadata to add nested embedded classes metadata from. - * @param ClassMetadata $parentClass Parent class to add nested embedded classes metadata to. - * @param string $prefix Embedded classes' prefix to use for nested embedded classes field names. - */ - private function addNestedEmbeddedClasses(ClassMetadata $subClass, ClassMetadata $parentClass, $prefix) - { - foreach ($subClass->embeddedClasses as $property => $embeddableClass) { - if (isset($embeddableClass['inherited'])) { - continue; - } - - $embeddableMetadata = $this->getMetadataFor($embeddableClass['class']); - - $parentClass->mapEmbedded( - [ - 'fieldName' => $prefix . '.' . $property, - 'class' => $embeddableMetadata->name, - 'columnPrefix' => $embeddableClass['columnPrefix'], - 'declaredField' => $embeddableClass['declaredField'] - ? $prefix . '.' . $embeddableClass['declaredField'] - : $prefix, - 'originalField' => $embeddableClass['originalField'] ?: $property, - ] - ); - } - } - - /** - * Copy the table indices from the parent class superclass to the child class - * - * @param ClassMetadata $subClass - * @param ClassMetadata $parentClass - * - * @return void - */ - private function addInheritedIndexes(ClassMetadata $subClass, ClassMetadata $parentClass) - { - if (! $parentClass->isMappedSuperclass) { - return; - } - - foreach (['uniqueConstraints', 'indexes'] as $indexType) { - if (isset($parentClass->table[$indexType])) { - foreach ($parentClass->table[$indexType] as $indexName => $index) { - if (isset($subClass->table[$indexType][$indexName])) { - continue; // Let the inheriting table override indices - } - - $subClass->table[$indexType][$indexName] = $index; - } - } - } - } - - /** - * Adds inherited named queries to the subclass mapping. - * - * @since 2.2 - * - * @param \Doctrine\ORM\Mapping\ClassMetadata $subClass - * @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass - * - * @return void - */ - private function addInheritedNamedQueries(ClassMetadata $subClass, ClassMetadata $parentClass) - { - foreach ($parentClass->namedQueries as $name => $query) { - if ( ! isset ($subClass->namedQueries[$name])) { - $subClass->addNamedQuery( - [ - 'name' => $query['name'], - 'query' => $query['query'] - ] - ); - } - } - } - - /** - * Adds inherited named native queries to the subclass mapping. - * - * @since 2.3 - * - * @param \Doctrine\ORM\Mapping\ClassMetadata $subClass - * @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass - * - * @return void - */ - private function addInheritedNamedNativeQueries(ClassMetadata $subClass, ClassMetadata $parentClass) - { - foreach ($parentClass->namedNativeQueries as $name => $query) { - if ( ! isset ($subClass->namedNativeQueries[$name])) { - $subClass->addNamedNativeQuery( - [ - 'name' => $query['name'], - 'query' => $query['query'], - 'isSelfClass' => $query['isSelfClass'], - 'resultSetMapping' => $query['resultSetMapping'], - 'resultClass' => $query['isSelfClass'] ? $subClass->name : $query['resultClass'], - ] - ); - } - } - } - - /** - * Adds inherited sql result set mappings to the subclass mapping. - * - * @since 2.3 - * - * @param \Doctrine\ORM\Mapping\ClassMetadata $subClass - * @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass - * - * @return void - */ - private function addInheritedSqlResultSetMappings(ClassMetadata $subClass, ClassMetadata $parentClass) - { - foreach ($parentClass->sqlResultSetMappings as $name => $mapping) { - if ( ! isset ($subClass->sqlResultSetMappings[$name])) { - $entities = []; - foreach ($mapping['entities'] as $entity) { - $entities[] = [ - 'fields' => $entity['fields'], - 'isSelfClass' => $entity['isSelfClass'], - 'discriminatorColumn' => $entity['discriminatorColumn'], - 'entityClass' => $entity['isSelfClass'] ? $subClass->name : $entity['entityClass'], - ]; - } - - $subClass->addSqlResultSetMapping( - [ - 'name' => $mapping['name'], - 'columns' => $mapping['columns'], - 'entities' => $entities, - ] - ); - } - } - } - - /** - * Completes the ID generator mapping. If "auto" is specified we choose the generator - * most appropriate for the targeted database platform. - * - * @param ClassMetadataInfo $class - * - * @return void - * - * @throws ORMException - */ - private function completeIdGeneratorMapping(ClassMetadataInfo $class) - { - $idGenType = $class->generatorType; - if ($idGenType == ClassMetadata::GENERATOR_TYPE_AUTO) { - if ($this->getTargetPlatform()->prefersSequences()) { - $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_SEQUENCE); - } else if ($this->getTargetPlatform()->prefersIdentityColumns()) { - $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_IDENTITY); - } else { - $class->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_TABLE); - } - } - - // Create & assign an appropriate ID generator instance - switch ($class->generatorType) { - case ClassMetadata::GENERATOR_TYPE_IDENTITY: - $sequenceName = null; - $fieldName = $class->identifier ? $class->getSingleIdentifierFieldName() : null; - - // Platforms that do not have native IDENTITY support need a sequence to emulate this behaviour. - if ($this->getTargetPlatform()->usesSequenceEmulatedIdentityColumns()) { - $columnName = $class->getSingleIdentifierColumnName(); - $quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']); - $sequencePrefix = $class->getSequencePrefix($this->getTargetPlatform()); - $sequenceName = $this->getTargetPlatform()->getIdentitySequenceName($sequencePrefix, $columnName); - $definition = [ - 'sequenceName' => $this->getTargetPlatform()->fixSchemaElementName($sequenceName) - ]; - - if ($quoted) { - $definition['quoted'] = true; - } - - $sequenceName = $this - ->em - ->getConfiguration() - ->getQuoteStrategy() - ->getSequenceName($definition, $class, $this->getTargetPlatform()); - } - - $generator = ($fieldName && $class->fieldMappings[$fieldName]['type'] === 'bigint') - ? new BigIntegerIdentityGenerator($sequenceName) - : new IdentityGenerator($sequenceName); - - $class->setIdGenerator($generator); - - break; - - case ClassMetadata::GENERATOR_TYPE_SEQUENCE: - // If there is no sequence definition yet, create a default definition - $definition = $class->sequenceGeneratorDefinition; - - if ( ! $definition) { - $fieldName = $class->getSingleIdentifierFieldName(); - $sequenceName = $class->getSequenceName($this->getTargetPlatform()); - $quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']); - - $definition = [ - 'sequenceName' => $this->getTargetPlatform()->fixSchemaElementName($sequenceName), - 'allocationSize' => 1, - 'initialValue' => 1, - ]; - - if ($quoted) { - $definition['quoted'] = true; - } - - $class->setSequenceGeneratorDefinition($definition); - } - - $sequenceGenerator = new \Doctrine\ORM\Id\SequenceGenerator( - $this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->getTargetPlatform()), - $definition['allocationSize'] - ); - $class->setIdGenerator($sequenceGenerator); - break; - - case ClassMetadata::GENERATOR_TYPE_NONE: - $class->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator()); - break; - - case ClassMetadata::GENERATOR_TYPE_UUID: - $class->setIdGenerator(new \Doctrine\ORM\Id\UuidGenerator()); - break; - - case ClassMetadata::GENERATOR_TYPE_TABLE: - throw new ORMException("TableGenerator not yet implemented."); - break; - - case ClassMetadata::GENERATOR_TYPE_CUSTOM: - $definition = $class->customGeneratorDefinition; - if ($definition === null) { - throw new ORMException("Can't instantiate custom generator : no custom generator definition"); - } - if ( ! class_exists($definition['class'])) { - throw new ORMException("Can't instantiate custom generator : " . - $definition['class']); - } - $class->setIdGenerator(new $definition['class']); - break; - - default: - throw new ORMException("Unknown generator type: " . $class->generatorType); - } - } - - /** - * Inherits the ID generator mapping from a parent class. - * - * @param ClassMetadataInfo $class - * @param ClassMetadataInfo $parent - */ - private function inheritIdGeneratorMapping(ClassMetadataInfo $class, ClassMetadataInfo $parent) - { - if ($parent->isIdGeneratorSequence()) { - $class->setSequenceGeneratorDefinition($parent->sequenceGeneratorDefinition); - } elseif ($parent->isIdGeneratorTable()) { - $class->tableGeneratorDefinition = $parent->tableGeneratorDefinition; - } - - if ($parent->generatorType) { - $class->setIdGeneratorType($parent->generatorType); - } - - if ($parent->idGenerator) { - $class->setIdGenerator($parent->idGenerator); - } - } - - /** - * {@inheritDoc} - */ - protected function wakeupReflection(ClassMetadataInterface $class, ReflectionService $reflService) - { - /* @var $class ClassMetadata */ - $class->wakeupReflection($reflService); - } - - /** - * {@inheritDoc} - */ - protected function initializeReflection(ClassMetadataInterface $class, ReflectionService $reflService) - { - /* @var $class ClassMetadata */ - $class->initializeReflection($reflService); - } - - /** - * {@inheritDoc} - */ - protected function getFqcnFromAlias($namespaceAlias, $simpleClassName) - { - return $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName; - } - - /** - * {@inheritDoc} - */ - protected function getDriver() - { - return $this->driver; - } - - /** - * {@inheritDoc} - */ - protected function isEntity(ClassMetadataInterface $class) - { - return isset($class->isMappedSuperclass) && $class->isMappedSuperclass === false; - } - - /** - * @return Platforms\AbstractPlatform - */ - private function getTargetPlatform() - { - if (!$this->targetPlatform) { - $this->targetPlatform = $this->em->getConnection()->getDatabasePlatform(); - } - - return $this->targetPlatform; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php deleted file mode 100644 index 8584a78..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php +++ /dev/null @@ -1,3402 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -use BadMethodCallException; -use Doctrine\Instantiator\Instantiator; -use InvalidArgumentException; -use RuntimeException; -use Doctrine\DBAL\Types\Type; -use Doctrine\DBAL\Platforms\AbstractPlatform; -use ReflectionClass; -use Doctrine\Common\Persistence\Mapping\ClassMetadata; -use Doctrine\ORM\Cache\CacheException; - -/** - * A ClassMetadata instance holds all the object-relational mapping metadata - * of an entity and its associations. - * - * Once populated, ClassMetadata instances are usually cached in a serialized form. - * - * IMPORTANT NOTE: - * - * The fields of this class are only public for 2 reasons: - * 1) To allow fast READ access. - * 2) To drastically reduce the size of a serialized instance (private/protected members - * get the whole class name, namespace inclusive, prepended to every property in - * the serialized representation). - * - * @author Roman Borschel - * @author Jonathan H. Wage - * @since 2.0 - */ -class ClassMetadataInfo implements ClassMetadata -{ - /* The inheritance mapping types */ - /** - * NONE means the class does not participate in an inheritance hierarchy - * and therefore does not need an inheritance mapping type. - */ - const INHERITANCE_TYPE_NONE = 1; - - /** - * JOINED means the class will be persisted according to the rules of - * Class Table Inheritance. - */ - const INHERITANCE_TYPE_JOINED = 2; - - /** - * SINGLE_TABLE means the class will be persisted according to the rules of - * Single Table Inheritance. - */ - const INHERITANCE_TYPE_SINGLE_TABLE = 3; - - /** - * TABLE_PER_CLASS means the class will be persisted according to the rules - * of Concrete Table Inheritance. - */ - const INHERITANCE_TYPE_TABLE_PER_CLASS = 4; - - /* The Id generator types. */ - /** - * AUTO means the generator type will depend on what the used platform prefers. - * Offers full portability. - */ - const GENERATOR_TYPE_AUTO = 1; - - /** - * SEQUENCE means a separate sequence object will be used. Platforms that do - * not have native sequence support may emulate it. Full portability is currently - * not guaranteed. - */ - const GENERATOR_TYPE_SEQUENCE = 2; - - /** - * TABLE means a separate table is used for id generation. - * Offers full portability. - */ - const GENERATOR_TYPE_TABLE = 3; - - /** - * IDENTITY means an identity column is used for id generation. The database - * will fill in the id column on insertion. Platforms that do not support - * native identity columns may emulate them. Full portability is currently - * not guaranteed. - */ - const GENERATOR_TYPE_IDENTITY = 4; - - /** - * NONE means the class does not have a generated id. That means the class - * must have a natural, manually assigned id. - */ - const GENERATOR_TYPE_NONE = 5; - - /** - * UUID means that a UUID/GUID expression is used for id generation. Full - * portability is currently not guaranteed. - */ - const GENERATOR_TYPE_UUID = 6; - - /** - * CUSTOM means that customer will use own ID generator that supposedly work - */ - const GENERATOR_TYPE_CUSTOM = 7; - - /** - * DEFERRED_IMPLICIT means that changes of entities are calculated at commit-time - * by doing a property-by-property comparison with the original data. This will - * be done for all entities that are in MANAGED state at commit-time. - * - * This is the default change tracking policy. - */ - const CHANGETRACKING_DEFERRED_IMPLICIT = 1; - - /** - * DEFERRED_EXPLICIT means that changes of entities are calculated at commit-time - * by doing a property-by-property comparison with the original data. This will - * be done only for entities that were explicitly saved (through persist() or a cascade). - */ - const CHANGETRACKING_DEFERRED_EXPLICIT = 2; - - /** - * NOTIFY means that Doctrine relies on the entities sending out notifications - * when their properties change. Such entity classes must implement - * the NotifyPropertyChanged interface. - */ - const CHANGETRACKING_NOTIFY = 3; - - /** - * Specifies that an association is to be fetched when it is first accessed. - */ - const FETCH_LAZY = 2; - - /** - * Specifies that an association is to be fetched when the owner of the - * association is fetched. - */ - const FETCH_EAGER = 3; - - /** - * Specifies that an association is to be fetched lazy (on first access) and that - * commands such as Collection#count, Collection#slice are issued directly against - * the database if the collection is not yet initialized. - */ - const FETCH_EXTRA_LAZY = 4; - - /** - * Identifies a one-to-one association. - */ - const ONE_TO_ONE = 1; - - /** - * Identifies a many-to-one association. - */ - const MANY_TO_ONE = 2; - - /** - * Identifies a one-to-many association. - */ - const ONE_TO_MANY = 4; - - /** - * Identifies a many-to-many association. - */ - const MANY_TO_MANY = 8; - - /** - * Combined bitmask for to-one (single-valued) associations. - */ - const TO_ONE = 3; - - /** - * Combined bitmask for to-many (collection-valued) associations. - */ - const TO_MANY = 12; - - /** - * ReadOnly cache can do reads, inserts and deletes, cannot perform updates or employ any locks, - */ - const CACHE_USAGE_READ_ONLY = 1; - - /** - * Nonstrict Read Write Cache doesn’t employ any locks but can do inserts, update and deletes. - */ - const CACHE_USAGE_NONSTRICT_READ_WRITE = 2; - - /** - * Read Write Attempts to lock the entity before update/delete. - */ - const CACHE_USAGE_READ_WRITE = 3; - - /** - * READ-ONLY: The name of the entity class. - * - * @var string - */ - public $name; - - /** - * READ-ONLY: The namespace the entity class is contained in. - * - * @var string - * - * @todo Not really needed. Usage could be localized. - */ - public $namespace; - - /** - * READ-ONLY: The name of the entity class that is at the root of the mapped entity inheritance - * hierarchy. If the entity is not part of a mapped inheritance hierarchy this is the same - * as {@link $name}. - * - * @var string - */ - public $rootEntityName; - - /** - * READ-ONLY: The definition of custom generator. Only used for CUSTOM - * generator type - * - * The definition has the following structure: - * - * array( - * 'class' => 'ClassName', - * ) - * - * - * @todo Merge with tableGeneratorDefinition into generic generatorDefinition - * - * @var array|null - */ - public $customGeneratorDefinition; - - /** - * The name of the custom repository class used for the entity class. - * (Optional). - * - * @var string - */ - public $customRepositoryClassName; - - /** - * READ-ONLY: Whether this class describes the mapping of a mapped superclass. - * - * @var boolean - */ - public $isMappedSuperclass = false; - - /** - * READ-ONLY: Whether this class describes the mapping of an embeddable class. - * - * @var boolean - */ - public $isEmbeddedClass = false; - - /** - * READ-ONLY: The names of the parent classes (ancestors). - * - * @var array - */ - public $parentClasses = []; - - /** - * READ-ONLY: The names of all subclasses (descendants). - * - * @var array - */ - public $subClasses = []; - - /** - * READ-ONLY: The names of all embedded classes based on properties. - * - * @var array - */ - public $embeddedClasses = []; - - /** - * READ-ONLY: The named queries allowed to be called directly from Repository. - * - * @var array - */ - public $namedQueries = []; - - /** - * READ-ONLY: The named native queries allowed to be called directly from Repository. - * - * A native SQL named query definition has the following structure: - *
    -     * array(
    -     *     'name'               => ,
    -     *     'query'              => ,
    -     *     'resultClass'        => ,
    -     *     'resultSetMapping'   => 
    -     * )
    -     * 
    - * - * @var array - */ - public $namedNativeQueries = []; - - /** - * READ-ONLY: The mappings of the results of native SQL queries. - * - * A native result mapping definition has the following structure: - *
    -     * array(
    -     *     'name'               => ,
    -     *     'entities'           => array(),
    -     *     'columns'            => array()
    -     * )
    -     * 
    - * - * @var array - */ - public $sqlResultSetMappings = []; - - /** - * READ-ONLY: The field names of all fields that are part of the identifier/primary key - * of the mapped entity class. - * - * @var array - */ - public $identifier = []; - - /** - * READ-ONLY: The inheritance mapping type used by the class. - * - * @var integer - */ - public $inheritanceType = self::INHERITANCE_TYPE_NONE; - - /** - * READ-ONLY: The Id generator type used by the class. - * - * @var int - */ - public $generatorType = self::GENERATOR_TYPE_NONE; - - /** - * READ-ONLY: The field mappings of the class. - * Keys are field names and values are mapping definitions. - * - * The mapping definition array has the following values: - * - * - fieldName (string) - * The name of the field in the Entity. - * - * - type (string) - * The type name of the mapped field. Can be one of Doctrine's mapping types - * or a custom mapping type. - * - * - columnName (string, optional) - * The column name. Optional. Defaults to the field name. - * - * - length (integer, optional) - * The database length of the column. Optional. Default value taken from - * the type. - * - * - id (boolean, optional) - * Marks the field as the primary key of the entity. Multiple fields of an - * entity can have the id attribute, forming a composite key. - * - * - nullable (boolean, optional) - * Whether the column is nullable. Defaults to FALSE. - * - * - columnDefinition (string, optional, schema-only) - * The SQL fragment that is used when generating the DDL for the column. - * - * - precision (integer, optional, schema-only) - * The precision of a decimal column. Only valid if the column type is decimal. - * - * - scale (integer, optional, schema-only) - * The scale of a decimal column. Only valid if the column type is decimal. - * - * - 'unique' (string, optional, schema-only) - * Whether a unique constraint should be generated for the column. - * - * @var array - */ - public $fieldMappings = []; - - /** - * READ-ONLY: An array of field names. Used to look up field names from column names. - * Keys are column names and values are field names. - * - * @var array - */ - public $fieldNames = []; - - /** - * READ-ONLY: A map of field names to column names. Keys are field names and values column names. - * Used to look up column names from field names. - * This is the reverse lookup map of $_fieldNames. - * - * @var array - * - * @deprecated 3.0 Remove this. - */ - public $columnNames = []; - - /** - * READ-ONLY: The discriminator value of this class. - * - * This does only apply to the JOINED and SINGLE_TABLE inheritance mapping strategies - * where a discriminator column is used. - * - * @var mixed - * - * @see discriminatorColumn - */ - public $discriminatorValue; - - /** - * READ-ONLY: The discriminator map of all mapped classes in the hierarchy. - * - * This does only apply to the JOINED and SINGLE_TABLE inheritance mapping strategies - * where a discriminator column is used. - * - * @var mixed - * - * @see discriminatorColumn - */ - public $discriminatorMap = []; - - /** - * READ-ONLY: The definition of the discriminator column used in JOINED and SINGLE_TABLE - * inheritance mappings. - * - * @var array - */ - public $discriminatorColumn; - - /** - * READ-ONLY: The primary table definition. The definition is an array with the - * following entries: - * - * name => - * schema => - * indexes => array - * uniqueConstraints => array - * - * @var array - */ - public $table; - - /** - * READ-ONLY: The registered lifecycle callbacks for entities of this class. - * - * @var array[] - */ - public $lifecycleCallbacks = []; - - /** - * READ-ONLY: The registered entity listeners. - * - * @var array - */ - public $entityListeners = []; - - /** - * READ-ONLY: The association mappings of this class. - * - * The mapping definition array supports the following keys: - * - * - fieldName (string) - * The name of the field in the entity the association is mapped to. - * - * - targetEntity (string) - * The class name of the target entity. If it is fully-qualified it is used as is. - * If it is a simple, unqualified class name the namespace is assumed to be the same - * as the namespace of the source entity. - * - * - mappedBy (string, required for bidirectional associations) - * The name of the field that completes the bidirectional association on the owning side. - * This key must be specified on the inverse side of a bidirectional association. - * - * - inversedBy (string, required for bidirectional associations) - * The name of the field that completes the bidirectional association on the inverse side. - * This key must be specified on the owning side of a bidirectional association. - * - * - cascade (array, optional) - * The names of persistence operations to cascade on the association. The set of possible - * values are: "persist", "remove", "detach", "merge", "refresh", "all" (implies all others). - * - * - orderBy (array, one-to-many/many-to-many only) - * A map of field names (of the target entity) to sorting directions (ASC/DESC). - * Example: array('priority' => 'desc') - * - * - fetch (integer, optional) - * The fetching strategy to use for the association, usually defaults to FETCH_LAZY. - * Possible values are: ClassMetadata::FETCH_EAGER, ClassMetadata::FETCH_LAZY. - * - * - joinTable (array, optional, many-to-many only) - * Specification of the join table and its join columns (foreign keys). - * Only valid for many-to-many mappings. Note that one-to-many associations can be mapped - * through a join table by simply mapping the association as many-to-many with a unique - * constraint on the join table. - * - * - indexBy (string, optional, to-many only) - * Specification of a field on target-entity that is used to index the collection by. - * This field HAS to be either the primary key or a unique column. Otherwise the collection - * does not contain all the entities that are actually related. - * - * A join table definition has the following structure: - *
    -     * array(
    -     *     'name' => ,
    -     *      'joinColumns' => array(),
    -     *      'inverseJoinColumns' => array()
    -     * )
    -     * 
    - * - * @var array - */ - public $associationMappings = []; - - /** - * READ-ONLY: Flag indicating whether the identifier/primary key of the class is composite. - * - * @var boolean - */ - public $isIdentifierComposite = false; - - /** - * READ-ONLY: Flag indicating whether the identifier/primary key contains at least one foreign key association. - * - * This flag is necessary because some code blocks require special treatment of this cases. - * - * @var boolean - */ - public $containsForeignIdentifier = false; - - /** - * READ-ONLY: The ID generator used for generating IDs for this class. - * - * @var \Doctrine\ORM\Id\AbstractIdGenerator - * - * @todo Remove! - */ - public $idGenerator; - - /** - * READ-ONLY: The definition of the sequence generator of this class. Only used for the - * SEQUENCE generation strategy. - * - * The definition has the following structure: - * - * array( - * 'sequenceName' => 'name', - * 'allocationSize' => 20, - * 'initialValue' => 1 - * ) - * - * - * @var array - * - * @todo Merge with tableGeneratorDefinition into generic generatorDefinition - */ - public $sequenceGeneratorDefinition; - - /** - * READ-ONLY: The definition of the table generator of this class. Only used for the - * TABLE generation strategy. - * - * @var array - * - * @todo Merge with tableGeneratorDefinition into generic generatorDefinition - */ - public $tableGeneratorDefinition; - - /** - * READ-ONLY: The policy used for change-tracking on entities of this class. - * - * @var integer - */ - public $changeTrackingPolicy = self::CHANGETRACKING_DEFERRED_IMPLICIT; - - /** - * READ-ONLY: A flag for whether or not instances of this class are to be versioned - * with optimistic locking. - * - * @var boolean - */ - public $isVersioned; - - /** - * READ-ONLY: The name of the field which is used for versioning in optimistic locking (if any). - * - * @var mixed - */ - public $versionField; - - /** - * @var array - */ - public $cache = null; - - /** - * The ReflectionClass instance of the mapped class. - * - * @var ReflectionClass - */ - public $reflClass; - - /** - * Is this entity marked as "read-only"? - * - * That means it is never considered for change-tracking in the UnitOfWork. It is a very helpful performance - * optimization for entities that are immutable, either in your domain or through the relation database - * (coming from a view, or a history table for example). - * - * @var bool - */ - public $isReadOnly = false; - - /** - * NamingStrategy determining the default column and table names. - * - * @var \Doctrine\ORM\Mapping\NamingStrategy - */ - protected $namingStrategy; - - /** - * The ReflectionProperty instances of the mapped class. - * - * @var \ReflectionProperty[] - */ - public $reflFields = []; - - /** - * @var \Doctrine\Instantiator\InstantiatorInterface|null - */ - private $instantiator; - - /** - * Initializes a new ClassMetadata instance that will hold the object-relational mapping - * metadata of the class with the given name. - * - * @param string $entityName The name of the entity class the new instance is used for. - * @param NamingStrategy|null $namingStrategy - */ - public function __construct($entityName, NamingStrategy $namingStrategy = null) - { - $this->name = $entityName; - $this->rootEntityName = $entityName; - $this->namingStrategy = $namingStrategy ?: new DefaultNamingStrategy(); - $this->instantiator = new Instantiator(); - } - - /** - * Gets the ReflectionProperties of the mapped class. - * - * @return array An array of ReflectionProperty instances. - */ - public function getReflectionProperties() - { - return $this->reflFields; - } - - /** - * Gets a ReflectionProperty for a specific field of the mapped class. - * - * @param string $name - * - * @return \ReflectionProperty - */ - public function getReflectionProperty($name) - { - return $this->reflFields[$name]; - } - - /** - * Gets the ReflectionProperty for the single identifier field. - * - * @return \ReflectionProperty - * - * @throws BadMethodCallException If the class has a composite identifier. - */ - public function getSingleIdReflectionProperty() - { - if ($this->isIdentifierComposite) { - throw new BadMethodCallException("Class " . $this->name . " has a composite identifier."); - } - - return $this->reflFields[$this->identifier[0]]; - } - - /** - * Extracts the identifier values of an entity of this class. - * - * For composite identifiers, the identifier values are returned as an array - * with the same order as the field order in {@link identifier}. - * - * @param object $entity - * - * @return array - */ - public function getIdentifierValues($entity) - { - if ($this->isIdentifierComposite) { - $id = []; - - foreach ($this->identifier as $idField) { - $value = $this->reflFields[$idField]->getValue($entity); - - if (null !== $value) { - $id[$idField] = $value; - } - } - - return $id; - } - - $id = $this->identifier[0]; - $value = $this->reflFields[$id]->getValue($entity); - - if (null === $value) { - return []; - } - - return [$id => $value]; - } - - /** - * Populates the entity identifier of an entity. - * - * @param object $entity - * @param array $id - * - * @return void - * - * @todo Rename to assignIdentifier() - */ - public function setIdentifierValues($entity, array $id) - { - foreach ($id as $idField => $idValue) { - $this->reflFields[$idField]->setValue($entity, $idValue); - } - } - - /** - * Sets the specified field to the specified value on the given entity. - * - * @param object $entity - * @param string $field - * @param mixed $value - * - * @return void - */ - public function setFieldValue($entity, $field, $value) - { - $this->reflFields[$field]->setValue($entity, $value); - } - - /** - * Gets the specified field's value off the given entity. - * - * @param object $entity - * @param string $field - * - * @return mixed - */ - public function getFieldValue($entity, $field) - { - return $this->reflFields[$field]->getValue($entity); - } - - /** - * Creates a string representation of this instance. - * - * @return string The string representation of this instance. - * - * @todo Construct meaningful string representation. - */ - public function __toString() - { - return __CLASS__ . '@' . spl_object_hash($this); - } - - /** - * Determines which fields get serialized. - * - * It is only serialized what is necessary for best unserialization performance. - * That means any metadata properties that are not set or empty or simply have - * their default value are NOT serialized. - * - * Parts that are also NOT serialized because they can not be properly unserialized: - * - reflClass (ReflectionClass) - * - reflFields (ReflectionProperty array) - * - * @return array The names of all the fields that should be serialized. - */ - public function __sleep() - { - // This metadata is always serialized/cached. - $serialized = [ - 'associationMappings', - 'columnNames', //TODO: 3.0 Remove this. Can use fieldMappings[$fieldName]['columnName'] - 'fieldMappings', - 'fieldNames', - 'embeddedClasses', - 'identifier', - 'isIdentifierComposite', // TODO: REMOVE - 'name', - 'namespace', // TODO: REMOVE - 'table', - 'rootEntityName', - 'idGenerator', //TODO: Does not really need to be serialized. Could be moved to runtime. - ]; - - // The rest of the metadata is only serialized if necessary. - if ($this->changeTrackingPolicy != self::CHANGETRACKING_DEFERRED_IMPLICIT) { - $serialized[] = 'changeTrackingPolicy'; - } - - if ($this->customRepositoryClassName) { - $serialized[] = 'customRepositoryClassName'; - } - - if ($this->inheritanceType != self::INHERITANCE_TYPE_NONE) { - $serialized[] = 'inheritanceType'; - $serialized[] = 'discriminatorColumn'; - $serialized[] = 'discriminatorValue'; - $serialized[] = 'discriminatorMap'; - $serialized[] = 'parentClasses'; - $serialized[] = 'subClasses'; - } - - if ($this->generatorType != self::GENERATOR_TYPE_NONE) { - $serialized[] = 'generatorType'; - if ($this->generatorType == self::GENERATOR_TYPE_SEQUENCE) { - $serialized[] = 'sequenceGeneratorDefinition'; - } - } - - if ($this->isMappedSuperclass) { - $serialized[] = 'isMappedSuperclass'; - } - - if ($this->isEmbeddedClass) { - $serialized[] = 'isEmbeddedClass'; - } - - if ($this->containsForeignIdentifier) { - $serialized[] = 'containsForeignIdentifier'; - } - - if ($this->isVersioned) { - $serialized[] = 'isVersioned'; - $serialized[] = 'versionField'; - } - - if ($this->lifecycleCallbacks) { - $serialized[] = 'lifecycleCallbacks'; - } - - if ($this->entityListeners) { - $serialized[] = 'entityListeners'; - } - - if ($this->namedQueries) { - $serialized[] = 'namedQueries'; - } - - if ($this->namedNativeQueries) { - $serialized[] = 'namedNativeQueries'; - } - - if ($this->sqlResultSetMappings) { - $serialized[] = 'sqlResultSetMappings'; - } - - if ($this->isReadOnly) { - $serialized[] = 'isReadOnly'; - } - - if ($this->customGeneratorDefinition) { - $serialized[] = "customGeneratorDefinition"; - } - - if ($this->cache) { - $serialized[] = 'cache'; - } - - return $serialized; - } - - /** - * Creates a new instance of the mapped class, without invoking the constructor. - * - * @return object - */ - public function newInstance() - { - return $this->instantiator->instantiate($this->name); - } - - /** - * Restores some state that can not be serialized/unserialized. - * - * @param \Doctrine\Common\Persistence\Mapping\ReflectionService $reflService - * - * @return void - */ - public function wakeupReflection($reflService) - { - // Restore ReflectionClass and properties - $this->reflClass = $reflService->getClass($this->name); - $this->instantiator = $this->instantiator ?: new Instantiator(); - - $parentReflFields = []; - - foreach ($this->embeddedClasses as $property => $embeddedClass) { - if (isset($embeddedClass['declaredField'])) { - $parentReflFields[$property] = new ReflectionEmbeddedProperty( - $parentReflFields[$embeddedClass['declaredField']], - $reflService->getAccessibleProperty( - $this->embeddedClasses[$embeddedClass['declaredField']]['class'], - $embeddedClass['originalField'] - ), - $this->embeddedClasses[$embeddedClass['declaredField']]['class'] - ); - - continue; - } - - $fieldRefl = $reflService->getAccessibleProperty( - $embeddedClass['declared'] ?? $this->name, - $property - ); - - $parentReflFields[$property] = $fieldRefl; - $this->reflFields[$property] = $fieldRefl; - } - - foreach ($this->fieldMappings as $field => $mapping) { - if (isset($mapping['declaredField']) && isset($parentReflFields[$mapping['declaredField']])) { - $this->reflFields[$field] = new ReflectionEmbeddedProperty( - $parentReflFields[$mapping['declaredField']], - $reflService->getAccessibleProperty($mapping['originalClass'], $mapping['originalField']), - $mapping['originalClass'] - ); - continue; - } - - $this->reflFields[$field] = isset($mapping['declared']) - ? $reflService->getAccessibleProperty($mapping['declared'], $field) - : $reflService->getAccessibleProperty($this->name, $field); - } - - foreach ($this->associationMappings as $field => $mapping) { - $this->reflFields[$field] = isset($mapping['declared']) - ? $reflService->getAccessibleProperty($mapping['declared'], $field) - : $reflService->getAccessibleProperty($this->name, $field); - } - } - - /** - * Initializes a new ClassMetadata instance that will hold the object-relational mapping - * metadata of the class with the given name. - * - * @param \Doctrine\Common\Persistence\Mapping\ReflectionService $reflService The reflection service. - * - * @return void - */ - public function initializeReflection($reflService) - { - $this->reflClass = $reflService->getClass($this->name); - $this->namespace = $reflService->getClassNamespace($this->name); - - if ($this->reflClass) { - $this->name = $this->rootEntityName = $this->reflClass->getName(); - } - - $this->table['name'] = $this->namingStrategy->classToTableName($this->name); - } - - /** - * Validates Identifier. - * - * @return void - * - * @throws MappingException - */ - public function validateIdentifier() - { - if ($this->isMappedSuperclass || $this->isEmbeddedClass) { - return; - } - - // Verify & complete identifier mapping - if ( ! $this->identifier) { - throw MappingException::identifierRequired($this->name); - } - - if ($this->usesIdGenerator() && $this->isIdentifierComposite) { - throw MappingException::compositeKeyAssignedIdGeneratorRequired($this->name); - } - } - - /** - * Validates association targets actually exist. - * - * @return void - * - * @throws MappingException - */ - public function validateAssociations() - { - foreach ($this->associationMappings as $mapping) { - if ( - ! class_exists($mapping['targetEntity']) - && ! interface_exists($mapping['targetEntity']) - && ! trait_exists($mapping['targetEntity']) - ) { - throw MappingException::invalidTargetEntityClass($mapping['targetEntity'], $this->name, $mapping['fieldName']); - } - } - } - - /** - * Validates lifecycle callbacks. - * - * @param \Doctrine\Common\Persistence\Mapping\ReflectionService $reflService - * - * @return void - * - * @throws MappingException - */ - public function validateLifecycleCallbacks($reflService) - { - foreach ($this->lifecycleCallbacks as $callbacks) { - foreach ($callbacks as $callbackFuncName) { - if ( ! $reflService->hasPublicMethod($this->name, $callbackFuncName)) { - throw MappingException::lifecycleCallbackMethodNotFound($this->name, $callbackFuncName); - } - } - } - } - - /** - * {@inheritDoc} - */ - public function getReflectionClass() - { - return $this->reflClass; - } - - /** - * @param array $cache - * - * @return void - */ - public function enableCache(array $cache) - { - if ( ! isset($cache['usage'])) { - $cache['usage'] = self::CACHE_USAGE_READ_ONLY; - } - - if ( ! isset($cache['region'])) { - $cache['region'] = strtolower(str_replace('\\', '_', $this->rootEntityName)); - } - - $this->cache = $cache; - } - - /** - * @param string $fieldName - * @param array $cache - * - * @return void - */ - public function enableAssociationCache($fieldName, array $cache) - { - $this->associationMappings[$fieldName]['cache'] = $this->getAssociationCacheDefaults($fieldName, $cache); - } - - /** - * @param string $fieldName - * @param array $cache - * - * @return array - */ - public function getAssociationCacheDefaults($fieldName, array $cache) - { - if ( ! isset($cache['usage'])) { - $cache['usage'] = isset($this->cache['usage']) - ? $this->cache['usage'] - : self::CACHE_USAGE_READ_ONLY; - } - - if ( ! isset($cache['region'])) { - $cache['region'] = strtolower(str_replace('\\', '_', $this->rootEntityName)) . '__' . $fieldName; - } - - return $cache; - } - - /** - * Sets the change tracking policy used by this class. - * - * @param integer $policy - * - * @return void - */ - public function setChangeTrackingPolicy($policy) - { - $this->changeTrackingPolicy = $policy; - } - - /** - * Whether the change tracking policy of this class is "deferred explicit". - * - * @return boolean - */ - public function isChangeTrackingDeferredExplicit() - { - return self::CHANGETRACKING_DEFERRED_EXPLICIT === $this->changeTrackingPolicy; - } - - /** - * Whether the change tracking policy of this class is "deferred implicit". - * - * @return boolean - */ - public function isChangeTrackingDeferredImplicit() - { - return self::CHANGETRACKING_DEFERRED_IMPLICIT === $this->changeTrackingPolicy; - } - - /** - * Whether the change tracking policy of this class is "notify". - * - * @return boolean - */ - public function isChangeTrackingNotify() - { - return self::CHANGETRACKING_NOTIFY === $this->changeTrackingPolicy; - } - - /** - * Checks whether a field is part of the identifier/primary key field(s). - * - * @param string $fieldName The field name. - * - * @return boolean TRUE if the field is part of the table identifier/primary key field(s), - * FALSE otherwise. - */ - public function isIdentifier($fieldName) - { - if ( ! $this->identifier) { - return false; - } - - if ( ! $this->isIdentifierComposite) { - return $fieldName === $this->identifier[0]; - } - - return in_array($fieldName, $this->identifier, true); - } - - /** - * Checks if the field is unique. - * - * @param string $fieldName The field name. - * - * @return boolean TRUE if the field is unique, FALSE otherwise. - */ - public function isUniqueField($fieldName) - { - $mapping = $this->getFieldMapping($fieldName); - - return false !== $mapping && isset($mapping['unique']) && $mapping['unique']; - } - - /** - * Checks if the field is not null. - * - * @param string $fieldName The field name. - * - * @return boolean TRUE if the field is not null, FALSE otherwise. - */ - public function isNullable($fieldName) - { - $mapping = $this->getFieldMapping($fieldName); - - return false !== $mapping && isset($mapping['nullable']) && $mapping['nullable']; - } - - /** - * Gets a column name for a field name. - * If the column name for the field cannot be found, the given field name - * is returned. - * - * @param string $fieldName The field name. - * - * @return string The column name. - */ - public function getColumnName($fieldName) - { - return isset($this->columnNames[$fieldName]) - ? $this->columnNames[$fieldName] - : $fieldName; - } - - /** - * Gets the mapping of a (regular) field that holds some data but not a - * reference to another object. - * - * @param string $fieldName The field name. - * - * @return array The field mapping. - * - * @throws MappingException - */ - public function getFieldMapping($fieldName) - { - if ( ! isset($this->fieldMappings[$fieldName])) { - throw MappingException::mappingNotFound($this->name, $fieldName); - } - - return $this->fieldMappings[$fieldName]; - } - - /** - * Gets the mapping of an association. - * - * @see ClassMetadataInfo::$associationMappings - * - * @param string $fieldName The field name that represents the association in - * the object model. - * - * @return array The mapping. - * - * @throws MappingException - */ - public function getAssociationMapping($fieldName) - { - if ( ! isset($this->associationMappings[$fieldName])) { - throw MappingException::mappingNotFound($this->name, $fieldName); - } - - return $this->associationMappings[$fieldName]; - } - - /** - * Gets all association mappings of the class. - * - * @return array - */ - public function getAssociationMappings() - { - return $this->associationMappings; - } - - /** - * Gets the field name for a column name. - * If no field name can be found the column name is returned. - * - * @param string $columnName The column name. - * - * @return string The column alias. - */ - public function getFieldName($columnName) - { - return isset($this->fieldNames[$columnName]) - ? $this->fieldNames[$columnName] - : $columnName; - } - - /** - * Gets the named query. - * - * @see ClassMetadataInfo::$namedQueries - * - * @param string $queryName The query name. - * - * @return string - * - * @throws MappingException - */ - public function getNamedQuery($queryName) - { - if ( ! isset($this->namedQueries[$queryName])) { - throw MappingException::queryNotFound($this->name, $queryName); - } - - return $this->namedQueries[$queryName]['dql']; - } - - /** - * Gets all named queries of the class. - * - * @return array - */ - public function getNamedQueries() - { - return $this->namedQueries; - } - - /** - * Gets the named native query. - * - * @see ClassMetadataInfo::$namedNativeQueries - * - * @param string $queryName The query name. - * - * @return array - * - * @throws MappingException - */ - public function getNamedNativeQuery($queryName) - { - if ( ! isset($this->namedNativeQueries[$queryName])) { - throw MappingException::queryNotFound($this->name, $queryName); - } - - return $this->namedNativeQueries[$queryName]; - } - - /** - * Gets all named native queries of the class. - * - * @return array - */ - public function getNamedNativeQueries() - { - return $this->namedNativeQueries; - } - - /** - * Gets the result set mapping. - * - * @see ClassMetadataInfo::$sqlResultSetMappings - * - * @param string $name The result set mapping name. - * - * @return array - * - * @throws MappingException - */ - public function getSqlResultSetMapping($name) - { - if ( ! isset($this->sqlResultSetMappings[$name])) { - throw MappingException::resultMappingNotFound($this->name, $name); - } - - return $this->sqlResultSetMappings[$name]; - } - - /** - * Gets all sql result set mappings of the class. - * - * @return array - */ - public function getSqlResultSetMappings() - { - return $this->sqlResultSetMappings; - } - - /** - * Validates & completes the given field mapping. - * - * @param array $mapping The field mapping to validate & complete. - * - * @return void - * - * @throws MappingException - */ - protected function _validateAndCompleteFieldMapping(array &$mapping) - { - // Check mandatory fields - if ( ! isset($mapping['fieldName']) || !$mapping['fieldName']) { - throw MappingException::missingFieldName($this->name); - } - - if ( ! isset($mapping['type'])) { - // Default to string - $mapping['type'] = 'string'; - } - - // Complete fieldName and columnName mapping - if ( ! isset($mapping['columnName'])) { - $mapping['columnName'] = $this->namingStrategy->propertyToColumnName($mapping['fieldName'], $this->name); - } - - if ('`' === $mapping['columnName'][0]) { - $mapping['columnName'] = trim($mapping['columnName'], '`'); - $mapping['quoted'] = true; - } - - $this->columnNames[$mapping['fieldName']] = $mapping['columnName']; - - if (isset($this->fieldNames[$mapping['columnName']]) || ($this->discriminatorColumn && $this->discriminatorColumn['name'] === $mapping['columnName'])) { - throw MappingException::duplicateColumnName($this->name, $mapping['columnName']); - } - - $this->fieldNames[$mapping['columnName']] = $mapping['fieldName']; - - // Complete id mapping - if (isset($mapping['id']) && true === $mapping['id']) { - if ($this->versionField == $mapping['fieldName']) { - throw MappingException::cannotVersionIdField($this->name, $mapping['fieldName']); - } - - if ( ! in_array($mapping['fieldName'], $this->identifier)) { - $this->identifier[] = $mapping['fieldName']; - } - - // Check for composite key - if ( ! $this->isIdentifierComposite && count($this->identifier) > 1) { - $this->isIdentifierComposite = true; - } - } - - if (Type::hasType($mapping['type']) && Type::getType($mapping['type'])->canRequireSQLConversion()) { - if (isset($mapping['id']) && true === $mapping['id']) { - throw MappingException::sqlConversionNotAllowedForIdentifiers($this->name, $mapping['fieldName'], $mapping['type']); - } - - $mapping['requireSQLConversion'] = true; - } - } - - /** - * Validates & completes the basic mapping information that is common to all - * association mappings (one-to-one, many-ot-one, one-to-many, many-to-many). - * - * @param array $mapping The mapping. - * - * @return array The updated mapping. - * - * @throws MappingException If something is wrong with the mapping. - */ - protected function _validateAndCompleteAssociationMapping(array $mapping) - { - if ( ! isset($mapping['mappedBy'])) { - $mapping['mappedBy'] = null; - } - - if ( ! isset($mapping['inversedBy'])) { - $mapping['inversedBy'] = null; - } - - $mapping['isOwningSide'] = true; // assume owning side until we hit mappedBy - - if (empty($mapping['indexBy'])) { - unset($mapping['indexBy']); - } - - // If targetEntity is unqualified, assume it is in the same namespace as - // the sourceEntity. - $mapping['sourceEntity'] = $this->name; - - if (isset($mapping['targetEntity'])) { - $mapping['targetEntity'] = $this->fullyQualifiedClassName($mapping['targetEntity']); - $mapping['targetEntity'] = ltrim($mapping['targetEntity'], '\\'); - } - - if (($mapping['type'] & self::MANY_TO_ONE) > 0 && isset($mapping['orphanRemoval']) && $mapping['orphanRemoval']) { - throw MappingException::illegalOrphanRemoval($this->name, $mapping['fieldName']); - } - - // Complete id mapping - if (isset($mapping['id']) && true === $mapping['id']) { - if (isset($mapping['orphanRemoval']) && $mapping['orphanRemoval']) { - throw MappingException::illegalOrphanRemovalOnIdentifierAssociation($this->name, $mapping['fieldName']); - } - - if ( ! in_array($mapping['fieldName'], $this->identifier)) { - if (isset($mapping['joinColumns']) && count($mapping['joinColumns']) >= 2) { - throw MappingException::cannotMapCompositePrimaryKeyEntitiesAsForeignId( - $mapping['targetEntity'], $this->name, $mapping['fieldName'] - ); - } - - $this->identifier[] = $mapping['fieldName']; - $this->containsForeignIdentifier = true; - } - - // Check for composite key - if ( ! $this->isIdentifierComposite && count($this->identifier) > 1) { - $this->isIdentifierComposite = true; - } - - if ($this->cache && !isset($mapping['cache'])) { - throw CacheException::nonCacheableEntityAssociation($this->name, $mapping['fieldName']); - } - } - - // Mandatory attributes for both sides - // Mandatory: fieldName, targetEntity - if ( ! isset($mapping['fieldName']) || !$mapping['fieldName']) { - throw MappingException::missingFieldName($this->name); - } - - if ( ! isset($mapping['targetEntity'])) { - throw MappingException::missingTargetEntity($mapping['fieldName']); - } - - // Mandatory and optional attributes for either side - if ( ! $mapping['mappedBy']) { - if (isset($mapping['joinTable']) && $mapping['joinTable']) { - if (isset($mapping['joinTable']['name']) && $mapping['joinTable']['name'][0] === '`') { - $mapping['joinTable']['name'] = trim($mapping['joinTable']['name'], '`'); - $mapping['joinTable']['quoted'] = true; - } - } - } else { - $mapping['isOwningSide'] = false; - } - - if (isset($mapping['id']) && true === $mapping['id'] && $mapping['type'] & self::TO_MANY) { - throw MappingException::illegalToManyIdentifierAssociation($this->name, $mapping['fieldName']); - } - - // Fetch mode. Default fetch mode to LAZY, if not set. - if ( ! isset($mapping['fetch'])) { - $mapping['fetch'] = self::FETCH_LAZY; - } - - // Cascades - $cascades = isset($mapping['cascade']) ? array_map('strtolower', $mapping['cascade']) : []; - - $allCascades = ['remove', 'persist', 'refresh', 'merge', 'detach']; - if (in_array('all', $cascades)) { - $cascades = $allCascades; - } elseif (count($cascades) !== count(array_intersect($cascades, $allCascades))) { - throw MappingException::invalidCascadeOption( - array_diff($cascades, $allCascades), - $this->name, - $mapping['fieldName'] - ); - } - - $mapping['cascade'] = $cascades; - $mapping['isCascadeRemove'] = in_array('remove', $cascades); - $mapping['isCascadePersist'] = in_array('persist', $cascades); - $mapping['isCascadeRefresh'] = in_array('refresh', $cascades); - $mapping['isCascadeMerge'] = in_array('merge', $cascades); - $mapping['isCascadeDetach'] = in_array('detach', $cascades); - - return $mapping; - } - - /** - * Validates & completes a one-to-one association mapping. - * - * @param array $mapping The mapping to validate & complete. - * - * @return array The validated & completed mapping. - * - * @throws RuntimeException - * @throws MappingException - */ - protected function _validateAndCompleteOneToOneMapping(array $mapping) - { - $mapping = $this->_validateAndCompleteAssociationMapping($mapping); - - if (isset($mapping['joinColumns']) && $mapping['joinColumns']) { - $mapping['isOwningSide'] = true; - } - - if ($mapping['isOwningSide']) { - if (empty($mapping['joinColumns'])) { - // Apply default join column - $mapping['joinColumns'] = [ - [ - 'name' => $this->namingStrategy->joinColumnName($mapping['fieldName'], $this->name), - 'referencedColumnName' => $this->namingStrategy->referenceColumnName() - ] - ]; - } - - $uniqueConstraintColumns = []; - - foreach ($mapping['joinColumns'] as &$joinColumn) { - if ($mapping['type'] === self::ONE_TO_ONE && ! $this->isInheritanceTypeSingleTable()) { - if (count($mapping['joinColumns']) === 1) { - if (empty($mapping['id'])) { - $joinColumn['unique'] = true; - } - } else { - $uniqueConstraintColumns[] = $joinColumn['name']; - } - } - - if (empty($joinColumn['name'])) { - $joinColumn['name'] = $this->namingStrategy->joinColumnName($mapping['fieldName'], $this->name); - } - - if (empty($joinColumn['referencedColumnName'])) { - $joinColumn['referencedColumnName'] = $this->namingStrategy->referenceColumnName(); - } - - if ($joinColumn['name'][0] === '`') { - $joinColumn['name'] = trim($joinColumn['name'], '`'); - $joinColumn['quoted'] = true; - } - - if ($joinColumn['referencedColumnName'][0] === '`') { - $joinColumn['referencedColumnName'] = trim($joinColumn['referencedColumnName'], '`'); - $joinColumn['quoted'] = true; - } - - $mapping['sourceToTargetKeyColumns'][$joinColumn['name']] = $joinColumn['referencedColumnName']; - $mapping['joinColumnFieldNames'][$joinColumn['name']] = $joinColumn['fieldName'] ?? $joinColumn['name']; - } - - if ($uniqueConstraintColumns) { - if ( ! $this->table) { - throw new RuntimeException("ClassMetadataInfo::setTable() has to be called before defining a one to one relationship."); - } - - $this->table['uniqueConstraints'][$mapping['fieldName'] . "_uniq"] = [ - 'columns' => $uniqueConstraintColumns - ]; - } - - $mapping['targetToSourceKeyColumns'] = array_flip($mapping['sourceToTargetKeyColumns']); - } - - $mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) && $mapping['orphanRemoval']; - $mapping['isCascadeRemove'] = $mapping['orphanRemoval'] || $mapping['isCascadeRemove']; - - if ($mapping['orphanRemoval']) { - unset($mapping['unique']); - } - - if (isset($mapping['id']) && $mapping['id'] === true && !$mapping['isOwningSide']) { - throw MappingException::illegalInverseIdentifierAssociation($this->name, $mapping['fieldName']); - } - - return $mapping; - } - - /** - * Validates & completes a one-to-many association mapping. - * - * @param array $mapping The mapping to validate and complete. - * - * @return array The validated and completed mapping. - * - * @throws MappingException - * @throws InvalidArgumentException - */ - protected function _validateAndCompleteOneToManyMapping(array $mapping) - { - $mapping = $this->_validateAndCompleteAssociationMapping($mapping); - - // OneToMany-side MUST be inverse (must have mappedBy) - if ( ! isset($mapping['mappedBy'])) { - throw MappingException::oneToManyRequiresMappedBy($mapping['fieldName']); - } - - $mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) && $mapping['orphanRemoval']; - $mapping['isCascadeRemove'] = $mapping['orphanRemoval'] || $mapping['isCascadeRemove']; - - $this->assertMappingOrderBy($mapping); - - return $mapping; - } - - /** - * Validates & completes a many-to-many association mapping. - * - * @param array $mapping The mapping to validate & complete. - * - * @return array The validated & completed mapping. - * - * @throws \InvalidArgumentException - */ - protected function _validateAndCompleteManyToManyMapping(array $mapping) - { - $mapping = $this->_validateAndCompleteAssociationMapping($mapping); - - if ($mapping['isOwningSide']) { - // owning side MUST have a join table - if ( ! isset($mapping['joinTable']['name'])) { - $mapping['joinTable']['name'] = $this->namingStrategy->joinTableName($mapping['sourceEntity'], $mapping['targetEntity'], $mapping['fieldName']); - } - - $selfReferencingEntityWithoutJoinColumns = $mapping['sourceEntity'] == $mapping['targetEntity'] - && (! (isset($mapping['joinTable']['joinColumns']) || isset($mapping['joinTable']['inverseJoinColumns']))); - - if ( ! isset($mapping['joinTable']['joinColumns'])) { - $mapping['joinTable']['joinColumns'] = [ - [ - 'name' => $this->namingStrategy->joinKeyColumnName($mapping['sourceEntity'], $selfReferencingEntityWithoutJoinColumns ? 'source' : null), - 'referencedColumnName' => $this->namingStrategy->referenceColumnName(), - 'onDelete' => 'CASCADE' - ] - ]; - } - - if ( ! isset($mapping['joinTable']['inverseJoinColumns'])) { - $mapping['joinTable']['inverseJoinColumns'] = [ - [ - 'name' => $this->namingStrategy->joinKeyColumnName($mapping['targetEntity'], $selfReferencingEntityWithoutJoinColumns ? 'target' : null), - 'referencedColumnName' => $this->namingStrategy->referenceColumnName(), - 'onDelete' => 'CASCADE' - ] - ]; - } - - $mapping['joinTableColumns'] = []; - - foreach ($mapping['joinTable']['joinColumns'] as &$joinColumn) { - if (empty($joinColumn['name'])) { - $joinColumn['name'] = $this->namingStrategy->joinKeyColumnName($mapping['sourceEntity'], $joinColumn['referencedColumnName']); - } - - if (empty($joinColumn['referencedColumnName'])) { - $joinColumn['referencedColumnName'] = $this->namingStrategy->referenceColumnName(); - } - - if ($joinColumn['name'][0] === '`') { - $joinColumn['name'] = trim($joinColumn['name'], '`'); - $joinColumn['quoted'] = true; - } - - if ($joinColumn['referencedColumnName'][0] === '`') { - $joinColumn['referencedColumnName'] = trim($joinColumn['referencedColumnName'], '`'); - $joinColumn['quoted'] = true; - } - - if (isset($joinColumn['onDelete']) && strtolower($joinColumn['onDelete']) == 'cascade') { - $mapping['isOnDeleteCascade'] = true; - } - - $mapping['relationToSourceKeyColumns'][$joinColumn['name']] = $joinColumn['referencedColumnName']; - $mapping['joinTableColumns'][] = $joinColumn['name']; - } - - foreach ($mapping['joinTable']['inverseJoinColumns'] as &$inverseJoinColumn) { - if (empty($inverseJoinColumn['name'])) { - $inverseJoinColumn['name'] = $this->namingStrategy->joinKeyColumnName($mapping['targetEntity'], $inverseJoinColumn['referencedColumnName']); - } - - if (empty($inverseJoinColumn['referencedColumnName'])) { - $inverseJoinColumn['referencedColumnName'] = $this->namingStrategy->referenceColumnName(); - } - - if ($inverseJoinColumn['name'][0] === '`') { - $inverseJoinColumn['name'] = trim($inverseJoinColumn['name'], '`'); - $inverseJoinColumn['quoted'] = true; - } - - if ($inverseJoinColumn['referencedColumnName'][0] === '`') { - $inverseJoinColumn['referencedColumnName'] = trim($inverseJoinColumn['referencedColumnName'], '`'); - $inverseJoinColumn['quoted'] = true; - } - - if (isset($inverseJoinColumn['onDelete']) && strtolower($inverseJoinColumn['onDelete']) == 'cascade') { - $mapping['isOnDeleteCascade'] = true; - } - - $mapping['relationToTargetKeyColumns'][$inverseJoinColumn['name']] = $inverseJoinColumn['referencedColumnName']; - $mapping['joinTableColumns'][] = $inverseJoinColumn['name']; - } - } - - $mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) && $mapping['orphanRemoval']; - - $this->assertMappingOrderBy($mapping); - - return $mapping; - } - - /** - * {@inheritDoc} - */ - public function getIdentifierFieldNames() - { - return $this->identifier; - } - - /** - * Gets the name of the single id field. Note that this only works on - * entity classes that have a single-field pk. - * - * @return string - * - * @throws MappingException If the class doesn't have an identifier or it has a composite primary key. - */ - public function getSingleIdentifierFieldName() - { - if ($this->isIdentifierComposite) { - throw MappingException::singleIdNotAllowedOnCompositePrimaryKey($this->name); - } - - if ( ! isset($this->identifier[0])) { - throw MappingException::noIdDefined($this->name); - } - - return $this->identifier[0]; - } - - /** - * Gets the column name of the single id column. Note that this only works on - * entity classes that have a single-field pk. - * - * @return string - * - * @throws MappingException If the class doesn't have an identifier or it has a composite primary key. - */ - public function getSingleIdentifierColumnName() - { - return $this->getColumnName($this->getSingleIdentifierFieldName()); - } - - /** - * INTERNAL: - * Sets the mapped identifier/primary key fields of this class. - * Mainly used by the ClassMetadataFactory to assign inherited identifiers. - * - * @param array $identifier - * - * @return void - */ - public function setIdentifier(array $identifier) - { - $this->identifier = $identifier; - $this->isIdentifierComposite = (count($this->identifier) > 1); - } - - /** - * {@inheritDoc} - */ - public function getIdentifier() - { - return $this->identifier; - } - - /** - * {@inheritDoc} - */ - public function hasField($fieldName) - { - return isset($this->fieldMappings[$fieldName]) || isset($this->embeddedClasses[$fieldName]); - } - - /** - * Gets an array containing all the column names. - * - * @param array|null $fieldNames - * - * @return array - */ - public function getColumnNames(array $fieldNames = null) - { - if (null === $fieldNames) { - return array_keys($this->fieldNames); - } - - return array_values(array_map([$this, 'getColumnName'], $fieldNames)); - } - - /** - * Returns an array with all the identifier column names. - * - * @return array - */ - public function getIdentifierColumnNames() - { - $columnNames = []; - - foreach ($this->identifier as $idProperty) { - if (isset($this->fieldMappings[$idProperty])) { - $columnNames[] = $this->fieldMappings[$idProperty]['columnName']; - - continue; - } - - // Association defined as Id field - $joinColumns = $this->associationMappings[$idProperty]['joinColumns']; - $assocColumnNames = array_map(function ($joinColumn) { return $joinColumn['name']; }, $joinColumns); - - $columnNames = array_merge($columnNames, $assocColumnNames); - } - - return $columnNames; - } - - /** - * Sets the type of Id generator to use for the mapped class. - * - * @param int $generatorType - * - * @return void - */ - public function setIdGeneratorType($generatorType) - { - $this->generatorType = $generatorType; - } - - /** - * Checks whether the mapped class uses an Id generator. - * - * @return boolean TRUE if the mapped class uses an Id generator, FALSE otherwise. - */ - public function usesIdGenerator() - { - return $this->generatorType != self::GENERATOR_TYPE_NONE; - } - - /** - * @return boolean - */ - public function isInheritanceTypeNone() - { - return $this->inheritanceType == self::INHERITANCE_TYPE_NONE; - } - - /** - * Checks whether the mapped class uses the JOINED inheritance mapping strategy. - * - * @return boolean TRUE if the class participates in a JOINED inheritance mapping, - * FALSE otherwise. - */ - public function isInheritanceTypeJoined() - { - return $this->inheritanceType == self::INHERITANCE_TYPE_JOINED; - } - - /** - * Checks whether the mapped class uses the SINGLE_TABLE inheritance mapping strategy. - * - * @return boolean TRUE if the class participates in a SINGLE_TABLE inheritance mapping, - * FALSE otherwise. - */ - public function isInheritanceTypeSingleTable() - { - return $this->inheritanceType == self::INHERITANCE_TYPE_SINGLE_TABLE; - } - - /** - * Checks whether the mapped class uses the TABLE_PER_CLASS inheritance mapping strategy. - * - * @return boolean TRUE if the class participates in a TABLE_PER_CLASS inheritance mapping, - * FALSE otherwise. - */ - public function isInheritanceTypeTablePerClass() - { - return $this->inheritanceType == self::INHERITANCE_TYPE_TABLE_PER_CLASS; - } - - /** - * Checks whether the class uses an identity column for the Id generation. - * - * @return boolean TRUE if the class uses the IDENTITY generator, FALSE otherwise. - */ - public function isIdGeneratorIdentity() - { - return $this->generatorType == self::GENERATOR_TYPE_IDENTITY; - } - - /** - * Checks whether the class uses a sequence for id generation. - * - * @return boolean TRUE if the class uses the SEQUENCE generator, FALSE otherwise. - */ - public function isIdGeneratorSequence() - { - return $this->generatorType == self::GENERATOR_TYPE_SEQUENCE; - } - - /** - * Checks whether the class uses a table for id generation. - * - * @return boolean TRUE if the class uses the TABLE generator, FALSE otherwise. - */ - public function isIdGeneratorTable() - { - return $this->generatorType == self::GENERATOR_TYPE_TABLE; - } - - /** - * Checks whether the class has a natural identifier/pk (which means it does - * not use any Id generator. - * - * @return boolean - */ - public function isIdentifierNatural() - { - return $this->generatorType == self::GENERATOR_TYPE_NONE; - } - - /** - * Checks whether the class use a UUID for id generation. - * - * @return boolean - */ - public function isIdentifierUuid() - { - return $this->generatorType == self::GENERATOR_TYPE_UUID; - } - - /** - * Gets the type of a field. - * - * @param string $fieldName - * - * @return string|null - * - * @todo 3.0 Remove this. PersisterHelper should fix it somehow - */ - public function getTypeOfField($fieldName) - { - return isset($this->fieldMappings[$fieldName]) - ? $this->fieldMappings[$fieldName]['type'] - : null; - } - - /** - * Gets the type of a column. - * - * @param string $columnName - * - * @return string|null - * - * @deprecated 3.0 remove this. this method is bogus and unreliable, since it cannot resolve the type of a column - * that is derived by a referenced field on a different entity. - */ - public function getTypeOfColumn($columnName) - { - return $this->getTypeOfField($this->getFieldName($columnName)); - } - - /** - * Gets the name of the primary table. - * - * @return string - */ - public function getTableName() - { - return $this->table['name']; - } - - /** - * Gets primary table's schema name. - * - * @return string|null - */ - public function getSchemaName() - { - return isset($this->table['schema']) ? $this->table['schema'] : null; - } - - /** - * Gets the table name to use for temporary identifier tables of this class. - * - * @return string - */ - public function getTemporaryIdTableName() - { - // replace dots with underscores because PostgreSQL creates temporary tables in a special schema - return str_replace('.', '_', $this->getTableName() . '_id_tmp'); - } - - /** - * Sets the mapped subclasses of this class. - * - * @param array $subclasses The names of all mapped subclasses. - * - * @return void - */ - public function setSubclasses(array $subclasses) - { - foreach ($subclasses as $subclass) { - $this->subClasses[] = $this->fullyQualifiedClassName($subclass); - } - } - - /** - * Sets the parent class names. - * Assumes that the class names in the passed array are in the order: - * directParent -> directParentParent -> directParentParentParent ... -> root. - * - * @param array $classNames - * - * @return void - */ - public function setParentClasses(array $classNames) - { - $this->parentClasses = $classNames; - - if (count($classNames) > 0) { - $this->rootEntityName = array_pop($classNames); - } - } - - /** - * Sets the inheritance type used by the class and its subclasses. - * - * @param integer $type - * - * @return void - * - * @throws MappingException - */ - public function setInheritanceType($type) - { - if ( ! $this->_isInheritanceType($type)) { - throw MappingException::invalidInheritanceType($this->name, $type); - } - - $this->inheritanceType = $type; - } - - /** - * Sets the association to override association mapping of property for an entity relationship. - * - * @param string $fieldName - * @param array $overrideMapping - * - * @return void - * - * @throws MappingException - */ - public function setAssociationOverride($fieldName, array $overrideMapping) - { - if ( ! isset($this->associationMappings[$fieldName])) { - throw MappingException::invalidOverrideFieldName($this->name, $fieldName); - } - - $mapping = $this->associationMappings[$fieldName]; - - if (isset($overrideMapping['joinColumns'])) { - $mapping['joinColumns'] = $overrideMapping['joinColumns']; - } - - if (isset($overrideMapping['inversedBy'])) { - $mapping['inversedBy'] = $overrideMapping['inversedBy']; - } - - if (isset($overrideMapping['joinTable'])) { - $mapping['joinTable'] = $overrideMapping['joinTable']; - } - - if (isset($overrideMapping['fetch'])) { - $mapping['fetch'] = $overrideMapping['fetch']; - } - - $mapping['joinColumnFieldNames'] = null; - $mapping['joinTableColumns'] = null; - $mapping['sourceToTargetKeyColumns'] = null; - $mapping['relationToSourceKeyColumns'] = null; - $mapping['relationToTargetKeyColumns'] = null; - - switch ($mapping['type']) { - case self::ONE_TO_ONE: - $mapping = $this->_validateAndCompleteOneToOneMapping($mapping); - break; - case self::ONE_TO_MANY: - $mapping = $this->_validateAndCompleteOneToManyMapping($mapping); - break; - case self::MANY_TO_ONE: - $mapping = $this->_validateAndCompleteOneToOneMapping($mapping); - break; - case self::MANY_TO_MANY: - $mapping = $this->_validateAndCompleteManyToManyMapping($mapping); - break; - } - - $this->associationMappings[$fieldName] = $mapping; - } - - /** - * Sets the override for a mapped field. - * - * @param string $fieldName - * @param array $overrideMapping - * - * @return void - * - * @throws MappingException - */ - public function setAttributeOverride($fieldName, array $overrideMapping) - { - if ( ! isset($this->fieldMappings[$fieldName])) { - throw MappingException::invalidOverrideFieldName($this->name, $fieldName); - } - - $mapping = $this->fieldMappings[$fieldName]; - - if (isset($mapping['id'])) { - $overrideMapping['id'] = $mapping['id']; - } - - if ( ! isset($overrideMapping['type'])) { - $overrideMapping['type'] = $mapping['type']; - } - - if ( ! isset($overrideMapping['fieldName'])) { - $overrideMapping['fieldName'] = $mapping['fieldName']; - } - - if ($overrideMapping['type'] !== $mapping['type']) { - throw MappingException::invalidOverrideFieldType($this->name, $fieldName); - } - - unset($this->fieldMappings[$fieldName]); - unset($this->fieldNames[$mapping['columnName']]); - unset($this->columnNames[$mapping['fieldName']]); - - $this->_validateAndCompleteFieldMapping($overrideMapping); - - $this->fieldMappings[$fieldName] = $overrideMapping; - } - - /** - * Checks whether a mapped field is inherited from an entity superclass. - * - * @param string $fieldName - * - * @return bool TRUE if the field is inherited, FALSE otherwise. - */ - public function isInheritedField($fieldName) - { - return isset($this->fieldMappings[$fieldName]['inherited']); - } - - /** - * Checks if this entity is the root in any entity-inheritance-hierarchy. - * - * @return bool - */ - public function isRootEntity() - { - return $this->name == $this->rootEntityName; - } - - /** - * Checks whether a mapped association field is inherited from a superclass. - * - * @param string $fieldName - * - * @return boolean TRUE if the field is inherited, FALSE otherwise. - */ - public function isInheritedAssociation($fieldName) - { - return isset($this->associationMappings[$fieldName]['inherited']); - } - - public function isInheritedEmbeddedClass($fieldName) - { - return isset($this->embeddedClasses[$fieldName]['inherited']); - } - - /** - * Sets the name of the primary table the class is mapped to. - * - * @param string $tableName The table name. - * - * @return void - * - * @deprecated Use {@link setPrimaryTable}. - */ - public function setTableName($tableName) - { - $this->table['name'] = $tableName; - } - - /** - * Sets the primary table definition. The provided array supports the - * following structure: - * - * name => (optional, defaults to class name) - * indexes => array of indexes (optional) - * uniqueConstraints => array of constraints (optional) - * - * If a key is omitted, the current value is kept. - * - * @param array $table The table description. - * - * @return void - */ - public function setPrimaryTable(array $table) - { - if (isset($table['name'])) { - // Split schema and table name from a table name like "myschema.mytable" - if (strpos($table['name'], '.') !== false) { - list($this->table['schema'], $table['name']) = explode('.', $table['name'], 2); - } - - if ($table['name'][0] === '`') { - $table['name'] = trim($table['name'], '`'); - $this->table['quoted'] = true; - } - - $this->table['name'] = $table['name']; - } - - if (isset($table['quoted'])) { - $this->table['quoted'] = $table['quoted']; - } - - if (isset($table['schema'])) { - $this->table['schema'] = $table['schema']; - } - - if (isset($table['indexes'])) { - $this->table['indexes'] = $table['indexes']; - } - - if (isset($table['uniqueConstraints'])) { - $this->table['uniqueConstraints'] = $table['uniqueConstraints']; - } - - if (isset($table['options'])) { - $this->table['options'] = $table['options']; - } - } - - /** - * Checks whether the given type identifies an inheritance type. - * - * @param integer $type - * - * @return boolean TRUE if the given type identifies an inheritance type, FALSe otherwise. - */ - private function _isInheritanceType($type) - { - return $type == self::INHERITANCE_TYPE_NONE || - $type == self::INHERITANCE_TYPE_SINGLE_TABLE || - $type == self::INHERITANCE_TYPE_JOINED || - $type == self::INHERITANCE_TYPE_TABLE_PER_CLASS; - } - - /** - * Adds a mapped field to the class. - * - * @param array $mapping The field mapping. - * - * @return void - * - * @throws MappingException - */ - public function mapField(array $mapping) - { - $this->_validateAndCompleteFieldMapping($mapping); - $this->assertFieldNotMapped($mapping['fieldName']); - - $this->fieldMappings[$mapping['fieldName']] = $mapping; - } - - /** - * INTERNAL: - * Adds an association mapping without completing/validating it. - * This is mainly used to add inherited association mappings to derived classes. - * - * @param array $mapping - * - * @return void - * - * @throws MappingException - */ - public function addInheritedAssociationMapping(array $mapping/*, $owningClassName = null*/) - { - if (isset($this->associationMappings[$mapping['fieldName']])) { - throw MappingException::duplicateAssociationMapping($this->name, $mapping['fieldName']); - } - $this->associationMappings[$mapping['fieldName']] = $mapping; - } - - /** - * INTERNAL: - * Adds a field mapping without completing/validating it. - * This is mainly used to add inherited field mappings to derived classes. - * - * @param array $fieldMapping - * - * @return void - */ - public function addInheritedFieldMapping(array $fieldMapping) - { - $this->fieldMappings[$fieldMapping['fieldName']] = $fieldMapping; - $this->columnNames[$fieldMapping['fieldName']] = $fieldMapping['columnName']; - $this->fieldNames[$fieldMapping['columnName']] = $fieldMapping['fieldName']; - } - - /** - * INTERNAL: - * Adds a named query to this class. - * - * @param array $queryMapping - * - * @return void - * - * @throws MappingException - */ - public function addNamedQuery(array $queryMapping) - { - if (!isset($queryMapping['name'])) { - throw MappingException::nameIsMandatoryForQueryMapping($this->name); - } - - if (isset($this->namedQueries[$queryMapping['name']])) { - throw MappingException::duplicateQueryMapping($this->name, $queryMapping['name']); - } - - if (!isset($queryMapping['query'])) { - throw MappingException::emptyQueryMapping($this->name, $queryMapping['name']); - } - - $name = $queryMapping['name']; - $query = $queryMapping['query']; - $dql = str_replace('__CLASS__', $this->name, $query); - - $this->namedQueries[$name] = [ - 'name' => $name, - 'query' => $query, - 'dql' => $dql, - ]; - } - - /** - * INTERNAL: - * Adds a named native query to this class. - * - * @param array $queryMapping - * - * @return void - * - * @throws MappingException - */ - public function addNamedNativeQuery(array $queryMapping) - { - if (!isset($queryMapping['name'])) { - throw MappingException::nameIsMandatoryForQueryMapping($this->name); - } - - if (isset($this->namedNativeQueries[$queryMapping['name']])) { - throw MappingException::duplicateQueryMapping($this->name, $queryMapping['name']); - } - - if (!isset($queryMapping['query'])) { - throw MappingException::emptyQueryMapping($this->name, $queryMapping['name']); - } - - if (!isset($queryMapping['resultClass']) && !isset($queryMapping['resultSetMapping'])) { - throw MappingException::missingQueryMapping($this->name, $queryMapping['name']); - } - - $queryMapping['isSelfClass'] = false; - - if (isset($queryMapping['resultClass'])) { - if ($queryMapping['resultClass'] === '__CLASS__') { - - $queryMapping['isSelfClass'] = true; - $queryMapping['resultClass'] = $this->name; - } - - $queryMapping['resultClass'] = $this->fullyQualifiedClassName($queryMapping['resultClass']); - $queryMapping['resultClass'] = ltrim($queryMapping['resultClass'], '\\'); - } - - $this->namedNativeQueries[$queryMapping['name']] = $queryMapping; - } - - /** - * INTERNAL: - * Adds a sql result set mapping to this class. - * - * @param array $resultMapping - * - * @return void - * - * @throws MappingException - */ - public function addSqlResultSetMapping(array $resultMapping) - { - if (!isset($resultMapping['name'])) { - throw MappingException::nameIsMandatoryForSqlResultSetMapping($this->name); - } - - if (isset($this->sqlResultSetMappings[$resultMapping['name']])) { - throw MappingException::duplicateResultSetMapping($this->name, $resultMapping['name']); - } - - if (isset($resultMapping['entities'])) { - foreach ($resultMapping['entities'] as $key => $entityResult) { - if (!isset($entityResult['entityClass'])) { - throw MappingException::missingResultSetMappingEntity($this->name, $resultMapping['name']); - } - - $entityResult['isSelfClass'] = false; - if ($entityResult['entityClass'] === '__CLASS__') { - - $entityResult['isSelfClass'] = true; - $entityResult['entityClass'] = $this->name; - - } - - $entityResult['entityClass'] = $this->fullyQualifiedClassName($entityResult['entityClass']); - - $resultMapping['entities'][$key]['entityClass'] = ltrim($entityResult['entityClass'], '\\'); - $resultMapping['entities'][$key]['isSelfClass'] = $entityResult['isSelfClass']; - - if (isset($entityResult['fields'])) { - foreach ($entityResult['fields'] as $k => $field) { - if (!isset($field['name'])) { - throw MappingException::missingResultSetMappingFieldName($this->name, $resultMapping['name']); - } - - if (!isset($field['column'])) { - $fieldName = $field['name']; - if (strpos($fieldName, '.')) { - list(, $fieldName) = explode('.', $fieldName); - } - - $resultMapping['entities'][$key]['fields'][$k]['column'] = $fieldName; - } - } - } - } - } - - $this->sqlResultSetMappings[$resultMapping['name']] = $resultMapping; - } - - /** - * Adds a one-to-one mapping. - * - * @param array $mapping The mapping. - * - * @return void - */ - public function mapOneToOne(array $mapping) - { - $mapping['type'] = self::ONE_TO_ONE; - - $mapping = $this->_validateAndCompleteOneToOneMapping($mapping); - - $this->_storeAssociationMapping($mapping); - } - - /** - * Adds a one-to-many mapping. - * - * @param array $mapping The mapping. - * - * @return void - */ - public function mapOneToMany(array $mapping) - { - $mapping['type'] = self::ONE_TO_MANY; - - $mapping = $this->_validateAndCompleteOneToManyMapping($mapping); - - $this->_storeAssociationMapping($mapping); - } - - /** - * Adds a many-to-one mapping. - * - * @param array $mapping The mapping. - * - * @return void - */ - public function mapManyToOne(array $mapping) - { - $mapping['type'] = self::MANY_TO_ONE; - - // A many-to-one mapping is essentially a one-one backreference - $mapping = $this->_validateAndCompleteOneToOneMapping($mapping); - - $this->_storeAssociationMapping($mapping); - } - - /** - * Adds a many-to-many mapping. - * - * @param array $mapping The mapping. - * - * @return void - */ - public function mapManyToMany(array $mapping) - { - $mapping['type'] = self::MANY_TO_MANY; - - $mapping = $this->_validateAndCompleteManyToManyMapping($mapping); - - $this->_storeAssociationMapping($mapping); - } - - /** - * Stores the association mapping. - * - * @param array $assocMapping - * - * @return void - * - * @throws MappingException - */ - protected function _storeAssociationMapping(array $assocMapping) - { - $sourceFieldName = $assocMapping['fieldName']; - - $this->assertFieldNotMapped($sourceFieldName); - - $this->associationMappings[$sourceFieldName] = $assocMapping; - } - - /** - * Registers a custom repository class for the entity class. - * - * @param string $repositoryClassName The class name of the custom mapper. - * - * @return void - */ - public function setCustomRepositoryClass($repositoryClassName) - { - $this->customRepositoryClassName = $this->fullyQualifiedClassName($repositoryClassName); - } - - /** - * Dispatches the lifecycle event of the given entity to the registered - * lifecycle callbacks and lifecycle listeners. - * - * @deprecated Deprecated since version 2.4 in favor of \Doctrine\ORM\Event\ListenersInvoker - * - * @param string $lifecycleEvent The lifecycle event. - * @param object $entity The Entity on which the event occurred. - * - * @return void - */ - public function invokeLifecycleCallbacks($lifecycleEvent, $entity) - { - foreach ($this->lifecycleCallbacks[$lifecycleEvent] as $callback) { - $entity->$callback(); - } - } - - /** - * Whether the class has any attached lifecycle listeners or callbacks for a lifecycle event. - * - * @param string $lifecycleEvent - * - * @return boolean - */ - public function hasLifecycleCallbacks($lifecycleEvent) - { - return isset($this->lifecycleCallbacks[$lifecycleEvent]); - } - - /** - * Gets the registered lifecycle callbacks for an event. - * - * @param string $event - * - * @return array - */ - public function getLifecycleCallbacks($event) - { - return isset($this->lifecycleCallbacks[$event]) ? $this->lifecycleCallbacks[$event] : []; - } - - /** - * Adds a lifecycle callback for entities of this class. - * - * @param string $callback - * @param string $event - * - * @return void - */ - public function addLifecycleCallback($callback, $event) - { - if (isset($this->lifecycleCallbacks[$event]) && in_array($callback, $this->lifecycleCallbacks[$event])) { - return; - } - - $this->lifecycleCallbacks[$event][] = $callback; - } - - /** - * Sets the lifecycle callbacks for entities of this class. - * Any previously registered callbacks are overwritten. - * - * @param array $callbacks - * - * @return void - */ - public function setLifecycleCallbacks(array $callbacks) - { - $this->lifecycleCallbacks = $callbacks; - } - - /** - * Adds a entity listener for entities of this class. - * - * @param string $eventName The entity lifecycle event. - * @param string $class The listener class. - * @param string $method The listener callback method. - * - * @throws \Doctrine\ORM\Mapping\MappingException - */ - public function addEntityListener($eventName, $class, $method) - { - $class = $this->fullyQualifiedClassName($class); - - $listener = [ - 'class' => $class, - 'method' => $method, - ]; - - if ( ! class_exists($class)) { - throw MappingException::entityListenerClassNotFound($class, $this->name); - } - - if ( ! method_exists($class, $method)) { - throw MappingException::entityListenerMethodNotFound($class, $method, $this->name); - } - - if (isset($this->entityListeners[$eventName]) && in_array($listener, $this->entityListeners[$eventName])) { - throw MappingException::duplicateEntityListener($class, $method, $this->name); - } - - $this->entityListeners[$eventName][] = $listener; - } - - /** - * Sets the discriminator column definition. - * - * @param array $columnDef - * - * @return void - * - * @throws MappingException - * - * @see getDiscriminatorColumn() - */ - public function setDiscriminatorColumn($columnDef) - { - if ($columnDef !== null) { - if ( ! isset($columnDef['name'])) { - throw MappingException::nameIsMandatoryForDiscriminatorColumns($this->name); - } - - if (isset($this->fieldNames[$columnDef['name']])) { - throw MappingException::duplicateColumnName($this->name, $columnDef['name']); - } - - if ( ! isset($columnDef['fieldName'])) { - $columnDef['fieldName'] = $columnDef['name']; - } - - if ( ! isset($columnDef['type'])) { - $columnDef['type'] = "string"; - } - - if (in_array($columnDef['type'], ["boolean", "array", "object", "datetime", "time", "date"])) { - throw MappingException::invalidDiscriminatorColumnType($this->name, $columnDef['type']); - } - - $this->discriminatorColumn = $columnDef; - } - } - - /** - * Sets the discriminator values used by this class. - * Used for JOINED and SINGLE_TABLE inheritance mapping strategies. - * - * @param array $map - * - * @return void - */ - public function setDiscriminatorMap(array $map) - { - foreach ($map as $value => $className) { - $this->addDiscriminatorMapClass($value, $className); - } - } - - /** - * Adds one entry of the discriminator map with a new class and corresponding name. - * - * @param string $name - * @param string $className - * - * @return void - * - * @throws MappingException - */ - public function addDiscriminatorMapClass($name, $className) - { - $className = $this->fullyQualifiedClassName($className); - $className = ltrim($className, '\\'); - - $this->discriminatorMap[$name] = $className; - - if ($this->name === $className) { - $this->discriminatorValue = $name; - - return; - } - - if ( ! (class_exists($className) || interface_exists($className))) { - throw MappingException::invalidClassInDiscriminatorMap($className, $this->name); - } - - if (is_subclass_of($className, $this->name) && ! in_array($className, $this->subClasses)) { - $this->subClasses[] = $className; - } - } - - /** - * Checks whether the class has a named query with the given query name. - * - * @param string $queryName - * - * @return boolean - */ - public function hasNamedQuery($queryName) - { - return isset($this->namedQueries[$queryName]); - } - - /** - * Checks whether the class has a named native query with the given query name. - * - * @param string $queryName - * - * @return boolean - */ - public function hasNamedNativeQuery($queryName) - { - return isset($this->namedNativeQueries[$queryName]); - } - - /** - * Checks whether the class has a named native query with the given query name. - * - * @param string $name - * - * @return boolean - */ - public function hasSqlResultSetMapping($name) - { - return isset($this->sqlResultSetMappings[$name]); - } - - /** - * {@inheritDoc} - */ - public function hasAssociation($fieldName) - { - return isset($this->associationMappings[$fieldName]); - } - - /** - * {@inheritDoc} - */ - public function isSingleValuedAssociation($fieldName) - { - return isset($this->associationMappings[$fieldName]) - && ($this->associationMappings[$fieldName]['type'] & self::TO_ONE); - } - - /** - * {@inheritDoc} - */ - public function isCollectionValuedAssociation($fieldName) - { - return isset($this->associationMappings[$fieldName]) - && ! ($this->associationMappings[$fieldName]['type'] & self::TO_ONE); - } - - /** - * Is this an association that only has a single join column? - * - * @param string $fieldName - * - * @return bool - */ - public function isAssociationWithSingleJoinColumn($fieldName) - { - return isset($this->associationMappings[$fieldName]) - && isset($this->associationMappings[$fieldName]['joinColumns'][0]) - && ! isset($this->associationMappings[$fieldName]['joinColumns'][1]); - } - - /** - * Returns the single association join column (if any). - * - * @param string $fieldName - * - * @return string - * - * @throws MappingException - */ - public function getSingleAssociationJoinColumnName($fieldName) - { - if ( ! $this->isAssociationWithSingleJoinColumn($fieldName)) { - throw MappingException::noSingleAssociationJoinColumnFound($this->name, $fieldName); - } - - return $this->associationMappings[$fieldName]['joinColumns'][0]['name']; - } - - /** - * Returns the single association referenced join column name (if any). - * - * @param string $fieldName - * - * @return string - * - * @throws MappingException - */ - public function getSingleAssociationReferencedJoinColumnName($fieldName) - { - if ( ! $this->isAssociationWithSingleJoinColumn($fieldName)) { - throw MappingException::noSingleAssociationJoinColumnFound($this->name, $fieldName); - } - - return $this->associationMappings[$fieldName]['joinColumns'][0]['referencedColumnName']; - } - - /** - * Used to retrieve a fieldname for either field or association from a given column. - * - * This method is used in foreign-key as primary-key contexts. - * - * @param string $columnName - * - * @return string - * - * @throws MappingException - */ - public function getFieldForColumn($columnName) - { - if (isset($this->fieldNames[$columnName])) { - return $this->fieldNames[$columnName]; - } - - foreach ($this->associationMappings as $assocName => $mapping) { - if ($this->isAssociationWithSingleJoinColumn($assocName) && - $this->associationMappings[$assocName]['joinColumns'][0]['name'] == $columnName) { - - return $assocName; - } - } - - throw MappingException::noFieldNameFoundForColumn($this->name, $columnName); - } - - /** - * Sets the ID generator used to generate IDs for instances of this class. - * - * @param \Doctrine\ORM\Id\AbstractIdGenerator $generator - * - * @return void - */ - public function setIdGenerator($generator) - { - $this->idGenerator = $generator; - } - - /** - * Sets definition. - * - * @param array $definition - * - * @return void - */ - public function setCustomGeneratorDefinition(array $definition) - { - $this->customGeneratorDefinition = $definition; - } - - /** - * Sets the definition of the sequence ID generator for this class. - * - * The definition must have the following structure: - * - * array( - * 'sequenceName' => 'name', - * 'allocationSize' => 20, - * 'initialValue' => 1 - * 'quoted' => 1 - * ) - * - * - * @param array $definition - * - * @return void - * - * @throws MappingException - */ - public function setSequenceGeneratorDefinition(array $definition) - { - if ( ! isset($definition['sequenceName']) || trim($definition['sequenceName']) === '') { - throw MappingException::missingSequenceName($this->name); - } - - if ($definition['sequenceName'][0] == '`') { - $definition['sequenceName'] = trim($definition['sequenceName'], '`'); - $definition['quoted'] = true; - } - - if ( ! isset($definition['allocationSize']) || trim($definition['allocationSize']) === '') { - $definition['allocationSize'] = '1'; - } - - if ( ! isset($definition['initialValue']) || trim($definition['initialValue']) === '') { - $definition['initialValue'] = '1'; - } - - $this->sequenceGeneratorDefinition = $definition; - } - - /** - * Sets the version field mapping used for versioning. Sets the default - * value to use depending on the column type. - * - * @param array $mapping The version field mapping array. - * - * @return void - * - * @throws MappingException - */ - public function setVersionMapping(array &$mapping) - { - $this->isVersioned = true; - $this->versionField = $mapping['fieldName']; - - if ( ! isset($mapping['default'])) { - if (in_array($mapping['type'], ['integer', 'bigint', 'smallint'])) { - $mapping['default'] = 1; - } else if ($mapping['type'] == 'datetime') { - $mapping['default'] = 'CURRENT_TIMESTAMP'; - } else { - throw MappingException::unsupportedOptimisticLockingType($this->name, $mapping['fieldName'], $mapping['type']); - } - } - } - - /** - * Sets whether this class is to be versioned for optimistic locking. - * - * @param boolean $bool - * - * @return void - */ - public function setVersioned($bool) - { - $this->isVersioned = $bool; - } - - /** - * Sets the name of the field that is to be used for versioning if this class is - * versioned for optimistic locking. - * - * @param string $versionField - * - * @return void - */ - public function setVersionField($versionField) - { - $this->versionField = $versionField; - } - - /** - * Marks this class as read only, no change tracking is applied to it. - * - * @return void - */ - public function markReadOnly() - { - $this->isReadOnly = true; - } - - /** - * {@inheritDoc} - */ - public function getFieldNames() - { - return array_keys($this->fieldMappings); - } - - /** - * {@inheritDoc} - */ - public function getAssociationNames() - { - return array_keys($this->associationMappings); - } - - /** - * {@inheritDoc} - * - * @throws InvalidArgumentException - */ - public function getAssociationTargetClass($assocName) - { - if ( ! isset($this->associationMappings[$assocName])) { - throw new InvalidArgumentException("Association name expected, '" . $assocName ."' is not an association."); - } - - return $this->associationMappings[$assocName]['targetEntity']; - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return $this->name; - } - - /** - * Gets the (possibly quoted) identifier column names for safe use in an SQL statement. - * - * @deprecated Deprecated since version 2.3 in favor of \Doctrine\ORM\Mapping\QuoteStrategy - * - * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform - * - * @return array - */ - public function getQuotedIdentifierColumnNames($platform) - { - $quotedColumnNames = []; - - foreach ($this->identifier as $idProperty) { - if (isset($this->fieldMappings[$idProperty])) { - $quotedColumnNames[] = isset($this->fieldMappings[$idProperty]['quoted']) - ? $platform->quoteIdentifier($this->fieldMappings[$idProperty]['columnName']) - : $this->fieldMappings[$idProperty]['columnName']; - - continue; - } - - // Association defined as Id field - $joinColumns = $this->associationMappings[$idProperty]['joinColumns']; - $assocQuotedColumnNames = array_map( - function ($joinColumn) use ($platform) { - return isset($joinColumn['quoted']) - ? $platform->quoteIdentifier($joinColumn['name']) - : $joinColumn['name']; - }, - $joinColumns - ); - - $quotedColumnNames = array_merge($quotedColumnNames, $assocQuotedColumnNames); - } - - return $quotedColumnNames; - } - - /** - * Gets the (possibly quoted) column name of a mapped field for safe use in an SQL statement. - * - * @deprecated Deprecated since version 2.3 in favor of \Doctrine\ORM\Mapping\QuoteStrategy - * - * @param string $field - * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform - * - * @return string - */ - public function getQuotedColumnName($field, $platform) - { - return isset($this->fieldMappings[$field]['quoted']) - ? $platform->quoteIdentifier($this->fieldMappings[$field]['columnName']) - : $this->fieldMappings[$field]['columnName']; - } - - /** - * Gets the (possibly quoted) primary table name of this class for safe use in an SQL statement. - * - * @deprecated Deprecated since version 2.3 in favor of \Doctrine\ORM\Mapping\QuoteStrategy - * - * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform - * - * @return string - */ - public function getQuotedTableName($platform) - { - return isset($this->table['quoted']) - ? $platform->quoteIdentifier($this->table['name']) - : $this->table['name']; - } - - /** - * Gets the (possibly quoted) name of the join table. - * - * @deprecated Deprecated since version 2.3 in favor of \Doctrine\ORM\Mapping\QuoteStrategy - * - * @param array $assoc - * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform - * - * @return string - */ - public function getQuotedJoinTableName(array $assoc, $platform) - { - return isset($assoc['joinTable']['quoted']) - ? $platform->quoteIdentifier($assoc['joinTable']['name']) - : $assoc['joinTable']['name']; - } - - /** - * {@inheritDoc} - */ - public function isAssociationInverseSide($fieldName) - { - return isset($this->associationMappings[$fieldName]) - && ! $this->associationMappings[$fieldName]['isOwningSide']; - } - - /** - * {@inheritDoc} - */ - public function getAssociationMappedByTargetField($fieldName) - { - return $this->associationMappings[$fieldName]['mappedBy']; - } - - /** - * @param string $targetClass - * - * @return array - */ - public function getAssociationsByTargetClass($targetClass) - { - $relations = []; - - foreach ($this->associationMappings as $mapping) { - if ($mapping['targetEntity'] == $targetClass) { - $relations[$mapping['fieldName']] = $mapping; - } - } - - return $relations; - } - - /** - * @param string|null $className - * - * @return string|null null if the input value is null - */ - public function fullyQualifiedClassName($className) - { - if (empty($className)) { - return $className; - } - - if ($className !== null && strpos($className, '\\') === false && $this->namespace) { - return $this->namespace . '\\' . $className; - } - - return $className; - } - - /** - * @param string $name - * - * @return mixed - */ - public function getMetadataValue($name) - { - - if (isset($this->$name)) { - return $this->$name; - } - - return null; - } - - /** - * Map Embedded Class - * - * @param array $mapping - * - * @throws MappingException - * @return void - */ - public function mapEmbedded(array $mapping) - { - $this->assertFieldNotMapped($mapping['fieldName']); - - $this->embeddedClasses[$mapping['fieldName']] = [ - 'class' => $this->fullyQualifiedClassName($mapping['class']), - 'columnPrefix' => $mapping['columnPrefix'], - 'declaredField' => $mapping['declaredField'] ?? null, - 'originalField' => $mapping['originalField'] ?? null, - ]; - } - - /** - * Inline the embeddable class - * - * @param string $property - * @param ClassMetadataInfo $embeddable - */ - public function inlineEmbeddable($property, ClassMetadataInfo $embeddable) - { - foreach ($embeddable->fieldMappings as $fieldMapping) { - $fieldMapping['originalClass'] = $fieldMapping['originalClass'] ?? $embeddable->name; - $fieldMapping['declaredField'] = isset($fieldMapping['declaredField']) - ? $property . '.' . $fieldMapping['declaredField'] - : $property; - $fieldMapping['originalField'] = $fieldMapping['originalField'] ?? $fieldMapping['fieldName']; - $fieldMapping['fieldName'] = $property . "." . $fieldMapping['fieldName']; - - if (! empty($this->embeddedClasses[$property]['columnPrefix'])) { - $fieldMapping['columnName'] = $this->embeddedClasses[$property]['columnPrefix'] . $fieldMapping['columnName']; - } elseif ($this->embeddedClasses[$property]['columnPrefix'] !== false) { - $fieldMapping['columnName'] = $this->namingStrategy - ->embeddedFieldToColumnName( - $property, - $fieldMapping['columnName'], - $this->reflClass->name, - $embeddable->reflClass->name - ); - } - - $this->mapField($fieldMapping); - } - } - - /** - * @param string $fieldName - * @throws MappingException - */ - private function assertFieldNotMapped($fieldName) - { - if (isset($this->fieldMappings[$fieldName]) || - isset($this->associationMappings[$fieldName]) || - isset($this->embeddedClasses[$fieldName])) { - - throw MappingException::duplicateFieldMapping($this->name, $fieldName); - } - } - - /** - * Gets the sequence name based on class metadata. - * - * @param AbstractPlatform $platform - * @return string - * - * @todo Sequence names should be computed in DBAL depending on the platform - */ - public function getSequenceName(AbstractPlatform $platform) - { - $sequencePrefix = $this->getSequencePrefix($platform); - $columnName = $this->getSingleIdentifierColumnName(); - $sequenceName = $sequencePrefix . '_' . $columnName . '_seq'; - - return $sequenceName; - } - - /** - * Gets the sequence name prefix based on class metadata. - * - * @param AbstractPlatform $platform - * @return string - * - * @todo Sequence names should be computed in DBAL depending on the platform - */ - public function getSequencePrefix(AbstractPlatform $platform) - { - $tableName = $this->getTableName(); - $sequencePrefix = $tableName; - - // Prepend the schema name to the table name if there is one - if ($schemaName = $this->getSchemaName()) { - $sequencePrefix = $schemaName . '.' . $tableName; - - if ( ! $platform->supportsSchemas() && $platform->canEmulateSchemas()) { - $sequencePrefix = $schemaName . '__' . $tableName; - } - } - - return $sequencePrefix; - } - - /** - * @param array $mapping - */ - private function assertMappingOrderBy(array $mapping) - { - if (isset($mapping['orderBy']) && !is_array($mapping['orderBy'])) { - throw new InvalidArgumentException("'orderBy' is expected to be an array, not " . gettype($mapping['orderBy'])); - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Column.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Column.php deleted file mode 100644 index 711590b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Column.php +++ /dev/null @@ -1,76 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target({"PROPERTY","ANNOTATION"}) - */ -final class Column implements Annotation -{ - /** - * @var string - */ - public $name; - - /** - * @var mixed - */ - public $type = 'string'; - - /** - * @var integer - */ - public $length; - - /** - * The precision for a decimal (exact numeric) column (Applies only for decimal column). - * - * @var integer - */ - public $precision = 0; - - /** - * The scale for a decimal (exact numeric) column (Applies only for decimal column). - * - * @var integer - */ - public $scale = 0; - - /** - * @var boolean - */ - public $unique = false; - - /** - * @var boolean - */ - public $nullable = false; - - /** - * @var array - */ - public $options = []; - - /** - * @var string - */ - public $columnDefinition; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ColumnResult.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ColumnResult.php deleted file mode 100644 index a164c85..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ColumnResult.php +++ /dev/null @@ -1,40 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * References name of a column in the SELECT clause of a SQL query. - * Scalar result types can be included in the query result by specifying this annotation in the metadata. - * - * @author Fabio B. Silva - * @since 2.3 - * - * @Annotation - * @Target("ANNOTATION") - */ -final class ColumnResult implements Annotation -{ - /** - * The name of a column in the SELECT clause of a SQL query. - * - * @var string - */ - public $name; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/CustomIdGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/CustomIdGenerator.php deleted file mode 100644 index 41e200e..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/CustomIdGenerator.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("PROPERTY") - */ -final class CustomIdGenerator implements Annotation -{ - /** - * @var string - */ - public $class; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultEntityListenerResolver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultEntityListenerResolver.php deleted file mode 100644 index a8ee2dc..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultEntityListenerResolver.php +++ /dev/null @@ -1,75 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * The default DefaultEntityListener - * - * @since 2.4 - * @author Fabio B. Silva - */ -class DefaultEntityListenerResolver implements EntityListenerResolver -{ - /** - * @var array Map to store entity listener instances. - */ - private $instances = []; - - /** - * {@inheritdoc} - */ - public function clear($className = null) - { - if ($className === null) { - $this->instances = []; - - return; - } - - if (isset($this->instances[$className = trim($className, '\\')])) { - unset($this->instances[$className]); - } - } - - /** - * {@inheritdoc} - */ - public function register($object) - { - if ( ! is_object($object)) { - throw new \InvalidArgumentException(sprintf('An object was expected, but got "%s".', gettype($object))); - } - - $this->instances[get_class($object)] = $object; - } - - /** - * {@inheritdoc} - */ - public function resolve($className) - { - if (isset($this->instances[$className = trim($className, '\\')])) { - return $this->instances[$className]; - } - - return $this->instances[$className] = new $className(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultNamingStrategy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultNamingStrategy.php deleted file mode 100644 index ef7f76b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultNamingStrategy.php +++ /dev/null @@ -1,94 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * The default NamingStrategy - * - * - * @link www.doctrine-project.org - * @since 2.3 - * @author Fabio B. Silva - */ -class DefaultNamingStrategy implements NamingStrategy -{ - /** - * {@inheritdoc} - */ - public function classToTableName($className) - { - if (strpos($className, '\\') !== false) { - return substr($className, strrpos($className, '\\') + 1); - } - - return $className; - } - - /** - * {@inheritdoc} - */ - public function propertyToColumnName($propertyName, $className = null) - { - return $propertyName; - } - - /** - * {@inheritdoc} - */ - public function embeddedFieldToColumnName($propertyName, $embeddedColumnName, $className = null, $embeddedClassName = null) - { - return $propertyName.'_'.$embeddedColumnName; - } - - /** - * {@inheritdoc} - */ - public function referenceColumnName() - { - return 'id'; - } - - /** - * {@inheritdoc} - */ - public function joinColumnName($propertyName, $className = null) - { - return $propertyName . '_' . $this->referenceColumnName(); - } - - /** - * {@inheritdoc} - */ - public function joinTableName($sourceEntity, $targetEntity, $propertyName = null) - { - return strtolower($this->classToTableName($sourceEntity) . '_' . - $this->classToTableName($targetEntity)); - } - - /** - * {@inheritdoc} - */ - public function joinKeyColumnName($entityName, $referencedColumnName = null) - { - return strtolower($this->classToTableName($entityName) . '_' . - ($referencedColumnName ?: $this->referenceColumnName())); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultQuoteStrategy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultQuoteStrategy.php deleted file mode 100644 index ade44a0..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DefaultQuoteStrategy.php +++ /dev/null @@ -1,164 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -use Doctrine\DBAL\Platforms\AbstractPlatform; - -/** - * A set of rules for determining the physical column, alias and table quotes - * - * @since 2.3 - * @author Fabio B. Silva - */ -class DefaultQuoteStrategy implements QuoteStrategy -{ - /** - * {@inheritdoc} - */ - public function getColumnName($fieldName, ClassMetadata $class, AbstractPlatform $platform) - { - return isset($class->fieldMappings[$fieldName]['quoted']) - ? $platform->quoteIdentifier($class->fieldMappings[$fieldName]['columnName']) - : $class->fieldMappings[$fieldName]['columnName']; - } - - /** - * {@inheritdoc} - * - * @todo Table names should be computed in DBAL depending on the platform - */ - public function getTableName(ClassMetadata $class, AbstractPlatform $platform) - { - $tableName = $class->table['name']; - - if ( ! empty($class->table['schema'])) { - $tableName = $class->table['schema'] . '.' . $class->table['name']; - - if ( ! $platform->supportsSchemas() && $platform->canEmulateSchemas()) { - $tableName = $class->table['schema'] . '__' . $class->table['name']; - } - } - - return isset($class->table['quoted']) - ? $platform->quoteIdentifier($tableName) - : $tableName; - } - - /** - * {@inheritdoc} - */ - public function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform) - { - return isset($definition['quoted']) - ? $platform->quoteIdentifier($definition['sequenceName']) - : $definition['sequenceName']; - } - - /** - * {@inheritdoc} - */ - public function getJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform) - { - return isset($joinColumn['quoted']) - ? $platform->quoteIdentifier($joinColumn['name']) - : $joinColumn['name']; - } - - /** - * {@inheritdoc} - */ - public function getReferencedJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform) - { - return isset($joinColumn['quoted']) - ? $platform->quoteIdentifier($joinColumn['referencedColumnName']) - : $joinColumn['referencedColumnName']; - } - - /** - * {@inheritdoc} - */ - public function getJoinTableName(array $association, ClassMetadata $class, AbstractPlatform $platform) - { - $schema = ''; - - if (isset($association['joinTable']['schema'])) { - $schema = $association['joinTable']['schema']; - $schema .= ! $platform->supportsSchemas() && $platform->canEmulateSchemas() ? '__' : '.'; - } - - $tableName = $association['joinTable']['name']; - - if (isset($association['joinTable']['quoted'])) { - $tableName = $platform->quoteIdentifier($tableName); - } - - return $schema . $tableName; - } - - /** - * {@inheritdoc} - */ - public function getIdentifierColumnNames(ClassMetadata $class, AbstractPlatform $platform) - { - $quotedColumnNames = []; - - foreach ($class->identifier as $fieldName) { - if (isset($class->fieldMappings[$fieldName])) { - $quotedColumnNames[] = $this->getColumnName($fieldName, $class, $platform); - - continue; - } - - // Association defined as Id field - $joinColumns = $class->associationMappings[$fieldName]['joinColumns']; - $assocQuotedColumnNames = array_map( - function ($joinColumn) use ($platform) - { - return isset($joinColumn['quoted']) - ? $platform->quoteIdentifier($joinColumn['name']) - : $joinColumn['name']; - }, - $joinColumns - ); - - $quotedColumnNames = array_merge($quotedColumnNames, $assocQuotedColumnNames); - } - - return $quotedColumnNames; - } - - /** - * {@inheritdoc} - */ - public function getColumnAlias($columnName, $counter, AbstractPlatform $platform, ClassMetadata $class = null) - { - // 1 ) Concatenate column name and counter - // 2 ) Trim the column alias to the maximum identifier length of the platform. - // If the alias is to long, characters are cut off from the beginning. - // 3 ) Strip non alphanumeric characters - // 4 ) Prefix with "_" if the result its numeric - $columnName = $columnName . '_' . $counter; - $columnName = substr($columnName, -$platform->getMaxIdentifierLength()); - $columnName = preg_replace('/[^A-Za-z0-9_]/', '', $columnName); - $columnName = is_numeric($columnName) ? '_' . $columnName : $columnName; - - return $platform->getSQLResultCasing($columnName); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorColumn.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorColumn.php deleted file mode 100644 index 97ca7e9..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorColumn.php +++ /dev/null @@ -1,54 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("CLASS") - */ -final class DiscriminatorColumn implements Annotation -{ - /** - * @var string - */ - public $name; - - /** - * @var string - */ - public $type; - - /** - * @var integer - */ - public $length; - - /** - * Field name used in non-object hydration (array/scalar). - * - * @var mixed - */ - public $fieldName; - - /** - * @var string - */ - public $columnDefinition; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorMap.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorMap.php deleted file mode 100644 index 09d6194..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/DiscriminatorMap.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("CLASS") - */ -final class DiscriminatorMap implements Annotation -{ - /** - * @var array - */ - public $value; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php deleted file mode 100644 index d59fd3b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php +++ /dev/null @@ -1,673 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Driver; - -use Doctrine\Common\Annotations\AnnotationReader; -use Doctrine\Common\Persistence\Mapping\ClassMetadata; -use Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver as AbstractAnnotationDriver; -use Doctrine\ORM\Events; -use Doctrine\ORM\Mapping; -use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder; -use Doctrine\ORM\Mapping\MappingException; - -/** - * The AnnotationDriver reads the mapping metadata from docblock annotations. - * - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan H. Wage - * @author Roman Borschel - */ -class AnnotationDriver extends AbstractAnnotationDriver -{ - /** - * {@inheritDoc} - */ - protected $entityAnnotationClasses = [ - Mapping\Entity::class => 1, - Mapping\MappedSuperclass::class => 2, - ]; - - /** - * {@inheritDoc} - */ - public function loadMetadataForClass($className, ClassMetadata $metadata) - { - /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */ - $class = $metadata->getReflectionClass(); - - if ( ! $class) { - // this happens when running annotation driver in combination with - // static reflection services. This is not the nicest fix - $class = new \ReflectionClass($metadata->name); - } - - $classAnnotations = $this->reader->getClassAnnotations($class); - - if ($classAnnotations) { - foreach ($classAnnotations as $key => $annot) { - if ( ! is_numeric($key)) { - continue; - } - - $classAnnotations[get_class($annot)] = $annot; - } - } - - // Evaluate Entity annotation - if (isset($classAnnotations[Mapping\Entity::class])) { - $entityAnnot = $classAnnotations[Mapping\Entity::class]; - if ($entityAnnot->repositoryClass !== null) { - $metadata->setCustomRepositoryClass($entityAnnot->repositoryClass); - } - - if ($entityAnnot->readOnly) { - $metadata->markReadOnly(); - } - } else if (isset($classAnnotations[Mapping\MappedSuperclass::class])) { - $mappedSuperclassAnnot = $classAnnotations[Mapping\MappedSuperclass::class]; - - $metadata->setCustomRepositoryClass($mappedSuperclassAnnot->repositoryClass); - $metadata->isMappedSuperclass = true; - } else if (isset($classAnnotations[Mapping\Embeddable::class])) { - $metadata->isEmbeddedClass = true; - } else { - throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className); - } - - // Evaluate Table annotation - if (isset($classAnnotations[Mapping\Table::class])) { - $tableAnnot = $classAnnotations[Mapping\Table::class]; - $primaryTable = [ - 'name' => $tableAnnot->name, - 'schema' => $tableAnnot->schema - ]; - - if ($tableAnnot->indexes !== null) { - foreach ($tableAnnot->indexes as $indexAnnot) { - $index = ['columns' => $indexAnnot->columns]; - - if ( ! empty($indexAnnot->flags)) { - $index['flags'] = $indexAnnot->flags; - } - - if ( ! empty($indexAnnot->options)) { - $index['options'] = $indexAnnot->options; - } - - if ( ! empty($indexAnnot->name)) { - $primaryTable['indexes'][$indexAnnot->name] = $index; - } else { - $primaryTable['indexes'][] = $index; - } - } - } - - if ($tableAnnot->uniqueConstraints !== null) { - foreach ($tableAnnot->uniqueConstraints as $uniqueConstraintAnnot) { - $uniqueConstraint = ['columns' => $uniqueConstraintAnnot->columns]; - - if ( ! empty($uniqueConstraintAnnot->options)) { - $uniqueConstraint['options'] = $uniqueConstraintAnnot->options; - } - - if ( ! empty($uniqueConstraintAnnot->name)) { - $primaryTable['uniqueConstraints'][$uniqueConstraintAnnot->name] = $uniqueConstraint; - } else { - $primaryTable['uniqueConstraints'][] = $uniqueConstraint; - } - } - } - - if ($tableAnnot->options) { - $primaryTable['options'] = $tableAnnot->options; - } - - $metadata->setPrimaryTable($primaryTable); - } - - // Evaluate @Cache annotation - if (isset($classAnnotations[Mapping\Cache::class])) { - $cacheAnnot = $classAnnotations[Mapping\Cache::class]; - $cacheMap = [ - 'region' => $cacheAnnot->region, - 'usage' => constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $cacheAnnot->usage), - ]; - - $metadata->enableCache($cacheMap); - } - - // Evaluate NamedNativeQueries annotation - if (isset($classAnnotations[Mapping\NamedNativeQueries::class])) { - $namedNativeQueriesAnnot = $classAnnotations[Mapping\NamedNativeQueries::class]; - - foreach ($namedNativeQueriesAnnot->value as $namedNativeQuery) { - $metadata->addNamedNativeQuery( - [ - 'name' => $namedNativeQuery->name, - 'query' => $namedNativeQuery->query, - 'resultClass' => $namedNativeQuery->resultClass, - 'resultSetMapping' => $namedNativeQuery->resultSetMapping, - ] - ); - } - } - - // Evaluate SqlResultSetMappings annotation - if (isset($classAnnotations[Mapping\SqlResultSetMappings::class])) { - $sqlResultSetMappingsAnnot = $classAnnotations[Mapping\SqlResultSetMappings::class]; - - foreach ($sqlResultSetMappingsAnnot->value as $resultSetMapping) { - $entities = []; - $columns = []; - foreach ($resultSetMapping->entities as $entityResultAnnot) { - $entityResult = [ - 'fields' => [], - 'entityClass' => $entityResultAnnot->entityClass, - 'discriminatorColumn' => $entityResultAnnot->discriminatorColumn, - ]; - - foreach ($entityResultAnnot->fields as $fieldResultAnnot) { - $entityResult['fields'][] = [ - 'name' => $fieldResultAnnot->name, - 'column' => $fieldResultAnnot->column - ]; - } - - $entities[] = $entityResult; - } - - foreach ($resultSetMapping->columns as $columnResultAnnot) { - $columns[] = [ - 'name' => $columnResultAnnot->name, - ]; - } - - $metadata->addSqlResultSetMapping( - [ - 'name' => $resultSetMapping->name, - 'entities' => $entities, - 'columns' => $columns - ] - ); - } - } - - // Evaluate NamedQueries annotation - if (isset($classAnnotations[Mapping\NamedQueries::class])) { - $namedQueriesAnnot = $classAnnotations[Mapping\NamedQueries::class]; - - if ( ! is_array($namedQueriesAnnot->value)) { - throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations."); - } - - foreach ($namedQueriesAnnot->value as $namedQuery) { - if ( ! ($namedQuery instanceof Mapping\NamedQuery)) { - throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations."); - } - $metadata->addNamedQuery( - [ - 'name' => $namedQuery->name, - 'query' => $namedQuery->query - ] - ); - } - } - - // Evaluate InheritanceType annotation - if (isset($classAnnotations[Mapping\InheritanceType::class])) { - $inheritanceTypeAnnot = $classAnnotations[Mapping\InheritanceType::class]; - - $metadata->setInheritanceType( - constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceTypeAnnot->value) - ); - - if ($metadata->inheritanceType != Mapping\ClassMetadata::INHERITANCE_TYPE_NONE) { - // Evaluate DiscriminatorColumn annotation - if (isset($classAnnotations[Mapping\DiscriminatorColumn::class])) { - $discrColumnAnnot = $classAnnotations[Mapping\DiscriminatorColumn::class]; - - $metadata->setDiscriminatorColumn( - [ - 'name' => $discrColumnAnnot->name, - 'type' => $discrColumnAnnot->type ?: 'string', - 'length' => $discrColumnAnnot->length ?: 255, - 'columnDefinition' => $discrColumnAnnot->columnDefinition, - ] - ); - } else { - $metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]); - } - - // Evaluate DiscriminatorMap annotation - if (isset($classAnnotations[Mapping\DiscriminatorMap::class])) { - $discrMapAnnot = $classAnnotations[Mapping\DiscriminatorMap::class]; - $metadata->setDiscriminatorMap($discrMapAnnot->value); - } - } - } - - - // Evaluate DoctrineChangeTrackingPolicy annotation - if (isset($classAnnotations[Mapping\ChangeTrackingPolicy::class])) { - $changeTrackingAnnot = $classAnnotations[Mapping\ChangeTrackingPolicy::class]; - $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_' . $changeTrackingAnnot->value)); - } - - // Evaluate annotations on properties/fields - /* @var $property \ReflectionProperty */ - foreach ($class->getProperties() as $property) { - if ($metadata->isMappedSuperclass && ! $property->isPrivate() - || - $metadata->isInheritedField($property->name) - || - $metadata->isInheritedAssociation($property->name) - || - $metadata->isInheritedEmbeddedClass($property->name)) { - continue; - } - - $mapping = []; - $mapping['fieldName'] = $property->getName(); - - // Evaluate @Cache annotation - if (($cacheAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Cache::class)) !== null) { - $mapping['cache'] = $metadata->getAssociationCacheDefaults( - $mapping['fieldName'], - [ - 'usage' => constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $cacheAnnot->usage), - 'region' => $cacheAnnot->region, - ] - ); - } - // Check for JoinColumn/JoinColumns annotations - $joinColumns = []; - - if ($joinColumnAnnot = $this->reader->getPropertyAnnotation($property, Mapping\JoinColumn::class)) { - $joinColumns[] = $this->joinColumnToArray($joinColumnAnnot); - } else if ($joinColumnsAnnot = $this->reader->getPropertyAnnotation($property, Mapping\JoinColumns::class)) { - foreach ($joinColumnsAnnot->value as $joinColumn) { - $joinColumns[] = $this->joinColumnToArray($joinColumn); - } - } - - // Field can only be annotated with one of: - // @Column, @OneToOne, @OneToMany, @ManyToOne, @ManyToMany - if ($columnAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Column::class)) { - if ($columnAnnot->type == null) { - throw MappingException::propertyTypeIsRequired($className, $property->getName()); - } - - $mapping = $this->columnToArray($property->getName(), $columnAnnot); - - if ($idAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Id::class)) { - $mapping['id'] = true; - } - - if ($generatedValueAnnot = $this->reader->getPropertyAnnotation($property, Mapping\GeneratedValue::class)) { - $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $generatedValueAnnot->strategy)); - } - - if ($this->reader->getPropertyAnnotation($property, Mapping\Version::class)) { - $metadata->setVersionMapping($mapping); - } - - $metadata->mapField($mapping); - - // Check for SequenceGenerator/TableGenerator definition - if ($seqGeneratorAnnot = $this->reader->getPropertyAnnotation($property, Mapping\SequenceGenerator::class)) { - $metadata->setSequenceGeneratorDefinition( - [ - 'sequenceName' => $seqGeneratorAnnot->sequenceName, - 'allocationSize' => $seqGeneratorAnnot->allocationSize, - 'initialValue' => $seqGeneratorAnnot->initialValue - ] - ); - } else if ($this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\TableGenerator')) { - throw MappingException::tableIdGeneratorNotImplemented($className); - } else if ($customGeneratorAnnot = $this->reader->getPropertyAnnotation($property, Mapping\CustomIdGenerator::class)) { - $metadata->setCustomGeneratorDefinition( - [ - 'class' => $customGeneratorAnnot->class - ] - ); - } - } else if ($oneToOneAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OneToOne::class)) { - if ($idAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Id::class)) { - $mapping['id'] = true; - } - - $mapping['targetEntity'] = $oneToOneAnnot->targetEntity; - $mapping['joinColumns'] = $joinColumns; - $mapping['mappedBy'] = $oneToOneAnnot->mappedBy; - $mapping['inversedBy'] = $oneToOneAnnot->inversedBy; - $mapping['cascade'] = $oneToOneAnnot->cascade; - $mapping['orphanRemoval'] = $oneToOneAnnot->orphanRemoval; - $mapping['fetch'] = $this->getFetchMode($className, $oneToOneAnnot->fetch); - $metadata->mapOneToOne($mapping); - } else if ($oneToManyAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OneToMany::class)) { - $mapping['mappedBy'] = $oneToManyAnnot->mappedBy; - $mapping['targetEntity'] = $oneToManyAnnot->targetEntity; - $mapping['cascade'] = $oneToManyAnnot->cascade; - $mapping['indexBy'] = $oneToManyAnnot->indexBy; - $mapping['orphanRemoval'] = $oneToManyAnnot->orphanRemoval; - $mapping['fetch'] = $this->getFetchMode($className, $oneToManyAnnot->fetch); - - if ($orderByAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OrderBy::class)) { - $mapping['orderBy'] = $orderByAnnot->value; - } - - $metadata->mapOneToMany($mapping); - } else if ($manyToOneAnnot = $this->reader->getPropertyAnnotation($property, Mapping\ManyToOne::class)) { - if ($idAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Id::class)) { - $mapping['id'] = true; - } - - $mapping['joinColumns'] = $joinColumns; - $mapping['cascade'] = $manyToOneAnnot->cascade; - $mapping['inversedBy'] = $manyToOneAnnot->inversedBy; - $mapping['targetEntity'] = $manyToOneAnnot->targetEntity; - $mapping['fetch'] = $this->getFetchMode($className, $manyToOneAnnot->fetch); - $metadata->mapManyToOne($mapping); - } else if ($manyToManyAnnot = $this->reader->getPropertyAnnotation($property, Mapping\ManyToMany::class)) { - $joinTable = []; - - if ($joinTableAnnot = $this->reader->getPropertyAnnotation($property, Mapping\JoinTable::class)) { - $joinTable = [ - 'name' => $joinTableAnnot->name, - 'schema' => $joinTableAnnot->schema - ]; - - foreach ($joinTableAnnot->joinColumns as $joinColumn) { - $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn); - } - - foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) { - $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn); - } - } - - $mapping['joinTable'] = $joinTable; - $mapping['targetEntity'] = $manyToManyAnnot->targetEntity; - $mapping['mappedBy'] = $manyToManyAnnot->mappedBy; - $mapping['inversedBy'] = $manyToManyAnnot->inversedBy; - $mapping['cascade'] = $manyToManyAnnot->cascade; - $mapping['indexBy'] = $manyToManyAnnot->indexBy; - $mapping['orphanRemoval'] = $manyToManyAnnot->orphanRemoval; - $mapping['fetch'] = $this->getFetchMode($className, $manyToManyAnnot->fetch); - - if ($orderByAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OrderBy::class)) { - $mapping['orderBy'] = $orderByAnnot->value; - } - - $metadata->mapManyToMany($mapping); - } else if ($embeddedAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Embedded::class)) { - $mapping['class'] = $embeddedAnnot->class; - $mapping['columnPrefix'] = $embeddedAnnot->columnPrefix; - - $metadata->mapEmbedded($mapping); - } - } - - // Evaluate AssociationOverrides annotation - if (isset($classAnnotations[Mapping\AssociationOverrides::class])) { - $associationOverridesAnnot = $classAnnotations[Mapping\AssociationOverrides::class]; - - foreach ($associationOverridesAnnot->value as $associationOverride) { - $override = []; - $fieldName = $associationOverride->name; - - // Check for JoinColumn/JoinColumns annotations - if ($associationOverride->joinColumns) { - $joinColumns = []; - - foreach ($associationOverride->joinColumns as $joinColumn) { - $joinColumns[] = $this->joinColumnToArray($joinColumn); - } - - $override['joinColumns'] = $joinColumns; - } - - // Check for JoinTable annotations - if ($associationOverride->joinTable) { - $joinTableAnnot = $associationOverride->joinTable; - $joinTable = [ - 'name' => $joinTableAnnot->name, - 'schema' => $joinTableAnnot->schema - ]; - - foreach ($joinTableAnnot->joinColumns as $joinColumn) { - $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn); - } - - foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) { - $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn); - } - - $override['joinTable'] = $joinTable; - } - - // Check for inversedBy - if ($associationOverride->inversedBy) { - $override['inversedBy'] = $associationOverride->inversedBy; - } - - // Check for `fetch` - if ($associationOverride->fetch) { - $override['fetch'] = constant(Mapping\ClassMetadata::class . '::FETCH_' . $associationOverride->fetch); - } - - $metadata->setAssociationOverride($fieldName, $override); - } - } - - // Evaluate AttributeOverrides annotation - if (isset($classAnnotations[Mapping\AttributeOverrides::class])) { - $attributeOverridesAnnot = $classAnnotations[Mapping\AttributeOverrides::class]; - - foreach ($attributeOverridesAnnot->value as $attributeOverrideAnnot) { - $attributeOverride = $this->columnToArray($attributeOverrideAnnot->name, $attributeOverrideAnnot->column); - - $metadata->setAttributeOverride($attributeOverrideAnnot->name, $attributeOverride); - } - } - - // Evaluate EntityListeners annotation - if (isset($classAnnotations[Mapping\EntityListeners::class])) { - $entityListenersAnnot = $classAnnotations[Mapping\EntityListeners::class]; - - foreach ($entityListenersAnnot->value as $item) { - $listenerClassName = $metadata->fullyQualifiedClassName($item); - - if ( ! class_exists($listenerClassName)) { - throw MappingException::entityListenerClassNotFound($listenerClassName, $className); - } - - $hasMapping = false; - $listenerClass = new \ReflectionClass($listenerClassName); - - /* @var $method \ReflectionMethod */ - foreach ($listenerClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { - // find method callbacks. - $callbacks = $this->getMethodCallbacks($method); - $hasMapping = $hasMapping ?: ( ! empty($callbacks)); - - foreach ($callbacks as $value) { - $metadata->addEntityListener($value[1], $listenerClassName, $value[0]); - } - } - - // Evaluate the listener using naming convention. - if ( ! $hasMapping ) { - EntityListenerBuilder::bindEntityListener($metadata, $listenerClassName); - } - } - } - - // Evaluate @HasLifecycleCallbacks annotation - if (isset($classAnnotations[Mapping\HasLifecycleCallbacks::class])) { - /* @var $method \ReflectionMethod */ - foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { - foreach ($this->getMethodCallbacks($method) as $value) { - $metadata->addLifecycleCallback($value[0], $value[1]); - } - } - } - } - - /** - * Attempts to resolve the fetch mode. - * - * @param string $className The class name. - * @param string $fetchMode The fetch mode. - * - * @return integer The fetch mode as defined in ClassMetadata. - * - * @throws MappingException If the fetch mode is not valid. - */ - private function getFetchMode($className, $fetchMode) - { - if ( ! defined('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode)) { - throw MappingException::invalidFetchMode($className, $fetchMode); - } - - return constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode); - } - - /** - * Parses the given method. - * - * @param \ReflectionMethod $method - * - * @return array - */ - private function getMethodCallbacks(\ReflectionMethod $method) - { - $callbacks = []; - $annotations = $this->reader->getMethodAnnotations($method); - - foreach ($annotations as $annot) { - if ($annot instanceof Mapping\PrePersist) { - $callbacks[] = [$method->name, Events::prePersist]; - } - - if ($annot instanceof Mapping\PostPersist) { - $callbacks[] = [$method->name, Events::postPersist]; - } - - if ($annot instanceof Mapping\PreUpdate) { - $callbacks[] = [$method->name, Events::preUpdate]; - } - - if ($annot instanceof Mapping\PostUpdate) { - $callbacks[] = [$method->name, Events::postUpdate]; - } - - if ($annot instanceof Mapping\PreRemove) { - $callbacks[] = [$method->name, Events::preRemove]; - } - - if ($annot instanceof Mapping\PostRemove) { - $callbacks[] = [$method->name, Events::postRemove]; - } - - if ($annot instanceof Mapping\PostLoad) { - $callbacks[] = [$method->name, Events::postLoad]; - } - - if ($annot instanceof Mapping\PreFlush) { - $callbacks[] = [$method->name, Events::preFlush]; - } - } - - return $callbacks; - } - - /** - * Parse the given JoinColumn as array - * - * @param Mapping\JoinColumn $joinColumn - * @return array - */ - private function joinColumnToArray(Mapping\JoinColumn $joinColumn) - { - return [ - 'name' => $joinColumn->name, - 'unique' => $joinColumn->unique, - 'nullable' => $joinColumn->nullable, - 'onDelete' => $joinColumn->onDelete, - 'columnDefinition' => $joinColumn->columnDefinition, - 'referencedColumnName' => $joinColumn->referencedColumnName, - ]; - } - - /** - * Parse the given Column as array - * - * @param string $fieldName - * @param Mapping\Column $column - * - * @return array - */ - private function columnToArray($fieldName, Mapping\Column $column) - { - $mapping = [ - 'fieldName' => $fieldName, - 'type' => $column->type, - 'scale' => $column->scale, - 'length' => $column->length, - 'unique' => $column->unique, - 'nullable' => $column->nullable, - 'precision' => $column->precision - ]; - - if ($column->options) { - $mapping['options'] = $column->options; - } - - if (isset($column->name)) { - $mapping['columnName'] = $column->name; - } - - if (isset($column->columnDefinition)) { - $mapping['columnDefinition'] = $column->columnDefinition; - } - - return $mapping; - } - - /** - * Factory method for the Annotation Driver. - * - * @param array|string $paths - * @param AnnotationReader|null $reader - * - * @return AnnotationDriver - */ - static public function create($paths = [], AnnotationReader $reader = null) - { - if ($reader == null) { - $reader = new AnnotationReader(); - } - - return new self($reader, $paths); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php deleted file mode 100644 index 83798e1..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php +++ /dev/null @@ -1,557 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Driver; - -use Doctrine\Common\Inflector\Inflector; -use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver; -use Doctrine\Common\Persistence\Mapping\ClassMetadata; -use Doctrine\DBAL\Schema\AbstractSchemaManager; -use Doctrine\DBAL\Schema\SchemaException; -use Doctrine\DBAL\Schema\Table; -use Doctrine\DBAL\Schema\Column; -use Doctrine\DBAL\Types\Type; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\ORM\Mapping\MappingException; -use function preg_replace; - -/** - * The DatabaseDriver reverse engineers the mapping metadata from a database. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Benjamin Eberlei - */ -class DatabaseDriver implements MappingDriver -{ - /** - * @var AbstractSchemaManager - */ - private $_sm; - - /** - * @var array|null - */ - private $tables = null; - - /** - * @var array - */ - private $classToTableNames = []; - - /** - * @var array - */ - private $manyToManyTables = []; - - /** - * @var array - */ - private $classNamesForTables = []; - - /** - * @var array - */ - private $fieldNamesForColumns = []; - - /** - * The namespace for the generated entities. - * - * @var string|null - */ - private $namespace; - - /** - * @param AbstractSchemaManager $schemaManager - */ - public function __construct(AbstractSchemaManager $schemaManager) - { - $this->_sm = $schemaManager; - } - - /** - * Set the namespace for the generated entities. - * - * @param string $namespace - * - * @return void - */ - public function setNamespace($namespace) - { - $this->namespace = $namespace; - } - - /** - * {@inheritDoc} - */ - public function isTransient($className) - { - return true; - } - - /** - * {@inheritDoc} - */ - public function getAllClassNames() - { - $this->reverseEngineerMappingFromDatabase(); - - return array_keys($this->classToTableNames); - } - - /** - * Sets class name for a table. - * - * @param string $tableName - * @param string $className - * - * @return void - */ - public function setClassNameForTable($tableName, $className) - { - $this->classNamesForTables[$tableName] = $className; - } - - /** - * Sets field name for a column on a specific table. - * - * @param string $tableName - * @param string $columnName - * @param string $fieldName - * - * @return void - */ - public function setFieldNameForColumn($tableName, $columnName, $fieldName) - { - $this->fieldNamesForColumns[$tableName][$columnName] = $fieldName; - } - - /** - * Sets tables manually instead of relying on the reverse engineering capabilities of SchemaManager. - * - * @param array $entityTables - * @param array $manyToManyTables - * - * @return void - */ - public function setTables($entityTables, $manyToManyTables) - { - $this->tables = $this->manyToManyTables = $this->classToTableNames = []; - - foreach ($entityTables as $table) { - $className = $this->getClassNameForTable($table->getName()); - - $this->classToTableNames[$className] = $table->getName(); - $this->tables[$table->getName()] = $table; - } - - foreach ($manyToManyTables as $table) { - $this->manyToManyTables[$table->getName()] = $table; - } - } - - /** - * {@inheritDoc} - */ - public function loadMetadataForClass($className, ClassMetadata $metadata) - { - $this->reverseEngineerMappingFromDatabase(); - - if ( ! isset($this->classToTableNames[$className])) { - throw new \InvalidArgumentException("Unknown class " . $className); - } - - $tableName = $this->classToTableNames[$className]; - - $metadata->name = $className; - $metadata->table['name'] = $tableName; - - $this->buildIndexes($metadata); - $this->buildFieldMappings($metadata); - $this->buildToOneAssociationMappings($metadata); - - foreach ($this->manyToManyTables as $manyTable) { - foreach ($manyTable->getForeignKeys() as $foreignKey) { - // foreign key maps to the table of the current entity, many to many association probably exists - if ( ! (strtolower($tableName) === strtolower($foreignKey->getForeignTableName()))) { - continue; - } - - $myFk = $foreignKey; - $otherFk = null; - - foreach ($manyTable->getForeignKeys() as $foreignKey) { - if ($foreignKey != $myFk) { - $otherFk = $foreignKey; - break; - } - } - - if ( ! $otherFk) { - // the definition of this many to many table does not contain - // enough foreign key information to continue reverse engineering. - continue; - } - - $localColumn = current($myFk->getColumns()); - - $associationMapping = []; - $associationMapping['fieldName'] = $this->getFieldNameForColumn($manyTable->getName(), current($otherFk->getColumns()), true); - $associationMapping['targetEntity'] = $this->getClassNameForTable($otherFk->getForeignTableName()); - - if (current($manyTable->getColumns())->getName() == $localColumn) { - $associationMapping['inversedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getColumns()), true); - $associationMapping['joinTable'] = [ - 'name' => strtolower($manyTable->getName()), - 'joinColumns' => [], - 'inverseJoinColumns' => [], - ]; - - $fkCols = $myFk->getForeignColumns(); - $cols = $myFk->getColumns(); - - for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) { - $associationMapping['joinTable']['joinColumns'][] = [ - 'name' => $cols[$i], - 'referencedColumnName' => $fkCols[$i], - ]; - } - - $fkCols = $otherFk->getForeignColumns(); - $cols = $otherFk->getColumns(); - - for ($i = 0, $colsCount = count($cols); $i < $colsCount; $i++) { - $associationMapping['joinTable']['inverseJoinColumns'][] = [ - 'name' => $cols[$i], - 'referencedColumnName' => $fkCols[$i], - ]; - } - } else { - $associationMapping['mappedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getColumns()), true); - } - - $metadata->mapManyToMany($associationMapping); - - break; - } - } - } - - /** - * @return void - * - * @throws \Doctrine\ORM\Mapping\MappingException - */ - private function reverseEngineerMappingFromDatabase() - { - if ($this->tables !== null) { - return; - } - - $tables = []; - - foreach ($this->_sm->listTableNames() as $tableName) { - $tables[$tableName] = $this->_sm->listTableDetails($tableName); - } - - $this->tables = $this->manyToManyTables = $this->classToTableNames = []; - - foreach ($tables as $tableName => $table) { - $foreignKeys = ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) - ? $table->getForeignKeys() - : []; - - $allForeignKeyColumns = []; - - foreach ($foreignKeys as $foreignKey) { - $allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns()); - } - - if ( ! $table->hasPrimaryKey()) { - throw new MappingException( - "Table " . $table->getName() . " has no primary key. Doctrine does not ". - "support reverse engineering from tables that don't have a primary key." - ); - } - - $pkColumns = $table->getPrimaryKey()->getColumns(); - - sort($pkColumns); - sort($allForeignKeyColumns); - - if ($pkColumns == $allForeignKeyColumns && count($foreignKeys) == 2) { - $this->manyToManyTables[$tableName] = $table; - } else { - // lower-casing is necessary because of Oracle Uppercase Tablenames, - // assumption is lower-case + underscore separated. - $className = $this->getClassNameForTable($tableName); - - $this->tables[$tableName] = $table; - $this->classToTableNames[$className] = $tableName; - } - } - } - - /** - * Build indexes from a class metadata. - * - * @param \Doctrine\ORM\Mapping\ClassMetadataInfo $metadata - */ - private function buildIndexes(ClassMetadataInfo $metadata) - { - $tableName = $metadata->table['name']; - $indexes = $this->tables[$tableName]->getIndexes(); - - foreach ($indexes as $index) { - if ($index->isPrimary()) { - continue; - } - - $indexName = $index->getName(); - $indexColumns = $index->getColumns(); - $constraintType = $index->isUnique() - ? 'uniqueConstraints' - : 'indexes'; - - $metadata->table[$constraintType][$indexName]['columns'] = $indexColumns; - } - } - - /** - * Build field mapping from class metadata. - * - * @param \Doctrine\ORM\Mapping\ClassMetadataInfo $metadata - */ - private function buildFieldMappings(ClassMetadataInfo $metadata) - { - $tableName = $metadata->table['name']; - $columns = $this->tables[$tableName]->getColumns(); - $primaryKeys = $this->getTablePrimaryKeys($this->tables[$tableName]); - $foreignKeys = $this->getTableForeignKeys($this->tables[$tableName]); - $allForeignKeys = []; - - foreach ($foreignKeys as $foreignKey) { - $allForeignKeys = array_merge($allForeignKeys, $foreignKey->getLocalColumns()); - } - - $ids = []; - $fieldMappings = []; - - foreach ($columns as $column) { - if (in_array($column->getName(), $allForeignKeys)) { - continue; - } - - $fieldMapping = $this->buildFieldMapping($tableName, $column); - - if ($primaryKeys && in_array($column->getName(), $primaryKeys)) { - $fieldMapping['id'] = true; - $ids[] = $fieldMapping; - } - - $fieldMappings[] = $fieldMapping; - } - - // We need to check for the columns here, because we might have associations as id as well. - if ($ids && count($primaryKeys) == 1) { - $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); - } - - foreach ($fieldMappings as $fieldMapping) { - $metadata->mapField($fieldMapping); - } - } - - /** - * Build field mapping from a schema column definition - * - * @param string $tableName - * @param \Doctrine\DBAL\Schema\Column $column - * - * @return array - */ - private function buildFieldMapping($tableName, Column $column) - { - $fieldMapping = [ - 'fieldName' => $this->getFieldNameForColumn($tableName, $column->getName(), false), - 'columnName' => $column->getName(), - 'type' => $column->getType()->getName(), - 'nullable' => ( ! $column->getNotnull()), - ]; - - // Type specific elements - switch ($fieldMapping['type']) { - case Type::TARRAY: - case Type::BLOB: - case Type::GUID: - case Type::JSON_ARRAY: - case Type::OBJECT: - case Type::SIMPLE_ARRAY: - case Type::STRING: - case Type::TEXT: - $fieldMapping['length'] = $column->getLength(); - $fieldMapping['options']['fixed'] = $column->getFixed(); - break; - - case Type::DECIMAL: - case Type::FLOAT: - $fieldMapping['precision'] = $column->getPrecision(); - $fieldMapping['scale'] = $column->getScale(); - break; - - case Type::INTEGER: - case Type::BIGINT: - case Type::SMALLINT: - $fieldMapping['options']['unsigned'] = $column->getUnsigned(); - break; - } - - // Comment - if (($comment = $column->getComment()) !== null) { - $fieldMapping['options']['comment'] = $comment; - } - - // Default - if (($default = $column->getDefault()) !== null) { - $fieldMapping['options']['default'] = $default; - } - - return $fieldMapping; - } - - /** - * Build to one (one to one, many to one) association mapping from class metadata. - * - * @param \Doctrine\ORM\Mapping\ClassMetadataInfo $metadata - */ - private function buildToOneAssociationMappings(ClassMetadataInfo $metadata) - { - $tableName = $metadata->table['name']; - $primaryKeys = $this->getTablePrimaryKeys($this->tables[$tableName]); - $foreignKeys = $this->getTableForeignKeys($this->tables[$tableName]); - - foreach ($foreignKeys as $foreignKey) { - $foreignTableName = $foreignKey->getForeignTableName(); - $fkColumns = $foreignKey->getColumns(); - $fkForeignColumns = $foreignKey->getForeignColumns(); - $localColumn = current($fkColumns); - $associationMapping = [ - 'fieldName' => $this->getFieldNameForColumn($tableName, $localColumn, true), - 'targetEntity' => $this->getClassNameForTable($foreignTableName), - ]; - - if (isset($metadata->fieldMappings[$associationMapping['fieldName']])) { - $associationMapping['fieldName'] .= '2'; // "foo" => "foo2" - } - - if ($primaryKeys && in_array($localColumn, $primaryKeys)) { - $associationMapping['id'] = true; - } - - for ($i = 0, $fkColumnsCount = count($fkColumns); $i < $fkColumnsCount; $i++) { - $associationMapping['joinColumns'][] = [ - 'name' => $fkColumns[$i], - 'referencedColumnName' => $fkForeignColumns[$i], - ]; - } - - // Here we need to check if $fkColumns are the same as $primaryKeys - if ( ! array_diff($fkColumns, $primaryKeys)) { - $metadata->mapOneToOne($associationMapping); - } else { - $metadata->mapManyToOne($associationMapping); - } - } - } - - /** - * Retrieve schema table definition foreign keys. - * - * @param \Doctrine\DBAL\Schema\Table $table - * - * @return array - */ - private function getTableForeignKeys(Table $table) - { - return ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) - ? $table->getForeignKeys() - : []; - } - - /** - * Retrieve schema table definition primary keys. - * - * @param \Doctrine\DBAL\Schema\Table $table - * - * @return array - */ - private function getTablePrimaryKeys(Table $table) - { - try { - return $table->getPrimaryKey()->getColumns(); - } catch (SchemaException $e) { - // Do nothing - } - - return []; - } - - /** - * Returns the mapped class name for a table if it exists. Otherwise return "classified" version. - * - * @param string $tableName - * - * @return string - */ - private function getClassNameForTable($tableName) - { - if (isset($this->classNamesForTables[$tableName])) { - return $this->namespace . $this->classNamesForTables[$tableName]; - } - - return $this->namespace . Inflector::classify(strtolower($tableName)); - } - - /** - * Return the mapped field name for a column, if it exists. Otherwise return camelized version. - * - * @param string $tableName - * @param string $columnName - * @param boolean $fk Whether the column is a foreignkey or not. - * - * @return string - */ - private function getFieldNameForColumn($tableName, $columnName, $fk = false) - { - if (isset($this->fieldNamesForColumns[$tableName]) && isset($this->fieldNamesForColumns[$tableName][$columnName])) { - return $this->fieldNamesForColumns[$tableName][$columnName]; - } - - $columnName = strtolower($columnName); - - // Replace _id if it is a foreignkey column - if ($fk) { - $columnName = preg_replace('/_id$/', '', $columnName); - } - - return Inflector::camelize($columnName); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php deleted file mode 100644 index 8f4a34c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php +++ /dev/null @@ -1,69 +0,0 @@ -. - */ - -require_once __DIR__.'/../Annotation.php'; -require_once __DIR__.'/../Entity.php'; -require_once __DIR__.'/../Embeddable.php'; -require_once __DIR__.'/../Embedded.php'; -require_once __DIR__.'/../MappedSuperclass.php'; -require_once __DIR__.'/../InheritanceType.php'; -require_once __DIR__.'/../DiscriminatorColumn.php'; -require_once __DIR__.'/../DiscriminatorMap.php'; -require_once __DIR__.'/../Id.php'; -require_once __DIR__.'/../GeneratedValue.php'; -require_once __DIR__.'/../Version.php'; -require_once __DIR__.'/../JoinColumn.php'; -require_once __DIR__.'/../JoinColumns.php'; -require_once __DIR__.'/../Column.php'; -require_once __DIR__.'/../OneToOne.php'; -require_once __DIR__.'/../OneToMany.php'; -require_once __DIR__.'/../ManyToOne.php'; -require_once __DIR__.'/../ManyToMany.php'; -require_once __DIR__.'/../Table.php'; -require_once __DIR__.'/../UniqueConstraint.php'; -require_once __DIR__.'/../Index.php'; -require_once __DIR__.'/../JoinTable.php'; -require_once __DIR__.'/../SequenceGenerator.php'; -require_once __DIR__.'/../CustomIdGenerator.php'; -require_once __DIR__.'/../ChangeTrackingPolicy.php'; -require_once __DIR__.'/../OrderBy.php'; -require_once __DIR__.'/../NamedQueries.php'; -require_once __DIR__.'/../NamedQuery.php'; -require_once __DIR__.'/../HasLifecycleCallbacks.php'; -require_once __DIR__.'/../PrePersist.php'; -require_once __DIR__.'/../PostPersist.php'; -require_once __DIR__.'/../PreUpdate.php'; -require_once __DIR__.'/../PostUpdate.php'; -require_once __DIR__.'/../PreRemove.php'; -require_once __DIR__.'/../PostRemove.php'; -require_once __DIR__.'/../PostLoad.php'; -require_once __DIR__.'/../PreFlush.php'; -require_once __DIR__.'/../FieldResult.php'; -require_once __DIR__.'/../ColumnResult.php'; -require_once __DIR__.'/../EntityResult.php'; -require_once __DIR__.'/../NamedNativeQuery.php'; -require_once __DIR__.'/../NamedNativeQueries.php'; -require_once __DIR__.'/../SqlResultSetMapping.php'; -require_once __DIR__.'/../SqlResultSetMappings.php'; -require_once __DIR__.'/../AssociationOverride.php'; -require_once __DIR__.'/../AssociationOverrides.php'; -require_once __DIR__.'/../AttributeOverride.php'; -require_once __DIR__.'/../AttributeOverrides.php'; -require_once __DIR__.'/../EntityListeners.php'; -require_once __DIR__.'/../Cache.php'; diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DriverChain.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DriverChain.php deleted file mode 100644 index f4cd8cd..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DriverChain.php +++ /dev/null @@ -1,31 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Driver; - -use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain; - -/** - * {@inheritDoc} - * - * @deprecated this driver will be removed. Use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain instead - */ -class DriverChain extends MappingDriverChain -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/PHPDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/PHPDriver.php deleted file mode 100644 index 28e2dbe..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/PHPDriver.php +++ /dev/null @@ -1,31 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Driver; - -use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver as CommonPHPDriver; - -/** - * {@inheritDoc} - * - * @deprecated this driver will be removed. Use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver instead - */ -class PHPDriver extends CommonPHPDriver -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedXmlDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedXmlDriver.php deleted file mode 100644 index 9bfd84c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedXmlDriver.php +++ /dev/null @@ -1,43 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Driver; - -use Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator; - -/** - * XmlDriver that additionally looks for mapping information in a global file. - * - * @author Fabien Potencier - * @author Benjamin Eberlei - * @license MIT - */ -class SimplifiedXmlDriver extends XmlDriver -{ - const DEFAULT_FILE_EXTENSION = '.orm.xml'; - - /** - * {@inheritDoc} - */ - public function __construct($prefixes, $fileExtension = self::DEFAULT_FILE_EXTENSION) - { - $locator = new SymfonyFileLocator((array) $prefixes, $fileExtension); - parent::__construct($locator, $fileExtension); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedYamlDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedYamlDriver.php deleted file mode 100644 index 8f38784..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/SimplifiedYamlDriver.php +++ /dev/null @@ -1,43 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Driver; - -use Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator; - -/** - * YamlDriver that additionally looks for mapping information in a global file. - * - * @author Fabien Potencier - * @author Benjamin Eberlei - * @license MIT - */ -class SimplifiedYamlDriver extends YamlDriver -{ - const DEFAULT_FILE_EXTENSION = '.orm.yml'; - - /** - * {@inheritDoc} - */ - public function __construct($prefixes, $fileExtension = self::DEFAULT_FILE_EXTENSION) - { - $locator = new SymfonyFileLocator((array) $prefixes, $fileExtension); - parent::__construct($locator, $fileExtension); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/StaticPHPDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/StaticPHPDriver.php deleted file mode 100644 index d6c6ead..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/StaticPHPDriver.php +++ /dev/null @@ -1,31 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Driver; - -use Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver as CommonStaticPHPDriver; - -/** - * {@inheritDoc} - * - * @deprecated this driver will be removed. Use Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver instead - */ -class StaticPHPDriver extends CommonStaticPHPDriver -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php deleted file mode 100644 index 93b697c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php +++ /dev/null @@ -1,881 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Driver; - -use Doctrine\Common\Collections\Criteria; -use SimpleXMLElement; -use Doctrine\Common\Persistence\Mapping\Driver\FileDriver; -use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder; -use Doctrine\Common\Persistence\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\MappingException; -use Doctrine\ORM\Mapping\ClassMetadata as Metadata; - -/** - * XmlDriver is a metadata driver that enables mapping through XML files. - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan H. Wage - * @author Roman Borschel - */ -class XmlDriver extends FileDriver -{ - const DEFAULT_FILE_EXTENSION = '.dcm.xml'; - - /** - * {@inheritDoc} - */ - public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION) - { - parent::__construct($locator, $fileExtension); - } - - /** - * {@inheritDoc} - */ - public function loadMetadataForClass($className, ClassMetadata $metadata) - { - /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */ - /* @var $xmlRoot SimpleXMLElement */ - $xmlRoot = $this->getElement($className); - - if ($xmlRoot->getName() == 'entity') { - if (isset($xmlRoot['repository-class'])) { - $metadata->setCustomRepositoryClass((string) $xmlRoot['repository-class']); - } - if (isset($xmlRoot['read-only']) && $this->evaluateBoolean($xmlRoot['read-only'])) { - $metadata->markReadOnly(); - } - } else if ($xmlRoot->getName() == 'mapped-superclass') { - $metadata->setCustomRepositoryClass( - isset($xmlRoot['repository-class']) ? (string) $xmlRoot['repository-class'] : null - ); - $metadata->isMappedSuperclass = true; - } else if ($xmlRoot->getName() == 'embeddable') { - $metadata->isEmbeddedClass = true; - } else { - throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className); - } - - // Evaluate attributes - $primaryTable = []; - - if (isset($xmlRoot['table'])) { - $primaryTable['name'] = (string) $xmlRoot['table']; - } - - if (isset($xmlRoot['schema'])) { - $primaryTable['schema'] = (string) $xmlRoot['schema']; - } - - $metadata->setPrimaryTable($primaryTable); - - // Evaluate second level cache - if (isset($xmlRoot->cache)) { - $metadata->enableCache($this->cacheToArray($xmlRoot->cache)); - } - - // Evaluate named queries - if (isset($xmlRoot->{'named-queries'})) { - foreach ($xmlRoot->{'named-queries'}->{'named-query'} as $namedQueryElement) { - $metadata->addNamedQuery( - [ - 'name' => (string) $namedQueryElement['name'], - 'query' => (string) $namedQueryElement['query'] - ] - ); - } - } - - // Evaluate native named queries - if (isset($xmlRoot->{'named-native-queries'})) { - foreach ($xmlRoot->{'named-native-queries'}->{'named-native-query'} as $nativeQueryElement) { - $metadata->addNamedNativeQuery( - [ - 'name' => isset($nativeQueryElement['name']) ? (string) $nativeQueryElement['name'] : null, - 'query' => isset($nativeQueryElement->query) ? (string) $nativeQueryElement->query : null, - 'resultClass' => isset($nativeQueryElement['result-class']) ? (string) $nativeQueryElement['result-class'] : null, - 'resultSetMapping' => isset($nativeQueryElement['result-set-mapping']) ? (string) $nativeQueryElement['result-set-mapping'] : null, - ] - ); - } - } - - // Evaluate sql result set mapping - if (isset($xmlRoot->{'sql-result-set-mappings'})) { - foreach ($xmlRoot->{'sql-result-set-mappings'}->{'sql-result-set-mapping'} as $rsmElement) { - $entities = []; - $columns = []; - foreach ($rsmElement as $entityElement) { - // - if (isset($entityElement['entity-class'])) { - $entityResult = [ - 'fields' => [], - 'entityClass' => (string) $entityElement['entity-class'], - 'discriminatorColumn' => isset($entityElement['discriminator-column']) ? (string) $entityElement['discriminator-column'] : null, - ]; - - foreach ($entityElement as $fieldElement) { - $entityResult['fields'][] = [ - 'name' => isset($fieldElement['name']) ? (string) $fieldElement['name'] : null, - 'column' => isset($fieldElement['column']) ? (string) $fieldElement['column'] : null, - ]; - } - - $entities[] = $entityResult; - } - - // - if (isset($entityElement['name'])) { - $columns[] = [ - 'name' => (string) $entityElement['name'], - ]; - } - } - - $metadata->addSqlResultSetMapping( - [ - 'name' => (string) $rsmElement['name'], - 'entities' => $entities, - 'columns' => $columns - ] - ); - } - } - - if (isset($xmlRoot['inheritance-type'])) { - $inheritanceType = (string) $xmlRoot['inheritance-type']; - $metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceType)); - - if ($metadata->inheritanceType != Metadata::INHERITANCE_TYPE_NONE) { - // Evaluate - if (isset($xmlRoot->{'discriminator-column'})) { - $discrColumn = $xmlRoot->{'discriminator-column'}; - $metadata->setDiscriminatorColumn( - [ - 'name' => isset($discrColumn['name']) ? (string) $discrColumn['name'] : null, - 'type' => isset($discrColumn['type']) ? (string) $discrColumn['type'] : 'string', - 'length' => isset($discrColumn['length']) ? (string) $discrColumn['length'] : 255, - 'columnDefinition' => isset($discrColumn['column-definition']) ? (string) $discrColumn['column-definition'] : null - ] - ); - } else { - $metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]); - } - - // Evaluate - if (isset($xmlRoot->{'discriminator-map'})) { - $map = []; - foreach ($xmlRoot->{'discriminator-map'}->{'discriminator-mapping'} as $discrMapElement) { - $map[(string) $discrMapElement['value']] = (string) $discrMapElement['class']; - } - $metadata->setDiscriminatorMap($map); - } - } - } - - - // Evaluate - if (isset($xmlRoot['change-tracking-policy'])) { - $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_' - . strtoupper((string) $xmlRoot['change-tracking-policy']))); - } - - // Evaluate - if (isset($xmlRoot->indexes)) { - $metadata->table['indexes'] = []; - foreach ($xmlRoot->indexes->index as $indexXml) { - $index = ['columns' => explode(',', (string) $indexXml['columns'])]; - - if (isset($indexXml['flags'])) { - $index['flags'] = explode(',', (string) $indexXml['flags']); - } - - if (isset($indexXml->options)) { - $index['options'] = $this->_parseOptions($indexXml->options->children()); - } - - if (isset($indexXml['name'])) { - $metadata->table['indexes'][(string) $indexXml['name']] = $index; - } else { - $metadata->table['indexes'][] = $index; - } - } - } - - // Evaluate - if (isset($xmlRoot->{'unique-constraints'})) { - $metadata->table['uniqueConstraints'] = []; - foreach ($xmlRoot->{'unique-constraints'}->{'unique-constraint'} as $uniqueXml) { - $unique = ['columns' => explode(',', (string) $uniqueXml['columns'])]; - - if (isset($uniqueXml->options)) { - $unique['options'] = $this->_parseOptions($uniqueXml->options->children()); - } - - if (isset($uniqueXml['name'])) { - $metadata->table['uniqueConstraints'][(string) $uniqueXml['name']] = $unique; - } else { - $metadata->table['uniqueConstraints'][] = $unique; - } - } - } - - if (isset($xmlRoot->options)) { - $metadata->table['options'] = $this->_parseOptions($xmlRoot->options->children()); - } - - // The mapping assignment is done in 2 times as a bug might occurs on some php/xml lib versions - // The internal SimpleXmlIterator get resetted, to this generate a duplicate field exception - $mappings = []; - // Evaluate mappings - if (isset($xmlRoot->field)) { - foreach ($xmlRoot->field as $fieldMapping) { - $mapping = $this->columnToArray($fieldMapping); - - if (isset($mapping['version'])) { - $metadata->setVersionMapping($mapping); - unset($mapping['version']); - } - - $metadata->mapField($mapping); - } - } - - if (isset($xmlRoot->embedded)) { - foreach ($xmlRoot->embedded as $embeddedMapping) { - $columnPrefix = isset($embeddedMapping['column-prefix']) - ? (string) $embeddedMapping['column-prefix'] - : null; - - $useColumnPrefix = isset($embeddedMapping['use-column-prefix']) - ? $this->evaluateBoolean($embeddedMapping['use-column-prefix']) - : true; - - $mapping = [ - 'fieldName' => (string) $embeddedMapping['name'], - 'class' => (string) $embeddedMapping['class'], - 'columnPrefix' => $useColumnPrefix ? $columnPrefix : false - ]; - - $metadata->mapEmbedded($mapping); - } - } - - foreach ($mappings as $mapping) { - if (isset($mapping['version'])) { - $metadata->setVersionMapping($mapping); - } - - $metadata->mapField($mapping); - } - - // Evaluate mappings - $associationIds = []; - foreach ($xmlRoot->id as $idElement) { - if (isset($idElement['association-key']) && $this->evaluateBoolean($idElement['association-key'])) { - $associationIds[(string) $idElement['name']] = true; - continue; - } - - $mapping = [ - 'id' => true, - 'fieldName' => (string) $idElement['name'] - ]; - - if (isset($idElement['type'])) { - $mapping['type'] = (string) $idElement['type']; - } - - if (isset($idElement['length'])) { - $mapping['length'] = (string) $idElement['length']; - } - - if (isset($idElement['column'])) { - $mapping['columnName'] = (string) $idElement['column']; - } - - if (isset($idElement['column-definition'])) { - $mapping['columnDefinition'] = (string) $idElement['column-definition']; - } - - if (isset($idElement->options)) { - $mapping['options'] = $this->_parseOptions($idElement->options->children()); - } - - $metadata->mapField($mapping); - - if (isset($idElement->generator)) { - $strategy = isset($idElement->generator['strategy']) ? - (string) $idElement->generator['strategy'] : 'AUTO'; - $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' - . $strategy)); - } - - // Check for SequenceGenerator/TableGenerator definition - if (isset($idElement->{'sequence-generator'})) { - $seqGenerator = $idElement->{'sequence-generator'}; - $metadata->setSequenceGeneratorDefinition( - [ - 'sequenceName' => (string) $seqGenerator['sequence-name'], - 'allocationSize' => (string) $seqGenerator['allocation-size'], - 'initialValue' => (string) $seqGenerator['initial-value'] - ] - ); - } else if (isset($idElement->{'custom-id-generator'})) { - $customGenerator = $idElement->{'custom-id-generator'}; - $metadata->setCustomGeneratorDefinition( - [ - 'class' => (string) $customGenerator['class'] - ] - ); - } else if (isset($idElement->{'table-generator'})) { - throw MappingException::tableIdGeneratorNotImplemented($className); - } - } - - // Evaluate mappings - if (isset($xmlRoot->{'one-to-one'})) { - foreach ($xmlRoot->{'one-to-one'} as $oneToOneElement) { - $mapping = [ - 'fieldName' => (string) $oneToOneElement['field'], - 'targetEntity' => (string) $oneToOneElement['target-entity'] - ]; - - if (isset($associationIds[$mapping['fieldName']])) { - $mapping['id'] = true; - } - - if (isset($oneToOneElement['fetch'])) { - $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string) $oneToOneElement['fetch']); - } - - if (isset($oneToOneElement['mapped-by'])) { - $mapping['mappedBy'] = (string) $oneToOneElement['mapped-by']; - } else { - if (isset($oneToOneElement['inversed-by'])) { - $mapping['inversedBy'] = (string) $oneToOneElement['inversed-by']; - } - $joinColumns = []; - - if (isset($oneToOneElement->{'join-column'})) { - $joinColumns[] = $this->joinColumnToArray($oneToOneElement->{'join-column'}); - } else if (isset($oneToOneElement->{'join-columns'})) { - foreach ($oneToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { - $joinColumns[] = $this->joinColumnToArray($joinColumnElement); - } - } - - $mapping['joinColumns'] = $joinColumns; - } - - if (isset($oneToOneElement->cascade)) { - $mapping['cascade'] = $this->_getCascadeMappings($oneToOneElement->cascade); - } - - if (isset($oneToOneElement['orphan-removal'])) { - $mapping['orphanRemoval'] = $this->evaluateBoolean($oneToOneElement['orphan-removal']); - } - - // Evaluate second level cache - if (isset($oneToOneElement->cache)) { - $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToOneElement->cache)); - } - - $metadata->mapOneToOne($mapping); - } - } - - // Evaluate mappings - if (isset($xmlRoot->{'one-to-many'})) { - foreach ($xmlRoot->{'one-to-many'} as $oneToManyElement) { - $mapping = [ - 'fieldName' => (string) $oneToManyElement['field'], - 'targetEntity' => (string) $oneToManyElement['target-entity'], - 'mappedBy' => (string) $oneToManyElement['mapped-by'] - ]; - - if (isset($oneToManyElement['fetch'])) { - $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string) $oneToManyElement['fetch']); - } - - if (isset($oneToManyElement->cascade)) { - $mapping['cascade'] = $this->_getCascadeMappings($oneToManyElement->cascade); - } - - if (isset($oneToManyElement['orphan-removal'])) { - $mapping['orphanRemoval'] = $this->evaluateBoolean($oneToManyElement['orphan-removal']); - } - - if (isset($oneToManyElement->{'order-by'})) { - $orderBy = []; - foreach ($oneToManyElement->{'order-by'}->{'order-by-field'} as $orderByField) { - $orderBy[(string) $orderByField['name']] = isset($orderByField['direction']) - ? (string) $orderByField['direction'] - : Criteria::ASC - ; - } - $mapping['orderBy'] = $orderBy; - } - - if (isset($oneToManyElement['index-by'])) { - $mapping['indexBy'] = (string) $oneToManyElement['index-by']; - } else if (isset($oneToManyElement->{'index-by'})) { - throw new \InvalidArgumentException(" is not a valid tag"); - } - - // Evaluate second level cache - if (isset($oneToManyElement->cache)) { - $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToManyElement->cache)); - } - - $metadata->mapOneToMany($mapping); - } - } - - // Evaluate mappings - if (isset($xmlRoot->{'many-to-one'})) { - foreach ($xmlRoot->{'many-to-one'} as $manyToOneElement) { - $mapping = [ - 'fieldName' => (string) $manyToOneElement['field'], - 'targetEntity' => (string) $manyToOneElement['target-entity'] - ]; - - if (isset($associationIds[$mapping['fieldName']])) { - $mapping['id'] = true; - } - - if (isset($manyToOneElement['fetch'])) { - $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string) $manyToOneElement['fetch']); - } - - if (isset($manyToOneElement['inversed-by'])) { - $mapping['inversedBy'] = (string) $manyToOneElement['inversed-by']; - } - - $joinColumns = []; - - if (isset($manyToOneElement->{'join-column'})) { - $joinColumns[] = $this->joinColumnToArray($manyToOneElement->{'join-column'}); - } else if (isset($manyToOneElement->{'join-columns'})) { - foreach ($manyToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { - $joinColumns[] = $this->joinColumnToArray($joinColumnElement); - } - } - - $mapping['joinColumns'] = $joinColumns; - - if (isset($manyToOneElement->cascade)) { - $mapping['cascade'] = $this->_getCascadeMappings($manyToOneElement->cascade); - } - - // Evaluate second level cache - if (isset($manyToOneElement->cache)) { - $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToOneElement->cache)); - } - - $metadata->mapManyToOne($mapping); - - } - } - - // Evaluate mappings - if (isset($xmlRoot->{'many-to-many'})) { - foreach ($xmlRoot->{'many-to-many'} as $manyToManyElement) { - $mapping = [ - 'fieldName' => (string) $manyToManyElement['field'], - 'targetEntity' => (string) $manyToManyElement['target-entity'] - ]; - - if (isset($manyToManyElement['fetch'])) { - $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string) $manyToManyElement['fetch']); - } - - if (isset($manyToManyElement['orphan-removal'])) { - $mapping['orphanRemoval'] = $this->evaluateBoolean($manyToManyElement['orphan-removal']); - } - - if (isset($manyToManyElement['mapped-by'])) { - $mapping['mappedBy'] = (string) $manyToManyElement['mapped-by']; - } else if (isset($manyToManyElement->{'join-table'})) { - if (isset($manyToManyElement['inversed-by'])) { - $mapping['inversedBy'] = (string) $manyToManyElement['inversed-by']; - } - - $joinTableElement = $manyToManyElement->{'join-table'}; - $joinTable = [ - 'name' => (string) $joinTableElement['name'] - ]; - - if (isset($joinTableElement['schema'])) { - $joinTable['schema'] = (string) $joinTableElement['schema']; - } - - foreach ($joinTableElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { - $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); - } - - foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} as $joinColumnElement) { - $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); - } - - $mapping['joinTable'] = $joinTable; - } - - if (isset($manyToManyElement->cascade)) { - $mapping['cascade'] = $this->_getCascadeMappings($manyToManyElement->cascade); - } - - if (isset($manyToManyElement->{'order-by'})) { - $orderBy = []; - foreach ($manyToManyElement->{'order-by'}->{'order-by-field'} as $orderByField) { - $orderBy[(string) $orderByField['name']] = isset($orderByField['direction']) - ? (string) $orderByField['direction'] - : Criteria::ASC; - } - $mapping['orderBy'] = $orderBy; - } - - if (isset($manyToManyElement['index-by'])) { - $mapping['indexBy'] = (string) $manyToManyElement['index-by']; - } else if (isset($manyToManyElement->{'index-by'})) { - throw new \InvalidArgumentException(" is not a valid tag"); - } - - // Evaluate second level cache - if (isset($manyToManyElement->cache)) { - $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToManyElement->cache)); - } - - $metadata->mapManyToMany($mapping); - } - } - - // Evaluate association-overrides - if (isset($xmlRoot->{'attribute-overrides'})) { - foreach ($xmlRoot->{'attribute-overrides'}->{'attribute-override'} as $overrideElement) { - $fieldName = (string) $overrideElement['name']; - foreach ($overrideElement->field as $field) { - $mapping = $this->columnToArray($field); - $mapping['fieldName'] = $fieldName; - $metadata->setAttributeOverride($fieldName, $mapping); - } - } - } - - // Evaluate association-overrides - if (isset($xmlRoot->{'association-overrides'})) { - foreach ($xmlRoot->{'association-overrides'}->{'association-override'} as $overrideElement) { - $fieldName = (string) $overrideElement['name']; - $override = []; - - // Check for join-columns - if (isset($overrideElement->{'join-columns'})) { - $joinColumns = []; - foreach ($overrideElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { - $joinColumns[] = $this->joinColumnToArray($joinColumnElement); - } - $override['joinColumns'] = $joinColumns; - } - - // Check for join-table - if ($overrideElement->{'join-table'}) { - $joinTable = null; - $joinTableElement = $overrideElement->{'join-table'}; - - $joinTable = [ - 'name' => (string) $joinTableElement['name'], - 'schema' => (string) $joinTableElement['schema'] - ]; - - if (isset($joinTableElement->{'join-columns'})) { - foreach ($joinTableElement->{'join-columns'}->{'join-column'} as $joinColumnElement) { - $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); - } - } - - if (isset($joinTableElement->{'inverse-join-columns'})) { - foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} as $joinColumnElement) { - $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); - } - } - - $override['joinTable'] = $joinTable; - } - - // Check for inversed-by - if (isset($overrideElement->{'inversed-by'})) { - $override['inversedBy'] = (string) $overrideElement->{'inversed-by'}['name']; - } - - // Check for `fetch` - if (isset($overrideElement['fetch'])) { - $override['fetch'] = constant(Metadata::class . '::FETCH_' . (string) $overrideElement['fetch']); - } - - $metadata->setAssociationOverride($fieldName, $override); - } - } - - // Evaluate - if (isset($xmlRoot->{'lifecycle-callbacks'})) { - foreach ($xmlRoot->{'lifecycle-callbacks'}->{'lifecycle-callback'} as $lifecycleCallback) { - $metadata->addLifecycleCallback((string) $lifecycleCallback['method'], constant('Doctrine\ORM\Events::' . (string) $lifecycleCallback['type'])); - } - } - - // Evaluate entity listener - if (isset($xmlRoot->{'entity-listeners'})) { - foreach ($xmlRoot->{'entity-listeners'}->{'entity-listener'} as $listenerElement) { - $className = (string) $listenerElement['class']; - // Evaluate the listener using naming convention. - if ($listenerElement->count() === 0) { - EntityListenerBuilder::bindEntityListener($metadata, $className); - - continue; - } - - foreach ($listenerElement as $callbackElement) { - $eventName = (string) $callbackElement['type']; - $methodName = (string) $callbackElement['method']; - - $metadata->addEntityListener($eventName, $className, $methodName); - } - } - } - } - - /** - * Parses (nested) option elements. - * - * @param SimpleXMLElement $options The XML element. - * - * @return array The options array. - */ - private function _parseOptions(SimpleXMLElement $options) - { - $array = []; - - /* @var $option SimpleXMLElement */ - foreach ($options as $option) { - if ($option->count()) { - $value = $this->_parseOptions($option->children()); - } else { - $value = (string) $option; - } - - $attributes = $option->attributes(); - - if (isset($attributes->name)) { - $nameAttribute = (string) $attributes->name; - $array[$nameAttribute] = in_array($nameAttribute, ['unsigned', 'fixed']) - ? $this->evaluateBoolean($value) - : $value; - } else { - $array[] = $value; - } - } - - return $array; - } - - /** - * Constructs a joinColumn mapping array based on the information - * found in the given SimpleXMLElement. - * - * @param SimpleXMLElement $joinColumnElement The XML element. - * - * @return array The mapping array. - */ - private function joinColumnToArray(SimpleXMLElement $joinColumnElement) - { - $joinColumn = [ - 'name' => (string) $joinColumnElement['name'], - 'referencedColumnName' => (string) $joinColumnElement['referenced-column-name'] - ]; - - if (isset($joinColumnElement['unique'])) { - $joinColumn['unique'] = $this->evaluateBoolean($joinColumnElement['unique']); - } - - if (isset($joinColumnElement['nullable'])) { - $joinColumn['nullable'] = $this->evaluateBoolean($joinColumnElement['nullable']); - } - - if (isset($joinColumnElement['on-delete'])) { - $joinColumn['onDelete'] = (string) $joinColumnElement['on-delete']; - } - - if (isset($joinColumnElement['column-definition'])) { - $joinColumn['columnDefinition'] = (string) $joinColumnElement['column-definition']; - } - - return $joinColumn; - } - - /** - * Parses the given field as array. - * - * @param SimpleXMLElement $fieldMapping - * - * @return array - */ - private function columnToArray(SimpleXMLElement $fieldMapping) - { - $mapping = [ - 'fieldName' => (string) $fieldMapping['name'], - ]; - - if (isset($fieldMapping['type'])) { - $mapping['type'] = (string) $fieldMapping['type']; - } - - if (isset($fieldMapping['column'])) { - $mapping['columnName'] = (string) $fieldMapping['column']; - } - - if (isset($fieldMapping['length'])) { - $mapping['length'] = (int) $fieldMapping['length']; - } - - if (isset($fieldMapping['precision'])) { - $mapping['precision'] = (int) $fieldMapping['precision']; - } - - if (isset($fieldMapping['scale'])) { - $mapping['scale'] = (int) $fieldMapping['scale']; - } - - if (isset($fieldMapping['unique'])) { - $mapping['unique'] = $this->evaluateBoolean($fieldMapping['unique']); - } - - if (isset($fieldMapping['nullable'])) { - $mapping['nullable'] = $this->evaluateBoolean($fieldMapping['nullable']); - } - - if (isset($fieldMapping['version']) && $fieldMapping['version']) { - $mapping['version'] = $this->evaluateBoolean($fieldMapping['version']); - } - - if (isset($fieldMapping['column-definition'])) { - $mapping['columnDefinition'] = (string) $fieldMapping['column-definition']; - } - - if (isset($fieldMapping->options)) { - $mapping['options'] = $this->_parseOptions($fieldMapping->options->children()); - } - - return $mapping; - } - - /** - * Parse / Normalize the cache configuration - * - * @param SimpleXMLElement $cacheMapping - * - * @return array - */ - private function cacheToArray(SimpleXMLElement $cacheMapping) - { - $region = isset($cacheMapping['region']) ? (string) $cacheMapping['region'] : null; - $usage = isset($cacheMapping['usage']) ? strtoupper($cacheMapping['usage']) : null; - - if ($usage && ! defined('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage)) { - throw new \InvalidArgumentException(sprintf('Invalid cache usage "%s"', $usage)); - } - - if ($usage) { - $usage = constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage); - } - - return [ - 'usage' => $usage, - 'region' => $region, - ]; - } - - /** - * Gathers a list of cascade options found in the given cascade element. - * - * @param SimpleXMLElement $cascadeElement The cascade element. - * - * @return array The list of cascade options. - */ - private function _getCascadeMappings(SimpleXMLElement $cascadeElement) - { - $cascades = []; - /* @var $action SimpleXmlElement */ - foreach ($cascadeElement->children() as $action) { - // According to the JPA specifications, XML uses "cascade-persist" - // instead of "persist". Here, both variations - // are supported because both YAML and Annotation use "persist" - // and we want to make sure that this driver doesn't need to know - // anything about the supported cascading actions - $cascades[] = str_replace('cascade-', '', $action->getName()); - } - - return $cascades; - } - - /** - * {@inheritDoc} - */ - protected function loadMappingFile($file) - { - $result = []; - // Note: we do not use `simplexml_load_file()` because of https://bugs.php.net/bug.php?id=62577 - $xmlElement = simplexml_load_string(file_get_contents($file)); - - if (isset($xmlElement->entity)) { - foreach ($xmlElement->entity as $entityElement) { - $entityName = (string) $entityElement['name']; - $result[$entityName] = $entityElement; - } - } else if (isset($xmlElement->{'mapped-superclass'})) { - foreach ($xmlElement->{'mapped-superclass'} as $mappedSuperClass) { - $className = (string) $mappedSuperClass['name']; - $result[$className] = $mappedSuperClass; - } - } else if (isset($xmlElement->embeddable)) { - foreach ($xmlElement->embeddable as $embeddableElement) { - $embeddableName = (string) $embeddableElement['name']; - $result[$embeddableName] = $embeddableElement; - } - } - - return $result; - } - - /** - * @param mixed $element - * - * @return bool - */ - protected function evaluateBoolean($element) - { - $flag = (string) $element; - - return ($flag == "true" || $flag == "1"); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php deleted file mode 100644 index 05339ec..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php +++ /dev/null @@ -1,819 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Driver; - -use Doctrine\Common\Persistence\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder; -use Doctrine\Common\Persistence\Mapping\Driver\FileDriver; -use Doctrine\ORM\Mapping\ClassMetadata as Metadata; -use Doctrine\ORM\Mapping\MappingException; -use Symfony\Component\Yaml\Yaml; -use function trigger_error; - -/** - * The YamlDriver reads the mapping metadata from yaml schema files. - * - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan H. Wage - * @author Roman Borschel - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class YamlDriver extends FileDriver -{ - const DEFAULT_FILE_EXTENSION = '.dcm.yml'; - - /** - * {@inheritDoc} - */ - public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION) - { - @trigger_error( - 'YAML mapping driver is deprecated and will be removed in Doctrine ORM 3.0, please migrate to annotation or XML driver.', - E_USER_DEPRECATED - ); - - parent::__construct($locator, $fileExtension); - } - - /** - * {@inheritDoc} - */ - public function loadMetadataForClass($className, ClassMetadata $metadata) - { - /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */ - $element = $this->getElement($className); - - if ($element['type'] == 'entity') { - if (isset($element['repositoryClass'])) { - $metadata->setCustomRepositoryClass($element['repositoryClass']); - } - if (isset($element['readOnly']) && $element['readOnly'] == true) { - $metadata->markReadOnly(); - } - } else if ($element['type'] == 'mappedSuperclass') { - $metadata->setCustomRepositoryClass( - $element['repositoryClass'] ?? null - ); - $metadata->isMappedSuperclass = true; - } else if ($element['type'] == 'embeddable') { - $metadata->isEmbeddedClass = true; - } else { - throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className); - } - - // Evaluate root level properties - $primaryTable = []; - - if (isset($element['table'])) { - $primaryTable['name'] = $element['table']; - } - - if (isset($element['schema'])) { - $primaryTable['schema'] = $element['schema']; - } - - // Evaluate second level cache - if (isset($element['cache'])) { - $metadata->enableCache($this->cacheToArray($element['cache'])); - } - - $metadata->setPrimaryTable($primaryTable); - - // Evaluate named queries - if (isset($element['namedQueries'])) { - foreach ($element['namedQueries'] as $name => $queryMapping) { - if (is_string($queryMapping)) { - $queryMapping = ['query' => $queryMapping]; - } - - if ( ! isset($queryMapping['name'])) { - $queryMapping['name'] = $name; - } - - $metadata->addNamedQuery($queryMapping); - } - } - - // Evaluate named native queries - if (isset($element['namedNativeQueries'])) { - foreach ($element['namedNativeQueries'] as $name => $mappingElement) { - if (!isset($mappingElement['name'])) { - $mappingElement['name'] = $name; - } - $metadata->addNamedNativeQuery( - [ - 'name' => $mappingElement['name'], - 'query' => $mappingElement['query'] ?? null, - 'resultClass' => $mappingElement['resultClass'] ?? null, - 'resultSetMapping' => $mappingElement['resultSetMapping'] ?? null, - ] - ); - } - } - - // Evaluate sql result set mappings - if (isset($element['sqlResultSetMappings'])) { - foreach ($element['sqlResultSetMappings'] as $name => $resultSetMapping) { - if (!isset($resultSetMapping['name'])) { - $resultSetMapping['name'] = $name; - } - - $entities = []; - $columns = []; - if (isset($resultSetMapping['entityResult'])) { - foreach ($resultSetMapping['entityResult'] as $entityResultElement) { - $entityResult = [ - 'fields' => [], - 'entityClass' => $entityResultElement['entityClass'] ?? null, - 'discriminatorColumn' => $entityResultElement['discriminatorColumn'] ?? null, - ]; - - if (isset($entityResultElement['fieldResult'])) { - foreach ($entityResultElement['fieldResult'] as $fieldResultElement) { - $entityResult['fields'][] = [ - 'name' => $fieldResultElement['name'] ?? null, - 'column' => $fieldResultElement['column'] ?? null, - ]; - } - } - - $entities[] = $entityResult; - } - } - - - if (isset($resultSetMapping['columnResult'])) { - foreach ($resultSetMapping['columnResult'] as $columnResultAnnot) { - $columns[] = [ - 'name' => $columnResultAnnot['name'] ?? null, - ]; - } - } - - $metadata->addSqlResultSetMapping( - [ - 'name' => $resultSetMapping['name'], - 'entities' => $entities, - 'columns' => $columns - ] - ); - } - } - - if (isset($element['inheritanceType'])) { - $metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . strtoupper($element['inheritanceType']))); - - if ($metadata->inheritanceType != Metadata::INHERITANCE_TYPE_NONE) { - // Evaluate discriminatorColumn - if (isset($element['discriminatorColumn'])) { - $discrColumn = $element['discriminatorColumn']; - $metadata->setDiscriminatorColumn( - [ - 'name' => isset($discrColumn['name']) ? (string) $discrColumn['name'] : null, - 'type' => isset($discrColumn['type']) ? (string) $discrColumn['type'] : 'string', - 'length' => isset($discrColumn['length']) ? (string) $discrColumn['length'] : 255, - 'columnDefinition' => isset($discrColumn['columnDefinition']) ? (string) $discrColumn['columnDefinition'] : null - ] - ); - } else { - $metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]); - } - - // Evaluate discriminatorMap - if (isset($element['discriminatorMap'])) { - $metadata->setDiscriminatorMap($element['discriminatorMap']); - } - } - } - - - // Evaluate changeTrackingPolicy - if (isset($element['changeTrackingPolicy'])) { - $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_' - . strtoupper($element['changeTrackingPolicy']))); - } - - // Evaluate indexes - if (isset($element['indexes'])) { - foreach ($element['indexes'] as $name => $indexYml) { - if ( ! isset($indexYml['name'])) { - $indexYml['name'] = $name; - } - - if (is_string($indexYml['columns'])) { - $index = ['columns' => array_map('trim', explode(',', $indexYml['columns']))]; - } else { - $index = ['columns' => $indexYml['columns']]; - } - - if (isset($indexYml['flags'])) { - if (is_string($indexYml['flags'])) { - $index['flags'] = array_map('trim', explode(',', $indexYml['flags'])); - } else { - $index['flags'] = $indexYml['flags']; - } - } - - if (isset($indexYml['options'])) { - $index['options'] = $indexYml['options']; - } - - $metadata->table['indexes'][$indexYml['name']] = $index; - } - } - - // Evaluate uniqueConstraints - if (isset($element['uniqueConstraints'])) { - foreach ($element['uniqueConstraints'] as $name => $uniqueYml) { - if ( ! isset($uniqueYml['name'])) { - $uniqueYml['name'] = $name; - } - - if (is_string($uniqueYml['columns'])) { - $unique = ['columns' => array_map('trim', explode(',', $uniqueYml['columns']))]; - } else { - $unique = ['columns' => $uniqueYml['columns']]; - } - - if (isset($uniqueYml['options'])) { - $unique['options'] = $uniqueYml['options']; - } - - $metadata->table['uniqueConstraints'][$uniqueYml['name']] = $unique; - } - } - - if (isset($element['options'])) { - $metadata->table['options'] = $element['options']; - } - - $associationIds = []; - if (isset($element['id'])) { - // Evaluate identifier settings - foreach ($element['id'] as $name => $idElement) { - if (isset($idElement['associationKey']) && $idElement['associationKey'] == true) { - $associationIds[$name] = true; - continue; - } - - $mapping = [ - 'id' => true, - 'fieldName' => $name - ]; - - if (isset($idElement['type'])) { - $mapping['type'] = $idElement['type']; - } - - if (isset($idElement['column'])) { - $mapping['columnName'] = $idElement['column']; - } - - if (isset($idElement['length'])) { - $mapping['length'] = $idElement['length']; - } - - if (isset($idElement['columnDefinition'])) { - $mapping['columnDefinition'] = $idElement['columnDefinition']; - } - - if (isset($idElement['options'])) { - $mapping['options'] = $idElement['options']; - } - - $metadata->mapField($mapping); - - if (isset($idElement['generator'])) { - $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' - . strtoupper($idElement['generator']['strategy']))); - } - // Check for SequenceGenerator/TableGenerator definition - if (isset($idElement['sequenceGenerator'])) { - $metadata->setSequenceGeneratorDefinition($idElement['sequenceGenerator']); - } else if (isset($idElement['customIdGenerator'])) { - $customGenerator = $idElement['customIdGenerator']; - $metadata->setCustomGeneratorDefinition( - [ - 'class' => (string) $customGenerator['class'] - ] - ); - } else if (isset($idElement['tableGenerator'])) { - throw MappingException::tableIdGeneratorNotImplemented($className); - } - } - } - - // Evaluate fields - if (isset($element['fields'])) { - foreach ($element['fields'] as $name => $fieldMapping) { - - $mapping = $this->columnToArray($name, $fieldMapping); - - if (isset($fieldMapping['id'])) { - $mapping['id'] = true; - if (isset($fieldMapping['generator']['strategy'])) { - $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' - . strtoupper($fieldMapping['generator']['strategy']))); - } - } - - if (isset($mapping['version'])) { - $metadata->setVersionMapping($mapping); - unset($mapping['version']); - } - - $metadata->mapField($mapping); - } - } - - if (isset($element['embedded'])) { - foreach ($element['embedded'] as $name => $embeddedMapping) { - $mapping = [ - 'fieldName' => $name, - 'class' => $embeddedMapping['class'], - 'columnPrefix' => $embeddedMapping['columnPrefix'] ?? null, - ]; - $metadata->mapEmbedded($mapping); - } - } - - // Evaluate oneToOne relationships - if (isset($element['oneToOne'])) { - foreach ($element['oneToOne'] as $name => $oneToOneElement) { - $mapping = [ - 'fieldName' => $name, - 'targetEntity' => $oneToOneElement['targetEntity'] - ]; - - if (isset($associationIds[$mapping['fieldName']])) { - $mapping['id'] = true; - } - - if (isset($oneToOneElement['fetch'])) { - $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToOneElement['fetch']); - } - - if (isset($oneToOneElement['mappedBy'])) { - $mapping['mappedBy'] = $oneToOneElement['mappedBy']; - } else { - if (isset($oneToOneElement['inversedBy'])) { - $mapping['inversedBy'] = $oneToOneElement['inversedBy']; - } - - $joinColumns = []; - - if (isset($oneToOneElement['joinColumn'])) { - $joinColumns[] = $this->joinColumnToArray($oneToOneElement['joinColumn']); - } else if (isset($oneToOneElement['joinColumns'])) { - foreach ($oneToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $joinColumnName; - } - - $joinColumns[] = $this->joinColumnToArray($joinColumnElement); - } - } - - $mapping['joinColumns'] = $joinColumns; - } - - if (isset($oneToOneElement['cascade'])) { - $mapping['cascade'] = $oneToOneElement['cascade']; - } - - if (isset($oneToOneElement['orphanRemoval'])) { - $mapping['orphanRemoval'] = (bool) $oneToOneElement['orphanRemoval']; - } - - // Evaluate second level cache - if (isset($oneToOneElement['cache'])) { - $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToOneElement['cache'])); - } - - $metadata->mapOneToOne($mapping); - } - } - - // Evaluate oneToMany relationships - if (isset($element['oneToMany'])) { - foreach ($element['oneToMany'] as $name => $oneToManyElement) { - $mapping = [ - 'fieldName' => $name, - 'targetEntity' => $oneToManyElement['targetEntity'], - 'mappedBy' => $oneToManyElement['mappedBy'] - ]; - - if (isset($oneToManyElement['fetch'])) { - $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToManyElement['fetch']); - } - - if (isset($oneToManyElement['cascade'])) { - $mapping['cascade'] = $oneToManyElement['cascade']; - } - - if (isset($oneToManyElement['orphanRemoval'])) { - $mapping['orphanRemoval'] = (bool) $oneToManyElement['orphanRemoval']; - } - - if (isset($oneToManyElement['orderBy'])) { - $mapping['orderBy'] = $oneToManyElement['orderBy']; - } - - if (isset($oneToManyElement['indexBy'])) { - $mapping['indexBy'] = $oneToManyElement['indexBy']; - } - - - // Evaluate second level cache - if (isset($oneToManyElement['cache'])) { - $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToManyElement['cache'])); - } - - $metadata->mapOneToMany($mapping); - } - } - - // Evaluate manyToOne relationships - if (isset($element['manyToOne'])) { - foreach ($element['manyToOne'] as $name => $manyToOneElement) { - $mapping = [ - 'fieldName' => $name, - 'targetEntity' => $manyToOneElement['targetEntity'] - ]; - - if (isset($associationIds[$mapping['fieldName']])) { - $mapping['id'] = true; - } - - if (isset($manyToOneElement['fetch'])) { - $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToOneElement['fetch']); - } - - if (isset($manyToOneElement['inversedBy'])) { - $mapping['inversedBy'] = $manyToOneElement['inversedBy']; - } - - $joinColumns = []; - - if (isset($manyToOneElement['joinColumn'])) { - $joinColumns[] = $this->joinColumnToArray($manyToOneElement['joinColumn']); - } else if (isset($manyToOneElement['joinColumns'])) { - foreach ($manyToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $joinColumnName; - } - - $joinColumns[] = $this->joinColumnToArray($joinColumnElement); - } - } - - $mapping['joinColumns'] = $joinColumns; - - if (isset($manyToOneElement['cascade'])) { - $mapping['cascade'] = $manyToOneElement['cascade']; - } - - // Evaluate second level cache - if (isset($manyToOneElement['cache'])) { - $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToOneElement['cache'])); - } - - $metadata->mapManyToOne($mapping); - } - } - - // Evaluate manyToMany relationships - if (isset($element['manyToMany'])) { - foreach ($element['manyToMany'] as $name => $manyToManyElement) { - $mapping = [ - 'fieldName' => $name, - 'targetEntity' => $manyToManyElement['targetEntity'] - ]; - - if (isset($manyToManyElement['fetch'])) { - $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToManyElement['fetch']); - } - - if (isset($manyToManyElement['mappedBy'])) { - $mapping['mappedBy'] = $manyToManyElement['mappedBy']; - } else if (isset($manyToManyElement['joinTable'])) { - - $joinTableElement = $manyToManyElement['joinTable']; - $joinTable = [ - 'name' => $joinTableElement['name'] - ]; - - if (isset($joinTableElement['schema'])) { - $joinTable['schema'] = $joinTableElement['schema']; - } - - if (isset($joinTableElement['joinColumns'])) { - foreach ($joinTableElement['joinColumns'] as $joinColumnName => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $joinColumnName; - } - $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); - } - } - - if (isset($joinTableElement['inverseJoinColumns'])) { - foreach ($joinTableElement['inverseJoinColumns'] as $joinColumnName => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $joinColumnName; - } - $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); - } - } - - $mapping['joinTable'] = $joinTable; - } - - if (isset($manyToManyElement['inversedBy'])) { - $mapping['inversedBy'] = $manyToManyElement['inversedBy']; - } - - if (isset($manyToManyElement['cascade'])) { - $mapping['cascade'] = $manyToManyElement['cascade']; - } - - if (isset($manyToManyElement['orderBy'])) { - $mapping['orderBy'] = $manyToManyElement['orderBy']; - } - - if (isset($manyToManyElement['indexBy'])) { - $mapping['indexBy'] = $manyToManyElement['indexBy']; - } - - if (isset($manyToManyElement['orphanRemoval'])) { - $mapping['orphanRemoval'] = (bool) $manyToManyElement['orphanRemoval']; - } - - // Evaluate second level cache - if (isset($manyToManyElement['cache'])) { - $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToManyElement['cache'])); - } - - $metadata->mapManyToMany($mapping); - } - } - - // Evaluate associationOverride - if (isset($element['associationOverride']) && is_array($element['associationOverride'])) { - - foreach ($element['associationOverride'] as $fieldName => $associationOverrideElement) { - $override = []; - - // Check for joinColumn - if (isset($associationOverrideElement['joinColumn'])) { - $joinColumns = []; - foreach ($associationOverrideElement['joinColumn'] as $name => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $name; - } - $joinColumns[] = $this->joinColumnToArray($joinColumnElement); - } - $override['joinColumns'] = $joinColumns; - } - - // Check for joinTable - if (isset($associationOverrideElement['joinTable'])) { - - $joinTableElement = $associationOverrideElement['joinTable']; - $joinTable = [ - 'name' => $joinTableElement['name'] - ]; - - if (isset($joinTableElement['schema'])) { - $joinTable['schema'] = $joinTableElement['schema']; - } - - foreach ($joinTableElement['joinColumns'] as $name => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $name; - } - - $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement); - } - - foreach ($joinTableElement['inverseJoinColumns'] as $name => $joinColumnElement) { - if ( ! isset($joinColumnElement['name'])) { - $joinColumnElement['name'] = $name; - } - - $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement); - } - - $override['joinTable'] = $joinTable; - } - - // Check for inversedBy - if (isset($associationOverrideElement['inversedBy'])) { - $override['inversedBy'] = (string) $associationOverrideElement['inversedBy']; - } - - // Check for `fetch` - if (isset($associationOverrideElement['fetch'])) { - $override['fetch'] = constant(Metadata::class . '::FETCH_' . $associationOverrideElement['fetch']); - } - - $metadata->setAssociationOverride($fieldName, $override); - } - } - - // Evaluate associationOverride - if (isset($element['attributeOverride']) && is_array($element['attributeOverride'])) { - - foreach ($element['attributeOverride'] as $fieldName => $attributeOverrideElement) { - $mapping = $this->columnToArray($fieldName, $attributeOverrideElement); - $metadata->setAttributeOverride($fieldName, $mapping); - } - } - - // Evaluate lifeCycleCallbacks - if (isset($element['lifecycleCallbacks'])) { - foreach ($element['lifecycleCallbacks'] as $type => $methods) { - foreach ($methods as $method) { - $metadata->addLifecycleCallback($method, constant('Doctrine\ORM\Events::' . $type)); - } - } - } - - // Evaluate entityListeners - if (isset($element['entityListeners'])) { - foreach ($element['entityListeners'] as $className => $entityListener) { - // Evaluate the listener using naming convention. - if (empty($entityListener)) { - EntityListenerBuilder::bindEntityListener($metadata, $className); - - continue; - } - - foreach ($entityListener as $eventName => $callbackElement) { - foreach ($callbackElement as $methodName) { - $metadata->addEntityListener($eventName, $className, $methodName); - } - } - } - } - } - - /** - * Constructs a joinColumn mapping array based on the information - * found in the given join column element. - * - * @param array $joinColumnElement The array join column element. - * - * @return array The mapping array. - */ - private function joinColumnToArray($joinColumnElement) - { - $joinColumn = []; - if (isset($joinColumnElement['referencedColumnName'])) { - $joinColumn['referencedColumnName'] = (string) $joinColumnElement['referencedColumnName']; - } - - if (isset($joinColumnElement['name'])) { - $joinColumn['name'] = (string) $joinColumnElement['name']; - } - - if (isset($joinColumnElement['fieldName'])) { - $joinColumn['fieldName'] = (string) $joinColumnElement['fieldName']; - } - - if (isset($joinColumnElement['unique'])) { - $joinColumn['unique'] = (bool) $joinColumnElement['unique']; - } - - if (isset($joinColumnElement['nullable'])) { - $joinColumn['nullable'] = (bool) $joinColumnElement['nullable']; - } - - if (isset($joinColumnElement['onDelete'])) { - $joinColumn['onDelete'] = $joinColumnElement['onDelete']; - } - - if (isset($joinColumnElement['columnDefinition'])) { - $joinColumn['columnDefinition'] = $joinColumnElement['columnDefinition']; - } - - return $joinColumn; - } - - /** - * Parses the given column as array. - * - * @param string $fieldName - * @param array $column - * - * @return array - */ - private function columnToArray($fieldName, $column) - { - $mapping = [ - 'fieldName' => $fieldName - ]; - - if (isset($column['type'])) { - $params = explode('(', $column['type']); - - $column['type'] = $params[0]; - $mapping['type'] = $column['type']; - - if (isset($params[1])) { - $column['length'] = (integer) substr($params[1], 0, strlen($params[1]) - 1); - } - } - - if (isset($column['column'])) { - $mapping['columnName'] = $column['column']; - } - - if (isset($column['length'])) { - $mapping['length'] = $column['length']; - } - - if (isset($column['precision'])) { - $mapping['precision'] = $column['precision']; - } - - if (isset($column['scale'])) { - $mapping['scale'] = $column['scale']; - } - - if (isset($column['unique'])) { - $mapping['unique'] = (bool) $column['unique']; - } - - if (isset($column['options'])) { - $mapping['options'] = $column['options']; - } - - if (isset($column['nullable'])) { - $mapping['nullable'] = $column['nullable']; - } - - if (isset($column['version']) && $column['version']) { - $mapping['version'] = $column['version']; - } - - if (isset($column['columnDefinition'])) { - $mapping['columnDefinition'] = $column['columnDefinition']; - } - - return $mapping; - } - - /** - * Parse / Normalize the cache configuration - * - * @param array $cacheMapping - * - * @return array - */ - private function cacheToArray($cacheMapping) - { - $region = isset($cacheMapping['region']) ? (string) $cacheMapping['region'] : null; - $usage = isset($cacheMapping['usage']) ? strtoupper($cacheMapping['usage']) : null; - - if ($usage && ! defined('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage)) { - throw new \InvalidArgumentException(sprintf('Invalid cache usage "%s"', $usage)); - } - - if ($usage) { - $usage = constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage); - } - - return [ - 'usage' => $usage, - 'region' => $region, - ]; - } - - /** - * {@inheritDoc} - */ - protected function loadMappingFile($file) - { - return Yaml::parse(file_get_contents($file)); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embeddable.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embeddable.php deleted file mode 100644 index f14bfac..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embeddable.php +++ /dev/null @@ -1,28 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("CLASS") - */ -final class Embeddable implements Annotation -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embedded.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embedded.php deleted file mode 100644 index 3733910..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Embedded.php +++ /dev/null @@ -1,38 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("PROPERTY") - */ -final class Embedded implements Annotation -{ - /** - * @Required - * @var string - */ - public $class; - - /** - * @var mixed - */ - public $columnPrefix; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Entity.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Entity.php deleted file mode 100644 index edf6ad5..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Entity.php +++ /dev/null @@ -1,37 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("CLASS") - */ -final class Entity implements Annotation -{ - /** - * @var string - */ - public $repositoryClass; - - /** - * @var boolean - */ - public $readOnly = false; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListenerResolver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListenerResolver.php deleted file mode 100644 index b0c62c8..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListenerResolver.php +++ /dev/null @@ -1,55 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * A resolver is used to instantiate an entity listener. - * - * @since 2.4 - * @author Fabio B. Silva - */ -interface EntityListenerResolver -{ - /** - * Clear all instances from the set, or a specific class when given. - * - * @param string $className The fully-qualified class name - * - * @return void - */ - function clear($className = null); - - /** - * Returns a entity listener instance for the given class name. - * - * @param string $className The fully-qualified class name - * - * @return object An entity listener - */ - function resolve($className); - - /** - * Register a entity listener instance. - * - * @param object $object An entity listener - */ - function register($object); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListeners.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListeners.php deleted file mode 100644 index ae6c912..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityListeners.php +++ /dev/null @@ -1,41 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * The EntityListeners annotation specifies the callback listener classes to be used for an entity or mapped superclass. - * The EntityListeners annotation may be applied to an entity class or mapped superclass. - * - * @author Fabio B. Silva - * @since 2.4 - * - * @Annotation - * @Target("CLASS") - */ -final class EntityListeners implements Annotation -{ - /** - * Specifies the names of the entity listeners. - * - * @var array - */ - public $value = []; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityResult.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityResult.php deleted file mode 100644 index d8b0573..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/EntityResult.php +++ /dev/null @@ -1,56 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * References an entity in the SELECT clause of a SQL query. - * If this annotation is used, the SQL statement should select all of the columns that are mapped to the entity object. - * This should include foreign key columns to related entities. - * The results obtained when insufficient data is available are undefined. - * - * @author Fabio B. Silva - * @since 2.3 - * - * @Annotation - * @Target("ANNOTATION") - */ -final class EntityResult implements Annotation -{ - /** - * The class of the result. - * - * @var string - */ - public $entityClass; - - /** - * Maps the columns specified in the SELECT list of the query to the properties or fields of the entity class. - * - * @var array<\Doctrine\ORM\Mapping\FieldResult> - */ - public $fields = []; - - /** - * Specifies the column name of the column in the SELECT list that is used to determine the type of the entity instance. - * - * @var string - */ - public $discriminatorColumn; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/FieldResult.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/FieldResult.php deleted file mode 100644 index 5e8aa0c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/FieldResult.php +++ /dev/null @@ -1,46 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * Is used to map the columns specified in the SELECT list of the query to the properties or fields of the entity class. - * - * @author Fabio B. Silva - * @since 2.3 - * - * @Annotation - * @Target("ANNOTATION") - */ -final class FieldResult implements Annotation -{ - /** - * Name of the column in the SELECT clause. - * - * @var string - */ - public $name; - - /** - * Name of the persistent field or property of the class. - * - * @var string - */ - public $column; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/GeneratedValue.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/GeneratedValue.php deleted file mode 100644 index 27c03d4..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/GeneratedValue.php +++ /dev/null @@ -1,36 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("PROPERTY") - */ -final class GeneratedValue implements Annotation -{ - /** - * The type of Id generator. - * - * @var string - * - * @Enum({"AUTO", "SEQUENCE", "TABLE", "IDENTITY", "NONE", "UUID", "CUSTOM"}) - */ - public $strategy = 'AUTO'; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/HasLifecycleCallbacks.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/HasLifecycleCallbacks.php deleted file mode 100644 index 313ece3..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/HasLifecycleCallbacks.php +++ /dev/null @@ -1,28 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("CLASS") - */ -final class HasLifecycleCallbacks implements Annotation -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Id.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Id.php deleted file mode 100644 index 6c9bcef..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Id.php +++ /dev/null @@ -1,28 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("PROPERTY") - */ -final class Id implements Annotation -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Index.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Index.php deleted file mode 100644 index 45953a8..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Index.php +++ /dev/null @@ -1,47 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("ANNOTATION") - */ -final class Index implements Annotation -{ - /** - * @var string - */ - public $name; - - /** - * @var array - */ - public $columns; - - /** - * @var array - */ - public $flags; - - /** - * @var array - */ - public $options; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/InheritanceType.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/InheritanceType.php deleted file mode 100644 index de80336..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/InheritanceType.php +++ /dev/null @@ -1,36 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("CLASS") - */ -final class InheritanceType implements Annotation -{ - /** - * The inheritance type used by the class and its subclasses. - * - * @var string - * - * @Enum({"NONE", "JOINED", "SINGLE_TABLE", "TABLE_PER_CLASS"}) - */ - public $value; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumn.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumn.php deleted file mode 100644 index febce91..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumn.php +++ /dev/null @@ -1,64 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target({"PROPERTY","ANNOTATION"}) - */ -final class JoinColumn implements Annotation -{ - /** - * @var string - */ - public $name; - - /** - * @var string - */ - public $referencedColumnName = 'id'; - - /** - * @var boolean - */ - public $unique = false; - - /** - * @var boolean - */ - public $nullable = true; - - /** - * @var mixed - */ - public $onDelete; - - /** - * @var string - */ - public $columnDefinition; - - /** - * Field name used in non-object hydration (array/scalar). - * - * @var string - */ - public $fieldName; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumns.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumns.php deleted file mode 100644 index ae096c2..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinColumns.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("PROPERTY") - */ -final class JoinColumns implements Annotation -{ - /** - * @var array<\Doctrine\ORM\Mapping\JoinColumn> - */ - public $value; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinTable.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinTable.php deleted file mode 100644 index 879316a..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/JoinTable.php +++ /dev/null @@ -1,47 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target({"PROPERTY","ANNOTATION"}) - */ -final class JoinTable implements Annotation -{ - /** - * @var string - */ - public $name; - - /** - * @var string - */ - public $schema; - - /** - * @var array<\Doctrine\ORM\Mapping\JoinColumn> - */ - public $joinColumns = []; - - /** - * @var array<\Doctrine\ORM\Mapping\JoinColumn> - */ - public $inverseJoinColumns = []; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToMany.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToMany.php deleted file mode 100644 index ca2f53c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToMany.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("PROPERTY") - */ -final class ManyToMany implements Annotation -{ - /** - * @var string - */ - public $targetEntity; - - /** - * @var string - */ - public $mappedBy; - - /** - * @var string - */ - public $inversedBy; - - /** - * @var array - */ - public $cascade; - - /** - * The fetching strategy to use for the association. - * - * @var string - * - * @Enum({"LAZY", "EAGER", "EXTRA_LAZY"}) - */ - public $fetch = 'LAZY'; - - /** - * @var boolean - */ - public $orphanRemoval = false; - - /** - * @var string - */ - public $indexBy; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToOne.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToOne.php deleted file mode 100644 index d3414e6..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ManyToOne.php +++ /dev/null @@ -1,51 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("PROPERTY") - */ -final class ManyToOne implements Annotation -{ - /** - * @var string - */ - public $targetEntity; - - /** - * @var array - */ - public $cascade; - - /** - * The fetching strategy to use for the association. - * - * @var string - * - * @Enum({"LAZY", "EAGER", "EXTRA_LAZY"}) - */ - public $fetch = 'LAZY'; - - /** - * @var string - */ - public $inversedBy; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappedSuperclass.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappedSuperclass.php deleted file mode 100644 index 7458810..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappedSuperclass.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("CLASS") - */ -final class MappedSuperclass implements Annotation -{ - /** - * @var string - */ - public $repositoryClass; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappingException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappingException.php deleted file mode 100644 index 7dc4405..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappingException.php +++ /dev/null @@ -1,823 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * A MappingException indicates that something is wrong with the mapping setup. - * - * @since 2.0 - */ -class MappingException extends \Doctrine\ORM\ORMException -{ - /** - * @return MappingException - */ - public static function pathRequired() - { - return new self("Specifying the paths to your entities is required ". - "in the AnnotationDriver to retrieve all class names."); - } - - /** - * @param string $entityName - * - * @return MappingException - */ - public static function identifierRequired($entityName) - { - if (false !== ($parent = get_parent_class($entityName))) { - return new self(sprintf( - 'No identifier/primary key specified for Entity "%s" sub class of "%s". Every Entity must have an identifier/primary key.', - $entityName, $parent - )); - } - - return new self(sprintf( - 'No identifier/primary key specified for Entity "%s". Every Entity must have an identifier/primary key.', - $entityName - )); - - } - - /** - * @param string $entityName - * @param string $type - * - * @return MappingException - */ - public static function invalidInheritanceType($entityName, $type) - { - return new self("The inheritance type '$type' specified for '$entityName' does not exist."); - } - - /** - * @return MappingException - */ - public static function generatorNotAllowedWithCompositeId() - { - return new self("Id generators can't be used with a composite id."); - } - - /** - * @param string $entity - * - * @return MappingException - */ - public static function missingFieldName($entity) - { - return new self("The field or association mapping misses the 'fieldName' attribute in entity '$entity'."); - } - - /** - * @param string $fieldName - * - * @return MappingException - */ - public static function missingTargetEntity($fieldName) - { - return new self("The association mapping '$fieldName' misses the 'targetEntity' attribute."); - } - - /** - * @param string $fieldName - * - * @return MappingException - */ - public static function missingSourceEntity($fieldName) - { - return new self("The association mapping '$fieldName' misses the 'sourceEntity' attribute."); - } - - /** - * @param string $fieldName - * - * @return MappingException - */ - public static function missingEmbeddedClass($fieldName) - { - return new self("The embed mapping '$fieldName' misses the 'class' attribute."); - } - - /** - * @param string $entityName - * @param string $fileName - * - * @return MappingException - */ - public static function mappingFileNotFound($entityName, $fileName) - { - return new self("No mapping file found named '$fileName' for class '$entityName'."); - } - - /** - * Exception for invalid property name override. - * - * @param string $className The entity's name. - * @param string $fieldName - * - * @return MappingException - */ - public static function invalidOverrideFieldName($className, $fieldName) - { - return new self("Invalid field override named '$fieldName' for class '$className'."); - } - - /** - * Exception for invalid property type override. - * - * @param string $className The entity's name. - * @param string $fieldName - * - * @return MappingException - */ - public static function invalidOverrideFieldType($className, $fieldName) - { - return new self("The column type of attribute '$fieldName' on class '$className' could not be changed."); - } - - /** - * @param string $className - * @param string $fieldName - * - * @return MappingException - */ - public static function mappingNotFound($className, $fieldName) - { - return new self("No mapping found for field '$fieldName' on class '$className'."); - } - - /** - * @param string $className - * @param string $queryName - * - * @return MappingException - */ - public static function queryNotFound($className, $queryName) - { - return new self("No query found named '$queryName' on class '$className'."); - } - - /** - * @param string $className - * @param string $resultName - * - * @return MappingException - */ - public static function resultMappingNotFound($className, $resultName) - { - return new self("No result set mapping found named '$resultName' on class '$className'."); - } - - /** - * @param string $entity - * @param string $queryName - * - * @return MappingException - */ - public static function emptyQueryMapping($entity, $queryName) - { - return new self('Query named "'.$queryName.'" in "'.$entity.'" could not be empty.'); - } - - /** - * @param string $className - * - * @return MappingException - */ - public static function nameIsMandatoryForQueryMapping($className) - { - return new self("Query name on entity class '$className' is not defined."); - } - - /** - * @param string $entity - * @param string $queryName - * - * @return MappingException - */ - public static function missingQueryMapping($entity, $queryName) - { - return new self('Query named "'.$queryName.'" in "'.$entity.' requires a result class or result set mapping.'); - } - - /** - * @param string $entity - * @param string $resultName - * - * @return MappingException - */ - public static function missingResultSetMappingEntity($entity, $resultName) - { - return new self('Result set mapping named "'.$resultName.'" in "'.$entity.' requires a entity class name.'); - } - - /** - * @param string $entity - * @param string $resultName - * - * @return MappingException - */ - public static function missingResultSetMappingFieldName($entity, $resultName) - { - return new self('Result set mapping named "'.$resultName.'" in "'.$entity.' requires a field name.'); - } - - /** - * @param string $className - * - * @return MappingException - */ - public static function nameIsMandatoryForSqlResultSetMapping($className) - { - return new self("Result set mapping name on entity class '$className' is not defined."); - } - - /** - * @param string $fieldName - * - * @return MappingException - */ - public static function oneToManyRequiresMappedBy($fieldName) - { - return new self("OneToMany mapping on field '$fieldName' requires the 'mappedBy' attribute."); - } - - /** - * @param string $fieldName - * - * @return MappingException - */ - public static function joinTableRequired($fieldName) - { - return new self("The mapping of field '$fieldName' requires an the 'joinTable' attribute."); - } - - /** - * Called if a required option was not found but is required - * - * @param string $field Which field cannot be processed? - * @param string $expectedOption Which option is required - * @param string $hint Can optionally be used to supply a tip for common mistakes, - * e.g. "Did you think of the plural s?" - * - * @return MappingException - */ - static function missingRequiredOption($field, $expectedOption, $hint = '') - { - $message = "The mapping of field '{$field}' is invalid: The option '{$expectedOption}' is required."; - - if ( ! empty($hint)) { - $message .= ' (Hint: ' . $hint . ')'; - } - - return new self($message); - } - - /** - * Generic exception for invalid mappings. - * - * @param string $fieldName - * - * @return MappingException - */ - public static function invalidMapping($fieldName) - { - return new self("The mapping of field '$fieldName' is invalid."); - } - - /** - * Exception for reflection exceptions - adds the entity name, - * because there might be long classnames that will be shortened - * within the stacktrace - * - * @param string $entity The entity's name - * @param \ReflectionException $previousException - * - * @return MappingException - */ - public static function reflectionFailure($entity, \ReflectionException $previousException) - { - return new self('An error occurred in ' . $entity, 0, $previousException); - } - - /** - * @param string $className - * @param string $joinColumn - * - * @return MappingException - */ - public static function joinColumnMustPointToMappedField($className, $joinColumn) - { - return new self('The column ' . $joinColumn . ' must be mapped to a field in class ' - . $className . ' since it is referenced by a join column of another class.'); - } - - /** - * @param string $className - * - * @return MappingException - */ - public static function classIsNotAValidEntityOrMappedSuperClass($className) - { - if (false !== ($parent = get_parent_class($className))) { - return new self(sprintf( - 'Class "%s" sub class of "%s" is not a valid entity or mapped super class.', - $className, $parent - )); - } - - return new self(sprintf( - 'Class "%s" is not a valid entity or mapped super class.', - $className - )); - } - - /** - * @param string $className - * @param string $propertyName - * - * @return MappingException - */ - public static function propertyTypeIsRequired($className, $propertyName) - { - return new self("The attribute 'type' is required for the column description of property ".$className."::\$".$propertyName."."); - } - - /** - * @param string $className - * - * @return MappingException - */ - public static function tableIdGeneratorNotImplemented($className) - { - return new self("TableIdGenerator is not yet implemented for use with class ".$className); - } - - /** - * @param string $entity The entity's name. - * @param string $fieldName The name of the field that was already declared. - * - * @return MappingException - */ - public static function duplicateFieldMapping($entity, $fieldName) - { - return new self('Property "'.$fieldName.'" in "'.$entity.'" was already declared, but it must be declared only once'); - } - - /** - * @param string $entity - * @param string $fieldName - * - * @return MappingException - */ - public static function duplicateAssociationMapping($entity, $fieldName) - { - return new self('Property "'.$fieldName.'" in "'.$entity.'" was already declared, but it must be declared only once'); - } - - /** - * @param string $entity - * @param string $queryName - * - * @return MappingException - */ - public static function duplicateQueryMapping($entity, $queryName) - { - return new self('Query named "'.$queryName.'" in "'.$entity.'" was already declared, but it must be declared only once'); - } - - /** - * @param string $entity - * @param string $resultName - * - * @return MappingException - */ - public static function duplicateResultSetMapping($entity, $resultName) - { - return new self('Result set mapping named "'.$resultName.'" in "'.$entity.'" was already declared, but it must be declared only once'); - } - - /** - * @param string $entity - * - * @return MappingException - */ - public static function singleIdNotAllowedOnCompositePrimaryKey($entity) - { - return new self('Single id is not allowed on composite primary key in entity '.$entity); - } - - /** - * @param string $entity - * - * @return MappingException - */ - public static function noIdDefined($entity) - { - return new self('No ID defined for entity ' . $entity); - } - - /** - * @param string $entity - * @param string $fieldName - * @param string $unsupportedType - * - * @return MappingException - */ - public static function unsupportedOptimisticLockingType($entity, $fieldName, $unsupportedType) - { - return new self('Locking type "'.$unsupportedType.'" (specified in "'.$entity.'", field "'.$fieldName.'") ' - .'is not supported by Doctrine.' - ); - } - - /** - * @param string|null $path - * - * @return MappingException - */ - public static function fileMappingDriversRequireConfiguredDirectoryPath($path = null) - { - if ( ! empty($path)) { - $path = '[' . $path . ']'; - } - - return new self( - 'File mapping drivers must have a valid directory path, ' . - 'however the given path ' . $path . ' seems to be incorrect!' - ); - } - - /** - * Returns an exception that indicates that a class used in a discriminator map does not exist. - * An example would be an outdated (maybe renamed) classname. - * - * @param string $className The class that could not be found - * @param string $owningClass The class that declares the discriminator map. - * - * @return MappingException - */ - public static function invalidClassInDiscriminatorMap($className, $owningClass) - { - return new self( - "Entity class '$className' used in the discriminator map of class '$owningClass' ". - "does not exist." - ); - } - - /** - * @param string $className - * @param array $entries - * @param array $map - * - * @return MappingException - */ - public static function duplicateDiscriminatorEntry($className, array $entries, array $map) - { - return new self( - "The entries " . implode(', ', $entries) . " in discriminator map of class '" . $className . "' is duplicated. " . - "If the discriminator map is automatically generated you have to convert it to an explicit discriminator map now. " . - "The entries of the current map are: @DiscriminatorMap({" . implode(', ', array_map( - function($a, $b) { return "'$a': '$b'"; }, array_keys($map), array_values($map) - )) . "})" - ); - } - - /** - * @param string $className - * - * @return MappingException - */ - public static function missingDiscriminatorMap($className) - { - return new self("Entity class '$className' is using inheritance but no discriminator map was defined."); - } - - /** - * @param string $className - * - * @return MappingException - */ - public static function missingDiscriminatorColumn($className) - { - return new self("Entity class '$className' is using inheritance but no discriminator column was defined."); - } - - /** - * @param string $className - * @param string $type - * - * @return MappingException - */ - public static function invalidDiscriminatorColumnType($className, $type) - { - return new self("Discriminator column type on entity class '$className' is not allowed to be '$type'. 'string' or 'integer' type variables are suggested!"); - } - - /** - * @param string $className - * - * @return MappingException - */ - public static function nameIsMandatoryForDiscriminatorColumns($className) - { - return new self("Discriminator column name on entity class '$className' is not defined."); - } - - /** - * @param string $className - * @param string $fieldName - * - * @return MappingException - */ - public static function cannotVersionIdField($className, $fieldName) - { - return new self("Setting Id field '$fieldName' as versionable in entity class '$className' is not supported."); - } - - /** - * @param string $className - * @param string $fieldName - * @param string $type - * - * @return MappingException - */ - public static function sqlConversionNotAllowedForIdentifiers($className, $fieldName, $type) - { - return new self("It is not possible to set id field '$fieldName' to type '$type' in entity class '$className'. The type '$type' requires conversion SQL which is not allowed for identifiers."); - } - - /** - * @param string $className - * @param string $columnName - * - * @return MappingException - */ - public static function duplicateColumnName($className, $columnName) - { - return new self("Duplicate definition of column '".$columnName."' on entity '".$className."' in a field or discriminator column mapping."); - } - - /** - * @param string $className - * @param string $field - * - * @return MappingException - */ - public static function illegalToManyAssociationOnMappedSuperclass($className, $field) - { - return new self("It is illegal to put an inverse side one-to-many or many-to-many association on mapped superclass '".$className."#".$field."'."); - } - - /** - * @param string $className - * @param string $targetEntity - * @param string $targetField - * - * @return MappingException - */ - public static function cannotMapCompositePrimaryKeyEntitiesAsForeignId($className, $targetEntity, $targetField) - { - return new self("It is not possible to map entity '".$className."' with a composite primary key ". - "as part of the primary key of another entity '".$targetEntity."#".$targetField."'."); - } - - /** - * @param string $className - * @param string $field - * - * @return MappingException - */ - public static function noSingleAssociationJoinColumnFound($className, $field) - { - return new self("'$className#$field' is not an association with a single join column."); - } - - /** - * @param string $className - * @param string $column - * - * @return MappingException - */ - public static function noFieldNameFoundForColumn($className, $column) - { - return new self("Cannot find a field on '$className' that is mapped to column '$column'. Either the ". - "field does not exist or an association exists but it has multiple join columns."); - } - - /** - * @param string $className - * @param string $field - * - * @return MappingException - */ - public static function illegalOrphanRemovalOnIdentifierAssociation($className, $field) - { - return new self("The orphan removal option is not allowed on an association that is ". - "part of the identifier in '$className#$field'."); - } - - /** - * @param string $className - * @param string $field - * - * @return MappingException - */ - public static function illegalOrphanRemoval($className, $field) - { - return new self("Orphan removal is only allowed on one-to-one and one-to-many ". - "associations, but " . $className."#" .$field . " is not."); - } - - /** - * @param string $className - * @param string $field - * - * @return MappingException - */ - public static function illegalInverseIdentifierAssociation($className, $field) - { - return new self("An inverse association is not allowed to be identifier in '$className#$field'."); - } - - /** - * @param string $className - * @param string $field - * - * @return MappingException - */ - public static function illegalToManyIdentifierAssociation($className, $field) - { - return new self("Many-to-many or one-to-many associations are not allowed to be identifier in '$className#$field'."); - } - - /** - * @param string $className - * - * @return MappingException - */ - public static function noInheritanceOnMappedSuperClass($className) - { - return new self("It is not supported to define inheritance information on a mapped superclass '" . $className . "'."); - } - - /** - * @param string $className - * @param string $rootClassName - * - * @return MappingException - */ - public static function mappedClassNotPartOfDiscriminatorMap($className, $rootClassName) - { - return new self( - "Entity '" . $className . "' has to be part of the discriminator map of '" . $rootClassName . "' " . - "to be properly mapped in the inheritance hierarchy. Alternatively you can make '".$className."' an abstract class " . - "to avoid this exception from occurring." - ); - } - - /** - * @param string $className - * @param string $methodName - * - * @return MappingException - */ - public static function lifecycleCallbackMethodNotFound($className, $methodName) - { - return new self("Entity '" . $className . "' has no method '" . $methodName . "' to be registered as lifecycle callback."); - } - - /** - * @param string $listenerName - * @param string $className - * - * @return \Doctrine\ORM\Mapping\MappingException - */ - public static function entityListenerClassNotFound($listenerName, $className) - { - return new self(sprintf('Entity Listener "%s" declared on "%s" not found.', $listenerName, $className)); - } - - /** - * @param string $listenerName - * @param string $methodName - * @param string $className - * - * @return \Doctrine\ORM\Mapping\MappingException - */ - public static function entityListenerMethodNotFound($listenerName, $methodName, $className) - { - return new self(sprintf('Entity Listener "%s" declared on "%s" has no method "%s".', $listenerName, $className, $methodName)); - } - - /** - * @param string $listenerName - * @param string $methodName - * @param string $className - * - * @return \Doctrine\ORM\Mapping\MappingException - */ - public static function duplicateEntityListener($listenerName, $methodName, $className) - { - return new self(sprintf('Entity Listener "%s#%s()" in "%s" was already declared, but it must be declared only once.', $listenerName, $methodName, $className)); - } - - /** - * @param string $className - * @param string $annotation - * - * @return MappingException - */ - public static function invalidFetchMode($className, $annotation) - { - return new self("Entity '" . $className . "' has a mapping with invalid fetch mode '" . $annotation . "'"); - } - - /** - * @param string $className - * - * @return MappingException - */ - public static function compositeKeyAssignedIdGeneratorRequired($className) - { - return new self("Entity '". $className . "' has a composite identifier but uses an ID generator other than manually assigning (Identity, Sequence). This is not supported."); - } - - /** - * @param string $targetEntity - * @param string $sourceEntity - * @param string $associationName - * - * @return MappingException - */ - public static function invalidTargetEntityClass($targetEntity, $sourceEntity, $associationName) - { - return new self("The target-entity " . $targetEntity . " cannot be found in '" . $sourceEntity."#".$associationName."'."); - } - - /** - * @param array $cascades - * @param string $className - * @param string $propertyName - * - * @return MappingException - */ - public static function invalidCascadeOption(array $cascades, $className, $propertyName) - { - $cascades = implode(", ", array_map(function ($e) { return "'" . $e . "'"; }, $cascades)); - - return new self(sprintf( - "You have specified invalid cascade options for %s::$%s: %s; available options: 'remove', 'persist', 'refresh', 'merge', and 'detach'", - $className, - $propertyName, - $cascades - )); - } - - /** - * @param string $className - * - * @return MappingException - */ - public static function missingSequenceName($className) - { - return new self( - sprintf('Missing "sequenceName" attribute for sequence id generator definition on class "%s".', $className) - ); - } - - /** - * @param string $className - * @param string $propertyName - * - * @return MappingException - */ - public static function infiniteEmbeddableNesting($className, $propertyName) - { - return new self( - sprintf( - 'Infinite nesting detected for embedded property %s::%s. ' . - 'You cannot embed an embeddable from the same type inside an embeddable.', - $className, - $propertyName - ) - ); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQueries.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQueries.php deleted file mode 100644 index 2539107..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQueries.php +++ /dev/null @@ -1,40 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * Is used to specify an array of native SQL named queries. - * The NamedNativeQueries annotation can be applied to an entity or mapped superclass. - * - * @author Fabio B. Silva - * @since 2.3 - * - * @Annotation - * @Target("CLASS") - */ -final class NamedNativeQueries implements Annotation -{ - /** - * One or more NamedNativeQuery annotations. - * - * @var array<\Doctrine\ORM\Mapping\NamedNativeQuery> - */ - public $value = []; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQuery.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQuery.php deleted file mode 100644 index f336c99..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedNativeQuery.php +++ /dev/null @@ -1,61 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * Is used to specify a native SQL named query. - * The NamedNativeQuery annotation can be applied to an entity or mapped superclass. - * - * @author Fabio B. Silva - * @since 2.3 - * - * @Annotation - * @Target("ANNOTATION") - */ -final class NamedNativeQuery implements Annotation -{ - /** - * The name used to refer to the query with the EntityManager methods that create query objects. - * - * @var string - */ - public $name; - - /** - * The SQL query string. - * - * @var string - */ - public $query; - - /** - * The class of the result. - * - * @var string - */ - public $resultClass; - - /** - * The name of a SqlResultSetMapping, as defined in metadata. - * - * @var string - */ - public $resultSetMapping; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQueries.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQueries.php deleted file mode 100644 index 5fce072..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQueries.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("CLASS") - */ -final class NamedQueries implements Annotation -{ - /** - * @var array<\Doctrine\ORM\Mapping\NamedQuery> - */ - public $value; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQuery.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQuery.php deleted file mode 100644 index c4e6cd5..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamedQuery.php +++ /dev/null @@ -1,37 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("ANNOTATION") - */ -final class NamedQuery implements Annotation -{ - /** - * @var string - */ - public $name; - - /** - * @var string - */ - public $query; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamingStrategy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamingStrategy.php deleted file mode 100644 index 9960f94..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/NamingStrategy.php +++ /dev/null @@ -1,100 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * A set of rules for determining the physical column and table names - * - * - * @link www.doctrine-project.org - * @since 2.3 - * @author Fabio B. Silva - */ -interface NamingStrategy -{ - /** - * Returns a table name for an entity class. - * - * @param string $className The fully-qualified class name. - * - * @return string A table name. - */ - function classToTableName($className); - - /** - * Returns a column name for a property. - * - * @param string $propertyName A property name. - * @param string|null $className The fully-qualified class name. - * - * @return string A column name. - */ - function propertyToColumnName($propertyName, $className = null); - - /** - * Returns a column name for an embedded property. - * - * @param string $propertyName - * @param string $embeddedColumnName - * @param string $className - * @param string $embeddedClassName - * - * @return string - */ - function embeddedFieldToColumnName($propertyName, $embeddedColumnName, $className = null, $embeddedClassName = null); - - /** - * Returns the default reference column name. - * - * @return string A column name. - */ - function referenceColumnName(); - - /** - * Returns a join column name for a property. - * - * @param string $propertyName A property name. - * - * @return string A join column name. - */ - function joinColumnName($propertyName); - - /** - * Returns a join table name. - * - * @param string $sourceEntity The source entity. - * @param string $targetEntity The target entity. - * @param string|null $propertyName A property name. - * - * @return string A join table name. - */ - function joinTableName($sourceEntity, $targetEntity, $propertyName = null); - - /** - * Returns the foreign key column name for the given parameters. - * - * @param string $entityName An entity. - * @param string|null $referencedColumnName A property. - * - * @return string A join column name. - */ - function joinKeyColumnName($entityName, $referencedColumnName = null); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToMany.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToMany.php deleted file mode 100644 index 4b24657..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToMany.php +++ /dev/null @@ -1,61 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("PROPERTY") - */ -final class OneToMany implements Annotation -{ - /** - * @var string - */ - public $mappedBy; - - /** - * @var string - */ - public $targetEntity; - - /** - * @var array - */ - public $cascade; - - /** - * The fetching strategy to use for the association. - * - * @var string - * - * @Enum({"LAZY", "EAGER", "EXTRA_LAZY"}) - */ - public $fetch = 'LAZY'; - - /** - * @var boolean - */ - public $orphanRemoval = false; - - /** - * @var string - */ - public $indexBy; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToOne.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToOne.php deleted file mode 100644 index b2ab81f..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OneToOne.php +++ /dev/null @@ -1,61 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("PROPERTY") - */ -final class OneToOne implements Annotation -{ - /** - * @var string - */ - public $targetEntity; - - /** - * @var string - */ - public $mappedBy; - - /** - * @var string - */ - public $inversedBy; - - /** - * @var array - */ - public $cascade; - - /** - * The fetching strategy to use for the association. - * - * @var string - * - * @Enum({"LAZY", "EAGER", "EXTRA_LAZY"}) - */ - public $fetch = 'LAZY'; - - /** - * @var boolean - */ - public $orphanRemoval = false; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OrderBy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OrderBy.php deleted file mode 100644 index ad1b7a8..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/OrderBy.php +++ /dev/null @@ -1,32 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("PROPERTY") - */ -final class OrderBy implements Annotation -{ - /** - * @var array - */ - public $value; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostLoad.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostLoad.php deleted file mode 100644 index 2f8e993..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostLoad.php +++ /dev/null @@ -1,28 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("METHOD") - */ -final class PostLoad implements Annotation -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostPersist.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostPersist.php deleted file mode 100644 index 2aea719..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostPersist.php +++ /dev/null @@ -1,28 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("METHOD") - */ -final class PostPersist implements Annotation -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostRemove.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostRemove.php deleted file mode 100644 index 321c4bd..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostRemove.php +++ /dev/null @@ -1,28 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("METHOD") - */ -final class PostRemove implements Annotation -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostUpdate.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostUpdate.php deleted file mode 100644 index a55f707..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PostUpdate.php +++ /dev/null @@ -1,28 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("METHOD") - */ -final class PostUpdate implements Annotation -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreFlush.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreFlush.php deleted file mode 100644 index 6697d37..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreFlush.php +++ /dev/null @@ -1,28 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("METHOD") - */ -final class PreFlush implements Annotation -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PrePersist.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PrePersist.php deleted file mode 100644 index fea05be..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PrePersist.php +++ /dev/null @@ -1,28 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("METHOD") - */ -final class PrePersist implements Annotation -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreRemove.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreRemove.php deleted file mode 100644 index 29822ed..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreRemove.php +++ /dev/null @@ -1,28 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("METHOD") - */ -final class PreRemove implements Annotation -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreUpdate.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreUpdate.php deleted file mode 100644 index 290df72..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/PreUpdate.php +++ /dev/null @@ -1,28 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("METHOD") - */ -final class PreUpdate implements Annotation -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/QuoteStrategy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/QuoteStrategy.php deleted file mode 100644 index 1a21ff1..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/QuoteStrategy.php +++ /dev/null @@ -1,119 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -use Doctrine\DBAL\Platforms\AbstractPlatform; - -/** - * A set of rules for determining the column, alias and table quotes. - * - * @since 2.3 - * @author Fabio B. Silva - */ -interface QuoteStrategy -{ - /** - * Gets the (possibly quoted) column name for safe use in an SQL statement. - * - * @param string $fieldName - * @param ClassMetadata $class - * @param AbstractPlatform $platform - * - * @return string - */ - function getColumnName($fieldName, ClassMetadata $class, AbstractPlatform $platform); - - /** - * Gets the (possibly quoted) primary table name for safe use in an SQL statement. - * - * @param ClassMetadata $class - * @param AbstractPlatform $platform - * - * @return string - */ - function getTableName(ClassMetadata $class, AbstractPlatform $platform); - - /** - * Gets the (possibly quoted) sequence name for safe use in an SQL statement. - * - * @param array $definition - * @param ClassMetadata $class - * @param AbstractPlatform $platform - * - * @return string - */ - function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform); - - /** - * Gets the (possibly quoted) name of the join table. - * - * @param array $association - * @param ClassMetadata $class - * @param AbstractPlatform $platform - * - * @return string - */ - function getJoinTableName(array $association, ClassMetadata $class, AbstractPlatform $platform); - - /** - * Gets the (possibly quoted) join column name. - * - * @param array $joinColumn - * @param ClassMetadata $class - * @param AbstractPlatform $platform - * - * @return string - */ - function getJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform); - - /** - * Gets the (possibly quoted) join column name. - * - * @param array $joinColumn - * @param ClassMetadata $class - * @param AbstractPlatform $platform - * - * @return string - */ - function getReferencedJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform); - - /** - * Gets the (possibly quoted) identifier column names for safe use in an SQL statement. - * - * @param ClassMetadata $class - * @param AbstractPlatform $platform - * - * @return array - */ - function getIdentifierColumnNames(ClassMetadata $class, AbstractPlatform $platform); - - /** - * Gets the column alias. - * - * @param string $columnName - * @param integer $counter - * @param AbstractPlatform $platform - * @param ClassMetadata|null $class - * - * @return string - */ - function getColumnAlias($columnName, $counter, AbstractPlatform $platform, ClassMetadata $class = null); - -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Reflection/ReflectionPropertiesGetter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Reflection/ReflectionPropertiesGetter.php deleted file mode 100644 index 6ac7f11..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Reflection/ReflectionPropertiesGetter.php +++ /dev/null @@ -1,163 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping\Reflection; - -use Doctrine\Common\Persistence\Mapping\ReflectionService; -use ReflectionClass; -use ReflectionProperty; - -/** - * Utility class to retrieve all reflection instance properties of a given class, including - * private inherited properties and transient properties. - * - * @private This API is for internal use only - * - * @author Marco Pivetta - */ -final class ReflectionPropertiesGetter -{ - /** - * @var ReflectionProperty[][] indexed by class name and property internal name - */ - private $properties = []; - - /** - * @var ReflectionService - */ - private $reflectionService; - - /** - * @param ReflectionService $reflectionService - */ - public function __construct(ReflectionService $reflectionService) - { - $this->reflectionService = $reflectionService; - } - - /** - * @param $className - * - * @return ReflectionProperty[] indexed by property internal name - */ - public function getProperties($className) - { - if (isset($this->properties[$className])) { - return $this->properties[$className]; - } - - return $this->properties[$className] = call_user_func_array( - 'array_merge', - // first merge because `array_merge` expects >= 1 params - array_merge( - [[]], - array_map( - [$this, 'getClassProperties'], - $this->getHierarchyClasses($className) - ) - ) - ); - } - - /** - * @param string $className - * - * @return ReflectionClass[] - */ - private function getHierarchyClasses($className) - { - $classes = []; - $parentClassName = $className; - - while ($parentClassName && $currentClass = $this->reflectionService->getClass($parentClassName)) { - $classes[] = $currentClass; - $parentClassName = null; - - if ($parentClass = $currentClass->getParentClass()) { - $parentClassName = $parentClass->getName(); - } - } - - return $classes; - } - - /** - * @param ReflectionClass $reflectionClass - * - * @return ReflectionProperty[] - */ - private function getClassProperties(ReflectionClass $reflectionClass) - { - $properties = $reflectionClass->getProperties(); - - return array_filter( - array_filter(array_map( - [$this, 'getAccessibleProperty'], - array_combine( - array_map([$this, 'getLogicalName'], $properties), - $properties - ) - )), - [$this, 'isInstanceProperty'] - ); - } - - /** - * @param ReflectionProperty $reflectionProperty - * - * @return bool - */ - private function isInstanceProperty(ReflectionProperty $reflectionProperty) - { - return ! $reflectionProperty->isStatic(); - } - - /** - * @param ReflectionProperty $property - * - * @return null|ReflectionProperty - */ - private function getAccessibleProperty(ReflectionProperty $property) - { - return $this->reflectionService->getAccessibleProperty( - $property->getDeclaringClass()->getName(), - $property->getName() - ); - } - - /** - * @param ReflectionProperty $property - * - * @return string - */ - private function getLogicalName(ReflectionProperty $property) - { - $propertyName = $property->getName(); - - if ($property->isPublic()) { - return $propertyName; - } - - if ($property->isProtected()) { - return "\0*\0" . $propertyName; - } - - return "\0" . $property->getDeclaringClass()->getName() . "\0" . $propertyName; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ReflectionEmbeddedProperty.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ReflectionEmbeddedProperty.php deleted file mode 100644 index b224fff..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ReflectionEmbeddedProperty.php +++ /dev/null @@ -1,101 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -use Doctrine\Instantiator\Instantiator; -use ReflectionProperty; - -/** - * Acts as a proxy to a nested Property structure, making it look like - * just a single scalar property. - * - * This way value objects "just work" without UnitOfWork, Persisters or Hydrators - * needing any changes. - * - * TODO: Move this class into Common\Reflection - */ -class ReflectionEmbeddedProperty extends ReflectionProperty -{ - /** - * @var ReflectionProperty reflection property of the class where the embedded object has to be put - */ - private $parentProperty; - - /** - * @var ReflectionProperty reflection property of the embedded object - */ - private $childProperty; - - /** - * @var string name of the embedded class to be eventually instantiated - */ - private $embeddedClass; - - /** - * @var Instantiator|null - */ - private $instantiator; - - /** - * @param ReflectionProperty $parentProperty - * @param ReflectionProperty $childProperty - * @param string $embeddedClass - */ - public function __construct(ReflectionProperty $parentProperty, ReflectionProperty $childProperty, $embeddedClass) - { - $this->parentProperty = $parentProperty; - $this->childProperty = $childProperty; - $this->embeddedClass = (string) $embeddedClass; - - parent::__construct($childProperty->getDeclaringClass()->getName(), $childProperty->getName()); - } - - /** - * {@inheritDoc} - */ - public function getValue($object = null) - { - $embeddedObject = $this->parentProperty->getValue($object); - - if (null === $embeddedObject) { - return null; - } - - return $this->childProperty->getValue($embeddedObject); - } - - /** - * {@inheritDoc} - */ - public function setValue($object, $value = null) - { - $embeddedObject = $this->parentProperty->getValue($object); - - if (null === $embeddedObject) { - $this->instantiator = $this->instantiator ?: new Instantiator(); - - $embeddedObject = $this->instantiator->instantiate($this->embeddedClass); - - $this->parentProperty->setValue($object, $embeddedObject); - } - - $this->childProperty->setValue($embeddedObject, $value); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SequenceGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SequenceGenerator.php deleted file mode 100644 index ba1c45b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SequenceGenerator.php +++ /dev/null @@ -1,42 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("PROPERTY") - */ -final class SequenceGenerator implements Annotation -{ - /** - * @var string - */ - public $sequenceName; - - /** - * @var integer - */ - public $allocationSize = 1; - - /** - * @var integer - */ - public $initialValue = 1; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMapping.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMapping.php deleted file mode 100644 index cb78c9a..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMapping.php +++ /dev/null @@ -1,54 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * The SqlResultSetMapping annotation is used to specify the mapping of the result of a native SQL query. - * The SqlResultSetMapping annotation can be applied to an entity or mapped superclass. - * - * @author Fabio B. Silva - * @since 2.3 - * - * @Annotation - * @Target("ANNOTATION") - */ -final class SqlResultSetMapping implements Annotation -{ - /** - * The name given to the result set mapping, and used to refer to it in the methods of the Query API. - * - * @var string - */ - public $name; - - /** - * Specifies the result set mapping to entities. - * - * @var array<\Doctrine\ORM\Mapping\EntityResult> - */ - public $entities = []; - - /** - * Specifies the result set mapping to scalar values. - * - * @var array<\Doctrine\ORM\Mapping\ColumnResult> - */ - public $columns = []; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMappings.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMappings.php deleted file mode 100644 index 0b74f2d..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/SqlResultSetMappings.php +++ /dev/null @@ -1,40 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * Is used to specify an array of mappings. - * The SqlResultSetMappings annotation can be applied to an entity or mapped superclass. - * - * @author Fabio B. Silva - * @since 2.3 - * - * @Annotation - * @Target("CLASS") - */ -final class SqlResultSetMappings implements Annotation -{ - /** - * One or more SqlResultSetMapping annotations. - * - * @var array<\Doctrine\ORM\Mapping\SqlResultSetMapping> - */ - public $value = []; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Table.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Table.php deleted file mode 100644 index 6ed7037..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Table.php +++ /dev/null @@ -1,52 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("CLASS") - */ -final class Table implements Annotation -{ - /** - * @var string - */ - public $name; - - /** - * @var string - */ - public $schema; - - /** - * @var array<\Doctrine\ORM\Mapping\Index> - */ - public $indexes; - - /** - * @var array<\Doctrine\ORM\Mapping\UniqueConstraint> - */ - public $uniqueConstraints; - - /** - * @var array - */ - public $options = []; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UnderscoreNamingStrategy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UnderscoreNamingStrategy.php deleted file mode 100644 index 177b390..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UnderscoreNamingStrategy.php +++ /dev/null @@ -1,166 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -use const CASE_LOWER; -use const CASE_UPPER; -use const E_USER_DEPRECATED; -use function preg_replace; -use function strpos; -use function strrpos; -use function strtolower; -use function strtoupper; -use function substr; -use function trigger_error; - -/** - * Naming strategy implementing the underscore naming convention. - * Converts 'MyEntity' to 'my_entity' or 'MY_ENTITY'. - * - * - * @link www.doctrine-project.org - * @since 2.3 - * @author Fabio B. Silva - */ -class UnderscoreNamingStrategy implements NamingStrategy -{ - private const DEFAULT_PATTERN = '/(?<=[a-z])([A-Z])/'; - private const NUMBER_AWARE_PATTERN = '/(?<=[a-z0-9])([A-Z])/'; - - /** - * @var integer - */ - private $case; - - /** @var string */ - private $pattern; - - /** - * Underscore naming strategy construct. - * - * @param int $case CASE_LOWER | CASE_UPPER - */ - public function __construct($case = CASE_LOWER, bool $numberAware = false) - { - if (! $numberAware) { - @trigger_error( - 'Creating ' . self::class . ' without making it number aware is deprecated and will be removed in Doctrine ORM 3.0.', - E_USER_DEPRECATED - ); - } - - $this->case = $case; - $this->pattern = $numberAware ? self::NUMBER_AWARE_PATTERN : self::DEFAULT_PATTERN; - } - - /** - * @return integer CASE_LOWER | CASE_UPPER - */ - public function getCase() - { - return $this->case; - } - - /** - * Sets string case CASE_LOWER | CASE_UPPER. - * Alphabetic characters converted to lowercase or uppercase. - * - * @param integer $case - * - * @return void - */ - public function setCase($case) - { - $this->case = $case; - } - - /** - * {@inheritdoc} - */ - public function classToTableName($className) - { - if (strpos($className, '\\') !== false) { - $className = substr($className, strrpos($className, '\\') + 1); - } - - return $this->underscore($className); - } - - /** - * {@inheritdoc} - */ - public function propertyToColumnName($propertyName, $className = null) - { - return $this->underscore($propertyName); - } - - /** - * {@inheritdoc} - */ - public function embeddedFieldToColumnName($propertyName, $embeddedColumnName, $className = null, $embeddedClassName = null) - { - return $this->underscore($propertyName).'_'.$embeddedColumnName; - } - - /** - * {@inheritdoc} - */ - public function referenceColumnName() - { - return $this->case === CASE_UPPER ? 'ID' : 'id'; - } - - /** - * {@inheritdoc} - */ - public function joinColumnName($propertyName, $className = null) - { - return $this->underscore($propertyName) . '_' . $this->referenceColumnName(); - } - - /** - * {@inheritdoc} - */ - public function joinTableName($sourceEntity, $targetEntity, $propertyName = null) - { - return $this->classToTableName($sourceEntity) . '_' . $this->classToTableName($targetEntity); - } - - /** - * {@inheritdoc} - */ - public function joinKeyColumnName($entityName, $referencedColumnName = null) - { - return $this->classToTableName($entityName) . '_' . - ($referencedColumnName ?: $this->referenceColumnName()); - } - - private function underscore(string $string) : string - { - $string = preg_replace($this->pattern, '_$1', $string); - - if ($this->case === CASE_UPPER) { - return strtoupper($string); - } - - return strtolower($string); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UniqueConstraint.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UniqueConstraint.php deleted file mode 100644 index f117d18..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/UniqueConstraint.php +++ /dev/null @@ -1,42 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("ANNOTATION") - */ -final class UniqueConstraint implements Annotation -{ - /** - * @var string - */ - public $name; - - /** - * @var array - */ - public $columns; - - /** - * @var array - */ - public $options; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Version.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Version.php deleted file mode 100644 index a237702..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Version.php +++ /dev/null @@ -1,28 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Mapping; - -/** - * @Annotation - * @Target("PROPERTY") - */ -final class Version implements Annotation -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/NativeQuery.php b/vendor/doctrine/orm/lib/Doctrine/ORM/NativeQuery.php deleted file mode 100644 index ddc5418..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/NativeQuery.php +++ /dev/null @@ -1,92 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -/** - * Represents a native SQL query. - * - * @author Roman Borschel - * @since 2.0 - */ -final class NativeQuery extends AbstractQuery -{ - /** - * @var string - */ - private $_sql; - - /** - * Sets the SQL of the query. - * - * @param string $sql - * - * @return NativeQuery This query instance. - */ - public function setSQL($sql) - { - $this->_sql = $sql; - - return $this; - } - - /** - * Gets the SQL query. - * - * @return mixed The built SQL query or an array of all SQL queries. - * - * @override - */ - public function getSQL() - { - return $this->_sql; - } - - /** - * {@inheritdoc} - */ - protected function _doExecute() - { - $parameters = []; - $types = []; - - foreach ($this->getParameters() as $parameter) { - $name = $parameter->getName(); - $value = $this->processParameterValue($parameter->getValue()); - $type = ($parameter->getValue() === $value) - ? $parameter->getType() - : Query\ParameterTypeInferer::inferType($value); - - $parameters[$name] = $value; - $types[$name] = $type; - } - - if ($parameters && is_int(key($parameters))) { - ksort($parameters); - ksort($types); - - $parameters = array_values($parameters); - $types = array_values($types); - } - - return $this->_em->getConnection()->executeQuery( - $this->_sql, $parameters, $types, $this->_queryCacheProfile - ); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/NoResultException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/NoResultException.php deleted file mode 100644 index 2cbac8e..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/NoResultException.php +++ /dev/null @@ -1,37 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -/** - * Exception thrown when an ORM query unexpectedly does not return any results. - * - * @author robo - * @since 2.0 - */ -class NoResultException extends UnexpectedResultException -{ - /** - * Constructor. - */ - public function __construct() - { - parent::__construct('No result was found for query although at least one row was expected.'); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/NonUniqueResultException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/NonUniqueResultException.php deleted file mode 100644 index 78a58dd..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/NonUniqueResultException.php +++ /dev/null @@ -1,36 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -/** - * Exception thrown when an ORM query unexpectedly returns more than one result. - * - * @author robo - * @since 2.0 - */ -class NonUniqueResultException extends UnexpectedResultException -{ - const DEFAULT_MESSAGE = 'More than one result was found for query although one row or none was expected.'; - - public function __construct(string $message = null) - { - parent::__construct($message ?? self::DEFAULT_MESSAGE); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/ORMException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/ORMException.php deleted file mode 100644 index 3ce9ce9..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/ORMException.php +++ /dev/null @@ -1,333 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -use Doctrine\Common\Cache\Cache as CacheDriver; -use Exception; - -/** - * Base exception class for all ORM exceptions. - * - * @author Roman Borschel - * @since 2.0 - */ -class ORMException extends Exception -{ - /** - * @return ORMException - */ - public static function missingMappingDriverImpl() - { - return new self("It's a requirement to specify a Metadata Driver and pass it ". - "to Doctrine\\ORM\\Configuration::setMetadataDriverImpl()."); - } - - /** - * @param string $queryName - * - * @return ORMException - */ - public static function namedQueryNotFound($queryName) - { - return new self('Could not find a named query by the name "' . $queryName . '"'); - } - - /** - * @param string $nativeQueryName - * - * @return ORMException - */ - public static function namedNativeQueryNotFound($nativeQueryName) - { - return new self('Could not find a named native query by the name "' . $nativeQueryName . '"'); - } - - /** - * @param object $entity - * @param object $relatedEntity - * - * @return ORMException - */ - public static function entityMissingForeignAssignedId($entity, $relatedEntity) - { - return new self( - "Entity of type " . get_class($entity) . " has identity through a foreign entity " . get_class($relatedEntity) . ", " . - "however this entity has no identity itself. You have to call EntityManager#persist() on the related entity " . - "and make sure that an identifier was generated before trying to persist '" . get_class($entity) . "'. In case " . - "of Post Insert ID Generation (such as MySQL Auto-Increment) this means you have to call " . - "EntityManager#flush() between both persist operations." - ); - } - - /** - * @param object $entity - * @param string $field - * - * @return ORMException - */ - public static function entityMissingAssignedIdForField($entity, $field) - { - return new self("Entity of type " . get_class($entity) . " is missing an assigned ID for field '" . $field . "'. " . - "The identifier generation strategy for this entity requires the ID field to be populated before ". - "EntityManager#persist() is called. If you want automatically generated identifiers instead " . - "you need to adjust the metadata mapping accordingly." - ); - } - - /** - * @param string $field - * - * @return ORMException - */ - public static function unrecognizedField($field) - { - return new self("Unrecognized field: $field"); - } - - /** - * - * @param string $class - * @param string $association - * @param string $given - * @param string $expected - * - * @return \Doctrine\ORM\ORMInvalidArgumentException - */ - public static function unexpectedAssociationValue($class, $association, $given, $expected) - { - return new self(sprintf('Found entity of type %s on association %s#%s, but expecting %s', $given, $class, $association, $expected)); - } - - /** - * @param string $className - * @param string $field - * - * @return ORMException - */ - public static function invalidOrientation($className, $field) - { - return new self("Invalid order by orientation specified for " . $className . "#" . $field); - } - - /** - * @param string $mode - * - * @return ORMException - */ - public static function invalidFlushMode($mode) - { - return new self("'$mode' is an invalid flush mode."); - } - - /** - * @return ORMException - */ - public static function entityManagerClosed() - { - return new self("The EntityManager is closed."); - } - - /** - * @param string $mode - * - * @return ORMException - */ - public static function invalidHydrationMode($mode) - { - return new self("'$mode' is an invalid hydration mode."); - } - - /** - * @return ORMException - */ - public static function mismatchedEventManager() - { - return new self("Cannot use different EventManager instances for EntityManager and Connection."); - } - - /** - * @param string $methodName - * - * @return ORMException - */ - public static function findByRequiresParameter($methodName) - { - return new self("You need to pass a parameter to '".$methodName."'"); - } - - /** - * @param string $entityName - * @param string $fieldName - * @param string $method - * - * @return ORMException - */ - public static function invalidFindByCall($entityName, $fieldName, $method) - { - return new self( - "Entity '".$entityName."' has no field '".$fieldName."'. ". - "You can therefore not call '".$method."' on the entities' repository" - ); - } - - /** - * @param string $entityName - * @param string $fieldName - * @param string $method - * - * @return ORMException - */ - public static function invalidMagicCall($entityName, $fieldName, $method) - { - return new self( - "Entity '".$entityName."' has no field '".$fieldName."'. ". - "You can therefore not call '".$method."' on the entities' repository" - ); - } - - /** - * @param string $entityName - * @param string $associationFieldName - * - * @return ORMException - */ - public static function invalidFindByInverseAssociation($entityName, $associationFieldName) - { - return new self( - "You cannot search for the association field '".$entityName."#".$associationFieldName."', ". - "because it is the inverse side of an association. Find methods only work on owning side associations." - ); - } - - /** - * @return ORMException - */ - public static function invalidResultCacheDriver() - { - return new self("Invalid result cache driver; it must implement Doctrine\\Common\\Cache\\Cache."); - } - - /** - * @return ORMException - */ - public static function notSupported() - { - return new self("This behaviour is (currently) not supported by Doctrine 2"); - } - - /** - * @return ORMException - */ - public static function queryCacheNotConfigured() - { - return new self('Query Cache is not configured.'); - } - - /** - * @return ORMException - */ - public static function metadataCacheNotConfigured() - { - return new self('Class Metadata Cache is not configured.'); - } - - /** - * @param \Doctrine\Common\Cache\Cache $cache - * - * @return ORMException - */ - public static function queryCacheUsesNonPersistentCache(CacheDriver $cache) - { - return new self('Query Cache uses a non-persistent cache driver, ' . get_class($cache) . '.'); - } - - /** - * @param \Doctrine\Common\Cache\Cache $cache - * - * @return ORMException - */ - public static function metadataCacheUsesNonPersistentCache(CacheDriver $cache) - { - return new self('Metadata Cache uses a non-persistent cache driver, ' . get_class($cache) . '.'); - } - - /** - * @return ORMException - */ - public static function proxyClassesAlwaysRegenerating() - { - return new self('Proxy Classes are always regenerating.'); - } - - /** - * @param string $entityNamespaceAlias - * - * @return ORMException - */ - public static function unknownEntityNamespace($entityNamespaceAlias) - { - return new self( - "Unknown Entity namespace alias '$entityNamespaceAlias'." - ); - } - - /** - * @param string $className - * - * @return ORMException - */ - public static function invalidEntityRepository($className) - { - return new self("Invalid repository class '".$className."'. It must be a Doctrine\Common\Persistence\ObjectRepository."); - } - - /** - * @param string $className - * @param string $fieldName - * - * @return ORMException - */ - public static function missingIdentifierField($className, $fieldName) - { - return new self("The identifier $fieldName is missing for a query of " . $className); - } - - /** - * @param string $className - * @param string[] $fieldNames - * - * @return ORMException - */ - public static function unrecognizedIdentifierFields($className, $fieldNames) - { - return new self( - "Unrecognized identifier fields: '" . implode("', '", $fieldNames) . "' " . - "are not present on class '" . $className . "'." - ); - } - - /** - * @return ORMException - */ - public static function cantUseInOperatorOnCompositeKeys() - { - return new self("Can't use IN operator on entities that have composite keys."); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/ORMInvalidArgumentException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/ORMInvalidArgumentException.php deleted file mode 100644 index 68bb6f9..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/ORMInvalidArgumentException.php +++ /dev/null @@ -1,272 +0,0 @@ -. - */ - -namespace Doctrine\ORM; -use Doctrine\ORM\Mapping\ClassMetadata; - -/** - * Contains exception messages for all invalid lifecycle state exceptions inside UnitOfWork - * - * @author Benjamin Eberlei - */ -class ORMInvalidArgumentException extends \InvalidArgumentException -{ - /** - * @param object $entity - * - * @return ORMInvalidArgumentException - */ - static public function scheduleInsertForManagedEntity($entity) - { - return new self("A managed+dirty entity " . self::objToStr($entity) . " can not be scheduled for insertion."); - } - - /** - * @param object $entity - * - * @return ORMInvalidArgumentException - */ - static public function scheduleInsertForRemovedEntity($entity) - { - return new self("Removed entity " . self::objToStr($entity) . " can not be scheduled for insertion."); - } - - /** - * @param object $entity - * - * @return ORMInvalidArgumentException - */ - static public function scheduleInsertTwice($entity) - { - return new self("Entity " . self::objToStr($entity) . " can not be scheduled for insertion twice."); - } - - /** - * @param string $className - * @param object $entity - * - * @return ORMInvalidArgumentException - */ - static public function entityWithoutIdentity($className, $entity) - { - return new self( - "The given entity of type '" . $className . "' (".self::objToStr($entity).") has no identity/no " . - "id values set. It cannot be added to the identity map." - ); - } - - /** - * @param object $entity - * - * @return ORMInvalidArgumentException - */ - static public function readOnlyRequiresManagedEntity($entity) - { - return new self("Only managed entities can be marked or checked as read only. But " . self::objToStr($entity) . " is not"); - } - - /** - * @param array[][]|object[][] $newEntitiesWithAssociations non-empty an array - * of [array $associationMapping, object $entity] pairs - * - * @return ORMInvalidArgumentException - */ - static public function newEntitiesFoundThroughRelationships($newEntitiesWithAssociations) - { - $errorMessages = array_map( - function (array $newEntityWithAssociation) : string { - [$associationMapping, $entity] = $newEntityWithAssociation; - - return self::newEntityFoundThroughRelationshipMessage($associationMapping, $entity); - }, - $newEntitiesWithAssociations - ); - - if (1 === count($errorMessages)) { - return new self(reset($errorMessages)); - } - - return new self( - 'Multiple non-persisted new entities were found through the given association graph:' - . "\n\n * " - . implode("\n * ", $errorMessages) - ); - } - - /** - * @param array $associationMapping - * @param object $entry - * - * @return ORMInvalidArgumentException - */ - static public function newEntityFoundThroughRelationship(array $associationMapping, $entry) - { - return new self(self::newEntityFoundThroughRelationshipMessage($associationMapping, $entry)); - } - - /** - * @param array $assoc - * @param object $entry - * - * @return ORMInvalidArgumentException - */ - static public function detachedEntityFoundThroughRelationship(array $assoc, $entry) - { - return new self("A detached entity of type " . $assoc['targetEntity'] . " (" . self::objToStr($entry) . ") " - . " was found through the relationship '" . $assoc['sourceEntity'] . "#" . $assoc['fieldName'] . "' " - . "during cascading a persist operation."); - } - - /** - * @param object $entity - * - * @return ORMInvalidArgumentException - */ - static public function entityNotManaged($entity) - { - return new self("Entity " . self::objToStr($entity) . " is not managed. An entity is managed if its fetched " . - "from the database or registered as new through EntityManager#persist"); - } - - /** - * @param object $entity - * @param string $operation - * - * @return ORMInvalidArgumentException - */ - static public function entityHasNoIdentity($entity, $operation) - { - return new self("Entity has no identity, therefore " . $operation ." cannot be performed. " . self::objToStr($entity)); - } - - /** - * @param object $entity - * @param string $operation - * - * @return ORMInvalidArgumentException - */ - static public function entityIsRemoved($entity, $operation) - { - return new self("Entity is removed, therefore " . $operation ." cannot be performed. " . self::objToStr($entity)); - } - - /** - * @param object $entity - * @param string $operation - * - * @return ORMInvalidArgumentException - */ - static public function detachedEntityCannot($entity, $operation) - { - return new self("Detached entity " . self::objToStr($entity) . " cannot be " . $operation); - } - - /** - * @param string $context - * @param mixed $given - * @param int $parameterIndex - * - * @return ORMInvalidArgumentException - */ - public static function invalidObject($context, $given, $parameterIndex = 1) - { - return new self($context . ' expects parameter ' . $parameterIndex . - ' to be an entity object, '. gettype($given) . ' given.'); - } - - /** - * @return ORMInvalidArgumentException - */ - public static function invalidCompositeIdentifier() - { - return new self("Binding an entity with a composite primary key to a query is not supported. " . - "You should split the parameter into the explicit fields and bind them separately."); - } - - /** - * @return ORMInvalidArgumentException - */ - public static function invalidIdentifierBindingEntity() - { - return new self("Binding entities to query parameters only allowed for entities that have an identifier."); - } - - /** - * @param ClassMetadata $targetClass - * @param array $assoc - * @param mixed $actualValue - * - * @return self - */ - public static function invalidAssociation(ClassMetadata $targetClass, $assoc, $actualValue) - { - $expectedType = $targetClass->getName(); - - return new self(sprintf( - 'Expected value of type "%s" for association field "%s#$%s", got "%s" instead.', - $expectedType, - $assoc['sourceEntity'], - $assoc['fieldName'], - is_object($actualValue) ? get_class($actualValue) : gettype($actualValue) - )); - } - - /** - * Used when a given entityName hasn't the good type - * - * @param mixed $entityName The given entity (which shouldn't be a string) - * - * @return self - */ - public static function invalidEntityName($entityName) - { - return new self(sprintf('Entity name must be a string, %s given', gettype($entityName))); - } - - /** - * Helper method to show an object as string. - * - * @param object $obj - * - * @return string - */ - private static function objToStr($obj) : string - { - return method_exists($obj, '__toString') ? (string) $obj : get_class($obj).'@'.spl_object_hash($obj); - } - - /** - * @param array $associationMapping - * @param object $entity - */ - private static function newEntityFoundThroughRelationshipMessage(array $associationMapping, $entity) : string - { - return 'A new entity was found through the relationship \'' - . $associationMapping['sourceEntity'] . '#' . $associationMapping['fieldName'] . '\' that was not' - . ' configured to cascade persist operations for entity: ' . self::objToStr($entity) . '.' - . ' To solve this issue: Either explicitly call EntityManager#persist()' - . ' on this unknown entity or configure cascade persist' - . ' this association in the mapping for example @ManyToOne(..,cascade={"persist"}).' - . (method_exists($entity, '__toString') - ? '' - : ' If you cannot find out which entity causes the problem implement \'' - . $associationMapping['targetEntity'] . '#__toString()\' to get a clue.' - ); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/OptimisticLockException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/OptimisticLockException.php deleted file mode 100644 index 2fbd9ce..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/OptimisticLockException.php +++ /dev/null @@ -1,91 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -/** - * An OptimisticLockException is thrown when a version check on an object - * that uses optimistic locking through a version field fails. - * - * @author Roman Borschel - * @author Benjamin Eberlei - * @since 2.0 - */ -class OptimisticLockException extends ORMException -{ - /** - * @var object|null - */ - private $entity; - - /** - * @param string $msg - * @param object $entity - */ - public function __construct($msg, $entity) - { - parent::__construct($msg); - $this->entity = $entity; - } - - /** - * Gets the entity that caused the exception. - * - * @return object|null - */ - public function getEntity() - { - return $this->entity; - } - - /** - * @param object $entity - * - * @return OptimisticLockException - */ - public static function lockFailed($entity) - { - return new self("The optimistic lock on an entity failed.", $entity); - } - - /** - * @param object $entity - * @param int $expectedLockVersion - * @param int $actualLockVersion - * - * @return OptimisticLockException - */ - public static function lockFailedVersionMismatch($entity, $expectedLockVersion, $actualLockVersion) - { - $expectedLockVersion = ($expectedLockVersion instanceof \DateTime) ? $expectedLockVersion->getTimestamp() : $expectedLockVersion; - $actualLockVersion = ($actualLockVersion instanceof \DateTime) ? $actualLockVersion->getTimestamp() : $actualLockVersion; - - return new self("The optimistic lock failed, version " . $expectedLockVersion . " was expected, but is actually ".$actualLockVersion, $entity); - } - - /** - * @param string $entityName - * - * @return OptimisticLockException - */ - public static function notVersioned($entityName) - { - return new self("Cannot obtain optimistic lock on unversioned entity " . $entityName, null); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/PersistentCollection.php b/vendor/doctrine/orm/lib/Doctrine/ORM/PersistentCollection.php deleted file mode 100644 index 7d52d53..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/PersistentCollection.php +++ /dev/null @@ -1,734 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -use Doctrine\Common\Collections\AbstractLazyCollection; -use Doctrine\Common\Collections\Collection; -use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Selectable; -use Doctrine\Common\Collections\Criteria; -use Doctrine\ORM\Mapping\ClassMetadata; -use function get_class; - -/** - * A PersistentCollection represents a collection of elements that have persistent state. - * - * Collections of entities represent only the associations (links) to those entities. - * That means, if the collection is part of a many-many mapping and you remove - * entities from the collection, only the links in the relation table are removed (on flush). - * Similarly, if you remove entities from a collection that is part of a one-many - * mapping this will only result in the nulling out of the foreign keys on flush. - * - * @since 2.0 - * @author Konsta Vesterinen - * @author Roman Borschel - * @author Giorgio Sironi - * @author Stefano Rodriguez - */ -final class PersistentCollection extends AbstractLazyCollection implements Selectable -{ - /** - * A snapshot of the collection at the moment it was fetched from the database. - * This is used to create a diff of the collection at commit time. - * - * @var array - */ - private $snapshot = []; - - /** - * The entity that owns this collection. - * - * @var object - */ - private $owner; - - /** - * The association mapping the collection belongs to. - * This is currently either a OneToManyMapping or a ManyToManyMapping. - * - * @var array - */ - private $association; - - /** - * The EntityManager that manages the persistence of the collection. - * - * @var \Doctrine\ORM\EntityManagerInterface - */ - private $em; - - /** - * The name of the field on the target entities that points to the owner - * of the collection. This is only set if the association is bi-directional. - * - * @var string - */ - private $backRefFieldName; - - /** - * The class descriptor of the collection's entity type. - * - * @var ClassMetadata - */ - private $typeClass; - - /** - * Whether the collection is dirty and needs to be synchronized with the database - * when the UnitOfWork that manages its persistent state commits. - * - * @var boolean - */ - private $isDirty = false; - - /** - * Creates a new persistent collection. - * - * @param EntityManagerInterface $em The EntityManager the collection will be associated with. - * @param ClassMetadata $class The class descriptor of the entity type of this collection. - * @param Collection $collection The collection elements. - */ - public function __construct(EntityManagerInterface $em, $class, Collection $collection) - { - $this->collection = $collection; - $this->em = $em; - $this->typeClass = $class; - $this->initialized = true; - } - - /** - * INTERNAL: - * Sets the collection's owning entity together with the AssociationMapping that - * describes the association between the owner and the elements of the collection. - * - * @param object $entity - * @param array $assoc - * - * @return void - */ - public function setOwner($entity, array $assoc) - { - $this->owner = $entity; - $this->association = $assoc; - $this->backRefFieldName = $assoc['inversedBy'] ?: $assoc['mappedBy']; - } - - /** - * INTERNAL: - * Gets the collection owner. - * - * @return object - */ - public function getOwner() - { - return $this->owner; - } - - /** - * @return Mapping\ClassMetadata - */ - public function getTypeClass() - { - return $this->typeClass; - } - - /** - * INTERNAL: - * Adds an element to a collection during hydration. This will automatically - * complete bidirectional associations in the case of a one-to-many association. - * - * @param mixed $element The element to add. - * - * @return void - */ - public function hydrateAdd($element) - { - $this->collection->add($element); - - // If _backRefFieldName is set and its a one-to-many association, - // we need to set the back reference. - if ($this->backRefFieldName && $this->association['type'] === ClassMetadata::ONE_TO_MANY) { - // Set back reference to owner - $this->typeClass->reflFields[$this->backRefFieldName]->setValue( - $element, $this->owner - ); - - $this->em->getUnitOfWork()->setOriginalEntityProperty( - spl_object_hash($element), $this->backRefFieldName, $this->owner - ); - } - } - - /** - * INTERNAL: - * Sets a keyed element in the collection during hydration. - * - * @param mixed $key The key to set. - * @param mixed $element The element to set. - * - * @return void - */ - public function hydrateSet($key, $element) - { - $this->collection->set($key, $element); - - // If _backRefFieldName is set, then the association is bidirectional - // and we need to set the back reference. - if ($this->backRefFieldName && $this->association['type'] === ClassMetadata::ONE_TO_MANY) { - // Set back reference to owner - $this->typeClass->reflFields[$this->backRefFieldName]->setValue( - $element, $this->owner - ); - } - } - - /** - * Initializes the collection by loading its contents from the database - * if the collection is not yet initialized. - * - * @return void - */ - public function initialize() - { - if ($this->initialized || ! $this->association) { - return; - } - - $this->doInitialize(); - - $this->initialized = true; - } - - /** - * INTERNAL: - * Tells this collection to take a snapshot of its current state. - * - * @return void - */ - public function takeSnapshot() - { - $this->snapshot = $this->collection->toArray(); - $this->isDirty = false; - } - - /** - * INTERNAL: - * Returns the last snapshot of the elements in the collection. - * - * @return array The last snapshot of the elements. - */ - public function getSnapshot() - { - return $this->snapshot; - } - - /** - * INTERNAL: - * getDeleteDiff - * - * @return array - */ - public function getDeleteDiff() - { - return array_udiff_assoc( - $this->snapshot, - $this->collection->toArray(), - function($a, $b) { return $a === $b ? 0 : 1; } - ); - } - - /** - * INTERNAL: - * getInsertDiff - * - * @return array - */ - public function getInsertDiff() - { - return array_udiff_assoc( - $this->collection->toArray(), - $this->snapshot, - function($a, $b) { return $a === $b ? 0 : 1; } - ); - } - - /** - * INTERNAL: Gets the association mapping of the collection. - * - * @return array - */ - public function getMapping() - { - return $this->association; - } - - /** - * Marks this collection as changed/dirty. - * - * @return void - */ - private function changed() - { - if ($this->isDirty) { - return; - } - - $this->isDirty = true; - - if ($this->association !== null && - $this->association['isOwningSide'] && - $this->association['type'] === ClassMetadata::MANY_TO_MANY && - $this->owner && - $this->em->getClassMetadata(get_class($this->owner))->isChangeTrackingNotify()) { - $this->em->getUnitOfWork()->scheduleForDirtyCheck($this->owner); - } - } - - /** - * Gets a boolean flag indicating whether this collection is dirty which means - * its state needs to be synchronized with the database. - * - * @return boolean TRUE if the collection is dirty, FALSE otherwise. - */ - public function isDirty() - { - return $this->isDirty; - } - - /** - * Sets a boolean flag, indicating whether this collection is dirty. - * - * @param boolean $dirty Whether the collection should be marked dirty or not. - * - * @return void - */ - public function setDirty($dirty) - { - $this->isDirty = $dirty; - } - - /** - * Sets the initialized flag of the collection, forcing it into that state. - * - * @param boolean $bool - * - * @return void - */ - public function setInitialized($bool) - { - $this->initialized = $bool; - } - - /** - * {@inheritdoc} - */ - public function remove($key) - { - // TODO: If the keys are persistent as well (not yet implemented) - // and the collection is not initialized and orphanRemoval is - // not used we can issue a straight SQL delete/update on the - // association (table). Without initializing the collection. - $removed = parent::remove($key); - - if ( ! $removed) { - return $removed; - } - - $this->changed(); - - if ($this->association !== null && - $this->association['type'] & ClassMetadata::TO_MANY && - $this->owner && - $this->association['orphanRemoval']) { - $this->em->getUnitOfWork()->scheduleOrphanRemoval($removed); - } - - return $removed; - } - - /** - * {@inheritdoc} - */ - public function removeElement($element) - { - if ( ! $this->initialized && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) { - if ($this->collection->contains($element)) { - return $this->collection->removeElement($element); - } - - $persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association); - - return $persister->removeElement($this, $element); - } - - $removed = parent::removeElement($element); - - if ( ! $removed) { - return $removed; - } - - $this->changed(); - - if ($this->association !== null && - $this->association['type'] & ClassMetadata::TO_MANY && - $this->owner && - $this->association['orphanRemoval']) { - $this->em->getUnitOfWork()->scheduleOrphanRemoval($element); - } - - return $removed; - } - - /** - * {@inheritdoc} - */ - public function containsKey($key) - { - if (! $this->initialized && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY - && isset($this->association['indexBy'])) { - $persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association); - - return $this->collection->containsKey($key) || $persister->containsKey($this, $key); - } - - return parent::containsKey($key); - } - - /** - * {@inheritdoc} - */ - public function contains($element) - { - if ( ! $this->initialized && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) { - $persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association); - - return $this->collection->contains($element) || $persister->contains($this, $element); - } - - return parent::contains($element); - } - - /** - * {@inheritdoc} - */ - public function get($key) - { - if ( ! $this->initialized - && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY - && isset($this->association['indexBy']) - ) { - if (!$this->typeClass->isIdentifierComposite && $this->typeClass->isIdentifier($this->association['indexBy'])) { - return $this->em->find($this->typeClass->name, $key); - } - - return $this->em->getUnitOfWork()->getCollectionPersister($this->association)->get($this, $key); - } - - return parent::get($key); - } - - /** - * {@inheritdoc} - */ - public function count() - { - if (! $this->initialized && $this->association !== null && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) { - $persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association); - - return $persister->count($this) + ($this->isDirty ? $this->collection->count() : 0); - } - - return parent::count(); - } - - /** - * {@inheritdoc} - */ - public function set($key, $value) - { - parent::set($key, $value); - - $this->changed(); - - if (is_object($value) && $this->em) { - $this->em->getUnitOfWork()->cancelOrphanRemoval($value); - } - } - - /** - * {@inheritdoc} - */ - public function add($value) - { - $this->collection->add($value); - - $this->changed(); - - if (is_object($value) && $this->em) { - $this->em->getUnitOfWork()->cancelOrphanRemoval($value); - } - - return true; - } - - /* ArrayAccess implementation */ - - /** - * {@inheritdoc} - */ - public function offsetExists($offset) - { - return $this->containsKey($offset); - } - - /** - * {@inheritdoc} - */ - public function offsetGet($offset) - { - return $this->get($offset); - } - - /** - * {@inheritdoc} - */ - public function offsetSet($offset, $value) - { - if ( ! isset($offset)) { - $this->add($value); - return; - } - - $this->set($offset, $value); - } - - /** - * {@inheritdoc} - */ - public function offsetUnset($offset) - { - return $this->remove($offset); - } - - /** - * {@inheritdoc} - */ - public function isEmpty() - { - return $this->collection->isEmpty() && $this->count() === 0; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - if ($this->initialized && $this->isEmpty()) { - $this->collection->clear(); - - return; - } - - $uow = $this->em->getUnitOfWork(); - - if ($this->association['type'] & ClassMetadata::TO_MANY && - $this->association['orphanRemoval'] && - $this->owner) { - // we need to initialize here, as orphan removal acts like implicit cascadeRemove, - // hence for event listeners we need the objects in memory. - $this->initialize(); - - foreach ($this->collection as $element) { - $uow->scheduleOrphanRemoval($element); - } - } - - $this->collection->clear(); - - $this->initialized = true; // direct call, {@link initialize()} is too expensive - - if ($this->association['isOwningSide'] && $this->owner) { - $this->changed(); - - $uow->scheduleCollectionDeletion($this); - - $this->takeSnapshot(); - } - } - - /** - * Called by PHP when this collection is serialized. Ensures that only the - * elements are properly serialized. - * - * Internal note: Tried to implement Serializable first but that did not work well - * with circular references. This solution seems simpler and works well. - * - * @return array - */ - public function __sleep() - { - return ['collection', 'initialized']; - } - - /** - * Extracts 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|null $length - * - * @return array - */ - public function slice($offset, $length = null) - { - if ( ! $this->initialized && ! $this->isDirty && $this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) { - $persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association); - - return $persister->slice($this, $offset, $length); - } - - return parent::slice($offset, $length); - } - - /** - * Cleans up internal state of cloned persistent collection. - * - * The following problems have to be prevented: - * 1. Added entities are added to old PC - * 2. New collection is not dirty, if reused on other entity nothing - * changes. - * 3. Snapshot leads to invalid diffs being generated. - * 4. Lazy loading grabs entities from old owner object. - * 5. New collection is connected to old owner and leads to duplicate keys. - * - * @return void - */ - public function __clone() - { - if (is_object($this->collection)) { - $this->collection = clone $this->collection; - } - - $this->initialize(); - - $this->owner = null; - $this->snapshot = []; - - $this->changed(); - } - - /** - * Selects all elements from a selectable that match the expression and - * return a new collection containing these elements. - * - * @param \Doctrine\Common\Collections\Criteria $criteria - * - * @return Collection - * - * @throws \RuntimeException - */ - public function matching(Criteria $criteria) - { - if ($this->isDirty) { - $this->initialize(); - } - - if ($this->initialized) { - return $this->collection->matching($criteria); - } - - if ($this->association['type'] === ClassMetadata::MANY_TO_MANY) { - $persister = $this->em->getUnitOfWork()->getCollectionPersister($this->association); - - return new ArrayCollection($persister->loadCriteria($this, $criteria)); - } - - $builder = Criteria::expr(); - $ownerExpression = $builder->eq($this->backRefFieldName, $this->owner); - $expression = $criteria->getWhereExpression(); - $expression = $expression ? $builder->andX($expression, $ownerExpression) : $ownerExpression; - - $criteria = clone $criteria; - $criteria->where($expression); - $criteria->orderBy($criteria->getOrderings() ?: $this->association['orderBy'] ?? []); - - $persister = $this->em->getUnitOfWork()->getEntityPersister($this->association['targetEntity']); - - return ($this->association['fetch'] === ClassMetadata::FETCH_EXTRA_LAZY) - ? new LazyCriteriaCollection($persister, $criteria) - : new ArrayCollection($persister->loadCriteria($criteria)); - } - - /** - * Retrieves the wrapped Collection instance. - * - * @return \Doctrine\Common\Collections\Collection - */ - public function unwrap() - { - return $this->collection; - } - - /** - * {@inheritdoc} - */ - protected function doInitialize() - { - // Has NEW objects added through add(). Remember them. - $newlyAddedDirtyObjects = []; - - if ($this->isDirty) { - $newlyAddedDirtyObjects = $this->collection->toArray(); - } - - $this->collection->clear(); - $this->em->getUnitOfWork()->loadCollection($this); - $this->takeSnapshot(); - - if ($newlyAddedDirtyObjects) { - $this->restoreNewObjectsInDirtyCollection($newlyAddedDirtyObjects); - } - } - - /** - * @param object[] $newObjects - * - * Note: the only reason why this entire looping/complexity is performed via `spl_object_hash` - * is because we want to prevent using `array_udiff()`, which is likely to cause very - * high overhead (complexity of O(n^2)). `array_diff_key()` performs the operation in - * core, which is faster than using a callback for comparisons - */ - private function restoreNewObjectsInDirtyCollection(array $newObjects) : void - { - $loadedObjects = $this->collection->toArray(); - $newObjectsByOid = \array_combine(\array_map('spl_object_hash', $newObjects), $newObjects); - $loadedObjectsByOid = \array_combine(\array_map('spl_object_hash', $loadedObjects), $loadedObjects); - $newObjectsThatWereNotLoaded = \array_diff_key($newObjectsByOid, $loadedObjectsByOid); - - if ($newObjectsThatWereNotLoaded) { - // Reattach NEW objects added through add(), if any. - \array_walk($newObjectsThatWereNotLoaded, [$this->collection, 'add']); - - $this->isDirty = true; - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/AbstractCollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/AbstractCollectionPersister.php deleted file mode 100644 index 2e85b67..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/AbstractCollectionPersister.php +++ /dev/null @@ -1,95 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Persisters\Collection; - -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\UnitOfWork; - -/** - * Base class for all collection persisters. - * - * @since 2.0 - * @author Roman Borschel - */ -abstract class AbstractCollectionPersister implements CollectionPersister -{ - /** - * @var EntityManagerInterface - */ - protected $em; - - /** - * @var \Doctrine\DBAL\Connection - */ - protected $conn; - - /** - * @var UnitOfWork - */ - protected $uow; - - /** - * The database platform. - * - * @var \Doctrine\DBAL\Platforms\AbstractPlatform - */ - protected $platform; - - /** - * The quote strategy. - * - * @var \Doctrine\ORM\Mapping\QuoteStrategy - */ - protected $quoteStrategy; - - /** - * Initializes a new instance of a class derived from AbstractCollectionPersister. - * - * @param EntityManagerInterface $em - */ - public function __construct(EntityManagerInterface $em) - { - $this->em = $em; - $this->uow = $em->getUnitOfWork(); - $this->conn = $em->getConnection(); - $this->platform = $this->conn->getDatabasePlatform(); - $this->quoteStrategy = $em->getConfiguration()->getQuoteStrategy(); - } - - /** - * Check if entity is in a valid state for operations. - * - * @param object $entity - * - * @return bool - */ - protected function isValidEntityState($entity) - { - $entityState = $this->uow->getEntityState($entity, UnitOfWork::STATE_NEW); - - if ($entityState === UnitOfWork::STATE_NEW) { - return false; - } - - // If Entity is scheduled for inclusion, it is not in this collection. - // We can assure that because it would have return true before on array check - return ! ($entityState === UnitOfWork::STATE_MANAGED && $this->uow->isScheduledForInsert($entity)); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/CollectionPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/CollectionPersister.php deleted file mode 100644 index 36b5706..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/CollectionPersister.php +++ /dev/null @@ -1,122 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Persisters\Collection; - -use Doctrine\Common\Collections\Criteria; -use Doctrine\ORM\PersistentCollection; - -/** - * Collection persister interface - * Define the behavior that should be implemented by all collection persisters. - * - * @author Fabio B. Silva - * @since 2.5 - */ -interface CollectionPersister -{ - /** - * Deletes the persistent state represented by the given collection. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * - * @return void - */ - public function delete(PersistentCollection $collection); - - /** - * Updates the given collection, synchronizing its state with the database - * by inserting, updating and deleting individual elements. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * - * @return void - */ - public function update(PersistentCollection $collection); - - /** - * Counts the size of this persistent collection. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * - * @return integer - */ - public function count(PersistentCollection $collection); - - /** - * Slices elements. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * @param integer $offset - * @param integer $length - * - * @return array - */ - public function slice(PersistentCollection $collection, $offset, $length = null); - - /** - * Checks for existence of an element. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * @param object $element - * - * @return boolean - */ - public function contains(PersistentCollection $collection, $element); - - /** - * Checks for existence of a key. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * @param mixed $key - * - * @return boolean - */ - public function containsKey(PersistentCollection $collection, $key); - - /** - * Removes an element. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * @param object $element - * - * @return mixed - */ - public function removeElement(PersistentCollection $collection, $element); - - /** - * Gets an element by key. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * @param mixed $index - * - * @return mixed - */ - public function get(PersistentCollection $collection, $index); - - /** - * Loads association entities matching the given Criteria object. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * @param \Doctrine\Common\Collections\Criteria $criteria - * - * @return array - */ - public function loadCriteria(PersistentCollection $collection, Criteria $criteria); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php deleted file mode 100644 index c817f60..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/ManyToManyPersister.php +++ /dev/null @@ -1,787 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Persisters\Collection; - -use Doctrine\Common\Collections\Criteria; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Persisters\SqlValueVisitor; -use Doctrine\ORM\PersistentCollection; -use Doctrine\ORM\Query; -use Doctrine\ORM\Utility\PersisterHelper; - -/** - * Persister for many-to-many collections. - * - * @author Roman Borschel - * @author Guilherme Blanco - * @author Alexander - * @since 2.0 - */ -class ManyToManyPersister extends AbstractCollectionPersister -{ - /** - * {@inheritdoc} - */ - public function delete(PersistentCollection $collection) - { - $mapping = $collection->getMapping(); - - if ( ! $mapping['isOwningSide']) { - return; // ignore inverse side - } - - $types = []; - $class = $this->em->getClassMetadata($mapping['sourceEntity']); - - foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) { - $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $class, $this->em); - } - - $this->conn->executeUpdate($this->getDeleteSQL($collection), $this->getDeleteSQLParameters($collection), $types); - } - - /** - * {@inheritdoc} - */ - public function update(PersistentCollection $collection) - { - $mapping = $collection->getMapping(); - - if ( ! $mapping['isOwningSide']) { - return; // ignore inverse side - } - - list($deleteSql, $deleteTypes) = $this->getDeleteRowSQL($collection); - list($insertSql, $insertTypes) = $this->getInsertRowSQL($collection); - - foreach ($collection->getDeleteDiff() as $element) { - $this->conn->executeUpdate( - $deleteSql, - $this->getDeleteRowSQLParameters($collection, $element), - $deleteTypes - ); - } - - foreach ($collection->getInsertDiff() as $element) { - $this->conn->executeUpdate( - $insertSql, - $this->getInsertRowSQLParameters($collection, $element), - $insertTypes - ); - } - } - - /** - * {@inheritdoc} - */ - public function get(PersistentCollection $collection, $index) - { - $mapping = $collection->getMapping(); - - if ( ! isset($mapping['indexBy'])) { - throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections."); - } - - $persister = $this->uow->getEntityPersister($mapping['targetEntity']); - $mappedKey = $mapping['isOwningSide'] - ? $mapping['inversedBy'] - : $mapping['mappedBy']; - - return $persister->load([$mappedKey => $collection->getOwner(), $mapping['indexBy'] => $index], null, $mapping, [], 0, 1); - } - - /** - * {@inheritdoc} - */ - public function count(PersistentCollection $collection) - { - $conditions = []; - $params = []; - $types = []; - $mapping = $collection->getMapping(); - $id = $this->uow->getEntityIdentifier($collection->getOwner()); - $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - $association = ( ! $mapping['isOwningSide']) - ? $targetClass->associationMappings[$mapping['mappedBy']] - : $mapping; - - $joinTableName = $this->quoteStrategy->getJoinTableName($association, $sourceClass, $this->platform); - $joinColumns = ( ! $mapping['isOwningSide']) - ? $association['joinTable']['inverseJoinColumns'] - : $association['joinTable']['joinColumns']; - - foreach ($joinColumns as $joinColumn) { - $columnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $sourceClass, $this->platform); - $referencedName = $joinColumn['referencedColumnName']; - $conditions[] = 't.' . $columnName . ' = ?'; - $params[] = $id[$sourceClass->getFieldForColumn($referencedName)]; - $types[] = PersisterHelper::getTypeOfColumn($referencedName, $sourceClass, $this->em); - } - - list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($mapping); - - if ($filterSql) { - $conditions[] = $filterSql; - } - - // If there is a provided criteria, make part of conditions - // @todo Fix this. Current SQL returns something like: - // - /*if ($criteria && ($expression = $criteria->getWhereExpression()) !== null) { - // A join is needed on the target entity - $targetTableName = $this->quoteStrategy->getTableName($targetClass, $this->platform); - $targetJoinSql = ' JOIN ' . $targetTableName . ' te' - . ' ON' . implode(' AND ', $this->getOnConditionSQL($association)); - - // And criteria conditions needs to be added - $persister = $this->uow->getEntityPersister($targetClass->name); - $visitor = new SqlExpressionVisitor($persister, $targetClass); - $conditions[] = $visitor->dispatch($expression); - - $joinTargetEntitySQL = $targetJoinSql . $joinTargetEntitySQL; - }*/ - - $sql = 'SELECT COUNT(*)' - . ' FROM ' . $joinTableName . ' t' - . $joinTargetEntitySQL - . ' WHERE ' . implode(' AND ', $conditions); - - return $this->conn->fetchColumn($sql, $params, 0, $types); - } - - /** - * {@inheritDoc} - */ - public function slice(PersistentCollection $collection, $offset, $length = null) - { - $mapping = $collection->getMapping(); - $persister = $this->uow->getEntityPersister($mapping['targetEntity']); - - return $persister->getManyToManyCollection($mapping, $collection->getOwner(), $offset, $length); - } - /** - * {@inheritdoc} - */ - public function containsKey(PersistentCollection $collection, $key) - { - $mapping = $collection->getMapping(); - - if ( ! isset($mapping['indexBy'])) { - throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections."); - } - - list($quotedJoinTable, $whereClauses, $params, $types) = $this->getJoinTableRestrictionsWithKey($collection, $key, true); - - $sql = 'SELECT 1 FROM ' . $quotedJoinTable . ' WHERE ' . implode(' AND ', $whereClauses); - - return (bool) $this->conn->fetchColumn($sql, $params, 0, $types); - } - - /** - * {@inheritDoc} - */ - public function contains(PersistentCollection $collection, $element) - { - if ( ! $this->isValidEntityState($element)) { - return false; - } - - list($quotedJoinTable, $whereClauses, $params, $types) = $this->getJoinTableRestrictions($collection, $element, true); - - $sql = 'SELECT 1 FROM ' . $quotedJoinTable . ' WHERE ' . implode(' AND ', $whereClauses); - - return (bool) $this->conn->fetchColumn($sql, $params, 0, $types); - } - - /** - * {@inheritDoc} - */ - public function removeElement(PersistentCollection $collection, $element) - { - if ( ! $this->isValidEntityState($element)) { - return false; - } - - list($quotedJoinTable, $whereClauses, $params, $types) = $this->getJoinTableRestrictions($collection, $element, false); - - $sql = 'DELETE FROM ' . $quotedJoinTable . ' WHERE ' . implode(' AND ', $whereClauses); - - return (bool) $this->conn->executeUpdate($sql, $params, $types); - } - - /** - * {@inheritDoc} - */ - public function loadCriteria(PersistentCollection $collection, Criteria $criteria) - { - $mapping = $collection->getMapping(); - $owner = $collection->getOwner(); - $ownerMetadata = $this->em->getClassMetadata(get_class($owner)); - $id = $this->uow->getEntityIdentifier($owner); - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - $onConditions = $this->getOnConditionSQL($mapping); - $whereClauses = $params = []; - - if ( ! $mapping['isOwningSide']) { - $associationSourceClass = $targetClass; - $mapping = $targetClass->associationMappings[$mapping['mappedBy']]; - $sourceRelationMode = 'relationToTargetKeyColumns'; - } else { - $associationSourceClass = $ownerMetadata; - $sourceRelationMode = 'relationToSourceKeyColumns'; - } - - foreach ($mapping[$sourceRelationMode] as $key => $value) { - $whereClauses[] = sprintf('t.%s = ?', $key); - $params[] = $ownerMetadata->containsForeignIdentifier - ? $id[$ownerMetadata->getFieldForColumn($value)] - : $id[$ownerMetadata->fieldNames[$value]]; - } - - $parameters = $this->expandCriteriaParameters($criteria); - - foreach ($parameters as $parameter) { - [$name, $value, $operator] = $parameter; - - $field = $this->quoteStrategy->getColumnName($name, $targetClass, $this->platform); - $whereClauses[] = sprintf('te.%s %s ?', $field, $operator); - $params[] = $value; - } - - $tableName = $this->quoteStrategy->getTableName($targetClass, $this->platform); - $joinTable = $this->quoteStrategy->getJoinTableName($mapping, $associationSourceClass, $this->platform); - - $rsm = new Query\ResultSetMappingBuilder($this->em); - $rsm->addRootEntityFromClassMetadata($targetClass->name, 'te'); - - $sql = 'SELECT ' . $rsm->generateSelectClause() - . ' FROM ' . $tableName . ' te' - . ' JOIN ' . $joinTable . ' t ON' - . implode(' AND ', $onConditions) - . ' WHERE ' . implode(' AND ', $whereClauses); - - $sql .= $this->getOrderingSql($criteria, $targetClass); - - $sql .= $this->getLimitSql($criteria); - - $stmt = $this->conn->executeQuery($sql, $params); - - return $this - ->em - ->newHydrator(Query::HYDRATE_OBJECT) - ->hydrateAll($stmt, $rsm); - } - - /** - * Generates the filter SQL for a given mapping. - * - * This method is not used for actually grabbing the related entities - * but when the extra-lazy collection methods are called on a filtered - * association. This is why besides the many to many table we also - * have to join in the actual entities table leading to additional - * JOIN. - * - * @param array $mapping Array containing mapping information. - * - * @return string[] ordered tuple: - * - JOIN condition to add to the SQL - * - WHERE condition to add to the SQL - */ - public function getFilterSql($mapping) - { - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - $rootClass = $this->em->getClassMetadata($targetClass->rootEntityName); - $filterSql = $this->generateFilterConditionSQL($rootClass, 'te'); - - if ('' === $filterSql) { - return ['', '']; - } - - // A join is needed if there is filtering on the target entity - $tableName = $this->quoteStrategy->getTableName($rootClass, $this->platform); - $joinSql = ' JOIN ' . $tableName . ' te' - . ' ON' . implode(' AND ', $this->getOnConditionSQL($mapping)); - - return [$joinSql, $filterSql]; - } - - /** - * Generates the filter SQL for a given entity and table alias. - * - * @param ClassMetadata $targetEntity Metadata of the target entity. - * @param string $targetTableAlias The table alias of the joined/selected table. - * - * @return string The SQL query part to add to a query. - */ - protected function generateFilterConditionSQL(ClassMetadata $targetEntity, $targetTableAlias) - { - $filterClauses = []; - - foreach ($this->em->getFilters()->getEnabledFilters() as $filter) { - if ($filterExpr = $filter->addFilterConstraint($targetEntity, $targetTableAlias)) { - $filterClauses[] = '(' . $filterExpr . ')'; - } - } - - return $filterClauses - ? '(' . implode(' AND ', $filterClauses) . ')' - : ''; - } - - /** - * Generate ON condition - * - * @param array $mapping - * - * @return array - */ - protected function getOnConditionSQL($mapping) - { - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - $association = ( ! $mapping['isOwningSide']) - ? $targetClass->associationMappings[$mapping['mappedBy']] - : $mapping; - - $joinColumns = $mapping['isOwningSide'] - ? $association['joinTable']['inverseJoinColumns'] - : $association['joinTable']['joinColumns']; - - $conditions = []; - - foreach ($joinColumns as $joinColumn) { - $joinColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); - $refColumnName = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform); - - $conditions[] = ' t.' . $joinColumnName . ' = ' . 'te.' . $refColumnName; - } - - return $conditions; - } - - /** - * {@inheritdoc} - * - * @override - */ - protected function getDeleteSQL(PersistentCollection $collection) - { - $columns = []; - $mapping = $collection->getMapping(); - $class = $this->em->getClassMetadata(get_class($collection->getOwner())); - $joinTable = $this->quoteStrategy->getJoinTableName($mapping, $class, $this->platform); - - foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) { - $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); - } - - return 'DELETE FROM ' . $joinTable - . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?'; - } - - /** - * {@inheritdoc} - * - * Internal note: Order of the parameters must be the same as the order of the columns in getDeleteSql. - * @override - */ - protected function getDeleteSQLParameters(PersistentCollection $collection) - { - $mapping = $collection->getMapping(); - $identifier = $this->uow->getEntityIdentifier($collection->getOwner()); - - // Optimization for single column identifier - if (count($mapping['relationToSourceKeyColumns']) === 1) { - return [reset($identifier)]; - } - - // Composite identifier - $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); - $params = []; - - foreach ($mapping['relationToSourceKeyColumns'] as $columnName => $refColumnName) { - $params[] = isset($sourceClass->fieldNames[$refColumnName]) - ? $identifier[$sourceClass->fieldNames[$refColumnName]] - : $identifier[$sourceClass->getFieldForColumn($refColumnName)]; - } - - return $params; - } - - /** - * Gets the SQL statement used for deleting a row from the collection. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * - * @return string[]|string[][] ordered tuple containing the SQL to be executed and an array - * of types for bound parameters - */ - protected function getDeleteRowSQL(PersistentCollection $collection) - { - $mapping = $collection->getMapping(); - $class = $this->em->getClassMetadata($mapping['sourceEntity']); - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - $columns = []; - $types = []; - - foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) { - $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); - $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $class, $this->em); - } - - foreach ($mapping['joinTable']['inverseJoinColumns'] as $joinColumn) { - $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); - $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); - } - - return [ - 'DELETE FROM ' . $this->quoteStrategy->getJoinTableName($mapping, $class, $this->platform) - . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?', - $types, - ]; - } - - /** - * Gets the SQL parameters for the corresponding SQL statement to delete the given - * element from the given collection. - * - * Internal note: Order of the parameters must be the same as the order of the columns in getDeleteRowSql. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * @param mixed $element - * - * @return array - */ - protected function getDeleteRowSQLParameters(PersistentCollection $collection, $element) - { - return $this->collectJoinTableColumnParameters($collection, $element); - } - - /** - * Gets the SQL statement used for inserting a row in the collection. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * - * @return string[]|string[][] ordered tuple containing the SQL to be executed and an array - * of types for bound parameters - */ - protected function getInsertRowSQL(PersistentCollection $collection) - { - $columns = []; - $types = []; - $mapping = $collection->getMapping(); - $class = $this->em->getClassMetadata($mapping['sourceEntity']); - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - - foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) { - $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); - $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $class, $this->em); - } - - foreach ($mapping['joinTable']['inverseJoinColumns'] as $joinColumn) { - $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); - $types[] = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); - } - - return [ - 'INSERT INTO ' . $this->quoteStrategy->getJoinTableName($mapping, $class, $this->platform) - . ' (' . implode(', ', $columns) . ')' - . ' VALUES' - . ' (' . implode(', ', array_fill(0, count($columns), '?')) . ')', - $types, - ]; - } - - /** - * Gets the SQL parameters for the corresponding SQL statement to insert the given - * element of the given collection into the database. - * - * Internal note: Order of the parameters must be the same as the order of the columns in getInsertRowSql. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * @param mixed $element - * - * @return array - */ - protected function getInsertRowSQLParameters(PersistentCollection $collection, $element) - { - return $this->collectJoinTableColumnParameters($collection, $element); - } - - /** - * Collects the parameters for inserting/deleting on the join table in the order - * of the join table columns as specified in ManyToManyMapping#joinTableColumns. - * - * @param \Doctrine\ORM\PersistentCollection $collection - * @param object $element - * - * @return array - */ - private function collectJoinTableColumnParameters(PersistentCollection $collection, $element) - { - $params = []; - $mapping = $collection->getMapping(); - $isComposite = count($mapping['joinTableColumns']) > 2; - - $identifier1 = $this->uow->getEntityIdentifier($collection->getOwner()); - $identifier2 = $this->uow->getEntityIdentifier($element); - - $class1 = $class2 = null; - if ($isComposite) { - $class1 = $this->em->getClassMetadata(get_class($collection->getOwner())); - $class2 = $collection->getTypeClass(); - } - - foreach ($mapping['joinTableColumns'] as $joinTableColumn) { - $isRelationToSource = isset($mapping['relationToSourceKeyColumns'][$joinTableColumn]); - - if ( ! $isComposite) { - $params[] = $isRelationToSource ? array_pop($identifier1) : array_pop($identifier2); - - continue; - } - - if ($isRelationToSource) { - $params[] = $identifier1[$class1->getFieldForColumn($mapping['relationToSourceKeyColumns'][$joinTableColumn])]; - - continue; - } - - $params[] = $identifier2[$class2->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])]; - } - - return $params; - } - - /** - * @param \Doctrine\ORM\PersistentCollection $collection - * @param string $key - * @param boolean $addFilters Whether the filter SQL should be included or not. - * - * @return array ordered vector: - * - quoted join table name - * - where clauses to be added for filtering - * - parameters to be bound for filtering - * - types of the parameters to be bound for filtering - */ - private function getJoinTableRestrictionsWithKey(PersistentCollection $collection, $key, $addFilters) - { - $filterMapping = $collection->getMapping(); - $mapping = $filterMapping; - $indexBy = $mapping['indexBy']; - $id = $this->uow->getEntityIdentifier($collection->getOwner()); - $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - - if (! $mapping['isOwningSide']) { - $associationSourceClass = $this->em->getClassMetadata($mapping['targetEntity']); - $mapping = $associationSourceClass->associationMappings[$mapping['mappedBy']]; - $joinColumns = $mapping['joinTable']['joinColumns']; - $sourceRelationMode = 'relationToTargetKeyColumns'; - $targetRelationMode = 'relationToSourceKeyColumns'; - } else { - $associationSourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); - $joinColumns = $mapping['joinTable']['inverseJoinColumns']; - $sourceRelationMode = 'relationToSourceKeyColumns'; - $targetRelationMode = 'relationToTargetKeyColumns'; - } - - $quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $associationSourceClass, $this->platform). ' t'; - $whereClauses = []; - $params = []; - $types = []; - - $joinNeeded = ! in_array($indexBy, $targetClass->identifier); - - if ($joinNeeded) { // extra join needed if indexBy is not a @id - $joinConditions = []; - - foreach ($joinColumns as $joinTableColumn) { - $joinConditions[] = 't.' . $joinTableColumn['name'] . ' = tr.' . $joinTableColumn['referencedColumnName']; - } - - $tableName = $this->quoteStrategy->getTableName($targetClass, $this->platform); - $quotedJoinTable .= ' JOIN ' . $tableName . ' tr ON ' . implode(' AND ', $joinConditions); - $columnName = $targetClass->getColumnName($indexBy); - - $whereClauses[] = 'tr.' . $columnName . ' = ?'; - $params[] = $key; - $types[] = PersisterHelper::getTypeOfColumn($columnName, $targetClass, $this->em); - } - - foreach ($mapping['joinTableColumns'] as $joinTableColumn) { - if (isset($mapping[$sourceRelationMode][$joinTableColumn])) { - $column = $mapping[$sourceRelationMode][$joinTableColumn]; - $whereClauses[] = 't.' . $joinTableColumn . ' = ?'; - $params[] = $sourceClass->containsForeignIdentifier - ? $id[$sourceClass->getFieldForColumn($column)] - : $id[$sourceClass->fieldNames[$column]]; - $types[] = PersisterHelper::getTypeOfColumn($column, $sourceClass, $this->em); - } elseif ( ! $joinNeeded) { - $column = $mapping[$targetRelationMode][$joinTableColumn]; - - $whereClauses[] = 't.' . $joinTableColumn . ' = ?'; - $params[] = $key; - $types[] = PersisterHelper::getTypeOfColumn($column, $targetClass, $this->em); - } - } - - if ($addFilters) { - list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($filterMapping); - - if ($filterSql) { - $quotedJoinTable .= ' ' . $joinTargetEntitySQL; - $whereClauses[] = $filterSql; - } - } - - return [$quotedJoinTable, $whereClauses, $params, $types]; - } - - /** - * @param \Doctrine\ORM\PersistentCollection $collection - * @param object $element - * @param boolean $addFilters Whether the filter SQL should be included or not. - * - * @return array ordered vector: - * - quoted join table name - * - where clauses to be added for filtering - * - parameters to be bound for filtering - * - types of the parameters to be bound for filtering - */ - private function getJoinTableRestrictions(PersistentCollection $collection, $element, $addFilters) - { - $filterMapping = $collection->getMapping(); - $mapping = $filterMapping; - - if ( ! $mapping['isOwningSide']) { - $sourceClass = $this->em->getClassMetadata($mapping['targetEntity']); - $targetClass = $this->em->getClassMetadata($mapping['sourceEntity']); - $sourceId = $this->uow->getEntityIdentifier($element); - $targetId = $this->uow->getEntityIdentifier($collection->getOwner()); - - $mapping = $sourceClass->associationMappings[$mapping['mappedBy']]; - } else { - $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - $sourceId = $this->uow->getEntityIdentifier($collection->getOwner()); - $targetId = $this->uow->getEntityIdentifier($element); - } - - $quotedJoinTable = $this->quoteStrategy->getJoinTableName($mapping, $sourceClass, $this->platform); - $whereClauses = []; - $params = []; - $types = []; - - foreach ($mapping['joinTableColumns'] as $joinTableColumn) { - $whereClauses[] = ($addFilters ? 't.' : '') . $joinTableColumn . ' = ?'; - - if (isset($mapping['relationToTargetKeyColumns'][$joinTableColumn])) { - $targetColumn = $mapping['relationToTargetKeyColumns'][$joinTableColumn]; - $params[] = $targetId[$targetClass->getFieldForColumn($targetColumn)]; - $types[] = PersisterHelper::getTypeOfColumn($targetColumn, $targetClass, $this->em); - - continue; - } - - // relationToSourceKeyColumns - $targetColumn = $mapping['relationToSourceKeyColumns'][$joinTableColumn]; - $params[] = $sourceId[$sourceClass->getFieldForColumn($targetColumn)]; - $types[] = PersisterHelper::getTypeOfColumn($targetColumn, $sourceClass, $this->em); - } - - if ($addFilters) { - $quotedJoinTable .= ' t'; - - list($joinTargetEntitySQL, $filterSql) = $this->getFilterSql($filterMapping); - - if ($filterSql) { - $quotedJoinTable .= ' ' . $joinTargetEntitySQL; - $whereClauses[] = $filterSql; - } - } - - return [$quotedJoinTable, $whereClauses, $params, $types]; - } - - /** - * Expands Criteria Parameters by walking the expressions and grabbing all - * parameters and types from it. - * - * @param \Doctrine\Common\Collections\Criteria $criteria - * - * @return array - */ - private function expandCriteriaParameters(Criteria $criteria) - { - $expression = $criteria->getWhereExpression(); - - if ($expression === null) { - return []; - } - - $valueVisitor = new SqlValueVisitor(); - - $valueVisitor->dispatch($expression); - - list(, $types) = $valueVisitor->getParamsAndTypes(); - - return $types; - } - - /** - * @param Criteria $criteria - * @param ClassMetadata $targetClass - * @return string - */ - private function getOrderingSql(Criteria $criteria, ClassMetadata $targetClass) - { - $orderings = $criteria->getOrderings(); - if ($orderings) { - $orderBy = []; - foreach ($orderings as $name => $direction) { - $field = $this->quoteStrategy->getColumnName( - $name, - $targetClass, - $this->platform - ); - $orderBy[] = $field . ' ' . $direction; - } - - return ' ORDER BY ' . implode(', ', $orderBy); - } - return ''; - } - - /** - * @param Criteria $criteria - * @return string - * @throws \Doctrine\DBAL\DBALException - */ - private function getLimitSql(Criteria $criteria) - { - $limit = $criteria->getMaxResults(); - $offset = $criteria->getFirstResult(); - if ($limit !== null || $offset !== null) { - return $this->platform->modifyLimitQuery('', $limit, $offset); - } - return ''; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/OneToManyPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/OneToManyPersister.php deleted file mode 100644 index 8211507..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Collection/OneToManyPersister.php +++ /dev/null @@ -1,291 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Persisters\Collection; - -use Doctrine\Common\Collections\Criteria; -use Doctrine\DBAL\Types\Type; -use Doctrine\ORM\PersistentCollection; -use Doctrine\ORM\Utility\PersisterHelper; - -/** - * Persister for one-to-many collections. - * - * @author Roman Borschel - * @author Guilherme Blanco - * @author Alexander - * @since 2.0 - */ -class OneToManyPersister extends AbstractCollectionPersister -{ - /** - * {@inheritdoc} - */ - public function delete(PersistentCollection $collection) - { - // The only valid case here is when you have weak entities. In this - // scenario, you have @OneToMany with orphanRemoval=true, and replacing - // the entire collection with a new would trigger this operation. - $mapping = $collection->getMapping(); - - if ( ! $mapping['orphanRemoval']) { - // Handling non-orphan removal should never happen, as @OneToMany - // can only be inverse side. For owning side one to many, it is - // required to have a join table, which would classify as a ManyToManyPersister. - return; - } - - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - - return $targetClass->isInheritanceTypeJoined() - ? $this->deleteJoinedEntityCollection($collection) - : $this->deleteEntityCollection($collection); - } - - /** - * {@inheritdoc} - */ - public function update(PersistentCollection $collection) - { - // This can never happen. One to many can only be inverse side. - // For owning side one to many, it is required to have a join table, - // then classifying it as a ManyToManyPersister. - return; - } - - /** - * {@inheritdoc} - */ - public function get(PersistentCollection $collection, $index) - { - $mapping = $collection->getMapping(); - - if ( ! isset($mapping['indexBy'])) { - throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections."); - } - - $persister = $this->uow->getEntityPersister($mapping['targetEntity']); - - return $persister->load( - [ - $mapping['mappedBy'] => $collection->getOwner(), - $mapping['indexBy'] => $index - ], - null, - $mapping, - [], - null, - 1 - ); - } - - /** - * {@inheritdoc} - */ - public function count(PersistentCollection $collection) - { - $mapping = $collection->getMapping(); - $persister = $this->uow->getEntityPersister($mapping['targetEntity']); - - // only works with single id identifier entities. Will throw an - // exception in Entity Persisters if that is not the case for the - // 'mappedBy' field. - $criteria = new Criteria(Criteria::expr()->eq($mapping['mappedBy'], $collection->getOwner())); - - return $persister->count($criteria); - } - - /** - * {@inheritdoc} - */ - public function slice(PersistentCollection $collection, $offset, $length = null) - { - $mapping = $collection->getMapping(); - $persister = $this->uow->getEntityPersister($mapping['targetEntity']); - - return $persister->getOneToManyCollection($mapping, $collection->getOwner(), $offset, $length); - } - - /** - * {@inheritdoc} - */ - public function containsKey(PersistentCollection $collection, $key) - { - $mapping = $collection->getMapping(); - - if ( ! isset($mapping['indexBy'])) { - throw new \BadMethodCallException("Selecting a collection by index is only supported on indexed collections."); - } - - $persister = $this->uow->getEntityPersister($mapping['targetEntity']); - - // only works with single id identifier entities. Will throw an - // exception in Entity Persisters if that is not the case for the - // 'mappedBy' field. - $criteria = new Criteria(); - - $criteria->andWhere(Criteria::expr()->eq($mapping['mappedBy'], $collection->getOwner())); - $criteria->andWhere(Criteria::expr()->eq($mapping['indexBy'], $key)); - - return (bool) $persister->count($criteria); - } - - /** - * {@inheritdoc} - */ - public function contains(PersistentCollection $collection, $element) - { - if ( ! $this->isValidEntityState($element)) { - return false; - } - - $mapping = $collection->getMapping(); - $persister = $this->uow->getEntityPersister($mapping['targetEntity']); - - // only works with single id identifier entities. Will throw an - // exception in Entity Persisters if that is not the case for the - // 'mappedBy' field. - $criteria = new Criteria(Criteria::expr()->eq($mapping['mappedBy'], $collection->getOwner())); - - return $persister->exists($element, $criteria); - } - - /** - * {@inheritdoc} - */ - public function removeElement(PersistentCollection $collection, $element) - { - $mapping = $collection->getMapping(); - - if ( ! $mapping['orphanRemoval']) { - // no-op: this is not the owning side, therefore no operations should be applied - return false; - } - - if ( ! $this->isValidEntityState($element)) { - return false; - } - - return $this - ->uow - ->getEntityPersister($mapping['targetEntity']) - ->delete($element); - } - - /** - * {@inheritdoc} - */ - public function loadCriteria(PersistentCollection $collection, Criteria $criteria) - { - throw new \BadMethodCallException("Filtering a collection by Criteria is not supported by this CollectionPersister."); - } - - /** - * @param PersistentCollection $collection - * - * @return int - * - * @throws \Doctrine\DBAL\DBALException - */ - private function deleteEntityCollection(PersistentCollection $collection) - { - $mapping = $collection->getMapping(); - $identifier = $this->uow->getEntityIdentifier($collection->getOwner()); - $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - $columns = []; - $parameters = []; - - foreach ($targetClass->associationMappings[$mapping['mappedBy']]['joinColumns'] as $joinColumn) { - $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); - $parameters[] = $identifier[$sourceClass->getFieldForColumn($joinColumn['referencedColumnName'])]; - } - - $statement = 'DELETE FROM ' . $this->quoteStrategy->getTableName($targetClass, $this->platform) - . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?'; - - return $this->conn->executeUpdate($statement, $parameters); - } - - /** - * Delete Class Table Inheritance entities. - * A temporary table is needed to keep IDs to be deleted in both parent and child class' tables. - * - * Thanks Steve Ebersole (Hibernate) for idea on how to tackle reliably this scenario, we owe him a beer! =) - * - * @param PersistentCollection $collection - * - * @return int - * - * @throws \Doctrine\DBAL\DBALException - */ - private function deleteJoinedEntityCollection(PersistentCollection $collection) - { - $mapping = $collection->getMapping(); - $sourceClass = $this->em->getClassMetadata($mapping['sourceEntity']); - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - $rootClass = $this->em->getClassMetadata($targetClass->rootEntityName); - - // 1) Build temporary table DDL - $tempTable = $this->platform->getTemporaryTableName($rootClass->getTemporaryIdTableName()); - $idColumnNames = $rootClass->getIdentifierColumnNames(); - $idColumnList = implode(', ', $idColumnNames); - $columnDefinitions = []; - - foreach ($idColumnNames as $idColumnName) { - $columnDefinitions[$idColumnName] = [ - 'notnull' => true, - 'type' => Type::getType(PersisterHelper::getTypeOfColumn($idColumnName, $rootClass, $this->em)), - ]; - } - - $statement = $this->platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable - . ' (' . $this->platform->getColumnDeclarationListSQL($columnDefinitions) . ')'; - - $this->conn->executeUpdate($statement); - - // 2) Build insert table records into temporary table - $query = $this->em->createQuery( - ' SELECT t0.' . implode(', t0.', $rootClass->getIdentifierFieldNames()) - . ' FROM ' . $targetClass->name . ' t0 WHERE t0.' . $mapping['mappedBy'] . ' = :owner' - )->setParameter('owner', $collection->getOwner()); - - $statement = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ') ' . $query->getSQL(); - $parameters = array_values($sourceClass->getIdentifierValues($collection->getOwner())); - $numDeleted = $this->conn->executeUpdate($statement, $parameters); - - // 3) Delete records on each table in the hierarchy - $classNames = array_merge($targetClass->parentClasses, [$targetClass->name], $targetClass->subClasses); - - foreach (array_reverse($classNames) as $className) { - $tableName = $this->quoteStrategy->getTableName($this->em->getClassMetadata($className), $this->platform); - $statement = 'DELETE FROM ' . $tableName . ' WHERE (' . $idColumnList . ')' - . ' IN (SELECT ' . $idColumnList . ' FROM ' . $tempTable . ')'; - - $this->conn->executeUpdate($statement); - } - - // 4) Drop temporary table - $statement = $this->platform->getDropTemporaryTableSQL($tempTable); - - $this->conn->executeUpdate($statement); - - return $numDeleted; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php deleted file mode 100644 index 79472b5..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php +++ /dev/null @@ -1,99 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Persisters\Entity; - -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\DBAL\Types\Type; - -/** - * Base class for entity persisters that implement a certain inheritance mapping strategy. - * All these persisters are assumed to use a discriminator column to discriminate entity - * types in the hierarchy. - * - * @author Roman Borschel - * @author Benjamin Eberlei - * @since 2.0 - */ -abstract class AbstractEntityInheritancePersister extends BasicEntityPersister -{ - /** - * {@inheritdoc} - */ - protected function prepareInsertData($entity) - { - $data = parent::prepareInsertData($entity); - - // Populate the discriminator column - $discColumn = $this->class->discriminatorColumn; - $this->columnTypes[$discColumn['name']] = $discColumn['type']; - $data[$this->getDiscriminatorColumnTableName()][$discColumn['name']] = $this->class->discriminatorValue; - - return $data; - } - - /** - * Gets the name of the table that contains the discriminator column. - * - * @return string The table name. - */ - abstract protected function getDiscriminatorColumnTableName(); - - /** - * {@inheritdoc} - */ - protected function getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r') - { - $tableAlias = $alias == 'r' ? '' : $alias; - $fieldMapping = $class->fieldMappings[$field]; - $columnAlias = $this->getSQLColumnAlias($fieldMapping['columnName']); - $sql = sprintf( - '%s.%s', - $this->getSQLTableAlias($class->name, $tableAlias), - $this->quoteStrategy->getColumnName($field, $class, $this->platform) - ); - - $this->currentPersisterContext->rsm->addFieldResult($alias, $columnAlias, $field, $class->name); - - if (isset($fieldMapping['requireSQLConversion'])) { - $type = Type::getType($fieldMapping['type']); - $sql = $type->convertToPHPValueSQL($sql, $this->platform); - } - - return $sql . ' AS ' . $columnAlias; - } - - /** - * @param string $tableAlias - * @param string $joinColumnName - * @param string $quotedColumnName - * - * @param string $type - * - * @return string - */ - protected function getSelectJoinColumnSQL($tableAlias, $joinColumnName, $quotedColumnName, $type) - { - $columnAlias = $this->getSQLColumnAlias($joinColumnName); - - $this->currentPersisterContext->rsm->addMetaResult('r', $columnAlias, $joinColumnName, false, $type); - - return $tableAlias . '.' . $quotedColumnName . ' AS ' . $columnAlias; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php deleted file mode 100644 index ea1f2ef..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php +++ /dev/null @@ -1,2095 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Persisters\Entity; - -use Doctrine\Common\Collections\Criteria; -use Doctrine\Common\Collections\Expr\Comparison; -use Doctrine\Common\Util\ClassUtils; -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\LockMode; -use Doctrine\DBAL\Types\Type; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\MappingException; -use Doctrine\ORM\OptimisticLockException; -use Doctrine\ORM\ORMException; -use Doctrine\ORM\PersistentCollection; -use Doctrine\ORM\Persisters\SqlExpressionVisitor; -use Doctrine\ORM\Persisters\SqlValueVisitor; -use Doctrine\ORM\Query; -use Doctrine\ORM\UnitOfWork; -use Doctrine\ORM\Utility\IdentifierFlattener; -use Doctrine\ORM\Utility\PersisterHelper; -use function array_map; -use function array_merge; -use function assert; -use function reset; - -/** - * A BasicEntityPersister maps an entity to a single table in a relational database. - * - * A persister is always responsible for a single entity type. - * - * EntityPersisters are used during a UnitOfWork to apply any changes to the persistent - * state of entities onto a relational database when the UnitOfWork is committed, - * as well as for basic querying of entities and their associations (not DQL). - * - * The persisting operations that are invoked during a commit of a UnitOfWork to - * persist the persistent entity state are: - * - * - {@link addInsert} : To schedule an entity for insertion. - * - {@link executeInserts} : To execute all scheduled insertions. - * - {@link update} : To update the persistent state of an entity. - * - {@link delete} : To delete the persistent state of an entity. - * - * As can be seen from the above list, insertions are batched and executed all at once - * for increased efficiency. - * - * The querying operations invoked during a UnitOfWork, either through direct find - * requests or lazy-loading, are the following: - * - * - {@link load} : Loads (the state of) a single, managed entity. - * - {@link loadAll} : Loads multiple, managed entities. - * - {@link loadOneToOneEntity} : Loads a one/many-to-one entity association (lazy-loading). - * - {@link loadOneToManyCollection} : Loads a one-to-many entity association (lazy-loading). - * - {@link loadManyToManyCollection} : Loads a many-to-many entity association (lazy-loading). - * - * The BasicEntityPersister implementation provides the default behavior for - * persisting and querying entities that are mapped to a single database table. - * - * Subclasses can be created to provide custom persisting and querying strategies, - * i.e. spanning multiple tables. - * - * @author Roman Borschel - * @author Giorgio Sironi - * @author Benjamin Eberlei - * @author Alexander - * @author Fabio B. Silva - * @author Rob Caiger - * @since 2.0 - */ -class BasicEntityPersister implements EntityPersister -{ - /** - * @var array - */ - static private $comparisonMap = [ - Comparison::EQ => '= %s', - Comparison::IS => '= %s', - Comparison::NEQ => '!= %s', - Comparison::GT => '> %s', - Comparison::GTE => '>= %s', - Comparison::LT => '< %s', - Comparison::LTE => '<= %s', - Comparison::IN => 'IN (%s)', - Comparison::NIN => 'NOT IN (%s)', - Comparison::CONTAINS => 'LIKE %s', - Comparison::STARTS_WITH => 'LIKE %s', - Comparison::ENDS_WITH => 'LIKE %s', - ]; - - /** - * Metadata object that describes the mapping of the mapped entity class. - * - * @var \Doctrine\ORM\Mapping\ClassMetadata - */ - protected $class; - - /** - * The underlying DBAL Connection of the used EntityManager. - * - * @var \Doctrine\DBAL\Connection $conn - */ - protected $conn; - - /** - * The database platform. - * - * @var \Doctrine\DBAL\Platforms\AbstractPlatform - */ - protected $platform; - - /** - * The EntityManager instance. - * - * @var EntityManagerInterface - */ - protected $em; - - /** - * Queued inserts. - * - * @var array - */ - protected $queuedInserts = []; - - /** - * The map of column names to DBAL mapping types of all prepared columns used - * when INSERTing or UPDATEing an entity. - * - * @var array - * - * @see prepareInsertData($entity) - * @see prepareUpdateData($entity) - */ - protected $columnTypes = []; - - /** - * The map of quoted column names. - * - * @var array - * - * @see prepareInsertData($entity) - * @see prepareUpdateData($entity) - */ - protected $quotedColumns = []; - - /** - * The INSERT SQL statement used for entities handled by this persister. - * This SQL is only generated once per request, if at all. - * - * @var string - */ - private $insertSql; - - /** - * The quote strategy. - * - * @var \Doctrine\ORM\Mapping\QuoteStrategy - */ - protected $quoteStrategy; - - /** - * The IdentifierFlattener used for manipulating identifiers - * - * @var \Doctrine\ORM\Utility\IdentifierFlattener - */ - private $identifierFlattener; - - /** - * @var CachedPersisterContext - */ - protected $currentPersisterContext; - - /** - * @var CachedPersisterContext - */ - private $limitsHandlingContext; - - /** - * @var CachedPersisterContext - */ - private $noLimitsContext; - - /** - * Initializes a new BasicEntityPersister that uses the given EntityManager - * and persists instances of the class described by the given ClassMetadata descriptor. - * - * @param EntityManagerInterface $em - * @param ClassMetadata $class - */ - public function __construct(EntityManagerInterface $em, ClassMetadata $class) - { - $this->em = $em; - $this->class = $class; - $this->conn = $em->getConnection(); - $this->platform = $this->conn->getDatabasePlatform(); - $this->quoteStrategy = $em->getConfiguration()->getQuoteStrategy(); - $this->identifierFlattener = new IdentifierFlattener($em->getUnitOfWork(), $em->getMetadataFactory()); - $this->noLimitsContext = $this->currentPersisterContext = new CachedPersisterContext( - $class, - new Query\ResultSetMapping(), - false - ); - $this->limitsHandlingContext = new CachedPersisterContext( - $class, - new Query\ResultSetMapping(), - true - ); - } - - /** - * {@inheritdoc} - */ - public function getClassMetadata() - { - return $this->class; - } - - /** - * {@inheritdoc} - */ - public function getResultSetMapping() - { - return $this->currentPersisterContext->rsm; - } - - /** - * {@inheritdoc} - */ - public function addInsert($entity) - { - $this->queuedInserts[spl_object_hash($entity)] = $entity; - } - - /** - * {@inheritdoc} - */ - public function getInserts() - { - return $this->queuedInserts; - } - - /** - * {@inheritdoc} - */ - public function executeInserts() - { - if ( ! $this->queuedInserts) { - return []; - } - - $postInsertIds = []; - $idGenerator = $this->class->idGenerator; - $isPostInsertId = $idGenerator->isPostInsertGenerator(); - - $stmt = $this->conn->prepare($this->getInsertSQL()); - $tableName = $this->class->getTableName(); - - foreach ($this->queuedInserts as $entity) { - $insertData = $this->prepareInsertData($entity); - - if (isset($insertData[$tableName])) { - $paramIndex = 1; - - foreach ($insertData[$tableName] as $column => $value) { - $stmt->bindValue($paramIndex++, $value, $this->columnTypes[$column]); - } - } - - $stmt->execute(); - - if ($isPostInsertId) { - $generatedId = $idGenerator->generate($this->em, $entity); - $id = [ - $this->class->identifier[0] => $generatedId - ]; - $postInsertIds[] = [ - 'generatedId' => $generatedId, - 'entity' => $entity, - ]; - } else { - $id = $this->class->getIdentifierValues($entity); - } - - if ($this->class->isVersioned) { - $this->assignDefaultVersionValue($entity, $id); - } - } - - $stmt->closeCursor(); - $this->queuedInserts = []; - - return $postInsertIds; - } - - /** - * Retrieves the default version value which was created - * by the preceding INSERT statement and assigns it back in to the - * entities version field. - * - * @param object $entity - * @param array $id - * - * @return void - */ - protected function assignDefaultVersionValue($entity, array $id) - { - $value = $this->fetchVersionValue($this->class, $id); - - $this->class->setFieldValue($entity, $this->class->versionField, $value); - } - - /** - * Fetches the current version value of a versioned entity. - * - * @param \Doctrine\ORM\Mapping\ClassMetadata $versionedClass - * @param array $id - * - * @return mixed - */ - protected function fetchVersionValue($versionedClass, array $id) - { - $versionField = $versionedClass->versionField; - $fieldMapping = $versionedClass->fieldMappings[$versionField]; - $tableName = $this->quoteStrategy->getTableName($versionedClass, $this->platform); - $identifier = $this->quoteStrategy->getIdentifierColumnNames($versionedClass, $this->platform); - $columnName = $this->quoteStrategy->getColumnName($versionField, $versionedClass, $this->platform); - - // FIXME: Order with composite keys might not be correct - $sql = 'SELECT ' . $columnName - . ' FROM ' . $tableName - . ' WHERE ' . implode(' = ? AND ', $identifier) . ' = ?'; - - - $flatId = $this->identifierFlattener->flattenIdentifier($versionedClass, $id); - - $value = $this->conn->fetchColumn( - $sql, - array_values($flatId), - 0, - $this->extractIdentifierTypes($id, $versionedClass) - ); - - return Type::getType($fieldMapping['type'])->convertToPHPValue($value, $this->platform); - } - - private function extractIdentifierTypes(array $id, ClassMetadata $versionedClass) : array - { - $types = []; - - foreach ($id as $field => $value) { - $types = array_merge($types, $this->getTypes($field, $value, $versionedClass)); - } - - return $types; - } - - /** - * {@inheritdoc} - */ - public function update($entity) - { - $tableName = $this->class->getTableName(); - $updateData = $this->prepareUpdateData($entity); - - if ( ! isset($updateData[$tableName]) || ! ($data = $updateData[$tableName])) { - return; - } - - $isVersioned = $this->class->isVersioned; - $quotedTableName = $this->quoteStrategy->getTableName($this->class, $this->platform); - - $this->updateTable($entity, $quotedTableName, $data, $isVersioned); - - if ($isVersioned) { - $id = $this->em->getUnitOfWork()->getEntityIdentifier($entity); - - $this->assignDefaultVersionValue($entity, $id); - } - } - - /** - * Performs an UPDATE statement for an entity on a specific table. - * The UPDATE can optionally be versioned, which requires the entity to have a version field. - * - * @param object $entity The entity object being updated. - * @param string $quotedTableName The quoted name of the table to apply the UPDATE on. - * @param array $updateData The map of columns to update (column => value). - * @param boolean $versioned Whether the UPDATE should be versioned. - * - * @return void - * - * @throws \Doctrine\ORM\ORMException - * @throws \Doctrine\ORM\OptimisticLockException - */ - protected final function updateTable($entity, $quotedTableName, array $updateData, $versioned = false) - { - $set = []; - $types = []; - $params = []; - - foreach ($updateData as $columnName => $value) { - $placeholder = '?'; - $column = $columnName; - - switch (true) { - case isset($this->class->fieldNames[$columnName]): - $fieldName = $this->class->fieldNames[$columnName]; - $column = $this->quoteStrategy->getColumnName($fieldName, $this->class, $this->platform); - - if (isset($this->class->fieldMappings[$fieldName]['requireSQLConversion'])) { - $type = Type::getType($this->columnTypes[$columnName]); - $placeholder = $type->convertToDatabaseValueSQL('?', $this->platform); - } - - break; - - case isset($this->quotedColumns[$columnName]): - $column = $this->quotedColumns[$columnName]; - - break; - } - - $params[] = $value; - $set[] = $column . ' = ' . $placeholder; - $types[] = $this->columnTypes[$columnName]; - } - - $where = []; - $identifier = $this->em->getUnitOfWork()->getEntityIdentifier($entity); - - foreach ($this->class->identifier as $idField) { - if ( ! isset($this->class->associationMappings[$idField])) { - $params[] = $identifier[$idField]; - $types[] = $this->class->fieldMappings[$idField]['type']; - $where[] = $this->quoteStrategy->getColumnName($idField, $this->class, $this->platform); - - continue; - } - - $params[] = $identifier[$idField]; - $where[] = $this->quoteStrategy->getJoinColumnName( - $this->class->associationMappings[$idField]['joinColumns'][0], - $this->class, - $this->platform - ); - - $targetMapping = $this->em->getClassMetadata($this->class->associationMappings[$idField]['targetEntity']); - $targetType = PersisterHelper::getTypeOfField($targetMapping->identifier[0], $targetMapping, $this->em); - - if ($targetType === []) { - throw ORMException::unrecognizedField($targetMapping->identifier[0]); - } - - $types[] = reset($targetType); - } - - if ($versioned) { - $versionField = $this->class->versionField; - $versionFieldType = $this->class->fieldMappings[$versionField]['type']; - $versionColumn = $this->quoteStrategy->getColumnName($versionField, $this->class, $this->platform); - - $where[] = $versionColumn; - $types[] = $this->class->fieldMappings[$versionField]['type']; - $params[] = $this->class->reflFields[$versionField]->getValue($entity); - - switch ($versionFieldType) { - case Type::SMALLINT: - case Type::INTEGER: - case Type::BIGINT: - $set[] = $versionColumn . ' = ' . $versionColumn . ' + 1'; - break; - - case Type::DATETIME: - $set[] = $versionColumn . ' = CURRENT_TIMESTAMP'; - break; - } - } - - $sql = 'UPDATE ' . $quotedTableName - . ' SET ' . implode(', ', $set) - . ' WHERE ' . implode(' = ? AND ', $where) . ' = ?'; - - $result = $this->conn->executeUpdate($sql, $params, $types); - - if ($versioned && ! $result) { - throw OptimisticLockException::lockFailed($entity); - } - } - - /** - * @todo Add check for platform if it supports foreign keys/cascading. - * - * @param array $identifier - * - * @return void - */ - protected function deleteJoinTableRecords($identifier) - { - foreach ($this->class->associationMappings as $mapping) { - if ($mapping['type'] !== ClassMetadata::MANY_TO_MANY) { - continue; - } - - // @Todo this only covers scenarios with no inheritance or of the same level. Is there something - // like self-referential relationship between different levels of an inheritance hierarchy? I hope not! - $selfReferential = ($mapping['targetEntity'] == $mapping['sourceEntity']); - $class = $this->class; - $association = $mapping; - $otherColumns = []; - $otherKeys = []; - $keys = []; - - if ( ! $mapping['isOwningSide']) { - $class = $this->em->getClassMetadata($mapping['targetEntity']); - $association = $class->associationMappings[$mapping['mappedBy']]; - } - - $joinColumns = $mapping['isOwningSide'] - ? $association['joinTable']['joinColumns'] - : $association['joinTable']['inverseJoinColumns']; - - - if ($selfReferential) { - $otherColumns = (! $mapping['isOwningSide']) - ? $association['joinTable']['joinColumns'] - : $association['joinTable']['inverseJoinColumns']; - } - - foreach ($joinColumns as $joinColumn) { - $keys[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); - } - - foreach ($otherColumns as $joinColumn) { - $otherKeys[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); - } - - if (isset($mapping['isOnDeleteCascade'])) { - continue; - } - - $joinTableName = $this->quoteStrategy->getJoinTableName($association, $this->class, $this->platform); - - $this->conn->delete($joinTableName, array_combine($keys, $identifier)); - - if ($selfReferential) { - $this->conn->delete($joinTableName, array_combine($otherKeys, $identifier)); - } - } - } - - /** - * {@inheritdoc} - */ - public function delete($entity) - { - $class = $this->class; - $identifier = $this->em->getUnitOfWork()->getEntityIdentifier($entity); - $tableName = $this->quoteStrategy->getTableName($class, $this->platform); - $idColumns = $this->quoteStrategy->getIdentifierColumnNames($class, $this->platform); - $id = array_combine($idColumns, $identifier); - $types = $this->getClassIdentifiersTypes($class); - - $this->deleteJoinTableRecords($identifier); - - return (bool) $this->conn->delete($tableName, $id, $types); - } - - /** - * Prepares the changeset of an entity for database insertion (UPDATE). - * - * The changeset is obtained from the currently running UnitOfWork. - * - * During this preparation the array that is passed as the second parameter is filled with - * => pairs, grouped by table name. - * - * Example: - * - * array( - * 'foo_table' => array('column1' => 'value1', 'column2' => 'value2', ...), - * 'bar_table' => array('columnX' => 'valueX', 'columnY' => 'valueY', ...), - * ... - * ) - * - * - * @param object $entity The entity for which to prepare the data. - * - * @return array The prepared data. - */ - protected function prepareUpdateData($entity) - { - $versionField = null; - $result = []; - $uow = $this->em->getUnitOfWork(); - - if (($versioned = $this->class->isVersioned) != false) { - $versionField = $this->class->versionField; - } - - foreach ($uow->getEntityChangeSet($entity) as $field => $change) { - if (isset($versionField) && $versionField == $field) { - continue; - } - - if (isset($this->class->embeddedClasses[$field])) { - continue; - } - - $newVal = $change[1]; - - if ( ! isset($this->class->associationMappings[$field])) { - $fieldMapping = $this->class->fieldMappings[$field]; - $columnName = $fieldMapping['columnName']; - - $this->columnTypes[$columnName] = $fieldMapping['type']; - - $result[$this->getOwningTable($field)][$columnName] = $newVal; - - continue; - } - - $assoc = $this->class->associationMappings[$field]; - - // Only owning side of x-1 associations can have a FK column. - if ( ! $assoc['isOwningSide'] || ! ($assoc['type'] & ClassMetadata::TO_ONE)) { - continue; - } - - if ($newVal !== null) { - $oid = spl_object_hash($newVal); - - if (isset($this->queuedInserts[$oid]) || $uow->isScheduledForInsert($newVal)) { - // The associated entity $newVal is not yet persisted, so we must - // set $newVal = null, in order to insert a null value and schedule an - // extra update on the UnitOfWork. - $uow->scheduleExtraUpdate($entity, [$field => [null, $newVal]]); - - $newVal = null; - } - } - - $newValId = null; - - if ($newVal !== null) { - $newValId = $uow->getEntityIdentifier($newVal); - } - - $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); - $owningTable = $this->getOwningTable($field); - - foreach ($assoc['joinColumns'] as $joinColumn) { - $sourceColumn = $joinColumn['name']; - $targetColumn = $joinColumn['referencedColumnName']; - $quotedColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); - - $this->quotedColumns[$sourceColumn] = $quotedColumn; - $this->columnTypes[$sourceColumn] = PersisterHelper::getTypeOfColumn($targetColumn, $targetClass, $this->em); - $result[$owningTable][$sourceColumn] = $newValId - ? $newValId[$targetClass->getFieldForColumn($targetColumn)] - : null; - } - } - - return $result; - } - - /** - * Prepares the data changeset of a managed entity for database insertion (initial INSERT). - * The changeset of the entity is obtained from the currently running UnitOfWork. - * - * The default insert data preparation is the same as for updates. - * - * @param object $entity The entity for which to prepare the data. - * - * @return array The prepared data for the tables to update. - * - * @see prepareUpdateData - */ - protected function prepareInsertData($entity) - { - return $this->prepareUpdateData($entity); - } - - /** - * {@inheritdoc} - */ - public function getOwningTable($fieldName) - { - return $this->class->getTableName(); - } - - /** - * {@inheritdoc} - */ - public function load(array $criteria, $entity = null, $assoc = null, array $hints = [], $lockMode = null, $limit = null, array $orderBy = null) - { - $this->switchPersisterContext(null, $limit); - - $sql = $this->getSelectSQL($criteria, $assoc, $lockMode, $limit, null, $orderBy); - list($params, $types) = $this->expandParameters($criteria); - $stmt = $this->conn->executeQuery($sql, $params, $types); - - if ($entity !== null) { - $hints[Query::HINT_REFRESH] = true; - $hints[Query::HINT_REFRESH_ENTITY] = $entity; - } - - $hydrator = $this->em->newHydrator($this->currentPersisterContext->selectJoinSql ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT); - $entities = $hydrator->hydrateAll($stmt, $this->currentPersisterContext->rsm, $hints); - - return $entities ? $entities[0] : null; - } - - /** - * {@inheritdoc} - */ - public function loadById(array $identifier, $entity = null) - { - return $this->load($identifier, $entity); - } - - /** - * {@inheritdoc} - */ - public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifier = []) - { - if (($foundEntity = $this->em->getUnitOfWork()->tryGetById($identifier, $assoc['targetEntity'])) != false) { - return $foundEntity; - } - - $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); - - if ($assoc['isOwningSide']) { - $isInverseSingleValued = $assoc['inversedBy'] && ! $targetClass->isCollectionValuedAssociation($assoc['inversedBy']); - - // Mark inverse side as fetched in the hints, otherwise the UoW would - // try to load it in a separate query (remember: to-one inverse sides can not be lazy). - $hints = []; - - if ($isInverseSingleValued) { - $hints['fetched']["r"][$assoc['inversedBy']] = true; - } - - /* cascade read-only status - if ($this->em->getUnitOfWork()->isReadOnly($sourceEntity)) { - $hints[Query::HINT_READ_ONLY] = true; - } - */ - - $targetEntity = $this->load($identifier, null, $assoc, $hints); - - // Complete bidirectional association, if necessary - if ($targetEntity !== null && $isInverseSingleValued) { - $targetClass->reflFields[$assoc['inversedBy']]->setValue($targetEntity, $sourceEntity); - } - - return $targetEntity; - } - - $sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']); - $owningAssoc = $targetClass->getAssociationMapping($assoc['mappedBy']); - - $computedIdentifier = []; - - // TRICKY: since the association is specular source and target are flipped - foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) { - if ( ! isset($sourceClass->fieldNames[$sourceKeyColumn])) { - throw MappingException::joinColumnMustPointToMappedField( - $sourceClass->name, $sourceKeyColumn - ); - } - - $computedIdentifier[$targetClass->getFieldForColumn($targetKeyColumn)] = - $sourceClass->reflFields[$sourceClass->fieldNames[$sourceKeyColumn]]->getValue($sourceEntity); - } - - $targetEntity = $this->load($computedIdentifier, null, $assoc); - - if ($targetEntity !== null) { - $targetClass->setFieldValue($targetEntity, $assoc['mappedBy'], $sourceEntity); - } - - return $targetEntity; - } - - /** - * {@inheritdoc} - */ - public function refresh(array $id, $entity, $lockMode = null) - { - $sql = $this->getSelectSQL($id, null, $lockMode); - list($params, $types) = $this->expandParameters($id); - $stmt = $this->conn->executeQuery($sql, $params, $types); - - $hydrator = $this->em->newHydrator(Query::HYDRATE_OBJECT); - $hydrator->hydrateAll($stmt, $this->currentPersisterContext->rsm, [Query::HINT_REFRESH => true]); - } - - /** - * {@inheritDoc} - */ - public function count($criteria = []) - { - $sql = $this->getCountSQL($criteria); - - list($params, $types) = ($criteria instanceof Criteria) - ? $this->expandCriteriaParameters($criteria) - : $this->expandParameters($criteria); - - return (int) $this->conn->executeQuery($sql, $params, $types)->fetchColumn(); - } - - /** - * {@inheritdoc} - */ - public function loadCriteria(Criteria $criteria) - { - $orderBy = $criteria->getOrderings(); - $limit = $criteria->getMaxResults(); - $offset = $criteria->getFirstResult(); - $query = $this->getSelectSQL($criteria, null, null, $limit, $offset, $orderBy); - - list($params, $types) = $this->expandCriteriaParameters($criteria); - - $stmt = $this->conn->executeQuery($query, $params, $types); - $hydrator = $this->em->newHydrator(($this->currentPersisterContext->selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT); - - return $hydrator->hydrateAll($stmt, $this->currentPersisterContext->rsm, [UnitOfWork::HINT_DEFEREAGERLOAD => true] - ); - } - - /** - * {@inheritdoc} - */ - public function expandCriteriaParameters(Criteria $criteria) - { - $expression = $criteria->getWhereExpression(); - $sqlParams = []; - $sqlTypes = []; - - if ($expression === null) { - return [$sqlParams, $sqlTypes]; - } - - $valueVisitor = new SqlValueVisitor(); - - $valueVisitor->dispatch($expression); - - list($params, $types) = $valueVisitor->getParamsAndTypes(); - - foreach ($params as $param) { - $sqlParams = array_merge($sqlParams, $this->getValues($param)); - } - - foreach ($types as $type) { - list ($field, $value) = $type; - $sqlTypes = array_merge($sqlTypes, $this->getTypes($field, $value, $this->class)); - } - - return [$sqlParams, $sqlTypes]; - } - - /** - * {@inheritdoc} - */ - public function loadAll(array $criteria = [], array $orderBy = null, $limit = null, $offset = null) - { - $this->switchPersisterContext($offset, $limit); - - $sql = $this->getSelectSQL($criteria, null, null, $limit, $offset, $orderBy); - list($params, $types) = $this->expandParameters($criteria); - $stmt = $this->conn->executeQuery($sql, $params, $types); - - $hydrator = $this->em->newHydrator(($this->currentPersisterContext->selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT); - - return $hydrator->hydrateAll($stmt, $this->currentPersisterContext->rsm, [UnitOfWork::HINT_DEFEREAGERLOAD => true] - ); - } - - /** - * {@inheritdoc} - */ - public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null) - { - $this->switchPersisterContext($offset, $limit); - - $stmt = $this->getManyToManyStatement($assoc, $sourceEntity, $offset, $limit); - - return $this->loadArrayFromStatement($assoc, $stmt); - } - - /** - * Loads an array of entities from a given DBAL statement. - * - * @param array $assoc - * @param \Doctrine\DBAL\Statement $stmt - * - * @return array - */ - private function loadArrayFromStatement($assoc, $stmt) - { - $rsm = $this->currentPersisterContext->rsm; - $hints = [UnitOfWork::HINT_DEFEREAGERLOAD => true]; - - if (isset($assoc['indexBy'])) { - $rsm = clone ($this->currentPersisterContext->rsm); // this is necessary because the "default rsm" should be changed. - $rsm->addIndexBy('r', $assoc['indexBy']); - } - - return $this->em->newHydrator(Query::HYDRATE_OBJECT)->hydrateAll($stmt, $rsm, $hints); - } - - /** - * Hydrates a collection from a given DBAL statement. - * - * @param array $assoc - * @param \Doctrine\DBAL\Statement $stmt - * @param PersistentCollection $coll - * - * @return array - */ - private function loadCollectionFromStatement($assoc, $stmt, $coll) - { - $rsm = $this->currentPersisterContext->rsm; - $hints = [ - UnitOfWork::HINT_DEFEREAGERLOAD => true, - 'collection' => $coll - ]; - - if (isset($assoc['indexBy'])) { - $rsm = clone ($this->currentPersisterContext->rsm); // this is necessary because the "default rsm" should be changed. - $rsm->addIndexBy('r', $assoc['indexBy']); - } - - return $this->em->newHydrator(Query::HYDRATE_OBJECT)->hydrateAll($stmt, $rsm, $hints); - } - - /** - * {@inheritdoc} - */ - public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll) - { - $stmt = $this->getManyToManyStatement($assoc, $sourceEntity); - - return $this->loadCollectionFromStatement($assoc, $stmt, $coll); - } - - /** - * @param array $assoc - * @param object $sourceEntity - * @param int|null $offset - * @param int|null $limit - * - * @return \Doctrine\DBAL\Driver\Statement - * - * @throws \Doctrine\ORM\Mapping\MappingException - */ - private function getManyToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null) - { - $this->switchPersisterContext($offset, $limit); - - $sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']); - $class = $sourceClass; - $association = $assoc; - $criteria = []; - $parameters = []; - - if ( ! $assoc['isOwningSide']) { - $class = $this->em->getClassMetadata($assoc['targetEntity']); - $association = $class->associationMappings[$assoc['mappedBy']]; - } - - $joinColumns = $assoc['isOwningSide'] - ? $association['joinTable']['joinColumns'] - : $association['joinTable']['inverseJoinColumns']; - - $quotedJoinTable = $this->quoteStrategy->getJoinTableName($association, $class, $this->platform); - - foreach ($joinColumns as $joinColumn) { - $sourceKeyColumn = $joinColumn['referencedColumnName']; - $quotedKeyColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); - - switch (true) { - case $sourceClass->containsForeignIdentifier: - $field = $sourceClass->getFieldForColumn($sourceKeyColumn); - $value = $sourceClass->reflFields[$field]->getValue($sourceEntity); - - if (isset($sourceClass->associationMappings[$field])) { - $value = $this->em->getUnitOfWork()->getEntityIdentifier($value); - $value = $value[$this->em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]]; - } - - break; - - case isset($sourceClass->fieldNames[$sourceKeyColumn]): - $field = $sourceClass->fieldNames[$sourceKeyColumn]; - $value = $sourceClass->reflFields[$field]->getValue($sourceEntity); - - break; - - default: - throw MappingException::joinColumnMustPointToMappedField( - $sourceClass->name, $sourceKeyColumn - ); - } - - $criteria[$quotedJoinTable . '.' . $quotedKeyColumn] = $value; - $parameters[] = [ - 'value' => $value, - 'field' => $field, - 'class' => $sourceClass, - ]; - } - - $sql = $this->getSelectSQL($criteria, $assoc, null, $limit, $offset); - list($params, $types) = $this->expandToManyParameters($parameters); - - return $this->conn->executeQuery($sql, $params, $types); - } - - /** - * {@inheritdoc} - */ - public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, array $orderBy = null) - { - $this->switchPersisterContext($offset, $limit); - - $lockSql = ''; - $joinSql = ''; - $orderBySql = ''; - - if ($assoc != null && $assoc['type'] == ClassMetadata::MANY_TO_MANY) { - $joinSql = $this->getSelectManyToManyJoinSQL($assoc); - } - - if (isset($assoc['orderBy'])) { - $orderBy = $assoc['orderBy']; - } - - if ($orderBy) { - $orderBySql = $this->getOrderBySQL($orderBy, $this->getSQLTableAlias($this->class->name)); - } - - $conditionSql = ($criteria instanceof Criteria) - ? $this->getSelectConditionCriteriaSQL($criteria) - : $this->getSelectConditionSQL($criteria, $assoc); - - switch ($lockMode) { - case LockMode::PESSIMISTIC_READ: - $lockSql = ' ' . $this->platform->getReadLockSQL(); - break; - - case LockMode::PESSIMISTIC_WRITE: - $lockSql = ' ' . $this->platform->getWriteLockSQL(); - break; - } - - $columnList = $this->getSelectColumnsSQL(); - $tableAlias = $this->getSQLTableAlias($this->class->name); - $filterSql = $this->generateFilterConditionSQL($this->class, $tableAlias); - $tableName = $this->quoteStrategy->getTableName($this->class, $this->platform); - - if ('' !== $filterSql) { - $conditionSql = $conditionSql - ? $conditionSql . ' AND ' . $filterSql - : $filterSql; - } - - $select = 'SELECT ' . $columnList; - $from = ' FROM ' . $tableName . ' '. $tableAlias; - $join = $this->currentPersisterContext->selectJoinSql . $joinSql; - $where = ($conditionSql ? ' WHERE ' . $conditionSql : ''); - $lock = $this->platform->appendLockHint($from, $lockMode); - $query = $select - . $lock - . $join - . $where - . $orderBySql; - - return $this->platform->modifyLimitQuery($query, $limit, $offset) . $lockSql; - } - - /** - * {@inheritDoc} - */ - public function getCountSQL($criteria = []) - { - $tableName = $this->quoteStrategy->getTableName($this->class, $this->platform); - $tableAlias = $this->getSQLTableAlias($this->class->name); - - $conditionSql = ($criteria instanceof Criteria) - ? $this->getSelectConditionCriteriaSQL($criteria) - : $this->getSelectConditionSQL($criteria); - - $filterSql = $this->generateFilterConditionSQL($this->class, $tableAlias); - - if ('' !== $filterSql) { - $conditionSql = $conditionSql - ? $conditionSql . ' AND ' . $filterSql - : $filterSql; - } - - $sql = 'SELECT COUNT(*) ' - . 'FROM ' . $tableName . ' ' . $tableAlias - . (empty($conditionSql) ? '' : ' WHERE ' . $conditionSql); - - return $sql; - } - - /** - * Gets the ORDER BY SQL snippet for ordered collections. - * - * @param array $orderBy - * @param string $baseTableAlias - * - * @return string - * - * @throws \Doctrine\ORM\ORMException - */ - protected final function getOrderBySQL(array $orderBy, $baseTableAlias) - { - $orderByList = []; - - foreach ($orderBy as $fieldName => $orientation) { - - $orientation = strtoupper(trim($orientation)); - - if ($orientation != 'ASC' && $orientation != 'DESC') { - throw ORMException::invalidOrientation($this->class->name, $fieldName); - } - - if (isset($this->class->fieldMappings[$fieldName])) { - $tableAlias = isset($this->class->fieldMappings[$fieldName]['inherited']) - ? $this->getSQLTableAlias($this->class->fieldMappings[$fieldName]['inherited']) - : $baseTableAlias; - - $columnName = $this->quoteStrategy->getColumnName($fieldName, $this->class, $this->platform); - $orderByList[] = $tableAlias . '.' . $columnName . ' ' . $orientation; - - continue; - } - - if (isset($this->class->associationMappings[$fieldName])) { - - if ( ! $this->class->associationMappings[$fieldName]['isOwningSide']) { - throw ORMException::invalidFindByInverseAssociation($this->class->name, $fieldName); - } - - $tableAlias = isset($this->class->associationMappings[$fieldName]['inherited']) - ? $this->getSQLTableAlias($this->class->associationMappings[$fieldName]['inherited']) - : $baseTableAlias; - - foreach ($this->class->associationMappings[$fieldName]['joinColumns'] as $joinColumn) { - $columnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); - $orderByList[] = $tableAlias . '.' . $columnName . ' ' . $orientation; - } - - continue; - } - - throw ORMException::unrecognizedField($fieldName); - } - - return ' ORDER BY ' . implode(', ', $orderByList); - } - - /** - * Gets the SQL fragment with the list of columns to select when querying for - * an entity in this persister. - * - * Subclasses should override this method to alter or change the select column - * list SQL fragment. Note that in the implementation of BasicEntityPersister - * the resulting SQL fragment is generated only once and cached in {@link selectColumnListSql}. - * Subclasses may or may not do the same. - * - * @return string The SQL fragment. - */ - protected function getSelectColumnsSQL() - { - if ($this->currentPersisterContext->selectColumnListSql !== null) { - return $this->currentPersisterContext->selectColumnListSql; - } - - $columnList = []; - $this->currentPersisterContext->rsm->addEntityResult($this->class->name, 'r'); // r for root - - // Add regular columns to select list - foreach ($this->class->fieldNames as $field) { - $columnList[] = $this->getSelectColumnSQL($field, $this->class); - } - - $this->currentPersisterContext->selectJoinSql = ''; - $eagerAliasCounter = 0; - - foreach ($this->class->associationMappings as $assocField => $assoc) { - $assocColumnSQL = $this->getSelectColumnAssociationSQL($assocField, $assoc, $this->class); - - if ($assocColumnSQL) { - $columnList[] = $assocColumnSQL; - } - - $isAssocToOneInverseSide = $assoc['type'] & ClassMetadata::TO_ONE && ! $assoc['isOwningSide']; - $isAssocFromOneEager = $assoc['type'] !== ClassMetadata::MANY_TO_MANY && $assoc['fetch'] === ClassMetadata::FETCH_EAGER; - - if ( ! ($isAssocFromOneEager || $isAssocToOneInverseSide)) { - continue; - } - - if ((($assoc['type'] & ClassMetadata::TO_MANY) > 0) && $this->currentPersisterContext->handlesLimits) { - continue; - } - - $eagerEntity = $this->em->getClassMetadata($assoc['targetEntity']); - - if ($eagerEntity->inheritanceType != ClassMetadata::INHERITANCE_TYPE_NONE) { - continue; // now this is why you shouldn't use inheritance - } - - $assocAlias = 'e' . ($eagerAliasCounter++); - $this->currentPersisterContext->rsm->addJoinedEntityResult($assoc['targetEntity'], $assocAlias, 'r', $assocField); - - foreach ($eagerEntity->fieldNames as $field) { - $columnList[] = $this->getSelectColumnSQL($field, $eagerEntity, $assocAlias); - } - - foreach ($eagerEntity->associationMappings as $eagerAssocField => $eagerAssoc) { - $eagerAssocColumnSQL = $this->getSelectColumnAssociationSQL( - $eagerAssocField, $eagerAssoc, $eagerEntity, $assocAlias - ); - - if ($eagerAssocColumnSQL) { - $columnList[] = $eagerAssocColumnSQL; - } - } - - $association = $assoc; - $joinCondition = []; - - if (isset($assoc['indexBy'])) { - $this->currentPersisterContext->rsm->addIndexBy($assocAlias, $assoc['indexBy']); - } - - if ( ! $assoc['isOwningSide']) { - $eagerEntity = $this->em->getClassMetadata($assoc['targetEntity']); - $association = $eagerEntity->getAssociationMapping($assoc['mappedBy']); - } - - $joinTableAlias = $this->getSQLTableAlias($eagerEntity->name, $assocAlias); - $joinTableName = $this->quoteStrategy->getTableName($eagerEntity, $this->platform); - - if ($assoc['isOwningSide']) { - $tableAlias = $this->getSQLTableAlias($association['targetEntity'], $assocAlias); - $this->currentPersisterContext->selectJoinSql .= ' ' . $this->getJoinSQLForJoinColumns($association['joinColumns']); - - foreach ($association['joinColumns'] as $joinColumn) { - $sourceCol = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); - $targetCol = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $this->class, $this->platform); - $joinCondition[] = $this->getSQLTableAlias($association['sourceEntity']) - . '.' . $sourceCol . ' = ' . $tableAlias . '.' . $targetCol; - } - - // Add filter SQL - if ($filterSql = $this->generateFilterConditionSQL($eagerEntity, $tableAlias)) { - $joinCondition[] = $filterSql; - } - - } else { - - $this->currentPersisterContext->selectJoinSql .= ' LEFT JOIN'; - - foreach ($association['joinColumns'] as $joinColumn) { - $sourceCol = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); - $targetCol = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $this->class, $this->platform); - - $joinCondition[] = $this->getSQLTableAlias($association['sourceEntity'], $assocAlias) . '.' . $sourceCol . ' = ' - . $this->getSQLTableAlias($association['targetEntity']) . '.' . $targetCol; - } - } - - $this->currentPersisterContext->selectJoinSql .= ' ' . $joinTableName . ' ' . $joinTableAlias . ' ON '; - $this->currentPersisterContext->selectJoinSql .= implode(' AND ', $joinCondition); - } - - $this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList); - - return $this->currentPersisterContext->selectColumnListSql; - } - - /** - * Gets the SQL join fragment used when selecting entities from an association. - * - * @param string $field - * @param array $assoc - * @param ClassMetadata $class - * @param string $alias - * - * @return string - */ - protected function getSelectColumnAssociationSQL($field, $assoc, ClassMetadata $class, $alias = 'r') - { - if ( ! ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) ) { - return ''; - } - - $columnList = []; - $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); - $isIdentifier = isset($assoc['id']) && $assoc['id'] === true; - $sqlTableAlias = $this->getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias)); - - foreach ($assoc['joinColumns'] as $joinColumn) { - $quotedColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); - $resultColumnName = $this->getSQLColumnAlias($joinColumn['name']); - $type = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); - - $this->currentPersisterContext->rsm->addMetaResult($alias, $resultColumnName, $joinColumn['name'], $isIdentifier, $type); - - $columnList[] = sprintf('%s.%s AS %s', $sqlTableAlias, $quotedColumn, $resultColumnName); - } - - return implode(', ', $columnList); - } - - /** - * Gets the SQL join fragment used when selecting entities from a - * many-to-many association. - * - * @param array $manyToMany - * - * @return string - */ - protected function getSelectManyToManyJoinSQL(array $manyToMany) - { - $conditions = []; - $association = $manyToMany; - $sourceTableAlias = $this->getSQLTableAlias($this->class->name); - - if ( ! $manyToMany['isOwningSide']) { - $targetEntity = $this->em->getClassMetadata($manyToMany['targetEntity']); - $association = $targetEntity->associationMappings[$manyToMany['mappedBy']]; - } - - $joinTableName = $this->quoteStrategy->getJoinTableName($association, $this->class, $this->platform); - $joinColumns = ($manyToMany['isOwningSide']) - ? $association['joinTable']['inverseJoinColumns'] - : $association['joinTable']['joinColumns']; - - foreach ($joinColumns as $joinColumn) { - $quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); - $quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $this->class, $this->platform); - $conditions[] = $sourceTableAlias . '.' . $quotedTargetColumn . ' = ' . $joinTableName . '.' . $quotedSourceColumn; - } - - return ' INNER JOIN ' . $joinTableName . ' ON ' . implode(' AND ', $conditions); - } - - /** - * {@inheritdoc} - */ - public function getInsertSQL() - { - if ($this->insertSql !== null) { - return $this->insertSql; - } - - $columns = $this->getInsertColumnList(); - $tableName = $this->quoteStrategy->getTableName($this->class, $this->platform); - - if (empty($columns)) { - $identityColumn = $this->quoteStrategy->getColumnName($this->class->identifier[0], $this->class, $this->platform); - $this->insertSql = $this->platform->getEmptyIdentityInsertSQL($tableName, $identityColumn); - - return $this->insertSql; - } - - $values = []; - $columns = array_unique($columns); - - foreach ($columns as $column) { - $placeholder = '?'; - - if (isset($this->class->fieldNames[$column]) - && isset($this->columnTypes[$this->class->fieldNames[$column]]) - && isset($this->class->fieldMappings[$this->class->fieldNames[$column]]['requireSQLConversion'])) { - $type = Type::getType($this->columnTypes[$this->class->fieldNames[$column]]); - $placeholder = $type->convertToDatabaseValueSQL('?', $this->platform); - } - - $values[] = $placeholder; - } - - $columns = implode(', ', $columns); - $values = implode(', ', $values); - - $this->insertSql = sprintf('INSERT INTO %s (%s) VALUES (%s)', $tableName, $columns, $values); - - return $this->insertSql; - } - - /** - * Gets the list of columns to put in the INSERT SQL statement. - * - * Subclasses should override this method to alter or change the list of - * columns placed in the INSERT statements used by the persister. - * - * @return array The list of columns. - */ - protected function getInsertColumnList() - { - $columns = []; - - foreach ($this->class->reflFields as $name => $field) { - if ($this->class->isVersioned && $this->class->versionField == $name) { - continue; - } - - if (isset($this->class->embeddedClasses[$name])) { - continue; - } - - if (isset($this->class->associationMappings[$name])) { - $assoc = $this->class->associationMappings[$name]; - - if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) { - foreach ($assoc['joinColumns'] as $joinColumn) { - $columns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); - } - } - - continue; - } - - if (! $this->class->isIdGeneratorIdentity() || $this->class->identifier[0] != $name) { - $columns[] = $this->quoteStrategy->getColumnName($name, $this->class, $this->platform); - $this->columnTypes[$name] = $this->class->fieldMappings[$name]['type']; - } - } - - return $columns; - } - - /** - * Gets the SQL snippet of a qualified column name for the given field name. - * - * @param string $field The field name. - * @param ClassMetadata $class The class that declares this field. The table this class is - * mapped to must own the column for the given field. - * @param string $alias - * - * @return string - */ - protected function getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r') - { - $root = $alias == 'r' ? '' : $alias ; - $tableAlias = $this->getSQLTableAlias($class->name, $root); - $fieldMapping = $class->fieldMappings[$field]; - $sql = sprintf('%s.%s', $tableAlias, $this->quoteStrategy->getColumnName($field, $class, $this->platform)); - $columnAlias = $this->getSQLColumnAlias($fieldMapping['columnName']); - - $this->currentPersisterContext->rsm->addFieldResult($alias, $columnAlias, $field); - - if (isset($fieldMapping['requireSQLConversion'])) { - $type = Type::getType($fieldMapping['type']); - $sql = $type->convertToPHPValueSQL($sql, $this->platform); - } - - return $sql . ' AS ' . $columnAlias; - } - - /** - * Gets the SQL table alias for the given class name. - * - * @param string $className - * @param string $assocName - * - * @return string The SQL table alias. - * - * @todo Reconsider. Binding table aliases to class names is not such a good idea. - */ - protected function getSQLTableAlias($className, $assocName = '') - { - if ($assocName) { - $className .= '#' . $assocName; - } - - if (isset($this->currentPersisterContext->sqlTableAliases[$className])) { - return $this->currentPersisterContext->sqlTableAliases[$className]; - } - - $tableAlias = 't' . $this->currentPersisterContext->sqlAliasCounter++; - - $this->currentPersisterContext->sqlTableAliases[$className] = $tableAlias; - - return $tableAlias; - } - - /** - * {@inheritdoc} - */ - public function lock(array $criteria, $lockMode) - { - $lockSql = ''; - $conditionSql = $this->getSelectConditionSQL($criteria); - - switch ($lockMode) { - case LockMode::PESSIMISTIC_READ: - $lockSql = $this->platform->getReadLockSQL(); - - break; - case LockMode::PESSIMISTIC_WRITE: - - $lockSql = $this->platform->getWriteLockSQL(); - break; - } - - $lock = $this->getLockTablesSql($lockMode); - $where = ($conditionSql ? ' WHERE ' . $conditionSql : '') . ' '; - $sql = 'SELECT 1 ' - . $lock - . $where - . $lockSql; - - list($params, $types) = $this->expandParameters($criteria); - - $this->conn->executeQuery($sql, $params, $types); - } - - /** - * Gets the FROM and optionally JOIN conditions to lock the entity managed by this persister. - * - * @param integer $lockMode One of the Doctrine\DBAL\LockMode::* constants. - * - * @return string - */ - protected function getLockTablesSql($lockMode) - { - return $this->platform->appendLockHint( - 'FROM ' - . $this->quoteStrategy->getTableName($this->class, $this->platform) . ' ' - . $this->getSQLTableAlias($this->class->name), - $lockMode - ); - } - - /** - * Gets the Select Where Condition from a Criteria object. - * - * @param \Doctrine\Common\Collections\Criteria $criteria - * - * @return string - */ - protected function getSelectConditionCriteriaSQL(Criteria $criteria) - { - $expression = $criteria->getWhereExpression(); - - if ($expression === null) { - return ''; - } - - $visitor = new SqlExpressionVisitor($this, $this->class); - - return $visitor->dispatch($expression); - } - - /** - * {@inheritdoc} - */ - public function getSelectConditionStatementSQL($field, $value, $assoc = null, $comparison = null) - { - $selectedColumns = []; - $columns = $this->getSelectConditionStatementColumnSQL($field, $assoc); - - if (count($columns) > 1 && $comparison === Comparison::IN) { - /* - * @todo try to support multi-column IN expressions. - * Example: (col1, col2) IN (('val1A', 'val2A'), ('val1B', 'val2B')) - */ - throw ORMException::cantUseInOperatorOnCompositeKeys(); - } - - foreach ($columns as $column) { - $placeholder = '?'; - - if (isset($this->class->fieldMappings[$field]['requireSQLConversion'])) { - $type = Type::getType($this->class->fieldMappings[$field]['type']); - $placeholder = $type->convertToDatabaseValueSQL($placeholder, $this->platform); - } - - if (null !== $comparison) { - // special case null value handling - if (($comparison === Comparison::EQ || $comparison === Comparison::IS) && null ===$value) { - $selectedColumns[] = $column . ' IS NULL'; - - continue; - } - - if ($comparison === Comparison::NEQ && null === $value) { - $selectedColumns[] = $column . ' IS NOT NULL'; - - continue; - } - - $selectedColumns[] = $column . ' ' . sprintf(self::$comparisonMap[$comparison], $placeholder); - - continue; - } - - if (is_array($value)) { - $in = sprintf('%s IN (%s)', $column, $placeholder); - - if (false !== array_search(null, $value, true)) { - $selectedColumns[] = sprintf('(%s OR %s IS NULL)', $in, $column); - - continue; - } - - $selectedColumns[] = $in; - - continue; - } - - if (null === $value) { - $selectedColumns[] = sprintf('%s IS NULL', $column); - - continue; - } - - $selectedColumns[] = sprintf('%s = %s', $column, $placeholder); - } - - return implode(' AND ', $selectedColumns); - } - - /** - * Builds the left-hand-side of a where condition statement. - * - * @param string $field - * @param array|null $assoc - * - * @return string[] - * - * @throws \Doctrine\ORM\ORMException - */ - private function getSelectConditionStatementColumnSQL($field, $assoc = null) - { - if (isset($this->class->fieldMappings[$field])) { - $className = (isset($this->class->fieldMappings[$field]['inherited'])) - ? $this->class->fieldMappings[$field]['inherited'] - : $this->class->name; - - return [$this->getSQLTableAlias($className) . '.' . $this->quoteStrategy->getColumnName($field, $this->class, $this->platform)]; - } - - if (isset($this->class->associationMappings[$field])) { - $association = $this->class->associationMappings[$field]; - // Many-To-Many requires join table check for joinColumn - $columns = []; - $class = $this->class; - - if ($association['type'] === ClassMetadata::MANY_TO_MANY) { - if ( ! $association['isOwningSide']) { - $association = $assoc; - } - - $joinTableName = $this->quoteStrategy->getJoinTableName($association, $class, $this->platform); - $joinColumns = $assoc['isOwningSide'] - ? $association['joinTable']['joinColumns'] - : $association['joinTable']['inverseJoinColumns']; - - - foreach ($joinColumns as $joinColumn) { - $columns[] = $joinTableName . '.' . $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); - } - - } else { - if ( ! $association['isOwningSide']) { - throw ORMException::invalidFindByInverseAssociation($this->class->name, $field); - } - - $className = (isset($association['inherited'])) - ? $association['inherited'] - : $this->class->name; - - foreach ($association['joinColumns'] as $joinColumn) { - $columns[] = $this->getSQLTableAlias($className) . '.' . $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform); - } - } - return $columns; - } - - if ($assoc !== null && strpos($field, " ") === false && strpos($field, "(") === false) { - // very careless developers could potentially open up this normally hidden api for userland attacks, - // therefore checking for spaces and function calls which are not allowed. - - // found a join column condition, not really a "field" - return [$field]; - } - - throw ORMException::unrecognizedField($field); - } - - /** - * Gets the conditional SQL fragment used in the WHERE clause when selecting - * entities in this persister. - * - * Subclasses are supposed to override this method if they intend to change - * or alter the criteria by which entities are selected. - * - * @param array $criteria - * @param array|null $assoc - * - * @return string - */ - protected function getSelectConditionSQL(array $criteria, $assoc = null) - { - $conditions = []; - - foreach ($criteria as $field => $value) { - $conditions[] = $this->getSelectConditionStatementSQL($field, $value, $assoc); - } - - return implode(' AND ', $conditions); - } - - /** - * {@inheritdoc} - */ - public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null) - { - $this->switchPersisterContext($offset, $limit); - - $stmt = $this->getOneToManyStatement($assoc, $sourceEntity, $offset, $limit); - - return $this->loadArrayFromStatement($assoc, $stmt); - } - - /** - * {@inheritdoc} - */ - public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $coll) - { - $stmt = $this->getOneToManyStatement($assoc, $sourceEntity); - - return $this->loadCollectionFromStatement($assoc, $stmt, $coll); - } - - /** - * Builds criteria and execute SQL statement to fetch the one to many entities from. - * - * @param array $assoc - * @param object $sourceEntity - * @param int|null $offset - * @param int|null $limit - * - * @return \Doctrine\DBAL\Statement - */ - private function getOneToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null) - { - $this->switchPersisterContext($offset, $limit); - - $criteria = []; - $parameters = []; - $owningAssoc = $this->class->associationMappings[$assoc['mappedBy']]; - $sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']); - $tableAlias = $this->getSQLTableAlias($owningAssoc['inherited'] ?? $this->class->name); - - foreach ($owningAssoc['targetToSourceKeyColumns'] as $sourceKeyColumn => $targetKeyColumn) { - if ($sourceClass->containsForeignIdentifier) { - $field = $sourceClass->getFieldForColumn($sourceKeyColumn); - $value = $sourceClass->reflFields[$field]->getValue($sourceEntity); - - if (isset($sourceClass->associationMappings[$field])) { - $value = $this->em->getUnitOfWork()->getEntityIdentifier($value); - $value = $value[$this->em->getClassMetadata($sourceClass->associationMappings[$field]['targetEntity'])->identifier[0]]; - } - - $criteria[$tableAlias . "." . $targetKeyColumn] = $value; - $parameters[] = [ - 'value' => $value, - 'field' => $field, - 'class' => $sourceClass, - ]; - - continue; - } - - $field = $sourceClass->fieldNames[$sourceKeyColumn]; - $value = $sourceClass->reflFields[$field]->getValue($sourceEntity); - - $criteria[$tableAlias . "." . $targetKeyColumn] = $value; - $parameters[] = [ - 'value' => $value, - 'field' => $field, - 'class' => $sourceClass, - ]; - - } - - $sql = $this->getSelectSQL($criteria, $assoc, null, $limit, $offset); - list($params, $types) = $this->expandToManyParameters($parameters); - - return $this->conn->executeQuery($sql, $params, $types); - } - - /** - * {@inheritdoc} - */ - public function expandParameters($criteria) - { - $params = []; - $types = []; - - foreach ($criteria as $field => $value) { - if ($value === null) { - continue; // skip null values. - } - - $types = array_merge($types, $this->getTypes($field, $value, $this->class)); - $params = array_merge($params, $this->getValues($value)); - } - - return [$params, $types]; - } - - /** - * Expands the parameters from the given criteria and use the correct binding types if found, - * specialized for OneToMany or ManyToMany associations. - * - * @param mixed[][] $criteria an array of arrays containing following: - * - field to which each criterion will be bound - * - value to be bound - * - class to which the field belongs to - * - * - * @return array - */ - private function expandToManyParameters($criteria) - { - $params = []; - $types = []; - - foreach ($criteria as $criterion) { - if ($criterion['value'] === null) { - continue; // skip null values. - } - - $types = array_merge($types, $this->getTypes($criterion['field'], $criterion['value'], $criterion['class'])); - $params = array_merge($params, $this->getValues($criterion['value'])); - } - - return [$params, $types]; - } - - /** - * Infers field types to be used by parameter type casting. - * - * @param string $field - * @param mixed $value - * @param ClassMetadata $class - * - * @return array - * - * @throws \Doctrine\ORM\Query\QueryException - */ - private function getTypes($field, $value, ClassMetadata $class) - { - $types = []; - - switch (true) { - case (isset($class->fieldMappings[$field])): - $types = array_merge($types, [$class->fieldMappings[$field]['type']]); - break; - - case (isset($class->associationMappings[$field])): - $assoc = $class->associationMappings[$field]; - $class = $this->em->getClassMetadata($assoc['targetEntity']); - - if (! $assoc['isOwningSide']) { - $assoc = $class->associationMappings[$assoc['mappedBy']]; - $class = $this->em->getClassMetadata($assoc['targetEntity']); - } - - $columns = $assoc['type'] === ClassMetadata::MANY_TO_MANY - ? $assoc['relationToTargetKeyColumns'] - : $assoc['sourceToTargetKeyColumns']; - - foreach ($columns as $column){ - $types[] = PersisterHelper::getTypeOfColumn($column, $class, $this->em); - } - break; - - default: - $types[] = null; - break; - } - - if (is_array($value)) { - return array_map(function ($type) { - $type = Type::getType($type); - - return $type->getBindingType() + Connection::ARRAY_PARAM_OFFSET; - }, $types); - } - - return $types; - } - - /** - * Retrieves the parameters that identifies a value. - * - * @param mixed $value - * - * @return array - */ - private function getValues($value) - { - if (is_array($value)) { - $newValue = []; - - foreach ($value as $itemValue) { - $newValue = array_merge($newValue, $this->getValues($itemValue)); - } - - return [$newValue]; - } - - if (is_object($value) && $this->em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value))) { - $class = $this->em->getClassMetadata(get_class($value)); - if ($class->isIdentifierComposite) { - $newValue = []; - - foreach ($class->getIdentifierValues($value) as $innerValue) { - $newValue = array_merge($newValue, $this->getValues($innerValue)); - } - - return $newValue; - } - } - - return [$this->getIndividualValue($value)]; - } - - /** - * Retrieves an individual parameter value. - * - * @param mixed $value - * - * @return mixed - */ - private function getIndividualValue($value) - { - if ( ! is_object($value) || ! $this->em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value))) { - return $value; - } - - return $this->em->getUnitOfWork()->getSingleIdentifierValue($value); - } - - /** - * {@inheritdoc} - */ - public function exists($entity, Criteria $extraConditions = null) - { - $criteria = $this->class->getIdentifierValues($entity); - - if ( ! $criteria) { - return false; - } - - $alias = $this->getSQLTableAlias($this->class->name); - - $sql = 'SELECT 1 ' - . $this->getLockTablesSql(null) - . ' WHERE ' . $this->getSelectConditionSQL($criteria); - - list($params, $types) = $this->expandParameters($criteria); - - if (null !== $extraConditions) { - $sql .= ' AND ' . $this->getSelectConditionCriteriaSQL($extraConditions); - list($criteriaParams, $criteriaTypes) = $this->expandCriteriaParameters($extraConditions); - - $params = array_merge($params, $criteriaParams); - $types = array_merge($types, $criteriaTypes); - } - - if ($filterSql = $this->generateFilterConditionSQL($this->class, $alias)) { - $sql .= ' AND ' . $filterSql; - } - - return (bool) $this->conn->fetchColumn($sql, $params, 0, $types); - } - - /** - * Generates the appropriate join SQL for the given join column. - * - * @param array $joinColumns The join columns definition of an association. - * - * @return string LEFT JOIN if one of the columns is nullable, INNER JOIN otherwise. - */ - protected function getJoinSQLForJoinColumns($joinColumns) - { - // if one of the join columns is nullable, return left join - foreach ($joinColumns as $joinColumn) { - if ( ! isset($joinColumn['nullable']) || $joinColumn['nullable']) { - return 'LEFT JOIN'; - } - } - - return 'INNER JOIN'; - } - - /** - * {@inheritdoc} - */ - public function getSQLColumnAlias($columnName) - { - return $this->quoteStrategy->getColumnAlias($columnName, $this->currentPersisterContext->sqlAliasCounter++, $this->platform); - } - - /** - * Generates the filter SQL for a given entity and table alias. - * - * @param ClassMetadata $targetEntity Metadata of the target entity. - * @param string $targetTableAlias The table alias of the joined/selected table. - * - * @return string The SQL query part to add to a query. - */ - protected function generateFilterConditionSQL(ClassMetadata $targetEntity, $targetTableAlias) - { - $filterClauses = []; - - foreach ($this->em->getFilters()->getEnabledFilters() as $filter) { - if ('' !== $filterExpr = $filter->addFilterConstraint($targetEntity, $targetTableAlias)) { - $filterClauses[] = '(' . $filterExpr . ')'; - } - } - - $sql = implode(' AND ', $filterClauses); - - return $sql ? "(" . $sql . ")" : ""; // Wrap again to avoid "X or Y and FilterConditionSQL" - } - - /** - * Switches persister context according to current query offset/limits - * - * This is due to the fact that to-many associations cannot be fetch-joined when a limit is involved - * - * @param null|int $offset - * @param null|int $limit - */ - protected function switchPersisterContext($offset, $limit) - { - if (null === $offset && null === $limit) { - $this->currentPersisterContext = $this->noLimitsContext; - - return; - } - - $this->currentPersisterContext = $this->limitsHandlingContext; - } - - /** - * @return string[] - */ - protected function getClassIdentifiersTypes(ClassMetadata $class) : array - { - $entityManager = $this->em; - - return array_map( - static function ($fieldName) use ($class, $entityManager) : string { - $types = PersisterHelper::getTypeOfField($fieldName, $class, $entityManager); - assert(isset($types[0])); - - return $types[0]; - }, - $class->identifier - ); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/CachedPersisterContext.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/CachedPersisterContext.php deleted file mode 100644 index 132dac7..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/CachedPersisterContext.php +++ /dev/null @@ -1,102 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Persisters\Entity; -use Doctrine\Common\Persistence\Mapping\ClassMetadata; -use Doctrine\ORM\Query\ResultSetMapping; - -/** - * A swappable persister context to use as a container for the current - * generated query/resultSetMapping/type binding information. - * - * This class is a utility class to be used only by the persister API - * - * This object is highly mutable due to performance reasons. Same reasoning - * behind its properties being public. - * - * @author Marco Pivetta - */ -class CachedPersisterContext -{ - /** - * Metadata object that describes the mapping of the mapped entity class. - * - * @var \Doctrine\ORM\Mapping\ClassMetadata - */ - public $class; - - /** - * ResultSetMapping that is used for all queries. Is generated lazily once per request. - * - * @var \Doctrine\ORM\Query\ResultSetMapping - */ - public $rsm; - - /** - * The SELECT column list SQL fragment used for querying entities by this persister. - * This SQL fragment is only generated once per request, if at all. - * - * @var string|null - */ - public $selectColumnListSql; - - /** - * The JOIN SQL fragment used to eagerly load all many-to-one and one-to-one - * associations configured as FETCH_EAGER, as well as all inverse one-to-one associations. - * - * @var string - */ - public $selectJoinSql; - - /** - * Counter for creating unique SQL table and column aliases. - * - * @var integer - */ - public $sqlAliasCounter = 0; - - /** - * Map from class names (FQCN) to the corresponding generated SQL table aliases. - * - * @var array - */ - public $sqlTableAliases = []; - - /** - * Whether this persistent context is considering limit operations applied to the selection queries - * - * @var bool - */ - public $handlesLimits; - - /** - * @param ClassMetadata $class - * @param ResultSetMapping $rsm - * @param bool $handlesLimits - */ - public function __construct( - ClassMetadata $class, - ResultSetMapping $rsm, - $handlesLimits - ) { - $this->class = $class; - $this->rsm = $rsm; - $this->handlesLimits = (bool) $handlesLimits; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/EntityPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/EntityPersister.php deleted file mode 100644 index 9ac6316..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/EntityPersister.php +++ /dev/null @@ -1,330 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Persisters\Entity; - -use Doctrine\ORM\PersistentCollection; -use Doctrine\Common\Collections\Criteria; - -/** - * Entity persister interface - * Define the behavior that should be implemented by all entity persisters. - * - * @author Fabio B. Silva - * @since 2.5 - */ -interface EntityPersister -{ - /** - * @return \Doctrine\ORM\Mapping\ClassMetadata - */ - public function getClassMetadata(); - - /** - * Gets the ResultSetMapping used for hydration. - * - * @return \Doctrine\ORM\Query\ResultSetMapping - */ - public function getResultSetMapping(); - - /** - * Get all queued inserts. - * - * @return array - */ - public function getInserts(); - - /** - * @TODO - It should not be here. - * But its necessary since JoinedSubclassPersister#executeInserts invoke the root persister. - * - * Gets the INSERT SQL used by the persister to persist a new entity. - * - * @return string - */ - public function getInsertSQL(); - - /** - * Gets the SELECT SQL to select one or more entities by a set of field criteria. - * - * @param array|\Doctrine\Common\Collections\Criteria $criteria - * @param array|null $assoc - * @param int|null $lockMode - * @param int|null $limit - * @param int|null $offset - * @param array|null $orderBy - * - * @return string - */ - public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, array $orderBy = null); - - /** - * Get the COUNT SQL to count entities (optionally based on a criteria) - * - * @param array|\Doctrine\Common\Collections\Criteria $criteria - * - * @return string - */ - public function getCountSQL($criteria = []); - - /** - * Expands the parameters from the given criteria and use the correct binding types if found. - * - * @param $criteria - * - * @return array - */ - public function expandParameters($criteria); - - /** - * Expands Criteria Parameters by walking the expressions and grabbing all parameters and types from it. - * - * @param \Doctrine\Common\Collections\Criteria $criteria - * - * @return array - */ - public function expandCriteriaParameters(Criteria $criteria); - - /** - * Gets the SQL WHERE condition for matching a field with a given value. - * - * @param string $field - * @param mixed $value - * @param array|null $assoc - * @param string|null $comparison - * - * @return string - */ - public function getSelectConditionStatementSQL($field, $value, $assoc = null, $comparison = null); - - /** - * Adds an entity to the queued insertions. - * The entity remains queued until {@link executeInserts} is invoked. - * - * @param object $entity The entity to queue for insertion. - * - * @return void - */ - public function addInsert($entity); - - /** - * Executes all queued entity insertions and returns any generated post-insert - * identifiers that were created as a result of the insertions. - * - * If no inserts are queued, invoking this method is a NOOP. - * - * @return array An array of any generated post-insert IDs. This will be an empty array - * if the entity class does not use the IDENTITY generation strategy. - */ - public function executeInserts(); - - /** - * Updates a managed entity. The entity is updated according to its current changeset - * in the running UnitOfWork. If there is no changeset, nothing is updated. - * - * @param object $entity The entity to update. - * - * @return void - */ - public function update($entity); - - /** - * Deletes a managed entity. - * - * The entity to delete must be managed and have a persistent identifier. - * The deletion happens instantaneously. - * - * Subclasses may override this method to customize the semantics of entity deletion. - * - * @param object $entity The entity to delete. - * - * @return bool TRUE if the entity got deleted in the database, FALSE otherwise. - */ - public function delete($entity); - - /** - * Count entities (optionally filtered by a criteria) - * - * @param array|\Doctrine\Common\Collections\Criteria $criteria - * - * @return int - */ - public function count($criteria = []); - - /** - * Gets the name of the table that owns the column the given field is mapped to. - * - * The default implementation in BasicEntityPersister always returns the name - * of the table the entity type of this persister is mapped to, since an entity - * is always persisted to a single table with a BasicEntityPersister. - * - * @param string $fieldName The field name. - * - * @return string The table name. - */ - public function getOwningTable($fieldName); - - /** - * Loads an entity by a list of field criteria. - * - * @param array $criteria The criteria by which to load the entity. - * @param object|null $entity The entity to load the data into. If not specified, a new entity is created. - * @param array|null $assoc The association that connects the entity to load to another entity, if any. - * @param array $hints Hints for entity creation. - * @param int|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants - * or NULL if no specific lock mode should be used - * for loading the entity. - * @param int|null $limit Limit number of results. - * @param array|null $orderBy Criteria to order by. - * - * @return object|null The loaded and managed entity instance or NULL if the entity can not be found. - * - * @todo Check identity map? loadById method? Try to guess whether $criteria is the id? - */ - public function load(array $criteria, $entity = null, $assoc = null, array $hints = [], $lockMode = null, $limit = null, array $orderBy = null); - - /** - * Loads an entity by identifier. - * - * @param array $identifier The entity identifier. - * @param object|null $entity The entity to load the data into. If not specified, a new entity is created. - * - * @return object The loaded and managed entity instance or NULL if the entity can not be found. - * - * @todo Check parameters - */ - public function loadById(array $identifier, $entity = null); - - /** - * Loads an entity of this persister's mapped class as part of a single-valued - * association from another entity. - * - * @param array $assoc The association to load. - * @param object $sourceEntity The entity that owns the association (not necessarily the "owning side"). - * @param array $identifier The identifier of the entity to load. Must be provided if - * the association to load represents the owning side, otherwise - * the identifier is derived from the $sourceEntity. - * - * @return object The loaded and managed entity instance or NULL if the entity can not be found. - * - * @throws \Doctrine\ORM\Mapping\MappingException - */ - public function loadOneToOneEntity(array $assoc, $sourceEntity, array $identifier = []); - - /** - * Refreshes a managed entity. - * - * @param array $id The identifier of the entity as an associative array from - * column or field names to values. - * @param object $entity The entity to refresh. - * @param int|null $lockMode One of the \Doctrine\DBAL\LockMode::* constants - * or NULL if no specific lock mode should be used - * for refreshing the managed entity. - * - * @return void - */ - public function refresh(array $id, $entity, $lockMode = null); - - /** - * Loads Entities matching the given Criteria object. - * - * @param \Doctrine\Common\Collections\Criteria $criteria - * - * @return array - */ - public function loadCriteria(Criteria $criteria); - - /** - * Loads a list of entities by a list of field criteria. - * - * @param array $criteria - * @param array|null $orderBy - * @param int|null $limit - * @param int|null $offset - * - * @return array - */ - public function loadAll(array $criteria = [], array $orderBy = null, $limit = null, $offset = null); - - /** - * Gets (sliced or full) elements of the given collection. - * - * @param array $assoc - * @param object $sourceEntity - * @param int|null $offset - * @param int|null $limit - * - * @return array - */ - public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null); - - /** - * Loads a collection of entities of a many-to-many association. - * - * @param array $assoc The association mapping of the association being loaded. - * @param object $sourceEntity The entity that owns the collection. - * @param PersistentCollection $collection The collection to fill. - * - * @return array - */ - public function loadManyToManyCollection(array $assoc, $sourceEntity, PersistentCollection $collection); - - /** - * Loads a collection of entities in a one-to-many association. - * - * @param array $assoc - * @param object $sourceEntity - * @param PersistentCollection $collection The collection to load/fill. - * - * @return array - */ - public function loadOneToManyCollection(array $assoc, $sourceEntity, PersistentCollection $collection); - - /** - * Locks all rows of this entity matching the given criteria with the specified pessimistic lock mode. - * - * @param array $criteria - * @param int $lockMode One of the Doctrine\DBAL\LockMode::* constants. - * - * @return void - */ - public function lock(array $criteria, $lockMode); - - /** - * Returns an array with (sliced or full list) of elements in the specified collection. - * - * @param array $assoc - * @param object $sourceEntity - * @param int|null $offset - * @param int|null $limit - * - * @return array - */ - public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null); - - /** - * Checks whether the given managed entity exists in the database. - * - * @param object $entity - * @param Criteria|null $extraConditions - * - * @return boolean TRUE if the entity exists in the database, FALSE otherwise. - */ - public function exists($entity, Criteria $extraConditions = null); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php deleted file mode 100644 index 1f6d401..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php +++ /dev/null @@ -1,616 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Persisters\Entity; - -use Doctrine\ORM\Mapping\ClassMetadata; - -use Doctrine\DBAL\LockMode; -use Doctrine\DBAL\Types\Type; - -use Doctrine\Common\Collections\Criteria; -use Doctrine\ORM\Utility\PersisterHelper; - -/** - * The joined subclass persister maps a single entity instance to several tables in the - * database as it is defined by the Class Table Inheritance strategy. - * - * @author Roman Borschel - * @author Benjamin Eberlei - * @author Alexander - * @since 2.0 - * @see http://martinfowler.com/eaaCatalog/classTableInheritance.html - */ -class JoinedSubclassPersister extends AbstractEntityInheritancePersister -{ - /** - * Map that maps column names to the table names that own them. - * This is mainly a temporary cache, used during a single request. - * - * @var array - */ - private $owningTableMap = []; - - /** - * Map of table to quoted table names. - * - * @var array - */ - private $quotedTableMap = []; - - /** - * {@inheritdoc} - */ - protected function getDiscriminatorColumnTableName() - { - $class = ($this->class->name !== $this->class->rootEntityName) - ? $this->em->getClassMetadata($this->class->rootEntityName) - : $this->class; - - return $class->getTableName(); - } - - /** - * This function finds the ClassMetadata instance in an inheritance hierarchy - * that is responsible for enabling versioning. - * - * @return \Doctrine\ORM\Mapping\ClassMetadata - */ - private function getVersionedClassMetadata() - { - if (isset($this->class->fieldMappings[$this->class->versionField]['inherited'])) { - $definingClassName = $this->class->fieldMappings[$this->class->versionField]['inherited']; - - return $this->em->getClassMetadata($definingClassName); - } - - return $this->class; - } - - /** - * Gets the name of the table that owns the column the given field is mapped to. - * - * @param string $fieldName - * - * @return string - * - * @override - */ - public function getOwningTable($fieldName) - { - if (isset($this->owningTableMap[$fieldName])) { - return $this->owningTableMap[$fieldName]; - } - - switch (true) { - case isset($this->class->associationMappings[$fieldName]['inherited']): - $cm = $this->em->getClassMetadata($this->class->associationMappings[$fieldName]['inherited']); - break; - - case isset($this->class->fieldMappings[$fieldName]['inherited']): - $cm = $this->em->getClassMetadata($this->class->fieldMappings[$fieldName]['inherited']); - break; - - default: - $cm = $this->class; - break; - } - - $tableName = $cm->getTableName(); - $quotedTableName = $this->quoteStrategy->getTableName($cm, $this->platform); - - $this->owningTableMap[$fieldName] = $tableName; - $this->quotedTableMap[$tableName] = $quotedTableName; - - return $tableName; - } - - /** - * {@inheritdoc} - */ - public function executeInserts() - { - if ( ! $this->queuedInserts) { - return []; - } - - $postInsertIds = []; - $idGenerator = $this->class->idGenerator; - $isPostInsertId = $idGenerator->isPostInsertGenerator(); - $rootClass = ($this->class->name !== $this->class->rootEntityName) - ? $this->em->getClassMetadata($this->class->rootEntityName) - : $this->class; - - // Prepare statement for the root table - $rootPersister = $this->em->getUnitOfWork()->getEntityPersister($rootClass->name); - $rootTableName = $rootClass->getTableName(); - $rootTableStmt = $this->conn->prepare($rootPersister->getInsertSQL()); - - // Prepare statements for sub tables. - $subTableStmts = []; - - if ($rootClass !== $this->class) { - $subTableStmts[$this->class->getTableName()] = $this->conn->prepare($this->getInsertSQL()); - } - - foreach ($this->class->parentClasses as $parentClassName) { - $parentClass = $this->em->getClassMetadata($parentClassName); - $parentTableName = $parentClass->getTableName(); - - if ($parentClass !== $rootClass) { - $parentPersister = $this->em->getUnitOfWork()->getEntityPersister($parentClassName); - $subTableStmts[$parentTableName] = $this->conn->prepare($parentPersister->getInsertSQL()); - } - } - - // Execute all inserts. For each entity: - // 1) Insert on root table - // 2) Insert on sub tables - foreach ($this->queuedInserts as $entity) { - $insertData = $this->prepareInsertData($entity); - - // Execute insert on root table - $paramIndex = 1; - - foreach ($insertData[$rootTableName] as $columnName => $value) { - $rootTableStmt->bindValue($paramIndex++, $value, $this->columnTypes[$columnName]); - } - - $rootTableStmt->execute(); - - if ($isPostInsertId) { - $generatedId = $idGenerator->generate($this->em, $entity); - $id = [ - $this->class->identifier[0] => $generatedId - ]; - $postInsertIds[] = [ - 'generatedId' => $generatedId, - 'entity' => $entity, - ]; - } else { - $id = $this->em->getUnitOfWork()->getEntityIdentifier($entity); - } - - if ($this->class->isVersioned) { - $this->assignDefaultVersionValue($entity, $id); - } - - // Execute inserts on subtables. - // The order doesn't matter because all child tables link to the root table via FK. - foreach ($subTableStmts as $tableName => $stmt) { - /** @var \Doctrine\DBAL\Statement $stmt */ - $paramIndex = 1; - $data = $insertData[$tableName] ?? []; - - foreach ((array) $id as $idName => $idVal) { - $type = isset($this->columnTypes[$idName]) ? $this->columnTypes[$idName] : Type::STRING; - - $stmt->bindValue($paramIndex++, $idVal, $type); - } - - foreach ($data as $columnName => $value) { - if (!is_array($id) || !isset($id[$columnName])) { - $stmt->bindValue($paramIndex++, $value, $this->columnTypes[$columnName]); - } - } - - $stmt->execute(); - } - } - - $rootTableStmt->closeCursor(); - - foreach ($subTableStmts as $stmt) { - $stmt->closeCursor(); - } - - $this->queuedInserts = []; - - return $postInsertIds; - } - - /** - * {@inheritdoc} - */ - public function update($entity) - { - $updateData = $this->prepareUpdateData($entity); - - if ( ! $updateData) { - return; - } - - if (($isVersioned = $this->class->isVersioned) === false) { - return; - } - - $versionedClass = $this->getVersionedClassMetadata(); - $versionedTable = $versionedClass->getTableName(); - - foreach ($updateData as $tableName => $data) { - $tableName = $this->quotedTableMap[$tableName]; - $versioned = $isVersioned && $versionedTable === $tableName; - - $this->updateTable($entity, $tableName, $data, $versioned); - } - - // Make sure the table with the version column is updated even if no columns on that - // table were affected. - if ($isVersioned) { - if ( ! isset($updateData[$versionedTable])) { - $tableName = $this->quoteStrategy->getTableName($versionedClass, $this->platform); - - $this->updateTable($entity, $tableName, [], true); - } - - $identifiers = $this->em->getUnitOfWork()->getEntityIdentifier($entity); - - $this->assignDefaultVersionValue($entity, $identifiers); - } - } - - /** - * {@inheritdoc} - */ - public function delete($entity) - { - $identifier = $this->em->getUnitOfWork()->getEntityIdentifier($entity); - $id = array_combine($this->class->getIdentifierColumnNames(), $identifier); - - $this->deleteJoinTableRecords($identifier); - - // If the database platform supports FKs, just - // delete the row from the root table. Cascades do the rest. - if ($this->platform->supportsForeignKeyConstraints()) { - $rootClass = $this->em->getClassMetadata($this->class->rootEntityName); - $rootTable = $this->quoteStrategy->getTableName($rootClass, $this->platform); - $rootTypes = $this->getClassIdentifiersTypes($rootClass); - - return (bool) $this->conn->delete($rootTable, $id, $rootTypes); - } - - // Delete from all tables individually, starting from this class' table up to the root table. - $rootTable = $this->quoteStrategy->getTableName($this->class, $this->platform); - $rootTypes = $this->getClassIdentifiersTypes($this->class); - - $affectedRows = $this->conn->delete($rootTable, $id, $rootTypes); - - foreach ($this->class->parentClasses as $parentClass) { - $parentMetadata = $this->em->getClassMetadata($parentClass); - $parentTable = $this->quoteStrategy->getTableName($parentMetadata, $this->platform); - $parentTypes = $this->getClassIdentifiersTypes($parentMetadata); - - $this->conn->delete($parentTable, $id, $parentTypes); - } - - return (bool) $affectedRows; - } - - /** - * {@inheritdoc} - */ - public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, array $orderBy = null) - { - $this->switchPersisterContext($offset, $limit); - - $baseTableAlias = $this->getSQLTableAlias($this->class->name); - $joinSql = $this->getJoinSql($baseTableAlias); - - if ($assoc != null && $assoc['type'] == ClassMetadata::MANY_TO_MANY) { - $joinSql .= $this->getSelectManyToManyJoinSQL($assoc); - } - - $conditionSql = ($criteria instanceof Criteria) - ? $this->getSelectConditionCriteriaSQL($criteria) - : $this->getSelectConditionSQL($criteria, $assoc); - - // If the current class in the root entity, add the filters - if ($filterSql = $this->generateFilterConditionSQL($this->em->getClassMetadata($this->class->rootEntityName), $this->getSQLTableAlias($this->class->rootEntityName))) { - $conditionSql .= $conditionSql - ? ' AND ' . $filterSql - : $filterSql; - } - - $orderBySql = ''; - - if ($assoc !== null && isset($assoc['orderBy'])) { - $orderBy = $assoc['orderBy']; - } - - if ($orderBy) { - $orderBySql = $this->getOrderBySQL($orderBy, $baseTableAlias); - } - - $lockSql = ''; - - switch ($lockMode) { - case LockMode::PESSIMISTIC_READ: - - $lockSql = ' ' . $this->platform->getReadLockSQL(); - - break; - - case LockMode::PESSIMISTIC_WRITE: - - $lockSql = ' ' . $this->platform->getWriteLockSQL(); - - break; - } - - $tableName = $this->quoteStrategy->getTableName($this->class, $this->platform); - $from = ' FROM ' . $tableName . ' ' . $baseTableAlias; - $where = $conditionSql != '' ? ' WHERE ' . $conditionSql : ''; - $lock = $this->platform->appendLockHint($from, $lockMode); - $columnList = $this->getSelectColumnsSQL(); - $query = 'SELECT ' . $columnList - . $lock - . $joinSql - . $where - . $orderBySql; - - return $this->platform->modifyLimitQuery($query, $limit, $offset) . $lockSql; - } - - /** - * {@inheritDoc} - */ - public function getCountSQL($criteria = []) - { - $tableName = $this->quoteStrategy->getTableName($this->class, $this->platform); - $baseTableAlias = $this->getSQLTableAlias($this->class->name); - $joinSql = $this->getJoinSql($baseTableAlias); - - $conditionSql = ($criteria instanceof Criteria) - ? $this->getSelectConditionCriteriaSQL($criteria) - : $this->getSelectConditionSQL($criteria); - - $filterSql = $this->generateFilterConditionSQL($this->em->getClassMetadata($this->class->rootEntityName), $this->getSQLTableAlias($this->class->rootEntityName)); - - if ('' !== $filterSql) { - $conditionSql = $conditionSql - ? $conditionSql . ' AND ' . $filterSql - : $filterSql; - } - - $sql = 'SELECT COUNT(*) ' - . 'FROM ' . $tableName . ' ' . $baseTableAlias - . $joinSql - . (empty($conditionSql) ? '' : ' WHERE ' . $conditionSql); - - return $sql; - } - - /** - * {@inheritdoc} - */ - protected function getLockTablesSql($lockMode) - { - $joinSql = ''; - $identifierColumns = $this->class->getIdentifierColumnNames(); - $baseTableAlias = $this->getSQLTableAlias($this->class->name); - - // INNER JOIN parent tables - foreach ($this->class->parentClasses as $parentClassName) { - $conditions = []; - $tableAlias = $this->getSQLTableAlias($parentClassName); - $parentClass = $this->em->getClassMetadata($parentClassName); - $joinSql .= ' INNER JOIN ' . $this->quoteStrategy->getTableName($parentClass, $this->platform) . ' ' . $tableAlias . ' ON '; - - foreach ($identifierColumns as $idColumn) { - $conditions[] = $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn; - } - - $joinSql .= implode(' AND ', $conditions); - } - - return parent::getLockTablesSql($lockMode) . $joinSql; - } - - /** - * Ensure this method is never called. This persister overrides getSelectEntitiesSQL directly. - * - * @return string - */ - protected function getSelectColumnsSQL() - { - // Create the column list fragment only once - if ($this->currentPersisterContext->selectColumnListSql !== null) { - return $this->currentPersisterContext->selectColumnListSql; - } - - $columnList = []; - $discrColumn = $this->class->discriminatorColumn['name']; - $discrColumnType = $this->class->discriminatorColumn['type']; - $baseTableAlias = $this->getSQLTableAlias($this->class->name); - $resultColumnName = $this->platform->getSQLResultCasing($discrColumn); - - $this->currentPersisterContext->rsm->addEntityResult($this->class->name, 'r'); - $this->currentPersisterContext->rsm->setDiscriminatorColumn('r', $resultColumnName); - $this->currentPersisterContext->rsm->addMetaResult('r', $resultColumnName, $discrColumn, false, $discrColumnType); - - // Add regular columns - foreach ($this->class->fieldMappings as $fieldName => $mapping) { - $class = isset($mapping['inherited']) - ? $this->em->getClassMetadata($mapping['inherited']) - : $this->class; - - $columnList[] = $this->getSelectColumnSQL($fieldName, $class); - } - - // Add foreign key columns - foreach ($this->class->associationMappings as $mapping) { - if ( ! $mapping['isOwningSide'] || ! ($mapping['type'] & ClassMetadata::TO_ONE)) { - continue; - } - - $tableAlias = isset($mapping['inherited']) - ? $this->getSQLTableAlias($mapping['inherited']) - : $baseTableAlias; - - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - - foreach ($mapping['joinColumns'] as $joinColumn) { - $columnList[] = $this->getSelectJoinColumnSQL( - $tableAlias, - $joinColumn['name'], - $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform), - PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em) - ); - } - } - - // Add discriminator column (DO NOT ALIAS, see AbstractEntityInheritancePersister#processSQLResult). - $tableAlias = ($this->class->rootEntityName == $this->class->name) - ? $baseTableAlias - : $this->getSQLTableAlias($this->class->rootEntityName); - - $columnList[] = $tableAlias . '.' . $discrColumn; - - // sub tables - foreach ($this->class->subClasses as $subClassName) { - $subClass = $this->em->getClassMetadata($subClassName); - $tableAlias = $this->getSQLTableAlias($subClassName); - - // Add subclass columns - foreach ($subClass->fieldMappings as $fieldName => $mapping) { - if (isset($mapping['inherited'])) { - continue; - } - - $columnList[] = $this->getSelectColumnSQL($fieldName, $subClass); - } - - // Add join columns (foreign keys) - foreach ($subClass->associationMappings as $mapping) { - if ( ! $mapping['isOwningSide'] - || ! ($mapping['type'] & ClassMetadata::TO_ONE) - || isset($mapping['inherited'])) { - continue; - } - - $targetClass = $this->em->getClassMetadata($mapping['targetEntity']); - - foreach ($mapping['joinColumns'] as $joinColumn) { - $columnList[] = $this->getSelectJoinColumnSQL( - $tableAlias, - $joinColumn['name'], - $this->quoteStrategy->getJoinColumnName($joinColumn, $subClass, $this->platform), - PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em) - ); - } - } - } - - $this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList); - - return $this->currentPersisterContext->selectColumnListSql; - } - - /** - * {@inheritdoc} - */ - protected function getInsertColumnList() - { - // Identifier columns must always come first in the column list of subclasses. - $columns = $this->class->parentClasses - ? $this->class->getIdentifierColumnNames() - : []; - - foreach ($this->class->reflFields as $name => $field) { - if (isset($this->class->fieldMappings[$name]['inherited']) - && ! isset($this->class->fieldMappings[$name]['id']) - || isset($this->class->associationMappings[$name]['inherited']) - || ($this->class->isVersioned && $this->class->versionField == $name) - || isset($this->class->embeddedClasses[$name])) { - continue; - } - - if (isset($this->class->associationMappings[$name])) { - $assoc = $this->class->associationMappings[$name]; - if ($assoc['type'] & ClassMetadata::TO_ONE && $assoc['isOwningSide']) { - foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) { - $columns[] = $sourceCol; - } - } - } else if ($this->class->name != $this->class->rootEntityName || - ! $this->class->isIdGeneratorIdentity() || $this->class->identifier[0] != $name) { - $columns[] = $this->quoteStrategy->getColumnName($name, $this->class, $this->platform); - $this->columnTypes[$name] = $this->class->fieldMappings[$name]['type']; - } - } - - // Add discriminator column if it is the topmost class. - if ($this->class->name == $this->class->rootEntityName) { - $columns[] = $this->class->discriminatorColumn['name']; - } - - return $columns; - } - - /** - * {@inheritdoc} - */ - protected function assignDefaultVersionValue($entity, array $id) - { - $value = $this->fetchVersionValue($this->getVersionedClassMetadata(), $id); - $this->class->setFieldValue($entity, $this->class->versionField, $value); - } - - /** - * @param string $baseTableAlias - * - * @return string - */ - private function getJoinSql($baseTableAlias) - { - $joinSql = ''; - $identifierColumn = $this->class->getIdentifierColumnNames(); - - // INNER JOIN parent tables - foreach ($this->class->parentClasses as $parentClassName) { - $conditions = []; - $parentClass = $this->em->getClassMetadata($parentClassName); - $tableAlias = $this->getSQLTableAlias($parentClassName); - $joinSql .= ' INNER JOIN ' . $this->quoteStrategy->getTableName($parentClass, $this->platform) . ' ' . $tableAlias . ' ON '; - - - foreach ($identifierColumn as $idColumn) { - $conditions[] = $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn; - } - - $joinSql .= implode(' AND ', $conditions); - } - - // OUTER JOIN sub tables - foreach ($this->class->subClasses as $subClassName) { - $conditions = []; - $subClass = $this->em->getClassMetadata($subClassName); - $tableAlias = $this->getSQLTableAlias($subClassName); - $joinSql .= ' LEFT JOIN ' . $this->quoteStrategy->getTableName($subClass, $this->platform) . ' ' . $tableAlias . ' ON '; - - foreach ($identifierColumn as $idColumn) { - $conditions[] = $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn; - } - - $joinSql .= implode(' AND ', $conditions); - } - - return $joinSql; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php deleted file mode 100644 index 4b8352b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php +++ /dev/null @@ -1,192 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Persisters\Entity; - -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\Common\Collections\Criteria; -use Doctrine\ORM\Utility\PersisterHelper; - -/** - * Persister for entities that participate in a hierarchy mapped with the - * SINGLE_TABLE strategy. - * - * @author Roman Borschel - * @author Benjamin Eberlei - * @author Alexander - * @since 2.0 - * @link http://martinfowler.com/eaaCatalog/singleTableInheritance.html - */ -class SingleTablePersister extends AbstractEntityInheritancePersister -{ - /** - * {@inheritdoc} - */ - protected function getDiscriminatorColumnTableName() - { - return $this->class->getTableName(); - } - - /** - * {@inheritdoc} - */ - protected function getSelectColumnsSQL() - { - if ($this->currentPersisterContext->selectColumnListSql !== null) { - return $this->currentPersisterContext->selectColumnListSql; - } - - $columnList[] = parent::getSelectColumnsSQL(); - - $rootClass = $this->em->getClassMetadata($this->class->rootEntityName); - $tableAlias = $this->getSQLTableAlias($rootClass->name); - - // Append discriminator column - $discrColumn = $this->class->discriminatorColumn['name']; - $discrColumnType = $this->class->discriminatorColumn['type']; - - $columnList[] = $tableAlias . '.' . $discrColumn; - - $resultColumnName = $this->platform->getSQLResultCasing($discrColumn); - - $this->currentPersisterContext->rsm->setDiscriminatorColumn('r', $resultColumnName); - $this->currentPersisterContext->rsm->addMetaResult('r', $resultColumnName, $discrColumn, false, $discrColumnType); - - // Append subclass columns - foreach ($this->class->subClasses as $subClassName) { - $subClass = $this->em->getClassMetadata($subClassName); - - // Regular columns - foreach ($subClass->fieldMappings as $fieldName => $mapping) { - if (isset($mapping['inherited'])) { - continue; - } - - $columnList[] = $this->getSelectColumnSQL($fieldName, $subClass); - } - - // Foreign key columns - foreach ($subClass->associationMappings as $assoc) { - if ( ! $assoc['isOwningSide'] || ! ($assoc['type'] & ClassMetadata::TO_ONE) || isset($assoc['inherited'])) { - continue; - } - - $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); - - foreach ($assoc['joinColumns'] as $joinColumn) { - $columnList[] = $this->getSelectJoinColumnSQL( - $tableAlias, - $joinColumn['name'], - $this->quoteStrategy->getJoinColumnName($joinColumn, $subClass, $this->platform), - PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em) - ); - } - } - } - - $this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList); - - return $this->currentPersisterContext->selectColumnListSql; - } - - /** - * {@inheritdoc} - */ - protected function getInsertColumnList() - { - $columns = parent::getInsertColumnList(); - - // Add discriminator column to the INSERT SQL - $columns[] = $this->class->discriminatorColumn['name']; - - return $columns; - } - - /** - * {@inheritdoc} - */ - protected function getSQLTableAlias($className, $assocName = '') - { - return parent::getSQLTableAlias($this->class->rootEntityName, $assocName); - } - - /** - * {@inheritdoc} - */ - protected function getSelectConditionSQL(array $criteria, $assoc = null) - { - $conditionSql = parent::getSelectConditionSQL($criteria, $assoc); - - if ($conditionSql) { - $conditionSql .= ' AND '; - } - - return $conditionSql . $this->getSelectConditionDiscriminatorValueSQL(); - } - - /** - * {@inheritdoc} - */ - protected function getSelectConditionCriteriaSQL(Criteria $criteria) - { - $conditionSql = parent::getSelectConditionCriteriaSQL($criteria); - - if ($conditionSql) { - $conditionSql .= ' AND '; - } - - return $conditionSql . $this->getSelectConditionDiscriminatorValueSQL(); - } - - /** - * @return string - */ - protected function getSelectConditionDiscriminatorValueSQL() - { - $values = []; - - if ($this->class->discriminatorValue !== null) { // discriminators can be 0 - $values[] = $this->conn->quote($this->class->discriminatorValue); - } - - $discrValues = array_flip($this->class->discriminatorMap); - - foreach ($this->class->subClasses as $subclassName) { - $values[] = $this->conn->quote($discrValues[$subclassName]); - } - - $values = implode(', ', $values); - $discColumn = $this->class->discriminatorColumn['name']; - $tableAlias = $this->getSQLTableAlias($this->class->name); - - return $tableAlias . '.' . $discColumn . ' IN (' . $values . ')'; - } - - /** - * {@inheritdoc} - */ - protected function generateFilterConditionSQL(ClassMetadata $targetEntity, $targetTableAlias) - { - // Ensure that the filters are applied to the root entity of the inheritance tree - $targetEntity = $this->em->getClassMetadata($targetEntity->rootEntityName); - // we don't care about the $targetTableAlias, in a STI there is only one table. - - return parent::generateFilterConditionSQL($targetEntity, $targetTableAlias); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/PersisterException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/PersisterException.php deleted file mode 100644 index 09f73b2..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/PersisterException.php +++ /dev/null @@ -1,40 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Persisters; - -use Doctrine\ORM\ORMException; - -class PersisterException extends ORMException -{ - /** - * @param string $class - * @param string $associationName - * - * @return PersisterException - */ - static public function matchingAssocationFieldRequiresObject($class, $associationName) - { - return new self(sprintf( - "Cannot match on %s::%s with a non-object value. Matching objects by id is " . - "not compatible with matching on an in-memory collection, which compares objects by reference.", - $class, $associationName - )); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlExpressionVisitor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlExpressionVisitor.php deleted file mode 100644 index 476ecab..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlExpressionVisitor.php +++ /dev/null @@ -1,122 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Persisters; - -use Doctrine\ORM\Mapping\ClassMetadata; - -use Doctrine\Common\Collections\Expr\ExpressionVisitor; -use Doctrine\Common\Collections\Expr\Comparison; -use Doctrine\Common\Collections\Expr\Value; -use Doctrine\Common\Collections\Expr\CompositeExpression; -use Doctrine\ORM\Persisters\Entity\BasicEntityPersister; - -/** - * Visit Expressions and generate SQL WHERE conditions from them. - * - * @author Benjamin Eberlei - * @since 2.3 - */ -class SqlExpressionVisitor extends ExpressionVisitor -{ - /** - * @var \Doctrine\ORM\Persisters\Entity\BasicEntityPersister - */ - private $persister; - - /** - * @var \Doctrine\ORM\Mapping\ClassMetadata - */ - private $classMetadata; - - /** - * @param \Doctrine\ORM\Persisters\Entity\BasicEntityPersister $persister - * @param \Doctrine\ORM\Mapping\ClassMetadata $classMetadata - */ - public function __construct(BasicEntityPersister $persister, ClassMetadata $classMetadata) - { - $this->persister = $persister; - $this->classMetadata = $classMetadata; - } - - /** - * Converts a comparison expression into the target query language output. - * - * @param \Doctrine\Common\Collections\Expr\Comparison $comparison - * - * @return mixed - */ - public function walkComparison(Comparison $comparison) - { - $field = $comparison->getField(); - $value = $comparison->getValue()->getValue(); // shortcut for walkValue() - - if (isset($this->classMetadata->associationMappings[$field]) && - $value !== null && - ! is_object($value) && - ! in_array($comparison->getOperator(), [Comparison::IN, Comparison::NIN])) { - - throw PersisterException::matchingAssocationFieldRequiresObject($this->classMetadata->name, $field); - } - - return $this->persister->getSelectConditionStatementSQL($field, $value, null, $comparison->getOperator()); - } - - /** - * Converts a composite expression into the target query language output. - * - * @param \Doctrine\Common\Collections\Expr\CompositeExpression $expr - * - * @return mixed - * - * @throws \RuntimeException - */ - public function walkCompositeExpression(CompositeExpression $expr) - { - $expressionList = []; - - foreach ($expr->getExpressionList() as $child) { - $expressionList[] = $this->dispatch($child); - } - - switch($expr->getType()) { - case CompositeExpression::TYPE_AND: - return '(' . implode(' AND ', $expressionList) . ')'; - - case CompositeExpression::TYPE_OR: - return '(' . implode(' OR ', $expressionList) . ')'; - - default: - throw new \RuntimeException("Unknown composite " . $expr->getType()); - } - } - - /** - * Converts a value expression into the target query language part. - * - * @param \Doctrine\Common\Collections\Expr\Value $value - * - * @return mixed - */ - public function walkValue(Value $value) - { - return '?'; - } -} - diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlValueVisitor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlValueVisitor.php deleted file mode 100644 index a5df126..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/SqlValueVisitor.php +++ /dev/null @@ -1,128 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Persisters; - -use Doctrine\Common\Collections\Expr\ExpressionVisitor; -use Doctrine\Common\Collections\Expr\Comparison; -use Doctrine\Common\Collections\Expr\Value; -use Doctrine\Common\Collections\Expr\CompositeExpression; - -/** - * Extract the values from a criteria/expression - * - * @author Benjamin Eberlei - */ -class SqlValueVisitor extends ExpressionVisitor -{ - /** - * @var array - */ - private $values = []; - - /** - * @var array - */ - private $types = []; - - /** - * Converts a comparison expression into the target query language output. - * - * @param \Doctrine\Common\Collections\Expr\Comparison $comparison - * - * @return void - */ - public function walkComparison(Comparison $comparison) - { - $value = $this->getValueFromComparison($comparison); - $field = $comparison->getField(); - $operator = $comparison->getOperator(); - - if (($operator === Comparison::EQ || $operator === Comparison::IS) && $value === null) { - return; - } else if ($operator === Comparison::NEQ && $value === null) { - return; - } - - $this->values[] = $value; - $this->types[] = [$field, $value, $operator]; - } - - /** - * Converts a composite expression into the target query language output. - * - * @param \Doctrine\Common\Collections\Expr\CompositeExpression $expr - * - * @return void - */ - public function walkCompositeExpression(CompositeExpression $expr) - { - foreach ($expr->getExpressionList() as $child) { - $this->dispatch($child); - } - } - - /** - * Converts a value expression into the target query language part. - * - * @param \Doctrine\Common\Collections\Expr\Value $value - * - * @return mixed - */ - public function walkValue(Value $value) - { - return; - } - - /** - * Returns the Parameters and Types necessary for matching the last visited expression. - * - * @return array - */ - public function getParamsAndTypes() - { - return [$this->values, $this->types]; - } - - /** - * Returns the value from a Comparison. In case of a CONTAINS comparison, - * the value is wrapped in %-signs, because it will be used in a LIKE clause. - * - * @param \Doctrine\Common\Collections\Expr\Comparison $comparison - * @return mixed - */ - protected function getValueFromComparison(Comparison $comparison) - { - $value = $comparison->getValue()->getValue(); - - switch ($comparison->getOperator()) { - case Comparison::CONTAINS: - return "%{$value}%"; - - case Comparison::STARTS_WITH: - return "{$value}%"; - - case Comparison::ENDS_WITH: - return "%{$value}"; - - default: - return $value; - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/PessimisticLockException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/PessimisticLockException.php deleted file mode 100644 index d60f7a8..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/PessimisticLockException.php +++ /dev/null @@ -1,40 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -/** - * Pessimistic Lock Exception - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.com - * @since 1.0 - * @author Benjamin Eberlei - * @author Roman Borschel - */ -class PessimisticLockException extends ORMException -{ - /** - * @return PessimisticLockException - */ - public static function lockFailed() - { - return new self("The pessimistic lock failed."); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Autoloader.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Autoloader.php deleted file mode 100644 index 9b2e2cd..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Autoloader.php +++ /dev/null @@ -1,29 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Proxy; - -use Doctrine\Common\Proxy\Autoloader as BaseAutoloader; - -/** - * @deprecated use \Doctrine\Common\Proxy\Autoloader instead - */ -class Autoloader extends BaseAutoloader -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Proxy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Proxy.php deleted file mode 100644 index 75a61a7..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/Proxy.php +++ /dev/null @@ -1,34 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Proxy; - -use Doctrine\Common\Proxy\Proxy as BaseProxy; - -/** - * Interface for proxy classes. - * - * @author Roman Borschel - * @since 2.0 - * - * @deprecated 2.7 This interface is being removed from the ORM and won't have any replacement, proxies will no longer implement it. - */ -interface Proxy extends BaseProxy -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php deleted file mode 100644 index 31fac18..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php +++ /dev/null @@ -1,213 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Proxy; - -use Doctrine\Common\Persistence\Mapping\ClassMetadata; -use Doctrine\Common\Proxy\AbstractProxyFactory; -use Doctrine\Common\Proxy\Proxy as BaseProxy; -use Doctrine\Common\Proxy\ProxyDefinition; -use Doctrine\Common\Proxy\ProxyGenerator; -use Doctrine\Common\Util\ClassUtils; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Persisters\Entity\EntityPersister; -use Doctrine\ORM\EntityNotFoundException; -use Doctrine\ORM\Utility\IdentifierFlattener; - -/** - * This factory is used to create proxy objects for entities at runtime. - * - * @author Roman Borschel - * @author Giorgio Sironi - * @author Marco Pivetta - * @since 2.0 - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class ProxyFactory extends AbstractProxyFactory -{ - /** - * @var EntityManagerInterface The EntityManager this factory is bound to. - */ - private $em; - - /** - * @var \Doctrine\ORM\UnitOfWork The UnitOfWork this factory uses to retrieve persisters - */ - private $uow; - - /** - * @var string - */ - private $proxyNs; - - /** - * The IdentifierFlattener used for manipulating identifiers - * - * @var \Doctrine\ORM\Utility\IdentifierFlattener - */ - private $identifierFlattener; - - /** - * Initializes a new instance of the ProxyFactory class that is - * connected to the given EntityManager. - * - * @param EntityManagerInterface $em The EntityManager the new factory works for. - * @param string $proxyDir The directory to use for the proxy classes. It must exist. - * @param string $proxyNs The namespace to use for the proxy classes. - * @param boolean|int $autoGenerate The strategy for automatically generating proxy classes. Possible - * values are constants of Doctrine\Common\Proxy\AbstractProxyFactory. - */ - public function __construct(EntityManagerInterface $em, $proxyDir, $proxyNs, $autoGenerate = AbstractProxyFactory::AUTOGENERATE_NEVER) - { - $proxyGenerator = new ProxyGenerator($proxyDir, $proxyNs); - - $proxyGenerator->setPlaceholder('baseProxyInterface', Proxy::class); - parent::__construct($proxyGenerator, $em->getMetadataFactory(), $autoGenerate); - - $this->em = $em; - $this->uow = $em->getUnitOfWork(); - $this->proxyNs = $proxyNs; - $this->identifierFlattener = new IdentifierFlattener($this->uow, $em->getMetadataFactory()); - } - - /** - * {@inheritDoc} - */ - protected function skipClass(ClassMetadata $metadata) - { - /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */ - return $metadata->isMappedSuperclass - || $metadata->isEmbeddedClass - || $metadata->getReflectionClass()->isAbstract(); - } - - /** - * {@inheritDoc} - */ - protected function createProxyDefinition($className) - { - $classMetadata = $this->em->getClassMetadata($className); - $entityPersister = $this->uow->getEntityPersister($className); - - return new ProxyDefinition( - ClassUtils::generateProxyClassName($className, $this->proxyNs), - $classMetadata->getIdentifierFieldNames(), - $classMetadata->getReflectionProperties(), - $this->createInitializer($classMetadata, $entityPersister), - $this->createCloner($classMetadata, $entityPersister) - ); - } - - /** - * Creates a closure capable of initializing a proxy - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $classMetadata - * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $entityPersister - * - * @return \Closure - * - * @throws \Doctrine\ORM\EntityNotFoundException - */ - private function createInitializer(ClassMetadata $classMetadata, EntityPersister $entityPersister) - { - $wakeupProxy = $classMetadata->getReflectionClass()->hasMethod('__wakeup'); - - return function (BaseProxy $proxy) use ($entityPersister, $classMetadata, $wakeupProxy) { - $initializer = $proxy->__getInitializer(); - $cloner = $proxy->__getCloner(); - - $proxy->__setInitializer(null); - $proxy->__setCloner(null); - - if ($proxy->__isInitialized()) { - return; - } - - $properties = $proxy->__getLazyProperties(); - - foreach ($properties as $propertyName => $property) { - if ( ! isset($proxy->$propertyName)) { - $proxy->$propertyName = $properties[$propertyName]; - } - } - - $proxy->__setInitialized(true); - - if ($wakeupProxy) { - $proxy->__wakeup(); - } - - $identifier = $classMetadata->getIdentifierValues($proxy); - - if (null === $entityPersister->loadById($identifier, $proxy)) { - $proxy->__setInitializer($initializer); - $proxy->__setCloner($cloner); - $proxy->__setInitialized(false); - - throw EntityNotFoundException::fromClassNameAndIdentifier( - $classMetadata->getName(), - $this->identifierFlattener->flattenIdentifier($classMetadata, $identifier) - ); - } - }; - } - - /** - * Creates a closure capable of finalizing state a cloned proxy - * - * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $classMetadata - * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $entityPersister - * - * @return \Closure - * - * @throws \Doctrine\ORM\EntityNotFoundException - */ - private function createCloner(ClassMetadata $classMetadata, EntityPersister $entityPersister) - { - return function (BaseProxy $proxy) use ($entityPersister, $classMetadata) { - if ($proxy->__isInitialized()) { - return; - } - - $proxy->__setInitialized(true); - $proxy->__setInitializer(null); - - $class = $entityPersister->getClassMetadata(); - $identifier = $classMetadata->getIdentifierValues($proxy); - $original = $entityPersister->loadById($identifier); - - if (null === $original) { - throw EntityNotFoundException::fromClassNameAndIdentifier( - $classMetadata->getName(), - $this->identifierFlattener->flattenIdentifier($classMetadata, $identifier) - ); - } - - foreach ($class->getReflectionProperties() as $property) { - if ( ! $class->hasField($property->name) && ! $class->hasAssociation($property->name)) { - continue; - } - - $property->setAccessible(true); - $property->setValue($proxy, $property->getValue($original)); - } - }; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query.php deleted file mode 100644 index c9d8fb6..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query.php +++ /dev/null @@ -1,794 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\DBAL\LockMode; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Query\Exec\AbstractSqlExecutor; -use Doctrine\ORM\Query\Parameter; -use Doctrine\ORM\Query\ParameterTypeInferer; -use Doctrine\ORM\Query\Parser; -use Doctrine\ORM\Query\ParserResult; -use Doctrine\ORM\Query\QueryException; -use Doctrine\ORM\Utility\HierarchyDiscriminatorResolver; -use function array_keys; -use function assert; - -/** - * A Query object represents a DQL query. - * - * @since 1.0 - * @author Guilherme Blanco - * @author Konsta Vesterinen - * @author Roman Borschel - */ -final class Query extends AbstractQuery -{ - /** - * A query object is in CLEAN state when it has NO unparsed/unprocessed DQL parts. - */ - const STATE_CLEAN = 1; - - /** - * A query object is in state DIRTY when it has DQL parts that have not yet been - * parsed/processed. This is automatically defined as DIRTY when addDqlQueryPart - * is called. - */ - const STATE_DIRTY = 2; - - /* Query HINTS */ - - /** - * The refresh hint turns any query into a refresh query with the result that - * any local changes in entities are overridden with the fetched values. - * - * @var string - */ - const HINT_REFRESH = 'doctrine.refresh'; - - /** - * @var string - */ - const HINT_CACHE_ENABLED = 'doctrine.cache.enabled'; - - /** - * @var string - */ - const HINT_CACHE_EVICT = 'doctrine.cache.evict'; - - /** - * Internal hint: is set to the proxy entity that is currently triggered for loading - * - * @var string - */ - const HINT_REFRESH_ENTITY = 'doctrine.refresh.entity'; - - /** - * The forcePartialLoad query hint forces a particular query to return - * partial objects. - * - * @var string - * @todo Rename: HINT_OPTIMIZE - */ - const HINT_FORCE_PARTIAL_LOAD = 'doctrine.forcePartialLoad'; - - /** - * The includeMetaColumns query hint causes meta columns like foreign keys and - * discriminator columns to be selected and returned as part of the query result. - * - * This hint does only apply to non-object queries. - * - * @var string - */ - const HINT_INCLUDE_META_COLUMNS = 'doctrine.includeMetaColumns'; - - /** - * An array of class names that implement \Doctrine\ORM\Query\TreeWalker and - * are iterated and executed after the DQL has been parsed into an AST. - * - * @var string - */ - const HINT_CUSTOM_TREE_WALKERS = 'doctrine.customTreeWalkers'; - - /** - * A string with a class name that implements \Doctrine\ORM\Query\TreeWalker - * and is used for generating the target SQL from any DQL AST tree. - * - * @var string - */ - const HINT_CUSTOM_OUTPUT_WALKER = 'doctrine.customOutputWalker'; - - //const HINT_READ_ONLY = 'doctrine.readOnly'; - - /** - * @var string - */ - const HINT_INTERNAL_ITERATION = 'doctrine.internal.iteration'; - - /** - * @var string - */ - const HINT_LOCK_MODE = 'doctrine.lockMode'; - - /** - * The current state of this query. - * - * @var integer - */ - private $_state = self::STATE_CLEAN; - - /** - * A snapshot of the parameter types the query was parsed with. - * - * @var array - */ - private $_parsedTypes = []; - - /** - * Cached DQL query. - * - * @var string|null - */ - private $_dql = null; - - /** - * The parser result that holds DQL => SQL information. - * - * @var \Doctrine\ORM\Query\ParserResult - */ - private $_parserResult; - - /** - * The first result to return (the "offset"). - * - * @var int|null - */ - private $_firstResult = null; - - /** - * The maximum number of results to return (the "limit"). - * - * @var integer|null - */ - private $_maxResults = null; - - /** - * The cache driver used for caching queries. - * - * @var \Doctrine\Common\Cache\Cache|null - */ - private $_queryCache; - - /** - * Whether or not expire the query cache. - * - * @var boolean - */ - private $_expireQueryCache = false; - - /** - * The query cache lifetime. - * - * @var int - */ - private $_queryCacheTTL; - - /** - * Whether to use a query cache, if available. Defaults to TRUE. - * - * @var boolean - */ - private $_useQueryCache = true; - - /** - * Gets the SQL query/queries that correspond to this DQL query. - * - * @return mixed The built sql query or an array of all sql queries. - * - * @override - */ - public function getSQL() - { - return $this->_parse()->getSqlExecutor()->getSqlStatements(); - } - - /** - * Returns the corresponding AST for this DQL query. - * - * @return \Doctrine\ORM\Query\AST\SelectStatement | - * \Doctrine\ORM\Query\AST\UpdateStatement | - * \Doctrine\ORM\Query\AST\DeleteStatement - */ - public function getAST() - { - $parser = new Parser($this); - - return $parser->getAST(); - } - - /** - * {@inheritdoc} - */ - protected function getResultSetMapping() - { - // parse query or load from cache - if ($this->_resultSetMapping === null) { - $this->_resultSetMapping = $this->_parse()->getResultSetMapping(); - } - - return $this->_resultSetMapping; - } - - /** - * Parses the DQL query, if necessary, and stores the parser result. - * - * Note: Populates $this->_parserResult as a side-effect. - * - * @return \Doctrine\ORM\Query\ParserResult - */ - private function _parse() - { - $types = []; - - foreach ($this->parameters as $parameter) { - /** @var Query\Parameter $parameter */ - $types[$parameter->getName()] = $parameter->getType(); - } - - // Return previous parser result if the query and the filter collection are both clean - if ($this->_state === self::STATE_CLEAN && $this->_parsedTypes === $types && $this->_em->isFiltersStateClean()) { - return $this->_parserResult; - } - - $this->_state = self::STATE_CLEAN; - $this->_parsedTypes = $types; - - // Check query cache. - if ( ! ($this->_useQueryCache && ($queryCache = $this->getQueryCacheDriver()))) { - $parser = new Parser($this); - - $this->_parserResult = $parser->parse(); - - return $this->_parserResult; - } - - $hash = $this->_getQueryCacheId(); - $cached = $this->_expireQueryCache ? false : $queryCache->fetch($hash); - - if ($cached instanceof ParserResult) { - // Cache hit. - $this->_parserResult = $cached; - - return $this->_parserResult; - } - - // Cache miss. - $parser = new Parser($this); - - $this->_parserResult = $parser->parse(); - - $queryCache->save($hash, $this->_parserResult, $this->_queryCacheTTL); - - return $this->_parserResult; - } - - /** - * {@inheritdoc} - */ - protected function _doExecute() - { - $executor = $this->_parse()->getSqlExecutor(); - - if ($this->_queryCacheProfile) { - $executor->setQueryCacheProfile($this->_queryCacheProfile); - } else { - $executor->removeQueryCacheProfile(); - } - - if ($this->_resultSetMapping === null) { - $this->_resultSetMapping = $this->_parserResult->getResultSetMapping(); - } - - // Prepare parameters - $paramMappings = $this->_parserResult->getParameterMappings(); - $paramCount = count($this->parameters); - $mappingCount = count($paramMappings); - - if ($paramCount > $mappingCount) { - throw QueryException::tooManyParameters($mappingCount, $paramCount); - } - - if ($paramCount < $mappingCount) { - throw QueryException::tooFewParameters($mappingCount, $paramCount); - } - - // evict all cache for the entity region - if ($this->hasCache && isset($this->_hints[self::HINT_CACHE_EVICT]) && $this->_hints[self::HINT_CACHE_EVICT]) { - $this->evictEntityCacheRegion(); - } - - list($sqlParams, $types) = $this->processParameterMappings($paramMappings); - - $this->evictResultSetCache( - $executor, - $sqlParams, - $types, - $this->_em->getConnection()->getParams() - ); - - return $executor->execute($this->_em->getConnection(), $sqlParams, $types); - } - - private function evictResultSetCache( - AbstractSqlExecutor $executor, - array $sqlParams, - array $types, - array $connectionParams - ) { - if (null === $this->_queryCacheProfile || ! $this->getExpireResultCache()) { - return; - } - - $cacheDriver = $this->_queryCacheProfile->getResultCacheDriver(); - $statements = (array) $executor->getSqlStatements(); // Type casted since it can either be a string or an array - - foreach ($statements as $statement) { - $cacheKeys = $this->_queryCacheProfile->generateCacheKeys($statement, $sqlParams, $types, $connectionParams); - - $cacheDriver->delete(reset($cacheKeys)); - } - } - - /** - * Evict entity cache region - */ - private function evictEntityCacheRegion() - { - $AST = $this->getAST(); - - if ($AST instanceof \Doctrine\ORM\Query\AST\SelectStatement) { - throw new QueryException('The hint "HINT_CACHE_EVICT" is not valid for select statements.'); - } - - $className = ($AST instanceof \Doctrine\ORM\Query\AST\DeleteStatement) - ? $AST->deleteClause->abstractSchemaName - : $AST->updateClause->abstractSchemaName; - - $this->_em->getCache()->evictEntityRegion($className); - } - - /** - * Processes query parameter mappings. - * - * @param array $paramMappings - * - * @return array - * - * @throws Query\QueryException - */ - private function processParameterMappings($paramMappings) - { - $sqlParams = []; - $types = []; - - foreach ($this->parameters as $parameter) { - $key = $parameter->getName(); - - if ( ! isset($paramMappings[$key])) { - throw QueryException::unknownParameter($key); - } - - [$value, $type] = $this->resolveParameterValue($parameter); - - foreach ($paramMappings[$key] as $position) { - $types[$position] = $type; - } - - $sqlPositions = $paramMappings[$key]; - - // optimized multi value sql positions away for now, - // they are not allowed in DQL anyways. - $value = [$value]; - $countValue = count($value); - - for ($i = 0, $l = count($sqlPositions); $i < $l; $i++) { - $sqlParams[$sqlPositions[$i]] = $value[($i % $countValue)]; - } - } - - if (count($sqlParams) != count($types)) { - throw QueryException::parameterTypeMismatch(); - } - - if ($sqlParams) { - ksort($sqlParams); - $sqlParams = array_values($sqlParams); - - ksort($types); - $types = array_values($types); - } - - return [$sqlParams, $types]; - } - - /** @return mixed[] tuple of (value, type) */ - private function resolveParameterValue(Parameter $parameter) : array - { - if ($parameter->typeWasSpecified()) { - return [$parameter->getValue(), $parameter->getType()]; - } - - $key = $parameter->getName(); - $originalValue = $parameter->getValue(); - $value = $originalValue; - $rsm = $this->getResultSetMapping(); - - assert($rsm !== null); - - if ($value instanceof ClassMetadata && isset($rsm->metadataParameterMapping[$key])) { - $value = $value->getMetadataValue($rsm->metadataParameterMapping[$key]); - } - - if ($value instanceof ClassMetadata && isset($rsm->discriminatorParameters[$key])) { - $value = array_keys(HierarchyDiscriminatorResolver::resolveDiscriminatorsForClass($value, $this->_em)); - } - - $processedValue = $this->processParameterValue($value); - - return [ - $processedValue, - $originalValue === $processedValue - ? $parameter->getType() - : ParameterTypeInferer::inferType($processedValue), - ]; - } - - /** - * Defines a cache driver to be used for caching queries. - * - * @param \Doctrine\Common\Cache\Cache|null $queryCache Cache driver. - * - * @return Query This query instance. - */ - public function setQueryCacheDriver($queryCache) - { - $this->_queryCache = $queryCache; - - return $this; - } - - /** - * Defines whether the query should make use of a query cache, if available. - * - * @param boolean $bool - * - * @return Query This query instance. - */ - public function useQueryCache($bool) - { - $this->_useQueryCache = $bool; - - return $this; - } - - /** - * Returns the cache driver used for query caching. - * - * @return \Doctrine\Common\Cache\Cache|null The cache driver used for query caching or NULL, if - * this Query does not use query caching. - */ - public function getQueryCacheDriver() - { - if ($this->_queryCache) { - return $this->_queryCache; - } - - return $this->_em->getConfiguration()->getQueryCacheImpl(); - } - - /** - * Defines how long the query cache will be active before expire. - * - * @param integer $timeToLive How long the cache entry is valid. - * - * @return Query This query instance. - */ - public function setQueryCacheLifetime($timeToLive) - { - if ($timeToLive !== null) { - $timeToLive = (int) $timeToLive; - } - - $this->_queryCacheTTL = $timeToLive; - - return $this; - } - - /** - * Retrieves the lifetime of resultset cache. - * - * @return int - */ - public function getQueryCacheLifetime() - { - return $this->_queryCacheTTL; - } - - /** - * Defines if the query cache is active or not. - * - * @param boolean $expire Whether or not to force query cache expiration. - * - * @return Query This query instance. - */ - public function expireQueryCache($expire = true) - { - $this->_expireQueryCache = $expire; - - return $this; - } - - /** - * Retrieves if the query cache is active or not. - * - * @return bool - */ - public function getExpireQueryCache() - { - return $this->_expireQueryCache; - } - - /** - * @override - */ - public function free() - { - parent::free(); - - $this->_dql = null; - $this->_state = self::STATE_CLEAN; - } - - /** - * Sets a DQL query string. - * - * @param string $dqlQuery DQL Query. - * - * @return \Doctrine\ORM\AbstractQuery - */ - public function setDQL($dqlQuery) - { - if ($dqlQuery !== null) { - $this->_dql = $dqlQuery; - $this->_state = self::STATE_DIRTY; - } - - return $this; - } - - /** - * Returns the DQL query that is represented by this query object. - * - * @return string|null - */ - public function getDQL() - { - return $this->_dql; - } - - /** - * Returns the state of this query object - * By default the type is Doctrine_ORM_Query_Abstract::STATE_CLEAN but if it appears any unprocessed DQL - * part, it is switched to Doctrine_ORM_Query_Abstract::STATE_DIRTY. - * - * @see AbstractQuery::STATE_CLEAN - * @see AbstractQuery::STATE_DIRTY - * - * @return integer The query state. - */ - public function getState() - { - return $this->_state; - } - - /** - * Method to check if an arbitrary piece of DQL exists - * - * @param string $dql Arbitrary piece of DQL to check for. - * - * @return boolean - */ - public function contains($dql) - { - return stripos($this->getDQL(), $dql) !== false; - } - - /** - * Sets the position of the first result to retrieve (the "offset"). - * - * @param integer $firstResult The first result to return. - * - * @return Query This query object. - */ - public function setFirstResult($firstResult) - { - $this->_firstResult = $firstResult; - $this->_state = self::STATE_DIRTY; - - return $this; - } - - /** - * Gets the position of the first result the query object was set to retrieve (the "offset"). - * Returns NULL if {@link setFirstResult} was not applied to this query. - * - * @return int|null The position of the first result. - */ - public function getFirstResult() - { - return $this->_firstResult; - } - - /** - * Sets the maximum number of results to retrieve (the "limit"). - * - * @param integer|null $maxResults - * - * @return Query This query object. - */ - public function setMaxResults($maxResults) - { - $this->_maxResults = $maxResults; - $this->_state = self::STATE_DIRTY; - - return $this; - } - - /** - * Gets the maximum number of results the query object was set to retrieve (the "limit"). - * Returns NULL if {@link setMaxResults} was not applied to this query. - * - * @return integer|null Maximum number of results. - */ - public function getMaxResults() - { - return $this->_maxResults; - } - - /** - * Executes the query and returns an IterableResult that can be used to incrementally - * iterated over the result. - * - * @param ArrayCollection|array|null $parameters The query parameters. - * @param string|int $hydrationMode The hydration mode to use. - * - * @return \Doctrine\ORM\Internal\Hydration\IterableResult - */ - public function iterate($parameters = null, $hydrationMode = self::HYDRATE_OBJECT) - { - $this->setHint(self::HINT_INTERNAL_ITERATION, true); - - return parent::iterate($parameters, $hydrationMode); - } - - /** - * {@inheritdoc} - */ - public function setHint($name, $value) - { - $this->_state = self::STATE_DIRTY; - - return parent::setHint($name, $value); - } - - /** - * {@inheritdoc} - */ - public function setHydrationMode($hydrationMode) - { - $this->_state = self::STATE_DIRTY; - - return parent::setHydrationMode($hydrationMode); - } - - /** - * Set the lock mode for this Query. - * - * @see \Doctrine\DBAL\LockMode - * - * @param int $lockMode - * - * @return Query - * - * @throws TransactionRequiredException - */ - public function setLockMode($lockMode) - { - if (in_array($lockMode, [LockMode::NONE, LockMode::PESSIMISTIC_READ, LockMode::PESSIMISTIC_WRITE], true)) { - if ( ! $this->_em->getConnection()->isTransactionActive()) { - throw TransactionRequiredException::transactionRequired(); - } - } - - $this->setHint(self::HINT_LOCK_MODE, $lockMode); - - return $this; - } - - /** - * Get the current lock mode for this query. - * - * @return int|null The current lock mode of this query or NULL if no specific lock mode is set. - */ - public function getLockMode() - { - $lockMode = $this->getHint(self::HINT_LOCK_MODE); - - if (false === $lockMode) { - return null; - } - - return $lockMode; - } - - /** - * Generate a cache id for the query cache - reusing the Result-Cache-Id generator. - * - * @return string - */ - protected function _getQueryCacheId() - { - ksort($this->_hints); - - $platform = $this->getEntityManager() - ->getConnection() - ->getDatabasePlatform() - ->getName(); - - return md5( - $this->getDQL() . serialize($this->_hints) . - '&platform=' . $platform . - ($this->_em->hasFilters() ? $this->_em->getFilters()->getHash() : '') . - '&firstResult=' . $this->_firstResult . '&maxResult=' . $this->_maxResults . - '&hydrationMode=' . $this->_hydrationMode . '&types=' . serialize($this->_parsedTypes) . 'DOCTRINE_QUERY_CACHE_SALT' - ); - } - - /** - * {@inheritdoc} - */ - protected function getHash() - { - return sha1(parent::getHash(). '-'. $this->_firstResult . '-' . $this->_maxResults); - } - - /** - * Cleanup Query resource when clone is called. - * - * @return void - */ - public function __clone() - { - parent::__clone(); - - $this->_state = self::STATE_DIRTY; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ASTException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ASTException.php deleted file mode 100644 index b8f931b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ASTException.php +++ /dev/null @@ -1,38 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -use Doctrine\ORM\Query\QueryException; - -/** - * Base exception class for AST exceptions. - */ -class ASTException extends QueryException -{ - /** - * @param Node $node - * - * @return ASTException - */ - public static function noDispatchForNode($node) - { - return new self("Double-dispatch for node " . get_class($node) . " is not supported."); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/AggregateExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/AggregateExpression.php deleted file mode 100644 index 0966d90..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/AggregateExpression.php +++ /dev/null @@ -1,69 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * Description of AggregateExpression. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class AggregateExpression extends Node -{ - /** - * @var string - */ - public $functionName; - - /** - * @var PathExpression|SimpleArithmeticExpression - */ - public $pathExpression; - - /** - * Some aggregate expressions support distinct, eg COUNT. - * - * @var bool - */ - public $isDistinct = false; - - /** - * @param string $functionName - * @param PathExpression|SimpleArithmeticExpression $pathExpression - * @param bool $isDistinct - */ - public function __construct($functionName, $pathExpression, $isDistinct) - { - $this->functionName = $functionName; - $this->pathExpression = $pathExpression; - $this->isDistinct = $isDistinct; - } - - /** - * {@inheritdoc} - */ - public function dispatch($walker) - { - return $walker->walkAggregateExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticExpression.php deleted file mode 100644 index b586cba..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticExpression.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")" - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ArithmeticExpression extends Node -{ - /** - * @var SimpleArithmeticExpression|null - */ - public $simpleArithmeticExpression; - - /** - * @var Subselect|null - */ - public $subselect; - - /** - * @return bool - */ - public function isSimpleArithmeticExpression() - { - return (bool) $this->simpleArithmeticExpression; - } - - /** - * @return bool - */ - public function isSubselect() - { - return (bool) $this->subselect; - } - - /** - * {@inheritdoc} - */ - public function dispatch($walker) - { - return $walker->walkArithmeticExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticFactor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticFactor.php deleted file mode 100644 index 3120466..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticFactor.php +++ /dev/null @@ -1,78 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * ArithmeticFactor ::= [("+" | "-")] ArithmeticPrimary - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ArithmeticFactor extends Node -{ - /** - * @var mixed - */ - public $arithmeticPrimary; - - /** - * NULL represents no sign, TRUE means positive and FALSE means negative sign. - * - * @var null|boolean - */ - public $sign; - - /** - * @param mixed $arithmeticPrimary - * @param null|bool $sign - */ - public function __construct($arithmeticPrimary, $sign = null) - { - $this->arithmeticPrimary = $arithmeticPrimary; - $this->sign = $sign; - } - - /** - * @return bool - */ - public function isPositiveSigned() - { - return $this->sign === true; - } - - /** - * @return bool - */ - public function isNegativeSigned() - { - return $this->sign === false; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkArithmeticFactor($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticTerm.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticTerm.php deleted file mode 100644 index e08ae7f..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ArithmeticTerm.php +++ /dev/null @@ -1,53 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * ArithmeticTerm ::= ArithmeticFactor {("*" | "/") ArithmeticFactor}* - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ArithmeticTerm extends Node -{ - /** - * @var array - */ - public $arithmeticFactors; - - /** - * @param array $arithmeticFactors - */ - public function __construct(array $arithmeticFactors) - { - $this->arithmeticFactors = $arithmeticFactors; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkArithmeticTerm($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/BetweenExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/BetweenExpression.php deleted file mode 100644 index 1e31fd1..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/BetweenExpression.php +++ /dev/null @@ -1,72 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * Description of BetweenExpression. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class BetweenExpression extends Node -{ - /** - * @var ArithmeticExpression - */ - public $expression; - - /** - * @var ArithmeticExpression - */ - public $leftBetweenExpression; - - /** - * @var ArithmeticExpression - */ - public $rightBetweenExpression; - - /** - * @var bool - */ - public $not; - - /** - * @param ArithmeticExpression $expr - * @param ArithmeticExpression $leftExpr - * @param ArithmeticExpression $rightExpr - */ - public function __construct($expr, $leftExpr, $rightExpr) - { - $this->expression = $expr; - $this->leftBetweenExpression = $leftExpr; - $this->rightBetweenExpression = $rightExpr; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkBetweenExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CoalesceExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CoalesceExpression.php deleted file mode 100644 index 9e3b4c5..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CoalesceExpression.php +++ /dev/null @@ -1,55 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * CoalesceExpression ::= "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")" - * - * @since 2.1 - * - * @link www.doctrine-project.org - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class CoalesceExpression extends Node -{ - /** - * @var array - */ - public $scalarExpressions = []; - - /** - * @param array $scalarExpressions - */ - public function __construct(array $scalarExpressions) - { - $this->scalarExpressions = $scalarExpressions; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkCoalesceExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CollectionMemberExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CollectionMemberExpression.php deleted file mode 100644 index 70989a2..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/CollectionMemberExpression.php +++ /dev/null @@ -1,63 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * CollectionMemberExpression ::= EntityExpression ["NOT"] "MEMBER" ["OF"] CollectionValuedPathExpression - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class CollectionMemberExpression extends Node -{ - public $entityExpression; - - /** - * @var PathExpression - */ - public $collectionValuedPathExpression; - - /** - * @var bool - */ - public $not; - - /** - * @param mixed $entityExpr - * @param PathExpression $collValuedPathExpr - */ - public function __construct($entityExpr, $collValuedPathExpr) - { - $this->entityExpression = $entityExpr; - $this->collectionValuedPathExpression = $collValuedPathExpr; - } - - /** - * {@inheritdoc} - */ - public function dispatch($walker) - { - return $walker->walkCollectionMemberExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ComparisonExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ComparisonExpression.php deleted file mode 100644 index ad4d222..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ComparisonExpression.php +++ /dev/null @@ -1,72 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression ) | - * StringExpression ComparisonOperator (StringExpression | QuantifiedExpression) | - * BooleanExpression ("=" | "<>" | "!=") (BooleanExpression | QuantifiedExpression) | - * EnumExpression ("=" | "<>" | "!=") (EnumExpression | QuantifiedExpression) | - * DatetimeExpression ComparisonOperator (DatetimeExpression | QuantifiedExpression) | - * EntityExpression ("=" | "<>") (EntityExpression | QuantifiedExpression) - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ComparisonExpression extends Node -{ - /** - * @var Node - */ - public $leftExpression; - - /** - * @var Node - */ - public $rightExpression; - - /** - * @var string - */ - public $operator; - - /** - * @param Node $leftExpr - * @param string $operator - * @param Node $rightExpr - */ - public function __construct($leftExpr, $operator, $rightExpr) - { - $this->leftExpression = $leftExpr; - $this->rightExpression = $rightExpr; - $this->operator = $operator; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkComparisonExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalExpression.php deleted file mode 100644 index bf82362..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalExpression.php +++ /dev/null @@ -1,53 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * ConditionalExpression ::= ConditionalTerm {"OR" ConditionalTerm}* - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ConditionalExpression extends Node -{ - /** - * @var array - */ - public $conditionalTerms = []; - - /** - * @param array $conditionalTerms - */ - public function __construct(array $conditionalTerms) - { - $this->conditionalTerms = $conditionalTerms; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkConditionalExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalFactor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalFactor.php deleted file mode 100644 index 7c89faa..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalFactor.php +++ /dev/null @@ -1,58 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * ConditionalFactor ::= ["NOT"] ConditionalPrimary - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ConditionalFactor extends Node -{ - /** - * @var bool - */ - public $not = false; - - /** - * @var ConditionalPrimary - */ - public $conditionalPrimary; - - /** - * @param ConditionalPrimary $conditionalPrimary - */ - public function __construct($conditionalPrimary) - { - $this->conditionalPrimary = $conditionalPrimary; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkConditionalFactor($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalPrimary.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalPrimary.php deleted file mode 100644 index 1eed41d..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalPrimary.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")" - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ConditionalPrimary extends Node -{ - /** - * @var Node|null - */ - public $simpleConditionalExpression; - - /** - * @var ConditionalExpression|null - */ - public $conditionalExpression; - - /** - * @return bool - */ - public function isSimpleConditionalExpression() - { - return (bool) $this->simpleConditionalExpression; - } - - /** - * @return bool - */ - public function isConditionalExpression() - { - return (bool) $this->conditionalExpression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkConditionalPrimary($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalTerm.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalTerm.php deleted file mode 100644 index 7122c9c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ConditionalTerm.php +++ /dev/null @@ -1,52 +0,0 @@ -. - */ -namespace Doctrine\ORM\Query\AST; - -/** - * ConditionalTerm ::= ConditionalFactor {"AND" ConditionalFactor}* - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ConditionalTerm extends Node -{ - /** - * @var array - */ - public $conditionalFactors = []; - - /** - * @param array $conditionalFactors - */ - public function __construct(array $conditionalFactors) - { - $this->conditionalFactors = $conditionalFactors; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkConditionalTerm($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteClause.php deleted file mode 100644 index 8ca35c6..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteClause.php +++ /dev/null @@ -1,58 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * DeleteClause ::= "DELETE" ["FROM"] AbstractSchemaName [["AS"] AliasIdentificationVariable] - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class DeleteClause extends Node -{ - /** - * @var string - */ - public $abstractSchemaName; - - /** - * @var string - */ - public $aliasIdentificationVariable; - - /** - * @param string $abstractSchemaName - */ - public function __construct($abstractSchemaName) - { - $this->abstractSchemaName = $abstractSchemaName; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkDeleteClause($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteStatement.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteStatement.php deleted file mode 100644 index da6859b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/DeleteStatement.php +++ /dev/null @@ -1,58 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * DeleteStatement = DeleteClause [WhereClause] - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class DeleteStatement extends Node -{ - /** - * @var DeleteClause - */ - public $deleteClause; - - /** - * @var WhereClause|null - */ - public $whereClause; - - /** - * @param DeleteClause $deleteClause - */ - public function __construct($deleteClause) - { - $this->deleteClause = $deleteClause; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkDeleteStatement($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/EmptyCollectionComparisonExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/EmptyCollectionComparisonExpression.php deleted file mode 100644 index bd978af..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/EmptyCollectionComparisonExpression.php +++ /dev/null @@ -1,58 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * EmptyCollectionComparisonExpression ::= CollectionValuedPathExpression "IS" ["NOT"] "EMPTY" - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class EmptyCollectionComparisonExpression extends Node -{ - /** - * @var PathExpression - */ - public $expression; - - /** - * @var bool - */ - public $not; - - /** - * @param PathExpression $expression - */ - public function __construct($expression) - { - $this->expression = $expression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkEmptyCollectionComparisonExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ExistsExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ExistsExpression.php deleted file mode 100644 index c53a107..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ExistsExpression.php +++ /dev/null @@ -1,58 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * ExistsExpression ::= ["NOT"] "EXISTS" "(" Subselect ")" - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ExistsExpression extends Node -{ - /** - * @var bool - */ - public $not; - - /** - * @var Subselect - */ - public $subselect; - - /** - * @param Subselect $subselect - */ - public function __construct($subselect) - { - $this->subselect = $subselect; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkExistsExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/FromClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/FromClause.php deleted file mode 100644 index fdb61ca..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/FromClause.php +++ /dev/null @@ -1,54 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration} - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class FromClause extends Node -{ - /** - * @var array - */ - public $identificationVariableDeclarations = []; - - /** - * @param array $identificationVariableDeclarations - */ - public function __construct(array $identificationVariableDeclarations) - { - $this->identificationVariableDeclarations = $identificationVariableDeclarations; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkFromClause($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AbsFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AbsFunction.php deleted file mode 100644 index 4c61435..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AbsFunction.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "ABS" "(" SimpleArithmeticExpression ")" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class AbsFunction extends FunctionNode -{ - /** - * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression - */ - public $simpleArithmeticExpression; - - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - return 'ABS(' . $sqlWalker->walkSimpleArithmeticExpression( - $this->simpleArithmeticExpression - ) . ')'; - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AvgFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AvgFunction.php deleted file mode 100644 index 6cb8d92..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/AvgFunction.php +++ /dev/null @@ -1,54 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Parser; -use Doctrine\ORM\Query\SqlWalker; -use Doctrine\ORM\Query\AST\AggregateExpression; - -/** - * "AVG" "(" ["DISTINCT"] StringPrimary ")" - * - * @since 2.6 - * @author Mathew Davies - */ -final class AvgFunction extends FunctionNode -{ - /** - * @var AggregateExpression - */ - private $aggregateExpression; - - /** - * @inheritDoc - */ - public function getSql(SqlWalker $sqlWalker): string - { - return $this->aggregateExpression->dispatch($sqlWalker); - } - - /** - * @inheritDoc - */ - public function parse(Parser $parser): void - { - $this->aggregateExpression = $parser->AggregateExpression(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitAndFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitAndFunction.php deleted file mode 100644 index 469a4b0..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitAndFunction.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "BIT_AND" "(" ArithmeticPrimary "," ArithmeticPrimary ")" - * - * - * @link www.doctrine-project.org - * @since 2.2 - * @author Fabio B. Silva - */ -class BitAndFunction extends FunctionNode -{ - public $firstArithmetic; - public $secondArithmetic; - - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - $platform = $sqlWalker->getConnection()->getDatabasePlatform(); - - return $platform->getBitAndComparisonExpression( - $this->firstArithmetic->dispatch($sqlWalker), - $this->secondArithmetic->dispatch($sqlWalker) - ); - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->firstArithmetic = $parser->ArithmeticPrimary(); - $parser->match(Lexer::T_COMMA); - $this->secondArithmetic = $parser->ArithmeticPrimary(); - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitOrFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitOrFunction.php deleted file mode 100644 index d3a3efc..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/BitOrFunction.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "BIT_OR" "(" ArithmeticPrimary "," ArithmeticPrimary ")" - * - * - * @link www.doctrine-project.org - * @since 2.2 - * @author Fabio B. Silva - */ -class BitOrFunction extends FunctionNode -{ - public $firstArithmetic; - public $secondArithmetic; - - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - $platform = $sqlWalker->getConnection()->getDatabasePlatform(); - - return $platform->getBitOrComparisonExpression( - $this->firstArithmetic->dispatch($sqlWalker), - $this->secondArithmetic->dispatch($sqlWalker) - ); - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->firstArithmetic = $parser->ArithmeticPrimary(); - $parser->match(Lexer::T_COMMA); - $this->secondArithmetic = $parser->ArithmeticPrimary(); - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php deleted file mode 100644 index b7c5ae1..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ConcatFunction.php +++ /dev/null @@ -1,85 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "CONCAT" "(" StringPrimary "," StringPrimary {"," StringPrimary }* ")" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class ConcatFunction extends FunctionNode -{ - public $firstStringPrimary; - - public $secondStringPrimary; - - public $concatExpressions = []; - - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - $platform = $sqlWalker->getConnection()->getDatabasePlatform(); - - $args = []; - - foreach ($this->concatExpressions as $expression) { - $args[] = $sqlWalker->walkStringPrimary($expression); - } - - return call_user_func_array([$platform,'getConcatExpression'], $args); - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->firstStringPrimary = $parser->StringPrimary(); - $this->concatExpressions[] = $this->firstStringPrimary; - - $parser->match(Lexer::T_COMMA); - - $this->secondStringPrimary = $parser->StringPrimary(); - $this->concatExpressions[] = $this->secondStringPrimary; - - while ($parser->getLexer()->isNextToken(Lexer::T_COMMA)) { - $parser->match(Lexer::T_COMMA); - $this->concatExpressions[] = $parser->StringPrimary(); - } - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} - diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CountFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CountFunction.php deleted file mode 100644 index f232cf4..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CountFunction.php +++ /dev/null @@ -1,54 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Parser; -use Doctrine\ORM\Query\SqlWalker; -use Doctrine\ORM\Query\AST\AggregateExpression; - -/** - * "COUNT" "(" ["DISTINCT"] StringPrimary ")" - * - * @since 2.6 - * @author Mathew Davies - */ -final class CountFunction extends FunctionNode -{ - /** - * @var AggregateExpression - */ - private $aggregateExpression; - - /** - * @inheritDoc - */ - public function getSql(SqlWalker $sqlWalker): string - { - return $this->aggregateExpression->dispatch($sqlWalker); - } - - /** - * @inheritDoc - */ - public function parse(Parser $parser): void - { - $this->aggregateExpression = $parser->AggregateExpression(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentDateFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentDateFunction.php deleted file mode 100644 index 565b875..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentDateFunction.php +++ /dev/null @@ -1,56 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "CURRENT_DATE" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class CurrentDateFunction extends FunctionNode -{ - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - return $sqlWalker->getConnection()->getDatabasePlatform()->getCurrentDateSQL(); - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimeFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimeFunction.php deleted file mode 100644 index ec9ceb7..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimeFunction.php +++ /dev/null @@ -1,56 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "CURRENT_TIME" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class CurrentTimeFunction extends FunctionNode -{ - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - return $sqlWalker->getConnection()->getDatabasePlatform()->getCurrentTimeSQL(); - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimestampFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimestampFunction.php deleted file mode 100644 index 4203072..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/CurrentTimestampFunction.php +++ /dev/null @@ -1,56 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "CURRENT_TIMESTAMP" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class CurrentTimestampFunction extends FunctionNode -{ - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - return $sqlWalker->getConnection()->getDatabasePlatform()->getCurrentTimestampSQL(); - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php deleted file mode 100644 index edec7f9..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateAddFunction.php +++ /dev/null @@ -1,109 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; -use Doctrine\ORM\Query\SqlWalker; -use Doctrine\ORM\Query\Parser; -use Doctrine\ORM\Query\QueryException; - -/** - * "DATE_ADD" "(" ArithmeticPrimary "," ArithmeticPrimary "," StringPrimary ")" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Benjamin Eberlei - */ -class DateAddFunction extends FunctionNode -{ - public $firstDateExpression = null; - public $intervalExpression = null; - public $unit = null; - - /** - * @override - * @inheritdoc - */ - public function getSql(SqlWalker $sqlWalker) - { - switch (strtolower($this->unit->value)) { - case 'second': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddSecondsExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - case 'minute': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddMinutesExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - case 'hour': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddHourExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - case 'day': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddDaysExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - case 'week': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddWeeksExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - case 'month': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddMonthExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - case 'year': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddYearsExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - - default: - throw QueryException::semanticalError( - 'DATE_ADD() only supports units of type second, minute, hour, day, week, month and year.' - ); - } - } - - /** - * @override - * @inheritdoc - */ - public function parse(Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->firstDateExpression = $parser->ArithmeticPrimary(); - $parser->match(Lexer::T_COMMA); - $this->intervalExpression = $parser->ArithmeticPrimary(); - $parser->match(Lexer::T_COMMA); - $this->unit = $parser->StringPrimary(); - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateDiffFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateDiffFunction.php deleted file mode 100644 index 5372482..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateDiffFunction.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; -use Doctrine\ORM\Query\SqlWalker; -use Doctrine\ORM\Query\Parser; - -/** - * "DATE_DIFF" "(" ArithmeticPrimary "," ArithmeticPrimary ")" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - */ -class DateDiffFunction extends FunctionNode -{ - public $date1; - public $date2; - - /** - * @override - * @inheritdoc - */ - public function getSql(SqlWalker $sqlWalker) - { - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateDiffExpression( - $this->date1->dispatch($sqlWalker), - $this->date2->dispatch($sqlWalker) - ); - } - - /** - * @override - * @inheritdoc - */ - public function parse(Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->date1 = $parser->ArithmeticPrimary(); - $parser->match(Lexer::T_COMMA); - $this->date2 = $parser->ArithmeticPrimary(); - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php deleted file mode 100644 index 8dcc135..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/DateSubFunction.php +++ /dev/null @@ -1,85 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\SqlWalker; -use Doctrine\ORM\Query\QueryException; - -/** - * "DATE_ADD(date1, interval, unit)" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Benjamin Eberlei - */ -class DateSubFunction extends DateAddFunction -{ - /** - * @override - * @inheritdoc - */ - public function getSql(SqlWalker $sqlWalker) - { - switch (strtolower($this->unit->value)) { - case 'second': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubSecondsExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - case 'minute': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubMinutesExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - case 'hour': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubHourExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - case 'day': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubDaysExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - case 'week': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubWeeksExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - case 'month': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubMonthExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - case 'year': - return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubYearsExpression( - $this->firstDateExpression->dispatch($sqlWalker), - $this->intervalExpression->dispatch($sqlWalker) - ); - - default: - throw QueryException::semanticalError( - 'DATE_SUB() only supports units of type second, minute, hour, day, week, month and year.' - ); - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/FunctionNode.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/FunctionNode.php deleted file mode 100644 index 2f33c9d..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/FunctionNode.php +++ /dev/null @@ -1,73 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\AST\Node; - -/** - * Abstract Function Node. - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -abstract class FunctionNode extends Node -{ - /** - * @var string - */ - public $name; - - /** - * @param string $name - */ - public function __construct($name) - { - $this->name = $name; - } - - /** - * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker - * - * @return string - */ - abstract public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker); - - /** - * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker - * - * @return string - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkFunction($this); - } - - /** - * @param \Doctrine\ORM\Query\Parser $parser - * - * @return void - */ - abstract public function parse(\Doctrine\ORM\Query\Parser $parser); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/IdentityFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/IdentityFunction.php deleted file mode 100644 index 6f69d53..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/IdentityFunction.php +++ /dev/null @@ -1,113 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; -use Doctrine\ORM\Query\Parser; -use Doctrine\ORM\Query\SqlWalker; -use Doctrine\ORM\Query\QueryException; - -/** - * "IDENTITY" "(" SingleValuedAssociationPathExpression {"," string} ")" - * - * - * @link www.doctrine-project.org - * @since 2.2 - * @author Guilherme Blanco - * @author Benjamin Eberlei - */ -class IdentityFunction extends FunctionNode -{ - /** - * @var \Doctrine\ORM\Query\AST\PathExpression - */ - public $pathExpression; - - /** - * @var string - */ - public $fieldMapping; - - /** - * {@inheritdoc} - */ - public function getSql(SqlWalker $sqlWalker) - { - $platform = $sqlWalker->getEntityManager()->getConnection()->getDatabasePlatform(); - $quoteStrategy = $sqlWalker->getEntityManager()->getConfiguration()->getQuoteStrategy(); - $dqlAlias = $this->pathExpression->identificationVariable; - $assocField = $this->pathExpression->field; - $qComp = $sqlWalker->getQueryComponent($dqlAlias); - $class = $qComp['metadata']; - $assoc = $class->associationMappings[$assocField]; - $targetEntity = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']); - $joinColumn = reset($assoc['joinColumns']); - - if ($this->fieldMapping !== null) { - if ( ! isset($targetEntity->fieldMappings[$this->fieldMapping])) { - throw new QueryException(sprintf('Undefined reference field mapping "%s"', $this->fieldMapping)); - } - - $field = $targetEntity->fieldMappings[$this->fieldMapping]; - $joinColumn = null; - - foreach ($assoc['joinColumns'] as $mapping) { - - if ($mapping['referencedColumnName'] === $field['columnName']) { - $joinColumn = $mapping; - - break; - } - } - - if ($joinColumn === null) { - throw new QueryException(sprintf('Unable to resolve the reference field mapping "%s"', $this->fieldMapping)); - } - } - - // The table with the relation may be a subclass, so get the table name from the association definition - $tableName = $sqlWalker->getEntityManager()->getClassMetadata($assoc['sourceEntity'])->getTableName(); - - $tableAlias = $sqlWalker->getSQLTableAlias($tableName, $dqlAlias); - $columnName = $quoteStrategy->getJoinColumnName($joinColumn, $targetEntity, $platform); - - return $tableAlias . '.' . $columnName; - } - - /** - * {@inheritdoc} - */ - public function parse(Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->pathExpression = $parser->SingleValuedAssociationPathExpression(); - - if ($parser->getLexer()->isNextToken(Lexer::T_COMMA)) { - $parser->match(Lexer::T_COMMA); - $parser->match(Lexer::T_STRING); - - $this->fieldMapping = $parser->getLexer()->token['value']; - } - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LengthFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LengthFunction.php deleted file mode 100644 index 3d2b1a6..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LengthFunction.php +++ /dev/null @@ -1,63 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "LENGTH" "(" StringPrimary ")" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class LengthFunction extends FunctionNode -{ - public $stringPrimary; - - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - return $sqlWalker->getConnection()->getDatabasePlatform()->getLengthExpression( - $sqlWalker->walkSimpleArithmeticExpression($this->stringPrimary) - ); - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->stringPrimary = $parser->StringPrimary(); - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LocateFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LocateFunction.php deleted file mode 100644 index 473aa34..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LocateFunction.php +++ /dev/null @@ -1,86 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class LocateFunction extends FunctionNode -{ - public $firstStringPrimary; - public $secondStringPrimary; - - /** - * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression|bool - */ - public $simpleArithmeticExpression = false; - - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - - return $sqlWalker->getConnection()->getDatabasePlatform()->getLocateExpression( - $sqlWalker->walkStringPrimary($this->secondStringPrimary), // its the other way around in platform - $sqlWalker->walkStringPrimary($this->firstStringPrimary), - (($this->simpleArithmeticExpression) - ? $sqlWalker->walkSimpleArithmeticExpression($this->simpleArithmeticExpression) - : false - ) - ); - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->firstStringPrimary = $parser->StringPrimary(); - - $parser->match(Lexer::T_COMMA); - - $this->secondStringPrimary = $parser->StringPrimary(); - - $lexer = $parser->getLexer(); - if ($lexer->isNextToken(Lexer::T_COMMA)) { - $parser->match(Lexer::T_COMMA); - - $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - } - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php deleted file mode 100644 index 5f0fb95..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/LowerFunction.php +++ /dev/null @@ -1,63 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "LOWER" "(" StringPrimary ")" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class LowerFunction extends FunctionNode -{ - public $stringPrimary; - - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - return $sqlWalker->getConnection()->getDatabasePlatform()->getLowerExpression( - $sqlWalker->walkSimpleArithmeticExpression($this->stringPrimary) - ); - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->stringPrimary = $parser->StringPrimary(); - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MaxFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MaxFunction.php deleted file mode 100644 index eba9b86..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MaxFunction.php +++ /dev/null @@ -1,54 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Parser; -use Doctrine\ORM\Query\SqlWalker; -use Doctrine\ORM\Query\AST\AggregateExpression; - -/** - * "MAX" "(" ["DISTINCT"] StringPrimary ")" - * - * @since 2.6 - * @author Mathew Davies - */ -final class MaxFunction extends FunctionNode -{ - /** - * @var AggregateExpression - */ - private $aggregateExpression; - - /** - * @inheritDoc - */ - public function getSql(SqlWalker $sqlWalker): string - { - return $this->aggregateExpression->dispatch($sqlWalker); - } - - /** - * @inheritDoc - */ - public function parse(Parser $parser): void - { - $this->aggregateExpression = $parser->AggregateExpression(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MinFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MinFunction.php deleted file mode 100644 index e1c0869..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/MinFunction.php +++ /dev/null @@ -1,54 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Parser; -use Doctrine\ORM\Query\SqlWalker; -use Doctrine\ORM\Query\AST\AggregateExpression; - -/** - * "MIN" "(" ["DISTINCT"] StringPrimary ")" - * - * @since 2.6 - * @author Mathew Davies - */ -final class MinFunction extends FunctionNode -{ - /** - * @var AggregateExpression - */ - private $aggregateExpression; - - /** - * @inheritDoc - */ - public function getSql(SqlWalker $sqlWalker): string - { - return $this->aggregateExpression->dispatch($sqlWalker); - } - - /** - * @inheritDoc - */ - public function parse(Parser $parser): void - { - $this->aggregateExpression = $parser->AggregateExpression(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ModFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ModFunction.php deleted file mode 100644 index 61bc9a7..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/ModFunction.php +++ /dev/null @@ -1,76 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class ModFunction extends FunctionNode -{ - /** - * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression - */ - public $firstSimpleArithmeticExpression; - - /** - * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression - */ - public $secondSimpleArithmeticExpression; - - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - return $sqlWalker->getConnection()->getDatabasePlatform()->getModExpression( - $sqlWalker->walkSimpleArithmeticExpression($this->firstSimpleArithmeticExpression), - $sqlWalker->walkSimpleArithmeticExpression($this->secondSimpleArithmeticExpression) - ); - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->firstSimpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - - $parser->match(Lexer::T_COMMA); - - $this->secondSimpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php deleted file mode 100644 index bf0f7a4..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SizeFunction.php +++ /dev/null @@ -1,125 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "SIZE" "(" CollectionValuedPathExpression ")" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class SizeFunction extends FunctionNode -{ - /** - * @var \Doctrine\ORM\Query\AST\PathExpression - */ - public $collectionPathExpression; - - /** - * @override - * @inheritdoc - * @todo If the collection being counted is already joined, the SQL can be simpler (more efficient). - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - $platform = $sqlWalker->getEntityManager()->getConnection()->getDatabasePlatform(); - $quoteStrategy = $sqlWalker->getEntityManager()->getConfiguration()->getQuoteStrategy(); - $dqlAlias = $this->collectionPathExpression->identificationVariable; - $assocField = $this->collectionPathExpression->field; - - $qComp = $sqlWalker->getQueryComponent($dqlAlias); - $class = $qComp['metadata']; - $assoc = $class->associationMappings[$assocField]; - $sql = 'SELECT COUNT(*) FROM '; - - if ($assoc['type'] == \Doctrine\ORM\Mapping\ClassMetadata::ONE_TO_MANY) { - $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']); - $targetTableAlias = $sqlWalker->getSQLTableAlias($targetClass->getTableName()); - $sourceTableAlias = $sqlWalker->getSQLTableAlias($class->getTableName(), $dqlAlias); - - $sql .= $quoteStrategy->getTableName($targetClass, $platform) . ' ' . $targetTableAlias . ' WHERE '; - - $owningAssoc = $targetClass->associationMappings[$assoc['mappedBy']]; - - $first = true; - - foreach ($owningAssoc['targetToSourceKeyColumns'] as $targetColumn => $sourceColumn) { - if ($first) $first = false; else $sql .= ' AND '; - - $sql .= $targetTableAlias . '.' . $sourceColumn - . ' = ' - . $sourceTableAlias . '.' . $quoteStrategy->getColumnName($class->fieldNames[$targetColumn], $class, $platform); - } - } else { // many-to-many - $targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']); - - $owningAssoc = $assoc['isOwningSide'] ? $assoc : $targetClass->associationMappings[$assoc['mappedBy']]; - $joinTable = $owningAssoc['joinTable']; - - // SQL table aliases - $joinTableAlias = $sqlWalker->getSQLTableAlias($joinTable['name']); - $sourceTableAlias = $sqlWalker->getSQLTableAlias($class->getTableName(), $dqlAlias); - - // join to target table - $sql .= $quoteStrategy->getJoinTableName($owningAssoc, $targetClass, $platform) . ' ' . $joinTableAlias . ' WHERE '; - - $joinColumns = $assoc['isOwningSide'] - ? $joinTable['joinColumns'] - : $joinTable['inverseJoinColumns']; - - $first = true; - - foreach ($joinColumns as $joinColumn) { - if ($first) $first = false; else $sql .= ' AND '; - - $sourceColumnName = $quoteStrategy->getColumnName( - $class->fieldNames[$joinColumn['referencedColumnName']], $class, $platform - ); - - $sql .= $joinTableAlias . '.' . $joinColumn['name'] - . ' = ' - . $sourceTableAlias . '.' . $sourceColumnName; - } - } - - return '(' . $sql . ')'; - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->collectionPathExpression = $parser->CollectionValuedPathExpression(); - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SqrtFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SqrtFunction.php deleted file mode 100644 index 08155d2..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SqrtFunction.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "SQRT" "(" SimpleArithmeticExpression ")" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class SqrtFunction extends FunctionNode -{ - /** - * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression - */ - public $simpleArithmeticExpression; - - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - return $sqlWalker->getConnection()->getDatabasePlatform()->getSqrtExpression( - $sqlWalker->walkSimpleArithmeticExpression($this->simpleArithmeticExpression) - ); - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php deleted file mode 100644 index a6a80f8..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SubstringFunction.php +++ /dev/null @@ -1,91 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class SubstringFunction extends FunctionNode -{ - public $stringPrimary; - - /** - * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression - */ - public $firstSimpleArithmeticExpression; - - /** - * @var \Doctrine\ORM\Query\AST\SimpleArithmeticExpression|null - */ - public $secondSimpleArithmeticExpression = null; - - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - $optionalSecondSimpleArithmeticExpression = null; - if ($this->secondSimpleArithmeticExpression !== null) { - $optionalSecondSimpleArithmeticExpression = $sqlWalker->walkSimpleArithmeticExpression($this->secondSimpleArithmeticExpression); - } - - return $sqlWalker->getConnection()->getDatabasePlatform()->getSubstringExpression( - $sqlWalker->walkStringPrimary($this->stringPrimary), - $sqlWalker->walkSimpleArithmeticExpression($this->firstSimpleArithmeticExpression), - $optionalSecondSimpleArithmeticExpression - ); - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->stringPrimary = $parser->StringPrimary(); - - $parser->match(Lexer::T_COMMA); - - $this->firstSimpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - - $lexer = $parser->getLexer(); - if ($lexer->isNextToken(Lexer::T_COMMA)) { - $parser->match(Lexer::T_COMMA); - - $this->secondSimpleArithmeticExpression = $parser->SimpleArithmeticExpression(); - } - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SumFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SumFunction.php deleted file mode 100644 index c9fcf7b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/SumFunction.php +++ /dev/null @@ -1,54 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Parser; -use Doctrine\ORM\Query\SqlWalker; -use Doctrine\ORM\Query\AST\AggregateExpression; - -/** - * "SUM" "(" ["DISTINCT"] StringPrimary ")" - * - * @since 2.6 - * @author Mathew Davies - */ -final class SumFunction extends FunctionNode -{ - /** - * @var AggregateExpression - */ - private $aggregateExpression; - - /** - * @inheritDoc - */ - public function getSql(SqlWalker $sqlWalker): string - { - return $this->aggregateExpression->dispatch($sqlWalker); - } - - /** - * @inheritDoc - */ - public function parse(Parser $parser): void - { - $this->aggregateExpression = $parser->AggregateExpression(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php deleted file mode 100644 index 9e748c3..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/TrimFunction.php +++ /dev/null @@ -1,161 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; -use Doctrine\ORM\Query\Parser; -use Doctrine\ORM\Query\SqlWalker; -use Doctrine\DBAL\Platforms\AbstractPlatform; - -/** - * "TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class TrimFunction extends FunctionNode -{ - /** - * @var boolean - */ - public $leading; - - /** - * @var boolean - */ - public $trailing; - - /** - * @var boolean - */ - public $both; - - /** - * @var boolean - */ - public $trimChar = false; - - /** - * @var \Doctrine\ORM\Query\AST\Node - */ - public $stringPrimary; - - /** - * {@inheritdoc} - */ - public function getSql(SqlWalker $sqlWalker) - { - $stringPrimary = $sqlWalker->walkStringPrimary($this->stringPrimary); - $platform = $sqlWalker->getConnection()->getDatabasePlatform(); - $trimMode = $this->getTrimMode(); - $trimChar = ($this->trimChar !== false) - ? $sqlWalker->getConnection()->quote($this->trimChar) - : false; - - return $platform->getTrimExpression($stringPrimary, $trimMode, $trimChar); - } - - /** - * {@inheritdoc} - */ - public function parse(Parser $parser) - { - $lexer = $parser->getLexer(); - - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->parseTrimMode($parser); - - if ($lexer->isNextToken(Lexer::T_STRING)) { - $parser->match(Lexer::T_STRING); - - $this->trimChar = $lexer->token['value']; - } - - if ($this->leading || $this->trailing || $this->both || $this->trimChar) { - $parser->match(Lexer::T_FROM); - } - - $this->stringPrimary = $parser->StringPrimary(); - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } - - /** - * @return integer - */ - private function getTrimMode() - { - if ($this->leading) { - return AbstractPlatform::TRIM_LEADING; - } - - if ($this->trailing) { - return AbstractPlatform::TRIM_TRAILING; - } - - if ($this->both) { - return AbstractPlatform::TRIM_BOTH; - } - - return AbstractPlatform::TRIM_UNSPECIFIED; - } - - /** - * @param \Doctrine\ORM\Query\Parser $parser - * - * @return void - */ - private function parseTrimMode(Parser $parser) - { - $lexer = $parser->getLexer(); - $value = $lexer->lookahead['value']; - - if (strcasecmp('leading', $value) === 0) { - $parser->match(Lexer::T_LEADING); - - $this->leading = true; - - return; - } - - if (strcasecmp('trailing', $value) === 0) { - $parser->match(Lexer::T_TRAILING); - - $this->trailing = true; - - return; - } - - if (strcasecmp('both', $value) === 0) { - $parser->match(Lexer::T_BOTH); - - $this->both = true; - - return; - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php deleted file mode 100644 index 28e0f16..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Functions/UpperFunction.php +++ /dev/null @@ -1,63 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST\Functions; - -use Doctrine\ORM\Query\Lexer; - -/** - * "UPPER" "(" StringPrimary ")" - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class UpperFunction extends FunctionNode -{ - public $stringPrimary; - - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - return $sqlWalker->getConnection()->getDatabasePlatform()->getUpperExpression( - $sqlWalker->walkSimpleArithmeticExpression($this->stringPrimary) - ); - } - - /** - * @override - * @inheritdoc - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - $parser->match(Lexer::T_IDENTIFIER); - $parser->match(Lexer::T_OPEN_PARENTHESIS); - - $this->stringPrimary = $parser->StringPrimary(); - - $parser->match(Lexer::T_CLOSE_PARENTHESIS); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GeneralCaseExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GeneralCaseExpression.php deleted file mode 100644 index e7937d6..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GeneralCaseExpression.php +++ /dev/null @@ -1,62 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * GeneralCaseExpression ::= "CASE" WhenClause {WhenClause}* "ELSE" ScalarExpression "END" - * - * @since 2.2 - * - * @link www.doctrine-project.org - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class GeneralCaseExpression extends Node -{ - /** - * @var array - */ - public $whenClauses = []; - - /** - * @var mixed - */ - public $elseScalarExpression = null; - - /** - * @param array $whenClauses - * @param mixed $elseScalarExpression - */ - public function __construct(array $whenClauses, $elseScalarExpression) - { - $this->whenClauses = $whenClauses; - $this->elseScalarExpression = $elseScalarExpression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkGeneralCaseExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GroupByClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GroupByClause.php deleted file mode 100644 index 687512a..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/GroupByClause.php +++ /dev/null @@ -1,53 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * Description of GroupByClause. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class GroupByClause extends Node -{ - /** - * @var array - */ - public $groupByItems = []; - - /** - * @param array $groupByItems - */ - public function __construct(array $groupByItems) - { - $this->groupByItems = $groupByItems; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkGroupByClause($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/HavingClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/HavingClause.php deleted file mode 100644 index 1d369ff..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/HavingClause.php +++ /dev/null @@ -1,53 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * Description of HavingClause. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class HavingClause extends Node -{ - /** - * @var ConditionalExpression - */ - public $conditionalExpression; - - /** - * @param ConditionalExpression $conditionalExpression - */ - public function __construct($conditionalExpression) - { - $this->conditionalExpression = $conditionalExpression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkHavingClause($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IdentificationVariableDeclaration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IdentificationVariableDeclaration.php deleted file mode 100644 index 2e2032c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IdentificationVariableDeclaration.php +++ /dev/null @@ -1,67 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {JoinVariableDeclaration}* - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class IdentificationVariableDeclaration extends Node -{ - /** - * @var RangeVariableDeclaration|null - */ - public $rangeVariableDeclaration = null; - - /** - * @var IndexBy|null - */ - public $indexBy = null; - - /** - * @var array - */ - public $joins = []; - - /** - * @param RangeVariableDeclaration|null $rangeVariableDecl - * @param IndexBy|null $indexBy - * @param array $joins - */ - public function __construct($rangeVariableDecl, $indexBy, array $joins) - { - $this->rangeVariableDeclaration = $rangeVariableDecl; - $this->indexBy = $indexBy; - $this->joins = $joins; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkIdentificationVariableDeclaration($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InExpression.php deleted file mode 100644 index 64ef134..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InExpression.php +++ /dev/null @@ -1,67 +0,0 @@ -. - */ -namespace Doctrine\ORM\Query\AST; - -/** - * InExpression ::= StateFieldPathExpression ["NOT"] "IN" "(" (Literal {"," Literal}* | Subselect) ")" - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class InExpression extends Node -{ - /** - * @var bool - */ - public $not; - - /** - * @var ArithmeticExpression - */ - public $expression; - - /** - * @var array - */ - public $literals = []; - - /** - * @var Subselect|null - */ - public $subselect; - - /** - * @param ArithmeticExpression $expression - */ - public function __construct($expression) - { - $this->expression = $expression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkInExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IndexBy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IndexBy.php deleted file mode 100644 index c7874b7..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/IndexBy.php +++ /dev/null @@ -1,53 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * IndexBy ::= "INDEX" "BY" SimpleStateFieldPathExpression - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class IndexBy extends Node -{ - /** - * @var PathExpression - */ - public $simpleStateFieldPathExpression = null; - - /** - * @param PathExpression $simpleStateFieldPathExpression - */ - public function __construct($simpleStateFieldPathExpression) - { - $this->simpleStateFieldPathExpression = $simpleStateFieldPathExpression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkIndexBy($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InputParameter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InputParameter.php deleted file mode 100644 index 4da550f..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InputParameter.php +++ /dev/null @@ -1,66 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * Description of InputParameter. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class InputParameter extends Node -{ - /** - * @var bool - */ - public $isNamed; - - /** - * @var string - */ - public $name; - - /** - * @param string $value - * - * @throws \Doctrine\ORM\Query\QueryException - */ - public function __construct($value) - { - if (strlen($value) === 1) { - throw \Doctrine\ORM\Query\QueryException::invalidParameterFormat($value); - } - - $param = substr($value, 1); - $this->isNamed = ! is_numeric($param); - $this->name = $param; - } - - /** - * {@inheritdoc} - */ - public function dispatch($walker) - { - return $walker->walkInputParameter($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InstanceOfExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InstanceOfExpression.php deleted file mode 100644 index c1fd65b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/InstanceOfExpression.php +++ /dev/null @@ -1,64 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (InstanceOfParameter | "(" InstanceOfParameter {"," InstanceOfParameter}* ")") - * InstanceOfParameter ::= AbstractSchemaName | InputParameter - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class InstanceOfExpression extends Node -{ - /** - * @var bool - */ - public $not; - - /** - * @var string - */ - public $identificationVariable; - - /** - * @var array - */ - public $value; - - /** - * @param string $identVariable - */ - public function __construct($identVariable) - { - $this->identificationVariable = $identVariable; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkInstanceOfExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Join.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Join.php deleted file mode 100644 index 5c203aa..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Join.php +++ /dev/null @@ -1,70 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" JoinAssociationPathExpression - * ["AS"] AliasIdentificationVariable [("ON" | "WITH") ConditionalExpression] - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Join extends Node -{ - const JOIN_TYPE_LEFT = 1; - const JOIN_TYPE_LEFTOUTER = 2; - const JOIN_TYPE_INNER = 3; - - /** - * @var int - */ - public $joinType = self::JOIN_TYPE_INNER; - - /** - * @var Node|null - */ - public $joinAssociationDeclaration = null; - - /** - * @var ConditionalExpression|null - */ - public $conditionalExpression = null; - - /** - * @param int $joinType - * @param Node $joinAssociationDeclaration - */ - public function __construct($joinType, $joinAssociationDeclaration) - { - $this->joinType = $joinType; - $this->joinAssociationDeclaration = $joinAssociationDeclaration; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkJoin($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationDeclaration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationDeclaration.php deleted file mode 100644 index a33900a..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationDeclaration.php +++ /dev/null @@ -1,65 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * JoinAssociationDeclaration ::= JoinAssociationPathExpression ["AS"] AliasIdentificationVariable - * - * @link www.doctrine-project.org - * @since 2.3 - * @author Guilherme Blanco - */ -class JoinAssociationDeclaration extends Node -{ - /** - * @var JoinAssociationPathExpression - */ - public $joinAssociationPathExpression; - - /** - * @var string - */ - public $aliasIdentificationVariable; - - /** - * @var IndexBy|null - */ - public $indexBy; - - /** - * @param JoinAssociationPathExpression $joinAssociationPathExpression - * @param string $aliasIdentificationVariable - * @param IndexBy|null $indexBy - */ - public function __construct($joinAssociationPathExpression, $aliasIdentificationVariable, $indexBy) - { - $this->joinAssociationPathExpression = $joinAssociationPathExpression; - $this->aliasIdentificationVariable = $aliasIdentificationVariable; - $this->indexBy = $indexBy; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkJoinAssociationDeclaration($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationPathExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationPathExpression.php deleted file mode 100644 index 946bbb1..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinAssociationPathExpression.php +++ /dev/null @@ -1,60 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * JoinAssociationPathExpression ::= IdentificationVariable "." (SingleValuedAssociationField | CollectionValuedAssociationField) - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class JoinAssociationPathExpression extends Node -{ - /** - * @var string - */ - public $identificationVariable; - - /** - * @var string - */ - public $associationField; - - /** - * @param string $identificationVariable - * @param string $associationField - */ - public function __construct($identificationVariable, $associationField) - { - $this->identificationVariable = $identificationVariable; - $this->associationField = $associationField; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkPathExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinClassPathExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinClassPathExpression.php deleted file mode 100644 index 7e37414..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinClassPathExpression.php +++ /dev/null @@ -1,59 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * JoinClassPathExpression ::= AbstractSchemaName ["AS"] AliasIdentificationVariable - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.org - * @since 2.3 - * @author Alexander - */ -class JoinClassPathExpression extends Node -{ - /** - * @var mixed - */ - public $abstractSchemaName; - - /** - * @var mixed - */ - public $aliasIdentificationVariable; - - /** - * @param mixed $abstractSchemaName - * @param mixed $aliasIdentificationVar - */ - public function __construct($abstractSchemaName, $aliasIdentificationVar) - { - $this->abstractSchemaName = $abstractSchemaName; - $this->aliasIdentificationVariable = $aliasIdentificationVar; - } - - /** - * {@inheritdoc} - */ - public function dispatch($walker) - { - return $walker->walkJoinPathExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinVariableDeclaration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinVariableDeclaration.php deleted file mode 100644 index 89aa83a..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/JoinVariableDeclaration.php +++ /dev/null @@ -1,61 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * JoinVariableDeclaration ::= Join [IndexBy] - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.org - * @since 2.5 - * @author Guilherme Blanco - */ -class JoinVariableDeclaration extends Node -{ - /** - * @var Join - */ - public $join; - - /** - * @var IndexBy|null - */ - public $indexBy; - - /** - * Constructor. - * - * @param Join $join - * @param IndexBy|null $indexBy - */ - public function __construct($join, $indexBy) - { - $this->join = $join; - $this->indexBy = $indexBy; - } - - /** - * {@inheritdoc} - */ - public function dispatch($walker) - { - return $walker->walkJoinVariableDeclaration($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/LikeExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/LikeExpression.php deleted file mode 100644 index e320c51..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/LikeExpression.php +++ /dev/null @@ -1,71 +0,0 @@ -. - */ -namespace Doctrine\ORM\Query\AST; - -/** - * LikeExpression ::= StringExpression ["NOT"] "LIKE" string ["ESCAPE" char] - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class LikeExpression extends Node -{ - /** - * @var bool - */ - public $not; - - /** - * @var Node - */ - public $stringExpression; - - /** - * @var InputParameter - */ - public $stringPattern; - - /** - * @var Literal|null - */ - public $escapeChar; - - /** - * @param Node $stringExpression - * @param InputParameter $stringPattern - * @param Literal|null $escapeChar - */ - public function __construct($stringExpression, $stringPattern, $escapeChar = null) - { - $this->stringExpression = $stringExpression; - $this->stringPattern = $stringPattern; - $this->escapeChar = $escapeChar; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkLikeExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Literal.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Literal.php deleted file mode 100644 index 43d71ad..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Literal.php +++ /dev/null @@ -1,55 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -class Literal extends Node -{ - const STRING = 1; - const BOOLEAN = 2; - const NUMERIC = 3; - - /** - * @var int - */ - public $type; - - /** - * @var mixed - */ - public $value; - - /** - * @param int $type - * @param mixed $value - */ - public function __construct($type, $value) - { - $this->type = $type; - $this->value = $value; - } - - /** - * {@inheritdoc} - */ - public function dispatch($walker) - { - return $walker->walkLiteral($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NewObjectExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NewObjectExpression.php deleted file mode 100644 index ec011ce..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NewObjectExpression.php +++ /dev/null @@ -1,58 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * NewObjectExpression ::= "NEW" IdentificationVariable "(" NewObjectArg {"," NewObjectArg}* ")" - * - * @link www.doctrine-project.org - * @since 2.4 - * @author Fabio B. Silva - */ -class NewObjectExpression extends Node -{ - /** - * @var string - */ - public $className; - - /** - * @var array - */ - public $args; - - /** - * @param string $className - * @param array $args - */ - public function __construct($className, array $args) - { - $this->className = $className; - $this->args = $args; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkNewObject($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Node.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Node.php deleted file mode 100644 index a257dc2..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Node.php +++ /dev/null @@ -1,103 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * Abstract class of an AST node. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -abstract class Node -{ - /** - * Double-dispatch method, supposed to dispatch back to the walker. - * - * Implementation is not mandatory for all nodes. - * - * @param \Doctrine\ORM\Query\SqlWalker $walker - * - * @return string - * - * @throws ASTException - */ - public function dispatch($walker) - { - throw ASTException::noDispatchForNode($this); - } - - /** - * Dumps the AST Node into a string representation for information purpose only. - * - * @return string - */ - public function __toString() - { - return $this->dump($this); - } - - /** - * @param object $obj - * - * @return string - */ - public function dump($obj) - { - static $ident = 0; - - $str = ''; - - if ($obj instanceof Node) { - $str .= get_class($obj) . '(' . PHP_EOL; - $props = get_object_vars($obj); - - foreach ($props as $name => $prop) { - $ident += 4; - $str .= str_repeat(' ', $ident) . '"' . $name . '": ' - . $this->dump($prop) . ',' . PHP_EOL; - $ident -= 4; - } - - $str .= str_repeat(' ', $ident) . ')'; - } else if (is_array($obj)) { - $ident += 4; - $str .= 'array('; - $some = false; - - foreach ($obj as $k => $v) { - $str .= PHP_EOL . str_repeat(' ', $ident) . '"' - . $k . '" => ' . $this->dump($v) . ','; - $some = true; - } - - $ident -= 4; - $str .= ($some ? PHP_EOL . str_repeat(' ', $ident) : '') . ')'; - } else if (is_object($obj)) { - $str .= 'instanceof(' . get_class($obj) . ')'; - } else { - $str .= var_export($obj, true); - } - - return $str; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullComparisonExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullComparisonExpression.php deleted file mode 100644 index 84a1997..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullComparisonExpression.php +++ /dev/null @@ -1,58 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * NullComparisonExpression ::= (SingleValuedPathExpression | InputParameter) "IS" ["NOT"] "NULL" - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class NullComparisonExpression extends Node -{ - /** - * @var bool - */ - public $not; - - /** - * @var Node - */ - public $expression; - - /** - * @param Node $expression - */ - public function __construct($expression) - { - $this->expression = $expression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkNullComparisonExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullIfExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullIfExpression.php deleted file mode 100644 index e33bc72..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/NullIfExpression.php +++ /dev/null @@ -1,62 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * NullIfExpression ::= "NULLIF" "(" ScalarExpression "," ScalarExpression ")" - * - * @since 2.1 - * - * @link www.doctrine-project.org - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class NullIfExpression extends Node -{ - /** - * @var mixed - */ - public $firstExpression; - - /** - * @var mixed - */ - public $secondExpression; - - /** - * @param mixed $firstExpression - * @param mixed $secondExpression - */ - public function __construct($firstExpression, $secondExpression) - { - $this->firstExpression = $firstExpression; - $this->secondExpression = $secondExpression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkNullIfExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByClause.php deleted file mode 100644 index e0e30e9..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByClause.php +++ /dev/null @@ -1,53 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}* - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class OrderByClause extends Node -{ - /** - * @var array - */ - public $orderByItems = []; - - /** - * @param array $orderByItems - */ - public function __construct(array $orderByItems) - { - $this->orderByItems = $orderByItems; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkOrderByClause($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByItem.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByItem.php deleted file mode 100644 index bf3288a..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/OrderByItem.php +++ /dev/null @@ -1,75 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * OrderByItem ::= (ResultVariable | StateFieldPathExpression) ["ASC" | "DESC"] - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class OrderByItem extends Node -{ - /** - * @var mixed - */ - public $expression; - - /** - * @var string - */ - public $type; - - /** - * @param mixed $expression - */ - public function __construct($expression) - { - $this->expression = $expression; - } - - /** - * @return bool - */ - public function isAsc() - { - return strtoupper($this->type) == 'ASC'; - } - - /** - * @return bool - */ - public function isDesc() - { - return strtoupper($this->type) == 'DESC'; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkOrderByItem($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ParenthesisExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ParenthesisExpression.php deleted file mode 100644 index f16db0e..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/ParenthesisExpression.php +++ /dev/null @@ -1,51 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * ParenthesisExpression ::= "(" ArithmeticPrimary ")" - * - * @author Fabio B. Silva - * @since 2.4 - */ -class ParenthesisExpression extends Node -{ - /** - * @var \Doctrine\ORM\Query\AST\Node - */ - public $expression; - - /** - * @param \Doctrine\ORM\Query\AST\Node $expression - */ - public function __construct(Node $expression) - { - $this->expression = $expression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($walker) - { - return $walker->walkParenthesisExpression($this); - } -} \ No newline at end of file diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PartialObjectExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PartialObjectExpression.php deleted file mode 100644 index e4ffe79..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PartialObjectExpression.php +++ /dev/null @@ -1,43 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -class PartialObjectExpression extends Node -{ - /** - * @var string - */ - public $identificationVariable; - - /** - * @var array - */ - public $partialFieldSet; - - /** - * @param string $identificationVariable - * @param array $partialFieldSet - */ - public function __construct($identificationVariable, array $partialFieldSet) - { - $this->identificationVariable = $identificationVariable; - $this->partialFieldSet = $partialFieldSet; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PathExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PathExpression.php deleted file mode 100644 index 37674b6..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/PathExpression.php +++ /dev/null @@ -1,81 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression - * SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression - * StateFieldPathExpression ::= SimpleStateFieldPathExpression | SimpleStateFieldAssociationPathExpression - * SingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField - * CollectionValuedPathExpression ::= IdentificationVariable "." CollectionValuedAssociationField - * StateField ::= {EmbeddedClassStateField "."}* SimpleStateField - * SimpleStateFieldPathExpression ::= IdentificationVariable "." StateField - * - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class PathExpression extends Node -{ - const TYPE_COLLECTION_VALUED_ASSOCIATION = 2; - const TYPE_SINGLE_VALUED_ASSOCIATION = 4; - const TYPE_STATE_FIELD = 8; - - /** - * @var int - */ - public $type; - - /** - * @var int - */ - public $expectedType; - - /** - * @var string - */ - public $identificationVariable; - - /** - * @var string|null - */ - public $field; - - /** - * @param int $expectedType - * @param string $identificationVariable - * @param string|null $field - */ - public function __construct($expectedType, $identificationVariable, $field = null) - { - $this->expectedType = $expectedType; - $this->identificationVariable = $identificationVariable; - $this->field = $field; - } - - /** - * {@inheritdoc} - */ - public function dispatch($walker) - { - return $walker->walkPathExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/QuantifiedExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/QuantifiedExpression.php deleted file mode 100644 index 15be952..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/QuantifiedExpression.php +++ /dev/null @@ -1,81 +0,0 @@ -. - */ -namespace Doctrine\ORM\Query\AST; - -/** - * QuantifiedExpression ::= ("ALL" | "ANY" | "SOME") "(" Subselect ")" - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class QuantifiedExpression extends Node -{ - /** - * @var string - */ - public $type; - - /** - * @var Subselect - */ - public $subselect; - - /** - * @param Subselect $subselect - */ - public function __construct($subselect) - { - $this->subselect = $subselect; - } - - /** - * @return bool - */ - public function isAll() - { - return strtoupper($this->type) == 'ALL'; - } - - /** - * @return bool - */ - public function isAny() - { - return strtoupper($this->type) == 'ANY'; - } - - /** - * @return bool - */ - public function isSome() - { - return strtoupper($this->type) == 'SOME'; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkQuantifiedExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/RangeVariableDeclaration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/RangeVariableDeclaration.php deleted file mode 100644 index 0ca5274..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/RangeVariableDeclaration.php +++ /dev/null @@ -1,67 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class RangeVariableDeclaration extends Node -{ - /** - * @var string - */ - public $abstractSchemaName; - - /** - * @var string - */ - public $aliasIdentificationVariable; - - /** - * @var boolean - */ - public $isRoot; - - /** - * @param string $abstractSchemaName - * @param string $aliasIdentificationVar - * @param boolean $isRoot - */ - public function __construct($abstractSchemaName, $aliasIdentificationVar, $isRoot = true) - { - $this->abstractSchemaName = $abstractSchemaName; - $this->aliasIdentificationVariable = $aliasIdentificationVar; - $this->isRoot = $isRoot; - } - - /** - * {@inheritdoc} - */ - public function dispatch($walker) - { - return $walker->walkRangeVariableDeclaration($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectClause.php deleted file mode 100644 index f8e6f47..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectClause.php +++ /dev/null @@ -1,60 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * SelectClause = "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression} - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class SelectClause extends Node -{ - /** - * @var bool - */ - public $isDistinct; - - /** - * @var array - */ - public $selectExpressions = []; - - /** - * @param array $selectExpressions - * @param bool $isDistinct - */ - public function __construct(array $selectExpressions, $isDistinct) - { - $this->isDistinct = $isDistinct; - $this->selectExpressions = $selectExpressions; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkSelectClause($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectExpression.php deleted file mode 100644 index 4187013..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectExpression.php +++ /dev/null @@ -1,68 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * SelectExpression ::= IdentificationVariable ["." "*"] | StateFieldPathExpression | - * (AggregateExpression | "(" Subselect ")") [["AS"] ["HIDDEN"] FieldAliasIdentificationVariable] - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class SelectExpression extends Node -{ - /** - * @var mixed - */ - public $expression; - - /** - * @var string|null - */ - public $fieldIdentificationVariable; - - /** - * @var bool - */ - public $hiddenAliasResultVariable; - - /** - * @param mixed $expression - * @param string|null $fieldIdentificationVariable - * @param bool $hiddenAliasResultVariable - */ - public function __construct($expression, $fieldIdentificationVariable, $hiddenAliasResultVariable = false) - { - $this->expression = $expression; - $this->fieldIdentificationVariable = $fieldIdentificationVariable; - $this->hiddenAliasResultVariable = $hiddenAliasResultVariable; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkSelectExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectStatement.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectStatement.php deleted file mode 100644 index d84f725..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SelectStatement.php +++ /dev/null @@ -1,80 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * SelectStatement = SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class SelectStatement extends Node -{ - /** - * @var SelectClause - */ - public $selectClause; - - /** - * @var FromClause - */ - public $fromClause; - - /** - * @var WhereClause|null - */ - public $whereClause; - - /** - * @var GroupByClause|null - */ - public $groupByClause; - - /** - * @var HavingClause|null - */ - public $havingClause; - - /** - * @var OrderByClause|null - */ - public $orderByClause; - - /** - * @param SelectClause $selectClause - * @param FromClause $fromClause - */ - public function __construct($selectClause, $fromClause) - { - $this->selectClause = $selectClause; - $this->fromClause = $fromClause; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkSelectStatement($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleArithmeticExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleArithmeticExpression.php deleted file mode 100644 index 80ecd15..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleArithmeticExpression.php +++ /dev/null @@ -1,53 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * SimpleArithmeticExpression ::= ArithmeticTerm {("+" | "-") ArithmeticTerm}* - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class SimpleArithmeticExpression extends Node -{ - /** - * @var array - */ - public $arithmeticTerms = []; - - /** - * @param array $arithmeticTerms - */ - public function __construct(array $arithmeticTerms) - { - $this->arithmeticTerms = $arithmeticTerms; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkSimpleArithmeticExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleCaseExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleCaseExpression.php deleted file mode 100644 index 67e354e..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleCaseExpression.php +++ /dev/null @@ -1,69 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * SimpleCaseExpression ::= "CASE" CaseOperand SimpleWhenClause {SimpleWhenClause}* "ELSE" ScalarExpression "END" - * - * @since 2.2 - * - * @link www.doctrine-project.org - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class SimpleCaseExpression extends Node -{ - /** - * @var PathExpression - */ - public $caseOperand = null; - - /** - * @var array - */ - public $simpleWhenClauses = []; - - /** - * @var mixed - */ - public $elseScalarExpression = null; - - /** - * @param PathExpression $caseOperand - * @param array $simpleWhenClauses - * @param mixed $elseScalarExpression - */ - public function __construct($caseOperand, array $simpleWhenClauses, $elseScalarExpression) - { - $this->caseOperand = $caseOperand; - $this->simpleWhenClauses = $simpleWhenClauses; - $this->elseScalarExpression = $elseScalarExpression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkSimpleCaseExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectClause.php deleted file mode 100644 index 92361da..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectClause.php +++ /dev/null @@ -1,60 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * SimpleSelectClause ::= "SELECT" ["DISTINCT"] SimpleSelectExpression - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class SimpleSelectClause extends Node -{ - /** - * @var bool - */ - public $isDistinct = false; - - /** - * @var SimpleSelectExpression - */ - public $simpleSelectExpression; - - /** - * @param SimpleSelectExpression $simpleSelectExpression - * @param bool $isDistinct - */ - public function __construct($simpleSelectExpression, $isDistinct) - { - $this->simpleSelectExpression = $simpleSelectExpression; - $this->isDistinct = $isDistinct; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkSimpleSelectClause($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectExpression.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectExpression.php deleted file mode 100644 index e556835..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleSelectExpression.php +++ /dev/null @@ -1,59 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * SimpleSelectExpression ::= StateFieldPathExpression | IdentificationVariable - * | (AggregateExpression [["AS"] FieldAliasIdentificationVariable]) - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class SimpleSelectExpression extends Node -{ - /** - * @var Node - */ - public $expression; - - /** - * @var string - */ - public $fieldIdentificationVariable; - - /** - * @param Node $expression - */ - public function __construct($expression) - { - $this->expression = $expression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkSimpleSelectExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleWhenClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleWhenClause.php deleted file mode 100644 index 4f60881..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SimpleWhenClause.php +++ /dev/null @@ -1,62 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * SimpleWhenClause ::= "WHEN" ScalarExpression "THEN" ScalarExpression - * - * @since 2.2 - * - * @link www.doctrine-project.org - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class SimpleWhenClause extends Node -{ - /** - * @var mixed - */ - public $caseScalarExpression = null; - - /** - * @var mixed - */ - public $thenScalarExpression = null; - - /** - * @param mixed $caseScalarExpression - * @param mixed $thenScalarExpression - */ - public function __construct($caseScalarExpression, $thenScalarExpression) - { - $this->caseScalarExpression = $caseScalarExpression; - $this->thenScalarExpression = $thenScalarExpression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkWhenClauseExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Subselect.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Subselect.php deleted file mode 100644 index ce08266..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/Subselect.php +++ /dev/null @@ -1,80 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * Subselect ::= SimpleSelectClause SubselectFromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Subselect extends Node -{ - /** - * @var SimpleSelectClause - */ - public $simpleSelectClause; - - /** - * @var SubselectFromClause - */ - public $subselectFromClause; - - /** - * @var WhereClause|null - */ - public $whereClause; - - /** - * @var GroupByClause|null - */ - public $groupByClause; - - /** - * @var HavingClause|null - */ - public $havingClause; - - /** - * @var OrderByClause|null - */ - public $orderByClause; - - /** - * @param SimpleSelectClause $simpleSelectClause - * @param SubselectFromClause $subselectFromClause - */ - public function __construct($simpleSelectClause, $subselectFromClause) - { - $this->simpleSelectClause = $simpleSelectClause; - $this->subselectFromClause = $subselectFromClause; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkSubselect($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectFromClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectFromClause.php deleted file mode 100644 index 9704061..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectFromClause.php +++ /dev/null @@ -1,53 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * SubselectFromClause ::= "FROM" SubselectIdentificationVariableDeclaration {"," SubselectIdentificationVariableDeclaration}* - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class SubselectFromClause extends Node -{ - /** - * @var array - */ - public $identificationVariableDeclarations = []; - - /** - * @param array $identificationVariableDeclarations - */ - public function __construct(array $identificationVariableDeclarations) - { - $this->identificationVariableDeclarations = $identificationVariableDeclarations; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkSubselectFromClause($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectIdentificationVariableDeclaration.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectIdentificationVariableDeclaration.php deleted file mode 100644 index 866f112..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/SubselectIdentificationVariableDeclaration.php +++ /dev/null @@ -1,52 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * SubselectIdentificationVariableDeclaration ::= AssociationPathExpression ["AS"] AliasIdentificationVariable - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - */ -class SubselectIdentificationVariableDeclaration -{ - /** - * @var PathExpression - */ - public $associationPathExpression; - - /** - * @var string - */ - public $aliasIdentificationVariable; - - /** - * Constructor. - * - * @param PathExpression $associationPathExpression - * @param string $aliasIdentificationVariable - */ - public function __construct($associationPathExpression, $aliasIdentificationVariable) - { - $this->associationPathExpression = $associationPathExpression; - $this->aliasIdentificationVariable = $aliasIdentificationVariable; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateClause.php deleted file mode 100644 index 23c722a..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateClause.php +++ /dev/null @@ -1,65 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * UpdateClause ::= "UPDATE" AbstractSchemaName [["AS"] AliasIdentificationVariable] "SET" UpdateItem {"," UpdateItem}* - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class UpdateClause extends Node -{ - /** - * @var string - */ - public $abstractSchemaName; - - /** - * @var string - */ - public $aliasIdentificationVariable; - - /** - * @var array - */ - public $updateItems = []; - - /** - * @param string $abstractSchemaName - * @param array $updateItems - */ - public function __construct($abstractSchemaName, array $updateItems) - { - $this->abstractSchemaName = $abstractSchemaName; - $this->updateItems = $updateItems; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkUpdateClause($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateItem.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateItem.php deleted file mode 100644 index f1a288c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateItem.php +++ /dev/null @@ -1,62 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * UpdateItem ::= [IdentificationVariable "."] {StateField | SingleValuedAssociationField} "=" NewValue - * NewValue ::= SimpleArithmeticExpression | StringPrimary | DatetimePrimary | BooleanPrimary | - * EnumPrimary | SimpleEntityExpression | "NULL" - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class UpdateItem extends Node -{ - /** - * @var PathExpression - */ - public $pathExpression; - - /** - * @var InputParameter|ArithmeticExpression|null - */ - public $newValue; - - /** - * @param PathExpression $pathExpression - * @param InputParameter|ArithmeticExpression|null $newValue - */ - public function __construct($pathExpression, $newValue) - { - $this->pathExpression = $pathExpression; - $this->newValue = $newValue; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkUpdateItem($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateStatement.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateStatement.php deleted file mode 100644 index c578efe..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/UpdateStatement.php +++ /dev/null @@ -1,58 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * UpdateStatement = UpdateClause [WhereClause] - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class UpdateStatement extends Node -{ - /** - * @var UpdateClause - */ - public $updateClause; - - /** - * @var WhereClause|null - */ - public $whereClause; - - /** - * @param UpdateClause $updateClause - */ - public function __construct($updateClause) - { - $this->updateClause = $updateClause; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkUpdateStatement($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhenClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhenClause.php deleted file mode 100644 index 01c0330..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhenClause.php +++ /dev/null @@ -1,62 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * WhenClause ::= "WHEN" ConditionalExpression "THEN" ScalarExpression - * - * @since 2.2 - * - * @link www.doctrine-project.org - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class WhenClause extends Node -{ - /** - * @var ConditionalExpression - */ - public $caseConditionExpression = null; - - /** - * @var mixed - */ - public $thenScalarExpression = null; - - /** - * @param ConditionalExpression $caseConditionExpression - * @param mixed $thenScalarExpression - */ - public function __construct($caseConditionExpression, $thenScalarExpression) - { - $this->caseConditionExpression = $caseConditionExpression; - $this->thenScalarExpression = $thenScalarExpression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkWhenClauseExpression($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhereClause.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhereClause.php deleted file mode 100644 index e659775..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/AST/WhereClause.php +++ /dev/null @@ -1,53 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\AST; - -/** - * WhereClause ::= "WHERE" ConditionalExpression - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class WhereClause extends Node -{ - /** - * @var ConditionalExpression - */ - public $conditionalExpression; - - /** - * @param ConditionalExpression $conditionalExpression - */ - public function __construct($conditionalExpression) - { - $this->conditionalExpression = $conditionalExpression; - } - - /** - * {@inheritdoc} - */ - public function dispatch($sqlWalker) - { - return $sqlWalker->walkWhereClause($this); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php deleted file mode 100644 index 8955b92..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php +++ /dev/null @@ -1,86 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Exec; - -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Cache\QueryCacheProfile; - -/** - * Base class for SQL statement executors. - * - * @author Roman Borschel - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://www.doctrine-project.org - * @since 2.0 - * @todo Rename: AbstractSQLExecutor - */ -abstract class AbstractSqlExecutor -{ - /** - * @var array - */ - protected $_sqlStatements; - - /** - * @var QueryCacheProfile - */ - protected $queryCacheProfile; - - /** - * Gets the SQL statements that are executed by the executor. - * - * @return array All the SQL update statements. - */ - public function getSqlStatements() - { - return $this->_sqlStatements; - } - - /** - * @param \Doctrine\DBAL\Cache\QueryCacheProfile $qcp - * - * @return void - */ - public function setQueryCacheProfile(QueryCacheProfile $qcp) - { - $this->queryCacheProfile = $qcp; - } - - /** - * Do not use query cache - * - * @return void - */ - public function removeQueryCacheProfile() - { - $this->queryCacheProfile = null; - } - - /** - * Executes all sql statements. - * - * @param Connection $conn The database connection that is used to execute the queries. - * @param array $params The parameters. - * @param array $types The parameter types. - * - * @return \Doctrine\DBAL\Driver\Statement - */ - abstract public function execute(Connection $conn, array $params, array $types); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php deleted file mode 100644 index 2f3d5ac..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php +++ /dev/null @@ -1,146 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Exec; - -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Types\Type; -use Doctrine\ORM\Query\AST; -use Doctrine\ORM\Utility\PersisterHelper; -use Throwable; - -/** - * Executes the SQL statements for bulk DQL DELETE statements on classes in - * Class Table Inheritance (JOINED). - * - * @author Roman Borschel - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://www.doctrine-project.org - * @since 2.0 - */ -class MultiTableDeleteExecutor extends AbstractSqlExecutor -{ - /** - * @var string - */ - private $_createTempTableSql; - - /** - * @var string - */ - private $_dropTempTableSql; - - /** - * @var string - */ - private $_insertSql; - - /** - * Initializes a new MultiTableDeleteExecutor. - * - * Internal note: Any SQL construction and preparation takes place in the constructor for - * best performance. With a query cache the executor will be cached. - * - * @param \Doctrine\ORM\Query\AST\Node $AST The root AST node of the DQL query. - * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker The walker used for SQL generation from the AST. - */ - public function __construct(AST\Node $AST, $sqlWalker) - { - $em = $sqlWalker->getEntityManager(); - $conn = $em->getConnection(); - $platform = $conn->getDatabasePlatform(); - $quoteStrategy = $em->getConfiguration()->getQuoteStrategy(); - - $primaryClass = $em->getClassMetadata($AST->deleteClause->abstractSchemaName); - $primaryDqlAlias = $AST->deleteClause->aliasIdentificationVariable; - $rootClass = $em->getClassMetadata($primaryClass->rootEntityName); - - $tempTable = $platform->getTemporaryTableName($rootClass->getTemporaryIdTableName()); - $idColumnNames = $rootClass->getIdentifierColumnNames(); - $idColumnList = implode(', ', $idColumnNames); - - // 1. Create an INSERT INTO temptable ... SELECT identifiers WHERE $AST->getWhereClause() - $sqlWalker->setSQLTableAlias($primaryClass->getTableName(), 't0', $primaryDqlAlias); - - $this->_insertSql = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ')' - . ' SELECT t0.' . implode(', t0.', $idColumnNames); - - $rangeDecl = new AST\RangeVariableDeclaration($primaryClass->name, $primaryDqlAlias); - $fromClause = new AST\FromClause([new AST\IdentificationVariableDeclaration($rangeDecl, null, [])]); - $this->_insertSql .= $sqlWalker->walkFromClause($fromClause); - - // Append WHERE clause, if there is one. - if ($AST->whereClause) { - $this->_insertSql .= $sqlWalker->walkWhereClause($AST->whereClause); - } - - // 2. Create ID subselect statement used in DELETE ... WHERE ... IN (subselect) - $idSubselect = 'SELECT ' . $idColumnList . ' FROM ' . $tempTable; - - // 3. Create and store DELETE statements - $classNames = array_merge($primaryClass->parentClasses, [$primaryClass->name], $primaryClass->subClasses); - foreach (array_reverse($classNames) as $className) { - $tableName = $quoteStrategy->getTableName($em->getClassMetadata($className), $platform); - $this->_sqlStatements[] = 'DELETE FROM ' . $tableName - . ' WHERE (' . $idColumnList . ') IN (' . $idSubselect . ')'; - } - - // 4. Store DDL for temporary identifier table. - $columnDefinitions = []; - foreach ($idColumnNames as $idColumnName) { - $columnDefinitions[$idColumnName] = [ - 'notnull' => true, - 'type' => Type::getType(PersisterHelper::getTypeOfColumn($idColumnName, $rootClass, $em)), - ]; - } - $this->_createTempTableSql = $platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' (' - . $platform->getColumnDeclarationListSQL($columnDefinitions) . ')'; - $this->_dropTempTableSql = $platform->getDropTemporaryTableSQL($tempTable); - } - - /** - * {@inheritDoc} - */ - public function execute(Connection $conn, array $params, array $types) - { - // Create temporary id table - $conn->executeUpdate($this->_createTempTableSql); - - try { - // Insert identifiers - $numDeleted = $conn->executeUpdate($this->_insertSql, $params, $types); - - // Execute DELETE statements - foreach ($this->_sqlStatements as $sql) { - $conn->executeUpdate($sql); - } - } catch (Throwable $exception) { - // FAILURE! Drop temporary table to avoid possible collisions - $conn->executeUpdate($this->_dropTempTableSql); - - // Re-throw exception - throw $exception; - } - - // Drop temporary table - $conn->executeUpdate($this->_dropTempTableSql); - - return $numDeleted; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php deleted file mode 100644 index 47db034..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php +++ /dev/null @@ -1,205 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Exec; - -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Types\Type; -use Doctrine\ORM\Query\ParameterTypeInferer; -use Doctrine\ORM\Query\AST; -use Doctrine\ORM\Utility\PersisterHelper; -use Throwable; - -/** - * Executes the SQL statements for bulk DQL UPDATE statements on classes in - * Class Table Inheritance (JOINED). - * - * @author Roman Borschel - * @since 2.0 - */ -class MultiTableUpdateExecutor extends AbstractSqlExecutor -{ - /** - * @var string - */ - private $_createTempTableSql; - - /** - * @var string - */ - private $_dropTempTableSql; - - /** - * @var string - */ - private $_insertSql; - - /** - * @var array - */ - private $_sqlParameters = []; - - /** - * @var int - */ - private $_numParametersInUpdateClause = 0; - - /** - * Initializes a new MultiTableUpdateExecutor. - * - * Internal note: Any SQL construction and preparation takes place in the constructor for - * best performance. With a query cache the executor will be cached. - * - * @param \Doctrine\ORM\Query\AST\Node $AST The root AST node of the DQL query. - * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker The walker used for SQL generation from the AST. - */ - public function __construct(AST\Node $AST, $sqlWalker) - { - $em = $sqlWalker->getEntityManager(); - $conn = $em->getConnection(); - $platform = $conn->getDatabasePlatform(); - $quoteStrategy = $em->getConfiguration()->getQuoteStrategy(); - - $updateClause = $AST->updateClause; - $primaryClass = $sqlWalker->getEntityManager()->getClassMetadata($updateClause->abstractSchemaName); - $rootClass = $em->getClassMetadata($primaryClass->rootEntityName); - - $updateItems = $updateClause->updateItems; - - $tempTable = $platform->getTemporaryTableName($rootClass->getTemporaryIdTableName()); - $idColumnNames = $rootClass->getIdentifierColumnNames(); - $idColumnList = implode(', ', $idColumnNames); - - // 1. Create an INSERT INTO temptable ... SELECT identifiers WHERE $AST->getWhereClause() - $sqlWalker->setSQLTableAlias($primaryClass->getTableName(), 't0', $updateClause->aliasIdentificationVariable); - - $this->_insertSql = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ')' - . ' SELECT t0.' . implode(', t0.', $idColumnNames); - - $rangeDecl = new AST\RangeVariableDeclaration($primaryClass->name, $updateClause->aliasIdentificationVariable); - $fromClause = new AST\FromClause([new AST\IdentificationVariableDeclaration($rangeDecl, null, [])]); - - $this->_insertSql .= $sqlWalker->walkFromClause($fromClause); - - // 2. Create ID subselect statement used in UPDATE ... WHERE ... IN (subselect) - $idSubselect = 'SELECT ' . $idColumnList . ' FROM ' . $tempTable; - - // 3. Create and store UPDATE statements - $classNames = array_merge($primaryClass->parentClasses, [$primaryClass->name], $primaryClass->subClasses); - $i = -1; - - foreach (array_reverse($classNames) as $className) { - $affected = false; - $class = $em->getClassMetadata($className); - $updateSql = 'UPDATE ' . $quoteStrategy->getTableName($class, $platform) . ' SET '; - - foreach ($updateItems as $updateItem) { - $field = $updateItem->pathExpression->field; - - if ((isset($class->fieldMappings[$field]) && ! isset($class->fieldMappings[$field]['inherited'])) || - (isset($class->associationMappings[$field]) && ! isset($class->associationMappings[$field]['inherited']))) { - $newValue = $updateItem->newValue; - - if ( ! $affected) { - $affected = true; - ++$i; - } else { - $updateSql .= ', '; - } - - $updateSql .= $sqlWalker->walkUpdateItem($updateItem); - - if ($newValue instanceof AST\InputParameter) { - $this->_sqlParameters[$i][] = $newValue->name; - - ++$this->_numParametersInUpdateClause; - } - } - } - - if ($affected) { - $this->_sqlStatements[$i] = $updateSql . ' WHERE (' . $idColumnList . ') IN (' . $idSubselect . ')'; - } - } - - // Append WHERE clause to insertSql, if there is one. - if ($AST->whereClause) { - $this->_insertSql .= $sqlWalker->walkWhereClause($AST->whereClause); - } - - // 4. Store DDL for temporary identifier table. - $columnDefinitions = []; - - foreach ($idColumnNames as $idColumnName) { - $columnDefinitions[$idColumnName] = [ - 'notnull' => true, - 'type' => Type::getType(PersisterHelper::getTypeOfColumn($idColumnName, $rootClass, $em)), - ]; - } - - $this->_createTempTableSql = $platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' (' - . $platform->getColumnDeclarationListSQL($columnDefinitions) . ')'; - - $this->_dropTempTableSql = $platform->getDropTemporaryTableSQL($tempTable); - } - - /** - * {@inheritDoc} - */ - public function execute(Connection $conn, array $params, array $types) - { - // Create temporary id table - $conn->executeUpdate($this->_createTempTableSql); - - try { - // Insert identifiers. Parameters from the update clause are cut off. - $numUpdated = $conn->executeUpdate( - $this->_insertSql, - array_slice($params, $this->_numParametersInUpdateClause), - array_slice($types, $this->_numParametersInUpdateClause) - ); - - // Execute UPDATE statements - foreach ($this->_sqlStatements as $key => $statement) { - $paramValues = []; - $paramTypes = []; - - if (isset($this->_sqlParameters[$key])) { - foreach ($this->_sqlParameters[$key] as $parameterKey => $parameterName) { - $paramValues[] = $params[$parameterKey]; - $paramTypes[] = $types[$parameterKey] ?? ParameterTypeInferer::inferType($params[$parameterKey]); - } - } - - $conn->executeUpdate($statement, $paramValues, $paramTypes); - } - } catch (Throwable $exception) { - // FAILURE! Drop temporary table to avoid possible collisions - $conn->executeUpdate($this->_dropTempTableSql); - - // Re-throw exception - throw $exception; - } - - // Drop temporary table - $conn->executeUpdate($this->_dropTempTableSql); - - return $numUpdated; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleSelectExecutor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleSelectExecutor.php deleted file mode 100644 index 91827ab..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleSelectExecutor.php +++ /dev/null @@ -1,52 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Exec; - -use Doctrine\DBAL\Connection; -use Doctrine\ORM\Query\AST\SelectStatement; -use Doctrine\ORM\Query\SqlWalker; - -/** - * Executor that executes the SQL statement for simple DQL SELECT statements. - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @author Roman Borschel - * @link www.doctrine-project.org - * @since 2.0 - */ -class SingleSelectExecutor extends AbstractSqlExecutor -{ - /** - * @param \Doctrine\ORM\Query\AST\SelectStatement $AST - * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker - */ - public function __construct(SelectStatement $AST, SqlWalker $sqlWalker) - { - $this->_sqlStatements = $sqlWalker->walkSelectStatement($AST); - } - - /** - * {@inheritDoc} - */ - public function execute(Connection $conn, array $params, array $types) - { - return $conn->executeQuery($this->_sqlStatements, $params, $types, $this->queryCacheProfile); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php deleted file mode 100644 index e0183dd..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php +++ /dev/null @@ -1,57 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Exec; - -use Doctrine\DBAL\Connection; -use Doctrine\ORM\Query\AST; - -/** - * Executor that executes the SQL statements for DQL DELETE/UPDATE statements on classes - * that are mapped to a single table. - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @author Roman Borschel - * @link www.doctrine-project.org - * @since 2.0 - * @todo This is exactly the same as SingleSelectExecutor. Unify in SingleStatementExecutor. - */ -class SingleTableDeleteUpdateExecutor extends AbstractSqlExecutor -{ - /** - * @param \Doctrine\ORM\Query\AST\Node $AST - * @param \Doctrine\ORM\Query\SqlWalker $sqlWalker - */ - public function __construct(AST\Node $AST, $sqlWalker) - { - if ($AST instanceof AST\UpdateStatement) { - $this->_sqlStatements = $sqlWalker->walkUpdateStatement($AST); - } else if ($AST instanceof AST\DeleteStatement) { - $this->_sqlStatements = $sqlWalker->walkDeleteStatement($AST); - } - } - - /** - * {@inheritDoc} - */ - public function execute(Connection $conn, array $params, array $types) - { - return $conn->executeUpdate($this->_sqlStatements, $params, $types); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr.php deleted file mode 100644 index 2523182..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr.php +++ /dev/null @@ -1,674 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -/** - * This class is used to generate DQL expressions via a set of PHP static functions. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - * @todo Rename: ExpressionBuilder - */ -class Expr -{ - /** - * Creates a conjunction of the given boolean expressions. - * - * Example: - * - * [php] - * // (u.type = ?1) AND (u.role = ?2) - * $expr->andX($expr->eq('u.type', ':1'), $expr->eq('u.role', ':2')); - * - * @param Expr\Comparison|Expr\Func|Expr\Orx|string $x Optional clause. Defaults to null, but requires at least one - * defined when converting to string. - * - * @return Expr\Andx - */ - public function andX($x = null) - { - return new Expr\Andx(func_get_args()); - } - - /** - * Creates a disjunction of the given boolean expressions. - * - * Example: - * - * [php] - * // (u.type = ?1) OR (u.role = ?2) - * $q->where($q->expr()->orX('u.type = ?1', 'u.role = ?2')); - * - * @param mixed $x Optional clause. Defaults to null, but requires - * at least one defined when converting to string. - * - * @return Expr\Orx - */ - public function orX($x = null) - { - return new Expr\Orx(func_get_args()); - } - - /** - * Creates an ASCending order expression. - * - * @param mixed $expr - * - * @return Expr\OrderBy - */ - public function asc($expr) - { - return new Expr\OrderBy($expr, 'ASC'); - } - - /** - * Creates a DESCending order expression. - * - * @param mixed $expr - * - * @return Expr\OrderBy - */ - public function desc($expr) - { - return new Expr\OrderBy($expr, 'DESC'); - } - - /** - * Creates an equality comparison expression with the given arguments. - * - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a = . Example: - * - * [php] - * // u.id = ?1 - * $expr->eq('u.id', '?1'); - * - * @param mixed $x Left expression. - * @param mixed $y Right expression. - * - * @return Expr\Comparison - */ - public function eq($x, $y) - { - return new Expr\Comparison($x, Expr\Comparison::EQ, $y); - } - - /** - * Creates an instance of Expr\Comparison, with the given arguments. - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a <> . Example: - * - * [php] - * // u.id <> ?1 - * $q->where($q->expr()->neq('u.id', '?1')); - * - * @param mixed $x Left expression. - * @param mixed $y Right expression. - * - * @return Expr\Comparison - */ - public function neq($x, $y) - { - return new Expr\Comparison($x, Expr\Comparison::NEQ, $y); - } - - /** - * Creates an instance of Expr\Comparison, with the given arguments. - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a < . Example: - * - * [php] - * // u.id < ?1 - * $q->where($q->expr()->lt('u.id', '?1')); - * - * @param mixed $x Left expression. - * @param mixed $y Right expression. - * - * @return Expr\Comparison - */ - public function lt($x, $y) - { - return new Expr\Comparison($x, Expr\Comparison::LT, $y); - } - - /** - * Creates an instance of Expr\Comparison, with the given arguments. - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a <= . Example: - * - * [php] - * // u.id <= ?1 - * $q->where($q->expr()->lte('u.id', '?1')); - * - * @param mixed $x Left expression. - * @param mixed $y Right expression. - * - * @return Expr\Comparison - */ - public function lte($x, $y) - { - return new Expr\Comparison($x, Expr\Comparison::LTE, $y); - } - - /** - * Creates an instance of Expr\Comparison, with the given arguments. - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a > . Example: - * - * [php] - * // u.id > ?1 - * $q->where($q->expr()->gt('u.id', '?1')); - * - * @param mixed $x Left expression. - * @param mixed $y Right expression. - * - * @return Expr\Comparison - */ - public function gt($x, $y) - { - return new Expr\Comparison($x, Expr\Comparison::GT, $y); - } - - /** - * Creates an instance of Expr\Comparison, with the given arguments. - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a >= . Example: - * - * [php] - * // u.id >= ?1 - * $q->where($q->expr()->gte('u.id', '?1')); - * - * @param mixed $x Left expression. - * @param mixed $y Right expression. - * - * @return Expr\Comparison - */ - public function gte($x, $y) - { - return new Expr\Comparison($x, Expr\Comparison::GTE, $y); - } - - /** - * Creates an instance of AVG() function, with the given argument. - * - * @param mixed $x Argument to be used in AVG() function. - * - * @return Expr\Func - */ - public function avg($x) - { - return new Expr\Func('AVG', [$x]); - } - - /** - * Creates an instance of MAX() function, with the given argument. - * - * @param mixed $x Argument to be used in MAX() function. - * - * @return Expr\Func - */ - public function max($x) - { - return new Expr\Func('MAX', [$x]); - } - - /** - * Creates an instance of MIN() function, with the given argument. - * - * @param mixed $x Argument to be used in MIN() function. - * - * @return Expr\Func - */ - public function min($x) - { - return new Expr\Func('MIN', [$x]); - } - - /** - * Creates an instance of COUNT() function, with the given argument. - * - * @param mixed $x Argument to be used in COUNT() function. - * - * @return Expr\Func - */ - public function count($x) - { - return new Expr\Func('COUNT', [$x]); - } - - /** - * Creates an instance of COUNT(DISTINCT) function, with the given argument. - * - * @param mixed $x Argument to be used in COUNT(DISTINCT) function. - * - * @return string - */ - public function countDistinct($x) - { - return 'COUNT(DISTINCT ' . implode(', ', func_get_args()) . ')'; - } - - /** - * Creates an instance of EXISTS() function, with the given DQL Subquery. - * - * @param mixed $subquery DQL Subquery to be used in EXISTS() function. - * - * @return Expr\Func - */ - public function exists($subquery) - { - return new Expr\Func('EXISTS', [$subquery]); - } - - /** - * Creates an instance of ALL() function, with the given DQL Subquery. - * - * @param mixed $subquery DQL Subquery to be used in ALL() function. - * - * @return Expr\Func - */ - public function all($subquery) - { - return new Expr\Func('ALL', [$subquery]); - } - - /** - * Creates a SOME() function expression with the given DQL subquery. - * - * @param mixed $subquery DQL Subquery to be used in SOME() function. - * - * @return Expr\Func - */ - public function some($subquery) - { - return new Expr\Func('SOME', [$subquery]); - } - - /** - * Creates an ANY() function expression with the given DQL subquery. - * - * @param mixed $subquery DQL Subquery to be used in ANY() function. - * - * @return Expr\Func - */ - public function any($subquery) - { - return new Expr\Func('ANY', [$subquery]); - } - - /** - * Creates a negation expression of the given restriction. - * - * @param mixed $restriction Restriction to be used in NOT() function. - * - * @return Expr\Func - */ - public function not($restriction) - { - return new Expr\Func('NOT', [$restriction]); - } - - /** - * Creates an ABS() function expression with the given argument. - * - * @param mixed $x Argument to be used in ABS() function. - * - * @return Expr\Func - */ - public function abs($x) - { - return new Expr\Func('ABS', [$x]); - } - - /** - * Creates a product mathematical expression with the given arguments. - * - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a * . Example: - * - * [php] - * // u.salary * u.percentAnnualSalaryIncrease - * $q->expr()->prod('u.salary', 'u.percentAnnualSalaryIncrease') - * - * @param mixed $x Left expression. - * @param mixed $y Right expression. - * - * @return Expr\Math - */ - public function prod($x, $y) - { - return new Expr\Math($x, '*', $y); - } - - /** - * Creates a difference mathematical expression with the given arguments. - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a - . Example: - * - * [php] - * // u.monthlySubscriptionCount - 1 - * $q->expr()->diff('u.monthlySubscriptionCount', '1') - * - * @param mixed $x Left expression. - * @param mixed $y Right expression. - * - * @return Expr\Math - */ - public function diff($x, $y) - { - return new Expr\Math($x, '-', $y); - } - - /** - * Creates a sum mathematical expression with the given arguments. - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a + . Example: - * - * [php] - * // u.numChildren + 1 - * $q->expr()->sum('u.numChildren', '1') - * - * @param mixed $x Left expression. - * @param mixed $y Right expression. - * - * @return Expr\Math - */ - public function sum($x, $y) - { - return new Expr\Math($x, '+', $y); - } - - /** - * Creates a quotient mathematical expression with the given arguments. - * First argument is considered the left expression and the second is the right expression. - * When converted to string, it will generated a / . Example: - * - * [php] - * // u.total / u.period - * $expr->quot('u.total', 'u.period') - * - * @param mixed $x Left expression. - * @param mixed $y Right expression. - * - * @return Expr\Math - */ - public function quot($x, $y) - { - return new Expr\Math($x, '/', $y); - } - - /** - * Creates a SQRT() function expression with the given argument. - * - * @param mixed $x Argument to be used in SQRT() function. - * - * @return Expr\Func - */ - public function sqrt($x) - { - return new Expr\Func('SQRT', [$x]); - } - - /** - * Creates an IN() expression with the given arguments. - * - * @param string $x Field in string format to be restricted by IN() function. - * @param mixed $y Argument to be used in IN() function. - * - * @return Expr\Func - */ - public function in($x, $y) - { - if (is_array($y)) { - foreach ($y as &$literal) { - if ( ! ($literal instanceof Expr\Literal)) { - $literal = $this->_quoteLiteral($literal); - } - } - } - - return new Expr\Func($x . ' IN', (array) $y); - } - - /** - * Creates a NOT IN() expression with the given arguments. - * - * @param string $x Field in string format to be restricted by NOT IN() function. - * @param mixed $y Argument to be used in NOT IN() function. - * - * @return Expr\Func - */ - public function notIn($x, $y) - { - if (is_array($y)) { - foreach ($y as &$literal) { - if ( ! ($literal instanceof Expr\Literal)) { - $literal = $this->_quoteLiteral($literal); - } - } - } - - return new Expr\Func($x . ' NOT IN', (array) $y); - } - - /** - * Creates an IS NULL expression with the given arguments. - * - * @param string $x Field in string format to be restricted by IS NULL. - * - * @return string - */ - public function isNull($x) - { - return $x . ' IS NULL'; - } - - /** - * Creates an IS NOT NULL expression with the given arguments. - * - * @param string $x Field in string format to be restricted by IS NOT NULL. - * - * @return string - */ - public function isNotNull($x) - { - return $x . ' IS NOT NULL'; - } - - /** - * Creates a LIKE() comparison expression with the given arguments. - * - * @param string $x Field in string format to be inspected by LIKE() comparison. - * @param mixed $y Argument to be used in LIKE() comparison. - * - * @return Expr\Comparison - */ - public function like($x, $y) - { - return new Expr\Comparison($x, 'LIKE', $y); - } - - /** - * Creates a NOT LIKE() comparison expression with the given arguments. - * - * @param string $x Field in string format to be inspected by LIKE() comparison. - * @param mixed $y Argument to be used in LIKE() comparison. - * - * @return Expr\Comparison - */ - public function notLike($x, $y) - { - return new Expr\Comparison($x, 'NOT LIKE', $y); - } - - /** - * Creates a CONCAT() function expression with the given arguments. - * - * @param mixed $x First argument to be used in CONCAT() function. - * @param mixed $y,... Other arguments to be used in CONCAT() function. - * - * @return Expr\Func - */ - public function concat($x, $y) - { - return new Expr\Func('CONCAT', func_get_args()); - } - - /** - * Creates a SUBSTRING() function expression with the given arguments. - * - * @param mixed $x Argument to be used as string to be cropped by SUBSTRING() function. - * @param int $from Initial offset to start cropping string. May accept negative values. - * @param int|null $len Length of crop. May accept negative values. - * - * @return Expr\Func - */ - public function substring($x, $from, $len = null) - { - $args = [$x, $from]; - if (null !== $len) { - $args[] = $len; - } - - return new Expr\Func('SUBSTRING', $args); - } - - /** - * Creates a LOWER() function expression with the given argument. - * - * @param mixed $x Argument to be used in LOWER() function. - * - * @return Expr\Func A LOWER function expression. - */ - public function lower($x) - { - return new Expr\Func('LOWER', [$x]); - } - - /** - * Creates an UPPER() function expression with the given argument. - * - * @param mixed $x Argument to be used in UPPER() function. - * - * @return Expr\Func An UPPER function expression. - */ - public function upper($x) - { - return new Expr\Func('UPPER', [$x]); - } - - /** - * Creates a LENGTH() function expression with the given argument. - * - * @param mixed $x Argument to be used as argument of LENGTH() function. - * - * @return Expr\Func A LENGTH function expression. - */ - public function length($x) - { - return new Expr\Func('LENGTH', [$x]); - } - - /** - * Creates a literal expression of the given argument. - * - * @param mixed $literal Argument to be converted to literal. - * - * @return Expr\Literal - */ - public function literal($literal) - { - return new Expr\Literal($this->_quoteLiteral($literal)); - } - - /** - * Quotes a literal value, if necessary, according to the DQL syntax. - * - * @param mixed $literal The literal value. - * - * @return string - */ - private function _quoteLiteral($literal) - { - if (is_numeric($literal) && !is_string($literal)) { - return (string) $literal; - } else if (is_bool($literal)) { - return $literal ? "true" : "false"; - } - - return "'" . str_replace("'", "''", $literal) . "'"; - } - - /** - * Creates an instance of BETWEEN() function, with the given argument. - * - * @param mixed $val Valued to be inspected by range values. - * @param integer|string $x Starting range value to be used in BETWEEN() function. - * @param integer|string $y End point value to be used in BETWEEN() function. - * - * @return Expr\Func A BETWEEN expression. - */ - public function between($val, $x, $y) - { - return $val . ' BETWEEN ' . $x . ' AND ' . $y; - } - - /** - * Creates an instance of TRIM() function, with the given argument. - * - * @param mixed $x Argument to be used as argument of TRIM() function. - * - * @return Expr\Func a TRIM expression. - */ - public function trim($x) - { - return new Expr\Func('TRIM', $x); - } - - /** - * Creates an instance of MEMBER OF function, with the given arguments. - * - * @param string $x Value to be checked - * @param string $y Value to be checked against - * - * @return Expr\Comparison - */ - public function isMemberOf($x, $y) - { - return new Expr\Comparison($x, 'MEMBER OF', $y); - } - - /** - * Creates an instance of INSTANCE OF function, with the given arguments. - * - * @param string $x Value to be checked - * @param string $y Value to be checked against - * - * @return Expr\Comparison - */ - public function isInstanceOf($x, $y) - { - return new Expr\Comparison($x, 'INSTANCE OF', $y); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Andx.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Andx.php deleted file mode 100644 index dd91916..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Andx.php +++ /dev/null @@ -1,55 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Expr; - -/** - * Expression class for building DQL and parts. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Andx extends Composite -{ - /** - * @var string - */ - protected $separator = ' AND '; - - /** - * @var array - */ - protected $allowedClasses = [ - Comparison::class, - Func::class, - Orx::class, - Andx::class, - ]; - - /** - * @return array - */ - public function getParts() - { - return $this->parts; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Base.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Base.php deleted file mode 100644 index d4b8d38..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Base.php +++ /dev/null @@ -1,124 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Expr; - -/** - * Abstract base Expr class for building DQL parts. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -abstract class Base -{ - /** - * @var string - */ - protected $preSeparator = '('; - - /** - * @var string - */ - protected $separator = ', '; - - /** - * @var string - */ - protected $postSeparator = ')'; - - /** - * @var array - */ - protected $allowedClasses = []; - - /** - * @var array - */ - protected $parts = []; - - /** - * @param mixed $args - */ - public function __construct($args = []) - { - $this->addMultiple($args); - } - - /** - * @param array $args - * - * @return Base - */ - public function addMultiple($args = []) - { - foreach ((array) $args as $arg) { - $this->add($arg); - } - - return $this; - } - - /** - * @param mixed $arg - * - * @return Base - * - * @throws \InvalidArgumentException - */ - public function add($arg) - { - if ( $arg !== null && (!$arg instanceof self || $arg->count() > 0) ) { - // If we decide to keep Expr\Base instances, we can use this check - if ( ! is_string($arg)) { - $class = get_class($arg); - - if ( ! in_array($class, $this->allowedClasses)) { - throw new \InvalidArgumentException("Expression of type '$class' not allowed in this context."); - } - } - - $this->parts[] = $arg; - } - - return $this; - } - - /** - * @return integer - */ - public function count() - { - return count($this->parts); - } - - /** - * @return string - */ - public function __toString() - { - if ($this->count() == 1) { - return (string) $this->parts[0]; - } - - return $this->preSeparator . implode($this->separator, $this->parts) . $this->postSeparator; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Comparison.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Comparison.php deleted file mode 100644 index 4103dce..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Comparison.php +++ /dev/null @@ -1,100 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Expr; - -/** - * Expression class for DQL comparison expressions. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Comparison -{ - const EQ = '='; - const NEQ = '<>'; - const LT = '<'; - const LTE = '<='; - const GT = '>'; - const GTE = '>='; - - /** - * @var mixed - */ - protected $leftExpr; - - /** - * @var string - */ - protected $operator; - - /** - * @var mixed - */ - protected $rightExpr; - - /** - * Creates a comparison expression with the given arguments. - * - * @param mixed $leftExpr - * @param string $operator - * @param mixed $rightExpr - */ - public function __construct($leftExpr, $operator, $rightExpr) - { - $this->leftExpr = $leftExpr; - $this->operator = $operator; - $this->rightExpr = $rightExpr; - } - - /** - * @return mixed - */ - public function getLeftExpr() - { - return $this->leftExpr; - } - - /** - * @return string - */ - public function getOperator() - { - return $this->operator; - } - - /** - * @return mixed - */ - public function getRightExpr() - { - return $this->rightExpr; - } - - /** - * @return string - */ - public function __toString() - { - return $this->leftExpr . ' ' . $this->operator . ' ' . $this->rightExpr; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Composite.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Composite.php deleted file mode 100644 index 6b8a04f..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Composite.php +++ /dev/null @@ -1,71 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Expr; - -/** - * Expression class for building DQL and parts. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Composite extends Base -{ - /** - * @return string - */ - public function __toString() - { - if ($this->count() === 1) { - return (string) $this->parts[0]; - } - - $components = []; - - foreach ($this->parts as $part) { - $components[] = $this->processQueryPart($part); - } - - return implode($this->separator, $components); - } - - /** - * @param string $part - * - * @return string - */ - private function processQueryPart($part) - { - $queryPart = (string) $part; - - if (is_object($part) && $part instanceof self && $part->count() > 1) { - return $this->preSeparator . $queryPart . $this->postSeparator; - } - - // Fixes DDC-1237: User may have added a where item containing nested expression (with "OR" or "AND") - if (stripos($queryPart, ' OR ') !== false || stripos($queryPart, ' AND ') !== false) { - return $this->preSeparator . $queryPart . $this->postSeparator; - } - - return $queryPart; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/From.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/From.php deleted file mode 100644 index 9dcce9b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/From.php +++ /dev/null @@ -1,92 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Expr; - -/** - * Expression class for DQL from. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class From -{ - /** - * @var string - */ - protected $from; - - /** - * @var string - */ - protected $alias; - - /** - * @var string - */ - protected $indexBy; - - /** - * @param string $from The class name. - * @param string $alias The alias of the class. - * @param string $indexBy The index for the from. - */ - public function __construct($from, $alias, $indexBy = null) - { - $this->from = $from; - $this->alias = $alias; - $this->indexBy = $indexBy; - } - - /** - * @return string - */ - public function getFrom() - { - return $this->from; - } - - /** - * @return string - */ - public function getAlias() - { - return $this->alias; - } - - /** - * @return string - */ - public function getIndexBy() - { - return $this->indexBy; - } - - /** - * @return string - */ - public function __toString() - { - return $this->from . ' ' . $this->alias . - ($this->indexBy ? ' INDEX BY ' . $this->indexBy : ''); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Func.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Func.php deleted file mode 100644 index b4ed07c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Func.php +++ /dev/null @@ -1,78 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Expr; - -/** - * Expression class for generating DQL functions. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Func -{ - /** - * @var string - */ - protected $name; - - /** - * @var array - */ - protected $arguments; - - /** - * Creates a function, with the given argument. - * - * @param string $name - * @param array $arguments - */ - public function __construct($name, $arguments) - { - $this->name = $name; - $this->arguments = (array) $arguments; - } - - /** - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * @return array - */ - public function getArguments() - { - return $this->arguments; - } - - /** - * @return string - */ - public function __toString() - { - return $this->name . '(' . implode(', ', $this->arguments) . ')'; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/GroupBy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/GroupBy.php deleted file mode 100644 index efa3582..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/GroupBy.php +++ /dev/null @@ -1,50 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Expr; - -/** - * Expression class for building DQL Group By parts. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class GroupBy extends Base -{ - /** - * @var string - */ - protected $preSeparator = ''; - - /** - * @var string - */ - protected $postSeparator = ''; - - /** - * @return array - */ - public function getParts() - { - return $this->parts; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Join.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Join.php deleted file mode 100644 index 7a59e24..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Join.php +++ /dev/null @@ -1,145 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Expr; - -/** - * Expression class for DQL join. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Join -{ - const INNER_JOIN = 'INNER'; - const LEFT_JOIN = 'LEFT'; - - const ON = 'ON'; - const WITH = 'WITH'; - - /** - * @var string - */ - protected $joinType; - - /** - * @var string - */ - protected $join; - - /** - * @var string - */ - protected $alias; - - /** - * @var string - */ - protected $conditionType; - - /** - * @var string - */ - protected $condition; - - /** - * @var string - */ - protected $indexBy; - - /** - * @param string $joinType The condition type constant. Either INNER_JOIN or LEFT_JOIN. - * @param string $join The relationship to join. - * @param string|null $alias The alias of the join. - * @param string|null $conditionType The condition type constant. Either ON or WITH. - * @param string|null $condition The condition for the join. - * @param string|null $indexBy The index for the join. - */ - public function __construct($joinType, $join, $alias = null, $conditionType = null, $condition = null, $indexBy = null) - { - $this->joinType = $joinType; - $this->join = $join; - $this->alias = $alias; - $this->conditionType = $conditionType; - $this->condition = $condition; - $this->indexBy = $indexBy; - } - - /** - * @return string - */ - public function getJoinType() - { - return $this->joinType; - } - - /** - * @return string - */ - public function getJoin() - { - return $this->join; - } - - /** - * @return string - */ - public function getAlias() - { - return $this->alias; - } - - /** - * @return string - */ - public function getConditionType() - { - return $this->conditionType; - } - - /** - * @return string - */ - public function getCondition() - { - return $this->condition; - } - - /** - * @return string - */ - public function getIndexBy() - { - return $this->indexBy; - } - - /** - * @return string - */ - public function __toString() - { - return strtoupper($this->joinType) . ' JOIN ' . $this->join - . ($this->alias ? ' ' . $this->alias : '') - . ($this->indexBy ? ' INDEX BY ' . $this->indexBy : '') - . ($this->condition ? ' ' . strtoupper($this->conditionType) . ' ' . $this->condition : ''); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Literal.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Literal.php deleted file mode 100644 index 98cee79..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Literal.php +++ /dev/null @@ -1,50 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Expr; - -/** - * Expression class for generating DQL functions. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Literal extends Base -{ - /** - * @var string - */ - protected $preSeparator = ''; - - /** - * @var string - */ - protected $postSeparator = ''; - - /** - * @return array - */ - public function getParts() - { - return $this->parts; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Math.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Math.php deleted file mode 100644 index 9bf800d..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Math.php +++ /dev/null @@ -1,107 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Expr; - -/** - * Expression class for DQL math statements. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Math -{ - /** - * @var mixed - */ - protected $leftExpr; - - /** - * @var string - */ - protected $operator; - - /** - * @var mixed - */ - protected $rightExpr; - - /** - * Creates a mathematical expression with the given arguments. - * - * @param mixed $leftExpr - * @param string $operator - * @param mixed $rightExpr - */ - public function __construct($leftExpr, $operator, $rightExpr) - { - $this->leftExpr = $leftExpr; - $this->operator = $operator; - $this->rightExpr = $rightExpr; - } - - /** - * @return mixed - */ - public function getLeftExpr() - { - return $this->leftExpr; - } - - /** - * @return string - */ - public function getOperator() - { - return $this->operator; - } - - /** - * @return mixed - */ - public function getRightExpr() - { - return $this->rightExpr; - } - - /** - * @return string - */ - public function __toString() - { - // Adjusting Left Expression - $leftExpr = (string) $this->leftExpr; - - if ($this->leftExpr instanceof Math) { - $leftExpr = '(' . $leftExpr . ')'; - } - - // Adjusting Right Expression - $rightExpr = (string) $this->rightExpr; - - if ($this->rightExpr instanceof Math) { - $rightExpr = '(' . $rightExpr . ')'; - } - - return $leftExpr . ' ' . $this->operator . ' ' . $rightExpr; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/OrderBy.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/OrderBy.php deleted file mode 100644 index a5f8ef9..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/OrderBy.php +++ /dev/null @@ -1,104 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Expr; - -/** - * Expression class for building DQL Order By parts. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class OrderBy -{ - /** - * @var string - */ - protected $preSeparator = ''; - - /** - * @var string - */ - protected $separator = ', '; - - /** - * @var string - */ - protected $postSeparator = ''; - - /** - * @var array - */ - protected $allowedClasses = []; - - /** - * @var array - */ - protected $parts = []; - - /** - * @param string|null $sort - * @param string|null $order - */ - public function __construct($sort = null, $order = null) - { - if ($sort) { - $this->add($sort, $order); - } - } - - /** - * @param string $sort - * @param string|null $order - * - * @return void - */ - public function add($sort, $order = null) - { - $order = ! $order ? 'ASC' : $order; - $this->parts[] = $sort . ' '. $order; - } - - /** - * @return integer - */ - public function count() - { - return count($this->parts); - } - - /** - * @return array - */ - public function getParts() - { - return $this->parts; - } - - /** - * @return string - */ - public function __toString() - { - return $this->preSeparator . implode($this->separator, $this->parts) . $this->postSeparator; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Orx.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Orx.php deleted file mode 100644 index d36abfa..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Orx.php +++ /dev/null @@ -1,55 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Expr; - -/** - * Expression class for building DQL OR clauses. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Orx extends Composite -{ - /** - * @var string - */ - protected $separator = ' OR '; - - /** - * @var array - */ - protected $allowedClasses = [ - Comparison::class, - Func::class, - Andx::class, - Orx::class, - ]; - - /** - * @return array - */ - public function getParts() - { - return $this->parts; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Select.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Select.php deleted file mode 100644 index 8ab5153..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Expr/Select.php +++ /dev/null @@ -1,55 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Expr; - -/** - * Expression class for building DQL select statements. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class Select extends Base -{ - /** - * @var string - */ - protected $preSeparator = ''; - - /** - * @var string - */ - protected $postSeparator = ''; - - /** - * @var array - */ - protected $allowedClasses = [Func::class]; - - /** - * @return array - */ - public function getParts() - { - return $this->parts; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Filter/SQLFilter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Filter/SQLFilter.php deleted file mode 100644 index c48edd4..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Filter/SQLFilter.php +++ /dev/null @@ -1,155 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query\Filter; - -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Query\ParameterTypeInferer; - -/** - * The base class that user defined filters should extend. - * - * Handles the setting and escaping of parameters. - * - * @author Alexander - * @author Benjamin Eberlei - * @abstract - */ -abstract class SQLFilter -{ - /** - * The entity manager. - * - * @var EntityManagerInterface - */ - private $em; - - /** - * Parameters for the filter. - * - * @var array - */ - private $parameters = []; - - /** - * Constructs the SQLFilter object. - * - * @param EntityManagerInterface $em The entity manager. - */ - final public function __construct(EntityManagerInterface $em) - { - $this->em = $em; - } - - /** - * Sets a parameter that can be used by the filter. - * - * @param string $name Name of the parameter. - * @param string $value Value of the parameter. - * @param string|null $type The parameter type. If specified, the given value will be run through - * the type conversion of this type. This is usually not needed for - * strings and numeric types. - * - * @return SQLFilter The current SQL filter. - */ - final public function setParameter($name, $value, $type = null) - { - if (null === $type) { - $type = ParameterTypeInferer::inferType($value); - } - - $this->parameters[$name] = ['value' => $value, 'type' => $type]; - - // Keep the parameters sorted for the hash - ksort($this->parameters); - - // The filter collection of the EM is now dirty - $this->em->getFilters()->setFiltersStateDirty(); - - return $this; - } - - /** - * Gets a parameter to use in a query. - * - * The function is responsible for the right output escaping to use the - * value in a query. - * - * @param string $name Name of the parameter. - * - * @return string The SQL escaped parameter to use in a query. - * - * @throws \InvalidArgumentException - */ - final public function getParameter($name) - { - if (!isset($this->parameters[$name])) { - throw new \InvalidArgumentException("Parameter '" . $name . "' does not exist."); - } - - return $this->em->getConnection()->quote($this->parameters[$name]['value'], $this->parameters[$name]['type']); - } - - /** - * Checks if a parameter was set for the filter. - * - * @param string $name Name of the parameter. - * - * @return boolean - */ - final public function hasParameter($name) - { - if (!isset($this->parameters[$name])) { - return false; - } - - return true; - } - - /** - * Returns as string representation of the SQLFilter parameters (the state). - * - * @return string String representation of the SQLFilter. - */ - final public function __toString() - { - return serialize($this->parameters); - } - - /** - * Returns the database connection used by the entity manager - * - * @return \Doctrine\DBAL\Connection - */ - final protected function getConnection() - { - return $this->em->getConnection(); - } - - /** - * Gets the SQL query part to add to a query. - * - * @param ClassMetaData $targetEntity - * @param string $targetTableAlias - * - * @return string The constraint SQL if there is available, empty string otherwise. - */ - abstract public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/FilterCollection.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/FilterCollection.php deleted file mode 100644 index ca7f1ac..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/FilterCollection.php +++ /dev/null @@ -1,225 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -use Doctrine\ORM\EntityManagerInterface; - -/** - * Collection class for all the query filters. - * - * @author Alexander - */ -class FilterCollection -{ - /* Filter STATES */ - - /** - * A filter object is in CLEAN state when it has no changed parameters. - */ - const FILTERS_STATE_CLEAN = 1; - - /** - * A filter object is in DIRTY state when it has changed parameters. - */ - const FILTERS_STATE_DIRTY = 2; - - /** - * The used Configuration. - * - * @var \Doctrine\ORM\Configuration - */ - private $config; - - /** - * The EntityManager that "owns" this FilterCollection instance. - * - * @var \Doctrine\ORM\EntityManager - */ - private $em; - - /** - * Instances of enabled filters. - * - * @var \Doctrine\ORM\Query\Filter\SQLFilter[] - */ - private $enabledFilters = []; - - /** - * @var string The filter hash from the last time the query was parsed. - */ - private $filterHash; - - /** - * @var integer The current state of this filter. - */ - private $filtersState = self::FILTERS_STATE_CLEAN; - - /** - * Constructor. - * - * @param EntityManagerInterface $em - */ - public function __construct(EntityManagerInterface $em) - { - $this->em = $em; - $this->config = $em->getConfiguration(); - } - - /** - * Gets all the enabled filters. - * - * @return \Doctrine\ORM\Query\Filter\SQLFilter[] The enabled filters. - */ - public function getEnabledFilters() - { - return $this->enabledFilters; - } - - /** - * Enables a filter from the collection. - * - * @param string $name Name of the filter. - * - * @return \Doctrine\ORM\Query\Filter\SQLFilter The enabled filter. - * - * @throws \InvalidArgumentException If the filter does not exist. - */ - public function enable($name) - { - if ( ! $this->has($name)) { - throw new \InvalidArgumentException("Filter '" . $name . "' does not exist."); - } - - if ( ! $this->isEnabled($name)) { - $filterClass = $this->config->getFilterClassName($name); - - $this->enabledFilters[$name] = new $filterClass($this->em); - - // Keep the enabled filters sorted for the hash - ksort($this->enabledFilters); - - // Now the filter collection is dirty - $this->filtersState = self::FILTERS_STATE_DIRTY; - } - - return $this->enabledFilters[$name]; - } - - /** - * Disables a filter. - * - * @param string $name Name of the filter. - * - * @return \Doctrine\ORM\Query\Filter\SQLFilter The disabled filter. - * - * @throws \InvalidArgumentException If the filter does not exist. - */ - public function disable($name) - { - // Get the filter to return it - $filter = $this->getFilter($name); - - unset($this->enabledFilters[$name]); - - // Now the filter collection is dirty - $this->filtersState = self::FILTERS_STATE_DIRTY; - - return $filter; - } - - /** - * Gets an enabled filter from the collection. - * - * @param string $name Name of the filter. - * - * @return \Doctrine\ORM\Query\Filter\SQLFilter The filter. - * - * @throws \InvalidArgumentException If the filter is not enabled. - */ - public function getFilter($name) - { - if ( ! $this->isEnabled($name)) { - throw new \InvalidArgumentException("Filter '" . $name . "' is not enabled."); - } - - return $this->enabledFilters[$name]; - } - - /** - * Checks whether filter with given name is defined. - * - * @param string $name Name of the filter. - * - * @return bool true if the filter exists, false if not. - */ - public function has($name) - { - return null !== $this->config->getFilterClassName($name); - } - - /** - * Checks if a filter is enabled. - * - * @param string $name Name of the filter. - * - * @return boolean True if the filter is enabled, false otherwise. - */ - public function isEnabled($name) - { - return isset($this->enabledFilters[$name]); - } - - /** - * @return boolean True, if the filter collection is clean. - */ - public function isClean() - { - return self::FILTERS_STATE_CLEAN === $this->filtersState; - } - - /** - * Generates a string of currently enabled filters to use for the cache id. - * - * @return string - */ - public function getHash() - { - // If there are only clean filters, the previous hash can be returned - if (self::FILTERS_STATE_CLEAN === $this->filtersState) { - return $this->filterHash; - } - - $filterHash = ''; - - foreach ($this->enabledFilters as $name => $filter) { - $filterHash .= $name . $filter; - } - - return $filterHash; - } - - /** - * Sets the filter state to dirty. - */ - public function setFiltersStateDirty() - { - $this->filtersState = self::FILTERS_STATE_DIRTY; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Lexer.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Lexer.php deleted file mode 100644 index 573e433..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Lexer.php +++ /dev/null @@ -1,222 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -use Doctrine\Common\Lexer\AbstractLexer; - -/** - * Scans a DQL query for tokens. - * - * @author Guilherme Blanco - * @author Janne Vanhala - * @author Roman Borschel - * @since 2.0 - */ -class Lexer extends AbstractLexer -{ - // All tokens that are not valid identifiers must be < 100 - const T_NONE = 1; - const T_INTEGER = 2; - const T_STRING = 3; - const T_INPUT_PARAMETER = 4; - const T_FLOAT = 5; - const T_CLOSE_PARENTHESIS = 6; - const T_OPEN_PARENTHESIS = 7; - const T_COMMA = 8; - const T_DIVIDE = 9; - const T_DOT = 10; - const T_EQUALS = 11; - const T_GREATER_THAN = 12; - const T_LOWER_THAN = 13; - const T_MINUS = 14; - const T_MULTIPLY = 15; - const T_NEGATE = 16; - const T_PLUS = 17; - const T_OPEN_CURLY_BRACE = 18; - const T_CLOSE_CURLY_BRACE = 19; - - // All tokens that are identifiers or keywords that could be considered as identifiers should be >= 100 - const T_ALIASED_NAME = 100; - const T_FULLY_QUALIFIED_NAME = 101; - const T_IDENTIFIER = 102; - - // All keyword tokens should be >= 200 - const T_ALL = 200; - const T_AND = 201; - const T_ANY = 202; - const T_AS = 203; - const T_ASC = 204; - const T_AVG = 205; - const T_BETWEEN = 206; - const T_BOTH = 207; - const T_BY = 208; - const T_CASE = 209; - const T_COALESCE = 210; - const T_COUNT = 211; - const T_DELETE = 212; - const T_DESC = 213; - const T_DISTINCT = 214; - const T_ELSE = 215; - const T_EMPTY = 216; - const T_END = 217; - const T_ESCAPE = 218; - const T_EXISTS = 219; - const T_FALSE = 220; - const T_FROM = 221; - const T_GROUP = 222; - const T_HAVING = 223; - const T_HIDDEN = 224; - const T_IN = 225; - const T_INDEX = 226; - const T_INNER = 227; - const T_INSTANCE = 228; - const T_IS = 229; - const T_JOIN = 230; - const T_LEADING = 231; - const T_LEFT = 232; - const T_LIKE = 233; - const T_MAX = 234; - const T_MEMBER = 235; - const T_MIN = 236; - const T_NEW = 237; - const T_NOT = 238; - const T_NULL = 239; - const T_NULLIF = 240; - const T_OF = 241; - const T_OR = 242; - const T_ORDER = 243; - const T_OUTER = 244; - const T_PARTIAL = 245; - const T_SELECT = 246; - const T_SET = 247; - const T_SOME = 248; - const T_SUM = 249; - const T_THEN = 250; - const T_TRAILING = 251; - const T_TRUE = 252; - const T_UPDATE = 253; - const T_WHEN = 254; - const T_WHERE = 255; - const T_WITH = 256; - - /** - * Creates a new query scanner object. - * - * @param string $input A query string. - */ - public function __construct($input) - { - $this->setInput($input); - } - - /** - * {@inheritdoc} - */ - protected function getCatchablePatterns() - { - return [ - '[a-z_][a-z0-9_]*\:[a-z_][a-z0-9_]*(?:\\\[a-z_][a-z0-9_]*)*', // aliased name - '[a-z_\\\][a-z0-9_]*(?:\\\[a-z_][a-z0-9_]*)*', // identifier or qualified name - '(?:[0-9]+(?:[\.][0-9]+)*)(?:e[+-]?[0-9]+)?', // numbers - "'(?:[^']|'')*'", // quoted strings - '\?[0-9]*|:[a-z_][a-z0-9_]*' // parameters - ]; - } - - /** - * {@inheritdoc} - */ - protected function getNonCatchablePatterns() - { - return ['\s+', '(.)']; - } - - /** - * {@inheritdoc} - */ - protected function getType(&$value) - { - $type = self::T_NONE; - - switch (true) { - // Recognize numeric values - case (is_numeric($value)): - if (strpos($value, '.') !== false || stripos($value, 'e') !== false) { - return self::T_FLOAT; - } - - return self::T_INTEGER; - - // Recognize quoted strings - case ($value[0] === "'"): - $value = str_replace("''", "'", substr($value, 1, strlen($value) - 2)); - - return self::T_STRING; - - // Recognize identifiers, aliased or qualified names - case (ctype_alpha($value[0]) || $value[0] === '_' || $value[0] === '\\'): - $name = 'Doctrine\ORM\Query\Lexer::T_' . strtoupper($value); - - if (defined($name)) { - $type = constant($name); - - if ($type > 100) { - return $type; - } - } - - if (strpos($value, ':') !== false) { - return self::T_ALIASED_NAME; - } - - if (strpos($value, '\\') !== false) { - return self::T_FULLY_QUALIFIED_NAME; - } - - return self::T_IDENTIFIER; - - // Recognize input parameters - case ($value[0] === '?' || $value[0] === ':'): - return self::T_INPUT_PARAMETER; - - // Recognize symbols - case ($value === '.'): return self::T_DOT; - case ($value === ','): return self::T_COMMA; - case ($value === '('): return self::T_OPEN_PARENTHESIS; - case ($value === ')'): return self::T_CLOSE_PARENTHESIS; - case ($value === '='): return self::T_EQUALS; - case ($value === '>'): return self::T_GREATER_THAN; - case ($value === '<'): return self::T_LOWER_THAN; - case ($value === '+'): return self::T_PLUS; - case ($value === '-'): return self::T_MINUS; - case ($value === '*'): return self::T_MULTIPLY; - case ($value === '/'): return self::T_DIVIDE; - case ($value === '!'): return self::T_NEGATE; - case ($value === '{'): return self::T_OPEN_CURLY_BRACE; - case ($value === '}'): return self::T_CLOSE_CURLY_BRACE; - - // Default - default: - // Do nothing - } - - return $type; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parameter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parameter.php deleted file mode 100644 index 6e968a1..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parameter.php +++ /dev/null @@ -1,122 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -use function trim; - -/** - * Defines a Query Parameter. - * - * @link www.doctrine-project.org - * @since 2.3 - * @author Guilherme Blanco - */ -class Parameter -{ - /** - * The parameter name. - * - * @var string - */ - private $name; - - /** - * The parameter value. - * - * @var mixed - */ - private $value; - - /** - * The parameter type. - * - * @var mixed - */ - private $type; - - /** - * Whether the parameter type was explicitly specified or not - * - * @var bool - */ - private $typeSpecified; - - /** - * Constructor. - * - * @param string $name Parameter name - * @param mixed $value Parameter value - * @param mixed $type Parameter type - */ - public function __construct($name, $value, $type = null) - { - $this->name = trim($name, ':'); - $this->typeSpecified = $type !== null; - - $this->setValue($value, $type); - } - - /** - * Retrieves the Parameter name. - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Retrieves the Parameter value. - * - * @return mixed - */ - public function getValue() - { - return $this->value; - } - - /** - * Retrieves the Parameter type. - * - * @return mixed - */ - public function getType() - { - return $this->type; - } - - /** - * Defines the Parameter value. - * - * @param mixed $value Parameter value. - * @param mixed $type Parameter type. - */ - public function setValue($value, $type = null) - { - $this->value = $value; - $this->type = $type ?: ParameterTypeInferer::inferType($value); - } - - public function typeWasSpecified() : bool - { - return $this->typeSpecified; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParameterTypeInferer.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParameterTypeInferer.php deleted file mode 100644 index 07b78f0..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParameterTypeInferer.php +++ /dev/null @@ -1,72 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Types\Type; - -/** - * Provides an enclosed support for parameter inferring. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ParameterTypeInferer -{ - /** - * Infers type of a given value, returning a compatible constant: - * - Type (\Doctrine\DBAL\Types\Type::*) - * - Connection (\Doctrine\DBAL\Connection::PARAM_*) - * - * @param mixed $value Parameter value. - * - * @return mixed Parameter type constant. - */ - public static function inferType($value) - { - if (is_int($value)) { - return Type::INTEGER; - } - - if (is_bool($value)) { - return Type::BOOLEAN; - } - - if ($value instanceof \DateTime || $value instanceof \DateTimeInterface) { - return Type::DATETIME; - } - - if ($value instanceof \DateInterval) { - return Type::DATEINTERVAL; - } - - if (is_array($value)) { - return is_int(current($value)) - ? Connection::PARAM_INT_ARRAY - : Connection::PARAM_STR_ARRAY; - } - - return \PDO::PARAM_STR; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php deleted file mode 100644 index 7b3e8ff..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php +++ /dev/null @@ -1,3539 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Query; -use Doctrine\ORM\Query\AST\Functions; -use function in_array; -use function strpos; - -/** - * An LL(*) recursive-descent parser for the context-free grammar of the Doctrine Query Language. - * Parses a DQL query, reports any errors in it, and generates an AST. - * - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Janne Vanhala - * @author Fabio B. Silva - */ -class Parser -{ - /** - * READ-ONLY: Maps BUILT-IN string function names to AST class names. - * - * @var array - */ - private static $_STRING_FUNCTIONS = [ - 'concat' => Functions\ConcatFunction::class, - 'substring' => Functions\SubstringFunction::class, - 'trim' => Functions\TrimFunction::class, - 'lower' => Functions\LowerFunction::class, - 'upper' => Functions\UpperFunction::class, - 'identity' => Functions\IdentityFunction::class, - ]; - - /** - * READ-ONLY: Maps BUILT-IN numeric function names to AST class names. - * - * @var array - */ - private static $_NUMERIC_FUNCTIONS = [ - 'length' => Functions\LengthFunction::class, - 'locate' => Functions\LocateFunction::class, - 'abs' => Functions\AbsFunction::class, - 'sqrt' => Functions\SqrtFunction::class, - 'mod' => Functions\ModFunction::class, - 'size' => Functions\SizeFunction::class, - 'date_diff' => Functions\DateDiffFunction::class, - 'bit_and' => Functions\BitAndFunction::class, - 'bit_or' => Functions\BitOrFunction::class, - - // Aggregate functions - 'min' => Functions\MinFunction::class, - 'max' => Functions\MaxFunction::class, - 'avg' => Functions\AvgFunction::class, - 'sum' => Functions\SumFunction::class, - 'count' => Functions\CountFunction::class, - ]; - - /** - * READ-ONLY: Maps BUILT-IN datetime function names to AST class names. - * - * @var array - */ - private static $_DATETIME_FUNCTIONS = [ - 'current_date' => Functions\CurrentDateFunction::class, - 'current_time' => Functions\CurrentTimeFunction::class, - 'current_timestamp' => Functions\CurrentTimestampFunction::class, - 'date_add' => Functions\DateAddFunction::class, - 'date_sub' => Functions\DateSubFunction::class, - ]; - - /* - * Expressions that were encountered during parsing of identifiers and expressions - * and still need to be validated. - */ - - /** - * @var array - */ - private $deferredIdentificationVariables = []; - - /** - * @var array - */ - private $deferredPartialObjectExpressions = []; - - /** - * @var array - */ - private $deferredPathExpressions = []; - - /** - * @var array - */ - private $deferredResultVariables = []; - - /** - * @var array - */ - private $deferredNewObjectExpressions = []; - - /** - * The lexer. - * - * @var \Doctrine\ORM\Query\Lexer - */ - private $lexer; - - /** - * The parser result. - * - * @var \Doctrine\ORM\Query\ParserResult - */ - private $parserResult; - - /** - * The EntityManager. - * - * @var \Doctrine\ORM\EntityManager - */ - private $em; - - /** - * The Query to parse. - * - * @var Query - */ - private $query; - - /** - * Map of declared query components in the parsed query. - * - * @var array - */ - private $queryComponents = []; - - /** - * Keeps the nesting level of defined ResultVariables. - * - * @var integer - */ - private $nestingLevel = 0; - - /** - * Any additional custom tree walkers that modify the AST. - * - * @var array - */ - private $customTreeWalkers = []; - - /** - * The custom last tree walker, if any, that is responsible for producing the output. - * - * @var TreeWalker - */ - private $customOutputWalker; - - /** - * @var array - */ - private $identVariableExpressions = []; - - /** - * Creates a new query parser object. - * - * @param Query $query The Query to parse. - */ - public function __construct(Query $query) - { - $this->query = $query; - $this->em = $query->getEntityManager(); - $this->lexer = new Lexer($query->getDQL()); - $this->parserResult = new ParserResult(); - } - - /** - * Sets a custom tree walker that produces output. - * This tree walker will be run last over the AST, after any other walkers. - * - * @param string $className - * - * @return void - */ - public function setCustomOutputTreeWalker($className) - { - $this->customOutputWalker = $className; - } - - /** - * Adds a custom tree walker for modifying the AST. - * - * @param string $className - * - * @return void - */ - public function addCustomTreeWalker($className) - { - $this->customTreeWalkers[] = $className; - } - - /** - * Gets the lexer used by the parser. - * - * @return \Doctrine\ORM\Query\Lexer - */ - public function getLexer() - { - return $this->lexer; - } - - /** - * Gets the ParserResult that is being filled with information during parsing. - * - * @return \Doctrine\ORM\Query\ParserResult - */ - public function getParserResult() - { - return $this->parserResult; - } - - /** - * Gets the EntityManager used by the parser. - * - * @return \Doctrine\ORM\EntityManager - */ - public function getEntityManager() - { - return $this->em; - } - - /** - * Parses and builds AST for the given Query. - * - * @return \Doctrine\ORM\Query\AST\SelectStatement | - * \Doctrine\ORM\Query\AST\UpdateStatement | - * \Doctrine\ORM\Query\AST\DeleteStatement - */ - public function getAST() - { - // Parse & build AST - $AST = $this->QueryLanguage(); - - // Process any deferred validations of some nodes in the AST. - // This also allows post-processing of the AST for modification purposes. - $this->processDeferredIdentificationVariables(); - - if ($this->deferredPartialObjectExpressions) { - $this->processDeferredPartialObjectExpressions(); - } - - if ($this->deferredPathExpressions) { - $this->processDeferredPathExpressions(); - } - - if ($this->deferredResultVariables) { - $this->processDeferredResultVariables(); - } - - if ($this->deferredNewObjectExpressions) { - $this->processDeferredNewObjectExpressions($AST); - } - - $this->processRootEntityAliasSelected(); - - // TODO: Is there a way to remove this? It may impact the mixed hydration resultset a lot! - $this->fixIdentificationVariableOrder($AST); - - return $AST; - } - - /** - * 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 The token type. - * - * @return void - * - * @throws QueryException If the tokens don't match. - */ - public function match($token) - { - $lookaheadType = $this->lexer->lookahead['type']; - - // Short-circuit on first condition, usually types match - if ($lookaheadType === $token) { - $this->lexer->moveNext(); - return; - } - - // If parameter is not identifier (1-99) must be exact match - if ($token < Lexer::T_IDENTIFIER) { - $this->syntaxError($this->lexer->getLiteral($token)); - } - - // If parameter is keyword (200+) must be exact match - if ($token > Lexer::T_IDENTIFIER) { - $this->syntaxError($this->lexer->getLiteral($token)); - } - - // If parameter is T_IDENTIFIER, then matches T_IDENTIFIER (100) and keywords (200+) - if ($token === Lexer::T_IDENTIFIER && $lookaheadType < Lexer::T_IDENTIFIER) { - $this->syntaxError($this->lexer->getLiteral($token)); - } - - $this->lexer->moveNext(); - } - - /** - * Frees this parser, enabling it to be reused. - * - * @param boolean $deep Whether to clean peek and reset errors. - * @param integer $position Position to reset. - * - * @return void - */ - public function free($deep = false, $position = 0) - { - // WARNING! Use this method with care. It resets the scanner! - $this->lexer->resetPosition($position); - - // Deep = true cleans peek and also any previously defined errors - if ($deep) { - $this->lexer->resetPeek(); - } - - $this->lexer->token = null; - $this->lexer->lookahead = null; - } - - /** - * Parses a query string. - * - * @return ParserResult - */ - public function parse() - { - $AST = $this->getAST(); - - if (($customWalkers = $this->query->getHint(Query::HINT_CUSTOM_TREE_WALKERS)) !== false) { - $this->customTreeWalkers = $customWalkers; - } - - if (($customOutputWalker = $this->query->getHint(Query::HINT_CUSTOM_OUTPUT_WALKER)) !== false) { - $this->customOutputWalker = $customOutputWalker; - } - - // Run any custom tree walkers over the AST - if ($this->customTreeWalkers) { - $treeWalkerChain = new TreeWalkerChain($this->query, $this->parserResult, $this->queryComponents); - - foreach ($this->customTreeWalkers as $walker) { - $treeWalkerChain->addTreeWalker($walker); - } - - switch (true) { - case ($AST instanceof AST\UpdateStatement): - $treeWalkerChain->walkUpdateStatement($AST); - break; - - case ($AST instanceof AST\DeleteStatement): - $treeWalkerChain->walkDeleteStatement($AST); - break; - - case ($AST instanceof AST\SelectStatement): - default: - $treeWalkerChain->walkSelectStatement($AST); - } - - $this->queryComponents = $treeWalkerChain->getQueryComponents(); - } - - $outputWalkerClass = $this->customOutputWalker ?: SqlWalker::class; - $outputWalker = new $outputWalkerClass($this->query, $this->parserResult, $this->queryComponents); - - // Assign an SQL executor to the parser result - $this->parserResult->setSqlExecutor($outputWalker->getExecutor($AST)); - - return $this->parserResult; - } - - /** - * Fixes order of identification variables. - * - * They have to appear in the select clause in the same order as the - * declarations (from ... x join ... y join ... z ...) appear in the query - * as the hydration process relies on that order for proper operation. - * - * @param AST\SelectStatement|AST\DeleteStatement|AST\UpdateStatement $AST - * - * @return void - */ - private function fixIdentificationVariableOrder($AST) - { - if (count($this->identVariableExpressions) <= 1) { - return; - } - - foreach ($this->queryComponents as $dqlAlias => $qComp) { - if ( ! isset($this->identVariableExpressions[$dqlAlias])) { - continue; - } - - $expr = $this->identVariableExpressions[$dqlAlias]; - $key = array_search($expr, $AST->selectClause->selectExpressions); - - unset($AST->selectClause->selectExpressions[$key]); - - $AST->selectClause->selectExpressions[] = $expr; - } - } - - /** - * Generates a new syntax error. - * - * @param string $expected Expected string. - * @param array|null $token Got token. - * - * @return void - * - * @throws \Doctrine\ORM\Query\QueryException - */ - public function syntaxError($expected = '', $token = null) - { - if ($token === null) { - $token = $this->lexer->lookahead; - } - - $tokenPos = (isset($token['position'])) ? $token['position'] : '-1'; - - $message = "line 0, col {$tokenPos}: Error: "; - $message .= ($expected !== '') ? "Expected {$expected}, got " : 'Unexpected '; - $message .= ($this->lexer->lookahead === null) ? 'end of string.' : "'{$token['value']}'"; - - throw QueryException::syntaxError($message, QueryException::dqlError($this->query->getDQL())); - } - - /** - * Generates a new semantical error. - * - * @param string $message Optional message. - * @param array|null $token Optional token. - * - * @return void - * - * @throws \Doctrine\ORM\Query\QueryException - */ - public function semanticalError($message = '', $token = null) - { - if ($token === null) { - $token = $this->lexer->lookahead ?? ['position' => null]; - } - - // Minimum exposed chars ahead of token - $distance = 12; - - // Find a position of a final word to display in error string - $dql = $this->query->getDQL(); - $length = strlen($dql); - $pos = $token['position'] + $distance; - $pos = strpos($dql, ' ', ($length > $pos) ? $pos : $length); - $length = ($pos !== false) ? $pos - $token['position'] : $distance; - - $tokenPos = (isset($token['position']) && $token['position'] > 0) ? $token['position'] : '-1'; - $tokenStr = substr($dql, $token['position'], $length); - - // Building informative message - $message = 'line 0, col ' . $tokenPos . " near '" . $tokenStr . "': Error: " . $message; - - throw QueryException::semanticalError($message, QueryException::dqlError($this->query->getDQL())); - } - - /** - * Peeks beyond the matched closing parenthesis and returns the first token after that one. - * - * @param boolean $resetPeek Reset peek after finding the closing parenthesis. - * - * @return array - */ - private function peekBeyondClosingParenthesis($resetPeek = true) - { - $token = $this->lexer->peek(); - $numUnmatched = 1; - - while ($numUnmatched > 0 && $token !== null) { - switch ($token['type']) { - case Lexer::T_OPEN_PARENTHESIS: - ++$numUnmatched; - break; - - case Lexer::T_CLOSE_PARENTHESIS: - --$numUnmatched; - break; - - default: - // Do nothing - } - - $token = $this->lexer->peek(); - } - - if ($resetPeek) { - $this->lexer->resetPeek(); - } - - return $token; - } - - /** - * Checks if the given token indicates a mathematical operator. - * - * @param array $token - * - * @return boolean TRUE if the token is a mathematical operator, FALSE otherwise. - */ - private function isMathOperator($token) - { - return $token !== null && in_array($token['type'], [Lexer::T_PLUS, Lexer::T_MINUS, Lexer::T_DIVIDE, Lexer::T_MULTIPLY]); - } - - /** - * Checks if the next-next (after lookahead) token starts a function. - * - * @return boolean TRUE if the next-next tokens start a function, FALSE otherwise. - */ - private function isFunction() - { - $lookaheadType = $this->lexer->lookahead['type']; - $peek = $this->lexer->peek(); - - $this->lexer->resetPeek(); - - return $lookaheadType >= Lexer::T_IDENTIFIER && $peek !== null && $peek['type'] === Lexer::T_OPEN_PARENTHESIS; - } - - /** - * Checks whether the given token type indicates an aggregate function. - * - * @param int $tokenType - * - * @return boolean TRUE if the token type is an aggregate function, FALSE otherwise. - */ - private function isAggregateFunction($tokenType) - { - return in_array($tokenType, [Lexer::T_AVG, Lexer::T_MIN, Lexer::T_MAX, Lexer::T_SUM, Lexer::T_COUNT]); - } - - /** - * Checks whether the current lookahead token of the lexer has the type T_ALL, T_ANY or T_SOME. - * - * @return boolean - */ - private function isNextAllAnySome() - { - return in_array($this->lexer->lookahead['type'], [Lexer::T_ALL, Lexer::T_ANY, Lexer::T_SOME]); - } - - /** - * Validates that the given IdentificationVariable is semantically correct. - * It must exist in query components list. - * - * @return void - */ - private function processDeferredIdentificationVariables() - { - foreach ($this->deferredIdentificationVariables as $deferredItem) { - $identVariable = $deferredItem['expression']; - - // Check if IdentificationVariable exists in queryComponents - if ( ! isset($this->queryComponents[$identVariable])) { - $this->semanticalError( - "'$identVariable' is not defined.", $deferredItem['token'] - ); - } - - $qComp = $this->queryComponents[$identVariable]; - - // Check if queryComponent points to an AbstractSchemaName or a ResultVariable - if ( ! isset($qComp['metadata'])) { - $this->semanticalError( - "'$identVariable' does not point to a Class.", $deferredItem['token'] - ); - } - - // Validate if identification variable nesting level is lower or equal than the current one - if ($qComp['nestingLevel'] > $deferredItem['nestingLevel']) { - $this->semanticalError( - "'$identVariable' is used outside the scope of its declaration.", $deferredItem['token'] - ); - } - } - } - - /** - * Validates that the given NewObjectExpression. - * - * @param \Doctrine\ORM\Query\AST\SelectClause $AST - * - * @return void - */ - private function processDeferredNewObjectExpressions($AST) - { - foreach ($this->deferredNewObjectExpressions as $deferredItem) { - $expression = $deferredItem['expression']; - $token = $deferredItem['token']; - $className = $expression->className; - $args = $expression->args; - $fromClassName = isset($AST->fromClause->identificationVariableDeclarations[0]->rangeVariableDeclaration->abstractSchemaName) - ? $AST->fromClause->identificationVariableDeclarations[0]->rangeVariableDeclaration->abstractSchemaName - : null; - - // If the namespace is not given then assumes the first FROM entity namespace - if (strpos($className, '\\') === false && ! class_exists($className) && strpos($fromClassName, '\\') !== false) { - $namespace = substr($fromClassName, 0, strrpos($fromClassName, '\\')); - $fqcn = $namespace . '\\' . $className; - - if (class_exists($fqcn)) { - $expression->className = $fqcn; - $className = $fqcn; - } - } - - if ( ! class_exists($className)) { - $this->semanticalError(sprintf('Class "%s" is not defined.', $className), $token); - } - - $class = new \ReflectionClass($className); - - if ( ! $class->isInstantiable()) { - $this->semanticalError(sprintf('Class "%s" can not be instantiated.', $className), $token); - } - - if ($class->getConstructor() === null) { - $this->semanticalError(sprintf('Class "%s" has not a valid constructor.', $className), $token); - } - - if ($class->getConstructor()->getNumberOfRequiredParameters() > count($args)) { - $this->semanticalError(sprintf('Number of arguments does not match with "%s" constructor declaration.', $className), $token); - } - } - } - - /** - * Validates that the given PartialObjectExpression is semantically correct. - * It must exist in query components list. - * - * @return void - */ - private function processDeferredPartialObjectExpressions() - { - foreach ($this->deferredPartialObjectExpressions as $deferredItem) { - $expr = $deferredItem['expression']; - $class = $this->queryComponents[$expr->identificationVariable]['metadata']; - - foreach ($expr->partialFieldSet as $field) { - if (isset($class->fieldMappings[$field])) { - continue; - } - - if (isset($class->associationMappings[$field]) && - $class->associationMappings[$field]['isOwningSide'] && - $class->associationMappings[$field]['type'] & ClassMetadata::TO_ONE) { - continue; - } - - $this->semanticalError( - "There is no mapped field named '$field' on class " . $class->name . ".", $deferredItem['token'] - ); - } - - if (array_intersect($class->identifier, $expr->partialFieldSet) != $class->identifier) { - $this->semanticalError( - "The partial field selection of class " . $class->name . " must contain the identifier.", - $deferredItem['token'] - ); - } - } - } - - /** - * Validates that the given ResultVariable is semantically correct. - * It must exist in query components list. - * - * @return void - */ - private function processDeferredResultVariables() - { - foreach ($this->deferredResultVariables as $deferredItem) { - $resultVariable = $deferredItem['expression']; - - // Check if ResultVariable exists in queryComponents - if ( ! isset($this->queryComponents[$resultVariable])) { - $this->semanticalError( - "'$resultVariable' is not defined.", $deferredItem['token'] - ); - } - - $qComp = $this->queryComponents[$resultVariable]; - - // Check if queryComponent points to an AbstractSchemaName or a ResultVariable - if ( ! isset($qComp['resultVariable'])) { - $this->semanticalError( - "'$resultVariable' does not point to a ResultVariable.", $deferredItem['token'] - ); - } - - // Validate if identification variable nesting level is lower or equal than the current one - if ($qComp['nestingLevel'] > $deferredItem['nestingLevel']) { - $this->semanticalError( - "'$resultVariable' is used outside the scope of its declaration.", $deferredItem['token'] - ); - } - } - } - - /** - * Validates that the given PathExpression is semantically correct for grammar rules: - * - * AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression - * SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression - * StateFieldPathExpression ::= IdentificationVariable "." StateField - * SingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField - * CollectionValuedPathExpression ::= IdentificationVariable "." CollectionValuedAssociationField - * - * @return void - */ - private function processDeferredPathExpressions() - { - foreach ($this->deferredPathExpressions as $deferredItem) { - $pathExpression = $deferredItem['expression']; - - $qComp = $this->queryComponents[$pathExpression->identificationVariable]; - $class = $qComp['metadata']; - - if (($field = $pathExpression->field) === null) { - $field = $pathExpression->field = $class->identifier[0]; - } - - // Check if field or association exists - if ( ! isset($class->associationMappings[$field]) && ! isset($class->fieldMappings[$field])) { - $this->semanticalError( - 'Class ' . $class->name . ' has no field or association named ' . $field, - $deferredItem['token'] - ); - } - - $fieldType = AST\PathExpression::TYPE_STATE_FIELD; - - if (isset($class->associationMappings[$field])) { - $assoc = $class->associationMappings[$field]; - - $fieldType = ($assoc['type'] & ClassMetadata::TO_ONE) - ? AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION - : AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION; - } - - // Validate if PathExpression is one of the expected types - $expectedType = $pathExpression->expectedType; - - if ( ! ($expectedType & $fieldType)) { - // We need to recognize which was expected type(s) - $expectedStringTypes = []; - - // Validate state field type - if ($expectedType & AST\PathExpression::TYPE_STATE_FIELD) { - $expectedStringTypes[] = 'StateFieldPathExpression'; - } - - // Validate single valued association (*-to-one) - if ($expectedType & AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION) { - $expectedStringTypes[] = 'SingleValuedAssociationField'; - } - - // Validate single valued association (*-to-many) - if ($expectedType & AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION) { - $expectedStringTypes[] = 'CollectionValuedAssociationField'; - } - - // Build the error message - $semanticalError = 'Invalid PathExpression. '; - $semanticalError .= (count($expectedStringTypes) == 1) - ? 'Must be a ' . $expectedStringTypes[0] . '.' - : implode(' or ', $expectedStringTypes) . ' expected.'; - - $this->semanticalError($semanticalError, $deferredItem['token']); - } - - // We need to force the type in PathExpression - $pathExpression->type = $fieldType; - } - } - - /** - * @return void - */ - private function processRootEntityAliasSelected() - { - if ( ! count($this->identVariableExpressions)) { - return; - } - - foreach ($this->identVariableExpressions as $dqlAlias => $expr) { - if (isset($this->queryComponents[$dqlAlias]) && $this->queryComponents[$dqlAlias]['parent'] === null) { - return; - } - } - - $this->semanticalError('Cannot select entity through identification variables without choosing at least one root entity alias.'); - } - - /** - * QueryLanguage ::= SelectStatement | UpdateStatement | DeleteStatement - * - * @return \Doctrine\ORM\Query\AST\SelectStatement | - * \Doctrine\ORM\Query\AST\UpdateStatement | - * \Doctrine\ORM\Query\AST\DeleteStatement - */ - public function QueryLanguage() - { - $statement = null; - - $this->lexer->moveNext(); - - switch ($this->lexer->lookahead['type'] ?? null) { - case Lexer::T_SELECT: - $statement = $this->SelectStatement(); - break; - - case Lexer::T_UPDATE: - $statement = $this->UpdateStatement(); - break; - - case Lexer::T_DELETE: - $statement = $this->DeleteStatement(); - break; - - default: - $this->syntaxError('SELECT, UPDATE or DELETE'); - break; - } - - // Check for end of string - if ($this->lexer->lookahead !== null) { - $this->syntaxError('end of string'); - } - - return $statement; - } - - /** - * SelectStatement ::= SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] - * - * @return \Doctrine\ORM\Query\AST\SelectStatement - */ - public function SelectStatement() - { - $selectStatement = new AST\SelectStatement($this->SelectClause(), $this->FromClause()); - - $selectStatement->whereClause = $this->lexer->isNextToken(Lexer::T_WHERE) ? $this->WhereClause() : null; - $selectStatement->groupByClause = $this->lexer->isNextToken(Lexer::T_GROUP) ? $this->GroupByClause() : null; - $selectStatement->havingClause = $this->lexer->isNextToken(Lexer::T_HAVING) ? $this->HavingClause() : null; - $selectStatement->orderByClause = $this->lexer->isNextToken(Lexer::T_ORDER) ? $this->OrderByClause() : null; - - return $selectStatement; - } - - /** - * UpdateStatement ::= UpdateClause [WhereClause] - * - * @return \Doctrine\ORM\Query\AST\UpdateStatement - */ - public function UpdateStatement() - { - $updateStatement = new AST\UpdateStatement($this->UpdateClause()); - - $updateStatement->whereClause = $this->lexer->isNextToken(Lexer::T_WHERE) ? $this->WhereClause() : null; - - return $updateStatement; - } - - /** - * DeleteStatement ::= DeleteClause [WhereClause] - * - * @return \Doctrine\ORM\Query\AST\DeleteStatement - */ - public function DeleteStatement() - { - $deleteStatement = new AST\DeleteStatement($this->DeleteClause()); - - $deleteStatement->whereClause = $this->lexer->isNextToken(Lexer::T_WHERE) ? $this->WhereClause() : null; - - return $deleteStatement; - } - - /** - * IdentificationVariable ::= identifier - * - * @return string - */ - public function IdentificationVariable() - { - $this->match(Lexer::T_IDENTIFIER); - - $identVariable = $this->lexer->token['value']; - - $this->deferredIdentificationVariables[] = [ - 'expression' => $identVariable, - 'nestingLevel' => $this->nestingLevel, - 'token' => $this->lexer->token, - ]; - - return $identVariable; - } - - /** - * AliasIdentificationVariable = identifier - * - * @return string - */ - public function AliasIdentificationVariable() - { - $this->match(Lexer::T_IDENTIFIER); - - $aliasIdentVariable = $this->lexer->token['value']; - $exists = isset($this->queryComponents[$aliasIdentVariable]); - - if ($exists) { - $this->semanticalError("'$aliasIdentVariable' is already defined.", $this->lexer->token); - } - - return $aliasIdentVariable; - } - - /** - * AbstractSchemaName ::= fully_qualified_name | aliased_name | identifier - * - * @return string - */ - public function AbstractSchemaName() - { - if ($this->lexer->isNextToken(Lexer::T_FULLY_QUALIFIED_NAME)) { - $this->match(Lexer::T_FULLY_QUALIFIED_NAME); - - return $this->lexer->token['value']; - } - - if ($this->lexer->isNextToken(Lexer::T_IDENTIFIER)) { - $this->match(Lexer::T_IDENTIFIER); - - return $this->lexer->token['value']; - } - - $this->match(Lexer::T_ALIASED_NAME); - - [$namespaceAlias, $simpleClassName] = explode(':', $this->lexer->token['value']); - - return $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName; - } - - /** - * Validates an AbstractSchemaName, making sure the class exists. - * - * @param string $schemaName The name to validate. - * - * @throws QueryException if the name does not exist. - */ - private function validateAbstractSchemaName($schemaName) - { - if (! (class_exists($schemaName, true) || interface_exists($schemaName, true))) { - $this->semanticalError("Class '$schemaName' is not defined.", $this->lexer->token); - } - } - - /** - * AliasResultVariable ::= identifier - * - * @return string - */ - public function AliasResultVariable() - { - $this->match(Lexer::T_IDENTIFIER); - - $resultVariable = $this->lexer->token['value']; - $exists = isset($this->queryComponents[$resultVariable]); - - if ($exists) { - $this->semanticalError("'$resultVariable' is already defined.", $this->lexer->token); - } - - return $resultVariable; - } - - /** - * ResultVariable ::= identifier - * - * @return string - */ - public function ResultVariable() - { - $this->match(Lexer::T_IDENTIFIER); - - $resultVariable = $this->lexer->token['value']; - - // Defer ResultVariable validation - $this->deferredResultVariables[] = [ - 'expression' => $resultVariable, - 'nestingLevel' => $this->nestingLevel, - 'token' => $this->lexer->token, - ]; - - return $resultVariable; - } - - /** - * JoinAssociationPathExpression ::= IdentificationVariable "." (CollectionValuedAssociationField | SingleValuedAssociationField) - * - * @return \Doctrine\ORM\Query\AST\JoinAssociationPathExpression - */ - public function JoinAssociationPathExpression() - { - $identVariable = $this->IdentificationVariable(); - - if ( ! isset($this->queryComponents[$identVariable])) { - $this->semanticalError( - 'Identification Variable ' . $identVariable .' used in join path expression but was not defined before.' - ); - } - - $this->match(Lexer::T_DOT); - $this->match(Lexer::T_IDENTIFIER); - - $field = $this->lexer->token['value']; - - // Validate association field - $qComp = $this->queryComponents[$identVariable]; - $class = $qComp['metadata']; - - if ( ! $class->hasAssociation($field)) { - $this->semanticalError('Class ' . $class->name . ' has no association named ' . $field); - } - - return new AST\JoinAssociationPathExpression($identVariable, $field); - } - - /** - * Parses an arbitrary path expression and defers semantical validation - * based on expected types. - * - * PathExpression ::= IdentificationVariable {"." identifier}* - * - * @param integer $expectedTypes - * - * @return \Doctrine\ORM\Query\AST\PathExpression - */ - public function PathExpression($expectedTypes) - { - $identVariable = $this->IdentificationVariable(); - $field = null; - - if ($this->lexer->isNextToken(Lexer::T_DOT)) { - $this->match(Lexer::T_DOT); - $this->match(Lexer::T_IDENTIFIER); - - $field = $this->lexer->token['value']; - - while ($this->lexer->isNextToken(Lexer::T_DOT)) { - $this->match(Lexer::T_DOT); - $this->match(Lexer::T_IDENTIFIER); - $field .= '.'.$this->lexer->token['value']; - } - } - - // Creating AST node - $pathExpr = new AST\PathExpression($expectedTypes, $identVariable, $field); - - // Defer PathExpression validation if requested to be deferred - $this->deferredPathExpressions[] = [ - 'expression' => $pathExpr, - 'nestingLevel' => $this->nestingLevel, - 'token' => $this->lexer->token, - ]; - - return $pathExpr; - } - - /** - * AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression - * - * @return \Doctrine\ORM\Query\AST\PathExpression - */ - public function AssociationPathExpression() - { - return $this->PathExpression( - AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION | - AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION - ); - } - - /** - * SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression - * - * @return \Doctrine\ORM\Query\AST\PathExpression - */ - public function SingleValuedPathExpression() - { - return $this->PathExpression( - AST\PathExpression::TYPE_STATE_FIELD | - AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION - ); - } - - /** - * StateFieldPathExpression ::= IdentificationVariable "." StateField - * - * @return \Doctrine\ORM\Query\AST\PathExpression - */ - public function StateFieldPathExpression() - { - return $this->PathExpression(AST\PathExpression::TYPE_STATE_FIELD); - } - - /** - * SingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField - * - * @return \Doctrine\ORM\Query\AST\PathExpression - */ - public function SingleValuedAssociationPathExpression() - { - return $this->PathExpression(AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION); - } - - /** - * CollectionValuedPathExpression ::= IdentificationVariable "." CollectionValuedAssociationField - * - * @return \Doctrine\ORM\Query\AST\PathExpression - */ - public function CollectionValuedPathExpression() - { - return $this->PathExpression(AST\PathExpression::TYPE_COLLECTION_VALUED_ASSOCIATION); - } - - /** - * SelectClause ::= "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression} - * - * @return \Doctrine\ORM\Query\AST\SelectClause - */ - public function SelectClause() - { - $isDistinct = false; - $this->match(Lexer::T_SELECT); - - // Check for DISTINCT - if ($this->lexer->isNextToken(Lexer::T_DISTINCT)) { - $this->match(Lexer::T_DISTINCT); - - $isDistinct = true; - } - - // Process SelectExpressions (1..N) - $selectExpressions = []; - $selectExpressions[] = $this->SelectExpression(); - - while ($this->lexer->isNextToken(Lexer::T_COMMA)) { - $this->match(Lexer::T_COMMA); - - $selectExpressions[] = $this->SelectExpression(); - } - - return new AST\SelectClause($selectExpressions, $isDistinct); - } - - /** - * SimpleSelectClause ::= "SELECT" ["DISTINCT"] SimpleSelectExpression - * - * @return \Doctrine\ORM\Query\AST\SimpleSelectClause - */ - public function SimpleSelectClause() - { - $isDistinct = false; - $this->match(Lexer::T_SELECT); - - if ($this->lexer->isNextToken(Lexer::T_DISTINCT)) { - $this->match(Lexer::T_DISTINCT); - - $isDistinct = true; - } - - return new AST\SimpleSelectClause($this->SimpleSelectExpression(), $isDistinct); - } - - /** - * UpdateClause ::= "UPDATE" AbstractSchemaName ["AS"] AliasIdentificationVariable "SET" UpdateItem {"," UpdateItem}* - * - * @return \Doctrine\ORM\Query\AST\UpdateClause - */ - public function UpdateClause() - { - $this->match(Lexer::T_UPDATE); - - $token = $this->lexer->lookahead; - $abstractSchemaName = $this->AbstractSchemaName(); - - $this->validateAbstractSchemaName($abstractSchemaName); - - if ($this->lexer->isNextToken(Lexer::T_AS)) { - $this->match(Lexer::T_AS); - } - - $aliasIdentificationVariable = $this->AliasIdentificationVariable(); - - $class = $this->em->getClassMetadata($abstractSchemaName); - - // Building queryComponent - $queryComponent = [ - 'metadata' => $class, - 'parent' => null, - 'relation' => null, - 'map' => null, - 'nestingLevel' => $this->nestingLevel, - 'token' => $token, - ]; - - $this->queryComponents[$aliasIdentificationVariable] = $queryComponent; - - $this->match(Lexer::T_SET); - - $updateItems = []; - $updateItems[] = $this->UpdateItem(); - - while ($this->lexer->isNextToken(Lexer::T_COMMA)) { - $this->match(Lexer::T_COMMA); - - $updateItems[] = $this->UpdateItem(); - } - - $updateClause = new AST\UpdateClause($abstractSchemaName, $updateItems); - $updateClause->aliasIdentificationVariable = $aliasIdentificationVariable; - - return $updateClause; - } - - /** - * DeleteClause ::= "DELETE" ["FROM"] AbstractSchemaName ["AS"] AliasIdentificationVariable - * - * @return \Doctrine\ORM\Query\AST\DeleteClause - */ - public function DeleteClause() - { - $this->match(Lexer::T_DELETE); - - if ($this->lexer->isNextToken(Lexer::T_FROM)) { - $this->match(Lexer::T_FROM); - } - - $token = $this->lexer->lookahead; - $abstractSchemaName = $this->AbstractSchemaName(); - - $this->validateAbstractSchemaName($abstractSchemaName); - - $deleteClause = new AST\DeleteClause($abstractSchemaName); - - if ($this->lexer->isNextToken(Lexer::T_AS)) { - $this->match(Lexer::T_AS); - } - - $aliasIdentificationVariable = $this->lexer->isNextToken(Lexer::T_IDENTIFIER) - ? $this->AliasIdentificationVariable() - : 'alias_should_have_been_set'; - - $deleteClause->aliasIdentificationVariable = $aliasIdentificationVariable; - $class = $this->em->getClassMetadata($deleteClause->abstractSchemaName); - - // Building queryComponent - $queryComponent = [ - 'metadata' => $class, - 'parent' => null, - 'relation' => null, - 'map' => null, - 'nestingLevel' => $this->nestingLevel, - 'token' => $token, - ]; - - $this->queryComponents[$aliasIdentificationVariable] = $queryComponent; - - return $deleteClause; - } - - /** - * FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}* - * - * @return \Doctrine\ORM\Query\AST\FromClause - */ - public function FromClause() - { - $this->match(Lexer::T_FROM); - - $identificationVariableDeclarations = []; - $identificationVariableDeclarations[] = $this->IdentificationVariableDeclaration(); - - while ($this->lexer->isNextToken(Lexer::T_COMMA)) { - $this->match(Lexer::T_COMMA); - - $identificationVariableDeclarations[] = $this->IdentificationVariableDeclaration(); - } - - return new AST\FromClause($identificationVariableDeclarations); - } - - /** - * SubselectFromClause ::= "FROM" SubselectIdentificationVariableDeclaration {"," SubselectIdentificationVariableDeclaration}* - * - * @return \Doctrine\ORM\Query\AST\SubselectFromClause - */ - public function SubselectFromClause() - { - $this->match(Lexer::T_FROM); - - $identificationVariables = []; - $identificationVariables[] = $this->SubselectIdentificationVariableDeclaration(); - - while ($this->lexer->isNextToken(Lexer::T_COMMA)) { - $this->match(Lexer::T_COMMA); - - $identificationVariables[] = $this->SubselectIdentificationVariableDeclaration(); - } - - return new AST\SubselectFromClause($identificationVariables); - } - - /** - * WhereClause ::= "WHERE" ConditionalExpression - * - * @return \Doctrine\ORM\Query\AST\WhereClause - */ - public function WhereClause() - { - $this->match(Lexer::T_WHERE); - - return new AST\WhereClause($this->ConditionalExpression()); - } - - /** - * HavingClause ::= "HAVING" ConditionalExpression - * - * @return \Doctrine\ORM\Query\AST\HavingClause - */ - public function HavingClause() - { - $this->match(Lexer::T_HAVING); - - return new AST\HavingClause($this->ConditionalExpression()); - } - - /** - * GroupByClause ::= "GROUP" "BY" GroupByItem {"," GroupByItem}* - * - * @return \Doctrine\ORM\Query\AST\GroupByClause - */ - public function GroupByClause() - { - $this->match(Lexer::T_GROUP); - $this->match(Lexer::T_BY); - - $groupByItems = [$this->GroupByItem()]; - - while ($this->lexer->isNextToken(Lexer::T_COMMA)) { - $this->match(Lexer::T_COMMA); - - $groupByItems[] = $this->GroupByItem(); - } - - return new AST\GroupByClause($groupByItems); - } - - /** - * OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}* - * - * @return \Doctrine\ORM\Query\AST\OrderByClause - */ - public function OrderByClause() - { - $this->match(Lexer::T_ORDER); - $this->match(Lexer::T_BY); - - $orderByItems = []; - $orderByItems[] = $this->OrderByItem(); - - while ($this->lexer->isNextToken(Lexer::T_COMMA)) { - $this->match(Lexer::T_COMMA); - - $orderByItems[] = $this->OrderByItem(); - } - - return new AST\OrderByClause($orderByItems); - } - - /** - * Subselect ::= SimpleSelectClause SubselectFromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] - * - * @return \Doctrine\ORM\Query\AST\Subselect - */ - public function Subselect() - { - // Increase query nesting level - $this->nestingLevel++; - - $subselect = new AST\Subselect($this->SimpleSelectClause(), $this->SubselectFromClause()); - - $subselect->whereClause = $this->lexer->isNextToken(Lexer::T_WHERE) ? $this->WhereClause() : null; - $subselect->groupByClause = $this->lexer->isNextToken(Lexer::T_GROUP) ? $this->GroupByClause() : null; - $subselect->havingClause = $this->lexer->isNextToken(Lexer::T_HAVING) ? $this->HavingClause() : null; - $subselect->orderByClause = $this->lexer->isNextToken(Lexer::T_ORDER) ? $this->OrderByClause() : null; - - // Decrease query nesting level - $this->nestingLevel--; - - return $subselect; - } - - /** - * UpdateItem ::= SingleValuedPathExpression "=" NewValue - * - * @return \Doctrine\ORM\Query\AST\UpdateItem - */ - public function UpdateItem() - { - $pathExpr = $this->SingleValuedPathExpression(); - - $this->match(Lexer::T_EQUALS); - - $updateItem = new AST\UpdateItem($pathExpr, $this->NewValue()); - - return $updateItem; - } - - /** - * GroupByItem ::= IdentificationVariable | ResultVariable | SingleValuedPathExpression - * - * @return string | \Doctrine\ORM\Query\AST\PathExpression - */ - public function GroupByItem() - { - // We need to check if we are in a IdentificationVariable or SingleValuedPathExpression - $glimpse = $this->lexer->glimpse(); - - if ($glimpse !== null && $glimpse['type'] === Lexer::T_DOT) { - return $this->SingleValuedPathExpression(); - } - - // Still need to decide between IdentificationVariable or ResultVariable - $lookaheadValue = $this->lexer->lookahead['value']; - - if ( ! isset($this->queryComponents[$lookaheadValue])) { - $this->semanticalError('Cannot group by undefined identification or result variable.'); - } - - return (isset($this->queryComponents[$lookaheadValue]['metadata'])) - ? $this->IdentificationVariable() - : $this->ResultVariable(); - } - - /** - * OrderByItem ::= ( - * SimpleArithmeticExpression | SingleValuedPathExpression | - * ScalarExpression | ResultVariable | FunctionDeclaration - * ) ["ASC" | "DESC"] - * - * @return \Doctrine\ORM\Query\AST\OrderByItem - */ - public function OrderByItem() - { - $this->lexer->peek(); // lookahead => '.' - $this->lexer->peek(); // lookahead => token after '.' - - $peek = $this->lexer->peek(); // lookahead => token after the token after the '.' - - $this->lexer->resetPeek(); - - $glimpse = $this->lexer->glimpse(); - - switch (true) { - case ($this->isFunction()): - $expr = $this->FunctionDeclaration(); - break; - - case ($this->isMathOperator($peek)): - $expr = $this->SimpleArithmeticExpression(); - break; - - case $glimpse !== null && $glimpse['type'] === Lexer::T_DOT: - $expr = $this->SingleValuedPathExpression(); - break; - - case ($this->lexer->peek() && $this->isMathOperator($this->peekBeyondClosingParenthesis())): - $expr = $this->ScalarExpression(); - break; - - default: - $expr = $this->ResultVariable(); - break; - } - - $type = 'ASC'; - $item = new AST\OrderByItem($expr); - - switch (true) { - case ($this->lexer->isNextToken(Lexer::T_DESC)): - $this->match(Lexer::T_DESC); - $type = 'DESC'; - break; - - case ($this->lexer->isNextToken(Lexer::T_ASC)): - $this->match(Lexer::T_ASC); - break; - - default: - // Do nothing - } - - $item->type = $type; - - return $item; - } - - /** - * NewValue ::= SimpleArithmeticExpression | StringPrimary | DatetimePrimary | BooleanPrimary | - * EnumPrimary | SimpleEntityExpression | "NULL" - * - * NOTE: Since it is not possible to correctly recognize individual types, here is the full - * grammar that needs to be supported: - * - * NewValue ::= SimpleArithmeticExpression | "NULL" - * - * SimpleArithmeticExpression covers all *Primary grammar rules and also SimpleEntityExpression - * - * @return AST\ArithmeticExpression - */ - public function NewValue() - { - if ($this->lexer->isNextToken(Lexer::T_NULL)) { - $this->match(Lexer::T_NULL); - - return null; - } - - if ($this->lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) { - $this->match(Lexer::T_INPUT_PARAMETER); - - return new AST\InputParameter($this->lexer->token['value']); - } - - return $this->ArithmeticExpression(); - } - - /** - * IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {Join}* - * - * @return \Doctrine\ORM\Query\AST\IdentificationVariableDeclaration - */ - public function IdentificationVariableDeclaration() - { - $joins = []; - $rangeVariableDeclaration = $this->RangeVariableDeclaration(); - $indexBy = $this->lexer->isNextToken(Lexer::T_INDEX) - ? $this->IndexBy() - : null; - - $rangeVariableDeclaration->isRoot = true; - - while ( - $this->lexer->isNextToken(Lexer::T_LEFT) || - $this->lexer->isNextToken(Lexer::T_INNER) || - $this->lexer->isNextToken(Lexer::T_JOIN) - ) { - $joins[] = $this->Join(); - } - - return new AST\IdentificationVariableDeclaration( - $rangeVariableDeclaration, $indexBy, $joins - ); - } - - /** - * SubselectIdentificationVariableDeclaration ::= IdentificationVariableDeclaration - * - * {Internal note: WARNING: Solution is harder than a bare implementation. - * Desired EBNF support: - * - * SubselectIdentificationVariableDeclaration ::= IdentificationVariableDeclaration | (AssociationPathExpression ["AS"] AliasIdentificationVariable) - * - * It demands that entire SQL generation to become programmatical. This is - * needed because association based subselect requires "WHERE" conditional - * expressions to be injected, but there is no scope to do that. Only scope - * accessible is "FROM", prohibiting an easy implementation without larger - * changes.} - * - * @return \Doctrine\ORM\Query\AST\SubselectIdentificationVariableDeclaration | - * \Doctrine\ORM\Query\AST\IdentificationVariableDeclaration - */ - public function SubselectIdentificationVariableDeclaration() - { - /* - NOT YET IMPLEMENTED! - - $glimpse = $this->lexer->glimpse(); - - if ($glimpse['type'] == Lexer::T_DOT) { - $associationPathExpression = $this->AssociationPathExpression(); - - if ($this->lexer->isNextToken(Lexer::T_AS)) { - $this->match(Lexer::T_AS); - } - - $aliasIdentificationVariable = $this->AliasIdentificationVariable(); - $identificationVariable = $associationPathExpression->identificationVariable; - $field = $associationPathExpression->associationField; - - $class = $this->queryComponents[$identificationVariable]['metadata']; - $targetClass = $this->em->getClassMetadata($class->associationMappings[$field]['targetEntity']); - - // Building queryComponent - $joinQueryComponent = array( - 'metadata' => $targetClass, - 'parent' => $identificationVariable, - 'relation' => $class->getAssociationMapping($field), - 'map' => null, - 'nestingLevel' => $this->nestingLevel, - 'token' => $this->lexer->lookahead - ); - - $this->queryComponents[$aliasIdentificationVariable] = $joinQueryComponent; - - return new AST\SubselectIdentificationVariableDeclaration( - $associationPathExpression, $aliasIdentificationVariable - ); - } - */ - - return $this->IdentificationVariableDeclaration(); - } - - /** - * Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" - * (JoinAssociationDeclaration | RangeVariableDeclaration) - * ["WITH" ConditionalExpression] - * - * @return \Doctrine\ORM\Query\AST\Join - */ - public function Join() - { - // Check Join type - $joinType = AST\Join::JOIN_TYPE_INNER; - - switch (true) { - case ($this->lexer->isNextToken(Lexer::T_LEFT)): - $this->match(Lexer::T_LEFT); - - $joinType = AST\Join::JOIN_TYPE_LEFT; - - // Possible LEFT OUTER join - if ($this->lexer->isNextToken(Lexer::T_OUTER)) { - $this->match(Lexer::T_OUTER); - - $joinType = AST\Join::JOIN_TYPE_LEFTOUTER; - } - break; - - case ($this->lexer->isNextToken(Lexer::T_INNER)): - $this->match(Lexer::T_INNER); - break; - - default: - // Do nothing - } - - $this->match(Lexer::T_JOIN); - - $next = $this->lexer->glimpse(); - $joinDeclaration = ($next['type'] === Lexer::T_DOT) ? $this->JoinAssociationDeclaration() : $this->RangeVariableDeclaration(); - $adhocConditions = $this->lexer->isNextToken(Lexer::T_WITH); - $join = new AST\Join($joinType, $joinDeclaration); - - // Describe non-root join declaration - if ($joinDeclaration instanceof AST\RangeVariableDeclaration) { - $joinDeclaration->isRoot = false; - } - - // Check for ad-hoc Join conditions - if ($adhocConditions) { - $this->match(Lexer::T_WITH); - - $join->conditionalExpression = $this->ConditionalExpression(); - } - - return $join; - } - - /** - * RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable - * - * @return \Doctrine\ORM\Query\AST\RangeVariableDeclaration - * - * @throws QueryException - */ - public function RangeVariableDeclaration() - { - if ($this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS) && $this->lexer->glimpse()['type'] === Lexer::T_SELECT) { - $this->semanticalError('Subquery is not supported here', $this->lexer->token); - } - - $abstractSchemaName = $this->AbstractSchemaName(); - - $this->validateAbstractSchemaName($abstractSchemaName); - - if ($this->lexer->isNextToken(Lexer::T_AS)) { - $this->match(Lexer::T_AS); - } - - $token = $this->lexer->lookahead; - $aliasIdentificationVariable = $this->AliasIdentificationVariable(); - $classMetadata = $this->em->getClassMetadata($abstractSchemaName); - - // Building queryComponent - $queryComponent = [ - 'metadata' => $classMetadata, - 'parent' => null, - 'relation' => null, - 'map' => null, - 'nestingLevel' => $this->nestingLevel, - 'token' => $token - ]; - - $this->queryComponents[$aliasIdentificationVariable] = $queryComponent; - - return new AST\RangeVariableDeclaration($abstractSchemaName, $aliasIdentificationVariable); - } - - /** - * JoinAssociationDeclaration ::= JoinAssociationPathExpression ["AS"] AliasIdentificationVariable [IndexBy] - * - * @return \Doctrine\ORM\Query\AST\JoinAssociationPathExpression - */ - public function JoinAssociationDeclaration() - { - $joinAssociationPathExpression = $this->JoinAssociationPathExpression(); - - if ($this->lexer->isNextToken(Lexer::T_AS)) { - $this->match(Lexer::T_AS); - } - - $aliasIdentificationVariable = $this->AliasIdentificationVariable(); - $indexBy = $this->lexer->isNextToken(Lexer::T_INDEX) ? $this->IndexBy() : null; - - $identificationVariable = $joinAssociationPathExpression->identificationVariable; - $field = $joinAssociationPathExpression->associationField; - - $class = $this->queryComponents[$identificationVariable]['metadata']; - $targetClass = $this->em->getClassMetadata($class->associationMappings[$field]['targetEntity']); - - // Building queryComponent - $joinQueryComponent = [ - 'metadata' => $targetClass, - 'parent' => $joinAssociationPathExpression->identificationVariable, - 'relation' => $class->getAssociationMapping($field), - 'map' => null, - 'nestingLevel' => $this->nestingLevel, - 'token' => $this->lexer->lookahead - ]; - - $this->queryComponents[$aliasIdentificationVariable] = $joinQueryComponent; - - return new AST\JoinAssociationDeclaration($joinAssociationPathExpression, $aliasIdentificationVariable, $indexBy); - } - - /** - * PartialObjectExpression ::= "PARTIAL" IdentificationVariable "." PartialFieldSet - * PartialFieldSet ::= "{" SimpleStateField {"," SimpleStateField}* "}" - * - * @return \Doctrine\ORM\Query\AST\PartialObjectExpression - */ - public function PartialObjectExpression() - { - $this->match(Lexer::T_PARTIAL); - - $partialFieldSet = []; - - $identificationVariable = $this->IdentificationVariable(); - - $this->match(Lexer::T_DOT); - $this->match(Lexer::T_OPEN_CURLY_BRACE); - $this->match(Lexer::T_IDENTIFIER); - - $field = $this->lexer->token['value']; - - // First field in partial expression might be embeddable property - while ($this->lexer->isNextToken(Lexer::T_DOT)) { - $this->match(Lexer::T_DOT); - $this->match(Lexer::T_IDENTIFIER); - $field .= '.'.$this->lexer->token['value']; - } - - $partialFieldSet[] = $field; - - while ($this->lexer->isNextToken(Lexer::T_COMMA)) { - $this->match(Lexer::T_COMMA); - $this->match(Lexer::T_IDENTIFIER); - - $field = $this->lexer->token['value']; - - while ($this->lexer->isNextToken(Lexer::T_DOT)) { - $this->match(Lexer::T_DOT); - $this->match(Lexer::T_IDENTIFIER); - $field .= '.'.$this->lexer->token['value']; - } - - $partialFieldSet[] = $field; - } - - $this->match(Lexer::T_CLOSE_CURLY_BRACE); - - $partialObjectExpression = new AST\PartialObjectExpression($identificationVariable, $partialFieldSet); - - // Defer PartialObjectExpression validation - $this->deferredPartialObjectExpressions[] = [ - 'expression' => $partialObjectExpression, - 'nestingLevel' => $this->nestingLevel, - 'token' => $this->lexer->token, - ]; - - return $partialObjectExpression; - } - - /** - * NewObjectExpression ::= "NEW" AbstractSchemaName "(" NewObjectArg {"," NewObjectArg}* ")" - * - * @return \Doctrine\ORM\Query\AST\NewObjectExpression - */ - public function NewObjectExpression() - { - $this->match(Lexer::T_NEW); - - $className = $this->AbstractSchemaName(); // note that this is not yet validated - $token = $this->lexer->token; - - $this->match(Lexer::T_OPEN_PARENTHESIS); - - $args[] = $this->NewObjectArg(); - - while ($this->lexer->isNextToken(Lexer::T_COMMA)) { - $this->match(Lexer::T_COMMA); - - $args[] = $this->NewObjectArg(); - } - - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - $expression = new AST\NewObjectExpression($className, $args); - - // Defer NewObjectExpression validation - $this->deferredNewObjectExpressions[] = [ - 'token' => $token, - 'expression' => $expression, - 'nestingLevel' => $this->nestingLevel, - ]; - - return $expression; - } - - /** - * NewObjectArg ::= ScalarExpression | "(" Subselect ")" - * - * @return mixed - */ - public function NewObjectArg() - { - $token = $this->lexer->lookahead; - $peek = $this->lexer->glimpse(); - - if ($token['type'] === Lexer::T_OPEN_PARENTHESIS && $peek['type'] === Lexer::T_SELECT) { - $this->match(Lexer::T_OPEN_PARENTHESIS); - $expression = $this->Subselect(); - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - return $expression; - } - - return $this->ScalarExpression(); - } - - /** - * IndexBy ::= "INDEX" "BY" StateFieldPathExpression - * - * @return \Doctrine\ORM\Query\AST\IndexBy - */ - public function IndexBy() - { - $this->match(Lexer::T_INDEX); - $this->match(Lexer::T_BY); - $pathExpr = $this->StateFieldPathExpression(); - - // Add the INDEX BY info to the query component - $this->queryComponents[$pathExpr->identificationVariable]['map'] = $pathExpr->field; - - return new AST\IndexBy($pathExpr); - } - - /** - * ScalarExpression ::= SimpleArithmeticExpression | StringPrimary | DateTimePrimary | - * StateFieldPathExpression | BooleanPrimary | CaseExpression | - * InstanceOfExpression - * - * @return mixed One of the possible expressions or subexpressions. - */ - public function ScalarExpression() - { - $lookahead = $this->lexer->lookahead['type']; - $peek = $this->lexer->glimpse(); - - switch (true) { - case ($lookahead === Lexer::T_INTEGER): - case ($lookahead === Lexer::T_FLOAT): - // SimpleArithmeticExpression : (- u.value ) or ( + u.value ) or ( - 1 ) or ( + 1 ) - case ($lookahead === Lexer::T_MINUS): - case ($lookahead === Lexer::T_PLUS): - return $this->SimpleArithmeticExpression(); - - case ($lookahead === Lexer::T_STRING): - return $this->StringPrimary(); - - case ($lookahead === Lexer::T_TRUE): - case ($lookahead === Lexer::T_FALSE): - $this->match($lookahead); - - return new AST\Literal(AST\Literal::BOOLEAN, $this->lexer->token['value']); - - case ($lookahead === Lexer::T_INPUT_PARAMETER): - switch (true) { - case $this->isMathOperator($peek): - // :param + u.value - return $this->SimpleArithmeticExpression(); - default: - return $this->InputParameter(); - } - - case ($lookahead === Lexer::T_CASE): - case ($lookahead === Lexer::T_COALESCE): - case ($lookahead === Lexer::T_NULLIF): - // Since NULLIF and COALESCE can be identified as a function, - // we need to check these before checking for FunctionDeclaration - return $this->CaseExpression(); - - case ($lookahead === Lexer::T_OPEN_PARENTHESIS): - return $this->SimpleArithmeticExpression(); - - // this check must be done before checking for a filed path expression - case ($this->isFunction()): - $this->lexer->peek(); // "(" - - switch (true) { - case ($this->isMathOperator($this->peekBeyondClosingParenthesis())): - // SUM(u.id) + COUNT(u.id) - return $this->SimpleArithmeticExpression(); - - default: - // IDENTITY(u) - return $this->FunctionDeclaration(); - } - - break; - // it is no function, so it must be a field path - case ($lookahead === Lexer::T_IDENTIFIER): - $this->lexer->peek(); // lookahead => '.' - $this->lexer->peek(); // lookahead => token after '.' - $peek = $this->lexer->peek(); // lookahead => token after the token after the '.' - $this->lexer->resetPeek(); - - if ($this->isMathOperator($peek)) { - return $this->SimpleArithmeticExpression(); - } - - return $this->StateFieldPathExpression(); - - default: - $this->syntaxError(); - } - } - - /** - * CaseExpression ::= GeneralCaseExpression | SimpleCaseExpression | CoalesceExpression | NullifExpression - * GeneralCaseExpression ::= "CASE" WhenClause {WhenClause}* "ELSE" ScalarExpression "END" - * WhenClause ::= "WHEN" ConditionalExpression "THEN" ScalarExpression - * SimpleCaseExpression ::= "CASE" CaseOperand SimpleWhenClause {SimpleWhenClause}* "ELSE" ScalarExpression "END" - * CaseOperand ::= StateFieldPathExpression | TypeDiscriminator - * SimpleWhenClause ::= "WHEN" ScalarExpression "THEN" ScalarExpression - * CoalesceExpression ::= "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")" - * NullifExpression ::= "NULLIF" "(" ScalarExpression "," ScalarExpression ")" - * - * @return mixed One of the possible expressions or subexpressions. - */ - public function CaseExpression() - { - $lookahead = $this->lexer->lookahead['type']; - - switch ($lookahead) { - case Lexer::T_NULLIF: - return $this->NullIfExpression(); - - case Lexer::T_COALESCE: - return $this->CoalesceExpression(); - - case Lexer::T_CASE: - $this->lexer->resetPeek(); - $peek = $this->lexer->peek(); - - if ($peek['type'] === Lexer::T_WHEN) { - return $this->GeneralCaseExpression(); - } - - return $this->SimpleCaseExpression(); - - default: - // Do nothing - break; - } - - $this->syntaxError(); - } - - /** - * CoalesceExpression ::= "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")" - * - * @return \Doctrine\ORM\Query\AST\CoalesceExpression - */ - public function CoalesceExpression() - { - $this->match(Lexer::T_COALESCE); - $this->match(Lexer::T_OPEN_PARENTHESIS); - - // Process ScalarExpressions (1..N) - $scalarExpressions = []; - $scalarExpressions[] = $this->ScalarExpression(); - - while ($this->lexer->isNextToken(Lexer::T_COMMA)) { - $this->match(Lexer::T_COMMA); - - $scalarExpressions[] = $this->ScalarExpression(); - } - - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - return new AST\CoalesceExpression($scalarExpressions); - } - - /** - * NullIfExpression ::= "NULLIF" "(" ScalarExpression "," ScalarExpression ")" - * - * @return \Doctrine\ORM\Query\AST\NullIfExpression - */ - public function NullIfExpression() - { - $this->match(Lexer::T_NULLIF); - $this->match(Lexer::T_OPEN_PARENTHESIS); - - $firstExpression = $this->ScalarExpression(); - $this->match(Lexer::T_COMMA); - $secondExpression = $this->ScalarExpression(); - - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - return new AST\NullIfExpression($firstExpression, $secondExpression); - } - - /** - * GeneralCaseExpression ::= "CASE" WhenClause {WhenClause}* "ELSE" ScalarExpression "END" - * - * @return \Doctrine\ORM\Query\AST\GeneralCaseExpression - */ - public function GeneralCaseExpression() - { - $this->match(Lexer::T_CASE); - - // Process WhenClause (1..N) - $whenClauses = []; - - do { - $whenClauses[] = $this->WhenClause(); - } while ($this->lexer->isNextToken(Lexer::T_WHEN)); - - $this->match(Lexer::T_ELSE); - $scalarExpression = $this->ScalarExpression(); - $this->match(Lexer::T_END); - - return new AST\GeneralCaseExpression($whenClauses, $scalarExpression); - } - - /** - * SimpleCaseExpression ::= "CASE" CaseOperand SimpleWhenClause {SimpleWhenClause}* "ELSE" ScalarExpression "END" - * CaseOperand ::= StateFieldPathExpression | TypeDiscriminator - * - * @return AST\SimpleCaseExpression - */ - public function SimpleCaseExpression() - { - $this->match(Lexer::T_CASE); - $caseOperand = $this->StateFieldPathExpression(); - - // Process SimpleWhenClause (1..N) - $simpleWhenClauses = []; - - do { - $simpleWhenClauses[] = $this->SimpleWhenClause(); - } while ($this->lexer->isNextToken(Lexer::T_WHEN)); - - $this->match(Lexer::T_ELSE); - $scalarExpression = $this->ScalarExpression(); - $this->match(Lexer::T_END); - - return new AST\SimpleCaseExpression($caseOperand, $simpleWhenClauses, $scalarExpression); - } - - /** - * WhenClause ::= "WHEN" ConditionalExpression "THEN" ScalarExpression - * - * @return \Doctrine\ORM\Query\AST\WhenClause - */ - public function WhenClause() - { - $this->match(Lexer::T_WHEN); - $conditionalExpression = $this->ConditionalExpression(); - $this->match(Lexer::T_THEN); - - return new AST\WhenClause($conditionalExpression, $this->ScalarExpression()); - } - - /** - * SimpleWhenClause ::= "WHEN" ScalarExpression "THEN" ScalarExpression - * - * @return \Doctrine\ORM\Query\AST\SimpleWhenClause - */ - public function SimpleWhenClause() - { - $this->match(Lexer::T_WHEN); - $conditionalExpression = $this->ScalarExpression(); - $this->match(Lexer::T_THEN); - - return new AST\SimpleWhenClause($conditionalExpression, $this->ScalarExpression()); - } - - /** - * SelectExpression ::= ( - * IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | - * PartialObjectExpression | "(" Subselect ")" | CaseExpression | NewObjectExpression - * ) [["AS"] ["HIDDEN"] AliasResultVariable] - * - * @return \Doctrine\ORM\Query\AST\SelectExpression - */ - public function SelectExpression() - { - $expression = null; - $identVariable = null; - $peek = $this->lexer->glimpse(); - $lookaheadType = $this->lexer->lookahead['type']; - - switch (true) { - // ScalarExpression (u.name) - case ($lookaheadType === Lexer::T_IDENTIFIER && $peek['type'] === Lexer::T_DOT): - $expression = $this->ScalarExpression(); - break; - - // IdentificationVariable (u) - case ($lookaheadType === Lexer::T_IDENTIFIER && $peek['type'] !== Lexer::T_OPEN_PARENTHESIS): - $expression = $identVariable = $this->IdentificationVariable(); - break; - - // CaseExpression (CASE ... or NULLIF(...) or COALESCE(...)) - case ($lookaheadType === Lexer::T_CASE): - case ($lookaheadType === Lexer::T_COALESCE): - case ($lookaheadType === Lexer::T_NULLIF): - $expression = $this->CaseExpression(); - break; - - // DQL Function (SUM(u.value) or SUM(u.value) + 1) - case ($this->isFunction()): - $this->lexer->peek(); // "(" - - switch (true) { - case ($this->isMathOperator($this->peekBeyondClosingParenthesis())): - // SUM(u.id) + COUNT(u.id) - $expression = $this->ScalarExpression(); - break; - - default: - // IDENTITY(u) - $expression = $this->FunctionDeclaration(); - break; - } - - break; - - // PartialObjectExpression (PARTIAL u.{id, name}) - case ($lookaheadType === Lexer::T_PARTIAL): - $expression = $this->PartialObjectExpression(); - $identVariable = $expression->identificationVariable; - break; - - // Subselect - case ($lookaheadType === Lexer::T_OPEN_PARENTHESIS && $peek['type'] === Lexer::T_SELECT): - $this->match(Lexer::T_OPEN_PARENTHESIS); - $expression = $this->Subselect(); - $this->match(Lexer::T_CLOSE_PARENTHESIS); - break; - - // Shortcut: ScalarExpression => SimpleArithmeticExpression - case ($lookaheadType === Lexer::T_OPEN_PARENTHESIS): - case ($lookaheadType === Lexer::T_INTEGER): - case ($lookaheadType === Lexer::T_STRING): - case ($lookaheadType === Lexer::T_FLOAT): - // SimpleArithmeticExpression : (- u.value ) or ( + u.value ) - case ($lookaheadType === Lexer::T_MINUS): - case ($lookaheadType === Lexer::T_PLUS): - $expression = $this->SimpleArithmeticExpression(); - break; - - // NewObjectExpression (New ClassName(id, name)) - case ($lookaheadType === Lexer::T_NEW): - $expression = $this->NewObjectExpression(); - break; - - default: - $this->syntaxError( - 'IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | PartialObjectExpression | "(" Subselect ")" | CaseExpression', - $this->lexer->lookahead - ); - } - - // [["AS"] ["HIDDEN"] AliasResultVariable] - $mustHaveAliasResultVariable = false; - - if ($this->lexer->isNextToken(Lexer::T_AS)) { - $this->match(Lexer::T_AS); - - $mustHaveAliasResultVariable = true; - } - - $hiddenAliasResultVariable = false; - - if ($this->lexer->isNextToken(Lexer::T_HIDDEN)) { - $this->match(Lexer::T_HIDDEN); - - $hiddenAliasResultVariable = true; - } - - $aliasResultVariable = null; - - if ($mustHaveAliasResultVariable || $this->lexer->isNextToken(Lexer::T_IDENTIFIER)) { - $token = $this->lexer->lookahead; - $aliasResultVariable = $this->AliasResultVariable(); - - // Include AliasResultVariable in query components. - $this->queryComponents[$aliasResultVariable] = [ - 'resultVariable' => $expression, - 'nestingLevel' => $this->nestingLevel, - 'token' => $token, - ]; - } - - // AST - - $expr = new AST\SelectExpression($expression, $aliasResultVariable, $hiddenAliasResultVariable); - - if ($identVariable) { - $this->identVariableExpressions[$identVariable] = $expr; - } - - return $expr; - } - - /** - * SimpleSelectExpression ::= ( - * StateFieldPathExpression | IdentificationVariable | FunctionDeclaration | - * AggregateExpression | "(" Subselect ")" | ScalarExpression - * ) [["AS"] AliasResultVariable] - * - * @return \Doctrine\ORM\Query\AST\SimpleSelectExpression - */ - public function SimpleSelectExpression() - { - $peek = $this->lexer->glimpse(); - - switch ($this->lexer->lookahead['type']) { - case Lexer::T_IDENTIFIER: - switch (true) { - case ($peek['type'] === Lexer::T_DOT): - $expression = $this->StateFieldPathExpression(); - - return new AST\SimpleSelectExpression($expression); - - case ($peek['type'] !== Lexer::T_OPEN_PARENTHESIS): - $expression = $this->IdentificationVariable(); - - return new AST\SimpleSelectExpression($expression); - - case ($this->isFunction()): - // SUM(u.id) + COUNT(u.id) - if ($this->isMathOperator($this->peekBeyondClosingParenthesis())) { - return new AST\SimpleSelectExpression($this->ScalarExpression()); - } - // COUNT(u.id) - if ($this->isAggregateFunction($this->lexer->lookahead['type'])) { - return new AST\SimpleSelectExpression($this->AggregateExpression()); - } - // IDENTITY(u) - return new AST\SimpleSelectExpression($this->FunctionDeclaration()); - - default: - // Do nothing - } - break; - - case Lexer::T_OPEN_PARENTHESIS: - if ($peek['type'] !== Lexer::T_SELECT) { - // Shortcut: ScalarExpression => SimpleArithmeticExpression - $expression = $this->SimpleArithmeticExpression(); - - return new AST\SimpleSelectExpression($expression); - } - - // Subselect - $this->match(Lexer::T_OPEN_PARENTHESIS); - $expression = $this->Subselect(); - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - return new AST\SimpleSelectExpression($expression); - - default: - // Do nothing - } - - $this->lexer->peek(); - - $expression = $this->ScalarExpression(); - $expr = new AST\SimpleSelectExpression($expression); - - if ($this->lexer->isNextToken(Lexer::T_AS)) { - $this->match(Lexer::T_AS); - } - - if ($this->lexer->isNextToken(Lexer::T_IDENTIFIER)) { - $token = $this->lexer->lookahead; - $resultVariable = $this->AliasResultVariable(); - $expr->fieldIdentificationVariable = $resultVariable; - - // Include AliasResultVariable in query components. - $this->queryComponents[$resultVariable] = [ - 'resultvariable' => $expr, - 'nestingLevel' => $this->nestingLevel, - 'token' => $token, - ]; - } - - return $expr; - } - - /** - * ConditionalExpression ::= ConditionalTerm {"OR" ConditionalTerm}* - * - * @return \Doctrine\ORM\Query\AST\ConditionalExpression - */ - public function ConditionalExpression() - { - $conditionalTerms = []; - $conditionalTerms[] = $this->ConditionalTerm(); - - while ($this->lexer->isNextToken(Lexer::T_OR)) { - $this->match(Lexer::T_OR); - - $conditionalTerms[] = $this->ConditionalTerm(); - } - - // Phase 1 AST optimization: Prevent AST\ConditionalExpression - // if only one AST\ConditionalTerm is defined - if (count($conditionalTerms) == 1) { - return $conditionalTerms[0]; - } - - return new AST\ConditionalExpression($conditionalTerms); - } - - /** - * ConditionalTerm ::= ConditionalFactor {"AND" ConditionalFactor}* - * - * @return \Doctrine\ORM\Query\AST\ConditionalTerm - */ - public function ConditionalTerm() - { - $conditionalFactors = []; - $conditionalFactors[] = $this->ConditionalFactor(); - - while ($this->lexer->isNextToken(Lexer::T_AND)) { - $this->match(Lexer::T_AND); - - $conditionalFactors[] = $this->ConditionalFactor(); - } - - // Phase 1 AST optimization: Prevent AST\ConditionalTerm - // if only one AST\ConditionalFactor is defined - if (count($conditionalFactors) == 1) { - return $conditionalFactors[0]; - } - - return new AST\ConditionalTerm($conditionalFactors); - } - - /** - * ConditionalFactor ::= ["NOT"] ConditionalPrimary - * - * @return \Doctrine\ORM\Query\AST\ConditionalFactor - */ - public function ConditionalFactor() - { - $not = false; - - if ($this->lexer->isNextToken(Lexer::T_NOT)) { - $this->match(Lexer::T_NOT); - - $not = true; - } - - $conditionalPrimary = $this->ConditionalPrimary(); - - // Phase 1 AST optimization: Prevent AST\ConditionalFactor - // if only one AST\ConditionalPrimary is defined - if ( ! $not) { - return $conditionalPrimary; - } - - $conditionalFactor = new AST\ConditionalFactor($conditionalPrimary); - $conditionalFactor->not = $not; - - return $conditionalFactor; - } - - /** - * ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")" - * - * @return \Doctrine\ORM\Query\AST\ConditionalPrimary - */ - public function ConditionalPrimary() - { - $condPrimary = new AST\ConditionalPrimary; - - if ( ! $this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) { - $condPrimary->simpleConditionalExpression = $this->SimpleConditionalExpression(); - - return $condPrimary; - } - - // Peek beyond the matching closing parenthesis ')' - $peek = $this->peekBeyondClosingParenthesis(); - - if ($peek !== null && ( - in_array($peek['value'], ['=', '<', '<=', '<>', '>', '>=', '!=']) || - in_array($peek['type'], [Lexer::T_NOT, Lexer::T_BETWEEN, Lexer::T_LIKE, Lexer::T_IN, Lexer::T_IS, Lexer::T_EXISTS]) || - $this->isMathOperator($peek) - )) { - $condPrimary->simpleConditionalExpression = $this->SimpleConditionalExpression(); - - return $condPrimary; - } - - $this->match(Lexer::T_OPEN_PARENTHESIS); - $condPrimary->conditionalExpression = $this->ConditionalExpression(); - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - return $condPrimary; - } - - /** - * SimpleConditionalExpression ::= - * ComparisonExpression | BetweenExpression | LikeExpression | - * InExpression | NullComparisonExpression | ExistsExpression | - * EmptyCollectionComparisonExpression | CollectionMemberExpression | - * InstanceOfExpression - */ - public function SimpleConditionalExpression() - { - if ($this->lexer->isNextToken(Lexer::T_EXISTS)) { - return $this->ExistsExpression(); - } - - $token = $this->lexer->lookahead; - $peek = $this->lexer->glimpse(); - $lookahead = $token; - - if ($this->lexer->isNextToken(Lexer::T_NOT)) { - $token = $this->lexer->glimpse(); - } - - if ($token['type'] === Lexer::T_IDENTIFIER || $token['type'] === Lexer::T_INPUT_PARAMETER || $this->isFunction()) { - // Peek beyond the matching closing parenthesis. - $beyond = $this->lexer->peek(); - - switch ($peek['value']) { - case '(': - // Peeks beyond the matched closing parenthesis. - $token = $this->peekBeyondClosingParenthesis(false); - - if ($token['type'] === Lexer::T_NOT) { - $token = $this->lexer->peek(); - } - - if ($token['type'] === Lexer::T_IS) { - $lookahead = $this->lexer->peek(); - } - break; - - default: - // Peek beyond the PathExpression or InputParameter. - $token = $beyond; - - while ($token['value'] === '.') { - $this->lexer->peek(); - - $token = $this->lexer->peek(); - } - - // Also peek beyond a NOT if there is one. - if ($token['type'] === Lexer::T_NOT) { - $token = $this->lexer->peek(); - } - - // We need to go even further in case of IS (differentiate between NULL and EMPTY) - $lookahead = $this->lexer->peek(); - } - - // Also peek beyond a NOT if there is one. - if ($lookahead['type'] === Lexer::T_NOT) { - $lookahead = $this->lexer->peek(); - } - - $this->lexer->resetPeek(); - } - - if ($token['type'] === Lexer::T_BETWEEN) { - return $this->BetweenExpression(); - } - - if ($token['type'] === Lexer::T_LIKE) { - return $this->LikeExpression(); - } - - if ($token['type'] === Lexer::T_IN) { - return $this->InExpression(); - } - - if ($token['type'] === Lexer::T_INSTANCE) { - return $this->InstanceOfExpression(); - } - - if ($token['type'] === Lexer::T_MEMBER) { - return $this->CollectionMemberExpression(); - } - - if ($token['type'] === Lexer::T_IS && $lookahead['type'] === Lexer::T_NULL) { - return $this->NullComparisonExpression(); - } - - if ($token['type'] === Lexer::T_IS && $lookahead['type'] === Lexer::T_EMPTY) { - return $this->EmptyCollectionComparisonExpression(); - } - - return $this->ComparisonExpression(); - } - - /** - * EmptyCollectionComparisonExpression ::= CollectionValuedPathExpression "IS" ["NOT"] "EMPTY" - * - * @return \Doctrine\ORM\Query\AST\EmptyCollectionComparisonExpression - */ - public function EmptyCollectionComparisonExpression() - { - $emptyCollectionCompExpr = new AST\EmptyCollectionComparisonExpression( - $this->CollectionValuedPathExpression() - ); - $this->match(Lexer::T_IS); - - if ($this->lexer->isNextToken(Lexer::T_NOT)) { - $this->match(Lexer::T_NOT); - $emptyCollectionCompExpr->not = true; - } - - $this->match(Lexer::T_EMPTY); - - return $emptyCollectionCompExpr; - } - - /** - * CollectionMemberExpression ::= EntityExpression ["NOT"] "MEMBER" ["OF"] CollectionValuedPathExpression - * - * EntityExpression ::= SingleValuedAssociationPathExpression | SimpleEntityExpression - * SimpleEntityExpression ::= IdentificationVariable | InputParameter - * - * @return \Doctrine\ORM\Query\AST\CollectionMemberExpression - */ - public function CollectionMemberExpression() - { - $not = false; - $entityExpr = $this->EntityExpression(); - - if ($this->lexer->isNextToken(Lexer::T_NOT)) { - $this->match(Lexer::T_NOT); - - $not = true; - } - - $this->match(Lexer::T_MEMBER); - - if ($this->lexer->isNextToken(Lexer::T_OF)) { - $this->match(Lexer::T_OF); - } - - $collMemberExpr = new AST\CollectionMemberExpression( - $entityExpr, $this->CollectionValuedPathExpression() - ); - $collMemberExpr->not = $not; - - return $collMemberExpr; - } - - /** - * Literal ::= string | char | integer | float | boolean - * - * @return \Doctrine\ORM\Query\AST\Literal - */ - public function Literal() - { - switch ($this->lexer->lookahead['type']) { - case Lexer::T_STRING: - $this->match(Lexer::T_STRING); - - return new AST\Literal(AST\Literal::STRING, $this->lexer->token['value']); - case Lexer::T_INTEGER: - case Lexer::T_FLOAT: - $this->match( - $this->lexer->isNextToken(Lexer::T_INTEGER) ? Lexer::T_INTEGER : Lexer::T_FLOAT - ); - - return new AST\Literal(AST\Literal::NUMERIC, $this->lexer->token['value']); - case Lexer::T_TRUE: - case Lexer::T_FALSE: - $this->match( - $this->lexer->isNextToken(Lexer::T_TRUE) ? Lexer::T_TRUE : Lexer::T_FALSE - ); - - return new AST\Literal(AST\Literal::BOOLEAN, $this->lexer->token['value']); - default: - $this->syntaxError('Literal'); - } - } - - /** - * InParameter ::= Literal | InputParameter - * - * @return string | \Doctrine\ORM\Query\AST\InputParameter - */ - public function InParameter() - { - if ($this->lexer->lookahead['type'] == Lexer::T_INPUT_PARAMETER) { - return $this->InputParameter(); - } - - return $this->Literal(); - } - - /** - * InputParameter ::= PositionalParameter | NamedParameter - * - * @return \Doctrine\ORM\Query\AST\InputParameter - */ - public function InputParameter() - { - $this->match(Lexer::T_INPUT_PARAMETER); - - return new AST\InputParameter($this->lexer->token['value']); - } - - /** - * ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")" - * - * @return \Doctrine\ORM\Query\AST\ArithmeticExpression - */ - public function ArithmeticExpression() - { - $expr = new AST\ArithmeticExpression; - - if ($this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) { - $peek = $this->lexer->glimpse(); - - if ($peek['type'] === Lexer::T_SELECT) { - $this->match(Lexer::T_OPEN_PARENTHESIS); - $expr->subselect = $this->Subselect(); - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - return $expr; - } - } - - $expr->simpleArithmeticExpression = $this->SimpleArithmeticExpression(); - - return $expr; - } - - /** - * SimpleArithmeticExpression ::= ArithmeticTerm {("+" | "-") ArithmeticTerm}* - * - * @return \Doctrine\ORM\Query\AST\SimpleArithmeticExpression - */ - public function SimpleArithmeticExpression() - { - $terms = []; - $terms[] = $this->ArithmeticTerm(); - - while (($isPlus = $this->lexer->isNextToken(Lexer::T_PLUS)) || $this->lexer->isNextToken(Lexer::T_MINUS)) { - $this->match(($isPlus) ? Lexer::T_PLUS : Lexer::T_MINUS); - - $terms[] = $this->lexer->token['value']; - $terms[] = $this->ArithmeticTerm(); - } - - // Phase 1 AST optimization: Prevent AST\SimpleArithmeticExpression - // if only one AST\ArithmeticTerm is defined - if (count($terms) == 1) { - return $terms[0]; - } - - return new AST\SimpleArithmeticExpression($terms); - } - - /** - * ArithmeticTerm ::= ArithmeticFactor {("*" | "/") ArithmeticFactor}* - * - * @return \Doctrine\ORM\Query\AST\ArithmeticTerm - */ - public function ArithmeticTerm() - { - $factors = []; - $factors[] = $this->ArithmeticFactor(); - - while (($isMult = $this->lexer->isNextToken(Lexer::T_MULTIPLY)) || $this->lexer->isNextToken(Lexer::T_DIVIDE)) { - $this->match(($isMult) ? Lexer::T_MULTIPLY : Lexer::T_DIVIDE); - - $factors[] = $this->lexer->token['value']; - $factors[] = $this->ArithmeticFactor(); - } - - // Phase 1 AST optimization: Prevent AST\ArithmeticTerm - // if only one AST\ArithmeticFactor is defined - if (count($factors) == 1) { - return $factors[0]; - } - - return new AST\ArithmeticTerm($factors); - } - - /** - * ArithmeticFactor ::= [("+" | "-")] ArithmeticPrimary - * - * @return \Doctrine\ORM\Query\AST\ArithmeticFactor - */ - public function ArithmeticFactor() - { - $sign = null; - - if (($isPlus = $this->lexer->isNextToken(Lexer::T_PLUS)) || $this->lexer->isNextToken(Lexer::T_MINUS)) { - $this->match(($isPlus) ? Lexer::T_PLUS : Lexer::T_MINUS); - $sign = $isPlus; - } - - $primary = $this->ArithmeticPrimary(); - - // Phase 1 AST optimization: Prevent AST\ArithmeticFactor - // if only one AST\ArithmeticPrimary is defined - if ($sign === null) { - return $primary; - } - - return new AST\ArithmeticFactor($primary, $sign); - } - - /** - * ArithmeticPrimary ::= SingleValuedPathExpression | Literal | ParenthesisExpression - * | FunctionsReturningNumerics | AggregateExpression | FunctionsReturningStrings - * | FunctionsReturningDatetime | IdentificationVariable | ResultVariable - * | InputParameter | CaseExpression - */ - public function ArithmeticPrimary() - { - if ($this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) { - $this->match(Lexer::T_OPEN_PARENTHESIS); - - $expr = $this->SimpleArithmeticExpression(); - - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - return new AST\ParenthesisExpression($expr); - } - - switch ($this->lexer->lookahead['type']) { - case Lexer::T_COALESCE: - case Lexer::T_NULLIF: - case Lexer::T_CASE: - return $this->CaseExpression(); - - case Lexer::T_IDENTIFIER: - $peek = $this->lexer->glimpse(); - - if ($peek !== null && $peek['value'] === '(') { - return $this->FunctionDeclaration(); - } - - if ($peek !== null && $peek['value'] === '.') { - return $this->SingleValuedPathExpression(); - } - - if (isset($this->queryComponents[$this->lexer->lookahead['value']]['resultVariable'])) { - return $this->ResultVariable(); - } - - return $this->StateFieldPathExpression(); - - case Lexer::T_INPUT_PARAMETER: - return $this->InputParameter(); - - default: - $peek = $this->lexer->glimpse(); - - if ($peek !== null && $peek['value'] === '(') { - return $this->FunctionDeclaration(); - } - - return $this->Literal(); - } - } - - /** - * StringExpression ::= StringPrimary | ResultVariable | "(" Subselect ")" - * - * @return \Doctrine\ORM\Query\AST\Subselect | - * string - */ - public function StringExpression() - { - $peek = $this->lexer->glimpse(); - - // Subselect - if ($this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS) && $peek['type'] === Lexer::T_SELECT) { - $this->match(Lexer::T_OPEN_PARENTHESIS); - $expr = $this->Subselect(); - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - return $expr; - } - - // ResultVariable (string) - if ($this->lexer->isNextToken(Lexer::T_IDENTIFIER) && - isset($this->queryComponents[$this->lexer->lookahead['value']]['resultVariable'])) { - return $this->ResultVariable(); - } - - return $this->StringPrimary(); - } - - /** - * StringPrimary ::= StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression | CaseExpression - */ - public function StringPrimary() - { - $lookaheadType = $this->lexer->lookahead['type']; - - switch ($lookaheadType) { - case Lexer::T_IDENTIFIER: - $peek = $this->lexer->glimpse(); - - if ($peek['value'] == '.') { - return $this->StateFieldPathExpression(); - } - - if ($peek['value'] == '(') { - // do NOT directly go to FunctionsReturningString() because it doesn't check for custom functions. - return $this->FunctionDeclaration(); - } - - $this->syntaxError("'.' or '('"); - break; - - case Lexer::T_STRING: - $this->match(Lexer::T_STRING); - - return new AST\Literal(AST\Literal::STRING, $this->lexer->token['value']); - - case Lexer::T_INPUT_PARAMETER: - return $this->InputParameter(); - - case Lexer::T_CASE: - case Lexer::T_COALESCE: - case Lexer::T_NULLIF: - return $this->CaseExpression(); - default: - if ($this->isAggregateFunction($lookaheadType)) { - return $this->AggregateExpression(); - } - } - - $this->syntaxError( - 'StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression' - ); - } - - /** - * EntityExpression ::= SingleValuedAssociationPathExpression | SimpleEntityExpression - * - * @return \Doctrine\ORM\Query\AST\PathExpression | - * \Doctrine\ORM\Query\AST\SimpleEntityExpression - */ - public function EntityExpression() - { - $glimpse = $this->lexer->glimpse(); - - if ($this->lexer->isNextToken(Lexer::T_IDENTIFIER) && $glimpse['value'] === '.') { - return $this->SingleValuedAssociationPathExpression(); - } - - return $this->SimpleEntityExpression(); - } - - /** - * SimpleEntityExpression ::= IdentificationVariable | InputParameter - * - * @return string | \Doctrine\ORM\Query\AST\InputParameter - */ - public function SimpleEntityExpression() - { - if ($this->lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) { - return $this->InputParameter(); - } - - return $this->StateFieldPathExpression(); - } - - /** - * AggregateExpression ::= - * ("AVG" | "MAX" | "MIN" | "SUM" | "COUNT") "(" ["DISTINCT"] SimpleArithmeticExpression ")" - * - * @return \Doctrine\ORM\Query\AST\AggregateExpression - */ - public function AggregateExpression() - { - $lookaheadType = $this->lexer->lookahead['type']; - $isDistinct = false; - - if ( ! in_array($lookaheadType, [Lexer::T_COUNT, Lexer::T_AVG, Lexer::T_MAX, Lexer::T_MIN, Lexer::T_SUM])) { - $this->syntaxError('One of: MAX, MIN, AVG, SUM, COUNT'); - } - - $this->match($lookaheadType); - $functionName = $this->lexer->token['value']; - $this->match(Lexer::T_OPEN_PARENTHESIS); - - if ($this->lexer->isNextToken(Lexer::T_DISTINCT)) { - $this->match(Lexer::T_DISTINCT); - $isDistinct = true; - } - - $pathExp = $this->SimpleArithmeticExpression(); - - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - return new AST\AggregateExpression($functionName, $pathExp, $isDistinct); - } - - /** - * QuantifiedExpression ::= ("ALL" | "ANY" | "SOME") "(" Subselect ")" - * - * @return \Doctrine\ORM\Query\AST\QuantifiedExpression - */ - public function QuantifiedExpression() - { - $lookaheadType = $this->lexer->lookahead['type']; - $value = $this->lexer->lookahead['value']; - - if ( ! in_array($lookaheadType, [Lexer::T_ALL, Lexer::T_ANY, Lexer::T_SOME])) { - $this->syntaxError('ALL, ANY or SOME'); - } - - $this->match($lookaheadType); - $this->match(Lexer::T_OPEN_PARENTHESIS); - - $qExpr = new AST\QuantifiedExpression($this->Subselect()); - $qExpr->type = $value; - - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - return $qExpr; - } - - /** - * BetweenExpression ::= ArithmeticExpression ["NOT"] "BETWEEN" ArithmeticExpression "AND" ArithmeticExpression - * - * @return \Doctrine\ORM\Query\AST\BetweenExpression - */ - public function BetweenExpression() - { - $not = false; - $arithExpr1 = $this->ArithmeticExpression(); - - if ($this->lexer->isNextToken(Lexer::T_NOT)) { - $this->match(Lexer::T_NOT); - $not = true; - } - - $this->match(Lexer::T_BETWEEN); - $arithExpr2 = $this->ArithmeticExpression(); - $this->match(Lexer::T_AND); - $arithExpr3 = $this->ArithmeticExpression(); - - $betweenExpr = new AST\BetweenExpression($arithExpr1, $arithExpr2, $arithExpr3); - $betweenExpr->not = $not; - - return $betweenExpr; - } - - /** - * ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression ) - * - * @return \Doctrine\ORM\Query\AST\ComparisonExpression - */ - public function ComparisonExpression() - { - $this->lexer->glimpse(); - - $leftExpr = $this->ArithmeticExpression(); - $operator = $this->ComparisonOperator(); - $rightExpr = ($this->isNextAllAnySome()) - ? $this->QuantifiedExpression() - : $this->ArithmeticExpression(); - - return new AST\ComparisonExpression($leftExpr, $operator, $rightExpr); - } - - /** - * InExpression ::= SingleValuedPathExpression ["NOT"] "IN" "(" (InParameter {"," InParameter}* | Subselect) ")" - * - * @return \Doctrine\ORM\Query\AST\InExpression - */ - public function InExpression() - { - $inExpression = new AST\InExpression($this->ArithmeticExpression()); - - if ($this->lexer->isNextToken(Lexer::T_NOT)) { - $this->match(Lexer::T_NOT); - $inExpression->not = true; - } - - $this->match(Lexer::T_IN); - $this->match(Lexer::T_OPEN_PARENTHESIS); - - if ($this->lexer->isNextToken(Lexer::T_SELECT)) { - $inExpression->subselect = $this->Subselect(); - } else { - $literals = []; - $literals[] = $this->InParameter(); - - while ($this->lexer->isNextToken(Lexer::T_COMMA)) { - $this->match(Lexer::T_COMMA); - $literals[] = $this->InParameter(); - } - - $inExpression->literals = $literals; - } - - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - return $inExpression; - } - - /** - * InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (InstanceOfParameter | "(" InstanceOfParameter {"," InstanceOfParameter}* ")") - * - * @return \Doctrine\ORM\Query\AST\InstanceOfExpression - */ - public function InstanceOfExpression() - { - $instanceOfExpression = new AST\InstanceOfExpression($this->IdentificationVariable()); - - if ($this->lexer->isNextToken(Lexer::T_NOT)) { - $this->match(Lexer::T_NOT); - $instanceOfExpression->not = true; - } - - $this->match(Lexer::T_INSTANCE); - $this->match(Lexer::T_OF); - - $exprValues = []; - - if ($this->lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS)) { - $this->match(Lexer::T_OPEN_PARENTHESIS); - - $exprValues[] = $this->InstanceOfParameter(); - - while ($this->lexer->isNextToken(Lexer::T_COMMA)) { - $this->match(Lexer::T_COMMA); - - $exprValues[] = $this->InstanceOfParameter(); - } - - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - $instanceOfExpression->value = $exprValues; - - return $instanceOfExpression; - } - - $exprValues[] = $this->InstanceOfParameter(); - - $instanceOfExpression->value = $exprValues; - - return $instanceOfExpression; - } - - /** - * InstanceOfParameter ::= AbstractSchemaName | InputParameter - * - * @return mixed - */ - public function InstanceOfParameter() - { - if ($this->lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) { - $this->match(Lexer::T_INPUT_PARAMETER); - - return new AST\InputParameter($this->lexer->token['value']); - } - - $abstractSchemaName = $this->AbstractSchemaName(); - - $this->validateAbstractSchemaName($abstractSchemaName); - - return $abstractSchemaName; - } - - /** - * LikeExpression ::= StringExpression ["NOT"] "LIKE" StringPrimary ["ESCAPE" char] - * - * @return \Doctrine\ORM\Query\AST\LikeExpression - */ - public function LikeExpression() - { - $stringExpr = $this->StringExpression(); - $not = false; - - if ($this->lexer->isNextToken(Lexer::T_NOT)) { - $this->match(Lexer::T_NOT); - $not = true; - } - - $this->match(Lexer::T_LIKE); - - if ($this->lexer->isNextToken(Lexer::T_INPUT_PARAMETER)) { - $this->match(Lexer::T_INPUT_PARAMETER); - $stringPattern = new AST\InputParameter($this->lexer->token['value']); - } else { - $stringPattern = $this->StringPrimary(); - } - - $escapeChar = null; - - if ($this->lexer->lookahead !== null && $this->lexer->lookahead['type'] === Lexer::T_ESCAPE) { - $this->match(Lexer::T_ESCAPE); - $this->match(Lexer::T_STRING); - - $escapeChar = new AST\Literal(AST\Literal::STRING, $this->lexer->token['value']); - } - - $likeExpr = new AST\LikeExpression($stringExpr, $stringPattern, $escapeChar); - $likeExpr->not = $not; - - return $likeExpr; - } - - /** - * NullComparisonExpression ::= (InputParameter | NullIfExpression | CoalesceExpression | AggregateExpression | FunctionDeclaration | IdentificationVariable | SingleValuedPathExpression | ResultVariable) "IS" ["NOT"] "NULL" - * - * @return \Doctrine\ORM\Query\AST\NullComparisonExpression - */ - public function NullComparisonExpression() - { - switch (true) { - case $this->lexer->isNextToken(Lexer::T_INPUT_PARAMETER): - $this->match(Lexer::T_INPUT_PARAMETER); - - $expr = new AST\InputParameter($this->lexer->token['value']); - break; - - case $this->lexer->isNextToken(Lexer::T_NULLIF): - $expr = $this->NullIfExpression(); - break; - - case $this->lexer->isNextToken(Lexer::T_COALESCE): - $expr = $this->CoalesceExpression(); - break; - - case $this->isFunction(): - $expr = $this->FunctionDeclaration(); - break; - - default: - // We need to check if we are in a IdentificationVariable or SingleValuedPathExpression - $glimpse = $this->lexer->glimpse(); - - if ($glimpse['type'] === Lexer::T_DOT) { - $expr = $this->SingleValuedPathExpression(); - - // Leave switch statement - break; - } - - $lookaheadValue = $this->lexer->lookahead['value']; - - // Validate existing component - if ( ! isset($this->queryComponents[$lookaheadValue])) { - $this->semanticalError('Cannot add having condition on undefined result variable.'); - } - - // Validate SingleValuedPathExpression (ie.: "product") - if (isset($this->queryComponents[$lookaheadValue]['metadata'])) { - $expr = $this->SingleValuedPathExpression(); - break; - } - - // Validating ResultVariable - if ( ! isset($this->queryComponents[$lookaheadValue]['resultVariable'])) { - $this->semanticalError('Cannot add having condition on a non result variable.'); - } - - $expr = $this->ResultVariable(); - break; - } - - $nullCompExpr = new AST\NullComparisonExpression($expr); - - $this->match(Lexer::T_IS); - - if ($this->lexer->isNextToken(Lexer::T_NOT)) { - $this->match(Lexer::T_NOT); - - $nullCompExpr->not = true; - } - - $this->match(Lexer::T_NULL); - - return $nullCompExpr; - } - - /** - * ExistsExpression ::= ["NOT"] "EXISTS" "(" Subselect ")" - * - * @return \Doctrine\ORM\Query\AST\ExistsExpression - */ - public function ExistsExpression() - { - $not = false; - - if ($this->lexer->isNextToken(Lexer::T_NOT)) { - $this->match(Lexer::T_NOT); - $not = true; - } - - $this->match(Lexer::T_EXISTS); - $this->match(Lexer::T_OPEN_PARENTHESIS); - - $existsExpression = new AST\ExistsExpression($this->Subselect()); - $existsExpression->not = $not; - - $this->match(Lexer::T_CLOSE_PARENTHESIS); - - return $existsExpression; - } - - /** - * ComparisonOperator ::= "=" | "<" | "<=" | "<>" | ">" | ">=" | "!=" - * - * @return string - */ - public function ComparisonOperator() - { - switch ($this->lexer->lookahead['value']) { - case '=': - $this->match(Lexer::T_EQUALS); - - return '='; - - case '<': - $this->match(Lexer::T_LOWER_THAN); - $operator = '<'; - - if ($this->lexer->isNextToken(Lexer::T_EQUALS)) { - $this->match(Lexer::T_EQUALS); - $operator .= '='; - } else if ($this->lexer->isNextToken(Lexer::T_GREATER_THAN)) { - $this->match(Lexer::T_GREATER_THAN); - $operator .= '>'; - } - - return $operator; - - case '>': - $this->match(Lexer::T_GREATER_THAN); - $operator = '>'; - - if ($this->lexer->isNextToken(Lexer::T_EQUALS)) { - $this->match(Lexer::T_EQUALS); - $operator .= '='; - } - - return $operator; - - case '!': - $this->match(Lexer::T_NEGATE); - $this->match(Lexer::T_EQUALS); - - return '<>'; - - default: - $this->syntaxError('=, <, <=, <>, >, >=, !='); - } - } - - /** - * FunctionDeclaration ::= FunctionsReturningStrings | FunctionsReturningNumerics | FunctionsReturningDatetime - * - * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode - */ - public function FunctionDeclaration() - { - $token = $this->lexer->lookahead; - $funcName = strtolower($token['value']); - - $customFunctionDeclaration = $this->CustomFunctionDeclaration(); - - // Check for custom functions functions first! - switch (true) { - case $customFunctionDeclaration !== null: - return $customFunctionDeclaration; - - case (isset(self::$_STRING_FUNCTIONS[$funcName])): - return $this->FunctionsReturningStrings(); - - case (isset(self::$_NUMERIC_FUNCTIONS[$funcName])): - return $this->FunctionsReturningNumerics(); - - case (isset(self::$_DATETIME_FUNCTIONS[$funcName])): - return $this->FunctionsReturningDatetime(); - - default: - $this->syntaxError('known function', $token); - } - } - - /** - * Helper function for FunctionDeclaration grammar rule. - * - * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode - */ - private function CustomFunctionDeclaration() - { - $token = $this->lexer->lookahead; - $funcName = strtolower($token['value']); - - // Check for custom functions afterwards - $config = $this->em->getConfiguration(); - - switch (true) { - case ($config->getCustomStringFunction($funcName) !== null): - return $this->CustomFunctionsReturningStrings(); - - case ($config->getCustomNumericFunction($funcName) !== null): - return $this->CustomFunctionsReturningNumerics(); - - case ($config->getCustomDatetimeFunction($funcName) !== null): - return $this->CustomFunctionsReturningDatetime(); - - default: - return null; - } - } - - /** - * FunctionsReturningNumerics ::= - * "LENGTH" "(" StringPrimary ")" | - * "LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" | - * "ABS" "(" SimpleArithmeticExpression ")" | - * "SQRT" "(" SimpleArithmeticExpression ")" | - * "MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" | - * "SIZE" "(" CollectionValuedPathExpression ")" | - * "DATE_DIFF" "(" ArithmeticPrimary "," ArithmeticPrimary ")" | - * "BIT_AND" "(" ArithmeticPrimary "," ArithmeticPrimary ")" | - * "BIT_OR" "(" ArithmeticPrimary "," ArithmeticPrimary ")" - * - * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode - */ - public function FunctionsReturningNumerics() - { - $funcNameLower = strtolower($this->lexer->lookahead['value']); - $funcClass = self::$_NUMERIC_FUNCTIONS[$funcNameLower]; - - $function = new $funcClass($funcNameLower); - $function->parse($this); - - return $function; - } - - /** - * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode - */ - public function CustomFunctionsReturningNumerics() - { - // getCustomNumericFunction is case-insensitive - $functionName = strtolower($this->lexer->lookahead['value']); - $functionClass = $this->em->getConfiguration()->getCustomNumericFunction($functionName); - - $function = is_string($functionClass) - ? new $functionClass($functionName) - : call_user_func($functionClass, $functionName); - - $function->parse($this); - - return $function; - } - - /** - * FunctionsReturningDateTime ::= - * "CURRENT_DATE" | - * "CURRENT_TIME" | - * "CURRENT_TIMESTAMP" | - * "DATE_ADD" "(" ArithmeticPrimary "," ArithmeticPrimary "," StringPrimary ")" | - * "DATE_SUB" "(" ArithmeticPrimary "," ArithmeticPrimary "," StringPrimary ")" - * - * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode - */ - public function FunctionsReturningDatetime() - { - $funcNameLower = strtolower($this->lexer->lookahead['value']); - $funcClass = self::$_DATETIME_FUNCTIONS[$funcNameLower]; - - $function = new $funcClass($funcNameLower); - $function->parse($this); - - return $function; - } - - /** - * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode - */ - public function CustomFunctionsReturningDatetime() - { - // getCustomDatetimeFunction is case-insensitive - $functionName = $this->lexer->lookahead['value']; - $functionClass = $this->em->getConfiguration()->getCustomDatetimeFunction($functionName); - - $function = is_string($functionClass) - ? new $functionClass($functionName) - : call_user_func($functionClass, $functionName); - - $function->parse($this); - - return $function; - } - - /** - * FunctionsReturningStrings ::= - * "CONCAT" "(" StringPrimary "," StringPrimary {"," StringPrimary}* ")" | - * "SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")" | - * "TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")" | - * "LOWER" "(" StringPrimary ")" | - * "UPPER" "(" StringPrimary ")" | - * "IDENTITY" "(" SingleValuedAssociationPathExpression {"," string} ")" - * - * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode - */ - public function FunctionsReturningStrings() - { - $funcNameLower = strtolower($this->lexer->lookahead['value']); - $funcClass = self::$_STRING_FUNCTIONS[$funcNameLower]; - - $function = new $funcClass($funcNameLower); - $function->parse($this); - - return $function; - } - - /** - * @return \Doctrine\ORM\Query\AST\Functions\FunctionNode - */ - public function CustomFunctionsReturningStrings() - { - // getCustomStringFunction is case-insensitive - $functionName = $this->lexer->lookahead['value']; - $functionClass = $this->em->getConfiguration()->getCustomStringFunction($functionName); - - $function = is_string($functionClass) - ? new $functionClass($functionName) - : call_user_func($functionClass, $functionName); - - $function->parse($this); - - return $function; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParserResult.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParserResult.php deleted file mode 100644 index 84ad178..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ParserResult.php +++ /dev/null @@ -1,145 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -/** - * Encapsulates the resulting components from a DQL query parsing process that - * can be serialized. - * - * @author Guilherme Blanco - * @author Janne Vanhala - * @author Roman Borschel - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://www.doctrine-project.org - * @since 2.0 - */ -class ParserResult -{ - /** - * The SQL executor used for executing the SQL. - * - * @var \Doctrine\ORM\Query\Exec\AbstractSqlExecutor - */ - private $_sqlExecutor; - - /** - * The ResultSetMapping that describes how to map the SQL result set. - * - * @var \Doctrine\ORM\Query\ResultSetMapping - */ - private $_resultSetMapping; - - /** - * The mappings of DQL parameter names/positions to SQL parameter positions. - * - * @var array - */ - private $_parameterMappings = []; - - /** - * Initializes a new instance of the ParserResult class. - * The new instance is initialized with an empty ResultSetMapping. - */ - public function __construct() - { - $this->_resultSetMapping = new ResultSetMapping; - } - - /** - * Gets the ResultSetMapping for the parsed query. - * - * @return ResultSetMapping|null The result set mapping of the parsed query or NULL - * if the query is not a SELECT query. - */ - public function getResultSetMapping() - { - return $this->_resultSetMapping; - } - - /** - * Sets the ResultSetMapping of the parsed query. - * - * @param ResultSetMapping $rsm - * - * @return void - */ - public function setResultSetMapping(ResultSetMapping $rsm) - { - $this->_resultSetMapping = $rsm; - } - - /** - * Sets the SQL executor that should be used for this ParserResult. - * - * @param \Doctrine\ORM\Query\Exec\AbstractSqlExecutor $executor - * - * @return void - */ - public function setSqlExecutor($executor) - { - $this->_sqlExecutor = $executor; - } - - /** - * Gets the SQL executor used by this ParserResult. - * - * @return \Doctrine\ORM\Query\Exec\AbstractSqlExecutor - */ - public function getSqlExecutor() - { - return $this->_sqlExecutor; - } - - /** - * Adds a DQL to SQL parameter mapping. One DQL parameter name/position can map to - * several SQL parameter positions. - * - * @param string|integer $dqlPosition - * @param integer $sqlPosition - * - * @return void - */ - public function addParameterMapping($dqlPosition, $sqlPosition) - { - $this->_parameterMappings[$dqlPosition][] = $sqlPosition; - } - - /** - * Gets all DQL to SQL parameter mappings. - * - * @return array The parameter mappings. - */ - public function getParameterMappings() - { - return $this->_parameterMappings; - } - - /** - * Gets the SQL parameter positions for a DQL parameter name/position. - * - * @param string|integer $dqlPosition The name or position of the DQL parameter. - * - * @return array The positions of the corresponding SQL parameters. - */ - public function getSqlParameterPositions($dqlPosition) - { - return $this->_parameterMappings[$dqlPosition]; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Printer.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Printer.php deleted file mode 100644 index d92ad85..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Printer.php +++ /dev/null @@ -1,98 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -/** - * A parse tree printer for Doctrine Query Language parser. - * - * @author Janne Vanhala - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link http://www.phpdoctrine.org - * @since 2.0 - */ -class Printer -{ - /** - * Current indentation level - * - * @var int - */ - protected $_indent = 0; - - /** - * Defines whether parse tree is printed (default, false) or not (true). - * - * @var bool - */ - protected $_silent; - - /** - * Constructs a new parse tree printer. - * - * @param bool $silent Parse tree will not be printed if true. - */ - public function __construct($silent = false) - { - $this->_silent = $silent; - } - - /** - * Prints an opening parenthesis followed by production name and increases - * indentation level by one. - * - * This method is called before executing a production. - * - * @param string $name Production name. - * - * @return void - */ - public function startProduction($name) - { - $this->println('(' . $name); - $this->_indent++; - } - - /** - * Decreases indentation level by one and prints a closing parenthesis. - * - * This method is called after executing a production. - * - * @return void - */ - public function endProduction() - { - $this->_indent--; - $this->println(')'); - } - - /** - * Prints text indented with spaces depending on current indentation level. - * - * @param string $str The text. - * - * @return void - */ - public function println($str) - { - if ( ! $this->_silent) { - echo str_repeat(' ', $this->_indent), $str, "\n"; - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php deleted file mode 100644 index b78e27b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php +++ /dev/null @@ -1,270 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -use Doctrine\ORM\Query\AST\PathExpression; - -/** - * Description of QueryException. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - */ -class QueryException extends \Doctrine\ORM\ORMException -{ - /** - * @param string $dql - * - * @return QueryException - */ - public static function dqlError($dql) - { - return new self($dql); - } - - /** - * @param string $message - * @param \Exception|null $previous - * - * @return QueryException - */ - public static function syntaxError($message, $previous = null) - { - return new self('[Syntax Error] ' . $message, 0, $previous); - } - - /** - * @param string $message - * @param \Exception|null $previous - * - * @return QueryException - */ - public static function semanticalError($message, $previous = null) - { - return new self('[Semantical Error] ' . $message, 0, $previous); - } - - /** - * @return QueryException - */ - public static function invalidLockMode() - { - return new self('Invalid lock mode hint provided.'); - } - - /** - * @param string $expected - * @param string $received - * - * @return QueryException - */ - public static function invalidParameterType($expected, $received) - { - return new self('Invalid parameter type, ' . $received . ' given, but ' . $expected . ' expected.'); - } - - /** - * @param string $pos - * - * @return QueryException - */ - public static function invalidParameterPosition($pos) - { - return new self('Invalid parameter position: ' . $pos); - } - - /** - * @param integer $expected - * @param integer $received - * - * @return QueryException - */ - public static function tooManyParameters($expected, $received) - { - return new self('Too many parameters: the query defines ' . $expected . ' parameters and you bound ' . $received); - } - - /** - * @param integer $expected - * @param integer $received - * - * @return QueryException - */ - public static function tooFewParameters($expected, $received) - { - return new self('Too few parameters: the query defines ' . $expected . ' parameters but you only bound ' . $received); - } - - /** - * @param string $value - * - * @return QueryException - */ - public static function invalidParameterFormat($value) - { - return new self('Invalid parameter format, '.$value.' given, but : or ? expected.'); - } - - /** - * @param string $key - * - * @return QueryException - */ - public static function unknownParameter($key) - { - return new self("Invalid parameter: token ".$key." is not defined in the query."); - } - - /** - * @return QueryException - */ - public static function parameterTypeMismatch() - { - return new self("DQL Query parameter and type numbers mismatch, but have to be exactly equal."); - } - - /** - * @param object $pathExpr - * - * @return QueryException - */ - public static function invalidPathExpression($pathExpr) - { - return new self( - "Invalid PathExpression '" . $pathExpr->identificationVariable . "." . $pathExpr->field . "'." - ); - } - - /** - * @param string $literal - * - * @return QueryException - */ - public static function invalidLiteral($literal) - { - return new self("Invalid literal '$literal'"); - } - - /** - * @param array $assoc - * - * @return QueryException - */ - public static function iterateWithFetchJoinCollectionNotAllowed($assoc) - { - return new self( - "Invalid query operation: Not allowed to iterate over fetch join collections ". - "in class ".$assoc['sourceEntity']." association ".$assoc['fieldName'] - ); - } - - /** - * @return QueryException - */ - public static function partialObjectsAreDangerous() - { - return new self( - "Loading partial objects is dangerous. Fetch full objects or consider " . - "using a different fetch mode. If you really want partial objects, " . - "set the doctrine.forcePartialLoad query hint to TRUE." - ); - } - - /** - * @param array $assoc - * - * @return QueryException - */ - public static function overwritingJoinConditionsNotYetSupported($assoc) - { - return new self( - "Unsupported query operation: It is not yet possible to overwrite the join ". - "conditions in class ".$assoc['sourceEntityName']." association ".$assoc['fieldName'].". ". - "Use WITH to append additional join conditions to the association." - ); - } - - /** - * @param PathExpression $pathExpr - * - * @return QueryException - */ - public static function associationPathInverseSideNotSupported(PathExpression $pathExpr) - { - return new self( - 'A single-valued association path expression to an inverse side is not supported in DQL queries. ' . - 'Instead of "' . $pathExpr->identificationVariable . '.' . $pathExpr->field . '" use an explicit join.' - ); - } - - /** - * @param array $assoc - * - * @return QueryException - */ - public static function iterateWithFetchJoinNotAllowed($assoc) - { - return new self( - "Iterate with fetch join in class " . $assoc['sourceEntity'] . - " using association " . $assoc['fieldName'] . " not allowed." - ); - } - - /** - * @return QueryException - */ - public static function associationPathCompositeKeyNotSupported() - { - return new self( - "A single-valued association path expression to an entity with a composite primary ". - "key is not supported. Explicitly name the components of the composite primary key ". - "in the query." - ); - } - - /** - * @param string $className - * @param string $rootClass - * - * @return QueryException - */ - public static function instanceOfUnrelatedClass($className, $rootClass) - { - return new self("Cannot check if a child of '" . $rootClass . "' is instanceof '" . $className . "', " . - "inheritance hierarchy does not exists between these two classes."); - } - - /** - * @param string $dqlAlias - * - * @return QueryException - */ - public static function invalidQueryComponent($dqlAlias) - { - return new self( - "Invalid query component given for DQL alias '" . $dqlAlias . "', ". - "requires 'metadata', 'parent', 'relation', 'map', 'nestingLevel' and 'token' keys." - ); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryExpressionVisitor.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryExpressionVisitor.php deleted file mode 100644 index 0381ac0..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryExpressionVisitor.php +++ /dev/null @@ -1,224 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -use Doctrine\Common\Collections\ArrayCollection; - -use Doctrine\Common\Collections\Expr\ExpressionVisitor; -use Doctrine\Common\Collections\Expr\Comparison; -use Doctrine\Common\Collections\Expr\CompositeExpression; -use Doctrine\Common\Collections\Expr\Value; - -/** - * Converts Collection expressions to Query expressions. - * - * @author Kirill chEbba Chebunin - * @since 2.4 - */ -class QueryExpressionVisitor extends ExpressionVisitor -{ - /** - * @var array - */ - private static $operatorMap = [ - Comparison::GT => Expr\Comparison::GT, - Comparison::GTE => Expr\Comparison::GTE, - Comparison::LT => Expr\Comparison::LT, - Comparison::LTE => Expr\Comparison::LTE - ]; - - /** - * @var array - */ - private $queryAliases; - - /** - * @var Expr - */ - private $expr; - - /** - * @var array - */ - private $parameters = []; - - /** - * Constructor - * - * @param array $queryAliases - */ - public function __construct($queryAliases) - { - $this->queryAliases = $queryAliases; - $this->expr = new Expr(); - } - - /** - * Gets bound parameters. - * Filled after {@link dispach()}. - * - * @return \Doctrine\Common\Collections\Collection - */ - public function getParameters() - { - return new ArrayCollection($this->parameters); - } - - /** - * Clears parameters. - * - * @return void - */ - public function clearParameters() - { - $this->parameters = []; - } - - /** - * Converts Criteria expression to Query one based on static map. - * - * @param string $criteriaOperator - * - * @return string|null - */ - private static function convertComparisonOperator($criteriaOperator) - { - return isset(self::$operatorMap[$criteriaOperator]) ? self::$operatorMap[$criteriaOperator] : null; - } - - /** - * {@inheritDoc} - */ - public function walkCompositeExpression(CompositeExpression $expr) - { - $expressionList = []; - - foreach ($expr->getExpressionList() as $child) { - $expressionList[] = $this->dispatch($child); - } - - switch($expr->getType()) { - case CompositeExpression::TYPE_AND: - return new Expr\Andx($expressionList); - - case CompositeExpression::TYPE_OR: - return new Expr\Orx($expressionList); - - default: - throw new \RuntimeException("Unknown composite " . $expr->getType()); - } - } - - /** - * {@inheritDoc} - */ - public function walkComparison(Comparison $comparison) - { - - if ( ! isset($this->queryAliases[0])) { - throw new QueryException('No aliases are set before invoking walkComparison().'); - } - - $field = $this->queryAliases[0] . '.' . $comparison->getField(); - - foreach($this->queryAliases as $alias) { - if(strpos($comparison->getField() . '.', $alias . '.') === 0) { - $field = $comparison->getField(); - break; - } - } - - $parameterName = str_replace('.', '_', $comparison->getField()); - - foreach ($this->parameters as $parameter) { - if ($parameter->getName() === $parameterName) { - $parameterName .= '_' . count($this->parameters); - break; - } - } - - $parameter = new Parameter($parameterName, $this->walkValue($comparison->getValue())); - $placeholder = ':' . $parameterName; - - switch ($comparison->getOperator()) { - case Comparison::IN: - $this->parameters[] = $parameter; - - return $this->expr->in($field, $placeholder); - case Comparison::NIN: - $this->parameters[] = $parameter; - - return $this->expr->notIn($field, $placeholder); - case Comparison::EQ: - case Comparison::IS: - if ($this->walkValue($comparison->getValue()) === null) { - return $this->expr->isNull($field); - } - $this->parameters[] = $parameter; - - return $this->expr->eq($field, $placeholder); - case Comparison::NEQ: - if ($this->walkValue($comparison->getValue()) === null) { - return $this->expr->isNotNull($field); - } - $this->parameters[] = $parameter; - - return $this->expr->neq($field, $placeholder); - case Comparison::CONTAINS: - $parameter->setValue('%' . $parameter->getValue() . '%', $parameter->getType()); - $this->parameters[] = $parameter; - - return $this->expr->like($field, $placeholder); - case Comparison::MEMBER_OF: - return $this->expr->isMemberOf($comparison->getField(), $comparison->getValue()->getValue()); - case Comparison::STARTS_WITH: - $parameter->setValue($parameter->getValue() . '%', $parameter->getType()); - $this->parameters[] = $parameter; - - return $this->expr->like($field, $placeholder); - case Comparison::ENDS_WITH: - $parameter->setValue('%' . $parameter->getValue(), $parameter->getType()); - $this->parameters[] = $parameter; - - return $this->expr->like($field, $placeholder); - default: - $operator = self::convertComparisonOperator($comparison->getOperator()); - if ($operator) { - $this->parameters[] = $parameter; - - return new Expr\Comparison( - $field, - $operator, - $placeholder - ); - } - - throw new \RuntimeException("Unknown comparison operator: " . $comparison->getOperator()); - } - } - - /** - * {@inheritDoc} - */ - public function walkValue(Value $value) - { - return $value->getValue(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMapping.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMapping.php deleted file mode 100644 index 640b8e6..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMapping.php +++ /dev/null @@ -1,586 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -/** - * A ResultSetMapping describes how a result set of an SQL query maps to a Doctrine result. - * - * IMPORTANT NOTE: - * The properties of this class are only public for fast internal READ access and to (drastically) - * reduce the size of serialized instances for more effective caching due to better (un-)serialization - * performance. - * - * Users should use the public methods. - * - * @author Roman Borschel - * @since 2.0 - * @todo Think about whether the number of lookup maps can be reduced. - */ -class ResultSetMapping -{ - /** - * Whether the result is mixed (contains scalar values together with field values). - * - * @ignore - * @var boolean - */ - public $isMixed = false; - - /** - * Whether the result is a select statement. - * - * @ignore - * @var boolean - */ - public $isSelect = true; - - /** - * Maps alias names to class names. - * - * @ignore - * @var array - */ - public $aliasMap = []; - - /** - * Maps alias names to related association field names. - * - * @ignore - * @var array - */ - public $relationMap = []; - - /** - * Maps alias names to parent alias names. - * - * @ignore - * @var array - */ - public $parentAliasMap = []; - - /** - * Maps column names in the result set to field names for each class. - * - * @ignore - * @var array - */ - public $fieldMappings = []; - - /** - * Maps column names in the result set to the alias/field name to use in the mapped result. - * - * @ignore - * @var array - */ - public $scalarMappings = []; - - /** - * Maps column names in the result set to the alias/field type to use in the mapped result. - * - * @ignore - * @var array - */ - public $typeMappings = []; - - /** - * Maps entities in the result set to the alias name to use in the mapped result. - * - * @ignore - * @var array - */ - public $entityMappings = []; - - /** - * Maps column names of meta columns (foreign keys, discriminator columns, ...) to field names. - * - * @ignore - * @var array - */ - public $metaMappings = []; - - /** - * Maps column names in the result set to the alias they belong to. - * - * @ignore - * @var array - */ - public $columnOwnerMap = []; - - /** - * List of columns in the result set that are used as discriminator columns. - * - * @ignore - * @var array - */ - public $discriminatorColumns = []; - - /** - * Maps alias names to field names that should be used for indexing. - * - * @ignore - * @var array - */ - public $indexByMap = []; - - /** - * Map from column names to class names that declare the field the column is mapped to. - * - * @ignore - * @var array - */ - public $declaringClasses = []; - - /** - * This is necessary to hydrate derivate foreign keys correctly. - * - * @var array - */ - public $isIdentifierColumn = []; - - /** - * Maps column names in the result set to field names for each new object expression. - * - * @var array - */ - public $newObjectMappings = []; - - /** - * Maps metadata parameter names to the metadata attribute. - * - * @var array - */ - public $metadataParameterMapping = []; - - /** - * Contains query parameter names to be resolved as discriminator values - * - * @var array - */ - public $discriminatorParameters = []; - - /** - * Adds an entity result to this ResultSetMapping. - * - * @param string $class The class name of the entity. - * @param string $alias The alias for the class. The alias must be unique among all entity - * results or joined entity results within this ResultSetMapping. - * @param string|null $resultAlias The result alias with which the entity result should be - * placed in the result structure. - * - * @return ResultSetMapping This ResultSetMapping instance. - * - * @todo Rename: addRootEntity - */ - public function addEntityResult($class, $alias, $resultAlias = null) - { - $this->aliasMap[$alias] = $class; - $this->entityMappings[$alias] = $resultAlias; - - if ($resultAlias !== null) { - $this->isMixed = true; - } - - return $this; - } - - /** - * Sets a discriminator column for an entity result or joined entity result. - * The discriminator column will be used to determine the concrete class name to - * instantiate. - * - * @param string $alias The alias of the entity result or joined entity result the discriminator - * column should be used for. - * @param string $discrColumn The name of the discriminator column in the SQL result set. - * - * @return ResultSetMapping This ResultSetMapping instance. - * - * @todo Rename: addDiscriminatorColumn - */ - public function setDiscriminatorColumn($alias, $discrColumn) - { - $this->discriminatorColumns[$alias] = $discrColumn; - $this->columnOwnerMap[$discrColumn] = $alias; - - return $this; - } - - /** - * Sets a field to use for indexing an entity result or joined entity result. - * - * @param string $alias The alias of an entity result or joined entity result. - * @param string $fieldName The name of the field to use for indexing. - * - * @return ResultSetMapping This ResultSetMapping instance. - */ - public function addIndexBy($alias, $fieldName) - { - $found = false; - - foreach (array_merge($this->metaMappings, $this->fieldMappings) as $columnName => $columnFieldName) { - if ( ! ($columnFieldName === $fieldName && $this->columnOwnerMap[$columnName] === $alias)) continue; - - $this->addIndexByColumn($alias, $columnName); - $found = true; - - break; - } - - /* TODO: check if this exception can be put back, for now it's gone because of assumptions made by some ORM internals - if ( ! $found) { - $message = sprintf( - 'Cannot add index by for DQL alias %s and field %s without calling addFieldResult() for them before.', - $alias, - $fieldName - ); - - throw new \LogicException($message); - } - */ - - return $this; - } - - /** - * Sets to index by a scalar result column name. - * - * @param string $resultColumnName - * - * @return ResultSetMapping This ResultSetMapping instance. - */ - public function addIndexByScalar($resultColumnName) - { - $this->indexByMap['scalars'] = $resultColumnName; - - return $this; - } - - /** - * Sets a column to use for indexing an entity or joined entity result by the given alias name. - * - * @param string $alias - * @param string $resultColumnName - * - * @return ResultSetMapping This ResultSetMapping instance. - */ - public function addIndexByColumn($alias, $resultColumnName) - { - $this->indexByMap[$alias] = $resultColumnName; - - return $this; - } - - /** - * Checks whether an entity result or joined entity result with a given alias has - * a field set for indexing. - * - * @param string $alias - * - * @return boolean - * - * @todo Rename: isIndexed($alias) - */ - public function hasIndexBy($alias) - { - return isset($this->indexByMap[$alias]); - } - - /** - * Checks whether the column with the given name is mapped as a field result - * as part of an entity result or joined entity result. - * - * @param string $columnName The name of the column in the SQL result set. - * - * @return boolean - * - * @todo Rename: isField - */ - public function isFieldResult($columnName) - { - return isset($this->fieldMappings[$columnName]); - } - - /** - * Adds a field to the result that belongs to an entity or joined entity. - * - * @param string $alias The alias of the root entity or joined entity to which the field belongs. - * @param string $columnName The name of the column in the SQL result set. - * @param string $fieldName The name of the field on the declaring class. - * @param string|null $declaringClass The name of the class that declares/owns the specified field. - * When $alias refers to a superclass in a mapped hierarchy but - * the field $fieldName is defined on a subclass, specify that here. - * If not specified, the field is assumed to belong to the class - * designated by $alias. - * - * @return ResultSetMapping This ResultSetMapping instance. - * - * @todo Rename: addField - */ - public function addFieldResult($alias, $columnName, $fieldName, $declaringClass = null) - { - // column name (in result set) => field name - $this->fieldMappings[$columnName] = $fieldName; - // column name => alias of owner - $this->columnOwnerMap[$columnName] = $alias; - // field name => class name of declaring class - $this->declaringClasses[$columnName] = $declaringClass ?: $this->aliasMap[$alias]; - - if ( ! $this->isMixed && $this->scalarMappings) { - $this->isMixed = true; - } - - return $this; - } - - /** - * Adds a joined entity result. - * - * @param string $class The class name of the joined entity. - * @param string $alias The unique alias to use for the joined entity. - * @param string $parentAlias The alias of the entity result that is the parent of this joined result. - * @param string $relation The association field that connects the parent entity result - * with the joined entity result. - * - * @return ResultSetMapping This ResultSetMapping instance. - * - * @todo Rename: addJoinedEntity - */ - public function addJoinedEntityResult($class, $alias, $parentAlias, $relation) - { - $this->aliasMap[$alias] = $class; - $this->parentAliasMap[$alias] = $parentAlias; - $this->relationMap[$alias] = $relation; - - return $this; - } - - /** - * Adds a scalar result mapping. - * - * @param string $columnName The name of the column in the SQL result set. - * @param string $alias The result alias with which the scalar result should be placed in the result structure. - * @param string $type The column type - * - * @return ResultSetMapping This ResultSetMapping instance. - * - * @todo Rename: addScalar - */ - public function addScalarResult($columnName, $alias, $type = 'string') - { - $this->scalarMappings[$columnName] = $alias; - $this->typeMappings[$columnName] = $type; - - if ( ! $this->isMixed && $this->fieldMappings) { - $this->isMixed = true; - } - - return $this; - } - - /** - * Adds a metadata parameter mappings. - * - * @param mixed $parameter The parameter name in the SQL result set. - * @param string $attribute The metadata attribute. - */ - public function addMetadataParameterMapping($parameter, $attribute) - { - $this->metadataParameterMapping[$parameter] = $attribute; - } - - /** - * Checks whether a column with a given name is mapped as a scalar result. - * - * @param string $columnName The name of the column in the SQL result set. - * - * @return boolean - * - * @todo Rename: isScalar - */ - public function isScalarResult($columnName) - { - return isset($this->scalarMappings[$columnName]); - } - - /** - * Gets the name of the class of an entity result or joined entity result, - * identified by the given unique alias. - * - * @param string $alias - * - * @return string - */ - public function getClassName($alias) - { - return $this->aliasMap[$alias]; - } - - /** - * Gets the field alias for a column that is mapped as a scalar value. - * - * @param string $columnName The name of the column in the SQL result set. - * - * @return string - */ - public function getScalarAlias($columnName) - { - return $this->scalarMappings[$columnName]; - } - - /** - * Gets the name of the class that owns a field mapping for the specified column. - * - * @param string $columnName - * - * @return string - */ - public function getDeclaringClass($columnName) - { - return $this->declaringClasses[$columnName]; - } - - /** - * @param string $alias - * - * @return string - */ - public function getRelation($alias) - { - return $this->relationMap[$alias]; - } - - /** - * @param string $alias - * - * @return boolean - */ - public function isRelation($alias) - { - return isset($this->relationMap[$alias]); - } - - /** - * Gets the alias of the class that owns a field mapping for the specified column. - * - * @param string $columnName - * - * @return string - */ - public function getEntityAlias($columnName) - { - return $this->columnOwnerMap[$columnName]; - } - - /** - * Gets the parent alias of the given alias. - * - * @param string $alias - * - * @return string - */ - public function getParentAlias($alias) - { - return $this->parentAliasMap[$alias]; - } - - /** - * Checks whether the given alias has a parent alias. - * - * @param string $alias - * - * @return boolean - */ - public function hasParentAlias($alias) - { - return isset($this->parentAliasMap[$alias]); - } - - /** - * Gets the field name for a column name. - * - * @param string $columnName - * - * @return string - */ - public function getFieldName($columnName) - { - return $this->fieldMappings[$columnName]; - } - - /** - * @return array - */ - public function getAliasMap() - { - return $this->aliasMap; - } - - /** - * Gets the number of different entities that appear in the mapped result. - * - * @return integer - */ - public function getEntityResultCount() - { - return count($this->aliasMap); - } - - /** - * Checks whether this ResultSetMapping defines a mixed result. - * - * Mixed results can only occur in object and array (graph) hydration. In such a - * case a mixed result means that scalar values are mixed with objects/array in - * the result. - * - * @return boolean - */ - public function isMixedResult() - { - return $this->isMixed; - } - - /** - * Adds a meta column (foreign key or discriminator column) to the result set. - * - * @param string $alias The result alias with which the meta result should be placed in the result structure. - * @param string $columnName The name of the column in the SQL result set. - * @param string $fieldName The name of the field on the declaring class. - * @param bool $isIdentifierColumn - * @param string $type The column type - * - * @return ResultSetMapping This ResultSetMapping instance. - * - * @todo Make all methods of this class require all parameters and not infer anything - */ - public function addMetaResult($alias, $columnName, $fieldName, $isIdentifierColumn = false, $type = null) - { - $this->metaMappings[$columnName] = $fieldName; - $this->columnOwnerMap[$columnName] = $alias; - - if ($isIdentifierColumn) { - $this->isIdentifierColumn[$alias][$columnName] = true; - } - - if ($type) { - $this->typeMappings[$columnName] = $type; - } - - return $this; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php deleted file mode 100644 index 0bf1181..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/ResultSetMappingBuilder.php +++ /dev/null @@ -1,473 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\ORM\Mapping\MappingException; -use Doctrine\ORM\Utility\PersisterHelper; - -/** - * A ResultSetMappingBuilder uses the EntityManager to automatically populate entity fields. - * - * @author Michael Ridgway - * @since 2.1 - */ -class ResultSetMappingBuilder extends ResultSetMapping -{ - /** - * Picking this rename mode will register entity columns as is, - * as they are in the database. This can cause clashes when multiple - * entities are fetched that have columns with the same name. - * - * @var int - */ - const COLUMN_RENAMING_NONE = 1; - - /** - * Picking custom renaming allows the user to define the renaming - * of specific columns with a rename array that contains column names as - * keys and result alias as values. - * - * @var int - */ - const COLUMN_RENAMING_CUSTOM = 2; - - /** - * Incremental renaming uses a result set mapping internal counter to add a - * number to each column result, leading to uniqueness. This only works if - * you use {@see generateSelectClause()} to generate the SELECT clause for - * you. - * - * @var int - */ - const COLUMN_RENAMING_INCREMENT = 3; - - /** - * @var int - */ - private $sqlCounter = 0; - - /** - * @var EntityManagerInterface - */ - private $em; - - /** - * Default column renaming mode. - * - * @var int - */ - private $defaultRenameMode; - - /** - * @param EntityManagerInterface $em - * @param integer $defaultRenameMode - */ - public function __construct(EntityManagerInterface $em, $defaultRenameMode = self::COLUMN_RENAMING_NONE) - { - $this->em = $em; - $this->defaultRenameMode = $defaultRenameMode; - } - - /** - * Adds a root entity and all of its fields to the result set. - * - * @param string $class The class name of the root entity. - * @param string $alias The unique alias to use for the root entity. - * @param array $renamedColumns Columns that have been renamed (tableColumnName => queryColumnName). - * @param int|null $renameMode One of the COLUMN_RENAMING_* constants or array for BC reasons (CUSTOM). - * - * @return void - */ - public function addRootEntityFromClassMetadata($class, $alias, $renamedColumns = [], $renameMode = null) - { - $renameMode = $renameMode ?: $this->defaultRenameMode; - $columnAliasMap = $this->getColumnAliasMap($class, $renameMode, $renamedColumns); - - $this->addEntityResult($class, $alias); - $this->addAllClassFields($class, $alias, $columnAliasMap); - } - - /** - * Adds a joined entity and all of its fields to the result set. - * - * @param string $class The class name of the joined entity. - * @param string $alias The unique alias to use for the joined entity. - * @param string $parentAlias The alias of the entity result that is the parent of this joined result. - * @param string $relation The association field that connects the parent entity result - * with the joined entity result. - * @param array $renamedColumns Columns that have been renamed (tableColumnName => queryColumnName). - * @param int|null $renameMode One of the COLUMN_RENAMING_* constants or array for BC reasons (CUSTOM). - * - * @return void - */ - public function addJoinedEntityFromClassMetadata($class, $alias, $parentAlias, $relation, $renamedColumns = [], $renameMode = null) - { - $renameMode = $renameMode ?: $this->defaultRenameMode; - $columnAliasMap = $this->getColumnAliasMap($class, $renameMode, $renamedColumns); - - $this->addJoinedEntityResult($class, $alias, $parentAlias, $relation); - $this->addAllClassFields($class, $alias, $columnAliasMap); - } - - /** - * Adds all fields of the given class to the result set mapping (columns and meta fields). - * - * @param string $class - * @param string $alias - * @param array $columnAliasMap - * - * @return void - * - * @throws \InvalidArgumentException - */ - protected function addAllClassFields($class, $alias, $columnAliasMap = []) - { - $classMetadata = $this->em->getClassMetadata($class); - $platform = $this->em->getConnection()->getDatabasePlatform(); - - if ( ! $this->isInheritanceSupported($classMetadata)) { - throw new \InvalidArgumentException('ResultSetMapping builder does not currently support your inheritance scheme.'); - } - - - foreach ($classMetadata->getColumnNames() as $columnName) { - $propertyName = $classMetadata->getFieldName($columnName); - $columnAlias = $platform->getSQLResultCasing($columnAliasMap[$columnName]); - - if (isset($this->fieldMappings[$columnAlias])) { - throw new \InvalidArgumentException("The column '$columnName' conflicts with another column in the mapper."); - } - - $this->addFieldResult($alias, $columnAlias, $propertyName); - } - - foreach ($classMetadata->associationMappings as $associationMapping) { - if ($associationMapping['isOwningSide'] && $associationMapping['type'] & ClassMetadataInfo::TO_ONE) { - $targetClass = $this->em->getClassMetadata($associationMapping['targetEntity']); - $isIdentifier = isset($associationMapping['id']) && $associationMapping['id'] === true; - - foreach ($associationMapping['joinColumns'] as $joinColumn) { - $columnName = $joinColumn['name']; - $columnAlias = $platform->getSQLResultCasing($columnAliasMap[$columnName]); - $columnType = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); - - if (isset($this->metaMappings[$columnAlias])) { - throw new \InvalidArgumentException("The column '$columnAlias' conflicts with another column in the mapper."); - } - - $this->addMetaResult($alias, $columnAlias, $columnName, $isIdentifier, $columnType); - } - } - } - } - - private function isInheritanceSupported(ClassMetadataInfo $classMetadata) - { - if ($classMetadata->isInheritanceTypeSingleTable() - && in_array($classMetadata->name, $classMetadata->discriminatorMap, true)) { - return true; - } - - return ! ($classMetadata->isInheritanceTypeSingleTable() || $classMetadata->isInheritanceTypeJoined()); - } - - /** - * Gets column alias for a given column. - * - * @param string $columnName - * @param int $mode - * @param array $customRenameColumns - * - * @return string - */ - private function getColumnAlias($columnName, $mode, array $customRenameColumns) - { - switch ($mode) { - case self::COLUMN_RENAMING_INCREMENT: - return $columnName . $this->sqlCounter++; - - case self::COLUMN_RENAMING_CUSTOM: - return $customRenameColumns[$columnName] ?? $columnName; - - case self::COLUMN_RENAMING_NONE: - return $columnName; - - } - } - - /** - * Retrieves a class columns and join columns aliases that are used in the SELECT clause. - * - * This depends on the renaming mode selected by the user. - * - * @param string $className - * @param int $mode - * @param array $customRenameColumns - * - * @return array - */ - private function getColumnAliasMap($className, $mode, array $customRenameColumns) - { - if ($customRenameColumns) { // for BC with 2.2-2.3 API - $mode = self::COLUMN_RENAMING_CUSTOM; - } - - $columnAlias = []; - $class = $this->em->getClassMetadata($className); - - foreach ($class->getColumnNames() as $columnName) { - $columnAlias[$columnName] = $this->getColumnAlias($columnName, $mode, $customRenameColumns); - } - - foreach ($class->associationMappings as $associationMapping) { - if ($associationMapping['isOwningSide'] && $associationMapping['type'] & ClassMetadataInfo::TO_ONE) { - foreach ($associationMapping['joinColumns'] as $joinColumn) { - $columnName = $joinColumn['name']; - $columnAlias[$columnName] = $this->getColumnAlias($columnName, $mode, $customRenameColumns); - } - } - } - - return $columnAlias; - } - - /** - * Adds the mappings of the results of native SQL queries to the result set. - * - * @param ClassMetadataInfo $class - * @param array $queryMapping - * - * @return ResultSetMappingBuilder - */ - public function addNamedNativeQueryMapping(ClassMetadataInfo $class, array $queryMapping) - { - if (isset($queryMapping['resultClass'])) { - return $this->addNamedNativeQueryResultClassMapping($class, $queryMapping['resultClass']); - } - - return $this->addNamedNativeQueryResultSetMapping($class, $queryMapping['resultSetMapping']); - } - - /** - * Adds the class mapping of the results of native SQL queries to the result set. - * - * @param ClassMetadataInfo $class - * @param string $resultClassName - * - * @return ResultSetMappingBuilder - */ - public function addNamedNativeQueryResultClassMapping(ClassMetadataInfo $class, $resultClassName) - { - $classMetadata = $this->em->getClassMetadata($resultClassName); - $shortName = $classMetadata->reflClass->getShortName(); - $alias = strtolower($shortName[0]).'0'; - - $this->addEntityResult($class->name, $alias); - - if ($classMetadata->discriminatorColumn) { - $discrColumn = $classMetadata->discriminatorColumn; - - $this->setDiscriminatorColumn($alias, $discrColumn['name']); - $this->addMetaResult($alias, $discrColumn['name'], $discrColumn['fieldName'], false, $discrColumn['type']); - } - - foreach ($classMetadata->getColumnNames() as $key => $columnName) { - $propertyName = $classMetadata->getFieldName($columnName); - - $this->addFieldResult($alias, $columnName, $propertyName); - } - - foreach ($classMetadata->associationMappings as $associationMapping) { - if ($associationMapping['isOwningSide'] && $associationMapping['type'] & ClassMetadataInfo::TO_ONE) { - $targetClass = $this->em->getClassMetadata($associationMapping['targetEntity']); - - foreach ($associationMapping['joinColumns'] as $joinColumn) { - $columnName = $joinColumn['name']; - $columnType = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); - - $this->addMetaResult($alias, $columnName, $columnName, $classMetadata->isIdentifier($columnName), $columnType); - } - } - } - - return $this; - } - - /** - * Adds the result set mapping of the results of native SQL queries to the result set. - * - * @param ClassMetadataInfo $class - * @param string $resultSetMappingName - * - * @return ResultSetMappingBuilder - */ - public function addNamedNativeQueryResultSetMapping(ClassMetadataInfo $class, $resultSetMappingName) - { - $counter = 0; - $resultMapping = $class->getSqlResultSetMapping($resultSetMappingName); - $rootShortName = $class->reflClass->getShortName(); - $rootAlias = strtolower($rootShortName[0]) . $counter; - - - if (isset($resultMapping['entities'])) { - foreach ($resultMapping['entities'] as $key => $entityMapping) { - $classMetadata = $this->em->getClassMetadata($entityMapping['entityClass']); - - if ($class->reflClass->name == $classMetadata->reflClass->name) { - $this->addEntityResult($classMetadata->name, $rootAlias); - $this->addNamedNativeQueryEntityResultMapping($classMetadata, $entityMapping, $rootAlias); - } else { - $shortName = $classMetadata->reflClass->getShortName(); - $joinAlias = strtolower($shortName[0]) . ++ $counter; - $associations = $class->getAssociationsByTargetClass($classMetadata->name); - - $this->addNamedNativeQueryEntityResultMapping($classMetadata, $entityMapping, $joinAlias); - - foreach ($associations as $relation => $mapping) { - $this->addJoinedEntityResult($mapping['targetEntity'], $joinAlias, $rootAlias, $relation); - } - } - - } - } - - if (isset($resultMapping['columns'])) { - foreach ($resultMapping['columns'] as $entityMapping) { - $type = isset($class->fieldNames[$entityMapping['name']]) - ? PersisterHelper::getTypeOfColumn($entityMapping['name'], $class, $this->em) - : 'string'; - - $this->addScalarResult($entityMapping['name'], $entityMapping['name'], $type); - } - } - - return $this; - } - - /** - * Adds the entity result mapping of the results of native SQL queries to the result set. - * - * @param ClassMetadataInfo $classMetadata - * @param array $entityMapping - * @param string $alias - * - * @return ResultSetMappingBuilder - * - * @throws MappingException - * @throws \InvalidArgumentException - */ - public function addNamedNativeQueryEntityResultMapping(ClassMetadataInfo $classMetadata, array $entityMapping, $alias) - { - if (isset($entityMapping['discriminatorColumn']) && $entityMapping['discriminatorColumn']) { - $discriminatorColumn = $entityMapping['discriminatorColumn']; - $discriminatorType = $classMetadata->discriminatorColumn['type']; - - $this->setDiscriminatorColumn($alias, $discriminatorColumn); - $this->addMetaResult($alias, $discriminatorColumn, $discriminatorColumn, false, $discriminatorType); - } - - if (isset($entityMapping['fields']) && !empty($entityMapping['fields'])) { - foreach ($entityMapping['fields'] as $field) { - $fieldName = $field['name']; - $relation = null; - - if (strpos($fieldName, '.') !== false) { - list($relation, $fieldName) = explode('.', $fieldName); - } - - if (isset($classMetadata->associationMappings[$relation])) { - if ($relation) { - $associationMapping = $classMetadata->associationMappings[$relation]; - $joinAlias = $alias.$relation; - $parentAlias = $alias; - - $this->addJoinedEntityResult($associationMapping['targetEntity'], $joinAlias, $parentAlias, $relation); - $this->addFieldResult($joinAlias, $field['column'], $fieldName); - } else { - $this->addFieldResult($alias, $field['column'], $fieldName, $classMetadata->name); - } - } else { - if ( ! isset($classMetadata->fieldMappings[$fieldName])) { - throw new \InvalidArgumentException("Entity '".$classMetadata->name."' has no field '".$fieldName."'. "); - } - - $this->addFieldResult($alias, $field['column'], $fieldName, $classMetadata->name); - } - } - - } else { - foreach ($classMetadata->getColumnNames() as $columnName) { - $propertyName = $classMetadata->getFieldName($columnName); - - $this->addFieldResult($alias, $columnName, $propertyName); - } - } - - return $this; - } - - /** - * Generates the Select clause from this ResultSetMappingBuilder. - * - * Works only for all the entity results. The select parts for scalar - * expressions have to be written manually. - * - * @param array $tableAliases - * - * @return string - */ - public function generateSelectClause($tableAliases = []) - { - $sql = ""; - - foreach ($this->columnOwnerMap as $columnName => $dqlAlias) { - $tableAlias = $tableAliases[$dqlAlias] ?? $dqlAlias; - - if ($sql) { - $sql .= ", "; - } - - $sql .= $tableAlias . "."; - - if (isset($this->fieldMappings[$columnName])) { - $class = $this->em->getClassMetadata($this->declaringClasses[$columnName]); - $sql .= $class->fieldMappings[$this->fieldMappings[$columnName]]['columnName']; - } else if (isset($this->metaMappings[$columnName])) { - $sql .= $this->metaMappings[$columnName]; - } else if (isset($this->discriminatorColumns[$dqlAlias])) { - $sql .= $this->discriminatorColumns[$dqlAlias]; - } - - $sql .= " AS " . $columnName; - } - - return $sql; - } - - /** - * @return string - */ - public function __toString() - { - return $this->generateSelectClause([]); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php deleted file mode 100644 index d06d070..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/SqlWalker.php +++ /dev/null @@ -1,2324 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -use Doctrine\DBAL\LockMode; -use Doctrine\DBAL\Types\Type; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\ORM\OptimisticLockException; -use Doctrine\ORM\Query; -use Doctrine\ORM\Utility\HierarchyDiscriminatorResolver; -use Doctrine\ORM\Utility\PersisterHelper; - -/** - * The SqlWalker is a TreeWalker that walks over a DQL AST and constructs - * the corresponding SQL. - * - * @author Guilherme Blanco - * @author Roman Borschel - * @author Benjamin Eberlei - * @author Alexander - * @author Fabio B. Silva - * @since 2.0 - */ -class SqlWalker implements TreeWalker -{ - /** - * @var string - */ - const HINT_DISTINCT = 'doctrine.distinct'; - - /** - * @var ResultSetMapping - */ - private $rsm; - - /** - * Counter for generating unique column aliases. - * - * @var integer - */ - private $aliasCounter = 0; - - /** - * Counter for generating unique table aliases. - * - * @var integer - */ - private $tableAliasCounter = 0; - - /** - * Counter for generating unique scalar result. - * - * @var integer - */ - private $scalarResultCounter = 1; - - /** - * Counter for generating unique parameter indexes. - * - * @var integer - */ - private $sqlParamIndex = 0; - - /** - * Counter for generating indexes. - * - * @var integer - */ - private $newObjectCounter = 0; - - /** - * @var ParserResult - */ - private $parserResult; - - /** - * @var \Doctrine\ORM\EntityManager - */ - private $em; - - /** - * @var \Doctrine\DBAL\Connection - */ - private $conn; - - /** - * @var \Doctrine\ORM\AbstractQuery - */ - private $query; - - /** - * @var array - */ - private $tableAliasMap = []; - - /** - * Map from result variable names to their SQL column alias names. - * - * @var array - */ - private $scalarResultAliasMap = []; - - /** - * Map from Table-Alias + Column-Name to OrderBy-Direction. - * - * @var array - */ - private $orderedColumnsMap = []; - - /** - * Map from DQL-Alias + Field-Name to SQL Column Alias. - * - * @var array - */ - private $scalarFields = []; - - /** - * Map of all components/classes that appear in the DQL query. - * - * @var array - */ - private $queryComponents; - - /** - * A list of classes that appear in non-scalar SelectExpressions. - * - * @var array - */ - private $selectedClasses = []; - - /** - * The DQL alias of the root class of the currently traversed query. - * - * @var array - */ - private $rootAliases = []; - - /** - * Flag that indicates whether to generate SQL table aliases in the SQL. - * These should only be generated for SELECT queries, not for UPDATE/DELETE. - * - * @var boolean - */ - private $useSqlTableAliases = true; - - /** - * The database platform abstraction. - * - * @var \Doctrine\DBAL\Platforms\AbstractPlatform - */ - private $platform; - - /** - * The quote strategy. - * - * @var \Doctrine\ORM\Mapping\QuoteStrategy - */ - private $quoteStrategy; - - /** - * {@inheritDoc} - */ - public function __construct($query, $parserResult, array $queryComponents) - { - $this->query = $query; - $this->parserResult = $parserResult; - $this->queryComponents = $queryComponents; - $this->rsm = $parserResult->getResultSetMapping(); - $this->em = $query->getEntityManager(); - $this->conn = $this->em->getConnection(); - $this->platform = $this->conn->getDatabasePlatform(); - $this->quoteStrategy = $this->em->getConfiguration()->getQuoteStrategy(); - } - - /** - * Gets the Query instance used by the walker. - * - * @return Query. - */ - public function getQuery() - { - return $this->query; - } - - /** - * Gets the Connection used by the walker. - * - * @return \Doctrine\DBAL\Connection - */ - public function getConnection() - { - return $this->conn; - } - - /** - * Gets the EntityManager used by the walker. - * - * @return \Doctrine\ORM\EntityManager - */ - public function getEntityManager() - { - return $this->em; - } - - /** - * Gets the information about a single query component. - * - * @param string $dqlAlias The DQL alias. - * - * @return array - */ - public function getQueryComponent($dqlAlias) - { - return $this->queryComponents[$dqlAlias]; - } - - /** - * {@inheritdoc} - */ - public function getQueryComponents() - { - return $this->queryComponents; - } - - /** - * {@inheritdoc} - */ - public function setQueryComponent($dqlAlias, array $queryComponent) - { - $requiredKeys = ['metadata', 'parent', 'relation', 'map', 'nestingLevel', 'token']; - - if (array_diff($requiredKeys, array_keys($queryComponent))) { - throw QueryException::invalidQueryComponent($dqlAlias); - } - - $this->queryComponents[$dqlAlias] = $queryComponent; - } - - /** - * {@inheritdoc} - */ - public function getExecutor($AST) - { - switch (true) { - case ($AST instanceof AST\DeleteStatement): - $primaryClass = $this->em->getClassMetadata($AST->deleteClause->abstractSchemaName); - - return ($primaryClass->isInheritanceTypeJoined()) - ? new Exec\MultiTableDeleteExecutor($AST, $this) - : new Exec\SingleTableDeleteUpdateExecutor($AST, $this); - - case ($AST instanceof AST\UpdateStatement): - $primaryClass = $this->em->getClassMetadata($AST->updateClause->abstractSchemaName); - - return ($primaryClass->isInheritanceTypeJoined()) - ? new Exec\MultiTableUpdateExecutor($AST, $this) - : new Exec\SingleTableDeleteUpdateExecutor($AST, $this); - - default: - return new Exec\SingleSelectExecutor($AST, $this); - } - } - - /** - * Generates a unique, short SQL table alias. - * - * @param string $tableName Table name - * @param string $dqlAlias The DQL alias. - * - * @return string Generated table alias. - */ - public function getSQLTableAlias($tableName, $dqlAlias = '') - { - $tableName .= ($dqlAlias) ? '@[' . $dqlAlias . ']' : ''; - - if ( ! isset($this->tableAliasMap[$tableName])) { - $this->tableAliasMap[$tableName] = (preg_match('/[a-z]/i', $tableName[0]) ? strtolower($tableName[0]) : 't') - . $this->tableAliasCounter++ . '_'; - } - - return $this->tableAliasMap[$tableName]; - } - - /** - * Forces the SqlWalker to use a specific alias for a table name, rather than - * generating an alias on its own. - * - * @param string $tableName - * @param string $alias - * @param string $dqlAlias - * - * @return string - */ - public function setSQLTableAlias($tableName, $alias, $dqlAlias = '') - { - $tableName .= ($dqlAlias) ? '@[' . $dqlAlias . ']' : ''; - - $this->tableAliasMap[$tableName] = $alias; - - return $alias; - } - - /** - * Gets an SQL column alias for a column name. - * - * @param string $columnName - * - * @return string - */ - public function getSQLColumnAlias($columnName) - { - return $this->quoteStrategy->getColumnAlias($columnName, $this->aliasCounter++, $this->platform); - } - - /** - * Generates the SQL JOINs that are necessary for Class Table Inheritance - * for the given class. - * - * @param ClassMetadata $class The class for which to generate the joins. - * @param string $dqlAlias The DQL alias of the class. - * - * @return string The SQL. - */ - private function _generateClassTableInheritanceJoins($class, $dqlAlias) - { - $sql = ''; - - $baseTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias); - - // INNER JOIN parent class tables - foreach ($class->parentClasses as $parentClassName) { - $parentClass = $this->em->getClassMetadata($parentClassName); - $tableAlias = $this->getSQLTableAlias($parentClass->getTableName(), $dqlAlias); - - // If this is a joined association we must use left joins to preserve the correct result. - $sql .= isset($this->queryComponents[$dqlAlias]['relation']) ? ' LEFT ' : ' INNER '; - $sql .= 'JOIN ' . $this->quoteStrategy->getTableName($parentClass, $this->platform) . ' ' . $tableAlias . ' ON '; - - $sqlParts = []; - - foreach ($this->quoteStrategy->getIdentifierColumnNames($class, $this->platform) as $columnName) { - $sqlParts[] = $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName; - } - - // Add filters on the root class - if ($filterSql = $this->generateFilterConditionSQL($parentClass, $tableAlias)) { - $sqlParts[] = $filterSql; - } - - $sql .= implode(' AND ', $sqlParts); - } - - // Ignore subclassing inclusion if partial objects is disallowed - if ($this->query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) { - return $sql; - } - - // LEFT JOIN child class tables - foreach ($class->subClasses as $subClassName) { - $subClass = $this->em->getClassMetadata($subClassName); - $tableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias); - - $sql .= ' LEFT JOIN ' . $this->quoteStrategy->getTableName($subClass, $this->platform) . ' ' . $tableAlias . ' ON '; - - $sqlParts = []; - - foreach ($this->quoteStrategy->getIdentifierColumnNames($subClass, $this->platform) as $columnName) { - $sqlParts[] = $baseTableAlias . '.' . $columnName . ' = ' . $tableAlias . '.' . $columnName; - } - - $sql .= implode(' AND ', $sqlParts); - } - - return $sql; - } - - /** - * @return string - */ - private function _generateOrderedCollectionOrderByItems() - { - $orderedColumns = []; - - foreach ($this->selectedClasses as $selectedClass) { - $dqlAlias = $selectedClass['dqlAlias']; - $qComp = $this->queryComponents[$dqlAlias]; - - if ( ! isset($qComp['relation']['orderBy'])) { - continue; - } - - $persister = $this->em->getUnitOfWork()->getEntityPersister($qComp['metadata']->name); - - foreach ($qComp['relation']['orderBy'] as $fieldName => $orientation) { - $columnName = $this->quoteStrategy->getColumnName($fieldName, $qComp['metadata'], $this->platform); - $tableName = ($qComp['metadata']->isInheritanceTypeJoined()) - ? $persister->getOwningTable($fieldName) - : $qComp['metadata']->getTableName(); - - $orderedColumn = $this->getSQLTableAlias($tableName, $dqlAlias) . '.' . $columnName; - - // OrderByClause should replace an ordered relation. see - DDC-2475 - if (isset($this->orderedColumnsMap[$orderedColumn])) { - continue; - } - - $this->orderedColumnsMap[$orderedColumn] = $orientation; - $orderedColumns[] = $orderedColumn . ' ' . $orientation; - } - } - - return implode(', ', $orderedColumns); - } - - /** - * Generates a discriminator column SQL condition for the class with the given DQL alias. - * - * @param array $dqlAliases List of root DQL aliases to inspect for discriminator restrictions. - * - * @return string - */ - private function _generateDiscriminatorColumnConditionSQL(array $dqlAliases) - { - $sqlParts = []; - - foreach ($dqlAliases as $dqlAlias) { - $class = $this->queryComponents[$dqlAlias]['metadata']; - - if ( ! $class->isInheritanceTypeSingleTable()) continue; - - $conn = $this->em->getConnection(); - $values = []; - - if ($class->discriminatorValue !== null) { // discriminators can be 0 - $values[] = $conn->quote($class->discriminatorValue); - } - - foreach ($class->subClasses as $subclassName) { - $values[] = $conn->quote($this->em->getClassMetadata($subclassName)->discriminatorValue); - } - - $sqlTableAlias = ($this->useSqlTableAliases) - ? $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.' - : ''; - - $sqlParts[] = $sqlTableAlias . $class->discriminatorColumn['name'] . ' IN (' . implode(', ', $values) . ')'; - } - - $sql = implode(' AND ', $sqlParts); - - return (count($sqlParts) > 1) ? '(' . $sql . ')' : $sql; - } - - /** - * Generates the filter SQL for a given entity and table alias. - * - * @param ClassMetadata $targetEntity Metadata of the target entity. - * @param string $targetTableAlias The table alias of the joined/selected table. - * - * @return string The SQL query part to add to a query. - */ - private function generateFilterConditionSQL(ClassMetadata $targetEntity, $targetTableAlias) - { - if (!$this->em->hasFilters()) { - return ''; - } - - switch($targetEntity->inheritanceType) { - case ClassMetadata::INHERITANCE_TYPE_NONE: - break; - case ClassMetadata::INHERITANCE_TYPE_JOINED: - // The classes in the inheritance will be added to the query one by one, - // but only the root node is getting filtered - if ($targetEntity->name !== $targetEntity->rootEntityName) { - return ''; - } - break; - case ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE: - // With STI the table will only be queried once, make sure that the filters - // are added to the root entity - $targetEntity = $this->em->getClassMetadata($targetEntity->rootEntityName); - break; - default: - //@todo: throw exception? - return ''; - } - - $filterClauses = []; - foreach ($this->em->getFilters()->getEnabledFilters() as $filter) { - if ('' !== $filterExpr = $filter->addFilterConstraint($targetEntity, $targetTableAlias)) { - $filterClauses[] = '(' . $filterExpr . ')'; - } - } - - return implode(' AND ', $filterClauses); - } - - /** - * {@inheritdoc} - */ - public function walkSelectStatement(AST\SelectStatement $AST) - { - $limit = $this->query->getMaxResults(); - $offset = $this->query->getFirstResult(); - $lockMode = $this->query->getHint(Query::HINT_LOCK_MODE); - $sql = $this->walkSelectClause($AST->selectClause) - . $this->walkFromClause($AST->fromClause) - . $this->walkWhereClause($AST->whereClause); - - if ($AST->groupByClause) { - $sql .= $this->walkGroupByClause($AST->groupByClause); - } - - if ($AST->havingClause) { - $sql .= $this->walkHavingClause($AST->havingClause); - } - - if ($AST->orderByClause) { - $sql .= $this->walkOrderByClause($AST->orderByClause); - } - - if ( ! $AST->orderByClause && ($orderBySql = $this->_generateOrderedCollectionOrderByItems())) { - $sql .= ' ORDER BY ' . $orderBySql; - } - - if ($limit !== null || $offset !== null) { - $sql = $this->platform->modifyLimitQuery($sql, $limit, $offset); - } - - if ($lockMode === null || $lockMode === false || $lockMode === LockMode::NONE) { - return $sql; - } - - if ($lockMode === LockMode::PESSIMISTIC_READ) { - return $sql . ' ' . $this->platform->getReadLockSQL(); - } - - if ($lockMode === LockMode::PESSIMISTIC_WRITE) { - return $sql . ' ' . $this->platform->getWriteLockSQL(); - } - - if ($lockMode !== LockMode::OPTIMISTIC) { - throw QueryException::invalidLockMode(); - } - - foreach ($this->selectedClasses as $selectedClass) { - if ( ! $selectedClass['class']->isVersioned) { - throw OptimisticLockException::lockFailed($selectedClass['class']->name); - } - } - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkUpdateStatement(AST\UpdateStatement $AST) - { - $this->useSqlTableAliases = false; - $this->rsm->isSelect = false; - - return $this->walkUpdateClause($AST->updateClause) - . $this->walkWhereClause($AST->whereClause); - } - - /** - * {@inheritdoc} - */ - public function walkDeleteStatement(AST\DeleteStatement $AST) - { - $this->useSqlTableAliases = false; - $this->rsm->isSelect = false; - - return $this->walkDeleteClause($AST->deleteClause) - . $this->walkWhereClause($AST->whereClause); - } - - /** - * Walks down an IdentificationVariable AST node, thereby generating the appropriate SQL. - * This one differs of ->walkIdentificationVariable() because it generates the entity identifiers. - * - * @param string $identVariable - * - * @return string - */ - public function walkEntityIdentificationVariable($identVariable) - { - $class = $this->queryComponents[$identVariable]['metadata']; - $tableAlias = $this->getSQLTableAlias($class->getTableName(), $identVariable); - $sqlParts = []; - - foreach ($this->quoteStrategy->getIdentifierColumnNames($class, $this->platform) as $columnName) { - $sqlParts[] = $tableAlias . '.' . $columnName; - } - - return implode(', ', $sqlParts); - } - - /** - * Walks down an IdentificationVariable (no AST node associated), thereby generating the SQL. - * - * @param string $identificationVariable - * @param string $fieldName - * - * @return string The SQL. - */ - public function walkIdentificationVariable($identificationVariable, $fieldName = null) - { - $class = $this->queryComponents[$identificationVariable]['metadata']; - - if ( - $fieldName !== null && $class->isInheritanceTypeJoined() && - isset($class->fieldMappings[$fieldName]['inherited']) - ) { - $class = $this->em->getClassMetadata($class->fieldMappings[$fieldName]['inherited']); - } - - return $this->getSQLTableAlias($class->getTableName(), $identificationVariable); - } - - /** - * {@inheritdoc} - */ - public function walkPathExpression($pathExpr) - { - $sql = ''; - - /* @var $pathExpr Query\AST\PathExpression */ - switch ($pathExpr->type) { - case AST\PathExpression::TYPE_STATE_FIELD: - $fieldName = $pathExpr->field; - $dqlAlias = $pathExpr->identificationVariable; - $class = $this->queryComponents[$dqlAlias]['metadata']; - - if ($this->useSqlTableAliases) { - $sql .= $this->walkIdentificationVariable($dqlAlias, $fieldName) . '.'; - } - - $sql .= $this->quoteStrategy->getColumnName($fieldName, $class, $this->platform); - break; - - case AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION: - // 1- the owning side: - // Just use the foreign key, i.e. u.group_id - $fieldName = $pathExpr->field; - $dqlAlias = $pathExpr->identificationVariable; - $class = $this->queryComponents[$dqlAlias]['metadata']; - - if (isset($class->associationMappings[$fieldName]['inherited'])) { - $class = $this->em->getClassMetadata($class->associationMappings[$fieldName]['inherited']); - } - - $assoc = $class->associationMappings[$fieldName]; - - if ( ! $assoc['isOwningSide']) { - throw QueryException::associationPathInverseSideNotSupported($pathExpr); - } - - // COMPOSITE KEYS NOT (YET?) SUPPORTED - if (count($assoc['sourceToTargetKeyColumns']) > 1) { - throw QueryException::associationPathCompositeKeyNotSupported(); - } - - if ($this->useSqlTableAliases) { - $sql .= $this->getSQLTableAlias($class->getTableName(), $dqlAlias) . '.'; - } - - $sql .= reset($assoc['targetToSourceKeyColumns']); - break; - - default: - throw QueryException::invalidPathExpression($pathExpr); - } - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkSelectClause($selectClause) - { - $sql = 'SELECT ' . (($selectClause->isDistinct) ? 'DISTINCT ' : ''); - $sqlSelectExpressions = array_filter(array_map([$this, 'walkSelectExpression'], $selectClause->selectExpressions)); - - if ($this->query->getHint(Query::HINT_INTERNAL_ITERATION) == true && $selectClause->isDistinct) { - $this->query->setHint(self::HINT_DISTINCT, true); - } - - $addMetaColumns = ! $this->query->getHint(Query::HINT_FORCE_PARTIAL_LOAD) && - $this->query->getHydrationMode() == Query::HYDRATE_OBJECT - || - $this->query->getHydrationMode() != Query::HYDRATE_OBJECT && - $this->query->getHint(Query::HINT_INCLUDE_META_COLUMNS); - - foreach ($this->selectedClasses as $selectedClass) { - $class = $selectedClass['class']; - $dqlAlias = $selectedClass['dqlAlias']; - $resultAlias = $selectedClass['resultAlias']; - - // Register as entity or joined entity result - if ($this->queryComponents[$dqlAlias]['relation'] === null) { - $this->rsm->addEntityResult($class->name, $dqlAlias, $resultAlias); - } else { - $this->rsm->addJoinedEntityResult( - $class->name, - $dqlAlias, - $this->queryComponents[$dqlAlias]['parent'], - $this->queryComponents[$dqlAlias]['relation']['fieldName'] - ); - } - - if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()) { - // Add discriminator columns to SQL - $rootClass = $this->em->getClassMetadata($class->rootEntityName); - $tblAlias = $this->getSQLTableAlias($rootClass->getTableName(), $dqlAlias); - $discrColumn = $rootClass->discriminatorColumn; - $columnAlias = $this->getSQLColumnAlias($discrColumn['name']); - - $sqlSelectExpressions[] = $tblAlias . '.' . $discrColumn['name'] . ' AS ' . $columnAlias; - - $this->rsm->setDiscriminatorColumn($dqlAlias, $columnAlias); - $this->rsm->addMetaResult($dqlAlias, $columnAlias, $discrColumn['fieldName'], false, $discrColumn['type']); - } - - // Add foreign key columns to SQL, if necessary - if ( ! $addMetaColumns && ! $class->containsForeignIdentifier) { - continue; - } - - // Add foreign key columns of class and also parent classes - foreach ($class->associationMappings as $assoc) { - if ( ! ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) - || ( ! $addMetaColumns && !isset($assoc['id']))) { - continue; - } - - $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); - $isIdentifier = (isset($assoc['id']) && $assoc['id'] === true); - $owningClass = (isset($assoc['inherited'])) ? $this->em->getClassMetadata($assoc['inherited']) : $class; - $sqlTableAlias = $this->getSQLTableAlias($owningClass->getTableName(), $dqlAlias); - - foreach ($assoc['joinColumns'] as $joinColumn) { - $columnName = $joinColumn['name']; - $columnAlias = $this->getSQLColumnAlias($columnName); - $columnType = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); - - $quotedColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); - $sqlSelectExpressions[] = $sqlTableAlias . '.' . $quotedColumnName . ' AS ' . $columnAlias; - - $this->rsm->addMetaResult($dqlAlias, $columnAlias, $columnName, $isIdentifier, $columnType); - } - } - - // Add foreign key columns to SQL, if necessary - if ( ! $addMetaColumns) { - continue; - } - - // Add foreign key columns of subclasses - foreach ($class->subClasses as $subClassName) { - $subClass = $this->em->getClassMetadata($subClassName); - $sqlTableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias); - - foreach ($subClass->associationMappings as $assoc) { - // Skip if association is inherited - if (isset($assoc['inherited'])) continue; - - if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) { - $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); - - foreach ($assoc['joinColumns'] as $joinColumn) { - $columnName = $joinColumn['name']; - $columnAlias = $this->getSQLColumnAlias($columnName); - $columnType = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em); - - $quotedColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $subClass, $this->platform); - $sqlSelectExpressions[] = $sqlTableAlias . '.' . $quotedColumnName . ' AS ' . $columnAlias; - - $this->rsm->addMetaResult($dqlAlias, $columnAlias, $columnName, $subClass->isIdentifier($columnName), $columnType); - } - } - } - } - } - - $sql .= implode(', ', $sqlSelectExpressions); - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkFromClause($fromClause) - { - $identificationVarDecls = $fromClause->identificationVariableDeclarations; - $sqlParts = []; - - foreach ($identificationVarDecls as $identificationVariableDecl) { - $sqlParts[] = $this->walkIdentificationVariableDeclaration($identificationVariableDecl); - } - - return ' FROM ' . implode(', ', $sqlParts); - } - - /** - * Walks down a IdentificationVariableDeclaration AST node, thereby generating the appropriate SQL. - * - * @param AST\IdentificationVariableDeclaration $identificationVariableDecl - * - * @return string - */ - public function walkIdentificationVariableDeclaration($identificationVariableDecl) - { - $sql = $this->walkRangeVariableDeclaration($identificationVariableDecl->rangeVariableDeclaration); - - if ($identificationVariableDecl->indexBy) { - $this->walkIndexBy($identificationVariableDecl->indexBy); - } - - foreach ($identificationVariableDecl->joins as $join) { - $sql .= $this->walkJoin($join); - } - - return $sql; - } - - /** - * Walks down a IndexBy AST node. - * - * @param AST\IndexBy $indexBy - * - * @return void - */ - public function walkIndexBy($indexBy) - { - $pathExpression = $indexBy->simpleStateFieldPathExpression; - $alias = $pathExpression->identificationVariable; - $field = $pathExpression->field; - - if (isset($this->scalarFields[$alias][$field])) { - $this->rsm->addIndexByScalar($this->scalarFields[$alias][$field]); - - return; - } - - $this->rsm->addIndexBy($alias, $field); - } - - /** - * Walks down a RangeVariableDeclaration AST node, thereby generating the appropriate SQL. - * - * @param AST\RangeVariableDeclaration $rangeVariableDeclaration - * - * @return string - */ - public function walkRangeVariableDeclaration($rangeVariableDeclaration) - { - return $this->generateRangeVariableDeclarationSQL($rangeVariableDeclaration, false); - } - - /** - * Generate appropriate SQL for RangeVariableDeclaration AST node - * - * @param AST\RangeVariableDeclaration $rangeVariableDeclaration - * @param bool $buildNestedJoins - * - * @return string - */ - private function generateRangeVariableDeclarationSQL($rangeVariableDeclaration, bool $buildNestedJoins) : string - { - $class = $this->em->getClassMetadata($rangeVariableDeclaration->abstractSchemaName); - $dqlAlias = $rangeVariableDeclaration->aliasIdentificationVariable; - - if ($rangeVariableDeclaration->isRoot) { - $this->rootAliases[] = $dqlAlias; - } - - $sql = $this->platform->appendLockHint( - $this->quoteStrategy->getTableName($class, $this->platform) . ' ' . - $this->getSQLTableAlias($class->getTableName(), $dqlAlias), - $this->query->getHint(Query::HINT_LOCK_MODE) - ); - - if ( ! $class->isInheritanceTypeJoined()) { - return $sql; - } - - $classTableInheritanceJoins = $this->_generateClassTableInheritanceJoins($class, $dqlAlias); - - if ( ! $buildNestedJoins) { - return $sql . $classTableInheritanceJoins; - } - - return $classTableInheritanceJoins === '' ? $sql : '(' . $sql . $classTableInheritanceJoins . ')'; - } - - /** - * Walks down a JoinAssociationDeclaration AST node, thereby generating the appropriate SQL. - * - * @param AST\JoinAssociationDeclaration $joinAssociationDeclaration - * @param int $joinType - * @param AST\ConditionalExpression $condExpr - * - * @return string - * - * @throws QueryException - */ - public function walkJoinAssociationDeclaration($joinAssociationDeclaration, $joinType = AST\Join::JOIN_TYPE_INNER, $condExpr = null) - { - $sql = ''; - - $associationPathExpression = $joinAssociationDeclaration->joinAssociationPathExpression; - $joinedDqlAlias = $joinAssociationDeclaration->aliasIdentificationVariable; - $indexBy = $joinAssociationDeclaration->indexBy; - - $relation = $this->queryComponents[$joinedDqlAlias]['relation']; - $targetClass = $this->em->getClassMetadata($relation['targetEntity']); - $sourceClass = $this->em->getClassMetadata($relation['sourceEntity']); - $targetTableName = $this->quoteStrategy->getTableName($targetClass, $this->platform); - - $targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName(), $joinedDqlAlias); - $sourceTableAlias = $this->getSQLTableAlias($sourceClass->getTableName(), $associationPathExpression->identificationVariable); - - // Ensure we got the owning side, since it has all mapping info - $assoc = ( ! $relation['isOwningSide']) ? $targetClass->associationMappings[$relation['mappedBy']] : $relation; - - if ($this->query->getHint(Query::HINT_INTERNAL_ITERATION) == true && (!$this->query->getHint(self::HINT_DISTINCT) || isset($this->selectedClasses[$joinedDqlAlias]))) { - if ($relation['type'] == ClassMetadata::ONE_TO_MANY || $relation['type'] == ClassMetadata::MANY_TO_MANY) { - throw QueryException::iterateWithFetchJoinNotAllowed($assoc); - } - } - - $targetTableJoin = null; - - // This condition is not checking ClassMetadata::MANY_TO_ONE, because by definition it cannot - // be the owning side and previously we ensured that $assoc is always the owning side of the associations. - // The owning side is necessary at this point because only it contains the JoinColumn information. - switch (true) { - case ($assoc['type'] & ClassMetadata::TO_ONE): - $conditions = []; - - foreach ($assoc['joinColumns'] as $joinColumn) { - $quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); - $quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform); - - if ($relation['isOwningSide']) { - $conditions[] = $sourceTableAlias . '.' . $quotedSourceColumn . ' = ' . $targetTableAlias . '.' . $quotedTargetColumn; - - continue; - } - - $conditions[] = $sourceTableAlias . '.' . $quotedTargetColumn . ' = ' . $targetTableAlias . '.' . $quotedSourceColumn; - } - - // Apply remaining inheritance restrictions - $discrSql = $this->_generateDiscriminatorColumnConditionSQL([$joinedDqlAlias]); - - if ($discrSql) { - $conditions[] = $discrSql; - } - - // Apply the filters - $filterExpr = $this->generateFilterConditionSQL($targetClass, $targetTableAlias); - - if ($filterExpr) { - $conditions[] = $filterExpr; - } - - $targetTableJoin = [ - 'table' => $targetTableName . ' ' . $targetTableAlias, - 'condition' => implode(' AND ', $conditions), - ]; - break; - - case ($assoc['type'] == ClassMetadata::MANY_TO_MANY): - // Join relation table - $joinTable = $assoc['joinTable']; - $joinTableAlias = $this->getSQLTableAlias($joinTable['name'], $joinedDqlAlias); - $joinTableName = $this->quoteStrategy->getJoinTableName($assoc, $sourceClass, $this->platform); - - $conditions = []; - $relationColumns = ($relation['isOwningSide']) - ? $assoc['joinTable']['joinColumns'] - : $assoc['joinTable']['inverseJoinColumns']; - - foreach ($relationColumns as $joinColumn) { - $quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); - $quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform); - - $conditions[] = $sourceTableAlias . '.' . $quotedTargetColumn . ' = ' . $joinTableAlias . '.' . $quotedSourceColumn; - } - - $sql .= $joinTableName . ' ' . $joinTableAlias . ' ON ' . implode(' AND ', $conditions); - - // Join target table - $sql .= ($joinType == AST\Join::JOIN_TYPE_LEFT || $joinType == AST\Join::JOIN_TYPE_LEFTOUTER) ? ' LEFT JOIN ' : ' INNER JOIN '; - - $conditions = []; - $relationColumns = ($relation['isOwningSide']) - ? $assoc['joinTable']['inverseJoinColumns'] - : $assoc['joinTable']['joinColumns']; - - foreach ($relationColumns as $joinColumn) { - $quotedSourceColumn = $this->quoteStrategy->getJoinColumnName($joinColumn, $targetClass, $this->platform); - $quotedTargetColumn = $this->quoteStrategy->getReferencedJoinColumnName($joinColumn, $targetClass, $this->platform); - - $conditions[] = $targetTableAlias . '.' . $quotedTargetColumn . ' = ' . $joinTableAlias . '.' . $quotedSourceColumn; - } - - // Apply remaining inheritance restrictions - $discrSql = $this->_generateDiscriminatorColumnConditionSQL([$joinedDqlAlias]); - - if ($discrSql) { - $conditions[] = $discrSql; - } - - // Apply the filters - $filterExpr = $this->generateFilterConditionSQL($targetClass, $targetTableAlias); - - if ($filterExpr) { - $conditions[] = $filterExpr; - } - - $targetTableJoin = [ - 'table' => $targetTableName . ' ' . $targetTableAlias, - 'condition' => implode(' AND ', $conditions), - ]; - break; - - default: - throw new \BadMethodCallException('Type of association must be one of *_TO_ONE or MANY_TO_MANY'); - } - - // Handle WITH clause - $withCondition = (null === $condExpr) ? '' : ('(' . $this->walkConditionalExpression($condExpr) . ')'); - - if ($targetClass->isInheritanceTypeJoined()) { - $ctiJoins = $this->_generateClassTableInheritanceJoins($targetClass, $joinedDqlAlias); - // If we have WITH condition, we need to build nested joins for target class table and cti joins - if ($withCondition) { - $sql .= '(' . $targetTableJoin['table'] . $ctiJoins . ') ON ' . $targetTableJoin['condition']; - } else { - $sql .= $targetTableJoin['table'] . ' ON ' . $targetTableJoin['condition'] . $ctiJoins; - } - } else { - $sql .= $targetTableJoin['table'] . ' ON ' . $targetTableJoin['condition']; - } - - if ($withCondition) { - $sql .= ' AND ' . $withCondition; - } - - // Apply the indexes - if ($indexBy) { - // For Many-To-One or One-To-One associations this obviously makes no sense, but is ignored silently. - $this->walkIndexBy($indexBy); - } else if (isset($relation['indexBy'])) { - $this->rsm->addIndexBy($joinedDqlAlias, $relation['indexBy']); - } - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkFunction($function) - { - return $function->getSql($this); - } - - /** - * {@inheritdoc} - */ - public function walkOrderByClause($orderByClause) - { - $orderByItems = array_map([$this, 'walkOrderByItem'], $orderByClause->orderByItems); - - if (($collectionOrderByItems = $this->_generateOrderedCollectionOrderByItems()) !== '') { - $orderByItems = array_merge($orderByItems, (array) $collectionOrderByItems); - } - - return ' ORDER BY ' . implode(', ', $orderByItems); - } - - /** - * {@inheritdoc} - */ - public function walkOrderByItem($orderByItem) - { - $type = strtoupper($orderByItem->type); - $expr = $orderByItem->expression; - $sql = ($expr instanceof AST\Node) - ? $expr->dispatch($this) - : $this->walkResultVariable($this->queryComponents[$expr]['token']['value']); - - $this->orderedColumnsMap[$sql] = $type; - - if ($expr instanceof AST\Subselect) { - return '(' . $sql . ') ' . $type; - } - - return $sql . ' ' . $type; - } - - /** - * {@inheritdoc} - */ - public function walkHavingClause($havingClause) - { - return ' HAVING ' . $this->walkConditionalExpression($havingClause->conditionalExpression); - } - - /** - * {@inheritdoc} - */ - public function walkJoin($join) - { - $joinType = $join->joinType; - $joinDeclaration = $join->joinAssociationDeclaration; - - $sql = ($joinType == AST\Join::JOIN_TYPE_LEFT || $joinType == AST\Join::JOIN_TYPE_LEFTOUTER) - ? ' LEFT JOIN ' - : ' INNER JOIN '; - - switch (true) { - case ($joinDeclaration instanceof AST\RangeVariableDeclaration): - $class = $this->em->getClassMetadata($joinDeclaration->abstractSchemaName); - $dqlAlias = $joinDeclaration->aliasIdentificationVariable; - $tableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias); - $conditions = []; - - if ($join->conditionalExpression) { - $conditions[] = '(' . $this->walkConditionalExpression($join->conditionalExpression) . ')'; - } - - $isUnconditionalJoin = empty($conditions); - $condExprConjunction = ($class->isInheritanceTypeJoined() && $joinType != AST\Join::JOIN_TYPE_LEFT && $joinType != AST\Join::JOIN_TYPE_LEFTOUTER && $isUnconditionalJoin) - ? ' AND ' - : ' ON '; - - $sql .= $this->generateRangeVariableDeclarationSQL($joinDeclaration, !$isUnconditionalJoin); - - // Apply remaining inheritance restrictions - $discrSql = $this->_generateDiscriminatorColumnConditionSQL([$dqlAlias]); - - if ($discrSql) { - $conditions[] = $discrSql; - } - - // Apply the filters - $filterExpr = $this->generateFilterConditionSQL($class, $tableAlias); - - if ($filterExpr) { - $conditions[] = $filterExpr; - } - - if ($conditions) { - $sql .= $condExprConjunction . implode(' AND ', $conditions); - } - - break; - - case ($joinDeclaration instanceof AST\JoinAssociationDeclaration): - $sql .= $this->walkJoinAssociationDeclaration($joinDeclaration, $joinType, $join->conditionalExpression); - break; - } - - return $sql; - } - - /** - * Walks down a CoalesceExpression AST node and generates the corresponding SQL. - * - * @param AST\CoalesceExpression $coalesceExpression - * - * @return string The SQL. - */ - public function walkCoalesceExpression($coalesceExpression) - { - $sql = 'COALESCE('; - - $scalarExpressions = []; - - foreach ($coalesceExpression->scalarExpressions as $scalarExpression) { - $scalarExpressions[] = $this->walkSimpleArithmeticExpression($scalarExpression); - } - - $sql .= implode(', ', $scalarExpressions) . ')'; - - return $sql; - } - - /** - * Walks down a NullIfExpression AST node and generates the corresponding SQL. - * - * @param AST\NullIfExpression $nullIfExpression - * - * @return string The SQL. - */ - public function walkNullIfExpression($nullIfExpression) - { - $firstExpression = is_string($nullIfExpression->firstExpression) - ? $this->conn->quote($nullIfExpression->firstExpression) - : $this->walkSimpleArithmeticExpression($nullIfExpression->firstExpression); - - $secondExpression = is_string($nullIfExpression->secondExpression) - ? $this->conn->quote($nullIfExpression->secondExpression) - : $this->walkSimpleArithmeticExpression($nullIfExpression->secondExpression); - - return 'NULLIF(' . $firstExpression . ', ' . $secondExpression . ')'; - } - - /** - * Walks down a GeneralCaseExpression AST node and generates the corresponding SQL. - * - * @param AST\GeneralCaseExpression $generalCaseExpression - * - * @return string The SQL. - */ - public function walkGeneralCaseExpression(AST\GeneralCaseExpression $generalCaseExpression) - { - $sql = 'CASE'; - - foreach ($generalCaseExpression->whenClauses as $whenClause) { - $sql .= ' WHEN ' . $this->walkConditionalExpression($whenClause->caseConditionExpression); - $sql .= ' THEN ' . $this->walkSimpleArithmeticExpression($whenClause->thenScalarExpression); - } - - $sql .= ' ELSE ' . $this->walkSimpleArithmeticExpression($generalCaseExpression->elseScalarExpression) . ' END'; - - return $sql; - } - - /** - * Walks down a SimpleCaseExpression AST node and generates the corresponding SQL. - * - * @param AST\SimpleCaseExpression $simpleCaseExpression - * - * @return string The SQL. - */ - public function walkSimpleCaseExpression($simpleCaseExpression) - { - $sql = 'CASE ' . $this->walkStateFieldPathExpression($simpleCaseExpression->caseOperand); - - foreach ($simpleCaseExpression->simpleWhenClauses as $simpleWhenClause) { - $sql .= ' WHEN ' . $this->walkSimpleArithmeticExpression($simpleWhenClause->caseScalarExpression); - $sql .= ' THEN ' . $this->walkSimpleArithmeticExpression($simpleWhenClause->thenScalarExpression); - } - - $sql .= ' ELSE ' . $this->walkSimpleArithmeticExpression($simpleCaseExpression->elseScalarExpression) . ' END'; - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkSelectExpression($selectExpression) - { - $sql = ''; - $expr = $selectExpression->expression; - $hidden = $selectExpression->hiddenAliasResultVariable; - - switch (true) { - case ($expr instanceof AST\PathExpression): - if ($expr->type !== AST\PathExpression::TYPE_STATE_FIELD) { - throw QueryException::invalidPathExpression($expr); - } - - $fieldName = $expr->field; - $dqlAlias = $expr->identificationVariable; - $qComp = $this->queryComponents[$dqlAlias]; - $class = $qComp['metadata']; - - $resultAlias = $selectExpression->fieldIdentificationVariable ?: $fieldName; - $tableName = ($class->isInheritanceTypeJoined()) - ? $this->em->getUnitOfWork()->getEntityPersister($class->name)->getOwningTable($fieldName) - : $class->getTableName(); - - $sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias); - $fieldMapping = $class->fieldMappings[$fieldName]; - $columnName = $this->quoteStrategy->getColumnName($fieldName, $class, $this->platform); - $columnAlias = $this->getSQLColumnAlias($fieldMapping['columnName']); - $col = $sqlTableAlias . '.' . $columnName; - - if (isset($fieldMapping['requireSQLConversion'])) { - $type = Type::getType($fieldMapping['type']); - $col = $type->convertToPHPValueSQL($col, $this->conn->getDatabasePlatform()); - } - - $sql .= $col . ' AS ' . $columnAlias; - - $this->scalarResultAliasMap[$resultAlias] = $columnAlias; - - if ( ! $hidden) { - $this->rsm->addScalarResult($columnAlias, $resultAlias, $fieldMapping['type']); - $this->scalarFields[$dqlAlias][$fieldName] = $columnAlias; - } - - break; - - case ($expr instanceof AST\AggregateExpression): - case ($expr instanceof AST\Functions\FunctionNode): - case ($expr instanceof AST\SimpleArithmeticExpression): - case ($expr instanceof AST\ArithmeticTerm): - case ($expr instanceof AST\ArithmeticFactor): - case ($expr instanceof AST\ParenthesisExpression): - case ($expr instanceof AST\Literal): - case ($expr instanceof AST\NullIfExpression): - case ($expr instanceof AST\CoalesceExpression): - case ($expr instanceof AST\GeneralCaseExpression): - case ($expr instanceof AST\SimpleCaseExpression): - $columnAlias = $this->getSQLColumnAlias('sclr'); - $resultAlias = $selectExpression->fieldIdentificationVariable ?: $this->scalarResultCounter++; - - $sql .= $expr->dispatch($this) . ' AS ' . $columnAlias; - - $this->scalarResultAliasMap[$resultAlias] = $columnAlias; - - if ( ! $hidden) { - // We cannot resolve field type here; assume 'string'. - $this->rsm->addScalarResult($columnAlias, $resultAlias, 'string'); - } - break; - - case ($expr instanceof AST\Subselect): - $columnAlias = $this->getSQLColumnAlias('sclr'); - $resultAlias = $selectExpression->fieldIdentificationVariable ?: $this->scalarResultCounter++; - - $sql .= '(' . $this->walkSubselect($expr) . ') AS ' . $columnAlias; - - $this->scalarResultAliasMap[$resultAlias] = $columnAlias; - - if ( ! $hidden) { - // We cannot resolve field type here; assume 'string'. - $this->rsm->addScalarResult($columnAlias, $resultAlias, 'string'); - } - break; - - case ($expr instanceof AST\NewObjectExpression): - $sql .= $this->walkNewObject($expr,$selectExpression->fieldIdentificationVariable); - break; - - default: - // IdentificationVariable or PartialObjectExpression - if ($expr instanceof AST\PartialObjectExpression) { - $dqlAlias = $expr->identificationVariable; - $partialFieldSet = $expr->partialFieldSet; - } else { - $dqlAlias = $expr; - $partialFieldSet = []; - } - - $queryComp = $this->queryComponents[$dqlAlias]; - $class = $queryComp['metadata']; - $resultAlias = $selectExpression->fieldIdentificationVariable ?: null; - - if ( ! isset($this->selectedClasses[$dqlAlias])) { - $this->selectedClasses[$dqlAlias] = [ - 'class' => $class, - 'dqlAlias' => $dqlAlias, - 'resultAlias' => $resultAlias - ]; - } - - $sqlParts = []; - - // Select all fields from the queried class - foreach ($class->fieldMappings as $fieldName => $mapping) { - if ($partialFieldSet && ! in_array($fieldName, $partialFieldSet)) { - continue; - } - - $tableName = (isset($mapping['inherited'])) - ? $this->em->getClassMetadata($mapping['inherited'])->getTableName() - : $class->getTableName(); - - $sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias); - $columnAlias = $this->getSQLColumnAlias($mapping['columnName']); - $quotedColumnName = $this->quoteStrategy->getColumnName($fieldName, $class, $this->platform); - - $col = $sqlTableAlias . '.' . $quotedColumnName; - - if (isset($mapping['requireSQLConversion'])) { - $type = Type::getType($mapping['type']); - $col = $type->convertToPHPValueSQL($col, $this->platform); - } - - $sqlParts[] = $col . ' AS '. $columnAlias; - - $this->scalarResultAliasMap[$resultAlias][] = $columnAlias; - - $this->rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name); - } - - // Add any additional fields of subclasses (excluding inherited fields) - // 1) on Single Table Inheritance: always, since its marginal overhead - // 2) on Class Table Inheritance only if partial objects are disallowed, - // since it requires outer joining subtables. - if ($class->isInheritanceTypeSingleTable() || ! $this->query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) { - foreach ($class->subClasses as $subClassName) { - $subClass = $this->em->getClassMetadata($subClassName); - $sqlTableAlias = $this->getSQLTableAlias($subClass->getTableName(), $dqlAlias); - - foreach ($subClass->fieldMappings as $fieldName => $mapping) { - if (isset($mapping['inherited']) || ($partialFieldSet && !in_array($fieldName, $partialFieldSet))) { - continue; - } - - $columnAlias = $this->getSQLColumnAlias($mapping['columnName']); - $quotedColumnName = $this->quoteStrategy->getColumnName($fieldName, $subClass, $this->platform); - - $col = $sqlTableAlias . '.' . $quotedColumnName; - - if (isset($mapping['requireSQLConversion'])) { - $type = Type::getType($mapping['type']); - $col = $type->convertToPHPValueSQL($col, $this->platform); - } - - $sqlParts[] = $col . ' AS ' . $columnAlias; - - $this->scalarResultAliasMap[$resultAlias][] = $columnAlias; - - $this->rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName); - } - } - } - - $sql .= implode(', ', $sqlParts); - } - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkQuantifiedExpression($qExpr) - { - return ' ' . strtoupper($qExpr->type) . '(' . $this->walkSubselect($qExpr->subselect) . ')'; - } - - /** - * {@inheritdoc} - */ - public function walkSubselect($subselect) - { - $useAliasesBefore = $this->useSqlTableAliases; - $rootAliasesBefore = $this->rootAliases; - - $this->rootAliases = []; // reset the rootAliases for the subselect - $this->useSqlTableAliases = true; - - $sql = $this->walkSimpleSelectClause($subselect->simpleSelectClause); - $sql .= $this->walkSubselectFromClause($subselect->subselectFromClause); - $sql .= $this->walkWhereClause($subselect->whereClause); - - $sql .= $subselect->groupByClause ? $this->walkGroupByClause($subselect->groupByClause) : ''; - $sql .= $subselect->havingClause ? $this->walkHavingClause($subselect->havingClause) : ''; - $sql .= $subselect->orderByClause ? $this->walkOrderByClause($subselect->orderByClause) : ''; - - $this->rootAliases = $rootAliasesBefore; // put the main aliases back - $this->useSqlTableAliases = $useAliasesBefore; - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkSubselectFromClause($subselectFromClause) - { - $identificationVarDecls = $subselectFromClause->identificationVariableDeclarations; - $sqlParts = []; - - foreach ($identificationVarDecls as $subselectIdVarDecl) { - $sqlParts[] = $this->walkIdentificationVariableDeclaration($subselectIdVarDecl); - } - - return ' FROM ' . implode(', ', $sqlParts); - } - - /** - * {@inheritdoc} - */ - public function walkSimpleSelectClause($simpleSelectClause) - { - return 'SELECT' . ($simpleSelectClause->isDistinct ? ' DISTINCT' : '') - . $this->walkSimpleSelectExpression($simpleSelectClause->simpleSelectExpression); - } - - /** - * @param \Doctrine\ORM\Query\AST\ParenthesisExpression $parenthesisExpression - * - * @return string. - */ - public function walkParenthesisExpression(AST\ParenthesisExpression $parenthesisExpression) - { - return sprintf('(%s)', $parenthesisExpression->expression->dispatch($this)); - } - - /** - * @param AST\NewObjectExpression $newObjectExpression - * @param null|string $newObjectResultAlias - * @return string The SQL. - */ - public function walkNewObject($newObjectExpression, $newObjectResultAlias=null) - { - $sqlSelectExpressions = []; - $objIndex = $newObjectResultAlias?:$this->newObjectCounter++; - - foreach ($newObjectExpression->args as $argIndex => $e) { - $resultAlias = $this->scalarResultCounter++; - $columnAlias = $this->getSQLColumnAlias('sclr'); - $fieldType = 'string'; - - switch (true) { - case ($e instanceof AST\NewObjectExpression): - $sqlSelectExpressions[] = $e->dispatch($this); - break; - - case ($e instanceof AST\Subselect): - $sqlSelectExpressions[] = '(' . $e->dispatch($this) . ') AS ' . $columnAlias; - break; - - case ($e instanceof AST\PathExpression): - $dqlAlias = $e->identificationVariable; - $qComp = $this->queryComponents[$dqlAlias]; - $class = $qComp['metadata']; - $fieldType = $class->fieldMappings[$e->field]['type']; - - $sqlSelectExpressions[] = trim($e->dispatch($this)) . ' AS ' . $columnAlias; - break; - - case ($e instanceof AST\Literal): - switch ($e->type) { - case AST\Literal::BOOLEAN: - $fieldType = 'boolean'; - break; - - case AST\Literal::NUMERIC: - $fieldType = is_float($e->value) ? 'float' : 'integer'; - break; - } - - $sqlSelectExpressions[] = trim($e->dispatch($this)) . ' AS ' . $columnAlias; - break; - - default: - $sqlSelectExpressions[] = trim($e->dispatch($this)) . ' AS ' . $columnAlias; - break; - } - - $this->scalarResultAliasMap[$resultAlias] = $columnAlias; - $this->rsm->addScalarResult($columnAlias, $resultAlias, $fieldType); - - $this->rsm->newObjectMappings[$columnAlias] = [ - 'className' => $newObjectExpression->className, - 'objIndex' => $objIndex, - 'argIndex' => $argIndex - ]; - } - - return implode(', ', $sqlSelectExpressions); - } - - /** - * {@inheritdoc} - */ - public function walkSimpleSelectExpression($simpleSelectExpression) - { - $expr = $simpleSelectExpression->expression; - $sql = ' '; - - switch (true) { - case ($expr instanceof AST\PathExpression): - $sql .= $this->walkPathExpression($expr); - break; - - case ($expr instanceof AST\Subselect): - $alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->scalarResultCounter++; - - $columnAlias = 'sclr' . $this->aliasCounter++; - $this->scalarResultAliasMap[$alias] = $columnAlias; - - $sql .= '(' . $this->walkSubselect($expr) . ') AS ' . $columnAlias; - break; - - case ($expr instanceof AST\Functions\FunctionNode): - case ($expr instanceof AST\SimpleArithmeticExpression): - case ($expr instanceof AST\ArithmeticTerm): - case ($expr instanceof AST\ArithmeticFactor): - case ($expr instanceof AST\Literal): - case ($expr instanceof AST\NullIfExpression): - case ($expr instanceof AST\CoalesceExpression): - case ($expr instanceof AST\GeneralCaseExpression): - case ($expr instanceof AST\SimpleCaseExpression): - $alias = $simpleSelectExpression->fieldIdentificationVariable ?: $this->scalarResultCounter++; - - $columnAlias = $this->getSQLColumnAlias('sclr'); - $this->scalarResultAliasMap[$alias] = $columnAlias; - - $sql .= $expr->dispatch($this) . ' AS ' . $columnAlias; - break; - - case ($expr instanceof AST\ParenthesisExpression): - $sql .= $this->walkParenthesisExpression($expr); - break; - - default: // IdentificationVariable - $sql .= $this->walkEntityIdentificationVariable($expr); - break; - } - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkAggregateExpression($aggExpression) - { - return $aggExpression->functionName . '(' . ($aggExpression->isDistinct ? 'DISTINCT ' : '') - . $this->walkSimpleArithmeticExpression($aggExpression->pathExpression) . ')'; - } - - /** - * {@inheritdoc} - */ - public function walkGroupByClause($groupByClause) - { - $sqlParts = []; - - foreach ($groupByClause->groupByItems as $groupByItem) { - $sqlParts[] = $this->walkGroupByItem($groupByItem); - } - - return ' GROUP BY ' . implode(', ', $sqlParts); - } - - /** - * {@inheritdoc} - */ - public function walkGroupByItem($groupByItem) - { - // StateFieldPathExpression - if ( ! is_string($groupByItem)) { - return $this->walkPathExpression($groupByItem); - } - - // ResultVariable - if (isset($this->queryComponents[$groupByItem]['resultVariable'])) { - $resultVariable = $this->queryComponents[$groupByItem]['resultVariable']; - - if ($resultVariable instanceof AST\PathExpression) { - return $this->walkPathExpression($resultVariable); - } - - if (isset($resultVariable->pathExpression)) { - return $this->walkPathExpression($resultVariable->pathExpression); - } - - return $this->walkResultVariable($groupByItem); - } - - // IdentificationVariable - $sqlParts = []; - - foreach ($this->queryComponents[$groupByItem]['metadata']->fieldNames as $field) { - $item = new AST\PathExpression(AST\PathExpression::TYPE_STATE_FIELD, $groupByItem, $field); - $item->type = AST\PathExpression::TYPE_STATE_FIELD; - - $sqlParts[] = $this->walkPathExpression($item); - } - - foreach ($this->queryComponents[$groupByItem]['metadata']->associationMappings as $mapping) { - if ($mapping['isOwningSide'] && $mapping['type'] & ClassMetadataInfo::TO_ONE) { - $item = new AST\PathExpression(AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $groupByItem, $mapping['fieldName']); - $item->type = AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION; - - $sqlParts[] = $this->walkPathExpression($item); - } - } - - return implode(', ', $sqlParts); - } - - /** - * {@inheritdoc} - */ - public function walkDeleteClause(AST\DeleteClause $deleteClause) - { - $class = $this->em->getClassMetadata($deleteClause->abstractSchemaName); - $tableName = $class->getTableName(); - $sql = 'DELETE FROM ' . $this->quoteStrategy->getTableName($class, $this->platform); - - $this->setSQLTableAlias($tableName, $tableName, $deleteClause->aliasIdentificationVariable); - $this->rootAliases[] = $deleteClause->aliasIdentificationVariable; - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkUpdateClause($updateClause) - { - $class = $this->em->getClassMetadata($updateClause->abstractSchemaName); - $tableName = $class->getTableName(); - $sql = 'UPDATE ' . $this->quoteStrategy->getTableName($class, $this->platform); - - $this->setSQLTableAlias($tableName, $tableName, $updateClause->aliasIdentificationVariable); - $this->rootAliases[] = $updateClause->aliasIdentificationVariable; - - $sql .= ' SET ' . implode(', ', array_map([$this, 'walkUpdateItem'], $updateClause->updateItems)); - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkUpdateItem($updateItem) - { - $useTableAliasesBefore = $this->useSqlTableAliases; - $this->useSqlTableAliases = false; - - $sql = $this->walkPathExpression($updateItem->pathExpression) . ' = '; - $newValue = $updateItem->newValue; - - switch (true) { - case ($newValue instanceof AST\Node): - $sql .= $newValue->dispatch($this); - break; - - case ($newValue === null): - $sql .= 'NULL'; - break; - - default: - $sql .= $this->conn->quote($newValue); - break; - } - - $this->useSqlTableAliases = $useTableAliasesBefore; - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkWhereClause($whereClause) - { - $condSql = null !== $whereClause ? $this->walkConditionalExpression($whereClause->conditionalExpression) : ''; - $discrSql = $this->_generateDiscriminatorColumnConditionSQL($this->rootAliases); - - if ($this->em->hasFilters()) { - $filterClauses = []; - foreach ($this->rootAliases as $dqlAlias) { - $class = $this->queryComponents[$dqlAlias]['metadata']; - $tableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias); - - if ($filterExpr = $this->generateFilterConditionSQL($class, $tableAlias)) { - $filterClauses[] = $filterExpr; - } - } - - if (count($filterClauses)) { - if ($condSql) { - $condSql = '(' . $condSql . ') AND '; - } - - $condSql .= implode(' AND ', $filterClauses); - } - } - - if ($condSql) { - return ' WHERE ' . (( ! $discrSql) ? $condSql : '(' . $condSql . ') AND ' . $discrSql); - } - - if ($discrSql) { - return ' WHERE ' . $discrSql; - } - - return ''; - } - - /** - * {@inheritdoc} - */ - public function walkConditionalExpression($condExpr) - { - // Phase 2 AST optimization: Skip processing of ConditionalExpression - // if only one ConditionalTerm is defined - if ( ! ($condExpr instanceof AST\ConditionalExpression)) { - return $this->walkConditionalTerm($condExpr); - } - - return implode(' OR ', array_map([$this, 'walkConditionalTerm'], $condExpr->conditionalTerms)); - } - - /** - * {@inheritdoc} - */ - public function walkConditionalTerm($condTerm) - { - // Phase 2 AST optimization: Skip processing of ConditionalTerm - // if only one ConditionalFactor is defined - if ( ! ($condTerm instanceof AST\ConditionalTerm)) { - return $this->walkConditionalFactor($condTerm); - } - - return implode(' AND ', array_map([$this, 'walkConditionalFactor'], $condTerm->conditionalFactors)); - } - - /** - * {@inheritdoc} - */ - public function walkConditionalFactor($factor) - { - // Phase 2 AST optimization: Skip processing of ConditionalFactor - // if only one ConditionalPrimary is defined - return ( ! ($factor instanceof AST\ConditionalFactor)) - ? $this->walkConditionalPrimary($factor) - : ($factor->not ? 'NOT ' : '') . $this->walkConditionalPrimary($factor->conditionalPrimary); - } - - /** - * {@inheritdoc} - */ - public function walkConditionalPrimary($primary) - { - if ($primary->isSimpleConditionalExpression()) { - return $primary->simpleConditionalExpression->dispatch($this); - } - - if ($primary->isConditionalExpression()) { - $condExpr = $primary->conditionalExpression; - - return '(' . $this->walkConditionalExpression($condExpr) . ')'; - } - } - - /** - * {@inheritdoc} - */ - public function walkExistsExpression($existsExpr) - { - $sql = ($existsExpr->not) ? 'NOT ' : ''; - - $sql .= 'EXISTS (' . $this->walkSubselect($existsExpr->subselect) . ')'; - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkCollectionMemberExpression($collMemberExpr) - { - $sql = $collMemberExpr->not ? 'NOT ' : ''; - $sql .= 'EXISTS (SELECT 1 FROM '; - - $entityExpr = $collMemberExpr->entityExpression; - $collPathExpr = $collMemberExpr->collectionValuedPathExpression; - - $fieldName = $collPathExpr->field; - $dqlAlias = $collPathExpr->identificationVariable; - - $class = $this->queryComponents[$dqlAlias]['metadata']; - - switch (true) { - // InputParameter - case ($entityExpr instanceof AST\InputParameter): - $dqlParamKey = $entityExpr->name; - $entitySql = '?'; - break; - - // SingleValuedAssociationPathExpression | IdentificationVariable - case ($entityExpr instanceof AST\PathExpression): - $entitySql = $this->walkPathExpression($entityExpr); - break; - - default: - throw new \BadMethodCallException("Not implemented"); - } - - $assoc = $class->associationMappings[$fieldName]; - - if ($assoc['type'] == ClassMetadata::ONE_TO_MANY) { - $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); - $targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName()); - $sourceTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias); - - $sql .= $this->quoteStrategy->getTableName($targetClass, $this->platform) . ' ' . $targetTableAlias . ' WHERE '; - - $owningAssoc = $targetClass->associationMappings[$assoc['mappedBy']]; - $sqlParts = []; - - foreach ($owningAssoc['targetToSourceKeyColumns'] as $targetColumn => $sourceColumn) { - $targetColumn = $this->quoteStrategy->getColumnName($class->fieldNames[$targetColumn], $class, $this->platform); - - $sqlParts[] = $sourceTableAlias . '.' . $targetColumn . ' = ' . $targetTableAlias . '.' . $sourceColumn; - } - - foreach ($this->quoteStrategy->getIdentifierColumnNames($targetClass, $this->platform) as $targetColumnName) { - if (isset($dqlParamKey)) { - $this->parserResult->addParameterMapping($dqlParamKey, $this->sqlParamIndex++); - } - - $sqlParts[] = $targetTableAlias . '.' . $targetColumnName . ' = ' . $entitySql; - } - - $sql .= implode(' AND ', $sqlParts); - } else { // many-to-many - $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); - - $owningAssoc = $assoc['isOwningSide'] ? $assoc : $targetClass->associationMappings[$assoc['mappedBy']]; - $joinTable = $owningAssoc['joinTable']; - - // SQL table aliases - $joinTableAlias = $this->getSQLTableAlias($joinTable['name']); - $targetTableAlias = $this->getSQLTableAlias($targetClass->getTableName()); - $sourceTableAlias = $this->getSQLTableAlias($class->getTableName(), $dqlAlias); - - // join to target table - $sql .= $this->quoteStrategy->getJoinTableName($owningAssoc, $targetClass, $this->platform) . ' ' . $joinTableAlias - . ' INNER JOIN ' . $this->quoteStrategy->getTableName($targetClass, $this->platform) . ' ' . $targetTableAlias . ' ON '; - - // join conditions - $joinColumns = $assoc['isOwningSide'] ? $joinTable['inverseJoinColumns'] : $joinTable['joinColumns']; - $joinSqlParts = []; - - foreach ($joinColumns as $joinColumn) { - $targetColumn = $this->quoteStrategy->getColumnName($targetClass->fieldNames[$joinColumn['referencedColumnName']], $targetClass, $this->platform); - - $joinSqlParts[] = $joinTableAlias . '.' . $joinColumn['name'] . ' = ' . $targetTableAlias . '.' . $targetColumn; - } - - $sql .= implode(' AND ', $joinSqlParts); - $sql .= ' WHERE '; - - $joinColumns = $assoc['isOwningSide'] ? $joinTable['joinColumns'] : $joinTable['inverseJoinColumns']; - $sqlParts = []; - - foreach ($joinColumns as $joinColumn) { - $targetColumn = $this->quoteStrategy->getColumnName($class->fieldNames[$joinColumn['referencedColumnName']], $class, $this->platform); - - $sqlParts[] = $joinTableAlias . '.' . $joinColumn['name'] . ' = ' . $sourceTableAlias . '.' . $targetColumn; - } - - foreach ($this->quoteStrategy->getIdentifierColumnNames($targetClass, $this->platform) as $targetColumnName) { - if (isset($dqlParamKey)) { - $this->parserResult->addParameterMapping($dqlParamKey, $this->sqlParamIndex++); - } - - $sqlParts[] = $targetTableAlias . '.' . $targetColumnName . ' IN (' . $entitySql . ')'; - } - - $sql .= implode(' AND ', $sqlParts); - } - - return $sql . ')'; - } - - /** - * {@inheritdoc} - */ - public function walkEmptyCollectionComparisonExpression($emptyCollCompExpr) - { - $sizeFunc = new AST\Functions\SizeFunction('size'); - $sizeFunc->collectionPathExpression = $emptyCollCompExpr->expression; - - return $sizeFunc->getSql($this) . ($emptyCollCompExpr->not ? ' > 0' : ' = 0'); - } - - /** - * {@inheritdoc} - */ - public function walkNullComparisonExpression($nullCompExpr) - { - $expression = $nullCompExpr->expression; - $comparison = ' IS' . ($nullCompExpr->not ? ' NOT' : '') . ' NULL'; - - // Handle ResultVariable - if (is_string($expression) && isset($this->queryComponents[$expression]['resultVariable'])) { - return $this->walkResultVariable($expression) . $comparison; - } - - // Handle InputParameter mapping inclusion to ParserResult - if ($expression instanceof AST\InputParameter) { - return $this->walkInputParameter($expression) . $comparison; - } - - return $expression->dispatch($this) . $comparison; - } - - /** - * {@inheritdoc} - */ - public function walkInExpression($inExpr) - { - $sql = $this->walkArithmeticExpression($inExpr->expression) . ($inExpr->not ? ' NOT' : '') . ' IN ('; - - $sql .= ($inExpr->subselect) - ? $this->walkSubselect($inExpr->subselect) - : implode(', ', array_map([$this, 'walkInParameter'], $inExpr->literals)); - - $sql .= ')'; - - return $sql; - } - - /** - * {@inheritdoc} - * @throws \Doctrine\ORM\Query\QueryException - */ - public function walkInstanceOfExpression($instanceOfExpr) - { - $sql = ''; - - $dqlAlias = $instanceOfExpr->identificationVariable; - $discrClass = $class = $this->queryComponents[$dqlAlias]['metadata']; - - if ($class->discriminatorColumn) { - $discrClass = $this->em->getClassMetadata($class->rootEntityName); - } - - if ($this->useSqlTableAliases) { - $sql .= $this->getSQLTableAlias($discrClass->getTableName(), $dqlAlias) . '.'; - } - - $sql .= $class->discriminatorColumn['name'] . ($instanceOfExpr->not ? ' NOT IN ' : ' IN '); - $sql .= $this->getChildDiscriminatorsFromClassMetadata($discrClass, $instanceOfExpr); - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkInParameter($inParam) - { - return $inParam instanceof AST\InputParameter - ? $this->walkInputParameter($inParam) - : $this->walkLiteral($inParam); - } - - /** - * {@inheritdoc} - */ - public function walkLiteral($literal) - { - switch ($literal->type) { - case AST\Literal::STRING: - return $this->conn->quote($literal->value); - - case AST\Literal::BOOLEAN: - return $this->conn->getDatabasePlatform()->convertBooleans('true' === strtolower($literal->value)); - - case AST\Literal::NUMERIC: - return $literal->value; - - default: - throw QueryException::invalidLiteral($literal); - } - } - - /** - * {@inheritdoc} - */ - public function walkBetweenExpression($betweenExpr) - { - $sql = $this->walkArithmeticExpression($betweenExpr->expression); - - if ($betweenExpr->not) { - $sql .= ' NOT'; - } - - $sql .= ' BETWEEN ' . $this->walkArithmeticExpression($betweenExpr->leftBetweenExpression) - . ' AND ' . $this->walkArithmeticExpression($betweenExpr->rightBetweenExpression); - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkLikeExpression($likeExpr) - { - $stringExpr = $likeExpr->stringExpression; - $leftExpr = (is_string($stringExpr) && isset($this->queryComponents[$stringExpr]['resultVariable'])) - ? $this->walkResultVariable($stringExpr) - : $stringExpr->dispatch($this); - - $sql = $leftExpr . ($likeExpr->not ? ' NOT' : '') . ' LIKE '; - - if ($likeExpr->stringPattern instanceof AST\InputParameter) { - $sql .= $this->walkInputParameter($likeExpr->stringPattern); - } elseif ($likeExpr->stringPattern instanceof AST\Functions\FunctionNode) { - $sql .= $this->walkFunction($likeExpr->stringPattern); - } elseif ($likeExpr->stringPattern instanceof AST\PathExpression) { - $sql .= $this->walkPathExpression($likeExpr->stringPattern); - } else { - $sql .= $this->walkLiteral($likeExpr->stringPattern); - } - - if ($likeExpr->escapeChar) { - $sql .= ' ESCAPE ' . $this->walkLiteral($likeExpr->escapeChar); - } - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkStateFieldPathExpression($stateFieldPathExpression) - { - return $this->walkPathExpression($stateFieldPathExpression); - } - - /** - * {@inheritdoc} - */ - public function walkComparisonExpression($compExpr) - { - $leftExpr = $compExpr->leftExpression; - $rightExpr = $compExpr->rightExpression; - $sql = ''; - - $sql .= ($leftExpr instanceof AST\Node) - ? $leftExpr->dispatch($this) - : (is_numeric($leftExpr) ? $leftExpr : $this->conn->quote($leftExpr)); - - $sql .= ' ' . $compExpr->operator . ' '; - - $sql .= ($rightExpr instanceof AST\Node) - ? $rightExpr->dispatch($this) - : (is_numeric($rightExpr) ? $rightExpr : $this->conn->quote($rightExpr)); - - return $sql; - } - - /** - * {@inheritdoc} - */ - public function walkInputParameter($inputParam) - { - $this->parserResult->addParameterMapping($inputParam->name, $this->sqlParamIndex++); - - $parameter = $this->query->getParameter($inputParam->name); - - if ($parameter && Type::hasType($type = $parameter->getType())) { - return Type::getType($type)->convertToDatabaseValueSQL('?', $this->platform); - } - - return '?'; - } - - /** - * {@inheritdoc} - */ - public function walkArithmeticExpression($arithmeticExpr) - { - return ($arithmeticExpr->isSimpleArithmeticExpression()) - ? $this->walkSimpleArithmeticExpression($arithmeticExpr->simpleArithmeticExpression) - : '(' . $this->walkSubselect($arithmeticExpr->subselect) . ')'; - } - - /** - * {@inheritdoc} - */ - public function walkSimpleArithmeticExpression($simpleArithmeticExpr) - { - if ( ! ($simpleArithmeticExpr instanceof AST\SimpleArithmeticExpression)) { - return $this->walkArithmeticTerm($simpleArithmeticExpr); - } - - return implode(' ', array_map([$this, 'walkArithmeticTerm'], $simpleArithmeticExpr->arithmeticTerms)); - } - - /** - * {@inheritdoc} - */ - public function walkArithmeticTerm($term) - { - if (is_string($term)) { - return (isset($this->queryComponents[$term])) - ? $this->walkResultVariable($this->queryComponents[$term]['token']['value']) - : $term; - } - - // Phase 2 AST optimization: Skip processing of ArithmeticTerm - // if only one ArithmeticFactor is defined - if ( ! ($term instanceof AST\ArithmeticTerm)) { - return $this->walkArithmeticFactor($term); - } - - return implode(' ', array_map([$this, 'walkArithmeticFactor'], $term->arithmeticFactors)); - } - - /** - * {@inheritdoc} - */ - public function walkArithmeticFactor($factor) - { - if (is_string($factor)) { - return (isset($this->queryComponents[$factor])) - ? $this->walkResultVariable($this->queryComponents[$factor]['token']['value']) - : $factor; - } - - // Phase 2 AST optimization: Skip processing of ArithmeticFactor - // if only one ArithmeticPrimary is defined - if ( ! ($factor instanceof AST\ArithmeticFactor)) { - return $this->walkArithmeticPrimary($factor); - } - - $sign = $factor->isNegativeSigned() ? '-' : ($factor->isPositiveSigned() ? '+' : ''); - - return $sign . $this->walkArithmeticPrimary($factor->arithmeticPrimary); - } - - /** - * Walks down an ArithmeticPrimary that represents an AST node, thereby generating the appropriate SQL. - * - * @param mixed $primary - * - * @return string The SQL. - */ - public function walkArithmeticPrimary($primary) - { - if ($primary instanceof AST\SimpleArithmeticExpression) { - return '(' . $this->walkSimpleArithmeticExpression($primary) . ')'; - } - - if ($primary instanceof AST\Node) { - return $primary->dispatch($this); - } - - return $this->walkEntityIdentificationVariable($primary); - } - - /** - * {@inheritdoc} - */ - public function walkStringPrimary($stringPrimary) - { - return (is_string($stringPrimary)) - ? $this->conn->quote($stringPrimary) - : $stringPrimary->dispatch($this); - } - - /** - * {@inheritdoc} - */ - public function walkResultVariable($resultVariable) - { - $resultAlias = $this->scalarResultAliasMap[$resultVariable]; - - if (is_array($resultAlias)) { - return implode(', ', $resultAlias); - } - - return $resultAlias; - } - - /** - * @param ClassMetadataInfo $rootClass - * @param AST\InstanceOfExpression $instanceOfExpr - * @return string The list in parentheses of valid child discriminators from the given class - * @throws QueryException - */ - private function getChildDiscriminatorsFromClassMetadata(ClassMetadataInfo $rootClass, AST\InstanceOfExpression $instanceOfExpr): string - { - $sqlParameterList = []; - $discriminators = []; - foreach ($instanceOfExpr->value as $parameter) { - if ($parameter instanceof AST\InputParameter) { - $this->rsm->discriminatorParameters[$parameter->name] = $parameter->name; - $sqlParameterList[] = $this->walkInParameter($parameter); - continue; - } - - $metadata = $this->em->getClassMetadata($parameter); - - if ($metadata->getName() !== $rootClass->name && ! $metadata->getReflectionClass()->isSubclassOf($rootClass->name)) { - throw QueryException::instanceOfUnrelatedClass($parameter, $rootClass->name); - } - - $discriminators += HierarchyDiscriminatorResolver::resolveDiscriminatorsForClass($metadata, $this->em); - } - - foreach (array_keys($discriminators) as $dis) { - $sqlParameterList[] = $this->conn->quote($dis); - } - - return '(' . implode(', ', $sqlParameterList) . ')'; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalker.php deleted file mode 100644 index 9ddd86b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalker.php +++ /dev/null @@ -1,479 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -/** - * Interface for walkers of DQL ASTs (abstract syntax trees). - * - * @author Roman Borschel - * @since 2.0 - */ -interface TreeWalker -{ - /** - * Initializes TreeWalker with important information about the ASTs to be walked. - * - * @param \Doctrine\ORM\AbstractQuery $query The parsed Query. - * @param \Doctrine\ORM\Query\ParserResult $parserResult The result of the parsing process. - * @param array $queryComponents The query components (symbol table). - */ - public function __construct($query, $parserResult, array $queryComponents); - - /** - * Returns internal queryComponents array. - * - * @return array - */ - public function getQueryComponents(); - - /** - * Sets or overrides a query component for a given dql alias. - * - * @param string $dqlAlias The DQL alias. - * @param array $queryComponent - * - * @return void - */ - public function setQueryComponent($dqlAlias, array $queryComponent); - - /** - * Walks down a SelectStatement AST node, thereby generating the appropriate SQL. - * - * @param AST\SelectStatement $AST - * - * @return string The SQL. - */ - function walkSelectStatement(AST\SelectStatement $AST); - - /** - * Walks down a SelectClause AST node, thereby generating the appropriate SQL. - * - * @param AST\SelectClause $selectClause - * - * @return string The SQL. - */ - function walkSelectClause($selectClause); - - /** - * Walks down a FromClause AST node, thereby generating the appropriate SQL. - * - * @param AST\FromClause $fromClause - * - * @return string The SQL. - */ - function walkFromClause($fromClause); - - /** - * Walks down a FunctionNode AST node, thereby generating the appropriate SQL. - * - * @param AST\Functions\FunctionNode $function - * - * @return string The SQL. - */ - function walkFunction($function); - - /** - * Walks down an OrderByClause AST node, thereby generating the appropriate SQL. - * - * @param AST\OrderByClause $orderByClause - * - * @return string The SQL. - */ - function walkOrderByClause($orderByClause); - - /** - * Walks down an OrderByItem AST node, thereby generating the appropriate SQL. - * - * @param AST\OrderByItem $orderByItem - * - * @return string The SQL. - */ - function walkOrderByItem($orderByItem); - - /** - * Walks down a HavingClause AST node, thereby generating the appropriate SQL. - * - * @param AST\HavingClause $havingClause - * - * @return string The SQL. - */ - function walkHavingClause($havingClause); - - /** - * Walks down a Join AST node and creates the corresponding SQL. - * - * @param AST\Join $join - * - * @return string The SQL. - */ - function walkJoin($join); - - /** - * Walks down a SelectExpression AST node and generates the corresponding SQL. - * - * @param AST\SelectExpression $selectExpression - * - * @return string The SQL. - */ - function walkSelectExpression($selectExpression); - - /** - * Walks down a QuantifiedExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\QuantifiedExpression $qExpr - * - * @return string The SQL. - */ - function walkQuantifiedExpression($qExpr); - - /** - * Walks down a Subselect AST node, thereby generating the appropriate SQL. - * - * @param AST\Subselect $subselect - * - * @return string The SQL. - */ - function walkSubselect($subselect); - - /** - * Walks down a SubselectFromClause AST node, thereby generating the appropriate SQL. - * - * @param AST\SubselectFromClause $subselectFromClause - * - * @return string The SQL. - */ - function walkSubselectFromClause($subselectFromClause); - - /** - * Walks down a SimpleSelectClause AST node, thereby generating the appropriate SQL. - * - * @param AST\SimpleSelectClause $simpleSelectClause - * - * @return string The SQL. - */ - function walkSimpleSelectClause($simpleSelectClause); - - /** - * Walks down a SimpleSelectExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\SimpleSelectExpression $simpleSelectExpression - * - * @return string The SQL. - */ - function walkSimpleSelectExpression($simpleSelectExpression); - - /** - * Walks down an AggregateExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\AggregateExpression $aggExpression - * - * @return string The SQL. - */ - function walkAggregateExpression($aggExpression); - - /** - * Walks down a GroupByClause AST node, thereby generating the appropriate SQL. - * - * @param AST\GroupByClause $groupByClause - * - * @return string The SQL. - */ - function walkGroupByClause($groupByClause); - - /** - * Walks down a GroupByItem AST node, thereby generating the appropriate SQL. - * - * @param AST\PathExpression|string $groupByItem - * - * @return string The SQL. - */ - function walkGroupByItem($groupByItem); - - /** - * Walks down an UpdateStatement AST node, thereby generating the appropriate SQL. - * - * @param AST\UpdateStatement $AST - * - * @return string The SQL. - */ - function walkUpdateStatement(AST\UpdateStatement $AST); - - /** - * Walks down a DeleteStatement AST node, thereby generating the appropriate SQL. - * - * @param AST\DeleteStatement $AST - * - * @return string The SQL. - */ - function walkDeleteStatement(AST\DeleteStatement $AST); - - /** - * Walks down a DeleteClause AST node, thereby generating the appropriate SQL. - * - * @param AST\DeleteClause $deleteClause - * - * @return string The SQL. - */ - function walkDeleteClause(AST\DeleteClause $deleteClause); - - /** - * Walks down an UpdateClause AST node, thereby generating the appropriate SQL. - * - * @param AST\UpdateClause $updateClause - * - * @return string The SQL. - */ - function walkUpdateClause($updateClause); - - /** - * Walks down an UpdateItem AST node, thereby generating the appropriate SQL. - * - * @param AST\UpdateItem $updateItem - * - * @return string The SQL. - */ - function walkUpdateItem($updateItem); - - /** - * Walks down a WhereClause AST node, thereby generating the appropriate SQL. - * WhereClause or not, the appropriate discriminator sql is added. - * - * @param AST\WhereClause $whereClause - * - * @return string The SQL. - */ - function walkWhereClause($whereClause); - - /** - * Walk down a ConditionalExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\ConditionalExpression $condExpr - * - * @return string The SQL. - */ - function walkConditionalExpression($condExpr); - - /** - * Walks down a ConditionalTerm AST node, thereby generating the appropriate SQL. - * - * @param AST\ConditionalTerm $condTerm - * - * @return string The SQL. - */ - function walkConditionalTerm($condTerm); - - /** - * Walks down a ConditionalFactor AST node, thereby generating the appropriate SQL. - * - * @param AST\ConditionalFactor $factor - * - * @return string The SQL. - */ - function walkConditionalFactor($factor); - - /** - * Walks down a ConditionalPrimary AST node, thereby generating the appropriate SQL. - * - * @param AST\ConditionalPrimary $primary - * - * @return string The SQL. - */ - function walkConditionalPrimary($primary); - - /** - * Walks down an ExistsExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\ExistsExpression $existsExpr - * - * @return string The SQL. - */ - function walkExistsExpression($existsExpr); - - /** - * Walks down a CollectionMemberExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\CollectionMemberExpression $collMemberExpr - * - * @return string The SQL. - */ - function walkCollectionMemberExpression($collMemberExpr); - - /** - * Walks down an EmptyCollectionComparisonExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\EmptyCollectionComparisonExpression $emptyCollCompExpr - * - * @return string The SQL. - */ - function walkEmptyCollectionComparisonExpression($emptyCollCompExpr); - - /** - * Walks down a NullComparisonExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\NullComparisonExpression $nullCompExpr - * - * @return string The SQL. - */ - function walkNullComparisonExpression($nullCompExpr); - - /** - * Walks down an InExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\InExpression $inExpr - * - * @return string The SQL. - */ - function walkInExpression($inExpr); - - /** - * Walks down an InstanceOfExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\InstanceOfExpression $instanceOfExpr - * - * @return string The SQL. - */ - function walkInstanceOfExpression($instanceOfExpr); - - /** - * Walks down a literal that represents an AST node, thereby generating the appropriate SQL. - * - * @param mixed $literal - * - * @return string The SQL. - */ - function walkLiteral($literal); - - /** - * Walks down a BetweenExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\BetweenExpression $betweenExpr - * - * @return string The SQL. - */ - function walkBetweenExpression($betweenExpr); - - /** - * Walks down a LikeExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\LikeExpression $likeExpr - * - * @return string The SQL. - */ - function walkLikeExpression($likeExpr); - - /** - * Walks down a StateFieldPathExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\PathExpression $stateFieldPathExpression - * - * @return string The SQL. - */ - function walkStateFieldPathExpression($stateFieldPathExpression); - - /** - * Walks down a ComparisonExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\ComparisonExpression $compExpr - * - * @return string The SQL. - */ - function walkComparisonExpression($compExpr); - - /** - * Walks down an InputParameter AST node, thereby generating the appropriate SQL. - * - * @param AST\InputParameter $inputParam - * - * @return string The SQL. - */ - function walkInputParameter($inputParam); - - /** - * Walks down an ArithmeticExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\ArithmeticExpression $arithmeticExpr - * - * @return string The SQL. - */ - function walkArithmeticExpression($arithmeticExpr); - - /** - * Walks down an ArithmeticTerm AST node, thereby generating the appropriate SQL. - * - * @param mixed $term - * - * @return string The SQL. - */ - function walkArithmeticTerm($term); - - /** - * Walks down a StringPrimary that represents an AST node, thereby generating the appropriate SQL. - * - * @param mixed $stringPrimary - * - * @return string The SQL. - */ - function walkStringPrimary($stringPrimary); - - /** - * Walks down an ArithmeticFactor that represents an AST node, thereby generating the appropriate SQL. - * - * @param mixed $factor - * - * @return string The SQL. - */ - function walkArithmeticFactor($factor); - - /** - * Walks down an SimpleArithmeticExpression AST node, thereby generating the appropriate SQL. - * - * @param AST\SimpleArithmeticExpression $simpleArithmeticExpr - * - * @return string The SQL. - */ - function walkSimpleArithmeticExpression($simpleArithmeticExpr); - - /** - * Walks down a PathExpression AST node, thereby generating the appropriate SQL. - * - * @param mixed $pathExpr - * - * @return string The SQL. - */ - function walkPathExpression($pathExpr); - - /** - * Walks down a ResultVariable that represents an AST node, thereby generating the appropriate SQL. - * - * @param string $resultVariable - * - * @return string The SQL. - */ - function walkResultVariable($resultVariable); - - /** - * Gets an executor that can be used to execute the result of this walker. - * - * @param AST\DeleteStatement|AST\UpdateStatement|AST\SelectStatement $AST - * - * @return Exec\AbstractSqlExecutor - */ - function getExecutor($AST); -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerAdapter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerAdapter.php deleted file mode 100644 index deee03a..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerAdapter.php +++ /dev/null @@ -1,440 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -/** - * An adapter implementation of the TreeWalker interface. The methods in this class - * are empty. This class exists as convenience for creating tree walkers. - * - * @author Roman Borschel - * @since 2.0 - */ -abstract class TreeWalkerAdapter implements TreeWalker -{ - /** - * The original Query. - * - * @var \Doctrine\ORM\AbstractQuery - */ - private $_query; - - /** - * The ParserResult of the original query that was produced by the Parser. - * - * @var \Doctrine\ORM\Query\ParserResult - */ - private $_parserResult; - - /** - * The query components of the original query (the "symbol table") that was produced by the Parser. - * - * @var array - */ - private $_queryComponents; - - /** - * {@inheritdoc} - */ - public function __construct($query, $parserResult, array $queryComponents) - { - $this->_query = $query; - $this->_parserResult = $parserResult; - $this->_queryComponents = $queryComponents; - } - - /** - * {@inheritdoc} - */ - public function getQueryComponents() - { - return $this->_queryComponents; - } - - /** - * {@inheritdoc} - */ - public function setQueryComponent($dqlAlias, array $queryComponent) - { - $requiredKeys = ['metadata', 'parent', 'relation', 'map', 'nestingLevel', 'token']; - - if (array_diff($requiredKeys, array_keys($queryComponent))) { - throw QueryException::invalidQueryComponent($dqlAlias); - } - - $this->_queryComponents[$dqlAlias] = $queryComponent; - } - - /** - * @return array - */ - protected function _getQueryComponents() - { - return $this->_queryComponents; - } - - /** - * Retrieves the Query Instance responsible for the current walkers execution. - * - * @return \Doctrine\ORM\AbstractQuery - */ - protected function _getQuery() - { - return $this->_query; - } - - /** - * Retrieves the ParserResult. - * - * @return \Doctrine\ORM\Query\ParserResult - */ - protected function _getParserResult() - { - return $this->_parserResult; - } - - /** - * {@inheritdoc} - */ - public function walkSelectStatement(AST\SelectStatement $AST) - { - } - - /** - * {@inheritdoc} - */ - public function walkSelectClause($selectClause) - { - } - - /** - * {@inheritdoc} - */ - public function walkFromClause($fromClause) - { - } - - /** - * {@inheritdoc} - */ - public function walkFunction($function) - { - } - - /** - * {@inheritdoc} - */ - public function walkOrderByClause($orderByClause) - { - } - - /** - * {@inheritdoc} - */ - public function walkOrderByItem($orderByItem) - { - } - - /** - * {@inheritdoc} - */ - public function walkHavingClause($havingClause) - { - } - - /** - * {@inheritdoc} - */ - public function walkJoin($join) - { - } - - /** - * {@inheritdoc} - */ - public function walkSelectExpression($selectExpression) - { - } - - /** - * {@inheritdoc} - */ - public function walkQuantifiedExpression($qExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkSubselect($subselect) - { - } - - /** - * {@inheritdoc} - */ - public function walkSubselectFromClause($subselectFromClause) - { - } - - /** - * {@inheritdoc} - */ - public function walkSimpleSelectClause($simpleSelectClause) - { - } - - /** - * {@inheritdoc} - */ - public function walkSimpleSelectExpression($simpleSelectExpression) - { - } - - /** - * {@inheritdoc} - */ - public function walkAggregateExpression($aggExpression) - { - } - - /** - * {@inheritdoc} - */ - public function walkGroupByClause($groupByClause) - { - } - - /** - * {@inheritdoc} - */ - public function walkGroupByItem($groupByItem) - { - } - - /** - * {@inheritdoc} - */ - public function walkUpdateStatement(AST\UpdateStatement $AST) - { - } - - /** - * {@inheritdoc} - */ - public function walkDeleteStatement(AST\DeleteStatement $AST) - { - } - - /** - * {@inheritdoc} - */ - public function walkDeleteClause(AST\DeleteClause $deleteClause) - { - } - - /** - * {@inheritdoc} - */ - public function walkUpdateClause($updateClause) - { - } - - /** - * {@inheritdoc} - */ - public function walkUpdateItem($updateItem) - { - } - - /** - * {@inheritdoc} - */ - public function walkWhereClause($whereClause) - { - } - - /** - * {@inheritdoc} - */ - public function walkConditionalExpression($condExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkConditionalTerm($condTerm) - { - } - - /** - * {@inheritdoc} - */ - public function walkConditionalFactor($factor) - { - } - - /** - * {@inheritdoc} - */ - public function walkConditionalPrimary($primary) - { - } - - /** - * {@inheritdoc} - */ - public function walkExistsExpression($existsExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkCollectionMemberExpression($collMemberExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkEmptyCollectionComparisonExpression($emptyCollCompExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkNullComparisonExpression($nullCompExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkInExpression($inExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkInstanceOfExpression($instanceOfExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkLiteral($literal) - { - } - - /** - * {@inheritdoc} - */ - public function walkBetweenExpression($betweenExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkLikeExpression($likeExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkStateFieldPathExpression($stateFieldPathExpression) - { - } - - /** - * {@inheritdoc} - */ - public function walkComparisonExpression($compExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkInputParameter($inputParam) - { - } - - /** - * {@inheritdoc} - */ - public function walkArithmeticExpression($arithmeticExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkArithmeticTerm($term) - { - } - - /** - * {@inheritdoc} - */ - public function walkStringPrimary($stringPrimary) - { - } - - /** - * {@inheritdoc} - */ - public function walkArithmeticFactor($factor) - { - } - - /** - * {@inheritdoc} - */ - public function walkSimpleArithmeticExpression($simpleArithmeticExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkPathExpression($pathExpr) - { - } - - /** - * {@inheritdoc} - */ - public function walkResultVariable($resultVariable) - { - } - - /** - * {@inheritdoc} - */ - public function getExecutor($AST) - { - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChain.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChain.php deleted file mode 100644 index 074aa93..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChain.php +++ /dev/null @@ -1,575 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -/** - * Represents a chain of tree walkers that modify an AST and finally emit output. - * Only the last walker in the chain can emit output. Any previous walkers can modify - * the AST to influence the final output produced by the last walker. - * - * @author Roman Borschel - * @since 2.0 - */ -class TreeWalkerChain implements TreeWalker -{ - /** - * The tree walkers. - * - * @var TreeWalker[] - */ - private $_walkers; - - /** - * The original Query. - * - * @var \Doctrine\ORM\AbstractQuery - */ - private $_query; - - /** - * The ParserResult of the original query that was produced by the Parser. - * - * @var \Doctrine\ORM\Query\ParserResult - */ - private $_parserResult; - - /** - * The query components of the original query (the "symbol table") that was produced by the Parser. - * - * @var array - */ - private $_queryComponents; - - /** - * Returns the internal queryComponents array. - * - * @return array - */ - public function getQueryComponents() - { - return $this->_queryComponents; - } - - /** - * {@inheritdoc} - */ - public function setQueryComponent($dqlAlias, array $queryComponent) - { - $requiredKeys = ['metadata', 'parent', 'relation', 'map', 'nestingLevel', 'token']; - - if (array_diff($requiredKeys, array_keys($queryComponent))) { - throw QueryException::invalidQueryComponent($dqlAlias); - } - - $this->_queryComponents[$dqlAlias] = $queryComponent; - } - - /** - * {@inheritdoc} - */ - public function __construct($query, $parserResult, array $queryComponents) - { - $this->_query = $query; - $this->_parserResult = $parserResult; - $this->_queryComponents = $queryComponents; - $this->_walkers = new TreeWalkerChainIterator($this, $query, $parserResult); - } - - /** - * Adds a tree walker to the chain. - * - * @param string $walkerClass The class of the walker to instantiate. - * - * @return void - */ - public function addTreeWalker($walkerClass) - { - $this->_walkers[] = $walkerClass; - } - - /** - * {@inheritdoc} - */ - public function walkSelectStatement(AST\SelectStatement $AST) - { - foreach ($this->_walkers as $walker) { - $walker->walkSelectStatement($AST); - - $this->_queryComponents = $walker->getQueryComponents(); - } - } - - /** - * {@inheritdoc} - */ - public function walkSelectClause($selectClause) - { - foreach ($this->_walkers as $walker) { - $walker->walkSelectClause($selectClause); - } - } - - /** - * {@inheritdoc} - */ - public function walkFromClause($fromClause) - { - foreach ($this->_walkers as $walker) { - $walker->walkFromClause($fromClause); - } - } - - /** - * {@inheritdoc} - */ - public function walkFunction($function) - { - foreach ($this->_walkers as $walker) { - $walker->walkFunction($function); - } - } - - /** - * {@inheritdoc} - */ - public function walkOrderByClause($orderByClause) - { - foreach ($this->_walkers as $walker) { - $walker->walkOrderByClause($orderByClause); - } - } - - /** - * {@inheritdoc} - */ - public function walkOrderByItem($orderByItem) - { - foreach ($this->_walkers as $walker) { - $walker->walkOrderByItem($orderByItem); - } - } - - /** - * {@inheritdoc} - */ - public function walkHavingClause($havingClause) - { - foreach ($this->_walkers as $walker) { - $walker->walkHavingClause($havingClause); - } - } - - /** - * {@inheritdoc} - */ - public function walkJoin($join) - { - foreach ($this->_walkers as $walker) { - $walker->walkJoin($join); - } - } - - /** - * {@inheritdoc} - */ - public function walkSelectExpression($selectExpression) - { - foreach ($this->_walkers as $walker) { - $walker->walkSelectExpression($selectExpression); - } - } - - /** - * {@inheritdoc} - */ - public function walkQuantifiedExpression($qExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkQuantifiedExpression($qExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkSubselect($subselect) - { - foreach ($this->_walkers as $walker) { - $walker->walkSubselect($subselect); - } - } - - /** - * {@inheritdoc} - */ - public function walkSubselectFromClause($subselectFromClause) - { - foreach ($this->_walkers as $walker) { - $walker->walkSubselectFromClause($subselectFromClause); - } - } - - /** - * {@inheritdoc} - */ - public function walkSimpleSelectClause($simpleSelectClause) - { - foreach ($this->_walkers as $walker) { - $walker->walkSimpleSelectClause($simpleSelectClause); - } - } - - /** - * {@inheritdoc} - */ - public function walkSimpleSelectExpression($simpleSelectExpression) - { - foreach ($this->_walkers as $walker) { - $walker->walkSimpleSelectExpression($simpleSelectExpression); - } - } - - /** - * {@inheritdoc} - */ - public function walkAggregateExpression($aggExpression) - { - foreach ($this->_walkers as $walker) { - $walker->walkAggregateExpression($aggExpression); - } - } - - /** - * {@inheritdoc} - */ - public function walkGroupByClause($groupByClause) - { - foreach ($this->_walkers as $walker) { - $walker->walkGroupByClause($groupByClause); - } - } - - /** - * {@inheritdoc} - */ - public function walkGroupByItem($groupByItem) - { - foreach ($this->_walkers as $walker) { - $walker->walkGroupByItem($groupByItem); - } - } - - /** - * {@inheritdoc} - */ - public function walkUpdateStatement(AST\UpdateStatement $AST) - { - foreach ($this->_walkers as $walker) { - $walker->walkUpdateStatement($AST); - } - } - - /** - * {@inheritdoc} - */ - public function walkDeleteStatement(AST\DeleteStatement $AST) - { - foreach ($this->_walkers as $walker) { - $walker->walkDeleteStatement($AST); - } - } - - /** - * {@inheritdoc} - */ - public function walkDeleteClause(AST\DeleteClause $deleteClause) - { - foreach ($this->_walkers as $walker) { - $walker->walkDeleteClause($deleteClause); - } - } - - /** - * {@inheritdoc} - */ - public function walkUpdateClause($updateClause) - { - foreach ($this->_walkers as $walker) { - $walker->walkUpdateClause($updateClause); - } - } - - /** - * {@inheritdoc} - */ - public function walkUpdateItem($updateItem) - { - foreach ($this->_walkers as $walker) { - $walker->walkUpdateItem($updateItem); - } - } - - /** - * {@inheritdoc} - */ - public function walkWhereClause($whereClause) - { - foreach ($this->_walkers as $walker) { - $walker->walkWhereClause($whereClause); - } - } - - /** - * {@inheritdoc} - */ - public function walkConditionalExpression($condExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkConditionalExpression($condExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkConditionalTerm($condTerm) - { - foreach ($this->_walkers as $walker) { - $walker->walkConditionalTerm($condTerm); - } - } - - /** - * {@inheritdoc} - */ - public function walkConditionalFactor($factor) - { - foreach ($this->_walkers as $walker) { - $walker->walkConditionalFactor($factor); - } - } - - /** - * {@inheritdoc} - */ - public function walkConditionalPrimary($condPrimary) - { - foreach ($this->_walkers as $walker) { - $walker->walkConditionalPrimary($condPrimary); - } - } - - /** - * {@inheritdoc} - */ - public function walkExistsExpression($existsExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkExistsExpression($existsExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkCollectionMemberExpression($collMemberExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkCollectionMemberExpression($collMemberExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkEmptyCollectionComparisonExpression($emptyCollCompExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkEmptyCollectionComparisonExpression($emptyCollCompExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkNullComparisonExpression($nullCompExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkNullComparisonExpression($nullCompExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkInExpression($inExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkInExpression($inExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkInstanceOfExpression($instanceOfExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkInstanceOfExpression($instanceOfExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkLiteral($literal) - { - foreach ($this->_walkers as $walker) { - $walker->walkLiteral($literal); - } - } - - /** - * {@inheritdoc} - */ - public function walkBetweenExpression($betweenExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkBetweenExpression($betweenExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkLikeExpression($likeExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkLikeExpression($likeExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkStateFieldPathExpression($stateFieldPathExpression) - { - foreach ($this->_walkers as $walker) { - $walker->walkStateFieldPathExpression($stateFieldPathExpression); - } - } - - /** - * {@inheritdoc} - */ - public function walkComparisonExpression($compExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkComparisonExpression($compExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkInputParameter($inputParam) - { - foreach ($this->_walkers as $walker) { - $walker->walkInputParameter($inputParam); - } - } - - /** - * {@inheritdoc} - */ - public function walkArithmeticExpression($arithmeticExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkArithmeticExpression($arithmeticExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkArithmeticTerm($term) - { - foreach ($this->_walkers as $walker) { - $walker->walkArithmeticTerm($term); - } - } - - /** - * {@inheritdoc} - */ - public function walkStringPrimary($stringPrimary) - { - foreach ($this->_walkers as $walker) { - $walker->walkStringPrimary($stringPrimary); - } - } - - /** - * {@inheritdoc} - */ - public function walkArithmeticFactor($factor) - { - foreach ($this->_walkers as $walker) { - $walker->walkArithmeticFactor($factor); - } - } - - /** - * {@inheritdoc} - */ - public function walkSimpleArithmeticExpression($simpleArithmeticExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkSimpleArithmeticExpression($simpleArithmeticExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkPathExpression($pathExpr) - { - foreach ($this->_walkers as $walker) { - $walker->walkPathExpression($pathExpr); - } - } - - /** - * {@inheritdoc} - */ - public function walkResultVariable($resultVariable) - { - foreach ($this->_walkers as $walker) { - $walker->walkResultVariable($resultVariable); - } - } - - /** - * {@inheritdoc} - */ - public function getExecutor($AST) - { - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChainIterator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChainIterator.php deleted file mode 100644 index e72e1d4..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Query/TreeWalkerChainIterator.php +++ /dev/null @@ -1,138 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Query; - -/** - * - */ -class TreeWalkerChainIterator implements \Iterator, \ArrayAccess -{ - /** - * @var TreeWalker[] - */ - private $walkers = []; - /** - * @var TreeWalkerChain - */ - private $treeWalkerChain; - /** - * @var - */ - private $query; - /** - * @var - */ - private $parserResult; - - public function __construct(TreeWalkerChain $treeWalkerChain, $query, $parserResult) - { - $this->treeWalkerChain = $treeWalkerChain; - $this->query = $query; - $this->parserResult = $parserResult; - } - - /** - * {@inheritdoc} - */ - public function rewind() - { - return reset($this->walkers); - } - - /** - * {@inheritdoc} - */ - public function current() - { - return $this->offsetGet(key($this->walkers)); - } - - /** - * {@inheritdoc} - */ - public function key() - { - return key($this->walkers); - } - - /** - * {@inheritdoc} - */ - public function next() - { - next($this->walkers); - - return $this->offsetGet(key($this->walkers)); - } - - /** - * {@inheritdoc} - */ - public function valid() - { - return key($this->walkers) !== null; - } - - /** - * {@inheritdoc} - */ - public function offsetExists($offset) - { - return isset($this->walkers[$offset]); - } - - /** - * {@inheritdoc} - */ - public function offsetGet($offset) - { - if ($this->offsetExists($offset)) { - return new $this->walkers[$offset]( - $this->query, - $this->parserResult, - $this->treeWalkerChain->getQueryComponents() - ); - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function offsetSet($offset, $value) - { - if (null === $offset) { - $this->walkers[] = $value; - } else { - $this->walkers[$offset] = $value; - } - } - - /** - * {@inheritdoc} - */ - public function offsetUnset($offset) - { - if ($this->offsetExists($offset)) { - unset($this->walkers[$offset]); - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/QueryBuilder.php b/vendor/doctrine/orm/lib/Doctrine/ORM/QueryBuilder.php deleted file mode 100644 index af4d8cd..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/QueryBuilder.php +++ /dev/null @@ -1,1513 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Criteria; - -use Doctrine\ORM\Query\Expr; -use Doctrine\ORM\Query\QueryExpressionVisitor; - -/** - * This class is responsible for building DQL query strings via an object oriented - * PHP interface. - * - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class QueryBuilder -{ - /* The query types. */ - const SELECT = 0; - const DELETE = 1; - const UPDATE = 2; - - /* The builder states. */ - const STATE_DIRTY = 0; - const STATE_CLEAN = 1; - - /** - * The EntityManager used by this QueryBuilder. - * - * @var EntityManagerInterface - */ - private $_em; - - /** - * The array of DQL parts collected. - * - * @var array - */ - private $_dqlParts = [ - 'distinct' => false, - 'select' => [], - 'from' => [], - 'join' => [], - 'set' => [], - 'where' => null, - 'groupBy' => [], - 'having' => null, - 'orderBy' => [] - ]; - - /** - * The type of query this is. Can be select, update or delete. - * - * @var integer - */ - private $_type = self::SELECT; - - /** - * The state of the query object. Can be dirty or clean. - * - * @var integer - */ - private $_state = self::STATE_CLEAN; - - /** - * The complete DQL string for this query. - * - * @var string - */ - private $_dql; - - /** - * The query parameters. - * - * @var \Doctrine\Common\Collections\ArrayCollection - */ - private $parameters; - - /** - * The index of the first result to retrieve. - * - * @var integer - */ - private $_firstResult = null; - - /** - * The maximum number of results to retrieve. - * - * @var integer|null - */ - private $_maxResults = null; - - /** - * Keeps root entity alias names for join entities. - * - * @var array - */ - private $joinRootAliases = []; - - /** - * Whether to use second level cache, if available. - * - * @var boolean - */ - protected $cacheable = false; - - /** - * Second level cache region name. - * - * @var string|null - */ - protected $cacheRegion; - - /** - * Second level query cache mode. - * - * @var integer|null - */ - protected $cacheMode; - - /** - * @var integer - */ - protected $lifetime = 0; - - /** - * Initializes a new QueryBuilder that uses the given EntityManager. - * - * @param EntityManagerInterface $em The EntityManager to use. - */ - public function __construct(EntityManagerInterface $em) - { - $this->_em = $em; - $this->parameters = new ArrayCollection(); - } - - /** - * Gets an ExpressionBuilder used for object-oriented construction of query expressions. - * This producer method is intended for convenient inline usage. Example: - * - * - * $qb = $em->createQueryBuilder(); - * $qb - * ->select('u') - * ->from('User', 'u') - * ->where($qb->expr()->eq('u.id', 1)); - * - * - * For more complex expression construction, consider storing the expression - * builder object in a local variable. - * - * @return Query\Expr - */ - public function expr() - { - return $this->_em->getExpressionBuilder(); - } - - /** - * - * Enable/disable second level query (result) caching for this query. - * - * @param boolean $cacheable - * - * @return self - */ - public function setCacheable($cacheable) - { - $this->cacheable = (boolean) $cacheable; - - return $this; - } - - /** - * @return boolean TRUE if the query results are enable for second level cache, FALSE otherwise. - */ - public function isCacheable() - { - return $this->cacheable; - } - - /** - * @param string $cacheRegion - * - * @return self - */ - public function setCacheRegion($cacheRegion) - { - $this->cacheRegion = (string) $cacheRegion; - - return $this; - } - - /** - * Obtain the name of the second level query cache region in which query results will be stored - * - * @return string|null The cache region name; NULL indicates the default region. - */ - public function getCacheRegion() - { - return $this->cacheRegion; - } - - /** - * @return integer - */ - public function getLifetime() - { - return $this->lifetime; - } - - /** - * Sets the life-time for this query into second level cache. - * - * @param integer $lifetime - * - * @return self - */ - public function setLifetime($lifetime) - { - $this->lifetime = (integer) $lifetime; - - return $this; - } - - /** - * @return integer - */ - public function getCacheMode() - { - return $this->cacheMode; - } - - /** - * @param integer $cacheMode - * - * @return self - */ - public function setCacheMode($cacheMode) - { - $this->cacheMode = (integer) $cacheMode; - - return $this; - } - - /** - * Gets the type of the currently built query. - * - * @return integer - */ - public function getType() - { - return $this->_type; - } - - /** - * Gets the associated EntityManager for this query builder. - * - * @return EntityManager - */ - public function getEntityManager() - { - return $this->_em; - } - - /** - * Gets the state of this query builder instance. - * - * @return integer Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN. - */ - public function getState() - { - return $this->_state; - } - - /** - * Gets the complete DQL string formed by the current specifications of this QueryBuilder. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u'); - * echo $qb->getDql(); // SELECT u FROM User u - * - * - * @return string The DQL query string. - */ - public function getDQL() - { - if ($this->_dql !== null && $this->_state === self::STATE_CLEAN) { - return $this->_dql; - } - - switch ($this->_type) { - case self::DELETE: - $dql = $this->_getDQLForDelete(); - break; - - case self::UPDATE: - $dql = $this->_getDQLForUpdate(); - break; - - case self::SELECT: - default: - $dql = $this->_getDQLForSelect(); - break; - } - - $this->_state = self::STATE_CLEAN; - $this->_dql = $dql; - - return $dql; - } - - /** - * Constructs a Query instance from the current specifications of the builder. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u'); - * $q = $qb->getQuery(); - * $results = $q->execute(); - * - * - * @return Query - */ - public function getQuery() - { - $parameters = clone $this->parameters; - $query = $this->_em->createQuery($this->getDQL()) - ->setParameters($parameters) - ->setFirstResult($this->_firstResult) - ->setMaxResults($this->_maxResults); - - if ($this->lifetime) { - $query->setLifetime($this->lifetime); - } - - if ($this->cacheMode) { - $query->setCacheMode($this->cacheMode); - } - - if ($this->cacheable) { - $query->setCacheable($this->cacheable); - } - - if ($this->cacheRegion) { - $query->setCacheRegion($this->cacheRegion); - } - - return $query; - } - - /** - * Finds the root entity alias of the joined entity. - * - * @param string $alias The alias of the new join entity - * @param string $parentAlias The parent entity alias of the join relationship - * - * @return string - */ - private function findRootAlias($alias, $parentAlias) - { - $rootAlias = null; - - if (in_array($parentAlias, $this->getRootAliases())) { - $rootAlias = $parentAlias; - } elseif (isset($this->joinRootAliases[$parentAlias])) { - $rootAlias = $this->joinRootAliases[$parentAlias]; - } else { - // Should never happen with correct joining order. Might be - // thoughtful to throw exception instead. - $rootAlias = $this->getRootAlias(); - } - - $this->joinRootAliases[$alias] = $rootAlias; - - return $rootAlias; - } - - /** - * Gets the FIRST root alias of the query. This is the first entity alias involved - * in the construction of the query. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u'); - * - * echo $qb->getRootAlias(); // u - * - * - * @deprecated Please use $qb->getRootAliases() instead. - * @throws \RuntimeException - * - * @return string - */ - public function getRootAlias() - { - $aliases = $this->getRootAliases(); - - if ( ! isset($aliases[0])) { - throw new \RuntimeException('No alias was set before invoking getRootAlias().'); - } - - return $aliases[0]; - } - - /** - * Gets the root aliases of the query. This is the entity aliases involved - * in the construction of the query. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u'); - * - * $qb->getRootAliases(); // array('u') - * - * - * @return array - */ - public function getRootAliases() - { - $aliases = []; - - foreach ($this->_dqlParts['from'] as &$fromClause) { - if (is_string($fromClause)) { - $spacePos = strrpos($fromClause, ' '); - $from = substr($fromClause, 0, $spacePos); - $alias = substr($fromClause, $spacePos + 1); - - $fromClause = new Query\Expr\From($from, $alias); - } - - $aliases[] = $fromClause->getAlias(); - } - - return $aliases; - } - - /** - * Gets all the aliases that have been used in the query. - * Including all select root aliases and join aliases - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u') - * ->join('u.articles','a'); - * - * $qb->getAllAliases(); // array('u','a') - * - * @return array - */ - public function getAllAliases() - { - return array_merge($this->getRootAliases(), array_keys($this->joinRootAliases)); - } - - /** - * Gets the root entities of the query. This is the entity aliases involved - * in the construction of the query. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u'); - * - * $qb->getRootEntities(); // array('User') - * - * - * @return array - */ - public function getRootEntities() - { - $entities = []; - - foreach ($this->_dqlParts['from'] as &$fromClause) { - if (is_string($fromClause)) { - $spacePos = strrpos($fromClause, ' '); - $from = substr($fromClause, 0, $spacePos); - $alias = substr($fromClause, $spacePos + 1); - - $fromClause = new Query\Expr\From($from, $alias); - } - - $entities[] = $fromClause->getFrom(); - } - - return $entities; - } - - /** - * Sets a query parameter for the query being constructed. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u') - * ->where('u.id = :user_id') - * ->setParameter('user_id', 1); - * - * - * @param string|integer $key The parameter position or name. - * @param mixed $value The parameter value. - * @param string|integer|null $type PDO::PARAM_* or \Doctrine\DBAL\Types\Type::* constant - * - * @return self - */ - public function setParameter($key, $value, $type = null) - { - $existingParameter = $this->getParameter($key); - - if ($existingParameter !== null) { - $existingParameter->setValue($value, $type); - - return $this; - } - - $this->parameters->add(new Query\Parameter($key, $value, $type)); - - return $this; - } - - /** - * Sets a collection of query parameters for the query being constructed. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u') - * ->where('u.id = :user_id1 OR u.id = :user_id2') - * ->setParameters(new ArrayCollection(array( - * new Parameter('user_id1', 1), - * new Parameter('user_id2', 2) - * ))); - * - * - * @param \Doctrine\Common\Collections\ArrayCollection|array $parameters The query parameters to set. - * - * @return self - */ - public function setParameters($parameters) - { - // BC compatibility with 2.3- - if (is_array($parameters)) { - $parameterCollection = new ArrayCollection(); - - foreach ($parameters as $key => $value) { - $parameter = new Query\Parameter($key, $value); - - $parameterCollection->add($parameter); - } - - $parameters = $parameterCollection; - } - - $this->parameters = $parameters; - - return $this; - } - - /** - * Gets all defined query parameters for the query being constructed. - * - * @return \Doctrine\Common\Collections\ArrayCollection The currently defined query parameters. - */ - public function getParameters() - { - return $this->parameters; - } - - /** - * Gets a (previously set) query parameter of the query being constructed. - * - * @param mixed $key The key (index or name) of the bound parameter. - * - * @return Query\Parameter|null The value of the bound parameter. - */ - public function getParameter($key) - { - $filteredParameters = $this->parameters->filter( - function (Query\Parameter $parameter) use ($key) : bool { - $parameterName = $parameter->getName(); - - return $key === $parameterName || (string) $key === (string) $parameterName; - } - ); - - return ! $filteredParameters->isEmpty() ? $filteredParameters->first() : null; - } - - /** - * Sets the position of the first result to retrieve (the "offset"). - * - * @param integer $firstResult The first result to return. - * - * @return self - */ - public function setFirstResult($firstResult) - { - $this->_firstResult = $firstResult; - - return $this; - } - - /** - * Gets the position of the first result the query object was set to retrieve (the "offset"). - * Returns NULL if {@link setFirstResult} was not applied to this QueryBuilder. - * - * @return integer The position of the first result. - */ - public function getFirstResult() - { - return $this->_firstResult; - } - - /** - * Sets the maximum number of results to retrieve (the "limit"). - * - * @param integer|null $maxResults The maximum number of results to retrieve. - * - * @return self - */ - public function setMaxResults($maxResults) - { - $this->_maxResults = $maxResults; - - return $this; - } - - /** - * Gets the maximum number of results the query object was set to retrieve (the "limit"). - * Returns NULL if {@link setMaxResults} was not applied to this query builder. - * - * @return integer|null Maximum number of results. - */ - public function getMaxResults() - { - return $this->_maxResults; - } - - /** - * Either appends to or replaces a single, generic query part. - * - * The available parts are: 'select', 'from', 'join', 'set', 'where', - * 'groupBy', 'having' and 'orderBy'. - * - * @param string $dqlPartName The DQL part name. - * @param object|array $dqlPart An Expr object. - * @param bool $append Whether to append (true) or replace (false). - * - * @return self - */ - public function add($dqlPartName, $dqlPart, $append = false) - { - if ($append && ($dqlPartName === "where" || $dqlPartName === "having")) { - throw new \InvalidArgumentException( - "Using \$append = true does not have an effect with 'where' or 'having' ". - "parts. See QueryBuilder#andWhere() for an example for correct usage." - ); - } - - $isMultiple = is_array($this->_dqlParts[$dqlPartName]) - && !($dqlPartName == 'join' && !$append); - - // Allow adding any part retrieved from self::getDQLParts(). - if (is_array($dqlPart) && $dqlPartName != 'join') { - $dqlPart = reset($dqlPart); - } - - // This is introduced for backwards compatibility reasons. - // TODO: Remove for 3.0 - if ($dqlPartName == 'join') { - $newDqlPart = []; - - foreach ($dqlPart as $k => $v) { - $k = is_numeric($k) ? $this->getRootAlias() : $k; - - $newDqlPart[$k] = $v; - } - - $dqlPart = $newDqlPart; - } - - if ($append && $isMultiple) { - if (is_array($dqlPart)) { - $key = key($dqlPart); - - $this->_dqlParts[$dqlPartName][$key][] = $dqlPart[$key]; - } else { - $this->_dqlParts[$dqlPartName][] = $dqlPart; - } - } else { - $this->_dqlParts[$dqlPartName] = ($isMultiple) ? [$dqlPart] : $dqlPart; - } - - $this->_state = self::STATE_DIRTY; - - return $this; - } - - /** - * Specifies an item that is to be returned in the query result. - * Replaces any previously specified selections, if any. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u', 'p') - * ->from('User', 'u') - * ->leftJoin('u.Phonenumbers', 'p'); - * - * - * @param mixed $select The selection expressions. - * - * @return self - */ - public function select($select = null) - { - $this->_type = self::SELECT; - - if (empty($select)) { - return $this; - } - - $selects = is_array($select) ? $select : func_get_args(); - - return $this->add('select', new Expr\Select($selects), false); - } - - /** - * Adds a DISTINCT flag to this query. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->distinct() - * ->from('User', 'u'); - * - * - * @param bool $flag - * - * @return self - */ - public function distinct($flag = true) - { - $this->_dqlParts['distinct'] = (bool) $flag; - - return $this; - } - - /** - * Adds an item that is to be returned in the query result. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->addSelect('p') - * ->from('User', 'u') - * ->leftJoin('u.Phonenumbers', 'p'); - * - * - * @param mixed $select The selection expression. - * - * @return self - */ - public function addSelect($select = null) - { - $this->_type = self::SELECT; - - if (empty($select)) { - return $this; - } - - $selects = is_array($select) ? $select : func_get_args(); - - return $this->add('select', new Expr\Select($selects), true); - } - - /** - * Turns the query being built into a bulk delete query that ranges over - * a certain entity type. - * - * - * $qb = $em->createQueryBuilder() - * ->delete('User', 'u') - * ->where('u.id = :user_id') - * ->setParameter('user_id', 1); - * - * - * @param string $delete The class/type whose instances are subject to the deletion. - * @param string $alias The class/type alias used in the constructed query. - * - * @return self - */ - public function delete($delete = null, $alias = null) - { - $this->_type = self::DELETE; - - if ( ! $delete) { - return $this; - } - - return $this->add('from', new Expr\From($delete, $alias)); - } - - /** - * Turns the query being built into a bulk update query that ranges over - * a certain entity type. - * - * - * $qb = $em->createQueryBuilder() - * ->update('User', 'u') - * ->set('u.password', '?1') - * ->where('u.id = ?2'); - * - * - * @param string $update The class/type whose instances are subject to the update. - * @param string $alias The class/type alias used in the constructed query. - * - * @return self - */ - public function update($update = null, $alias = null) - { - $this->_type = self::UPDATE; - - if ( ! $update) { - return $this; - } - - return $this->add('from', new Expr\From($update, $alias)); - } - - /** - * Creates and adds a query root corresponding to the entity identified by the given alias, - * forming a cartesian product with any existing query roots. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u'); - * - * - * @param string $from The class name. - * @param string $alias The alias of the class. - * @param string $indexBy The index for the from. - * - * @return self - */ - public function from($from, $alias, $indexBy = null) - { - return $this->add('from', new Expr\From($from, $alias, $indexBy), true); - } - - /** - * Updates a query root corresponding to an entity setting its index by. This method is intended to be used with - * EntityRepository->createQueryBuilder(), which creates the initial FROM clause and do not allow you to update it - * setting an index by. - * - * - * $qb = $userRepository->createQueryBuilder('u') - * ->indexBy('u', 'u.id'); - * - * // Is equivalent to... - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u', 'u.id'); - * - * - * @param string $alias The root alias of the class. - * @param string $indexBy The index for the from. - * - * @return self - * - * @throws Query\QueryException - */ - public function indexBy($alias, $indexBy) - { - $rootAliases = $this->getRootAliases(); - - if (!in_array($alias, $rootAliases)) { - throw new Query\QueryException( - sprintf('Specified root alias %s must be set before invoking indexBy().', $alias) - ); - } - - foreach ($this->_dqlParts['from'] as &$fromClause) { - /* @var Expr\From $fromClause */ - if ($fromClause->getAlias() !== $alias) { - continue; - } - - $fromClause = new Expr\From($fromClause->getFrom(), $fromClause->getAlias(), $indexBy); - } - - return $this; - } - - /** - * Creates and adds a join over an entity association to the query. - * - * The entities in the joined association will be fetched as part of the query - * result if the alias used for the joined association is placed in the select - * expressions. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u') - * ->join('u.Phonenumbers', 'p', Expr\Join::WITH, 'p.is_primary = 1'); - * - * - * @param string $join The relationship to join. - * @param string $alias The alias of the join. - * @param string|null $conditionType The condition type constant. Either ON or WITH. - * @param string|null $condition The condition for the join. - * @param string|null $indexBy The index for the join. - * - * @return self - */ - public function join($join, $alias, $conditionType = null, $condition = null, $indexBy = null) - { - return $this->innerJoin($join, $alias, $conditionType, $condition, $indexBy); - } - - /** - * Creates and adds a join over an entity association to the query. - * - * The entities in the joined association will be fetched as part of the query - * result if the alias used for the joined association is placed in the select - * expressions. - * - * [php] - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u') - * ->innerJoin('u.Phonenumbers', 'p', Expr\Join::WITH, 'p.is_primary = 1'); - * - * @param string $join The relationship to join. - * @param string $alias The alias of the join. - * @param string|null $conditionType The condition type constant. Either ON or WITH. - * @param string|null $condition The condition for the join. - * @param string|null $indexBy The index for the join. - * - * @return self - */ - public function innerJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null) - { - $parentAlias = substr($join, 0, strpos($join, '.')); - - $rootAlias = $this->findRootAlias($alias, $parentAlias); - - $join = new Expr\Join( - Expr\Join::INNER_JOIN, $join, $alias, $conditionType, $condition, $indexBy - ); - - return $this->add('join', [$rootAlias => $join], true); - } - - /** - * Creates and adds a left join over an entity association to the query. - * - * The entities in the joined association will be fetched as part of the query - * result if the alias used for the joined association is placed in the select - * expressions. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u') - * ->leftJoin('u.Phonenumbers', 'p', Expr\Join::WITH, 'p.is_primary = 1'); - * - * - * @param string $join The relationship to join. - * @param string $alias The alias of the join. - * @param string|null $conditionType The condition type constant. Either ON or WITH. - * @param string|null $condition The condition for the join. - * @param string|null $indexBy The index for the join. - * - * @return self - */ - public function leftJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null) - { - $parentAlias = substr($join, 0, strpos($join, '.')); - - $rootAlias = $this->findRootAlias($alias, $parentAlias); - - $join = new Expr\Join( - Expr\Join::LEFT_JOIN, $join, $alias, $conditionType, $condition, $indexBy - ); - - return $this->add('join', [$rootAlias => $join], true); - } - - /** - * Sets a new value for a field in a bulk update query. - * - * - * $qb = $em->createQueryBuilder() - * ->update('User', 'u') - * ->set('u.password', '?1') - * ->where('u.id = ?2'); - * - * - * @param string $key The key/field to set. - * @param mixed $value The value, expression, placeholder, etc. - * - * @return self - */ - public function set($key, $value) - { - return $this->add('set', new Expr\Comparison($key, Expr\Comparison::EQ, $value), true); - } - - /** - * Specifies one or more restrictions to the query result. - * Replaces any previously specified restrictions, if any. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u') - * ->where('u.id = ?'); - * - * // You can optionally programmatically build and/or expressions - * $qb = $em->createQueryBuilder(); - * - * $or = $qb->expr()->orX(); - * $or->add($qb->expr()->eq('u.id', 1)); - * $or->add($qb->expr()->eq('u.id', 2)); - * - * $qb->update('User', 'u') - * ->set('u.password', '?') - * ->where($or); - * - * - * @param mixed $predicates The restriction predicates. - * - * @return self - */ - public function where($predicates) - { - if ( ! (func_num_args() == 1 && $predicates instanceof Expr\Composite)) { - $predicates = new Expr\Andx(func_get_args()); - } - - return $this->add('where', $predicates); - } - - /** - * Adds one or more restrictions to the query results, forming a logical - * conjunction with any previously specified restrictions. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u') - * ->where('u.username LIKE ?') - * ->andWhere('u.is_active = 1'); - * - * - * @param mixed $where The query restrictions. - * - * @return self - * - * @see where() - */ - public function andWhere() - { - $args = func_get_args(); - $where = $this->getDQLPart('where'); - - if ($where instanceof Expr\Andx) { - $where->addMultiple($args); - } else { - array_unshift($args, $where); - $where = new Expr\Andx($args); - } - - return $this->add('where', $where); - } - - /** - * Adds one or more restrictions to the query results, forming a logical - * disjunction with any previously specified restrictions. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u') - * ->where('u.id = 1') - * ->orWhere('u.id = 2'); - * - * - * @param mixed $where The WHERE statement. - * - * @return self - * - * @see where() - */ - public function orWhere() - { - $args = func_get_args(); - $where = $this->getDQLPart('where'); - - if ($where instanceof Expr\Orx) { - $where->addMultiple($args); - } else { - array_unshift($args, $where); - $where = new Expr\Orx($args); - } - - return $this->add('where', $where); - } - - /** - * Specifies a grouping over the results of the query. - * Replaces any previously specified groupings, if any. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u') - * ->groupBy('u.id'); - * - * - * @param string $groupBy The grouping expression. - * - * @return self - */ - public function groupBy($groupBy) - { - return $this->add('groupBy', new Expr\GroupBy(func_get_args())); - } - - /** - * Adds a grouping expression to the query. - * - * - * $qb = $em->createQueryBuilder() - * ->select('u') - * ->from('User', 'u') - * ->groupBy('u.lastLogin') - * ->addGroupBy('u.createdAt'); - * - * - * @param string $groupBy The grouping expression. - * - * @return self - */ - public function addGroupBy($groupBy) - { - return $this->add('groupBy', new Expr\GroupBy(func_get_args()), true); - } - - /** - * Specifies a restriction over the groups of the query. - * Replaces any previous having restrictions, if any. - * - * @param mixed $having The restriction over the groups. - * - * @return self - */ - public function having($having) - { - if ( ! (func_num_args() == 1 && ($having instanceof Expr\Andx || $having instanceof Expr\Orx))) { - $having = new Expr\Andx(func_get_args()); - } - - return $this->add('having', $having); - } - - /** - * Adds a restriction over the groups of the query, forming a logical - * conjunction with any existing having restrictions. - * - * @param mixed $having The restriction to append. - * - * @return self - */ - public function andHaving($having) - { - $args = func_get_args(); - $having = $this->getDQLPart('having'); - - if ($having instanceof Expr\Andx) { - $having->addMultiple($args); - } else { - array_unshift($args, $having); - $having = new Expr\Andx($args); - } - - return $this->add('having', $having); - } - - /** - * Adds a restriction over the groups of the query, forming a logical - * disjunction with any existing having restrictions. - * - * @param mixed $having The restriction to add. - * - * @return self - */ - public function orHaving($having) - { - $args = func_get_args(); - $having = $this->getDQLPart('having'); - - if ($having instanceof Expr\Orx) { - $having->addMultiple($args); - } else { - array_unshift($args, $having); - $having = new Expr\Orx($args); - } - - return $this->add('having', $having); - } - - /** - * Specifies an ordering for the query results. - * Replaces any previously specified orderings, if any. - * - * @param string|Expr\OrderBy $sort The ordering expression. - * @param string $order The ordering direction. - * - * @return self - */ - public function orderBy($sort, $order = null) - { - $orderBy = ($sort instanceof Expr\OrderBy) ? $sort : new Expr\OrderBy($sort, $order); - - return $this->add('orderBy', $orderBy); - } - - /** - * Adds an ordering to the query results. - * - * @param string|Expr\OrderBy $sort The ordering expression. - * @param string $order The ordering direction. - * - * @return self - */ - public function addOrderBy($sort, $order = null) - { - $orderBy = ($sort instanceof Expr\OrderBy) ? $sort : new Expr\OrderBy($sort, $order); - - return $this->add('orderBy', $orderBy, true); - } - - /** - * Adds criteria to the query. - * - * Adds where expressions with AND operator. - * Adds orderings. - * Overrides firstResult and maxResults if they're set. - * - * @param Criteria $criteria - * - * @return self - * - * @throws Query\QueryException - */ - public function addCriteria(Criteria $criteria) - { - $allAliases = $this->getAllAliases(); - if ( ! isset($allAliases[0])) { - throw new Query\QueryException('No aliases are set before invoking addCriteria().'); - } - - $visitor = new QueryExpressionVisitor($this->getAllAliases()); - - if ($whereExpression = $criteria->getWhereExpression()) { - $this->andWhere($visitor->dispatch($whereExpression)); - foreach ($visitor->getParameters() as $parameter) { - $this->parameters->add($parameter); - } - } - - if ($criteria->getOrderings()) { - foreach ($criteria->getOrderings() as $sort => $order) { - - $hasValidAlias = false; - foreach($allAliases as $alias) { - if(strpos($sort . '.', $alias . '.') === 0) { - $hasValidAlias = true; - break; - } - } - - if(!$hasValidAlias) { - $sort = $allAliases[0] . '.' . $sort; - } - - $this->addOrderBy($sort, $order); - } - } - - // Overwrite limits only if they was set in criteria - if (($firstResult = $criteria->getFirstResult()) !== null) { - $this->setFirstResult($firstResult); - } - if (($maxResults = $criteria->getMaxResults()) !== null) { - $this->setMaxResults($maxResults); - } - - return $this; - } - - /** - * Gets a query part by its name. - * - * @param string $queryPartName - * - * @return mixed $queryPart - * - * @todo Rename: getQueryPart (or remove?) - */ - public function getDQLPart($queryPartName) - { - return $this->_dqlParts[$queryPartName]; - } - - /** - * Gets all query parts. - * - * @return array $dqlParts - * - * @todo Rename: getQueryParts (or remove?) - */ - public function getDQLParts() - { - return $this->_dqlParts; - } - - /** - * @return string - */ - private function _getDQLForDelete() - { - return 'DELETE' - . $this->_getReducedDQLQueryPart('from', ['pre' => ' ', 'separator' => ', ']) - . $this->_getReducedDQLQueryPart('where', ['pre' => ' WHERE ']) - . $this->_getReducedDQLQueryPart('orderBy', ['pre' => ' ORDER BY ', 'separator' => ', ']); - } - - /** - * @return string - */ - private function _getDQLForUpdate() - { - return 'UPDATE' - . $this->_getReducedDQLQueryPart('from', ['pre' => ' ', 'separator' => ', ']) - . $this->_getReducedDQLQueryPart('set', ['pre' => ' SET ', 'separator' => ', ']) - . $this->_getReducedDQLQueryPart('where', ['pre' => ' WHERE ']) - . $this->_getReducedDQLQueryPart('orderBy', ['pre' => ' ORDER BY ', 'separator' => ', ']); - } - - /** - * @return string - */ - private function _getDQLForSelect() - { - $dql = 'SELECT' - . ($this->_dqlParts['distinct']===true ? ' DISTINCT' : '') - . $this->_getReducedDQLQueryPart('select', ['pre' => ' ', 'separator' => ', ']); - - $fromParts = $this->getDQLPart('from'); - $joinParts = $this->getDQLPart('join'); - $fromClauses = []; - - // Loop through all FROM clauses - if ( ! empty($fromParts)) { - $dql .= ' FROM '; - - foreach ($fromParts as $from) { - $fromClause = (string) $from; - - if ($from instanceof Expr\From && isset($joinParts[$from->getAlias()])) { - foreach ($joinParts[$from->getAlias()] as $join) { - $fromClause .= ' ' . ((string) $join); - } - } - - $fromClauses[] = $fromClause; - } - } - - $dql .= implode(', ', $fromClauses) - . $this->_getReducedDQLQueryPart('where', ['pre' => ' WHERE ']) - . $this->_getReducedDQLQueryPart('groupBy', ['pre' => ' GROUP BY ', 'separator' => ', ']) - . $this->_getReducedDQLQueryPart('having', ['pre' => ' HAVING ']) - . $this->_getReducedDQLQueryPart('orderBy', ['pre' => ' ORDER BY ', 'separator' => ', ']); - - return $dql; - } - - /** - * @param string $queryPartName - * @param array $options - * - * @return string - */ - private function _getReducedDQLQueryPart($queryPartName, $options = []) - { - $queryPart = $this->getDQLPart($queryPartName); - - if (empty($queryPart)) { - return ($options['empty'] ?? ''); - } - - return ($options['pre'] ?? '') - . (is_array($queryPart) ? implode($options['separator'], $queryPart) : $queryPart) - . ($options['post'] ?? ''); - } - - /** - * Resets DQL parts. - * - * @param array|null $parts - * - * @return self - */ - public function resetDQLParts($parts = null) - { - if (null === $parts) { - $parts = array_keys($this->_dqlParts); - } - - foreach ($parts as $part) { - $this->resetDQLPart($part); - } - - return $this; - } - - /** - * Resets single DQL part. - * - * @param string $part - * - * @return self - */ - public function resetDQLPart($part) - { - $this->_dqlParts[$part] = is_array($this->_dqlParts[$part]) ? [] : null; - $this->_state = self::STATE_DIRTY; - - return $this; - } - - /** - * Gets a string representation of this QueryBuilder which corresponds to - * the final DQL query being constructed. - * - * @return string The string representation of this QueryBuilder. - */ - public function __toString() - { - return $this->getDQL(); - } - - /** - * Deep clones all expression objects in the DQL parts. - * - * @return void - */ - public function __clone() - { - foreach ($this->_dqlParts as $part => $elements) { - if (is_array($this->_dqlParts[$part])) { - foreach ($this->_dqlParts[$part] as $idx => $element) { - if (is_object($element)) { - $this->_dqlParts[$part][$idx] = clone $element; - } - } - } else if (is_object($elements)) { - $this->_dqlParts[$part] = clone $elements; - } - } - - $parameters = []; - - foreach ($this->parameters as $parameter) { - $parameters[] = clone $parameter; - } - - $this->parameters = new ArrayCollection($parameters); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php deleted file mode 100644 index 6809624..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/DefaultRepositoryFactory.php +++ /dev/null @@ -1,70 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Repository; - -use Doctrine\ORM\EntityManagerInterface; - -/** - * This factory is used to create default repository objects for entities at runtime. - * - * @author Guilherme Blanco - * @since 2.4 - */ -final class DefaultRepositoryFactory implements RepositoryFactory -{ - /** - * The list of EntityRepository instances. - * - * @var \Doctrine\Common\Persistence\ObjectRepository[] - */ - private $repositoryList = []; - - /** - * {@inheritdoc} - */ - public function getRepository(EntityManagerInterface $entityManager, $entityName) - { - $repositoryHash = $entityManager->getClassMetadata($entityName)->getName() . spl_object_hash($entityManager); - - if (isset($this->repositoryList[$repositoryHash])) { - return $this->repositoryList[$repositoryHash]; - } - - return $this->repositoryList[$repositoryHash] = $this->createRepository($entityManager, $entityName); - } - - /** - * Create a new repository instance for an entity class. - * - * @param \Doctrine\ORM\EntityManagerInterface $entityManager The EntityManager instance. - * @param string $entityName The name of the entity. - * - * @return \Doctrine\Common\Persistence\ObjectRepository - */ - private function createRepository(EntityManagerInterface $entityManager, $entityName) - { - /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */ - $metadata = $entityManager->getClassMetadata($entityName); - $repositoryClassName = $metadata->customRepositoryClassName - ?: $entityManager->getConfiguration()->getDefaultRepositoryClassName(); - - return new $repositoryClassName($entityManager, $metadata); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/RepositoryFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/RepositoryFactory.php deleted file mode 100644 index f3af43e..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Repository/RepositoryFactory.php +++ /dev/null @@ -1,41 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Repository; - -use Doctrine\ORM\EntityManagerInterface; - -/** - * Interface for entity repository factory. - * - * @author Guilherme Blanco - * @since 2.4 - */ -interface RepositoryFactory -{ - /** - * Gets the repository for an entity class. - * - * @param \Doctrine\ORM\EntityManagerInterface $entityManager The EntityManager instance. - * @param string $entityName The name of the entity. - * - * @return \Doctrine\Common\Persistence\ObjectRepository - */ - public function getRepository(EntityManagerInterface $entityManager, $entityName); -} \ No newline at end of file diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/AttachEntityListenersListener.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/AttachEntityListenersListener.php deleted file mode 100644 index cf7cc8b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/AttachEntityListenersListener.php +++ /dev/null @@ -1,79 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools; - -use Doctrine\ORM\Event\LoadClassMetadataEventArgs; - -/** - * Mechanism to programmatically attach entity listeners. - * - * @author Fabio B. SIlva - * - * @since 2.5 - */ -class AttachEntityListenersListener -{ - /** - * @var array[] - */ - private $entityListeners = []; - - /** - * Adds a entity listener for a specific entity. - * - * @param string $entityClass The entity to attach the listener. - * @param string $listenerClass The listener class. - * @param string $eventName The entity lifecycle event. - * @param string|null $listenerCallback The listener callback method or NULL to use $eventName. - * - * @return void - */ - public function addEntityListener($entityClass, $listenerClass, $eventName, $listenerCallback = null) - { - $this->entityListeners[ltrim($entityClass, '\\')][] = [ - 'event' => $eventName, - 'class' => $listenerClass, - 'method' => $listenerCallback ?: $eventName - ]; - } - - /** - * Processes event and attach the entity listener. - * - * @param \Doctrine\ORM\Event\LoadClassMetadataEventArgs $event - * - * @return void - */ - public function loadClassMetadata(LoadClassMetadataEventArgs $event) - { - /** @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */ - $metadata = $event->getClassMetadata(); - - if ( ! isset($this->entityListeners[$metadata->name])) { - return; - } - - foreach ($this->entityListeners[$metadata->name] as $listener) { - $metadata->addEntityListener($listener['event'], $listener['class'], $listener['method']); - } - - unset($this->entityListeners[$metadata->name]); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/CollectionRegionCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/CollectionRegionCommand.php deleted file mode 100644 index 1c75ccc..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/CollectionRegionCommand.php +++ /dev/null @@ -1,149 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command\ClearCache; - -use Doctrine\ORM\Cache; -use Doctrine\ORM\Cache\Region\DefaultRegion; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to clear a collection cache region. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class CollectionRegionCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:clear-cache:region:collection') - ->setDescription('Clear a second-level cache collection region') - ->addArgument('owner-class', InputArgument::OPTIONAL, 'The owner entity name.') - ->addArgument('association', InputArgument::OPTIONAL, 'The association collection name.') - ->addArgument('owner-id', InputArgument::OPTIONAL, 'The owner identifier.') - ->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all entity regions will be deleted/invalidated.') - ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, all cache entries will be flushed.') - ->setHelp(<<%command.name% command is meant to clear a second-level cache collection regions for an associated Entity Manager. -It is possible to delete/invalidate all collection region, a specific collection region or flushes the cache provider. - -The execution type differ on how you execute the command. -If you want to invalidate all entries for an collection region this command would do the work: - -%command.name% 'Entities\MyEntity' 'collectionName' - -To invalidate a specific entry you should use : - -%command.name% 'Entities\MyEntity' 'collectionName' 1 - -If you want to invalidate all entries for the all collection regions: - -%command.name% --all - -Alternatively, if you want to flush the configured cache provider for an collection region use this command: - -%command.name% 'Entities\MyEntity' 'collectionName' --flush - -Finally, be aware that if --flush option is passed, -not all cache providers are able to flush entries, because of a limitation of its execution nature. -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - $em = $this->getHelper('em')->getEntityManager(); - $ownerClass = $input->getArgument('owner-class'); - $assoc = $input->getArgument('association'); - $ownerId = $input->getArgument('owner-id'); - $cache = $em->getCache(); - - if ( ! $cache instanceof Cache) { - throw new \InvalidArgumentException('No second-level cache is configured on the given EntityManager.'); - } - - if (( ! $ownerClass || ! $assoc) && ! $input->getOption('all')) { - throw new \InvalidArgumentException('Missing arguments "--owner-class" "--association"'); - } - - if ($input->getOption('flush')) { - $collectionRegion = $cache->getCollectionCacheRegion($ownerClass, $assoc); - - if ( ! $collectionRegion instanceof DefaultRegion) { - throw new \InvalidArgumentException(sprintf( - 'The option "--flush" expects a "Doctrine\ORM\Cache\Region\DefaultRegion", but got "%s".', - is_object($collectionRegion) ? get_class($collectionRegion) : gettype($collectionRegion) - )); - } - - $collectionRegion->getCache()->flushAll(); - - $ui->comment( - sprintf( - 'Flushing cache provider configured for "%s#%s"', - $ownerClass, - $assoc - ) - ); - - return 0; - } - - if ($input->getOption('all')) { - $ui->comment('Clearing all second-level cache collection regions'); - - $cache->evictEntityRegions(); - - return 0; - } - - if ($ownerId) { - $ui->comment( - sprintf( - 'Clearing second-level cache entry for collection "%s#%s" owner entity identified by "%s"', - $ownerClass, - $assoc, - $ownerId - ) - ); - $cache->evictCollection($ownerClass, $assoc, $ownerId); - - return 0; - } - - $ui->comment(sprintf('Clearing second-level cache for collection "%s#%s"', $ownerClass, $assoc)); - $cache->evictCollectionRegion($ownerClass, $assoc); - - return 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/EntityRegionCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/EntityRegionCommand.php deleted file mode 100644 index c246910..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/EntityRegionCommand.php +++ /dev/null @@ -1,140 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command\ClearCache; - -use Doctrine\ORM\Cache; -use Doctrine\ORM\Cache\Region\DefaultRegion; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to clear a entity cache region. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class EntityRegionCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:clear-cache:region:entity') - ->setDescription('Clear a second-level cache entity region') - ->addArgument('entity-class', InputArgument::OPTIONAL, 'The entity name.') - ->addArgument('entity-id', InputArgument::OPTIONAL, 'The entity identifier.') - ->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all entity regions will be deleted/invalidated.') - ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, all cache entries will be flushed.') - ->setHelp(<<%command.name% command is meant to clear a second-level cache entity region for an associated Entity Manager. -It is possible to delete/invalidate all entity region, a specific entity region or flushes the cache provider. - -The execution type differ on how you execute the command. -If you want to invalidate all entries for an entity region this command would do the work: - -%command.name% 'Entities\MyEntity' - -To invalidate a specific entry you should use : - -%command.name% 'Entities\MyEntity' 1 - -If you want to invalidate all entries for the all entity regions: - -%command.name% --all - -Alternatively, if you want to flush the configured cache provider for an entity region use this command: - -%command.name% 'Entities\MyEntity' --flush - -Finally, be aware that if --flush option is passed, -not all cache providers are able to flush entries, because of a limitation of its execution nature. -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - $em = $this->getHelper('em')->getEntityManager(); - $entityClass = $input->getArgument('entity-class'); - $entityId = $input->getArgument('entity-id'); - $cache = $em->getCache(); - - if ( ! $cache instanceof Cache) { - throw new \InvalidArgumentException('No second-level cache is configured on the given EntityManager.'); - } - - if ( ! $entityClass && ! $input->getOption('all')) { - throw new \InvalidArgumentException('Invalid argument "--entity-class"'); - } - - if ($input->getOption('flush')) { - $entityRegion = $cache->getEntityCacheRegion($entityClass); - - if ( ! $entityRegion instanceof DefaultRegion) { - throw new \InvalidArgumentException(sprintf( - 'The option "--flush" expects a "Doctrine\ORM\Cache\Region\DefaultRegion", but got "%s".', - is_object($entityRegion) ? get_class($entityRegion) : gettype($entityRegion) - )); - } - - $entityRegion->getCache()->flushAll(); - - $ui->comment(sprintf('Flushing cache provider configured for entity named "%s"', $entityClass)); - - return 0; - } - - if ($input->getOption('all')) { - $ui->comment('Clearing all second-level cache entity regions'); - - $cache->evictEntityRegions(); - - return 0; - } - - if ($entityId) { - $ui->comment( - sprintf( - 'Clearing second-level cache entry for entity "%s" identified by "%s"', - $entityClass, - $entityId - ) - ); - $cache->evictEntity($entityClass, $entityId); - - return 0; - } - - $ui->comment(sprintf('Clearing second-level cache for entity "%s"', $entityClass)); - $cache->evictEntityRegion($entityClass); - - return 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/MetadataCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/MetadataCommand.php deleted file mode 100644 index e6531f2..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/MetadataCommand.php +++ /dev/null @@ -1,112 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command\ClearCache; - -use Doctrine\Common\Cache\ApcCache; -use Doctrine\Common\Cache\XcacheCache; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to clear the metadata cache of the various cache drivers. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class MetadataCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:clear-cache:metadata') - ->setDescription('Clear all metadata cache of the various cache drivers') - ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, cache entries will be flushed instead of deleted/invalidated.') - ->setHelp(<<%command.name% command is meant to clear the metadata cache of associated Entity Manager. -It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider -instance completely. - -The execution type differ on how you execute the command. -If you want to invalidate the entries (and not delete from cache instance), this command would do the work: - -%command.name% - -Alternatively, if you want to flush the cache provider using this command: - -%command.name% --flush - -Finally, be aware that if --flush option is passed, not all cache providers are able to flush entries, -because of a limitation of its execution nature. -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - $em = $this->getHelper('em')->getEntityManager(); - $cacheDriver = $em->getConfiguration()->getMetadataCacheImpl(); - - if ( ! $cacheDriver) { - throw new \InvalidArgumentException('No Metadata cache driver is configured on given EntityManager.'); - } - - if ($cacheDriver instanceof ApcCache) { - throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); - } - - if ($cacheDriver instanceof XcacheCache) { - throw new \LogicException("Cannot clear XCache Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); - } - - $ui->comment('Clearing all Metadata cache entries'); - - $result = $cacheDriver->deleteAll(); - $message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.'; - - if (true === $input->getOption('flush')) { - $result = $cacheDriver->flushAll(); - $message = ($result) ? 'Successfully flushed cache entries.' : $message; - } - - if ( ! $result) { - $ui->error($message); - - return 1; - } - - $ui->success($message); - - return 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php deleted file mode 100644 index 95bec91..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php +++ /dev/null @@ -1,111 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command\ClearCache; - -use Doctrine\Common\Cache\ApcCache; -use Doctrine\Common\Cache\XcacheCache; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to clear the query cache of the various cache drivers. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class QueryCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:clear-cache:query') - ->setDescription('Clear all query cache of the various cache drivers') - ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, cache entries will be flushed instead of deleted/invalidated.') - ->setHelp(<<%command.name% command is meant to clear the query cache of associated Entity Manager. -It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider -instance completely. - -The execution type differ on how you execute the command. -If you want to invalidate the entries (and not delete from cache instance), this command would do the work: - -%command.name% - -Alternatively, if you want to flush the cache provider using this command: - -%command.name% --flush - -Finally, be aware that if --flush option is passed, not all cache providers are able to flush entries, -because of a limitation of its execution nature. -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - $em = $this->getHelper('em')->getEntityManager(); - $cacheDriver = $em->getConfiguration()->getQueryCacheImpl(); - - if ( ! $cacheDriver) { - throw new \InvalidArgumentException('No Query cache driver is configured on given EntityManager.'); - } - - if ($cacheDriver instanceof ApcCache) { - throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); - } - if ($cacheDriver instanceof XcacheCache) { - throw new \LogicException("Cannot clear XCache Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); - } - - $ui->comment('Clearing all Query cache entries'); - - $result = $cacheDriver->deleteAll(); - $message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.'; - - if (true === $input->getOption('flush')) { - $result = $cacheDriver->flushAll(); - $message = ($result) ? 'Successfully flushed cache entries.' : $message; - } - - if ( ! $result) { - $ui->error($message); - - return 1; - } - - $ui->success($message); - - return 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryRegionCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryRegionCommand.php deleted file mode 100644 index 36ffa12..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryRegionCommand.php +++ /dev/null @@ -1,131 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command\ClearCache; - -use Doctrine\ORM\Cache; -use Doctrine\ORM\Cache\Region\DefaultRegion; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to clear a query cache region. - * - * @since 2.5 - * @author Fabio B. Silva - */ -class QueryRegionCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:clear-cache:region:query') - ->setDescription('Clear a second-level cache query region') - ->addArgument('region-name', InputArgument::OPTIONAL, 'The query region to clear.') - ->addOption('all', null, InputOption::VALUE_NONE, 'If defined, all query regions will be deleted/invalidated.') - ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, all cache entries will be flushed.') - ->setHelp(<<%command.name% command is meant to clear a second-level cache query region for an associated Entity Manager. -It is possible to delete/invalidate all query region, a specific query region or flushes the cache provider. - -The execution type differ on how you execute the command. -If you want to invalidate all entries for the default query region this command would do the work: - -%command.name% - -To invalidate entries for a specific query region you should use : - -%command.name% my_region_name - -If you want to invalidate all entries for the all query region: - -%command.name% --all - -Alternatively, if you want to flush the configured cache provider use this command: - -%command.name% my_region_name --flush - -Finally, be aware that if --flush option is passed, -not all cache providers are able to flush entries, because of a limitation of its execution nature. -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - $em = $this->getHelper('em')->getEntityManager(); - $name = $input->getArgument('region-name'); - $cache = $em->getCache(); - - if ($name === null) { - $name = Cache::DEFAULT_QUERY_REGION_NAME; - } - - if ( ! $cache instanceof Cache) { - throw new \InvalidArgumentException('No second-level cache is configured on the given EntityManager.'); - } - - if ($input->getOption('flush')) { - $queryCache = $cache->getQueryCache($name); - $queryRegion = $queryCache->getRegion(); - - if ( ! $queryRegion instanceof DefaultRegion) { - throw new \InvalidArgumentException(sprintf( - 'The option "--flush" expects a "Doctrine\ORM\Cache\Region\DefaultRegion", but got "%s".', - is_object($queryRegion) ? get_class($queryRegion) : gettype($queryRegion) - )); - } - - $queryRegion->getCache()->flushAll(); - - $ui->comment( - sprintf( - 'Flushing cache provider configured for second-level cache query region named "%s"', - $name - ) - ); - - return 0; - } - - if ($input->getOption('all')) { - $ui->comment('Clearing all second-level cache query regions'); - - $cache->evictQueryRegions(); - - return 0; - } - - $ui->comment(sprintf('Clearing second-level cache query region named "%s"', $name)); - $cache->evictQueryRegion($name); - - return 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php deleted file mode 100644 index 42ad79c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php +++ /dev/null @@ -1,112 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command\ClearCache; - -use Doctrine\Common\Cache\ApcCache; -use Doctrine\Common\Cache\XcacheCache; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to clear the result cache of the various cache drivers. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ResultCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:clear-cache:result') - ->setDescription('Clear all result cache of the various cache drivers') - ->addOption('flush', null, InputOption::VALUE_NONE, 'If defined, cache entries will be flushed instead of deleted/invalidated.') - ->setHelp(<<%command.name% command is meant to clear the result cache of associated Entity Manager. -It is possible to invalidate all cache entries at once - called delete -, or flushes the cache provider -instance completely. - -The execution type differ on how you execute the command. -If you want to invalidate the entries (and not delete from cache instance), this command would do the work: - -%command.name% - -Alternatively, if you want to flush the cache provider using this command: - -%command.name% --flush - -Finally, be aware that if --flush option is passed, not all cache providers are able to flush entries, -because of a limitation of its execution nature. -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - $em = $this->getHelper('em')->getEntityManager(); - $cacheDriver = $em->getConfiguration()->getResultCacheImpl(); - - if ( ! $cacheDriver) { - throw new \InvalidArgumentException('No Result cache driver is configured on given EntityManager.'); - } - - if ($cacheDriver instanceof ApcCache) { - throw new \LogicException("Cannot clear APC Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); - } - - if ($cacheDriver instanceof XcacheCache) { - throw new \LogicException("Cannot clear XCache Cache from Console, its shared in the Webserver memory and not accessible from the CLI."); - } - - $ui->comment('Clearing all Result cache entries'); - - $result = $cacheDriver->deleteAll(); - $message = ($result) ? 'Successfully deleted cache entries.' : 'No cache entries were deleted.'; - - if (true === $input->getOption('flush')) { - $result = $cacheDriver->flushAll(); - $message = ($result) ? 'Successfully flushed cache entries.' : $message; - } - - if ( ! $result) { - $ui->error($message); - - return 1; - } - - $ui->success($message); - - return 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php deleted file mode 100644 index 90de732..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertDoctrine1SchemaCommand.php +++ /dev/null @@ -1,214 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command; - -use Doctrine\ORM\Tools\ConvertDoctrine1Schema; -use Doctrine\ORM\Tools\EntityGenerator; -use Doctrine\ORM\Tools\Export\ClassMetadataExporter; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to convert a Doctrine 1 schema to a Doctrine 2 mapping file. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class ConvertDoctrine1SchemaCommand extends Command -{ - /** - * @var EntityGenerator|null - */ - private $entityGenerator = null; - - /** - * @var ClassMetadataExporter|null - */ - private $metadataExporter = null; - - /** - * @return EntityGenerator - */ - public function getEntityGenerator() - { - if ($this->entityGenerator == null) { - $this->entityGenerator = new EntityGenerator(); - } - - return $this->entityGenerator; - } - - /** - * @param EntityGenerator $entityGenerator - * - * @return void - */ - public function setEntityGenerator(EntityGenerator $entityGenerator) - { - $this->entityGenerator = $entityGenerator; - } - - /** - * @return ClassMetadataExporter - */ - public function getMetadataExporter() - { - if ($this->metadataExporter == null) { - $this->metadataExporter = new ClassMetadataExporter(); - } - - return $this->metadataExporter; - } - - /** - * @param ClassMetadataExporter $metadataExporter - * - * @return void - */ - public function setMetadataExporter(ClassMetadataExporter $metadataExporter) - { - $this->metadataExporter = $metadataExporter; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:convert-d1-schema') - ->setAliases(['orm:convert:d1-schema']) - ->setDescription('Converts Doctrine 1.x schema into a Doctrine 2.x schema') - ->addArgument('from-path', InputArgument::REQUIRED, 'The path of Doctrine 1.X schema information.') - ->addArgument('to-type', InputArgument::REQUIRED, 'The destination Doctrine 2.X mapping type.') - ->addArgument('dest-path', InputArgument::REQUIRED, 'The path to generate your Doctrine 2.X mapping information.') - ->addOption('from', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Optional paths of Doctrine 1.X schema information.', []) - ->addOption('extend', null, InputOption::VALUE_OPTIONAL, 'Defines a base class to be extended by generated entity classes.') - ->addOption('num-spaces', null, InputOption::VALUE_OPTIONAL, 'Defines the number of indentation spaces', 4) - ->setHelp('Converts Doctrine 1.x schema into a Doctrine 2.x schema.'); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - $ui->warning('Command ' . $this->getName() . ' is deprecated and will be removed in Doctrine ORM 3.0.'); - - // Process source directories - $fromPaths = array_merge([$input->getArgument('from-path')], $input->getOption('from')); - - // Process destination directory - $destPath = realpath($input->getArgument('dest-path')); - - $toType = $input->getArgument('to-type'); - $extend = $input->getOption('extend'); - $numSpaces = $input->getOption('num-spaces'); - - $this->convertDoctrine1Schema($fromPaths, $destPath, $toType, $numSpaces, $extend, $output); - - return 0; - } - - /** - * @param array $fromPaths - * @param string $destPath - * @param string $toType - * @param int $numSpaces - * @param string|null $extend - * @param OutputInterface $output - * - * @throws \InvalidArgumentException - */ - public function convertDoctrine1Schema(array $fromPaths, $destPath, $toType, $numSpaces, $extend, OutputInterface $output) - { - foreach ($fromPaths as &$dirName) { - $dirName = realpath($dirName); - - if ( ! file_exists($dirName)) { - throw new \InvalidArgumentException( - sprintf("Doctrine 1.X schema directory '%s' does not exist.", $dirName) - ); - } - - if ( ! is_readable($dirName)) { - throw new \InvalidArgumentException( - sprintf("Doctrine 1.X schema directory '%s' does not have read permissions.", $dirName) - ); - } - } - - if ( ! file_exists($destPath)) { - throw new \InvalidArgumentException( - sprintf("Doctrine 2.X mapping destination directory '%s' does not exist.", $destPath) - ); - } - - if ( ! is_writable($destPath)) { - throw new \InvalidArgumentException( - sprintf("Doctrine 2.X mapping destination directory '%s' does not have write permissions.", $destPath) - ); - } - - $cme = $this->getMetadataExporter(); - $exporter = $cme->getExporter($toType, $destPath); - - if (strtolower($toType) === 'annotation') { - $entityGenerator = $this->getEntityGenerator(); - $exporter->setEntityGenerator($entityGenerator); - - $entityGenerator->setNumSpaces($numSpaces); - - if ($extend !== null) { - $entityGenerator->setClassToExtend($extend); - } - } - - $converter = new ConvertDoctrine1Schema($fromPaths); - $metadata = $converter->getMetadata(); - - if ($metadata) { - $output->writeln(''); - - foreach ($metadata as $class) { - $output->writeln(sprintf('Processing entity "%s"', $class->name)); - } - - $exporter->setMetadata($metadata); - $exporter->export(); - - $output->writeln(PHP_EOL . sprintf( - 'Converting Doctrine 1.X schema to "%s" mapping type in "%s"', $toType, $destPath - )); - } else { - $output->writeln('No Metadata Classes to process.'); - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php deleted file mode 100644 index 8de2b84..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php +++ /dev/null @@ -1,186 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command; - -use Doctrine\ORM\Mapping\Driver\DatabaseDriver; -use Doctrine\ORM\Tools\Console\MetadataFilter; -use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory; -use Doctrine\ORM\Tools\EntityGenerator; -use Doctrine\ORM\Tools\Export\ClassMetadataExporter; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to convert your mapping information between the various formats. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ConvertMappingCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:convert-mapping') - ->setAliases(['orm:convert:mapping']) - ->setDescription('Convert mapping information between supported formats') - ->addArgument('to-type', InputArgument::REQUIRED, 'The mapping type to be converted.') - ->addArgument('dest-path', InputArgument::REQUIRED, 'The path to generate your entities classes.') - ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be processed.') - ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force to overwrite existing mapping files.') - ->addOption('from-database', null, null, 'Whether or not to convert mapping information from existing database.') - ->addOption('extend', null, InputOption::VALUE_OPTIONAL, 'Defines a base class to be extended by generated entity classes.') - ->addOption('num-spaces', null, InputOption::VALUE_OPTIONAL, 'Defines the number of indentation spaces', 4) - ->addOption('namespace', null, InputOption::VALUE_OPTIONAL, 'Defines a namespace for the generated entity classes, if converted from database.') - ->setHelp(<<one-time command. It should not be necessary for -you to call this method multiple times, especially when using the --from-database -flag. - -Converting an existing database schema into mapping files only solves about 70-80% -of the necessary mapping information. Additionally the detection from an existing -database cannot detect inverse associations, inheritance types, -entities with foreign keys as primary keys and many of the -semantical operations on associations such as cascade. - -Hint: There is no need to convert YAML or XML mapping files to annotations -every time you make changes. All mapping drivers are first class citizens -in Doctrine 2 and can be used as runtime mapping for the ORM. - -Hint: If you have a database with tables that should not be managed -by the ORM, you can use a DBAL functionality to filter the tables and sequences down -on a global level: - - \$config->setFilterSchemaAssetsExpression(\$regexp); -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - $em = $this->getHelper('em')->getEntityManager(); - - if ($input->getOption('from-database') === true) { - $databaseDriver = new DatabaseDriver( - $em->getConnection()->getSchemaManager() - ); - - $em->getConfiguration()->setMetadataDriverImpl( - $databaseDriver - ); - - if (($namespace = $input->getOption('namespace')) !== null) { - $databaseDriver->setNamespace($namespace); - } - } - - $cmf = new DisconnectedClassMetadataFactory(); - $cmf->setEntityManager($em); - $metadata = $cmf->getAllMetadata(); - $metadata = MetadataFilter::filter($metadata, $input->getOption('filter')); - - // Process destination directory - if ( ! is_dir($destPath = $input->getArgument('dest-path'))) { - mkdir($destPath, 0775, true); - } - $destPath = realpath($destPath); - - if ( ! file_exists($destPath)) { - throw new \InvalidArgumentException( - sprintf("Mapping destination directory '%s' does not exist.", $input->getArgument('dest-path')) - ); - } - - if ( ! is_writable($destPath)) { - throw new \InvalidArgumentException( - sprintf("Mapping destination directory '%s' does not have write permissions.", $destPath) - ); - } - - $toType = strtolower($input->getArgument('to-type')); - - $exporter = $this->getExporter($toType, $destPath); - $exporter->setOverwriteExistingFiles($input->getOption('force')); - - if ($toType == 'annotation') { - $entityGenerator = new EntityGenerator(); - $exporter->setEntityGenerator($entityGenerator); - - $entityGenerator->setNumSpaces($input->getOption('num-spaces')); - - if (($extend = $input->getOption('extend')) !== null) { - $entityGenerator->setClassToExtend($extend); - } - } - - if (empty($metadata)) { - $ui->success('No Metadata Classes to process.'); - return; - } - - foreach ($metadata as $class) { - $ui->text(sprintf('Processing entity "%s"', $class->name)); - } - - $exporter->setMetadata($metadata); - $exporter->export(); - - $ui->newLine(); - $ui->text( - sprintf( - 'Exporting "%s" mapping information to "%s"', - $toType, - $destPath - ) - ); - - return 0; - } - - /** - * @param string $toType - * @param string $destPath - * - * @return \Doctrine\ORM\Tools\Export\Driver\AbstractExporter - */ - protected function getExporter($toType, $destPath) - { - $cme = new ClassMetadataExporter(); - - return $cme->getExporter($toType, $destPath); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php deleted file mode 100644 index eb0ff17..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php +++ /dev/null @@ -1,78 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Throwable; - -/** - * Command to ensure that Doctrine is properly configured for a production environment. - * - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class EnsureProductionSettingsCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:ensure-production-settings') - ->setDescription('Verify that Doctrine is properly configured for a production environment') - ->addOption('complete', null, InputOption::VALUE_NONE, 'Flag to also inspect database connection existence.') - ->setHelp('Verify that Doctrine is properly configured for a production environment.'); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - $em = $this->getHelper('em')->getEntityManager(); - - try { - $em->getConfiguration()->ensureProductionSettings(); - - if ($input->getOption('complete') !== null) { - $em->getConnection()->connect(); - } - } catch (Throwable $e) { - $ui->error($e->getMessage()); - - return 1; - } - - $ui->success('Environment is correctly configured for production.'); - - return 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php deleted file mode 100644 index f1bba22..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateEntitiesCommand.php +++ /dev/null @@ -1,147 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command; - -use Doctrine\ORM\Tools\Console\MetadataFilter; -use Doctrine\ORM\Tools\DisconnectedClassMetadataFactory; -use Doctrine\ORM\Tools\EntityGenerator; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to generate entity classes and method stubs from your mapping information. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class GenerateEntitiesCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:generate-entities') - ->setAliases(['orm:generate:entities']) - ->setDescription('Generate entity classes and method stubs from your mapping information') - ->addArgument('dest-path', InputArgument::REQUIRED, 'The path to generate your entity classes.') - ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be processed.') - ->addOption('generate-annotations', null, InputOption::VALUE_OPTIONAL, 'Flag to define if generator should generate annotation metadata on entities.', false) - ->addOption('generate-methods', null, InputOption::VALUE_OPTIONAL, 'Flag to define if generator should generate stub methods on entities.', true) - ->addOption('regenerate-entities', null, InputOption::VALUE_OPTIONAL, 'Flag to define if generator should regenerate entity if it exists.', false) - ->addOption('update-entities', null, InputOption::VALUE_OPTIONAL, 'Flag to define if generator should only update entity if it exists.', true) - ->addOption('extend', null, InputOption::VALUE_REQUIRED, 'Defines a base class to be extended by generated entity classes.') - ->addOption('num-spaces', null, InputOption::VALUE_REQUIRED, 'Defines the number of indentation spaces', 4) - ->addOption('no-backup', null, InputOption::VALUE_NONE, 'Flag to define if generator should avoid backuping existing entity file if it exists.') - ->setHelp(<<--update-entities or --regenerate-entities flags your existing -code gets overwritten. The EntityGenerator will only append new code to your -file and will not delete the old code. However this approach may still be prone -to error and we suggest you use code repositories such as GIT or SVN to make -backups of your code. - -It makes sense to generate the entity code if you are using entities as Data -Access Objects only and don't put much additional logic on them. If you are -however putting much more logic on the entities you should refrain from using -the entity-generator and code your entities manually. - -Important: Even if you specified Inheritance options in your -XML or YAML Mapping files the generator cannot generate the base and -child classes for you correctly, because it doesn't know which -class is supposed to extend which. You have to adjust the entity -code manually for inheritance to work! -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - $ui->warning('Command ' . $this->getName() . ' is deprecated and will be removed in Doctrine ORM 3.0.'); - - $em = $this->getHelper('em')->getEntityManager(); - - $cmf = new DisconnectedClassMetadataFactory(); - $cmf->setEntityManager($em); - $metadatas = $cmf->getAllMetadata(); - $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter')); - - // Process destination directory - $destPath = realpath($input->getArgument('dest-path')); - - if ( ! file_exists($destPath)) { - throw new \InvalidArgumentException( - sprintf("Entities destination directory '%s' does not exist.", $input->getArgument('dest-path')) - ); - } - - if ( ! is_writable($destPath)) { - throw new \InvalidArgumentException( - sprintf("Entities destination directory '%s' does not have write permissions.", $destPath) - ); - } - - if (empty($metadatas)) { - $ui->success('No Metadata Classes to process.'); - return 0; - } - - $entityGenerator = new EntityGenerator(); - - $entityGenerator->setGenerateAnnotations($input->getOption('generate-annotations')); - $entityGenerator->setGenerateStubMethods($input->getOption('generate-methods')); - $entityGenerator->setRegenerateEntityIfExists($input->getOption('regenerate-entities')); - $entityGenerator->setUpdateEntityIfExists($input->getOption('update-entities')); - $entityGenerator->setNumSpaces($input->getOption('num-spaces')); - $entityGenerator->setBackupExisting(!$input->getOption('no-backup')); - - if (($extend = $input->getOption('extend')) !== null) { - $entityGenerator->setClassToExtend($extend); - } - - foreach ($metadatas as $metadata) { - $ui->text(sprintf('Processing entity "%s"', $metadata->name)); - } - - // Generating Entities - $entityGenerator->generate($metadatas, $destPath); - - // Outputting information message - $ui->newLine(); - $ui->success(sprintf('Entity classes generated to "%s"', $destPath)); - - return 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php deleted file mode 100644 index 2cace34..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php +++ /dev/null @@ -1,110 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command; - -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Tools\Console\MetadataFilter; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to (re)generate the proxy classes used by doctrine. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class GenerateProxiesCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:generate-proxies') - ->setAliases(['orm:generate:proxies']) - ->setDescription('Generates proxy classes for entity classes') - ->addArgument('dest-path', InputArgument::OPTIONAL, 'The path to generate your proxy classes. If none is provided, it will attempt to grab from configuration.') - ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be processed.') - ->setHelp('Generates proxy classes for entity classes.'); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - /** @var EntityManagerInterface $em */ - $em = $this->getHelper('em')->getEntityManager(); - - $metadatas = $em->getMetadataFactory()->getAllMetadata(); - $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter')); - - // Process destination directory - if (($destPath = $input->getArgument('dest-path')) === null) { - $destPath = $em->getConfiguration()->getProxyDir(); - } - - if ( ! is_dir($destPath)) { - mkdir($destPath, 0775, true); - } - - $destPath = realpath($destPath); - - if ( ! file_exists($destPath)) { - throw new \InvalidArgumentException( - sprintf("Proxies destination directory '%s' does not exist.", $em->getConfiguration()->getProxyDir()) - ); - } - - if ( ! is_writable($destPath)) { - throw new \InvalidArgumentException( - sprintf("Proxies destination directory '%s' does not have write permissions.", $destPath) - ); - } - - if (empty($metadatas)) { - $ui->success('No Metadata Classes to process.'); - return 0; - } - - foreach ($metadatas as $metadata) { - $ui->text(sprintf('Processing entity "%s"', $metadata->name)); - } - - // Generating Proxies - $em->getProxyFactory()->generateProxyClasses($metadatas, $destPath); - - // Outputting information message - $ui->newLine(); - $ui->text(sprintf('Proxy classes generated to "%s"', $destPath)); - - return 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php deleted file mode 100644 index 379c935..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/GenerateRepositoriesCommand.php +++ /dev/null @@ -1,119 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command; - -use Doctrine\ORM\Tools\Console\MetadataFilter; -use Doctrine\ORM\Tools\EntityRepositoryGenerator; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to generate repository classes for mapping information. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class GenerateRepositoriesCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:generate-repositories') - ->setAliases(['orm:generate:repositories']) - ->setDescription('Generate repository classes from your mapping information') - ->addArgument('dest-path', InputArgument::REQUIRED, 'The path to generate your repository classes.') - ->addOption('filter', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A string pattern used to match entities that should be processed.') - ->setHelp('Generate repository classes from your mapping information.'); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - $ui->warning('Command ' . $this->getName() . ' is deprecated and will be removed in Doctrine ORM 3.0.'); - - $em = $this->getHelper('em')->getEntityManager(); - - $metadatas = $em->getMetadataFactory()->getAllMetadata(); - $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter')); - - $repositoryName = $em->getConfiguration()->getDefaultRepositoryClassName(); - - // Process destination directory - $destPath = realpath($input->getArgument('dest-path')); - - if ( ! file_exists($destPath)) { - throw new \InvalidArgumentException( - sprintf("Entities destination directory '%s' does not exist.", $input->getArgument('dest-path')) - ); - } - - if ( ! is_writable($destPath)) { - throw new \InvalidArgumentException( - sprintf("Entities destination directory '%s' does not have write permissions.", $destPath) - ); - } - - if (empty($metadatas)) { - $ui->success('No Metadata Classes to process.'); - return 0; - } - - $numRepositories = 0; - $generator = new EntityRepositoryGenerator(); - - $generator->setDefaultRepositoryName($repositoryName); - - foreach ($metadatas as $metadata) { - if ($metadata->customRepositoryClassName) { - $ui->text(sprintf('Processing repository "%s"', $metadata->customRepositoryClassName)); - - $generator->writeEntityRepositoryClass($metadata->customRepositoryClassName, $destPath); - - ++$numRepositories; - } - } - - if ($numRepositories === 0) { - $ui->text('No Repository classes were found to be processed.'); - return 0; - } - - // Outputting information message - $ui->newLine(); - $ui->text(sprintf('Repository classes generated to "%s"', $destPath)); - - return 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php deleted file mode 100644 index 89f6c31..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/InfoCommand.php +++ /dev/null @@ -1,101 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command; - -use Doctrine\ORM\Mapping\MappingException; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Show information about mapped entities. - * - * @link www.doctrine-project.org - * @since 2.1 - * @author Benjamin Eberlei - */ -class InfoCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:info') - ->setDescription('Show basic information about all mapped entities') - ->setHelp(<<%command.name% shows basic information about which -entities exist and possibly if their mapping information contains errors or -not. -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - /* @var $entityManager \Doctrine\ORM\EntityManager */ - $entityManager = $this->getHelper('em')->getEntityManager(); - - $entityClassNames = $entityManager->getConfiguration() - ->getMetadataDriverImpl() - ->getAllClassNames(); - - if ( ! $entityClassNames) { - $ui->caution( - [ - 'You do not have any mapped Doctrine ORM entities according to the current configuration.', - 'If you have entities or mapping files you should check your mapping configuration for errors.' - ] - ); - - return 1; - } - - $ui->text(sprintf("Found %d mapped entities:", count($entityClassNames))); - $ui->newLine(); - - $failure = false; - - foreach ($entityClassNames as $entityClassName) { - try { - $entityManager->getClassMetadata($entityClassName); - $ui->text(sprintf("[OK] %s", $entityClassName)); - } catch (MappingException $e) { - $ui->text( - [ - sprintf("[FAIL] %s", $entityClassName), - sprintf("%s", $e->getMessage()), - '' - ] - ); - - $failure = true; - } - } - - return $failure ? 1 : 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php deleted file mode 100644 index 0e1f505..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ /dev/null @@ -1,284 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command; - -use Doctrine\Common\Persistence\Mapping\MappingException; -use Doctrine\ORM\EntityManagerInterface; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use const JSON_PRETTY_PRINT; -use const JSON_UNESCAPED_SLASHES; -use const JSON_UNESCAPED_UNICODE; -use function json_encode; - -/** - * Show information about mapped entities. - * - * @link www.doctrine-project.org - * @since 2.4 - * @author Daniel Leech - */ -final class MappingDescribeCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:mapping:describe') - ->addArgument('entityName', InputArgument::REQUIRED, 'Full or partial name of entity') - ->setDescription('Display information about mapped objects') - ->setHelp(<<%command.full_name% My\Namespace\Entity\MyEntity - -Or: - - %command.full_name% MyEntity -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - /* @var $entityManager \Doctrine\ORM\EntityManagerInterface */ - $entityManager = $this->getHelper('em')->getEntityManager(); - - $this->displayEntity($input->getArgument('entityName'), $entityManager, $ui); - - return 0; - } - - /** - * Display all the mapping information for a single Entity. - * - * @param string $entityName Full or partial entity class name - * @param EntityManagerInterface $entityManager - * @param SymfonyStyle $ui - */ - private function displayEntity($entityName, EntityManagerInterface $entityManager, SymfonyStyle $ui) - { - $metadata = $this->getClassMetadata($entityName, $entityManager); - - $ui->table( - ['Field', 'Value'], - array_merge( - [ - $this->formatField('Name', $metadata->name), - $this->formatField('Root entity name', $metadata->rootEntityName), - $this->formatField('Custom generator definition', $metadata->customGeneratorDefinition), - $this->formatField('Custom repository class', $metadata->customRepositoryClassName), - $this->formatField('Mapped super class?', $metadata->isMappedSuperclass), - $this->formatField('Embedded class?', $metadata->isEmbeddedClass), - $this->formatField('Parent classes', $metadata->parentClasses), - $this->formatField('Sub classes', $metadata->subClasses), - $this->formatField('Embedded classes', $metadata->subClasses), - $this->formatField('Named queries', $metadata->namedQueries), - $this->formatField('Named native queries', $metadata->namedNativeQueries), - $this->formatField('SQL result set mappings', $metadata->sqlResultSetMappings), - $this->formatField('Identifier', $metadata->identifier), - $this->formatField('Inheritance type', $metadata->inheritanceType), - $this->formatField('Discriminator column', $metadata->discriminatorColumn), - $this->formatField('Discriminator value', $metadata->discriminatorValue), - $this->formatField('Discriminator map', $metadata->discriminatorMap), - $this->formatField('Generator type', $metadata->generatorType), - $this->formatField('Table', $metadata->table), - $this->formatField('Composite identifier?', $metadata->isIdentifierComposite), - $this->formatField('Foreign identifier?', $metadata->containsForeignIdentifier), - $this->formatField('Sequence generator definition', $metadata->sequenceGeneratorDefinition), - $this->formatField('Table generator definition', $metadata->tableGeneratorDefinition), - $this->formatField('Change tracking policy', $metadata->changeTrackingPolicy), - $this->formatField('Versioned?', $metadata->isVersioned), - $this->formatField('Version field', $metadata->versionField), - $this->formatField('Read only?', $metadata->isReadOnly), - - $this->formatEntityListeners($metadata->entityListeners), - ], - [$this->formatField('Association mappings:', '')], - $this->formatMappings($metadata->associationMappings), - [$this->formatField('Field mappings:', '')], - $this->formatMappings($metadata->fieldMappings) - ) - ); - } - - /** - * Return all mapped entity class names - * - * @param EntityManagerInterface $entityManager - * - * @return string[] - */ - private function getMappedEntities(EntityManagerInterface $entityManager) - { - $entityClassNames = $entityManager->getConfiguration() - ->getMetadataDriverImpl() - ->getAllClassNames(); - - if ( ! $entityClassNames) { - throw new \InvalidArgumentException( - 'You do not have any mapped Doctrine ORM entities according to the current configuration. '. - 'If you have entities or mapping files you should check your mapping configuration for errors.' - ); - } - - return $entityClassNames; - } - - /** - * Return the class metadata for the given entity - * name - * - * @param string $entityName Full or partial entity name - * @param EntityManagerInterface $entityManager - * - * @return \Doctrine\ORM\Mapping\ClassMetadata - */ - private function getClassMetadata($entityName, EntityManagerInterface $entityManager) - { - try { - return $entityManager->getClassMetadata($entityName); - } catch (MappingException $e) { - } - - $matches = array_filter( - $this->getMappedEntities($entityManager), - function ($mappedEntity) use ($entityName) { - return preg_match('{' . preg_quote($entityName) . '}', $mappedEntity); - } - ); - - if ( ! $matches) { - throw new \InvalidArgumentException(sprintf( - 'Could not find any mapped Entity classes matching "%s"', - $entityName - )); - } - - if (count($matches) > 1) { - throw new \InvalidArgumentException(sprintf( - 'Entity name "%s" is ambiguous, possible matches: "%s"', - $entityName, implode(', ', $matches) - )); - } - - return $entityManager->getClassMetadata(current($matches)); - } - - /** - * Format the given value for console output - * - * @param mixed $value - * - * @return string - */ - private function formatValue($value) - { - if ('' === $value) { - return ''; - } - - if (null === $value) { - return 'Null'; - } - - if (is_bool($value)) { - return '' . ($value ? 'True' : 'False') . ''; - } - - if (empty($value)) { - return 'Empty'; - } - - if (is_array($value)) { - return json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT); - } - - if (is_object($value)) { - return sprintf('<%s>', get_class($value)); - } - - if (is_scalar($value)) { - return $value; - } - - throw new \InvalidArgumentException(sprintf('Do not know how to format value "%s"', print_r($value, true))); - } - - /** - * Add the given label and value to the two column table output - * - * @param string $label Label for the value - * @param mixed $value A Value to show - * - * @return array - */ - private function formatField($label, $value) - { - if (null === $value) { - $value = 'None'; - } - - return [sprintf('%s', $label), $this->formatValue($value)]; - } - - /** - * Format the association mappings - * - * @param array $propertyMappings - * - * @return array - */ - private function formatMappings(array $propertyMappings) - { - $output = []; - - foreach ($propertyMappings as $propertyName => $mapping) { - $output[] = $this->formatField(sprintf(' %s', $propertyName), ''); - - foreach ($mapping as $field => $value) { - $output[] = $this->formatField(sprintf(' %s', $field), $this->formatValue($value)); - } - } - - return $output; - } - - /** - * Format the entity listeners - * - * @param array $entityListeners - * - * @return array - */ - private function formatEntityListeners(array $entityListeners) - { - return $this->formatField('Entity listeners', array_map('get_class', $entityListeners)); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php deleted file mode 100644 index 7f40692..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/RunDqlCommand.php +++ /dev/null @@ -1,116 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command; - -use Doctrine\Common\Util\Debug; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to execute DQL queries in a given EntityManager. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class RunDqlCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:run-dql') - ->setDescription('Executes arbitrary DQL directly from the command line') - ->addArgument('dql', InputArgument::REQUIRED, 'The DQL to execute.') - ->addOption('hydrate', null, InputOption::VALUE_REQUIRED, 'Hydration mode of result set. Should be either: object, array, scalar or single-scalar.', 'object') - ->addOption('first-result', null, InputOption::VALUE_REQUIRED, 'The first result in the result set.') - ->addOption('max-result', null, InputOption::VALUE_REQUIRED, 'The maximum number of results in the result set.') - ->addOption('depth', null, InputOption::VALUE_REQUIRED, 'Dumping depth of Entity graph.', 7) - ->addOption('show-sql', null, InputOption::VALUE_NONE, 'Dump generated SQL instead of executing query') - ->setHelp('Executes arbitrary DQL directly from the command line.'); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - /* @var $em \Doctrine\ORM\EntityManagerInterface */ - $em = $this->getHelper('em')->getEntityManager(); - - if (($dql = $input->getArgument('dql')) === null) { - throw new \RuntimeException("Argument 'dql' is required in order to execute this command correctly."); - } - - $depth = $input->getOption('depth'); - - if ( ! is_numeric($depth)) { - throw new \LogicException("Option 'depth' must contain an integer value"); - } - - $hydrationModeName = $input->getOption('hydrate'); - $hydrationMode = 'Doctrine\ORM\Query::HYDRATE_' . strtoupper(str_replace('-', '_', $hydrationModeName)); - - if ( ! defined($hydrationMode)) { - throw new \RuntimeException( - "Hydration mode '$hydrationModeName' does not exist. It should be either: object. array, scalar or single-scalar." - ); - } - - $query = $em->createQuery($dql); - - if (($firstResult = $input->getOption('first-result')) !== null) { - if ( ! is_numeric($firstResult)) { - throw new \LogicException("Option 'first-result' must contain an integer value"); - } - - $query->setFirstResult((int) $firstResult); - } - - if (($maxResult = $input->getOption('max-result')) !== null) { - if ( ! is_numeric($maxResult)) { - throw new \LogicException("Option 'max-result' must contain an integer value"); - } - - $query->setMaxResults((int) $maxResult); - } - - if ($input->getOption('show-sql')) { - $ui->text($query->getSQL()); - return 0; - } - - $resultSet = $query->execute([], constant($hydrationMode)); - - $ui->text(Debug::dump($resultSet, $input->getOption('depth'), true, false)); - - return 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/AbstractCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/AbstractCommand.php deleted file mode 100644 index 21907d0..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/AbstractCommand.php +++ /dev/null @@ -1,72 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; - -use Doctrine\ORM\Tools\SchemaTool; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Base class for CreateCommand, DropCommand and UpdateCommand. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -abstract class AbstractCommand extends Command -{ - /** - * @param InputInterface $input - * @param OutputInterface $output - * @param SchemaTool $schemaTool - * @param array $metadatas - * - * @return null|int Null or 0 if everything went fine, or an error code. - */ - abstract protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui); - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - $emHelper = $this->getHelper('em'); - - /* @var $em \Doctrine\ORM\EntityManager */ - $em = $emHelper->getEntityManager(); - - $metadatas = $em->getMetadataFactory()->getAllMetadata(); - - if (empty($metadatas)) { - $ui->success('No Metadata Classes to process.'); - - return 0; - } - - return $this->executeSchemaCommand($input, $output, new SchemaTool($em), $metadatas, $ui); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php deleted file mode 100644 index 0c21374..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/CreateCommand.php +++ /dev/null @@ -1,90 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; - -use Doctrine\ORM\Tools\SchemaTool; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to create the database schema for a set of classes based on their mappings. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class CreateCommand extends AbstractCommand -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:schema-tool:create') - ->setDescription('Processes the schema and either create it directly on EntityManager Storage Connection or generate the SQL output') - ->addOption('dump-sql', null, InputOption::VALUE_NONE, 'Instead of trying to apply generated SQLs into EntityManager Storage Connection, output them.') - ->setHelp(<<Hint: If you have a database with tables that should not be managed -by the ORM, you can use a DBAL functionality to filter the tables and sequences down -on a global level: - - \$config->setFilterSchemaAssetsExpression(\$regexp); -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui) - { - $dumpSql = true === $input->getOption('dump-sql'); - - if ($dumpSql) { - $sqls = $schemaTool->getCreateSchemaSql($metadatas); - $ui->text('The following SQL statements will be executed:'); - $ui->newLine(); - - foreach ($sqls as $sql) { - $ui->text(sprintf(' %s;', $sql)); - } - - return 0; - } - - $ui->caution('This operation should not be executed in a production environment!'); - - $ui->text('Creating database schema...'); - $ui->newLine(); - - $schemaTool->createSchema($metadatas); - - $ui->success('Database schema created successfully!'); - - return 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php deleted file mode 100644 index 3d77fc8..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/DropCommand.php +++ /dev/null @@ -1,130 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; - -use Doctrine\ORM\Tools\SchemaTool; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to drop the database schema for a set of classes based on their mappings. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class DropCommand extends AbstractCommand -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:schema-tool:drop') - ->setDescription('Drop the complete database schema of EntityManager Storage Connection or generate the corresponding SQL output') - ->addOption('dump-sql', null, InputOption::VALUE_NONE, 'Instead of trying to apply generated SQLs into EntityManager Storage Connection, output them.') - ->addOption('force', 'f', InputOption::VALUE_NONE, "Don't ask for the deletion of the database, but force the operation to run.") - ->addOption('full-database', null, InputOption::VALUE_NONE, 'Instead of using the Class Metadata to detect the database table schema, drop ALL assets that the database contains.') - ->setHelp(<<Hint: If you have a database with tables that should not be managed -by the ORM, you can use a DBAL functionality to filter the tables and sequences down -on a global level: - - \$config->setFilterSchemaAssetsExpression(\$regexp); -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui) - { - $isFullDatabaseDrop = $input->getOption('full-database'); - $dumpSql = true === $input->getOption('dump-sql'); - $force = true === $input->getOption('force'); - - if ($dumpSql) { - if ($isFullDatabaseDrop) { - $sqls = $schemaTool->getDropDatabaseSQL(); - } else { - $sqls = $schemaTool->getDropSchemaSQL($metadatas); - } - $ui->text('The following SQL statements will be executed:'); - $ui->newLine(); - - foreach ($sqls as $sql) { - $ui->text(sprintf(' %s;', $sql)); - } - - return 0; - } - - if ($force) { - $ui->text('Dropping database schema...'); - $ui->newLine(); - - if ($isFullDatabaseDrop) { - $schemaTool->dropDatabase(); - } else { - $schemaTool->dropSchema($metadatas); - } - - $ui->success('Database schema dropped successfully!'); - - return 0; - } - - $ui->caution('This operation should not be executed in a production environment!'); - - if ($isFullDatabaseDrop) { - $sqls = $schemaTool->getDropDatabaseSQL(); - } else { - $sqls = $schemaTool->getDropSchemaSQL($metadatas); - } - - if (empty($sqls)) { - $ui->success('Nothing to drop. The database is empty!'); - - return 0; - } - - $ui->text( - [ - sprintf('The Schema-Tool would execute "%s" queries to update the database.', count($sqls)), - '', - 'Please run the operation by passing one - or both - of the following options:', - '', - sprintf(' %s --force to execute the command', $this->getName()), - sprintf(' %s --dump-sql to dump the SQL statements to the screen', $this->getName()), - ] - ); - - return 1; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php deleted file mode 100644 index c905977..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/SchemaTool/UpdateCommand.php +++ /dev/null @@ -1,159 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command\SchemaTool; - -use Doctrine\ORM\Tools\SchemaTool; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to generate the SQL needed to update the database schema to match - * the current mapping information. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Ryan Weaver - */ -class UpdateCommand extends AbstractCommand -{ - /** - * @var string - */ - protected $name = 'orm:schema-tool:update'; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName($this->name) - ->setDescription('Executes (or dumps) the SQL needed to update the database schema to match the current mapping metadata') - ->addOption('complete', null, InputOption::VALUE_NONE, 'If defined, all assets of the database which are not relevant to the current metadata will be dropped.') - ->addOption('dump-sql', null, InputOption::VALUE_NONE, 'Dumps the generated SQL statements to the screen (does not execute them).') - ->addOption('force', 'f', InputOption::VALUE_NONE, 'Causes the generated SQL statements to be physically executed against your database.') - ->setHelp(<<%command.name% command generates the SQL needed to -synchronize the database schema with the current mapping metadata of the -default entity manager. - -For example, if you add metadata for a new column to an entity, this command -would generate and output the SQL needed to add the new column to the database: - -%command.name% --dump-sql - -Alternatively, you can execute the generated queries: - -%command.name% --force - -If both options are specified, the queries are output and then executed: - -%command.name% --dump-sql --force - -Finally, be aware that if the --complete option is passed, this -task will drop all database assets (e.g. tables, etc) that are *not* described -by the current metadata. In other words, without this option, this task leaves -untouched any "extra" tables that exist in the database, but which aren't -described by any metadata. - -Hint: If you have a database with tables that should not be managed -by the ORM, you can use a DBAL functionality to filter the tables and sequences down -on a global level: - - \$config->setFilterSchemaAssetsExpression(\$regexp); -EOT - ); - } - - /** - * {@inheritdoc} - */ - protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui) - { - // Defining if update is complete or not (--complete not defined means $saveMode = true) - $saveMode = ! $input->getOption('complete'); - - $sqls = $schemaTool->getUpdateSchemaSql($metadatas, $saveMode); - - if (empty($sqls)) { - $ui->success('Nothing to update - your database is already in sync with the current entity metadata.'); - - return 0; - } - - $dumpSql = true === $input->getOption('dump-sql'); - $force = true === $input->getOption('force'); - - if ($dumpSql) { - $ui->text('The following SQL statements will be executed:'); - $ui->newLine(); - - foreach ($sqls as $sql) { - $ui->text(sprintf(' %s;', $sql)); - } - } - - if ($force) { - if ($dumpSql) { - $ui->newLine(); - } - $ui->text('Updating database schema...'); - $ui->newLine(); - - $schemaTool->updateSchema($metadatas, $saveMode); - - $pluralization = (1 === count($sqls)) ? 'query was' : 'queries were'; - - $ui->text(sprintf(' %s %s executed', count($sqls), $pluralization)); - $ui->success('Database schema updated successfully!'); - } - - if ($dumpSql || $force) { - return 0; - } - - $ui->caution( - [ - 'This operation should not be executed in a production environment!', - '', - 'Use the incremental update to detect changes during development and use', - 'the SQL DDL provided to manually update your database in production.', - ] - ); - - $ui->text( - [ - sprintf('The Schema-Tool would execute "%s" queries to update the database.', count($sqls)), - '', - 'Please run the operation by passing one - or both - of the following options:', - '', - sprintf(' %s --force to execute the command', $this->getName()), - sprintf(' %s --dump-sql to dump the SQL statements to the screen', $this->getName()), - ] - ); - - return 1; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ValidateSchemaCommand.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ValidateSchemaCommand.php deleted file mode 100644 index 343d3b5..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/Command/ValidateSchemaCommand.php +++ /dev/null @@ -1,100 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console\Command; - -use Doctrine\ORM\Tools\SchemaValidator; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Command to validate that the current mapping is valid. - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.com - * @since 1.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ValidateSchemaCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->setName('orm:validate-schema') - ->setDescription('Validate the mapping files') - ->addOption('skip-mapping', null, InputOption::VALUE_NONE, 'Skip the mapping validation check') - ->addOption('skip-sync', null, InputOption::VALUE_NONE, 'Skip checking if the mapping is in sync with the database') - ->setHelp('Validate that the mapping files are correct and in sync with the database.'); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $ui = new SymfonyStyle($input, $output); - - $em = $this->getHelper('em')->getEntityManager(); - $validator = new SchemaValidator($em); - $exit = 0; - - $ui->section('Mapping'); - - if ($input->getOption('skip-mapping')) { - $ui->text('[SKIPPED] The mapping was not checked.'); - } elseif ($errors = $validator->validateMapping()) { - foreach ($errors as $className => $errorMessages) { - $ui->text( - sprintf( - '[FAIL] The entity-class %s mapping is invalid:', - $className - ) - ); - - $ui->listing($errorMessages); - $ui->newLine(); - } - - ++$exit; - } else { - $ui->success('The mapping files are correct.'); - } - - $ui->section('Database'); - - if ($input->getOption('skip-sync')) { - $ui->text('[SKIPPED] The database was not checked for synchronicity.'); - } elseif ( ! $validator->schemaInSyncWithMetadata()) { - $ui->error('The database schema is not in sync with the current mapping file.'); - $exit += 2; - } else { - $ui->success('The database schema is in sync with the mapping files.'); - } - - return $exit; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php deleted file mode 100644 index c6a265c..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/ConsoleRunner.php +++ /dev/null @@ -1,143 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console; - -use Doctrine\DBAL\Tools\Console as DBALConsole; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper; -use Doctrine\ORM\Version; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Helper\HelperSet; - -/** - * Handles running the Console Tools inside Symfony Console context. - */ -final class ConsoleRunner -{ - /** - * Create a Symfony Console HelperSet - * - * @param EntityManagerInterface $entityManager - * - * @return HelperSet - */ - public static function createHelperSet(EntityManagerInterface $entityManager) : HelperSet - { - return new HelperSet( - [ - 'db' => new DBALConsole\Helper\ConnectionHelper($entityManager->getConnection()), - 'em' => new EntityManagerHelper($entityManager), - ] - ); - } - - /** - * Runs console with the given helper set. - * - * @param \Symfony\Component\Console\Helper\HelperSet $helperSet - * @param \Symfony\Component\Console\Command\Command[] $commands - * - * @return void - */ - public static function run(HelperSet $helperSet, array $commands = []) : void - { - $cli = self::createApplication($helperSet, $commands); - $cli->run(); - } - - /** - * Creates a console application with the given helperset and - * optional commands. - * - * @param \Symfony\Component\Console\Helper\HelperSet $helperSet - * @param array $commands - * - * @return \Symfony\Component\Console\Application - */ - public static function createApplication(HelperSet $helperSet, array $commands = []) : Application - { - $cli = new Application('Doctrine Command Line Interface', Version::VERSION); - $cli->setCatchExceptions(true); - $cli->setHelperSet($helperSet); - self::addCommands($cli); - $cli->addCommands($commands); - - return $cli; - } - - /** - * @param Application $cli - * - * @return void - */ - public static function addCommands(Application $cli) : void - { - $cli->addCommands( - [ - // DBAL Commands - new DBALConsole\Command\ImportCommand(), - new DBALConsole\Command\ReservedWordsCommand(), - new DBALConsole\Command\RunSqlCommand(), - - // ORM Commands - new Command\ClearCache\CollectionRegionCommand(), - new Command\ClearCache\EntityRegionCommand(), - new Command\ClearCache\MetadataCommand(), - new Command\ClearCache\QueryCommand(), - new Command\ClearCache\QueryRegionCommand(), - new Command\ClearCache\ResultCommand(), - new Command\SchemaTool\CreateCommand(), - new Command\SchemaTool\UpdateCommand(), - new Command\SchemaTool\DropCommand(), - new Command\EnsureProductionSettingsCommand(), - new Command\ConvertDoctrine1SchemaCommand(), - new Command\GenerateRepositoriesCommand(), - new Command\GenerateEntitiesCommand(), - new Command\GenerateProxiesCommand(), - new Command\ConvertMappingCommand(), - new Command\RunDqlCommand(), - new Command\ValidateSchemaCommand(), - new Command\InfoCommand(), - new Command\MappingDescribeCommand(), - ] - ); - } - - public static function printCliConfigTemplate() : void - { - echo <<<'HELP' -You are missing a "cli-config.php" or "config/cli-config.php" file in your -project, which is required to get the Doctrine Console working. You can use the -following sample as a template: - -. - */ - -namespace Doctrine\ORM\Tools\Console\Helper; - -use Doctrine\ORM\EntityManagerInterface; -use Symfony\Component\Console\Helper\Helper; - -/** - * Doctrine CLI Connection Helper. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class EntityManagerHelper extends Helper -{ - /** - * Doctrine ORM EntityManagerInterface. - * - * @var EntityManagerInterface - */ - protected $_em; - - /** - * Constructor. - * - * @param EntityManagerInterface $em - */ - public function __construct(EntityManagerInterface $em) - { - $this->_em = $em; - } - - /** - * Retrieves Doctrine ORM EntityManager. - * - * @return EntityManagerInterface - */ - public function getEntityManager() - { - return $this->_em; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'entityManager'; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/MetadataFilter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/MetadataFilter.php deleted file mode 100644 index 88357e3..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Console/MetadataFilter.php +++ /dev/null @@ -1,102 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Console; - -/** - * Used by CLI Tools to restrict entity-based commands to given patterns. - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.com - * @since 1.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class MetadataFilter extends \FilterIterator implements \Countable -{ - /** - * @var array - */ - private $filter = []; - - /** - * Filter Metadatas by one or more filter options. - * - * @param array $metadatas - * @param array|string $filter - * - * @return array - */ - static public function filter(array $metadatas, $filter) - { - $metadatas = new MetadataFilter(new \ArrayIterator($metadatas), $filter); - - return iterator_to_array($metadatas); - } - - /** - * @param \ArrayIterator $metadata - * @param array|string $filter - */ - public function __construct(\ArrayIterator $metadata, $filter) - { - $this->filter = (array) $filter; - - parent::__construct($metadata); - } - - /** - * @return bool - */ - public function accept() - { - if (count($this->filter) == 0) { - return true; - } - - $it = $this->getInnerIterator(); - $metadata = $it->current(); - - foreach ($this->filter as $filter) { - $pregResult = preg_match("/$filter/", $metadata->name); - - if ($pregResult === false) { - throw new \RuntimeException( - sprintf("Error while evaluating regex '/%s/'.", $filter) - ); - } - - if ($pregResult) { - return true; - } - } - - return false; - } - - /** - * @return int - */ - public function count() - { - return count($this->getInnerIterator()); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php deleted file mode 100644 index 41a103d..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ConvertDoctrine1Schema.php +++ /dev/null @@ -1,344 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools; - -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\Common\Inflector\Inflector; -use Doctrine\DBAL\Types\Type; -use Symfony\Component\Yaml\Yaml; - -/** - * Class to help with converting Doctrine 1 schema files to Doctrine 2 mapping files - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class ConvertDoctrine1Schema -{ - /** - * @var array - */ - private $from; - - /** - * @var array - */ - private $legacyTypeMap = [ - // TODO: This list may need to be updated - 'clob' => 'text', - 'timestamp' => 'datetime', - 'enum' => 'string' - ]; - - /** - * Constructor passes the directory or array of directories - * to convert the Doctrine 1 schema files from. - * - * @param array $from - * - * @author Jonathan Wage - */ - public function __construct($from) - { - $this->from = (array) $from; - } - - /** - * Gets an array of ClassMetadataInfo instances from the passed - * Doctrine 1 schema. - * - * @return array An array of ClassMetadataInfo instances - */ - public function getMetadata() - { - $schema = []; - foreach ($this->from as $path) { - if (is_dir($path)) { - $files = glob($path . '/*.yml'); - foreach ($files as $file) { - $schema = array_merge($schema, (array) Yaml::parse(file_get_contents($file))); - } - } else { - $schema = array_merge($schema, (array) Yaml::parse(file_get_contents($path))); - } - } - - $metadatas = []; - foreach ($schema as $className => $mappingInformation) { - $metadatas[] = $this->convertToClassMetadataInfo($className, $mappingInformation); - } - - return $metadatas; - } - - /** - * @param string $className - * @param array $mappingInformation - * - * @return \Doctrine\ORM\Mapping\ClassMetadataInfo - */ - private function convertToClassMetadataInfo($className, $mappingInformation) - { - $metadata = new ClassMetadataInfo($className); - - $this->convertTableName($className, $mappingInformation, $metadata); - $this->convertColumns($className, $mappingInformation, $metadata); - $this->convertIndexes($className, $mappingInformation, $metadata); - $this->convertRelations($className, $mappingInformation, $metadata); - - return $metadata; - } - - /** - * @param string $className - * @param array $model - * @param ClassMetadataInfo $metadata - * - * @return void - */ - private function convertTableName($className, array $model, ClassMetadataInfo $metadata) - { - if (isset($model['tableName']) && $model['tableName']) { - $e = explode('.', $model['tableName']); - - if (count($e) > 1) { - $metadata->table['schema'] = $e[0]; - $metadata->table['name'] = $e[1]; - } else { - $metadata->table['name'] = $e[0]; - } - } - } - - /** - * @param string $className - * @param array $model - * @param ClassMetadataInfo $metadata - * - * @return void - */ - private function convertColumns($className, array $model, ClassMetadataInfo $metadata) - { - $id = false; - - if (isset($model['columns']) && $model['columns']) { - foreach ($model['columns'] as $name => $column) { - $fieldMapping = $this->convertColumn($className, $name, $column, $metadata); - - if (isset($fieldMapping['id']) && $fieldMapping['id']) { - $id = true; - } - } - } - - if ( ! $id) { - $fieldMapping = [ - 'fieldName' => 'id', - 'columnName' => 'id', - 'type' => 'integer', - 'id' => true - ]; - $metadata->mapField($fieldMapping); - $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); - } - } - - /** - * @param string $className - * @param string $name - * @param string|array $column - * @param ClassMetadataInfo $metadata - * - * @return array - * - * @throws ToolsException - */ - private function convertColumn($className, $name, $column, ClassMetadataInfo $metadata) - { - if (is_string($column)) { - $string = $column; - $column = []; - $column['type'] = $string; - } - - if ( ! isset($column['name'])) { - $column['name'] = $name; - } - - // check if a column alias was used (column_name as field_name) - if (preg_match("/(\w+)\sas\s(\w+)/i", $column['name'], $matches)) { - $name = $matches[1]; - $column['name'] = $name; - $column['alias'] = $matches[2]; - } - - if (preg_match("/([a-zA-Z]+)\(([0-9]+)\)/", $column['type'], $matches)) { - $column['type'] = $matches[1]; - $column['length'] = $matches[2]; - } - - $column['type'] = strtolower($column['type']); - // check if legacy column type (1.x) needs to be mapped to a 2.0 one - if (isset($this->legacyTypeMap[$column['type']])) { - $column['type'] = $this->legacyTypeMap[$column['type']]; - } - - if ( ! Type::hasType($column['type'])) { - throw ToolsException::couldNotMapDoctrine1Type($column['type']); - } - - $fieldMapping = []; - - if (isset($column['primary'])) { - $fieldMapping['id'] = true; - } - - $fieldMapping['fieldName'] = $column['alias'] ?? $name; - $fieldMapping['columnName'] = $column['name']; - $fieldMapping['type'] = $column['type']; - - if (isset($column['length'])) { - $fieldMapping['length'] = $column['length']; - } - - $allowed = ['precision', 'scale', 'unique', 'options', 'notnull', 'version']; - - foreach ($column as $key => $value) { - if (in_array($key, $allowed)) { - $fieldMapping[$key] = $value; - } - } - - $metadata->mapField($fieldMapping); - - if (isset($column['autoincrement'])) { - $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); - } elseif (isset($column['sequence'])) { - $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE); - - $definition = [ - 'sequenceName' => is_array($column['sequence']) ? $column['sequence']['name']:$column['sequence'] - ]; - - if (isset($column['sequence']['size'])) { - $definition['allocationSize'] = $column['sequence']['size']; - } - - if (isset($column['sequence']['value'])) { - $definition['initialValue'] = $column['sequence']['value']; - } - - $metadata->setSequenceGeneratorDefinition($definition); - } - - return $fieldMapping; - } - - /** - * @param string $className - * @param array $model - * @param ClassMetadataInfo $metadata - * - * @return void - */ - private function convertIndexes($className, array $model, ClassMetadataInfo $metadata) - { - if (empty($model['indexes'])) { - return; - } - - foreach ($model['indexes'] as $name => $index) { - $type = (isset($index['type']) && $index['type'] == 'unique') - ? 'uniqueConstraints' : 'indexes'; - - $metadata->table[$type][$name] = [ - 'columns' => $index['fields'] - ]; - } - } - - /** - * @param string $className - * @param array $model - * @param ClassMetadataInfo $metadata - * - * @return void - */ - private function convertRelations($className, array $model, ClassMetadataInfo $metadata) - { - if (empty($model['relations'])) { - return; - } - - foreach ($model['relations'] as $name => $relation) { - if ( ! isset($relation['alias'])) { - $relation['alias'] = $name; - } - if ( ! isset($relation['class'])) { - $relation['class'] = $name; - } - if ( ! isset($relation['local'])) { - $relation['local'] = Inflector::tableize($relation['class']); - } - if ( ! isset($relation['foreign'])) { - $relation['foreign'] = 'id'; - } - if ( ! isset($relation['foreignAlias'])) { - $relation['foreignAlias'] = $className; - } - - if (isset($relation['refClass'])) { - $type = 'many'; - $foreignType = 'many'; - $joinColumns = []; - } else { - $type = $relation['type'] ?? 'one'; - $foreignType = $relation['foreignType'] ?? 'many'; - $joinColumns = [ - [ - 'name' => $relation['local'], - 'referencedColumnName' => $relation['foreign'], - 'onDelete' => $relation['onDelete'] ?? null, - ] - ]; - } - - if ($type == 'one' && $foreignType == 'one') { - $method = 'mapOneToOne'; - } elseif ($type == 'many' && $foreignType == 'many') { - $method = 'mapManyToMany'; - } else { - $method = 'mapOneToMany'; - } - - $associationMapping = []; - $associationMapping['fieldName'] = $relation['alias']; - $associationMapping['targetEntity'] = $relation['class']; - $associationMapping['mappedBy'] = $relation['foreignAlias']; - $associationMapping['joinColumns'] = $joinColumns; - - $metadata->$method($associationMapping); - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DebugUnitOfWorkListener.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DebugUnitOfWorkListener.php deleted file mode 100644 index 5011382..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DebugUnitOfWorkListener.php +++ /dev/null @@ -1,185 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools; - -use Doctrine\Common\Persistence\Proxy; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Event\OnFlushEventArgs; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\PersistentCollection; -use Doctrine\ORM\UnitOfWork; - -/** - * Use this logger to dump the identity map during the onFlush event. This is useful for debugging - * weird UnitOfWork behavior with complex operations. - */ -class DebugUnitOfWorkListener -{ - /** - * @var string - */ - private $file; - - /** - * @var string - */ - private $context; - - /** - * Pass a stream and context information for the debugging session. - * - * The stream can be php://output to print to the screen. - * - * @param string $file - * @param string $context - */ - public function __construct($file = 'php://output', $context = '') - { - $this->file = $file; - $this->context = $context; - } - - /** - * @param \Doctrine\ORM\Event\OnFlushEventArgs $args - * - * @return void - */ - public function onFlush(OnFlushEventArgs $args) - { - $this->dumpIdentityMap($args->getEntityManager()); - } - - /** - * Dumps the contents of the identity map into a stream. - * - * @param EntityManagerInterface $em - * - * @return void - */ - public function dumpIdentityMap(EntityManagerInterface $em) - { - $uow = $em->getUnitOfWork(); - $identityMap = $uow->getIdentityMap(); - - $fh = fopen($this->file, 'xb+'); - if (count($identityMap) == 0) { - fwrite($fh, "Flush Operation [".$this->context."] - Empty identity map.\n"); - - return; - } - - fwrite($fh, "Flush Operation [".$this->context."] - Dumping identity map:\n"); - foreach ($identityMap as $className => $map) { - fwrite($fh, "Class: ". $className . "\n"); - - foreach ($map as $entity) { - fwrite($fh, " Entity: " . $this->getIdString($entity, $uow) . " " . spl_object_hash($entity)."\n"); - fwrite($fh, " Associations:\n"); - - $cm = $em->getClassMetadata($className); - - foreach ($cm->associationMappings as $field => $assoc) { - fwrite($fh, " " . $field . " "); - $value = $cm->getFieldValue($entity, $field); - - if ($assoc['type'] & ClassMetadata::TO_ONE) { - if ($value === null) { - fwrite($fh, " NULL\n"); - } else { - if ($value instanceof Proxy && !$value->__isInitialized()) { - fwrite($fh, "[PROXY] "); - } - - fwrite($fh, $this->getIdString($value, $uow) . " " . spl_object_hash($value) . "\n"); - } - } else { - $initialized = !($value instanceof PersistentCollection) || $value->isInitialized(); - if ($value === null) { - fwrite($fh, " NULL\n"); - } elseif ($initialized) { - fwrite($fh, "[INITIALIZED] " . $this->getType($value). " " . count($value) . " elements\n"); - - foreach ($value as $obj) { - fwrite($fh, " " . $this->getIdString($obj, $uow) . " " . spl_object_hash($obj)."\n"); - } - } else { - fwrite($fh, "[PROXY] " . $this->getType($value) . " unknown element size\n"); - foreach ($value->unwrap() as $obj) { - fwrite($fh, " " . $this->getIdString($obj, $uow) . " " . spl_object_hash($obj)."\n"); - } - } - } - } - } - } - - fclose($fh); - } - - /** - * @param mixed $var - * - * @return string - */ - private function getType($var) - { - if (is_object($var)) { - $refl = new \ReflectionObject($var); - - return $refl->getShortName(); - } - - return gettype($var); - } - - /** - * @param object $entity - * @param UnitOfWork $uow - * - * @return string - */ - private function getIdString($entity, UnitOfWork $uow) - { - if ($uow->isInIdentityMap($entity)) { - $ids = $uow->getEntityIdentifier($entity); - $idstring = ""; - - foreach ($ids as $k => $v) { - $idstring .= $k."=".$v; - } - } else { - $idstring = "NEWOBJECT "; - } - - $state = $uow->getEntityState($entity); - - if ($state == UnitOfWork::STATE_NEW) { - $idstring .= " [NEW]"; - } elseif ($state == UnitOfWork::STATE_REMOVED) { - $idstring .= " [REMOVED]"; - } elseif ($state == UnitOfWork::STATE_MANAGED) { - $idstring .= " [MANAGED]"; - } elseif ($state == UnitOfWork::STATE_DETACHED) { - $idstring .= " [DETACHED]"; - } - - return $idstring; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DisconnectedClassMetadataFactory.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DisconnectedClassMetadataFactory.php deleted file mode 100644 index 7a3ec6f..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/DisconnectedClassMetadataFactory.php +++ /dev/null @@ -1,48 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools; - -use Doctrine\Common\Persistence\Mapping\StaticReflectionService; -use Doctrine\ORM\Mapping\ClassMetadataFactory; - -/** - * The DisconnectedClassMetadataFactory is used to create ClassMetadataInfo objects - * that do not require the entity class actually exist. This allows us to - * load some mapping information and use it to do things like generate code - * from the mapping information. - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class DisconnectedClassMetadataFactory extends ClassMetadataFactory -{ - /** - * @return \Doctrine\Common\Persistence\Mapping\StaticReflectionService - */ - public function getReflectionService() - { - return new StaticReflectionService(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityGenerator.php deleted file mode 100644 index 5c304db..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityGenerator.php +++ /dev/null @@ -1,1906 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools; - -use Doctrine\Common\Collections\Collection; -use Doctrine\Common\Inflector\Inflector; -use Doctrine\DBAL\Types\Type; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use const E_USER_DEPRECATED; -use function str_replace; -use function trigger_error; - -/** - * Generic class used to generate PHP5 entity classes from ClassMetadataInfo instances. - * - * [php] - * $classes = $em->getClassMetadataFactory()->getAllMetadata(); - * - * $generator = new \Doctrine\ORM\Tools\EntityGenerator(); - * $generator->setGenerateAnnotations(true); - * $generator->setGenerateStubMethods(true); - * $generator->setRegenerateEntityIfExists(false); - * $generator->setUpdateEntityIfExists(true); - * $generator->generate($classes, '/path/to/generate/entities'); - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class EntityGenerator -{ - /** - * Specifies class fields should be protected. - */ - const FIELD_VISIBLE_PROTECTED = 'protected'; - - /** - * Specifies class fields should be private. - */ - const FIELD_VISIBLE_PRIVATE = 'private'; - - /** - * @var bool - */ - protected $backupExisting = true; - - /** - * The extension to use for written php files. - * - * @var string - */ - protected $extension = '.php'; - - /** - * Whether or not the current ClassMetadataInfo instance is new or old. - * - * @var boolean - */ - protected $isNew = true; - - /** - * @var array - */ - protected $staticReflection = []; - - /** - * Number of spaces to use for indention in generated code. - */ - protected $numSpaces = 4; - - /** - * The actual spaces to use for indention. - * - * @var string - */ - protected $spaces = ' '; - - /** - * The class all generated entities should extend. - * - * @var string - */ - protected $classToExtend; - - /** - * Whether or not to generation annotations. - * - * @var boolean - */ - protected $generateAnnotations = false; - - /** - * @var string - */ - protected $annotationsPrefix = ''; - - /** - * Whether or not to generate sub methods. - * - * @var boolean - */ - protected $generateEntityStubMethods = false; - - /** - * Whether or not to update the entity class if it exists already. - * - * @var boolean - */ - protected $updateEntityIfExists = false; - - /** - * Whether or not to re-generate entity class if it exists already. - * - * @var boolean - */ - protected $regenerateEntityIfExists = false; - - /** - * Visibility of the field - * - * @var string - */ - protected $fieldVisibility = 'private'; - - /** - * Whether or not to make generated embeddables immutable. - * - * @var boolean. - */ - protected $embeddablesImmutable = false; - - /** - * Hash-map for handle types. - * - * @var array - */ - protected $typeAlias = [ - Type::DATETIMETZ => '\DateTime', - Type::DATETIME => '\DateTime', - Type::DATE => '\DateTime', - Type::TIME => '\DateTime', - Type::OBJECT => '\stdClass', - Type::INTEGER => 'int', - Type::BIGINT => 'int', - Type::SMALLINT => 'int', - Type::TEXT => 'string', - Type::BLOB => 'string', - Type::DECIMAL => 'string', - Type::GUID => 'string', - Type::JSON_ARRAY => 'array', - Type::SIMPLE_ARRAY => 'array', - Type::BOOLEAN => 'bool', - ]; - - /** - * Hash-map to handle generator types string. - * - * @var array - */ - protected static $generatorStrategyMap = [ - ClassMetadataInfo::GENERATOR_TYPE_AUTO => 'AUTO', - ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE => 'SEQUENCE', - ClassMetadataInfo::GENERATOR_TYPE_TABLE => 'TABLE', - ClassMetadataInfo::GENERATOR_TYPE_IDENTITY => 'IDENTITY', - ClassMetadataInfo::GENERATOR_TYPE_NONE => 'NONE', - ClassMetadataInfo::GENERATOR_TYPE_UUID => 'UUID', - ClassMetadataInfo::GENERATOR_TYPE_CUSTOM => 'CUSTOM' - ]; - - /** - * Hash-map to handle the change tracking policy string. - * - * @var array - */ - protected static $changeTrackingPolicyMap = [ - ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT => 'DEFERRED_IMPLICIT', - ClassMetadataInfo::CHANGETRACKING_DEFERRED_EXPLICIT => 'DEFERRED_EXPLICIT', - ClassMetadataInfo::CHANGETRACKING_NOTIFY => 'NOTIFY', - ]; - - /** - * Hash-map to handle the inheritance type string. - * - * @var array - */ - protected static $inheritanceTypeMap = [ - ClassMetadataInfo::INHERITANCE_TYPE_NONE => 'NONE', - ClassMetadataInfo::INHERITANCE_TYPE_JOINED => 'JOINED', - ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_TABLE => 'SINGLE_TABLE', - ClassMetadataInfo::INHERITANCE_TYPE_TABLE_PER_CLASS => 'TABLE_PER_CLASS', - ]; - - /** - * @var string - */ - protected static $classTemplate = -' - - - -{ - -} -'; - - /** - * @var string - */ - protected static $getMethodTemplate = -'/** - * - * - * @return - */ -public function () -{ -return $this->; -}'; - - /** - * @var string - */ - protected static $setMethodTemplate = -'/** - * - * - * @param $ - * - * @return - */ -public function ($) -{ -$this-> = $; - -return $this; -}'; - - /** - * @var string - */ - protected static $addMethodTemplate = -'/** - * - * - * @param $ - * - * @return - */ -public function ($) -{ -$this->[] = $; - -return $this; -}'; - - /** - * @var string - */ - protected static $removeMethodTemplate = -'/** - * - * - * @param $ - * - * @return boolean TRUE if this collection contained the specified element, FALSE otherwise. - */ -public function ($) -{ -return $this->->removeElement($); -}'; - - /** - * @var string - */ - protected static $lifecycleCallbackMethodTemplate = -'/** - * @ - */ -public function () -{ -// Add your code here -}'; - - /** - * @var string - */ - protected static $constructorMethodTemplate = -'/** - * Constructor - */ -public function __construct() -{ - -} -'; - - /** - * @var string - */ - protected static $embeddableConstructorMethodTemplate = -'/** - * Constructor - * - * - */ -public function __construct() -{ - -} -'; - - /** - * Constructor. - */ - public function __construct() - { - @trigger_error(self::class . ' is deprecated and will be removed in Doctrine ORM 3.0', E_USER_DEPRECATED); - - if (version_compare(\Doctrine\Common\Version::VERSION, '2.2.0-DEV', '>=')) { - $this->annotationsPrefix = 'ORM\\'; - } - } - - /** - * Generates and writes entity classes for the given array of ClassMetadataInfo instances. - * - * @param array $metadatas - * @param string $outputDirectory - * - * @return void - */ - public function generate(array $metadatas, $outputDirectory) - { - foreach ($metadatas as $metadata) { - $this->writeEntityClass($metadata, $outputDirectory); - } - } - - /** - * Generates and writes entity class to disk for the given ClassMetadataInfo instance. - * - * @param ClassMetadataInfo $metadata - * @param string $outputDirectory - * - * @return void - * - * @throws \RuntimeException - */ - public function writeEntityClass(ClassMetadataInfo $metadata, $outputDirectory) - { - $path = $outputDirectory . '/' . str_replace('\\', DIRECTORY_SEPARATOR, $metadata->name) . $this->extension; - $dir = dirname($path); - - if ( ! is_dir($dir)) { - mkdir($dir, 0775, true); - } - - $this->isNew = ! file_exists($path) || $this->regenerateEntityIfExists; - - if ( ! $this->isNew) { - $this->parseTokensInEntityFile(file_get_contents($path)); - } else { - $this->staticReflection[$metadata->name] = ['properties' => [], 'methods' => []]; - } - - if ($this->backupExisting && file_exists($path)) { - $backupPath = dirname($path) . DIRECTORY_SEPARATOR . basename($path) . "~"; - if (!copy($path, $backupPath)) { - throw new \RuntimeException("Attempt to backup overwritten entity file but copy operation failed."); - } - } - - // If entity doesn't exist or we're re-generating the entities entirely - if ($this->isNew) { - file_put_contents($path, $this->generateEntityClass($metadata)); - // If entity exists and we're allowed to update the entity class - } elseif ($this->updateEntityIfExists) { - file_put_contents($path, $this->generateUpdatedEntityClass($metadata, $path)); - } - chmod($path, 0664); - } - - /** - * Generates a PHP5 Doctrine 2 entity class from the given ClassMetadataInfo instance. - * - * @param ClassMetadataInfo $metadata - * - * @return string - */ - public function generateEntityClass(ClassMetadataInfo $metadata) - { - $placeHolders = [ - '', - '', - '', - '', - '' - ]; - - $replacements = [ - $this->generateEntityNamespace($metadata), - $this->generateEntityUse(), - $this->generateEntityDocBlock($metadata), - $this->generateEntityClassName($metadata), - $this->generateEntityBody($metadata) - ]; - - $code = str_replace($placeHolders, $replacements, static::$classTemplate); - - return str_replace('', $this->spaces, $code); - } - - /** - * Generates the updated code for the given ClassMetadataInfo and entity at path. - * - * @param ClassMetadataInfo $metadata - * @param string $path - * - * @return string - */ - public function generateUpdatedEntityClass(ClassMetadataInfo $metadata, $path) - { - $currentCode = file_get_contents($path); - - $body = $this->generateEntityBody($metadata); - $body = str_replace('', $this->spaces, $body); - $last = strrpos($currentCode, '}'); - - return substr($currentCode, 0, $last) . $body . ($body ? "\n" : '') . "}\n"; - } - - /** - * Sets the number of spaces the exported class should have. - * - * @param integer $numSpaces - * - * @return void - */ - public function setNumSpaces($numSpaces) - { - $this->spaces = str_repeat(' ', $numSpaces); - $this->numSpaces = $numSpaces; - } - - /** - * Sets the extension to use when writing php files to disk. - * - * @param string $extension - * - * @return void - */ - public function setExtension($extension) - { - $this->extension = $extension; - } - - /** - * Sets the name of the class the generated classes should extend from. - * - * @param string $classToExtend - * - * @return void - */ - public function setClassToExtend($classToExtend) - { - $this->classToExtend = $classToExtend; - } - - /** - * Sets whether or not to generate annotations for the entity. - * - * @param bool $bool - * - * @return void - */ - public function setGenerateAnnotations($bool) - { - $this->generateAnnotations = $bool; - } - - /** - * Sets the class fields visibility for the entity (can either be private or protected). - * - * @param bool $visibility - * - * @return void - * - * @throws \InvalidArgumentException - */ - public function setFieldVisibility($visibility) - { - if ($visibility !== static::FIELD_VISIBLE_PRIVATE && $visibility !== static::FIELD_VISIBLE_PROTECTED) { - throw new \InvalidArgumentException('Invalid provided visibility (only private and protected are allowed): ' . $visibility); - } - - $this->fieldVisibility = $visibility; - } - - /** - * Sets whether or not to generate immutable embeddables. - * - * @param boolean $embeddablesImmutable - */ - public function setEmbeddablesImmutable($embeddablesImmutable) - { - $this->embeddablesImmutable = (boolean) $embeddablesImmutable; - } - - /** - * Sets an annotation prefix. - * - * @param string $prefix - * - * @return void - */ - public function setAnnotationPrefix($prefix) - { - $this->annotationsPrefix = $prefix; - } - - /** - * Sets whether or not to try and update the entity if it already exists. - * - * @param bool $bool - * - * @return void - */ - public function setUpdateEntityIfExists($bool) - { - $this->updateEntityIfExists = $bool; - } - - /** - * Sets whether or not to regenerate the entity if it exists. - * - * @param bool $bool - * - * @return void - */ - public function setRegenerateEntityIfExists($bool) - { - $this->regenerateEntityIfExists = $bool; - } - - /** - * Sets whether or not to generate stub methods for the entity. - * - * @param bool $bool - * - * @return void - */ - public function setGenerateStubMethods($bool) - { - $this->generateEntityStubMethods = $bool; - } - - /** - * Should an existing entity be backed up if it already exists? - * - * @param bool $bool - * - * @return void - */ - public function setBackupExisting($bool) - { - $this->backupExisting = $bool; - } - - /** - * @param string $type - * - * @return string - */ - protected function getType($type) - { - if (isset($this->typeAlias[$type])) { - return $this->typeAlias[$type]; - } - - return $type; - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateEntityNamespace(ClassMetadataInfo $metadata) - { - if (! $this->hasNamespace($metadata)) { - return ''; - } - - return 'namespace ' . $this->getNamespace($metadata) .';'; - } - - /** - * @return string - */ - protected function generateEntityUse() - { - if (! $this->generateAnnotations) { - return ''; - } - - return "\n".'use Doctrine\ORM\Mapping as ORM;'."\n"; - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateEntityClassName(ClassMetadataInfo $metadata) - { - return 'class ' . $this->getClassName($metadata) . - ($this->extendsClass() ? ' extends ' . $this->getClassToExtendName() : null); - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateEntityBody(ClassMetadataInfo $metadata) - { - $fieldMappingProperties = $this->generateEntityFieldMappingProperties($metadata); - $embeddedProperties = $this->generateEntityEmbeddedProperties($metadata); - $associationMappingProperties = $this->generateEntityAssociationMappingProperties($metadata); - $stubMethods = $this->generateEntityStubMethods ? $this->generateEntityStubMethods($metadata) : null; - $lifecycleCallbackMethods = $this->generateEntityLifecycleCallbackMethods($metadata); - - $code = []; - - if ($fieldMappingProperties) { - $code[] = $fieldMappingProperties; - } - - if ($embeddedProperties) { - $code[] = $embeddedProperties; - } - - if ($associationMappingProperties) { - $code[] = $associationMappingProperties; - } - - $code[] = $this->generateEntityConstructor($metadata); - - if ($stubMethods) { - $code[] = $stubMethods; - } - - if ($lifecycleCallbackMethods) { - $code[] = $lifecycleCallbackMethods; - } - - return implode("\n", $code); - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateEntityConstructor(ClassMetadataInfo $metadata) - { - if ($this->hasMethod('__construct', $metadata)) { - return ''; - } - - if ($metadata->isEmbeddedClass && $this->embeddablesImmutable) { - return $this->generateEmbeddableConstructor($metadata); - } - - $collections = []; - - foreach ($metadata->associationMappings as $mapping) { - if ($mapping['type'] & ClassMetadataInfo::TO_MANY) { - $collections[] = '$this->'.$mapping['fieldName'].' = new \Doctrine\Common\Collections\ArrayCollection();'; - } - } - - if ($collections) { - return $this->prefixCodeWithSpaces(str_replace("", implode("\n".$this->spaces, $collections), static::$constructorMethodTemplate)); - } - - return ''; - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - private function generateEmbeddableConstructor(ClassMetadataInfo $metadata) - { - $paramTypes = []; - $paramVariables = []; - $params = []; - $fields = []; - - // Resort fields to put optional fields at the end of the method signature. - $requiredFields = []; - $optionalFields = []; - - foreach ($metadata->fieldMappings as $fieldMapping) { - if (empty($fieldMapping['nullable'])) { - $requiredFields[] = $fieldMapping; - - continue; - } - - $optionalFields[] = $fieldMapping; - } - - $fieldMappings = array_merge($requiredFields, $optionalFields); - - foreach ($metadata->embeddedClasses as $fieldName => $embeddedClass) { - $paramType = '\\' . ltrim($embeddedClass['class'], '\\'); - $paramVariable = '$' . $fieldName; - - $paramTypes[] = $paramType; - $paramVariables[] = $paramVariable; - $params[] = $paramType . ' ' . $paramVariable; - $fields[] = '$this->' . $fieldName . ' = ' . $paramVariable . ';'; - } - - foreach ($fieldMappings as $fieldMapping) { - if (isset($fieldMapping['declaredField'], $metadata->embeddedClasses[$fieldMapping['declaredField']])) { - continue; - } - - $paramTypes[] = $this->getType($fieldMapping['type']) . (!empty($fieldMapping['nullable']) ? '|null' : ''); - $param = '$' . $fieldMapping['fieldName']; - $paramVariables[] = $param; - - if ($fieldMapping['type'] === 'datetime') { - $param = $this->getType($fieldMapping['type']) . ' ' . $param; - } - - if (!empty($fieldMapping['nullable'])) { - $param .= ' = null'; - } - - $params[] = $param; - - $fields[] = '$this->' . $fieldMapping['fieldName'] . ' = $' . $fieldMapping['fieldName'] . ';'; - } - - $maxParamTypeLength = max(array_map('strlen', $paramTypes)); - $paramTags = array_map( - function ($type, $variable) use ($maxParamTypeLength) { - return '@param ' . $type . str_repeat(' ', $maxParamTypeLength - strlen($type) + 1) . $variable; - }, - $paramTypes, - $paramVariables - ); - - // Generate multi line constructor if the signature exceeds 120 characters. - if (array_sum(array_map('strlen', $params)) + count($params) * 2 + 29 > 120) { - $delimiter = "\n" . $this->spaces; - $params = $delimiter . implode(',' . $delimiter, $params) . "\n"; - } else { - $params = implode(', ', $params); - } - - $replacements = [ - '' => implode("\n * ", $paramTags), - '' => $params, - '' => implode("\n" . $this->spaces, $fields), - ]; - - $constructor = str_replace( - array_keys($replacements), - array_values($replacements), - static::$embeddableConstructorMethodTemplate - ); - - return $this->prefixCodeWithSpaces($constructor); - } - - /** - * @todo this won't work if there is a namespace in brackets and a class outside of it. - * - * @param string $src - * - * @return void - */ - protected function parseTokensInEntityFile($src) - { - $tokens = token_get_all($src); - $tokensCount = count($tokens); - $lastSeenNamespace = ''; - $lastSeenClass = false; - - $inNamespace = false; - $inClass = false; - - for ($i = 0; $i < $tokensCount; $i++) { - $token = $tokens[$i]; - if (in_array($token[0], [T_WHITESPACE, T_COMMENT, T_DOC_COMMENT], true)) { - continue; - } - - if ($inNamespace) { - if (in_array($token[0], [T_NS_SEPARATOR, T_STRING], true)) { - $lastSeenNamespace .= $token[1]; - } elseif (is_string($token) && in_array($token, [';', '{'], true)) { - $inNamespace = false; - } - } - - if ($inClass) { - $inClass = false; - $lastSeenClass = $lastSeenNamespace . ($lastSeenNamespace ? '\\' : '') . $token[1]; - $this->staticReflection[$lastSeenClass]['properties'] = []; - $this->staticReflection[$lastSeenClass]['methods'] = []; - } - - if (T_NAMESPACE === $token[0]) { - $lastSeenNamespace = ''; - $inNamespace = true; - } elseif (T_CLASS === $token[0] && T_DOUBLE_COLON !== $tokens[$i-1][0]) { - $inClass = true; - } elseif (T_FUNCTION === $token[0]) { - if (T_STRING === $tokens[$i+2][0]) { - $this->staticReflection[$lastSeenClass]['methods'][] = strtolower($tokens[$i+2][1]); - } elseif ($tokens[$i+2] == '&' && T_STRING === $tokens[$i+3][0]) { - $this->staticReflection[$lastSeenClass]['methods'][] = strtolower($tokens[$i+3][1]); - } - } elseif (in_array($token[0], [T_VAR, T_PUBLIC, T_PRIVATE, T_PROTECTED], true) && T_FUNCTION !== $tokens[$i+2][0]) { - $this->staticReflection[$lastSeenClass]['properties'][] = substr($tokens[$i+2][1], 1); - } - } - } - - /** - * @param string $property - * @param ClassMetadataInfo $metadata - * - * @return bool - */ - protected function hasProperty($property, ClassMetadataInfo $metadata) - { - if ($this->extendsClass() || (!$this->isNew && class_exists($metadata->name))) { - // don't generate property if its already on the base class. - $reflClass = new \ReflectionClass($this->getClassToExtend() ?: $metadata->name); - if ($reflClass->hasProperty($property)) { - return true; - } - } - - // check traits for existing property - foreach ($this->getTraits($metadata) as $trait) { - if ($trait->hasProperty($property)) { - return true; - } - } - - return ( - isset($this->staticReflection[$metadata->name]) && - in_array($property, $this->staticReflection[$metadata->name]['properties'], true) - ); - } - - /** - * @param string $method - * @param ClassMetadataInfo $metadata - * - * @return bool - */ - protected function hasMethod($method, ClassMetadataInfo $metadata) - { - if ($this->extendsClass() || (!$this->isNew && class_exists($metadata->name))) { - // don't generate method if its already on the base class. - $reflClass = new \ReflectionClass($this->getClassToExtend() ?: $metadata->name); - - if ($reflClass->hasMethod($method)) { - return true; - } - } - - // check traits for existing method - foreach ($this->getTraits($metadata) as $trait) { - if ($trait->hasMethod($method)) { - return true; - } - } - - return ( - isset($this->staticReflection[$metadata->name]) && - in_array(strtolower($method), $this->staticReflection[$metadata->name]['methods'], true) - ); - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return array - * - * @throws \ReflectionException - */ - protected function getTraits(ClassMetadataInfo $metadata) - { - if (! ($metadata->reflClass !== null || class_exists($metadata->name))) { - return []; - } - - $reflClass = $metadata->reflClass ?? new \ReflectionClass($metadata->name); - - $traits = []; - - while ($reflClass !== false) { - $traits = array_merge($traits, $reflClass->getTraits()); - - $reflClass = $reflClass->getParentClass(); - } - - return $traits; - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return bool - */ - protected function hasNamespace(ClassMetadataInfo $metadata) - { - return (bool) strpos($metadata->name, '\\'); - } - - /** - * @return bool - */ - protected function extendsClass() - { - return (bool) $this->classToExtend; - } - - /** - * @return string - */ - protected function getClassToExtend() - { - return $this->classToExtend; - } - - /** - * @return string - */ - protected function getClassToExtendName() - { - $refl = new \ReflectionClass($this->getClassToExtend()); - - return '\\' . $refl->getName(); - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function getClassName(ClassMetadataInfo $metadata) - { - return ($pos = strrpos($metadata->name, '\\')) - ? substr($metadata->name, $pos + 1, strlen($metadata->name)) : $metadata->name; - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function getNamespace(ClassMetadataInfo $metadata) - { - return substr($metadata->name, 0, strrpos($metadata->name, '\\')); - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateEntityDocBlock(ClassMetadataInfo $metadata) - { - $lines = []; - $lines[] = '/**'; - $lines[] = ' * ' . $this->getClassName($metadata); - - if ($this->generateAnnotations) { - $lines[] = ' *'; - - $methods = [ - 'generateTableAnnotation', - 'generateInheritanceAnnotation', - 'generateDiscriminatorColumnAnnotation', - 'generateDiscriminatorMapAnnotation', - 'generateEntityAnnotation', - 'generateEntityListenerAnnotation', - ]; - - foreach ($methods as $method) { - if ($code = $this->$method($metadata)) { - $lines[] = ' * ' . $code; - } - } - - if (isset($metadata->lifecycleCallbacks) && $metadata->lifecycleCallbacks) { - $lines[] = ' * @' . $this->annotationsPrefix . 'HasLifecycleCallbacks'; - } - } - - $lines[] = ' */'; - - return implode("\n", $lines); - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateEntityAnnotation(ClassMetadataInfo $metadata) - { - $prefix = '@' . $this->annotationsPrefix; - - if ($metadata->isEmbeddedClass) { - return $prefix . 'Embeddable'; - } - - $customRepository = $metadata->customRepositoryClassName - ? '(repositoryClass="' . $metadata->customRepositoryClassName . '")' - : ''; - - return $prefix . ($metadata->isMappedSuperclass ? 'MappedSuperclass' : 'Entity') . $customRepository; - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateTableAnnotation(ClassMetadataInfo $metadata) - { - if ($metadata->isEmbeddedClass) { - return ''; - } - - $table = []; - - if (isset($metadata->table['schema'])) { - $table[] = 'schema="' . $metadata->table['schema'] . '"'; - } - - if (isset($metadata->table['name'])) { - $table[] = 'name="' . $metadata->table['name'] . '"'; - } - - if (isset($metadata->table['options']) && $metadata->table['options']) { - $table[] = 'options={' . $this->exportTableOptions((array) $metadata->table['options']) . '}'; - } - - if (isset($metadata->table['uniqueConstraints']) && $metadata->table['uniqueConstraints']) { - $constraints = $this->generateTableConstraints('UniqueConstraint', $metadata->table['uniqueConstraints']); - $table[] = 'uniqueConstraints={' . $constraints . '}'; - } - - if (isset($metadata->table['indexes']) && $metadata->table['indexes']) { - $constraints = $this->generateTableConstraints('Index', $metadata->table['indexes']); - $table[] = 'indexes={' . $constraints . '}'; - } - - return '@' . $this->annotationsPrefix . 'Table(' . implode(', ', $table) . ')'; - } - - /** - * @param string $constraintName - * @param array $constraints - * - * @return string - */ - protected function generateTableConstraints($constraintName, array $constraints) - { - $annotations = []; - foreach ($constraints as $name => $constraint) { - $columns = []; - foreach ($constraint['columns'] as $column) { - $columns[] = '"' . $column . '"'; - } - $annotations[] = '@' . $this->annotationsPrefix . $constraintName . '(name="' . $name . '", columns={' . implode(', ', $columns) . '})'; - } - - return implode(', ', $annotations); - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateInheritanceAnnotation(ClassMetadataInfo $metadata) - { - if ($metadata->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_NONE) { - return ''; - } - - return '@' . $this->annotationsPrefix . 'InheritanceType("'.$this->getInheritanceTypeString($metadata->inheritanceType).'")'; - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateDiscriminatorColumnAnnotation(ClassMetadataInfo $metadata) - { - if ($metadata->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_NONE) { - return ''; - } - - $discrColumn = $metadata->discriminatorColumn; - $columnDefinition = 'name="' . $discrColumn['name'] - . '", type="' . $discrColumn['type'] - . '", length=' . $discrColumn['length']; - - return '@' . $this->annotationsPrefix . 'DiscriminatorColumn(' . $columnDefinition . ')'; - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateDiscriminatorMapAnnotation(ClassMetadataInfo $metadata) - { - if ($metadata->inheritanceType === ClassMetadataInfo::INHERITANCE_TYPE_NONE) { - return null; - } - - $inheritanceClassMap = []; - - foreach ($metadata->discriminatorMap as $type => $class) { - $inheritanceClassMap[] .= '"' . $type . '" = "' . $class . '"'; - } - - return '@' . $this->annotationsPrefix . 'DiscriminatorMap({' . implode(', ', $inheritanceClassMap) . '})'; - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateEntityStubMethods(ClassMetadataInfo $metadata) - { - $methods = []; - - foreach ($metadata->fieldMappings as $fieldMapping) { - if (isset($fieldMapping['declaredField'], $metadata->embeddedClasses[$fieldMapping['declaredField']])) { - continue; - } - - $nullableField = $this->nullableFieldExpression($fieldMapping); - - if ((!$metadata->isEmbeddedClass || !$this->embeddablesImmutable) - && (!isset($fieldMapping['id']) || ! $fieldMapping['id'] || $metadata->generatorType === ClassMetadataInfo::GENERATOR_TYPE_NONE) - && $code = $this->generateEntityStubMethod($metadata, 'set', $fieldMapping['fieldName'], $fieldMapping['type'], $nullableField) - ) { - $methods[] = $code; - } - - if ($code = $this->generateEntityStubMethod($metadata, 'get', $fieldMapping['fieldName'], $fieldMapping['type'], $nullableField)) { - $methods[] = $code; - } - } - - foreach ($metadata->embeddedClasses as $fieldName => $embeddedClass) { - if (isset($embeddedClass['declaredField'])) { - continue; - } - - if ( ! $metadata->isEmbeddedClass || ! $this->embeddablesImmutable) { - if ($code = $this->generateEntityStubMethod($metadata, 'set', $fieldName, $embeddedClass['class'])) { - $methods[] = $code; - } - } - - if ($code = $this->generateEntityStubMethod($metadata, 'get', $fieldName, $embeddedClass['class'])) { - $methods[] = $code; - } - } - - foreach ($metadata->associationMappings as $associationMapping) { - if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) { - $nullable = $this->isAssociationIsNullable($associationMapping) ? 'null' : null; - if ($code = $this->generateEntityStubMethod($metadata, 'set', $associationMapping['fieldName'], $associationMapping['targetEntity'], $nullable)) { - $methods[] = $code; - } - if ($code = $this->generateEntityStubMethod($metadata, 'get', $associationMapping['fieldName'], $associationMapping['targetEntity'], $nullable)) { - $methods[] = $code; - } - } elseif ($associationMapping['type'] & ClassMetadataInfo::TO_MANY) { - if ($code = $this->generateEntityStubMethod($metadata, 'add', $associationMapping['fieldName'], $associationMapping['targetEntity'])) { - $methods[] = $code; - } - if ($code = $this->generateEntityStubMethod($metadata, 'remove', $associationMapping['fieldName'], $associationMapping['targetEntity'])) { - $methods[] = $code; - } - if ($code = $this->generateEntityStubMethod($metadata, 'get', $associationMapping['fieldName'], Collection::class)) { - $methods[] = $code; - } - } - } - - return implode("\n\n", $methods); - } - - /** - * @param array $associationMapping - * - * @return bool - */ - protected function isAssociationIsNullable(array $associationMapping) - { - if (isset($associationMapping['id']) && $associationMapping['id']) { - return false; - } - - if (isset($associationMapping['joinColumns'])) { - $joinColumns = $associationMapping['joinColumns']; - } else { - //@todo there is no way to retrieve targetEntity metadata - $joinColumns = []; - } - - foreach ($joinColumns as $joinColumn) { - if (isset($joinColumn['nullable']) && !$joinColumn['nullable']) { - return false; - } - } - - return true; - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateEntityLifecycleCallbackMethods(ClassMetadataInfo $metadata) - { - if (empty($metadata->lifecycleCallbacks)) { - return ''; - } - - $methods = []; - - foreach ($metadata->lifecycleCallbacks as $name => $callbacks) { - foreach ($callbacks as $callback) { - $methods[] = $this->generateLifecycleCallbackMethod($name, $callback, $metadata); - } - } - - return implode("\n\n", array_filter($methods)); - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateEntityAssociationMappingProperties(ClassMetadataInfo $metadata) - { - $lines = []; - - foreach ($metadata->associationMappings as $associationMapping) { - if ($this->hasProperty($associationMapping['fieldName'], $metadata)) { - continue; - } - - $lines[] = $this->generateAssociationMappingPropertyDocBlock($associationMapping, $metadata); - $lines[] = $this->spaces . $this->fieldVisibility . ' $' . $associationMapping['fieldName'] - . ($associationMapping['type'] == 'manyToMany' ? ' = array()' : null) . ";\n"; - } - - return implode("\n", $lines); - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateEntityFieldMappingProperties(ClassMetadataInfo $metadata) - { - $lines = []; - - foreach ($metadata->fieldMappings as $fieldMapping) { - if (isset($fieldMapping['declaredField'], $metadata->embeddedClasses[$fieldMapping['declaredField']]) || - $this->hasProperty($fieldMapping['fieldName'], $metadata) || - $metadata->isInheritedField($fieldMapping['fieldName']) - ) { - continue; - } - - $lines[] = $this->generateFieldMappingPropertyDocBlock($fieldMapping, $metadata); - $lines[] = $this->spaces . $this->fieldVisibility . ' $' . $fieldMapping['fieldName'] - . (isset($fieldMapping['options']['default']) ? ' = ' . var_export($fieldMapping['options']['default'], true) : null) . ";\n"; - } - - return implode("\n", $lines); - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateEntityEmbeddedProperties(ClassMetadataInfo $metadata) - { - $lines = []; - - foreach ($metadata->embeddedClasses as $fieldName => $embeddedClass) { - if (isset($embeddedClass['declaredField']) || $this->hasProperty($fieldName, $metadata)) { - continue; - } - - $lines[] = $this->generateEmbeddedPropertyDocBlock($embeddedClass); - $lines[] = $this->spaces . $this->fieldVisibility . ' $' . $fieldName . ";\n"; - } - - return implode("\n", $lines); - } - - /** - * @param ClassMetadataInfo $metadata - * @param string $type - * @param string $fieldName - * @param string|null $typeHint - * @param string|null $defaultValue - * - * @return string - */ - protected function generateEntityStubMethod(ClassMetadataInfo $metadata, $type, $fieldName, $typeHint = null, $defaultValue = null) - { - $methodName = $type . Inflector::classify($fieldName); - $variableName = Inflector::camelize($fieldName); - if (in_array($type, ["add", "remove"])) { - $methodName = Inflector::singularize($methodName); - $variableName = Inflector::singularize($variableName); - } - - if ($this->hasMethod($methodName, $metadata)) { - return ''; - } - $this->staticReflection[$metadata->name]['methods'][] = strtolower($methodName); - - $var = sprintf('%sMethodTemplate', $type); - $template = static::$$var; - - $methodTypeHint = null; - $types = Type::getTypesMap(); - $variableType = $typeHint ? $this->getType($typeHint) : null; - - if ($typeHint && ! isset($types[$typeHint])) { - $variableType = '\\' . ltrim($variableType, '\\'); - $methodTypeHint = '\\' . $typeHint . ' '; - } - - $replacements = [ - '' => ucfirst($type) . ' ' . $variableName . '.', - '' => $methodTypeHint, - '' => $variableType . (null !== $defaultValue ? ('|' . $defaultValue) : ''), - '' => $variableName, - '' => $methodName, - '' => $fieldName, - '' => ($defaultValue !== null ) ? (' = ' . $defaultValue) : '', - '' => $this->getClassName($metadata) - ]; - - $method = str_replace( - array_keys($replacements), - array_values($replacements), - $template - ); - - return $this->prefixCodeWithSpaces($method); - } - - /** - * @param string $name - * @param string $methodName - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateLifecycleCallbackMethod($name, $methodName, ClassMetadataInfo $metadata) - { - if ($this->hasMethod($methodName, $metadata)) { - return ''; - } - - $this->staticReflection[$metadata->name]['methods'][] = $methodName; - - $replacements = [ - '' => $this->annotationsPrefix . ucfirst($name), - '' => $methodName, - ]; - - $method = str_replace( - array_keys($replacements), - array_values($replacements), - static::$lifecycleCallbackMethodTemplate - ); - - return $this->prefixCodeWithSpaces($method); - } - - /** - * @param array $joinColumn - * - * @return string - */ - protected function generateJoinColumnAnnotation(array $joinColumn) - { - $joinColumnAnnot = []; - - if (isset($joinColumn['name'])) { - $joinColumnAnnot[] = 'name="' . $joinColumn['name'] . '"'; - } - - if (isset($joinColumn['referencedColumnName'])) { - $joinColumnAnnot[] = 'referencedColumnName="' . $joinColumn['referencedColumnName'] . '"'; - } - - if (isset($joinColumn['unique']) && $joinColumn['unique']) { - $joinColumnAnnot[] = 'unique=' . ($joinColumn['unique'] ? 'true' : 'false'); - } - - if (isset($joinColumn['nullable'])) { - $joinColumnAnnot[] = 'nullable=' . ($joinColumn['nullable'] ? 'true' : 'false'); - } - - if (isset($joinColumn['onDelete'])) { - $joinColumnAnnot[] = 'onDelete="' . ($joinColumn['onDelete'] . '"'); - } - - if (isset($joinColumn['columnDefinition'])) { - $joinColumnAnnot[] = 'columnDefinition="' . $joinColumn['columnDefinition'] . '"'; - } - - return '@' . $this->annotationsPrefix . 'JoinColumn(' . implode(', ', $joinColumnAnnot) . ')'; - } - - /** - * @param array $associationMapping - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateAssociationMappingPropertyDocBlock(array $associationMapping, ClassMetadataInfo $metadata) - { - $lines = []; - $lines[] = $this->spaces . '/**'; - - if ($associationMapping['type'] & ClassMetadataInfo::TO_MANY) { - $lines[] = $this->spaces . ' * @var \Doctrine\Common\Collections\Collection'; - } else { - $lines[] = $this->spaces . ' * @var \\' . ltrim($associationMapping['targetEntity'], '\\'); - } - - if ($this->generateAnnotations) { - $lines[] = $this->spaces . ' *'; - - if (isset($associationMapping['id']) && $associationMapping['id']) { - $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'Id'; - - if ($generatorType = $this->getIdGeneratorTypeString($metadata->generatorType)) { - $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'GeneratedValue(strategy="' . $generatorType . '")'; - } - } - - $type = null; - switch ($associationMapping['type']) { - case ClassMetadataInfo::ONE_TO_ONE: - $type = 'OneToOne'; - break; - case ClassMetadataInfo::MANY_TO_ONE: - $type = 'ManyToOne'; - break; - case ClassMetadataInfo::ONE_TO_MANY: - $type = 'OneToMany'; - break; - case ClassMetadataInfo::MANY_TO_MANY: - $type = 'ManyToMany'; - break; - } - $typeOptions = []; - - if (isset($associationMapping['targetEntity'])) { - $typeOptions[] = 'targetEntity="' . $associationMapping['targetEntity'] . '"'; - } - - if (isset($associationMapping['inversedBy'])) { - $typeOptions[] = 'inversedBy="' . $associationMapping['inversedBy'] . '"'; - } - - if (isset($associationMapping['mappedBy'])) { - $typeOptions[] = 'mappedBy="' . $associationMapping['mappedBy'] . '"'; - } - - if ($associationMapping['cascade']) { - $cascades = []; - - if ($associationMapping['isCascadePersist']) $cascades[] = '"persist"'; - if ($associationMapping['isCascadeRemove']) $cascades[] = '"remove"'; - if ($associationMapping['isCascadeDetach']) $cascades[] = '"detach"'; - if ($associationMapping['isCascadeMerge']) $cascades[] = '"merge"'; - if ($associationMapping['isCascadeRefresh']) $cascades[] = '"refresh"'; - - if (count($cascades) === 5) { - $cascades = ['"all"']; - } - - $typeOptions[] = 'cascade={' . implode(',', $cascades) . '}'; - } - - if (isset($associationMapping['orphanRemoval']) && $associationMapping['orphanRemoval']) { - $typeOptions[] = 'orphanRemoval=' . ($associationMapping['orphanRemoval'] ? 'true' : 'false'); - } - - if (isset($associationMapping['fetch']) && $associationMapping['fetch'] !== ClassMetadataInfo::FETCH_LAZY) { - $fetchMap = [ - ClassMetadataInfo::FETCH_EXTRA_LAZY => 'EXTRA_LAZY', - ClassMetadataInfo::FETCH_EAGER => 'EAGER', - ]; - - $typeOptions[] = 'fetch="' . $fetchMap[$associationMapping['fetch']] . '"'; - } - - $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . '' . $type . '(' . implode(', ', $typeOptions) . ')'; - - if (isset($associationMapping['joinColumns']) && $associationMapping['joinColumns']) { - $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'JoinColumns({'; - - $joinColumnsLines = []; - - foreach ($associationMapping['joinColumns'] as $joinColumn) { - if ($joinColumnAnnot = $this->generateJoinColumnAnnotation($joinColumn)) { - $joinColumnsLines[] = $this->spaces . ' * ' . $joinColumnAnnot; - } - } - - $lines[] = implode(",\n", $joinColumnsLines); - $lines[] = $this->spaces . ' * })'; - } - - if (isset($associationMapping['joinTable']) && $associationMapping['joinTable']) { - $joinTable = []; - $joinTable[] = 'name="' . $associationMapping['joinTable']['name'] . '"'; - - if (isset($associationMapping['joinTable']['schema'])) { - $joinTable[] = 'schema="' . $associationMapping['joinTable']['schema'] . '"'; - } - - $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'JoinTable(' . implode(', ', $joinTable) . ','; - $lines[] = $this->spaces . ' * joinColumns={'; - - $joinColumnsLines = []; - - foreach ($associationMapping['joinTable']['joinColumns'] as $joinColumn) { - $joinColumnsLines[] = $this->spaces . ' * ' . $this->generateJoinColumnAnnotation($joinColumn); - } - - $lines[] = implode(",". PHP_EOL, $joinColumnsLines); - $lines[] = $this->spaces . ' * },'; - $lines[] = $this->spaces . ' * inverseJoinColumns={'; - - $inverseJoinColumnsLines = []; - - foreach ($associationMapping['joinTable']['inverseJoinColumns'] as $joinColumn) { - $inverseJoinColumnsLines[] = $this->spaces . ' * ' . $this->generateJoinColumnAnnotation($joinColumn); - } - - $lines[] = implode(",". PHP_EOL, $inverseJoinColumnsLines); - $lines[] = $this->spaces . ' * }'; - $lines[] = $this->spaces . ' * )'; - } - - if (isset($associationMapping['orderBy'])) { - $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'OrderBy({'; - - foreach ($associationMapping['orderBy'] as $name => $direction) { - $lines[] = $this->spaces . ' * "' . $name . '"="' . $direction . '",'; - } - - $lines[count($lines) - 1] = substr($lines[count($lines) - 1], 0, strlen($lines[count($lines) - 1]) - 1); - $lines[] = $this->spaces . ' * })'; - } - } - - $lines[] = $this->spaces . ' */'; - - return implode("\n", $lines); - } - - /** - * @param array $fieldMapping - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function generateFieldMappingPropertyDocBlock(array $fieldMapping, ClassMetadataInfo $metadata) - { - $lines = []; - $lines[] = $this->spaces . '/**'; - $lines[] = $this->spaces . ' * @var ' - . $this->getType($fieldMapping['type']) - . ($this->nullableFieldExpression($fieldMapping) ? '|null' : ''); - - if ($this->generateAnnotations) { - $lines[] = $this->spaces . ' *'; - - $column = []; - if (isset($fieldMapping['columnName'])) { - $column[] = 'name="' . $fieldMapping['columnName'] . '"'; - } - - if (isset($fieldMapping['type'])) { - $column[] = 'type="' . $fieldMapping['type'] . '"'; - } - - if (isset($fieldMapping['length'])) { - $column[] = 'length=' . $fieldMapping['length']; - } - - if (isset($fieldMapping['precision'])) { - $column[] = 'precision=' . $fieldMapping['precision']; - } - - if (isset($fieldMapping['scale'])) { - $column[] = 'scale=' . $fieldMapping['scale']; - } - - if (isset($fieldMapping['nullable'])) { - $column[] = 'nullable=' . var_export($fieldMapping['nullable'], true); - } - - $options = []; - - if (isset($fieldMapping['options']['default']) && $fieldMapping['options']['default']) { - $options[] = '"default"="' . $fieldMapping['options']['default'] .'"'; - } - - if (isset($fieldMapping['options']['unsigned']) && $fieldMapping['options']['unsigned']) { - $options[] = '"unsigned"=true'; - } - - if (isset($fieldMapping['options']['fixed']) && $fieldMapping['options']['fixed']) { - $options[] = '"fixed"=true'; - } - - if (isset($fieldMapping['options']['comment']) && $fieldMapping['options']['comment']) { - $options[] = '"comment"="' . str_replace('"', '""', $fieldMapping['options']['comment']) . '"'; - } - - if (isset($fieldMapping['options']['collation']) && $fieldMapping['options']['collation']) { - $options[] = '"collation"="' . $fieldMapping['options']['collation'] .'"'; - } - - if (isset($fieldMapping['options']['check']) && $fieldMapping['options']['check']) { - $options[] = '"check"="' . $fieldMapping['options']['check'] .'"'; - } - - if ($options) { - $column[] = 'options={'.implode(',', $options).'}'; - } - - if (isset($fieldMapping['columnDefinition'])) { - $column[] = 'columnDefinition="' . $fieldMapping['columnDefinition'] . '"'; - } - - if (isset($fieldMapping['unique'])) { - $column[] = 'unique=' . var_export($fieldMapping['unique'], true); - } - - $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'Column(' . implode(', ', $column) . ')'; - - if (isset($fieldMapping['id']) && $fieldMapping['id']) { - $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'Id'; - - if ($generatorType = $this->getIdGeneratorTypeString($metadata->generatorType)) { - $lines[] = $this->spaces.' * @' . $this->annotationsPrefix . 'GeneratedValue(strategy="' . $generatorType . '")'; - } - - if ($metadata->sequenceGeneratorDefinition) { - $sequenceGenerator = []; - - if (isset($metadata->sequenceGeneratorDefinition['sequenceName'])) { - $sequenceGenerator[] = 'sequenceName="' . $metadata->sequenceGeneratorDefinition['sequenceName'] . '"'; - } - - if (isset($metadata->sequenceGeneratorDefinition['allocationSize'])) { - $sequenceGenerator[] = 'allocationSize=' . $metadata->sequenceGeneratorDefinition['allocationSize']; - } - - if (isset($metadata->sequenceGeneratorDefinition['initialValue'])) { - $sequenceGenerator[] = 'initialValue=' . $metadata->sequenceGeneratorDefinition['initialValue']; - } - - $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'SequenceGenerator(' . implode(', ', $sequenceGenerator) . ')'; - } - } - - if (isset($fieldMapping['version']) && $fieldMapping['version']) { - $lines[] = $this->spaces . ' * @' . $this->annotationsPrefix . 'Version'; - } - } - - $lines[] = $this->spaces . ' */'; - - return implode("\n", $lines); - } - - /** - * @param array $embeddedClass - * - * @return string - */ - protected function generateEmbeddedPropertyDocBlock(array $embeddedClass) - { - $lines = []; - $lines[] = $this->spaces . '/**'; - $lines[] = $this->spaces . ' * @var \\' . ltrim($embeddedClass['class'], '\\'); - - if ($this->generateAnnotations) { - $lines[] = $this->spaces . ' *'; - - $embedded = ['class="' . $embeddedClass['class'] . '"']; - - if (isset($embeddedClass['columnPrefix'])) { - if (is_string($embeddedClass['columnPrefix'])) { - $embedded[] = 'columnPrefix="' . $embeddedClass['columnPrefix'] . '"'; - } else { - $embedded[] = 'columnPrefix=' . var_export($embeddedClass['columnPrefix'], true); - } - } - - $lines[] = $this->spaces . ' * @' . - $this->annotationsPrefix . 'Embedded(' . implode(', ', $embedded) . ')'; - } - - $lines[] = $this->spaces . ' */'; - - return implode("\n", $lines); - } - - private function generateEntityListenerAnnotation(ClassMetadataInfo $metadata): string - { - if (0 === \count($metadata->entityListeners)) { - return ''; - } - - $processedClasses = []; - foreach ($metadata->entityListeners as $event => $eventListeners) { - foreach ($eventListeners as $eventListener) { - $processedClasses[] = '"' . $eventListener['class'] . '"'; - } - } - - return \sprintf( - '%s%s({%s})', - '@' . $this->annotationsPrefix, - 'EntityListeners', - \implode(',', \array_unique($processedClasses)) - ); - } - - /** - * @param string $code - * @param int $num - * - * @return string - */ - protected function prefixCodeWithSpaces($code, $num = 1) - { - $lines = explode("\n", $code); - - foreach ($lines as $key => $value) { - if ( ! empty($value)) { - $lines[$key] = str_repeat($this->spaces, $num) . $lines[$key]; - } - } - - return implode("\n", $lines); - } - - /** - * @param integer $type The inheritance type used by the class and its subclasses. - * - * @return string The literal string for the inheritance type. - * - * @throws \InvalidArgumentException When the inheritance type does not exist. - */ - protected function getInheritanceTypeString($type) - { - if ( ! isset(static::$inheritanceTypeMap[$type])) { - throw new \InvalidArgumentException(sprintf('Invalid provided InheritanceType: %s', $type)); - } - - return static::$inheritanceTypeMap[$type]; - } - - /** - * @param integer $type The policy used for change-tracking for the mapped class. - * - * @return string The literal string for the change-tracking type. - * - * @throws \InvalidArgumentException When the change-tracking type does not exist. - */ - protected function getChangeTrackingPolicyString($type) - { - if ( ! isset(static::$changeTrackingPolicyMap[$type])) { - throw new \InvalidArgumentException(sprintf('Invalid provided ChangeTrackingPolicy: %s', $type)); - } - - return static::$changeTrackingPolicyMap[$type]; - } - - /** - * @param integer $type The generator to use for the mapped class. - * - * @return string The literal string for the generator type. - * - * @throws \InvalidArgumentException When the generator type does not exist. - */ - protected function getIdGeneratorTypeString($type) - { - if ( ! isset(static::$generatorStrategyMap[$type])) { - throw new \InvalidArgumentException(sprintf('Invalid provided IdGeneratorType: %s', $type)); - } - - return static::$generatorStrategyMap[$type]; - } - - /** - * @param array $fieldMapping - * - * @return string|null - */ - private function nullableFieldExpression(array $fieldMapping) - { - if (isset($fieldMapping['nullable']) && true === $fieldMapping['nullable']) { - return 'null'; - } - - return null; - } - - /** - * Exports (nested) option elements. - * - * @param array $options - * - * @return string - */ - private function exportTableOptions(array $options) - { - $optionsStr = []; - - foreach ($options as $name => $option) { - if (is_array($option)) { - $optionsStr[] = '"' . $name . '"={' . $this->exportTableOptions($option) . '}'; - } else { - $optionsStr[] = '"' . $name . '"="' . (string) $option . '"'; - } - } - - return implode(',', $optionsStr); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityRepositoryGenerator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityRepositoryGenerator.php deleted file mode 100644 index 9b3b290..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/EntityRepositoryGenerator.php +++ /dev/null @@ -1,182 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools; - -use Doctrine\ORM\EntityRepository; -use const E_USER_DEPRECATED; -use function trigger_error; - -/** - * Class to generate entity repository classes - * - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class EntityRepositoryGenerator -{ - private $repositoryName; - - protected static $_template = -' - -/** - * - * - * This class was generated by the Doctrine ORM. Add your own custom - * repository methods below. - */ -class extends -{ -} -'; - - public function __construct() - { - @trigger_error(self::class . ' is deprecated and will be removed in Doctrine ORM 3.0', E_USER_DEPRECATED); - } - - /** - * @param string $fullClassName - * - * @return string - */ - public function generateEntityRepositoryClass($fullClassName) - { - $variables = [ - '' => $this->generateEntityRepositoryNamespace($fullClassName), - '' => $this->generateEntityRepositoryName($fullClassName), - '' => $this->generateClassName($fullClassName) - ]; - - return str_replace(array_keys($variables), array_values($variables), self::$_template); - } - - /** - * Generates the namespace, if class do not have namespace, return empty string instead. - * - * @param string $fullClassName - * - * @return string $namespace - */ - private function getClassNamespace($fullClassName) - { - $namespace = substr($fullClassName, 0, strrpos($fullClassName, '\\')); - - return $namespace; - } - - /** - * Generates the class name - * - * @param string $fullClassName - * - * @return string - */ - private function generateClassName($fullClassName) - { - $namespace = $this->getClassNamespace($fullClassName); - - $className = $fullClassName; - - if ($namespace) { - $className = substr($fullClassName, strrpos($fullClassName, '\\') + 1, strlen($fullClassName)); - } - - return $className; - } - - /** - * Generates the namespace statement, if class do not have namespace, return empty string instead. - * - * @param string $fullClassName The full repository class name. - * - * @return string $namespace - */ - private function generateEntityRepositoryNamespace($fullClassName) - { - $namespace = $this->getClassNamespace($fullClassName); - - return $namespace ? 'namespace ' . $namespace . ';' : ''; - } - - /** - * @param string $fullClassName - * - * @return string $repositoryName - */ - private function generateEntityRepositoryName($fullClassName) - { - $namespace = $this->getClassNamespace($fullClassName); - - $repositoryName = $this->repositoryName ?: EntityRepository::class; - - if ($namespace && $repositoryName[0] !== '\\') { - $repositoryName = '\\' . $repositoryName; - } - - return $repositoryName; - } - - /** - * @param string $fullClassName - * @param string $outputDirectory - * - * @return void - */ - public function writeEntityRepositoryClass($fullClassName, $outputDirectory) - { - $code = $this->generateEntityRepositoryClass($fullClassName); - - $path = $outputDirectory . DIRECTORY_SEPARATOR - . str_replace('\\', \DIRECTORY_SEPARATOR, $fullClassName) . '.php'; - $dir = dirname($path); - - if ( ! is_dir($dir)) { - mkdir($dir, 0775, true); - } - - if ( ! file_exists($path)) { - file_put_contents($path, $code); - chmod($path, 0664); - } - } - - /** - * @param string $repositoryName - * - * @return \Doctrine\ORM\Tools\EntityRepositoryGenerator - */ - public function setDefaultRepositoryName($repositoryName) - { - $this->repositoryName = $repositoryName; - - return $this; - } - -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaEventArgs.php deleted file mode 100644 index ed03e32..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaEventArgs.php +++ /dev/null @@ -1,71 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Event; - -use Doctrine\Common\EventArgs; -use Doctrine\DBAL\Schema\Schema; -use Doctrine\ORM\EntityManagerInterface; - -/** - * Event Args used for the Events::postGenerateSchema event. - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.com - * @since 1.0 - * @author Benjamin Eberlei - */ -class GenerateSchemaEventArgs extends EventArgs -{ - /** - * @var \Doctrine\ORM\EntityManagerInterface - */ - private $em; - - /** - * @var \Doctrine\DBAL\Schema\Schema - */ - private $schema; - - /** - * @param EntityManagerInterface $em - * @param Schema $schema - */ - public function __construct(EntityManagerInterface $em, Schema $schema) - { - $this->em = $em; - $this->schema = $schema; - } - - /** - * @return EntityManagerInterface - */ - public function getEntityManager() - { - return $this->em; - } - - /** - * @return Schema - */ - public function getSchema() - { - return $this->schema; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaTableEventArgs.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaTableEventArgs.php deleted file mode 100644 index e2c38f9..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Event/GenerateSchemaTableEventArgs.php +++ /dev/null @@ -1,86 +0,0 @@ -. - */ -namespace Doctrine\ORM\Tools\Event; - -use Doctrine\Common\EventArgs; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\DBAL\Schema\Schema; -use Doctrine\DBAL\Schema\Table; - -/** - * Event Args used for the Events::postGenerateSchemaTable event. - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.com - * @since 1.0 - * @author Benjamin Eberlei - */ -class GenerateSchemaTableEventArgs extends EventArgs -{ - /** - * @var \Doctrine\ORM\Mapping\ClassMetadata - */ - private $classMetadata; - - /** - * @var \Doctrine\DBAL\Schema\Schema - */ - private $schema; - - /** - * @var \Doctrine\DBAL\Schema\Table - */ - private $classTable; - - /** - * @param ClassMetadata $classMetadata - * @param Schema $schema - * @param Table $classTable - */ - public function __construct(ClassMetadata $classMetadata, Schema $schema, Table $classTable) - { - $this->classMetadata = $classMetadata; - $this->schema = $schema; - $this->classTable = $classTable; - } - - /** - * @return ClassMetadata - */ - public function getClassMetadata() - { - return $this->classMetadata; - } - - /** - * @return Schema - */ - public function getSchema() - { - return $this->schema; - } - - /** - * @return Table - */ - public function getClassTable() - { - return $this->classTable; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ClassMetadataExporter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ClassMetadataExporter.php deleted file mode 100644 index 15c03b5..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ClassMetadataExporter.php +++ /dev/null @@ -1,86 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Export; - -use const E_USER_DEPRECATED; -use function trigger_error; - -/** - * Class used for converting your mapping information between the - * supported formats: yaml, xml, and php/annotation. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Jonathan Wage - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class ClassMetadataExporter -{ - /** - * @var array - */ - private static $_exporterDrivers = [ - 'xml' => Driver\XmlExporter::class, - 'yaml' => Driver\YamlExporter::class, - 'yml' => Driver\YamlExporter::class, - 'php' => Driver\PhpExporter::class, - 'annotation' => Driver\AnnotationExporter::class - ]; - - public function __construct() - { - @trigger_error(self::class . ' is deprecated and will be removed in Doctrine ORM 3.0', E_USER_DEPRECATED); - } - - /** - * Registers a new exporter driver class under a specified name. - * - * @param string $name - * @param string $class - * - * @return void - */ - public static function registerExportDriver($name, $class) - { - self::$_exporterDrivers[$name] = $class; - } - - /** - * Gets an exporter driver instance. - * - * @param string $type The type to get (yml, xml, etc.). - * @param string|null $dest The directory where the exporter will export to. - * - * @return Driver\AbstractExporter - * - * @throws ExportException - */ - public function getExporter($type, $dest = null) - { - if ( ! isset(self::$_exporterDrivers[$type])) { - throw ExportException::invalidExporterDriverType($type); - } - - $class = self::$_exporterDrivers[$type]; - - return new $class($dest); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php deleted file mode 100644 index efe8e7b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php +++ /dev/null @@ -1,275 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Export\Driver; - -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\ORM\Tools\Export\ExportException; -use const E_USER_DEPRECATED; -use function trigger_error; - -/** - * Abstract base class which is to be used for the Exporter drivers - * which can be found in \Doctrine\ORM\Tools\Export\Driver. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Jonathan Wage - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -abstract class AbstractExporter -{ - /** - * @var array - */ - protected $_metadata = []; - - /** - * @var string|null - */ - protected $_outputDir; - - /** - * @var string|null - */ - protected $_extension; - - /** - * @var bool - */ - protected $_overwriteExistingFiles = false; - - /** - * @param string|null $dir - */ - public function __construct($dir = null) - { - @trigger_error(static::class . ' is deprecated and will be removed in Doctrine ORM 3.0', E_USER_DEPRECATED); - - $this->_outputDir = $dir; - } - - /** - * @param bool $overwrite - * - * @return void - */ - public function setOverwriteExistingFiles($overwrite) - { - $this->_overwriteExistingFiles = $overwrite; - } - - /** - * Converts a single ClassMetadata instance to the exported format - * and returns it. - * - * @param ClassMetadataInfo $metadata - * - * @return string - */ - abstract public function exportClassMetadata(ClassMetadataInfo $metadata); - - /** - * Sets the array of ClassMetadataInfo instances to export. - * - * @param array $metadata - * - * @return void - */ - public function setMetadata(array $metadata) - { - $this->_metadata = $metadata; - } - - /** - * Gets the extension used to generated the path to a class. - * - * @return string|null - */ - public function getExtension() - { - return $this->_extension; - } - - /** - * Sets the directory to output the mapping files to. - * - * [php] - * $exporter = new YamlExporter($metadata); - * $exporter->setOutputDir(__DIR__ . '/yaml'); - * $exporter->export(); - * - * @param string $dir - * - * @return void - */ - public function setOutputDir($dir) - { - $this->_outputDir = $dir; - } - - /** - * Exports each ClassMetadata instance to a single Doctrine Mapping file - * named after the entity. - * - * @return void - * - * @throws \Doctrine\ORM\Tools\Export\ExportException - */ - public function export() - { - if ( ! is_dir($this->_outputDir)) { - mkdir($this->_outputDir, 0775, true); - } - - foreach ($this->_metadata as $metadata) { - // In case output is returned, write it to a file, skip otherwise - if ($output = $this->exportClassMetadata($metadata)) { - $path = $this->_generateOutputPath($metadata); - $dir = dirname($path); - if ( ! is_dir($dir)) { - mkdir($dir, 0775, true); - } - if (file_exists($path) && !$this->_overwriteExistingFiles) { - throw ExportException::attemptOverwriteExistingFile($path); - } - file_put_contents($path, $output); - chmod($path, 0664); - } - } - } - - /** - * Generates the path to write the class for the given ClassMetadataInfo instance. - * - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function _generateOutputPath(ClassMetadataInfo $metadata) - { - return $this->_outputDir . '/' . str_replace('\\', '.', $metadata->name) . $this->_extension; - } - - /** - * Sets the directory to output the mapping files to. - * - * [php] - * $exporter = new YamlExporter($metadata, __DIR__ . '/yaml'); - * $exporter->setExtension('.yml'); - * $exporter->export(); - * - * @param string $extension - * - * @return void - */ - public function setExtension($extension) - { - $this->_extension = $extension; - } - - /** - * @param int $type - * - * @return string - */ - protected function _getInheritanceTypeString($type) - { - switch ($type) { - case ClassMetadataInfo::INHERITANCE_TYPE_NONE: - return 'NONE'; - - case ClassMetadataInfo::INHERITANCE_TYPE_JOINED: - return 'JOINED'; - - case ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_TABLE: - return 'SINGLE_TABLE'; - - case ClassMetadataInfo::INHERITANCE_TYPE_TABLE_PER_CLASS: - return 'PER_CLASS'; - } - } - - /** - * @param int $mode - * - * @return string - */ - protected function _getFetchModeString($mode) - { - switch ($mode) { - case ClassMetadataInfo::FETCH_EAGER: - return 'EAGER'; - - case ClassMetadataInfo::FETCH_EXTRA_LAZY: - return 'EXTRA_LAZY'; - - case ClassMetadataInfo::FETCH_LAZY: - return 'LAZY'; - } - } - - /** - * @param int $policy - * - * @return string - */ - protected function _getChangeTrackingPolicyString($policy) - { - switch ($policy) { - case ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT: - return 'DEFERRED_IMPLICIT'; - - case ClassMetadataInfo::CHANGETRACKING_DEFERRED_EXPLICIT: - return 'DEFERRED_EXPLICIT'; - - case ClassMetadataInfo::CHANGETRACKING_NOTIFY: - return 'NOTIFY'; - } - } - - /** - * @param int $type - * - * @return string - */ - protected function _getIdGeneratorTypeString($type) - { - switch ($type) { - case ClassMetadataInfo::GENERATOR_TYPE_AUTO: - return 'AUTO'; - - case ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE: - return 'SEQUENCE'; - - case ClassMetadataInfo::GENERATOR_TYPE_TABLE: - return 'TABLE'; - - case ClassMetadataInfo::GENERATOR_TYPE_IDENTITY: - return 'IDENTITY'; - - case ClassMetadataInfo::GENERATOR_TYPE_UUID: - return 'UUID'; - - case ClassMetadataInfo::GENERATOR_TYPE_CUSTOM: - return 'CUSTOM'; - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php deleted file mode 100644 index 29cb8df..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/AnnotationExporter.php +++ /dev/null @@ -1,82 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Export\Driver; - -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\ORM\Tools\EntityGenerator; - -/** - * ClassMetadata exporter for PHP classes with annotations. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Jonathan Wage - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class AnnotationExporter extends AbstractExporter -{ - /** - * @var string - */ - protected $_extension = '.php'; - - /** - * @var EntityGenerator|null - */ - private $_entityGenerator; - - /** - * {@inheritdoc} - */ - public function exportClassMetadata(ClassMetadataInfo $metadata) - { - if ( ! $this->_entityGenerator) { - throw new \RuntimeException('For the AnnotationExporter you must set an EntityGenerator instance with the setEntityGenerator() method.'); - } - - $this->_entityGenerator->setGenerateAnnotations(true); - $this->_entityGenerator->setGenerateStubMethods(false); - $this->_entityGenerator->setRegenerateEntityIfExists(false); - $this->_entityGenerator->setUpdateEntityIfExists(false); - - return $this->_entityGenerator->generateEntityClass($metadata); - } - - /** - * @param ClassMetadataInfo $metadata - * - * @return string - */ - protected function _generateOutputPath(ClassMetadataInfo $metadata) - { - return $this->_outputDir . '/' . str_replace('\\', '/', $metadata->name) . $this->_extension; - } - - /** - * @param EntityGenerator $entityGenerator - * - * @return void - */ - public function setEntityGenerator(EntityGenerator $entityGenerator) - { - $this->_entityGenerator = $entityGenerator; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php deleted file mode 100644 index c0cd176..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/PhpExporter.php +++ /dev/null @@ -1,202 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Export\Driver; - -use Doctrine\ORM\Mapping\ClassMetadataInfo; - -/** - * ClassMetadata exporter for PHP code. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Jonathan Wage - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class PhpExporter extends AbstractExporter -{ - /** - * @var string - */ - protected $_extension = '.php'; - - /** - * {@inheritdoc} - */ - public function exportClassMetadata(ClassMetadataInfo $metadata) - { - $lines = []; - $lines[] = 'isMappedSuperclass) { - $lines[] = '$metadata->isMappedSuperclass = true;'; - } - - if ($metadata->inheritanceType) { - $lines[] = '$metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_' . $this->_getInheritanceTypeString($metadata->inheritanceType) . ');'; - } - - if ($metadata->customRepositoryClassName) { - $lines[] = "\$metadata->customRepositoryClassName = '" . $metadata->customRepositoryClassName . "';"; - } - - if ($metadata->table) { - $lines[] = '$metadata->setPrimaryTable(' . $this->_varExport($metadata->table) . ');'; - } - - if ($metadata->discriminatorColumn) { - $lines[] = '$metadata->setDiscriminatorColumn(' . $this->_varExport($metadata->discriminatorColumn) . ');'; - } - - if ($metadata->discriminatorMap) { - $lines[] = '$metadata->setDiscriminatorMap(' . $this->_varExport($metadata->discriminatorMap) . ');'; - } - - if ($metadata->changeTrackingPolicy) { - $lines[] = '$metadata->setChangeTrackingPolicy(ClassMetadataInfo::CHANGETRACKING_' . $this->_getChangeTrackingPolicyString($metadata->changeTrackingPolicy) . ');'; - } - - if ($metadata->lifecycleCallbacks) { - foreach ($metadata->lifecycleCallbacks as $event => $callbacks) { - foreach ($callbacks as $callback) { - $lines[] = "\$metadata->addLifecycleCallback('$callback', '$event');"; - } - } - } - - $lines = array_merge($lines, $this->processEntityListeners($metadata)); - - foreach ($metadata->fieldMappings as $fieldMapping) { - $lines[] = '$metadata->mapField(' . $this->_varExport($fieldMapping) . ');'; - } - - if ( ! $metadata->isIdentifierComposite && $generatorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) { - $lines[] = '$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_' . $generatorType . ');'; - } - - foreach ($metadata->associationMappings as $associationMapping) { - $cascade = ['remove', 'persist', 'refresh', 'merge', 'detach']; - foreach ($cascade as $key => $value) { - if ( ! $associationMapping['isCascade'.ucfirst($value)]) { - unset($cascade[$key]); - } - } - - if (count($cascade) === 5) { - $cascade = ['all']; - } - - $method = null; - $associationMappingArray = [ - 'fieldName' => $associationMapping['fieldName'], - 'targetEntity' => $associationMapping['targetEntity'], - 'cascade' => $cascade, - ]; - - if (isset($associationMapping['fetch'])) { - $associationMappingArray['fetch'] = $associationMapping['fetch']; - } - - if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) { - $method = 'mapOneToOne'; - $oneToOneMappingArray = [ - 'mappedBy' => $associationMapping['mappedBy'], - 'inversedBy' => $associationMapping['inversedBy'], - 'joinColumns' => $associationMapping['isOwningSide'] ? $associationMapping['joinColumns'] : [], - 'orphanRemoval' => $associationMapping['orphanRemoval'], - ]; - - $associationMappingArray = array_merge($associationMappingArray, $oneToOneMappingArray); - } elseif ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) { - $method = 'mapOneToMany'; - $potentialAssociationMappingIndexes = [ - 'mappedBy', - 'orphanRemoval', - 'orderBy', - ]; - $oneToManyMappingArray = []; - foreach ($potentialAssociationMappingIndexes as $index) { - if (isset($associationMapping[$index])) { - $oneToManyMappingArray[$index] = $associationMapping[$index]; - } - } - $associationMappingArray = array_merge($associationMappingArray, $oneToManyMappingArray); - } elseif ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_MANY) { - $method = 'mapManyToMany'; - $potentialAssociationMappingIndexes = [ - 'mappedBy', - 'joinTable', - 'orderBy', - ]; - $manyToManyMappingArray = []; - foreach ($potentialAssociationMappingIndexes as $index) { - if (isset($associationMapping[$index])) { - $manyToManyMappingArray[$index] = $associationMapping[$index]; - } - } - $associationMappingArray = array_merge($associationMappingArray, $manyToManyMappingArray); - } - - $lines[] = '$metadata->' . $method . '(' . $this->_varExport($associationMappingArray) . ');'; - } - - return implode("\n", $lines); - } - - /** - * @param mixed $var - * - * @return string - */ - protected function _varExport($var) - { - $export = var_export($var, true); - $export = str_replace("\n", PHP_EOL . str_repeat(' ', 8), $export); - $export = str_replace(' ', ' ', $export); - $export = str_replace('array (', 'array(', $export); - $export = str_replace('array( ', 'array(', $export); - $export = str_replace(',)', ')', $export); - $export = str_replace(', )', ')', $export); - $export = str_replace(' ', ' ', $export); - - return $export; - } - - private function processEntityListeners(ClassMetadataInfo $metadata) : array - { - $lines = []; - - foreach ($metadata->entityListeners as $event => $entityListenerConfig) { - foreach ($entityListenerConfig as $entityListener) { - $lines[] = \sprintf( - '$metadata->addEntityListener(%s, %s, %s);', - \var_export($event, true), - \var_export($entityListener['class'], true), - \var_export($entityListener['method'], true) - ); - } - } - - return $lines; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php deleted file mode 100644 index 6503649..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/XmlExporter.php +++ /dev/null @@ -1,496 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Export\Driver; - -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use SimpleXMLElement; - -/** - * ClassMetadata exporter for Doctrine XML mapping files. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Jonathan Wage - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class XmlExporter extends AbstractExporter -{ - /** - * @var string - */ - protected $_extension = '.dcm.xml'; - - /** - * {@inheritdoc} - */ - public function exportClassMetadata(ClassMetadataInfo $metadata) - { - $xml = new SimpleXmlElement(''); - - if ($metadata->isMappedSuperclass) { - $root = $xml->addChild('mapped-superclass'); - } else { - $root = $xml->addChild('entity'); - } - - if ($metadata->customRepositoryClassName) { - $root->addAttribute('repository-class', $metadata->customRepositoryClassName); - } - - $root->addAttribute('name', $metadata->name); - - if (isset($metadata->table['name'])) { - $root->addAttribute('table', $metadata->table['name']); - } - - if (isset($metadata->table['schema'])) { - $root->addAttribute('schema', $metadata->table['schema']); - } - - if ($metadata->inheritanceType && $metadata->inheritanceType !== ClassMetadataInfo::INHERITANCE_TYPE_NONE) { - $root->addAttribute('inheritance-type', $this->_getInheritanceTypeString($metadata->inheritanceType)); - } - - if (isset($metadata->table['options'])) { - $optionsXml = $root->addChild('options'); - - $this->exportTableOptions($optionsXml, $metadata->table['options']); - } - - if ($metadata->discriminatorColumn) { - $discriminatorColumnXml = $root->addChild('discriminator-column'); - $discriminatorColumnXml->addAttribute('name', $metadata->discriminatorColumn['name']); - $discriminatorColumnXml->addAttribute('type', $metadata->discriminatorColumn['type']); - - if (isset($metadata->discriminatorColumn['length'])) { - $discriminatorColumnXml->addAttribute('length', $metadata->discriminatorColumn['length']); - } - } - - if ($metadata->discriminatorMap) { - $discriminatorMapXml = $root->addChild('discriminator-map'); - - foreach ($metadata->discriminatorMap as $value => $className) { - $discriminatorMappingXml = $discriminatorMapXml->addChild('discriminator-mapping'); - $discriminatorMappingXml->addAttribute('value', $value); - $discriminatorMappingXml->addAttribute('class', $className); - } - } - - $trackingPolicy = $this->_getChangeTrackingPolicyString($metadata->changeTrackingPolicy); - - if ( $trackingPolicy != 'DEFERRED_IMPLICIT') { - $root->addChild('change-tracking-policy', $trackingPolicy); - } - - if (isset($metadata->table['indexes'])) { - $indexesXml = $root->addChild('indexes'); - - foreach ($metadata->table['indexes'] as $name => $index) { - $indexXml = $indexesXml->addChild('index'); - $indexXml->addAttribute('name', $name); - $indexXml->addAttribute('columns', implode(',', $index['columns'])); - if (isset($index['flags'])) { - $indexXml->addAttribute('flags', implode(',', $index['flags'])); - } - } - } - - if (isset($metadata->table['uniqueConstraints'])) { - $uniqueConstraintsXml = $root->addChild('unique-constraints'); - - foreach ($metadata->table['uniqueConstraints'] as $name => $unique) { - $uniqueConstraintXml = $uniqueConstraintsXml->addChild('unique-constraint'); - $uniqueConstraintXml->addAttribute('name', $name); - $uniqueConstraintXml->addAttribute('columns', implode(',', $unique['columns'])); - } - } - - $fields = $metadata->fieldMappings; - - $id = []; - foreach ($fields as $name => $field) { - if (isset($field['id']) && $field['id']) { - $id[$name] = $field; - unset($fields[$name]); - } - } - - foreach ($metadata->associationMappings as $name => $assoc) { - if (isset($assoc['id']) && $assoc['id']) { - $id[$name] = [ - 'fieldName' => $name, - 'associationKey' => true - ]; - } - } - - if ( ! $metadata->isIdentifierComposite && $idGeneratorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) { - $id[$metadata->getSingleIdentifierFieldName()]['generator']['strategy'] = $idGeneratorType; - } - - if ($id) { - foreach ($id as $field) { - $idXml = $root->addChild('id'); - $idXml->addAttribute('name', $field['fieldName']); - - if (isset($field['type'])) { - $idXml->addAttribute('type', $field['type']); - } - - if (isset($field['columnName'])) { - $idXml->addAttribute('column', $field['columnName']); - } - - if (isset($field['length'])) { - $idXml->addAttribute('length', $field['length']); - } - - if (isset($field['associationKey']) && $field['associationKey']) { - $idXml->addAttribute('association-key', 'true'); - } - - if ($idGeneratorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) { - $generatorXml = $idXml->addChild('generator'); - $generatorXml->addAttribute('strategy', $idGeneratorType); - - $this->exportSequenceInformation($idXml, $metadata); - } - } - } - - if ($fields) { - foreach ($fields as $field) { - $fieldXml = $root->addChild('field'); - $fieldXml->addAttribute('name', $field['fieldName']); - $fieldXml->addAttribute('type', $field['type']); - - if (isset($field['columnName'])) { - $fieldXml->addAttribute('column', $field['columnName']); - } - - if (isset($field['length'])) { - $fieldXml->addAttribute('length', $field['length']); - } - - if (isset($field['precision'])) { - $fieldXml->addAttribute('precision', $field['precision']); - } - - if (isset($field['scale'])) { - $fieldXml->addAttribute('scale', $field['scale']); - } - - if (isset($field['unique']) && $field['unique']) { - $fieldXml->addAttribute('unique', $field['unique'] ? 'true' : 'false'); - } - - if (isset($field['options'])) { - $optionsXml = $fieldXml->addChild('options'); - foreach ($field['options'] as $key => $value) { - $optionXml = $optionsXml->addChild('option', $value); - $optionXml->addAttribute('name', $key); - } - } - - if (isset($field['version'])) { - $fieldXml->addAttribute('version', $field['version']); - } - - if (isset($field['columnDefinition'])) { - $fieldXml->addAttribute('column-definition', $field['columnDefinition']); - } - - if (isset($field['nullable'])) { - $fieldXml->addAttribute('nullable', $field['nullable'] ? 'true' : 'false'); - } - } - } - - $orderMap = [ - ClassMetadataInfo::ONE_TO_ONE, - ClassMetadataInfo::ONE_TO_MANY, - ClassMetadataInfo::MANY_TO_ONE, - ClassMetadataInfo::MANY_TO_MANY, - ]; - - uasort($metadata->associationMappings, function($m1, $m2) use (&$orderMap){ - $a1 = array_search($m1['type'], $orderMap); - $a2 = array_search($m2['type'], $orderMap); - - return strcmp($a1, $a2); - }); - - foreach ($metadata->associationMappings as $associationMapping) { - $associationMappingXml = null; - if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_ONE) { - $associationMappingXml = $root->addChild('one-to-one'); - } elseif ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_ONE) { - $associationMappingXml = $root->addChild('many-to-one'); - } elseif ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) { - $associationMappingXml = $root->addChild('one-to-many'); - } elseif ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_MANY) { - $associationMappingXml = $root->addChild('many-to-many'); - } - - $associationMappingXml->addAttribute('field', $associationMapping['fieldName']); - $associationMappingXml->addAttribute('target-entity', $associationMapping['targetEntity']); - - if (isset($associationMapping['mappedBy'])) { - $associationMappingXml->addAttribute('mapped-by', $associationMapping['mappedBy']); - } - - if (isset($associationMapping['inversedBy'])) { - $associationMappingXml->addAttribute('inversed-by', $associationMapping['inversedBy']); - } - - if (isset($associationMapping['indexBy'])) { - $associationMappingXml->addAttribute('index-by', $associationMapping['indexBy']); - } - - if (isset($associationMapping['orphanRemoval']) && $associationMapping['orphanRemoval'] !== false) { - $associationMappingXml->addAttribute('orphan-removal', 'true'); - } - - if (isset($associationMapping['fetch'])) { - $associationMappingXml->addAttribute('fetch', $this->_getFetchModeString($associationMapping['fetch'])); - } - - $cascade = []; - if ($associationMapping['isCascadeRemove']) { - $cascade[] = 'cascade-remove'; - } - - if ($associationMapping['isCascadePersist']) { - $cascade[] = 'cascade-persist'; - } - - if ($associationMapping['isCascadeRefresh']) { - $cascade[] = 'cascade-refresh'; - } - - if ($associationMapping['isCascadeMerge']) { - $cascade[] = 'cascade-merge'; - } - - if ($associationMapping['isCascadeDetach']) { - $cascade[] = 'cascade-detach'; - } - - if (count($cascade) === 5) { - $cascade = ['cascade-all']; - } - - if ($cascade) { - $cascadeXml = $associationMappingXml->addChild('cascade'); - - foreach ($cascade as $type) { - $cascadeXml->addChild($type); - } - } - - if (isset($associationMapping['joinTable']) && $associationMapping['joinTable']) { - $joinTableXml = $associationMappingXml->addChild('join-table'); - $joinTableXml->addAttribute('name', $associationMapping['joinTable']['name']); - $joinColumnsXml = $joinTableXml->addChild('join-columns'); - - foreach ($associationMapping['joinTable']['joinColumns'] as $joinColumn) { - $joinColumnXml = $joinColumnsXml->addChild('join-column'); - $joinColumnXml->addAttribute('name', $joinColumn['name']); - $joinColumnXml->addAttribute('referenced-column-name', $joinColumn['referencedColumnName']); - - if (isset($joinColumn['onDelete'])) { - $joinColumnXml->addAttribute('on-delete', $joinColumn['onDelete']); - } - } - - $inverseJoinColumnsXml = $joinTableXml->addChild('inverse-join-columns'); - - foreach ($associationMapping['joinTable']['inverseJoinColumns'] as $inverseJoinColumn) { - $inverseJoinColumnXml = $inverseJoinColumnsXml->addChild('join-column'); - $inverseJoinColumnXml->addAttribute('name', $inverseJoinColumn['name']); - $inverseJoinColumnXml->addAttribute('referenced-column-name', $inverseJoinColumn['referencedColumnName']); - - if (isset($inverseJoinColumn['onDelete'])) { - $inverseJoinColumnXml->addAttribute('on-delete', $inverseJoinColumn['onDelete']); - } - - if (isset($inverseJoinColumn['columnDefinition'])) { - $inverseJoinColumnXml->addAttribute('column-definition', $inverseJoinColumn['columnDefinition']); - } - - if (isset($inverseJoinColumn['nullable'])) { - $inverseJoinColumnXml->addAttribute('nullable', $inverseJoinColumn['nullable']); - } - - if (isset($inverseJoinColumn['orderBy'])) { - $inverseJoinColumnXml->addAttribute('order-by', $inverseJoinColumn['orderBy']); - } - } - } - if (isset($associationMapping['joinColumns'])) { - $joinColumnsXml = $associationMappingXml->addChild('join-columns'); - - foreach ($associationMapping['joinColumns'] as $joinColumn) { - $joinColumnXml = $joinColumnsXml->addChild('join-column'); - $joinColumnXml->addAttribute('name', $joinColumn['name']); - $joinColumnXml->addAttribute('referenced-column-name', $joinColumn['referencedColumnName']); - - if (isset($joinColumn['onDelete'])) { - $joinColumnXml->addAttribute('on-delete', $joinColumn['onDelete']); - } - - if (isset($joinColumn['columnDefinition'])) { - $joinColumnXml->addAttribute('column-definition', $joinColumn['columnDefinition']); - } - - if (isset($joinColumn['nullable'])) { - $joinColumnXml->addAttribute('nullable', $joinColumn['nullable']); - } - } - } - if (isset($associationMapping['orderBy'])) { - $orderByXml = $associationMappingXml->addChild('order-by'); - - foreach ($associationMapping['orderBy'] as $name => $direction) { - $orderByFieldXml = $orderByXml->addChild('order-by-field'); - $orderByFieldXml->addAttribute('name', $name); - $orderByFieldXml->addAttribute('direction', $direction); - } - } - } - - if (isset($metadata->lifecycleCallbacks) && count($metadata->lifecycleCallbacks)>0) { - $lifecycleCallbacksXml = $root->addChild('lifecycle-callbacks'); - - foreach ($metadata->lifecycleCallbacks as $name => $methods) { - foreach ($methods as $method) { - $lifecycleCallbackXml = $lifecycleCallbacksXml->addChild('lifecycle-callback'); - $lifecycleCallbackXml->addAttribute('type', $name); - $lifecycleCallbackXml->addAttribute('method', $method); - } - } - } - - $this->processEntityListeners($metadata, $root); - - return $this->_asXml($xml); - } - - /** - * Exports (nested) option elements. - * - * @param SimpleXMLElement $parentXml - * @param array $options - */ - private function exportTableOptions(SimpleXMLElement $parentXml, array $options) : void - { - foreach ($options as $name => $option) { - $isArray = is_array($option); - $optionXml = $isArray - ? $parentXml->addChild('option') - : $parentXml->addChild('option', (string) $option); - - $optionXml->addAttribute('name', (string) $name); - - if ($isArray) { - $this->exportTableOptions($optionXml, $option); - } - } - } - - /** - * Export sequence information (if available/configured) into the current identifier XML node - * - * @param SimpleXMLElement $identifierXmlNode - * @param ClassMetadataInfo $metadata - * - * @return void - */ - private function exportSequenceInformation(SimpleXMLElement $identifierXmlNode, ClassMetadataInfo $metadata) : void - { - $sequenceDefinition = $metadata->sequenceGeneratorDefinition; - - if (! ($metadata->generatorType === ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE && $sequenceDefinition)) { - return; - } - - $sequenceGeneratorXml = $identifierXmlNode->addChild('sequence-generator'); - - $sequenceGeneratorXml->addAttribute('sequence-name', $sequenceDefinition['sequenceName']); - $sequenceGeneratorXml->addAttribute('allocation-size', $sequenceDefinition['allocationSize']); - $sequenceGeneratorXml->addAttribute('initial-value', $sequenceDefinition['initialValue']); - } - - private function _asXml(SimpleXMLElement $simpleXml) : string - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->loadXML($simpleXml->asXML()); - $dom->formatOutput = true; - - return $dom->saveXML(); - } - - private function processEntityListeners(ClassMetadataInfo $metadata, SimpleXMLElement $root): void - { - if (0 === \count($metadata->entityListeners)) { - return; - } - - $entityListenersXml = $root->addChild('entity-listeners'); - $entityListenersXmlMap = []; - - $this->generateEntityListenerXml($metadata, $entityListenersXmlMap, $entityListenersXml); - } - - private function generateEntityListenerXml(ClassMetadataInfo $metadata, array $entityListenersXmlMap, SimpleXMLElement $entityListenersXml): void - { - foreach ($metadata->entityListeners as $event => $entityListenerConfig) { - foreach ($entityListenerConfig as $entityListener) { - $entityListenerXml = $this->addClassToMapIfExists( - $entityListenersXmlMap, - $entityListener, - $entityListenersXml - ); - - $entityListenerCallbackXml = $entityListenerXml->addChild('lifecycle-callback'); - $entityListenerCallbackXml->addAttribute('type', $event); - $entityListenerCallbackXml->addAttribute('method', $entityListener['method']); - } - } - } - - private function addClassToMapIfExists(array $entityListenersXmlMap, array $entityListener, SimpleXMLElement $entityListenersXml): SimpleXMLElement - { - if (isset($entityListenersXmlMap[$entityListener['class']])) { - return $entityListenersXmlMap[$entityListener['class']]; - } - - $entityListenerXml = $entityListenersXml->addChild('entity-listener'); - $entityListenerXml->addAttribute('class', $entityListener['class']); - $entityListenersXmlMap[$entityListener['class']] = $entityListenerXml; - - return $entityListenerXml; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php deleted file mode 100644 index 1fb960b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/Driver/YamlExporter.php +++ /dev/null @@ -1,268 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Export\Driver; - -use Symfony\Component\Yaml\Yaml; -use Doctrine\ORM\Mapping\ClassMetadataInfo; - -/** - * ClassMetadata exporter for Doctrine YAML mapping files. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Jonathan Wage - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class YamlExporter extends AbstractExporter -{ - /** - * @var string - */ - protected $_extension = '.dcm.yml'; - - /** - * {@inheritdoc} - */ - public function exportClassMetadata(ClassMetadataInfo $metadata) - { - $array = []; - - if ($metadata->isMappedSuperclass) { - $array['type'] = 'mappedSuperclass'; - } else { - $array['type'] = 'entity'; - } - $metadataTable = $metadata->table ?? ['name' => null]; - - $array['table'] = $metadataTable['name']; - - if (isset($metadataTable['schema'])) { - $array['schema'] = $metadataTable['schema']; - } - - $inheritanceType = $metadata->inheritanceType; - - if ($inheritanceType !== ClassMetadataInfo::INHERITANCE_TYPE_NONE) { - $array['inheritanceType'] = $this->_getInheritanceTypeString($inheritanceType); - } - - if ($column = $metadata->discriminatorColumn) { - $array['discriminatorColumn'] = $column; - } - - if ($map = $metadata->discriminatorMap) { - $array['discriminatorMap'] = $map; - } - - if ($metadata->changeTrackingPolicy !== ClassMetadataInfo::CHANGETRACKING_DEFERRED_IMPLICIT) { - $array['changeTrackingPolicy'] = $this->_getChangeTrackingPolicyString($metadata->changeTrackingPolicy); - } - - if (isset($metadataTable['indexes'])) { - $array['indexes'] = $metadataTable['indexes']; - } - - if ($metadata->customRepositoryClassName) { - $array['repositoryClass'] = $metadata->customRepositoryClassName; - } - - if (isset($metadataTable['uniqueConstraints'])) { - $array['uniqueConstraints'] = $metadataTable['uniqueConstraints']; - } - - if (isset($metadataTable['options'])) { - $array['options'] = $metadataTable['options']; - } - - $fieldMappings = $metadata->fieldMappings; - - $ids = []; - foreach ($fieldMappings as $name => $fieldMapping) { - $fieldMapping['column'] = $fieldMapping['columnName']; - - unset($fieldMapping['columnName'], $fieldMapping['fieldName']); - - if ($fieldMapping['column'] == $name) { - unset($fieldMapping['column']); - } - - if (isset($fieldMapping['id']) && $fieldMapping['id']) { - $ids[$name] = $fieldMapping; - unset($fieldMappings[$name]); - continue; - } - - $fieldMappings[$name] = $fieldMapping; - } - - if ( ! $metadata->isIdentifierComposite && $idGeneratorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) { - $ids[$metadata->getSingleIdentifierFieldName()]['generator']['strategy'] = $idGeneratorType; - } - - $array['id'] = $ids; - - if ($fieldMappings) { - if ( ! isset($array['fields'])) { - $array['fields'] = []; - } - $array['fields'] = array_merge($array['fields'], $fieldMappings); - } - - foreach ($metadata->associationMappings as $name => $associationMapping) { - $cascade = []; - - if ($associationMapping['isCascadeRemove']) { - $cascade[] = 'remove'; - } - - if ($associationMapping['isCascadePersist']) { - $cascade[] = 'persist'; - } - - if ($associationMapping['isCascadeRefresh']) { - $cascade[] = 'refresh'; - } - - if ($associationMapping['isCascadeMerge']) { - $cascade[] = 'merge'; - } - - if ($associationMapping['isCascadeDetach']) { - $cascade[] = 'detach'; - } - if (count($cascade) === 5) { - $cascade = ['all']; - } - - $associationMappingArray = [ - 'targetEntity' => $associationMapping['targetEntity'], - 'cascade' => $cascade, - ]; - - if (isset($associationMapping['fetch'])) { - $associationMappingArray['fetch'] = $this->_getFetchModeString($associationMapping['fetch']); - } - - if (isset($associationMapping['id']) && $associationMapping['id'] === true) { - $array['id'][$name]['associationKey'] = true; - } - - if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) { - $joinColumns = $associationMapping['isOwningSide'] ? $associationMapping['joinColumns'] : []; - $newJoinColumns = []; - - foreach ($joinColumns as $joinColumn) { - $newJoinColumns[$joinColumn['name']]['referencedColumnName'] = $joinColumn['referencedColumnName']; - - if (isset($joinColumn['onDelete'])) { - $newJoinColumns[$joinColumn['name']]['onDelete'] = $joinColumn['onDelete']; - } - } - - $oneToOneMappingArray = [ - 'mappedBy' => $associationMapping['mappedBy'], - 'inversedBy' => $associationMapping['inversedBy'], - 'joinColumns' => $newJoinColumns, - 'orphanRemoval' => $associationMapping['orphanRemoval'], - ]; - - $associationMappingArray = array_merge($associationMappingArray, $oneToOneMappingArray); - - if ($associationMapping['type'] & ClassMetadataInfo::ONE_TO_ONE) { - $array['oneToOne'][$name] = $associationMappingArray; - } else { - $array['manyToOne'][$name] = $associationMappingArray; - } - } elseif ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) { - $oneToManyMappingArray = [ - 'mappedBy' => $associationMapping['mappedBy'], - 'inversedBy' => $associationMapping['inversedBy'], - 'orphanRemoval' => $associationMapping['orphanRemoval'], - 'orderBy' => $associationMapping['orderBy'] ?? null - ]; - - $associationMappingArray = array_merge($associationMappingArray, $oneToManyMappingArray); - $array['oneToMany'][$name] = $associationMappingArray; - } elseif ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_MANY) { - $manyToManyMappingArray = [ - 'mappedBy' => $associationMapping['mappedBy'], - 'inversedBy' => $associationMapping['inversedBy'], - 'joinTable' => $associationMapping['joinTable'] ?? null, - 'orderBy' => $associationMapping['orderBy'] ?? null - ]; - - $associationMappingArray = array_merge($associationMappingArray, $manyToManyMappingArray); - $array['manyToMany'][$name] = $associationMappingArray; - } - } - if (isset($metadata->lifecycleCallbacks)) { - $array['lifecycleCallbacks'] = $metadata->lifecycleCallbacks; - } - - $array = $this->processEntityListeners($metadata, $array); - - return $this->yamlDump([$metadata->name => $array], 10); - } - - /** - * Dumps a PHP array to a YAML string. - * - * The yamlDump 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 [optional] The level where you switch to inline YAML - * - * @return string A YAML string representing the original PHP array - */ - protected function yamlDump($array, $inline = 2) - { - return Yaml::dump($array, $inline); - } - - private function processEntityListeners(ClassMetadataInfo $metadata, array $array) : array - { - if (0 === \count($metadata->entityListeners)) { - return $array; - } - - $array['entityListeners'] = []; - - foreach ($metadata->entityListeners as $event => $entityListenerConfig) { - $array = $this->processEntityListenerConfig($array, $entityListenerConfig, $event); - } - - return $array; - } - - private function processEntityListenerConfig(array $array, array $entityListenerConfig, string $event) : array - { - foreach ($entityListenerConfig as $entityListener) { - if (! isset($array['entityListeners'][$entityListener['class']])) { - $array['entityListeners'][$entityListener['class']] = []; - } - - $array['entityListeners'][$entityListener['class']][$event] = [$entityListener['method']]; - } - - return $array; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ExportException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ExportException.php deleted file mode 100644 index 725ea21..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Export/ExportException.php +++ /dev/null @@ -1,58 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Export; - -use Doctrine\ORM\ORMException; - -/** - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class ExportException extends ORMException -{ - /** - * @param string $type - * - * @return ExportException - */ - public static function invalidExporterDriverType($type) - { - return new self("The specified export driver '$type' does not exist"); - } - - /** - * @param string $type - * - * @return ExportException - */ - public static function invalidMappingDriverType($type) - { - return new self("The mapping driver '$type' does not exist"); - } - - /** - * @param string $file - * - * @return ExportException - */ - public static function attemptOverwriteExistingFile($file) - { - return new self("Attempting to overwrite an existing file '".$file."'."); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php deleted file mode 100644 index f3db053..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php +++ /dev/null @@ -1,154 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Pagination; - -use Doctrine\ORM\Query\SqlWalker; -use Doctrine\ORM\Query\AST\SelectStatement; - -/** - * Wraps the query in order to accurately count the root objects. - * - * Given a DQL like `SELECT u FROM User u` it will generate an SQL query like: - * SELECT COUNT(*) (SELECT DISTINCT FROM ()) - * - * Works with composite keys but cannot deal with queries that have multiple - * root entities (e.g. `SELECT f, b from Foo, Bar`) - * - * @author Sander Marechal - */ -class CountOutputWalker extends SqlWalker -{ - /** - * @var \Doctrine\DBAL\Platforms\AbstractPlatform - */ - private $platform; - - /** - * @var \Doctrine\ORM\Query\ResultSetMapping - */ - private $rsm; - - /** - * @var array - */ - private $queryComponents; - - /** - * Constructor. - * - * Stores various parameters that are otherwise unavailable - * because Doctrine\ORM\Query\SqlWalker keeps everything private without - * accessors. - * - * @param \Doctrine\ORM\Query $query - * @param \Doctrine\ORM\Query\ParserResult $parserResult - * @param array $queryComponents - */ - public function __construct($query, $parserResult, array $queryComponents) - { - $this->platform = $query->getEntityManager()->getConnection()->getDatabasePlatform(); - $this->rsm = $parserResult->getResultSetMapping(); - $this->queryComponents = $queryComponents; - - parent::__construct($query, $parserResult, $queryComponents); - } - - /** - * Walks down a SelectStatement AST node, wrapping it in a COUNT (SELECT DISTINCT). - * - * Note that the ORDER BY clause is not removed. Many SQL implementations (e.g. MySQL) - * are able to cache subqueries. By keeping the ORDER BY clause intact, the limitSubQuery - * that will most likely be executed next can be read from the native SQL cache. - * - * @param SelectStatement $AST - * - * @return string - * - * @throws \RuntimeException - */ - public function walkSelectStatement(SelectStatement $AST) - { - if ($this->platform->getName() === "mssql") { - $AST->orderByClause = null; - } - - $sql = parent::walkSelectStatement($AST); - - if ($AST->groupByClause) { - return sprintf( - 'SELECT %s AS dctrn_count FROM (%s) dctrn_table', - $this->platform->getCountExpression('*'), - $sql - ); - } - - // Find out the SQL alias of the identifier column of the root entity - // It may be possible to make this work with multiple root entities but that - // would probably require issuing multiple queries or doing a UNION SELECT - // so for now, It's not supported. - - // Get the root entity and alias from the AST fromClause - $from = $AST->fromClause->identificationVariableDeclarations; - if (count($from) > 1) { - throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); - } - - $fromRoot = reset($from); - $rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable; - $rootClass = $this->queryComponents[$rootAlias]['metadata']; - $rootIdentifier = $rootClass->identifier; - - // For every identifier, find out the SQL alias by combing through the ResultSetMapping - $sqlIdentifier = []; - foreach ($rootIdentifier as $property) { - if (isset($rootClass->fieldMappings[$property])) { - foreach (array_keys($this->rsm->fieldMappings, $property) as $alias) { - if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { - $sqlIdentifier[$property] = $alias; - } - } - } - - if (isset($rootClass->associationMappings[$property])) { - $joinColumn = $rootClass->associationMappings[$property]['joinColumns'][0]['name']; - - foreach (array_keys($this->rsm->metaMappings, $joinColumn) as $alias) { - if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { - $sqlIdentifier[$property] = $alias; - } - } - } - } - - if (count($rootIdentifier) != count($sqlIdentifier)) { - throw new \RuntimeException(sprintf( - 'Not all identifier properties can be found in the ResultSetMapping: %s', - implode(', ', array_diff($rootIdentifier, array_keys($sqlIdentifier))) - )); - } - - // Build the counter query - return sprintf('SELECT %s AS dctrn_count FROM (SELECT DISTINCT %s FROM (%s) dctrn_result) dctrn_table', - $this->platform->getCountExpression('*'), - implode(', ', $sqlIdentifier), - $sql - ); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountWalker.php deleted file mode 100644 index a8f2600..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/CountWalker.php +++ /dev/null @@ -1,94 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Pagination; - -use Doctrine\ORM\Query\TreeWalkerAdapter; -use Doctrine\ORM\Query\AST\SelectStatement; -use Doctrine\ORM\Query\AST\SelectExpression; -use Doctrine\ORM\Query\AST\PathExpression; -use Doctrine\ORM\Query\AST\AggregateExpression; - -/** - * Replaces the selectClause of the AST with a COUNT statement. - * - * @category DoctrineExtensions - * @package DoctrineExtensions\Paginate - * @author David Abdemoulaie - * @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/) - * @license http://hobodave.com/license.txt New BSD License - */ -class CountWalker extends TreeWalkerAdapter -{ - /** - * Distinct mode hint name. - */ - const HINT_DISTINCT = 'doctrine_paginator.distinct'; - - /** - * Walks down a SelectStatement AST node, modifying it to retrieve a COUNT. - * - * @param SelectStatement $AST - * - * @return void - * - * @throws \RuntimeException - */ - public function walkSelectStatement(SelectStatement $AST) - { - if ($AST->havingClause) { - throw new \RuntimeException('Cannot count query that uses a HAVING clause. Use the output walkers for pagination'); - } - - $queryComponents = $this->_getQueryComponents(); - // Get the root entity and alias from the AST fromClause - $from = $AST->fromClause->identificationVariableDeclarations; - - if (count($from) > 1) { - throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); - } - - $fromRoot = reset($from); - $rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable; - $rootClass = $queryComponents[$rootAlias]['metadata']; - $identifierFieldName = $rootClass->getSingleIdentifierFieldName(); - - $pathType = PathExpression::TYPE_STATE_FIELD; - if (isset($rootClass->associationMappings[$identifierFieldName])) { - $pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION; - } - - $pathExpression = new PathExpression( - PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $rootAlias, - $identifierFieldName - ); - $pathExpression->type = $pathType; - - $distinct = $this->_getQuery()->getHint(self::HINT_DISTINCT); - $AST->selectClause->selectExpressions = [ - new SelectExpression( - new AggregateExpression('count', $pathExpression, $distinct), null - ) - ]; - - // ORDER BY is not needed, only increases query execution through unnecessary sorting. - $AST->orderByClause = null; - } -} - diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php deleted file mode 100644 index 034b33b..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php +++ /dev/null @@ -1,605 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Pagination; - -use Doctrine\DBAL\Platforms\DB2Platform; -use Doctrine\DBAL\Platforms\OraclePlatform; -use Doctrine\DBAL\Platforms\PostgreSqlPlatform; -use Doctrine\DBAL\Platforms\SQLAnywherePlatform; -use Doctrine\DBAL\Platforms\SQLServerPlatform; -use Doctrine\ORM\Query\AST\OrderByClause; -use Doctrine\ORM\Query\AST\PartialObjectExpression; -use Doctrine\ORM\Query\AST\SelectExpression; -use Doctrine\ORM\Query\SqlWalker; -use Doctrine\ORM\Query\AST\SelectStatement; - -/** - * Wraps the query in order to select root entity IDs for pagination. - * - * Given a DQL like `SELECT u FROM User u` it will generate an SQL query like: - * SELECT DISTINCT FROM () LIMIT x OFFSET y - * - * Works with composite keys but cannot deal with queries that have multiple - * root entities (e.g. `SELECT f, b from Foo, Bar`) - * - * @author Sander Marechal - */ -class LimitSubqueryOutputWalker extends SqlWalker -{ - private const ORDER_BY_PATH_EXPRESSION = '/(?platform = $query->getEntityManager()->getConnection()->getDatabasePlatform(); - $this->rsm = $parserResult->getResultSetMapping(); - $this->queryComponents = $queryComponents; - - // Reset limit and offset - $this->firstResult = $query->getFirstResult(); - $this->maxResults = $query->getMaxResults(); - $query->setFirstResult(null)->setMaxResults(null); - - $this->em = $query->getEntityManager(); - $this->quoteStrategy = $this->em->getConfiguration()->getQuoteStrategy(); - - parent::__construct($query, $parserResult, $queryComponents); - } - - /** - * Check if the platform supports the ROW_NUMBER window function. - * - * @return bool - */ - private function platformSupportsRowNumber() - { - return $this->platform instanceof PostgreSqlPlatform - || $this->platform instanceof SQLServerPlatform - || $this->platform instanceof OraclePlatform - || $this->platform instanceof SQLAnywherePlatform - || $this->platform instanceof DB2Platform - || (method_exists($this->platform, 'supportsRowNumberFunction') - && $this->platform->supportsRowNumberFunction()); - } - - /** - * Rebuilds a select statement's order by clause for use in a - * ROW_NUMBER() OVER() expression. - * - * @param SelectStatement $AST - */ - private function rebuildOrderByForRowNumber(SelectStatement $AST) - { - $orderByClause = $AST->orderByClause; - $selectAliasToExpressionMap = []; - // Get any aliases that are available for select expressions. - foreach ($AST->selectClause->selectExpressions as $selectExpression) { - $selectAliasToExpressionMap[$selectExpression->fieldIdentificationVariable] = $selectExpression->expression; - } - - // Rebuild string orderby expressions to use the select expression they're referencing - foreach ($orderByClause->orderByItems as $orderByItem) { - if (is_string($orderByItem->expression) && isset($selectAliasToExpressionMap[$orderByItem->expression])) { - $orderByItem->expression = $selectAliasToExpressionMap[$orderByItem->expression]; - } - } - $func = new RowNumberOverFunction('dctrn_rownum'); - $func->orderByClause = $AST->orderByClause; - $AST->selectClause->selectExpressions[] = new SelectExpression($func, 'dctrn_rownum', true); - - // No need for an order by clause, we'll order by rownum in the outer query. - $AST->orderByClause = null; - } - - /** - * Walks down a SelectStatement AST node, wrapping it in a SELECT DISTINCT. - * - * @param SelectStatement $AST - * - * @return string - * - * @throws \RuntimeException - */ - public function walkSelectStatement(SelectStatement $AST) - { - if ($this->platformSupportsRowNumber()) { - return $this->walkSelectStatementWithRowNumber($AST); - } - return $this->walkSelectStatementWithoutRowNumber($AST); - } - - /** - * Walks down a SelectStatement AST node, wrapping it in a SELECT DISTINCT. - * This method is for use with platforms which support ROW_NUMBER. - * - * @param SelectStatement $AST - * - * @return string - * - * @throws \RuntimeException - */ - public function walkSelectStatementWithRowNumber(SelectStatement $AST) - { - $hasOrderBy = false; - $outerOrderBy = ' ORDER BY dctrn_minrownum ASC'; - $orderGroupBy = ''; - if ($AST->orderByClause instanceof OrderByClause) { - $hasOrderBy = true; - $this->rebuildOrderByForRowNumber($AST); - } - - $innerSql = $this->getInnerSQL($AST); - - $sqlIdentifier = $this->getSQLIdentifier($AST); - - if ($hasOrderBy) { - $orderGroupBy = ' GROUP BY ' . implode(', ', $sqlIdentifier); - $sqlIdentifier[] = 'MIN(' . $this->walkResultVariable('dctrn_rownum') . ') AS dctrn_minrownum'; - } - - // Build the counter query - $sql = sprintf( - 'SELECT DISTINCT %s FROM (%s) dctrn_result', - implode(', ', $sqlIdentifier), - $innerSql - ); - - if ($hasOrderBy) { - $sql .= $orderGroupBy . $outerOrderBy; - } - - // Apply the limit and offset. - $sql = $this->platform->modifyLimitQuery( - $sql, - $this->maxResults, - $this->firstResult - ); - - // Add the columns to the ResultSetMapping. It's not really nice but - // it works. Preferably I'd clear the RSM or simply create a new one - // but that is not possible from inside the output walker, so we dirty - // up the one we have. - foreach ($sqlIdentifier as $property => $alias) { - $this->rsm->addScalarResult($alias, $property); - } - - return $sql; - } - - /** - * Walks down a SelectStatement AST node, wrapping it in a SELECT DISTINCT. - * This method is for platforms which DO NOT support ROW_NUMBER. - * - * @param SelectStatement $AST - * @param bool $addMissingItemsFromOrderByToSelect - * - * @return string - * - * @throws \RuntimeException - */ - public function walkSelectStatementWithoutRowNumber(SelectStatement $AST, $addMissingItemsFromOrderByToSelect = true) - { - // We don't want to call this recursively! - if ($AST->orderByClause instanceof OrderByClause && $addMissingItemsFromOrderByToSelect) { - // In the case of ordering a query by columns from joined tables, we - // must add those columns to the select clause of the query BEFORE - // the SQL is generated. - $this->addMissingItemsFromOrderByToSelect($AST); - } - - // Remove order by clause from the inner query - // It will be re-appended in the outer select generated by this method - $orderByClause = $AST->orderByClause; - $AST->orderByClause = null; - - $innerSql = $this->getInnerSQL($AST); - - $sqlIdentifier = $this->getSQLIdentifier($AST); - - // Build the counter query - $sql = sprintf('SELECT DISTINCT %s FROM (%s) dctrn_result', - implode(', ', $sqlIdentifier), $innerSql); - - // http://www.doctrine-project.org/jira/browse/DDC-1958 - $sql = $this->preserveSqlOrdering($sqlIdentifier, $innerSql, $sql, $orderByClause); - - // Apply the limit and offset. - $sql = $this->platform->modifyLimitQuery( - $sql, $this->maxResults, $this->firstResult - ); - - // Add the columns to the ResultSetMapping. It's not really nice but - // it works. Preferably I'd clear the RSM or simply create a new one - // but that is not possible from inside the output walker, so we dirty - // up the one we have. - foreach ($sqlIdentifier as $property => $alias) { - $this->rsm->addScalarResult($alias, $property); - } - - // Restore orderByClause - $AST->orderByClause = $orderByClause; - - return $sql; - } - - /** - * Finds all PathExpressions in an AST's OrderByClause, and ensures that - * the referenced fields are present in the SelectClause of the passed AST. - * - * @param SelectStatement $AST - */ - private function addMissingItemsFromOrderByToSelect(SelectStatement $AST) - { - $this->orderByPathExpressions = []; - - // We need to do this in another walker because otherwise we'll end up - // polluting the state of this one. - $walker = clone $this; - - // This will populate $orderByPathExpressions via - // LimitSubqueryOutputWalker::walkPathExpression, which will be called - // as the select statement is walked. We'll end up with an array of all - // path expressions referenced in the query. - $walker->walkSelectStatementWithoutRowNumber($AST, false); - $orderByPathExpressions = $walker->getOrderByPathExpressions(); - - // Get a map of referenced identifiers to field names. - $selects = []; - foreach ($orderByPathExpressions as $pathExpression) { - $idVar = $pathExpression->identificationVariable; - $field = $pathExpression->field; - if (!isset($selects[$idVar])) { - $selects[$idVar] = []; - } - $selects[$idVar][$field] = true; - } - - // Loop the select clause of the AST and exclude items from $select - // that are already being selected in the query. - foreach ($AST->selectClause->selectExpressions as $selectExpression) { - if ($selectExpression instanceof SelectExpression) { - $idVar = $selectExpression->expression; - if (!is_string($idVar)) { - continue; - } - $field = $selectExpression->fieldIdentificationVariable; - if ($field === null) { - // No need to add this select, as we're already fetching the whole object. - unset($selects[$idVar]); - } else { - unset($selects[$idVar][$field]); - } - } - } - - // Add select items which were not excluded to the AST's select clause. - foreach ($selects as $idVar => $fields) { - $AST->selectClause->selectExpressions[] = new SelectExpression(new PartialObjectExpression($idVar, array_keys($fields)), null, true); - } - } - - /** - * Generates new SQL for statements with an order by clause - * - * @param array $sqlIdentifier - * @param string $innerSql - * @param string $sql - * @param OrderByClause|null $orderByClause - * - * @return string - */ - private function preserveSqlOrdering( - array $sqlIdentifier, - string $innerSql, - string $sql, - ?OrderByClause $orderByClause - ) : string { - // If the sql statement has an order by clause, we need to wrap it in a new select distinct statement - if (! $orderByClause) { - return $sql; - } - - // now only select distinct identifier - return \sprintf( - 'SELECT DISTINCT %s FROM (%s) dctrn_result', - \implode(', ', $sqlIdentifier), - $this->recreateInnerSql($orderByClause, $sqlIdentifier, $innerSql) - ); - } - - /** - * Generates a new SQL statement for the inner query to keep the correct sorting - * - * @param OrderByClause $orderByClause - * @param array $identifiers - * @param string $innerSql - * - * @return string - */ - private function recreateInnerSql( - OrderByClause $orderByClause, - array $identifiers, - string $innerSql - ) : string { - [$searchPatterns, $replacements] = $this->generateSqlAliasReplacements(); - - $orderByItems = []; - - foreach ($orderByClause->orderByItems as $orderByItem) { - // Walk order by item to get string representation of it and - // replace path expressions in the order by clause with their column alias - $orderByItemString = \preg_replace( - $searchPatterns, - $replacements, - $this->walkOrderByItem($orderByItem) - ); - - $orderByItems[] = $orderByItemString; - $identifier = \substr($orderByItemString, 0, \strrpos($orderByItemString, ' ')); - - if (! \in_array($identifier, $identifiers, true)) { - $identifiers[] = $identifier; - } - } - - return $sql = \sprintf( - 'SELECT DISTINCT %s FROM (%s) dctrn_result_inner ORDER BY %s', - \implode(', ', $identifiers), - $innerSql, - \implode(', ', $orderByItems) - ); - } - - /** - * @return string[][] - */ - private function generateSqlAliasReplacements() : array - { - $aliasMap = $searchPatterns = $replacements = $metadataList = []; - - // Generate DQL alias -> SQL table alias mapping - foreach (\array_keys($this->rsm->aliasMap) as $dqlAlias) { - $metadataList[$dqlAlias] = $class = $this->queryComponents[$dqlAlias]['metadata']; - $aliasMap[$dqlAlias] = $this->getSQLTableAlias($class->getTableName(), $dqlAlias); - } - - // Generate search patterns for each field's path expression in the order by clause - foreach ($this->rsm->fieldMappings as $fieldAlias => $fieldName) { - $dqlAliasForFieldAlias = $this->rsm->columnOwnerMap[$fieldAlias]; - $class = $metadataList[$dqlAliasForFieldAlias]; - - // If the field is from a joined child table, we won't be ordering on it. - if (! isset($class->fieldMappings[$fieldName])) { - continue; - } - - $fieldMapping = $class->fieldMappings[$fieldName]; - - // Get the proper column name as will appear in the select list - $columnName = $this->quoteStrategy->getColumnName( - $fieldName, - $metadataList[$dqlAliasForFieldAlias], - $this->em->getConnection()->getDatabasePlatform() - ); - - // Get the SQL table alias for the entity and field - $sqlTableAliasForFieldAlias = $aliasMap[$dqlAliasForFieldAlias]; - - if (isset($fieldMapping['declared']) && $fieldMapping['declared'] !== $class->name) { - // Field was declared in a parent class, so we need to get the proper SQL table alias - // for the joined parent table. - $otherClassMetadata = $this->em->getClassMetadata($fieldMapping['declared']); - - if (! $otherClassMetadata->isMappedSuperclass) { - $sqlTableAliasForFieldAlias = $this->getSQLTableAlias($otherClassMetadata->getTableName(), $dqlAliasForFieldAlias); - } - } - - // Compose search and replace patterns - $searchPatterns[] = \sprintf(self::ORDER_BY_PATH_EXPRESSION, $sqlTableAliasForFieldAlias, $columnName); - $replacements[] = $fieldAlias; - } - - return [$searchPatterns, $replacements]; - } - - /** - * getter for $orderByPathExpressions - * - * @return array - */ - public function getOrderByPathExpressions() - { - return $this->orderByPathExpressions; - } - - /** - * @param SelectStatement $AST - * - * @return string - * - * @throws \Doctrine\ORM\OptimisticLockException - * @throws \Doctrine\ORM\Query\QueryException - */ - private function getInnerSQL(SelectStatement $AST) - { - // Set every select expression as visible(hidden = false) to - // make $AST have scalar mappings properly - this is relevant for referencing selected - // fields from outside the subquery, for example in the ORDER BY segment - $hiddens = []; - - foreach ($AST->selectClause->selectExpressions as $idx => $expr) { - $hiddens[$idx] = $expr->hiddenAliasResultVariable; - $expr->hiddenAliasResultVariable = false; - } - - $innerSql = parent::walkSelectStatement($AST); - - // Restore hiddens - foreach ($AST->selectClause->selectExpressions as $idx => $expr) { - $expr->hiddenAliasResultVariable = $hiddens[$idx]; - } - - return $innerSql; - } - - /** - * @param SelectStatement $AST - * - * @return array - */ - private function getSQLIdentifier(SelectStatement $AST) - { - // Find out the SQL alias of the identifier column of the root entity. - // It may be possible to make this work with multiple root entities but that - // would probably require issuing multiple queries or doing a UNION SELECT. - // So for now, it's not supported. - - // Get the root entity and alias from the AST fromClause. - $from = $AST->fromClause->identificationVariableDeclarations; - if (count($from) !== 1) { - throw new \RuntimeException('Cannot count query which selects two FROM components, cannot make distinction'); - } - - $fromRoot = reset($from); - $rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable; - $rootClass = $this->queryComponents[$rootAlias]['metadata']; - $rootIdentifier = $rootClass->identifier; - - // For every identifier, find out the SQL alias by combing through the ResultSetMapping - $sqlIdentifier = []; - foreach ($rootIdentifier as $property) { - if (isset($rootClass->fieldMappings[$property])) { - foreach (array_keys($this->rsm->fieldMappings, $property) as $alias) { - if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { - $sqlIdentifier[$property] = $alias; - } - } - } - - if (isset($rootClass->associationMappings[$property])) { - $joinColumn = $rootClass->associationMappings[$property]['joinColumns'][0]['name']; - - foreach (array_keys($this->rsm->metaMappings, $joinColumn) as $alias) { - if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { - $sqlIdentifier[$property] = $alias; - } - } - } - } - - if (count($sqlIdentifier) === 0) { - throw new \RuntimeException('The Paginator does not support Queries which only yield ScalarResults.'); - } - - if (count($rootIdentifier) != count($sqlIdentifier)) { - throw new \RuntimeException(sprintf( - 'Not all identifier properties can be found in the ResultSetMapping: %s', - implode(', ', array_diff($rootIdentifier, array_keys($sqlIdentifier))) - )); - } - - return $sqlIdentifier; - } - - /** - * {@inheritdoc} - */ - public function walkPathExpression($pathExpr) - { - if (!$this->inSubSelect && !$this->platformSupportsRowNumber() && !in_array($pathExpr, $this->orderByPathExpressions)) { - $this->orderByPathExpressions[] = $pathExpr; - } - - return parent::walkPathExpression($pathExpr); - } - - /** - * {@inheritdoc} - */ - public function walkSubSelect($subselect) - { - $this->inSubSelect = true; - - $sql = parent::walkSubselect($subselect); - - $this->inSubSelect = false; - - return $sql; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php deleted file mode 100644 index 5614138..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php +++ /dev/null @@ -1,177 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Pagination; - -use Doctrine\DBAL\Types\Type; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\ORM\Query; -use Doctrine\ORM\Query\TreeWalkerAdapter; -use Doctrine\ORM\Query\AST\Functions\IdentityFunction; -use Doctrine\ORM\Query\AST\PathExpression; -use Doctrine\ORM\Query\AST\SelectExpression; -use Doctrine\ORM\Query\AST\SelectStatement; - -/** - * Replaces the selectClause of the AST with a SELECT DISTINCT root.id equivalent. - * - * @category DoctrineExtensions - * @package DoctrineExtensions\Paginate - * @author David Abdemoulaie - * @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/) - * @license http://hobodave.com/license.txt New BSD License - */ -class LimitSubqueryWalker extends TreeWalkerAdapter -{ - public const IDENTIFIER_TYPE = 'doctrine_paginator.id.type'; - - public const FORCE_DBAL_TYPE_CONVERSION = 'doctrine_paginator.scalar_result.force_dbal_type_conversion'; - - /** - * Counter for generating unique order column aliases. - * - * @var int - */ - private $_aliasCounter = 0; - - /** - * Walks down a SelectStatement AST node, modifying it to retrieve DISTINCT ids - * of the root Entity. - * - * @param SelectStatement $AST - * - * @return void - * - * @throws \RuntimeException - */ - public function walkSelectStatement(SelectStatement $AST) - { - $queryComponents = $this->_getQueryComponents(); - // Get the root entity and alias from the AST fromClause - $from = $AST->fromClause->identificationVariableDeclarations; - $fromRoot = reset($from); - $rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable; - $rootClass = $queryComponents[$rootAlias]['metadata']; - - $this->validate($AST); - $identifier = $rootClass->getSingleIdentifierFieldName(); - - if (isset($rootClass->associationMappings[$identifier])) { - throw new \RuntimeException("Paginating an entity with foreign key as identifier only works when using the Output Walkers. Call Paginator#setUseOutputWalkers(true) before iterating the paginator."); - } - - $this->_getQuery()->setHint( - self::IDENTIFIER_TYPE, - Type::getType($rootClass->fieldMappings[$identifier]['type']) - ); - - $this->_getQuery()->setHint(self::FORCE_DBAL_TYPE_CONVERSION, true); - - $pathExpression = new PathExpression( - PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, - $rootAlias, - $identifier - ); - - $pathExpression->type = PathExpression::TYPE_STATE_FIELD; - - $AST->selectClause->selectExpressions = [new SelectExpression($pathExpression, '_dctrn_id')]; - $AST->selectClause->isDistinct = true; - - if ( ! isset($AST->orderByClause)) { - return; - } - - foreach ($AST->orderByClause->orderByItems as $item) { - if ($item->expression instanceof PathExpression) { - $AST->selectClause->selectExpressions[] = new SelectExpression( - $this->createSelectExpressionItem($item->expression), '_dctrn_ord' . $this->_aliasCounter++ - ); - - continue; - } - - if (is_string($item->expression) && isset($queryComponents[$item->expression])) { - $qComp = $queryComponents[$item->expression]; - - if (isset($qComp['resultVariable'])) { - $AST->selectClause->selectExpressions[] = new SelectExpression( - $qComp['resultVariable'], - $item->expression - ); - } - } - } - } - - /** - * Validate the AST to ensure that this walker is able to properly manipulate it. - * - * @param SelectStatement $AST - */ - private function validate(SelectStatement $AST) - { - // Prevent LimitSubqueryWalker from being used with queries that include - // a limit, a fetched to-many join, and an order by condition that - // references a column from the fetch joined table. - $queryComponents = $this->getQueryComponents(); - $query = $this->_getQuery(); - $from = $AST->fromClause->identificationVariableDeclarations; - $fromRoot = reset($from); - - if ($query instanceof Query - && null !== $query->getMaxResults() - && $AST->orderByClause - && count($fromRoot->joins)) { - // Check each orderby item. - // TODO: check complex orderby items too... - foreach ($AST->orderByClause->orderByItems as $orderByItem) { - $expression = $orderByItem->expression; - if ($orderByItem->expression instanceof PathExpression - && isset($queryComponents[$expression->identificationVariable])) { - $queryComponent = $queryComponents[$expression->identificationVariable]; - if (isset($queryComponent['parent']) - && $queryComponent['relation']['type'] & ClassMetadataInfo::TO_MANY) { - throw new \RuntimeException("Cannot select distinct identifiers from query with LIMIT and ORDER BY on a column from a fetch joined to-many association. Use output walkers."); - } - } - } - } - } - - /** - * Retrieve either an IdentityFunction (IDENTITY(u.assoc)) or a state field (u.name). - * - * @param \Doctrine\ORM\Query\AST\PathExpression $pathExpression - * - * @return \Doctrine\ORM\Query\AST\Functions\IdentityFunction - */ - private function createSelectExpressionItem(PathExpression $pathExpression) - { - if ($pathExpression->type === PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION) { - $identity = new IdentityFunction('identity'); - - $identity->pathExpression = clone $pathExpression; - - return $identity; - } - - return clone $pathExpression; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/Paginator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/Paginator.php deleted file mode 100644 index 64cd9e2..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/Paginator.php +++ /dev/null @@ -1,289 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Pagination; - -use Doctrine\ORM\NoResultException; -use Doctrine\ORM\Query; -use Doctrine\ORM\Query\Parser; -use Doctrine\ORM\Query\ResultSetMapping; -use Doctrine\ORM\QueryBuilder; -use function array_map; - -/** - * The paginator can handle various complex scenarios with DQL. - * - * @author Pablo Díez - * @author Benjamin Eberlei - * @license New BSD - */ -class Paginator implements \Countable, \IteratorAggregate -{ - /** - * @var Query - */ - private $query; - - /** - * @var bool - */ - private $fetchJoinCollection; - - /** - * @var bool|null - */ - private $useOutputWalkers; - - /** - * @var int - */ - private $count; - - /** - * Constructor. - * - * @param Query|QueryBuilder $query A Doctrine ORM query or query builder. - * @param boolean $fetchJoinCollection Whether the query joins a collection (true by default). - */ - public function __construct($query, $fetchJoinCollection = true) - { - if ($query instanceof QueryBuilder) { - $query = $query->getQuery(); - } - - $this->query = $query; - $this->fetchJoinCollection = (bool) $fetchJoinCollection; - } - - /** - * Returns the query. - * - * @return Query - */ - public function getQuery() - { - return $this->query; - } - - /** - * Returns whether the query joins a collection. - * - * @return boolean Whether the query joins a collection. - */ - public function getFetchJoinCollection() - { - return $this->fetchJoinCollection; - } - - /** - * Returns whether the paginator will use an output walker. - * - * @return bool|null - */ - public function getUseOutputWalkers() - { - return $this->useOutputWalkers; - } - - /** - * Sets whether the paginator will use an output walker. - * - * @param bool|null $useOutputWalkers - * - * @return $this - */ - public function setUseOutputWalkers($useOutputWalkers) - { - $this->useOutputWalkers = $useOutputWalkers; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function count() - { - if ($this->count === null) { - try { - $this->count = array_sum(array_map('current', $this->getCountQuery()->getScalarResult())); - } catch (NoResultException $e) { - $this->count = 0; - } - } - - return $this->count; - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - $offset = $this->query->getFirstResult(); - $length = $this->query->getMaxResults(); - - if ($this->fetchJoinCollection && $length !== null) { - $subQuery = $this->cloneQuery($this->query); - - if ($this->useOutputWalker($subQuery)) { - $subQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, LimitSubqueryOutputWalker::class); - } else { - $this->appendTreeWalker($subQuery, LimitSubqueryWalker::class); - $this->unbindUnusedQueryParams($subQuery); - } - - $subQuery->setFirstResult($offset)->setMaxResults($length); - - $foundIdRows = $subQuery->getScalarResult(); - - // don't do this for an empty id array - if ($foundIdRows === []) { - return new \ArrayIterator([]); - } - - $whereInQuery = $this->cloneQuery($this->query); - $ids = array_map('current', $foundIdRows); - - $this->appendTreeWalker($whereInQuery, WhereInWalker::class); - $whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, count($ids)); - $whereInQuery->setFirstResult(null)->setMaxResults(null); - $whereInQuery->setParameter(WhereInWalker::PAGINATOR_ID_ALIAS, $ids); - $whereInQuery->setCacheable($this->query->isCacheable()); - $whereInQuery->expireQueryCache(); - - $result = $whereInQuery->getResult($this->query->getHydrationMode()); - } else { - $result = $this->cloneQuery($this->query) - ->setMaxResults($length) - ->setFirstResult($offset) - ->setCacheable($this->query->isCacheable()) - ->getResult($this->query->getHydrationMode()) - ; - } - - return new \ArrayIterator($result); - } - - /** - * Clones a query. - * - * @param Query $query The query. - * - * @return Query The cloned query. - */ - private function cloneQuery(Query $query) - { - /* @var $cloneQuery Query */ - $cloneQuery = clone $query; - - $cloneQuery->setParameters(clone $query->getParameters()); - $cloneQuery->setCacheable(false); - - foreach ($query->getHints() as $name => $value) { - $cloneQuery->setHint($name, $value); - } - - return $cloneQuery; - } - - /** - * Determines whether to use an output walker for the query. - * - * @param Query $query The query. - * - * @return bool - */ - private function useOutputWalker(Query $query) - { - if ($this->useOutputWalkers === null) { - return (bool) $query->getHint(Query::HINT_CUSTOM_OUTPUT_WALKER) === false; - } - - return $this->useOutputWalkers; - } - - /** - * Appends a custom tree walker to the tree walkers hint. - * - * @param Query $query - * @param string $walkerClass - */ - private function appendTreeWalker(Query $query, $walkerClass) - { - $hints = $query->getHint(Query::HINT_CUSTOM_TREE_WALKERS); - - if ($hints === false) { - $hints = []; - } - - $hints[] = $walkerClass; - $query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, $hints); - } - - /** - * Returns Query prepared to count. - * - * @return Query - */ - private function getCountQuery() - { - /* @var $countQuery Query */ - $countQuery = $this->cloneQuery($this->query); - - if ( ! $countQuery->hasHint(CountWalker::HINT_DISTINCT)) { - $countQuery->setHint(CountWalker::HINT_DISTINCT, true); - } - - if ($this->useOutputWalker($countQuery)) { - $platform = $countQuery->getEntityManager()->getConnection()->getDatabasePlatform(); // law of demeter win - - $rsm = new ResultSetMapping(); - $rsm->addScalarResult($platform->getSQLResultCasing('dctrn_count'), 'count'); - - $countQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, CountOutputWalker::class); - $countQuery->setResultSetMapping($rsm); - } else { - $this->appendTreeWalker($countQuery, CountWalker::class); - $this->unbindUnusedQueryParams($countQuery); - } - - $countQuery->setFirstResult(null)->setMaxResults(null); - - return $countQuery; - } - - private function unbindUnusedQueryParams(Query $query): void - { - $parser = new Parser($query); - $parameterMappings = $parser->parse()->getParameterMappings(); - /* @var $parameters \Doctrine\Common\Collections\Collection|\Doctrine\ORM\Query\Parameter[] */ - $parameters = $query->getParameters(); - - foreach ($parameters as $key => $parameter) { - $parameterName = $parameter->getName(); - - if ( ! (isset($parameterMappings[$parameterName]) || array_key_exists($parameterName, $parameterMappings))) { - unset($parameters[$key]); - } - } - - $query->setParameters($parameters); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/RowNumberOverFunction.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/RowNumberOverFunction.php deleted file mode 100644 index a9d3e5d..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/RowNumberOverFunction.php +++ /dev/null @@ -1,62 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Pagination; - -use Doctrine\ORM\ORMException; -use Doctrine\ORM\Query\AST\Functions\FunctionNode; - -/** - * RowNumberOverFunction - * - * Provides ROW_NUMBER() OVER(ORDER BY...) construct for use in LimitSubqueryOutputWalker - * - * @since 2.5 - * @author Bill Schaller - */ -class RowNumberOverFunction extends FunctionNode -{ - /** - * @var \Doctrine\ORM\Query\AST\OrderByClause - */ - public $orderByClause; - - /** - * @override - * @inheritdoc - */ - public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) - { - return 'ROW_NUMBER() OVER(' . trim($sqlWalker->walkOrderByClause( - $this->orderByClause - )) . ')'; - } - - /** - * @override - * @inheritdoc - * - * @throws ORMException - */ - public function parse(\Doctrine\ORM\Query\Parser $parser) - { - throw new ORMException("The RowNumberOverFunction is not intended for, nor is it enabled for use in DQL."); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php deleted file mode 100644 index de66f64..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php +++ /dev/null @@ -1,184 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools\Pagination; - -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Query\AST\ArithmeticExpression; -use Doctrine\ORM\Query\AST\ConditionalExpression; -use Doctrine\ORM\Query\AST\ConditionalFactor; -use Doctrine\ORM\Query\AST\ConditionalPrimary; -use Doctrine\ORM\Query\AST\ConditionalTerm; -use Doctrine\ORM\Query\AST\InExpression; -use Doctrine\ORM\Query\AST\InputParameter; -use Doctrine\ORM\Query\AST\NullComparisonExpression; -use Doctrine\ORM\Query\AST\PathExpression; -use Doctrine\ORM\Query\AST\SelectStatement; -use Doctrine\ORM\Query\AST\SimpleArithmeticExpression; -use Doctrine\ORM\Query\AST\WhereClause; -use Doctrine\ORM\Query\TreeWalkerAdapter; -use Doctrine\ORM\Utility\PersisterHelper; -use function array_map; -use function assert; -use function is_array; - -/** - * Replaces the whereClause of the AST with a WHERE id IN (:foo_1, :foo_2) equivalent. - * - * @category DoctrineExtensions - * @package DoctrineExtensions\Paginate - * @author David Abdemoulaie - * @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/) - * @license http://hobodave.com/license.txt New BSD License - */ -class WhereInWalker extends TreeWalkerAdapter -{ - /** - * ID Count hint name. - */ - const HINT_PAGINATOR_ID_COUNT = 'doctrine.id.count'; - - /** - * Primary key alias for query. - */ - const PAGINATOR_ID_ALIAS = 'dpid'; - - /** - * Replaces the whereClause in the AST. - * - * Generates a clause equivalent to WHERE IN (:dpid_1, :dpid_2, ...) - * - * The parameter namespace (dpid) is defined by - * the PAGINATOR_ID_ALIAS - * - * The total number of parameters is retrieved from - * the HINT_PAGINATOR_ID_COUNT query hint. - * - * @param SelectStatement $AST - * - * @return void - * - * @throws \RuntimeException - */ - public function walkSelectStatement(SelectStatement $AST) - { - $queryComponents = $this->_getQueryComponents(); - // Get the root entity and alias from the AST fromClause - $from = $AST->fromClause->identificationVariableDeclarations; - - if (count($from) > 1) { - throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); - } - - $fromRoot = reset($from); - $rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable; - /** @var ClassMetadata $rootClass */ - $rootClass = $queryComponents[$rootAlias]['metadata']; - $identifierFieldName = $rootClass->getSingleIdentifierFieldName(); - - $pathType = PathExpression::TYPE_STATE_FIELD; - if (isset($rootClass->associationMappings[$identifierFieldName])) { - $pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION; - } - - $pathExpression = new PathExpression(PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $rootAlias, $identifierFieldName); - $pathExpression->type = $pathType; - - $count = $this->_getQuery()->getHint(self::HINT_PAGINATOR_ID_COUNT); - - if ($count > 0) { - $arithmeticExpression = new ArithmeticExpression(); - $arithmeticExpression->simpleArithmeticExpression = new SimpleArithmeticExpression( - [$pathExpression] - ); - $expression = new InExpression($arithmeticExpression); - $expression->literals[] = new InputParameter(":" . self::PAGINATOR_ID_ALIAS); - - $this->convertWhereInIdentifiersToDatabaseValue( - PersisterHelper::getTypeOfField( - $identifierFieldName, - $rootClass, - $this->_getQuery() - ->getEntityManager() - )[0] - ); - } else { - $expression = new NullComparisonExpression($pathExpression); - $expression->not = false; - } - - $conditionalPrimary = new ConditionalPrimary; - $conditionalPrimary->simpleConditionalExpression = $expression; - if ($AST->whereClause) { - if ($AST->whereClause->conditionalExpression instanceof ConditionalTerm) { - $AST->whereClause->conditionalExpression->conditionalFactors[] = $conditionalPrimary; - } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalPrimary) { - $AST->whereClause->conditionalExpression = new ConditionalExpression( - [ - new ConditionalTerm( - [ - $AST->whereClause->conditionalExpression, - $conditionalPrimary - ] - ) - ] - ); - } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalExpression - || $AST->whereClause->conditionalExpression instanceof ConditionalFactor - ) { - $tmpPrimary = new ConditionalPrimary; - $tmpPrimary->conditionalExpression = $AST->whereClause->conditionalExpression; - $AST->whereClause->conditionalExpression = new ConditionalTerm( - [ - $tmpPrimary, - $conditionalPrimary - ] - ); - } - } else { - $AST->whereClause = new WhereClause( - new ConditionalExpression( - [ - new ConditionalTerm([$conditionalPrimary]) - ] - ) - ); - } - } - - private function convertWhereInIdentifiersToDatabaseValue(string $type) : void - { - $query = $this->_getQuery(); - $identifiersParameter = $query->getParameter(self::PAGINATOR_ID_ALIAS); - - assert($identifiersParameter !== null); - - $identifiers = $identifiersParameter->getValue(); - - assert(is_array($identifiers)); - - $connection = $this->_getQuery() - ->getEntityManager() - ->getConnection(); - - $query->setParameter(self::PAGINATOR_ID_ALIAS, array_map(static function ($id) use ($connection, $type) { - return $connection->convertToDatabaseValue($id, $type); - }, $identifiers)); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ResolveTargetEntityListener.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ResolveTargetEntityListener.php deleted file mode 100644 index 36f1f92..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ResolveTargetEntityListener.php +++ /dev/null @@ -1,144 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools; - -use Doctrine\ORM\Event\LoadClassMetadataEventArgs; -use Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\Common\EventSubscriber; -use Doctrine\ORM\Events; - -/** - * ResolveTargetEntityListener - * - * Mechanism to overwrite interfaces or classes specified as association - * targets. - * - * @author Benjamin Eberlei - * @since 2.2 - */ -class ResolveTargetEntityListener implements EventSubscriber -{ - /** - * @var array[] indexed by original entity name - */ - private $resolveTargetEntities = []; - - /** - * {@inheritDoc} - */ - public function getSubscribedEvents() - { - return [ - Events::loadClassMetadata, - Events::onClassMetadataNotFound - ]; - } - - /** - * Adds a target-entity class name to resolve to a new class name. - * - * @param string $originalEntity - * @param string $newEntity - * @param array $mapping - * - * @return void - */ - public function addResolveTargetEntity($originalEntity, $newEntity, array $mapping) - { - $mapping['targetEntity'] = ltrim($newEntity, "\\"); - $this->resolveTargetEntities[ltrim($originalEntity, "\\")] = $mapping; - } - - /** - * @param OnClassMetadataNotFoundEventArgs $args - * - * @internal this is an event callback, and should not be called directly - * - * @return void - */ - public function onClassMetadataNotFound(OnClassMetadataNotFoundEventArgs $args) - { - if (array_key_exists($args->getClassName(), $this->resolveTargetEntities)) { - $args->setFoundMetadata( - $args - ->getObjectManager() - ->getClassMetadata($this->resolveTargetEntities[$args->getClassName()]['targetEntity']) - ); - } - } - - /** - * Processes event and resolves new target entity names. - * - * @param LoadClassMetadataEventArgs $args - * - * @return void - * - * @internal this is an event callback, and should not be called directly - */ - public function loadClassMetadata(LoadClassMetadataEventArgs $args) - { - /* @var $cm \Doctrine\ORM\Mapping\ClassMetadata */ - $cm = $args->getClassMetadata(); - - foreach ($cm->associationMappings as $mapping) { - if (isset($this->resolveTargetEntities[$mapping['targetEntity']])) { - $this->remapAssociation($cm, $mapping); - } - } - - foreach ($this->resolveTargetEntities as $interface => $data) { - if ($data['targetEntity'] == $cm->getName()) { - $args->getEntityManager()->getMetadataFactory()->setMetadataFor($interface, $cm); - } - } - } - - /** - * @param \Doctrine\ORM\Mapping\ClassMetadataInfo $classMetadata - * @param array $mapping - * - * @return void - */ - private function remapAssociation($classMetadata, $mapping) - { - $newMapping = $this->resolveTargetEntities[$mapping['targetEntity']]; - $newMapping = array_replace_recursive($mapping, $newMapping); - $newMapping['fieldName'] = $mapping['fieldName']; - - unset($classMetadata->associationMappings[$mapping['fieldName']]); - - switch ($mapping['type']) { - case ClassMetadata::MANY_TO_MANY: - $classMetadata->mapManyToMany($newMapping); - break; - case ClassMetadata::MANY_TO_ONE: - $classMetadata->mapManyToOne($newMapping); - break; - case ClassMetadata::ONE_TO_MANY: - $classMetadata->mapOneToMany($newMapping); - break; - case ClassMetadata::ONE_TO_ONE: - $classMetadata->mapOneToOne($newMapping); - break; - } - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaTool.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaTool.php deleted file mode 100644 index ba63e69..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaTool.php +++ /dev/null @@ -1,913 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools; - -use Doctrine\ORM\ORMException; -use Doctrine\DBAL\Schema\Comparator; -use Doctrine\DBAL\Schema\Index; -use Doctrine\DBAL\Schema\Schema; -use Doctrine\DBAL\Schema\Table; -use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector; -use Doctrine\DBAL\Schema\Visitor\RemoveNamespacedAssets; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Tools\Event\GenerateSchemaTableEventArgs; -use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs; - -/** - * The SchemaTool is a tool to create/drop/update database schemas based on - * ClassMetadata class descriptors. - * - * @link www.doctrine-project.org - * @since 2.0 - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Benjamin Eberlei - * @author Stefano Rodriguez - */ -class SchemaTool -{ - private const KNOWN_COLUMN_OPTIONS = ['comment', 'unsigned', 'fixed', 'default']; - - /** - * @var \Doctrine\ORM\EntityManagerInterface - */ - private $em; - - /** - * @var \Doctrine\DBAL\Platforms\AbstractPlatform - */ - private $platform; - - /** - * The quote strategy. - * - * @var \Doctrine\ORM\Mapping\QuoteStrategy - */ - private $quoteStrategy; - - /** - * Initializes a new SchemaTool instance that uses the connection of the - * provided EntityManager. - * - * @param \Doctrine\ORM\EntityManagerInterface $em - */ - public function __construct(EntityManagerInterface $em) - { - $this->em = $em; - $this->platform = $em->getConnection()->getDatabasePlatform(); - $this->quoteStrategy = $em->getConfiguration()->getQuoteStrategy(); - } - - /** - * Creates the database schema for the given array of ClassMetadata instances. - * - * @param array $classes - * - * @return void - * - * @throws ToolsException - */ - public function createSchema(array $classes) - { - $createSchemaSql = $this->getCreateSchemaSql($classes); - $conn = $this->em->getConnection(); - - foreach ($createSchemaSql as $sql) { - try { - $conn->executeQuery($sql); - } catch (\Throwable $e) { - throw ToolsException::schemaToolFailure($sql, $e); - } - } - } - - /** - * Gets the list of DDL statements that are required to create the database schema for - * the given list of ClassMetadata instances. - * - * @param array $classes - * - * @return array The SQL statements needed to create the schema for the classes. - */ - public function getCreateSchemaSql(array $classes) - { - $schema = $this->getSchemaFromMetadata($classes); - - return $schema->toSql($this->platform); - } - - /** - * Detects instances of ClassMetadata that don't need to be processed in the SchemaTool context. - * - * @param ClassMetadata $class - * @param array $processedClasses - * - * @return bool - */ - private function processingNotRequired($class, array $processedClasses) - { - return ( - isset($processedClasses[$class->name]) || - $class->isMappedSuperclass || - $class->isEmbeddedClass || - ($class->isInheritanceTypeSingleTable() && $class->name != $class->rootEntityName) - ); - } - - /** - * Creates a Schema instance from a given set of metadata classes. - * - * @param array $classes - * - * @return Schema - * - * @throws \Doctrine\ORM\ORMException - */ - public function getSchemaFromMetadata(array $classes) - { - // Reminder for processed classes, used for hierarchies - $processedClasses = []; - $eventManager = $this->em->getEventManager(); - $schemaManager = $this->em->getConnection()->getSchemaManager(); - $metadataSchemaConfig = $schemaManager->createSchemaConfig(); - - $metadataSchemaConfig->setExplicitForeignKeyIndexes(false); - $schema = new Schema([], [], $metadataSchemaConfig); - - $addedFks = []; - $blacklistedFks = []; - - foreach ($classes as $class) { - /** @var \Doctrine\ORM\Mapping\ClassMetadata $class */ - if ($this->processingNotRequired($class, $processedClasses)) { - continue; - } - - $table = $schema->createTable($this->quoteStrategy->getTableName($class, $this->platform)); - - if ($class->isInheritanceTypeSingleTable()) { - $this->gatherColumns($class, $table); - $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks); - - // Add the discriminator column - $this->addDiscriminatorColumnDefinition($class, $table); - - // Aggregate all the information from all classes in the hierarchy - foreach ($class->parentClasses as $parentClassName) { - // Parent class information is already contained in this class - $processedClasses[$parentClassName] = true; - } - - foreach ($class->subClasses as $subClassName) { - $subClass = $this->em->getClassMetadata($subClassName); - $this->gatherColumns($subClass, $table); - $this->gatherRelationsSql($subClass, $table, $schema, $addedFks, $blacklistedFks); - $processedClasses[$subClassName] = true; - } - } elseif ($class->isInheritanceTypeJoined()) { - // Add all non-inherited fields as columns - foreach ($class->fieldMappings as $fieldName => $mapping) { - if ( ! isset($mapping['inherited'])) { - $this->gatherColumn($class, $mapping, $table); - } - } - - $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks); - - // Add the discriminator column only to the root table - if ($class->name == $class->rootEntityName) { - $this->addDiscriminatorColumnDefinition($class, $table); - } else { - // Add an ID FK column to child tables - $pkColumns = []; - $inheritedKeyColumns = []; - - foreach ($class->identifier as $identifierField) { - if (isset($class->fieldMappings[$identifierField]['inherited'])) { - $idMapping = $class->fieldMappings[$identifierField]; - $this->gatherColumn($class, $idMapping, $table); - $columnName = $this->quoteStrategy->getColumnName( - $identifierField, - $class, - $this->platform - ); - // TODO: This seems rather hackish, can we optimize it? - $table->getColumn($columnName)->setAutoincrement(false); - - $pkColumns[] = $columnName; - $inheritedKeyColumns[] = $columnName; - - continue; - } - - if (isset($class->associationMappings[$identifierField]['inherited'])) { - $idMapping = $class->associationMappings[$identifierField]; - - $targetEntity = current( - array_filter( - $classes, - function (ClassMetadata $class) use ($idMapping) : bool { - return $class->name === $idMapping['targetEntity']; - } - ) - ); - - foreach ($idMapping['joinColumns'] as $joinColumn) { - if (isset($targetEntity->fieldMappings[$joinColumn['referencedColumnName']])) { - $columnName = $this->quoteStrategy->getJoinColumnName( - $joinColumn, - $class, - $this->platform - ); - - $pkColumns[] = $columnName; - $inheritedKeyColumns[] = $columnName; - } - } - } - } - - if ( ! empty($inheritedKeyColumns)) { - // Add a FK constraint on the ID column - $table->addForeignKeyConstraint( - $this->quoteStrategy->getTableName( - $this->em->getClassMetadata($class->rootEntityName), - $this->platform - ), - $inheritedKeyColumns, - $inheritedKeyColumns, - ['onDelete' => 'CASCADE'] - ); - } - - if ( ! empty($pkColumns)) { - $table->setPrimaryKey($pkColumns); - } - } - } elseif ($class->isInheritanceTypeTablePerClass()) { - throw ORMException::notSupported(); - } else { - $this->gatherColumns($class, $table); - $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks); - } - - $pkColumns = []; - - foreach ($class->identifier as $identifierField) { - if (isset($class->fieldMappings[$identifierField])) { - $pkColumns[] = $this->quoteStrategy->getColumnName($identifierField, $class, $this->platform); - } elseif (isset($class->associationMappings[$identifierField])) { - /* @var $assoc \Doctrine\ORM\Mapping\OneToOne */ - $assoc = $class->associationMappings[$identifierField]; - - foreach ($assoc['joinColumns'] as $joinColumn) { - $pkColumns[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); - } - } - } - - if ( ! $table->hasIndex('primary')) { - $table->setPrimaryKey($pkColumns); - } - - // there can be unique indexes automatically created for join column - // if join column is also primary key we should keep only primary key on this column - // so, remove indexes overruled by primary key - $primaryKey = $table->getIndex('primary'); - - foreach ($table->getIndexes() as $idxKey => $existingIndex) { - if ($primaryKey->overrules($existingIndex)) { - $table->dropIndex($idxKey); - } - } - - if (isset($class->table['indexes'])) { - foreach ($class->table['indexes'] as $indexName => $indexData) { - if ( ! isset($indexData['flags'])) { - $indexData['flags'] = []; - } - - $table->addIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName, (array) $indexData['flags'], $indexData['options'] ?? []); - } - } - - if (isset($class->table['uniqueConstraints'])) { - foreach ($class->table['uniqueConstraints'] as $indexName => $indexData) { - $uniqIndex = new Index($indexName, $indexData['columns'], true, false, [], $indexData['options'] ?? []); - - foreach ($table->getIndexes() as $tableIndexName => $tableIndex) { - if ($tableIndex->isFullfilledBy($uniqIndex)) { - $table->dropIndex($tableIndexName); - break; - } - } - - $table->addUniqueIndex($indexData['columns'], is_numeric($indexName) ? null : $indexName, $indexData['options'] ?? []); - } - } - - if (isset($class->table['options'])) { - foreach ($class->table['options'] as $key => $val) { - $table->addOption($key, $val); - } - } - - $processedClasses[$class->name] = true; - - if ($class->isIdGeneratorSequence() && $class->name == $class->rootEntityName) { - $seqDef = $class->sequenceGeneratorDefinition; - $quotedName = $this->quoteStrategy->getSequenceName($seqDef, $class, $this->platform); - if ( ! $schema->hasSequence($quotedName)) { - $schema->createSequence( - $quotedName, - $seqDef['allocationSize'], - $seqDef['initialValue'] - ); - } - } - - if ($eventManager->hasListeners(ToolEvents::postGenerateSchemaTable)) { - $eventManager->dispatchEvent( - ToolEvents::postGenerateSchemaTable, - new GenerateSchemaTableEventArgs($class, $schema, $table) - ); - } - } - - if ( ! $this->platform->supportsSchemas() && ! $this->platform->canEmulateSchemas()) { - $schema->visit(new RemoveNamespacedAssets()); - } - - if ($eventManager->hasListeners(ToolEvents::postGenerateSchema)) { - $eventManager->dispatchEvent( - ToolEvents::postGenerateSchema, - new GenerateSchemaEventArgs($this->em, $schema) - ); - } - - return $schema; - } - - /** - * Gets a portable column definition as required by the DBAL for the discriminator - * column of a class. - * - * @param ClassMetadata $class - * @param Table $table - * - * @return void - */ - private function addDiscriminatorColumnDefinition($class, Table $table) - { - $discrColumn = $class->discriminatorColumn; - - if ( ! isset($discrColumn['type']) || - (strtolower($discrColumn['type']) == 'string' && ! isset($discrColumn['length'])) - ) { - $discrColumn['type'] = 'string'; - $discrColumn['length'] = 255; - } - - $options = [ - 'length' => $discrColumn['length'] ?? null, - 'notnull' => true - ]; - - if (isset($discrColumn['columnDefinition'])) { - $options['columnDefinition'] = $discrColumn['columnDefinition']; - } - - $table->addColumn($discrColumn['name'], $discrColumn['type'], $options); - } - - /** - * Gathers the column definitions as required by the DBAL of all field mappings - * found in the given class. - * - * @param ClassMetadata $class - * @param Table $table - * - * @return void - */ - private function gatherColumns($class, Table $table) - { - $pkColumns = []; - - foreach ($class->fieldMappings as $mapping) { - if ($class->isInheritanceTypeSingleTable() && isset($mapping['inherited'])) { - continue; - } - - $this->gatherColumn($class, $mapping, $table); - - if ($class->isIdentifier($mapping['fieldName'])) { - $pkColumns[] = $this->quoteStrategy->getColumnName($mapping['fieldName'], $class, $this->platform); - } - } - } - - /** - * Creates a column definition as required by the DBAL from an ORM field mapping definition. - * - * @param ClassMetadata $class The class that owns the field mapping. - * @param array $mapping The field mapping. - * @param Table $table - * - * @return void - */ - private function gatherColumn($class, array $mapping, Table $table) - { - $columnName = $this->quoteStrategy->getColumnName($mapping['fieldName'], $class, $this->platform); - $columnType = $mapping['type']; - - $options = []; - $options['length'] = $mapping['length'] ?? null; - $options['notnull'] = isset($mapping['nullable']) ? ! $mapping['nullable'] : true; - if ($class->isInheritanceTypeSingleTable() && $class->parentClasses) { - $options['notnull'] = false; - } - - $options['platformOptions'] = []; - $options['platformOptions']['version'] = $class->isVersioned && $class->versionField === $mapping['fieldName']; - - if (strtolower($columnType) === 'string' && null === $options['length']) { - $options['length'] = 255; - } - - if (isset($mapping['precision'])) { - $options['precision'] = $mapping['precision']; - } - - if (isset($mapping['scale'])) { - $options['scale'] = $mapping['scale']; - } - - if (isset($mapping['default'])) { - $options['default'] = $mapping['default']; - } - - if (isset($mapping['columnDefinition'])) { - $options['columnDefinition'] = $mapping['columnDefinition']; - } - - // the 'default' option can be overwritten here - $options = $this->gatherColumnOptions($mapping) + $options; - - if ($class->isIdGeneratorIdentity() && $class->getIdentifierFieldNames() == [$mapping['fieldName']]) { - $options['autoincrement'] = true; - } - if ($class->isInheritanceTypeJoined() && $class->name !== $class->rootEntityName) { - $options['autoincrement'] = false; - } - - if ($table->hasColumn($columnName)) { - // required in some inheritance scenarios - $table->changeColumn($columnName, $options); - } else { - $table->addColumn($columnName, $columnType, $options); - } - - $isUnique = $mapping['unique'] ?? false; - if ($isUnique) { - $table->addUniqueIndex([$columnName]); - } - } - - /** - * Gathers the SQL for properly setting up the relations of the given class. - * This includes the SQL for foreign key constraints and join tables. - * - * @param ClassMetadata $class - * @param Table $table - * @param Schema $schema - * @param array $addedFks - * @param array $blacklistedFks - * - * @return void - * - * @throws \Doctrine\ORM\ORMException - */ - private function gatherRelationsSql($class, $table, $schema, &$addedFks, &$blacklistedFks) - { - foreach ($class->associationMappings as $id => $mapping) { - if (isset($mapping['inherited']) && ! \in_array($id, $class->identifier, true)) { - continue; - } - - $foreignClass = $this->em->getClassMetadata($mapping['targetEntity']); - - if ($mapping['type'] & ClassMetadata::TO_ONE && $mapping['isOwningSide']) { - $primaryKeyColumns = []; // PK is unnecessary for this relation-type - - $this->gatherRelationJoinColumns( - $mapping['joinColumns'], - $table, - $foreignClass, - $mapping, - $primaryKeyColumns, - $addedFks, - $blacklistedFks - ); - } elseif ($mapping['type'] == ClassMetadata::ONE_TO_MANY && $mapping['isOwningSide']) { - //... create join table, one-many through join table supported later - throw ORMException::notSupported(); - } elseif ($mapping['type'] == ClassMetadata::MANY_TO_MANY && $mapping['isOwningSide']) { - // create join table - $joinTable = $mapping['joinTable']; - - $theJoinTable = $schema->createTable( - $this->quoteStrategy->getJoinTableName($mapping, $foreignClass, $this->platform) - ); - - $primaryKeyColumns = []; - - // Build first FK constraint (relation table => source table) - $this->gatherRelationJoinColumns( - $joinTable['joinColumns'], - $theJoinTable, - $class, - $mapping, - $primaryKeyColumns, - $addedFks, - $blacklistedFks - ); - - // Build second FK constraint (relation table => target table) - $this->gatherRelationJoinColumns( - $joinTable['inverseJoinColumns'], - $theJoinTable, - $foreignClass, - $mapping, - $primaryKeyColumns, - $addedFks, - $blacklistedFks - ); - - $theJoinTable->setPrimaryKey($primaryKeyColumns); - } - } - } - - /** - * Gets the class metadata that is responsible for the definition of the referenced column name. - * - * Previously this was a simple task, but with DDC-117 this problem is actually recursive. If its - * not a simple field, go through all identifier field names that are associations recursively and - * find that referenced column name. - * - * TODO: Is there any way to make this code more pleasing? - * - * @param ClassMetadata $class - * @param string $referencedColumnName - * - * @return array (ClassMetadata, referencedFieldName) - */ - private function getDefiningClass($class, $referencedColumnName) - { - $referencedFieldName = $class->getFieldName($referencedColumnName); - - if ($class->hasField($referencedFieldName)) { - return [$class, $referencedFieldName]; - } - - if (in_array($referencedColumnName, $class->getIdentifierColumnNames())) { - // it seems to be an entity as foreign key - foreach ($class->getIdentifierFieldNames() as $fieldName) { - if ($class->hasAssociation($fieldName) - && $class->getSingleAssociationJoinColumnName($fieldName) == $referencedColumnName) { - return $this->getDefiningClass( - $this->em->getClassMetadata($class->associationMappings[$fieldName]['targetEntity']), - $class->getSingleAssociationReferencedJoinColumnName($fieldName) - ); - } - } - } - - return null; - } - - /** - * Gathers columns and fk constraints that are required for one part of relationship. - * - * @param array $joinColumns - * @param Table $theJoinTable - * @param ClassMetadata $class - * @param array $mapping - * @param array $primaryKeyColumns - * @param array $addedFks - * @param array $blacklistedFks - * - * @return void - * - * @throws \Doctrine\ORM\ORMException - */ - private function gatherRelationJoinColumns( - $joinColumns, - $theJoinTable, - $class, - $mapping, - &$primaryKeyColumns, - &$addedFks, - &$blacklistedFks - ) - { - $localColumns = []; - $foreignColumns = []; - $fkOptions = []; - $foreignTableName = $this->quoteStrategy->getTableName($class, $this->platform); - $uniqueConstraints = []; - - foreach ($joinColumns as $joinColumn) { - - list($definingClass, $referencedFieldName) = $this->getDefiningClass( - $class, - $joinColumn['referencedColumnName'] - ); - - if ( ! $definingClass) { - throw new \Doctrine\ORM\ORMException( - 'Column name `' . $joinColumn['referencedColumnName'] . '` referenced for relation from ' - . $mapping['sourceEntity'] . ' towards ' . $mapping['targetEntity'] . ' does not exist.' - ); - } - - $quotedColumnName = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform); - $quotedRefColumnName = $this->quoteStrategy->getReferencedJoinColumnName( - $joinColumn, - $class, - $this->platform - ); - - $primaryKeyColumns[] = $quotedColumnName; - $localColumns[] = $quotedColumnName; - $foreignColumns[] = $quotedRefColumnName; - - if ( ! $theJoinTable->hasColumn($quotedColumnName)) { - // Only add the column to the table if it does not exist already. - // It might exist already if the foreign key is mapped into a regular - // property as well. - - $fieldMapping = $definingClass->getFieldMapping($referencedFieldName); - - $columnDef = null; - if (isset($joinColumn['columnDefinition'])) { - $columnDef = $joinColumn['columnDefinition']; - } elseif (isset($fieldMapping['columnDefinition'])) { - $columnDef = $fieldMapping['columnDefinition']; - } - - $columnOptions = ['notnull' => false, 'columnDefinition' => $columnDef]; - - if (isset($joinColumn['nullable'])) { - $columnOptions['notnull'] = ! $joinColumn['nullable']; - } - - $columnOptions = $columnOptions + $this->gatherColumnOptions($fieldMapping); - - if ($fieldMapping['type'] == "string" && isset($fieldMapping['length'])) { - $columnOptions['length'] = $fieldMapping['length']; - } elseif ($fieldMapping['type'] == "decimal") { - $columnOptions['scale'] = $fieldMapping['scale']; - $columnOptions['precision'] = $fieldMapping['precision']; - } - - $theJoinTable->addColumn($quotedColumnName, $fieldMapping['type'], $columnOptions); - } - - if (isset($joinColumn['unique']) && $joinColumn['unique'] == true) { - $uniqueConstraints[] = ['columns' => [$quotedColumnName]]; - } - - if (isset($joinColumn['onDelete'])) { - $fkOptions['onDelete'] = $joinColumn['onDelete']; - } - } - - // Prefer unique constraints over implicit simple indexes created for foreign keys. - // Also avoids index duplication. - foreach ($uniqueConstraints as $indexName => $unique) { - $theJoinTable->addUniqueIndex($unique['columns'], is_numeric($indexName) ? null : $indexName); - } - - $compositeName = $theJoinTable->getName().'.'.implode('', $localColumns); - - if (! $this->platform->supportsForeignKeyConstraints()) { - return; - } - - if (isset($addedFks[$compositeName]) - && ($foreignTableName != $addedFks[$compositeName]['foreignTableName'] - || 0 < count(array_diff($foreignColumns, $addedFks[$compositeName]['foreignColumns']))) - ) { - foreach ($theJoinTable->getForeignKeys() as $fkName => $key) { - if (0 === count(array_diff($key->getLocalColumns(), $localColumns)) - && (($key->getForeignTableName() != $foreignTableName) - || 0 < count(array_diff($key->getForeignColumns(), $foreignColumns))) - ) { - $theJoinTable->removeForeignKey($fkName); - break; - } - } - $blacklistedFks[$compositeName] = true; - } elseif ( ! isset($blacklistedFks[$compositeName])) { - $addedFks[$compositeName] = ['foreignTableName' => $foreignTableName, 'foreignColumns' => $foreignColumns]; - $theJoinTable->addUnnamedForeignKeyConstraint( - $foreignTableName, - $localColumns, - $foreignColumns, - $fkOptions - ); - } - } - - /** - * @param mixed[] $mapping - * - * @return mixed[] - */ - private function gatherColumnOptions(array $mapping) : array - { - if (! isset($mapping['options'])) { - return []; - } - - $options = array_intersect_key($mapping['options'], array_flip(self::KNOWN_COLUMN_OPTIONS)); - $options['customSchemaOptions'] = array_diff_key($mapping['options'], $options); - - return $options; - } - - /** - * Drops the database schema for the given classes. - * - * In any way when an exception is thrown it is suppressed since drop was - * issued for all classes of the schema and some probably just don't exist. - * - * @param array $classes - * - * @return void - */ - public function dropSchema(array $classes) - { - $dropSchemaSql = $this->getDropSchemaSQL($classes); - $conn = $this->em->getConnection(); - - foreach ($dropSchemaSql as $sql) { - try { - $conn->executeQuery($sql); - } catch (\Throwable $e) { - // ignored - } - } - } - - /** - * Drops all elements in the database of the current connection. - * - * @return void - */ - public function dropDatabase() - { - $dropSchemaSql = $this->getDropDatabaseSQL(); - $conn = $this->em->getConnection(); - - foreach ($dropSchemaSql as $sql) { - $conn->executeQuery($sql); - } - } - - /** - * Gets the SQL needed to drop the database schema for the connections database. - * - * @return array - */ - public function getDropDatabaseSQL() - { - $sm = $this->em->getConnection()->getSchemaManager(); - $schema = $sm->createSchema(); - - $visitor = new DropSchemaSqlCollector($this->platform); - $schema->visit($visitor); - - return $visitor->getQueries(); - } - - /** - * Gets SQL to drop the tables defined by the passed classes. - * - * @param array $classes - * - * @return array - */ - public function getDropSchemaSQL(array $classes) - { - $visitor = new DropSchemaSqlCollector($this->platform); - $schema = $this->getSchemaFromMetadata($classes); - - $sm = $this->em->getConnection()->getSchemaManager(); - $fullSchema = $sm->createSchema(); - - foreach ($fullSchema->getTables() as $table) { - if ( ! $schema->hasTable($table->getName())) { - foreach ($table->getForeignKeys() as $foreignKey) { - /* @var $foreignKey \Doctrine\DBAL\Schema\ForeignKeyConstraint */ - if ($schema->hasTable($foreignKey->getForeignTableName())) { - $visitor->acceptForeignKey($table, $foreignKey); - } - } - } else { - $visitor->acceptTable($table); - foreach ($table->getForeignKeys() as $foreignKey) { - $visitor->acceptForeignKey($table, $foreignKey); - } - } - } - - if ($this->platform->supportsSequences()) { - foreach ($schema->getSequences() as $sequence) { - $visitor->acceptSequence($sequence); - } - - foreach ($schema->getTables() as $table) { - /* @var $sequence Table */ - if ($table->hasPrimaryKey()) { - $columns = $table->getPrimaryKey()->getColumns(); - if (count($columns) == 1) { - $checkSequence = $table->getName() . '_' . $columns[0] . '_seq'; - if ($fullSchema->hasSequence($checkSequence)) { - $visitor->acceptSequence($fullSchema->getSequence($checkSequence)); - } - } - } - } - } - - return $visitor->getQueries(); - } - - /** - * Updates the database schema of the given classes by comparing the ClassMetadata - * instances to the current database schema that is inspected. - * - * @param array $classes - * @param boolean $saveMode If TRUE, only performs a partial update - * without dropping assets which are scheduled for deletion. - * - * @return void - */ - public function updateSchema(array $classes, $saveMode = false) - { - $updateSchemaSql = $this->getUpdateSchemaSql($classes, $saveMode); - $conn = $this->em->getConnection(); - - foreach ($updateSchemaSql as $sql) { - $conn->executeQuery($sql); - } - } - - /** - * Gets the sequence of SQL statements that need to be performed in order - * to bring the given class mappings in-synch with the relational schema. - * - * @param array $classes The classes to consider. - * @param boolean $saveMode If TRUE, only generates SQL for a partial update - * that does not include SQL for dropping assets which are scheduled for deletion. - * - * @return array The sequence of SQL statements. - */ - public function getUpdateSchemaSql(array $classes, $saveMode = false) - { - $sm = $this->em->getConnection()->getSchemaManager(); - - $fromSchema = $sm->createSchema(); - $toSchema = $this->getSchemaFromMetadata($classes); - - $comparator = new Comparator(); - $schemaDiff = $comparator->compare($fromSchema, $toSchema); - - if ($saveMode) { - return $schemaDiff->toSaveSql($this->platform); - } - - return $schemaDiff->toSql($this->platform); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaValidator.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaValidator.php deleted file mode 100644 index 6446598..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/SchemaValidator.php +++ /dev/null @@ -1,273 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools; - -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\DBAL\Types\Type; - -/** - * Performs strict validation of the mapping schema - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.com - * @since 1.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - */ -class SchemaValidator -{ - /** - * @var EntityManagerInterface - */ - private $em; - - /** - * @param EntityManagerInterface $em - */ - public function __construct(EntityManagerInterface $em) - { - $this->em = $em; - } - - /** - * Checks the internal consistency of all mapping files. - * - * There are several checks that can't be done at runtime or are too expensive, which can be verified - * with this command. For example: - * - * 1. Check if a relation with "mappedBy" is actually connected to that specified field. - * 2. Check if "mappedBy" and "inversedBy" are consistent to each other. - * 3. Check if "referencedColumnName" attributes are really pointing to primary key columns. - * - * @return array - */ - public function validateMapping() - { - $errors = []; - $cmf = $this->em->getMetadataFactory(); - $classes = $cmf->getAllMetadata(); - - foreach ($classes as $class) { - if ($ce = $this->validateClass($class)) { - $errors[$class->name] = $ce; - } - } - - return $errors; - } - - /** - * Validates a single class of the current. - * - * @param ClassMetadataInfo $class - * - * @return array - */ - public function validateClass(ClassMetadataInfo $class) - { - $ce = []; - $cmf = $this->em->getMetadataFactory(); - - foreach ($class->fieldMappings as $fieldName => $mapping) { - if (!Type::hasType($mapping['type'])) { - $ce[] = "The field '" . $class->name . "#" . $fieldName."' uses a non-existent type '" . $mapping['type'] . "'."; - } - } - - foreach ($class->associationMappings as $fieldName => $assoc) { - if (!class_exists($assoc['targetEntity']) || $cmf->isTransient($assoc['targetEntity'])) { - $ce[] = "The target entity '" . $assoc['targetEntity'] . "' specified on " . $class->name . '#' . $fieldName . ' is unknown or not an entity.'; - - return $ce; - } - - if ($assoc['mappedBy'] && $assoc['inversedBy']) { - $ce[] = "The association " . $class . "#" . $fieldName . " cannot be defined as both inverse and owning."; - } - - $targetMetadata = $cmf->getMetadataFor($assoc['targetEntity']); - - if (isset($assoc['id']) && $targetMetadata->containsForeignIdentifier) { - $ce[] = "Cannot map association '" . $class->name. "#". $fieldName ." as identifier, because " . - "the target entity '". $targetMetadata->name . "' also maps an association as identifier."; - } - - if ($assoc['mappedBy']) { - if ($targetMetadata->hasField($assoc['mappedBy'])) { - $ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the owning side ". - "field " . $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " which is not defined as association, but as field."; - } - if (!$targetMetadata->hasAssociation($assoc['mappedBy'])) { - $ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the owning side ". - "field " . $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " which does not exist."; - } elseif ($targetMetadata->associationMappings[$assoc['mappedBy']]['inversedBy'] == null) { - $ce[] = "The field " . $class->name . "#" . $fieldName . " is on the inverse side of a ". - "bi-directional relationship, but the specified mappedBy association on the target-entity ". - $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " does not contain the required ". - "'inversedBy=\"" . $fieldName . "\"' attribute."; - } elseif ($targetMetadata->associationMappings[$assoc['mappedBy']]['inversedBy'] != $fieldName) { - $ce[] = "The mappings " . $class->name . "#" . $fieldName . " and " . - $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " are ". - "inconsistent with each other."; - } - } - - if ($assoc['inversedBy']) { - if ($targetMetadata->hasField($assoc['inversedBy'])) { - $ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the inverse side ". - "field " . $assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " which is not defined as association."; - } - - if (!$targetMetadata->hasAssociation($assoc['inversedBy'])) { - $ce[] = "The association " . $class->name . "#" . $fieldName . " refers to the inverse side ". - "field " . $assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " which does not exist."; - } elseif ($targetMetadata->associationMappings[$assoc['inversedBy']]['mappedBy'] == null) { - $ce[] = "The field " . $class->name . "#" . $fieldName . " is on the owning side of a ". - "bi-directional relationship, but the specified mappedBy association on the target-entity ". - $assoc['targetEntity'] . "#" . $assoc['mappedBy'] . " does not contain the required ". - "'inversedBy' attribute."; - } elseif ($targetMetadata->associationMappings[$assoc['inversedBy']]['mappedBy'] != $fieldName) { - $ce[] = "The mappings " . $class->name . "#" . $fieldName . " and " . - $assoc['targetEntity'] . "#" . $assoc['inversedBy'] . " are ". - "inconsistent with each other."; - } - - // Verify inverse side/owning side match each other - if (array_key_exists($assoc['inversedBy'], $targetMetadata->associationMappings)) { - $targetAssoc = $targetMetadata->associationMappings[$assoc['inversedBy']]; - if ($assoc['type'] == ClassMetadataInfo::ONE_TO_ONE && $targetAssoc['type'] !== ClassMetadataInfo::ONE_TO_ONE) { - $ce[] = "If association " . $class->name . "#" . $fieldName . " is one-to-one, then the inversed " . - "side " . $targetMetadata->name . "#" . $assoc['inversedBy'] . " has to be one-to-one as well."; - } elseif ($assoc['type'] == ClassMetadataInfo::MANY_TO_ONE && $targetAssoc['type'] !== ClassMetadataInfo::ONE_TO_MANY) { - $ce[] = "If association " . $class->name . "#" . $fieldName . " is many-to-one, then the inversed " . - "side " . $targetMetadata->name . "#" . $assoc['inversedBy'] . " has to be one-to-many."; - } elseif ($assoc['type'] == ClassMetadataInfo::MANY_TO_MANY && $targetAssoc['type'] !== ClassMetadataInfo::MANY_TO_MANY) { - $ce[] = "If association " . $class->name . "#" . $fieldName . " is many-to-many, then the inversed " . - "side " . $targetMetadata->name . "#" . $assoc['inversedBy'] . " has to be many-to-many as well."; - } - } - } - - if ($assoc['isOwningSide']) { - if ($assoc['type'] == ClassMetadataInfo::MANY_TO_MANY) { - $identifierColumns = $class->getIdentifierColumnNames(); - foreach ($assoc['joinTable']['joinColumns'] as $joinColumn) { - if (!in_array($joinColumn['referencedColumnName'], $identifierColumns)) { - $ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' " . - "has to be a primary key column on the target entity class '".$class->name."'."; - break; - } - } - - $identifierColumns = $targetMetadata->getIdentifierColumnNames(); - foreach ($assoc['joinTable']['inverseJoinColumns'] as $inverseJoinColumn) { - if (! in_array($inverseJoinColumn['referencedColumnName'], $identifierColumns)) { - $ce[] = "The referenced column name '" . $inverseJoinColumn['referencedColumnName'] . "' " . - "has to be a primary key column on the target entity class '" .$targetMetadata->name . "'."; - break; - } - } - - if (count($targetMetadata->getIdentifierColumnNames()) != count($assoc['joinTable']['inverseJoinColumns'])) { - $ce[] = "The inverse join columns of the many-to-many table '" . $assoc['joinTable']['name'] . "' " . - "have to contain to ALL identifier columns of the target entity '". $targetMetadata->name . "', " . - "however '" . implode(", ", array_diff($targetMetadata->getIdentifierColumnNames(), array_values($assoc['relationToTargetKeyColumns']))) . - "' are missing."; - } - - if (count($class->getIdentifierColumnNames()) != count($assoc['joinTable']['joinColumns'])) { - $ce[] = "The join columns of the many-to-many table '" . $assoc['joinTable']['name'] . "' " . - "have to contain to ALL identifier columns of the source entity '". $class->name . "', " . - "however '" . implode(", ", array_diff($class->getIdentifierColumnNames(), array_values($assoc['relationToSourceKeyColumns']))) . - "' are missing."; - } - - } elseif ($assoc['type'] & ClassMetadataInfo::TO_ONE) { - $identifierColumns = $targetMetadata->getIdentifierColumnNames(); - foreach ($assoc['joinColumns'] as $joinColumn) { - if (!in_array($joinColumn['referencedColumnName'], $identifierColumns)) { - $ce[] = "The referenced column name '" . $joinColumn['referencedColumnName'] . "' " . - "has to be a primary key column on the target entity class '".$targetMetadata->name."'."; - } - } - - if (count($identifierColumns) != count($assoc['joinColumns'])) { - $ids = []; - - foreach ($assoc['joinColumns'] as $joinColumn) { - $ids[] = $joinColumn['name']; - } - - $ce[] = "The join columns of the association '" . $assoc['fieldName'] . "' " . - "have to match to ALL identifier columns of the target entity '". $targetMetadata->name . "', " . - "however '" . implode(", ", array_diff($targetMetadata->getIdentifierColumnNames(), $ids)) . - "' are missing."; - } - } - } - - if (isset($assoc['orderBy']) && $assoc['orderBy'] !== null) { - foreach ($assoc['orderBy'] as $orderField => $orientation) { - if (!$targetMetadata->hasField($orderField) && !$targetMetadata->hasAssociation($orderField)) { - $ce[] = "The association " . $class->name."#".$fieldName." is ordered by a foreign field " . - $orderField . " that is not a field on the target entity " . $targetMetadata->name . "."; - continue; - } - if ($targetMetadata->isCollectionValuedAssociation($orderField)) { - $ce[] = "The association " . $class->name."#".$fieldName." is ordered by a field " . - $orderField . " on " . $targetMetadata->name . " that is a collection-valued association."; - continue; - } - if ($targetMetadata->isAssociationInverseSide($orderField)) { - $ce[] = "The association " . $class->name."#".$fieldName." is ordered by a field " . - $orderField . " on " . $targetMetadata->name . " that is the inverse side of an association."; - continue; - } - } - } - } - - foreach ($class->subClasses as $subClass) { - if (!in_array($class->name, class_parents($subClass))) { - $ce[] = "According to the discriminator map class '" . $subClass . "' has to be a child ". - "of '" . $class->name . "' but these entities are not related through inheritance."; - } - } - - return $ce; - } - - /** - * Checks if the Database Schema is in sync with the current metadata state. - * - * @return bool - */ - public function schemaInSyncWithMetadata() - { - $schemaTool = new SchemaTool($this->em); - - $allMetadata = $this->em->getMetadataFactory()->getAllMetadata(); - - return count($schemaTool->getUpdateSchemaSql($allMetadata, true)) == 0; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Setup.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Setup.php deleted file mode 100644 index 302db67..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/Setup.php +++ /dev/null @@ -1,195 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools; - -use Doctrine\Common\ClassLoader; -use Doctrine\Common\Cache\Cache; -use Doctrine\Common\Cache\CacheProvider; -use Doctrine\Common\Cache\ArrayCache; -use Doctrine\ORM\Configuration; -use Doctrine\ORM\Mapping\Driver\XmlDriver; -use Doctrine\ORM\Mapping\Driver\YamlDriver; - -/** - * Convenience class for setting up Doctrine from different installations and configurations. - * - * @author Benjamin Eberlei - */ -class Setup -{ - /** - * Use this method to register all autoloads for a downloaded Doctrine library. - * Pick the directory the library was uncompressed into. - * - * @param string $directory - * - * @return void - */ - public static function registerAutoloadDirectory($directory) - { - if (!class_exists('Doctrine\Common\ClassLoader', false)) { - require_once $directory . "/Doctrine/Common/ClassLoader.php"; - } - - $loader = new ClassLoader("Doctrine", $directory); - $loader->register(); - - $loader = new ClassLoader("Symfony\Component", $directory . "/Doctrine"); - $loader->register(); - } - - /** - * Creates a configuration with an annotation metadata driver. - * - * @param array $paths - * @param boolean $isDevMode - * @param string $proxyDir - * @param Cache $cache - * @param bool $useSimpleAnnotationReader - * - * @return Configuration - */ - public static function createAnnotationMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null, $useSimpleAnnotationReader = true) - { - $config = self::createConfiguration($isDevMode, $proxyDir, $cache); - $config->setMetadataDriverImpl($config->newDefaultAnnotationDriver($paths, $useSimpleAnnotationReader)); - - return $config; - } - - /** - * Creates a configuration with a xml metadata driver. - * - * @param array $paths - * @param boolean $isDevMode - * @param string $proxyDir - * @param Cache $cache - * - * @return Configuration - */ - public static function createXMLMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null) - { - $config = self::createConfiguration($isDevMode, $proxyDir, $cache); - $config->setMetadataDriverImpl(new XmlDriver($paths)); - - return $config; - } - - /** - * Creates a configuration with a yaml metadata driver. - * - * @param array $paths - * @param boolean $isDevMode - * @param string $proxyDir - * @param Cache $cache - * - * @return Configuration - */ - public static function createYAMLMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null) - { - $config = self::createConfiguration($isDevMode, $proxyDir, $cache); - $config->setMetadataDriverImpl(new YamlDriver($paths)); - - return $config; - } - - /** - * Creates a configuration without a metadata driver. - * - * @param bool $isDevMode - * @param string $proxyDir - * @param Cache $cache - * - * @return Configuration - */ - public static function createConfiguration($isDevMode = false, $proxyDir = null, Cache $cache = null) - { - $proxyDir = $proxyDir ?: sys_get_temp_dir(); - - $cache = self::createCacheConfiguration($isDevMode, $proxyDir, $cache); - - $config = new Configuration(); - $config->setMetadataCacheImpl($cache); - $config->setQueryCacheImpl($cache); - $config->setResultCacheImpl($cache); - $config->setProxyDir($proxyDir); - $config->setProxyNamespace('DoctrineProxies'); - $config->setAutoGenerateProxyClasses($isDevMode); - - return $config; - } - - private static function createCacheConfiguration(bool $isDevMode, string $proxyDir, ?Cache $cache) : Cache - { - $cache = self::createCacheInstance($isDevMode, $cache); - - if ( ! $cache instanceof CacheProvider) { - return $cache; - } - - $namespace = $cache->getNamespace(); - - if ($namespace !== '') { - $namespace .= ':'; - } - - $cache->setNamespace($namespace . 'dc2_' . md5($proxyDir) . '_'); // to avoid collisions - - return $cache; - } - - private static function createCacheInstance(bool $isDevMode, ?Cache $cache) : Cache - { - if ($cache !== null) { - return $cache; - } - - if ($isDevMode === true) { - return new ArrayCache(); - } - - if (extension_loaded('apcu')) { - return new \Doctrine\Common\Cache\ApcuCache(); - } - - - if (extension_loaded('memcached')) { - $memcached = new \Memcached(); - $memcached->addServer('127.0.0.1', 11211); - - $cache = new \Doctrine\Common\Cache\MemcachedCache(); - $cache->setMemcached($memcached); - - return $cache; - } - - if (extension_loaded('redis')) { - $redis = new \Redis(); - $redis->connect('127.0.0.1'); - - $cache = new \Doctrine\Common\Cache\RedisCache(); - $cache->setRedis($redis); - - return $cache; - } - - return new ArrayCache(); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolEvents.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolEvents.php deleted file mode 100644 index aebb5d8..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolEvents.php +++ /dev/null @@ -1,42 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools; - -class ToolEvents -{ - /** - * The postGenerateSchemaTable event occurs in SchemaTool#getSchemaFromMetadata() - * whenever an entity class is transformed into its table representation. It receives - * the current non-complete Schema instance, the Entity Metadata Class instance and - * the Schema Table instance of this entity. - * - * @var string - */ - const postGenerateSchemaTable = 'postGenerateSchemaTable'; - - /** - * The postGenerateSchema event is triggered in SchemaTool#getSchemaFromMetadata() - * after all entity classes have been transformed into the related Schema structure. - * The EventArgs contain the EntityManager and the created Schema instance. - * - * @var string - */ - const postGenerateSchema = 'postGenerateSchema'; -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolsException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolsException.php deleted file mode 100644 index 95b3af0..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Tools/ToolsException.php +++ /dev/null @@ -1,46 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Tools; - -use Doctrine\ORM\ORMException; -use Throwable; - -/** - * Tools related Exceptions. - * - * @author Benjamin Eberlei - */ -class ToolsException extends ORMException -{ - public static function schemaToolFailure(string $sql, Throwable $e) : self - { - return new self("Schema-Tool failed with Error '" . $e->getMessage() . "' while executing DDL: " . $sql, "0", $e); - } - - /** - * @param string $type - * - * @return ToolsException - */ - public static function couldNotMapDoctrine1Type($type) - { - return new self("Could not map doctrine 1 type '$type'!"); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/TransactionRequiredException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/TransactionRequiredException.php deleted file mode 100644 index c3417b6..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/TransactionRequiredException.php +++ /dev/null @@ -1,40 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -/** - * Is thrown when a transaction is required for the current operation, but there is none open. - * - * @license http://www.opensource.org/licenses/mit-license.php MIT - * @link www.doctrine-project.com - * @since 1.0 - * @author Benjamin Eberlei - * @author Roman Borschel - */ -class TransactionRequiredException extends ORMException -{ - /** - * @return TransactionRequiredException - */ - static public function transactionRequired() - { - return new self('An open transaction is required for this operation.'); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/UnexpectedResultException.php b/vendor/doctrine/orm/lib/Doctrine/ORM/UnexpectedResultException.php deleted file mode 100644 index 3cd561f..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/UnexpectedResultException.php +++ /dev/null @@ -1,30 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -/** - * Exception for a unexpected query result. - * - * @author Fabio B. Silva - * @since 2.3 - */ -class UnexpectedResultException extends ORMException -{ -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php b/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php deleted file mode 100644 index f7b32b3..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php +++ /dev/null @@ -1,3628 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Collection; -use Doctrine\Common\NotifyPropertyChanged; -use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService; -use Doctrine\Common\Persistence\ObjectManagerAware; -use Doctrine\Common\PropertyChangedListener; -use Doctrine\DBAL\LockMode; -use Doctrine\ORM\Cache\Persister\CachedPersister; -use Doctrine\ORM\Event\LifecycleEventArgs; -use Doctrine\ORM\Event\ListenersInvoker; -use Doctrine\ORM\Event\OnFlushEventArgs; -use Doctrine\ORM\Event\PostFlushEventArgs; -use Doctrine\ORM\Event\PreFlushEventArgs; -use Doctrine\ORM\Event\PreUpdateEventArgs; -use Doctrine\ORM\Internal\HydrationCompleteHandler; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\Reflection\ReflectionPropertiesGetter; -use Doctrine\ORM\Persisters\Collection\ManyToManyPersister; -use Doctrine\ORM\Persisters\Collection\OneToManyPersister; -use Doctrine\ORM\Persisters\Entity\BasicEntityPersister; -use Doctrine\ORM\Persisters\Entity\JoinedSubclassPersister; -use Doctrine\ORM\Persisters\Entity\SingleTablePersister; -use Doctrine\ORM\Proxy\Proxy; -use Doctrine\ORM\Utility\IdentifierFlattener; -use InvalidArgumentException; -use Throwable; -use UnexpectedValueException; -use function get_class; - -/** - * The UnitOfWork is responsible for tracking changes to objects during an - * "object-level" transaction and for writing out changes to the database - * in the correct order. - * - * Internal note: This class contains highly performance-sensitive code. - * - * @since 2.0 - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Rob Caiger - */ -class UnitOfWork implements PropertyChangedListener -{ - /** - * An entity is in MANAGED state when its persistence is managed by an EntityManager. - */ - const STATE_MANAGED = 1; - - /** - * An entity is new if it has just been instantiated (i.e. using the "new" operator) - * and is not (yet) managed by an EntityManager. - */ - const STATE_NEW = 2; - - /** - * A detached entity is an instance with persistent state and identity that is not - * (or no longer) associated with an EntityManager (and a UnitOfWork). - */ - const STATE_DETACHED = 3; - - /** - * A removed entity instance is an instance with a persistent identity, - * associated with an EntityManager, whose persistent state will be deleted - * on commit. - */ - const STATE_REMOVED = 4; - - /** - * Hint used to collect all primary keys of associated entities during hydration - * and execute it in a dedicated query afterwards - * @see https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#temporarily-change-fetch-mode-in-dql - */ - const HINT_DEFEREAGERLOAD = 'deferEagerLoad'; - - /** - * The identity map that holds references to all managed entities that have - * an identity. The entities are grouped by their class name. - * Since all classes in a hierarchy must share the same identifier set, - * we always take the root class name of the hierarchy. - * - * @var array - */ - private $identityMap = []; - - /** - * Map of all identifiers of managed entities. - * Keys are object ids (spl_object_hash). - * - * @var array - */ - private $entityIdentifiers = []; - - /** - * Map of the original entity data of managed entities. - * Keys are object ids (spl_object_hash). This is used for calculating changesets - * at commit time. - * - * Internal note: Note that PHPs "copy-on-write" behavior helps a lot with memory usage. - * A value will only really be copied if the value in the entity is modified - * by the user. - * - * @var array - */ - private $originalEntityData = []; - - /** - * Map of entity changes. Keys are object ids (spl_object_hash). - * Filled at the beginning of a commit of the UnitOfWork and cleaned at the end. - * - * @var array - */ - private $entityChangeSets = []; - - /** - * The (cached) states of any known entities. - * Keys are object ids (spl_object_hash). - * - * @var array - */ - private $entityStates = []; - - /** - * Map of entities that are scheduled for dirty checking at commit time. - * This is only used for entities with a change tracking policy of DEFERRED_EXPLICIT. - * Keys are object ids (spl_object_hash). - * - * @var array - */ - private $scheduledForSynchronization = []; - - /** - * A list of all pending entity insertions. - * - * @var array - */ - private $entityInsertions = []; - - /** - * A list of all pending entity updates. - * - * @var array - */ - private $entityUpdates = []; - - /** - * Any pending extra updates that have been scheduled by persisters. - * - * @var array - */ - private $extraUpdates = []; - - /** - * A list of all pending entity deletions. - * - * @var array - */ - private $entityDeletions = []; - - /** - * New entities that were discovered through relationships that were not - * marked as cascade-persist. During flush, this array is populated and - * then pruned of any entities that were discovered through a valid - * cascade-persist path. (Leftovers cause an error.) - * - * Keys are OIDs, payload is a two-item array describing the association - * and the entity. - * - * @var object[][]|array[][] indexed by respective object spl_object_hash() - */ - private $nonCascadedNewDetectedEntities = []; - - /** - * All pending collection deletions. - * - * @var array - */ - private $collectionDeletions = []; - - /** - * All pending collection updates. - * - * @var array - */ - private $collectionUpdates = []; - - /** - * List of collections visited during changeset calculation on a commit-phase of a UnitOfWork. - * At the end of the UnitOfWork all these collections will make new snapshots - * of their data. - * - * @var array - */ - private $visitedCollections = []; - - /** - * The EntityManager that "owns" this UnitOfWork instance. - * - * @var EntityManagerInterface - */ - private $em; - - /** - * The entity persister instances used to persist entity instances. - * - * @var array - */ - private $persisters = []; - - /** - * The collection persister instances used to persist collections. - * - * @var array - */ - private $collectionPersisters = []; - - /** - * The EventManager used for dispatching events. - * - * @var \Doctrine\Common\EventManager - */ - private $evm; - - /** - * The ListenersInvoker used for dispatching events. - * - * @var \Doctrine\ORM\Event\ListenersInvoker - */ - private $listenersInvoker; - - /** - * The IdentifierFlattener used for manipulating identifiers - * - * @var \Doctrine\ORM\Utility\IdentifierFlattener - */ - private $identifierFlattener; - - /** - * Orphaned entities that are scheduled for removal. - * - * @var array - */ - private $orphanRemovals = []; - - /** - * Read-Only objects are never evaluated - * - * @var array - */ - private $readOnlyObjects = []; - - /** - * Map of Entity Class-Names and corresponding IDs that should eager loaded when requested. - * - * @var array - */ - private $eagerLoadingEntities = []; - - /** - * @var boolean - */ - protected $hasCache = false; - - /** - * Helper for handling completion of hydration - * - * @var HydrationCompleteHandler - */ - private $hydrationCompleteHandler; - - /** - * @var ReflectionPropertiesGetter - */ - private $reflectionPropertiesGetter; - - /** - * Initializes a new UnitOfWork instance, bound to the given EntityManager. - * - * @param EntityManagerInterface $em - */ - public function __construct(EntityManagerInterface $em) - { - $this->em = $em; - $this->evm = $em->getEventManager(); - $this->listenersInvoker = new ListenersInvoker($em); - $this->hasCache = $em->getConfiguration()->isSecondLevelCacheEnabled(); - $this->identifierFlattener = new IdentifierFlattener($this, $em->getMetadataFactory()); - $this->hydrationCompleteHandler = new HydrationCompleteHandler($this->listenersInvoker, $em); - $this->reflectionPropertiesGetter = new ReflectionPropertiesGetter(new RuntimeReflectionService()); - } - - /** - * Commits the UnitOfWork, executing all operations that have been postponed - * up to this point. The state of all managed entities will be synchronized with - * the database. - * - * The operations are executed in the following order: - * - * 1) All entity insertions - * 2) All entity updates - * 3) All collection deletions - * 4) All collection updates - * 5) All entity deletions - * - * @param null|object|array $entity - * - * @return void - * - * @throws \Exception - */ - public function commit($entity = null) - { - // Raise preFlush - if ($this->evm->hasListeners(Events::preFlush)) { - $this->evm->dispatchEvent(Events::preFlush, new PreFlushEventArgs($this->em)); - } - - // Compute changes done since last commit. - if (null === $entity) { - $this->computeChangeSets(); - } elseif (is_object($entity)) { - $this->computeSingleEntityChangeSet($entity); - } elseif (is_array($entity)) { - foreach ($entity as $object) { - $this->computeSingleEntityChangeSet($object); - } - } - - if ( ! ($this->entityInsertions || - $this->entityDeletions || - $this->entityUpdates || - $this->collectionUpdates || - $this->collectionDeletions || - $this->orphanRemovals)) { - $this->dispatchOnFlushEvent(); - $this->dispatchPostFlushEvent(); - - $this->postCommitCleanup($entity); - - return; // Nothing to do. - } - - $this->assertThatThereAreNoUnintentionallyNonPersistedAssociations(); - - if ($this->orphanRemovals) { - foreach ($this->orphanRemovals as $orphan) { - $this->remove($orphan); - } - } - - $this->dispatchOnFlushEvent(); - - // Now we need a commit order to maintain referential integrity - $commitOrder = $this->getCommitOrder(); - - $conn = $this->em->getConnection(); - $conn->beginTransaction(); - - try { - // Collection deletions (deletions of complete collections) - foreach ($this->collectionDeletions as $collectionToDelete) { - if (! $collectionToDelete instanceof PersistentCollection) { - $this->getCollectionPersister($collectionToDelete->getMapping())->delete($collectionToDelete); - - continue; - } - - // Deferred explicit tracked collections can be removed only when owning relation was persisted - $owner = $collectionToDelete->getOwner(); - - if ($this->em->getClassMetadata(get_class($owner))->isChangeTrackingDeferredImplicit() || $this->isScheduledForDirtyCheck($owner)) { - $this->getCollectionPersister($collectionToDelete->getMapping())->delete($collectionToDelete); - } - } - - if ($this->entityInsertions) { - foreach ($commitOrder as $class) { - $this->executeInserts($class); - } - } - - if ($this->entityUpdates) { - foreach ($commitOrder as $class) { - $this->executeUpdates($class); - } - } - - // Extra updates that were requested by persisters. - if ($this->extraUpdates) { - $this->executeExtraUpdates(); - } - - // Collection updates (deleteRows, updateRows, insertRows) - foreach ($this->collectionUpdates as $collectionToUpdate) { - $this->getCollectionPersister($collectionToUpdate->getMapping())->update($collectionToUpdate); - } - - // Entity deletions come last and need to be in reverse commit order - if ($this->entityDeletions) { - for ($count = count($commitOrder), $i = $count - 1; $i >= 0 && $this->entityDeletions; --$i) { - $this->executeDeletions($commitOrder[$i]); - } - } - - $conn->commit(); - } catch (Throwable $e) { - $this->em->close(); - $conn->rollBack(); - - $this->afterTransactionRolledBack(); - - throw $e; - } - - $this->afterTransactionComplete(); - - // Take new snapshots from visited collections - foreach ($this->visitedCollections as $coll) { - $coll->takeSnapshot(); - } - - $this->dispatchPostFlushEvent(); - - $this->postCommitCleanup($entity); - } - - /** - * @param null|object|object[] $entity - */ - private function postCommitCleanup($entity) : void - { - $this->entityInsertions = - $this->entityUpdates = - $this->entityDeletions = - $this->extraUpdates = - $this->collectionUpdates = - $this->nonCascadedNewDetectedEntities = - $this->collectionDeletions = - $this->visitedCollections = - $this->orphanRemovals = []; - - if (null === $entity) { - $this->entityChangeSets = $this->scheduledForSynchronization = []; - - return; - } - - $entities = \is_object($entity) - ? [$entity] - : $entity; - - foreach ($entities as $object) { - $oid = \spl_object_hash($object); - - $this->clearEntityChangeSet($oid); - - unset($this->scheduledForSynchronization[$this->em->getClassMetadata(\get_class($object))->rootEntityName][$oid]); - } - } - - /** - * Computes the changesets of all entities scheduled for insertion. - * - * @return void - */ - private function computeScheduleInsertsChangeSets() - { - foreach ($this->entityInsertions as $entity) { - $class = $this->em->getClassMetadata(get_class($entity)); - - $this->computeChangeSet($class, $entity); - } - } - - /** - * Only flushes the given entity according to a ruleset that keeps the UoW consistent. - * - * 1. All entities scheduled for insertion, (orphan) removals and changes in collections are processed as well! - * 2. Read Only entities are skipped. - * 3. Proxies are skipped. - * 4. Only if entity is properly managed. - * - * @param object $entity - * - * @return void - * - * @throws \InvalidArgumentException - */ - private function computeSingleEntityChangeSet($entity) - { - $state = $this->getEntityState($entity); - - if ($state !== self::STATE_MANAGED && $state !== self::STATE_REMOVED) { - throw new \InvalidArgumentException("Entity has to be managed or scheduled for removal for single computation " . self::objToStr($entity)); - } - - $class = $this->em->getClassMetadata(get_class($entity)); - - if ($state === self::STATE_MANAGED && $class->isChangeTrackingDeferredImplicit()) { - $this->persist($entity); - } - - // Compute changes for INSERTed entities first. This must always happen even in this case. - $this->computeScheduleInsertsChangeSets(); - - if ($class->isReadOnly) { - return; - } - - // Ignore uninitialized proxy objects - if ($entity instanceof Proxy && ! $entity->__isInitialized__) { - return; - } - - // Only MANAGED entities that are NOT SCHEDULED FOR INSERTION OR DELETION are processed here. - $oid = spl_object_hash($entity); - - if ( ! isset($this->entityInsertions[$oid]) && ! isset($this->entityDeletions[$oid]) && isset($this->entityStates[$oid])) { - $this->computeChangeSet($class, $entity); - } - } - - /** - * Executes any extra updates that have been scheduled. - */ - private function executeExtraUpdates() - { - foreach ($this->extraUpdates as $oid => $update) { - list ($entity, $changeset) = $update; - - $this->entityChangeSets[$oid] = $changeset; - $this->getEntityPersister(get_class($entity))->update($entity); - } - - $this->extraUpdates = []; - } - - /** - * Gets the changeset for an entity. - * - * @param object $entity - * - * @return array - */ - public function & getEntityChangeSet($entity) - { - $oid = spl_object_hash($entity); - $data = []; - - if (!isset($this->entityChangeSets[$oid])) { - return $data; - } - - return $this->entityChangeSets[$oid]; - } - - /** - * Computes the changes that happened to a single entity. - * - * Modifies/populates the following properties: - * - * {@link _originalEntityData} - * If the entity is NEW or MANAGED but not yet fully persisted (only has an id) - * then it was not fetched from the database and therefore we have no original - * entity data yet. All of the current entity data is stored as the original entity data. - * - * {@link _entityChangeSets} - * The changes detected on all properties of the entity are stored there. - * A change is a tuple array where the first entry is the old value and the second - * entry is the new value of the property. Changesets are used by persisters - * to INSERT/UPDATE the persistent entity state. - * - * {@link _entityUpdates} - * If the entity is already fully MANAGED (has been fetched from the database before) - * and any changes to its properties are detected, then a reference to the entity is stored - * there to mark it for an update. - * - * {@link _collectionDeletions} - * If a PersistentCollection has been de-referenced in a fully MANAGED entity, - * then this collection is marked for deletion. - * - * @ignore - * - * @internal Don't call from the outside. - * - * @param ClassMetadata $class The class descriptor of the entity. - * @param object $entity The entity for which to compute the changes. - * - * @return void - */ - public function computeChangeSet(ClassMetadata $class, $entity) - { - $oid = spl_object_hash($entity); - - if (isset($this->readOnlyObjects[$oid])) { - return; - } - - if ( ! $class->isInheritanceTypeNone()) { - $class = $this->em->getClassMetadata(get_class($entity)); - } - - $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preFlush) & ~ListenersInvoker::INVOKE_MANAGER; - - if ($invoke !== ListenersInvoker::INVOKE_NONE) { - $this->listenersInvoker->invoke($class, Events::preFlush, $entity, new PreFlushEventArgs($this->em), $invoke); - } - - $actualData = []; - - foreach ($class->reflFields as $name => $refProp) { - $value = $refProp->getValue($entity); - - if ($class->isCollectionValuedAssociation($name) && $value !== null) { - if ($value instanceof PersistentCollection) { - if ($value->getOwner() === $entity) { - continue; - } - - $value = new ArrayCollection($value->getValues()); - } - - // If $value is not a Collection then use an ArrayCollection. - if ( ! $value instanceof Collection) { - $value = new ArrayCollection($value); - } - - $assoc = $class->associationMappings[$name]; - - // Inject PersistentCollection - $value = new PersistentCollection( - $this->em, $this->em->getClassMetadata($assoc['targetEntity']), $value - ); - $value->setOwner($entity, $assoc); - $value->setDirty( ! $value->isEmpty()); - - $class->reflFields[$name]->setValue($entity, $value); - - $actualData[$name] = $value; - - continue; - } - - if (( ! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity()) && ($name !== $class->versionField)) { - $actualData[$name] = $value; - } - } - - if ( ! isset($this->originalEntityData[$oid])) { - // Entity is either NEW or MANAGED but not yet fully persisted (only has an id). - // These result in an INSERT. - $this->originalEntityData[$oid] = $actualData; - $changeSet = []; - - foreach ($actualData as $propName => $actualValue) { - if ( ! isset($class->associationMappings[$propName])) { - $changeSet[$propName] = [null, $actualValue]; - - continue; - } - - $assoc = $class->associationMappings[$propName]; - - if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) { - $changeSet[$propName] = [null, $actualValue]; - } - } - - $this->entityChangeSets[$oid] = $changeSet; - } else { - // Entity is "fully" MANAGED: it was already fully persisted before - // and we have a copy of the original data - $originalData = $this->originalEntityData[$oid]; - $isChangeTrackingNotify = $class->isChangeTrackingNotify(); - $changeSet = ($isChangeTrackingNotify && isset($this->entityChangeSets[$oid])) - ? $this->entityChangeSets[$oid] - : []; - - foreach ($actualData as $propName => $actualValue) { - // skip field, its a partially omitted one! - if ( ! (isset($originalData[$propName]) || array_key_exists($propName, $originalData))) { - continue; - } - - $orgValue = $originalData[$propName]; - - // skip if value haven't changed - if ($orgValue === $actualValue) { - continue; - } - - // if regular field - if ( ! isset($class->associationMappings[$propName])) { - if ($isChangeTrackingNotify) { - continue; - } - - $changeSet[$propName] = [$orgValue, $actualValue]; - - continue; - } - - $assoc = $class->associationMappings[$propName]; - - // Persistent collection was exchanged with the "originally" - // created one. This can only mean it was cloned and replaced - // on another entity. - if ($actualValue instanceof PersistentCollection) { - $owner = $actualValue->getOwner(); - if ($owner === null) { // cloned - $actualValue->setOwner($entity, $assoc); - } else if ($owner !== $entity) { // no clone, we have to fix - if (!$actualValue->isInitialized()) { - $actualValue->initialize(); // we have to do this otherwise the cols share state - } - $newValue = clone $actualValue; - $newValue->setOwner($entity, $assoc); - $class->reflFields[$propName]->setValue($entity, $newValue); - } - } - - if ($orgValue instanceof PersistentCollection) { - // A PersistentCollection was de-referenced, so delete it. - $coid = spl_object_hash($orgValue); - - if (isset($this->collectionDeletions[$coid])) { - continue; - } - - $this->collectionDeletions[$coid] = $orgValue; - $changeSet[$propName] = $orgValue; // Signal changeset, to-many assocs will be ignored. - - continue; - } - - if ($assoc['type'] & ClassMetadata::TO_ONE) { - if ($assoc['isOwningSide']) { - $changeSet[$propName] = [$orgValue, $actualValue]; - } - - if ($orgValue !== null && $assoc['orphanRemoval']) { - $this->scheduleOrphanRemoval($orgValue); - } - } - } - - if ($changeSet) { - $this->entityChangeSets[$oid] = $changeSet; - $this->originalEntityData[$oid] = $actualData; - $this->entityUpdates[$oid] = $entity; - } - } - - // Look for changes in associations of the entity - foreach ($class->associationMappings as $field => $assoc) { - if (($val = $class->reflFields[$field]->getValue($entity)) === null) { - continue; - } - - $this->computeAssociationChanges($assoc, $val); - - if ( ! isset($this->entityChangeSets[$oid]) && - $assoc['isOwningSide'] && - $assoc['type'] == ClassMetadata::MANY_TO_MANY && - $val instanceof PersistentCollection && - $val->isDirty()) { - - $this->entityChangeSets[$oid] = []; - $this->originalEntityData[$oid] = $actualData; - $this->entityUpdates[$oid] = $entity; - } - } - } - - /** - * Computes all the changes that have been done to entities and collections - * since the last commit and stores these changes in the _entityChangeSet map - * temporarily for access by the persisters, until the UoW commit is finished. - * - * @return void - */ - public function computeChangeSets() - { - // Compute changes for INSERTed entities first. This must always happen. - $this->computeScheduleInsertsChangeSets(); - - // Compute changes for other MANAGED entities. Change tracking policies take effect here. - foreach ($this->identityMap as $className => $entities) { - $class = $this->em->getClassMetadata($className); - - // Skip class if instances are read-only - if ($class->isReadOnly) { - continue; - } - - // If change tracking is explicit or happens through notification, then only compute - // changes on entities of that type that are explicitly marked for synchronization. - switch (true) { - case ($class->isChangeTrackingDeferredImplicit()): - $entitiesToProcess = $entities; - break; - - case (isset($this->scheduledForSynchronization[$className])): - $entitiesToProcess = $this->scheduledForSynchronization[$className]; - break; - - default: - $entitiesToProcess = []; - - } - - foreach ($entitiesToProcess as $entity) { - // Ignore uninitialized proxy objects - if ($entity instanceof Proxy && ! $entity->__isInitialized__) { - continue; - } - - // Only MANAGED entities that are NOT SCHEDULED FOR INSERTION OR DELETION are processed here. - $oid = spl_object_hash($entity); - - if ( ! isset($this->entityInsertions[$oid]) && ! isset($this->entityDeletions[$oid]) && isset($this->entityStates[$oid])) { - $this->computeChangeSet($class, $entity); - } - } - } - } - - /** - * Computes the changes of an association. - * - * @param array $assoc The association mapping. - * @param mixed $value The value of the association. - * - * @throws ORMInvalidArgumentException - * @throws ORMException - * - * @return void - */ - private function computeAssociationChanges($assoc, $value) - { - if ($value instanceof Proxy && ! $value->__isInitialized__) { - return; - } - - if ($value instanceof PersistentCollection && $value->isDirty()) { - $coid = spl_object_hash($value); - - $this->collectionUpdates[$coid] = $value; - $this->visitedCollections[$coid] = $value; - } - - // Look through the entities, and in any of their associations, - // for transient (new) entities, recursively. ("Persistence by reachability") - // Unwrap. Uninitialized collections will simply be empty. - $unwrappedValue = ($assoc['type'] & ClassMetadata::TO_ONE) ? [$value] : $value->unwrap(); - $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); - - foreach ($unwrappedValue as $key => $entry) { - if (! ($entry instanceof $targetClass->name)) { - throw ORMInvalidArgumentException::invalidAssociation($targetClass, $assoc, $entry); - } - - $state = $this->getEntityState($entry, self::STATE_NEW); - - if ( ! ($entry instanceof $assoc['targetEntity'])) { - throw ORMException::unexpectedAssociationValue($assoc['sourceEntity'], $assoc['fieldName'], get_class($entry), $assoc['targetEntity']); - } - - switch ($state) { - case self::STATE_NEW: - if ( ! $assoc['isCascadePersist']) { - /* - * For now just record the details, because this may - * not be an issue if we later discover another pathway - * through the object-graph where cascade-persistence - * is enabled for this object. - */ - $this->nonCascadedNewDetectedEntities[\spl_object_hash($entry)] = [$assoc, $entry]; - - break; - } - - $this->persistNew($targetClass, $entry); - $this->computeChangeSet($targetClass, $entry); - - break; - - case self::STATE_REMOVED: - // Consume the $value as array (it's either an array or an ArrayAccess) - // and remove the element from Collection. - if ($assoc['type'] & ClassMetadata::TO_MANY) { - unset($value[$key]); - } - break; - - case self::STATE_DETACHED: - // Can actually not happen right now as we assume STATE_NEW, - // so the exception will be raised from the DBAL layer (constraint violation). - throw ORMInvalidArgumentException::detachedEntityFoundThroughRelationship($assoc, $entry); - break; - - default: - // MANAGED associated entities are already taken into account - // during changeset calculation anyway, since they are in the identity map. - } - } - } - - /** - * @param \Doctrine\ORM\Mapping\ClassMetadata $class - * @param object $entity - * - * @return void - */ - private function persistNew($class, $entity) - { - $oid = spl_object_hash($entity); - $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::prePersist); - - if ($invoke !== ListenersInvoker::INVOKE_NONE) { - $this->listenersInvoker->invoke($class, Events::prePersist, $entity, new LifecycleEventArgs($entity, $this->em), $invoke); - } - - $idGen = $class->idGenerator; - - if ( ! $idGen->isPostInsertGenerator()) { - $idValue = $idGen->generate($this->em, $entity); - - if ( ! $idGen instanceof \Doctrine\ORM\Id\AssignedGenerator) { - $idValue = [$class->getSingleIdentifierFieldName() => $this->convertSingleFieldIdentifierToPHPValue($class, $idValue)]; - - $class->setIdentifierValues($entity, $idValue); - } - - // Some identifiers may be foreign keys to new entities. - // In this case, we don't have the value yet and should treat it as if we have a post-insert generator - if (! $this->hasMissingIdsWhichAreForeignKeys($class, $idValue)) { - $this->entityIdentifiers[$oid] = $idValue; - } - } - - $this->entityStates[$oid] = self::STATE_MANAGED; - - $this->scheduleForInsert($entity); - } - - /** - * @param mixed[] $idValue - */ - private function hasMissingIdsWhichAreForeignKeys(ClassMetadata $class, array $idValue) : bool - { - foreach ($idValue as $idField => $idFieldValue) { - if ($idFieldValue === null && isset($class->associationMappings[$idField])) { - return true; - } - } - - return false; - } - - /** - * INTERNAL: - * Computes the changeset of an individual entity, independently of the - * computeChangeSets() routine that is used at the beginning of a UnitOfWork#commit(). - * - * The passed entity must be a managed entity. If the entity already has a change set - * because this method is invoked during a commit cycle then the change sets are added. - * whereby changes detected in this method prevail. - * - * @ignore - * - * @param ClassMetadata $class The class descriptor of the entity. - * @param object $entity The entity for which to (re)calculate the change set. - * - * @return void - * - * @throws ORMInvalidArgumentException If the passed entity is not MANAGED. - */ - public function recomputeSingleEntityChangeSet(ClassMetadata $class, $entity) - { - $oid = spl_object_hash($entity); - - if ( ! isset($this->entityStates[$oid]) || $this->entityStates[$oid] != self::STATE_MANAGED) { - throw ORMInvalidArgumentException::entityNotManaged($entity); - } - - // skip if change tracking is "NOTIFY" - if ($class->isChangeTrackingNotify()) { - return; - } - - if ( ! $class->isInheritanceTypeNone()) { - $class = $this->em->getClassMetadata(get_class($entity)); - } - - $actualData = []; - - foreach ($class->reflFields as $name => $refProp) { - if (( ! $class->isIdentifier($name) || ! $class->isIdGeneratorIdentity()) - && ($name !== $class->versionField) - && ! $class->isCollectionValuedAssociation($name)) { - $actualData[$name] = $refProp->getValue($entity); - } - } - - if ( ! isset($this->originalEntityData[$oid])) { - throw new \RuntimeException('Cannot call recomputeSingleEntityChangeSet before computeChangeSet on an entity.'); - } - - $originalData = $this->originalEntityData[$oid]; - $changeSet = []; - - foreach ($actualData as $propName => $actualValue) { - $orgValue = $originalData[$propName] ?? null; - - if ($orgValue !== $actualValue) { - $changeSet[$propName] = [$orgValue, $actualValue]; - } - } - - if ($changeSet) { - if (isset($this->entityChangeSets[$oid])) { - $this->entityChangeSets[$oid] = array_merge($this->entityChangeSets[$oid], $changeSet); - } else if ( ! isset($this->entityInsertions[$oid])) { - $this->entityChangeSets[$oid] = $changeSet; - $this->entityUpdates[$oid] = $entity; - } - $this->originalEntityData[$oid] = $actualData; - } - } - - /** - * Executes all entity insertions for entities of the specified type. - * - * @param \Doctrine\ORM\Mapping\ClassMetadata $class - * - * @return void - */ - private function executeInserts($class) - { - $entities = []; - $className = $class->name; - $persister = $this->getEntityPersister($className); - $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postPersist); - - $insertionsForClass = []; - - foreach ($this->entityInsertions as $oid => $entity) { - - if ($this->em->getClassMetadata(get_class($entity))->name !== $className) { - continue; - } - - $insertionsForClass[$oid] = $entity; - - $persister->addInsert($entity); - - unset($this->entityInsertions[$oid]); - - if ($invoke !== ListenersInvoker::INVOKE_NONE) { - $entities[] = $entity; - } - } - - $postInsertIds = $persister->executeInserts(); - - if ($postInsertIds) { - // Persister returned post-insert IDs - foreach ($postInsertIds as $postInsertId) { - $idField = $class->getSingleIdentifierFieldName(); - $idValue = $this->convertSingleFieldIdentifierToPHPValue($class, $postInsertId['generatedId']); - - $entity = $postInsertId['entity']; - $oid = spl_object_hash($entity); - - $class->reflFields[$idField]->setValue($entity, $idValue); - - $this->entityIdentifiers[$oid] = [$idField => $idValue]; - $this->entityStates[$oid] = self::STATE_MANAGED; - $this->originalEntityData[$oid][$idField] = $idValue; - - $this->addToIdentityMap($entity); - } - } else { - foreach ($insertionsForClass as $oid => $entity) { - if (! isset($this->entityIdentifiers[$oid])) { - //entity was not added to identity map because some identifiers are foreign keys to new entities. - //add it now - $this->addToEntityIdentifiersAndEntityMap($class, $oid, $entity); - } - } - } - - foreach ($entities as $entity) { - $this->listenersInvoker->invoke($class, Events::postPersist, $entity, new LifecycleEventArgs($entity, $this->em), $invoke); - } - } - - /** - * @param object $entity - */ - private function addToEntityIdentifiersAndEntityMap(ClassMetadata $class, string $oid, $entity): void - { - $identifier = []; - - foreach ($class->getIdentifierFieldNames() as $idField) { - $value = $class->getFieldValue($entity, $idField); - - if (isset($class->associationMappings[$idField])) { - // NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced. - $value = $this->getSingleIdentifierValue($value); - } - - $identifier[$idField] = $this->originalEntityData[$oid][$idField] = $value; - } - - $this->entityStates[$oid] = self::STATE_MANAGED; - $this->entityIdentifiers[$oid] = $identifier; - - $this->addToIdentityMap($entity); - } - - /** - * Executes all entity updates for entities of the specified type. - * - * @param \Doctrine\ORM\Mapping\ClassMetadata $class - * - * @return void - */ - private function executeUpdates($class) - { - $className = $class->name; - $persister = $this->getEntityPersister($className); - $preUpdateInvoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preUpdate); - $postUpdateInvoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postUpdate); - - foreach ($this->entityUpdates as $oid => $entity) { - if ($this->em->getClassMetadata(get_class($entity))->name !== $className) { - continue; - } - - if ($preUpdateInvoke != ListenersInvoker::INVOKE_NONE) { - $this->listenersInvoker->invoke($class, Events::preUpdate, $entity, new PreUpdateEventArgs($entity, $this->em, $this->getEntityChangeSet($entity)), $preUpdateInvoke); - - $this->recomputeSingleEntityChangeSet($class, $entity); - } - - if ( ! empty($this->entityChangeSets[$oid])) { - $persister->update($entity); - } - - unset($this->entityUpdates[$oid]); - - if ($postUpdateInvoke != ListenersInvoker::INVOKE_NONE) { - $this->listenersInvoker->invoke($class, Events::postUpdate, $entity, new LifecycleEventArgs($entity, $this->em), $postUpdateInvoke); - } - } - } - - /** - * Executes all entity deletions for entities of the specified type. - * - * @param \Doctrine\ORM\Mapping\ClassMetadata $class - * - * @return void - */ - private function executeDeletions($class) - { - $className = $class->name; - $persister = $this->getEntityPersister($className); - $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postRemove); - - foreach ($this->entityDeletions as $oid => $entity) { - if ($this->em->getClassMetadata(get_class($entity))->name !== $className) { - continue; - } - - $persister->delete($entity); - - unset( - $this->entityDeletions[$oid], - $this->entityIdentifiers[$oid], - $this->originalEntityData[$oid], - $this->entityStates[$oid] - ); - - // Entity with this $oid after deletion treated as NEW, even if the $oid - // is obtained by a new entity because the old one went out of scope. - //$this->entityStates[$oid] = self::STATE_NEW; - if ( ! $class->isIdentifierNatural()) { - $class->reflFields[$class->identifier[0]]->setValue($entity, null); - } - - if ($invoke !== ListenersInvoker::INVOKE_NONE) { - $this->listenersInvoker->invoke($class, Events::postRemove, $entity, new LifecycleEventArgs($entity, $this->em), $invoke); - } - } - } - - /** - * Gets the commit order. - * - * @param array|null $entityChangeSet - * - * @return array - */ - private function getCommitOrder(array $entityChangeSet = null) - { - if ($entityChangeSet === null) { - $entityChangeSet = array_merge($this->entityInsertions, $this->entityUpdates, $this->entityDeletions); - } - - $calc = $this->getCommitOrderCalculator(); - - // See if there are any new classes in the changeset, that are not in the - // commit order graph yet (don't have a node). - // We have to inspect changeSet to be able to correctly build dependencies. - // It is not possible to use IdentityMap here because post inserted ids - // are not yet available. - $newNodes = []; - - foreach ($entityChangeSet as $entity) { - $class = $this->em->getClassMetadata(get_class($entity)); - - if ($calc->hasNode($class->name)) { - continue; - } - - $calc->addNode($class->name, $class); - - $newNodes[] = $class; - } - - // Calculate dependencies for new nodes - while ($class = array_pop($newNodes)) { - foreach ($class->associationMappings as $assoc) { - if ( ! ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE)) { - continue; - } - - $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); - - if ( ! $calc->hasNode($targetClass->name)) { - $calc->addNode($targetClass->name, $targetClass); - - $newNodes[] = $targetClass; - } - - $joinColumns = reset($assoc['joinColumns']); - - $calc->addDependency($targetClass->name, $class->name, (int)empty($joinColumns['nullable'])); - - // If the target class has mapped subclasses, these share the same dependency. - if ( ! $targetClass->subClasses) { - continue; - } - - foreach ($targetClass->subClasses as $subClassName) { - $targetSubClass = $this->em->getClassMetadata($subClassName); - - if ( ! $calc->hasNode($subClassName)) { - $calc->addNode($targetSubClass->name, $targetSubClass); - - $newNodes[] = $targetSubClass; - } - - $calc->addDependency($targetSubClass->name, $class->name, 1); - } - } - } - - return $calc->sort(); - } - - /** - * Schedules an entity for insertion into the database. - * If the entity already has an identifier, it will be added to the identity map. - * - * @param object $entity The entity to schedule for insertion. - * - * @return void - * - * @throws ORMInvalidArgumentException - * @throws \InvalidArgumentException - */ - public function scheduleForInsert($entity) - { - $oid = spl_object_hash($entity); - - if (isset($this->entityUpdates[$oid])) { - throw new InvalidArgumentException("Dirty entity can not be scheduled for insertion."); - } - - if (isset($this->entityDeletions[$oid])) { - throw ORMInvalidArgumentException::scheduleInsertForRemovedEntity($entity); - } - if (isset($this->originalEntityData[$oid]) && ! isset($this->entityInsertions[$oid])) { - throw ORMInvalidArgumentException::scheduleInsertForManagedEntity($entity); - } - - if (isset($this->entityInsertions[$oid])) { - throw ORMInvalidArgumentException::scheduleInsertTwice($entity); - } - - $this->entityInsertions[$oid] = $entity; - - if (isset($this->entityIdentifiers[$oid])) { - $this->addToIdentityMap($entity); - } - - if ($entity instanceof NotifyPropertyChanged) { - $entity->addPropertyChangedListener($this); - } - } - - /** - * Checks whether an entity is scheduled for insertion. - * - * @param object $entity - * - * @return boolean - */ - public function isScheduledForInsert($entity) - { - return isset($this->entityInsertions[spl_object_hash($entity)]); - } - - /** - * Schedules an entity for being updated. - * - * @param object $entity The entity to schedule for being updated. - * - * @return void - * - * @throws ORMInvalidArgumentException - */ - public function scheduleForUpdate($entity) - { - $oid = spl_object_hash($entity); - - if ( ! isset($this->entityIdentifiers[$oid])) { - throw ORMInvalidArgumentException::entityHasNoIdentity($entity, "scheduling for update"); - } - - if (isset($this->entityDeletions[$oid])) { - throw ORMInvalidArgumentException::entityIsRemoved($entity, "schedule for update"); - } - - if ( ! isset($this->entityUpdates[$oid]) && ! isset($this->entityInsertions[$oid])) { - $this->entityUpdates[$oid] = $entity; - } - } - - /** - * INTERNAL: - * Schedules an extra update that will be executed immediately after the - * regular entity updates within the currently running commit cycle. - * - * Extra updates for entities are stored as (entity, changeset) tuples. - * - * @ignore - * - * @param object $entity The entity for which to schedule an extra update. - * @param array $changeset The changeset of the entity (what to update). - * - * @return void - */ - public function scheduleExtraUpdate($entity, array $changeset) - { - $oid = spl_object_hash($entity); - $extraUpdate = [$entity, $changeset]; - - if (isset($this->extraUpdates[$oid])) { - list(, $changeset2) = $this->extraUpdates[$oid]; - - $extraUpdate = [$entity, $changeset + $changeset2]; - } - - $this->extraUpdates[$oid] = $extraUpdate; - } - - /** - * Checks whether an entity is registered as dirty in the unit of work. - * Note: Is not very useful currently as dirty entities are only registered - * at commit time. - * - * @param object $entity - * - * @return boolean - */ - public function isScheduledForUpdate($entity) - { - return isset($this->entityUpdates[spl_object_hash($entity)]); - } - - /** - * Checks whether an entity is registered to be checked in the unit of work. - * - * @param object $entity - * - * @return boolean - */ - public function isScheduledForDirtyCheck($entity) - { - $rootEntityName = $this->em->getClassMetadata(get_class($entity))->rootEntityName; - - return isset($this->scheduledForSynchronization[$rootEntityName][spl_object_hash($entity)]); - } - - /** - * INTERNAL: - * Schedules an entity for deletion. - * - * @param object $entity - * - * @return void - */ - public function scheduleForDelete($entity) - { - $oid = spl_object_hash($entity); - - if (isset($this->entityInsertions[$oid])) { - if ($this->isInIdentityMap($entity)) { - $this->removeFromIdentityMap($entity); - } - - unset($this->entityInsertions[$oid], $this->entityStates[$oid]); - - return; // entity has not been persisted yet, so nothing more to do. - } - - if ( ! $this->isInIdentityMap($entity)) { - return; - } - - $this->removeFromIdentityMap($entity); - - unset($this->entityUpdates[$oid]); - - if ( ! isset($this->entityDeletions[$oid])) { - $this->entityDeletions[$oid] = $entity; - $this->entityStates[$oid] = self::STATE_REMOVED; - } - } - - /** - * Checks whether an entity is registered as removed/deleted with the unit - * of work. - * - * @param object $entity - * - * @return boolean - */ - public function isScheduledForDelete($entity) - { - return isset($this->entityDeletions[spl_object_hash($entity)]); - } - - /** - * Checks whether an entity is scheduled for insertion, update or deletion. - * - * @param object $entity - * - * @return boolean - */ - public function isEntityScheduled($entity) - { - $oid = spl_object_hash($entity); - - return isset($this->entityInsertions[$oid]) - || isset($this->entityUpdates[$oid]) - || isset($this->entityDeletions[$oid]); - } - - /** - * INTERNAL: - * Registers an entity in the identity map. - * Note that entities in a hierarchy are registered with the class name of - * the root entity. - * - * @ignore - * - * @param object $entity The entity to register. - * - * @return boolean TRUE if the registration was successful, FALSE if the identity of - * the entity in question is already managed. - * - * @throws ORMInvalidArgumentException - */ - public function addToIdentityMap($entity) - { - $classMetadata = $this->em->getClassMetadata(get_class($entity)); - $identifier = $this->entityIdentifiers[spl_object_hash($entity)]; - - if (empty($identifier) || in_array(null, $identifier, true)) { - throw ORMInvalidArgumentException::entityWithoutIdentity($classMetadata->name, $entity); - } - - $idHash = implode(' ', $identifier); - $className = $classMetadata->rootEntityName; - - if (isset($this->identityMap[$className][$idHash])) { - return false; - } - - $this->identityMap[$className][$idHash] = $entity; - - return true; - } - - /** - * Gets the state of an entity with regard to the current unit of work. - * - * @param object $entity - * @param int|null $assume The state to assume if the state is not yet known (not MANAGED or REMOVED). - * This parameter can be set to improve performance of entity state detection - * by potentially avoiding a database lookup if the distinction between NEW and DETACHED - * is either known or does not matter for the caller of the method. - * - * @return int The entity state. - */ - public function getEntityState($entity, $assume = null) - { - $oid = spl_object_hash($entity); - - if (isset($this->entityStates[$oid])) { - return $this->entityStates[$oid]; - } - - if ($assume !== null) { - return $assume; - } - - // State can only be NEW or DETACHED, because MANAGED/REMOVED states are known. - // Note that you can not remember the NEW or DETACHED state in _entityStates since - // the UoW does not hold references to such objects and the object hash can be reused. - // More generally because the state may "change" between NEW/DETACHED without the UoW being aware of it. - $class = $this->em->getClassMetadata(get_class($entity)); - $id = $class->getIdentifierValues($entity); - - if ( ! $id) { - return self::STATE_NEW; - } - - if ($class->containsForeignIdentifier) { - $id = $this->identifierFlattener->flattenIdentifier($class, $id); - } - - switch (true) { - case ($class->isIdentifierNatural()): - // Check for a version field, if available, to avoid a db lookup. - if ($class->isVersioned) { - return ($class->getFieldValue($entity, $class->versionField)) - ? self::STATE_DETACHED - : self::STATE_NEW; - } - - // Last try before db lookup: check the identity map. - if ($this->tryGetById($id, $class->rootEntityName)) { - return self::STATE_DETACHED; - } - - // db lookup - if ($this->getEntityPersister($class->name)->exists($entity)) { - return self::STATE_DETACHED; - } - - return self::STATE_NEW; - - case ( ! $class->idGenerator->isPostInsertGenerator()): - // if we have a pre insert generator we can't be sure that having an id - // really means that the entity exists. We have to verify this through - // the last resort: a db lookup - - // Last try before db lookup: check the identity map. - if ($this->tryGetById($id, $class->rootEntityName)) { - return self::STATE_DETACHED; - } - - // db lookup - if ($this->getEntityPersister($class->name)->exists($entity)) { - return self::STATE_DETACHED; - } - - return self::STATE_NEW; - - default: - return self::STATE_DETACHED; - } - } - - /** - * INTERNAL: - * Removes an entity from the identity map. This effectively detaches the - * entity from the persistence management of Doctrine. - * - * @ignore - * - * @param object $entity - * - * @return boolean - * - * @throws ORMInvalidArgumentException - */ - public function removeFromIdentityMap($entity) - { - $oid = spl_object_hash($entity); - $classMetadata = $this->em->getClassMetadata(get_class($entity)); - $idHash = implode(' ', $this->entityIdentifiers[$oid]); - - if ($idHash === '') { - throw ORMInvalidArgumentException::entityHasNoIdentity($entity, "remove from identity map"); - } - - $className = $classMetadata->rootEntityName; - - if (isset($this->identityMap[$className][$idHash])) { - unset($this->identityMap[$className][$idHash]); - unset($this->readOnlyObjects[$oid]); - - //$this->entityStates[$oid] = self::STATE_DETACHED; - - return true; - } - - return false; - } - - /** - * INTERNAL: - * Gets an entity in the identity map by its identifier hash. - * - * @ignore - * - * @param string $idHash - * @param string $rootClassName - * - * @return object - */ - public function getByIdHash($idHash, $rootClassName) - { - return $this->identityMap[$rootClassName][$idHash]; - } - - /** - * INTERNAL: - * Tries to get an entity by its identifier hash. If no entity is found for - * the given hash, FALSE is returned. - * - * @ignore - * - * @param mixed $idHash (must be possible to cast it to string) - * @param string $rootClassName - * - * @return object|bool The found entity or FALSE. - */ - public function tryGetByIdHash($idHash, $rootClassName) - { - $stringIdHash = (string) $idHash; - - return isset($this->identityMap[$rootClassName][$stringIdHash]) - ? $this->identityMap[$rootClassName][$stringIdHash] - : false; - } - - /** - * Checks whether an entity is registered in the identity map of this UnitOfWork. - * - * @param object $entity - * - * @return boolean - */ - public function isInIdentityMap($entity) - { - $oid = spl_object_hash($entity); - - if (empty($this->entityIdentifiers[$oid])) { - return false; - } - - $classMetadata = $this->em->getClassMetadata(get_class($entity)); - $idHash = implode(' ', $this->entityIdentifiers[$oid]); - - return isset($this->identityMap[$classMetadata->rootEntityName][$idHash]); - } - - /** - * INTERNAL: - * Checks whether an identifier hash exists in the identity map. - * - * @ignore - * - * @param string $idHash - * @param string $rootClassName - * - * @return boolean - */ - public function containsIdHash($idHash, $rootClassName) - { - return isset($this->identityMap[$rootClassName][$idHash]); - } - - /** - * Persists an entity as part of the current unit of work. - * - * @param object $entity The entity to persist. - * - * @return void - */ - public function persist($entity) - { - $visited = []; - - $this->doPersist($entity, $visited); - } - - /** - * Persists an entity as part of the current unit of work. - * - * This method is internally called during persist() cascades as it tracks - * the already visited entities to prevent infinite recursions. - * - * @param object $entity The entity to persist. - * @param array $visited The already visited entities. - * - * @return void - * - * @throws ORMInvalidArgumentException - * @throws UnexpectedValueException - */ - private function doPersist($entity, array &$visited) - { - $oid = spl_object_hash($entity); - - if (isset($visited[$oid])) { - return; // Prevent infinite recursion - } - - $visited[$oid] = $entity; // Mark visited - - $class = $this->em->getClassMetadata(get_class($entity)); - - // We assume NEW, so DETACHED entities result in an exception on flush (constraint violation). - // If we would detect DETACHED here we would throw an exception anyway with the same - // consequences (not recoverable/programming error), so just assuming NEW here - // lets us avoid some database lookups for entities with natural identifiers. - $entityState = $this->getEntityState($entity, self::STATE_NEW); - - switch ($entityState) { - case self::STATE_MANAGED: - // Nothing to do, except if policy is "deferred explicit" - if ($class->isChangeTrackingDeferredExplicit()) { - $this->scheduleForDirtyCheck($entity); - } - break; - - case self::STATE_NEW: - $this->persistNew($class, $entity); - break; - - case self::STATE_REMOVED: - // Entity becomes managed again - unset($this->entityDeletions[$oid]); - $this->addToIdentityMap($entity); - - $this->entityStates[$oid] = self::STATE_MANAGED; - break; - - case self::STATE_DETACHED: - // Can actually not happen right now since we assume STATE_NEW. - throw ORMInvalidArgumentException::detachedEntityCannot($entity, "persisted"); - - default: - throw new UnexpectedValueException("Unexpected entity state: $entityState." . self::objToStr($entity)); - } - - $this->cascadePersist($entity, $visited); - } - - /** - * Deletes an entity as part of the current unit of work. - * - * @param object $entity The entity to remove. - * - * @return void - */ - public function remove($entity) - { - $visited = []; - - $this->doRemove($entity, $visited); - } - - /** - * Deletes an entity as part of the current unit of work. - * - * This method is internally called during delete() cascades as it tracks - * the already visited entities to prevent infinite recursions. - * - * @param object $entity The entity to delete. - * @param array $visited The map of the already visited entities. - * - * @return void - * - * @throws ORMInvalidArgumentException If the instance is a detached entity. - * @throws UnexpectedValueException - */ - private function doRemove($entity, array &$visited) - { - $oid = spl_object_hash($entity); - - if (isset($visited[$oid])) { - return; // Prevent infinite recursion - } - - $visited[$oid] = $entity; // mark visited - - // Cascade first, because scheduleForDelete() removes the entity from the identity map, which - // can cause problems when a lazy proxy has to be initialized for the cascade operation. - $this->cascadeRemove($entity, $visited); - - $class = $this->em->getClassMetadata(get_class($entity)); - $entityState = $this->getEntityState($entity); - - switch ($entityState) { - case self::STATE_NEW: - case self::STATE_REMOVED: - // nothing to do - break; - - case self::STATE_MANAGED: - $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preRemove); - - if ($invoke !== ListenersInvoker::INVOKE_NONE) { - $this->listenersInvoker->invoke($class, Events::preRemove, $entity, new LifecycleEventArgs($entity, $this->em), $invoke); - } - - $this->scheduleForDelete($entity); - break; - - case self::STATE_DETACHED: - throw ORMInvalidArgumentException::detachedEntityCannot($entity, "removed"); - default: - throw new UnexpectedValueException("Unexpected entity state: $entityState." . self::objToStr($entity)); - } - - } - - /** - * Merges the state of the given detached entity into this UnitOfWork. - * - * @param object $entity - * - * @return object The managed copy of the entity. - * - * @throws OptimisticLockException If the entity uses optimistic locking through a version - * attribute and the version check against the managed copy fails. - * - * @deprecated 2.7 This method is being removed from the ORM and won't have any replacement - */ - public function merge($entity) - { - $visited = []; - - return $this->doMerge($entity, $visited); - } - - /** - * Executes a merge operation on an entity. - * - * @param object $entity - * @param array $visited - * @param object|null $prevManagedCopy - * @param array|null $assoc - * - * @return object The managed copy of the entity. - * - * @throws OptimisticLockException If the entity uses optimistic locking through a version - * attribute and the version check against the managed copy fails. - * @throws ORMInvalidArgumentException If the entity instance is NEW. - * @throws EntityNotFoundException if an assigned identifier is used in the entity, but none is provided - */ - private function doMerge($entity, array &$visited, $prevManagedCopy = null, array $assoc = []) - { - $oid = spl_object_hash($entity); - - if (isset($visited[$oid])) { - $managedCopy = $visited[$oid]; - - if ($prevManagedCopy !== null) { - $this->updateAssociationWithMergedEntity($entity, $assoc, $prevManagedCopy, $managedCopy); - } - - return $managedCopy; - } - - $class = $this->em->getClassMetadata(get_class($entity)); - - // First we assume DETACHED, although it can still be NEW but we can avoid - // an extra db-roundtrip this way. If it is not MANAGED but has an identity, - // we need to fetch it from the db anyway in order to merge. - // MANAGED entities are ignored by the merge operation. - $managedCopy = $entity; - - if ($this->getEntityState($entity, self::STATE_DETACHED) !== self::STATE_MANAGED) { - // Try to look the entity up in the identity map. - $id = $class->getIdentifierValues($entity); - - // If there is no ID, it is actually NEW. - if ( ! $id) { - $managedCopy = $this->newInstance($class); - - $this->mergeEntityStateIntoManagedCopy($entity, $managedCopy); - $this->persistNew($class, $managedCopy); - } else { - $flatId = ($class->containsForeignIdentifier) - ? $this->identifierFlattener->flattenIdentifier($class, $id) - : $id; - - $managedCopy = $this->tryGetById($flatId, $class->rootEntityName); - - if ($managedCopy) { - // We have the entity in-memory already, just make sure its not removed. - if ($this->getEntityState($managedCopy) == self::STATE_REMOVED) { - throw ORMInvalidArgumentException::entityIsRemoved($managedCopy, "merge"); - } - } else { - // We need to fetch the managed copy in order to merge. - $managedCopy = $this->em->find($class->name, $flatId); - } - - if ($managedCopy === null) { - // If the identifier is ASSIGNED, it is NEW, otherwise an error - // since the managed entity was not found. - if ( ! $class->isIdentifierNatural()) { - throw EntityNotFoundException::fromClassNameAndIdentifier( - $class->getName(), - $this->identifierFlattener->flattenIdentifier($class, $id) - ); - } - - $managedCopy = $this->newInstance($class); - $class->setIdentifierValues($managedCopy, $id); - - $this->mergeEntityStateIntoManagedCopy($entity, $managedCopy); - $this->persistNew($class, $managedCopy); - } else { - $this->ensureVersionMatch($class, $entity, $managedCopy); - $this->mergeEntityStateIntoManagedCopy($entity, $managedCopy); - } - } - - $visited[$oid] = $managedCopy; // mark visited - - if ($class->isChangeTrackingDeferredExplicit()) { - $this->scheduleForDirtyCheck($entity); - } - } - - if ($prevManagedCopy !== null) { - $this->updateAssociationWithMergedEntity($entity, $assoc, $prevManagedCopy, $managedCopy); - } - - // Mark the managed copy visited as well - $visited[spl_object_hash($managedCopy)] = $managedCopy; - - $this->cascadeMerge($entity, $managedCopy, $visited); - - return $managedCopy; - } - - /** - * @param ClassMetadata $class - * @param object $entity - * @param object $managedCopy - * - * @return void - * - * @throws OptimisticLockException - */ - private function ensureVersionMatch(ClassMetadata $class, $entity, $managedCopy) - { - if (! ($class->isVersioned && $this->isLoaded($managedCopy) && $this->isLoaded($entity))) { - return; - } - - $reflField = $class->reflFields[$class->versionField]; - $managedCopyVersion = $reflField->getValue($managedCopy); - $entityVersion = $reflField->getValue($entity); - - // Throw exception if versions don't match. - if ($managedCopyVersion == $entityVersion) { - return; - } - - throw OptimisticLockException::lockFailedVersionMismatch($entity, $entityVersion, $managedCopyVersion); - } - - /** - * Tests if an entity is loaded - must either be a loaded proxy or not a proxy - * - * @param object $entity - * - * @return bool - */ - private function isLoaded($entity) - { - return !($entity instanceof Proxy) || $entity->__isInitialized(); - } - - /** - * Sets/adds associated managed copies into the previous entity's association field - * - * @param object $entity - * @param array $association - * @param object $previousManagedCopy - * @param object $managedCopy - * - * @return void - */ - private function updateAssociationWithMergedEntity($entity, array $association, $previousManagedCopy, $managedCopy) - { - $assocField = $association['fieldName']; - $prevClass = $this->em->getClassMetadata(get_class($previousManagedCopy)); - - if ($association['type'] & ClassMetadata::TO_ONE) { - $prevClass->reflFields[$assocField]->setValue($previousManagedCopy, $managedCopy); - - return; - } - - $value = $prevClass->reflFields[$assocField]->getValue($previousManagedCopy); - $value[] = $managedCopy; - - if ($association['type'] == ClassMetadata::ONE_TO_MANY) { - $class = $this->em->getClassMetadata(get_class($entity)); - - $class->reflFields[$association['mappedBy']]->setValue($managedCopy, $previousManagedCopy); - } - } - - /** - * Detaches an entity from the persistence management. It's persistence will - * no longer be managed by Doctrine. - * - * @param object $entity The entity to detach. - * - * @return void - * - * @deprecated 2.7 This method is being removed from the ORM and won't have any replacement - */ - public function detach($entity) - { - $visited = []; - - $this->doDetach($entity, $visited); - } - - /** - * Executes a detach operation on the given entity. - * - * @param object $entity - * @param array $visited - * @param boolean $noCascade if true, don't cascade detach operation. - * - * @return void - */ - private function doDetach($entity, array &$visited, $noCascade = false) - { - $oid = spl_object_hash($entity); - - if (isset($visited[$oid])) { - return; // Prevent infinite recursion - } - - $visited[$oid] = $entity; // mark visited - - switch ($this->getEntityState($entity, self::STATE_DETACHED)) { - case self::STATE_MANAGED: - if ($this->isInIdentityMap($entity)) { - $this->removeFromIdentityMap($entity); - } - - unset( - $this->entityInsertions[$oid], - $this->entityUpdates[$oid], - $this->entityDeletions[$oid], - $this->entityIdentifiers[$oid], - $this->entityStates[$oid], - $this->originalEntityData[$oid] - ); - break; - case self::STATE_NEW: - case self::STATE_DETACHED: - return; - } - - if ( ! $noCascade) { - $this->cascadeDetach($entity, $visited); - } - } - - /** - * Refreshes the state of the given entity from the database, overwriting - * any local, unpersisted changes. - * - * @param object $entity The entity to refresh. - * - * @return void - * - * @throws InvalidArgumentException If the entity is not MANAGED. - */ - public function refresh($entity) - { - $visited = []; - - $this->doRefresh($entity, $visited); - } - - /** - * Executes a refresh operation on an entity. - * - * @param object $entity The entity to refresh. - * @param array $visited The already visited entities during cascades. - * - * @return void - * - * @throws ORMInvalidArgumentException If the entity is not MANAGED. - */ - private function doRefresh($entity, array &$visited) - { - $oid = spl_object_hash($entity); - - if (isset($visited[$oid])) { - return; // Prevent infinite recursion - } - - $visited[$oid] = $entity; // mark visited - - $class = $this->em->getClassMetadata(get_class($entity)); - - if ($this->getEntityState($entity) !== self::STATE_MANAGED) { - throw ORMInvalidArgumentException::entityNotManaged($entity); - } - - $this->getEntityPersister($class->name)->refresh( - array_combine($class->getIdentifierFieldNames(), $this->entityIdentifiers[$oid]), - $entity - ); - - $this->cascadeRefresh($entity, $visited); - } - - /** - * Cascades a refresh operation to associated entities. - * - * @param object $entity - * @param array $visited - * - * @return void - */ - private function cascadeRefresh($entity, array &$visited) - { - $class = $this->em->getClassMetadata(get_class($entity)); - - $associationMappings = array_filter( - $class->associationMappings, - function ($assoc) { return $assoc['isCascadeRefresh']; } - ); - - foreach ($associationMappings as $assoc) { - $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity); - - switch (true) { - case ($relatedEntities instanceof PersistentCollection): - // Unwrap so that foreach() does not initialize - $relatedEntities = $relatedEntities->unwrap(); - // break; is commented intentionally! - - case ($relatedEntities instanceof Collection): - case (is_array($relatedEntities)): - foreach ($relatedEntities as $relatedEntity) { - $this->doRefresh($relatedEntity, $visited); - } - break; - - case ($relatedEntities !== null): - $this->doRefresh($relatedEntities, $visited); - break; - - default: - // Do nothing - } - } - } - - /** - * Cascades a detach operation to associated entities. - * - * @param object $entity - * @param array $visited - * - * @return void - */ - private function cascadeDetach($entity, array &$visited) - { - $class = $this->em->getClassMetadata(get_class($entity)); - - $associationMappings = array_filter( - $class->associationMappings, - function ($assoc) { return $assoc['isCascadeDetach']; } - ); - - foreach ($associationMappings as $assoc) { - $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity); - - switch (true) { - case ($relatedEntities instanceof PersistentCollection): - // Unwrap so that foreach() does not initialize - $relatedEntities = $relatedEntities->unwrap(); - // break; is commented intentionally! - - case ($relatedEntities instanceof Collection): - case (is_array($relatedEntities)): - foreach ($relatedEntities as $relatedEntity) { - $this->doDetach($relatedEntity, $visited); - } - break; - - case ($relatedEntities !== null): - $this->doDetach($relatedEntities, $visited); - break; - - default: - // Do nothing - } - } - } - - /** - * Cascades a merge operation to associated entities. - * - * @param object $entity - * @param object $managedCopy - * @param array $visited - * - * @return void - */ - private function cascadeMerge($entity, $managedCopy, array &$visited) - { - $class = $this->em->getClassMetadata(get_class($entity)); - - $associationMappings = array_filter( - $class->associationMappings, - function ($assoc) { return $assoc['isCascadeMerge']; } - ); - - foreach ($associationMappings as $assoc) { - $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity); - - if ($relatedEntities instanceof Collection) { - if ($relatedEntities === $class->reflFields[$assoc['fieldName']]->getValue($managedCopy)) { - continue; - } - - if ($relatedEntities instanceof PersistentCollection) { - // Unwrap so that foreach() does not initialize - $relatedEntities = $relatedEntities->unwrap(); - } - - foreach ($relatedEntities as $relatedEntity) { - $this->doMerge($relatedEntity, $visited, $managedCopy, $assoc); - } - } else if ($relatedEntities !== null) { - $this->doMerge($relatedEntities, $visited, $managedCopy, $assoc); - } - } - } - - /** - * Cascades the save operation to associated entities. - * - * @param object $entity - * @param array $visited - * - * @return void - */ - private function cascadePersist($entity, array &$visited) - { - $class = $this->em->getClassMetadata(get_class($entity)); - - $associationMappings = array_filter( - $class->associationMappings, - function ($assoc) { return $assoc['isCascadePersist']; } - ); - - foreach ($associationMappings as $assoc) { - $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity); - - switch (true) { - case ($relatedEntities instanceof PersistentCollection): - // Unwrap so that foreach() does not initialize - $relatedEntities = $relatedEntities->unwrap(); - // break; is commented intentionally! - - case ($relatedEntities instanceof Collection): - case (is_array($relatedEntities)): - if (($assoc['type'] & ClassMetadata::TO_MANY) <= 0) { - throw ORMInvalidArgumentException::invalidAssociation( - $this->em->getClassMetadata($assoc['targetEntity']), - $assoc, - $relatedEntities - ); - } - - foreach ($relatedEntities as $relatedEntity) { - $this->doPersist($relatedEntity, $visited); - } - - break; - - case ($relatedEntities !== null): - if (! $relatedEntities instanceof $assoc['targetEntity']) { - throw ORMInvalidArgumentException::invalidAssociation( - $this->em->getClassMetadata($assoc['targetEntity']), - $assoc, - $relatedEntities - ); - } - - $this->doPersist($relatedEntities, $visited); - break; - - default: - // Do nothing - } - } - } - - /** - * Cascades the delete operation to associated entities. - * - * @param object $entity - * @param array $visited - * - * @return void - */ - private function cascadeRemove($entity, array &$visited) - { - $class = $this->em->getClassMetadata(get_class($entity)); - - $associationMappings = array_filter( - $class->associationMappings, - function ($assoc) { return $assoc['isCascadeRemove']; } - ); - - $entitiesToCascade = []; - - foreach ($associationMappings as $assoc) { - if ($entity instanceof Proxy && !$entity->__isInitialized__) { - $entity->__load(); - } - - $relatedEntities = $class->reflFields[$assoc['fieldName']]->getValue($entity); - - switch (true) { - case ($relatedEntities instanceof Collection): - case (is_array($relatedEntities)): - // If its a PersistentCollection initialization is intended! No unwrap! - foreach ($relatedEntities as $relatedEntity) { - $entitiesToCascade[] = $relatedEntity; - } - break; - - case ($relatedEntities !== null): - $entitiesToCascade[] = $relatedEntities; - break; - - default: - // Do nothing - } - } - - foreach ($entitiesToCascade as $relatedEntity) { - $this->doRemove($relatedEntity, $visited); - } - } - - /** - * Acquire a lock on the given entity. - * - * @param object $entity - * @param int $lockMode - * @param int $lockVersion - * - * @return void - * - * @throws ORMInvalidArgumentException - * @throws TransactionRequiredException - * @throws OptimisticLockException - */ - public function lock($entity, $lockMode, $lockVersion = null) - { - if ($entity === null) { - throw new \InvalidArgumentException("No entity passed to UnitOfWork#lock()."); - } - - if ($this->getEntityState($entity, self::STATE_DETACHED) != self::STATE_MANAGED) { - throw ORMInvalidArgumentException::entityNotManaged($entity); - } - - $class = $this->em->getClassMetadata(get_class($entity)); - - switch (true) { - case LockMode::OPTIMISTIC === $lockMode: - if ( ! $class->isVersioned) { - throw OptimisticLockException::notVersioned($class->name); - } - - if ($lockVersion === null) { - return; - } - - if ($entity instanceof Proxy && !$entity->__isInitialized__) { - $entity->__load(); - } - - $entityVersion = $class->reflFields[$class->versionField]->getValue($entity); - - if ($entityVersion != $lockVersion) { - throw OptimisticLockException::lockFailedVersionMismatch($entity, $lockVersion, $entityVersion); - } - - break; - - case LockMode::NONE === $lockMode: - case LockMode::PESSIMISTIC_READ === $lockMode: - case LockMode::PESSIMISTIC_WRITE === $lockMode: - if (!$this->em->getConnection()->isTransactionActive()) { - throw TransactionRequiredException::transactionRequired(); - } - - $oid = spl_object_hash($entity); - - $this->getEntityPersister($class->name)->lock( - array_combine($class->getIdentifierFieldNames(), $this->entityIdentifiers[$oid]), - $lockMode - ); - break; - - default: - // Do nothing - } - } - - /** - * Gets the CommitOrderCalculator used by the UnitOfWork to order commits. - * - * @return \Doctrine\ORM\Internal\CommitOrderCalculator - */ - public function getCommitOrderCalculator() - { - return new Internal\CommitOrderCalculator(); - } - - /** - * Clears the UnitOfWork. - * - * @param string|null $entityName if given, only entities of this type will get detached. - * - * @return void - * - * @throws ORMInvalidArgumentException if an invalid entity name is given - */ - public function clear($entityName = null) - { - if ($entityName === null) { - $this->identityMap = - $this->entityIdentifiers = - $this->originalEntityData = - $this->entityChangeSets = - $this->entityStates = - $this->scheduledForSynchronization = - $this->entityInsertions = - $this->entityUpdates = - $this->entityDeletions = - $this->nonCascadedNewDetectedEntities = - $this->collectionDeletions = - $this->collectionUpdates = - $this->extraUpdates = - $this->readOnlyObjects = - $this->visitedCollections = - $this->eagerLoadingEntities = - $this->orphanRemovals = []; - } else { - $this->clearIdentityMapForEntityName($entityName); - $this->clearEntityInsertionsForEntityName($entityName); - } - - if ($this->evm->hasListeners(Events::onClear)) { - $this->evm->dispatchEvent(Events::onClear, new Event\OnClearEventArgs($this->em, $entityName)); - } - } - - /** - * INTERNAL: - * Schedules an orphaned entity for removal. The remove() operation will be - * invoked on that entity at the beginning of the next commit of this - * UnitOfWork. - * - * @ignore - * - * @param object $entity - * - * @return void - */ - public function scheduleOrphanRemoval($entity) - { - $this->orphanRemovals[spl_object_hash($entity)] = $entity; - } - - /** - * INTERNAL: - * Cancels a previously scheduled orphan removal. - * - * @ignore - * - * @param object $entity - * - * @return void - */ - public function cancelOrphanRemoval($entity) - { - unset($this->orphanRemovals[spl_object_hash($entity)]); - } - - /** - * INTERNAL: - * Schedules a complete collection for removal when this UnitOfWork commits. - * - * @param PersistentCollection $coll - * - * @return void - */ - public function scheduleCollectionDeletion(PersistentCollection $coll) - { - $coid = spl_object_hash($coll); - - // TODO: if $coll is already scheduled for recreation ... what to do? - // Just remove $coll from the scheduled recreations? - unset($this->collectionUpdates[$coid]); - - $this->collectionDeletions[$coid] = $coll; - } - - /** - * @param PersistentCollection $coll - * - * @return bool - */ - public function isCollectionScheduledForDeletion(PersistentCollection $coll) - { - return isset($this->collectionDeletions[spl_object_hash($coll)]); - } - - /** - * @param ClassMetadata $class - * - * @return \Doctrine\Common\Persistence\ObjectManagerAware|object - */ - private function newInstance($class) - { - $entity = $class->newInstance(); - - if ($entity instanceof \Doctrine\Common\Persistence\ObjectManagerAware) { - $entity->injectObjectManager($this->em, $class); - } - - return $entity; - } - - /** - * INTERNAL: - * Creates an entity. Used for reconstitution of persistent entities. - * - * Internal note: Highly performance-sensitive method. - * - * @ignore - * - * @param string $className The name of the entity class. - * @param array $data The data for the entity. - * @param array $hints Any hints to account for during reconstitution/lookup of the entity. - * - * @return object The managed entity instance. - * - * @todo Rename: getOrCreateEntity - */ - public function createEntity($className, array $data, &$hints = []) - { - $class = $this->em->getClassMetadata($className); - - $id = $this->identifierFlattener->flattenIdentifier($class, $data); - $idHash = implode(' ', $id); - - if (isset($this->identityMap[$class->rootEntityName][$idHash])) { - $entity = $this->identityMap[$class->rootEntityName][$idHash]; - $oid = spl_object_hash($entity); - - if ( - isset($hints[Query::HINT_REFRESH]) - && isset($hints[Query::HINT_REFRESH_ENTITY]) - && ($unmanagedProxy = $hints[Query::HINT_REFRESH_ENTITY]) !== $entity - && $unmanagedProxy instanceof Proxy - && $this->isIdentifierEquals($unmanagedProxy, $entity) - ) { - // DDC-1238 - we have a managed instance, but it isn't the provided one. - // Therefore we clear its identifier. Also, we must re-fetch metadata since the - // refreshed object may be anything - - foreach ($class->identifier as $fieldName) { - $class->reflFields[$fieldName]->setValue($unmanagedProxy, null); - } - - return $unmanagedProxy; - } - - if ($entity instanceof Proxy && ! $entity->__isInitialized()) { - $entity->__setInitialized(true); - - if ($entity instanceof NotifyPropertyChanged) { - $entity->addPropertyChangedListener($this); - } - } else { - if ( ! isset($hints[Query::HINT_REFRESH]) - || (isset($hints[Query::HINT_REFRESH_ENTITY]) && $hints[Query::HINT_REFRESH_ENTITY] !== $entity)) { - return $entity; - } - } - - // inject ObjectManager upon refresh. - if ($entity instanceof ObjectManagerAware) { - $entity->injectObjectManager($this->em, $class); - } - - $this->originalEntityData[$oid] = $data; - } else { - $entity = $this->newInstance($class); - $oid = spl_object_hash($entity); - - $this->entityIdentifiers[$oid] = $id; - $this->entityStates[$oid] = self::STATE_MANAGED; - $this->originalEntityData[$oid] = $data; - - $this->identityMap[$class->rootEntityName][$idHash] = $entity; - - if ($entity instanceof NotifyPropertyChanged) { - $entity->addPropertyChangedListener($this); - } - } - - foreach ($data as $field => $value) { - if (isset($class->fieldMappings[$field])) { - $class->reflFields[$field]->setValue($entity, $value); - } - } - - // Loading the entity right here, if its in the eager loading map get rid of it there. - unset($this->eagerLoadingEntities[$class->rootEntityName][$idHash]); - - if (isset($this->eagerLoadingEntities[$class->rootEntityName]) && ! $this->eagerLoadingEntities[$class->rootEntityName]) { - unset($this->eagerLoadingEntities[$class->rootEntityName]); - } - - // Properly initialize any unfetched associations, if partial objects are not allowed. - if (isset($hints[Query::HINT_FORCE_PARTIAL_LOAD])) { - return $entity; - } - - foreach ($class->associationMappings as $field => $assoc) { - // Check if the association is not among the fetch-joined associations already. - if (isset($hints['fetchAlias']) && isset($hints['fetched'][$hints['fetchAlias']][$field])) { - continue; - } - - $targetClass = $this->em->getClassMetadata($assoc['targetEntity']); - - switch (true) { - case ($assoc['type'] & ClassMetadata::TO_ONE): - if ( ! $assoc['isOwningSide']) { - - // use the given entity association - if (isset($data[$field]) && is_object($data[$field]) && isset($this->entityStates[spl_object_hash($data[$field])])) { - - $this->originalEntityData[$oid][$field] = $data[$field]; - - $class->reflFields[$field]->setValue($entity, $data[$field]); - $targetClass->reflFields[$assoc['mappedBy']]->setValue($data[$field], $entity); - - continue 2; - } - - // Inverse side of x-to-one can never be lazy - $class->reflFields[$field]->setValue($entity, $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity)); - - continue 2; - } - - // use the entity association - if (isset($data[$field]) && is_object($data[$field]) && isset($this->entityStates[spl_object_hash($data[$field])])) { - $class->reflFields[$field]->setValue($entity, $data[$field]); - $this->originalEntityData[$oid][$field] = $data[$field]; - - break; - } - - $associatedId = []; - - // TODO: Is this even computed right in all cases of composite keys? - foreach ($assoc['targetToSourceKeyColumns'] as $targetColumn => $srcColumn) { - $joinColumnValue = $data[$srcColumn] ?? null; - - if ($joinColumnValue !== null) { - if ($targetClass->containsForeignIdentifier) { - $associatedId[$targetClass->getFieldForColumn($targetColumn)] = $joinColumnValue; - } else { - $associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue; - } - } elseif ($targetClass->containsForeignIdentifier - && in_array($targetClass->getFieldForColumn($targetColumn), $targetClass->identifier, true) - ) { - // the missing key is part of target's entity primary key - $associatedId = []; - break; - } - } - - if ( ! $associatedId) { - // Foreign key is NULL - $class->reflFields[$field]->setValue($entity, null); - $this->originalEntityData[$oid][$field] = null; - - break; - } - - if ( ! isset($hints['fetchMode'][$class->name][$field])) { - $hints['fetchMode'][$class->name][$field] = $assoc['fetch']; - } - - // Foreign key is set - // Check identity map first - // FIXME: Can break easily with composite keys if join column values are in - // wrong order. The correct order is the one in ClassMetadata#identifier. - $relatedIdHash = implode(' ', $associatedId); - - switch (true) { - case (isset($this->identityMap[$targetClass->rootEntityName][$relatedIdHash])): - $newValue = $this->identityMap[$targetClass->rootEntityName][$relatedIdHash]; - - // If this is an uninitialized proxy, we are deferring eager loads, - // this association is marked as eager fetch, and its an uninitialized proxy (wtf!) - // then we can append this entity for eager loading! - if ($hints['fetchMode'][$class->name][$field] == ClassMetadata::FETCH_EAGER && - isset($hints[self::HINT_DEFEREAGERLOAD]) && - !$targetClass->isIdentifierComposite && - $newValue instanceof Proxy && - $newValue->__isInitialized__ === false) { - - $this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId); - } - - break; - - case ($targetClass->subClasses): - // If it might be a subtype, it can not be lazy. There isn't even - // a way to solve this with deferred eager loading, which means putting - // an entity with subclasses at a *-to-one location is really bad! (performance-wise) - $newValue = $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity, $associatedId); - break; - - default: - switch (true) { - // We are negating the condition here. Other cases will assume it is valid! - case ($hints['fetchMode'][$class->name][$field] !== ClassMetadata::FETCH_EAGER): - $newValue = $this->em->getProxyFactory()->getProxy($assoc['targetEntity'], $associatedId); - break; - - // Deferred eager load only works for single identifier classes - case (isset($hints[self::HINT_DEFEREAGERLOAD]) && ! $targetClass->isIdentifierComposite): - // TODO: Is there a faster approach? - $this->eagerLoadingEntities[$targetClass->rootEntityName][$relatedIdHash] = current($associatedId); - - $newValue = $this->em->getProxyFactory()->getProxy($assoc['targetEntity'], $associatedId); - break; - - default: - // TODO: This is very imperformant, ignore it? - $newValue = $this->em->find($assoc['targetEntity'], $associatedId); - break; - } - - // PERF: Inlined & optimized code from UnitOfWork#registerManaged() - $newValueOid = spl_object_hash($newValue); - $this->entityIdentifiers[$newValueOid] = $associatedId; - $this->identityMap[$targetClass->rootEntityName][$relatedIdHash] = $newValue; - - if ( - $newValue instanceof NotifyPropertyChanged && - ( ! $newValue instanceof Proxy || $newValue->__isInitialized()) - ) { - $newValue->addPropertyChangedListener($this); - } - $this->entityStates[$newValueOid] = self::STATE_MANAGED; - // make sure that when an proxy is then finally loaded, $this->originalEntityData is set also! - break; - } - - $this->originalEntityData[$oid][$field] = $newValue; - $class->reflFields[$field]->setValue($entity, $newValue); - - if ($assoc['inversedBy'] && $assoc['type'] & ClassMetadata::ONE_TO_ONE) { - $inverseAssoc = $targetClass->associationMappings[$assoc['inversedBy']]; - $targetClass->reflFields[$inverseAssoc['fieldName']]->setValue($newValue, $entity); - } - - break; - - default: - // Ignore if its a cached collection - if (isset($hints[Query::HINT_CACHE_ENABLED]) && $class->getFieldValue($entity, $field) instanceof PersistentCollection) { - break; - } - - // use the given collection - if (isset($data[$field]) && $data[$field] instanceof PersistentCollection) { - - $data[$field]->setOwner($entity, $assoc); - - $class->reflFields[$field]->setValue($entity, $data[$field]); - $this->originalEntityData[$oid][$field] = $data[$field]; - - break; - } - - // Inject collection - $pColl = new PersistentCollection($this->em, $targetClass, new ArrayCollection); - $pColl->setOwner($entity, $assoc); - $pColl->setInitialized(false); - - $reflField = $class->reflFields[$field]; - $reflField->setValue($entity, $pColl); - - if ($assoc['fetch'] == ClassMetadata::FETCH_EAGER) { - $this->loadCollection($pColl); - $pColl->takeSnapshot(); - } - - $this->originalEntityData[$oid][$field] = $pColl; - break; - } - } - - // defer invoking of postLoad event to hydration complete step - $this->hydrationCompleteHandler->deferPostLoadInvoking($class, $entity); - - return $entity; - } - - /** - * @return void - */ - public function triggerEagerLoads() - { - if ( ! $this->eagerLoadingEntities) { - return; - } - - // avoid infinite recursion - $eagerLoadingEntities = $this->eagerLoadingEntities; - $this->eagerLoadingEntities = []; - - foreach ($eagerLoadingEntities as $entityName => $ids) { - if ( ! $ids) { - continue; - } - - $class = $this->em->getClassMetadata($entityName); - - $this->getEntityPersister($entityName)->loadAll( - array_combine($class->identifier, [array_values($ids)]) - ); - } - } - - /** - * Initializes (loads) an uninitialized persistent collection of an entity. - * - * @param \Doctrine\ORM\PersistentCollection $collection The collection to initialize. - * - * @return void - * - * @todo Maybe later move to EntityManager#initialize($proxyOrCollection). See DDC-733. - */ - public function loadCollection(PersistentCollection $collection) - { - $assoc = $collection->getMapping(); - $persister = $this->getEntityPersister($assoc['targetEntity']); - - switch ($assoc['type']) { - case ClassMetadata::ONE_TO_MANY: - $persister->loadOneToManyCollection($assoc, $collection->getOwner(), $collection); - break; - - case ClassMetadata::MANY_TO_MANY: - $persister->loadManyToManyCollection($assoc, $collection->getOwner(), $collection); - break; - } - - $collection->setInitialized(true); - } - - /** - * Gets the identity map of the UnitOfWork. - * - * @return array - */ - public function getIdentityMap() - { - return $this->identityMap; - } - - /** - * Gets the original data of an entity. The original data is the data that was - * present at the time the entity was reconstituted from the database. - * - * @param object $entity - * - * @return array - */ - public function getOriginalEntityData($entity) - { - $oid = spl_object_hash($entity); - - return isset($this->originalEntityData[$oid]) - ? $this->originalEntityData[$oid] - : []; - } - - /** - * @ignore - * - * @param object $entity - * @param array $data - * - * @return void - */ - public function setOriginalEntityData($entity, array $data) - { - $this->originalEntityData[spl_object_hash($entity)] = $data; - } - - /** - * INTERNAL: - * Sets a property value of the original data array of an entity. - * - * @ignore - * - * @param string $oid - * @param string $property - * @param mixed $value - * - * @return void - */ - public function setOriginalEntityProperty($oid, $property, $value) - { - $this->originalEntityData[$oid][$property] = $value; - } - - /** - * Gets the identifier of an entity. - * The returned value is always an array of identifier values. If the entity - * has a composite identifier then the identifier values are in the same - * order as the identifier field names as returned by ClassMetadata#getIdentifierFieldNames(). - * - * @param object $entity - * - * @return array The identifier values. - */ - public function getEntityIdentifier($entity) - { - return $this->entityIdentifiers[spl_object_hash($entity)]; - } - - /** - * Processes an entity instance to extract their identifier values. - * - * @param object $entity The entity instance. - * - * @return mixed A scalar value. - * - * @throws \Doctrine\ORM\ORMInvalidArgumentException - */ - public function getSingleIdentifierValue($entity) - { - $class = $this->em->getClassMetadata(get_class($entity)); - - if ($class->isIdentifierComposite) { - throw ORMInvalidArgumentException::invalidCompositeIdentifier(); - } - - $values = $this->isInIdentityMap($entity) - ? $this->getEntityIdentifier($entity) - : $class->getIdentifierValues($entity); - - return isset($values[$class->identifier[0]]) ? $values[$class->identifier[0]] : null; - } - - /** - * Tries to find an entity with the given identifier in the identity map of - * this UnitOfWork. - * - * @param mixed $id The entity identifier to look for. - * @param string $rootClassName The name of the root class of the mapped entity hierarchy. - * - * @return object|bool Returns the entity with the specified identifier if it exists in - * this UnitOfWork, FALSE otherwise. - */ - public function tryGetById($id, $rootClassName) - { - $idHash = implode(' ', (array) $id); - - return isset($this->identityMap[$rootClassName][$idHash]) - ? $this->identityMap[$rootClassName][$idHash] - : false; - } - - /** - * Schedules an entity for dirty-checking at commit-time. - * - * @param object $entity The entity to schedule for dirty-checking. - * - * @return void - * - * @todo Rename: scheduleForSynchronization - */ - public function scheduleForDirtyCheck($entity) - { - $rootClassName = $this->em->getClassMetadata(get_class($entity))->rootEntityName; - - $this->scheduledForSynchronization[$rootClassName][spl_object_hash($entity)] = $entity; - } - - /** - * Checks whether the UnitOfWork has any pending insertions. - * - * @return boolean TRUE if this UnitOfWork has pending insertions, FALSE otherwise. - */ - public function hasPendingInsertions() - { - return ! empty($this->entityInsertions); - } - - /** - * Calculates the size of the UnitOfWork. The size of the UnitOfWork is the - * number of entities in the identity map. - * - * @return integer - */ - public function size() - { - $countArray = array_map('count', $this->identityMap); - - return array_sum($countArray); - } - - /** - * Gets the EntityPersister for an Entity. - * - * @param string $entityName The name of the Entity. - * - * @return \Doctrine\ORM\Persisters\Entity\EntityPersister - */ - public function getEntityPersister($entityName) - { - if (isset($this->persisters[$entityName])) { - return $this->persisters[$entityName]; - } - - $class = $this->em->getClassMetadata($entityName); - - switch (true) { - case ($class->isInheritanceTypeNone()): - $persister = new BasicEntityPersister($this->em, $class); - break; - - case ($class->isInheritanceTypeSingleTable()): - $persister = new SingleTablePersister($this->em, $class); - break; - - case ($class->isInheritanceTypeJoined()): - $persister = new JoinedSubclassPersister($this->em, $class); - break; - - default: - throw new \RuntimeException('No persister found for entity.'); - } - - if ($this->hasCache && $class->cache !== null) { - $persister = $this->em->getConfiguration() - ->getSecondLevelCacheConfiguration() - ->getCacheFactory() - ->buildCachedEntityPersister($this->em, $persister, $class); - } - - $this->persisters[$entityName] = $persister; - - return $this->persisters[$entityName]; - } - - /** - * Gets a collection persister for a collection-valued association. - * - * @param array $association - * - * @return \Doctrine\ORM\Persisters\Collection\CollectionPersister - */ - public function getCollectionPersister(array $association) - { - $role = isset($association['cache']) - ? $association['sourceEntity'] . '::' . $association['fieldName'] - : $association['type']; - - if (isset($this->collectionPersisters[$role])) { - return $this->collectionPersisters[$role]; - } - - $persister = ClassMetadata::ONE_TO_MANY === $association['type'] - ? new OneToManyPersister($this->em) - : new ManyToManyPersister($this->em); - - if ($this->hasCache && isset($association['cache'])) { - $persister = $this->em->getConfiguration() - ->getSecondLevelCacheConfiguration() - ->getCacheFactory() - ->buildCachedCollectionPersister($this->em, $persister, $association); - } - - $this->collectionPersisters[$role] = $persister; - - return $this->collectionPersisters[$role]; - } - - /** - * INTERNAL: - * Registers an entity as managed. - * - * @param object $entity The entity. - * @param array $id The identifier values. - * @param array $data The original entity data. - * - * @return void - */ - public function registerManaged($entity, array $id, array $data) - { - $oid = spl_object_hash($entity); - - $this->entityIdentifiers[$oid] = $id; - $this->entityStates[$oid] = self::STATE_MANAGED; - $this->originalEntityData[$oid] = $data; - - $this->addToIdentityMap($entity); - - if ($entity instanceof NotifyPropertyChanged && ( ! $entity instanceof Proxy || $entity->__isInitialized())) { - $entity->addPropertyChangedListener($this); - } - } - - /** - * INTERNAL: - * Clears the property changeset of the entity with the given OID. - * - * @param string $oid The entity's OID. - * - * @return void - */ - public function clearEntityChangeSet($oid) - { - unset($this->entityChangeSets[$oid]); - } - - /* PropertyChangedListener implementation */ - - /** - * Notifies this UnitOfWork of a property change in an entity. - * - * @param object $entity The entity that owns the property. - * @param string $propertyName The name of the property that changed. - * @param mixed $oldValue The old value of the property. - * @param mixed $newValue The new value of the property. - * - * @return void - */ - public function propertyChanged($entity, $propertyName, $oldValue, $newValue) - { - $oid = spl_object_hash($entity); - $class = $this->em->getClassMetadata(get_class($entity)); - - $isAssocField = isset($class->associationMappings[$propertyName]); - - if ( ! $isAssocField && ! isset($class->fieldMappings[$propertyName])) { - return; // ignore non-persistent fields - } - - // Update changeset and mark entity for synchronization - $this->entityChangeSets[$oid][$propertyName] = [$oldValue, $newValue]; - - if ( ! isset($this->scheduledForSynchronization[$class->rootEntityName][$oid])) { - $this->scheduleForDirtyCheck($entity); - } - } - - /** - * Gets the currently scheduled entity insertions in this UnitOfWork. - * - * @return array - */ - public function getScheduledEntityInsertions() - { - return $this->entityInsertions; - } - - /** - * Gets the currently scheduled entity updates in this UnitOfWork. - * - * @return array - */ - public function getScheduledEntityUpdates() - { - return $this->entityUpdates; - } - - /** - * Gets the currently scheduled entity deletions in this UnitOfWork. - * - * @return array - */ - public function getScheduledEntityDeletions() - { - return $this->entityDeletions; - } - - /** - * Gets the currently scheduled complete collection deletions - * - * @return array - */ - public function getScheduledCollectionDeletions() - { - return $this->collectionDeletions; - } - - /** - * Gets the currently scheduled collection inserts, updates and deletes. - * - * @return array - */ - public function getScheduledCollectionUpdates() - { - return $this->collectionUpdates; - } - - /** - * Helper method to initialize a lazy loading proxy or persistent collection. - * - * @param object $obj - * - * @return void - */ - public function initializeObject($obj) - { - if ($obj instanceof Proxy) { - $obj->__load(); - - return; - } - - if ($obj instanceof PersistentCollection) { - $obj->initialize(); - } - } - - /** - * Helper method to show an object as string. - * - * @param object $obj - * - * @return string - */ - private static function objToStr($obj) - { - return method_exists($obj, '__toString') ? (string) $obj : get_class($obj).'@'.spl_object_hash($obj); - } - - /** - * Marks an entity as read-only so that it will not be considered for updates during UnitOfWork#commit(). - * - * This operation cannot be undone as some parts of the UnitOfWork now keep gathering information - * on this object that might be necessary to perform a correct update. - * - * @param object $object - * - * @return void - * - * @throws ORMInvalidArgumentException - */ - public function markReadOnly($object) - { - if ( ! is_object($object) || ! $this->isInIdentityMap($object)) { - throw ORMInvalidArgumentException::readOnlyRequiresManagedEntity($object); - } - - $this->readOnlyObjects[spl_object_hash($object)] = true; - } - - /** - * Is this entity read only? - * - * @param object $object - * - * @return bool - * - * @throws ORMInvalidArgumentException - */ - public function isReadOnly($object) - { - if ( ! is_object($object)) { - throw ORMInvalidArgumentException::readOnlyRequiresManagedEntity($object); - } - - return isset($this->readOnlyObjects[spl_object_hash($object)]); - } - - /** - * Perform whatever processing is encapsulated here after completion of the transaction. - */ - private function afterTransactionComplete() - { - $this->performCallbackOnCachedPersister(function (CachedPersister $persister) { - $persister->afterTransactionComplete(); - }); - } - - /** - * Perform whatever processing is encapsulated here after completion of the rolled-back. - */ - private function afterTransactionRolledBack() - { - $this->performCallbackOnCachedPersister(function (CachedPersister $persister) { - $persister->afterTransactionRolledBack(); - }); - } - - /** - * Performs an action after the transaction. - * - * @param callable $callback - */ - private function performCallbackOnCachedPersister(callable $callback) - { - if ( ! $this->hasCache) { - return; - } - - foreach (array_merge($this->persisters, $this->collectionPersisters) as $persister) { - if ($persister instanceof CachedPersister) { - $callback($persister); - } - } - } - - private function dispatchOnFlushEvent() - { - if ($this->evm->hasListeners(Events::onFlush)) { - $this->evm->dispatchEvent(Events::onFlush, new OnFlushEventArgs($this->em)); - } - } - - private function dispatchPostFlushEvent() - { - if ($this->evm->hasListeners(Events::postFlush)) { - $this->evm->dispatchEvent(Events::postFlush, new PostFlushEventArgs($this->em)); - } - } - - /** - * Verifies if two given entities actually are the same based on identifier comparison - * - * @param object $entity1 - * @param object $entity2 - * - * @return bool - */ - private function isIdentifierEquals($entity1, $entity2) - { - if ($entity1 === $entity2) { - return true; - } - - $class = $this->em->getClassMetadata(get_class($entity1)); - - if ($class !== $this->em->getClassMetadata(get_class($entity2))) { - return false; - } - - $oid1 = spl_object_hash($entity1); - $oid2 = spl_object_hash($entity2); - - $id1 = isset($this->entityIdentifiers[$oid1]) - ? $this->entityIdentifiers[$oid1] - : $this->identifierFlattener->flattenIdentifier($class, $class->getIdentifierValues($entity1)); - $id2 = isset($this->entityIdentifiers[$oid2]) - ? $this->entityIdentifiers[$oid2] - : $this->identifierFlattener->flattenIdentifier($class, $class->getIdentifierValues($entity2)); - - return $id1 === $id2 || implode(' ', $id1) === implode(' ', $id2); - } - - /** - * @throws ORMInvalidArgumentException - */ - private function assertThatThereAreNoUnintentionallyNonPersistedAssociations() : void - { - $entitiesNeedingCascadePersist = \array_diff_key($this->nonCascadedNewDetectedEntities, $this->entityInsertions); - - $this->nonCascadedNewDetectedEntities = []; - - if ($entitiesNeedingCascadePersist) { - throw ORMInvalidArgumentException::newEntitiesFoundThroughRelationships( - \array_values($entitiesNeedingCascadePersist) - ); - } - } - - /** - * @param object $entity - * @param object $managedCopy - * - * @throws ORMException - * @throws OptimisticLockException - * @throws TransactionRequiredException - */ - private function mergeEntityStateIntoManagedCopy($entity, $managedCopy) - { - if (! $this->isLoaded($entity)) { - return; - } - - if (! $this->isLoaded($managedCopy)) { - $managedCopy->__load(); - } - - $class = $this->em->getClassMetadata(get_class($entity)); - - foreach ($this->reflectionPropertiesGetter->getProperties($class->name) as $prop) { - $name = $prop->name; - - $prop->setAccessible(true); - - if ( ! isset($class->associationMappings[$name])) { - if ( ! $class->isIdentifier($name)) { - $prop->setValue($managedCopy, $prop->getValue($entity)); - } - } else { - $assoc2 = $class->associationMappings[$name]; - - if ($assoc2['type'] & ClassMetadata::TO_ONE) { - $other = $prop->getValue($entity); - if ($other === null) { - $prop->setValue($managedCopy, null); - } else { - if ($other instanceof Proxy && !$other->__isInitialized()) { - // do not merge fields marked lazy that have not been fetched. - continue; - } - - if ( ! $assoc2['isCascadeMerge']) { - if ($this->getEntityState($other) === self::STATE_DETACHED) { - $targetClass = $this->em->getClassMetadata($assoc2['targetEntity']); - $relatedId = $targetClass->getIdentifierValues($other); - - if ($targetClass->subClasses) { - $other = $this->em->find($targetClass->name, $relatedId); - } else { - $other = $this->em->getProxyFactory()->getProxy( - $assoc2['targetEntity'], - $relatedId - ); - $this->registerManaged($other, $relatedId, []); - } - } - - $prop->setValue($managedCopy, $other); - } - } - } else { - $mergeCol = $prop->getValue($entity); - - if ($mergeCol instanceof PersistentCollection && ! $mergeCol->isInitialized()) { - // do not merge fields marked lazy that have not been fetched. - // keep the lazy persistent collection of the managed copy. - continue; - } - - $managedCol = $prop->getValue($managedCopy); - - if ( ! $managedCol) { - $managedCol = new PersistentCollection( - $this->em, - $this->em->getClassMetadata($assoc2['targetEntity']), - new ArrayCollection - ); - $managedCol->setOwner($managedCopy, $assoc2); - $prop->setValue($managedCopy, $managedCol); - } - - if ($assoc2['isCascadeMerge']) { - $managedCol->initialize(); - - // clear and set dirty a managed collection if its not also the same collection to merge from. - if ( ! $managedCol->isEmpty() && $managedCol !== $mergeCol) { - $managedCol->unwrap()->clear(); - $managedCol->setDirty(true); - - if ($assoc2['isOwningSide'] - && $assoc2['type'] == ClassMetadata::MANY_TO_MANY - && $class->isChangeTrackingNotify() - ) { - $this->scheduleForDirtyCheck($managedCopy); - } - } - } - } - } - - if ($class->isChangeTrackingNotify()) { - // Just treat all properties as changed, there is no other choice. - $this->propertyChanged($managedCopy, $name, null, $prop->getValue($managedCopy)); - } - } - } - - /** - * This method called by hydrators, and indicates that hydrator totally completed current hydration cycle. - * Unit of work able to fire deferred events, related to loading events here. - * - * @internal should be called internally from object hydrators - */ - public function hydrationComplete() - { - $this->hydrationCompleteHandler->hydrationComplete(); - } - - /** - * @param string $entityName - */ - private function clearIdentityMapForEntityName($entityName) - { - if (! isset($this->identityMap[$entityName])) { - return; - } - - $visited = []; - - foreach ($this->identityMap[$entityName] as $entity) { - $this->doDetach($entity, $visited, false); - } - } - - /** - * @param string $entityName - */ - private function clearEntityInsertionsForEntityName($entityName) - { - foreach ($this->entityInsertions as $hash => $entity) { - // note: performance optimization - `instanceof` is much faster than a function call - if ($entity instanceof $entityName && get_class($entity) === $entityName) { - unset($this->entityInsertions[$hash]); - } - } - } - - /** - * @param ClassMetadata $class - * @param mixed $identifierValue - * - * @return mixed the identifier after type conversion - * - * @throws \Doctrine\ORM\Mapping\MappingException if the entity has more than a single identifier - */ - private function convertSingleFieldIdentifierToPHPValue(ClassMetadata $class, $identifierValue) - { - return $this->em->getConnection()->convertToPHPValue( - $identifierValue, - $class->getTypeOfField($class->getSingleIdentifierFieldName()) - ); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/HierarchyDiscriminatorResolver.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/HierarchyDiscriminatorResolver.php deleted file mode 100644 index 9b08b7f..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/HierarchyDiscriminatorResolver.php +++ /dev/null @@ -1,41 +0,0 @@ -subClasses; - $hierarchyClasses[] = $rootClassMetadata->name; - - $discriminators = []; - - foreach ($hierarchyClasses as $class) { - $currentMetadata = $entityManager->getClassMetadata($class); - $currentDiscriminator = $currentMetadata->discriminatorValue; - - if (null !== $currentDiscriminator) { - $discriminators[$currentDiscriminator] = null; - } - } - - return $discriminators; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/IdentifierFlattener.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/IdentifierFlattener.php deleted file mode 100644 index a283a68..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/IdentifierFlattener.php +++ /dev/null @@ -1,102 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Utility; - -use Doctrine\ORM\UnitOfWork; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory; - -/** - * The IdentifierFlattener utility now houses some of the identifier manipulation logic from unit of work, so that it - * can be re-used elsewhere. - * - * @since 2.5 - * @author Rob Caiger - */ -final class IdentifierFlattener -{ - /** - * The UnitOfWork used to coordinate object-level transactions. - * - * @var UnitOfWork - */ - private $unitOfWork; - - /** - * The metadata factory, used to retrieve the ORM metadata of entity classes. - * - * @var ClassMetadataFactory - */ - private $metadataFactory; - - /** - * Initializes a new IdentifierFlattener instance, bound to the given EntityManager. - * - * @param UnitOfWork $unitOfWork - * @param ClassMetadataFactory $metadataFactory - */ - public function __construct(UnitOfWork $unitOfWork, ClassMetadataFactory $metadataFactory) - { - $this->unitOfWork = $unitOfWork; - $this->metadataFactory = $metadataFactory; - } - - /** - * convert foreign identifiers into scalar foreign key values to avoid object to string conversion failures. - * - * @param ClassMetadata $class - * @param array $id - * - * @return array - */ - public function flattenIdentifier(ClassMetadata $class, array $id) - { - $flatId = []; - - foreach ($class->identifier as $field) { - if (isset($class->associationMappings[$field]) && isset($id[$field]) && is_object($id[$field])) { - /* @var $targetClassMetadata ClassMetadata */ - $targetClassMetadata = $this->metadataFactory->getMetadataFor( - $class->associationMappings[$field]['targetEntity'] - ); - - if ($this->unitOfWork->isInIdentityMap($id[$field])) { - $associatedId = $this->flattenIdentifier($targetClassMetadata, $this->unitOfWork->getEntityIdentifier($id[$field])); - } else { - $associatedId = $this->flattenIdentifier($targetClassMetadata, $targetClassMetadata->getIdentifierValues($id[$field])); - } - - $flatId[$field] = implode(' ', $associatedId); - } elseif (isset($class->associationMappings[$field])) { - $associatedId = []; - - foreach ($class->associationMappings[$field]['joinColumns'] as $joinColumn) { - $associatedId[] = $id[$joinColumn['name']]; - } - - $flatId[$field] = implode(' ', $associatedId); - } else { - $flatId[$field] = $id[$field]; - } - } - - return $flatId; - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/PersisterHelper.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/PersisterHelper.php deleted file mode 100644 index fc6e492..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Utility/PersisterHelper.php +++ /dev/null @@ -1,135 +0,0 @@ -. - */ - -namespace Doctrine\ORM\Utility; - -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Query\QueryException; - -/** - * The PersisterHelper contains logic to infer binding types which is used in - * several persisters. - * - * @link www.doctrine-project.org - * @since 2.5 - * @author Jasper N. Brouwer - */ -class PersisterHelper -{ - /** - * @param string $fieldName - * @param ClassMetadata $class - * @param EntityManagerInterface $em - * - * @return array - * - * @throws QueryException - */ - public static function getTypeOfField($fieldName, ClassMetadata $class, EntityManagerInterface $em) - { - if (isset($class->fieldMappings[$fieldName])) { - return [$class->fieldMappings[$fieldName]['type']]; - } - - if ( ! isset($class->associationMappings[$fieldName])) { - return []; - } - - $assoc = $class->associationMappings[$fieldName]; - - if (! $assoc['isOwningSide']) { - return self::getTypeOfField($assoc['mappedBy'], $em->getClassMetadata($assoc['targetEntity']), $em); - } - - if ($assoc['type'] & ClassMetadata::MANY_TO_MANY) { - $joinData = $assoc['joinTable']; - } else { - $joinData = $assoc; - } - - $types = []; - $targetClass = $em->getClassMetadata($assoc['targetEntity']); - - foreach ($joinData['joinColumns'] as $joinColumn) { - $types[] = self::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $em); - } - - return $types; - } - - /** - * @param string $columnName - * @param ClassMetadata $class - * @param EntityManagerInterface $em - * - * @return string - * - * @throws \RuntimeException - */ - public static function getTypeOfColumn($columnName, ClassMetadata $class, EntityManagerInterface $em) - { - if (isset($class->fieldNames[$columnName])) { - $fieldName = $class->fieldNames[$columnName]; - - if (isset($class->fieldMappings[$fieldName])) { - return $class->fieldMappings[$fieldName]['type']; - } - } - - // iterate over to-one association mappings - foreach ($class->associationMappings as $assoc) { - if ( ! isset($assoc['joinColumns'])) { - continue; - } - - foreach ($assoc['joinColumns'] as $joinColumn) { - if ($joinColumn['name'] == $columnName) { - $targetColumnName = $joinColumn['referencedColumnName']; - $targetClass = $em->getClassMetadata($assoc['targetEntity']); - - return self::getTypeOfColumn($targetColumnName, $targetClass, $em); - } - } - } - - // iterate over to-many association mappings - foreach ($class->associationMappings as $assoc) { - if ( ! (isset($assoc['joinTable']) && isset($assoc['joinTable']['joinColumns']))) { - continue; - } - - foreach ($assoc['joinTable']['joinColumns'] as $joinColumn) { - if ($joinColumn['name'] == $columnName) { - $targetColumnName = $joinColumn['referencedColumnName']; - $targetClass = $em->getClassMetadata($assoc['targetEntity']); - - return self::getTypeOfColumn($targetColumnName, $targetClass, $em); - } - } - } - - throw new \RuntimeException(sprintf( - 'Could not resolve type of column "%s" of class "%s"', - $columnName, - $class->getName() - )); - } -} diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Version.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Version.php deleted file mode 100644 index 1af5517..0000000 --- a/vendor/doctrine/orm/lib/Doctrine/ORM/Version.php +++ /dev/null @@ -1,57 +0,0 @@ -. - */ - -namespace Doctrine\ORM; - -/** - * Class to store and retrieve the version of Doctrine - * - * @link www.doctrine-project.org - * @since 2.0 - * @version $Revision$ - * @author Benjamin Eberlei - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * - * @deprecated 2.7 This class is being removed from the ORM and won't have any replacement - */ -class Version -{ - /** - * Current Doctrine Version - */ - const VERSION = '2.7.0'; - - /** - * 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); - } -} diff --git a/vendor/doctrine/orm/phpbench.json b/vendor/doctrine/orm/phpbench.json deleted file mode 100644 index 74fdef4..0000000 --- a/vendor/doctrine/orm/phpbench.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "bootstrap": "vendor/autoload.php", - "path": "tests/Doctrine/Performance", - - "extensions": [ - "PhpBench\\Extensions\\Dbal\\DbalExtension", - "PhpBench\\Extensions\\XDebug\\XDebugExtension" - ], - - "storage": "dbal", - "storage.dbal.connection": { - "driver": "pdo_sqlite", - "path": "tests/Doctrine/Performance/history.db" - } -} diff --git a/vendor/doctrine/orm/phpstan.neon b/vendor/doctrine/orm/phpstan.neon deleted file mode 100644 index 4046aa1..0000000 --- a/vendor/doctrine/orm/phpstan.neon +++ /dev/null @@ -1,4 +0,0 @@ -parameters: - earlyTerminatingMethodCalls: - Doctrine\ORM\Query\Parser: - - syntaxError diff --git a/vendor/doctrine/persistence/.doctrine-project.json b/vendor/doctrine/persistence/.doctrine-project.json deleted file mode 100644 index cfeefa4..0000000 --- a/vendor/doctrine/persistence/.doctrine-project.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "active": true, - "name": "Persistence", - "slug": "persistence", - "docsSlug": "doctrine-persistence", - "versions": [ - { - "name": "1.1", - "branchName": "1.1.x", - "slug": "latest", - "current": true, - "aliases": [ - "current", - "stable" - ] - }, - { - "name": "1.0", - "branchName": "1.0.x", - "slug": "1.0", - "maintained": false - } - ] -} diff --git a/vendor/doctrine/persistence/LICENSE b/vendor/doctrine/persistence/LICENSE deleted file mode 100644 index 8c38cc1..0000000 --- a/vendor/doctrine/persistence/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006-2015 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/doctrine/persistence/README.md b/vendor/doctrine/persistence/README.md deleted file mode 100644 index b5d32d5..0000000 --- a/vendor/doctrine/persistence/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Doctrine Persistence - -[![Build Status](https://travis-ci.org/doctrine/persistence.svg)](https://travis-ci.org/doctrine/persistence) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/persistence/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/persistence/?branch=master) -[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/persistence/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/persistence/?branch=master) - -The Doctrine Persistence project is a library that provides common abstractions for object mapper persistence. - -## More resources: - -* [Website](https://www.doctrine-project.org/) -* [Documentation](https://www.doctrine-project.org/projects/doctrine-persistence/en/latest/index.html) -* [Downloads](https://github.com/doctrine/persistence/releases) diff --git a/vendor/doctrine/persistence/UPGRADE-1.2.md b/vendor/doctrine/persistence/UPGRADE-1.2.md deleted file mode 100644 index 0c0115d..0000000 --- a/vendor/doctrine/persistence/UPGRADE-1.2.md +++ /dev/null @@ -1,6 +0,0 @@ -UPGRADE FROM 1.x to 1.2 -======================= - -* Deprecated `ObjectManager::merge()`. Please handle merge operations in your application instead. -* Deprecated `ObjectManager::detach()`. Please use `ObjectManager::clear()` instead. -* Deprecated `PersistentObject` class. Please implement this functionality directly in your application if you want ActiveRecord style functionality. diff --git a/vendor/doctrine/persistence/composer.json b/vendor/doctrine/persistence/composer.json deleted file mode 100644 index 10704f1..0000000 --- a/vendor/doctrine/persistence/composer.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "doctrine/persistence", - "type": "library", - "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", - "keywords": [ - "persistence", - "object", - "mapper", - "orm", - "odm" - ], - "homepage": "https://doctrine-project.org/projects/persistence.html", - "license": "MIT", - "authors": [ - {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, - {"name": "Roman Borschel", "email": "roman@code-factory.org"}, - {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, - {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, - {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}, - {"name": "Marco Pivetta", "email": "ocramius@gmail.com"} - ], - "require": { - "php": "^7.1", - "doctrine/annotations": "^1.0", - "doctrine/cache": "^1.0", - "doctrine/collections": "^1.0", - "doctrine/event-manager": "^1.0", - "doctrine/reflection": "^1.0" - }, - "require-dev": { - "phpstan/phpstan": "^0.11", - "doctrine/coding-standard": "^6.0", - "phpunit/phpunit": "^7.0" - }, - "conflict": { - "doctrine/common": "<2.10@dev" - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common", - "Doctrine\\Persistence\\": "lib/Doctrine/Persistence" - } - }, - "autoload-dev": { - "psr-4": { - "Doctrine\\Tests\\": "tests/Doctrine/Tests" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - } -} diff --git a/vendor/doctrine/persistence/lib/Doctrine/Common/NotifyPropertyChanged.php b/vendor/doctrine/persistence/lib/Doctrine/Common/NotifyPropertyChanged.php deleted file mode 100644 index b570bb8..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Common/NotifyPropertyChanged.php +++ /dev/null @@ -1,31 +0,0 @@ -getId(); // method exists through __call - */ -abstract class PersistentObject implements ObjectManagerAware -{ - /** @var ObjectManager|null */ - private static $objectManager = null; - - /** @var ClassMetadata|null */ - private $cm = null; - - /** - * Sets the object manager responsible for all persistent object base classes. - * - * @return void - */ - public static function setObjectManager(?ObjectManager $objectManager = null) - { - self::$objectManager = $objectManager; - } - - /** - * @return ObjectManager|null - */ - public static function getObjectManager() - { - return self::$objectManager; - } - - /** - * Injects the Doctrine Object Manager. - * - * @return void - * - * @throws RuntimeException - */ - public function injectObjectManager(ObjectManager $objectManager, ClassMetadata $classMetadata) - { - if ($objectManager !== self::$objectManager) { - throw new RuntimeException('Trying to use PersistentObject with different ObjectManager instances. ' . - 'Was PersistentObject::setObjectManager() called?'); - } - - $this->cm = $classMetadata; - } - - /** - * Sets a persistent fields value. - * - * @param string $field - * @param mixed[] $args - * - * @return void - * - * @throws BadMethodCallException When no persistent field exists by that name. - * @throws InvalidArgumentException When the wrong target object type is passed to an association. - */ - private function set($field, $args) - { - if ($this->cm->hasField($field) && ! $this->cm->isIdentifier($field)) { - $this->$field = $args[0]; - } elseif ($this->cm->hasAssociation($field) && $this->cm->isSingleValuedAssociation($field)) { - $targetClass = $this->cm->getAssociationTargetClass($field); - if (! ($args[0] instanceof $targetClass) && $args[0] !== null) { - throw new InvalidArgumentException("Expected persistent object of type '" . $targetClass . "'"); - } - $this->$field = $args[0]; - $this->completeOwningSide($field, $targetClass, $args[0]); - } else { - throw new BadMethodCallException("no field with name '" . $field . "' exists on '" . $this->cm->getName() . "'"); - } - } - - /** - * Gets a persistent field value. - * - * @param string $field - * - * @return mixed - * - * @throws BadMethodCallException When no persistent field exists by that name. - */ - private function get($field) - { - if ($this->cm->hasField($field) || $this->cm->hasAssociation($field)) { - return $this->$field; - } - - throw new BadMethodCallException("no field with name '" . $field . "' exists on '" . $this->cm->getName() . "'"); - } - - /** - * If this is an inverse side association, completes the owning side. - * - * @param string $field - * @param ClassMetadata $targetClass - * @param object $targetObject - * - * @return void - */ - private function completeOwningSide($field, $targetClass, $targetObject) - { - // add this object on the owning side as well, for obvious infinite recursion - // reasons this is only done when called on the inverse side. - if (! $this->cm->isAssociationInverseSide($field)) { - return; - } - - $mappedByField = $this->cm->getAssociationMappedByTargetField($field); - $targetMetadata = self::$objectManager->getClassMetadata($targetClass); - - $setter = ($targetMetadata->isCollectionValuedAssociation($mappedByField) ? 'add' : 'set') . $mappedByField; - $targetObject->$setter($this); - } - - /** - * Adds an object to a collection. - * - * @param string $field - * @param mixed[] $args - * - * @return void - * - * @throws BadMethodCallException - * @throws InvalidArgumentException - */ - private function add($field, $args) - { - if (! $this->cm->hasAssociation($field) || ! $this->cm->isCollectionValuedAssociation($field)) { - throw new BadMethodCallException('There is no method add' . $field . '() on ' . $this->cm->getName()); - } - - $targetClass = $this->cm->getAssociationTargetClass($field); - if (! ($args[0] instanceof $targetClass)) { - throw new InvalidArgumentException("Expected persistent object of type '" . $targetClass . "'"); - } - if (! ($this->$field instanceof Collection)) { - $this->$field = new ArrayCollection($this->$field ?: []); - } - $this->$field->add($args[0]); - $this->completeOwningSide($field, $targetClass, $args[0]); - } - - /** - * Initializes Doctrine Metadata for this class. - * - * @return void - * - * @throws RuntimeException - */ - private function initializeDoctrine() - { - if ($this->cm !== null) { - return; - } - - if (! self::$objectManager) { - throw new RuntimeException('No runtime object manager set. Call PersistentObject#setObjectManager().'); - } - - $this->cm = self::$objectManager->getClassMetadata(static::class); - } - - /** - * Magic methods. - * - * @param string $method - * @param mixed[] $args - * - * @return mixed - * - * @throws BadMethodCallException - */ - public function __call($method, $args) - { - $this->initializeDoctrine(); - - $command = substr($method, 0, 3); - $field = lcfirst(substr($method, 3)); - if ($command === 'set') { - $this->set($field, $args); - } elseif ($command === 'get') { - return $this->get($field); - } elseif ($command === 'add') { - $this->add($field, $args); - } else { - throw new BadMethodCallException('There is no method ' . $method . ' on ' . $this->cm->getName()); - } - } -} - -class_exists(\Doctrine\Common\Persistence\PersistentObject::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Proxy.php b/vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Proxy.php deleted file mode 100644 index e7a31eb..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Common/Persistence/Proxy.php +++ /dev/null @@ -1,31 +0,0 @@ -name = $name; - $this->connections = $connections; - $this->managers = $managers; - $this->defaultConnection = $defaultConnection; - $this->defaultManager = $defaultManager; - $this->proxyInterfaceName = $proxyInterfaceName; - } - - /** - * Fetches/creates the given services. - * - * A service in this context is connection or a manager instance. - * - * @param string $name The name of the service. - * - * @return ObjectManager The instance of the given service. - */ - abstract protected function getService($name); - - /** - * Resets the given services. - * - * A service in this context is connection or a manager instance. - * - * @param string $name The name of the service. - * - * @return void - */ - abstract protected function resetService($name); - - /** - * Gets the name of the registry. - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * {@inheritdoc} - */ - public function getConnection($name = null) - { - if ($name === null) { - $name = $this->defaultConnection; - } - - if (! isset($this->connections[$name])) { - throw new InvalidArgumentException(sprintf('Doctrine %s Connection named "%s" does not exist.', $this->name, $name)); - } - - return $this->getService($this->connections[$name]); - } - - /** - * {@inheritdoc} - */ - public function getConnectionNames() - { - return $this->connections; - } - - /** - * {@inheritdoc} - */ - public function getConnections() - { - $connections = []; - foreach ($this->connections as $name => $id) { - $connections[$name] = $this->getService($id); - } - - return $connections; - } - - /** - * {@inheritdoc} - */ - public function getDefaultConnectionName() - { - return $this->defaultConnection; - } - - /** - * {@inheritdoc} - */ - public function getDefaultManagerName() - { - return $this->defaultManager; - } - - /** - * {@inheritdoc} - * - * @throws InvalidArgumentException - */ - public function getManager($name = null) - { - if ($name === null) { - $name = $this->defaultManager; - } - - if (! isset($this->managers[$name])) { - throw new InvalidArgumentException(sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name)); - } - - return $this->getService($this->managers[$name]); - } - - /** - * {@inheritdoc} - */ - public function getManagerForClass($class) - { - // Check for namespace alias - if (strpos($class, ':') !== false) { - [$namespaceAlias, $simpleClassName] = explode(':', $class, 2); - $class = $this->getAliasNamespace($namespaceAlias) . '\\' . $simpleClassName; - } - - $proxyClass = new ReflectionClass($class); - - if ($proxyClass->implementsInterface($this->proxyInterfaceName)) { - $parentClass = $proxyClass->getParentClass(); - - if (! $parentClass) { - return null; - } - - $class = $parentClass->getName(); - } - - foreach ($this->managers as $id) { - $manager = $this->getService($id); - - if (! $manager->getMetadataFactory()->isTransient($class)) { - return $manager; - } - } - } - - /** - * {@inheritdoc} - */ - public function getManagerNames() - { - return $this->managers; - } - - /** - * {@inheritdoc} - */ - public function getManagers() - { - $dms = []; - foreach ($this->managers as $name => $id) { - $dms[$name] = $this->getService($id); - } - - return $dms; - } - - /** - * {@inheritdoc} - */ - public function getRepository($persistentObjectName, $persistentManagerName = null) - { - return $this - ->selectManager($persistentObjectName, $persistentManagerName) - ->getRepository($persistentObjectName); - } - - /** - * {@inheritdoc} - */ - public function resetManager($name = null) - { - if ($name === null) { - $name = $this->defaultManager; - } - - if (! isset($this->managers[$name])) { - throw new InvalidArgumentException(sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name)); - } - - // force the creation of a new document manager - // if the current one is closed - $this->resetService($this->managers[$name]); - - return $this->getManager($name); - } - - private function selectManager(string $persistentObjectName, ?string $persistentManagerName = null) : ObjectManager - { - if ($persistentManagerName !== null) { - return $this->getManager($persistentManagerName); - } - - return $this->getManagerForClass($persistentObjectName) ?? $this->getManager(); - } -} - -class_exists(\Doctrine\Common\Persistence\AbstractManagerRegistry::class); -interface_exists(ObjectManager::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/ConnectionRegistry.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/ConnectionRegistry.php deleted file mode 100644 index a822c71..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/ConnectionRegistry.php +++ /dev/null @@ -1,43 +0,0 @@ -object = $object; - $this->objectManager = $objectManager; - } - - /** - * Retrieves the associated entity. - * - * @deprecated - * - * @return object - */ - public function getEntity() - { - return $this->object; - } - - /** - * Retrieves the associated object. - * - * @return object - */ - public function getObject() - { - return $this->object; - } - - /** - * Retrieves the associated ObjectManager. - * - * @return ObjectManager - */ - public function getObjectManager() - { - return $this->objectManager; - } -} - -class_exists(\Doctrine\Common\Persistence\Event\LifecycleEventArgs::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/LoadClassMetadataEventArgs.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/LoadClassMetadataEventArgs.php deleted file mode 100644 index 31aae4a..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/LoadClassMetadataEventArgs.php +++ /dev/null @@ -1,48 +0,0 @@ -classMetadata = $classMetadata; - $this->objectManager = $objectManager; - } - - /** - * Retrieves the associated ClassMetadata. - * - * @return ClassMetadata - */ - public function getClassMetadata() - { - return $this->classMetadata; - } - - /** - * Retrieves the associated ObjectManager. - * - * @return ObjectManager - */ - public function getObjectManager() - { - return $this->objectManager; - } -} - -class_exists(\Doctrine\Common\Persistence\Event\LoadClassMetadataEventArgs::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/ManagerEventArgs.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/ManagerEventArgs.php deleted file mode 100644 index 66dd903..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/ManagerEventArgs.php +++ /dev/null @@ -1,33 +0,0 @@ -objectManager = $objectManager; - } - - /** - * Retrieves the associated ObjectManager. - * - * @return ObjectManager - */ - public function getObjectManager() - { - return $this->objectManager; - } -} - -class_exists(\Doctrine\Common\Persistence\Event\ManagerEventArgs::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/OnClearEventArgs.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/OnClearEventArgs.php deleted file mode 100644 index cc263c1..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/OnClearEventArgs.php +++ /dev/null @@ -1,61 +0,0 @@ -objectManager = $objectManager; - $this->entityClass = $entityClass; - } - - /** - * Retrieves the associated ObjectManager. - * - * @return ObjectManager - */ - public function getObjectManager() - { - return $this->objectManager; - } - - /** - * Returns the name of the entity class that is cleared, or null if all are cleared. - * - * @return string|null - */ - public function getEntityClass() - { - return $this->entityClass; - } - - /** - * Returns whether this event clears all entities. - * - * @return bool - */ - public function clearsAllEntities() - { - return $this->entityClass === null; - } -} - -class_exists(\Doctrine\Common\Persistence\Event\OnClearEventArgs::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/PreUpdateEventArgs.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/PreUpdateEventArgs.php deleted file mode 100644 index b9f8376..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Event/PreUpdateEventArgs.php +++ /dev/null @@ -1,116 +0,0 @@ -entityChangeSet = &$changeSet; - } - - /** - * Retrieves the entity changeset. - * - * @return mixed[][] - */ - public function getEntityChangeSet() - { - return $this->entityChangeSet; - } - - /** - * Checks if field has a changeset. - * - * @param string $field - * - * @return bool - */ - public function hasChangedField($field) - { - return isset($this->entityChangeSet[$field]); - } - - /** - * Gets the old value of the changeset of the changed field. - * - * @param string $field - * - * @return mixed - */ - public function getOldValue($field) - { - $this->assertValidField($field); - - return $this->entityChangeSet[$field][0]; - } - - /** - * Gets the new value of the changeset of the changed field. - * - * @param string $field - * - * @return mixed - */ - public function getNewValue($field) - { - $this->assertValidField($field); - - return $this->entityChangeSet[$field][1]; - } - - /** - * Sets the new value of this field. - * - * @param string $field - * @param mixed $value - * - * @return void - */ - public function setNewValue($field, $value) - { - $this->assertValidField($field); - - $this->entityChangeSet[$field][1] = $value; - } - - /** - * Asserts the field exists in changeset. - * - * @param string $field - * - * @return void - * - * @throws InvalidArgumentException - */ - private function assertValidField($field) - { - if (! isset($this->entityChangeSet[$field])) { - throw new InvalidArgumentException(sprintf( - 'Field "%s" is not a valid field of the entity "%s" in PreUpdateEventArgs.', - $field, - get_class($this->getObject()) - )); - } - } -} - -class_exists(\Doctrine\Common\Persistence\Event\PreUpdateEventArgs::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/ManagerRegistry.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/ManagerRegistry.php deleted file mode 100644 index b28664c..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/ManagerRegistry.php +++ /dev/null @@ -1,92 +0,0 @@ -cacheDriver = $cacheDriver; - } - - /** - * Gets the cache driver used by the factory to cache ClassMetadata instances. - * - * @return Cache|null - */ - public function getCacheDriver() - { - return $this->cacheDriver; - } - - /** - * Returns an array of all the loaded metadata currently in memory. - * - * @return ClassMetadata[] - */ - public function getLoadedMetadata() - { - return $this->loadedMetadata; - } - - /** - * Forces the factory to load the metadata of all classes known to the underlying - * mapping driver. - * - * @return ClassMetadata[] The ClassMetadata instances of all mapped classes. - */ - public function getAllMetadata() - { - if (! $this->initialized) { - $this->initialize(); - } - - $driver = $this->getDriver(); - $metadata = []; - foreach ($driver->getAllClassNames() as $className) { - $metadata[] = $this->getMetadataFor($className); - } - - return $metadata; - } - - /** - * Lazy initialization of this stuff, especially the metadata driver, - * since these are not needed at all when a metadata cache is active. - * - * @return void - */ - abstract protected function initialize(); - - /** - * Gets the fully qualified class-name from the namespace alias. - * - * @param string $namespaceAlias - * @param string $simpleClassName - * - * @return string - */ - abstract protected function getFqcnFromAlias($namespaceAlias, $simpleClassName); - - /** - * Returns the mapping driver implementation. - * - * @return MappingDriver - */ - abstract protected function getDriver(); - - /** - * Wakes up reflection after ClassMetadata gets unserialized from cache. - * - * @return void - */ - abstract protected function wakeupReflection(ClassMetadata $class, ReflectionService $reflService); - - /** - * Initializes Reflection after ClassMetadata was constructed. - * - * @return void - */ - abstract protected function initializeReflection(ClassMetadata $class, ReflectionService $reflService); - - /** - * Checks whether the class metadata is an entity. - * - * This method should return false for mapped superclasses or embedded classes. - * - * @return bool - */ - abstract protected function isEntity(ClassMetadata $class); - - /** - * Gets the class metadata descriptor for a class. - * - * @param string $className The name of the class. - * - * @return ClassMetadata - * - * @throws ReflectionException - * @throws MappingException - */ - public function getMetadataFor($className) - { - if (isset($this->loadedMetadata[$className])) { - return $this->loadedMetadata[$className]; - } - - // Check for namespace alias - if (strpos($className, ':') !== false) { - [$namespaceAlias, $simpleClassName] = explode(':', $className, 2); - - $realClassName = $this->getFqcnFromAlias($namespaceAlias, $simpleClassName); - } else { - $realClassName = $this->getRealClass($className); - } - - if (isset($this->loadedMetadata[$realClassName])) { - // We do not have the alias name in the map, include it - return $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName]; - } - - $loadingException = null; - - try { - if ($this->cacheDriver) { - $cached = $this->cacheDriver->fetch($realClassName . $this->cacheSalt); - if ($cached instanceof ClassMetadata) { - $this->loadedMetadata[$realClassName] = $cached; - - $this->wakeupReflection($cached, $this->getReflectionService()); - } else { - foreach ($this->loadMetadata($realClassName) as $loadedClassName) { - $this->cacheDriver->save( - $loadedClassName . $this->cacheSalt, - $this->loadedMetadata[$loadedClassName] - ); - } - } - } else { - $this->loadMetadata($realClassName); - } - } catch (MappingException $loadingException) { - $fallbackMetadataResponse = $this->onNotFoundMetadata($realClassName); - - if (! $fallbackMetadataResponse) { - throw $loadingException; - } - - $this->loadedMetadata[$realClassName] = $fallbackMetadataResponse; - } - - if ($className !== $realClassName) { - // We do not have the alias name in the map, include it - $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName]; - } - - return $this->loadedMetadata[$className]; - } - - /** - * Checks whether the factory has the metadata for a class loaded already. - * - * @param string $className - * - * @return bool TRUE if the metadata of the class in question is already loaded, FALSE otherwise. - */ - public function hasMetadataFor($className) - { - return isset($this->loadedMetadata[$className]); - } - - /** - * Sets the metadata descriptor for a specific class. - * - * NOTE: This is only useful in very special cases, like when generating proxy classes. - * - * @param string $className - * @param ClassMetadata $class - * - * @return void - */ - public function setMetadataFor($className, $class) - { - $this->loadedMetadata[$className] = $class; - } - - /** - * Gets an array of parent classes for the given entity class. - * - * @param string $name - * - * @return string[] - */ - protected function getParentClasses($name) - { - // Collect parent classes, ignoring transient (not-mapped) classes. - $parentClasses = []; - - foreach (array_reverse($this->getReflectionService()->getParentClasses($name)) as $parentClass) { - if ($this->getDriver()->isTransient($parentClass)) { - continue; - } - - $parentClasses[] = $parentClass; - } - - return $parentClasses; - } - - /** - * Loads the metadata of the class in question and all it's ancestors whose metadata - * is still not loaded. - * - * Important: The class $name does not necessarily exist at this point here. - * Scenarios in a code-generation setup might have access to XML/YAML - * Mapping files without the actual PHP code existing here. That is why the - * {@see Doctrine\Common\Persistence\Mapping\ReflectionService} interface - * should be used for reflection. - * - * @param string $name The name of the class for which the metadata should get loaded. - * - * @return string[] - */ - protected function loadMetadata($name) - { - if (! $this->initialized) { - $this->initialize(); - } - - $loaded = []; - - $parentClasses = $this->getParentClasses($name); - $parentClasses[] = $name; - - // Move down the hierarchy of parent classes, starting from the topmost class - $parent = null; - $rootEntityFound = false; - $visited = []; - $reflService = $this->getReflectionService(); - foreach ($parentClasses as $className) { - if (isset($this->loadedMetadata[$className])) { - $parent = $this->loadedMetadata[$className]; - if ($this->isEntity($parent)) { - $rootEntityFound = true; - array_unshift($visited, $className); - } - continue; - } - - $class = $this->newClassMetadataInstance($className); - $this->initializeReflection($class, $reflService); - - $this->doLoadMetadata($class, $parent, $rootEntityFound, $visited); - - $this->loadedMetadata[$className] = $class; - - $parent = $class; - - if ($this->isEntity($class)) { - $rootEntityFound = true; - array_unshift($visited, $className); - } - - $this->wakeupReflection($class, $reflService); - - $loaded[] = $className; - } - - return $loaded; - } - - /** - * Provides a fallback hook for loading metadata when loading failed due to reflection/mapping exceptions - * - * Override this method to implement a fallback strategy for failed metadata loading - * - * @param string $className - * - * @return ClassMetadata|null - */ - protected function onNotFoundMetadata($className) - { - return null; - } - - /** - * Actually loads the metadata from the underlying metadata. - * - * @param ClassMetadata $class - * @param ClassMetadata|null $parent - * @param bool $rootEntityFound - * @param string[] $nonSuperclassParents All parent class names - * that are not marked as mapped superclasses. - * - * @return void - */ - abstract protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonSuperclassParents); - - /** - * Creates a new ClassMetadata instance for the given class name. - * - * @param string $className - * - * @return ClassMetadata - */ - abstract protected function newClassMetadataInstance($className); - - /** - * {@inheritDoc} - */ - public function isTransient($class) - { - if (! $this->initialized) { - $this->initialize(); - } - - // Check for namespace alias - if (strpos($class, ':') !== false) { - [$namespaceAlias, $simpleClassName] = explode(':', $class, 2); - $class = $this->getFqcnFromAlias($namespaceAlias, $simpleClassName); - } - - return $this->getDriver()->isTransient($class); - } - - /** - * Sets the reflectionService. - * - * @return void - */ - public function setReflectionService(ReflectionService $reflectionService) - { - $this->reflectionService = $reflectionService; - } - - /** - * Gets the reflection service associated with this metadata factory. - * - * @return ReflectionService - */ - public function getReflectionService() - { - if ($this->reflectionService === null) { - $this->reflectionService = new RuntimeReflectionService(); - } - - return $this->reflectionService; - } - - /** - * Gets the real class name of a class name that could be a proxy. - */ - private function getRealClass(string $class) : string - { - $pos = strrpos($class, '\\' . Proxy::MARKER . '\\'); - - if ($pos === false) { - return $class; - } - - return substr($class, $pos + Proxy::MARKER_LENGTH + 2); - } -} - -class_exists(\Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory::class); -interface_exists(ClassMetadata::class); -interface_exists(ReflectionService::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/ClassMetadata.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/ClassMetadata.php deleted file mode 100644 index 7b995d5..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/ClassMetadata.php +++ /dev/null @@ -1,157 +0,0 @@ -reader = $reader; - if (! $paths) { - return; - } - - $this->addPaths((array) $paths); - } - - /** - * Appends lookup paths to metadata driver. - * - * @param string[] $paths - * - * @return void - */ - public function addPaths(array $paths) - { - $this->paths = array_unique(array_merge($this->paths, $paths)); - } - - /** - * Retrieves the defined metadata lookup paths. - * - * @return string[] - */ - public function getPaths() - { - return $this->paths; - } - - /** - * Append exclude lookup paths to metadata driver. - * - * @param string[] $paths - */ - public function addExcludePaths(array $paths) - { - $this->excludePaths = array_unique(array_merge($this->excludePaths, $paths)); - } - - /** - * Retrieve the defined metadata lookup exclude paths. - * - * @return string[] - */ - public function getExcludePaths() - { - return $this->excludePaths; - } - - /** - * Retrieve the current annotation reader - * - * @return Reader - */ - public function getReader() - { - return $this->reader; - } - - /** - * Gets the file extension used to look for mapping files under. - * - * @return string - */ - public function getFileExtension() - { - return $this->fileExtension; - } - - /** - * Sets the file extension used to look for mapping files under. - * - * @param string $fileExtension The file extension to set. - * - * @return void - */ - public function setFileExtension($fileExtension) - { - $this->fileExtension = $fileExtension; - } - - /** - * Returns whether the class with the specified name is transient. Only non-transient - * classes, that is entities and mapped superclasses, should have their metadata loaded. - * - * A class is non-transient if it is annotated with an annotation - * from the {@see AnnotationDriver::entityAnnotationClasses}. - * - * @param string $className - * - * @return bool - */ - public function isTransient($className) - { - $classAnnotations = $this->reader->getClassAnnotations(new ReflectionClass($className)); - - foreach ($classAnnotations as $annot) { - if (isset($this->entityAnnotationClasses[get_class($annot)])) { - return false; - } - } - - return true; - } - - /** - * {@inheritDoc} - */ - public function getAllClassNames() - { - if ($this->classNames !== null) { - return $this->classNames; - } - - if (! $this->paths) { - throw MappingException::pathRequired(); - } - - $classes = []; - $includedFiles = []; - - foreach ($this->paths as $path) { - if (! is_dir($path)) { - throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); - } - - $iterator = new RegexIterator( - new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS), - RecursiveIteratorIterator::LEAVES_ONLY - ), - '/^.+' . preg_quote($this->fileExtension) . '$/i', - RecursiveRegexIterator::GET_MATCH - ); - - foreach ($iterator as $file) { - $sourceFile = $file[0]; - - if (! preg_match('(^phar:)i', $sourceFile)) { - $sourceFile = realpath($sourceFile); - } - - foreach ($this->excludePaths as $excludePath) { - $exclude = str_replace('\\', '/', realpath($excludePath)); - $current = str_replace('\\', '/', $sourceFile); - - if (strpos($current, $exclude) !== false) { - continue 2; - } - } - - require_once $sourceFile; - - $includedFiles[] = $sourceFile; - } - } - - $declared = get_declared_classes(); - - foreach ($declared as $className) { - $rc = new ReflectionClass($className); - $sourceFile = $rc->getFileName(); - if (! in_array($sourceFile, $includedFiles) || $this->isTransient($className)) { - continue; - } - - $classes[] = $className; - } - - $this->classNames = $classes; - - return $classes; - } -} - -class_exists(\Doctrine\Persistence\Mapping\Driver\AnnotationDriver::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/DefaultFileLocator.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/DefaultFileLocator.php deleted file mode 100644 index 4f49bc2..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/DefaultFileLocator.php +++ /dev/null @@ -1,164 +0,0 @@ -addPaths((array) $paths); - $this->fileExtension = $fileExtension; - } - - /** - * Appends lookup paths to metadata driver. - * - * @param string[] $paths - * - * @return void - */ - public function addPaths(array $paths) - { - $this->paths = array_unique(array_merge($this->paths, $paths)); - } - - /** - * Retrieves the defined metadata lookup paths. - * - * @return string[] - */ - public function getPaths() - { - return $this->paths; - } - - /** - * Gets the file extension used to look for mapping files under. - * - * @return string|null - */ - public function getFileExtension() - { - return $this->fileExtension; - } - - /** - * Sets the file extension used to look for mapping files under. - * - * @param string|null $fileExtension The file extension to set. - * - * @return void - */ - public function setFileExtension($fileExtension) - { - $this->fileExtension = $fileExtension; - } - - /** - * {@inheritDoc} - */ - public function findMappingFile($className) - { - $fileName = str_replace('\\', '.', $className) . $this->fileExtension; - - // Check whether file exists - foreach ($this->paths as $path) { - if (is_file($path . DIRECTORY_SEPARATOR . $fileName)) { - return $path . DIRECTORY_SEPARATOR . $fileName; - } - } - - throw MappingException::mappingFileNotFound($className, $fileName); - } - - /** - * {@inheritDoc} - */ - public function getAllClassNames($globalBasename) - { - $classes = []; - - if ($this->paths) { - foreach ($this->paths as $path) { - if (! is_dir($path)) { - throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); - } - - $iterator = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($path), - RecursiveIteratorIterator::LEAVES_ONLY - ); - - foreach ($iterator as $file) { - $fileName = $file->getBasename($this->fileExtension); - - if ($fileName === $file->getBasename() || $fileName === $globalBasename) { - continue; - } - - // NOTE: All files found here means classes are not transient! - $classes[] = str_replace('.', '\\', $fileName); - } - } - } - - return $classes; - } - - /** - * {@inheritDoc} - */ - public function fileExists($className) - { - $fileName = str_replace('\\', '.', $className) . $this->fileExtension; - - // Check whether file exists - foreach ((array) $this->paths as $path) { - if (is_file($path . DIRECTORY_SEPARATOR . $fileName)) { - return true; - } - } - - return false; - } -} - -class_exists(\Doctrine\Common\Persistence\Mapping\Driver\DefaultFileLocator::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileDriver.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileDriver.php deleted file mode 100644 index c8c783a..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileDriver.php +++ /dev/null @@ -1,199 +0,0 @@ -locator = $locator; - } else { - $this->locator = new DefaultFileLocator((array) $locator, $fileExtension); - } - } - - /** - * Sets the global basename. - * - * @param string $file - * - * @return void - */ - public function setGlobalBasename($file) - { - $this->globalBasename = $file; - } - - /** - * Retrieves the global basename. - * - * @return string|null - */ - public function getGlobalBasename() - { - return $this->globalBasename; - } - - /** - * Gets the element of schema meta data for the class from the mapping file. - * This will lazily load the mapping file if it is not loaded yet. - * - * @param string $className - * - * @return ClassMetadata The element of schema meta data. - * - * @throws MappingException - */ - public function getElement($className) - { - if ($this->classCache === null) { - $this->initialize(); - } - - if (isset($this->classCache[$className])) { - return $this->classCache[$className]; - } - - $result = $this->loadMappingFile($this->locator->findMappingFile($className)); - if (! isset($result[$className])) { - throw MappingException::invalidMappingFile($className, str_replace('\\', '.', $className) . $this->locator->getFileExtension()); - } - - $this->classCache[$className] = $result[$className]; - - return $result[$className]; - } - - /** - * {@inheritDoc} - */ - public function isTransient($className) - { - if ($this->classCache === null) { - $this->initialize(); - } - - if (isset($this->classCache[$className])) { - return false; - } - - return ! $this->locator->fileExists($className); - } - - /** - * {@inheritDoc} - */ - public function getAllClassNames() - { - if ($this->classCache === null) { - $this->initialize(); - } - - if (! $this->classCache) { - return (array) $this->locator->getAllClassNames($this->globalBasename); - } - - return array_unique(array_merge( - array_keys($this->classCache), - (array) $this->locator->getAllClassNames($this->globalBasename) - )); - } - - /** - * Loads a mapping file with the given name and returns a map - * from class/entity names to their corresponding file driver elements. - * - * @param string $file The mapping file to load. - * - * @return ClassMetadata[] - */ - abstract protected function loadMappingFile($file); - - /** - * Initializes the class cache from all the global files. - * - * Using this feature adds a substantial performance hit to file drivers as - * more metadata has to be loaded into memory than might actually be - * necessary. This may not be relevant to scenarios where caching of - * metadata is in place, however hits very hard in scenarios where no - * caching is used. - * - * @return void - */ - protected function initialize() - { - $this->classCache = []; - if ($this->globalBasename === null) { - return; - } - - foreach ($this->locator->getPaths() as $path) { - $file = $path . '/' . $this->globalBasename . $this->locator->getFileExtension(); - if (! is_file($file)) { - continue; - } - - $this->classCache = array_merge( - $this->classCache, - $this->loadMappingFile($file) - ); - } - } - - /** - * Retrieves the locator used to discover mapping files by className. - * - * @return FileLocator - */ - public function getLocator() - { - return $this->locator; - } - - /** - * Sets the locator used to discover mapping files by className. - */ - public function setLocator(FileLocator $locator) - { - $this->locator = $locator; - } -} - -class_exists(\Doctrine\Common\Persistence\Mapping\Driver\FileDriver::class); -interface_exists(FileLocator::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileLocator.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileLocator.php deleted file mode 100644 index bce3c03..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/FileLocator.php +++ /dev/null @@ -1,57 +0,0 @@ -defaultDriver; - } - - /** - * Set the default driver. - * - * @return void - */ - public function setDefaultDriver(MappingDriver $driver) - { - $this->defaultDriver = $driver; - } - - /** - * Adds a nested driver. - * - * @param string $namespace - * - * @return void - */ - public function addDriver(MappingDriver $nestedDriver, $namespace) - { - $this->drivers[$namespace] = $nestedDriver; - } - - /** - * Gets the array of nested drivers. - * - * @return MappingDriver[] $drivers - */ - public function getDrivers() - { - return $this->drivers; - } - - /** - * {@inheritDoc} - */ - public function loadMetadataForClass($className, ClassMetadata $metadata) - { - /** @var MappingDriver $driver */ - foreach ($this->drivers as $namespace => $driver) { - if (strpos($className, $namespace) === 0) { - $driver->loadMetadataForClass($className, $metadata); - - return; - } - } - - if ($this->defaultDriver !== null) { - $this->defaultDriver->loadMetadataForClass($className, $metadata); - - return; - } - - throw MappingException::classNotFoundInNamespaces($className, array_keys($this->drivers)); - } - - /** - * {@inheritDoc} - */ - public function getAllClassNames() - { - $classNames = []; - $driverClasses = []; - - /** @var MappingDriver $driver */ - foreach ($this->drivers as $namespace => $driver) { - $oid = spl_object_hash($driver); - - if (! isset($driverClasses[$oid])) { - $driverClasses[$oid] = $driver->getAllClassNames(); - } - - foreach ($driverClasses[$oid] as $className) { - if (strpos($className, $namespace) !== 0) { - continue; - } - - $classNames[$className] = true; - } - } - - if ($this->defaultDriver !== null) { - foreach ($this->defaultDriver->getAllClassNames() as $className) { - $classNames[$className] = true; - } - } - - return array_keys($classNames); - } - - /** - * {@inheritDoc} - */ - public function isTransient($className) - { - /** @var MappingDriver $driver */ - foreach ($this->drivers as $namespace => $driver) { - if (strpos($className, $namespace) === 0) { - return $driver->isTransient($className); - } - } - - if ($this->defaultDriver !== null) { - return $this->defaultDriver->isTransient($className); - } - - return true; - } -} - -class_exists(\Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain::class); -interface_exists(ClassMetadata::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/PHPDriver.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/PHPDriver.php deleted file mode 100644 index 4f1d948..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/PHPDriver.php +++ /dev/null @@ -1,49 +0,0 @@ -metadata = $metadata; - - $this->loadMappingFile($this->locator->findMappingFile($className)); - } - - /** - * {@inheritDoc} - */ - protected function loadMappingFile($file) - { - $metadata = $this->metadata; - include $file; - - return [$metadata->getName() => $metadata]; - } -} - -class_exists(\Doctrine\Common\Persistence\Mapping\Driver\PHPDriver::class); -interface_exists(ClassMetadata::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/StaticPHPDriver.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/StaticPHPDriver.php deleted file mode 100644 index 848b3bd..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/StaticPHPDriver.php +++ /dev/null @@ -1,134 +0,0 @@ -addPaths((array) $paths); - } - - /** - * Adds paths. - * - * @param string[] $paths - * - * @return void - */ - public function addPaths(array $paths) - { - $this->paths = array_unique(array_merge($this->paths, $paths)); - } - - /** - * {@inheritdoc} - */ - public function loadMetadataForClass($className, ClassMetadata $metadata) - { - $className::loadMetadata($metadata); - } - - /** - * {@inheritDoc} - * - * @todo Same code exists in AnnotationDriver, should we re-use it somehow or not worry about it? - */ - public function getAllClassNames() - { - if ($this->classNames !== null) { - return $this->classNames; - } - - if (! $this->paths) { - throw MappingException::pathRequired(); - } - - $classes = []; - $includedFiles = []; - - foreach ($this->paths as $path) { - if (! is_dir($path)) { - throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); - } - - $iterator = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($path), - RecursiveIteratorIterator::LEAVES_ONLY - ); - - foreach ($iterator as $file) { - if ($file->getBasename('.php') === $file->getBasename()) { - continue; - } - - $sourceFile = realpath($file->getPathName()); - require_once $sourceFile; - $includedFiles[] = $sourceFile; - } - } - - $declared = get_declared_classes(); - - foreach ($declared as $className) { - $rc = new ReflectionClass($className); - $sourceFile = $rc->getFileName(); - if (! in_array($sourceFile, $includedFiles) || $this->isTransient($className)) { - continue; - } - - $classes[] = $className; - } - - $this->classNames = $classes; - - return $classes; - } - - /** - * {@inheritdoc} - */ - public function isTransient($className) - { - return ! method_exists($className, 'loadMetadata'); - } -} - -class_exists(\Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver::class); -interface_exists(ClassMetadata::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/SymfonyFileLocator.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/SymfonyFileLocator.php deleted file mode 100644 index 3124c66..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/Driver/SymfonyFileLocator.php +++ /dev/null @@ -1,233 +0,0 @@ -addNamespacePrefixes($prefixes); - $this->fileExtension = $fileExtension; - - if (empty($nsSeparator)) { - throw new InvalidArgumentException('Namespace separator should not be empty'); - } - - $this->nsSeparator = (string) $nsSeparator; - } - - /** - * Adds Namespace Prefixes. - * - * @param string[] $prefixes - * - * @return void - */ - public function addNamespacePrefixes(array $prefixes) - { - $this->prefixes = array_merge($this->prefixes, $prefixes); - $this->paths = array_merge($this->paths, array_keys($prefixes)); - } - - /** - * Gets Namespace Prefixes. - * - * @return string[] - */ - public function getNamespacePrefixes() - { - return $this->prefixes; - } - - /** - * {@inheritDoc} - */ - public function getPaths() - { - return $this->paths; - } - - /** - * {@inheritDoc} - */ - public function getFileExtension() - { - return $this->fileExtension; - } - - /** - * Sets the file extension used to look for mapping files under. - * - * @param string $fileExtension The file extension to set. - * - * @return void - */ - public function setFileExtension($fileExtension) - { - $this->fileExtension = $fileExtension; - } - - /** - * {@inheritDoc} - */ - public function fileExists($className) - { - $defaultFileName = str_replace('\\', $this->nsSeparator, $className) . $this->fileExtension; - foreach ($this->paths as $path) { - if (! isset($this->prefixes[$path])) { - // global namespace class - if (is_file($path . DIRECTORY_SEPARATOR . $defaultFileName)) { - return true; - } - - continue; - } - - $prefix = $this->prefixes[$path]; - - if (strpos($className, $prefix . '\\') !== 0) { - continue; - } - - $filename = $path . '/' . strtr(substr($className, strlen($prefix) + 1), '\\', $this->nsSeparator) . $this->fileExtension; - if (is_file($filename)) { - return true; - } - } - - return false; - } - - /** - * {@inheritDoc} - */ - public function getAllClassNames($globalBasename = null) - { - $classes = []; - - if ($this->paths) { - foreach ((array) $this->paths as $path) { - if (! is_dir($path)) { - throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); - } - - $iterator = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($path), - RecursiveIteratorIterator::LEAVES_ONLY - ); - - foreach ($iterator as $file) { - $fileName = $file->getBasename($this->fileExtension); - - if ($fileName === $file->getBasename() || $fileName === $globalBasename) { - continue; - } - - // NOTE: All files found here means classes are not transient! - if (isset($this->prefixes[$path])) { - // Calculate namespace suffix for given prefix as a relative path from basepath to file path - $nsSuffix = strtr( - substr(realpath($file->getPath()), strlen(realpath($path))), - $this->nsSeparator, - '\\' - ); - - $classes[] = $this->prefixes[$path] . str_replace(DIRECTORY_SEPARATOR, '\\', $nsSuffix) . '\\' . str_replace($this->nsSeparator, '\\', $fileName); - } else { - $classes[] = str_replace($this->nsSeparator, '\\', $fileName); - } - } - } - } - - return $classes; - } - - /** - * {@inheritDoc} - */ - public function findMappingFile($className) - { - $defaultFileName = str_replace('\\', $this->nsSeparator, $className) . $this->fileExtension; - foreach ($this->paths as $path) { - if (! isset($this->prefixes[$path])) { - if (is_file($path . DIRECTORY_SEPARATOR . $defaultFileName)) { - return $path . DIRECTORY_SEPARATOR . $defaultFileName; - } - - continue; - } - - $prefix = $this->prefixes[$path]; - - if (strpos($className, $prefix . '\\') !== 0) { - continue; - } - - $filename = $path . '/' . strtr(substr($className, strlen($prefix) + 1), '\\', $this->nsSeparator) . $this->fileExtension; - if (is_file($filename)) { - return $filename; - } - } - - throw MappingException::mappingFileNotFound($className, substr($className, strrpos($className, '\\') + 1) . $this->fileExtension); - } -} - -class_exists(\Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/MappingException.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/MappingException.php deleted file mode 100644 index 9729e5f..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/MappingException.php +++ /dev/null @@ -1,98 +0,0 @@ -getShortName(); - } - - /** - * {@inheritDoc} - */ - public function getClassNamespace($class) - { - $reflectionClass = new ReflectionClass($class); - - return $reflectionClass->getNamespaceName(); - } - - /** - * {@inheritDoc} - */ - public function getClass($class) - { - return new ReflectionClass($class); - } - - /** - * {@inheritDoc} - */ - public function getAccessibleProperty($class, $property) - { - $reflectionProperty = new ReflectionProperty($class, $property); - - if ($reflectionProperty->isPublic()) { - $reflectionProperty = new RuntimePublicReflectionProperty($class, $property); - } - - $reflectionProperty->setAccessible(true); - - return $reflectionProperty; - } - - /** - * {@inheritDoc} - */ - public function hasPublicMethod($class, $method) - { - try { - $reflectionMethod = new ReflectionMethod($class, $method); - } catch (ReflectionException $e) { - return false; - } - - return $reflectionMethod->isPublic(); - } -} - -class_exists(\Doctrine\Common\Persistence\Mapping\RuntimeReflectionService::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/StaticReflectionService.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/StaticReflectionService.php deleted file mode 100644 index ac24e45..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/StaticReflectionService.php +++ /dev/null @@ -1,74 +0,0 @@ -find($id). - * - * @param string $className The class name of the object to find. - * @param mixed $id The identity of the object to find. - * - * @return object|null The found object. - */ - public function find($className, $id); - - /** - * Tells the ObjectManager to make an instance managed and persistent. - * - * The object will be entered into the database as a result of the flush operation. - * - * NOTE: The persist operation always considers objects that are not yet known to - * this ObjectManager as NEW. Do not pass detached objects to the persist operation. - * - * @param object $object The instance to make managed and persistent. - * - * @return void - */ - public function persist($object); - - /** - * Removes an object instance. - * - * A removed object will be removed from the database as a result of the flush operation. - * - * @param object $object The object instance to remove. - * - * @return void - */ - public function remove($object); - - /** - * Merges the state of a detached object into the persistence context - * of this ObjectManager and returns the managed copy of the object. - * The object passed to merge will not become associated/managed with this ObjectManager. - * - * @deprecated Merge operation is deprecated and will be removed in Persistence 2.0. - * Merging should be part of the business domain of an application rather than - * a generic operation of ObjectManager. - * - * @param object $object - * - * @return object - */ - public function merge($object); - - /** - * Clears the ObjectManager. All objects that are currently managed - * by this ObjectManager become detached. - * - * @param string|null $objectName if given, only objects of this type will get detached. - * - * @return void - */ - public function clear($objectName = null); - - /** - * Detaches an object from the ObjectManager, causing a managed object to - * become detached. Unflushed changes made to the object if any - * (including removal of the object), will not be synchronized to the database. - * Objects which previously referenced the detached object will continue to - * reference it. - * - * @deprecated Detach operation is deprecated and will be removed in Persistence 2.0. Please use - * {@see ObjectManager::clear()} instead. - * - * @param object $object The object to detach. - * - * @return void - */ - public function detach($object); - - /** - * Refreshes the persistent state of an object from the database, - * overriding any local changes that have not yet been persisted. - * - * @param object $object The object to refresh. - * - * @return void - */ - public function refresh($object); - - /** - * Flushes all changes to objects that have been queued up to now to the database. - * This effectively synchronizes the in-memory state of managed objects with the - * database. - * - * @return void - */ - public function flush(); - - /** - * Gets the repository for a class. - * - * @param string $className - * - * @return ObjectRepository - */ - public function getRepository($className); - - /** - * Returns the ClassMetadata descriptor for a class. - * - * The class name must be the fully-qualified class name without a leading backslash - * (as it is returned by get_class($obj)). - * - * @param string $className - * - * @return ClassMetadata - */ - public function getClassMetadata($className); - - /** - * Gets the metadata factory used to gather the metadata of classes. - * - * @return ClassMetadataFactory - */ - public function getMetadataFactory(); - - /** - * Helper method to initialize a lazy loading proxy or persistent collection. - * - * This method is a no-op for other objects. - * - * @param object $obj - * - * @return void - */ - public function initializeObject($obj); - - /** - * Checks if the object is part of the current UnitOfWork and therefore managed. - * - * @param object $object - * - * @return bool - */ - public function contains($object); -} - -interface_exists(\Doctrine\Common\Persistence\ObjectManager::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectManagerAware.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectManagerAware.php deleted file mode 100644 index 2593b7c..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectManagerAware.php +++ /dev/null @@ -1,34 +0,0 @@ -wrapped->find($className, $id); - } - - /** - * {@inheritdoc} - */ - public function persist($object) - { - $this->wrapped->persist($object); - } - - /** - * {@inheritdoc} - */ - public function remove($object) - { - $this->wrapped->remove($object); - } - - /** - * {@inheritdoc} - */ - public function merge($object) - { - return $this->wrapped->merge($object); - } - - /** - * {@inheritdoc} - */ - public function clear($objectName = null) - { - $this->wrapped->clear($objectName); - } - - /** - * {@inheritdoc} - */ - public function detach($object) - { - $this->wrapped->detach($object); - } - - /** - * {@inheritdoc} - */ - public function refresh($object) - { - $this->wrapped->refresh($object); - } - - /** - * {@inheritdoc} - */ - public function flush() - { - $this->wrapped->flush(); - } - - /** - * {@inheritdoc} - */ - public function getRepository($className) - { - return $this->wrapped->getRepository($className); - } - - /** - * {@inheritdoc} - */ - public function getClassMetadata($className) - { - return $this->wrapped->getClassMetadata($className); - } - - /** - * {@inheritdoc} - */ - public function getMetadataFactory() - { - return $this->wrapped->getMetadataFactory(); - } - - /** - * {@inheritdoc} - */ - public function initializeObject($obj) - { - $this->wrapped->initializeObject($obj); - } - - /** - * {@inheritdoc} - */ - public function contains($object) - { - return $this->wrapped->contains($object); - } -} - -class_exists(\Doctrine\Common\Persistence\ObjectManagerDecorator::class); diff --git a/vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectRepository.php b/vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectRepository.php deleted file mode 100644 index 7661be2..0000000 --- a/vendor/doctrine/persistence/lib/Doctrine/Persistence/ObjectRepository.php +++ /dev/null @@ -1,64 +0,0 @@ -= MAJOR).new.exists' # New issues of major or higher severity - - 'project.metric_change("scrutinizer.test_coverage", < 0)' # Code Coverage decreased from previous inspection diff --git a/vendor/doctrine/reflection/LICENSE b/vendor/doctrine/reflection/LICENSE deleted file mode 100644 index 8c38cc1..0000000 --- a/vendor/doctrine/reflection/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2006-2015 Doctrine Project - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/doctrine/reflection/README.md b/vendor/doctrine/reflection/README.md deleted file mode 100644 index 756c55b..0000000 --- a/vendor/doctrine/reflection/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Doctrine Reflection - -[![Build Status](https://travis-ci.org/doctrine/reflection.svg)](https://travis-ci.org/doctrine/reflection) -[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/reflection/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/reflection/?branch=master) -[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/reflection/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/reflection/?branch=master) - -The Doctrine Reflection project is a simple library used by the various Doctrine projects which adds some additional functionality on top of the reflection functionality that comes with PHP. It allows you to get the reflection information about classes, methods and properties statically. - -## More resources: - -* [Website](https://www.doctrine-project.org/) -* [Documentation](https://www.doctrine-project.org/projects/doctrine-reflection/en/latest/) -* [Downloads](https://github.com/doctrine/reflection/releases) diff --git a/vendor/doctrine/reflection/composer.json b/vendor/doctrine/reflection/composer.json deleted file mode 100644 index ad31969..0000000 --- a/vendor/doctrine/reflection/composer.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "doctrine/reflection", - "type": "library", - "description": "Doctrine Reflection component", - "keywords": ["reflection"], - "homepage": "https://www.doctrine-project.org/projects/reflection.html", - "license": "MIT", - "authors": [ - {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, - {"name": "Roman Borschel", "email": "roman@code-factory.org"}, - {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, - {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, - {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}, - {"name": "Marco Pivetta", "email": "ocramius@gmail.com"} - ], - "require": { - "php": "^7.1", - "ext-tokenizer": "*", - "doctrine/annotations": "^1.0" - }, - "require-dev": { - "phpstan/phpstan": "^0.9.2", - "phpstan/phpstan-phpunit": "^0.9.4", - "phpunit/phpunit": "^7.0", - "doctrine/coding-standard": "^4.0", - "doctrine/common": "^2.8", - "squizlabs/php_codesniffer": "^3.0" - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "autoload-dev": { - "psr-4": { - "Doctrine\\Tests\\": "tests/Doctrine/Tests" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - } -} diff --git a/vendor/doctrine/reflection/docs/en/index.rst b/vendor/doctrine/reflection/docs/en/index.rst deleted file mode 100644 index ae85870..0000000 --- a/vendor/doctrine/reflection/docs/en/index.rst +++ /dev/null @@ -1,22 +0,0 @@ -Reflection Documentation -================= - -The Doctrine Reflection documentation is a reference guide to everything you need -to know about the reflection project. - -Getting Help ------------- - -If this documentation is not helping to answer questions you have about -Doctrine Reflection don't panic. You can get help from different sources: - -- The `Doctrine Mailing List `_ -- Gitter chat room `#doctrine/reflection `_ -- Report a bug on `GitHub `_. -- On `StackOverflow `_ - -Getting Started ---------------- - -The best way to get started is with the :doc:`Introduction ` section. -Use the sidebar to browse other documentation for the Doctrine PHP Reflection project. diff --git a/vendor/doctrine/reflection/docs/en/reference/index.rst b/vendor/doctrine/reflection/docs/en/reference/index.rst deleted file mode 100644 index e383a17..0000000 --- a/vendor/doctrine/reflection/docs/en/reference/index.rst +++ /dev/null @@ -1,85 +0,0 @@ -Introduction -============ - -The Doctrine Reflection project is a simple library used by the various Doctrine projects which adds some additional -functionality on top of the reflection functionality that comes with PHP. It allows you to get the reflection information -about classes, methods and properties statically. - -Installation -============ - -The library can easily be installed with composer. - -.. code-block:: sh - - $ composer require doctrine/reflection - -Setup -===== - -.. code-block:: php - - use Doctrine\Common\Reflection\Psr0FindFile; - use Doctrine\Common\Reflection\StaticReflectionParser; - use App\Model\User; - - $finder = new Psr0FindFile(['App' => [ - '/path/to/project/src/App' - ]]); - - $staticReflectionParser = new StaticReflectionParser(User::class, $finder); - -Usage -===== - -.. code-block:: php - - echo $staticReflectionParser->getClassName(); - echo $staticReflectionParser->getNamespaceName(); - -StaticReflectionClass -===================== - -.. code-block:: php - - $staticReflectionClass = $staticReflectionParser->getReflectionClass(); - - echo $staticReflectionClass->getName(); - - echo $staticReflectionClass->getDocComment(); - - echo $staticReflectionClass->getNamespaceName(); - - print_r($staticReflectionClass->getUseStatements()); - -StaticReflectionMethod -====================== - -.. code-block:: php - - $staticReflectionMethod = $staticReflectionParser->getReflectionMethod('getSomething'); - - echo $staticReflectionMethod->getName(); - - echo $staticReflectionMethod->getDeclaringClass(); - - echo $staticReflectionMethod->getNamespaceName(); - - echo $staticReflectionMethod->getDocComment(); - - print_r($staticReflectionMethod->getUseStatements()); - -StaticReflectionProperty -======================== - -.. code-block:: php - - $staticReflectionProperty = $staticReflectionParser->getReflectionProperty('something'); - - echo $staticReflectionProperty->getName(); - - echo $staticReflectionProperty->getDeclaringClass(); - - echo $staticReflectionProperty->getDocComment(); - - print_r($staticReflectionProperty->getUseStatements()); diff --git a/vendor/doctrine/reflection/docs/en/sidebar.rst b/vendor/doctrine/reflection/docs/en/sidebar.rst deleted file mode 100644 index 0672d8d..0000000 --- a/vendor/doctrine/reflection/docs/en/sidebar.rst +++ /dev/null @@ -1,4 +0,0 @@ -.. toctree:: - :depth: 3 - - reference/index diff --git a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ClassFinderInterface.php b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ClassFinderInterface.php deleted file mode 100644 index 8f4ed00..0000000 --- a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ClassFinderInterface.php +++ /dev/null @@ -1,18 +0,0 @@ -prefixes = $prefixes; - } - - /** - * {@inheritDoc} - */ - public function findFile($class) - { - if ($class[0] === '\\') { - $class = substr($class, 1); - } - - $lastNsPos = strrpos($class, '\\'); - - if ($lastNsPos !== false) { - // namespaced class name - $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $lastNsPos)) . DIRECTORY_SEPARATOR; - $className = substr($class, $lastNsPos + 1); - } else { - // PEAR-like class name - $classPath = null; - $className = $class; - } - - $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; - - foreach ($this->prefixes as $prefix => $dirs) { - if (strpos($class, $prefix) !== 0) { - continue; - } - - foreach ($dirs as $dir) { - if (is_file($dir . DIRECTORY_SEPARATOR . $classPath)) { - return $dir . DIRECTORY_SEPARATOR . $classPath; - } - } - } - - return null; - } -} diff --git a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ReflectionProviderInterface.php b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ReflectionProviderInterface.php deleted file mode 100644 index 473325b..0000000 --- a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/ReflectionProviderInterface.php +++ /dev/null @@ -1,31 +0,0 @@ -getName(); - - if ($object instanceof Proxy && ! $object->__isInitialized()) { - $originalInitializer = $object->__getInitializer(); - $object->__setInitializer(null); - $val = $object->$name ?? null; - $object->__setInitializer($originalInitializer); - - return $val; - } - - return isset($object->$name) ? parent::getValue($object) : null; - } - - /** - * {@inheritDoc} - * - * Avoids triggering lazy loading via `__set` if the provided object - * is a {@see \Doctrine\Common\Proxy\Proxy}. - * @link https://bugs.php.net/bug.php?id=63463 - */ - public function setValue($object, $value = null) - { - if (! ($object instanceof Proxy && ! $object->__isInitialized())) { - parent::setValue($object, $value); - - return; - } - - $originalInitializer = $object->__getInitializer(); - $object->__setInitializer(null); - parent::setValue($object, $value); - $object->__setInitializer($originalInitializer); - } -} diff --git a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionClass.php b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionClass.php deleted file mode 100644 index 180f5a6..0000000 --- a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionClass.php +++ /dev/null @@ -1,413 +0,0 @@ -staticReflectionParser = $staticReflectionParser; - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return $this->staticReflectionParser->getClassName(); - } - - /** - * {@inheritDoc} - */ - public function getDocComment() - { - return $this->staticReflectionParser->getDocComment(); - } - - /** - * {@inheritDoc} - */ - public function getNamespaceName() - { - return $this->staticReflectionParser->getNamespaceName(); - } - - /** - * @return string[] - */ - public function getUseStatements() - { - return $this->staticReflectionParser->getUseStatements(); - } - - /** - * {@inheritDoc} - */ - public function getMethod($name) - { - return $this->staticReflectionParser->getReflectionMethod($name); - } - - /** - * {@inheritDoc} - */ - public function getProperty($name) - { - return $this->staticReflectionParser->getReflectionProperty($name); - } - - /** - * {@inheritDoc} - */ - public static function export($argument, $return = false) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getConstant($name) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getConstants() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getConstructor() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getDefaultProperties() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getEndLine() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getExtension() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getExtensionName() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getFileName() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getInterfaceNames() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getInterfaces() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getMethods($filter = null) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getModifiers() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getParentClass() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getProperties($filter = null) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getShortName() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getStartLine() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getStaticProperties() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getStaticPropertyValue($name, $default = '') - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getTraitAliases() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getTraitNames() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getTraits() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function hasConstant($name) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function hasMethod($name) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function hasProperty($name) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function implementsInterface($interface) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function inNamespace() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isAbstract() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isCloneable() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isFinal() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isInstance($object) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isInstantiable() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isInterface() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isInternal() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isIterateable() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isSubclassOf($class) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isTrait() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isUserDefined() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function newInstance($args) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function newInstanceArgs(array $args = []) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function newInstanceWithoutConstructor() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function setStaticPropertyValue($name, $value) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function __toString() - { - throw new ReflectionException('Method not implemented'); - } -} diff --git a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionMethod.php b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionMethod.php deleted file mode 100644 index 67bd998..0000000 --- a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionMethod.php +++ /dev/null @@ -1,344 +0,0 @@ -staticReflectionParser = $staticReflectionParser; - $this->methodName = $methodName; - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return $this->methodName; - } - - /** - * @return StaticReflectionParser - */ - protected function getStaticReflectionParser() - { - return $this->staticReflectionParser->getStaticReflectionParserForDeclaringClass('method', $this->methodName); - } - - /** - * {@inheritDoc} - */ - public function getDeclaringClass() - { - return $this->getStaticReflectionParser()->getReflectionClass(); - } - - /** - * {@inheritDoc} - */ - public function getNamespaceName() - { - return $this->getStaticReflectionParser()->getNamespaceName(); - } - - /** - * {@inheritDoc} - */ - public function getDocComment() - { - return $this->getStaticReflectionParser()->getDocComment('method', $this->methodName); - } - - /** - * @return string[] - */ - public function getUseStatements() - { - return $this->getStaticReflectionParser()->getUseStatements(); - } - - /** - * {@inheritDoc} - */ - public static function export($class, $name, $return = false) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getClosure($object) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getModifiers() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getPrototype() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function invoke($object, $parameter = null) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function invokeArgs($object, array $args) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isAbstract() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isConstructor() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isDestructor() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isFinal() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isPrivate() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isProtected() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isPublic() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isStatic() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function setAccessible($accessible) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function __toString() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getClosureThis() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getEndLine() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getExtension() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getExtensionName() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getFileName() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getNumberOfParameters() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getNumberOfRequiredParameters() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getParameters() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getShortName() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getStartLine() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getStaticVariables() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function inNamespace() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isClosure() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isDeprecated() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isInternal() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isUserDefined() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function returnsReference() - { - throw new ReflectionException('Method not implemented'); - } -} diff --git a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionParser.php b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionParser.php deleted file mode 100644 index 94e0b07..0000000 --- a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionParser.php +++ /dev/null @@ -1,328 +0,0 @@ - '', - 'property' => [], - 'method' => [], - ]; - - /** - * The name of the class this class extends, if any. - * - * @var string - */ - protected $parentClassName = ''; - - /** - * The parent PSR-0 Parser. - * - * @var \Doctrine\Common\Reflection\StaticReflectionParser - */ - protected $parentStaticReflectionParser; - - /** - * Parses a class residing in a PSR-0 hierarchy. - * - * @param string $className The full, namespaced class name. - * @param ClassFinderInterface $finder A ClassFinder object which finds the class. - * @param bool $classAnnotationOptimize Only retrieve the class docComment. - * Presumes there is only one statement per line. - */ - public function __construct($className, $finder, $classAnnotationOptimize = false) - { - $this->className = ltrim($className, '\\'); - $lastNsPos = strrpos($this->className, '\\'); - - if ($lastNsPos !== false) { - $this->namespace = substr($this->className, 0, $lastNsPos); - $this->shortClassName = substr($this->className, $lastNsPos + 1); - } else { - $this->shortClassName = $this->className; - } - - $this->finder = $finder; - $this->classAnnotationOptimize = $classAnnotationOptimize; - } - - /** - * @return void - */ - protected function parse() - { - $fileName = $this->finder->findFile($this->className); - - if ($this->parsed || ! $fileName) { - return; - } - $this->parsed = true; - $contents = file_get_contents($fileName); - if ($this->classAnnotationOptimize) { - $regex = sprintf('/\A.*^\s*((abstract|final)\s+)?class\s+%s\s+/sm', $this->shortClassName); - - if (preg_match($regex, $contents, $matches)) { - $contents = $matches[0]; - } - } - $tokenParser = new TokenParser($contents); - $docComment = ''; - $last_token = false; - - while ($token = $tokenParser->next(false)) { - switch ($token[0]) { - case T_USE: - $this->useStatements = array_merge($this->useStatements, $tokenParser->parseUseStatement()); - break; - case T_DOC_COMMENT: - $docComment = $token[1]; - break; - case T_CLASS: - if ($last_token !== T_PAAMAYIM_NEKUDOTAYIM) { - $this->docComment['class'] = $docComment; - $docComment = ''; - } - break; - case T_VAR: - case T_PRIVATE: - case T_PROTECTED: - case T_PUBLIC: - $token = $tokenParser->next(); - if ($token[0] === T_VARIABLE) { - $propertyName = substr($token[1], 1); - $this->docComment['property'][$propertyName] = $docComment; - continue 2; - } - if ($token[0] !== T_FUNCTION) { - // For example, it can be T_FINAL. - continue 2; - } - // No break. - case T_FUNCTION: - // The next string after function is the name, but - // there can be & before the function name so find the - // string. - while (($token = $tokenParser->next()) && $token[0] !== T_STRING) { - continue; - } - $methodName = $token[1]; - $this->docComment['method'][$methodName] = $docComment; - $docComment = ''; - break; - case T_EXTENDS: - $this->parentClassName = $tokenParser->parseClass(); - $nsPos = strpos($this->parentClassName, '\\'); - $fullySpecified = false; - if ($nsPos === 0) { - $fullySpecified = true; - } else { - if ($nsPos) { - $prefix = strtolower(substr($this->parentClassName, 0, $nsPos)); - $postfix = substr($this->parentClassName, $nsPos); - } else { - $prefix = strtolower($this->parentClassName); - $postfix = ''; - } - foreach ($this->useStatements as $alias => $use) { - if ($alias !== $prefix) { - continue; - } - - $this->parentClassName = '\\' . $use . $postfix; - $fullySpecified = true; - } - } - if (! $fullySpecified) { - $this->parentClassName = '\\' . $this->namespace . '\\' . $this->parentClassName; - } - break; - } - - $last_token = $token[0]; - } - } - - /** - * @return StaticReflectionParser - */ - protected function getParentStaticReflectionParser() - { - if (empty($this->parentStaticReflectionParser)) { - $this->parentStaticReflectionParser = new static($this->parentClassName, $this->finder); - } - - return $this->parentStaticReflectionParser; - } - - /** - * @return string - */ - public function getClassName() - { - return $this->className; - } - - /** - * @return string - */ - public function getNamespaceName() - { - return $this->namespace; - } - - /** - * {@inheritDoc} - */ - public function getReflectionClass() - { - return new StaticReflectionClass($this); - } - - /** - * {@inheritDoc} - */ - public function getReflectionMethod($methodName) - { - return new StaticReflectionMethod($this, $methodName); - } - - /** - * {@inheritDoc} - */ - public function getReflectionProperty($propertyName) - { - return new StaticReflectionProperty($this, $propertyName); - } - - /** - * Gets the use statements from this file. - * - * @return string[] - */ - public function getUseStatements() - { - $this->parse(); - - return $this->useStatements; - } - - /** - * Gets the doc comment. - * - * @param string $type The type: 'class', 'property' or 'method'. - * @param string $name The name of the property or method, not needed for 'class'. - * - * @return string The doc comment, empty string if none. - */ - public function getDocComment($type = 'class', $name = '') - { - $this->parse(); - - return $name ? $this->docComment[$type][$name] : $this->docComment[$type]; - } - - /** - * Gets the PSR-0 parser for the declaring class. - * - * @param string $type The type: 'property' or 'method'. - * @param string $name The name of the property or method. - * - * @return StaticReflectionParser A static reflection parser for the declaring class. - * - * @throws ReflectionException - */ - public function getStaticReflectionParserForDeclaringClass($type, $name) - { - $this->parse(); - if (isset($this->docComment[$type][$name])) { - return $this; - } - if (! empty($this->parentClassName)) { - return $this->getParentStaticReflectionParser()->getStaticReflectionParserForDeclaringClass($type, $name); - } - throw new ReflectionException('Invalid ' . $type . ' "' . $name . '"'); - } -} diff --git a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionProperty.php b/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionProperty.php deleted file mode 100644 index b94fda3..0000000 --- a/vendor/doctrine/reflection/lib/Doctrine/Common/Reflection/StaticReflectionProperty.php +++ /dev/null @@ -1,160 +0,0 @@ -staticReflectionParser = $staticReflectionParser; - $this->propertyName = $propertyName; - } - - /** - * {@inheritDoc} - */ - public function getName() - { - return $this->propertyName; - } - - /** - * @return StaticReflectionParser - */ - protected function getStaticReflectionParser() - { - return $this->staticReflectionParser->getStaticReflectionParserForDeclaringClass('property', $this->propertyName); - } - - /** - * {@inheritDoc} - */ - public function getDeclaringClass() - { - return $this->getStaticReflectionParser()->getReflectionClass(); - } - - /** - * {@inheritDoc} - */ - public function getDocComment() - { - return $this->getStaticReflectionParser()->getDocComment('property', $this->propertyName); - } - - /** - * @return string[] - */ - public function getUseStatements() - { - return $this->getStaticReflectionParser()->getUseStatements(); - } - - /** - * {@inheritDoc} - */ - public static function export($class, $name, $return = false) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getModifiers() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function getValue($object = null) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isDefault() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isPrivate() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isProtected() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isPublic() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function isStatic() - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function setAccessible($accessible) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function setValue($object, $value = null) - { - throw new ReflectionException('Method not implemented'); - } - - /** - * {@inheritDoc} - */ - public function __toString() - { - throw new ReflectionException('Method not implemented'); - } -} diff --git a/vendor/doctrine/reflection/phpstan.neon b/vendor/doctrine/reflection/phpstan.neon deleted file mode 100644 index 4c8102b..0000000 --- a/vendor/doctrine/reflection/phpstan.neon +++ /dev/null @@ -1,6 +0,0 @@ -includes: - - vendor/phpstan/phpstan-phpunit/extension.neon - -parameters: - ignoreErrors: - - '#Doctrine\\Common\\Reflection\\StaticReflection[a-zA-Z0-9_]+::__construct\(\) does not call parent constructor from Reflection[a-zA-Z0-9_]+#' diff --git a/vendor/jdorn/sql-formatter/.gitignore b/vendor/jdorn/sql-formatter/.gitignore deleted file mode 100644 index 48b8bf9..0000000 --- a/vendor/jdorn/sql-formatter/.gitignore +++ /dev/null @@ -1 +0,0 @@ -vendor/ diff --git a/vendor/jdorn/sql-formatter/.travis.yml b/vendor/jdorn/sql-formatter/.travis.yml deleted file mode 100644 index 310d8e0..0000000 --- a/vendor/jdorn/sql-formatter/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: php -php: - - 5.4 - - 5.3 -script: phpunit --coverage-text diff --git a/vendor/jdorn/sql-formatter/LICENSE.txt b/vendor/jdorn/sql-formatter/LICENSE.txt deleted file mode 100644 index e822279..0000000 --- a/vendor/jdorn/sql-formatter/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Jeremy Dorn - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/jdorn/sql-formatter/README.md b/vendor/jdorn/sql-formatter/README.md deleted file mode 100644 index a144323..0000000 --- a/vendor/jdorn/sql-formatter/README.md +++ /dev/null @@ -1,185 +0,0 @@ -SqlFormatter -============= - -A lightweight php class for formatting sql statements. - -It can automatically indent and add line breaks in addition to syntax highlighting. - -History -============ - -I found myself having to debug auto-generated SQL statements all the time and -wanted some way to easily output formatted HTML without having to include a -huge library or copy and paste into online formatters. - -I was originally planning to extract the formatting code from PhpMyAdmin, -but that was 10,000+ lines of code and used global variables. - -I saw that other people had the same problem and used Stack Overflow user -losif's answer as a starting point. http://stackoverflow.com/a/3924147 - -Usage -============ - -The SqlFormatter class has a static method 'format' which takes a SQL string -as input and returns a formatted HTML block inside a pre tag. - -Sample usage: - -```php -= NOW()) ) - GROUP BY Column1 ORDER BY Column3 DESC LIMIT 5,10"; - -echo SqlFormatter::format($query); -``` - -Output: - -![](http://jdorn.github.com/sql-formatter/format-highlight.png) - -Formatting Only -------------------------- -If you don't want syntax highlighting and only want the indentations and -line breaks, pass in false as the second parameter. - -This is useful for outputting to error logs or other non-html formats. - -```php -=5.2.4" - }, - "require-dev": { - "phpunit/phpunit": "3.7.*" - }, - "authors": [ - { - "name": "Jeremy Dorn", - "email": "jeremy@jeremydorn.com", - "homepage": "http://jeremydorn.com/" - } - ], - "autoload": { - "classmap": ["lib"] - }, - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - } -} diff --git a/vendor/jdorn/sql-formatter/composer.lock b/vendor/jdorn/sql-formatter/composer.lock deleted file mode 100644 index 379ab13..0000000 --- a/vendor/jdorn/sql-formatter/composer.lock +++ /dev/null @@ -1,422 +0,0 @@ -{ - "hash": "a709b40d4a35e7077aa40fbd0f78f6c6", - "packages": [ - - ], - "packages-dev": [ - { - "name": "phpunit/php-code-coverage", - "version": "1.2.x-dev", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "1.2.9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1.2.9", - "reference": "1.2.9", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": ">=1.3.0@stable", - "phpunit/php-text-template": ">=1.1.1@stable", - "phpunit/php-token-stream": ">=1.1.3@stable" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.0.5" - }, - "type": "library", - "autoload": { - "classmap": [ - "PHP/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2013-02-26 18:55:56" - }, - { - "name": "phpunit/php-file-iterator", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "2deb24c65ea78e126daa8d45b2089ddc29ec1d26" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2deb24c65ea78e126daa8d45b2089ddc29ec1d26", - "reference": "2deb24c65ea78e126daa8d45b2089ddc29ec1d26", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "File/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2013-01-07 10:47:05" - }, - { - "name": "phpunit/php-text-template", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "1eeef106193d2f8c539728e566bb4793071a9e18" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/1eeef106193d2f8c539728e566bb4793071a9e18", - "reference": "1eeef106193d2f8c539728e566bb4793071a9e18", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "Text/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2013-01-07 10:56:17" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.x-dev", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "ecf7920b27003a9412b07dad79dbb5ad1249e6c3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/ecf7920b27003a9412b07dad79dbb5ad1249e6c3", - "reference": "ecf7920b27003a9412b07dad79dbb5ad1249e6c3", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "PHP/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2013-01-30 06:08:51" - }, - { - "name": "phpunit/php-token-stream", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "c25dd88e1592e66dee2553c99ef244203d5a1b98" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c25dd88e1592e66dee2553c99ef244203d5a1b98", - "reference": "c25dd88e1592e66dee2553c99ef244203d5a1b98", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "PHP/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2013-01-07 10:56:35" - }, - { - "name": "phpunit/phpunit", - "version": "3.7.x-dev", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2c67e52445416bb7c14046b432acd7eb79e4e612" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2c67e52445416bb7c14046b432acd7eb79e4e612", - "reference": "2c67e52445416bb7c14046b432acd7eb79e4e612", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpunit/php-code-coverage": ">=1.2.1,<1.3.0", - "phpunit/php-file-iterator": ">=1.3.1", - "phpunit/php-text-template": ">=1.1.1", - "phpunit/php-timer": ">=1.0.2,<1.1.0", - "phpunit/phpunit-mock-objects": ">=1.2.0,<1.3.0", - "symfony/yaml": ">=2.2.0" - }, - "require-dev": { - "pear-pear/pear": "1.9.4" - }, - "suggest": { - "ext-json": "*", - "ext-simplexml": "*", - "ext-tokenizer": "*", - "phpunit/php-invoker": ">=1.1.0,<1.2.0" - }, - "bin": [ - "composer/bin/phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.7.x-dev" - } - }, - "autoload": { - "classmap": [ - "PHPUnit/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "", - "../../symfony/yaml/" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "http://www.phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2013-03-11 07:06:05" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "1.2.x-dev", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "d49b5683200b5db9b1c64cb06f52f50d147891c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/d49b5683200b5db9b1c64cb06f52f50d147891c4", - "reference": "d49b5683200b5db9b1c64cb06f52f50d147891c4", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-text-template": ">=1.1.1@stable" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "autoload": { - "classmap": [ - "PHPUnit/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2013-02-05 07:46:41" - }, - { - "name": "symfony/yaml", - "version": "dev-master", - "target-dir": "Symfony/Component/Yaml", - "source": { - "type": "git", - "url": "https://github.com/symfony/Yaml.git", - "reference": "f198ac28048eeceae852419c076123aaee59cd1c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/f198ac28048eeceae852419c076123aaee59cd1c", - "reference": "f198ac28048eeceae852419c076123aaee59cd1c", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Yaml\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "http://symfony.com", - "time": "2013-01-31 21:39:01" - } - ], - "aliases": [ - - ], - "minimum-stability": "dev", - "stability-flags": [ - - ], - "platform": { - "php": ">=5.2.4" - }, - "platform-dev": [ - - ] -} diff --git a/vendor/jdorn/sql-formatter/examples/cli.php b/vendor/jdorn/sql-formatter/examples/cli.php deleted file mode 100644 index 17ee0e1..0000000 --- a/vendor/jdorn/sql-formatter/examples/cli.php +++ /dev/null @@ -1,17 +0,0 @@ -Run this php script from the command line to see CLI syntax highlighting and formatting. It support Unix pipes or command line argument style.

    "; - echo "
    php examples/cli.php \"SELECT * FROM MyTable WHERE (id>5 AND \\`name\\` LIKE \\"testing\\");\"
    "; - echo "
    echo \"SELECT * FROM MyTable WHERE (id>5 AND \\`name\\` LIKE \\"testing\\");\" | php examples/cli.php
    "; -} - -if(isset($argv[1])) { - $sql = $argv[1]; -} -else { - $sql = stream_get_contents(fopen("php://stdin", "r")); -} - -require_once(__DIR__.'/../lib/SqlFormatter.php'); - -echo SqlFormatter::format($sql); diff --git a/vendor/jdorn/sql-formatter/examples/examples.php b/vendor/jdorn/sql-formatter/examples/examples.php deleted file mode 100644 index f54cfb0..0000000 --- a/vendor/jdorn/sql-formatter/examples/examples.php +++ /dev/null @@ -1,270 +0,0 @@ - - - - SqlFormatter Examples - - - -= - DATE_FORMAT((DATE_SUB(NOW(),INTERVAL 1 DAY)),'%Y-%c-%d') AND t_create - < DATE_FORMAT(NOW(), '%Y-%c-%d') ORDER BY d.id LIMIT 2,10) a, - orc_scheme_detail b WHERE a.id = b.id", - - "SELECT * from Table1 LEFT - OUTER JOIN Table2 on Table1.id = Table2.id", - - "SELECT * FROM MyTable WHERE id = 46", - - "SELECT count(*),`Column1` as count,`Testing`, `Testing Three` FROM `Table1` - WHERE Column1 = 'testing' AND ( (`Column2` = `Column3` OR Column4 >= NOW()) ) - GROUP BY Column1 ORDER BY Column3 DESC LIMIT 5,10", - - "select * from `Table`, (SELECT group_concat(column1) as col FROM Table2 GROUP BY category) - Table2, Table3 where Table2.col = (Table3.col2 - `Table`.id)", - - "insert ignore into Table3 (column1, column2) VALUES ('test1','test2'), ('test3','test4');", - - "UPDATE MyTable SET name='sql', category='databases' WHERE id > '65'", - - "delete from MyTable WHERE name LIKE \"test%\"", - - "SELECT * FROM UnmatchedParens WHERE ( A = B)) AND (((Test=1)", - - "-- This is a comment - SELECT - /* This is another comment - On more than one line */ - Id #This is one final comment - as temp, DateCreated as Created FROM MyTable;", -); - -// Example statements for splitting SQL strings into individual queries -$split_statements = array( - "DROP TABLE IF EXISTS MyTable; - CREATE TABLE MyTable ( id int ); - INSERT INTO MyTable (id) - VALUES - (1),(2),(3),(4); - SELECT * FROM MyTable;", - - "SELECT \";\"; SELECT \";\\\"; a;\"; - SELECT \"; - abc\"; - SELECT a,b #comment; - FROM test;", - - " - -- Drop the table first if it exists - DROP TABLE IF EXISTS MyTable; - - -- Create the table - CREATE TABLE MyTable ( id int ); - - -- Insert values - INSERT INTO MyTable (id) - VALUES - (1),(2),(3),(4); - - -- Done", -); - -// Example statements for removing comments -$comment_statements = array( - "-- This is a comment - SELECT - /* This is another comment - On more than one line */ - Id #This is one final comment - as temp, DateCreated as Created FROM MyTable;", -); -?> - - -

    Formatting And Syntax Highlighting

    - -
    - Usage: -
    -    '); ?>
    -    
    -
    - - - - - - - - - - - -
    OriginalFormatted And Highlighted
    -
    -
    - - -

    Formatting Only

    - -
    - Usage: -
    -    '); ?>
    -    
    -
    - - - - - - - - - - - -
    OriginalFormatted
    -
    -
    - - -

    Syntax Highlighting Only

    - -
    - Usage: -
    -    '); ?>
    -    
    -
    - - - - - - - - - - - -
    OriginalHighlighted
    -
    -
    - - -

    Compress Query

    - -
    - Usage: -
    -    '); ?>
    -    
    -
    - - - - - - - - - - - -
    OriginalCompressed
    -
    -
    - - -

    Splitting SQL Strings Into Individual Queries

    - -
    - Usage: -
    -    '); ?>
    -    
    -
    - - - - - - - - - - - -
    OriginalSplit
    -
    -
    "; - foreach ($queries as $query) { - echo "
  • " . SqlFormatter::highlight($query) . "
  • "; - } - echo ""; - ?>
    - - -

    Removing Comments

    - -
    - Usage: -
    -    '); ?>
    -    
    -
    - - - - - - - - - - - -
    OriginalComments Removed
    -
    -
    -
    -
    - - - diff --git a/vendor/jdorn/sql-formatter/lib/SqlFormatter.php b/vendor/jdorn/sql-formatter/lib/SqlFormatter.php deleted file mode 100644 index e569682..0000000 --- a/vendor/jdorn/sql-formatter/lib/SqlFormatter.php +++ /dev/null @@ -1,1080 +0,0 @@ - - * @author Florin Patan - * @copyright 2013 Jeremy Dorn - * @license http://opensource.org/licenses/MIT - * @link http://github.com/jdorn/sql-formatter - * @version 1.2.17 - */ -class SqlFormatter -{ - // Constants for token types - const TOKEN_TYPE_WHITESPACE = 0; - const TOKEN_TYPE_WORD = 1; - const TOKEN_TYPE_QUOTE = 2; - const TOKEN_TYPE_BACKTICK_QUOTE = 3; - const TOKEN_TYPE_RESERVED = 4; - const TOKEN_TYPE_RESERVED_TOPLEVEL = 5; - const TOKEN_TYPE_RESERVED_NEWLINE = 6; - const TOKEN_TYPE_BOUNDARY = 7; - const TOKEN_TYPE_COMMENT = 8; - const TOKEN_TYPE_BLOCK_COMMENT = 9; - const TOKEN_TYPE_NUMBER = 10; - const TOKEN_TYPE_ERROR = 11; - const TOKEN_TYPE_VARIABLE = 12; - - // Constants for different components of a token - const TOKEN_TYPE = 0; - const TOKEN_VALUE = 1; - - // Reserved words (for syntax highlighting) - protected static $reserved = array( - 'ACCESSIBLE', 'ACTION', 'AGAINST', 'AGGREGATE', 'ALGORITHM', 'ALL', 'ALTER', 'ANALYSE', 'ANALYZE', 'AS', 'ASC', - 'AUTOCOMMIT', 'AUTO_INCREMENT', 'BACKUP', 'BEGIN', 'BETWEEN', 'BINLOG', 'BOTH', 'CASCADE', 'CASE', 'CHANGE', 'CHANGED', 'CHARACTER SET', - 'CHARSET', 'CHECK', 'CHECKSUM', 'COLLATE', 'COLLATION', 'COLUMN', 'COLUMNS', 'COMMENT', 'COMMIT', 'COMMITTED', 'COMPRESSED', 'CONCURRENT', - 'CONSTRAINT', 'CONTAINS', 'CONVERT', 'CREATE', 'CROSS', 'CURRENT_TIMESTAMP', 'DATABASE', 'DATABASES', 'DAY', 'DAY_HOUR', 'DAY_MINUTE', - 'DAY_SECOND', 'DEFAULT', 'DEFINER', 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 'DISTINCT', 'DISTINCTROW', 'DIV', - 'DO', 'DUMPFILE', 'DUPLICATE', 'DYNAMIC', 'ELSE', 'ENCLOSED', 'END', 'ENGINE', 'ENGINE_TYPE', 'ENGINES', 'ESCAPE', 'ESCAPED', 'EVENTS', 'EXECUTE', - 'EXISTS', 'EXPLAIN', 'EXTENDED', 'FAST', 'FIELDS', 'FILE', 'FIRST', 'FIXED', 'FLUSH', 'FOR', 'FORCE', 'FOREIGN', 'FULL', 'FULLTEXT', - 'FUNCTION', 'GLOBAL', 'GRANT', 'GRANTS', 'GROUP_CONCAT', 'HEAP', 'HIGH_PRIORITY', 'HOSTS', 'HOUR', 'HOUR_MINUTE', - 'HOUR_SECOND', 'IDENTIFIED', 'IF', 'IFNULL', 'IGNORE', 'IN', 'INDEX', 'INDEXES', 'INFILE', 'INSERT', 'INSERT_ID', 'INSERT_METHOD', 'INTERVAL', - 'INTO', 'INVOKER', 'IS', 'ISOLATION', 'KEY', 'KEYS', 'KILL', 'LAST_INSERT_ID', 'LEADING', 'LEVEL', 'LIKE', 'LINEAR', - 'LINES', 'LOAD', 'LOCAL', 'LOCK', 'LOCKS', 'LOGS', 'LOW_PRIORITY', 'MARIA', 'MASTER', 'MASTER_CONNECT_RETRY', 'MASTER_HOST', 'MASTER_LOG_FILE', - 'MATCH','MAX_CONNECTIONS_PER_HOUR', 'MAX_QUERIES_PER_HOUR', 'MAX_ROWS', 'MAX_UPDATES_PER_HOUR', 'MAX_USER_CONNECTIONS', - 'MEDIUM', 'MERGE', 'MINUTE', 'MINUTE_SECOND', 'MIN_ROWS', 'MODE', 'MODIFY', - 'MONTH', 'MRG_MYISAM', 'MYISAM', 'NAMES', 'NATURAL', 'NOT', 'NOW()','NULL', 'OFFSET', 'ON', 'OPEN', 'OPTIMIZE', 'OPTION', 'OPTIONALLY', - 'ON UPDATE', 'ON DELETE', 'OUTFILE', 'PACK_KEYS', 'PAGE', 'PARTIAL', 'PARTITION', 'PARTITIONS', 'PASSWORD', 'PRIMARY', 'PRIVILEGES', 'PROCEDURE', - 'PROCESS', 'PROCESSLIST', 'PURGE', 'QUICK', 'RANGE', 'RAID0', 'RAID_CHUNKS', 'RAID_CHUNKSIZE','RAID_TYPE', 'READ', 'READ_ONLY', - 'READ_WRITE', 'REFERENCES', 'REGEXP', 'RELOAD', 'RENAME', 'REPAIR', 'REPEATABLE', 'REPLACE', 'REPLICATION', 'RESET', 'RESTORE', 'RESTRICT', - 'RETURN', 'RETURNS', 'REVOKE', 'RLIKE', 'ROLLBACK', 'ROW', 'ROWS', 'ROW_FORMAT', 'SECOND', 'SECURITY', 'SEPARATOR', - 'SERIALIZABLE', 'SESSION', 'SHARE', 'SHOW', 'SHUTDOWN', 'SLAVE', 'SONAME', 'SOUNDS', 'SQL', 'SQL_AUTO_IS_NULL', 'SQL_BIG_RESULT', - 'SQL_BIG_SELECTS', 'SQL_BIG_TABLES', 'SQL_BUFFER_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_LOG_BIN', 'SQL_LOG_OFF', 'SQL_LOG_UPDATE', - 'SQL_LOW_PRIORITY_UPDATES', 'SQL_MAX_JOIN_SIZE', 'SQL_QUOTE_SHOW_CREATE', 'SQL_SAFE_UPDATES', 'SQL_SELECT_LIMIT', 'SQL_SLAVE_SKIP_COUNTER', - 'SQL_SMALL_RESULT', 'SQL_WARNINGS', 'SQL_CACHE', 'SQL_NO_CACHE', 'START', 'STARTING', 'STATUS', 'STOP', 'STORAGE', - 'STRAIGHT_JOIN', 'STRING', 'STRIPED', 'SUPER', 'TABLE', 'TABLES', 'TEMPORARY', 'TERMINATED', 'THEN', 'TO', 'TRAILING', 'TRANSACTIONAL', 'TRUE', - 'TRUNCATE', 'TYPE', 'TYPES', 'UNCOMMITTED', 'UNIQUE', 'UNLOCK', 'UNSIGNED', 'USAGE', 'USE', 'USING', 'VARIABLES', - 'VIEW', 'WHEN', 'WITH', 'WORK', 'WRITE', 'YEAR_MONTH' - ); - - // For SQL formatting - // These keywords will all be on their own line - protected static $reserved_toplevel = array( - 'SELECT', 'FROM', 'WHERE', 'SET', 'ORDER BY', 'GROUP BY', 'LIMIT', 'DROP', - 'VALUES', 'UPDATE', 'HAVING', 'ADD', 'AFTER', 'ALTER TABLE', 'DELETE FROM', 'UNION ALL', 'UNION', 'EXCEPT', 'INTERSECT' - ); - - protected static $reserved_newline = array( - 'LEFT OUTER JOIN', 'RIGHT OUTER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'OUTER JOIN', 'INNER JOIN', 'JOIN', 'XOR', 'OR', 'AND' - ); - - protected static $functions = array ( - 'ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_DECRYPT', 'AES_ENCRYPT', 'AREA', 'ASBINARY', 'ASCII', 'ASIN', 'ASTEXT', 'ATAN', 'ATAN2', - 'AVG', 'BDMPOLYFROMTEXT', 'BDMPOLYFROMWKB', 'BDPOLYFROMTEXT', 'BDPOLYFROMWKB', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_COUNT', 'BIT_LENGTH', - 'BIT_OR', 'BIT_XOR', 'BOUNDARY', 'BUFFER', 'CAST', 'CEIL', 'CEILING', 'CENTROID', 'CHAR', 'CHARACTER_LENGTH', 'CHARSET', 'CHAR_LENGTH', - 'COALESCE', 'COERCIBILITY', 'COLLATION', 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONNECTION_ID', 'CONTAINS', 'CONV', 'CONVERT', 'CONVERT_TZ', - 'CONVEXHULL', 'COS', 'COT', 'COUNT', 'CRC32', 'CROSSES', 'CURDATE', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER', - 'CURTIME', 'DATABASE', 'DATE', 'DATEDIFF', 'DATE_ADD', 'DATE_DIFF', 'DATE_FORMAT', 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', - 'DAYOFYEAR', 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 'DIFFERENCE', 'DIMENSION', 'DISJOINT', 'DISTANCE', 'ELT', 'ENCODE', - 'ENCRYPT', 'ENDPOINT', 'ENVELOPE', 'EQUALS', 'EXP', 'EXPORT_SET', 'EXTERIORRING', 'EXTRACT', 'EXTRACTVALUE', 'FIELD', 'FIND_IN_SET', 'FLOOR', - 'FORMAT', 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', 'GEOMCOLLFROMTEXT', 'GEOMCOLLFROMWKB', 'GEOMETRYCOLLECTION', 'GEOMETRYCOLLECTIONFROMTEXT', - 'GEOMETRYCOLLECTIONFROMWKB', 'GEOMETRYFROMTEXT', 'GEOMETRYFROMWKB', 'GEOMETRYN', 'GEOMETRYTYPE', 'GEOMFROMTEXT', 'GEOMFROMWKB', 'GET_FORMAT', - 'GET_LOCK', 'GLENGTH', 'GREATEST', 'GROUP_CONCAT', 'GROUP_UNIQUE_USERS', 'HEX', 'HOUR', 'IF', 'IFNULL', 'INET_ATON', 'INET_NTOA', 'INSERT', 'INSTR', - 'INTERIORRINGN', 'INTERSECTION', 'INTERSECTS', 'INTERVAL', 'ISCLOSED', 'ISEMPTY', 'ISNULL', 'ISRING', 'ISSIMPLE', 'IS_FREE_LOCK', 'IS_USED_LOCK', - 'LAST_DAY', 'LAST_INSERT_ID', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 'LINEFROMTEXT', 'LINEFROMWKB', 'LINESTRING', 'LINESTRINGFROMTEXT', 'LINESTRINGFROMWKB', - 'LN', 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATE', 'LOG', 'LOG10', 'LOG2', 'LOWER', 'LPAD', 'LTRIM', 'MAKEDATE', 'MAKETIME', 'MAKE_SET', - 'MASTER_POS_WAIT', 'MAX', 'MBRCONTAINS', 'MBRDISJOINT', 'MBREQUAL', 'MBRINTERSECTS', 'MBROVERLAPS', 'MBRTOUCHES', 'MBRWITHIN', 'MD5', 'MICROSECOND', - 'MID', 'MIN', 'MINUTE', 'MLINEFROMTEXT', 'MLINEFROMWKB', 'MOD', 'MONTH', 'MONTHNAME', 'MPOINTFROMTEXT', 'MPOINTFROMWKB', 'MPOLYFROMTEXT', 'MPOLYFROMWKB', - 'MULTILINESTRING', 'MULTILINESTRINGFROMTEXT', 'MULTILINESTRINGFROMWKB', 'MULTIPOINT', 'MULTIPOINTFROMTEXT', 'MULTIPOINTFROMWKB', 'MULTIPOLYGON', - 'MULTIPOLYGONFROMTEXT', 'MULTIPOLYGONFROMWKB', 'NAME_CONST', 'NULLIF', 'NUMGEOMETRIES', 'NUMINTERIORRINGS', 'NUMPOINTS', 'OCT', 'OCTET_LENGTH', - 'OLD_PASSWORD', 'ORD', 'OVERLAPS', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', 'PI', 'POINT', 'POINTFROMTEXT', 'POINTFROMWKB', 'POINTN', 'POINTONSURFACE', - 'POLYFROMTEXT', 'POLYFROMWKB', 'POLYGON', 'POLYGONFROMTEXT', 'POLYGONFROMWKB', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RAND', - 'RELATED', 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'ROW_COUNT', 'RPAD', 'RTRIM', 'SCHEMA', 'SECOND', 'SEC_TO_TIME', - 'SESSION_USER', 'SHA', 'SHA1', 'SIGN', 'SIN', 'SLEEP', 'SOUNDEX', 'SPACE', 'SQRT', 'SRID', 'STARTPOINT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', - 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTR', 'SUBSTRING', 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'SYMDIFFERENCE', 'SYSDATE', 'SYSTEM_USER', 'TAN', - 'TIME', 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TOUCHES', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', - 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UNIQUE_USERS', 'UNIX_TIMESTAMP', 'UPDATEXML', 'UPPER', 'USER', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', - 'UUID', 'VARIANCE', 'VAR_POP', 'VAR_SAMP', 'VERSION', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'WITHIN', 'X', 'Y', 'YEAR', 'YEARWEEK' - ); - - // Punctuation that can be used as a boundary between other tokens - protected static $boundaries = array(',', ';',':', ')', '(', '.', '=', '<', '>', '+', '-', '*', '/', '!', '^', '%', '|', '&', '#'); - - // For HTML syntax highlighting - // Styles applied to different token types - public static $quote_attributes = 'style="color: blue;"'; - public static $backtick_quote_attributes = 'style="color: purple;"'; - public static $reserved_attributes = 'style="font-weight:bold;"'; - public static $boundary_attributes = ''; - public static $number_attributes = 'style="color: green;"'; - public static $word_attributes = 'style="color: #333;"'; - public static $error_attributes = 'style="background-color: red;"'; - public static $comment_attributes = 'style="color: #aaa;"'; - public static $variable_attributes = 'style="color: orange;"'; - public static $pre_attributes = 'style="color: black; background-color: white;"'; - - // Boolean - whether or not the current environment is the CLI - // This affects the type of syntax highlighting - // If not defined, it will be determined automatically - public static $cli; - - // For CLI syntax highlighting - public static $cli_quote = "\x1b[34;1m"; - public static $cli_backtick_quote = "\x1b[35;1m"; - public static $cli_reserved = "\x1b[37m"; - public static $cli_boundary = ""; - public static $cli_number = "\x1b[32;1m"; - public static $cli_word = ""; - public static $cli_error = "\x1b[31;1;7m"; - public static $cli_comment = "\x1b[30;1m"; - public static $cli_functions = "\x1b[37m"; - public static $cli_variable = "\x1b[36;1m"; - - // The tab character to use when formatting SQL - public static $tab = ' '; - - // This flag tells us if queries need to be enclosed in
     tags
    -    public static $use_pre = true;
    -
    -    // This flag tells us if SqlFormatted has been initialized
    -    protected static $init;
    -
    -    // Regular expressions for tokenizing
    -    protected static $regex_boundaries;
    -    protected static $regex_reserved;
    -    protected static $regex_reserved_newline;
    -    protected static $regex_reserved_toplevel;
    -    protected static $regex_function;
    -
    -    // Cache variables
    -    // Only tokens shorter than this size will be cached.  Somewhere between 10 and 20 seems to work well for most cases.
    -    public static $max_cachekey_size = 15;
    -    protected static $token_cache = array();
    -    protected static $cache_hits = 0;
    -    protected static $cache_misses = 0;
    -
    -    /**
    -     * Get stats about the token cache
    -     * @return Array An array containing the keys 'hits', 'misses', 'entries', and 'size' in bytes
    -     */
    -    public static function getCacheStats()
    -    {
    -        return array(
    -            'hits'=>self::$cache_hits,
    -            'misses'=>self::$cache_misses,
    -            'entries'=>count(self::$token_cache),
    -            'size'=>strlen(serialize(self::$token_cache))
    -        );
    -    }
    -
    -    /**
    -     * Stuff that only needs to be done once.  Builds regular expressions and sorts the reserved words.
    -     */
    -    protected static function init()
    -    {
    -        if (self::$init) return;
    -
    -        // Sort reserved word list from longest word to shortest, 3x faster than usort
    -        $reservedMap = array_combine(self::$reserved, array_map('strlen', self::$reserved));
    -        arsort($reservedMap);
    -        self::$reserved = array_keys($reservedMap);
    -
    -        // Set up regular expressions
    -        self::$regex_boundaries = '('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$boundaries)).')';
    -        self::$regex_reserved = '('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$reserved)).')';
    -        self::$regex_reserved_toplevel = str_replace(' ','\\s+','('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$reserved_toplevel)).')');
    -        self::$regex_reserved_newline = str_replace(' ','\\s+','('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$reserved_newline)).')');
    -
    -        self::$regex_function = '('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$functions)).')';
    -
    -        self::$init = true;
    -    }
    -
    -    /**
    -     * Return the next token and token type in a SQL string.
    -     * Quoted strings, comments, reserved words, whitespace, and punctuation are all their own tokens.
    -     *
    -     * @param String $string   The SQL string
    -     * @param array  $previous The result of the previous getNextToken() call
    -     *
    -     * @return Array An associative array containing the type and value of the token.
    -     */
    -    protected static function getNextToken($string, $previous = null)
    -    {
    -        // Whitespace
    -        if (preg_match('/^\s+/',$string,$matches)) {
    -            return array(
    -                self::TOKEN_VALUE => $matches[0],
    -                self::TOKEN_TYPE=>self::TOKEN_TYPE_WHITESPACE
    -            );
    -        }
    -
    -        // Comment
    -        if ($string[0] === '#' || (isset($string[1])&&($string[0]==='-'&&$string[1]==='-') || ($string[0]==='/'&&$string[1]==='*'))) {
    -            // Comment until end of line
    -            if ($string[0] === '-' || $string[0] === '#') {
    -                $last = strpos($string, "\n");
    -                $type = self::TOKEN_TYPE_COMMENT;
    -            } else { // Comment until closing comment tag
    -                $last = strpos($string, "*/", 2) + 2;
    -                $type = self::TOKEN_TYPE_BLOCK_COMMENT;
    -            }
    -
    -            if ($last === false) {
    -                $last = strlen($string);
    -            }
    -
    -            return array(
    -                self::TOKEN_VALUE => substr($string, 0, $last),
    -                self::TOKEN_TYPE  => $type
    -            );
    -        }
    -
    -        // Quoted String
    -        if ($string[0]==='"' || $string[0]==='\'' || $string[0]==='`') {
    -            $return = array(
    -                self::TOKEN_TYPE => ($string[0]==='`'? self::TOKEN_TYPE_BACKTICK_QUOTE : self::TOKEN_TYPE_QUOTE),
    -                self::TOKEN_VALUE => self::getQuotedString($string)
    -            );
    -
    -            return $return;
    -        }
    -
    -        // User-defined Variable
    -        if ($string[0] === '@' && isset($string[1])) {
    -            $ret = array(
    -                self::TOKEN_VALUE => null,
    -                self::TOKEN_TYPE => self::TOKEN_TYPE_VARIABLE
    -            );
    -            
    -            // If the variable name is quoted
    -            if ($string[1]==='"' || $string[1]==='\'' || $string[1]==='`') {
    -                $ret[self::TOKEN_VALUE] = '@'.self::getQuotedString(substr($string,1));
    -            }
    -            // Non-quoted variable name
    -            else {
    -                preg_match('/^(@[a-zA-Z0-9\._\$]+)/',$string,$matches);
    -                if ($matches) {
    -                    $ret[self::TOKEN_VALUE] = $matches[1];
    -                }
    -            }
    -            
    -            if($ret[self::TOKEN_VALUE] !== null) return $ret;
    -        }
    -
    -        // Number (decimal, binary, or hex)
    -        if (preg_match('/^([0-9]+(\.[0-9]+)?|0x[0-9a-fA-F]+|0b[01]+)($|\s|"\'`|'.self::$regex_boundaries.')/',$string,$matches)) {
    -            return array(
    -                self::TOKEN_VALUE => $matches[1],
    -                self::TOKEN_TYPE=>self::TOKEN_TYPE_NUMBER
    -            );
    -        }
    -
    -        // Boundary Character (punctuation and symbols)
    -        if (preg_match('/^('.self::$regex_boundaries.')/',$string,$matches)) {
    -            return array(
    -                self::TOKEN_VALUE => $matches[1],
    -                self::TOKEN_TYPE  => self::TOKEN_TYPE_BOUNDARY
    -            );
    -        }
    -
    -        // A reserved word cannot be preceded by a '.'
    -        // this makes it so in "mytable.from", "from" is not considered a reserved word
    -        if (!$previous || !isset($previous[self::TOKEN_VALUE]) || $previous[self::TOKEN_VALUE] !== '.') {
    -            $upper = strtoupper($string);
    -            // Top Level Reserved Word
    -            if (preg_match('/^('.self::$regex_reserved_toplevel.')($|\s|'.self::$regex_boundaries.')/', $upper,$matches)) {
    -                return array(
    -                    self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED_TOPLEVEL,
    -                    self::TOKEN_VALUE=>substr($string,0,strlen($matches[1]))
    -                );
    -            }
    -            // Newline Reserved Word
    -            if (preg_match('/^('.self::$regex_reserved_newline.')($|\s|'.self::$regex_boundaries.')/', $upper,$matches)) {
    -                return array(
    -                    self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED_NEWLINE,
    -                    self::TOKEN_VALUE=>substr($string,0,strlen($matches[1]))
    -                );
    -            }
    -            // Other Reserved Word
    -            if (preg_match('/^('.self::$regex_reserved.')($|\s|'.self::$regex_boundaries.')/', $upper,$matches)) {
    -                return array(
    -                    self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED,
    -                    self::TOKEN_VALUE=>substr($string,0,strlen($matches[1]))
    -                );
    -            }
    -        }
    -
    -        // A function must be suceeded by '('
    -        // this makes it so "count(" is considered a function, but "count" alone is not
    -        $upper = strtoupper($string);
    -        // function
    -        if (preg_match('/^('.self::$regex_function.'[(]|\s|[)])/', $upper,$matches)) {
    -            return array(
    -                self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED,
    -                self::TOKEN_VALUE=>substr($string,0,strlen($matches[1])-1)
    -            );
    -        }
    -
    -        // Non reserved word
    -        preg_match('/^(.*?)($|\s|["\'`]|'.self::$regex_boundaries.')/',$string,$matches);
    -
    -        return array(
    -            self::TOKEN_VALUE => $matches[1],
    -            self::TOKEN_TYPE  => self::TOKEN_TYPE_WORD
    -        );
    -    }
    -
    -    protected static function getQuotedString($string)
    -    {
    -        $ret = null;
    -        
    -        // This checks for the following patterns:
    -        // 1. backtick quoted string using `` to escape
    -        // 2. double quoted string using "" or \" to escape
    -        // 3. single quoted string using '' or \' to escape
    -        if ( preg_match('/^(((`[^`]*($|`))+)|(("[^"\\\\]*(?:\\\\.[^"\\\\]*)*("|$))+)|((\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*(\'|$))+))/s', $string, $matches)) {
    -            $ret = $matches[1];
    -        }
    -        
    -        return $ret;
    -    }
    -
    -    /**
    -     * Takes a SQL string and breaks it into tokens.
    -     * Each token is an associative array with type and value.
    -     *
    -     * @param String $string The SQL string
    -     *
    -     * @return Array An array of tokens.
    -     */
    -    protected static function tokenize($string)
    -    {
    -        self::init();
    -
    -        $tokens = array();
    -
    -        // Used for debugging if there is an error while tokenizing the string
    -        $original_length = strlen($string);
    -
    -        // Used to make sure the string keeps shrinking on each iteration
    -        $old_string_len = strlen($string) + 1;
    -
    -        $token = null;
    -
    -        $current_length = strlen($string);
    -
    -        // Keep processing the string until it is empty
    -        while ($current_length) {
    -            // If the string stopped shrinking, there was a problem
    -            if ($old_string_len <= $current_length) {
    -                $tokens[] = array(
    -                    self::TOKEN_VALUE=>$string,
    -                    self::TOKEN_TYPE=>self::TOKEN_TYPE_ERROR
    -                );
    -
    -                return $tokens;
    -            }
    -            $old_string_len =  $current_length;
    -
    -            // Determine if we can use caching
    -            if ($current_length >= self::$max_cachekey_size) {
    -                $cacheKey = substr($string,0,self::$max_cachekey_size);
    -            } else {
    -                $cacheKey = false;
    -            }
    -
    -            // See if the token is already cached
    -            if ($cacheKey && isset(self::$token_cache[$cacheKey])) {
    -                // Retrieve from cache
    -                $token = self::$token_cache[$cacheKey];
    -                $token_length = strlen($token[self::TOKEN_VALUE]);
    -                self::$cache_hits++;
    -            } else {
    -                // Get the next token and the token type
    -                $token = self::getNextToken($string, $token);
    -                $token_length = strlen($token[self::TOKEN_VALUE]);
    -                self::$cache_misses++;
    -
    -                // If the token is shorter than the max length, store it in cache
    -                if ($cacheKey && $token_length < self::$max_cachekey_size) {
    -                    self::$token_cache[$cacheKey] = $token;
    -                }
    -            }
    -
    -            $tokens[] = $token;
    -
    -            // Advance the string
    -            $string = substr($string, $token_length);
    -
    -            $current_length -= $token_length;
    -        }
    -
    -        return $tokens;
    -    }
    -
    -    /**
    -     * Format the whitespace in a SQL string to make it easier to read.
    -     *
    -     * @param String  $string    The SQL string
    -     * @param boolean $highlight If true, syntax highlighting will also be performed
    -     *
    -     * @return String The SQL string with HTML styles and formatting wrapped in a 
     tag
    -     */
    -    public static function format($string, $highlight=true)
    -    {
    -        // This variable will be populated with formatted html
    -        $return = '';
    -
    -        // Use an actual tab while formatting and then switch out with self::$tab at the end
    -        $tab = "\t";
    -
    -        $indent_level = 0;
    -        $newline = false;
    -        $inline_parentheses = false;
    -        $increase_special_indent = false;
    -        $increase_block_indent = false;
    -        $indent_types = array();
    -        $added_newline = false;
    -        $inline_count = 0;
    -        $inline_indented = false;
    -        $clause_limit = false;
    -
    -        // Tokenize String
    -        $original_tokens = self::tokenize($string);
    -
    -        // Remove existing whitespace
    -        $tokens = array();
    -        foreach ($original_tokens as $i=>$token) {
    -            if ($token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) {
    -                $token['i'] = $i;
    -                $tokens[] = $token;
    -            }
    -        }
    -
    -        // Format token by token
    -        foreach ($tokens as $i=>$token) {
    -            // Get highlighted token if doing syntax highlighting
    -            if ($highlight) {
    -                $highlighted = self::highlightToken($token);
    -            } else { // If returning raw text
    -                $highlighted = $token[self::TOKEN_VALUE];
    -            }
    -
    -            // If we are increasing the special indent level now
    -            if ($increase_special_indent) {
    -                $indent_level++;
    -                $increase_special_indent = false;
    -                array_unshift($indent_types,'special');
    -            }
    -            // If we are increasing the block indent level now
    -            if ($increase_block_indent) {
    -                $indent_level++;
    -                $increase_block_indent = false;
    -                array_unshift($indent_types,'block');
    -            }
    -
    -            // If we need a new line before the token
    -            if ($newline) {
    -                $return .= "\n" . str_repeat($tab, $indent_level);
    -                $newline = false;
    -                $added_newline = true;
    -            } else {
    -                $added_newline = false;
    -            }
    -
    -            // Display comments directly where they appear in the source
    -            if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_COMMENT || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) {
    -                if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) {
    -                    $indent = str_repeat($tab,$indent_level);
    -                    $return .= "\n" . $indent;
    -                    $highlighted = str_replace("\n","\n".$indent,$highlighted);
    -                }
    -
    -                $return .= $highlighted;
    -                $newline = true;
    -                continue;
    -            }
    -
    -            if ($inline_parentheses) {
    -                // End of inline parentheses
    -                if ($token[self::TOKEN_VALUE] === ')') {
    -                    $return = rtrim($return,' ');
    -
    -                    if ($inline_indented) {
    -                        array_shift($indent_types);
    -                        $indent_level --;
    -                        $return .= "\n" . str_repeat($tab, $indent_level);
    -                    }
    -
    -                    $inline_parentheses = false;
    -
    -                    $return .= $highlighted . ' ';
    -                    continue;
    -                }
    -
    -                if ($token[self::TOKEN_VALUE] === ',') {
    -                    if ($inline_count >= 30) {
    -                        $inline_count = 0;
    -                        $newline = true;
    -                    }
    -                }
    -
    -                $inline_count += strlen($token[self::TOKEN_VALUE]);
    -            }
    -
    -            // Opening parentheses increase the block indent level and start a new line
    -            if ($token[self::TOKEN_VALUE] === '(') {
    -                // First check if this should be an inline parentheses block
    -                // Examples are "NOW()", "COUNT(*)", "int(10)", key(`somecolumn`), DECIMAL(7,2)
    -                // Allow up to 3 non-whitespace tokens inside inline parentheses
    -                $length = 0;
    -                for ($j=1;$j<=250;$j++) {
    -                    // Reached end of string
    -                    if (!isset($tokens[$i+$j])) break;
    -
    -                    $next = $tokens[$i+$j];
    -
    -                    // Reached closing parentheses, able to inline it
    -                    if ($next[self::TOKEN_VALUE] === ')') {
    -                        $inline_parentheses = true;
    -                        $inline_count = 0;
    -                        $inline_indented = false;
    -                        break;
    -                    }
    -
    -                    // Reached an invalid token for inline parentheses
    -                    if ($next[self::TOKEN_VALUE]===';' || $next[self::TOKEN_VALUE]==='(') {
    -                        break;
    -                    }
    -
    -                    // Reached an invalid token type for inline parentheses
    -                    if ($next[self::TOKEN_TYPE]===self::TOKEN_TYPE_RESERVED_TOPLEVEL || $next[self::TOKEN_TYPE]===self::TOKEN_TYPE_RESERVED_NEWLINE || $next[self::TOKEN_TYPE]===self::TOKEN_TYPE_COMMENT || $next[self::TOKEN_TYPE]===self::TOKEN_TYPE_BLOCK_COMMENT) {
    -                        break;
    -                    }
    -
    -                    $length += strlen($next[self::TOKEN_VALUE]);
    -                }
    -
    -                if ($inline_parentheses && $length > 30) {
    -                    $increase_block_indent = true;
    -                    $inline_indented = true;
    -                    $newline = true;
    -                }
    -
    -                // Take out the preceding space unless there was whitespace there in the original query
    -                if (isset($original_tokens[$token['i']-1]) && $original_tokens[$token['i']-1][self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) {
    -                    $return = rtrim($return,' ');
    -                }
    -
    -                if (!$inline_parentheses) {
    -                    $increase_block_indent = true;
    -                    // Add a newline after the parentheses
    -                    $newline = true;
    -                }
    -
    -            }
    -
    -            // Closing parentheses decrease the block indent level
    -            elseif ($token[self::TOKEN_VALUE] === ')') {
    -                // Remove whitespace before the closing parentheses
    -                $return = rtrim($return,' ');
    -
    -                $indent_level--;
    -
    -                // Reset indent level
    -                while ($j=array_shift($indent_types)) {
    -                    if ($j==='special') {
    -                        $indent_level--;
    -                    } else {
    -                        break;
    -                    }
    -                }
    -
    -                if ($indent_level < 0) {
    -                    // This is an error
    -                    $indent_level = 0;
    -
    -                    if ($highlight) {
    -                        $return .= "\n".self::highlightError($token[self::TOKEN_VALUE]);
    -                        continue;
    -                    }
    -                }
    -
    -                // Add a newline before the closing parentheses (if not already added)
    -                if (!$added_newline) {
    -                    $return .= "\n" . str_repeat($tab, $indent_level);
    -                }
    -            }
    -
    -            // Top level reserved words start a new line and increase the special indent level
    -            elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_TOPLEVEL) {
    -                $increase_special_indent = true;
    -
    -                // If the last indent type was 'special', decrease the special indent for this round
    -                reset($indent_types);
    -                if (current($indent_types)==='special') {
    -                    $indent_level--;
    -                    array_shift($indent_types);
    -                }
    -
    -                // Add a newline after the top level reserved word
    -                $newline = true;
    -                // Add a newline before the top level reserved word (if not already added)
    -                if (!$added_newline) {
    -                    $return .= "\n" . str_repeat($tab, $indent_level);
    -                }
    -                // If we already added a newline, redo the indentation since it may be different now
    -                else {
    -                    $return = rtrim($return,$tab).str_repeat($tab, $indent_level);
    -                }
    -
    -                // If the token may have extra whitespace
    -                if (strpos($token[self::TOKEN_VALUE],' ')!==false || strpos($token[self::TOKEN_VALUE],"\n")!==false || strpos($token[self::TOKEN_VALUE],"\t")!==false) {
    -                    $highlighted = preg_replace('/\s+/',' ',$highlighted);
    -                }
    -                //if SQL 'LIMIT' clause, start variable to reset newline
    -                if ($token[self::TOKEN_VALUE] === 'LIMIT' && !$inline_parentheses) {
    -                    $clause_limit = true;
    -                }
    -            }
    -
    -            // Checks if we are out of the limit clause
    -            elseif ($clause_limit && $token[self::TOKEN_VALUE] !== "," && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_NUMBER && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) {
    -                $clause_limit = false;
    -            }
    -
    -            // Commas start a new line (unless within inline parentheses or SQL 'LIMIT' clause)
    -            elseif ($token[self::TOKEN_VALUE] === ',' && !$inline_parentheses) {
    -                //If the previous TOKEN_VALUE is 'LIMIT', resets new line
    -                if ($clause_limit === true) {
    -                    $newline = false;
    -                    $clause_limit = false;
    -                }
    -                // All other cases of commas
    -                else {
    -                    $newline = true;
    -                }
    -            }
    -
    -            // Newline reserved words start a new line
    -            elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_NEWLINE) {
    -                // Add a newline before the reserved word (if not already added)
    -                if (!$added_newline) {
    -                    $return .= "\n" . str_repeat($tab, $indent_level);
    -                }
    -
    -                // If the token may have extra whitespace
    -                if (strpos($token[self::TOKEN_VALUE],' ')!==false || strpos($token[self::TOKEN_VALUE],"\n")!==false || strpos($token[self::TOKEN_VALUE],"\t")!==false) {
    -                    $highlighted = preg_replace('/\s+/',' ',$highlighted);
    -                }
    -            }
    -
    -            // Multiple boundary characters in a row should not have spaces between them (not including parentheses)
    -            elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BOUNDARY) {
    -                if (isset($tokens[$i-1]) && $tokens[$i-1][self::TOKEN_TYPE] === self::TOKEN_TYPE_BOUNDARY) {
    -                    if (isset($original_tokens[$token['i']-1]) && $original_tokens[$token['i']-1][self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) {
    -                        $return = rtrim($return,' ');
    -                    }
    -                }
    -            }
    -
    -            // If the token shouldn't have a space before it
    -            if ($token[self::TOKEN_VALUE] === '.' || $token[self::TOKEN_VALUE] === ',' || $token[self::TOKEN_VALUE] === ';') {
    -                $return = rtrim($return, ' ');
    -            }
    -
    -            $return .= $highlighted.' ';
    -
    -            // If the token shouldn't have a space after it
    -            if ($token[self::TOKEN_VALUE] === '(' || $token[self::TOKEN_VALUE] === '.') {
    -                $return = rtrim($return,' ');
    -            }
    -            
    -            // If this is the "-" of a negative number, it shouldn't have a space after it
    -            if($token[self::TOKEN_VALUE] === '-' && isset($tokens[$i+1]) && $tokens[$i+1][self::TOKEN_TYPE] === self::TOKEN_TYPE_NUMBER && isset($tokens[$i-1])) {
    -                $prev = $tokens[$i-1][self::TOKEN_TYPE];
    -                if($prev !== self::TOKEN_TYPE_QUOTE && $prev !== self::TOKEN_TYPE_BACKTICK_QUOTE && $prev !== self::TOKEN_TYPE_WORD && $prev !== self::TOKEN_TYPE_NUMBER) {
    -                    $return = rtrim($return,' ');
    -                }
    -            } 
    -        }
    -
    -        // If there are unmatched parentheses
    -        if ($highlight && array_search('block',$indent_types) !== false) {
    -            $return .= "\n".self::highlightError("WARNING: unclosed parentheses or section");
    -        }
    -
    -        // Replace tab characters with the configuration tab character
    -        $return = trim(str_replace("\t",self::$tab,$return));
    -
    -        if ($highlight) {
    -            $return = self::output($return);
    -        }
    -
    -        return $return;
    -    }
    -
    -    /**
    -     * Add syntax highlighting to a SQL string
    -     *
    -     * @param String $string The SQL string
    -     *
    -     * @return String The SQL string with HTML styles applied
    -     */
    -    public static function highlight($string)
    -    {
    -        $tokens = self::tokenize($string);
    -
    -        $return = '';
    -
    -        foreach ($tokens as $token) {
    -            $return .= self::highlightToken($token);
    -        }
    -
    -        return self::output($return);
    -    }
    -
    -    /**
    -     * Split a SQL string into multiple queries.
    -     * Uses ";" as a query delimiter.
    -     *
    -     * @param String $string The SQL string
    -     *
    -     * @return Array An array of individual query strings without trailing semicolons
    -     */
    -    public static function splitQuery($string)
    -    {
    -        $queries = array();
    -        $current_query = '';
    -        $empty = true;
    -
    -        $tokens = self::tokenize($string);
    -
    -        foreach ($tokens as $token) {
    -            // If this is a query separator
    -            if ($token[self::TOKEN_VALUE] === ';') {
    -                if (!$empty) {
    -                    $queries[] = $current_query.';';
    -                }
    -                $current_query = '';
    -                $empty = true;
    -                continue;
    -            }
    -
    -            // If this is a non-empty character
    -            if ($token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_COMMENT && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_BLOCK_COMMENT) {
    -                $empty = false;
    -            }
    -
    -            $current_query .= $token[self::TOKEN_VALUE];
    -        }
    -
    -        if (!$empty) {
    -            $queries[] = trim($current_query);
    -        }
    -
    -        return $queries;
    -    }
    -
    -    /**
    -     * Remove all comments from a SQL string
    -     *
    -     * @param String $string The SQL string
    -     *
    -     * @return String The SQL string without comments
    -     */
    -    public static function removeComments($string)
    -    {
    -        $result = '';
    -
    -        $tokens = self::tokenize($string);
    -
    -        foreach ($tokens as $token) {
    -            // Skip comment tokens
    -            if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_COMMENT || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) {
    -                continue;
    -            }
    -
    -            $result .= $token[self::TOKEN_VALUE];
    -        }
    -        $result = self::format( $result,false);
    -
    -        return $result;
    -    }
    -
    -    /**
    -     * Compress a query by collapsing white space and removing comments
    -     *
    -     * @param String $string The SQL string
    -     *
    -     * @return String The SQL string without comments
    -     */
    -    public static function compress($string)
    -    {
    -        $result = '';
    -
    -        $tokens = self::tokenize($string);
    -
    -        $whitespace = true;
    -        foreach ($tokens as $token) {
    -            // Skip comment tokens
    -            if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_COMMENT || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) {
    -                continue;
    -            }
    -            // Remove extra whitespace in reserved words (e.g "OUTER     JOIN" becomes "OUTER JOIN")
    -            elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_NEWLINE || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_TOPLEVEL) {
    -                $token[self::TOKEN_VALUE] = preg_replace('/\s+/',' ',$token[self::TOKEN_VALUE]);
    -            }
    -
    -            if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_WHITESPACE) {
    -                // If the last token was whitespace, don't add another one
    -                if ($whitespace) {
    -                    continue;
    -                } else {
    -                    $whitespace = true;
    -                    // Convert all whitespace to a single space
    -                    $token[self::TOKEN_VALUE] = ' ';
    -                }
    -            } else {
    -                $whitespace = false;
    -            }
    -
    -            $result .= $token[self::TOKEN_VALUE];
    -        }
    -
    -        return rtrim($result);
    -    }
    -
    -    /**
    -     * Highlights a token depending on its type.
    -     *
    -     * @param Array $token An associative array containing type and value.
    -     *
    -     * @return String HTML code of the highlighted token.
    -     */
    -    protected static function highlightToken($token)
    -    {
    -        $type = $token[self::TOKEN_TYPE];
    -
    -        if (self::is_cli()) {
    -            $token = $token[self::TOKEN_VALUE];
    -        } else {
    -            $token = htmlentities($token[self::TOKEN_VALUE],ENT_COMPAT,'UTF-8');
    -        }
    -
    -        if ($type===self::TOKEN_TYPE_BOUNDARY) {
    -            return self::highlightBoundary($token);
    -        } elseif ($type===self::TOKEN_TYPE_WORD) {
    -            return self::highlightWord($token);
    -        } elseif ($type===self::TOKEN_TYPE_BACKTICK_QUOTE) {
    -            return self::highlightBacktickQuote($token);
    -        } elseif ($type===self::TOKEN_TYPE_QUOTE) {
    -            return self::highlightQuote($token);
    -        } elseif ($type===self::TOKEN_TYPE_RESERVED) {
    -            return self::highlightReservedWord($token);
    -        } elseif ($type===self::TOKEN_TYPE_RESERVED_TOPLEVEL) {
    -            return self::highlightReservedWord($token);
    -        } elseif ($type===self::TOKEN_TYPE_RESERVED_NEWLINE) {
    -            return self::highlightReservedWord($token);
    -        } elseif ($type===self::TOKEN_TYPE_NUMBER) {
    -            return self::highlightNumber($token);
    -        } elseif ($type===self::TOKEN_TYPE_VARIABLE) {
    -            return self::highlightVariable($token);
    -        } elseif ($type===self::TOKEN_TYPE_COMMENT || $type===self::TOKEN_TYPE_BLOCK_COMMENT) {
    -            return self::highlightComment($token);
    -        }
    -
    -        return $token;
    -    }
    -
    -    /**
    -     * Highlights a quoted string
    -     *
    -     * @param String $value The token's value
    -     *
    -     * @return String HTML code of the highlighted token.
    -     */
    -    protected static function highlightQuote($value)
    -    {
    -        if (self::is_cli()) {
    -            return self::$cli_quote . $value . "\x1b[0m";
    -        } else {
    -            return '' . $value . '';
    -        }
    -    }
    -
    -    /**
    -     * Highlights a backtick quoted string
    -     *
    -     * @param String $value The token's value
    -     *
    -     * @return String HTML code of the highlighted token.
    -     */
    -    protected static function highlightBacktickQuote($value)
    -    {
    -        if (self::is_cli()) {
    -            return self::$cli_backtick_quote . $value . "\x1b[0m";
    -        } else {
    -            return '' . $value . '';
    -        }
    -    }
    -
    -    /**
    -     * Highlights a reserved word
    -     *
    -     * @param String $value The token's value
    -     *
    -     * @return String HTML code of the highlighted token.
    -     */
    -    protected static function highlightReservedWord($value)
    -    {
    -        if (self::is_cli()) {
    -            return self::$cli_reserved . $value . "\x1b[0m";
    -        } else {
    -            return '' . $value . '';
    -        }
    -    }
    -
    -    /**
    -     * Highlights a boundary token
    -     *
    -     * @param String $value The token's value
    -     *
    -     * @return String HTML code of the highlighted token.
    -     */
    -    protected static function highlightBoundary($value)
    -    {
    -        if ($value==='(' || $value===')') return $value;
    -
    -        if (self::is_cli()) {
    -            return self::$cli_boundary . $value . "\x1b[0m";
    -        } else {
    -            return '' . $value . '';
    -        }
    -    }
    -
    -    /**
    -     * Highlights a number
    -     *
    -     * @param String $value The token's value
    -     *
    -     * @return String HTML code of the highlighted token.
    -     */
    -    protected static function highlightNumber($value)
    -    {
    -        if (self::is_cli()) {
    -            return self::$cli_number . $value . "\x1b[0m";
    -        } else {
    -            return '' . $value . '';
    -        }
    -    }
    -
    -    /**
    -     * Highlights an error
    -     *
    -     * @param String $value The token's value
    -     *
    -     * @return String HTML code of the highlighted token.
    -     */
    -    protected static function highlightError($value)
    -    {
    -        if (self::is_cli()) {
    -            return self::$cli_error . $value . "\x1b[0m";
    -        } else {
    -            return '' . $value . '';
    -        }
    -    }
    -
    -    /**
    -     * Highlights a comment
    -     *
    -     * @param String $value The token's value
    -     *
    -     * @return String HTML code of the highlighted token.
    -     */
    -    protected static function highlightComment($value)
    -    {
    -        if (self::is_cli()) {
    -            return self::$cli_comment . $value . "\x1b[0m";
    -        } else {
    -            return '' . $value . '';
    -        }
    -    }
    -
    -    /**
    -     * Highlights a word token
    -     *
    -     * @param String $value The token's value
    -     *
    -     * @return String HTML code of the highlighted token.
    -     */
    -    protected static function highlightWord($value)
    -    {
    -        if (self::is_cli()) {
    -            return self::$cli_word . $value . "\x1b[0m";
    -        } else {
    -            return '' . $value . '';
    -        }
    -    }
    -
    -    /**
    -     * Highlights a variable token
    -     *
    -     * @param String $value The token's value
    -     *
    -     * @return String HTML code of the highlighted token.
    -     */
    -    protected static function highlightVariable($value)
    -    {
    -        if (self::is_cli()) {
    -            return self::$cli_variable . $value . "\x1b[0m";
    -        } else {
    -            return '' . $value . '';
    -        }
    -    }
    -
    -    /**
    -     * Helper function for building regular expressions for reserved words and boundary characters
    -     *
    -     * @param String $a The string to be quoted
    -     *
    -     * @return String The quoted string
    -     */
    -    private static function quote_regex($a)
    -    {
    -        return preg_quote($a,'/');
    -    }
    -
    -    /**
    -     * Helper function for building string output
    -     *
    -     * @param String $string The string to be quoted
    -     *
    -     * @return String The quoted string
    -     */
    -    private static function output($string)
    -    {
    -        if (self::is_cli()) {
    -            return $string."\n";
    -        } else {
    -            $string=trim($string);
    -            if (!self::$use_pre) {
    -                return $string;
    -            }
    -
    -            return '
    ' . $string . '
    '; - } - } - - private static function is_cli() - { - if (isset(self::$cli)) return self::$cli; - else return php_sapi_name() === 'cli'; - } - -} diff --git a/vendor/jdorn/sql-formatter/phpunit.xml.dist b/vendor/jdorn/sql-formatter/phpunit.xml.dist deleted file mode 100644 index ebfda97..0000000 --- a/vendor/jdorn/sql-formatter/phpunit.xml.dist +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - ./tests - - - - - - ./ - - ./tests - ./vendor - ./examples - - - - diff --git a/vendor/jdorn/sql-formatter/tests/SqlFormatterTest.php b/vendor/jdorn/sql-formatter/tests/SqlFormatterTest.php deleted file mode 100644 index ca535cf..0000000 --- a/vendor/jdorn/sql-formatter/tests/SqlFormatterTest.php +++ /dev/null @@ -1,197 +0,0 @@ -assertEquals(trim($html), trim(SqlFormatter::format($sql))); - } - /** - * @dataProvider formatData - */ - function testFormat($sql, $html) { - $this->assertEquals(trim($html), trim(SqlFormatter::format($sql, false))); - } - /** - * @dataProvider highlightData - */ - function testHighlight($sql, $html) { - $this->assertEquals(trim($html), trim(SqlFormatter::highlight($sql))); - } - /** - * @dataProvider highlightCliData - */ - function testCliHighlight($sql, $html) { - SqlFormatter::$cli = true; - $this->assertEquals(trim($html), trim(SqlFormatter::format($sql))); - SqlFormatter::$cli = false; - } - /** - * @dataProvider compressData - */ - function testCompress($sql, $html) { - $this->assertEquals(trim($html), trim(SqlFormatter::compress($sql))); - } - - function testUsePre() { - SqlFormatter::$use_pre = false; - $actual = SqlFormatter::highlight("test"); - $expected = 'test'; - $this->assertEquals($actual,$expected); - - SqlFormatter::$use_pre = true; - $actual = SqlFormatter::highlight("test"); - $expected = '
    test
    '; - $this->assertEquals($actual,$expected); - } - - function testSplitQuery() { - $expected = array( - "SELECT 'test' FROM MyTable;", - "SELECT Column2 FROM SomeOther Table WHERE (test = true);" - ); - - $actual = SqlFormatter::splitQuery(implode(';',$expected)); - - $this->assertEquals($expected, $actual); - } - - function testSplitQueryEmpty() { - $sql = "SELECT 1;SELECT 2;\n-- This is a comment\n;SELECT 3"; - $expected = array("SELECT 1;","SELECT 2;","SELECT 3"); - $actual = SqlFormatter::splitQuery($sql); - - $this->assertEquals($expected, $actual); - } - - function testRemoveComments() { - $expected = SqlFormatter::format("SELECT\n * FROM\n MyTable",false); - $sql = "/* this is a comment */SELECT#This is another comment\n * FROM-- One final comment\n MyTable"; - $actual = SqlFormatter::removeComments($sql); - - $this->assertEquals($expected, $actual); - } - - function testCacheStats() { - $stats = SqlFormatter::getCacheStats(); - $this->assertGreaterThan(1,$stats['hits']); - } - - function formatHighlightData() { - $formatHighlightData = explode("\n\n",file_get_contents(__DIR__."/format-highlight.html")); - $sqlData = $this->sqlData(); - - $return = array(); - foreach($formatHighlightData as $i=>$data) { - $return[] = array( - $sqlData[$i], - $data - ); - } - - return $return; - } - - function highlightCliData() { - $clidata = explode("\n\n",file_get_contents(__DIR__."/clihighlight.html")); - $sqlData = $this->sqlData(); - - $return = array(); - foreach($clidata as $i=>$data) { - $return[] = array( - $sqlData[$i], - $data - ); - } - - return $return; - } - - function formatData() { - $formatData = explode("\n\n",file_get_contents(__DIR__."/format.html")); - $sqlData = $this->sqlData(); - - $return = array(); - foreach($formatData as $i=>$data) { - $return[] = array( - $sqlData[$i], - $data - ); - } - - return $return; - } - - function compressData() { - $compressData = explode("\n\n",file_get_contents(__DIR__."/compress.html")); - $sqlData = $this->sqlData(); - - $return = array(); - foreach($compressData as $i=>$data) { - $return[] = array( - $sqlData[$i], - $data - ); - } - - return $return; - } - - function highlightData() { - $highlightData = explode("\n\n",file_get_contents(__DIR__."/highlight.html")); - $sqlData = $this->sqlData(); - - $return = array(); - foreach($highlightData as $i=>$data) { - $return[] = array( - $sqlData[$i], - $data - ); - } - - return $return; - } - - - - function sqlData() { - if(!$this->sqlData) { - $this->sqlData = explode("\n\n",file_get_contents(__DIR__."/sql.sql")); - } - - /** - $formatHighlight = array(); - $highlight = array(); - $format = array(); - $compress = array(); - $clihighlight = array(); - - foreach($this->sqlData as $sql) { - $formatHighlight[] = trim(SqlFormatter::format($sql)); - $highlight[] = trim(SqlFormatter::highlight($sql)); - $format[] = trim(SqlFormatter::format($sql, false)); - $compress[] = trim(SqlFormatter::compress($sql)); - - SqlFormatter::$cli = true; - $clihighlight[] = trim(SqlFormatter::format($sql)); - SqlFormatter::$cli = false; - } - - file_put_contents(__DIR__."/format-highlight.html", implode("\n\n",$formatHighlight)); - file_put_contents(__DIR__."/highlight.html", implode("\n\n",$highlight)); - file_put_contents(__DIR__."/format.html", implode("\n\n",$format)); - file_put_contents(__DIR__."/compress.html", implode("\n\n",$compress)); - file_put_contents(__DIR__."/clihighlight.html", implode("\n\n",$clihighlight)); - /**/ - - return $this->sqlData; - } - -} diff --git a/vendor/jdorn/sql-formatter/tests/clihighlight.html b/vendor/jdorn/sql-formatter/tests/clihighlight.html deleted file mode 100644 index 6ccfc12..0000000 --- a/vendor/jdorn/sql-formatter/tests/clihighlight.html +++ /dev/null @@ -1,809 +0,0 @@ -SELECT - customer_id, - customer_name, - COUNT(order_id) as total -FROM - customers - INNER JOIN orders ON customers.customer_id = orders.customer_id -GROUP BY - customer_id, - customer_name -HAVING - COUNT(order_id) > 5 -ORDER BY - COUNT(order_id) DESC; - -UPDATE - customers -SET - totalorders = ordersummary.total -FROM - ( - SELECT - customer_id, - count(order_id) As total - FROM - orders - GROUP BY - customer_id - ) As ordersummary -WHERE - customers.customer_id = ordersummary.customer_id - -SELECT - * -FROM - sometable -UNION ALL -SELECT - * -FROM - someothertable; - -SET - NAMES 'utf8'; - -CREATE TABLE `PREFIX_address` ( - `id_address` int(10) unsigned NOT NULL auto_increment, - `id_country` int(10) unsigned NOT NULL, - `id_state` int(10) unsigned default NULL, - `id_customer` int(10) unsigned NOT NULL default '0', - `id_manufacturer` int(10) unsigned NOT NULL default '0', - `id_supplier` int(10) unsigned NOT NULL default '0', - `id_warehouse` int(10) unsigned NOT NULL default '0', - `alias` varchar(32) NOT NULL, - `company` varchar(64) default NULL, - `lastname` varchar(32) NOT NULL, - `firstname` varchar(32) NOT NULL, - `address1` varchar(128) NOT NULL, - `address2` varchar(128) default NULL, - `postcode` varchar(12) default NULL, - `city` varchar(64) NOT NULL, - `other` text, - `phone` varchar(16) default NULL, - `phone_mobile` varchar(16) default NULL, - `vat_number` varchar(32) default NULL, - `dni` varchar(16) DEFAULT NULL, - `date_add` datetime NOT NULL, - `date_upd` datetime NOT NULL, - `active` tinyint(1) unsigned NOT NULL default '1', - `deleted` tinyint(1) unsigned NOT NULL default '0', - PRIMARY KEY (`id_address`), - KEY `address_customer` (`id_customer`), - KEY `id_country` (`id_country`), - KEY `id_state` (`id_state`), - KEY `id_manufacturer` (`id_manufacturer`), - KEY `id_supplier` (`id_supplier`), - KEY `id_warehouse` (`id_warehouse`) -) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 - -CREATE TABLE `PREFIX_alias` ( - `id_alias` int(10) unsigned NOT NULL auto_increment, - `alias` varchar(255) NOT NULL, - `search` varchar(255) NOT NULL, - `active` tinyint(1) NOT NULL default '1', - PRIMARY KEY (`id_alias`), - UNIQUE KEY `alias` (`alias`) -) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 - -CREATE TABLE `PREFIX_carrier` ( - `id_carrier` int(10) unsigned NOT NULL AUTO_INCREMENT, - `id_reference` int(10) unsigned NOT NULL, - `id_tax_rules_group` int(10) unsigned DEFAULT '0', - `name` varchar(64) NOT NULL, - `url` varchar(255) DEFAULT NULL, - `active` tinyint(1) unsigned NOT NULL DEFAULT '0', - `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0', - `shipping_handling` tinyint(1) unsigned NOT NULL DEFAULT '1', - `range_behavior` tinyint(1) unsigned NOT NULL DEFAULT '0', - `is_module` tinyint(1) unsigned NOT NULL DEFAULT '0', - `is_free` tinyint(1) unsigned NOT NULL DEFAULT '0', - `shipping_external` tinyint(1) unsigned NOT NULL DEFAULT '0', - `need_range` tinyint(1) unsigned NOT NULL DEFAULT '0', - `external_module_name` varchar(64) DEFAULT NULL, - `shipping_method` int(2) NOT NULL DEFAULT '0', - `position` int(10) unsigned NOT NULL default '0', - `max_width` int(10) DEFAULT 0, - `max_height` int(10) DEFAULT 0, - `max_depth` int(10) DEFAULT 0, - `max_weight` int(10) DEFAULT 0, - `grade` int(10) DEFAULT 0, - PRIMARY KEY (`id_carrier`), - KEY `deleted` (`deleted`, `active`), - KEY `id_tax_rules_group` (`id_tax_rules_group`) -) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 - -CREATE TABLE IF NOT EXISTS `PREFIX_specific_price_rule` ( - `id_specific_price_rule` int(10) unsigned NOT NULL AUTO_INCREMENT, - `name` VARCHAR(255) NOT NULL, - `id_shop` int(11) unsigned NOT NULL DEFAULT '1', - `id_currency` int(10) unsigned NOT NULL, - `id_country` int(10) unsigned NOT NULL, - `id_group` int(10) unsigned NOT NULL, - `from_quantity` mediumint(8) unsigned NOT NULL, - `price` DECIMAL(20, 6), - `reduction` decimal(20, 6) NOT NULL, - `reduction_type` enum('amount', 'percentage') NOT NULL, - `from` datetime NOT NULL, - `to` datetime NOT NULL, - PRIMARY KEY (`id_specific_price_rule`), - KEY `id_product` ( - `id_shop`, `id_currency`, `id_country`, - `id_group`, `from_quantity`, `from`, - `to` - ) -) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 - -UPDATE - `PREFIX_configuration` -SET - value = '6' -WHERE - name = 'PS_SEARCH_WEIGHT_PNAME' - -UPDATE - `PREFIX_hook_module` -SET - position = 1 -WHERE - id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayPayment' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'cheque' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayPaymentReturn' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'cheque' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayHome' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'homeslider' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionAuthentication' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'statsdata' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionShopDataDuplication' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'homeslider' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayTop' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blocklanguages' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionCustomerAccountAdd' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'statsdata' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayCustomerAccount' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'favoriteproducts' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayAdminStatsModules' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'statsvisits' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayAdminStatsGraphEngine' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'graphvisifire' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayAdminStatsGridEngine' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'gridhtml' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayLeftColumnProduct' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blocksharefb' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionSearch' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'statssearch' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionCategoryAdd' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blockcategories' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionCategoryUpdate' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blockcategories' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionCategoryDelete' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blockcategories' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionAdminMetaSave' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blockcategories' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayMyAccountBlock' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'favoriteproducts' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayFooter' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blockreinsurance' - ) - -ALTER TABLE - `PREFIX_employee` -ADD - `bo_color` varchar(32) default NULL -AFTER - `stats_date_to` - -INSERT INTO `PREFIX_cms_category_lang` -VALUES - ( - 1, 3, 'Inicio', '', 'home', NULL, NULL, - NULL - ) - -INSERT INTO `PREFIX_cms_category` -VALUES - (1, 0, 0, 1, NOW(), NOW(), 0) - -UPDATE - `PREFIX_cms_category` -SET - `position` = 0 - -ALTER TABLE - `PREFIX_customer` -ADD - `note` text -AFTER - `secure_key` - -ALTER TABLE - `PREFIX_contact` -ADD - `customer_service` tinyint(1) NOT NULL DEFAULT 0 -AFTER - `email` - -INSERT INTO `PREFIX_specific_price` ( - `id_product`, `id_shop`, `id_currency`, - `id_country`, `id_group`, `priority`, - `price`, `from_quantity`, `reduction`, - `reduction_type`, `from`, `to` -) ( - SELECT - dq.`id_product`, - 1, - 1, - 0, - 1, - 0, - 0.00, - dq.`quantity`, - IF( - dq.`id_discount_type` = 2, dq.`value`, - dq.`value` / 100 - ), - IF ( - dq.`id_discount_type` = 2, 'amount', - 'percentage' - ), - '0000-00-00 00:00:00', - '0000-00-00 00:00:00' - FROM - `PREFIX_discount_quantity` dq - INNER JOIN `PREFIX_product` p ON (p.`id_product` = dq.`id_product`) -) - -DROP - TABLE `PREFIX_discount_quantity` - -INSERT INTO `PREFIX_specific_price` ( - `id_product`, `id_shop`, `id_currency`, - `id_country`, `id_group`, `priority`, - `price`, `from_quantity`, `reduction`, - `reduction_type`, `from`, `to` -) ( - SELECT - p.`id_product`, - 1, - 0, - 0, - 0, - 0, - 0.00, - 1, - IF( - p.`reduction_price` > 0, p.`reduction_price`, - p.`reduction_percent` / 100 - ), - IF( - p.`reduction_price` > 0, 'amount', - 'percentage' - ), - IF ( - p.`reduction_from` = p.`reduction_to`, - '0000-00-00 00:00:00', p.`reduction_from` - ), - IF ( - p.`reduction_from` = p.`reduction_to`, - '0000-00-00 00:00:00', p.`reduction_to` - ) - FROM - `PREFIX_product` p - WHERE - p.`reduction_price` - OR p.`reduction_percent` -) - -ALTER TABLE - `PREFIX_product` -DROP - `reduction_price`, -DROP - `reduction_percent`, -DROP - `reduction_from`, -DROP - `reduction_to` - -INSERT INTO `PREFIX_configuration` ( - `name`, `value`, `date_add`, `date_upd` -) -VALUES - ( - 'PS_SPECIFIC_PRICE_PRIORITIES', - 'id_shop;id_currency;id_country;id_group', - NOW(), NOW() - ), - ('PS_TAX_DISPLAY', 0, NOW(), NOW()), - ( - 'PS_SMARTY_FORCE_COMPILE', 1, NOW(), - NOW() - ), - ( - 'PS_DISTANCE_UNIT', 'km', NOW(), NOW() - ), - ( - 'PS_STORES_DISPLAY_CMS', 0, NOW(), - NOW() - ), - ( - 'PS_STORES_DISPLAY_FOOTER', 0, NOW(), - NOW() - ), - ( - 'PS_STORES_SIMPLIFIED', 0, NOW(), - NOW() - ), - ( - 'PS_STATSDATA_CUSTOMER_PAGESVIEWS', - 1, NOW(), NOW() - ), - ( - 'PS_STATSDATA_PAGESVIEWS', 1, NOW(), - NOW() - ), - ( - 'PS_STATSDATA_PLUGINS', 1, NOW(), - NOW() - ) - -INSERT INTO `PREFIX_configuration` ( - `name`, `value`, `date_add`, `date_upd` -) -VALUES - ( - 'PS_CONDITIONS_CMS_ID', - IFNULL( - ( - SELECT - `id_cms` - FROM - `PREFIX_cms` - WHERE - `id_cms` = 3 - ), - 0 - ), - NOW(), - NOW() - ) - -CREATE TEMPORARY TABLE `PREFIX_configuration_tmp` (`value` text) - -SET - @defaultOOS = ( - SELECT - value - FROM - `PREFIX_configuration` - WHERE - name = 'PS_ORDER_OUT_OF_STOCK' - ) - -UPDATE - `PREFIX_product` p -SET - `cache_default_attribute` = 0 -WHERE - `id_product` NOT IN ( - SELECT - `id_product` - FROM - `PREFIX_product_attribute` - ) - -INSERT INTO `PREFIX_hook` ( - `name`, `title`, `description`, `position` -) -VALUES - ( - 'processCarrier', 'Carrier Process', - NULL, 0 - ) - -INSERT INTO `PREFIX_stock_mvt_reason_lang` ( - `id_stock_mvt_reason`, `id_lang`, - `name` -) -VALUES - (1, 1, 'Order'), - (1, 2, 'Commande'), - (2, 1, 'Missing Stock Movement'), - ( - 2, 2, 'Mouvement de stock manquant' - ), - (3, 1, 'Restocking'), - (3, 2, 'Réassort') - -INSERT INTO `PREFIX_meta_lang` ( - `id_lang`, `id_meta`, `title`, `url_rewrite` -) -VALUES - ( - 1, - ( - SELECT - `id_meta` - FROM - `PREFIX_meta` - WHERE - `page` = 'authentication' - ), - 'Authentication', - 'authentication' - ), - ( - 2, - ( - SELECT - `id_meta` - FROM - `PREFIX_meta` - WHERE - `page` = 'authentication' - ), - 'Authentification', - 'authentification' - ), - ( - 3, - ( - SELECT - `id_meta` - FROM - `PREFIX_meta` - WHERE - `page` = 'authentication' - ), - 'Autenticación', - 'autenticacion' - ) - -LOCK TABLES `admin_assert` WRITE - -UNLOCK TABLES - -DROP - TABLE IF EXISTS `admin_role` - -SELECT - * -FROM - -- This is another comment - MyTable # One final comment - - /* This is a block comment - */ -WHERE - 1 = 2; - -SELECT - -- This is a test - -SELECT - Test -FROM - Test -WHERE - (MyColumn = 1) -) -AND ( - ( - (SomeOtherColumn = 2); -WARNING: unclosed parentheses or section - -SELECT - * -LIMIT - 1; -SELECT - a, - b, - c, - d -FROM - e -LIMIT - 1, 2; -SELECT - 1, - 2, - 3 -WHERE - a in (1, 2, 3, 4, 5) - and b = 5; - -SELECT - count - 50 -WHERE - a - 50 = b -WHERE - 1 - and -50 -WHERE - -50 = a -WHERE - a = -50 -WHERE - 1 - /*test*/ - -50 -WHERE - 1 - and -50; - -SELECT - @ - and b; - -SELECT - @"weird variable name"; - -SELECT - "no closing quote - \ No newline at end of file diff --git a/vendor/jdorn/sql-formatter/tests/compress.html b/vendor/jdorn/sql-formatter/tests/compress.html deleted file mode 100644 index bb2fcf7..0000000 --- a/vendor/jdorn/sql-formatter/tests/compress.html +++ /dev/null @@ -1,77 +0,0 @@ -SELECT customer_id, customer_name, COUNT(order_id) as total FROM customers INNER JOIN orders ON customers.customer_id = orders.customer_id GROUP BY customer_id, customer_name HAVING COUNT(order_id) > 5 ORDER BY COUNT(order_id) DESC; - -UPDATE customers SET totalorders = ordersummary.total FROM (SELECT customer_id, count(order_id) As total FROM orders GROUP BY customer_id) As ordersummary WHERE customers.customer_id = ordersummary.customer_id - -SELECT * FROM sometable UNION ALL SELECT * FROM someothertable; - -SET NAMES 'utf8'; - -CREATE TABLE `PREFIX_address` ( `id_address` int(10) unsigned NOT NULL auto_increment, `id_country` int(10) unsigned NOT NULL, `id_state` int(10) unsigned default NULL, `id_customer` int(10) unsigned NOT NULL default '0', `id_manufacturer` int(10) unsigned NOT NULL default '0', `id_supplier` int(10) unsigned NOT NULL default '0', `id_warehouse` int(10) unsigned NOT NULL default '0', `alias` varchar(32) NOT NULL, `company` varchar(64) default NULL, `lastname` varchar(32) NOT NULL, `firstname` varchar(32) NOT NULL, `address1` varchar(128) NOT NULL, `address2` varchar(128) default NULL, `postcode` varchar(12) default NULL, `city` varchar(64) NOT NULL, `other` text, `phone` varchar(16) default NULL, `phone_mobile` varchar(16) default NULL, `vat_number` varchar(32) default NULL, `dni` varchar(16) DEFAULT NULL, `date_add` datetime NOT NULL, `date_upd` datetime NOT NULL, `active` tinyint(1) unsigned NOT NULL default '1', `deleted` tinyint(1) unsigned NOT NULL default '0', PRIMARY KEY (`id_address`), KEY `address_customer` (`id_customer`), KEY `id_country` (`id_country`), KEY `id_state` (`id_state`), KEY `id_manufacturer` (`id_manufacturer`), KEY `id_supplier` (`id_supplier`), KEY `id_warehouse` (`id_warehouse`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 - -CREATE TABLE `PREFIX_alias` ( `id_alias` int(10) unsigned NOT NULL auto_increment, `alias` varchar(255) NOT NULL, `search` varchar(255) NOT NULL, `active` tinyint(1) NOT NULL default '1', PRIMARY KEY (`id_alias`), UNIQUE KEY `alias` (`alias`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 - -CREATE TABLE `PREFIX_carrier` ( `id_carrier` int(10) unsigned NOT NULL AUTO_INCREMENT, `id_reference` int(10) unsigned NOT NULL, `id_tax_rules_group` int(10) unsigned DEFAULT '0', `name` varchar(64) NOT NULL, `url` varchar(255) DEFAULT NULL, `active` tinyint(1) unsigned NOT NULL DEFAULT '0', `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0', `shipping_handling` tinyint(1) unsigned NOT NULL DEFAULT '1', `range_behavior` tinyint(1) unsigned NOT NULL DEFAULT '0', `is_module` tinyint(1) unsigned NOT NULL DEFAULT '0', `is_free` tinyint(1) unsigned NOT NULL DEFAULT '0', `shipping_external` tinyint(1) unsigned NOT NULL DEFAULT '0', `need_range` tinyint(1) unsigned NOT NULL DEFAULT '0', `external_module_name` varchar(64) DEFAULT NULL, `shipping_method` int(2) NOT NULL DEFAULT '0', `position` int(10) unsigned NOT NULL default '0', `max_width` int(10) DEFAULT 0, `max_height` int(10) DEFAULT 0, `max_depth` int(10) DEFAULT 0, `max_weight` int(10) DEFAULT 0, `grade` int(10) DEFAULT 0, PRIMARY KEY (`id_carrier`), KEY `deleted` (`deleted`,`active`), KEY `id_tax_rules_group` (`id_tax_rules_group`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 - -CREATE TABLE IF NOT EXISTS `PREFIX_specific_price_rule` ( `id_specific_price_rule` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL, `id_shop` int(11) unsigned NOT NULL DEFAULT '1', `id_currency` int(10) unsigned NOT NULL, `id_country` int(10) unsigned NOT NULL, `id_group` int(10) unsigned NOT NULL, `from_quantity` mediumint(8) unsigned NOT NULL, `price` DECIMAL(20,6), `reduction` decimal(20,6) NOT NULL, `reduction_type` enum('amount','percentage') NOT NULL, `from` datetime NOT NULL, `to` datetime NOT NULL, PRIMARY KEY (`id_specific_price_rule`), KEY `id_product` (`id_shop`,`id_currency`,`id_country`,`id_group`,`from_quantity`,`from`,`to`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 - -UPDATE `PREFIX_configuration` SET value = '6' WHERE name = 'PS_SEARCH_WEIGHT_PNAME' - -UPDATE `PREFIX_hook_module` SET position = 1 WHERE id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayPayment') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'cheque') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayPaymentReturn') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'cheque') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayHome') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'homeslider') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionAuthentication') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsdata') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionShopDataDuplication') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'homeslider') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayTop') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blocklanguages') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCustomerAccountAdd') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsdata') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayCustomerAccount') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'favoriteproducts') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsModules') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsvisits') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsGraphEngine') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'graphvisifire') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsGridEngine') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'gridhtml') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayLeftColumnProduct') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blocksharefb') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionSearch') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statssearch') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryAdd') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryUpdate') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryDelete') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionAdminMetaSave') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayMyAccountBlock') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'favoriteproducts') OR id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayFooter') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockreinsurance') - -ALTER TABLE `PREFIX_employee` ADD `bo_color` varchar(32) default NULL AFTER `stats_date_to` - -INSERT INTO `PREFIX_cms_category_lang` VALUES(1, 3, 'Inicio', '', 'home', NULL, NULL, NULL) - -INSERT INTO `PREFIX_cms_category` VALUES(1, 0, 0, 1, NOW(), NOW(),0) - -UPDATE `PREFIX_cms_category` SET `position` = 0 - -ALTER TABLE `PREFIX_customer` ADD `note` text AFTER `secure_key` - -ALTER TABLE `PREFIX_contact` ADD `customer_service` tinyint(1) NOT NULL DEFAULT 0 AFTER `email` - -INSERT INTO `PREFIX_specific_price` (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `priority`, `price`, `from_quantity`, `reduction`, `reduction_type`, `from`, `to`) ( SELECT dq.`id_product`, 1, 1, 0, 1, 0, 0.00, dq.`quantity`, IF(dq.`id_discount_type` = 2, dq.`value`, dq.`value` / 100), IF (dq.`id_discount_type` = 2, 'amount', 'percentage'), '0000-00-00 00:00:00', '0000-00-00 00:00:00' FROM `PREFIX_discount_quantity` dq INNER JOIN `PREFIX_product` p ON (p.`id_product` = dq.`id_product`) ) - -DROP TABLE `PREFIX_discount_quantity` - -INSERT INTO `PREFIX_specific_price` (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `priority`, `price`, `from_quantity`, `reduction`, `reduction_type`, `from`, `to`) ( SELECT p.`id_product`, 1, 0, 0, 0, 0, 0.00, 1, IF(p.`reduction_price` > 0, p.`reduction_price`, p.`reduction_percent` / 100), IF(p.`reduction_price` > 0, 'amount', 'percentage'), IF (p.`reduction_from` = p.`reduction_to`, '0000-00-00 00:00:00', p.`reduction_from`), IF (p.`reduction_from` = p.`reduction_to`, '0000-00-00 00:00:00', p.`reduction_to`) FROM `PREFIX_product` p WHERE p.`reduction_price` OR p.`reduction_percent` ) - -ALTER TABLE `PREFIX_product` DROP `reduction_price`, DROP `reduction_percent`, DROP `reduction_from`, DROP `reduction_to` - -INSERT INTO `PREFIX_configuration` (`name`, `value`, `date_add`, `date_upd`) VALUES ('PS_SPECIFIC_PRICE_PRIORITIES', 'id_shop;id_currency;id_country;id_group', NOW(), NOW()), ('PS_TAX_DISPLAY', 0, NOW(), NOW()), ('PS_SMARTY_FORCE_COMPILE', 1, NOW(), NOW()), ('PS_DISTANCE_UNIT', 'km', NOW(), NOW()), ('PS_STORES_DISPLAY_CMS', 0, NOW(), NOW()), ('PS_STORES_DISPLAY_FOOTER', 0, NOW(), NOW()), ('PS_STORES_SIMPLIFIED', 0, NOW(), NOW()), ('PS_STATSDATA_CUSTOMER_PAGESVIEWS', 1, NOW(), NOW()), ('PS_STATSDATA_PAGESVIEWS', 1, NOW(), NOW()), ('PS_STATSDATA_PLUGINS', 1, NOW(), NOW()) - -INSERT INTO `PREFIX_configuration` (`name`, `value`, `date_add`, `date_upd`) VALUES ('PS_CONDITIONS_CMS_ID', IFNULL((SELECT `id_cms` FROM `PREFIX_cms` WHERE `id_cms` = 3), 0), NOW(), NOW()) - -CREATE TEMPORARY TABLE `PREFIX_configuration_tmp` ( `value` text ) - -SET @defaultOOS = (SELECT value FROM `PREFIX_configuration` WHERE name = 'PS_ORDER_OUT_OF_STOCK') - -UPDATE `PREFIX_product` p SET `cache_default_attribute` = 0 WHERE `id_product` NOT IN (SELECT `id_product` FROM `PREFIX_product_attribute`) - -INSERT INTO `PREFIX_hook` (`name`, `title`, `description`, `position`) VALUES ('processCarrier', 'Carrier Process', NULL, 0) - -INSERT INTO `PREFIX_stock_mvt_reason_lang` (`id_stock_mvt_reason`, `id_lang`, `name`) VALUES (1, 1, 'Order'), (1, 2, 'Commande'), (2, 1, 'Missing Stock Movement'), (2, 2, 'Mouvement de stock manquant'), (3, 1, 'Restocking'), (3, 2, 'Réassort') - -INSERT INTO `PREFIX_meta_lang` (`id_lang`, `id_meta`, `title`, `url_rewrite`) VALUES (1, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Authentication', 'authentication'), (2, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Authentification', 'authentification'), (3, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Autenticación', 'autenticacion') - -LOCK TABLES `admin_assert` WRITE - -UNLOCK TABLES - -DROP TABLE IF EXISTS `admin_role` - -SELECT * FROM MyTable WHERE 1 = 2; - -SELECT - -SELECT Test FROM Test WHERE ( MyColumn = 1 )) AND ((( SomeOtherColumn = 2); - -SELECT * LIMIT 1; SELECT a,b,c,d FROM e LIMIT 1, 2; SELECT 1,2,3 WHERE a in (1,2,3,4,5) and b=5; - -SELECT count - 50 WHERE a-50 = b WHERE 1 and - 50 WHERE -50 = a WHERE a = -50 WHERE 1 - 50 WHERE 1 and -50; - -SELECT @ and b; - -SELECT @"weird variable name"; - -SELECT "no closing quote \ No newline at end of file diff --git a/vendor/jdorn/sql-formatter/tests/format-highlight.html b/vendor/jdorn/sql-formatter/tests/format-highlight.html deleted file mode 100644 index 73af253..0000000 --- a/vendor/jdorn/sql-formatter/tests/format-highlight.html +++ /dev/null @@ -1,809 +0,0 @@ -
    SELECT 
    -  customer_id, 
    -  customer_name, 
    -  COUNT(order_id) as total 
    -FROM 
    -  customers 
    -  INNER JOIN orders ON customers.customer_id = orders.customer_id 
    -GROUP BY 
    -  customer_id, 
    -  customer_name 
    -HAVING 
    -  COUNT(order_id) > 5 
    -ORDER BY 
    -  COUNT(order_id) DESC;
    - -
    UPDATE 
    -  customers 
    -SET 
    -  totalorders = ordersummary.total 
    -FROM 
    -  (
    -    SELECT 
    -      customer_id, 
    -      count(order_id) As total 
    -    FROM 
    -      orders 
    -    GROUP BY 
    -      customer_id
    -  ) As ordersummary 
    -WHERE 
    -  customers.customer_id = ordersummary.customer_id
    - -
    SELECT 
    -  * 
    -FROM 
    -  sometable 
    -UNION ALL 
    -SELECT 
    -  * 
    -FROM 
    -  someothertable;
    - -
    SET 
    -  NAMES 'utf8';
    - -
    CREATE TABLE `PREFIX_address` (
    -  `id_address` int(10) unsigned NOT NULL auto_increment, 
    -  `id_country` int(10) unsigned NOT NULL, 
    -  `id_state` int(10) unsigned default NULL, 
    -  `id_customer` int(10) unsigned NOT NULL default '0', 
    -  `id_manufacturer` int(10) unsigned NOT NULL default '0', 
    -  `id_supplier` int(10) unsigned NOT NULL default '0', 
    -  `id_warehouse` int(10) unsigned NOT NULL default '0', 
    -  `alias` varchar(32) NOT NULL, 
    -  `company` varchar(64) default NULL, 
    -  `lastname` varchar(32) NOT NULL, 
    -  `firstname` varchar(32) NOT NULL, 
    -  `address1` varchar(128) NOT NULL, 
    -  `address2` varchar(128) default NULL, 
    -  `postcode` varchar(12) default NULL, 
    -  `city` varchar(64) NOT NULL, 
    -  `other` text, 
    -  `phone` varchar(16) default NULL, 
    -  `phone_mobile` varchar(16) default NULL, 
    -  `vat_number` varchar(32) default NULL, 
    -  `dni` varchar(16) DEFAULT NULL, 
    -  `date_add` datetime NOT NULL, 
    -  `date_upd` datetime NOT NULL, 
    -  `active` tinyint(1) unsigned NOT NULL default '1', 
    -  `deleted` tinyint(1) unsigned NOT NULL default '0', 
    -  PRIMARY KEY (`id_address`), 
    -  KEY `address_customer` (`id_customer`), 
    -  KEY `id_country` (`id_country`), 
    -  KEY `id_state` (`id_state`), 
    -  KEY `id_manufacturer` (`id_manufacturer`), 
    -  KEY `id_supplier` (`id_supplier`), 
    -  KEY `id_warehouse` (`id_warehouse`)
    -) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8
    - -
    CREATE TABLE `PREFIX_alias` (
    -  `id_alias` int(10) unsigned NOT NULL auto_increment, 
    -  `alias` varchar(255) NOT NULL, 
    -  `search` varchar(255) NOT NULL, 
    -  `active` tinyint(1) NOT NULL default '1', 
    -  PRIMARY KEY (`id_alias`), 
    -  UNIQUE KEY `alias` (`alias`)
    -) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8
    - -
    CREATE TABLE `PREFIX_carrier` (
    -  `id_carrier` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    -  `id_reference` int(10) unsigned NOT NULL, 
    -  `id_tax_rules_group` int(10) unsigned DEFAULT '0', 
    -  `name` varchar(64) NOT NULL, 
    -  `url` varchar(255) DEFAULT NULL, 
    -  `active` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    -  `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    -  `shipping_handling` tinyint(1) unsigned NOT NULL DEFAULT '1', 
    -  `range_behavior` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    -  `is_module` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    -  `is_free` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    -  `shipping_external` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    -  `need_range` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    -  `external_module_name` varchar(64) DEFAULT NULL, 
    -  `shipping_method` int(2) NOT NULL DEFAULT '0', 
    -  `position` int(10) unsigned NOT NULL default '0', 
    -  `max_width` int(10) DEFAULT 0, 
    -  `max_height` int(10) DEFAULT 0, 
    -  `max_depth` int(10) DEFAULT 0, 
    -  `max_weight` int(10) DEFAULT 0, 
    -  `grade` int(10) DEFAULT 0, 
    -  PRIMARY KEY (`id_carrier`), 
    -  KEY `deleted` (`deleted`, `active`), 
    -  KEY `id_tax_rules_group` (`id_tax_rules_group`)
    -) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8
    - -
    CREATE TABLE IF NOT EXISTS `PREFIX_specific_price_rule` (
    -  `id_specific_price_rule` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    -  `name` VARCHAR(255) NOT NULL, 
    -  `id_shop` int(11) unsigned NOT NULL DEFAULT '1', 
    -  `id_currency` int(10) unsigned NOT NULL, 
    -  `id_country` int(10) unsigned NOT NULL, 
    -  `id_group` int(10) unsigned NOT NULL, 
    -  `from_quantity` mediumint(8) unsigned NOT NULL, 
    -  `price` DECIMAL(20, 6), 
    -  `reduction` decimal(20, 6) NOT NULL, 
    -  `reduction_type` enum('amount', 'percentage') NOT NULL, 
    -  `from` datetime NOT NULL, 
    -  `to` datetime NOT NULL, 
    -  PRIMARY KEY (`id_specific_price_rule`), 
    -  KEY `id_product` (
    -    `id_shop`, `id_currency`, `id_country`, 
    -    `id_group`, `from_quantity`, `from`, 
    -    `to`
    -  )
    -) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8
    - -
    UPDATE 
    -  `PREFIX_configuration` 
    -SET 
    -  value = '6' 
    -WHERE 
    -  name = 'PS_SEARCH_WEIGHT_PNAME'
    - -
    UPDATE 
    -  `PREFIX_hook_module` 
    -SET 
    -  position = 1 
    -WHERE 
    -  id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'displayPayment'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'cheque'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'displayPaymentReturn'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'cheque'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'displayHome'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'homeslider'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'actionAuthentication'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'statsdata'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'actionShopDataDuplication'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'homeslider'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'displayTop'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'blocklanguages'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'actionCustomerAccountAdd'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'statsdata'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'displayCustomerAccount'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'favoriteproducts'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'displayAdminStatsModules'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'statsvisits'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'displayAdminStatsGraphEngine'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'graphvisifire'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'displayAdminStatsGridEngine'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'gridhtml'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'displayLeftColumnProduct'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'blocksharefb'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'actionSearch'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'statssearch'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'actionCategoryAdd'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'blockcategories'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'actionCategoryUpdate'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'blockcategories'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'actionCategoryDelete'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'blockcategories'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'actionAdminMetaSave'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'blockcategories'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'displayMyAccountBlock'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'favoriteproducts'
    -  ) 
    -  OR id_hook = (
    -    SELECT 
    -      id_hook 
    -    FROM 
    -      `PREFIX_hook` 
    -    WHERE 
    -      name = 'displayFooter'
    -  ) 
    -  AND id_module = (
    -    SELECT 
    -      id_module 
    -    FROM 
    -      `PREFIX_module` 
    -    WHERE 
    -      name = 'blockreinsurance'
    -  )
    - -
    ALTER TABLE 
    -  `PREFIX_employee` 
    -ADD 
    -  `bo_color` varchar(32) default NULL 
    -AFTER 
    -  `stats_date_to`
    - -
    INSERT INTO `PREFIX_cms_category_lang` 
    -VALUES 
    -  (
    -    1, 3, 'Inicio', '', 'home', NULL, NULL, 
    -    NULL
    -  )
    - -
    INSERT INTO `PREFIX_cms_category` 
    -VALUES 
    -  (1, 0, 0, 1, NOW(), NOW(), 0)
    - -
    UPDATE 
    -  `PREFIX_cms_category` 
    -SET 
    -  `position` = 0
    - -
    ALTER TABLE 
    -  `PREFIX_customer` 
    -ADD 
    -  `note` text 
    -AFTER 
    -  `secure_key`
    - -
    ALTER TABLE 
    -  `PREFIX_contact` 
    -ADD 
    -  `customer_service` tinyint(1) NOT NULL DEFAULT 0 
    -AFTER 
    -  `email`
    - -
    INSERT INTO `PREFIX_specific_price` (
    -  `id_product`, `id_shop`, `id_currency`, 
    -  `id_country`, `id_group`, `priority`, 
    -  `price`, `from_quantity`, `reduction`, 
    -  `reduction_type`, `from`, `to`
    -) (
    -  SELECT 
    -    dq.`id_product`, 
    -    1, 
    -    1, 
    -    0, 
    -    1, 
    -    0, 
    -    0.00, 
    -    dq.`quantity`, 
    -    IF(
    -      dq.`id_discount_type` = 2, dq.`value`, 
    -      dq.`value` / 100
    -    ), 
    -    IF (
    -      dq.`id_discount_type` = 2, 'amount', 
    -      'percentage'
    -    ), 
    -    '0000-00-00 00:00:00', 
    -    '0000-00-00 00:00:00' 
    -  FROM 
    -    `PREFIX_discount_quantity` dq 
    -    INNER JOIN `PREFIX_product` p ON (p.`id_product` = dq.`id_product`)
    -)
    - -
    DROP 
    -  TABLE `PREFIX_discount_quantity`
    - -
    INSERT INTO `PREFIX_specific_price` (
    -  `id_product`, `id_shop`, `id_currency`, 
    -  `id_country`, `id_group`, `priority`, 
    -  `price`, `from_quantity`, `reduction`, 
    -  `reduction_type`, `from`, `to`
    -) (
    -  SELECT 
    -    p.`id_product`, 
    -    1, 
    -    0, 
    -    0, 
    -    0, 
    -    0, 
    -    0.00, 
    -    1, 
    -    IF(
    -      p.`reduction_price` > 0, p.`reduction_price`, 
    -      p.`reduction_percent` / 100
    -    ), 
    -    IF(
    -      p.`reduction_price` > 0, 'amount', 
    -      'percentage'
    -    ), 
    -    IF (
    -      p.`reduction_from` = p.`reduction_to`, 
    -      '0000-00-00 00:00:00', p.`reduction_from`
    -    ), 
    -    IF (
    -      p.`reduction_from` = p.`reduction_to`, 
    -      '0000-00-00 00:00:00', p.`reduction_to`
    -    ) 
    -  FROM 
    -    `PREFIX_product` p 
    -  WHERE 
    -    p.`reduction_price` 
    -    OR p.`reduction_percent`
    -)
    - -
    ALTER TABLE 
    -  `PREFIX_product` 
    -DROP 
    -  `reduction_price`, 
    -DROP 
    -  `reduction_percent`, 
    -DROP 
    -  `reduction_from`, 
    -DROP 
    -  `reduction_to`
    - -
    INSERT INTO `PREFIX_configuration` (
    -  `name`, `value`, `date_add`, `date_upd`
    -) 
    -VALUES 
    -  (
    -    'PS_SPECIFIC_PRICE_PRIORITIES', 
    -    'id_shop;id_currency;id_country;id_group', 
    -    NOW(), NOW()
    -  ), 
    -  ('PS_TAX_DISPLAY', 0, NOW(), NOW()), 
    -  (
    -    'PS_SMARTY_FORCE_COMPILE', 1, NOW(), 
    -    NOW()
    -  ), 
    -  (
    -    'PS_DISTANCE_UNIT', 'km', NOW(), NOW()
    -  ), 
    -  (
    -    'PS_STORES_DISPLAY_CMS', 0, NOW(), 
    -    NOW()
    -  ), 
    -  (
    -    'PS_STORES_DISPLAY_FOOTER', 0, NOW(), 
    -    NOW()
    -  ), 
    -  (
    -    'PS_STORES_SIMPLIFIED', 0, NOW(), 
    -    NOW()
    -  ), 
    -  (
    -    'PS_STATSDATA_CUSTOMER_PAGESVIEWS', 
    -    1, NOW(), NOW()
    -  ), 
    -  (
    -    'PS_STATSDATA_PAGESVIEWS', 1, NOW(), 
    -    NOW()
    -  ), 
    -  (
    -    'PS_STATSDATA_PLUGINS', 1, NOW(), 
    -    NOW()
    -  )
    - -
    INSERT INTO `PREFIX_configuration` (
    -  `name`, `value`, `date_add`, `date_upd`
    -) 
    -VALUES 
    -  (
    -    'PS_CONDITIONS_CMS_ID', 
    -    IFNULL(
    -      (
    -        SELECT 
    -          `id_cms` 
    -        FROM 
    -          `PREFIX_cms` 
    -        WHERE 
    -          `id_cms` = 3
    -      ), 
    -      0
    -    ), 
    -    NOW(), 
    -    NOW()
    -  )
    - -
    CREATE TEMPORARY TABLE `PREFIX_configuration_tmp` (`value` text)
    - -
    SET 
    -  @defaultOOS = (
    -    SELECT 
    -      value 
    -    FROM 
    -      `PREFIX_configuration` 
    -    WHERE 
    -      name = 'PS_ORDER_OUT_OF_STOCK'
    -  )
    - -
    UPDATE 
    -  `PREFIX_product` p 
    -SET 
    -  `cache_default_attribute` = 0 
    -WHERE 
    -  `id_product` NOT IN (
    -    SELECT 
    -      `id_product` 
    -    FROM 
    -      `PREFIX_product_attribute`
    -  )
    - -
    INSERT INTO `PREFIX_hook` (
    -  `name`, `title`, `description`, `position`
    -) 
    -VALUES 
    -  (
    -    'processCarrier', 'Carrier Process', 
    -    NULL, 0
    -  )
    - -
    INSERT INTO `PREFIX_stock_mvt_reason_lang` (
    -  `id_stock_mvt_reason`, `id_lang`, 
    -  `name`
    -) 
    -VALUES 
    -  (1, 1, 'Order'), 
    -  (1, 2, 'Commande'), 
    -  (2, 1, 'Missing Stock Movement'), 
    -  (
    -    2, 2, 'Mouvement de stock manquant'
    -  ), 
    -  (3, 1, 'Restocking'), 
    -  (3, 2, 'Réassort')
    - -
    INSERT INTO `PREFIX_meta_lang` (
    -  `id_lang`, `id_meta`, `title`, `url_rewrite`
    -) 
    -VALUES 
    -  (
    -    1, 
    -    (
    -      SELECT 
    -        `id_meta` 
    -      FROM 
    -        `PREFIX_meta` 
    -      WHERE 
    -        `page` = 'authentication'
    -    ), 
    -    'Authentication', 
    -    'authentication'
    -  ), 
    -  (
    -    2, 
    -    (
    -      SELECT 
    -        `id_meta` 
    -      FROM 
    -        `PREFIX_meta` 
    -      WHERE 
    -        `page` = 'authentication'
    -    ), 
    -    'Authentification', 
    -    'authentification'
    -  ), 
    -  (
    -    3, 
    -    (
    -      SELECT 
    -        `id_meta` 
    -      FROM 
    -        `PREFIX_meta` 
    -      WHERE 
    -        `page` = 'authentication'
    -    ), 
    -    'Autenticación', 
    -    'autenticacion'
    -  )
    - -
    LOCK TABLES `admin_assert` WRITE
    - -
    UNLOCK TABLES
    - -
    DROP 
    -  TABLE IF EXISTS `admin_role`
    - -
    SELECT 
    -  * 
    -FROM 
    -  -- This is another comment
    -  MyTable # One final comment
    -  
    -  /* This is a block comment 
    -  */
    -WHERE 
    -  1 = 2;
    - -
    SELECT 
    -  -- This is a test
    - -
    SELECT 
    -  Test 
    -FROM 
    -  Test 
    -WHERE 
    -  (MyColumn = 1)
    -)
    -AND (
    -  (
    -    (SomeOtherColumn = 2); 
    -WARNING: unclosed parentheses or section
    - -
    SELECT 
    -  * 
    -LIMIT 
    -  1; 
    -SELECT 
    -  a, 
    -  b, 
    -  c, 
    -  d 
    -FROM 
    -  e 
    -LIMIT 
    -  1, 2; 
    -SELECT 
    -  1, 
    -  2, 
    -  3 
    -WHERE 
    -  a in (1, 2, 3, 4, 5) 
    -  and b = 5;
    - -
    SELECT 
    -  count - 50 
    -WHERE 
    -  a - 50 = b 
    -WHERE 
    -  1 
    -  and -50 
    -WHERE 
    -  -50 = a 
    -WHERE 
    -  a = -50 
    -WHERE 
    -  1 
    -  /*test*/
    -  -50 
    -WHERE 
    -  1 
    -  and -50;
    - -
    SELECT 
    -  @ 
    -  and b;
    - -
    SELECT 
    -  @"weird variable name";
    - -
    SELECT 
    -  "no closing quote
    -
    \ No newline at end of file diff --git a/vendor/jdorn/sql-formatter/tests/format.html b/vendor/jdorn/sql-formatter/tests/format.html deleted file mode 100644 index dcbac03..0000000 --- a/vendor/jdorn/sql-formatter/tests/format.html +++ /dev/null @@ -1,807 +0,0 @@ -SELECT - customer_id, - customer_name, - COUNT(order_id) as total -FROM - customers - INNER JOIN orders ON customers.customer_id = orders.customer_id -GROUP BY - customer_id, - customer_name -HAVING - COUNT(order_id) > 5 -ORDER BY - COUNT(order_id) DESC; - -UPDATE - customers -SET - totalorders = ordersummary.total -FROM - ( - SELECT - customer_id, - count(order_id) As total - FROM - orders - GROUP BY - customer_id - ) As ordersummary -WHERE - customers.customer_id = ordersummary.customer_id - -SELECT - * -FROM - sometable -UNION ALL -SELECT - * -FROM - someothertable; - -SET - NAMES 'utf8'; - -CREATE TABLE `PREFIX_address` ( - `id_address` int(10) unsigned NOT NULL auto_increment, - `id_country` int(10) unsigned NOT NULL, - `id_state` int(10) unsigned default NULL, - `id_customer` int(10) unsigned NOT NULL default '0', - `id_manufacturer` int(10) unsigned NOT NULL default '0', - `id_supplier` int(10) unsigned NOT NULL default '0', - `id_warehouse` int(10) unsigned NOT NULL default '0', - `alias` varchar(32) NOT NULL, - `company` varchar(64) default NULL, - `lastname` varchar(32) NOT NULL, - `firstname` varchar(32) NOT NULL, - `address1` varchar(128) NOT NULL, - `address2` varchar(128) default NULL, - `postcode` varchar(12) default NULL, - `city` varchar(64) NOT NULL, - `other` text, - `phone` varchar(16) default NULL, - `phone_mobile` varchar(16) default NULL, - `vat_number` varchar(32) default NULL, - `dni` varchar(16) DEFAULT NULL, - `date_add` datetime NOT NULL, - `date_upd` datetime NOT NULL, - `active` tinyint(1) unsigned NOT NULL default '1', - `deleted` tinyint(1) unsigned NOT NULL default '0', - PRIMARY KEY (`id_address`), - KEY `address_customer` (`id_customer`), - KEY `id_country` (`id_country`), - KEY `id_state` (`id_state`), - KEY `id_manufacturer` (`id_manufacturer`), - KEY `id_supplier` (`id_supplier`), - KEY `id_warehouse` (`id_warehouse`) -) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 - -CREATE TABLE `PREFIX_alias` ( - `id_alias` int(10) unsigned NOT NULL auto_increment, - `alias` varchar(255) NOT NULL, - `search` varchar(255) NOT NULL, - `active` tinyint(1) NOT NULL default '1', - PRIMARY KEY (`id_alias`), - UNIQUE KEY `alias` (`alias`) -) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 - -CREATE TABLE `PREFIX_carrier` ( - `id_carrier` int(10) unsigned NOT NULL AUTO_INCREMENT, - `id_reference` int(10) unsigned NOT NULL, - `id_tax_rules_group` int(10) unsigned DEFAULT '0', - `name` varchar(64) NOT NULL, - `url` varchar(255) DEFAULT NULL, - `active` tinyint(1) unsigned NOT NULL DEFAULT '0', - `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0', - `shipping_handling` tinyint(1) unsigned NOT NULL DEFAULT '1', - `range_behavior` tinyint(1) unsigned NOT NULL DEFAULT '0', - `is_module` tinyint(1) unsigned NOT NULL DEFAULT '0', - `is_free` tinyint(1) unsigned NOT NULL DEFAULT '0', - `shipping_external` tinyint(1) unsigned NOT NULL DEFAULT '0', - `need_range` tinyint(1) unsigned NOT NULL DEFAULT '0', - `external_module_name` varchar(64) DEFAULT NULL, - `shipping_method` int(2) NOT NULL DEFAULT '0', - `position` int(10) unsigned NOT NULL default '0', - `max_width` int(10) DEFAULT 0, - `max_height` int(10) DEFAULT 0, - `max_depth` int(10) DEFAULT 0, - `max_weight` int(10) DEFAULT 0, - `grade` int(10) DEFAULT 0, - PRIMARY KEY (`id_carrier`), - KEY `deleted` (`deleted`, `active`), - KEY `id_tax_rules_group` (`id_tax_rules_group`) -) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 - -CREATE TABLE IF NOT EXISTS `PREFIX_specific_price_rule` ( - `id_specific_price_rule` int(10) unsigned NOT NULL AUTO_INCREMENT, - `name` VARCHAR(255) NOT NULL, - `id_shop` int(11) unsigned NOT NULL DEFAULT '1', - `id_currency` int(10) unsigned NOT NULL, - `id_country` int(10) unsigned NOT NULL, - `id_group` int(10) unsigned NOT NULL, - `from_quantity` mediumint(8) unsigned NOT NULL, - `price` DECIMAL(20, 6), - `reduction` decimal(20, 6) NOT NULL, - `reduction_type` enum('amount', 'percentage') NOT NULL, - `from` datetime NOT NULL, - `to` datetime NOT NULL, - PRIMARY KEY (`id_specific_price_rule`), - KEY `id_product` ( - `id_shop`, `id_currency`, `id_country`, - `id_group`, `from_quantity`, `from`, - `to` - ) -) ENGINE = ENGINE_TYPE DEFAULT CHARSET = utf8 - -UPDATE - `PREFIX_configuration` -SET - value = '6' -WHERE - name = 'PS_SEARCH_WEIGHT_PNAME' - -UPDATE - `PREFIX_hook_module` -SET - position = 1 -WHERE - id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayPayment' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'cheque' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayPaymentReturn' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'cheque' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayHome' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'homeslider' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionAuthentication' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'statsdata' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionShopDataDuplication' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'homeslider' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayTop' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blocklanguages' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionCustomerAccountAdd' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'statsdata' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayCustomerAccount' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'favoriteproducts' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayAdminStatsModules' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'statsvisits' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayAdminStatsGraphEngine' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'graphvisifire' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayAdminStatsGridEngine' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'gridhtml' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayLeftColumnProduct' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blocksharefb' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionSearch' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'statssearch' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionCategoryAdd' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blockcategories' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionCategoryUpdate' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blockcategories' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionCategoryDelete' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blockcategories' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'actionAdminMetaSave' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blockcategories' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayMyAccountBlock' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'favoriteproducts' - ) - OR id_hook = ( - SELECT - id_hook - FROM - `PREFIX_hook` - WHERE - name = 'displayFooter' - ) - AND id_module = ( - SELECT - id_module - FROM - `PREFIX_module` - WHERE - name = 'blockreinsurance' - ) - -ALTER TABLE - `PREFIX_employee` -ADD - `bo_color` varchar(32) default NULL -AFTER - `stats_date_to` - -INSERT INTO `PREFIX_cms_category_lang` -VALUES - ( - 1, 3, 'Inicio', '', 'home', NULL, NULL, - NULL - ) - -INSERT INTO `PREFIX_cms_category` -VALUES - (1, 0, 0, 1, NOW(), NOW(), 0) - -UPDATE - `PREFIX_cms_category` -SET - `position` = 0 - -ALTER TABLE - `PREFIX_customer` -ADD - `note` text -AFTER - `secure_key` - -ALTER TABLE - `PREFIX_contact` -ADD - `customer_service` tinyint(1) NOT NULL DEFAULT 0 -AFTER - `email` - -INSERT INTO `PREFIX_specific_price` ( - `id_product`, `id_shop`, `id_currency`, - `id_country`, `id_group`, `priority`, - `price`, `from_quantity`, `reduction`, - `reduction_type`, `from`, `to` -) ( - SELECT - dq.`id_product`, - 1, - 1, - 0, - 1, - 0, - 0.00, - dq.`quantity`, - IF( - dq.`id_discount_type` = 2, dq.`value`, - dq.`value` / 100 - ), - IF ( - dq.`id_discount_type` = 2, 'amount', - 'percentage' - ), - '0000-00-00 00:00:00', - '0000-00-00 00:00:00' - FROM - `PREFIX_discount_quantity` dq - INNER JOIN `PREFIX_product` p ON (p.`id_product` = dq.`id_product`) -) - -DROP - TABLE `PREFIX_discount_quantity` - -INSERT INTO `PREFIX_specific_price` ( - `id_product`, `id_shop`, `id_currency`, - `id_country`, `id_group`, `priority`, - `price`, `from_quantity`, `reduction`, - `reduction_type`, `from`, `to` -) ( - SELECT - p.`id_product`, - 1, - 0, - 0, - 0, - 0, - 0.00, - 1, - IF( - p.`reduction_price` > 0, p.`reduction_price`, - p.`reduction_percent` / 100 - ), - IF( - p.`reduction_price` > 0, 'amount', - 'percentage' - ), - IF ( - p.`reduction_from` = p.`reduction_to`, - '0000-00-00 00:00:00', p.`reduction_from` - ), - IF ( - p.`reduction_from` = p.`reduction_to`, - '0000-00-00 00:00:00', p.`reduction_to` - ) - FROM - `PREFIX_product` p - WHERE - p.`reduction_price` - OR p.`reduction_percent` -) - -ALTER TABLE - `PREFIX_product` -DROP - `reduction_price`, -DROP - `reduction_percent`, -DROP - `reduction_from`, -DROP - `reduction_to` - -INSERT INTO `PREFIX_configuration` ( - `name`, `value`, `date_add`, `date_upd` -) -VALUES - ( - 'PS_SPECIFIC_PRICE_PRIORITIES', - 'id_shop;id_currency;id_country;id_group', - NOW(), NOW() - ), - ('PS_TAX_DISPLAY', 0, NOW(), NOW()), - ( - 'PS_SMARTY_FORCE_COMPILE', 1, NOW(), - NOW() - ), - ( - 'PS_DISTANCE_UNIT', 'km', NOW(), NOW() - ), - ( - 'PS_STORES_DISPLAY_CMS', 0, NOW(), - NOW() - ), - ( - 'PS_STORES_DISPLAY_FOOTER', 0, NOW(), - NOW() - ), - ( - 'PS_STORES_SIMPLIFIED', 0, NOW(), - NOW() - ), - ( - 'PS_STATSDATA_CUSTOMER_PAGESVIEWS', - 1, NOW(), NOW() - ), - ( - 'PS_STATSDATA_PAGESVIEWS', 1, NOW(), - NOW() - ), - ( - 'PS_STATSDATA_PLUGINS', 1, NOW(), - NOW() - ) - -INSERT INTO `PREFIX_configuration` ( - `name`, `value`, `date_add`, `date_upd` -) -VALUES - ( - 'PS_CONDITIONS_CMS_ID', - IFNULL( - ( - SELECT - `id_cms` - FROM - `PREFIX_cms` - WHERE - `id_cms` = 3 - ), - 0 - ), - NOW(), - NOW() - ) - -CREATE TEMPORARY TABLE `PREFIX_configuration_tmp` (`value` text) - -SET - @defaultOOS = ( - SELECT - value - FROM - `PREFIX_configuration` - WHERE - name = 'PS_ORDER_OUT_OF_STOCK' - ) - -UPDATE - `PREFIX_product` p -SET - `cache_default_attribute` = 0 -WHERE - `id_product` NOT IN ( - SELECT - `id_product` - FROM - `PREFIX_product_attribute` - ) - -INSERT INTO `PREFIX_hook` ( - `name`, `title`, `description`, `position` -) -VALUES - ( - 'processCarrier', 'Carrier Process', - NULL, 0 - ) - -INSERT INTO `PREFIX_stock_mvt_reason_lang` ( - `id_stock_mvt_reason`, `id_lang`, - `name` -) -VALUES - (1, 1, 'Order'), - (1, 2, 'Commande'), - (2, 1, 'Missing Stock Movement'), - ( - 2, 2, 'Mouvement de stock manquant' - ), - (3, 1, 'Restocking'), - (3, 2, 'Réassort') - -INSERT INTO `PREFIX_meta_lang` ( - `id_lang`, `id_meta`, `title`, `url_rewrite` -) -VALUES - ( - 1, - ( - SELECT - `id_meta` - FROM - `PREFIX_meta` - WHERE - `page` = 'authentication' - ), - 'Authentication', - 'authentication' - ), - ( - 2, - ( - SELECT - `id_meta` - FROM - `PREFIX_meta` - WHERE - `page` = 'authentication' - ), - 'Authentification', - 'authentification' - ), - ( - 3, - ( - SELECT - `id_meta` - FROM - `PREFIX_meta` - WHERE - `page` = 'authentication' - ), - 'Autenticación', - 'autenticacion' - ) - -LOCK TABLES `admin_assert` WRITE - -UNLOCK TABLES - -DROP - TABLE IF EXISTS `admin_role` - -SELECT - * -FROM - -- This is another comment - MyTable # One final comment - - /* This is a block comment - */ -WHERE - 1 = 2; - -SELECT - -- This is a test - -SELECT - Test -FROM - Test -WHERE - (MyColumn = 1) -) -AND ( - ( - (SomeOtherColumn = 2); - -SELECT - * -LIMIT - 1; -SELECT - a, - b, - c, - d -FROM - e -LIMIT - 1, 2; -SELECT - 1, - 2, - 3 -WHERE - a in (1, 2, 3, 4, 5) - and b = 5; - -SELECT - count - 50 -WHERE - a - 50 = b -WHERE - 1 - and -50 -WHERE - -50 = a -WHERE - a = -50 -WHERE - 1 - /*test*/ - -50 -WHERE - 1 - and -50; - -SELECT - @ - and b; - -SELECT - @"weird variable name"; - -SELECT - "no closing quote \ No newline at end of file diff --git a/vendor/jdorn/sql-formatter/tests/highlight.html b/vendor/jdorn/sql-formatter/tests/highlight.html deleted file mode 100644 index e26af9a..0000000 --- a/vendor/jdorn/sql-formatter/tests/highlight.html +++ /dev/null @@ -1,262 +0,0 @@ -
    SELECT customer_id, customer_name, COUNT(order_id) as total
    -FROM customers INNER JOIN orders ON customers.customer_id = orders.customer_id
    -GROUP BY customer_id, customer_name
    -HAVING COUNT(order_id) > 5
    -ORDER BY COUNT(order_id) DESC;
    - -
    UPDATE customers
    -        SET totalorders = ordersummary.total
    -        FROM (SELECT customer_id, count(order_id) As total 
    -FROM orders GROUP BY customer_id) As ordersummary
    -        WHERE customers.customer_id = ordersummary.customer_id
    - -
    SELECT * FROM sometable
    -UNION ALL
    -SELECT * FROM someothertable;
    - -
    SET NAMES 'utf8';
    - -
    CREATE TABLE `PREFIX_address` (
    -  `id_address` int(10) unsigned NOT NULL auto_increment,
    -  `id_country` int(10) unsigned NOT NULL,
    -  `id_state` int(10) unsigned default NULL,
    -  `id_customer` int(10) unsigned NOT NULL default '0',
    -  `id_manufacturer` int(10) unsigned NOT NULL default '0',
    -  `id_supplier` int(10) unsigned NOT NULL default '0',
    -  `id_warehouse` int(10) unsigned NOT NULL default '0',
    -  `alias` varchar(32) NOT NULL,
    -  `company` varchar(64) default NULL,
    -  `lastname` varchar(32) NOT NULL,
    -  `firstname` varchar(32) NOT NULL,
    -  `address1` varchar(128) NOT NULL,
    -  `address2` varchar(128) default NULL,
    -  `postcode` varchar(12) default NULL,
    -  `city` varchar(64) NOT NULL,
    -  `other` text,
    -  `phone` varchar(16) default NULL,
    -  `phone_mobile` varchar(16) default NULL,
    -  `vat_number` varchar(32) default NULL,
    -  `dni` varchar(16) DEFAULT NULL,
    -  `date_add` datetime NOT NULL,
    -  `date_upd` datetime NOT NULL,
    -  `active` tinyint(1) unsigned NOT NULL default '1',
    -  `deleted` tinyint(1) unsigned NOT NULL default '0',
    -  PRIMARY KEY (`id_address`),
    -  KEY `address_customer` (`id_customer`),
    -  KEY `id_country` (`id_country`),
    -  KEY `id_state` (`id_state`),
    -  KEY `id_manufacturer` (`id_manufacturer`),
    -  KEY `id_supplier` (`id_supplier`),
    -  KEY `id_warehouse` (`id_warehouse`)
    -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8
    - -
    CREATE TABLE `PREFIX_alias` (
    -  `id_alias` int(10) unsigned NOT NULL auto_increment,
    -  `alias` varchar(255) NOT NULL,
    -  `search` varchar(255) NOT NULL,
    -  `active` tinyint(1) NOT NULL default '1',
    -  PRIMARY KEY (`id_alias`),
    -  UNIQUE KEY `alias` (`alias`)
    -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8
    - -
    CREATE TABLE `PREFIX_carrier` (
    -  `id_carrier` int(10) unsigned NOT NULL AUTO_INCREMENT,
    -  `id_reference` int(10) unsigned NOT NULL,
    -  `id_tax_rules_group` int(10) unsigned DEFAULT '0',
    -  `name` varchar(64) NOT NULL,
    -  `url` varchar(255) DEFAULT NULL,
    -  `active` tinyint(1) unsigned NOT NULL DEFAULT '0',
    -  `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0',
    -  `shipping_handling` tinyint(1) unsigned NOT NULL DEFAULT '1',
    -  `range_behavior` tinyint(1) unsigned NOT NULL DEFAULT '0',
    -  `is_module` tinyint(1) unsigned NOT NULL DEFAULT '0',
    -  `is_free` tinyint(1) unsigned NOT NULL DEFAULT '0',
    -  `shipping_external` tinyint(1) unsigned NOT NULL DEFAULT '0',
    -  `need_range` tinyint(1) unsigned NOT NULL DEFAULT '0',
    -  `external_module_name` varchar(64) DEFAULT NULL,
    -  `shipping_method` int(2) NOT NULL DEFAULT '0',
    -  `position` int(10) unsigned NOT NULL default '0',
    -  `max_width` int(10) DEFAULT 0,
    -  `max_height` int(10)  DEFAULT 0,
    -  `max_depth` int(10)  DEFAULT 0,
    -  `max_weight` int(10)  DEFAULT 0,
    -  `grade` int(10)  DEFAULT 0,
    -  PRIMARY KEY (`id_carrier`),
    -  KEY `deleted` (`deleted`,`active`),
    -  KEY `id_tax_rules_group` (`id_tax_rules_group`)
    -) ENGINE=ENGINE_TYPE  DEFAULT CHARSET=utf8
    - -
    CREATE TABLE IF NOT EXISTS `PREFIX_specific_price_rule` (
    -	`id_specific_price_rule` int(10) unsigned NOT NULL AUTO_INCREMENT,
    -	`name` VARCHAR(255) NOT NULL,
    -	`id_shop` int(11) unsigned NOT NULL DEFAULT '1',
    -	`id_currency` int(10) unsigned NOT NULL,
    -	`id_country` int(10) unsigned NOT NULL,
    -	`id_group` int(10) unsigned NOT NULL,
    -	`from_quantity` mediumint(8) unsigned NOT NULL,
    -	`price` DECIMAL(20,6),
    -	`reduction` decimal(20,6) NOT NULL,
    -	`reduction_type` enum('amount','percentage') NOT NULL,
    -	`from` datetime NOT NULL,
    -	`to` datetime NOT NULL,
    -	PRIMARY KEY (`id_specific_price_rule`),
    -	KEY `id_product` (`id_shop`,`id_currency`,`id_country`,`id_group`,`from_quantity`,`from`,`to`)
    -) ENGINE=ENGINE_TYPE  DEFAULT CHARSET=utf8
    - -
    UPDATE `PREFIX_configuration` SET value = '6' WHERE name = 'PS_SEARCH_WEIGHT_PNAME'
    - -
    UPDATE `PREFIX_hook_module` SET position = 1
    -WHERE
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayPayment') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'cheque')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayPaymentReturn') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'cheque')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayHome') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'homeslider')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionAuthentication') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsdata')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionShopDataDuplication') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'homeslider')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayTop') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blocklanguages')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCustomerAccountAdd') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsdata')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayCustomerAccount') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'favoriteproducts')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsModules') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsvisits')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsGraphEngine') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'graphvisifire')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsGridEngine') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'gridhtml')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayLeftColumnProduct') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blocksharefb')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionSearch') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statssearch')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryAdd') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryUpdate') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryDelete') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionAdminMetaSave') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayMyAccountBlock') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'favoriteproducts')
    -	OR
    -	id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayFooter') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockreinsurance')
    - -
    ALTER TABLE `PREFIX_employee` ADD `bo_color` varchar(32) default NULL AFTER `stats_date_to`
    - -
    INSERT INTO `PREFIX_cms_category_lang` VALUES(1, 3, 'Inicio', '', 'home', NULL, NULL, NULL)
    - -
    INSERT INTO `PREFIX_cms_category` VALUES(1, 0, 0, 1, NOW(), NOW(),0)
    - -
    UPDATE `PREFIX_cms_category` SET `position` = 0
    - -
    ALTER TABLE `PREFIX_customer` ADD `note` text AFTER `secure_key`
    - -
    ALTER TABLE `PREFIX_contact` ADD `customer_service` tinyint(1) NOT NULL DEFAULT 0 AFTER `email`
    - -
    INSERT INTO `PREFIX_specific_price` (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `priority`, `price`, `from_quantity`, `reduction`, `reduction_type`, `from`, `to`)
    -	(	SELECT dq.`id_product`, 1, 1, 0, 1, 0, 0.00, dq.`quantity`, IF(dq.`id_discount_type` = 2, dq.`value`, dq.`value` / 100), IF (dq.`id_discount_type` = 2, 'amount', 'percentage'), '0000-00-00 00:00:00', '0000-00-00 00:00:00'
    -		FROM `PREFIX_discount_quantity` dq
    -		INNER JOIN `PREFIX_product` p ON (p.`id_product` = dq.`id_product`)
    -	)
    - -
    DROP TABLE `PREFIX_discount_quantity`
    - -
    INSERT INTO `PREFIX_specific_price` (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `priority`, `price`, `from_quantity`, `reduction`, `reduction_type`, `from`, `to`) (
    -	SELECT
    -		p.`id_product`,
    -		1,
    -		0,
    -		0,
    -		0,
    -		0,
    -		0.00,
    -		1,
    -		IF(p.`reduction_price` > 0, p.`reduction_price`, p.`reduction_percent` / 100),
    -		IF(p.`reduction_price` > 0, 'amount', 'percentage'),
    -		IF (p.`reduction_from` = p.`reduction_to`, '0000-00-00 00:00:00', p.`reduction_from`),
    -		IF (p.`reduction_from` = p.`reduction_to`, '0000-00-00 00:00:00', p.`reduction_to`)
    -	FROM `PREFIX_product` p
    -	WHERE p.`reduction_price` OR p.`reduction_percent`
    -)
    - -
    ALTER TABLE `PREFIX_product`
    -	DROP `reduction_price`,
    -	DROP `reduction_percent`,
    -	DROP `reduction_from`,
    -	DROP `reduction_to`
    - -
    INSERT INTO `PREFIX_configuration` (`name`, `value`, `date_add`, `date_upd`) VALUES
    -('PS_SPECIFIC_PRICE_PRIORITIES', 'id_shop;id_currency;id_country;id_group', NOW(), NOW()),
    -('PS_TAX_DISPLAY', 0, NOW(), NOW()),
    -('PS_SMARTY_FORCE_COMPILE', 1, NOW(), NOW()),
    -('PS_DISTANCE_UNIT', 'km', NOW(), NOW()),
    -('PS_STORES_DISPLAY_CMS', 0, NOW(), NOW()),
    -('PS_STORES_DISPLAY_FOOTER', 0, NOW(), NOW()),
    -('PS_STORES_SIMPLIFIED', 0, NOW(), NOW()),
    -('PS_STATSDATA_CUSTOMER_PAGESVIEWS', 1, NOW(), NOW()),
    -('PS_STATSDATA_PAGESVIEWS', 1, NOW(), NOW()),
    -('PS_STATSDATA_PLUGINS', 1, NOW(), NOW())
    - -
    INSERT INTO `PREFIX_configuration` (`name`, `value`, `date_add`, `date_upd`) VALUES ('PS_CONDITIONS_CMS_ID', IFNULL((SELECT `id_cms` FROM `PREFIX_cms` WHERE `id_cms` = 3), 0), NOW(), NOW())
    - -
    CREATE TEMPORARY TABLE `PREFIX_configuration_tmp` (
    -	`value` text
    -)
    - -
    SET @defaultOOS = (SELECT value FROM `PREFIX_configuration` WHERE name = 'PS_ORDER_OUT_OF_STOCK')
    - -
    UPDATE `PREFIX_product` p SET `cache_default_attribute` =  0 WHERE `id_product` NOT IN (SELECT `id_product` FROM `PREFIX_product_attribute`)
    - -
    INSERT INTO `PREFIX_hook` (`name`, `title`, `description`, `position`) VALUES ('processCarrier', 'Carrier Process', NULL, 0)
    - -
    INSERT INTO `PREFIX_stock_mvt_reason_lang` (`id_stock_mvt_reason`, `id_lang`, `name`) VALUES
    -(1, 1, 'Order'),
    -(1, 2, 'Commande'),
    -(2, 1, 'Missing Stock Movement'),
    -(2, 2, 'Mouvement de stock manquant'),
    -(3, 1, 'Restocking'),
    -(3, 2, 'Réassort')
    - -
    INSERT INTO `PREFIX_meta_lang` (`id_lang`, `id_meta`, `title`, `url_rewrite`) VALUES
    -(1, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Authentication', 'authentication'),
    -(2, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Authentification', 'authentification'),
    -(3, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Autenticación', 'autenticacion')
    - -
    LOCK TABLES `admin_assert` WRITE
    - -
    UNLOCK TABLES
    - -
    DROP TABLE IF EXISTS `admin_role`
    - -
    SELECT * FROM
    --- This is another comment
    -MyTable # One final comment
    -/* This is a block comment 
    -*/ WHERE 1 = 2;
    - -
    SELECT -- This is a test
    - -
    SELECT Test FROM Test WHERE
    -(
    - MyColumn = 1 )) AND ((( SomeOtherColumn = 2);
    - -
    SELECT * LIMIT 1; SELECT a,b,c,d FROM e LIMIT 1, 2; SELECT 1,2,3 WHERE a in (1,2,3,4,5) and b=5;
    - -
    SELECT count - 50
    -WHERE a-50 = b
    -WHERE 1 and - 50
    -WHERE -50 = a
    -WHERE a = -50
    -WHERE 1 /*test*/ - 50
    -WHERE 1 and -50;
    - -
    SELECT @ and b;
    - -
    SELECT @"weird variable name";
    - -
    SELECT "no closing quote
    -
    \ No newline at end of file diff --git a/vendor/jdorn/sql-formatter/tests/performance.php b/vendor/jdorn/sql-formatter/tests/performance.php deleted file mode 100644 index 6c9eb97..0000000 --- a/vendor/jdorn/sql-formatter/tests/performance.php +++ /dev/null @@ -1,44 +0,0 @@ -Formatted ".$num." queries using a max_cachekey_size of ".SqlFormatter::$max_cachekey_size."

    "; - -echo "

    Average query length of ".number_format($chars/$num,5)." characters

    "; - -echo "

    Took ".number_format($end-$start,5)." seconds total, ".number_format(($end-$start)/$num,5)." seconds per query, ".number_format(1000*($end-$start)/$chars,5)." seconds per 1000 characters

    "; - -echo "

    Used ".number_format($uend-$ustart)." bytes of memory

    "; - -echo "

    Cache Stats

    ".print_r(SqlFormatter::getCacheStats(),true)."
    "; - diff --git a/vendor/jdorn/sql-formatter/tests/sql.sql b/vendor/jdorn/sql-formatter/tests/sql.sql deleted file mode 100644 index 4e2d988..0000000 --- a/vendor/jdorn/sql-formatter/tests/sql.sql +++ /dev/null @@ -1,261 +0,0 @@ -SELECT customer_id, customer_name, COUNT(order_id) as total -FROM customers INNER JOIN orders ON customers.customer_id = orders.customer_id -GROUP BY customer_id, customer_name -HAVING COUNT(order_id) > 5 -ORDER BY COUNT(order_id) DESC; - -UPDATE customers - SET totalorders = ordersummary.total - FROM (SELECT customer_id, count(order_id) As total -FROM orders GROUP BY customer_id) As ordersummary - WHERE customers.customer_id = ordersummary.customer_id - -SELECT * FROM sometable -UNION ALL -SELECT * FROM someothertable; - -SET NAMES 'utf8'; - -CREATE TABLE `PREFIX_address` ( - `id_address` int(10) unsigned NOT NULL auto_increment, - `id_country` int(10) unsigned NOT NULL, - `id_state` int(10) unsigned default NULL, - `id_customer` int(10) unsigned NOT NULL default '0', - `id_manufacturer` int(10) unsigned NOT NULL default '0', - `id_supplier` int(10) unsigned NOT NULL default '0', - `id_warehouse` int(10) unsigned NOT NULL default '0', - `alias` varchar(32) NOT NULL, - `company` varchar(64) default NULL, - `lastname` varchar(32) NOT NULL, - `firstname` varchar(32) NOT NULL, - `address1` varchar(128) NOT NULL, - `address2` varchar(128) default NULL, - `postcode` varchar(12) default NULL, - `city` varchar(64) NOT NULL, - `other` text, - `phone` varchar(16) default NULL, - `phone_mobile` varchar(16) default NULL, - `vat_number` varchar(32) default NULL, - `dni` varchar(16) DEFAULT NULL, - `date_add` datetime NOT NULL, - `date_upd` datetime NOT NULL, - `active` tinyint(1) unsigned NOT NULL default '1', - `deleted` tinyint(1) unsigned NOT NULL default '0', - PRIMARY KEY (`id_address`), - KEY `address_customer` (`id_customer`), - KEY `id_country` (`id_country`), - KEY `id_state` (`id_state`), - KEY `id_manufacturer` (`id_manufacturer`), - KEY `id_supplier` (`id_supplier`), - KEY `id_warehouse` (`id_warehouse`) -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 - -CREATE TABLE `PREFIX_alias` ( - `id_alias` int(10) unsigned NOT NULL auto_increment, - `alias` varchar(255) NOT NULL, - `search` varchar(255) NOT NULL, - `active` tinyint(1) NOT NULL default '1', - PRIMARY KEY (`id_alias`), - UNIQUE KEY `alias` (`alias`) -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 - -CREATE TABLE `PREFIX_carrier` ( - `id_carrier` int(10) unsigned NOT NULL AUTO_INCREMENT, - `id_reference` int(10) unsigned NOT NULL, - `id_tax_rules_group` int(10) unsigned DEFAULT '0', - `name` varchar(64) NOT NULL, - `url` varchar(255) DEFAULT NULL, - `active` tinyint(1) unsigned NOT NULL DEFAULT '0', - `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0', - `shipping_handling` tinyint(1) unsigned NOT NULL DEFAULT '1', - `range_behavior` tinyint(1) unsigned NOT NULL DEFAULT '0', - `is_module` tinyint(1) unsigned NOT NULL DEFAULT '0', - `is_free` tinyint(1) unsigned NOT NULL DEFAULT '0', - `shipping_external` tinyint(1) unsigned NOT NULL DEFAULT '0', - `need_range` tinyint(1) unsigned NOT NULL DEFAULT '0', - `external_module_name` varchar(64) DEFAULT NULL, - `shipping_method` int(2) NOT NULL DEFAULT '0', - `position` int(10) unsigned NOT NULL default '0', - `max_width` int(10) DEFAULT 0, - `max_height` int(10) DEFAULT 0, - `max_depth` int(10) DEFAULT 0, - `max_weight` int(10) DEFAULT 0, - `grade` int(10) DEFAULT 0, - PRIMARY KEY (`id_carrier`), - KEY `deleted` (`deleted`,`active`), - KEY `id_tax_rules_group` (`id_tax_rules_group`) -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 - -CREATE TABLE IF NOT EXISTS `PREFIX_specific_price_rule` ( - `id_specific_price_rule` int(10) unsigned NOT NULL AUTO_INCREMENT, - `name` VARCHAR(255) NOT NULL, - `id_shop` int(11) unsigned NOT NULL DEFAULT '1', - `id_currency` int(10) unsigned NOT NULL, - `id_country` int(10) unsigned NOT NULL, - `id_group` int(10) unsigned NOT NULL, - `from_quantity` mediumint(8) unsigned NOT NULL, - `price` DECIMAL(20,6), - `reduction` decimal(20,6) NOT NULL, - `reduction_type` enum('amount','percentage') NOT NULL, - `from` datetime NOT NULL, - `to` datetime NOT NULL, - PRIMARY KEY (`id_specific_price_rule`), - KEY `id_product` (`id_shop`,`id_currency`,`id_country`,`id_group`,`from_quantity`,`from`,`to`) -) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8 - -UPDATE `PREFIX_configuration` SET value = '6' WHERE name = 'PS_SEARCH_WEIGHT_PNAME' - -UPDATE `PREFIX_hook_module` SET position = 1 -WHERE - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayPayment') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'cheque') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayPaymentReturn') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'cheque') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayHome') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'homeslider') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionAuthentication') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsdata') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionShopDataDuplication') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'homeslider') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayTop') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blocklanguages') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCustomerAccountAdd') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsdata') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayCustomerAccount') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'favoriteproducts') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsModules') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statsvisits') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsGraphEngine') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'graphvisifire') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayAdminStatsGridEngine') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'gridhtml') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayLeftColumnProduct') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blocksharefb') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionSearch') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'statssearch') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryAdd') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryUpdate') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionCategoryDelete') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'actionAdminMetaSave') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockcategories') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayMyAccountBlock') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'favoriteproducts') - OR - id_hook = (SELECT id_hook FROM `PREFIX_hook` WHERE name = 'displayFooter') AND id_module = (SELECT id_module FROM `PREFIX_module` WHERE name = 'blockreinsurance') - -ALTER TABLE `PREFIX_employee` ADD `bo_color` varchar(32) default NULL AFTER `stats_date_to` - -INSERT INTO `PREFIX_cms_category_lang` VALUES(1, 3, 'Inicio', '', 'home', NULL, NULL, NULL) - -INSERT INTO `PREFIX_cms_category` VALUES(1, 0, 0, 1, NOW(), NOW(),0) - -UPDATE `PREFIX_cms_category` SET `position` = 0 - -ALTER TABLE `PREFIX_customer` ADD `note` text AFTER `secure_key` - -ALTER TABLE `PREFIX_contact` ADD `customer_service` tinyint(1) NOT NULL DEFAULT 0 AFTER `email` - -INSERT INTO `PREFIX_specific_price` (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `priority`, `price`, `from_quantity`, `reduction`, `reduction_type`, `from`, `to`) - ( SELECT dq.`id_product`, 1, 1, 0, 1, 0, 0.00, dq.`quantity`, IF(dq.`id_discount_type` = 2, dq.`value`, dq.`value` / 100), IF (dq.`id_discount_type` = 2, 'amount', 'percentage'), '0000-00-00 00:00:00', '0000-00-00 00:00:00' - FROM `PREFIX_discount_quantity` dq - INNER JOIN `PREFIX_product` p ON (p.`id_product` = dq.`id_product`) - ) - -DROP TABLE `PREFIX_discount_quantity` - -INSERT INTO `PREFIX_specific_price` (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `priority`, `price`, `from_quantity`, `reduction`, `reduction_type`, `from`, `to`) ( - SELECT - p.`id_product`, - 1, - 0, - 0, - 0, - 0, - 0.00, - 1, - IF(p.`reduction_price` > 0, p.`reduction_price`, p.`reduction_percent` / 100), - IF(p.`reduction_price` > 0, 'amount', 'percentage'), - IF (p.`reduction_from` = p.`reduction_to`, '0000-00-00 00:00:00', p.`reduction_from`), - IF (p.`reduction_from` = p.`reduction_to`, '0000-00-00 00:00:00', p.`reduction_to`) - FROM `PREFIX_product` p - WHERE p.`reduction_price` OR p.`reduction_percent` -) - -ALTER TABLE `PREFIX_product` - DROP `reduction_price`, - DROP `reduction_percent`, - DROP `reduction_from`, - DROP `reduction_to` - -INSERT INTO `PREFIX_configuration` (`name`, `value`, `date_add`, `date_upd`) VALUES -('PS_SPECIFIC_PRICE_PRIORITIES', 'id_shop;id_currency;id_country;id_group', NOW(), NOW()), -('PS_TAX_DISPLAY', 0, NOW(), NOW()), -('PS_SMARTY_FORCE_COMPILE', 1, NOW(), NOW()), -('PS_DISTANCE_UNIT', 'km', NOW(), NOW()), -('PS_STORES_DISPLAY_CMS', 0, NOW(), NOW()), -('PS_STORES_DISPLAY_FOOTER', 0, NOW(), NOW()), -('PS_STORES_SIMPLIFIED', 0, NOW(), NOW()), -('PS_STATSDATA_CUSTOMER_PAGESVIEWS', 1, NOW(), NOW()), -('PS_STATSDATA_PAGESVIEWS', 1, NOW(), NOW()), -('PS_STATSDATA_PLUGINS', 1, NOW(), NOW()) - -INSERT INTO `PREFIX_configuration` (`name`, `value`, `date_add`, `date_upd`) VALUES ('PS_CONDITIONS_CMS_ID', IFNULL((SELECT `id_cms` FROM `PREFIX_cms` WHERE `id_cms` = 3), 0), NOW(), NOW()) - -CREATE TEMPORARY TABLE `PREFIX_configuration_tmp` ( - `value` text -) - -SET @defaultOOS = (SELECT value FROM `PREFIX_configuration` WHERE name = 'PS_ORDER_OUT_OF_STOCK') - -UPDATE `PREFIX_product` p SET `cache_default_attribute` = 0 WHERE `id_product` NOT IN (SELECT `id_product` FROM `PREFIX_product_attribute`) - -INSERT INTO `PREFIX_hook` (`name`, `title`, `description`, `position`) VALUES ('processCarrier', 'Carrier Process', NULL, 0) - -INSERT INTO `PREFIX_stock_mvt_reason_lang` (`id_stock_mvt_reason`, `id_lang`, `name`) VALUES -(1, 1, 'Order'), -(1, 2, 'Commande'), -(2, 1, 'Missing Stock Movement'), -(2, 2, 'Mouvement de stock manquant'), -(3, 1, 'Restocking'), -(3, 2, 'Réassort') - -INSERT INTO `PREFIX_meta_lang` (`id_lang`, `id_meta`, `title`, `url_rewrite`) VALUES -(1, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Authentication', 'authentication'), -(2, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Authentification', 'authentification'), -(3, (SELECT `id_meta` FROM `PREFIX_meta` WHERE `page` = 'authentication'), 'Autenticación', 'autenticacion') - -LOCK TABLES `admin_assert` WRITE - -UNLOCK TABLES - -DROP TABLE IF EXISTS `admin_role` - -SELECT * FROM --- This is another comment -MyTable # One final comment -/* This is a block comment -*/ WHERE 1 = 2; - -SELECT -- This is a test - -SELECT Test FROM Test WHERE -( - MyColumn = 1 )) AND ((( SomeOtherColumn = 2); - -SELECT * LIMIT 1; SELECT a,b,c,d FROM e LIMIT 1, 2; SELECT 1,2,3 WHERE a in (1,2,3,4,5) and b=5; - -SELECT count - 50 -WHERE a-50 = b -WHERE 1 and - 50 -WHERE -50 = a -WHERE a = -50 -WHERE 1 /*test*/ - 50 -WHERE 1 and -50; - -SELECT @ and b; - -SELECT @"weird variable name"; - -SELECT "no closing quote diff --git a/vendor/psr/cache/CHANGELOG.md b/vendor/psr/cache/CHANGELOG.md deleted file mode 100644 index 58ddab0..0000000 --- a/vendor/psr/cache/CHANGELOG.md +++ /dev/null @@ -1,16 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file, in reverse chronological order by release. - -## 1.0.1 - 2016-08-06 - -### Fixed - -- Make spacing consistent in phpdoc annotations php-fig/cache#9 - chalasr -- Fix grammar in phpdoc annotations php-fig/cache#10 - chalasr -- Be more specific in docblocks that `getItems()` and `deleteItems()` take an array of strings (`string[]`) compared to just `array` php-fig/cache#8 - GrahamCampbell -- For `expiresAt()` and `expiresAfter()` in CacheItemInterface fix docblock to specify null as a valid parameters as well as an implementation of DateTimeInterface php-fig/cache#7 - GrahamCampbell - -## 1.0.0 - 2015-12-11 - -Initial stable release; reflects accepted PSR-6 specification diff --git a/vendor/psr/cache/LICENSE.txt b/vendor/psr/cache/LICENSE.txt deleted file mode 100644 index b1c2c97..0000000 --- a/vendor/psr/cache/LICENSE.txt +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2015 PHP Framework Interoperability Group - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/psr/cache/README.md b/vendor/psr/cache/README.md deleted file mode 100644 index c8706ce..0000000 --- a/vendor/psr/cache/README.md +++ /dev/null @@ -1,9 +0,0 @@ -PSR Cache -========= - -This repository holds all interfaces defined by -[PSR-6](http://www.php-fig.org/psr/psr-6/). - -Note that this is not a Cache implementation of its own. It is merely an -interface that describes a Cache implementation. See the specification for more -details. diff --git a/vendor/psr/cache/composer.json b/vendor/psr/cache/composer.json deleted file mode 100644 index e828fec..0000000 --- a/vendor/psr/cache/composer.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "psr/cache", - "description": "Common interface for caching libraries", - "keywords": ["psr", "psr-6", "cache"], - "license": "MIT", - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "require": { - "php": ">=5.3.0" - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - } -} diff --git a/vendor/psr/cache/src/CacheException.php b/vendor/psr/cache/src/CacheException.php deleted file mode 100644 index e27f22f..0000000 --- a/vendor/psr/cache/src/CacheException.php +++ /dev/null @@ -1,10 +0,0 @@ -=5.3.0" - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - } -} diff --git a/vendor/psr/container/src/ContainerExceptionInterface.php b/vendor/psr/container/src/ContainerExceptionInterface.php deleted file mode 100644 index d35c6b4..0000000 --- a/vendor/psr/container/src/ContainerExceptionInterface.php +++ /dev/null @@ -1,13 +0,0 @@ -=7.2.0" - }, - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - } -} diff --git a/vendor/psr/event-dispatcher/src/EventDispatcherInterface.php b/vendor/psr/event-dispatcher/src/EventDispatcherInterface.php deleted file mode 100644 index 4306fa9..0000000 --- a/vendor/psr/event-dispatcher/src/EventDispatcherInterface.php +++ /dev/null @@ -1,21 +0,0 @@ -log(LogLevel::EMERGENCY, $message, $context); - } - - /** - * Action must be taken immediately. - * - * Example: Entire website down, database unavailable, etc. This should - * trigger the SMS alerts and wake you up. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function alert($message, array $context = array()) - { - $this->log(LogLevel::ALERT, $message, $context); - } - - /** - * Critical conditions. - * - * Example: Application component unavailable, unexpected exception. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function critical($message, array $context = array()) - { - $this->log(LogLevel::CRITICAL, $message, $context); - } - - /** - * Runtime errors that do not require immediate action but should typically - * be logged and monitored. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function error($message, array $context = array()) - { - $this->log(LogLevel::ERROR, $message, $context); - } - - /** - * Exceptional occurrences that are not errors. - * - * Example: Use of deprecated APIs, poor use of an API, undesirable things - * that are not necessarily wrong. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function warning($message, array $context = array()) - { - $this->log(LogLevel::WARNING, $message, $context); - } - - /** - * Normal but significant events. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function notice($message, array $context = array()) - { - $this->log(LogLevel::NOTICE, $message, $context); - } - - /** - * Interesting events. - * - * Example: User logs in, SQL logs. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function info($message, array $context = array()) - { - $this->log(LogLevel::INFO, $message, $context); - } - - /** - * Detailed debug information. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function debug($message, array $context = array()) - { - $this->log(LogLevel::DEBUG, $message, $context); - } -} diff --git a/vendor/psr/log/Psr/Log/InvalidArgumentException.php b/vendor/psr/log/Psr/Log/InvalidArgumentException.php deleted file mode 100644 index 67f852d..0000000 --- a/vendor/psr/log/Psr/Log/InvalidArgumentException.php +++ /dev/null @@ -1,7 +0,0 @@ -logger = $logger; - } -} diff --git a/vendor/psr/log/Psr/Log/LoggerInterface.php b/vendor/psr/log/Psr/Log/LoggerInterface.php deleted file mode 100644 index e695046..0000000 --- a/vendor/psr/log/Psr/Log/LoggerInterface.php +++ /dev/null @@ -1,125 +0,0 @@ -log(LogLevel::EMERGENCY, $message, $context); - } - - /** - * Action must be taken immediately. - * - * Example: Entire website down, database unavailable, etc. This should - * trigger the SMS alerts and wake you up. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function alert($message, array $context = array()) - { - $this->log(LogLevel::ALERT, $message, $context); - } - - /** - * Critical conditions. - * - * Example: Application component unavailable, unexpected exception. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function critical($message, array $context = array()) - { - $this->log(LogLevel::CRITICAL, $message, $context); - } - - /** - * Runtime errors that do not require immediate action but should typically - * be logged and monitored. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function error($message, array $context = array()) - { - $this->log(LogLevel::ERROR, $message, $context); - } - - /** - * Exceptional occurrences that are not errors. - * - * Example: Use of deprecated APIs, poor use of an API, undesirable things - * that are not necessarily wrong. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function warning($message, array $context = array()) - { - $this->log(LogLevel::WARNING, $message, $context); - } - - /** - * Normal but significant events. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function notice($message, array $context = array()) - { - $this->log(LogLevel::NOTICE, $message, $context); - } - - /** - * Interesting events. - * - * Example: User logs in, SQL logs. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function info($message, array $context = array()) - { - $this->log(LogLevel::INFO, $message, $context); - } - - /** - * Detailed debug information. - * - * @param string $message - * @param array $context - * - * @return void - */ - public function debug($message, array $context = array()) - { - $this->log(LogLevel::DEBUG, $message, $context); - } - - /** - * Logs with an arbitrary level. - * - * @param mixed $level - * @param string $message - * @param array $context - * - * @return void - * - * @throws \Psr\Log\InvalidArgumentException - */ - abstract public function log($level, $message, array $context = array()); -} diff --git a/vendor/psr/log/Psr/Log/NullLogger.php b/vendor/psr/log/Psr/Log/NullLogger.php deleted file mode 100644 index c8f7293..0000000 --- a/vendor/psr/log/Psr/Log/NullLogger.php +++ /dev/null @@ -1,30 +0,0 @@ -logger) { }` - * blocks. - */ -class NullLogger extends AbstractLogger -{ - /** - * Logs with an arbitrary level. - * - * @param mixed $level - * @param string $message - * @param array $context - * - * @return void - * - * @throws \Psr\Log\InvalidArgumentException - */ - public function log($level, $message, array $context = array()) - { - // noop - } -} diff --git a/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php b/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php deleted file mode 100644 index 9ecb6c4..0000000 --- a/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php +++ /dev/null @@ -1,146 +0,0 @@ - ". - * - * Example ->error('Foo') would yield "error Foo". - * - * @return string[] - */ - abstract public function getLogs(); - - public function testImplements() - { - $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger()); - } - - /** - * @dataProvider provideLevelsAndMessages - */ - public function testLogsAtAllLevels($level, $message) - { - $logger = $this->getLogger(); - $logger->{$level}($message, array('user' => 'Bob')); - $logger->log($level, $message, array('user' => 'Bob')); - - $expected = array( - $level.' message of level '.$level.' with context: Bob', - $level.' message of level '.$level.' with context: Bob', - ); - $this->assertEquals($expected, $this->getLogs()); - } - - public function provideLevelsAndMessages() - { - return array( - LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), - LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), - LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), - LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), - LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), - LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), - LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), - LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'), - ); - } - - /** - * @expectedException \Psr\Log\InvalidArgumentException - */ - public function testThrowsOnInvalidLevel() - { - $logger = $this->getLogger(); - $logger->log('invalid level', 'Foo'); - } - - public function testContextReplacement() - { - $logger = $this->getLogger(); - $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); - - $expected = array('info {Message {nothing} Bob Bar a}'); - $this->assertEquals($expected, $this->getLogs()); - } - - public function testObjectCastToString() - { - if (method_exists($this, 'createPartialMock')) { - $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString')); - } else { - $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString')); - } - $dummy->expects($this->once()) - ->method('__toString') - ->will($this->returnValue('DUMMY')); - - $this->getLogger()->warning($dummy); - - $expected = array('warning DUMMY'); - $this->assertEquals($expected, $this->getLogs()); - } - - public function testContextCanContainAnything() - { - $closed = fopen('php://memory', 'r'); - fclose($closed); - - $context = array( - 'bool' => true, - 'null' => null, - 'string' => 'Foo', - 'int' => 0, - 'float' => 0.5, - 'nested' => array('with object' => new DummyTest), - 'object' => new \DateTime, - 'resource' => fopen('php://memory', 'r'), - 'closed' => $closed, - ); - - $this->getLogger()->warning('Crazy context data', $context); - - $expected = array('warning Crazy context data'); - $this->assertEquals($expected, $this->getLogs()); - } - - public function testContextExceptionKeyCanBeExceptionOrOtherValues() - { - $logger = $this->getLogger(); - $logger->warning('Random message', array('exception' => 'oops')); - $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail'))); - - $expected = array( - 'warning Random message', - 'critical Uncaught Exception!' - ); - $this->assertEquals($expected, $this->getLogs()); - } -} - -class DummyTest -{ - public function __toString() - { - return 'DummyTest'; - } -} diff --git a/vendor/psr/log/Psr/Log/Test/TestLogger.php b/vendor/psr/log/Psr/Log/Test/TestLogger.php deleted file mode 100644 index 1be3230..0000000 --- a/vendor/psr/log/Psr/Log/Test/TestLogger.php +++ /dev/null @@ -1,147 +0,0 @@ - $level, - 'message' => $message, - 'context' => $context, - ]; - - $this->recordsByLevel[$record['level']][] = $record; - $this->records[] = $record; - } - - public function hasRecords($level) - { - return isset($this->recordsByLevel[$level]); - } - - public function hasRecord($record, $level) - { - if (is_string($record)) { - $record = ['message' => $record]; - } - return $this->hasRecordThatPasses(function ($rec) use ($record) { - if ($rec['message'] !== $record['message']) { - return false; - } - if (isset($record['context']) && $rec['context'] !== $record['context']) { - return false; - } - return true; - }, $level); - } - - public function hasRecordThatContains($message, $level) - { - return $this->hasRecordThatPasses(function ($rec) use ($message) { - return strpos($rec['message'], $message) !== false; - }, $level); - } - - public function hasRecordThatMatches($regex, $level) - { - return $this->hasRecordThatPasses(function ($rec) use ($regex) { - return preg_match($regex, $rec['message']) > 0; - }, $level); - } - - public function hasRecordThatPasses(callable $predicate, $level) - { - if (!isset($this->recordsByLevel[$level])) { - return false; - } - foreach ($this->recordsByLevel[$level] as $i => $rec) { - if (call_user_func($predicate, $rec, $i)) { - return true; - } - } - return false; - } - - public function __call($method, $args) - { - if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { - $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; - $level = strtolower($matches[2]); - if (method_exists($this, $genericMethod)) { - $args[] = $level; - return call_user_func_array([$this, $genericMethod], $args); - } - } - throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); - } - - public function reset() - { - $this->records = []; - $this->recordsByLevel = []; - } -} diff --git a/vendor/psr/log/README.md b/vendor/psr/log/README.md deleted file mode 100644 index a9f20c4..0000000 --- a/vendor/psr/log/README.md +++ /dev/null @@ -1,58 +0,0 @@ -PSR Log -======= - -This repository holds all interfaces/classes/traits related to -[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md). - -Note that this is not a logger of its own. It is merely an interface that -describes a logger. See the specification for more details. - -Installation ------------- - -```bash -composer require psr/log -``` - -Usage ------ - -If you need a logger, you can use the interface like this: - -```php -logger = $logger; - } - - public function doSomething() - { - if ($this->logger) { - $this->logger->info('Doing work'); - } - - try { - $this->doSomethingElse(); - } catch (Exception $exception) { - $this->logger->error('Oh no!', array('exception' => $exception)); - } - - // do something useful - } -} -``` - -You can then pick one of the implementations of the interface to get a logger. - -If you want to implement the interface, you can require this package and -implement `Psr\Log\LoggerInterface` in your code. Please read the -[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) -for details. diff --git a/vendor/psr/log/composer.json b/vendor/psr/log/composer.json deleted file mode 100644 index 3f6d4ee..0000000 --- a/vendor/psr/log/composer.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "psr/log", - "description": "Common interface for logging libraries", - "keywords": ["psr", "psr-3", "log"], - "homepage": "https://github.com/php-fig/log", - "license": "MIT", - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "require": { - "php": ">=5.3.0" - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - } -} diff --git a/vendor/symfony/cache-contracts/.gitignore b/vendor/symfony/cache-contracts/.gitignore deleted file mode 100644 index c49a5d8..0000000 --- a/vendor/symfony/cache-contracts/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/vendor/symfony/cache-contracts/CacheInterface.php b/vendor/symfony/cache-contracts/CacheInterface.php deleted file mode 100644 index 4b1686b..0000000 --- a/vendor/symfony/cache-contracts/CacheInterface.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Cache; - -use Psr\Cache\CacheItemInterface; -use Psr\Cache\InvalidArgumentException; - -/** - * Covers most simple to advanced caching needs. - * - * @author Nicolas Grekas - */ -interface CacheInterface -{ - /** - * Fetches a value from the pool or computes it if not found. - * - * On cache misses, a callback is called that should return the missing value. - * This callback is given a PSR-6 CacheItemInterface instance corresponding to the - * requested key, that could be used e.g. for expiration control. It could also - * be an ItemInterface instance when its additional features are needed. - * - * @param string $key The key of the item to retrieve from the cache - * @param callable|CallbackInterface $callback Should return the computed value for the given key/item - * @param float|null $beta A float that, as it grows, controls the likeliness of triggering - * early expiration. 0 disables it, INF forces immediate expiration. - * The default (or providing null) is implementation dependent but should - * typically be 1.0, which should provide optimal stampede protection. - * See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration - * @param array &$metadata The metadata of the cached item {@see ItemInterface::getMetadata()} - * - * @return mixed The value corresponding to the provided key - * - * @throws InvalidArgumentException When $key is not valid or when $beta is negative - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null); - - /** - * Removes an item from the pool. - * - * @param string $key The key to delete - * - * @throws InvalidArgumentException When $key is not valid - * - * @return bool True if the item was successfully removed, false if there was any error - */ - public function delete(string $key): bool; -} diff --git a/vendor/symfony/cache-contracts/CacheTrait.php b/vendor/symfony/cache-contracts/CacheTrait.php deleted file mode 100644 index 355ea29..0000000 --- a/vendor/symfony/cache-contracts/CacheTrait.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Cache; - -use Psr\Cache\CacheItemPoolInterface; -use Psr\Cache\InvalidArgumentException; -use Psr\Log\LoggerInterface; - -/** - * An implementation of CacheInterface for PSR-6 CacheItemPoolInterface classes. - * - * @author Nicolas Grekas - */ -trait CacheTrait -{ - /** - * {@inheritdoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - return $this->doGet($this, $key, $callback, $beta, $metadata); - } - - /** - * {@inheritdoc} - */ - public function delete(string $key): bool - { - return $this->deleteItem($key); - } - - private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null, LoggerInterface $logger = null) - { - if (0 > $beta = $beta ?? 1.0) { - throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', \get_class($this), $beta)) extends \InvalidArgumentException implements InvalidArgumentException { - }; - } - - $item = $pool->getItem($key); - $recompute = !$item->isHit() || INF === $beta; - $metadata = $item instanceof ItemInterface ? $item->getMetadata() : []; - - if (!$recompute && $metadata) { - $expiry = $metadata[ItemInterface::METADATA_EXPIRY] ?? false; - $ctime = $metadata[ItemInterface::METADATA_CTIME] ?? false; - - if ($recompute = $ctime && $expiry && $expiry <= ($now = microtime(true)) - $ctime / 1000 * $beta * log(random_int(1, PHP_INT_MAX) / PHP_INT_MAX)) { - // force applying defaultLifetime to expiry - $item->expiresAt(null); - $logger && $logger->info('Item "{key}" elected for early recomputation {delta}s before its expiration', [ - 'key' => $key, - 'delta' => sprintf('%.1f', $expiry - $now), - ]); - } - } - - if ($recompute) { - $save = true; - $item->set($callback($item, $save)); - if ($save) { - $pool->save($item); - } - } - - return $item->get(); - } -} diff --git a/vendor/symfony/cache-contracts/CallbackInterface.php b/vendor/symfony/cache-contracts/CallbackInterface.php deleted file mode 100644 index 7dae2aa..0000000 --- a/vendor/symfony/cache-contracts/CallbackInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Cache; - -use Psr\Cache\CacheItemInterface; - -/** - * Computes and returns the cached value of an item. - * - * @author Nicolas Grekas - */ -interface CallbackInterface -{ - /** - * @param CacheItemInterface|ItemInterface $item The item to compute the value for - * @param bool &$save Should be set to false when the value should not be saved in the pool - * - * @return mixed The computed value for the passed item - */ - public function __invoke(CacheItemInterface $item, bool &$save); -} diff --git a/vendor/symfony/cache-contracts/ItemInterface.php b/vendor/symfony/cache-contracts/ItemInterface.php deleted file mode 100644 index cbd7226..0000000 --- a/vendor/symfony/cache-contracts/ItemInterface.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Cache; - -use Psr\Cache\CacheException; -use Psr\Cache\CacheItemInterface; -use Psr\Cache\InvalidArgumentException; - -/** - * Augments PSR-6's CacheItemInterface with support for tags and metadata. - * - * @author Nicolas Grekas - */ -interface ItemInterface extends CacheItemInterface -{ - /** - * References the Unix timestamp stating when the item will expire. - */ - const METADATA_EXPIRY = 'expiry'; - - /** - * References the time the item took to be created, in milliseconds. - */ - const METADATA_CTIME = 'ctime'; - - /** - * References the list of tags that were assigned to the item, as string[]. - */ - const METADATA_TAGS = 'tags'; - - /** - * Reserved characters that cannot be used in a key or tag. - */ - const RESERVED_CHARACTERS = '{}()/\@:'; - - /** - * Adds a tag to a cache item. - * - * Tags are strings that follow the same validation rules as keys. - * - * @param string|string[] $tags A tag or array of tags - * - * @return $this - * - * @throws InvalidArgumentException When $tag is not valid - * @throws CacheException When the item comes from a pool that is not tag-aware - */ - public function tag($tags): self; - - /** - * Returns a list of metadata info that were saved alongside with the cached value. - * - * See ItemInterface::METADATA_* consts for keys potentially found in the returned array. - */ - public function getMetadata(): array; -} diff --git a/vendor/symfony/cache-contracts/LICENSE b/vendor/symfony/cache-contracts/LICENSE deleted file mode 100644 index 3f853aa..0000000 --- a/vendor/symfony/cache-contracts/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2018-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/cache-contracts/README.md b/vendor/symfony/cache-contracts/README.md deleted file mode 100644 index 58c589e..0000000 --- a/vendor/symfony/cache-contracts/README.md +++ /dev/null @@ -1,9 +0,0 @@ -Symfony Cache Contracts -======================= - -A set of abstractions extracted out of the Symfony components. - -Can be used to build on semantics that the Symfony components proved useful - and -that already have battle tested implementations. - -See https://github.com/symfony/contracts/blob/master/README.md for more information. diff --git a/vendor/symfony/cache-contracts/TagAwareCacheInterface.php b/vendor/symfony/cache-contracts/TagAwareCacheInterface.php deleted file mode 100644 index 7c4cf11..0000000 --- a/vendor/symfony/cache-contracts/TagAwareCacheInterface.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Cache; - -use Psr\Cache\InvalidArgumentException; - -/** - * Allows invalidating cached items using tags. - * - * @author Nicolas Grekas - */ -interface TagAwareCacheInterface extends CacheInterface -{ - /** - * Invalidates cached items using tags. - * - * When implemented on a PSR-6 pool, invalidation should not apply - * to deferred items. Instead, they should be committed as usual. - * This allows replacing old tagged values by new ones without - * race conditions. - * - * @param string[] $tags An array of tags to invalidate - * - * @return bool True on success - * - * @throws InvalidArgumentException When $tags is not valid - */ - public function invalidateTags(array $tags); -} diff --git a/vendor/symfony/cache-contracts/composer.json b/vendor/symfony/cache-contracts/composer.json deleted file mode 100644 index c9cf8b5..0000000 --- a/vendor/symfony/cache-contracts/composer.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "symfony/cache-contracts", - "type": "library", - "description": "Generic abstractions related to caching", - "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "psr/cache": "^1.0" - }, - "suggest": { - "symfony/cache-implementation": "" - }, - "autoload": { - "psr-4": { "Symfony\\Contracts\\Cache\\": "" } - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - } -} diff --git a/vendor/symfony/cache/.gitattributes b/vendor/symfony/cache/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/cache/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/cache/Adapter/AbstractAdapter.php b/vendor/symfony/cache/Adapter/AbstractAdapter.php deleted file mode 100644 index d12d8f6..0000000 --- a/vendor/symfony/cache/Adapter/AbstractAdapter.php +++ /dev/null @@ -1,195 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Log\LoggerAwareInterface; -use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\AbstractAdapterTrait; -use Symfony\Component\Cache\Traits\ContractsTrait; -use Symfony\Contracts\Cache\CacheInterface; - -/** - * @author Nicolas Grekas - */ -abstract class AbstractAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface -{ - /** - * @internal - */ - protected const NS_SEPARATOR = ':'; - - use AbstractAdapterTrait; - use ContractsTrait; - - private static $apcuSupported; - private static $phpFilesSupported; - - protected function __construct(string $namespace = '', int $defaultLifetime = 0) - { - $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).static::NS_SEPARATOR; - if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) { - throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")', $this->maxIdLength - 24, \strlen($namespace), $namespace)); - } - $this->createCacheItem = \Closure::bind( - static function ($key, $value, $isHit) use ($defaultLifetime) { - $item = new CacheItem(); - $item->key = $key; - $item->value = $v = $value; - $item->isHit = $isHit; - $item->defaultLifetime = $defaultLifetime; - // Detect wrapped values that encode for their expiry and creation duration - // For compactness, these values are packed in the key of an array using - // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F - if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = key($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) { - $item->value = $v[$k]; - $v = unpack('Ve/Nc', substr($k, 1, -1)); - $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; - $item->metadata[CacheItem::METADATA_CTIME] = $v['c']; - } - - return $item; - }, - null, - CacheItem::class - ); - $getId = \Closure::fromCallable([$this, 'getId']); - $this->mergeByLifetime = \Closure::bind( - static function ($deferred, $namespace, &$expiredIds) use ($getId) { - $byLifetime = []; - $now = microtime(true); - $expiredIds = []; - - foreach ($deferred as $key => $item) { - $key = (string) $key; - if (null === $item->expiry) { - $ttl = 0 < $item->defaultLifetime ? $item->defaultLifetime : 0; - } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) { - $expiredIds[] = $getId($key); - continue; - } - if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) { - unset($metadata[CacheItem::METADATA_TAGS]); - } - // For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators - $byLifetime[$ttl][$getId($key)] = $metadata ? ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item->value] : $item->value; - } - - return $byLifetime; - }, - null, - CacheItem::class - ); - } - - /** - * Returns the best possible adapter that your runtime supports. - * - * Using ApcuAdapter makes system caches compatible with read-only filesystems. - * - * @return AdapterInterface - */ - public static function createSystemCache(string $namespace, int $defaultLifetime, string $version, string $directory, LoggerInterface $logger = null) - { - $opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory, true); - if (null !== $logger) { - $opcache->setLogger($logger); - } - - if (!self::$apcuSupported = self::$apcuSupported ?? ApcuAdapter::isSupported()) { - return $opcache; - } - - $apcu = new ApcuAdapter($namespace, $defaultLifetime / 5, $version); - if ('cli' === \PHP_SAPI && !filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN)) { - $apcu->setLogger(new NullLogger()); - } elseif (null !== $logger) { - $apcu->setLogger($logger); - } - - return new ChainAdapter([$apcu, $opcache]); - } - - public static function createConnection(string $dsn, array $options = []) - { - if (0 === strpos($dsn, 'redis:') || 0 === strpos($dsn, 'rediss:')) { - return RedisAdapter::createConnection($dsn, $options); - } - if (0 === strpos($dsn, 'memcached:')) { - return MemcachedAdapter::createConnection($dsn, $options); - } - - throw new InvalidArgumentException(sprintf('Unsupported DSN: %s.', $dsn)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - $ok = true; - $byLifetime = $this->mergeByLifetime; - $byLifetime = $byLifetime($this->deferred, $this->namespace, $expiredIds); - $retry = $this->deferred = []; - - if ($expiredIds) { - $this->doDelete($expiredIds); - } - foreach ($byLifetime as $lifetime => $values) { - try { - $e = $this->doSave($values, $lifetime); - } catch (\Exception $e) { - } - if (true === $e || [] === $e) { - continue; - } - if (\is_array($e) || 1 === \count($values)) { - foreach (\is_array($e) ? $e : array_keys($values) as $id) { - $ok = false; - $v = $values[$id]; - $type = \is_object($v) ? \get_class($v) : \gettype($v); - $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]); - } - } else { - foreach ($values as $id => $v) { - $retry[$lifetime][] = $id; - } - } - } - - // When bulk-save failed, retry each item individually - foreach ($retry as $lifetime => $ids) { - foreach ($ids as $id) { - try { - $v = $byLifetime[$lifetime][$id]; - $e = $this->doSave([$id => $v], $lifetime); - } catch (\Exception $e) { - } - if (true === $e || [] === $e) { - continue; - } - $ok = false; - $type = \is_object($v) ? \get_class($v) : \gettype($v); - $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]); - } - } - - return $ok; - } -} diff --git a/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php b/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php deleted file mode 100644 index a1d2440..0000000 --- a/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php +++ /dev/null @@ -1,323 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Log\LoggerAwareInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\AbstractAdapterTrait; -use Symfony\Component\Cache\Traits\ContractsTrait; -use Symfony\Contracts\Cache\TagAwareCacheInterface; - -/** - * Abstract for native TagAware adapters. - * - * To keep info on tags, the tags are both serialized as part of cache value and provided as tag ids - * to Adapters on operations when needed for storage to doSave(), doDelete() & doInvalidate(). - * - * @author Nicolas Grekas - * @author André Rømcke - * - * @internal - */ -abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, LoggerAwareInterface, ResettableInterface -{ - use AbstractAdapterTrait; - use ContractsTrait; - - private const TAGS_PREFIX = "\0tags\0"; - - protected function __construct(string $namespace = '', int $defaultLifetime = 0) - { - $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':'; - if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) { - throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")', $this->maxIdLength - 24, \strlen($namespace), $namespace)); - } - $this->createCacheItem = \Closure::bind( - static function ($key, $value, $isHit) use ($defaultLifetime) { - $item = new CacheItem(); - $item->key = $key; - $item->defaultLifetime = $defaultLifetime; - $item->isTaggable = true; - // If structure does not match what we expect return item as is (no value and not a hit) - if (!\is_array($value) || !\array_key_exists('value', $value)) { - return $item; - } - $item->isHit = $isHit; - // Extract value, tags and meta data from the cache value - $item->value = $value['value']; - $item->metadata[CacheItem::METADATA_TAGS] = $value['tags'] ?? []; - if (isset($value['meta'])) { - // For compactness these values are packed, & expiry is offset to reduce size - $v = unpack('Ve/Nc', $value['meta']); - $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; - $item->metadata[CacheItem::METADATA_CTIME] = $v['c']; - } - - return $item; - }, - null, - CacheItem::class - ); - $getId = \Closure::fromCallable([$this, 'getId']); - $tagPrefix = self::TAGS_PREFIX; - $this->mergeByLifetime = \Closure::bind( - static function ($deferred, &$expiredIds) use ($getId, $tagPrefix) { - $byLifetime = []; - $now = microtime(true); - $expiredIds = []; - - foreach ($deferred as $key => $item) { - $key = (string) $key; - if (null === $item->expiry) { - $ttl = 0 < $item->defaultLifetime ? $item->defaultLifetime : 0; - } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) { - $expiredIds[] = $getId($key); - continue; - } - // Store Value and Tags on the cache value - if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) { - $value = ['value' => $item->value, 'tags' => $metadata[CacheItem::METADATA_TAGS]]; - unset($metadata[CacheItem::METADATA_TAGS]); - } else { - $value = ['value' => $item->value, 'tags' => []]; - } - - if ($metadata) { - // For compactness, expiry and creation duration are packed, using magic numbers as separators - $value['meta'] = pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME]); - } - - // Extract tag changes, these should be removed from values in doSave() - $value['tag-operations'] = ['add' => [], 'remove' => []]; - $oldTags = $item->metadata[CacheItem::METADATA_TAGS] ?? []; - foreach (array_diff($value['tags'], $oldTags) as $addedTag) { - $value['tag-operations']['add'][] = $getId($tagPrefix.$addedTag); - } - foreach (array_diff($oldTags, $value['tags']) as $removedTag) { - $value['tag-operations']['remove'][] = $getId($tagPrefix.$removedTag); - } - - $byLifetime[$ttl][$getId($key)] = $value; - } - - return $byLifetime; - }, - null, - CacheItem::class - ); - } - - /** - * Persists several cache items immediately. - * - * @param array $values The values to cache, indexed by their cache identifier - * @param int $lifetime The lifetime of the cached values, 0 for persisting until manual cleaning - * @param array[] $addTagData Hash where key is tag id, and array value is list of cache id's to add to tag - * @param array[] $removeTagData Hash where key is tag id, and array value is list of cache id's to remove to tag - * - * @return array The identifiers that failed to be cached or a boolean stating if caching succeeded or not - */ - abstract protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array; - - /** - * Removes multiple items from the pool and their corresponding tags. - * - * @param array $ids An array of identifiers that should be removed from the pool - * - * @return bool True if the items were successfully removed, false otherwise - */ - abstract protected function doDelete(array $ids); - - /** - * Removes relations between tags and deleted items. - * - * @param array $tagData Array of tag => key identifiers that should be removed from the pool - */ - abstract protected function doDeleteTagRelations(array $tagData): bool; - - /** - * Invalidates cached items using tags. - * - * @param string[] $tagIds An array of tags to invalidate, key is tag and value is tag id - * - * @return bool True on success - */ - abstract protected function doInvalidate(array $tagIds): bool; - - /** - * Delete items and yields the tags they were bound to. - */ - protected function doDeleteYieldTags(array $ids): iterable - { - foreach ($this->doFetch($ids) as $id => $value) { - yield $id => \is_array($value) && \is_array($value['tags'] ?? null) ? $value['tags'] : []; - } - - $this->doDelete($ids); - } - - /** - * {@inheritdoc} - */ - public function commit(): bool - { - $ok = true; - $byLifetime = $this->mergeByLifetime; - $byLifetime = $byLifetime($this->deferred, $expiredIds); - $retry = $this->deferred = []; - - if ($expiredIds) { - // Tags are not cleaned up in this case, however that is done on invalidateTags(). - $this->doDelete($expiredIds); - } - foreach ($byLifetime as $lifetime => $values) { - try { - $values = $this->extractTagData($values, $addTagData, $removeTagData); - $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData); - } catch (\Exception $e) { - } - if (true === $e || [] === $e) { - continue; - } - if (\is_array($e) || 1 === \count($values)) { - foreach (\is_array($e) ? $e : array_keys($values) as $id) { - $ok = false; - $v = $values[$id]; - $type = \is_object($v) ? \get_class($v) : \gettype($v); - $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]); - } - } else { - foreach ($values as $id => $v) { - $retry[$lifetime][] = $id; - } - } - } - - // When bulk-save failed, retry each item individually - foreach ($retry as $lifetime => $ids) { - foreach ($ids as $id) { - try { - $v = $byLifetime[$lifetime][$id]; - $values = $this->extractTagData([$id => $v], $addTagData, $removeTagData); - $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData); - } catch (\Exception $e) { - } - if (true === $e || [] === $e) { - continue; - } - $ok = false; - $type = \is_object($v) ? \get_class($v) : \gettype($v); - $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]); - } - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - public function deleteItems(array $keys): bool - { - if (!$keys) { - return true; - } - - $ok = true; - $ids = []; - $tagData = []; - - foreach ($keys as $key) { - $ids[$key] = $this->getId($key); - unset($this->deferred[$key]); - } - - try { - foreach ($this->doDeleteYieldTags(array_values($ids)) as $id => $tags) { - foreach ($tags as $tag) { - $tagData[$this->getId(self::TAGS_PREFIX.$tag)][] = $id; - } - } - } catch (\Exception $e) { - $ok = false; - } - - try { - if ((!$tagData || $this->doDeleteTagRelations($tagData)) && $ok) { - return true; - } - } catch (\Exception $e) { - } - - // When bulk-delete failed, retry each item individually - foreach ($ids as $key => $id) { - try { - $e = null; - if ($this->doDelete([$id])) { - continue; - } - } catch (\Exception $e) { - } - $message = 'Failed to delete key "{key}"'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e]); - $ok = false; - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - public function invalidateTags(array $tags) - { - if (empty($tags)) { - return false; - } - - $tagIds = []; - foreach (array_unique($tags) as $tag) { - $tagIds[] = $this->getId(self::TAGS_PREFIX.$tag); - } - - if ($this->doInvalidate($tagIds)) { - return true; - } - - return false; - } - - /** - * Extracts tags operation data from $values set in mergeByLifetime, and returns values without it. - */ - private function extractTagData(array $values, ?array &$addTagData, ?array &$removeTagData): array - { - $addTagData = $removeTagData = []; - foreach ($values as $id => $value) { - foreach ($value['tag-operations']['add'] as $tag => $tagId) { - $addTagData[$tagId][] = $id; - } - - foreach ($value['tag-operations']['remove'] as $tag => $tagId) { - $removeTagData[$tagId][] = $id; - } - - unset($values[$id]['tag-operations']); - } - - return $values; - } -} diff --git a/vendor/symfony/cache/Adapter/AdapterInterface.php b/vendor/symfony/cache/Adapter/AdapterInterface.php deleted file mode 100644 index 99c5cd1..0000000 --- a/vendor/symfony/cache/Adapter/AdapterInterface.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\CacheItem; - -/** - * Interface for adapters managing instances of Symfony's CacheItem. - * - * @author Kévin Dunglas - */ -interface AdapterInterface extends CacheItemPoolInterface -{ - /** - * {@inheritdoc} - * - * @return CacheItem - */ - public function getItem($key); - - /** - * {@inheritdoc} - * - * @return \Traversable|CacheItem[] - */ - public function getItems(array $keys = []); - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = ''); -} diff --git a/vendor/symfony/cache/Adapter/ApcuAdapter.php b/vendor/symfony/cache/Adapter/ApcuAdapter.php deleted file mode 100644 index 62ba4d9..0000000 --- a/vendor/symfony/cache/Adapter/ApcuAdapter.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\CacheException; - -/** - * @author Nicolas Grekas - */ -class ApcuAdapter extends AbstractAdapter -{ - /** - * @throws CacheException if APCu is not enabled - */ - public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null) - { - if (!static::isSupported()) { - throw new CacheException('APCu is not enabled'); - } - if ('cli' === \PHP_SAPI) { - ini_set('apc.use_request_time', 0); - } - parent::__construct($namespace, $defaultLifetime); - - if (null !== $version) { - CacheItem::validateKey($version); - - if (!apcu_exists($version.'@'.$namespace)) { - $this->doClear($namespace); - apcu_add($version.'@'.$namespace, null); - } - } - } - - public static function isSupported() - { - return \function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN); - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); - try { - $values = []; - foreach (apcu_fetch($ids, $ok) ?: [] as $k => $v) { - if (null !== $v || $ok) { - $values[$k] = $v; - } - } - - return $values; - } catch (\Error $e) { - throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); - } finally { - ini_set('unserialize_callback_func', $unserializeCallbackHandler); - } - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - return apcu_exists($id); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - return isset($namespace[0]) && class_exists('APCuIterator', false) && ('cli' !== \PHP_SAPI || filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN)) - ? apcu_delete(new \APCuIterator(sprintf('/^%s/', preg_quote($namespace, '/')), APC_ITER_KEY)) - : apcu_clear_cache(); - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - foreach ($ids as $id) { - apcu_delete($id); - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - try { - if (false === $failures = apcu_store($values, null, $lifetime)) { - $failures = $values; - } - - return array_keys($failures); - } catch (\Throwable $e) { - if (1 === \count($values)) { - // Workaround https://github.com/krakjoe/apcu/issues/170 - apcu_delete(key($values)); - } - - throw $e; - } - } -} diff --git a/vendor/symfony/cache/Adapter/ArrayAdapter.php b/vendor/symfony/cache/Adapter/ArrayAdapter.php deleted file mode 100644 index 05920d0..0000000 --- a/vendor/symfony/cache/Adapter/ArrayAdapter.php +++ /dev/null @@ -1,324 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Psr\Log\LoggerAwareInterface; -use Psr\Log\LoggerAwareTrait; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Contracts\Cache\CacheInterface; - -/** - * @author Nicolas Grekas - */ -class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface -{ - use LoggerAwareTrait; - - private $storeSerialized; - private $values = []; - private $expiries = []; - private $createCacheItem; - - /** - * @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise - */ - public function __construct(int $defaultLifetime = 0, bool $storeSerialized = true) - { - $this->storeSerialized = $storeSerialized; - $this->createCacheItem = \Closure::bind( - static function ($key, $value, $isHit) use ($defaultLifetime) { - $item = new CacheItem(); - $item->key = $key; - $item->value = $value; - $item->isHit = $isHit; - $item->defaultLifetime = $defaultLifetime; - - return $item; - }, - null, - CacheItem::class - ); - } - - /** - * {@inheritdoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - $item = $this->getItem($key); - $metadata = $item->getMetadata(); - - // ArrayAdapter works in memory, we don't care about stampede protection - if (INF === $beta || !$item->isHit()) { - $save = true; - $this->save($item->set($callback($item, $save))); - } - - return $item->get(); - } - - /** - * {@inheritdoc} - */ - public function delete(string $key): bool - { - return $this->deleteItem($key); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - if (\is_string($key) && isset($this->expiries[$key]) && $this->expiries[$key] > microtime(true)) { - return true; - } - CacheItem::validateKey($key); - - return isset($this->expiries[$key]) && !$this->deleteItem($key); - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - if (!$isHit = $this->hasItem($key)) { - $this->values[$key] = $value = null; - } else { - $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key]; - } - $f = $this->createCacheItem; - - return $f($key, $value, $isHit); - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - foreach ($keys as $key) { - if (!\is_string($key) || !isset($this->expiries[$key])) { - CacheItem::validateKey($key); - } - } - - return $this->generateItems($keys, microtime(true), $this->createCacheItem); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - if (!\is_string($key) || !isset($this->expiries[$key])) { - CacheItem::validateKey($key); - } - unset($this->values[$key], $this->expiries[$key]); - - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - foreach ($keys as $key) { - $this->deleteItem($key); - } - - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - if (!$item instanceof CacheItem) { - return false; - } - $item = (array) $item; - $key = $item["\0*\0key"]; - $value = $item["\0*\0value"]; - $expiry = $item["\0*\0expiry"]; - - if (null !== $expiry && $expiry <= microtime(true)) { - $this->deleteItem($key); - - return true; - } - if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) { - return false; - } - if (null === $expiry && 0 < $item["\0*\0defaultLifetime"]) { - $expiry = microtime(true) + $item["\0*\0defaultLifetime"]; - } - - $this->values[$key] = $value; - $this->expiries[$key] = null !== $expiry ? $expiry : PHP_INT_MAX; - - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - return $this->save($item); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - if ('' !== $prefix) { - foreach ($this->values as $key => $value) { - if (0 === strpos($key, $prefix)) { - unset($this->values[$key], $this->expiries[$key]); - } - } - } else { - $this->values = $this->expiries = []; - } - - return true; - } - - /** - * Returns all cached values, with cache miss as null. - * - * @return array - */ - public function getValues() - { - if (!$this->storeSerialized) { - return $this->values; - } - - $values = $this->values; - foreach ($values as $k => $v) { - if (null === $v || 'N;' === $v) { - continue; - } - if (!\is_string($v) || !isset($v[2]) || ':' !== $v[1]) { - $values[$k] = serialize($v); - } - } - - return $values; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $this->clear(); - } - - private function generateItems(array $keys, $now, $f) - { - foreach ($keys as $i => $key) { - if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > $now || !$this->deleteItem($key))) { - $this->values[$key] = $value = null; - } else { - $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key]; - } - unset($keys[$i]); - - yield $key => $f($key, $value, $isHit); - } - - foreach ($keys as $key) { - yield $key => $f($key, null, false); - } - } - - private function freeze($value, $key) - { - if (null === $value) { - return 'N;'; - } - if (\is_string($value)) { - // Serialize strings if they could be confused with serialized objects or arrays - if ('N;' === $value || (isset($value[2]) && ':' === $value[1])) { - return serialize($value); - } - } elseif (!is_scalar($value)) { - try { - $serialized = serialize($value); - } catch (\Exception $e) { - $type = \is_object($value) ? \get_class($value) : \gettype($value); - $message = sprintf('Failed to save key "{key}" of type %s: %s', $type, $e->getMessage()); - CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e]); - - return; - } - // Keep value serialized if it contains any objects or any internal references - if ('C' === $serialized[0] || 'O' === $serialized[0] || preg_match('/;[OCRr]:[1-9]/', $serialized)) { - return $serialized; - } - } - - return $value; - } - - private function unfreeze(string $key, bool &$isHit) - { - if ('N;' === $value = $this->values[$key]) { - return null; - } - if (\is_string($value) && isset($value[2]) && ':' === $value[1]) { - try { - $value = unserialize($value); - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to unserialize key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e]); - $value = false; - } - if (false === $value) { - $this->values[$key] = $value = null; - $isHit = false; - } - } - - return $value; - } -} diff --git a/vendor/symfony/cache/Adapter/ChainAdapter.php b/vendor/symfony/cache/Adapter/ChainAdapter.php deleted file mode 100644 index a2fc8e7..0000000 --- a/vendor/symfony/cache/Adapter/ChainAdapter.php +++ /dev/null @@ -1,329 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\ContractsTrait; -use Symfony\Contracts\Cache\CacheInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * Chains several adapters together. - * - * Cached items are fetched from the first adapter having them in its data store. - * They are saved and deleted in all adapters at once. - * - * @author Kévin Dunglas - */ -class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface -{ - use ContractsTrait; - - private $adapters = []; - private $adapterCount; - private $syncItem; - - /** - * @param CacheItemPoolInterface[] $adapters The ordered list of adapters used to fetch cached items - * @param int $defaultLifetime The default lifetime of items propagated from lower adapters to upper ones - */ - public function __construct(array $adapters, int $defaultLifetime = 0) - { - if (!$adapters) { - throw new InvalidArgumentException('At least one adapter must be specified.'); - } - - foreach ($adapters as $adapter) { - if (!$adapter instanceof CacheItemPoolInterface) { - throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', \get_class($adapter), CacheItemPoolInterface::class)); - } - - if ($adapter instanceof AdapterInterface) { - $this->adapters[] = $adapter; - } else { - $this->adapters[] = new ProxyAdapter($adapter); - } - } - $this->adapterCount = \count($this->adapters); - - $this->syncItem = \Closure::bind( - static function ($sourceItem, $item, $sourceMetadata = null) use ($defaultLifetime) { - $sourceItem->isTaggable = false; - $sourceMetadata = $sourceMetadata ?? $sourceItem->metadata; - unset($sourceMetadata[CacheItem::METADATA_TAGS]); - - $item->value = $sourceItem->value; - $item->expiry = $sourceMetadata[CacheItem::METADATA_EXPIRY] ?? $sourceItem->expiry; - $item->isHit = $sourceItem->isHit; - $item->metadata = $item->newMetadata = $sourceItem->metadata = $sourceMetadata; - - if (0 < $sourceItem->defaultLifetime && $sourceItem->defaultLifetime < $defaultLifetime) { - $defaultLifetime = $sourceItem->defaultLifetime; - } - if (0 < $defaultLifetime && ($item->defaultLifetime <= 0 || $defaultLifetime < $item->defaultLifetime)) { - $item->defaultLifetime = $defaultLifetime; - } - - return $item; - }, - null, - CacheItem::class - ); - } - - /** - * {@inheritdoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - $lastItem = null; - $i = 0; - $wrap = function (CacheItem $item = null) use ($key, $callback, $beta, &$wrap, &$i, &$lastItem, &$metadata) { - $adapter = $this->adapters[$i]; - if (isset($this->adapters[++$i])) { - $callback = $wrap; - $beta = INF === $beta ? INF : 0; - } - if ($adapter instanceof CacheInterface) { - $value = $adapter->get($key, $callback, $beta, $metadata); - } else { - $value = $this->doGet($adapter, $key, $callback, $beta, $metadata); - } - if (null !== $item) { - ($this->syncItem)($lastItem = $lastItem ?? $item, $item, $metadata); - } - - return $value; - }; - - return $wrap(); - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - $syncItem = $this->syncItem; - $misses = []; - - foreach ($this->adapters as $i => $adapter) { - $item = $adapter->getItem($key); - - if ($item->isHit()) { - while (0 <= --$i) { - $this->adapters[$i]->save($syncItem($item, $misses[$i])); - } - - return $item; - } - - $misses[$i] = $item; - } - - return $item; - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - return $this->generateItems($this->adapters[0]->getItems($keys), 0); - } - - private function generateItems(iterable $items, int $adapterIndex) - { - $missing = []; - $misses = []; - $nextAdapterIndex = $adapterIndex + 1; - $nextAdapter = isset($this->adapters[$nextAdapterIndex]) ? $this->adapters[$nextAdapterIndex] : null; - - foreach ($items as $k => $item) { - if (!$nextAdapter || $item->isHit()) { - yield $k => $item; - } else { - $missing[] = $k; - $misses[$k] = $item; - } - } - - if ($missing) { - $syncItem = $this->syncItem; - $adapter = $this->adapters[$adapterIndex]; - $items = $this->generateItems($nextAdapter->getItems($missing), $nextAdapterIndex); - - foreach ($items as $k => $item) { - if ($item->isHit()) { - $adapter->save($syncItem($item, $misses[$k])); - } - - yield $k => $item; - } - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - foreach ($this->adapters as $adapter) { - if ($adapter->hasItem($key)) { - return true; - } - } - - return false; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - $cleared = true; - $i = $this->adapterCount; - - while ($i--) { - if ($this->adapters[$i] instanceof AdapterInterface) { - $cleared = $this->adapters[$i]->clear($prefix) && $cleared; - } else { - $cleared = $this->adapters[$i]->clear() && $cleared; - } - } - - return $cleared; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - $deleted = true; - $i = $this->adapterCount; - - while ($i--) { - $deleted = $this->adapters[$i]->deleteItem($key) && $deleted; - } - - return $deleted; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - $deleted = true; - $i = $this->adapterCount; - - while ($i--) { - $deleted = $this->adapters[$i]->deleteItems($keys) && $deleted; - } - - return $deleted; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - $saved = true; - $i = $this->adapterCount; - - while ($i--) { - $saved = $this->adapters[$i]->save($item) && $saved; - } - - return $saved; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - $saved = true; - $i = $this->adapterCount; - - while ($i--) { - $saved = $this->adapters[$i]->saveDeferred($item) && $saved; - } - - return $saved; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - $committed = true; - $i = $this->adapterCount; - - while ($i--) { - $committed = $this->adapters[$i]->commit() && $committed; - } - - return $committed; - } - - /** - * {@inheritdoc} - */ - public function prune() - { - $pruned = true; - - foreach ($this->adapters as $adapter) { - if ($adapter instanceof PruneableInterface) { - $pruned = $adapter->prune() && $pruned; - } - } - - return $pruned; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - foreach ($this->adapters as $adapter) { - if ($adapter instanceof ResetInterface) { - $adapter->reset(); - } - } - } -} diff --git a/vendor/symfony/cache/Adapter/DoctrineAdapter.php b/vendor/symfony/cache/Adapter/DoctrineAdapter.php deleted file mode 100644 index 55a36e1..0000000 --- a/vendor/symfony/cache/Adapter/DoctrineAdapter.php +++ /dev/null @@ -1,105 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Doctrine\Common\Cache\CacheProvider; - -/** - * @author Nicolas Grekas - */ -class DoctrineAdapter extends AbstractAdapter -{ - private $provider; - - public function __construct(CacheProvider $provider, string $namespace = '', int $defaultLifetime = 0) - { - parent::__construct('', $defaultLifetime); - $this->provider = $provider; - $provider->setNamespace($namespace); - } - - /** - * {@inheritdoc} - */ - public function reset() - { - parent::reset(); - $this->provider->setNamespace($this->provider->getNamespace()); - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - $unserializeCallbackHandler = ini_set('unserialize_callback_func', parent::class.'::handleUnserializeCallback'); - try { - return $this->provider->fetchMultiple($ids); - } catch (\Error $e) { - $trace = $e->getTrace(); - - if (isset($trace[0]['function']) && !isset($trace[0]['class'])) { - switch ($trace[0]['function']) { - case 'unserialize': - case 'apcu_fetch': - case 'apc_fetch': - throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); - } - } - - throw $e; - } finally { - ini_set('unserialize_callback_func', $unserializeCallbackHandler); - } - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - return $this->provider->contains($id); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - $namespace = $this->provider->getNamespace(); - - return isset($namespace[0]) - ? $this->provider->deleteAll() - : $this->provider->flushAll(); - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - $ok = true; - foreach ($ids as $id) { - $ok = $this->provider->delete($id) && $ok; - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - return $this->provider->saveMultiple($values, $lifetime); - } -} diff --git a/vendor/symfony/cache/Adapter/FilesystemAdapter.php b/vendor/symfony/cache/Adapter/FilesystemAdapter.php deleted file mode 100644 index 7185dd4..0000000 --- a/vendor/symfony/cache/Adapter/FilesystemAdapter.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\Traits\FilesystemTrait; - -class FilesystemAdapter extends AbstractAdapter implements PruneableInterface -{ - use FilesystemTrait; - - public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null) - { - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - parent::__construct('', $defaultLifetime); - $this->init($namespace, $directory); - } -} diff --git a/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php b/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php deleted file mode 100644 index 2496bda..0000000 --- a/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php +++ /dev/null @@ -1,239 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Component\Cache\Marshaller\MarshallerInterface; -use Symfony\Component\Cache\Marshaller\TagAwareMarshaller; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\Traits\FilesystemTrait; - -/** - * Stores tag id <> cache id relationship as a symlink, and lookup on invalidation calls. - * - * @author Nicolas Grekas - * @author André Rømcke - */ -class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements PruneableInterface -{ - use FilesystemTrait { - doClear as private doClearCache; - doSave as private doSaveCache; - } - - /** - * Folder used for tag symlinks. - */ - private const TAG_FOLDER = 'tags'; - - public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null) - { - $this->marshaller = new TagAwareMarshaller($marshaller); - parent::__construct('', $defaultLifetime); - $this->init($namespace, $directory); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - $ok = $this->doClearCache($namespace); - - if ('' !== $namespace) { - return $ok; - } - - set_error_handler(static function () {}); - $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; - - try { - foreach ($this->scanHashDir($this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR) as $dir) { - if (rename($dir, $renamed = substr_replace($dir, bin2hex(random_bytes(4)), -8))) { - $dir = $renamed.\DIRECTORY_SEPARATOR; - } else { - $dir .= \DIRECTORY_SEPARATOR; - $renamed = null; - } - - for ($i = 0; $i < 38; ++$i) { - if (!file_exists($dir.$chars[$i])) { - continue; - } - for ($j = 0; $j < 38; ++$j) { - if (!file_exists($d = $dir.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j])) { - continue; - } - foreach (scandir($d, SCANDIR_SORT_NONE) ?: [] as $link) { - if ('.' !== $link && '..' !== $link && (null !== $renamed || !realpath($d.\DIRECTORY_SEPARATOR.$link))) { - unlink($d.\DIRECTORY_SEPARATOR.$link); - } - } - null === $renamed ?: rmdir($d); - } - null === $renamed ?: rmdir($dir.$chars[$i]); - } - null === $renamed ?: rmdir($renamed); - } - } finally { - restore_error_handler(); - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array - { - $failed = $this->doSaveCache($values, $lifetime); - - // Add Tags as symlinks - foreach ($addTagData as $tagId => $ids) { - $tagFolder = $this->getTagFolder($tagId); - foreach ($ids as $id) { - if ($failed && \in_array($id, $failed, true)) { - continue; - } - - $file = $this->getFile($id); - - if (!@symlink($file, $this->getFile($id, true, $tagFolder))) { - @unlink($file); - $failed[] = $id; - } - } - } - - // Unlink removed Tags - foreach ($removeTagData as $tagId => $ids) { - $tagFolder = $this->getTagFolder($tagId); - foreach ($ids as $id) { - if ($failed && \in_array($id, $failed, true)) { - continue; - } - - @unlink($this->getFile($id, false, $tagFolder)); - } - } - - return $failed; - } - - /** - * {@inheritdoc} - */ - protected function doDeleteYieldTags(array $ids): iterable - { - foreach ($ids as $id) { - $file = $this->getFile($id); - if (!file_exists($file) || !$h = @fopen($file, 'rb')) { - continue; - } - - if ((\PHP_VERSION_ID >= 70300 || '\\' !== \DIRECTORY_SEPARATOR) && !@unlink($file)) { - fclose($h); - continue; - } - - $meta = explode("\n", fread($h, 4096), 3)[2] ?? ''; - - // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F - if (13 < \strlen($meta) && "\x9D" === $meta[0] && "\0" === $meta[5] && "\x5F" === $meta[9]) { - $meta[9] = "\0"; - $tagLen = unpack('Nlen', $meta, 9)['len']; - $meta = substr($meta, 13, $tagLen); - - if (0 < $tagLen -= \strlen($meta)) { - $meta .= fread($h, $tagLen); - } - - try { - yield $id => '' === $meta ? [] : $this->marshaller->unmarshall($meta); - } catch (\Exception $e) { - yield $id => []; - } - } - - fclose($h); - - if (\PHP_VERSION_ID < 70300 && '\\' === \DIRECTORY_SEPARATOR) { - @unlink($file); - } - } - } - - /** - * {@inheritdoc} - */ - protected function doDeleteTagRelations(array $tagData): bool - { - foreach ($tagData as $tagId => $idList) { - $tagFolder = $this->getTagFolder($tagId); - foreach ($idList as $id) { - @unlink($this->getFile($id, false, $tagFolder)); - } - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doInvalidate(array $tagIds): bool - { - foreach ($tagIds as $tagId) { - if (!file_exists($tagFolder = $this->getTagFolder($tagId))) { - continue; - } - - set_error_handler(static function () {}); - - try { - if (rename($tagFolder, $renamed = substr_replace($tagFolder, bin2hex(random_bytes(4)), -9))) { - $tagFolder = $renamed.\DIRECTORY_SEPARATOR; - } else { - $renamed = null; - } - - foreach ($this->scanHashDir($tagFolder) as $itemLink) { - unlink(realpath($itemLink) ?: $itemLink); - unlink($itemLink); - } - - if (null === $renamed) { - continue; - } - - $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; - - for ($i = 0; $i < 38; ++$i) { - for ($j = 0; $j < 38; ++$j) { - rmdir($tagFolder.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j]); - } - rmdir($tagFolder.$chars[$i]); - } - rmdir($renamed); - } finally { - restore_error_handler(); - } - } - - return true; - } - - private function getTagFolder(string $tagId): string - { - return $this->getFile($tagId, false, $this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR; - } -} diff --git a/vendor/symfony/cache/Adapter/MemcachedAdapter.php b/vendor/symfony/cache/Adapter/MemcachedAdapter.php deleted file mode 100644 index e2bc068..0000000 --- a/vendor/symfony/cache/Adapter/MemcachedAdapter.php +++ /dev/null @@ -1,335 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Component\Cache\Exception\CacheException; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; - -/** - * @author Rob Frawley 2nd - * @author Nicolas Grekas - */ -class MemcachedAdapter extends AbstractAdapter -{ - protected $maxIdLength = 250; - - private static $defaultClientOptions = [ - 'persistent_id' => null, - 'username' => null, - 'password' => null, - \Memcached::OPT_SERIALIZER => \Memcached::SERIALIZER_PHP, - ]; - - private $marshaller; - private $client; - private $lazyClient; - - /** - * Using a MemcachedAdapter with a TagAwareAdapter for storing tags is discouraged. - * Using a RedisAdapter is recommended instead. If you cannot do otherwise, be aware that: - * - the Memcached::OPT_BINARY_PROTOCOL must be enabled - * (that's the default when using MemcachedAdapter::createConnection()); - * - tags eviction by Memcached's LRU algorithm will break by-tags invalidation; - * your Memcached memory should be large enough to never trigger LRU. - * - * Using a MemcachedAdapter as a pure items store is fine. - */ - public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) - { - if (!static::isSupported()) { - throw new CacheException('Memcached >= 2.2.0 is required'); - } - if ('Memcached' === \get_class($client)) { - $opt = $client->getOption(\Memcached::OPT_SERIALIZER); - if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { - throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); - } - $this->maxIdLength -= \strlen($client->getOption(\Memcached::OPT_PREFIX_KEY)); - $this->client = $client; - } else { - $this->lazyClient = $client; - } - - parent::__construct($namespace, $defaultLifetime); - $this->enableVersioning(); - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - } - - public static function isSupported() - { - return \extension_loaded('memcached') && version_compare(phpversion('memcached'), '2.2.0', '>='); - } - - /** - * Creates a Memcached instance. - * - * By default, the binary protocol, no block, and libketama compatible options are enabled. - * - * Examples for servers: - * - 'memcached://user:pass@localhost?weight=33' - * - [['localhost', 11211, 33]] - * - * @param array[]|string|string[] $servers An array of servers, a DSN, or an array of DSNs - * @param array $options An array of options - * - * @return \Memcached - * - * @throws \ErrorException When invalid options or servers are provided - */ - public static function createConnection($servers, array $options = []) - { - if (\is_string($servers)) { - $servers = [$servers]; - } elseif (!\is_array($servers)) { - throw new InvalidArgumentException(sprintf('MemcachedAdapter::createClient() expects array or string as first argument, %s given.', \gettype($servers))); - } - if (!static::isSupported()) { - throw new CacheException('Memcached >= 2.2.0 is required'); - } - set_error_handler(function ($type, $msg, $file, $line) { throw new \ErrorException($msg, 0, $type, $file, $line); }); - try { - $options += static::$defaultClientOptions; - $client = new \Memcached($options['persistent_id']); - $username = $options['username']; - $password = $options['password']; - - // parse any DSN in $servers - foreach ($servers as $i => $dsn) { - if (\is_array($dsn)) { - continue; - } - if (0 !== strpos($dsn, 'memcached:')) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s does not start with "memcached:"', $dsn)); - } - $params = preg_replace_callback('#^memcached:(//)?(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { - if (!empty($m[2])) { - list($username, $password) = explode(':', $m[2], 2) + [1 => null]; - } - - return 'file:'.($m[1] ?? ''); - }, $dsn); - if (false === $params = parse_url($params)) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $dsn)); - } - $query = $hosts = []; - if (isset($params['query'])) { - parse_str($params['query'], $query); - - if (isset($query['host'])) { - if (!\is_array($hosts = $query['host'])) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $dsn)); - } - foreach ($hosts as $host => $weight) { - if (false === $port = strrpos($host, ':')) { - $hosts[$host] = [$host, 11211, (int) $weight]; - } else { - $hosts[$host] = [substr($host, 0, $port), (int) substr($host, 1 + $port), (int) $weight]; - } - } - $hosts = array_values($hosts); - unset($query['host']); - } - if ($hosts && !isset($params['host']) && !isset($params['path'])) { - unset($servers[$i]); - $servers = array_merge($servers, $hosts); - continue; - } - } - if (!isset($params['host']) && !isset($params['path'])) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $dsn)); - } - if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { - $params['weight'] = $m[1]; - $params['path'] = substr($params['path'], 0, -\strlen($m[0])); - } - $params += [ - 'host' => isset($params['host']) ? $params['host'] : $params['path'], - 'port' => isset($params['host']) ? 11211 : null, - 'weight' => 0, - ]; - if ($query) { - $params += $query; - $options = $query + $options; - } - - $servers[$i] = [$params['host'], $params['port'], $params['weight']]; - - if ($hosts) { - $servers = array_merge($servers, $hosts); - } - } - - // set client's options - unset($options['persistent_id'], $options['username'], $options['password'], $options['weight'], $options['lazy']); - $options = array_change_key_case($options, CASE_UPPER); - $client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); - $client->setOption(\Memcached::OPT_NO_BLOCK, true); - $client->setOption(\Memcached::OPT_TCP_NODELAY, true); - if (!\array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !\array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) { - $client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true); - } - foreach ($options as $name => $value) { - if (\is_int($name)) { - continue; - } - if ('HASH' === $name || 'SERIALIZER' === $name || 'DISTRIBUTION' === $name) { - $value = \constant('Memcached::'.$name.'_'.strtoupper($value)); - } - $opt = \constant('Memcached::OPT_'.$name); - - unset($options[$name]); - $options[$opt] = $value; - } - $client->setOptions($options); - - // set client's servers, taking care of persistent connections - if (!$client->isPristine()) { - $oldServers = []; - foreach ($client->getServerList() as $server) { - $oldServers[] = [$server['host'], $server['port']]; - } - - $newServers = []; - foreach ($servers as $server) { - if (1 < \count($server)) { - $server = array_values($server); - unset($server[2]); - $server[1] = (int) $server[1]; - } - $newServers[] = $server; - } - - if ($oldServers !== $newServers) { - $client->resetServerList(); - $client->addServers($servers); - } - } else { - $client->addServers($servers); - } - - if (null !== $username || null !== $password) { - if (!method_exists($client, 'setSaslAuthData')) { - trigger_error('Missing SASL support: the memcached extension must be compiled with --enable-memcached-sasl.'); - } - $client->setSaslAuthData($username, $password); - } - - return $client; - } finally { - restore_error_handler(); - } - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - if (!$values = $this->marshaller->marshall($values, $failed)) { - return $failed; - } - - if ($lifetime && $lifetime > 30 * 86400) { - $lifetime += time(); - } - - $encodedValues = []; - foreach ($values as $key => $value) { - $encodedValues[rawurlencode($key)] = $value; - } - - return $this->checkResultCode($this->getClient()->setMulti($encodedValues, $lifetime)) ? $failed : false; - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - try { - $encodedIds = array_map('rawurlencode', $ids); - - $encodedResult = $this->checkResultCode($this->getClient()->getMulti($encodedIds)); - - $result = []; - foreach ($encodedResult as $key => $value) { - $result[rawurldecode($key)] = $this->marshaller->unmarshall($value); - } - - return $result; - } catch (\Error $e) { - throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); - } - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - return false !== $this->getClient()->get(rawurlencode($id)) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode()); - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - $ok = true; - $encodedIds = array_map('rawurlencode', $ids); - foreach ($this->checkResultCode($this->getClient()->deleteMulti($encodedIds)) as $result) { - if (\Memcached::RES_SUCCESS !== $result && \Memcached::RES_NOTFOUND !== $result) { - $ok = false; - } - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - return '' === $namespace && $this->getClient()->flush(); - } - - private function checkResultCode($result) - { - $code = $this->client->getResultCode(); - - if (\Memcached::RES_SUCCESS === $code || \Memcached::RES_NOTFOUND === $code) { - return $result; - } - - throw new CacheException(sprintf('MemcachedAdapter client error: %s.', strtolower($this->client->getResultMessage()))); - } - - private function getClient(): \Memcached - { - if ($this->client) { - return $this->client; - } - - $opt = $this->lazyClient->getOption(\Memcached::OPT_SERIALIZER); - if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { - throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); - } - if ('' !== $prefix = (string) $this->lazyClient->getOption(\Memcached::OPT_PREFIX_KEY)) { - throw new CacheException(sprintf('MemcachedAdapter: "prefix_key" option must be empty when using proxified connections, "%s" given.', $prefix)); - } - - return $this->client = $this->lazyClient; - } -} diff --git a/vendor/symfony/cache/Adapter/NullAdapter.php b/vendor/symfony/cache/Adapter/NullAdapter.php deleted file mode 100644 index 44778d7..0000000 --- a/vendor/symfony/cache/Adapter/NullAdapter.php +++ /dev/null @@ -1,154 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Contracts\Cache\CacheInterface; - -/** - * @author Titouan Galopin - */ -class NullAdapter implements AdapterInterface, CacheInterface -{ - private $createCacheItem; - - public function __construct() - { - $this->createCacheItem = \Closure::bind( - function ($key) { - $item = new CacheItem(); - $item->key = $key; - $item->isHit = false; - - return $item; - }, - $this, - CacheItem::class - ); - } - - /** - * {@inheritdoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - $save = true; - - return $callback(($this->createCacheItem)($key), $save); - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - $f = $this->createCacheItem; - - return $f($key); - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - return $this->generateItems($keys); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - return false; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - return false; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - return false; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function delete(string $key): bool - { - return $this->deleteItem($key); - } - - private function generateItems(array $keys) - { - $f = $this->createCacheItem; - - foreach ($keys as $key) { - yield $key => $f($key); - } - } -} diff --git a/vendor/symfony/cache/Adapter/PdoAdapter.php b/vendor/symfony/cache/Adapter/PdoAdapter.php deleted file mode 100644 index 79f9a33..0000000 --- a/vendor/symfony/cache/Adapter/PdoAdapter.php +++ /dev/null @@ -1,469 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\DBALException; -use Doctrine\DBAL\Driver\ServerInfoAwareConnection; -use Doctrine\DBAL\DriverManager; -use Doctrine\DBAL\Exception\TableNotFoundException; -use Doctrine\DBAL\Schema\Schema; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; -use Symfony\Component\Cache\PruneableInterface; - -class PdoAdapter extends AbstractAdapter implements PruneableInterface -{ - protected $maxIdLength = 255; - - private $marshaller; - private $conn; - private $dsn; - private $driver; - private $serverVersion; - private $table = 'cache_items'; - private $idCol = 'item_id'; - private $dataCol = 'item_data'; - private $lifetimeCol = 'item_lifetime'; - private $timeCol = 'item_time'; - private $username = ''; - private $password = ''; - private $connectionOptions = []; - private $namespace; - - /** - * You can either pass an existing database connection as PDO instance or - * a Doctrine DBAL Connection or a DSN string that will be used to - * lazy-connect to the database when the cache is actually used. - * - * When a Doctrine DBAL Connection is passed, the cache table is created - * automatically when possible. Otherwise, use the createTable() method. - * - * List of available options: - * * db_table: The name of the table [default: cache_items] - * * db_id_col: The column where to store the cache id [default: item_id] - * * db_data_col: The column where to store the cache data [default: item_data] - * * db_lifetime_col: The column where to store the lifetime [default: item_lifetime] - * * db_time_col: The column where to store the timestamp [default: item_time] - * * db_username: The username when lazy-connect [default: ''] - * * db_password: The password when lazy-connect [default: ''] - * * db_connection_options: An array of driver-specific connection options [default: []] - * - * @param \PDO|Connection|string $connOrDsn a \PDO or Connection instance or DSN string or null - * - * @throws InvalidArgumentException When first argument is not PDO nor Connection nor string - * @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION - * @throws InvalidArgumentException When namespace contains invalid characters - */ - public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null) - { - if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) { - throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0])); - } - - if ($connOrDsn instanceof \PDO) { - if (\PDO::ERRMODE_EXCEPTION !== $connOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { - throw new InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION))', __CLASS__)); - } - - $this->conn = $connOrDsn; - } elseif ($connOrDsn instanceof Connection) { - $this->conn = $connOrDsn; - } elseif (\is_string($connOrDsn)) { - $this->dsn = $connOrDsn; - } else { - throw new InvalidArgumentException(sprintf('"%s" requires PDO or Doctrine\DBAL\Connection instance or DSN string as first argument, "%s" given.', __CLASS__, \is_object($connOrDsn) ? \get_class($connOrDsn) : \gettype($connOrDsn))); - } - - $this->table = isset($options['db_table']) ? $options['db_table'] : $this->table; - $this->idCol = isset($options['db_id_col']) ? $options['db_id_col'] : $this->idCol; - $this->dataCol = isset($options['db_data_col']) ? $options['db_data_col'] : $this->dataCol; - $this->lifetimeCol = isset($options['db_lifetime_col']) ? $options['db_lifetime_col'] : $this->lifetimeCol; - $this->timeCol = isset($options['db_time_col']) ? $options['db_time_col'] : $this->timeCol; - $this->username = isset($options['db_username']) ? $options['db_username'] : $this->username; - $this->password = isset($options['db_password']) ? $options['db_password'] : $this->password; - $this->connectionOptions = isset($options['db_connection_options']) ? $options['db_connection_options'] : $this->connectionOptions; - $this->namespace = $namespace; - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - - parent::__construct($namespace, $defaultLifetime); - } - - /** - * Creates the table to store cache items which can be called once for setup. - * - * Cache ID are saved in a column of maximum length 255. Cache data is - * saved in a BLOB. - * - * @throws \PDOException When the table already exists - * @throws DBALException When the table already exists - * @throws \DomainException When an unsupported PDO driver is used - */ - public function createTable() - { - // connect if we are not yet - $conn = $this->getConnection(); - - if ($conn instanceof Connection) { - $types = [ - 'mysql' => 'binary', - 'sqlite' => 'text', - 'pgsql' => 'string', - 'oci' => 'string', - 'sqlsrv' => 'string', - ]; - if (!isset($types[$this->driver])) { - throw new \DomainException(sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $this->driver)); - } - - $schema = new Schema(); - $table = $schema->createTable($this->table); - $table->addColumn($this->idCol, $types[$this->driver], ['length' => 255]); - $table->addColumn($this->dataCol, 'blob', ['length' => 16777215]); - $table->addColumn($this->lifetimeCol, 'integer', ['unsigned' => true, 'notnull' => false]); - $table->addColumn($this->timeCol, 'integer', ['unsigned' => true]); - $table->setPrimaryKey([$this->idCol]); - - foreach ($schema->toSql($conn->getDatabasePlatform()) as $sql) { - $conn->exec($sql); - } - - return; - } - - switch ($this->driver) { - case 'mysql': - // We use varbinary for the ID column because it prevents unwanted conversions: - // - character set conversions between server and client - // - trailing space removal - // - case-insensitivity - // - language processing like é == e - $sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(255) NOT NULL PRIMARY KEY, $this->dataCol MEDIUMBLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8_bin, ENGINE = InnoDB"; - break; - case 'sqlite': - $sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)"; - break; - case 'pgsql': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)"; - break; - case 'oci': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR2(255) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)"; - break; - case 'sqlsrv': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(255) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER, $this->timeCol INTEGER NOT NULL)"; - break; - default: - throw new \DomainException(sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $this->driver)); - } - - $conn->exec($sql); - } - - /** - * {@inheritdoc} - */ - public function prune() - { - $deleteSql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= :time"; - - if ('' !== $this->namespace) { - $deleteSql .= " AND $this->idCol LIKE :namespace"; - } - - try { - $delete = $this->getConnection()->prepare($deleteSql); - } catch (TableNotFoundException $e) { - return true; - } catch (\PDOException $e) { - return true; - } - $delete->bindValue(':time', time(), \PDO::PARAM_INT); - - if ('' !== $this->namespace) { - $delete->bindValue(':namespace', sprintf('%s%%', $this->namespace), \PDO::PARAM_STR); - } - try { - return $delete->execute(); - } catch (TableNotFoundException $e) { - return true; - } catch (\PDOException $e) { - return true; - } - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - $now = time(); - $expired = []; - - $sql = str_pad('', (\count($ids) << 1) - 1, '?,'); - $sql = "SELECT $this->idCol, CASE WHEN $this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > ? THEN $this->dataCol ELSE NULL END FROM $this->table WHERE $this->idCol IN ($sql)"; - $stmt = $this->getConnection()->prepare($sql); - $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); - foreach ($ids as $id) { - $stmt->bindValue(++$i, $id); - } - $stmt->execute(); - - while ($row = $stmt->fetch(\PDO::FETCH_NUM)) { - if (null === $row[1]) { - $expired[] = $row[0]; - } else { - yield $row[0] => $this->marshaller->unmarshall(\is_resource($row[1]) ? stream_get_contents($row[1]) : $row[1]); - } - } - - if ($expired) { - $sql = str_pad('', (\count($expired) << 1) - 1, '?,'); - $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= ? AND $this->idCol IN ($sql)"; - $stmt = $this->getConnection()->prepare($sql); - $stmt->bindValue($i = 1, $now, \PDO::PARAM_INT); - foreach ($expired as $id) { - $stmt->bindValue(++$i, $id); - } - $stmt->execute(); - } - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - $sql = "SELECT 1 FROM $this->table WHERE $this->idCol = :id AND ($this->lifetimeCol IS NULL OR $this->lifetimeCol + $this->timeCol > :time)"; - $stmt = $this->getConnection()->prepare($sql); - - $stmt->bindValue(':id', $id); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - $stmt->execute(); - - return (bool) $stmt->fetchColumn(); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - $conn = $this->getConnection(); - - if ('' === $namespace) { - if ('sqlite' === $this->driver) { - $sql = "DELETE FROM $this->table"; - } else { - $sql = "TRUNCATE TABLE $this->table"; - } - } else { - $sql = "DELETE FROM $this->table WHERE $this->idCol LIKE '$namespace%'"; - } - - try { - $conn->exec($sql); - } catch (TableNotFoundException $e) { - } catch (\PDOException $e) { - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - $sql = str_pad('', (\count($ids) << 1) - 1, '?,'); - $sql = "DELETE FROM $this->table WHERE $this->idCol IN ($sql)"; - try { - $stmt = $this->getConnection()->prepare($sql); - $stmt->execute(array_values($ids)); - } catch (TableNotFoundException $e) { - } catch (\PDOException $e) { - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - if (!$values = $this->marshaller->marshall($values, $failed)) { - return $failed; - } - - $conn = $this->getConnection(); - $driver = $this->driver; - $insertSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)"; - - switch (true) { - case 'mysql' === $driver: - $sql = $insertSql." ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)"; - break; - case 'oci' === $driver: - // DUAL is Oracle specific dummy table - $sql = "MERGE INTO $this->table USING DUAL ON ($this->idCol = ?) ". - "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". - "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?"; - break; - case 'sqlsrv' === $driver && version_compare($this->getServerVersion(), '10', '>='): - // MERGE is only available since SQL Server 2008 and must be terminated by semicolon - // It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx - $sql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ". - "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". - "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;"; - break; - case 'sqlite' === $driver: - $sql = 'INSERT OR REPLACE'.substr($insertSql, 6); - break; - case 'pgsql' === $driver && version_compare($this->getServerVersion(), '9.5', '>='): - $sql = $insertSql." ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; - break; - default: - $driver = null; - $sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id"; - break; - } - - $now = time(); - $lifetime = $lifetime ?: null; - try { - $stmt = $conn->prepare($sql); - } catch (TableNotFoundException $e) { - if (!$conn->isTransactionActive() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { - $this->createTable(); - } - $stmt = $conn->prepare($sql); - } catch (\PDOException $e) { - if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { - $this->createTable(); - } - $stmt = $conn->prepare($sql); - } - - if ('sqlsrv' === $driver || 'oci' === $driver) { - $stmt->bindParam(1, $id); - $stmt->bindParam(2, $id); - $stmt->bindParam(3, $data, \PDO::PARAM_LOB); - $stmt->bindValue(4, $lifetime, \PDO::PARAM_INT); - $stmt->bindValue(5, $now, \PDO::PARAM_INT); - $stmt->bindParam(6, $data, \PDO::PARAM_LOB); - $stmt->bindValue(7, $lifetime, \PDO::PARAM_INT); - $stmt->bindValue(8, $now, \PDO::PARAM_INT); - } else { - $stmt->bindParam(':id', $id); - $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $stmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT); - $stmt->bindValue(':time', $now, \PDO::PARAM_INT); - } - if (null === $driver) { - $insertStmt = $conn->prepare($insertSql); - - $insertStmt->bindParam(':id', $id); - $insertStmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $insertStmt->bindValue(':lifetime', $lifetime, \PDO::PARAM_INT); - $insertStmt->bindValue(':time', $now, \PDO::PARAM_INT); - } - - foreach ($values as $id => $data) { - try { - $stmt->execute(); - } catch (TableNotFoundException $e) { - if (!$conn->isTransactionActive() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { - $this->createTable(); - } - $stmt->execute(); - } catch (\PDOException $e) { - if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { - $this->createTable(); - } - $stmt->execute(); - } - if (null === $driver && !$stmt->rowCount()) { - try { - $insertStmt->execute(); - } catch (DBALException $e) { - } catch (\PDOException $e) { - // A concurrent write won, let it be - } - } - } - - return $failed; - } - - /** - * @return \PDO|Connection - */ - private function getConnection(): object - { - if (null === $this->conn) { - if (strpos($this->dsn, '://')) { - if (!class_exists(DriverManager::class)) { - throw new InvalidArgumentException(sprintf('Failed to parse the DSN "%s". Try running "composer require doctrine/dbal".', $this->dsn)); - } - $this->conn = DriverManager::getConnection(['url' => $this->dsn]); - } else { - $this->conn = new \PDO($this->dsn, $this->username, $this->password, $this->connectionOptions); - $this->conn->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - } - } - if (null === $this->driver) { - if ($this->conn instanceof \PDO) { - $this->driver = $this->conn->getAttribute(\PDO::ATTR_DRIVER_NAME); - } else { - switch ($this->driver = $this->conn->getDriver()->getName()) { - case 'mysqli': - case 'pdo_mysql': - case 'drizzle_pdo_mysql': - $this->driver = 'mysql'; - break; - case 'pdo_sqlite': - $this->driver = 'sqlite'; - break; - case 'pdo_pgsql': - $this->driver = 'pgsql'; - break; - case 'oci8': - case 'pdo_oracle': - $this->driver = 'oci'; - break; - case 'pdo_sqlsrv': - $this->driver = 'sqlsrv'; - break; - } - } - } - - return $this->conn; - } - - private function getServerVersion(): string - { - if (null === $this->serverVersion) { - $conn = $this->conn instanceof \PDO ? $this->conn : $this->conn->getWrappedConnection(); - if ($conn instanceof \PDO) { - $this->serverVersion = $conn->getAttribute(\PDO::ATTR_SERVER_VERSION); - } elseif ($conn instanceof ServerInfoAwareConnection) { - $this->serverVersion = $conn->getServerVersion(); - } else { - $this->serverVersion = '0'; - } - } - - return $this->serverVersion; - } -} diff --git a/vendor/symfony/cache/Adapter/PhpArrayAdapter.php b/vendor/symfony/cache/Adapter/PhpArrayAdapter.php deleted file mode 100644 index 84946f6..0000000 --- a/vendor/symfony/cache/Adapter/PhpArrayAdapter.php +++ /dev/null @@ -1,432 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\ContractsTrait; -use Symfony\Component\Cache\Traits\ProxyTrait; -use Symfony\Component\VarExporter\VarExporter; -use Symfony\Contracts\Cache\CacheInterface; - -/** - * Caches items at warm up time using a PHP array that is stored in shared memory by OPCache since PHP 7.0. - * Warmed up items are read-only and run-time discovered items are cached using a fallback adapter. - * - * @author Titouan Galopin - * @author Nicolas Grekas - */ -class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface -{ - use ContractsTrait; - use ProxyTrait; - - private $file; - private $keys; - private $values; - private $createCacheItem; - - private static $valuesCache = []; - - /** - * @param string $file The PHP file were values are cached - * @param AdapterInterface $fallbackPool A pool to fallback on when an item is not hit - */ - public function __construct(string $file, AdapterInterface $fallbackPool) - { - $this->file = $file; - $this->pool = $fallbackPool; - $this->createCacheItem = \Closure::bind( - static function ($key, $value, $isHit) { - $item = new CacheItem(); - $item->key = $key; - $item->value = $value; - $item->isHit = $isHit; - - return $item; - }, - null, - CacheItem::class - ); - } - - /** - * This adapter takes advantage of how PHP stores arrays in its latest versions. - * - * @param string $file The PHP file were values are cached - * @param CacheItemPoolInterface $fallbackPool A pool to fallback on when an item is not hit - * - * @return CacheItemPoolInterface - */ - public static function create(string $file, CacheItemPoolInterface $fallbackPool) - { - if (!$fallbackPool instanceof AdapterInterface) { - $fallbackPool = new ProxyAdapter($fallbackPool); - } - - return new static($file, $fallbackPool); - } - - /** - * {@inheritdoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - if (null === $this->values) { - $this->initialize(); - } - if (!isset($this->keys[$key])) { - get_from_pool: - if ($this->pool instanceof CacheInterface) { - return $this->pool->get($key, $callback, $beta, $metadata); - } - - return $this->doGet($this->pool, $key, $callback, $beta, $metadata); - } - $value = $this->values[$this->keys[$key]]; - - if ('N;' === $value) { - return null; - } - try { - if ($value instanceof \Closure) { - return $value(); - } - } catch (\Throwable $e) { - unset($this->keys[$key]); - goto get_from_pool; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - if (!\is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); - } - if (null === $this->values) { - $this->initialize(); - } - if (!isset($this->keys[$key])) { - return $this->pool->getItem($key); - } - - $value = $this->values[$this->keys[$key]]; - $isHit = true; - - if ('N;' === $value) { - $value = null; - } elseif ($value instanceof \Closure) { - try { - $value = $value(); - } catch (\Throwable $e) { - $value = null; - $isHit = false; - } - } - - $f = $this->createCacheItem; - - return $f($key, $value, $isHit); - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - foreach ($keys as $key) { - if (!\is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); - } - } - if (null === $this->values) { - $this->initialize(); - } - - return $this->generateItems($keys); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - if (!\is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); - } - if (null === $this->values) { - $this->initialize(); - } - - return isset($this->keys[$key]) || $this->pool->hasItem($key); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - if (!\is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); - } - if (null === $this->values) { - $this->initialize(); - } - - return !isset($this->keys[$key]) && $this->pool->deleteItem($key); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - $deleted = true; - $fallbackKeys = []; - - foreach ($keys as $key) { - if (!\is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key))); - } - - if (isset($this->keys[$key])) { - $deleted = false; - } else { - $fallbackKeys[] = $key; - } - } - if (null === $this->values) { - $this->initialize(); - } - - if ($fallbackKeys) { - $deleted = $this->pool->deleteItems($fallbackKeys) && $deleted; - } - - return $deleted; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - if (null === $this->values) { - $this->initialize(); - } - - return !isset($this->keys[$item->getKey()]) && $this->pool->save($item); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - if (null === $this->values) { - $this->initialize(); - } - - return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - return $this->pool->commit(); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - $this->keys = $this->values = []; - - $cleared = @unlink($this->file) || !file_exists($this->file); - unset(self::$valuesCache[$this->file]); - - if ($this->pool instanceof AdapterInterface) { - return $this->pool->clear($prefix) && $cleared; - } - - return $this->pool->clear() && $cleared; - } - - /** - * Store an array of cached values. - * - * @param array $values The cached values - */ - public function warmUp(array $values) - { - if (file_exists($this->file)) { - if (!is_file($this->file)) { - throw new InvalidArgumentException(sprintf('Cache path exists and is not a file: %s.', $this->file)); - } - - if (!is_writable($this->file)) { - throw new InvalidArgumentException(sprintf('Cache file is not writable: %s.', $this->file)); - } - } else { - $directory = \dirname($this->file); - - if (!is_dir($directory) && !@mkdir($directory, 0777, true)) { - throw new InvalidArgumentException(sprintf('Cache directory does not exist and cannot be created: %s.', $directory)); - } - - if (!is_writable($directory)) { - throw new InvalidArgumentException(sprintf('Cache directory is not writable: %s.', $directory)); - } - } - - $dumpedValues = ''; - $dumpedMap = []; - $dump = <<<'EOF' - $value) { - CacheItem::validateKey(\is_int($key) ? (string) $key : $key); - $isStaticValue = true; - - if (null === $value) { - $value = "'N;'"; - } elseif (\is_object($value) || \is_array($value)) { - try { - $value = VarExporter::export($value, $isStaticValue); - } catch (\Exception $e) { - throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, \is_object($value) ? \get_class($value) : 'array'), 0, $e); - } - } elseif (\is_string($value)) { - // Wrap "N;" in a closure to not confuse it with an encoded `null` - if ('N;' === $value) { - $isStaticValue = false; - } - $value = var_export($value, true); - } elseif (!is_scalar($value)) { - throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, \gettype($value))); - } else { - $value = var_export($value, true); - } - - if (!$isStaticValue) { - $value = str_replace("\n", "\n ", $value); - $value = "static function () {\n return {$value};\n}"; - } - $hash = hash('md5', $value); - - if (null === $id = $dumpedMap[$hash] ?? null) { - $id = $dumpedMap[$hash] = \count($dumpedMap); - $dumpedValues .= "{$id} => {$value},\n"; - } - - $dump .= var_export($key, true)." => {$id},\n"; - } - - $dump .= "\n], [\n\n{$dumpedValues}\n]];\n"; - - $tmpFile = uniqid($this->file, true); - - file_put_contents($tmpFile, $dump); - @chmod($tmpFile, 0666 & ~umask()); - unset($serialized, $value, $dump); - - @rename($tmpFile, $this->file); - unset(self::$valuesCache[$this->file]); - - $this->initialize(); - } - - /** - * Load the cache file. - */ - private function initialize() - { - if (isset(self::$valuesCache[$this->file])) { - $values = self::$valuesCache[$this->file]; - } elseif (!file_exists($this->file)) { - $this->keys = $this->values = []; - - return; - } else { - $values = self::$valuesCache[$this->file] = (include $this->file) ?: [[], []]; - } - - if (2 !== \count($values) || !isset($values[0], $values[1])) { - $this->keys = $this->values = []; - } else { - list($this->keys, $this->values) = $values; - } - } - - private function generateItems(array $keys): \Generator - { - $f = $this->createCacheItem; - $fallbackKeys = []; - - foreach ($keys as $key) { - if (isset($this->keys[$key])) { - $value = $this->values[$this->keys[$key]]; - - if ('N;' === $value) { - yield $key => $f($key, null, true); - } elseif ($value instanceof \Closure) { - try { - yield $key => $f($key, $value(), true); - } catch (\Throwable $e) { - yield $key => $f($key, null, false); - } - } else { - yield $key => $f($key, $value, true); - } - } else { - $fallbackKeys[] = $key; - } - } - - if ($fallbackKeys) { - yield from $this->pool->getItems($fallbackKeys); - } - } -} diff --git a/vendor/symfony/cache/Adapter/PhpFilesAdapter.php b/vendor/symfony/cache/Adapter/PhpFilesAdapter.php deleted file mode 100644 index f148a89..0000000 --- a/vendor/symfony/cache/Adapter/PhpFilesAdapter.php +++ /dev/null @@ -1,330 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Component\Cache\Exception\CacheException; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\Traits\FilesystemCommonTrait; -use Symfony\Component\VarExporter\VarExporter; - -/** - * @author Piotr Stankowski - * @author Nicolas Grekas - * @author Rob Frawley 2nd - */ -class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface -{ - use FilesystemCommonTrait { - doClear as private doCommonClear; - doDelete as private doCommonDelete; - } - - private $includeHandler; - private $appendOnly; - private $values = []; - private $files = []; - - private static $startTime; - private static $valuesCache = []; - - /** - * @param $appendOnly Set to `true` to gain extra performance when the items stored in this pool never expire. - * Doing so is encouraged because it fits perfectly OPcache's memory model. - * - * @throws CacheException if OPcache is not enabled - */ - public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, bool $appendOnly = false) - { - $this->appendOnly = $appendOnly; - self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time(); - parent::__construct('', $defaultLifetime); - $this->init($namespace, $directory); - $this->includeHandler = static function ($type, $msg, $file, $line) { - throw new \ErrorException($msg, 0, $type, $file, $line); - }; - } - - public static function isSupported() - { - self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time(); - - return \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(ini_get('opcache.enable_cli'), FILTER_VALIDATE_BOOLEAN)); - } - - /** - * @return bool - */ - public function prune() - { - $time = time(); - $pruned = true; - $getExpiry = true; - - set_error_handler($this->includeHandler); - try { - foreach ($this->scanHashDir($this->directory) as $file) { - try { - if (\is_array($expiresAt = include $file)) { - $expiresAt = $expiresAt[0]; - } - } catch (\ErrorException $e) { - $expiresAt = $time; - } - - if ($time >= $expiresAt) { - $pruned = $this->doUnlink($file) && !file_exists($file) && $pruned; - } - } - } finally { - restore_error_handler(); - } - - return $pruned; - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - if ($this->appendOnly) { - $now = 0; - $missingIds = []; - } else { - $now = time(); - $missingIds = $ids; - $ids = []; - } - $values = []; - - begin: - $getExpiry = false; - - foreach ($ids as $id) { - if (null === $value = $this->values[$id] ?? null) { - $missingIds[] = $id; - } elseif ('N;' === $value) { - $values[$id] = null; - } elseif (!\is_object($value)) { - $values[$id] = $value; - } elseif (!$value instanceof LazyValue) { - $values[$id] = $value(); - } elseif (false === $values[$id] = include $value->file) { - unset($values[$id], $this->values[$id]); - $missingIds[] = $id; - } - if (!$this->appendOnly) { - unset($this->values[$id]); - } - } - - if (!$missingIds) { - return $values; - } - - set_error_handler($this->includeHandler); - try { - $getExpiry = true; - - foreach ($missingIds as $k => $id) { - try { - $file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id); - - if (isset(self::$valuesCache[$file])) { - [$expiresAt, $this->values[$id]] = self::$valuesCache[$file]; - } elseif (\is_array($expiresAt = include $file)) { - if ($this->appendOnly) { - self::$valuesCache[$file] = $expiresAt; - } - - [$expiresAt, $this->values[$id]] = $expiresAt; - } elseif ($now < $expiresAt) { - $this->values[$id] = new LazyValue($file); - } - - if ($now >= $expiresAt) { - unset($this->values[$id], $missingIds[$k], self::$valuesCache[$file]); - } - } catch (\ErrorException $e) { - unset($missingIds[$k]); - } - } - } finally { - restore_error_handler(); - } - - $ids = $missingIds; - $missingIds = []; - goto begin; - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - if ($this->appendOnly && isset($this->values[$id])) { - return true; - } - - set_error_handler($this->includeHandler); - try { - $file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id); - $getExpiry = true; - - if (isset(self::$valuesCache[$file])) { - [$expiresAt, $value] = self::$valuesCache[$file]; - } elseif (\is_array($expiresAt = include $file)) { - if ($this->appendOnly) { - self::$valuesCache[$file] = $expiresAt; - } - - [$expiresAt, $value] = $expiresAt; - } elseif ($this->appendOnly) { - $value = new LazyValue($file); - } - } catch (\ErrorException $e) { - return false; - } finally { - restore_error_handler(); - } - if ($this->appendOnly) { - $now = 0; - $this->values[$id] = $value; - } else { - $now = time(); - } - - return $now < $expiresAt; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - $ok = true; - $expiry = $lifetime ? time() + $lifetime : 'PHP_INT_MAX'; - $allowCompile = self::isSupported(); - - foreach ($values as $key => $value) { - unset($this->values[$key]); - $isStaticValue = true; - if (null === $value) { - $value = "'N;'"; - } elseif (\is_object($value) || \is_array($value)) { - try { - $value = VarExporter::export($value, $isStaticValue); - } catch (\Exception $e) { - throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, \is_object($value) ? \get_class($value) : 'array'), 0, $e); - } - } elseif (\is_string($value)) { - // Wrap "N;" in a closure to not confuse it with an encoded `null` - if ('N;' === $value) { - $isStaticValue = false; - } - $value = var_export($value, true); - } elseif (!is_scalar($value)) { - throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.', $key, \gettype($value))); - } else { - $value = var_export($value, true); - } - - $encodedKey = rawurlencode($key); - - if ($isStaticValue) { - $value = "return [{$expiry}, {$value}];"; - } elseif ($this->appendOnly) { - $value = "return [{$expiry}, static function () { return {$value}; }];"; - } else { - // We cannot use a closure here because of https://bugs.php.net/76982 - $value = str_replace('\Symfony\Component\VarExporter\Internal\\', '', $value); - $value = "namespace Symfony\Component\VarExporter\Internal;\n\nreturn \$getExpiry ? {$expiry} : {$value};"; - } - - $file = $this->files[$key] = $this->getFile($key, true); - // Since OPcache only compiles files older than the script execution start, set the file's mtime in the past - $ok = $this->write($file, "directory)) { - throw new CacheException(sprintf('Cache directory is not writable (%s)', $this->directory)); - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - $this->values = []; - - return $this->doCommonClear($namespace); - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - foreach ($ids as $id) { - unset($this->values[$id]); - } - - return $this->doCommonDelete($ids); - } - - protected function doUnlink($file) - { - unset(self::$valuesCache[$file]); - - if (self::isSupported()) { - @opcache_invalidate($file, true); - } - - return @unlink($file); - } - - private function getFileKey(string $file): string - { - if (!$h = @fopen($file, 'rb')) { - return ''; - } - - $encodedKey = substr(fgets($h), 8); - fclose($h); - - return rawurldecode(rtrim($encodedKey)); - } -} - -/** - * @internal - */ -class LazyValue -{ - public $file; - - public function __construct($file) - { - $this->file = $file; - } -} diff --git a/vendor/symfony/cache/Adapter/ProxyAdapter.php b/vendor/symfony/cache/Adapter/ProxyAdapter.php deleted file mode 100644 index bd96fa8..0000000 --- a/vendor/symfony/cache/Adapter/ProxyAdapter.php +++ /dev/null @@ -1,265 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\ContractsTrait; -use Symfony\Component\Cache\Traits\ProxyTrait; -use Symfony\Contracts\Cache\CacheInterface; - -/** - * @author Nicolas Grekas - */ -class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface -{ - use ProxyTrait; - use ContractsTrait; - - private $namespace; - private $namespaceLen; - private $createCacheItem; - private $setInnerItem; - private $poolHash; - - public function __construct(CacheItemPoolInterface $pool, string $namespace = '', int $defaultLifetime = 0) - { - $this->pool = $pool; - $this->poolHash = $poolHash = spl_object_hash($pool); - $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace); - $this->namespaceLen = \strlen($namespace); - $this->createCacheItem = \Closure::bind( - static function ($key, $innerItem) use ($defaultLifetime, $poolHash) { - $item = new CacheItem(); - $item->key = $key; - - if (null === $innerItem) { - return $item; - } - - $item->value = $v = $innerItem->get(); - $item->isHit = $innerItem->isHit(); - $item->innerItem = $innerItem; - $item->defaultLifetime = $defaultLifetime; - $item->poolHash = $poolHash; - - // Detect wrapped values that encode for their expiry and creation duration - // For compactness, these values are packed in the key of an array using - // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F - if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = key($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) { - $item->value = $v[$k]; - $v = unpack('Ve/Nc', substr($k, 1, -1)); - $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; - $item->metadata[CacheItem::METADATA_CTIME] = $v['c']; - } elseif ($innerItem instanceof CacheItem) { - $item->metadata = $innerItem->metadata; - } - $innerItem->set(null); - - return $item; - }, - null, - CacheItem::class - ); - $this->setInnerItem = \Closure::bind( - /** - * @param array $item A CacheItem cast to (array); accessing protected properties requires adding the "\0*\0" PHP prefix - */ - static function (CacheItemInterface $innerItem, array $item) { - // Tags are stored separately, no need to account for them when considering this item's newly set metadata - if (isset(($metadata = $item["\0*\0newMetadata"])[CacheItem::METADATA_TAGS])) { - unset($metadata[CacheItem::METADATA_TAGS]); - } - if ($metadata) { - // For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators - $item["\0*\0value"] = ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item["\0*\0value"]]; - } - $innerItem->set($item["\0*\0value"]); - $innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6f', $item["\0*\0expiry"])) : null); - }, - null, - CacheItem::class - ); - } - - /** - * {@inheritdoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - if (!$this->pool instanceof CacheInterface) { - return $this->doGet($this, $key, $callback, $beta, $metadata); - } - - return $this->pool->get($this->getId($key), function ($innerItem, bool &$save) use ($key, $callback) { - $item = ($this->createCacheItem)($key, $innerItem); - $item->set($value = $callback($item, $save)); - ($this->setInnerItem)($innerItem, (array) $item); - - return $value; - }, $beta, $metadata); - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - $f = $this->createCacheItem; - $item = $this->pool->getItem($this->getId($key)); - - return $f($key, $item); - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - if ($this->namespaceLen) { - foreach ($keys as $i => $key) { - $keys[$i] = $this->getId($key); - } - } - - return $this->generateItems($this->pool->getItems($keys)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - return $this->pool->hasItem($this->getId($key)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - if ($this->pool instanceof AdapterInterface) { - return $this->pool->clear($this->namespace.$prefix); - } - - return $this->pool->clear(); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - return $this->pool->deleteItem($this->getId($key)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - if ($this->namespaceLen) { - foreach ($keys as $i => $key) { - $keys[$i] = $this->getId($key); - } - } - - return $this->pool->deleteItems($keys); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - return $this->doSave($item, __FUNCTION__); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - return $this->doSave($item, __FUNCTION__); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - return $this->pool->commit(); - } - - private function doSave(CacheItemInterface $item, string $method) - { - if (!$item instanceof CacheItem) { - return false; - } - $item = (array) $item; - if (null === $item["\0*\0expiry"] && 0 < $item["\0*\0defaultLifetime"]) { - $item["\0*\0expiry"] = microtime(true) + $item["\0*\0defaultLifetime"]; - } - - if ($item["\0*\0poolHash"] === $this->poolHash && $item["\0*\0innerItem"]) { - $innerItem = $item["\0*\0innerItem"]; - } elseif ($this->pool instanceof AdapterInterface) { - // this is an optimization specific for AdapterInterface implementations - // so we can save a round-trip to the backend by just creating a new item - $f = $this->createCacheItem; - $innerItem = $f($this->namespace.$item["\0*\0key"], null); - } else { - $innerItem = $this->pool->getItem($this->namespace.$item["\0*\0key"]); - } - - ($this->setInnerItem)($innerItem, $item); - - return $this->pool->$method($innerItem); - } - - private function generateItems(iterable $items) - { - $f = $this->createCacheItem; - - foreach ($items as $key => $item) { - if ($this->namespaceLen) { - $key = substr($key, $this->namespaceLen); - } - - yield $key => $f($key, $item); - } - } - - private function getId($key): string - { - CacheItem::validateKey($key); - - return $this->namespace.$key; - } -} diff --git a/vendor/symfony/cache/Adapter/Psr16Adapter.php b/vendor/symfony/cache/Adapter/Psr16Adapter.php deleted file mode 100644 index a13b20e..0000000 --- a/vendor/symfony/cache/Adapter/Psr16Adapter.php +++ /dev/null @@ -1,86 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\ProxyTrait; - -/** - * Turns a PSR-16 cache into a PSR-6 one. - * - * @author Nicolas Grekas - */ -class Psr16Adapter extends AbstractAdapter implements PruneableInterface, ResettableInterface -{ - /** - * @internal - */ - protected const NS_SEPARATOR = '_'; - - use ProxyTrait; - - private $miss; - - public function __construct(CacheInterface $pool, string $namespace = '', int $defaultLifetime = 0) - { - parent::__construct($namespace, $defaultLifetime); - - $this->pool = $pool; - $this->miss = new \stdClass(); - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - foreach ($this->pool->getMultiple($ids, $this->miss) as $key => $value) { - if ($this->miss !== $value) { - yield $key => $value; - } - } - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - return $this->pool->has($id); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - return $this->pool->clear(); - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - return $this->pool->deleteMultiple($ids); - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - return $this->pool->setMultiple($values, 0 === $lifetime ? null : $lifetime); - } -} diff --git a/vendor/symfony/cache/Adapter/RedisAdapter.php b/vendor/symfony/cache/Adapter/RedisAdapter.php deleted file mode 100644 index 5c49f7a..0000000 --- a/vendor/symfony/cache/Adapter/RedisAdapter.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Component\Cache\Marshaller\MarshallerInterface; -use Symfony\Component\Cache\Traits\RedisTrait; - -class RedisAdapter extends AbstractAdapter -{ - use RedisTrait; - - /** - * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface $redisClient The redis client - * @param string $namespace The default namespace - * @param int $defaultLifetime The default lifetime - */ - public function __construct($redisClient, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) - { - $this->init($redisClient, $namespace, $defaultLifetime, $marshaller); - } -} diff --git a/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php b/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php deleted file mode 100644 index acdfa88..0000000 --- a/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php +++ /dev/null @@ -1,292 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Predis\Connection\Aggregate\ClusterInterface; -use Predis\Connection\Aggregate\PredisCluster; -use Predis\Response\Status; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Marshaller\DeflateMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; -use Symfony\Component\Cache\Marshaller\TagAwareMarshaller; -use Symfony\Component\Cache\Traits\RedisTrait; - -/** - * Stores tag id <> cache id relationship as a Redis Set, lookup on invalidation using RENAME+SMEMBERS. - * - * Set (tag relation info) is stored without expiry (non-volatile), while cache always gets an expiry (volatile) even - * if not set by caller. Thus if you configure redis with the right eviction policy you can be safe this tag <> cache - * relationship survives eviction (cache cleanup when Redis runs out of memory). - * - * Requirements: - * - Client: PHP Redis or Predis - * Note: Due to lack of RENAME support it is NOT recommended to use Cluster on Predis, instead use phpredis. - * - Server: Redis 2.8+ - * Configured with any `volatile-*` eviction policy, OR `noeviction` if it will NEVER fill up memory - * - * Design limitations: - * - Max 4 billion cache keys per cache tag as limited by Redis Set datatype. - * E.g. If you use a "all" items tag for expiry instead of clear(), that limits you to 4 billion cache items also. - * - * @see https://redis.io/topics/lru-cache#eviction-policies Documentation for Redis eviction policies. - * @see https://redis.io/topics/data-types#sets Documentation for Redis Set datatype. - * - * @author Nicolas Grekas - * @author André Rømcke - */ -class RedisTagAwareAdapter extends AbstractTagAwareAdapter -{ - use RedisTrait; - - /** - * Limits for how many keys are deleted in batch. - */ - private const BULK_DELETE_LIMIT = 10000; - - /** - * On cache items without a lifetime set, we set it to 100 days. This is to make sure cache items are - * preferred to be evicted over tag Sets, if eviction policy is configured according to requirements. - */ - private const DEFAULT_CACHE_TTL = 8640000; - - /** - * @var string|null detected eviction policy used on Redis server - */ - private $redisEvictionPolicy; - - /** - * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface $redisClient The redis client - * @param string $namespace The default namespace - * @param int $defaultLifetime The default lifetime - */ - public function __construct($redisClient, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) - { - if ($redisClient instanceof \Predis\ClientInterface && $redisClient->getConnection() instanceof ClusterInterface && !$redisClient->getConnection() instanceof PredisCluster) { - throw new InvalidArgumentException(sprintf('Unsupported Predis cluster connection: only "%s" is, "%s" given.', PredisCluster::class, \get_class($redisClient->getConnection()))); - } - - if (\defined('Redis::OPT_COMPRESSION') && ($redisClient instanceof \Redis || $redisClient instanceof \RedisArray || $redisClient instanceof \RedisCluster)) { - $compression = $redisClient->getOption(\Redis::OPT_COMPRESSION); - - foreach (\is_array($compression) ? $compression : [$compression] as $c) { - if (\Redis::COMPRESSION_NONE !== $c) { - throw new InvalidArgumentException(sprintf('phpredis compression must be disabled when using "%s", use "%s" instead.', \get_class($this), DeflateMarshaller::class)); - } - } - } - - $this->init($redisClient, $namespace, $defaultLifetime, new TagAwareMarshaller($marshaller)); - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime, array $addTagData = [], array $delTagData = []): array - { - $eviction = $this->getRedisEvictionPolicy(); - if ('noeviction' !== $eviction && 0 !== strpos($eviction, 'volatile-')) { - CacheItem::log($this->logger, sprintf('Redis maxmemory-policy setting "%s" is *not* supported by RedisTagAwareAdapter, use "noeviction" or "volatile-*" eviction policies', $eviction)); - - return false; - } - - // serialize values - if (!$serialized = $this->marshaller->marshall($values, $failed)) { - return $failed; - } - - // While pipeline isn't supported on RedisCluster, other setups will at least benefit from doing this in one op - $results = $this->pipeline(static function () use ($serialized, $lifetime, $addTagData, $delTagData, $failed) { - // Store cache items, force a ttl if none is set, as there is no MSETEX we need to set each one - foreach ($serialized as $id => $value) { - yield 'setEx' => [ - $id, - 0 >= $lifetime ? self::DEFAULT_CACHE_TTL : $lifetime, - $value, - ]; - } - - // Add and Remove Tags - foreach ($addTagData as $tagId => $ids) { - if (!$failed || $ids = array_diff($ids, $failed)) { - yield 'sAdd' => array_merge([$tagId], $ids); - } - } - - foreach ($delTagData as $tagId => $ids) { - if (!$failed || $ids = array_diff($ids, $failed)) { - yield 'sRem' => array_merge([$tagId], $ids); - } - } - }); - - foreach ($results as $id => $result) { - // Skip results of SADD/SREM operations, they'll be 1 or 0 depending on if set value already existed or not - if (is_numeric($result)) { - continue; - } - // setEx results - if (true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) { - $failed[] = $id; - } - } - - return $failed; - } - - /** - * {@inheritdoc} - */ - protected function doDeleteYieldTags(array $ids): iterable - { - $lua = <<<'EOLUA' - local v = redis.call('GET', KEYS[1]) - redis.call('DEL', KEYS[1]) - - if not v or v:len() <= 13 or v:byte(1) ~= 0x9D or v:byte(6) ~= 0 or v:byte(10) ~= 0x5F then - return '' - end - - return v:sub(14, 13 + v:byte(13) + v:byte(12) * 256 + v:byte(11) * 65536) -EOLUA; - - if ($this->redis instanceof \Predis\ClientInterface) { - $evalArgs = [$lua, 1, &$id]; - } else { - $evalArgs = [$lua, [&$id], 1]; - } - - $results = $this->pipeline(function () use ($ids, &$id, $evalArgs) { - foreach ($ids as $id) { - yield 'eval' => $evalArgs; - } - }); - - foreach ($results as $id => $result) { - try { - yield $id => !\is_string($result) || '' === $result ? [] : $this->marshaller->unmarshall($result); - } catch (\Exception $e) { - yield $id => []; - } - } - } - - /** - * {@inheritdoc} - */ - protected function doDeleteTagRelations(array $tagData): bool - { - $this->pipeline(static function () use ($tagData) { - foreach ($tagData as $tagId => $idList) { - array_unshift($idList, $tagId); - yield 'sRem' => $idList; - } - })->rewind(); - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doInvalidate(array $tagIds): bool - { - if (!$this->redis instanceof \Predis\ClientInterface || !$this->redis->getConnection() instanceof PredisCluster) { - $movedTagSetIds = $this->renameKeys($this->redis, $tagIds); - } else { - $clusterConnection = $this->redis->getConnection(); - $tagIdsByConnection = new \SplObjectStorage(); - $movedTagSetIds = []; - - foreach ($tagIds as $id) { - $connection = $clusterConnection->getConnectionByKey($id); - $slot = $tagIdsByConnection[$connection] ?? $tagIdsByConnection[$connection] = new \ArrayObject(); - $slot[] = $id; - } - - foreach ($tagIdsByConnection as $connection) { - $slot = $tagIdsByConnection[$connection]; - $movedTagSetIds = array_merge($movedTagSetIds, $this->renameKeys(new $this->redis($connection, $this->redis->getOptions()), $slot->getArrayCopy())); - } - } - - // No Sets found - if (!$movedTagSetIds) { - return false; - } - - // Now safely take the time to read the keys in each set and collect ids we need to delete - $tagIdSets = $this->pipeline(static function () use ($movedTagSetIds) { - foreach ($movedTagSetIds as $movedTagId) { - yield 'sMembers' => [$movedTagId]; - } - }); - - // Return combination of the temporary Tag Set ids and their values (cache ids) - $ids = array_merge($movedTagSetIds, ...iterator_to_array($tagIdSets, false)); - - // Delete cache in chunks to avoid overloading the connection - foreach (array_chunk(array_unique($ids), self::BULK_DELETE_LIMIT) as $chunkIds) { - $this->doDelete($chunkIds); - } - - return true; - } - - /** - * Renames several keys in order to be able to operate on them without risk of race conditions. - * - * Filters out keys that do not exist before returning new keys. - * - * @see https://redis.io/commands/rename - * @see https://redis.io/topics/cluster-spec#keys-hash-tags - * - * @return array Filtered list of the valid moved keys (only those that existed) - */ - private function renameKeys($redis, array $ids): array - { - $newIds = []; - $uniqueToken = bin2hex(random_bytes(10)); - - $results = $this->pipeline(static function () use ($ids, $uniqueToken) { - foreach ($ids as $id) { - yield 'rename' => [$id, '{'.$id.'}'.$uniqueToken]; - } - }, $redis); - - foreach ($results as $id => $result) { - if (true === $result || ($result instanceof Status && Status::get('OK') === $result)) { - // Only take into account if ok (key existed), will be false on phpredis if it did not exist - $newIds[] = '{'.$id.'}'.$uniqueToken; - } - } - - return $newIds; - } - - private function getRedisEvictionPolicy(): string - { - if (null !== $this->redisEvictionPolicy) { - return $this->redisEvictionPolicy; - } - - foreach ($this->getHosts() as $host) { - $info = $host->info('Memory'); - $info = isset($info['Memory']) ? $info['Memory'] : $info; - - return $this->redisEvictionPolicy = $info['maxmemory_policy']; - } - - return $this->redisEvictionPolicy = ''; - } -} diff --git a/vendor/symfony/cache/Adapter/TagAwareAdapter.php b/vendor/symfony/cache/Adapter/TagAwareAdapter.php deleted file mode 100644 index 793df43..0000000 --- a/vendor/symfony/cache/Adapter/TagAwareAdapter.php +++ /dev/null @@ -1,425 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Psr\Cache\InvalidArgumentException; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Cache\Traits\ContractsTrait; -use Symfony\Component\Cache\Traits\ProxyTrait; -use Symfony\Contracts\Cache\TagAwareCacheInterface; - -/** - * @author Nicolas Grekas - */ -class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, PruneableInterface, ResettableInterface -{ - const TAGS_PREFIX = "\0tags\0"; - - use ProxyTrait; - use ContractsTrait; - - private $deferred = []; - private $createCacheItem; - private $setCacheItemTags; - private $getTagsByKey; - private $invalidateTags; - private $tags; - private $knownTagVersions = []; - private $knownTagVersionsTtl; - - public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15) - { - $this->pool = $itemsPool; - $this->tags = $tagsPool ?: $itemsPool; - $this->knownTagVersionsTtl = $knownTagVersionsTtl; - $this->createCacheItem = \Closure::bind( - static function ($key, $value, CacheItem $protoItem) { - $item = new CacheItem(); - $item->key = $key; - $item->value = $value; - $item->defaultLifetime = $protoItem->defaultLifetime; - $item->expiry = $protoItem->expiry; - $item->poolHash = $protoItem->poolHash; - - return $item; - }, - null, - CacheItem::class - ); - $this->setCacheItemTags = \Closure::bind( - static function (CacheItem $item, $key, array &$itemTags) { - $item->isTaggable = true; - if (!$item->isHit) { - return $item; - } - if (isset($itemTags[$key])) { - foreach ($itemTags[$key] as $tag => $version) { - $item->metadata[CacheItem::METADATA_TAGS][$tag] = $tag; - } - unset($itemTags[$key]); - } else { - $item->value = null; - $item->isHit = false; - } - - return $item; - }, - null, - CacheItem::class - ); - $this->getTagsByKey = \Closure::bind( - static function ($deferred) { - $tagsByKey = []; - foreach ($deferred as $key => $item) { - $tagsByKey[$key] = $item->newMetadata[CacheItem::METADATA_TAGS] ?? []; - } - - return $tagsByKey; - }, - null, - CacheItem::class - ); - $this->invalidateTags = \Closure::bind( - static function (AdapterInterface $tagsAdapter, array $tags) { - foreach ($tags as $v) { - $v->defaultLifetime = 0; - $v->expiry = null; - $tagsAdapter->saveDeferred($v); - } - - return $tagsAdapter->commit(); - }, - null, - CacheItem::class - ); - } - - /** - * {@inheritdoc} - */ - public function invalidateTags(array $tags) - { - $ok = true; - $tagsByKey = []; - $invalidatedTags = []; - foreach ($tags as $tag) { - CacheItem::validateKey($tag); - $invalidatedTags[$tag] = 0; - } - - if ($this->deferred) { - $items = $this->deferred; - foreach ($items as $key => $item) { - if (!$this->pool->saveDeferred($item)) { - unset($this->deferred[$key]); - $ok = false; - } - } - - $f = $this->getTagsByKey; - $tagsByKey = $f($items); - $this->deferred = []; - } - - $tagVersions = $this->getTagVersions($tagsByKey, $invalidatedTags); - $f = $this->createCacheItem; - - foreach ($tagsByKey as $key => $tags) { - $this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key])); - } - $ok = $this->pool->commit() && $ok; - - if ($invalidatedTags) { - $f = $this->invalidateTags; - $ok = $f($this->tags, $invalidatedTags) && $ok; - } - - return $ok; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - if ($this->deferred) { - $this->commit(); - } - if (!$this->pool->hasItem($key)) { - return false; - } - - $itemTags = $this->pool->getItem(static::TAGS_PREFIX.$key); - - if (!$itemTags->isHit()) { - return false; - } - - if (!$itemTags = $itemTags->get()) { - return true; - } - - foreach ($this->getTagVersions([$itemTags]) as $tag => $version) { - if ($itemTags[$tag] !== $version && 1 !== $itemTags[$tag] - $version) { - return false; - } - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - foreach ($this->getItems([$key]) as $item) { - return $item; - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - if ($this->deferred) { - $this->commit(); - } - $tagKeys = []; - - foreach ($keys as $key) { - if ('' !== $key && \is_string($key)) { - $key = static::TAGS_PREFIX.$key; - $tagKeys[$key] = $key; - } - } - - try { - $items = $this->pool->getItems($tagKeys + $keys); - } catch (InvalidArgumentException $e) { - $this->pool->getItems($keys); // Should throw an exception - - throw $e; - } - - return $this->generateItems($items, $tagKeys); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - if ('' !== $prefix) { - foreach ($this->deferred as $key => $item) { - if (0 === strpos($key, $prefix)) { - unset($this->deferred[$key]); - } - } - } else { - $this->deferred = []; - } - - if ($this->pool instanceof AdapterInterface) { - return $this->pool->clear($prefix); - } - - return $this->pool->clear(); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - return $this->deleteItems([$key]); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - foreach ($keys as $key) { - if ('' !== $key && \is_string($key)) { - $keys[] = static::TAGS_PREFIX.$key; - } - } - - return $this->pool->deleteItems($keys); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - if (!$item instanceof CacheItem) { - return false; - } - $this->deferred[$item->getKey()] = $item; - - return $this->commit(); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - if (!$item instanceof CacheItem) { - return false; - } - $this->deferred[$item->getKey()] = $item; - - return true; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - return $this->invalidateTags([]); - } - - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - public function __destruct() - { - $this->commit(); - } - - private function generateItems(iterable $items, array $tagKeys) - { - $bufferedItems = $itemTags = []; - $f = $this->setCacheItemTags; - - foreach ($items as $key => $item) { - if (!$tagKeys) { - yield $key => $f($item, static::TAGS_PREFIX.$key, $itemTags); - continue; - } - if (!isset($tagKeys[$key])) { - $bufferedItems[$key] = $item; - continue; - } - - unset($tagKeys[$key]); - - if ($item->isHit()) { - $itemTags[$key] = $item->get() ?: []; - } - - if (!$tagKeys) { - $tagVersions = $this->getTagVersions($itemTags); - - foreach ($itemTags as $key => $tags) { - foreach ($tags as $tag => $version) { - if ($tagVersions[$tag] !== $version && 1 !== $version - $tagVersions[$tag]) { - unset($itemTags[$key]); - continue 2; - } - } - } - $tagVersions = $tagKeys = null; - - foreach ($bufferedItems as $key => $item) { - yield $key => $f($item, static::TAGS_PREFIX.$key, $itemTags); - } - $bufferedItems = null; - } - } - } - - private function getTagVersions(array $tagsByKey, array &$invalidatedTags = []) - { - $tagVersions = $invalidatedTags; - - foreach ($tagsByKey as $tags) { - $tagVersions += $tags; - } - - if (!$tagVersions) { - return []; - } - - if (!$fetchTagVersions = 1 !== \func_num_args()) { - foreach ($tagsByKey as $tags) { - foreach ($tags as $tag => $version) { - if ($tagVersions[$tag] > $version) { - $tagVersions[$tag] = $version; - } - } - } - } - - $now = microtime(true); - $tags = []; - foreach ($tagVersions as $tag => $version) { - $tags[$tag.static::TAGS_PREFIX] = $tag; - if ($fetchTagVersions || !isset($this->knownTagVersions[$tag])) { - $fetchTagVersions = true; - continue; - } - $version -= $this->knownTagVersions[$tag][1]; - if ((0 !== $version && 1 !== $version) || $now - $this->knownTagVersions[$tag][0] >= $this->knownTagVersionsTtl) { - // reuse previously fetched tag versions up to the ttl, unless we are storing items or a potential miss arises - $fetchTagVersions = true; - } else { - $this->knownTagVersions[$tag][1] += $version; - } - } - - if (!$fetchTagVersions) { - return $tagVersions; - } - - foreach ($this->tags->getItems(array_keys($tags)) as $tag => $version) { - $tagVersions[$tag = $tags[$tag]] = $version->get() ?: 0; - if (isset($invalidatedTags[$tag])) { - $invalidatedTags[$tag] = $version->set(++$tagVersions[$tag]); - } - $this->knownTagVersions[$tag] = [$now, $tagVersions[$tag]]; - } - - return $tagVersions; - } -} diff --git a/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php b/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php deleted file mode 100644 index 340048c..0000000 --- a/vendor/symfony/cache/Adapter/TagAwareAdapterInterface.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\InvalidArgumentException; - -/** - * Interface for invalidating cached items using tags. - * - * @author Nicolas Grekas - */ -interface TagAwareAdapterInterface extends AdapterInterface -{ - /** - * Invalidates cached items using tags. - * - * @param string[] $tags An array of tags to invalidate - * - * @return bool True on success - * - * @throws InvalidArgumentException When $tags is not valid - */ - public function invalidateTags(array $tags); -} diff --git a/vendor/symfony/cache/Adapter/TraceableAdapter.php b/vendor/symfony/cache/Adapter/TraceableAdapter.php deleted file mode 100644 index 16d819e..0000000 --- a/vendor/symfony/cache/Adapter/TraceableAdapter.php +++ /dev/null @@ -1,299 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Psr\Cache\CacheItemInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Contracts\Cache\CacheInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * An adapter that collects data about all cache calls. - * - * @author Aaron Scherer - * @author Tobias Nyholm - * @author Nicolas Grekas - */ -class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface -{ - protected $pool; - private $calls = []; - - public function __construct(AdapterInterface $pool) - { - $this->pool = $pool; - } - - /** - * {@inheritdoc} - */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null) - { - if (!$this->pool instanceof CacheInterface) { - throw new \BadMethodCallException(sprintf('Cannot call "%s::get()": this class doesn\'t implement "%s".', \get_class($this->pool), CacheInterface::class)); - } - - $isHit = true; - $callback = function (CacheItem $item, bool &$save) use ($callback, &$isHit) { - $isHit = $item->isHit(); - - return $callback($item, $save); - }; - - $event = $this->start(__FUNCTION__); - try { - $value = $this->pool->get($key, $callback, $beta, $metadata); - $event->result[$key] = \is_object($value) ? \get_class($value) : \gettype($value); - } finally { - $event->end = microtime(true); - } - if ($isHit) { - ++$event->hits; - } else { - ++$event->misses; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - $event = $this->start(__FUNCTION__); - try { - $item = $this->pool->getItem($key); - } finally { - $event->end = microtime(true); - } - if ($event->result[$key] = $item->isHit()) { - ++$event->hits; - } else { - ++$event->misses; - } - - return $item; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - $event = $this->start(__FUNCTION__); - try { - return $event->result[$key] = $this->pool->hasItem($key); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - $event = $this->start(__FUNCTION__); - try { - return $event->result[$key] = $this->pool->deleteItem($key); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - $event = $this->start(__FUNCTION__); - try { - return $event->result[$item->getKey()] = $this->pool->save($item); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - $event = $this->start(__FUNCTION__); - try { - return $event->result[$item->getKey()] = $this->pool->saveDeferred($item); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - $event = $this->start(__FUNCTION__); - try { - $result = $this->pool->getItems($keys); - } finally { - $event->end = microtime(true); - } - $f = function () use ($result, $event) { - $event->result = []; - foreach ($result as $key => $item) { - if ($event->result[$key] = $item->isHit()) { - ++$event->hits; - } else { - ++$event->misses; - } - yield $key => $item; - } - }; - - return $f(); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - $event = $this->start(__FUNCTION__); - try { - if ($this->pool instanceof AdapterInterface) { - return $event->result = $this->pool->clear($prefix); - } - - return $event->result = $this->pool->clear(); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - $event = $this->start(__FUNCTION__); - $event->result['keys'] = $keys; - try { - return $event->result['result'] = $this->pool->deleteItems($keys); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function commit() - { - $event = $this->start(__FUNCTION__); - try { - return $event->result = $this->pool->commit(); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - */ - public function prune() - { - if (!$this->pool instanceof PruneableInterface) { - return false; - } - $event = $this->start(__FUNCTION__); - try { - return $event->result = $this->pool->prune(); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - */ - public function reset() - { - if (!$this->pool instanceof ResetInterface) { - return; - } - $event = $this->start(__FUNCTION__); - try { - $this->pool->reset(); - } finally { - $event->end = microtime(true); - } - } - - /** - * {@inheritdoc} - */ - public function delete(string $key): bool - { - $event = $this->start(__FUNCTION__); - try { - return $event->result[$key] = $this->pool->deleteItem($key); - } finally { - $event->end = microtime(true); - } - } - - public function getCalls() - { - return $this->calls; - } - - public function clearCalls() - { - $this->calls = []; - } - - protected function start($name) - { - $this->calls[] = $event = new TraceableAdapterEvent(); - $event->name = $name; - $event->start = microtime(true); - - return $event; - } -} - -class TraceableAdapterEvent -{ - public $name; - public $start; - public $end; - public $result; - public $hits = 0; - public $misses = 0; -} diff --git a/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php b/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php deleted file mode 100644 index 69461b8..0000000 --- a/vendor/symfony/cache/Adapter/TraceableTagAwareAdapter.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Adapter; - -use Symfony\Contracts\Cache\TagAwareCacheInterface; - -/** - * @author Robin Chalas - */ -class TraceableTagAwareAdapter extends TraceableAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface -{ - public function __construct(TagAwareAdapterInterface $pool) - { - parent::__construct($pool); - } - - /** - * {@inheritdoc} - */ - public function invalidateTags(array $tags) - { - $event = $this->start(__FUNCTION__); - try { - return $event->result = $this->pool->invalidateTags($tags); - } finally { - $event->end = microtime(true); - } - } -} diff --git a/vendor/symfony/cache/CHANGELOG.md b/vendor/symfony/cache/CHANGELOG.md deleted file mode 100644 index 2f2b249..0000000 --- a/vendor/symfony/cache/CHANGELOG.md +++ /dev/null @@ -1,81 +0,0 @@ -CHANGELOG -========= - -5.0.0 ------ - - * removed all PSR-16 implementations in the `Simple` namespace - * removed `SimpleCacheAdapter` - * removed `AbstractAdapter::unserialize()` - * removed `CacheItem::getPreviousTags()` - -4.4.0 ------ - - * added support for connecting to Redis Sentinel clusters - * added argument `$prefix` to `AdapterInterface::clear()` - * improved `RedisTagAwareAdapter` to support Redis server >= 2.8 and up to 4B items per tag - * added `TagAwareMarshaller` for optimized data storage when using `AbstractTagAwareAdapter` - * added `DeflateMarshaller` to compress serialized values - * removed support for phpredis 4 `compression` - * [BC BREAK] `RedisTagAwareAdapter` is not compatible with `RedisCluster` from `Predis` anymore, use `phpredis` instead - * Marked the `CacheDataCollector` class as `@final`. - -4.3.0 ------ - - * removed `psr/simple-cache` dependency, run `composer require psr/simple-cache` if you need it - * deprecated all PSR-16 adapters, use `Psr16Cache` or `Symfony\Contracts\Cache\CacheInterface` implementations instead - * deprecated `SimpleCacheAdapter`, use `Psr16Adapter` instead - -4.2.0 ------ - - * added support for connecting to Redis clusters via DSN - * added support for configuring multiple Memcached servers via DSN - * added `MarshallerInterface` and `DefaultMarshaller` to allow changing the serializer and provide one that automatically uses igbinary when available - * implemented `CacheInterface`, which provides stampede protection via probabilistic early expiration and should become the preferred way to use a cache - * added sub-second expiry accuracy for backends that support it - * added support for phpredis 4 `compression` and `tcp_keepalive` options - * added automatic table creation when using Doctrine DBAL with PDO-based backends - * throw `LogicException` when `CacheItem::tag()` is called on an item coming from a non tag-aware pool - * deprecated `CacheItem::getPreviousTags()`, use `CacheItem::getMetadata()` instead - * deprecated the `AbstractAdapter::unserialize()` and `AbstractCache::unserialize()` methods - * added `CacheCollectorPass` (originally in `FrameworkBundle`) - * added `CachePoolClearerPass` (originally in `FrameworkBundle`) - * added `CachePoolPass` (originally in `FrameworkBundle`) - * added `CachePoolPrunerPass` (originally in `FrameworkBundle`) - -3.4.0 ------ - - * added using options from Memcached DSN - * added PruneableInterface so PSR-6 or PSR-16 cache implementations can declare support for manual stale cache pruning - * added prune logic to FilesystemTrait, PhpFilesTrait, PdoTrait, TagAwareAdapter and ChainTrait - * now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, PhpFilesCache, PdoAdapter, PdoCache, ChainAdapter, and - ChainCache implement PruneableInterface and support manual stale cache pruning - -3.3.0 ------ - - * added CacheItem::getPreviousTags() to get bound tags coming from the pool storage if any - * added PSR-16 "Simple Cache" implementations for all existing PSR-6 adapters - * added Psr6Cache and SimpleCacheAdapter for bidirectional interoperability between PSR-6 and PSR-16 - * added MemcachedAdapter (PSR-6) and MemcachedCache (PSR-16) - * added TraceableAdapter (PSR-6) and TraceableCache (PSR-16) - -3.2.0 ------ - - * added TagAwareAdapter for tags-based invalidation - * added PdoAdapter with PDO and Doctrine DBAL support - * added PhpArrayAdapter and PhpFilesAdapter for OPcache-backed shared memory storage (PHP 7+ only) - * added NullAdapter - -3.1.0 ------ - - * added the component with strict PSR-6 implementations - * added ApcuAdapter, ArrayAdapter, FilesystemAdapter and RedisAdapter - * added AbstractAdapter, ChainAdapter and ProxyAdapter - * added DoctrineAdapter and DoctrineProvider for bidirectional interoperability with Doctrine Cache diff --git a/vendor/symfony/cache/CacheItem.php b/vendor/symfony/cache/CacheItem.php deleted file mode 100644 index 5880803..0000000 --- a/vendor/symfony/cache/CacheItem.php +++ /dev/null @@ -1,190 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Exception\LogicException; -use Symfony\Contracts\Cache\ItemInterface; - -/** - * @author Nicolas Grekas - */ -final class CacheItem implements ItemInterface -{ - private const METADATA_EXPIRY_OFFSET = 1527506807; - - protected $key; - protected $value; - protected $isHit = false; - protected $expiry; - protected $defaultLifetime; - protected $metadata = []; - protected $newMetadata = []; - protected $innerItem; - protected $poolHash; - protected $isTaggable = false; - - /** - * {@inheritdoc} - */ - public function getKey(): string - { - return $this->key; - } - - /** - * {@inheritdoc} - */ - public function get() - { - return $this->value; - } - - /** - * {@inheritdoc} - */ - public function isHit(): bool - { - return $this->isHit; - } - - /** - * {@inheritdoc} - * - * @return $this - */ - public function set($value): self - { - $this->value = $value; - - return $this; - } - - /** - * {@inheritdoc} - * - * @return $this - */ - public function expiresAt($expiration): self - { - if (null === $expiration) { - $this->expiry = $this->defaultLifetime > 0 ? microtime(true) + $this->defaultLifetime : null; - } elseif ($expiration instanceof \DateTimeInterface) { - $this->expiry = (float) $expiration->format('U.u'); - } else { - throw new InvalidArgumentException(sprintf('Expiration date must implement DateTimeInterface or be null, "%s" given', \is_object($expiration) ? \get_class($expiration) : \gettype($expiration))); - } - - return $this; - } - - /** - * {@inheritdoc} - * - * @return $this - */ - public function expiresAfter($time): self - { - if (null === $time) { - $this->expiry = $this->defaultLifetime > 0 ? microtime(true) + $this->defaultLifetime : null; - } elseif ($time instanceof \DateInterval) { - $this->expiry = microtime(true) + \DateTime::createFromFormat('U', 0)->add($time)->format('U.u'); - } elseif (\is_int($time)) { - $this->expiry = $time + microtime(true); - } else { - throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given', \is_object($time) ? \get_class($time) : \gettype($time))); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function tag($tags): ItemInterface - { - if (!$this->isTaggable) { - throw new LogicException(sprintf('Cache item "%s" comes from a non tag-aware pool: you cannot tag it.', $this->key)); - } - if (!is_iterable($tags)) { - $tags = [$tags]; - } - foreach ($tags as $tag) { - if (!\is_string($tag)) { - throw new InvalidArgumentException(sprintf('Cache tag must be string, "%s" given', \is_object($tag) ? \get_class($tag) : \gettype($tag))); - } - if (isset($this->newMetadata[self::METADATA_TAGS][$tag])) { - continue; - } - if ('' === $tag) { - throw new InvalidArgumentException('Cache tag length must be greater than zero'); - } - if (false !== strpbrk($tag, self::RESERVED_CHARACTERS)) { - throw new InvalidArgumentException(sprintf('Cache tag "%s" contains reserved characters %s', $tag, self::RESERVED_CHARACTERS)); - } - $this->newMetadata[self::METADATA_TAGS][$tag] = $tag; - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getMetadata(): array - { - return $this->metadata; - } - - /** - * Validates a cache key according to PSR-6. - * - * @param string $key The key to validate - * - * @throws InvalidArgumentException When $key is not valid - */ - public static function validateKey($key): string - { - if (!\is_string($key)) { - throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given', \is_object($key) ? \get_class($key) : \gettype($key))); - } - if ('' === $key) { - throw new InvalidArgumentException('Cache key length must be greater than zero'); - } - if (false !== strpbrk($key, self::RESERVED_CHARACTERS)) { - throw new InvalidArgumentException(sprintf('Cache key "%s" contains reserved characters %s', $key, self::RESERVED_CHARACTERS)); - } - - return $key; - } - - /** - * Internal logging helper. - * - * @internal - */ - public static function log(?LoggerInterface $logger, string $message, array $context = []) - { - if ($logger) { - $logger->warning($message, $context); - } else { - $replace = []; - foreach ($context as $k => $v) { - if (is_scalar($v)) { - $replace['{'.$k.'}'] = $v; - } - } - @trigger_error(strtr($message, $replace), E_USER_WARNING); - } - } -} diff --git a/vendor/symfony/cache/DataCollector/CacheDataCollector.php b/vendor/symfony/cache/DataCollector/CacheDataCollector.php deleted file mode 100644 index 363b887..0000000 --- a/vendor/symfony/cache/DataCollector/CacheDataCollector.php +++ /dev/null @@ -1,189 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\DataCollector; - -use Symfony\Component\Cache\Adapter\TraceableAdapter; -use Symfony\Component\Cache\Adapter\TraceableAdapterEvent; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\DataCollector\DataCollector; -use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; - -/** - * @author Aaron Scherer - * @author Tobias Nyholm - * - * @final - */ -class CacheDataCollector extends DataCollector implements LateDataCollectorInterface -{ - /** - * @var TraceableAdapter[] - */ - private $instances = []; - - public function addInstance(string $name, TraceableAdapter $instance) - { - $this->instances[$name] = $instance; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - $empty = ['calls' => [], 'config' => [], 'options' => [], 'statistics' => []]; - $this->data = ['instances' => $empty, 'total' => $empty]; - foreach ($this->instances as $name => $instance) { - $this->data['instances']['calls'][$name] = $instance->getCalls(); - } - - $this->data['instances']['statistics'] = $this->calculateStatistics(); - $this->data['total']['statistics'] = $this->calculateTotalStatistics(); - } - - public function reset() - { - $this->data = []; - foreach ($this->instances as $instance) { - $instance->clearCalls(); - } - } - - public function lateCollect() - { - $this->data = $this->cloneVar($this->data); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'cache'; - } - - /** - * Method returns amount of logged Cache reads: "get" calls. - * - * @return array - */ - public function getStatistics() - { - return $this->data['instances']['statistics']; - } - - /** - * Method returns the statistic totals. - * - * @return array - */ - public function getTotals() - { - return $this->data['total']['statistics']; - } - - /** - * Method returns all logged Cache call objects. - * - * @return mixed - */ - public function getCalls() - { - return $this->data['instances']['calls']; - } - - private function calculateStatistics(): array - { - $statistics = []; - foreach ($this->data['instances']['calls'] as $name => $calls) { - $statistics[$name] = [ - 'calls' => 0, - 'time' => 0, - 'reads' => 0, - 'writes' => 0, - 'deletes' => 0, - 'hits' => 0, - 'misses' => 0, - ]; - /** @var TraceableAdapterEvent $call */ - foreach ($calls as $call) { - ++$statistics[$name]['calls']; - $statistics[$name]['time'] += $call->end - $call->start; - if ('get' === $call->name) { - ++$statistics[$name]['reads']; - if ($call->hits) { - ++$statistics[$name]['hits']; - } else { - ++$statistics[$name]['misses']; - ++$statistics[$name]['writes']; - } - } elseif ('getItem' === $call->name) { - ++$statistics[$name]['reads']; - if ($call->hits) { - ++$statistics[$name]['hits']; - } else { - ++$statistics[$name]['misses']; - } - } elseif ('getItems' === $call->name) { - $statistics[$name]['reads'] += $call->hits + $call->misses; - $statistics[$name]['hits'] += $call->hits; - $statistics[$name]['misses'] += $call->misses; - } elseif ('hasItem' === $call->name) { - ++$statistics[$name]['reads']; - if (false === $call->result) { - ++$statistics[$name]['misses']; - } else { - ++$statistics[$name]['hits']; - } - } elseif ('save' === $call->name) { - ++$statistics[$name]['writes']; - } elseif ('deleteItem' === $call->name) { - ++$statistics[$name]['deletes']; - } - } - if ($statistics[$name]['reads']) { - $statistics[$name]['hit_read_ratio'] = round(100 * $statistics[$name]['hits'] / $statistics[$name]['reads'], 2); - } else { - $statistics[$name]['hit_read_ratio'] = null; - } - } - - return $statistics; - } - - private function calculateTotalStatistics(): array - { - $statistics = $this->getStatistics(); - $totals = [ - 'calls' => 0, - 'time' => 0, - 'reads' => 0, - 'writes' => 0, - 'deletes' => 0, - 'hits' => 0, - 'misses' => 0, - ]; - foreach ($statistics as $name => $values) { - foreach ($totals as $key => $value) { - $totals[$key] += $statistics[$name][$key]; - } - } - if ($totals['reads']) { - $totals['hit_read_ratio'] = round(100 * $totals['hits'] / $totals['reads'], 2); - } else { - $totals['hit_read_ratio'] = null; - } - - return $totals; - } -} diff --git a/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php b/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php deleted file mode 100644 index 6193d34..0000000 --- a/vendor/symfony/cache/DependencyInjection/CacheCollectorPass.php +++ /dev/null @@ -1,72 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\DependencyInjection; - -use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface; -use Symfony\Component\Cache\Adapter\TraceableAdapter; -use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Inject a data collector to all the cache services to be able to get detailed statistics. - * - * @author Tobias Nyholm - */ -class CacheCollectorPass implements CompilerPassInterface -{ - private $dataCollectorCacheId; - private $cachePoolTag; - private $cachePoolRecorderInnerSuffix; - - public function __construct(string $dataCollectorCacheId = 'data_collector.cache', string $cachePoolTag = 'cache.pool', string $cachePoolRecorderInnerSuffix = '.recorder_inner') - { - $this->dataCollectorCacheId = $dataCollectorCacheId; - $this->cachePoolTag = $cachePoolTag; - $this->cachePoolRecorderInnerSuffix = $cachePoolRecorderInnerSuffix; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->dataCollectorCacheId)) { - return; - } - - $collectorDefinition = $container->getDefinition($this->dataCollectorCacheId); - foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $attributes) { - $definition = $container->getDefinition($id); - if ($definition->isAbstract()) { - continue; - } - - $recorder = new Definition(is_subclass_of($definition->getClass(), TagAwareAdapterInterface::class) ? TraceableTagAwareAdapter::class : TraceableAdapter::class); - $recorder->setTags($definition->getTags()); - $recorder->setPublic($definition->isPublic()); - $recorder->setArguments([new Reference($innerId = $id.$this->cachePoolRecorderInnerSuffix)]); - - $definition->setTags([]); - $definition->setPublic(false); - - $container->setDefinition($innerId, $definition); - $container->setDefinition($id, $recorder); - - // Tell the collector to add the new instance - $collectorDefinition->addMethodCall('addInstance', [$id, new Reference($id)]); - $collectorDefinition->setPublic(false); - } - } -} diff --git a/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php b/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php deleted file mode 100644 index 3ca89a3..0000000 --- a/vendor/symfony/cache/DependencyInjection/CachePoolClearerPass.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Nicolas Grekas - */ -class CachePoolClearerPass implements CompilerPassInterface -{ - private $cachePoolClearerTag; - - public function __construct(string $cachePoolClearerTag = 'cache.pool.clearer') - { - $this->cachePoolClearerTag = $cachePoolClearerTag; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $container->getParameterBag()->remove('cache.prefix.seed'); - - foreach ($container->findTaggedServiceIds($this->cachePoolClearerTag) as $id => $attr) { - $clearer = $container->getDefinition($id); - $pools = []; - foreach ($clearer->getArgument(0) as $name => $ref) { - if ($container->hasDefinition($ref)) { - $pools[$name] = new Reference($ref); - } - } - $clearer->replaceArgument(0, $pools); - } - } -} diff --git a/vendor/symfony/cache/DependencyInjection/CachePoolPass.php b/vendor/symfony/cache/DependencyInjection/CachePoolPass.php deleted file mode 100644 index 35bf5e7..0000000 --- a/vendor/symfony/cache/DependencyInjection/CachePoolPass.php +++ /dev/null @@ -1,222 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\DependencyInjection; - -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\ChainAdapter; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Nicolas Grekas - */ -class CachePoolPass implements CompilerPassInterface -{ - private $cachePoolTag; - private $kernelResetTag; - private $cacheClearerId; - private $cachePoolClearerTag; - private $cacheSystemClearerId; - private $cacheSystemClearerTag; - - public function __construct(string $cachePoolTag = 'cache.pool', string $kernelResetTag = 'kernel.reset', string $cacheClearerId = 'cache.global_clearer', string $cachePoolClearerTag = 'cache.pool.clearer', string $cacheSystemClearerId = 'cache.system_clearer', string $cacheSystemClearerTag = 'kernel.cache_clearer') - { - $this->cachePoolTag = $cachePoolTag; - $this->kernelResetTag = $kernelResetTag; - $this->cacheClearerId = $cacheClearerId; - $this->cachePoolClearerTag = $cachePoolClearerTag; - $this->cacheSystemClearerId = $cacheSystemClearerId; - $this->cacheSystemClearerTag = $cacheSystemClearerTag; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if ($container->hasParameter('cache.prefix.seed')) { - $seed = '.'.$container->getParameterBag()->resolveValue($container->getParameter('cache.prefix.seed')); - } else { - $seed = '_'.$container->getParameter('kernel.project_dir'); - } - $seed .= '.'.$container->getParameter('kernel.container_class'); - - $pools = []; - $clearers = []; - $attributes = [ - 'provider', - 'name', - 'namespace', - 'default_lifetime', - 'reset', - ]; - foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $tags) { - $adapter = $pool = $container->getDefinition($id); - if ($pool->isAbstract()) { - continue; - } - $class = $adapter->getClass(); - while ($adapter instanceof ChildDefinition) { - $adapter = $container->findDefinition($adapter->getParent()); - $class = $class ?: $adapter->getClass(); - if ($t = $adapter->getTag($this->cachePoolTag)) { - $tags[0] += $t[0]; - } - } - $name = $tags[0]['name'] ?? $id; - if (!isset($tags[0]['namespace'])) { - $namespaceSeed = $seed; - if (null !== $class) { - $namespaceSeed .= '.'.$class; - } - - $tags[0]['namespace'] = $this->getNamespace($namespaceSeed, $name); - } - if (isset($tags[0]['clearer'])) { - $clearer = $tags[0]['clearer']; - while ($container->hasAlias($clearer)) { - $clearer = (string) $container->getAlias($clearer); - } - } else { - $clearer = null; - } - unset($tags[0]['clearer'], $tags[0]['name']); - - if (isset($tags[0]['provider'])) { - $tags[0]['provider'] = new Reference(static::getServiceProvider($container, $tags[0]['provider'])); - } - - if (ChainAdapter::class === $class) { - $adapters = []; - foreach ($adapter->getArgument(0) as $provider => $adapter) { - $chainedPool = $adapter = new ChildDefinition($adapter); - $chainedTags = [\is_int($provider) ? [] : ['provider' => $provider]]; - $chainedClass = ''; - - while ($adapter instanceof ChildDefinition) { - $adapter = $container->findDefinition($adapter->getParent()); - $chainedClass = $chainedClass ?: $adapter->getClass(); - if ($t = $adapter->getTag($this->cachePoolTag)) { - $chainedTags[0] += $t[0]; - } - } - - if (ChainAdapter::class === $chainedClass) { - throw new InvalidArgumentException(sprintf('Invalid service "%s": chain of adapters cannot reference another chain, found "%s".', $id, $chainedPool->getParent())); - } - - $i = 0; - - if (isset($chainedTags[0]['provider'])) { - $chainedPool->replaceArgument($i++, new Reference(static::getServiceProvider($container, $chainedTags[0]['provider']))); - } - - if (isset($tags[0]['namespace']) && ArrayAdapter::class !== $adapter->getClass()) { - $chainedPool->replaceArgument($i++, $tags[0]['namespace']); - } - - if (isset($tags[0]['default_lifetime'])) { - $chainedPool->replaceArgument($i++, $tags[0]['default_lifetime']); - } - - $adapters[] = $chainedPool; - } - - $pool->replaceArgument(0, $adapters); - unset($tags[0]['provider'], $tags[0]['namespace']); - $i = 1; - } else { - $i = 0; - } - - foreach ($attributes as $attr) { - if (!isset($tags[0][$attr])) { - // no-op - } elseif ('reset' === $attr) { - if ($tags[0][$attr]) { - $pool->addTag($this->kernelResetTag, ['method' => $tags[0][$attr]]); - } - } elseif ('namespace' !== $attr || ArrayAdapter::class !== $class) { - $pool->replaceArgument($i++, $tags[0][$attr]); - } - unset($tags[0][$attr]); - } - if (!empty($tags[0])) { - throw new InvalidArgumentException(sprintf('Invalid "%s" tag for service "%s": accepted attributes are "clearer", "provider", "name", "namespace", "default_lifetime" and "reset", found "%s".', $this->cachePoolTag, $id, implode('", "', array_keys($tags[0])))); - } - - if (null !== $clearer) { - $clearers[$clearer][$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE); - } - - $pools[$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE); - } - - $notAliasedCacheClearerId = $this->cacheClearerId; - while ($container->hasAlias($this->cacheClearerId)) { - $this->cacheClearerId = (string) $container->getAlias($this->cacheClearerId); - } - if ($container->hasDefinition($this->cacheClearerId)) { - $clearers[$notAliasedCacheClearerId] = $pools; - } - - foreach ($clearers as $id => $pools) { - $clearer = $container->getDefinition($id); - if ($clearer instanceof ChildDefinition) { - $clearer->replaceArgument(0, $pools); - } else { - $clearer->setArgument(0, $pools); - } - $clearer->addTag($this->cachePoolClearerTag); - - if ($this->cacheSystemClearerId === $id) { - $clearer->addTag($this->cacheSystemClearerTag); - } - } - - if ($container->hasDefinition('console.command.cache_pool_list')) { - $container->getDefinition('console.command.cache_pool_list')->replaceArgument(0, array_keys($pools)); - } - } - - private function getNamespace(string $seed, string $id) - { - return substr(str_replace('/', '-', base64_encode(hash('sha256', $id.$seed, true))), 0, 10); - } - - /** - * @internal - */ - public static function getServiceProvider(ContainerBuilder $container, $name) - { - $container->resolveEnvPlaceholders($name, null, $usedEnvs); - - if ($usedEnvs || preg_match('#^[a-z]++:#', $name)) { - $dsn = $name; - - if (!$container->hasDefinition($name = '.cache_connection.'.ContainerBuilder::hash($dsn))) { - $definition = new Definition(AbstractAdapter::class); - $definition->setPublic(false); - $definition->setFactory([AbstractAdapter::class, 'createConnection']); - $definition->setArguments([$dsn, ['lazy' => true]]); - $container->setDefinition($name, $definition); - } - } - - return $name; - } -} diff --git a/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php b/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php deleted file mode 100644 index e569962..0000000 --- a/vendor/symfony/cache/DependencyInjection/CachePoolPrunerPass.php +++ /dev/null @@ -1,60 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\DependencyInjection; - -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Rob Frawley 2nd - */ -class CachePoolPrunerPass implements CompilerPassInterface -{ - private $cacheCommandServiceId; - private $cachePoolTag; - - public function __construct(string $cacheCommandServiceId = 'console.command.cache_pool_prune', string $cachePoolTag = 'cache.pool') - { - $this->cacheCommandServiceId = $cacheCommandServiceId; - $this->cachePoolTag = $cachePoolTag; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->cacheCommandServiceId)) { - return; - } - - $services = []; - - foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $tags) { - $class = $container->getParameterBag()->resolveValue($container->getDefinition($id)->getClass()); - - if (!$reflection = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } - - if ($reflection->implementsInterface(PruneableInterface::class)) { - $services[$id] = new Reference($id); - } - } - - $container->getDefinition($this->cacheCommandServiceId)->replaceArgument(0, new IteratorArgument($services)); - } -} diff --git a/vendor/symfony/cache/DoctrineProvider.php b/vendor/symfony/cache/DoctrineProvider.php deleted file mode 100644 index d7e0bca..0000000 --- a/vendor/symfony/cache/DoctrineProvider.php +++ /dev/null @@ -1,114 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache; - -use Doctrine\Common\Cache\CacheProvider; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * @author Nicolas Grekas - */ -class DoctrineProvider extends CacheProvider implements PruneableInterface, ResettableInterface -{ - private $pool; - - public function __construct(CacheItemPoolInterface $pool) - { - $this->pool = $pool; - } - - /** - * {@inheritdoc} - */ - public function prune() - { - return $this->pool instanceof PruneableInterface && $this->pool->prune(); - } - - /** - * {@inheritdoc} - */ - public function reset() - { - if ($this->pool instanceof ResetInterface) { - $this->pool->reset(); - } - $this->setNamespace($this->getNamespace()); - } - - /** - * {@inheritdoc} - */ - protected function doFetch($id) - { - $item = $this->pool->getItem(rawurlencode($id)); - - return $item->isHit() ? $item->get() : false; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - protected function doContains($id) - { - return $this->pool->hasItem(rawurlencode($id)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - protected function doSave($id, $data, $lifeTime = 0) - { - $item = $this->pool->getItem(rawurlencode($id)); - - if (0 < $lifeTime) { - $item->expiresAfter($lifeTime); - } - - return $this->pool->save($item->set($data)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - protected function doDelete($id) - { - return $this->pool->deleteItem(rawurlencode($id)); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - protected function doFlush() - { - return $this->pool->clear(); - } - - /** - * {@inheritdoc} - * - * @return array|null - */ - protected function doGetStats() - { - return null; - } -} diff --git a/vendor/symfony/cache/Exception/CacheException.php b/vendor/symfony/cache/Exception/CacheException.php deleted file mode 100644 index d2e975b..0000000 --- a/vendor/symfony/cache/Exception/CacheException.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Exception; - -use Psr\Cache\CacheException as Psr6CacheInterface; -use Psr\SimpleCache\CacheException as SimpleCacheInterface; - -if (interface_exists(SimpleCacheInterface::class)) { - class CacheException extends \Exception implements Psr6CacheInterface, SimpleCacheInterface - { - } -} else { - class CacheException extends \Exception implements Psr6CacheInterface - { - } -} diff --git a/vendor/symfony/cache/Exception/InvalidArgumentException.php b/vendor/symfony/cache/Exception/InvalidArgumentException.php deleted file mode 100644 index 7f9584a..0000000 --- a/vendor/symfony/cache/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Exception; - -use Psr\Cache\InvalidArgumentException as Psr6CacheInterface; -use Psr\SimpleCache\InvalidArgumentException as SimpleCacheInterface; - -if (interface_exists(SimpleCacheInterface::class)) { - class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface, SimpleCacheInterface - { - } -} else { - class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface - { - } -} diff --git a/vendor/symfony/cache/Exception/LogicException.php b/vendor/symfony/cache/Exception/LogicException.php deleted file mode 100644 index 9ffa7ed..0000000 --- a/vendor/symfony/cache/Exception/LogicException.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Exception; - -use Psr\Cache\CacheException as Psr6CacheInterface; -use Psr\SimpleCache\CacheException as SimpleCacheInterface; - -if (interface_exists(SimpleCacheInterface::class)) { - class LogicException extends \LogicException implements Psr6CacheInterface, SimpleCacheInterface - { - } -} else { - class LogicException extends \LogicException implements Psr6CacheInterface - { - } -} diff --git a/vendor/symfony/cache/LICENSE b/vendor/symfony/cache/LICENSE deleted file mode 100644 index 3c464ca..0000000 --- a/vendor/symfony/cache/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2016-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/cache/LockRegistry.php b/vendor/symfony/cache/LockRegistry.php deleted file mode 100644 index 6c0fbff..0000000 --- a/vendor/symfony/cache/LockRegistry.php +++ /dev/null @@ -1,153 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache; - -use Psr\Log\LoggerInterface; -use Symfony\Contracts\Cache\CacheInterface; -use Symfony\Contracts\Cache\ItemInterface; - -/** - * LockRegistry is used internally by existing adapters to protect against cache stampede. - * - * It does so by wrapping the computation of items in a pool of locks. - * Foreach each apps, there can be at most 20 concurrent processes that - * compute items at the same time and only one per cache-key. - * - * @author Nicolas Grekas - */ -final class LockRegistry -{ - private static $openedFiles = []; - private static $lockedFiles = []; - - /** - * The number of items in this list controls the max number of concurrent processes. - */ - private static $files = [ - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AbstractAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AbstractTagAwareAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AdapterInterface.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ApcuAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ArrayAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ChainAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'DoctrineAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'FilesystemAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'FilesystemTagAwareAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'MemcachedAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'NullAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PdoAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PhpArrayAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PhpFilesAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ProxyAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'Psr16Adapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'RedisAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'RedisTagAwareAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TagAwareAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TagAwareAdapterInterface.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TraceableAdapter.php', - __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TraceableTagAwareAdapter.php', - ]; - - /** - * Defines a set of existing files that will be used as keys to acquire locks. - * - * @return array The previously defined set of files - */ - public static function setFiles(array $files): array - { - $previousFiles = self::$files; - self::$files = $files; - - foreach (self::$openedFiles as $file) { - if ($file) { - flock($file, LOCK_UN); - fclose($file); - } - } - self::$openedFiles = self::$lockedFiles = []; - - return $previousFiles; - } - - public static function compute(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata = null, LoggerInterface $logger = null) - { - $key = self::$files ? crc32($item->getKey()) % \count(self::$files) : -1; - - if ($key < 0 || (self::$lockedFiles[$key] ?? false) || !$lock = self::open($key)) { - return $callback($item, $save); - } - - while (true) { - try { - // race to get the lock in non-blocking mode - $locked = flock($lock, LOCK_EX | LOCK_NB, $wouldBlock); - - if ($locked || !$wouldBlock) { - $logger && $logger->info(sprintf('Lock %s, now computing item "{key}"', $locked ? 'acquired' : 'not supported'), ['key' => $item->getKey()]); - self::$lockedFiles[$key] = true; - - $value = $callback($item, $save); - - if ($save) { - if ($setMetadata) { - $setMetadata($item); - } - - $pool->save($item->set($value)); - $save = false; - } - - return $value; - } - // if we failed the race, retry locking in blocking mode to wait for the winner - $logger && $logger->info('Item "{key}" is locked, waiting for it to be released', ['key' => $item->getKey()]); - flock($lock, LOCK_SH); - } finally { - flock($lock, LOCK_UN); - unset(self::$lockedFiles[$key]); - } - static $signalingException, $signalingCallback; - $signalingException = $signalingException ?? unserialize("O:9:\"Exception\":1:{s:16:\"\0Exception\0trace\";a:0:{}}"); - $signalingCallback = $signalingCallback ?? function () use ($signalingException) { throw $signalingException; }; - - try { - $value = $pool->get($item->getKey(), $signalingCallback, 0); - $logger && $logger->info('Item "{key}" retrieved after lock was released', ['key' => $item->getKey()]); - $save = false; - - return $value; - } catch (\Exception $e) { - if ($signalingException !== $e) { - throw $e; - } - $logger && $logger->info('Item "{key}" not found while lock was released, now retrying', ['key' => $item->getKey()]); - } - } - - return null; - } - - private static function open(int $key) - { - if (null !== $h = self::$openedFiles[$key] ?? null) { - return $h; - } - set_error_handler(function () {}); - try { - $h = fopen(self::$files[$key], 'r+'); - } finally { - restore_error_handler(); - } - - return self::$openedFiles[$key] = $h ?: @fopen(self::$files[$key], 'r'); - } -} diff --git a/vendor/symfony/cache/Marshaller/DefaultMarshaller.php b/vendor/symfony/cache/Marshaller/DefaultMarshaller.php deleted file mode 100644 index 24b67a5..0000000 --- a/vendor/symfony/cache/Marshaller/DefaultMarshaller.php +++ /dev/null @@ -1,99 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Marshaller; - -use Symfony\Component\Cache\Exception\CacheException; - -/** - * Serializes/unserializes values using igbinary_serialize() if available, serialize() otherwise. - * - * @author Nicolas Grekas - */ -class DefaultMarshaller implements MarshallerInterface -{ - private $useIgbinarySerialize = true; - - public function __construct(bool $useIgbinarySerialize = null) - { - if (null === $useIgbinarySerialize) { - $useIgbinarySerialize = \extension_loaded('igbinary') && \PHP_VERSION_ID < 70400; - } elseif ($useIgbinarySerialize && (!\extension_loaded('igbinary') || \PHP_VERSION_ID >= 70400)) { - throw new CacheException('The "igbinary" PHP extension is not '.(\PHP_VERSION_ID >= 70400 ? 'compatible with PHP 7.4.' : 'loaded.')); - } - $this->useIgbinarySerialize = $useIgbinarySerialize; - } - - /** - * {@inheritdoc} - */ - public function marshall(array $values, ?array &$failed): array - { - $serialized = $failed = []; - - foreach ($values as $id => $value) { - try { - if ($this->useIgbinarySerialize) { - $serialized[$id] = igbinary_serialize($value); - } else { - $serialized[$id] = serialize($value); - } - } catch (\Exception $e) { - $failed[] = $id; - } - } - - return $serialized; - } - - /** - * {@inheritdoc} - */ - public function unmarshall(string $value) - { - if ('b:0;' === $value) { - return false; - } - if ('N;' === $value) { - return null; - } - static $igbinaryNull; - if ($value === ($igbinaryNull ?? $igbinaryNull = \extension_loaded('igbinary') && \PHP_VERSION_ID < 70400 ? igbinary_serialize(null) : false)) { - return null; - } - $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); - try { - if (':' === ($value[1] ?? ':')) { - if (false !== $value = unserialize($value)) { - return $value; - } - } elseif (false === $igbinaryNull) { - throw new \RuntimeException('Failed to unserialize values, did you forget to install the "igbinary" extension?'); - } elseif (null !== $value = igbinary_unserialize($value)) { - return $value; - } - - throw new \DomainException(error_get_last() ? error_get_last()['message'] : 'Failed to unserialize values.'); - } catch (\Error $e) { - throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); - } finally { - ini_set('unserialize_callback_func', $unserializeCallbackHandler); - } - } - - /** - * @internal - */ - public static function handleUnserializeCallback(string $class) - { - throw new \DomainException('Class not found: '.$class); - } -} diff --git a/vendor/symfony/cache/Marshaller/DeflateMarshaller.php b/vendor/symfony/cache/Marshaller/DeflateMarshaller.php deleted file mode 100644 index 5544806..0000000 --- a/vendor/symfony/cache/Marshaller/DeflateMarshaller.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Marshaller; - -use Symfony\Component\Cache\Exception\CacheException; - -/** - * Compresses values using gzdeflate(). - * - * @author Nicolas Grekas - */ -class DeflateMarshaller implements MarshallerInterface -{ - private $marshaller; - - public function __construct(MarshallerInterface $marshaller) - { - if (!\function_exists('gzdeflate')) { - throw new CacheException('The "zlib" PHP extension is not loaded.'); - } - - $this->marshaller = $marshaller; - } - - /** - * {@inheritdoc} - */ - public function marshall(array $values, ?array &$failed): array - { - return array_map('gzdeflate', $this->marshaller->marshall($values, $failed)); - } - - /** - * {@inheritdoc} - */ - public function unmarshall(string $value) - { - if (false !== $inflatedValue = @gzinflate($value)) { - $value = $inflatedValue; - } - - return $this->marshaller->unmarshall($value); - } -} diff --git a/vendor/symfony/cache/Marshaller/MarshallerInterface.php b/vendor/symfony/cache/Marshaller/MarshallerInterface.php deleted file mode 100644 index cdd6c40..0000000 --- a/vendor/symfony/cache/Marshaller/MarshallerInterface.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Marshaller; - -/** - * Serializes/unserializes PHP values. - * - * Implementations of this interface MUST deal with errors carefully. They MUST - * also deal with forward and backward compatibility at the storage format level. - * - * @author Nicolas Grekas - */ -interface MarshallerInterface -{ - /** - * Serializes a list of values. - * - * When serialization fails for a specific value, no exception should be - * thrown. Instead, its key should be listed in $failed. - */ - public function marshall(array $values, ?array &$failed): array; - - /** - * Unserializes a single value and throws an exception if anything goes wrong. - * - * @return mixed - * - * @throws \Exception Whenever unserialization fails - */ - public function unmarshall(string $value); -} diff --git a/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php b/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php deleted file mode 100644 index 5d1e303..0000000 --- a/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php +++ /dev/null @@ -1,89 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Marshaller; - -/** - * A marshaller optimized for data structures generated by AbstractTagAwareAdapter. - * - * @author Nicolas Grekas - */ -class TagAwareMarshaller implements MarshallerInterface -{ - private $marshaller; - - public function __construct(MarshallerInterface $marshaller = null) - { - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - } - - /** - * {@inheritdoc} - */ - public function marshall(array $values, ?array &$failed): array - { - $failed = $notSerialized = $serialized = []; - - foreach ($values as $id => $value) { - if (\is_array($value) && \is_array($value['tags'] ?? null) && \array_key_exists('value', $value) && \count($value) === 2 + (\is_string($value['meta'] ?? null) && 8 === \strlen($value['meta']))) { - // if the value is an array with keys "tags", "value" and "meta", use a compact serialization format - // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F allow detecting this format quickly in unmarshall() - - $v = $this->marshaller->marshall($value, $f); - - if ($f) { - $f = []; - $failed[] = $id; - } else { - if ([] === $value['tags']) { - $v['tags'] = ''; - } - - $serialized[$id] = "\x9D".($value['meta'] ?? "\0\0\0\0\0\0\0\0").pack('N', \strlen($v['tags'])).$v['tags'].$v['value']; - $serialized[$id][9] = "\x5F"; - } - } else { - // other arbitratry values are serialized using the decorated marshaller below - $notSerialized[$id] = $value; - } - } - - if ($notSerialized) { - $serialized += $this->marshaller->marshall($notSerialized, $f); - $failed = array_merge($failed, $f); - } - - return $serialized; - } - - /** - * {@inheritdoc} - */ - public function unmarshall(string $value) - { - // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F - if (13 >= \strlen($value) || "\x9D" !== $value[0] || "\0" !== $value[5] || "\x5F" !== $value[9]) { - return $this->marshaller->unmarshall($value); - } - - // data consists of value, tags and metadata which we need to unpack - $meta = substr($value, 1, 12); - $meta[8] = "\0"; - $tagLen = unpack('Nlen', $meta, 8)['len']; - $meta = substr($meta, 0, 8); - - return [ - 'value' => $this->marshaller->unmarshall(substr($value, 13 + $tagLen)), - 'tags' => $tagLen ? $this->marshaller->unmarshall(substr($value, 13, $tagLen)) : [], - 'meta' => "\0\0\0\0\0\0\0\0" === $meta ? null : $meta, - ]; - } -} diff --git a/vendor/symfony/cache/PruneableInterface.php b/vendor/symfony/cache/PruneableInterface.php deleted file mode 100644 index 4261525..0000000 --- a/vendor/symfony/cache/PruneableInterface.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache; - -/** - * Interface extends psr-6 and psr-16 caches to allow for pruning (deletion) of all expired cache items. - */ -interface PruneableInterface -{ - /** - * @return bool - */ - public function prune(); -} diff --git a/vendor/symfony/cache/Psr16Cache.php b/vendor/symfony/cache/Psr16Cache.php deleted file mode 100644 index 6501516..0000000 --- a/vendor/symfony/cache/Psr16Cache.php +++ /dev/null @@ -1,277 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache; - -use Psr\Cache\CacheException as Psr6CacheException; -use Psr\Cache\CacheItemPoolInterface; -use Psr\SimpleCache\CacheException as SimpleCacheException; -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Traits\ProxyTrait; - -/** - * Turns a PSR-6 cache into a PSR-16 one. - * - * @author Nicolas Grekas - */ -class Psr16Cache implements CacheInterface, PruneableInterface, ResettableInterface -{ - use ProxyTrait; - - private const METADATA_EXPIRY_OFFSET = 1527506807; - - private $createCacheItem; - private $cacheItemPrototype; - - public function __construct(CacheItemPoolInterface $pool) - { - $this->pool = $pool; - - if (!$pool instanceof AdapterInterface) { - return; - } - $cacheItemPrototype = &$this->cacheItemPrototype; - $createCacheItem = \Closure::bind( - static function ($key, $value, $allowInt = false) use (&$cacheItemPrototype) { - $item = clone $cacheItemPrototype; - $item->key = $allowInt && \is_int($key) ? (string) $key : CacheItem::validateKey($key); - $item->value = $value; - $item->isHit = false; - - return $item; - }, - null, - CacheItem::class - ); - $this->createCacheItem = function ($key, $value, $allowInt = false) use ($createCacheItem) { - if (null === $this->cacheItemPrototype) { - $this->get($allowInt && \is_int($key) ? (string) $key : $key); - } - $this->createCacheItem = $createCacheItem; - - return $createCacheItem($key, null, $allowInt)->set($value); - }; - } - - /** - * {@inheritdoc} - */ - public function get($key, $default = null) - { - try { - $item = $this->pool->getItem($key); - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - if (null === $this->cacheItemPrototype) { - $this->cacheItemPrototype = clone $item; - $this->cacheItemPrototype->set(null); - } - - return $item->isHit() ? $item->get() : $default; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function set($key, $value, $ttl = null) - { - try { - if (null !== $f = $this->createCacheItem) { - $item = $f($key, $value); - } else { - $item = $this->pool->getItem($key)->set($value); - } - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - if (null !== $ttl) { - $item->expiresAfter($ttl); - } - - return $this->pool->save($item); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function delete($key) - { - try { - return $this->pool->deleteItem($key); - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear() - { - return $this->pool->clear(); - } - - /** - * {@inheritdoc} - * - * @return iterable - */ - public function getMultiple($keys, $default = null) - { - if ($keys instanceof \Traversable) { - $keys = iterator_to_array($keys, false); - } elseif (!\is_array($keys)) { - throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', \is_object($keys) ? \get_class($keys) : \gettype($keys))); - } - - try { - $items = $this->pool->getItems($keys); - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - $values = []; - - if (!$this->pool instanceof AdapterInterface) { - foreach ($items as $key => $item) { - $values[$key] = $item->isHit() ? $item->get() : $default; - } - - return $values; - } - - foreach ($items as $key => $item) { - if (!$item->isHit()) { - $values[$key] = $default; - continue; - } - $values[$key] = $item->get(); - - if (!$metadata = $item->getMetadata()) { - continue; - } - unset($metadata[CacheItem::METADATA_TAGS]); - - if ($metadata) { - $values[$key] = ["\x9D".pack('VN', (int) (0.1 + $metadata[CacheItem::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[CacheItem::METADATA_CTIME])."\x5F" => $values[$key]]; - } - } - - return $values; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function setMultiple($values, $ttl = null) - { - $valuesIsArray = \is_array($values); - if (!$valuesIsArray && !$values instanceof \Traversable) { - throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given', \is_object($values) ? \get_class($values) : \gettype($values))); - } - $items = []; - - try { - if (null !== $f = $this->createCacheItem) { - $valuesIsArray = false; - foreach ($values as $key => $value) { - $items[$key] = $f($key, $value, true); - } - } elseif ($valuesIsArray) { - $items = []; - foreach ($values as $key => $value) { - $items[] = (string) $key; - } - $items = $this->pool->getItems($items); - } else { - foreach ($values as $key => $value) { - if (\is_int($key)) { - $key = (string) $key; - } - $items[$key] = $this->pool->getItem($key)->set($value); - } - } - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - $ok = true; - - foreach ($items as $key => $item) { - if ($valuesIsArray) { - $item->set($values[$key]); - } - if (null !== $ttl) { - $item->expiresAfter($ttl); - } - $ok = $this->pool->saveDeferred($item) && $ok; - } - - return $this->pool->commit() && $ok; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteMultiple($keys) - { - if ($keys instanceof \Traversable) { - $keys = iterator_to_array($keys, false); - } elseif (!\is_array($keys)) { - throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given', \is_object($keys) ? \get_class($keys) : \gettype($keys))); - } - - try { - return $this->pool->deleteItems($keys); - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function has($key) - { - try { - return $this->pool->hasItem($key); - } catch (SimpleCacheException $e) { - throw $e; - } catch (Psr6CacheException $e) { - throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); - } - } -} diff --git a/vendor/symfony/cache/README.md b/vendor/symfony/cache/README.md deleted file mode 100644 index c4ab752..0000000 --- a/vendor/symfony/cache/README.md +++ /dev/null @@ -1,18 +0,0 @@ -Symfony PSR-6 implementation for caching -======================================== - -This component provides an extended [PSR-6](http://www.php-fig.org/psr/psr-6/) -implementation for adding cache to your applications. It is designed to have a -low overhead so that caching is fastest. It ships with a few caching adapters -for the most widespread and suited to caching backends. It also provides a -`doctrine/cache` proxy adapter to cover more advanced caching needs and a proxy -adapter for greater interoperability between PSR-6 implementations. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/cache.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/cache/ResettableInterface.php b/vendor/symfony/cache/ResettableInterface.php deleted file mode 100644 index 7b0a853..0000000 --- a/vendor/symfony/cache/ResettableInterface.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache; - -use Symfony\Contracts\Service\ResetInterface; - -/** - * Resets a pool's local state. - */ -interface ResettableInterface extends ResetInterface -{ -} diff --git a/vendor/symfony/cache/Traits/AbstractAdapterTrait.php b/vendor/symfony/cache/Traits/AbstractAdapterTrait.php deleted file mode 100644 index d166c53..0000000 --- a/vendor/symfony/cache/Traits/AbstractAdapterTrait.php +++ /dev/null @@ -1,392 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -use Psr\Cache\CacheItemInterface; -use Psr\Log\LoggerAwareTrait; -use Symfony\Component\Cache\CacheItem; - -/** - * @author Nicolas Grekas - * - * @internal - */ -trait AbstractAdapterTrait -{ - use LoggerAwareTrait; - - /** - * @var \Closure needs to be set by class, signature is function(string , mixed , bool ) - */ - private $createCacheItem; - - /** - * @var \Closure needs to be set by class, signature is function(array , string , array <&expiredIds>) - */ - private $mergeByLifetime; - - private $namespace; - private $namespaceVersion = ''; - private $versioningIsEnabled = false; - private $deferred = []; - private $ids = []; - - /** - * @var int|null The maximum length to enforce for identifiers or null when no limit applies - */ - protected $maxIdLength; - - /** - * Fetches several cache items. - * - * @param array $ids The cache identifiers to fetch - * - * @return array|\Traversable The corresponding values found in the cache - */ - abstract protected function doFetch(array $ids); - - /** - * Confirms if the cache contains specified cache item. - * - * @param string $id The identifier for which to check existence - * - * @return bool True if item exists in the cache, false otherwise - */ - abstract protected function doHave(string $id); - - /** - * Deletes all items in the pool. - * - * @param string $namespace The prefix used for all identifiers managed by this pool - * - * @return bool True if the pool was successfully cleared, false otherwise - */ - abstract protected function doClear(string $namespace); - - /** - * Removes multiple items from the pool. - * - * @param array $ids An array of identifiers that should be removed from the pool - * - * @return bool True if the items were successfully removed, false otherwise - */ - abstract protected function doDelete(array $ids); - - /** - * Persists several cache items immediately. - * - * @param array $values The values to cache, indexed by their cache identifier - * @param int $lifetime The lifetime of the cached values, 0 for persisting until manual cleaning - * - * @return array|bool The identifiers that failed to be cached or a boolean stating if caching succeeded or not - */ - abstract protected function doSave(array $values, int $lifetime); - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasItem($key) - { - $id = $this->getId($key); - - if (isset($this->deferred[$key])) { - $this->commit(); - } - - try { - return $this->doHave($id); - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to check if key "{key}" is cached: '.$e->getMessage(), ['key' => $key, 'exception' => $e]); - - return false; - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function clear(string $prefix = '') - { - $this->deferred = []; - if ($cleared = $this->versioningIsEnabled) { - $namespaceVersion = substr_replace(base64_encode(pack('V', mt_rand())), static::NS_SEPARATOR, 5); - try { - $cleared = $this->doSave([static::NS_SEPARATOR.$this->namespace => $namespaceVersion], 0); - } catch (\Exception $e) { - $cleared = false; - } - if ($cleared = true === $cleared || [] === $cleared) { - $this->namespaceVersion = $namespaceVersion; - $this->ids = []; - } - } - - try { - return $this->doClear($this->namespace.$prefix) || $cleared; - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to clear the cache: '.$e->getMessage(), ['exception' => $e]); - - return false; - } - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItem($key) - { - return $this->deleteItems([$key]); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function deleteItems(array $keys) - { - $ids = []; - - foreach ($keys as $key) { - $ids[$key] = $this->getId($key); - unset($this->deferred[$key]); - } - - try { - if ($this->doDelete($ids)) { - return true; - } - } catch (\Exception $e) { - } - - $ok = true; - - // When bulk-delete failed, retry each item individually - foreach ($ids as $key => $id) { - try { - $e = null; - if ($this->doDelete([$id])) { - continue; - } - } catch (\Exception $e) { - } - $message = 'Failed to delete key "{key}"'.($e instanceof \Exception ? ': '.$e->getMessage() : '.'); - CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e]); - $ok = false; - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - if ($this->deferred) { - $this->commit(); - } - $id = $this->getId($key); - - $f = $this->createCacheItem; - $isHit = false; - $value = null; - - try { - foreach ($this->doFetch([$id]) as $value) { - $isHit = true; - } - - return $f($key, $value, $isHit); - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e]); - } - - return $f($key, null, false); - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = []) - { - if ($this->deferred) { - $this->commit(); - } - $ids = []; - - foreach ($keys as $key) { - $ids[] = $this->getId($key); - } - try { - $items = $this->doFetch($ids); - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch items: '.$e->getMessage(), ['keys' => $keys, 'exception' => $e]); - $items = []; - } - $ids = array_combine($ids, $keys); - - return $this->generateItems($items, $ids); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function save(CacheItemInterface $item) - { - if (!$item instanceof CacheItem) { - return false; - } - $this->deferred[$item->getKey()] = $item; - - return $this->commit(); - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function saveDeferred(CacheItemInterface $item) - { - if (!$item instanceof CacheItem) { - return false; - } - $this->deferred[$item->getKey()] = $item; - - return true; - } - - /** - * Enables/disables versioning of items. - * - * When versioning is enabled, clearing the cache is atomic and doesn't require listing existing keys to proceed, - * but old keys may need garbage collection and extra round-trips to the back-end are required. - * - * Calling this method also clears the memoized namespace version and thus forces a resynchonization of it. - * - * @param bool $enable - * - * @return bool the previous state of versioning - */ - public function enableVersioning($enable = true) - { - $wasEnabled = $this->versioningIsEnabled; - $this->versioningIsEnabled = (bool) $enable; - $this->namespaceVersion = ''; - $this->ids = []; - - return $wasEnabled; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - if ($this->deferred) { - $this->commit(); - } - $this->namespaceVersion = ''; - $this->ids = []; - } - - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - public function __destruct() - { - if ($this->deferred) { - $this->commit(); - } - } - - private function generateItems(iterable $items, array &$keys): iterable - { - $f = $this->createCacheItem; - - try { - foreach ($items as $id => $value) { - if (!isset($keys[$id])) { - $id = key($keys); - } - $key = $keys[$id]; - unset($keys[$id]); - yield $key => $f($key, $value, true); - } - } catch (\Exception $e) { - CacheItem::log($this->logger, 'Failed to fetch items: '.$e->getMessage(), ['keys' => array_values($keys), 'exception' => $e]); - } - - foreach ($keys as $key) { - yield $key => $f($key, null, false); - } - } - - private function getId($key) - { - if ($this->versioningIsEnabled && '' === $this->namespaceVersion) { - $this->ids = []; - $this->namespaceVersion = '1'.static::NS_SEPARATOR; - try { - foreach ($this->doFetch([static::NS_SEPARATOR.$this->namespace]) as $v) { - $this->namespaceVersion = $v; - } - if ('1'.static::NS_SEPARATOR === $this->namespaceVersion) { - $this->namespaceVersion = substr_replace(base64_encode(pack('V', time())), static::NS_SEPARATOR, 5); - $this->doSave([static::NS_SEPARATOR.$this->namespace => $this->namespaceVersion], 0); - } - } catch (\Exception $e) { - } - } - - if (\is_string($key) && isset($this->ids[$key])) { - return $this->namespace.$this->namespaceVersion.$this->ids[$key]; - } - CacheItem::validateKey($key); - $this->ids[$key] = $key; - - if (null === $this->maxIdLength) { - return $this->namespace.$this->namespaceVersion.$key; - } - if (\strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) { - // Use MD5 to favor speed over security, which is not an issue here - $this->ids[$key] = $id = substr_replace(base64_encode(hash('md5', $key, true)), static::NS_SEPARATOR, -(\strlen($this->namespaceVersion) + 2)); - $id = $this->namespace.$this->namespaceVersion.$id; - } - - return $id; - } - - /** - * @internal - */ - public static function handleUnserializeCallback($class) - { - throw new \DomainException('Class not found: '.$class); - } -} diff --git a/vendor/symfony/cache/Traits/ContractsTrait.php b/vendor/symfony/cache/Traits/ContractsTrait.php deleted file mode 100644 index c5827c3..0000000 --- a/vendor/symfony/cache/Traits/ContractsTrait.php +++ /dev/null @@ -1,97 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\CacheItem; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\LockRegistry; -use Symfony\Contracts\Cache\CacheInterface; -use Symfony\Contracts\Cache\CacheTrait; -use Symfony\Contracts\Cache\ItemInterface; - -/** - * @author Nicolas Grekas - * - * @internal - */ -trait ContractsTrait -{ - use CacheTrait { - doGet as private contractsGet; - } - - private $callbackWrapper = [LockRegistry::class, 'compute']; - private $computing = []; - - /** - * Wraps the callback passed to ->get() in a callable. - * - * @return callable the previous callback wrapper - */ - public function setCallbackWrapper(?callable $callbackWrapper): callable - { - $previousWrapper = $this->callbackWrapper; - $this->callbackWrapper = $callbackWrapper ?? function (callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger) { - return $callback($item, $save); - }; - - return $previousWrapper; - } - - private function doGet(AdapterInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null) - { - if (0 > $beta = $beta ?? 1.0) { - throw new InvalidArgumentException(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', \get_class($this), $beta)); - } - - static $setMetadata; - - $setMetadata = $setMetadata ?? \Closure::bind( - static function (CacheItem $item, float $startTime, ?array &$metadata) { - if ($item->expiry > $endTime = microtime(true)) { - $item->newMetadata[CacheItem::METADATA_EXPIRY] = $metadata[CacheItem::METADATA_EXPIRY] = $item->expiry; - $item->newMetadata[CacheItem::METADATA_CTIME] = $metadata[CacheItem::METADATA_CTIME] = (int) ceil(1000 * ($endTime - $startTime)); - } else { - unset($metadata[CacheItem::METADATA_EXPIRY], $metadata[CacheItem::METADATA_CTIME]); - } - }, - null, - CacheItem::class - ); - - return $this->contractsGet($pool, $key, function (CacheItem $item, bool &$save) use ($pool, $callback, $setMetadata, &$metadata, $key) { - // don't wrap nor save recursive calls - if (isset($this->computing[$key])) { - $value = $callback($item, $save); - $save = false; - - return $value; - } - - $this->computing[$key] = $key; - $startTime = microtime(true); - - try { - $value = ($this->callbackWrapper)($callback, $item, $save, $pool, function (CacheItem $item) use ($setMetadata, $startTime, &$metadata) { - $setMetadata($item, $startTime, $metadata); - }, $this->logger ?? null); - $setMetadata($item, $startTime, $metadata); - - return $value; - } finally { - unset($this->computing[$key]); - } - }, $beta, $metadata, $this->logger ?? null); - } -} diff --git a/vendor/symfony/cache/Traits/FilesystemCommonTrait.php b/vendor/symfony/cache/Traits/FilesystemCommonTrait.php deleted file mode 100644 index 01400c8..0000000 --- a/vendor/symfony/cache/Traits/FilesystemCommonTrait.php +++ /dev/null @@ -1,183 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -use Symfony\Component\Cache\Exception\InvalidArgumentException; - -/** - * @author Nicolas Grekas - * - * @internal - */ -trait FilesystemCommonTrait -{ - private $directory; - private $tmp; - - private function init(string $namespace, ?string $directory) - { - if (!isset($directory[0])) { - $directory = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'symfony-cache'; - } else { - $directory = realpath($directory) ?: $directory; - } - if (isset($namespace[0])) { - if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) { - throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0])); - } - $directory .= \DIRECTORY_SEPARATOR.$namespace; - } - if (!file_exists($directory)) { - @mkdir($directory, 0777, true); - } - $directory .= \DIRECTORY_SEPARATOR; - // On Windows the whole path is limited to 258 chars - if ('\\' === \DIRECTORY_SEPARATOR && \strlen($directory) > 234) { - throw new InvalidArgumentException(sprintf('Cache directory too long (%s)', $directory)); - } - - $this->directory = $directory; - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - $ok = true; - - foreach ($this->scanHashDir($this->directory) as $file) { - if ('' !== $namespace && 0 !== strpos($this->getFileKey($file), $namespace)) { - continue; - } - - $ok = ($this->doUnlink($file) || !file_exists($file)) && $ok; - } - - return $ok; - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - $ok = true; - - foreach ($ids as $id) { - $file = $this->getFile($id); - $ok = (!file_exists($file) || $this->doUnlink($file) || !file_exists($file)) && $ok; - } - - return $ok; - } - - protected function doUnlink($file) - { - return @unlink($file); - } - - private function write(string $file, string $data, int $expiresAt = null) - { - set_error_handler(__CLASS__.'::throwError'); - try { - if (null === $this->tmp) { - $this->tmp = $this->directory.uniqid('', true); - } - file_put_contents($this->tmp, $data); - - if (null !== $expiresAt) { - touch($this->tmp, $expiresAt); - } - - return rename($this->tmp, $file); - } finally { - restore_error_handler(); - } - } - - private function getFile(string $id, bool $mkdir = false, string $directory = null) - { - // Use MD5 to favor speed over security, which is not an issue here - $hash = str_replace('/', '-', base64_encode(hash('md5', static::class.$id, true))); - $dir = ($directory ?? $this->directory).strtoupper($hash[0].\DIRECTORY_SEPARATOR.$hash[1].\DIRECTORY_SEPARATOR); - - if ($mkdir && !file_exists($dir)) { - @mkdir($dir, 0777, true); - } - - return $dir.substr($hash, 2, 20); - } - - private function getFileKey(string $file): string - { - return ''; - } - - private function scanHashDir(string $directory): \Generator - { - if (!file_exists($directory)) { - return; - } - - $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; - - for ($i = 0; $i < 38; ++$i) { - if (!file_exists($directory.$chars[$i])) { - continue; - } - - for ($j = 0; $j < 38; ++$j) { - if (!file_exists($dir = $directory.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j])) { - continue; - } - - foreach (@scandir($dir, SCANDIR_SORT_NONE) ?: [] as $file) { - if ('.' !== $file && '..' !== $file) { - yield $dir.\DIRECTORY_SEPARATOR.$file; - } - } - } - } - } - - /** - * @internal - */ - public static function throwError($type, $message, $file, $line) - { - throw new \ErrorException($message, 0, $type, $file, $line); - } - - /** - * @return array - */ - public function __sleep() - { - throw new \BadMethodCallException('Cannot serialize '.__CLASS__); - } - - public function __wakeup() - { - throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); - } - - public function __destruct() - { - if (method_exists(parent::class, '__destruct')) { - parent::__destruct(); - } - if (null !== $this->tmp && file_exists($this->tmp)) { - unlink($this->tmp); - } - } -} diff --git a/vendor/symfony/cache/Traits/FilesystemTrait.php b/vendor/symfony/cache/Traits/FilesystemTrait.php deleted file mode 100644 index d6926c7..0000000 --- a/vendor/symfony/cache/Traits/FilesystemTrait.php +++ /dev/null @@ -1,124 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -use Symfony\Component\Cache\Exception\CacheException; - -/** - * @author Nicolas Grekas - * @author Rob Frawley 2nd - * - * @internal - */ -trait FilesystemTrait -{ - use FilesystemCommonTrait; - - private $marshaller; - - /** - * @return bool - */ - public function prune() - { - $time = time(); - $pruned = true; - - foreach ($this->scanHashDir($this->directory) as $file) { - if (!$h = @fopen($file, 'rb')) { - continue; - } - - if (($expiresAt = (int) fgets($h)) && $time >= $expiresAt) { - fclose($h); - $pruned = @unlink($file) && !file_exists($file) && $pruned; - } else { - fclose($h); - } - } - - return $pruned; - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - $values = []; - $now = time(); - - foreach ($ids as $id) { - $file = $this->getFile($id); - if (!file_exists($file) || !$h = @fopen($file, 'rb')) { - continue; - } - if (($expiresAt = (int) fgets($h)) && $now >= $expiresAt) { - fclose($h); - @unlink($file); - } else { - $i = rawurldecode(rtrim(fgets($h))); - $value = stream_get_contents($h); - fclose($h); - if ($i === $id) { - $values[$id] = $this->marshaller->unmarshall($value); - } - } - } - - return $values; - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - $file = $this->getFile($id); - - return file_exists($file) && (@filemtime($file) > time() || $this->doFetch([$id])); - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - $expiresAt = $lifetime ? (time() + $lifetime) : 0; - $values = $this->marshaller->marshall($values, $failed); - - foreach ($values as $id => $value) { - if (!$this->write($this->getFile($id, true), $expiresAt."\n".rawurlencode($id)."\n".$value, $expiresAt)) { - $failed[] = $id; - } - } - - if ($failed && !is_writable($this->directory)) { - throw new CacheException(sprintf('Cache directory is not writable (%s)', $this->directory)); - } - - return $failed; - } - - private function getFileKey(string $file): string - { - if (!$h = @fopen($file, 'rb')) { - return ''; - } - - fgets($h); // expiry - $encodedKey = fgets($h); - fclose($h); - - return rawurldecode(rtrim($encodedKey)); - } -} diff --git a/vendor/symfony/cache/Traits/ProxyTrait.php b/vendor/symfony/cache/Traits/ProxyTrait.php deleted file mode 100644 index c86f360..0000000 --- a/vendor/symfony/cache/Traits/ProxyTrait.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * @author Nicolas Grekas - * - * @internal - */ -trait ProxyTrait -{ - private $pool; - - /** - * {@inheritdoc} - */ - public function prune() - { - return $this->pool instanceof PruneableInterface && $this->pool->prune(); - } - - /** - * {@inheritdoc} - */ - public function reset() - { - if ($this->pool instanceof ResetInterface) { - $this->pool->reset(); - } - } -} diff --git a/vendor/symfony/cache/Traits/RedisClusterProxy.php b/vendor/symfony/cache/Traits/RedisClusterProxy.php deleted file mode 100644 index 73c6a4f..0000000 --- a/vendor/symfony/cache/Traits/RedisClusterProxy.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -/** - * @author Alessandro Chitolina - * - * @internal - */ -class RedisClusterProxy -{ - private $redis; - private $initializer; - - public function __construct(\Closure $initializer) - { - $this->initializer = $initializer; - } - - public function __call(string $method, array $args) - { - $this->redis ?: $this->redis = $this->initializer->__invoke(); - - return $this->redis->{$method}(...$args); - } - - public function hscan($strKey, &$iIterator, $strPattern = null, $iCount = null) - { - $this->redis ?: $this->redis = $this->initializer->__invoke(); - - return $this->redis->hscan($strKey, $iIterator, $strPattern, $iCount); - } - - public function scan(&$iIterator, $strPattern = null, $iCount = null) - { - $this->redis ?: $this->redis = $this->initializer->__invoke(); - - return $this->redis->scan($iIterator, $strPattern, $iCount); - } - - public function sscan($strKey, &$iIterator, $strPattern = null, $iCount = null) - { - $this->redis ?: $this->redis = $this->initializer->__invoke(); - - return $this->redis->sscan($strKey, $iIterator, $strPattern, $iCount); - } - - public function zscan($strKey, &$iIterator, $strPattern = null, $iCount = null) - { - $this->redis ?: $this->redis = $this->initializer->__invoke(); - - return $this->redis->zscan($strKey, $iIterator, $strPattern, $iCount); - } -} diff --git a/vendor/symfony/cache/Traits/RedisProxy.php b/vendor/symfony/cache/Traits/RedisProxy.php deleted file mode 100644 index ec5cfab..0000000 --- a/vendor/symfony/cache/Traits/RedisProxy.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -/** - * @author Nicolas Grekas - * - * @internal - */ -class RedisProxy -{ - private $redis; - private $initializer; - private $ready = false; - - public function __construct(\Redis $redis, \Closure $initializer) - { - $this->redis = $redis; - $this->initializer = $initializer; - } - - public function __call(string $method, array $args) - { - $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); - - return $this->redis->{$method}(...$args); - } - - public function hscan($strKey, &$iIterator, $strPattern = null, $iCount = null) - { - $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); - - return $this->redis->hscan($strKey, $iIterator, $strPattern, $iCount); - } - - public function scan(&$iIterator, $strPattern = null, $iCount = null) - { - $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); - - return $this->redis->scan($iIterator, $strPattern, $iCount); - } - - public function sscan($strKey, &$iIterator, $strPattern = null, $iCount = null) - { - $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); - - return $this->redis->sscan($strKey, $iIterator, $strPattern, $iCount); - } - - public function zscan($strKey, &$iIterator, $strPattern = null, $iCount = null) - { - $this->ready ?: $this->ready = $this->initializer->__invoke($this->redis); - - return $this->redis->zscan($strKey, $iIterator, $strPattern, $iCount); - } -} diff --git a/vendor/symfony/cache/Traits/RedisTrait.php b/vendor/symfony/cache/Traits/RedisTrait.php deleted file mode 100644 index 5a8460a..0000000 --- a/vendor/symfony/cache/Traits/RedisTrait.php +++ /dev/null @@ -1,511 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Cache\Traits; - -use Predis\Connection\Aggregate\ClusterInterface; -use Predis\Connection\Aggregate\RedisCluster; -use Predis\Response\Status; -use Symfony\Component\Cache\Exception\CacheException; -use Symfony\Component\Cache\Exception\InvalidArgumentException; -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; - -/** - * @author Aurimas Niekis - * @author Nicolas Grekas - * - * @internal - */ -trait RedisTrait -{ - private static $defaultConnectionOptions = [ - 'class' => null, - 'persistent' => 0, - 'persistent_id' => null, - 'timeout' => 30, - 'read_timeout' => 0, - 'retry_interval' => 0, - 'tcp_keepalive' => 0, - 'lazy' => null, - 'redis_cluster' => false, - 'redis_sentinel' => null, - 'dbindex' => 0, - 'failover' => 'none', - ]; - private $redis; - private $marshaller; - - /** - * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface $redisClient - */ - private function init($redisClient, string $namespace, int $defaultLifetime, ?MarshallerInterface $marshaller) - { - parent::__construct($namespace, $defaultLifetime); - - if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) { - throw new InvalidArgumentException(sprintf('RedisAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0])); - } - - if (!$redisClient instanceof \Redis && !$redisClient instanceof \RedisArray && !$redisClient instanceof \RedisCluster && !$redisClient instanceof \Predis\ClientInterface && !$redisClient instanceof RedisProxy && !$redisClient instanceof RedisClusterProxy) { - throw new InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, %s given.', __METHOD__, \is_object($redisClient) ? \get_class($redisClient) : \gettype($redisClient))); - } - - if ($redisClient instanceof \Predis\ClientInterface && $redisClient->getOptions()->exceptions) { - $options = clone $redisClient->getOptions(); - \Closure::bind(function () { $this->options['exceptions'] = false; }, $options, $options)(); - $redisClient = new $redisClient($redisClient->getConnection(), $options); - } - - $this->redis = $redisClient; - $this->marshaller = $marshaller ?? new DefaultMarshaller(); - } - - /** - * Creates a Redis connection using a DSN configuration. - * - * Example DSN: - * - redis://localhost - * - redis://example.com:1234 - * - redis://secret@example.com/13 - * - redis:///var/run/redis.sock - * - redis://secret@/var/run/redis.sock/13 - * - * @param string $dsn - * @param array $options See self::$defaultConnectionOptions - * - * @throws InvalidArgumentException when the DSN is invalid - * - * @return \Redis|\RedisCluster|\Predis\ClientInterface According to the "class" option - */ - public static function createConnection($dsn, array $options = []) - { - if (0 === strpos($dsn, 'redis:')) { - $scheme = 'redis'; - } elseif (0 === strpos($dsn, 'rediss:')) { - $scheme = 'rediss'; - } else { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s does not start with "redis:" or "rediss".', $dsn)); - } - - if (!\extension_loaded('redis') && !class_exists(\Predis\Client::class)) { - throw new CacheException(sprintf('Cannot find the "redis" extension nor the "predis/predis" package: %s', $dsn)); - } - - $params = preg_replace_callback('#^'.$scheme.':(//)?(?:(?:[^:@]*+:)?([^@]*+)@)?#', function ($m) use (&$auth) { - if (isset($m[2])) { - $auth = $m[2]; - } - - return 'file:'.($m[1] ?? ''); - }, $dsn); - - if (false === $params = parse_url($params)) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s', $dsn)); - } - - $query = $hosts = []; - - if (isset($params['query'])) { - parse_str($params['query'], $query); - - if (isset($query['host'])) { - if (!\is_array($hosts = $query['host'])) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s', $dsn)); - } - foreach ($hosts as $host => $parameters) { - if (\is_string($parameters)) { - parse_str($parameters, $parameters); - } - if (false === $i = strrpos($host, ':')) { - $hosts[$host] = ['scheme' => 'tcp', 'host' => $host, 'port' => 6379] + $parameters; - } elseif ($port = (int) substr($host, 1 + $i)) { - $hosts[$host] = ['scheme' => 'tcp', 'host' => substr($host, 0, $i), 'port' => $port] + $parameters; - } else { - $hosts[$host] = ['scheme' => 'unix', 'path' => substr($host, 0, $i)] + $parameters; - } - } - $hosts = array_values($hosts); - } - } - - if (isset($params['host']) || isset($params['path'])) { - if (!isset($params['dbindex']) && isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { - $params['dbindex'] = $m[1]; - $params['path'] = substr($params['path'], 0, -\strlen($m[0])); - } - - if (isset($params['host'])) { - array_unshift($hosts, ['scheme' => 'tcp', 'host' => $params['host'], 'port' => $params['port'] ?? 6379]); - } else { - array_unshift($hosts, ['scheme' => 'unix', 'path' => $params['path']]); - } - } - - if (!$hosts) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s', $dsn)); - } - - if (isset($params['redis_sentinel']) && !class_exists(\Predis\Client::class)) { - throw new CacheException(sprintf('Redis Sentinel support requires the "predis/predis" package: %s', $dsn)); - } - - $params += $query + $options + self::$defaultConnectionOptions; - - if (null === $params['class'] && !isset($params['redis_sentinel']) && \extension_loaded('redis')) { - $class = $params['redis_cluster'] ? \RedisCluster::class : (1 < \count($hosts) ? \RedisArray::class : \Redis::class); - } else { - $class = null === $params['class'] ? \Predis\Client::class : $params['class']; - } - - if (is_a($class, \Redis::class, true)) { - $connect = $params['persistent'] || $params['persistent_id'] ? 'pconnect' : 'connect'; - $redis = new $class(); - - $initializer = function ($redis) use ($connect, $params, $dsn, $auth, $hosts) { - try { - @$redis->{$connect}($hosts[0]['host'] ?? $hosts[0]['path'], $hosts[0]['port'] ?? null, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval']); - } catch (\RedisException $e) { - throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e->getMessage(), $dsn)); - } - - set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); - $isConnected = $redis->isConnected(); - restore_error_handler(); - if (!$isConnected) { - $error = preg_match('/^Redis::p?connect\(\): (.*)/', $error, $error) ? sprintf(' (%s)', $error[1]) : ''; - throw new InvalidArgumentException(sprintf('Redis connection failed%s: %s', $error, $dsn)); - } - - if ((null !== $auth && !$redis->auth($auth)) - || ($params['dbindex'] && !$redis->select($params['dbindex'])) - || ($params['read_timeout'] && !$redis->setOption(\Redis::OPT_READ_TIMEOUT, $params['read_timeout'])) - ) { - $e = preg_replace('/^ERR /', '', $redis->getLastError()); - throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e, $dsn)); - } - - if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { - $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); - } - - return true; - }; - - if ($params['lazy']) { - $redis = new RedisProxy($redis, $initializer); - } else { - $initializer($redis); - } - } elseif (is_a($class, \RedisArray::class, true)) { - foreach ($hosts as $i => $host) { - $hosts[$i] = 'tcp' === $host['scheme'] ? $host['host'].':'.$host['port'] : $host['path']; - } - $params['lazy_connect'] = $params['lazy'] ?? true; - $params['connect_timeout'] = $params['timeout']; - - try { - $redis = new $class($hosts, $params); - } catch (\RedisClusterException $e) { - throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e->getMessage(), $dsn)); - } - - if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { - $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); - } - } elseif (is_a($class, \RedisCluster::class, true)) { - $initializer = function () use ($class, $params, $dsn, $hosts) { - foreach ($hosts as $i => $host) { - $hosts[$i] = 'tcp' === $host['scheme'] ? $host['host'].':'.$host['port'] : $host['path']; - } - - try { - $redis = new $class(null, $hosts, $params['timeout'], $params['read_timeout'], (bool) $params['persistent']); - } catch (\RedisClusterException $e) { - throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e->getMessage(), $dsn)); - } - - if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) { - $redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']); - } - switch ($params['failover']) { - case 'error': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_ERROR); break; - case 'distribute': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_DISTRIBUTE); break; - case 'slaves': $redis->setOption(\RedisCluster::OPT_SLAVE_FAILOVER, \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES); break; - } - - return $redis; - }; - - $redis = $params['lazy'] ? new RedisClusterProxy($initializer) : $initializer(); - } elseif (is_a($class, \Predis\ClientInterface::class, true)) { - if ($params['redis_cluster']) { - $params['cluster'] = 'redis'; - if (isset($params['redis_sentinel'])) { - throw new InvalidArgumentException(sprintf('Cannot use both "redis_cluster" and "redis_sentinel" at the same time: %s', $dsn)); - } - } elseif (isset($params['redis_sentinel'])) { - $params['replication'] = 'sentinel'; - $params['service'] = $params['redis_sentinel']; - } - $params += ['parameters' => []]; - $params['parameters'] += [ - 'persistent' => $params['persistent'], - 'timeout' => $params['timeout'], - 'read_write_timeout' => $params['read_timeout'], - 'tcp_nodelay' => true, - ]; - if ($params['dbindex']) { - $params['parameters']['database'] = $params['dbindex']; - } - if (null !== $auth) { - $params['parameters']['password'] = $auth; - } - if (1 === \count($hosts) && !($params['redis_cluster'] || $params['redis_sentinel'])) { - $hosts = $hosts[0]; - } elseif (\in_array($params['failover'], ['slaves', 'distribute'], true) && !isset($params['replication'])) { - $params['replication'] = true; - $hosts[0] += ['alias' => 'master']; - } - $params['exceptions'] = false; - - $redis = new $class($hosts, array_diff_key($params, self::$defaultConnectionOptions)); - if (isset($params['redis_sentinel'])) { - $redis->getConnection()->setSentinelTimeout($params['timeout']); - } - } elseif (class_exists($class, false)) { - throw new InvalidArgumentException(sprintf('"%s" is not a subclass of "Redis", "RedisArray", "RedisCluster" nor "Predis\ClientInterface".', $class)); - } else { - throw new InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); - } - - return $redis; - } - - /** - * {@inheritdoc} - */ - protected function doFetch(array $ids) - { - if (!$ids) { - return []; - } - - $result = []; - - if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) { - $values = $this->pipeline(function () use ($ids) { - foreach ($ids as $id) { - yield 'get' => [$id]; - } - }); - } else { - $values = $this->redis->mget($ids); - - if (!\is_array($values) || \count($values) !== \count($ids)) { - return []; - } - - $values = array_combine($ids, $values); - } - - foreach ($values as $id => $v) { - if ($v) { - $result[$id] = $this->marshaller->unmarshall($v); - } - } - - return $result; - } - - /** - * {@inheritdoc} - */ - protected function doHave(string $id) - { - return (bool) $this->redis->exists($id); - } - - /** - * {@inheritdoc} - */ - protected function doClear(string $namespace) - { - $cleared = true; - if ($this->redis instanceof \Predis\ClientInterface) { - $evalArgs = [0, $namespace]; - } else { - $evalArgs = [[$namespace], 0]; - } - - foreach ($this->getHosts() as $host) { - if (!isset($namespace[0])) { - $cleared = $host->flushDb() && $cleared; - continue; - } - - $info = $host->info('Server'); - $info = isset($info['Server']) ? $info['Server'] : $info; - - if (!version_compare($info['redis_version'], '2.8', '>=')) { - // As documented in Redis documentation (http://redis.io/commands/keys) using KEYS - // can hang your server when it is executed against large databases (millions of items). - // Whenever you hit this scale, you should really consider upgrading to Redis 2.8 or above. - $cleared = $host->eval("local keys=redis.call('KEYS',ARGV[1]..'*') for i=1,#keys,5000 do redis.call('DEL',unpack(keys,i,math.min(i+4999,#keys))) end return 1", $evalArgs[0], $evalArgs[1]) && $cleared; - continue; - } - - $cursor = null; - do { - $keys = $host instanceof \Predis\ClientInterface ? $host->scan($cursor, 'MATCH', $namespace.'*', 'COUNT', 1000) : $host->scan($cursor, $namespace.'*', 1000); - if (isset($keys[1]) && \is_array($keys[1])) { - $cursor = $keys[0]; - $keys = $keys[1]; - } - if ($keys) { - $this->doDelete($keys); - } - } while ($cursor = (int) $cursor); - } - - return $cleared; - } - - /** - * {@inheritdoc} - */ - protected function doDelete(array $ids) - { - if (!$ids) { - return true; - } - - if ($this->redis instanceof \Predis\ClientInterface && $this->redis->getConnection() instanceof ClusterInterface) { - $this->pipeline(function () use ($ids) { - foreach ($ids as $id) { - yield 'del' => [$id]; - } - })->rewind(); - } else { - $this->redis->del($ids); - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doSave(array $values, int $lifetime) - { - if (!$values = $this->marshaller->marshall($values, $failed)) { - return $failed; - } - - $results = $this->pipeline(function () use ($values, $lifetime) { - foreach ($values as $id => $value) { - if (0 >= $lifetime) { - yield 'set' => [$id, $value]; - } else { - yield 'setEx' => [$id, $lifetime, $value]; - } - } - }); - - foreach ($results as $id => $result) { - if (true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) { - $failed[] = $id; - } - } - - return $failed; - } - - private function pipeline(\Closure $generator, $redis = null): \Generator - { - $ids = []; - $redis = $redis ?? $this->redis; - - if ($redis instanceof RedisClusterProxy || $redis instanceof \RedisCluster || ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof RedisCluster)) { - // phpredis & predis don't support pipelining with RedisCluster - // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining - // see https://github.com/nrk/predis/issues/267#issuecomment-123781423 - $results = []; - foreach ($generator() as $command => $args) { - $results[] = $redis->{$command}(...$args); - $ids[] = 'eval' === $command ? ($redis instanceof \Predis\ClientInterface ? $args[2] : $args[1][0]) : $args[0]; - } - } elseif ($redis instanceof \Predis\ClientInterface) { - $results = $redis->pipeline(static function ($redis) use ($generator, &$ids) { - foreach ($generator() as $command => $args) { - $redis->{$command}(...$args); - $ids[] = 'eval' === $command ? $args[2] : $args[0]; - } - }); - } elseif ($redis instanceof \RedisArray) { - $connections = $results = $ids = []; - foreach ($generator() as $command => $args) { - $id = 'eval' === $command ? $args[1][0] : $args[0]; - if (!isset($connections[$h = $redis->_target($id)])) { - $connections[$h] = [$redis->_instance($h), -1]; - $connections[$h][0]->multi(\Redis::PIPELINE); - } - $connections[$h][0]->{$command}(...$args); - $results[] = [$h, ++$connections[$h][1]]; - $ids[] = $id; - } - foreach ($connections as $h => $c) { - $connections[$h] = $c[0]->exec(); - } - foreach ($results as $k => list($h, $c)) { - $results[$k] = $connections[$h][$c]; - } - } else { - $redis->multi(\Redis::PIPELINE); - foreach ($generator() as $command => $args) { - $redis->{$command}(...$args); - $ids[] = 'eval' === $command ? $args[1][0] : $args[0]; - } - $results = $redis->exec(); - } - - foreach ($ids as $k => $id) { - yield $id => $results[$k]; - } - } - - private function getHosts(): array - { - $hosts = [$this->redis]; - if ($this->redis instanceof \Predis\ClientInterface) { - $connection = $this->redis->getConnection(); - if ($connection instanceof ClusterInterface && $connection instanceof \Traversable) { - $hosts = []; - foreach ($connection as $c) { - $hosts[] = new \Predis\Client($c); - } - } - } elseif ($this->redis instanceof \RedisArray) { - $hosts = []; - foreach ($this->redis->_hosts() as $host) { - $hosts[] = $this->redis->_instance($host); - } - } elseif ($this->redis instanceof RedisClusterProxy || $this->redis instanceof \RedisCluster) { - $hosts = []; - foreach ($this->redis->_masters() as $host) { - $hosts[] = $h = new \Redis(); - $h->connect($host[0], $host[1]); - } - } - - return $hosts; - } -} diff --git a/vendor/symfony/cache/composer.json b/vendor/symfony/cache/composer.json deleted file mode 100644 index 6e23abc..0000000 --- a/vendor/symfony/cache/composer.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "symfony/cache", - "type": "library", - "description": "Symfony Cache component with PSR-6, PSR-16, and tags", - "keywords": ["caching", "psr6"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "provide": { - "psr/cache-implementation": "1.0", - "psr/simple-cache-implementation": "1.0", - "symfony/cache-implementation": "1.0" - }, - "require": { - "php": "^7.2.5", - "psr/cache": "~1.0", - "psr/log": "~1.0", - "symfony/cache-contracts": "^1.1.7|^2", - "symfony/service-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/cache": "~1.6", - "doctrine/dbal": "~2.5", - "predis/predis": "~1.1", - "psr/simple-cache": "^1.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/var-dumper": "^4.4|^5.0" - }, - "conflict": { - "doctrine/dbal": "<2.5", - "symfony/dependency-injection": "<4.4", - "symfony/http-kernel": "<4.4", - "symfony/var-dumper": "<4.4" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Cache\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/config/.gitattributes b/vendor/symfony/config/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/config/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/config/CHANGELOG.md b/vendor/symfony/config/CHANGELOG.md deleted file mode 100644 index 14743e4..0000000 --- a/vendor/symfony/config/CHANGELOG.md +++ /dev/null @@ -1,116 +0,0 @@ -CHANGELOG -========= - -5.0.0 ------ - - * Dropped support for constructing a `TreeBuilder` without passing root node information. - * Removed the `root()` method in `TreeBuilder`, pass the root node information to the constructor instead - * Added method `getChildNodeDefinitions()` to ParentNodeDefinitionInterface - * Removed `FileLoaderLoadException`, use `LoaderLoadException` instead - -4.4.0 ------ - - * added a way to exclude patterns of resources from being imported by the `import()` method - -4.3.0 ------ - - * deprecated using environment variables with `cannotBeEmpty()` if the value is validated with `validate()` - * made `Resource\*` classes final and not implement `Serializable` anymore - * deprecated the `root()` method in `TreeBuilder`, pass the root node information to the constructor instead - -4.2.0 ------ - - * deprecated constructing a `TreeBuilder` without passing root node information - * renamed `FileLoaderLoadException` to `LoaderLoadException` - -4.1.0 ------ - - * added `setPathSeparator` method to `NodeBuilder` class - * added third `$pathSeparator` constructor argument to `BaseNode` - * the `Processor` class has been made final - -4.0.0 ------ - - * removed `ConfigCachePass` - -3.4.0 ------ - - * added `setDeprecated()` method to indicate a deprecated node - * added `XmlUtils::parse()` method to parse an XML string - * deprecated `ConfigCachePass` - -3.3.0 ------ - - * added `ReflectionClassResource` class - * added second `$exists` constructor argument to `ClassExistenceResource` - * made `ClassExistenceResource` work with interfaces and traits - * added `ConfigCachePass` (originally in FrameworkBundle) - * added `castToArray()` helper to turn any config value into an array - -3.0.0 ------ - - * removed `ReferenceDumper` class - * removed the `ResourceInterface::isFresh()` method - * removed `BCResourceInterfaceChecker` class - * removed `ResourceInterface::getResource()` method - -2.8.0 ------ - -The edge case of defining just one value for nodes of type Enum is now allowed: - -```php -$rootNode - ->children() - ->enumNode('variable') - ->values(['value']) - ->end() - ->end() -; -``` - -Before: `InvalidArgumentException` (variable must contain at least two -distinct elements). -After: the code will work as expected and it will restrict the values of the -`variable` option to just `value`. - - * deprecated the `ResourceInterface::isFresh()` method. If you implement custom resource types and they - can be validated that way, make them implement the new `SelfCheckingResourceInterface`. - * deprecated the getResource() method in ResourceInterface. You can still call this method - on concrete classes implementing the interface, but it does not make sense at the interface - level as you need to know about the particular type of resource at hand to understand the - semantics of the returned value. - -2.7.0 ------ - - * added `ConfigCacheInterface`, `ConfigCacheFactoryInterface` and a basic `ConfigCacheFactory` - implementation to delegate creation of ConfigCache instances - -2.2.0 ------ - - * added `ArrayNodeDefinition::canBeEnabled()` and `ArrayNodeDefinition::canBeDisabled()` - to ease configuration when some sections are respectively disabled / enabled - by default. - * added a `normalizeKeys()` method for array nodes (to avoid key normalization) - * added numerical type handling for config definitions - * added convenience methods for optional configuration sections to `ArrayNodeDefinition` - * added a utils class for XML manipulations - -2.1.0 ------ - - * added a way to add documentation on configuration - * implemented `Serializable` on resources - * `LoaderResolverInterface` is now used instead of `LoaderResolver` for type - hinting diff --git a/vendor/symfony/config/ConfigCache.php b/vendor/symfony/config/ConfigCache.php deleted file mode 100644 index 053059b..0000000 --- a/vendor/symfony/config/ConfigCache.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -use Symfony\Component\Config\Resource\SelfCheckingResourceChecker; - -/** - * ConfigCache caches arbitrary content in files on disk. - * - * When in debug mode, those metadata resources that implement - * \Symfony\Component\Config\Resource\SelfCheckingResourceInterface will - * be used to check cache freshness. - * - * @author Fabien Potencier - * @author Matthias Pigulla - */ -class ConfigCache extends ResourceCheckerConfigCache -{ - private $debug; - - /** - * @param string $file The absolute cache path - * @param bool $debug Whether debugging is enabled or not - */ - public function __construct(string $file, bool $debug) - { - $this->debug = $debug; - - $checkers = []; - if (true === $this->debug) { - $checkers = [new SelfCheckingResourceChecker()]; - } - - parent::__construct($file, $checkers); - } - - /** - * Checks if the cache is still fresh. - * - * This implementation always returns true when debug is off and the - * cache file exists. - * - * @return bool true if the cache is fresh, false otherwise - */ - public function isFresh() - { - if (!$this->debug && is_file($this->getPath())) { - return true; - } - - return parent::isFresh(); - } -} diff --git a/vendor/symfony/config/ConfigCacheFactory.php b/vendor/symfony/config/ConfigCacheFactory.php deleted file mode 100644 index 11fd3cb..0000000 --- a/vendor/symfony/config/ConfigCacheFactory.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -/** - * Basic implementation of ConfigCacheFactoryInterface that - * creates an instance of the default ConfigCache. - * - * This factory and/or cache do not support cache validation - * by means of ResourceChecker instances (that is, service-based). - * - * @author Matthias Pigulla - */ -class ConfigCacheFactory implements ConfigCacheFactoryInterface -{ - private $debug; - - /** - * @param bool $debug The debug flag to pass to ConfigCache - */ - public function __construct(bool $debug) - { - $this->debug = $debug; - } - - /** - * {@inheritdoc} - */ - public function cache(string $file, callable $callback) - { - $cache = new ConfigCache($file, $this->debug); - if (!$cache->isFresh()) { - $callback($cache); - } - - return $cache; - } -} diff --git a/vendor/symfony/config/ConfigCacheFactoryInterface.php b/vendor/symfony/config/ConfigCacheFactoryInterface.php deleted file mode 100644 index 7dfa0f2..0000000 --- a/vendor/symfony/config/ConfigCacheFactoryInterface.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -/** - * Interface for a ConfigCache factory. This factory creates - * an instance of ConfigCacheInterface and initializes the - * cache if necessary. - * - * @author Matthias Pigulla - */ -interface ConfigCacheFactoryInterface -{ - /** - * Creates a cache instance and (re-)initializes it if necessary. - * - * @param string $file The absolute cache file path - * @param callable $callable The callable to be executed when the cache needs to be filled (i. e. is not fresh). The cache will be passed as the only parameter to this callback - * - * @return ConfigCacheInterface The cache instance - */ - public function cache(string $file, callable $callable); -} diff --git a/vendor/symfony/config/ConfigCacheInterface.php b/vendor/symfony/config/ConfigCacheInterface.php deleted file mode 100644 index 001e7e7..0000000 --- a/vendor/symfony/config/ConfigCacheInterface.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -use Symfony\Component\Config\Resource\ResourceInterface; - -/** - * Interface for ConfigCache. - * - * @author Matthias Pigulla - */ -interface ConfigCacheInterface -{ - /** - * Gets the cache file path. - * - * @return string The cache file path - */ - public function getPath(); - - /** - * Checks if the cache is still fresh. - * - * This check should take the metadata passed to the write() method into consideration. - * - * @return bool Whether the cache is still fresh - */ - public function isFresh(); - - /** - * Writes the given content into the cache file. Metadata will be stored - * independently and can be used to check cache freshness at a later time. - * - * @param string $content The content to write into the cache - * @param ResourceInterface[]|null $metadata An array of ResourceInterface instances - * - * @throws \RuntimeException When the cache file cannot be written - */ - public function write(string $content, array $metadata = null); -} diff --git a/vendor/symfony/config/Definition/ArrayNode.php b/vendor/symfony/config/Definition/ArrayNode.php deleted file mode 100644 index 88e8eaf..0000000 --- a/vendor/symfony/config/Definition/ArrayNode.php +++ /dev/null @@ -1,406 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; -use Symfony\Component\Config\Definition\Exception\UnsetKeyException; - -/** - * Represents an Array node in the config tree. - * - * @author Johannes M. Schmitt - */ -class ArrayNode extends BaseNode implements PrototypeNodeInterface -{ - protected $xmlRemappings = []; - protected $children = []; - protected $allowFalse = false; - protected $allowNewKeys = true; - protected $addIfNotSet = false; - protected $performDeepMerging = true; - protected $ignoreExtraKeys = false; - protected $removeExtraKeys = true; - protected $normalizeKeys = true; - - public function setNormalizeKeys($normalizeKeys) - { - $this->normalizeKeys = (bool) $normalizeKeys; - } - - /** - * {@inheritdoc} - * - * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML. - * After running this method, all keys are normalized to foo_bar. - * - * If you have a mixed key like foo-bar_moo, it will not be altered. - * The key will also not be altered if the target key already exists. - */ - protected function preNormalize($value) - { - if (!$this->normalizeKeys || !\is_array($value)) { - return $value; - } - - $normalized = []; - - foreach ($value as $k => $v) { - if (false !== strpos($k, '-') && false === strpos($k, '_') && !\array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) { - $normalized[$normalizedKey] = $v; - } else { - $normalized[$k] = $v; - } - } - - return $normalized; - } - - /** - * Retrieves the children of this node. - * - * @return array The children - */ - public function getChildren() - { - return $this->children; - } - - /** - * Sets the xml remappings that should be performed. - * - * @param array $remappings An array of the form [[string, string]] - */ - public function setXmlRemappings(array $remappings) - { - $this->xmlRemappings = $remappings; - } - - /** - * Gets the xml remappings that should be performed. - * - * @return array an array of the form [[string, string]] - */ - public function getXmlRemappings() - { - return $this->xmlRemappings; - } - - /** - * Sets whether to add default values for this array if it has not been - * defined in any of the configuration files. - */ - public function setAddIfNotSet(bool $boolean) - { - $this->addIfNotSet = $boolean; - } - - /** - * Sets whether false is allowed as value indicating that the array should be unset. - */ - public function setAllowFalse(bool $allow) - { - $this->allowFalse = $allow; - } - - /** - * Sets whether new keys can be defined in subsequent configurations. - */ - public function setAllowNewKeys(bool $allow) - { - $this->allowNewKeys = $allow; - } - - /** - * Sets if deep merging should occur. - */ - public function setPerformDeepMerging(bool $boolean) - { - $this->performDeepMerging = $boolean; - } - - /** - * Whether extra keys should just be ignored without an exception. - * - * @param bool $boolean To allow extra keys - * @param bool $remove To remove extra keys - */ - public function setIgnoreExtraKeys(bool $boolean, bool $remove = true) - { - $this->ignoreExtraKeys = $boolean; - $this->removeExtraKeys = $this->ignoreExtraKeys && $remove; - } - - /** - * {@inheritdoc} - */ - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function hasDefaultValue() - { - return $this->addIfNotSet; - } - - /** - * {@inheritdoc} - */ - public function getDefaultValue() - { - if (!$this->hasDefaultValue()) { - throw new \RuntimeException(sprintf('The node at path "%s" has no default value.', $this->getPath())); - } - - $defaults = []; - foreach ($this->children as $name => $child) { - if ($child->hasDefaultValue()) { - $defaults[$name] = $child->getDefaultValue(); - } - } - - return $defaults; - } - - /** - * Adds a child node. - * - * @throws \InvalidArgumentException when the child node has no name - * @throws \InvalidArgumentException when the child node's name is not unique - */ - public function addChild(NodeInterface $node) - { - $name = $node->getName(); - if (!\strlen($name)) { - throw new \InvalidArgumentException('Child nodes must be named.'); - } - if (isset($this->children[$name])) { - throw new \InvalidArgumentException(sprintf('A child node named "%s" already exists.', $name)); - } - - $this->children[$name] = $node; - } - - /** - * Finalizes the value of this node. - * - * @param mixed $value - * - * @return mixed The finalised value - * - * @throws UnsetKeyException - * @throws InvalidConfigurationException if the node doesn't have enough children - */ - protected function finalizeValue($value) - { - if (false === $value) { - throw new UnsetKeyException(sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value))); - } - - foreach ($this->children as $name => $child) { - if (!\array_key_exists($name, $value)) { - if ($child->isRequired()) { - $ex = new InvalidConfigurationException(sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath())); - $ex->setPath($this->getPath()); - - throw $ex; - } - - if ($child->hasDefaultValue()) { - $value[$name] = $child->getDefaultValue(); - } - - continue; - } - - if ($child->isDeprecated()) { - @trigger_error($child->getDeprecationMessage($name, $this->getPath()), E_USER_DEPRECATED); - } - - try { - $value[$name] = $child->finalize($value[$name]); - } catch (UnsetKeyException $e) { - unset($value[$name]); - } - } - - return $value; - } - - /** - * Validates the type of the value. - * - * @param mixed $value - * - * @throws InvalidTypeException - */ - protected function validateType($value) - { - if (!\is_array($value) && (!$this->allowFalse || false !== $value)) { - $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected array, but got %s', $this->getPath(), \gettype($value))); - if ($hint = $this->getInfo()) { - $ex->addHint($hint); - } - $ex->setPath($this->getPath()); - - throw $ex; - } - } - - /** - * Normalizes the value. - * - * @param mixed $value The value to normalize - * - * @return mixed The normalized value - * - * @throws InvalidConfigurationException - */ - protected function normalizeValue($value) - { - if (false === $value) { - return $value; - } - - $value = $this->remapXml($value); - - $normalized = []; - foreach ($value as $name => $val) { - if (isset($this->children[$name])) { - try { - $normalized[$name] = $this->children[$name]->normalize($val); - } catch (UnsetKeyException $e) { - } - unset($value[$name]); - } elseif (!$this->removeExtraKeys) { - $normalized[$name] = $val; - } - } - - // if extra fields are present, throw exception - if (\count($value) && !$this->ignoreExtraKeys) { - $proposals = array_keys($this->children); - sort($proposals); - $guesses = []; - - foreach (array_keys($value) as $subject) { - $minScore = INF; - foreach ($proposals as $proposal) { - $distance = levenshtein($subject, $proposal); - if ($distance <= $minScore && $distance < 3) { - $guesses[$proposal] = $distance; - $minScore = $distance; - } - } - } - - $msg = sprintf('Unrecognized option%s "%s" under "%s"', 1 === \count($value) ? '' : 's', implode(', ', array_keys($value)), $this->getPath()); - - if (\count($guesses)) { - asort($guesses); - $msg .= sprintf('. Did you mean "%s"?', implode('", "', array_keys($guesses))); - } else { - $msg .= sprintf('. Available option%s %s "%s".', 1 === \count($proposals) ? '' : 's', 1 === \count($proposals) ? 'is' : 'are', implode('", "', $proposals)); - } - - $ex = new InvalidConfigurationException($msg); - $ex->setPath($this->getPath()); - - throw $ex; - } - - return $normalized; - } - - /** - * Remaps multiple singular values to a single plural value. - * - * @return array The remapped values - */ - protected function remapXml(array $value) - { - foreach ($this->xmlRemappings as list($singular, $plural)) { - if (!isset($value[$singular])) { - continue; - } - - $value[$plural] = Processor::normalizeConfig($value, $singular, $plural); - unset($value[$singular]); - } - - return $value; - } - - /** - * Merges values together. - * - * @param mixed $leftSide The left side to merge - * @param mixed $rightSide The right side to merge - * - * @return mixed The merged values - * - * @throws InvalidConfigurationException - * @throws \RuntimeException - */ - protected function mergeValues($leftSide, $rightSide) - { - if (false === $rightSide) { - // if this is still false after the last config has been merged the - // finalization pass will take care of removing this key entirely - return false; - } - - if (false === $leftSide || !$this->performDeepMerging) { - return $rightSide; - } - - foreach ($rightSide as $k => $v) { - // no conflict - if (!\array_key_exists($k, $leftSide)) { - if (!$this->allowNewKeys) { - $ex = new InvalidConfigurationException(sprintf('You are not allowed to define new elements for path "%s". Please define all elements for this path in one config file. If you are trying to overwrite an element, make sure you redefine it with the same name.', $this->getPath())); - $ex->setPath($this->getPath()); - - throw $ex; - } - - $leftSide[$k] = $v; - continue; - } - - if (!isset($this->children[$k])) { - if (!$this->ignoreExtraKeys || $this->removeExtraKeys) { - throw new \RuntimeException('merge() expects a normalized config array.'); - } - - $leftSide[$k] = $v; - continue; - } - - $leftSide[$k] = $this->children[$k]->merge($leftSide[$k], $v); - } - - return $leftSide; - } - - /** - * {@inheritdoc} - */ - protected function allowPlaceholders(): bool - { - return false; - } -} diff --git a/vendor/symfony/config/Definition/BaseNode.php b/vendor/symfony/config/Definition/BaseNode.php deleted file mode 100644 index d721620..0000000 --- a/vendor/symfony/config/Definition/BaseNode.php +++ /dev/null @@ -1,543 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\Exception; -use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; -use Symfony\Component\Config\Definition\Exception\UnsetKeyException; - -/** - * The base node class. - * - * @author Johannes M. Schmitt - */ -abstract class BaseNode implements NodeInterface -{ - const DEFAULT_PATH_SEPARATOR = '.'; - - private static $placeholderUniquePrefix; - private static $placeholders = []; - - protected $name; - protected $parent; - protected $normalizationClosures = []; - protected $finalValidationClosures = []; - protected $allowOverwrite = true; - protected $required = false; - protected $deprecationMessage = null; - protected $equivalentValues = []; - protected $attributes = []; - protected $pathSeparator; - - private $handlingPlaceholder; - - /** - * @throws \InvalidArgumentException if the name contains a period - */ - public function __construct(?string $name, NodeInterface $parent = null, string $pathSeparator = self::DEFAULT_PATH_SEPARATOR) - { - if (false !== strpos($name = (string) $name, $pathSeparator)) { - throw new \InvalidArgumentException('The name must not contain "'.$pathSeparator.'".'); - } - - $this->name = $name; - $this->parent = $parent; - $this->pathSeparator = $pathSeparator; - } - - /** - * Register possible (dummy) values for a dynamic placeholder value. - * - * Matching configuration values will be processed with a provided value, one by one. After a provided value is - * successfully processed the configuration value is returned as is, thus preserving the placeholder. - * - * @internal - */ - public static function setPlaceholder(string $placeholder, array $values): void - { - if (!$values) { - throw new \InvalidArgumentException('At least one value must be provided.'); - } - - self::$placeholders[$placeholder] = $values; - } - - /** - * Sets a common prefix for dynamic placeholder values. - * - * Matching configuration values will be skipped from being processed and are returned as is, thus preserving the - * placeholder. An exact match provided by {@see setPlaceholder()} might take precedence. - * - * @internal - */ - public static function setPlaceholderUniquePrefix(string $prefix): void - { - self::$placeholderUniquePrefix = $prefix; - } - - /** - * Resets all current placeholders available. - * - * @internal - */ - public static function resetPlaceholders(): void - { - self::$placeholderUniquePrefix = null; - self::$placeholders = []; - } - - public function setAttribute(string $key, $value) - { - $this->attributes[$key] = $value; - } - - /** - * @return mixed - */ - public function getAttribute(string $key, $default = null) - { - return isset($this->attributes[$key]) ? $this->attributes[$key] : $default; - } - - /** - * @return bool - */ - public function hasAttribute(string $key) - { - return isset($this->attributes[$key]); - } - - /** - * @return array - */ - public function getAttributes() - { - return $this->attributes; - } - - public function setAttributes(array $attributes) - { - $this->attributes = $attributes; - } - - public function removeAttribute(string $key) - { - unset($this->attributes[$key]); - } - - /** - * Sets an info message. - */ - public function setInfo(string $info) - { - $this->setAttribute('info', $info); - } - - /** - * Returns info message. - * - * @return string|null The info text - */ - public function getInfo() - { - return $this->getAttribute('info'); - } - - /** - * Sets the example configuration for this node. - * - * @param string|array $example - */ - public function setExample($example) - { - $this->setAttribute('example', $example); - } - - /** - * Retrieves the example configuration for this node. - * - * @return string|array|null The example - */ - public function getExample() - { - return $this->getAttribute('example'); - } - - /** - * Adds an equivalent value. - * - * @param mixed $originalValue - * @param mixed $equivalentValue - */ - public function addEquivalentValue($originalValue, $equivalentValue) - { - $this->equivalentValues[] = [$originalValue, $equivalentValue]; - } - - /** - * Set this node as required. - * - * @param bool $boolean Required node - */ - public function setRequired(bool $boolean) - { - $this->required = $boolean; - } - - /** - * Sets this node as deprecated. - * - * You can use %node% and %path% placeholders in your message to display, - * respectively, the node name and its complete path. - */ - public function setDeprecated(?string $message) - { - $this->deprecationMessage = $message; - } - - /** - * Sets if this node can be overridden. - */ - public function setAllowOverwrite(bool $allow) - { - $this->allowOverwrite = $allow; - } - - /** - * Sets the closures used for normalization. - * - * @param \Closure[] $closures An array of Closures used for normalization - */ - public function setNormalizationClosures(array $closures) - { - $this->normalizationClosures = $closures; - } - - /** - * Sets the closures used for final validation. - * - * @param \Closure[] $closures An array of Closures used for final validation - */ - public function setFinalValidationClosures(array $closures) - { - $this->finalValidationClosures = $closures; - } - - /** - * {@inheritdoc} - */ - public function isRequired() - { - return $this->required; - } - - /** - * Checks if this node is deprecated. - * - * @return bool - */ - public function isDeprecated() - { - return null !== $this->deprecationMessage; - } - - /** - * Returns the deprecated message. - * - * @param string $node the configuration node name - * @param string $path the path of the node - * - * @return string - */ - public function getDeprecationMessage(string $node, string $path) - { - return strtr($this->deprecationMessage, ['%node%' => $node, '%path%' => $path]); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - /** - * {@inheritdoc} - */ - public function getPath() - { - if (null !== $this->parent) { - return $this->parent->getPath().$this->pathSeparator.$this->name; - } - - return $this->name; - } - - /** - * {@inheritdoc} - */ - final public function merge($leftSide, $rightSide) - { - if (!$this->allowOverwrite) { - throw new ForbiddenOverwriteException(sprintf('Configuration path "%s" cannot be overwritten. You have to define all options for this path, and any of its sub-paths in one configuration section.', $this->getPath())); - } - - if ($leftSide !== $leftPlaceholders = self::resolvePlaceholderValue($leftSide)) { - foreach ($leftPlaceholders as $leftPlaceholder) { - $this->handlingPlaceholder = $leftSide; - try { - $this->merge($leftPlaceholder, $rightSide); - } finally { - $this->handlingPlaceholder = null; - } - } - - return $rightSide; - } - - if ($rightSide !== $rightPlaceholders = self::resolvePlaceholderValue($rightSide)) { - foreach ($rightPlaceholders as $rightPlaceholder) { - $this->handlingPlaceholder = $rightSide; - try { - $this->merge($leftSide, $rightPlaceholder); - } finally { - $this->handlingPlaceholder = null; - } - } - - return $rightSide; - } - - $this->doValidateType($leftSide); - $this->doValidateType($rightSide); - - return $this->mergeValues($leftSide, $rightSide); - } - - /** - * {@inheritdoc} - */ - final public function normalize($value) - { - $value = $this->preNormalize($value); - - // run custom normalization closures - foreach ($this->normalizationClosures as $closure) { - $value = $closure($value); - } - - // resolve placeholder value - if ($value !== $placeholders = self::resolvePlaceholderValue($value)) { - foreach ($placeholders as $placeholder) { - $this->handlingPlaceholder = $value; - try { - $this->normalize($placeholder); - } finally { - $this->handlingPlaceholder = null; - } - } - - return $value; - } - - // replace value with their equivalent - foreach ($this->equivalentValues as $data) { - if ($data[0] === $value) { - $value = $data[1]; - } - } - - // validate type - $this->doValidateType($value); - - // normalize value - return $this->normalizeValue($value); - } - - /** - * Normalizes the value before any other normalization is applied. - * - * @param mixed $value - * - * @return mixed The normalized array value - */ - protected function preNormalize($value) - { - return $value; - } - - /** - * Returns parent node for this node. - * - * @return NodeInterface|null - */ - public function getParent() - { - return $this->parent; - } - - /** - * {@inheritdoc} - */ - final public function finalize($value) - { - if ($value !== $placeholders = self::resolvePlaceholderValue($value)) { - foreach ($placeholders as $placeholder) { - $this->handlingPlaceholder = $value; - try { - $this->finalize($placeholder); - } finally { - $this->handlingPlaceholder = null; - } - } - - return $value; - } - - $this->doValidateType($value); - - $value = $this->finalizeValue($value); - - // Perform validation on the final value if a closure has been set. - // The closure is also allowed to return another value. - foreach ($this->finalValidationClosures as $closure) { - try { - $value = $closure($value); - } catch (Exception $e) { - if ($e instanceof UnsetKeyException && null !== $this->handlingPlaceholder) { - continue; - } - - throw $e; - } catch (\Exception $e) { - throw new InvalidConfigurationException(sprintf('Invalid configuration for path "%s": %s', $this->getPath(), $e->getMessage()), $e->getCode(), $e); - } - } - - return $value; - } - - /** - * Validates the type of a Node. - * - * @param mixed $value The value to validate - * - * @throws InvalidTypeException when the value is invalid - */ - abstract protected function validateType($value); - - /** - * Normalizes the value. - * - * @param mixed $value The value to normalize - * - * @return mixed The normalized value - */ - abstract protected function normalizeValue($value); - - /** - * Merges two values together. - * - * @param mixed $leftSide - * @param mixed $rightSide - * - * @return mixed The merged value - */ - abstract protected function mergeValues($leftSide, $rightSide); - - /** - * Finalizes a value. - * - * @param mixed $value The value to finalize - * - * @return mixed The finalized value - */ - abstract protected function finalizeValue($value); - - /** - * Tests if placeholder values are allowed for this node. - */ - protected function allowPlaceholders(): bool - { - return true; - } - - /** - * Tests if a placeholder is being handled currently. - */ - protected function isHandlingPlaceholder(): bool - { - return null !== $this->handlingPlaceholder; - } - - /** - * Gets allowed dynamic types for this node. - */ - protected function getValidPlaceholderTypes(): array - { - return []; - } - - private static function resolvePlaceholderValue($value) - { - if (\is_string($value)) { - if (isset(self::$placeholders[$value])) { - return self::$placeholders[$value]; - } - - if (self::$placeholderUniquePrefix && 0 === strpos($value, self::$placeholderUniquePrefix)) { - return []; - } - } - - return $value; - } - - private function doValidateType($value): void - { - if (null !== $this->handlingPlaceholder && !$this->allowPlaceholders()) { - $e = new InvalidTypeException(sprintf('A dynamic value is not compatible with a "%s" node type at path "%s".', \get_class($this), $this->getPath())); - $e->setPath($this->getPath()); - - throw $e; - } - - if (null === $this->handlingPlaceholder || null === $value) { - $this->validateType($value); - - return; - } - - $knownTypes = array_keys(self::$placeholders[$this->handlingPlaceholder]); - $validTypes = $this->getValidPlaceholderTypes(); - - if ($validTypes && array_diff($knownTypes, $validTypes)) { - $e = new InvalidTypeException(sprintf( - 'Invalid type for path "%s". Expected %s, but got %s.', - $this->getPath(), - 1 === \count($validTypes) ? '"'.reset($validTypes).'"' : 'one of "'.implode('", "', $validTypes).'"', - 1 === \count($knownTypes) ? '"'.reset($knownTypes).'"' : 'one of "'.implode('", "', $knownTypes).'"' - )); - if ($hint = $this->getInfo()) { - $e->addHint($hint); - } - $e->setPath($this->getPath()); - - throw $e; - } - - $this->validateType($value); - } -} diff --git a/vendor/symfony/config/Definition/BooleanNode.php b/vendor/symfony/config/Definition/BooleanNode.php deleted file mode 100644 index c43c46f..0000000 --- a/vendor/symfony/config/Definition/BooleanNode.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; - -/** - * This node represents a Boolean value in the config tree. - * - * @author Johannes M. Schmitt - */ -class BooleanNode extends ScalarNode -{ - /** - * {@inheritdoc} - */ - protected function validateType($value) - { - if (!\is_bool($value)) { - $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected boolean, but got %s.', $this->getPath(), \gettype($value))); - if ($hint = $this->getInfo()) { - $ex->addHint($hint); - } - $ex->setPath($this->getPath()); - - throw $ex; - } - } - - /** - * {@inheritdoc} - */ - protected function isValueEmpty($value) - { - // a boolean value cannot be empty - return false; - } - - /** - * {@inheritdoc} - */ - protected function getValidPlaceholderTypes(): array - { - return ['bool']; - } -} diff --git a/vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php b/vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php deleted file mode 100644 index fdac03a..0000000 --- a/vendor/symfony/config/Definition/Builder/ArrayNodeDefinition.php +++ /dev/null @@ -1,546 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\ArrayNode; -use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; -use Symfony\Component\Config\Definition\PrototypedArrayNode; - -/** - * This class provides a fluent interface for defining an array node. - * - * @author Johannes M. Schmitt - */ -class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface -{ - protected $performDeepMerging = true; - protected $ignoreExtraKeys = false; - protected $removeExtraKeys = true; - protected $children = []; - protected $prototype; - protected $atLeastOne = false; - protected $allowNewKeys = true; - protected $key; - protected $removeKeyItem; - protected $addDefaults = false; - protected $addDefaultChildren = false; - protected $nodeBuilder; - protected $normalizeKeys = true; - - /** - * {@inheritdoc} - */ - public function __construct(?string $name, NodeParentInterface $parent = null) - { - parent::__construct($name, $parent); - - $this->nullEquivalent = []; - $this->trueEquivalent = []; - } - - /** - * {@inheritdoc} - */ - public function setBuilder(NodeBuilder $builder) - { - $this->nodeBuilder = $builder; - } - - /** - * {@inheritdoc} - */ - public function children() - { - return $this->getNodeBuilder(); - } - - /** - * Sets a prototype for child nodes. - * - * @return NodeDefinition - */ - public function prototype(string $type) - { - return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this); - } - - /** - * @return VariableNodeDefinition - */ - public function variablePrototype() - { - return $this->prototype('variable'); - } - - /** - * @return ScalarNodeDefinition - */ - public function scalarPrototype() - { - return $this->prototype('scalar'); - } - - /** - * @return BooleanNodeDefinition - */ - public function booleanPrototype() - { - return $this->prototype('boolean'); - } - - /** - * @return IntegerNodeDefinition - */ - public function integerPrototype() - { - return $this->prototype('integer'); - } - - /** - * @return FloatNodeDefinition - */ - public function floatPrototype() - { - return $this->prototype('float'); - } - - /** - * @return ArrayNodeDefinition - */ - public function arrayPrototype() - { - return $this->prototype('array'); - } - - /** - * @return EnumNodeDefinition - */ - public function enumPrototype() - { - return $this->prototype('enum'); - } - - /** - * Adds the default value if the node is not set in the configuration. - * - * This method is applicable to concrete nodes only (not to prototype nodes). - * If this function has been called and the node is not set during the finalization - * phase, it's default value will be derived from its children default values. - * - * @return $this - */ - public function addDefaultsIfNotSet() - { - $this->addDefaults = true; - - return $this; - } - - /** - * Adds children with a default value when none are defined. - * - * This method is applicable to prototype nodes only. - * - * @param int|string|array|null $children The number of children|The child name|The children names to be added - * - * @return $this - */ - public function addDefaultChildrenIfNoneSet($children = null) - { - $this->addDefaultChildren = $children; - - return $this; - } - - /** - * Requires the node to have at least one element. - * - * This method is applicable to prototype nodes only. - * - * @return $this - */ - public function requiresAtLeastOneElement() - { - $this->atLeastOne = true; - - return $this; - } - - /** - * Disallows adding news keys in a subsequent configuration. - * - * If used all keys have to be defined in the same configuration file. - * - * @return $this - */ - public function disallowNewKeysInSubsequentConfigs() - { - $this->allowNewKeys = false; - - return $this; - } - - /** - * Sets a normalization rule for XML configurations. - * - * @param string $singular The key to remap - * @param string|null $plural The plural of the key for irregular plurals - * - * @return $this - */ - public function fixXmlConfig(string $singular, string $plural = null) - { - $this->normalization()->remap($singular, $plural); - - return $this; - } - - /** - * Sets the attribute which value is to be used as key. - * - * This is useful when you have an indexed array that should be an - * associative array. You can select an item from within the array - * to be the key of the particular item. For example, if "id" is the - * "key", then: - * - * [ - * ['id' => 'my_name', 'foo' => 'bar'], - * ]; - * - * becomes - * - * [ - * 'my_name' => ['foo' => 'bar'], - * ]; - * - * If you'd like "'id' => 'my_name'" to still be present in the resulting - * array, then you can set the second argument of this method to false. - * - * This method is applicable to prototype nodes only. - * - * @param string $name The name of the key - * @param bool $removeKeyItem Whether or not the key item should be removed - * - * @return $this - */ - public function useAttributeAsKey(string $name, bool $removeKeyItem = true) - { - $this->key = $name; - $this->removeKeyItem = $removeKeyItem; - - return $this; - } - - /** - * Sets whether the node can be unset. - * - * @return $this - */ - public function canBeUnset(bool $allow = true) - { - $this->merge()->allowUnset($allow); - - return $this; - } - - /** - * Adds an "enabled" boolean to enable the current section. - * - * By default, the section is disabled. If any configuration is specified then - * the node will be automatically enabled: - * - * enableableArrayNode: {enabled: true, ...} # The config is enabled & default values get overridden - * enableableArrayNode: ~ # The config is enabled & use the default values - * enableableArrayNode: true # The config is enabled & use the default values - * enableableArrayNode: {other: value, ...} # The config is enabled & default values get overridden - * enableableArrayNode: {enabled: false, ...} # The config is disabled - * enableableArrayNode: false # The config is disabled - * - * @return $this - */ - public function canBeEnabled() - { - $this - ->addDefaultsIfNotSet() - ->treatFalseLike(['enabled' => false]) - ->treatTrueLike(['enabled' => true]) - ->treatNullLike(['enabled' => true]) - ->beforeNormalization() - ->ifArray() - ->then(function ($v) { - $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true; - - return $v; - }) - ->end() - ->children() - ->booleanNode('enabled') - ->defaultFalse() - ; - - return $this; - } - - /** - * Adds an "enabled" boolean to enable the current section. - * - * By default, the section is enabled. - * - * @return $this - */ - public function canBeDisabled() - { - $this - ->addDefaultsIfNotSet() - ->treatFalseLike(['enabled' => false]) - ->treatTrueLike(['enabled' => true]) - ->treatNullLike(['enabled' => true]) - ->children() - ->booleanNode('enabled') - ->defaultTrue() - ; - - return $this; - } - - /** - * Disables the deep merging of the node. - * - * @return $this - */ - public function performNoDeepMerging() - { - $this->performDeepMerging = false; - - return $this; - } - - /** - * Allows extra config keys to be specified under an array without - * throwing an exception. - * - * Those config values are ignored and removed from the resulting - * array. This should be used only in special cases where you want - * to send an entire configuration array through a special tree that - * processes only part of the array. - * - * @param bool $remove Whether to remove the extra keys - * - * @return $this - */ - public function ignoreExtraKeys(bool $remove = true) - { - $this->ignoreExtraKeys = true; - $this->removeExtraKeys = $remove; - - return $this; - } - - /** - * Sets whether to enable key normalization. - * - * @return $this - */ - public function normalizeKeys(bool $bool) - { - $this->normalizeKeys = $bool; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function append(NodeDefinition $node) - { - $this->children[$node->name] = $node->setParent($this); - - return $this; - } - - /** - * Returns a node builder to be used to add children and prototype. - * - * @return NodeBuilder The node builder - */ - protected function getNodeBuilder() - { - if (null === $this->nodeBuilder) { - $this->nodeBuilder = new NodeBuilder(); - } - - return $this->nodeBuilder->setParent($this); - } - - /** - * {@inheritdoc} - */ - protected function createNode() - { - if (null === $this->prototype) { - $node = new ArrayNode($this->name, $this->parent, $this->pathSeparator); - - $this->validateConcreteNode($node); - - $node->setAddIfNotSet($this->addDefaults); - - foreach ($this->children as $child) { - $child->parent = $node; - $node->addChild($child->getNode()); - } - } else { - $node = new PrototypedArrayNode($this->name, $this->parent, $this->pathSeparator); - - $this->validatePrototypeNode($node); - - if (null !== $this->key) { - $node->setKeyAttribute($this->key, $this->removeKeyItem); - } - - if (true === $this->atLeastOne || false === $this->allowEmptyValue) { - $node->setMinNumberOfElements(1); - } - - if ($this->default) { - if (!\is_array($this->defaultValue)) { - throw new \InvalidArgumentException(sprintf('%s: the default value of an array node has to be an array.', $node->getPath())); - } - - $node->setDefaultValue($this->defaultValue); - } - - if (false !== $this->addDefaultChildren) { - $node->setAddChildrenIfNoneSet($this->addDefaultChildren); - if ($this->prototype instanceof static && null === $this->prototype->prototype) { - $this->prototype->addDefaultsIfNotSet(); - } - } - - $this->prototype->parent = $node; - $node->setPrototype($this->prototype->getNode()); - } - - $node->setAllowNewKeys($this->allowNewKeys); - $node->addEquivalentValue(null, $this->nullEquivalent); - $node->addEquivalentValue(true, $this->trueEquivalent); - $node->addEquivalentValue(false, $this->falseEquivalent); - $node->setPerformDeepMerging($this->performDeepMerging); - $node->setRequired($this->required); - $node->setDeprecated($this->deprecationMessage); - $node->setIgnoreExtraKeys($this->ignoreExtraKeys, $this->removeExtraKeys); - $node->setNormalizeKeys($this->normalizeKeys); - - if (null !== $this->normalization) { - $node->setNormalizationClosures($this->normalization->before); - $node->setXmlRemappings($this->normalization->remappings); - } - - if (null !== $this->merge) { - $node->setAllowOverwrite($this->merge->allowOverwrite); - $node->setAllowFalse($this->merge->allowFalse); - } - - if (null !== $this->validation) { - $node->setFinalValidationClosures($this->validation->rules); - } - - return $node; - } - - /** - * Validate the configuration of a concrete node. - * - * @throws InvalidDefinitionException - */ - protected function validateConcreteNode(ArrayNode $node) - { - $path = $node->getPath(); - - if (null !== $this->key) { - throw new InvalidDefinitionException(sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s"', $path)); - } - - if (false === $this->allowEmptyValue) { - throw new InvalidDefinitionException(sprintf('->cannotBeEmpty() is not applicable to concrete nodes at path "%s"', $path)); - } - - if (true === $this->atLeastOne) { - throw new InvalidDefinitionException(sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s"', $path)); - } - - if ($this->default) { - throw new InvalidDefinitionException(sprintf('->defaultValue() is not applicable to concrete nodes at path "%s"', $path)); - } - - if (false !== $this->addDefaultChildren) { - throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s"', $path)); - } - } - - /** - * Validate the configuration of a prototype node. - * - * @throws InvalidDefinitionException - */ - protected function validatePrototypeNode(PrototypedArrayNode $node) - { - $path = $node->getPath(); - - if ($this->addDefaults) { - throw new InvalidDefinitionException(sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s"', $path)); - } - - if (false !== $this->addDefaultChildren) { - if ($this->default) { - throw new InvalidDefinitionException(sprintf('A default value and default children might not be used together at path "%s"', $path)); - } - - if (null !== $this->key && (null === $this->addDefaultChildren || \is_int($this->addDefaultChildren) && $this->addDefaultChildren > 0)) { - throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s"', $path)); - } - - if (null === $this->key && (\is_string($this->addDefaultChildren) || \is_array($this->addDefaultChildren))) { - throw new InvalidDefinitionException(sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s"', $path)); - } - } - } - - /** - * @return NodeDefinition[] - */ - public function getChildNodeDefinitions() - { - return $this->children; - } - - /** - * Finds a node defined by the given $nodePath. - * - * @param string $nodePath The path of the node to find. e.g "doctrine.orm.mappings" - */ - public function find(string $nodePath): NodeDefinition - { - $firstPathSegment = (false === $pathSeparatorPos = strpos($nodePath, $this->pathSeparator)) - ? $nodePath - : substr($nodePath, 0, $pathSeparatorPos); - - if (null === $node = ($this->children[$firstPathSegment] ?? null)) { - throw new \RuntimeException(sprintf('Node with name "%s" does not exist in the current node "%s".', $firstPathSegment, $this->name)); - } - - if (false === $pathSeparatorPos) { - return $node; - } - - return $node->find(substr($nodePath, $pathSeparatorPos + \strlen($this->pathSeparator))); - } -} diff --git a/vendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php b/vendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php deleted file mode 100644 index d193242..0000000 --- a/vendor/symfony/config/Definition/Builder/BooleanNodeDefinition.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\BooleanNode; -use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; - -/** - * This class provides a fluent interface for defining a node. - * - * @author Johannes M. Schmitt - */ -class BooleanNodeDefinition extends ScalarNodeDefinition -{ - /** - * {@inheritdoc} - */ - public function __construct(?string $name, NodeParentInterface $parent = null) - { - parent::__construct($name, $parent); - - $this->nullEquivalent = true; - } - - /** - * Instantiate a Node. - * - * @return BooleanNode The node - */ - protected function instantiateNode() - { - return new BooleanNode($this->name, $this->parent, $this->pathSeparator); - } - - /** - * {@inheritdoc} - * - * @throws InvalidDefinitionException - */ - public function cannotBeEmpty() - { - throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to BooleanNodeDefinition.'); - } -} diff --git a/vendor/symfony/config/Definition/Builder/BuilderAwareInterface.php b/vendor/symfony/config/Definition/Builder/BuilderAwareInterface.php deleted file mode 100644 index f30b873..0000000 --- a/vendor/symfony/config/Definition/Builder/BuilderAwareInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * An interface that can be implemented by nodes which build other nodes. - * - * @author Roland Franssen - */ -interface BuilderAwareInterface -{ - /** - * Sets a custom children builder. - */ - public function setBuilder(NodeBuilder $builder); -} diff --git a/vendor/symfony/config/Definition/Builder/EnumNodeDefinition.php b/vendor/symfony/config/Definition/Builder/EnumNodeDefinition.php deleted file mode 100644 index 9a9c096..0000000 --- a/vendor/symfony/config/Definition/Builder/EnumNodeDefinition.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\EnumNode; - -/** - * Enum Node Definition. - * - * @author Johannes M. Schmitt - */ -class EnumNodeDefinition extends ScalarNodeDefinition -{ - private $values; - - /** - * @return $this - */ - public function values(array $values) - { - $values = array_unique($values); - - if (empty($values)) { - throw new \InvalidArgumentException('->values() must be called with at least one value.'); - } - - $this->values = $values; - - return $this; - } - - /** - * Instantiate a Node. - * - * @return EnumNode The node - * - * @throws \RuntimeException - */ - protected function instantiateNode() - { - if (null === $this->values) { - throw new \RuntimeException('You must call ->values() on enum nodes.'); - } - - return new EnumNode($this->name, $this->parent, $this->values, $this->pathSeparator); - } -} diff --git a/vendor/symfony/config/Definition/Builder/ExprBuilder.php b/vendor/symfony/config/Definition/Builder/ExprBuilder.php deleted file mode 100644 index 4d918ce..0000000 --- a/vendor/symfony/config/Definition/Builder/ExprBuilder.php +++ /dev/null @@ -1,246 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\Exception\UnsetKeyException; - -/** - * This class builds an if expression. - * - * @author Johannes M. Schmitt - * @author Christophe Coevoet - */ -class ExprBuilder -{ - protected $node; - public $ifPart; - public $thenPart; - - public function __construct(NodeDefinition $node) - { - $this->node = $node; - } - - /** - * Marks the expression as being always used. - * - * @return $this - */ - public function always(\Closure $then = null) - { - $this->ifPart = function ($v) { return true; }; - - if (null !== $then) { - $this->thenPart = $then; - } - - return $this; - } - - /** - * Sets a closure to use as tests. - * - * The default one tests if the value is true. - * - * @return $this - */ - public function ifTrue(\Closure $closure = null) - { - if (null === $closure) { - $closure = function ($v) { return true === $v; }; - } - - $this->ifPart = $closure; - - return $this; - } - - /** - * Tests if the value is a string. - * - * @return $this - */ - public function ifString() - { - $this->ifPart = function ($v) { return \is_string($v); }; - - return $this; - } - - /** - * Tests if the value is null. - * - * @return $this - */ - public function ifNull() - { - $this->ifPart = function ($v) { return null === $v; }; - - return $this; - } - - /** - * Tests if the value is empty. - * - * @return ExprBuilder - */ - public function ifEmpty() - { - $this->ifPart = function ($v) { return empty($v); }; - - return $this; - } - - /** - * Tests if the value is an array. - * - * @return $this - */ - public function ifArray() - { - $this->ifPart = function ($v) { return \is_array($v); }; - - return $this; - } - - /** - * Tests if the value is in an array. - * - * @return $this - */ - public function ifInArray(array $array) - { - $this->ifPart = function ($v) use ($array) { return \in_array($v, $array, true); }; - - return $this; - } - - /** - * Tests if the value is not in an array. - * - * @return $this - */ - public function ifNotInArray(array $array) - { - $this->ifPart = function ($v) use ($array) { return !\in_array($v, $array, true); }; - - return $this; - } - - /** - * Transforms variables of any type into an array. - * - * @return $this - */ - public function castToArray() - { - $this->ifPart = function ($v) { return !\is_array($v); }; - $this->thenPart = function ($v) { return [$v]; }; - - return $this; - } - - /** - * Sets the closure to run if the test pass. - * - * @return $this - */ - public function then(\Closure $closure) - { - $this->thenPart = $closure; - - return $this; - } - - /** - * Sets a closure returning an empty array. - * - * @return $this - */ - public function thenEmptyArray() - { - $this->thenPart = function ($v) { return []; }; - - return $this; - } - - /** - * Sets a closure marking the value as invalid at processing time. - * - * if you want to add the value of the node in your message just use a %s placeholder. - * - * @return $this - * - * @throws \InvalidArgumentException - */ - public function thenInvalid(string $message) - { - $this->thenPart = function ($v) use ($message) { throw new \InvalidArgumentException(sprintf($message, json_encode($v))); }; - - return $this; - } - - /** - * Sets a closure unsetting this key of the array at processing time. - * - * @return $this - * - * @throws UnsetKeyException - */ - public function thenUnset() - { - $this->thenPart = function ($v) { throw new UnsetKeyException('Unsetting key'); }; - - return $this; - } - - /** - * Returns the related node. - * - * @return NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition - * - * @throws \RuntimeException - */ - public function end() - { - if (null === $this->ifPart) { - throw new \RuntimeException('You must specify an if part.'); - } - if (null === $this->thenPart) { - throw new \RuntimeException('You must specify a then part.'); - } - - return $this->node; - } - - /** - * Builds the expressions. - * - * @param ExprBuilder[] $expressions An array of ExprBuilder instances to build - * - * @return array - */ - public static function buildExpressions(array $expressions) - { - foreach ($expressions as $k => $expr) { - if ($expr instanceof self) { - $if = $expr->ifPart; - $then = $expr->thenPart; - $expressions[$k] = function ($v) use ($if, $then) { - return $if($v) ? $then($v) : $v; - }; - } - } - - return $expressions; - } -} diff --git a/vendor/symfony/config/Definition/Builder/FloatNodeDefinition.php b/vendor/symfony/config/Definition/Builder/FloatNodeDefinition.php deleted file mode 100644 index 7b74271..0000000 --- a/vendor/symfony/config/Definition/Builder/FloatNodeDefinition.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\FloatNode; - -/** - * This class provides a fluent interface for defining a float node. - * - * @author Jeanmonod David - */ -class FloatNodeDefinition extends NumericNodeDefinition -{ - /** - * Instantiates a Node. - * - * @return FloatNode The node - */ - protected function instantiateNode() - { - return new FloatNode($this->name, $this->parent, $this->min, $this->max, $this->pathSeparator); - } -} diff --git a/vendor/symfony/config/Definition/Builder/IntegerNodeDefinition.php b/vendor/symfony/config/Definition/Builder/IntegerNodeDefinition.php deleted file mode 100644 index 0472a98..0000000 --- a/vendor/symfony/config/Definition/Builder/IntegerNodeDefinition.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\IntegerNode; - -/** - * This class provides a fluent interface for defining an integer node. - * - * @author Jeanmonod David - */ -class IntegerNodeDefinition extends NumericNodeDefinition -{ - /** - * Instantiates a Node. - * - * @return IntegerNode The node - */ - protected function instantiateNode() - { - return new IntegerNode($this->name, $this->parent, $this->min, $this->max, $this->pathSeparator); - } -} diff --git a/vendor/symfony/config/Definition/Builder/MergeBuilder.php b/vendor/symfony/config/Definition/Builder/MergeBuilder.php deleted file mode 100644 index a88d49b..0000000 --- a/vendor/symfony/config/Definition/Builder/MergeBuilder.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * This class builds merge conditions. - * - * @author Johannes M. Schmitt - */ -class MergeBuilder -{ - protected $node; - public $allowFalse = false; - public $allowOverwrite = true; - - public function __construct(NodeDefinition $node) - { - $this->node = $node; - } - - /** - * Sets whether the node can be unset. - * - * @return $this - */ - public function allowUnset(bool $allow = true) - { - $this->allowFalse = $allow; - - return $this; - } - - /** - * Sets whether the node can be overwritten. - * - * @return $this - */ - public function denyOverwrite(bool $deny = true) - { - $this->allowOverwrite = !$deny; - - return $this; - } - - /** - * Returns the related node. - * - * @return NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition - */ - public function end() - { - return $this->node; - } -} diff --git a/vendor/symfony/config/Definition/Builder/NodeBuilder.php b/vendor/symfony/config/Definition/Builder/NodeBuilder.php deleted file mode 100644 index bab439b..0000000 --- a/vendor/symfony/config/Definition/Builder/NodeBuilder.php +++ /dev/null @@ -1,219 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * This class provides a fluent interface for building a node. - * - * @author Johannes M. Schmitt - */ -class NodeBuilder implements NodeParentInterface -{ - protected $parent; - protected $nodeMapping; - - public function __construct() - { - $this->nodeMapping = [ - 'variable' => VariableNodeDefinition::class, - 'scalar' => ScalarNodeDefinition::class, - 'boolean' => BooleanNodeDefinition::class, - 'integer' => IntegerNodeDefinition::class, - 'float' => FloatNodeDefinition::class, - 'array' => ArrayNodeDefinition::class, - 'enum' => EnumNodeDefinition::class, - ]; - } - - /** - * Set the parent node. - * - * @return $this - */ - public function setParent(ParentNodeDefinitionInterface $parent = null) - { - $this->parent = $parent; - - return $this; - } - - /** - * Creates a child array node. - * - * @return ArrayNodeDefinition The child node - */ - public function arrayNode(string $name) - { - return $this->node($name, 'array'); - } - - /** - * Creates a child scalar node. - * - * @return ScalarNodeDefinition The child node - */ - public function scalarNode(string $name) - { - return $this->node($name, 'scalar'); - } - - /** - * Creates a child Boolean node. - * - * @return BooleanNodeDefinition The child node - */ - public function booleanNode(string $name) - { - return $this->node($name, 'boolean'); - } - - /** - * Creates a child integer node. - * - * @return IntegerNodeDefinition The child node - */ - public function integerNode(string $name) - { - return $this->node($name, 'integer'); - } - - /** - * Creates a child float node. - * - * @return FloatNodeDefinition The child node - */ - public function floatNode(string $name) - { - return $this->node($name, 'float'); - } - - /** - * Creates a child EnumNode. - * - * @return EnumNodeDefinition - */ - public function enumNode(string $name) - { - return $this->node($name, 'enum'); - } - - /** - * Creates a child variable node. - * - * @return VariableNodeDefinition The builder of the child node - */ - public function variableNode(string $name) - { - return $this->node($name, 'variable'); - } - - /** - * Returns the parent node. - * - * @return NodeDefinition&ParentNodeDefinitionInterface The parent node - */ - public function end() - { - return $this->parent; - } - - /** - * Creates a child node. - * - * @return NodeDefinition The child node - * - * @throws \RuntimeException When the node type is not registered - * @throws \RuntimeException When the node class is not found - */ - public function node(?string $name, string $type) - { - $class = $this->getNodeClass($type); - - $node = new $class($name); - - $this->append($node); - - return $node; - } - - /** - * Appends a node definition. - * - * Usage: - * - * $node = new ArrayNodeDefinition('name') - * ->children() - * ->scalarNode('foo')->end() - * ->scalarNode('baz')->end() - * ->append($this->getBarNodeDefinition()) - * ->end() - * ; - * - * @return $this - */ - public function append(NodeDefinition $node) - { - if ($node instanceof BuilderAwareInterface) { - $builder = clone $this; - $builder->setParent(null); - $node->setBuilder($builder); - } - - if (null !== $this->parent) { - $this->parent->append($node); - // Make this builder the node parent to allow for a fluid interface - $node->setParent($this); - } - - return $this; - } - - /** - * Adds or overrides a node Type. - * - * @param string $type The name of the type - * @param string $class The fully qualified name the node definition class - * - * @return $this - */ - public function setNodeClass(string $type, string $class) - { - $this->nodeMapping[strtolower($type)] = $class; - - return $this; - } - - /** - * Returns the class name of the node definition. - * - * @return string The node definition class name - * - * @throws \RuntimeException When the node type is not registered - * @throws \RuntimeException When the node class is not found - */ - protected function getNodeClass(string $type) - { - $type = strtolower($type); - - if (!isset($this->nodeMapping[$type])) { - throw new \RuntimeException(sprintf('The node type "%s" is not registered.', $type)); - } - - $class = $this->nodeMapping[$type]; - - if (!class_exists($class)) { - throw new \RuntimeException(sprintf('The node class "%s" does not exist.', $class)); - } - - return $class; - } -} diff --git a/vendor/symfony/config/Definition/Builder/NodeDefinition.php b/vendor/symfony/config/Definition/Builder/NodeDefinition.php deleted file mode 100644 index 3651990..0000000 --- a/vendor/symfony/config/Definition/Builder/NodeDefinition.php +++ /dev/null @@ -1,362 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\BaseNode; -use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; -use Symfony\Component\Config\Definition\NodeInterface; - -/** - * This class provides a fluent interface for defining a node. - * - * @author Johannes M. Schmitt - */ -abstract class NodeDefinition implements NodeParentInterface -{ - protected $name; - protected $normalization; - protected $validation; - protected $defaultValue; - protected $default = false; - protected $required = false; - protected $deprecationMessage = null; - protected $merge; - protected $allowEmptyValue = true; - protected $nullEquivalent; - protected $trueEquivalent = true; - protected $falseEquivalent = false; - protected $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR; - protected $parent; - protected $attributes = []; - - public function __construct(?string $name, NodeParentInterface $parent = null) - { - $this->parent = $parent; - $this->name = $name; - } - - /** - * Sets the parent node. - * - * @return $this - */ - public function setParent(NodeParentInterface $parent) - { - $this->parent = $parent; - - return $this; - } - - /** - * Sets info message. - * - * @return $this - */ - public function info(string $info) - { - return $this->attribute('info', $info); - } - - /** - * Sets example configuration. - * - * @param string|array $example - * - * @return $this - */ - public function example($example) - { - return $this->attribute('example', $example); - } - - /** - * Sets an attribute on the node. - * - * @param mixed $value - * - * @return $this - */ - public function attribute(string $key, $value) - { - $this->attributes[$key] = $value; - - return $this; - } - - /** - * Returns the parent node. - * - * @return NodeParentInterface|NodeBuilder|NodeDefinition|ArrayNodeDefinition|VariableNodeDefinition|null The builder of the parent node - */ - public function end() - { - return $this->parent; - } - - /** - * Creates the node. - * - * @param bool $forceRootNode Whether to force this node as the root node - * - * @return NodeInterface - */ - public function getNode(bool $forceRootNode = false) - { - if ($forceRootNode) { - $this->parent = null; - } - - if (null !== $this->normalization) { - $this->normalization->before = ExprBuilder::buildExpressions($this->normalization->before); - } - - if (null !== $this->validation) { - $this->validation->rules = ExprBuilder::buildExpressions($this->validation->rules); - } - - $node = $this->createNode(); - $node->setAttributes($this->attributes); - - return $node; - } - - /** - * Sets the default value. - * - * @param mixed $value The default value - * - * @return $this - */ - public function defaultValue($value) - { - $this->default = true; - $this->defaultValue = $value; - - return $this; - } - - /** - * Sets the node as required. - * - * @return $this - */ - public function isRequired() - { - $this->required = true; - - return $this; - } - - /** - * Sets the node as deprecated. - * - * You can use %node% and %path% placeholders in your message to display, - * respectively, the node name and its complete path. - * - * @return $this - */ - public function setDeprecated(string $message = 'The child node "%node%" at path "%path%" is deprecated.') - { - $this->deprecationMessage = $message; - - return $this; - } - - /** - * Sets the equivalent value used when the node contains null. - * - * @param mixed $value - * - * @return $this - */ - public function treatNullLike($value) - { - $this->nullEquivalent = $value; - - return $this; - } - - /** - * Sets the equivalent value used when the node contains true. - * - * @param mixed $value - * - * @return $this - */ - public function treatTrueLike($value) - { - $this->trueEquivalent = $value; - - return $this; - } - - /** - * Sets the equivalent value used when the node contains false. - * - * @param mixed $value - * - * @return $this - */ - public function treatFalseLike($value) - { - $this->falseEquivalent = $value; - - return $this; - } - - /** - * Sets null as the default value. - * - * @return $this - */ - public function defaultNull() - { - return $this->defaultValue(null); - } - - /** - * Sets true as the default value. - * - * @return $this - */ - public function defaultTrue() - { - return $this->defaultValue(true); - } - - /** - * Sets false as the default value. - * - * @return $this - */ - public function defaultFalse() - { - return $this->defaultValue(false); - } - - /** - * Sets an expression to run before the normalization. - * - * @return ExprBuilder - */ - public function beforeNormalization() - { - return $this->normalization()->before(); - } - - /** - * Denies the node value being empty. - * - * @return $this - */ - public function cannotBeEmpty() - { - $this->allowEmptyValue = false; - - return $this; - } - - /** - * Sets an expression to run for the validation. - * - * The expression receives the value of the node and must return it. It can - * modify it. - * An exception should be thrown when the node is not valid. - * - * @return ExprBuilder - */ - public function validate() - { - return $this->validation()->rule(); - } - - /** - * Sets whether the node can be overwritten. - * - * @return $this - */ - public function cannotBeOverwritten(bool $deny = true) - { - $this->merge()->denyOverwrite($deny); - - return $this; - } - - /** - * Gets the builder for validation rules. - * - * @return ValidationBuilder - */ - protected function validation() - { - if (null === $this->validation) { - $this->validation = new ValidationBuilder($this); - } - - return $this->validation; - } - - /** - * Gets the builder for merging rules. - * - * @return MergeBuilder - */ - protected function merge() - { - if (null === $this->merge) { - $this->merge = new MergeBuilder($this); - } - - return $this->merge; - } - - /** - * Gets the builder for normalization rules. - * - * @return NormalizationBuilder - */ - protected function normalization() - { - if (null === $this->normalization) { - $this->normalization = new NormalizationBuilder($this); - } - - return $this->normalization; - } - - /** - * Instantiate and configure the node according to this definition. - * - * @return NodeInterface The node instance - * - * @throws InvalidDefinitionException When the definition is invalid - */ - abstract protected function createNode(); - - /** - * Set PathSeparator to use. - * - * @return $this - */ - public function setPathSeparator(string $separator) - { - if ($this instanceof ParentNodeDefinitionInterface) { - foreach ($this->getChildNodeDefinitions() as $child) { - $child->setPathSeparator($separator); - } - } - - $this->pathSeparator = $separator; - - return $this; - } -} diff --git a/vendor/symfony/config/Definition/Builder/NodeParentInterface.php b/vendor/symfony/config/Definition/Builder/NodeParentInterface.php deleted file mode 100644 index 305e993..0000000 --- a/vendor/symfony/config/Definition/Builder/NodeParentInterface.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * An interface that must be implemented by all node parents. - * - * @author Victor Berchet - */ -interface NodeParentInterface -{ -} diff --git a/vendor/symfony/config/Definition/Builder/NormalizationBuilder.php b/vendor/symfony/config/Definition/Builder/NormalizationBuilder.php deleted file mode 100644 index 06cbbd4..0000000 --- a/vendor/symfony/config/Definition/Builder/NormalizationBuilder.php +++ /dev/null @@ -1,60 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * This class builds normalization conditions. - * - * @author Johannes M. Schmitt - */ -class NormalizationBuilder -{ - protected $node; - public $before = []; - public $remappings = []; - - public function __construct(NodeDefinition $node) - { - $this->node = $node; - } - - /** - * Registers a key to remap to its plural form. - * - * @param string $key The key to remap - * @param string|null $plural The plural of the key in case of irregular plural - * - * @return $this - */ - public function remap(string $key, string $plural = null) - { - $this->remappings[] = [$key, null === $plural ? $key.'s' : $plural]; - - return $this; - } - - /** - * Registers a closure to run before the normalization or an expression builder to build it if null is provided. - * - * @return ExprBuilder|$this - */ - public function before(\Closure $closure = null) - { - if (null !== $closure) { - $this->before[] = $closure; - - return $this; - } - - return $this->before[] = new ExprBuilder($this->node); - } -} diff --git a/vendor/symfony/config/Definition/Builder/NumericNodeDefinition.php b/vendor/symfony/config/Definition/Builder/NumericNodeDefinition.php deleted file mode 100644 index 0d0207c..0000000 --- a/vendor/symfony/config/Definition/Builder/NumericNodeDefinition.php +++ /dev/null @@ -1,73 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; - -/** - * Abstract class that contains common code of integer and float node definitions. - * - * @author David Jeanmonod - */ -abstract class NumericNodeDefinition extends ScalarNodeDefinition -{ - protected $min; - protected $max; - - /** - * Ensures that the value is smaller than the given reference. - * - * @param mixed $max - * - * @return $this - * - * @throws \InvalidArgumentException when the constraint is inconsistent - */ - public function max($max) - { - if (isset($this->min) && $this->min > $max) { - throw new \InvalidArgumentException(sprintf('You cannot define a max(%s) as you already have a min(%s)', $max, $this->min)); - } - $this->max = $max; - - return $this; - } - - /** - * Ensures that the value is bigger than the given reference. - * - * @param mixed $min - * - * @return $this - * - * @throws \InvalidArgumentException when the constraint is inconsistent - */ - public function min($min) - { - if (isset($this->max) && $this->max < $min) { - throw new \InvalidArgumentException(sprintf('You cannot define a min(%s) as you already have a max(%s)', $min, $this->max)); - } - $this->min = $min; - - return $this; - } - - /** - * {@inheritdoc} - * - * @throws InvalidDefinitionException - */ - public function cannotBeEmpty() - { - throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to NumericNodeDefinition.'); - } -} diff --git a/vendor/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php b/vendor/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php deleted file mode 100644 index 449b91a..0000000 --- a/vendor/symfony/config/Definition/Builder/ParentNodeDefinitionInterface.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * An interface that must be implemented by nodes which can have children. - * - * @author Victor Berchet - */ -interface ParentNodeDefinitionInterface extends BuilderAwareInterface -{ - /** - * Returns a builder to add children nodes. - * - * @return NodeBuilder - */ - public function children(); - - /** - * Appends a node definition. - * - * Usage: - * - * $node = $parentNode - * ->children() - * ->scalarNode('foo')->end() - * ->scalarNode('baz')->end() - * ->append($this->getBarNodeDefinition()) - * ->end() - * ; - * - * @return $this - */ - public function append(NodeDefinition $node); - - /** - * Gets the child node definitions. - * - * @return NodeDefinition[] - */ - public function getChildNodeDefinitions(); -} diff --git a/vendor/symfony/config/Definition/Builder/ScalarNodeDefinition.php b/vendor/symfony/config/Definition/Builder/ScalarNodeDefinition.php deleted file mode 100644 index 428f612..0000000 --- a/vendor/symfony/config/Definition/Builder/ScalarNodeDefinition.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\ScalarNode; - -/** - * This class provides a fluent interface for defining a node. - * - * @author Johannes M. Schmitt - */ -class ScalarNodeDefinition extends VariableNodeDefinition -{ - /** - * Instantiate a Node. - * - * @return ScalarNode The node - */ - protected function instantiateNode() - { - return new ScalarNode($this->name, $this->parent, $this->pathSeparator); - } -} diff --git a/vendor/symfony/config/Definition/Builder/TreeBuilder.php b/vendor/symfony/config/Definition/Builder/TreeBuilder.php deleted file mode 100644 index 13a18db..0000000 --- a/vendor/symfony/config/Definition/Builder/TreeBuilder.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\NodeInterface; - -/** - * This is the entry class for building a config tree. - * - * @author Johannes M. Schmitt - */ -class TreeBuilder implements NodeParentInterface -{ - protected $tree; - protected $root; - - public function __construct(string $name, string $type = 'array', NodeBuilder $builder = null) - { - $builder = $builder ?: new NodeBuilder(); - $this->root = $builder->node($name, $type)->setParent($this); - } - - /** - * @return NodeDefinition|ArrayNodeDefinition The root node (as an ArrayNodeDefinition when the type is 'array') - */ - public function getRootNode(): NodeDefinition - { - return $this->root; - } - - /** - * Builds the tree. - * - * @return NodeInterface - * - * @throws \RuntimeException - */ - public function buildTree() - { - if (null !== $this->tree) { - return $this->tree; - } - - return $this->tree = $this->root->getNode(true); - } - - public function setPathSeparator(string $separator) - { - // unset last built as changing path separator changes all nodes - $this->tree = null; - - $this->root->setPathSeparator($separator); - } -} diff --git a/vendor/symfony/config/Definition/Builder/ValidationBuilder.php b/vendor/symfony/config/Definition/Builder/ValidationBuilder.php deleted file mode 100644 index 4efc726..0000000 --- a/vendor/symfony/config/Definition/Builder/ValidationBuilder.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -/** - * This class builds validation conditions. - * - * @author Christophe Coevoet - */ -class ValidationBuilder -{ - protected $node; - public $rules = []; - - public function __construct(NodeDefinition $node) - { - $this->node = $node; - } - - /** - * Registers a closure to run as normalization or an expression builder to build it if null is provided. - * - * @return ExprBuilder|$this - */ - public function rule(\Closure $closure = null) - { - if (null !== $closure) { - $this->rules[] = $closure; - - return $this; - } - - return $this->rules[] = new ExprBuilder($this->node); - } -} diff --git a/vendor/symfony/config/Definition/Builder/VariableNodeDefinition.php b/vendor/symfony/config/Definition/Builder/VariableNodeDefinition.php deleted file mode 100644 index 39a564f..0000000 --- a/vendor/symfony/config/Definition/Builder/VariableNodeDefinition.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Builder; - -use Symfony\Component\Config\Definition\VariableNode; - -/** - * This class provides a fluent interface for defining a node. - * - * @author Johannes M. Schmitt - */ -class VariableNodeDefinition extends NodeDefinition -{ - /** - * Instantiate a Node. - * - * @return VariableNode The node - */ - protected function instantiateNode() - { - return new VariableNode($this->name, $this->parent, $this->pathSeparator); - } - - /** - * {@inheritdoc} - */ - protected function createNode() - { - $node = $this->instantiateNode(); - - if (null !== $this->normalization) { - $node->setNormalizationClosures($this->normalization->before); - } - - if (null !== $this->merge) { - $node->setAllowOverwrite($this->merge->allowOverwrite); - } - - if (true === $this->default) { - $node->setDefaultValue($this->defaultValue); - } - - $node->setAllowEmptyValue($this->allowEmptyValue); - $node->addEquivalentValue(null, $this->nullEquivalent); - $node->addEquivalentValue(true, $this->trueEquivalent); - $node->addEquivalentValue(false, $this->falseEquivalent); - $node->setRequired($this->required); - $node->setDeprecated($this->deprecationMessage); - - if (null !== $this->validation) { - $node->setFinalValidationClosures($this->validation->rules); - } - - return $node; - } -} diff --git a/vendor/symfony/config/Definition/ConfigurationInterface.php b/vendor/symfony/config/Definition/ConfigurationInterface.php deleted file mode 100644 index d6456ed..0000000 --- a/vendor/symfony/config/Definition/ConfigurationInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -/** - * Configuration interface. - * - * @author Victor Berchet - */ -interface ConfigurationInterface -{ - /** - * Generates the configuration tree builder. - * - * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder - */ - public function getConfigTreeBuilder(); -} diff --git a/vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.php b/vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.php deleted file mode 100644 index 32f32e0..0000000 --- a/vendor/symfony/config/Definition/Dumper/XmlReferenceDumper.php +++ /dev/null @@ -1,302 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Dumper; - -use Symfony\Component\Config\Definition\ArrayNode; -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\EnumNode; -use Symfony\Component\Config\Definition\NodeInterface; -use Symfony\Component\Config\Definition\PrototypedArrayNode; - -/** - * Dumps a XML reference configuration for the given configuration/node instance. - * - * @author Wouter J - */ -class XmlReferenceDumper -{ - private $reference; - - public function dump(ConfigurationInterface $configuration, string $namespace = null) - { - return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree(), $namespace); - } - - public function dumpNode(NodeInterface $node, string $namespace = null) - { - $this->reference = ''; - $this->writeNode($node, 0, true, $namespace); - $ref = $this->reference; - $this->reference = null; - - return $ref; - } - - private function writeNode(NodeInterface $node, int $depth = 0, bool $root = false, string $namespace = null) - { - $rootName = ($root ? 'config' : $node->getName()); - $rootNamespace = ($namespace ?: ($root ? 'http://example.org/schema/dic/'.$node->getName() : null)); - - // xml remapping - if ($node->getParent()) { - $remapping = array_filter($node->getParent()->getXmlRemappings(), function ($mapping) use ($rootName) { - return $rootName === $mapping[1]; - }); - - if (\count($remapping)) { - list($singular) = current($remapping); - $rootName = $singular; - } - } - $rootName = str_replace('_', '-', $rootName); - - $rootAttributes = []; - $rootAttributeComments = []; - $rootChildren = []; - $rootComments = []; - - if ($node instanceof ArrayNode) { - $children = $node->getChildren(); - - // comments about the root node - if ($rootInfo = $node->getInfo()) { - $rootComments[] = $rootInfo; - } - - if ($rootNamespace) { - $rootComments[] = 'Namespace: '.$rootNamespace; - } - - // render prototyped nodes - if ($node instanceof PrototypedArrayNode) { - $prototype = $node->getPrototype(); - - $info = 'prototype'; - if (null !== $prototype->getInfo()) { - $info .= ': '.$prototype->getInfo(); - } - array_unshift($rootComments, $info); - - if ($key = $node->getKeyAttribute()) { - $rootAttributes[$key] = str_replace('-', ' ', $rootName).' '.$key; - } - - if ($prototype instanceof PrototypedArrayNode) { - $prototype->setName($key); - $children = [$key => $prototype]; - } elseif ($prototype instanceof ArrayNode) { - $children = $prototype->getChildren(); - } else { - if ($prototype->hasDefaultValue()) { - $prototypeValue = $prototype->getDefaultValue(); - } else { - switch (\get_class($prototype)) { - case 'Symfony\Component\Config\Definition\ScalarNode': - $prototypeValue = 'scalar value'; - break; - - case 'Symfony\Component\Config\Definition\FloatNode': - case 'Symfony\Component\Config\Definition\IntegerNode': - $prototypeValue = 'numeric value'; - break; - - case 'Symfony\Component\Config\Definition\BooleanNode': - $prototypeValue = 'true|false'; - break; - - case 'Symfony\Component\Config\Definition\EnumNode': - $prototypeValue = implode('|', array_map('json_encode', $prototype->getValues())); - break; - - default: - $prototypeValue = 'value'; - } - } - } - } - - // get attributes and elements - foreach ($children as $child) { - if (!$child instanceof ArrayNode) { - // get attributes - - // metadata - $name = str_replace('_', '-', $child->getName()); - $value = '%%%%not_defined%%%%'; // use a string which isn't used in the normal world - - // comments - $comments = []; - if ($info = $child->getInfo()) { - $comments[] = $info; - } - - if ($example = $child->getExample()) { - $comments[] = 'Example: '.$example; - } - - if ($child->isRequired()) { - $comments[] = 'Required'; - } - - if ($child->isDeprecated()) { - $comments[] = sprintf('Deprecated (%s)', $child->getDeprecationMessage($child->getName(), $node->getPath())); - } - - if ($child instanceof EnumNode) { - $comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues())); - } - - if (\count($comments)) { - $rootAttributeComments[$name] = implode(";\n", $comments); - } - - // default values - if ($child->hasDefaultValue()) { - $value = $child->getDefaultValue(); - } - - // append attribute - $rootAttributes[$name] = $value; - } else { - // get elements - $rootChildren[] = $child; - } - } - } - - // render comments - - // root node comment - if (\count($rootComments)) { - foreach ($rootComments as $comment) { - $this->writeLine('', $depth); - } - } - - // attribute comments - if (\count($rootAttributeComments)) { - foreach ($rootAttributeComments as $attrName => $comment) { - $commentDepth = $depth + 4 + \strlen($attrName) + 2; - $commentLines = explode("\n", $comment); - $multiline = (\count($commentLines) > 1); - $comment = implode(PHP_EOL.str_repeat(' ', $commentDepth), $commentLines); - - if ($multiline) { - $this->writeLine('', $depth); - } else { - $this->writeLine('', $depth); - } - } - } - - // render start tag + attributes - $rootIsVariablePrototype = isset($prototypeValue); - $rootIsEmptyTag = (0 === \count($rootChildren) && !$rootIsVariablePrototype); - $rootOpenTag = '<'.$rootName; - if (1 >= ($attributesCount = \count($rootAttributes))) { - if (1 === $attributesCount) { - $rootOpenTag .= sprintf(' %s="%s"', current(array_keys($rootAttributes)), $this->writeValue(current($rootAttributes))); - } - - $rootOpenTag .= $rootIsEmptyTag ? ' />' : '>'; - - if ($rootIsVariablePrototype) { - $rootOpenTag .= $prototypeValue.''; - } - - $this->writeLine($rootOpenTag, $depth); - } else { - $this->writeLine($rootOpenTag, $depth); - - $i = 1; - - foreach ($rootAttributes as $attrName => $attrValue) { - $attr = sprintf('%s="%s"', $attrName, $this->writeValue($attrValue)); - - $this->writeLine($attr, $depth + 4); - - if ($attributesCount === $i++) { - $this->writeLine($rootIsEmptyTag ? '/>' : '>', $depth); - - if ($rootIsVariablePrototype) { - $rootOpenTag .= $prototypeValue.''; - } - } - } - } - - // render children tags - foreach ($rootChildren as $child) { - $this->writeLine(''); - $this->writeNode($child, $depth + 4); - } - - // render end tag - if (!$rootIsEmptyTag && !$rootIsVariablePrototype) { - $this->writeLine(''); - - $rootEndTag = ''; - $this->writeLine($rootEndTag, $depth); - } - } - - /** - * Outputs a single config reference line. - */ - private function writeLine(string $text, int $indent = 0) - { - $indent = \strlen($text) + $indent; - $format = '%'.$indent.'s'; - - $this->reference .= sprintf($format, $text).PHP_EOL; - } - - /** - * Renders the string conversion of the value. - * - * @param mixed $value - */ - private function writeValue($value): string - { - if ('%%%%not_defined%%%%' === $value) { - return ''; - } - - if (\is_string($value) || is_numeric($value)) { - return $value; - } - - if (false === $value) { - return 'false'; - } - - if (true === $value) { - return 'true'; - } - - if (null === $value) { - return 'null'; - } - - if (empty($value)) { - return ''; - } - - if (\is_array($value)) { - return implode(',', $value); - } - - return ''; - } -} diff --git a/vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.php b/vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.php deleted file mode 100644 index 757963d..0000000 --- a/vendor/symfony/config/Definition/Dumper/YamlReferenceDumper.php +++ /dev/null @@ -1,242 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Dumper; - -use Symfony\Component\Config\Definition\ArrayNode; -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\EnumNode; -use Symfony\Component\Config\Definition\NodeInterface; -use Symfony\Component\Config\Definition\PrototypedArrayNode; -use Symfony\Component\Config\Definition\ScalarNode; -use Symfony\Component\Yaml\Inline; - -/** - * Dumps a Yaml reference configuration for the given configuration/node instance. - * - * @author Kevin Bond - */ -class YamlReferenceDumper -{ - private $reference; - - public function dump(ConfigurationInterface $configuration) - { - return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree()); - } - - public function dumpAtPath(ConfigurationInterface $configuration, string $path) - { - $rootNode = $node = $configuration->getConfigTreeBuilder()->buildTree(); - - foreach (explode('.', $path) as $step) { - if (!$node instanceof ArrayNode) { - throw new \UnexpectedValueException(sprintf('Unable to find node at path "%s.%s"', $rootNode->getName(), $path)); - } - - /** @var NodeInterface[] $children */ - $children = $node instanceof PrototypedArrayNode ? $this->getPrototypeChildren($node) : $node->getChildren(); - - foreach ($children as $child) { - if ($child->getName() === $step) { - $node = $child; - - continue 2; - } - } - - throw new \UnexpectedValueException(sprintf('Unable to find node at path "%s.%s"', $rootNode->getName(), $path)); - } - - return $this->dumpNode($node); - } - - public function dumpNode(NodeInterface $node) - { - $this->reference = ''; - $this->writeNode($node); - $ref = $this->reference; - $this->reference = null; - - return $ref; - } - - private function writeNode(NodeInterface $node, NodeInterface $parentNode = null, int $depth = 0, bool $prototypedArray = false) - { - $comments = []; - $default = ''; - $defaultArray = null; - $children = null; - $example = $node->getExample(); - - // defaults - if ($node instanceof ArrayNode) { - $children = $node->getChildren(); - - if ($node instanceof PrototypedArrayNode) { - $children = $this->getPrototypeChildren($node); - } - - if (!$children) { - if ($node->hasDefaultValue() && \count($defaultArray = $node->getDefaultValue())) { - $default = ''; - } elseif (!\is_array($example)) { - $default = '[]'; - } - } - } elseif ($node instanceof EnumNode) { - $comments[] = 'One of '.implode('; ', array_map('json_encode', $node->getValues())); - $default = $node->hasDefaultValue() ? Inline::dump($node->getDefaultValue()) : '~'; - } else { - $default = '~'; - - if ($node->hasDefaultValue()) { - $default = $node->getDefaultValue(); - - if (\is_array($default)) { - if (\count($defaultArray = $node->getDefaultValue())) { - $default = ''; - } elseif (!\is_array($example)) { - $default = '[]'; - } - } else { - $default = Inline::dump($default); - } - } - } - - // required? - if ($node->isRequired()) { - $comments[] = 'Required'; - } - - // deprecated? - if ($node->isDeprecated()) { - $comments[] = sprintf('Deprecated (%s)', $node->getDeprecationMessage($node->getName(), $parentNode ? $parentNode->getPath() : $node->getPath())); - } - - // example - if ($example && !\is_array($example)) { - $comments[] = 'Example: '.$example; - } - - $default = '' != (string) $default ? ' '.$default : ''; - $comments = \count($comments) ? '# '.implode(', ', $comments) : ''; - - $key = $prototypedArray ? '-' : $node->getName().':'; - $text = rtrim(sprintf('%-21s%s %s', $key, $default, $comments), ' '); - - if ($info = $node->getInfo()) { - $this->writeLine(''); - // indenting multi-line info - $info = str_replace("\n", sprintf("\n%".($depth * 4).'s# ', ' '), $info); - $this->writeLine('# '.$info, $depth * 4); - } - - $this->writeLine($text, $depth * 4); - - // output defaults - if ($defaultArray) { - $this->writeLine(''); - - $message = \count($defaultArray) > 1 ? 'Defaults' : 'Default'; - - $this->writeLine('# '.$message.':', $depth * 4 + 4); - - $this->writeArray($defaultArray, $depth + 1); - } - - if (\is_array($example)) { - $this->writeLine(''); - - $message = \count($example) > 1 ? 'Examples' : 'Example'; - - $this->writeLine('# '.$message.':', $depth * 4 + 4); - - $this->writeArray($example, $depth + 1); - } - - if ($children) { - foreach ($children as $childNode) { - $this->writeNode($childNode, $node, $depth + 1, $node instanceof PrototypedArrayNode && !$node->getKeyAttribute()); - } - } - } - - /** - * Outputs a single config reference line. - */ - private function writeLine(string $text, int $indent = 0) - { - $indent = \strlen($text) + $indent; - $format = '%'.$indent.'s'; - - $this->reference .= sprintf($format, $text)."\n"; - } - - private function writeArray(array $array, int $depth) - { - $isIndexed = array_values($array) === $array; - - foreach ($array as $key => $value) { - if (\is_array($value)) { - $val = ''; - } else { - $val = $value; - } - - if ($isIndexed) { - $this->writeLine('- '.$val, $depth * 4); - } else { - $this->writeLine(sprintf('%-20s %s', $key.':', $val), $depth * 4); - } - - if (\is_array($value)) { - $this->writeArray($value, $depth + 1); - } - } - } - - private function getPrototypeChildren(PrototypedArrayNode $node): array - { - $prototype = $node->getPrototype(); - $key = $node->getKeyAttribute(); - - // Do not expand prototype if it isn't an array node nor uses attribute as key - if (!$key && !$prototype instanceof ArrayNode) { - return $node->getChildren(); - } - - if ($prototype instanceof ArrayNode) { - $keyNode = new ArrayNode($key, $node); - $children = $prototype->getChildren(); - - if ($prototype instanceof PrototypedArrayNode && $prototype->getKeyAttribute()) { - $children = $this->getPrototypeChildren($prototype); - } - - // add children - foreach ($children as $childNode) { - $keyNode->addChild($childNode); - } - } else { - $keyNode = new ScalarNode($key, $node); - } - - $info = 'Prototype'; - if (null !== $prototype->getInfo()) { - $info .= ': '.$prototype->getInfo(); - } - $keyNode->setInfo($info); - - return [$key => $keyNode]; - } -} diff --git a/vendor/symfony/config/Definition/EnumNode.php b/vendor/symfony/config/Definition/EnumNode.php deleted file mode 100644 index 23fc508..0000000 --- a/vendor/symfony/config/Definition/EnumNode.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; - -/** - * Node which only allows a finite set of values. - * - * @author Johannes M. Schmitt - */ -class EnumNode extends ScalarNode -{ - private $values; - - public function __construct(?string $name, NodeInterface $parent = null, array $values = [], string $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR) - { - $values = array_unique($values); - if (empty($values)) { - throw new \InvalidArgumentException('$values must contain at least one element.'); - } - - parent::__construct($name, $parent, $pathSeparator); - $this->values = $values; - } - - public function getValues() - { - return $this->values; - } - - protected function finalizeValue($value) - { - $value = parent::finalizeValue($value); - - if (!\in_array($value, $this->values, true)) { - $ex = new InvalidConfigurationException(sprintf('The value %s is not allowed for path "%s". Permissible values: %s', json_encode($value), $this->getPath(), implode(', ', array_map('json_encode', $this->values)))); - $ex->setPath($this->getPath()); - - throw $ex; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - protected function allowPlaceholders(): bool - { - return false; - } -} diff --git a/vendor/symfony/config/Definition/Exception/DuplicateKeyException.php b/vendor/symfony/config/Definition/Exception/DuplicateKeyException.php deleted file mode 100644 index 48dd932..0000000 --- a/vendor/symfony/config/Definition/Exception/DuplicateKeyException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * This exception is thrown whenever the key of an array is not unique. This can - * only be the case if the configuration is coming from an XML file. - * - * @author Johannes M. Schmitt - */ -class DuplicateKeyException extends InvalidConfigurationException -{ -} diff --git a/vendor/symfony/config/Definition/Exception/Exception.php b/vendor/symfony/config/Definition/Exception/Exception.php deleted file mode 100644 index 8933a49..0000000 --- a/vendor/symfony/config/Definition/Exception/Exception.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * Base exception for all configuration exceptions. - * - * @author Johannes M. Schmitt - */ -class Exception extends \RuntimeException -{ -} diff --git a/vendor/symfony/config/Definition/Exception/ForbiddenOverwriteException.php b/vendor/symfony/config/Definition/Exception/ForbiddenOverwriteException.php deleted file mode 100644 index 726c07f..0000000 --- a/vendor/symfony/config/Definition/Exception/ForbiddenOverwriteException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * This exception is thrown when a configuration path is overwritten from a - * subsequent configuration file, but the entry node specifically forbids this. - * - * @author Johannes M. Schmitt - */ -class ForbiddenOverwriteException extends InvalidConfigurationException -{ -} diff --git a/vendor/symfony/config/Definition/Exception/InvalidConfigurationException.php b/vendor/symfony/config/Definition/Exception/InvalidConfigurationException.php deleted file mode 100644 index fcaaf49..0000000 --- a/vendor/symfony/config/Definition/Exception/InvalidConfigurationException.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * A very general exception which can be thrown whenever non of the more specific - * exceptions is suitable. - * - * @author Johannes M. Schmitt - */ -class InvalidConfigurationException extends Exception -{ - private $path; - private $containsHints = false; - - public function setPath($path) - { - $this->path = $path; - } - - public function getPath() - { - return $this->path; - } - - /** - * Adds extra information that is suffixed to the original exception message. - */ - public function addHint(string $hint) - { - if (!$this->containsHints) { - $this->message .= "\nHint: ".$hint; - $this->containsHints = true; - } else { - $this->message .= ', '.$hint; - } - } -} diff --git a/vendor/symfony/config/Definition/Exception/InvalidDefinitionException.php b/vendor/symfony/config/Definition/Exception/InvalidDefinitionException.php deleted file mode 100644 index 98310da..0000000 --- a/vendor/symfony/config/Definition/Exception/InvalidDefinitionException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * Thrown when an error is detected in a node Definition. - * - * @author Victor Berchet - */ -class InvalidDefinitionException extends Exception -{ -} diff --git a/vendor/symfony/config/Definition/Exception/InvalidTypeException.php b/vendor/symfony/config/Definition/Exception/InvalidTypeException.php deleted file mode 100644 index d7ca8c9..0000000 --- a/vendor/symfony/config/Definition/Exception/InvalidTypeException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * This exception is thrown if an invalid type is encountered. - * - * @author Johannes M. Schmitt - */ -class InvalidTypeException extends InvalidConfigurationException -{ -} diff --git a/vendor/symfony/config/Definition/Exception/UnsetKeyException.php b/vendor/symfony/config/Definition/Exception/UnsetKeyException.php deleted file mode 100644 index 863181a..0000000 --- a/vendor/symfony/config/Definition/Exception/UnsetKeyException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition\Exception; - -/** - * This exception is usually not encountered by the end-user, but only used - * internally to signal the parent scope to unset a key. - * - * @author Johannes M. Schmitt - */ -class UnsetKeyException extends Exception -{ -} diff --git a/vendor/symfony/config/Definition/FloatNode.php b/vendor/symfony/config/Definition/FloatNode.php deleted file mode 100644 index 8e229ed..0000000 --- a/vendor/symfony/config/Definition/FloatNode.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; - -/** - * This node represents a float value in the config tree. - * - * @author Jeanmonod David - */ -class FloatNode extends NumericNode -{ - /** - * {@inheritdoc} - */ - protected function validateType($value) - { - // Integers are also accepted, we just cast them - if (\is_int($value)) { - $value = (float) $value; - } - - if (!\is_float($value)) { - $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected float, but got %s.', $this->getPath(), \gettype($value))); - if ($hint = $this->getInfo()) { - $ex->addHint($hint); - } - $ex->setPath($this->getPath()); - - throw $ex; - } - } - - /** - * {@inheritdoc} - */ - protected function getValidPlaceholderTypes(): array - { - return ['float']; - } -} diff --git a/vendor/symfony/config/Definition/IntegerNode.php b/vendor/symfony/config/Definition/IntegerNode.php deleted file mode 100644 index e8c6a81..0000000 --- a/vendor/symfony/config/Definition/IntegerNode.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; - -/** - * This node represents an integer value in the config tree. - * - * @author Jeanmonod David - */ -class IntegerNode extends NumericNode -{ - /** - * {@inheritdoc} - */ - protected function validateType($value) - { - if (!\is_int($value)) { - $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected int, but got %s.', $this->getPath(), \gettype($value))); - if ($hint = $this->getInfo()) { - $ex->addHint($hint); - } - $ex->setPath($this->getPath()); - - throw $ex; - } - } - - /** - * {@inheritdoc} - */ - protected function getValidPlaceholderTypes(): array - { - return ['int']; - } -} diff --git a/vendor/symfony/config/Definition/NodeInterface.php b/vendor/symfony/config/Definition/NodeInterface.php deleted file mode 100644 index 45f1f68..0000000 --- a/vendor/symfony/config/Definition/NodeInterface.php +++ /dev/null @@ -1,100 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; - -/** - * Common Interface among all nodes. - * - * In most cases, it is better to inherit from BaseNode instead of implementing - * this interface yourself. - * - * @author Johannes M. Schmitt - */ -interface NodeInterface -{ - /** - * Returns the name of the node. - * - * @return string The name of the node - */ - public function getName(); - - /** - * Returns the path of the node. - * - * @return string The node path - */ - public function getPath(); - - /** - * Returns true when the node is required. - * - * @return bool If the node is required - */ - public function isRequired(); - - /** - * Returns true when the node has a default value. - * - * @return bool If the node has a default value - */ - public function hasDefaultValue(); - - /** - * Returns the default value of the node. - * - * @return mixed The default value - * - * @throws \RuntimeException if the node has no default value - */ - public function getDefaultValue(); - - /** - * Normalizes a value. - * - * @param mixed $value The value to normalize - * - * @return mixed The normalized value - * - * @throws InvalidTypeException if the value type is invalid - */ - public function normalize($value); - - /** - * Merges two values together. - * - * @param mixed $leftSide - * @param mixed $rightSide - * - * @return mixed The merged value - * - * @throws ForbiddenOverwriteException if the configuration path cannot be overwritten - * @throws InvalidTypeException if the value type is invalid - */ - public function merge($leftSide, $rightSide); - - /** - * Finalizes a value. - * - * @param mixed $value The value to finalize - * - * @return mixed The finalized value - * - * @throws InvalidTypeException if the value type is invalid - * @throws InvalidConfigurationException if the value is invalid configuration - */ - public function finalize($value); -} diff --git a/vendor/symfony/config/Definition/NumericNode.php b/vendor/symfony/config/Definition/NumericNode.php deleted file mode 100644 index 19c96e8..0000000 --- a/vendor/symfony/config/Definition/NumericNode.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; - -/** - * This node represents a numeric value in the config tree. - * - * @author David Jeanmonod - */ -class NumericNode extends ScalarNode -{ - protected $min; - protected $max; - - public function __construct(?string $name, NodeInterface $parent = null, $min = null, $max = null, string $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR) - { - parent::__construct($name, $parent, $pathSeparator); - $this->min = $min; - $this->max = $max; - } - - /** - * {@inheritdoc} - */ - protected function finalizeValue($value) - { - $value = parent::finalizeValue($value); - - $errorMsg = null; - if (isset($this->min) && $value < $this->min) { - $errorMsg = sprintf('The value %s is too small for path "%s". Should be greater than or equal to %s', $value, $this->getPath(), $this->min); - } - if (isset($this->max) && $value > $this->max) { - $errorMsg = sprintf('The value %s is too big for path "%s". Should be less than or equal to %s', $value, $this->getPath(), $this->max); - } - if (isset($errorMsg)) { - $ex = new InvalidConfigurationException($errorMsg); - $ex->setPath($this->getPath()); - throw $ex; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - protected function isValueEmpty($value) - { - // a numeric value cannot be empty - return false; - } -} diff --git a/vendor/symfony/config/Definition/Processor.php b/vendor/symfony/config/Definition/Processor.php deleted file mode 100644 index 76f4700..0000000 --- a/vendor/symfony/config/Definition/Processor.php +++ /dev/null @@ -1,95 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -/** - * This class is the entry point for config normalization/merging/finalization. - * - * @author Johannes M. Schmitt - * - * @final - */ -class Processor -{ - /** - * Processes an array of configurations. - * - * @param array $configs An array of configuration items to process - * - * @return array The processed configuration - */ - public function process(NodeInterface $configTree, array $configs): array - { - $currentConfig = []; - foreach ($configs as $config) { - $config = $configTree->normalize($config); - $currentConfig = $configTree->merge($currentConfig, $config); - } - - return $configTree->finalize($currentConfig); - } - - /** - * Processes an array of configurations. - * - * @param array $configs An array of configuration items to process - * - * @return array The processed configuration - */ - public function processConfiguration(ConfigurationInterface $configuration, array $configs): array - { - return $this->process($configuration->getConfigTreeBuilder()->buildTree(), $configs); - } - - /** - * Normalizes a configuration entry. - * - * This method returns a normalize configuration array for a given key - * to remove the differences due to the original format (YAML and XML mainly). - * - * Here is an example. - * - * The configuration in XML: - * - * twig.extension.foo - * twig.extension.bar - * - * And the same configuration in YAML: - * - * extensions: ['twig.extension.foo', 'twig.extension.bar'] - * - * @param array $config A config array - * @param string $key The key to normalize - * @param string $plural The plural form of the key if it is irregular - */ - public static function normalizeConfig(array $config, string $key, string $plural = null): array - { - if (null === $plural) { - $plural = $key.'s'; - } - - if (isset($config[$plural])) { - return $config[$plural]; - } - - if (isset($config[$key])) { - if (\is_string($config[$key]) || !\is_int(key($config[$key]))) { - // only one - return [$config[$key]]; - } - - return $config[$key]; - } - - return []; - } -} diff --git a/vendor/symfony/config/Definition/PrototypeNodeInterface.php b/vendor/symfony/config/Definition/PrototypeNodeInterface.php deleted file mode 100644 index b160aa9..0000000 --- a/vendor/symfony/config/Definition/PrototypeNodeInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -/** - * This interface must be implemented by nodes which can be used as prototypes. - * - * @author Johannes M. Schmitt - */ -interface PrototypeNodeInterface extends NodeInterface -{ - /** - * Sets the name of the node. - */ - public function setName(string $name); -} diff --git a/vendor/symfony/config/Definition/PrototypedArrayNode.php b/vendor/symfony/config/Definition/PrototypedArrayNode.php deleted file mode 100644 index ff4570e..0000000 --- a/vendor/symfony/config/Definition/PrototypedArrayNode.php +++ /dev/null @@ -1,365 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\DuplicateKeyException; -use Symfony\Component\Config\Definition\Exception\Exception; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; -use Symfony\Component\Config\Definition\Exception\UnsetKeyException; - -/** - * Represents a prototyped Array node in the config tree. - * - * @author Johannes M. Schmitt - */ -class PrototypedArrayNode extends ArrayNode -{ - protected $prototype; - protected $keyAttribute; - protected $removeKeyAttribute = false; - protected $minNumberOfElements = 0; - protected $defaultValue = []; - protected $defaultChildren; - /** - * @var NodeInterface[] An array of the prototypes of the simplified value children - */ - private $valuePrototypes = []; - - /** - * Sets the minimum number of elements that a prototype based node must - * contain. By default this is zero, meaning no elements. - */ - public function setMinNumberOfElements(int $number) - { - $this->minNumberOfElements = $number; - } - - /** - * Sets the attribute which value is to be used as key. - * - * This is useful when you have an indexed array that should be an - * associative array. You can select an item from within the array - * to be the key of the particular item. For example, if "id" is the - * "key", then: - * - * [ - * ['id' => 'my_name', 'foo' => 'bar'], - * ]; - * - * becomes - * - * [ - * 'my_name' => ['foo' => 'bar'], - * ]; - * - * If you'd like "'id' => 'my_name'" to still be present in the resulting - * array, then you can set the second argument of this method to false. - * - * @param string $attribute The name of the attribute which value is to be used as a key - * @param bool $remove Whether or not to remove the key - */ - public function setKeyAttribute(string $attribute, bool $remove = true) - { - $this->keyAttribute = $attribute; - $this->removeKeyAttribute = $remove; - } - - /** - * Retrieves the name of the attribute which value should be used as key. - * - * @return string|null The name of the attribute - */ - public function getKeyAttribute() - { - return $this->keyAttribute; - } - - /** - * Sets the default value of this node. - */ - public function setDefaultValue(array $value) - { - $this->defaultValue = $value; - } - - /** - * {@inheritdoc} - */ - public function hasDefaultValue() - { - return true; - } - - /** - * Adds default children when none are set. - * - * @param int|string|array|null $children The number of children|The child name|The children names to be added - */ - public function setAddChildrenIfNoneSet($children = ['defaults']) - { - if (null === $children) { - $this->defaultChildren = ['defaults']; - } else { - $this->defaultChildren = \is_int($children) && $children > 0 ? range(1, $children) : (array) $children; - } - } - - /** - * {@inheritdoc} - * - * The default value could be either explicited or derived from the prototype - * default value. - */ - public function getDefaultValue() - { - if (null !== $this->defaultChildren) { - $default = $this->prototype->hasDefaultValue() ? $this->prototype->getDefaultValue() : []; - $defaults = []; - foreach (array_values($this->defaultChildren) as $i => $name) { - $defaults[null === $this->keyAttribute ? $i : $name] = $default; - } - - return $defaults; - } - - return $this->defaultValue; - } - - /** - * Sets the node prototype. - */ - public function setPrototype(PrototypeNodeInterface $node) - { - $this->prototype = $node; - } - - /** - * Retrieves the prototype. - * - * @return PrototypeNodeInterface The prototype - */ - public function getPrototype() - { - return $this->prototype; - } - - /** - * Disable adding concrete children for prototyped nodes. - * - * @throws Exception - */ - public function addChild(NodeInterface $node) - { - throw new Exception('A prototyped array node can not have concrete children.'); - } - - /** - * Finalizes the value of this node. - * - * @param mixed $value - * - * @return mixed The finalized value - * - * @throws UnsetKeyException - * @throws InvalidConfigurationException if the node doesn't have enough children - */ - protected function finalizeValue($value) - { - if (false === $value) { - throw new UnsetKeyException(sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value))); - } - - foreach ($value as $k => $v) { - $prototype = $this->getPrototypeForChild($k); - try { - $value[$k] = $prototype->finalize($v); - } catch (UnsetKeyException $e) { - unset($value[$k]); - } - } - - if (\count($value) < $this->minNumberOfElements) { - $ex = new InvalidConfigurationException(sprintf('The path "%s" should have at least %d element(s) defined.', $this->getPath(), $this->minNumberOfElements)); - $ex->setPath($this->getPath()); - - throw $ex; - } - - return $value; - } - - /** - * Normalizes the value. - * - * @param mixed $value The value to normalize - * - * @return mixed The normalized value - * - * @throws InvalidConfigurationException - * @throws DuplicateKeyException - */ - protected function normalizeValue($value) - { - if (false === $value) { - return $value; - } - - $value = $this->remapXml($value); - - $isAssoc = array_keys($value) !== range(0, \count($value) - 1); - $normalized = []; - foreach ($value as $k => $v) { - if (null !== $this->keyAttribute && \is_array($v)) { - if (!isset($v[$this->keyAttribute]) && \is_int($k) && !$isAssoc) { - $ex = new InvalidConfigurationException(sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath())); - $ex->setPath($this->getPath()); - - throw $ex; - } elseif (isset($v[$this->keyAttribute])) { - $k = $v[$this->keyAttribute]; - - // remove the key attribute when required - if ($this->removeKeyAttribute) { - unset($v[$this->keyAttribute]); - } - - // if only "value" is left - if (array_keys($v) === ['value']) { - $v = $v['value']; - if ($this->prototype instanceof ArrayNode && ($children = $this->prototype->getChildren()) && \array_key_exists('value', $children)) { - $valuePrototype = current($this->valuePrototypes) ?: clone $children['value']; - $valuePrototype->parent = $this; - $originalClosures = $this->prototype->normalizationClosures; - if (\is_array($originalClosures)) { - $valuePrototypeClosures = $valuePrototype->normalizationClosures; - $valuePrototype->normalizationClosures = \is_array($valuePrototypeClosures) ? array_merge($originalClosures, $valuePrototypeClosures) : $originalClosures; - } - $this->valuePrototypes[$k] = $valuePrototype; - } - } - } - - if (\array_key_exists($k, $normalized)) { - $ex = new DuplicateKeyException(sprintf('Duplicate key "%s" for path "%s".', $k, $this->getPath())); - $ex->setPath($this->getPath()); - - throw $ex; - } - } - - $prototype = $this->getPrototypeForChild($k); - if (null !== $this->keyAttribute || $isAssoc) { - $normalized[$k] = $prototype->normalize($v); - } else { - $normalized[] = $prototype->normalize($v); - } - } - - return $normalized; - } - - /** - * Merges values together. - * - * @param mixed $leftSide The left side to merge - * @param mixed $rightSide The right side to merge - * - * @return mixed The merged values - * - * @throws InvalidConfigurationException - * @throws \RuntimeException - */ - protected function mergeValues($leftSide, $rightSide) - { - if (false === $rightSide) { - // if this is still false after the last config has been merged the - // finalization pass will take care of removing this key entirely - return false; - } - - if (false === $leftSide || !$this->performDeepMerging) { - return $rightSide; - } - - foreach ($rightSide as $k => $v) { - // prototype, and key is irrelevant, append the element - if (null === $this->keyAttribute) { - $leftSide[] = $v; - continue; - } - - // no conflict - if (!\array_key_exists($k, $leftSide)) { - if (!$this->allowNewKeys) { - $ex = new InvalidConfigurationException(sprintf('You are not allowed to define new elements for path "%s". Please define all elements for this path in one config file.', $this->getPath())); - $ex->setPath($this->getPath()); - - throw $ex; - } - - $leftSide[$k] = $v; - continue; - } - - $prototype = $this->getPrototypeForChild($k); - $leftSide[$k] = $prototype->merge($leftSide[$k], $v); - } - - return $leftSide; - } - - /** - * Returns a prototype for the child node that is associated to $key in the value array. - * For general child nodes, this will be $this->prototype. - * But if $this->removeKeyAttribute is true and there are only two keys in the child node: - * one is same as this->keyAttribute and the other is 'value', then the prototype will be different. - * - * For example, assume $this->keyAttribute is 'name' and the value array is as follows: - * - * [ - * [ - * 'name' => 'name001', - * 'value' => 'value001' - * ] - * ] - * - * Now, the key is 0 and the child node is: - * - * [ - * 'name' => 'name001', - * 'value' => 'value001' - * ] - * - * When normalizing the value array, the 'name' element will removed from the child node - * and its value becomes the new key of the child node: - * - * [ - * 'name001' => ['value' => 'value001'] - * ] - * - * Now only 'value' element is left in the child node which can be further simplified into a string: - * - * ['name001' => 'value001'] - * - * Now, the key becomes 'name001' and the child node becomes 'value001' and - * the prototype of child node 'name001' should be a ScalarNode instead of an ArrayNode instance. - * - * @return mixed The prototype instance - */ - private function getPrototypeForChild(string $key) - { - $prototype = isset($this->valuePrototypes[$key]) ? $this->valuePrototypes[$key] : $this->prototype; - $prototype->setName($key); - - return $prototype; - } -} diff --git a/vendor/symfony/config/Definition/ScalarNode.php b/vendor/symfony/config/Definition/ScalarNode.php deleted file mode 100644 index 5ad28ec..0000000 --- a/vendor/symfony/config/Definition/ScalarNode.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidTypeException; - -/** - * This node represents a scalar value in the config tree. - * - * The following values are considered scalars: - * * booleans - * * strings - * * null - * * integers - * * floats - * - * @author Johannes M. Schmitt - */ -class ScalarNode extends VariableNode -{ - /** - * {@inheritdoc} - */ - protected function validateType($value) - { - if (!is_scalar($value) && null !== $value) { - $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected scalar, but got %s.', $this->getPath(), \gettype($value))); - if ($hint = $this->getInfo()) { - $ex->addHint($hint); - } - $ex->setPath($this->getPath()); - - throw $ex; - } - } - - /** - * {@inheritdoc} - */ - protected function isValueEmpty($value) - { - // assume environment variables are never empty (which in practice is likely to be true during runtime) - // not doing so breaks many configs that are valid today - if ($this->isHandlingPlaceholder()) { - return false; - } - - return null === $value || '' === $value; - } - - /** - * {@inheritdoc} - */ - protected function getValidPlaceholderTypes(): array - { - return ['bool', 'int', 'float', 'string']; - } -} diff --git a/vendor/symfony/config/Definition/VariableNode.php b/vendor/symfony/config/Definition/VariableNode.php deleted file mode 100644 index e868ece..0000000 --- a/vendor/symfony/config/Definition/VariableNode.php +++ /dev/null @@ -1,142 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Definition; - -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; - -/** - * This node represents a value of variable type in the config tree. - * - * This node is intended for values of arbitrary type. - * Any PHP type is accepted as a value. - * - * @author Jeremy Mikola - */ -class VariableNode extends BaseNode implements PrototypeNodeInterface -{ - protected $defaultValueSet = false; - protected $defaultValue; - protected $allowEmptyValue = true; - - public function setDefaultValue($value) - { - $this->defaultValueSet = true; - $this->defaultValue = $value; - } - - /** - * {@inheritdoc} - */ - public function hasDefaultValue() - { - return $this->defaultValueSet; - } - - /** - * {@inheritdoc} - */ - public function getDefaultValue() - { - $v = $this->defaultValue; - - return $v instanceof \Closure ? $v() : $v; - } - - /** - * Sets if this node is allowed to have an empty value. - * - * @param bool $boolean True if this entity will accept empty values - */ - public function setAllowEmptyValue(bool $boolean) - { - $this->allowEmptyValue = $boolean; - } - - /** - * {@inheritdoc} - */ - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - protected function validateType($value) - { - } - - /** - * {@inheritdoc} - */ - protected function finalizeValue($value) - { - // deny environment variables only when using custom validators - // this avoids ever passing an empty value to final validation closures - if (!$this->allowEmptyValue && $this->isHandlingPlaceholder() && $this->finalValidationClosures) { - $e = new InvalidConfigurationException(sprintf('The path "%s" cannot contain an environment variable when empty values are not allowed by definition and are validated.', $this->getPath())); - if ($hint = $this->getInfo()) { - $e->addHint($hint); - } - $e->setPath($this->getPath()); - - throw $e; - } - - if (!$this->allowEmptyValue && $this->isValueEmpty($value)) { - $ex = new InvalidConfigurationException(sprintf('The path "%s" cannot contain an empty value, but got %s.', $this->getPath(), json_encode($value))); - if ($hint = $this->getInfo()) { - $ex->addHint($hint); - } - $ex->setPath($this->getPath()); - - throw $ex; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - protected function normalizeValue($value) - { - return $value; - } - - /** - * {@inheritdoc} - */ - protected function mergeValues($leftSide, $rightSide) - { - return $rightSide; - } - - /** - * Evaluates if the given value is to be treated as empty. - * - * By default, PHP's empty() function is used to test for emptiness. This - * method may be overridden by subtypes to better match their understanding - * of empty data. - * - * @param mixed $value - * - * @return bool - * - * @see finalizeValue() - */ - protected function isValueEmpty($value) - { - return empty($value); - } -} diff --git a/vendor/symfony/config/Exception/FileLoaderImportCircularReferenceException.php b/vendor/symfony/config/Exception/FileLoaderImportCircularReferenceException.php deleted file mode 100644 index 8c5e736..0000000 --- a/vendor/symfony/config/Exception/FileLoaderImportCircularReferenceException.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Exception; - -/** - * Exception class for when a circular reference is detected when importing resources. - * - * @author Fabien Potencier - */ -class FileLoaderImportCircularReferenceException extends LoaderLoadException -{ - public function __construct(array $resources, int $code = null, \Throwable $previous = null) - { - $message = sprintf('Circular reference detected in "%s" ("%s" > "%s").', $this->varToString($resources[0]), implode('" > "', $resources), $resources[0]); - - \Exception::__construct($message, $code, $previous); - } -} diff --git a/vendor/symfony/config/Exception/FileLocatorFileNotFoundException.php b/vendor/symfony/config/Exception/FileLocatorFileNotFoundException.php deleted file mode 100644 index 3ee4b93..0000000 --- a/vendor/symfony/config/Exception/FileLocatorFileNotFoundException.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Exception; - -/** - * File locator exception if a file does not exist. - * - * @author Leo Feyer - */ -class FileLocatorFileNotFoundException extends \InvalidArgumentException -{ - private $paths; - - public function __construct(string $message = '', int $code = 0, \Throwable $previous = null, array $paths = []) - { - parent::__construct($message, $code, $previous); - - $this->paths = $paths; - } - - public function getPaths() - { - return $this->paths; - } -} diff --git a/vendor/symfony/config/Exception/LoaderLoadException.php b/vendor/symfony/config/Exception/LoaderLoadException.php deleted file mode 100644 index dcec320..0000000 --- a/vendor/symfony/config/Exception/LoaderLoadException.php +++ /dev/null @@ -1,109 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Exception; - -/** - * Exception class for when a resource cannot be loaded or imported. - * - * @author Ryan Weaver - */ -class LoaderLoadException extends \Exception -{ - /** - * @param string $resource The resource that could not be imported - * @param string $sourceResource The original resource importing the new resource - * @param int $code The error code - * @param \Throwable $previous A previous exception - * @param string $type The type of resource - */ - public function __construct(string $resource, string $sourceResource = null, int $code = null, \Throwable $previous = null, string $type = null) - { - $message = ''; - if ($previous) { - // Include the previous exception, to help the user see what might be the underlying cause - - // Trim the trailing period of the previous message. We only want 1 period remove so no rtrim... - if ('.' === substr($previous->getMessage(), -1)) { - $trimmedMessage = substr($previous->getMessage(), 0, -1); - $message .= sprintf('%s', $trimmedMessage).' in '; - } else { - $message .= sprintf('%s', $previous->getMessage()).' in '; - } - $message .= $resource.' '; - - // show tweaked trace to complete the human readable sentence - if (null === $sourceResource) { - $message .= sprintf('(which is loaded in resource "%s")', $resource); - } else { - $message .= sprintf('(which is being imported from "%s")', $sourceResource); - } - $message .= '.'; - - // if there's no previous message, present it the default way - } elseif (null === $sourceResource) { - $message .= sprintf('Cannot load resource "%s".', $resource); - } else { - $message .= sprintf('Cannot import resource "%s" from "%s".', $resource, $sourceResource); - } - - // Is the resource located inside a bundle? - if ('@' === $resource[0]) { - $parts = explode(\DIRECTORY_SEPARATOR, $resource); - $bundle = substr($parts[0], 1); - $message .= sprintf(' Make sure the "%s" bundle is correctly registered and loaded in the application kernel class.', $bundle); - $message .= sprintf(' If the bundle is registered, make sure the bundle path "%s" is not empty.', $resource); - } elseif (null !== $type) { - // maybe there is no loader for this specific type - if ('annotation' === $type) { - $message .= ' Make sure annotations are installed and enabled.'; - } else { - $message .= sprintf(' Make sure there is a loader supporting the "%s" type.', $type); - } - } - - parent::__construct($message, $code, $previous); - } - - protected function varToString($var) - { - if (\is_object($var)) { - return sprintf('Object(%s)', \get_class($var)); - } - - if (\is_array($var)) { - $a = []; - foreach ($var as $k => $v) { - $a[] = sprintf('%s => %s', $k, $this->varToString($v)); - } - - return sprintf('Array(%s)', implode(', ', $a)); - } - - if (\is_resource($var)) { - return sprintf('Resource(%s)', get_resource_type($var)); - } - - if (null === $var) { - return 'null'; - } - - if (false === $var) { - return 'false'; - } - - if (true === $var) { - return 'true'; - } - - return (string) $var; - } -} diff --git a/vendor/symfony/config/FileLocator.php b/vendor/symfony/config/FileLocator.php deleted file mode 100644 index 965f940..0000000 --- a/vendor/symfony/config/FileLocator.php +++ /dev/null @@ -1,94 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; - -/** - * FileLocator uses an array of pre-defined paths to find files. - * - * @author Fabien Potencier - */ -class FileLocator implements FileLocatorInterface -{ - protected $paths; - - /** - * @param string|string[] $paths A path or an array of paths where to look for resources - */ - public function __construct($paths = []) - { - $this->paths = (array) $paths; - } - - /** - * {@inheritdoc} - */ - public function locate(string $name, string $currentPath = null, bool $first = true) - { - if ('' === $name) { - throw new \InvalidArgumentException('An empty file name is not valid to be located.'); - } - - if ($this->isAbsolutePath($name)) { - if (!file_exists($name)) { - throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist.', $name), 0, null, [$name]); - } - - return $name; - } - - $paths = $this->paths; - - if (null !== $currentPath) { - array_unshift($paths, $currentPath); - } - - $paths = array_unique($paths); - $filepaths = $notfound = []; - - foreach ($paths as $path) { - if (@file_exists($file = $path.\DIRECTORY_SEPARATOR.$name)) { - if (true === $first) { - return $file; - } - $filepaths[] = $file; - } else { - $notfound[] = $file; - } - } - - if (!$filepaths) { - throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist (in: %s).', $name, implode(', ', $paths)), 0, null, $notfound); - } - - return $filepaths; - } - - /** - * Returns whether the file path is an absolute path. - */ - private function isAbsolutePath(string $file): bool - { - if ('/' === $file[0] || '\\' === $file[0] - || (\strlen($file) > 3 && ctype_alpha($file[0]) - && ':' === $file[1] - && ('\\' === $file[2] || '/' === $file[2]) - ) - || null !== parse_url($file, PHP_URL_SCHEME) - ) { - return true; - } - - return false; - } -} diff --git a/vendor/symfony/config/FileLocatorInterface.php b/vendor/symfony/config/FileLocatorInterface.php deleted file mode 100644 index e3ca1d4..0000000 --- a/vendor/symfony/config/FileLocatorInterface.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; - -/** - * @author Fabien Potencier - */ -interface FileLocatorInterface -{ - /** - * Returns a full path for a given file name. - * - * @param string $name The file name to locate - * @param string|null $currentPath The current path - * @param bool $first Whether to return the first occurrence or an array of filenames - * - * @return string|array The full path to the file or an array of file paths - * - * @throws \InvalidArgumentException If $name is empty - * @throws FileLocatorFileNotFoundException If a file is not found - */ - public function locate(string $name, string $currentPath = null, bool $first = true); -} diff --git a/vendor/symfony/config/LICENSE b/vendor/symfony/config/LICENSE deleted file mode 100644 index a677f43..0000000 --- a/vendor/symfony/config/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/config/Loader/DelegatingLoader.php b/vendor/symfony/config/Loader/DelegatingLoader.php deleted file mode 100644 index 2ec64cb..0000000 --- a/vendor/symfony/config/Loader/DelegatingLoader.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -use Symfony\Component\Config\Exception\LoaderLoadException; - -/** - * DelegatingLoader delegates loading to other loaders using a loader resolver. - * - * This loader acts as an array of LoaderInterface objects - each having - * a chance to load a given resource (handled by the resolver) - * - * @author Fabien Potencier - */ -class DelegatingLoader extends Loader -{ - public function __construct(LoaderResolverInterface $resolver) - { - $this->resolver = $resolver; - } - - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - if (false === $loader = $this->resolver->resolve($resource, $type)) { - throw new LoaderLoadException($resource, null, null, null, $type); - } - - return $loader->load($resource, $type); - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return false !== $this->resolver->resolve($resource, $type); - } -} diff --git a/vendor/symfony/config/Loader/FileLoader.php b/vendor/symfony/config/Loader/FileLoader.php deleted file mode 100644 index 58dc4e7..0000000 --- a/vendor/symfony/config/Loader/FileLoader.php +++ /dev/null @@ -1,179 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException; -use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; -use Symfony\Component\Config\Exception\LoaderLoadException; -use Symfony\Component\Config\FileLocatorInterface; -use Symfony\Component\Config\Resource\FileExistenceResource; -use Symfony\Component\Config\Resource\GlobResource; - -/** - * FileLoader is the abstract class used by all built-in loaders that are file based. - * - * @author Fabien Potencier - */ -abstract class FileLoader extends Loader -{ - protected static $loading = []; - - protected $locator; - - private $currentDir; - - public function __construct(FileLocatorInterface $locator) - { - $this->locator = $locator; - } - - /** - * Sets the current directory. - */ - public function setCurrentDir(string $dir) - { - $this->currentDir = $dir; - } - - /** - * Returns the file locator used by this loader. - * - * @return FileLocatorInterface - */ - public function getLocator() - { - return $this->locator; - } - - /** - * Imports a resource. - * - * @param mixed $resource A Resource - * @param string|null $type The resource type or null if unknown - * @param bool $ignoreErrors Whether to ignore import errors or not - * @param string|null $sourceResource The original resource importing the new resource - * @param string|string[]|null $exclude Glob patterns to exclude from the import - * - * @return mixed - * - * @throws LoaderLoadException - * @throws FileLoaderImportCircularReferenceException - * @throws FileLocatorFileNotFoundException - */ - public function import($resource, string $type = null, bool $ignoreErrors = false, string $sourceResource = null, $exclude = null) - { - if (\is_string($resource) && \strlen($resource) !== $i = strcspn($resource, '*?{[')) { - $excluded = []; - foreach ((array) $exclude as $pattern) { - foreach ($this->glob($pattern, true, $_, false, true) as $path => $info) { - // normalize Windows slashes - $excluded[str_replace('\\', '/', $path)] = true; - } - } - - $ret = []; - $isSubpath = 0 !== $i && false !== strpos(substr($resource, 0, $i), '/'); - foreach ($this->glob($resource, false, $_, $ignoreErrors || !$isSubpath, false, $excluded) as $path => $info) { - if (null !== $res = $this->doImport($path, $type, $ignoreErrors, $sourceResource)) { - $ret[] = $res; - } - $isSubpath = true; - } - - if ($isSubpath) { - return isset($ret[1]) ? $ret : (isset($ret[0]) ? $ret[0] : null); - } - } - - return $this->doImport($resource, $type, $ignoreErrors, $sourceResource); - } - - /** - * @internal - */ - protected function glob(string $pattern, bool $recursive, &$resource = null, bool $ignoreErrors = false, bool $forExclusion = false, array $excluded = []) - { - if (\strlen($pattern) === $i = strcspn($pattern, '*?{[')) { - $prefix = $pattern; - $pattern = ''; - } elseif (0 === $i || false === strpos(substr($pattern, 0, $i), '/')) { - $prefix = '.'; - $pattern = '/'.$pattern; - } else { - $prefix = \dirname(substr($pattern, 0, 1 + $i)); - $pattern = substr($pattern, \strlen($prefix)); - } - - try { - $prefix = $this->locator->locate($prefix, $this->currentDir, true); - } catch (FileLocatorFileNotFoundException $e) { - if (!$ignoreErrors) { - throw $e; - } - - $resource = []; - foreach ($e->getPaths() as $path) { - $resource[] = new FileExistenceResource($path); - } - - return; - } - $resource = new GlobResource($prefix, $pattern, $recursive, $forExclusion, $excluded); - - yield from $resource; - } - - private function doImport($resource, string $type = null, bool $ignoreErrors = false, string $sourceResource = null) - { - try { - $loader = $this->resolve($resource, $type); - - if ($loader instanceof self && null !== $this->currentDir) { - $resource = $loader->getLocator()->locate($resource, $this->currentDir, false); - } - - $resources = \is_array($resource) ? $resource : [$resource]; - for ($i = 0; $i < $resourcesCount = \count($resources); ++$i) { - if (isset(self::$loading[$resources[$i]])) { - if ($i == $resourcesCount - 1) { - throw new FileLoaderImportCircularReferenceException(array_keys(self::$loading)); - } - } else { - $resource = $resources[$i]; - break; - } - } - self::$loading[$resource] = true; - - try { - $ret = $loader->load($resource, $type); - } finally { - unset(self::$loading[$resource]); - } - - return $ret; - } catch (FileLoaderImportCircularReferenceException $e) { - throw $e; - } catch (\Exception $e) { - if (!$ignoreErrors) { - // prevent embedded imports from nesting multiple exceptions - if ($e instanceof LoaderLoadException) { - throw $e; - } - - throw new LoaderLoadException($resource, $sourceResource, null, $e, $type); - } - } - - return null; - } -} diff --git a/vendor/symfony/config/Loader/GlobFileLoader.php b/vendor/symfony/config/Loader/GlobFileLoader.php deleted file mode 100644 index fecb1c5..0000000 --- a/vendor/symfony/config/Loader/GlobFileLoader.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -/** - * GlobFileLoader loads files from a glob pattern. - * - * @author Fabien Potencier - */ -class GlobFileLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - return $this->import($resource); - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return 'glob' === $type; - } -} diff --git a/vendor/symfony/config/Loader/Loader.php b/vendor/symfony/config/Loader/Loader.php deleted file mode 100644 index 62cae68..0000000 --- a/vendor/symfony/config/Loader/Loader.php +++ /dev/null @@ -1,78 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -use Symfony\Component\Config\Exception\LoaderLoadException; - -/** - * Loader is the abstract class used by all built-in loaders. - * - * @author Fabien Potencier - */ -abstract class Loader implements LoaderInterface -{ - protected $resolver; - - /** - * {@inheritdoc} - */ - public function getResolver() - { - return $this->resolver; - } - - /** - * {@inheritdoc} - */ - public function setResolver(LoaderResolverInterface $resolver) - { - $this->resolver = $resolver; - } - - /** - * Imports a resource. - * - * @param mixed $resource A resource - * @param string|null $type The resource type or null if unknown - * - * @return mixed - */ - public function import($resource, string $type = null) - { - return $this->resolve($resource, $type)->load($resource, $type); - } - - /** - * Finds a loader able to load an imported resource. - * - * @param mixed $resource A resource - * @param string|null $type The resource type or null if unknown - * - * @return $this|LoaderInterface - * - * @throws LoaderLoadException If no loader is found - */ - public function resolve($resource, string $type = null) - { - if ($this->supports($resource, $type)) { - return $this; - } - - $loader = null === $this->resolver ? false : $this->resolver->resolve($resource, $type); - - if (false === $loader) { - throw new LoaderLoadException($resource, null, null, null, $type); - } - - return $loader; - } -} diff --git a/vendor/symfony/config/Loader/LoaderInterface.php b/vendor/symfony/config/Loader/LoaderInterface.php deleted file mode 100644 index 4dfb42c..0000000 --- a/vendor/symfony/config/Loader/LoaderInterface.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -/** - * LoaderInterface is the interface implemented by all loader classes. - * - * @author Fabien Potencier - */ -interface LoaderInterface -{ - /** - * Loads a resource. - * - * @param mixed $resource The resource - * - * @throws \Exception If something went wrong - */ - public function load($resource, string $type = null); - - /** - * Returns whether this class supports the given resource. - * - * @param mixed $resource A resource - * - * @return bool True if this class supports the given resource, false otherwise - */ - public function supports($resource, string $type = null); - - /** - * Gets the loader resolver. - * - * @return LoaderResolverInterface A LoaderResolverInterface instance - */ - public function getResolver(); - - /** - * Sets the loader resolver. - */ - public function setResolver(LoaderResolverInterface $resolver); -} diff --git a/vendor/symfony/config/Loader/LoaderResolver.php b/vendor/symfony/config/Loader/LoaderResolver.php deleted file mode 100644 index d243b91..0000000 --- a/vendor/symfony/config/Loader/LoaderResolver.php +++ /dev/null @@ -1,68 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -/** - * LoaderResolver selects a loader for a given resource. - * - * A resource can be anything (e.g. a full path to a config file or a Closure). - * Each loader determines whether it can load a resource and how. - * - * @author Fabien Potencier - */ -class LoaderResolver implements LoaderResolverInterface -{ - /** - * @var LoaderInterface[] An array of LoaderInterface objects - */ - private $loaders = []; - - /** - * @param LoaderInterface[] $loaders An array of loaders - */ - public function __construct(array $loaders = []) - { - foreach ($loaders as $loader) { - $this->addLoader($loader); - } - } - - /** - * {@inheritdoc} - */ - public function resolve($resource, string $type = null) - { - foreach ($this->loaders as $loader) { - if ($loader->supports($resource, $type)) { - return $loader; - } - } - - return false; - } - - public function addLoader(LoaderInterface $loader) - { - $this->loaders[] = $loader; - $loader->setResolver($this); - } - - /** - * Returns the registered loaders. - * - * @return LoaderInterface[] An array of LoaderInterface instances - */ - public function getLoaders() - { - return $this->loaders; - } -} diff --git a/vendor/symfony/config/Loader/LoaderResolverInterface.php b/vendor/symfony/config/Loader/LoaderResolverInterface.php deleted file mode 100644 index 2c45a4c..0000000 --- a/vendor/symfony/config/Loader/LoaderResolverInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Loader; - -/** - * LoaderResolverInterface selects a loader for a given resource. - * - * @author Fabien Potencier - */ -interface LoaderResolverInterface -{ - /** - * Returns a loader able to load the resource. - * - * @param mixed $resource A resource - * @param string|null $type The resource type or null if unknown - * - * @return LoaderInterface|false The loader or false if none is able to load the resource - */ - public function resolve($resource, string $type = null); -} diff --git a/vendor/symfony/config/README.md b/vendor/symfony/config/README.md deleted file mode 100644 index bf400da..0000000 --- a/vendor/symfony/config/README.md +++ /dev/null @@ -1,15 +0,0 @@ -Config Component -================ - -The Config component provides several classes to help you find, load, combine, -autofill and validate configuration values of any kind, whatever their source -may be (YAML, XML, INI files, or for instance a database). - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/config/index.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/config/Resource/ClassExistenceResource.php b/vendor/symfony/config/Resource/ClassExistenceResource.php deleted file mode 100644 index a547fb4..0000000 --- a/vendor/symfony/config/Resource/ClassExistenceResource.php +++ /dev/null @@ -1,231 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * ClassExistenceResource represents a class existence. - * Freshness is only evaluated against resource existence. - * - * The resource must be a fully-qualified class name. - * - * @author Fabien Potencier - * - * @final - */ -class ClassExistenceResource implements SelfCheckingResourceInterface -{ - private $resource; - private $exists; - - private static $autoloadLevel = 0; - private static $autoloadedClass; - private static $existsCache = []; - - /** - * @param string $resource The fully-qualified class name - * @param bool|null $exists Boolean when the existency check has already been done - */ - public function __construct(string $resource, bool $exists = null) - { - $this->resource = $resource; - if (null !== $exists) { - $this->exists = [(bool) $exists, null]; - } - } - - /** - * {@inheritdoc} - */ - public function __toString(): string - { - return $this->resource; - } - - /** - * @return string The file path to the resource - */ - public function getResource(): string - { - return $this->resource; - } - - /** - * {@inheritdoc} - * - * @throws \ReflectionException when a parent class/interface/trait is not found - */ - public function isFresh(int $timestamp): bool - { - $loaded = class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false); - - if (null !== $exists = &self::$existsCache[$this->resource]) { - if ($loaded) { - $exists = [true, null]; - } elseif (0 >= $timestamp && !$exists[0] && null !== $exists[1]) { - throw new \ReflectionException($exists[1]); - } - } elseif ([false, null] === $exists = [$loaded, null]) { - if (!self::$autoloadLevel++) { - spl_autoload_register(__CLASS__.'::throwOnRequiredClass'); - } - $autoloadedClass = self::$autoloadedClass; - self::$autoloadedClass = ltrim($this->resource, '\\'); - - try { - $exists[0] = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false); - } catch (\Exception $e) { - $exists[1] = $e->getMessage(); - - try { - self::throwOnRequiredClass($this->resource, $e); - } catch (\ReflectionException $e) { - if (0 >= $timestamp) { - throw $e; - } - } - } catch (\Throwable $e) { - $exists[1] = $e->getMessage(); - } finally { - self::$autoloadedClass = $autoloadedClass; - if (!--self::$autoloadLevel) { - spl_autoload_unregister(__CLASS__.'::throwOnRequiredClass'); - } - } - } - - if (null === $this->exists) { - $this->exists = $exists; - } - - return $this->exists[0] xor !$exists[0]; - } - - /** - * @internal - */ - public function __sleep(): array - { - if (null === $this->exists) { - $this->isFresh(0); - } - - return ['resource', 'exists']; - } - - /** - * @internal - */ - public function __wakeup() - { - if (\is_bool($this->exists)) { - $this->exists = [$this->exists, null]; - } - } - - /** - * Throws a reflection exception when the passed class does not exist but is required. - * - * A class is considered "not required" when it's loaded as part of a "class_exists" or similar check. - * - * This function can be used as an autoload function to throw a reflection - * exception if the class was not found by previous autoload functions. - * - * A previous exception can be passed. In this case, the class is considered as being - * required totally, so if it doesn't exist, a reflection exception is always thrown. - * If it exists, the previous exception is rethrown. - * - * @throws \ReflectionException - * - * @internal - */ - public static function throwOnRequiredClass(string $class, \Exception $previous = null) - { - // If the passed class is the resource being checked, we shouldn't throw. - if (null === $previous && self::$autoloadedClass === $class) { - return; - } - - if (class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) { - if (null !== $previous) { - throw $previous; - } - - return; - } - - if ($previous instanceof \ReflectionException) { - throw $previous; - } - - $message = sprintf('Class "%s" not found.', $class); - - if (self::$autoloadedClass !== $class) { - $message = substr_replace($message, sprintf(' while loading "%s"', self::$autoloadedClass), -1, 0); - } - - if (null !== $previous) { - $message = $previous->getMessage(); - } - - $e = new \ReflectionException($message, 0, $previous); - - if (null !== $previous) { - throw $e; - } - - $trace = debug_backtrace(); - $autoloadFrame = [ - 'function' => 'spl_autoload_call', - 'args' => [$class], - ]; - - if (false === $i = array_search($autoloadFrame, $trace, true)) { - throw $e; - } - - if (isset($trace[++$i]['function']) && !isset($trace[$i]['class'])) { - switch ($trace[$i]['function']) { - case 'get_class_methods': - case 'get_class_vars': - case 'get_parent_class': - case 'is_a': - case 'is_subclass_of': - case 'class_exists': - case 'class_implements': - case 'class_parents': - case 'trait_exists': - case 'defined': - case 'interface_exists': - case 'method_exists': - case 'property_exists': - case 'is_callable': - return; - } - - $props = [ - 'file' => isset($trace[$i]['file']) ? $trace[$i]['file'] : null, - 'line' => isset($trace[$i]['line']) ? $trace[$i]['line'] : null, - 'trace' => \array_slice($trace, 1 + $i), - ]; - - foreach ($props as $p => $v) { - if (null !== $v) { - $r = new \ReflectionProperty('Exception', $p); - $r->setAccessible(true); - $r->setValue($e, $v); - } - } - } - - throw $e; - } -} diff --git a/vendor/symfony/config/Resource/ComposerResource.php b/vendor/symfony/config/Resource/ComposerResource.php deleted file mode 100644 index e2abe0c..0000000 --- a/vendor/symfony/config/Resource/ComposerResource.php +++ /dev/null @@ -1,70 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * ComposerResource tracks the PHP version and Composer dependencies. - * - * @author Nicolas Grekas - * - * @final - */ -class ComposerResource implements SelfCheckingResourceInterface -{ - private $vendors; - - private static $runtimeVendors; - - public function __construct() - { - self::refresh(); - $this->vendors = self::$runtimeVendors; - } - - public function getVendors(): array - { - return array_keys($this->vendors); - } - - /** - * {@inheritdoc} - */ - public function __toString(): string - { - return __CLASS__; - } - - /** - * {@inheritdoc} - */ - public function isFresh(int $timestamp): bool - { - self::refresh(); - - return array_values(self::$runtimeVendors) === array_values($this->vendors); - } - - private static function refresh() - { - self::$runtimeVendors = []; - - foreach (get_declared_classes() as $class) { - if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) { - $r = new \ReflectionClass($class); - $v = \dirname($r->getFileName(), 2); - if (file_exists($v.'/composer/installed.json')) { - self::$runtimeVendors[$v] = @filemtime($v.'/composer/installed.json'); - } - } - } - } -} diff --git a/vendor/symfony/config/Resource/DirectoryResource.php b/vendor/symfony/config/Resource/DirectoryResource.php deleted file mode 100644 index 1a28881..0000000 --- a/vendor/symfony/config/Resource/DirectoryResource.php +++ /dev/null @@ -1,106 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * DirectoryResource represents a resources stored in a subdirectory tree. - * - * @author Fabien Potencier - * - * @final - */ -class DirectoryResource implements SelfCheckingResourceInterface -{ - private $resource; - private $pattern; - - /** - * @param string $resource The file path to the resource - * @param string|null $pattern A pattern to restrict monitored files - * - * @throws \InvalidArgumentException - */ - public function __construct(string $resource, string $pattern = null) - { - $this->resource = realpath($resource) ?: (file_exists($resource) ? $resource : false); - $this->pattern = $pattern; - - if (false === $this->resource || !is_dir($this->resource)) { - throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist.', $resource)); - } - } - - /** - * {@inheritdoc} - */ - public function __toString(): string - { - return md5(serialize([$this->resource, $this->pattern])); - } - - /** - * @return string The file path to the resource - */ - public function getResource(): string - { - return $this->resource; - } - - /** - * Returns the pattern to restrict monitored files. - */ - public function getPattern(): ?string - { - return $this->pattern; - } - - /** - * {@inheritdoc} - */ - public function isFresh(int $timestamp): bool - { - if (!is_dir($this->resource)) { - return false; - } - - if ($timestamp < filemtime($this->resource)) { - return false; - } - - foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->resource), \RecursiveIteratorIterator::SELF_FIRST) as $file) { - // if regex filtering is enabled only check matching files - if ($this->pattern && $file->isFile() && !preg_match($this->pattern, $file->getBasename())) { - continue; - } - - // always monitor directories for changes, except the .. entries - // (otherwise deleted files wouldn't get detected) - if ($file->isDir() && '/..' === substr($file, -3)) { - continue; - } - - // for broken links - try { - $fileMTime = $file->getMTime(); - } catch (\RuntimeException $e) { - continue; - } - - // early return if a file's mtime exceeds the passed timestamp - if ($timestamp < $fileMTime) { - return false; - } - } - - return true; - } -} diff --git a/vendor/symfony/config/Resource/FileExistenceResource.php b/vendor/symfony/config/Resource/FileExistenceResource.php deleted file mode 100644 index ca2d2c3..0000000 --- a/vendor/symfony/config/Resource/FileExistenceResource.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * FileExistenceResource represents a resource stored on the filesystem. - * Freshness is only evaluated against resource creation or deletion. - * - * The resource can be a file or a directory. - * - * @author Charles-Henri Bruyand - * - * @final - */ -class FileExistenceResource implements SelfCheckingResourceInterface -{ - private $resource; - - private $exists; - - /** - * @param string $resource The file path to the resource - */ - public function __construct(string $resource) - { - $this->resource = $resource; - $this->exists = file_exists($resource); - } - - /** - * {@inheritdoc} - */ - public function __toString(): string - { - return $this->resource; - } - - /** - * @return string The file path to the resource - */ - public function getResource(): string - { - return $this->resource; - } - - /** - * {@inheritdoc} - */ - public function isFresh(int $timestamp): bool - { - return file_exists($this->resource) === $this->exists; - } -} diff --git a/vendor/symfony/config/Resource/FileResource.php b/vendor/symfony/config/Resource/FileResource.php deleted file mode 100644 index 4274d07..0000000 --- a/vendor/symfony/config/Resource/FileResource.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * FileResource represents a resource stored on the filesystem. - * - * The resource can be a file or a directory. - * - * @author Fabien Potencier - * - * @final - */ -class FileResource implements SelfCheckingResourceInterface -{ - /** - * @var string|false - */ - private $resource; - - /** - * @param string $resource The file path to the resource - * - * @throws \InvalidArgumentException - */ - public function __construct(string $resource) - { - $this->resource = realpath($resource) ?: (file_exists($resource) ? $resource : false); - - if (false === $this->resource) { - throw new \InvalidArgumentException(sprintf('The file "%s" does not exist.', $resource)); - } - } - - /** - * {@inheritdoc} - */ - public function __toString(): string - { - return $this->resource; - } - - /** - * @return string The canonicalized, absolute path to the resource - */ - public function getResource(): string - { - return $this->resource; - } - - /** - * {@inheritdoc} - */ - public function isFresh(int $timestamp): bool - { - return false !== ($filemtime = @filemtime($this->resource)) && $filemtime <= $timestamp; - } -} diff --git a/vendor/symfony/config/Resource/GlobResource.php b/vendor/symfony/config/Resource/GlobResource.php deleted file mode 100644 index 8f5a2f1..0000000 --- a/vendor/symfony/config/Resource/GlobResource.php +++ /dev/null @@ -1,230 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -use Symfony\Component\Finder\Finder; -use Symfony\Component\Finder\Glob; - -/** - * GlobResource represents a set of resources stored on the filesystem. - * - * Only existence/removal is tracked (not mtimes.) - * - * @author Nicolas Grekas - * - * @final - */ -class GlobResource implements \IteratorAggregate, SelfCheckingResourceInterface -{ - private $prefix; - private $pattern; - private $recursive; - private $hash; - private $forExclusion; - private $excludedPrefixes; - private $globBrace; - - /** - * @param string $prefix A directory prefix - * @param string $pattern A glob pattern - * @param bool $recursive Whether directories should be scanned recursively or not - * - * @throws \InvalidArgumentException - */ - public function __construct(string $prefix, string $pattern, bool $recursive, bool $forExclusion = false, array $excludedPrefixes = []) - { - ksort($excludedPrefixes); - $this->prefix = realpath($prefix) ?: (file_exists($prefix) ? $prefix : false); - $this->pattern = $pattern; - $this->recursive = $recursive; - $this->forExclusion = $forExclusion; - $this->excludedPrefixes = $excludedPrefixes; - $this->globBrace = \defined('GLOB_BRACE') ? GLOB_BRACE : 0; - - if (false === $this->prefix) { - throw new \InvalidArgumentException(sprintf('The path "%s" does not exist.', $prefix)); - } - } - - public function getPrefix(): string - { - return $this->prefix; - } - - /** - * {@inheritdoc} - */ - public function __toString(): string - { - return 'glob.'.$this->prefix.(int) $this->recursive.$this->pattern.(int) $this->forExclusion.implode("\0", $this->excludedPrefixes); - } - - /** - * {@inheritdoc} - */ - public function isFresh(int $timestamp): bool - { - $hash = $this->computeHash(); - - if (null === $this->hash) { - $this->hash = $hash; - } - - return $this->hash === $hash; - } - - /** - * @internal - */ - public function __sleep(): array - { - if (null === $this->hash) { - $this->hash = $this->computeHash(); - } - - return ['prefix', 'pattern', 'recursive', 'hash', 'forExclusion', 'excludedPrefixes']; - } - - public function getIterator(): \Traversable - { - if (!file_exists($this->prefix) || (!$this->recursive && '' === $this->pattern)) { - return; - } - $prefix = str_replace('\\', '/', $this->prefix); - $paths = null; - - if (0 !== strpos($this->prefix, 'phar://') && false === strpos($this->pattern, '/**/')) { - if ($this->globBrace || false === strpos($this->pattern, '{')) { - $paths = glob($this->prefix.$this->pattern, GLOB_NOSORT | $this->globBrace); - } elseif (false === strpos($this->pattern, '\\') || !preg_match('/\\\\[,{}]/', $this->pattern)) { - foreach ($this->expandGlob($this->pattern) as $p) { - $paths[] = glob($this->prefix.$p, GLOB_NOSORT); - } - $paths = array_merge(...$paths); - } - } - - if (null !== $paths) { - sort($paths); - foreach ($paths as $path) { - if ($this->excludedPrefixes) { - $normalizedPath = str_replace('\\', '/', $path); - do { - if (isset($this->excludedPrefixes[$dirPath = $normalizedPath])) { - continue 2; - } - } while ($prefix !== $dirPath && $dirPath !== $normalizedPath = \dirname($dirPath)); - } - - if (is_file($path)) { - yield $path => new \SplFileInfo($path); - } - if (!is_dir($path)) { - continue; - } - if ($this->forExclusion) { - yield $path => new \SplFileInfo($path); - continue; - } - if (!$this->recursive || isset($this->excludedPrefixes[str_replace('\\', '/', $path)])) { - continue; - } - $files = iterator_to_array(new \RecursiveIteratorIterator( - new \RecursiveCallbackFilterIterator( - new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), - function (\SplFileInfo $file, $path) { - return !isset($this->excludedPrefixes[str_replace('\\', '/', $path)]) && '.' !== $file->getBasename()[0]; - } - ), - \RecursiveIteratorIterator::LEAVES_ONLY - )); - uasort($files, 'strnatcmp'); - - foreach ($files as $path => $info) { - if ($info->isFile()) { - yield $path => $info; - } - } - } - - return; - } - - if (!class_exists(Finder::class)) { - throw new \LogicException(sprintf('Extended glob pattern "%s" cannot be used as the Finder component is not installed.', $this->pattern)); - } - - $finder = new Finder(); - $regex = Glob::toRegex($this->pattern); - if ($this->recursive) { - $regex = substr_replace($regex, '(/|$)', -2, 1); - } - - $prefixLen = \strlen($this->prefix); - foreach ($finder->followLinks()->sortByName()->in($this->prefix) as $path => $info) { - $normalizedPath = str_replace('\\', '/', $path); - if (!preg_match($regex, substr($normalizedPath, $prefixLen)) || !$info->isFile()) { - continue; - } - if ($this->excludedPrefixes) { - do { - if (isset($this->excludedPrefixes[$dirPath = $normalizedPath])) { - continue 2; - } - } while ($prefix !== $dirPath && $dirPath !== $normalizedPath = \dirname($dirPath)); - } - - yield $path => $info; - } - } - - private function computeHash(): string - { - $hash = hash_init('md5'); - - foreach ($this->getIterator() as $path => $info) { - hash_update($hash, $path."\n"); - } - - return hash_final($hash); - } - - private function expandGlob(string $pattern): array - { - $segments = preg_split('/\{([^{}]*+)\}/', $pattern, -1, PREG_SPLIT_DELIM_CAPTURE); - $paths = [$segments[0]]; - $patterns = []; - - for ($i = 1; $i < \count($segments); $i += 2) { - $patterns = []; - - foreach (explode(',', $segments[$i]) as $s) { - foreach ($paths as $p) { - $patterns[] = $p.$s.$segments[1 + $i]; - } - } - - $paths = $patterns; - } - - $j = 0; - foreach ($patterns as $i => $p) { - if (false !== strpos($p, '{')) { - $p = $this->expandGlob($p); - array_splice($paths, $i + $j, 1, $p); - $j += \count($p) - 1; - } - } - - return $paths; - } -} diff --git a/vendor/symfony/config/Resource/ReflectionClassResource.php b/vendor/symfony/config/Resource/ReflectionClassResource.php deleted file mode 100644 index bca9269..0000000 --- a/vendor/symfony/config/Resource/ReflectionClassResource.php +++ /dev/null @@ -1,220 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Messenger\Handler\MessageSubscriberInterface; -use Symfony\Contracts\Service\ServiceSubscriberInterface; - -/** - * @author Nicolas Grekas - * - * @final - */ -class ReflectionClassResource implements SelfCheckingResourceInterface -{ - private $files = []; - private $className; - private $classReflector; - private $excludedVendors = []; - private $hash; - - public function __construct(\ReflectionClass $classReflector, array $excludedVendors = []) - { - $this->className = $classReflector->name; - $this->classReflector = $classReflector; - $this->excludedVendors = $excludedVendors; - } - - /** - * {@inheritdoc} - */ - public function isFresh(int $timestamp): bool - { - if (null === $this->hash) { - $this->hash = $this->computeHash(); - $this->loadFiles($this->classReflector); - } - - foreach ($this->files as $file => $v) { - if (false === $filemtime = @filemtime($file)) { - return false; - } - - if ($filemtime > $timestamp) { - return $this->hash === $this->computeHash(); - } - } - - return true; - } - - public function __toString(): string - { - return 'reflection.'.$this->className; - } - - /** - * @internal - */ - public function __sleep(): array - { - if (null === $this->hash) { - $this->hash = $this->computeHash(); - $this->loadFiles($this->classReflector); - } - - return ['files', 'className', 'hash']; - } - - private function loadFiles(\ReflectionClass $class) - { - foreach ($class->getInterfaces() as $v) { - $this->loadFiles($v); - } - do { - $file = $class->getFileName(); - if (false !== $file && file_exists($file)) { - foreach ($this->excludedVendors as $vendor) { - if (0 === strpos($file, $vendor) && false !== strpbrk(substr($file, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) { - $file = false; - break; - } - } - if ($file) { - $this->files[$file] = null; - } - } - foreach ($class->getTraits() as $v) { - $this->loadFiles($v); - } - } while ($class = $class->getParentClass()); - } - - private function computeHash(): string - { - if (null === $this->classReflector) { - try { - $this->classReflector = new \ReflectionClass($this->className); - } catch (\ReflectionException $e) { - // the class does not exist anymore - return false; - } - } - $hash = hash_init('md5'); - - foreach ($this->generateSignature($this->classReflector) as $info) { - hash_update($hash, $info); - } - - return hash_final($hash); - } - - private function generateSignature(\ReflectionClass $class): iterable - { - yield $class->getDocComment(); - yield (int) $class->isFinal(); - yield (int) $class->isAbstract(); - - if ($class->isTrait()) { - yield print_r(class_uses($class->name), true); - } else { - yield print_r(class_parents($class->name), true); - yield print_r(class_implements($class->name), true); - yield print_r($class->getConstants(), true); - } - - if (!$class->isInterface()) { - $defaults = $class->getDefaultProperties(); - - foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED) as $p) { - yield $p->getDocComment().$p; - yield print_r(isset($defaults[$p->name]) && !\is_object($defaults[$p->name]) ? $defaults[$p->name] : null, true); - } - } - - foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) { - $defaults = []; - $parametersWithUndefinedConstants = []; - foreach ($m->getParameters() as $p) { - if (!$p->isDefaultValueAvailable()) { - $defaults[$p->name] = null; - - continue; - } - - if (!$p->isDefaultValueConstant() || \defined($p->getDefaultValueConstantName())) { - $defaults[$p->name] = $p->getDefaultValue(); - - continue; - } - - $defaults[$p->name] = $p->getDefaultValueConstantName(); - $parametersWithUndefinedConstants[$p->name] = true; - } - - if (!$parametersWithUndefinedConstants) { - yield preg_replace('/^ @@.*/m', '', $m); - } else { - $stack = [ - $m->getDocComment(), - $m->getName(), - $m->isAbstract(), - $m->isFinal(), - $m->isStatic(), - $m->isPublic(), - $m->isPrivate(), - $m->isProtected(), - $m->returnsReference(), - $m->hasReturnType() ? $m->getReturnType()->getName() : '', - ]; - - foreach ($m->getParameters() as $p) { - if (!isset($parametersWithUndefinedConstants[$p->name])) { - $stack[] = (string) $p; - } else { - $stack[] = $p->isOptional(); - $stack[] = $p->hasType() ? $p->getType()->getName() : ''; - $stack[] = $p->isPassedByReference(); - $stack[] = $p->isVariadic(); - $stack[] = $p->getName(); - } - } - - yield implode(',', $stack); - } - - yield print_r($defaults, true); - } - - if ($class->isAbstract() || $class->isInterface() || $class->isTrait()) { - return; - } - - if (interface_exists(EventSubscriberInterface::class, false) && $class->isSubclassOf(EventSubscriberInterface::class)) { - yield EventSubscriberInterface::class; - yield print_r($class->name::getSubscribedEvents(), true); - } - - if (interface_exists(MessageSubscriberInterface::class, false) && $class->isSubclassOf(MessageSubscriberInterface::class)) { - yield MessageSubscriberInterface::class; - foreach ($class->name::getHandledMessages() as $key => $value) { - yield $key.print_r($value, true); - } - } - - if (interface_exists(ServiceSubscriberInterface::class, false) && $class->isSubclassOf(ServiceSubscriberInterface::class)) { - yield ServiceSubscriberInterface::class; - yield print_r($class->name::getSubscribedServices(), true); - } - } -} diff --git a/vendor/symfony/config/Resource/ResourceInterface.php b/vendor/symfony/config/Resource/ResourceInterface.php deleted file mode 100644 index d98fd42..0000000 --- a/vendor/symfony/config/Resource/ResourceInterface.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * ResourceInterface is the interface that must be implemented by all Resource classes. - * - * @author Fabien Potencier - */ -interface ResourceInterface -{ - /** - * Returns a string representation of the Resource. - * - * This method is necessary to allow for resource de-duplication, for example by means - * of array_unique(). The string returned need not have a particular meaning, but has - * to be identical for different ResourceInterface instances referring to the same - * resource; and it should be unlikely to collide with that of other, unrelated - * resource instances. - * - * @return string A string representation unique to the underlying Resource - */ - public function __toString(); -} diff --git a/vendor/symfony/config/Resource/SelfCheckingResourceChecker.php b/vendor/symfony/config/Resource/SelfCheckingResourceChecker.php deleted file mode 100644 index eab3323..0000000 --- a/vendor/symfony/config/Resource/SelfCheckingResourceChecker.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -use Symfony\Component\Config\ResourceCheckerInterface; - -/** - * Resource checker for instances of SelfCheckingResourceInterface. - * - * As these resources perform the actual check themselves, we can provide - * this class as a standard way of validating them. - * - * @author Matthias Pigulla - */ -class SelfCheckingResourceChecker implements ResourceCheckerInterface -{ - public function supports(ResourceInterface $metadata) - { - return $metadata instanceof SelfCheckingResourceInterface; - } - - public function isFresh(ResourceInterface $resource, int $timestamp) - { - /* @var SelfCheckingResourceInterface $resource */ - return $resource->isFresh($timestamp); - } -} diff --git a/vendor/symfony/config/Resource/SelfCheckingResourceInterface.php b/vendor/symfony/config/Resource/SelfCheckingResourceInterface.php deleted file mode 100644 index c08d969..0000000 --- a/vendor/symfony/config/Resource/SelfCheckingResourceInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -/** - * Interface for Resources that can check for freshness autonomously, - * without special support from external services. - * - * @author Matthias Pigulla - */ -interface SelfCheckingResourceInterface extends ResourceInterface -{ - /** - * Returns true if the resource has not been updated since the given timestamp. - * - * @param int $timestamp The last time the resource was loaded - * - * @return bool True if the resource has not been updated, false otherwise - */ - public function isFresh(int $timestamp); -} diff --git a/vendor/symfony/config/ResourceCheckerConfigCache.php b/vendor/symfony/config/ResourceCheckerConfigCache.php deleted file mode 100644 index 753ee4d..0000000 --- a/vendor/symfony/config/ResourceCheckerConfigCache.php +++ /dev/null @@ -1,188 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -use Symfony\Component\Config\Resource\ResourceInterface; -use Symfony\Component\Filesystem\Exception\IOException; -use Symfony\Component\Filesystem\Filesystem; - -/** - * ResourceCheckerConfigCache uses instances of ResourceCheckerInterface - * to check whether cached data is still fresh. - * - * @author Matthias Pigulla - */ -class ResourceCheckerConfigCache implements ConfigCacheInterface -{ - /** - * @var string - */ - private $file; - - /** - * @var iterable|ResourceCheckerInterface[] - */ - private $resourceCheckers; - - /** - * @param string $file The absolute cache path - * @param iterable|ResourceCheckerInterface[] $resourceCheckers The ResourceCheckers to use for the freshness check - */ - public function __construct(string $file, iterable $resourceCheckers = []) - { - $this->file = $file; - $this->resourceCheckers = $resourceCheckers; - } - - /** - * {@inheritdoc} - */ - public function getPath() - { - return $this->file; - } - - /** - * Checks if the cache is still fresh. - * - * This implementation will make a decision solely based on the ResourceCheckers - * passed in the constructor. - * - * The first ResourceChecker that supports a given resource is considered authoritative. - * Resources with no matching ResourceChecker will silently be ignored and considered fresh. - * - * @return bool true if the cache is fresh, false otherwise - */ - public function isFresh() - { - if (!is_file($this->file)) { - return false; - } - - if ($this->resourceCheckers instanceof \Traversable && !$this->resourceCheckers instanceof \Countable) { - $this->resourceCheckers = iterator_to_array($this->resourceCheckers); - } - - if (!\count($this->resourceCheckers)) { - return true; // shortcut - if we don't have any checkers we don't need to bother with the meta file at all - } - - $metadata = $this->getMetaFile(); - - if (!is_file($metadata)) { - return false; - } - - $meta = $this->safelyUnserialize($metadata); - - if (false === $meta) { - return false; - } - - $time = filemtime($this->file); - - foreach ($meta as $resource) { - /* @var ResourceInterface $resource */ - foreach ($this->resourceCheckers as $checker) { - if (!$checker->supports($resource)) { - continue; // next checker - } - if ($checker->isFresh($resource, $time)) { - break; // no need to further check this resource - } - - return false; // cache is stale - } - // no suitable checker found, ignore this resource - } - - return true; - } - - /** - * Writes cache. - * - * @param string $content The content to write in the cache - * @param ResourceInterface[] $metadata An array of metadata - * - * @throws \RuntimeException When cache file can't be written - */ - public function write(string $content, array $metadata = null) - { - $mode = 0666; - $umask = umask(); - $filesystem = new Filesystem(); - $filesystem->dumpFile($this->file, $content); - try { - $filesystem->chmod($this->file, $mode, $umask); - } catch (IOException $e) { - // discard chmod failure (some filesystem may not support it) - } - - if (null !== $metadata) { - $filesystem->dumpFile($this->getMetaFile(), serialize($metadata)); - try { - $filesystem->chmod($this->getMetaFile(), $mode, $umask); - } catch (IOException $e) { - // discard chmod failure (some filesystem may not support it) - } - } - - if (\function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN)) { - @opcache_invalidate($this->file, true); - } - } - - /** - * Gets the meta file path. - */ - private function getMetaFile(): string - { - return $this->file.'.meta'; - } - - private function safelyUnserialize(string $file) - { - $meta = false; - $content = file_get_contents($file); - $signalingException = new \UnexpectedValueException(); - $prevUnserializeHandler = ini_set('unserialize_callback_func', self::class.'::handleUnserializeCallback'); - $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler, $signalingException) { - if (__FILE__ === $file) { - throw $signalingException; - } - - return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false; - }); - - try { - $meta = unserialize($content); - } catch (\Throwable $e) { - if ($e !== $signalingException) { - throw $e; - } - } finally { - restore_error_handler(); - ini_set('unserialize_callback_func', $prevUnserializeHandler); - } - - return $meta; - } - - /** - * @internal - */ - public static function handleUnserializeCallback($class) - { - trigger_error('Class not found: '.$class); - } -} diff --git a/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php b/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php deleted file mode 100644 index a789644..0000000 --- a/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -/** - * A ConfigCacheFactory implementation that validates the - * cache with an arbitrary set of ResourceCheckers. - * - * @author Matthias Pigulla - */ -class ResourceCheckerConfigCacheFactory implements ConfigCacheFactoryInterface -{ - private $resourceCheckers = []; - - /** - * @param iterable|ResourceCheckerInterface[] $resourceCheckers - */ - public function __construct(iterable $resourceCheckers = []) - { - $this->resourceCheckers = $resourceCheckers; - } - - /** - * {@inheritdoc} - */ - public function cache(string $file, callable $callable) - { - $cache = new ResourceCheckerConfigCache($file, $this->resourceCheckers); - if (!$cache->isFresh()) { - $callable($cache); - } - - return $cache; - } -} diff --git a/vendor/symfony/config/ResourceCheckerInterface.php b/vendor/symfony/config/ResourceCheckerInterface.php deleted file mode 100644 index 0688f51..0000000 --- a/vendor/symfony/config/ResourceCheckerInterface.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config; - -use Symfony\Component\Config\Resource\ResourceInterface; - -/** - * Interface for ResourceCheckers. - * - * When a ResourceCheckerConfigCache instance is checked for freshness, all its associated - * metadata resources are passed to ResourceCheckers. The ResourceCheckers - * can then inspect the resources and decide whether the cache can be considered - * fresh or not. - * - * @author Matthias Pigulla - * @author Benjamin Klotz - */ -interface ResourceCheckerInterface -{ - /** - * Queries the ResourceChecker whether it can validate a given - * resource or not. - * - * @return bool True if the ResourceChecker can handle this resource type, false if not - */ - public function supports(ResourceInterface $metadata); - - /** - * Validates the resource. - * - * @param int $timestamp The timestamp at which the cache associated with this resource was created - * - * @return bool True if the resource has not changed since the given timestamp, false otherwise - */ - public function isFresh(ResourceInterface $resource, int $timestamp); -} diff --git a/vendor/symfony/config/Util/Exception/InvalidXmlException.php b/vendor/symfony/config/Util/Exception/InvalidXmlException.php deleted file mode 100644 index a335bbd..0000000 --- a/vendor/symfony/config/Util/Exception/InvalidXmlException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Util\Exception; - -/** - * Exception class for when XML parsing with an XSD schema file path or a callable validator produces errors unrelated - * to the actual XML parsing. - * - * @author Ole Rößner - */ -class InvalidXmlException extends XmlParsingException -{ -} diff --git a/vendor/symfony/config/Util/Exception/XmlParsingException.php b/vendor/symfony/config/Util/Exception/XmlParsingException.php deleted file mode 100644 index 9bceed6..0000000 --- a/vendor/symfony/config/Util/Exception/XmlParsingException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Util\Exception; - -/** - * Exception class for when XML cannot be parsed properly. - * - * @author Ole Rößner - */ -class XmlParsingException extends \InvalidArgumentException -{ -} diff --git a/vendor/symfony/config/Util/XmlUtils.php b/vendor/symfony/config/Util/XmlUtils.php deleted file mode 100644 index 0ebeec4..0000000 --- a/vendor/symfony/config/Util/XmlUtils.php +++ /dev/null @@ -1,269 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Util; - -use Symfony\Component\Config\Util\Exception\InvalidXmlException; -use Symfony\Component\Config\Util\Exception\XmlParsingException; - -/** - * XMLUtils is a bunch of utility methods to XML operations. - * - * This class contains static methods only and is not meant to be instantiated. - * - * @author Fabien Potencier - * @author Martin Hasoň - * @author Ole Rößner - */ -class XmlUtils -{ - /** - * This class should not be instantiated. - */ - private function __construct() - { - } - - /** - * Parses an XML string. - * - * @param string $content An XML string - * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation - * - * @return \DOMDocument - * - * @throws XmlParsingException When parsing of XML file returns error - * @throws InvalidXmlException When parsing of XML with schema or callable produces any errors unrelated to the XML parsing itself - * @throws \RuntimeException When DOM extension is missing - */ - public static function parse(string $content, $schemaOrCallable = null) - { - if (!\extension_loaded('dom')) { - throw new \LogicException('Extension DOM is required.'); - } - - $internalErrors = libxml_use_internal_errors(true); - $disableEntities = libxml_disable_entity_loader(true); - libxml_clear_errors(); - - $dom = new \DOMDocument(); - $dom->validateOnParse = true; - if (!$dom->loadXML($content, LIBXML_NONET | (\defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) { - libxml_disable_entity_loader($disableEntities); - - throw new XmlParsingException(implode("\n", static::getXmlErrors($internalErrors))); - } - - $dom->normalizeDocument(); - - libxml_use_internal_errors($internalErrors); - libxml_disable_entity_loader($disableEntities); - - foreach ($dom->childNodes as $child) { - if (XML_DOCUMENT_TYPE_NODE === $child->nodeType) { - throw new XmlParsingException('Document types are not allowed.'); - } - } - - if (null !== $schemaOrCallable) { - $internalErrors = libxml_use_internal_errors(true); - libxml_clear_errors(); - - $e = null; - if (\is_callable($schemaOrCallable)) { - try { - $valid = $schemaOrCallable($dom, $internalErrors); - } catch (\Exception $e) { - $valid = false; - } - } elseif (!\is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) { - $schemaSource = file_get_contents((string) $schemaOrCallable); - $valid = @$dom->schemaValidateSource($schemaSource); - } else { - libxml_use_internal_errors($internalErrors); - - throw new XmlParsingException('The schemaOrCallable argument has to be a valid path to XSD file or callable.'); - } - - if (!$valid) { - $messages = static::getXmlErrors($internalErrors); - if (empty($messages)) { - throw new InvalidXmlException('The XML is not valid.', 0, $e); - } - throw new XmlParsingException(implode("\n", $messages), 0, $e); - } - } - - libxml_clear_errors(); - libxml_use_internal_errors($internalErrors); - - return $dom; - } - - /** - * Loads an XML file. - * - * @param string $file An XML file path - * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation - * - * @return \DOMDocument - * - * @throws \InvalidArgumentException When loading of XML file returns error - * @throws XmlParsingException When XML parsing returns any errors - * @throws \RuntimeException When DOM extension is missing - */ - public static function loadFile(string $file, $schemaOrCallable = null) - { - $content = @file_get_contents($file); - if ('' === trim($content)) { - throw new \InvalidArgumentException(sprintf('File %s does not contain valid XML, it is empty.', $file)); - } - - try { - return static::parse($content, $schemaOrCallable); - } catch (InvalidXmlException $e) { - throw new XmlParsingException(sprintf('The XML file "%s" is not valid.', $file), 0, $e->getPrevious()); - } - } - - /** - * Converts a \DOMElement object to a PHP array. - * - * The following rules applies during the conversion: - * - * * Each tag is converted to a key value or an array - * if there is more than one "value" - * - * * The content of a tag is set under a "value" key (bar) - * if the tag also has some nested tags - * - * * The attributes are converted to keys () - * - * * The nested-tags are converted to keys (bar) - * - * @param \DOMElement $element A \DOMElement instance - * @param bool $checkPrefix Check prefix in an element or an attribute name - * - * @return mixed - */ - public static function convertDomElementToArray(\DOMElement $element, bool $checkPrefix = true) - { - $prefix = (string) $element->prefix; - $empty = true; - $config = []; - foreach ($element->attributes as $name => $node) { - if ($checkPrefix && !\in_array((string) $node->prefix, ['', $prefix], true)) { - continue; - } - $config[$name] = static::phpize($node->value); - $empty = false; - } - - $nodeValue = false; - foreach ($element->childNodes as $node) { - if ($node instanceof \DOMText) { - if ('' !== trim($node->nodeValue)) { - $nodeValue = trim($node->nodeValue); - $empty = false; - } - } elseif ($checkPrefix && $prefix != (string) $node->prefix) { - continue; - } elseif (!$node instanceof \DOMComment) { - $value = static::convertDomElementToArray($node, $checkPrefix); - - $key = $node->localName; - if (isset($config[$key])) { - if (!\is_array($config[$key]) || !\is_int(key($config[$key]))) { - $config[$key] = [$config[$key]]; - } - $config[$key][] = $value; - } else { - $config[$key] = $value; - } - - $empty = false; - } - } - - if (false !== $nodeValue) { - $value = static::phpize($nodeValue); - if (\count($config)) { - $config['value'] = $value; - } else { - $config = $value; - } - } - - return !$empty ? $config : null; - } - - /** - * Converts an xml value to a PHP type. - * - * @param mixed $value - * - * @return mixed - */ - public static function phpize($value) - { - $value = (string) $value; - $lowercaseValue = strtolower($value); - - switch (true) { - case 'null' === $lowercaseValue: - return null; - case ctype_digit($value): - $raw = $value; - $cast = (int) $value; - - return '0' == $value[0] ? octdec($value) : (((string) $raw === (string) $cast) ? $cast : $raw); - case isset($value[1]) && '-' === $value[0] && ctype_digit(substr($value, 1)): - $raw = $value; - $cast = (int) $value; - - return '0' == $value[1] ? octdec($value) : (((string) $raw === (string) $cast) ? $cast : $raw); - case 'true' === $lowercaseValue: - return true; - case 'false' === $lowercaseValue: - return false; - case isset($value[1]) && '0b' == $value[0].$value[1] && preg_match('/^0b[01]*$/', $value): - return bindec($value); - case is_numeric($value): - return '0x' === $value[0].$value[1] ? hexdec($value) : (float) $value; - case preg_match('/^0x[0-9a-f]++$/i', $value): - return hexdec($value); - case preg_match('/^[+-]?[0-9]+(\.[0-9]+)?$/', $value): - return (float) $value; - default: - return $value; - } - } - - protected static function getXmlErrors(bool $internalErrors) - { - $errors = []; - foreach (libxml_get_errors() as $error) { - $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)', - LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', - $error->code, - trim($error->message), - $error->file ?: 'n/a', - $error->line, - $error->column - ); - } - - libxml_clear_errors(); - libxml_use_internal_errors($internalErrors); - - return $errors; - } -} diff --git a/vendor/symfony/config/composer.json b/vendor/symfony/config/composer.json deleted file mode 100644 index cd31eb9..0000000 --- a/vendor/symfony/config/composer.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "symfony/config", - "type": "library", - "description": "Symfony Config Component", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "symfony/filesystem": "^4.4|^5.0", - "symfony/polyfill-ctype": "~1.8" - }, - "require-dev": { - "symfony/event-dispatcher": "^4.4|^5.0", - "symfony/finder": "^4.4|^5.0", - "symfony/messenger": "^4.4|^5.0", - "symfony/service-contracts": "^1.1|^2", - "symfony/yaml": "^4.4|^5.0" - }, - "conflict": { - "symfony/finder": "<4.4" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Config\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/console/.gitattributes b/vendor/symfony/console/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/console/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/console/Application.php b/vendor/symfony/console/Application.php deleted file mode 100644 index 38956d1..0000000 --- a/vendor/symfony/console/Application.php +++ /dev/null @@ -1,1187 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Command\HelpCommand; -use Symfony\Component\Console\Command\ListCommand; -use Symfony\Component\Console\CommandLoader\CommandLoaderInterface; -use Symfony\Component\Console\Event\ConsoleCommandEvent; -use Symfony\Component\Console\Event\ConsoleErrorEvent; -use Symfony\Component\Console\Event\ConsoleTerminateEvent; -use Symfony\Component\Console\Exception\CommandNotFoundException; -use Symfony\Component\Console\Exception\ExceptionInterface; -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Exception\NamespaceNotFoundException; -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Helper\DebugFormatterHelper; -use Symfony\Component\Console\Helper\FormatterHelper; -use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Helper\HelperSet; -use Symfony\Component\Console\Helper\ProcessHelper; -use Symfony\Component\Console\Helper\QuestionHelper; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputAwareInterface; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Input\StreamableInputInterface; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\ErrorHandler\ErrorHandler; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * 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->add(new SimpleCommand()); - * $app->run(); - * - * @author Fabien Potencier - */ -class Application implements ResetInterface -{ - private $commands = []; - private $wantHelps = false; - private $runningCommand; - private $name; - private $version; - private $commandLoader; - private $catchExceptions = true; - private $autoExit = true; - private $definition; - private $helperSet; - private $dispatcher; - private $terminal; - private $defaultCommand; - private $singleCommand = false; - private $initialized; - - public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN') - { - $this->name = $name; - $this->version = $version; - $this->terminal = new Terminal(); - $this->defaultCommand = 'list'; - } - - /** - * @final - */ - public function setDispatcher(EventDispatcherInterface $dispatcher) - { - $this->dispatcher = $dispatcher; - } - - public function setCommandLoader(CommandLoaderInterface $commandLoader) - { - $this->commandLoader = $commandLoader; - } - - /** - * Runs the current application. - * - * @return int 0 if everything went fine, or an error code - * - * @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}. - */ - public function run(InputInterface $input = null, OutputInterface $output = null) - { - putenv('LINES='.$this->terminal->getHeight()); - putenv('COLUMNS='.$this->terminal->getWidth()); - - if (null === $input) { - $input = new ArgvInput(); - } - - if (null === $output) { - $output = new ConsoleOutput(); - } - - $renderException = function (\Throwable $e) use ($output) { - if ($output instanceof ConsoleOutputInterface) { - $this->renderThrowable($e, $output->getErrorOutput()); - } else { - $this->renderThrowable($e, $output); - } - }; - if ($phpHandler = set_exception_handler($renderException)) { - restore_exception_handler(); - if (!\is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) { - $errorHandler = true; - } elseif ($errorHandler = $phpHandler[0]->setExceptionHandler($renderException)) { - $phpHandler[0]->setExceptionHandler($errorHandler); - } - } - - $this->configureIO($input, $output); - - try { - $exitCode = $this->doRun($input, $output); - } catch (\Exception $e) { - if (!$this->catchExceptions) { - throw $e; - } - - $renderException($e); - - $exitCode = $e->getCode(); - if (is_numeric($exitCode)) { - $exitCode = (int) $exitCode; - if (0 === $exitCode) { - $exitCode = 1; - } - } else { - $exitCode = 1; - } - } finally { - // if the exception handler changed, keep it - // otherwise, unregister $renderException - if (!$phpHandler) { - if (set_exception_handler($renderException) === $renderException) { - restore_exception_handler(); - } - restore_exception_handler(); - } elseif (!$errorHandler) { - $finalHandler = $phpHandler[0]->setExceptionHandler(null); - if ($finalHandler !== $renderException) { - $phpHandler[0]->setExceptionHandler($finalHandler); - } - } - } - - if ($this->autoExit) { - if ($exitCode > 255) { - $exitCode = 255; - } - - exit($exitCode); - } - - return $exitCode; - } - - /** - * Runs the current application. - * - * @return int 0 if everything went fine, or an error code - */ - public function doRun(InputInterface $input, OutputInterface $output) - { - if (true === $input->hasParameterOption(['--version', '-V'], true)) { - $output->writeln($this->getLongVersion()); - - return 0; - } - - try { - // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument. - $input->bind($this->getDefinition()); - } catch (ExceptionInterface $e) { - // Errors must be ignored, full binding/validation happens later when the command is known. - } - - $name = $this->getCommandName($input); - if (true === $input->hasParameterOption(['--help', '-h'], true)) { - if (!$name) { - $name = 'help'; - $input = new ArrayInput(['command_name' => $this->defaultCommand]); - } else { - $this->wantHelps = true; - } - } - - if (!$name) { - $name = $this->defaultCommand; - $definition = $this->getDefinition(); - $definition->setArguments(array_merge( - $definition->getArguments(), - [ - 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name), - ] - )); - } - - try { - $this->runningCommand = null; - // the command name MUST be the first element of the input - $command = $this->find($name); - } catch (\Throwable $e) { - if (!($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException) || 1 !== \count($alternatives = $e->getAlternatives()) || !$input->isInteractive()) { - if (null !== $this->dispatcher) { - $event = new ConsoleErrorEvent($input, $output, $e); - $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); - - if (0 === $event->getExitCode()) { - return 0; - } - - $e = $event->getError(); - } - - throw $e; - } - - $alternative = $alternatives[0]; - - $style = new SymfonyStyle($input, $output); - $style->block(sprintf("\nCommand \"%s\" is not defined.\n", $name), null, 'error'); - if (!$style->confirm(sprintf('Do you want to run "%s" instead? ', $alternative), false)) { - if (null !== $this->dispatcher) { - $event = new ConsoleErrorEvent($input, $output, $e); - $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); - - return $event->getExitCode(); - } - - return 1; - } - - $command = $this->find($alternative); - } - - $this->runningCommand = $command; - $exitCode = $this->doRunCommand($command, $input, $output); - $this->runningCommand = null; - - return $exitCode; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - } - - 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() - { - if (!$this->helperSet) { - $this->helperSet = $this->getDefaultHelperSet(); - } - - return $this->helperSet; - } - - public function setDefinition(InputDefinition $definition) - { - $this->definition = $definition; - } - - /** - * Gets the InputDefinition related to this Application. - * - * @return InputDefinition The InputDefinition instance - */ - public function getDefinition() - { - if (!$this->definition) { - $this->definition = $this->getDefaultInputDefinition(); - } - - if ($this->singleCommand) { - $inputDefinition = $this->definition; - $inputDefinition->setArguments(); - - return $inputDefinition; - } - - return $this->definition; - } - - /** - * Gets the help message. - * - * @return string A help message - */ - public function getHelp() - { - return $this->getLongVersion(); - } - - /** - * Gets whether to catch exceptions or not during commands execution. - * - * @return bool Whether to catch exceptions or not during commands execution - */ - public function areExceptionsCaught() - { - return $this->catchExceptions; - } - - /** - * Sets whether to catch exceptions or not during commands execution. - */ - public function setCatchExceptions(bool $boolean) - { - $this->catchExceptions = $boolean; - } - - /** - * Gets whether to automatically exit after a command execution or not. - * - * @return bool Whether to automatically exit after a command execution or not - */ - public function isAutoExitEnabled() - { - return $this->autoExit; - } - - /** - * Sets whether to automatically exit after a command execution or not. - */ - public function setAutoExit(bool $boolean) - { - $this->autoExit = $boolean; - } - - /** - * Gets the name of the application. - * - * @return string The application name - */ - public function getName() - { - return $this->name; - } - - /** - * Sets the application name. - **/ - public function setName(string $name) - { - $this->name = $name; - } - - /** - * Gets the application version. - * - * @return string The application version - */ - public function getVersion() - { - return $this->version; - } - - /** - * Sets the application version. - */ - public function setVersion(string $version) - { - $this->version = $version; - } - - /** - * Returns the long version of the application. - * - * @return string The long application version - */ - public function getLongVersion() - { - if ('UNKNOWN' !== $this->getName()) { - if ('UNKNOWN' !== $this->getVersion()) { - return sprintf('%s %s', $this->getName(), $this->getVersion()); - } - - return $this->getName(); - } - - return 'Console Tool'; - } - - /** - * Registers a new command. - * - * @return Command The newly created command - */ - public function register(string $name) - { - return $this->add(new Command($name)); - } - - /** - * Adds an array of command objects. - * - * If a Command is not enabled it will not be added. - * - * @param Command[] $commands An array of commands - */ - public function addCommands(array $commands) - { - foreach ($commands as $command) { - $this->add($command); - } - } - - /** - * Adds a command object. - * - * If a command with the same name already exists, it will be overridden. - * If the command is not enabled it will not be added. - * - * @return Command|null The registered command if enabled or null - */ - public function add(Command $command) - { - $this->init(); - - $command->setApplication($this); - - if (!$command->isEnabled()) { - $command->setApplication(null); - - return null; - } - - // Will throw if the command is not correctly initialized. - $command->getDefinition(); - - if (!$command->getName()) { - throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', \get_class($command))); - } - - $this->commands[$command->getName()] = $command; - - foreach ($command->getAliases() as $alias) { - $this->commands[$alias] = $command; - } - - return $command; - } - - /** - * Returns a registered command by name or alias. - * - * @return Command A Command object - * - * @throws CommandNotFoundException When given command name does not exist - */ - public function get(string $name) - { - $this->init(); - - if (!$this->has($name)) { - throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); - } - - $command = $this->commands[$name]; - - if ($this->wantHelps) { - $this->wantHelps = false; - - $helpCommand = $this->get('help'); - $helpCommand->setCommand($command); - - return $helpCommand; - } - - return $command; - } - - /** - * Returns true if the command exists, false otherwise. - * - * @return bool true if the command exists, false otherwise - */ - public function has(string $name) - { - $this->init(); - - return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name) && $this->add($this->commandLoader->get($name))); - } - - /** - * Returns an array of all unique namespaces used by currently registered commands. - * - * It does not return the global namespace which always exists. - * - * @return string[] An array of namespaces - */ - public function getNamespaces() - { - $namespaces = []; - foreach ($this->all() as $command) { - if ($command->isHidden()) { - continue; - } - - $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName())); - - foreach ($command->getAliases() as $alias) { - $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias)); - } - } - - return array_values(array_unique(array_filter($namespaces))); - } - - /** - * Finds a registered namespace by a name or an abbreviation. - * - * @return string A registered namespace - * - * @throws NamespaceNotFoundException When namespace is incorrect or ambiguous - */ - public function findNamespace(string $namespace) - { - $allNamespaces = $this->getNamespaces(); - $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace); - $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces); - - if (empty($namespaces)) { - $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); - - if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) { - if (1 == \count($alternatives)) { - $message .= "\n\nDid you mean this?\n "; - } else { - $message .= "\n\nDid you mean one of these?\n "; - } - - $message .= implode("\n ", $alternatives); - } - - throw new NamespaceNotFoundException($message, $alternatives); - } - - $exact = \in_array($namespace, $namespaces, true); - if (\count($namespaces) > 1 && !$exact) { - throw new NamespaceNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); - } - - return $exact ? $namespace : reset($namespaces); - } - - /** - * Finds a command by name or alias. - * - * Contrary to get, this command tries to find the best - * match if you give it an abbreviation of a name or alias. - * - * @return Command A Command instance - * - * @throws CommandNotFoundException When command name is incorrect or ambiguous - */ - public function find(string $name) - { - $this->init(); - - $aliases = []; - - foreach ($this->commands as $command) { - foreach ($command->getAliases() as $alias) { - if (!$this->has($alias)) { - $this->commands[$alias] = $command; - } - } - } - - if ($this->has($name)) { - return $this->get($name); - } - - $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands); - $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); - $commands = preg_grep('{^'.$expr.'}', $allCommands); - - if (empty($commands)) { - $commands = preg_grep('{^'.$expr.'}i', $allCommands); - } - - // if no commands matched or we just matched namespaces - if (empty($commands) || \count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) { - if (false !== $pos = strrpos($name, ':')) { - // check if a namespace exists and contains commands - $this->findNamespace(substr($name, 0, $pos)); - } - - $message = sprintf('Command "%s" is not defined.', $name); - - if ($alternatives = $this->findAlternatives($name, $allCommands)) { - // remove hidden commands - $alternatives = array_filter($alternatives, function ($name) { - return !$this->get($name)->isHidden(); - }); - - if (1 == \count($alternatives)) { - $message .= "\n\nDid you mean this?\n "; - } else { - $message .= "\n\nDid you mean one of these?\n "; - } - $message .= implode("\n ", $alternatives); - } - - throw new CommandNotFoundException($message, array_values($alternatives)); - } - - // filter out aliases for commands which are already on the list - if (\count($commands) > 1) { - $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands; - $commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) { - $commandName = $commandList[$nameOrAlias] instanceof Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias; - $aliases[$nameOrAlias] = $commandName; - - return $commandName === $nameOrAlias || !\in_array($commandName, $commands); - })); - } - - if (\count($commands) > 1) { - $usableWidth = $this->terminal->getWidth() - 10; - $abbrevs = array_values($commands); - $maxLen = 0; - foreach ($abbrevs as $abbrev) { - $maxLen = max(Helper::strlen($abbrev), $maxLen); - } - $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen, &$commands) { - if (!$commandList[$cmd] instanceof Command) { - $commandList[$cmd] = $this->commandLoader->get($cmd); - } - - if ($commandList[$cmd]->isHidden()) { - unset($commands[array_search($cmd, $commands)]); - - return false; - } - - $abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription(); - - return Helper::strlen($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev; - }, array_values($commands)); - - if (\count($commands) > 1) { - $suggestions = $this->getAbbreviationSuggestions(array_filter($abbrevs)); - - throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s", $name, $suggestions), array_values($commands)); - } - } - - $command = $this->get(reset($commands)); - - if ($command->isHidden()) { - throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); - } - - return $command; - } - - /** - * Gets the commands (registered in the given namespace if provided). - * - * The array keys are the full names and the values the command instances. - * - * @return Command[] An array of Command instances - */ - public function all(string $namespace = null) - { - $this->init(); - - if (null === $namespace) { - if (!$this->commandLoader) { - return $this->commands; - } - - $commands = $this->commands; - foreach ($this->commandLoader->getNames() as $name) { - if (!isset($commands[$name]) && $this->has($name)) { - $commands[$name] = $this->get($name); - } - } - - return $commands; - } - - $commands = []; - foreach ($this->commands as $name => $command) { - if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { - $commands[$name] = $command; - } - } - - if ($this->commandLoader) { - foreach ($this->commandLoader->getNames() as $name) { - if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1) && $this->has($name)) { - $commands[$name] = $this->get($name); - } - } - } - - return $commands; - } - - /** - * Returns an array of possible abbreviations given a set of names. - * - * @return string[][] An array of abbreviations - */ - public static function getAbbreviations(array $names) - { - $abbrevs = []; - foreach ($names as $name) { - for ($len = \strlen($name); $len > 0; --$len) { - $abbrev = substr($name, 0, $len); - $abbrevs[$abbrev][] = $name; - } - } - - return $abbrevs; - } - - public function renderThrowable(\Throwable $e, OutputInterface $output): void - { - $output->writeln('', OutputInterface::VERBOSITY_QUIET); - - $this->doRenderThrowable($e, $output); - - if (null !== $this->runningCommand) { - $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET); - $output->writeln('', OutputInterface::VERBOSITY_QUIET); - } - } - - protected function doRenderThrowable(\Throwable $e, OutputInterface $output): void - { - do { - $message = trim($e->getMessage()); - if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $class = \get_class($e); - $class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; - $title = sprintf(' [%s%s] ', $class, 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : ''); - $len = Helper::strlen($title); - } else { - $len = 0; - } - - if (false !== strpos($message, "class@anonymous\0")) { - $message = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:)[0-9a-fA-F]++/', function ($m) { - return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0]; - }, $message); - } - - $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX; - $lines = []; - foreach ('' !== $message ? preg_split('/\r?\n/', $message) : [] as $line) { - foreach ($this->splitStringByWidth($line, $width - 4) as $line) { - // pre-format lines to get the right string length - $lineLength = Helper::strlen($line) + 4; - $lines[] = [$line, $lineLength]; - - $len = max($lineLength, $len); - } - } - - $messages = []; - if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $messages[] = sprintf('%s', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); - } - $messages[] = $emptyLine = sprintf('%s', str_repeat(' ', $len)); - if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $messages[] = sprintf('%s%s', $title, str_repeat(' ', max(0, $len - Helper::strlen($title)))); - } - foreach ($lines as $line) { - $messages[] = sprintf(' %s %s', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1])); - } - $messages[] = $emptyLine; - $messages[] = ''; - - $output->writeln($messages, OutputInterface::VERBOSITY_QUIET); - - if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $output->writeln('Exception trace:', OutputInterface::VERBOSITY_QUIET); - - // exception related properties - $trace = $e->getTrace(); - - array_unshift($trace, [ - 'function' => '', - 'file' => $e->getFile() ?: 'n/a', - 'line' => $e->getLine() ?: 'n/a', - 'args' => [], - ]); - - 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 = isset($trace[$i]['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 at %s:%s', $class, $function ? $type.$function.'()' : '', $file, $line), OutputInterface::VERBOSITY_QUIET); - } - - $output->writeln('', OutputInterface::VERBOSITY_QUIET); - } - } while ($e = $e->getPrevious()); - } - - /** - * Configures the input and output instances based on the user arguments and options. - */ - protected function configureIO(InputInterface $input, OutputInterface $output) - { - if (true === $input->hasParameterOption(['--ansi'], true)) { - $output->setDecorated(true); - } elseif (true === $input->hasParameterOption(['--no-ansi'], true)) { - $output->setDecorated(false); - } - - if (true === $input->hasParameterOption(['--no-interaction', '-n'], true)) { - $input->setInteractive(false); - } else { - $inputStream = null; - - if ($input instanceof StreamableInputInterface) { - $inputStream = $input->getStream(); - } - - $inputStream = !$inputStream && \defined('STDIN') ? STDIN : $inputStream; - - if ((!$inputStream || !stream_isatty($inputStream)) && false === getenv('SHELL_INTERACTIVE')) { - $input->setInteractive(false); - } - } - - switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) { - case -1: $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); break; - case 1: $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); break; - case 2: $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); break; - case 3: $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); break; - default: $shellVerbosity = 0; break; - } - - if (true === $input->hasParameterOption(['--quiet', '-q'], true)) { - $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); - $shellVerbosity = -1; - } else { - if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) { - $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); - $shellVerbosity = 3; - } elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || 2 === $input->getParameterOption('--verbose', false, true)) { - $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); - $shellVerbosity = 2; - } elseif ($input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true)) { - $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); - $shellVerbosity = 1; - } - } - - if (-1 === $shellVerbosity) { - $input->setInteractive(false); - } - - putenv('SHELL_VERBOSITY='.$shellVerbosity); - $_ENV['SHELL_VERBOSITY'] = $shellVerbosity; - $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity; - } - - /** - * Runs the current command. - * - * If an event dispatcher has been attached to the application, - * events are also dispatched during the life-cycle of the command. - * - * @return int 0 if everything went fine, or an error code - */ - protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) - { - foreach ($command->getHelperSet() as $helper) { - if ($helper instanceof InputAwareInterface) { - $helper->setInput($input); - } - } - - if (null === $this->dispatcher) { - return $command->run($input, $output); - } - - // bind before the console.command event, so the listeners have access to input options/arguments - try { - $command->mergeApplicationDefinition(); - $input->bind($command->getDefinition()); - } catch (ExceptionInterface $e) { - // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition - } - - $event = new ConsoleCommandEvent($command, $input, $output); - $e = null; - - try { - $this->dispatcher->dispatch($event, ConsoleEvents::COMMAND); - - if ($event->commandShouldRun()) { - $exitCode = $command->run($input, $output); - } else { - $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED; - } - } catch (\Throwable $e) { - $event = new ConsoleErrorEvent($input, $output, $e, $command); - $this->dispatcher->dispatch($event, ConsoleEvents::ERROR); - $e = $event->getError(); - - if (0 === $exitCode = $event->getExitCode()) { - $e = null; - } - } - - $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); - $this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE); - - if (null !== $e) { - throw $e; - } - - return $event->getExitCode(); - } - - /** - * Gets the name of the command based on input. - * - * @return string|null - */ - protected function getCommandName(InputInterface $input) - { - return $this->singleCommand ? $this->defaultCommand : $input->getFirstArgument(); - } - - /** - * Gets the default input definition. - * - * @return InputDefinition An InputDefinition instance - */ - protected function getDefaultInputDefinition() - { - return new InputDefinition([ - new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), - - new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'), - new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'), - new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), - new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'), - new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'), - new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'), - new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'), - ]); - } - - /** - * Gets the default commands that should always be available. - * - * @return Command[] An array of default Command instances - */ - protected function getDefaultCommands() - { - return [new HelpCommand(), new ListCommand()]; - } - - /** - * Gets the default helper set with the helpers that should always be available. - * - * @return HelperSet A HelperSet instance - */ - protected function getDefaultHelperSet() - { - return new HelperSet([ - new FormatterHelper(), - new DebugFormatterHelper(), - new ProcessHelper(), - new QuestionHelper(), - ]); - } - - /** - * Returns abbreviated suggestions in string format. - */ - private function getAbbreviationSuggestions(array $abbrevs): string - { - return ' '.implode("\n ", $abbrevs); - } - - /** - * Returns the namespace part of the command name. - * - * This method is not part of public API and should not be used directly. - * - * @return string The namespace of the command - */ - public function extractNamespace(string $name, int $limit = null) - { - $parts = explode(':', $name, -1); - - return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit)); - } - - /** - * Finds alternative of $name among $collection, - * if nothing is found in $collection, try in $abbrevs. - * - * @return string[] A sorted array of similar string - */ - private function findAlternatives(string $name, iterable $collection): array - { - $threshold = 1e3; - $alternatives = []; - - $collectionParts = []; - foreach ($collection as $item) { - $collectionParts[$item] = explode(':', $item); - } - - foreach (explode(':', $name) as $i => $subname) { - foreach ($collectionParts as $collectionName => $parts) { - $exists = isset($alternatives[$collectionName]); - if (!isset($parts[$i]) && $exists) { - $alternatives[$collectionName] += $threshold; - continue; - } elseif (!isset($parts[$i])) { - continue; - } - - $lev = levenshtein($subname, $parts[$i]); - if ($lev <= \strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) { - $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev; - } elseif ($exists) { - $alternatives[$collectionName] += $threshold; - } - } - } - - foreach ($collection as $item) { - $lev = levenshtein($name, $item); - if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) { - $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; - } - } - - $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; }); - ksort($alternatives, SORT_NATURAL | SORT_FLAG_CASE); - - return array_keys($alternatives); - } - - /** - * Sets the default Command name. - * - * @return self - */ - public function setDefaultCommand(string $commandName, bool $isSingleCommand = false) - { - $this->defaultCommand = $commandName; - - if ($isSingleCommand) { - // Ensure the command exist - $this->find($commandName); - - $this->singleCommand = true; - } - - return $this; - } - - /** - * @internal - */ - public function isSingleCommand(): bool - { - return $this->singleCommand; - } - - private function splitStringByWidth(string $string, int $width): array - { - // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly. - // additionally, array_slice() is not enough as some character has doubled width. - // we need a function to split string not by character count but by string width - if (false === $encoding = mb_detect_encoding($string, null, true)) { - return str_split($string, $width); - } - - $utf8String = mb_convert_encoding($string, 'utf8', $encoding); - $lines = []; - $line = ''; - - $offset = 0; - while (preg_match('/.{1,10000}/u', $utf8String, $m, 0, $offset)) { - $offset += \strlen($m[0]); - - foreach (preg_split('//u', $m[0]) as $char) { - // test if $char could be appended to current line - if (mb_strwidth($line.$char, 'utf8') <= $width) { - $line .= $char; - continue; - } - // if not, push current line to array and make new line - $lines[] = str_pad($line, $width); - $line = $char; - } - } - - $lines[] = \count($lines) ? str_pad($line, $width) : $line; - - mb_convert_variables($encoding, 'utf8', $lines); - - return $lines; - } - - /** - * Returns all namespaces of the command name. - * - * @return string[] The namespaces of the command - */ - private function extractAllNamespaces(string $name): array - { - // -1 as third argument is needed to skip the command short name when exploding - $parts = explode(':', $name, -1); - $namespaces = []; - - foreach ($parts as $part) { - if (\count($namespaces)) { - $namespaces[] = end($namespaces).':'.$part; - } else { - $namespaces[] = $part; - } - } - - return $namespaces; - } - - private function init() - { - if ($this->initialized) { - return; - } - $this->initialized = true; - - foreach ($this->getDefaultCommands() as $command) { - $this->add($command); - } - } -} diff --git a/vendor/symfony/console/CHANGELOG.md b/vendor/symfony/console/CHANGELOG.md deleted file mode 100644 index 3273efb..0000000 --- a/vendor/symfony/console/CHANGELOG.md +++ /dev/null @@ -1,178 +0,0 @@ -CHANGELOG -========= - -5.0.0 ------ - - * removed support for finding hidden commands using an abbreviation, use the full name instead - * removed `TableStyle::setCrossingChar()` method in favor of `TableStyle::setDefaultCrossingChar()` - * removed `TableStyle::setHorizontalBorderChar()` method in favor of `TableStyle::setDefaultCrossingChars()` - * removed `TableStyle::getHorizontalBorderChar()` method in favor of `TableStyle::getBorderChars()` - * removed `TableStyle::setVerticalBorderChar()` method in favor of `TableStyle::setVerticalBorderChars()` - * removed `TableStyle::getVerticalBorderChar()` method in favor of `TableStyle::getBorderChars()` - * removed support for returning `null` from `Command::execute()`, return `0` instead - * `ProcessHelper::run()` accepts only `array|Symfony\Component\Process\Process` for its `command` argument - * `Application::setDispatcher` accepts only `Symfony\Contracts\EventDispatcher\EventDispatcherInterface` - for its `dispatcher` argument - * renamed `Application::renderException()` and `Application::doRenderException()` - to `renderThrowable()` and `doRenderThrowable()` respectively. - -4.4.0 ------ - - * deprecated finding hidden commands using an abbreviation, use the full name instead - * added `Question::setTrimmable` default to true to allow the answer to be trimmed - * added method `minSecondsBetweenRedraws()` and `maxSecondsBetweenRedraws()` on `ProgressBar` - * `Application` implements `ResetInterface` - * marked all dispatched event classes as `@final` - * added support for displaying table horizontally - * deprecated returning `null` from `Command::execute()`, return `0` instead - * Deprecated the `Application::renderException()` and `Application::doRenderException()` methods, - use `renderThrowable()` and `doRenderThrowable()` instead. - * added support for the `NO_COLOR` env var (https://no-color.org/) - -4.3.0 ------ - - * added support for hyperlinks - * added `ProgressBar::iterate()` method that simplify updating the progress bar when iterating - * added `Question::setAutocompleterCallback()` to provide a callback function - that dynamically generates suggestions as the user types - -4.2.0 ------ - - * allowed passing commands as `[$process, 'ENV_VAR' => 'value']` to - `ProcessHelper::run()` to pass environment variables - * deprecated passing a command as a string to `ProcessHelper::run()`, - pass it the command as an array of its arguments instead - * made the `ProcessHelper` class final - * added `WrappableOutputFormatterInterface::formatAndWrap()` (implemented in `OutputFormatter`) - * added `capture_stderr_separately` option to `CommandTester::execute()` - -4.1.0 ------ - - * added option to run suggested command if command is not found and only 1 alternative is available - * added option to modify console output and print multiple modifiable sections - * added support for iterable messages in output `write` and `writeln` methods - -4.0.0 ------ - - * `OutputFormatter` throws an exception when unknown options are used - * removed `QuestionHelper::setInputStream()/getInputStream()` - * removed `Application::getTerminalWidth()/getTerminalHeight()` and - `Application::setTerminalDimensions()/getTerminalDimensions()` -* removed `ConsoleExceptionEvent` -* removed `ConsoleEvents::EXCEPTION` - -3.4.0 ------ - - * added `SHELL_VERBOSITY` env var to control verbosity - * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11 - `ContainerCommandLoader` for commands lazy-loading - * added a case-insensitive command name matching fallback - * added static `Command::$defaultName/getDefaultName()`, allowing for - commands to be registered at compile time in the application command loader. - Setting the `$defaultName` property avoids the need for filling the `command` - attribute on the `console.command` tag when using `AddConsoleCommandPass`. - -3.3.0 ------ - -* added `ExceptionListener` -* added `AddConsoleCommandPass` (originally in FrameworkBundle) -* [BC BREAK] `Input::getOption()` no longer returns the default value for options - with value optional explicitly passed empty -* added console.error event to catch exceptions thrown by other listeners -* deprecated console.exception event in favor of console.error -* added ability to handle `CommandNotFoundException` through the - `console.error` event -* deprecated default validation in `SymfonyQuestionHelper::ask` - -3.2.0 ------- - -* added `setInputs()` method to CommandTester for ease testing of commands expecting inputs -* added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface) -* added StreamableInputInterface -* added LockableTrait - -3.1.0 ------ - - * added truncate method to FormatterHelper - * added setColumnWidth(s) method to Table - -2.8.3 ------ - - * remove readline support from the question helper as it caused issues - -2.8.0 ------ - - * use readline for user input in the question helper when available to allow - the use of arrow keys - -2.6.0 ------ - - * added a Process helper - * added a DebugFormatter helper - -2.5.0 ------ - - * deprecated the dialog helper (use the question helper instead) - * deprecated TableHelper in favor of Table - * deprecated ProgressHelper in favor of ProgressBar - * added ConsoleLogger - * added a question helper - * added a way to set the process name of a command - * added a way to set a default command instead of `ListCommand` - -2.4.0 ------ - - * added a way to force terminal dimensions - * added a convenient method to detect verbosity level - * [BC BREAK] made descriptors use output instead of returning a string - -2.3.0 ------ - - * added multiselect support to the select dialog helper - * added Table Helper for tabular data rendering - * added support for events in `Application` - * added a way to normalize EOLs in `ApplicationTester::getDisplay()` and `CommandTester::getDisplay()` - * added a way to set the progress bar progress via the `setCurrent` method - * added support for multiple InputOption shortcuts, written as `'-a|-b|-c'` - * added two additional verbosity levels, VERBOSITY_VERY_VERBOSE and VERBOSITY_DEBUG - -2.2.0 ------ - - * added support for colorization on Windows via ConEmu - * add a method to Dialog Helper to ask for a question and hide the response - * added support for interactive selections in console (DialogHelper::select()) - * added support for autocompletion as you type in Dialog Helper - -2.1.0 ------ - - * added ConsoleOutputInterface - * added the possibility to disable a command (Command::isEnabled()) - * added suggestions when a command does not exist - * added a --raw option to the list command - * added support for STDERR in the console output class (errors are now sent - to STDERR) - * made the defaults (helper set, commands, input definition) in Application - more easily customizable - * added support for the shell even if readline is not available - * added support for process isolation in Symfony shell via - `--process-isolation` switch - * added support for `--`, which disables options parsing after that point - (tokens will be parsed as arguments) diff --git a/vendor/symfony/console/Command/Command.php b/vendor/symfony/console/Command/Command.php deleted file mode 100644 index b7bf16c..0000000 --- a/vendor/symfony/console/Command/Command.php +++ /dev/null @@ -1,642 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Exception\ExceptionInterface; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Helper\HelperSet; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Base class for all commands. - * - * @author Fabien Potencier - */ -class Command -{ - /** - * @var string|null The default command name - */ - protected static $defaultName; - - private $application; - private $name; - private $processTitle; - private $aliases = []; - private $definition; - private $hidden = false; - private $help = ''; - private $description = ''; - private $ignoreValidationErrors = false; - private $applicationDefinitionMerged = false; - private $applicationDefinitionMergedWithArgs = false; - private $code; - private $synopsis = []; - private $usages = []; - private $helperSet; - - /** - * @return string|null The default command name or null when no default name is set - */ - public static function getDefaultName() - { - $class = \get_called_class(); - $r = new \ReflectionProperty($class, 'defaultName'); - - return $class === $r->class ? static::$defaultName : null; - } - - /** - * @param string|null $name The name of the command; passing null means it must be set in configure() - * - * @throws LogicException When the command name is empty - */ - public function __construct(string $name = null) - { - $this->definition = new InputDefinition(); - - if (null !== $name || null !== $name = static::getDefaultName()) { - $this->setName($name); - } - - $this->configure(); - } - - /** - * Ignores validation errors. - * - * This is mainly useful for the help command. - */ - public function ignoreValidationErrors() - { - $this->ignoreValidationErrors = true; - } - - public function setApplication(Application $application = null) - { - $this->application = $application; - if ($application) { - $this->setHelperSet($application->getHelperSet()); - } else { - $this->helperSet = null; - } - } - - public function setHelperSet(HelperSet $helperSet) - { - $this->helperSet = $helperSet; - } - - /** - * Gets the helper set. - * - * @return HelperSet|null A HelperSet instance - */ - public function getHelperSet() - { - return $this->helperSet; - } - - /** - * Gets the application instance for this command. - * - * @return Application|null An Application instance - */ - public function getApplication() - { - return $this->application; - } - - /** - * Checks whether the command is enabled or not in the current environment. - * - * Override this to check for x or y and return false if the command can not - * run properly under the current conditions. - * - * @return bool - */ - public function isEnabled() - { - return true; - } - - /** - * Configures the current command. - */ - protected function configure() - { - } - - /** - * Executes the current command. - * - * This method is not abstract because you can use this class - * as a concrete class. In this case, instead of defining the - * execute() method, you set the code to execute by passing - * a Closure to the setCode() method. - * - * @return int 0 if everything went fine, or an exit code - * - * @throws LogicException When this abstract method is not implemented - * - * @see setCode() - */ - 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. - * - * This method is executed before the InputDefinition is validated. - * This means that this is the only place where the command can - * interactively ask for values of missing required arguments. - */ - protected function interact(InputInterface $input, OutputInterface $output) - { - } - - /** - * Initializes the command after the input has been bound and before the input - * is 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. - * - * @see InputInterface::bind() - * @see InputInterface::validate() - */ - protected function initialize(InputInterface $input, OutputInterface $output) - { - } - - /** - * Runs the command. - * - * The code to execute is either defined directly with the - * setCode() method or by overriding the execute() method - * in a sub-class. - * - * @return int The command exit code - * - * @throws \Exception When binding input fails. Bypass this by calling {@link ignoreValidationErrors()}. - * - * @see setCode() - * @see execute() - */ - public function run(InputInterface $input, OutputInterface $output) - { - // force the creation of the synopsis before the merge with the app definition - $this->getSynopsis(true); - $this->getSynopsis(false); - - // add the application arguments and options - $this->mergeApplicationDefinition(); - - // bind the input against the command specific arguments/options - try { - $input->bind($this->definition); - } catch (ExceptionInterface $e) { - if (!$this->ignoreValidationErrors) { - throw $e; - } - } - - $this->initialize($input, $output); - - if (null !== $this->processTitle) { - if (\function_exists('cli_set_process_title')) { - if (!@cli_set_process_title($this->processTitle)) { - if ('Darwin' === PHP_OS) { - $output->writeln('Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.', OutputInterface::VERBOSITY_VERY_VERBOSE); - } else { - cli_set_process_title($this->processTitle); - } - } - } elseif (\function_exists('setproctitle')) { - setproctitle($this->processTitle); - } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) { - $output->writeln('Install the proctitle PECL to be able to change the process title.'); - } - } - - if ($input->isInteractive()) { - $this->interact($input, $output); - } - - // The command name argument is often omitted when a command is executed directly with its run() method. - // It would fail the validation if we didn't make sure the command argument is present, - // since it's required by the application. - if ($input->hasArgument('command') && null === $input->getArgument('command')) { - $input->setArgument('command', $this->getName()); - } - - $input->validate(); - - if ($this->code) { - $statusCode = ($this->code)($input, $output); - } else { - $statusCode = $this->execute($input, $output); - - if (!\is_int($statusCode)) { - throw new \TypeError(sprintf('Return value of "%s::execute()" must be of the type int, %s returned.', \get_class($this), \gettype($statusCode))); - } - } - - return is_numeric($statusCode) ? (int) $statusCode : 0; - } - - /** - * Sets the code to execute when running this command. - * - * If this method is used, it overrides the code defined - * in the execute() method. - * - * @param callable $code A callable(InputInterface $input, OutputInterface $output) - * - * @return $this - * - * @throws InvalidArgumentException - * - * @see execute() - */ - public function setCode(callable $code) - { - if ($code instanceof \Closure) { - $r = new \ReflectionFunction($code); - if (null === $r->getClosureThis()) { - $code = \Closure::bind($code, $this); - } - } - - $this->code = $code; - - return $this; - } - - /** - * Merges the application definition with the command definition. - * - * This method is not part of public API and should not be used directly. - * - * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments - */ - public function mergeApplicationDefinition(bool $mergeArgs = true) - { - if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) { - return; - } - - $this->definition->addOptions($this->application->getDefinition()->getOptions()); - - $this->applicationDefinitionMerged = true; - - if ($mergeArgs) { - $currentArguments = $this->definition->getArguments(); - $this->definition->setArguments($this->application->getDefinition()->getArguments()); - $this->definition->addArguments($currentArguments); - - $this->applicationDefinitionMergedWithArgs = true; - } - } - - /** - * Sets an array of argument and option instances. - * - * @param array|InputDefinition $definition An array of argument and option instances or a definition instance - * - * @return $this - */ - 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() - { - if (null === $this->definition) { - throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', \get_class($this))); - } - - return $this->definition; - } - - /** - * Gets the InputDefinition to be used to create representations of this Command. - * - * Can be overridden to provide the original command representation when it would otherwise - * be changed by merging with the application InputDefinition. - * - * This method is not part of public API and should not be used directly. - * - * @return InputDefinition An InputDefinition instance - */ - public function getNativeDefinition() - { - return $this->getDefinition(); - } - - /** - * Adds an argument. - * - * @param int|null $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL - * @param string|string[]|null $default The default value (for InputArgument::OPTIONAL mode only) - * - * @throws InvalidArgumentException When argument mode is not valid - * - * @return $this - */ - public function addArgument(string $name, int $mode = null, string $description = '', $default = null) - { - $this->definition->addArgument(new InputArgument($name, $mode, $description, $default)); - - return $this; - } - - /** - * Adds an option. - * - * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts - * @param int|null $mode The option mode: One of the InputOption::VALUE_* constants - * @param string|string[]|int|bool|null $default The default value (must be null for InputOption::VALUE_NONE) - * - * @throws InvalidArgumentException If option mode is invalid or incompatible - * - * @return $this - */ - public function addOption(string $name, $shortcut = null, int $mode = null, string $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'); - * - * @return $this - * - * @throws InvalidArgumentException When the name is invalid - */ - public function setName(string $name) - { - $this->validateName($name); - - $this->name = $name; - - return $this; - } - - /** - * Sets the process title of the command. - * - * This feature should be used only when creating a long process command, - * like a daemon. - * - * PHP 5.5+ or the proctitle PECL library is required - * - * @return $this - */ - public function setProcessTitle(string $title) - { - $this->processTitle = $title; - - return $this; - } - - /** - * Returns the command name. - * - * @return string|null - */ - public function getName() - { - return $this->name; - } - - /** - * @param bool $hidden Whether or not the command should be hidden from the list of commands - * - * @return Command The current instance - */ - public function setHidden(bool $hidden) - { - $this->hidden = $hidden; - - return $this; - } - - /** - * @return bool whether the command should be publicly shown or not - */ - public function isHidden() - { - return $this->hidden; - } - - /** - * Sets the description for the command. - * - * @return $this - */ - public function setDescription(string $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. - * - * @return $this - */ - public function setHelp(string $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->name; - $isSingleCommand = $this->application && $this->application->isSingleCommand(); - - $placeholders = [ - '%command.name%', - '%command.full_name%', - ]; - $replacements = [ - $name, - $isSingleCommand ? $_SERVER['PHP_SELF'] : $_SERVER['PHP_SELF'].' '.$name, - ]; - - return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription()); - } - - /** - * Sets the aliases for the command. - * - * @param string[] $aliases An array of aliases for the command - * - * @return $this - * - * @throws InvalidArgumentException When an alias is invalid - */ - public function setAliases(iterable $aliases) - { - foreach ($aliases as $alias) { - $this->validateName($alias); - } - - $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. - * - * @param bool $short Whether to show the short version of the synopsis (with options folded) or not - * - * @return string The synopsis - */ - public function getSynopsis(bool $short = false) - { - $key = $short ? 'short' : 'long'; - - if (!isset($this->synopsis[$key])) { - $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short))); - } - - return $this->synopsis[$key]; - } - - /** - * Add a command usage example, it'll be prefixed with the command name. - * - * @return $this - */ - public function addUsage(string $usage) - { - if (0 !== strpos($usage, $this->name)) { - $usage = sprintf('%s %s', $this->name, $usage); - } - - $this->usages[] = $usage; - - return $this; - } - - /** - * Returns alternative usages of the command. - * - * @return array - */ - public function getUsages() - { - return $this->usages; - } - - /** - * Gets a helper instance by name. - * - * @return mixed The helper value - * - * @throws LogicException if no HelperSet is defined - * @throws InvalidArgumentException if the helper is not defined - */ - public function getHelper(string $name) - { - if (null === $this->helperSet) { - throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name)); - } - - return $this->helperSet->get($name); - } - - /** - * Validates a command name. - * - * It must be non-empty and parts can optionally be separated by ":". - * - * @throws InvalidArgumentException When the name is invalid - */ - private function validateName(string $name) - { - if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) { - throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name)); - } - } -} diff --git a/vendor/symfony/console/Command/HelpCommand.php b/vendor/symfony/console/Command/HelpCommand.php deleted file mode 100644 index b32be4c..0000000 --- a/vendor/symfony/console/Command/HelpCommand.php +++ /dev/null @@ -1,83 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Helper\DescriptorHelper; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * HelpCommand displays the help for a given command. - * - * @author Fabien Potencier - */ -class HelpCommand extends Command -{ - private $command; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this->ignoreValidationErrors(); - - $this - ->setName('help') - ->setDefinition([ - new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), - new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'), - ]) - ->setDescription('Displays help for a command') - ->setHelp(<<<'EOF' -The %command.name% command displays help for a given command: - - php %command.full_name% list - -You can also output the help in other formats by using the --format option: - - php %command.full_name% --format=xml list - -To display the list of available commands, please use the list command. -EOF - ) - ; - } - - public function setCommand(Command $command) - { - $this->command = $command; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - if (null === $this->command) { - $this->command = $this->getApplication()->find($input->getArgument('command_name')); - } - - $helper = new DescriptorHelper(); - $helper->describe($output, $this->command, [ - 'format' => $input->getOption('format'), - 'raw_text' => $input->getOption('raw'), - ]); - - $this->command = null; - - return 0; - } -} diff --git a/vendor/symfony/console/Command/ListCommand.php b/vendor/symfony/console/Command/ListCommand.php deleted file mode 100644 index 8af9526..0000000 --- a/vendor/symfony/console/Command/ListCommand.php +++ /dev/null @@ -1,89 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Helper\DescriptorHelper; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * ListCommand displays the list of all available commands for the application. - * - * @author Fabien Potencier - */ -class ListCommand extends Command -{ - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setName('list') - ->setDefinition($this->createDefinition()) - ->setDescription('Lists commands') - ->setHelp(<<<'EOF' -The %command.name% command lists all commands: - - php %command.full_name% - -You can also display the commands for a specific namespace: - - php %command.full_name% test - -You can also output the information in other formats by using the --format option: - - php %command.full_name% --format=xml - -It's also possible to get raw list of commands (useful for embedding command runner): - - php %command.full_name% --raw -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - public function getNativeDefinition() - { - return $this->createDefinition(); - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $helper = new DescriptorHelper(); - $helper->describe($output, $this->getApplication(), [ - 'format' => $input->getOption('format'), - 'raw_text' => $input->getOption('raw'), - 'namespace' => $input->getArgument('namespace'), - ]); - - return 0; - } - - private function createDefinition(): InputDefinition - { - return new InputDefinition([ - new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), - new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), - ]); - } -} diff --git a/vendor/symfony/console/Command/LockableTrait.php b/vendor/symfony/console/Command/LockableTrait.php deleted file mode 100644 index 60cfe36..0000000 --- a/vendor/symfony/console/Command/LockableTrait.php +++ /dev/null @@ -1,69 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Lock\Lock; -use Symfony\Component\Lock\LockFactory; -use Symfony\Component\Lock\Store\FlockStore; -use Symfony\Component\Lock\Store\SemaphoreStore; - -/** - * Basic lock feature for commands. - * - * @author Geoffrey Brier - */ -trait LockableTrait -{ - /** @var Lock */ - private $lock; - - /** - * Locks a command. - */ - private function lock(string $name = null, bool $blocking = false): bool - { - if (!class_exists(SemaphoreStore::class)) { - throw new LogicException('To enable the locking feature you must install the symfony/lock component.'); - } - - if (null !== $this->lock) { - throw new LogicException('A lock is already in place.'); - } - - if (SemaphoreStore::isSupported()) { - $store = new SemaphoreStore(); - } else { - $store = new FlockStore(); - } - - $this->lock = (new LockFactory($store))->createLock($name ?: $this->getName()); - if (!$this->lock->acquire($blocking)) { - $this->lock = null; - - return false; - } - - return true; - } - - /** - * Releases the command lock if there is one. - */ - private function release() - { - if ($this->lock) { - $this->lock->release(); - $this->lock = null; - } - } -} diff --git a/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php b/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php deleted file mode 100644 index d4f44e8..0000000 --- a/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\CommandLoader; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\CommandNotFoundException; - -/** - * @author Robin Chalas - */ -interface CommandLoaderInterface -{ - /** - * Loads a command. - * - * @return Command - * - * @throws CommandNotFoundException - */ - public function get(string $name); - - /** - * Checks if a command exists. - * - * @return bool - */ - public function has(string $name); - - /** - * @return string[] All registered command names - */ - public function getNames(); -} diff --git a/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php b/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php deleted file mode 100644 index ddccb3d..0000000 --- a/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\CommandLoader; - -use Psr\Container\ContainerInterface; -use Symfony\Component\Console\Exception\CommandNotFoundException; - -/** - * Loads commands from a PSR-11 container. - * - * @author Robin Chalas - */ -class ContainerCommandLoader implements CommandLoaderInterface -{ - private $container; - private $commandMap; - - /** - * @param array $commandMap An array with command names as keys and service ids as values - */ - public function __construct(ContainerInterface $container, array $commandMap) - { - $this->container = $container; - $this->commandMap = $commandMap; - } - - /** - * {@inheritdoc} - */ - public function get(string $name) - { - if (!$this->has($name)) { - throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); - } - - return $this->container->get($this->commandMap[$name]); - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]); - } - - /** - * {@inheritdoc} - */ - public function getNames() - { - return array_keys($this->commandMap); - } -} diff --git a/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php b/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php deleted file mode 100644 index 7e2db34..0000000 --- a/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\CommandLoader; - -use Symfony\Component\Console\Exception\CommandNotFoundException; - -/** - * A simple command loader using factories to instantiate commands lazily. - * - * @author Maxime Steinhausser - */ -class FactoryCommandLoader implements CommandLoaderInterface -{ - private $factories; - - /** - * @param callable[] $factories Indexed by command names - */ - public function __construct(array $factories) - { - $this->factories = $factories; - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - return isset($this->factories[$name]); - } - - /** - * {@inheritdoc} - */ - public function get(string $name) - { - if (!isset($this->factories[$name])) { - throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); - } - - $factory = $this->factories[$name]; - - return $factory(); - } - - /** - * {@inheritdoc} - */ - public function getNames() - { - return array_keys($this->factories); - } -} diff --git a/vendor/symfony/console/ConsoleEvents.php b/vendor/symfony/console/ConsoleEvents.php deleted file mode 100644 index 4975643..0000000 --- a/vendor/symfony/console/ConsoleEvents.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -/** - * Contains all events dispatched by an Application. - * - * @author Francesco Levorato - */ -final class ConsoleEvents -{ - /** - * The COMMAND event allows you to attach listeners before any command is - * executed by the console. It also allows you to modify the command, input and output - * before they are handled to the command. - * - * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent") - */ - const COMMAND = 'console.command'; - - /** - * The TERMINATE event allows you to attach listeners after a command is - * executed by the console. - * - * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent") - */ - const TERMINATE = 'console.terminate'; - - /** - * The ERROR event occurs when an uncaught exception or error appears. - * - * This event allows you to deal with the exception/error or - * to modify the thrown exception. - * - * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent") - */ - const ERROR = 'console.error'; -} diff --git a/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php b/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php deleted file mode 100644 index 666c8fa..0000000 --- a/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php +++ /dev/null @@ -1,98 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\DependencyInjection; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\TypedReference; - -/** - * Registers console commands. - * - * @author Grégoire Pineau - */ -class AddConsoleCommandPass implements CompilerPassInterface -{ - private $commandLoaderServiceId; - private $commandTag; - - public function __construct(string $commandLoaderServiceId = 'console.command_loader', string $commandTag = 'console.command') - { - $this->commandLoaderServiceId = $commandLoaderServiceId; - $this->commandTag = $commandTag; - } - - public function process(ContainerBuilder $container) - { - $commandServices = $container->findTaggedServiceIds($this->commandTag, true); - $lazyCommandMap = []; - $lazyCommandRefs = []; - $serviceIds = []; - - foreach ($commandServices as $id => $tags) { - $definition = $container->getDefinition($id); - $class = $container->getParameterBag()->resolveValue($definition->getClass()); - - if (isset($tags[0]['command'])) { - $commandName = $tags[0]['command']; - } else { - if (!$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } - if (!$r->isSubclassOf(Command::class)) { - throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class)); - } - $commandName = $class::getDefaultName(); - } - - if (null === $commandName) { - if (!$definition->isPublic() || $definition->isPrivate()) { - $commandId = 'console.command.public_alias.'.$id; - $container->setAlias($commandId, $id)->setPublic(true); - $id = $commandId; - } - $serviceIds[] = $id; - - continue; - } - - unset($tags[0]); - $lazyCommandMap[$commandName] = $id; - $lazyCommandRefs[$id] = new TypedReference($id, $class); - $aliases = []; - - foreach ($tags as $tag) { - if (isset($tag['command'])) { - $aliases[] = $tag['command']; - $lazyCommandMap[$tag['command']] = $id; - } - } - - $definition->addMethodCall('setName', [$commandName]); - - if ($aliases) { - $definition->addMethodCall('setAliases', [$aliases]); - } - } - - $container - ->register($this->commandLoaderServiceId, ContainerCommandLoader::class) - ->setPublic(true) - ->setArguments([ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]); - - $container->setParameter('console.command.ids', $serviceIds); - } -} diff --git a/vendor/symfony/console/Descriptor/ApplicationDescription.php b/vendor/symfony/console/Descriptor/ApplicationDescription.php deleted file mode 100644 index af88363..0000000 --- a/vendor/symfony/console/Descriptor/ApplicationDescription.php +++ /dev/null @@ -1,143 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\CommandNotFoundException; - -/** - * @author Jean-François Simon - * - * @internal - */ -class ApplicationDescription -{ - const GLOBAL_NAMESPACE = '_global'; - - private $application; - private $namespace; - private $showHidden; - - /** - * @var array - */ - private $namespaces; - - /** - * @var Command[] - */ - private $commands; - - /** - * @var Command[] - */ - private $aliases; - - public function __construct(Application $application, string $namespace = null, bool $showHidden = false) - { - $this->application = $application; - $this->namespace = $namespace; - $this->showHidden = $showHidden; - } - - public function getNamespaces(): array - { - if (null === $this->namespaces) { - $this->inspectApplication(); - } - - return $this->namespaces; - } - - /** - * @return Command[] - */ - public function getCommands(): array - { - if (null === $this->commands) { - $this->inspectApplication(); - } - - return $this->commands; - } - - /** - * @throws CommandNotFoundException - */ - public function getCommand(string $name): Command - { - if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { - throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name)); - } - - return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name]; - } - - private function inspectApplication() - { - $this->commands = []; - $this->namespaces = []; - - $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null); - foreach ($this->sortCommands($all) as $namespace => $commands) { - $names = []; - - /** @var Command $command */ - foreach ($commands as $name => $command) { - if (!$command->getName() || (!$this->showHidden && $command->isHidden())) { - continue; - } - - if ($command->getName() === $name) { - $this->commands[$name] = $command; - } else { - $this->aliases[$name] = $command; - } - - $names[] = $name; - } - - $this->namespaces[$namespace] = ['id' => $namespace, 'commands' => $names]; - } - } - - private function sortCommands(array $commands): array - { - $namespacedCommands = []; - $globalCommands = []; - $sortedCommands = []; - foreach ($commands as $name => $command) { - $key = $this->application->extractNamespace($name, 1); - if (\in_array($key, ['', self::GLOBAL_NAMESPACE], true)) { - $globalCommands[$name] = $command; - } else { - $namespacedCommands[$key][$name] = $command; - } - } - - if ($globalCommands) { - ksort($globalCommands); - $sortedCommands[self::GLOBAL_NAMESPACE] = $globalCommands; - } - - if ($namespacedCommands) { - ksort($namespacedCommands); - foreach ($namespacedCommands as $key => $commandsSet) { - ksort($commandsSet); - $sortedCommands[$key] = $commandsSet; - } - } - - return $sortedCommands; - } -} diff --git a/vendor/symfony/console/Descriptor/Descriptor.php b/vendor/symfony/console/Descriptor/Descriptor.php deleted file mode 100644 index df85e38..0000000 --- a/vendor/symfony/console/Descriptor/Descriptor.php +++ /dev/null @@ -1,104 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * @author Jean-François Simon - * - * @internal - */ -abstract class Descriptor implements DescriptorInterface -{ - /** - * @var OutputInterface - */ - protected $output; - - /** - * {@inheritdoc} - */ - public function describe(OutputInterface $output, $object, array $options = []) - { - $this->output = $output; - - switch (true) { - case $object instanceof InputArgument: - $this->describeInputArgument($object, $options); - break; - case $object instanceof InputOption: - $this->describeInputOption($object, $options); - break; - case $object instanceof InputDefinition: - $this->describeInputDefinition($object, $options); - break; - case $object instanceof Command: - $this->describeCommand($object, $options); - break; - case $object instanceof Application: - $this->describeApplication($object, $options); - break; - default: - throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', \get_class($object))); - } - } - - /** - * Writes content to output. - */ - protected function write(string $content, bool $decorated = false) - { - $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); - } - - /** - * Describes an InputArgument instance. - * - * @return string|mixed - */ - abstract protected function describeInputArgument(InputArgument $argument, array $options = []); - - /** - * Describes an InputOption instance. - * - * @return string|mixed - */ - abstract protected function describeInputOption(InputOption $option, array $options = []); - - /** - * Describes an InputDefinition instance. - * - * @return string|mixed - */ - abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []); - - /** - * Describes a Command instance. - * - * @return string|mixed - */ - abstract protected function describeCommand(Command $command, array $options = []); - - /** - * Describes an Application instance. - * - * @return string|mixed - */ - abstract protected function describeApplication(Application $application, array $options = []); -} diff --git a/vendor/symfony/console/Descriptor/DescriptorInterface.php b/vendor/symfony/console/Descriptor/DescriptorInterface.php deleted file mode 100644 index e3184a6..0000000 --- a/vendor/symfony/console/Descriptor/DescriptorInterface.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Descriptor interface. - * - * @author Jean-François Simon - */ -interface DescriptorInterface -{ - /** - * Describes an object if supported. - * - * @param object $object - */ - public function describe(OutputInterface $output, $object, array $options = []); -} diff --git a/vendor/symfony/console/Descriptor/JsonDescriptor.php b/vendor/symfony/console/Descriptor/JsonDescriptor.php deleted file mode 100644 index 131fef1..0000000 --- a/vendor/symfony/console/Descriptor/JsonDescriptor.php +++ /dev/null @@ -1,156 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -/** - * JSON descriptor. - * - * @author Jean-François Simon - * - * @internal - */ -class JsonDescriptor extends Descriptor -{ - /** - * {@inheritdoc} - */ - protected function describeInputArgument(InputArgument $argument, array $options = []) - { - $this->writeData($this->getInputArgumentData($argument), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeInputOption(InputOption $option, array $options = []) - { - $this->writeData($this->getInputOptionData($option), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeInputDefinition(InputDefinition $definition, array $options = []) - { - $this->writeData($this->getInputDefinitionData($definition), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeCommand(Command $command, array $options = []) - { - $this->writeData($this->getCommandData($command), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeApplication(Application $application, array $options = []) - { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; - $description = new ApplicationDescription($application, $describedNamespace, true); - $commands = []; - - foreach ($description->getCommands() as $command) { - $commands[] = $this->getCommandData($command); - } - - $data = []; - if ('UNKNOWN' !== $application->getName()) { - $data['application']['name'] = $application->getName(); - if ('UNKNOWN' !== $application->getVersion()) { - $data['application']['version'] = $application->getVersion(); - } - } - - $data['commands'] = $commands; - - if ($describedNamespace) { - $data['namespace'] = $describedNamespace; - } else { - $data['namespaces'] = array_values($description->getNamespaces()); - } - - $this->writeData($data, $options); - } - - /** - * Writes data as json. - */ - private function writeData(array $data, array $options) - { - $flags = isset($options['json_encoding']) ? $options['json_encoding'] : 0; - - $this->write(json_encode($data, $flags)); - } - - private function getInputArgumentData(InputArgument $argument): array - { - return [ - 'name' => $argument->getName(), - 'is_required' => $argument->isRequired(), - 'is_array' => $argument->isArray(), - 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), - 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), - ]; - } - - private function getInputOptionData(InputOption $option): array - { - return [ - 'name' => '--'.$option->getName(), - 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '', - 'accept_value' => $option->acceptValue(), - 'is_value_required' => $option->isValueRequired(), - 'is_multiple' => $option->isArray(), - 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), - 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(), - ]; - } - - private function getInputDefinitionData(InputDefinition $definition): array - { - $inputArguments = []; - foreach ($definition->getArguments() as $name => $argument) { - $inputArguments[$name] = $this->getInputArgumentData($argument); - } - - $inputOptions = []; - foreach ($definition->getOptions() as $name => $option) { - $inputOptions[$name] = $this->getInputOptionData($option); - } - - return ['arguments' => $inputArguments, 'options' => $inputOptions]; - } - - private function getCommandData(Command $command): array - { - $command->getSynopsis(); - $command->mergeApplicationDefinition(false); - - return [ - 'name' => $command->getName(), - 'usage' => array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()), - 'description' => $command->getDescription(), - 'help' => $command->getProcessedHelp(), - 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()), - 'hidden' => $command->isHidden(), - ]; - } -} diff --git a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php b/vendor/symfony/console/Descriptor/MarkdownDescriptor.php deleted file mode 100644 index 8b3e182..0000000 --- a/vendor/symfony/console/Descriptor/MarkdownDescriptor.php +++ /dev/null @@ -1,188 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Markdown descriptor. - * - * @author Jean-François Simon - * - * @internal - */ -class MarkdownDescriptor extends Descriptor -{ - /** - * {@inheritdoc} - */ - public function describe(OutputInterface $output, $object, array $options = []) - { - $decorated = $output->isDecorated(); - $output->setDecorated(false); - - parent::describe($output, $object, $options); - - $output->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - protected function write(string $content, bool $decorated = true) - { - parent::write($content, $decorated); - } - - /** - * {@inheritdoc} - */ - protected function describeInputArgument(InputArgument $argument, array $options = []) - { - $this->write( - '#### `'.($argument->getName() ?: '')."`\n\n" - .($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription())."\n\n" : '') - .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" - .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" - .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`' - ); - } - - /** - * {@inheritdoc} - */ - protected function describeInputOption(InputOption $option, array $options = []) - { - $name = '--'.$option->getName(); - if ($option->getShortcut()) { - $name .= '|-'.str_replace('|', '|-', $option->getShortcut()).''; - } - - $this->write( - '#### `'.$name.'`'."\n\n" - .($option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $option->getDescription())."\n\n" : '') - .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" - .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" - .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" - .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`' - ); - } - - /** - * {@inheritdoc} - */ - protected function describeInputDefinition(InputDefinition $definition, array $options = []) - { - if ($showArguments = \count($definition->getArguments()) > 0) { - $this->write('### Arguments'); - foreach ($definition->getArguments() as $argument) { - $this->write("\n\n"); - if (null !== $describeInputArgument = $this->describeInputArgument($argument)) { - $this->write($describeInputArgument); - } - } - } - - if (\count($definition->getOptions()) > 0) { - if ($showArguments) { - $this->write("\n\n"); - } - - $this->write('### Options'); - foreach ($definition->getOptions() as $option) { - $this->write("\n\n"); - if (null !== $describeInputOption = $this->describeInputOption($option)) { - $this->write($describeInputOption); - } - } - } - } - - /** - * {@inheritdoc} - */ - protected function describeCommand(Command $command, array $options = []) - { - $command->getSynopsis(); - $command->mergeApplicationDefinition(false); - - $this->write( - '`'.$command->getName()."`\n" - .str_repeat('-', Helper::strlen($command->getName()) + 2)."\n\n" - .($command->getDescription() ? $command->getDescription()."\n\n" : '') - .'### Usage'."\n\n" - .array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), function ($carry, $usage) { - return $carry.'* `'.$usage.'`'."\n"; - }) - ); - - if ($help = $command->getProcessedHelp()) { - $this->write("\n"); - $this->write($help); - } - - if ($command->getNativeDefinition()) { - $this->write("\n\n"); - $this->describeInputDefinition($command->getNativeDefinition()); - } - } - - /** - * {@inheritdoc} - */ - protected function describeApplication(Application $application, array $options = []) - { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; - $description = new ApplicationDescription($application, $describedNamespace); - $title = $this->getApplicationTitle($application); - - $this->write($title."\n".str_repeat('=', Helper::strlen($title))); - - foreach ($description->getNamespaces() as $namespace) { - if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { - $this->write("\n\n"); - $this->write('**'.$namespace['id'].':**'); - } - - $this->write("\n\n"); - $this->write(implode("\n", array_map(function ($commandName) use ($description) { - return sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName())); - }, $namespace['commands']))); - } - - foreach ($description->getCommands() as $command) { - $this->write("\n\n"); - if (null !== $describeCommand = $this->describeCommand($command)) { - $this->write($describeCommand); - } - } - } - - private function getApplicationTitle(Application $application): string - { - if ('UNKNOWN' !== $application->getName()) { - if ('UNKNOWN' !== $application->getVersion()) { - return sprintf('%s %s', $application->getName(), $application->getVersion()); - } - - return $application->getName(); - } - - return 'Console Tool'; - } -} diff --git a/vendor/symfony/console/Descriptor/TextDescriptor.php b/vendor/symfony/console/Descriptor/TextDescriptor.php deleted file mode 100644 index ef6d8af..0000000 --- a/vendor/symfony/console/Descriptor/TextDescriptor.php +++ /dev/null @@ -1,342 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -/** - * Text descriptor. - * - * @author Jean-François Simon - * - * @internal - */ -class TextDescriptor extends Descriptor -{ - /** - * {@inheritdoc} - */ - protected function describeInputArgument(InputArgument $argument, array $options = []) - { - if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) { - $default = sprintf(' [default: %s]', $this->formatDefaultValue($argument->getDefault())); - } else { - $default = ''; - } - - $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName()); - $spacingWidth = $totalWidth - \strlen($argument->getName()); - - $this->writeText(sprintf(' %s %s%s%s', - $argument->getName(), - str_repeat(' ', $spacingWidth), - // + 4 = 2 spaces before , 2 spaces after - preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()), - $default - ), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeInputOption(InputOption $option, array $options = []) - { - if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) { - $default = sprintf(' [default: %s]', $this->formatDefaultValue($option->getDefault())); - } else { - $default = ''; - } - - $value = ''; - if ($option->acceptValue()) { - $value = '='.strtoupper($option->getName()); - - if ($option->isValueOptional()) { - $value = '['.$value.']'; - } - } - - $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions([$option]); - $synopsis = sprintf('%s%s', - $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ', - sprintf('--%s%s', $option->getName(), $value) - ); - - $spacingWidth = $totalWidth - Helper::strlen($synopsis); - - $this->writeText(sprintf(' %s %s%s%s%s', - $synopsis, - str_repeat(' ', $spacingWidth), - // + 4 = 2 spaces before , 2 spaces after - preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()), - $default, - $option->isArray() ? ' (multiple values allowed)' : '' - ), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeInputDefinition(InputDefinition $definition, array $options = []) - { - $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions()); - foreach ($definition->getArguments() as $argument) { - $totalWidth = max($totalWidth, Helper::strlen($argument->getName())); - } - - if ($definition->getArguments()) { - $this->writeText('Arguments:', $options); - $this->writeText("\n"); - foreach ($definition->getArguments() as $argument) { - $this->describeInputArgument($argument, array_merge($options, ['total_width' => $totalWidth])); - $this->writeText("\n"); - } - } - - if ($definition->getArguments() && $definition->getOptions()) { - $this->writeText("\n"); - } - - if ($definition->getOptions()) { - $laterOptions = []; - - $this->writeText('Options:', $options); - foreach ($definition->getOptions() as $option) { - if (\strlen($option->getShortcut()) > 1) { - $laterOptions[] = $option; - continue; - } - $this->writeText("\n"); - $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); - } - foreach ($laterOptions as $option) { - $this->writeText("\n"); - $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); - } - } - } - - /** - * {@inheritdoc} - */ - protected function describeCommand(Command $command, array $options = []) - { - $command->getSynopsis(true); - $command->getSynopsis(false); - $command->mergeApplicationDefinition(false); - - if ($description = $command->getDescription()) { - $this->writeText('Description:', $options); - $this->writeText("\n"); - $this->writeText(' '.$description); - $this->writeText("\n\n"); - } - - $this->writeText('Usage:', $options); - foreach (array_merge([$command->getSynopsis(true)], $command->getAliases(), $command->getUsages()) as $usage) { - $this->writeText("\n"); - $this->writeText(' '.OutputFormatter::escape($usage), $options); - } - $this->writeText("\n"); - - $definition = $command->getNativeDefinition(); - if ($definition->getOptions() || $definition->getArguments()) { - $this->writeText("\n"); - $this->describeInputDefinition($definition, $options); - $this->writeText("\n"); - } - - $help = $command->getProcessedHelp(); - if ($help && $help !== $description) { - $this->writeText("\n"); - $this->writeText('Help:', $options); - $this->writeText("\n"); - $this->writeText(' '.str_replace("\n", "\n ", $help), $options); - $this->writeText("\n"); - } - } - - /** - * {@inheritdoc} - */ - protected function describeApplication(Application $application, array $options = []) - { - $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; - $description = new ApplicationDescription($application, $describedNamespace); - - if (isset($options['raw_text']) && $options['raw_text']) { - $width = $this->getColumnWidth($description->getCommands()); - - foreach ($description->getCommands() as $command) { - $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options); - $this->writeText("\n"); - } - } else { - if ('' != $help = $application->getHelp()) { - $this->writeText("$help\n\n", $options); - } - - $this->writeText("Usage:\n", $options); - $this->writeText(" command [options] [arguments]\n\n", $options); - - $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options); - - $this->writeText("\n"); - $this->writeText("\n"); - - $commands = $description->getCommands(); - $namespaces = $description->getNamespaces(); - if ($describedNamespace && $namespaces) { - // make sure all alias commands are included when describing a specific namespace - $describedNamespaceInfo = reset($namespaces); - foreach ($describedNamespaceInfo['commands'] as $name) { - $commands[$name] = $description->getCommand($name); - } - } - - // calculate max. width based on available commands per namespace - $width = $this->getColumnWidth(array_merge(...array_values(array_map(function ($namespace) use ($commands) { - return array_intersect($namespace['commands'], array_keys($commands)); - }, $namespaces)))); - - if ($describedNamespace) { - $this->writeText(sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options); - } else { - $this->writeText('Available commands:', $options); - } - - foreach ($namespaces as $namespace) { - $namespace['commands'] = array_filter($namespace['commands'], function ($name) use ($commands) { - return isset($commands[$name]); - }); - - if (!$namespace['commands']) { - continue; - } - - if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { - $this->writeText("\n"); - $this->writeText(' '.$namespace['id'].'', $options); - } - - foreach ($namespace['commands'] as $name) { - $this->writeText("\n"); - $spacingWidth = $width - Helper::strlen($name); - $command = $commands[$name]; - $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : ''; - $this->writeText(sprintf(' %s%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options); - } - } - - $this->writeText("\n"); - } - } - - /** - * {@inheritdoc} - */ - private function writeText(string $content, array $options = []) - { - $this->write( - isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, - isset($options['raw_output']) ? !$options['raw_output'] : true - ); - } - - /** - * Formats command aliases to show them in the command description. - */ - private function getCommandAliasesText(Command $command): string - { - $text = ''; - $aliases = $command->getAliases(); - - if ($aliases) { - $text = '['.implode('|', $aliases).'] '; - } - - return $text; - } - - /** - * Formats input option/argument default value. - * - * @param mixed $default - */ - private function formatDefaultValue($default): string - { - if (INF === $default) { - return 'INF'; - } - - if (\is_string($default)) { - $default = OutputFormatter::escape($default); - } elseif (\is_array($default)) { - foreach ($default as $key => $value) { - if (\is_string($value)) { - $default[$key] = OutputFormatter::escape($value); - } - } - } - - return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); - } - - /** - * @param (Command|string)[] $commands - */ - private function getColumnWidth(array $commands): int - { - $widths = []; - - foreach ($commands as $command) { - if ($command instanceof Command) { - $widths[] = Helper::strlen($command->getName()); - foreach ($command->getAliases() as $alias) { - $widths[] = Helper::strlen($alias); - } - } else { - $widths[] = Helper::strlen($command); - } - } - - return $widths ? max($widths) + 2 : 0; - } - - /** - * @param InputOption[] $options - */ - private function calculateTotalWidthForOptions(array $options): int - { - $totalWidth = 0; - foreach ($options as $option) { - // "-" + shortcut + ", --" + name - $nameLength = 1 + max(Helper::strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName()); - - if ($option->acceptValue()) { - $valueLength = 1 + Helper::strlen($option->getName()); // = + value - $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ] - - $nameLength += $valueLength; - } - $totalWidth = max($totalWidth, $nameLength); - } - - return $totalWidth; - } -} diff --git a/vendor/symfony/console/Descriptor/XmlDescriptor.php b/vendor/symfony/console/Descriptor/XmlDescriptor.php deleted file mode 100644 index 3d5dce1..0000000 --- a/vendor/symfony/console/Descriptor/XmlDescriptor.php +++ /dev/null @@ -1,231 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Descriptor; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputDefinition; -use Symfony\Component\Console\Input\InputOption; - -/** - * XML descriptor. - * - * @author Jean-François Simon - * - * @internal - */ -class XmlDescriptor extends Descriptor -{ - public function getInputDefinitionDocument(InputDefinition $definition): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($definitionXML = $dom->createElement('definition')); - - $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); - foreach ($definition->getArguments() as $argument) { - $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument)); - } - - $definitionXML->appendChild($optionsXML = $dom->createElement('options')); - foreach ($definition->getOptions() as $option) { - $this->appendDocument($optionsXML, $this->getInputOptionDocument($option)); - } - - return $dom; - } - - public function getCommandDocument(Command $command): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($commandXML = $dom->createElement('command')); - - $command->getSynopsis(); - $command->mergeApplicationDefinition(false); - - $commandXML->setAttribute('id', $command->getName()); - $commandXML->setAttribute('name', $command->getName()); - $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0); - - $commandXML->appendChild($usagesXML = $dom->createElement('usages')); - - foreach (array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()) as $usage) { - $usagesXML->appendChild($dom->createElement('usage', $usage)); - } - - $commandXML->appendChild($descriptionXML = $dom->createElement('description')); - $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription()))); - - $commandXML->appendChild($helpXML = $dom->createElement('help')); - $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp()))); - - $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition()); - $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); - - return $dom; - } - - public function getApplicationDocument(Application $application, string $namespace = null): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($rootXml = $dom->createElement('symfony')); - - if ('UNKNOWN' !== $application->getName()) { - $rootXml->setAttribute('name', $application->getName()); - if ('UNKNOWN' !== $application->getVersion()) { - $rootXml->setAttribute('version', $application->getVersion()); - } - } - - $rootXml->appendChild($commandsXML = $dom->createElement('commands')); - - $description = new ApplicationDescription($application, $namespace, true); - - if ($namespace) { - $commandsXML->setAttribute('namespace', $namespace); - } - - foreach ($description->getCommands() as $command) { - $this->appendDocument($commandsXML, $this->getCommandDocument($command)); - } - - if (!$namespace) { - $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces')); - - foreach ($description->getNamespaces() as $namespaceDescription) { - $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace')); - $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']); - - foreach ($namespaceDescription['commands'] as $name) { - $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command')); - $commandXML->appendChild($dom->createTextNode($name)); - } - } - } - - return $dom; - } - - /** - * {@inheritdoc} - */ - protected function describeInputArgument(InputArgument $argument, array $options = []) - { - $this->writeDocument($this->getInputArgumentDocument($argument)); - } - - /** - * {@inheritdoc} - */ - protected function describeInputOption(InputOption $option, array $options = []) - { - $this->writeDocument($this->getInputOptionDocument($option)); - } - - /** - * {@inheritdoc} - */ - protected function describeInputDefinition(InputDefinition $definition, array $options = []) - { - $this->writeDocument($this->getInputDefinitionDocument($definition)); - } - - /** - * {@inheritdoc} - */ - protected function describeCommand(Command $command, array $options = []) - { - $this->writeDocument($this->getCommandDocument($command)); - } - - /** - * {@inheritdoc} - */ - protected function describeApplication(Application $application, array $options = []) - { - $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null)); - } - - /** - * Appends document children to parent node. - */ - private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) - { - foreach ($importedParent->childNodes as $childNode) { - $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true)); - } - } - - /** - * Writes DOM document. - */ - private function writeDocument(\DOMDocument $dom) - { - $dom->formatOutput = true; - $this->write($dom->saveXML()); - } - - private function getInputArgumentDocument(InputArgument $argument): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - - $dom->appendChild($objectXML = $dom->createElement('argument')); - $objectXML->setAttribute('name', $argument->getName()); - $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); - $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); - $objectXML->appendChild($descriptionXML = $dom->createElement('description')); - $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); - - $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); - $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? [var_export($argument->getDefault(), true)] : ($argument->getDefault() ? [$argument->getDefault()] : [])); - foreach ($defaults as $default) { - $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); - $defaultXML->appendChild($dom->createTextNode($default)); - } - - return $dom; - } - - private function getInputOptionDocument(InputOption $option): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - - $dom->appendChild($objectXML = $dom->createElement('option')); - $objectXML->setAttribute('name', '--'.$option->getName()); - $pos = strpos($option->getShortcut(), '|'); - if (false !== $pos) { - $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); - $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut())); - } else { - $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); - } - $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0); - $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0); - $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); - $objectXML->appendChild($descriptionXML = $dom->createElement('description')); - $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); - - if ($option->acceptValue()) { - $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? [var_export($option->getDefault(), true)] : ($option->getDefault() ? [$option->getDefault()] : [])); - $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); - - if (!empty($defaults)) { - foreach ($defaults as $default) { - $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); - $defaultXML->appendChild($dom->createTextNode($default)); - } - } - } - - return $dom; - } -} diff --git a/vendor/symfony/console/Event/ConsoleCommandEvent.php b/vendor/symfony/console/Event/ConsoleCommandEvent.php deleted file mode 100644 index a24697c..0000000 --- a/vendor/symfony/console/Event/ConsoleCommandEvent.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -/** - * Allows to do things before the command is executed, like skipping the command or changing the input. - * - * @author Fabien Potencier - */ -final class ConsoleCommandEvent extends ConsoleEvent -{ - /** - * The return code for skipped commands, this will also be passed into the terminate event. - */ - const RETURN_CODE_DISABLED = 113; - - /** - * Indicates if the command should be run or skipped. - */ - private $commandShouldRun = true; - - /** - * Disables the command, so it won't be run. - */ - public function disableCommand(): bool - { - return $this->commandShouldRun = false; - } - - public function enableCommand(): bool - { - return $this->commandShouldRun = true; - } - - /** - * Returns true if the command is runnable, false otherwise. - */ - public function commandShouldRun(): bool - { - return $this->commandShouldRun; - } -} diff --git a/vendor/symfony/console/Event/ConsoleErrorEvent.php b/vendor/symfony/console/Event/ConsoleErrorEvent.php deleted file mode 100644 index 25d9b88..0000000 --- a/vendor/symfony/console/Event/ConsoleErrorEvent.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Allows to handle throwables thrown while running a command. - * - * @author Wouter de Jong - */ -final class ConsoleErrorEvent extends ConsoleEvent -{ - private $error; - private $exitCode; - - public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null) - { - parent::__construct($command, $input, $output); - - $this->error = $error; - } - - public function getError(): \Throwable - { - return $this->error; - } - - public function setError(\Throwable $error): void - { - $this->error = $error; - } - - public function setExitCode(int $exitCode): void - { - $this->exitCode = $exitCode; - - $r = new \ReflectionProperty($this->error, 'code'); - $r->setAccessible(true); - $r->setValue($this->error, $this->exitCode); - } - - public function getExitCode(): int - { - return null !== $this->exitCode ? $this->exitCode : (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1); - } -} diff --git a/vendor/symfony/console/Event/ConsoleEvent.php b/vendor/symfony/console/Event/ConsoleEvent.php deleted file mode 100644 index 89ab645..0000000 --- a/vendor/symfony/console/Event/ConsoleEvent.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Contracts\EventDispatcher\Event; - -/** - * Allows to inspect input and output of a command. - * - * @author Francesco Levorato - */ -class ConsoleEvent extends Event -{ - protected $command; - - private $input; - private $output; - - public function __construct(Command $command = null, InputInterface $input, OutputInterface $output) - { - $this->command = $command; - $this->input = $input; - $this->output = $output; - } - - /** - * Gets the command that is executed. - * - * @return Command|null A Command instance - */ - public function getCommand() - { - return $this->command; - } - - /** - * Gets the input instance. - * - * @return InputInterface An InputInterface instance - */ - public function getInput() - { - return $this->input; - } - - /** - * Gets the output instance. - * - * @return OutputInterface An OutputInterface instance - */ - public function getOutput() - { - return $this->output; - } -} diff --git a/vendor/symfony/console/Event/ConsoleTerminateEvent.php b/vendor/symfony/console/Event/ConsoleTerminateEvent.php deleted file mode 100644 index 190038d..0000000 --- a/vendor/symfony/console/Event/ConsoleTerminateEvent.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Allows to manipulate the exit code of a command after its execution. - * - * @author Francesco Levorato - */ -final class ConsoleTerminateEvent extends ConsoleEvent -{ - private $exitCode; - - public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $exitCode) - { - parent::__construct($command, $input, $output); - - $this->setExitCode($exitCode); - } - - public function setExitCode(int $exitCode): void - { - $this->exitCode = $exitCode; - } - - public function getExitCode(): int - { - return $this->exitCode; - } -} diff --git a/vendor/symfony/console/EventListener/ErrorListener.php b/vendor/symfony/console/EventListener/ErrorListener.php deleted file mode 100644 index a340757..0000000 --- a/vendor/symfony/console/EventListener/ErrorListener.php +++ /dev/null @@ -1,95 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\EventListener; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Console\ConsoleEvents; -use Symfony\Component\Console\Event\ConsoleErrorEvent; -use Symfony\Component\Console\Event\ConsoleEvent; -use Symfony\Component\Console\Event\ConsoleTerminateEvent; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; - -/** - * @author James Halsall - * @author Robin Chalas - */ -class ErrorListener implements EventSubscriberInterface -{ - private $logger; - - public function __construct(LoggerInterface $logger = null) - { - $this->logger = $logger; - } - - public function onConsoleError(ConsoleErrorEvent $event) - { - if (null === $this->logger) { - return; - } - - $error = $event->getError(); - - if (!$inputString = $this->getInputString($event)) { - $this->logger->error('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]); - - return; - } - - $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]); - } - - public function onConsoleTerminate(ConsoleTerminateEvent $event) - { - if (null === $this->logger) { - return; - } - - $exitCode = $event->getExitCode(); - - if (0 === $exitCode) { - return; - } - - if (!$inputString = $this->getInputString($event)) { - $this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]); - - return; - } - - $this->logger->debug('Command "{command}" exited with code "{code}"', ['command' => $inputString, 'code' => $exitCode]); - } - - public static function getSubscribedEvents() - { - return [ - ConsoleEvents::ERROR => ['onConsoleError', -128], - ConsoleEvents::TERMINATE => ['onConsoleTerminate', -128], - ]; - } - - private static function getInputString(ConsoleEvent $event): ?string - { - $commandName = $event->getCommand() ? $event->getCommand()->getName() : null; - $input = $event->getInput(); - - if (method_exists($input, '__toString')) { - if ($commandName) { - return str_replace(["'$commandName'", "\"$commandName\""], $commandName, (string) $input); - } - - return (string) $input; - } - - return $commandName; - } -} diff --git a/vendor/symfony/console/Exception/CommandNotFoundException.php b/vendor/symfony/console/Exception/CommandNotFoundException.php deleted file mode 100644 index 69d5cb9..0000000 --- a/vendor/symfony/console/Exception/CommandNotFoundException.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * Represents an incorrect command name typed in the console. - * - * @author Jérôme Tamarelle - */ -class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface -{ - private $alternatives; - - /** - * @param string $message Exception message to throw - * @param array $alternatives List of similar defined names - * @param int $code Exception code - * @param \Throwable $previous Previous exception used for the exception chaining - */ - public function __construct(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null) - { - parent::__construct($message, $code, $previous); - - $this->alternatives = $alternatives; - } - - /** - * @return array A list of similar defined names - */ - public function getAlternatives() - { - return $this->alternatives; - } -} diff --git a/vendor/symfony/console/Exception/ExceptionInterface.php b/vendor/symfony/console/Exception/ExceptionInterface.php deleted file mode 100644 index 1624e13..0000000 --- a/vendor/symfony/console/Exception/ExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * ExceptionInterface. - * - * @author Jérôme Tamarelle - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/vendor/symfony/console/Exception/InvalidArgumentException.php b/vendor/symfony/console/Exception/InvalidArgumentException.php deleted file mode 100644 index 07cc0b6..0000000 --- a/vendor/symfony/console/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * @author Jérôme Tamarelle - */ -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/console/Exception/InvalidOptionException.php b/vendor/symfony/console/Exception/InvalidOptionException.php deleted file mode 100644 index b2eec61..0000000 --- a/vendor/symfony/console/Exception/InvalidOptionException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * Represents an incorrect option name typed in the console. - * - * @author Jérôme Tamarelle - */ -class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/console/Exception/LogicException.php b/vendor/symfony/console/Exception/LogicException.php deleted file mode 100644 index fc37b8d..0000000 --- a/vendor/symfony/console/Exception/LogicException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * @author Jérôme Tamarelle - */ -class LogicException extends \LogicException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/console/Exception/NamespaceNotFoundException.php b/vendor/symfony/console/Exception/NamespaceNotFoundException.php deleted file mode 100644 index dd16e45..0000000 --- a/vendor/symfony/console/Exception/NamespaceNotFoundException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * Represents an incorrect namespace typed in the console. - * - * @author Pierre du Plessis - */ -class NamespaceNotFoundException extends CommandNotFoundException -{ -} diff --git a/vendor/symfony/console/Exception/RuntimeException.php b/vendor/symfony/console/Exception/RuntimeException.php deleted file mode 100644 index 51d7d80..0000000 --- a/vendor/symfony/console/Exception/RuntimeException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Exception; - -/** - * @author Jérôme Tamarelle - */ -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/console/Formatter/OutputFormatter.php b/vendor/symfony/console/Formatter/OutputFormatter.php deleted file mode 100644 index 2ca63b6..0000000 --- a/vendor/symfony/console/Formatter/OutputFormatter.php +++ /dev/null @@ -1,275 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * Formatter class for console output. - * - * @author Konstantin Kudryashov - * @author Roland Franssen - */ -class OutputFormatter implements WrappableOutputFormatterInterface -{ - private $decorated; - private $styles = []; - private $styleStack; - - /** - * Escapes "<" special char in given text. - * - * @return string Escaped text - */ - public static function escape(string $text) - { - $text = preg_replace('/([^\\\\]?) FormatterStyle" instances - */ - public function __construct(bool $decorated = false, array $styles = []) - { - $this->decorated = $decorated; - - $this->setStyle('error', new OutputFormatterStyle('white', 'red')); - $this->setStyle('info', new OutputFormatterStyle('green')); - $this->setStyle('comment', new OutputFormatterStyle('yellow')); - $this->setStyle('question', new OutputFormatterStyle('black', 'cyan')); - - foreach ($styles as $name => $style) { - $this->setStyle($name, $style); - } - - $this->styleStack = new OutputFormatterStyleStack(); - } - - /** - * {@inheritdoc} - */ - public function setDecorated(bool $decorated) - { - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function isDecorated() - { - return $this->decorated; - } - - /** - * {@inheritdoc} - */ - public function setStyle(string $name, OutputFormatterStyleInterface $style) - { - $this->styles[strtolower($name)] = $style; - } - - /** - * {@inheritdoc} - */ - public function hasStyle(string $name) - { - return isset($this->styles[strtolower($name)]); - } - - /** - * {@inheritdoc} - */ - public function getStyle(string $name) - { - if (!$this->hasStyle($name)) { - throw new InvalidArgumentException(sprintf('Undefined style: %s', $name)); - } - - return $this->styles[strtolower($name)]; - } - - /** - * {@inheritdoc} - */ - public function format(?string $message) - { - return $this->formatAndWrap($message, 0); - } - - /** - * {@inheritdoc} - */ - public function formatAndWrap(?string $message, int $width) - { - $offset = 0; - $output = ''; - $tagRegex = '[a-z][^<>]*+'; - $currentLineLength = 0; - preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE); - foreach ($matches[0] as $i => $match) { - $pos = $match[1]; - $text = $match[0]; - - if (0 != $pos && '\\' == $message[$pos - 1]) { - continue; - } - - // add the text up to the next tag - $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength); - $offset = $pos + \strlen($text); - - // opening tag? - if ($open = '/' != $text[1]) { - $tag = $matches[1][$i][0]; - } else { - $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : ''; - } - - if (!$open && !$tag) { - // - $this->styleStack->pop(); - } elseif (null === $style = $this->createStyleFromString($tag)) { - $output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength); - } elseif ($open) { - $this->styleStack->push($style); - } else { - $this->styleStack->pop($style); - } - } - - $output .= $this->applyCurrentStyle(substr($message, $offset), $output, $width, $currentLineLength); - - if (false !== strpos($output, "\0")) { - return strtr($output, ["\0" => '\\', '\\<' => '<']); - } - - return str_replace('\\<', '<', $output); - } - - /** - * @return OutputFormatterStyleStack - */ - public function getStyleStack() - { - return $this->styleStack; - } - - /** - * Tries to create new style instance from string. - */ - private function createStyleFromString(string $string): ?OutputFormatterStyleInterface - { - if (isset($this->styles[$string])) { - return $this->styles[$string]; - } - - if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, PREG_SET_ORDER)) { - return null; - } - - $style = new OutputFormatterStyle(); - foreach ($matches as $match) { - array_shift($match); - $match[0] = strtolower($match[0]); - - if ('fg' == $match[0]) { - $style->setForeground(strtolower($match[1])); - } elseif ('bg' == $match[0]) { - $style->setBackground(strtolower($match[1])); - } elseif ('href' === $match[0]) { - $style->setHref($match[1]); - } elseif ('options' === $match[0]) { - preg_match_all('([^,;]+)', strtolower($match[1]), $options); - $options = array_shift($options); - foreach ($options as $option) { - $style->setOption($option); - } - } else { - return null; - } - } - - return $style; - } - - /** - * Applies current style from stack to text, if must be applied. - */ - private function applyCurrentStyle(string $text, string $current, int $width, int &$currentLineLength): string - { - if ('' === $text) { - return ''; - } - - if (!$width) { - return $this->isDecorated() ? $this->styleStack->getCurrent()->apply($text) : $text; - } - - if (!$currentLineLength && '' !== $current) { - $text = ltrim($text); - } - - if ($currentLineLength) { - $prefix = substr($text, 0, $i = $width - $currentLineLength)."\n"; - $text = substr($text, $i); - } else { - $prefix = ''; - } - - preg_match('~(\\n)$~', $text, $matches); - $text = $prefix.preg_replace('~([^\\n]{'.$width.'})\\ *~', "\$1\n", $text); - $text = rtrim($text, "\n").($matches[1] ?? ''); - - if (!$currentLineLength && '' !== $current && "\n" !== substr($current, -1)) { - $text = "\n".$text; - } - - $lines = explode("\n", $text); - - foreach ($lines as $line) { - $currentLineLength += \strlen($line); - if ($width <= $currentLineLength) { - $currentLineLength = 0; - } - } - - if ($this->isDecorated()) { - foreach ($lines as $i => $line) { - $lines[$i] = $this->styleStack->getCurrent()->apply($line); - } - } - - return implode("\n", $lines); - } -} diff --git a/vendor/symfony/console/Formatter/OutputFormatterInterface.php b/vendor/symfony/console/Formatter/OutputFormatterInterface.php deleted file mode 100644 index 8c50d41..0000000 --- a/vendor/symfony/console/Formatter/OutputFormatterInterface.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter interface for console output. - * - * @author Konstantin Kudryashov - */ -interface OutputFormatterInterface -{ - /** - * Sets the decorated flag. - */ - public function setDecorated(bool $decorated); - - /** - * Gets the decorated flag. - * - * @return bool true if the output will decorate messages, false otherwise - */ - public function isDecorated(); - - /** - * Sets a new style. - */ - public function setStyle(string $name, OutputFormatterStyleInterface $style); - - /** - * Checks if output formatter has style with specified name. - * - * @return bool - */ - public function hasStyle(string $name); - - /** - * Gets style options from style with specified name. - * - * @return OutputFormatterStyleInterface - * - * @throws \InvalidArgumentException When style isn't defined - */ - public function getStyle(string $name); - - /** - * Formats a message according to the given styles. - */ - public function format(?string $message); -} diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyle.php b/vendor/symfony/console/Formatter/OutputFormatterStyle.php deleted file mode 100644 index c5d3ea1..0000000 --- a/vendor/symfony/console/Formatter/OutputFormatterStyle.php +++ /dev/null @@ -1,196 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * Formatter style class for defining styles. - * - * @author Konstantin Kudryashov - */ -class OutputFormatterStyle implements OutputFormatterStyleInterface -{ - private static $availableForegroundColors = [ - 'black' => ['set' => 30, 'unset' => 39], - 'red' => ['set' => 31, 'unset' => 39], - 'green' => ['set' => 32, 'unset' => 39], - 'yellow' => ['set' => 33, 'unset' => 39], - 'blue' => ['set' => 34, 'unset' => 39], - 'magenta' => ['set' => 35, 'unset' => 39], - 'cyan' => ['set' => 36, 'unset' => 39], - 'white' => ['set' => 37, 'unset' => 39], - 'default' => ['set' => 39, 'unset' => 39], - ]; - private static $availableBackgroundColors = [ - 'black' => ['set' => 40, 'unset' => 49], - 'red' => ['set' => 41, 'unset' => 49], - 'green' => ['set' => 42, 'unset' => 49], - 'yellow' => ['set' => 43, 'unset' => 49], - 'blue' => ['set' => 44, 'unset' => 49], - 'magenta' => ['set' => 45, 'unset' => 49], - 'cyan' => ['set' => 46, 'unset' => 49], - 'white' => ['set' => 47, 'unset' => 49], - 'default' => ['set' => 49, 'unset' => 49], - ]; - private static $availableOptions = [ - 'bold' => ['set' => 1, 'unset' => 22], - 'underscore' => ['set' => 4, 'unset' => 24], - 'blink' => ['set' => 5, 'unset' => 25], - 'reverse' => ['set' => 7, 'unset' => 27], - 'conceal' => ['set' => 8, 'unset' => 28], - ]; - - private $foreground; - private $background; - private $href; - private $options = []; - private $handlesHrefGracefully; - - /** - * Initializes output formatter style. - * - * @param string|null $foreground The style foreground color name - * @param string|null $background The style background color name - */ - public function __construct(string $foreground = null, string $background = null, array $options = []) - { - if (null !== $foreground) { - $this->setForeground($foreground); - } - if (null !== $background) { - $this->setBackground($background); - } - if (\count($options)) { - $this->setOptions($options); - } - } - - /** - * {@inheritdoc} - */ - public function setForeground(string $color = null) - { - if (null === $color) { - $this->foreground = null; - - return; - } - - if (!isset(static::$availableForegroundColors[$color])) { - throw new InvalidArgumentException(sprintf('Invalid foreground color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableForegroundColors)))); - } - - $this->foreground = static::$availableForegroundColors[$color]; - } - - /** - * {@inheritdoc} - */ - public function setBackground(string $color = null) - { - if (null === $color) { - $this->background = null; - - return; - } - - if (!isset(static::$availableBackgroundColors[$color])) { - throw new InvalidArgumentException(sprintf('Invalid background color specified: "%s". Expected one of (%s)', $color, implode(', ', array_keys(static::$availableBackgroundColors)))); - } - - $this->background = static::$availableBackgroundColors[$color]; - } - - public function setHref(string $url): void - { - $this->href = $url; - } - - /** - * {@inheritdoc} - */ - public function setOption(string $option) - { - if (!isset(static::$availableOptions[$option])) { - throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions)))); - } - - if (!\in_array(static::$availableOptions[$option], $this->options)) { - $this->options[] = static::$availableOptions[$option]; - } - } - - /** - * {@inheritdoc} - */ - public function unsetOption(string $option) - { - if (!isset(static::$availableOptions[$option])) { - throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s)', $option, implode(', ', array_keys(static::$availableOptions)))); - } - - $pos = array_search(static::$availableOptions[$option], $this->options); - if (false !== $pos) { - unset($this->options[$pos]); - } - } - - /** - * {@inheritdoc} - */ - public function setOptions(array $options) - { - $this->options = []; - - foreach ($options as $option) { - $this->setOption($option); - } - } - - /** - * {@inheritdoc} - */ - public function apply(string $text) - { - $setCodes = []; - $unsetCodes = []; - - if (null === $this->handlesHrefGracefully) { - $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') && !getenv('KONSOLE_VERSION'); - } - - if (null !== $this->foreground) { - $setCodes[] = $this->foreground['set']; - $unsetCodes[] = $this->foreground['unset']; - } - if (null !== $this->background) { - $setCodes[] = $this->background['set']; - $unsetCodes[] = $this->background['unset']; - } - - foreach ($this->options as $option) { - $setCodes[] = $option['set']; - $unsetCodes[] = $option['unset']; - } - - if (null !== $this->href && $this->handlesHrefGracefully) { - $text = "\033]8;;$this->href\033\\$text\033]8;;\033\\"; - } - - if (0 === \count($setCodes)) { - return $text; - } - - return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes)); - } -} diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php b/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php deleted file mode 100644 index b30560d..0000000 --- a/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter style interface for defining styles. - * - * @author Konstantin Kudryashov - */ -interface OutputFormatterStyleInterface -{ - /** - * Sets style foreground color. - */ - public function setForeground(string $color = null); - - /** - * Sets style background color. - */ - public function setBackground(string $color = null); - - /** - * Sets some specific style option. - */ - public function setOption(string $option); - - /** - * Unsets some specific style option. - */ - public function unsetOption(string $option); - - /** - * Sets multiple style options at once. - */ - public function setOptions(array $options); - - /** - * Applies the style to a given text. - * - * @return string - */ - public function apply(string $text); -} diff --git a/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php b/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php deleted file mode 100644 index 33f7d52..0000000 --- a/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php +++ /dev/null @@ -1,110 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Contracts\Service\ResetInterface; - -/** - * @author Jean-François Simon - */ -class OutputFormatterStyleStack implements ResetInterface -{ - /** - * @var OutputFormatterStyleInterface[] - */ - private $styles; - - private $emptyStyle; - - public function __construct(OutputFormatterStyleInterface $emptyStyle = null) - { - $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle(); - $this->reset(); - } - - /** - * Resets stack (ie. empty internal arrays). - */ - public function reset() - { - $this->styles = []; - } - - /** - * Pushes a style in the stack. - */ - public function push(OutputFormatterStyleInterface $style) - { - $this->styles[] = $style; - } - - /** - * Pops a style from the stack. - * - * @return OutputFormatterStyleInterface - * - * @throws InvalidArgumentException When style tags incorrectly nested - */ - public function pop(OutputFormatterStyleInterface $style = null) - { - if (empty($this->styles)) { - return $this->emptyStyle; - } - - if (null === $style) { - return array_pop($this->styles); - } - - foreach (array_reverse($this->styles, true) as $index => $stackedStyle) { - if ($style->apply('') === $stackedStyle->apply('')) { - $this->styles = \array_slice($this->styles, 0, $index); - - return $stackedStyle; - } - } - - throw new InvalidArgumentException('Incorrectly nested style tag found.'); - } - - /** - * Computes current style with stacks top codes. - * - * @return OutputFormatterStyle - */ - public function getCurrent() - { - if (empty($this->styles)) { - return $this->emptyStyle; - } - - return $this->styles[\count($this->styles) - 1]; - } - - /** - * @return $this - */ - public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle) - { - $this->emptyStyle = $emptyStyle; - - return $this; - } - - /** - * @return OutputFormatterStyleInterface - */ - public function getEmptyStyle() - { - return $this->emptyStyle; - } -} diff --git a/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php b/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php deleted file mode 100644 index 42319ee..0000000 --- a/vendor/symfony/console/Formatter/WrappableOutputFormatterInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Formatter; - -/** - * Formatter interface for console output that supports word wrapping. - * - * @author Roland Franssen - */ -interface WrappableOutputFormatterInterface extends OutputFormatterInterface -{ - /** - * Formats a message according to the given styles, wrapping at `$width` (0 means no wrapping). - */ - public function formatAndWrap(?string $message, int $width); -} diff --git a/vendor/symfony/console/Helper/DebugFormatterHelper.php b/vendor/symfony/console/Helper/DebugFormatterHelper.php deleted file mode 100644 index 9d07ec2..0000000 --- a/vendor/symfony/console/Helper/DebugFormatterHelper.php +++ /dev/null @@ -1,107 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -/** - * Helps outputting debug information when running an external program from a command. - * - * An external program can be a Process, an HTTP request, or anything else. - * - * @author Fabien Potencier - */ -class DebugFormatterHelper extends Helper -{ - private $colors = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default']; - private $started = []; - private $count = -1; - - /** - * Starts a debug formatting session. - * - * @return string - */ - public function start(string $id, string $message, string $prefix = 'RUN') - { - $this->started[$id] = ['border' => ++$this->count % \count($this->colors)]; - - return sprintf("%s %s %s\n", $this->getBorder($id), $prefix, $message); - } - - /** - * Adds progress to a formatting session. - * - * @return string - */ - public function progress(string $id, string $buffer, bool $error = false, string $prefix = 'OUT', string $errorPrefix = 'ERR') - { - $message = ''; - - if ($error) { - if (isset($this->started[$id]['out'])) { - $message .= "\n"; - unset($this->started[$id]['out']); - } - if (!isset($this->started[$id]['err'])) { - $message .= sprintf('%s %s ', $this->getBorder($id), $errorPrefix); - $this->started[$id]['err'] = true; - } - - $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $errorPrefix), $buffer); - } else { - if (isset($this->started[$id]['err'])) { - $message .= "\n"; - unset($this->started[$id]['err']); - } - if (!isset($this->started[$id]['out'])) { - $message .= sprintf('%s %s ', $this->getBorder($id), $prefix); - $this->started[$id]['out'] = true; - } - - $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $prefix), $buffer); - } - - return $message; - } - - /** - * Stops a formatting session. - * - * @return string - */ - public function stop(string $id, string $message, bool $successful, string $prefix = 'RES') - { - $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : ''; - - if ($successful) { - return sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); - } - - $message = sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); - - unset($this->started[$id]['out'], $this->started[$id]['err']); - - return $message; - } - - private function getBorder(string $id): string - { - return sprintf(' ', $this->colors[$this->started[$id]['border']]); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'debug_formatter'; - } -} diff --git a/vendor/symfony/console/Helper/DescriptorHelper.php b/vendor/symfony/console/Helper/DescriptorHelper.php deleted file mode 100644 index f2ad9db..0000000 --- a/vendor/symfony/console/Helper/DescriptorHelper.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Descriptor\DescriptorInterface; -use Symfony\Component\Console\Descriptor\JsonDescriptor; -use Symfony\Component\Console\Descriptor\MarkdownDescriptor; -use Symfony\Component\Console\Descriptor\TextDescriptor; -use Symfony\Component\Console\Descriptor\XmlDescriptor; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * This class adds helper method to describe objects in various formats. - * - * @author Jean-François Simon - */ -class DescriptorHelper extends Helper -{ - /** - * @var DescriptorInterface[] - */ - private $descriptors = []; - - public function __construct() - { - $this - ->register('txt', new TextDescriptor()) - ->register('xml', new XmlDescriptor()) - ->register('json', new JsonDescriptor()) - ->register('md', new MarkdownDescriptor()) - ; - } - - /** - * Describes an object if supported. - * - * Available options are: - * * format: string, the output format name - * * raw_text: boolean, sets output type as raw - * - * @throws InvalidArgumentException when the given format is not supported - */ - public function describe(OutputInterface $output, ?object $object, array $options = []) - { - $options = array_merge([ - 'raw_text' => false, - 'format' => 'txt', - ], $options); - - if (!isset($this->descriptors[$options['format']])) { - throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format'])); - } - - $descriptor = $this->descriptors[$options['format']]; - $descriptor->describe($output, $object, $options); - } - - /** - * Registers a descriptor. - * - * @return $this - */ - public function register(string $format, DescriptorInterface $descriptor) - { - $this->descriptors[$format] = $descriptor; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'descriptor'; - } -} diff --git a/vendor/symfony/console/Helper/Dumper.php b/vendor/symfony/console/Helper/Dumper.php deleted file mode 100644 index b013b6c..0000000 --- a/vendor/symfony/console/Helper/Dumper.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\VarDumper\Cloner\ClonerInterface; -use Symfony\Component\VarDumper\Cloner\VarCloner; -use Symfony\Component\VarDumper\Dumper\CliDumper; - -/** - * @author Roland Franssen - */ -final class Dumper -{ - private $output; - private $dumper; - private $cloner; - private $handler; - - public function __construct(OutputInterface $output, CliDumper $dumper = null, ClonerInterface $cloner = null) - { - $this->output = $output; - $this->dumper = $dumper; - $this->cloner = $cloner; - - if (class_exists(CliDumper::class)) { - $this->handler = function ($var): string { - $dumper = $this->dumper ?? $this->dumper = new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR); - $dumper->setColors($this->output->isDecorated()); - - return rtrim($dumper->dump(($this->cloner ?? $this->cloner = new VarCloner())->cloneVar($var)->withRefHandles(false), true)); - }; - } else { - $this->handler = function ($var): string { - switch (true) { - case null === $var: - return 'null'; - case true === $var: - return 'true'; - case false === $var: - return 'false'; - case \is_string($var): - return '"'.$var.'"'; - default: - return rtrim(print_r($var, true)); - } - }; - } - } - - public function __invoke($var): string - { - return ($this->handler)($var); - } -} diff --git a/vendor/symfony/console/Helper/FormatterHelper.php b/vendor/symfony/console/Helper/FormatterHelper.php deleted file mode 100644 index 75c9b61..0000000 --- a/vendor/symfony/console/Helper/FormatterHelper.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Formatter\OutputFormatter; - -/** - * The Formatter class provides helpers to format messages. - * - * @author Fabien Potencier - */ -class FormatterHelper extends Helper -{ - /** - * Formats a message within a section. - * - * @return string The format section - */ - public function formatSection(string $section, string $message, string $style = 'info') - { - return sprintf('<%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 - * - * @return string The formatter message - */ - public function formatBlock($messages, string $style, bool $large = false) - { - if (!\is_array($messages)) { - $messages = [$messages]; - } - - $len = 0; - $lines = []; - foreach ($messages as $message) { - $message = OutputFormatter::escape($message); - $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); - $len = max($this->strlen($message) + ($large ? 4 : 2), $len); - } - - $messages = $large ? [str_repeat(' ', $len)] : []; - for ($i = 0; isset($lines[$i]); ++$i) { - $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i])); - } - if ($large) { - $messages[] = str_repeat(' ', $len); - } - - for ($i = 0; isset($messages[$i]); ++$i) { - $messages[$i] = sprintf('<%s>%s', $style, $messages[$i], $style); - } - - return implode("\n", $messages); - } - - /** - * Truncates a message to the given length. - * - * @return string - */ - public function truncate(string $message, int $length, string $suffix = '...') - { - $computedLength = $length - $this->strlen($suffix); - - if ($computedLength > $this->strlen($message)) { - return $message; - } - - if (false === $encoding = mb_detect_encoding($message, null, true)) { - return substr($message, 0, $length).$suffix; - } - - return mb_substr($message, 0, $length, $encoding).$suffix; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'formatter'; - } -} diff --git a/vendor/symfony/console/Helper/Helper.php b/vendor/symfony/console/Helper/Helper.php deleted file mode 100644 index e52e315..0000000 --- a/vendor/symfony/console/Helper/Helper.php +++ /dev/null @@ -1,132 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * Helper is the base class for all helper classes. - * - * @author Fabien Potencier - */ -abstract class Helper implements HelperInterface -{ - protected $helperSet = null; - - /** - * {@inheritdoc} - */ - public function setHelperSet(HelperSet $helperSet = null) - { - $this->helperSet = $helperSet; - } - - /** - * {@inheritdoc} - */ - public function getHelperSet() - { - return $this->helperSet; - } - - /** - * Returns the length of a string, using mb_strwidth if it is available. - * - * @return int The length of the string - */ - public static function strlen(?string $string) - { - if (false === $encoding = mb_detect_encoding($string, null, true)) { - return \strlen($string); - } - - return mb_strwidth($string, $encoding); - } - - /** - * Returns the subset of a string, using mb_substr if it is available. - * - * @return string The string subset - */ - public static function substr(string $string, int $from, int $length = null) - { - if (false === $encoding = mb_detect_encoding($string, null, true)) { - return substr($string, $from, $length); - } - - return mb_substr($string, $from, $length, $encoding); - } - - public static function formatTime($secs) - { - static $timeFormats = [ - [0, '< 1 sec'], - [1, '1 sec'], - [2, 'secs', 1], - [60, '1 min'], - [120, 'mins', 60], - [3600, '1 hr'], - [7200, 'hrs', 3600], - [86400, '1 day'], - [172800, 'days', 86400], - ]; - - foreach ($timeFormats as $index => $format) { - if ($secs >= $format[0]) { - if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0]) - || $index == \count($timeFormats) - 1 - ) { - if (2 == \count($format)) { - return $format[1]; - } - - return floor($secs / $format[2]).' '.$format[1]; - } - } - } - } - - public static function formatMemory(int $memory) - { - if ($memory >= 1024 * 1024 * 1024) { - return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024); - } - - if ($memory >= 1024 * 1024) { - return sprintf('%.1f MiB', $memory / 1024 / 1024); - } - - if ($memory >= 1024) { - return sprintf('%d KiB', $memory / 1024); - } - - return sprintf('%d B', $memory); - } - - public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string) - { - return self::strlen(self::removeDecoration($formatter, $string)); - } - - public static function removeDecoration(OutputFormatterInterface $formatter, $string) - { - $isDecorated = $formatter->isDecorated(); - $formatter->setDecorated(false); - // remove <...> formatting - $string = $formatter->format($string); - // remove already formatted characters - $string = preg_replace("/\033\[[^m]*m/", '', $string); - $formatter->setDecorated($isDecorated); - - return $string; - } -} diff --git a/vendor/symfony/console/Helper/HelperInterface.php b/vendor/symfony/console/Helper/HelperInterface.php deleted file mode 100644 index 1ce8235..0000000 --- a/vendor/symfony/console/Helper/HelperInterface.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -/** - * HelperInterface is the interface all helpers must implement. - * - * @author Fabien Potencier - */ -interface HelperInterface -{ - /** - * Sets the helper set associated with this helper. - */ - public function setHelperSet(HelperSet $helperSet = null); - - /** - * Gets the helper set associated with this helper. - * - * @return HelperSet A HelperSet instance - */ - public function getHelperSet(); - - /** - * Returns the canonical name of this helper. - * - * @return string The canonical name - */ - public function getName(); -} diff --git a/vendor/symfony/console/Helper/HelperSet.php b/vendor/symfony/console/Helper/HelperSet.php deleted file mode 100644 index 5c08a76..0000000 --- a/vendor/symfony/console/Helper/HelperSet.php +++ /dev/null @@ -1,98 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * HelperSet represents a set of helpers to be used with a command. - * - * @author Fabien Potencier - */ -class HelperSet implements \IteratorAggregate -{ - /** - * @var Helper[] - */ - private $helpers = []; - private $command; - - /** - * @param Helper[] $helpers An array of helper - */ - public function __construct(array $helpers = []) - { - foreach ($helpers as $alias => $helper) { - $this->set($helper, \is_int($alias) ? null : $alias); - } - } - - public function set(HelperInterface $helper, string $alias = null) - { - $this->helpers[$helper->getName()] = $helper; - if (null !== $alias) { - $this->helpers[$alias] = $helper; - } - - $helper->setHelperSet($this); - } - - /** - * Returns true if the helper if defined. - * - * @return bool true if the helper is defined, false otherwise - */ - public function has(string $name) - { - return isset($this->helpers[$name]); - } - - /** - * Gets a helper value. - * - * @return HelperInterface The helper instance - * - * @throws InvalidArgumentException if the helper is not defined - */ - public function get(string $name) - { - if (!$this->has($name)) { - throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); - } - - return $this->helpers[$name]; - } - - 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; - } - - /** - * @return Helper[] - */ - public function getIterator() - { - return new \ArrayIterator($this->helpers); - } -} diff --git a/vendor/symfony/console/Helper/InputAwareHelper.php b/vendor/symfony/console/Helper/InputAwareHelper.php deleted file mode 100644 index 0d0dba2..0000000 --- a/vendor/symfony/console/Helper/InputAwareHelper.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Input\InputAwareInterface; -use Symfony\Component\Console\Input\InputInterface; - -/** - * An implementation of InputAwareInterface for Helpers. - * - * @author Wouter J - */ -abstract class InputAwareHelper extends Helper implements InputAwareInterface -{ - protected $input; - - /** - * {@inheritdoc} - */ - public function setInput(InputInterface $input) - { - $this->input = $input; - } -} diff --git a/vendor/symfony/console/Helper/ProcessHelper.php b/vendor/symfony/console/Helper/ProcessHelper.php deleted file mode 100644 index 944c593..0000000 --- a/vendor/symfony/console/Helper/ProcessHelper.php +++ /dev/null @@ -1,144 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Process\Exception\ProcessFailedException; -use Symfony\Component\Process\Process; - -/** - * The ProcessHelper class provides helpers to run external processes. - * - * @author Fabien Potencier - * - * @final - */ -class ProcessHelper extends Helper -{ - /** - * Runs an external process. - * - * @param array|Process $cmd An instance of Process or an array of the command and arguments - * @param callable|null $callback A PHP callback to run whenever there is some - * output available on STDOUT or STDERR - * - * @return Process The process that ran - */ - public function run(OutputInterface $output, $cmd, string $error = null, callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process - { - if ($output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - - $formatter = $this->getHelperSet()->get('debug_formatter'); - - if ($cmd instanceof Process) { - $cmd = [$cmd]; - } - - if (!\is_array($cmd)) { - throw new \TypeError(sprintf('The "command" argument of "%s()" must be an array or a "%s" instance, "%s" given.', __METHOD__, Process::class, \is_object($cmd) ? \get_class($cmd) : \gettype($cmd))); - } - - if (\is_string($cmd[0] ?? null)) { - $process = new Process($cmd); - $cmd = []; - } elseif (($cmd[0] ?? null) instanceof Process) { - $process = $cmd[0]; - unset($cmd[0]); - } else { - throw new \InvalidArgumentException(sprintf('Invalid command provided to "%s()": the command should be an array whose first element is either the path to the binary to run or a "Process" object.', __METHOD__)); - } - - if ($verbosity <= $output->getVerbosity()) { - $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine()))); - } - - if ($output->isDebug()) { - $callback = $this->wrapCallback($output, $process, $callback); - } - - $process->run($callback, $cmd); - - if ($verbosity <= $output->getVerbosity()) { - $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode()); - $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful())); - } - - if (!$process->isSuccessful() && null !== $error) { - $output->writeln(sprintf('%s', $this->escapeString($error))); - } - - return $process; - } - - /** - * Runs the process. - * - * This is identical to run() except that an exception is thrown if the process - * exits with a non-zero exit code. - * - * @param string|Process $cmd An instance of Process or a command to run - * @param callable|null $callback A PHP callback to run whenever there is some - * output available on STDOUT or STDERR - * - * @return Process The process that ran - * - * @throws ProcessFailedException - * - * @see run() - */ - public function mustRun(OutputInterface $output, $cmd, string $error = null, callable $callback = null): Process - { - $process = $this->run($output, $cmd, $error, $callback); - - if (!$process->isSuccessful()) { - throw new ProcessFailedException($process); - } - - return $process; - } - - /** - * Wraps a Process callback to add debugging output. - */ - public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null): callable - { - if ($output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - - $formatter = $this->getHelperSet()->get('debug_formatter'); - - return function ($type, $buffer) use ($output, $process, $callback, $formatter) { - $output->write($formatter->progress(spl_object_hash($process), $this->escapeString($buffer), Process::ERR === $type)); - - if (null !== $callback) { - $callback($type, $buffer); - } - }; - } - - private function escapeString(string $str): string - { - return str_replace('<', '\\<', $str); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return 'process'; - } -} diff --git a/vendor/symfony/console/Helper/ProgressBar.php b/vendor/symfony/console/Helper/ProgressBar.php deleted file mode 100644 index e4f0a99..0000000 --- a/vendor/symfony/console/Helper/ProgressBar.php +++ /dev/null @@ -1,592 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\ConsoleSectionOutput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Terminal; - -/** - * The ProgressBar provides helpers to display progress output. - * - * @author Fabien Potencier - * @author Chris Jones - */ -final class ProgressBar -{ - private $barWidth = 28; - private $barChar; - private $emptyBarChar = '-'; - private $progressChar = '>'; - private $format; - private $internalFormat; - private $redrawFreq = 1; - private $writeCount; - private $lastWriteTime; - private $minSecondsBetweenRedraws = 0; - private $maxSecondsBetweenRedraws = 1; - private $output; - private $step = 0; - private $max; - private $startTime; - private $stepWidth; - private $percent = 0.0; - private $formatLineCount; - private $messages = []; - private $overwrite = true; - private $terminal; - private $previousMessage; - - private static $formatters; - private static $formats; - - /** - * @param int $max Maximum steps (0 if unknown) - */ - public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 0.1) - { - if ($output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - - $this->output = $output; - $this->setMaxSteps($max); - $this->terminal = new Terminal(); - - if (0 < $minSecondsBetweenRedraws) { - $this->redrawFreq = null; - $this->minSecondsBetweenRedraws = $minSecondsBetweenRedraws; - } - - if (!$this->output->isDecorated()) { - // disable overwrite when output does not support ANSI codes. - $this->overwrite = false; - - // set a reasonable redraw frequency so output isn't flooded - $this->redrawFreq = null; - } - - $this->startTime = time(); - } - - /** - * Sets a placeholder formatter for a given name. - * - * This method also allow you to override an existing placeholder. - * - * @param string $name The placeholder name (including the delimiter char like %) - * @param callable $callable A PHP callable - */ - public static function setPlaceholderFormatterDefinition(string $name, callable $callable): void - { - if (!self::$formatters) { - self::$formatters = self::initPlaceholderFormatters(); - } - - self::$formatters[$name] = $callable; - } - - /** - * Gets the placeholder formatter for a given name. - * - * @param string $name The placeholder name (including the delimiter char like %) - * - * @return callable|null A PHP callable - */ - public static function getPlaceholderFormatterDefinition(string $name): ?callable - { - if (!self::$formatters) { - self::$formatters = self::initPlaceholderFormatters(); - } - - return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; - } - - /** - * Sets a format for a given name. - * - * This method also allow you to override an existing format. - * - * @param string $name The format name - * @param string $format A format string - */ - public static function setFormatDefinition(string $name, string $format): void - { - if (!self::$formats) { - self::$formats = self::initFormats(); - } - - self::$formats[$name] = $format; - } - - /** - * Gets the format for a given name. - * - * @param string $name The format name - * - * @return string|null A format string - */ - public static function getFormatDefinition(string $name): ?string - { - if (!self::$formats) { - self::$formats = self::initFormats(); - } - - return isset(self::$formats[$name]) ? self::$formats[$name] : null; - } - - /** - * Associates a text with a named placeholder. - * - * The text is displayed when the progress bar is rendered but only - * when the corresponding placeholder is part of the custom format line - * (by wrapping the name with %). - * - * @param string $message The text to associate with the placeholder - * @param string $name The name of the placeholder - */ - public function setMessage(string $message, string $name = 'message') - { - $this->messages[$name] = $message; - } - - public function getMessage(string $name = 'message') - { - return $this->messages[$name]; - } - - public function getStartTime(): int - { - return $this->startTime; - } - - public function getMaxSteps(): int - { - return $this->max; - } - - public function getProgress(): int - { - return $this->step; - } - - private function getStepWidth(): int - { - return $this->stepWidth; - } - - public function getProgressPercent(): float - { - return $this->percent; - } - - public function getBarOffset(): int - { - return floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? min(5, $this->barWidth / 15) * $this->writeCount : $this->step) % $this->barWidth); - } - - public function setBarWidth(int $size) - { - $this->barWidth = max(1, $size); - } - - public function getBarWidth(): int - { - return $this->barWidth; - } - - public function setBarCharacter(string $char) - { - $this->barChar = $char; - } - - public function getBarCharacter(): string - { - if (null === $this->barChar) { - return $this->max ? '=' : $this->emptyBarChar; - } - - return $this->barChar; - } - - public function setEmptyBarCharacter(string $char) - { - $this->emptyBarChar = $char; - } - - public function getEmptyBarCharacter(): string - { - return $this->emptyBarChar; - } - - public function setProgressCharacter(string $char) - { - $this->progressChar = $char; - } - - public function getProgressCharacter(): string - { - return $this->progressChar; - } - - public function setFormat(string $format) - { - $this->format = null; - $this->internalFormat = $format; - } - - /** - * Sets the redraw frequency. - * - * @param int|float $freq The frequency in steps - */ - public function setRedrawFrequency(?int $freq) - { - $this->redrawFreq = null !== $freq ? max(1, $freq) : null; - } - - public function minSecondsBetweenRedraws(float $seconds): void - { - $this->minSecondsBetweenRedraws = $seconds; - } - - public function maxSecondsBetweenRedraws(float $seconds): void - { - $this->maxSecondsBetweenRedraws = $seconds; - } - - /** - * Returns an iterator that will automatically update the progress bar when iterated. - * - * @param int|null $max Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable - */ - public function iterate(iterable $iterable, int $max = null): iterable - { - $this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0)); - - foreach ($iterable as $key => $value) { - yield $key => $value; - - $this->advance(); - } - - $this->finish(); - } - - /** - * Starts the progress output. - * - * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged - */ - public function start(int $max = null) - { - $this->startTime = time(); - $this->step = 0; - $this->percent = 0.0; - - if (null !== $max) { - $this->setMaxSteps($max); - } - - $this->display(); - } - - /** - * Advances the progress output X steps. - * - * @param int $step Number of steps to advance - */ - public function advance(int $step = 1) - { - $this->setProgress($this->step + $step); - } - - /** - * Sets whether to overwrite the progressbar, false for new line. - */ - public function setOverwrite(bool $overwrite) - { - $this->overwrite = $overwrite; - } - - public function setProgress(int $step) - { - if ($this->max && $step > $this->max) { - $this->max = $step; - } elseif ($step < 0) { - $step = 0; - } - - $redrawFreq = $this->redrawFreq ?? (($this->max ?: 10) / 10); - $prevPeriod = (int) ($this->step / $redrawFreq); - $currPeriod = (int) ($step / $redrawFreq); - $this->step = $step; - $this->percent = $this->max ? (float) $this->step / $this->max : 0; - $timeInterval = microtime(true) - $this->lastWriteTime; - - // Draw regardless of other limits - if ($this->max === $step) { - $this->display(); - - return; - } - - // Throttling - if ($timeInterval < $this->minSecondsBetweenRedraws) { - return; - } - - // Draw each step period, but not too late - if ($prevPeriod !== $currPeriod || $timeInterval >= $this->maxSecondsBetweenRedraws) { - $this->display(); - } - } - - public function setMaxSteps(int $max) - { - $this->format = null; - $this->max = max(0, $max); - $this->stepWidth = $this->max ? Helper::strlen((string) $this->max) : 4; - } - - /** - * Finishes the progress output. - */ - public function finish(): void - { - if (!$this->max) { - $this->max = $this->step; - } - - if ($this->step === $this->max && !$this->overwrite) { - // prevent double 100% output - return; - } - - $this->setProgress($this->max); - } - - /** - * Outputs the current progress string. - */ - public function display(): void - { - if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { - return; - } - - if (null === $this->format) { - $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat()); - } - - $this->overwrite($this->buildLine()); - } - - /** - * Removes the progress bar from the current line. - * - * This is useful if you wish to write some output - * while a progress bar is running. - * Call display() to show the progress bar again. - */ - public function clear(): void - { - if (!$this->overwrite) { - return; - } - - if (null === $this->format) { - $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat()); - } - - $this->overwrite(''); - } - - private function setRealFormat(string $format) - { - // try to use the _nomax variant if available - if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) { - $this->format = self::getFormatDefinition($format.'_nomax'); - } elseif (null !== self::getFormatDefinition($format)) { - $this->format = self::getFormatDefinition($format); - } else { - $this->format = $format; - } - - $this->formatLineCount = substr_count($this->format, "\n"); - } - - /** - * Overwrites a previous message to the output. - */ - private function overwrite(string $message): void - { - if ($this->previousMessage === $message) { - return; - } - - $originalMessage = $message; - - if ($this->overwrite) { - if (null !== $this->previousMessage) { - if ($this->output instanceof ConsoleSectionOutput) { - $lines = floor(Helper::strlen($message) / $this->terminal->getWidth()) + $this->formatLineCount + 1; - $this->output->clear($lines); - } else { - // Erase previous lines - if ($this->formatLineCount > 0) { - $message = str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount).$message; - } - - // Move the cursor to the beginning of the line and erase the line - $message = "\x0D\x1B[2K$message"; - } - } - } elseif ($this->step > 0) { - $message = PHP_EOL.$message; - } - - $this->previousMessage = $originalMessage; - $this->lastWriteTime = microtime(true); - - $this->output->write($message); - ++$this->writeCount; - } - - private function determineBestFormat(): string - { - switch ($this->output->getVerbosity()) { - // OutputInterface::VERBOSITY_QUIET: display is disabled anyway - case OutputInterface::VERBOSITY_VERBOSE: - return $this->max ? 'verbose' : 'verbose_nomax'; - case OutputInterface::VERBOSITY_VERY_VERBOSE: - return $this->max ? 'very_verbose' : 'very_verbose_nomax'; - case OutputInterface::VERBOSITY_DEBUG: - return $this->max ? 'debug' : 'debug_nomax'; - default: - return $this->max ? 'normal' : 'normal_nomax'; - } - } - - private static function initPlaceholderFormatters(): array - { - return [ - 'bar' => function (self $bar, OutputInterface $output) { - $completeBars = $bar->getBarOffset(); - $display = str_repeat($bar->getBarCharacter(), $completeBars); - if ($completeBars < $bar->getBarWidth()) { - $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter()); - $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars); - } - - return $display; - }, - 'elapsed' => function (self $bar) { - return Helper::formatTime(time() - $bar->getStartTime()); - }, - 'remaining' => function (self $bar) { - if (!$bar->getMaxSteps()) { - throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.'); - } - - if (!$bar->getProgress()) { - $remaining = 0; - } else { - $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress())); - } - - return Helper::formatTime($remaining); - }, - 'estimated' => function (self $bar) { - if (!$bar->getMaxSteps()) { - throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.'); - } - - if (!$bar->getProgress()) { - $estimated = 0; - } else { - $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps()); - } - - return Helper::formatTime($estimated); - }, - 'memory' => function (self $bar) { - return Helper::formatMemory(memory_get_usage(true)); - }, - 'current' => function (self $bar) { - return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT); - }, - 'max' => function (self $bar) { - return $bar->getMaxSteps(); - }, - 'percent' => function (self $bar) { - return floor($bar->getProgressPercent() * 100); - }, - ]; - } - - private static function initFormats(): array - { - return [ - 'normal' => ' %current%/%max% [%bar%] %percent:3s%%', - 'normal_nomax' => ' %current% [%bar%]', - - 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%', - 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', - - 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%', - 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', - - 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%', - 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%', - ]; - } - - private function buildLine(): string - { - $regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i"; - $callback = function ($matches) { - if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) { - $text = $formatter($this, $this->output); - } elseif (isset($this->messages[$matches[1]])) { - $text = $this->messages[$matches[1]]; - } else { - return $matches[0]; - } - - if (isset($matches[2])) { - $text = sprintf('%'.$matches[2], $text); - } - - return $text; - }; - $line = preg_replace_callback($regex, $callback, $this->format); - - // gets string length for each sub line with multiline format - $linesLength = array_map(function ($subLine) { - return Helper::strlenWithoutDecoration($this->output->getFormatter(), rtrim($subLine, "\r")); - }, explode("\n", $line)); - - $linesWidth = max($linesLength); - - $terminalWidth = $this->terminal->getWidth(); - if ($linesWidth <= $terminalWidth) { - return $line; - } - - $this->setBarWidth($this->barWidth - $linesWidth + $terminalWidth); - - return preg_replace_callback($regex, $callback, $this->format); - } -} diff --git a/vendor/symfony/console/Helper/ProgressIndicator.php b/vendor/symfony/console/Helper/ProgressIndicator.php deleted file mode 100644 index 81cb783..0000000 --- a/vendor/symfony/console/Helper/ProgressIndicator.php +++ /dev/null @@ -1,254 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * @author Kevin Bond - */ -class ProgressIndicator -{ - private $output; - private $startTime; - private $format; - private $message; - private $indicatorValues; - private $indicatorCurrent; - private $indicatorChangeInterval; - private $indicatorUpdateTime; - private $started = false; - - private static $formatters; - private static $formats; - - /** - * @param int $indicatorChangeInterval Change interval in milliseconds - * @param array|null $indicatorValues Animated indicator characters - */ - public function __construct(OutputInterface $output, string $format = null, int $indicatorChangeInterval = 100, array $indicatorValues = null) - { - $this->output = $output; - - if (null === $format) { - $format = $this->determineBestFormat(); - } - - if (null === $indicatorValues) { - $indicatorValues = ['-', '\\', '|', '/']; - } - - $indicatorValues = array_values($indicatorValues); - - if (2 > \count($indicatorValues)) { - throw new InvalidArgumentException('Must have at least 2 indicator value characters.'); - } - - $this->format = self::getFormatDefinition($format); - $this->indicatorChangeInterval = $indicatorChangeInterval; - $this->indicatorValues = $indicatorValues; - $this->startTime = time(); - } - - /** - * Sets the current indicator message. - */ - public function setMessage(?string $message) - { - $this->message = $message; - - $this->display(); - } - - /** - * Starts the indicator output. - */ - public function start(string $message) - { - if ($this->started) { - throw new LogicException('Progress indicator already started.'); - } - - $this->message = $message; - $this->started = true; - $this->startTime = time(); - $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval; - $this->indicatorCurrent = 0; - - $this->display(); - } - - /** - * Advances the indicator. - */ - public function advance() - { - if (!$this->started) { - throw new LogicException('Progress indicator has not yet been started.'); - } - - if (!$this->output->isDecorated()) { - return; - } - - $currentTime = $this->getCurrentTimeInMilliseconds(); - - if ($currentTime < $this->indicatorUpdateTime) { - return; - } - - $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval; - ++$this->indicatorCurrent; - - $this->display(); - } - - /** - * Finish the indicator with message. - * - * @param $message - */ - public function finish(string $message) - { - if (!$this->started) { - throw new LogicException('Progress indicator has not yet been started.'); - } - - $this->message = $message; - $this->display(); - $this->output->writeln(''); - $this->started = false; - } - - /** - * Gets the format for a given name. - * - * @return string|null A format string - */ - public static function getFormatDefinition(string $name) - { - if (!self::$formats) { - self::$formats = self::initFormats(); - } - - return isset(self::$formats[$name]) ? self::$formats[$name] : null; - } - - /** - * Sets a placeholder formatter for a given name. - * - * This method also allow you to override an existing placeholder. - */ - public static function setPlaceholderFormatterDefinition(string $name, callable $callable) - { - if (!self::$formatters) { - self::$formatters = self::initPlaceholderFormatters(); - } - - self::$formatters[$name] = $callable; - } - - /** - * Gets the placeholder formatter for a given name (including the delimiter char like %). - * - * @return callable|null A PHP callable - */ - public static function getPlaceholderFormatterDefinition(string $name) - { - if (!self::$formatters) { - self::$formatters = self::initPlaceholderFormatters(); - } - - return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; - } - - private function display() - { - if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { - return; - } - - $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) { - if ($formatter = self::getPlaceholderFormatterDefinition($matches[1])) { - return $formatter($this); - } - - return $matches[0]; - }, $this->format)); - } - - private function determineBestFormat(): string - { - switch ($this->output->getVerbosity()) { - // OutputInterface::VERBOSITY_QUIET: display is disabled anyway - case OutputInterface::VERBOSITY_VERBOSE: - return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi'; - case OutputInterface::VERBOSITY_VERY_VERBOSE: - case OutputInterface::VERBOSITY_DEBUG: - return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi'; - default: - return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi'; - } - } - - /** - * Overwrites a previous message to the output. - */ - private function overwrite(string $message) - { - if ($this->output->isDecorated()) { - $this->output->write("\x0D\x1B[2K"); - $this->output->write($message); - } else { - $this->output->writeln($message); - } - } - - private function getCurrentTimeInMilliseconds(): float - { - return round(microtime(true) * 1000); - } - - private static function initPlaceholderFormatters(): array - { - return [ - 'indicator' => function (self $indicator) { - return $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)]; - }, - 'message' => function (self $indicator) { - return $indicator->message; - }, - 'elapsed' => function (self $indicator) { - return Helper::formatTime(time() - $indicator->startTime); - }, - 'memory' => function () { - return Helper::formatMemory(memory_get_usage(true)); - }, - ]; - } - - private static function initFormats(): array - { - return [ - 'normal' => ' %indicator% %message%', - 'normal_no_ansi' => ' %message%', - - 'verbose' => ' %indicator% %message% (%elapsed:6s%)', - 'verbose_no_ansi' => ' %message% (%elapsed:6s%)', - - 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)', - 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)', - ]; - } -} diff --git a/vendor/symfony/console/Helper/QuestionHelper.php b/vendor/symfony/console/Helper/QuestionHelper.php deleted file mode 100644 index 594a291..0000000 --- a/vendor/symfony/console/Helper/QuestionHelper.php +++ /dev/null @@ -1,485 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Formatter\OutputFormatterStyle; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\StreamableInputInterface; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\ConsoleSectionOutput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Question\ChoiceQuestion; -use Symfony\Component\Console\Question\Question; -use Symfony\Component\Console\Terminal; - -/** - * The QuestionHelper class provides helpers to interact with the user. - * - * @author Fabien Potencier - */ -class QuestionHelper extends Helper -{ - private $inputStream; - private static $shell; - private static $stty; - - /** - * Asks a question to the user. - * - * @return mixed The user answer - * - * @throws RuntimeException If there is no data to read in the input stream - */ - public function ask(InputInterface $input, OutputInterface $output, Question $question) - { - if ($output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - - if (!$input->isInteractive()) { - $default = $question->getDefault(); - - if (null === $default) { - return $default; - } - - if ($validator = $question->getValidator()) { - return \call_user_func($question->getValidator(), $default); - } elseif ($question instanceof ChoiceQuestion) { - $choices = $question->getChoices(); - - if (!$question->isMultiselect()) { - return isset($choices[$default]) ? $choices[$default] : $default; - } - - $default = explode(',', $default); - foreach ($default as $k => $v) { - $v = $question->isTrimmable() ? trim($v) : $v; - $default[$k] = isset($choices[$v]) ? $choices[$v] : $v; - } - } - - return $default; - } - - if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) { - $this->inputStream = $stream; - } - - if (!$question->getValidator()) { - return $this->doAsk($output, $question); - } - - $interviewer = function () use ($output, $question) { - return $this->doAsk($output, $question); - }; - - return $this->validateAttempts($interviewer, $output, $question); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'question'; - } - - /** - * Prevents usage of stty. - */ - public static function disableStty() - { - self::$stty = false; - } - - /** - * Asks the question to the user. - * - * @return bool|mixed|string|null - * - * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden - */ - private function doAsk(OutputInterface $output, Question $question) - { - $this->writePrompt($output, $question); - - $inputStream = $this->inputStream ?: STDIN; - $autocomplete = $question->getAutocompleterCallback(); - - if (null === $autocomplete || !Terminal::hasSttyAvailable()) { - $ret = false; - if ($question->isHidden()) { - try { - $hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable()); - $ret = $question->isTrimmable() ? trim($hiddenResponse) : $hiddenResponse; - } catch (RuntimeException $e) { - if (!$question->isHiddenFallback()) { - throw $e; - } - } - } - - if (false === $ret) { - $ret = fgets($inputStream, 4096); - if (false === $ret) { - throw new RuntimeException('Aborted.'); - } - if ($question->isTrimmable()) { - $ret = trim($ret); - } - } - } else { - $autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete); - $ret = $question->isTrimmable() ? trim($autocomplete) : $autocomplete; - } - - if ($output instanceof ConsoleSectionOutput) { - $output->addContent($ret); - } - - $ret = \strlen($ret) > 0 ? $ret : $question->getDefault(); - - if ($normalizer = $question->getNormalizer()) { - return $normalizer($ret); - } - - return $ret; - } - - /** - * Outputs the question prompt. - */ - protected function writePrompt(OutputInterface $output, Question $question) - { - $message = $question->getQuestion(); - - if ($question instanceof ChoiceQuestion) { - $output->writeln(array_merge([ - $question->getQuestion(), - ], $this->formatChoiceQuestionChoices($question, 'info'))); - - $message = $question->getPrompt(); - } - - $output->write($message); - } - - /** - * @return string[] - */ - protected function formatChoiceQuestionChoices(ChoiceQuestion $question, string $tag) - { - $messages = []; - - $maxWidth = max(array_map('self::strlen', array_keys($choices = $question->getChoices()))); - - foreach ($choices as $key => $value) { - $padding = str_repeat(' ', $maxWidth - self::strlen($key)); - - $messages[] = sprintf(" [<$tag>%s$padding] %s", $key, $value); - } - - return $messages; - } - - /** - * Outputs an error message. - */ - protected function writeError(OutputInterface $output, \Exception $error) - { - if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) { - $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'); - } else { - $message = ''.$error->getMessage().''; - } - - $output->writeln($message); - } - - /** - * Autocompletes a question. - * - * @param resource $inputStream - */ - private function autocomplete(OutputInterface $output, Question $question, $inputStream, callable $autocomplete): string - { - $fullChoice = ''; - $ret = ''; - - $i = 0; - $ofs = -1; - $matches = $autocomplete($ret); - $numMatches = \count($matches); - - $sttyMode = shell_exec('stty -g'); - - // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) - shell_exec('stty -icanon -echo'); - - // Add highlighted text style - $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); - - // Read a keypress - while (!feof($inputStream)) { - $c = fread($inputStream, 1); - - // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false. - if (false === $c || ('' === $ret && '' === $c && null === $question->getDefault())) { - shell_exec(sprintf('stty %s', $sttyMode)); - throw new RuntimeException('Aborted.'); - } elseif ("\177" === $c) { // Backspace Character - if (0 === $numMatches && 0 !== $i) { - --$i; - $fullChoice = self::substr($fullChoice, 0, $i); - // Move cursor backwards - $output->write("\033[1D"); - } - - if (0 === $i) { - $ofs = -1; - $matches = $autocomplete($ret); - $numMatches = \count($matches); - } else { - $numMatches = 0; - } - - // Pop the last character off the end of our string - $ret = self::substr($ret, 0, $i); - } elseif ("\033" === $c) { - // Did we read an escape sequence? - $c .= fread($inputStream, 2); - - // A = Up Arrow. B = Down Arrow - if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) { - if ('A' === $c[2] && -1 === $ofs) { - $ofs = 0; - } - - if (0 === $numMatches) { - continue; - } - - $ofs += ('A' === $c[2]) ? -1 : 1; - $ofs = ($numMatches + $ofs) % $numMatches; - } - } elseif (\ord($c) < 32) { - if ("\t" === $c || "\n" === $c) { - if ($numMatches > 0 && -1 !== $ofs) { - $ret = (string) $matches[$ofs]; - // Echo out remaining chars for current match - $remainingCharacters = substr($ret, \strlen(trim($this->mostRecentlyEnteredValue($fullChoice)))); - $output->write($remainingCharacters); - $fullChoice .= $remainingCharacters; - $i = self::strlen($fullChoice); - - $matches = array_filter( - $autocomplete($ret), - function ($match) use ($ret) { - return '' === $ret || 0 === strpos($match, $ret); - } - ); - $numMatches = \count($matches); - $ofs = -1; - } - - if ("\n" === $c) { - $output->write($c); - break; - } - - $numMatches = 0; - } - - continue; - } else { - if ("\x80" <= $c) { - $c .= fread($inputStream, ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3][$c & "\xF0"]); - } - - $output->write($c); - $ret .= $c; - $fullChoice .= $c; - ++$i; - - $tempRet = $ret; - - if ($question instanceof ChoiceQuestion && $question->isMultiselect()) { - $tempRet = $this->mostRecentlyEnteredValue($fullChoice); - } - - $numMatches = 0; - $ofs = 0; - - foreach ($autocomplete($ret) as $value) { - // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) - if (0 === strpos($value, $tempRet)) { - $matches[$numMatches++] = $value; - } - } - } - - // Erase characters from cursor to end of line - $output->write("\033[K"); - - if ($numMatches > 0 && -1 !== $ofs) { - // Save cursor position - $output->write("\0337"); - // Write highlighted text, complete the partially entered response - $charactersEntered = \strlen(trim($this->mostRecentlyEnteredValue($fullChoice))); - $output->write(''.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $charactersEntered)).''); - // Restore cursor position - $output->write("\0338"); - } - } - - // Reset stty so it behaves normally again - shell_exec(sprintf('stty %s', $sttyMode)); - - return $fullChoice; - } - - private function mostRecentlyEnteredValue(string $entered): string - { - // Determine the most recent value that the user entered - if (false === strpos($entered, ',')) { - return $entered; - } - - $choices = explode(',', $entered); - if (\strlen($lastChoice = trim($choices[\count($choices) - 1])) > 0) { - return $lastChoice; - } - - return $entered; - } - - /** - * Gets a hidden response from user. - * - * @param resource $inputStream The handler resource - * @param bool $trimmable Is the answer trimmable - * - * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden - */ - private function getHiddenResponse(OutputInterface $output, $inputStream, bool $trimmable = true): string - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; - - // handle code running from a phar - if ('phar:' === substr(__FILE__, 0, 5)) { - $tmpExe = sys_get_temp_dir().'/hiddeninput.exe'; - copy($exe, $tmpExe); - $exe = $tmpExe; - } - - $sExec = shell_exec($exe); - $value = $trimmable ? rtrim($sExec) : $sExec; - $output->writeln(''); - - if (isset($tmpExe)) { - unlink($tmpExe); - } - - return $value; - } - - if (Terminal::hasSttyAvailable()) { - $sttyMode = shell_exec('stty -g'); - - shell_exec('stty -echo'); - $value = fgets($inputStream, 4096); - shell_exec(sprintf('stty %s', $sttyMode)); - - if (false === $value) { - throw new RuntimeException('Aborted.'); - } - if ($trimmable) { - $value = trim($value); - } - $output->writeln(''); - - return $value; - } - - if (false !== $shell = $this->getShell()) { - $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword'; - $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); - $sCommand = shell_exec($command); - $value = $trimmable ? rtrim($sCommand) : $sCommand; - $output->writeln(''); - - return $value; - } - - throw new RuntimeException('Unable to hide the response.'); - } - - /** - * Validates an attempt. - * - * @param callable $interviewer A callable that will ask for a question and return the result - * - * @return mixed The validated response - * - * @throws \Exception In case the max number of attempts has been reached and no valid response has been given - */ - private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question) - { - $error = null; - $attempts = $question->getMaxAttempts(); - while (null === $attempts || $attempts--) { - if (null !== $error) { - $this->writeError($output, $error); - } - - try { - return $question->getValidator()($interviewer()); - } catch (RuntimeException $e) { - throw $e; - } catch (\Exception $error) { - } - } - - throw $error; - } - - /** - * Returns a valid unix shell. - * - * @return string|bool The valid shell name, false in case no valid shell is found - */ - private function getShell() - { - if (null !== self::$shell) { - return self::$shell; - } - - self::$shell = false; - - if (file_exists('/usr/bin/env')) { - // handle other OSs with bash/zsh/ksh/csh if available to hide the answer - $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null"; - foreach (['bash', 'zsh', 'ksh', 'csh'] as $sh) { - if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) { - self::$shell = $sh; - break; - } - } - } - - return self::$shell; - } -} diff --git a/vendor/symfony/console/Helper/SymfonyQuestionHelper.php b/vendor/symfony/console/Helper/SymfonyQuestionHelper.php deleted file mode 100644 index e4e87b2..0000000 --- a/vendor/symfony/console/Helper/SymfonyQuestionHelper.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Question\ChoiceQuestion; -use Symfony\Component\Console\Question\ConfirmationQuestion; -use Symfony\Component\Console\Question\Question; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Symfony Style Guide compliant question helper. - * - * @author Kevin Bond - */ -class SymfonyQuestionHelper extends QuestionHelper -{ - /** - * {@inheritdoc} - */ - protected function writePrompt(OutputInterface $output, Question $question) - { - $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion()); - $default = $question->getDefault(); - - switch (true) { - case null === $default: - $text = sprintf(' %s:', $text); - - break; - - case $question instanceof ConfirmationQuestion: - $text = sprintf(' %s (yes/no) [%s]:', $text, $default ? 'yes' : 'no'); - - break; - - case $question instanceof ChoiceQuestion && $question->isMultiselect(): - $choices = $question->getChoices(); - $default = explode(',', $default); - - foreach ($default as $key => $value) { - $default[$key] = $choices[trim($value)]; - } - - $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape(implode(', ', $default))); - - break; - - case $question instanceof ChoiceQuestion: - $choices = $question->getChoices(); - $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape(isset($choices[$default]) ? $choices[$default] : $default)); - - break; - - default: - $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape($default)); - } - - $output->writeln($text); - - $prompt = ' > '; - - if ($question instanceof ChoiceQuestion) { - $output->writeln($this->formatChoiceQuestionChoices($question, 'comment')); - - $prompt = $question->getPrompt(); - } - - $output->write($prompt); - } - - /** - * {@inheritdoc} - */ - protected function writeError(OutputInterface $output, \Exception $error) - { - if ($output instanceof SymfonyStyle) { - $output->newLine(); - $output->error($error->getMessage()); - - return; - } - - parent::writeError($output, $error); - } -} diff --git a/vendor/symfony/console/Helper/Table.php b/vendor/symfony/console/Helper/Table.php deleted file mode 100644 index 0a64110..0000000 --- a/vendor/symfony/console/Helper/Table.php +++ /dev/null @@ -1,834 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface; -use Symfony\Component\Console\Output\ConsoleSectionOutput; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Provides helpers to display a table. - * - * @author Fabien Potencier - * @author Саша Стаменковић - * @author Abdellatif Ait boudad - * @author Max Grigorian - * @author Dany Maillard - */ -class Table -{ - private const SEPARATOR_TOP = 0; - private const SEPARATOR_TOP_BOTTOM = 1; - private const SEPARATOR_MID = 2; - private const SEPARATOR_BOTTOM = 3; - private const BORDER_OUTSIDE = 0; - private const BORDER_INSIDE = 1; - - private $headerTitle; - private $footerTitle; - - /** - * Table headers. - */ - private $headers = []; - - /** - * Table rows. - */ - private $rows = []; - private $horizontal = false; - - /** - * Column widths cache. - */ - private $effectiveColumnWidths = []; - - /** - * Number of columns cache. - * - * @var int - */ - private $numberOfColumns; - - /** - * @var OutputInterface - */ - private $output; - - /** - * @var TableStyle - */ - private $style; - - /** - * @var array - */ - private $columnStyles = []; - - /** - * User set column widths. - * - * @var array - */ - private $columnWidths = []; - private $columnMaxWidths = []; - - private static $styles; - - private $rendered = false; - - public function __construct(OutputInterface $output) - { - $this->output = $output; - - if (!self::$styles) { - self::$styles = self::initStyles(); - } - - $this->setStyle('default'); - } - - /** - * Sets a style definition. - */ - public static function setStyleDefinition(string $name, TableStyle $style) - { - if (!self::$styles) { - self::$styles = self::initStyles(); - } - - self::$styles[$name] = $style; - } - - /** - * Gets a style definition by name. - * - * @return TableStyle - */ - public static function getStyleDefinition(string $name) - { - if (!self::$styles) { - self::$styles = self::initStyles(); - } - - if (isset(self::$styles[$name])) { - return self::$styles[$name]; - } - - throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); - } - - /** - * Sets table style. - * - * @param TableStyle|string $name The style name or a TableStyle instance - * - * @return $this - */ - public function setStyle($name) - { - $this->style = $this->resolveStyle($name); - - return $this; - } - - /** - * Gets the current table style. - * - * @return TableStyle - */ - public function getStyle() - { - return $this->style; - } - - /** - * Sets table column style. - * - * @param TableStyle|string $name The style name or a TableStyle instance - * - * @return $this - */ - public function setColumnStyle(int $columnIndex, $name) - { - $this->columnStyles[$columnIndex] = $this->resolveStyle($name); - - return $this; - } - - /** - * Gets the current style for a column. - * - * If style was not set, it returns the global table style. - * - * @return TableStyle - */ - public function getColumnStyle(int $columnIndex) - { - return $this->columnStyles[$columnIndex] ?? $this->getStyle(); - } - - /** - * Sets the minimum width of a column. - * - * @return $this - */ - public function setColumnWidth(int $columnIndex, int $width) - { - $this->columnWidths[$columnIndex] = $width; - - return $this; - } - - /** - * Sets the minimum width of all columns. - * - * @return $this - */ - public function setColumnWidths(array $widths) - { - $this->columnWidths = []; - foreach ($widths as $index => $width) { - $this->setColumnWidth($index, $width); - } - - return $this; - } - - /** - * Sets the maximum width of a column. - * - * Any cell within this column which contents exceeds the specified width will be wrapped into multiple lines, while - * formatted strings are preserved. - * - * @return $this - */ - public function setColumnMaxWidth(int $columnIndex, int $width): self - { - if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) { - throw new \LogicException(sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, \get_class($this->output->getFormatter()))); - } - - $this->columnMaxWidths[$columnIndex] = $width; - - return $this; - } - - public function setHeaders(array $headers) - { - $headers = array_values($headers); - if (!empty($headers) && !\is_array($headers[0])) { - $headers = [$headers]; - } - - $this->headers = $headers; - - return $this; - } - - public function setRows(array $rows) - { - $this->rows = []; - - return $this->addRows($rows); - } - - public function addRows(array $rows) - { - foreach ($rows as $row) { - $this->addRow($row); - } - - return $this; - } - - public function addRow($row) - { - if ($row instanceof TableSeparator) { - $this->rows[] = $row; - - return $this; - } - - if (!\is_array($row)) { - throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.'); - } - - $this->rows[] = array_values($row); - - return $this; - } - - /** - * Adds a row to the table, and re-renders the table. - */ - public function appendRow($row): self - { - if (!$this->output instanceof ConsoleSectionOutput) { - throw new RuntimeException(sprintf('Output should be an instance of "%s" when calling "%s".', ConsoleSectionOutput::class, __METHOD__)); - } - - if ($this->rendered) { - $this->output->clear($this->calculateRowCount()); - } - - $this->addRow($row); - $this->render(); - - return $this; - } - - public function setRow($column, array $row) - { - $this->rows[$column] = $row; - - return $this; - } - - public function setHeaderTitle(?string $title): self - { - $this->headerTitle = $title; - - return $this; - } - - public function setFooterTitle(?string $title): self - { - $this->footerTitle = $title; - - return $this; - } - - public function setHorizontal(bool $horizontal = true): self - { - $this->horizontal = $horizontal; - - return $this; - } - - /** - * Renders table to output. - * - * Example: - * - * +---------------+-----------------------+------------------+ - * | ISBN | Title | Author | - * +---------------+-----------------------+------------------+ - * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | - * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | - * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | - * +---------------+-----------------------+------------------+ - */ - public function render() - { - $divider = new TableSeparator(); - if ($this->horizontal) { - $rows = []; - foreach ($this->headers[0] ?? [] as $i => $header) { - $rows[$i] = [$header]; - foreach ($this->rows as $row) { - if ($row instanceof TableSeparator) { - continue; - } - if (isset($row[$i])) { - $rows[$i][] = $row[$i]; - } elseif ($rows[$i][0] instanceof TableCell && $rows[$i][0]->getColspan() >= 2) { - // Noop, there is a "title" - } else { - $rows[$i][] = null; - } - } - } - } else { - $rows = array_merge($this->headers, [$divider], $this->rows); - } - - $this->calculateNumberOfColumns($rows); - - $rows = $this->buildTableRows($rows); - $this->calculateColumnsWidth($rows); - - $isHeader = !$this->horizontal; - $isFirstRow = $this->horizontal; - foreach ($rows as $row) { - if ($divider === $row) { - $isHeader = false; - $isFirstRow = true; - - continue; - } - if ($row instanceof TableSeparator) { - $this->renderRowSeparator(); - - continue; - } - if (!$row) { - continue; - } - - if ($isHeader || $isFirstRow) { - if ($isFirstRow) { - $this->renderRowSeparator(self::SEPARATOR_TOP_BOTTOM); - $isFirstRow = false; - } else { - $this->renderRowSeparator(self::SEPARATOR_TOP, $this->headerTitle, $this->style->getHeaderTitleFormat()); - } - } - if ($this->horizontal) { - $this->renderRow($row, $this->style->getCellRowFormat(), $this->style->getCellHeaderFormat()); - } else { - $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat()); - } - } - $this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat()); - - $this->cleanup(); - $this->rendered = true; - } - - /** - * Renders horizontal header separator. - * - * Example: - * - * +-----+-----------+-------+ - */ - private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null, string $titleFormat = null) - { - if (0 === $count = $this->numberOfColumns) { - return; - } - - $borders = $this->style->getBorderChars(); - if (!$borders[0] && !$borders[2] && !$this->style->getCrossingChar()) { - return; - } - - $crossings = $this->style->getCrossingChars(); - if (self::SEPARATOR_MID === $type) { - list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[2], $crossings[8], $crossings[0], $crossings[4]]; - } elseif (self::SEPARATOR_TOP === $type) { - list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[1], $crossings[2], $crossings[3]]; - } elseif (self::SEPARATOR_TOP_BOTTOM === $type) { - list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[9], $crossings[10], $crossings[11]]; - } else { - list($horizontal, $leftChar, $midChar, $rightChar) = [$borders[0], $crossings[7], $crossings[6], $crossings[5]]; - } - - $markup = $leftChar; - for ($column = 0; $column < $count; ++$column) { - $markup .= str_repeat($horizontal, $this->effectiveColumnWidths[$column]); - $markup .= $column === $count - 1 ? $rightChar : $midChar; - } - - if (null !== $title) { - $titleLength = Helper::strlenWithoutDecoration($formatter = $this->output->getFormatter(), $formattedTitle = sprintf($titleFormat, $title)); - $markupLength = Helper::strlen($markup); - if ($titleLength > $limit = $markupLength - 4) { - $titleLength = $limit; - $formatLength = Helper::strlenWithoutDecoration($formatter, sprintf($titleFormat, '')); - $formattedTitle = sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3).'...'); - } - - $titleStart = ($markupLength - $titleLength) / 2; - if (false === mb_detect_encoding($markup, null, true)) { - $markup = substr_replace($markup, $formattedTitle, $titleStart, $titleLength); - } else { - $markup = mb_substr($markup, 0, $titleStart).$formattedTitle.mb_substr($markup, $titleStart + $titleLength); - } - } - - $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup)); - } - - /** - * Renders vertical column separator. - */ - private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE): string - { - $borders = $this->style->getBorderChars(); - - return sprintf($this->style->getBorderFormat(), self::BORDER_OUTSIDE === $type ? $borders[1] : $borders[3]); - } - - /** - * Renders table row. - * - * Example: - * - * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | - */ - private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null) - { - $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE); - $columns = $this->getRowColumns($row); - $last = \count($columns) - 1; - foreach ($columns as $i => $column) { - if ($firstCellFormat && 0 === $i) { - $rowContent .= $this->renderCell($row, $column, $firstCellFormat); - } else { - $rowContent .= $this->renderCell($row, $column, $cellFormat); - } - $rowContent .= $this->renderColumnSeparator($last === $i ? self::BORDER_OUTSIDE : self::BORDER_INSIDE); - } - $this->output->writeln($rowContent); - } - - /** - * Renders table cell with padding. - */ - private function renderCell(array $row, int $column, string $cellFormat): string - { - $cell = isset($row[$column]) ? $row[$column] : ''; - $width = $this->effectiveColumnWidths[$column]; - if ($cell instanceof TableCell && $cell->getColspan() > 1) { - // add the width of the following columns(numbers of colspan). - foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) { - $width += $this->getColumnSeparatorWidth() + $this->effectiveColumnWidths[$nextColumn]; - } - } - - // str_pad won't work properly with multi-byte strings, we need to fix the padding - if (false !== $encoding = mb_detect_encoding($cell, null, true)) { - $width += \strlen($cell) - mb_strwidth($cell, $encoding); - } - - $style = $this->getColumnStyle($column); - - if ($cell instanceof TableSeparator) { - return sprintf($style->getBorderFormat(), str_repeat($style->getBorderChars()[2], $width)); - } - - $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); - $content = sprintf($style->getCellRowContentFormat(), $cell); - - return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType())); - } - - /** - * Calculate number of columns for this table. - */ - private function calculateNumberOfColumns(array $rows) - { - $columns = [0]; - foreach ($rows as $row) { - if ($row instanceof TableSeparator) { - continue; - } - - $columns[] = $this->getNumberOfColumns($row); - } - - $this->numberOfColumns = max($columns); - } - - private function buildTableRows(array $rows): TableRows - { - /** @var WrappableOutputFormatterInterface $formatter */ - $formatter = $this->output->getFormatter(); - $unmergedRows = []; - for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) { - $rows = $this->fillNextRows($rows, $rowKey); - - // Remove any new line breaks and replace it with a new line - foreach ($rows[$rowKey] as $column => $cell) { - $colspan = $cell instanceof TableCell ? $cell->getColspan() : 1; - - if (isset($this->columnMaxWidths[$column]) && Helper::strlenWithoutDecoration($formatter, $cell) > $this->columnMaxWidths[$column]) { - $cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column] * $colspan); - } - if (!strstr($cell, "\n")) { - continue; - } - $escaped = implode("\n", array_map([OutputFormatter::class, 'escapeTrailingBackslash'], explode("\n", $cell))); - $cell = $cell instanceof TableCell ? new TableCell($escaped, ['colspan' => $cell->getColspan()]) : $escaped; - $lines = explode("\n", str_replace("\n", "\n", $cell)); - foreach ($lines as $lineKey => $line) { - if ($colspan > 1) { - $line = new TableCell($line, ['colspan' => $colspan]); - } - if (0 === $lineKey) { - $rows[$rowKey][$column] = $line; - } else { - $unmergedRows[$rowKey][$lineKey][$column] = $line; - } - } - } - } - - return new TableRows(function () use ($rows, $unmergedRows): \Traversable { - foreach ($rows as $rowKey => $row) { - yield $this->fillCells($row); - - if (isset($unmergedRows[$rowKey])) { - foreach ($unmergedRows[$rowKey] as $row) { - yield $row; - } - } - } - }); - } - - private function calculateRowCount(): int - { - $numberOfRows = \count(iterator_to_array($this->buildTableRows(array_merge($this->headers, [new TableSeparator()], $this->rows)))); - - if ($this->headers) { - ++$numberOfRows; // Add row for header separator - } - - ++$numberOfRows; // Add row for footer separator - - return $numberOfRows; - } - - /** - * fill rows that contains rowspan > 1. - * - * @throws InvalidArgumentException - */ - private function fillNextRows(array $rows, int $line): array - { - $unmergedRows = []; - foreach ($rows[$line] as $column => $cell) { - if (null !== $cell && !$cell instanceof TableCell && !is_scalar($cell) && !(\is_object($cell) && method_exists($cell, '__toString'))) { - throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing __toString, %s given.', \gettype($cell))); - } - if ($cell instanceof TableCell && $cell->getRowspan() > 1) { - $nbLines = $cell->getRowspan() - 1; - $lines = [$cell]; - if (strstr($cell, "\n")) { - $lines = explode("\n", str_replace("\n", "\n", $cell)); - $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines; - - $rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan()]); - unset($lines[0]); - } - - // create a two dimensional array (rowspan x colspan) - $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, []), $unmergedRows); - foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { - $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : ''; - $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan()]); - if ($nbLines === $unmergedRowKey - $line) { - break; - } - } - } - } - - foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { - // we need to know if $unmergedRow will be merged or inserted into $rows - if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) { - foreach ($unmergedRow as $cellKey => $cell) { - // insert cell into row at cellKey position - array_splice($rows[$unmergedRowKey], $cellKey, 0, [$cell]); - } - } else { - $row = $this->copyRow($rows, $unmergedRowKey - 1); - foreach ($unmergedRow as $column => $cell) { - if (!empty($cell)) { - $row[$column] = $unmergedRow[$column]; - } - } - array_splice($rows, $unmergedRowKey, 0, [$row]); - } - } - - return $rows; - } - - /** - * fill cells for a row that contains colspan > 1. - */ - private function fillCells($row) - { - $newRow = []; - foreach ($row as $column => $cell) { - $newRow[] = $cell; - if ($cell instanceof TableCell && $cell->getColspan() > 1) { - foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) { - // insert empty value at column position - $newRow[] = ''; - } - } - } - - return $newRow ?: $row; - } - - private function copyRow(array $rows, int $line): array - { - $row = $rows[$line]; - foreach ($row as $cellKey => $cellValue) { - $row[$cellKey] = ''; - if ($cellValue instanceof TableCell) { - $row[$cellKey] = new TableCell('', ['colspan' => $cellValue->getColspan()]); - } - } - - return $row; - } - - /** - * Gets number of columns by row. - */ - private function getNumberOfColumns(array $row): int - { - $columns = \count($row); - foreach ($row as $column) { - $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0; - } - - return $columns; - } - - /** - * Gets list of columns for the given row. - */ - private function getRowColumns(array $row): array - { - $columns = range(0, $this->numberOfColumns - 1); - foreach ($row as $cellKey => $cell) { - if ($cell instanceof TableCell && $cell->getColspan() > 1) { - // exclude grouped columns. - $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1)); - } - } - - return $columns; - } - - /** - * Calculates columns widths. - */ - private function calculateColumnsWidth(iterable $rows) - { - for ($column = 0; $column < $this->numberOfColumns; ++$column) { - $lengths = []; - foreach ($rows as $row) { - if ($row instanceof TableSeparator) { - continue; - } - - foreach ($row as $i => $cell) { - if ($cell instanceof TableCell) { - $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell); - $textLength = Helper::strlen($textContent); - if ($textLength > 0) { - $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan())); - foreach ($contentColumns as $position => $content) { - $row[$i + $position] = $content; - } - } - } - } - - $lengths[] = $this->getCellWidth($row, $column); - } - - $this->effectiveColumnWidths[$column] = max($lengths) + Helper::strlen($this->style->getCellRowContentFormat()) - 2; - } - } - - private function getColumnSeparatorWidth(): int - { - return Helper::strlen(sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3])); - } - - private function getCellWidth(array $row, int $column): int - { - $cellWidth = 0; - - if (isset($row[$column])) { - $cell = $row[$column]; - $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); - } - - $columnWidth = isset($this->columnWidths[$column]) ? $this->columnWidths[$column] : 0; - $cellWidth = max($cellWidth, $columnWidth); - - return isset($this->columnMaxWidths[$column]) ? min($this->columnMaxWidths[$column], $cellWidth) : $cellWidth; - } - - /** - * Called after rendering to cleanup cache data. - */ - private function cleanup() - { - $this->effectiveColumnWidths = []; - $this->numberOfColumns = null; - } - - private static function initStyles(): array - { - $borderless = new TableStyle(); - $borderless - ->setHorizontalBorderChars('=') - ->setVerticalBorderChars(' ') - ->setDefaultCrossingChar(' ') - ; - - $compact = new TableStyle(); - $compact - ->setHorizontalBorderChars('') - ->setVerticalBorderChars(' ') - ->setDefaultCrossingChar('') - ->setCellRowContentFormat('%s') - ; - - $styleGuide = new TableStyle(); - $styleGuide - ->setHorizontalBorderChars('-') - ->setVerticalBorderChars(' ') - ->setDefaultCrossingChar(' ') - ->setCellHeaderFormat('%s') - ; - - $box = (new TableStyle()) - ->setHorizontalBorderChars('─') - ->setVerticalBorderChars('│') - ->setCrossingChars('┼', '┌', '┬', '┐', '┤', '┘', '┴', '└', '├') - ; - - $boxDouble = (new TableStyle()) - ->setHorizontalBorderChars('═', '─') - ->setVerticalBorderChars('║', '│') - ->setCrossingChars('┼', '╔', '╤', '╗', '╢', '╝', '╧', '╚', '╟', '╠', '╪', '╣') - ; - - return [ - 'default' => new TableStyle(), - 'borderless' => $borderless, - 'compact' => $compact, - 'symfony-style-guide' => $styleGuide, - 'box' => $box, - 'box-double' => $boxDouble, - ]; - } - - private function resolveStyle($name): TableStyle - { - if ($name instanceof TableStyle) { - return $name; - } - - if (isset(self::$styles[$name])) { - return self::$styles[$name]; - } - - throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); - } -} diff --git a/vendor/symfony/console/Helper/TableCell.php b/vendor/symfony/console/Helper/TableCell.php deleted file mode 100644 index 5b6af4a..0000000 --- a/vendor/symfony/console/Helper/TableCell.php +++ /dev/null @@ -1,68 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * @author Abdellatif Ait boudad - */ -class TableCell -{ - private $value; - private $options = [ - 'rowspan' => 1, - 'colspan' => 1, - ]; - - public function __construct(string $value = '', array $options = []) - { - $this->value = $value; - - // check option names - if ($diff = array_diff(array_keys($options), array_keys($this->options))) { - throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff))); - } - - $this->options = array_merge($this->options, $options); - } - - /** - * Returns the cell value. - * - * @return string - */ - public function __toString() - { - return $this->value; - } - - /** - * Gets number of colspan. - * - * @return int - */ - public function getColspan() - { - return (int) $this->options['colspan']; - } - - /** - * Gets number of rowspan. - * - * @return int - */ - public function getRowspan() - { - return (int) $this->options['rowspan']; - } -} diff --git a/vendor/symfony/console/Helper/TableRows.php b/vendor/symfony/console/Helper/TableRows.php deleted file mode 100644 index 16aabb3..0000000 --- a/vendor/symfony/console/Helper/TableRows.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -/** - * @internal - */ -class TableRows implements \IteratorAggregate -{ - private $generator; - - public function __construct(callable $generator) - { - $this->generator = $generator; - } - - public function getIterator(): \Traversable - { - $g = $this->generator; - - return $g(); - } -} diff --git a/vendor/symfony/console/Helper/TableSeparator.php b/vendor/symfony/console/Helper/TableSeparator.php deleted file mode 100644 index e541c53..0000000 --- a/vendor/symfony/console/Helper/TableSeparator.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -/** - * Marks a row as being a separator. - * - * @author Fabien Potencier - */ -class TableSeparator extends TableCell -{ - public function __construct(array $options = []) - { - parent::__construct('', $options); - } -} diff --git a/vendor/symfony/console/Helper/TableStyle.php b/vendor/symfony/console/Helper/TableStyle.php deleted file mode 100644 index 8371942..0000000 --- a/vendor/symfony/console/Helper/TableStyle.php +++ /dev/null @@ -1,364 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Helper; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\LogicException; - -/** - * Defines the styles for a Table. - * - * @author Fabien Potencier - * @author Саша Стаменковић - * @author Dany Maillard - */ -class TableStyle -{ - private $paddingChar = ' '; - private $horizontalOutsideBorderChar = '-'; - private $horizontalInsideBorderChar = '-'; - private $verticalOutsideBorderChar = '|'; - private $verticalInsideBorderChar = '|'; - private $crossingChar = '+'; - private $crossingTopRightChar = '+'; - private $crossingTopMidChar = '+'; - private $crossingTopLeftChar = '+'; - private $crossingMidRightChar = '+'; - private $crossingBottomRightChar = '+'; - private $crossingBottomMidChar = '+'; - private $crossingBottomLeftChar = '+'; - private $crossingMidLeftChar = '+'; - private $crossingTopLeftBottomChar = '+'; - private $crossingTopMidBottomChar = '+'; - private $crossingTopRightBottomChar = '+'; - private $headerTitleFormat = ' %s '; - private $footerTitleFormat = ' %s '; - private $cellHeaderFormat = '%s'; - private $cellRowFormat = '%s'; - private $cellRowContentFormat = ' %s '; - private $borderFormat = '%s'; - private $padType = STR_PAD_RIGHT; - - /** - * Sets padding character, used for cell padding. - * - * @return $this - */ - public function setPaddingChar(string $paddingChar) - { - if (!$paddingChar) { - throw new LogicException('The padding char must not be empty'); - } - - $this->paddingChar = $paddingChar; - - return $this; - } - - /** - * Gets padding character, used for cell padding. - * - * @return string - */ - public function getPaddingChar() - { - return $this->paddingChar; - } - - /** - * Sets horizontal border characters. - * - * - * ╔═══════════════╤══════════════════════════╤══════════════════╗ - * 1 ISBN 2 Title │ Author ║ - * ╠═══════════════╪══════════════════════════╪══════════════════╣ - * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ - * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ - * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ - * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ - * ╚═══════════════╧══════════════════════════╧══════════════════╝ - * - */ - public function setHorizontalBorderChars(string $outside, string $inside = null): self - { - $this->horizontalOutsideBorderChar = $outside; - $this->horizontalInsideBorderChar = $inside ?? $outside; - - return $this; - } - - /** - * Sets vertical border characters. - * - * - * ╔═══════════════╤══════════════════════════╤══════════════════╗ - * ║ ISBN │ Title │ Author ║ - * ╠═══════1═══════╪══════════════════════════╪══════════════════╣ - * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ - * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ - * ╟───────2───────┼──────────────────────────┼──────────────────╢ - * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ - * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ - * ╚═══════════════╧══════════════════════════╧══════════════════╝ - * - */ - public function setVerticalBorderChars(string $outside, string $inside = null): self - { - $this->verticalOutsideBorderChar = $outside; - $this->verticalInsideBorderChar = $inside ?? $outside; - - return $this; - } - - /** - * Gets border characters. - * - * @internal - */ - public function getBorderChars(): array - { - return [ - $this->horizontalOutsideBorderChar, - $this->verticalOutsideBorderChar, - $this->horizontalInsideBorderChar, - $this->verticalInsideBorderChar, - ]; - } - - /** - * Sets crossing characters. - * - * Example: - * - * 1═══════════════2══════════════════════════2══════════════════3 - * ║ ISBN │ Title │ Author ║ - * 8'══════════════0'═════════════════════════0'═════════════════4' - * ║ 99921-58-10-7 │ Divine Comedy │ Dante Alighieri ║ - * ║ 9971-5-0210-0 │ A Tale of Two Cities │ Charles Dickens ║ - * 8───────────────0──────────────────────────0──────────────────4 - * ║ 960-425-059-0 │ The Lord of the Rings │ J. R. R. Tolkien ║ - * ║ 80-902734-1-6 │ And Then There Were None │ Agatha Christie ║ - * 7═══════════════6══════════════════════════6══════════════════5 - * - * - * @param string $cross Crossing char (see #0 of example) - * @param string $topLeft Top left char (see #1 of example) - * @param string $topMid Top mid char (see #2 of example) - * @param string $topRight Top right char (see #3 of example) - * @param string $midRight Mid right char (see #4 of example) - * @param string $bottomRight Bottom right char (see #5 of example) - * @param string $bottomMid Bottom mid char (see #6 of example) - * @param string $bottomLeft Bottom left char (see #7 of example) - * @param string $midLeft Mid left char (see #8 of example) - * @param string|null $topLeftBottom Top left bottom char (see #8' of example), equals to $midLeft if null - * @param string|null $topMidBottom Top mid bottom char (see #0' of example), equals to $cross if null - * @param string|null $topRightBottom Top right bottom char (see #4' of example), equals to $midRight if null - */ - public function setCrossingChars(string $cross, string $topLeft, string $topMid, string $topRight, string $midRight, string $bottomRight, string $bottomMid, string $bottomLeft, string $midLeft, string $topLeftBottom = null, string $topMidBottom = null, string $topRightBottom = null): self - { - $this->crossingChar = $cross; - $this->crossingTopLeftChar = $topLeft; - $this->crossingTopMidChar = $topMid; - $this->crossingTopRightChar = $topRight; - $this->crossingMidRightChar = $midRight; - $this->crossingBottomRightChar = $bottomRight; - $this->crossingBottomMidChar = $bottomMid; - $this->crossingBottomLeftChar = $bottomLeft; - $this->crossingMidLeftChar = $midLeft; - $this->crossingTopLeftBottomChar = $topLeftBottom ?? $midLeft; - $this->crossingTopMidBottomChar = $topMidBottom ?? $cross; - $this->crossingTopRightBottomChar = $topRightBottom ?? $midRight; - - return $this; - } - - /** - * Sets default crossing character used for each cross. - * - * @see {@link setCrossingChars()} for setting each crossing individually. - */ - public function setDefaultCrossingChar(string $char): self - { - return $this->setCrossingChars($char, $char, $char, $char, $char, $char, $char, $char, $char); - } - - /** - * Gets crossing character. - * - * @return string - */ - public function getCrossingChar() - { - return $this->crossingChar; - } - - /** - * Gets crossing characters. - * - * @internal - */ - public function getCrossingChars(): array - { - return [ - $this->crossingChar, - $this->crossingTopLeftChar, - $this->crossingTopMidChar, - $this->crossingTopRightChar, - $this->crossingMidRightChar, - $this->crossingBottomRightChar, - $this->crossingBottomMidChar, - $this->crossingBottomLeftChar, - $this->crossingMidLeftChar, - $this->crossingTopLeftBottomChar, - $this->crossingTopMidBottomChar, - $this->crossingTopRightBottomChar, - ]; - } - - /** - * Sets header cell format. - * - * @return $this - */ - public function setCellHeaderFormat(string $cellHeaderFormat) - { - $this->cellHeaderFormat = $cellHeaderFormat; - - return $this; - } - - /** - * Gets header cell format. - * - * @return string - */ - public function getCellHeaderFormat() - { - return $this->cellHeaderFormat; - } - - /** - * Sets row cell format. - * - * @return $this - */ - public function setCellRowFormat(string $cellRowFormat) - { - $this->cellRowFormat = $cellRowFormat; - - return $this; - } - - /** - * Gets row cell format. - * - * @return string - */ - public function getCellRowFormat() - { - return $this->cellRowFormat; - } - - /** - * Sets row cell content format. - * - * @return $this - */ - public function setCellRowContentFormat(string $cellRowContentFormat) - { - $this->cellRowContentFormat = $cellRowContentFormat; - - return $this; - } - - /** - * Gets row cell content format. - * - * @return string - */ - public function getCellRowContentFormat() - { - return $this->cellRowContentFormat; - } - - /** - * Sets table border format. - * - * @return $this - */ - public function setBorderFormat(string $borderFormat) - { - $this->borderFormat = $borderFormat; - - return $this; - } - - /** - * Gets table border format. - * - * @return string - */ - public function getBorderFormat() - { - return $this->borderFormat; - } - - /** - * Sets cell padding type. - * - * @return $this - */ - public function setPadType(int $padType) - { - if (!\in_array($padType, [STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH], true)) { - throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).'); - } - - $this->padType = $padType; - - return $this; - } - - /** - * Gets cell padding type. - * - * @return int - */ - public function getPadType() - { - return $this->padType; - } - - public function getHeaderTitleFormat(): string - { - return $this->headerTitleFormat; - } - - public function setHeaderTitleFormat(string $format): self - { - $this->headerTitleFormat = $format; - - return $this; - } - - public function getFooterTitleFormat(): string - { - return $this->footerTitleFormat; - } - - public function setFooterTitleFormat(string $format): self - { - $this->footerTitleFormat = $format; - - return $this; - } -} diff --git a/vendor/symfony/console/Input/ArgvInput.php b/vendor/symfony/console/Input/ArgvInput.php deleted file mode 100644 index cbd9f41..0000000 --- a/vendor/symfony/console/Input/ArgvInput.php +++ /dev/null @@ -1,349 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -use Symfony\Component\Console\Exception\RuntimeException; - -/** - * 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 application. - * - * 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 - * - * @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 -{ - private $tokens; - private $parsed; - - public function __construct(array $argv = null, InputDefinition $definition = null) - { - if (null === $argv) { - $argv = $_SERVER['argv']; - } - - // strip the application name - array_shift($argv); - - $this->tokens = $argv; - - parent::__construct($definition); - } - - protected function setTokens(array $tokens) - { - $this->tokens = $tokens; - } - - /** - * {@inheritdoc} - */ - protected function parse() - { - $parseOptions = true; - $this->parsed = $this->tokens; - while (null !== $token = array_shift($this->parsed)) { - if ($parseOptions && '' == $token) { - $this->parseArgument($token); - } elseif ($parseOptions && '--' == $token) { - $parseOptions = false; - } elseif ($parseOptions && 0 === strpos($token, '--')) { - $this->parseLongOption($token); - } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { - $this->parseShortOption($token); - } else { - $this->parseArgument($token); - } - } - } - - /** - * Parses a short option. - */ - private function parseShortOption(string $token) - { - $name = substr($token, 1); - - if (\strlen($name) > 1) { - if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { - // 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. - * - * @throws RuntimeException When option given doesn't exist - */ - private function parseShortOptionSet(string $name) - { - $len = \strlen($name); - for ($i = 0; $i < $len; ++$i) { - if (!$this->definition->hasShortcut($name[$i])) { - $encoding = mb_detect_encoding($name, null, true); - throw new RuntimeException(sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding))); - } - - $option = $this->definition->getOptionForShortcut($name[$i]); - if ($option->acceptValue()) { - $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); - - break; - } else { - $this->addLongOption($option->getName(), null); - } - } - } - - /** - * Parses a long option. - */ - private function parseLongOption(string $token) - { - $name = substr($token, 2); - - if (false !== $pos = strpos($name, '=')) { - if (0 === \strlen($value = substr($name, $pos + 1))) { - array_unshift($this->parsed, $value); - } - $this->addLongOption(substr($name, 0, $pos), $value); - } else { - $this->addLongOption($name, null); - } - } - - /** - * Parses an argument. - * - * @throws RuntimeException When too many arguments are given - */ - private function parseArgument(string $token) - { - $c = \count($this->arguments); - - // if input is expecting another argument, add it - if ($this->definition->hasArgument($c)) { - $arg = $this->definition->getArgument($c); - $this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token; - - // if last argument isArray(), append token to last argument - } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { - $arg = $this->definition->getArgument($c - 1); - $this->arguments[$arg->getName()][] = $token; - - // unexpected argument - } else { - $all = $this->definition->getArguments(); - if (\count($all)) { - throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all)))); - } - - throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token)); - } - } - - /** - * Adds a short option value. - * - * @throws RuntimeException When option given doesn't exist - */ - private function addShortOption(string $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. - * - * @throws RuntimeException When option given doesn't exist - */ - private function addLongOption(string $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->acceptValue()) { - throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name)); - } - - if (\in_array($value, ['', null], true) && $option->acceptValue() && \count($this->parsed)) { - // if option accepts an optional or mandatory argument - // let's see if there is one provided - $next = array_shift($this->parsed); - if ((isset($next[0]) && '-' !== $next[0]) || \in_array($next, ['', null], true)) { - $value = $next; - } else { - array_unshift($this->parsed, $next); - } - } - - if (null === $value) { - if ($option->isValueRequired()) { - throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name)); - } - - if (!$option->isArray() && !$option->isValueOptional()) { - $value = true; - } - } - - if ($option->isArray()) { - $this->options[$name][] = $value; - } else { - $this->options[$name] = $value; - } - } - - /** - * {@inheritdoc} - */ - public function getFirstArgument() - { - $isOption = false; - foreach ($this->tokens as $i => $token) { - if ($token && '-' === $token[0]) { - if (false !== strpos($token, '=') || !isset($this->tokens[$i + 1])) { - continue; - } - - // If it's a long option, consider that everything after "--" is the option name. - // Otherwise, use the last char (if it's a short option set, only the last one can take a value with space separator) - $name = '-' === $token[1] ? substr($token, 2) : substr($token, -1); - if (!isset($this->options[$name]) && !$this->definition->hasShortcut($name)) { - // noop - } elseif ((isset($this->options[$name]) || isset($this->options[$name = $this->definition->shortcutToName($name)])) && $this->tokens[$i + 1] === $this->options[$name]) { - $isOption = true; - } - - continue; - } - - if ($isOption) { - $isOption = false; - continue; - } - - return $token; - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function hasParameterOption($values, bool $onlyParams = false) - { - $values = (array) $values; - - foreach ($this->tokens as $token) { - if ($onlyParams && '--' === $token) { - return false; - } - foreach ($values as $value) { - // Options with values: - // For long options, test for '--option=' at beginning - // For short options, test for '-o' at beginning - $leading = 0 === strpos($value, '--') ? $value.'=' : $value; - if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) { - return true; - } - } - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function getParameterOption($values, $default = false, bool $onlyParams = false) - { - $values = (array) $values; - $tokens = $this->tokens; - - while (0 < \count($tokens)) { - $token = array_shift($tokens); - if ($onlyParams && '--' === $token) { - return $default; - } - - foreach ($values as $value) { - if ($token === $value) { - return array_shift($tokens); - } - // Options with values: - // For long options, test for '--option=' at beginning - // For short options, test for '-o' at beginning - $leading = 0 === strpos($value, '--') ? $value.'=' : $value; - if ('' !== $leading && 0 === strpos($token, $leading)) { - return substr($token, \strlen($leading)); - } - } - } - - return $default; - } - - /** - * Returns a stringified representation of the args passed to the command. - * - * @return string - */ - public function __toString() - { - $tokens = array_map(function ($token) { - if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) { - return $match[1].$this->escapeToken($match[2]); - } - - if ($token && '-' !== $token[0]) { - return $this->escapeToken($token); - } - - return $token; - }, $this->tokens); - - return implode(' ', $tokens); - } -} diff --git a/vendor/symfony/console/Input/ArrayInput.php b/vendor/symfony/console/Input/ArrayInput.php deleted file mode 100644 index 66f0bed..0000000 --- a/vendor/symfony/console/Input/ArrayInput.php +++ /dev/null @@ -1,202 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\InvalidOptionException; - -/** - * ArrayInput represents an input provided as an array. - * - * Usage: - * - * $input = new ArrayInput(['command' => 'foo:bar', 'foo' => 'bar', '--bar' => 'foobar']); - * - * @author Fabien Potencier - */ -class ArrayInput extends Input -{ - private $parameters; - - public function __construct(array $parameters, InputDefinition $definition = null) - { - $this->parameters = $parameters; - - parent::__construct($definition); - } - - /** - * {@inheritdoc} - */ - public function getFirstArgument() - { - foreach ($this->parameters as $param => $value) { - if ($param && \is_string($param) && '-' === $param[0]) { - continue; - } - - return $value; - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function hasParameterOption($values, bool $onlyParams = false) - { - $values = (array) $values; - - foreach ($this->parameters as $k => $v) { - if (!\is_int($k)) { - $v = $k; - } - - if ($onlyParams && '--' === $v) { - return false; - } - - if (\in_array($v, $values)) { - return true; - } - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function getParameterOption($values, $default = false, bool $onlyParams = false) - { - $values = (array) $values; - - foreach ($this->parameters as $k => $v) { - if ($onlyParams && ('--' === $k || (\is_int($k) && '--' === $v))) { - return $default; - } - - if (\is_int($k)) { - if (\in_array($v, $values)) { - return true; - } - } elseif (\in_array($k, $values)) { - return $v; - } - } - - return $default; - } - - /** - * Returns a stringified representation of the args passed to the command. - * - * @return string - */ - public function __toString() - { - $params = []; - foreach ($this->parameters as $param => $val) { - if ($param && \is_string($param) && '-' === $param[0]) { - if (\is_array($val)) { - foreach ($val as $v) { - $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : ''); - } - } else { - $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : ''); - } - } else { - $params[] = \is_array($val) ? implode(' ', array_map([$this, 'escapeToken'], $val)) : $this->escapeToken($val); - } - } - - return implode(' ', $params); - } - - /** - * {@inheritdoc} - */ - protected function parse() - { - foreach ($this->parameters as $key => $value) { - if ('--' === $key) { - return; - } - if (0 === strpos($key, '--')) { - $this->addLongOption(substr($key, 2), $value); - } elseif (0 === strpos($key, '-')) { - $this->addShortOption(substr($key, 1), $value); - } else { - $this->addArgument($key, $value); - } - } - } - - /** - * Adds a short option value. - * - * @throws InvalidOptionException When option given doesn't exist - */ - private function addShortOption(string $shortcut, $value) - { - if (!$this->definition->hasShortcut($shortcut)) { - throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut)); - } - - $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); - } - - /** - * Adds a long option value. - * - * @throws InvalidOptionException When option given doesn't exist - * @throws InvalidOptionException When a required value is missing - */ - private function addLongOption(string $name, $value) - { - if (!$this->definition->hasOption($name)) { - throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name)); - } - - $option = $this->definition->getOption($name); - - if (null === $value) { - if ($option->isValueRequired()) { - throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name)); - } - - if (!$option->isValueOptional()) { - $value = true; - } - } - - $this->options[$name] = $value; - } - - /** - * Adds an argument value. - * - * @param string|int $name The argument name - * @param mixed $value The value for the argument - * - * @throws InvalidArgumentException When argument given doesn't exist - */ - private function addArgument($name, $value) - { - if (!$this->definition->hasArgument($name)) { - throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); - } - - $this->arguments[$name] = $value; - } -} diff --git a/vendor/symfony/console/Input/Input.php b/vendor/symfony/console/Input/Input.php deleted file mode 100644 index 8c7905d..0000000 --- a/vendor/symfony/console/Input/Input.php +++ /dev/null @@ -1,201 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\RuntimeException; - -/** - * 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 - */ -abstract class Input implements InputInterface, StreamableInputInterface -{ - protected $definition; - protected $stream; - protected $options = []; - protected $arguments = []; - protected $interactive = true; - - public function __construct(InputDefinition $definition = null) - { - if (null === $definition) { - $this->definition = new InputDefinition(); - } else { - $this->bind($definition); - $this->validate(); - } - } - - /** - * {@inheritdoc} - */ - public function bind(InputDefinition $definition) - { - $this->arguments = []; - $this->options = []; - $this->definition = $definition; - - $this->parse(); - } - - /** - * Processes command line arguments. - */ - abstract protected function parse(); - - /** - * {@inheritdoc} - */ - public function validate() - { - $definition = $this->definition; - $givenArguments = $this->arguments; - - $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) { - return !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired(); - }); - - if (\count($missingArguments) > 0) { - throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments))); - } - } - - /** - * {@inheritdoc} - */ - public function isInteractive() - { - return $this->interactive; - } - - /** - * {@inheritdoc} - */ - public function setInteractive(bool $interactive) - { - $this->interactive = $interactive; - } - - /** - * {@inheritdoc} - */ - public function getArguments() - { - return array_merge($this->definition->getArgumentDefaults(), $this->arguments); - } - - /** - * {@inheritdoc} - */ - 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(); - } - - /** - * {@inheritdoc} - */ - 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; - } - - /** - * {@inheritdoc} - */ - public function hasArgument($name) - { - return $this->definition->hasArgument($name); - } - - /** - * {@inheritdoc} - */ - public function getOptions() - { - return array_merge($this->definition->getOptionDefaults(), $this->options); - } - - /** - * {@inheritdoc} - */ - public function getOption(string $name) - { - if (!$this->definition->hasOption($name)) { - throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); - } - - return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); - } - - /** - * {@inheritdoc} - */ - public function setOption(string $name, $value) - { - if (!$this->definition->hasOption($name)) { - throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); - } - - $this->options[$name] = $value; - } - - /** - * {@inheritdoc} - */ - public function hasOption(string $name) - { - return $this->definition->hasOption($name); - } - - /** - * Escapes a token through escapeshellarg if it contains unsafe chars. - * - * @return string - */ - public function escapeToken(string $token) - { - return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token); - } - - /** - * {@inheritdoc} - */ - public function setStream($stream) - { - $this->stream = $stream; - } - - /** - * {@inheritdoc} - */ - public function getStream() - { - return $this->stream; - } -} diff --git a/vendor/symfony/console/Input/InputArgument.php b/vendor/symfony/console/Input/InputArgument.php deleted file mode 100644 index b6aa645..0000000 --- a/vendor/symfony/console/Input/InputArgument.php +++ /dev/null @@ -1,129 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\LogicException; - -/** - * Represents a command line argument. - * - * @author Fabien Potencier - */ -class InputArgument -{ - const REQUIRED = 1; - const OPTIONAL = 2; - const IS_ARRAY = 4; - - private $name; - private $mode; - private $default; - private $description; - - /** - * @param string $name The argument name - * @param int|null $mode The argument mode: self::REQUIRED or self::OPTIONAL - * @param string $description A description text - * @param string|string[]|null $default The default value (for self::OPTIONAL mode only) - * - * @throws InvalidArgumentException When argument mode is not valid - */ - public function __construct(string $name, int $mode = null, string $description = '', $default = null) - { - if (null === $mode) { - $mode = self::OPTIONAL; - } elseif ($mode > 7 || $mode < 1) { - 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 bool 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 bool 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 string|string[]|null $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 InputArgument::OPTIONAL mode.'); - } - - if ($this->isArray()) { - if (null === $default) { - $default = []; - } elseif (!\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 string|string[]|null The default value - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns the description text. - * - * @return string The description text - */ - public function getDescription() - { - return $this->description; - } -} diff --git a/vendor/symfony/console/Input/InputAwareInterface.php b/vendor/symfony/console/Input/InputAwareInterface.php deleted file mode 100644 index 5a288de..0000000 --- a/vendor/symfony/console/Input/InputAwareInterface.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * InputAwareInterface should be implemented by classes that depends on the - * Console Input. - * - * @author Wouter J - */ -interface InputAwareInterface -{ - /** - * Sets the Console Input. - */ - public function setInput(InputInterface $input); -} diff --git a/vendor/symfony/console/Input/InputDefinition.php b/vendor/symfony/console/Input/InputDefinition.php deleted file mode 100644 index 4e95e9b..0000000 --- a/vendor/symfony/console/Input/InputDefinition.php +++ /dev/null @@ -1,390 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\LogicException; - -/** - * A InputDefinition represents a set of valid command line arguments and options. - * - * Usage: - * - * $definition = new InputDefinition([ - * new InputArgument('name', InputArgument::REQUIRED), - * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED), - * ]); - * - * @author Fabien Potencier - */ -class InputDefinition -{ - private $arguments; - private $requiredCount; - private $hasAnArrayArgument = false; - private $hasOptional; - private $options; - private $shortcuts; - - /** - * @param array $definition An array of InputArgument and InputOption instance - */ - public function __construct(array $definition = []) - { - $this->setDefinition($definition); - } - - /** - * Sets the definition of the input. - */ - public function setDefinition(array $definition) - { - $arguments = []; - $options = []; - foreach ($definition as $item) { - if ($item instanceof InputOption) { - $options[] = $item; - } else { - $arguments[] = $item; - } - } - - $this->setArguments($arguments); - $this->setOptions($options); - } - - /** - * Sets the InputArgument objects. - * - * @param InputArgument[] $arguments An array of InputArgument objects - */ - public function setArguments(array $arguments = []) - { - $this->arguments = []; - $this->requiredCount = 0; - $this->hasOptional = false; - $this->hasAnArrayArgument = false; - $this->addArguments($arguments); - } - - /** - * Adds an array of InputArgument objects. - * - * @param InputArgument[] $arguments An array of InputArgument objects - */ - public function addArguments(?array $arguments = []) - { - if (null !== $arguments) { - foreach ($arguments as $argument) { - $this->addArgument($argument); - } - } - } - - /** - * @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 exists.', $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|int $name The InputArgument name or position - * - * @return InputArgument An InputArgument object - * - * @throws InvalidArgumentException When argument given doesn't exist - */ - public function getArgument($name) - { - if (!$this->hasArgument($name)) { - throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); - } - - $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments; - - return $arguments[$name]; - } - - /** - * Returns true if an InputArgument object exists by name or position. - * - * @param string|int $name The InputArgument name or position - * - * @return bool 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 InputArgument[] An array of InputArgument objects - */ - public function getArguments() - { - return $this->arguments; - } - - /** - * Returns the number of InputArguments. - * - * @return int The number of InputArguments - */ - public function getArgumentCount() - { - return $this->hasAnArrayArgument ? PHP_INT_MAX : \count($this->arguments); - } - - /** - * Returns the number of required InputArguments. - * - * @return int 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 = []; - foreach ($this->arguments as $argument) { - $values[$argument->getName()] = $argument->getDefault(); - } - - return $values; - } - - /** - * Sets the InputOption objects. - * - * @param InputOption[] $options An array of InputOption objects - */ - public function setOptions(array $options = []) - { - $this->options = []; - $this->shortcuts = []; - $this->addOptions($options); - } - - /** - * Adds an array of InputOption objects. - * - * @param InputOption[] $options An array of InputOption objects - */ - public function addOptions(array $options = []) - { - foreach ($options as $option) { - $this->addOption($option); - } - } - - /** - * @throws LogicException When option given already exist - */ - public function addOption(InputOption $option) - { - if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) { - throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName())); - } - - if ($option->getShortcut()) { - foreach (explode('|', $option->getShortcut()) as $shortcut) { - if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) { - throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut)); - } - } - } - - $this->options[$option->getName()] = $option; - if ($option->getShortcut()) { - foreach (explode('|', $option->getShortcut()) as $shortcut) { - $this->shortcuts[$shortcut] = $option->getName(); - } - } - } - - /** - * Returns an InputOption by name. - * - * @return InputOption A InputOption object - * - * @throws InvalidArgumentException When option given doesn't exist - */ - public function getOption(string $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. - * - * This method can't be used to check if the user included the option when - * executing the command (use getOption() instead). - * - * @return bool true if the InputOption object exists, false otherwise - */ - public function hasOption(string $name) - { - return isset($this->options[$name]); - } - - /** - * Gets the array of InputOption objects. - * - * @return InputOption[] An array of InputOption objects - */ - public function getOptions() - { - return $this->options; - } - - /** - * Returns true if an InputOption object exists by shortcut. - * - * @return bool true if the InputOption object exists, false otherwise - */ - public function hasShortcut(string $name) - { - return isset($this->shortcuts[$name]); - } - - /** - * Gets an InputOption by shortcut. - * - * @return InputOption An InputOption object - */ - public function getOptionForShortcut(string $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 = []; - foreach ($this->options as $option) { - $values[$option->getName()] = $option->getDefault(); - } - - return $values; - } - - /** - * Returns the InputOption name given a shortcut. - * - * @throws InvalidArgumentException When option given does not exist - * - * @internal - */ - public function shortcutToName(string $shortcut): string - { - 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(bool $short = false) - { - $elements = []; - - if ($short && $this->getOptions()) { - $elements[] = '[options]'; - } elseif (!$short) { - foreach ($this->getOptions() as $option) { - $value = ''; - if ($option->acceptValue()) { - $value = sprintf( - ' %s%s%s', - $option->isValueOptional() ? '[' : '', - strtoupper($option->getName()), - $option->isValueOptional() ? ']' : '' - ); - } - - $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : ''; - $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value); - } - } - - if (\count($elements) && $this->getArguments()) { - $elements[] = '[--]'; - } - - $tail = ''; - foreach ($this->getArguments() as $argument) { - $element = '<'.$argument->getName().'>'; - if ($argument->isArray()) { - $element .= '...'; - } - - if (!$argument->isRequired()) { - $element = '['.$element; - $tail .= ']'; - } - - $elements[] = $element; - } - - return implode(' ', $elements).$tail; - } -} diff --git a/vendor/symfony/console/Input/InputInterface.php b/vendor/symfony/console/Input/InputInterface.php deleted file mode 100644 index f6ad722..0000000 --- a/vendor/symfony/console/Input/InputInterface.php +++ /dev/null @@ -1,153 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\RuntimeException; - -/** - * InputInterface is the interface implemented by all input classes. - * - * @author Fabien Potencier - */ -interface InputInterface -{ - /** - * Returns the first argument from the raw parameters (not parsed). - * - * @return string|null The value of the first argument or null otherwise - */ - public function getFirstArgument(); - - /** - * Returns true if the raw parameters (not parsed) contain a value. - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * Does not necessarily return the correct result for short options - * when multiple flags are combined in the same option. - * - * @param string|array $values The values to look for in the raw parameters (can be an array) - * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal - * - * @return bool true if the value is contained in the raw parameters - */ - public function hasParameterOption($values, bool $onlyParams = false); - - /** - * Returns the value of a raw option (not parsed). - * - * This method is to be used to introspect the input parameters - * before they have been validated. It must be used carefully. - * Does not necessarily return the correct result for short options - * when multiple flags are combined in the same option. - * - * @param string|array $values The value(s) to look for in the raw parameters (can be an array) - * @param mixed $default The default value to return if no result is found - * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal - * - * @return mixed The option value - */ - public function getParameterOption($values, $default = false, bool $onlyParams = false); - - /** - * Binds the current Input instance with the given arguments and options. - * - * @throws RuntimeException - */ - public function bind(InputDefinition $definition); - - /** - * Validates the input. - * - * @throws RuntimeException When not enough arguments are given - */ - public function validate(); - - /** - * Returns all the given arguments merged with the default values. - * - * @return array - */ - public function getArguments(); - - /** - * Returns the argument value for a given argument name. - * - * @return string|string[]|null The argument value - * - * @throws InvalidArgumentException When argument given doesn't exist - */ - public function getArgument(string $name); - - /** - * Sets an argument value by name. - * - * @param string|string[]|null $value The argument value - * - * @throws InvalidArgumentException When argument given doesn't exist - */ - public function setArgument(string $name, $value); - - /** - * Returns true if an InputArgument object exists by name or position. - * - * @param string|int $name The InputArgument name or position - * - * @return bool true if the InputArgument object exists, false otherwise - */ - public function hasArgument($name); - - /** - * Returns all the given options merged with the default values. - * - * @return array - */ - public function getOptions(); - - /** - * Returns the option value for a given option name. - * - * @return string|string[]|bool|null The option value - * - * @throws InvalidArgumentException When option given doesn't exist - */ - public function getOption(string $name); - - /** - * Sets an option value by name. - * - * @param string|string[]|bool|null $value The option value - * - * @throws InvalidArgumentException When option given doesn't exist - */ - public function setOption(string $name, $value); - - /** - * Returns true if an InputOption object exists by name. - * - * @return bool true if the InputOption object exists, false otherwise - */ - public function hasOption(string $name); - - /** - * Is this input means interactive? - * - * @return bool - */ - public function isInteractive(); - - /** - * Sets the input interactivity. - */ - public function setInteractive(bool $interactive); -} diff --git a/vendor/symfony/console/Input/InputOption.php b/vendor/symfony/console/Input/InputOption.php deleted file mode 100644 index d62e0ae..0000000 --- a/vendor/symfony/console/Input/InputOption.php +++ /dev/null @@ -1,208 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\LogicException; - -/** - * Represents a command line option. - * - * @author Fabien Potencier - */ -class InputOption -{ - const VALUE_NONE = 1; - const VALUE_REQUIRED = 2; - const VALUE_OPTIONAL = 4; - const VALUE_IS_ARRAY = 8; - - private $name; - private $shortcut; - private $mode; - private $default; - private $description; - - /** - * @param string $name The option name - * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts - * @param int|null $mode The option mode: One of the VALUE_* constants - * @param string $description A description text - * @param string|string[]|int|bool|null $default The default value (must be null for self::VALUE_NONE) - * - * @throws InvalidArgumentException If option mode is invalid or incompatible - */ - public function __construct(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null) - { - if (0 === strpos($name, '--')) { - $name = substr($name, 2); - } - - if (empty($name)) { - throw new InvalidArgumentException('An option name cannot be empty.'); - } - - if (empty($shortcut)) { - $shortcut = null; - } - - if (null !== $shortcut) { - if (\is_array($shortcut)) { - $shortcut = implode('|', $shortcut); - } - $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-')); - $shortcuts = array_filter($shortcuts); - $shortcut = implode('|', $shortcuts); - - if (empty($shortcut)) { - throw new InvalidArgumentException('An option shortcut cannot be empty.'); - } - } - - if (null === $mode) { - $mode = self::VALUE_NONE; - } elseif ($mode > 15 || $mode < 1) { - 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->acceptValue()) { - throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.'); - } - - $this->setDefault($default); - } - - /** - * Returns the option shortcut. - * - * @return string|null The shortcut - */ - public function getShortcut() - { - return $this->shortcut; - } - - /** - * Returns the option name. - * - * @return string The name - */ - public function getName() - { - return $this->name; - } - - /** - * Returns true if the option accepts a value. - * - * @return bool true if value mode is not self::VALUE_NONE, false otherwise - */ - public function acceptValue() - { - return $this->isValueRequired() || $this->isValueOptional(); - } - - /** - * Returns true if the option requires a value. - * - * @return bool true if value mode is self::VALUE_REQUIRED, false otherwise - */ - public function isValueRequired() - { - return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode); - } - - /** - * Returns true if the option takes an optional value. - * - * @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise - */ - public function isValueOptional() - { - return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode); - } - - /** - * Returns true if the option can take multiple values. - * - * @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise - */ - public function isArray() - { - return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); - } - - /** - * Sets the default value. - * - * @param string|string[]|int|bool|null $default The default value - * - * @throws LogicException When incorrect default value is given - */ - public function setDefault($default = null) - { - if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) { - throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.'); - } - - if ($this->isArray()) { - if (null === $default) { - $default = []; - } elseif (!\is_array($default)) { - throw new LogicException('A default value for an array option must be an array.'); - } - } - - $this->default = $this->acceptValue() ? $default : false; - } - - /** - * Returns the default value. - * - * @return string|string[]|int|bool|null The default value - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns the description text. - * - * @return string The description text - */ - public function getDescription() - { - return $this->description; - } - - /** - * Checks whether the given option equals this one. - * - * @return bool - */ - public function equals(self $option) - { - return $option->getName() === $this->getName() - && $option->getShortcut() === $this->getShortcut() - && $option->getDefault() === $this->getDefault() - && $option->isArray() === $this->isArray() - && $option->isValueRequired() === $this->isValueRequired() - && $option->isValueOptional() === $this->isValueOptional() - ; - } -} diff --git a/vendor/symfony/console/Input/StreamableInputInterface.php b/vendor/symfony/console/Input/StreamableInputInterface.php deleted file mode 100644 index d7e462f..0000000 --- a/vendor/symfony/console/Input/StreamableInputInterface.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -/** - * StreamableInputInterface is the interface implemented by all input classes - * that have an input stream. - * - * @author Robin Chalas - */ -interface StreamableInputInterface extends InputInterface -{ - /** - * Sets the input stream to read from when interacting with the user. - * - * This is mainly useful for testing purpose. - * - * @param resource $stream The input stream - */ - public function setStream($stream); - - /** - * Returns the input stream. - * - * @return resource|null - */ - public function getStream(); -} diff --git a/vendor/symfony/console/Input/StringInput.php b/vendor/symfony/console/Input/StringInput.php deleted file mode 100644 index 0ec0197..0000000 --- a/vendor/symfony/console/Input/StringInput.php +++ /dev/null @@ -1,68 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Input; - -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * StringInput represents an input provided as a string. - * - * Usage: - * - * $input = new StringInput('foo --bar="foobar"'); - * - * @author Fabien Potencier - */ -class StringInput extends ArgvInput -{ - const REGEX_STRING = '([^\s]+?)(?:\s|(?setTokens($this->tokenize($input)); - } - - /** - * Tokenizes a string. - * - * @throws InvalidArgumentException When unable to parse input (should never happen) - */ - private function tokenize(string $input): array - { - $tokens = []; - $length = \strlen($input); - $cursor = 0; - while ($cursor < $length) { - if (preg_match('/\s+/A', $input, $match, null, $cursor)) { - } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) { - $tokens[] = $match[1].$match[2].stripcslashes(str_replace(['"\'', '\'"', '\'\'', '""'], '', 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 - throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10))); - } - - $cursor += \strlen($match[0]); - } - - return $tokens; - } -} diff --git a/vendor/symfony/console/LICENSE b/vendor/symfony/console/LICENSE deleted file mode 100644 index a677f43..0000000 --- a/vendor/symfony/console/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/console/Logger/ConsoleLogger.php b/vendor/symfony/console/Logger/ConsoleLogger.php deleted file mode 100644 index 3236118..0000000 --- a/vendor/symfony/console/Logger/ConsoleLogger.php +++ /dev/null @@ -1,126 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Logger; - -use Psr\Log\AbstractLogger; -use Psr\Log\InvalidArgumentException; -use Psr\Log\LogLevel; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * PSR-3 compliant console logger. - * - * @author Kévin Dunglas - * - * @see https://www.php-fig.org/psr/psr-3/ - */ -class ConsoleLogger extends AbstractLogger -{ - const INFO = 'info'; - const ERROR = 'error'; - - private $output; - private $verbosityLevelMap = [ - LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, - LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, - LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL, - LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL, - LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL, - LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE, - LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE, - LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG, - ]; - private $formatLevelMap = [ - LogLevel::EMERGENCY => self::ERROR, - LogLevel::ALERT => self::ERROR, - LogLevel::CRITICAL => self::ERROR, - LogLevel::ERROR => self::ERROR, - LogLevel::WARNING => self::INFO, - LogLevel::NOTICE => self::INFO, - LogLevel::INFO => self::INFO, - LogLevel::DEBUG => self::INFO, - ]; - private $errored = false; - - public function __construct(OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = []) - { - $this->output = $output; - $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap; - $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap; - } - - /** - * {@inheritdoc} - * - * @return void - */ - public function log($level, $message, array $context = []) - { - if (!isset($this->verbosityLevelMap[$level])) { - throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); - } - - $output = $this->output; - - // Write to the error output if necessary and available - if (self::ERROR === $this->formatLevelMap[$level]) { - if ($this->output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - $this->errored = true; - } - - // the if condition check isn't necessary -- it's the same one that $output will do internally anyway. - // We only do it for efficiency here as the message formatting is relatively expensive. - if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) { - $output->writeln(sprintf('<%1$s>[%2$s] %3$s', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]); - } - } - - /** - * Returns true when any messages have been logged at error levels. - * - * @return bool - */ - public function hasErrored() - { - return $this->errored; - } - - /** - * Interpolates context values into the message placeholders. - * - * @author PHP Framework Interoperability Group - */ - private function interpolate(string $message, array $context): string - { - if (false === strpos($message, '{')) { - return $message; - } - - $replacements = []; - foreach ($context as $key => $val) { - if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { - $replacements["{{$key}}"] = $val; - } elseif ($val instanceof \DateTimeInterface) { - $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); - } elseif (\is_object($val)) { - $replacements["{{$key}}"] = '[object '.\get_class($val).']'; - } else { - $replacements["{{$key}}"] = '['.\gettype($val).']'; - } - } - - return strtr($message, $replacements); - } -} diff --git a/vendor/symfony/console/Output/BufferedOutput.php b/vendor/symfony/console/Output/BufferedOutput.php deleted file mode 100644 index a5ad7ad..0000000 --- a/vendor/symfony/console/Output/BufferedOutput.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -/** - * @author Jean-François Simon - */ -class BufferedOutput extends Output -{ - private $buffer = ''; - - /** - * Empties buffer and returns its content. - * - * @return string - */ - public function fetch() - { - $content = $this->buffer; - $this->buffer = ''; - - return $content; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $message, bool $newline) - { - $this->buffer .= $message; - - if ($newline) { - $this->buffer .= PHP_EOL; - } - } -} diff --git a/vendor/symfony/console/Output/ConsoleOutput.php b/vendor/symfony/console/Output/ConsoleOutput.php deleted file mode 100644 index 8356d4d..0000000 --- a/vendor/symfony/console/Output/ConsoleOutput.php +++ /dev/null @@ -1,159 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * ConsoleOutput is the default class for all CLI output. It uses STDOUT and STDERR. - * - * This class is a convenient wrapper around `StreamOutput` for both STDOUT and STDERR. - * - * $output = new ConsoleOutput(); - * - * This is equivalent to: - * - * $output = new StreamOutput(fopen('php://stdout', 'w')); - * $stdErr = new StreamOutput(fopen('php://stderr', 'w')); - * - * @author Fabien Potencier - */ -class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface -{ - private $stderr; - private $consoleSectionOutputs = []; - - /** - * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) - * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) - * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) - */ - public function __construct(int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null) - { - parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter); - - $actualDecorated = $this->isDecorated(); - $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter()); - - if (null === $decorated) { - $this->setDecorated($actualDecorated && $this->stderr->isDecorated()); - } - } - - /** - * Creates a new output section. - */ - public function section(): ConsoleSectionOutput - { - return new ConsoleSectionOutput($this->getStream(), $this->consoleSectionOutputs, $this->getVerbosity(), $this->isDecorated(), $this->getFormatter()); - } - - /** - * {@inheritdoc} - */ - public function setDecorated(bool $decorated) - { - parent::setDecorated($decorated); - $this->stderr->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - public function setFormatter(OutputFormatterInterface $formatter) - { - parent::setFormatter($formatter); - $this->stderr->setFormatter($formatter); - } - - /** - * {@inheritdoc} - */ - public function setVerbosity(int $level) - { - parent::setVerbosity($level); - $this->stderr->setVerbosity($level); - } - - /** - * {@inheritdoc} - */ - public function getErrorOutput() - { - return $this->stderr; - } - - /** - * {@inheritdoc} - */ - public function setErrorOutput(OutputInterface $error) - { - $this->stderr = $error; - } - - /** - * Returns true if current environment supports writing console output to - * STDOUT. - * - * @return bool - */ - protected function hasStdoutSupport() - { - return false === $this->isRunningOS400(); - } - - /** - * Returns true if current environment supports writing console output to - * STDERR. - * - * @return bool - */ - protected function hasStderrSupport() - { - return false === $this->isRunningOS400(); - } - - /** - * Checks if current executing environment is IBM iSeries (OS400), which - * doesn't properly convert character-encodings between ASCII to EBCDIC. - */ - private function isRunningOS400(): bool - { - $checks = [ - \function_exists('php_uname') ? php_uname('s') : '', - getenv('OSTYPE'), - PHP_OS, - ]; - - return false !== stripos(implode(';', $checks), 'OS400'); - } - - /** - * @return resource - */ - private function openOutputStream() - { - if (!$this->hasStdoutSupport()) { - return fopen('php://output', 'w'); - } - - return @fopen('php://stdout', 'w') ?: fopen('php://output', 'w'); - } - - /** - * @return resource - */ - private function openErrorStream() - { - return fopen($this->hasStderrSupport() ? 'php://stderr' : 'php://output', 'w'); - } -} diff --git a/vendor/symfony/console/Output/ConsoleOutputInterface.php b/vendor/symfony/console/Output/ConsoleOutputInterface.php deleted file mode 100644 index 6b6635f..0000000 --- a/vendor/symfony/console/Output/ConsoleOutputInterface.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -/** - * ConsoleOutputInterface is the interface implemented by ConsoleOutput class. - * This adds information about stderr and section output stream. - * - * @author Dariusz Górecki - */ -interface ConsoleOutputInterface extends OutputInterface -{ - /** - * Gets the OutputInterface for errors. - * - * @return OutputInterface - */ - public function getErrorOutput(); - - public function setErrorOutput(OutputInterface $error); - - public function section(): ConsoleSectionOutput; -} diff --git a/vendor/symfony/console/Output/ConsoleSectionOutput.php b/vendor/symfony/console/Output/ConsoleSectionOutput.php deleted file mode 100644 index 024d99d..0000000 --- a/vendor/symfony/console/Output/ConsoleSectionOutput.php +++ /dev/null @@ -1,143 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; -use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Terminal; - -/** - * @author Pierre du Plessis - * @author Gabriel Ostrolucký - */ -class ConsoleSectionOutput extends StreamOutput -{ - private $content = []; - private $lines = 0; - private $sections; - private $terminal; - - /** - * @param resource $stream - * @param ConsoleSectionOutput[] $sections - */ - public function __construct($stream, array &$sections, int $verbosity, bool $decorated, OutputFormatterInterface $formatter) - { - parent::__construct($stream, $verbosity, $decorated, $formatter); - array_unshift($sections, $this); - $this->sections = &$sections; - $this->terminal = new Terminal(); - } - - /** - * Clears previous output for this section. - * - * @param int $lines Number of lines to clear. If null, then the entire output of this section is cleared - */ - public function clear(int $lines = null) - { - if (empty($this->content) || !$this->isDecorated()) { - return; - } - - if ($lines) { - array_splice($this->content, -($lines * 2)); // Multiply lines by 2 to cater for each new line added between content - } else { - $lines = $this->lines; - $this->content = []; - } - - $this->lines -= $lines; - - parent::doWrite($this->popStreamContentUntilCurrentSection($lines), false); - } - - /** - * Overwrites the previous output with a new message. - * - * @param array|string $message - */ - public function overwrite($message) - { - $this->clear(); - $this->writeln($message); - } - - public function getContent(): string - { - return implode('', $this->content); - } - - /** - * @internal - */ - public function addContent(string $input) - { - foreach (explode(PHP_EOL, $input) as $lineContent) { - $this->lines += ceil($this->getDisplayLength($lineContent) / $this->terminal->getWidth()) ?: 1; - $this->content[] = $lineContent; - $this->content[] = PHP_EOL; - } - } - - /** - * {@inheritdoc} - */ - protected function doWrite($message, $newline) - { - if (!$this->isDecorated()) { - parent::doWrite($message, $newline); - - return; - } - - $erasedContent = $this->popStreamContentUntilCurrentSection(); - - $this->addContent($message); - - parent::doWrite($message, true); - parent::doWrite($erasedContent, false); - } - - /** - * At initial stage, cursor is at the end of stream output. This method makes cursor crawl upwards until it hits - * current section. Then it erases content it crawled through. Optionally, it erases part of current section too. - */ - private function popStreamContentUntilCurrentSection(int $numberOfLinesToClearFromCurrentSection = 0): string - { - $numberOfLinesToClear = $numberOfLinesToClearFromCurrentSection; - $erasedContent = []; - - foreach ($this->sections as $section) { - if ($section === $this) { - break; - } - - $numberOfLinesToClear += $section->lines; - $erasedContent[] = $section->getContent(); - } - - if ($numberOfLinesToClear > 0) { - // move cursor up n lines - parent::doWrite(sprintf("\x1b[%dA", $numberOfLinesToClear), false); - // erase to end of screen - parent::doWrite("\x1b[0J", false); - } - - return implode('', array_reverse($erasedContent)); - } - - private function getDisplayLength(string $text): string - { - return Helper::strlenWithoutDecoration($this->getFormatter(), str_replace("\t", ' ', $text)); - } -} diff --git a/vendor/symfony/console/Output/NullOutput.php b/vendor/symfony/console/Output/NullOutput.php deleted file mode 100644 index 78a1cb4..0000000 --- a/vendor/symfony/console/Output/NullOutput.php +++ /dev/null @@ -1,123 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * NullOutput suppresses all output. - * - * $output = new NullOutput(); - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class NullOutput implements OutputInterface -{ - /** - * {@inheritdoc} - */ - public function setFormatter(OutputFormatterInterface $formatter) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function getFormatter() - { - // to comply with the interface we must return a OutputFormatterInterface - return new OutputFormatter(); - } - - /** - * {@inheritdoc} - */ - public function setDecorated(bool $decorated) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function isDecorated() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function setVerbosity(int $level) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function getVerbosity() - { - return self::VERBOSITY_QUIET; - } - - /** - * {@inheritdoc} - */ - public function isQuiet() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function isVerbose() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function isVeryVerbose() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function isDebug() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function writeln($messages, int $options = self::OUTPUT_NORMAL) - { - // do nothing - } - - /** - * {@inheritdoc} - */ - public function write($messages, bool $newline = false, int $options = self::OUTPUT_NORMAL) - { - // do nothing - } -} diff --git a/vendor/symfony/console/Output/Output.php b/vendor/symfony/console/Output/Output.php deleted file mode 100644 index ed13d58..0000000 --- a/vendor/symfony/console/Output/Output.php +++ /dev/null @@ -1,174 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * Base class for output classes. - * - * There are five levels of verbosity: - * - * * normal: no option passed (normal output) - * * verbose: -v (more output) - * * very verbose: -vv (highly extended output) - * * debug: -vvv (all debug output) - * * quiet: -q (no output) - * - * @author Fabien Potencier - */ -abstract class Output implements OutputInterface -{ - private $verbosity; - private $formatter; - - /** - * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) - * @param bool $decorated Whether to decorate messages - * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) - */ - public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null) - { - $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity; - $this->formatter = $formatter ?: new OutputFormatter(); - $this->formatter->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - public function setFormatter(OutputFormatterInterface $formatter) - { - $this->formatter = $formatter; - } - - /** - * {@inheritdoc} - */ - public function getFormatter() - { - return $this->formatter; - } - - /** - * {@inheritdoc} - */ - public function setDecorated(bool $decorated) - { - $this->formatter->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - public function isDecorated() - { - return $this->formatter->isDecorated(); - } - - /** - * {@inheritdoc} - */ - public function setVerbosity(int $level) - { - $this->verbosity = $level; - } - - /** - * {@inheritdoc} - */ - public function getVerbosity() - { - return $this->verbosity; - } - - /** - * {@inheritdoc} - */ - public function isQuiet() - { - return self::VERBOSITY_QUIET === $this->verbosity; - } - - /** - * {@inheritdoc} - */ - public function isVerbose() - { - return self::VERBOSITY_VERBOSE <= $this->verbosity; - } - - /** - * {@inheritdoc} - */ - public function isVeryVerbose() - { - return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity; - } - - /** - * {@inheritdoc} - */ - public function isDebug() - { - return self::VERBOSITY_DEBUG <= $this->verbosity; - } - - /** - * {@inheritdoc} - */ - public function writeln($messages, int $options = self::OUTPUT_NORMAL) - { - $this->write($messages, true, $options); - } - - /** - * {@inheritdoc} - */ - public function write($messages, bool $newline = false, int $options = self::OUTPUT_NORMAL) - { - if (!is_iterable($messages)) { - $messages = [$messages]; - } - - $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN; - $type = $types & $options ?: self::OUTPUT_NORMAL; - - $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG; - $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL; - - if ($verbosity > $this->getVerbosity()) { - return; - } - - foreach ($messages as $message) { - switch ($type) { - case OutputInterface::OUTPUT_NORMAL: - $message = $this->formatter->format($message); - break; - case OutputInterface::OUTPUT_RAW: - break; - case OutputInterface::OUTPUT_PLAIN: - $message = strip_tags($this->formatter->format($message)); - break; - } - - $this->doWrite($message, $newline); - } - } - - /** - * Writes a message to the output. - */ - abstract protected function doWrite(string $message, bool $newline); -} diff --git a/vendor/symfony/console/Output/OutputInterface.php b/vendor/symfony/console/Output/OutputInterface.php deleted file mode 100644 index 38f82d8..0000000 --- a/vendor/symfony/console/Output/OutputInterface.php +++ /dev/null @@ -1,110 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * OutputInterface is the interface implemented by all Output classes. - * - * @author Fabien Potencier - */ -interface OutputInterface -{ - const VERBOSITY_QUIET = 16; - const VERBOSITY_NORMAL = 32; - const VERBOSITY_VERBOSE = 64; - const VERBOSITY_VERY_VERBOSE = 128; - const VERBOSITY_DEBUG = 256; - - const OUTPUT_NORMAL = 1; - const OUTPUT_RAW = 2; - const OUTPUT_PLAIN = 4; - - /** - * Writes a message to the output. - * - * @param string|iterable $messages The message as an iterable of strings or a single string - * @param bool $newline Whether to add a newline - * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL - */ - public function write($messages, bool $newline = false, int $options = 0); - - /** - * Writes a message to the output and adds a newline at the end. - * - * @param string|iterable $messages The message as an iterable of strings or a single string - * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL - */ - public function writeln($messages, int $options = 0); - - /** - * Sets the verbosity of the output. - */ - public function setVerbosity(int $level); - - /** - * Gets the current verbosity of the output. - * - * @return int The current level of verbosity (one of the VERBOSITY constants) - */ - public function getVerbosity(); - - /** - * Returns whether verbosity is quiet (-q). - * - * @return bool true if verbosity is set to VERBOSITY_QUIET, false otherwise - */ - public function isQuiet(); - - /** - * Returns whether verbosity is verbose (-v). - * - * @return bool true if verbosity is set to VERBOSITY_VERBOSE, false otherwise - */ - public function isVerbose(); - - /** - * Returns whether verbosity is very verbose (-vv). - * - * @return bool true if verbosity is set to VERBOSITY_VERY_VERBOSE, false otherwise - */ - public function isVeryVerbose(); - - /** - * Returns whether verbosity is debug (-vvv). - * - * @return bool true if verbosity is set to VERBOSITY_DEBUG, false otherwise - */ - public function isDebug(); - - /** - * Sets the decorated flag. - */ - public function setDecorated(bool $decorated); - - /** - * Gets the decorated flag. - * - * @return bool true if the output will decorate messages, false otherwise - */ - public function isDecorated(); - - public function setFormatter(OutputFormatterInterface $formatter); - - /** - * Returns current output formatter instance. - * - * @return OutputFormatterInterface - */ - public function getFormatter(); -} diff --git a/vendor/symfony/console/Output/StreamOutput.php b/vendor/symfony/console/Output/StreamOutput.php deleted file mode 100644 index 0b24052..0000000 --- a/vendor/symfony/console/Output/StreamOutput.php +++ /dev/null @@ -1,119 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Output; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\Formatter\OutputFormatterInterface; - -/** - * 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 - */ -class StreamOutput extends Output -{ - private $stream; - - /** - * @param resource $stream A stream resource - * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) - * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) - * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) - * - * @throws InvalidArgumentException When first argument is not a real stream - */ - public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = 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(); - } - - parent::__construct($verbosity, $decorated, $formatter); - } - - /** - * Gets the stream attached to this StreamOutput instance. - * - * @return resource A stream resource - */ - public function getStream() - { - return $this->stream; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $message, bool $newline) - { - if ($newline) { - $message .= PHP_EOL; - } - - if (false === @fwrite($this->stream, $message)) { - // should never happen - throw new RuntimeException('Unable to write output.'); - } - - fflush($this->stream); - } - - /** - * Returns true if the stream supports colorization. - * - * Colorization is disabled if not supported by the stream: - * - * This is tricky on Windows, because Cygwin, Msys2 etc emulate pseudo - * terminals via named pipes, so we can only check the environment. - * - * Reference: Composer\XdebugHandler\Process::supportsColor - * https://github.com/composer/xdebug-handler - * - * @return bool true if the stream supports colorization, false otherwise - */ - protected function hasColorSupport() - { - // Follow https://no-color.org/ - if (isset($_SERVER['NO_COLOR']) || false !== getenv('NO_COLOR')) { - return false; - } - - if ('Hyper' === getenv('TERM_PROGRAM')) { - return true; - } - - if (\DIRECTORY_SEPARATOR === '\\') { - return (\function_exists('sapi_windows_vt100_support') - && @sapi_windows_vt100_support($this->stream)) - || false !== getenv('ANSICON') - || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM'); - } - - return stream_isatty($this->stream); - } -} diff --git a/vendor/symfony/console/Question/ChoiceQuestion.php b/vendor/symfony/console/Question/ChoiceQuestion.php deleted file mode 100644 index 020b733..0000000 --- a/vendor/symfony/console/Question/ChoiceQuestion.php +++ /dev/null @@ -1,182 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Question; - -use Symfony\Component\Console\Exception\InvalidArgumentException; - -/** - * Represents a choice question. - * - * @author Fabien Potencier - */ -class ChoiceQuestion extends Question -{ - private $choices; - private $multiselect = false; - private $prompt = ' > '; - private $errorMessage = 'Value "%s" is invalid'; - - /** - * @param string $question The question to ask to the user - * @param array $choices The list of available choices - * @param mixed $default The default answer to return - */ - public function __construct(string $question, array $choices, $default = null) - { - if (!$choices) { - throw new \LogicException('Choice question must have at least 1 choice available.'); - } - - parent::__construct($question, $default); - - $this->choices = $choices; - $this->setValidator($this->getDefaultValidator()); - $this->setAutocompleterValues($choices); - } - - /** - * Returns available choices. - * - * @return array - */ - public function getChoices() - { - return $this->choices; - } - - /** - * Sets multiselect option. - * - * When multiselect is set to true, multiple choices can be answered. - * - * @return $this - */ - public function setMultiselect(bool $multiselect) - { - $this->multiselect = $multiselect; - $this->setValidator($this->getDefaultValidator()); - - return $this; - } - - /** - * Returns whether the choices are multiselect. - * - * @return bool - */ - public function isMultiselect() - { - return $this->multiselect; - } - - /** - * Gets the prompt for choices. - * - * @return string - */ - public function getPrompt() - { - return $this->prompt; - } - - /** - * Sets the prompt for choices. - * - * @return $this - */ - public function setPrompt(string $prompt) - { - $this->prompt = $prompt; - - return $this; - } - - /** - * Sets the error message for invalid values. - * - * The error message has a string placeholder (%s) for the invalid value. - * - * @return $this - */ - public function setErrorMessage(string $errorMessage) - { - $this->errorMessage = $errorMessage; - $this->setValidator($this->getDefaultValidator()); - - return $this; - } - - private function getDefaultValidator(): callable - { - $choices = $this->choices; - $errorMessage = $this->errorMessage; - $multiselect = $this->multiselect; - $isAssoc = $this->isAssoc($choices); - - return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) { - if ($multiselect) { - // Check for a separated comma values - if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selected, $matches)) { - throw new InvalidArgumentException(sprintf($errorMessage, $selected)); - } - - $selectedChoices = explode(',', $selected); - } else { - $selectedChoices = [$selected]; - } - - if ($this->isTrimmable()) { - foreach ($selectedChoices as $k => $v) { - $selectedChoices[$k] = trim($v); - } - } - - $multiselectChoices = []; - foreach ($selectedChoices as $value) { - $results = []; - foreach ($choices as $key => $choice) { - if ($choice === $value) { - $results[] = $key; - } - } - - if (\count($results) > 1) { - throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results))); - } - - $result = array_search($value, $choices); - - if (!$isAssoc) { - if (false !== $result) { - $result = $choices[$result]; - } elseif (isset($choices[$value])) { - $result = $choices[$value]; - } - } elseif (false === $result && isset($choices[$value])) { - $result = $value; - } - - if (false === $result) { - throw new InvalidArgumentException(sprintf($errorMessage, $value)); - } - - $multiselectChoices[] = (string) $result; - } - - if ($multiselect) { - return $multiselectChoices; - } - - return current($multiselectChoices); - }; - } -} diff --git a/vendor/symfony/console/Question/ConfirmationQuestion.php b/vendor/symfony/console/Question/ConfirmationQuestion.php deleted file mode 100644 index 4228521..0000000 --- a/vendor/symfony/console/Question/ConfirmationQuestion.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Question; - -/** - * Represents a yes/no question. - * - * @author Fabien Potencier - */ -class ConfirmationQuestion extends Question -{ - private $trueAnswerRegex; - - /** - * @param string $question The question to ask to the user - * @param bool $default The default answer to return, true or false - * @param string $trueAnswerRegex A regex to match the "yes" answer - */ - public function __construct(string $question, bool $default = true, string $trueAnswerRegex = '/^y/i') - { - parent::__construct($question, $default); - - $this->trueAnswerRegex = $trueAnswerRegex; - $this->setNormalizer($this->getDefaultNormalizer()); - } - - /** - * Returns the default answer normalizer. - */ - private function getDefaultNormalizer(): callable - { - $default = $this->getDefault(); - $regex = $this->trueAnswerRegex; - - return function ($answer) use ($default, $regex) { - if (\is_bool($answer)) { - return $answer; - } - - $answerIsTrue = (bool) preg_match($regex, $answer); - if (false === $default) { - return $answer && $answerIsTrue; - } - - return '' === $answer || $answerIsTrue; - }; - } -} diff --git a/vendor/symfony/console/Question/Question.php b/vendor/symfony/console/Question/Question.php deleted file mode 100644 index 8b0e4d9..0000000 --- a/vendor/symfony/console/Question/Question.php +++ /dev/null @@ -1,282 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Question; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\LogicException; - -/** - * Represents a Question. - * - * @author Fabien Potencier - */ -class Question -{ - private $question; - private $attempts; - private $hidden = false; - private $hiddenFallback = true; - private $autocompleterCallback; - private $validator; - private $default; - private $normalizer; - private $trimmable = true; - - /** - * @param string $question The question to ask to the user - * @param mixed $default The default answer to return if the user enters nothing - */ - public function __construct(string $question, $default = null) - { - $this->question = $question; - $this->default = $default; - } - - /** - * Returns the question. - * - * @return string - */ - public function getQuestion() - { - return $this->question; - } - - /** - * Returns the default answer. - * - * @return mixed - */ - public function getDefault() - { - return $this->default; - } - - /** - * Returns whether the user response must be hidden. - * - * @return bool - */ - public function isHidden() - { - return $this->hidden; - } - - /** - * Sets whether the user response must be hidden or not. - * - * @param bool $hidden - * - * @return $this - * - * @throws LogicException In case the autocompleter is also used - */ - public function setHidden($hidden) - { - if ($this->autocompleterCallback) { - throw new LogicException('A hidden question cannot use the autocompleter.'); - } - - $this->hidden = (bool) $hidden; - - return $this; - } - - /** - * In case the response can not be hidden, whether to fallback on non-hidden question or not. - * - * @return bool - */ - public function isHiddenFallback() - { - return $this->hiddenFallback; - } - - /** - * Sets whether to fallback on non-hidden question if the response can not be hidden. - * - * @param bool $fallback - * - * @return $this - */ - public function setHiddenFallback($fallback) - { - $this->hiddenFallback = (bool) $fallback; - - return $this; - } - - /** - * Gets values for the autocompleter. - * - * @return iterable|null - */ - public function getAutocompleterValues() - { - $callback = $this->getAutocompleterCallback(); - - return $callback ? $callback('') : null; - } - - /** - * Sets values for the autocompleter. - * - * @return $this - * - * @throws LogicException - */ - public function setAutocompleterValues(?iterable $values) - { - if (\is_array($values)) { - $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values); - - $callback = static function () use ($values) { - return $values; - }; - } elseif ($values instanceof \Traversable) { - $valueCache = null; - $callback = static function () use ($values, &$valueCache) { - return $valueCache ?? $valueCache = iterator_to_array($values, false); - }; - } else { - $callback = null; - } - - return $this->setAutocompleterCallback($callback); - } - - /** - * Gets the callback function used for the autocompleter. - */ - public function getAutocompleterCallback(): ?callable - { - return $this->autocompleterCallback; - } - - /** - * Sets the callback function used for the autocompleter. - * - * The callback is passed the user input as argument and should return an iterable of corresponding suggestions. - * - * @return $this - */ - public function setAutocompleterCallback(callable $callback = null): self - { - if ($this->hidden && null !== $callback) { - throw new LogicException('A hidden question cannot use the autocompleter.'); - } - - $this->autocompleterCallback = $callback; - - return $this; - } - - /** - * Sets a validator for the question. - * - * @return $this - */ - public function setValidator(callable $validator = null) - { - $this->validator = $validator; - - return $this; - } - - /** - * Gets the validator for the question. - * - * @return callable|null - */ - public function getValidator() - { - return $this->validator; - } - - /** - * Sets the maximum number of attempts. - * - * Null means an unlimited number of attempts. - * - * @return $this - * - * @throws InvalidArgumentException in case the number of attempts is invalid - */ - public function setMaxAttempts(?int $attempts) - { - if (null !== $attempts && $attempts < 1) { - throw new InvalidArgumentException('Maximum number of attempts must be a positive value.'); - } - - $this->attempts = $attempts; - - return $this; - } - - /** - * Gets the maximum number of attempts. - * - * Null means an unlimited number of attempts. - * - * @return int|null - */ - public function getMaxAttempts() - { - return $this->attempts; - } - - /** - * Sets a normalizer for the response. - * - * The normalizer can be a callable (a string), a closure or a class implementing __invoke. - * - * @return $this - */ - public function setNormalizer(callable $normalizer) - { - $this->normalizer = $normalizer; - - return $this; - } - - /** - * Gets the normalizer for the response. - * - * The normalizer can ba a callable (a string), a closure or a class implementing __invoke. - * - * @return callable|null - */ - public function getNormalizer() - { - return $this->normalizer; - } - - protected function isAssoc(array $array) - { - return (bool) \count(array_filter(array_keys($array), 'is_string')); - } - - public function isTrimmable(): bool - { - return $this->trimmable; - } - - /** - * @return $this - */ - public function setTrimmable(bool $trimmable): self - { - $this->trimmable = $trimmable; - - return $this; - } -} diff --git a/vendor/symfony/console/README.md b/vendor/symfony/console/README.md deleted file mode 100644 index 664a37c..0000000 --- a/vendor/symfony/console/README.md +++ /dev/null @@ -1,20 +0,0 @@ -Console Component -================= - -The Console component eases the creation of beautiful and testable command line -interfaces. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/console/index.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) - -Credits -------- - -`Resources/bin/hiddeninput.exe` is a third party binary provided within this -component. Find sources and license at https://github.com/Seldaek/hidden-input. diff --git a/vendor/symfony/console/Resources/bin/hiddeninput.exe b/vendor/symfony/console/Resources/bin/hiddeninput.exe deleted file mode 100644 index c8cf65e8d819e6e525121cf6b21f1c2429746038..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9216 zcmeHNe{@sVeZR8hV88~S)=Hp|Mpn({rC^@)BwNOI{ERJXCYlx+k1K6PLHo z_e!z_fhOzeA3JTX&-Z@s{rFOgjEwBlqjr!)9f zjyHz`A+ni`!0Taby{Uj5Y>jQq(k5A+X})PLWAi|{IZbtc8n^^trM{GI=P_15U6d?l zJJ3PW8XjfHpR}6`k{&5@JcEeH_SqQoQbU62o2YS30W)p_t&Fjy*RXQCZt$gCf|ao| zx&3R}m6|-Lfi@pua=$26n(UlnWo$>K67*|+#(qL_An=?l0M02AhOSJDv3;~?1ORfw z76EdK#MpSHqACHLcnJLIYlCSiX4eS@Pr8rN)Xwz0dk7O*y^0_C(Yks2Kvg! z-d-fJ)F9@k?>)m(XqDKIe2OKfhCQde9fpO0ko24yn*4xzX7q+ze`Z*=aJgwV?D?73 zaJ8UkSk|NN>@-|mB*f`EIK7$ElgAB<7p&p`^Vuq$58#;?B^*Bz7&d$B#+AYUC z(^m|`7{lqx&b^5$;i`j|S!+u|lcaQplp_&Nb)!>r>vGh3wb!tW zLq6%bkSt8jO|(vWH>LiPV(Xkp%BiGhl1q!PXXNKVKE!>Y5cHc2%cJOJA{-&ZsSn`T z#8~TA#(HWH4m>uCd+kCMTFgMI*s*n3!iCOwEI`{vGcVhzDu!Lw%-Ea^JATtrF`q3`+#KvvYJ0vM~A}D#LOD zlw`4ncB0U*Jji=--Wz#>I&5?hy;MgYW2u91d8ob=7MWfY`u;7Xe-J{Qsb0=0p|SM2 zG|=~mERIj4?gi)Ew|{LIN#oAsh20k_khIYjJBBN6rrIJ=eQO=nE;rTnPSiaQS$1$# z+|JRh0!IbQIa*f1(TZ}QM;|WO0+jTy(e)ggN4>zqp2E>C>hGPLHjHBh--2%@{EZNE zbUk{<3MABX&20QwK{MxK8`1Vk>^%dO5i@VTfu>NG3$K4NC=hSPsj9UYy`rNO}sBnB9QdKdIk7G+2_amnWstdTYVg z7HgLJGC~XLZG`63GwH8PdO_+G(k6~?J8Wj5mQos#21kC4W#2)guQXI)!z^{@F)U)5 z*re+r(2dib3D4P~%Z6TL=$PIkpmm<_#isu%t=%DcIwNkJhMeJ|bpahHO%8h|y~Ccf zUg#xVk+dyu>Q1O7JZ~8KS>tqi0qK**X*y6yHM71`bT=kFZ=@E%oe2!Km1^2sa>v+onZ%x_>aOJF+N0{i~z|<(IzgT*{0PpQq}E zQpU35@bm;qI?t_znGI&5&4sZV>+%m}w$(4hSDvLk)l<{5XyMlnCl7C%AjM3XnWvVz z{NoFsX)JB)SoqABZxUa*Yq+^^(cbq4mL%^lO12c${z{pf+)|kTTI~nQywyYF6}6|8 zlsN9&{-vwTrTyu<5^90_AsIU-ID#ZG@6d%poU44<**%xVe?`uxf}_Mr$SLHLS|K_N zQnw>(Lr2U=%$-<2D~RSzbG)2W2u^KMDnFFE?GmmbQ)V)fty957F`4OvQ_25E68ITr z5?`suu`|v?r!y=gFOGj$%9IJ zuTP=&2GcnoZZ0qSe6YL-*-lg>Q#>?Ew`a=GDc4vI#<1sNdKn?n7iSj0Orl$-#FMFi zykr>X-Xvi>sVr;92+8*H!r|3L$#o~hXa0z>AmF=z z?|@FF;*S|S0yqsw0j>Z(3mX-HD!|{N-vYc9paC8Ld=|6?00!6(_%lERupO`&um*4k z0b~W>e*uhTe4;V;mq>(ox$9FB`wLt!*DKj~!aOh|fL&#Pg*b??tm%5~_6M#02wqeC zS~wO>TWGnSp^r<0&8f2V6W->w=C+p~daC5e5wNQM*(* z66^}b0(!q3)zq$mu&VnbR#nr3;h5DS*o7{y66=!#;Dy4$pd1ZH<6WEOi0oJ8SxRL* z*v-9@Z^2w%^S(w5dO{_9Duby%2RT~;ppxaE$l()x6&}>7Wcg=u_&>f`Vs8OJGTy{X z2HpG=ThJz<{%|4Qq-~ad0qcrc87n88DHpM(nypwXIkZn<{zIT$ul&BQ?{ApCAZtyr zs2YpNt@x(G*faTU*HCKnAk(G=Tl~>r1QK8LY~J8mFFGoN5iIkYSwlm4Lsj#g4dsE5 zU-4;*Kdh-zv!rT4N$O}Q&n)?v0-9Y)lRFz58^P-KtKonzrfQ1p@0V_10^0||cGRn9 zRG<-#_TEV2nn4{BOh{YVBR4e!V!D?0K%BAlQN!D%M#k1bHypiIHT)5tlj>p0Pp_;+ z!cqC-JIs@JRhB+#teGs$Cib_=(yjRo4OJg^YPg%58aJVsC(LQ?W6%pn!-#aMZwoPcopo^Rn6BE z3=c5&W5~pP(C(-2r;PnH-S0{F`runM0ERCf3rESX$+S(MKOXmKJL9zXF}9-lf^xUs z+bb)+P%L&gV@<4q{6w^xEJ>Y>TQFUeoz0o-yq)jUqww=?wjUO8Y{a5G;DJ0Jr!LL+ zWhgsLuzi&eDrGDn$2DJwpFfH-?SGWbr>qRb?v{P`_%)So)CQgzO^HQ%;y#tJ=knH4 z95jX;^bF#BiuTH^%-j}{9VrZD=R%Q%wselH^p>5 z7d>gWB-st&3Fj%Mt*|tR5iK3J=`xhs&G)I7E>`FO@o7L z@S$B!pYMuzz5DN@X!O4DPm5n@raPJn-Q#o*m*e^5lk$g?0esg%$;>g5QW-|;c=H2GM}bo2tW^D924wmOkrUbWxcQ# z#v6bP%Tdfe~jtCRzAL;-OahZ=#yvUixu2-9fD2j$*|YY`F?0wF-{a# ztr<&kZjZ+81}6ZESqtgW)8kP#s@VLTSUR{}6?U^R*x7RE3Rl&n=VnFFqg9Uqz1n@N9N|=9<4} zuJfy^+}|D9X&vm3MAdqmu0&UMd^=K>b1hLAm_E!$rZC2b;;T~Dl zI`Eo_yRY76uM})|6wk9->of(=9&4jLv5#p@OzS~Yl>@pG)^>6`R+KtL{<4ly4o9WiM!%p_pfROU354)e8PIeE z1_s?#;OX6waNvvb&UQRN(WLbR+}&b#jo&WY-LlwCX}Q*$jGuKYuOGoIoyR(>e}}ix z+t}Q^cEcC8Y{@h}>HmJ^gD!l@gzwHmiBKl26x_lZVZG2UY!`w;RJd122;US&geQdW z3Qq}R!gIo5;ka;0I4c-Jq5X6A6?VzK&c4y!ZXdAUYu{r}*!SBXw?Aor+J4-A(*COb zb^CwV-?3k`zi-cX*c`VzL`RLI(b4MgIrGN z%ojf`E*6)Gg1A9!7q^N##2zsss^V9~-Qt7d!{UDNZ^XY9pA^3@9ui*?e=7c5d`nD; z?}~R(p>y1Kw!>|X4ycYEAkcZa*n-R%y! zqi)Up756UpqwfE7=hfigw$k~G@25gaxF9UGTkV>C(7x1Rbx4jb#|}rxq0vQ!n-c#f J0sQ~1{4brj`U(I5 diff --git a/vendor/symfony/console/Style/OutputStyle.php b/vendor/symfony/console/Style/OutputStyle.php deleted file mode 100644 index d46947f..0000000 --- a/vendor/symfony/console/Style/OutputStyle.php +++ /dev/null @@ -1,153 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Style; - -use Symfony\Component\Console\Formatter\OutputFormatterInterface; -use Symfony\Component\Console\Helper\ProgressBar; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Decorates output to add console style guide helpers. - * - * @author Kevin Bond - */ -abstract class OutputStyle implements OutputInterface, StyleInterface -{ - private $output; - - public function __construct(OutputInterface $output) - { - $this->output = $output; - } - - /** - * {@inheritdoc} - */ - public function newLine(int $count = 1) - { - $this->output->write(str_repeat(PHP_EOL, $count)); - } - - /** - * @return ProgressBar - */ - public function createProgressBar(int $max = 0) - { - return new ProgressBar($this->output, $max); - } - - /** - * {@inheritdoc} - */ - public function write($messages, bool $newline = false, int $type = self::OUTPUT_NORMAL) - { - $this->output->write($messages, $newline, $type); - } - - /** - * {@inheritdoc} - */ - public function writeln($messages, int $type = self::OUTPUT_NORMAL) - { - $this->output->writeln($messages, $type); - } - - /** - * {@inheritdoc} - */ - public function setVerbosity(int $level) - { - $this->output->setVerbosity($level); - } - - /** - * {@inheritdoc} - */ - public function getVerbosity() - { - return $this->output->getVerbosity(); - } - - /** - * {@inheritdoc} - */ - public function setDecorated(bool $decorated) - { - $this->output->setDecorated($decorated); - } - - /** - * {@inheritdoc} - */ - public function isDecorated() - { - return $this->output->isDecorated(); - } - - /** - * {@inheritdoc} - */ - public function setFormatter(OutputFormatterInterface $formatter) - { - $this->output->setFormatter($formatter); - } - - /** - * {@inheritdoc} - */ - public function getFormatter() - { - return $this->output->getFormatter(); - } - - /** - * {@inheritdoc} - */ - public function isQuiet() - { - return $this->output->isQuiet(); - } - - /** - * {@inheritdoc} - */ - public function isVerbose() - { - return $this->output->isVerbose(); - } - - /** - * {@inheritdoc} - */ - public function isVeryVerbose() - { - return $this->output->isVeryVerbose(); - } - - /** - * {@inheritdoc} - */ - public function isDebug() - { - return $this->output->isDebug(); - } - - protected function getErrorOutput() - { - if (!$this->output instanceof ConsoleOutputInterface) { - return $this->output; - } - - return $this->output->getErrorOutput(); - } -} diff --git a/vendor/symfony/console/Style/StyleInterface.php b/vendor/symfony/console/Style/StyleInterface.php deleted file mode 100644 index afb841c..0000000 --- a/vendor/symfony/console/Style/StyleInterface.php +++ /dev/null @@ -1,132 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Style; - -/** - * Output style helpers. - * - * @author Kevin Bond - */ -interface StyleInterface -{ - /** - * Formats a command title. - */ - public function title(string $message); - - /** - * Formats a section title. - */ - public function section(string $message); - - /** - * Formats a list. - */ - public function listing(array $elements); - - /** - * Formats informational text. - * - * @param string|array $message - */ - public function text($message); - - /** - * Formats a success result bar. - * - * @param string|array $message - */ - public function success($message); - - /** - * Formats an error result bar. - * - * @param string|array $message - */ - public function error($message); - - /** - * Formats an warning result bar. - * - * @param string|array $message - */ - public function warning($message); - - /** - * Formats a note admonition. - * - * @param string|array $message - */ - public function note($message); - - /** - * Formats a caution admonition. - * - * @param string|array $message - */ - public function caution($message); - - /** - * Formats a table. - */ - public function table(array $headers, array $rows); - - /** - * Asks a question. - * - * @return mixed - */ - public function ask(string $question, ?string $default = null, callable $validator = null); - - /** - * Asks a question with the user input hidden. - * - * @return mixed - */ - public function askHidden(string $question, callable $validator = null); - - /** - * Asks for confirmation. - * - * @return bool - */ - public function confirm(string $question, bool $default = true); - - /** - * Asks a choice question. - * - * @param string|int|null $default - * - * @return mixed - */ - public function choice(string $question, array $choices, $default = null); - - /** - * Add newline(s). - */ - public function newLine(int $count = 1); - - /** - * Starts the progress output. - */ - public function progressStart(int $max = 0); - - /** - * Advances the progress output X steps. - */ - public function progressAdvance(int $step = 1); - - /** - * Finishes the progress output. - */ - public function progressFinish(); -} diff --git a/vendor/symfony/console/Style/SymfonyStyle.php b/vendor/symfony/console/Style/SymfonyStyle.php deleted file mode 100644 index eea624e..0000000 --- a/vendor/symfony/console/Style/SymfonyStyle.php +++ /dev/null @@ -1,499 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Style; - -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Helper\ProgressBar; -use Symfony\Component\Console\Helper\SymfonyQuestionHelper; -use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Helper\TableCell; -use Symfony\Component\Console\Helper\TableSeparator; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\BufferedOutput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Question\ChoiceQuestion; -use Symfony\Component\Console\Question\ConfirmationQuestion; -use Symfony\Component\Console\Question\Question; -use Symfony\Component\Console\Terminal; - -/** - * Output decorator helpers for the Symfony Style Guide. - * - * @author Kevin Bond - */ -class SymfonyStyle extends OutputStyle -{ - const MAX_LINE_LENGTH = 120; - - private $input; - private $questionHelper; - private $progressBar; - private $lineLength; - private $bufferedOutput; - - public function __construct(InputInterface $input, OutputInterface $output) - { - $this->input = $input; - $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter()); - // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not. - $width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH; - $this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH); - - parent::__construct($output); - } - - /** - * Formats a message as a block of text. - * - * @param string|array $messages The message to write in the block - */ - public function block($messages, ?string $type = null, ?string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = true) - { - $messages = \is_array($messages) ? array_values($messages) : [$messages]; - - $this->autoPrependBlock(); - $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape)); - $this->newLine(); - } - - /** - * {@inheritdoc} - */ - public function title(string $message) - { - $this->autoPrependBlock(); - $this->writeln([ - sprintf('%s', OutputFormatter::escapeTrailingBackslash($message)), - sprintf('%s', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))), - ]); - $this->newLine(); - } - - /** - * {@inheritdoc} - */ - public function section(string $message) - { - $this->autoPrependBlock(); - $this->writeln([ - sprintf('%s', OutputFormatter::escapeTrailingBackslash($message)), - sprintf('%s', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))), - ]); - $this->newLine(); - } - - /** - * {@inheritdoc} - */ - public function listing(array $elements) - { - $this->autoPrependText(); - $elements = array_map(function ($element) { - return sprintf(' * %s', $element); - }, $elements); - - $this->writeln($elements); - $this->newLine(); - } - - /** - * {@inheritdoc} - */ - public function text($message) - { - $this->autoPrependText(); - - $messages = \is_array($message) ? array_values($message) : [$message]; - foreach ($messages as $message) { - $this->writeln(sprintf(' %s', $message)); - } - } - - /** - * Formats a command comment. - * - * @param string|array $message - */ - public function comment($message) - { - $this->block($message, null, null, ' // ', false, false); - } - - /** - * {@inheritdoc} - */ - public function success($message) - { - $this->block($message, 'OK', 'fg=black;bg=green', ' ', true); - } - - /** - * {@inheritdoc} - */ - public function error($message) - { - $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true); - } - - /** - * {@inheritdoc} - */ - public function warning($message) - { - $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', true); - } - - /** - * {@inheritdoc} - */ - public function note($message) - { - $this->block($message, 'NOTE', 'fg=yellow', ' ! '); - } - - /** - * {@inheritdoc} - */ - public function caution($message) - { - $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true); - } - - /** - * {@inheritdoc} - */ - public function table(array $headers, array $rows) - { - $style = clone Table::getStyleDefinition('symfony-style-guide'); - $style->setCellHeaderFormat('%s'); - - $table = new Table($this); - $table->setHeaders($headers); - $table->setRows($rows); - $table->setStyle($style); - - $table->render(); - $this->newLine(); - } - - /** - * Formats a horizontal table. - */ - public function horizontalTable(array $headers, array $rows) - { - $style = clone Table::getStyleDefinition('symfony-style-guide'); - $style->setCellHeaderFormat('%s'); - - $table = new Table($this); - $table->setHeaders($headers); - $table->setRows($rows); - $table->setStyle($style); - $table->setHorizontal(true); - - $table->render(); - $this->newLine(); - } - - /** - * Formats a list of key/value horizontally. - * - * Each row can be one of: - * * 'A title' - * * ['key' => 'value'] - * * new TableSeparator() - * - * @param string|array|TableSeparator ...$list - */ - public function definitionList(...$list) - { - $style = clone Table::getStyleDefinition('symfony-style-guide'); - $style->setCellHeaderFormat('%s'); - - $table = new Table($this); - $headers = []; - $row = []; - foreach ($list as $value) { - if ($value instanceof TableSeparator) { - $headers[] = $value; - $row[] = $value; - continue; - } - if (\is_string($value)) { - $headers[] = new TableCell($value, ['colspan' => 2]); - $row[] = null; - continue; - } - if (!\is_array($value)) { - throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.'); - } - $headers[] = key($value); - $row[] = current($value); - } - - $table->setHeaders($headers); - $table->setRows([$row]); - $table->setHorizontal(); - $table->setStyle($style); - - $table->render(); - $this->newLine(); - } - - /** - * {@inheritdoc} - */ - public function ask(string $question, ?string $default = null, $validator = null) - { - $question = new Question($question, $default); - $question->setValidator($validator); - - return $this->askQuestion($question); - } - - /** - * {@inheritdoc} - */ - public function askHidden(string $question, $validator = null) - { - $question = new Question($question); - - $question->setHidden(true); - $question->setValidator($validator); - - return $this->askQuestion($question); - } - - /** - * {@inheritdoc} - */ - public function confirm($question, $default = true) - { - return $this->askQuestion(new ConfirmationQuestion($question, $default)); - } - - /** - * {@inheritdoc} - */ - public function choice(string $question, array $choices, $default = null) - { - if (null !== $default) { - $values = array_flip($choices); - $default = $values[$default]; - } - - return $this->askQuestion(new ChoiceQuestion($question, $choices, $default)); - } - - /** - * {@inheritdoc} - */ - public function progressStart(int $max = 0) - { - $this->progressBar = $this->createProgressBar($max); - $this->progressBar->start(); - } - - /** - * {@inheritdoc} - */ - public function progressAdvance(int $step = 1) - { - $this->getProgressBar()->advance($step); - } - - /** - * {@inheritdoc} - */ - public function progressFinish() - { - $this->getProgressBar()->finish(); - $this->newLine(2); - $this->progressBar = null; - } - - /** - * {@inheritdoc} - */ - public function createProgressBar(int $max = 0) - { - $progressBar = parent::createProgressBar($max); - - if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) { - $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591 - $progressBar->setProgressCharacter(''); - $progressBar->setBarCharacter('▓'); // dark shade character \u2593 - } - - return $progressBar; - } - - /** - * @return mixed - */ - public function askQuestion(Question $question) - { - if ($this->input->isInteractive()) { - $this->autoPrependBlock(); - } - - if (!$this->questionHelper) { - $this->questionHelper = new SymfonyQuestionHelper(); - } - - $answer = $this->questionHelper->ask($this->input, $this, $question); - - if ($this->input->isInteractive()) { - $this->newLine(); - $this->bufferedOutput->write("\n"); - } - - return $answer; - } - - /** - * {@inheritdoc} - */ - public function writeln($messages, int $type = self::OUTPUT_NORMAL) - { - if (!is_iterable($messages)) { - $messages = [$messages]; - } - - foreach ($messages as $message) { - parent::writeln($message, $type); - $this->writeBuffer($message, true, $type); - } - } - - /** - * {@inheritdoc} - */ - public function write($messages, bool $newline = false, int $type = self::OUTPUT_NORMAL) - { - if (!is_iterable($messages)) { - $messages = [$messages]; - } - - foreach ($messages as $message) { - parent::write($message, $newline, $type); - $this->writeBuffer($message, $newline, $type); - } - } - - /** - * {@inheritdoc} - */ - public function newLine(int $count = 1) - { - parent::newLine($count); - $this->bufferedOutput->write(str_repeat("\n", $count)); - } - - /** - * Returns a new instance which makes use of stderr if available. - * - * @return self - */ - public function getErrorStyle() - { - return new self($this->input, $this->getErrorOutput()); - } - - private function getProgressBar(): ProgressBar - { - if (!$this->progressBar) { - throw new RuntimeException('The ProgressBar is not started.'); - } - - return $this->progressBar; - } - - private function autoPrependBlock(): void - { - $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2); - - if (!isset($chars[0])) { - $this->newLine(); //empty history, so we should start with a new line. - - return; - } - //Prepend new line for each non LF chars (This means no blank line was output before) - $this->newLine(2 - substr_count($chars, "\n")); - } - - private function autoPrependText(): void - { - $fetched = $this->bufferedOutput->fetch(); - //Prepend new line if last char isn't EOL: - if ("\n" !== substr($fetched, -1)) { - $this->newLine(); - } - } - - private function writeBuffer(string $message, bool $newLine, int $type): void - { - // We need to know if the two last chars are PHP_EOL - // Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer - $this->bufferedOutput->write(substr($message, -4), $newLine, $type); - } - - private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false): array - { - $indentLength = 0; - $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix); - $lines = []; - - if (null !== $type) { - $type = sprintf('[%s] ', $type); - $indentLength = \strlen($type); - $lineIndentation = str_repeat(' ', $indentLength); - } - - // wrap and add newlines for each element - foreach ($messages as $key => $message) { - if ($escape) { - $message = OutputFormatter::escape($message); - } - - $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true))); - - if (\count($messages) > 1 && $key < \count($messages) - 1) { - $lines[] = ''; - } - } - - $firstLineIndex = 0; - if ($padding && $this->isDecorated()) { - $firstLineIndex = 1; - array_unshift($lines, ''); - $lines[] = ''; - } - - foreach ($lines as $i => &$line) { - if (null !== $type) { - $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line; - } - - $line = $prefix.$line; - $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line)); - - if ($style) { - $line = sprintf('<%s>%s', $style, $line); - } - } - - return $lines; - } -} diff --git a/vendor/symfony/console/Terminal.php b/vendor/symfony/console/Terminal.php deleted file mode 100644 index b8cc04e..0000000 --- a/vendor/symfony/console/Terminal.php +++ /dev/null @@ -1,169 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console; - -class Terminal -{ - private static $width; - private static $height; - private static $stty; - - /** - * Gets the terminal width. - * - * @return int - */ - public function getWidth() - { - $width = getenv('COLUMNS'); - if (false !== $width) { - return (int) trim($width); - } - - if (null === self::$width) { - self::initDimensions(); - } - - return self::$width ?: 80; - } - - /** - * Gets the terminal height. - * - * @return int - */ - public function getHeight() - { - $height = getenv('LINES'); - if (false !== $height) { - return (int) trim($height); - } - - if (null === self::$height) { - self::initDimensions(); - } - - return self::$height ?: 50; - } - - /** - * @internal - * - * @return bool - */ - public static function hasSttyAvailable() - { - if (null !== self::$stty) { - return self::$stty; - } - - exec('stty 2>&1', $output, $exitcode); - - return self::$stty = 0 === $exitcode; - } - - private static function initDimensions() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON')), $matches)) { - // extract [w, H] from "wxh (WxH)" - // or [w, h] from "wxh" - self::$width = (int) $matches[1]; - self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; - } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) { - // only use stty on Windows if the terminal does not support vt100 (e.g. Windows 7 + git-bash) - // testing for stty in a Windows 10 vt100-enabled console will implicitly disable vt100 support on STDOUT - self::initDimensionsUsingStty(); - } elseif (null !== $dimensions = self::getConsoleMode()) { - // extract [w, h] from "wxh" - self::$width = (int) $dimensions[0]; - self::$height = (int) $dimensions[1]; - } - } else { - self::initDimensionsUsingStty(); - } - } - - /** - * Returns whether STDOUT has vt100 support (some Windows 10+ configurations). - */ - private static function hasVt100Support(): bool - { - return \function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(fopen('php://stdout', 'w')); - } - - /** - * Initializes dimensions using the output of an stty columns line. - */ - private static function initDimensionsUsingStty() - { - if ($sttyString = self::getSttyColumns()) { - if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { - // extract [w, h] from "rows h; columns w;" - self::$width = (int) $matches[2]; - self::$height = (int) $matches[1]; - } elseif (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) { - // extract [w, h] from "; h rows; w columns" - self::$width = (int) $matches[2]; - self::$height = (int) $matches[1]; - } - } - } - - /** - * Runs and parses mode CON if it's available, suppressing any error output. - * - * @return int[]|null An array composed of the width and the height or null if it could not be parsed - */ - private static function getConsoleMode(): ?array - { - $info = self::readFromProcess('mode CON'); - - if (null === $info || !preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { - return null; - } - - return [(int) $matches[2], (int) $matches[1]]; - } - - /** - * Runs and parses stty -a if it's available, suppressing any error output. - */ - private static function getSttyColumns(): ?string - { - return self::readFromProcess('stty -a | grep columns'); - } - - private static function readFromProcess(string $command): ?string - { - if (!\function_exists('proc_open')) { - return null; - } - - $descriptorspec = [ - 1 => ['pipe', 'w'], - 2 => ['pipe', 'w'], - ]; - - $process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]); - if (!\is_resource($process)) { - return null; - } - - $info = stream_get_contents($pipes[1]); - fclose($pipes[1]); - fclose($pipes[2]); - proc_close($process); - - return $info; - } -} diff --git a/vendor/symfony/console/Tester/ApplicationTester.php b/vendor/symfony/console/Tester/ApplicationTester.php deleted file mode 100644 index 9da40cf..0000000 --- a/vendor/symfony/console/Tester/ApplicationTester.php +++ /dev/null @@ -1,74 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tester; - -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Input\ArrayInput; - -/** - * Eases the testing of console applications. - * - * When testing an application, don't forget to disable the auto exit flag: - * - * $application = new Application(); - * $application->setAutoExit(false); - * - * @author Fabien Potencier - */ -class ApplicationTester -{ - use TesterTrait; - - private $application; - private $input; - private $statusCode; - - 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 - * * capture_stderr_separately: Make output of stdOut and stdErr separately available - * - * @return int The command exit code - */ - public function run(array $input, array $options = []) - { - $this->input = new ArrayInput($input); - if (isset($options['interactive'])) { - $this->input->setInteractive($options['interactive']); - } - - $shellInteractive = getenv('SHELL_INTERACTIVE'); - - if ($this->inputs) { - $this->input->setStream(self::createStream($this->inputs)); - putenv('SHELL_INTERACTIVE=1'); - } - - $this->initOutput($options); - - $this->statusCode = $this->application->run($this->input, $this->output); - - putenv($shellInteractive ? "SHELL_INTERACTIVE=$shellInteractive" : 'SHELL_INTERACTIVE'); - - return $this->statusCode; - } -} diff --git a/vendor/symfony/console/Tester/CommandTester.php b/vendor/symfony/console/Tester/CommandTester.php deleted file mode 100644 index 57efc9a..0000000 --- a/vendor/symfony/console/Tester/CommandTester.php +++ /dev/null @@ -1,78 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tester; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\ArrayInput; - -/** - * Eases the testing of console commands. - * - * @author Fabien Potencier - * @author Robin Chalas - */ -class CommandTester -{ - use TesterTrait; - - private $command; - private $input; - private $statusCode; - - public function __construct(Command $command) - { - $this->command = $command; - } - - /** - * Executes the command. - * - * Available execution options: - * - * * interactive: Sets the input interactive flag - * * decorated: Sets the output decorated flag - * * verbosity: Sets the output verbosity flag - * * capture_stderr_separately: Make output of stdOut and stdErr separately available - * - * @param array $input An array of command arguments and options - * @param array $options An array of execution options - * - * @return int The command exit code - */ - public function execute(array $input, array $options = []) - { - // set the command name automatically if the application requires - // this argument and no command name was passed - if (!isset($input['command']) - && (null !== $application = $this->command->getApplication()) - && $application->getDefinition()->hasArgument('command') - ) { - $input = array_merge(['command' => $this->command->getName()], $input); - } - - $this->input = new ArrayInput($input); - // Use an in-memory input stream even if no inputs are set so that QuestionHelper::ask() does not rely on the blocking STDIN. - $this->input->setStream(self::createStream($this->inputs)); - - if (isset($options['interactive'])) { - $this->input->setInteractive($options['interactive']); - } - - if (!isset($options['decorated'])) { - $options['decorated'] = false; - } - - $this->initOutput($options); - - return $this->statusCode = $this->command->run($this->input, $this->output); - } -} diff --git a/vendor/symfony/console/Tester/TesterTrait.php b/vendor/symfony/console/Tester/TesterTrait.php deleted file mode 100644 index 73ee010..0000000 --- a/vendor/symfony/console/Tester/TesterTrait.php +++ /dev/null @@ -1,178 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Tester; - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Output\StreamOutput; - -/** - * @author Amrouche Hamza - */ -trait TesterTrait -{ - /** @var StreamOutput */ - private $output; - private $inputs = []; - private $captureStreamsIndependently = false; - - /** - * Gets the display returned by the last execution of the command or application. - * - * @return string The display - */ - public function getDisplay(bool $normalize = false) - { - if (null === $this->output) { - throw new \RuntimeException('Output not initialized, did you execute the command before requesting the display?'); - } - - rewind($this->output->getStream()); - - $display = stream_get_contents($this->output->getStream()); - - if ($normalize) { - $display = str_replace(PHP_EOL, "\n", $display); - } - - return $display; - } - - /** - * Gets the output written to STDERR by the application. - * - * @param bool $normalize Whether to normalize end of lines to \n or not - * - * @return string - */ - public function getErrorOutput(bool $normalize = false) - { - if (!$this->captureStreamsIndependently) { - throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.'); - } - - rewind($this->output->getErrorOutput()->getStream()); - - $display = stream_get_contents($this->output->getErrorOutput()->getStream()); - - if ($normalize) { - $display = str_replace(PHP_EOL, "\n", $display); - } - - return $display; - } - - /** - * Gets the input instance used by the last execution of the command or application. - * - * @return InputInterface The current input instance - */ - public function getInput() - { - return $this->input; - } - - /** - * Gets the output instance used by the last execution of the command or application. - * - * @return OutputInterface The current output instance - */ - public function getOutput() - { - return $this->output; - } - - /** - * Gets the status code returned by the last execution of the command or application. - * - * @return int The status code - */ - public function getStatusCode() - { - return $this->statusCode; - } - - /** - * Sets the user inputs. - * - * @param array $inputs An array of strings representing each input - * passed to the command input stream - * - * @return $this - */ - public function setInputs(array $inputs) - { - $this->inputs = $inputs; - - return $this; - } - - /** - * Initializes the output property. - * - * Available options: - * - * * decorated: Sets the output decorated flag - * * verbosity: Sets the output verbosity flag - * * capture_stderr_separately: Make output of stdOut and stdErr separately available - */ - private function initOutput(array $options) - { - $this->captureStreamsIndependently = \array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately']; - if (!$this->captureStreamsIndependently) { - $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']); - } - } else { - $this->output = new ConsoleOutput( - isset($options['verbosity']) ? $options['verbosity'] : ConsoleOutput::VERBOSITY_NORMAL, - isset($options['decorated']) ? $options['decorated'] : null - ); - - $errorOutput = new StreamOutput(fopen('php://memory', 'w', false)); - $errorOutput->setFormatter($this->output->getFormatter()); - $errorOutput->setVerbosity($this->output->getVerbosity()); - $errorOutput->setDecorated($this->output->isDecorated()); - - $reflectedOutput = new \ReflectionObject($this->output); - $strErrProperty = $reflectedOutput->getProperty('stderr'); - $strErrProperty->setAccessible(true); - $strErrProperty->setValue($this->output, $errorOutput); - - $reflectedParent = $reflectedOutput->getParentClass(); - $streamProperty = $reflectedParent->getProperty('stream'); - $streamProperty->setAccessible(true); - $streamProperty->setValue($this->output, fopen('php://memory', 'w', false)); - } - } - - /** - * @return resource - */ - private static function createStream(array $inputs) - { - $stream = fopen('php://memory', 'r+', false); - - foreach ($inputs as $input) { - fwrite($stream, $input.PHP_EOL); - } - - rewind($stream); - - return $stream; - } -} diff --git a/vendor/symfony/console/composer.json b/vendor/symfony/console/composer.json deleted file mode 100644 index 8948071..0000000 --- a/vendor/symfony/console/composer.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "name": "symfony/console", - "type": "library", - "description": "Symfony Console Component", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.8", - "symfony/service-contracts": "^1.1|^2" - }, - "require-dev": { - "symfony/config": "^4.4|^5.0", - "symfony/event-dispatcher": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/lock": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0", - "symfony/var-dumper": "^4.4|^5.0", - "psr/log": "~1.0" - }, - "provide": { - "psr/log-implementation": "1.0" - }, - "suggest": { - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "", - "psr/log": "For using the console logger" - }, - "conflict": { - "symfony/dependency-injection": "<4.4", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Console\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/dependency-injection/.gitattributes b/vendor/symfony/dependency-injection/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/dependency-injection/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/dependency-injection/Alias.php b/vendor/symfony/dependency-injection/Alias.php deleted file mode 100644 index 79e7e24..0000000 --- a/vendor/symfony/dependency-injection/Alias.php +++ /dev/null @@ -1,133 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -class Alias -{ - private $id; - private $public; - private $private; - private $deprecated; - private $deprecationTemplate; - - private static $defaultDeprecationTemplate = 'The "%alias_id%" service alias is deprecated. You should stop using it, as it will be removed in the future.'; - - public function __construct(string $id, bool $public = true) - { - $this->id = $id; - $this->public = $public; - $this->private = 2 > \func_num_args(); - $this->deprecated = false; - } - - /** - * Checks if this DI Alias should be public or not. - * - * @return bool - */ - public function isPublic() - { - return $this->public; - } - - /** - * Sets if this Alias is public. - * - * @return $this - */ - public function setPublic(bool $boolean) - { - $this->public = $boolean; - $this->private = false; - - return $this; - } - - /** - * Sets if this Alias is private. - * - * When set, the "private" state has a higher precedence than "public". - * In version 3.4, a "private" alias always remains publicly accessible, - * but triggers a deprecation notice when accessed from the container, - * so that the alias can be made really private in 4.0. - * - * @return $this - */ - public function setPrivate(bool $boolean) - { - $this->private = $boolean; - - return $this; - } - - /** - * Whether this alias is private. - * - * @return bool - */ - public function isPrivate() - { - return $this->private; - } - - /** - * Whether this alias is deprecated, that means it should not be referenced - * anymore. - * - * @param bool $status Whether this alias is deprecated, defaults to true - * @param string $template Optional template message to use if the alias is deprecated - * - * @return $this - * - * @throws InvalidArgumentException when the message template is invalid - */ - public function setDeprecated(bool $status = true, string $template = null) - { - if (null !== $template) { - if (preg_match('#[\r\n]|\*/#', $template)) { - throw new InvalidArgumentException('Invalid characters found in deprecation template.'); - } - - if (false === strpos($template, '%alias_id%')) { - throw new InvalidArgumentException('The deprecation template must contain the "%alias_id%" placeholder.'); - } - - $this->deprecationTemplate = $template; - } - - $this->deprecated = $status; - - return $this; - } - - public function isDeprecated(): bool - { - return $this->deprecated; - } - - public function getDeprecationMessage(string $id): string - { - return str_replace('%alias_id%', $id, $this->deprecationTemplate ?: self::$defaultDeprecationTemplate); - } - - /** - * Returns the Id of this alias. - * - * @return string The alias id - */ - public function __toString() - { - return $this->id; - } -} diff --git a/vendor/symfony/dependency-injection/Argument/ArgumentInterface.php b/vendor/symfony/dependency-injection/Argument/ArgumentInterface.php deleted file mode 100644 index b46eb77..0000000 --- a/vendor/symfony/dependency-injection/Argument/ArgumentInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -/** - * Represents a complex argument containing nested values. - * - * @author Titouan Galopin - */ -interface ArgumentInterface -{ - /** - * @return array - */ - public function getValues(); - - public function setValues(array $values); -} diff --git a/vendor/symfony/dependency-injection/Argument/BoundArgument.php b/vendor/symfony/dependency-injection/Argument/BoundArgument.php deleted file mode 100644 index 6005926..0000000 --- a/vendor/symfony/dependency-injection/Argument/BoundArgument.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -/** - * @author Guilhem Niot - */ -final class BoundArgument implements ArgumentInterface -{ - const SERVICE_BINDING = 0; - const DEFAULTS_BINDING = 1; - const INSTANCEOF_BINDING = 2; - - private static $sequence = 0; - - private $value; - private $identifier; - private $used; - private $type; - private $file; - - public function __construct($value, bool $trackUsage = true, int $type = 0, string $file = null) - { - $this->value = $value; - if ($trackUsage) { - $this->identifier = ++self::$sequence; - } else { - $this->used = true; - } - $this->type = $type; - $this->file = $file; - } - - /** - * {@inheritdoc} - */ - public function getValues(): array - { - return [$this->value, $this->identifier, $this->used, $this->type, $this->file]; - } - - /** - * {@inheritdoc} - */ - public function setValues(array $values) - { - if (5 === \count($values)) { - list($this->value, $this->identifier, $this->used, $this->type, $this->file) = $values; - } else { - list($this->value, $this->identifier, $this->used) = $values; - } - } -} diff --git a/vendor/symfony/dependency-injection/Argument/IteratorArgument.php b/vendor/symfony/dependency-injection/Argument/IteratorArgument.php deleted file mode 100644 index d413678..0000000 --- a/vendor/symfony/dependency-injection/Argument/IteratorArgument.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -/** - * Represents a collection of values to lazily iterate over. - * - * @author Titouan Galopin - */ -class IteratorArgument implements ArgumentInterface -{ - use ReferenceSetArgumentTrait; -} diff --git a/vendor/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php b/vendor/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php deleted file mode 100644 index 6f8d5d9..0000000 --- a/vendor/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Titouan Galopin - * @author Nicolas Grekas - */ -trait ReferenceSetArgumentTrait -{ - private $values; - - /** - * @param Reference[] $values - */ - public function __construct(array $values) - { - $this->setValues($values); - } - - /** - * @return Reference[] The values in the set - */ - public function getValues() - { - return $this->values; - } - - /** - * @param Reference[] $values The service references to put in the set - */ - public function setValues(array $values) - { - foreach ($values as $k => $v) { - if (null !== $v && !$v instanceof Reference) { - throw new InvalidArgumentException(sprintf('A %s must hold only Reference instances, "%s" given.', __CLASS__, \is_object($v) ? \get_class($v) : \gettype($v))); - } - } - - $this->values = $values; - } -} diff --git a/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php b/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php deleted file mode 100644 index 41fec78..0000000 --- a/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -/** - * @internal - */ -class RewindableGenerator implements \IteratorAggregate, \Countable -{ - private $generator; - private $count; - - /** - * @param int|callable $count - */ - public function __construct(callable $generator, $count) - { - $this->generator = $generator; - $this->count = $count; - } - - public function getIterator(): \Traversable - { - $g = $this->generator; - - return $g(); - } - - public function count(): int - { - if (\is_callable($count = $this->count)) { - $this->count = $count(); - } - - return $this->count; - } -} diff --git a/vendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php b/vendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php deleted file mode 100644 index 6331aff..0000000 --- a/vendor/symfony/dependency-injection/Argument/ServiceClosureArgument.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Represents a service wrapped in a memoizing closure. - * - * @author Nicolas Grekas - */ -class ServiceClosureArgument implements ArgumentInterface -{ - private $values; - - public function __construct(Reference $reference) - { - $this->values = [$reference]; - } - - /** - * {@inheritdoc} - */ - public function getValues() - { - return $this->values; - } - - /** - * {@inheritdoc} - */ - public function setValues(array $values) - { - if ([0] !== array_keys($values) || !($values[0] instanceof Reference || null === $values[0])) { - throw new InvalidArgumentException('A ServiceClosureArgument must hold one and only one Reference.'); - } - - $this->values = $values; - } -} diff --git a/vendor/symfony/dependency-injection/Argument/ServiceLocator.php b/vendor/symfony/dependency-injection/Argument/ServiceLocator.php deleted file mode 100644 index 2001a95..0000000 --- a/vendor/symfony/dependency-injection/Argument/ServiceLocator.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -use Symfony\Component\DependencyInjection\ServiceLocator as BaseServiceLocator; - -/** - * @author Nicolas Grekas - * - * @internal - */ -class ServiceLocator extends BaseServiceLocator -{ - private $factory; - private $serviceMap; - private $serviceTypes; - - public function __construct(\Closure $factory, array $serviceMap, array $serviceTypes = null) - { - $this->factory = $factory; - $this->serviceMap = $serviceMap; - $this->serviceTypes = $serviceTypes; - parent::__construct($serviceMap); - } - - /** - * {@inheritdoc} - */ - public function get($id) - { - return isset($this->serviceMap[$id]) ? ($this->factory)(...$this->serviceMap[$id]) : parent::get($id); - } - - /** - * {@inheritdoc} - */ - public function getProvidedServices(): array - { - return $this->serviceTypes ?? $this->serviceTypes = array_map(function () { return '?'; }, $this->serviceMap); - } -} diff --git a/vendor/symfony/dependency-injection/Argument/ServiceLocatorArgument.php b/vendor/symfony/dependency-injection/Argument/ServiceLocatorArgument.php deleted file mode 100644 index fcbf478..0000000 --- a/vendor/symfony/dependency-injection/Argument/ServiceLocatorArgument.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -use Symfony\Component\DependencyInjection\Reference; - -/** - * Represents a closure acting as a service locator. - * - * @author Nicolas Grekas - */ -class ServiceLocatorArgument implements ArgumentInterface -{ - use ReferenceSetArgumentTrait; - - private $taggedIteratorArgument; - - /** - * @param Reference[]|TaggedIteratorArgument $values - */ - public function __construct($values = []) - { - if ($values instanceof TaggedIteratorArgument) { - $this->taggedIteratorArgument = $values; - $this->values = []; - } else { - $this->setValues($values); - } - } - - public function getTaggedIteratorArgument(): ?TaggedIteratorArgument - { - return $this->taggedIteratorArgument; - } -} diff --git a/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php b/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php deleted file mode 100644 index d1d5f6d..0000000 --- a/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php +++ /dev/null @@ -1,73 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -/** - * Represents a collection of services found by tag name to lazily iterate over. - * - * @author Roland Franssen - */ -class TaggedIteratorArgument extends IteratorArgument -{ - private $tag; - private $indexAttribute; - private $defaultIndexMethod; - private $defaultPriorityMethod; - private $needsIndexes = false; - - /** - * @param string $tag The name of the tag identifying the target services - * @param string|null $indexAttribute The name of the attribute that defines the key referencing each service in the tagged collection - * @param string|null $defaultIndexMethod The static method that should be called to get each service's key when their tag doesn't define the previous attribute - * @param bool $needsIndexes Whether indexes are required and should be generated when computing the map - * @param string|null $defaultPriorityMethod The static method that should be called to get each service's priority when their tag doesn't define the "priority" attribute - */ - public function __construct(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, bool $needsIndexes = false, string $defaultPriorityMethod = null) - { - parent::__construct([]); - - if (null === $indexAttribute && $needsIndexes) { - $indexAttribute = preg_match('/[^.]++$/', $tag, $m) ? $m[0] : $tag; - } - - $this->tag = $tag; - $this->indexAttribute = $indexAttribute; - $this->defaultIndexMethod = $defaultIndexMethod ?: ('getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute ?? ''))).'Name'); - $this->needsIndexes = $needsIndexes; - $this->defaultPriorityMethod = $defaultPriorityMethod ?: ('getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute ?? ''))).'Priority'); - } - - public function getTag() - { - return $this->tag; - } - - public function getIndexAttribute(): ?string - { - return $this->indexAttribute; - } - - public function getDefaultIndexMethod(): ?string - { - return $this->defaultIndexMethod; - } - - public function needsIndexes(): bool - { - return $this->needsIndexes; - } - - public function getDefaultPriorityMethod(): ?string - { - return $this->defaultPriorityMethod; - } -} diff --git a/vendor/symfony/dependency-injection/CHANGELOG.md b/vendor/symfony/dependency-injection/CHANGELOG.md deleted file mode 100644 index b043220..0000000 --- a/vendor/symfony/dependency-injection/CHANGELOG.md +++ /dev/null @@ -1,248 +0,0 @@ -CHANGELOG -========= - -5.0.0 ------ - - * removed support for auto-discovered extension configuration class which does not implement `ConfigurationInterface` - * removed support for non-string default env() parameters - * moved `ServiceSubscriberInterface` to the `Symfony\Contracts\Service` namespace - * removed `RepeatedPass` and `RepeatablePassInterface` - * removed support for short factory/configurator syntax from `YamlFileLoader` - * removed `ResettableContainerInterface`, use `ResetInterface` instead - * added argument `$returnsClone` to `Definition::addMethodCall()` - * removed `tagged`, use `tagged_iterator` instead - -4.4.0 ------ - - * added `CheckTypeDeclarationsPass` to check injected parameters type during compilation - * added support for opcache.preload by generating a preloading script in the cache folder - * added support for dumping the container in one file instead of many files - * deprecated support for short factories and short configurators in Yaml - * added `tagged_iterator` alias for `tagged` which might be deprecated in a future version - * deprecated passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition` - * added support for binding iterable and tagged services - * made singly-implemented interfaces detection be scoped by file - * added ability to define a static priority method for tagged service - * added support for improved syntax to define method calls in Yaml - * made the `%env(base64:...)%` processor able to decode base64url - * added ability to choose behavior of decorations on non existent decorated services - -4.3.0 ------ - - * added `%env(trim:...)%` processor to trim a string value - * added `%env(default:param_name:...)%` processor to fallback to a parameter or to null when using `%env(default::...)%` - * added `%env(url:...)%` processor to convert an URL or DNS into an array of components - * added `%env(query_string:...)%` processor to convert a query string into an array of key values - * added support for deprecating aliases - * made `ContainerParametersResource` final and not implement `Serializable` anymore - * added `ReverseContainer`: a container that turns services back to their ids - * added ability to define an index for a tagged collection - * added ability to define an index for services in an injected service locator argument - * made `ServiceLocator` implement `ServiceProviderInterface` - * deprecated support for non-string default env() parameters - * added `%env(require:...)%` processor to `require()` a PHP file and use the value returned from it - -4.2.0 ------ - - * added `ContainerBuilder::registerAliasForArgument()` to support autowiring by type+name - * added support for binding by type+name - * added `ServiceSubscriberTrait` to ease implementing `ServiceSubscriberInterface` using methods' return types - * added `ServiceLocatorArgument` and `!service_locator` config tag for creating optimized service-locators - * added support for autoconfiguring bindings - * added `%env(key:...)%` processor to fetch a specific key from an array - * deprecated `ServiceSubscriberInterface`, use the same interface from the `Symfony\Contracts\Service` namespace instead - * deprecated `ResettableContainerInterface`, use `Symfony\Contracts\Service\ResetInterface` instead - -4.1.0 ------ - - * added support for variadics in named arguments - * added PSR-11 `ContainerBagInterface` and its `ContainerBag` implementation to access parameters as-a-service - * added support for service's decorators autowiring - * deprecated the `TypedReference::canBeAutoregistered()` and `TypedReference::getRequiringClass()` methods - * environment variables are validated when used in extension configuration - * deprecated support for auto-discovered extension configuration class which does not implement `ConfigurationInterface` - -4.0.0 ------ - - * Relying on service auto-registration while autowiring is not supported anymore. - Explicitly inject your dependencies or create services whose ids are - their fully-qualified class name. - - Before: - - ```php - namespace App\Controller; - - use App\Mailer; - - class DefaultController - { - public function __construct(Mailer $mailer) { - // ... - } - - // ... - } - ``` - ```yml - services: - App\Controller\DefaultController: - autowire: true - ``` - - After: - - ```php - // same PHP code - ``` - ```yml - services: - App\Controller\DefaultController: - autowire: true - - # or - # App\Controller\DefaultController: - # arguments: { $mailer: "@App\Mailer" } - - App\Mailer: - autowire: true - ``` - * removed autowiring services based on the types they implement - * added a third `$methodName` argument to the `getProxyFactoryCode()` method - of the `DumperInterface` - * removed support for autowiring types - * removed `Container::isFrozen` - * removed support for dumping an ucompiled container in `PhpDumper` - * removed support for generating a dumped `Container` without populating the method map - * removed support for case insensitive service identifiers - * removed the `DefinitionDecorator` class, replaced by `ChildDefinition` - * removed the `AutowireServiceResource` class and related `AutowirePass::createResourceForClass()` method - * removed `LoggingFormatter`, `Compiler::getLoggingFormatter()` and `addLogMessage()` class and methods, use the `ContainerBuilder::log()` method instead - * removed `FactoryReturnTypePass` - * removed `ContainerBuilder::addClassResource()`, use the `addObjectResource()` or the `getReflectionClass()` method instead. - * removed support for top-level anonymous services - * removed silent behavior for unused attributes and elements - * removed support for setting and accessing private services in `Container` - * removed support for setting pre-defined services in `Container` - * removed support for case insensitivity of parameter names - * removed `AutowireExceptionPass` and `AutowirePass::getAutowiringExceptions()`, use `Definition::addError()` and the `DefinitionErrorExceptionPass` instead - -3.4.0 ------ - - * moved the `ExtensionCompilerPass` to before-optimization passes with priority -1000 - * deprecated "public-by-default" definitions and aliases, the new default will be "private" in 4.0 - * added `EnvVarProcessorInterface` and corresponding "container.env_var_processor" tag for processing env vars - * added support for ignore-on-uninitialized references - * deprecated service auto-registration while autowiring - * deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method - * deprecated support for top-level anonymous services in XML - * deprecated case insensitivity of parameter names - * deprecated the `ResolveDefinitionTemplatesPass` class in favor of `ResolveChildDefinitionsPass` - * added `TaggedIteratorArgument` with YAML (`!tagged foo`) and XML (``) support - * deprecated `AutowireExceptionPass` and `AutowirePass::getAutowiringExceptions()`, use `Definition::addError()` and the `DefinitionErrorExceptionPass` instead - - -3.3.0 ------ - - * deprecated autowiring services based on the types they implement; - rename (or alias) your services to their FQCN id to make them autowirable - * added "ServiceSubscriberInterface" - to allow for per-class explicit service-locator definitions - * added "container.service_locator" tag for defining service-locator services - * added anonymous services support in YAML configuration files using the `!service` tag. - * added "TypedReference" and "ServiceClosureArgument" for creating service-locator services - * added `ServiceLocator` - a PSR-11 container holding a set of services to be lazily loaded - * added "instanceof" section for local interface-defined configs - * added prototype services for PSR4-based discovery and registration - * added `ContainerBuilder::getReflectionClass()` for retrieving and tracking reflection class info - * deprecated `ContainerBuilder::getClassResource()`, use `ContainerBuilder::getReflectionClass()` or `ContainerBuilder::addObjectResource()` instead - * added `ContainerBuilder::fileExists()` for checking and tracking file or directory existence - * deprecated autowiring-types, use aliases instead - * added support for omitting the factory class name in a service definition if the definition class is set - * deprecated case insensitivity of service identifiers - * added "iterator" argument type for lazy iteration over a set of values and services - * added file-wide configurable defaults for service attributes "public", "tags", - "autowire" and "autoconfigure" - * made the "class" attribute optional, using the "id" as fallback - * using the `PhpDumper` with an uncompiled `ContainerBuilder` is deprecated and - will not be supported anymore in 4.0 - * deprecated the `DefinitionDecorator` class in favor of `ChildDefinition` - * allow config files to be loaded using a glob pattern - * [BC BREAK] the `NullDumper` class is now final - -3.2.0 ------ - - * allowed to prioritize compiler passes by introducing a third argument to `PassConfig::addPass()`, to `Compiler::addPass` and to `ContainerBuilder::addCompilerPass()` - * added support for PHP constants in YAML configuration files - * deprecated the ability to set or unset a private service with the `Container::set()` method - * deprecated the ability to check for the existence of a private service with the `Container::has()` method - * deprecated the ability to request a private service with the `Container::get()` method - * deprecated support for generating a dumped `Container` without populating the method map - -3.0.0 ------ - - * removed all deprecated codes from 2.x versions - -2.8.0 ------ - - * deprecated the abstract ContainerAware class in favor of ContainerAwareTrait - * deprecated IntrospectableContainerInterface, to be merged with ContainerInterface in 3.0 - * allowed specifying a directory to recursively load all configuration files it contains - * deprecated the concept of scopes - * added `Definition::setShared()` and `Definition::isShared()` - * added ResettableContainerInterface to be able to reset the container to release memory on shutdown - * added a way to define the priority of service decoration - * added support for service autowiring - -2.7.0 ------ - - * deprecated synchronized services - -2.6.0 ------ - - * added new factory syntax and deprecated the old one - -2.5.0 ------ - -* added DecoratorServicePass and a way to override a service definition (Definition::setDecoratedService()) -* deprecated SimpleXMLElement class. - -2.4.0 ------ - - * added support for expressions in service definitions - * added ContainerAwareTrait to add default container aware behavior to a class - -2.2.0 ------ - - * added Extension::isConfigEnabled() to ease working with enableable configurations - * added an Extension base class with sensible defaults to be used in conjunction - with the Config component. - * added PrependExtensionInterface (to be able to allow extensions to prepend - application configuration settings for any Bundle) - -2.1.0 ------ - - * added IntrospectableContainerInterface (to be able to check if a service - has been initialized or not) - * added ConfigurationExtensionInterface - * added Definition::clearTag() - * component exceptions that inherit base SPL classes are now used exclusively - (this includes dumped containers) - * [BC BREAK] fixed unescaping of class arguments, method - ParameterBag::unescapeValue() was made public diff --git a/vendor/symfony/dependency-injection/ChildDefinition.php b/vendor/symfony/dependency-injection/ChildDefinition.php deleted file mode 100644 index 657a7fa..0000000 --- a/vendor/symfony/dependency-injection/ChildDefinition.php +++ /dev/null @@ -1,124 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; - -/** - * This definition extends another definition. - * - * @author Johannes M. Schmitt - */ -class ChildDefinition extends Definition -{ - private $parent; - - /** - * @param string $parent The id of Definition instance to decorate - */ - public function __construct(string $parent) - { - $this->parent = $parent; - $this->setPrivate(false); - } - - /** - * Returns the Definition to inherit from. - * - * @return string - */ - public function getParent() - { - return $this->parent; - } - - /** - * Sets the Definition to inherit from. - * - * @param string $parent - * - * @return $this - */ - public function setParent($parent) - { - $this->parent = $parent; - - return $this; - } - - /** - * Gets an argument to pass to the service constructor/factory method. - * - * If replaceArgument() has been used to replace an argument, this method - * will return the replacement value. - * - * @param int|string $index - * - * @return mixed The argument value - * - * @throws OutOfBoundsException When the argument does not exist - */ - public function getArgument($index) - { - if (\array_key_exists('index_'.$index, $this->arguments)) { - return $this->arguments['index_'.$index]; - } - - return parent::getArgument($index); - } - - /** - * You should always use this method when overwriting existing arguments - * of the parent definition. - * - * If you directly call setArguments() keep in mind that you must follow - * certain conventions when you want to overwrite the arguments of the - * parent definition, otherwise your arguments will only be appended. - * - * @param int|string $index - * @param mixed $value - * - * @return $this - * - * @throws InvalidArgumentException when $index isn't an integer - */ - public function replaceArgument($index, $value) - { - if (\is_int($index)) { - $this->arguments['index_'.$index] = $value; - } elseif (0 === strpos($index, '$')) { - $this->arguments[$index] = $value; - } else { - throw new InvalidArgumentException('The argument must be an existing index or the name of a constructor\'s parameter.'); - } - - return $this; - } - - /** - * @internal - */ - public function setAutoconfigured(bool $autoconfigured): self - { - throw new BadMethodCallException('A ChildDefinition cannot be autoconfigured.'); - } - - /** - * @internal - */ - public function setInstanceofConditionals(array $instanceof): self - { - throw new BadMethodCallException('A ChildDefinition cannot have instanceof conditionals set on it.'); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php b/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php deleted file mode 100644 index 2920af1..0000000 --- a/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php +++ /dev/null @@ -1,223 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\ExpressionLanguage; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\ExpressionLanguage\Expression; - -/** - * @author Nicolas Grekas - */ -abstract class AbstractRecursivePass implements CompilerPassInterface -{ - /** - * @var ContainerBuilder - */ - protected $container; - protected $currentId; - - private $processExpressions = false; - private $expressionLanguage; - private $inExpression = false; - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $this->container = $container; - - try { - $this->processValue($container->getDefinitions(), true); - } finally { - $this->container = null; - } - } - - protected function enableExpressionProcessing() - { - $this->processExpressions = true; - } - - protected function inExpression(bool $reset = true): bool - { - $inExpression = $this->inExpression; - if ($reset) { - $this->inExpression = false; - } - - return $inExpression; - } - - /** - * Processes a value found in a definition tree. - * - * @param mixed $value - * - * @return mixed The processed value - */ - protected function processValue($value, bool $isRoot = false) - { - if (\is_array($value)) { - foreach ($value as $k => $v) { - if ($isRoot) { - $this->currentId = $k; - } - if ($v !== $processedValue = $this->processValue($v, $isRoot)) { - $value[$k] = $processedValue; - } - } - } elseif ($value instanceof ArgumentInterface) { - $value->setValues($this->processValue($value->getValues())); - } elseif ($value instanceof Expression && $this->processExpressions) { - $this->getExpressionLanguage()->compile((string) $value, ['this' => 'container']); - } elseif ($value instanceof Definition) { - $value->setArguments($this->processValue($value->getArguments())); - $value->setProperties($this->processValue($value->getProperties())); - $value->setMethodCalls($this->processValue($value->getMethodCalls())); - - $changes = $value->getChanges(); - if (isset($changes['factory'])) { - $value->setFactory($this->processValue($value->getFactory())); - } - if (isset($changes['configurator'])) { - $value->setConfigurator($this->processValue($value->getConfigurator())); - } - } - - return $value; - } - - /** - * @return \ReflectionFunctionAbstract|null - * - * @throws RuntimeException - */ - protected function getConstructor(Definition $definition, bool $required) - { - if ($definition->isSynthetic()) { - return null; - } - - if (\is_string($factory = $definition->getFactory())) { - if (!\function_exists($factory)) { - throw new RuntimeException(sprintf('Invalid service "%s": function "%s" does not exist.', $this->currentId, $factory)); - } - $r = new \ReflectionFunction($factory); - if (false !== $r->getFileName() && file_exists($r->getFileName())) { - $this->container->fileExists($r->getFileName()); - } - - return $r; - } - - if ($factory) { - list($class, $method) = $factory; - if ($class instanceof Reference) { - $class = $this->container->findDefinition((string) $class)->getClass(); - } elseif ($class instanceof Definition) { - $class = $class->getClass(); - } elseif (null === $class) { - $class = $definition->getClass(); - } - - if ('__construct' === $method) { - throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId)); - } - - return $this->getReflectionMethod(new Definition($class), $method); - } - - $class = $definition->getClass(); - - try { - if (!$r = $this->container->getReflectionClass($class)) { - throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class)); - } - } catch (\ReflectionException $e) { - throw new RuntimeException(sprintf('Invalid service "%s": %s.', $this->currentId, lcfirst(rtrim($e->getMessage(), '.')))); - } - if (!$r = $r->getConstructor()) { - if ($required) { - throw new RuntimeException(sprintf('Invalid service "%s": class%s has no constructor.', $this->currentId, sprintf($class !== $this->currentId ? ' "%s"' : '', $class))); - } - } elseif (!$r->isPublic()) { - throw new RuntimeException(sprintf('Invalid service "%s": %s must be public.', $this->currentId, sprintf($class !== $this->currentId ? 'constructor of class "%s"' : 'its constructor', $class))); - } - - return $r; - } - - /** - * @throws RuntimeException - * - * @return \ReflectionFunctionAbstract - */ - protected function getReflectionMethod(Definition $definition, string $method) - { - if ('__construct' === $method) { - return $this->getConstructor($definition, true); - } - - if (!$class = $definition->getClass()) { - throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId)); - } - - if (!$r = $this->container->getReflectionClass($class)) { - throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class)); - } - - if (!$r->hasMethod($method)) { - throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" does not exist.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method)); - } - - $r = $r->getMethod($method); - if (!$r->isPublic()) { - throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" must be public.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method)); - } - - return $r; - } - - private function getExpressionLanguage(): ExpressionLanguage - { - if (null === $this->expressionLanguage) { - if (!class_exists(ExpressionLanguage::class)) { - throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - - $providers = $this->container->getExpressionLanguageProviders(); - $this->expressionLanguage = new ExpressionLanguage(null, $providers, function (string $arg): string { - if ('""' === substr_replace($arg, '', 1, -1)) { - $id = stripcslashes(substr($arg, 1, -1)); - $this->inExpression = true; - $arg = $this->processValue(new Reference($id)); - $this->inExpression = false; - if (!$arg instanceof Reference) { - throw new RuntimeException(sprintf('"%s::processValue()" must return a Reference when processing an expression, %s returned for service("%s").', \get_class($this), \is_object($arg) ? \get_class($arg) : \gettype($arg), $id)); - } - $arg = sprintf('"%s"', $arg); - } - - return sprintf('$this->get(%s)', $arg); - }); - } - - return $this->expressionLanguage; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php b/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php deleted file mode 100644 index beb4882..0000000 --- a/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php +++ /dev/null @@ -1,184 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Run this pass before passes that need to know more about the relation of - * your services. - * - * This class will populate the ServiceReferenceGraph with information. You can - * retrieve the graph in other passes from the compiler. - * - * @author Johannes M. Schmitt - * @author Nicolas Grekas - */ -class AnalyzeServiceReferencesPass extends AbstractRecursivePass -{ - private $graph; - private $currentDefinition; - private $onlyConstructorArguments; - private $hasProxyDumper; - private $lazy; - private $byConstructor; - private $definitions; - private $aliases; - - /** - * @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls - */ - public function __construct(bool $onlyConstructorArguments = false, bool $hasProxyDumper = true) - { - $this->onlyConstructorArguments = $onlyConstructorArguments; - $this->hasProxyDumper = $hasProxyDumper; - $this->enableExpressionProcessing(); - } - - /** - * Processes a ContainerBuilder object to populate the service reference graph. - */ - public function process(ContainerBuilder $container) - { - $this->container = $container; - $this->graph = $container->getCompiler()->getServiceReferenceGraph(); - $this->graph->clear(); - $this->lazy = false; - $this->byConstructor = false; - $this->definitions = $container->getDefinitions(); - $this->aliases = $container->getAliases(); - - foreach ($this->aliases as $id => $alias) { - $targetId = $this->getDefinitionId((string) $alias); - $this->graph->connect($id, $alias, $targetId, null !== $targetId ? $this->container->getDefinition($targetId) : null, null); - } - - try { - parent::process($container); - } finally { - $this->aliases = $this->definitions = []; - } - } - - protected function processValue($value, bool $isRoot = false) - { - $lazy = $this->lazy; - $inExpression = $this->inExpression(); - - if ($value instanceof ArgumentInterface) { - $this->lazy = true; - parent::processValue($value->getValues()); - $this->lazy = $lazy; - - return $value; - } - if ($value instanceof Reference) { - $targetId = $this->getDefinitionId((string) $value); - $targetDefinition = null !== $targetId ? $this->container->getDefinition($targetId) : null; - - $this->graph->connect( - $this->currentId, - $this->currentDefinition, - $targetId, - $targetDefinition, - $value, - $this->lazy || ($this->hasProxyDumper && $targetDefinition && $targetDefinition->isLazy()), - ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior(), - $this->byConstructor - ); - - if ($inExpression) { - $this->graph->connect( - '.internal.reference_in_expression', - null, - $targetId, - $targetDefinition, - $value, - $this->lazy || ($targetDefinition && $targetDefinition->isLazy()), - true - ); - } - - return $value; - } - if (!$value instanceof Definition) { - return parent::processValue($value, $isRoot); - } - if ($isRoot) { - if ($value->isSynthetic() || $value->isAbstract()) { - return $value; - } - $this->currentDefinition = $value; - } elseif ($this->currentDefinition === $value) { - return $value; - } - $this->lazy = false; - - $byConstructor = $this->byConstructor; - $this->byConstructor = $isRoot || $byConstructor; - $this->processValue($value->getFactory()); - $this->processValue($value->getArguments()); - - $properties = $value->getProperties(); - $setters = $value->getMethodCalls(); - - // Any references before a "wither" are part of the constructor-instantiation graph - $lastWitherIndex = null; - foreach ($setters as $k => $call) { - if ($call[2] ?? false) { - $lastWitherIndex = $k; - } - } - - if (null !== $lastWitherIndex) { - $this->processValue($properties); - $setters = $properties = []; - - foreach ($value->getMethodCalls() as $k => $call) { - if (null === $lastWitherIndex) { - $setters[] = $call; - continue; - } - - if ($lastWitherIndex === $k) { - $lastWitherIndex = null; - } - - $this->processValue($call); - } - } - - $this->byConstructor = $byConstructor; - - if (!$this->onlyConstructorArguments) { - $this->processValue($properties); - $this->processValue($setters); - $this->processValue($value->getConfigurator()); - } - $this->lazy = $lazy; - - return $value; - } - - private function getDefinitionId(string $id): ?string - { - while (isset($this->aliases[$id])) { - $id = (string) $this->aliases[$id]; - } - - return isset($this->definitions[$id]) ? $id : null; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php b/vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php deleted file mode 100644 index 0342068..0000000 --- a/vendor/symfony/dependency-injection/Compiler/AutoAliasServicePass.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * Sets a service to be an alias of another one, given a format pattern. - */ -class AutoAliasServicePass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - foreach ($container->findTaggedServiceIds('auto_alias') as $serviceId => $tags) { - foreach ($tags as $tag) { - if (!isset($tag['format'])) { - throw new InvalidArgumentException(sprintf('Missing tag information "format" on auto_alias service "%s".', $serviceId)); - } - - $aliasId = $container->getParameterBag()->resolveValue($tag['format']); - if ($container->hasDefinition($aliasId) || $container->hasAlias($aliasId)) { - $container->setAlias($serviceId, new Alias($aliasId, true)); - } - } - } - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/AutowirePass.php b/vendor/symfony/dependency-injection/Compiler/AutowirePass.php deleted file mode 100644 index ba10e92..0000000 --- a/vendor/symfony/dependency-injection/Compiler/AutowirePass.php +++ /dev/null @@ -1,475 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\Config\Resource\ClassExistenceResource; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; -use Symfony\Component\DependencyInjection\TypedReference; - -/** - * Inspects existing service definitions and wires the autowired ones using the type hints of their classes. - * - * @author Kévin Dunglas - * @author Nicolas Grekas - */ -class AutowirePass extends AbstractRecursivePass -{ - private $types; - private $ambiguousServiceTypes; - private $lastFailure; - private $throwOnAutowiringException; - private $decoratedClass; - private $decoratedId; - private $methodCalls; - private $getPreviousValue; - private $decoratedMethodIndex; - private $decoratedMethodArgumentIndex; - private $typesClone; - - public function __construct(bool $throwOnAutowireException = true) - { - $this->throwOnAutowiringException = $throwOnAutowireException; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - try { - $this->typesClone = clone $this; - parent::process($container); - } finally { - $this->decoratedClass = null; - $this->decoratedId = null; - $this->methodCalls = null; - $this->getPreviousValue = null; - $this->decoratedMethodIndex = null; - $this->decoratedMethodArgumentIndex = null; - $this->typesClone = null; - } - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - try { - return $this->doProcessValue($value, $isRoot); - } catch (AutowiringFailedException $e) { - if ($this->throwOnAutowiringException) { - throw $e; - } - - $this->container->getDefinition($this->currentId)->addError($e->getMessageCallback() ?? $e->getMessage()); - - return parent::processValue($value, $isRoot); - } - } - - /** - * @return mixed - */ - private function doProcessValue($value, bool $isRoot = false) - { - if ($value instanceof TypedReference) { - if ($ref = $this->getAutowiredReference($value)) { - return $ref; - } - if (ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) { - $message = $this->createTypeNotFoundMessageCallback($value, 'it'); - - // since the error message varies by referenced id and $this->currentId, so should the id of the dummy errored definition - $this->container->register($id = sprintf('.errored.%s.%s', $this->currentId, (string) $value), $value->getType()) - ->addError($message); - - return new TypedReference($id, $value->getType(), $value->getInvalidBehavior(), $value->getName()); - } - } - $value = parent::processValue($value, $isRoot); - - if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) { - return $value; - } - if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) { - $this->container->log($this, sprintf('Skipping service "%s": Class or interface "%s" cannot be loaded.', $this->currentId, $value->getClass())); - - return $value; - } - - $this->methodCalls = $value->getMethodCalls(); - - try { - $constructor = $this->getConstructor($value, false); - } catch (RuntimeException $e) { - throw new AutowiringFailedException($this->currentId, $e->getMessage(), 0, $e); - } - - if ($constructor) { - array_unshift($this->methodCalls, [$constructor, $value->getArguments()]); - } - - $this->methodCalls = $this->autowireCalls($reflectionClass, $isRoot); - - if ($constructor) { - list(, $arguments) = array_shift($this->methodCalls); - - if ($arguments !== $value->getArguments()) { - $value->setArguments($arguments); - } - } - - if ($this->methodCalls !== $value->getMethodCalls()) { - $value->setMethodCalls($this->methodCalls); - } - - return $value; - } - - private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot): array - { - $this->decoratedId = null; - $this->decoratedClass = null; - $this->getPreviousValue = null; - - if ($isRoot && ($definition = $this->container->getDefinition($this->currentId)) && $this->container->has($this->decoratedId = $definition->innerServiceId)) { - $this->decoratedClass = $this->container->findDefinition($this->decoratedId)->getClass(); - } - - foreach ($this->methodCalls as $i => $call) { - $this->decoratedMethodIndex = $i; - list($method, $arguments) = $call; - - if ($method instanceof \ReflectionFunctionAbstract) { - $reflectionMethod = $method; - } else { - $definition = new Definition($reflectionClass->name); - try { - $reflectionMethod = $this->getReflectionMethod($definition, $method); - } catch (RuntimeException $e) { - if ($definition->getFactory()) { - continue; - } - throw $e; - } - } - - $arguments = $this->autowireMethod($reflectionMethod, $arguments); - - if ($arguments !== $call[1]) { - $this->methodCalls[$i][1] = $arguments; - } - } - - return $this->methodCalls; - } - - /** - * Autowires the constructor or a method. - * - * @return array The autowired arguments - * - * @throws AutowiringFailedException - */ - private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments): array - { - $class = $reflectionMethod instanceof \ReflectionMethod ? $reflectionMethod->class : $this->currentId; - $method = $reflectionMethod->name; - $parameters = $reflectionMethod->getParameters(); - if ($reflectionMethod->isVariadic()) { - array_pop($parameters); - } - - foreach ($parameters as $index => $parameter) { - if (\array_key_exists($index, $arguments) && '' !== $arguments[$index]) { - continue; - } - - $type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true); - - if (!$type) { - if (isset($arguments[$index])) { - continue; - } - - // no default value? Then fail - if (!$parameter->isDefaultValueAvailable()) { - // For core classes, isDefaultValueAvailable() can - // be false when isOptional() returns true. If the - // argument *is* optional, allow it to be missing - if ($parameter->isOptional()) { - continue; - } - $type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, false); - $type = $type ? sprintf('is type-hinted "%s"', ltrim($type, '\\')) : 'has no type-hint'; - - throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" %s, you should configure its value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method, $type)); - } - - // specifically pass the default value - $arguments[$index] = $parameter->getDefaultValue(); - - continue; - } - - $getValue = function () use ($type, $parameter, $class, $method) { - if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $parameter->name))) { - $failureMessage = $this->createTypeNotFoundMessageCallback($ref, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method)); - - if ($parameter->isDefaultValueAvailable()) { - $value = $parameter->getDefaultValue(); - } elseif (!$parameter->allowsNull()) { - throw new AutowiringFailedException($this->currentId, $failureMessage); - } - } - - return $value; - }; - - if ($this->decoratedClass && $isDecorated = is_a($this->decoratedClass, $type, true)) { - if ($this->getPreviousValue) { - // The inner service is injected only if there is only 1 argument matching the type of the decorated class - // across all arguments of all autowired methods. - // If a second matching argument is found, the default behavior is restored. - - $getPreviousValue = $this->getPreviousValue; - $this->methodCalls[$this->decoratedMethodIndex][1][$this->decoratedMethodArgumentIndex] = $getPreviousValue(); - $this->decoratedClass = null; // Prevent further checks - } else { - $arguments[$index] = new TypedReference($this->decoratedId, $this->decoratedClass); - $this->getPreviousValue = $getValue; - $this->decoratedMethodArgumentIndex = $index; - - continue; - } - } - - $arguments[$index] = $getValue(); - } - - if ($parameters && !isset($arguments[++$index])) { - while (0 <= --$index) { - $parameter = $parameters[$index]; - if (!$parameter->isDefaultValueAvailable() || $parameter->getDefaultValue() !== $arguments[$index]) { - break; - } - unset($arguments[$index]); - } - } - - // it's possible index 1 was set, then index 0, then 2, etc - // make sure that we re-order so they're injected as expected - ksort($arguments); - - return $arguments; - } - - /** - * Returns a reference to the service matching the given type, if any. - */ - private function getAutowiredReference(TypedReference $reference): ?TypedReference - { - $this->lastFailure = null; - $type = $reference->getType(); - - if ($type !== (string) $reference) { - return $reference; - } - - if (null !== $name = $reference->getName()) { - if ($this->container->has($alias = $type.' $'.$name) && !$this->container->findDefinition($alias)->isAbstract()) { - return new TypedReference($alias, $type, $reference->getInvalidBehavior()); - } - - if ($this->container->has($name) && !$this->container->findDefinition($name)->isAbstract()) { - foreach ($this->container->getAliases() as $id => $alias) { - if ($name === (string) $alias && 0 === strpos($id, $type.' $')) { - return new TypedReference($name, $type, $reference->getInvalidBehavior()); - } - } - } - } - - if ($this->container->has($type) && !$this->container->findDefinition($type)->isAbstract()) { - return new TypedReference($type, $type, $reference->getInvalidBehavior()); - } - - return null; - } - - /** - * Populates the list of available types. - */ - private function populateAvailableTypes(ContainerBuilder $container) - { - $this->types = []; - $this->ambiguousServiceTypes = []; - - foreach ($container->getDefinitions() as $id => $definition) { - $this->populateAvailableType($container, $id, $definition); - } - } - - /** - * Populates the list of available types for a given definition. - */ - private function populateAvailableType(ContainerBuilder $container, string $id, Definition $definition) - { - // Never use abstract services - if ($definition->isAbstract()) { - return; - } - - if ('' === $id || '.' === $id[0] || $definition->isDeprecated() || !$reflectionClass = $container->getReflectionClass($definition->getClass(), false)) { - return; - } - - foreach ($reflectionClass->getInterfaces() as $reflectionInterface) { - $this->set($reflectionInterface->name, $id); - } - - do { - $this->set($reflectionClass->name, $id); - } while ($reflectionClass = $reflectionClass->getParentClass()); - } - - /** - * Associates a type and a service id if applicable. - */ - private function set(string $type, string $id) - { - // is this already a type/class that is known to match multiple services? - if (isset($this->ambiguousServiceTypes[$type])) { - $this->ambiguousServiceTypes[$type][] = $id; - - return; - } - - // check to make sure the type doesn't match multiple services - if (!isset($this->types[$type]) || $this->types[$type] === $id) { - $this->types[$type] = $id; - - return; - } - - // keep an array of all services matching this type - if (!isset($this->ambiguousServiceTypes[$type])) { - $this->ambiguousServiceTypes[$type] = [$this->types[$type]]; - unset($this->types[$type]); - } - $this->ambiguousServiceTypes[$type][] = $id; - } - - private function createTypeNotFoundMessageCallback(TypedReference $reference, string $label): callable - { - if (null === $this->typesClone->container) { - $this->typesClone->container = new ContainerBuilder($this->container->getParameterBag()); - $this->typesClone->container->setAliases($this->container->getAliases()); - $this->typesClone->container->setDefinitions($this->container->getDefinitions()); - $this->typesClone->container->setResourceTracking(false); - } - $currentId = $this->currentId; - - return (function () use ($reference, $label, $currentId) { - return $this->createTypeNotFoundMessage($reference, $label, $currentId); - })->bindTo($this->typesClone); - } - - private function createTypeNotFoundMessage(TypedReference $reference, string $label, string $currentId): string - { - if (!$r = $this->container->getReflectionClass($type = $reference->getType(), false)) { - // either $type does not exist or a parent class does not exist - try { - $resource = new ClassExistenceResource($type, false); - // isFresh() will explode ONLY if a parent class/trait does not exist - $resource->isFresh(0); - $parentMsg = false; - } catch (\ReflectionException $e) { - $parentMsg = $e->getMessage(); - } - - $message = sprintf('has type "%s" but this class %s.', $type, $parentMsg ? sprintf('is missing a parent class (%s)', $parentMsg) : 'was not found'); - } else { - $alternatives = $this->createTypeAlternatives($this->container, $reference); - $message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists'; - $message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $alternatives); - - if ($r->isInterface() && !$alternatives) { - $message .= ' Did you create a class that implements this interface?'; - } - } - - $message = sprintf('Cannot autowire service "%s": %s %s', $currentId, $label, $message); - - if (null !== $this->lastFailure) { - $message = $this->lastFailure."\n".$message; - $this->lastFailure = null; - } - - return $message; - } - - private function createTypeAlternatives(ContainerBuilder $container, TypedReference $reference): string - { - // try suggesting available aliases first - if ($message = $this->getAliasesSuggestionForType($container, $type = $reference->getType())) { - return ' '.$message; - } - if (null === $this->ambiguousServiceTypes) { - $this->populateAvailableTypes($container); - } - - $servicesAndAliases = $container->getServiceIds(); - if (!$container->has($type) && false !== $key = array_search(strtolower($type), array_map('strtolower', $servicesAndAliases))) { - return sprintf(' Did you mean "%s"?', $servicesAndAliases[$key]); - } elseif (isset($this->ambiguousServiceTypes[$type])) { - $message = sprintf('one of these existing services: "%s"', implode('", "', $this->ambiguousServiceTypes[$type])); - } elseif (isset($this->types[$type])) { - $message = sprintf('the existing "%s" service', $this->types[$type]); - } else { - return ''; - } - - return sprintf(' You should maybe alias this %s to %s.', class_exists($type, false) ? 'class' : 'interface', $message); - } - - private function getAliasesSuggestionForType(ContainerBuilder $container, string $type): ?string - { - $aliases = []; - foreach (class_parents($type) + class_implements($type) as $parent) { - if ($container->has($parent) && !$container->findDefinition($parent)->isAbstract()) { - $aliases[] = $parent; - } - } - - if (1 < $len = \count($aliases)) { - $message = 'Try changing the type-hint to one of its parents: '; - for ($i = 0, --$len; $i < $len; ++$i) { - $message .= sprintf('%s "%s", ', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]); - } - $message .= sprintf('or %s "%s".', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]); - - return $message; - } - - if ($aliases) { - return sprintf('Try changing the type-hint to "%s" instead.', $aliases[0]); - } - - return null; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php b/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php deleted file mode 100644 index c46d71f..0000000 --- a/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php +++ /dev/null @@ -1,84 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Definition; - -/** - * Looks for definitions with autowiring enabled and registers their corresponding "@required" methods as setters. - * - * @author Nicolas Grekas - */ -class AutowireRequiredMethodsPass extends AbstractRecursivePass -{ - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - $value = parent::processValue($value, $isRoot); - - if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) { - return $value; - } - if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) { - return $value; - } - - $alreadyCalledMethods = []; - $withers = []; - - foreach ($value->getMethodCalls() as list($method)) { - $alreadyCalledMethods[strtolower($method)] = true; - } - - foreach ($reflectionClass->getMethods() as $reflectionMethod) { - $r = $reflectionMethod; - - if ($r->isConstructor() || isset($alreadyCalledMethods[strtolower($r->name)])) { - continue; - } - - while (true) { - if (false !== $doc = $r->getDocComment()) { - if (false !== stripos($doc, '@required') && preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) { - if (preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@return\s++static[\s\*]#i', $doc)) { - $withers[] = [$reflectionMethod->name, [], true]; - } else { - $value->addMethodCall($reflectionMethod->name, []); - } - break; - } - if (false === stripos($doc, '@inheritdoc') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+(?:\{@inheritdoc\}|@inheritdoc)(?:\s|\*/$)#i', $doc)) { - break; - } - } - try { - $r = $r->getPrototype(); - } catch (\ReflectionException $e) { - break; // method has no prototype - } - } - } - - if ($withers) { - // Prepend withers to prevent creating circular loops - $setters = $value->getMethodCalls(); - $value->setMethodCalls($withers); - foreach ($setters as $call) { - $value->addMethodCall($call[0], $call[1], $call[2] ?? false); - } - } - - return $value; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php b/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php deleted file mode 100644 index 348498d..0000000 --- a/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * Checks if arguments of methods are properly configured. - * - * @author Kévin Dunglas - * @author Nicolas Grekas - */ -class CheckArgumentsValidityPass extends AbstractRecursivePass -{ - private $throwExceptions; - - public function __construct(bool $throwExceptions = true) - { - $this->throwExceptions = $throwExceptions; - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Definition) { - return parent::processValue($value, $isRoot); - } - - $i = 0; - foreach ($value->getArguments() as $k => $v) { - if ($k !== $i++) { - if (!\is_int($k)) { - $msg = sprintf('Invalid constructor argument for service "%s": integer expected but found string "%s". Check your service definition.', $this->currentId, $k); - $value->addError($msg); - if ($this->throwExceptions) { - throw new RuntimeException($msg); - } - - break; - } - - $msg = sprintf('Invalid constructor argument %d for service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $this->currentId, $i); - $value->addError($msg); - if ($this->throwExceptions) { - throw new RuntimeException($msg); - } - } - } - - foreach ($value->getMethodCalls() as $methodCall) { - $i = 0; - foreach ($methodCall[1] as $k => $v) { - if ($k !== $i++) { - if (!\is_int($k)) { - $msg = sprintf('Invalid argument for method call "%s" of service "%s": integer expected but found string "%s". Check your service definition.', $methodCall[0], $this->currentId, $k); - $value->addError($msg); - if ($this->throwExceptions) { - throw new RuntimeException($msg); - } - - break; - } - - $msg = sprintf('Invalid argument %d for method call "%s" of service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $methodCall[0], $this->currentId, $i); - $value->addError($msg); - if ($this->throwExceptions) { - throw new RuntimeException($msg); - } - } - } - } - - return null; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php b/vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php deleted file mode 100644 index 55d911c..0000000 --- a/vendor/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php +++ /dev/null @@ -1,78 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; - -/** - * Checks your services for circular references. - * - * References from method calls are ignored since we might be able to resolve - * these references depending on the order in which services are called. - * - * Circular reference from method calls will only be detected at run-time. - * - * @author Johannes M. Schmitt - */ -class CheckCircularReferencesPass implements CompilerPassInterface -{ - private $currentPath; - private $checkedNodes; - - /** - * Checks the ContainerBuilder object for circular references. - */ - public function process(ContainerBuilder $container) - { - $graph = $container->getCompiler()->getServiceReferenceGraph(); - - $this->checkedNodes = []; - foreach ($graph->getNodes() as $id => $node) { - $this->currentPath = [$id]; - - $this->checkOutEdges($node->getOutEdges()); - } - } - - /** - * Checks for circular references. - * - * @param ServiceReferenceGraphEdge[] $edges An array of Edges - * - * @throws ServiceCircularReferenceException when a circular reference is found - */ - private function checkOutEdges(array $edges) - { - foreach ($edges as $edge) { - $node = $edge->getDestNode(); - $id = $node->getId(); - - if (empty($this->checkedNodes[$id])) { - // Don't check circular references for lazy edges - if (!$node->getValue() || (!$edge->isLazy() && !$edge->isWeak())) { - $searchKey = array_search($id, $this->currentPath); - $this->currentPath[] = $id; - - if (false !== $searchKey) { - throw new ServiceCircularReferenceException($id, \array_slice($this->currentPath, $searchKey)); - } - - $this->checkOutEdges($node->getOutEdges()); - } - - $this->checkedNodes[$id] = true; - array_pop($this->currentPath); - } - } - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php b/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php deleted file mode 100644 index bb87f47..0000000 --- a/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php +++ /dev/null @@ -1,90 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\EnvParameterException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Loader\FileLoader; - -/** - * This pass validates each definition individually only taking the information - * into account which is contained in the definition itself. - * - * Later passes can rely on the following, and specifically do not need to - * perform these checks themselves: - * - * - non synthetic, non abstract services always have a class set - * - synthetic services are always public - * - * @author Johannes M. Schmitt - */ -class CheckDefinitionValidityPass implements CompilerPassInterface -{ - /** - * Processes the ContainerBuilder to validate the Definition. - * - * @throws RuntimeException When the Definition is invalid - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getDefinitions() as $id => $definition) { - // synthetic service is public - if ($definition->isSynthetic() && !$definition->isPublic()) { - throw new RuntimeException(sprintf('A synthetic service ("%s") must be public.', $id)); - } - - // non-synthetic, non-abstract service has class - if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass() && (!$definition->getFactory() || !preg_match(FileLoader::ANONYMOUS_ID_REGEXP, $id))) { - if ($definition->getFactory()) { - throw new RuntimeException(sprintf('Please add the class to service "%s" even if it is constructed by a factory since we might need to add method calls based on compile-time checks.', $id)); - } - if (class_exists($id) || interface_exists($id, false)) { - if (0 === strpos($id, '\\') && 1 < substr_count($id, '\\')) { - throw new RuntimeException(sprintf('The definition for "%s" has no class attribute, and appears to reference a class or interface. Please specify the class attribute explicitly or remove the leading backslash by renaming the service to "%s" to get rid of this error.', $id, substr($id, 1))); - } - - throw new RuntimeException(sprintf('The definition for "%s" has no class attribute, and appears to reference a class or interface in the global namespace. Leaving out the "class" attribute is only allowed for namespaced classes. Please specify the class attribute explicitly to get rid of this error.', $id)); - } - - throw new RuntimeException(sprintf('The definition for "%s" has no class. If you intend to inject this service dynamically at runtime, please mark it as synthetic=true. If this is an abstract definition solely used by child definitions, please add abstract=true, otherwise specify a class to get rid of this error.', $id)); - } - - // tag attribute values must be scalars - foreach ($definition->getTags() as $name => $tags) { - foreach ($tags as $attributes) { - foreach ($attributes as $attribute => $value) { - if (!is_scalar($value) && null !== $value) { - throw new RuntimeException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $id, $name, $attribute)); - } - } - } - } - - if ($definition->isPublic() && !$definition->isPrivate()) { - $resolvedId = $container->resolveEnvPlaceholders($id, null, $usedEnvs); - if (null !== $usedEnvs) { - throw new EnvParameterException([$resolvedId], null, 'A service name ("%s") cannot contain dynamic values.'); - } - } - } - - foreach ($container->getAliases() as $id => $alias) { - if ($alias->isPublic() && !$alias->isPrivate()) { - $resolvedId = $container->resolveEnvPlaceholders($id, null, $usedEnvs); - if (null !== $usedEnvs) { - throw new EnvParameterException([$resolvedId], null, 'An alias name ("%s") cannot contain dynamic values.'); - } - } - } - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php b/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php deleted file mode 100644 index 4ffe354..0000000 --- a/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php +++ /dev/null @@ -1,88 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Checks that all references are pointing to a valid service. - * - * @author Johannes M. Schmitt - */ -class CheckExceptionOnInvalidReferenceBehaviorPass extends AbstractRecursivePass -{ - private $serviceLocatorContextIds = []; - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $this->serviceLocatorContextIds = []; - foreach ($container->findTaggedServiceIds('container.service_locator_context') as $id => $tags) { - $this->serviceLocatorContextIds[$id] = $tags[0]['id']; - $container->getDefinition($id)->clearTag('container.service_locator_context'); - } - - try { - return parent::process($container); - } finally { - $this->serviceLocatorContextIds = []; - } - } - - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Reference) { - return parent::processValue($value, $isRoot); - } - if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $value->getInvalidBehavior() || $this->container->has($id = (string) $value)) { - return $value; - } - - $currentId = $this->currentId; - $graph = $this->container->getCompiler()->getServiceReferenceGraph(); - - if (isset($this->serviceLocatorContextIds[$currentId])) { - $currentId = $this->serviceLocatorContextIds[$currentId]; - $locator = $this->container->getDefinition($this->currentId)->getFactory()[0]; - - foreach ($locator->getArgument(0) as $k => $v) { - if ($v->getValues()[0] === $value) { - if ($k !== $id) { - $currentId = $k.'" in the container provided to "'.$currentId; - } - throw new ServiceNotFoundException($id, $currentId); - } - } - } - - if ('.' === $currentId[0] && $graph->hasNode($currentId)) { - foreach ($graph->getNode($currentId)->getInEdges() as $edge) { - if (!$edge->getValue() instanceof Reference || ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $edge->getValue()->getInvalidBehavior()) { - continue; - } - $sourceId = $edge->getSourceNode()->getId(); - - if ('.' !== $sourceId[0]) { - $currentId = $sourceId; - break; - } - } - } - - throw new ServiceNotFoundException($id, $currentId); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php b/vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php deleted file mode 100644 index 0349ef7..0000000 --- a/vendor/symfony/dependency-injection/Compiler/CheckReferenceValidityPass.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Checks the validity of references. - * - * The following checks are performed by this pass: - * - target definitions are not abstract - * - * @author Johannes M. Schmitt - */ -class CheckReferenceValidityPass extends AbstractRecursivePass -{ - protected function processValue($value, bool $isRoot = false) - { - if ($isRoot && $value instanceof Definition && ($value->isSynthetic() || $value->isAbstract())) { - return $value; - } - if ($value instanceof Reference && $this->container->hasDefinition((string) $value)) { - $targetDefinition = $this->container->getDefinition((string) $value); - - if ($targetDefinition->isAbstract()) { - throw new RuntimeException(sprintf('The definition "%s" has a reference to an abstract definition "%s". Abstract definitions cannot be the target of references.', $this->currentId, $value)); - } - } - - return parent::processValue($value, $isRoot); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php b/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php deleted file mode 100644 index 0743cbb..0000000 --- a/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php +++ /dev/null @@ -1,245 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\InvalidParameterTypeException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\ExpressionLanguage; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ServiceLocator; -use Symfony\Component\ExpressionLanguage\Expression; - -/** - * Checks whether injected parameters are compatible with type declarations. - * - * This pass should be run after all optimization passes. - * - * It can be added either: - * * before removing passes to check all services even if they are not currently used, - * * after removing passes to check only services are used in the app. - * - * @author Nicolas Grekas - * @author Julien Maulny - */ -final class CheckTypeDeclarationsPass extends AbstractRecursivePass -{ - private const SCALAR_TYPES = ['int', 'float', 'bool', 'string']; - - private $autoload; - private $skippedIds; - - private $expressionLanguage; - - /** - * @param bool $autoload Whether services who's class in not loaded should be checked or not. - * Defaults to false to save loading code during compilation. - * @param array $skippedIds An array indexed by the service ids to skip - */ - public function __construct(bool $autoload = false, array $skippedIds = []) - { - $this->autoload = $autoload; - $this->skippedIds = $skippedIds; - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, $isRoot = false) - { - if (isset($this->skippedIds[$this->currentId])) { - return $value; - } - - if (!$value instanceof Definition || $value->hasErrors()) { - return parent::processValue($value, $isRoot); - } - - if (!$this->autoload && !class_exists($class = $value->getClass(), false) && !interface_exists($class, false)) { - return parent::processValue($value, $isRoot); - } - - if (ServiceLocator::class === $value->getClass()) { - return parent::processValue($value, $isRoot); - } - - if ($constructor = $this->getConstructor($value, false)) { - $this->checkTypeDeclarations($value, $constructor, $value->getArguments()); - } - - foreach ($value->getMethodCalls() as $methodCall) { - try { - $reflectionMethod = $this->getReflectionMethod($value, $methodCall[0]); - } catch (RuntimeException $e) { - if ($value->getFactory()) { - continue; - } - - throw $e; - } - - $this->checkTypeDeclarations($value, $reflectionMethod, $methodCall[1]); - } - - return parent::processValue($value, $isRoot); - } - - /** - * @throws InvalidArgumentException When not enough parameters are defined for the method - */ - private function checkTypeDeclarations(Definition $checkedDefinition, \ReflectionFunctionAbstract $reflectionFunction, array $values): void - { - $numberOfRequiredParameters = $reflectionFunction->getNumberOfRequiredParameters(); - - if (\count($values) < $numberOfRequiredParameters) { - throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": "%s::%s()" requires %d arguments, %d passed.', $this->currentId, $reflectionFunction->class, $reflectionFunction->name, $numberOfRequiredParameters, \count($values))); - } - - $reflectionParameters = $reflectionFunction->getParameters(); - $checksCount = min($reflectionFunction->getNumberOfParameters(), \count($values)); - - $envPlaceholderUniquePrefix = $this->container->getParameterBag() instanceof EnvPlaceholderParameterBag ? $this->container->getParameterBag()->getEnvPlaceholderUniquePrefix() : null; - - for ($i = 0; $i < $checksCount; ++$i) { - if (!$reflectionParameters[$i]->hasType() || $reflectionParameters[$i]->isVariadic()) { - continue; - } - - $this->checkType($checkedDefinition, $values[$i], $reflectionParameters[$i], $envPlaceholderUniquePrefix); - } - - if ($reflectionFunction->isVariadic() && ($lastParameter = end($reflectionParameters))->hasType()) { - $variadicParameters = \array_slice($values, $lastParameter->getPosition()); - - foreach ($variadicParameters as $variadicParameter) { - $this->checkType($checkedDefinition, $variadicParameter, $lastParameter, $envPlaceholderUniquePrefix); - } - } - } - - /** - * @throws InvalidParameterTypeException When a parameter is not compatible with the declared type - */ - private function checkType(Definition $checkedDefinition, $value, \ReflectionParameter $parameter, ?string $envPlaceholderUniquePrefix): void - { - $type = $parameter->getType()->getName(); - - if ($value instanceof Reference) { - if (!$this->container->has($value = (string) $value)) { - return; - } - - if ('service_container' === $value && is_a($type, Container::class, true)) { - return; - } - - $value = $this->container->findDefinition($value); - } - - if ('self' === $type) { - $type = $parameter->getDeclaringClass()->getName(); - } - - if ('static' === $type) { - $type = $checkedDefinition->getClass(); - } - - if ($value instanceof Definition) { - $class = $value->getClass(); - - if (!$class || (!$this->autoload && !class_exists($class, false) && !interface_exists($class, false))) { - return; - } - - if ('callable' === $type && method_exists($class, '__invoke')) { - return; - } - - if ('iterable' === $type && is_subclass_of($class, 'Traversable')) { - return; - } - - if ('object' === $type) { - return; - } - - if (is_a($class, $type, true)) { - return; - } - - throw new InvalidParameterTypeException($this->currentId, $class, $parameter); - } - - if ($value instanceof Parameter) { - $value = $this->container->getParameter($value); - } elseif ($value instanceof Expression) { - $value = $this->getExpressionLanguage()->evaluate($value, ['container' => $this->container]); - } elseif (\is_string($value)) { - if ('%' === ($value[0] ?? '') && preg_match('/^%([^%]+)%$/', $value, $match)) { - // Only array parameters are not inlined when dumped. - $value = []; - } elseif ($envPlaceholderUniquePrefix && false !== strpos($value, 'env_')) { - // If the value is an env placeholder that is either mixed with a string or with another env placeholder, then its resolved value will always be a string, so we don't need to resolve it. - // We don't need to change the value because it is already a string. - if ('' === preg_replace('/'.$envPlaceholderUniquePrefix.'_\w+_[a-f0-9]{32}/U', '', $value, -1, $c) && 1 === $c) { - try { - $value = $this->container->resolveEnvPlaceholders($value, true); - } catch (EnvNotFoundException | RuntimeException $e) { - // If an env placeholder cannot be resolved, we skip the validation. - return; - } - } - } - } - - if (null === $value && $parameter->allowsNull()) { - return; - } - - if (\in_array($type, self::SCALAR_TYPES, true) && is_scalar($value)) { - return; - } - - if ('callable' === $type && \is_array($value) && isset($value[0]) && ($value[0] instanceof Reference || $value[0] instanceof Definition)) { - return; - } - - if ('iterable' === $type && (\is_array($value) || $value instanceof \Traversable || $value instanceof IteratorArgument)) { - return; - } - - if ('Traversable' === $type && ($value instanceof \Traversable || $value instanceof IteratorArgument)) { - return; - } - - $checkFunction = sprintf('is_%s', $parameter->getType()->getName()); - - if (!$parameter->getType()->isBuiltin() || !$checkFunction($value)) { - throw new InvalidParameterTypeException($this->currentId, \is_object($value) ? \get_class($value) : \gettype($value), $parameter); - } - } - - private function getExpressionLanguage(): ExpressionLanguage - { - if (null === $this->expressionLanguage) { - $this->expressionLanguage = new ExpressionLanguage(null, $this->container->getExpressionLanguageProviders()); - } - - return $this->expressionLanguage; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/Compiler.php b/vendor/symfony/dependency-injection/Compiler/Compiler.php deleted file mode 100644 index 04ae8d5..0000000 --- a/vendor/symfony/dependency-injection/Compiler/Compiler.php +++ /dev/null @@ -1,116 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\EnvParameterException; - -/** - * This class is used to remove circular dependencies between individual passes. - * - * @author Johannes M. Schmitt - */ -class Compiler -{ - private $passConfig; - private $log = []; - private $serviceReferenceGraph; - - public function __construct() - { - $this->passConfig = new PassConfig(); - $this->serviceReferenceGraph = new ServiceReferenceGraph(); - } - - /** - * Returns the PassConfig. - * - * @return PassConfig The PassConfig instance - */ - public function getPassConfig() - { - return $this->passConfig; - } - - /** - * Returns the ServiceReferenceGraph. - * - * @return ServiceReferenceGraph The ServiceReferenceGraph instance - */ - public function getServiceReferenceGraph() - { - return $this->serviceReferenceGraph; - } - - /** - * Adds a pass to the PassConfig. - */ - public function addPass(CompilerPassInterface $pass, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) - { - $this->passConfig->addPass($pass, $type, $priority); - } - - /** - * @final - */ - public function log(CompilerPassInterface $pass, string $message) - { - if (false !== strpos($message, "\n")) { - $message = str_replace("\n", "\n".\get_class($pass).': ', trim($message)); - } - - $this->log[] = \get_class($pass).': '.$message; - } - - /** - * Returns the log. - * - * @return array Log array - */ - public function getLog() - { - return $this->log; - } - - /** - * Run the Compiler and process all Passes. - */ - public function compile(ContainerBuilder $container) - { - try { - foreach ($this->passConfig->getPasses() as $pass) { - $pass->process($container); - } - } catch (\Exception $e) { - $usedEnvs = []; - $prev = $e; - - do { - $msg = $prev->getMessage(); - - if ($msg !== $resolvedMsg = $container->resolveEnvPlaceholders($msg, null, $usedEnvs)) { - $r = new \ReflectionProperty($prev, 'message'); - $r->setAccessible(true); - $r->setValue($prev, $resolvedMsg); - } - } while ($prev = $prev->getPrevious()); - - if ($usedEnvs) { - $e = new EnvParameterException($usedEnvs, $e); - } - - throw $e; - } finally { - $this->getServiceReferenceGraph()->clear(); - } - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/CompilerPassInterface.php b/vendor/symfony/dependency-injection/Compiler/CompilerPassInterface.php deleted file mode 100644 index 3085006..0000000 --- a/vendor/symfony/dependency-injection/Compiler/CompilerPassInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Interface that must be implemented by compilation passes. - * - * @author Johannes M. Schmitt - */ -interface CompilerPassInterface -{ - /** - * You can modify the container here before it is dumped to PHP code. - */ - public function process(ContainerBuilder $container); -} diff --git a/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php b/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php deleted file mode 100644 index da909ae..0000000 --- a/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php +++ /dev/null @@ -1,89 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Overwrites a service but keeps the overridden one. - * - * @author Christophe Coevoet - * @author Fabien Potencier - * @author Diego Saint Esteben - */ -class DecoratorServicePass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - $definitions = new \SplPriorityQueue(); - $order = PHP_INT_MAX; - - foreach ($container->getDefinitions() as $id => $definition) { - if (!$decorated = $definition->getDecoratedService()) { - continue; - } - $definitions->insert([$id, $definition], [$decorated[2], --$order]); - } - $decoratingDefinitions = []; - - foreach ($definitions as list($id, $definition)) { - $decoratedService = $definition->getDecoratedService(); - list($inner, $renamedId) = $decoratedService; - $invalidBehavior = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - - $definition->setDecoratedService(null); - - if (!$renamedId) { - $renamedId = $id.'.inner'; - } - $definition->innerServiceId = $renamedId; - $definition->decorationOnInvalid = $invalidBehavior; - - // we create a new alias/service for the service we are replacing - // to be able to reference it in the new one - if ($container->hasAlias($inner)) { - $alias = $container->getAlias($inner); - $public = $alias->isPublic(); - $private = $alias->isPrivate(); - $container->setAlias($renamedId, new Alias((string) $alias, false)); - } elseif ($container->hasDefinition($inner)) { - $decoratedDefinition = $container->getDefinition($inner); - $public = $decoratedDefinition->isPublic(); - $private = $decoratedDefinition->isPrivate(); - $decoratedDefinition->setPublic(false); - $container->setDefinition($renamedId, $decoratedDefinition); - $decoratingDefinitions[$inner] = $decoratedDefinition; - } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) { - $container->removeDefinition($id); - continue; - } elseif (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) { - $public = $definition->isPublic(); - $private = $definition->isPrivate(); - } else { - throw new ServiceNotFoundException($inner, $id); - } - - if (isset($decoratingDefinitions[$inner])) { - $decoratingDefinition = $decoratingDefinitions[$inner]; - $definition->setTags(array_merge($decoratingDefinition->getTags(), $definition->getTags())); - $decoratingDefinition->setTags([]); - $decoratingDefinitions[$inner] = $definition; - } - - $container->setAlias($inner, $id)->setPublic($public)->setPrivate($private); - } - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php b/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php deleted file mode 100644 index 5e7ba31..0000000 --- a/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Throws an exception for any Definitions that have errors and still exist. - * - * @author Ryan Weaver - */ -class DefinitionErrorExceptionPass extends AbstractRecursivePass -{ - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Definition || !$value->hasErrors()) { - return parent::processValue($value, $isRoot); - } - - if ($isRoot && !$value->isPublic()) { - $graph = $this->container->getCompiler()->getServiceReferenceGraph(); - $runtimeException = false; - foreach ($graph->getNode($this->currentId)->getInEdges() as $edge) { - if (!$edge->getValue() instanceof Reference || ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE !== $edge->getValue()->getInvalidBehavior()) { - $runtimeException = false; - break; - } - $runtimeException = true; - } - if ($runtimeException) { - return parent::processValue($value, $isRoot); - } - } - - // only show the first error so the user can focus on it - $errors = $value->getErrors(); - $message = reset($errors); - - throw new RuntimeException($message); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php b/vendor/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php deleted file mode 100644 index 27e5048..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ExtensionCompilerPass.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * A pass to automatically process extensions if they implement - * CompilerPassInterface. - * - * @author Wouter J - */ -class ExtensionCompilerPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getExtensions() as $extension) { - if (!$extension instanceof CompilerPassInterface) { - continue; - } - - $extension->process($container); - } - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php b/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php deleted file mode 100644 index 41af126..0000000 --- a/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php +++ /dev/null @@ -1,217 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Inline service definitions where this is possible. - * - * @author Johannes M. Schmitt - */ -class InlineServiceDefinitionsPass extends AbstractRecursivePass -{ - private $analyzingPass; - private $cloningIds = []; - private $connectedIds = []; - private $notInlinedIds = []; - private $inlinedIds = []; - private $graph; - - public function __construct(AnalyzeServiceReferencesPass $analyzingPass = null) - { - $this->analyzingPass = $analyzingPass; - } - - public function process(ContainerBuilder $container) - { - $this->container = $container; - if ($this->analyzingPass) { - $analyzedContainer = new ContainerBuilder(); - $analyzedContainer->setAliases($container->getAliases()); - $analyzedContainer->setDefinitions($container->getDefinitions()); - foreach ($container->getExpressionLanguageProviders() as $provider) { - $analyzedContainer->addExpressionLanguageProvider($provider); - } - } else { - $analyzedContainer = $container; - } - try { - $remainingInlinedIds = []; - $this->connectedIds = $this->notInlinedIds = $container->getDefinitions(); - do { - if ($this->analyzingPass) { - $analyzedContainer->setDefinitions(array_intersect_key($analyzedContainer->getDefinitions(), $this->connectedIds)); - $this->analyzingPass->process($analyzedContainer); - } - $this->graph = $analyzedContainer->getCompiler()->getServiceReferenceGraph(); - $notInlinedIds = $this->notInlinedIds; - $this->connectedIds = $this->notInlinedIds = $this->inlinedIds = []; - - foreach ($analyzedContainer->getDefinitions() as $id => $definition) { - if (!$this->graph->hasNode($id)) { - continue; - } - foreach ($this->graph->getNode($id)->getOutEdges() as $edge) { - if (isset($notInlinedIds[$edge->getSourceNode()->getId()])) { - $this->currentId = $id; - $this->processValue($definition, true); - break; - } - } - } - - foreach ($this->inlinedIds as $id => $isPublicOrNotShared) { - if ($isPublicOrNotShared) { - $remainingInlinedIds[$id] = $id; - } else { - $container->removeDefinition($id); - $analyzedContainer->removeDefinition($id); - } - } - } while ($this->inlinedIds && $this->analyzingPass); - - foreach ($remainingInlinedIds as $id) { - $definition = $container->getDefinition($id); - - if (!$definition->isShared() && !$definition->isPublic()) { - $container->removeDefinition($id); - } - } - } finally { - $this->container = null; - $this->connectedIds = $this->notInlinedIds = $this->inlinedIds = []; - $this->graph = null; - } - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof ArgumentInterface) { - // Reference found in ArgumentInterface::getValues() are not inlineable - return $value; - } - - if ($value instanceof Definition && $this->cloningIds) { - if ($value->isShared()) { - return $value; - } - $value = clone $value; - } - - if (!$value instanceof Reference) { - return parent::processValue($value, $isRoot); - } elseif (!$this->container->hasDefinition($id = (string) $value)) { - return $value; - } - - $definition = $this->container->getDefinition($id); - - if (!$this->isInlineableDefinition($id, $definition)) { - return $value; - } - - $this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId)); - $this->inlinedIds[$id] = $definition->isPublic() || !$definition->isShared(); - $this->notInlinedIds[$this->currentId] = true; - - if ($definition->isShared()) { - return $definition; - } - - if (isset($this->cloningIds[$id])) { - $ids = array_keys($this->cloningIds); - $ids[] = $id; - - throw new ServiceCircularReferenceException($id, \array_slice($ids, array_search($id, $ids))); - } - - $this->cloningIds[$id] = true; - try { - return $this->processValue($definition); - } finally { - unset($this->cloningIds[$id]); - } - } - - /** - * Checks if the definition is inlineable. - */ - private function isInlineableDefinition(string $id, Definition $definition): bool - { - if ($definition->hasErrors() || $definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic()) { - return false; - } - - if (!$definition->isShared()) { - if (!$this->graph->hasNode($id)) { - return true; - } - - foreach ($this->graph->getNode($id)->getInEdges() as $edge) { - $srcId = $edge->getSourceNode()->getId(); - $this->connectedIds[$srcId] = true; - if ($edge->isWeak() || $edge->isLazy()) { - return false; - } - } - - return true; - } - - if ($definition->isPublic()) { - return false; - } - - if (!$this->graph->hasNode($id)) { - return true; - } - - if ($this->currentId == $id) { - return false; - } - $this->connectedIds[$id] = true; - - $srcIds = []; - $srcCount = 0; - $isReferencedByConstructor = false; - foreach ($this->graph->getNode($id)->getInEdges() as $edge) { - $isReferencedByConstructor = $isReferencedByConstructor || $edge->isReferencedByConstructor(); - $srcId = $edge->getSourceNode()->getId(); - $this->connectedIds[$srcId] = true; - if ($edge->isWeak() || $edge->isLazy()) { - return false; - } - $srcIds[$srcId] = true; - ++$srcCount; - } - - if (1 !== \count($srcIds)) { - $this->notInlinedIds[$id] = true; - - return false; - } - - if ($srcCount > 1 && \is_array($factory = $definition->getFactory()) && ($factory[0] instanceof Reference || $factory[0] instanceof Definition)) { - return false; - } - - return $this->container->getDefinition($srcId)->isShared(); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php b/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php deleted file mode 100644 index bfeb7b8..0000000 --- a/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php +++ /dev/null @@ -1,220 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\Config\Definition\BaseNode; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; -use Symfony\Component\DependencyInjection\Extension\Extension; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; - -/** - * Merges extension configs into the container builder. - * - * @author Fabien Potencier - */ -class MergeExtensionConfigurationPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $parameters = $container->getParameterBag()->all(); - $definitions = $container->getDefinitions(); - $aliases = $container->getAliases(); - $exprLangProviders = $container->getExpressionLanguageProviders(); - $configAvailable = class_exists(BaseNode::class); - - foreach ($container->getExtensions() as $extension) { - if ($extension instanceof PrependExtensionInterface) { - $extension->prepend($container); - } - } - - foreach ($container->getExtensions() as $name => $extension) { - if (!$config = $container->getExtensionConfig($name)) { - // this extension was not called - continue; - } - $resolvingBag = $container->getParameterBag(); - if ($resolvingBag instanceof EnvPlaceholderParameterBag && $extension instanceof Extension) { - // create a dedicated bag so that we can track env vars per-extension - $resolvingBag = new MergeExtensionConfigurationParameterBag($resolvingBag); - if ($configAvailable) { - BaseNode::setPlaceholderUniquePrefix($resolvingBag->getEnvPlaceholderUniquePrefix()); - } - } - $config = $resolvingBag->resolveValue($config); - - try { - $tmpContainer = new MergeExtensionConfigurationContainerBuilder($extension, $resolvingBag); - $tmpContainer->setResourceTracking($container->isTrackingResources()); - $tmpContainer->addObjectResource($extension); - if ($extension instanceof ConfigurationExtensionInterface && null !== $configuration = $extension->getConfiguration($config, $tmpContainer)) { - $tmpContainer->addObjectResource($configuration); - } - - foreach ($exprLangProviders as $provider) { - $tmpContainer->addExpressionLanguageProvider($provider); - } - - $extension->load($config, $tmpContainer); - } catch (\Exception $e) { - if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) { - $container->getParameterBag()->mergeEnvPlaceholders($resolvingBag); - } - - throw $e; - } finally { - if ($configAvailable) { - BaseNode::resetPlaceholders(); - } - } - - if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) { - // don't keep track of env vars that are *overridden* when configs are merged - $resolvingBag->freezeAfterProcessing($extension, $tmpContainer); - } - - $container->merge($tmpContainer); - $container->getParameterBag()->add($parameters); - } - - $container->addDefinitions($definitions); - $container->addAliases($aliases); - } -} - -/** - * @internal - */ -class MergeExtensionConfigurationParameterBag extends EnvPlaceholderParameterBag -{ - private $processedEnvPlaceholders; - - public function __construct(parent $parameterBag) - { - parent::__construct($parameterBag->all()); - $this->mergeEnvPlaceholders($parameterBag); - } - - public function freezeAfterProcessing(Extension $extension, ContainerBuilder $container) - { - if (!$config = $extension->getProcessedConfigs()) { - // Extension::processConfiguration() wasn't called, we cannot know how configs were merged - return; - } - $this->processedEnvPlaceholders = []; - - // serialize config and container to catch env vars nested in object graphs - $config = serialize($config).serialize($container->getDefinitions()).serialize($container->getAliases()).serialize($container->getParameterBag()->all()); - - foreach (parent::getEnvPlaceholders() as $env => $placeholders) { - foreach ($placeholders as $placeholder) { - if (false !== stripos($config, $placeholder)) { - $this->processedEnvPlaceholders[$env] = $placeholders; - break; - } - } - } - } - - /** - * {@inheritdoc} - */ - public function getEnvPlaceholders(): array - { - return null !== $this->processedEnvPlaceholders ? $this->processedEnvPlaceholders : parent::getEnvPlaceholders(); - } - - public function getUnusedEnvPlaceholders(): array - { - return null === $this->processedEnvPlaceholders ? [] : array_diff_key(parent::getEnvPlaceholders(), $this->processedEnvPlaceholders); - } -} - -/** - * A container builder preventing using methods that wouldn't have any effect from extensions. - * - * @internal - */ -class MergeExtensionConfigurationContainerBuilder extends ContainerBuilder -{ - private $extensionClass; - - public function __construct(ExtensionInterface $extension, ParameterBagInterface $parameterBag = null) - { - parent::__construct($parameterBag); - - $this->extensionClass = \get_class($extension); - } - - /** - * {@inheritdoc} - */ - public function addCompilerPass(CompilerPassInterface $pass, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0): self - { - throw new LogicException(sprintf('You cannot add compiler pass "%s" from extension "%s". Compiler passes must be registered before the container is compiled.', \get_class($pass), $this->extensionClass)); - } - - /** - * {@inheritdoc} - */ - public function registerExtension(ExtensionInterface $extension) - { - throw new LogicException(sprintf('You cannot register extension "%s" from "%s". Extensions must be registered before the container is compiled.', \get_class($extension), $this->extensionClass)); - } - - /** - * {@inheritdoc} - */ - public function compile(bool $resolveEnvPlaceholders = false) - { - throw new LogicException(sprintf('Cannot compile the container in extension "%s".', $this->extensionClass)); - } - - /** - * {@inheritdoc} - */ - public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs = null) - { - if (true !== $format || !\is_string($value)) { - return parent::resolveEnvPlaceholders($value, $format, $usedEnvs); - } - - $bag = $this->getParameterBag(); - $value = $bag->resolveValue($value); - - if (!$bag instanceof EnvPlaceholderParameterBag) { - return parent::resolveEnvPlaceholders($value, $format, $usedEnvs); - } - - foreach ($bag->getEnvPlaceholders() as $env => $placeholders) { - if (false === strpos($env, ':')) { - continue; - } - foreach ($placeholders as $placeholder) { - if (false !== stripos($value, $placeholder)) { - throw new RuntimeException(sprintf('Using a cast in "env(%s)" is incompatible with resolution at compile time in "%s". The logic in the extension should be moved to a compiler pass, or an env parameter with no cast should be used instead.', $env, $this->extensionClass)); - } - } - } - - return parent::resolveEnvPlaceholders($value, $format, $usedEnvs); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/PassConfig.php b/vendor/symfony/dependency-injection/Compiler/PassConfig.php deleted file mode 100644 index 8df9f0e..0000000 --- a/vendor/symfony/dependency-injection/Compiler/PassConfig.php +++ /dev/null @@ -1,266 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * Compiler Pass Configuration. - * - * This class has a default configuration embedded. - * - * @author Johannes M. Schmitt - */ -class PassConfig -{ - const TYPE_AFTER_REMOVING = 'afterRemoving'; - const TYPE_BEFORE_OPTIMIZATION = 'beforeOptimization'; - const TYPE_BEFORE_REMOVING = 'beforeRemoving'; - const TYPE_OPTIMIZE = 'optimization'; - const TYPE_REMOVE = 'removing'; - - private $mergePass; - private $afterRemovingPasses = []; - private $beforeOptimizationPasses = []; - private $beforeRemovingPasses = []; - private $optimizationPasses; - private $removingPasses; - - public function __construct() - { - $this->mergePass = new MergeExtensionConfigurationPass(); - - $this->beforeOptimizationPasses = [ - 100 => [ - new ResolveClassPass(), - new ResolveInstanceofConditionalsPass(), - new RegisterEnvVarProcessorsPass(), - ], - -1000 => [new ExtensionCompilerPass()], - ]; - - $this->optimizationPasses = [[ - new ValidateEnvPlaceholdersPass(), - new ResolveChildDefinitionsPass(), - new RegisterServiceSubscribersPass(), - new ResolveParameterPlaceHoldersPass(false), - new ResolveFactoryClassPass(), - new ResolveNamedArgumentsPass(), - new AutowireRequiredMethodsPass(), - new ResolveBindingsPass(), - new ServiceLocatorTagPass(), - new DecoratorServicePass(), - new CheckDefinitionValidityPass(), - new AutowirePass(false), - new ResolveTaggedIteratorArgumentPass(), - new ResolveServiceSubscribersPass(), - new ResolveReferencesToAliasesPass(), - new ResolveInvalidReferencesPass(), - new AnalyzeServiceReferencesPass(true), - new CheckCircularReferencesPass(), - new CheckReferenceValidityPass(), - new CheckArgumentsValidityPass(false), - ]]; - - $this->beforeRemovingPasses = [ - -100 => [ - new ResolvePrivatesPass(), - ], - ]; - - $this->removingPasses = [[ - new RemovePrivateAliasesPass(), - new ReplaceAliasByActualDefinitionPass(), - new RemoveAbstractDefinitionsPass(), - new RemoveUnusedDefinitionsPass(), - new InlineServiceDefinitionsPass(new AnalyzeServiceReferencesPass()), - new AnalyzeServiceReferencesPass(), - new DefinitionErrorExceptionPass(), - ]]; - - $this->afterRemovingPasses = [[ - new CheckExceptionOnInvalidReferenceBehaviorPass(), - new ResolveHotPathPass(), - ]]; - } - - /** - * Returns all passes in order to be processed. - * - * @return CompilerPassInterface[] - */ - public function getPasses() - { - return array_merge( - [$this->mergePass], - $this->getBeforeOptimizationPasses(), - $this->getOptimizationPasses(), - $this->getBeforeRemovingPasses(), - $this->getRemovingPasses(), - $this->getAfterRemovingPasses() - ); - } - - /** - * Adds a pass. - * - * @throws InvalidArgumentException when a pass type doesn't exist - */ - public function addPass(CompilerPassInterface $pass, string $type = self::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) - { - $property = $type.'Passes'; - if (!isset($this->$property)) { - throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type)); - } - - $passes = &$this->$property; - - if (!isset($passes[$priority])) { - $passes[$priority] = []; - } - $passes[$priority][] = $pass; - } - - /** - * Gets all passes for the AfterRemoving pass. - * - * @return CompilerPassInterface[] - */ - public function getAfterRemovingPasses() - { - return $this->sortPasses($this->afterRemovingPasses); - } - - /** - * Gets all passes for the BeforeOptimization pass. - * - * @return CompilerPassInterface[] - */ - public function getBeforeOptimizationPasses() - { - return $this->sortPasses($this->beforeOptimizationPasses); - } - - /** - * Gets all passes for the BeforeRemoving pass. - * - * @return CompilerPassInterface[] - */ - public function getBeforeRemovingPasses() - { - return $this->sortPasses($this->beforeRemovingPasses); - } - - /** - * Gets all passes for the Optimization pass. - * - * @return CompilerPassInterface[] - */ - public function getOptimizationPasses() - { - return $this->sortPasses($this->optimizationPasses); - } - - /** - * Gets all passes for the Removing pass. - * - * @return CompilerPassInterface[] - */ - public function getRemovingPasses() - { - return $this->sortPasses($this->removingPasses); - } - - /** - * Gets the Merge pass. - * - * @return CompilerPassInterface - */ - public function getMergePass() - { - return $this->mergePass; - } - - public function setMergePass(CompilerPassInterface $pass) - { - $this->mergePass = $pass; - } - - /** - * Sets the AfterRemoving passes. - * - * @param CompilerPassInterface[] $passes - */ - public function setAfterRemovingPasses(array $passes) - { - $this->afterRemovingPasses = [$passes]; - } - - /** - * Sets the BeforeOptimization passes. - * - * @param CompilerPassInterface[] $passes - */ - public function setBeforeOptimizationPasses(array $passes) - { - $this->beforeOptimizationPasses = [$passes]; - } - - /** - * Sets the BeforeRemoving passes. - * - * @param CompilerPassInterface[] $passes - */ - public function setBeforeRemovingPasses(array $passes) - { - $this->beforeRemovingPasses = [$passes]; - } - - /** - * Sets the Optimization passes. - * - * @param CompilerPassInterface[] $passes - */ - public function setOptimizationPasses(array $passes) - { - $this->optimizationPasses = [$passes]; - } - - /** - * Sets the Removing passes. - * - * @param CompilerPassInterface[] $passes - */ - public function setRemovingPasses(array $passes) - { - $this->removingPasses = [$passes]; - } - - /** - * Sort passes by priority. - * - * @param array $passes CompilerPassInterface instances with their priority as key - * - * @return CompilerPassInterface[] - */ - private function sortPasses(array $passes): array - { - if (0 === \count($passes)) { - return []; - } - - krsort($passes); - - // Flatten the array - return array_merge(...$passes); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php b/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php deleted file mode 100644 index 9b3760b..0000000 --- a/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php +++ /dev/null @@ -1,138 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\TypedReference; - -/** - * Trait that allows a generic method to find and sort service by priority option in the tag. - * - * @author Iltar van der Berg - */ -trait PriorityTaggedServiceTrait -{ - /** - * Finds all services with the given tag name and order them by their priority. - * - * The order of additions must be respected for services having the same priority, - * and knowing that the \SplPriorityQueue class does not respect the FIFO method, - * we should not use that class. - * - * @see https://bugs.php.net/53710 - * @see https://bugs.php.net/60926 - * - * @param string|TaggedIteratorArgument $tagName - * - * @return Reference[] - */ - private function findAndSortTaggedServices($tagName, ContainerBuilder $container): array - { - $indexAttribute = $defaultIndexMethod = $needsIndexes = $defaultPriorityMethod = null; - - if ($tagName instanceof TaggedIteratorArgument) { - $indexAttribute = $tagName->getIndexAttribute(); - $defaultIndexMethod = $tagName->getDefaultIndexMethod(); - $needsIndexes = $tagName->needsIndexes(); - $defaultPriorityMethod = $tagName->getDefaultPriorityMethod(); - $tagName = $tagName->getTag(); - } - - $services = []; - - foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) { - $class = $r = null; - $priority = 0; - if (isset($attributes[0]['priority'])) { - $priority = $attributes[0]['priority']; - } elseif ($defaultPriorityMethod) { - $class = $container->getDefinition($serviceId)->getClass(); - $class = $container->getParameterBag()->resolveValue($class) ?: null; - - if (($r = $container->getReflectionClass($class)) && $r->hasMethod($defaultPriorityMethod)) { - if (!($rm = $r->getMethod($defaultPriorityMethod))->isStatic()) { - throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId)); - } - - if (!$rm->isPublic()) { - throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId)); - } - - $priority = $rm->invoke(null); - - if (!\is_int($priority)) { - throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return an integer, got %s: tag "%s" on service "%s".', $class, $defaultPriorityMethod, \gettype($priority), $tagName, $serviceId)); - } - } - } - - if (null === $indexAttribute && !$needsIndexes) { - $services[$priority][] = new Reference($serviceId); - - continue; - } - - if (!$class) { - $class = $container->getDefinition($serviceId)->getClass(); - $class = $container->getParameterBag()->resolveValue($class) ?: null; - } - - if (null !== $indexAttribute && isset($attributes[0][$indexAttribute])) { - $services[$priority][$attributes[0][$indexAttribute]] = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $attributes[0][$indexAttribute]); - - continue; - } - - if (!$r && !$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $serviceId)); - } - - $class = $r->name; - - if (!$r->hasMethod($defaultIndexMethod)) { - if ($needsIndexes) { - $services[$priority][$serviceId] = new TypedReference($serviceId, $class); - - continue; - } - - throw new InvalidArgumentException(sprintf('Method "%s::%s()" not found: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute)); - } - - if (!($rm = $r->getMethod($defaultIndexMethod))->isStatic()) { - throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute)); - } - - if (!$rm->isPublic()) { - throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute)); - } - - $key = $rm->invoke(null); - - if (!\is_string($key)) { - throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return a string, got %s: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, \gettype($key), $tagName, $serviceId, $indexAttribute)); - } - - $services[$priority][$key] = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $key); - } - - if ($services) { - krsort($services); - $services = array_merge(...$services); - } - - return $services; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php b/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php deleted file mode 100644 index a9a133b..0000000 --- a/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php +++ /dev/null @@ -1,75 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\EnvVarProcessor; -use Symfony\Component\DependencyInjection\EnvVarProcessorInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Creates the container.env_var_processors_locator service. - * - * @author Nicolas Grekas - */ -class RegisterEnvVarProcessorsPass implements CompilerPassInterface -{ - private static $allowedTypes = ['array', 'bool', 'float', 'int', 'string']; - - public function process(ContainerBuilder $container) - { - $bag = $container->getParameterBag(); - $types = []; - $processors = []; - foreach ($container->findTaggedServiceIds('container.env_var_processor') as $id => $tags) { - if (!$r = $container->getReflectionClass($class = $container->getDefinition($id)->getClass())) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } elseif (!$r->isSubclassOf(EnvVarProcessorInterface::class)) { - throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EnvVarProcessorInterface::class)); - } - foreach ($class::getProvidedTypes() as $prefix => $type) { - $processors[$prefix] = new Reference($id); - $types[$prefix] = self::validateProvidedTypes($type, $class); - } - } - - if ($bag instanceof EnvPlaceholderParameterBag) { - foreach (EnvVarProcessor::getProvidedTypes() as $prefix => $type) { - if (!isset($types[$prefix])) { - $types[$prefix] = self::validateProvidedTypes($type, EnvVarProcessor::class); - } - } - $bag->setProvidedTypes($types); - } - - if ($processors) { - $container->setAlias('container.env_var_processors_locator', (string) ServiceLocatorTagPass::register($container, $processors)) - ->setPublic(true) - ; - } - } - - private static function validateProvidedTypes(string $types, string $class): array - { - $types = explode('|', $types); - - foreach ($types as $type) { - if (!\in_array($type, self::$allowedTypes)) { - throw new InvalidArgumentException(sprintf('Invalid type "%s" returned by "%s::getProvidedTypes()", expected one of "%s".', $type, $class, implode('", "', self::$allowedTypes))); - } - } - - return $types; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php b/vendor/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php deleted file mode 100644 index 571eab3..0000000 --- a/vendor/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php +++ /dev/null @@ -1,66 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Nicolas Grekas - */ -class RegisterReverseContainerPass implements CompilerPassInterface -{ - private $beforeRemoving; - private $serviceId; - private $tagName; - - public function __construct(bool $beforeRemoving, string $serviceId = 'reverse_container', string $tagName = 'container.reversible') - { - $this->beforeRemoving = $beforeRemoving; - $this->serviceId = $serviceId; - $this->tagName = $tagName; - } - - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->serviceId)) { - return; - } - - $refType = $this->beforeRemoving ? ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE : ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - $services = []; - foreach ($container->findTaggedServiceIds($this->tagName) as $id => $tags) { - $services[$id] = new Reference($id, $refType); - } - - if ($this->beforeRemoving) { - // prevent inlining of the reverse container - $services[$this->serviceId] = new Reference($this->serviceId, $refType); - } - $locator = $container->getDefinition($this->serviceId)->getArgument(1); - - if ($locator instanceof Reference) { - $locator = $container->getDefinition((string) $locator); - } - if ($locator instanceof Definition) { - foreach ($services as $id => $ref) { - $services[$id] = new ServiceClosureArgument($ref); - } - $locator->replaceArgument(0, $services); - } else { - $locator->setValues($services); - } - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php b/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php deleted file mode 100644 index 7d9c366..0000000 --- a/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Psr\Container\ContainerInterface as PsrContainerInterface; -use Symfony\Component\DependencyInjection\Argument\BoundArgument; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\TypedReference; -use Symfony\Contracts\Service\ServiceProviderInterface; -use Symfony\Contracts\Service\ServiceSubscriberInterface; - -/** - * Compiler pass to register tagged services that require a service locator. - * - * @author Nicolas Grekas - */ -class RegisterServiceSubscribersPass extends AbstractRecursivePass -{ - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Definition || $value->isAbstract() || $value->isSynthetic() || !$value->hasTag('container.service_subscriber')) { - return parent::processValue($value, $isRoot); - } - - $serviceMap = []; - $autowire = $value->isAutowired(); - - foreach ($value->getTag('container.service_subscriber') as $attributes) { - if (!$attributes) { - $autowire = true; - continue; - } - ksort($attributes); - if ([] !== array_diff(array_keys($attributes), ['id', 'key'])) { - throw new InvalidArgumentException(sprintf('The "container.service_subscriber" tag accepts only the "key" and "id" attributes, "%s" given for service "%s".', implode('", "', array_keys($attributes)), $this->currentId)); - } - if (!\array_key_exists('id', $attributes)) { - throw new InvalidArgumentException(sprintf('Missing "id" attribute on "container.service_subscriber" tag with key="%s" for service "%s".', $attributes['key'], $this->currentId)); - } - if (!\array_key_exists('key', $attributes)) { - $attributes['key'] = $attributes['id']; - } - if (isset($serviceMap[$attributes['key']])) { - continue; - } - $serviceMap[$attributes['key']] = new Reference($attributes['id']); - } - $class = $value->getClass(); - - if (!$r = $this->container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $this->currentId)); - } - if (!$r->isSubclassOf(ServiceSubscriberInterface::class)) { - throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $this->currentId, ServiceSubscriberInterface::class)); - } - $class = $r->name; - - $subscriberMap = []; - - foreach ($class::getSubscribedServices() as $key => $type) { - if (!\is_string($type) || !preg_match('/^\??[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $type)) { - throw new InvalidArgumentException(sprintf('"%s::getSubscribedServices()" must return valid PHP types for service "%s" key "%s", "%s" returned.', $class, $this->currentId, $key, \is_string($type) ? $type : \gettype($type))); - } - if ($optionalBehavior = '?' === $type[0]) { - $type = substr($type, 1); - $optionalBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - } - if (\is_int($name = $key)) { - $key = $type; - $name = null; - } - if (!isset($serviceMap[$key])) { - if (!$autowire) { - throw new InvalidArgumentException(sprintf('Service "%s" misses a "container.service_subscriber" tag with "key"/"id" attributes corresponding to entry "%s" as returned by "%s::getSubscribedServices()".', $this->currentId, $key, $class)); - } - $serviceMap[$key] = new Reference($type); - } - - if (false !== $i = strpos($name, '::get')) { - $name = lcfirst(substr($name, 5 + $i)); - } elseif (false !== strpos($name, '::')) { - $name = null; - } - - if (null !== $name && !$this->container->has($name) && !$this->container->has($type.' $'.$name)) { - $camelCaseName = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $name)))); - $name = $this->container->has($type.' $'.$camelCaseName) ? $camelCaseName : $name; - } - - $subscriberMap[$key] = new TypedReference((string) $serviceMap[$key], $type, $optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $name); - unset($serviceMap[$key]); - } - - if ($serviceMap = array_keys($serviceMap)) { - $message = sprintf(1 < \count($serviceMap) ? 'keys "%s" do' : 'key "%s" does', str_replace('%', '%%', implode('", "', $serviceMap))); - throw new InvalidArgumentException(sprintf('Service %s not exist in the map returned by "%s::getSubscribedServices()" for service "%s".', $message, $class, $this->currentId)); - } - - $locatorRef = ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId); - - $value->addTag('container.service_subscriber.locator', ['id' => (string) $locatorRef]); - - $value->setBindings([ - PsrContainerInterface::class => new BoundArgument($locatorRef, false), - ServiceProviderInterface::class => new BoundArgument($locatorRef, false), - ] + $value->getBindings()); - - return parent::processValue($value); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php b/vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php deleted file mode 100644 index 04b6852..0000000 --- a/vendor/symfony/dependency-injection/Compiler/RemoveAbstractDefinitionsPass.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Removes abstract Definitions. - */ -class RemoveAbstractDefinitionsPass implements CompilerPassInterface -{ - /** - * Removes abstract definitions from the ContainerBuilder. - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getDefinitions() as $id => $definition) { - if ($definition->isAbstract()) { - $container->removeDefinition($id); - $container->log($this, sprintf('Removed service "%s"; reason: abstract.', $id)); - } - } - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php b/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php deleted file mode 100644 index 75b36d2..0000000 --- a/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Remove private aliases from the container. They were only used to establish - * dependencies between services, and these dependencies have been resolved in - * one of the previous passes. - * - * @author Johannes M. Schmitt - */ -class RemovePrivateAliasesPass implements CompilerPassInterface -{ - /** - * Removes private aliases from the ContainerBuilder. - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getAliases() as $id => $alias) { - if ($alias->isPublic()) { - continue; - } - - $container->removeAlias($id); - $container->log($this, sprintf('Removed service "%s"; reason: private alias.', $id)); - } - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php b/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php deleted file mode 100644 index cf1a3dd..0000000 --- a/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php +++ /dev/null @@ -1,90 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Removes unused service definitions from the container. - * - * @author Johannes M. Schmitt - * @author Nicolas Grekas - */ -class RemoveUnusedDefinitionsPass extends AbstractRecursivePass -{ - private $connectedIds = []; - - /** - * Processes the ContainerBuilder to remove unused definitions. - */ - public function process(ContainerBuilder $container) - { - try { - $this->enableExpressionProcessing(); - $this->container = $container; - $connectedIds = []; - $aliases = $container->getAliases(); - - foreach ($aliases as $id => $alias) { - if ($alias->isPublic()) { - $this->connectedIds[] = (string) $aliases[$id]; - } - } - - foreach ($container->getDefinitions() as $id => $definition) { - if ($definition->isPublic()) { - $connectedIds[$id] = true; - $this->processValue($definition); - } - } - - while ($this->connectedIds) { - $ids = $this->connectedIds; - $this->connectedIds = []; - foreach ($ids as $id) { - if (!isset($connectedIds[$id]) && $container->hasDefinition($id)) { - $connectedIds[$id] = true; - $this->processValue($container->getDefinition($id)); - } - } - } - - foreach ($container->getDefinitions() as $id => $definition) { - if (!isset($connectedIds[$id])) { - $container->removeDefinition($id); - $container->resolveEnvPlaceholders(!$definition->hasErrors() ? serialize($definition) : $definition); - $container->log($this, sprintf('Removed service "%s"; reason: unused.', $id)); - } - } - } finally { - $this->container = null; - $this->connectedIds = []; - } - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Reference) { - return parent::processValue($value, $isRoot); - } - - if (ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior()) { - $this->connectedIds[] = (string) $value; - } - - return $value; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php b/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php deleted file mode 100644 index ca781f2..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php +++ /dev/null @@ -1,94 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Replaces aliases with actual service definitions, effectively removing these - * aliases. - * - * @author Johannes M. Schmitt - */ -class ReplaceAliasByActualDefinitionPass extends AbstractRecursivePass -{ - private $replacements; - - /** - * Process the Container to replace aliases with service definitions. - * - * @throws InvalidArgumentException if the service definition does not exist - */ - public function process(ContainerBuilder $container) - { - // First collect all alias targets that need to be replaced - $seenAliasTargets = []; - $replacements = []; - foreach ($container->getAliases() as $definitionId => $target) { - $targetId = (string) $target; - // Special case: leave this target alone - if ('service_container' === $targetId) { - continue; - } - // Check if target needs to be replaces - if (isset($replacements[$targetId])) { - $container->setAlias($definitionId, $replacements[$targetId])->setPublic($target->isPublic())->setPrivate($target->isPrivate()); - } - // No need to process the same target twice - if (isset($seenAliasTargets[$targetId])) { - continue; - } - // Process new target - $seenAliasTargets[$targetId] = true; - try { - $definition = $container->getDefinition($targetId); - } catch (ServiceNotFoundException $e) { - if ('' !== $e->getId() && '@' === $e->getId()[0]) { - throw new ServiceNotFoundException($e->getId(), $e->getSourceId(), null, [substr($e->getId(), 1)]); - } - - throw $e; - } - if ($definition->isPublic()) { - continue; - } - // Remove private definition and schedule for replacement - $definition->setPublic(!$target->isPrivate()); - $definition->setPrivate($target->isPrivate()); - $container->setDefinition($definitionId, $definition); - $container->removeDefinition($targetId); - $replacements[$targetId] = $definitionId; - } - $this->replacements = $replacements; - - parent::process($container); - $this->replacements = []; - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof Reference && isset($this->replacements[$referenceId = (string) $value])) { - // Perform the replacement - $newId = $this->replacements[$referenceId]; - $value = new Reference($newId, $value->getInvalidBehavior()); - $this->container->log($this, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $this->currentId, $referenceId, $newId)); - } - - return parent::processValue($value, $isRoot); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php deleted file mode 100644 index 77eff72..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php +++ /dev/null @@ -1,227 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\BoundArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\TypedReference; - -/** - * @author Guilhem Niot - */ -class ResolveBindingsPass extends AbstractRecursivePass -{ - private $usedBindings = []; - private $unusedBindings = []; - private $errorMessages = []; - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $this->usedBindings = $container->getRemovedBindingIds(); - - try { - parent::process($container); - - foreach ($this->unusedBindings as list($key, $serviceId, $bindingType, $file)) { - $argumentType = $argumentName = $message = null; - - if (false !== strpos($key, ' ')) { - list($argumentType, $argumentName) = explode(' ', $key, 2); - } elseif ('$' === $key[0]) { - $argumentName = $key; - } else { - $argumentType = $key; - } - - if ($argumentType) { - $message .= sprintf('of type "%s" ', $argumentType); - } - - if ($argumentName) { - $message .= sprintf('named "%s" ', $argumentName); - } - - if (BoundArgument::DEFAULTS_BINDING === $bindingType) { - $message .= 'under "_defaults"'; - } elseif (BoundArgument::INSTANCEOF_BINDING === $bindingType) { - $message .= 'under "_instanceof"'; - } else { - $message .= sprintf('for service "%s"', $serviceId); - } - - if ($file) { - $message .= sprintf(' in file "%s"', $file); - } - - $message = sprintf('A binding is configured for an argument %s, but no corresponding argument has been found. It may be unused and should be removed, or it may have a typo.', $message); - - if ($this->errorMessages) { - $message .= sprintf("\nCould be related to%s:", 1 < \count($this->errorMessages) ? ' one of' : ''); - } - foreach ($this->errorMessages as $m) { - $message .= "\n - ".$m; - } - throw new InvalidArgumentException($message); - } - } finally { - $this->usedBindings = []; - $this->unusedBindings = []; - $this->errorMessages = []; - } - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof TypedReference && $value->getType() === (string) $value) { - // Already checked - $bindings = $this->container->getDefinition($this->currentId)->getBindings(); - $name = $value->getName(); - - if (isset($name, $bindings[$name = $value.' $'.$name])) { - return $this->getBindingValue($bindings[$name]); - } - - if (isset($bindings[$value->getType()])) { - return $this->getBindingValue($bindings[$value->getType()]); - } - - return parent::processValue($value, $isRoot); - } - - if (!$value instanceof Definition || !$bindings = $value->getBindings()) { - return parent::processValue($value, $isRoot); - } - - foreach ($bindings as $key => $binding) { - list($bindingValue, $bindingId, $used, $bindingType, $file) = $binding->getValues(); - if ($used) { - $this->usedBindings[$bindingId] = true; - unset($this->unusedBindings[$bindingId]); - } elseif (!isset($this->usedBindings[$bindingId])) { - $this->unusedBindings[$bindingId] = [$key, $this->currentId, $bindingType, $file]; - } - - if (preg_match('/^(?:(?:array|bool|float|int|string) )?\$/', $key)) { - continue; - } - - if (null !== $bindingValue && !$bindingValue instanceof Reference && !$bindingValue instanceof Definition && !$bindingValue instanceof TaggedIteratorArgument && !$bindingValue instanceof ServiceLocatorArgument) { - throw new InvalidArgumentException(sprintf('Invalid value for binding key "%s" for service "%s": expected null, %s, %s, %s or ServiceLocatorArgument, %s given.', $key, $this->currentId, Reference::class, Definition::class, TaggedIteratorArgument::class, \gettype($bindingValue))); - } - } - - if ($value->isAbstract()) { - return parent::processValue($value, $isRoot); - } - - $calls = $value->getMethodCalls(); - - try { - if ($constructor = $this->getConstructor($value, false)) { - $calls[] = [$constructor, $value->getArguments()]; - } - } catch (RuntimeException $e) { - $this->errorMessages[] = $e->getMessage(); - $this->container->getDefinition($this->currentId)->addError($e->getMessage()); - - return parent::processValue($value, $isRoot); - } - - foreach ($calls as $i => $call) { - list($method, $arguments) = $call; - - if ($method instanceof \ReflectionFunctionAbstract) { - $reflectionMethod = $method; - } else { - try { - $reflectionMethod = $this->getReflectionMethod($value, $method); - } catch (RuntimeException $e) { - if ($value->getFactory()) { - continue; - } - throw $e; - } - } - - foreach ($reflectionMethod->getParameters() as $key => $parameter) { - if (\array_key_exists($key, $arguments) && '' !== $arguments[$key]) { - continue; - } - - $typeHint = ProxyHelper::getTypeHint($reflectionMethod, $parameter); - - if (\array_key_exists($k = ltrim($typeHint, '\\').' $'.$parameter->name, $bindings)) { - $arguments[$key] = $this->getBindingValue($bindings[$k]); - - continue; - } - - if (\array_key_exists('$'.$parameter->name, $bindings)) { - $arguments[$key] = $this->getBindingValue($bindings['$'.$parameter->name]); - - continue; - } - - if (!$typeHint || '\\' !== $typeHint[0] || !isset($bindings[$typeHint = substr($typeHint, 1)])) { - continue; - } - - $arguments[$key] = $this->getBindingValue($bindings[$typeHint]); - } - - if ($arguments !== $call[1]) { - ksort($arguments); - $calls[$i][1] = $arguments; - } - } - - if ($constructor) { - list(, $arguments) = array_pop($calls); - - if ($arguments !== $value->getArguments()) { - $value->setArguments($arguments); - } - } - - if ($calls !== $value->getMethodCalls()) { - $value->setMethodCalls($calls); - } - - return parent::processValue($value, $isRoot); - } - - /** - * @return mixed - */ - private function getBindingValue(BoundArgument $binding) - { - list($bindingValue, $bindingId) = $binding->getValues(); - - $this->usedBindings[$bindingId] = true; - unset($this->unusedBindings[$bindingId]); - - return $bindingValue; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php deleted file mode 100644 index f180d22..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php +++ /dev/null @@ -1,190 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\ExceptionInterface; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; - -/** - * This replaces all ChildDefinition instances with their equivalent fully - * merged Definition instance. - * - * @author Johannes M. Schmitt - * @author Nicolas Grekas - */ -class ResolveChildDefinitionsPass extends AbstractRecursivePass -{ - private $currentPath; - - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Definition) { - return parent::processValue($value, $isRoot); - } - if ($isRoot) { - // yes, we are specifically fetching the definition from the - // container to ensure we are not operating on stale data - $value = $this->container->getDefinition($this->currentId); - } - if ($value instanceof ChildDefinition) { - $this->currentPath = []; - $value = $this->resolveDefinition($value); - if ($isRoot) { - $this->container->setDefinition($this->currentId, $value); - } - } - - return parent::processValue($value, $isRoot); - } - - /** - * Resolves the definition. - * - * @throws RuntimeException When the definition is invalid - */ - private function resolveDefinition(ChildDefinition $definition): Definition - { - try { - return $this->doResolveDefinition($definition); - } catch (ServiceCircularReferenceException $e) { - throw $e; - } catch (ExceptionInterface $e) { - $r = new \ReflectionProperty($e, 'message'); - $r->setAccessible(true); - $r->setValue($e, sprintf('Service "%s": %s', $this->currentId, $e->getMessage())); - - throw $e; - } - } - - private function doResolveDefinition(ChildDefinition $definition): Definition - { - if (!$this->container->has($parent = $definition->getParent())) { - throw new RuntimeException(sprintf('Parent definition "%s" does not exist.', $parent)); - } - - $searchKey = array_search($parent, $this->currentPath); - $this->currentPath[] = $parent; - - if (false !== $searchKey) { - throw new ServiceCircularReferenceException($parent, \array_slice($this->currentPath, $searchKey)); - } - - $parentDef = $this->container->findDefinition($parent); - if ($parentDef instanceof ChildDefinition) { - $id = $this->currentId; - $this->currentId = $parent; - $parentDef = $this->resolveDefinition($parentDef); - $this->container->setDefinition($parent, $parentDef); - $this->currentId = $id; - } - - $this->container->log($this, sprintf('Resolving inheritance for "%s" (parent: %s).', $this->currentId, $parent)); - $def = new Definition(); - - // merge in parent definition - // purposely ignored attributes: abstract, shared, tags, autoconfigured - $def->setClass($parentDef->getClass()); - $def->setArguments($parentDef->getArguments()); - $def->setMethodCalls($parentDef->getMethodCalls()); - $def->setProperties($parentDef->getProperties()); - if ($parentDef->isDeprecated()) { - $def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%')); - } - $def->setFactory($parentDef->getFactory()); - $def->setConfigurator($parentDef->getConfigurator()); - $def->setFile($parentDef->getFile()); - $def->setPublic($parentDef->isPublic()); - $def->setLazy($parentDef->isLazy()); - $def->setAutowired($parentDef->isAutowired()); - $def->setChanges($parentDef->getChanges()); - - $def->setBindings($definition->getBindings() + $parentDef->getBindings()); - - // overwrite with values specified in the decorator - $changes = $definition->getChanges(); - if (isset($changes['class'])) { - $def->setClass($definition->getClass()); - } - if (isset($changes['factory'])) { - $def->setFactory($definition->getFactory()); - } - if (isset($changes['configurator'])) { - $def->setConfigurator($definition->getConfigurator()); - } - if (isset($changes['file'])) { - $def->setFile($definition->getFile()); - } - if (isset($changes['public'])) { - $def->setPublic($definition->isPublic()); - } else { - $def->setPrivate($definition->isPrivate() || $parentDef->isPrivate()); - } - if (isset($changes['lazy'])) { - $def->setLazy($definition->isLazy()); - } - if (isset($changes['deprecated'])) { - $def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%')); - } - if (isset($changes['autowired'])) { - $def->setAutowired($definition->isAutowired()); - } - if (isset($changes['shared'])) { - $def->setShared($definition->isShared()); - } - if (isset($changes['decorated_service'])) { - $decoratedService = $definition->getDecoratedService(); - if (null === $decoratedService) { - $def->setDecoratedService($decoratedService); - } else { - $def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2], $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE); - } - } - - // merge arguments - foreach ($definition->getArguments() as $k => $v) { - if (is_numeric($k)) { - $def->addArgument($v); - } elseif (0 === strpos($k, 'index_')) { - $def->replaceArgument((int) substr($k, \strlen('index_')), $v); - } else { - $def->setArgument($k, $v); - } - } - - // merge properties - foreach ($definition->getProperties() as $k => $v) { - $def->setProperty($k, $v); - } - - // append method calls - if ($calls = $definition->getMethodCalls()) { - $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls)); - } - - $def->addError($parentDef); - $def->addError($definition); - - // these attributes are always taken from the child - $def->setAbstract($definition->isAbstract()); - $def->setTags($definition->getTags()); - // autoconfigure is never taken from parent (on purpose) - // and it's not legal on an instanceof - $def->setAutoconfigured($definition->isAutoconfigured()); - - return $def; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php deleted file mode 100644 index 5932472..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * @author Nicolas Grekas - */ -class ResolveClassPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getDefinitions() as $id => $definition) { - if ($definition->isSynthetic() || null !== $definition->getClass()) { - continue; - } - if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $id)) { - if ($definition instanceof ChildDefinition && !class_exists($id)) { - throw new InvalidArgumentException(sprintf('Service definition "%s" has a parent but no class, and its name looks like a FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.', $id)); - } - $definition->setClass($id); - } - } - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php deleted file mode 100644 index ea52b14..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolveEnvPlaceholdersPass.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Definition; - -/** - * Replaces env var placeholders by their current values. - */ -class ResolveEnvPlaceholdersPass extends AbstractRecursivePass -{ - protected function processValue($value, bool $isRoot = false) - { - if (\is_string($value)) { - return $this->container->resolveEnvPlaceholders($value, true); - } - if ($value instanceof Definition) { - $changes = $value->getChanges(); - if (isset($changes['class'])) { - $value->setClass($this->container->resolveEnvPlaceholders($value->getClass(), true)); - } - if (isset($changes['file'])) { - $value->setFile($this->container->resolveEnvPlaceholders($value->getFile(), true)); - } - } - - $value = parent::processValue($value, $isRoot); - - if ($value && \is_array($value) && !$isRoot) { - $value = array_combine($this->container->resolveEnvPlaceholders(array_keys($value), true), $value); - } - - return $value; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php deleted file mode 100644 index 23f535b..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolveFactoryClassPass.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * @author Maxime Steinhausser - */ -class ResolveFactoryClassPass extends AbstractRecursivePass -{ - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof Definition && \is_array($factory = $value->getFactory()) && null === $factory[0]) { - if (null === $class = $value->getClass()) { - throw new RuntimeException(sprintf('The "%s" service is defined to be created by a factory, but is missing the factory class. Did you forget to define the factory or service class?', $this->currentId)); - } - - $factory[0] = $class; - $value->setFactory($factory); - } - - return parent::processValue($value, $isRoot); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php deleted file mode 100644 index 0d01e2a..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php +++ /dev/null @@ -1,71 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Propagate "container.hot_path" tags to referenced services. - * - * @author Nicolas Grekas - */ -class ResolveHotPathPass extends AbstractRecursivePass -{ - private $tagName; - private $resolvedIds = []; - - public function __construct(string $tagName = 'container.hot_path') - { - $this->tagName = $tagName; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - try { - parent::process($container); - $container->getDefinition('service_container')->clearTag($this->tagName); - } finally { - $this->resolvedIds = []; - } - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof ArgumentInterface) { - return $value; - } - if ($value instanceof Definition && $isRoot && (isset($this->resolvedIds[$this->currentId]) || !$value->hasTag($this->tagName) || $value->isDeprecated())) { - return $value->isDeprecated() ? $value->clearTag($this->tagName) : $value; - } - if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->has($id = (string) $value)) { - $definition = $this->container->findDefinition($id); - if (!$definition->hasTag($this->tagName) && !$definition->isDeprecated()) { - $this->resolvedIds[$id] = true; - $definition->addTag($this->tagName); - parent::processValue($definition, false); - } - - return $value; - } - - return parent::processValue($value, $isRoot); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php deleted file mode 100644 index 96afb03..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php +++ /dev/null @@ -1,168 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * Applies instanceof conditionals to definitions. - * - * @author Nicolas Grekas - */ -class ResolveInstanceofConditionalsPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getAutoconfiguredInstanceof() as $interface => $definition) { - if ($definition->getArguments()) { - throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines arguments but these are not supported and should be removed.', $interface)); - } - } - - foreach ($container->getDefinitions() as $id => $definition) { - if ($definition instanceof ChildDefinition) { - // don't apply "instanceof" to children: it will be applied to their parent - continue; - } - $container->setDefinition($id, $this->processDefinition($container, $id, $definition)); - } - } - - private function processDefinition(ContainerBuilder $container, string $id, Definition $definition): Definition - { - $instanceofConditionals = $definition->getInstanceofConditionals(); - $autoconfiguredInstanceof = $definition->isAutoconfigured() ? $container->getAutoconfiguredInstanceof() : []; - if (!$instanceofConditionals && !$autoconfiguredInstanceof) { - return $definition; - } - - if (!$class = $container->getParameterBag()->resolveValue($definition->getClass())) { - return $definition; - } - - $conditionals = $this->mergeConditionals($autoconfiguredInstanceof, $instanceofConditionals, $container); - - $definition->setInstanceofConditionals([]); - $parent = $shared = null; - $instanceofTags = []; - $instanceofCalls = []; - $instanceofBindings = []; - $reflectionClass = null; - - foreach ($conditionals as $interface => $instanceofDefs) { - if ($interface !== $class && !(null === $reflectionClass ? $reflectionClass = ($container->getReflectionClass($class, false) ?: false) : $reflectionClass)) { - continue; - } - - if ($interface !== $class && !is_subclass_of($class, $interface)) { - continue; - } - - foreach ($instanceofDefs as $key => $instanceofDef) { - /** @var ChildDefinition $instanceofDef */ - $instanceofDef = clone $instanceofDef; - $instanceofDef->setAbstract(true)->setParent($parent ?: '.abstract.instanceof.'.$id); - $parent = '.instanceof.'.$interface.'.'.$key.'.'.$id; - $container->setDefinition($parent, $instanceofDef); - $instanceofTags[] = $instanceofDef->getTags(); - $instanceofBindings = $instanceofDef->getBindings() + $instanceofBindings; - - foreach ($instanceofDef->getMethodCalls() as $methodCall) { - $instanceofCalls[] = $methodCall; - } - - $instanceofDef->setTags([]); - $instanceofDef->setMethodCalls([]); - $instanceofDef->setBindings([]); - - if (isset($instanceofDef->getChanges()['shared'])) { - $shared = $instanceofDef->isShared(); - } - } - } - - if ($parent) { - $bindings = $definition->getBindings(); - $abstract = $container->setDefinition('.abstract.instanceof.'.$id, $definition); - - // cast Definition to ChildDefinition - $definition->setBindings([]); - $definition = serialize($definition); - $definition = substr_replace($definition, '53', 2, 2); - $definition = substr_replace($definition, 'Child', 44, 0); - /** @var ChildDefinition $definition */ - $definition = unserialize($definition); - $definition->setParent($parent); - - if (null !== $shared && !isset($definition->getChanges()['shared'])) { - $definition->setShared($shared); - } - - // Don't add tags to service decorators - if (null === $definition->getDecoratedService()) { - $i = \count($instanceofTags); - while (0 <= --$i) { - foreach ($instanceofTags[$i] as $k => $v) { - foreach ($v as $v) { - if ($definition->hasTag($k) && \in_array($v, $definition->getTag($k))) { - continue; - } - $definition->addTag($k, $v); - } - } - } - } - - $definition->setMethodCalls(array_merge($instanceofCalls, $definition->getMethodCalls())); - $definition->setBindings($bindings + $instanceofBindings); - - // reset fields with "merge" behavior - $abstract - ->setBindings([]) - ->setArguments([]) - ->setMethodCalls([]) - ->setDecoratedService(null) - ->setTags([]) - ->setAbstract(true); - } - - return $definition; - } - - private function mergeConditionals(array $autoconfiguredInstanceof, array $instanceofConditionals, ContainerBuilder $container): array - { - // make each value an array of ChildDefinition - $conditionals = array_map(function ($childDef) { return [$childDef]; }, $autoconfiguredInstanceof); - - foreach ($instanceofConditionals as $interface => $instanceofDef) { - // make sure the interface/class exists (but don't validate automaticInstanceofConditionals) - if (!$container->getReflectionClass($interface)) { - throw new RuntimeException(sprintf('"%s" is set as an "instanceof" conditional, but it does not exist.', $interface)); - } - - if (!isset($autoconfiguredInstanceof[$interface])) { - $conditionals[$interface] = []; - } - - $conditionals[$interface][] = $instanceofDef; - } - - return $conditionals; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php deleted file mode 100644 index 948de42..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php +++ /dev/null @@ -1,136 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\TypedReference; - -/** - * Emulates the invalid behavior if the reference is not found within the - * container. - * - * @author Johannes M. Schmitt - */ -class ResolveInvalidReferencesPass implements CompilerPassInterface -{ - private $container; - private $signalingException; - private $currentId; - - /** - * Process the ContainerBuilder to resolve invalid references. - */ - public function process(ContainerBuilder $container) - { - $this->container = $container; - $this->signalingException = new RuntimeException('Invalid reference.'); - - try { - foreach ($container->getDefinitions() as $this->currentId => $definition) { - $this->processValue($definition); - } - } finally { - $this->container = $this->signalingException = null; - } - } - - /** - * Processes arguments to determine invalid references. - * - * @return mixed - * - * @throws RuntimeException When an invalid reference is found - */ - private function processValue($value, int $rootLevel = 0, int $level = 0) - { - if ($value instanceof ServiceClosureArgument) { - $value->setValues($this->processValue($value->getValues(), 1, 1)); - } elseif ($value instanceof ArgumentInterface) { - $value->setValues($this->processValue($value->getValues(), $rootLevel, 1 + $level)); - } elseif ($value instanceof Definition) { - if ($value->isSynthetic() || $value->isAbstract()) { - return $value; - } - $value->setArguments($this->processValue($value->getArguments(), 0)); - $value->setProperties($this->processValue($value->getProperties(), 1)); - $value->setMethodCalls($this->processValue($value->getMethodCalls(), 2)); - } elseif (\is_array($value)) { - $i = 0; - - foreach ($value as $k => $v) { - try { - if (false !== $i && $k !== $i++) { - $i = false; - } - if ($v !== $processedValue = $this->processValue($v, $rootLevel, 1 + $level)) { - $value[$k] = $processedValue; - } - } catch (RuntimeException $e) { - if ($rootLevel < $level || ($rootLevel && !$level)) { - unset($value[$k]); - } elseif ($rootLevel) { - throw $e; - } else { - $value[$k] = null; - } - } - } - - // Ensure numerically indexed arguments have sequential numeric keys. - if (false !== $i) { - $value = array_values($value); - } - } elseif ($value instanceof Reference) { - if ($this->container->has($id = (string) $value)) { - return $value; - } - - $currentDefinition = $this->container->getDefinition($this->currentId); - - // resolve decorated service behavior depending on decorator service - if ($currentDefinition->innerServiceId === $id && ContainerInterface::NULL_ON_INVALID_REFERENCE === $currentDefinition->decorationOnInvalid) { - return null; - } - - $invalidBehavior = $value->getInvalidBehavior(); - - if (ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior && $value instanceof TypedReference && !$this->container->has($id)) { - $e = new ServiceNotFoundException($id, $this->currentId); - - // since the error message varies by $id and $this->currentId, so should the id of the dummy errored definition - $this->container->register($id = sprintf('.errored.%s.%s', $this->currentId, $id), $value->getType()) - ->addError($e->getMessage()); - - return new TypedReference($id, $value->getType(), $value->getInvalidBehavior()); - } - - // resolve invalid behavior - if (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) { - $value = null; - } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) { - if (0 < $level || $rootLevel) { - throw $this->signalingException; - } - $value = null; - } - } - - return $value; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php deleted file mode 100644 index 8fa3868..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php +++ /dev/null @@ -1,112 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Resolves named arguments to their corresponding numeric index. - * - * @author Kévin Dunglas - */ -class ResolveNamedArgumentsPass extends AbstractRecursivePass -{ - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Definition) { - return parent::processValue($value, $isRoot); - } - - $calls = $value->getMethodCalls(); - $calls[] = ['__construct', $value->getArguments()]; - - foreach ($calls as $i => $call) { - list($method, $arguments) = $call; - $parameters = null; - $resolvedArguments = []; - - foreach ($arguments as $key => $argument) { - if (\is_int($key)) { - $resolvedArguments[$key] = $argument; - continue; - } - - if (null === $parameters) { - $r = $this->getReflectionMethod($value, $method); - $class = $r instanceof \ReflectionMethod ? $r->class : $this->currentId; - $method = $r->getName(); - $parameters = $r->getParameters(); - } - - if (isset($key[0]) && '$' !== $key[0] && !class_exists($key) && !interface_exists($key, false)) { - throw new InvalidArgumentException(sprintf('Invalid service "%s": did you forget to add the "$" prefix to argument "%s"?', $this->currentId, $key)); - } - - if (isset($key[0]) && '$' === $key[0]) { - foreach ($parameters as $j => $p) { - if ($key === '$'.$p->name) { - if ($p->isVariadic() && \is_array($argument)) { - foreach ($argument as $variadicArgument) { - $resolvedArguments[$j++] = $variadicArgument; - } - } else { - $resolvedArguments[$j] = $argument; - } - - continue 2; - } - } - - throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument named "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); - } - - if (null !== $argument && !$argument instanceof Reference && !$argument instanceof Definition) { - throw new InvalidArgumentException(sprintf('Invalid service "%s": the value of argument "%s" of method "%s()" must be null, an instance of %s or an instance of %s, %s given.', $this->currentId, $key, $class !== $this->currentId ? $class.'::'.$method : $method, Reference::class, Definition::class, \gettype($argument))); - } - - $typeFound = false; - foreach ($parameters as $j => $p) { - if (!\array_key_exists($j, $resolvedArguments) && ProxyHelper::getTypeHint($r, $p, true) === $key) { - $resolvedArguments[$j] = $argument; - $typeFound = true; - } - } - - if (!$typeFound) { - throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument type-hinted as "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); - } - } - - if ($resolvedArguments !== $call[1]) { - ksort($resolvedArguments); - $calls[$i][1] = $resolvedArguments; - } - } - - list(, $arguments) = array_pop($calls); - - if ($arguments !== $value->getArguments()) { - $value->setArguments($arguments); - } - if ($calls !== $value->getMethodCalls()) { - $value->setMethodCalls($calls); - } - - return parent::processValue($value, $isRoot); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php deleted file mode 100644 index 91bba7d..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolveParameterPlaceHoldersPass.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; - -/** - * Resolves all parameter placeholders "%somevalue%" to their real values. - * - * @author Johannes M. Schmitt - */ -class ResolveParameterPlaceHoldersPass extends AbstractRecursivePass -{ - private $bag; - private $resolveArrays; - - public function __construct(bool $resolveArrays = true) - { - $this->resolveArrays = $resolveArrays; - } - - /** - * {@inheritdoc} - * - * @throws ParameterNotFoundException - */ - public function process(ContainerBuilder $container) - { - $this->bag = $container->getParameterBag(); - - try { - parent::process($container); - - $aliases = []; - foreach ($container->getAliases() as $name => $target) { - $this->currentId = $name; - $aliases[$this->bag->resolveValue($name)] = $target; - } - $container->setAliases($aliases); - } catch (ParameterNotFoundException $e) { - $e->setSourceId($this->currentId); - - throw $e; - } - - $this->bag->resolve(); - $this->bag = null; - } - - protected function processValue($value, bool $isRoot = false) - { - if (\is_string($value)) { - $v = $this->bag->resolveValue($value); - - return $this->resolveArrays || !$v || !\is_array($v) ? $v : $value; - } - if ($value instanceof Definition) { - $value->setBindings($this->processValue($value->getBindings())); - $changes = $value->getChanges(); - if (isset($changes['class'])) { - $value->setClass($this->bag->resolveValue($value->getClass())); - } - if (isset($changes['file'])) { - $value->setFile($this->bag->resolveValue($value->getFile())); - } - } - - $value = parent::processValue($value, $isRoot); - - if ($value && \is_array($value)) { - $value = array_combine($this->bag->resolveValue(array_keys($value)), $value); - } - - return $value; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php b/vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php deleted file mode 100644 index 1bd9934..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolvePrivatesPass.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * @author Nicolas Grekas - */ -class ResolvePrivatesPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - foreach ($container->getDefinitions() as $id => $definition) { - if ($definition->isPrivate()) { - $definition->setPublic(false); - $definition->setPrivate(true); - } - } - - foreach ($container->getAliases() as $id => $alias) { - if ($alias->isPrivate()) { - $alias->setPublic(false); - $alias->setPrivate(true); - } - } - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php deleted file mode 100644 index f38dbc7..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php +++ /dev/null @@ -1,80 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Replaces all references to aliases with references to the actual service. - * - * @author Johannes M. Schmitt - */ -class ResolveReferencesToAliasesPass extends AbstractRecursivePass -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - parent::process($container); - - foreach ($container->getAliases() as $id => $alias) { - $aliasId = (string) $alias; - $this->currentId = $id; - - if ($aliasId !== $defId = $this->getDefinitionId($aliasId, $container)) { - $container->setAlias($id, $defId)->setPublic($alias->isPublic())->setPrivate($alias->isPrivate()); - } - } - } - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof Reference) { - return parent::processValue($value, $isRoot); - } - - $defId = $this->getDefinitionId($id = (string) $value, $this->container); - - return $defId !== $id ? new Reference($defId, $value->getInvalidBehavior()) : $value; - } - - private function getDefinitionId(string $id, ContainerBuilder $container): string - { - if (!$container->hasAlias($id)) { - return $id; - } - - $alias = $container->getAlias($id); - - if ($alias->isDeprecated()) { - @trigger_error(sprintf('%s. It is being referenced by the "%s" %s.', rtrim($alias->getDeprecationMessage($id), '. '), $this->currentId, $container->hasDefinition($this->currentId) ? 'service' : 'alias'), E_USER_DEPRECATED); - } - - $seen = []; - do { - if (isset($seen[$id])) { - throw new ServiceCircularReferenceException($id, array_merge(array_keys($seen), [$id])); - } - - $seen[$id] = true; - $id = (string) $container->getAlias($id); - } while ($container->hasAlias($id)); - - return $id; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php deleted file mode 100644 index 518c03d..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Contracts\Service\ServiceProviderInterface; - -/** - * Compiler pass to inject their service locator to service subscribers. - * - * @author Nicolas Grekas - */ -class ResolveServiceSubscribersPass extends AbstractRecursivePass -{ - private $serviceLocator; - - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof Reference && $this->serviceLocator && \in_array((string) $value, [ContainerInterface::class, ServiceProviderInterface::class], true)) { - return new Reference($this->serviceLocator); - } - - if (!$value instanceof Definition) { - return parent::processValue($value, $isRoot); - } - - $serviceLocator = $this->serviceLocator; - $this->serviceLocator = null; - - if ($value->hasTag('container.service_subscriber.locator')) { - $this->serviceLocator = $value->getTag('container.service_subscriber.locator')[0]['id']; - $value->clearTag('container.service_subscriber.locator'); - } - - try { - return parent::processValue($value); - } finally { - $this->serviceLocator = $serviceLocator; - } - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php deleted file mode 100644 index 48a034a..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; - -/** - * Resolves all TaggedIteratorArgument arguments. - * - * @author Roland Franssen - */ -class ResolveTaggedIteratorArgumentPass extends AbstractRecursivePass -{ - use PriorityTaggedServiceTrait; - - /** - * {@inheritdoc} - */ - protected function processValue($value, bool $isRoot = false) - { - if (!$value instanceof TaggedIteratorArgument) { - return parent::processValue($value, $isRoot); - } - - $value->setValues($this->findAndSortTaggedServices($value, $this->container)); - - return $value; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php b/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php deleted file mode 100644 index 5985451..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php +++ /dev/null @@ -1,135 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ServiceLocator; - -/** - * Applies the "container.service_locator" tag by wrapping references into ServiceClosureArgument instances. - * - * @author Nicolas Grekas - */ -final class ServiceLocatorTagPass extends AbstractRecursivePass -{ - use PriorityTaggedServiceTrait; - - protected function processValue($value, bool $isRoot = false) - { - if ($value instanceof ServiceLocatorArgument) { - if ($value->getTaggedIteratorArgument()) { - $value->setValues($this->findAndSortTaggedServices($value->getTaggedIteratorArgument(), $this->container)); - } - - return self::register($this->container, $value->getValues()); - } - - if (!$value instanceof Definition || !$value->hasTag('container.service_locator')) { - return parent::processValue($value, $isRoot); - } - - if (!$value->getClass()) { - $value->setClass(ServiceLocator::class); - } - - $arguments = $value->getArguments(); - if (!isset($arguments[0]) || !\is_array($arguments[0])) { - throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set.', $this->currentId)); - } - - $i = 0; - - foreach ($arguments[0] as $k => $v) { - if ($v instanceof ServiceClosureArgument) { - continue; - } - if (!$v instanceof Reference) { - throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set, "%s" found for key "%s".', $this->currentId, \is_object($v) ? \get_class($v) : \gettype($v), $k)); - } - - if ($i === $k) { - unset($arguments[0][$k]); - - $k = (string) $v; - ++$i; - } elseif (\is_int($k)) { - $i = null; - } - $arguments[0][$k] = new ServiceClosureArgument($v); - } - ksort($arguments[0]); - - $value->setArguments($arguments); - - $id = '.service_locator.'.ContainerBuilder::hash($value); - - if ($isRoot) { - if ($id !== $this->currentId) { - $this->container->setAlias($id, new Alias($this->currentId, false)); - } - - return $value; - } - - $this->container->setDefinition($id, $value->setPublic(false)); - - return new Reference($id); - } - - /** - * @param Reference[] $refMap - */ - public static function register(ContainerBuilder $container, array $refMap, string $callerId = null): Reference - { - foreach ($refMap as $id => $ref) { - if (!$ref instanceof Reference) { - throw new InvalidArgumentException(sprintf('Invalid service locator definition: only services can be referenced, "%s" found for key "%s". Inject parameter values using constructors instead.', \is_object($ref) ? \get_class($ref) : \gettype($ref), $id)); - } - $refMap[$id] = new ServiceClosureArgument($ref); - } - ksort($refMap); - - $locator = (new Definition(ServiceLocator::class)) - ->addArgument($refMap) - ->setPublic(false) - ->addTag('container.service_locator'); - - if (null !== $callerId && $container->hasDefinition($callerId)) { - $locator->setBindings($container->getDefinition($callerId)->getBindings()); - } - - if (!$container->hasDefinition($id = '.service_locator.'.ContainerBuilder::hash($locator))) { - $container->setDefinition($id, $locator); - } - - if (null !== $callerId) { - $locatorId = $id; - // Locators are shared when they hold the exact same list of factories; - // to have them specialized per consumer service, we use a cloning factory - // to derivate customized instances from the prototype one. - $container->register($id .= '.'.$callerId, ServiceLocator::class) - ->setPublic(false) - ->setFactory([new Reference($locatorId), 'withContext']) - ->addTag('container.service_locator_context', ['id' => $callerId]) - ->addArgument($callerId) - ->addArgument(new Reference('service_container')); - } - - return new Reference($id); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php deleted file mode 100644 index 308abc6..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php +++ /dev/null @@ -1,98 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * This is a directed graph of your services. - * - * This information can be used by your compiler passes instead of collecting - * it themselves which improves performance quite a lot. - * - * @author Johannes M. Schmitt - * - * @final - */ -class ServiceReferenceGraph -{ - /** - * @var ServiceReferenceGraphNode[] - */ - private $nodes = []; - - public function hasNode(string $id): bool - { - return isset($this->nodes[$id]); - } - - /** - * Gets a node by identifier. - * - * @throws InvalidArgumentException if no node matches the supplied identifier - */ - public function getNode(string $id): ServiceReferenceGraphNode - { - if (!isset($this->nodes[$id])) { - throw new InvalidArgumentException(sprintf('There is no node with id "%s".', $id)); - } - - return $this->nodes[$id]; - } - - /** - * Returns all nodes. - * - * @return ServiceReferenceGraphNode[] - */ - public function getNodes(): array - { - return $this->nodes; - } - - /** - * Clears all nodes. - */ - public function clear() - { - foreach ($this->nodes as $node) { - $node->clear(); - } - $this->nodes = []; - } - - /** - * Connects 2 nodes together in the Graph. - */ - public function connect(?string $sourceId, $sourceValue, ?string $destId, $destValue = null, $reference = null, bool $lazy = false, bool $weak = false, bool $byConstructor = false) - { - if (null === $sourceId || null === $destId) { - return; - } - - $sourceNode = $this->createNode($sourceId, $sourceValue); - $destNode = $this->createNode($destId, $destValue); - $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference, $lazy, $weak, $byConstructor); - - $sourceNode->addOutEdge($edge); - $destNode->addInEdge($edge); - } - - private function createNode(string $id, $value): ServiceReferenceGraphNode - { - if (isset($this->nodes[$id]) && $this->nodes[$id]->getValue() === $value) { - return $this->nodes[$id]; - } - - return $this->nodes[$id] = new ServiceReferenceGraphNode($id, $value); - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php deleted file mode 100644 index 9861456..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php +++ /dev/null @@ -1,99 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -/** - * Represents an edge in your service graph. - * - * Value is typically a reference. - * - * @author Johannes M. Schmitt - */ -class ServiceReferenceGraphEdge -{ - private $sourceNode; - private $destNode; - private $value; - private $lazy; - private $weak; - private $byConstructor; - - public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null, bool $lazy = false, bool $weak = false, bool $byConstructor = false) - { - $this->sourceNode = $sourceNode; - $this->destNode = $destNode; - $this->value = $value; - $this->lazy = $lazy; - $this->weak = $weak; - $this->byConstructor = $byConstructor; - } - - /** - * Returns the value of the edge. - * - * @return mixed - */ - public function getValue() - { - return $this->value; - } - - /** - * Returns the source node. - * - * @return ServiceReferenceGraphNode - */ - public function getSourceNode() - { - return $this->sourceNode; - } - - /** - * Returns the destination node. - * - * @return ServiceReferenceGraphNode - */ - public function getDestNode() - { - return $this->destNode; - } - - /** - * Returns true if the edge is lazy, meaning it's a dependency not requiring direct instantiation. - * - * @return bool - */ - public function isLazy() - { - return $this->lazy; - } - - /** - * Returns true if the edge is weak, meaning it shouldn't prevent removing the target service. - * - * @return bool - */ - public function isWeak() - { - return $this->weak; - } - - /** - * Returns true if the edge links with a constructor argument. - * - * @return bool - */ - public function isReferencedByConstructor() - { - return $this->byConstructor; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php deleted file mode 100644 index fec1424..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php +++ /dev/null @@ -1,118 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Definition; - -/** - * Represents a node in your service graph. - * - * Value is typically a definition, or an alias. - * - * @author Johannes M. Schmitt - */ -class ServiceReferenceGraphNode -{ - private $id; - private $inEdges = []; - private $outEdges = []; - private $value; - - /** - * @param string $id The node identifier - * @param mixed $value The node value - */ - public function __construct(string $id, $value) - { - $this->id = $id; - $this->value = $value; - } - - public function addInEdge(ServiceReferenceGraphEdge $edge) - { - $this->inEdges[] = $edge; - } - - public function addOutEdge(ServiceReferenceGraphEdge $edge) - { - $this->outEdges[] = $edge; - } - - /** - * Checks if the value of this node is an Alias. - * - * @return bool True if the value is an Alias instance - */ - public function isAlias() - { - return $this->value instanceof Alias; - } - - /** - * Checks if the value of this node is a Definition. - * - * @return bool True if the value is a Definition instance - */ - public function isDefinition() - { - return $this->value instanceof Definition; - } - - /** - * Returns the identifier. - * - * @return string - */ - public function getId() - { - return $this->id; - } - - /** - * Returns the in edges. - * - * @return ServiceReferenceGraphEdge[] - */ - public function getInEdges() - { - return $this->inEdges; - } - - /** - * Returns the out edges. - * - * @return ServiceReferenceGraphEdge[] - */ - public function getOutEdges() - { - return $this->outEdges; - } - - /** - * Returns the value of this Node. - * - * @return mixed The value - */ - public function getValue() - { - return $this->value; - } - - /** - * Clears all edges. - */ - public function clear() - { - $this->inEdges = $this->outEdges = []; - } -} diff --git a/vendor/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php b/vendor/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php deleted file mode 100644 index be0f1ed..0000000 --- a/vendor/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php +++ /dev/null @@ -1,116 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\Config\Definition\BaseNode; -use Symfony\Component\Config\Definition\Processor; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; - -/** - * Validates environment variable placeholders used in extension configuration with dummy values. - * - * @author Roland Franssen - */ -class ValidateEnvPlaceholdersPass implements CompilerPassInterface -{ - private static $typeFixtures = ['array' => [], 'bool' => false, 'float' => 0.0, 'int' => 0, 'string' => '']; - - private $extensionConfig = []; - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $this->extensionConfig = []; - - if (!class_exists(BaseNode::class) || !$extensions = $container->getExtensions()) { - return; - } - - $resolvingBag = $container->getParameterBag(); - if (!$resolvingBag instanceof EnvPlaceholderParameterBag) { - return; - } - - $defaultBag = new ParameterBag($resolvingBag->all()); - $envTypes = $resolvingBag->getProvidedTypes(); - try { - foreach ($resolvingBag->getEnvPlaceholders() + $resolvingBag->getUnusedEnvPlaceholders() as $env => $placeholders) { - $values = []; - if (false === $i = strpos($env, ':')) { - $default = $defaultBag->has("env($env)") ? $defaultBag->get("env($env)") : self::$typeFixtures['string']; - $defaultType = null !== $default ? self::getType($default) : 'string'; - $values[$defaultType] = $default; - } else { - $prefix = substr($env, 0, $i); - foreach ($envTypes[$prefix] ?? ['string'] as $type) { - $values[$type] = self::$typeFixtures[$type] ?? null; - } - } - foreach ($placeholders as $placeholder) { - BaseNode::setPlaceholder($placeholder, $values); - } - } - - $processor = new Processor(); - - foreach ($extensions as $name => $extension) { - if (!$extension instanceof ConfigurationExtensionInterface || !$config = array_filter($container->getExtensionConfig($name))) { - // this extension has no semantic configuration or was not called - continue; - } - - $config = $resolvingBag->resolveValue($config); - - if (null === $configuration = $extension->getConfiguration($config, $container)) { - continue; - } - - $this->extensionConfig[$name] = $processor->processConfiguration($configuration, $config); - } - } finally { - BaseNode::resetPlaceholders(); - } - - $resolvingBag->clearUnusedEnvPlaceholders(); - } - - /** - * @internal - */ - public function getExtensionConfig(): array - { - try { - return $this->extensionConfig; - } finally { - $this->extensionConfig = []; - } - } - - private static function getType($value): string - { - switch ($type = \gettype($value)) { - case 'boolean': - return 'bool'; - case 'double': - return 'float'; - case 'integer': - return 'int'; - } - - return $type; - } -} diff --git a/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php b/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php deleted file mode 100644 index 8ffb8dc..0000000 --- a/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Config; - -use Symfony\Component\Config\Resource\ResourceInterface; - -/** - * Tracks container parameters. - * - * @author Maxime Steinhausser - * - * @final - */ -class ContainerParametersResource implements ResourceInterface -{ - private $parameters; - - /** - * @param array $parameters The container parameters to track - */ - public function __construct(array $parameters) - { - $this->parameters = $parameters; - } - - /** - * {@inheritdoc} - */ - public function __toString(): string - { - return 'container_parameters_'.md5(serialize($this->parameters)); - } - - /** - * @return array Tracked parameters - */ - public function getParameters(): array - { - return $this->parameters; - } -} diff --git a/vendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php b/vendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php deleted file mode 100644 index 2f2affa..0000000 --- a/vendor/symfony/dependency-injection/Config/ContainerParametersResourceChecker.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Config; - -use Symfony\Component\Config\Resource\ResourceInterface; -use Symfony\Component\Config\ResourceCheckerInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * @author Maxime Steinhausser - */ -class ContainerParametersResourceChecker implements ResourceCheckerInterface -{ - /** @var ContainerInterface */ - private $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function supports(ResourceInterface $metadata) - { - return $metadata instanceof ContainerParametersResource; - } - - /** - * {@inheritdoc} - */ - public function isFresh(ResourceInterface $resource, int $timestamp) - { - foreach ($resource->getParameters() as $key => $value) { - if (!$this->container->hasParameter($key) || $this->container->getParameter($key) !== $value) { - return false; - } - } - - return true; - } -} diff --git a/vendor/symfony/dependency-injection/Container.php b/vendor/symfony/dependency-injection/Container.php deleted file mode 100644 index 53bebdf..0000000 --- a/vendor/symfony/dependency-injection/Container.php +++ /dev/null @@ -1,447 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * Container is a dependency injection container. - * - * It gives access to object instances (services). - * Services and parameters are simple key/pair stores. - * The container can have four possible behaviors when a service - * does not exist (or is not initialized for the last case): - * - * * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default) - * * NULL_ON_INVALID_REFERENCE: Returns null - * * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference - * (for instance, ignore a setter if the service does not exist) - * * IGNORE_ON_UNINITIALIZED_REFERENCE: Ignores/returns null for uninitialized services or invalid references - * - * @author Fabien Potencier - * @author Johannes M. Schmitt - */ -class Container implements ContainerInterface, ResetInterface -{ - protected $parameterBag; - protected $services = []; - protected $privates = []; - protected $fileMap = []; - protected $methodMap = []; - protected $factories = []; - protected $aliases = []; - protected $loading = []; - protected $resolving = []; - protected $syntheticIds = []; - - private $envCache = []; - private $compiled = false; - private $getEnv; - - public function __construct(ParameterBagInterface $parameterBag = null) - { - $this->parameterBag = $parameterBag ?: new EnvPlaceholderParameterBag(); - } - - /** - * Compiles the container. - * - * This method does two things: - * - * * Parameter values are resolved; - * * The parameter bag is frozen. - */ - public function compile() - { - $this->parameterBag->resolve(); - - $this->parameterBag = new FrozenParameterBag($this->parameterBag->all()); - - $this->compiled = true; - } - - /** - * Returns true if the container is compiled. - * - * @return bool - */ - public function isCompiled() - { - return $this->compiled; - } - - /** - * Gets the service container parameter bag. - * - * @return ParameterBagInterface A ParameterBagInterface instance - */ - public function getParameterBag() - { - return $this->parameterBag; - } - - /** - * Gets a parameter. - * - * @param string $name The parameter name - * - * @return mixed The parameter value - * - * @throws InvalidArgumentException if the parameter is not defined - */ - public function getParameter(string $name) - { - return $this->parameterBag->get($name); - } - - /** - * Checks if a parameter exists. - * - * @param string $name The parameter name - * - * @return bool The presence of parameter in container - */ - public function hasParameter(string $name) - { - return $this->parameterBag->has($name); - } - - /** - * Sets a parameter. - * - * @param string $name The parameter name - * @param mixed $value The parameter value - */ - public function setParameter(string $name, $value) - { - $this->parameterBag->set($name, $value); - } - - /** - * Sets a service. - * - * Setting a synthetic service to null resets it: has() returns false and get() - * behaves in the same way as if the service was never created. - */ - public function set(string $id, ?object $service) - { - // Runs the internal initializer; used by the dumped container to include always-needed files - if (isset($this->privates['service_container']) && $this->privates['service_container'] instanceof \Closure) { - $initialize = $this->privates['service_container']; - unset($this->privates['service_container']); - $initialize(); - } - - if ('service_container' === $id) { - throw new InvalidArgumentException('You cannot set service "service_container".'); - } - - if (!(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) { - if (isset($this->syntheticIds[$id]) || !isset($this->getRemovedIds()[$id])) { - // no-op - } elseif (null === $service) { - throw new InvalidArgumentException(sprintf('The "%s" service is private, you cannot unset it.', $id)); - } else { - throw new InvalidArgumentException(sprintf('The "%s" service is private, you cannot replace it.', $id)); - } - } elseif (isset($this->services[$id])) { - throw new InvalidArgumentException(sprintf('The "%s" service is already initialized, you cannot replace it.', $id)); - } - - if (isset($this->aliases[$id])) { - unset($this->aliases[$id]); - } - - if (null === $service) { - unset($this->services[$id]); - - return; - } - - $this->services[$id] = $service; - } - - /** - * Returns true if the given service is defined. - * - * @param string $id The service identifier - * - * @return bool true if the service is defined, false otherwise - */ - public function has($id) - { - if (isset($this->aliases[$id])) { - $id = $this->aliases[$id]; - } - if (isset($this->services[$id])) { - return true; - } - if ('service_container' === $id) { - return true; - } - - return isset($this->fileMap[$id]) || isset($this->methodMap[$id]); - } - - /** - * Gets a service. - * - * @param string $id The service identifier - * @param int $invalidBehavior The behavior when the service does not exist - * - * @return object|null The associated service - * - * @throws ServiceCircularReferenceException When a circular reference is detected - * @throws ServiceNotFoundException When the service is not defined - * @throws \Exception if an exception has been thrown when the service has been resolved - * - * @see Reference - */ - public function get($id, int $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERENCE */ 1) - { - return $this->services[$id] - ?? $this->services[$id = $this->aliases[$id] ?? $id] - ?? ('service_container' === $id ? $this : ($this->factories[$id] ?? [$this, 'make'])($id, $invalidBehavior)); - } - - /** - * Creates a service. - * - * As a separate method to allow "get()" to use the really fast `??` operator. - */ - private function make(string $id, int $invalidBehavior) - { - if (isset($this->loading[$id])) { - throw new ServiceCircularReferenceException($id, array_merge(array_keys($this->loading), [$id])); - } - - $this->loading[$id] = true; - - try { - if (isset($this->fileMap[$id])) { - return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->load($this->fileMap[$id]); - } elseif (isset($this->methodMap[$id])) { - return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->{$this->methodMap[$id]}(); - } - } catch (\Exception $e) { - unset($this->services[$id]); - - throw $e; - } finally { - unset($this->loading[$id]); - } - - if (/* self::EXCEPTION_ON_INVALID_REFERENCE */ 1 === $invalidBehavior) { - if (!$id) { - throw new ServiceNotFoundException($id); - } - if (isset($this->syntheticIds[$id])) { - throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service is synthetic, it needs to be set at boot time before it can be used.', $id)); - } - if (isset($this->getRemovedIds()[$id])) { - throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.', $id)); - } - - $alternatives = []; - foreach ($this->getServiceIds() as $knownId) { - if ('' === $knownId || '.' === $knownId[0]) { - continue; - } - $lev = levenshtein($id, $knownId); - if ($lev <= \strlen($id) / 3 || false !== strpos($knownId, $id)) { - $alternatives[] = $knownId; - } - } - - throw new ServiceNotFoundException($id, null, null, $alternatives); - } - - return null; - } - - /** - * Returns true if the given service has actually been initialized. - * - * @param string $id The service identifier - * - * @return bool true if service has already been initialized, false otherwise - */ - public function initialized(string $id) - { - if (isset($this->aliases[$id])) { - $id = $this->aliases[$id]; - } - - if ('service_container' === $id) { - return false; - } - - return isset($this->services[$id]); - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $services = $this->services + $this->privates; - $this->services = $this->factories = $this->privates = []; - - foreach ($services as $service) { - try { - if ($service instanceof ResetInterface) { - $service->reset(); - } - } catch (\Throwable $e) { - continue; - } - } - } - - /** - * Gets all service ids. - * - * @return string[] An array of all defined service ids - */ - public function getServiceIds() - { - return array_map('strval', array_unique(array_merge(['service_container'], array_keys($this->fileMap), array_keys($this->methodMap), array_keys($this->aliases), array_keys($this->services)))); - } - - /** - * Gets service ids that existed at compile time. - * - * @return array - */ - public function getRemovedIds() - { - return []; - } - - /** - * Camelizes a string. - * - * @param string $id A string to camelize - * - * @return string The camelized string - */ - public static function camelize($id) - { - return strtr(ucwords(strtr($id, ['_' => ' ', '.' => '_ ', '\\' => '_ '])), [' ' => '']); - } - - /** - * A string to underscore. - * - * @param string $id The string to underscore - * - * @return string The underscored string - */ - public static function underscore($id) - { - return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], str_replace('_', '.', $id))); - } - - /** - * Creates a service by requiring its factory file. - */ - protected function load($file) - { - return require $file; - } - - /** - * Fetches a variable from the environment. - * - * @param string $name The name of the environment variable - * - * @return mixed The value to use for the provided environment variable name - * - * @throws EnvNotFoundException When the environment variable is not found and has no default value - */ - protected function getEnv($name) - { - if (isset($this->resolving[$envName = "env($name)"])) { - throw new ParameterCircularReferenceException(array_keys($this->resolving)); - } - if (isset($this->envCache[$name]) || \array_key_exists($name, $this->envCache)) { - return $this->envCache[$name]; - } - if (!$this->has($id = 'container.env_var_processors_locator')) { - $this->set($id, new ServiceLocator([])); - } - if (!$this->getEnv) { - $this->getEnv = new \ReflectionMethod($this, __FUNCTION__); - $this->getEnv->setAccessible(true); - $this->getEnv = $this->getEnv->getClosure($this); - } - $processors = $this->get($id); - - if (false !== $i = strpos($name, ':')) { - $prefix = substr($name, 0, $i); - $localName = substr($name, 1 + $i); - } else { - $prefix = 'string'; - $localName = $name; - } - $processor = $processors->has($prefix) ? $processors->get($prefix) : new EnvVarProcessor($this); - - $this->resolving[$envName] = true; - try { - return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv); - } finally { - unset($this->resolving[$envName]); - } - } - - /** - * @param string|false $registry - * @param string|bool $load - * - * @return mixed - * - * @internal - */ - final protected function getService($registry, string $id, ?string $method, $load) - { - if ('service_container' === $id) { - return $this; - } - if (\is_string($load)) { - throw new RuntimeException($load); - } - if (null === $method) { - return false !== $registry ? $this->{$registry}[$id] ?? null : null; - } - if (false !== $registry) { - return $this->{$registry}[$id] ?? $this->{$registry}[$id] = $load ? $this->load($method) : $this->{$method}(); - } - if (!$load) { - return $this->{$method}(); - } - - return ($factory = $this->factories[$id] ?? $this->factories['service_container'][$id] ?? null) ? $factory() : $this->load($method); - } - - private function __clone() - { - } -} diff --git a/vendor/symfony/dependency-injection/ContainerAwareInterface.php b/vendor/symfony/dependency-injection/ContainerAwareInterface.php deleted file mode 100644 index e7b9d57..0000000 --- a/vendor/symfony/dependency-injection/ContainerAwareInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * ContainerAwareInterface should be implemented by classes that depends on a Container. - * - * @author Fabien Potencier - */ -interface ContainerAwareInterface -{ - /** - * Sets the container. - */ - public function setContainer(ContainerInterface $container = null); -} diff --git a/vendor/symfony/dependency-injection/ContainerAwareTrait.php b/vendor/symfony/dependency-injection/ContainerAwareTrait.php deleted file mode 100644 index ee1ea2c..0000000 --- a/vendor/symfony/dependency-injection/ContainerAwareTrait.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * ContainerAware trait. - * - * @author Fabien Potencier - */ -trait ContainerAwareTrait -{ - /** - * @var ContainerInterface - */ - protected $container; - - public function setContainer(ContainerInterface $container = null) - { - $this->container = $container; - } -} diff --git a/vendor/symfony/dependency-injection/ContainerBuilder.php b/vendor/symfony/dependency-injection/ContainerBuilder.php deleted file mode 100644 index 414dad6..0000000 --- a/vendor/symfony/dependency-injection/ContainerBuilder.php +++ /dev/null @@ -1,1611 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Psr\Container\ContainerInterface as PsrContainerInterface; -use Symfony\Component\Config\Resource\ClassExistenceResource; -use Symfony\Component\Config\Resource\ComposerResource; -use Symfony\Component\Config\Resource\DirectoryResource; -use Symfony\Component\Config\Resource\FileExistenceResource; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Config\Resource\GlobResource; -use Symfony\Component\Config\Resource\ReflectionClassResource; -use Symfony\Component\Config\Resource\ResourceInterface; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocator; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Compiler\Compiler; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\PassConfig; -use Symfony\Component\DependencyInjection\Compiler\ResolveEnvPlaceholdersPass; -use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; -use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; -use Symfony\Component\ExpressionLanguage\Expression; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; - -/** - * ContainerBuilder is a DI container that provides an API to easily describe services. - * - * @author Fabien Potencier - */ -class ContainerBuilder extends Container implements TaggedContainerInterface -{ - /** - * @var ExtensionInterface[] - */ - private $extensions = []; - - /** - * @var ExtensionInterface[] - */ - private $extensionsByNs = []; - - /** - * @var Definition[] - */ - private $definitions = []; - - /** - * @var Alias[] - */ - private $aliasDefinitions = []; - - /** - * @var ResourceInterface[] - */ - private $resources = []; - - private $extensionConfigs = []; - - /** - * @var Compiler - */ - private $compiler; - - private $trackResources; - - /** - * @var InstantiatorInterface|null - */ - private $proxyInstantiator; - - /** - * @var ExpressionLanguage|null - */ - private $expressionLanguage; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - private $expressionLanguageProviders = []; - - /** - * @var string[] with tag names used by findTaggedServiceIds - */ - private $usedTags = []; - - /** - * @var string[][] a map of env var names to their placeholders - */ - private $envPlaceholders = []; - - /** - * @var int[] a map of env vars to their resolution counter - */ - private $envCounters = []; - - /** - * @var string[] the list of vendor directories - */ - private $vendors; - - private $autoconfiguredInstanceof = []; - - private $removedIds = []; - - private $removedBindingIds = []; - - private static $internalTypes = [ - 'int' => true, - 'float' => true, - 'string' => true, - 'bool' => true, - 'resource' => true, - 'object' => true, - 'array' => true, - 'null' => true, - 'callable' => true, - 'iterable' => true, - 'mixed' => true, - ]; - - public function __construct(ParameterBagInterface $parameterBag = null) - { - parent::__construct($parameterBag); - - $this->trackResources = interface_exists('Symfony\Component\Config\Resource\ResourceInterface'); - $this->setDefinition('service_container', (new Definition(ContainerInterface::class))->setSynthetic(true)->setPublic(true)); - $this->setAlias(PsrContainerInterface::class, new Alias('service_container', false)); - $this->setAlias(ContainerInterface::class, new Alias('service_container', false)); - } - - /** - * @var \ReflectionClass[] a list of class reflectors - */ - private $classReflectors; - - /** - * Sets the track resources flag. - * - * If you are not using the loaders and therefore don't want - * to depend on the Config component, set this flag to false. - */ - public function setResourceTracking(bool $track) - { - $this->trackResources = $track; - } - - /** - * Checks if resources are tracked. - * - * @return bool true If resources are tracked, false otherwise - */ - public function isTrackingResources() - { - return $this->trackResources; - } - - /** - * Sets the instantiator to be used when fetching proxies. - */ - public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator) - { - $this->proxyInstantiator = $proxyInstantiator; - } - - public function registerExtension(ExtensionInterface $extension) - { - $this->extensions[$extension->getAlias()] = $extension; - - if (false !== $extension->getNamespace()) { - $this->extensionsByNs[$extension->getNamespace()] = $extension; - } - } - - /** - * Returns an extension by alias or namespace. - * - * @return ExtensionInterface An extension instance - * - * @throws LogicException if the extension is not registered - */ - public function getExtension(string $name) - { - if (isset($this->extensions[$name])) { - return $this->extensions[$name]; - } - - if (isset($this->extensionsByNs[$name])) { - return $this->extensionsByNs[$name]; - } - - throw new LogicException(sprintf('Container extension "%s" is not registered', $name)); - } - - /** - * Returns all registered extensions. - * - * @return ExtensionInterface[] An array of ExtensionInterface - */ - public function getExtensions() - { - return $this->extensions; - } - - /** - * Checks if we have an extension. - * - * @return bool If the extension exists - */ - public function hasExtension(string $name) - { - return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]); - } - - /** - * Returns an array of resources loaded to build this configuration. - * - * @return ResourceInterface[] An array of resources - */ - public function getResources() - { - return array_values($this->resources); - } - - /** - * @return $this - */ - public function addResource(ResourceInterface $resource) - { - if (!$this->trackResources) { - return $this; - } - - if ($resource instanceof GlobResource && $this->inVendors($resource->getPrefix())) { - return $this; - } - - $this->resources[(string) $resource] = $resource; - - return $this; - } - - /** - * Sets the resources for this configuration. - * - * @param ResourceInterface[] $resources An array of resources - * - * @return $this - */ - public function setResources(array $resources) - { - if (!$this->trackResources) { - return $this; - } - - $this->resources = $resources; - - return $this; - } - - /** - * Adds the object class hierarchy as resources. - * - * @param object|string $object An object instance or class name - * - * @return $this - */ - public function addObjectResource($object) - { - if ($this->trackResources) { - if (\is_object($object)) { - $object = \get_class($object); - } - if (!isset($this->classReflectors[$object])) { - $this->classReflectors[$object] = new \ReflectionClass($object); - } - $class = $this->classReflectors[$object]; - - foreach ($class->getInterfaceNames() as $name) { - if (null === $interface = &$this->classReflectors[$name]) { - $interface = new \ReflectionClass($name); - } - $file = $interface->getFileName(); - if (false !== $file && file_exists($file)) { - $this->fileExists($file); - } - } - do { - $file = $class->getFileName(); - if (false !== $file && file_exists($file)) { - $this->fileExists($file); - } - foreach ($class->getTraitNames() as $name) { - $this->addObjectResource($name); - } - } while ($class = $class->getParentClass()); - } - - return $this; - } - - /** - * Retrieves the requested reflection class and registers it for resource tracking. - * - * @throws \ReflectionException when a parent class/interface/trait is not found and $throw is true - * - * @final - */ - public function getReflectionClass(?string $class, bool $throw = true): ?\ReflectionClass - { - if (!$class = $this->getParameterBag()->resolveValue($class)) { - return null; - } - - if (isset(self::$internalTypes[$class])) { - return null; - } - - $resource = $classReflector = null; - - try { - if (isset($this->classReflectors[$class])) { - $classReflector = $this->classReflectors[$class]; - } elseif (class_exists(ClassExistenceResource::class)) { - $resource = new ClassExistenceResource($class, false); - $classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class); - } else { - $classReflector = class_exists($class) ? new \ReflectionClass($class) : false; - } - } catch (\ReflectionException $e) { - if ($throw) { - throw $e; - } - } - - if ($this->trackResources) { - if (!$classReflector) { - $this->addResource($resource ?: new ClassExistenceResource($class, false)); - } elseif (!$classReflector->isInternal()) { - $path = $classReflector->getFileName(); - - if (!$this->inVendors($path)) { - $this->addResource(new ReflectionClassResource($classReflector, $this->vendors)); - } - } - $this->classReflectors[$class] = $classReflector; - } - - return $classReflector ?: null; - } - - /** - * Checks whether the requested file or directory exists and registers the result for resource tracking. - * - * @param string $path The file or directory path for which to check the existence - * @param bool|string $trackContents Whether to track contents of the given resource. If a string is passed, - * it will be used as pattern for tracking contents of the requested directory - * - * @final - */ - public function fileExists(string $path, $trackContents = true): bool - { - $exists = file_exists($path); - - if (!$this->trackResources || $this->inVendors($path)) { - return $exists; - } - - if (!$exists) { - $this->addResource(new FileExistenceResource($path)); - - return $exists; - } - - if (is_dir($path)) { - if ($trackContents) { - $this->addResource(new DirectoryResource($path, \is_string($trackContents) ? $trackContents : null)); - } else { - $this->addResource(new GlobResource($path, '/*', false)); - } - } elseif ($trackContents) { - $this->addResource(new FileResource($path)); - } - - return $exists; - } - - /** - * Loads the configuration for an extension. - * - * @param string $extension The extension alias or namespace - * @param array $values An array of values that customizes the extension - * - * @return $this - * - * @throws BadMethodCallException When this ContainerBuilder is compiled - * @throws \LogicException if the extension is not registered - */ - public function loadFromExtension(string $extension, array $values = null) - { - if ($this->isCompiled()) { - throw new BadMethodCallException('Cannot load from an extension on a compiled container.'); - } - - if (\func_num_args() < 2) { - $values = []; - } - - $namespace = $this->getExtension($extension)->getAlias(); - - $this->extensionConfigs[$namespace][] = $values; - - return $this; - } - - /** - * Adds a compiler pass. - * - * @param string $type The type of compiler pass - * @param int $priority Used to sort the passes - * - * @return $this - */ - public function addCompilerPass(CompilerPassInterface $pass, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) - { - $this->getCompiler()->addPass($pass, $type, $priority); - - $this->addObjectResource($pass); - - return $this; - } - - /** - * Returns the compiler pass config which can then be modified. - * - * @return PassConfig The compiler pass config - */ - public function getCompilerPassConfig() - { - return $this->getCompiler()->getPassConfig(); - } - - /** - * Returns the compiler. - * - * @return Compiler The compiler - */ - public function getCompiler() - { - if (null === $this->compiler) { - $this->compiler = new Compiler(); - } - - return $this->compiler; - } - - /** - * Sets a service. - * - * @throws BadMethodCallException When this ContainerBuilder is compiled - */ - public function set(string $id, ?object $service) - { - if ($this->isCompiled() && (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())) { - // setting a synthetic service on a compiled container is alright - throw new BadMethodCallException(sprintf('Setting service "%s" for an unknown or non-synthetic service definition on a compiled container is not allowed.', $id)); - } - - unset($this->definitions[$id], $this->aliasDefinitions[$id], $this->removedIds[$id]); - - parent::set($id, $service); - } - - /** - * Removes a service definition. - */ - public function removeDefinition(string $id) - { - if (isset($this->definitions[$id])) { - unset($this->definitions[$id]); - $this->removedIds[$id] = true; - } - } - - /** - * Returns true if the given service is defined. - * - * @param string $id The service identifier - * - * @return bool true if the service is defined, false otherwise - */ - public function has($id) - { - $id = (string) $id; - - return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id); - } - - /** - * Gets a service. - * - * @param string $id The service identifier - * @param int $invalidBehavior The behavior when the service does not exist - * - * @return object|null The associated service - * - * @throws InvalidArgumentException when no definitions are available - * @throws ServiceCircularReferenceException When a circular reference is detected - * @throws ServiceNotFoundException When the service is not defined - * @throws \Exception - * - * @see Reference - */ - public function get($id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) - { - if ($this->isCompiled() && isset($this->removedIds[$id = (string) $id]) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $invalidBehavior) { - return parent::get($id); - } - - return $this->doGet($id, $invalidBehavior); - } - - private function doGet(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, array &$inlineServices = null, bool $isConstructorArgument = false) - { - if (isset($inlineServices[$id])) { - return $inlineServices[$id]; - } - if (null === $inlineServices) { - $isConstructorArgument = true; - $inlineServices = []; - } - try { - if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior) { - return parent::get($id, $invalidBehavior); - } - if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) { - return $service; - } - } catch (ServiceCircularReferenceException $e) { - if ($isConstructorArgument) { - throw $e; - } - } - - if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) { - $alias = $this->aliasDefinitions[$id]; - - if ($alias->isDeprecated()) { - @trigger_error($alias->getDeprecationMessage($id), E_USER_DEPRECATED); - } - - return $this->doGet((string) $alias, $invalidBehavior, $inlineServices, $isConstructorArgument); - } - - try { - $definition = $this->getDefinition($id); - } catch (ServiceNotFoundException $e) { - if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $invalidBehavior) { - return null; - } - - throw $e; - } - - if ($definition->hasErrors() && $e = $definition->getErrors()) { - throw new RuntimeException(reset($e)); - } - - if ($isConstructorArgument) { - $this->loading[$id] = true; - } - - try { - return $this->createService($definition, $inlineServices, $isConstructorArgument, $id); - } finally { - if ($isConstructorArgument) { - unset($this->loading[$id]); - } - } - } - - /** - * Merges a ContainerBuilder with the current ContainerBuilder configuration. - * - * Service definitions overrides the current defined ones. - * - * But for parameters, they are overridden by the current ones. It allows - * the parameters passed to the container constructor to have precedence - * over the loaded ones. - * - * $container = new ContainerBuilder(new ParameterBag(['foo' => 'bar'])); - * $loader = new LoaderXXX($container); - * $loader->load('resource_name'); - * $container->register('foo', 'stdClass'); - * - * In the above example, even if the loaded resource defines a foo - * parameter, the value will still be 'bar' as defined in the ContainerBuilder - * constructor. - * - * @throws BadMethodCallException When this ContainerBuilder is compiled - */ - public function merge(self $container) - { - if ($this->isCompiled()) { - throw new BadMethodCallException('Cannot merge on a compiled container.'); - } - - $this->addDefinitions($container->getDefinitions()); - $this->addAliases($container->getAliases()); - $this->getParameterBag()->add($container->getParameterBag()->all()); - - if ($this->trackResources) { - foreach ($container->getResources() as $resource) { - $this->addResource($resource); - } - } - - foreach ($this->extensions as $name => $extension) { - if (!isset($this->extensionConfigs[$name])) { - $this->extensionConfigs[$name] = []; - } - - $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name)); - } - - if ($this->getParameterBag() instanceof EnvPlaceholderParameterBag && $container->getParameterBag() instanceof EnvPlaceholderParameterBag) { - $envPlaceholders = $container->getParameterBag()->getEnvPlaceholders(); - $this->getParameterBag()->mergeEnvPlaceholders($container->getParameterBag()); - } else { - $envPlaceholders = []; - } - - foreach ($container->envCounters as $env => $count) { - if (!$count && !isset($envPlaceholders[$env])) { - continue; - } - if (!isset($this->envCounters[$env])) { - $this->envCounters[$env] = $count; - } else { - $this->envCounters[$env] += $count; - } - } - - foreach ($container->getAutoconfiguredInstanceof() as $interface => $childDefinition) { - if (isset($this->autoconfiguredInstanceof[$interface])) { - throw new InvalidArgumentException(sprintf('"%s" has already been autoconfigured and merge() does not support merging autoconfiguration for the same class/interface.', $interface)); - } - - $this->autoconfiguredInstanceof[$interface] = $childDefinition; - } - } - - /** - * Returns the configuration array for the given extension. - * - * @return array An array of configuration - */ - public function getExtensionConfig(string $name) - { - if (!isset($this->extensionConfigs[$name])) { - $this->extensionConfigs[$name] = []; - } - - return $this->extensionConfigs[$name]; - } - - /** - * Prepends a config array to the configs of the given extension. - */ - public function prependExtensionConfig(string $name, array $config) - { - if (!isset($this->extensionConfigs[$name])) { - $this->extensionConfigs[$name] = []; - } - - array_unshift($this->extensionConfigs[$name], $config); - } - - /** - * Compiles the container. - * - * This method passes the container to compiler - * passes whose job is to manipulate and optimize - * the container. - * - * The main compiler passes roughly do four things: - * - * * The extension configurations are merged; - * * Parameter values are resolved; - * * The parameter bag is frozen; - * * Extension loading is disabled. - * - * @param bool $resolveEnvPlaceholders Whether %env()% parameters should be resolved using the current - * env vars or be replaced by uniquely identifiable placeholders. - * Set to "true" when you want to use the current ContainerBuilder - * directly, keep to "false" when the container is dumped instead. - */ - public function compile(bool $resolveEnvPlaceholders = false) - { - $compiler = $this->getCompiler(); - - if ($this->trackResources) { - foreach ($compiler->getPassConfig()->getPasses() as $pass) { - $this->addObjectResource($pass); - } - } - $bag = $this->getParameterBag(); - - if ($resolveEnvPlaceholders && $bag instanceof EnvPlaceholderParameterBag) { - $compiler->addPass(new ResolveEnvPlaceholdersPass(), PassConfig::TYPE_AFTER_REMOVING, -1000); - } - - $compiler->compile($this); - - foreach ($this->definitions as $id => $definition) { - if ($this->trackResources && $definition->isLazy()) { - $this->getReflectionClass($definition->getClass()); - } - } - - $this->extensionConfigs = []; - - if ($bag instanceof EnvPlaceholderParameterBag) { - if ($resolveEnvPlaceholders) { - $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true)); - } - - $this->envPlaceholders = $bag->getEnvPlaceholders(); - } - - parent::compile(); - - foreach ($this->definitions + $this->aliasDefinitions as $id => $definition) { - if (!$definition->isPublic() || $definition->isPrivate()) { - $this->removedIds[$id] = true; - } - } - } - - /** - * {@inheritdoc} - */ - public function getServiceIds() - { - return array_map('strval', array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds()))); - } - - /** - * Gets removed service or alias ids. - * - * @return array - */ - public function getRemovedIds() - { - return $this->removedIds; - } - - /** - * Adds the service aliases. - */ - public function addAliases(array $aliases) - { - foreach ($aliases as $alias => $id) { - $this->setAlias($alias, $id); - } - } - - /** - * Sets the service aliases. - */ - public function setAliases(array $aliases) - { - $this->aliasDefinitions = []; - $this->addAliases($aliases); - } - - /** - * Sets an alias for an existing service. - * - * @param string $alias The alias to create - * @param string|Alias $id The service to alias - * - * @return Alias - * - * @throws InvalidArgumentException if the id is not a string or an Alias - * @throws InvalidArgumentException if the alias is for itself - */ - public function setAlias(string $alias, $id) - { - if ('' === $alias || '\\' === $alias[-1] || \strlen($alias) !== strcspn($alias, "\0\r\n'")) { - throw new InvalidArgumentException(sprintf('Invalid alias id: "%s"', $alias)); - } - - if (\is_string($id)) { - $id = new Alias($id); - } elseif (!$id instanceof Alias) { - throw new InvalidArgumentException('$id must be a string, or an Alias object.'); - } - - if ($alias === (string) $id) { - throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias)); - } - - unset($this->definitions[$alias], $this->removedIds[$alias]); - - return $this->aliasDefinitions[$alias] = $id; - } - - /** - * Removes an alias. - * - * @param string $alias The alias to remove - */ - public function removeAlias(string $alias) - { - if (isset($this->aliasDefinitions[$alias])) { - unset($this->aliasDefinitions[$alias]); - $this->removedIds[$alias] = true; - } - } - - /** - * Returns true if an alias exists under the given identifier. - * - * @return bool true if the alias exists, false otherwise - */ - public function hasAlias(string $id) - { - return isset($this->aliasDefinitions[$id]); - } - - /** - * Gets all defined aliases. - * - * @return Alias[] An array of aliases - */ - public function getAliases() - { - return $this->aliasDefinitions; - } - - /** - * Gets an alias. - * - * @return Alias An Alias instance - * - * @throws InvalidArgumentException if the alias does not exist - */ - public function getAlias(string $id) - { - if (!isset($this->aliasDefinitions[$id])) { - throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id)); - } - - return $this->aliasDefinitions[$id]; - } - - /** - * Registers a service definition. - * - * This methods allows for simple registration of service definition - * with a fluid interface. - * - * @return Definition A Definition instance - */ - public function register(string $id, string $class = null) - { - return $this->setDefinition($id, new Definition($class)); - } - - /** - * Registers an autowired service definition. - * - * This method implements a shortcut for using setDefinition() with - * an autowired definition. - * - * @return Definition The created definition - */ - public function autowire(string $id, string $class = null) - { - return $this->setDefinition($id, (new Definition($class))->setAutowired(true)); - } - - /** - * Adds the service definitions. - * - * @param Definition[] $definitions An array of service definitions - */ - public function addDefinitions(array $definitions) - { - foreach ($definitions as $id => $definition) { - $this->setDefinition($id, $definition); - } - } - - /** - * Sets the service definitions. - * - * @param Definition[] $definitions An array of service definitions - */ - public function setDefinitions(array $definitions) - { - $this->definitions = []; - $this->addDefinitions($definitions); - } - - /** - * Gets all service definitions. - * - * @return Definition[] An array of Definition instances - */ - public function getDefinitions() - { - return $this->definitions; - } - - /** - * Sets a service definition. - * - * @return Definition the service definition - * - * @throws BadMethodCallException When this ContainerBuilder is compiled - */ - public function setDefinition(string $id, Definition $definition) - { - if ($this->isCompiled()) { - throw new BadMethodCallException('Adding definition to a compiled container is not allowed'); - } - - if ('' === $id || '\\' === $id[-1] || \strlen($id) !== strcspn($id, "\0\r\n'")) { - throw new InvalidArgumentException(sprintf('Invalid service id: "%s"', $id)); - } - - unset($this->aliasDefinitions[$id], $this->removedIds[$id]); - - return $this->definitions[$id] = $definition; - } - - /** - * Returns true if a service definition exists under the given identifier. - * - * @return bool true if the service definition exists, false otherwise - */ - public function hasDefinition(string $id) - { - return isset($this->definitions[$id]); - } - - /** - * Gets a service definition. - * - * @return Definition A Definition instance - * - * @throws ServiceNotFoundException if the service definition does not exist - */ - public function getDefinition(string $id) - { - if (!isset($this->definitions[$id])) { - throw new ServiceNotFoundException($id); - } - - return $this->definitions[$id]; - } - - /** - * Gets a service definition by id or alias. - * - * The method "unaliases" recursively to return a Definition instance. - * - * @return Definition A Definition instance - * - * @throws ServiceNotFoundException if the service definition does not exist - */ - public function findDefinition(string $id) - { - $seen = []; - while (isset($this->aliasDefinitions[$id])) { - $id = (string) $this->aliasDefinitions[$id]; - - if (isset($seen[$id])) { - $seen = array_values($seen); - $seen = \array_slice($seen, array_search($id, $seen)); - $seen[] = $id; - - throw new ServiceCircularReferenceException($id, $seen); - } - - $seen[$id] = $id; - } - - return $this->getDefinition($id); - } - - /** - * Creates a service for a service definition. - * - * @return mixed The service described by the service definition - * - * @throws RuntimeException When the factory definition is incomplete - * @throws RuntimeException When the service is a synthetic service - * @throws InvalidArgumentException When configure callable is not callable - */ - private function createService(Definition $definition, array &$inlineServices, bool $isConstructorArgument = false, string $id = null, bool $tryProxy = true) - { - if (null === $id && isset($inlineServices[$h = spl_object_hash($definition)])) { - return $inlineServices[$h]; - } - - if ($definition instanceof ChildDefinition) { - throw new RuntimeException(sprintf('Constructing service "%s" from a parent definition is not supported at build time.', $id)); - } - - if ($definition->isSynthetic()) { - throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id)); - } - - if ($definition->isDeprecated()) { - @trigger_error($definition->getDeprecationMessage($id), E_USER_DEPRECATED); - } - - if ($tryProxy && $definition->isLazy() && !$tryProxy = !($proxy = $this->proxyInstantiator) || $proxy instanceof RealServiceInstantiator) { - $proxy = $proxy->instantiateProxy( - $this, - $definition, - $id, function () use ($definition, &$inlineServices, $id) { - return $this->createService($definition, $inlineServices, true, $id, false); - } - ); - $this->shareService($definition, $proxy, $id, $inlineServices); - - return $proxy; - } - - $parameterBag = $this->getParameterBag(); - - if (null !== $definition->getFile()) { - require_once $parameterBag->resolveValue($definition->getFile()); - } - - $arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlineServices, $isConstructorArgument); - - if (null !== $factory = $definition->getFactory()) { - if (\is_array($factory)) { - $factory = [$this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlineServices, $isConstructorArgument), $factory[1]]; - } elseif (!\is_string($factory)) { - throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id)); - } - } - - if (null !== $id && $definition->isShared() && isset($this->services[$id]) && ($tryProxy || !$definition->isLazy())) { - return $this->services[$id]; - } - - if (null !== $factory) { - $service = $factory(...$arguments); - - if (!$definition->isDeprecated() && \is_array($factory) && \is_string($factory[0])) { - $r = new \ReflectionClass($factory[0]); - - if (0 < strpos($r->getDocComment(), "\n * @deprecated ")) { - @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" factory class. It should either be deprecated or its factory upgraded.', $id, $r->name), E_USER_DEPRECATED); - } - } - } else { - $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass())); - - $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); - - if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) { - @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name), E_USER_DEPRECATED); - } - } - - $lastWitherIndex = null; - foreach ($definition->getMethodCalls() as $k => $call) { - if ($call[2] ?? false) { - $lastWitherIndex = $k; - } - } - - if (null === $lastWitherIndex && ($tryProxy || !$definition->isLazy())) { - // share only if proxying failed, or if not a proxy, and if no withers are found - $this->shareService($definition, $service, $id, $inlineServices); - } - - $properties = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())), $inlineServices); - foreach ($properties as $name => $value) { - $service->$name = $value; - } - - foreach ($definition->getMethodCalls() as $k => $call) { - $service = $this->callMethod($service, $call, $inlineServices); - - if ($lastWitherIndex === $k && ($tryProxy || !$definition->isLazy())) { - // share only if proxying failed, or if not a proxy, and this is the last wither - $this->shareService($definition, $service, $id, $inlineServices); - } - } - - if ($callable = $definition->getConfigurator()) { - if (\is_array($callable)) { - $callable[0] = $parameterBag->resolveValue($callable[0]); - - if ($callable[0] instanceof Reference) { - $callable[0] = $this->doGet((string) $callable[0], $callable[0]->getInvalidBehavior(), $inlineServices); - } elseif ($callable[0] instanceof Definition) { - $callable[0] = $this->createService($callable[0], $inlineServices); - } - } - - if (!\is_callable($callable)) { - throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', \get_class($service))); - } - - $callable($service); - } - - return $service; - } - - /** - * Replaces service references by the real service instance and evaluates expressions. - * - * @param mixed $value A value - * - * @return mixed The same value with all service references replaced by - * the real service instances and all expressions evaluated - */ - public function resolveServices($value) - { - return $this->doResolveServices($value); - } - - private function doResolveServices($value, array &$inlineServices = [], bool $isConstructorArgument = false) - { - if (\is_array($value)) { - foreach ($value as $k => $v) { - $value[$k] = $this->doResolveServices($v, $inlineServices, $isConstructorArgument); - } - } elseif ($value instanceof ServiceClosureArgument) { - $reference = $value->getValues()[0]; - $value = function () use ($reference) { - return $this->resolveServices($reference); - }; - } elseif ($value instanceof IteratorArgument) { - $value = new RewindableGenerator(function () use ($value) { - foreach ($value->getValues() as $k => $v) { - foreach (self::getServiceConditionals($v) as $s) { - if (!$this->has($s)) { - continue 2; - } - } - foreach (self::getInitializedConditionals($v) as $s) { - if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { - continue 2; - } - } - - yield $k => $this->resolveServices($v); - } - }, function () use ($value): int { - $count = 0; - foreach ($value->getValues() as $v) { - foreach (self::getServiceConditionals($v) as $s) { - if (!$this->has($s)) { - continue 2; - } - } - foreach (self::getInitializedConditionals($v) as $s) { - if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { - continue 2; - } - } - - ++$count; - } - - return $count; - }); - } elseif ($value instanceof ServiceLocatorArgument) { - $refs = $types = []; - foreach ($value->getValues() as $k => $v) { - if ($v) { - $refs[$k] = [$v]; - $types[$k] = $v instanceof TypedReference ? $v->getType() : '?'; - } - } - $value = new ServiceLocator(\Closure::fromCallable([$this, 'resolveServices']), $refs, $types); - } elseif ($value instanceof Reference) { - $value = $this->doGet((string) $value, $value->getInvalidBehavior(), $inlineServices, $isConstructorArgument); - } elseif ($value instanceof Definition) { - $value = $this->createService($value, $inlineServices, $isConstructorArgument); - } elseif ($value instanceof Parameter) { - $value = $this->getParameter((string) $value); - } elseif ($value instanceof Expression) { - $value = $this->getExpressionLanguage()->evaluate($value, ['container' => $this]); - } - - return $value; - } - - /** - * Returns service ids for a given tag. - * - * Example: - * - * $container->register('foo')->addTag('my.tag', ['hello' => 'world']); - * - * $serviceIds = $container->findTaggedServiceIds('my.tag'); - * foreach ($serviceIds as $serviceId => $tags) { - * foreach ($tags as $tag) { - * echo $tag['hello']; - * } - * } - * - * @return array An array of tags with the tagged service as key, holding a list of attribute arrays - */ - public function findTaggedServiceIds(string $name, bool $throwOnAbstract = false) - { - $this->usedTags[] = $name; - $tags = []; - foreach ($this->getDefinitions() as $id => $definition) { - if ($definition->hasTag($name)) { - if ($throwOnAbstract && $definition->isAbstract()) { - throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must not be abstract.', $id, $name)); - } - $tags[$id] = $definition->getTag($name); - } - } - - return $tags; - } - - /** - * Returns all tags the defined services use. - * - * @return array An array of tags - */ - public function findTags() - { - $tags = []; - foreach ($this->getDefinitions() as $id => $definition) { - $tags = array_merge(array_keys($definition->getTags()), $tags); - } - - return array_unique($tags); - } - - /** - * Returns all tags not queried by findTaggedServiceIds. - * - * @return string[] An array of tags - */ - public function findUnusedTags() - { - return array_values(array_diff($this->findTags(), $this->usedTags)); - } - - public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) - { - $this->expressionLanguageProviders[] = $provider; - } - - /** - * @return ExpressionFunctionProviderInterface[] - */ - public function getExpressionLanguageProviders() - { - return $this->expressionLanguageProviders; - } - - /** - * Returns a ChildDefinition that will be used for autoconfiguring the interface/class. - * - * @return ChildDefinition - */ - public function registerForAutoconfiguration(string $interface) - { - if (!isset($this->autoconfiguredInstanceof[$interface])) { - $this->autoconfiguredInstanceof[$interface] = new ChildDefinition(''); - } - - return $this->autoconfiguredInstanceof[$interface]; - } - - /** - * Registers an autowiring alias that only binds to a specific argument name. - * - * The argument name is derived from $name if provided (from $id otherwise) - * using camel case: "foo.bar" or "foo_bar" creates an alias bound to - * "$fooBar"-named arguments with $type as type-hint. Such arguments will - * receive the service $id when autowiring is used. - */ - public function registerAliasForArgument(string $id, string $type, string $name = null): Alias - { - $name = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $name ?? $id)))); - - if (!preg_match('/^[a-zA-Z_\x7f-\xff]/', $name)) { - throw new InvalidArgumentException(sprintf('Invalid argument name "%s" for service "%s": the first character must be a letter.', $name, $id)); - } - - return $this->setAlias($type.' $'.$name, $id); - } - - /** - * Returns an array of ChildDefinition[] keyed by interface. - * - * @return ChildDefinition[] - */ - public function getAutoconfiguredInstanceof() - { - return $this->autoconfiguredInstanceof; - } - - /** - * Resolves env parameter placeholders in a string or an array. - * - * @param mixed $value The value to resolve - * @param string|true|null $format A sprintf() format returning the replacement for each env var name or - * null to resolve back to the original "%env(VAR)%" format or - * true to resolve to the actual values of the referenced env vars - * @param array &$usedEnvs Env vars found while resolving are added to this array - * - * @return mixed The value with env parameters resolved if a string or an array is passed - */ - public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs = null) - { - if (null === $format) { - $format = '%%env(%s)%%'; - } - - $bag = $this->getParameterBag(); - if (true === $format) { - $value = $bag->resolveValue($value); - } - - if ($value instanceof Definition) { - $value = (array) $value; - } - - if (\is_array($value)) { - $result = []; - foreach ($value as $k => $v) { - $result[\is_string($k) ? $this->resolveEnvPlaceholders($k, $format, $usedEnvs) : $k] = $this->resolveEnvPlaceholders($v, $format, $usedEnvs); - } - - return $result; - } - - if (!\is_string($value) || 38 > \strlen($value)) { - return $value; - } - $envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders; - - $completed = false; - foreach ($envPlaceholders as $env => $placeholders) { - foreach ($placeholders as $placeholder) { - if (false !== stripos($value, $placeholder)) { - if (true === $format) { - $resolved = $bag->escapeValue($this->getEnv($env)); - } else { - $resolved = sprintf($format, $env); - } - if ($placeholder === $value) { - $value = $resolved; - $completed = true; - } else { - if (!\is_string($resolved) && !is_numeric($resolved)) { - throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "env(%s)" of type %s inside string value "%s".', $env, \gettype($resolved), $this->resolveEnvPlaceholders($value))); - } - $value = str_ireplace($placeholder, $resolved, $value); - } - $usedEnvs[$env] = $env; - $this->envCounters[$env] = isset($this->envCounters[$env]) ? 1 + $this->envCounters[$env] : 1; - - if ($completed) { - break 2; - } - } - } - } - - return $value; - } - - /** - * Get statistics about env usage. - * - * @return int[] The number of time each env vars has been resolved - */ - public function getEnvCounters() - { - $bag = $this->getParameterBag(); - $envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : $this->envPlaceholders; - - foreach ($envPlaceholders as $env => $placeholders) { - if (!isset($this->envCounters[$env])) { - $this->envCounters[$env] = 0; - } - } - - return $this->envCounters; - } - - /** - * @final - */ - public function log(CompilerPassInterface $pass, string $message) - { - $this->getCompiler()->log($pass, $this->resolveEnvPlaceholders($message)); - } - - /** - * Gets removed binding ids. - * - * @internal - */ - public function getRemovedBindingIds(): array - { - return $this->removedBindingIds; - } - - /** - * Removes bindings for a service. - * - * @internal - */ - public function removeBindings(string $id) - { - if ($this->hasDefinition($id)) { - foreach ($this->getDefinition($id)->getBindings() as $key => $binding) { - list(, $bindingId) = $binding->getValues(); - $this->removedBindingIds[(int) $bindingId] = true; - } - } - } - - /** - * Returns the Service Conditionals. - * - * @param mixed $value An array of conditionals to return - * - * @internal - */ - public static function getServiceConditionals($value): array - { - $services = []; - - if (\is_array($value)) { - foreach ($value as $v) { - $services = array_unique(array_merge($services, self::getServiceConditionals($v))); - } - } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) { - $services[] = (string) $value; - } - - return $services; - } - - /** - * Returns the initialized conditionals. - * - * @param mixed $value An array of conditionals to return - * - * @internal - */ - public static function getInitializedConditionals($value): array - { - $services = []; - - if (\is_array($value)) { - foreach ($value as $v) { - $services = array_unique(array_merge($services, self::getInitializedConditionals($v))); - } - } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()) { - $services[] = (string) $value; - } - - return $services; - } - - /** - * Computes a reasonably unique hash of a value. - * - * @param mixed $value A serializable value - * - * @return string - */ - public static function hash($value) - { - $hash = substr(base64_encode(hash('sha256', serialize($value), true)), 0, 7); - - return str_replace(['/', '+'], ['.', '_'], $hash); - } - - /** - * {@inheritdoc} - */ - protected function getEnv($name) - { - $value = parent::getEnv($name); - $bag = $this->getParameterBag(); - - if (!\is_string($value) || !$bag instanceof EnvPlaceholderParameterBag) { - return $value; - } - - $envPlaceholders = $bag->getEnvPlaceholders(); - if (isset($envPlaceholders[$name][$value])) { - $bag = new ParameterBag($bag->all()); - - return $bag->unescapeValue($bag->get("env($name)")); - } - foreach ($envPlaceholders as $env => $placeholders) { - if (isset($placeholders[$value])) { - return $this->getEnv($env); - } - } - - $this->resolving["env($name)"] = true; - try { - return $bag->unescapeValue($this->resolveEnvPlaceholders($bag->escapeValue($value), true)); - } finally { - unset($this->resolving["env($name)"]); - } - } - - private function callMethod($service, array $call, array &$inlineServices) - { - foreach (self::getServiceConditionals($call[1]) as $s) { - if (!$this->has($s)) { - return $service; - } - } - foreach (self::getInitializedConditionals($call[1]) as $s) { - if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) { - return $service; - } - } - - $result = $service->{$call[0]}(...$this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlineServices)); - - return empty($call[2]) ? $service : $result; - } - - /** - * Shares a given service in the container. - * - * @param mixed $service - */ - private function shareService(Definition $definition, $service, ?string $id, array &$inlineServices) - { - $inlineServices[null !== $id ? $id : spl_object_hash($definition)] = $service; - - if (null !== $id && $definition->isShared()) { - $this->services[$id] = $service; - unset($this->loading[$id]); - } - } - - private function getExpressionLanguage(): ExpressionLanguage - { - if (null === $this->expressionLanguage) { - if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { - throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); - } - - return $this->expressionLanguage; - } - - private function inVendors(string $path): bool - { - if (null === $this->vendors) { - $resource = new ComposerResource(); - $this->vendors = $resource->getVendors(); - $this->addResource($resource); - } - $path = realpath($path) ?: $path; - - foreach ($this->vendors as $vendor) { - if (0 === strpos($path, $vendor) && false !== strpbrk(substr($path, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) { - return true; - } - } - - return false; - } -} diff --git a/vendor/symfony/dependency-injection/ContainerInterface.php b/vendor/symfony/dependency-injection/ContainerInterface.php deleted file mode 100644 index 616648f..0000000 --- a/vendor/symfony/dependency-injection/ContainerInterface.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Psr\Container\ContainerInterface as PsrContainerInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; - -/** - * ContainerInterface is the interface implemented by service container classes. - * - * @author Fabien Potencier - * @author Johannes M. Schmitt - */ -interface ContainerInterface extends PsrContainerInterface -{ - const RUNTIME_EXCEPTION_ON_INVALID_REFERENCE = 0; - const EXCEPTION_ON_INVALID_REFERENCE = 1; - const NULL_ON_INVALID_REFERENCE = 2; - const IGNORE_ON_INVALID_REFERENCE = 3; - const IGNORE_ON_UNINITIALIZED_REFERENCE = 4; - - /** - * Sets a service. - */ - public function set(string $id, ?object $service); - - /** - * Gets a service. - * - * @param string $id The service identifier - * @param int $invalidBehavior The behavior when the service does not exist - * - * @return object|null The associated service - * - * @throws ServiceCircularReferenceException When a circular reference is detected - * @throws ServiceNotFoundException When the service is not defined - * - * @see Reference - */ - public function get($id, int $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE); - - /** - * Returns true if the given service is defined. - * - * @param string $id The service identifier - * - * @return bool true if the service is defined, false otherwise - */ - public function has($id); - - /** - * Check for whether or not a service has been initialized. - * - * @return bool true if the service has been initialized, false otherwise - */ - public function initialized(string $id); - - /** - * Gets a parameter. - * - * @param string $name The parameter name - * - * @return mixed The parameter value - * - * @throws InvalidArgumentException if the parameter is not defined - */ - public function getParameter(string $name); - - /** - * Checks if a parameter exists. - * - * @param string $name The parameter name - * - * @return bool The presence of parameter in container - */ - public function hasParameter(string $name); - - /** - * Sets a parameter. - * - * @param string $name The parameter name - * @param mixed $value The parameter value - */ - public function setParameter(string $name, $value); -} diff --git a/vendor/symfony/dependency-injection/Definition.php b/vendor/symfony/dependency-injection/Definition.php deleted file mode 100644 index 83b7cd2..0000000 --- a/vendor/symfony/dependency-injection/Definition.php +++ /dev/null @@ -1,890 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\BoundArgument; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; - -/** - * Definition represents a service definition. - * - * @author Fabien Potencier - */ -class Definition -{ - private $class; - private $file; - private $factory; - private $shared = true; - private $deprecated = false; - private $deprecationTemplate; - private $properties = []; - private $calls = []; - private $instanceof = []; - private $autoconfigured = false; - private $configurator; - private $tags = []; - private $public = true; - private $private = true; - private $synthetic = false; - private $abstract = false; - private $lazy = false; - private $decoratedService; - private $autowired = false; - private $changes = []; - private $bindings = []; - private $errors = []; - - protected $arguments = []; - - private static $defaultDeprecationTemplate = 'The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.'; - - /** - * @internal - * - * Used to store the name of the inner id when using service decoration together with autowiring - */ - public $innerServiceId; - - /** - * @internal - * - * Used to store the behavior to follow when using service decoration and the decorated service is invalid - */ - public $decorationOnInvalid; - - public function __construct(string $class = null, array $arguments = []) - { - if (null !== $class) { - $this->setClass($class); - } - $this->arguments = $arguments; - } - - /** - * Returns all changes tracked for the Definition object. - * - * @return array An array of changes for this Definition - */ - public function getChanges() - { - return $this->changes; - } - - /** - * Sets the tracked changes for the Definition object. - * - * @param array $changes An array of changes for this Definition - * - * @return $this - */ - public function setChanges(array $changes) - { - $this->changes = $changes; - - return $this; - } - - /** - * Sets a factory. - * - * @param string|array|Reference $factory A PHP function, reference or an array containing a class/Reference and a method to call - * - * @return $this - */ - public function setFactory($factory) - { - $this->changes['factory'] = true; - - if (\is_string($factory) && false !== strpos($factory, '::')) { - $factory = explode('::', $factory, 2); - } elseif ($factory instanceof Reference) { - $factory = [$factory, '__invoke']; - } - - $this->factory = $factory; - - return $this; - } - - /** - * Gets the factory. - * - * @return string|array|null The PHP function or an array containing a class/Reference and a method to call - */ - public function getFactory() - { - return $this->factory; - } - - /** - * Sets the service that this service is decorating. - * - * @param string|null $id The decorated service id, use null to remove decoration - * @param string|null $renamedId The new decorated service id - * - * @return $this - * - * @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals - */ - public function setDecoratedService(?string $id, ?string $renamedId = null, int $priority = 0, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) - { - if ($renamedId && $id === $renamedId) { - throw new InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id)); - } - - $this->changes['decorated_service'] = true; - - if (null === $id) { - $this->decoratedService = null; - } else { - $this->decoratedService = [$id, $renamedId, (int) $priority]; - - if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) { - $this->decoratedService[] = $invalidBehavior; - } - } - - return $this; - } - - /** - * Gets the service that this service is decorating. - * - * @return array|null An array composed of the decorated service id, the new id for it and the priority of decoration, null if no service is decorated - */ - public function getDecoratedService() - { - return $this->decoratedService; - } - - /** - * Sets the service class. - * - * @return $this - */ - public function setClass(?string $class) - { - $this->changes['class'] = true; - - $this->class = $class; - - return $this; - } - - /** - * Gets the service class. - * - * @return string|null The service class - */ - public function getClass() - { - return $this->class; - } - - /** - * Sets the arguments to pass to the service constructor/factory method. - * - * @return $this - */ - public function setArguments(array $arguments) - { - $this->arguments = $arguments; - - return $this; - } - - /** - * Sets the properties to define when creating the service. - * - * @return $this - */ - public function setProperties(array $properties) - { - $this->properties = $properties; - - return $this; - } - - /** - * Gets the properties to define when creating the service. - * - * @return array - */ - public function getProperties() - { - return $this->properties; - } - - /** - * Sets a specific property. - * - * @param mixed $value - * - * @return $this - */ - public function setProperty(string $name, $value) - { - $this->properties[$name] = $value; - - return $this; - } - - /** - * Adds an argument to pass to the service constructor/factory method. - * - * @param mixed $argument An argument - * - * @return $this - */ - public function addArgument($argument) - { - $this->arguments[] = $argument; - - return $this; - } - - /** - * Replaces a specific argument. - * - * @param int|string $index - * @param mixed $argument - * - * @return $this - * - * @throws OutOfBoundsException When the replaced argument does not exist - */ - public function replaceArgument($index, $argument) - { - if (0 === \count($this->arguments)) { - throw new OutOfBoundsException('Cannot replace arguments if none have been configured yet.'); - } - - if (\is_int($index) && ($index < 0 || $index > \count($this->arguments) - 1)) { - throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, \count($this->arguments) - 1)); - } - - if (!\array_key_exists($index, $this->arguments)) { - throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist.', $index)); - } - - $this->arguments[$index] = $argument; - - return $this; - } - - /** - * Sets a specific argument. - * - * @param int|string $key - * @param mixed $value - * - * @return $this - */ - public function setArgument($key, $value) - { - $this->arguments[$key] = $value; - - return $this; - } - - /** - * Gets the arguments to pass to the service constructor/factory method. - * - * @return array The array of arguments - */ - public function getArguments() - { - return $this->arguments; - } - - /** - * Gets an argument to pass to the service constructor/factory method. - * - * @param int|string $index - * - * @return mixed The argument value - * - * @throws OutOfBoundsException When the argument does not exist - */ - public function getArgument($index) - { - if (!\array_key_exists($index, $this->arguments)) { - throw new OutOfBoundsException(sprintf('The argument "%s" doesn\'t exist.', $index)); - } - - return $this->arguments[$index]; - } - - /** - * Sets the methods to call after service initialization. - * - * @return $this - */ - public function setMethodCalls(array $calls = []) - { - $this->calls = []; - foreach ($calls as $call) { - $this->addMethodCall($call[0], $call[1], $call[2] ?? false); - } - - return $this; - } - - /** - * Adds a method to call after service initialization. - * - * @param string $method The method name to call - * @param array $arguments An array of arguments to pass to the method call - * @param bool $returnsClone Whether the call returns the service instance or not - * - * @return $this - * - * @throws InvalidArgumentException on empty $method param - */ - public function addMethodCall(string $method, array $arguments = [], bool $returnsClone = false) - { - if (empty($method)) { - throw new InvalidArgumentException('Method name cannot be empty.'); - } - $this->calls[] = $returnsClone ? [$method, $arguments, true] : [$method, $arguments]; - - return $this; - } - - /** - * Removes a method to call after service initialization. - * - * @return $this - */ - public function removeMethodCall(string $method) - { - foreach ($this->calls as $i => $call) { - if ($call[0] === $method) { - unset($this->calls[$i]); - break; - } - } - - return $this; - } - - /** - * Check if the current definition has a given method to call after service initialization. - * - * @return bool - */ - public function hasMethodCall(string $method) - { - foreach ($this->calls as $call) { - if ($call[0] === $method) { - return true; - } - } - - return false; - } - - /** - * Gets the methods to call after service initialization. - * - * @return array An array of method calls - */ - public function getMethodCalls() - { - return $this->calls; - } - - /** - * Sets the definition templates to conditionally apply on the current definition, keyed by parent interface/class. - * - * @param ChildDefinition[] $instanceof - * - * @return $this - */ - public function setInstanceofConditionals(array $instanceof) - { - $this->instanceof = $instanceof; - - return $this; - } - - /** - * Gets the definition templates to conditionally apply on the current definition, keyed by parent interface/class. - * - * @return ChildDefinition[] - */ - public function getInstanceofConditionals() - { - return $this->instanceof; - } - - /** - * Sets whether or not instanceof conditionals should be prepended with a global set. - * - * @return $this - */ - public function setAutoconfigured(bool $autoconfigured) - { - $this->changes['autoconfigured'] = true; - - $this->autoconfigured = $autoconfigured; - - return $this; - } - - /** - * @return bool - */ - public function isAutoconfigured() - { - return $this->autoconfigured; - } - - /** - * Sets tags for this definition. - * - * @return $this - */ - public function setTags(array $tags) - { - $this->tags = $tags; - - return $this; - } - - /** - * Returns all tags. - * - * @return array An array of tags - */ - public function getTags() - { - return $this->tags; - } - - /** - * Gets a tag by name. - * - * @return array An array of attributes - */ - public function getTag(string $name) - { - return isset($this->tags[$name]) ? $this->tags[$name] : []; - } - - /** - * Adds a tag for this definition. - * - * @return $this - */ - public function addTag(string $name, array $attributes = []) - { - $this->tags[$name][] = $attributes; - - return $this; - } - - /** - * Whether this definition has a tag with the given name. - * - * @return bool - */ - public function hasTag(string $name) - { - return isset($this->tags[$name]); - } - - /** - * Clears all tags for a given name. - * - * @return $this - */ - public function clearTag(string $name) - { - unset($this->tags[$name]); - - return $this; - } - - /** - * Clears the tags for this definition. - * - * @return $this - */ - public function clearTags() - { - $this->tags = []; - - return $this; - } - - /** - * Sets a file to require before creating the service. - * - * @return $this - */ - public function setFile(?string $file) - { - $this->changes['file'] = true; - - $this->file = $file; - - return $this; - } - - /** - * Gets the file to require before creating the service. - * - * @return string|null The full pathname to include - */ - public function getFile() - { - return $this->file; - } - - /** - * Sets if the service must be shared or not. - * - * @return $this - */ - public function setShared(bool $shared) - { - $this->changes['shared'] = true; - - $this->shared = $shared; - - return $this; - } - - /** - * Whether this service is shared. - * - * @return bool - */ - public function isShared() - { - return $this->shared; - } - - /** - * Sets the visibility of this service. - * - * @return $this - */ - public function setPublic(bool $boolean) - { - $this->changes['public'] = true; - - $this->public = $boolean; - $this->private = false; - - return $this; - } - - /** - * Whether this service is public facing. - * - * @return bool - */ - public function isPublic() - { - return $this->public; - } - - /** - * Sets if this service is private. - * - * When set, the "private" state has a higher precedence than "public". - * In version 3.4, a "private" service always remains publicly accessible, - * but triggers a deprecation notice when accessed from the container, - * so that the service can be made really private in 4.0. - * - * @return $this - */ - public function setPrivate(bool $boolean) - { - $this->private = $boolean; - - return $this; - } - - /** - * Whether this service is private. - * - * @return bool - */ - public function isPrivate() - { - return $this->private; - } - - /** - * Sets the lazy flag of this service. - * - * @return $this - */ - public function setLazy(bool $lazy) - { - $this->changes['lazy'] = true; - - $this->lazy = $lazy; - - return $this; - } - - /** - * Whether this service is lazy. - * - * @return bool - */ - public function isLazy() - { - return $this->lazy; - } - - /** - * Sets whether this definition is synthetic, that is not constructed by the - * container, but dynamically injected. - * - * @return $this - */ - public function setSynthetic(bool $boolean) - { - $this->synthetic = $boolean; - - return $this; - } - - /** - * Whether this definition is synthetic, that is not constructed by the - * container, but dynamically injected. - * - * @return bool - */ - public function isSynthetic() - { - return $this->synthetic; - } - - /** - * Whether this definition is abstract, that means it merely serves as a - * template for other definitions. - * - * @return $this - */ - public function setAbstract(bool $boolean) - { - $this->abstract = $boolean; - - return $this; - } - - /** - * Whether this definition is abstract, that means it merely serves as a - * template for other definitions. - * - * @return bool - */ - public function isAbstract() - { - return $this->abstract; - } - - /** - * Whether this definition is deprecated, that means it should not be called - * anymore. - * - * @param string $template Template message to use if the definition is deprecated - * - * @return $this - * - * @throws InvalidArgumentException when the message template is invalid - */ - public function setDeprecated(bool $status = true, string $template = null) - { - if (null !== $template) { - if (preg_match('#[\r\n]|\*/#', $template)) { - throw new InvalidArgumentException('Invalid characters found in deprecation template.'); - } - - if (false === strpos($template, '%service_id%')) { - throw new InvalidArgumentException('The deprecation template must contain the "%service_id%" placeholder.'); - } - - $this->deprecationTemplate = $template; - } - - $this->changes['deprecated'] = true; - - $this->deprecated = $status; - - return $this; - } - - /** - * Whether this definition is deprecated, that means it should not be called - * anymore. - * - * @return bool - */ - public function isDeprecated() - { - return $this->deprecated; - } - - /** - * Message to use if this definition is deprecated. - * - * @param string $id Service id relying on this definition - * - * @return string - */ - public function getDeprecationMessage(string $id) - { - return str_replace('%service_id%', $id, $this->deprecationTemplate ?: self::$defaultDeprecationTemplate); - } - - /** - * Sets a configurator to call after the service is fully initialized. - * - * @param string|array|Reference $configurator A PHP function, reference or an array containing a class/Reference and a method to call - * - * @return $this - */ - public function setConfigurator($configurator) - { - $this->changes['configurator'] = true; - - if (\is_string($configurator) && false !== strpos($configurator, '::')) { - $configurator = explode('::', $configurator, 2); - } elseif ($configurator instanceof Reference) { - $configurator = [$configurator, '__invoke']; - } - - $this->configurator = $configurator; - - return $this; - } - - /** - * Gets the configurator to call after the service is fully initialized. - * - * @return callable|array|null - */ - public function getConfigurator() - { - return $this->configurator; - } - - /** - * Is the definition autowired? - * - * @return bool - */ - public function isAutowired() - { - return $this->autowired; - } - - /** - * Enables/disables autowiring. - * - * @return $this - */ - public function setAutowired(bool $autowired) - { - $this->changes['autowired'] = true; - - $this->autowired = $autowired; - - return $this; - } - - /** - * Gets bindings. - * - * @return array|BoundArgument[] - */ - public function getBindings() - { - return $this->bindings; - } - - /** - * Sets bindings. - * - * Bindings map $named or FQCN arguments to values that should be - * injected in the matching parameters (of the constructor, of methods - * called and of controller actions). - * - * @return $this - */ - public function setBindings(array $bindings) - { - foreach ($bindings as $key => $binding) { - if (0 < strpos($key, '$') && $key !== $k = preg_replace('/[ \t]*\$/', ' $', $key)) { - unset($bindings[$key]); - $bindings[$key = $k] = $binding; - } - if (!$binding instanceof BoundArgument) { - $bindings[$key] = new BoundArgument($binding); - } - } - - $this->bindings = $bindings; - - return $this; - } - - /** - * Add an error that occurred when building this Definition. - * - * @param string|\Closure|self $error - * - * @return $this - */ - public function addError($error) - { - if ($error instanceof self) { - $this->errors = array_merge($this->errors, $error->errors); - } else { - $this->errors[] = $error; - } - - return $this; - } - - /** - * Returns any errors that occurred while building this Definition. - * - * @return array - */ - public function getErrors() - { - foreach ($this->errors as $i => $error) { - if ($error instanceof \Closure) { - $this->errors[$i] = (string) $error(); - } elseif (!\is_string($error)) { - $this->errors[$i] = (string) $error; - } - } - - return $this->errors; - } - - public function hasErrors(): bool - { - return (bool) $this->errors; - } -} diff --git a/vendor/symfony/dependency-injection/Dumper/Dumper.php b/vendor/symfony/dependency-injection/Dumper/Dumper.php deleted file mode 100644 index e7407b0..0000000 --- a/vendor/symfony/dependency-injection/Dumper/Dumper.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Dumper is the abstract class for all built-in dumpers. - * - * @author Fabien Potencier - */ -abstract class Dumper implements DumperInterface -{ - protected $container; - - public function __construct(ContainerBuilder $container) - { - $this->container = $container; - } -} diff --git a/vendor/symfony/dependency-injection/Dumper/DumperInterface.php b/vendor/symfony/dependency-injection/Dumper/DumperInterface.php deleted file mode 100644 index 8abc192..0000000 --- a/vendor/symfony/dependency-injection/Dumper/DumperInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -/** - * DumperInterface is the interface implemented by service container dumper classes. - * - * @author Fabien Potencier - */ -interface DumperInterface -{ - /** - * Dumps the service container. - * - * @return string|array The representation of the service container - */ - public function dump(array $options = []); -} diff --git a/vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php b/vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php deleted file mode 100644 index c21dd91..0000000 --- a/vendor/symfony/dependency-injection/Dumper/GraphvizDumper.php +++ /dev/null @@ -1,251 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\DependencyInjection\Reference; - -/** - * GraphvizDumper dumps a service container as a graphviz file. - * - * You can convert the generated dot file with the dot utility (http://www.graphviz.org/): - * - * dot -Tpng container.dot > foo.png - * - * @author Fabien Potencier - */ -class GraphvizDumper extends Dumper -{ - private $nodes; - private $edges; - private $options = [ - 'graph' => ['ratio' => 'compress'], - 'node' => ['fontsize' => 11, 'fontname' => 'Arial', 'shape' => 'record'], - 'edge' => ['fontsize' => 9, 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => 0.5], - 'node.instance' => ['fillcolor' => '#9999ff', 'style' => 'filled'], - 'node.definition' => ['fillcolor' => '#eeeeee'], - 'node.missing' => ['fillcolor' => '#ff9999', 'style' => 'filled'], - ]; - - /** - * Dumps the service container as a graphviz graph. - * - * Available options: - * - * * graph: The default options for the whole graph - * * node: The default options for nodes - * * edge: The default options for edges - * * node.instance: The default options for services that are defined directly by object instances - * * node.definition: The default options for services that are defined via service definition instances - * * node.missing: The default options for missing services - * - * @return string The dot representation of the service container - */ - public function dump(array $options = []) - { - foreach (['graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing'] as $key) { - if (isset($options[$key])) { - $this->options[$key] = array_merge($this->options[$key], $options[$key]); - } - } - - $this->nodes = $this->findNodes(); - - $this->edges = []; - foreach ($this->container->getDefinitions() as $id => $definition) { - $this->edges[$id] = array_merge( - $this->findEdges($id, $definition->getArguments(), true, ''), - $this->findEdges($id, $definition->getProperties(), false, '') - ); - - foreach ($definition->getMethodCalls() as $call) { - $this->edges[$id] = array_merge( - $this->edges[$id], - $this->findEdges($id, $call[1], false, $call[0].'()') - ); - } - } - - return $this->container->resolveEnvPlaceholders($this->startDot().$this->addNodes().$this->addEdges().$this->endDot(), '__ENV_%s__'); - } - - private function addNodes(): string - { - $code = ''; - foreach ($this->nodes as $id => $node) { - $aliases = $this->getAliases($id); - - $code .= sprintf(" node_%s [label=\"%s\\n%s\\n\", shape=%s%s];\n", $this->dotize($id), $id.($aliases ? ' ('.implode(', ', $aliases).')' : ''), $node['class'], $this->options['node']['shape'], $this->addAttributes($node['attributes'])); - } - - return $code; - } - - private function addEdges(): string - { - $code = ''; - foreach ($this->edges as $id => $edges) { - foreach ($edges as $edge) { - $code .= sprintf(" node_%s -> node_%s [label=\"%s\" style=\"%s\"%s];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed', $edge['lazy'] ? ' color="#9999ff"' : ''); - } - } - - return $code; - } - - /** - * Finds all edges belonging to a specific service id. - */ - private function findEdges(string $id, array $arguments, bool $required, string $name, bool $lazy = false): array - { - $edges = []; - foreach ($arguments as $argument) { - if ($argument instanceof Parameter) { - $argument = $this->container->hasParameter($argument) ? $this->container->getParameter($argument) : null; - } elseif (\is_string($argument) && preg_match('/^%([^%]+)%$/', $argument, $match)) { - $argument = $this->container->hasParameter($match[1]) ? $this->container->getParameter($match[1]) : null; - } - - if ($argument instanceof Reference) { - $lazyEdge = $lazy; - - if (!$this->container->has((string) $argument)) { - $this->nodes[(string) $argument] = ['name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']]; - } elseif ('service_container' !== (string) $argument) { - $lazyEdge = $lazy || $this->container->getDefinition((string) $argument)->isLazy(); - } - - $edges[] = ['name' => $name, 'required' => $required, 'to' => $argument, 'lazy' => $lazyEdge]; - } elseif ($argument instanceof ArgumentInterface) { - $edges = array_merge($edges, $this->findEdges($id, $argument->getValues(), $required, $name, true)); - } elseif ($argument instanceof Definition) { - $edges = array_merge($edges, - $this->findEdges($id, $argument->getArguments(), $required, ''), - $this->findEdges($id, $argument->getProperties(), false, '') - ); - foreach ($argument->getMethodCalls() as $call) { - $edges = array_merge($edges, $this->findEdges($id, $call[1], false, $call[0].'()')); - } - } elseif (\is_array($argument)) { - $edges = array_merge($edges, $this->findEdges($id, $argument, $required, $name, $lazy)); - } - } - - return $edges; - } - - private function findNodes(): array - { - $nodes = []; - - $container = $this->cloneContainer(); - - foreach ($container->getDefinitions() as $id => $definition) { - $class = $definition->getClass(); - - if ('\\' === substr($class, 0, 1)) { - $class = substr($class, 1); - } - - try { - $class = $this->container->getParameterBag()->resolveValue($class); - } catch (ParameterNotFoundException $e) { - } - - $nodes[$id] = ['class' => str_replace('\\', '\\\\', $class), 'attributes' => array_merge($this->options['node.definition'], ['style' => $definition->isShared() ? 'filled' : 'dotted'])]; - $container->setDefinition($id, new Definition('stdClass')); - } - - foreach ($container->getServiceIds() as $id) { - if (\array_key_exists($id, $container->getAliases())) { - continue; - } - - if (!$container->hasDefinition($id)) { - $nodes[$id] = ['class' => str_replace('\\', '\\\\', \get_class($container->get($id))), 'attributes' => $this->options['node.instance']]; - } - } - - return $nodes; - } - - private function cloneContainer(): ContainerBuilder - { - $parameterBag = new ParameterBag($this->container->getParameterBag()->all()); - - $container = new ContainerBuilder($parameterBag); - $container->setDefinitions($this->container->getDefinitions()); - $container->setAliases($this->container->getAliases()); - $container->setResources($this->container->getResources()); - foreach ($this->container->getExtensions() as $extension) { - $container->registerExtension($extension); - } - - return $container; - } - - private function startDot(): string - { - return sprintf("digraph sc {\n %s\n node [%s];\n edge [%s];\n\n", - $this->addOptions($this->options['graph']), - $this->addOptions($this->options['node']), - $this->addOptions($this->options['edge']) - ); - } - - private function endDot(): string - { - return "}\n"; - } - - private function addAttributes(array $attributes): string - { - $code = []; - foreach ($attributes as $k => $v) { - $code[] = sprintf('%s="%s"', $k, $v); - } - - return $code ? ', '.implode(', ', $code) : ''; - } - - private function addOptions(array $options): string - { - $code = []; - foreach ($options as $k => $v) { - $code[] = sprintf('%s="%s"', $k, $v); - } - - return implode(' ', $code); - } - - private function dotize(string $id): string - { - return preg_replace('/\W/i', '_', $id); - } - - private function getAliases(string $id): array - { - $aliases = []; - foreach ($this->container->getAliases() as $alias => $origin) { - if ($id == $origin) { - $aliases[] = $alias; - } - } - - return $aliases; - } -} diff --git a/vendor/symfony/dependency-injection/Dumper/PhpDumper.php b/vendor/symfony/dependency-injection/Dumper/PhpDumper.php deleted file mode 100644 index b0dd269..0000000 --- a/vendor/symfony/dependency-injection/Dumper/PhpDumper.php +++ /dev/null @@ -1,2064 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -use Composer\Autoload\ClassLoader; -use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader; -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocator; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass; -use Symfony\Component\DependencyInjection\Compiler\CheckCircularReferencesPass; -use Symfony\Component\DependencyInjection\Compiler\ServiceReferenceGraphEdge; -use Symfony\Component\DependencyInjection\Compiler\ServiceReferenceGraphNode; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\EnvParameterException; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\ExpressionLanguage; -use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper; -use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; -use Symfony\Component\DependencyInjection\Loader\FileLoader; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ServiceLocator as BaseServiceLocator; -use Symfony\Component\DependencyInjection\TypedReference; -use Symfony\Component\DependencyInjection\Variable; -use Symfony\Component\ErrorHandler\DebugClassLoader; -use Symfony\Component\ExpressionLanguage\Expression; -use Symfony\Component\HttpKernel\Kernel; - -/** - * PhpDumper dumps a service container as a PHP class. - * - * @author Fabien Potencier - * @author Johannes M. Schmitt - */ -class PhpDumper extends Dumper -{ - /** - * Characters that might appear in the generated variable name as first character. - */ - const FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz'; - - /** - * Characters that might appear in the generated variable name as any but the first character. - */ - const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_'; - - private $definitionVariables; - private $referenceVariables; - private $variableCount; - private $inlinedDefinitions; - private $serviceCalls; - private $reservedVariables = ['instance', 'class', 'this']; - private $expressionLanguage; - private $targetDirRegex; - private $targetDirMaxMatches; - private $docStar; - private $serviceIdToMethodNameMap; - private $usedMethodNames; - private $namespace; - private $asFiles; - private $hotPathTag; - private $inlineFactories; - private $inlineRequires; - private $inlinedRequires = []; - private $circularReferences = []; - private $singleUsePrivateIds = []; - private $addThrow = false; - private $addGetService = false; - private $locatedIds = []; - private $serviceLocatorTag; - private $exportedVariables = []; - private $baseClass; - - /** - * @var ProxyDumper - */ - private $proxyDumper; - - /** - * {@inheritdoc} - */ - public function __construct(ContainerBuilder $container) - { - if (!$container->isCompiled()) { - throw new LogicException('Cannot dump an uncompiled container.'); - } - - parent::__construct($container); - } - - /** - * Sets the dumper to be used when dumping proxies in the generated container. - */ - public function setProxyDumper(ProxyDumper $proxyDumper) - { - $this->proxyDumper = $proxyDumper; - } - - /** - * Dumps the service container as a PHP class. - * - * Available options: - * - * * class: The class name - * * base_class: The base class name - * * namespace: The class namespace - * * as_files: To split the container in several files - * - * @return string|array A PHP class representing the service container or an array of PHP files if the "as_files" option is set - * - * @throws EnvParameterException When an env var exists but has not been dumped - */ - public function dump(array $options = []) - { - $this->locatedIds = []; - $this->targetDirRegex = null; - $this->inlinedRequires = []; - $this->exportedVariables = []; - $options = array_merge([ - 'class' => 'ProjectServiceContainer', - 'base_class' => 'Container', - 'namespace' => '', - 'as_files' => false, - 'debug' => true, - 'hot_path_tag' => 'container.hot_path', - 'inline_factories_parameter' => 'container.dumper.inline_factories', - 'inline_class_loader_parameter' => 'container.dumper.inline_class_loader', - 'service_locator_tag' => 'container.service_locator', - 'build_time' => time(), - ], $options); - - $this->addThrow = $this->addGetService = false; - $this->namespace = $options['namespace']; - $this->asFiles = $options['as_files']; - $this->hotPathTag = $options['hot_path_tag']; - $this->inlineFactories = $this->asFiles && $options['inline_factories_parameter'] && $this->container->hasParameter($options['inline_factories_parameter']) && $this->container->getParameter($options['inline_factories_parameter']); - $this->inlineRequires = $options['inline_class_loader_parameter'] && $this->container->hasParameter($options['inline_class_loader_parameter']) && $this->container->getParameter($options['inline_class_loader_parameter']); - $this->serviceLocatorTag = $options['service_locator_tag']; - - if (0 !== strpos($baseClass = $options['base_class'], '\\') && 'Container' !== $baseClass) { - $baseClass = sprintf('%s\%s', $options['namespace'] ? '\\'.$options['namespace'] : '', $baseClass); - $this->baseClass = $baseClass; - } elseif ('Container' === $baseClass) { - $this->baseClass = Container::class; - } else { - $this->baseClass = $baseClass; - } - - $this->initializeMethodNamesMap('Container' === $baseClass ? Container::class : $baseClass); - - if ($this->getProxyDumper() instanceof NullDumper) { - (new AnalyzeServiceReferencesPass(true, false))->process($this->container); - try { - (new CheckCircularReferencesPass())->process($this->container); - } catch (ServiceCircularReferenceException $e) { - $path = $e->getPath(); - end($path); - $path[key($path)] .= '". Try running "composer require symfony/proxy-manager-bridge'; - - throw new ServiceCircularReferenceException($e->getServiceId(), $path); - } - } - - (new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->process($this->container); - $checkedNodes = []; - $this->circularReferences = []; - $this->singleUsePrivateIds = []; - foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) { - if (!$node->getValue() instanceof Definition) { - continue; - } - if (!isset($checkedNodes[$id])) { - $this->analyzeCircularReferences($id, $node->getOutEdges(), $checkedNodes); - } - if ($this->isSingleUsePrivateNode($node)) { - $this->singleUsePrivateIds[$id] = $id; - } - } - $this->container->getCompiler()->getServiceReferenceGraph()->clear(); - $checkedNodes = []; - $this->singleUsePrivateIds = array_diff_key($this->singleUsePrivateIds, $this->circularReferences); - - $this->docStar = $options['debug'] ? '*' : ''; - - if (!empty($options['file']) && is_dir($dir = \dirname($options['file']))) { - // Build a regexp where the first root dirs are mandatory, - // but every other sub-dir is optional up to the full path in $dir - // Mandate at least 1 root dir and not more than 5 optional dirs. - - $dir = explode(\DIRECTORY_SEPARATOR, realpath($dir)); - $i = \count($dir); - - if (2 + (int) ('\\' === \DIRECTORY_SEPARATOR) <= $i) { - $regex = ''; - $lastOptionalDir = $i > 8 ? $i - 5 : (2 + (int) ('\\' === \DIRECTORY_SEPARATOR)); - $this->targetDirMaxMatches = $i - $lastOptionalDir; - - while (--$i >= $lastOptionalDir) { - $regex = sprintf('(%s%s)?', preg_quote(\DIRECTORY_SEPARATOR.$dir[$i], '#'), $regex); - } - - do { - $regex = preg_quote(\DIRECTORY_SEPARATOR.$dir[$i], '#').$regex; - } while (0 < --$i); - - $this->targetDirRegex = '#'.preg_quote($dir[0], '#').$regex.'#'; - } - } - - $proxyClasses = $this->inlineFactories ? $this->generateProxyClasses() : null; - - $code = - $this->startClass($options['class'], $baseClass, $preload). - $this->addServices($services). - $this->addDeprecatedAliases(). - $this->addDefaultParametersMethod() - ; - - $proxyClasses = $proxyClasses ?? $this->generateProxyClasses(); - - if ($this->addGetService) { - $code = preg_replace( - "/(\r?\n\r?\n public function __construct.+?\\{\r?\n)/s", - "\n private \$getService;$1 \$this->getService = \\Closure::fromCallable([\$this, 'getService']);\n", - $code, - 1 - ); - } - - if ($this->asFiles) { - $fileStart = <<container->getRemovedIds(); - foreach ($this->container->getDefinitions() as $id => $definition) { - if (!$definition->isPublic()) { - $ids[$id] = true; - } - } - if ($ids = array_keys($ids)) { - sort($ids); - $c = "doExport($id)." => true,\n"; - } - $files['removed-ids.php'] = $c."];\n"; - } - - if (!$this->inlineFactories) { - foreach ($this->generateServiceFiles($services) as $file => $c) { - $files[$file] = $fileStart.$c; - } - foreach ($proxyClasses as $file => $c) { - $files[$file] = "endClass(); - - if ($this->inlineFactories) { - foreach ($proxyClasses as $c) { - $code .= $c; - } - } - - $files[$options['class'].'.php'] = $code; - $hash = ucfirst(strtr(ContainerBuilder::hash($files), '._', 'xx')); - $code = []; - - foreach ($files as $file => $c) { - $code["Container{$hash}/{$file}"] = $c; - } - array_pop($code); - $code["Container{$hash}/{$options['class']}.php"] = substr_replace($files[$options['class'].'.php'], "namespace ? "\nnamespace {$this->namespace};\n" : ''; - $time = $options['build_time']; - $id = hash('crc32', $hash.$time); - $this->asFiles = false; - - if ($preload && null !== $autoloadFile = $this->getAutoloadFile()) { - $autoloadFile = substr($this->export($autoloadFile), 2, -1); - - $code[$options['class'].'.preload.php'] = <<= 7.4 when preloading is desired - -use Symfony\Component\DependencyInjection\Dumper\Preloader; - -require $autoloadFile; -require __DIR__.'/Container{$hash}/{$options['class']}.php'; - -\$classes = []; - -EOF; - - foreach ($preload as $class) { - $code[$options['class'].'.preload.php'] .= sprintf("\$classes[] = '%s';\n", $class); - } - - $code[$options['class'].'.preload.php'] .= <<<'EOF' - -Preloader::preload($classes); - -EOF; - } - - $code[$options['class'].'.php'] = << '$hash', - 'container.build_id' => '$id', - 'container.build_time' => $time, -], __DIR__.\\DIRECTORY_SEPARATOR.'Container{$hash}'); - -EOF; - } else { - $code .= $this->endClass(); - foreach ($proxyClasses as $c) { - $code .= $c; - } - } - - $this->targetDirRegex = null; - $this->inlinedRequires = []; - $this->circularReferences = []; - $this->locatedIds = []; - $this->exportedVariables = []; - - $unusedEnvs = []; - foreach ($this->container->getEnvCounters() as $env => $use) { - if (!$use) { - $unusedEnvs[] = $env; - } - } - if ($unusedEnvs) { - throw new EnvParameterException($unusedEnvs, null, 'Environment variables "%s" are never used. Please, check your container\'s configuration.'); - } - - return $code; - } - - /** - * Retrieves the currently set proxy dumper or instantiates one. - */ - private function getProxyDumper(): ProxyDumper - { - if (!$this->proxyDumper) { - $this->proxyDumper = new NullDumper(); - } - - return $this->proxyDumper; - } - - /** - * @param ServiceReferenceGraphEdge[] $edges - */ - private function analyzeCircularReferences(string $sourceId, array $edges, array &$checkedNodes, array &$currentPath = [], bool $byConstructor = true) - { - $checkedNodes[$sourceId] = true; - $currentPath[$sourceId] = $byConstructor; - - foreach ($edges as $edge) { - $node = $edge->getDestNode(); - $id = $node->getId(); - - if (!$node->getValue() instanceof Definition || $sourceId === $id || $edge->isLazy() || $edge->isWeak()) { - // no-op - } elseif (isset($currentPath[$id])) { - $this->addCircularReferences($id, $currentPath, $edge->isReferencedByConstructor()); - } elseif (!isset($checkedNodes[$id])) { - $this->analyzeCircularReferences($id, $node->getOutEdges(), $checkedNodes, $currentPath, $edge->isReferencedByConstructor()); - } elseif (isset($this->circularReferences[$id])) { - $this->connectCircularReferences($id, $currentPath, $edge->isReferencedByConstructor()); - } - } - unset($currentPath[$sourceId]); - } - - private function connectCircularReferences(string $sourceId, array &$currentPath, bool $byConstructor, array &$subPath = []) - { - $currentPath[$sourceId] = $subPath[$sourceId] = $byConstructor; - - foreach ($this->circularReferences[$sourceId] as $id => $byConstructor) { - if (isset($currentPath[$id])) { - $this->addCircularReferences($id, $currentPath, $byConstructor); - } elseif (!isset($subPath[$id]) && isset($this->circularReferences[$id])) { - $this->connectCircularReferences($id, $currentPath, $byConstructor, $subPath); - } - } - unset($currentPath[$sourceId], $subPath[$sourceId]); - } - - private function addCircularReferences(string $id, array $currentPath, bool $byConstructor) - { - $currentPath[$id] = $byConstructor; - $circularRefs = []; - - foreach (array_reverse($currentPath) as $parentId => $v) { - $byConstructor = $byConstructor && $v; - $circularRefs[] = $parentId; - - if ($parentId === $id) { - break; - } - } - - $currentId = $id; - foreach ($circularRefs as $parentId) { - if (empty($this->circularReferences[$parentId][$currentId])) { - $this->circularReferences[$parentId][$currentId] = $byConstructor; - } - - $currentId = $parentId; - } - } - - private function collectLineage(string $class, array &$lineage) - { - if (isset($lineage[$class])) { - return; - } - if (!$r = $this->container->getReflectionClass($class, false)) { - return; - } - if (is_a($class, $this->baseClass, true)) { - return; - } - $file = $r->getFileName(); - if (!$file || $this->doExport($file) === $exportedFile = $this->export($file)) { - return; - } - - $lineage[$class] = substr($exportedFile, 1, -1); - - if ($parent = $r->getParentClass()) { - $this->collectLineage($parent->name, $lineage); - } - - foreach ($r->getInterfaces() as $parent) { - $this->collectLineage($parent->name, $lineage); - } - - foreach ($r->getTraits() as $parent) { - $this->collectLineage($parent->name, $lineage); - } - - unset($lineage[$class]); - $lineage[$class] = substr($exportedFile, 1, -1); - } - - private function generateProxyClasses(): array - { - $proxyClasses = []; - $alreadyGenerated = []; - $definitions = $this->container->getDefinitions(); - $strip = '' === $this->docStar && method_exists('Symfony\Component\HttpKernel\Kernel', 'stripComments'); - $proxyDumper = $this->getProxyDumper(); - ksort($definitions); - foreach ($definitions as $definition) { - if (!$proxyDumper->isProxyCandidate($definition)) { - continue; - } - if (isset($alreadyGenerated[$class = $definition->getClass()])) { - continue; - } - $alreadyGenerated[$class] = true; - // register class' reflector for resource tracking - $this->container->getReflectionClass($class); - if ("\n" === $proxyCode = "\n".$proxyDumper->getProxyCode($definition)) { - continue; - } - - if ($this->inlineRequires) { - $lineage = []; - $this->collectLineage($class, $lineage); - - $code = ''; - foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) { - if ($this->inlineFactories) { - $this->inlinedRequires[$file] = true; - } - $code .= sprintf("include_once %s;\n", $file); - } - - $proxyCode = $code.$proxyCode; - } - - if ($strip) { - $proxyCode = "inlineRequires ? substr($proxyCode, \strlen($code)) : $proxyCode, 3)[1])] = $proxyCode; - } - - return $proxyClasses; - } - - private function addServiceInclude(string $cId, Definition $definition): string - { - $code = ''; - - if ($this->inlineRequires && (!$this->isHotPath($definition) || $this->getProxyDumper()->isProxyCandidate($definition))) { - $lineage = []; - foreach ($this->inlinedDefinitions as $def) { - if (!$def->isDeprecated() && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) { - $this->collectLineage($class, $lineage); - } - } - - foreach ($this->serviceCalls as $id => list($callCount, $behavior)) { - if ('service_container' !== $id && $id !== $cId - && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $behavior - && $this->container->has($id) - && $this->isTrivialInstance($def = $this->container->findDefinition($id)) - && \is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass()) - ) { - $this->collectLineage($class, $lineage); - } - } - - foreach (array_diff_key(array_flip($lineage), $this->inlinedRequires) as $file => $class) { - $code .= sprintf(" include_once %s;\n", $file); - } - } - - foreach ($this->inlinedDefinitions as $def) { - if ($file = $def->getFile()) { - $file = $this->dumpValue($file); - $file = '(' === $file[0] ? substr($file, 1, -1) : $file; - $code .= sprintf(" include_once %s;\n", $file); - } - } - - if ('' !== $code) { - $code .= "\n"; - } - - return $code; - } - - /** - * @throws InvalidArgumentException - * @throws RuntimeException - */ - private function addServiceInstance(string $id, Definition $definition, bool $isSimpleInstance): string - { - $class = $this->dumpValue($definition->getClass()); - - if (0 === strpos($class, "'") && false === strpos($class, '$') && !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { - throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id)); - } - - $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); - $instantiation = ''; - - $lastWitherIndex = null; - foreach ($definition->getMethodCalls() as $k => $call) { - if ($call[2] ?? false) { - $lastWitherIndex = $k; - } - } - - if (!$isProxyCandidate && $definition->isShared() && !isset($this->singleUsePrivateIds[$id]) && null === $lastWitherIndex) { - $instantiation = sprintf('$this->%s[%s] = %s', $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', $this->doExport($id), $isSimpleInstance ? '' : '$instance'); - } elseif (!$isSimpleInstance) { - $instantiation = '$instance'; - } - - $return = ''; - if ($isSimpleInstance) { - $return = 'return '; - } else { - $instantiation .= ' = '; - } - - return $this->addNewInstance($definition, ' '.$return.$instantiation, $id); - } - - private function isTrivialInstance(Definition $definition): bool - { - if ($definition->hasErrors()) { - return true; - } - if ($definition->isSynthetic() || $definition->getFile() || $definition->getMethodCalls() || $definition->getProperties() || $definition->getConfigurator()) { - return false; - } - if ($definition->isDeprecated() || $definition->isLazy() || $definition->getFactory() || 3 < \count($definition->getArguments())) { - return false; - } - - foreach ($definition->getArguments() as $arg) { - if (!$arg || $arg instanceof Parameter) { - continue; - } - if (\is_array($arg) && 3 >= \count($arg)) { - foreach ($arg as $k => $v) { - if ($this->dumpValue($k) !== $this->dumpValue($k, false)) { - return false; - } - if (!$v || $v instanceof Parameter) { - continue; - } - if ($v instanceof Reference && $this->container->has($id = (string) $v) && $this->container->findDefinition($id)->isSynthetic()) { - continue; - } - if (!is_scalar($v) || $this->dumpValue($v) !== $this->dumpValue($v, false)) { - return false; - } - } - } elseif ($arg instanceof Reference && $this->container->has($id = (string) $arg) && $this->container->findDefinition($id)->isSynthetic()) { - continue; - } elseif (!is_scalar($arg) || $this->dumpValue($arg) !== $this->dumpValue($arg, false)) { - return false; - } - } - - return true; - } - - private function addServiceMethodCalls(Definition $definition, string $variableName, ?string $sharedNonLazyId): string - { - $lastWitherIndex = null; - foreach ($definition->getMethodCalls() as $k => $call) { - if ($call[2] ?? false) { - $lastWitherIndex = $k; - } - } - - $calls = ''; - foreach ($definition->getMethodCalls() as $k => $call) { - $arguments = []; - foreach ($call[1] as $value) { - $arguments[] = $this->dumpValue($value); - } - - $witherAssignation = ''; - - if ($call[2] ?? false) { - if (null !== $sharedNonLazyId && $lastWitherIndex === $k) { - $witherAssignation = sprintf('$this->%s[\'%s\'] = ', $definition->isPublic() ? 'services' : 'privates', $sharedNonLazyId); - } - $witherAssignation .= sprintf('$%s = ', $variableName); - } - - $calls .= $this->wrapServiceConditionals($call[1], sprintf(" %s\$%s->%s(%s);\n", $witherAssignation, $variableName, $call[0], implode(', ', $arguments))); - } - - return $calls; - } - - private function addServiceProperties(Definition $definition, string $variableName = 'instance'): string - { - $code = ''; - foreach ($definition->getProperties() as $name => $value) { - $code .= sprintf(" \$%s->%s = %s;\n", $variableName, $name, $this->dumpValue($value)); - } - - return $code; - } - - private function addServiceConfigurator(Definition $definition, string $variableName = 'instance'): string - { - if (!$callable = $definition->getConfigurator()) { - return ''; - } - - if (\is_array($callable)) { - if ($callable[0] instanceof Reference - || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0])) - ) { - return sprintf(" %s->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); - } - - $class = $this->dumpValue($callable[0]); - // If the class is a string we can optimize away - if (0 === strpos($class, "'") && false === strpos($class, '$')) { - return sprintf(" %s::%s(\$%s);\n", $this->dumpLiteralClass($class), $callable[1], $variableName); - } - - if (0 === strpos($class, 'new ')) { - return sprintf(" (%s)->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); - } - - return sprintf(" [%s, '%s'](\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); - } - - return sprintf(" %s(\$%s);\n", $callable, $variableName); - } - - private function addService(string $id, Definition $definition): array - { - $this->definitionVariables = new \SplObjectStorage(); - $this->referenceVariables = []; - $this->variableCount = 0; - $this->referenceVariables[$id] = new Variable('instance'); - - $return = []; - - if ($class = $definition->getClass()) { - $class = $class instanceof Parameter ? '%'.$class.'%' : $this->container->resolveEnvPlaceholders($class); - $return[] = sprintf(0 === strpos($class, '%') ? '@return object A %1$s instance' : '@return \%s', ltrim($class, '\\')); - } elseif ($definition->getFactory()) { - $factory = $definition->getFactory(); - if (\is_string($factory)) { - $return[] = sprintf('@return object An instance returned by %s()', $factory); - } elseif (\is_array($factory) && (\is_string($factory[0]) || $factory[0] instanceof Definition || $factory[0] instanceof Reference)) { - $class = $factory[0] instanceof Definition ? $factory[0]->getClass() : (string) $factory[0]; - $class = $class instanceof Parameter ? '%'.$class.'%' : $this->container->resolveEnvPlaceholders($class); - $return[] = sprintf('@return object An instance returned by %s::%s()', $class, $factory[1]); - } - } - - if ($definition->isDeprecated()) { - if ($return && 0 === strpos($return[\count($return) - 1], '@return')) { - $return[] = ''; - } - - $return[] = sprintf('@deprecated %s', $definition->getDeprecationMessage($id)); - } - - $return = str_replace("\n * \n", "\n *\n", implode("\n * ", $return)); - $return = $this->container->resolveEnvPlaceholders($return); - - $shared = $definition->isShared() ? ' shared' : ''; - $public = $definition->isPublic() ? 'public' : 'private'; - $autowired = $definition->isAutowired() ? ' autowired' : ''; - - if ($definition->isLazy()) { - $lazyInitialization = '$lazyLoad = true'; - } else { - $lazyInitialization = ''; - } - - $asFile = $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition); - $methodName = $this->generateMethodName($id); - if ($asFile) { - $file = $methodName.'.php'; - $code = " // Returns the $public '$id'$shared$autowired service.\n\n"; - } else { - $file = null; - $code = <<docStar} - * Gets the $public '$id'$shared$autowired service. - * - * $return -EOF; - $code = str_replace('*/', ' ', $code).<<serviceCalls = []; - $this->inlinedDefinitions = $this->getDefinitionsFromArguments([$definition], null, $this->serviceCalls); - - if ($definition->isDeprecated()) { - $code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id))); - } - - if ($this->getProxyDumper()->isProxyCandidate($definition)) { - $factoryCode = $asFile ? ($definition->isShared() ? "\$this->load('%s.php', false)" : '$this->factories[%2$s](false)') : '$this->%s(false)'; - $code .= $this->getProxyDumper()->getProxyFactoryCode($definition, $id, sprintf($factoryCode, $methodName, $this->doExport($id))); - } - - $code .= $this->addServiceInclude($id, $definition); - $code .= $this->addInlineService($id, $definition); - - if ($asFile) { - $code = implode("\n", array_map(function ($line) { return $line ? substr($line, 8) : $line; }, explode("\n", $code))); - } else { - $code .= " }\n"; - } - - $this->definitionVariables = $this->inlinedDefinitions = null; - $this->referenceVariables = $this->serviceCalls = null; - - return [$file, $code]; - } - - private function addInlineVariables(string $id, Definition $definition, array $arguments, bool $forConstructor): string - { - $code = ''; - - foreach ($arguments as $argument) { - if (\is_array($argument)) { - $code .= $this->addInlineVariables($id, $definition, $argument, $forConstructor); - } elseif ($argument instanceof Reference) { - $code .= $this->addInlineReference($id, $definition, $argument, $forConstructor); - } elseif ($argument instanceof Definition) { - $code .= $this->addInlineService($id, $definition, $argument, $forConstructor); - } - } - - return $code; - } - - private function addInlineReference(string $id, Definition $definition, string $targetId, bool $forConstructor): string - { - while ($this->container->hasAlias($targetId)) { - $targetId = (string) $this->container->getAlias($targetId); - } - - list($callCount, $behavior) = $this->serviceCalls[$targetId]; - - if ($id === $targetId) { - return $this->addInlineService($id, $definition, $definition); - } - - if ('service_container' === $targetId || isset($this->referenceVariables[$targetId])) { - return ''; - } - - $hasSelfRef = isset($this->circularReferences[$id][$targetId]) && !isset($this->definitionVariables[$definition]); - - if ($hasSelfRef && !$forConstructor && !$forConstructor = !$this->circularReferences[$id][$targetId]) { - $code = $this->addInlineService($id, $definition, $definition); - } else { - $code = ''; - } - - if (isset($this->referenceVariables[$targetId]) || (2 > $callCount && (!$hasSelfRef || !$forConstructor))) { - return $code; - } - - $name = $this->getNextVariableName(); - $this->referenceVariables[$targetId] = new Variable($name); - - $reference = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $behavior ? new Reference($targetId, $behavior) : null; - $code .= sprintf(" \$%s = %s;\n", $name, $this->getServiceCall($targetId, $reference)); - - if (!$hasSelfRef || !$forConstructor) { - return $code; - } - - $code .= sprintf(<<<'EOTXT' - - if (isset($this->%s[%s])) { - return $this->%1$s[%2$s]; - } - -EOTXT - , - $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', - $this->doExport($id) - ); - - return $code; - } - - private function addInlineService(string $id, Definition $definition, Definition $inlineDef = null, bool $forConstructor = true): string - { - $code = ''; - - if ($isSimpleInstance = $isRootInstance = null === $inlineDef) { - foreach ($this->serviceCalls as $targetId => list($callCount, $behavior, $byConstructor)) { - if ($byConstructor && isset($this->circularReferences[$id][$targetId]) && !$this->circularReferences[$id][$targetId]) { - $code .= $this->addInlineReference($id, $definition, $targetId, $forConstructor); - } - } - } - - if (isset($this->definitionVariables[$inlineDef = $inlineDef ?: $definition])) { - return $code; - } - - $arguments = [$inlineDef->getArguments(), $inlineDef->getFactory()]; - - $code .= $this->addInlineVariables($id, $definition, $arguments, $forConstructor); - - if ($arguments = array_filter([$inlineDef->getProperties(), $inlineDef->getMethodCalls(), $inlineDef->getConfigurator()])) { - $isSimpleInstance = false; - } elseif ($definition !== $inlineDef && 2 > $this->inlinedDefinitions[$inlineDef]) { - return $code; - } - - if (isset($this->definitionVariables[$inlineDef])) { - $isSimpleInstance = false; - } else { - $name = $definition === $inlineDef ? 'instance' : $this->getNextVariableName(); - $this->definitionVariables[$inlineDef] = new Variable($name); - $code .= '' !== $code ? "\n" : ''; - - if ('instance' === $name) { - $code .= $this->addServiceInstance($id, $definition, $isSimpleInstance); - } else { - $code .= $this->addNewInstance($inlineDef, ' $'.$name.' = ', $id); - } - - if ('' !== $inline = $this->addInlineVariables($id, $definition, $arguments, false)) { - $code .= "\n".$inline."\n"; - } elseif ($arguments && 'instance' === $name) { - $code .= "\n"; - } - - $code .= $this->addServiceProperties($inlineDef, $name); - $code .= $this->addServiceMethodCalls($inlineDef, $name, !$this->getProxyDumper()->isProxyCandidate($inlineDef) && $inlineDef->isShared() && !isset($this->singleUsePrivateIds[$id]) ? $id : null); - $code .= $this->addServiceConfigurator($inlineDef, $name); - } - - if ($isRootInstance && !$isSimpleInstance) { - $code .= "\n return \$instance;\n"; - } - - return $code; - } - - private function addServices(array &$services = null): string - { - $publicServices = $privateServices = ''; - $definitions = $this->container->getDefinitions(); - ksort($definitions); - foreach ($definitions as $id => $definition) { - $services[$id] = $definition->isSynthetic() ? null : $this->addService($id, $definition); - } - - foreach ($definitions as $id => $definition) { - if (!(list($file, $code) = $services[$id]) || null !== $file) { - continue; - } - if ($definition->isPublic()) { - $publicServices .= $code; - } elseif (!$this->isTrivialInstance($definition) || isset($this->locatedIds[$id])) { - $privateServices .= $code; - } - } - - return $publicServices.$privateServices; - } - - private function generateServiceFiles(array $services): iterable - { - $definitions = $this->container->getDefinitions(); - ksort($definitions); - foreach ($definitions as $id => $definition) { - if ((list($file, $code) = $services[$id]) && null !== $file && ($definition->isPublic() || !$this->isTrivialInstance($definition) || isset($this->locatedIds[$id]))) { - if (!$definition->isShared()) { - $i = strpos($code, "\n\ninclude_once "); - if (false !== $i && false !== $i = strpos($code, "\n\n", 2 + $i)) { - $code = [substr($code, 0, 2 + $i), substr($code, 2 + $i)]; - } else { - $code = ["\n", $code]; - } - $code[1] = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $code[1]))); - $factory = sprintf('$this->factories%s[%s]', $definition->isPublic() ? '' : "['service_container']", $this->doExport($id)); - $lazyloadInitialization = $definition->isLazy() ? '$lazyLoad = true' : ''; - - $code[1] = sprintf("%s = function (%s) {\n%s};\n\nreturn %1\$s();\n", $factory, $lazyloadInitialization, $code[1]); - $code = $code[0].$code[1]; - } - - yield $file => $code; - } - } - } - - private function addNewInstance(Definition $definition, string $return = '', string $id = null): string - { - $tail = $return ? ";\n" : ''; - - if (BaseServiceLocator::class === $definition->getClass() && $definition->hasTag($this->serviceLocatorTag)) { - $arguments = []; - foreach ($definition->getArgument(0) as $k => $argument) { - $arguments[$k] = $argument->getValues()[0]; - } - - return $return.$this->dumpValue(new ServiceLocatorArgument($arguments)).$tail; - } - - $arguments = []; - foreach ($definition->getArguments() as $value) { - $arguments[] = $this->dumpValue($value); - } - - if (null !== $definition->getFactory()) { - $callable = $definition->getFactory(); - - if (\is_array($callable)) { - if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $callable[1])) { - throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s)', $callable[1] ?: 'n/a')); - } - - if ($callable[0] instanceof Reference - || ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) { - return $return.sprintf('%s->%s(%s)', $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : '').$tail; - } - - $class = $this->dumpValue($callable[0]); - // If the class is a string we can optimize away - if (0 === strpos($class, "'") && false === strpos($class, '$')) { - if ("''" === $class) { - throw new RuntimeException(sprintf('Cannot dump definition: %s service is defined to be created by a factory but is missing the service reference, did you forget to define the factory service id or class?', $id ? 'The "'.$id.'"' : 'inline')); - } - - return $return.sprintf('%s::%s(%s)', $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : '').$tail; - } - - if (0 === strpos($class, 'new ')) { - return $return.sprintf('(%s)->%s(%s)', $class, $callable[1], $arguments ? implode(', ', $arguments) : '').$tail; - } - - return $return.sprintf("[%s, '%s'](%s)", $class, $callable[1], $arguments ? implode(', ', $arguments) : '').$tail; - } - - return $return.sprintf('%s(%s)', $this->dumpLiteralClass($this->dumpValue($callable)), $arguments ? implode(', ', $arguments) : '').$tail; - } - - if (null === $class = $definition->getClass()) { - throw new RuntimeException('Cannot dump definitions which have no class nor factory.'); - } - - return $return.sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments)).$tail; - } - - private function startClass(string $class, string $baseClass, ?array &$preload): string - { - $namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : ''; - - $code = <<docStar} - * This class has been auto-generated - * by the Symfony Dependency Injection Component. - * - * @final - */ -class $class extends $baseClass -{ - private \$parameters = []; - - public function __construct() - { - -EOF; - if ($this->asFiles) { - $code = str_replace('$parameters', "\$buildParameters;\n private \$containerDir;\n private \$parameters", $code); - $code = str_replace('__construct()', '__construct(array $buildParameters = [], $containerDir = __DIR__)', $code); - $code .= " \$this->buildParameters = \$buildParameters;\n"; - $code .= " \$this->containerDir = \$containerDir;\n"; - - if (null !== $this->targetDirRegex) { - $code = str_replace('$parameters', "\$targetDir;\n private \$parameters", $code); - $code .= ' $this->targetDir = \\dirname($containerDir);'."\n"; - } - } - - if (Container::class !== $this->baseClass) { - $r = $this->container->getReflectionClass($this->baseClass, false); - if (null !== $r - && (null !== $constructor = $r->getConstructor()) - && 0 === $constructor->getNumberOfRequiredParameters() - && Container::class !== $constructor->getDeclaringClass()->name - ) { - $code .= " parent::__construct();\n"; - $code .= " \$this->parameterBag = null;\n\n"; - } - } - - if ($this->container->getParameterBag()->all()) { - $code .= " \$this->parameters = \$this->getDefaultParameters();\n\n"; - } - $code .= " \$this->services = \$this->privates = [];\n"; - - $code .= $this->addSyntheticIds(); - $code .= $this->addMethodMap(); - $code .= $this->asFiles && !$this->inlineFactories ? $this->addFileMap() : ''; - $code .= $this->addAliases(); - $code .= $this->addInlineRequires($preload); - $code .= <<addRemovedIds(); - - if ($this->asFiles && !$this->inlineFactories) { - $code .= <<containerDir.\\DIRECTORY_SEPARATOR.\$file; - } - -EOF; - } - - $proxyDumper = $this->getProxyDumper(); - foreach ($this->container->getDefinitions() as $definition) { - if (!$proxyDumper->isProxyCandidate($definition)) { - continue; - } - if ($this->asFiles && !$this->inlineFactories) { - $proxyLoader = '$this->load("{$class}.php")'; - } elseif ($this->namespace || $this->inlineFactories) { - $proxyLoader = 'class_alias(__NAMESPACE__."\\\\$class", $class, false)'; - } else { - $proxyLoader = ''; - } - if ($proxyLoader) { - $proxyLoader = "class_exists(\$class, false) || {$proxyLoader};\n\n "; - } - $code .= <<container->getDefinitions(); - ksort($definitions); - foreach ($definitions as $id => $definition) { - if ($definition->isSynthetic() && 'service_container' !== $id) { - $code .= ' '.$this->doExport($id)." => true,\n"; - } - } - - return $code ? " \$this->syntheticIds = [\n{$code} ];\n" : ''; - } - - private function addRemovedIds(): string - { - $ids = $this->container->getRemovedIds(); - foreach ($this->container->getDefinitions() as $id => $definition) { - if (!$definition->isPublic()) { - $ids[$id] = true; - } - } - if (!$ids) { - return ''; - } - if ($this->asFiles) { - $code = "require \$this->containerDir.\\DIRECTORY_SEPARATOR.'removed-ids.php'"; - } else { - $code = ''; - $ids = array_keys($ids); - sort($ids); - foreach ($ids as $id) { - if (preg_match(FileLoader::ANONYMOUS_ID_REGEXP, $id)) { - continue; - } - $code .= ' '.$this->doExport($id)." => true,\n"; - } - - $code = "[\n{$code} ]"; - } - - return <<container->getDefinitions(); - ksort($definitions); - foreach ($definitions as $id => $definition) { - if (!$definition->isSynthetic() && $definition->isPublic() && (!$this->asFiles || $this->inlineFactories || $this->isHotPath($definition))) { - $code .= ' '.$this->doExport($id).' => '.$this->doExport($this->generateMethodName($id)).",\n"; - } - } - - $aliases = $this->container->getAliases(); - foreach ($aliases as $alias => $id) { - if (!$id->isDeprecated()) { - continue; - } - $code .= ' '.$this->doExport($alias).' => '.$this->doExport($this->generateMethodName($alias)).",\n"; - } - - return $code ? " \$this->methodMap = [\n{$code} ];\n" : ''; - } - - private function addFileMap(): string - { - $code = ''; - $definitions = $this->container->getDefinitions(); - ksort($definitions); - foreach ($definitions as $id => $definition) { - if (!$definition->isSynthetic() && $definition->isPublic() && !$this->isHotPath($definition)) { - $code .= sprintf(" %s => '%s.php',\n", $this->doExport($id), $this->generateMethodName($id)); - } - } - - return $code ? " \$this->fileMap = [\n{$code} ];\n" : ''; - } - - private function addAliases(): string - { - if (!$aliases = $this->container->getAliases()) { - return "\n \$this->aliases = [];\n"; - } - - $code = " \$this->aliases = [\n"; - ksort($aliases); - foreach ($aliases as $alias => $id) { - if ($id->isDeprecated()) { - continue; - } - - $id = (string) $id; - while (isset($aliases[$id])) { - $id = (string) $aliases[$id]; - } - $code .= ' '.$this->doExport($alias).' => '.$this->doExport($id).",\n"; - } - - return $code." ];\n"; - } - - private function addDeprecatedAliases(): string - { - $code = ''; - $aliases = $this->container->getAliases(); - foreach ($aliases as $alias => $definition) { - if (!$definition->isDeprecated()) { - continue; - } - $public = $definition->isPublic() ? 'public' : 'private'; - $id = (string) $definition; - $methodNameAlias = $this->generateMethodName($alias); - $idExported = $this->export($id); - $messageExported = $this->export($definition->getDeprecationMessage($alias)); - $code .= <<docStar} - * Gets the $public '$alias' alias. - * - * @return object The "$id" service. - */ - protected function {$methodNameAlias}() - { - @trigger_error($messageExported, E_USER_DEPRECATED); - - return \$this->get($idExported); - } - -EOF; - } - - return $code; - } - - private function addInlineRequires(?array &$preload): string - { - if (!$this->hotPathTag || !$this->inlineRequires) { - return ''; - } - - $lineage = []; - - foreach ($this->container->findTaggedServiceIds($this->hotPathTag) as $id => $tags) { - $definition = $this->container->getDefinition($id); - - if ($this->getProxyDumper()->isProxyCandidate($definition)) { - continue; - } - - $inlinedDefinitions = $this->getDefinitionsFromArguments([$definition]); - - foreach ($inlinedDefinitions as $def) { - if (\is_string($class = \is_array($factory = $def->getFactory()) && \is_string($factory[0]) ? $factory[0] : $def->getClass())) { - $preload[$class] = $class; - $this->collectLineage($class, $lineage); - } - } - } - - $code = ''; - - foreach ($lineage as $file) { - if (!isset($this->inlinedRequires[$file])) { - $this->inlinedRequires[$file] = true; - $code .= sprintf("\n include_once %s;", $file); - } - } - - return $code ? sprintf("\n \$this->privates['service_container'] = function () {%s\n };\n", $code) : ''; - } - - private function addDefaultParametersMethod(): string - { - if (!$this->container->getParameterBag()->all()) { - return ''; - } - - $php = []; - $dynamicPhp = []; - - foreach ($this->container->getParameterBag()->all() as $key => $value) { - if ($key !== $resolvedKey = $this->container->resolveEnvPlaceholders($key)) { - throw new InvalidArgumentException(sprintf('Parameter name cannot use env parameters: %s.', $resolvedKey)); - } - $export = $this->exportParameters([$value]); - $export = explode('0 => ', substr(rtrim($export, " ]\n"), 2, -1), 2); - - if (preg_match("/\\\$this->(?:getEnv\('(?:\w++:)*+\w++'\)|targetDir\.'')/", $export[1])) { - $dynamicPhp[$key] = sprintf('%scase %s: $value = %s; break;', $export[0], $this->export($key), $export[1]); - } else { - $php[] = sprintf('%s%s => %s,', $export[0], $this->export($key), $export[1]); - } - } - $parameters = sprintf("[\n%s\n%s]", implode("\n", $php), str_repeat(' ', 8)); - - $code = <<<'EOF' - - public function getParameter(string $name) - { - if (isset($this->buildParameters[$name])) { - return $this->buildParameters[$name]; - } - - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); - } - if (isset($this->loadedDynamicParameters[$name])) { - return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); - } - - return $this->parameters[$name]; - } - - public function hasParameter(string $name): bool - { - if (isset($this->buildParameters[$name])) { - return true; - } - - return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); - } - - public function setParameter(string $name, $value): void - { - throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); - } - - public function getParameterBag(): ParameterBagInterface - { - if (null === $this->parameterBag) { - $parameters = $this->parameters; - foreach ($this->loadedDynamicParameters as $name => $loaded) { - $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); - } - foreach ($this->buildParameters as $name => $value) { - $parameters[$name] = $value; - } - $this->parameterBag = new FrozenParameterBag($parameters); - } - - return $this->parameterBag; - } - -EOF; - if (!$this->asFiles) { - $code = preg_replace('/^.*buildParameters.*\n.*\n.*\n\n?/m', '', $code); - } - - if ($dynamicPhp) { - $loadedDynamicParameters = $this->exportParameters(array_combine(array_keys($dynamicPhp), array_fill(0, \count($dynamicPhp), false)), '', 8); - $getDynamicParameter = <<<'EOF' - switch ($name) { -%s - default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%%s" must be defined.', $name)); - } - $this->loadedDynamicParameters[$name] = true; - - return $this->dynamicParameters[$name] = $value; -EOF; - $getDynamicParameter = sprintf($getDynamicParameter, implode("\n", $dynamicPhp)); - } else { - $loadedDynamicParameters = '[]'; - $getDynamicParameter = str_repeat(' ', 8).'throw new InvalidArgumentException(sprintf(\'The dynamic parameter "%s" must be defined.\', $name));'; - } - - $code .= << $value) { - if (\is_array($value)) { - $value = $this->exportParameters($value, $path.'/'.$key, $indent + 4); - } elseif ($value instanceof ArgumentInterface) { - throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain special arguments. "%s" found in "%s".', \get_class($value), $path.'/'.$key)); - } elseif ($value instanceof Variable) { - throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain variable references. Variable "%s" found in "%s".', $value, $path.'/'.$key)); - } elseif ($value instanceof Definition) { - throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain service definitions. Definition for "%s" found in "%s".', $value->getClass(), $path.'/'.$key)); - } elseif ($value instanceof Reference) { - throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain references to other services (reference to service "%s" found in "%s").', $value, $path.'/'.$key)); - } elseif ($value instanceof Expression) { - throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain expressions. Expression "%s" found in "%s".', $value, $path.'/'.$key)); - } else { - $value = $this->export($value); - } - - $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), $this->export($key), $value); - } - - return sprintf("[\n%s\n%s]", implode("\n", $php), str_repeat(' ', $indent - 4)); - } - - private function endClass(): string - { - if ($this->addThrow) { - return <<<'EOF' - - protected function throw($message) - { - throw new RuntimeException($message); - } -} - -EOF; - } - - return <<<'EOF' -} - -EOF; - } - - private function wrapServiceConditionals($value, string $code): string - { - if (!$condition = $this->getServiceConditionals($value)) { - return $code; - } - - // re-indent the wrapped code - $code = implode("\n", array_map(function ($line) { return $line ? ' '.$line : $line; }, explode("\n", $code))); - - return sprintf(" if (%s) {\n%s }\n", $condition, $code); - } - - private function getServiceConditionals($value): string - { - $conditions = []; - foreach (ContainerBuilder::getInitializedConditionals($value) as $service) { - if (!$this->container->hasDefinition($service)) { - return 'false'; - } - $conditions[] = sprintf('isset($this->%s[%s])', $this->container->getDefinition($service)->isPublic() ? 'services' : 'privates', $this->doExport($service)); - } - foreach (ContainerBuilder::getServiceConditionals($value) as $service) { - if ($this->container->hasDefinition($service) && !$this->container->getDefinition($service)->isPublic()) { - continue; - } - - $conditions[] = sprintf('$this->has(%s)', $this->doExport($service)); - } - - if (!$conditions) { - return ''; - } - - return implode(' && ', $conditions); - } - - private function getDefinitionsFromArguments(array $arguments, \SplObjectStorage $definitions = null, array &$calls = [], bool $byConstructor = null): \SplObjectStorage - { - if (null === $definitions) { - $definitions = new \SplObjectStorage(); - } - - foreach ($arguments as $argument) { - if (\is_array($argument)) { - $this->getDefinitionsFromArguments($argument, $definitions, $calls, $byConstructor); - } elseif ($argument instanceof Reference) { - $id = (string) $argument; - - while ($this->container->hasAlias($id)) { - $id = (string) $this->container->getAlias($id); - } - - if (!isset($calls[$id])) { - $calls[$id] = [0, $argument->getInvalidBehavior(), $byConstructor]; - } else { - $calls[$id][1] = min($calls[$id][1], $argument->getInvalidBehavior()); - } - - ++$calls[$id][0]; - } elseif (!$argument instanceof Definition) { - // no-op - } elseif (isset($definitions[$argument])) { - $definitions[$argument] = 1 + $definitions[$argument]; - } else { - $definitions[$argument] = 1; - $arguments = [$argument->getArguments(), $argument->getFactory()]; - $this->getDefinitionsFromArguments($arguments, $definitions, $calls, null === $byConstructor || $byConstructor); - $arguments = [$argument->getProperties(), $argument->getMethodCalls(), $argument->getConfigurator()]; - $this->getDefinitionsFromArguments($arguments, $definitions, $calls, null !== $byConstructor && $byConstructor); - } - } - - return $definitions; - } - - /** - * @throws RuntimeException - */ - private function dumpValue($value, bool $interpolate = true): string - { - if (\is_array($value)) { - if ($value && $interpolate && false !== $param = array_search($value, $this->container->getParameterBag()->all(), true)) { - return $this->dumpValue("%$param%"); - } - $code = []; - foreach ($value as $k => $v) { - $code[] = sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate)); - } - - return sprintf('[%s]', implode(', ', $code)); - } elseif ($value instanceof ArgumentInterface) { - $scope = [$this->definitionVariables, $this->referenceVariables]; - $this->definitionVariables = $this->referenceVariables = null; - - try { - if ($value instanceof ServiceClosureArgument) { - $value = $value->getValues()[0]; - $code = $this->dumpValue($value, $interpolate); - - $returnedType = ''; - if ($value instanceof TypedReference) { - $returnedType = sprintf(': %s\%s', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $value->getInvalidBehavior() ? '' : '?', $value->getType()); - } - - $code = sprintf('return %s;', $code); - - return sprintf("function ()%s {\n %s\n }", $returnedType, $code); - } - - if ($value instanceof IteratorArgument) { - $operands = [0]; - $code = []; - $code[] = 'new RewindableGenerator(function () {'; - - if (!$values = $value->getValues()) { - $code[] = ' return new \EmptyIterator();'; - } else { - $countCode = []; - $countCode[] = 'function () {'; - - foreach ($values as $k => $v) { - ($c = $this->getServiceConditionals($v)) ? $operands[] = "(int) ($c)" : ++$operands[0]; - $v = $this->wrapServiceConditionals($v, sprintf(" yield %s => %s;\n", $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate))); - foreach (explode("\n", $v) as $v) { - if ($v) { - $code[] = ' '.$v; - } - } - } - - $countCode[] = sprintf(' return %s;', implode(' + ', $operands)); - $countCode[] = ' }'; - } - - $code[] = sprintf(' }, %s)', \count($operands) > 1 ? implode("\n", $countCode) : $operands[0]); - - return implode("\n", $code); - } - - if ($value instanceof ServiceLocatorArgument) { - $serviceMap = ''; - $serviceTypes = ''; - foreach ($value->getValues() as $k => $v) { - if (!$v) { - continue; - } - $definition = $this->container->findDefinition($id = (string) $v); - $load = !($definition->hasErrors() && $e = $definition->getErrors()) ? $this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition) : reset($e); - $serviceMap .= sprintf("\n %s => [%s, %s, %s, %s],", - $this->export($k), - $this->export($definition->isShared() ? ($definition->isPublic() ? 'services' : 'privates') : false), - $this->doExport($id), - $this->export(ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE !== $v->getInvalidBehavior() && !\is_string($load) ? $this->generateMethodName($id).($load ? '.php' : '') : null), - $this->export($load) - ); - $serviceTypes .= sprintf("\n %s => %s,", $this->export($k), $this->export($v instanceof TypedReference ? $v->getType() : '?')); - $this->locatedIds[$id] = true; - } - $this->addGetService = true; - - return sprintf('new \%s($this->getService, [%s%s], [%s%s])', ServiceLocator::class, $serviceMap, $serviceMap ? "\n " : '', $serviceTypes, $serviceTypes ? "\n " : ''); - } - } finally { - list($this->definitionVariables, $this->referenceVariables) = $scope; - } - } elseif ($value instanceof Definition) { - if ($value->hasErrors() && $e = $value->getErrors()) { - $this->addThrow = true; - - return sprintf('$this->throw(%s)', $this->export(reset($e))); - } - if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) { - return $this->dumpValue($this->definitionVariables[$value], $interpolate); - } - if ($value->getMethodCalls()) { - throw new RuntimeException('Cannot dump definitions which have method calls.'); - } - if ($value->getProperties()) { - throw new RuntimeException('Cannot dump definitions which have properties.'); - } - if (null !== $value->getConfigurator()) { - throw new RuntimeException('Cannot dump definitions which have a configurator.'); - } - - return $this->addNewInstance($value); - } elseif ($value instanceof Variable) { - return '$'.$value; - } elseif ($value instanceof Reference) { - $id = (string) $value; - - while ($this->container->hasAlias($id)) { - $id = (string) $this->container->getAlias($id); - } - - if (null !== $this->referenceVariables && isset($this->referenceVariables[$id])) { - return $this->dumpValue($this->referenceVariables[$id], $interpolate); - } - - return $this->getServiceCall($id, $value); - } elseif ($value instanceof Expression) { - return $this->getExpressionLanguage()->compile((string) $value, ['this' => 'container']); - } elseif ($value instanceof Parameter) { - return $this->dumpParameter($value); - } elseif (true === $interpolate && \is_string($value)) { - if (preg_match('/^%([^%]+)%$/', $value, $match)) { - // we do this to deal with non string values (Boolean, integer, ...) - // the preg_replace_callback converts them to strings - return $this->dumpParameter($match[1]); - } else { - $replaceParameters = function ($match) { - return "'.".$this->dumpParameter($match[2]).".'"; - }; - - $code = str_replace('%%', '%', preg_replace_callback('/(?export($value))); - - return $code; - } - } elseif (\is_object($value) || \is_resource($value)) { - throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); - } - - return $this->export($value); - } - - /** - * Dumps a string to a literal (aka PHP Code) class value. - * - * @throws RuntimeException - */ - private function dumpLiteralClass(string $class): string - { - if (false !== strpos($class, '$')) { - return sprintf('${($_ = %s) && false ?: "_"}', $class); - } - if (0 !== strpos($class, "'") || !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { - throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s)', $class ?: 'n/a')); - } - - $class = substr(str_replace('\\\\', '\\', $class), 1, -1); - - return 0 === strpos($class, '\\') ? $class : '\\'.$class; - } - - private function dumpParameter(string $name): string - { - if ($this->container->hasParameter($name)) { - $value = $this->container->getParameter($name); - $dumpedValue = $this->dumpValue($value, false); - - if (!$value || !\is_array($value)) { - return $dumpedValue; - } - - if (!preg_match("/\\\$this->(?:getEnv\('(?:\w++:)*+\w++'\)|targetDir\.'')/", $dumpedValue)) { - return sprintf('$this->parameters[%s]', $this->doExport($name)); - } - } - - return sprintf('$this->getParameter(%s)', $this->doExport($name)); - } - - private function getServiceCall(string $id, Reference $reference = null): string - { - while ($this->container->hasAlias($id)) { - $id = (string) $this->container->getAlias($id); - } - - if ('service_container' === $id) { - return '$this'; - } - - if ($this->container->hasDefinition($id) && $definition = $this->container->getDefinition($id)) { - if ($definition->isSynthetic()) { - $code = sprintf('$this->get(%s%s)', $this->doExport($id), null !== $reference ? ', '.$reference->getInvalidBehavior() : ''); - } elseif (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) { - $code = 'null'; - if (!$definition->isShared()) { - return $code; - } - } elseif ($this->isTrivialInstance($definition)) { - if ($definition->hasErrors() && $e = $definition->getErrors()) { - $this->addThrow = true; - - return sprintf('$this->throw(%s)', $this->export(reset($e))); - } - $code = $this->addNewInstance($definition, '', $id); - if ($definition->isShared() && !isset($this->singleUsePrivateIds[$id])) { - $code = sprintf('$this->%s[%s] = %s', $definition->isPublic() ? 'services' : 'privates', $this->doExport($id), $code); - } - $code = "($code)"; - } elseif ($this->asFiles && !$this->inlineFactories && !$this->isHotPath($definition)) { - $code = sprintf("\$this->load('%s.php')", $this->generateMethodName($id)); - if (!$definition->isShared()) { - $factory = sprintf('$this->factories%s[%s]', $definition->isPublic() ? '' : "['service_container']", $this->doExport($id)); - $code = sprintf('(isset(%s) ? %1$s() : %s)', $factory, $code); - } - } else { - $code = sprintf('$this->%s()', $this->generateMethodName($id)); - } - if ($definition->isShared() && !isset($this->singleUsePrivateIds[$id])) { - $code = sprintf('($this->%s[%s] ?? %s)', $definition->isPublic() ? 'services' : 'privates', $this->doExport($id), $code); - } - - return $code; - } - if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) { - return 'null'; - } - if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $reference->getInvalidBehavior()) { - $code = sprintf('$this->get(%s, /* ContainerInterface::NULL_ON_INVALID_REFERENCE */ %d)', $this->doExport($id), ContainerInterface::NULL_ON_INVALID_REFERENCE); - } else { - $code = sprintf('$this->get(%s)', $this->doExport($id)); - } - - return sprintf('($this->services[%s] ?? %s)', $this->doExport($id), $code); - } - - /** - * Initializes the method names map to avoid conflicts with the Container methods. - */ - private function initializeMethodNamesMap(string $class) - { - $this->serviceIdToMethodNameMap = []; - $this->usedMethodNames = []; - - if ($reflectionClass = $this->container->getReflectionClass($class)) { - foreach ($reflectionClass->getMethods() as $method) { - $this->usedMethodNames[strtolower($method->getName())] = true; - } - } - } - - /** - * @throws InvalidArgumentException - */ - private function generateMethodName(string $id): string - { - if (isset($this->serviceIdToMethodNameMap[$id])) { - return $this->serviceIdToMethodNameMap[$id]; - } - - $i = strrpos($id, '\\'); - $name = Container::camelize(false !== $i && isset($id[1 + $i]) ? substr($id, 1 + $i) : $id); - $name = preg_replace('/[^a-zA-Z0-9_\x7f-\xff]/', '', $name); - $methodName = 'get'.$name.'Service'; - $suffix = 1; - - while (isset($this->usedMethodNames[strtolower($methodName)])) { - ++$suffix; - $methodName = 'get'.$name.$suffix.'Service'; - } - - $this->serviceIdToMethodNameMap[$id] = $methodName; - $this->usedMethodNames[strtolower($methodName)] = true; - - return $methodName; - } - - private function getNextVariableName(): string - { - $firstChars = self::FIRST_CHARS; - $firstCharsLength = \strlen($firstChars); - $nonFirstChars = self::NON_FIRST_CHARS; - $nonFirstCharsLength = \strlen($nonFirstChars); - - while (true) { - $name = ''; - $i = $this->variableCount; - - if ('' === $name) { - $name .= $firstChars[$i % $firstCharsLength]; - $i = (int) ($i / $firstCharsLength); - } - - while ($i > 0) { - --$i; - $name .= $nonFirstChars[$i % $nonFirstCharsLength]; - $i = (int) ($i / $nonFirstCharsLength); - } - - ++$this->variableCount; - - // check that the name is not reserved - if (\in_array($name, $this->reservedVariables, true)) { - continue; - } - - return $name; - } - } - - private function getExpressionLanguage(): ExpressionLanguage - { - if (null === $this->expressionLanguage) { - if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { - throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - $providers = $this->container->getExpressionLanguageProviders(); - $this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) { - $id = '""' === substr_replace($arg, '', 1, -1) ? stripcslashes(substr($arg, 1, -1)) : null; - - if (null !== $id && ($this->container->hasAlias($id) || $this->container->hasDefinition($id))) { - return $this->getServiceCall($id); - } - - return sprintf('$this->get(%s)', $arg); - }); - - if ($this->container->isTrackingResources()) { - foreach ($providers as $provider) { - $this->container->addObjectResource($provider); - } - } - } - - return $this->expressionLanguage; - } - - private function isHotPath(Definition $definition): bool - { - return $this->hotPathTag && $definition->hasTag($this->hotPathTag) && !$definition->isDeprecated(); - } - - private function isSingleUsePrivateNode(ServiceReferenceGraphNode $node): bool - { - if ($node->getValue()->isPublic()) { - return false; - } - $ids = []; - foreach ($node->getInEdges() as $edge) { - if (!$value = $edge->getSourceNode()->getValue()) { - continue; - } - if ($edge->isLazy() || !$value instanceof Definition || !$value->isShared()) { - return false; - } - $ids[$edge->getSourceNode()->getId()] = true; - } - - return 1 === \count($ids); - } - - /** - * @return mixed - */ - private function export($value) - { - if (null !== $this->targetDirRegex && \is_string($value) && preg_match($this->targetDirRegex, $value, $matches, PREG_OFFSET_CAPTURE)) { - $prefix = $matches[0][1] ? $this->doExport(substr($value, 0, $matches[0][1]), true).'.' : ''; - $suffix = $matches[0][1] + \strlen($matches[0][0]); - $suffix = isset($value[$suffix]) ? '.'.$this->doExport(substr($value, $suffix), true) : ''; - $dirname = $this->asFiles ? '$this->containerDir' : '__DIR__'; - $offset = 1 + $this->targetDirMaxMatches - \count($matches); - - if (0 < $offset) { - $dirname = sprintf('\dirname(__DIR__, %d)', $offset + (int) $this->asFiles); - } elseif ($this->asFiles) { - $dirname = "\$this->targetDir.''"; // empty string concatenation on purpose - } - - if ($prefix || $suffix) { - return sprintf('(%s%s%s)', $prefix, $dirname, $suffix); - } - - return $dirname; - } - - return $this->doExport($value, true); - } - - /** - * @return mixed - */ - private function doExport($value, bool $resolveEnv = false) - { - $shouldCacheValue = $resolveEnv && \is_string($value); - if ($shouldCacheValue && isset($this->exportedVariables[$value])) { - return $this->exportedVariables[$value]; - } - if (\is_string($value) && false !== strpos($value, "\n")) { - $cleanParts = explode("\n", $value); - $cleanParts = array_map(function ($part) { return var_export($part, true); }, $cleanParts); - $export = implode('."\n".', $cleanParts); - } else { - $export = var_export($value, true); - } - - if ($resolveEnv && "'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$this->getEnv('string:%s').'")) { - $export = $resolvedExport; - if (".''" === substr($export, -3)) { - $export = substr($export, 0, -3); - if ("'" === $export[1]) { - $export = substr_replace($export, '', 18, 7); - } - } - if ("'" === $export[1]) { - $export = substr($export, 3); - } - } - - if ($shouldCacheValue) { - $this->exportedVariables[$value] = $export; - } - - return $export; - } - - private function getAutoloadFile(): ?string - { - if (null === $this->targetDirRegex) { - return null; - } - - foreach (spl_autoload_functions() as $autoloader) { - if (!\is_array($autoloader)) { - continue; - } - - if ($autoloader[0] instanceof DebugClassLoader || $autoloader[0] instanceof LegacyDebugClassLoader) { - $autoloader = $autoloader[0]->getClassLoader(); - } - - if (!\is_array($autoloader) || !$autoloader[0] instanceof ClassLoader || !$autoloader[0]->findFile(__CLASS__)) { - continue; - } - - foreach (get_declared_classes() as $class) { - if (0 === strpos($class, 'ComposerAutoloaderInit') && $class::getLoader() === $autoloader[0]) { - $file = \dirname((new \ReflectionClass($class))->getFileName(), 2).'/autoload.php'; - - if (preg_match($this->targetDirRegex.'A', $file)) { - return $file; - } - } - } - } - - return null; - } -} diff --git a/vendor/symfony/dependency-injection/Dumper/Preloader.php b/vendor/symfony/dependency-injection/Dumper/Preloader.php deleted file mode 100644 index abb7d90..0000000 --- a/vendor/symfony/dependency-injection/Dumper/Preloader.php +++ /dev/null @@ -1,100 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -/** - * @author Nicolas Grekas - * - * @internal - */ -class Preloader -{ - public static function preload(array $classes) - { - set_error_handler(function ($t, $m, $f, $l) { - if (error_reporting() & $t) { - if (__FILE__ !== $f) { - throw new \ErrorException($m, 0, $t, $f, $l); - } - - throw new \ReflectionException($m); - } - }); - - $prev = []; - $preloaded = []; - - try { - while ($prev !== $classes) { - $prev = $classes; - foreach ($classes as $c) { - if (!isset($preloaded[$c])) { - self::doPreload($c, $preloaded); - } - } - $classes = array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits()); - } - } finally { - restore_error_handler(); - } - } - - private static function doPreload(string $class, array &$preloaded) - { - if (isset($preloaded[$class]) || \in_array($class, ['self', 'static', 'parent'], true)) { - return; - } - - $preloaded[$class] = true; - - try { - $r = new \ReflectionClass($class); - - if ($r->isInternal()) { - return; - } - - $r->getConstants(); - $r->getDefaultProperties(); - - if (\PHP_VERSION_ID >= 70400) { - foreach ($r->getProperties(\ReflectionProperty::IS_PUBLIC) as $p) { - if (($t = $p->getType()) && !$t->isBuiltin()) { - self::doPreload($t->getName(), $preloaded); - } - } - } - - foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $m) { - foreach ($m->getParameters() as $p) { - if ($p->isDefaultValueAvailable() && $p->isDefaultValueConstant()) { - $c = $p->getDefaultValueConstantName(); - - if ($i = strpos($c, '::')) { - self::doPreload(substr($c, 0, $i), $preloaded); - } - } - - if (($t = $p->getType()) && !$t->isBuiltin()) { - self::doPreload($t->getName(), $preloaded); - } - } - - if (($t = $m->getReturnType()) && !$t->isBuiltin()) { - self::doPreload($t->getName(), $preloaded); - } - } - } catch (\ReflectionException $e) { - // ignore missing classes - } - } -} diff --git a/vendor/symfony/dependency-injection/Dumper/XmlDumper.php b/vendor/symfony/dependency-injection/Dumper/XmlDumper.php deleted file mode 100644 index fb5d827..0000000 --- a/vendor/symfony/dependency-injection/Dumper/XmlDumper.php +++ /dev/null @@ -1,374 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\ExpressionLanguage\Expression; - -/** - * XmlDumper dumps a service container as an XML string. - * - * @author Fabien Potencier - * @author Martin Hasoň - */ -class XmlDumper extends Dumper -{ - /** - * @var \DOMDocument - */ - private $document; - - /** - * Dumps the service container as an XML string. - * - * @return string An xml string representing of the service container - */ - public function dump(array $options = []) - { - $this->document = new \DOMDocument('1.0', 'utf-8'); - $this->document->formatOutput = true; - - $container = $this->document->createElementNS('http://symfony.com/schema/dic/services', 'container'); - $container->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); - $container->setAttribute('xsi:schemaLocation', 'http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd'); - - $this->addParameters($container); - $this->addServices($container); - - $this->document->appendChild($container); - $xml = $this->document->saveXML(); - $this->document = null; - - return $this->container->resolveEnvPlaceholders($xml); - } - - private function addParameters(\DOMElement $parent) - { - $data = $this->container->getParameterBag()->all(); - if (!$data) { - return; - } - - if ($this->container->isCompiled()) { - $data = $this->escape($data); - } - - $parameters = $this->document->createElement('parameters'); - $parent->appendChild($parameters); - $this->convertParameters($data, 'parameter', $parameters); - } - - private function addMethodCalls(array $methodcalls, \DOMElement $parent) - { - foreach ($methodcalls as $methodcall) { - $call = $this->document->createElement('call'); - $call->setAttribute('method', $methodcall[0]); - if (\count($methodcall[1])) { - $this->convertParameters($methodcall[1], 'argument', $call); - } - if ($methodcall[2] ?? false) { - $call->setAttribute('returns-clone', 'true'); - } - $parent->appendChild($call); - } - } - - private function addService(Definition $definition, ?string $id, \DOMElement $parent) - { - $service = $this->document->createElement('service'); - if (null !== $id) { - $service->setAttribute('id', $id); - } - if ($class = $definition->getClass()) { - if ('\\' === substr($class, 0, 1)) { - $class = substr($class, 1); - } - - $service->setAttribute('class', $class); - } - if (!$definition->isShared()) { - $service->setAttribute('shared', 'false'); - } - if (!$definition->isPrivate()) { - $service->setAttribute('public', $definition->isPublic() ? 'true' : 'false'); - } - if ($definition->isSynthetic()) { - $service->setAttribute('synthetic', 'true'); - } - if ($definition->isLazy()) { - $service->setAttribute('lazy', 'true'); - } - if (null !== $decoratedService = $definition->getDecoratedService()) { - list($decorated, $renamedId, $priority) = $decoratedService; - $service->setAttribute('decorates', $decorated); - - $decorationOnInvalid = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - if (\in_array($decorationOnInvalid, [ContainerInterface::IGNORE_ON_INVALID_REFERENCE, ContainerInterface::NULL_ON_INVALID_REFERENCE], true)) { - $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE === $decorationOnInvalid ? 'null' : 'ignore'; - $service->setAttribute('decoration-on-invalid', $invalidBehavior); - } - if (null !== $renamedId) { - $service->setAttribute('decoration-inner-name', $renamedId); - } - if (0 !== $priority) { - $service->setAttribute('decoration-priority', $priority); - } - } - - foreach ($definition->getTags() as $name => $tags) { - foreach ($tags as $attributes) { - $tag = $this->document->createElement('tag'); - $tag->setAttribute('name', $name); - foreach ($attributes as $key => $value) { - $tag->setAttribute($key, $value); - } - $service->appendChild($tag); - } - } - - if ($definition->getFile()) { - $file = $this->document->createElement('file'); - $file->appendChild($this->document->createTextNode($definition->getFile())); - $service->appendChild($file); - } - - if ($parameters = $definition->getArguments()) { - $this->convertParameters($parameters, 'argument', $service); - } - - if ($parameters = $definition->getProperties()) { - $this->convertParameters($parameters, 'property', $service, 'name'); - } - - $this->addMethodCalls($definition->getMethodCalls(), $service); - - if ($callable = $definition->getFactory()) { - $factory = $this->document->createElement('factory'); - - if (\is_array($callable) && $callable[0] instanceof Definition) { - $this->addService($callable[0], null, $factory); - $factory->setAttribute('method', $callable[1]); - } elseif (\is_array($callable)) { - if (null !== $callable[0]) { - $factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); - } - $factory->setAttribute('method', $callable[1]); - } else { - $factory->setAttribute('function', $callable); - } - $service->appendChild($factory); - } - - if ($definition->isDeprecated()) { - $deprecated = $this->document->createElement('deprecated'); - $deprecated->appendChild($this->document->createTextNode($definition->getDeprecationMessage('%service_id%'))); - - $service->appendChild($deprecated); - } - - if ($definition->isAutowired()) { - $service->setAttribute('autowire', 'true'); - } - - if ($definition->isAutoconfigured()) { - $service->setAttribute('autoconfigure', 'true'); - } - - if ($definition->isAbstract()) { - $service->setAttribute('abstract', 'true'); - } - - if ($callable = $definition->getConfigurator()) { - $configurator = $this->document->createElement('configurator'); - - if (\is_array($callable) && $callable[0] instanceof Definition) { - $this->addService($callable[0], null, $configurator); - $configurator->setAttribute('method', $callable[1]); - } elseif (\is_array($callable)) { - $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]); - $configurator->setAttribute('method', $callable[1]); - } else { - $configurator->setAttribute('function', $callable); - } - $service->appendChild($configurator); - } - - $parent->appendChild($service); - } - - private function addServiceAlias(string $alias, Alias $id, \DOMElement $parent) - { - $service = $this->document->createElement('service'); - $service->setAttribute('id', $alias); - $service->setAttribute('alias', $id); - if (!$id->isPrivate()) { - $service->setAttribute('public', $id->isPublic() ? 'true' : 'false'); - } - - if ($id->isDeprecated()) { - $deprecated = $this->document->createElement('deprecated'); - $deprecated->appendChild($this->document->createTextNode($id->getDeprecationMessage('%alias_id%'))); - - $service->appendChild($deprecated); - } - - $parent->appendChild($service); - } - - private function addServices(\DOMElement $parent) - { - $definitions = $this->container->getDefinitions(); - if (!$definitions) { - return; - } - - $services = $this->document->createElement('services'); - foreach ($definitions as $id => $definition) { - $this->addService($definition, $id, $services); - } - - $aliases = $this->container->getAliases(); - foreach ($aliases as $alias => $id) { - while (isset($aliases[(string) $id])) { - $id = $aliases[(string) $id]; - } - $this->addServiceAlias($alias, $id, $services); - } - $parent->appendChild($services); - } - - private function convertParameters(array $parameters, string $type, \DOMElement $parent, string $keyAttribute = 'key') - { - $withKeys = array_keys($parameters) !== range(0, \count($parameters) - 1); - foreach ($parameters as $key => $value) { - $element = $this->document->createElement($type); - if ($withKeys) { - $element->setAttribute($keyAttribute, $key); - } - - if ($value instanceof ServiceClosureArgument) { - $value = $value->getValues()[0]; - } - if (\is_array($tag = $value)) { - $element->setAttribute('type', 'collection'); - $this->convertParameters($value, $type, $element, 'key'); - } elseif ($value instanceof TaggedIteratorArgument || ($value instanceof ServiceLocatorArgument && $tag = $value->getTaggedIteratorArgument())) { - $element->setAttribute('type', $value instanceof TaggedIteratorArgument ? 'tagged_iterator' : 'tagged_locator'); - $element->setAttribute('tag', $tag->getTag()); - - if (null !== $tag->getIndexAttribute()) { - $element->setAttribute('index-by', $tag->getIndexAttribute()); - - if (null !== $tag->getDefaultIndexMethod()) { - $element->setAttribute('default-index-method', $tag->getDefaultIndexMethod()); - } - if (null !== $tag->getDefaultPriorityMethod()) { - $element->setAttribute('default-priority-method', $tag->getDefaultPriorityMethod()); - } - } - } elseif ($value instanceof IteratorArgument) { - $element->setAttribute('type', 'iterator'); - $this->convertParameters($value->getValues(), $type, $element, 'key'); - } elseif ($value instanceof ServiceLocatorArgument) { - $element->setAttribute('type', 'service_locator'); - $this->convertParameters($value->getValues(), $type, $element, 'key'); - } elseif ($value instanceof Reference) { - $element->setAttribute('type', 'service'); - $element->setAttribute('id', (string) $value); - $behavior = $value->getInvalidBehavior(); - if (ContainerInterface::NULL_ON_INVALID_REFERENCE == $behavior) { - $element->setAttribute('on-invalid', 'null'); - } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE == $behavior) { - $element->setAttribute('on-invalid', 'ignore'); - } elseif (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE == $behavior) { - $element->setAttribute('on-invalid', 'ignore_uninitialized'); - } - } elseif ($value instanceof Definition) { - $element->setAttribute('type', 'service'); - $this->addService($value, null, $element); - } elseif ($value instanceof Expression) { - $element->setAttribute('type', 'expression'); - $text = $this->document->createTextNode(self::phpToXml((string) $value)); - $element->appendChild($text); - } elseif (\is_string($value) && !preg_match('/^[^\x00-\x08\x0B\x0E-\x1A\x1C-\x1F\x7F]*+$/u', $value)) { - $element->setAttribute('type', 'binary'); - $text = $this->document->createTextNode(self::phpToXml(base64_encode($value))); - $element->appendChild($text); - } else { - if (\in_array($value, ['null', 'true', 'false'], true)) { - $element->setAttribute('type', 'string'); - } - - if (\is_string($value) && (is_numeric($value) || preg_match('/^0b[01]*$/', $value) || preg_match('/^0x[0-9a-f]++$/i', $value))) { - $element->setAttribute('type', 'string'); - } - - $text = $this->document->createTextNode(self::phpToXml($value)); - $element->appendChild($text); - } - $parent->appendChild($element); - } - } - - /** - * Escapes arguments. - */ - private function escape(array $arguments): array - { - $args = []; - foreach ($arguments as $k => $v) { - if (\is_array($v)) { - $args[$k] = $this->escape($v); - } elseif (\is_string($v)) { - $args[$k] = str_replace('%', '%%', $v); - } else { - $args[$k] = $v; - } - } - - return $args; - } - - /** - * Converts php types to xml types. - * - * @param mixed $value Value to convert - * - * @throws RuntimeException When trying to dump object or resource - */ - public static function phpToXml($value): string - { - switch (true) { - case null === $value: - return 'null'; - case true === $value: - return 'true'; - case false === $value: - return 'false'; - case $value instanceof Parameter: - return '%'.$value.'%'; - case \is_object($value) || \is_resource($value): - throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); - default: - return (string) $value; - } - } -} diff --git a/vendor/symfony/dependency-injection/Dumper/YamlDumper.php b/vendor/symfony/dependency-injection/Dumper/YamlDumper.php deleted file mode 100644 index ccb68ee..0000000 --- a/vendor/symfony/dependency-injection/Dumper/YamlDumper.php +++ /dev/null @@ -1,349 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Dumper; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\ExpressionLanguage\Expression; -use Symfony\Component\Yaml\Dumper as YmlDumper; -use Symfony\Component\Yaml\Parser; -use Symfony\Component\Yaml\Tag\TaggedValue; -use Symfony\Component\Yaml\Yaml; - -/** - * YamlDumper dumps a service container as a YAML string. - * - * @author Fabien Potencier - */ -class YamlDumper extends Dumper -{ - private $dumper; - - /** - * Dumps the service container as an YAML string. - * - * @return string A YAML string representing of the service container - */ - public function dump(array $options = []) - { - if (!class_exists('Symfony\Component\Yaml\Dumper')) { - throw new LogicException('Unable to dump the container as the Symfony Yaml Component is not installed.'); - } - - if (null === $this->dumper) { - $this->dumper = new YmlDumper(); - } - - return $this->container->resolveEnvPlaceholders($this->addParameters()."\n".$this->addServices()); - } - - private function addService(string $id, Definition $definition): string - { - $code = " $id:\n"; - if ($class = $definition->getClass()) { - if ('\\' === substr($class, 0, 1)) { - $class = substr($class, 1); - } - - $code .= sprintf(" class: %s\n", $this->dumper->dump($class)); - } - - if (!$definition->isPrivate()) { - $code .= sprintf(" public: %s\n", $definition->isPublic() ? 'true' : 'false'); - } - - $tagsCode = ''; - foreach ($definition->getTags() as $name => $tags) { - foreach ($tags as $attributes) { - $att = []; - foreach ($attributes as $key => $value) { - $att[] = sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value)); - } - $att = $att ? ', '.implode(', ', $att) : ''; - - $tagsCode .= sprintf(" - { name: %s%s }\n", $this->dumper->dump($name), $att); - } - } - if ($tagsCode) { - $code .= " tags:\n".$tagsCode; - } - - if ($definition->getFile()) { - $code .= sprintf(" file: %s\n", $this->dumper->dump($definition->getFile())); - } - - if ($definition->isSynthetic()) { - $code .= " synthetic: true\n"; - } - - if ($definition->isDeprecated()) { - $code .= sprintf(" deprecated: %s\n", $this->dumper->dump($definition->getDeprecationMessage('%service_id%'))); - } - - if ($definition->isAutowired()) { - $code .= " autowire: true\n"; - } - - if ($definition->isAutoconfigured()) { - $code .= " autoconfigure: true\n"; - } - - if ($definition->isAbstract()) { - $code .= " abstract: true\n"; - } - - if ($definition->isLazy()) { - $code .= " lazy: true\n"; - } - - if ($definition->getArguments()) { - $code .= sprintf(" arguments: %s\n", $this->dumper->dump($this->dumpValue($definition->getArguments()), 0)); - } - - if ($definition->getProperties()) { - $code .= sprintf(" properties: %s\n", $this->dumper->dump($this->dumpValue($definition->getProperties()), 0)); - } - - if ($definition->getMethodCalls()) { - $code .= sprintf(" calls:\n%s\n", $this->dumper->dump($this->dumpValue($definition->getMethodCalls()), 1, 12)); - } - - if (!$definition->isShared()) { - $code .= " shared: false\n"; - } - - if (null !== $decoratedService = $definition->getDecoratedService()) { - list($decorated, $renamedId, $priority) = $decoratedService; - $code .= sprintf(" decorates: %s\n", $decorated); - if (null !== $renamedId) { - $code .= sprintf(" decoration_inner_name: %s\n", $renamedId); - } - if (0 !== $priority) { - $code .= sprintf(" decoration_priority: %s\n", $priority); - } - - $decorationOnInvalid = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - if (\in_array($decorationOnInvalid, [ContainerInterface::IGNORE_ON_INVALID_REFERENCE, ContainerInterface::NULL_ON_INVALID_REFERENCE])) { - $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE === $decorationOnInvalid ? 'null' : 'ignore'; - $code .= sprintf(" decoration_on_invalid: %s\n", $invalidBehavior); - } - } - - if ($callable = $definition->getFactory()) { - $code .= sprintf(" factory: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0)); - } - - if ($callable = $definition->getConfigurator()) { - $code .= sprintf(" configurator: %s\n", $this->dumper->dump($this->dumpCallable($callable), 0)); - } - - return $code; - } - - private function addServiceAlias(string $alias, Alias $id): string - { - $deprecated = $id->isDeprecated() ? sprintf(" deprecated: %s\n", $id->getDeprecationMessage('%alias_id%')) : ''; - - if ($id->isPrivate()) { - return sprintf(" %s: '@%s'\n%s", $alias, $id, $deprecated); - } - - return sprintf(" %s:\n alias: %s\n public: %s\n%s", $alias, $id, $id->isPublic() ? 'true' : 'false', $deprecated); - } - - private function addServices(): string - { - if (!$this->container->getDefinitions()) { - return ''; - } - - $code = "services:\n"; - foreach ($this->container->getDefinitions() as $id => $definition) { - $code .= $this->addService($id, $definition); - } - - $aliases = $this->container->getAliases(); - foreach ($aliases as $alias => $id) { - while (isset($aliases[(string) $id])) { - $id = $aliases[(string) $id]; - } - $code .= $this->addServiceAlias($alias, $id); - } - - return $code; - } - - private function addParameters(): string - { - if (!$this->container->getParameterBag()->all()) { - return ''; - } - - $parameters = $this->prepareParameters($this->container->getParameterBag()->all(), $this->container->isCompiled()); - - return $this->dumper->dump(['parameters' => $parameters], 2); - } - - /** - * Dumps callable to YAML format. - * - * @param mixed $callable - * - * @return mixed - */ - private function dumpCallable($callable) - { - if (\is_array($callable)) { - if ($callable[0] instanceof Reference) { - $callable = [$this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]]; - } else { - $callable = [$callable[0], $callable[1]]; - } - } - - return $callable; - } - - /** - * Dumps the value to YAML format. - * - * @return mixed - * - * @throws RuntimeException When trying to dump object or resource - */ - private function dumpValue($value) - { - if ($value instanceof ServiceClosureArgument) { - $value = $value->getValues()[0]; - } - if ($value instanceof ArgumentInterface) { - $tag = $value; - - if ($value instanceof TaggedIteratorArgument || ($value instanceof ServiceLocatorArgument && $tag = $value->getTaggedIteratorArgument())) { - if (null === $tag->getIndexAttribute()) { - $content = $tag->getTag(); - } else { - $content = [ - 'tag' => $tag->getTag(), - 'index_by' => $tag->getIndexAttribute(), - ]; - - if (null !== $tag->getDefaultIndexMethod()) { - $content['default_index_method'] = $tag->getDefaultIndexMethod(); - } - if (null !== $tag->getDefaultPriorityMethod()) { - $content['default_priority_method'] = $tag->getDefaultPriorityMethod(); - } - } - - return new TaggedValue($value instanceof TaggedIteratorArgument ? 'tagged_iterator' : 'tagged_locator', $content); - } - - if ($value instanceof IteratorArgument) { - $tag = 'iterator'; - } elseif ($value instanceof ServiceLocatorArgument) { - $tag = 'service_locator'; - } else { - throw new RuntimeException(sprintf('Unspecified Yaml tag for type "%s".', \get_class($value))); - } - - return new TaggedValue($tag, $this->dumpValue($value->getValues())); - } - - if (\is_array($value)) { - $code = []; - foreach ($value as $k => $v) { - $code[$k] = $this->dumpValue($v); - } - - return $code; - } elseif ($value instanceof Reference) { - return $this->getServiceCall((string) $value, $value); - } elseif ($value instanceof Parameter) { - return $this->getParameterCall((string) $value); - } elseif ($value instanceof Expression) { - return $this->getExpressionCall((string) $value); - } elseif ($value instanceof Definition) { - return new TaggedValue('service', (new Parser())->parse("_:\n".$this->addService('_', $value), Yaml::PARSE_CUSTOM_TAGS)['_']['_']); - } elseif (\is_object($value) || \is_resource($value)) { - throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); - } - - return $value; - } - - private function getServiceCall(string $id, Reference $reference = null): string - { - if (null !== $reference) { - switch ($reference->getInvalidBehavior()) { - case ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE: break; - case ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE: break; - case ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE: return sprintf('@!%s', $id); - default: return sprintf('@?%s', $id); - } - } - - return sprintf('@%s', $id); - } - - private function getParameterCall(string $id): string - { - return sprintf('%%%s%%', $id); - } - - private function getExpressionCall(string $expression): string - { - return sprintf('@=%s', $expression); - } - - private function prepareParameters(array $parameters, bool $escape = true): array - { - $filtered = []; - foreach ($parameters as $key => $value) { - if (\is_array($value)) { - $value = $this->prepareParameters($value, $escape); - } elseif ($value instanceof Reference || \is_string($value) && 0 === strpos($value, '@')) { - $value = '@'.$value; - } - - $filtered[$key] = $value; - } - - return $escape ? $this->escape($filtered) : $filtered; - } - - private function escape(array $arguments): array - { - $args = []; - foreach ($arguments as $k => $v) { - if (\is_array($v)) { - $args[$k] = $this->escape($v); - } elseif (\is_string($v)) { - $args[$k] = str_replace('%', '%%', $v); - } else { - $args[$k] = $v; - } - } - - return $args; - } -} diff --git a/vendor/symfony/dependency-injection/EnvVarLoaderInterface.php b/vendor/symfony/dependency-injection/EnvVarLoaderInterface.php deleted file mode 100644 index 0c547f8..0000000 --- a/vendor/symfony/dependency-injection/EnvVarLoaderInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * EnvVarLoaderInterface objects return key/value pairs that are added to the list of available env vars. - * - * @author Nicolas Grekas - */ -interface EnvVarLoaderInterface -{ - /** - * @return string[] Key/value pairs that can be accessed using the regular "%env()%" syntax - */ - public function loadEnvVars(): array; -} diff --git a/vendor/symfony/dependency-injection/EnvVarProcessor.php b/vendor/symfony/dependency-injection/EnvVarProcessor.php deleted file mode 100644 index 0e23d93..0000000 --- a/vendor/symfony/dependency-injection/EnvVarProcessor.php +++ /dev/null @@ -1,280 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; -use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * @author Nicolas Grekas - */ -class EnvVarProcessor implements EnvVarProcessorInterface -{ - private $container; - private $loaders; - private $loadedVars = []; - - /** - * @param EnvVarLoaderInterface[] $loaders - */ - public function __construct(ContainerInterface $container, \Traversable $loaders = null) - { - $this->container = $container; - $this->loaders = new \IteratorIterator($loaders ?? new \ArrayIterator()); - $this->loaders = $this->loaders->getInnerIterator(); - } - - /** - * {@inheritdoc} - */ - public static function getProvidedTypes() - { - return [ - 'base64' => 'string', - 'bool' => 'bool', - 'const' => 'bool|int|float|string|array', - 'csv' => 'array', - 'file' => 'string', - 'float' => 'float', - 'int' => 'int', - 'json' => 'array', - 'key' => 'bool|int|float|string|array', - 'url' => 'array', - 'query_string' => 'array', - 'resolve' => 'string', - 'default' => 'bool|int|float|string|array', - 'string' => 'string', - 'trim' => 'string', - 'require' => 'bool|int|float|string|array', - ]; - } - - /** - * {@inheritdoc} - */ - public function getEnv(string $prefix, string $name, \Closure $getEnv) - { - $i = strpos($name, ':'); - - if ('key' === $prefix) { - if (false === $i) { - throw new RuntimeException(sprintf('Invalid env "key:%s": a key specifier should be provided.', $name)); - } - - $next = substr($name, $i + 1); - $key = substr($name, 0, $i); - $array = $getEnv($next); - - if (!\is_array($array)) { - throw new RuntimeException(sprintf('Resolved value of "%s" did not result in an array value.', $next)); - } - - if (!isset($array[$key]) && !\array_key_exists($key, $array)) { - throw new EnvNotFoundException(sprintf('Key "%s" not found in "%s" (resolved from "%s").', $key, json_encode($array), $next)); - } - - return $array[$key]; - } - - if ('default' === $prefix) { - if (false === $i) { - throw new RuntimeException(sprintf('Invalid env "default:%s": a fallback parameter should be provided.', $name)); - } - - $next = substr($name, $i + 1); - $default = substr($name, 0, $i); - - if ('' !== $default && !$this->container->hasParameter($default)) { - throw new RuntimeException(sprintf('Invalid env fallback in "default:%s": parameter "%s" not found.', $name, $default)); - } - - try { - $env = $getEnv($next); - - if ('' !== $env && null !== $env) { - return $env; - } - } catch (EnvNotFoundException $e) { - // no-op - } - - return '' === $default ? null : $this->container->getParameter($default); - } - - if ('file' === $prefix || 'require' === $prefix) { - if (!is_scalar($file = $getEnv($name))) { - throw new RuntimeException(sprintf('Invalid file name: env var "%s" is non-scalar.', $name)); - } - if (!file_exists($file)) { - throw new EnvNotFoundException(sprintf('File "%s" not found (resolved from "%s").', $file, $name)); - } - - if ('file' === $prefix) { - return file_get_contents($file); - } else { - return require $file; - } - } - - if (false !== $i || 'string' !== $prefix) { - if (null === $env = $getEnv($name)) { - return null; - } - } elseif (isset($_ENV[$name])) { - $env = $_ENV[$name]; - } elseif (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) { - $env = $_SERVER[$name]; - } elseif (false === ($env = getenv($name)) || null === $env) { // null is a possible value because of thread safety issues - foreach ($this->loadedVars as $vars) { - if (false !== $env = ($vars[$name] ?? false)) { - break; - } - } - - $loaders = $this->loaders; - $this->loaders = new \ArrayIterator(); - - try { - while ((false === $env || null === $env) && $loaders->valid()) { - $loader = $loaders->current(); - $loaders->next(); - $this->loadedVars[] = $vars = $loader->loadEnvVars(); - $env = $vars[$name] ?? false; - } - } catch (ParameterCircularReferenceException $e) { - // skip loaders that need an env var that is not defined - } finally { - $this->loaders = $loaders; - } - - if (false === $env || null === $env) { - if (!$this->container->hasParameter("env($name)")) { - throw new EnvNotFoundException(sprintf('Environment variable not found: "%s".', $name)); - } - - if (null === $env = $this->container->getParameter("env($name)")) { - return null; - } - } - } - - if (!is_scalar($env)) { - throw new RuntimeException(sprintf('Non-scalar env var "%s" cannot be cast to %s.', $name, $prefix)); - } - - if ('string' === $prefix) { - return (string) $env; - } - - if ('bool' === $prefix) { - return (bool) (filter_var($env, FILTER_VALIDATE_BOOLEAN) ?: filter_var($env, FILTER_VALIDATE_INT) ?: filter_var($env, FILTER_VALIDATE_FLOAT)); - } - - if ('int' === $prefix) { - if (false === $env = filter_var($env, FILTER_VALIDATE_INT) ?: filter_var($env, FILTER_VALIDATE_FLOAT)) { - throw new RuntimeException(sprintf('Non-numeric env var "%s" cannot be cast to int.', $name)); - } - - return (int) $env; - } - - if ('float' === $prefix) { - if (false === $env = filter_var($env, FILTER_VALIDATE_FLOAT)) { - throw new RuntimeException(sprintf('Non-numeric env var "%s" cannot be cast to float.', $name)); - } - - return (float) $env; - } - - if ('const' === $prefix) { - if (!\defined($env)) { - throw new RuntimeException(sprintf('Env var "%s" maps to undefined constant "%s".', $name, $env)); - } - - return \constant($env); - } - - if ('base64' === $prefix) { - return base64_decode(strtr($env, '-_', '+/')); - } - - if ('json' === $prefix) { - $env = json_decode($env, true); - - if (JSON_ERROR_NONE !== json_last_error()) { - throw new RuntimeException(sprintf('Invalid JSON in env var "%s": '.json_last_error_msg(), $name)); - } - - if (null !== $env && !\is_array($env)) { - throw new RuntimeException(sprintf('Invalid JSON env var "%s": array or null expected, %s given.', $name, \gettype($env))); - } - - return $env; - } - - if ('url' === $prefix) { - $parsedEnv = parse_url($env); - - if (false === $parsedEnv) { - throw new RuntimeException(sprintf('Invalid URL in env var "%s"', $name)); - } - if (!isset($parsedEnv['scheme'], $parsedEnv['host'])) { - throw new RuntimeException(sprintf('Invalid URL env var "%s": schema and host expected, %s given.', $name, $env)); - } - $parsedEnv += [ - 'port' => null, - 'user' => null, - 'pass' => null, - 'path' => null, - 'query' => null, - 'fragment' => null, - ]; - - // remove the '/' separator - $parsedEnv['path'] = '/' === $parsedEnv['path'] ? null : substr($parsedEnv['path'], 1); - - return $parsedEnv; - } - - if ('query_string' === $prefix) { - $queryString = parse_url($env, PHP_URL_QUERY) ?: $env; - parse_str($queryString, $result); - - return $result; - } - - if ('resolve' === $prefix) { - return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($name) { - if (!isset($match[1])) { - return '%'; - } - $value = $this->container->getParameter($match[1]); - if (!is_scalar($value)) { - throw new RuntimeException(sprintf('Parameter "%s" found when resolving env var "%s" must be scalar, "%s" given.', $match[1], $name, \gettype($value))); - } - - return $value; - }, $env); - } - - if ('csv' === $prefix) { - return str_getcsv($env, ',', '"', \PHP_VERSION_ID >= 70400 ? '' : '\\'); - } - - if ('trim' === $prefix) { - return trim($env); - } - - throw new RuntimeException(sprintf('Unsupported env var prefix "%s".', $prefix)); - } -} diff --git a/vendor/symfony/dependency-injection/EnvVarProcessorInterface.php b/vendor/symfony/dependency-injection/EnvVarProcessorInterface.php deleted file mode 100644 index d3275fe..0000000 --- a/vendor/symfony/dependency-injection/EnvVarProcessorInterface.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * The EnvVarProcessorInterface is implemented by objects that manage environment-like variables. - * - * @author Nicolas Grekas - */ -interface EnvVarProcessorInterface -{ - /** - * Returns the value of the given variable as managed by the current instance. - * - * @param string $prefix The namespace of the variable - * @param string $name The name of the variable within the namespace - * @param \Closure $getEnv A closure that allows fetching more env vars - * - * @return mixed - * - * @throws RuntimeException on error - */ - public function getEnv(string $prefix, string $name, \Closure $getEnv); - - /** - * @return string[] The PHP-types managed by getEnv(), keyed by prefixes - */ - public static function getProvidedTypes(); -} diff --git a/vendor/symfony/dependency-injection/Exception/AutowiringFailedException.php b/vendor/symfony/dependency-injection/Exception/AutowiringFailedException.php deleted file mode 100644 index c203b85..0000000 --- a/vendor/symfony/dependency-injection/Exception/AutowiringFailedException.php +++ /dev/null @@ -1,72 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Thrown when a definition cannot be autowired. - */ -class AutowiringFailedException extends RuntimeException -{ - private $serviceId; - private $messageCallback; - - public function __construct(string $serviceId, $message = '', int $code = 0, \Throwable $previous = null) - { - $this->serviceId = $serviceId; - - if ($message instanceof \Closure && \function_exists('xdebug_is_enabled') && xdebug_is_enabled()) { - $message = $message(); - } - - if (!$message instanceof \Closure) { - parent::__construct($message, $code, $previous); - - return; - } - - $this->messageCallback = $message; - parent::__construct('', $code, $previous); - - $this->message = new class($this->message, $this->messageCallback) { - private $message; - private $messageCallback; - - public function __construct(&$message, &$messageCallback) - { - $this->message = &$message; - $this->messageCallback = &$messageCallback; - } - - public function __toString(): string - { - $messageCallback = $this->messageCallback; - $this->messageCallback = null; - - try { - return $this->message = $messageCallback(); - } catch (\Throwable $e) { - return $this->message = $e->getMessage(); - } - } - }; - } - - public function getMessageCallback(): ?\Closure - { - return $this->messageCallback; - } - - public function getServiceId() - { - return $this->serviceId; - } -} diff --git a/vendor/symfony/dependency-injection/Exception/BadMethodCallException.php b/vendor/symfony/dependency-injection/Exception/BadMethodCallException.php deleted file mode 100644 index 959238e..0000000 --- a/vendor/symfony/dependency-injection/Exception/BadMethodCallException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Base BadMethodCallException for Dependency Injection component. - */ -class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/dependency-injection/Exception/EnvNotFoundException.php b/vendor/symfony/dependency-injection/Exception/EnvNotFoundException.php deleted file mode 100644 index 04ac848..0000000 --- a/vendor/symfony/dependency-injection/Exception/EnvNotFoundException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * This exception is thrown when an environment variable is not found. - * - * @author Nicolas Grekas - */ -class EnvNotFoundException extends InvalidArgumentException -{ -} diff --git a/vendor/symfony/dependency-injection/Exception/EnvParameterException.php b/vendor/symfony/dependency-injection/Exception/EnvParameterException.php deleted file mode 100644 index 48b5e48..0000000 --- a/vendor/symfony/dependency-injection/Exception/EnvParameterException.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * This exception wraps exceptions whose messages contain a reference to an env parameter. - * - * @author Nicolas Grekas - */ -class EnvParameterException extends InvalidArgumentException -{ - public function __construct(array $envs, \Throwable $previous = null, string $message = 'Incompatible use of dynamic environment variables "%s" found in parameters.') - { - parent::__construct(sprintf($message, implode('", "', $envs)), 0, $previous); - } -} diff --git a/vendor/symfony/dependency-injection/Exception/ExceptionInterface.php b/vendor/symfony/dependency-injection/Exception/ExceptionInterface.php deleted file mode 100644 index 6202df7..0000000 --- a/vendor/symfony/dependency-injection/Exception/ExceptionInterface.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -use Psr\Container\ContainerExceptionInterface; - -/** - * Base ExceptionInterface for Dependency Injection component. - * - * @author Fabien Potencier - * @author Bulat Shakirzyanov - */ -interface ExceptionInterface extends ContainerExceptionInterface, \Throwable -{ -} diff --git a/vendor/symfony/dependency-injection/Exception/InvalidArgumentException.php b/vendor/symfony/dependency-injection/Exception/InvalidArgumentException.php deleted file mode 100644 index 119bb7d..0000000 --- a/vendor/symfony/dependency-injection/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Base InvalidArgumentException for Dependency Injection component. - * - * @author Bulat Shakirzyanov - */ -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/dependency-injection/Exception/InvalidParameterTypeException.php b/vendor/symfony/dependency-injection/Exception/InvalidParameterTypeException.php deleted file mode 100644 index 206561f..0000000 --- a/vendor/symfony/dependency-injection/Exception/InvalidParameterTypeException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Thrown when trying to inject a parameter into a constructor/method with an incompatible type. - * - * @author Nicolas Grekas - * @author Julien Maulny - */ -class InvalidParameterTypeException extends InvalidArgumentException -{ - public function __construct(string $serviceId, string $type, \ReflectionParameter $parameter) - { - parent::__construct(sprintf('Invalid definition for service "%s": argument %d of "%s::%s" accepts "%s", "%s" passed.', $serviceId, 1 + $parameter->getPosition(), $parameter->getDeclaringClass()->getName(), $parameter->getDeclaringFunction()->getName(), $parameter->getType()->getName(), $type)); - } -} diff --git a/vendor/symfony/dependency-injection/Exception/LogicException.php b/vendor/symfony/dependency-injection/Exception/LogicException.php deleted file mode 100644 index 17a070c..0000000 --- a/vendor/symfony/dependency-injection/Exception/LogicException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Base LogicException for Dependency Injection component. - */ -class LogicException extends \LogicException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/dependency-injection/Exception/OutOfBoundsException.php b/vendor/symfony/dependency-injection/Exception/OutOfBoundsException.php deleted file mode 100644 index a61f143..0000000 --- a/vendor/symfony/dependency-injection/Exception/OutOfBoundsException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Base OutOfBoundsException for Dependency Injection component. - */ -class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php b/vendor/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php deleted file mode 100644 index 2450ccb..0000000 --- a/vendor/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * This exception is thrown when a circular reference in a parameter is detected. - * - * @author Fabien Potencier - */ -class ParameterCircularReferenceException extends RuntimeException -{ - private $parameters; - - public function __construct(array $parameters, \Throwable $previous = null) - { - parent::__construct(sprintf('Circular reference detected for parameter "%s" ("%s" > "%s").', $parameters[0], implode('" > "', $parameters), $parameters[0]), 0, $previous); - - $this->parameters = $parameters; - } - - public function getParameters() - { - return $this->parameters; - } -} diff --git a/vendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php b/vendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php deleted file mode 100644 index 7c0c5e3..0000000 --- a/vendor/symfony/dependency-injection/Exception/ParameterNotFoundException.php +++ /dev/null @@ -1,100 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -use Psr\Container\NotFoundExceptionInterface; - -/** - * This exception is thrown when a non-existent parameter is used. - * - * @author Fabien Potencier - */ -class ParameterNotFoundException extends InvalidArgumentException implements NotFoundExceptionInterface -{ - private $key; - private $sourceId; - private $sourceKey; - private $alternatives; - private $nonNestedAlternative; - - /** - * @param string $key The requested parameter key - * @param string $sourceId The service id that references the non-existent parameter - * @param string $sourceKey The parameter key that references the non-existent parameter - * @param \Throwable $previous The previous exception - * @param string[] $alternatives Some parameter name alternatives - * @param string|null $nonNestedAlternative The alternative parameter name when the user expected dot notation for nested parameters - */ - public function __construct(string $key, string $sourceId = null, string $sourceKey = null, \Throwable $previous = null, array $alternatives = [], string $nonNestedAlternative = null) - { - $this->key = $key; - $this->sourceId = $sourceId; - $this->sourceKey = $sourceKey; - $this->alternatives = $alternatives; - $this->nonNestedAlternative = $nonNestedAlternative; - - parent::__construct('', 0, $previous); - - $this->updateRepr(); - } - - public function updateRepr() - { - if (null !== $this->sourceId) { - $this->message = sprintf('The service "%s" has a dependency on a non-existent parameter "%s".', $this->sourceId, $this->key); - } elseif (null !== $this->sourceKey) { - $this->message = sprintf('The parameter "%s" has a dependency on a non-existent parameter "%s".', $this->sourceKey, $this->key); - } else { - $this->message = sprintf('You have requested a non-existent parameter "%s".', $this->key); - } - - if ($this->alternatives) { - if (1 == \count($this->alternatives)) { - $this->message .= ' Did you mean this: "'; - } else { - $this->message .= ' Did you mean one of these: "'; - } - $this->message .= implode('", "', $this->alternatives).'"?'; - } elseif (null !== $this->nonNestedAlternative) { - $this->message .= ' You cannot access nested array items, do you want to inject "'.$this->nonNestedAlternative.'" instead?'; - } - } - - public function getKey() - { - return $this->key; - } - - public function getSourceId() - { - return $this->sourceId; - } - - public function getSourceKey() - { - return $this->sourceKey; - } - - public function setSourceId($sourceId) - { - $this->sourceId = $sourceId; - - $this->updateRepr(); - } - - public function setSourceKey($sourceKey) - { - $this->sourceKey = $sourceKey; - - $this->updateRepr(); - } -} diff --git a/vendor/symfony/dependency-injection/Exception/RuntimeException.php b/vendor/symfony/dependency-injection/Exception/RuntimeException.php deleted file mode 100644 index 5c24541..0000000 --- a/vendor/symfony/dependency-injection/Exception/RuntimeException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * Base RuntimeException for Dependency Injection component. - * - * @author Johannes M. Schmitt - */ -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php b/vendor/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php deleted file mode 100644 index a38671b..0000000 --- a/vendor/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -/** - * This exception is thrown when a circular reference is detected. - * - * @author Johannes M. Schmitt - */ -class ServiceCircularReferenceException extends RuntimeException -{ - private $serviceId; - private $path; - - public function __construct(string $serviceId, array $path, \Throwable $previous = null) - { - parent::__construct(sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, implode(' -> ', $path)), 0, $previous); - - $this->serviceId = $serviceId; - $this->path = $path; - } - - public function getServiceId() - { - return $this->serviceId; - } - - public function getPath() - { - return $this->path; - } -} diff --git a/vendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php b/vendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php deleted file mode 100644 index f91afae..0000000 --- a/vendor/symfony/dependency-injection/Exception/ServiceNotFoundException.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Exception; - -use Psr\Container\NotFoundExceptionInterface; - -/** - * This exception is thrown when a non-existent service is requested. - * - * @author Johannes M. Schmitt - */ -class ServiceNotFoundException extends InvalidArgumentException implements NotFoundExceptionInterface -{ - private $id; - private $sourceId; - private $alternatives; - - public function __construct(string $id, string $sourceId = null, \Throwable $previous = null, array $alternatives = [], string $msg = null) - { - if (null !== $msg) { - // no-op - } elseif (null === $sourceId) { - $msg = sprintf('You have requested a non-existent service "%s".', $id); - } else { - $msg = sprintf('The service "%s" has a dependency on a non-existent service "%s".', $sourceId, $id); - } - - if ($alternatives) { - if (1 == \count($alternatives)) { - $msg .= ' Did you mean this: "'; - } else { - $msg .= ' Did you mean one of these: "'; - } - $msg .= implode('", "', $alternatives).'"?'; - } - - parent::__construct($msg, 0, $previous); - - $this->id = $id; - $this->sourceId = $sourceId; - $this->alternatives = $alternatives; - } - - public function getId() - { - return $this->id; - } - - public function getSourceId() - { - return $this->sourceId; - } - - public function getAlternatives() - { - return $this->alternatives; - } -} diff --git a/vendor/symfony/dependency-injection/ExpressionLanguage.php b/vendor/symfony/dependency-injection/ExpressionLanguage.php deleted file mode 100644 index 961c737..0000000 --- a/vendor/symfony/dependency-injection/ExpressionLanguage.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; - -if (!class_exists(BaseExpressionLanguage::class)) { - return; -} - -/** - * Adds some function to the default ExpressionLanguage. - * - * @author Fabien Potencier - * - * @see ExpressionLanguageProvider - */ -class ExpressionLanguage extends BaseExpressionLanguage -{ - /** - * {@inheritdoc} - */ - public function __construct(CacheItemPoolInterface $cache = null, array $providers = [], callable $serviceCompiler = null) - { - // prepend the default provider to let users override it easily - array_unshift($providers, new ExpressionLanguageProvider($serviceCompiler)); - - parent::__construct($cache, $providers); - } -} diff --git a/vendor/symfony/dependency-injection/ExpressionLanguageProvider.php b/vendor/symfony/dependency-injection/ExpressionLanguageProvider.php deleted file mode 100644 index 9198ca0..0000000 --- a/vendor/symfony/dependency-injection/ExpressionLanguageProvider.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Symfony\Component\ExpressionLanguage\ExpressionFunction; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; - -/** - * Define some ExpressionLanguage functions. - * - * To get a service, use service('request'). - * To get a parameter, use parameter('kernel.debug'). - * - * @author Fabien Potencier - */ -class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface -{ - private $serviceCompiler; - - public function __construct(callable $serviceCompiler = null) - { - $this->serviceCompiler = $serviceCompiler; - } - - public function getFunctions() - { - return [ - new ExpressionFunction('service', $this->serviceCompiler ?: function ($arg) { - return sprintf('$this->get(%s)', $arg); - }, function (array $variables, $value) { - return $variables['container']->get($value); - }), - - new ExpressionFunction('parameter', function ($arg) { - return sprintf('$this->getParameter(%s)', $arg); - }, function (array $variables, $value) { - return $variables['container']->getParameter($value); - }), - ]; - } -} diff --git a/vendor/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php b/vendor/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php deleted file mode 100644 index c3bd842..0000000 --- a/vendor/symfony/dependency-injection/Extension/ConfigurationExtensionInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Extension; - -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * ConfigurationExtensionInterface is the interface implemented by container extension classes. - * - * @author Kevin Bond - */ -interface ConfigurationExtensionInterface -{ - /** - * Returns extension configuration. - * - * @return ConfigurationInterface|null The configuration or null - */ - public function getConfiguration(array $config, ContainerBuilder $container); -} diff --git a/vendor/symfony/dependency-injection/Extension/Extension.php b/vendor/symfony/dependency-injection/Extension/Extension.php deleted file mode 100644 index ffa4707..0000000 --- a/vendor/symfony/dependency-injection/Extension/Extension.php +++ /dev/null @@ -1,139 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Extension; - -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\Processor; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\LogicException; - -/** - * Provides useful features shared by many extensions. - * - * @author Fabien Potencier - */ -abstract class Extension implements ExtensionInterface, ConfigurationExtensionInterface -{ - private $processedConfigs = []; - - /** - * {@inheritdoc} - */ - public function getXsdValidationBasePath() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function getNamespace() - { - return 'http://example.org/schema/dic/'.$this->getAlias(); - } - - /** - * Returns the recommended alias to use in XML. - * - * This alias is also the mandatory prefix to use when using YAML. - * - * This convention is to remove the "Extension" postfix from the class - * name and then lowercase and underscore the result. So: - * - * AcmeHelloExtension - * - * becomes - * - * acme_hello - * - * This can be overridden in a sub-class to specify the alias manually. - * - * @return string The alias - * - * @throws BadMethodCallException When the extension name does not follow conventions - */ - public function getAlias() - { - $className = \get_class($this); - if ('Extension' != substr($className, -9)) { - throw new BadMethodCallException('This extension does not follow the naming convention; you must overwrite the getAlias() method.'); - } - $classBaseName = substr(strrchr($className, '\\'), 1, -9); - - return Container::underscore($classBaseName); - } - - /** - * {@inheritdoc} - */ - public function getConfiguration(array $config, ContainerBuilder $container) - { - $class = \get_class($this); - - if (false !== strpos($class, "\0")) { - return null; // ignore anonymous classes - } - - $class = substr_replace($class, '\Configuration', strrpos($class, '\\')); - $class = $container->getReflectionClass($class); - - if (!$class) { - return null; - } - - if (!$class->implementsInterface(ConfigurationInterface::class)) { - throw new LogicException(sprintf('The extension configuration class "%s" must implement "%s".', $class->getName(), ConfigurationInterface::class)); - } - - if (!($constructor = $class->getConstructor()) || !$constructor->getNumberOfRequiredParameters()) { - return $class->newInstance(); - } - - return null; - } - - final protected function processConfiguration(ConfigurationInterface $configuration, array $configs): array - { - $processor = new Processor(); - - return $this->processedConfigs[] = $processor->processConfiguration($configuration, $configs); - } - - /** - * @internal - */ - final public function getProcessedConfigs(): array - { - try { - return $this->processedConfigs; - } finally { - $this->processedConfigs = []; - } - } - - /** - * @return bool Whether the configuration is enabled - * - * @throws InvalidArgumentException When the config is not enableable - */ - protected function isConfigEnabled(ContainerBuilder $container, array $config) - { - if (!\array_key_exists('enabled', $config)) { - throw new InvalidArgumentException("The config array has no 'enabled' key."); - } - - return (bool) $container->getParameterBag()->resolveValue($config['enabled']); - } -} diff --git a/vendor/symfony/dependency-injection/Extension/ExtensionInterface.php b/vendor/symfony/dependency-injection/Extension/ExtensionInterface.php deleted file mode 100644 index 6a7a2cf..0000000 --- a/vendor/symfony/dependency-injection/Extension/ExtensionInterface.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Extension; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * ExtensionInterface is the interface implemented by container extension classes. - * - * @author Fabien Potencier - */ -interface ExtensionInterface -{ - /** - * Loads a specific configuration. - * - * @throws \InvalidArgumentException When provided tag is not defined in this extension - */ - public function load(array $configs, ContainerBuilder $container); - - /** - * Returns the namespace to be used for this extension (XML namespace). - * - * @return string The XML namespace - */ - public function getNamespace(); - - /** - * Returns the base path for the XSD files. - * - * @return string|false - */ - public function getXsdValidationBasePath(); - - /** - * Returns the recommended alias to use in XML. - * - * This alias is also the mandatory prefix to use when using YAML. - * - * @return string The alias - */ - public function getAlias(); -} diff --git a/vendor/symfony/dependency-injection/Extension/PrependExtensionInterface.php b/vendor/symfony/dependency-injection/Extension/PrependExtensionInterface.php deleted file mode 100644 index 5bd18d7..0000000 --- a/vendor/symfony/dependency-injection/Extension/PrependExtensionInterface.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Extension; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -interface PrependExtensionInterface -{ - /** - * Allow an extension to prepend the extension configurations. - */ - public function prepend(ContainerBuilder $container); -} diff --git a/vendor/symfony/dependency-injection/LICENSE b/vendor/symfony/dependency-injection/LICENSE deleted file mode 100644 index a677f43..0000000 --- a/vendor/symfony/dependency-injection/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php b/vendor/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php deleted file mode 100644 index a9d7811..0000000 --- a/vendor/symfony/dependency-injection/LazyProxy/Instantiator/InstantiatorInterface.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; - -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; - -/** - * Lazy proxy instantiator, capable of instantiating a proxy given a container, the - * service definitions and a callback that produces the real service instance. - * - * @author Marco Pivetta - */ -interface InstantiatorInterface -{ - /** - * Instantiates a proxy object. - * - * @param string $id Identifier of the requested service - * @param callable $realInstantiator Zero-argument callback that is capable of producing the real service instance - * - * @return object - */ - public function instantiateProxy(ContainerInterface $container, Definition $definition, string $id, callable $realInstantiator); -} diff --git a/vendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php b/vendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php deleted file mode 100644 index 1696e7a..0000000 --- a/vendor/symfony/dependency-injection/LazyProxy/Instantiator/RealServiceInstantiator.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator; - -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; - -/** - * {@inheritdoc} - * - * Noop proxy instantiator - produces the real service instead of a proxy instance. - * - * @author Marco Pivetta - */ -class RealServiceInstantiator implements InstantiatorInterface -{ - /** - * {@inheritdoc} - */ - public function instantiateProxy(ContainerInterface $container, Definition $definition, string $id, callable $realInstantiator) - { - return $realInstantiator(); - } -} diff --git a/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php b/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php deleted file mode 100644 index 351560d..0000000 --- a/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; - -use Symfony\Component\DependencyInjection\Definition; - -/** - * Lazy proxy dumper capable of generating the instantiation logic PHP code for proxied services. - * - * @author Marco Pivetta - */ -interface DumperInterface -{ - /** - * Inspects whether the given definitions should produce proxy instantiation logic in the dumped container. - * - * @return bool - */ - public function isProxyCandidate(Definition $definition); - - /** - * Generates the code to be used to instantiate a proxy in the dumped factory code. - * - * @return string - */ - public function getProxyFactoryCode(Definition $definition, string $id, string $factoryCode); - - /** - * Generates the code for the lazy proxy. - * - * @return string - */ - public function getProxyCode(Definition $definition); -} diff --git a/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php b/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php deleted file mode 100644 index 7e0f14c..0000000 --- a/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper; - -use Symfony\Component\DependencyInjection\Definition; - -/** - * Null dumper, negates any proxy code generation for any given service definition. - * - * @author Marco Pivetta - * - * @final - */ -class NullDumper implements DumperInterface -{ - /** - * {@inheritdoc} - */ - public function isProxyCandidate(Definition $definition): bool - { - return false; - } - - /** - * {@inheritdoc} - */ - public function getProxyFactoryCode(Definition $definition, string $id, string $factoryCode): string - { - return ''; - } - - /** - * {@inheritdoc} - */ - public function getProxyCode(Definition $definition): string - { - return ''; - } -} diff --git a/vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php b/vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php deleted file mode 100644 index e5611bc..0000000 --- a/vendor/symfony/dependency-injection/LazyProxy/ProxyHelper.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\LazyProxy; - -/** - * @author Nicolas Grekas - * - * @internal - */ -class ProxyHelper -{ - /** - * @return string|null The FQCN or builtin name of the type hint, or null when the type hint references an invalid self|parent context - */ - public static function getTypeHint(\ReflectionFunctionAbstract $r, \ReflectionParameter $p = null, bool $noBuiltin = false): ?string - { - if ($p instanceof \ReflectionParameter) { - $type = $p->getType(); - } else { - $type = $r->getReturnType(); - } - if (!$type) { - return null; - } - if (!\is_string($type)) { - $name = $type->getName(); - - if ($type->isBuiltin()) { - return $noBuiltin ? null : $name; - } - } - $lcName = strtolower($name); - $prefix = $noBuiltin ? '' : '\\'; - - if ('self' !== $lcName && 'parent' !== $lcName) { - return $prefix.$name; - } - if (!$r instanceof \ReflectionMethod) { - return null; - } - if ('self' === $lcName) { - return $prefix.$r->getDeclaringClass()->name; - } - - return ($parent = $r->getDeclaringClass()->getParentClass()) ? $prefix.$parent->name : null; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/ClosureLoader.php b/vendor/symfony/dependency-injection/Loader/ClosureLoader.php deleted file mode 100644 index 57aa83d..0000000 --- a/vendor/symfony/dependency-injection/Loader/ClosureLoader.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -use Symfony\Component\Config\Loader\Loader; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * ClosureLoader loads service definitions from a PHP closure. - * - * The Closure has access to the container as its first argument. - * - * @author Fabien Potencier - */ -class ClosureLoader extends Loader -{ - private $container; - - public function __construct(ContainerBuilder $container) - { - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - $resource($this->container); - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return $resource instanceof \Closure; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php deleted file mode 100644 index 539eb39..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\ExpressionLanguage\Expression; - -abstract class AbstractConfigurator -{ - const FACTORY = 'unknown'; - - /** @internal */ - protected $definition; - - public function __call(string $method, array $args) - { - if (method_exists($this, 'set'.$method)) { - return $this->{'set'.$method}(...$args); - } - - throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', \get_class($this), $method)); - } - - /** - * Checks that a value is valid, optionally replacing Definition and Reference configurators by their configure value. - * - * @param mixed $value - * @param bool $allowServices whether Definition and Reference are allowed; by default, only scalars and arrays are - * - * @return mixed the value, optionally cast to a Definition/Reference - */ - public static function processValue($value, $allowServices = false) - { - if (\is_array($value)) { - foreach ($value as $k => $v) { - $value[$k] = static::processValue($v, $allowServices); - } - - return $value; - } - - if ($value instanceof ReferenceConfigurator) { - return new Reference($value->id, $value->invalidBehavior); - } - - if ($value instanceof InlineServiceConfigurator) { - $def = $value->definition; - $value->definition = null; - - return $def; - } - - if ($value instanceof self) { - throw new InvalidArgumentException(sprintf('"%s()" can be used only at the root of service configuration files.', $value::FACTORY)); - } - - switch (true) { - case null === $value: - case is_scalar($value): - return $value; - - case $value instanceof ArgumentInterface: - case $value instanceof Definition: - case $value instanceof Expression: - case $value instanceof Parameter: - case $value instanceof Reference: - if ($allowServices) { - return $value; - } - } - - throw new InvalidArgumentException(sprintf('Cannot use values of type "%s" in service configuration files.', \is_object($value) ? \get_class($value) : \gettype($value))); - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php deleted file mode 100644 index 9d3305e..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php +++ /dev/null @@ -1,93 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; - -abstract class AbstractServiceConfigurator extends AbstractConfigurator -{ - protected $parent; - protected $id; - private $defaultTags = []; - - public function __construct(ServicesConfigurator $parent, Definition $definition, string $id = null, array $defaultTags = []) - { - $this->parent = $parent; - $this->definition = $definition; - $this->id = $id; - $this->defaultTags = $defaultTags; - } - - public function __destruct() - { - // default tags should be added last - foreach ($this->defaultTags as $name => $attributes) { - foreach ($attributes as $attributes) { - $this->definition->addTag($name, $attributes); - } - } - $this->defaultTags = []; - } - - /** - * Registers a service. - */ - final public function set(string $id, string $class = null): ServiceConfigurator - { - $this->__destruct(); - - return $this->parent->set($id, $class); - } - - /** - * Creates an alias. - */ - final public function alias(string $id, string $referencedId): AliasConfigurator - { - $this->__destruct(); - - return $this->parent->alias($id, $referencedId); - } - - /** - * Registers a PSR-4 namespace using a glob pattern. - */ - final public function load(string $namespace, string $resource): PrototypeConfigurator - { - $this->__destruct(); - - return $this->parent->load($namespace, $resource); - } - - /** - * Gets an already defined service definition. - * - * @throws ServiceNotFoundException if the service definition does not exist - */ - final public function get(string $id): ServiceConfigurator - { - $this->__destruct(); - - return $this->parent->get($id); - } - - /** - * Registers a service. - */ - final public function __invoke(string $id, string $class = null): ServiceConfigurator - { - $this->__destruct(); - - return $this->parent->set($id, $class); - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php deleted file mode 100644 index cb00f58..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/AliasConfigurator.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Alias; - -/** - * @author Nicolas Grekas - */ -class AliasConfigurator extends AbstractServiceConfigurator -{ - const FACTORY = 'alias'; - - use Traits\PublicTrait; - - public function __construct(ServicesConfigurator $parent, Alias $alias) - { - $this->parent = $parent; - $this->definition = $alias; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php deleted file mode 100644 index 28c9d79..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php +++ /dev/null @@ -1,132 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; -use Symfony\Component\ExpressionLanguage\Expression; - -/** - * @author Nicolas Grekas - */ -class ContainerConfigurator extends AbstractConfigurator -{ - const FACTORY = 'container'; - - private $container; - private $loader; - private $instanceof; - private $path; - private $file; - private $anonymousCount = 0; - - public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, string $path, string $file) - { - $this->container = $container; - $this->loader = $loader; - $this->instanceof = &$instanceof; - $this->path = $path; - $this->file = $file; - } - - final public function extension(string $namespace, array $config) - { - if (!$this->container->hasExtension($namespace)) { - $extensions = array_filter(array_map(function (ExtensionInterface $ext) { return $ext->getAlias(); }, $this->container->getExtensions())); - throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $namespace, $this->file, $namespace, $extensions ? sprintf('"%s"', implode('", "', $extensions)) : 'none')); - } - - $this->container->loadFromExtension($namespace, static::processValue($config)); - } - - final public function import(string $resource, string $type = null, $ignoreErrors = false) - { - $this->loader->setCurrentDir(\dirname($this->path)); - $this->loader->import($resource, $type, $ignoreErrors, $this->file); - } - - final public function parameters(): ParametersConfigurator - { - return new ParametersConfigurator($this->container); - } - - final public function services(): ServicesConfigurator - { - return new ServicesConfigurator($this->container, $this->loader, $this->instanceof, $this->path, $this->anonymousCount); - } -} - -/** - * Creates a service reference. - */ -function ref(string $id): ReferenceConfigurator -{ - return new ReferenceConfigurator($id); -} - -/** - * Creates an inline service. - */ -function inline(string $class = null): InlineServiceConfigurator -{ - return new InlineServiceConfigurator(new Definition($class)); -} - -/** - * Creates a service locator. - * - * @param ReferenceConfigurator[] $values - */ -function service_locator(array $values): ServiceLocatorArgument -{ - return new ServiceLocatorArgument(AbstractConfigurator::processValue($values, true)); -} - -/** - * Creates a lazy iterator. - * - * @param ReferenceConfigurator[] $values - */ -function iterator(array $values): IteratorArgument -{ - return new IteratorArgument(AbstractConfigurator::processValue($values, true)); -} - -/** - * Creates a lazy iterator by tag name. - */ -function tagged_iterator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, string $defaultPriorityMethod = null): TaggedIteratorArgument -{ - return new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, false, $defaultPriorityMethod); -} - -/** - * Creates a service locator by tag name. - */ -function tagged_locator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null): ServiceLocatorArgument -{ - return new ServiceLocatorArgument(new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, true)); -} - -/** - * Creates an expression. - */ -function expr(string $expression): Expression -{ - return new Expression($expression); -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php deleted file mode 100644 index cd9088f..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php +++ /dev/null @@ -1,69 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * @author Nicolas Grekas - */ -class DefaultsConfigurator extends AbstractServiceConfigurator -{ - const FACTORY = 'defaults'; - - use Traits\AutoconfigureTrait; - use Traits\AutowireTrait; - use Traits\BindTrait; - use Traits\PublicTrait; - - private $path; - - public function __construct(ServicesConfigurator $parent, Definition $definition, string $path = null) - { - parent::__construct($parent, $definition, null, []); - - $this->path = $path; - } - - /** - * Adds a tag for this definition. - * - * @return $this - * - * @throws InvalidArgumentException when an invalid tag name or attribute is provided - */ - final public function tag(string $name, array $attributes = []): self - { - if ('' === $name) { - throw new InvalidArgumentException('The tag name in "_defaults" must be a non-empty string.'); - } - - foreach ($attributes as $attribute => $value) { - if (null !== $value && !is_scalar($value)) { - throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type.', $name, $attribute)); - } - } - - $this->definition->addTag($name, $attributes); - - return $this; - } - - /** - * Defines an instanceof-conditional to be applied to following service definitions. - */ - final public function instanceof(string $fqcn): InstanceofConfigurator - { - return $this->parent->instanceof($fqcn); - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php deleted file mode 100644 index 362b374..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/InlineServiceConfigurator.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Definition; - -/** - * @author Nicolas Grekas - */ -class InlineServiceConfigurator extends AbstractConfigurator -{ - const FACTORY = 'inline'; - - use Traits\ArgumentTrait; - use Traits\AutowireTrait; - use Traits\BindTrait; - use Traits\FactoryTrait; - use Traits\FileTrait; - use Traits\LazyTrait; - use Traits\ParentTrait; - use Traits\TagTrait; - - public function __construct(Definition $definition) - { - $this->definition = $definition; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php deleted file mode 100644 index f75e176..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Definition; - -/** - * @author Nicolas Grekas - */ -class InstanceofConfigurator extends AbstractServiceConfigurator -{ - const FACTORY = 'instanceof'; - - use Traits\AutowireTrait; - use Traits\CallTrait; - use Traits\ConfiguratorTrait; - use Traits\LazyTrait; - use Traits\PropertyTrait; - use Traits\PublicTrait; - use Traits\ShareTrait; - use Traits\TagTrait; - use Traits\BindTrait; - - private $path; - - public function __construct(ServicesConfigurator $parent, Definition $definition, string $id, string $path = null) - { - parent::__construct($parent, $definition, $id, []); - - $this->path = $path; - } - - /** - * Defines an instanceof-conditional to be applied to following service definitions. - */ - final public function instanceof(string $fqcn): self - { - return $this->parent->instanceof($fqcn); - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php deleted file mode 100644 index a88d28e..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/ParametersConfigurator.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * @author Nicolas Grekas - */ -class ParametersConfigurator extends AbstractConfigurator -{ - const FACTORY = 'parameters'; - - private $container; - - public function __construct(ContainerBuilder $container) - { - $this->container = $container; - } - - /** - * Creates a parameter. - * - * @return $this - */ - final public function set(string $name, $value): self - { - $this->container->setParameter($name, static::processValue($value, true)); - - return $this; - } - - /** - * Creates a parameter. - * - * @return $this - */ - final public function __invoke(string $name, $value): self - { - return $this->set($name, $value); - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php deleted file mode 100644 index 3cd56e0..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php +++ /dev/null @@ -1,84 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; - -/** - * @author Nicolas Grekas - */ -class PrototypeConfigurator extends AbstractServiceConfigurator -{ - const FACTORY = 'load'; - - use Traits\AbstractTrait; - use Traits\ArgumentTrait; - use Traits\AutoconfigureTrait; - use Traits\AutowireTrait; - use Traits\BindTrait; - use Traits\CallTrait; - use Traits\ConfiguratorTrait; - use Traits\DeprecateTrait; - use Traits\FactoryTrait; - use Traits\LazyTrait; - use Traits\ParentTrait; - use Traits\PropertyTrait; - use Traits\PublicTrait; - use Traits\ShareTrait; - use Traits\TagTrait; - - private $loader; - private $resource; - private $excludes; - private $allowParent; - - public function __construct(ServicesConfigurator $parent, PhpFileLoader $loader, Definition $defaults, string $namespace, string $resource, bool $allowParent) - { - $definition = new Definition(); - $definition->setPublic($defaults->isPublic()); - $definition->setAutowired($defaults->isAutowired()); - $definition->setAutoconfigured($defaults->isAutoconfigured()); - $definition->setBindings($defaults->getBindings()); - $definition->setChanges([]); - - $this->loader = $loader; - $this->resource = $resource; - $this->allowParent = $allowParent; - - parent::__construct($parent, $definition, $namespace, $defaults->getTags()); - } - - public function __destruct() - { - parent::__destruct(); - - if ($this->loader) { - $this->loader->registerClasses($this->definition, $this->id, $this->resource, $this->excludes); - } - $this->loader = null; - } - - /** - * Excludes files from registration using glob patterns. - * - * @param string[]|string $excludes - * - * @return $this - */ - final public function exclude($excludes): self - { - $this->excludes = (array) $excludes; - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php deleted file mode 100644 index fa04253..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/ReferenceConfigurator.php +++ /dev/null @@ -1,69 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * @author Nicolas Grekas - */ -class ReferenceConfigurator extends AbstractConfigurator -{ - /** @internal */ - protected $id; - - /** @internal */ - protected $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - - public function __construct(string $id) - { - $this->id = $id; - } - - /** - * @return $this - */ - final public function ignoreOnInvalid(): self - { - $this->invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - - return $this; - } - - /** - * @return $this - */ - final public function nullOnInvalid(): self - { - $this->invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; - - return $this; - } - - /** - * @return $this - */ - final public function ignoreOnUninitialized(): self - { - $this->invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; - - return $this; - } - - /** - * @return string - */ - public function __toString() - { - return $this->id; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php deleted file mode 100644 index f1a6af7..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php +++ /dev/null @@ -1,72 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; - -/** - * @author Nicolas Grekas - */ -class ServiceConfigurator extends AbstractServiceConfigurator -{ - const FACTORY = 'services'; - - use Traits\AbstractTrait; - use Traits\ArgumentTrait; - use Traits\AutoconfigureTrait; - use Traits\AutowireTrait; - use Traits\BindTrait; - use Traits\CallTrait; - use Traits\ClassTrait; - use Traits\ConfiguratorTrait; - use Traits\DecorateTrait; - use Traits\DeprecateTrait; - use Traits\FactoryTrait; - use Traits\FileTrait; - use Traits\LazyTrait; - use Traits\ParentTrait; - use Traits\PropertyTrait; - use Traits\PublicTrait; - use Traits\ShareTrait; - use Traits\SyntheticTrait; - use Traits\TagTrait; - - private $container; - private $instanceof; - private $allowParent; - private $path; - - public function __construct(ContainerBuilder $container, array $instanceof, bool $allowParent, ServicesConfigurator $parent, Definition $definition, $id, array $defaultTags, string $path = null) - { - $this->container = $container; - $this->instanceof = $instanceof; - $this->allowParent = $allowParent; - $this->path = $path; - - parent::__construct($parent, $definition, $id, $defaultTags); - } - - public function __destruct() - { - parent::__destruct(); - - $this->container->removeBindings($this->id); - - if (!$this->definition instanceof ChildDefinition) { - $this->container->setDefinition($this->id, $this->definition->setInstanceofConditionals($this->instanceof)); - } else { - $this->container->setDefinition($this->id, $this->definition); - } - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php b/vendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php deleted file mode 100644 index f0fdde8..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php +++ /dev/null @@ -1,147 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; - -/** - * @author Nicolas Grekas - */ -class ServicesConfigurator extends AbstractConfigurator -{ - const FACTORY = 'services'; - - private $defaults; - private $container; - private $loader; - private $instanceof; - private $path; - private $anonymousHash; - private $anonymousCount; - - public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, string $path = null, int &$anonymousCount = 0) - { - $this->defaults = new Definition(); - $this->container = $container; - $this->loader = $loader; - $this->instanceof = &$instanceof; - $this->path = $path; - $this->anonymousHash = ContainerBuilder::hash($path ?: mt_rand()); - $this->anonymousCount = &$anonymousCount; - $instanceof = []; - } - - /** - * Defines a set of defaults for following service definitions. - */ - final public function defaults(): DefaultsConfigurator - { - return new DefaultsConfigurator($this, $this->defaults = new Definition(), $this->path); - } - - /** - * Defines an instanceof-conditional to be applied to following service definitions. - */ - final public function instanceof(string $fqcn): InstanceofConfigurator - { - $this->instanceof[$fqcn] = $definition = new ChildDefinition(''); - - return new InstanceofConfigurator($this, $definition, $fqcn, $this->path); - } - - /** - * Registers a service. - * - * @param string|null $id The service id, or null to create an anonymous service - * @param string|null $class The class of the service, or null when $id is also the class name - */ - final public function set(?string $id, string $class = null): ServiceConfigurator - { - $defaults = $this->defaults; - $allowParent = !$defaults->getChanges() && empty($this->instanceof); - - $definition = new Definition(); - - if (null === $id) { - if (!$class) { - throw new \LogicException('Anonymous services must have a class name.'); - } - - $id = sprintf('.%d_%s', ++$this->anonymousCount, preg_replace('/^.*\\\\/', '', $class).'~'.$this->anonymousHash); - $definition->setPublic(false); - } else { - $definition->setPublic($defaults->isPublic()); - } - - $definition->setAutowired($defaults->isAutowired()); - $definition->setAutoconfigured($defaults->isAutoconfigured()); - $definition->setBindings($defaults->getBindings()); - $definition->setChanges([]); - - $configurator = new ServiceConfigurator($this->container, $this->instanceof, $allowParent, $this, $definition, $id, $defaults->getTags(), $this->path); - - return null !== $class ? $configurator->class($class) : $configurator; - } - - /** - * Creates an alias. - */ - final public function alias(string $id, string $referencedId): AliasConfigurator - { - $ref = static::processValue($referencedId, true); - $alias = new Alias((string) $ref, $this->defaults->isPublic()); - $this->container->setAlias($id, $alias); - - return new AliasConfigurator($this, $alias); - } - - /** - * Registers a PSR-4 namespace using a glob pattern. - */ - final public function load(string $namespace, string $resource): PrototypeConfigurator - { - $allowParent = !$this->defaults->getChanges() && empty($this->instanceof); - - return new PrototypeConfigurator($this, $this->loader, $this->defaults, $namespace, $resource, $allowParent); - } - - /** - * Gets an already defined service definition. - * - * @throws ServiceNotFoundException if the service definition does not exist - */ - final public function get(string $id): ServiceConfigurator - { - $allowParent = !$this->defaults->getChanges() && empty($this->instanceof); - $definition = $this->container->getDefinition($id); - - return new ServiceConfigurator($this->container, $definition->getInstanceofConditionals(), $allowParent, $this, $definition, $id, []); - } - - /** - * Registers a service. - */ - final public function __invoke(string $id, string $class = null): ServiceConfigurator - { - return $this->set($id, $class); - } - - public function __destruct() - { - $this->loader->registerAliasesForSinglyImplementedInterfaces(); - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php deleted file mode 100644 index 82ba21d..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AbstractTrait.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait AbstractTrait -{ - /** - * Whether this definition is abstract, that means it merely serves as a - * template for other definitions. - * - * @return $this - */ - final public function abstract(bool $abstract = true): self - { - $this->definition->setAbstract($abstract); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php deleted file mode 100644 index 5c9a475..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ArgumentTrait.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait ArgumentTrait -{ - /** - * Sets the arguments to pass to the service constructor/factory method. - * - * @return $this - */ - final public function args(array $arguments): self - { - $this->definition->setArguments(static::processValue($arguments, true)); - - return $this; - } - - /** - * Sets one argument to pass to the service constructor/factory method. - * - * @param string|int $key - * @param mixed $value - * - * @return $this - */ - final public function arg($key, $value): self - { - $this->definition->setArgument($key, static::processValue($value, true)); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php deleted file mode 100644 index 836f458..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutoconfigureTrait.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -trait AutoconfigureTrait -{ - /** - * Sets whether or not instanceof conditionals should be prepended with a global set. - * - * @return $this - * - * @throws InvalidArgumentException when a parent is already set - */ - final public function autoconfigure(bool $autoconfigured = true): self - { - if ($autoconfigured && $this->definition instanceof ChildDefinition) { - throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try disabling autoconfiguration for the service.', $this->id)); - } - $this->definition->setAutoconfigured($autoconfigured); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php deleted file mode 100644 index 2837a02..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/AutowireTrait.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait AutowireTrait -{ - /** - * Enables/disables autowiring. - * - * @return $this - */ - final public function autowire(bool $autowired = true): self - { - $this->definition->setAutowired($autowired); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php deleted file mode 100644 index 1328494..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/BindTrait.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\Argument\BoundArgument; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Loader\Configurator\DefaultsConfigurator; -use Symfony\Component\DependencyInjection\Loader\Configurator\InstanceofConfigurator; -use Symfony\Component\DependencyInjection\Reference; - -trait BindTrait -{ - /** - * Sets bindings. - * - * Bindings map $named or FQCN arguments to values that should be - * injected in the matching parameters (of the constructor, of methods - * called and of controller actions). - * - * @param string $nameOrFqcn A parameter name with its "$" prefix, or a FQCN - * @param mixed $valueOrRef The value or reference to bind - * - * @return $this - */ - final public function bind(string $nameOrFqcn, $valueOrRef): self - { - $valueOrRef = static::processValue($valueOrRef, true); - if (!preg_match('/^(?:(?:array|bool|float|int|string)[ \t]*+)?\$/', $nameOrFqcn) && !$valueOrRef instanceof Reference) { - throw new InvalidArgumentException(sprintf('Invalid binding for service "%s": named arguments must start with a "$", and FQCN must map to references. Neither applies to binding "%s".', $this->id, $nameOrFqcn)); - } - $bindings = $this->definition->getBindings(); - $type = $this instanceof DefaultsConfigurator ? BoundArgument::DEFAULTS_BINDING : ($this instanceof InstanceofConfigurator ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING); - $bindings[$nameOrFqcn] = new BoundArgument($valueOrRef, true, $type, $this->path ?? null); - $this->definition->setBindings($bindings); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php deleted file mode 100644 index 28f92d2..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/CallTrait.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -trait CallTrait -{ - /** - * Adds a method to call after service initialization. - * - * @param string $method The method name to call - * @param array $arguments An array of arguments to pass to the method call - * @param bool $returnsClone Whether the call returns the service instance or not - * - * @return $this - * - * @throws InvalidArgumentException on empty $method param - */ - final public function call(string $method, array $arguments = [], bool $returnsClone = false): self - { - $this->definition->addMethodCall($method, static::processValue($arguments, true), $returnsClone); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php deleted file mode 100644 index 20da791..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ClassTrait.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait ClassTrait -{ - /** - * Sets the service class. - * - * @return $this - */ - final public function class(?string $class): self - { - $this->definition->setClass($class); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php deleted file mode 100644 index 25d363c..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ConfiguratorTrait.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait ConfiguratorTrait -{ - /** - * Sets a configurator to call after the service is fully initialized. - * - * @param string|array $configurator A PHP callable reference - * - * @return $this - */ - final public function configurator($configurator): self - { - $this->definition->setConfigurator(static::processValue($configurator, true)); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php deleted file mode 100644 index b3a1ae1..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -trait DecorateTrait -{ - /** - * Sets the service that this service is decorating. - * - * @param string|null $id The decorated service id, use null to remove decoration - * - * @return $this - * - * @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals - */ - final public function decorate(?string $id, string $renamedId = null, int $priority = 0, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE): self - { - $this->definition->setDecoratedService($id, $renamedId, $priority, $invalidBehavior); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php deleted file mode 100644 index b2d5b0e..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/DeprecateTrait.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -trait DeprecateTrait -{ - /** - * Whether this definition is deprecated, that means it should not be called anymore. - * - * @param string $template Template message to use if the definition is deprecated - * - * @return $this - * - * @throws InvalidArgumentException when the message template is invalid - */ - final public function deprecate(string $template = null): self - { - $this->definition->setDeprecated(true, $template); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php deleted file mode 100644 index 3834d72..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FactoryTrait.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -trait FactoryTrait -{ - /** - * Sets a factory. - * - * @param string|array $factory A PHP callable reference - * - * @return $this - */ - final public function factory($factory): self - { - if (\is_string($factory) && 1 === substr_count($factory, ':')) { - $factoryParts = explode(':', $factory); - - throw new InvalidArgumentException(sprintf('Invalid factory "%s": the "service:method" notation is not available when using PHP-based DI configuration. Use "[ref(\'%s\'), \'%s\']" instead.', $factory, $factoryParts[0], $factoryParts[1])); - } - - $this->definition->setFactory(static::processValue($factory, true)); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php deleted file mode 100644 index 5f42aef..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/FileTrait.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait FileTrait -{ - /** - * Sets a file to require before creating the service. - * - * @return $this - */ - final public function file(string $file): self - { - $this->definition->setFile($file); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php deleted file mode 100644 index 2829def..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/LazyTrait.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait LazyTrait -{ - /** - * Sets the lazy flag of this service. - * - * @param bool|string $lazy A FQCN to derivate the lazy proxy from or `true` to make it extend from the definition's class - * - * @return $this - */ - final public function lazy($lazy = true): self - { - $this->definition->setLazy((bool) $lazy); - if (\is_string($lazy)) { - $this->definition->addTag('proxy', ['interface' => $lazy]); - } - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php deleted file mode 100644 index 7488a38..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ParentTrait.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -trait ParentTrait -{ - /** - * Sets the Definition to inherit from. - * - * @return $this - * - * @throws InvalidArgumentException when parent cannot be set - */ - final public function parent(string $parent): self - { - if (!$this->allowParent) { - throw new InvalidArgumentException(sprintf('A parent cannot be defined when either "_instanceof" or "_defaults" are also defined for service prototype "%s".', $this->id)); - } - - if ($this->definition instanceof ChildDefinition) { - $this->definition->setParent($parent); - } elseif ($this->definition->isAutoconfigured()) { - throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try disabling autoconfiguration for the service.', $this->id)); - } elseif ($this->definition->getBindings()) { - throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also "bind" arguments.', $this->id)); - } else { - // cast Definition to ChildDefinition - $definition = serialize($this->definition); - $definition = substr_replace($definition, '53', 2, 2); - $definition = substr_replace($definition, 'Child', 44, 0); - $definition = unserialize($definition); - - $this->definition = $definition->setParent($parent); - } - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php deleted file mode 100644 index 10fdcfb..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PropertyTrait.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait PropertyTrait -{ - /** - * Sets a specific property. - * - * @return $this - */ - final public function property(string $name, $value): self - { - $this->definition->setProperty($name, static::processValue($value, true)); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php deleted file mode 100644 index f15756c..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/PublicTrait.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait PublicTrait -{ - /** - * @return $this - */ - final public function public(): self - { - $this->definition->setPublic(true); - - return $this; - } - - /** - * @return $this - */ - final public function private(): self - { - $this->definition->setPublic(false); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php deleted file mode 100644 index 16fde0f..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/ShareTrait.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait ShareTrait -{ - /** - * Sets if the service must be shared or not. - * - * @return $this - */ - final public function share(bool $shared = true): self - { - $this->definition->setShared($shared); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php deleted file mode 100644 index cb08b11..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/SyntheticTrait.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -trait SyntheticTrait -{ - /** - * Sets whether this definition is synthetic, that is not constructed by the - * container, but dynamically injected. - * - * @return $this - */ - final public function synthetic(bool $synthetic = true): self - { - $this->definition->setSynthetic($synthetic); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php b/vendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php deleted file mode 100644 index f4d5f00..0000000 --- a/vendor/symfony/dependency-injection/Loader/Configurator/Traits/TagTrait.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -trait TagTrait -{ - /** - * Adds a tag for this definition. - * - * @return $this - */ - final public function tag(string $name, array $attributes = []): self - { - if ('' === $name) { - throw new InvalidArgumentException(sprintf('The tag name for service "%s" must be a non-empty string.', $this->id)); - } - - foreach ($attributes as $attribute => $value) { - if (!is_scalar($value) && null !== $value) { - throw new InvalidArgumentException(sprintf('A tag attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $this->id, $name, $attribute)); - } - } - - $this->definition->addTag($name, $attributes); - - return $this; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/DirectoryLoader.php b/vendor/symfony/dependency-injection/Loader/DirectoryLoader.php deleted file mode 100644 index 9439869..0000000 --- a/vendor/symfony/dependency-injection/Loader/DirectoryLoader.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -/** - * DirectoryLoader is a recursive loader to go through directories. - * - * @author Sebastien Lavoie - */ -class DirectoryLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($file, string $type = null) - { - $file = rtrim($file, '/'); - $path = $this->locator->locate($file); - $this->container->fileExists($path, false); - - foreach (scandir($path) as $dir) { - if ('.' !== $dir[0]) { - if (is_dir($path.'/'.$dir)) { - $dir .= '/'; // append / to allow recursion - } - - $this->setCurrentDir($path); - - $this->import($dir, null, false, $path); - } - } - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - if ('directory' === $type) { - return true; - } - - return null === $type && \is_string($resource) && '/' === substr($resource, -1); - } -} diff --git a/vendor/symfony/dependency-injection/Loader/FileLoader.php b/vendor/symfony/dependency-injection/Loader/FileLoader.php deleted file mode 100644 index 26577c9..0000000 --- a/vendor/symfony/dependency-injection/Loader/FileLoader.php +++ /dev/null @@ -1,225 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException; -use Symfony\Component\Config\Exception\LoaderLoadException; -use Symfony\Component\Config\FileLocatorInterface; -use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader; -use Symfony\Component\Config\Loader\Loader; -use Symfony\Component\Config\Resource\GlobResource; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * FileLoader is the abstract class used by all built-in loaders that are file based. - * - * @author Fabien Potencier - */ -abstract class FileLoader extends BaseFileLoader -{ - public const ANONYMOUS_ID_REGEXP = '/^\.\d+_[^~]*+~[._a-zA-Z\d]{7}$/'; - - protected $container; - protected $isLoadingInstanceof = false; - protected $instanceof = []; - protected $interfaces = []; - protected $singlyImplemented = []; - protected $autoRegisterAliasesForSinglyImplementedInterfaces = true; - - public function __construct(ContainerBuilder $container, FileLocatorInterface $locator) - { - $this->container = $container; - - parent::__construct($locator); - } - - /** - * {@inheritdoc} - * - * @param bool|string $ignoreErrors Whether errors should be ignored; pass "not_found" to ignore only when the loaded resource is not found - */ - public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null, $exclude = null) - { - $args = \func_get_args(); - - if ($ignoreNotFound = 'not_found' === $ignoreErrors) { - $args[2] = false; - } elseif (!\is_bool($ignoreErrors)) { - throw new \TypeError(sprintf('Invalid argument $ignoreErrors provided to %s::import(): boolean or "not_found" expected, %s given.', \get_class($this), \gettype($ignoreErrors))); - } - - try { - parent::import(...$args); - } catch (LoaderLoadException $e) { - if (!$ignoreNotFound || !($prev = $e->getPrevious()) instanceof FileLocatorFileNotFoundException) { - throw $e; - } - - foreach ($prev->getTrace() as $frame) { - if ('import' === ($frame['function'] ?? null) && is_a($frame['class'] ?? '', Loader::class, true)) { - break; - } - } - - if (__FILE__ !== $frame['file']) { - throw $e; - } - } - } - - /** - * Registers a set of classes as services using PSR-4 for discovery. - * - * @param Definition $prototype A definition to use as template - * @param string $namespace The namespace prefix of classes in the scanned directory - * @param string $resource The directory to look for classes, glob-patterns allowed - * @param string|string[]|null $exclude A globbed path of files to exclude or an array of globbed paths of files to exclude - */ - public function registerClasses(Definition $prototype, $namespace, $resource, $exclude = null) - { - if ('\\' !== substr($namespace, -1)) { - throw new InvalidArgumentException(sprintf('Namespace prefix must end with a "\\": %s.', $namespace)); - } - if (!preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+\\\\)++$/', $namespace)) { - throw new InvalidArgumentException(sprintf('Namespace is not a valid PSR-4 prefix: %s.', $namespace)); - } - - $classes = $this->findClasses($namespace, $resource, (array) $exclude); - // prepare for deep cloning - $serializedPrototype = serialize($prototype); - - foreach ($classes as $class => $errorMessage) { - if (interface_exists($class, false)) { - $this->interfaces[] = $class; - } else { - $this->setDefinition($class, $definition = unserialize($serializedPrototype)); - if (null !== $errorMessage) { - $definition->addError($errorMessage); - - continue; - } - foreach (class_implements($class, false) as $interface) { - $this->singlyImplemented[$interface] = ($this->singlyImplemented[$interface] ?? $class) !== $class ? false : $class; - } - } - } - - if ($this->autoRegisterAliasesForSinglyImplementedInterfaces) { - $this->registerAliasesForSinglyImplementedInterfaces(); - } - } - - public function registerAliasesForSinglyImplementedInterfaces() - { - foreach ($this->interfaces as $interface) { - if (!empty($this->singlyImplemented[$interface]) && !$this->container->has($interface)) { - $this->container->setAlias($interface, $this->singlyImplemented[$interface])->setPublic(false); - } - } - - $this->interfaces = $this->singlyImplemented = []; - } - - /** - * Registers a definition in the container with its instanceof-conditionals. - * - * @param string $id - */ - protected function setDefinition($id, Definition $definition) - { - $this->container->removeBindings($id); - - if ($this->isLoadingInstanceof) { - if (!$definition instanceof ChildDefinition) { - throw new InvalidArgumentException(sprintf('Invalid type definition "%s": ChildDefinition expected, "%s" given.', $id, \get_class($definition))); - } - $this->instanceof[$id] = $definition; - } else { - $this->container->setDefinition($id, $definition instanceof ChildDefinition ? $definition : $definition->setInstanceofConditionals($this->instanceof)); - } - } - - private function findClasses(string $namespace, string $pattern, array $excludePatterns): array - { - $parameterBag = $this->container->getParameterBag(); - - $excludePaths = []; - $excludePrefix = null; - $excludePatterns = $parameterBag->unescapeValue($parameterBag->resolveValue($excludePatterns)); - foreach ($excludePatterns as $excludePattern) { - foreach ($this->glob($excludePattern, true, $resource, false, true) as $path => $info) { - if (null === $excludePrefix) { - $excludePrefix = $resource->getPrefix(); - } - - // normalize Windows slashes - $excludePaths[str_replace('\\', '/', $path)] = true; - } - } - - $pattern = $parameterBag->unescapeValue($parameterBag->resolveValue($pattern)); - $classes = []; - $extRegexp = '/\\.php$/'; - $prefixLen = null; - foreach ($this->glob($pattern, true, $resource, false, false, $excludePaths) as $path => $info) { - if (null === $prefixLen) { - $prefixLen = \strlen($resource->getPrefix()); - - if ($excludePrefix && 0 !== strpos($excludePrefix, $resource->getPrefix())) { - throw new InvalidArgumentException(sprintf('Invalid "exclude" pattern when importing classes for "%s": make sure your "exclude" pattern (%s) is a subset of the "resource" pattern (%s)', $namespace, $excludePattern, $pattern)); - } - } - - if (isset($excludePaths[str_replace('\\', '/', $path)])) { - continue; - } - - if (!preg_match($extRegexp, $path, $m) || !$info->isReadable()) { - continue; - } - $class = $namespace.ltrim(str_replace('/', '\\', substr($path, $prefixLen, -\strlen($m[0]))), '\\'); - - if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $class)) { - continue; - } - - try { - $r = $this->container->getReflectionClass($class); - } catch (\ReflectionException $e) { - $classes[$class] = $e->getMessage(); - continue; - } - // check to make sure the expected class exists - if (!$r) { - throw new InvalidArgumentException(sprintf('Expected to find class "%s" in file "%s" while importing services from resource "%s", but it was not found! Check the namespace prefix used with the resource.', $class, $path, $pattern)); - } - - if ($r->isInstantiable() || $r->isInterface()) { - $classes[$class] = null; - } - } - - // track only for new & removed files - if ($resource instanceof GlobResource) { - $this->container->addResource($resource); - } else { - foreach ($resource as $path) { - $this->container->fileExists($path, false); - } - } - - return $classes; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/GlobFileLoader.php b/vendor/symfony/dependency-injection/Loader/GlobFileLoader.php deleted file mode 100644 index 53af9cf..0000000 --- a/vendor/symfony/dependency-injection/Loader/GlobFileLoader.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -/** - * GlobFileLoader loads files from a glob pattern. - * - * @author Nicolas Grekas - */ -class GlobFileLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - foreach ($this->glob($resource, false, $globResource) as $path => $info) { - $this->import($path); - } - - $this->container->addResource($globResource); - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return 'glob' === $type; - } -} diff --git a/vendor/symfony/dependency-injection/Loader/IniFileLoader.php b/vendor/symfony/dependency-injection/Loader/IniFileLoader.php deleted file mode 100644 index 8ed1e42..0000000 --- a/vendor/symfony/dependency-injection/Loader/IniFileLoader.php +++ /dev/null @@ -1,97 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -use Symfony\Component\Config\Util\XmlUtils; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * IniFileLoader loads parameters from INI files. - * - * @author Fabien Potencier - */ -class IniFileLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - $path = $this->locator->locate($resource); - - $this->container->fileExists($path); - - // first pass to catch parsing errors - $result = parse_ini_file($path, true); - if (false === $result || [] === $result) { - throw new InvalidArgumentException(sprintf('The "%s" file is not valid.', $resource)); - } - - // real raw parsing - $result = parse_ini_file($path, true, INI_SCANNER_RAW); - - if (isset($result['parameters']) && \is_array($result['parameters'])) { - foreach ($result['parameters'] as $key => $value) { - $this->container->setParameter($key, $this->phpize($value)); - } - } - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - if (!\is_string($resource)) { - return false; - } - - if (null === $type && 'ini' === pathinfo($resource, PATHINFO_EXTENSION)) { - return true; - } - - return 'ini' === $type; - } - - /** - * Note that the following features are not supported: - * * strings with escaped quotes are not supported "foo\"bar"; - * * string concatenation ("foo" "bar"). - * - * @return mixed - */ - private function phpize(string $value) - { - // trim on the right as comments removal keep whitespaces - if ($value !== $v = rtrim($value)) { - $value = '""' === substr_replace($v, '', 1, -1) ? substr($v, 1, -1) : $v; - } - $lowercaseValue = strtolower($value); - - switch (true) { - case \defined($value): - return \constant($value); - case 'yes' === $lowercaseValue || 'on' === $lowercaseValue: - return true; - case 'no' === $lowercaseValue || 'off' === $lowercaseValue || 'none' === $lowercaseValue: - return false; - case isset($value[1]) && ( - ("'" === $value[0] && "'" === $value[\strlen($value) - 1]) || - ('"' === $value[0] && '"' === $value[\strlen($value) - 1]) - ): - // quoted string - return substr($value, 1, -1); - default: - return XmlUtils::phpize($value); - } - } -} diff --git a/vendor/symfony/dependency-injection/Loader/PhpFileLoader.php b/vendor/symfony/dependency-injection/Loader/PhpFileLoader.php deleted file mode 100644 index 207fb83..0000000 --- a/vendor/symfony/dependency-injection/Loader/PhpFileLoader.php +++ /dev/null @@ -1,80 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; - -/** - * PhpFileLoader loads service definitions from a PHP file. - * - * The PHP file is required and the $container variable can be - * used within the file to change the container. - * - * @author Fabien Potencier - */ -class PhpFileLoader extends FileLoader -{ - protected $autoRegisterAliasesForSinglyImplementedInterfaces = false; - - /** - * {@inheritdoc} - */ - public function load($resource, $type = null) - { - // the container and loader variables are exposed to the included file below - $container = $this->container; - $loader = $this; - - $path = $this->locator->locate($resource); - $this->setCurrentDir(\dirname($path)); - $this->container->fileExists($path); - - // the closure forbids access to the private scope in the included file - $load = \Closure::bind(function ($path) use ($container, $loader, $resource, $type) { - return include $path; - }, $this, ProtectedPhpFileLoader::class); - - try { - $callback = $load($path); - - if (\is_object($callback) && \is_callable($callback)) { - $callback(new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource), $this->container, $this); - } - } finally { - $this->instanceof = []; - $this->registerAliasesForSinglyImplementedInterfaces(); - } - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - if (!\is_string($resource)) { - return false; - } - - if (null === $type && 'php' === pathinfo($resource, PATHINFO_EXTENSION)) { - return true; - } - - return 'php' === $type; - } -} - -/** - * @internal - */ -final class ProtectedPhpFileLoader extends PhpFileLoader -{ -} diff --git a/vendor/symfony/dependency-injection/Loader/XmlFileLoader.php b/vendor/symfony/dependency-injection/Loader/XmlFileLoader.php deleted file mode 100644 index 82e61b6..0000000 --- a/vendor/symfony/dependency-injection/Loader/XmlFileLoader.php +++ /dev/null @@ -1,728 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -use Symfony\Component\Config\Util\XmlUtils; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\BoundArgument; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\ExpressionLanguage\Expression; - -/** - * XmlFileLoader loads XML files service definitions. - * - * @author Fabien Potencier - */ -class XmlFileLoader extends FileLoader -{ - const NS = 'http://symfony.com/schema/dic/services'; - - protected $autoRegisterAliasesForSinglyImplementedInterfaces = false; - - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - $path = $this->locator->locate($resource); - - $xml = $this->parseFileToDOM($path); - - $this->container->fileExists($path); - - $defaults = $this->getServiceDefaults($xml, $path); - - // anonymous services - $this->processAnonymousServices($xml, $path); - - // imports - $this->parseImports($xml, $path); - - // parameters - $this->parseParameters($xml, $path); - - // extensions - $this->loadFromExtensions($xml); - - // services - try { - $this->parseDefinitions($xml, $path, $defaults); - } finally { - $this->instanceof = []; - $this->registerAliasesForSinglyImplementedInterfaces(); - } - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - if (!\is_string($resource)) { - return false; - } - - if (null === $type && 'xml' === pathinfo($resource, PATHINFO_EXTENSION)) { - return true; - } - - return 'xml' === $type; - } - - private function parseParameters(\DOMDocument $xml, string $file) - { - if ($parameters = $this->getChildren($xml->documentElement, 'parameters')) { - $this->container->getParameterBag()->add($this->getArgumentsAsPhp($parameters[0], 'parameter', $file)); - } - } - - private function parseImports(\DOMDocument $xml, string $file) - { - $xpath = new \DOMXPath($xml); - $xpath->registerNamespace('container', self::NS); - - if (false === $imports = $xpath->query('//container:imports/container:import')) { - return; - } - - $defaultDirectory = \dirname($file); - foreach ($imports as $import) { - $this->setCurrentDir($defaultDirectory); - $this->import($import->getAttribute('resource'), XmlUtils::phpize($import->getAttribute('type')) ?: null, XmlUtils::phpize($import->getAttribute('ignore-errors')) ?: false, $file); - } - } - - private function parseDefinitions(\DOMDocument $xml, string $file, array $defaults) - { - $xpath = new \DOMXPath($xml); - $xpath->registerNamespace('container', self::NS); - - if (false === $services = $xpath->query('//container:services/container:service|//container:services/container:prototype')) { - return; - } - $this->setCurrentDir(\dirname($file)); - - $this->instanceof = []; - $this->isLoadingInstanceof = true; - $instanceof = $xpath->query('//container:services/container:instanceof'); - foreach ($instanceof as $service) { - $this->setDefinition((string) $service->getAttribute('id'), $this->parseDefinition($service, $file, [])); - } - - $this->isLoadingInstanceof = false; - foreach ($services as $service) { - if (null !== $definition = $this->parseDefinition($service, $file, $defaults)) { - if ('prototype' === $service->tagName) { - $excludes = array_column($this->getChildren($service, 'exclude'), 'nodeValue'); - if ($service->hasAttribute('exclude')) { - if (\count($excludes) > 0) { - throw new InvalidArgumentException('You cannot use both the attribute "exclude" and tags at the same time.'); - } - $excludes = [$service->getAttribute('exclude')]; - } - $this->registerClasses($definition, (string) $service->getAttribute('namespace'), (string) $service->getAttribute('resource'), $excludes); - } else { - $this->setDefinition((string) $service->getAttribute('id'), $definition); - } - } - } - } - - /** - * Get service defaults. - */ - private function getServiceDefaults(\DOMDocument $xml, string $file): array - { - $xpath = new \DOMXPath($xml); - $xpath->registerNamespace('container', self::NS); - - if (null === $defaultsNode = $xpath->query('//container:services/container:defaults')->item(0)) { - return []; - } - - $bindings = []; - foreach ($this->getArgumentsAsPhp($defaultsNode, 'bind', $file) as $argument => $value) { - $bindings[$argument] = new BoundArgument($value, true, BoundArgument::DEFAULTS_BINDING, $file); - } - - $defaults = [ - 'tags' => $this->getChildren($defaultsNode, 'tag'), - 'bind' => $bindings, - ]; - - foreach ($defaults['tags'] as $tag) { - if ('' === $tag->getAttribute('name')) { - throw new InvalidArgumentException(sprintf('The tag name for tag "" in %s must be a non-empty string.', $file)); - } - } - - if ($defaultsNode->hasAttribute('autowire')) { - $defaults['autowire'] = XmlUtils::phpize($defaultsNode->getAttribute('autowire')); - } - if ($defaultsNode->hasAttribute('public')) { - $defaults['public'] = XmlUtils::phpize($defaultsNode->getAttribute('public')); - } - if ($defaultsNode->hasAttribute('autoconfigure')) { - $defaults['autoconfigure'] = XmlUtils::phpize($defaultsNode->getAttribute('autoconfigure')); - } - - return $defaults; - } - - /** - * Parses an individual Definition. - */ - private function parseDefinition(\DOMElement $service, string $file, array $defaults): ?Definition - { - if ($alias = $service->getAttribute('alias')) { - $this->validateAlias($service, $file); - - $this->container->setAlias((string) $service->getAttribute('id'), $alias = new Alias($alias)); - if ($publicAttr = $service->getAttribute('public')) { - $alias->setPublic(XmlUtils::phpize($publicAttr)); - } elseif (isset($defaults['public'])) { - $alias->setPublic($defaults['public']); - } - - if ($deprecated = $this->getChildren($service, 'deprecated')) { - $alias->setDeprecated(true, $deprecated[0]->nodeValue ?: null); - } - - return null; - } - - if ($this->isLoadingInstanceof) { - $definition = new ChildDefinition(''); - } elseif ($parent = $service->getAttribute('parent')) { - if (!empty($this->instanceof)) { - throw new InvalidArgumentException(sprintf('The service "%s" cannot use the "parent" option in the same file where "instanceof" configuration is defined as using both is not supported. Move your child definitions to a separate file.', $service->getAttribute('id'))); - } - - foreach ($defaults as $k => $v) { - if ('tags' === $k) { - // since tags are never inherited from parents, there is no confusion - // thus we can safely add them as defaults to ChildDefinition - continue; - } - if ('bind' === $k) { - if ($defaults['bind']) { - throw new InvalidArgumentException(sprintf('Bound values on service "%s" cannot be inherited from "defaults" when a "parent" is set. Move your child definitions to a separate file.', $service->getAttribute('id'))); - } - - continue; - } - if (!$service->hasAttribute($k)) { - throw new InvalidArgumentException(sprintf('Attribute "%s" on service "%s" cannot be inherited from "defaults" when a "parent" is set. Move your child definitions to a separate file or define this attribute explicitly.', $k, $service->getAttribute('id'))); - } - } - - $definition = new ChildDefinition($parent); - } else { - $definition = new Definition(); - - if (isset($defaults['public'])) { - $definition->setPublic($defaults['public']); - } - if (isset($defaults['autowire'])) { - $definition->setAutowired($defaults['autowire']); - } - if (isset($defaults['autoconfigure'])) { - $definition->setAutoconfigured($defaults['autoconfigure']); - } - - $definition->setChanges([]); - } - - foreach (['class', 'public', 'shared', 'synthetic', 'abstract'] as $key) { - if ($value = $service->getAttribute($key)) { - $method = 'set'.$key; - $definition->$method($value = XmlUtils::phpize($value)); - } - } - - if ($value = $service->getAttribute('lazy')) { - $definition->setLazy((bool) $value = XmlUtils::phpize($value)); - if (\is_string($value)) { - $definition->addTag('proxy', ['interface' => $value]); - } - } - - if ($value = $service->getAttribute('autowire')) { - $definition->setAutowired(XmlUtils::phpize($value)); - } - - if ($value = $service->getAttribute('autoconfigure')) { - if (!$definition instanceof ChildDefinition) { - $definition->setAutoconfigured(XmlUtils::phpize($value)); - } elseif ($value = XmlUtils::phpize($value)) { - throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try setting autoconfigure="false" for the service.', $service->getAttribute('id'))); - } - } - - if ($files = $this->getChildren($service, 'file')) { - $definition->setFile($files[0]->nodeValue); - } - - if ($deprecated = $this->getChildren($service, 'deprecated')) { - $definition->setDeprecated(true, $deprecated[0]->nodeValue ?: null); - } - - $definition->setArguments($this->getArgumentsAsPhp($service, 'argument', $file, $definition instanceof ChildDefinition)); - $definition->setProperties($this->getArgumentsAsPhp($service, 'property', $file)); - - if ($factories = $this->getChildren($service, 'factory')) { - $factory = $factories[0]; - if ($function = $factory->getAttribute('function')) { - $definition->setFactory($function); - } else { - if ($childService = $factory->getAttribute('service')) { - $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE); - } else { - $class = $factory->hasAttribute('class') ? $factory->getAttribute('class') : null; - } - - $definition->setFactory([$class, $factory->getAttribute('method') ?: '__invoke']); - } - } - - if ($configurators = $this->getChildren($service, 'configurator')) { - $configurator = $configurators[0]; - if ($function = $configurator->getAttribute('function')) { - $definition->setConfigurator($function); - } else { - if ($childService = $configurator->getAttribute('service')) { - $class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE); - } else { - $class = $configurator->getAttribute('class'); - } - - $definition->setConfigurator([$class, $configurator->getAttribute('method') ?: '__invoke']); - } - } - - foreach ($this->getChildren($service, 'call') as $call) { - $definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument', $file), XmlUtils::phpize($call->getAttribute('returns-clone'))); - } - - $tags = $this->getChildren($service, 'tag'); - - if (!empty($defaults['tags'])) { - $tags = array_merge($tags, $defaults['tags']); - } - - foreach ($tags as $tag) { - $parameters = []; - foreach ($tag->attributes as $name => $node) { - if ('name' === $name) { - continue; - } - - if (false !== strpos($name, '-') && false === strpos($name, '_') && !\array_key_exists($normalizedName = str_replace('-', '_', $name), $parameters)) { - $parameters[$normalizedName] = XmlUtils::phpize($node->nodeValue); - } - // keep not normalized key - $parameters[$name] = XmlUtils::phpize($node->nodeValue); - } - - if ('' === $tag->getAttribute('name')) { - throw new InvalidArgumentException(sprintf('The tag name for service "%s" in %s must be a non-empty string.', (string) $service->getAttribute('id'), $file)); - } - - $definition->addTag($tag->getAttribute('name'), $parameters); - } - - $bindings = $this->getArgumentsAsPhp($service, 'bind', $file); - $bindingType = $this->isLoadingInstanceof ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING; - foreach ($bindings as $argument => $value) { - $bindings[$argument] = new BoundArgument($value, true, $bindingType, $file); - } - - if (isset($defaults['bind'])) { - // deep clone, to avoid multiple process of the same instance in the passes - $bindings = array_merge(unserialize(serialize($defaults['bind'])), $bindings); - } - if ($bindings) { - $definition->setBindings($bindings); - } - - if ($decorates = $service->getAttribute('decorates')) { - $decorationOnInvalid = $service->getAttribute('decoration-on-invalid') ?: 'exception'; - if ('exception' === $decorationOnInvalid) { - $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - } elseif ('ignore' === $decorationOnInvalid) { - $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - } elseif ('null' === $decorationOnInvalid) { - $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; - } else { - throw new InvalidArgumentException(sprintf('Invalid value "%s" for attribute "decoration-on-invalid" on service "%s". Did you mean "exception", "ignore" or "null" in "%s"?', $decorationOnInvalid, (string) $service->getAttribute('id'), $file)); - } - - $renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null; - $priority = $service->hasAttribute('decoration-priority') ? $service->getAttribute('decoration-priority') : 0; - - $definition->setDecoratedService($decorates, $renameId, $priority, $invalidBehavior); - } - - return $definition; - } - - /** - * Parses a XML file to a \DOMDocument. - * - * @throws InvalidArgumentException When loading of XML file returns error - */ - private function parseFileToDOM(string $file): \DOMDocument - { - try { - $dom = XmlUtils::loadFile($file, [$this, 'validateSchema']); - } catch (\InvalidArgumentException $e) { - throw new InvalidArgumentException(sprintf('Unable to parse file "%s": %s', $file, $e->getMessage()), $e->getCode(), $e); - } - - $this->validateExtensions($dom, $file); - - return $dom; - } - - /** - * Processes anonymous services. - */ - private function processAnonymousServices(\DOMDocument $xml, string $file) - { - $definitions = []; - $count = 0; - $suffix = '~'.ContainerBuilder::hash($file); - - $xpath = new \DOMXPath($xml); - $xpath->registerNamespace('container', self::NS); - - // anonymous services as arguments/properties - if (false !== $nodes = $xpath->query('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]|//container:bind[not(@id)]|//container:factory[not(@service)]|//container:configurator[not(@service)]')) { - foreach ($nodes as $node) { - if ($services = $this->getChildren($node, 'service')) { - // give it a unique name - $id = sprintf('.%d_%s', ++$count, preg_replace('/^.*\\\\/', '', $services[0]->getAttribute('class')).$suffix); - $node->setAttribute('id', $id); - $node->setAttribute('service', $id); - - $definitions[$id] = [$services[0], $file]; - $services[0]->setAttribute('id', $id); - - // anonymous services are always private - // we could not use the constant false here, because of XML parsing - $services[0]->setAttribute('public', 'false'); - } - } - } - - // anonymous services "in the wild" - if (false !== $nodes = $xpath->query('//container:services/container:service[not(@id)]')) { - foreach ($nodes as $node) { - throw new InvalidArgumentException(sprintf('Top-level services must have "id" attribute, none found in %s at line %d.', $file, $node->getLineNo())); - } - } - - // resolve definitions - uksort($definitions, 'strnatcmp'); - foreach (array_reverse($definitions) as $id => list($domElement, $file)) { - if (null !== $definition = $this->parseDefinition($domElement, $file, [])) { - $this->setDefinition($id, $definition); - } - } - } - - private function getArgumentsAsPhp(\DOMElement $node, string $name, string $file, bool $isChildDefinition = false): array - { - $arguments = []; - foreach ($this->getChildren($node, $name) as $arg) { - if ($arg->hasAttribute('name')) { - $arg->setAttribute('key', $arg->getAttribute('name')); - } - - // this is used by ChildDefinition to overwrite a specific - // argument of the parent definition - if ($arg->hasAttribute('index')) { - $key = ($isChildDefinition ? 'index_' : '').$arg->getAttribute('index'); - } elseif (!$arg->hasAttribute('key')) { - // Append an empty argument, then fetch its key to overwrite it later - $arguments[] = null; - $keys = array_keys($arguments); - $key = array_pop($keys); - } else { - $key = $arg->getAttribute('key'); - } - - $onInvalid = $arg->getAttribute('on-invalid'); - $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - if ('ignore' == $onInvalid) { - $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - } elseif ('ignore_uninitialized' == $onInvalid) { - $invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; - } elseif ('null' == $onInvalid) { - $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; - } - - switch ($arg->getAttribute('type')) { - case 'service': - if ('' === $arg->getAttribute('id')) { - throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service" has no or empty "id" attribute in "%s".', $name, $file)); - } - - $arguments[$key] = new Reference($arg->getAttribute('id'), $invalidBehavior); - break; - case 'expression': - if (!class_exists(Expression::class)) { - throw new \LogicException(sprintf('The type="expression" attribute cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".')); - } - - $arguments[$key] = new Expression($arg->nodeValue); - break; - case 'collection': - $arguments[$key] = $this->getArgumentsAsPhp($arg, $name, $file); - break; - case 'iterator': - $arg = $this->getArgumentsAsPhp($arg, $name, $file); - try { - $arguments[$key] = new IteratorArgument($arg); - } catch (InvalidArgumentException $e) { - throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="iterator" only accepts collections of type="service" references in "%s".', $name, $file)); - } - break; - case 'service_locator': - $arg = $this->getArgumentsAsPhp($arg, $name, $file); - try { - $arguments[$key] = new ServiceLocatorArgument($arg); - } catch (InvalidArgumentException $e) { - throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service_locator" only accepts maps of type="service" references in "%s".', $name, $file)); - } - break; - case 'tagged': - case 'tagged_iterator': - case 'tagged_locator': - $type = $arg->getAttribute('type'); - $forLocator = 'tagged_locator' === $type; - - if (!$arg->getAttribute('tag')) { - throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="%s" has no or empty "tag" attribute in "%s".', $name, $type, $file)); - } - - $arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'), $arg->getAttribute('index-by') ?: null, $arg->getAttribute('default-index-method') ?: null, $forLocator, $arg->getAttribute('default-priority-method') ?: null); - - if ($forLocator) { - $arguments[$key] = new ServiceLocatorArgument($arguments[$key]); - } - break; - case 'binary': - if (false === $value = base64_decode($arg->nodeValue)) { - throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="binary" is not a valid base64 encoded string.', $name)); - } - $arguments[$key] = $value; - break; - case 'string': - $arguments[$key] = $arg->nodeValue; - break; - case 'constant': - $arguments[$key] = \constant(trim($arg->nodeValue)); - break; - default: - $arguments[$key] = XmlUtils::phpize($arg->nodeValue); - } - } - - return $arguments; - } - - /** - * Get child elements by name. - * - * @return \DOMElement[] - */ - private function getChildren(\DOMNode $node, string $name): array - { - $children = []; - foreach ($node->childNodes as $child) { - if ($child instanceof \DOMElement && $child->localName === $name && self::NS === $child->namespaceURI) { - $children[] = $child; - } - } - - return $children; - } - - /** - * Validates a documents XML schema. - * - * @return bool - * - * @throws RuntimeException When extension references a non-existent XSD file - */ - public function validateSchema(\DOMDocument $dom) - { - $schemaLocations = ['http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd')]; - - if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) { - $items = preg_split('/\s+/', $element); - for ($i = 0, $nb = \count($items); $i < $nb; $i += 2) { - if (!$this->container->hasExtension($items[$i])) { - continue; - } - - if (($extension = $this->container->getExtension($items[$i])) && false !== $extension->getXsdValidationBasePath()) { - $ns = $extension->getNamespace(); - $path = str_replace([$ns, str_replace('http://', 'https://', $ns)], str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]); - - if (!is_file($path)) { - throw new RuntimeException(sprintf('Extension "%s" references a non-existent XSD file "%s"', \get_class($extension), $path)); - } - - $schemaLocations[$items[$i]] = $path; - } - } - } - - $tmpfiles = []; - $imports = ''; - foreach ($schemaLocations as $namespace => $location) { - $parts = explode('/', $location); - $locationstart = 'file:///'; - if (0 === stripos($location, 'phar://')) { - $tmpfile = tempnam(sys_get_temp_dir(), 'symfony'); - if ($tmpfile) { - copy($location, $tmpfile); - $tmpfiles[] = $tmpfile; - $parts = explode('/', str_replace('\\', '/', $tmpfile)); - } else { - array_shift($parts); - $locationstart = 'phar:///'; - } - } - $drive = '\\' === \DIRECTORY_SEPARATOR ? array_shift($parts).'/' : ''; - $location = $locationstart.$drive.implode('/', array_map('rawurlencode', $parts)); - - $imports .= sprintf(' '."\n", $namespace, $location); - } - - $source = << - - - -$imports - -EOF - ; - - $disableEntities = libxml_disable_entity_loader(false); - $valid = @$dom->schemaValidateSource($source); - libxml_disable_entity_loader($disableEntities); - - foreach ($tmpfiles as $tmpfile) { - @unlink($tmpfile); - } - - return $valid; - } - - private function validateAlias(\DOMElement $alias, string $file) - { - foreach ($alias->attributes as $name => $node) { - if (!\in_array($name, ['alias', 'id', 'public'])) { - throw new InvalidArgumentException(sprintf('Invalid attribute "%s" defined for alias "%s" in "%s".', $name, $alias->getAttribute('id'), $file)); - } - } - - foreach ($alias->childNodes as $child) { - if (!$child instanceof \DOMElement || self::NS !== $child->namespaceURI) { - continue; - } - if (!\in_array($child->localName, ['deprecated'], true)) { - throw new InvalidArgumentException(sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $alias->getAttribute('id'), $file)); - } - } - } - - /** - * Validates an extension. - * - * @throws InvalidArgumentException When no extension is found corresponding to a tag - */ - private function validateExtensions(\DOMDocument $dom, string $file) - { - foreach ($dom->documentElement->childNodes as $node) { - if (!$node instanceof \DOMElement || 'http://symfony.com/schema/dic/services' === $node->namespaceURI) { - continue; - } - - // can it be handled by an extension? - if (!$this->container->hasExtension($node->namespaceURI)) { - $extensionNamespaces = array_filter(array_map(function (ExtensionInterface $ext) { return $ext->getNamespace(); }, $this->container->getExtensions())); - throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $node->tagName, $file, $node->namespaceURI, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none')); - } - } - } - - /** - * Loads from an extension. - */ - private function loadFromExtensions(\DOMDocument $xml) - { - foreach ($xml->documentElement->childNodes as $node) { - if (!$node instanceof \DOMElement || self::NS === $node->namespaceURI) { - continue; - } - - $values = static::convertDomElementToArray($node); - if (!\is_array($values)) { - $values = []; - } - - $this->container->loadFromExtension($node->namespaceURI, $values); - } - } - - /** - * Converts a \DOMElement object to a PHP array. - * - * The following rules applies during the conversion: - * - * * Each tag is converted to a key value or an array - * if there is more than one "value" - * - * * The content of a tag is set under a "value" key (bar) - * if the tag also has some nested tags - * - * * The attributes are converted to keys () - * - * * The nested-tags are converted to keys (bar) - * - * @param \DOMElement $element A \DOMElement instance - * - * @return mixed - */ - public static function convertDomElementToArray(\DOMElement $element) - { - return XmlUtils::convertDomElementToArray($element); - } -} diff --git a/vendor/symfony/dependency-injection/Loader/YamlFileLoader.php b/vendor/symfony/dependency-injection/Loader/YamlFileLoader.php deleted file mode 100644 index cb17e57..0000000 --- a/vendor/symfony/dependency-injection/Loader/YamlFileLoader.php +++ /dev/null @@ -1,872 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Loader; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\BoundArgument; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\ExpressionLanguage\Expression; -use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Parser as YamlParser; -use Symfony\Component\Yaml\Tag\TaggedValue; -use Symfony\Component\Yaml\Yaml; - -/** - * YamlFileLoader loads YAML files service definitions. - * - * @author Fabien Potencier - */ -class YamlFileLoader extends FileLoader -{ - private static $serviceKeywords = [ - 'alias' => 'alias', - 'parent' => 'parent', - 'class' => 'class', - 'shared' => 'shared', - 'synthetic' => 'synthetic', - 'lazy' => 'lazy', - 'public' => 'public', - 'abstract' => 'abstract', - 'deprecated' => 'deprecated', - 'factory' => 'factory', - 'file' => 'file', - 'arguments' => 'arguments', - 'properties' => 'properties', - 'configurator' => 'configurator', - 'calls' => 'calls', - 'tags' => 'tags', - 'decorates' => 'decorates', - 'decoration_inner_name' => 'decoration_inner_name', - 'decoration_priority' => 'decoration_priority', - 'decoration_on_invalid' => 'decoration_on_invalid', - 'autowire' => 'autowire', - 'autoconfigure' => 'autoconfigure', - 'bind' => 'bind', - ]; - - private static $prototypeKeywords = [ - 'resource' => 'resource', - 'namespace' => 'namespace', - 'exclude' => 'exclude', - 'parent' => 'parent', - 'shared' => 'shared', - 'lazy' => 'lazy', - 'public' => 'public', - 'abstract' => 'abstract', - 'deprecated' => 'deprecated', - 'factory' => 'factory', - 'arguments' => 'arguments', - 'properties' => 'properties', - 'configurator' => 'configurator', - 'calls' => 'calls', - 'tags' => 'tags', - 'autowire' => 'autowire', - 'autoconfigure' => 'autoconfigure', - 'bind' => 'bind', - ]; - - private static $instanceofKeywords = [ - 'shared' => 'shared', - 'lazy' => 'lazy', - 'public' => 'public', - 'properties' => 'properties', - 'configurator' => 'configurator', - 'calls' => 'calls', - 'tags' => 'tags', - 'autowire' => 'autowire', - 'bind' => 'bind', - ]; - - private static $defaultsKeywords = [ - 'public' => 'public', - 'tags' => 'tags', - 'autowire' => 'autowire', - 'autoconfigure' => 'autoconfigure', - 'bind' => 'bind', - ]; - - private $yamlParser; - - private $anonymousServicesCount; - private $anonymousServicesSuffix; - - protected $autoRegisterAliasesForSinglyImplementedInterfaces = false; - - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - $path = $this->locator->locate($resource); - - $content = $this->loadFile($path); - - $this->container->fileExists($path); - - // empty file - if (null === $content) { - return; - } - - // imports - $this->parseImports($content, $path); - - // parameters - if (isset($content['parameters'])) { - if (!\is_array($content['parameters'])) { - throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in %s. Check your YAML syntax.', $path)); - } - - foreach ($content['parameters'] as $key => $value) { - $this->container->setParameter($key, $this->resolveServices($value, $path, true)); - } - } - - // extensions - $this->loadFromExtensions($content); - - // services - $this->anonymousServicesCount = 0; - $this->anonymousServicesSuffix = '~'.ContainerBuilder::hash($path); - $this->setCurrentDir(\dirname($path)); - try { - $this->parseDefinitions($content, $path); - } finally { - $this->instanceof = []; - $this->registerAliasesForSinglyImplementedInterfaces(); - } - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - if (!\is_string($resource)) { - return false; - } - - if (null === $type && \in_array(pathinfo($resource, PATHINFO_EXTENSION), ['yaml', 'yml'], true)) { - return true; - } - - return \in_array($type, ['yaml', 'yml'], true); - } - - private function parseImports(array $content, string $file) - { - if (!isset($content['imports'])) { - return; - } - - if (!\is_array($content['imports'])) { - throw new InvalidArgumentException(sprintf('The "imports" key should contain an array in %s. Check your YAML syntax.', $file)); - } - - $defaultDirectory = \dirname($file); - foreach ($content['imports'] as $import) { - if (!\is_array($import)) { - $import = ['resource' => $import]; - } - if (!isset($import['resource'])) { - throw new InvalidArgumentException(sprintf('An import should provide a resource in %s. Check your YAML syntax.', $file)); - } - - $this->setCurrentDir($defaultDirectory); - $this->import($import['resource'], $import['type'] ?? null, $import['ignore_errors'] ?? false, $file); - } - } - - private function parseDefinitions(array $content, string $file) - { - if (!isset($content['services'])) { - return; - } - - if (!\is_array($content['services'])) { - throw new InvalidArgumentException(sprintf('The "services" key should contain an array in %s. Check your YAML syntax.', $file)); - } - - if (\array_key_exists('_instanceof', $content['services'])) { - $instanceof = $content['services']['_instanceof']; - unset($content['services']['_instanceof']); - - if (!\is_array($instanceof)) { - throw new InvalidArgumentException(sprintf('Service "_instanceof" key must be an array, "%s" given in "%s".', \gettype($instanceof), $file)); - } - $this->instanceof = []; - $this->isLoadingInstanceof = true; - foreach ($instanceof as $id => $service) { - if (!$service || !\is_array($service)) { - throw new InvalidArgumentException(sprintf('Type definition "%s" must be a non-empty array within "_instanceof" in %s. Check your YAML syntax.', $id, $file)); - } - if (\is_string($service) && 0 === strpos($service, '@')) { - throw new InvalidArgumentException(sprintf('Type definition "%s" cannot be an alias within "_instanceof" in %s. Check your YAML syntax.', $id, $file)); - } - $this->parseDefinition($id, $service, $file, []); - } - } - - $this->isLoadingInstanceof = false; - $defaults = $this->parseDefaults($content, $file); - foreach ($content['services'] as $id => $service) { - $this->parseDefinition($id, $service, $file, $defaults); - } - } - - /** - * @throws InvalidArgumentException - */ - private function parseDefaults(array &$content, string $file): array - { - if (!\array_key_exists('_defaults', $content['services'])) { - return []; - } - $defaults = $content['services']['_defaults']; - unset($content['services']['_defaults']); - - if (!\is_array($defaults)) { - throw new InvalidArgumentException(sprintf('Service "_defaults" key must be an array, "%s" given in "%s".', \gettype($defaults), $file)); - } - - foreach ($defaults as $key => $default) { - if (!isset(self::$defaultsKeywords[$key])) { - throw new InvalidArgumentException(sprintf('The configuration key "%s" cannot be used to define a default value in "%s". Allowed keys are "%s".', $key, $file, implode('", "', self::$defaultsKeywords))); - } - } - - if (isset($defaults['tags'])) { - if (!\is_array($tags = $defaults['tags'])) { - throw new InvalidArgumentException(sprintf('Parameter "tags" in "_defaults" must be an array in %s. Check your YAML syntax.', $file)); - } - - foreach ($tags as $tag) { - if (!\is_array($tag)) { - $tag = ['name' => $tag]; - } - - if (!isset($tag['name'])) { - throw new InvalidArgumentException(sprintf('A "tags" entry in "_defaults" is missing a "name" key in %s.', $file)); - } - $name = $tag['name']; - unset($tag['name']); - - if (!\is_string($name) || '' === $name) { - throw new InvalidArgumentException(sprintf('The tag name in "_defaults" must be a non-empty string in %s.', $file)); - } - - foreach ($tag as $attribute => $value) { - if (!is_scalar($value) && null !== $value) { - throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type in %s. Check your YAML syntax.', $name, $attribute, $file)); - } - } - } - } - - if (isset($defaults['bind'])) { - if (!\is_array($defaults['bind'])) { - throw new InvalidArgumentException(sprintf('Parameter "bind" in "_defaults" must be an array in %s. Check your YAML syntax.', $file)); - } - - foreach ($this->resolveServices($defaults['bind'], $file) as $argument => $value) { - $defaults['bind'][$argument] = new BoundArgument($value, true, BoundArgument::DEFAULTS_BINDING, $file); - } - } - - return $defaults; - } - - private function isUsingShortSyntax(array $service): bool - { - foreach ($service as $key => $value) { - if (\is_string($key) && ('' === $key || '$' !== $key[0])) { - return false; - } - } - - return true; - } - - /** - * Parses a definition. - * - * @param array|string $service - * - * @throws InvalidArgumentException When tags are invalid - */ - private function parseDefinition(string $id, $service, string $file, array $defaults) - { - if (preg_match('/^_[a-zA-Z0-9_]*$/', $id)) { - throw new InvalidArgumentException(sprintf('Service names that start with an underscore are reserved. Rename the "%s" service or define it in XML instead.', $id)); - } - - if (\is_string($service) && 0 === strpos($service, '@')) { - $this->container->setAlias($id, $alias = new Alias(substr($service, 1))); - if (isset($defaults['public'])) { - $alias->setPublic($defaults['public']); - } - - return; - } - - if (\is_array($service) && $this->isUsingShortSyntax($service)) { - $service = ['arguments' => $service]; - } - - if (null === $service) { - $service = []; - } - - if (!\is_array($service)) { - throw new InvalidArgumentException(sprintf('A service definition must be an array or a string starting with "@" but %s found for service "%s" in %s. Check your YAML syntax.', \gettype($service), $id, $file)); - } - - $this->checkDefinition($id, $service, $file); - - if (isset($service['alias'])) { - $this->container->setAlias($id, $alias = new Alias($service['alias'])); - if (\array_key_exists('public', $service)) { - $alias->setPublic($service['public']); - } elseif (isset($defaults['public'])) { - $alias->setPublic($defaults['public']); - } - - foreach ($service as $key => $value) { - if (!\in_array($key, ['alias', 'public', 'deprecated'])) { - throw new InvalidArgumentException(sprintf('The configuration key "%s" is unsupported for the service "%s" which is defined as an alias in "%s". Allowed configuration keys for service aliases are "alias", "public" and "deprecated".', $key, $id, $file)); - } - - if ('deprecated' === $key) { - $alias->setDeprecated(true, $value); - } - } - - return; - } - - if ($this->isLoadingInstanceof) { - $definition = new ChildDefinition(''); - } elseif (isset($service['parent'])) { - if (!empty($this->instanceof)) { - throw new InvalidArgumentException(sprintf('The service "%s" cannot use the "parent" option in the same file where "_instanceof" configuration is defined as using both is not supported. Move your child definitions to a separate file.', $id)); - } - - foreach ($defaults as $k => $v) { - if ('tags' === $k) { - // since tags are never inherited from parents, there is no confusion - // thus we can safely add them as defaults to ChildDefinition - continue; - } - if ('bind' === $k) { - throw new InvalidArgumentException(sprintf('Attribute "bind" on service "%s" cannot be inherited from "_defaults" when a "parent" is set. Move your child definitions to a separate file.', $id)); - } - if (!isset($service[$k])) { - throw new InvalidArgumentException(sprintf('Attribute "%s" on service "%s" cannot be inherited from "_defaults" when a "parent" is set. Move your child definitions to a separate file or define this attribute explicitly.', $k, $id)); - } - } - - if ('' !== $service['parent'] && '@' === $service['parent'][0]) { - throw new InvalidArgumentException(sprintf('The value of the "parent" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s").', $id, $service['parent'], substr($service['parent'], 1))); - } - - $definition = new ChildDefinition($service['parent']); - } else { - $definition = new Definition(); - - if (isset($defaults['public'])) { - $definition->setPublic($defaults['public']); - } - if (isset($defaults['autowire'])) { - $definition->setAutowired($defaults['autowire']); - } - if (isset($defaults['autoconfigure'])) { - $definition->setAutoconfigured($defaults['autoconfigure']); - } - - $definition->setChanges([]); - } - - if (isset($service['class'])) { - $definition->setClass($service['class']); - } - - if (isset($service['shared'])) { - $definition->setShared($service['shared']); - } - - if (isset($service['synthetic'])) { - $definition->setSynthetic($service['synthetic']); - } - - if (isset($service['lazy'])) { - $definition->setLazy((bool) $service['lazy']); - if (\is_string($service['lazy'])) { - $definition->addTag('proxy', ['interface' => $service['lazy']]); - } - } - - if (isset($service['public'])) { - $definition->setPublic($service['public']); - } - - if (isset($service['abstract'])) { - $definition->setAbstract($service['abstract']); - } - - if (\array_key_exists('deprecated', $service)) { - $definition->setDeprecated(true, $service['deprecated']); - } - - if (isset($service['factory'])) { - $definition->setFactory($this->parseCallable($service['factory'], 'factory', $id, $file)); - } - - if (isset($service['file'])) { - $definition->setFile($service['file']); - } - - if (isset($service['arguments'])) { - $definition->setArguments($this->resolveServices($service['arguments'], $file)); - } - - if (isset($service['properties'])) { - $definition->setProperties($this->resolveServices($service['properties'], $file)); - } - - if (isset($service['configurator'])) { - $definition->setConfigurator($this->parseCallable($service['configurator'], 'configurator', $id, $file)); - } - - if (isset($service['calls'])) { - if (!\is_array($service['calls'])) { - throw new InvalidArgumentException(sprintf('Parameter "calls" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); - } - - foreach ($service['calls'] as $k => $call) { - if (!\is_array($call) && (!\is_string($k) || !$call instanceof TaggedValue)) { - throw new InvalidArgumentException(sprintf('Invalid method call for service "%s": expected map or array, %s given in %s.', $id, $call instanceof TaggedValue ? '!'.$call->getTag() : \gettype($call), $file)); - } - - if (\is_string($k)) { - throw new InvalidArgumentException(sprintf('Invalid method call for service "%s", did you forgot a leading dash before "%s: ..." in %s?', $id, $k, $file)); - } - - if (isset($call['method'])) { - $method = $call['method']; - $args = $call['arguments'] ?? []; - $returnsClone = $call['returns_clone'] ?? false; - } else { - if (1 === \count($call) && \is_string(key($call))) { - $method = key($call); - $args = $call[$method]; - - if ($args instanceof TaggedValue) { - if ('returns_clone' !== $args->getTag()) { - throw new InvalidArgumentException(sprintf('Unsupported tag "!%s", did you mean "!returns_clone" for service "%s" in %s?', $args->getTag(), $id, $file)); - } - - $returnsClone = true; - $args = $args->getValue(); - } else { - $returnsClone = false; - } - } elseif (empty($call[0])) { - throw new InvalidArgumentException(sprintf('Invalid call for service "%s": the method must be defined as the first index of an array or as the only key of a map in %s.', $id, $file)); - } else { - $method = $call[0]; - $args = $call[1] ?? []; - $returnsClone = $call[2] ?? false; - } - } - - if (!\is_array($args)) { - throw new InvalidArgumentException(sprintf('The second parameter for function call "%s" must be an array of its arguments for service "%s" in %s. Check your YAML syntax.', $method, $id, $file)); - } - - $args = $this->resolveServices($args, $file); - $definition->addMethodCall($method, $args, $returnsClone); - } - } - - $tags = isset($service['tags']) ? $service['tags'] : []; - if (!\is_array($tags)) { - throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); - } - - if (isset($defaults['tags'])) { - $tags = array_merge($tags, $defaults['tags']); - } - - foreach ($tags as $tag) { - if (!\is_array($tag)) { - $tag = ['name' => $tag]; - } - - if (!isset($tag['name'])) { - throw new InvalidArgumentException(sprintf('A "tags" entry is missing a "name" key for service "%s" in %s.', $id, $file)); - } - $name = $tag['name']; - unset($tag['name']); - - if (!\is_string($name) || '' === $name) { - throw new InvalidArgumentException(sprintf('The tag name for service "%s" in %s must be a non-empty string.', $id, $file)); - } - - foreach ($tag as $attribute => $value) { - if (!is_scalar($value) && null !== $value) { - throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s" in %s. Check your YAML syntax.', $id, $name, $attribute, $file)); - } - } - - $definition->addTag($name, $tag); - } - - if (null !== $decorates = $service['decorates'] ?? null) { - if ('' !== $decorates && '@' === $decorates[0]) { - throw new InvalidArgumentException(sprintf('The value of the "decorates" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s").', $id, $service['decorates'], substr($decorates, 1))); - } - - $decorationOnInvalid = \array_key_exists('decoration_on_invalid', $service) ? $service['decoration_on_invalid'] : 'exception'; - if ('exception' === $decorationOnInvalid) { - $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - } elseif ('ignore' === $decorationOnInvalid) { - $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - } elseif (null === $decorationOnInvalid) { - $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; - } elseif ('null' === $decorationOnInvalid) { - throw new InvalidArgumentException(sprintf('Invalid value "%s" for attribute "decoration_on_invalid" on service "%s". Did you mean null (without quotes) in "%s"?', $decorationOnInvalid, $id, $file)); - } else { - throw new InvalidArgumentException(sprintf('Invalid value "%s" for attribute "decoration_on_invalid" on service "%s". Did you mean "exception", "ignore" or null in "%s"?', $decorationOnInvalid, $id, $file)); - } - - $renameId = isset($service['decoration_inner_name']) ? $service['decoration_inner_name'] : null; - $priority = isset($service['decoration_priority']) ? $service['decoration_priority'] : 0; - - $definition->setDecoratedService($decorates, $renameId, $priority, $invalidBehavior); - } - - if (isset($service['autowire'])) { - $definition->setAutowired($service['autowire']); - } - - if (isset($defaults['bind']) || isset($service['bind'])) { - // deep clone, to avoid multiple process of the same instance in the passes - $bindings = isset($defaults['bind']) ? unserialize(serialize($defaults['bind'])) : []; - - if (isset($service['bind'])) { - if (!\is_array($service['bind'])) { - throw new InvalidArgumentException(sprintf('Parameter "bind" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); - } - - $bindings = array_merge($bindings, $this->resolveServices($service['bind'], $file)); - $bindingType = $this->isLoadingInstanceof ? BoundArgument::INSTANCEOF_BINDING : BoundArgument::SERVICE_BINDING; - foreach ($bindings as $argument => $value) { - if (!$value instanceof BoundArgument) { - $bindings[$argument] = new BoundArgument($value, true, $bindingType, $file); - } - } - } - - $definition->setBindings($bindings); - } - - if (isset($service['autoconfigure'])) { - if (!$definition instanceof ChildDefinition) { - $definition->setAutoconfigured($service['autoconfigure']); - } elseif ($service['autoconfigure']) { - throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try setting "autoconfigure: false" for the service.', $id)); - } - } - - if (\array_key_exists('namespace', $service) && !\array_key_exists('resource', $service)) { - throw new InvalidArgumentException(sprintf('A "resource" attribute must be set when the "namespace" attribute is set for service "%s" in %s. Check your YAML syntax.', $id, $file)); - } - - if (\array_key_exists('resource', $service)) { - if (!\is_string($service['resource'])) { - throw new InvalidArgumentException(sprintf('A "resource" attribute must be of type string for service "%s" in %s. Check your YAML syntax.', $id, $file)); - } - $exclude = isset($service['exclude']) ? $service['exclude'] : null; - $namespace = isset($service['namespace']) ? $service['namespace'] : $id; - $this->registerClasses($definition, $namespace, $service['resource'], $exclude); - } else { - $this->setDefinition($id, $definition); - } - } - - /** - * Parses a callable. - * - * @param string|array $callable A callable reference - * - * @throws InvalidArgumentException When errors occur - * - * @return string|array|Reference A parsed callable - */ - private function parseCallable($callable, string $parameter, string $id, string $file) - { - if (\is_string($callable)) { - if ('' !== $callable && '@' === $callable[0]) { - if (false === strpos($callable, ':')) { - return [$this->resolveServices($callable, $file), '__invoke']; - } - - throw new InvalidArgumentException(sprintf('The value of the "%s" option for the "%s" service must be the id of the service without the "@" prefix (replace "%s" with "%s" in "%s").', $parameter, $id, $callable, substr($callable, 1), $file)); - } - - return $callable; - } - - if (\is_array($callable)) { - if (isset($callable[0]) && isset($callable[1])) { - return [$this->resolveServices($callable[0], $file), $callable[1]]; - } - - if ('factory' === $parameter && isset($callable[1]) && null === $callable[0]) { - return $callable; - } - - throw new InvalidArgumentException(sprintf('Parameter "%s" must contain an array with two elements for service "%s" in %s. Check your YAML syntax.', $parameter, $id, $file)); - } - - throw new InvalidArgumentException(sprintf('Parameter "%s" must be a string or an array for service "%s" in %s. Check your YAML syntax.', $parameter, $id, $file)); - } - - /** - * Loads a YAML file. - * - * @param string $file - * - * @return array The file content - * - * @throws InvalidArgumentException when the given file is not a local file or when it does not exist - */ - protected function loadFile($file) - { - if (!class_exists('Symfony\Component\Yaml\Parser')) { - throw new RuntimeException('Unable to load YAML config files as the Symfony Yaml Component is not installed.'); - } - - if (!stream_is_local($file)) { - throw new InvalidArgumentException(sprintf('This is not a local file "%s".', $file)); - } - - if (!file_exists($file)) { - throw new InvalidArgumentException(sprintf('The file "%s" does not exist.', $file)); - } - - if (null === $this->yamlParser) { - $this->yamlParser = new YamlParser(); - } - - try { - $configuration = $this->yamlParser->parseFile($file, Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS); - } catch (ParseException $e) { - throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML: %s', $file, $e->getMessage()), 0, $e); - } - - return $this->validate($configuration, $file); - } - - /** - * Validates a YAML file. - * - * @throws InvalidArgumentException When service file is not valid - */ - private function validate($content, string $file): ?array - { - if (null === $content) { - return $content; - } - - if (!\is_array($content)) { - throw new InvalidArgumentException(sprintf('The service file "%s" is not valid. It should contain an array. Check your YAML syntax.', $file)); - } - - foreach ($content as $namespace => $data) { - if (\in_array($namespace, ['imports', 'parameters', 'services'])) { - continue; - } - - if (!$this->container->hasExtension($namespace)) { - $extensionNamespaces = array_filter(array_map(function (ExtensionInterface $ext) { return $ext->getAlias(); }, $this->container->getExtensions())); - throw new InvalidArgumentException(sprintf('There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', $namespace, $file, $namespace, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none')); - } - } - - return $content; - } - - /** - * Resolves services. - * - * @return array|string|Reference|ArgumentInterface - */ - private function resolveServices($value, string $file, bool $isParameter = false) - { - if ($value instanceof TaggedValue) { - $argument = $value->getValue(); - if ('iterator' === $value->getTag()) { - if (!\is_array($argument)) { - throw new InvalidArgumentException(sprintf('"!iterator" tag only accepts sequences in "%s".', $file)); - } - $argument = $this->resolveServices($argument, $file, $isParameter); - try { - return new IteratorArgument($argument); - } catch (InvalidArgumentException $e) { - throw new InvalidArgumentException(sprintf('"!iterator" tag only accepts arrays of "@service" references in "%s".', $file)); - } - } - if ('service_locator' === $value->getTag()) { - if (!\is_array($argument)) { - throw new InvalidArgumentException(sprintf('"!service_locator" tag only accepts maps in "%s".', $file)); - } - - $argument = $this->resolveServices($argument, $file, $isParameter); - - try { - return new ServiceLocatorArgument($argument); - } catch (InvalidArgumentException $e) { - throw new InvalidArgumentException(sprintf('"!service_locator" tag only accepts maps of "@service" references in "%s".', $file)); - } - } - if (\in_array($value->getTag(), ['tagged', 'tagged_iterator', 'tagged_locator'], true)) { - $forLocator = 'tagged_locator' === $value->getTag(); - - if (\is_array($argument) && isset($argument['tag']) && $argument['tag']) { - if ($diff = array_diff(array_keys($argument), ['tag', 'index_by', 'default_index_method', 'default_priority_method'])) { - throw new InvalidArgumentException(sprintf('"!%s" tag contains unsupported key "%s"; supported ones are "tag", "index_by", "default_index_method", and "default_priority_method".', $value->getTag(), implode('"", "', $diff))); - } - - $argument = new TaggedIteratorArgument($argument['tag'], $argument['index_by'] ?? null, $argument['default_index_method'] ?? null, $forLocator, $argument['default_priority_method'] ?? null); - } elseif (\is_string($argument) && $argument) { - $argument = new TaggedIteratorArgument($argument, null, null, $forLocator); - } else { - throw new InvalidArgumentException(sprintf('"!%s" tags only accept a non empty string or an array with a key "tag" in "%s".', $value->getTag(), $file)); - } - - if ($forLocator) { - $argument = new ServiceLocatorArgument($argument); - } - - return $argument; - } - if ('service' === $value->getTag()) { - if ($isParameter) { - throw new InvalidArgumentException(sprintf('Using an anonymous service in a parameter is not allowed in "%s".', $file)); - } - - $isLoadingInstanceof = $this->isLoadingInstanceof; - $this->isLoadingInstanceof = false; - $instanceof = $this->instanceof; - $this->instanceof = []; - - $id = sprintf('.%d_%s', ++$this->anonymousServicesCount, preg_replace('/^.*\\\\/', '', isset($argument['class']) ? $argument['class'] : '').$this->anonymousServicesSuffix); - $this->parseDefinition($id, $argument, $file, []); - - if (!$this->container->hasDefinition($id)) { - throw new InvalidArgumentException(sprintf('Creating an alias using the tag "!service" is not allowed in "%s".', $file)); - } - - $this->container->getDefinition($id)->setPublic(false); - - $this->isLoadingInstanceof = $isLoadingInstanceof; - $this->instanceof = $instanceof; - - return new Reference($id); - } - - throw new InvalidArgumentException(sprintf('Unsupported tag "!%s".', $value->getTag())); - } - - if (\is_array($value)) { - foreach ($value as $k => $v) { - $value[$k] = $this->resolveServices($v, $file, $isParameter); - } - } elseif (\is_string($value) && 0 === strpos($value, '@=')) { - if (!class_exists(Expression::class)) { - throw new \LogicException(sprintf('The "@=" expression syntax cannot be used without the ExpressionLanguage component. Try running "composer require symfony/expression-language".')); - } - - return new Expression(substr($value, 2)); - } elseif (\is_string($value) && 0 === strpos($value, '@')) { - if (0 === strpos($value, '@@')) { - $value = substr($value, 1); - $invalidBehavior = null; - } elseif (0 === strpos($value, '@!')) { - $value = substr($value, 2); - $invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; - } elseif (0 === strpos($value, '@?')) { - $value = substr($value, 2); - $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - } else { - $value = substr($value, 1); - $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - } - - if (null !== $invalidBehavior) { - $value = new Reference($value, $invalidBehavior); - } - } - - return $value; - } - - /** - * Loads from Extensions. - */ - private function loadFromExtensions(array $content) - { - foreach ($content as $namespace => $values) { - if (\in_array($namespace, ['imports', 'parameters', 'services'])) { - continue; - } - - if (!\is_array($values) && null !== $values) { - $values = []; - } - - $this->container->loadFromExtension($namespace, $values); - } - } - - /** - * Checks the keywords used to define a service. - */ - private function checkDefinition(string $id, array $definition, string $file) - { - if ($this->isLoadingInstanceof) { - $keywords = self::$instanceofKeywords; - } elseif (isset($definition['resource']) || isset($definition['namespace'])) { - $keywords = self::$prototypeKeywords; - } else { - $keywords = self::$serviceKeywords; - } - - foreach ($definition as $key => $value) { - if (!isset($keywords[$key])) { - throw new InvalidArgumentException(sprintf('The configuration key "%s" is unsupported for definition "%s" in "%s". Allowed configuration keys are "%s".', $key, $id, $file, implode('", "', $keywords))); - } - } - } -} diff --git a/vendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd b/vendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd deleted file mode 100644 index 2f745c3..0000000 --- a/vendor/symfony/dependency-injection/Loader/schema/dic/services/services-1.0.xsd +++ /dev/null @@ -1,305 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/dependency-injection/Parameter.php b/vendor/symfony/dependency-injection/Parameter.php deleted file mode 100644 index d484ac0..0000000 --- a/vendor/symfony/dependency-injection/Parameter.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * Parameter represents a parameter reference. - * - * @author Fabien Potencier - */ -class Parameter -{ - private $id; - - public function __construct(string $id) - { - $this->id = $id; - } - - /** - * @return string The parameter key - */ - public function __toString() - { - return $this->id; - } -} diff --git a/vendor/symfony/dependency-injection/ParameterBag/ContainerBag.php b/vendor/symfony/dependency-injection/ParameterBag/ContainerBag.php deleted file mode 100644 index 7671dfc..0000000 --- a/vendor/symfony/dependency-injection/ParameterBag/ContainerBag.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\ParameterBag; - -use Symfony\Component\DependencyInjection\Container; - -/** - * @author Nicolas Grekas - */ -class ContainerBag extends FrozenParameterBag implements ContainerBagInterface -{ - private $container; - - public function __construct(Container $container) - { - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function all() - { - return $this->container->getParameterBag()->all(); - } - - /** - * {@inheritdoc} - */ - public function get($name) - { - return $this->container->getParameter($name); - } - - /** - * {@inheritdoc} - */ - public function has($name) - { - return $this->container->hasParameter($name); - } -} diff --git a/vendor/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php b/vendor/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php deleted file mode 100644 index 1c1227a..0000000 --- a/vendor/symfony/dependency-injection/ParameterBag/ContainerBagInterface.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\ParameterBag; - -use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; - -/** - * ContainerBagInterface is the interface implemented by objects that manage service container parameters. - * - * @author Nicolas Grekas - */ -interface ContainerBagInterface extends ContainerInterface -{ - /** - * Gets the service container parameters. - * - * @return array An array of parameters - */ - public function all(); - - /** - * Replaces parameter placeholders (%name%) by their values. - * - * @param mixed $value A value - * - * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist - */ - public function resolveValue($value); - - /** - * Escape parameter placeholders %. - * - * @param mixed $value - * - * @return mixed - */ - public function escapeValue($value); - - /** - * Unescape parameter placeholders %. - * - * @param mixed $value - * - * @return mixed - */ - public function unescapeValue($value); -} diff --git a/vendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php b/vendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php deleted file mode 100644 index ec95d4c..0000000 --- a/vendor/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php +++ /dev/null @@ -1,154 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\ParameterBag; - -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * @author Nicolas Grekas - */ -class EnvPlaceholderParameterBag extends ParameterBag -{ - private $envPlaceholderUniquePrefix; - private $envPlaceholders = []; - private $unusedEnvPlaceholders = []; - private $providedTypes = []; - - private static $counter = 0; - - /** - * {@inheritdoc} - */ - public function get(string $name) - { - if (0 === strpos($name, 'env(') && ')' === substr($name, -1) && 'env()' !== $name) { - $env = substr($name, 4, -1); - - if (isset($this->envPlaceholders[$env])) { - foreach ($this->envPlaceholders[$env] as $placeholder) { - return $placeholder; // return first result - } - } - if (isset($this->unusedEnvPlaceholders[$env])) { - foreach ($this->unusedEnvPlaceholders[$env] as $placeholder) { - return $placeholder; // return first result - } - } - if (!preg_match('/^(?:\w*+:)*+\w++$/', $env)) { - throw new InvalidArgumentException(sprintf('Invalid %s name: only "word" characters are allowed.', $name)); - } - if ($this->has($name) && null !== ($defaultValue = parent::get($name)) && !\is_string($defaultValue)) { - throw new RuntimeException(sprintf('The default value of an env() parameter must be a string or null, but "%s" given to "%s".', \gettype($defaultValue), $name)); - } - - $uniqueName = md5($name.'_'.self::$counter++); - $placeholder = sprintf('%s_%s_%s', $this->getEnvPlaceholderUniquePrefix(), str_replace(':', '_', $env), $uniqueName); - $this->envPlaceholders[$env][$placeholder] = $placeholder; - - return $placeholder; - } - - return parent::get($name); - } - - /** - * Gets the common env placeholder prefix for env vars created by this bag. - */ - public function getEnvPlaceholderUniquePrefix(): string - { - if (null === $this->envPlaceholderUniquePrefix) { - $reproducibleEntropy = unserialize(serialize($this->parameters)); - array_walk_recursive($reproducibleEntropy, function (&$v) { $v = null; }); - $this->envPlaceholderUniquePrefix = 'env_'.substr(md5(serialize($reproducibleEntropy)), -16); - } - - return $this->envPlaceholderUniquePrefix; - } - - /** - * Returns the map of env vars used in the resolved parameter values to their placeholders. - * - * @return string[][] A map of env var names to their placeholders - */ - public function getEnvPlaceholders() - { - return $this->envPlaceholders; - } - - public function getUnusedEnvPlaceholders(): array - { - return $this->unusedEnvPlaceholders; - } - - public function clearUnusedEnvPlaceholders() - { - $this->unusedEnvPlaceholders = []; - } - - /** - * Merges the env placeholders of another EnvPlaceholderParameterBag. - */ - public function mergeEnvPlaceholders(self $bag) - { - if ($newPlaceholders = $bag->getEnvPlaceholders()) { - $this->envPlaceholders += $newPlaceholders; - - foreach ($newPlaceholders as $env => $placeholders) { - $this->envPlaceholders[$env] += $placeholders; - } - } - - if ($newUnusedPlaceholders = $bag->getUnusedEnvPlaceholders()) { - $this->unusedEnvPlaceholders += $newUnusedPlaceholders; - - foreach ($newUnusedPlaceholders as $env => $placeholders) { - $this->unusedEnvPlaceholders[$env] += $placeholders; - } - } - } - - /** - * Maps env prefixes to their corresponding PHP types. - */ - public function setProvidedTypes(array $providedTypes) - { - $this->providedTypes = $providedTypes; - } - - /** - * Gets the PHP types corresponding to env() parameter prefixes. - * - * @return string[][] - */ - public function getProvidedTypes() - { - return $this->providedTypes; - } - - /** - * {@inheritdoc} - */ - public function resolve() - { - if ($this->resolved) { - return; - } - parent::resolve(); - - foreach ($this->envPlaceholders as $env => $placeholders) { - if ($this->has($name = "env($env)") && null !== ($default = $this->parameters[$name]) && !\is_string($default)) { - throw new RuntimeException(sprintf('The default value of env parameter "%s" must be a string or null, %s given.', $env, \gettype($default))); - } - } - } -} diff --git a/vendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php b/vendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php deleted file mode 100644 index 5a4aaf8..0000000 --- a/vendor/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php +++ /dev/null @@ -1,68 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\ParameterBag; - -use Symfony\Component\DependencyInjection\Exception\LogicException; - -/** - * Holds read-only parameters. - * - * @author Fabien Potencier - */ -class FrozenParameterBag extends ParameterBag -{ - /** - * For performance reasons, the constructor assumes that - * all keys are already lowercased. - * - * This is always the case when used internally. - * - * @param array $parameters An array of parameters - */ - public function __construct(array $parameters = []) - { - $this->parameters = $parameters; - $this->resolved = true; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - throw new LogicException('Impossible to call clear() on a frozen ParameterBag.'); - } - - /** - * {@inheritdoc} - */ - public function add(array $parameters) - { - throw new LogicException('Impossible to call add() on a frozen ParameterBag.'); - } - - /** - * {@inheritdoc} - */ - public function set(string $name, $value) - { - throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); - } - - /** - * {@inheritdoc} - */ - public function remove(string $name) - { - throw new LogicException('Impossible to call remove() on a frozen ParameterBag.'); - } -} diff --git a/vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php b/vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php deleted file mode 100644 index 643424a..0000000 --- a/vendor/symfony/dependency-injection/ParameterBag/ParameterBag.php +++ /dev/null @@ -1,286 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\ParameterBag; - -use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; - -/** - * Holds parameters. - * - * @author Fabien Potencier - */ -class ParameterBag implements ParameterBagInterface -{ - protected $parameters = []; - protected $resolved = false; - - /** - * @param array $parameters An array of parameters - */ - public function __construct(array $parameters = []) - { - $this->add($parameters); - } - - /** - * Clears all parameters. - */ - public function clear() - { - $this->parameters = []; - } - - /** - * Adds parameters to the service container parameters. - * - * @param array $parameters An array of parameters - */ - public function add(array $parameters) - { - foreach ($parameters as $key => $value) { - $this->set($key, $value); - } - } - - /** - * {@inheritdoc} - */ - public function all() - { - return $this->parameters; - } - - /** - * {@inheritdoc} - */ - public function get(string $name) - { - if (!\array_key_exists($name, $this->parameters)) { - if (!$name) { - throw new ParameterNotFoundException($name); - } - - $alternatives = []; - foreach ($this->parameters as $key => $parameterValue) { - $lev = levenshtein($name, $key); - if ($lev <= \strlen($name) / 3 || false !== strpos($key, $name)) { - $alternatives[] = $key; - } - } - - $nonNestedAlternative = null; - if (!\count($alternatives) && false !== strpos($name, '.')) { - $namePartsLength = array_map('strlen', explode('.', $name)); - $key = substr($name, 0, -1 * (1 + array_pop($namePartsLength))); - while (\count($namePartsLength)) { - if ($this->has($key)) { - if (\is_array($this->get($key))) { - $nonNestedAlternative = $key; - } - break; - } - - $key = substr($key, 0, -1 * (1 + array_pop($namePartsLength))); - } - } - - throw new ParameterNotFoundException($name, null, null, null, $alternatives, $nonNestedAlternative); - } - - return $this->parameters[$name]; - } - - /** - * Sets a service container parameter. - * - * @param string $name The parameter name - * @param mixed $value The parameter value - */ - public function set(string $name, $value) - { - $this->parameters[$name] = $value; - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - return \array_key_exists((string) $name, $this->parameters); - } - - /** - * Removes a parameter. - * - * @param string $name The parameter name - */ - public function remove(string $name) - { - unset($this->parameters[$name]); - } - - /** - * {@inheritdoc} - */ - public function resolve() - { - if ($this->resolved) { - return; - } - - $parameters = []; - foreach ($this->parameters as $key => $value) { - try { - $value = $this->resolveValue($value); - $parameters[$key] = $this->unescapeValue($value); - } catch (ParameterNotFoundException $e) { - $e->setSourceKey($key); - - throw $e; - } - } - - $this->parameters = $parameters; - $this->resolved = true; - } - - /** - * Replaces parameter placeholders (%name%) by their values. - * - * @param mixed $value A value - * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) - * - * @return mixed The resolved value - * - * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist - * @throws ParameterCircularReferenceException if a circular reference if detected - * @throws RuntimeException when a given parameter has a type problem - */ - public function resolveValue($value, array $resolving = []) - { - if (\is_array($value)) { - $args = []; - foreach ($value as $k => $v) { - $args[\is_string($k) ? $this->resolveValue($k, $resolving) : $k] = $this->resolveValue($v, $resolving); - } - - return $args; - } - - if (!\is_string($value) || 2 > \strlen($value)) { - return $value; - } - - return $this->resolveString($value, $resolving); - } - - /** - * Resolves parameters inside a string. - * - * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) - * - * @return mixed The resolved string - * - * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist - * @throws ParameterCircularReferenceException if a circular reference if detected - * @throws RuntimeException when a given parameter has a type problem - */ - public function resolveString(string $value, array $resolving = []) - { - // we do this to deal with non string values (Boolean, integer, ...) - // as the preg_replace_callback throw an exception when trying - // a non-string in a parameter value - if (preg_match('/^%([^%\s]+)%$/', $value, $match)) { - $key = $match[1]; - - if (isset($resolving[$key])) { - throw new ParameterCircularReferenceException(array_keys($resolving)); - } - - $resolving[$key] = true; - - return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving); - } - - return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($resolving, $value) { - // skip %% - if (!isset($match[1])) { - return '%%'; - } - - $key = $match[1]; - if (isset($resolving[$key])) { - throw new ParameterCircularReferenceException(array_keys($resolving)); - } - - $resolved = $this->get($key); - - if (!\is_string($resolved) && !is_numeric($resolved)) { - throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type %s inside string value "%s".', $key, \gettype($resolved), $value)); - } - - $resolved = (string) $resolved; - $resolving[$key] = true; - - return $this->isResolved() ? $resolved : $this->resolveString($resolved, $resolving); - }, $value); - } - - public function isResolved() - { - return $this->resolved; - } - - /** - * {@inheritdoc} - */ - public function escapeValue($value) - { - if (\is_string($value)) { - return str_replace('%', '%%', $value); - } - - if (\is_array($value)) { - $result = []; - foreach ($value as $k => $v) { - $result[$k] = $this->escapeValue($v); - } - - return $result; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - public function unescapeValue($value) - { - if (\is_string($value)) { - return str_replace('%%', '%', $value); - } - - if (\is_array($value)) { - $result = []; - foreach ($value as $k => $v) { - $result[$k] = $this->unescapeValue($v); - } - - return $result; - } - - return $value; - } -} diff --git a/vendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php b/vendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php deleted file mode 100644 index f224216..0000000 --- a/vendor/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php +++ /dev/null @@ -1,108 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\ParameterBag; - -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; - -/** - * ParameterBagInterface is the interface implemented by objects that manage service container parameters. - * - * @author Fabien Potencier - */ -interface ParameterBagInterface -{ - /** - * Clears all parameters. - * - * @throws LogicException if the ParameterBagInterface can not be cleared - */ - public function clear(); - - /** - * Adds parameters to the service container parameters. - * - * @param array $parameters An array of parameters - * - * @throws LogicException if the parameter can not be added - */ - public function add(array $parameters); - - /** - * Gets the service container parameters. - * - * @return array An array of parameters - */ - public function all(); - - /** - * Gets a service container parameter. - * - * @return mixed The parameter value - * - * @throws ParameterNotFoundException if the parameter is not defined - */ - public function get(string $name); - - /** - * Removes a parameter. - */ - public function remove(string $name); - - /** - * Sets a service container parameter. - * - * @param mixed $value The parameter value - * - * @throws LogicException if the parameter can not be set - */ - public function set(string $name, $value); - - /** - * Returns true if a parameter name is defined. - * - * @return bool true if the parameter name is defined, false otherwise - */ - public function has(string $name); - - /** - * Replaces parameter placeholders (%name%) by their values for all parameters. - */ - public function resolve(); - - /** - * Replaces parameter placeholders (%name%) by their values. - * - * @param mixed $value A value - * - * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist - */ - public function resolveValue($value); - - /** - * Escape parameter placeholders %. - * - * @param mixed $value - * - * @return mixed - */ - public function escapeValue($value); - - /** - * Unescape parameter placeholders %. - * - * @param mixed $value - * - * @return mixed - */ - public function unescapeValue($value); -} diff --git a/vendor/symfony/dependency-injection/README.md b/vendor/symfony/dependency-injection/README.md deleted file mode 100644 index 932647f..0000000 --- a/vendor/symfony/dependency-injection/README.md +++ /dev/null @@ -1,14 +0,0 @@ -DependencyInjection Component -============================= - -The DependencyInjection component allows you to standardize and centralize the -way objects are constructed in your application. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/dependency_injection/index.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/dependency-injection/Reference.php b/vendor/symfony/dependency-injection/Reference.php deleted file mode 100644 index c13cf6f..0000000 --- a/vendor/symfony/dependency-injection/Reference.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * Reference represents a service reference. - * - * @author Fabien Potencier - */ -class Reference -{ - private $id; - private $invalidBehavior; - - public function __construct(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) - { - $this->id = $id; - $this->invalidBehavior = $invalidBehavior; - } - - /** - * @return string The service identifier - */ - public function __toString() - { - return $this->id; - } - - /** - * Returns the behavior to be used when the service does not exist. - * - * @return int - */ - public function getInvalidBehavior() - { - return $this->invalidBehavior; - } -} diff --git a/vendor/symfony/dependency-injection/ReverseContainer.php b/vendor/symfony/dependency-injection/ReverseContainer.php deleted file mode 100644 index 280e9e2..0000000 --- a/vendor/symfony/dependency-injection/ReverseContainer.php +++ /dev/null @@ -1,81 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; - -/** - * Turns public and "container.reversible" services back to their ids. - * - * @author Nicolas Grekas - */ -final class ReverseContainer -{ - private $serviceContainer; - private $reversibleLocator; - private $tagName; - private $getServiceId; - - public function __construct(Container $serviceContainer, ContainerInterface $reversibleLocator, string $tagName = 'container.reversible') - { - $this->serviceContainer = $serviceContainer; - $this->reversibleLocator = $reversibleLocator; - $this->tagName = $tagName; - $this->getServiceId = \Closure::bind(function (object $service): ?string { - return array_search($service, $this->services, true) ?: array_search($service, $this->privates, true) ?: null; - }, $serviceContainer, Container::class); - } - - /** - * Returns the id of the passed object when it exists as a service. - * - * To be reversible, services need to be either public or be tagged with "container.reversible". - */ - public function getId(object $service): ?string - { - if ($this->serviceContainer === $service) { - return 'service_container'; - } - - if (null === $id = ($this->getServiceId)($service)) { - return null; - } - - if ($this->serviceContainer->has($id) || $this->reversibleLocator->has($id)) { - return $id; - } - - return null; - } - - /** - * @throws ServiceNotFoundException When the service is not reversible - */ - public function getService(string $id): object - { - if ($this->serviceContainer->has($id)) { - return $this->serviceContainer->get($id); - } - - if ($this->reversibleLocator->has($id)) { - return $this->reversibleLocator->get($id); - } - - if (isset($this->serviceContainer->getRemovedIds()[$id])) { - throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service is private and cannot be accessed by reference. You should either make it public, or tag it as "%s".', $id, $this->tagName)); - } - - // will throw a ServiceNotFoundException - $this->serviceContainer->get($id); - } -} diff --git a/vendor/symfony/dependency-injection/ServiceLocator.php b/vendor/symfony/dependency-injection/ServiceLocator.php deleted file mode 100644 index dd97e39..0000000 --- a/vendor/symfony/dependency-injection/ServiceLocator.php +++ /dev/null @@ -1,145 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\NotFoundExceptionInterface; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Contracts\Service\ServiceLocatorTrait; -use Symfony\Contracts\Service\ServiceProviderInterface; -use Symfony\Contracts\Service\ServiceSubscriberInterface; - -/** - * @author Robin Chalas - * @author Nicolas Grekas - */ -class ServiceLocator implements ServiceProviderInterface -{ - use ServiceLocatorTrait { - get as private doGet; - } - - private $externalId; - private $container; - - public function get($id) - { - if (!$this->externalId) { - return $this->doGet($id); - } - - try { - return $this->doGet($id); - } catch (RuntimeException $e) { - $what = sprintf('service "%s" required by "%s"', $id, $this->externalId); - $message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage()); - - if ($e->getMessage() === $message) { - $message = sprintf('Cannot resolve %s: %s', $what, $message); - } - - $r = new \ReflectionProperty($e, 'message'); - $r->setAccessible(true); - $r->setValue($e, $message); - - throw $e; - } - } - - public function __invoke(string $id) - { - return isset($this->factories[$id]) ? $this->get($id) : null; - } - - /** - * @internal - * - * @return static - */ - public function withContext(string $externalId, Container $container): self - { - $locator = clone $this; - $locator->externalId = $externalId; - $locator->container = $container; - - return $locator; - } - - private function createNotFoundException(string $id): NotFoundExceptionInterface - { - if ($this->loading) { - $msg = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $this->formatAlternatives()); - - return new ServiceNotFoundException($id, end($this->loading) ?: null, null, [], $msg); - } - - $class = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, 4); - $class = isset($class[3]['object']) ? \get_class($class[3]['object']) : null; - $externalId = $this->externalId ?: $class; - - $msg = []; - $msg[] = sprintf('Service "%s" not found:', $id); - - if (!$this->container) { - $class = null; - } elseif ($this->container->has($id) || isset($this->container->getRemovedIds()[$id])) { - $msg[] = 'even though it exists in the app\'s container,'; - } else { - try { - $this->container->get($id); - $class = null; - } catch (ServiceNotFoundException $e) { - if ($e->getAlternatives()) { - $msg[] = sprintf('did you mean %s? Anyway,', $this->formatAlternatives($e->getAlternatives(), 'or')); - } else { - $class = null; - } - } - } - if ($externalId) { - $msg[] = sprintf('the container inside "%s" is a smaller service locator that %s', $externalId, $this->formatAlternatives()); - } else { - $msg[] = sprintf('the current service locator %s', $this->formatAlternatives()); - } - - if (!$class) { - // no-op - } elseif (is_subclass_of($class, ServiceSubscriberInterface::class)) { - $msg[] = sprintf('Unless you need extra laziness, try using dependency injection instead. Otherwise, you need to declare it using "%s::getSubscribedServices()".', preg_replace('/([^\\\\]++\\\\)++/', '', $class)); - } else { - $msg[] = 'Try using dependency injection instead.'; - } - - return new ServiceNotFoundException($id, end($this->loading) ?: null, null, [], implode(' ', $msg)); - } - - private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface - { - return new ServiceCircularReferenceException($id, $path); - } - - private function formatAlternatives(array $alternatives = null, string $separator = 'and'): string - { - $format = '"%s"%s'; - if (null === $alternatives) { - if (!$alternatives = array_keys($this->factories)) { - return 'is empty...'; - } - $format = sprintf('only knows about the %s service%s.', $format, 1 < \count($alternatives) ? 's' : ''); - } - $last = array_pop($alternatives); - - return sprintf($format, $alternatives ? implode('", "', $alternatives) : $last, $alternatives ? sprintf(' %s "%s"', $separator, $last) : ''); - } -} diff --git a/vendor/symfony/dependency-injection/TaggedContainerInterface.php b/vendor/symfony/dependency-injection/TaggedContainerInterface.php deleted file mode 100644 index 2e32cd5..0000000 --- a/vendor/symfony/dependency-injection/TaggedContainerInterface.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * TaggedContainerInterface is the interface implemented when a container knows how to deals with tags. - * - * @author Fabien Potencier - */ -interface TaggedContainerInterface extends ContainerInterface -{ - /** - * Returns service ids for a given tag. - * - * @param string $name The tag name - * - * @return array An array of tags - */ - public function findTaggedServiceIds(string $name); -} diff --git a/vendor/symfony/dependency-injection/TypedReference.php b/vendor/symfony/dependency-injection/TypedReference.php deleted file mode 100644 index 3765bc7..0000000 --- a/vendor/symfony/dependency-injection/TypedReference.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * Represents a PHP type-hinted service reference. - * - * @author Nicolas Grekas - */ -class TypedReference extends Reference -{ - private $type; - private $name; - private $requiringClass; - - /** - * @param string $id The service identifier - * @param string $type The PHP type of the identified service - * @param int $invalidBehavior The behavior when the service does not exist - * @param string $name The name of the argument targeting the service - */ - public function __construct(string $id, string $type, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, string $name = null) - { - $this->name = $type === $id ? $name : null; - parent::__construct($id, $invalidBehavior); - $this->type = $type; - } - - public function getType() - { - return $this->type; - } - - public function getName(): ?string - { - return $this->name; - } -} diff --git a/vendor/symfony/dependency-injection/Variable.php b/vendor/symfony/dependency-injection/Variable.php deleted file mode 100644 index 21d33eb..0000000 --- a/vendor/symfony/dependency-injection/Variable.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -/** - * Represents a variable. - * - * $var = new Variable('a'); - * - * will be dumped as - * - * $a - * - * by the PHP dumper. - * - * @author Johannes M. Schmitt - */ -class Variable -{ - private $name; - - public function __construct(string $name) - { - $this->name = $name; - } - - /** - * @return string - */ - public function __toString() - { - return $this->name; - } -} diff --git a/vendor/symfony/dependency-injection/composer.json b/vendor/symfony/dependency-injection/composer.json deleted file mode 100644 index 25e65e3..0000000 --- a/vendor/symfony/dependency-injection/composer.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "name": "symfony/dependency-injection", - "type": "library", - "description": "Symfony DependencyInjection Component", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "psr/container": "^1.0", - "symfony/service-contracts": "^1.1.6|^2" - }, - "require-dev": { - "symfony/yaml": "^4.4|^5.0", - "symfony/config": "^5.0", - "symfony/expression-language": "^4.4|^5.0" - }, - "suggest": { - "symfony/yaml": "", - "symfony/config": "", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them" - }, - "conflict": { - "symfony/config": "<5.0", - "symfony/finder": "<4.4", - "symfony/proxy-manager-bridge": "<4.4", - "symfony/yaml": "<4.4" - }, - "provide": { - "psr/container-implementation": "1.0", - "symfony/service-implementation": "1.0" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\DependencyInjection\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/doctrine-bridge/.gitattributes b/vendor/symfony/doctrine-bridge/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/doctrine-bridge/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/doctrine-bridge/CHANGELOG.md b/vendor/symfony/doctrine-bridge/CHANGELOG.md deleted file mode 100644 index 78ebd8b..0000000 --- a/vendor/symfony/doctrine-bridge/CHANGELOG.md +++ /dev/null @@ -1,114 +0,0 @@ -CHANGELOG -========= - -5.0.0 ------ - - * the `getMetadataDriverClass()` method is abstract and must be implemented by class extending `AbstractDoctrineExtension` - * passing an `IdReader` to the `DoctrineChoiceLoader` when the query cannot be optimized with single id field, throws an exception; pass `null` instead - * not explicitly passing an instance of `IdReader` to `DoctrineChoiceLoader` when it can optimize single id field, will not apply any optimization - * `DoctrineExtractor` now requires an `EntityManagerInterface` on instantiation - -4.4.0 ------ - - * [BC BREAK] using null as `$classValidatorRegexp` value in `DoctrineLoader::__construct` will not enable auto-mapping for all classes anymore, use `'{.*}'` instead. - * added `DoctrineClearEntityManagerWorkerSubscriber` - * deprecated `RegistryInterface`, use `Doctrine\Persistence\ManagerRegistry` - * added support for invokable event listeners - * added `getMetadataDriverClass` method to deprecate class parameters in service configuration files - -4.3.0 ------ - - * changed guessing of DECIMAL to set the `input` option of `NumberType` to string - * deprecated not passing an `IdReader` to the `DoctrineChoiceLoader` when query can be optimized with a single id field - * deprecated passing an `IdReader` to the `DoctrineChoiceLoader` when entities have a composite id - * added two Messenger middleware: `DoctrinePingConnectionMiddleware` and `DoctrineCloseConnectionMiddleware` - -4.2.0 ------ - - * deprecated injecting `ClassMetadataFactory` in `DoctrineExtractor`, - an instance of `EntityManagerInterface` should be injected instead - * added support for `simple_array` type - * the `DoctrineTransactionMiddlewareFactory` class has been removed - -4.1.0 ------ - - * added support for datetime immutable types in form type guesser - -4.0.0 ------ - - * the first constructor argument of the `DoctrineChoiceLoader` class must be - an `ObjectManager` implementation - * removed the `MergeDoctrineCollectionListener::onBind()` method - * trying to reset a non-lazy manager service using the `ManagerRegistry::resetService()` - method throws an exception - * removed the `DoctrineParserCache` class - -3.4.0 ------ - - * added support for doctrine/dbal v2.6 types - * added cause of UniqueEntity constraint violation - * deprecated `DbalSessionHandler` and `DbalSessionHandlerSchema` in favor of - `Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler` - -3.1.0 ------ - - * added "{{ value }}" message placeholder to UniqueEntityValidator - * deprecated `MergeDoctrineCollectionListener::onBind` in favor of - `MergeDoctrineCollectionListener::onSubmit` - * deprecated passing `ChoiceListFactoryInterface` as first argument of - `DoctrineChoiceLoader`'s constructor - -3.0.0 ------ - - * removed `EntityChoiceList` - * removed `$manager` (2nd) and `$class` (3th) arguments of `ORMQueryBuilderLoader` - * removed passing a query builder closure to `ORMQueryBuilderLoader` - * removed `loader` and `property` options of the `DoctrineType` - -2.8.0 ------ - - * deprecated using the entity provider with a Doctrine repository implementing UserProviderInterface - * added UserLoaderInterface for loading users through Doctrine. - -2.7.0 ------ - - * added DoctrineChoiceLoader - * deprecated EntityChoiceList - * deprecated passing a query builder closure to ORMQueryBuilderLoader - * deprecated $manager and $em arguments of ORMQueryBuilderLoader - * added optional arguments $propertyAccessor and $choiceListFactory to DoctrineOrmExtension constructor - * deprecated "loader" and "property" options of DoctrineType - -2.4.0 ------ - - * deprecated DoctrineOrmTestCase class - -2.2.0 ------ - - * added an optional PropertyAccessorInterface parameter to DoctrineType, - EntityType and EntityChoiceList - -2.1.0 ------ - - * added a default implementation of the ManagerRegistry - * added a session storage for Doctrine DBAL - * DoctrineOrmTypeGuesser now guesses "collection" for array Doctrine type - * DoctrineType now caches its choice lists in order to improve performance - * DoctrineType now uses ManagerRegistry::getManagerForClass() if the option "em" is not set - * UniqueEntity validation constraint now accepts a "repositoryMethod" option that will be used to check for uniqueness instead of the default "findBy" - * [BC BREAK] the DbalLogger::log() visibility has been changed from public to - protected diff --git a/vendor/symfony/doctrine-bridge/CacheWarmer/ProxyCacheWarmer.php b/vendor/symfony/doctrine-bridge/CacheWarmer/ProxyCacheWarmer.php deleted file mode 100644 index 0a90bc1..0000000 --- a/vendor/symfony/doctrine-bridge/CacheWarmer/ProxyCacheWarmer.php +++ /dev/null @@ -1,69 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\CacheWarmer; - -use Doctrine\Persistence\ManagerRegistry; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; - -/** - * The proxy generator cache warmer generates all entity proxies. - * - * In the process of generating proxies the cache for all the metadata is primed also, - * since this information is necessary to build the proxies in the first place. - * - * @author Benjamin Eberlei - */ -class ProxyCacheWarmer implements CacheWarmerInterface -{ - private $registry; - - public function __construct(ManagerRegistry $registry) - { - $this->registry = $registry; - } - - /** - * This cache warmer is not optional, without proxies fatal error occurs! - * - * @return false - */ - public function isOptional() - { - return false; - } - - /** - * {@inheritdoc} - */ - public function warmUp(string $cacheDir) - { - foreach ($this->registry->getManagers() as $em) { - // we need the directory no matter the proxy cache generation strategy - if (!is_dir($proxyCacheDir = $em->getConfiguration()->getProxyDir())) { - if (false === @mkdir($proxyCacheDir, 0777, true)) { - throw new \RuntimeException(sprintf('Unable to create the Doctrine Proxy directory "%s".', $proxyCacheDir)); - } - } elseif (!is_writable($proxyCacheDir)) { - throw new \RuntimeException(sprintf('The Doctrine Proxy directory "%s" is not writeable for the current system user.', $proxyCacheDir)); - } - - // if proxies are autogenerated we don't need to generate them in the cache warmer - if ($em->getConfiguration()->getAutoGenerateProxyClasses()) { - continue; - } - - $classes = $em->getMetadataFactory()->getAllMetadata(); - - $em->getProxyFactory()->generateProxyClasses($classes); - } - } -} diff --git a/vendor/symfony/doctrine-bridge/ContainerAwareEventManager.php b/vendor/symfony/doctrine-bridge/ContainerAwareEventManager.php deleted file mode 100644 index 67ba6ab..0000000 --- a/vendor/symfony/doctrine-bridge/ContainerAwareEventManager.php +++ /dev/null @@ -1,174 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine; - -use Doctrine\Common\EventArgs; -use Doctrine\Common\EventManager; -use Psr\Container\ContainerInterface; - -/** - * Allows lazy loading of listener services. - * - * @author Johannes M. Schmitt - */ -class ContainerAwareEventManager extends EventManager -{ - /** - * Map of registered listeners. - * - * => - */ - private $listeners = []; - private $initialized = []; - private $methods = []; - private $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - /** - * {@inheritdoc} - * - * @return void - */ - public function dispatchEvent($eventName, EventArgs $eventArgs = null) - { - if (!isset($this->listeners[$eventName])) { - return; - } - - $eventArgs = null === $eventArgs ? EventArgs::getEmptyInstance() : $eventArgs; - - if (!isset($this->initialized[$eventName])) { - $this->initializeListeners($eventName); - } - - foreach ($this->listeners[$eventName] as $hash => $listener) { - $listener->{$this->methods[$eventName][$hash]}($eventArgs); - } - } - - /** - * {@inheritdoc} - * - * @return object[][] - */ - public function getListeners($event = null) - { - if (null !== $event) { - if (!isset($this->initialized[$event])) { - $this->initializeListeners($event); - } - - return $this->listeners[$event]; - } - - foreach ($this->listeners as $event => $listeners) { - if (!isset($this->initialized[$event])) { - $this->initializeListeners($event); - } - } - - return $this->listeners; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function hasListeners($event) - { - return isset($this->listeners[$event]) && $this->listeners[$event]; - } - - /** - * {@inheritdoc} - * - * @return void - */ - public function addEventListener($events, $listener) - { - $hash = $this->getHash($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; - - if (\is_string($listener)) { - unset($this->initialized[$event]); - } else { - $this->methods[$event][$hash] = $this->getMethod($listener, $event); - } - } - } - - /** - * {@inheritdoc} - * - * @return void - */ - public function removeEventListener($events, $listener) - { - $hash = $this->getHash($listener); - - foreach ((array) $events as $event) { - // Check if we actually have this listener associated - if (isset($this->listeners[$event][$hash])) { - unset($this->listeners[$event][$hash]); - } - - if (isset($this->methods[$event][$hash])) { - unset($this->methods[$event][$hash]); - } - } - } - - private function initializeListeners(string $eventName) - { - foreach ($this->listeners[$eventName] as $hash => $listener) { - if (\is_string($listener)) { - $this->listeners[$eventName][$hash] = $listener = $this->container->get($listener); - - $this->methods[$eventName][$hash] = $this->getMethod($listener, $eventName); - } - } - $this->initialized[$eventName] = true; - } - - /** - * @param string|object $listener - */ - private function getHash($listener): string - { - if (\is_string($listener)) { - return '_service_'.$listener; - } - - return spl_object_hash($listener); - } - - /** - * @param object $listener - */ - private function getMethod($listener, string $event): string - { - if (!method_exists($listener, $event) && method_exists($listener, '__invoke')) { - return '__invoke'; - } - - return $event; - } -} diff --git a/vendor/symfony/doctrine-bridge/DataCollector/DoctrineDataCollector.php b/vendor/symfony/doctrine-bridge/DataCollector/DoctrineDataCollector.php deleted file mode 100644 index 67bf68d..0000000 --- a/vendor/symfony/doctrine-bridge/DataCollector/DoctrineDataCollector.php +++ /dev/null @@ -1,245 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\DataCollector; - -use Doctrine\DBAL\Logging\DebugStack; -use Doctrine\DBAL\Types\ConversionException; -use Doctrine\DBAL\Types\Type; -use Doctrine\Persistence\ManagerRegistry; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\DataCollector\DataCollector; -use Symfony\Component\VarDumper\Caster\Caster; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * DoctrineDataCollector. - * - * @author Fabien Potencier - */ -class DoctrineDataCollector extends DataCollector -{ - private $registry; - private $connections; - private $managers; - - /** - * @var DebugStack[] - */ - private $loggers = []; - - public function __construct(ManagerRegistry $registry) - { - $this->registry = $registry; - $this->connections = $registry->getConnectionNames(); - $this->managers = $registry->getManagerNames(); - } - - /** - * Adds the stack logger for a connection. - */ - public function addLogger(string $name, DebugStack $logger) - { - $this->loggers[$name] = $logger; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - $queries = []; - foreach ($this->loggers as $name => $logger) { - $queries[$name] = $this->sanitizeQueries($name, $logger->queries); - } - - $this->data = [ - 'queries' => $queries, - 'connections' => $this->connections, - 'managers' => $this->managers, - ]; - } - - public function reset() - { - $this->data = []; - - foreach ($this->loggers as $logger) { - $logger->queries = []; - $logger->currentQuery = 0; - } - } - - public function getManagers() - { - return $this->data['managers']; - } - - public function getConnections() - { - return $this->data['connections']; - } - - public function getQueryCount() - { - return array_sum(array_map('count', $this->data['queries'])); - } - - public function getQueries() - { - return $this->data['queries']; - } - - public function getTime() - { - $time = 0; - foreach ($this->data['queries'] as $queries) { - foreach ($queries as $query) { - $time += $query['executionMS']; - } - } - - return $time; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'db'; - } - - /** - * {@inheritdoc} - */ - protected function getCasters() - { - return parent::getCasters() + [ - ObjectParameter::class => static function (ObjectParameter $o, array $a, Stub $s): array { - $s->class = $o->getClass(); - $s->value = $o->getObject(); - - $r = new \ReflectionClass($o->getClass()); - if ($f = $r->getFileName()) { - $s->attr['file'] = $f; - $s->attr['line'] = $r->getStartLine(); - } else { - unset($s->attr['file']); - unset($s->attr['line']); - } - - if ($error = $o->getError()) { - return [Caster::PREFIX_VIRTUAL.'⚠' => $error->getMessage()]; - } - - if ($o->isStringable()) { - return [Caster::PREFIX_VIRTUAL.'__toString()' => (string) $o->getObject()]; - } - - return [Caster::PREFIX_VIRTUAL.'⚠' => sprintf('Object of class "%s" could not be converted to string.', $o->getClass())]; - }, - ]; - } - - private function sanitizeQueries(string $connectionName, array $queries): array - { - foreach ($queries as $i => $query) { - $queries[$i] = $this->sanitizeQuery($connectionName, $query); - } - - return $queries; - } - - private function sanitizeQuery(string $connectionName, array $query): array - { - $query['explainable'] = true; - $query['runnable'] = true; - if (null === $query['params']) { - $query['params'] = []; - } - if (!\is_array($query['params'])) { - $query['params'] = [$query['params']]; - } - if (!\is_array($query['types'])) { - $query['types'] = []; - } - foreach ($query['params'] as $j => $param) { - $e = null; - if (isset($query['types'][$j])) { - // Transform the param according to the type - $type = $query['types'][$j]; - if (\is_string($type)) { - $type = Type::getType($type); - } - if ($type instanceof Type) { - $query['types'][$j] = $type->getBindingType(); - try { - $param = $type->convertToDatabaseValue($param, $this->registry->getConnection($connectionName)->getDatabasePlatform()); - } catch (\TypeError $e) { - } catch (ConversionException $e) { - } - } - } - - list($query['params'][$j], $explainable, $runnable) = $this->sanitizeParam($param, $e); - if (!$explainable) { - $query['explainable'] = false; - } - - if (!$runnable) { - $query['runnable'] = false; - } - } - - $query['params'] = $this->cloneVar($query['params']); - - return $query; - } - - /** - * Sanitizes a param. - * - * The return value is an array with the sanitized value and a boolean - * indicating if the original value was kept (allowing to use the sanitized - * value to explain the query). - */ - private function sanitizeParam($var, ?\Throwable $error): array - { - if (\is_object($var)) { - return [$o = new ObjectParameter($var, $error), false, $o->isStringable() && !$error]; - } - - if ($error) { - return ['⚠ '.$error->getMessage(), false, false]; - } - - if (\is_array($var)) { - $a = []; - $explainable = $runnable = true; - foreach ($var as $k => $v) { - list($value, $e, $r) = $this->sanitizeParam($v, null); - $explainable = $explainable && $e; - $runnable = $runnable && $r; - $a[$k] = $value; - } - - return [$a, $explainable, $runnable]; - } - - if (\is_resource($var)) { - return [sprintf('/* Resource(%s) */', get_resource_type($var)), false, false]; - } - - return [$var, true, true]; - } -} diff --git a/vendor/symfony/doctrine-bridge/DataCollector/ObjectParameter.php b/vendor/symfony/doctrine-bridge/DataCollector/ObjectParameter.php deleted file mode 100644 index 26bdb7f..0000000 --- a/vendor/symfony/doctrine-bridge/DataCollector/ObjectParameter.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\DataCollector; - -final class ObjectParameter -{ - private $object; - private $error; - private $stringable; - private $class; - - /** - * @param object $object - */ - public function __construct($object, ?\Throwable $error) - { - $this->object = $object; - $this->error = $error; - $this->stringable = \is_callable([$object, '__toString']); - $this->class = \get_class($object); - } - - /** - * @return object - */ - public function getObject() - { - return $this->object; - } - - public function getError(): ?\Throwable - { - return $this->error; - } - - public function isStringable(): bool - { - return $this->stringable; - } - - public function getClass(): string - { - return $this->class; - } -} diff --git a/vendor/symfony/doctrine-bridge/DataFixtures/ContainerAwareLoader.php b/vendor/symfony/doctrine-bridge/DataFixtures/ContainerAwareLoader.php deleted file mode 100644 index 7ccd1df..0000000 --- a/vendor/symfony/doctrine-bridge/DataFixtures/ContainerAwareLoader.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\DataFixtures; - -use Doctrine\Common\DataFixtures\FixtureInterface; -use Doctrine\Common\DataFixtures\Loader; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Doctrine data fixtures loader that injects the service container into - * fixture objects that implement ContainerAwareInterface. - * - * Note: Use of this class requires the Doctrine data fixtures extension, which - * is a suggested dependency for Symfony. - */ -class ContainerAwareLoader extends Loader -{ - private $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function addFixture(FixtureInterface $fixture) - { - if ($fixture instanceof ContainerAwareInterface) { - $fixture->setContainer($this->container); - } - - parent::addFixture($fixture); - } -} diff --git a/vendor/symfony/doctrine-bridge/DependencyInjection/AbstractDoctrineExtension.php b/vendor/symfony/doctrine-bridge/DependencyInjection/AbstractDoctrineExtension.php deleted file mode 100644 index 23230f7..0000000 --- a/vendor/symfony/doctrine-bridge/DependencyInjection/AbstractDoctrineExtension.php +++ /dev/null @@ -1,440 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\DependencyInjection; - -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\HttpKernel\DependencyInjection\Extension; - -/** - * This abstract classes groups common code that Doctrine Object Manager extensions (ORM, MongoDB, CouchDB) need. - * - * @author Benjamin Eberlei - */ -abstract class AbstractDoctrineExtension extends Extension -{ - /** - * Used inside metadata driver method to simplify aggregation of data. - */ - protected $aliasMap = []; - - /** - * Used inside metadata driver method to simplify aggregation of data. - */ - protected $drivers = []; - - /** - * @param array $objectManager A configured object manager - * - * @throws \InvalidArgumentException - */ - protected function loadMappingInformation(array $objectManager, ContainerBuilder $container) - { - if ($objectManager['auto_mapping']) { - // automatically register bundle mappings - foreach (array_keys($container->getParameter('kernel.bundles')) as $bundle) { - if (!isset($objectManager['mappings'][$bundle])) { - $objectManager['mappings'][$bundle] = [ - 'mapping' => true, - 'is_bundle' => true, - ]; - } - } - } - - foreach ($objectManager['mappings'] as $mappingName => $mappingConfig) { - if (null !== $mappingConfig && false === $mappingConfig['mapping']) { - continue; - } - - $mappingConfig = array_replace([ - 'dir' => false, - 'type' => false, - 'prefix' => false, - ], (array) $mappingConfig); - - $mappingConfig['dir'] = $container->getParameterBag()->resolveValue($mappingConfig['dir']); - // a bundle configuration is detected by realizing that the specified dir is not absolute and existing - if (!isset($mappingConfig['is_bundle'])) { - $mappingConfig['is_bundle'] = !is_dir($mappingConfig['dir']); - } - - if ($mappingConfig['is_bundle']) { - $bundle = null; - foreach ($container->getParameter('kernel.bundles') as $name => $class) { - if ($mappingName === $name) { - $bundle = new \ReflectionClass($class); - - break; - } - } - - if (null === $bundle) { - throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled.', $mappingName)); - } - - $mappingConfig = $this->getMappingDriverBundleConfigDefaults($mappingConfig, $bundle, $container); - if (!$mappingConfig) { - continue; - } - } - - $this->assertValidMappingConfiguration($mappingConfig, $objectManager['name']); - $this->setMappingDriverConfig($mappingConfig, $mappingName); - $this->setMappingDriverAlias($mappingConfig, $mappingName); - } - } - - /** - * Register the alias for this mapping driver. - * - * Aliases can be used in the Query languages of all the Doctrine object managers to simplify writing tasks. - */ - protected function setMappingDriverAlias(array $mappingConfig, string $mappingName) - { - if (isset($mappingConfig['alias'])) { - $this->aliasMap[$mappingConfig['alias']] = $mappingConfig['prefix']; - } else { - $this->aliasMap[$mappingName] = $mappingConfig['prefix']; - } - } - - /** - * Register the mapping driver configuration for later use with the object managers metadata driver chain. - * - * @throws \InvalidArgumentException - */ - protected function setMappingDriverConfig(array $mappingConfig, string $mappingName) - { - $mappingDirectory = $mappingConfig['dir']; - if (!is_dir($mappingDirectory)) { - throw new \InvalidArgumentException(sprintf('Invalid Doctrine mapping path given. Cannot load Doctrine mapping/bundle named "%s".', $mappingName)); - } - - $this->drivers[$mappingConfig['type']][$mappingConfig['prefix']] = realpath($mappingDirectory) ?: $mappingDirectory; - } - - /** - * If this is a bundle controlled mapping all the missing information can be autodetected by this method. - * - * Returns false when autodetection failed, an array of the completed information otherwise. - * - * @return array|false - */ - protected function getMappingDriverBundleConfigDefaults(array $bundleConfig, \ReflectionClass $bundle, ContainerBuilder $container) - { - $bundleDir = \dirname($bundle->getFileName()); - - if (!$bundleConfig['type']) { - $bundleConfig['type'] = $this->detectMetadataDriver($bundleDir, $container); - } - - if (!$bundleConfig['type']) { - // skip this bundle, no mapping information was found. - return false; - } - - if (!$bundleConfig['dir']) { - if (\in_array($bundleConfig['type'], ['annotation', 'staticphp'])) { - $bundleConfig['dir'] = $bundleDir.'/'.$this->getMappingObjectDefaultName(); - } else { - $bundleConfig['dir'] = $bundleDir.'/'.$this->getMappingResourceConfigDirectory(); - } - } else { - $bundleConfig['dir'] = $bundleDir.'/'.$bundleConfig['dir']; - } - - if (!$bundleConfig['prefix']) { - $bundleConfig['prefix'] = $bundle->getNamespaceName().'\\'.$this->getMappingObjectDefaultName(); - } - - return $bundleConfig; - } - - /** - * Register all the collected mapping information with the object manager by registering the appropriate mapping drivers. - */ - protected function registerMappingDrivers(array $objectManager, ContainerBuilder $container) - { - // configure metadata driver for each bundle based on the type of mapping files found - if ($container->hasDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver'))) { - $chainDriverDef = $container->getDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver')); - } else { - $chainDriverDef = new Definition($this->getMetadataDriverClass('driver_chain')); - $chainDriverDef->setPublic(false); - } - - foreach ($this->drivers as $driverType => $driverPaths) { - $mappingService = $this->getObjectManagerElementName($objectManager['name'].'_'.$driverType.'_metadata_driver'); - if ($container->hasDefinition($mappingService)) { - $mappingDriverDef = $container->getDefinition($mappingService); - $args = $mappingDriverDef->getArguments(); - if ('annotation' == $driverType) { - $args[1] = array_merge(array_values($driverPaths), $args[1]); - } else { - $args[0] = array_merge(array_values($driverPaths), $args[0]); - } - $mappingDriverDef->setArguments($args); - } elseif ('annotation' == $driverType) { - $mappingDriverDef = new Definition($this->getMetadataDriverClass($driverType), [ - new Reference($this->getObjectManagerElementName('metadata.annotation_reader')), - array_values($driverPaths), - ]); - } else { - $mappingDriverDef = new Definition($this->getMetadataDriverClass($driverType), [ - array_values($driverPaths), - ]); - } - $mappingDriverDef->setPublic(false); - if (false !== strpos($mappingDriverDef->getClass(), 'yml') || false !== strpos($mappingDriverDef->getClass(), 'xml')) { - $mappingDriverDef->setArguments([array_flip($driverPaths)]); - $mappingDriverDef->addMethodCall('setGlobalBasename', ['mapping']); - } - - $container->setDefinition($mappingService, $mappingDriverDef); - - foreach ($driverPaths as $prefix => $driverPath) { - $chainDriverDef->addMethodCall('addDriver', [new Reference($mappingService), $prefix]); - } - } - - $container->setDefinition($this->getObjectManagerElementName($objectManager['name'].'_metadata_driver'), $chainDriverDef); - } - - /** - * Assertion if the specified mapping information is valid. - * - * @throws \InvalidArgumentException - */ - protected function assertValidMappingConfiguration(array $mappingConfig, string $objectManagerName) - { - if (!$mappingConfig['type'] || !$mappingConfig['dir'] || !$mappingConfig['prefix']) { - throw new \InvalidArgumentException(sprintf('Mapping definitions for Doctrine manager "%s" require at least the "type", "dir" and "prefix" options.', $objectManagerName)); - } - - if (!is_dir($mappingConfig['dir'])) { - throw new \InvalidArgumentException(sprintf('Specified non-existing directory "%s" as Doctrine mapping source.', $mappingConfig['dir'])); - } - - if (!\in_array($mappingConfig['type'], ['xml', 'yml', 'annotation', 'php', 'staticphp'])) { - throw new \InvalidArgumentException(sprintf('Can only configure "xml", "yml", "annotation", "php" or "staticphp" through the DoctrineBundle. Use your own bundle to configure other metadata drivers. You can register them by adding a new driver to the "%s" service definition.', $this->getObjectManagerElementName($objectManagerName.'_metadata_driver'))); - } - } - - /** - * Detects what metadata driver to use for the supplied directory. - * - * @return string|null A metadata driver short name, if one can be detected - */ - protected function detectMetadataDriver(string $dir, ContainerBuilder $container) - { - $configPath = $this->getMappingResourceConfigDirectory(); - $extension = $this->getMappingResourceExtension(); - - if (glob($dir.'/'.$configPath.'/*.'.$extension.'.xml', GLOB_NOSORT)) { - $driver = 'xml'; - } elseif (glob($dir.'/'.$configPath.'/*.'.$extension.'.yml', GLOB_NOSORT)) { - $driver = 'yml'; - } elseif (glob($dir.'/'.$configPath.'/*.'.$extension.'.php', GLOB_NOSORT)) { - $driver = 'php'; - } else { - // add the closest existing directory as a resource - $resource = $dir.'/'.$configPath; - while (!is_dir($resource)) { - $resource = \dirname($resource); - } - $container->fileExists($resource, false); - - return $container->fileExists($dir.'/'.$this->getMappingObjectDefaultName(), false) ? 'annotation' : null; - } - $container->fileExists($dir.'/'.$configPath, false); - - return $driver; - } - - /** - * Loads a configured object manager metadata, query or result cache driver. - * - * @throws \InvalidArgumentException in case of unknown driver type - */ - protected function loadObjectManagerCacheDriver(array $objectManager, ContainerBuilder $container, string $cacheName) - { - $this->loadCacheDriver($cacheName, $objectManager['name'], $objectManager[$cacheName.'_driver'], $container); - } - - /** - * Loads a cache driver. - * - * @return string - * - * @throws \InvalidArgumentException - */ - protected function loadCacheDriver(string $cacheName, string $objectManagerName, array $cacheDriver, ContainerBuilder $container) - { - $cacheDriverServiceId = $this->getObjectManagerElementName($objectManagerName.'_'.$cacheName); - - switch ($cacheDriver['type']) { - case 'service': - $container->setAlias($cacheDriverServiceId, new Alias($cacheDriver['id'], false)); - - return $cacheDriverServiceId; - case 'memcached': - $memcachedClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.memcached.class').'%'; - $memcachedInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.memcached_instance.class').'%'; - $memcachedHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.memcached_host').'%'; - $memcachedPort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcached_port').'%'; - $cacheDef = new Definition($memcachedClass); - $memcachedInstance = new Definition($memcachedInstanceClass); - $memcachedInstance->setPrivate(true); - $memcachedInstance->addMethodCall('addServer', [ - $memcachedHost, $memcachedPort, - ]); - $container->setDefinition($this->getObjectManagerElementName(sprintf('%s_memcached_instance', $objectManagerName)), $memcachedInstance); - $cacheDef->addMethodCall('setMemcached', [new Reference($this->getObjectManagerElementName(sprintf('%s_memcached_instance', $objectManagerName)))]); - break; - case 'redis': - $redisClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.redis.class').'%'; - $redisInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.redis_instance.class').'%'; - $redisHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.redis_host').'%'; - $redisPort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.redis_port').'%'; - $cacheDef = new Definition($redisClass); - $redisInstance = new Definition($redisInstanceClass); - $redisInstance->setPrivate(true); - $redisInstance->addMethodCall('connect', [ - $redisHost, $redisPort, - ]); - $container->setDefinition($this->getObjectManagerElementName(sprintf('%s_redis_instance', $objectManagerName)), $redisInstance); - $cacheDef->addMethodCall('setRedis', [new Reference($this->getObjectManagerElementName(sprintf('%s_redis_instance', $objectManagerName)))]); - break; - case 'apc': - case 'apcu': - case 'array': - case 'xcache': - case 'wincache': - case 'zenddata': - $cacheDef = new Definition('%'.$this->getObjectManagerElementName(sprintf('cache.%s.class', $cacheDriver['type'])).'%'); - break; - default: - throw new \InvalidArgumentException(sprintf('"%s" is an unrecognized Doctrine cache driver.', $cacheDriver['type'])); - } - - $cacheDef->setPublic(false); - - if (!isset($cacheDriver['namespace'])) { - // generate a unique namespace for the given application - if ($container->hasParameter('cache.prefix.seed')) { - $seed = '.'.$container->getParameterBag()->resolveValue($container->getParameter('cache.prefix.seed')); - } else { - $seed = '_'.$container->getParameter('kernel.project_dir'); - } - $seed .= '.'.$container->getParameter('kernel.container_class'); - $namespace = 'sf_'.$this->getMappingResourceExtension().'_'.$objectManagerName.'_'.ContainerBuilder::hash($seed); - - $cacheDriver['namespace'] = $namespace; - } - - $cacheDef->addMethodCall('setNamespace', [$cacheDriver['namespace']]); - - $container->setDefinition($cacheDriverServiceId, $cacheDef); - - return $cacheDriverServiceId; - } - - /** - * Returns a modified version of $managerConfigs. - * - * The manager called $autoMappedManager will map all bundles that are not mapped by other managers. - * - * @return array The modified version of $managerConfigs - */ - protected function fixManagersAutoMappings(array $managerConfigs, array $bundles) - { - if ($autoMappedManager = $this->validateAutoMapping($managerConfigs)) { - foreach (array_keys($bundles) as $bundle) { - foreach ($managerConfigs as $manager) { - if (isset($manager['mappings'][$bundle])) { - continue 2; - } - } - $managerConfigs[$autoMappedManager]['mappings'][$bundle] = [ - 'mapping' => true, - 'is_bundle' => true, - ]; - } - $managerConfigs[$autoMappedManager]['auto_mapping'] = false; - } - - return $managerConfigs; - } - - /** - * Prefixes the relative dependency injection container path with the object manager prefix. - * - * @example $name is 'entity_manager' then the result would be 'doctrine.orm.entity_manager' - * - * @return string - */ - abstract protected function getObjectManagerElementName(string $name); - - /** - * Noun that describes the mapped objects such as Entity or Document. - * - * Will be used for autodetection of persistent objects directory. - * - * @return string - */ - abstract protected function getMappingObjectDefaultName(); - - /** - * Relative path from the bundle root to the directory where mapping files reside. - * - * @return string - */ - abstract protected function getMappingResourceConfigDirectory(); - - /** - * Extension used by the mapping files. - * - * @return string - */ - abstract protected function getMappingResourceExtension(); - - /** - * The class name used by the various mapping drivers. - */ - abstract protected function getMetadataDriverClass(string $driverType): string; - - /** - * Search for a manager that is declared as 'auto_mapping' = true. - * - * @throws \LogicException - */ - private function validateAutoMapping(array $managerConfigs): ?string - { - $autoMappedManager = null; - foreach ($managerConfigs as $name => $manager) { - if (!$manager['auto_mapping']) { - continue; - } - - if (null !== $autoMappedManager) { - throw new \LogicException(sprintf('You cannot enable "auto_mapping" on more than one manager at the same time (found in "%s" and %s").', $autoMappedManager, $name)); - } - - $autoMappedManager = $name; - } - - return $autoMappedManager; - } -} diff --git a/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/DoctrineValidationPass.php b/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/DoctrineValidationPass.php deleted file mode 100644 index 2577664..0000000 --- a/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/DoctrineValidationPass.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Registers additional validators. - * - * @author Benjamin Eberlei - */ -class DoctrineValidationPass implements CompilerPassInterface -{ - private $managerType; - - public function __construct(string $managerType) - { - $this->managerType = $managerType; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $this->updateValidatorMappingFiles($container, 'xml', 'xml'); - $this->updateValidatorMappingFiles($container, 'yaml', 'yml'); - } - - /** - * Gets the validation mapping files for the format and extends them with - * files matching a doctrine search pattern (Resources/config/validation.orm.xml). - */ - private function updateValidatorMappingFiles(ContainerBuilder $container, string $mapping, string $extension) - { - if (!$container->hasParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files')) { - return; - } - - $files = $container->getParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files'); - $validationPath = '/config/validation.'.$this->managerType.'.'.$extension; - - foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { - if ($container->fileExists($file = $bundle['path'].'/Resources'.$validationPath) || $container->fileExists($file = $bundle['path'].$validationPath)) { - $files[] = $file; - } - } - - $container->setParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files', $files); - } -} diff --git a/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php b/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php deleted file mode 100644 index e73de3d..0000000 --- a/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php +++ /dev/null @@ -1,149 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Registers event listeners and subscribers to the available doctrine connections. - * - * @author Jeremy Mikola - * @author Alexander - * @author David Maicher - */ -class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface -{ - private $connections; - private $eventManagers; - private $managerTemplate; - private $tagPrefix; - - /** - * @param string $connections Parameter ID for connections - * @param string $managerTemplate sprintf() template for generating the event - * manager's service ID for a connection name - * @param string $tagPrefix Tag prefix for listeners and subscribers - */ - public function __construct(string $connections, string $managerTemplate, string $tagPrefix) - { - $this->connections = $connections; - $this->managerTemplate = $managerTemplate; - $this->tagPrefix = $tagPrefix; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->hasParameter($this->connections)) { - return; - } - - $this->connections = $container->getParameter($this->connections); - $this->addTaggedSubscribers($container); - $this->addTaggedListeners($container); - } - - private function addTaggedSubscribers(ContainerBuilder $container) - { - $subscriberTag = $this->tagPrefix.'.event_subscriber'; - $taggedSubscribers = $this->findAndSortTags($subscriberTag, $container); - - foreach ($taggedSubscribers as $taggedSubscriber) { - list($id, $tag) = $taggedSubscriber; - $connections = isset($tag['connection']) ? [$tag['connection']] : array_keys($this->connections); - foreach ($connections as $con) { - if (!isset($this->connections[$con])) { - throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections)))); - } - - $this->getEventManagerDef($container, $con)->addMethodCall('addEventSubscriber', [new Reference($id)]); - } - } - } - - private function addTaggedListeners(ContainerBuilder $container) - { - $listenerTag = $this->tagPrefix.'.event_listener'; - $taggedListeners = $this->findAndSortTags($listenerTag, $container); - $listenerRefs = []; - - foreach ($taggedListeners as $taggedListener) { - list($id, $tag) = $taggedListener; - if (!isset($tag['event'])) { - throw new InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id)); - } - - $connections = isset($tag['connection']) ? [$tag['connection']] : array_keys($this->connections); - foreach ($connections as $con) { - if (!isset($this->connections[$con])) { - throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections)))); - } - $listenerRefs[$con][$id] = new Reference($id); - - // we add one call per event per service so we have the correct order - $this->getEventManagerDef($container, $con)->addMethodCall('addEventListener', [[$tag['event']], $id]); - } - } - - // replace service container argument of event managers with smaller service locator - // so services can even remain private - foreach ($listenerRefs as $connection => $refs) { - $this->getEventManagerDef($container, $connection) - ->replaceArgument(0, ServiceLocatorTagPass::register($container, $refs)); - } - } - - private function getEventManagerDef(ContainerBuilder $container, string $name) - { - if (!isset($this->eventManagers[$name])) { - $this->eventManagers[$name] = $container->getDefinition(sprintf($this->managerTemplate, $name)); - } - - return $this->eventManagers[$name]; - } - - /** - * Finds and orders all service tags with the given name by their priority. - * - * The order of additions must be respected for services having the same priority, - * and knowing that the \SplPriorityQueue class does not respect the FIFO method, - * we should not use this class. - * - * @see https://bugs.php.net/53710 - * @see https://bugs.php.net/60926 - */ - private function findAndSortTags(string $tagName, ContainerBuilder $container): array - { - $sortedTags = []; - - foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $tags) { - foreach ($tags as $attributes) { - $priority = isset($attributes['priority']) ? $attributes['priority'] : 0; - $sortedTags[$priority][] = [$serviceId, $attributes]; - } - } - - if ($sortedTags) { - krsort($sortedTags); - $sortedTags = array_merge(...$sortedTags); - } - - return $sortedTags; - } -} diff --git a/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterMappingsPass.php b/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterMappingsPass.php deleted file mode 100644 index 3c06fa2..0000000 --- a/vendor/symfony/doctrine-bridge/DependencyInjection/CompilerPass/RegisterMappingsPass.php +++ /dev/null @@ -1,237 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Base class for the doctrine bundles to provide a compiler pass class that - * helps to register doctrine mappings. - * - * The compiler pass is meant to register the mappings with the metadata - * chain driver corresponding to one of the object managers. - * - * For concrete implementations, see the RegisterXyMappingsPass classes - * in the DoctrineBundle resp. - * DoctrineMongodbBundle, DoctrineCouchdbBundle and DoctrinePhpcrBundle. - * - * @author David Buchmann - */ -abstract class RegisterMappingsPass implements CompilerPassInterface -{ - /** - * DI object for the driver to use, either a service definition for a - * private service or a reference for a public service. - * - * @var Definition|Reference - */ - protected $driver; - - /** - * List of namespaces handled by the driver. - * - * @var string[] - */ - protected $namespaces; - - /** - * List of potential container parameters that hold the object manager name - * to register the mappings with the correct metadata driver, for example - * ['acme.manager', 'doctrine.default_entity_manager']. - * - * @var string[] - */ - protected $managerParameters; - - /** - * Naming pattern of the metadata chain driver service ids, for example - * 'doctrine.orm.%s_metadata_driver'. - * - * @var string - */ - protected $driverPattern; - - /** - * A name for a parameter in the container. If set, this compiler pass will - * only do anything if the parameter is present. (But regardless of the - * value of that parameter. - * - * @var string|false - */ - protected $enabledParameter; - - /** - * Naming pattern for the configuration service id, for example - * 'doctrine.orm.%s_configuration'. - * - * @var string - */ - private $configurationPattern; - - /** - * Method name to call on the configuration service. This depends on the - * Doctrine implementation. For example addEntityNamespace. - * - * @var string - */ - private $registerAliasMethodName; - - /** - * Map of alias to namespace. - * - * @var string[] - */ - private $aliasMap; - - /** - * The $managerParameters is an ordered list of container parameters that could provide the - * name of the manager to register these namespaces and alias on. The first non-empty name - * is used, the others skipped. - * - * The $aliasMap parameter can be used to define bundle namespace shortcuts like the - * DoctrineBundle provides automatically for objects in the default Entity/Document folder. - * - * @param Definition|Reference $driver Driver DI definition or reference - * @param string[] $namespaces List of namespaces handled by $driver - * @param string[] $managerParameters list of container parameters that could - * hold the manager name - * @param string $driverPattern Pattern for the metadata driver service name - * @param string|false $enabledParameter Service container parameter that must be - * present to enable the mapping. Set to false - * to not do any check, optional. - * @param string $configurationPattern Pattern for the Configuration service name - * @param string $registerAliasMethodName Name of Configuration class method to - * register alias - * @param string[] $aliasMap Map of alias to namespace - */ - public function __construct($driver, array $namespaces, array $managerParameters, string $driverPattern, $enabledParameter = false, string $configurationPattern = '', string $registerAliasMethodName = '', array $aliasMap = []) - { - $this->driver = $driver; - $this->namespaces = $namespaces; - $this->managerParameters = $managerParameters; - $this->driverPattern = $driverPattern; - $this->enabledParameter = $enabledParameter; - if (\count($aliasMap) && (!$configurationPattern || !$registerAliasMethodName)) { - throw new \InvalidArgumentException('configurationPattern and registerAliasMethodName are required to register namespace alias'); - } - $this->configurationPattern = $configurationPattern; - $this->registerAliasMethodName = $registerAliasMethodName; - $this->aliasMap = $aliasMap; - } - - /** - * Register mappings and alias with the metadata drivers. - */ - public function process(ContainerBuilder $container) - { - if (!$this->enabled($container)) { - return; - } - - $mappingDriverDef = $this->getDriver($container); - $chainDriverDefService = $this->getChainDriverServiceName($container); - // Definition for a Doctrine\Persistence\Mapping\Driver\MappingDriverChain - $chainDriverDef = $container->getDefinition($chainDriverDefService); - foreach ($this->namespaces as $namespace) { - $chainDriverDef->addMethodCall('addDriver', [$mappingDriverDef, $namespace]); - } - - if (!\count($this->aliasMap)) { - return; - } - - $configurationServiceName = $this->getConfigurationServiceName($container); - // Definition of the Doctrine\...\Configuration class specific to the Doctrine flavour. - $configurationServiceDefinition = $container->getDefinition($configurationServiceName); - foreach ($this->aliasMap as $alias => $namespace) { - $configurationServiceDefinition->addMethodCall($this->registerAliasMethodName, [$alias, $namespace]); - } - } - - /** - * Get the service name of the metadata chain driver that the mappings - * should be registered with. - * - * @return string The name of the chain driver service - * - * @throws InvalidArgumentException if non of the managerParameters has a - * non-empty value - */ - protected function getChainDriverServiceName(ContainerBuilder $container) - { - return sprintf($this->driverPattern, $this->getManagerName($container)); - } - - /** - * Create the service definition for the metadata driver. - * - * @param ContainerBuilder $container Passed on in case an extending class - * needs access to the container - * - * @return Definition|Reference the metadata driver to add to all chain drivers - */ - protected function getDriver(ContainerBuilder $container) - { - return $this->driver; - } - - /** - * Get the service name from the pattern and the configured manager name. - * - * @throws InvalidArgumentException if none of the managerParameters has a - * non-empty value - */ - private function getConfigurationServiceName(ContainerBuilder $container): string - { - return sprintf($this->configurationPattern, $this->getManagerName($container)); - } - - /** - * Determine the manager name. - * - * The default implementation loops over the managerParameters and returns - * the first non-empty parameter. - * - * @throws InvalidArgumentException if none of the managerParameters is found in the container - */ - private function getManagerName(ContainerBuilder $container): string - { - foreach ($this->managerParameters as $param) { - if ($container->hasParameter($param)) { - $name = $container->getParameter($param); - if ($name) { - return $name; - } - } - } - - throw new InvalidArgumentException(sprintf('Could not find the manager name parameter in the container. Tried the following parameter names: "%s"', implode('", "', $this->managerParameters))); - } - - /** - * Determine whether this mapping should be activated or not. This allows - * to take this decision with the container builder available. - * - * This default implementation checks if the class has the enabledParameter - * configured and if so if that parameter is present in the container. - * - * @return bool whether this compiler pass really should register the mappings - */ - protected function enabled(ContainerBuilder $container) - { - return !$this->enabledParameter || $container->hasParameter($this->enabledParameter); - } -} diff --git a/vendor/symfony/doctrine-bridge/DependencyInjection/Security/UserProvider/EntityFactory.php b/vendor/symfony/doctrine-bridge/DependencyInjection/Security/UserProvider/EntityFactory.php deleted file mode 100644 index 454c7cc..0000000 --- a/vendor/symfony/doctrine-bridge/DependencyInjection/Security/UserProvider/EntityFactory.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\DependencyInjection\Security\UserProvider; - -use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface; -use Symfony\Component\Config\Definition\Builder\NodeDefinition; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * EntityFactory creates services for Doctrine user provider. - * - * @author Fabien Potencier - * @author Christophe Coevoet - */ -class EntityFactory implements UserProviderFactoryInterface -{ - private $key; - private $providerId; - - public function __construct(string $key, string $providerId) - { - $this->key = $key; - $this->providerId = $providerId; - } - - public function create(ContainerBuilder $container, string $id, array $config) - { - $container - ->setDefinition($id, new ChildDefinition($this->providerId)) - ->addArgument($config['class']) - ->addArgument($config['property']) - ->addArgument($config['manager_name']) - ; - } - - public function getKey() - { - return $this->key; - } - - public function addConfiguration(NodeDefinition $node) - { - $node - ->children() - ->scalarNode('class')->isRequired()->cannotBeEmpty()->end() - ->scalarNode('property')->defaultNull()->end() - ->scalarNode('manager_name')->defaultNull()->end() - ->end() - ; - } -} diff --git a/vendor/symfony/doctrine-bridge/Form/ChoiceList/DoctrineChoiceLoader.php b/vendor/symfony/doctrine-bridge/Form/ChoiceList/DoctrineChoiceLoader.php deleted file mode 100644 index cb09a3d..0000000 --- a/vendor/symfony/doctrine-bridge/Form/ChoiceList/DoctrineChoiceLoader.php +++ /dev/null @@ -1,150 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Form\ChoiceList; - -use Doctrine\Persistence\ObjectManager; -use Symfony\Component\Form\ChoiceList\ArrayChoiceList; -use Symfony\Component\Form\ChoiceList\ChoiceListInterface; -use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; - -/** - * Loads choices using a Doctrine object manager. - * - * @author Bernhard Schussek - */ -class DoctrineChoiceLoader implements ChoiceLoaderInterface -{ - private $manager; - private $class; - private $idReader; - private $objectLoader; - - /** - * @var ChoiceListInterface - */ - private $choiceList; - - /** - * Creates a new choice loader. - * - * Optionally, an implementation of {@link EntityLoaderInterface} can be - * passed which optimizes the object loading for one of the Doctrine - * mapper implementations. - * - * @param string $class The class name of the loaded objects - */ - public function __construct(ObjectManager $manager, string $class, IdReader $idReader = null, EntityLoaderInterface $objectLoader = null) - { - $classMetadata = $manager->getClassMetadata($class); - - if ($idReader && !$idReader->isSingleId()) { - throw new \InvalidArgumentException(sprintf('The second argument `$idReader` of "%s" must be null when the query cannot be optimized because of composite id fields.', __METHOD__)); - } - - $this->manager = $manager; - $this->class = $classMetadata->getName(); - $this->idReader = $idReader; - $this->objectLoader = $objectLoader; - } - - /** - * {@inheritdoc} - */ - public function loadChoiceList(callable $value = null) - { - if ($this->choiceList) { - return $this->choiceList; - } - - $objects = $this->objectLoader - ? $this->objectLoader->getEntities() - : $this->manager->getRepository($this->class)->findAll(); - - return $this->choiceList = new ArrayChoiceList($objects, $value); - } - - /** - * {@inheritdoc} - */ - public function loadValuesForChoices(array $choices, callable $value = null) - { - // Performance optimization - if (empty($choices)) { - return []; - } - - // Optimize performance for single-field identifiers. We already - // know that the IDs are used as values - $optimize = $this->idReader && (null === $value || \is_array($value) && $value[0] === $this->idReader); - - // Attention: This optimization does not check choices for existence - if ($optimize && !$this->choiceList) { - $values = []; - - // Maintain order and indices of the given objects - foreach ($choices as $i => $object) { - if ($object instanceof $this->class) { - // Make sure to convert to the right format - $values[$i] = (string) $this->idReader->getIdValue($object); - } - } - - return $values; - } - - return $this->loadChoiceList($value)->getValuesForChoices($choices); - } - - /** - * {@inheritdoc} - */ - public function loadChoicesForValues(array $values, callable $value = null) - { - // Performance optimization - // Also prevents the generation of "WHERE id IN ()" queries through the - // object loader. At least with MySQL and on the development machine - // this was tested on, no exception was thrown for such invalid - // statements, consequently no test fails when this code is removed. - // https://github.com/symfony/symfony/pull/8981#issuecomment-24230557 - if (empty($values)) { - return []; - } - - // Optimize performance in case we have an object loader and - // a single-field identifier - $optimize = $this->idReader && (null === $value || \is_array($value) && $this->idReader === $value[0]); - - if ($optimize && !$this->choiceList && $this->objectLoader) { - $unorderedObjects = $this->objectLoader->getEntitiesByIds($this->idReader->getIdField(), $values); - $objectsById = []; - $objects = []; - - // Maintain order and indices from the given $values - // An alternative approach to the following loop is to add the - // "INDEX BY" clause to the Doctrine query in the loader, - // but I'm not sure whether that's doable in a generic fashion. - foreach ($unorderedObjects as $object) { - $objectsById[(string) $this->idReader->getIdValue($object)] = $object; - } - - foreach ($values as $i => $id) { - if (isset($objectsById[$id])) { - $objects[$i] = $objectsById[$id]; - } - } - - return $objects; - } - - return $this->loadChoiceList($value)->getChoicesForValues($values); - } -} diff --git a/vendor/symfony/doctrine-bridge/Form/ChoiceList/EntityLoaderInterface.php b/vendor/symfony/doctrine-bridge/Form/ChoiceList/EntityLoaderInterface.php deleted file mode 100644 index 8eb5a84..0000000 --- a/vendor/symfony/doctrine-bridge/Form/ChoiceList/EntityLoaderInterface.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Form\ChoiceList; - -/** - * Custom loader for entities in the choice list. - * - * @author Benjamin Eberlei - */ -interface EntityLoaderInterface -{ - /** - * Returns an array of entities that are valid choices in the corresponding choice list. - * - * @return array The entities - */ - public function getEntities(); - - /** - * Returns an array of entities matching the given identifiers. - * - * @return array The entities - */ - public function getEntitiesByIds(string $identifier, array $values); -} diff --git a/vendor/symfony/doctrine-bridge/Form/ChoiceList/IdReader.php b/vendor/symfony/doctrine-bridge/Form/ChoiceList/IdReader.php deleted file mode 100644 index 195e7ce..0000000 --- a/vendor/symfony/doctrine-bridge/Form/ChoiceList/IdReader.php +++ /dev/null @@ -1,121 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Form\ChoiceList; - -use Doctrine\Persistence\Mapping\ClassMetadata; -use Doctrine\Persistence\ObjectManager; -use Symfony\Component\Form\Exception\RuntimeException; - -/** - * A utility for reading object IDs. - * - * @author Bernhard Schussek - * - * @internal - */ -class IdReader -{ - private $om; - private $classMetadata; - private $singleId; - private $intId; - private $idField; - - /** - * @var IdReader|null - */ - private $associationIdReader; - - public function __construct(ObjectManager $om, ClassMetadata $classMetadata) - { - $ids = $classMetadata->getIdentifierFieldNames(); - $idType = $classMetadata->getTypeOfField(current($ids)); - - $this->om = $om; - $this->classMetadata = $classMetadata; - $this->singleId = 1 === \count($ids); - $this->intId = $this->singleId && \in_array($idType, ['integer', 'smallint', 'bigint']); - $this->idField = current($ids); - - // single field association are resolved, since the schema column could be an int - if ($this->singleId && $classMetadata->hasAssociation($this->idField)) { - $this->associationIdReader = new self($om, $om->getClassMetadata( - $classMetadata->getAssociationTargetClass($this->idField) - )); - - $this->singleId = $this->associationIdReader->isSingleId(); - $this->intId = $this->associationIdReader->isIntId(); - } - } - - /** - * Returns whether the class has a single-column ID. - * - * @return bool returns `true` if the class has a single-column ID and - * `false` otherwise - */ - public function isSingleId(): bool - { - return $this->singleId; - } - - /** - * Returns whether the class has a single-column integer ID. - * - * @return bool returns `true` if the class has a single-column integer ID - * and `false` otherwise - */ - public function isIntId(): bool - { - return $this->intId; - } - - /** - * Returns the ID value for an object. - * - * This method assumes that the object has a single-column ID. - * - * @return mixed The ID value - */ - public function getIdValue(object $object = null) - { - if (!$object) { - return null; - } - - if (!$this->om->contains($object)) { - throw new RuntimeException(sprintf('Entity of type "%s" passed to the choice field must be managed. Maybe you forget to persist it in the entity manager?', \get_class($object))); - } - - $this->om->initializeObject($object); - - $idValue = current($this->classMetadata->getIdentifierValues($object)); - - if ($this->associationIdReader) { - $idValue = $this->associationIdReader->getIdValue($idValue); - } - - return $idValue; - } - - /** - * Returns the name of the ID field. - * - * This method assumes that the object has a single-column ID. - * - * @return string The name of the ID field - */ - public function getIdField(): string - { - return $this->idField; - } -} diff --git a/vendor/symfony/doctrine-bridge/Form/ChoiceList/ORMQueryBuilderLoader.php b/vendor/symfony/doctrine-bridge/Form/ChoiceList/ORMQueryBuilderLoader.php deleted file mode 100644 index e208c6b..0000000 --- a/vendor/symfony/doctrine-bridge/Form/ChoiceList/ORMQueryBuilderLoader.php +++ /dev/null @@ -1,104 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Form\ChoiceList; - -use Doctrine\DBAL\Connection; -use Doctrine\ORM\QueryBuilder; - -/** - * Loads entities using a {@link QueryBuilder} instance. - * - * @author Benjamin Eberlei - * @author Bernhard Schussek - */ -class ORMQueryBuilderLoader implements EntityLoaderInterface -{ - /** - * Contains the query builder that builds the query for fetching the - * entities. - * - * This property should only be accessed through queryBuilder. - * - * @var QueryBuilder - */ - private $queryBuilder; - - public function __construct(QueryBuilder $queryBuilder) - { - $this->queryBuilder = $queryBuilder; - } - - /** - * {@inheritdoc} - */ - public function getEntities() - { - return $this->queryBuilder->getQuery()->execute(); - } - - /** - * {@inheritdoc} - */ - public function getEntitiesByIds(string $identifier, array $values) - { - if (null !== $this->queryBuilder->getMaxResults() || null !== $this->queryBuilder->getFirstResult()) { - // an offset or a limit would apply on results including the where clause with submitted id values - // that could make invalid choices valid - $choices = []; - $metadata = $this->queryBuilder->getEntityManager()->getClassMetadata(current($this->queryBuilder->getRootEntities())); - - foreach ($this->getEntities() as $entity) { - if (\in_array(current($metadata->getIdentifierValues($entity)), $values, true)) { - $choices[] = $entity; - } - } - - return $choices; - } - - $qb = clone $this->queryBuilder; - $alias = current($qb->getRootAliases()); - $parameter = 'ORMQueryBuilderLoader_getEntitiesByIds_'.$identifier; - $parameter = str_replace('.', '_', $parameter); - $where = $qb->expr()->in($alias.'.'.$identifier, ':'.$parameter); - - // Guess type - $entity = current($qb->getRootEntities()); - $metadata = $qb->getEntityManager()->getClassMetadata($entity); - if (\in_array($metadata->getTypeOfField($identifier), ['integer', 'bigint', 'smallint'])) { - $parameterType = Connection::PARAM_INT_ARRAY; - - // Filter out non-integer values (e.g. ""). If we don't, some - // databases such as PostgreSQL fail. - $values = array_values(array_filter($values, function ($v) { - return (string) $v === (string) (int) $v || ctype_digit($v); - })); - } elseif (\in_array($metadata->getTypeOfField($identifier), ['uuid', 'guid'])) { - $parameterType = Connection::PARAM_STR_ARRAY; - - // Like above, but we just filter out empty strings. - $values = array_values(array_filter($values, function ($v) { - return '' !== (string) $v; - })); - } else { - $parameterType = Connection::PARAM_STR_ARRAY; - } - if (!$values) { - return []; - } - - return $qb->andWhere($where) - ->getQuery() - ->setParameter($parameter, $values, $parameterType) - ->getResult(); - } -} diff --git a/vendor/symfony/doctrine-bridge/Form/DataTransformer/CollectionToArrayTransformer.php b/vendor/symfony/doctrine-bridge/Form/DataTransformer/CollectionToArrayTransformer.php deleted file mode 100644 index 3202dae..0000000 --- a/vendor/symfony/doctrine-bridge/Form/DataTransformer/CollectionToArrayTransformer.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Form\DataTransformer; - -use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\Common\Collections\Collection; -use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\TransformationFailedException; - -/** - * @author Bernhard Schussek - */ -class CollectionToArrayTransformer implements DataTransformerInterface -{ - /** - * Transforms a collection into an array. - * - * @return mixed An array of entities - * - * @throws TransformationFailedException - */ - public function transform($collection) - { - if (null === $collection) { - return []; - } - - // For cases when the collection getter returns $collection->toArray() - // in order to prevent modifications of the returned collection - if (\is_array($collection)) { - return $collection; - } - - if (!$collection instanceof Collection) { - throw new TransformationFailedException('Expected a Doctrine\Common\Collections\Collection object.'); - } - - return $collection->toArray(); - } - - /** - * Transforms choice keys into entities. - * - * @param mixed $array An array of entities - * - * @return Collection A collection of entities - */ - public function reverseTransform($array) - { - if ('' === $array || null === $array) { - $array = []; - } else { - $array = (array) $array; - } - - return new ArrayCollection($array); - } -} diff --git a/vendor/symfony/doctrine-bridge/Form/DoctrineOrmExtension.php b/vendor/symfony/doctrine-bridge/Form/DoctrineOrmExtension.php deleted file mode 100644 index c2897c6..0000000 --- a/vendor/symfony/doctrine-bridge/Form/DoctrineOrmExtension.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Form; - -use Doctrine\Persistence\ManagerRegistry; -use Symfony\Bridge\Doctrine\Form\Type\EntityType; -use Symfony\Component\Form\AbstractExtension; - -class DoctrineOrmExtension extends AbstractExtension -{ - protected $registry; - - public function __construct(ManagerRegistry $registry) - { - $this->registry = $registry; - } - - protected function loadTypes() - { - return [ - new EntityType($this->registry), - ]; - } - - protected function loadTypeGuesser() - { - return new DoctrineOrmTypeGuesser($this->registry); - } -} diff --git a/vendor/symfony/doctrine-bridge/Form/DoctrineOrmTypeGuesser.php b/vendor/symfony/doctrine-bridge/Form/DoctrineOrmTypeGuesser.php deleted file mode 100644 index 4374ec3..0000000 --- a/vendor/symfony/doctrine-bridge/Form/DoctrineOrmTypeGuesser.php +++ /dev/null @@ -1,201 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Form; - -use Doctrine\DBAL\Types\Type; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\ORM\Mapping\MappingException as LegacyMappingException; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\Mapping\MappingException; -use Doctrine\Persistence\Proxy; -use Symfony\Component\Form\FormTypeGuesserInterface; -use Symfony\Component\Form\Guess\Guess; -use Symfony\Component\Form\Guess\TypeGuess; -use Symfony\Component\Form\Guess\ValueGuess; - -class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface -{ - protected $registry; - - private $cache = []; - - public function __construct(ManagerRegistry $registry) - { - $this->registry = $registry; - } - - /** - * {@inheritdoc} - */ - public function guessType(string $class, string $property) - { - if (!$ret = $this->getMetadata($class)) { - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE); - } - - list($metadata, $name) = $ret; - - if ($metadata->hasAssociation($property)) { - $multiple = $metadata->isCollectionValuedAssociation($property); - $mapping = $metadata->getAssociationMapping($property); - - return new TypeGuess('Symfony\Bridge\Doctrine\Form\Type\EntityType', ['em' => $name, 'class' => $mapping['targetEntity'], 'multiple' => $multiple], Guess::HIGH_CONFIDENCE); - } - - switch ($metadata->getTypeOfField($property)) { - case Type::TARRAY: - case Type::SIMPLE_ARRAY: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CollectionType', [], Guess::MEDIUM_CONFIDENCE); - case Type::BOOLEAN: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CheckboxType', [], Guess::HIGH_CONFIDENCE); - case Type::DATETIME: - case Type::DATETIMETZ: - case 'vardatetime': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateTimeType', [], Guess::HIGH_CONFIDENCE); - case 'datetime_immutable': - case 'datetimetz_immutable': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateTimeType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE); - case 'dateinterval': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateIntervalType', [], Guess::HIGH_CONFIDENCE); - case Type::DATE: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', [], Guess::HIGH_CONFIDENCE); - case 'date_immutable': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE); - case Type::TIME: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', [], Guess::HIGH_CONFIDENCE); - case 'time_immutable': - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', ['input' => 'datetime_immutable'], Guess::HIGH_CONFIDENCE); - case Type::DECIMAL: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', ['input' => 'string'], Guess::MEDIUM_CONFIDENCE); - case Type::FLOAT: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', [], Guess::MEDIUM_CONFIDENCE); - case Type::INTEGER: - case Type::BIGINT: - case Type::SMALLINT: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\IntegerType', [], Guess::MEDIUM_CONFIDENCE); - case Type::STRING: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::MEDIUM_CONFIDENCE); - case Type::TEXT: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextareaType', [], Guess::MEDIUM_CONFIDENCE); - default: - return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE); - } - } - - /** - * {@inheritdoc} - */ - public function guessRequired(string $class, string $property) - { - $classMetadatas = $this->getMetadata($class); - - if (!$classMetadatas) { - return null; - } - - /** @var ClassMetadataInfo $classMetadata */ - $classMetadata = $classMetadatas[0]; - - // Check whether the field exists and is nullable or not - if (isset($classMetadata->fieldMappings[$property])) { - if (!$classMetadata->isNullable($property) && Type::BOOLEAN !== $classMetadata->getTypeOfField($property)) { - return new ValueGuess(true, Guess::HIGH_CONFIDENCE); - } - - return new ValueGuess(false, Guess::MEDIUM_CONFIDENCE); - } - - // Check whether the association exists, is a to-one association and its - // join column is nullable or not - if ($classMetadata->isAssociationWithSingleJoinColumn($property)) { - $mapping = $classMetadata->getAssociationMapping($property); - - if (!isset($mapping['joinColumns'][0]['nullable'])) { - // The "nullable" option defaults to true, in that case the - // field should not be required. - return new ValueGuess(false, Guess::HIGH_CONFIDENCE); - } - - return new ValueGuess(!$mapping['joinColumns'][0]['nullable'], Guess::HIGH_CONFIDENCE); - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function guessMaxLength(string $class, string $property) - { - $ret = $this->getMetadata($class); - if ($ret && isset($ret[0]->fieldMappings[$property]) && !$ret[0]->hasAssociation($property)) { - $mapping = $ret[0]->getFieldMapping($property); - - if (isset($mapping['length'])) { - return new ValueGuess($mapping['length'], Guess::HIGH_CONFIDENCE); - } - - if (\in_array($ret[0]->getTypeOfField($property), [Type::DECIMAL, Type::FLOAT])) { - return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); - } - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function guessPattern(string $class, string $property) - { - $ret = $this->getMetadata($class); - if ($ret && isset($ret[0]->fieldMappings[$property]) && !$ret[0]->hasAssociation($property)) { - if (\in_array($ret[0]->getTypeOfField($property), [Type::DECIMAL, Type::FLOAT])) { - return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); - } - } - - return null; - } - - protected function getMetadata(string $class) - { - // normalize class name - $class = self::getRealClass(ltrim($class, '\\')); - - if (\array_key_exists($class, $this->cache)) { - return $this->cache[$class]; - } - - $this->cache[$class] = null; - foreach ($this->registry->getManagers() as $name => $em) { - try { - return $this->cache[$class] = [$em->getClassMetadata($class), $name]; - } catch (MappingException $e) { - // not an entity or mapped super class - } catch (LegacyMappingException $e) { - // not an entity or mapped super class, using Doctrine ORM 2.2 - } - } - - return null; - } - - private static function getRealClass(string $class): string - { - if (false === $pos = strrpos($class, '\\'.Proxy::MARKER.'\\')) { - return $class; - } - - return substr($class, $pos + Proxy::MARKER_LENGTH + 2); - } -} diff --git a/vendor/symfony/doctrine-bridge/Form/EventListener/MergeDoctrineCollectionListener.php b/vendor/symfony/doctrine-bridge/Form/EventListener/MergeDoctrineCollectionListener.php deleted file mode 100644 index 1ec496b..0000000 --- a/vendor/symfony/doctrine-bridge/Form/EventListener/MergeDoctrineCollectionListener.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Form\EventListener; - -use Doctrine\Common\Collections\Collection; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormEvents; - -/** - * Merge changes from the request to a Doctrine\Common\Collections\Collection instance. - * - * This works with ORM, MongoDB and CouchDB instances of the collection interface. - * - * @author Bernhard Schussek - * - * @see Collection - */ -class MergeDoctrineCollectionListener implements EventSubscriberInterface -{ - public static function getSubscribedEvents() - { - // Higher priority than core MergeCollectionListener so that this one - // is called before - return [ - FormEvents::SUBMIT => [ - ['onSubmit', 5], - ], - ]; - } - - public function onSubmit(FormEvent $event) - { - $collection = $event->getForm()->getData(); - $data = $event->getData(); - - // If all items were removed, call clear which has a higher - // performance on persistent collections - if ($collection instanceof Collection && 0 === \count($data)) { - $collection->clear(); - } - } -} diff --git a/vendor/symfony/doctrine-bridge/Form/Type/DoctrineType.php b/vendor/symfony/doctrine-bridge/Form/Type/DoctrineType.php deleted file mode 100644 index d7de810..0000000 --- a/vendor/symfony/doctrine-bridge/Form/Type/DoctrineType.php +++ /dev/null @@ -1,279 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Form\Type; - -use Doctrine\Common\Collections\Collection; -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\ObjectManager; -use Symfony\Bridge\Doctrine\Form\ChoiceList\DoctrineChoiceLoader; -use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityLoaderInterface; -use Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader; -use Symfony\Bridge\Doctrine\Form\DataTransformer\CollectionToArrayTransformer; -use Symfony\Bridge\Doctrine\Form\EventListener\MergeDoctrineCollectionListener; -use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator; -use Symfony\Component\Form\Exception\RuntimeException; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Contracts\Service\ResetInterface; - -abstract class DoctrineType extends AbstractType implements ResetInterface -{ - /** - * @var ManagerRegistry - */ - protected $registry; - - /** - * @var IdReader[] - */ - private $idReaders = []; - - /** - * @var DoctrineChoiceLoader[] - */ - private $choiceLoaders = []; - - /** - * Creates the label for a choice. - * - * For backwards compatibility, objects are cast to strings by default. - * - * @internal This method is public to be usable as callback. It should not - * be used in user code. - */ - public static function createChoiceLabel(object $choice): string - { - return (string) $choice; - } - - /** - * Creates the field name for a choice. - * - * This method is used to generate field names if the underlying object has - * a single-column integer ID. In that case, the value of the field is - * the ID of the object. That ID is also used as field name. - * - * @param int|string $key The choice key - * @param string $value The choice value. Corresponds to the object's - * ID here. - * - * @internal This method is public to be usable as callback. It should not - * be used in user code. - */ - public static function createChoiceName(object $choice, $key, string $value): string - { - return str_replace('-', '_', (string) $value); - } - - /** - * Gets important parts from QueryBuilder that will allow to cache its results. - * For instance in ORM two query builders with an equal SQL string and - * equal parameters are considered to be equal. - * - * @param object $queryBuilder A query builder, type declaration is not present here as there - * is no common base class for the different implementations - * - * @return array|null Array with important QueryBuilder parts or null if - * they can't be determined - * - * @internal This method is public to be usable as callback. It should not - * be used in user code. - */ - public function getQueryBuilderPartsForCachingHash($queryBuilder): ?array - { - return null; - } - - public function __construct(ManagerRegistry $registry) - { - $this->registry = $registry; - } - - public function buildForm(FormBuilderInterface $builder, array $options) - { - if ($options['multiple'] && interface_exists(Collection::class)) { - $builder - ->addEventSubscriber(new MergeDoctrineCollectionListener()) - ->addViewTransformer(new CollectionToArrayTransformer(), true) - ; - } - } - - public function configureOptions(OptionsResolver $resolver) - { - $choiceLoader = function (Options $options) { - // Unless the choices are given explicitly, load them on demand - if (null === $options['choices']) { - $hash = null; - $qbParts = null; - - // If there is no QueryBuilder we can safely cache DoctrineChoiceLoader, - // also if concrete Type can return important QueryBuilder parts to generate - // hash key we go for it as well - if (!$options['query_builder'] || null !== $qbParts = $this->getQueryBuilderPartsForCachingHash($options['query_builder'])) { - $hash = CachingFactoryDecorator::generateHash([ - $options['em'], - $options['class'], - $qbParts, - ]); - - if (isset($this->choiceLoaders[$hash])) { - return $this->choiceLoaders[$hash]; - } - } - - if (null !== $options['query_builder']) { - $entityLoader = $this->getLoader($options['em'], $options['query_builder'], $options['class']); - } else { - $queryBuilder = $options['em']->getRepository($options['class'])->createQueryBuilder('e'); - $entityLoader = $this->getLoader($options['em'], $queryBuilder, $options['class']); - } - - $doctrineChoiceLoader = new DoctrineChoiceLoader( - $options['em'], - $options['class'], - $options['id_reader'], - $entityLoader - ); - - if (null !== $hash) { - $this->choiceLoaders[$hash] = $doctrineChoiceLoader; - } - - return $doctrineChoiceLoader; - } - - return null; - }; - - $choiceName = function (Options $options) { - // If the object has a single-column, numeric ID, use that ID as - // field name. We can only use numeric IDs as names, as we cannot - // guarantee that a non-numeric ID contains a valid form name - if ($options['id_reader'] instanceof IdReader && $options['id_reader']->isIntId()) { - return [__CLASS__, 'createChoiceName']; - } - - // Otherwise, an incrementing integer is used as name automatically - return null; - }; - - // The choices are always indexed by ID (see "choices" normalizer - // and DoctrineChoiceLoader), unless the ID is composite. Then they - // are indexed by an incrementing integer. - // Use the ID/incrementing integer as choice value. - $choiceValue = function (Options $options) { - // If the entity has a single-column ID, use that ID as value - if ($options['id_reader'] instanceof IdReader && $options['id_reader']->isSingleId()) { - return [$options['id_reader'], 'getIdValue']; - } - - // Otherwise, an incrementing integer is used as value automatically - return null; - }; - - $emNormalizer = function (Options $options, $em) { - if (null !== $em) { - if ($em instanceof ObjectManager) { - return $em; - } - - return $this->registry->getManager($em); - } - - $em = $this->registry->getManagerForClass($options['class']); - - if (null === $em) { - throw new RuntimeException(sprintf('Class "%s" seems not to be a managed Doctrine entity. Did you forget to map it?', $options['class'])); - } - - return $em; - }; - - // Invoke the query builder closure so that we can cache choice lists - // for equal query builders - $queryBuilderNormalizer = function (Options $options, $queryBuilder) { - if (\is_callable($queryBuilder)) { - $queryBuilder = $queryBuilder($options['em']->getRepository($options['class'])); - } - - return $queryBuilder; - }; - - // Set the "id_reader" option via the normalizer. This option is not - // supposed to be set by the user. - $idReaderNormalizer = function (Options $options) { - $hash = CachingFactoryDecorator::generateHash([ - $options['em'], - $options['class'], - ]); - - // The ID reader is a utility that is needed to read the object IDs - // when generating the field values. The callback generating the - // field values has no access to the object manager or the class - // of the field, so we store that information in the reader. - // The reader is cached so that two choice lists for the same class - // (and hence with the same reader) can successfully be cached. - if (!isset($this->idReaders[$hash])) { - $classMetadata = $options['em']->getClassMetadata($options['class']); - $this->idReaders[$hash] = new IdReader($options['em'], $classMetadata); - } - - if ($this->idReaders[$hash]->isSingleId()) { - return $this->idReaders[$hash]; - } - - return null; - }; - - $resolver->setDefaults([ - 'em' => null, - 'query_builder' => null, - 'choices' => null, - 'choice_loader' => $choiceLoader, - 'choice_label' => [__CLASS__, 'createChoiceLabel'], - 'choice_name' => $choiceName, - 'choice_value' => $choiceValue, - 'id_reader' => null, // internal - 'choice_translation_domain' => false, - ]); - - $resolver->setRequired(['class']); - - $resolver->setNormalizer('em', $emNormalizer); - $resolver->setNormalizer('query_builder', $queryBuilderNormalizer); - $resolver->setNormalizer('id_reader', $idReaderNormalizer); - - $resolver->setAllowedTypes('em', ['null', 'string', ObjectManager::class]); - } - - /** - * Return the default loader object. - * - * @param mixed $queryBuilder - * - * @return EntityLoaderInterface - */ - abstract public function getLoader(ObjectManager $manager, $queryBuilder, string $class); - - public function getParent() - { - return 'Symfony\Component\Form\Extension\Core\Type\ChoiceType'; - } - - public function reset() - { - $this->choiceLoaders = []; - } -} diff --git a/vendor/symfony/doctrine-bridge/Form/Type/EntityType.php b/vendor/symfony/doctrine-bridge/Form/Type/EntityType.php deleted file mode 100644 index e4dafdd..0000000 --- a/vendor/symfony/doctrine-bridge/Form/Type/EntityType.php +++ /dev/null @@ -1,98 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Form\Type; - -use Doctrine\ORM\Query\Parameter; -use Doctrine\ORM\QueryBuilder; -use Doctrine\Persistence\ObjectManager; -use Symfony\Bridge\Doctrine\Form\ChoiceList\ORMQueryBuilderLoader; -use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\OptionsResolver\Options; -use Symfony\Component\OptionsResolver\OptionsResolver; - -class EntityType extends DoctrineType -{ - public function configureOptions(OptionsResolver $resolver) - { - parent::configureOptions($resolver); - - // Invoke the query builder closure so that we can cache choice lists - // for equal query builders - $queryBuilderNormalizer = function (Options $options, $queryBuilder) { - if (\is_callable($queryBuilder)) { - $queryBuilder = $queryBuilder($options['em']->getRepository($options['class'])); - - if (null !== $queryBuilder && !$queryBuilder instanceof QueryBuilder) { - throw new UnexpectedTypeException($queryBuilder, 'Doctrine\ORM\QueryBuilder'); - } - } - - return $queryBuilder; - }; - - $resolver->setNormalizer('query_builder', $queryBuilderNormalizer); - $resolver->setAllowedTypes('query_builder', ['null', 'callable', 'Doctrine\ORM\QueryBuilder']); - } - - /** - * Return the default loader object. - * - * @param QueryBuilder $queryBuilder - * - * @return ORMQueryBuilderLoader - */ - public function getLoader(ObjectManager $manager, $queryBuilder, string $class) - { - if (!$queryBuilder instanceof QueryBuilder) { - throw new \TypeError(sprintf('Expected an instance of %s, but got %s.', QueryBuilder::class, \is_object($queryBuilder) ? \get_class($queryBuilder) : \gettype($queryBuilder))); - } - - return new ORMQueryBuilderLoader($queryBuilder); - } - - /** - * {@inheritdoc} - */ - public function getBlockPrefix() - { - return 'entity'; - } - - /** - * We consider two query builders with an equal SQL string and - * equal parameters to be equal. - * - * @param QueryBuilder $queryBuilder - * - * @internal This method is public to be usable as callback. It should not - * be used in user code. - */ - public function getQueryBuilderPartsForCachingHash($queryBuilder): ?array - { - if (!$queryBuilder instanceof QueryBuilder) { - throw new \TypeError(sprintf('Expected an instance of %s, but got %s.', QueryBuilder::class, \is_object($queryBuilder) ? \get_class($queryBuilder) : \gettype($queryBuilder))); - } - - return [ - $queryBuilder->getQuery()->getSQL(), - array_map([$this, 'parameterToArray'], $queryBuilder->getParameters()->toArray()), - ]; - } - - /** - * Converts a query parameter to an array. - */ - private function parameterToArray(Parameter $parameter): array - { - return [$parameter->getName(), $parameter->getType(), $parameter->getValue()]; - } -} diff --git a/vendor/symfony/doctrine-bridge/LICENSE b/vendor/symfony/doctrine-bridge/LICENSE deleted file mode 100644 index a677f43..0000000 --- a/vendor/symfony/doctrine-bridge/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/doctrine-bridge/Logger/DbalLogger.php b/vendor/symfony/doctrine-bridge/Logger/DbalLogger.php deleted file mode 100644 index 6343792..0000000 --- a/vendor/symfony/doctrine-bridge/Logger/DbalLogger.php +++ /dev/null @@ -1,99 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Logger; - -use Doctrine\DBAL\Logging\SQLLogger; -use Psr\Log\LoggerInterface; -use Symfony\Component\Stopwatch\Stopwatch; - -/** - * @author Fabien Potencier - */ -class DbalLogger implements SQLLogger -{ - const MAX_STRING_LENGTH = 32; - const BINARY_DATA_VALUE = '(binary value)'; - - protected $logger; - protected $stopwatch; - - public function __construct(LoggerInterface $logger = null, Stopwatch $stopwatch = null) - { - $this->logger = $logger; - $this->stopwatch = $stopwatch; - } - - /** - * {@inheritdoc} - * - * @return void - */ - public function startQuery($sql, array $params = null, array $types = null) - { - if (null !== $this->stopwatch) { - $this->stopwatch->start('doctrine', 'doctrine'); - } - - if (null !== $this->logger) { - $this->log($sql, null === $params ? [] : $this->normalizeParams($params)); - } - } - - /** - * {@inheritdoc} - * - * @return void - */ - public function stopQuery() - { - if (null !== $this->stopwatch) { - $this->stopwatch->stop('doctrine'); - } - } - - /** - * Logs a message. - */ - protected function log(string $message, array $params) - { - $this->logger->debug($message, $params); - } - - private function normalizeParams(array $params): array - { - foreach ($params as $index => $param) { - // normalize recursively - if (\is_array($param)) { - $params[$index] = $this->normalizeParams($param); - continue; - } - - if (!\is_string($params[$index])) { - continue; - } - - // non utf-8 strings break json encoding - if (!preg_match('//u', $params[$index])) { - $params[$index] = self::BINARY_DATA_VALUE; - continue; - } - - // detect if the too long string must be shorten - if (self::MAX_STRING_LENGTH < mb_strlen($params[$index], 'UTF-8')) { - $params[$index] = mb_substr($params[$index], 0, self::MAX_STRING_LENGTH - 6, 'UTF-8').' [...]'; - continue; - } - } - - return $params; - } -} diff --git a/vendor/symfony/doctrine-bridge/ManagerRegistry.php b/vendor/symfony/doctrine-bridge/ManagerRegistry.php deleted file mode 100644 index ab76c4c..0000000 --- a/vendor/symfony/doctrine-bridge/ManagerRegistry.php +++ /dev/null @@ -1,74 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine; - -use Doctrine\Persistence\AbstractManagerRegistry; -use ProxyManager\Proxy\LazyLoadingInterface; -use Symfony\Component\DependencyInjection\Container; - -/** - * References Doctrine connections and entity/document managers. - * - * @author Lukas Kahwe Smith - */ -abstract class ManagerRegistry extends AbstractManagerRegistry -{ - /** - * @var Container - */ - protected $container; - - /** - * {@inheritdoc} - * - * @return object - */ - protected function getService($name) - { - return $this->container->get($name); - } - - /** - * {@inheritdoc} - * - * @return void - */ - protected function resetService($name) - { - if (!$this->container->initialized($name)) { - return; - } - $manager = $this->container->get($name); - - if (!$manager instanceof LazyLoadingInterface) { - throw new \LogicException('Resetting a non-lazy manager service is not supported. '.(interface_exists(LazyLoadingInterface::class) ? sprintf('Declare the "%s" service as lazy.', $name) : 'Try running "composer require symfony/proxy-manager-bridge".')); - } - $manager->setProxyInitializer(\Closure::bind( - function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { - if (isset($this->aliases[$name])) { - $name = $this->aliases[$name]; - } - if (isset($this->fileMap[$name])) { - $wrappedInstance = $this->load($this->fileMap[$name]); - } else { - $wrappedInstance = $this->{$this->methodMap[$name]}(false); - } - - $manager->setProxyInitializer(null); - - return true; - }, - $this->container, - Container::class - )); - } -} diff --git a/vendor/symfony/doctrine-bridge/Messenger/AbstractDoctrineMiddleware.php b/vendor/symfony/doctrine-bridge/Messenger/AbstractDoctrineMiddleware.php deleted file mode 100644 index 9fbf2de..0000000 --- a/vendor/symfony/doctrine-bridge/Messenger/AbstractDoctrineMiddleware.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Messenger; - -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\Persistence\ManagerRegistry; -use Symfony\Component\Messenger\Envelope; -use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException; -use Symfony\Component\Messenger\Middleware\MiddlewareInterface; -use Symfony\Component\Messenger\Middleware\StackInterface; - -/** - * @author Konstantin Myakshin - * - * @internal - */ -abstract class AbstractDoctrineMiddleware implements MiddlewareInterface -{ - protected $managerRegistry; - protected $entityManagerName; - - public function __construct(ManagerRegistry $managerRegistry, string $entityManagerName = null) - { - $this->managerRegistry = $managerRegistry; - $this->entityManagerName = $entityManagerName; - } - - final public function handle(Envelope $envelope, StackInterface $stack): Envelope - { - try { - $entityManager = $this->managerRegistry->getManager($this->entityManagerName); - } catch (\InvalidArgumentException $e) { - throw new UnrecoverableMessageHandlingException($e->getMessage(), 0, $e); - } - - return $this->handleForManager($entityManager, $envelope, $stack); - } - - abstract protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope; -} diff --git a/vendor/symfony/doctrine-bridge/Messenger/DoctrineClearEntityManagerWorkerSubscriber.php b/vendor/symfony/doctrine-bridge/Messenger/DoctrineClearEntityManagerWorkerSubscriber.php deleted file mode 100644 index d702186..0000000 --- a/vendor/symfony/doctrine-bridge/Messenger/DoctrineClearEntityManagerWorkerSubscriber.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Messenger; - -use Doctrine\Persistence\ManagerRegistry; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent; -use Symfony\Component\Messenger\Event\WorkerMessageHandledEvent; - -/** - * Clears entity managers between messages being handled to avoid outdated data. - * - * @author Ryan Weaver - */ -class DoctrineClearEntityManagerWorkerSubscriber implements EventSubscriberInterface -{ - private $managerRegistry; - - public function __construct(ManagerRegistry $managerRegistry) - { - $this->managerRegistry = $managerRegistry; - } - - public function onWorkerMessageHandled() - { - $this->clearEntityManagers(); - } - - public function onWorkerMessageFailed() - { - $this->clearEntityManagers(); - } - - public static function getSubscribedEvents() - { - yield WorkerMessageHandledEvent::class => 'onWorkerMessageHandled'; - yield WorkerMessageFailedEvent::class => 'onWorkerMessageFailed'; - } - - private function clearEntityManagers() - { - foreach ($this->managerRegistry->getManagers() as $manager) { - $manager->clear(); - } - } -} diff --git a/vendor/symfony/doctrine-bridge/Messenger/DoctrineCloseConnectionMiddleware.php b/vendor/symfony/doctrine-bridge/Messenger/DoctrineCloseConnectionMiddleware.php deleted file mode 100644 index b0a96e0..0000000 --- a/vendor/symfony/doctrine-bridge/Messenger/DoctrineCloseConnectionMiddleware.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Messenger; - -use Doctrine\ORM\EntityManagerInterface; -use Symfony\Component\Messenger\Envelope; -use Symfony\Component\Messenger\Middleware\StackInterface; -use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp; - -/** - * Closes connection and therefore saves number of connections. - * - * @author Fuong - */ -class DoctrineCloseConnectionMiddleware extends AbstractDoctrineMiddleware -{ - protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope - { - try { - $connection = $entityManager->getConnection(); - - return $stack->next()->handle($envelope, $stack); - } finally { - if (null !== $envelope->last(ConsumedByWorkerStamp::class)) { - $connection->close(); - } - } - } -} diff --git a/vendor/symfony/doctrine-bridge/Messenger/DoctrinePingConnectionMiddleware.php b/vendor/symfony/doctrine-bridge/Messenger/DoctrinePingConnectionMiddleware.php deleted file mode 100644 index f6febb2..0000000 --- a/vendor/symfony/doctrine-bridge/Messenger/DoctrinePingConnectionMiddleware.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Messenger; - -use Doctrine\ORM\EntityManagerInterface; -use Symfony\Component\Messenger\Envelope; -use Symfony\Component\Messenger\Middleware\StackInterface; -use Symfony\Component\Messenger\Stamp\ConsumedByWorkerStamp; - -/** - * Checks whether the connection is still open or reconnects otherwise. - * - * @author Fuong - */ -class DoctrinePingConnectionMiddleware extends AbstractDoctrineMiddleware -{ - protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope - { - if (null !== $envelope->last(ConsumedByWorkerStamp::class)) { - $this->pingConnection($entityManager); - } - - return $stack->next()->handle($envelope, $stack); - } - - private function pingConnection(EntityManagerInterface $entityManager) - { - $connection = $entityManager->getConnection(); - - if (!$connection->ping()) { - $connection->close(); - $connection->connect(); - } - - if (!$entityManager->isOpen()) { - $this->managerRegistry->resetManager($this->entityManagerName); - } - } -} diff --git a/vendor/symfony/doctrine-bridge/Messenger/DoctrineTransactionMiddleware.php b/vendor/symfony/doctrine-bridge/Messenger/DoctrineTransactionMiddleware.php deleted file mode 100644 index 4eb7afc..0000000 --- a/vendor/symfony/doctrine-bridge/Messenger/DoctrineTransactionMiddleware.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Messenger; - -use Doctrine\ORM\EntityManagerInterface; -use Symfony\Component\Messenger\Envelope; -use Symfony\Component\Messenger\Exception\HandlerFailedException; -use Symfony\Component\Messenger\Middleware\StackInterface; -use Symfony\Component\Messenger\Stamp\HandledStamp; - -/** - * Wraps all handlers in a single doctrine transaction. - * - * @author Tobias Nyholm - */ -class DoctrineTransactionMiddleware extends AbstractDoctrineMiddleware -{ - protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope - { - $entityManager->getConnection()->beginTransaction(); - try { - $envelope = $stack->next()->handle($envelope, $stack); - $entityManager->flush(); - $entityManager->getConnection()->commit(); - - return $envelope; - } catch (\Throwable $exception) { - $entityManager->getConnection()->rollBack(); - - if ($exception instanceof HandlerFailedException) { - // Remove all HandledStamp from the envelope so the retry will execute all handlers again. - // When a handler fails, the queries of allegedly successful previous handlers just got rolled back. - throw new HandlerFailedException($exception->getEnvelope()->withoutAll(HandledStamp::class), $exception->getNestedExceptions()); - } - - throw $exception; - } - } -} diff --git a/vendor/symfony/doctrine-bridge/PropertyInfo/DoctrineExtractor.php b/vendor/symfony/doctrine-bridge/PropertyInfo/DoctrineExtractor.php deleted file mode 100644 index bc81982..0000000 --- a/vendor/symfony/doctrine-bridge/PropertyInfo/DoctrineExtractor.php +++ /dev/null @@ -1,255 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\PropertyInfo; - -use Doctrine\DBAL\Types\Type as DBALType; -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\ORM\Mapping\MappingException as OrmMappingException; -use Doctrine\Persistence\Mapping\MappingException; -use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; -use Symfony\Component\PropertyInfo\Type; - -/** - * Extracts data using Doctrine ORM and ODM metadata. - * - * @author Kévin Dunglas - */ -class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeExtractorInterface, PropertyAccessExtractorInterface -{ - private $entityManager; - private $classMetadataFactory; - - public function __construct(EntityManagerInterface $entityManager) - { - $this->entityManager = $entityManager; - } - - /** - * {@inheritdoc} - */ - public function getProperties(string $class, array $context = []) - { - if (null === $metadata = $this->getMetadata($class)) { - return null; - } - - $properties = array_merge($metadata->getFieldNames(), $metadata->getAssociationNames()); - - if ($metadata instanceof ClassMetadataInfo && class_exists('Doctrine\ORM\Mapping\Embedded') && $metadata->embeddedClasses) { - $properties = array_filter($properties, function ($property) { - return false === strpos($property, '.'); - }); - - $properties = array_merge($properties, array_keys($metadata->embeddedClasses)); - } - - return $properties; - } - - /** - * {@inheritdoc} - */ - public function getTypes(string $class, string $property, array $context = []) - { - if (null === $metadata = $this->getMetadata($class)) { - return null; - } - - if ($metadata->hasAssociation($property)) { - $class = $metadata->getAssociationTargetClass($property); - - if ($metadata->isSingleValuedAssociation($property)) { - if ($metadata instanceof ClassMetadataInfo) { - $associationMapping = $metadata->getAssociationMapping($property); - - $nullable = $this->isAssociationNullable($associationMapping); - } else { - $nullable = false; - } - - return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $class)]; - } - - $collectionKeyType = Type::BUILTIN_TYPE_INT; - - if ($metadata instanceof ClassMetadataInfo) { - $associationMapping = $metadata->getAssociationMapping($property); - - if (isset($associationMapping['indexBy'])) { - $indexProperty = $associationMapping['indexBy']; - /** @var ClassMetadataInfo $subMetadata */ - $subMetadata = $this->entityManager ? $this->entityManager->getClassMetadata($associationMapping['targetEntity']) : $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']); - $typeOfField = $subMetadata->getTypeOfField($indexProperty); - - if (null === $typeOfField) { - $associationMapping = $subMetadata->getAssociationMapping($indexProperty); - - /** @var ClassMetadataInfo $subMetadata */ - $indexProperty = $subMetadata->getSingleAssociationReferencedJoinColumnName($indexProperty); - $subMetadata = $this->entityManager ? $this->entityManager->getClassMetadata($associationMapping['targetEntity']) : $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']); - $typeOfField = $subMetadata->getTypeOfField($indexProperty); - } - - $collectionKeyType = $this->getPhpType($typeOfField); - } - } - - return [new Type( - Type::BUILTIN_TYPE_OBJECT, - false, - 'Doctrine\Common\Collections\Collection', - true, - new Type($collectionKeyType), - new Type(Type::BUILTIN_TYPE_OBJECT, false, $class) - )]; - } - - if ($metadata instanceof ClassMetadataInfo && class_exists('Doctrine\ORM\Mapping\Embedded') && isset($metadata->embeddedClasses[$property])) { - return [new Type(Type::BUILTIN_TYPE_OBJECT, false, $metadata->embeddedClasses[$property]['class'])]; - } - - if ($metadata->hasField($property)) { - $typeOfField = $metadata->getTypeOfField($property); - $nullable = $metadata instanceof ClassMetadataInfo && $metadata->isNullable($property); - - switch ($typeOfField) { - case DBALType::DATE: - case DBALType::DATETIME: - case DBALType::DATETIMETZ: - case 'vardatetime': - case DBALType::TIME: - return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTime')]; - - case 'date_immutable': - case 'datetime_immutable': - case 'datetimetz_immutable': - case 'time_immutable': - return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTimeImmutable')]; - - case 'dateinterval': - return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateInterval')]; - - case DBALType::TARRAY: - return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)]; - - case DBALType::SIMPLE_ARRAY: - return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]; - - case DBALType::JSON_ARRAY: - return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)]; - - default: - $builtinType = $this->getPhpType($typeOfField); - - return $builtinType ? [new Type($builtinType, $nullable)] : null; - } - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function isReadable(string $class, string $property, array $context = []) - { - return null; - } - - /** - * {@inheritdoc} - */ - public function isWritable(string $class, string $property, array $context = []) - { - if ( - null === ($metadata = $this->getMetadata($class)) - || ClassMetadata::GENERATOR_TYPE_NONE === $metadata->generatorType - || !\in_array($property, $metadata->getIdentifierFieldNames(), true) - ) { - return null; - } - - return false; - } - - private function getMetadata(string $class): ?ClassMetadata - { - try { - return $this->entityManager ? $this->entityManager->getClassMetadata($class) : $this->classMetadataFactory->getMetadataFor($class); - } catch (MappingException | OrmMappingException $exception) { - return null; - } - } - - /** - * Determines whether an association is nullable. - * - * @see https://github.com/doctrine/doctrine2/blob/v2.5.4/lib/Doctrine/ORM/Tools/EntityGenerator.php#L1221-L1246 - */ - private function isAssociationNullable(array $associationMapping): bool - { - if (isset($associationMapping['id']) && $associationMapping['id']) { - return false; - } - - if (!isset($associationMapping['joinColumns'])) { - return true; - } - - $joinColumns = $associationMapping['joinColumns']; - foreach ($joinColumns as $joinColumn) { - if (isset($joinColumn['nullable']) && !$joinColumn['nullable']) { - return false; - } - } - - return true; - } - - /** - * Gets the corresponding built-in PHP type. - */ - private function getPhpType(string $doctrineType): ?string - { - switch ($doctrineType) { - case DBALType::SMALLINT: - case DBALType::INTEGER: - return Type::BUILTIN_TYPE_INT; - - case DBALType::FLOAT: - return Type::BUILTIN_TYPE_FLOAT; - - case DBALType::BIGINT: - case DBALType::STRING: - case DBALType::TEXT: - case DBALType::GUID: - case DBALType::DECIMAL: - return Type::BUILTIN_TYPE_STRING; - - case DBALType::BOOLEAN: - return Type::BUILTIN_TYPE_BOOL; - - case DBALType::BLOB: - case 'binary': - return Type::BUILTIN_TYPE_RESOURCE; - - case DBALType::OBJECT: - return Type::BUILTIN_TYPE_OBJECT; - } - - return null; - } -} diff --git a/vendor/symfony/doctrine-bridge/README.md b/vendor/symfony/doctrine-bridge/README.md deleted file mode 100644 index 46d897d..0000000 --- a/vendor/symfony/doctrine-bridge/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Doctrine Bridge -=============== - -Provides integration for [Doctrine](http://www.doctrine-project.org/) with -various Symfony components. - -Resources ---------- - - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/doctrine-bridge/Security/RememberMe/DoctrineTokenProvider.php b/vendor/symfony/doctrine-bridge/Security/RememberMe/DoctrineTokenProvider.php deleted file mode 100644 index 7a6c832..0000000 --- a/vendor/symfony/doctrine-bridge/Security/RememberMe/DoctrineTokenProvider.php +++ /dev/null @@ -1,126 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Security\RememberMe; - -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Types\Type as DoctrineType; -use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken; -use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentTokenInterface; -use Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface; -use Symfony\Component\Security\Core\Exception\TokenNotFoundException; - -/** - * This class provides storage for the tokens that is set in "remember me" - * cookies. This way no password secrets will be stored in the cookies on - * the client machine, and thus the security is improved. - * - * This depends only on doctrine in order to get a database connection - * and to do the conversion of the datetime column. - * - * In order to use this class, you need the following table in your database: - * - * CREATE TABLE `rememberme_token` ( - * `series` char(88) UNIQUE PRIMARY KEY NOT NULL, - * `value` char(88) NOT NULL, - * `lastUsed` datetime NOT NULL, - * `class` varchar(100) NOT NULL, - * `username` varchar(200) NOT NULL - * ); - */ -class DoctrineTokenProvider implements TokenProviderInterface -{ - private $conn; - - public function __construct(Connection $conn) - { - $this->conn = $conn; - } - - /** - * {@inheritdoc} - */ - public function loadTokenBySeries(string $series) - { - // the alias for lastUsed works around case insensitivity in PostgreSQL - $sql = 'SELECT class, username, value, lastUsed AS last_used' - .' FROM rememberme_token WHERE series=:series'; - $paramValues = ['series' => $series]; - $paramTypes = ['series' => \PDO::PARAM_STR]; - $stmt = $this->conn->executeQuery($sql, $paramValues, $paramTypes); - $row = $stmt->fetch(\PDO::FETCH_ASSOC); - - if ($row) { - return new PersistentToken($row['class'], $row['username'], $series, $row['value'], new \DateTime($row['last_used'])); - } - - throw new TokenNotFoundException('No token found.'); - } - - /** - * {@inheritdoc} - */ - public function deleteTokenBySeries(string $series) - { - $sql = 'DELETE FROM rememberme_token WHERE series=:series'; - $paramValues = ['series' => $series]; - $paramTypes = ['series' => \PDO::PARAM_STR]; - $this->conn->executeUpdate($sql, $paramValues, $paramTypes); - } - - /** - * {@inheritdoc} - */ - public function updateToken(string $series, string $tokenValue, \DateTime $lastUsed) - { - $sql = 'UPDATE rememberme_token SET value=:value, lastUsed=:lastUsed' - .' WHERE series=:series'; - $paramValues = [ - 'value' => $tokenValue, - 'lastUsed' => $lastUsed, - 'series' => $series, - ]; - $paramTypes = [ - 'value' => \PDO::PARAM_STR, - 'lastUsed' => DoctrineType::DATETIME, - 'series' => \PDO::PARAM_STR, - ]; - $updated = $this->conn->executeUpdate($sql, $paramValues, $paramTypes); - if ($updated < 1) { - throw new TokenNotFoundException('No token found.'); - } - } - - /** - * {@inheritdoc} - */ - public function createNewToken(PersistentTokenInterface $token) - { - $sql = 'INSERT INTO rememberme_token' - .' (class, username, series, value, lastUsed)' - .' VALUES (:class, :username, :series, :value, :lastUsed)'; - $paramValues = [ - 'class' => $token->getClass(), - 'username' => $token->getUsername(), - 'series' => $token->getSeries(), - 'value' => $token->getTokenValue(), - 'lastUsed' => $token->getLastUsed(), - ]; - $paramTypes = [ - 'class' => \PDO::PARAM_STR, - 'username' => \PDO::PARAM_STR, - 'series' => \PDO::PARAM_STR, - 'value' => \PDO::PARAM_STR, - 'lastUsed' => DoctrineType::DATETIME, - ]; - $this->conn->executeUpdate($sql, $paramValues, $paramTypes); - } -} diff --git a/vendor/symfony/doctrine-bridge/Security/User/EntityUserProvider.php b/vendor/symfony/doctrine-bridge/Security/User/EntityUserProvider.php deleted file mode 100644 index 01b2d64..0000000 --- a/vendor/symfony/doctrine-bridge/Security/User/EntityUserProvider.php +++ /dev/null @@ -1,155 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Security\User; - -use Doctrine\Persistence\ManagerRegistry; -use Doctrine\Persistence\Mapping\ClassMetadata; -use Doctrine\Persistence\ObjectManager; -use Doctrine\Persistence\ObjectRepository; -use Symfony\Component\Security\Core\Exception\UnsupportedUserException; -use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; -use Symfony\Component\Security\Core\User\PasswordUpgraderInterface; -use Symfony\Component\Security\Core\User\UserInterface; -use Symfony\Component\Security\Core\User\UserProviderInterface; - -/** - * Wrapper around a Doctrine ObjectManager. - * - * Provides provisioning for Doctrine entity users. - * - * @author Fabien Potencier - * @author Johannes M. Schmitt - */ -class EntityUserProvider implements UserProviderInterface, PasswordUpgraderInterface -{ - private $registry; - private $managerName; - private $classOrAlias; - private $class; - private $property; - - public function __construct(ManagerRegistry $registry, string $classOrAlias, string $property = null, string $managerName = null) - { - $this->registry = $registry; - $this->managerName = $managerName; - $this->classOrAlias = $classOrAlias; - $this->property = $property; - } - - /** - * {@inheritdoc} - */ - public function loadUserByUsername(string $username) - { - $repository = $this->getRepository(); - if (null !== $this->property) { - $user = $repository->findOneBy([$this->property => $username]); - } else { - if (!$repository instanceof UserLoaderInterface) { - throw new \InvalidArgumentException(sprintf('You must either make the "%s" entity Doctrine Repository ("%s") implement "Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface" or set the "property" option in the corresponding entity provider configuration.', $this->classOrAlias, \get_class($repository))); - } - - $user = $repository->loadUserByUsername($username); - } - - if (null === $user) { - throw new UsernameNotFoundException(sprintf('User "%s" not found.', $username)); - } - - return $user; - } - - /** - * {@inheritdoc} - */ - public function refreshUser(UserInterface $user) - { - $class = $this->getClass(); - if (!$user instanceof $class) { - throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', \get_class($user))); - } - - $repository = $this->getRepository(); - if ($repository instanceof UserProviderInterface) { - $refreshedUser = $repository->refreshUser($user); - } else { - // The user must be reloaded via the primary key as all other data - // might have changed without proper persistence in the database. - // That's the case when the user has been changed by a form with - // validation errors. - if (!$id = $this->getClassMetadata()->getIdentifierValues($user)) { - throw new \InvalidArgumentException('You cannot refresh a user from the EntityUserProvider that does not contain an identifier. The user object has to be serialized with its own identifier mapped by Doctrine.'); - } - - $refreshedUser = $repository->find($id); - if (null === $refreshedUser) { - throw new UsernameNotFoundException(sprintf('User with id %s not found', json_encode($id))); - } - } - - return $refreshedUser; - } - - /** - * {@inheritdoc} - */ - public function supportsClass(string $class) - { - return $class === $this->getClass() || is_subclass_of($class, $this->getClass()); - } - - /** - * {@inheritdoc} - */ - public function upgradePassword(UserInterface $user, string $newEncodedPassword): void - { - $class = $this->getClass(); - if (!$user instanceof $class) { - throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', \get_class($user))); - } - - $repository = $this->getRepository(); - if ($repository instanceof PasswordUpgraderInterface) { - $repository->upgradePassword($user, $newEncodedPassword); - } - } - - private function getObjectManager(): ObjectManager - { - return $this->registry->getManager($this->managerName); - } - - private function getRepository(): ObjectRepository - { - return $this->getObjectManager()->getRepository($this->classOrAlias); - } - - private function getClass(): string - { - if (null === $this->class) { - $class = $this->classOrAlias; - - if (false !== strpos($class, ':')) { - $class = $this->getClassMetadata()->getName(); - } - - $this->class = $class; - } - - return $this->class; - } - - private function getClassMetadata(): ClassMetadata - { - return $this->getObjectManager()->getClassMetadata($this->classOrAlias); - } -} diff --git a/vendor/symfony/doctrine-bridge/Security/User/UserLoaderInterface.php b/vendor/symfony/doctrine-bridge/Security/User/UserLoaderInterface.php deleted file mode 100644 index d996f71..0000000 --- a/vendor/symfony/doctrine-bridge/Security/User/UserLoaderInterface.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Security\User; - -use Symfony\Component\Security\Core\User\UserInterface; - -/** - * Represents a class that loads UserInterface objects from Doctrine source for the authentication system. - * - * This interface is meant to facilitate the loading of a User from Doctrine source using a custom method. - * If you want to implement your own logic of retrieving the user from Doctrine your repository should implement this - * interface. - * - * @see UserInterface - * - * @author Michal Trojanowski - */ -interface UserLoaderInterface -{ - /** - * Loads the user for the given username. - * - * This method must return null if the user is not found. - * - * @return UserInterface|null - */ - public function loadUserByUsername(string $username); -} diff --git a/vendor/symfony/doctrine-bridge/Test/DoctrineTestHelper.php b/vendor/symfony/doctrine-bridge/Test/DoctrineTestHelper.php deleted file mode 100644 index 2ad16dc..0000000 --- a/vendor/symfony/doctrine-bridge/Test/DoctrineTestHelper.php +++ /dev/null @@ -1,99 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Test; - -use Doctrine\Common\Annotations\AnnotationReader; -use Doctrine\Common\Cache\ArrayCache; -use Doctrine\ORM\Configuration; -use Doctrine\ORM\EntityManager; -use Doctrine\ORM\Mapping\Driver\AnnotationDriver; -use Doctrine\ORM\Mapping\Driver\XmlDriver; -use Doctrine\Persistence\Mapping\Driver\MappingDriverChain; -use Doctrine\Persistence\Mapping\Driver\SymfonyFileLocator; -use PHPUnit\Framework\TestCase; - -/** - * Provides utility functions needed in tests. - * - * @author Bernhard Schussek - */ -class DoctrineTestHelper -{ - /** - * Returns an entity manager for testing. - * - * @return EntityManager - */ - public static function createTestEntityManager(Configuration $config = null) - { - if (!\extension_loaded('pdo_sqlite')) { - TestCase::markTestSkipped('Extension pdo_sqlite is required.'); - } - - if (null === $config) { - $config = self::createTestConfiguration(); - } - - $params = [ - 'driver' => 'pdo_sqlite', - 'memory' => true, - ]; - - return EntityManager::create($params, $config); - } - - /** - * @return Configuration - */ - public static function createTestConfiguration() - { - $config = new Configuration(); - $config->setEntityNamespaces(['SymfonyTestsDoctrine' => 'Symfony\Bridge\Doctrine\Tests\Fixtures']); - $config->setAutoGenerateProxyClasses(true); - $config->setProxyDir(sys_get_temp_dir()); - $config->setProxyNamespace('SymfonyTests\Doctrine'); - $config->setMetadataDriverImpl(new AnnotationDriver(new AnnotationReader())); - $config->setQueryCacheImpl(new ArrayCache()); - $config->setMetadataCacheImpl(new ArrayCache()); - - return $config; - } - - /** - * @return Configuration - */ - public static function createTestConfigurationWithXmlLoader() - { - $config = static::createTestConfiguration(); - - $driverChain = new MappingDriverChain(); - $driverChain->addDriver( - new XmlDriver( - new SymfonyFileLocator( - [__DIR__.'/../Tests/Resources/orm' => 'Symfony\\Bridge\\Doctrine\\Tests\\Fixtures'], '.orm.xml' - ) - ), - 'Symfony\\Bridge\\Doctrine\\Tests\\Fixtures' - ); - - $config->setMetadataDriverImpl($driverChain); - - return $config; - } - - /** - * This class cannot be instantiated. - */ - private function __construct() - { - } -} diff --git a/vendor/symfony/doctrine-bridge/Test/TestRepositoryFactory.php b/vendor/symfony/doctrine-bridge/Test/TestRepositoryFactory.php deleted file mode 100644 index 6197c6a..0000000 --- a/vendor/symfony/doctrine-bridge/Test/TestRepositoryFactory.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Test; - -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Repository\RepositoryFactory; -use Doctrine\Persistence\ObjectRepository; - -/** - * @author Andreas Braun - */ -final class TestRepositoryFactory implements RepositoryFactory -{ - /** - * @var ObjectRepository[] - */ - private $repositoryList = []; - - /** - * {@inheritdoc} - * - * @return ObjectRepository - */ - public function getRepository(EntityManagerInterface $entityManager, $entityName) - { - $repositoryHash = $this->getRepositoryHash($entityManager, $entityName); - - if (isset($this->repositoryList[$repositoryHash])) { - return $this->repositoryList[$repositoryHash]; - } - - return $this->repositoryList[$repositoryHash] = $this->createRepository($entityManager, $entityName); - } - - public function setRepository(EntityManagerInterface $entityManager, string $entityName, ObjectRepository $repository) - { - $repositoryHash = $this->getRepositoryHash($entityManager, $entityName); - - $this->repositoryList[$repositoryHash] = $repository; - } - - private function createRepository(EntityManagerInterface $entityManager, string $entityName): ObjectRepository - { - /* @var $metadata ClassMetadata */ - $metadata = $entityManager->getClassMetadata($entityName); - $repositoryClassName = $metadata->customRepositoryClassName ?: $entityManager->getConfiguration()->getDefaultRepositoryClassName(); - - return new $repositoryClassName($entityManager, $metadata); - } - - private function getRepositoryHash(EntityManagerInterface $entityManager, string $entityName): string - { - return $entityManager->getClassMetadata($entityName)->getName().spl_object_hash($entityManager); - } -} diff --git a/vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntity.php b/vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntity.php deleted file mode 100644 index 2c31970..0000000 --- a/vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntity.php +++ /dev/null @@ -1,68 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Validator\Constraints; - -use Symfony\Component\Validator\Constraint; - -/** - * Constraint for the Unique Entity validator. - * - * @Annotation - * @Target({"CLASS", "ANNOTATION"}) - * - * @author Benjamin Eberlei - */ -class UniqueEntity extends Constraint -{ - const NOT_UNIQUE_ERROR = '23bd9dbf-6b9b-41cd-a99e-4844bcf3077f'; - - public $message = 'This value is already used.'; - public $service = 'doctrine.orm.validator.unique'; - public $em = null; - public $entityClass = null; - public $repositoryMethod = 'findBy'; - public $fields = []; - public $errorPath = null; - public $ignoreNull = true; - - protected static $errorNames = [ - self::NOT_UNIQUE_ERROR => 'NOT_UNIQUE_ERROR', - ]; - - public function getRequiredOptions() - { - return ['fields']; - } - - /** - * The validator must be defined as a service with this name. - * - * @return string - */ - public function validatedBy() - { - return $this->service; - } - - /** - * {@inheritdoc} - */ - public function getTargets() - { - return self::CLASS_CONSTRAINT; - } - - public function getDefaultOption() - { - return 'fields'; - } -} diff --git a/vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntityValidator.php b/vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntityValidator.php deleted file mode 100644 index 35f723a..0000000 --- a/vendor/symfony/doctrine-bridge/Validator/Constraints/UniqueEntityValidator.php +++ /dev/null @@ -1,218 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Validator\Constraints; - -use Doctrine\Persistence\ManagerRegistry; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\ConstraintValidator; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; -use Symfony\Component\Validator\Exception\UnexpectedTypeException; - -/** - * Unique Entity Validator checks if one or a set of fields contain unique values. - * - * @author Benjamin Eberlei - */ -class UniqueEntityValidator extends ConstraintValidator -{ - private $registry; - - public function __construct(ManagerRegistry $registry) - { - $this->registry = $registry; - } - - /** - * @param object $entity - * - * @throws UnexpectedTypeException - * @throws ConstraintDefinitionException - */ - public function validate($entity, Constraint $constraint) - { - if (!$constraint instanceof UniqueEntity) { - throw new UnexpectedTypeException($constraint, UniqueEntity::class); - } - - if (!\is_array($constraint->fields) && !\is_string($constraint->fields)) { - throw new UnexpectedTypeException($constraint->fields, 'array'); - } - - if (null !== $constraint->errorPath && !\is_string($constraint->errorPath)) { - throw new UnexpectedTypeException($constraint->errorPath, 'string or null'); - } - - $fields = (array) $constraint->fields; - - if (0 === \count($fields)) { - throw new ConstraintDefinitionException('At least one field has to be specified.'); - } - - if (null === $entity) { - return; - } - - if ($constraint->em) { - $em = $this->registry->getManager($constraint->em); - - if (!$em) { - throw new ConstraintDefinitionException(sprintf('Object manager "%s" does not exist.', $constraint->em)); - } - } else { - $em = $this->registry->getManagerForClass(\get_class($entity)); - - if (!$em) { - throw new ConstraintDefinitionException(sprintf('Unable to find the object manager associated with an entity of class "%s".', \get_class($entity))); - } - } - - $class = $em->getClassMetadata(\get_class($entity)); - - $criteria = []; - $hasNullValue = false; - - foreach ($fields as $fieldName) { - if (!$class->hasField($fieldName) && !$class->hasAssociation($fieldName)) { - throw new ConstraintDefinitionException(sprintf('The field "%s" is not mapped by Doctrine, so it cannot be validated for uniqueness.', $fieldName)); - } - - $fieldValue = $class->reflFields[$fieldName]->getValue($entity); - - if (null === $fieldValue) { - $hasNullValue = true; - } - - if ($constraint->ignoreNull && null === $fieldValue) { - continue; - } - - $criteria[$fieldName] = $fieldValue; - - if (null !== $criteria[$fieldName] && $class->hasAssociation($fieldName)) { - /* Ensure the Proxy is initialized before using reflection to - * read its identifiers. This is necessary because the wrapped - * getter methods in the Proxy are being bypassed. - */ - $em->initializeObject($criteria[$fieldName]); - } - } - - // validation doesn't fail if one of the fields is null and if null values should be ignored - if ($hasNullValue && $constraint->ignoreNull) { - return; - } - - // skip validation if there are no criteria (this can happen when the - // "ignoreNull" option is enabled and fields to be checked are null - if (empty($criteria)) { - return; - } - - if (null !== $constraint->entityClass) { - /* Retrieve repository from given entity name. - * We ensure the retrieved repository can handle the entity - * by checking the entity is the same, or subclass of the supported entity. - */ - $repository = $em->getRepository($constraint->entityClass); - $supportedClass = $repository->getClassName(); - - if (!$entity instanceof $supportedClass) { - throw new ConstraintDefinitionException(sprintf('The "%s" entity repository does not support the "%s" entity. The entity should be an instance of or extend "%s".', $constraint->entityClass, $class->getName(), $supportedClass)); - } - } else { - $repository = $em->getRepository(\get_class($entity)); - } - - $result = $repository->{$constraint->repositoryMethod}($criteria); - - if ($result instanceof \IteratorAggregate) { - $result = $result->getIterator(); - } - - /* If the result is a MongoCursor, it must be advanced to the first - * element. Rewinding should have no ill effect if $result is another - * iterator implementation. - */ - if ($result instanceof \Iterator) { - $result->rewind(); - if ($result instanceof \Countable && 1 < \count($result)) { - $result = [$result->current(), $result->current()]; - } else { - $result = $result->current(); - $result = null === $result ? [] : [$result]; - } - } elseif (\is_array($result)) { - reset($result); - } else { - $result = null === $result ? [] : [$result]; - } - - /* If no entity matched the query criteria or a single entity matched, - * which is the same as the entity being validated, the criteria is - * unique. - */ - if (!$result || (1 === \count($result) && current($result) === $entity)) { - return; - } - - $errorPath = null !== $constraint->errorPath ? $constraint->errorPath : $fields[0]; - $invalidValue = isset($criteria[$errorPath]) ? $criteria[$errorPath] : $criteria[$fields[0]]; - - $this->context->buildViolation($constraint->message) - ->atPath($errorPath) - ->setParameter('{{ value }}', $this->formatWithIdentifiers($em, $class, $invalidValue)) - ->setInvalidValue($invalidValue) - ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) - ->setCause($result) - ->addViolation(); - } - - private function formatWithIdentifiers($em, $class, $value) - { - if (!\is_object($value) || $value instanceof \DateTimeInterface) { - return $this->formatValue($value, self::PRETTY_DATE); - } - - if (method_exists($value, '__toString')) { - return (string) $value; - } - - if ($class->getName() !== $idClass = \get_class($value)) { - // non unique value might be a composite PK that consists of other entity objects - if ($em->getMetadataFactory()->hasMetadataFor($idClass)) { - $identifiers = $em->getClassMetadata($idClass)->getIdentifierValues($value); - } else { - // this case might happen if the non unique column has a custom doctrine type and its value is an object - // in which case we cannot get any identifiers for it - $identifiers = []; - } - } else { - $identifiers = $class->getIdentifierValues($value); - } - - if (!$identifiers) { - return sprintf('object("%s")', $idClass); - } - - array_walk($identifiers, function (&$id, $field) { - if (!\is_object($id) || $id instanceof \DateTimeInterface) { - $idAsString = $this->formatValue($id, self::PRETTY_DATE); - } else { - $idAsString = sprintf('object("%s")', \get_class($id)); - } - - $id = sprintf('%s => %s', $field, $idAsString); - }); - - return sprintf('object("%s") identified by (%s)', $idClass, implode(', ', $identifiers)); - } -} diff --git a/vendor/symfony/doctrine-bridge/Validator/DoctrineInitializer.php b/vendor/symfony/doctrine-bridge/Validator/DoctrineInitializer.php deleted file mode 100644 index 28d5fcc..0000000 --- a/vendor/symfony/doctrine-bridge/Validator/DoctrineInitializer.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Validator; - -use Doctrine\Persistence\ManagerRegistry; -use Symfony\Component\Validator\ObjectInitializerInterface; - -/** - * Automatically loads proxy object before validation. - * - * @author Fabien Potencier - */ -class DoctrineInitializer implements ObjectInitializerInterface -{ - protected $registry; - - public function __construct(ManagerRegistry $registry) - { - $this->registry = $registry; - } - - public function initialize(object $object) - { - $manager = $this->registry->getManagerForClass(\get_class($object)); - if (null !== $manager) { - $manager->initializeObject($object); - } - } -} diff --git a/vendor/symfony/doctrine-bridge/Validator/DoctrineLoader.php b/vendor/symfony/doctrine-bridge/Validator/DoctrineLoader.php deleted file mode 100644 index ca9eb4f..0000000 --- a/vendor/symfony/doctrine-bridge/Validator/DoctrineLoader.php +++ /dev/null @@ -1,140 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Validator; - -use Doctrine\ORM\EntityManagerInterface; -use Doctrine\ORM\Mapping\ClassMetadataInfo; -use Doctrine\ORM\Mapping\MappingException as OrmMappingException; -use Doctrine\Persistence\Mapping\MappingException; -use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; -use Symfony\Component\Validator\Constraints\Length; -use Symfony\Component\Validator\Constraints\Valid; -use Symfony\Component\Validator\Mapping\AutoMappingStrategy; -use Symfony\Component\Validator\Mapping\ClassMetadata; -use Symfony\Component\Validator\Mapping\Loader\AutoMappingTrait; -use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; - -/** - * Guesses and loads the appropriate constraints using Doctrine's metadata. - * - * @author Kévin Dunglas - */ -final class DoctrineLoader implements LoaderInterface -{ - use AutoMappingTrait; - - private $entityManager; - private $classValidatorRegexp; - - public function __construct(EntityManagerInterface $entityManager, string $classValidatorRegexp = null) - { - $this->entityManager = $entityManager; - $this->classValidatorRegexp = $classValidatorRegexp; - } - - /** - * {@inheritdoc} - */ - public function loadClassMetadata(ClassMetadata $metadata): bool - { - $className = $metadata->getClassName(); - try { - $doctrineMetadata = $this->entityManager->getClassMetadata($className); - } catch (MappingException | OrmMappingException $exception) { - return false; - } - - if (!$doctrineMetadata instanceof ClassMetadataInfo) { - return false; - } - - $loaded = false; - $enabledForClass = $this->isAutoMappingEnabledForClass($metadata, $this->classValidatorRegexp); - - /* Available keys: - - type - - scale - - length - - unique - - nullable - - precision - */ - $existingUniqueFields = $this->getExistingUniqueFields($metadata); - - // Type and nullable aren't handled here, use the PropertyInfo Loader instead. - foreach ($doctrineMetadata->fieldMappings as $mapping) { - $enabledForProperty = $enabledForClass; - $lengthConstraint = null; - foreach ($metadata->getPropertyMetadata($mapping['fieldName']) as $propertyMetadata) { - // Enabling or disabling auto-mapping explicitly always takes precedence - if (AutoMappingStrategy::DISABLED === $propertyMetadata->getAutoMappingStrategy()) { - continue 2; - } - if (AutoMappingStrategy::ENABLED === $propertyMetadata->getAutoMappingStrategy()) { - $enabledForProperty = true; - } - - foreach ($propertyMetadata->getConstraints() as $constraint) { - if ($constraint instanceof Length) { - $lengthConstraint = $constraint; - } - } - } - - if (!$enabledForProperty) { - continue; - } - - if (true === ($mapping['unique'] ?? false) && !isset($existingUniqueFields[$mapping['fieldName']])) { - $metadata->addConstraint(new UniqueEntity(['fields' => $mapping['fieldName']])); - $loaded = true; - } - - if (null === ($mapping['length'] ?? null) || !\in_array($mapping['type'], ['string', 'text'], true)) { - continue; - } - - if (null === $lengthConstraint) { - if (isset($mapping['originalClass']) && false === strpos($mapping['declaredField'], '.')) { - $metadata->addPropertyConstraint($mapping['declaredField'], new Valid()); - $loaded = true; - } elseif (property_exists($className, $mapping['fieldName'])) { - $metadata->addPropertyConstraint($mapping['fieldName'], new Length(['max' => $mapping['length']])); - $loaded = true; - } - } elseif (null === $lengthConstraint->max) { - // If a Length constraint exists and no max length has been explicitly defined, set it - $lengthConstraint->max = $mapping['length']; - } - } - - return $loaded; - } - - private function getExistingUniqueFields(ClassMetadata $metadata): array - { - $fields = []; - foreach ($metadata->getConstraints() as $constraint) { - if (!$constraint instanceof UniqueEntity) { - continue; - } - - if (\is_string($constraint->fields)) { - $fields[$constraint->fields] = true; - } elseif (\is_array($constraint->fields) && 1 === \count($constraint->fields)) { - $fields[$constraint->fields[0]] = true; - } - } - - return $fields; - } -} diff --git a/vendor/symfony/doctrine-bridge/composer.json b/vendor/symfony/doctrine-bridge/composer.json deleted file mode 100644 index bf8b981..0000000 --- a/vendor/symfony/doctrine-bridge/composer.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "name": "symfony/doctrine-bridge", - "type": "symfony-bridge", - "description": "Symfony Doctrine Bridge", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "doctrine/event-manager": "~1.0", - "doctrine/persistence": "^1.3", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2" - }, - "require-dev": { - "symfony/stopwatch": "^4.4|^5.0", - "symfony/config": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/form": "^5.0", - "symfony/http-kernel": "^5.0", - "symfony/messenger": "^4.4|^5.0", - "symfony/property-access": "^4.4|^5.0", - "symfony/property-info": "^5.0", - "symfony/proxy-manager-bridge": "^4.4|^5.0", - "symfony/security-core": "^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/validator": "^5.0.2", - "symfony/translation": "^4.4|^5.0", - "symfony/var-dumper": "^4.4|^5.0", - "doctrine/annotations": "~1.7", - "doctrine/cache": "~1.6", - "doctrine/collections": "~1.0", - "doctrine/data-fixtures": "1.0.*", - "doctrine/dbal": "~2.4", - "doctrine/orm": "^2.6.3", - "doctrine/reflection": "~1.0" - }, - "conflict": { - "phpunit/phpunit": "<5.4.3", - "symfony/dependency-injection": "<4.4", - "symfony/form": "<5", - "symfony/http-kernel": "<5", - "symfony/messenger": "<4.4", - "symfony/property-info": "<5", - "symfony/security-bundle": "<5", - "symfony/security-core": "<5", - "symfony/validator": "<5.0.2" - }, - "suggest": { - "symfony/form": "", - "symfony/validator": "", - "symfony/property-info": "", - "doctrine/data-fixtures": "", - "doctrine/dbal": "", - "doctrine/orm": "" - }, - "autoload": { - "psr-4": { "Symfony\\Bridge\\Doctrine\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/error-handler/.gitattributes b/vendor/symfony/error-handler/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/error-handler/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/error-handler/BufferingLogger.php b/vendor/symfony/error-handler/BufferingLogger.php deleted file mode 100644 index 16e433d..0000000 --- a/vendor/symfony/error-handler/BufferingLogger.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler; - -use Psr\Log\AbstractLogger; - -/** - * A buffering logger that stacks logs for later. - * - * @author Nicolas Grekas - */ -class BufferingLogger extends AbstractLogger -{ - private $logs = []; - - public function log($level, $message, array $context = []): void - { - $this->logs[] = [$level, $message, $context]; - } - - public function cleanLogs(): array - { - $logs = $this->logs; - $this->logs = []; - - return $logs; - } - - public function __destruct() - { - foreach ($this->logs as [$level, $message, $context]) { - if (false !== strpos($message, '{')) { - foreach ($context as $key => $val) { - if (null === $val || is_scalar($val) || (\is_object($val) && \is_callable([$val, '__toString']))) { - $message = str_replace("{{$key}}", $val, $message); - } elseif ($val instanceof \DateTimeInterface) { - $message = str_replace("{{$key}}", $val->format(\DateTime::RFC3339), $message); - } elseif (\is_object($val)) { - $message = str_replace("{{$key}}", '[object '.\get_class($val).']', $message); - } else { - $message = str_replace("{{$key}}", '['.\gettype($val).']', $message); - } - } - } - - error_log(sprintf('%s [%s] %s', date(\DateTime::RFC3339), $level, $message)); - } - } -} diff --git a/vendor/symfony/error-handler/CHANGELOG.md b/vendor/symfony/error-handler/CHANGELOG.md deleted file mode 100644 index c7c245a..0000000 --- a/vendor/symfony/error-handler/CHANGELOG.md +++ /dev/null @@ -1,8 +0,0 @@ -CHANGELOG -========= - -4.4.0 ------ - - * added the component - * added `ErrorHandler::call()` method utility to turn any PHP error into `\ErrorException` diff --git a/vendor/symfony/error-handler/Debug.php b/vendor/symfony/error-handler/Debug.php deleted file mode 100644 index f95334e..0000000 --- a/vendor/symfony/error-handler/Debug.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler; - -/** - * Registers all the debug tools. - * - * @author Fabien Potencier - */ -class Debug -{ - public static function enable(): ErrorHandler - { - error_reporting(-1); - - if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { - ini_set('display_errors', 0); - } elseif (!filter_var(ini_get('log_errors'), FILTER_VALIDATE_BOOLEAN) || ini_get('error_log')) { - // CLI - display errors only if they're not already logged to STDERR - ini_set('display_errors', 1); - } - - DebugClassLoader::enable(); - - return ErrorHandler::register(new ErrorHandler(new BufferingLogger())); - } -} diff --git a/vendor/symfony/error-handler/DebugClassLoader.php b/vendor/symfony/error-handler/DebugClassLoader.php deleted file mode 100644 index a9ce96e..0000000 --- a/vendor/symfony/error-handler/DebugClassLoader.php +++ /dev/null @@ -1,1074 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler; - -use Doctrine\Common\Persistence\Proxy as LegacyProxy; -use Doctrine\Persistence\Proxy; -use PHPUnit\Framework\MockObject\Matcher\StatelessInvocation; -use PHPUnit\Framework\MockObject\MockObject; -use Prophecy\Prophecy\ProphecySubjectInterface; -use ProxyManager\Proxy\ProxyInterface; - -/** - * Autoloader checking if the class is really defined in the file found. - * - * The ClassLoader will wrap all registered autoloaders - * and will throw an exception if a file is found but does - * not declare the class. - * - * It can also patch classes to turn docblocks into actual return types. - * This behavior is controlled by the SYMFONY_PATCH_TYPE_DECLARATIONS env var, - * which is a url-encoded array with the follow parameters: - * - "force": any value enables deprecation notices - can be any of: - * - "docblock" to patch only docblock annotations - * - "object" to turn union types to the "object" type when possible (not recommended) - * - "1" to add all possible return types including magic methods - * - "0" to add possible return types excluding magic methods - * - "php": the target version of PHP - e.g. "7.1" doesn't generate "object" types - * - "deprecations": "1" to trigger a deprecation notice when a child class misses a - * return type while the parent declares an "@return" annotation - * - * Note that patching doesn't care about any coding style so you'd better to run - * php-cs-fixer after, with rules "phpdoc_trim_consecutive_blank_line_separation" - * and "no_superfluous_phpdoc_tags" enabled typically. - * - * @author Fabien Potencier - * @author Christophe Coevoet - * @author Nicolas Grekas - * @author Guilhem Niot - */ -class DebugClassLoader -{ - private const SPECIAL_RETURN_TYPES = [ - 'mixed' => 'mixed', - 'void' => 'void', - 'null' => 'null', - 'resource' => 'resource', - 'static' => 'object', - '$this' => 'object', - 'boolean' => 'bool', - 'true' => 'bool', - 'false' => 'bool', - 'integer' => 'int', - 'array' => 'array', - 'bool' => 'bool', - 'callable' => 'callable', - 'float' => 'float', - 'int' => 'int', - 'iterable' => 'iterable', - 'object' => 'object', - 'string' => 'string', - 'self' => 'self', - 'parent' => 'parent', - ]; - - private const BUILTIN_RETURN_TYPES = [ - 'void' => true, - 'array' => true, - 'bool' => true, - 'callable' => true, - 'float' => true, - 'int' => true, - 'iterable' => true, - 'object' => true, - 'string' => true, - 'self' => true, - 'parent' => true, - ]; - - private const MAGIC_METHODS = [ - '__set' => 'void', - '__isset' => 'bool', - '__unset' => 'void', - '__sleep' => 'array', - '__wakeup' => 'void', - '__toString' => 'string', - '__clone' => 'void', - '__debugInfo' => 'array', - '__serialize' => 'array', - '__unserialize' => 'void', - ]; - - private const INTERNAL_TYPES = [ - 'ArrayAccess' => [ - 'offsetExists' => 'bool', - 'offsetSet' => 'void', - 'offsetUnset' => 'void', - ], - 'Countable' => [ - 'count' => 'int', - ], - 'Iterator' => [ - 'next' => 'void', - 'valid' => 'bool', - 'rewind' => 'void', - ], - 'IteratorAggregate' => [ - 'getIterator' => '\Traversable', - ], - 'OuterIterator' => [ - 'getInnerIterator' => '\Iterator', - ], - 'RecursiveIterator' => [ - 'hasChildren' => 'bool', - ], - 'SeekableIterator' => [ - 'seek' => 'void', - ], - 'Serializable' => [ - 'serialize' => 'string', - 'unserialize' => 'void', - ], - 'SessionHandlerInterface' => [ - 'open' => 'bool', - 'close' => 'bool', - 'read' => 'string', - 'write' => 'bool', - 'destroy' => 'bool', - 'gc' => 'bool', - ], - 'SessionIdInterface' => [ - 'create_sid' => 'string', - ], - 'SessionUpdateTimestampHandlerInterface' => [ - 'validateId' => 'bool', - 'updateTimestamp' => 'bool', - ], - 'Throwable' => [ - 'getMessage' => 'string', - 'getCode' => 'int', - 'getFile' => 'string', - 'getLine' => 'int', - 'getTrace' => 'array', - 'getPrevious' => '?\Throwable', - 'getTraceAsString' => 'string', - ], - ]; - - private $classLoader; - private $isFinder; - private $loaded = []; - private $patchTypes; - - private static $caseCheck; - private static $checkedClasses = []; - private static $final = []; - private static $finalMethods = []; - private static $deprecated = []; - private static $internal = []; - private static $internalMethods = []; - private static $annotatedParameters = []; - private static $darwinCache = ['/' => ['/', []]]; - private static $method = []; - private static $returnTypes = []; - private static $methodTraits = []; - private static $fileOffsets = []; - - public function __construct(callable $classLoader) - { - $this->classLoader = $classLoader; - $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile'); - parse_str(getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?: '', $this->patchTypes); - $this->patchTypes += [ - 'force' => null, - 'php' => null, - 'deprecations' => false, - ]; - - if (!isset(self::$caseCheck)) { - $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR); - $i = strrpos($file, \DIRECTORY_SEPARATOR); - $dir = substr($file, 0, 1 + $i); - $file = substr($file, 1 + $i); - $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file); - $test = realpath($dir.$test); - - if (false === $test || false === $i) { - // filesystem is case sensitive - self::$caseCheck = 0; - } elseif (substr($test, -\strlen($file)) === $file) { - // filesystem is case insensitive and realpath() normalizes the case of characters - self::$caseCheck = 1; - } elseif (false !== stripos(PHP_OS, 'darwin')) { - // on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters - self::$caseCheck = 2; - } else { - // filesystem case checks failed, fallback to disabling them - self::$caseCheck = 0; - } - } - } - - /** - * Gets the wrapped class loader. - * - * @return callable The wrapped class loader - */ - public function getClassLoader(): callable - { - return $this->classLoader; - } - - /** - * Wraps all autoloaders. - */ - public static function enable(): void - { - // Ensures we don't hit https://bugs.php.net/42098 - class_exists('Symfony\Component\ErrorHandler\ErrorHandler'); - class_exists('Psr\Log\LogLevel'); - - if (!\is_array($functions = spl_autoload_functions())) { - return; - } - - foreach ($functions as $function) { - spl_autoload_unregister($function); - } - - foreach ($functions as $function) { - if (!\is_array($function) || !$function[0] instanceof self) { - $function = [new static($function), 'loadClass']; - } - - spl_autoload_register($function); - } - } - - /** - * Disables the wrapping. - */ - public static function disable(): void - { - if (!\is_array($functions = spl_autoload_functions())) { - return; - } - - foreach ($functions as $function) { - spl_autoload_unregister($function); - } - - foreach ($functions as $function) { - if (\is_array($function) && $function[0] instanceof self) { - $function = $function[0]->getClassLoader(); - } - - spl_autoload_register($function); - } - } - - public static function checkClasses(): bool - { - if (!\is_array($functions = spl_autoload_functions())) { - return false; - } - - $loader = null; - - foreach ($functions as $function) { - if (\is_array($function) && $function[0] instanceof self) { - $loader = $function[0]; - break; - } - } - - if (null === $loader) { - return false; - } - - static $offsets = [ - 'get_declared_interfaces' => 0, - 'get_declared_traits' => 0, - 'get_declared_classes' => 0, - ]; - - foreach ($offsets as $getSymbols => $i) { - $symbols = $getSymbols(); - - for (; $i < \count($symbols); ++$i) { - if (!is_subclass_of($symbols[$i], MockObject::class) - && !is_subclass_of($symbols[$i], ProphecySubjectInterface::class) - && !is_subclass_of($symbols[$i], Proxy::class) - && !is_subclass_of($symbols[$i], ProxyInterface::class) - && !is_subclass_of($symbols[$i], LegacyProxy::class) - ) { - $loader->checkClass($symbols[$i]); - } - } - - $offsets[$getSymbols] = $i; - } - - return true; - } - - public function findFile(string $class): ?string - { - return $this->isFinder ? ($this->classLoader[0]->findFile($class) ?: null) : null; - } - - /** - * Loads the given class or interface. - * - * @throws \RuntimeException - */ - public function loadClass(string $class): void - { - $e = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR); - - try { - if ($this->isFinder && !isset($this->loaded[$class])) { - $this->loaded[$class] = true; - if (!$file = $this->classLoader[0]->findFile($class) ?: '') { - // no-op - } elseif (\function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file)) { - include $file; - - return; - } elseif (false === include $file) { - return; - } - } else { - ($this->classLoader)($class); - $file = ''; - } - } finally { - error_reporting($e); - } - - $this->checkClass($class, $file); - } - - private function checkClass(string $class, string $file = null): void - { - $exists = null === $file || class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); - - if (null !== $file && $class && '\\' === $class[0]) { - $class = substr($class, 1); - } - - if ($exists) { - if (isset(self::$checkedClasses[$class])) { - return; - } - self::$checkedClasses[$class] = true; - - $refl = new \ReflectionClass($class); - if (null === $file && $refl->isInternal()) { - return; - } - $name = $refl->getName(); - - if ($name !== $class && 0 === strcasecmp($name, $class)) { - throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name)); - } - - $deprecations = $this->checkAnnotations($refl, $name); - - foreach ($deprecations as $message) { - @trigger_error($message, E_USER_DEPRECATED); - } - } - - if (!$file) { - return; - } - - if (!$exists) { - if (false !== strpos($class, '/')) { - throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class)); - } - - throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); - } - - if (self::$caseCheck && $message = $this->checkCase($refl, $file, $class)) { - throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', $message[0], $message[1], $message[2])); - } - } - - public function checkAnnotations(\ReflectionClass $refl, string $class): array - { - if ( - 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV7' === $class - || 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV6' === $class - ) { - return []; - } - $deprecations = []; - - $className = isset($class[15]) && "\0" === $class[15] && 0 === strpos($class, "class@anonymous\x00") ? get_parent_class($class).'@anonymous' : $class; - - // Don't trigger deprecations for classes in the same vendor - if ($class !== $className) { - $vendor = preg_match('/^namespace ([^;\\\\\s]++)[;\\\\]/m', @file_get_contents($refl->getFileName()), $vendor) ? $vendor[1].'\\' : ''; - $vendorLen = \strlen($vendor); - } elseif (2 > $vendorLen = 1 + (strpos($class, '\\') ?: strpos($class, '_'))) { - $vendorLen = 0; - $vendor = ''; - } else { - $vendor = str_replace('_', '\\', substr($class, 0, $vendorLen)); - } - - // Detect annotations on the class - if (false !== $doc = $refl->getDocComment()) { - foreach (['final', 'deprecated', 'internal'] as $annotation) { - if (false !== strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) { - self::${$annotation}[$class] = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : ''; - } - } - - if ($refl->isInterface() && false !== strpos($doc, 'method') && preg_match_all('#\n \* @method\s+(static\s+)?+(?:[\w\|&\[\]\\\]+\s+)?(\w+(?:\s*\([^\)]*\))?)+(.+?([[:punct:]]\s*)?)?(?=\r?\n \*(?: @|/$|\r?\n))#', $doc, $notice, PREG_SET_ORDER)) { - foreach ($notice as $method) { - $static = '' !== $method[1]; - $name = $method[2]; - $description = $method[3] ?? null; - if (false === strpos($name, '(')) { - $name .= '()'; - } - if (null !== $description) { - $description = trim($description); - if (!isset($method[4])) { - $description .= '.'; - } - } - self::$method[$class][] = [$class, $name, $static, $description]; - } - } - } - - $parent = get_parent_class($class) ?: null; - $parentAndOwnInterfaces = $this->getOwnInterfaces($class, $parent); - if ($parent) { - $parentAndOwnInterfaces[$parent] = $parent; - - if (!isset(self::$checkedClasses[$parent])) { - $this->checkClass($parent); - } - - if (isset(self::$final[$parent])) { - $deprecations[] = sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $className); - } - } - - // Detect if the parent is annotated - foreach ($parentAndOwnInterfaces + class_uses($class, false) as $use) { - if (!isset(self::$checkedClasses[$use])) { - $this->checkClass($use); - } - if (isset(self::$deprecated[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen) && !isset(self::$deprecated[$class])) { - $type = class_exists($class, false) ? 'class' : (interface_exists($class, false) ? 'interface' : 'trait'); - $verb = class_exists($use, false) || interface_exists($class, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses'); - - $deprecations[] = sprintf('The "%s" %s %s "%s" that is deprecated%s.', $className, $type, $verb, $use, self::$deprecated[$use]); - } - if (isset(self::$internal[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen)) { - $deprecations[] = sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $className); - } - if (isset(self::$method[$use])) { - if ($refl->isAbstract()) { - if (isset(self::$method[$class])) { - self::$method[$class] = array_merge(self::$method[$class], self::$method[$use]); - } else { - self::$method[$class] = self::$method[$use]; - } - } elseif (!$refl->isInterface()) { - $hasCall = $refl->hasMethod('__call'); - $hasStaticCall = $refl->hasMethod('__callStatic'); - foreach (self::$method[$use] as $method) { - list($interface, $name, $static, $description) = $method; - if ($static ? $hasStaticCall : $hasCall) { - continue; - } - $realName = substr($name, 0, strpos($name, '(')); - if (!$refl->hasMethod($realName) || !($methodRefl = $refl->getMethod($realName))->isPublic() || ($static && !$methodRefl->isStatic()) || (!$static && $methodRefl->isStatic())) { - $deprecations[] = sprintf('Class "%s" should implement method "%s::%s"%s', $className, ($static ? 'static ' : '').$interface, $name, null == $description ? '.' : ': '.$description); - } - } - } - } - } - - if (trait_exists($class)) { - $file = $refl->getFileName(); - - foreach ($refl->getMethods() as $method) { - if ($method->getFileName() === $file) { - self::$methodTraits[$file][$method->getStartLine()] = $class; - } - } - - return $deprecations; - } - - // Inherit @final, @internal, @param and @return annotations for methods - self::$finalMethods[$class] = []; - self::$internalMethods[$class] = []; - self::$annotatedParameters[$class] = []; - self::$returnTypes[$class] = []; - foreach ($parentAndOwnInterfaces as $use) { - foreach (['finalMethods', 'internalMethods', 'annotatedParameters', 'returnTypes'] as $property) { - if (isset(self::${$property}[$use])) { - self::${$property}[$class] = self::${$property}[$class] ? self::${$property}[$use] + self::${$property}[$class] : self::${$property}[$use]; - } - } - - if (null !== (self::INTERNAL_TYPES[$use] ?? null)) { - foreach (self::INTERNAL_TYPES[$use] as $method => $returnType) { - if ('void' !== $returnType) { - self::$returnTypes[$class] += [$method => [$returnType, $returnType, $class, '']]; - } - } - } - } - - foreach ($refl->getMethods() as $method) { - if ($method->class !== $class) { - continue; - } - - if (null === $ns = self::$methodTraits[$method->getFileName()][$method->getStartLine()] ?? null) { - $ns = $vendor; - $len = $vendorLen; - } elseif (2 > $len = 1 + (strpos($ns, '\\') ?: strpos($ns, '_'))) { - $len = 0; - $ns = ''; - } else { - $ns = str_replace('_', '\\', substr($ns, 0, $len)); - } - - if ($parent && isset(self::$finalMethods[$parent][$method->name])) { - list($declaringClass, $message) = self::$finalMethods[$parent][$method->name]; - $deprecations[] = sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className); - } - - if (isset(self::$internalMethods[$class][$method->name])) { - list($declaringClass, $message) = self::$internalMethods[$class][$method->name]; - if (strncmp($ns, $declaringClass, $len)) { - $deprecations[] = sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className); - } - } - - // To read method annotations - $doc = $method->getDocComment(); - - if (isset(self::$annotatedParameters[$class][$method->name])) { - $definedParameters = []; - foreach ($method->getParameters() as $parameter) { - $definedParameters[$parameter->name] = true; - } - - foreach (self::$annotatedParameters[$class][$method->name] as $parameterName => $deprecation) { - if (!isset($definedParameters[$parameterName]) && !($doc && preg_match("/\\n\\s+\\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\\\${$parameterName}\\b/", $doc))) { - $deprecations[] = sprintf($deprecation, $className); - } - } - } - - $forcePatchTypes = $this->patchTypes['force']; - - if ($canAddReturnType = null !== $forcePatchTypes && false === strpos($method->getFileName(), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) { - if ('void' !== (self::MAGIC_METHODS[$method->name] ?? 'void')) { - $this->patchTypes['force'] = $forcePatchTypes ?: 'docblock'; - } - - $canAddReturnType = false !== strpos($refl->getFileName(), \DIRECTORY_SEPARATOR.'Tests'.\DIRECTORY_SEPARATOR) - || $refl->isFinal() - || $method->isFinal() - || $method->isPrivate() - || ('' === (self::$internal[$class] ?? null) && !$refl->isAbstract()) - || '' === (self::$final[$class] ?? null) - || preg_match('/@(final|internal)$/m', $doc) - ; - } - - if (null !== ($returnType = self::$returnTypes[$class][$method->name] ?? self::MAGIC_METHODS[$method->name] ?? null) && !$method->hasReturnType() && !($doc && preg_match('/\n\s+\* @return +(\S+)/', $doc))) { - list($normalizedType, $returnType, $declaringClass, $declaringFile) = \is_string($returnType) ? [$returnType, $returnType, '', ''] : $returnType; - - if ('void' === $normalizedType) { - $canAddReturnType = false; - } - - if ($canAddReturnType && 'docblock' !== $this->patchTypes['force']) { - $this->patchMethod($method, $returnType, $declaringFile, $normalizedType); - } - - if (strncmp($ns, $declaringClass, $len)) { - if ($canAddReturnType && 'docblock' === $this->patchTypes['force'] && false === strpos($method->getFileName(), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) { - $this->patchMethod($method, $returnType, $declaringFile, $normalizedType); - } elseif ('' !== $declaringClass && $this->patchTypes['deprecations']) { - $deprecations[] = sprintf('Method "%s::%s()" will return "%s" as of its next major version. Doing the same in child class "%s" will be required when upgrading.', $declaringClass, $method->name, $normalizedType, $className); - } - } - } - - if (!$doc) { - $this->patchTypes['force'] = $forcePatchTypes; - - continue; - } - - $matches = []; - - if (!$method->hasReturnType() && ((false !== strpos($doc, '@return') && preg_match('/\n\s+\* @return +(\S+)/', $doc, $matches)) || 'void' !== (self::MAGIC_METHODS[$method->name] ?? 'void'))) { - $matches = $matches ?: [1 => self::MAGIC_METHODS[$method->name]]; - $this->setReturnType($matches[1], $method, $parent); - - if (isset(self::$returnTypes[$class][$method->name][0]) && $canAddReturnType) { - $this->fixReturnStatements($method, self::$returnTypes[$class][$method->name][0]); - } - - if ($method->isPrivate()) { - unset(self::$returnTypes[$class][$method->name]); - } - } - - $this->patchTypes['force'] = $forcePatchTypes; - - if ($method->isPrivate()) { - continue; - } - - $finalOrInternal = false; - - foreach (['final', 'internal'] as $annotation) { - if (false !== strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) { - $message = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : ''; - self::${$annotation.'Methods'}[$class][$method->name] = [$class, $message]; - $finalOrInternal = true; - } - } - - if ($finalOrInternal || $method->isConstructor() || false === strpos($doc, '@param') || StatelessInvocation::class === $class) { - continue; - } - if (!preg_match_all('#\n\s+\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\$([a-zA-Z0-9_\x7f-\xff]++)#', $doc, $matches, PREG_SET_ORDER)) { - continue; - } - if (!isset(self::$annotatedParameters[$class][$method->name])) { - $definedParameters = []; - foreach ($method->getParameters() as $parameter) { - $definedParameters[$parameter->name] = true; - } - } - foreach ($matches as list(, $parameterType, $parameterName)) { - if (!isset($definedParameters[$parameterName])) { - $parameterType = trim($parameterType); - self::$annotatedParameters[$class][$method->name][$parameterName] = sprintf('The "%%s::%s()" method will require a new "%s$%s" argument in the next major version of its parent class "%s", not defining it is deprecated.', $method->name, $parameterType ? $parameterType.' ' : '', $parameterName, $className); - } - } - } - - return $deprecations; - } - - public function checkCase(\ReflectionClass $refl, string $file, string $class): ?array - { - $real = explode('\\', $class.strrchr($file, '.')); - $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file)); - - $i = \count($tail) - 1; - $j = \count($real) - 1; - - while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) { - --$i; - --$j; - } - - array_splice($tail, 0, $i + 1); - - if (!$tail) { - return null; - } - - $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail); - $tailLen = \strlen($tail); - $real = $refl->getFileName(); - - if (2 === self::$caseCheck) { - $real = $this->darwinRealpath($real); - } - - if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true) - && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false) - ) { - return [substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)]; - } - - return null; - } - - /** - * `realpath` on MacOSX doesn't normalize the case of characters. - */ - private function darwinRealpath(string $real): string - { - $i = 1 + strrpos($real, '/'); - $file = substr($real, $i); - $real = substr($real, 0, $i); - - if (isset(self::$darwinCache[$real])) { - $kDir = $real; - } else { - $kDir = strtolower($real); - - if (isset(self::$darwinCache[$kDir])) { - $real = self::$darwinCache[$kDir][0]; - } else { - $dir = getcwd(); - - if (!@chdir($real)) { - return $real.$file; - } - - $real = getcwd().'/'; - chdir($dir); - - $dir = $real; - $k = $kDir; - $i = \strlen($dir) - 1; - while (!isset(self::$darwinCache[$k])) { - self::$darwinCache[$k] = [$dir, []]; - self::$darwinCache[$dir] = &self::$darwinCache[$k]; - - while ('/' !== $dir[--$i]) { - } - $k = substr($k, 0, ++$i); - $dir = substr($dir, 0, $i--); - } - } - } - - $dirFiles = self::$darwinCache[$kDir][1]; - - if (!isset($dirFiles[$file]) && ') : eval()\'d code' === substr($file, -17)) { - // Get the file name from "file_name.php(123) : eval()'d code" - $file = substr($file, 0, strrpos($file, '(', -17)); - } - - if (isset($dirFiles[$file])) { - return $real.$dirFiles[$file]; - } - - $kFile = strtolower($file); - - if (!isset($dirFiles[$kFile])) { - foreach (scandir($real, 2) as $f) { - if ('.' !== $f[0]) { - $dirFiles[$f] = $f; - if ($f === $file) { - $kFile = $k = $file; - } elseif ($f !== $k = strtolower($f)) { - $dirFiles[$k] = $f; - } - } - } - self::$darwinCache[$kDir][1] = $dirFiles; - } - - return $real.$dirFiles[$kFile]; - } - - /** - * `class_implements` includes interfaces from the parents so we have to manually exclude them. - * - * @return string[] - */ - private function getOwnInterfaces(string $class, ?string $parent): array - { - $ownInterfaces = class_implements($class, false); - - if ($parent) { - foreach (class_implements($parent, false) as $interface) { - unset($ownInterfaces[$interface]); - } - } - - foreach ($ownInterfaces as $interface) { - foreach (class_implements($interface) as $interface) { - unset($ownInterfaces[$interface]); - } - } - - return $ownInterfaces; - } - - private function setReturnType(string $types, \ReflectionMethod $method, ?string $parent): void - { - $nullable = false; - $typesMap = []; - foreach (explode('|', $types) as $t) { - $typesMap[$this->normalizeType($t, $method->class, $parent)] = $t; - } - - if (isset($typesMap['array'])) { - if (isset($typesMap['Traversable']) || isset($typesMap['\Traversable'])) { - $typesMap['iterable'] = 'array' !== $typesMap['array'] ? $typesMap['array'] : 'iterable'; - unset($typesMap['array'], $typesMap['Traversable'], $typesMap['\Traversable']); - } elseif ('array' !== $typesMap['array'] && isset(self::$returnTypes[$method->class][$method->name])) { - return; - } - } - - if (isset($typesMap['array']) && isset($typesMap['iterable'])) { - if ('[]' === substr($typesMap['array'], -2)) { - $typesMap['iterable'] = $typesMap['array']; - } - unset($typesMap['array']); - } - - $iterable = $object = true; - foreach ($typesMap as $n => $t) { - if ('null' !== $n) { - $iterable = $iterable && (\in_array($n, ['array', 'iterable']) || false !== strpos($n, 'Iterator')); - $object = $object && (\in_array($n, ['callable', 'object', '$this', 'static']) || !isset(self::SPECIAL_RETURN_TYPES[$n])); - } - } - - $normalizedType = key($typesMap); - $returnType = current($typesMap); - - foreach ($typesMap as $n => $t) { - if ('null' === $n) { - $nullable = true; - } elseif ('null' === $normalizedType) { - $normalizedType = $t; - $returnType = $t; - } elseif ($n !== $normalizedType || !preg_match('/^\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $n)) { - if ($iterable) { - $normalizedType = $returnType = 'iterable'; - } elseif ($object && 'object' === $this->patchTypes['force']) { - $normalizedType = $returnType = 'object'; - } else { - // ignore multi-types return declarations - return; - } - } - } - - if ('void' === $normalizedType) { - $nullable = false; - } elseif (!isset(self::BUILTIN_RETURN_TYPES[$normalizedType]) && isset(self::SPECIAL_RETURN_TYPES[$normalizedType])) { - // ignore other special return types - return; - } - - if ($nullable) { - $normalizedType = '?'.$normalizedType; - $returnType .= '|null'; - } - - self::$returnTypes[$method->class][$method->name] = [$normalizedType, $returnType, $method->class, $method->getFileName()]; - } - - private function normalizeType(string $type, string $class, ?string $parent): string - { - if (isset(self::SPECIAL_RETURN_TYPES[$lcType = strtolower($type)])) { - if ('parent' === $lcType = self::SPECIAL_RETURN_TYPES[$lcType]) { - $lcType = null !== $parent ? '\\'.$parent : 'parent'; - } elseif ('self' === $lcType) { - $lcType = '\\'.$class; - } - - return $lcType; - } - - if ('[]' === substr($type, -2)) { - return 'array'; - } - - if (preg_match('/^(array|iterable|callable) *[<(]/', $lcType, $m)) { - return $m[1]; - } - - // We could resolve "use" statements to return the FQDN - // but this would be too expensive for a runtime checker - - return $type; - } - - /** - * Utility method to add @return annotations to the Symfony code-base where it triggers a self-deprecations. - */ - private function patchMethod(\ReflectionMethod $method, string $returnType, string $declaringFile, string $normalizedType) - { - static $patchedMethods = []; - static $useStatements = []; - - if (!file_exists($file = $method->getFileName()) || isset($patchedMethods[$file][$startLine = $method->getStartLine()])) { - return; - } - - $patchedMethods[$file][$startLine] = true; - $fileOffset = self::$fileOffsets[$file] ?? 0; - $startLine += $fileOffset - 2; - $nullable = '?' === $normalizedType[0] ? '?' : ''; - $normalizedType = ltrim($normalizedType, '?'); - $returnType = explode('|', $returnType); - $code = file($file); - - foreach ($returnType as $i => $type) { - if (preg_match('/((?:\[\])+)$/', $type, $m)) { - $type = substr($type, 0, -\strlen($m[1])); - $format = '%s'.$m[1]; - } elseif (preg_match('/^(array|iterable)<([^,>]++)>$/', $type, $m)) { - $type = $m[2]; - $format = $m[1].'<%s>'; - } else { - $format = null; - } - - if (isset(self::SPECIAL_RETURN_TYPES[$type]) || ('\\' === $type[0] && !$p = strrpos($type, '\\', 1))) { - continue; - } - - list($namespace, $useOffset, $useMap) = $useStatements[$file] ?? $useStatements[$file] = self::getUseStatements($file); - - if ('\\' !== $type[0]) { - list($declaringNamespace, , $declaringUseMap) = $useStatements[$declaringFile] ?? $useStatements[$declaringFile] = self::getUseStatements($declaringFile); - - $p = strpos($type, '\\', 1); - $alias = $p ? substr($type, 0, $p) : $type; - - if (isset($declaringUseMap[$alias])) { - $type = '\\'.$declaringUseMap[$alias].($p ? substr($type, $p) : ''); - } else { - $type = '\\'.$declaringNamespace.$type; - } - - $p = strrpos($type, '\\', 1); - } - - $alias = substr($type, 1 + $p); - $type = substr($type, 1); - - if (!isset($useMap[$alias]) && (class_exists($c = $namespace.$alias) || interface_exists($c) || trait_exists($c))) { - $useMap[$alias] = $c; - } - - if (!isset($useMap[$alias])) { - $useStatements[$file][2][$alias] = $type; - $code[$useOffset] = "use $type;\n".$code[$useOffset]; - ++$fileOffset; - } elseif ($useMap[$alias] !== $type) { - $alias .= 'FIXME'; - $useStatements[$file][2][$alias] = $type; - $code[$useOffset] = "use $type as $alias;\n".$code[$useOffset]; - ++$fileOffset; - } - - $returnType[$i] = null !== $format ? sprintf($format, $alias) : $alias; - - if (!isset(self::SPECIAL_RETURN_TYPES[$normalizedType]) && !isset(self::SPECIAL_RETURN_TYPES[$returnType[$i]])) { - $normalizedType = $returnType[$i]; - } - } - - if ('docblock' === $this->patchTypes['force'] || ('object' === $normalizedType && '7.1' === $this->patchTypes['php'])) { - $returnType = implode('|', $returnType); - - if ($method->getDocComment()) { - $code[$startLine] = " * @return $returnType\n".$code[$startLine]; - } else { - $code[$startLine] .= <<fixReturnStatements($method, $nullable.$normalizedType); - } - - private static function getUseStatements(string $file): array - { - $namespace = ''; - $useMap = []; - $useOffset = 0; - - if (!file_exists($file)) { - return [$namespace, $useOffset, $useMap]; - } - - $file = file($file); - - for ($i = 0; $i < \count($file); ++$i) { - if (preg_match('/^(class|interface|trait|abstract) /', $file[$i])) { - break; - } - - if (0 === strpos($file[$i], 'namespace ')) { - $namespace = substr($file[$i], \strlen('namespace '), -2).'\\'; - $useOffset = $i + 2; - } - - if (0 === strpos($file[$i], 'use ')) { - $useOffset = $i; - - for (; 0 === strpos($file[$i], 'use '); ++$i) { - $u = explode(' as ', substr($file[$i], 4, -2), 2); - - if (1 === \count($u)) { - $p = strrpos($u[0], '\\'); - $useMap[substr($u[0], false !== $p ? 1 + $p : 0)] = $u[0]; - } else { - $useMap[$u[1]] = $u[0]; - } - } - - break; - } - } - - return [$namespace, $useOffset, $useMap]; - } - - private function fixReturnStatements(\ReflectionMethod $method, string $returnType) - { - if ('7.1' === $this->patchTypes['php'] && 'object' === ltrim($returnType, '?') && 'docblock' !== $this->patchTypes['force']) { - return; - } - - if (!file_exists($file = $method->getFileName())) { - return; - } - - $fixedCode = $code = file($file); - $i = (self::$fileOffsets[$file] ?? 0) + $method->getStartLine(); - - if ('?' !== $returnType && 'docblock' !== $this->patchTypes['force']) { - $fixedCode[$i - 1] = preg_replace('/\)(;?\n)/', "): $returnType\\1", $code[$i - 1]); - } - - $end = $method->isGenerator() ? $i : $method->getEndLine(); - for (; $i < $end; ++$i) { - if ('void' === $returnType) { - $fixedCode[$i] = str_replace(' return null;', ' return;', $code[$i]); - } elseif ('mixed' === $returnType || '?' === $returnType[0]) { - $fixedCode[$i] = str_replace(' return;', ' return null;', $code[$i]); - } else { - $fixedCode[$i] = str_replace(' return;', " return $returnType!?;", $code[$i]); - } - } - - if ($fixedCode !== $code) { - file_put_contents($file, $fixedCode); - } - } -} diff --git a/vendor/symfony/error-handler/Error/ClassNotFoundError.php b/vendor/symfony/error-handler/Error/ClassNotFoundError.php deleted file mode 100644 index 443fba2..0000000 --- a/vendor/symfony/error-handler/Error/ClassNotFoundError.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Error; - -class ClassNotFoundError extends \Error -{ - /** - * {@inheritdoc} - */ - public function __construct(string $message, \Throwable $previous) - { - parent::__construct($message, $previous->getCode(), $previous->getPrevious()); - - foreach ([ - 'file' => $previous->getFile(), - 'line' => $previous->getLine(), - 'trace' => $previous->getTrace(), - ] as $property => $value) { - $refl = new \ReflectionProperty(\Error::class, $property); - $refl->setAccessible(true); - $refl->setValue($this, $value); - } - } -} diff --git a/vendor/symfony/error-handler/Error/FatalError.php b/vendor/symfony/error-handler/Error/FatalError.php deleted file mode 100644 index 68172d8..0000000 --- a/vendor/symfony/error-handler/Error/FatalError.php +++ /dev/null @@ -1,88 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Error; - -class FatalError extends \Error -{ - private $error; - - /** - * {@inheritdoc} - * - * @param array $error An array as returned by error_get_last() - */ - public function __construct(string $message, int $code, array $error, int $traceOffset = null, bool $traceArgs = true, array $trace = null) - { - parent::__construct($message, $code); - - $this->error = $error; - - if (null !== $trace) { - if (!$traceArgs) { - foreach ($trace as &$frame) { - unset($frame['args'], $frame['this'], $frame); - } - } - } elseif (null !== $traceOffset) { - if (\function_exists('xdebug_get_function_stack')) { - $trace = xdebug_get_function_stack(); - if (0 < $traceOffset) { - array_splice($trace, -$traceOffset); - } - - foreach ($trace as &$frame) { - if (!isset($frame['type'])) { - // XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695 - if (isset($frame['class'])) { - $frame['type'] = '::'; - } - } elseif ('dynamic' === $frame['type']) { - $frame['type'] = '->'; - } elseif ('static' === $frame['type']) { - $frame['type'] = '::'; - } - - // XDebug also has a different name for the parameters array - if (!$traceArgs) { - unset($frame['params'], $frame['args']); - } elseif (isset($frame['params']) && !isset($frame['args'])) { - $frame['args'] = $frame['params']; - unset($frame['params']); - } - } - - unset($frame); - $trace = array_reverse($trace); - } else { - $trace = []; - } - } - - foreach ([ - 'file' => $error['file'], - 'line' => $error['line'], - 'trace' => $trace, - ] as $property => $value) { - $refl = new \ReflectionProperty(\Error::class, $property); - $refl->setAccessible(true); - $refl->setValue($this, $value); - } - } - - /** - * {@inheritdoc} - */ - public function getError(): array - { - return $this->error; - } -} diff --git a/vendor/symfony/error-handler/Error/OutOfMemoryError.php b/vendor/symfony/error-handler/Error/OutOfMemoryError.php deleted file mode 100644 index d685c3d..0000000 --- a/vendor/symfony/error-handler/Error/OutOfMemoryError.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Error; - -class OutOfMemoryError extends FatalError -{ -} diff --git a/vendor/symfony/error-handler/Error/UndefinedFunctionError.php b/vendor/symfony/error-handler/Error/UndefinedFunctionError.php deleted file mode 100644 index b57dd15..0000000 --- a/vendor/symfony/error-handler/Error/UndefinedFunctionError.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Error; - -class UndefinedFunctionError extends \Error -{ - /** - * {@inheritdoc} - */ - public function __construct(string $message, \Throwable $previous) - { - parent::__construct($message, $previous->getCode(), $previous->getPrevious()); - - foreach ([ - 'file' => $previous->getFile(), - 'line' => $previous->getLine(), - 'trace' => $previous->getTrace(), - ] as $property => $value) { - $refl = new \ReflectionProperty(\Error::class, $property); - $refl->setAccessible(true); - $refl->setValue($this, $value); - } - } -} diff --git a/vendor/symfony/error-handler/Error/UndefinedMethodError.php b/vendor/symfony/error-handler/Error/UndefinedMethodError.php deleted file mode 100644 index adc8731..0000000 --- a/vendor/symfony/error-handler/Error/UndefinedMethodError.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Error; - -class UndefinedMethodError extends \Error -{ - /** - * {@inheritdoc} - */ - public function __construct(string $message, \Throwable $previous) - { - parent::__construct($message, $previous->getCode(), $previous->getPrevious()); - - foreach ([ - 'file' => $previous->getFile(), - 'line' => $previous->getLine(), - 'trace' => $previous->getTrace(), - ] as $property => $value) { - $refl = new \ReflectionProperty(\Error::class, $property); - $refl->setAccessible(true); - $refl->setValue($this, $value); - } - } -} diff --git a/vendor/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php b/vendor/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php deleted file mode 100644 index 7cd2b38..0000000 --- a/vendor/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php +++ /dev/null @@ -1,193 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorEnhancer; - -use Composer\Autoload\ClassLoader; -use Symfony\Component\ErrorHandler\DebugClassLoader; -use Symfony\Component\ErrorHandler\Error\ClassNotFoundError; -use Symfony\Component\ErrorHandler\Error\FatalError; - -/** - * @author Fabien Potencier - */ -class ClassNotFoundErrorEnhancer implements ErrorEnhancerInterface -{ - /** - * {@inheritdoc} - */ - public function enhance(\Throwable $error): ?\Throwable - { - // Some specific versions of PHP produce a fatal error when extending a not found class. - $message = !$error instanceof FatalError ? $error->getMessage() : $error->getError()['message']; - $messageLen = \strlen($message); - $notFoundSuffix = '\' not found'; - $notFoundSuffixLen = \strlen($notFoundSuffix); - if ($notFoundSuffixLen > $messageLen) { - return null; - } - - if (0 !== substr_compare($message, $notFoundSuffix, -$notFoundSuffixLen)) { - return null; - } - - foreach (['class', 'interface', 'trait'] as $typeName) { - $prefix = ucfirst($typeName).' \''; - $prefixLen = \strlen($prefix); - if (0 !== strpos($message, $prefix)) { - continue; - } - - $fullyQualifiedClassName = substr($message, $prefixLen, -$notFoundSuffixLen); - if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) { - $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1); - $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex); - $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix); - $tail = ' for another namespace?'; - } else { - $className = $fullyQualifiedClassName; - $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className); - $tail = '?'; - } - - if ($candidates = $this->getClassCandidates($className)) { - $tail = array_pop($candidates).'"?'; - if ($candidates) { - $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail; - } else { - $tail = ' for "'.$tail; - } - } - $message .= "\nDid you forget a \"use\" statement".$tail; - - return new ClassNotFoundError($message, $error); - } - - return null; - } - - /** - * Tries to guess the full namespace for a given class name. - * - * By default, it looks for PSR-0 and PSR-4 classes registered via a Symfony or a Composer - * autoloader (that should cover all common cases). - * - * @param string $class A class name (without its namespace) - * - * Returns an array of possible fully qualified class names - */ - private function getClassCandidates(string $class): array - { - if (!\is_array($functions = spl_autoload_functions())) { - return []; - } - - // find Symfony and Composer autoloaders - $classes = []; - - foreach ($functions as $function) { - if (!\is_array($function)) { - continue; - } - // get class loaders wrapped by DebugClassLoader - if ($function[0] instanceof DebugClassLoader) { - $function = $function[0]->getClassLoader(); - - if (!\is_array($function)) { - continue; - } - } - - if ($function[0] instanceof ClassLoader) { - foreach ($function[0]->getPrefixes() as $prefix => $paths) { - foreach ($paths as $path) { - $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix)); - } - } - - foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) { - foreach ($paths as $path) { - $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix)); - } - } - } - } - - return array_unique($classes); - } - - private function findClassInPath(string $path, string $class, string $prefix): array - { - if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) { - return []; - } - - $classes = []; - $filename = $class.'.php'; - foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { - if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) { - $classes[] = $class; - } - } - - return $classes; - } - - private function convertFileToClass(string $path, string $file, string $prefix): ?string - { - $candidates = [ - // namespaced class - $namespacedClass = str_replace([$path.\DIRECTORY_SEPARATOR, '.php', '/'], ['', '', '\\'], $file), - // namespaced class (with target dir) - $prefix.$namespacedClass, - // namespaced class (with target dir and separator) - $prefix.'\\'.$namespacedClass, - // PEAR class - str_replace('\\', '_', $namespacedClass), - // PEAR class (with target dir) - str_replace('\\', '_', $prefix.$namespacedClass), - // PEAR class (with target dir and separator) - str_replace('\\', '_', $prefix.'\\'.$namespacedClass), - ]; - - if ($prefix) { - $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); }); - } - - // We cannot use the autoloader here as most of them use require; but if the class - // is not found, the new autoloader call will require the file again leading to a - // "cannot redeclare class" error. - foreach ($candidates as $candidate) { - if ($this->classExists($candidate)) { - return $candidate; - } - } - - try { - require_once $file; - } catch (\Throwable $e) { - return null; - } - - foreach ($candidates as $candidate) { - if ($this->classExists($candidate)) { - return $candidate; - } - } - - return null; - } - - private function classExists(string $class): bool - { - return class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); - } -} diff --git a/vendor/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php b/vendor/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php deleted file mode 100644 index 7c3f4ef..0000000 --- a/vendor/symfony/error-handler/ErrorEnhancer/ErrorEnhancerInterface.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorEnhancer; - -interface ErrorEnhancerInterface -{ - /** - * Returns an \Throwable instance if the class is able to improve the error, null otherwise. - */ - public function enhance(\Throwable $error): ?\Throwable; -} diff --git a/vendor/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php b/vendor/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php deleted file mode 100644 index f4c49c2..0000000 --- a/vendor/symfony/error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorEnhancer; - -use Symfony\Component\ErrorHandler\Error\FatalError; -use Symfony\Component\ErrorHandler\Error\UndefinedFunctionError; - -/** - * @author Fabien Potencier - */ -class UndefinedFunctionErrorEnhancer implements ErrorEnhancerInterface -{ - /** - * {@inheritdoc} - */ - public function enhance(\Throwable $error): ?\Throwable - { - if ($error instanceof FatalError) { - return null; - } - - $message = $error->getMessage(); - $messageLen = \strlen($message); - $notFoundSuffix = '()'; - $notFoundSuffixLen = \strlen($notFoundSuffix); - if ($notFoundSuffixLen > $messageLen) { - return null; - } - - if (0 !== substr_compare($message, $notFoundSuffix, -$notFoundSuffixLen)) { - return null; - } - - $prefix = 'Call to undefined function '; - $prefixLen = \strlen($prefix); - if (0 !== strpos($message, $prefix)) { - return null; - } - - $fullyQualifiedFunctionName = substr($message, $prefixLen, -$notFoundSuffixLen); - if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) { - $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1); - $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex); - $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix); - } else { - $functionName = $fullyQualifiedFunctionName; - $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName); - } - - $candidates = []; - foreach (get_defined_functions() as $type => $definedFunctionNames) { - foreach ($definedFunctionNames as $definedFunctionName) { - if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) { - $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1); - } else { - $definedFunctionNameBasename = $definedFunctionName; - } - - if ($definedFunctionNameBasename === $functionName) { - $candidates[] = '\\'.$definedFunctionName; - } - } - } - - if ($candidates) { - sort($candidates); - $last = array_pop($candidates).'"?'; - if ($candidates) { - $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; - } else { - $candidates = '"'.$last; - } - $message .= "\nDid you mean to call ".$candidates; - } - - return new UndefinedFunctionError($message, $error); - } -} diff --git a/vendor/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php b/vendor/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php deleted file mode 100644 index ad0e4b3..0000000 --- a/vendor/symfony/error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php +++ /dev/null @@ -1,69 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorEnhancer; - -use Symfony\Component\ErrorHandler\Error\FatalError; -use Symfony\Component\ErrorHandler\Error\UndefinedMethodError; - -/** - * @author Grégoire Pineau - */ -class UndefinedMethodErrorEnhancer implements ErrorEnhancerInterface -{ - /** - * {@inheritdoc} - */ - public function enhance(\Throwable $error): ?\Throwable - { - if ($error instanceof FatalError) { - return null; - } - - $message = $error->getMessage(); - preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $message, $matches); - if (!$matches) { - return null; - } - - $className = $matches[1]; - $methodName = $matches[2]; - - $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className); - - if (!class_exists($className) || null === $methods = get_class_methods($className)) { - // failed to get the class or its methods on which an unknown method was called (for example on an anonymous class) - return new UndefinedMethodError($message, $error); - } - - $candidates = []; - foreach ($methods as $definedMethodName) { - $lev = levenshtein($methodName, $definedMethodName); - if ($lev <= \strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) { - $candidates[] = $definedMethodName; - } - } - - if ($candidates) { - sort($candidates); - $last = array_pop($candidates).'"?'; - if ($candidates) { - $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; - } else { - $candidates = '"'.$last; - } - - $message .= "\nDid you mean to call ".$candidates; - } - - return new UndefinedMethodError($message, $error); - } -} diff --git a/vendor/symfony/error-handler/ErrorHandler.php b/vendor/symfony/error-handler/ErrorHandler.php deleted file mode 100644 index f4dcfb1..0000000 --- a/vendor/symfony/error-handler/ErrorHandler.php +++ /dev/null @@ -1,768 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler; - -use Psr\Log\LoggerInterface; -use Psr\Log\LogLevel; -use Symfony\Component\ErrorHandler\Error\FatalError; -use Symfony\Component\ErrorHandler\Error\OutOfMemoryError; -use Symfony\Component\ErrorHandler\ErrorEnhancer\ClassNotFoundErrorEnhancer; -use Symfony\Component\ErrorHandler\ErrorEnhancer\ErrorEnhancerInterface; -use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedFunctionErrorEnhancer; -use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedMethodErrorEnhancer; -use Symfony\Component\ErrorHandler\ErrorRenderer\CliErrorRenderer; -use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; -use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; - -/** - * A generic ErrorHandler for the PHP engine. - * - * Provides five bit fields that control how errors are handled: - * - thrownErrors: errors thrown as \ErrorException - * - loggedErrors: logged errors, when not @-silenced - * - scopedErrors: errors thrown or logged with their local context - * - tracedErrors: errors logged with their stack trace - * - screamedErrors: never @-silenced errors - * - * Each error level can be logged by a dedicated PSR-3 logger object. - * Screaming only applies to logging. - * Throwing takes precedence over logging. - * Uncaught exceptions are logged as E_ERROR. - * E_DEPRECATED and E_USER_DEPRECATED levels never throw. - * E_RECOVERABLE_ERROR and E_USER_ERROR levels always throw. - * Non catchable errors that can be detected at shutdown time are logged when the scream bit field allows so. - * As errors have a performance cost, repeated errors are all logged, so that the developer - * can see them and weight them as more important to fix than others of the same level. - * - * @author Nicolas Grekas - * @author Grégoire Pineau - * - * @final - */ -class ErrorHandler -{ - private $levels = [ - E_DEPRECATED => 'Deprecated', - E_USER_DEPRECATED => 'User Deprecated', - E_NOTICE => 'Notice', - E_USER_NOTICE => 'User Notice', - E_STRICT => 'Runtime Notice', - E_WARNING => 'Warning', - E_USER_WARNING => 'User Warning', - E_COMPILE_WARNING => 'Compile Warning', - E_CORE_WARNING => 'Core Warning', - E_USER_ERROR => 'User Error', - E_RECOVERABLE_ERROR => 'Catchable Fatal Error', - E_COMPILE_ERROR => 'Compile Error', - E_PARSE => 'Parse Error', - E_ERROR => 'Error', - E_CORE_ERROR => 'Core Error', - ]; - - private $loggers = [ - E_DEPRECATED => [null, LogLevel::INFO], - E_USER_DEPRECATED => [null, LogLevel::INFO], - E_NOTICE => [null, LogLevel::WARNING], - E_USER_NOTICE => [null, LogLevel::WARNING], - E_STRICT => [null, LogLevel::WARNING], - E_WARNING => [null, LogLevel::WARNING], - E_USER_WARNING => [null, LogLevel::WARNING], - E_COMPILE_WARNING => [null, LogLevel::WARNING], - E_CORE_WARNING => [null, LogLevel::WARNING], - E_USER_ERROR => [null, LogLevel::CRITICAL], - E_RECOVERABLE_ERROR => [null, LogLevel::CRITICAL], - E_COMPILE_ERROR => [null, LogLevel::CRITICAL], - E_PARSE => [null, LogLevel::CRITICAL], - E_ERROR => [null, LogLevel::CRITICAL], - E_CORE_ERROR => [null, LogLevel::CRITICAL], - ]; - - private $thrownErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED - private $scopedErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED - private $tracedErrors = 0x77FB; // E_ALL - E_STRICT - E_PARSE - private $screamedErrors = 0x55; // E_ERROR + E_CORE_ERROR + E_COMPILE_ERROR + E_PARSE - private $loggedErrors = 0; - private $traceReflector; - - private $isRecursive = 0; - private $isRoot = false; - private $exceptionHandler; - private $bootstrappingLogger; - - private static $reservedMemory; - private static $toStringException; - private static $silencedErrorCache = []; - private static $silencedErrorCount = 0; - private static $exitCode = 0; - - /** - * Registers the error handler. - */ - public static function register(self $handler = null, bool $replace = true): self - { - if (null === self::$reservedMemory) { - self::$reservedMemory = str_repeat('x', 10240); - register_shutdown_function(__CLASS__.'::handleFatalError'); - } - - if ($handlerIsNew = null === $handler) { - $handler = new static(); - } - - if (null === $prev = set_error_handler([$handler, 'handleError'])) { - restore_error_handler(); - // Specifying the error types earlier would expose us to https://bugs.php.net/63206 - set_error_handler([$handler, 'handleError'], $handler->thrownErrors | $handler->loggedErrors); - $handler->isRoot = true; - } - - if ($handlerIsNew && \is_array($prev) && $prev[0] instanceof self) { - $handler = $prev[0]; - $replace = false; - } - if (!$replace && $prev) { - restore_error_handler(); - $handlerIsRegistered = \is_array($prev) && $handler === $prev[0]; - } else { - $handlerIsRegistered = true; - } - if (\is_array($prev = set_exception_handler([$handler, 'handleException'])) && $prev[0] instanceof self) { - restore_exception_handler(); - if (!$handlerIsRegistered) { - $handler = $prev[0]; - } elseif ($handler !== $prev[0] && $replace) { - set_exception_handler([$handler, 'handleException']); - $p = $prev[0]->setExceptionHandler(null); - $handler->setExceptionHandler($p); - $prev[0]->setExceptionHandler($p); - } - } else { - $handler->setExceptionHandler($prev ?? [$handler, 'renderException']); - } - - $handler->throwAt(E_ALL & $handler->thrownErrors, true); - - return $handler; - } - - /** - * Calls a function and turns any PHP error into \ErrorException. - * - * @return mixed What $function(...$arguments) returns - * - * @throws \ErrorException When $function(...$arguments) triggers a PHP error - */ - public static function call(callable $function, ...$arguments) - { - set_error_handler(static function (int $type, string $message, string $file, int $line) { - if (__FILE__ === $file) { - $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3); - $file = $trace[2]['file'] ?? $file; - $line = $trace[2]['line'] ?? $line; - } - - throw new \ErrorException($message, 0, $type, $file, $line); - }); - - try { - return $function(...$arguments); - } finally { - restore_error_handler(); - } - } - - public function __construct(BufferingLogger $bootstrappingLogger = null) - { - if ($bootstrappingLogger) { - $this->bootstrappingLogger = $bootstrappingLogger; - $this->setDefaultLogger($bootstrappingLogger); - } - $this->traceReflector = new \ReflectionProperty('Exception', 'trace'); - $this->traceReflector->setAccessible(true); - } - - /** - * Sets a logger to non assigned errors levels. - * - * @param LoggerInterface $logger A PSR-3 logger to put as default for the given levels - * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants - * @param bool $replace Whether to replace or not any existing logger - */ - public function setDefaultLogger(LoggerInterface $logger, $levels = E_ALL, bool $replace = false): void - { - $loggers = []; - - if (\is_array($levels)) { - foreach ($levels as $type => $logLevel) { - if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) { - $loggers[$type] = [$logger, $logLevel]; - } - } - } else { - if (null === $levels) { - $levels = E_ALL; - } - foreach ($this->loggers as $type => $log) { - if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) { - $log[0] = $logger; - $loggers[$type] = $log; - } - } - } - - $this->setLoggers($loggers); - } - - /** - * Sets a logger for each error level. - * - * @param array $loggers Error levels to [LoggerInterface|null, LogLevel::*] map - * - * @return array The previous map - * - * @throws \InvalidArgumentException - */ - public function setLoggers(array $loggers): array - { - $prevLogged = $this->loggedErrors; - $prev = $this->loggers; - $flush = []; - - foreach ($loggers as $type => $log) { - if (!isset($prev[$type])) { - throw new \InvalidArgumentException('Unknown error type: '.$type); - } - if (!\is_array($log)) { - $log = [$log]; - } elseif (!\array_key_exists(0, $log)) { - throw new \InvalidArgumentException('No logger provided'); - } - if (null === $log[0]) { - $this->loggedErrors &= ~$type; - } elseif ($log[0] instanceof LoggerInterface) { - $this->loggedErrors |= $type; - } else { - throw new \InvalidArgumentException('Invalid logger provided'); - } - $this->loggers[$type] = $log + $prev[$type]; - - if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) { - $flush[$type] = $type; - } - } - $this->reRegister($prevLogged | $this->thrownErrors); - - if ($flush) { - foreach ($this->bootstrappingLogger->cleanLogs() as $log) { - $type = ThrowableUtils::getSeverity($log[2]['exception']); - if (!isset($flush[$type])) { - $this->bootstrappingLogger->log($log[0], $log[1], $log[2]); - } elseif ($this->loggers[$type][0]) { - $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]); - } - } - } - - return $prev; - } - - /** - * Sets a user exception handler. - * - * @param callable(\Throwable $e)|null $handler - * - * @return callable|null The previous exception handler - */ - public function setExceptionHandler(?callable $handler): ?callable - { - $prev = $this->exceptionHandler; - $this->exceptionHandler = $handler; - - return $prev; - } - - /** - * Sets the PHP error levels that throw an exception when a PHP error occurs. - * - * @param int $levels A bit field of E_* constants for thrown errors - * @param bool $replace Replace or amend the previous value - * - * @return int The previous value - */ - public function throwAt(int $levels, bool $replace = false): int - { - $prev = $this->thrownErrors; - $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED; - if (!$replace) { - $this->thrownErrors |= $prev; - } - $this->reRegister($prev | $this->loggedErrors); - - return $prev; - } - - /** - * Sets the PHP error levels for which local variables are preserved. - * - * @param int $levels A bit field of E_* constants for scoped errors - * @param bool $replace Replace or amend the previous value - * - * @return int The previous value - */ - public function scopeAt(int $levels, bool $replace = false): int - { - $prev = $this->scopedErrors; - $this->scopedErrors = $levels; - if (!$replace) { - $this->scopedErrors |= $prev; - } - - return $prev; - } - - /** - * Sets the PHP error levels for which the stack trace is preserved. - * - * @param int $levels A bit field of E_* constants for traced errors - * @param bool $replace Replace or amend the previous value - * - * @return int The previous value - */ - public function traceAt(int $levels, bool $replace = false): int - { - $prev = $this->tracedErrors; - $this->tracedErrors = (int) $levels; - if (!$replace) { - $this->tracedErrors |= $prev; - } - - return $prev; - } - - /** - * Sets the error levels where the @-operator is ignored. - * - * @param int $levels A bit field of E_* constants for screamed errors - * @param bool $replace Replace or amend the previous value - * - * @return int The previous value - */ - public function screamAt(int $levels, bool $replace = false): int - { - $prev = $this->screamedErrors; - $this->screamedErrors = $levels; - if (!$replace) { - $this->screamedErrors |= $prev; - } - - return $prev; - } - - /** - * Re-registers as a PHP error handler if levels changed. - */ - private function reRegister(int $prev): void - { - if ($prev !== $this->thrownErrors | $this->loggedErrors) { - $handler = set_error_handler('var_dump'); - $handler = \is_array($handler) ? $handler[0] : null; - restore_error_handler(); - if ($handler === $this) { - restore_error_handler(); - if ($this->isRoot) { - set_error_handler([$this, 'handleError'], $this->thrownErrors | $this->loggedErrors); - } else { - set_error_handler([$this, 'handleError']); - } - } - } - } - - /** - * Handles errors by filtering then logging them according to the configured bit fields. - * - * @return bool Returns false when no handling happens so that the PHP engine can handle the error itself - * - * @throws \ErrorException When $this->thrownErrors requests so - * - * @internal - */ - public function handleError(int $type, string $message, string $file, int $line): bool - { - if (\PHP_VERSION_ID >= 70300 && E_WARNING === $type && '"' === $message[0] && false !== strpos($message, '" targeting switch is equivalent to "break')) { - $type = E_DEPRECATED; - } - - // Level is the current error reporting level to manage silent error. - $level = error_reporting(); - $silenced = 0 === ($level & $type); - // Strong errors are not authorized to be silenced. - $level |= E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED; - $log = $this->loggedErrors & $type; - $throw = $this->thrownErrors & $type & $level; - $type &= $level | $this->screamedErrors; - - if (!$type || (!$log && !$throw)) { - return !$silenced && $type && $log; - } - $scope = $this->scopedErrors & $type; - - if (4 < $numArgs = \func_num_args()) { - $context = $scope ? (func_get_arg(4) ?: []) : []; - } else { - $context = []; - } - - if (isset($context['GLOBALS']) && $scope) { - $e = $context; // Whatever the signature of the method, - unset($e['GLOBALS'], $context); // $context is always a reference in 5.3 - $context = $e; - } - - if (false !== strpos($message, "class@anonymous\0")) { - $logMessage = $this->parseAnonymousClass($message); - } else { - $logMessage = $this->levels[$type].': '.$message; - } - - if (null !== self::$toStringException) { - $errorAsException = self::$toStringException; - self::$toStringException = null; - } elseif (!$throw && !($type & $level)) { - if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) { - $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5), $type, $file, $line, false) : []; - $errorAsException = new SilencedErrorContext($type, $file, $line, isset($lightTrace[1]) ? [$lightTrace[0]] : $lightTrace); - } elseif (isset(self::$silencedErrorCache[$id][$message])) { - $lightTrace = null; - $errorAsException = self::$silencedErrorCache[$id][$message]; - ++$errorAsException->count; - } else { - $lightTrace = []; - $errorAsException = null; - } - - if (100 < ++self::$silencedErrorCount) { - self::$silencedErrorCache = $lightTrace = []; - self::$silencedErrorCount = 1; - } - if ($errorAsException) { - self::$silencedErrorCache[$id][$message] = $errorAsException; - } - if (null === $lightTrace) { - return true; - } - } else { - $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line); - - if ($throw || $this->tracedErrors & $type) { - $backtrace = $errorAsException->getTrace(); - $lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw); - $this->traceReflector->setValue($errorAsException, $lightTrace); - } else { - $this->traceReflector->setValue($errorAsException, []); - $backtrace = []; - } - } - - if ($throw) { - if (\PHP_VERSION_ID < 70400 && E_USER_ERROR & $type) { - for ($i = 1; isset($backtrace[$i]); ++$i) { - if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function']) - && '__toString' === $backtrace[$i]['function'] - && '->' === $backtrace[$i]['type'] - && !isset($backtrace[$i - 1]['class']) - && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function']) - ) { - // Here, we know trigger_error() has been called from __toString(). - // PHP triggers a fatal error when throwing from __toString(). - // A small convention allows working around the limitation: - // given a caught $e exception in __toString(), quitting the method with - // `return trigger_error($e, E_USER_ERROR);` allows this error handler - // to make $e get through the __toString() barrier. - - foreach ($context as $e) { - if ($e instanceof \Throwable && $e->__toString() === $message) { - self::$toStringException = $e; - - return true; - } - } - - // Display the original error message instead of the default one. - $this->handleException($errorAsException); - - // Stop the process by giving back the error to the native handler. - return false; - } - } - } - - throw $errorAsException; - } - - if ($this->isRecursive) { - $log = 0; - } else { - if (!\defined('HHVM_VERSION')) { - $currentErrorHandler = set_error_handler('var_dump'); - restore_error_handler(); - } - - try { - $this->isRecursive = true; - $level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG; - $this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? ['exception' => $errorAsException] : []); - } finally { - $this->isRecursive = false; - - if (!\defined('HHVM_VERSION')) { - set_error_handler($currentErrorHandler); - } - } - } - - return !$silenced && $type && $log; - } - - /** - * Handles an exception by logging then forwarding it to another handler. - * - * @internal - */ - public function handleException(\Throwable $exception) - { - $handlerException = null; - - if (!$exception instanceof FatalError) { - self::$exitCode = 255; - - $type = ThrowableUtils::getSeverity($exception); - } else { - $type = $exception->getError()['type']; - } - - if ($this->loggedErrors & $type) { - if (false !== strpos($message = $exception->getMessage(), "class@anonymous\0")) { - $message = $this->parseAnonymousClass($message); - } - - if ($exception instanceof FatalError) { - $message = 'Fatal '.$message; - } elseif ($exception instanceof \Error) { - $message = 'Uncaught Error: '.$message; - } elseif ($exception instanceof \ErrorException) { - $message = 'Uncaught '.$message; - } else { - $message = 'Uncaught Exception: '.$message; - } - - try { - $this->loggers[$type][0]->log($this->loggers[$type][1], $message, ['exception' => $exception]); - } catch (\Throwable $handlerException) { - } - } - - if (!$exception instanceof OutOfMemoryError) { - foreach ($this->getErrorEnhancers() as $errorEnhancer) { - if ($e = $errorEnhancer->enhance($exception)) { - $exception = $e; - break; - } - } - } - - $exceptionHandler = $this->exceptionHandler; - $this->exceptionHandler = [$this, 'renderException']; - - if (null === $exceptionHandler || $exceptionHandler === $this->exceptionHandler) { - $this->exceptionHandler = null; - } - - try { - if (null !== $exceptionHandler) { - return $exceptionHandler($exception); - } - $handlerException = $handlerException ?: $exception; - } catch (\Throwable $handlerException) { - } - if ($exception === $handlerException && null === $this->exceptionHandler) { - self::$reservedMemory = null; // Disable the fatal error handler - throw $exception; // Give back $exception to the native handler - } - - $loggedErrors = $this->loggedErrors; - $this->loggedErrors = $exception === $handlerException ? 0 : $this->loggedErrors; - - try { - $this->handleException($handlerException); - } finally { - $this->loggedErrors = $loggedErrors; - } - } - - /** - * Shutdown registered function for handling PHP fatal errors. - * - * @param array|null $error An array as returned by error_get_last() - * - * @internal - */ - public static function handleFatalError(array $error = null): void - { - if (null === self::$reservedMemory) { - return; - } - - $handler = self::$reservedMemory = null; - $handlers = []; - $previousHandler = null; - $sameHandlerLimit = 10; - - while (!\is_array($handler) || !$handler[0] instanceof self) { - $handler = set_exception_handler('var_dump'); - restore_exception_handler(); - - if (!$handler) { - break; - } - restore_exception_handler(); - - if ($handler !== $previousHandler) { - array_unshift($handlers, $handler); - $previousHandler = $handler; - } elseif (0 === --$sameHandlerLimit) { - $handler = null; - break; - } - } - foreach ($handlers as $h) { - set_exception_handler($h); - } - if (!$handler) { - return; - } - if ($handler !== $h) { - $handler[0]->setExceptionHandler($h); - } - $handler = $handler[0]; - $handlers = []; - - if ($exit = null === $error) { - $error = error_get_last(); - } - - if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) { - // Let's not throw anymore but keep logging - $handler->throwAt(0, true); - $trace = isset($error['backtrace']) ? $error['backtrace'] : null; - - if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) { - $fatalError = new OutOfMemoryError($handler->levels[$error['type']].': '.$error['message'], 0, $error, 2, false, $trace); - } else { - $fatalError = new FatalError($handler->levels[$error['type']].': '.$error['message'], 0, $error, 2, true, $trace); - } - } else { - $fatalError = null; - } - - try { - if (null !== $fatalError) { - self::$exitCode = 255; - $handler->handleException($fatalError); - } - } catch (FatalError $e) { - // Ignore this re-throw - } - - if ($exit && self::$exitCode) { - $exitCode = self::$exitCode; - register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); }); - } - } - - /** - * Renders the given exception. - * - * As this method is mainly called during boot where nothing is yet available, - * the output is always either HTML or CLI depending where PHP runs. - */ - private function renderException(\Throwable $exception): void - { - $renderer = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliErrorRenderer() : new HtmlErrorRenderer(0 !== $this->scopedErrors); - - $exception = $renderer->render($exception); - - if (!headers_sent()) { - http_response_code($exception->getStatusCode()); - - foreach ($exception->getHeaders() as $name => $value) { - header($name.': '.$value, false); - } - } - - echo $exception->getAsString(); - } - - /** - * Override this method if you want to define more error enhancers. - * - * @return ErrorEnhancerInterface[] - */ - protected function getErrorEnhancers(): iterable - { - return [ - new UndefinedFunctionErrorEnhancer(), - new UndefinedMethodErrorEnhancer(), - new ClassNotFoundErrorEnhancer(), - ]; - } - - /** - * Cleans the trace by removing function arguments and the frames added by the error handler and DebugClassLoader. - */ - private function cleanTrace(array $backtrace, int $type, string $file, int $line, bool $throw): array - { - $lightTrace = $backtrace; - - for ($i = 0; isset($backtrace[$i]); ++$i) { - if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { - $lightTrace = \array_slice($lightTrace, 1 + $i); - break; - } - } - if (class_exists(DebugClassLoader::class, false)) { - for ($i = \count($lightTrace) - 2; 0 < $i; --$i) { - if (DebugClassLoader::class === ($lightTrace[$i]['class'] ?? null)) { - array_splice($lightTrace, --$i, 2); - } - } - } - if (!($throw || $this->scopedErrors & $type)) { - for ($i = 0; isset($lightTrace[$i]); ++$i) { - unset($lightTrace[$i]['args'], $lightTrace[$i]['object']); - } - } - - return $lightTrace; - } - - /** - * Parse the error message by removing the anonymous class notation - * and using the parent class instead if possible. - */ - private function parseAnonymousClass(string $message): string - { - return preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:)[0-9a-fA-F]++/', static function ($m) { - return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0]; - }, $message); - } -} diff --git a/vendor/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php b/vendor/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php deleted file mode 100644 index aa132d1..0000000 --- a/vendor/symfony/error-handler/ErrorRenderer/CliErrorRenderer.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorRenderer; - -use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\VarDumper\Cloner\VarCloner; -use Symfony\Component\VarDumper\Dumper\CliDumper; - -/** - * @author Nicolas Grekas - */ -class CliErrorRenderer implements ErrorRendererInterface -{ - /** - * {@inheritdoc} - */ - public function render(\Throwable $exception): FlattenException - { - $cloner = new VarCloner(); - $dumper = new class() extends CliDumper { - protected function supportsColors(): bool - { - $outputStream = $this->outputStream; - $this->outputStream = fopen('php://stdout', 'w'); - - try { - return parent::supportsColors(); - } finally { - $this->outputStream = $outputStream; - } - } - }; - - return FlattenException::createFromThrowable($exception) - ->setAsString($dumper->dump($cloner->cloneVar($exception), true)); - } -} diff --git a/vendor/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php b/vendor/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php deleted file mode 100644 index aba1966..0000000 --- a/vendor/symfony/error-handler/ErrorRenderer/ErrorRendererInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorRenderer; - -use Symfony\Component\ErrorHandler\Exception\FlattenException; - -/** - * Formats an exception to be used as response content. - * - * @author Yonel Ceruto - */ -interface ErrorRendererInterface -{ - /** - * Renders a Throwable as a FlattenException. - */ - public function render(\Throwable $exception): FlattenException; -} diff --git a/vendor/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php b/vendor/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php deleted file mode 100644 index 883a94f..0000000 --- a/vendor/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php +++ /dev/null @@ -1,350 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorRenderer; - -use Psr\Log\LoggerInterface; -use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; - -/** - * @author Yonel Ceruto - */ -class HtmlErrorRenderer implements ErrorRendererInterface -{ - private const GHOST_ADDONS = [ - '02-14' => self::GHOST_HEART, - '02-29' => self::GHOST_PLUS, - '10-18' => self::GHOST_GIFT, - ]; - - private const GHOST_GIFT = 'M124.00534057617188,5.3606138080358505 C124.40059661865234,4.644828304648399 125.1237564086914,3.712414965033531 123.88127899169922,3.487462028861046 C123.53517150878906,3.3097832053899765 123.18894958496094,2.9953975528478622 122.8432846069336,3.345616325736046 C122.07421112060547,3.649444565176964 121.40750122070312,4.074306473135948 122.2164306640625,4.869479164481163 C122.57514953613281,5.3830065578222275 122.90142822265625,6.503447040915489 123.3077621459961,6.626829609274864 C123.55027770996094,6.210384353995323 123.7774658203125,5.785196766257286 124.00534057617188,5.3606138080358505 zM122.30630493164062,7.336987480521202 C121.60028076171875,6.076864704489708 121.03211975097656,4.72498320043087 120.16796875,3.562500938773155 C119.11695098876953,2.44033907353878 117.04605865478516,2.940566048026085 116.57544708251953,4.387995228171349 C115.95028686523438,5.819030746817589 117.2991714477539,7.527640804648399 118.826171875,7.348545059561729 C119.98493194580078,7.367936596274376 121.15027618408203,7.420116886496544 122.30630493164062,7.336987480521202 zM128.1732177734375,7.379541382193565 C129.67486572265625,7.17823551595211 130.53842163085938,5.287807449698448 129.68344116210938,4.032590612769127 C128.92578125,2.693056806921959 126.74605560302734,2.6463639587163925 125.98509216308594,4.007616028189659 C125.32617950439453,5.108129009604454 124.75428009033203,6.258124336600304 124.14962768554688,7.388818249106407 C125.48638916015625,7.465229496359825 126.8357162475586,7.447416767477989 128.1732177734375,7.379541382193565 zM130.6601104736328,8.991325363516808 C131.17202758789062,8.540884003043175 133.1543731689453,8.009847149252892 131.65304565429688,7.582054600119591 C131.2811279296875,7.476506695151329 130.84751892089844,6.99234913289547 130.5132598876953,7.124847874045372 C129.78744506835938,8.02728746831417 128.67140197753906,8.55669592320919 127.50616455078125,8.501235947012901 C127.27806091308594,8.576229080557823 126.11459350585938,8.38720129430294 126.428955078125,8.601900085806847 C127.25099182128906,9.070617660880089 128.0523223876953,9.579657539725304 128.902587890625,9.995706543326378 C129.49813842773438,9.678531631827354 130.0761260986328,9.329126343131065 130.6601104736328,8.991325363516808 zM118.96446990966797,9.246344551444054 C119.4022445678711,8.991325363516808 119.84001922607422,8.736305221915245 120.27779388427734,8.481284126639366 C118.93965911865234,8.414779648184776 117.40827941894531,8.607666000723839 116.39698791503906,7.531384453177452 C116.11186981201172,7.212117180228233 115.83845520019531,6.846597656607628 115.44329071044922,7.248530372977257 C114.96995544433594,7.574637398123741 113.5140609741211,7.908811077475548 114.63501739501953,8.306883797049522 C115.61112976074219,8.883499130606651 116.58037567138672,9.474181160330772 117.58061218261719,10.008124336600304 C118.05723571777344,9.784612640738487 118.50651550292969,9.5052699893713 118.96446990966797,9.246344551444054 zM125.38018035888672,12.091858848929405 C125.9474868774414,11.636047348380089 127.32159423828125,11.201767906546593 127.36749267578125,10.712632164359093 C126.08487701416016,9.974547371268272 124.83960723876953,9.152772888541222 123.49772644042969,8.528907760977745 C123.03594207763672,8.353693947196007 122.66152954101562,8.623294815421104 122.28982543945312,8.857431396842003 C121.19065856933594,9.51122473180294 120.06505584716797,10.12446115911007 119.00167083740234,10.835315689444542 C120.39238739013672,11.69529627263546 121.79983520507812,12.529837593436241 123.22095489501953,13.338589653372765 C123.94580841064453,12.932025894522667 124.66128540039062,12.508862480521202 125.38018035888672,12.091858848929405 zM131.07164001464844,13.514615997672081 C131.66018676757812,13.143282875418663 132.2487335205078,12.771927818655968 132.8372802734375,12.400571808218956 C132.8324737548828,11.156818374991417 132.8523406982422,9.912529930472374 132.81829833984375,8.669195160269737 C131.63046264648438,9.332009300589561 130.45948791503906,10.027913078665733 129.30828857421875,10.752535805106163 C129.182373046875,12.035354599356651 129.24623107910156,13.33940313756466 129.27359008789062,14.628684982657433 C129.88104248046875,14.27079389989376 130.4737548828125,13.888019546866417 131.07164001464844,13.514640793204308 zM117.26847839355469,12.731024727225304 C117.32825469970703,11.67083452641964 117.45709991455078,10.46224020421505 116.17853546142578,10.148179039359093 C115.37110900878906,9.77159021794796 114.25194549560547,8.806716904044151 113.62991333007812,8.81639002263546 C113.61052703857422,10.0110072940588 113.62078857421875,11.20585821568966 113.61869049072266,12.400571808218956 C114.81139373779297,13.144886955618858 115.98292541503906,13.925040230154991 117.20137023925781,14.626662239432335 C117.31951141357422,14.010867103934288 117.24227905273438,13.35805033147335 117.26847839355469,12.731024727225304 zM125.80937957763672,16.836034759879112 C126.51483917236328,16.390663132071495 127.22030639648438,15.945291504263878 127.92576599121094,15.49991987645626 C127.92250061035156,14.215868934988976 127.97560119628906,12.929980263113976 127.91757202148438,11.647302612662315 C127.14225769042969,11.869626984000206 126.25550079345703,12.556857094168663 125.43866729736328,12.983742699027061 C124.82704162597656,13.342005714774132 124.21542358398438,13.700271591544151 123.60379028320312,14.05853746831417 C123.61585235595703,15.429577812552452 123.57081604003906,16.803131088614464 123.64839172363281,18.172149643301964 C124.37957000732422,17.744937881827354 125.09130859375,17.284801468253136 125.80937957763672,16.836034759879112 zM122.8521499633789,16.115344032645226 C122.8521499633789,15.429741844534874 122.8521499633789,14.744139656424522 122.8521499633789,14.05853746831417 C121.43595123291016,13.230924591422081 120.02428436279297,12.395455345511436 118.60256958007812,11.577354416251183 C118.52394104003906,12.888403877615929 118.56887817382812,14.204405769705772 118.55702209472656,15.517732605338097 C119.97289276123047,16.4041957706213 121.37410736083984,17.314891800284386 122.80789947509766,18.172149643301964 C122.86368560791016,17.488990768790245 122.84332275390625,16.800363525748253 122.8521499633789,16.115344032645226 zM131.10684204101562,18.871450409293175 C131.68399047851562,18.48711584508419 132.2611541748047,18.10278509557247 132.8383026123047,17.718475326895714 C132.81423950195312,16.499977096915245 132.89776611328125,15.264989838004112 132.77627563476562,14.05993078649044 C131.5760040283203,14.744719490408897 130.41763305664062,15.524359688162804 129.23875427246094,16.255397781729698 C129.26707458496094,17.516149505972862 129.18060302734375,18.791316971182823 129.3108367919922,20.041303619742393 C129.91973876953125,19.667551025748253 130.51010131835938,19.264152511954308 131.10684204101562,18.871450409293175 zM117.2557373046875,18.188333496451378 C117.25104522705078,17.549470886588097 117.24633026123047,16.91058538854122 117.24163055419922,16.271720871329308 C116.04924774169922,15.525708183646202 114.87187957763672,14.75476549565792 113.66158294677734,14.038097366690636 C113.5858383178711,15.262084946036339 113.62901306152344,16.49083898961544 113.61761474609375,17.717010483145714 C114.82051086425781,18.513254150748253 116.00987243652344,19.330610260367393 117.22888946533203,20.101993545889854 C117.27559661865234,19.466014847159386 117.25241088867188,18.825733169913292 117.2557373046875,18.188333496451378 zM125.8398666381836,22.38675306737423 C126.54049682617188,21.921453461050987 127.24110412597656,21.456151947379112 127.94172668457031,20.99083136022091 C127.94009399414062,19.693386062979698 127.96646118164062,18.395381912589073 127.93160247802734,17.098379120230675 C126.50540924072266,17.97775076329708 125.08877563476562,18.873308166861534 123.68258666992188,19.78428266942501 C123.52366638183594,21.03710363805294 123.626708984375,22.32878302037716 123.62647247314453,23.595300659537315 C124.06291198730469,23.86113165318966 125.1788101196289,22.68297766149044 125.8398666381836,22.38675306737423 zM122.8521499633789,21.83134649693966 C122.76741790771484,20.936696991324425 123.21651458740234,19.67745779454708 122.0794677734375,19.330633148550987 C120.93280029296875,18.604360565543175 119.7907485961914,17.870157226920128 118.62899780273438,17.16818617284298 C118.45966339111328,18.396427139639854 118.63676452636719,19.675991043448448 118.50668334960938,20.919256195425987 C119.89984130859375,21.92635916173458 121.32942199707031,22.88914106786251 122.78502655029297,23.803510650992393 C122.90177917480469,23.1627406924963 122.82917022705078,22.48402212560177 122.8521499633789,21.83134649693966 zM117.9798355102539,21.59483526647091 C116.28416442871094,20.46288488805294 114.58848571777344,19.330957397818565 112.892822265625,18.199007019400597 C112.89473724365234,14.705654129385948 112.84647369384766,11.211485847830772 112.90847778320312,7.718807205557823 C113.7575912475586,7.194885239005089 114.66117858886719,6.765397056937218 115.5350341796875,6.284702762961388 C114.97061157226562,4.668964847922325 115.78496551513672,2.7054970115423203 117.42159271240234,2.1007001250982285 C118.79354095458984,1.537783369421959 120.44731903076172,2.0457767099142075 121.32200622558594,3.23083733022213 C121.95732116699219,2.9050118774175644 122.59264373779297,2.5791852325201035 123.22796630859375,2.253336176276207 C123.86669921875,2.5821153968572617 124.50543975830078,2.9108948558568954 125.1441650390625,3.23967407643795 C126.05941009521484,2.154020771384239 127.62747192382812,1.5344576686620712 128.986328125,2.1429056972265244 C130.61741638183594,2.716217741370201 131.50650024414062,4.675290569663048 130.9215545654297,6.2884936183691025 C131.8018341064453,6.78548763692379 132.7589111328125,7.1738648265600204 133.5660400390625,7.780336365103722 C133.60182189941406,11.252970680594444 133.56637573242188,14.726140961050987 133.5631103515625,18.199007019400597 C130.18914794921875,20.431867584586143 126.86984252929688,22.74994657933712 123.44108581542969,24.897907242178917 C122.44406127929688,24.897628769278526 121.5834732055664,23.815067276358604 120.65831756591797,23.37616156041622 C119.76387023925781,22.784828171133995 118.87168884277344,22.19007681310177 117.9798355102539,21.59483526647091 z'; - private const GHOST_HEART = 'M125.91386369681868,8.305165958366445 C128.95033202169043,-0.40540639102854037 140.8469835342744,8.305165958366445 125.91386369681868,19.504526138305664 C110.98208663272044,8.305165958366445 122.87795231771452,-0.40540639102854037 125.91386369681868,8.305165958366445 z'; - private const GHOST_PLUS = 'M111.36824226379395,8.969108581542969 L118.69175148010254,8.969108581542969 L118.69175148010254,1.6455793380737305 L126.20429420471191,1.6455793380737305 L126.20429420471191,8.969108581542969 L133.52781105041504,8.969108581542969 L133.52781105041504,16.481630325317383 L126.20429420471191,16.481630325317383 L126.20429420471191,23.805158615112305 L118.69175148010254,23.805158615112305 L118.69175148010254,16.481630325317383 L111.36824226379395,16.481630325317383 z'; - - private $debug; - private $charset; - private $fileLinkFormat; - private $projectDir; - private $outputBuffer; - private $logger; - - /** - * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it - * @param bool|callable $outputBuffer The output buffer as a string or a callable that should return it - */ - public function __construct($debug = false, string $charset = null, $fileLinkFormat = null, string $projectDir = null, $outputBuffer = '', LoggerInterface $logger = null) - { - if (!\is_bool($debug) && !\is_callable($debug)) { - throw new \TypeError(sprintf('Argument 1 passed to %s() must be a boolean or a callable, %s given.', __METHOD__, \is_object($debug) ? \get_class($debug) : \gettype($debug))); - } - - if (!\is_string($outputBuffer) && !\is_callable($outputBuffer)) { - throw new \TypeError(sprintf('Argument 5 passed to %s() must be a string or a callable, %s given.', __METHOD__, \is_object($outputBuffer) ? \get_class($outputBuffer) : \gettype($outputBuffer))); - } - - $this->debug = $debug; - $this->charset = $charset ?: (ini_get('default_charset') ?: 'UTF-8'); - $this->fileLinkFormat = $fileLinkFormat ?: (ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')); - $this->projectDir = $projectDir; - $this->outputBuffer = $outputBuffer; - $this->logger = $logger; - } - - /** - * {@inheritdoc} - */ - public function render(\Throwable $exception): FlattenException - { - $exception = FlattenException::createFromThrowable($exception, null, [ - 'Content-Type' => 'text/html; charset='.$this->charset, - ]); - - return $exception->setAsString($this->renderException($exception)); - } - - /** - * Gets the HTML content associated with the given exception. - */ - public function getBody(FlattenException $exception): string - { - return $this->renderException($exception, 'views/exception.html.php'); - } - - /** - * Gets the stylesheet associated with the given exception. - */ - public function getStylesheet(): string - { - if (!$this->debug) { - return $this->include('assets/css/error.css'); - } - - return $this->include('assets/css/exception.css'); - } - - public static function isDebug(RequestStack $requestStack, bool $debug): \Closure - { - return static function () use ($requestStack, $debug): bool { - if (!$request = $requestStack->getCurrentRequest()) { - return $debug; - } - - return $debug && $request->attributes->getBoolean('showException', true); - }; - } - - public static function getAndCleanOutputBuffer(RequestStack $requestStack): \Closure - { - return static function () use ($requestStack): string { - if (!$request = $requestStack->getCurrentRequest()) { - return ''; - } - - $startObLevel = $request->headers->get('X-Php-Ob-Level', -1); - - if (ob_get_level() <= $startObLevel) { - return ''; - } - - Response::closeOutputBuffers($startObLevel + 1, true); - - return ob_get_clean(); - }; - } - - private function renderException(FlattenException $exception, string $debugTemplate = 'views/exception_full.html.php'): string - { - $debug = \is_bool($this->debug) ? $this->debug : ($this->debug)($exception); - $statusText = $this->escape($exception->getStatusText()); - $statusCode = $this->escape($exception->getStatusCode()); - - if (!$debug) { - return $this->include('views/error.html.php', [ - 'statusText' => $statusText, - 'statusCode' => $statusCode, - ]); - } - - $exceptionMessage = $this->escape($exception->getMessage()); - - return $this->include($debugTemplate, [ - 'exception' => $exception, - 'exceptionMessage' => $exceptionMessage, - 'statusText' => $statusText, - 'statusCode' => $statusCode, - 'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null, - 'currentContent' => \is_string($this->outputBuffer) ? $this->outputBuffer : ($this->outputBuffer)(), - ]); - } - - /** - * Formats an array as a string. - */ - private function formatArgs(array $args): string - { - $result = []; - foreach ($args as $key => $item) { - if ('object' === $item[0]) { - $formattedValue = sprintf('object(%s)', $this->abbrClass($item[1])); - } elseif ('array' === $item[0]) { - $formattedValue = sprintf('array(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); - } elseif ('null' === $item[0]) { - $formattedValue = 'null'; - } elseif ('boolean' === $item[0]) { - $formattedValue = ''.strtolower(var_export($item[1], true)).''; - } elseif ('resource' === $item[0]) { - $formattedValue = 'resource'; - } else { - $formattedValue = str_replace("\n", '', $this->escape(var_export($item[1], true))); - } - - $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escape($key), $formattedValue); - } - - return implode(', ', $result); - } - - private function formatArgsAsText(array $args) - { - return strip_tags($this->formatArgs($args)); - } - - private function escape(string $string): string - { - return htmlspecialchars($string, ENT_COMPAT | ENT_SUBSTITUTE, $this->charset); - } - - private function abbrClass(string $class): string - { - $parts = explode('\\', $class); - $short = array_pop($parts); - - return sprintf('%s', $class, $short); - } - - private function getFileRelative(string $file): ?string - { - $file = str_replace('\\', '/', $file); - - if (null !== $this->projectDir && 0 === strpos($file, $this->projectDir)) { - return ltrim(substr($file, \strlen($this->projectDir)), '/'); - } - - return null; - } - - /** - * Returns the link for a given file/line pair. - * - * @return string|false A link or false - */ - private function getFileLink(string $file, int $line) - { - if ($fmt = $this->fileLinkFormat) { - return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line); - } - - return false; - } - - /** - * Formats a file path. - * - * @param string $file An absolute file path - * @param int $line The line number - * @param string $text Use this text for the link rather than the file path - */ - private function formatFile(string $file, int $line, string $text = null): string - { - $file = trim($file); - - if (null === $text) { - $text = $file; - if (null !== $rel = $this->getFileRelative($text)) { - $rel = explode('/', $rel, 2); - $text = sprintf('%s%s', $this->projectDir, $rel[0], '/'.($rel[1] ?? '')); - } - } - - if (0 < $line) { - $text .= ' at line '.$line; - } - - if (false !== $link = $this->getFileLink($file, $line)) { - return sprintf('%s', $this->escape($link), $text); - } - - return $text; - } - - /** - * Returns an excerpt of a code file around the given line number. - * - * @param string $file A file path - * @param int $line The selected line number - * @param int $srcContext The number of displayed lines around or -1 for the whole file - * - * @return string An HTML string - */ - private function fileExcerpt(string $file, int $line, int $srcContext = 3): string - { - if (is_file($file) && is_readable($file)) { - // highlight_file could throw warnings - // see https://bugs.php.net/25725 - $code = @highlight_file($file, true); - // remove main code/span tags - $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); - // split multiline spans - $code = preg_replace_callback('#]++)>((?:[^<]*+
    )++[^<]*+)
    #', function ($m) { - return "".str_replace('
    ', "

    ", $m[2]).''; - }, $code); - $content = explode('
    ', $code); - - $lines = []; - if (0 > $srcContext) { - $srcContext = \count($content); - } - - for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, \count($content)); $i <= $max; ++$i) { - $lines[] = ''.$this->fixCodeMarkup($content[$i - 1]).''; - } - - return '
      '.implode("\n", $lines).'
    '; - } - - return ''; - } - - private function fixCodeMarkup(string $line) - { - // ending tag from previous line - $opening = strpos($line, ''); - if (false !== $closing && (false === $opening || $closing < $opening)) { - $line = substr_replace($line, '', $closing, 7); - } - - // missing tag at the end of line - $opening = strpos($line, ''); - if (false !== $opening && (false === $closing || $closing > $opening)) { - $line .= ''; - } - - return trim($line); - } - - private function formatFileFromText(string $text) - { - return preg_replace_callback('/in ("|")?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', function ($match) { - return 'in '.$this->formatFile($match[2], $match[3]); - }, $text); - } - - private function formatLogMessage(string $message, array $context) - { - if ($context && false !== strpos($message, '{')) { - $replacements = []; - foreach ($context as $key => $val) { - if (is_scalar($val)) { - $replacements['{'.$key.'}'] = $val; - } - } - - if ($replacements) { - $message = strtr($message, $replacements); - } - } - - return $this->escape($message); - } - - private function addElementToGhost(): string - { - if (!isset(self::GHOST_ADDONS[date('m-d')])) { - return ''; - } - - return ''; - } - - private function include(string $name, array $context = []): string - { - extract($context, EXTR_SKIP); - ob_start(); - include __DIR__.'/../Resources/'.$name; - - return trim(ob_get_clean()); - } -} diff --git a/vendor/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php b/vendor/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php deleted file mode 100644 index 6cc363d..0000000 --- a/vendor/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php +++ /dev/null @@ -1,80 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\ErrorRenderer; - -use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\Serializer\Exception\NotEncodableValueException; -use Symfony\Component\Serializer\SerializerInterface; - -/** - * Formats an exception using Serializer for rendering. - * - * @author Nicolas Grekas - */ -class SerializerErrorRenderer implements ErrorRendererInterface -{ - private $serializer; - private $format; - private $fallbackErrorRenderer; - private $debug; - - /** - * @param string|callable(FlattenException) $format The format as a string or a callable that should return it - * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it - */ - public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null, $debug = false) - { - if (!\is_string($format) && !\is_callable($format)) { - throw new \TypeError(sprintf('Argument 2 passed to %s() must be a string or a callable, %s given.', __METHOD__, \is_object($format) ? \get_class($format) : \gettype($format))); - } - - if (!\is_bool($debug) && !\is_callable($debug)) { - throw new \TypeError(sprintf('Argument 4 passed to %s() must be a boolean or a callable, %s given.', __METHOD__, \is_object($debug) ? \get_class($debug) : \gettype($debug))); - } - - $this->serializer = $serializer; - $this->format = $format; - $this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer(); - $this->debug = $debug; - } - - /** - * {@inheritdoc} - */ - public function render(\Throwable $exception): FlattenException - { - $flattenException = FlattenException::createFromThrowable($exception); - - try { - $format = \is_string($this->format) ? $this->format : ($this->format)($flattenException); - - return $flattenException->setAsString($this->serializer->serialize($flattenException, $format, [ - 'exception' => $exception, - 'debug' => \is_bool($this->debug) ? $this->debug : ($this->debug)($exception), - ])); - } catch (NotEncodableValueException $e) { - return $this->fallbackErrorRenderer->render($exception); - } - } - - public static function getPreferredFormat(RequestStack $requestStack): \Closure - { - return static function () use ($requestStack) { - if (!$request = $requestStack->getCurrentRequest()) { - throw new NotEncodableValueException(); - } - - return $request->getPreferredFormat(); - }; - } -} diff --git a/vendor/symfony/error-handler/Exception/FlattenException.php b/vendor/symfony/error-handler/Exception/FlattenException.php deleted file mode 100644 index 0cff4cd..0000000 --- a/vendor/symfony/error-handler/Exception/FlattenException.php +++ /dev/null @@ -1,397 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Exception; - -use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; - -/** - * FlattenException wraps a PHP Error or Exception to be able to serialize it. - * - * Basically, this class removes all objects from the trace. - * - * @author Fabien Potencier - */ -class FlattenException -{ - private $message; - private $code; - private $previous; - private $trace; - private $traceAsString; - private $class; - private $statusCode; - private $statusText; - private $headers; - private $file; - private $line; - private $asString; - - /** - * @return static - */ - public static function create(\Exception $exception, $statusCode = null, array $headers = []): self - { - return static::createFromThrowable($exception, $statusCode, $headers); - } - - /** - * @return static - */ - public static function createFromThrowable(\Throwable $exception, int $statusCode = null, array $headers = []): self - { - $e = new static(); - $e->setMessage($exception->getMessage()); - $e->setCode($exception->getCode()); - - if ($exception instanceof HttpExceptionInterface) { - $statusCode = $exception->getStatusCode(); - $headers = array_merge($headers, $exception->getHeaders()); - } elseif ($exception instanceof RequestExceptionInterface) { - $statusCode = 400; - } - - if (null === $statusCode) { - $statusCode = 500; - } - - if (class_exists(Response::class) && isset(Response::$statusTexts[$statusCode])) { - $statusText = Response::$statusTexts[$statusCode]; - } else { - $statusText = 'Whoops, looks like something went wrong.'; - } - - $e->setStatusText($statusText); - $e->setStatusCode($statusCode); - $e->setHeaders($headers); - $e->setTraceFromThrowable($exception); - $e->setClass(\get_class($exception)); - $e->setFile($exception->getFile()); - $e->setLine($exception->getLine()); - - $previous = $exception->getPrevious(); - - if ($previous instanceof \Throwable) { - $e->setPrevious(static::createFromThrowable($previous)); - } - - return $e; - } - - public function toArray(): array - { - $exceptions = []; - foreach (array_merge([$this], $this->getAllPrevious()) as $exception) { - $exceptions[] = [ - 'message' => $exception->getMessage(), - 'class' => $exception->getClass(), - 'trace' => $exception->getTrace(), - ]; - } - - return $exceptions; - } - - public function getStatusCode(): int - { - return $this->statusCode; - } - - /** - * @return $this - */ - public function setStatusCode($code): self - { - $this->statusCode = $code; - - return $this; - } - - public function getHeaders(): array - { - return $this->headers; - } - - /** - * @return $this - */ - public function setHeaders(array $headers): self - { - $this->headers = $headers; - - return $this; - } - - public function getClass(): string - { - return $this->class; - } - - /** - * @return $this - */ - public function setClass($class): self - { - $this->class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; - - return $this; - } - - public function getFile(): string - { - return $this->file; - } - - /** - * @return $this - */ - public function setFile($file): self - { - $this->file = $file; - - return $this; - } - - public function getLine(): int - { - return $this->line; - } - - /** - * @return $this - */ - public function setLine($line): self - { - $this->line = $line; - - return $this; - } - - public function getStatusText(): string - { - return $this->statusText; - } - - public function setStatusText(string $statusText): self - { - $this->statusText = $statusText; - - return $this; - } - - public function getMessage(): string - { - return $this->message; - } - - /** - * @return $this - */ - public function setMessage($message): self - { - if (false !== strpos($message, "class@anonymous\0")) { - $message = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:)[0-9a-fA-F]++/', function ($m) { - return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0]; - }, $message); - } - - $this->message = $message; - - return $this; - } - - public function getCode(): int - { - return $this->code; - } - - /** - * @return $this - */ - public function setCode($code): self - { - $this->code = $code; - - return $this; - } - - public function getPrevious(): ?self - { - return $this->previous; - } - - /** - * @return $this - */ - public function setPrevious(self $previous): self - { - $this->previous = $previous; - - return $this; - } - - /** - * @return self[] - */ - public function getAllPrevious(): array - { - $exceptions = []; - $e = $this; - while ($e = $e->getPrevious()) { - $exceptions[] = $e; - } - - return $exceptions; - } - - public function getTrace(): array - { - return $this->trace; - } - - /** - * @return $this - */ - public function setTraceFromThrowable(\Throwable $throwable): self - { - $this->traceAsString = $throwable->getTraceAsString(); - - return $this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine()); - } - - /** - * @return $this - */ - public function setTrace($trace, $file, $line): self - { - $this->trace = []; - $this->trace[] = [ - 'namespace' => '', - 'short_class' => '', - 'class' => '', - 'type' => '', - 'function' => '', - 'file' => $file, - 'line' => $line, - 'args' => [], - ]; - foreach ($trace as $entry) { - $class = ''; - $namespace = ''; - if (isset($entry['class'])) { - $parts = explode('\\', $entry['class']); - $class = array_pop($parts); - $namespace = implode('\\', $parts); - } - - $this->trace[] = [ - 'namespace' => $namespace, - 'short_class' => $class, - 'class' => isset($entry['class']) ? $entry['class'] : '', - 'type' => isset($entry['type']) ? $entry['type'] : '', - 'function' => isset($entry['function']) ? $entry['function'] : null, - 'file' => isset($entry['file']) ? $entry['file'] : null, - 'line' => isset($entry['line']) ? $entry['line'] : null, - 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : [], - ]; - } - - return $this; - } - - private function flattenArgs(array $args, int $level = 0, int &$count = 0): array - { - $result = []; - foreach ($args as $key => $value) { - if (++$count > 1e4) { - return ['array', '*SKIPPED over 10000 entries*']; - } - if ($value instanceof \__PHP_Incomplete_Class) { - // is_object() returns false on PHP<=7.1 - $result[$key] = ['incomplete-object', $this->getClassNameFromIncomplete($value)]; - } elseif (\is_object($value)) { - $result[$key] = ['object', \get_class($value)]; - } elseif (\is_array($value)) { - if ($level > 10) { - $result[$key] = ['array', '*DEEP NESTED ARRAY*']; - } else { - $result[$key] = ['array', $this->flattenArgs($value, $level + 1, $count)]; - } - } elseif (null === $value) { - $result[$key] = ['null', null]; - } elseif (\is_bool($value)) { - $result[$key] = ['boolean', $value]; - } elseif (\is_int($value)) { - $result[$key] = ['integer', $value]; - } elseif (\is_float($value)) { - $result[$key] = ['float', $value]; - } elseif (\is_resource($value)) { - $result[$key] = ['resource', get_resource_type($value)]; - } else { - $result[$key] = ['string', (string) $value]; - } - } - - return $result; - } - - private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value): string - { - $array = new \ArrayObject($value); - - return $array['__PHP_Incomplete_Class_Name']; - } - - public function getTraceAsString(): string - { - return $this->traceAsString; - } - - /** - * @return $this - */ - public function setAsString(?string $asString): self - { - $this->asString = $asString; - - return $this; - } - - public function getAsString(): string - { - if (null !== $this->asString) { - return $this->asString; - } - - $message = ''; - $next = false; - - foreach (array_reverse(array_merge([$this], $this->getAllPrevious())) as $exception) { - if ($next) { - $message .= 'Next '; - } else { - $next = true; - } - $message .= $exception->getClass(); - - if ('' != $exception->getMessage()) { - $message .= ': '.$exception->getMessage(); - } - - $message .= ' in '.$exception->getFile().':'.$exception->getLine(). - "\nStack trace:\n".$exception->getTraceAsString()."\n\n"; - } - - return rtrim($message); - } -} diff --git a/vendor/symfony/error-handler/Exception/SilencedErrorContext.php b/vendor/symfony/error-handler/Exception/SilencedErrorContext.php deleted file mode 100644 index 18defc7..0000000 --- a/vendor/symfony/error-handler/Exception/SilencedErrorContext.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler\Exception; - -/** - * Data Object that represents a Silenced Error. - * - * @author Grégoire Pineau - */ -class SilencedErrorContext implements \JsonSerializable -{ - public $count = 1; - - private $severity; - private $file; - private $line; - private $trace; - - public function __construct(int $severity, string $file, int $line, array $trace = [], int $count = 1) - { - $this->severity = $severity; - $this->file = $file; - $this->line = $line; - $this->trace = $trace; - $this->count = $count; - } - - public function getSeverity(): int - { - return $this->severity; - } - - public function getFile(): string - { - return $this->file; - } - - public function getLine(): int - { - return $this->line; - } - - public function getTrace(): array - { - return $this->trace; - } - - public function jsonSerialize(): array - { - return [ - 'severity' => $this->severity, - 'file' => $this->file, - 'line' => $this->line, - 'trace' => $this->trace, - 'count' => $this->count, - ]; - } -} diff --git a/vendor/symfony/error-handler/LICENSE b/vendor/symfony/error-handler/LICENSE deleted file mode 100644 index 1a18697..0000000 --- a/vendor/symfony/error-handler/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/error-handler/README.md b/vendor/symfony/error-handler/README.md deleted file mode 100644 index 17e1cfd..0000000 --- a/vendor/symfony/error-handler/README.md +++ /dev/null @@ -1,12 +0,0 @@ -ErrorHandler Component -====================== - -The ErrorHandler component provides tools to manage errors and ease debugging PHP code. - -Resources ---------- - - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/error-handler/Resources/assets/css/error.css b/vendor/symfony/error-handler/Resources/assets/css/error.css deleted file mode 100644 index 332d818..0000000 --- a/vendor/symfony/error-handler/Resources/assets/css/error.css +++ /dev/null @@ -1,4 +0,0 @@ -body { background-color: #fff; color: #222; font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 0; } -.container { margin: 30px; max-width: 600px; } -h1 { color: #dc3545; font-size: 24px; } -h2 { font-size: 18px; } diff --git a/vendor/symfony/error-handler/Resources/assets/css/exception.css b/vendor/symfony/error-handler/Resources/assets/css/exception.css deleted file mode 100644 index 952c66d..0000000 --- a/vendor/symfony/error-handler/Resources/assets/css/exception.css +++ /dev/null @@ -1,209 +0,0 @@ -/* This file is based on WebProfilerBundle/Resources/views/Profiler/profiler.css.twig. - If you make any change in this file, verify the same change is needed in the other file. */ -:root { - --font-sans-serif: Helvetica, Arial, sans-serif; - --page-background: #f9f9f9; - --color-text: #222; - /* when updating any of these colors, do the same in toolbar.css.twig */ - --color-success: #4f805d; - --color-warning: #a46a1f; - --color-error: #b0413e; - --color-muted: #999; - --tab-background: #fff; - --tab-color: #444; - --tab-active-background: #666; - --tab-active-color: #fafafa; - --tab-disabled-background: #f5f5f5; - --tab-disabled-color: #999; - --metric-value-background: #fff; - --metric-value-color: inherit; - --metric-unit-color: #999; - --metric-label-background: #e0e0e0; - --metric-label-color: inherit; - --table-border: #e0e0e0; - --table-background: #fff; - --table-header: #e0e0e0; - --trace-selected-background: #F7E5A1; - --tree-active-background: #F7E5A1; - --exception-title-color: var(--base-2); - --shadow: 0px 0px 1px rgba(128, 128, 128, .2); - --border: 1px solid #e0e0e0; - --background-error: var(--color-error); - --highlight-comment: #969896; - --highlight-default: #222222; - --highlight-keyword: #a71d5d; - --highlight-string: #183691; - --base-0: #fff; - --base-1: #f5f5f5; - --base-2: #e0e0e0; - --base-3: #ccc; - --base-4: #666; - --base-5: #444; - --base-6: #222; -} - -html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0} - -html { - /* always display the vertical scrollbar to avoid jumps when toggling contents */ - overflow-y: scroll; -} -body { background-color: #F9F9F9; color: var(--base-6); font: 14px/1.4 Helvetica, Arial, sans-serif; padding-bottom: 45px; } - -a { cursor: pointer; text-decoration: none; } -a:hover { text-decoration: underline; } -abbr[title] { border-bottom: none; cursor: help; text-decoration: none; } - -code, pre { font: 13px/1.5 Consolas, Monaco, Menlo, "Ubuntu Mono", "Liberation Mono", monospace; } - -table, tr, th, td { background: #FFF; border-collapse: collapse; vertical-align: top; } -table { background: #FFF; border: var(--border); box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; width: 100%; } -table th, table td { border: solid var(--base-2); border-width: 1px 0; padding: 8px 10px; } -table th { background-color: var(--base-2); font-weight: bold; text-align: left; } - -.m-t-5 { margin-top: 5px; } -.hidden-xs-down { display: none; } -.block { display: block; } -.full-width { width: 100%; } -.hidden { display: none; } -.prewrap { white-space: pre-wrap; } -.nowrap { white-space: nowrap; } -.newline { display: block; } -.break-long-words { word-wrap: break-word; overflow-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; min-width: 0; } -.text-small { font-size: 12px !important; } -.text-muted { color: #999; } -.text-bold { font-weight: bold; } -.empty { border: 4px dashed var(--base-2); color: #999; margin: 1em 0; padding: .5em 2em; } - -.status-success { background: rgba(94, 151, 110, 0.3); } -.status-warning { background: rgba(240, 181, 24, 0.3); } -.status-error { background: rgba(176, 65, 62, 0.2); } -.status-success td, .status-warning td, .status-error td { background: transparent; } -tr.status-error td, tr.status-warning td { border-bottom: 1px solid #FAFAFA; border-top: 1px solid #FAFAFA; } -.status-warning .colored { color: #A46A1F; } -.status-error .colored { color: var(--color-error); } - -.sf-toggle { cursor: pointer; } -.sf-toggle-content { -moz-transition: display .25s ease; -webkit-transition: display .25s ease; transition: display .25s ease; } -.sf-toggle-content.sf-toggle-hidden { display: none; } -.sf-toggle-content.sf-toggle-visible { display: block; } -thead.sf-toggle-content.sf-toggle-visible, tbody.sf-toggle-content.sf-toggle-visible { display: table-row-group; } -.sf-toggle-off .icon-close, .sf-toggle-on .icon-open { display: none; } -.sf-toggle-off .icon-open, .sf-toggle-on .icon-close { display: block; } - -.tab-navigation { margin: 0 0 1em 0; padding: 0; } -.tab-navigation li { background: var(--tab-background); border: 1px solid var(--table-border); color: var(--tab-color); cursor: pointer; display: inline-block; font-size: 16px; margin: 0 0 0 -1px; padding: .5em .75em; z-index: 1; } -.tab-navigation li .badge { background-color: var(--base-1); color: var(--base-4); display: inline-block; font-size: 14px; font-weight: bold; margin-left: 8px; min-width: 10px; padding: 1px 6px; text-align: center; white-space: nowrap; } -.tab-navigation li.disabled { background: var(--tab-disabled-background); color: var(--tab-disabled-color); } -.tab-navigation li.active { background: var(--tab-active-background); color: var(--tab-active-color); z-index: 1100; } -.tab-navigation li.active .badge { background-color: var(--base-5); color: var(--base-2); } -.tab-content > *:first-child { margin-top: 0; } -.tab-navigation li .badge.status-warning { background: var(--color-warning); color: #FFF; } -.tab-navigation li .badge.status-error { background: var(--background-error); color: #FFF; } -.sf-tabs .tab:not(:first-child) { display: none; } - -[data-filters] { position: relative; } -[data-filtered] { cursor: pointer; } -[data-filtered]:after { content: '\00a0\25BE'; } -[data-filtered]:hover .filter-list li { display: inline-flex; } -[class*="filter-hidden-"] { display: none; } -.filter-list { position: absolute; border: var(--border); box-shadow: var(--shadow); margin: 0; padding: 0; display: flex; flex-direction: column; } -.filter-list :after { content: ''; } -.filter-list li { - background: var(--tab-disabled-background); - border-bottom: var(--border); - color: var(--tab-disabled-color); - display: none; - list-style: none; - margin: 0; - padding: 5px 10px; - text-align: left; - font-weight: normal; -} -.filter-list li.active { - background: var(--tab-background); - color: var(--tab-color); -} -.filter-list li.last-active { - background: var(--tab-active-background); - color: var(--tab-active-color); -} - -.filter-list-level li { cursor: s-resize; } -.filter-list-level li.active { cursor: n-resize; } -.filter-list-level li.last-active { cursor: default; } -.filter-list-level li.last-active:before { content: '\2714\00a0'; } -.filter-list-choice li:before { content: '\2714\00a0'; color: transparent; } -.filter-list-choice li.active:before { color: unset; } - -.container { max-width: 1024px; margin: 0 auto; padding: 0 15px; } -.container::after { content: ""; display: table; clear: both; } - -header { background-color: var(--base-6); color: rgba(255, 255, 255, 0.75); font-size: 13px; height: 33px; line-height: 33px; padding: 0; } -header .container { display: flex; justify-content: space-between; } -.logo { flex: 1; font-size: 13px; font-weight: normal; margin: 0; padding: 0; } -.logo svg { height: 18px; width: 18px; opacity: .8; vertical-align: -5px; } - -.help-link { margin-left: 15px; } -.help-link a { color: inherit; } -.help-link .icon svg { height: 15px; width: 15px; opacity: .7; vertical-align: -2px; } -.help-link a:hover { color: #EEE; text-decoration: none; } -.help-link a:hover svg { opacity: .9; } - -.exception-summary { background: var(--background-error); border-bottom: 2px solid rgba(0, 0, 0, 0.1); border-top: 1px solid rgba(0, 0, 0, .3); flex: 0 0 auto; margin-bottom: 15px; } -.exception-metadata { background: rgba(0, 0, 0, 0.1); padding: 7px 0; } -.exception-metadata .container { display: flex; flex-direction: row; justify-content: space-between; } -.exception-metadata h2, .exception-metadata h2 > a { color: rgba(255, 255, 255, 0.8); font-size: 13px; font-weight: 400; margin: 0; } -.exception-http small { font-size: 13px; opacity: .7; } -.exception-hierarchy { flex: 1; } -.exception-hierarchy .icon { margin: 0 3px; opacity: .7; } -.exception-hierarchy .icon svg { height: 13px; width: 13px; vertical-align: -2px; } - -.exception-without-message .exception-message-wrapper { display: none; } -.exception-message-wrapper .container { display: flex; align-items: flex-start; min-height: 70px; padding: 10px 15px 8px; } -.exception-message { flex-grow: 1; } -.exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; } -.exception-message.long { font-size: 18px; } -.exception-message a { border-bottom: 1px solid rgba(255, 255, 255, 0.5); font-size: inherit; text-decoration: none; } -.exception-message a:hover { border-bottom-color: #ffffff; } - -.exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; } - -.trace + .trace { margin-top: 30px; } -.trace-head { background-color: var(--base-2); padding: 10px; position: relative; } -.trace-head .trace-class { color: var(--base-6); font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; } -.trace-head .trace-namespace { color: #999; display: block; font-size: 13px; } -.trace-head .icon { position: absolute; right: 0; top: 0; } -.trace-head .icon svg { height: 24px; width: 24px; } - -.trace-details { background: var(--base-0); border: var(--border); box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; table-layout: fixed; } - -.trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; } - -.trace-line { position: relative; padding-top: 8px; padding-bottom: 8px; } -.trace-line + .trace-line { border-top: var(--border); } -.trace-line:hover { background: var(--base-1); } -.trace-line a { color: var(--base-6); } -.trace-line .icon { opacity: .4; position: absolute; left: 10px; top: 11px; } -.trace-line .icon svg { height: 16px; width: 16px; } -.trace-line-header { padding-left: 36px; padding-right: 10px; } - -.trace-file-path, .trace-file-path a { color: var(--base-6); font-size: 13px; } -.trace-class { color: var(--color-error); } -.trace-type { padding: 0 2px; } -.trace-method { color: var(--color-error); font-weight: bold; } -.trace-arguments { color: #777; font-weight: normal; padding-left: 2px; } - -.trace-code { background: var(--base-0); font-size: 12px; margin: 10px 10px 2px 10px; padding: 10px; overflow-x: auto; white-space: nowrap; } -.trace-code ol { margin: 0; float: left; } -.trace-code li { color: #969896; margin: 0; padding-left: 10px; float: left; width: 100%; } -.trace-code li + li { margin-top: 5px; } -.trace-code li.selected { background: var(--trace-selected-background); margin-top: 2px; } -.trace-code li code { color: var(--base-6); white-space: nowrap; } - -.trace-as-text .stacktrace { line-height: 1.8; margin: 0 0 15px; white-space: pre-wrap; } - -@media (min-width: 575px) { - .hidden-xs-down { display: initial; } - .help-link { margin-left: 30px; } -} diff --git a/vendor/symfony/error-handler/Resources/assets/css/exception_full.css b/vendor/symfony/error-handler/Resources/assets/css/exception_full.css deleted file mode 100644 index fa77cb3..0000000 --- a/vendor/symfony/error-handler/Resources/assets/css/exception_full.css +++ /dev/null @@ -1,128 +0,0 @@ -.sf-reset .traces { - padding-bottom: 14px; -} -.sf-reset .traces li { - font-size: 12px; - color: #868686; - padding: 5px 4px; - list-style-type: decimal; - margin-left: 20px; -} -.sf-reset #logs .traces li.error { - font-style: normal; - color: #AA3333; - background: #f9ecec; -} -.sf-reset #logs .traces li.warning { - font-style: normal; - background: #ffcc00; -} -/* fix for Opera not liking empty
  • */ -.sf-reset .traces li:after { - content: "\00A0"; -} -.sf-reset .trace { - border: 1px solid #D3D3D3; - padding: 10px; - overflow: auto; - margin: 10px 0 20px; -} -.sf-reset .block-exception { - -moz-border-radius: 16px; - -webkit-border-radius: 16px; - border-radius: 16px; - margin-bottom: 20px; - background-color: #f6f6f6; - border: 1px solid #dfdfdf; - padding: 30px 28px; - word-wrap: break-word; - overflow: hidden; -} -.sf-reset .block-exception div { - color: #313131; - font-size: 10px; -} -.sf-reset .block-exception-detected .illustration-exception, -.sf-reset .block-exception-detected .text-exception { - float: left; -} -.sf-reset .block-exception-detected .illustration-exception { - width: 152px; -} -.sf-reset .block-exception-detected .text-exception { - width: 670px; - padding: 30px 44px 24px 46px; - position: relative; -} -.sf-reset .text-exception .open-quote, -.sf-reset .text-exception .close-quote { - font-family: Arial, Helvetica, sans-serif; - position: absolute; - color: #C9C9C9; - font-size: 8em; -} -.sf-reset .open-quote { - top: 0; - left: 0; -} -.sf-reset .close-quote { - bottom: -0.5em; - right: 50px; -} -.sf-reset .block-exception p { - font-family: Arial, Helvetica, sans-serif; -} -.sf-reset .block-exception p a, -.sf-reset .block-exception p a:hover { - color: #565656; -} -.sf-reset .logs h2 { - float: left; - width: 654px; -} -.sf-reset .error-count, .sf-reset .support { - float: right; - width: 170px; - text-align: right; -} -.sf-reset .error-count span { - display: inline-block; - background-color: #aacd4e; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; - padding: 4px; - color: white; - margin-right: 2px; - font-size: 11px; - font-weight: bold; -} - -.sf-reset .support a { - display: inline-block; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; - padding: 4px; - color: #000000; - margin-right: 2px; - font-size: 11px; - font-weight: bold; -} - -.sf-reset .toggle { - vertical-align: middle; -} -.sf-reset .linked ul, -.sf-reset .linked li { - display: inline; -} -.sf-reset #output-content { - color: #000; - font-size: 12px; -} -.sf-reset #traces-text pre { - white-space: pre; - font-size: 12px; - font-family: monospace; -} diff --git a/vendor/symfony/error-handler/Resources/assets/images/chevron-right.svg b/vendor/symfony/error-handler/Resources/assets/images/chevron-right.svg deleted file mode 100644 index 6837aff..0000000 --- a/vendor/symfony/error-handler/Resources/assets/images/chevron-right.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/vendor/symfony/error-handler/Resources/assets/images/favicon.png.base64 b/vendor/symfony/error-handler/Resources/assets/images/favicon.png.base64 deleted file mode 100644 index fb076ed..0000000 --- a/vendor/symfony/error-handler/Resources/assets/images/favicon.png.base64 +++ /dev/null @@ -1 +0,0 @@ -data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAgCAYAAAABtRhCAAADVUlEQVRIx82XX0jTURTHLYPyqZdefQx66CEo80+aYpoIkqzUikz6Z5klQoWUWYRIJYEUGpQ+lIr9U5dOTLdCtkmWZis3rbnC5fw/neYW002307mX/cZvP3/7o1PwwOdh95x7vnf39zvnd29AgBer2xO6DclAXiMqZAqxIiNIN/IYSUS2BPhjmGATchUxI+ADWiRhpWK7HKuHFVBFdmU5YvnI4grFGCaReF/EBH4KsZlGgj2JBTuCYBWRIYF8YoEOJ6wBt/gEs7mBbyOjQXruPLSdOgPCiEiPSUUHDoL8Ug5IUo9B/d5wrt+G7OAKNrODPuVdB6vRCIzN6SdBlpW9RIgk/1FeAXabzRlrUPVCS/JhbmwudztnGeeH9AyXBIwtmM3wLinZJZHifjHw2V+NBoRh+9ixQrbgbnaSIcl7cGea6hoXQbNe7za241oeO5Z0p42M4BV2EqP2D50wo+6HzvwC6C4sApNOR8cmOrtcnhtj2kYRyC9eBvXzKrBZrXSs72kFd1t3MoKVbMekQkEnSNKOO8fac3LpmK6l1TlGtsxmsdKFsecPYgwxst0cwROMYDXboSotg0WLBRqjY51jLYcENElXwW2XJKPydvoI2GN9T8rBtrAArYIUruBJXkFheCQYlCpQP6uk5dAQFQNaUROMSGVQFxLmkoQsxDJrhLbTZ+nvVsERME9MgPJRKV/58AsyomTSzE813WLFvWK++qI0xSfQl8k8Pg46sYRuv5t6dS+4RqxDwaa4BGjYH+NTQvKScIp9+YL/hoZh3jDtLRHtt2C3g6bmhX+CpsFBWg7ilDSPgj0lD2ncr5ev/BP8VvyAJhqVyZeUhPOrEhEFxgEtjft846Z/guQTNT89Q5P9flMLoth4F7808wKtWWKzAwNQHxrh/1vaid2F+XpYTSbQf1XA2McOmOpROnvpvMEA4tSjq1cW0sws2gCYxswY6TKkvzYnJq1NHZLnRU4BX+4U0uburvusu8Kv8iHY7qefkM4IFngJHEOUXmLEPgiGsI8YnlZILit3vSSLRTQe/MPIZva5pshNIEmyFQlCvruJKXPkCEfmePzkphXHdzZNQdoRI9KPlBAxlj/I8U97ERPS5bjGbWDFbEdqHVe5caTBeZZx2H/IMvzeN15yoQAAAABJRU5ErkJggg== diff --git a/vendor/symfony/error-handler/Resources/assets/images/icon-book.svg b/vendor/symfony/error-handler/Resources/assets/images/icon-book.svg deleted file mode 100644 index 498a74f..0000000 --- a/vendor/symfony/error-handler/Resources/assets/images/icon-book.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/vendor/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg b/vendor/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg deleted file mode 100644 index be534ad..0000000 --- a/vendor/symfony/error-handler/Resources/assets/images/icon-minus-square-o.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/vendor/symfony/error-handler/Resources/assets/images/icon-minus-square.svg b/vendor/symfony/error-handler/Resources/assets/images/icon-minus-square.svg deleted file mode 100644 index 471c274..0000000 --- a/vendor/symfony/error-handler/Resources/assets/images/icon-minus-square.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/vendor/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg b/vendor/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg deleted file mode 100644 index b2593a9..0000000 --- a/vendor/symfony/error-handler/Resources/assets/images/icon-plus-square-o.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/vendor/symfony/error-handler/Resources/assets/images/icon-plus-square.svg b/vendor/symfony/error-handler/Resources/assets/images/icon-plus-square.svg deleted file mode 100644 index 2f5c3b3..0000000 --- a/vendor/symfony/error-handler/Resources/assets/images/icon-plus-square.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/vendor/symfony/error-handler/Resources/assets/images/icon-support.svg b/vendor/symfony/error-handler/Resources/assets/images/icon-support.svg deleted file mode 100644 index 03fd8e7..0000000 --- a/vendor/symfony/error-handler/Resources/assets/images/icon-support.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/vendor/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php b/vendor/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php deleted file mode 100644 index 4b2f9c1..0000000 --- a/vendor/symfony/error-handler/Resources/assets/images/symfony-ghost.svg.php +++ /dev/null @@ -1 +0,0 @@ -addElementToGhost(); ?> diff --git a/vendor/symfony/error-handler/Resources/assets/images/symfony-logo.svg b/vendor/symfony/error-handler/Resources/assets/images/symfony-logo.svg deleted file mode 100644 index f10824a..0000000 --- a/vendor/symfony/error-handler/Resources/assets/images/symfony-logo.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/vendor/symfony/error-handler/Resources/assets/js/exception.js b/vendor/symfony/error-handler/Resources/assets/js/exception.js deleted file mode 100644 index 8cc7b53..0000000 --- a/vendor/symfony/error-handler/Resources/assets/js/exception.js +++ /dev/null @@ -1,279 +0,0 @@ -/* This file is based on WebProfilerBundle/Resources/views/Profiler/base_js.html.twig. - If you make any change in this file, verify the same change is needed in the other file. */ -/* .tab'); - var tabNavigation = document.createElement('ul'); - tabNavigation.className = 'tab-navigation'; - - var selectedTabId = 'tab-' + i + '-0'; /* select the first tab by default */ - for (var j = 0; j < tabs.length; j++) { - var tabId = 'tab-' + i + '-' + j; - var tabTitle = tabs[j].querySelector('.tab-title').innerHTML; - - var tabNavigationItem = document.createElement('li'); - tabNavigationItem.setAttribute('data-tab-id', tabId); - if (hasClass(tabs[j], 'active')) { selectedTabId = tabId; } - if (hasClass(tabs[j], 'disabled')) { addClass(tabNavigationItem, 'disabled'); } - tabNavigationItem.innerHTML = tabTitle; - tabNavigation.appendChild(tabNavigationItem); - - var tabContent = tabs[j].querySelector('.tab-content'); - tabContent.parentElement.setAttribute('id', tabId); - } - - tabGroups[i].insertBefore(tabNavigation, tabGroups[i].firstChild); - addClass(document.querySelector('[data-tab-id="' + selectedTabId + '"]'), 'active'); - } - - /* display the active tab and add the 'click' event listeners */ - for (i = 0; i < tabGroups.length; i++) { - tabNavigation = tabGroups[i].querySelectorAll(':scope >.tab-navigation li'); - - for (j = 0; j < tabNavigation.length; j++) { - tabId = tabNavigation[j].getAttribute('data-tab-id'); - document.getElementById(tabId).querySelector('.tab-title').className = 'hidden'; - - if (hasClass(tabNavigation[j], 'active')) { - document.getElementById(tabId).className = 'block'; - } else { - document.getElementById(tabId).className = 'hidden'; - } - - tabNavigation[j].addEventListener('click', function(e) { - var activeTab = e.target || e.srcElement; - - /* needed because when the tab contains HTML contents, user can click */ - /* on any of those elements instead of their parent '
  • ' element */ - while (activeTab.tagName.toLowerCase() !== 'li') { - activeTab = activeTab.parentNode; - } - - /* get the full list of tabs through the parent of the active tab element */ - var tabNavigation = activeTab.parentNode.children; - for (var k = 0; k < tabNavigation.length; k++) { - var tabId = tabNavigation[k].getAttribute('data-tab-id'); - document.getElementById(tabId).className = 'hidden'; - removeClass(tabNavigation[k], 'active'); - } - - addClass(activeTab, 'active'); - var activeTabId = activeTab.getAttribute('data-tab-id'); - document.getElementById(activeTabId).className = 'block'; - }); - } - - tabGroups[i].setAttribute('data-processed', 'true'); - } - }, - - createToggles: function() { - var toggles = document.querySelectorAll('.sf-toggle:not([data-processed=true])'); - - for (var i = 0; i < toggles.length; i++) { - var elementSelector = toggles[i].getAttribute('data-toggle-selector'); - var element = document.querySelector(elementSelector); - - addClass(element, 'sf-toggle-content'); - - if (toggles[i].hasAttribute('data-toggle-initial') && toggles[i].getAttribute('data-toggle-initial') == 'display') { - addClass(toggles[i], 'sf-toggle-on'); - addClass(element, 'sf-toggle-visible'); - } else { - addClass(toggles[i], 'sf-toggle-off'); - addClass(element, 'sf-toggle-hidden'); - } - - addEventListener(toggles[i], 'click', function(e) { - e.preventDefault(); - - if ('' !== window.getSelection().toString()) { - /* Don't do anything on text selection */ - return; - } - - var toggle = e.target || e.srcElement; - - /* needed because when the toggle contains HTML contents, user can click */ - /* on any of those elements instead of their parent '.sf-toggle' element */ - while (!hasClass(toggle, 'sf-toggle')) { - toggle = toggle.parentNode; - } - - var element = document.querySelector(toggle.getAttribute('data-toggle-selector')); - - toggleClass(toggle, 'sf-toggle-on'); - toggleClass(toggle, 'sf-toggle-off'); - toggleClass(element, 'sf-toggle-hidden'); - toggleClass(element, 'sf-toggle-visible'); - - /* the toggle doesn't change its contents when clicking on it */ - if (!toggle.hasAttribute('data-toggle-alt-content')) { - return; - } - - if (!toggle.hasAttribute('data-toggle-original-content')) { - toggle.setAttribute('data-toggle-original-content', toggle.innerHTML); - } - - var currentContent = toggle.innerHTML; - var originalContent = toggle.getAttribute('data-toggle-original-content'); - var altContent = toggle.getAttribute('data-toggle-alt-content'); - toggle.innerHTML = currentContent !== altContent ? altContent : originalContent; - }); - - /* Prevents from disallowing clicks on links inside toggles */ - var toggleLinks = toggles[i].querySelectorAll('a'); - for (var j = 0; j < toggleLinks.length; j++) { - addEventListener(toggleLinks[j], 'click', function(e) { - e.stopPropagation(); - }); - } - - toggles[i].setAttribute('data-processed', 'true'); - } - }, - - createFilters: function() { - document.querySelectorAll('[data-filters] [data-filter]').forEach(function (filter) { - var filters = filter.closest('[data-filters]'), - type = 'choice', - name = filter.dataset.filter, - ucName = name.charAt(0).toUpperCase()+name.slice(1), - list = document.createElement('ul'), - values = filters.dataset['filter'+ucName] || filters.querySelectorAll('[data-filter-'+name+']'), - labels = {}, - defaults = null, - indexed = {}, - processed = {}; - if (typeof values === 'string') { - type = 'level'; - labels = values.split(','); - values = values.toLowerCase().split(','); - defaults = values.length - 1; - } - addClass(list, 'filter-list'); - addClass(list, 'filter-list-'+type); - values.forEach(function (value, i) { - if (value instanceof HTMLElement) { - value = value.dataset['filter'+ucName]; - } - if (value in processed) { - return; - } - var option = document.createElement('li'), - label = i in labels ? labels[i] : value, - active = false, - matches; - if ('' === label) { - option.innerHTML = '(none)'; - } else { - option.innerText = label; - } - option.dataset.filter = value; - option.setAttribute('title', 1 === (matches = filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').length) ? 'Matches 1 row' : 'Matches '+matches+' rows'); - indexed[value] = i; - list.appendChild(option); - addEventListener(option, 'click', function () { - if ('choice' === type) { - filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) { - if (option.dataset.filter === row.dataset['filter'+ucName]) { - toggleClass(row, 'filter-hidden-'+name); - } - }); - toggleClass(option, 'active'); - } else if ('level' === type) { - if (i === this.parentNode.querySelectorAll('.active').length - 1) { - return; - } - this.parentNode.querySelectorAll('li').forEach(function (currentOption, j) { - if (j <= i) { - addClass(currentOption, 'active'); - if (i === j) { - addClass(currentOption, 'last-active'); - } else { - removeClass(currentOption, 'last-active'); - } - } else { - removeClass(currentOption, 'active'); - removeClass(currentOption, 'last-active'); - } - }); - filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) { - if (i < indexed[row.dataset['filter'+ucName]]) { - addClass(row, 'filter-hidden-'+name); - } else { - removeClass(row, 'filter-hidden-'+name); - } - }); - } - }); - if ('choice' === type) { - active = null === defaults || 0 <= defaults.indexOf(value); - } else if ('level' === type) { - active = i <= defaults; - if (active && i === defaults) { - addClass(option, 'last-active'); - } - } - if (active) { - addClass(option, 'active'); - } else { - filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').forEach(function (row) { - toggleClass(row, 'filter-hidden-'+name); - }); - } - processed[value] = true; - }); - - if (1 < list.childNodes.length) { - filter.appendChild(list); - filter.dataset.filtered = ''; - } - }); - } - }; -})(); - -Sfjs.addEventListener(document, 'DOMContentLoaded', function() { - Sfjs.createTabs(); - Sfjs.createToggles(); - Sfjs.createFilters(); -}); - -/*]]>*/ diff --git a/vendor/symfony/error-handler/Resources/views/error.html.php b/vendor/symfony/error-handler/Resources/views/error.html.php deleted file mode 100644 index 5416d03..0000000 --- a/vendor/symfony/error-handler/Resources/views/error.html.php +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - An Error Occurred: <?= $statusText; ?> - - - -
    -

    Oops! An Error Occurred

    -

    The server returned a " ".

    - -

    - Something is broken. Please let us know what you were doing when this error occurred. - We will fix it as soon as possible. Sorry for any inconvenience caused. -

    -
    - - diff --git a/vendor/symfony/error-handler/Resources/views/exception.html.php b/vendor/symfony/error-handler/Resources/views/exception.html.php deleted file mode 100644 index b470b56..0000000 --- a/vendor/symfony/error-handler/Resources/views/exception.html.php +++ /dev/null @@ -1,116 +0,0 @@ -
    - - -
    -
    -

    formatFileFromText(nl2br($exceptionMessage)); ?>

    - -
    - include('assets/images/symfony-ghost.svg.php'); ?> -
    -
    -
    -
    - -
    -
    -
    - toArray(); - $exceptionWithUserCode = []; - $exceptionAsArrayCount = count($exceptionAsArray); - $last = count($exceptionAsArray) - 1; - foreach ($exceptionAsArray as $i => $e) { - foreach ($e['trace'] as $trace) { - if ($trace['file'] && false === mb_strpos($trace['file'], '/vendor/') && false === mb_strpos($trace['file'], '/var/cache/') && $i < $last) { - $exceptionWithUserCode[] = $i; - } - } - } - ?> -

    - 1) { ?> - Exceptions - - Exception - -

    - -
    - $e) { - echo $this->include('views/traces.html.php', [ - 'exception' => $e, - 'index' => $i + 1, - 'expand' => in_array($i, $exceptionWithUserCode, true) || ([] === $exceptionWithUserCode && 0 === $i), - ]); - } - ?> -
    -
    - - -
    -

    - Logs - countErrors()) { ?>countErrors(); ?> -

    - -
    - getLogs()) { ?> - include('views/logs.html.php', ['logs' => $logger->getLogs()]); ?> - -
    -

    No log messages

    -
    - -
    -
    - - -
    -

    - 1) { ?> - Stack Traces - - Stack Trace - -

    - -
    - $e) { - echo $this->include('views/traces_text.html.php', [ - 'exception' => $e, - 'index' => $i + 1, - 'numExceptions' => $exceptionAsArrayCount, - ]); - } - ?> -
    -
    - - -
    -

    Output content

    - -
    - -
    -
    - -
    -
    diff --git a/vendor/symfony/error-handler/Resources/views/exception_full.html.php b/vendor/symfony/error-handler/Resources/views/exception_full.html.php deleted file mode 100644 index 4d46d59..0000000 --- a/vendor/symfony/error-handler/Resources/views/exception_full.html.php +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - <?= $_message; ?> - - - - - - -
    - -
    - - - include('views/exception.html.php', $context); ?> - - - - - diff --git a/vendor/symfony/error-handler/Resources/views/logs.html.php b/vendor/symfony/error-handler/Resources/views/logs.html.php deleted file mode 100644 index c866e06..0000000 --- a/vendor/symfony/error-handler/Resources/views/logs.html.php +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - = 400) { - $status = 'error'; - } elseif ($log['priority'] >= 300) { - $status = 'warning'; - } else { - $severity = 0; - if (($exception = $log['context']['exception'] ?? null) instanceof \ErrorException) { - $severity = $exception->getSeverity(); - } - $status = E_DEPRECATED === $severity || E_USER_DEPRECATED === $severity ? 'warning' : 'normal'; - } ?> - data-filter-channel="escape($log['channel']); ?>"> - - - - - - - - -
    LevelChannelMessage
    - escape($log['priorityName']); ?> - - - escape($log['channel']); ?> - - formatLogMessage($log['message'], $log['context']); ?> - -
    - -
    diff --git a/vendor/symfony/error-handler/Resources/views/trace.html.php b/vendor/symfony/error-handler/Resources/views/trace.html.php deleted file mode 100644 index 153f7d6..0000000 --- a/vendor/symfony/error-handler/Resources/views/trace.html.php +++ /dev/null @@ -1,40 +0,0 @@ -
    - - include('assets/images/icon-minus-square.svg'); ?> - include('assets/images/icon-plus-square.svg'); ?> - - - - abbrClass($trace['class']); ?>(formatArgs($trace['args']); ?>) - - - - getFileLink($trace['file'], $lineNumber); - $filePath = strtr(strip_tags($this->formatFile($trace['file'], $lineNumber)), [' at line '.$lineNumber => '']); - $filePathParts = explode(DIRECTORY_SEPARATOR, $filePath); - ?> - - in - - - - - - - - (line ) - - -
    - -
    - fileExcerpt($trace['file'], $trace['line'], 5), [ - '#DD0000' => 'var(--highlight-string)', - '#007700' => 'var(--highlight-keyword)', - '#0000BB' => 'var(--highlight-default)', - '#FF8000' => 'var(--highlight-comment)', - ]); ?> -
    - diff --git a/vendor/symfony/error-handler/Resources/views/traces.html.php b/vendor/symfony/error-handler/Resources/views/traces.html.php deleted file mode 100644 index d587b05..0000000 --- a/vendor/symfony/error-handler/Resources/views/traces.html.php +++ /dev/null @@ -1,42 +0,0 @@ -
    -
    -
    - -

    - include('assets/images/icon-minus-square-o.svg'); ?> - include('assets/images/icon-plus-square-o.svg'); ?> - - - 1 ? '\\' : ''; ?> - - -

    - - 1) { ?> -

    escape($exception['message']); ?>

    - -
    -
    - -
    - $trace) { - $isVendorTrace = $trace['file'] && (false !== mb_strpos($trace['file'], '/vendor/') || false !== mb_strpos($trace['file'], '/var/cache/')); - $displayCodeSnippet = $isFirstUserCode && !$isVendorTrace; - if ($displayCodeSnippet) { - $isFirstUserCode = false; - } ?> -
    - include('views/trace.html.php', [ - 'prefix' => $index, - 'i' => $i, - 'trace' => $trace, - 'style' => $isVendorTrace ? 'compact' : ($displayCodeSnippet ? 'expanded' : ''), - ]); ?> -
    - -
    -
    -
    diff --git a/vendor/symfony/error-handler/Resources/views/traces_text.html.php b/vendor/symfony/error-handler/Resources/views/traces_text.html.php deleted file mode 100644 index e178fe0..0000000 --- a/vendor/symfony/error-handler/Resources/views/traces_text.html.php +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - -
    -

    - 1) { ?> - [/] - - - include('assets/images/icon-minus-square-o.svg'); ?> - include('assets/images/icon-plus-square-o.svg'); ?> -

    -
    - -
    -formatArgsAsText($trace['args']) : '').')';
    -                        }
    -                        if ($trace['file'] && $trace['line']) {
    -                            echo($trace['function'] ? "\n     (" : 'at ').strtr(strip_tags($this->formatFile($trace['file'], $trace['line'])), [' at line '.$trace['line'] => '']).':'.$trace['line'].($trace['function'] ? ')' : '');
    -                        }
    -                    }
    -?>
    -                
    - -
    diff --git a/vendor/symfony/error-handler/ThrowableUtils.php b/vendor/symfony/error-handler/ThrowableUtils.php deleted file mode 100644 index 5cbe87f..0000000 --- a/vendor/symfony/error-handler/ThrowableUtils.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ErrorHandler; - -/** - * @internal - */ -class ThrowableUtils -{ - public static function getSeverity(\Throwable $throwable): int - { - if ($throwable instanceof \ErrorException) { - return $throwable->getSeverity(); - } - - if ($throwable instanceof \ParseError) { - return E_PARSE; - } - - if ($throwable instanceof \TypeError) { - return E_RECOVERABLE_ERROR; - } - - return E_ERROR; - } -} diff --git a/vendor/symfony/error-handler/composer.json b/vendor/symfony/error-handler/composer.json deleted file mode 100644 index 3ca2724..0000000 --- a/vendor/symfony/error-handler/composer.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "symfony/error-handler", - "type": "library", - "description": "Symfony ErrorHandler Component", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "psr/log": "^1.0", - "symfony/var-dumper": "^4.4|^5.0" - }, - "require-dev": { - "symfony/http-kernel": "^4.4|^5.0", - "symfony/serializer": "^4.4|^5.0" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\ErrorHandler\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/event-dispatcher-contracts/.gitignore b/vendor/symfony/event-dispatcher-contracts/.gitignore deleted file mode 100644 index c49a5d8..0000000 --- a/vendor/symfony/event-dispatcher-contracts/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/vendor/symfony/event-dispatcher-contracts/Event.php b/vendor/symfony/event-dispatcher-contracts/Event.php deleted file mode 100644 index 46dcb2b..0000000 --- a/vendor/symfony/event-dispatcher-contracts/Event.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\EventDispatcher; - -use Psr\EventDispatcher\StoppableEventInterface; - -/** - * Event 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. - * - * You can call the method stopPropagation() to abort the execution of - * further listeners in your event listener. - * - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Bernhard Schussek - * @author Nicolas Grekas - */ -class Event implements StoppableEventInterface -{ - private $propagationStopped = false; - - /** - * {@inheritdoc} - */ - public function isPropagationStopped(): bool - { - return $this->propagationStopped; - } - - /** - * Stops the propagation of the event to further event listeners. - * - * If multiple event listeners are connected to the same event, no - * further event listener will be triggered once any trigger calls - * stopPropagation(). - */ - public function stopPropagation(): void - { - $this->propagationStopped = true; - } -} diff --git a/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php b/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php deleted file mode 100644 index 351dc51..0000000 --- a/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\EventDispatcher; - -use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface; - -/** - * Allows providing hooks on domain-specific lifecycles by dispatching events. - */ -interface EventDispatcherInterface extends PsrEventDispatcherInterface -{ - /** - * Dispatches an event to all registered listeners. - * - * @param object $event The event to pass to the event handlers/listeners - * @param string|null $eventName The name of the event to dispatch. If not supplied, - * the class of $event should be used instead. - * - * @return object The passed $event MUST be returned - */ - public function dispatch(object $event, string $eventName = null): object; -} diff --git a/vendor/symfony/event-dispatcher-contracts/LICENSE b/vendor/symfony/event-dispatcher-contracts/LICENSE deleted file mode 100644 index 3f853aa..0000000 --- a/vendor/symfony/event-dispatcher-contracts/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2018-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/event-dispatcher-contracts/README.md b/vendor/symfony/event-dispatcher-contracts/README.md deleted file mode 100644 index fb051c7..0000000 --- a/vendor/symfony/event-dispatcher-contracts/README.md +++ /dev/null @@ -1,9 +0,0 @@ -Symfony EventDispatcher Contracts -================================= - -A set of abstractions extracted out of the Symfony components. - -Can be used to build on semantics that the Symfony components proved useful - and -that already have battle tested implementations. - -See https://github.com/symfony/contracts/blob/master/README.md for more information. diff --git a/vendor/symfony/event-dispatcher-contracts/composer.json b/vendor/symfony/event-dispatcher-contracts/composer.json deleted file mode 100644 index f7ba8f1..0000000 --- a/vendor/symfony/event-dispatcher-contracts/composer.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "symfony/event-dispatcher-contracts", - "type": "library", - "description": "Generic abstractions related to dispatching event", - "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "psr/event-dispatcher": "^1" - }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, - "autoload": { - "psr-4": { "Symfony\\Contracts\\EventDispatcher\\": "" } - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - } -} diff --git a/vendor/symfony/event-dispatcher/.gitattributes b/vendor/symfony/event-dispatcher/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/event-dispatcher/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/event-dispatcher/CHANGELOG.md b/vendor/symfony/event-dispatcher/CHANGELOG.md deleted file mode 100644 index ce30074..0000000 --- a/vendor/symfony/event-dispatcher/CHANGELOG.md +++ /dev/null @@ -1,75 +0,0 @@ -CHANGELOG -========= - -5.0.0 ------ - - * The signature of the `EventDispatcherInterface::dispatch()` method has been changed to `dispatch($event, string $eventName = null): object`. - * The `Event` class has been removed in favor of `Symfony\Contracts\EventDispatcher\Event`. - * The `TraceableEventDispatcherInterface` has been removed. - * The `WrappedListener` class is now final. - -4.4.0 ------ - - * `AddEventAliasesPass` has been added, allowing applications and bundles to extend the event alias mapping used by `RegisterListenersPass`. - * Made the `event` attribute of the `kernel.event_listener` tag optional for FQCN events. - -4.3.0 ------ - - * The signature of the `EventDispatcherInterface::dispatch()` method should be updated to `dispatch($event, string $eventName = null)`, not doing so is deprecated - * deprecated the `Event` class, use `Symfony\Contracts\EventDispatcher\Event` instead - -4.1.0 ------ - - * added support for invokable event listeners tagged with `kernel.event_listener` by default - * The `TraceableEventDispatcher::getOrphanedEvents()` method has been added. - * The `TraceableEventDispatcherInterface` has been deprecated. - -4.0.0 ------ - - * removed the `ContainerAwareEventDispatcher` class - * added the `reset()` method to the `TraceableEventDispatcherInterface` - -3.4.0 ------ - - * Implementing `TraceableEventDispatcherInterface` without the `reset()` method has been deprecated. - -3.3.0 ------ - - * The ContainerAwareEventDispatcher class has been deprecated. Use EventDispatcher with closure factories instead. - -3.0.0 ------ - - * The method `getListenerPriority($eventName, $listener)` has been added to the - `EventDispatcherInterface`. - * The methods `Event::setDispatcher()`, `Event::getDispatcher()`, `Event::setName()` - and `Event::getName()` have been removed. - The event dispatcher and the event name are passed to the listener call. - -2.5.0 ------ - - * added Debug\TraceableEventDispatcher (originally in HttpKernel) - * changed Debug\TraceableEventDispatcherInterface to extend EventDispatcherInterface - * added RegisterListenersPass (originally in HttpKernel) - -2.1.0 ------ - - * added TraceableEventDispatcherInterface - * added ContainerAwareEventDispatcher - * added a reference to the EventDispatcher on the Event - * added a reference to the Event name on the event - * added fluid interface to the dispatch() method which now returns the Event - object - * added GenericEvent event class - * added the possibility for subscribers to subscribe several times for the - same event - * added ImmutableEventDispatcher diff --git a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php deleted file mode 100644 index 11dce48..0000000 --- a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php +++ /dev/null @@ -1,363 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Debug; - -use Psr\EventDispatcher\StoppableEventInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\Stopwatch\Stopwatch; -use Symfony\Contracts\Service\ResetInterface; - -/** - * Collects some data about event listeners. - * - * This event dispatcher delegates the dispatching to another one. - * - * @author Fabien Potencier - */ -class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterface -{ - protected $logger; - protected $stopwatch; - - private $callStack; - private $dispatcher; - private $wrappedListeners; - private $orphanedEvents; - private $requestStack; - private $currentRequestHash = ''; - - public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null, RequestStack $requestStack = null) - { - $this->dispatcher = $dispatcher; - $this->stopwatch = $stopwatch; - $this->logger = $logger; - $this->wrappedListeners = []; - $this->orphanedEvents = []; - $this->requestStack = $requestStack; - } - - /** - * {@inheritdoc} - */ - public function addListener(string $eventName, $listener, int $priority = 0) - { - $this->dispatcher->addListener($eventName, $listener, $priority); - } - - /** - * {@inheritdoc} - */ - public function addSubscriber(EventSubscriberInterface $subscriber) - { - $this->dispatcher->addSubscriber($subscriber); - } - - /** - * {@inheritdoc} - */ - public function removeListener(string $eventName, $listener) - { - if (isset($this->wrappedListeners[$eventName])) { - foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { - if ($wrappedListener->getWrappedListener() === $listener) { - $listener = $wrappedListener; - unset($this->wrappedListeners[$eventName][$index]); - break; - } - } - } - - return $this->dispatcher->removeListener($eventName, $listener); - } - - /** - * {@inheritdoc} - */ - public function removeSubscriber(EventSubscriberInterface $subscriber) - { - return $this->dispatcher->removeSubscriber($subscriber); - } - - /** - * {@inheritdoc} - */ - public function getListeners(string $eventName = null) - { - return $this->dispatcher->getListeners($eventName); - } - - /** - * {@inheritdoc} - */ - public function getListenerPriority(string $eventName, $listener) - { - // we might have wrapped listeners for the event (if called while dispatching) - // in that case get the priority by wrapper - if (isset($this->wrappedListeners[$eventName])) { - foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { - if ($wrappedListener->getWrappedListener() === $listener) { - return $this->dispatcher->getListenerPriority($eventName, $wrappedListener); - } - } - } - - return $this->dispatcher->getListenerPriority($eventName, $listener); - } - - /** - * {@inheritdoc} - */ - public function hasListeners(string $eventName = null) - { - return $this->dispatcher->hasListeners($eventName); - } - - /** - * {@inheritdoc} - */ - public function dispatch(object $event, string $eventName = null): object - { - $eventName = $eventName ?? \get_class($event); - - if (null === $this->callStack) { - $this->callStack = new \SplObjectStorage(); - } - - $currentRequestHash = $this->currentRequestHash = $this->requestStack && ($request = $this->requestStack->getCurrentRequest()) ? spl_object_hash($request) : ''; - - if (null !== $this->logger && $event instanceof StoppableEventInterface && $event->isPropagationStopped()) { - $this->logger->debug(sprintf('The "%s" event is already stopped. No listeners have been called.', $eventName)); - } - - $this->preProcess($eventName); - try { - $this->beforeDispatch($eventName, $event); - try { - $e = $this->stopwatch->start($eventName, 'section'); - try { - $this->dispatcher->dispatch($event, $eventName); - } finally { - if ($e->isStarted()) { - $e->stop(); - } - } - } finally { - $this->afterDispatch($eventName, $event); - } - } finally { - $this->currentRequestHash = $currentRequestHash; - $this->postProcess($eventName); - } - - return $event; - } - - /** - * @return array - */ - public function getCalledListeners(Request $request = null) - { - if (null === $this->callStack) { - return []; - } - - $hash = $request ? spl_object_hash($request) : null; - $called = []; - foreach ($this->callStack as $listener) { - list($eventName, $requestHash) = $this->callStack->getInfo(); - if (null === $hash || $hash === $requestHash) { - $called[] = $listener->getInfo($eventName); - } - } - - return $called; - } - - /** - * @return array - */ - public function getNotCalledListeners(Request $request = null) - { - try { - $allListeners = $this->getListeners(); - } catch (\Exception $e) { - if (null !== $this->logger) { - $this->logger->info('An exception was thrown while getting the uncalled listeners.', ['exception' => $e]); - } - - // unable to retrieve the uncalled listeners - return []; - } - - $hash = $request ? spl_object_hash($request) : null; - $calledListeners = []; - - if (null !== $this->callStack) { - foreach ($this->callStack as $calledListener) { - list(, $requestHash) = $this->callStack->getInfo(); - - if (null === $hash || $hash === $requestHash) { - $calledListeners[] = $calledListener->getWrappedListener(); - } - } - } - - $notCalled = []; - foreach ($allListeners as $eventName => $listeners) { - foreach ($listeners as $listener) { - if (!\in_array($listener, $calledListeners, true)) { - if (!$listener instanceof WrappedListener) { - $listener = new WrappedListener($listener, null, $this->stopwatch, $this); - } - $notCalled[] = $listener->getInfo($eventName); - } - } - } - - uasort($notCalled, [$this, 'sortNotCalledListeners']); - - return $notCalled; - } - - public function getOrphanedEvents(Request $request = null): array - { - if ($request) { - return $this->orphanedEvents[spl_object_hash($request)] ?? []; - } - - if (!$this->orphanedEvents) { - return []; - } - - return array_merge(...array_values($this->orphanedEvents)); - } - - public function reset() - { - $this->callStack = null; - $this->orphanedEvents = []; - $this->currentRequestHash = ''; - } - - /** - * Proxies all method calls to the original event dispatcher. - * - * @param string $method The method name - * @param array $arguments The method arguments - * - * @return mixed - */ - public function __call(string $method, array $arguments) - { - return $this->dispatcher->{$method}(...$arguments); - } - - /** - * Called before dispatching the event. - */ - protected function beforeDispatch(string $eventName, object $event) - { - } - - /** - * Called after dispatching the event. - */ - protected function afterDispatch(string $eventName, object $event) - { - } - - private function preProcess(string $eventName): void - { - if (!$this->dispatcher->hasListeners($eventName)) { - $this->orphanedEvents[$this->currentRequestHash][] = $eventName; - - return; - } - - foreach ($this->dispatcher->getListeners($eventName) as $listener) { - $priority = $this->getListenerPriority($eventName, $listener); - $wrappedListener = new WrappedListener($listener instanceof WrappedListener ? $listener->getWrappedListener() : $listener, null, $this->stopwatch, $this); - $this->wrappedListeners[$eventName][] = $wrappedListener; - $this->dispatcher->removeListener($eventName, $listener); - $this->dispatcher->addListener($eventName, $wrappedListener, $priority); - $this->callStack->attach($wrappedListener, [$eventName, $this->currentRequestHash]); - } - } - - private function postProcess(string $eventName): void - { - unset($this->wrappedListeners[$eventName]); - $skipped = false; - foreach ($this->dispatcher->getListeners($eventName) as $listener) { - if (!$listener instanceof WrappedListener) { // #12845: a new listener was added during dispatch. - continue; - } - // Unwrap listener - $priority = $this->getListenerPriority($eventName, $listener); - $this->dispatcher->removeListener($eventName, $listener); - $this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority); - - if (null !== $this->logger) { - $context = ['event' => $eventName, 'listener' => $listener->getPretty()]; - } - - if ($listener->wasCalled()) { - if (null !== $this->logger) { - $this->logger->debug('Notified event "{event}" to listener "{listener}".', $context); - } - } else { - $this->callStack->detach($listener); - } - - if (null !== $this->logger && $skipped) { - $this->logger->debug('Listener "{listener}" was not called for event "{event}".', $context); - } - - if ($listener->stoppedPropagation()) { - if (null !== $this->logger) { - $this->logger->debug('Listener "{listener}" stopped propagation of the event "{event}".', $context); - } - - $skipped = true; - } - } - } - - private function sortNotCalledListeners(array $a, array $b) - { - if (0 !== $cmp = strcmp($a['event'], $b['event'])) { - return $cmp; - } - - if (\is_int($a['priority']) && !\is_int($b['priority'])) { - return 1; - } - - if (!\is_int($a['priority']) && \is_int($b['priority'])) { - return -1; - } - - if ($a['priority'] === $b['priority']) { - return 0; - } - - if ($a['priority'] > $b['priority']) { - return -1; - } - - return 1; - } -} diff --git a/vendor/symfony/event-dispatcher/Debug/WrappedListener.php b/vendor/symfony/event-dispatcher/Debug/WrappedListener.php deleted file mode 100644 index 295bcae..0000000 --- a/vendor/symfony/event-dispatcher/Debug/WrappedListener.php +++ /dev/null @@ -1,127 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Debug; - -use Psr\EventDispatcher\StoppableEventInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Stopwatch\Stopwatch; -use Symfony\Component\VarDumper\Caster\ClassStub; - -/** - * @author Fabien Potencier - */ -final class WrappedListener -{ - private $listener; - private $optimizedListener; - private $name; - private $called; - private $stoppedPropagation; - private $stopwatch; - private $dispatcher; - private $pretty; - private $stub; - private $priority; - private static $hasClassStub; - - public function __construct($listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) - { - $this->listener = $listener; - $this->optimizedListener = $listener instanceof \Closure ? $listener : (\is_callable($listener) ? \Closure::fromCallable($listener) : null); - $this->stopwatch = $stopwatch; - $this->dispatcher = $dispatcher; - $this->called = false; - $this->stoppedPropagation = false; - - if (\is_array($listener)) { - $this->name = \is_object($listener[0]) ? \get_class($listener[0]) : $listener[0]; - $this->pretty = $this->name.'::'.$listener[1]; - } elseif ($listener instanceof \Closure) { - $r = new \ReflectionFunction($listener); - if (false !== strpos($r->name, '{closure}')) { - $this->pretty = $this->name = 'closure'; - } elseif ($class = $r->getClosureScopeClass()) { - $this->name = $class->name; - $this->pretty = $this->name.'::'.$r->name; - } else { - $this->pretty = $this->name = $r->name; - } - } elseif (\is_string($listener)) { - $this->pretty = $this->name = $listener; - } else { - $this->name = \get_class($listener); - $this->pretty = $this->name.'::__invoke'; - } - - if (null !== $name) { - $this->name = $name; - } - - if (null === self::$hasClassStub) { - self::$hasClassStub = class_exists(ClassStub::class); - } - } - - public function getWrappedListener() - { - return $this->listener; - } - - public function wasCalled(): bool - { - return $this->called; - } - - public function stoppedPropagation(): bool - { - return $this->stoppedPropagation; - } - - public function getPretty(): string - { - return $this->pretty; - } - - public function getInfo(string $eventName): array - { - if (null === $this->stub) { - $this->stub = self::$hasClassStub ? new ClassStub($this->pretty.'()', $this->listener) : $this->pretty.'()'; - } - - return [ - 'event' => $eventName, - 'priority' => null !== $this->priority ? $this->priority : (null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null), - 'pretty' => $this->pretty, - 'stub' => $this->stub, - ]; - } - - public function __invoke(object $event, string $eventName, EventDispatcherInterface $dispatcher): void - { - $dispatcher = $this->dispatcher ?: $dispatcher; - - $this->called = true; - $this->priority = $dispatcher->getListenerPriority($eventName, $this->listener); - - $e = $this->stopwatch->start($this->name, 'event_listener'); - - ($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher); - - if ($e->isStarted()) { - $e->stop(); - } - - if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) { - $this->stoppedPropagation = true; - } - } -} diff --git a/vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php b/vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php deleted file mode 100644 index c4ea50f..0000000 --- a/vendor/symfony/event-dispatcher/DependencyInjection/AddEventAliasesPass.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * This pass allows bundles to extend the list of event aliases. - * - * @author Alexander M. Turek - */ -class AddEventAliasesPass implements CompilerPassInterface -{ - private $eventAliases; - private $eventAliasesParameter; - - public function __construct(array $eventAliases, string $eventAliasesParameter = 'event_dispatcher.event_aliases') - { - $this->eventAliases = $eventAliases; - $this->eventAliasesParameter = $eventAliasesParameter; - } - - public function process(ContainerBuilder $container): void - { - $eventAliases = $container->hasParameter($this->eventAliasesParameter) ? $container->getParameter($this->eventAliasesParameter) : []; - - $container->setParameter( - $this->eventAliasesParameter, - array_merge($eventAliases, $this->eventAliases) - ); - } -} diff --git a/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php b/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php deleted file mode 100644 index 7820d35..0000000 --- a/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php +++ /dev/null @@ -1,178 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\EventDispatcher\Event as LegacyEvent; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Contracts\EventDispatcher\Event; - -/** - * Compiler pass to register tagged services for an event dispatcher. - */ -class RegisterListenersPass implements CompilerPassInterface -{ - protected $dispatcherService; - protected $listenerTag; - protected $subscriberTag; - protected $eventAliasesParameter; - - private $hotPathEvents = []; - private $hotPathTagName; - - public function __construct(string $dispatcherService = 'event_dispatcher', string $listenerTag = 'kernel.event_listener', string $subscriberTag = 'kernel.event_subscriber', string $eventAliasesParameter = 'event_dispatcher.event_aliases') - { - $this->dispatcherService = $dispatcherService; - $this->listenerTag = $listenerTag; - $this->subscriberTag = $subscriberTag; - $this->eventAliasesParameter = $eventAliasesParameter; - } - - public function setHotPathEvents(array $hotPathEvents, $tagName = 'container.hot_path') - { - $this->hotPathEvents = array_flip($hotPathEvents); - $this->hotPathTagName = $tagName; - - return $this; - } - - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) { - return; - } - - if ($container->hasParameter($this->eventAliasesParameter)) { - $aliases = $container->getParameter($this->eventAliasesParameter); - $container->getParameterBag()->remove($this->eventAliasesParameter); - } else { - $aliases = []; - } - $definition = $container->findDefinition($this->dispatcherService); - - foreach ($container->findTaggedServiceIds($this->listenerTag, true) as $id => $events) { - foreach ($events as $event) { - $priority = isset($event['priority']) ? $event['priority'] : 0; - - if (!isset($event['event'])) { - if ($container->getDefinition($id)->hasTag($this->subscriberTag)) { - continue; - } - - $event['method'] = $event['method'] ?? '__invoke'; - $event['event'] = $this->getEventFromTypeDeclaration($container, $id, $event['method']); - } - - $event['event'] = $aliases[$event['event']] ?? $event['event']; - - if (!isset($event['method'])) { - $event['method'] = 'on'.preg_replace_callback([ - '/(?<=\b)[a-z]/i', - '/[^a-z0-9]/i', - ], function ($matches) { return strtoupper($matches[0]); }, $event['event']); - $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); - - if (null !== ($class = $container->getDefinition($id)->getClass()) && ($r = $container->getReflectionClass($class, false)) && !$r->hasMethod($event['method']) && $r->hasMethod('__invoke')) { - $event['method'] = '__invoke'; - } - } - - $definition->addMethodCall('addListener', [$event['event'], [new ServiceClosureArgument(new Reference($id)), $event['method']], $priority]); - - if (isset($this->hotPathEvents[$event['event']])) { - $container->getDefinition($id)->addTag($this->hotPathTagName); - } - } - } - - $extractingDispatcher = new ExtractingEventDispatcher(); - - foreach ($container->findTaggedServiceIds($this->subscriberTag, true) as $id => $attributes) { - $def = $container->getDefinition($id); - - // We must assume that the class value has been correctly filled, even if the service is created by a factory - $class = $def->getClass(); - - if (!$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } - if (!$r->isSubclassOf(EventSubscriberInterface::class)) { - throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EventSubscriberInterface::class)); - } - $class = $r->name; - - ExtractingEventDispatcher::$aliases = $aliases; - ExtractingEventDispatcher::$subscriber = $class; - $extractingDispatcher->addSubscriber($extractingDispatcher); - foreach ($extractingDispatcher->listeners as $args) { - $args[1] = [new ServiceClosureArgument(new Reference($id)), $args[1]]; - $definition->addMethodCall('addListener', $args); - - if (isset($this->hotPathEvents[$args[0]])) { - $container->getDefinition($id)->addTag($this->hotPathTagName); - } - } - $extractingDispatcher->listeners = []; - ExtractingEventDispatcher::$aliases = []; - } - } - - private function getEventFromTypeDeclaration(ContainerBuilder $container, string $id, string $method): string - { - if ( - null === ($class = $container->getDefinition($id)->getClass()) - || !($r = $container->getReflectionClass($class, false)) - || !$r->hasMethod($method) - || 1 > ($m = $r->getMethod($method))->getNumberOfParameters() - || !($type = $m->getParameters()[0]->getType()) - || $type->isBuiltin() - || Event::class === ($name = $type->getName()) - || LegacyEvent::class === $name - ) { - throw new InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag)); - } - - return $name; - } -} - -/** - * @internal - */ -class ExtractingEventDispatcher extends EventDispatcher implements EventSubscriberInterface -{ - public $listeners = []; - - public static $aliases = []; - public static $subscriber; - - public function addListener(string $eventName, $listener, int $priority = 0) - { - $this->listeners[] = [$eventName, $listener[1], $priority]; - } - - public static function getSubscribedEvents(): array - { - $events = []; - - foreach ([self::$subscriber, 'getSubscribedEvents']() as $eventName => $params) { - $events[self::$aliases[$eventName] ?? $eventName] = $params; - } - - return $events; - } -} diff --git a/vendor/symfony/event-dispatcher/EventDispatcher.php b/vendor/symfony/event-dispatcher/EventDispatcher.php deleted file mode 100644 index c0f839b..0000000 --- a/vendor/symfony/event-dispatcher/EventDispatcher.php +++ /dev/null @@ -1,280 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -use Psr\EventDispatcher\StoppableEventInterface; -use Symfony\Component\EventDispatcher\Debug\WrappedListener; - -/** - * The EventDispatcherInterface is the central point of Symfony's event listener system. - * - * Listeners are registered on the manager and events are dispatched through the - * manager. - * - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Bernhard Schussek - * @author Fabien Potencier - * @author Jordi Boggiano - * @author Jordan Alliot - * @author Nicolas Grekas - */ -class EventDispatcher implements EventDispatcherInterface -{ - private $listeners = []; - private $sorted = []; - private $optimized; - - public function __construct() - { - if (__CLASS__ === \get_class($this)) { - $this->optimized = []; - } - } - - /** - * {@inheritdoc} - */ - public function dispatch(object $event, string $eventName = null): object - { - $eventName = $eventName ?? \get_class($event); - - if (null !== $this->optimized && null !== $eventName) { - $listeners = $this->optimized[$eventName] ?? (empty($this->listeners[$eventName]) ? [] : $this->optimizeListeners($eventName)); - } else { - $listeners = $this->getListeners($eventName); - } - - if ($listeners) { - $this->callListeners($listeners, $eventName, $event); - } - - return $event; - } - - /** - * {@inheritdoc} - */ - public function getListeners(string $eventName = null) - { - if (null !== $eventName) { - if (empty($this->listeners[$eventName])) { - return []; - } - - if (!isset($this->sorted[$eventName])) { - $this->sortListeners($eventName); - } - - return $this->sorted[$eventName]; - } - - foreach ($this->listeners as $eventName => $eventListeners) { - if (!isset($this->sorted[$eventName])) { - $this->sortListeners($eventName); - } - } - - return array_filter($this->sorted); - } - - /** - * {@inheritdoc} - */ - public function getListenerPriority(string $eventName, $listener) - { - if (empty($this->listeners[$eventName])) { - return null; - } - - if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { - $listener[0] = $listener[0](); - $listener[1] = $listener[1] ?? '__invoke'; - } - - foreach ($this->listeners[$eventName] as $priority => &$listeners) { - foreach ($listeners as &$v) { - if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) { - $v[0] = $v[0](); - $v[1] = $v[1] ?? '__invoke'; - } - if ($v === $listener) { - return $priority; - } - } - } - - return null; - } - - /** - * {@inheritdoc} - */ - public function hasListeners(string $eventName = null) - { - if (null !== $eventName) { - return !empty($this->listeners[$eventName]); - } - - foreach ($this->listeners as $eventListeners) { - if ($eventListeners) { - return true; - } - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function addListener(string $eventName, $listener, int $priority = 0) - { - $this->listeners[$eventName][$priority][] = $listener; - unset($this->sorted[$eventName], $this->optimized[$eventName]); - } - - /** - * {@inheritdoc} - */ - public function removeListener(string $eventName, $listener) - { - if (empty($this->listeners[$eventName])) { - return; - } - - if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { - $listener[0] = $listener[0](); - $listener[1] = $listener[1] ?? '__invoke'; - } - - foreach ($this->listeners[$eventName] as $priority => &$listeners) { - foreach ($listeners as $k => &$v) { - if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) { - $v[0] = $v[0](); - $v[1] = $v[1] ?? '__invoke'; - } - if ($v === $listener) { - unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]); - } - } - - if (!$listeners) { - unset($this->listeners[$eventName][$priority]); - } - } - } - - /** - * {@inheritdoc} - */ - public function addSubscriber(EventSubscriberInterface $subscriber) - { - foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { - if (\is_string($params)) { - $this->addListener($eventName, [$subscriber, $params]); - } elseif (\is_string($params[0])) { - $this->addListener($eventName, [$subscriber, $params[0]], isset($params[1]) ? $params[1] : 0); - } else { - foreach ($params as $listener) { - $this->addListener($eventName, [$subscriber, $listener[0]], isset($listener[1]) ? $listener[1] : 0); - } - } - } - } - - /** - * {@inheritdoc} - */ - public function removeSubscriber(EventSubscriberInterface $subscriber) - { - foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { - if (\is_array($params) && \is_array($params[0])) { - foreach ($params as $listener) { - $this->removeListener($eventName, [$subscriber, $listener[0]]); - } - } else { - $this->removeListener($eventName, [$subscriber, \is_string($params) ? $params : $params[0]]); - } - } - } - - /** - * Triggers the listeners of an event. - * - * This method can be overridden to add functionality that is executed - * for each listener. - * - * @param callable[] $listeners The event listeners - * @param string $eventName The name of the event to dispatch - * @param object $event The event object to pass to the event handlers/listeners - */ - protected function callListeners(iterable $listeners, string $eventName, object $event) - { - $stoppable = $event instanceof StoppableEventInterface; - - foreach ($listeners as $listener) { - if ($stoppable && $event->isPropagationStopped()) { - break; - } - $listener($event, $eventName, $this); - } - } - - /** - * Sorts the internal list of listeners for the given event by priority. - */ - private function sortListeners(string $eventName) - { - krsort($this->listeners[$eventName]); - $this->sorted[$eventName] = []; - - foreach ($this->listeners[$eventName] as &$listeners) { - foreach ($listeners as $k => $listener) { - if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { - $listener[0] = $listener[0](); - $listener[1] = $listener[1] ?? '__invoke'; - } - $this->sorted[$eventName][] = $listener; - } - } - } - - /** - * Optimizes the internal list of listeners for the given event by priority. - */ - private function optimizeListeners(string $eventName): array - { - krsort($this->listeners[$eventName]); - $this->optimized[$eventName] = []; - - foreach ($this->listeners[$eventName] as &$listeners) { - foreach ($listeners as &$listener) { - $closure = &$this->optimized[$eventName][]; - if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { - $closure = static function (...$args) use (&$listener, &$closure) { - if ($listener[0] instanceof \Closure) { - $listener[0] = $listener[0](); - $listener[1] = $listener[1] ?? '__invoke'; - } - ($closure = \Closure::fromCallable($listener))(...$args); - }; - } else { - $closure = $listener instanceof \Closure || $listener instanceof WrappedListener ? $listener : \Closure::fromCallable($listener); - } - } - } - - return $this->optimized[$eventName]; - } -} diff --git a/vendor/symfony/event-dispatcher/EventDispatcherInterface.php b/vendor/symfony/event-dispatcher/EventDispatcherInterface.php deleted file mode 100644 index 88c707c..0000000 --- a/vendor/symfony/event-dispatcher/EventDispatcherInterface.php +++ /dev/null @@ -1,75 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface as ContractsEventDispatcherInterface; - -/** - * The EventDispatcherInterface is the central point of Symfony's event listener system. - * Listeners are registered on the manager and events are dispatched through the - * manager. - * - * @author Bernhard Schussek - */ -interface EventDispatcherInterface extends ContractsEventDispatcherInterface -{ - /** - * Adds an event listener that listens on the specified events. - * - * @param callable $listener The listener - * @param int $priority The higher this value, the earlier an event - * listener will be triggered in the chain (defaults to 0) - */ - public function addListener(string $eventName, $listener, int $priority = 0); - - /** - * Adds an event subscriber. - * - * The subscriber is asked for all the events it is - * interested in and added as a listener for these events. - */ - public function addSubscriber(EventSubscriberInterface $subscriber); - - /** - * Removes an event listener from the specified events. - * - * @param callable $listener The listener to remove - */ - public function removeListener(string $eventName, $listener); - - public function removeSubscriber(EventSubscriberInterface $subscriber); - - /** - * Gets the listeners of a specific event or all listeners sorted by descending priority. - * - * @return array The event listeners for the specified event, or all event listeners by event name - */ - public function getListeners(string $eventName = null); - - /** - * Gets the listener priority for a specific event. - * - * Returns null if the event or the listener does not exist. - * - * @param callable $listener The listener - * - * @return int|null The event listener priority - */ - public function getListenerPriority(string $eventName, $listener); - - /** - * Checks whether an event has any registered listeners. - * - * @return bool true if the specified event has any listeners, false otherwise - */ - public function hasListeners(string $eventName = null); -} diff --git a/vendor/symfony/event-dispatcher/EventSubscriberInterface.php b/vendor/symfony/event-dispatcher/EventSubscriberInterface.php deleted file mode 100644 index 824f215..0000000 --- a/vendor/symfony/event-dispatcher/EventSubscriberInterface.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -/** - * An EventSubscriber knows itself what events it is interested in. - * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes - * {@link getSubscribedEvents} and registers the subscriber as a listener for all - * returned events. - * - * @author Guilherme Blanco - * @author Jonathan Wage - * @author Roman Borschel - * @author Bernhard Schussek - */ -interface EventSubscriberInterface -{ - /** - * Returns an array of event names this subscriber wants to listen to. - * - * The array keys are event names and the value can be: - * - * * The method name to call (priority defaults to 0) - * * An array composed of the method name to call and the priority - * * An array of arrays composed of the method names to call and respective - * priorities, or 0 if unset - * - * For instance: - * - * * ['eventName' => 'methodName'] - * * ['eventName' => ['methodName', $priority]] - * * ['eventName' => [['methodName1', $priority], ['methodName2']]] - * - * @return array The event names to listen to - */ - public static function getSubscribedEvents(); -} diff --git a/vendor/symfony/event-dispatcher/GenericEvent.php b/vendor/symfony/event-dispatcher/GenericEvent.php deleted file mode 100644 index 34b95ce..0000000 --- a/vendor/symfony/event-dispatcher/GenericEvent.php +++ /dev/null @@ -1,170 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -use Symfony\Contracts\EventDispatcher\Event; - -/** - * Event encapsulation class. - * - * Encapsulates events thus decoupling the observer from the subject they encapsulate. - * - * @author Drak - */ -class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate -{ - protected $subject; - protected $arguments; - - /** - * Encapsulate an event with $subject and $args. - * - * @param mixed $subject The subject of the event, usually an object or a callable - * @param array $arguments Arguments to store in the event - */ - public function __construct($subject = null, array $arguments = []) - { - $this->subject = $subject; - $this->arguments = $arguments; - } - - /** - * Getter for subject property. - * - * @return mixed The observer subject - */ - public function getSubject() - { - return $this->subject; - } - - /** - * Get argument by key. - * - * @return mixed Contents of array key - * - * @throws \InvalidArgumentException if key is not found - */ - public function getArgument(string $key) - { - if ($this->hasArgument($key)) { - return $this->arguments[$key]; - } - - throw new \InvalidArgumentException(sprintf('Argument "%s" not found.', $key)); - } - - /** - * Add argument to event. - * - * @param mixed $value Value - * - * @return $this - */ - public function setArgument(string $key, $value) - { - $this->arguments[$key] = $value; - - return $this; - } - - /** - * Getter for all arguments. - * - * @return array - */ - public function getArguments() - { - return $this->arguments; - } - - /** - * Set args property. - * - * @return $this - */ - public function setArguments(array $args = []) - { - $this->arguments = $args; - - return $this; - } - - /** - * Has argument. - * - * @return bool - */ - public function hasArgument(string $key) - { - return \array_key_exists($key, $this->arguments); - } - - /** - * ArrayAccess for argument getter. - * - * @param string $key Array key - * - * @return mixed - * - * @throws \InvalidArgumentException if key does not exist in $this->args - */ - public function offsetGet($key) - { - return $this->getArgument($key); - } - - /** - * ArrayAccess for argument setter. - * - * @param string $key Array key to set - * @param mixed $value Value - */ - public function offsetSet($key, $value) - { - $this->setArgument($key, $value); - } - - /** - * ArrayAccess for unset argument. - * - * @param string $key Array key - */ - public function offsetUnset($key) - { - if ($this->hasArgument($key)) { - unset($this->arguments[$key]); - } - } - - /** - * ArrayAccess has argument. - * - * @param string $key Array key - * - * @return bool - */ - public function offsetExists($key) - { - return $this->hasArgument($key); - } - - /** - * IteratorAggregate for iterating over the object like an array. - * - * @return \ArrayIterator - */ - public function getIterator() - { - return new \ArrayIterator($this->arguments); - } -} diff --git a/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php b/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php deleted file mode 100644 index 568d79c..0000000 --- a/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php +++ /dev/null @@ -1,91 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -/** - * A read-only proxy for an event dispatcher. - * - * @author Bernhard Schussek - */ -class ImmutableEventDispatcher implements EventDispatcherInterface -{ - private $dispatcher; - - public function __construct(EventDispatcherInterface $dispatcher) - { - $this->dispatcher = $dispatcher; - } - - /** - * {@inheritdoc} - */ - public function dispatch(object $event, string $eventName = null): object - { - return $this->dispatcher->dispatch($event, $eventName); - } - - /** - * {@inheritdoc} - */ - public function addListener(string $eventName, $listener, int $priority = 0) - { - throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); - } - - /** - * {@inheritdoc} - */ - public function addSubscriber(EventSubscriberInterface $subscriber) - { - throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); - } - - /** - * {@inheritdoc} - */ - public function removeListener(string $eventName, $listener) - { - throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); - } - - /** - * {@inheritdoc} - */ - public function removeSubscriber(EventSubscriberInterface $subscriber) - { - throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); - } - - /** - * {@inheritdoc} - */ - public function getListeners(string $eventName = null) - { - return $this->dispatcher->getListeners($eventName); - } - - /** - * {@inheritdoc} - */ - public function getListenerPriority(string $eventName, $listener) - { - return $this->dispatcher->getListenerPriority($eventName, $listener); - } - - /** - * {@inheritdoc} - */ - public function hasListeners(string $eventName = null) - { - return $this->dispatcher->hasListeners($eventName); - } -} diff --git a/vendor/symfony/event-dispatcher/LICENSE b/vendor/symfony/event-dispatcher/LICENSE deleted file mode 100644 index a677f43..0000000 --- a/vendor/symfony/event-dispatcher/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php b/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php deleted file mode 100644 index a44b766..0000000 --- a/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; - -/** - * A helper class to provide BC/FC with the legacy signature of EventDispatcherInterface::dispatch(). - * - * This class should be deprecated in Symfony 5.1 - * - * @author Nicolas Grekas - */ -final class LegacyEventDispatcherProxy -{ - public static function decorate(?EventDispatcherInterface $dispatcher): ?EventDispatcherInterface - { - return $dispatcher; - } -} diff --git a/vendor/symfony/event-dispatcher/README.md b/vendor/symfony/event-dispatcher/README.md deleted file mode 100644 index 185c3fe..0000000 --- a/vendor/symfony/event-dispatcher/README.md +++ /dev/null @@ -1,15 +0,0 @@ -EventDispatcher Component -========================= - -The EventDispatcher component provides tools that allow your application -components to communicate with each other by dispatching events and listening to -them. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/event_dispatcher/index.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/event-dispatcher/composer.json b/vendor/symfony/event-dispatcher/composer.json deleted file mode 100644 index e867a7c..0000000 --- a/vendor/symfony/event-dispatcher/composer.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "symfony/event-dispatcher", - "type": "library", - "description": "Symfony EventDispatcher Component", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "symfony/event-dispatcher-contracts": "^2" - }, - "require-dev": { - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/config": "^4.4|^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/service-contracts": "^1.1|^2", - "symfony/stopwatch": "^4.4|^5.0", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/dependency-injection": "<4.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/filesystem/.gitattributes b/vendor/symfony/filesystem/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/filesystem/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/filesystem/CHANGELOG.md b/vendor/symfony/filesystem/CHANGELOG.md deleted file mode 100644 index d103bc2..0000000 --- a/vendor/symfony/filesystem/CHANGELOG.md +++ /dev/null @@ -1,75 +0,0 @@ -CHANGELOG -========= - -5.0.0 ------ - - * `Filesystem::dumpFile()` and `appendToFile()` don't accept arrays anymore - -4.4.0 ------ - - * support for passing a `null` value to `Filesystem::isAbsolutePath()` is deprecated and will be removed in 5.0 - -4.3.0 ------ - - * support for passing arrays to `Filesystem::dumpFile()` is deprecated and will be removed in 5.0 - * support for passing arrays to `Filesystem::appendToFile()` is deprecated and will be removed in 5.0 - -4.0.0 ------ - - * removed `LockHandler` - * Support for passing relative paths to `Filesystem::makePathRelative()` has been removed. - -3.4.0 ------ - - * support for passing relative paths to `Filesystem::makePathRelative()` is deprecated and will be removed in 4.0 - -3.3.0 ------ - - * added `appendToFile()` to append contents to existing files - -3.2.0 ------ - - * added `readlink()` as a platform independent method to read links - -3.0.0 ------ - - * removed `$mode` argument from `Filesystem::dumpFile()` - -2.8.0 ------ - - * added tempnam() a stream aware version of PHP's native tempnam() - -2.6.0 ------ - - * added LockHandler - -2.3.12 ------- - - * deprecated dumpFile() file mode argument. - -2.3.0 ------ - - * added the dumpFile() method to atomically write files - -2.2.0 ------ - - * added a delete option for the mirror() method - -2.1.0 ------ - - * 24eb396 : BC Break : mkdir() function now throws exception in case of failure instead of returning Boolean value - * created the component diff --git a/vendor/symfony/filesystem/Exception/ExceptionInterface.php b/vendor/symfony/filesystem/Exception/ExceptionInterface.php deleted file mode 100644 index fc438d9..0000000 --- a/vendor/symfony/filesystem/Exception/ExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * Exception interface for all exceptions thrown by the component. - * - * @author Romain Neutron - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/vendor/symfony/filesystem/Exception/FileNotFoundException.php b/vendor/symfony/filesystem/Exception/FileNotFoundException.php deleted file mode 100644 index 48b6408..0000000 --- a/vendor/symfony/filesystem/Exception/FileNotFoundException.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * Exception class thrown when a file couldn't be found. - * - * @author Fabien Potencier - * @author Christian Gärtner - */ -class FileNotFoundException extends IOException -{ - public function __construct(string $message = null, int $code = 0, \Throwable $previous = null, string $path = null) - { - if (null === $message) { - if (null === $path) { - $message = 'File could not be found.'; - } else { - $message = sprintf('File "%s" could not be found.', $path); - } - } - - parent::__construct($message, $code, $previous, $path); - } -} diff --git a/vendor/symfony/filesystem/Exception/IOException.php b/vendor/symfony/filesystem/Exception/IOException.php deleted file mode 100644 index fea26e4..0000000 --- a/vendor/symfony/filesystem/Exception/IOException.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * Exception class thrown when a filesystem operation failure happens. - * - * @author Romain Neutron - * @author Christian Gärtner - * @author Fabien Potencier - */ -class IOException extends \RuntimeException implements IOExceptionInterface -{ - private $path; - - public function __construct(string $message, int $code = 0, \Throwable $previous = null, string $path = null) - { - $this->path = $path; - - parent::__construct($message, $code, $previous); - } - - /** - * {@inheritdoc} - */ - public function getPath() - { - return $this->path; - } -} diff --git a/vendor/symfony/filesystem/Exception/IOExceptionInterface.php b/vendor/symfony/filesystem/Exception/IOExceptionInterface.php deleted file mode 100644 index f9d4644..0000000 --- a/vendor/symfony/filesystem/Exception/IOExceptionInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * IOException interface for file and input/output stream related exceptions thrown by the component. - * - * @author Christian Gärtner - */ -interface IOExceptionInterface extends ExceptionInterface -{ - /** - * Returns the associated path for the exception. - * - * @return string|null The path - */ - public function getPath(); -} diff --git a/vendor/symfony/filesystem/Exception/InvalidArgumentException.php b/vendor/symfony/filesystem/Exception/InvalidArgumentException.php deleted file mode 100644 index abadc20..0000000 --- a/vendor/symfony/filesystem/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Exception; - -/** - * @author Christian Flothmann - */ -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/filesystem/Filesystem.php b/vendor/symfony/filesystem/Filesystem.php deleted file mode 100644 index 76c10b0..0000000 --- a/vendor/symfony/filesystem/Filesystem.php +++ /dev/null @@ -1,734 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem; - -use Symfony\Component\Filesystem\Exception\FileNotFoundException; -use Symfony\Component\Filesystem\Exception\InvalidArgumentException; -use Symfony\Component\Filesystem\Exception\IOException; - -/** - * Provides basic utility to manipulate the file system. - * - * @author Fabien Potencier - */ -class Filesystem -{ - private static $lastError; - - /** - * Copies a file. - * - * If the target file is older than the origin file, it's always overwritten. - * If the target file is newer, it is overwritten only when the - * $overwriteNewerFiles option is set to true. - * - * @throws FileNotFoundException When originFile doesn't exist - * @throws IOException When copy fails - */ - public function copy(string $originFile, string $targetFile, bool $overwriteNewerFiles = false) - { - $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://'); - if ($originIsLocal && !is_file($originFile)) { - throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile); - } - - $this->mkdir(\dirname($targetFile)); - - $doCopy = true; - if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) { - $doCopy = filemtime($originFile) > filemtime($targetFile); - } - - if ($doCopy) { - // https://bugs.php.net/64634 - if (false === $source = @fopen($originFile, 'r')) { - throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile); - } - - // Stream context created to allow files overwrite when using FTP stream wrapper - disabled by default - if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(['ftp' => ['overwrite' => true]]))) { - throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile); - } - - $bytesCopied = stream_copy_to_stream($source, $target); - fclose($source); - fclose($target); - unset($source, $target); - - if (!is_file($targetFile)) { - throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile); - } - - if ($originIsLocal) { - // Like `cp`, preserve executable permission bits - @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111)); - - if ($bytesCopied !== $bytesOrigin = filesize($originFile)) { - throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile); - } - } - } - } - - /** - * Creates a directory recursively. - * - * @param string|iterable $dirs The directory path - * - * @throws IOException On any directory creation failure - */ - public function mkdir($dirs, int $mode = 0777) - { - foreach ($this->toIterable($dirs) as $dir) { - if (is_dir($dir)) { - continue; - } - - if (!self::box('mkdir', $dir, $mode, true)) { - if (!is_dir($dir)) { - // The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one - if (self::$lastError) { - throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir); - } - throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir); - } - } - } - } - - /** - * Checks the existence of files or directories. - * - * @param string|iterable $files A filename, an array of files, or a \Traversable instance to check - * - * @return bool true if the file exists, false otherwise - */ - public function exists($files) - { - $maxPathLength = PHP_MAXPATHLEN - 2; - - foreach ($this->toIterable($files) as $file) { - if (\strlen($file) > $maxPathLength) { - throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file); - } - - if (!file_exists($file)) { - return false; - } - } - - return true; - } - - /** - * Sets access and modification time of file. - * - * @param string|iterable $files A filename, an array of files, or a \Traversable instance to create - * @param int|null $time The touch time as a Unix timestamp, if not supplied the current system time is used - * @param int|null $atime The access time as a Unix timestamp, if not supplied the current system time is used - * - * @throws IOException When touch fails - */ - public function touch($files, int $time = null, int $atime = null) - { - foreach ($this->toIterable($files) as $file) { - $touch = $time ? @touch($file, $time, $atime) : @touch($file); - if (true !== $touch) { - throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file); - } - } - } - - /** - * Removes files or directories. - * - * @param string|iterable $files A filename, an array of files, or a \Traversable instance to remove - * - * @throws IOException When removal fails - */ - public function remove($files) - { - if ($files instanceof \Traversable) { - $files = iterator_to_array($files, false); - } elseif (!\is_array($files)) { - $files = [$files]; - } - $files = array_reverse($files); - foreach ($files as $file) { - if (is_link($file)) { - // See https://bugs.php.net/52176 - if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) { - throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError)); - } - } elseif (is_dir($file)) { - $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS)); - - if (!self::box('rmdir', $file) && file_exists($file)) { - throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError)); - } - } elseif (!self::box('unlink', $file) && file_exists($file)) { - throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError)); - } - } - } - - /** - * Change mode for an array of files or directories. - * - * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change mode - * @param int $mode The new mode (octal) - * @param int $umask The mode mask (octal) - * @param bool $recursive Whether change the mod recursively or not - * - * @throws IOException When the change fails - */ - public function chmod($files, int $mode, int $umask = 0000, bool $recursive = false) - { - foreach ($this->toIterable($files) as $file) { - if (true !== @chmod($file, $mode & ~$umask)) { - throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file); - } - if ($recursive && is_dir($file) && !is_link($file)) { - $this->chmod(new \FilesystemIterator($file), $mode, $umask, true); - } - } - } - - /** - * Change the owner of an array of files or directories. - * - * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change owner - * - * @throws IOException When the change fails - */ - public function chown($files, string $user, bool $recursive = false) - { - foreach ($this->toIterable($files) as $file) { - if ($recursive && is_dir($file) && !is_link($file)) { - $this->chown(new \FilesystemIterator($file), $user, true); - } - if (is_link($file) && \function_exists('lchown')) { - if (true !== @lchown($file, $user)) { - throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file); - } - } else { - if (true !== @chown($file, $user)) { - throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file); - } - } - } - } - - /** - * Change the group of an array of files or directories. - * - * @param string|iterable $files A filename, an array of files, or a \Traversable instance to change group - * - * @throws IOException When the change fails - */ - public function chgrp($files, string $group, bool $recursive = false) - { - foreach ($this->toIterable($files) as $file) { - if ($recursive && is_dir($file) && !is_link($file)) { - $this->chgrp(new \FilesystemIterator($file), $group, true); - } - if (is_link($file) && \function_exists('lchgrp')) { - if (true !== @lchgrp($file, $group)) { - throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file); - } - } else { - if (true !== @chgrp($file, $group)) { - throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file); - } - } - } - } - - /** - * Renames a file or a directory. - * - * @throws IOException When target file or directory already exists - * @throws IOException When origin cannot be renamed - */ - public function rename(string $origin, string $target, bool $overwrite = false) - { - // we check that target does not exist - if (!$overwrite && $this->isReadable($target)) { - throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target); - } - - if (true !== @rename($origin, $target)) { - if (is_dir($origin)) { - // See https://bugs.php.net/54097 & https://php.net/rename#113943 - $this->mirror($origin, $target, null, ['override' => $overwrite, 'delete' => $overwrite]); - $this->remove($origin); - - return; - } - throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target); - } - } - - /** - * Tells whether a file exists and is readable. - * - * @throws IOException When windows path is longer than 258 characters - */ - private function isReadable(string $filename): bool - { - $maxPathLength = PHP_MAXPATHLEN - 2; - - if (\strlen($filename) > $maxPathLength) { - throw new IOException(sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename); - } - - return is_readable($filename); - } - - /** - * Creates a symbolic link or copy a directory. - * - * @throws IOException When symlink fails - */ - public function symlink(string $originDir, string $targetDir, bool $copyOnWindows = false) - { - if ('\\' === \DIRECTORY_SEPARATOR) { - $originDir = strtr($originDir, '/', '\\'); - $targetDir = strtr($targetDir, '/', '\\'); - - if ($copyOnWindows) { - $this->mirror($originDir, $targetDir); - - return; - } - } - - $this->mkdir(\dirname($targetDir)); - - if (is_link($targetDir)) { - if (readlink($targetDir) === $originDir) { - return; - } - $this->remove($targetDir); - } - - if (!self::box('symlink', $originDir, $targetDir)) { - $this->linkException($originDir, $targetDir, 'symbolic'); - } - } - - /** - * Creates a hard link, or several hard links to a file. - * - * @param string|string[] $targetFiles The target file(s) - * - * @throws FileNotFoundException When original file is missing or not a file - * @throws IOException When link fails, including if link already exists - */ - public function hardlink(string $originFile, $targetFiles) - { - if (!$this->exists($originFile)) { - throw new FileNotFoundException(null, 0, null, $originFile); - } - - if (!is_file($originFile)) { - throw new FileNotFoundException(sprintf('Origin file "%s" is not a file', $originFile)); - } - - foreach ($this->toIterable($targetFiles) as $targetFile) { - if (is_file($targetFile)) { - if (fileinode($originFile) === fileinode($targetFile)) { - continue; - } - $this->remove($targetFile); - } - - if (!self::box('link', $originFile, $targetFile)) { - $this->linkException($originFile, $targetFile, 'hard'); - } - } - } - - /** - * @param string $linkType Name of the link type, typically 'symbolic' or 'hard' - */ - private function linkException(string $origin, string $target, string $linkType) - { - if (self::$lastError) { - if ('\\' === \DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) { - throw new IOException(sprintf('Unable to create %s link due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', $linkType), 0, null, $target); - } - } - throw new IOException(sprintf('Failed to create %s link from "%s" to "%s".', $linkType, $origin, $target), 0, null, $target); - } - - /** - * Resolves links in paths. - * - * With $canonicalize = false (default) - * - if $path does not exist or is not a link, returns null - * - if $path is a link, returns the next direct target of the link without considering the existence of the target - * - * With $canonicalize = true - * - if $path does not exist, returns null - * - if $path exists, returns its absolute fully resolved final version - * - * @return string|null - */ - public function readlink(string $path, bool $canonicalize = false) - { - if (!$canonicalize && !is_link($path)) { - return null; - } - - if ($canonicalize) { - if (!$this->exists($path)) { - return null; - } - - if ('\\' === \DIRECTORY_SEPARATOR) { - $path = readlink($path); - } - - return realpath($path); - } - - if ('\\' === \DIRECTORY_SEPARATOR) { - return realpath($path); - } - - return readlink($path); - } - - /** - * Given an existing path, convert it to a path relative to a given starting path. - * - * @return string Path of target relative to starting path - */ - public function makePathRelative(string $endPath, string $startPath) - { - if (!$this->isAbsolutePath($startPath)) { - throw new InvalidArgumentException(sprintf('The start path "%s" is not absolute.', $startPath)); - } - - if (!$this->isAbsolutePath($endPath)) { - throw new InvalidArgumentException(sprintf('The end path "%s" is not absolute.', $endPath)); - } - - // Normalize separators on Windows - if ('\\' === \DIRECTORY_SEPARATOR) { - $endPath = str_replace('\\', '/', $endPath); - $startPath = str_replace('\\', '/', $startPath); - } - - $stripDriveLetter = function ($path) { - if (\strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) { - return substr($path, 2); - } - - return $path; - }; - - $endPath = $stripDriveLetter($endPath); - $startPath = $stripDriveLetter($startPath); - - // Split the paths into arrays - $startPathArr = explode('/', trim($startPath, '/')); - $endPathArr = explode('/', trim($endPath, '/')); - - $normalizePathArray = function ($pathSegments) { - $result = []; - - foreach ($pathSegments as $segment) { - if ('..' === $segment) { - array_pop($result); - } elseif ('.' !== $segment) { - $result[] = $segment; - } - } - - return $result; - }; - - $startPathArr = $normalizePathArray($startPathArr); - $endPathArr = $normalizePathArray($endPathArr); - - // Find for which directory the common path stops - $index = 0; - while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) { - ++$index; - } - - // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels) - if (1 === \count($startPathArr) && '' === $startPathArr[0]) { - $depth = 0; - } else { - $depth = \count($startPathArr) - $index; - } - - // Repeated "../" for each level need to reach the common path - $traverser = str_repeat('../', $depth); - - $endPathRemainder = implode('/', \array_slice($endPathArr, $index)); - - // Construct $endPath from traversing to the common path, then to the remaining $endPath - $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : ''); - - return '' === $relativePath ? './' : $relativePath; - } - - /** - * Mirrors a directory to another. - * - * Copies files and directories from the origin directory into the target directory. By default: - * - * - existing files in the target directory will be overwritten, except if they are newer (see the `override` option) - * - files in the target directory that do not exist in the source directory will not be deleted (see the `delete` option) - * - * @param \Traversable|null $iterator Iterator that filters which files and directories to copy, if null a recursive iterator is created - * @param array $options An array of boolean options - * Valid options are: - * - $options['override'] If true, target files newer than origin files are overwritten (see copy(), defaults to false) - * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink(), defaults to false) - * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) - * - * @throws IOException When file type is unknown - */ - public function mirror(string $originDir, string $targetDir, \Traversable $iterator = null, array $options = []) - { - $targetDir = rtrim($targetDir, '/\\'); - $originDir = rtrim($originDir, '/\\'); - $originDirLen = \strlen($originDir); - - if (!$this->exists($originDir)) { - throw new IOException(sprintf('The origin directory specified "%s" was not found.', $originDir), 0, null, $originDir); - } - - // Iterate in destination folder to remove obsolete entries - if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) { - $deleteIterator = $iterator; - if (null === $deleteIterator) { - $flags = \FilesystemIterator::SKIP_DOTS; - $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST); - } - $targetDirLen = \strlen($targetDir); - foreach ($deleteIterator as $file) { - $origin = $originDir.substr($file->getPathname(), $targetDirLen); - if (!$this->exists($origin)) { - $this->remove($file); - } - } - } - - $copyOnWindows = $options['copy_on_windows'] ?? false; - - if (null === $iterator) { - $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS; - $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST); - } - - $this->mkdir($targetDir); - $filesCreatedWhileMirroring = []; - - foreach ($iterator as $file) { - if ($file->getPathname() === $targetDir || $file->getRealPath() === $targetDir || isset($filesCreatedWhileMirroring[$file->getRealPath()])) { - continue; - } - - $target = $targetDir.substr($file->getPathname(), $originDirLen); - $filesCreatedWhileMirroring[$target] = true; - - if (!$copyOnWindows && is_link($file)) { - $this->symlink($file->getLinkTarget(), $target); - } elseif (is_dir($file)) { - $this->mkdir($target); - } elseif (is_file($file)) { - $this->copy($file, $target, isset($options['override']) ? $options['override'] : false); - } else { - throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file); - } - } - } - - /** - * Returns whether the file path is an absolute path. - * - * @return bool - */ - public function isAbsolutePath(string $file) - { - return strspn($file, '/\\', 0, 1) - || (\strlen($file) > 3 && ctype_alpha($file[0]) - && ':' === $file[1] - && strspn($file, '/\\', 2, 1) - ) - || null !== parse_url($file, PHP_URL_SCHEME) - ; - } - - /** - * Creates a temporary file with support for custom stream wrappers. - * - * @param string $prefix The prefix of the generated temporary filename - * Note: Windows uses only the first three characters of prefix - * - * @return string The new temporary filename (with path), or throw an exception on failure - */ - public function tempnam(string $dir, string $prefix) - { - list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir); - - // If no scheme or scheme is "file" or "gs" (Google Cloud) create temp file in local filesystem - if (null === $scheme || 'file' === $scheme || 'gs' === $scheme) { - $tmpFile = @tempnam($hierarchy, $prefix); - - // If tempnam failed or no scheme return the filename otherwise prepend the scheme - if (false !== $tmpFile) { - if (null !== $scheme && 'gs' !== $scheme) { - return $scheme.'://'.$tmpFile; - } - - return $tmpFile; - } - - throw new IOException('A temporary file could not be created.'); - } - - // Loop until we create a valid temp file or have reached 10 attempts - for ($i = 0; $i < 10; ++$i) { - // Create a unique filename - $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true); - - // Use fopen instead of file_exists as some streams do not support stat - // Use mode 'x+' to atomically check existence and create to avoid a TOCTOU vulnerability - $handle = @fopen($tmpFile, 'x+'); - - // If unsuccessful restart the loop - if (false === $handle) { - continue; - } - - // Close the file if it was successfully opened - @fclose($handle); - - return $tmpFile; - } - - throw new IOException('A temporary file could not be created.'); - } - - /** - * Atomically dumps content into a file. - * - * @param string|resource $content The data to write into the file - * - * @throws IOException if the file cannot be written to - */ - public function dumpFile(string $filename, $content) - { - if (\is_array($content)) { - throw new \TypeError(sprintf('Argument 2 passed to %s() must be string or resource, array given.', __METHOD__)); - } - - $dir = \dirname($filename); - - if (!is_dir($dir)) { - $this->mkdir($dir); - } - - if (!is_writable($dir)) { - throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir); - } - - // Will create a temp file with 0600 access rights - // when the filesystem supports chmod. - $tmpFile = $this->tempnam($dir, basename($filename)); - - if (false === @file_put_contents($tmpFile, $content)) { - throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename); - } - - @chmod($tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask()); - - $this->rename($tmpFile, $filename, true); - } - - /** - * Appends content to an existing file. - * - * @param string|resource $content The content to append - * - * @throws IOException If the file is not writable - */ - public function appendToFile(string $filename, $content) - { - if (\is_array($content)) { - throw new \TypeError(sprintf('Argument 2 passed to %s() must be string or resource, array given.', __METHOD__)); - } - - $dir = \dirname($filename); - - if (!is_dir($dir)) { - $this->mkdir($dir); - } - - if (!is_writable($dir)) { - throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir); - } - - if (false === @file_put_contents($filename, $content, FILE_APPEND)) { - throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename); - } - } - - private function toIterable($files): iterable - { - return \is_array($files) || $files instanceof \Traversable ? $files : [$files]; - } - - /** - * Gets a 2-tuple of scheme (may be null) and hierarchical part of a filename (e.g. file:///tmp -> [file, tmp]). - */ - private function getSchemeAndHierarchy(string $filename): array - { - $components = explode('://', $filename, 2); - - return 2 === \count($components) ? [$components[0], $components[1]] : [null, $components[0]]; - } - - /** - * @return mixed - */ - private static function box(callable $func) - { - self::$lastError = null; - set_error_handler(__CLASS__.'::handleError'); - try { - $result = $func(...\array_slice(\func_get_args(), 1)); - restore_error_handler(); - - return $result; - } catch (\Throwable $e) { - } - restore_error_handler(); - - throw $e; - } - - /** - * @internal - */ - public static function handleError($type, $msg) - { - self::$lastError = $msg; - } -} diff --git a/vendor/symfony/filesystem/LICENSE b/vendor/symfony/filesystem/LICENSE deleted file mode 100644 index a677f43..0000000 --- a/vendor/symfony/filesystem/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/filesystem/README.md b/vendor/symfony/filesystem/README.md deleted file mode 100644 index 877ab35..0000000 --- a/vendor/symfony/filesystem/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Filesystem Component -==================== - -The Filesystem component provides basic utilities for the filesystem. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/filesystem/index.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/filesystem/composer.json b/vendor/symfony/filesystem/composer.json deleted file mode 100644 index 3eb1070..0000000 --- a/vendor/symfony/filesystem/composer.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "symfony/filesystem", - "type": "library", - "description": "Symfony Filesystem Component", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "symfony/polyfill-ctype": "~1.8" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Filesystem\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/finder/.gitattributes b/vendor/symfony/finder/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/finder/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/finder/CHANGELOG.md b/vendor/symfony/finder/CHANGELOG.md deleted file mode 100644 index 33f5bd5..0000000 --- a/vendor/symfony/finder/CHANGELOG.md +++ /dev/null @@ -1,79 +0,0 @@ -CHANGELOG -========= - -5.0.0 ------ - - * added `$useNaturalSort` argument to `Finder::sortByName()` - -4.3.0 ------ - - * added Finder::ignoreVCSIgnored() to ignore files based on rules listed in .gitignore - -4.2.0 ------ - - * added $useNaturalSort option to Finder::sortByName() method - * the `Finder::sortByName()` method will have a new `$useNaturalSort` - argument in version 5.0, not defining it is deprecated - * added `Finder::reverseSorting()` to reverse the sorting - -4.0.0 ------ - - * removed `ExceptionInterface` - * removed `Symfony\Component\Finder\Iterator\FilterIterator` - -3.4.0 ------ - - * deprecated `Symfony\Component\Finder\Iterator\FilterIterator` - * added Finder::hasResults() method to check if any results were found - -3.3.0 ------ - - * added double-star matching to Glob::toRegex() - -3.0.0 ------ - - * removed deprecated classes - -2.8.0 ------ - - * deprecated adapters and related classes - -2.5.0 ------ - * added support for GLOB_BRACE in the paths passed to Finder::in() - -2.3.0 ------ - - * added a way to ignore unreadable directories (via Finder::ignoreUnreadableDirs()) - * unified the way subfolders that are not executable are handled by always throwing an AccessDeniedException exception - -2.2.0 ------ - - * added Finder::path() and Finder::notPath() methods - * added finder adapters to improve performance on specific platforms - * added support for wildcard characters (glob patterns) in the paths passed - to Finder::in() - -2.1.0 ------ - - * added Finder::sortByAccessedTime(), Finder::sortByChangedTime(), and - Finder::sortByModifiedTime() - * added Countable to Finder - * added support for an array of directories as an argument to - Finder::exclude() - * added searching based on the file content via Finder::contains() and - Finder::notContains() - * added support for the != operator in the Comparator - * [BC BREAK] filter expressions (used for file name and content) are no more - considered as regexps but glob patterns when they are enclosed in '*' or '?' diff --git a/vendor/symfony/finder/Comparator/Comparator.php b/vendor/symfony/finder/Comparator/Comparator.php deleted file mode 100644 index cfe3965..0000000 --- a/vendor/symfony/finder/Comparator/Comparator.php +++ /dev/null @@ -1,91 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Comparator; - -/** - * Comparator. - * - * @author Fabien Potencier - */ -class Comparator -{ - private $target; - private $operator = '=='; - - /** - * Gets the target value. - * - * @return string The target value - */ - public function getTarget() - { - return $this->target; - } - - public function setTarget(string $target) - { - $this->target = $target; - } - - /** - * Gets the comparison operator. - * - * @return string The operator - */ - public function getOperator() - { - return $this->operator; - } - - /** - * Sets the comparison operator. - * - * @throws \InvalidArgumentException - */ - public function setOperator(string $operator) - { - if ('' === $operator) { - $operator = '=='; - } - - if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) { - throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator)); - } - - $this->operator = $operator; - } - - /** - * Tests against the target. - * - * @param mixed $test A test value - * - * @return bool - */ - public function test($test) - { - switch ($this->operator) { - case '>': - return $test > $this->target; - case '>=': - return $test >= $this->target; - case '<': - return $test < $this->target; - case '<=': - return $test <= $this->target; - case '!=': - return $test != $this->target; - } - - return $test == $this->target; - } -} diff --git a/vendor/symfony/finder/Comparator/DateComparator.php b/vendor/symfony/finder/Comparator/DateComparator.php deleted file mode 100644 index d17c77a..0000000 --- a/vendor/symfony/finder/Comparator/DateComparator.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Comparator; - -/** - * DateCompare compiles date comparisons. - * - * @author Fabien Potencier - */ -class DateComparator extends Comparator -{ - /** - * @param string $test A comparison string - * - * @throws \InvalidArgumentException If the test is not understood - */ - public function __construct(string $test) - { - if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) { - throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test)); - } - - try { - $date = new \DateTime($matches[2]); - $target = $date->format('U'); - } catch (\Exception $e) { - throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2])); - } - - $operator = isset($matches[1]) ? $matches[1] : '=='; - if ('since' === $operator || 'after' === $operator) { - $operator = '>'; - } - - if ('until' === $operator || 'before' === $operator) { - $operator = '<'; - } - - $this->setOperator($operator); - $this->setTarget($target); - } -} diff --git a/vendor/symfony/finder/Comparator/NumberComparator.php b/vendor/symfony/finder/Comparator/NumberComparator.php deleted file mode 100644 index 80667c9..0000000 --- a/vendor/symfony/finder/Comparator/NumberComparator.php +++ /dev/null @@ -1,79 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Comparator; - -/** - * NumberComparator compiles a simple comparison to an anonymous - * subroutine, which you can call with a value to be tested again. - * - * Now this would be very pointless, if NumberCompare didn't understand - * magnitudes. - * - * The target value may use magnitudes of kilobytes (k, ki), - * megabytes (m, mi), or gigabytes (g, gi). Those suffixed - * with an i use the appropriate 2**n version in accordance with the - * IEC standard: http://physics.nist.gov/cuu/Units/binary.html - * - * Based on the Perl Number::Compare module. - * - * @author Fabien Potencier PHP port - * @author Richard Clamp Perl version - * @copyright 2004-2005 Fabien Potencier - * @copyright 2002 Richard Clamp - * - * @see http://physics.nist.gov/cuu/Units/binary.html - */ -class NumberComparator extends Comparator -{ - /** - * @param string|int $test A comparison string or an integer - * - * @throws \InvalidArgumentException If the test is not understood - */ - public function __construct(?string $test) - { - if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) { - throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test)); - } - - $target = $matches[2]; - if (!is_numeric($target)) { - throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target)); - } - if (isset($matches[3])) { - // magnitude - switch (strtolower($matches[3])) { - case 'k': - $target *= 1000; - break; - case 'ki': - $target *= 1024; - break; - case 'm': - $target *= 1000000; - break; - case 'mi': - $target *= 1024 * 1024; - break; - case 'g': - $target *= 1000000000; - break; - case 'gi': - $target *= 1024 * 1024 * 1024; - break; - } - } - - $this->setTarget($target); - $this->setOperator(isset($matches[1]) ? $matches[1] : '=='); - } -} diff --git a/vendor/symfony/finder/Exception/AccessDeniedException.php b/vendor/symfony/finder/Exception/AccessDeniedException.php deleted file mode 100644 index ee195ea..0000000 --- a/vendor/symfony/finder/Exception/AccessDeniedException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -/** - * @author Jean-François Simon - */ -class AccessDeniedException extends \UnexpectedValueException -{ -} diff --git a/vendor/symfony/finder/Exception/DirectoryNotFoundException.php b/vendor/symfony/finder/Exception/DirectoryNotFoundException.php deleted file mode 100644 index c6cc0f2..0000000 --- a/vendor/symfony/finder/Exception/DirectoryNotFoundException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -/** - * @author Andreas Erhard - */ -class DirectoryNotFoundException extends \InvalidArgumentException -{ -} diff --git a/vendor/symfony/finder/Finder.php b/vendor/symfony/finder/Finder.php deleted file mode 100644 index da1c6ab..0000000 --- a/vendor/symfony/finder/Finder.php +++ /dev/null @@ -1,793 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -use Symfony\Component\Finder\Comparator\DateComparator; -use Symfony\Component\Finder\Comparator\NumberComparator; -use Symfony\Component\Finder\Exception\DirectoryNotFoundException; -use Symfony\Component\Finder\Iterator\CustomFilterIterator; -use Symfony\Component\Finder\Iterator\DateRangeFilterIterator; -use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator; -use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator; -use Symfony\Component\Finder\Iterator\FilecontentFilterIterator; -use Symfony\Component\Finder\Iterator\FilenameFilterIterator; -use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator; -use Symfony\Component\Finder\Iterator\SortableIterator; - -/** - * Finder allows to build rules to find files and directories. - * - * It is a thin wrapper around several specialized iterator classes. - * - * All rules may be invoked several times. - * - * All methods return the current Finder object to allow chaining: - * - * $finder = Finder::create()->files()->name('*.php')->in(__DIR__); - * - * @author Fabien Potencier - */ -class Finder implements \IteratorAggregate, \Countable -{ - const IGNORE_VCS_FILES = 1; - const IGNORE_DOT_FILES = 2; - const IGNORE_VCS_IGNORED_FILES = 4; - - private $mode = 0; - private $names = []; - private $notNames = []; - private $exclude = []; - private $filters = []; - private $depths = []; - private $sizes = []; - private $followLinks = false; - private $reverseSorting = false; - private $sort = false; - private $ignore = 0; - private $dirs = []; - private $dates = []; - private $iterators = []; - private $contains = []; - private $notContains = []; - private $paths = []; - private $notPaths = []; - private $ignoreUnreadableDirs = false; - - private static $vcsPatterns = ['.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg']; - - public function __construct() - { - $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES; - } - - /** - * Creates a new Finder. - * - * @return static - */ - public static function create() - { - return new static(); - } - - /** - * Restricts the matching to directories only. - * - * @return $this - */ - public function directories() - { - $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES; - - return $this; - } - - /** - * Restricts the matching to files only. - * - * @return $this - */ - public function files() - { - $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES; - - return $this; - } - - /** - * Adds tests for the directory depth. - * - * Usage: - * - * $finder->depth('> 1') // the Finder will start matching at level 1. - * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point. - * $finder->depth(['>= 1', '< 3']) - * - * @param string|int|string[]|int[] $levels The depth level expression or an array of depth levels - * - * @return $this - * - * @see DepthRangeFilterIterator - * @see NumberComparator - */ - public function depth($levels) - { - foreach ((array) $levels as $level) { - $this->depths[] = new Comparator\NumberComparator($level); - } - - return $this; - } - - /** - * Adds tests for file dates (last modified). - * - * The date must be something that strtotime() is able to parse: - * - * $finder->date('since yesterday'); - * $finder->date('until 2 days ago'); - * $finder->date('> now - 2 hours'); - * $finder->date('>= 2005-10-15'); - * $finder->date(['>= 2005-10-15', '<= 2006-05-27']); - * - * @param string|string[] $dates A date range string or an array of date ranges - * - * @return $this - * - * @see strtotime - * @see DateRangeFilterIterator - * @see DateComparator - */ - public function date($dates) - { - foreach ((array) $dates as $date) { - $this->dates[] = new Comparator\DateComparator($date); - } - - return $this; - } - - /** - * Adds rules that files must match. - * - * You can use patterns (delimited with / sign), globs or simple strings. - * - * $finder->name('*.php') - * $finder->name('/\.php$/') // same as above - * $finder->name('test.php') - * $finder->name(['test.py', 'test.php']) - * - * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns - * - * @return $this - * - * @see FilenameFilterIterator - */ - public function name($patterns) - { - $this->names = array_merge($this->names, (array) $patterns); - - return $this; - } - - /** - * Adds rules that files must not match. - * - * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns - * - * @return $this - * - * @see FilenameFilterIterator - */ - public function notName($patterns) - { - $this->notNames = array_merge($this->notNames, (array) $patterns); - - return $this; - } - - /** - * Adds tests that file contents must match. - * - * Strings or PCRE patterns can be used: - * - * $finder->contains('Lorem ipsum') - * $finder->contains('/Lorem ipsum/i') - * $finder->contains(['dolor', '/ipsum/i']) - * - * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns - * - * @return $this - * - * @see FilecontentFilterIterator - */ - public function contains($patterns) - { - $this->contains = array_merge($this->contains, (array) $patterns); - - return $this; - } - - /** - * Adds tests that file contents must not match. - * - * Strings or PCRE patterns can be used: - * - * $finder->notContains('Lorem ipsum') - * $finder->notContains('/Lorem ipsum/i') - * $finder->notContains(['lorem', '/dolor/i']) - * - * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns - * - * @return $this - * - * @see FilecontentFilterIterator - */ - public function notContains($patterns) - { - $this->notContains = array_merge($this->notContains, (array) $patterns); - - return $this; - } - - /** - * Adds rules that filenames must match. - * - * You can use patterns (delimited with / sign) or simple strings. - * - * $finder->path('some/special/dir') - * $finder->path('/some\/special\/dir/') // same as above - * $finder->path(['some dir', 'another/dir']) - * - * Use only / as dirname separator. - * - * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns - * - * @return $this - * - * @see FilenameFilterIterator - */ - public function path($patterns) - { - $this->paths = array_merge($this->paths, (array) $patterns); - - return $this; - } - - /** - * Adds rules that filenames must not match. - * - * You can use patterns (delimited with / sign) or simple strings. - * - * $finder->notPath('some/special/dir') - * $finder->notPath('/some\/special\/dir/') // same as above - * $finder->notPath(['some/file.txt', 'another/file.log']) - * - * Use only / as dirname separator. - * - * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns - * - * @return $this - * - * @see FilenameFilterIterator - */ - public function notPath($patterns) - { - $this->notPaths = array_merge($this->notPaths, (array) $patterns); - - return $this; - } - - /** - * Adds tests for file sizes. - * - * $finder->size('> 10K'); - * $finder->size('<= 1Ki'); - * $finder->size(4); - * $finder->size(['> 10K', '< 20K']) - * - * @param string|int|string[]|int[] $sizes A size range string or an integer or an array of size ranges - * - * @return $this - * - * @see SizeRangeFilterIterator - * @see NumberComparator - */ - public function size($sizes) - { - foreach ((array) $sizes as $size) { - $this->sizes[] = new Comparator\NumberComparator($size); - } - - return $this; - } - - /** - * Excludes directories. - * - * Directories passed as argument must be relative to the ones defined with the `in()` method. For example: - * - * $finder->in(__DIR__)->exclude('ruby'); - * - * @param string|array $dirs A directory path or an array of directories - * - * @return $this - * - * @see ExcludeDirectoryFilterIterator - */ - public function exclude($dirs) - { - $this->exclude = array_merge($this->exclude, (array) $dirs); - - return $this; - } - - /** - * Excludes "hidden" directories and files (starting with a dot). - * - * This option is enabled by default. - * - * @return $this - * - * @see ExcludeDirectoryFilterIterator - */ - public function ignoreDotFiles(bool $ignoreDotFiles) - { - if ($ignoreDotFiles) { - $this->ignore |= static::IGNORE_DOT_FILES; - } else { - $this->ignore &= ~static::IGNORE_DOT_FILES; - } - - return $this; - } - - /** - * Forces the finder to ignore version control directories. - * - * This option is enabled by default. - * - * @return $this - * - * @see ExcludeDirectoryFilterIterator - */ - public function ignoreVCS(bool $ignoreVCS) - { - if ($ignoreVCS) { - $this->ignore |= static::IGNORE_VCS_FILES; - } else { - $this->ignore &= ~static::IGNORE_VCS_FILES; - } - - return $this; - } - - /** - * Forces Finder to obey .gitignore and ignore files based on rules listed there. - * - * This option is disabled by default. - * - * @return $this - */ - public function ignoreVCSIgnored(bool $ignoreVCSIgnored) - { - if ($ignoreVCSIgnored) { - $this->ignore |= static::IGNORE_VCS_IGNORED_FILES; - } else { - $this->ignore &= ~static::IGNORE_VCS_IGNORED_FILES; - } - - return $this; - } - - /** - * Adds VCS patterns. - * - * @see ignoreVCS() - * - * @param string|string[] $pattern VCS patterns to ignore - */ - public static function addVCSPattern($pattern) - { - foreach ((array) $pattern as $p) { - self::$vcsPatterns[] = $p; - } - - self::$vcsPatterns = array_unique(self::$vcsPatterns); - } - - /** - * Sorts files and directories by an anonymous function. - * - * The anonymous function receives two \SplFileInfo instances to compare. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sort(\Closure $closure) - { - $this->sort = $closure; - - return $this; - } - - /** - * Sorts files and directories by name. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sortByName(bool $useNaturalSort = false) - { - $this->sort = $useNaturalSort ? Iterator\SortableIterator::SORT_BY_NAME_NATURAL : Iterator\SortableIterator::SORT_BY_NAME; - - return $this; - } - - /** - * Sorts files and directories by type (directories before files), then by name. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sortByType() - { - $this->sort = Iterator\SortableIterator::SORT_BY_TYPE; - - return $this; - } - - /** - * Sorts files and directories by the last accessed time. - * - * This is the time that the file was last accessed, read or written to. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sortByAccessedTime() - { - $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME; - - return $this; - } - - /** - * Reverses the sorting. - * - * @return $this - */ - public function reverseSorting() - { - $this->reverseSorting = true; - - return $this; - } - - /** - * Sorts files and directories by the last inode changed time. - * - * This is the time that the inode information was last modified (permissions, owner, group or other metadata). - * - * On Windows, since inode is not available, changed time is actually the file creation time. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sortByChangedTime() - { - $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME; - - return $this; - } - - /** - * Sorts files and directories by the last modified time. - * - * This is the last time the actual contents of the file were last modified. - * - * This can be slow as all the matching files and directories must be retrieved for comparison. - * - * @return $this - * - * @see SortableIterator - */ - public function sortByModifiedTime() - { - $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME; - - return $this; - } - - /** - * Filters the iterator with an anonymous function. - * - * The anonymous function receives a \SplFileInfo and must return false - * to remove files. - * - * @return $this - * - * @see CustomFilterIterator - */ - public function filter(\Closure $closure) - { - $this->filters[] = $closure; - - return $this; - } - - /** - * Forces the following of symlinks. - * - * @return $this - */ - public function followLinks() - { - $this->followLinks = true; - - return $this; - } - - /** - * Tells finder to ignore unreadable directories. - * - * By default, scanning unreadable directories content throws an AccessDeniedException. - * - * @return $this - */ - public function ignoreUnreadableDirs(bool $ignore = true) - { - $this->ignoreUnreadableDirs = $ignore; - - return $this; - } - - /** - * Searches files and directories which match defined rules. - * - * @param string|string[] $dirs A directory path or an array of directories - * - * @return $this - * - * @throws DirectoryNotFoundException if one of the directories does not exist - */ - public function in($dirs) - { - $resolvedDirs = []; - - foreach ((array) $dirs as $dir) { - if (is_dir($dir)) { - $resolvedDirs[] = $this->normalizeDir($dir); - } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR | GLOB_NOSORT)) { - sort($glob); - $resolvedDirs = array_merge($resolvedDirs, array_map([$this, 'normalizeDir'], $glob)); - } else { - throw new DirectoryNotFoundException(sprintf('The "%s" directory does not exist.', $dir)); - } - } - - $this->dirs = array_merge($this->dirs, $resolvedDirs); - - return $this; - } - - /** - * Returns an Iterator for the current Finder configuration. - * - * This method implements the IteratorAggregate interface. - * - * @return \Iterator|SplFileInfo[] An iterator - * - * @throws \LogicException if the in() method has not been called - */ - public function getIterator() - { - if (0 === \count($this->dirs) && 0 === \count($this->iterators)) { - throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.'); - } - - if (1 === \count($this->dirs) && 0 === \count($this->iterators)) { - return $this->searchInDirectory($this->dirs[0]); - } - - $iterator = new \AppendIterator(); - foreach ($this->dirs as $dir) { - $iterator->append($this->searchInDirectory($dir)); - } - - foreach ($this->iterators as $it) { - $iterator->append($it); - } - - return $iterator; - } - - /** - * Appends an existing set of files/directories to the finder. - * - * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array. - * - * @return $this - * - * @throws \InvalidArgumentException when the given argument is not iterable - */ - public function append(iterable $iterator) - { - if ($iterator instanceof \IteratorAggregate) { - $this->iterators[] = $iterator->getIterator(); - } elseif ($iterator instanceof \Iterator) { - $this->iterators[] = $iterator; - } elseif ($iterator instanceof \Traversable || \is_array($iterator)) { - $it = new \ArrayIterator(); - foreach ($iterator as $file) { - $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file)); - } - $this->iterators[] = $it; - } else { - throw new \InvalidArgumentException('Finder::append() method wrong argument type.'); - } - - return $this; - } - - /** - * Check if the any results were found. - * - * @return bool - */ - public function hasResults() - { - foreach ($this->getIterator() as $_) { - return true; - } - - return false; - } - - /** - * Counts all the results collected by the iterators. - * - * @return int - */ - public function count() - { - return iterator_count($this->getIterator()); - } - - private function searchInDirectory(string $dir): \Iterator - { - $exclude = $this->exclude; - $notPaths = $this->notPaths; - - if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) { - $exclude = array_merge($exclude, self::$vcsPatterns); - } - - if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) { - $notPaths[] = '#(^|/)\..+(/|$)#'; - } - - if (static::IGNORE_VCS_IGNORED_FILES === (static::IGNORE_VCS_IGNORED_FILES & $this->ignore)) { - $gitignoreFilePath = sprintf('%s/.gitignore', $dir); - if (!is_readable($gitignoreFilePath)) { - throw new \RuntimeException(sprintf('The "ignoreVCSIgnored" option cannot be used by the Finder as the "%s" file is not readable.', $gitignoreFilePath)); - } - $notPaths = array_merge($notPaths, [Gitignore::toRegex(file_get_contents($gitignoreFilePath))]); - } - - $minDepth = 0; - $maxDepth = PHP_INT_MAX; - - foreach ($this->depths as $comparator) { - switch ($comparator->getOperator()) { - case '>': - $minDepth = $comparator->getTarget() + 1; - break; - case '>=': - $minDepth = $comparator->getTarget(); - break; - case '<': - $maxDepth = $comparator->getTarget() - 1; - break; - case '<=': - $maxDepth = $comparator->getTarget(); - break; - default: - $minDepth = $maxDepth = $comparator->getTarget(); - } - } - - $flags = \RecursiveDirectoryIterator::SKIP_DOTS; - - if ($this->followLinks) { - $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS; - } - - $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs); - - if ($exclude) { - $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $exclude); - } - - $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST); - - if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) { - $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth); - } - - if ($this->mode) { - $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode); - } - - if ($this->names || $this->notNames) { - $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames); - } - - if ($this->contains || $this->notContains) { - $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); - } - - if ($this->sizes) { - $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes); - } - - if ($this->dates) { - $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates); - } - - if ($this->filters) { - $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); - } - - if ($this->paths || $notPaths) { - $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $notPaths); - } - - if ($this->sort || $this->reverseSorting) { - $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort, $this->reverseSorting); - $iterator = $iteratorAggregate->getIterator(); - } - - return $iterator; - } - - /** - * Normalizes given directory names by removing trailing slashes. - * - * Excluding: (s)ftp:// or ssh2.(s)ftp:// wrapper - */ - private function normalizeDir(string $dir): string - { - $dir = rtrim($dir, '/'.\DIRECTORY_SEPARATOR); - - if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) { - $dir .= '/'; - } - - return $dir; - } -} diff --git a/vendor/symfony/finder/Gitignore.php b/vendor/symfony/finder/Gitignore.php deleted file mode 100644 index 5ffe585..0000000 --- a/vendor/symfony/finder/Gitignore.php +++ /dev/null @@ -1,105 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -/** - * Gitignore matches against text. - * - * @author Ahmed Abdou - */ -class Gitignore -{ - /** - * Returns a regexp which is the equivalent of the gitignore pattern. - * - * @return string The regexp - */ - public static function toRegex(string $gitignoreFileContent): string - { - $gitignoreFileContent = preg_replace('/^[^\\\r\n]*#.*/m', '', $gitignoreFileContent); - $gitignoreLines = preg_split('/\r\n|\r|\n/', $gitignoreFileContent); - $gitignoreLines = array_map('trim', $gitignoreLines); - $gitignoreLines = array_filter($gitignoreLines); - - $ignoreLinesPositive = array_filter($gitignoreLines, function (string $line) { - return !preg_match('/^!/', $line); - }); - - $ignoreLinesNegative = array_filter($gitignoreLines, function (string $line) { - return preg_match('/^!/', $line); - }); - - $ignoreLinesNegative = array_map(function (string $line) { - return preg_replace('/^!(.*)/', '${1}', $line); - }, $ignoreLinesNegative); - $ignoreLinesNegative = array_map([__CLASS__, 'getRegexFromGitignore'], $ignoreLinesNegative); - - $ignoreLinesPositive = array_map([__CLASS__, 'getRegexFromGitignore'], $ignoreLinesPositive); - if (empty($ignoreLinesPositive)) { - return '/^$/'; - } - - if (empty($ignoreLinesNegative)) { - return sprintf('/%s/', implode('|', $ignoreLinesPositive)); - } - - return sprintf('/(?=^(?:(?!(%s)).)*$)(%s)/', implode('|', $ignoreLinesNegative), implode('|', $ignoreLinesPositive)); - } - - private static function getRegexFromGitignore(string $gitignorePattern): string - { - $regex = '('; - if (0 === strpos($gitignorePattern, '/')) { - $gitignorePattern = substr($gitignorePattern, 1); - $regex .= '^'; - } else { - $regex .= '(^|\/)'; - } - - if ('/' === $gitignorePattern[\strlen($gitignorePattern) - 1]) { - $gitignorePattern = substr($gitignorePattern, 0, -1); - } - - $iMax = \strlen($gitignorePattern); - for ($i = 0; $i < $iMax; ++$i) { - $doubleChars = substr($gitignorePattern, $i, 2); - if ('**' === $doubleChars) { - $regex .= '.+'; - ++$i; - continue; - } - - $c = $gitignorePattern[$i]; - switch ($c) { - case '*': - $regex .= '[^\/]+'; - break; - case '/': - case '.': - case ':': - case '(': - case ')': - case '{': - case '}': - $regex .= '\\'.$c; - break; - default: - $regex .= $c; - } - } - - $regex .= '($|\/)'; - $regex .= ')'; - - return $regex; - } -} diff --git a/vendor/symfony/finder/Glob.php b/vendor/symfony/finder/Glob.php deleted file mode 100644 index 8447932..0000000 --- a/vendor/symfony/finder/Glob.php +++ /dev/null @@ -1,111 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -/** - * Glob matches globbing patterns against text. - * - * if match_glob("foo.*", "foo.bar") echo "matched\n"; - * - * // prints foo.bar and foo.baz - * $regex = glob_to_regex("foo.*"); - * for (['foo.bar', 'foo.baz', 'foo', 'bar'] as $t) - * { - * if (/$regex/) echo "matched: $car\n"; - * } - * - * Glob implements glob(3) style matching that can be used to match - * against text, rather than fetching names from a filesystem. - * - * Based on the Perl Text::Glob module. - * - * @author Fabien Potencier PHP port - * @author Richard Clamp Perl version - * @copyright 2004-2005 Fabien Potencier - * @copyright 2002 Richard Clamp - */ -class Glob -{ - /** - * Returns a regexp which is the equivalent of the glob pattern. - * - * @return string - */ - public static function toRegex(string $glob, bool $strictLeadingDot = true, bool $strictWildcardSlash = true, string $delimiter = '#') - { - $firstByte = true; - $escaping = false; - $inCurlies = 0; - $regex = ''; - $sizeGlob = \strlen($glob); - for ($i = 0; $i < $sizeGlob; ++$i) { - $car = $glob[$i]; - if ($firstByte && $strictLeadingDot && '.' !== $car) { - $regex .= '(?=[^\.])'; - } - - $firstByte = '/' === $car; - - if ($firstByte && $strictWildcardSlash && isset($glob[$i + 2]) && '**' === $glob[$i + 1].$glob[$i + 2] && (!isset($glob[$i + 3]) || '/' === $glob[$i + 3])) { - $car = '[^/]++/'; - if (!isset($glob[$i + 3])) { - $car .= '?'; - } - - if ($strictLeadingDot) { - $car = '(?=[^\.])'.$car; - } - - $car = '/(?:'.$car.')*'; - $i += 2 + isset($glob[$i + 3]); - - if ('/' === $delimiter) { - $car = str_replace('/', '\\/', $car); - } - } - - if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { - $regex .= "\\$car"; - } elseif ('*' === $car) { - $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); - } elseif ('?' === $car) { - $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); - } elseif ('{' === $car) { - $regex .= $escaping ? '\\{' : '('; - if (!$escaping) { - ++$inCurlies; - } - } elseif ('}' === $car && $inCurlies) { - $regex .= $escaping ? '}' : ')'; - if (!$escaping) { - --$inCurlies; - } - } elseif (',' === $car && $inCurlies) { - $regex .= $escaping ? ',' : '|'; - } elseif ('\\' === $car) { - if ($escaping) { - $regex .= '\\\\'; - $escaping = false; - } else { - $escaping = true; - } - - continue; - } else { - $regex .= $car; - } - $escaping = false; - } - - return $delimiter.'^'.$regex.'$'.$delimiter; - } -} diff --git a/vendor/symfony/finder/Iterator/CustomFilterIterator.php b/vendor/symfony/finder/Iterator/CustomFilterIterator.php deleted file mode 100644 index a30bbd0..0000000 --- a/vendor/symfony/finder/Iterator/CustomFilterIterator.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * CustomFilterIterator filters files by applying anonymous functions. - * - * The anonymous function receives a \SplFileInfo and must return false - * to remove files. - * - * @author Fabien Potencier - */ -class CustomFilterIterator extends \FilterIterator -{ - private $filters = []; - - /** - * @param \Iterator $iterator The Iterator to filter - * @param callable[] $filters An array of PHP callbacks - * - * @throws \InvalidArgumentException - */ - public function __construct(\Iterator $iterator, array $filters) - { - foreach ($filters as $filter) { - if (!\is_callable($filter)) { - throw new \InvalidArgumentException('Invalid PHP callback.'); - } - } - $this->filters = $filters; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return bool true if the value should be kept, false otherwise - */ - public function accept() - { - $fileinfo = $this->current(); - - foreach ($this->filters as $filter) { - if (false === $filter($fileinfo)) { - return false; - } - } - - return true; - } -} diff --git a/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php b/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php deleted file mode 100644 index 2e97e00..0000000 --- a/vendor/symfony/finder/Iterator/DateRangeFilterIterator.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Comparator\DateComparator; - -/** - * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates). - * - * @author Fabien Potencier - */ -class DateRangeFilterIterator extends \FilterIterator -{ - private $comparators = []; - - /** - * @param \Iterator $iterator The Iterator to filter - * @param DateComparator[] $comparators An array of DateComparator instances - */ - public function __construct(\Iterator $iterator, array $comparators) - { - $this->comparators = $comparators; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return bool true if the value should be kept, false otherwise - */ - public function accept() - { - $fileinfo = $this->current(); - - if (!file_exists($fileinfo->getPathname())) { - return false; - } - - $filedate = $fileinfo->getMTime(); - foreach ($this->comparators as $compare) { - if (!$compare->test($filedate)) { - return false; - } - } - - return true; - } -} diff --git a/vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php b/vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php deleted file mode 100644 index 436a66d..0000000 --- a/vendor/symfony/finder/Iterator/DepthRangeFilterIterator.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * DepthRangeFilterIterator limits the directory depth. - * - * @author Fabien Potencier - */ -class DepthRangeFilterIterator extends \FilterIterator -{ - private $minDepth = 0; - - /** - * @param \RecursiveIteratorIterator $iterator The Iterator to filter - * @param int $minDepth The min depth - * @param int $maxDepth The max depth - */ - public function __construct(\RecursiveIteratorIterator $iterator, int $minDepth = 0, int $maxDepth = PHP_INT_MAX) - { - $this->minDepth = $minDepth; - $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth); - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return bool true if the value should be kept, false otherwise - */ - public function accept() - { - return $this->getInnerIterator()->getDepth() >= $this->minDepth; - } -} diff --git a/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php b/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php deleted file mode 100644 index 6a1b291..0000000 --- a/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * ExcludeDirectoryFilterIterator filters out directories. - * - * @author Fabien Potencier - */ -class ExcludeDirectoryFilterIterator extends \FilterIterator implements \RecursiveIterator -{ - private $iterator; - private $isRecursive; - private $excludedDirs = []; - private $excludedPattern; - - /** - * @param \Iterator $iterator The Iterator to filter - * @param string[] $directories An array of directories to exclude - */ - public function __construct(\Iterator $iterator, array $directories) - { - $this->iterator = $iterator; - $this->isRecursive = $iterator instanceof \RecursiveIterator; - $patterns = []; - foreach ($directories as $directory) { - $directory = rtrim($directory, '/'); - if (!$this->isRecursive || false !== strpos($directory, '/')) { - $patterns[] = preg_quote($directory, '#'); - } else { - $this->excludedDirs[$directory] = true; - } - } - if ($patterns) { - $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#'; - } - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return bool True if the value should be kept, false otherwise - */ - public function accept() - { - if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) { - return false; - } - - if ($this->excludedPattern) { - $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath(); - $path = str_replace('\\', '/', $path); - - return !preg_match($this->excludedPattern, $path); - } - - return true; - } - - /** - * @return bool - */ - public function hasChildren() - { - return $this->isRecursive && $this->iterator->hasChildren(); - } - - public function getChildren() - { - $children = new self($this->iterator->getChildren(), []); - $children->excludedDirs = $this->excludedDirs; - $children->excludedPattern = $this->excludedPattern; - - return $children; - } -} diff --git a/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php b/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php deleted file mode 100644 index a4c4eec..0000000 --- a/vendor/symfony/finder/Iterator/FileTypeFilterIterator.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * FileTypeFilterIterator only keeps files, directories, or both. - * - * @author Fabien Potencier - */ -class FileTypeFilterIterator extends \FilterIterator -{ - const ONLY_FILES = 1; - const ONLY_DIRECTORIES = 2; - - private $mode; - - /** - * @param \Iterator $iterator The Iterator to filter - * @param int $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) - */ - public function __construct(\Iterator $iterator, int $mode) - { - $this->mode = $mode; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return bool true if the value should be kept, false otherwise - */ - public function accept() - { - $fileinfo = $this->current(); - if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) { - return false; - } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) { - return false; - } - - return true; - } -} diff --git a/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php b/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php deleted file mode 100644 index b26a368..0000000 --- a/vendor/symfony/finder/Iterator/FilecontentFilterIterator.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings). - * - * @author Fabien Potencier - * @author Włodzimierz Gajda - */ -class FilecontentFilterIterator extends MultiplePcreFilterIterator -{ - /** - * Filters the iterator values. - * - * @return bool true if the value should be kept, false otherwise - */ - public function accept() - { - if (!$this->matchRegexps && !$this->noMatchRegexps) { - return true; - } - - $fileinfo = $this->current(); - - if ($fileinfo->isDir() || !$fileinfo->isReadable()) { - return false; - } - - $content = $fileinfo->getContents(); - if (!$content) { - return false; - } - - return $this->isAccepted($content); - } - - /** - * Converts string to regexp if necessary. - * - * @param string $str Pattern: string or regexp - * - * @return string regexp corresponding to a given string or regexp - */ - protected function toRegex(string $str) - { - return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; - } -} diff --git a/vendor/symfony/finder/Iterator/FilenameFilterIterator.php b/vendor/symfony/finder/Iterator/FilenameFilterIterator.php deleted file mode 100644 index dedd1ca..0000000 --- a/vendor/symfony/finder/Iterator/FilenameFilterIterator.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Glob; - -/** - * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string). - * - * @author Fabien Potencier - */ -class FilenameFilterIterator extends MultiplePcreFilterIterator -{ - /** - * Filters the iterator values. - * - * @return bool true if the value should be kept, false otherwise - */ - public function accept() - { - return $this->isAccepted($this->current()->getFilename()); - } - - /** - * Converts glob to regexp. - * - * PCRE patterns are left unchanged. - * Glob strings are transformed with Glob::toRegex(). - * - * @param string $str Pattern: glob or regexp - * - * @return string regexp corresponding to a given glob or regexp - */ - protected function toRegex(string $str) - { - return $this->isRegex($str) ? $str : Glob::toRegex($str); - } -} diff --git a/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php b/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php deleted file mode 100644 index 78a34ab..0000000 --- a/vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php +++ /dev/null @@ -1,106 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings). - * - * @author Fabien Potencier - */ -abstract class MultiplePcreFilterIterator extends \FilterIterator -{ - protected $matchRegexps = []; - protected $noMatchRegexps = []; - - /** - * @param \Iterator $iterator The Iterator to filter - * @param string[] $matchPatterns An array of patterns that need to match - * @param string[] $noMatchPatterns An array of patterns that need to not match - */ - public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns) - { - foreach ($matchPatterns as $pattern) { - $this->matchRegexps[] = $this->toRegex($pattern); - } - - foreach ($noMatchPatterns as $pattern) { - $this->noMatchRegexps[] = $this->toRegex($pattern); - } - - parent::__construct($iterator); - } - - /** - * Checks whether the string is accepted by the regex filters. - * - * If there is no regexps defined in the class, this method will accept the string. - * Such case can be handled by child classes before calling the method if they want to - * apply a different behavior. - * - * @return bool - */ - protected function isAccepted(string $string) - { - // should at least not match one rule to exclude - foreach ($this->noMatchRegexps as $regex) { - if (preg_match($regex, $string)) { - return false; - } - } - - // should at least match one rule - if ($this->matchRegexps) { - foreach ($this->matchRegexps as $regex) { - if (preg_match($regex, $string)) { - return true; - } - } - - return false; - } - - // If there is no match rules, the file is accepted - return true; - } - - /** - * Checks whether the string is a regex. - * - * @return bool - */ - protected function isRegex(string $str) - { - if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) { - $start = substr($m[1], 0, 1); - $end = substr($m[1], -1); - - if ($start === $end) { - return !preg_match('/[*?[:alnum:] \\\\]/', $start); - } - - foreach ([['{', '}'], ['(', ')'], ['[', ']'], ['<', '>']] as $delimiters) { - if ($start === $delimiters[0] && $end === $delimiters[1]) { - return true; - } - } - } - - return false; - } - - /** - * Converts string into regexp. - * - * @return string - */ - abstract protected function toRegex(string $str); -} diff --git a/vendor/symfony/finder/Iterator/PathFilterIterator.php b/vendor/symfony/finder/Iterator/PathFilterIterator.php deleted file mode 100644 index 67b71f4..0000000 --- a/vendor/symfony/finder/Iterator/PathFilterIterator.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * PathFilterIterator filters files by path patterns (e.g. some/special/dir). - * - * @author Fabien Potencier - * @author Włodzimierz Gajda - */ -class PathFilterIterator extends MultiplePcreFilterIterator -{ - /** - * Filters the iterator values. - * - * @return bool true if the value should be kept, false otherwise - */ - public function accept() - { - $filename = $this->current()->getRelativePathname(); - - if ('\\' === \DIRECTORY_SEPARATOR) { - $filename = str_replace('\\', '/', $filename); - } - - return $this->isAccepted($filename); - } - - /** - * Converts strings to regexp. - * - * PCRE patterns are left unchanged. - * - * Default conversion: - * 'lorem/ipsum/dolor' ==> 'lorem\/ipsum\/dolor/' - * - * Use only / as directory separator (on Windows also). - * - * @param string $str Pattern: regexp or dirname - * - * @return string regexp corresponding to a given string or regexp - */ - protected function toRegex(string $str) - { - return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; - } -} diff --git a/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php b/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php deleted file mode 100644 index 3facef5..0000000 --- a/vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php +++ /dev/null @@ -1,140 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Exception\AccessDeniedException; -use Symfony\Component\Finder\SplFileInfo; - -/** - * Extends the \RecursiveDirectoryIterator to support relative paths. - * - * @author Victor Berchet - */ -class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator -{ - /** - * @var bool - */ - private $ignoreUnreadableDirs; - - /** - * @var bool - */ - private $rewindable; - - // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations - private $rootPath; - private $subPath; - private $directorySeparator = '/'; - - /** - * @throws \RuntimeException - */ - public function __construct(string $path, int $flags, bool $ignoreUnreadableDirs = false) - { - if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) { - throw new \RuntimeException('This iterator only support returning current as fileinfo.'); - } - - parent::__construct($path, $flags); - $this->ignoreUnreadableDirs = $ignoreUnreadableDirs; - $this->rootPath = $path; - if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) { - $this->directorySeparator = \DIRECTORY_SEPARATOR; - } - } - - /** - * Return an instance of SplFileInfo with support for relative paths. - * - * @return SplFileInfo File information - */ - public function current() - { - // the logic here avoids redoing the same work in all iterations - - if (null === $subPathname = $this->subPath) { - $subPathname = $this->subPath = (string) $this->getSubPath(); - } - if ('' !== $subPathname) { - $subPathname .= $this->directorySeparator; - } - $subPathname .= $this->getFilename(); - - return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname); - } - - /** - * @return \RecursiveIterator - * - * @throws AccessDeniedException - */ - public function getChildren() - { - try { - $children = parent::getChildren(); - - if ($children instanceof self) { - // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore - $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs; - - // performance optimization to avoid redoing the same work in all children - $children->rewindable = &$this->rewindable; - $children->rootPath = $this->rootPath; - } - - return $children; - } catch (\UnexpectedValueException $e) { - if ($this->ignoreUnreadableDirs) { - // If directory is unreadable and finder is set to ignore it, a fake empty content is returned. - return new \RecursiveArrayIterator([]); - } else { - throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); - } - } - } - - /** - * Do nothing for non rewindable stream. - */ - public function rewind() - { - if (false === $this->isRewindable()) { - return; - } - - parent::rewind(); - } - - /** - * Checks if the stream is rewindable. - * - * @return bool true when the stream is rewindable, false otherwise - */ - public function isRewindable() - { - if (null !== $this->rewindable) { - return $this->rewindable; - } - - if (false !== $stream = @opendir($this->getPath())) { - $infos = stream_get_meta_data($stream); - closedir($stream); - - if ($infos['seekable']) { - return $this->rewindable = true; - } - } - - return $this->rewindable = false; - } -} diff --git a/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php b/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php deleted file mode 100644 index 2aeef67..0000000 --- a/vendor/symfony/finder/Iterator/SizeRangeFilterIterator.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -use Symfony\Component\Finder\Comparator\NumberComparator; - -/** - * SizeRangeFilterIterator filters out files that are not in the given size range. - * - * @author Fabien Potencier - */ -class SizeRangeFilterIterator extends \FilterIterator -{ - private $comparators = []; - - /** - * @param \Iterator $iterator The Iterator to filter - * @param NumberComparator[] $comparators An array of NumberComparator instances - */ - public function __construct(\Iterator $iterator, array $comparators) - { - $this->comparators = $comparators; - - parent::__construct($iterator); - } - - /** - * Filters the iterator values. - * - * @return bool true if the value should be kept, false otherwise - */ - public function accept() - { - $fileinfo = $this->current(); - if (!$fileinfo->isFile()) { - return true; - } - - $filesize = $fileinfo->getSize(); - foreach ($this->comparators as $compare) { - if (!$compare->test($filesize)) { - return false; - } - } - - return true; - } -} diff --git a/vendor/symfony/finder/Iterator/SortableIterator.php b/vendor/symfony/finder/Iterator/SortableIterator.php deleted file mode 100644 index 2aca397..0000000 --- a/vendor/symfony/finder/Iterator/SortableIterator.php +++ /dev/null @@ -1,101 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * SortableIterator applies a sort on a given Iterator. - * - * @author Fabien Potencier - */ -class SortableIterator implements \IteratorAggregate -{ - const SORT_BY_NONE = 0; - const SORT_BY_NAME = 1; - const SORT_BY_TYPE = 2; - const SORT_BY_ACCESSED_TIME = 3; - const SORT_BY_CHANGED_TIME = 4; - const SORT_BY_MODIFIED_TIME = 5; - const SORT_BY_NAME_NATURAL = 6; - - private $iterator; - private $sort; - - /** - * @param \Traversable $iterator The Iterator to filter - * @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback) - * - * @throws \InvalidArgumentException - */ - public function __construct(\Traversable $iterator, $sort, bool $reverseOrder = false) - { - $this->iterator = $iterator; - $order = $reverseOrder ? -1 : 1; - - if (self::SORT_BY_NAME === $sort) { - $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { - return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); - }; - } elseif (self::SORT_BY_NAME_NATURAL === $sort) { - $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { - return $order * strnatcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); - }; - } elseif (self::SORT_BY_TYPE === $sort) { - $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { - if ($a->isDir() && $b->isFile()) { - return -$order; - } elseif ($a->isFile() && $b->isDir()) { - return $order; - } - - return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); - }; - } elseif (self::SORT_BY_ACCESSED_TIME === $sort) { - $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { - return $order * ($a->getATime() - $b->getATime()); - }; - } elseif (self::SORT_BY_CHANGED_TIME === $sort) { - $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { - return $order * ($a->getCTime() - $b->getCTime()); - }; - } elseif (self::SORT_BY_MODIFIED_TIME === $sort) { - $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { - return $order * ($a->getMTime() - $b->getMTime()); - }; - } elseif (self::SORT_BY_NONE === $sort) { - $this->sort = $order; - } elseif (\is_callable($sort)) { - $this->sort = $reverseOrder ? static function (\SplFileInfo $a, \SplFileInfo $b) use ($sort) { return -$sort($a, $b); } : $sort; - } else { - throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.'); - } - } - - /** - * @return \Traversable - */ - public function getIterator() - { - if (1 === $this->sort) { - return $this->iterator; - } - - $array = iterator_to_array($this->iterator, true); - - if (-1 === $this->sort) { - $array = array_reverse($array); - } else { - uasort($array, $this->sort); - } - - return new \ArrayIterator($array); - } -} diff --git a/vendor/symfony/finder/LICENSE b/vendor/symfony/finder/LICENSE deleted file mode 100644 index a677f43..0000000 --- a/vendor/symfony/finder/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/finder/README.md b/vendor/symfony/finder/README.md deleted file mode 100644 index 0b19c75..0000000 --- a/vendor/symfony/finder/README.md +++ /dev/null @@ -1,14 +0,0 @@ -Finder Component -================ - -The Finder component finds files and directories via an intuitive fluent -interface. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/finder.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/finder/SplFileInfo.php b/vendor/symfony/finder/SplFileInfo.php deleted file mode 100644 index 65d7423..0000000 --- a/vendor/symfony/finder/SplFileInfo.php +++ /dev/null @@ -1,85 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder; - -/** - * Extends \SplFileInfo to support relative paths. - * - * @author Fabien Potencier - */ -class SplFileInfo extends \SplFileInfo -{ - private $relativePath; - private $relativePathname; - - /** - * @param string $file The file name - * @param string $relativePath The relative path - * @param string $relativePathname The relative path name - */ - public function __construct(string $file, string $relativePath, string $relativePathname) - { - parent::__construct($file); - $this->relativePath = $relativePath; - $this->relativePathname = $relativePathname; - } - - /** - * Returns the relative path. - * - * This path does not contain the file name. - * - * @return string the relative path - */ - public function getRelativePath() - { - return $this->relativePath; - } - - /** - * Returns the relative path name. - * - * This path contains the file name. - * - * @return string the relative path name - */ - public function getRelativePathname() - { - return $this->relativePathname; - } - - public function getFilenameWithoutExtension(): string - { - $filename = $this->getFilename(); - - return pathinfo($filename, PATHINFO_FILENAME); - } - - /** - * Returns the contents of the file. - * - * @return string the contents of the file - * - * @throws \RuntimeException - */ - public function getContents() - { - set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); - $content = file_get_contents($this->getPathname()); - restore_error_handler(); - if (false === $content) { - throw new \RuntimeException($error); - } - - return $content; - } -} diff --git a/vendor/symfony/finder/composer.json b/vendor/symfony/finder/composer.json deleted file mode 100644 index 65a1988..0000000 --- a/vendor/symfony/finder/composer.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "symfony/finder", - "type": "library", - "description": "Symfony Finder Component", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Finder\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/framework-bundle/.gitattributes b/vendor/symfony/framework-bundle/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/framework-bundle/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/framework-bundle/CHANGELOG.md b/vendor/symfony/framework-bundle/CHANGELOG.md deleted file mode 100644 index 8188769..0000000 --- a/vendor/symfony/framework-bundle/CHANGELOG.md +++ /dev/null @@ -1,413 +0,0 @@ -CHANGELOG -========= - -5.0.0 ------ - - * Removed support to load translation resources from the legacy directories `src/Resources/translations/` and `src/Resources//translations/` - * Removed `ControllerNameParser`. - * Removed `ResolveControllerNameSubscriber` - * Removed support for `bundle:controller:action` to reference controllers. Use `serviceOrFqcn::method` instead - * Removed support for PHP templating, use Twig instead - * Removed `Controller`, use `AbstractController` instead - * Removed `Client`, use `KernelBrowser` instead - * Removed `ContainerAwareCommand`, use dependency injection instead - * Removed the `validation.strict_email` option, use `validation.email_validation_mode` instead - * Removed the `cache.app.simple` service and its corresponding PSR-16 autowiring alias - * Removed cache-related compiler passes and `RequestDataCollector` - * Removed the `translator.selector` and `session.save_listener` services - * Removed `SecurityUserValueResolver`, use `UserValueResolver` instead - * Removed `routing.loader.service`. - * Service route loaders must be tagged with `routing.route_loader`. - * Added `slugger` service and `SluggerInterface` alias - * Removed the `lock.store.flock`, `lock.store.semaphore`, `lock.store.memcached.abstract` and `lock.store.redis.abstract` services. - -4.4.0 ------ - - * Added `lint:container` command to check that services wiring matches type declarations - * Added `MailerAssertionsTrait` - * Deprecated support for `templating` engine in `TemplateController`, use Twig instead - * Deprecated the `$parser` argument of `ControllerResolver::__construct()` and `DelegatingLoader::__construct()` - * Deprecated the `controller_name_converter` and `resolve_controller_name_subscriber` services - * The `ControllerResolver` and `DelegatingLoader` classes have been marked as `final` - * Added support for configuring chained cache pools - * Deprecated calling `WebTestCase::createClient()` while a kernel has been booted, ensure the kernel is shut down before calling the method - * Deprecated `routing.loader.service`, use `routing.loader.container` instead. - * Not tagging service route loaders with `routing.route_loader` has been deprecated. - * Overriding the methods `KernelTestCase::tearDown()` and `WebTestCase::tearDown()` without the `void` return-type is deprecated. - * Added new `error_controller` configuration to handle system exceptions - * Added sort option for `translation:update` command. - * [BC Break] The `framework.messenger.routing.senders` config key is not deeply merged anymore. - * Added `secrets:*` commands to deal with secrets seamlessly. - * Made `framework.session.handler_id` accept a DSN - * Marked the `RouterDataCollector` class as `@final`. - * [BC Break] The `framework.messenger.buses..middleware` config key is not deeply merged anymore. - -4.3.0 ------ - - * Deprecated the `framework.templating` option, configure the Twig bundle instead. - * Added `WebTestAssertionsTrait` (included by default in `WebTestCase`) - * Renamed `Client` to `KernelBrowser` - * Not passing the project directory to the constructor of the `AssetsInstallCommand` is deprecated. This argument will - be mandatory in 5.0. - * Deprecated the "Psr\SimpleCache\CacheInterface" / "cache.app.simple" service, use "Symfony\Contracts\Cache\CacheInterface" / "cache.app" instead - * Added the ability to specify a custom `serializer` option for each - transport under`framework.messenger.transports`. - * Added the `RegisterLocaleAwareServicesPass` and configured the `LocaleAwareListener` - * [BC Break] When using Messenger, the default transport changed from - using Symfony's serializer service to use `PhpSerializer`, which uses - PHP's native `serialize()` and `unserialize()` functions. To use the - original serialization method, set the `framework.messenger.default_serializer` - config option to `messenger.transport.symfony_serializer`. Or set the - `serializer` option under one specific `transport`. - * [BC Break] The `framework.messenger.serializer` config key changed to - `framework.messenger.default_serializer`, which holds the string service - id and `framework.messenger.symfony_serializer`, which configures the - options if you're using Symfony's serializer. - * [BC Break] Removed the `framework.messenger.routing.send_and_handle` configuration. - Instead of setting it to true, configure a `SyncTransport` and route messages to it. - * Added information about deprecated aliases in `debug:autowiring` - * Added php ini session options `sid_length` and `sid_bits_per_character` - to the `session` section of the configuration - * Added support for Translator paths, Twig paths in translation commands. - * Added support for PHP files with translations in translation commands. - * Added support for boolean container parameters within routes. - * Added the `messenger:setup-transports` command to setup messenger transports - * Added a `InMemoryTransport` to Messenger. Use it with a DSN starting with `in-memory://`. - * Added `framework.property_access.throw_exception_on_invalid_property_path` config option. - * Added `cache:pool:list` command to list all available cache pools. - -4.2.0 ------ - - * Added a `AbstractController::addLink()` method to add Link headers to the current response - * Allowed configuring taggable cache pools via a new `framework.cache.pools.tags` option (bool|service-id) - * Allowed configuring PDO-based cache pools via a new `cache.adapter.pdo` abstract service - * Deprecated auto-injection of the container in AbstractController instances, register them as service subscribers instead - * Deprecated processing of services tagged `security.expression_language_provider` in favor of a new `AddExpressionLanguageProvidersPass` in SecurityBundle. - * Deprecated the `Symfony\Bundle\FrameworkBundle\Controller\Controller` class in favor of `Symfony\Bundle\FrameworkBundle\Controller\AbstractController`. - * Enabled autoconfiguration for `Psr\Log\LoggerAwareInterface` - * Added new "auto" mode for `framework.session.cookie_secure` to turn it on when HTTPS is used - * Removed the `framework.messenger.encoder` and `framework.messenger.decoder` options. Use the `framework.messenger.serializer.id` option to replace the Messenger serializer. - * Deprecated the `ContainerAwareCommand` class in favor of `Symfony\Component\Console\Command\Command` - * Made `debug:container` and `debug:autowiring` ignore backslashes in service ids - * Deprecated the `Templating\Helper\TranslatorHelper::transChoice()` method, use the `trans()` one instead with a `%count%` parameter - * Deprecated `CacheCollectorPass`. Use `Symfony\Component\Cache\DependencyInjection\CacheCollectorPass` instead. - * Deprecated `CachePoolClearerPass`. Use `Symfony\Component\Cache\DependencyInjection\CachePoolClearerPass` instead. - * Deprecated `CachePoolPass`. Use `Symfony\Component\Cache\DependencyInjection\CachePoolPass` instead. - * Deprecated `CachePoolPrunerPass`. Use `Symfony\Component\Cache\DependencyInjection\CachePoolPrunerPass` instead. - * Deprecated support for legacy translations directories `src/Resources/translations/` and `src/Resources//translations/`, use `translations/` instead. - * Deprecated support for the legacy directory structure in `translation:update` and `debug:translation` commands. - -4.1.0 ------ - - * Allowed to pass an optional `LoggerInterface $logger` instance to the `Router` - * Added a new `parameter_bag` service with related autowiring aliases to access parameters as-a-service - * Allowed the `Router` to work with any PSR-11 container - * Added option in workflow dump command to label graph with a custom label - * Using a `RouterInterface` that does not implement the `WarmableInterface` is deprecated. - * Warming up a router in `RouterCacheWarmer` that does not implement the `WarmableInterface` is deprecated and will not - be supported anymore in 5.0. - * The `RequestDataCollector` class has been deprecated. Use the `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector` class instead. - * The `RedirectController` class allows for 307/308 HTTP status codes - * Deprecated `bundle:controller:action` syntax to reference controllers. Use `serviceOrFqcn::method` instead where `serviceOrFqcn` - is either the service ID or the FQCN of the controller. - * Deprecated `Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser` - * The `container.service_locator` tag of `ServiceLocator`s is now autoconfigured. - * Add the ability to search a route in `debug:router`. - * Add the ability to use SameSite cookies for sessions. - -4.0.0 ------ - - * The default `type` option of the `framework.workflows.*` configuration entries is `state_machine` - * removed `AddConsoleCommandPass`, `AddConstraintValidatorsPass`, - `AddValidatorInitializersPass`, `CompilerDebugDumpPass`, `ConfigCachePass`, - `ControllerArgumentValueResolverPass`, `FormPass`, `PropertyInfoPass`, - `RoutingResolverPass`, `SerializerPass`, `ValidateWorkflowsPass` - * made `Translator::__construct()` `$defaultLocale` argument required - * removed `SessionListener`, `TestSessionListener` - * Removed `cache:clear` warmup part along with the `--no-optional-warmers` option - * Removed core form types services registration when unnecessary - * Removed `framework.serializer.cache` option and `serializer.mapping.cache.apc`, `serializer.mapping.cache.doctrine.apc` services - * Removed `ConstraintValidatorFactory` - * Removed class parameters related to routing - * Removed absolute template paths support in the template name parser - * Removed support of the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. - * Removed the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. - * Removed the "framework.validation.cache" configuration option. Configure the "cache.validator" service under "framework.cache.pools" instead. - * Removed `PhpStringTokenParser`, use `Symfony\Component\Translation\Extractor\PhpStringTokenParser` instead. - * Removed `PhpExtractor`, use `Symfony\Component\Translation\Extractor\PhpExtractor` instead. - * Removed the `use_strict_mode` session option, it's is now enabled by default - -3.4.0 ------ - - * Added `translator.default_path` option and parameter - * Session `use_strict_mode` is now enabled by default and the corresponding option has been deprecated - * Made the `cache:clear` command to *not* clear "app" PSR-6 cache pools anymore, - but to still clear "system" ones; use the `cache:pool:clear` command to clear "app" pools instead - * Always register a minimalist logger that writes in `stderr` - * Deprecated `profiler.matcher` option - * Added support for `EventSubscriberInterface` on `MicroKernelTrait` - * Removed `doctrine/cache` from the list of required dependencies in `composer.json` - * Deprecated `validator.mapping.cache.doctrine.apc` service - * The `symfony/stopwatch` dependency has been removed, require it via `composer - require symfony/stopwatch` in your `dev` environment. - * Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. - * Deprecated the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. - * Deprecated `AddCacheClearerPass`, use tagged iterator arguments instead. - * Deprecated `AddCacheWarmerPass`, use tagged iterator arguments instead. - * Deprecated `TranslationDumperPass`, use - `Symfony\Component\Translation\DependencyInjection\TranslationDumperPass` instead - * Deprecated `TranslationExtractorPass`, use - `Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass` instead - * Deprecated `TranslatorPass`, use - `Symfony\Component\Translation\DependencyInjection\TranslatorPass` instead - * Added `command` attribute to the `console.command` tag which takes the command - name as value, using it makes the command lazy - * Added `cache:pool:prune` command to allow manual stale cache item pruning of supported PSR-6 and PSR-16 cache pool - implementations - * Deprecated `Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader`, use - `Symfony\Component\Translation\Reader\TranslationReader` instead - * Deprecated `translation.loader` service, use `translation.reader` instead - * `AssetsInstallCommand::__construct()` now takes an instance of - `Symfony\Component\Filesystem\Filesystem` as first argument - * `CacheClearCommand::__construct()` now takes an instance of - `Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface` as - first argument - * `CachePoolClearCommand::__construct()` now takes an instance of - `Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer` as - first argument - * `EventDispatcherDebugCommand::__construct()` now takes an instance of - `Symfony\Component\EventDispatcher\EventDispatcherInterface` as - first argument - * `RouterDebugCommand::__construct()` now takes an instance of - `Symfony\Component\Routing\RouterInterface` as - first argument - * `RouterMatchCommand::__construct()` now takes an instance of - `Symfony\Component\Routing\RouterInterface` as - first argument - * `TranslationDebugCommand::__construct()` now takes an instance of - `Symfony\Component\Translation\TranslatorInterface` as - first argument - * `TranslationUpdateCommand::__construct()` now takes an instance of - `Symfony\Component\Translation\TranslatorInterface` as - first argument - * `AssetsInstallCommand`, `CacheClearCommand`, `CachePoolClearCommand`, - `EventDispatcherDebugCommand`, `RouterDebugCommand`, `RouterMatchCommand`, - `TranslationDebugCommand`, `TranslationUpdateCommand`, `XliffLintCommand` - and `YamlLintCommand` classes have been marked as final - * Added `asset.request_context.base_path` and `asset.request_context.secure` parameters - to provide a default request context in case the stack is empty (similar to `router.request_context.*` parameters) - * Display environment variables managed by `Dotenv` in `AboutCommand` - -3.3.0 ------ - - * Not defining the `type` option of the `framework.workflows.*` configuration entries is deprecated. - The default value will be `state_machine` in Symfony 4.0. - * Deprecated the `CompilerDebugDumpPass` class - * Deprecated the "framework.trusted_proxies" configuration option and the corresponding "kernel.trusted_proxies" parameter - * Added a new version strategy option called "json_manifest_path" - that allows you to use the `JsonManifestVersionStrategy`. - * Added `Symfony\Bundle\FrameworkBundle\Controller\AbstractController`. It provides - the same helpers as the `Controller` class, but does not allow accessing the dependency - injection container, in order to encourage explicit dependency declarations. - * Added support for the `controller.service_arguments` tag, for injecting services into controllers' actions - * Changed default configuration for - assets/forms/validation/translation/serialization/csrf from `canBeEnabled()` to - `canBeDisabled()` when Flex is used - * The server:* commands and their associated router files were moved to WebServerBundle - * Translation related services are not loaded anymore when the `framework.translator` option - is disabled. - * Added `GlobalVariables::getToken()` - * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass`. Use `Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass` instead. - * Added configurable paths for validation files - * Deprecated `SerializerPass`, use `Symfony\Component\Serializer\DependencyInjection\SerializerPass` instead - * Deprecated `FormPass`, use `Symfony\Component\Form\DependencyInjection\FormPass` instead - * Deprecated `SessionListener` - * Deprecated `TestSessionListener` - * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass`. - Use tagged iterator arguments instead. - * Deprecated `PropertyInfoPass`, use `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass` instead - * Deprecated `ControllerArgumentValueResolverPass`. Use - `Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass` instead - * Deprecated `RoutingResolverPass`, use `Symfony\Component\Routing\DependencyInjection\RoutingResolverPass` instead - * [BC BREAK] The `server:run`, `server:start`, `server:stop` and - `server:status` console commands have been moved to a dedicated bundle. - Require `symfony/web-server-bundle` in your composer.json and register - `Symfony\Bundle\WebServerBundle\WebServerBundle` in your AppKernel to use them. - * Added `$defaultLocale` as 3rd argument of `Translator::__construct()` - making `Translator` works with any PSR-11 container - * Added `framework.serializer.mapping` config option allowing to define custom - serialization mapping files and directories - * Deprecated `AddValidatorInitializersPass`, use - `Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass` instead - * Deprecated `AddConstraintValidatorsPass`, use - `Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass` instead - * Deprecated `ValidateWorkflowsPass`, use - `Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass` instead - * Deprecated `ConstraintValidatorFactory`, use - `Symfony\Component\Validator\ContainerConstraintValidatorFactory` instead. - * Deprecated `PhpStringTokenParser`, use - `Symfony\Component\Translation\Extractor\PhpStringTokenParser` instead. - * Deprecated `PhpExtractor`, use - `Symfony\Component\Translation\Extractor\PhpExtractor` instead. - -3.2.0 ------ - - * Removed `doctrine/annotations` from the list of required dependencies in `composer.json` - * Removed `symfony/security-core` and `symfony/security-csrf` from the list of required dependencies in `composer.json` - * Removed `symfony/templating` from the list of required dependencies in `composer.json` - * Removed `symfony/translation` from the list of required dependencies in `composer.json` - * Removed `symfony/asset` from the list of required dependencies in `composer.json` - * The `Resources/public/images/*` files have been removed. - * The `Resources/public/css/*.css` files have been removed (they are now inlined in TwigBundle). - * Added possibility to prioritize form type extensions with `'priority'` attribute on tags `form.type_extension` - -3.1.0 ------ - - * Added `Controller::json` to simplify creating JSON responses when using the Serializer component - * Deprecated absolute template paths support in the template name parser - * Deprecated using core form types without dependencies as services - * Added `Symfony\Component\HttpHernel\DataCollector\RequestDataCollector::onKernelResponse()` - * Added `Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector` - * The `framework.serializer.cache` option and the service `serializer.mapping.cache.apc` have been - deprecated. APCu should now be automatically used when available. - -3.0.0 ------ - - * removed `validator.api` parameter - * removed `alias` option of the `form.type` tag - -2.8.0 ------ - - * Deprecated the `alias` option of the `form.type_extension` tag in favor of the - `extended_type`/`extended-type` option - * Deprecated the `alias` option of the `form.type` tag - * Deprecated the Shell - -2.7.0 ------ - - * Added possibility to extract translation messages from a file or files besides extracting from a directory - * Added `TranslationsCacheWarmer` to create catalogues at warmup - -2.6.0 ------ - - * Added helper commands (`server:start`, `server:stop` and `server:status`) to control the built-in web - server in the background - * Added `Controller::isCsrfTokenValid` helper - * Added configuration for the PropertyAccess component - * Added `Controller::redirectToRoute` helper - * Added `Controller::addFlash` helper - * Added `Controller::isGranted` helper - * Added `Controller::denyAccessUnlessGranted` helper - * Deprecated `app.security` in twig as `app.user` and `is_granted()` are already available - -2.5.0 ------ - - * Added `translation:debug` command - * Added `--no-backup` option to `translation:update` command - * Added `config:debug` command - * Added `yaml:lint` command - * Deprecated the `RouterApacheDumperCommand` which will be removed in Symfony 3.0. - -2.4.0 ------ - - * allowed multiple IP addresses in profiler matcher settings - * added stopwatch helper to time templates with the WebProfilerBundle - * added service definition for "security.secure_random" service - * added service definitions for the new Security CSRF sub-component - -2.3.0 ------ - - * [BC BREAK] added a way to disable the profiler (when disabling the profiler, it is now completely removed) - To get the same "disabled" behavior as before, set `enabled` to `true` and `collect` to `false` - * [BC BREAK] the `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RegisterKernelListenersPass` was moved - to `Component\HttpKernel\DependencyInjection\RegisterListenersPass` - * added ControllerNameParser::build() which converts a controller short notation (a:b:c) to a class::method notation - * added possibility to run PHP built-in server in production environment - * added possibility to load the serializer component in the service container - * added route debug information when using the `router:match` command - * added `TimedPhpEngine` - * added `--clean` option to the `translation:update` command - * added `http_method_override` option - * added support for default templates per render tag - * added FormHelper::form(), FormHelper::start() and FormHelper::end() - * deprecated FormHelper::enctype() in favor of FormHelper::start() - * RedirectController actions now receive the Request instance via the method signature. - -2.2.0 ------ - - * added a new `uri_signer` service to help sign URIs - * deprecated `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` and `Symfony\Bundle\FrameworkBundle\HttpKernel::forward()` - * deprecated the `Symfony\Bundle\FrameworkBundle\HttpKernel` class in favor of `Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel` - * added support for adding new HTTP content rendering strategies (like ESI and Hinclude) - in the DIC via the `kernel.fragment_renderer` tag - * [BC BREAK] restricted the `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method to only accept URIs or ControllerReference instances - * `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method signature changed and the first argument - must now be a URI or a ControllerReference instance (the `generateInternalUri()` method was removed) - * The internal routes (`Resources/config/routing/internal.xml`) have been removed and replaced with a listener (`Symfony\Component\HttpKernel\EventListener\FragmentListener`) - * The `render` method of the `actions` templating helper signature and arguments changed - * replaced Symfony\Bundle\FrameworkBundle\Controller\TraceableControllerResolver by Symfony\Component\HttpKernel\Controller\TraceableControllerResolver - * replaced Symfony\Component\HttpKernel\Debug\ContainerAwareTraceableEventDispatcher by Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher - * added Client::enableProfiler() - * a new parameter has been added to the DIC: `router.request_context.base_url` - You can customize it for your functional tests or for generating URLs with - the right base URL when your are in the CLI context. - * added support for default templates per render tag - -2.1.0 ------ - - * moved the translation files to the Form and Validator components - * changed the default extension for XLIFF files from .xliff to .xlf - * moved Symfony\Bundle\FrameworkBundle\ContainerAwareEventDispatcher to Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher - * moved Symfony\Bundle\FrameworkBundle\Debug\TraceableEventDispatcher to Symfony\Component\EventDispatcher\ContainerAwareTraceableEventDispatcher - * added a router:match command - * added a config:dump-reference command - * added a server:run command - * added kernel.event_subscriber tag - * added a way to create relative symlinks when running assets:install command (--relative option) - * added Controller::getUser() - * [BC BREAK] assets_base_urls and base_urls merging strategy has changed - * changed the default profiler storage to use the filesystem instead of SQLite - * added support for placeholders in route defaults and requirements (replaced - by the value set in the service container) - * added Filesystem component as a dependency - * added support for hinclude (use ``standalone: 'js'`` in render tag) - * session options: lifetime, path, domain, secure, httponly were deprecated. - Prefixed versions should now be used instead: cookie_lifetime, cookie_path, - cookie_domain, cookie_secure, cookie_httponly - * [BC BREAK] following session options: 'lifetime', 'path', 'domain', 'secure', - 'httponly' are now prefixed with cookie_ when dumped to the container - * Added `handler_id` configuration under `session` key to represent `session.handler` - service, defaults to `session.handler.native_file`. - * Added `gc_maxlifetime`, `gc_probability`, and `gc_divisor` to session - configuration. This means session garbage collection has a - `gc_probability`/`gc_divisor` chance of being run. The `gc_maxlifetime` defines - how long a session can idle for. It is different from cookie lifetime which - declares how long a cookie can be stored on the remote client. - * Removed 'auto_start' configuration parameter from session config. The session will - start on demand. - * [BC BREAK] TemplateNameParser::parseFromFilename() has been moved to a dedicated - parser: TemplateFilenameParser::parse(). - * [BC BREAK] Kernel parameters are replaced by their value wherever they appear - in Route patterns, requirements and defaults. Use '%%' as the escaped value for '%'. - * [BC BREAK] Switched behavior of flash messages to expire flash messages on retrieval - using Symfony\Component\HttpFoundation\Session\Flash\FlashBag as opposed to on - next pageload regardless of whether they are displayed or not. diff --git a/vendor/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php b/vendor/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php deleted file mode 100644 index 0e4561a..0000000 --- a/vendor/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\NullAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; -use Symfony\Component\Config\Resource\ClassExistenceResource; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; - -/** - * @internal - */ -abstract class AbstractPhpFileCacheWarmer implements CacheWarmerInterface -{ - private $phpArrayFile; - - /** - * @param string $phpArrayFile The PHP file where metadata are cached - */ - public function __construct(string $phpArrayFile) - { - $this->phpArrayFile = $phpArrayFile; - } - - /** - * {@inheritdoc} - */ - public function isOptional() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function warmUp(string $cacheDir) - { - $arrayAdapter = new ArrayAdapter(); - - spl_autoload_register([ClassExistenceResource::class, 'throwOnRequiredClass']); - try { - if (!$this->doWarmUp($cacheDir, $arrayAdapter)) { - return; - } - } finally { - spl_autoload_unregister([ClassExistenceResource::class, 'throwOnRequiredClass']); - } - - // the ArrayAdapter stores the values serialized - // to avoid mutation of the data after it was written to the cache - // so here we un-serialize the values first - $values = array_map(function ($val) { return null !== $val ? unserialize($val) : null; }, $arrayAdapter->getValues()); - - $this->warmUpPhpArrayAdapter(new PhpArrayAdapter($this->phpArrayFile, new NullAdapter()), $values); - } - - protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values) - { - $phpArrayAdapter->warmUp($values); - } - - /** - * @internal - */ - final protected function ignoreAutoloadException(string $class, \Exception $exception): void - { - try { - ClassExistenceResource::throwOnRequiredClass($class, $exception); - } catch (\ReflectionException $e) { - } - } - - /** - * @return bool false if there is nothing to warm-up - */ - abstract protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter); -} diff --git a/vendor/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php b/vendor/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php deleted file mode 100644 index 2169eec..0000000 --- a/vendor/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php +++ /dev/null @@ -1,102 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Doctrine\Common\Annotations\AnnotationException; -use Doctrine\Common\Annotations\CachedReader; -use Doctrine\Common\Annotations\Reader; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\DoctrineProvider; - -/** - * Warms up annotation caches for classes found in composer's autoload class map - * and declared in DI bundle extensions using the addAnnotatedClassesToCache method. - * - * @author Titouan Galopin - */ -class AnnotationsCacheWarmer extends AbstractPhpFileCacheWarmer -{ - private $annotationReader; - private $excludeRegexp; - private $debug; - - /** - * @param string $phpArrayFile The PHP file where annotations are cached - */ - public function __construct(Reader $annotationReader, string $phpArrayFile, string $excludeRegexp = null, bool $debug = false) - { - parent::__construct($phpArrayFile); - $this->annotationReader = $annotationReader; - $this->excludeRegexp = $excludeRegexp; - $this->debug = $debug; - } - - /** - * {@inheritdoc} - */ - protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter) - { - $annotatedClassPatterns = $cacheDir.'/annotations.map'; - - if (!is_file($annotatedClassPatterns)) { - return true; - } - - $annotatedClasses = include $annotatedClassPatterns; - $reader = new CachedReader($this->annotationReader, new DoctrineProvider($arrayAdapter), $this->debug); - - foreach ($annotatedClasses as $class) { - if (null !== $this->excludeRegexp && preg_match($this->excludeRegexp, $class)) { - continue; - } - try { - $this->readAllComponents($reader, $class); - } catch (\Exception $e) { - $this->ignoreAutoloadException($class, $e); - } - } - - return true; - } - - private function readAllComponents(Reader $reader, string $class) - { - $reflectionClass = new \ReflectionClass($class); - - try { - $reader->getClassAnnotations($reflectionClass); - } catch (AnnotationException $e) { - /* - * Ignore any AnnotationException to not break the cache warming process if an Annotation is badly - * configured or could not be found / read / etc. - * - * In particular cases, an Annotation in your code can be used and defined only for a specific - * environment but is always added to the annotations.map file by some Symfony default behaviors, - * and you always end up with a not found Annotation. - */ - } - - foreach ($reflectionClass->getMethods() as $reflectionMethod) { - try { - $reader->getMethodAnnotations($reflectionMethod); - } catch (AnnotationException $e) { - } - } - - foreach ($reflectionClass->getProperties() as $reflectionProperty) { - try { - $reader->getPropertyAnnotations($reflectionProperty); - } catch (AnnotationException $e) { - } - } - } -} diff --git a/vendor/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php b/vendor/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php deleted file mode 100644 index fecce27..0000000 --- a/vendor/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php +++ /dev/null @@ -1,72 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; -use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; -use Symfony\Component\Routing\RouterInterface; -use Symfony\Contracts\Service\ServiceSubscriberInterface; - -/** - * Generates the router matcher and generator classes. - * - * @author Fabien Potencier - * - * @final - */ -class RouterCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface -{ - private $container; - - public function __construct(ContainerInterface $container) - { - // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function warmUp(string $cacheDir) - { - $router = $this->container->get('router'); - - if ($router instanceof WarmableInterface) { - $router->warmUp($cacheDir); - - return; - } - - throw new \LogicException(sprintf('The router %s cannot be warmed up because it does not implement %s.', \get_class($router), WarmableInterface::class)); - } - - /** - * Checks whether this warmer is optional or not. - * - * @return bool always true - */ - public function isOptional(): bool - { - return true; - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedServices(): array - { - return [ - 'router' => RouterInterface::class, - ]; - } -} diff --git a/vendor/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php b/vendor/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php deleted file mode 100644 index 0ada0ff..0000000 --- a/vendor/symfony/framework-bundle/CacheWarmer/SerializerCacheWarmer.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Doctrine\Common\Annotations\AnnotationException; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; -use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; -use Symfony\Component\Serializer\Mapping\Loader\LoaderChain; -use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface; -use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; -use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; - -/** - * Warms up XML and YAML serializer metadata. - * - * @author Titouan Galopin - */ -class SerializerCacheWarmer extends AbstractPhpFileCacheWarmer -{ - private $loaders; - - /** - * @param LoaderInterface[] $loaders The serializer metadata loaders - * @param string $phpArrayFile The PHP file where metadata are cached - */ - public function __construct(array $loaders, string $phpArrayFile) - { - parent::__construct($phpArrayFile); - $this->loaders = $loaders; - } - - /** - * {@inheritdoc} - */ - protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter) - { - if (!class_exists(CacheClassMetadataFactory::class) || !method_exists(XmlFileLoader::class, 'getMappedClasses') || !method_exists(YamlFileLoader::class, 'getMappedClasses')) { - return false; - } - - $metadataFactory = new CacheClassMetadataFactory(new ClassMetadataFactory(new LoaderChain($this->loaders)), $arrayAdapter); - - foreach ($this->extractSupportedLoaders($this->loaders) as $loader) { - foreach ($loader->getMappedClasses() as $mappedClass) { - try { - $metadataFactory->getMetadataFor($mappedClass); - } catch (AnnotationException $e) { - // ignore failing annotations - } catch (\Exception $e) { - $this->ignoreAutoloadException($mappedClass, $e); - } - } - } - - return true; - } - - /** - * @param LoaderInterface[] $loaders - * - * @return XmlFileLoader[]|YamlFileLoader[] - */ - private function extractSupportedLoaders(array $loaders): array - { - $supportedLoaders = []; - - foreach ($loaders as $loader) { - if ($loader instanceof XmlFileLoader || $loader instanceof YamlFileLoader) { - $supportedLoaders[] = $loader; - } elseif ($loader instanceof LoaderChain) { - $supportedLoaders = array_merge($supportedLoaders, $this->extractSupportedLoaders($loader->getLoaders())); - } - } - - return $supportedLoaders; - } -} diff --git a/vendor/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php b/vendor/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php deleted file mode 100644 index 28b6e43..0000000 --- a/vendor/symfony/framework-bundle/CacheWarmer/TranslationsCacheWarmer.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; -use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; -use Symfony\Contracts\Service\ServiceSubscriberInterface; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * Generates the catalogues for translations. - * - * @author Xavier Leune - */ -class TranslationsCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface -{ - private $container; - private $translator; - - public function __construct(ContainerInterface $container) - { - // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function warmUp(string $cacheDir) - { - if (null === $this->translator) { - $this->translator = $this->container->get('translator'); - } - - if ($this->translator instanceof WarmableInterface) { - $this->translator->warmUp($cacheDir); - } - } - - /** - * {@inheritdoc} - */ - public function isOptional() - { - return true; - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedServices() - { - return [ - 'translator' => TranslatorInterface::class, - ]; - } -} diff --git a/vendor/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php b/vendor/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php deleted file mode 100644 index 8569521..0000000 --- a/vendor/symfony/framework-bundle/CacheWarmer/ValidatorCacheWarmer.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Doctrine\Common\Annotations\AnnotationException; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; -use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; -use Symfony\Component\Validator\Mapping\Loader\LoaderChain; -use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; -use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader; -use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader; -use Symfony\Component\Validator\ValidatorBuilder; - -/** - * Warms up XML and YAML validator metadata. - * - * @author Titouan Galopin - */ -class ValidatorCacheWarmer extends AbstractPhpFileCacheWarmer -{ - private $validatorBuilder; - - /** - * @param string $phpArrayFile The PHP file where metadata are cached - */ - public function __construct(ValidatorBuilder $validatorBuilder, string $phpArrayFile) - { - parent::__construct($phpArrayFile); - $this->validatorBuilder = $validatorBuilder; - } - - /** - * {@inheritdoc} - */ - protected function doWarmUp(string $cacheDir, ArrayAdapter $arrayAdapter) - { - if (!method_exists($this->validatorBuilder, 'getLoaders')) { - return false; - } - - $loaders = $this->validatorBuilder->getLoaders(); - $metadataFactory = new LazyLoadingMetadataFactory(new LoaderChain($loaders), $arrayAdapter); - - foreach ($this->extractSupportedLoaders($loaders) as $loader) { - foreach ($loader->getMappedClasses() as $mappedClass) { - try { - if ($metadataFactory->hasMetadataFor($mappedClass)) { - $metadataFactory->getMetadataFor($mappedClass); - } - } catch (AnnotationException $e) { - // ignore failing annotations - } catch (\Exception $e) { - $this->ignoreAutoloadException($mappedClass, $e); - } - } - } - - return true; - } - - protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values) - { - // make sure we don't cache null values - parent::warmUpPhpArrayAdapter($phpArrayAdapter, array_filter($values)); - } - - /** - * @param LoaderInterface[] $loaders - * - * @return XmlFileLoader[]|YamlFileLoader[] - */ - private function extractSupportedLoaders(array $loaders): array - { - $supportedLoaders = []; - - foreach ($loaders as $loader) { - if ($loader instanceof XmlFileLoader || $loader instanceof YamlFileLoader) { - $supportedLoaders[] = $loader; - } elseif ($loader instanceof LoaderChain) { - $supportedLoaders = array_merge($supportedLoaders, $this->extractSupportedLoaders($loader->getLoaders())); - } - } - - return $supportedLoaders; - } -} diff --git a/vendor/symfony/framework-bundle/Command/AboutCommand.php b/vendor/symfony/framework-bundle/Command/AboutCommand.php deleted file mode 100644 index b9fbe67..0000000 --- a/vendor/symfony/framework-bundle/Command/AboutCommand.php +++ /dev/null @@ -1,144 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\Helper; -use Symfony\Component\Console\Helper\TableSeparator; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\Kernel; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * A console command to display information about the current installation. - * - * @author Roland Franssen - * - * @final - */ -class AboutCommand extends Command -{ - protected static $defaultName = 'about'; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription('Displays information about the current project') - ->setHelp(<<<'EOT' -The %command.name% command displays information about the current Symfony project. - -The PHP section displays important configuration that could affect your application. The values might -be different between web and CLI. - -The Environment section displays the current environment variables managed by Symfony Dotenv. It will not -be shown if no variables were found. The values might be different between web and CLI. -EOT - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - /** @var KernelInterface $kernel */ - $kernel = $this->getApplication()->getKernel(); - - $rows = [ - ['Symfony'], - new TableSeparator(), - ['Version', Kernel::VERSION], - ['Long-Term Support', 4 === Kernel::MINOR_VERSION ? 'Yes' : 'No'], - ['End of maintenance', Kernel::END_OF_MAINTENANCE.(self::isExpired(Kernel::END_OF_MAINTENANCE) ? ' Expired' : '')], - ['End of life', Kernel::END_OF_LIFE.(self::isExpired(Kernel::END_OF_LIFE) ? ' Expired' : '')], - new TableSeparator(), - ['Kernel'], - new TableSeparator(), - ['Type', \get_class($kernel)], - ['Environment', $kernel->getEnvironment()], - ['Debug', $kernel->isDebug() ? 'true' : 'false'], - ['Charset', $kernel->getCharset()], - ['Cache directory', self::formatPath($kernel->getCacheDir(), $kernel->getProjectDir()).' ('.self::formatFileSize($kernel->getCacheDir()).')'], - ['Log directory', self::formatPath($kernel->getLogDir(), $kernel->getProjectDir()).' ('.self::formatFileSize($kernel->getLogDir()).')'], - new TableSeparator(), - ['PHP'], - new TableSeparator(), - ['Version', PHP_VERSION], - ['Architecture', (PHP_INT_SIZE * 8).' bits'], - ['Intl locale', class_exists('Locale', false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a'], - ['Timezone', date_default_timezone_get().' ('.(new \DateTime())->format(\DateTime::W3C).')'], - ['OPcache', \extension_loaded('Zend OPcache') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false'], - ['APCu', \extension_loaded('apcu') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? 'true' : 'false'], - ['Xdebug', \extension_loaded('xdebug') ? 'true' : 'false'], - ]; - - if ($dotenv = self::getDotenvVars()) { - $rows = array_merge($rows, [ - new TableSeparator(), - ['Environment (.env)'], - new TableSeparator(), - ], array_map(function ($value, $name) { - return [$name, $value]; - }, $dotenv, array_keys($dotenv))); - } - - $io->table([], $rows); - - return 0; - } - - private static function formatPath(string $path, string $baseDir): string - { - return preg_replace('~^'.preg_quote($baseDir, '~').'~', '.', $path); - } - - private static function formatFileSize(string $path): string - { - if (is_file($path)) { - $size = filesize($path) ?: 0; - } else { - $size = 0; - foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS | \RecursiveDirectoryIterator::FOLLOW_SYMLINKS)) as $file) { - $size += $file->getSize(); - } - } - - return Helper::formatMemory($size); - } - - private static function isExpired(string $date): bool - { - $date = \DateTime::createFromFormat('d/m/Y', '01/'.$date); - - return false !== $date && new \DateTime() > $date->modify('last day of this month 23:59:59'); - } - - private static function getDotenvVars(): array - { - $vars = []; - foreach (explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? $_ENV['SYMFONY_DOTENV_VARS'] ?? '') as $name) { - if ('' !== $name && isset($_ENV[$name])) { - $vars[$name] = $_ENV[$name]; - } - } - - return $vars; - } -} diff --git a/vendor/symfony/framework-bundle/Command/AbstractConfigCommand.php b/vendor/symfony/framework-bundle/Command/AbstractConfigCommand.php deleted file mode 100644 index 232348d..0000000 --- a/vendor/symfony/framework-bundle/Command/AbstractConfigCommand.php +++ /dev/null @@ -1,141 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\StyleInterface; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; - -/** - * A console command for dumping available configuration reference. - * - * @author Kevin Bond - * @author Wouter J - * @author Grégoire Pineau - */ -abstract class AbstractConfigCommand extends ContainerDebugCommand -{ - /** - * @param OutputInterface|StyleInterface $output - */ - protected function listBundles($output) - { - $title = 'Available registered bundles with their extension alias if available'; - $headers = ['Bundle name', 'Extension alias']; - $rows = []; - - $bundles = $this->getApplication()->getKernel()->getBundles(); - usort($bundles, function ($bundleA, $bundleB) { - return strcmp($bundleA->getName(), $bundleB->getName()); - }); - - foreach ($bundles as $bundle) { - $extension = $bundle->getContainerExtension(); - $rows[] = [$bundle->getName(), $extension ? $extension->getAlias() : '']; - } - - if ($output instanceof StyleInterface) { - $output->title($title); - $output->table($headers, $rows); - } else { - $output->writeln($title); - $table = new Table($output); - $table->setHeaders($headers)->setRows($rows)->render(); - } - } - - /** - * @return ExtensionInterface - */ - protected function findExtension(string $name) - { - $bundles = $this->initializeBundles(); - $minScore = INF; - - foreach ($bundles as $bundle) { - if ($name === $bundle->getName()) { - if (!$bundle->getContainerExtension()) { - throw new \LogicException(sprintf('Bundle "%s" does not have a container extension.', $name)); - } - - return $bundle->getContainerExtension(); - } - - $distance = levenshtein($name, $bundle->getName()); - - if ($distance < $minScore) { - $guess = $bundle->getName(); - $minScore = $distance; - } - - $extension = $bundle->getContainerExtension(); - - if ($extension) { - if ($name === $extension->getAlias()) { - return $extension; - } - - $distance = levenshtein($name, $extension->getAlias()); - - if ($distance < $minScore) { - $guess = $extension->getAlias(); - $minScore = $distance; - } - } - } - - if ('Bundle' !== substr($name, -6)) { - $message = sprintf('No extensions with configuration available for "%s".', $name); - } else { - $message = sprintf('No extension with alias "%s" is enabled.', $name); - } - - if (isset($guess) && $minScore < 3) { - $message .= sprintf("\n\nDid you mean \"%s\"?", $guess); - } - - throw new LogicException($message); - } - - public function validateConfiguration(ExtensionInterface $extension, $configuration) - { - if (!$configuration) { - throw new \LogicException(sprintf('The extension with alias "%s" does not have its getConfiguration() method setup', $extension->getAlias())); - } - - if (!$configuration instanceof ConfigurationInterface) { - throw new \LogicException(sprintf('Configuration class "%s" should implement ConfigurationInterface in order to be dumpable', \get_class($configuration))); - } - } - - private function initializeBundles() - { - // Re-build bundle manually to initialize DI extensions that can be extended by other bundles in their build() method - // as this method is not called when the container is loaded from the cache. - $container = $this->getContainerBuilder(); - $bundles = $this->getApplication()->getKernel()->getBundles(); - foreach ($bundles as $bundle) { - if ($extension = $bundle->getContainerExtension()) { - $container->registerExtension($extension); - } - } - - foreach ($bundles as $bundle) { - $bundle->build($container); - } - - return $bundles; - } -} diff --git a/vendor/symfony/framework-bundle/Command/AssetsInstallCommand.php b/vendor/symfony/framework-bundle/Command/AssetsInstallCommand.php deleted file mode 100644 index b02b6a4..0000000 --- a/vendor/symfony/framework-bundle/Command/AssetsInstallCommand.php +++ /dev/null @@ -1,283 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\Filesystem\Exception\IOException; -use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Finder\Finder; -use Symfony\Component\HttpKernel\Bundle\BundleInterface; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * Command that places bundle web assets into a given directory. - * - * @author Fabien Potencier - * @author Gábor Egyed - * - * @final - */ -class AssetsInstallCommand extends Command -{ - const METHOD_COPY = 'copy'; - const METHOD_ABSOLUTE_SYMLINK = 'absolute symlink'; - const METHOD_RELATIVE_SYMLINK = 'relative symlink'; - - protected static $defaultName = 'assets:install'; - - private $filesystem; - private $projectDir; - - public function __construct(Filesystem $filesystem, string $projectDir) - { - parent::__construct(); - - $this->filesystem = $filesystem; - $this->projectDir = $projectDir; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('target', InputArgument::OPTIONAL, 'The target directory', null), - ]) - ->addOption('symlink', null, InputOption::VALUE_NONE, 'Symlinks the assets instead of copying it') - ->addOption('relative', null, InputOption::VALUE_NONE, 'Make relative symlinks') - ->addOption('no-cleanup', null, InputOption::VALUE_NONE, 'Do not remove the assets of the bundles that no longer exist') - ->setDescription('Installs bundles web assets under a public directory') - ->setHelp(<<<'EOT' -The %command.name% command installs bundle assets into a given -directory (e.g. the public directory). - - php %command.full_name% public - -A "bundles" directory will be created inside the target directory and the -"Resources/public" directory of each bundle will be copied into it. - -To create a symlink to each bundle instead of copying its assets, use the ---symlink option (will fall back to hard copies when symbolic links aren't possible: - - php %command.full_name% public --symlink - -To make symlink relative, add the --relative option: - - php %command.full_name% public --symlink --relative - -EOT - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - /** @var KernelInterface $kernel */ - $kernel = $this->getApplication()->getKernel(); - $targetArg = rtrim($input->getArgument('target'), '/'); - - if (!$targetArg) { - $targetArg = $this->getPublicDirectory($kernel->getContainer()); - } - - if (!is_dir($targetArg)) { - $targetArg = $kernel->getProjectDir().'/'.$targetArg; - - if (!is_dir($targetArg)) { - throw new InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target'))); - } - } - - $bundlesDir = $targetArg.'/bundles/'; - - $io = new SymfonyStyle($input, $output); - $io->newLine(); - - if ($input->getOption('relative')) { - $expectedMethod = self::METHOD_RELATIVE_SYMLINK; - $io->text('Trying to install assets as relative symbolic links.'); - } elseif ($input->getOption('symlink')) { - $expectedMethod = self::METHOD_ABSOLUTE_SYMLINK; - $io->text('Trying to install assets as absolute symbolic links.'); - } else { - $expectedMethod = self::METHOD_COPY; - $io->text('Installing assets as hard copies.'); - } - - $io->newLine(); - - $rows = []; - $copyUsed = false; - $exitCode = 0; - $validAssetDirs = []; - /** @var BundleInterface $bundle */ - foreach ($kernel->getBundles() as $bundle) { - if (!is_dir($originDir = $bundle->getPath().'/Resources/public') && !is_dir($originDir = $bundle->getPath().'/public')) { - continue; - } - - $assetDir = preg_replace('/bundle$/', '', strtolower($bundle->getName())); - $targetDir = $bundlesDir.$assetDir; - $validAssetDirs[] = $assetDir; - - if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $message = sprintf("%s\n-> %s", $bundle->getName(), $targetDir); - } else { - $message = $bundle->getName(); - } - - try { - $this->filesystem->remove($targetDir); - - if (self::METHOD_RELATIVE_SYMLINK === $expectedMethod) { - $method = $this->relativeSymlinkWithFallback($originDir, $targetDir); - } elseif (self::METHOD_ABSOLUTE_SYMLINK === $expectedMethod) { - $method = $this->absoluteSymlinkWithFallback($originDir, $targetDir); - } else { - $method = $this->hardCopy($originDir, $targetDir); - } - - if (self::METHOD_COPY === $method) { - $copyUsed = true; - } - - if ($method === $expectedMethod) { - $rows[] = [sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'OK' : "\xE2\x9C\x94" /* HEAVY CHECK MARK (U+2714) */), $message, $method]; - } else { - $rows[] = [sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'WARNING' : '!'), $message, $method]; - } - } catch (\Exception $e) { - $exitCode = 1; - $rows[] = [sprintf('%s', '\\' === \DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */), $message, $e->getMessage()]; - } - } - // remove the assets of the bundles that no longer exist - if (!$input->getOption('no-cleanup') && is_dir($bundlesDir)) { - $dirsToRemove = Finder::create()->depth(0)->directories()->exclude($validAssetDirs)->in($bundlesDir); - $this->filesystem->remove($dirsToRemove); - } - - if ($rows) { - $io->table(['', 'Bundle', 'Method / Error'], $rows); - } - - if (0 !== $exitCode) { - $io->error('Some errors occurred while installing assets.'); - } else { - if ($copyUsed) { - $io->note('Some assets were installed via copy. If you make changes to these assets you have to run this command again.'); - } - $io->success($rows ? 'All assets were successfully installed.' : 'No assets were provided by any bundle.'); - } - - return $exitCode; - } - - /** - * Try to create relative symlink. - * - * Falling back to absolute symlink and finally hard copy. - */ - private function relativeSymlinkWithFallback(string $originDir, string $targetDir): string - { - try { - $this->symlink($originDir, $targetDir, true); - $method = self::METHOD_RELATIVE_SYMLINK; - } catch (IOException $e) { - $method = $this->absoluteSymlinkWithFallback($originDir, $targetDir); - } - - return $method; - } - - /** - * Try to create absolute symlink. - * - * Falling back to hard copy. - */ - private function absoluteSymlinkWithFallback(string $originDir, string $targetDir): string - { - try { - $this->symlink($originDir, $targetDir); - $method = self::METHOD_ABSOLUTE_SYMLINK; - } catch (IOException $e) { - // fall back to copy - $method = $this->hardCopy($originDir, $targetDir); - } - - return $method; - } - - /** - * Creates symbolic link. - * - * @throws IOException if link can not be created - */ - private function symlink(string $originDir, string $targetDir, bool $relative = false) - { - if ($relative) { - $this->filesystem->mkdir(\dirname($targetDir)); - $originDir = $this->filesystem->makePathRelative($originDir, realpath(\dirname($targetDir))); - } - $this->filesystem->symlink($originDir, $targetDir); - if (!file_exists($targetDir)) { - throw new IOException(sprintf('Symbolic link "%s" was created but appears to be broken.', $targetDir), 0, null, $targetDir); - } - } - - /** - * Copies origin to target. - */ - private function hardCopy(string $originDir, string $targetDir): string - { - $this->filesystem->mkdir($targetDir, 0777); - // We use a custom iterator to ignore VCS files - $this->filesystem->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(false)->in($originDir)); - - return self::METHOD_COPY; - } - - private function getPublicDirectory(ContainerInterface $container): string - { - $defaultPublicDir = 'public'; - - if (null === $this->projectDir && !$container->hasParameter('kernel.project_dir')) { - return $defaultPublicDir; - } - - $composerFilePath = ($this->projectDir ?? $container->getParameter('kernel.project_dir')).'/composer.json'; - - if (!file_exists($composerFilePath)) { - return $defaultPublicDir; - } - - $composerConfig = json_decode(file_get_contents($composerFilePath), true); - - if (isset($composerConfig['extra']['public-dir'])) { - return $composerConfig['extra']['public-dir']; - } - - return $defaultPublicDir; - } -} diff --git a/vendor/symfony/framework-bundle/Command/CacheClearCommand.php b/vendor/symfony/framework-bundle/Command/CacheClearCommand.php deleted file mode 100644 index 6711e45..0000000 --- a/vendor/symfony/framework-bundle/Command/CacheClearCommand.php +++ /dev/null @@ -1,209 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\Filesystem\Exception\IOException; -use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Finder\Finder; -use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; -use Symfony\Component\HttpKernel\RebootableInterface; - -/** - * Clear and Warmup the cache. - * - * @author Francis Besset - * @author Fabien Potencier - * - * @final - */ -class CacheClearCommand extends Command -{ - protected static $defaultName = 'cache:clear'; - - private $cacheClearer; - private $filesystem; - - public function __construct(CacheClearerInterface $cacheClearer, Filesystem $filesystem = null) - { - parent::__construct(); - - $this->cacheClearer = $cacheClearer; - $this->filesystem = $filesystem ?: new Filesystem(); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputOption('no-warmup', '', InputOption::VALUE_NONE, 'Do not warm up the cache'), - new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), - ]) - ->setDescription('Clears the cache') - ->setHelp(<<<'EOF' -The %command.name% command clears the application cache for a given environment -and debug mode: - - php %command.full_name% --env=dev - php %command.full_name% --env=prod --no-debug -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $fs = $this->filesystem; - $io = new SymfonyStyle($input, $output); - - $kernel = $this->getApplication()->getKernel(); - $realCacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir'); - // the old cache dir name must not be longer than the real one to avoid exceeding - // the maximum length of a directory or file path within it (esp. Windows MAX_PATH) - $oldCacheDir = substr($realCacheDir, 0, -1).('~' === substr($realCacheDir, -1) ? '+' : '~'); - $fs->remove($oldCacheDir); - - if (!is_writable($realCacheDir)) { - throw new RuntimeException(sprintf('Unable to write in the "%s" directory', $realCacheDir)); - } - - $io->comment(sprintf('Clearing the cache for the %s environment with debug %s', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); - $this->cacheClearer->clear($realCacheDir); - - // The current event dispatcher is stale, let's not use it anymore - $this->getApplication()->setDispatcher(new EventDispatcher()); - - $containerFile = (new \ReflectionObject($kernel->getContainer()))->getFileName(); - $containerDir = basename(\dirname($containerFile)); - - // the warmup cache dir name must have the same length as the real one - // to avoid the many problems in serialized resources files - $warmupDir = substr($realCacheDir, 0, -1).('_' === substr($realCacheDir, -1) ? '-' : '_'); - - if ($output->isVerbose() && $fs->exists($warmupDir)) { - $io->comment('Clearing outdated warmup directory...'); - } - $fs->remove($warmupDir); - - if ($_SERVER['REQUEST_TIME'] <= filemtime($containerFile) && filemtime($containerFile) <= time()) { - if ($output->isVerbose()) { - $io->comment('Cache is fresh.'); - } - if (!$input->getOption('no-warmup') && !$input->getOption('no-optional-warmers')) { - if ($output->isVerbose()) { - $io->comment('Warming up optional cache...'); - } - $warmer = $kernel->getContainer()->get('cache_warmer'); - // non optional warmers already ran during container compilation - $warmer->enableOnlyOptionalWarmers(); - $warmer->warmUp($realCacheDir); - } - } else { - $fs->mkdir($warmupDir); - - if (!$input->getOption('no-warmup')) { - if ($output->isVerbose()) { - $io->comment('Warming up cache...'); - } - $this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers')); - } - - if (!$fs->exists($warmupDir.'/'.$containerDir)) { - $fs->rename($realCacheDir.'/'.$containerDir, $warmupDir.'/'.$containerDir); - touch($warmupDir.'/'.$containerDir.'.legacy'); - } - - if ('/' === \DIRECTORY_SEPARATOR && $mounts = @file('/proc/mounts')) { - foreach ($mounts as $mount) { - $mount = \array_slice(explode(' ', $mount), 1, -3); - if (!\in_array(array_pop($mount), ['vboxsf', 'nfs'])) { - continue; - } - $mount = implode(' ', $mount).'/'; - - if (0 === strpos($realCacheDir, $mount)) { - $io->note('For better performances, you should move the cache and log directories to a non-shared folder of the VM.'); - $oldCacheDir = false; - break; - } - } - } - - if ($oldCacheDir) { - $fs->rename($realCacheDir, $oldCacheDir); - } else { - $fs->remove($realCacheDir); - } - $fs->rename($warmupDir, $realCacheDir); - - if ($output->isVerbose()) { - $io->comment('Removing old cache directory...'); - } - - try { - $fs->remove($oldCacheDir); - } catch (IOException $e) { - if ($output->isVerbose()) { - $io->warning($e->getMessage()); - } - } - } - - if ($output->isVerbose()) { - $io->comment('Finished'); - } - - $io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); - - return 0; - } - - private function warmup(string $warmupDir, string $realCacheDir, bool $enableOptionalWarmers = true) - { - // create a temporary kernel - $kernel = $this->getApplication()->getKernel(); - if (!$kernel instanceof RebootableInterface) { - throw new \LogicException('Calling "cache:clear" with a kernel that does not implement "Symfony\Component\HttpKernel\RebootableInterface" is not supported.'); - } - $kernel->reboot($warmupDir); - - // warmup temporary dir - if ($enableOptionalWarmers) { - $warmer = $kernel->getContainer()->get('cache_warmer'); - // non optional warmers already ran during container compilation - $warmer->enableOnlyOptionalWarmers(); - $warmer->warmUp($warmupDir); - } - - // fix references to cached files with the real cache directory name - $search = [$warmupDir, str_replace('\\', '\\\\', $warmupDir)]; - $replace = str_replace('\\', '/', $realCacheDir); - foreach (Finder::create()->files()->in($warmupDir) as $file) { - $content = str_replace($search, $replace, file_get_contents($file), $count); - if ($count) { - file_put_contents($file, $content); - } - } - } -} diff --git a/vendor/symfony/framework-bundle/Command/CachePoolClearCommand.php b/vendor/symfony/framework-bundle/Command/CachePoolClearCommand.php deleted file mode 100644 index 50aacd9..0000000 --- a/vendor/symfony/framework-bundle/Command/CachePoolClearCommand.php +++ /dev/null @@ -1,105 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; - -/** - * Clear cache pools. - * - * @author Nicolas Grekas - */ -final class CachePoolClearCommand extends Command -{ - protected static $defaultName = 'cache:pool:clear'; - - private $poolClearer; - - public function __construct(Psr6CacheClearer $poolClearer) - { - parent::__construct(); - - $this->poolClearer = $poolClearer; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('pools', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'A list of cache pools or cache pool clearers'), - ]) - ->setDescription('Clears cache pools') - ->setHelp(<<<'EOF' -The %command.name% command clears the given cache pools or cache pool clearers. - - %command.full_name% [...] -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $kernel = $this->getApplication()->getKernel(); - $pools = []; - $clearers = []; - - foreach ($input->getArgument('pools') as $id) { - if ($this->poolClearer->hasPool($id)) { - $pools[$id] = $id; - } else { - $pool = $kernel->getContainer()->get($id); - - if ($pool instanceof CacheItemPoolInterface) { - $pools[$id] = $pool; - } elseif ($pool instanceof Psr6CacheClearer) { - $clearers[$id] = $pool; - } else { - throw new InvalidArgumentException(sprintf('"%s" is not a cache pool nor a cache clearer.', $id)); - } - } - } - - foreach ($clearers as $id => $clearer) { - $io->comment(sprintf('Calling cache clearer: %s', $id)); - $clearer->clear($kernel->getContainer()->getParameter('kernel.cache_dir')); - } - - foreach ($pools as $id => $pool) { - $io->comment(sprintf('Clearing cache pool: %s', $id)); - - if ($pool instanceof CacheItemPoolInterface) { - $pool->clear(); - } else { - $this->poolClearer->clearPool($id); - } - } - - $io->success('Cache was successfully cleared.'); - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/CachePoolDeleteCommand.php b/vendor/symfony/framework-bundle/Command/CachePoolDeleteCommand.php deleted file mode 100644 index 2a7a2fe..0000000 --- a/vendor/symfony/framework-bundle/Command/CachePoolDeleteCommand.php +++ /dev/null @@ -1,83 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; - -/** - * Delete an item from a cache pool. - * - * @author Pierre du Plessis - */ -final class CachePoolDeleteCommand extends Command -{ - protected static $defaultName = 'cache:pool:delete'; - - private $poolClearer; - - public function __construct(Psr6CacheClearer $poolClearer) - { - parent::__construct(); - - $this->poolClearer = $poolClearer; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('pool', InputArgument::REQUIRED, 'The cache pool from which to delete an item'), - new InputArgument('key', InputArgument::REQUIRED, 'The cache key to delete from the pool'), - ]) - ->setDescription('Deletes an item from a cache pool') - ->setHelp(<<<'EOF' -The %command.name% deletes an item from a given cache pool. - - %command.full_name% -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $pool = $input->getArgument('pool'); - $key = $input->getArgument('key'); - $cachePool = $this->poolClearer->getPool($pool); - - if (!$cachePool->hasItem($key)) { - $io->note(sprintf('Cache item "%s" does not exist in cache pool "%s".', $key, $pool)); - - return 0; - } - - if (!$cachePool->deleteItem($key)) { - throw new \Exception(sprintf('Cache item "%s" could not be deleted.', $key)); - } - - $io->success(sprintf('Cache item "%s" was successfully deleted.', $key)); - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/CachePoolListCommand.php b/vendor/symfony/framework-bundle/Command/CachePoolListCommand.php deleted file mode 100644 index 7b72541..0000000 --- a/vendor/symfony/framework-bundle/Command/CachePoolListCommand.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * List available cache pools. - * - * @author Tobias Nyholm - */ -final class CachePoolListCommand extends Command -{ - protected static $defaultName = 'cache:pool:list'; - - private $poolNames; - - public function __construct(array $poolNames) - { - parent::__construct(); - - $this->poolNames = $poolNames; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription('List available cache pools') - ->setHelp(<<<'EOF' -The %command.name% command lists all available cache pools. -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - $io->table(['Pool name'], array_map(function ($pool) { - return [$pool]; - }, $this->poolNames)); - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/CachePoolPruneCommand.php b/vendor/symfony/framework-bundle/Command/CachePoolPruneCommand.php deleted file mode 100644 index 65f3ff6..0000000 --- a/vendor/symfony/framework-bundle/Command/CachePoolPruneCommand.php +++ /dev/null @@ -1,73 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Cache\PruneableInterface; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Cache pool pruner command. - * - * @author Rob Frawley 2nd - */ -final class CachePoolPruneCommand extends Command -{ - protected static $defaultName = 'cache:pool:prune'; - - private $pools; - - /** - * @param iterable|PruneableInterface[] $pools - */ - public function __construct(iterable $pools) - { - parent::__construct(); - - $this->pools = $pools; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription('Prunes cache pools') - ->setHelp(<<<'EOF' -The %command.name% command deletes all expired items from all pruneable pools. - - %command.full_name% -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - foreach ($this->pools as $name => $pool) { - $io->comment(sprintf('Pruning cache pool: %s', $name)); - $pool->prune(); - } - - $io->success('Successfully pruned cache pool(s).'); - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/CacheWarmupCommand.php b/vendor/symfony/framework-bundle/Command/CacheWarmupCommand.php deleted file mode 100644 index 0a87acf..0000000 --- a/vendor/symfony/framework-bundle/Command/CacheWarmupCommand.php +++ /dev/null @@ -1,86 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate; - -/** - * Warmup the cache. - * - * @author Fabien Potencier - * - * @final - */ -class CacheWarmupCommand extends Command -{ - protected static $defaultName = 'cache:warmup'; - - private $cacheWarmer; - - public function __construct(CacheWarmerAggregate $cacheWarmer) - { - parent::__construct(); - - $this->cacheWarmer = $cacheWarmer; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), - ]) - ->setDescription('Warms up an empty cache') - ->setHelp(<<<'EOF' -The %command.name% command warms up the cache. - -Before running this command, the cache must be empty. - -This command does not generate the classes cache (as when executing this -command, too many classes that should be part of the cache are already loaded -in memory). Use curl or any other similar tool to warm up -the classes cache if you want. - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - $kernel = $this->getApplication()->getKernel(); - $io->comment(sprintf('Warming up the cache for the %s environment with debug %s', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); - - if (!$input->getOption('no-optional-warmers')) { - $this->cacheWarmer->enableOptionalWarmers(); - } - - $this->cacheWarmer->warmUp($kernel->getContainer()->getParameter('kernel.cache_dir')); - - $io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully warmed.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/ConfigDebugCommand.php b/vendor/symfony/framework-bundle/Command/ConfigDebugCommand.php deleted file mode 100644 index 2aa631e..0000000 --- a/vendor/symfony/framework-bundle/Command/ConfigDebugCommand.php +++ /dev/null @@ -1,156 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\Compiler\ValidateEnvPlaceholdersPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\Yaml\Yaml; - -/** - * A console command for dumping available configuration reference. - * - * @author Grégoire Pineau - * - * @final - */ -class ConfigDebugCommand extends AbstractConfigCommand -{ - protected static $defaultName = 'debug:config'; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('name', InputArgument::OPTIONAL, 'The bundle name or the extension alias'), - new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), - ]) - ->setDescription('Dumps the current configuration for an extension') - ->setHelp(<<<'EOF' -The %command.name% command dumps the current configuration for an -extension/bundle. - -Either the extension alias or bundle name can be used: - - php %command.full_name% framework - php %command.full_name% FrameworkBundle - -For dumping a specific option, add its path as second argument: - - php %command.full_name% framework serializer.enabled - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $errorIo = $io->getErrorStyle(); - - if (null === $name = $input->getArgument('name')) { - $this->listBundles($errorIo); - $errorIo->comment('Provide the name of a bundle as the first argument of this command to dump its configuration. (e.g. debug:config FrameworkBundle)'); - $errorIo->comment('For dumping a specific option, add its path as the second argument of this command. (e.g. debug:config FrameworkBundle serializer to dump the framework.serializer configuration)'); - - return 0; - } - - $extension = $this->findExtension($name); - $container = $this->compileContainer(); - - $extensionAlias = $extension->getAlias(); - $extensionConfig = []; - foreach ($container->getCompilerPassConfig()->getPasses() as $pass) { - if ($pass instanceof ValidateEnvPlaceholdersPass) { - $extensionConfig = $pass->getExtensionConfig(); - break; - } - } - - if (!isset($extensionConfig[$extensionAlias])) { - throw new \LogicException(sprintf('The extension with alias "%s" does not have configuration.', $extensionAlias)); - } - - $config = $container->resolveEnvPlaceholders($extensionConfig[$extensionAlias]); - - if (null === $path = $input->getArgument('path')) { - $io->title( - sprintf('Current configuration for %s', ($name === $extensionAlias ? sprintf('extension with alias "%s"', $extensionAlias) : sprintf('"%s"', $name))) - ); - - $io->writeln(Yaml::dump([$extensionAlias => $config], 10)); - - return 0; - } - - try { - $config = $this->getConfigForPath($config, $path, $extensionAlias); - } catch (LogicException $e) { - $errorIo->error($e->getMessage()); - - return 1; - } - - $io->title(sprintf('Current configuration for "%s.%s"', $extensionAlias, $path)); - - $io->writeln(Yaml::dump($config, 10)); - - return 0; - } - - private function compileContainer(): ContainerBuilder - { - $kernel = clone $this->getApplication()->getKernel(); - $kernel->boot(); - - $method = new \ReflectionMethod($kernel, 'buildContainer'); - $method->setAccessible(true); - $container = $method->invoke($kernel); - $container->getCompiler()->compile($container); - - return $container; - } - - /** - * Iterate over configuration until the last step of the given path. - * - * @throws LogicException If the configuration does not exist - * - * @return mixed - */ - private function getConfigForPath(array $config, string $path, string $alias) - { - $steps = explode('.', $path); - - foreach ($steps as $step) { - if (!\array_key_exists($step, $config)) { - throw new LogicException(sprintf('Unable to find configuration for "%s.%s"', $alias, $path)); - } - - $config = $config[$step]; - } - - return $config; - } -} diff --git a/vendor/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php b/vendor/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php deleted file mode 100644 index 60445e4..0000000 --- a/vendor/symfony/framework-bundle/Command/ConfigDumpReferenceCommand.php +++ /dev/null @@ -1,135 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Config\Definition\Dumper\XmlReferenceDumper; -use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * A console command for dumping available configuration reference. - * - * @author Kevin Bond - * @author Wouter J - * @author Grégoire Pineau - * - * @final - */ -class ConfigDumpReferenceCommand extends AbstractConfigCommand -{ - protected static $defaultName = 'config:dump-reference'; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('name', InputArgument::OPTIONAL, 'The Bundle name or the extension alias'), - new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (yaml or xml)', 'yaml'), - ]) - ->setDescription('Dumps the default configuration for an extension') - ->setHelp(<<<'EOF' -The %command.name% command dumps the default configuration for an -extension/bundle. - -Either the extension alias or bundle name can be used: - - php %command.full_name% framework - php %command.full_name% FrameworkBundle - -With the --format option specifies the format of the configuration, -this is either yaml or xml. -When the option is not provided, yaml is used. - - php %command.full_name% FrameworkBundle --format=xml - -For dumping a specific option, add its path as second argument (only available for the yaml format): - - php %command.full_name% framework profiler.matcher - -EOF - ) - ; - } - - /** - * {@inheritdoc} - * - * @throws \LogicException - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $errorIo = $io->getErrorStyle(); - - if (null === $name = $input->getArgument('name')) { - $this->listBundles($errorIo); - $errorIo->comment([ - 'Provide the name of a bundle as the first argument of this command to dump its default configuration. (e.g. config:dump-reference FrameworkBundle)', - 'For dumping a specific option, add its path as the second argument of this command. (e.g. config:dump-reference FrameworkBundle profiler.matcher to dump the framework.profiler.matcher configuration)', - ]); - - return 0; - } - - $extension = $this->findExtension($name); - - $configuration = $extension->getConfiguration([], $this->getContainerBuilder()); - - $this->validateConfiguration($extension, $configuration); - - $format = $input->getOption('format'); - $path = $input->getArgument('path'); - - if (null !== $path && 'yaml' !== $format) { - $errorIo->error('The "path" option is only available for the "yaml" format.'); - - return 1; - } - - if ($name === $extension->getAlias()) { - $message = sprintf('Default configuration for extension with alias: "%s"', $name); - } else { - $message = sprintf('Default configuration for "%s"', $name); - } - - if (null !== $path) { - $message .= sprintf(' at path "%s"', $path); - } - - switch ($format) { - case 'yaml': - $io->writeln(sprintf('# %s', $message)); - $dumper = new YamlReferenceDumper(); - break; - case 'xml': - $io->writeln(sprintf('', $message)); - $dumper = new XmlReferenceDumper(); - break; - default: - $io->writeln($message); - throw new InvalidArgumentException('Only the yaml and xml formats are supported.'); - } - - $io->writeln(null === $path ? $dumper->dump($configuration, $extension->getNamespace()) : $dumper->dumpAtPath($configuration, $path)); - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/ContainerDebugCommand.php b/vendor/symfony/framework-bundle/Command/ContainerDebugCommand.php deleted file mode 100644 index 4440ed0..0000000 --- a/vendor/symfony/framework-bundle/Command/ContainerDebugCommand.php +++ /dev/null @@ -1,295 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; -use Symfony\Component\Config\ConfigCache; -use Symfony\Component\Config\FileLocator; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; - -/** - * A console command for retrieving information about services. - * - * @author Ryan Weaver - * - * @internal - */ -class ContainerDebugCommand extends Command -{ - protected static $defaultName = 'debug:container'; - - /** - * @var ContainerBuilder|null - */ - protected $containerBuilder; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('name', InputArgument::OPTIONAL, 'A service name (foo)'), - new InputOption('show-arguments', null, InputOption::VALUE_NONE, 'Used to show arguments in services'), - new InputOption('show-hidden', null, InputOption::VALUE_NONE, 'Used to show hidden (internal) services'), - new InputOption('tag', null, InputOption::VALUE_REQUIRED, 'Shows all services with a specific tag'), - new InputOption('tags', null, InputOption::VALUE_NONE, 'Displays tagged services for an application'), - new InputOption('parameter', null, InputOption::VALUE_REQUIRED, 'Displays a specific parameter for an application'), - new InputOption('parameters', null, InputOption::VALUE_NONE, 'Displays parameters for an application'), - new InputOption('types', null, InputOption::VALUE_NONE, 'Displays types (classes/interfaces) available in the container'), - new InputOption('env-var', null, InputOption::VALUE_REQUIRED, 'Displays a specific environment variable used in the container'), - new InputOption('env-vars', null, InputOption::VALUE_NONE, 'Displays environment variables used in the container'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), - new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'), - ]) - ->setDescription('Displays current services for an application') - ->setHelp(<<<'EOF' -The %command.name% command displays all configured public services: - - php %command.full_name% - -To get specific information about a service, specify its name: - - php %command.full_name% validator - -To see available types that can be used for autowiring, use the --types flag: - - php %command.full_name% --types - -To see environment variables used by the container, use the --env-vars flag: - - php %command.full_name% --env-vars - -Display a specific environment variable by specifying its name with the --env-var option: - - php %command.full_name% --env-var=APP_ENV - -Use the --tags option to display tagged public services grouped by tag: - - php %command.full_name% --tags - -Find all services with a specific tag by specifying the tag name with the --tag option: - - php %command.full_name% --tag=form.type - -Use the --parameters option to display all parameters: - - php %command.full_name% --parameters - -Display a specific parameter by specifying its name with the --parameter option: - - php %command.full_name% --parameter=kernel.debug - -By default, internal services are hidden. You can display them -using the --show-hidden flag: - - php %command.full_name% --show-hidden - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $errorIo = $io->getErrorStyle(); - - $this->validateInput($input); - $object = $this->getContainerBuilder(); - - if ($input->getOption('env-vars')) { - $options = ['env-vars' => true]; - } elseif ($envVar = $input->getOption('env-var')) { - $options = ['env-vars' => true, 'name' => $envVar]; - } elseif ($input->getOption('types')) { - $options = []; - $options['filter'] = [$this, 'filterToServiceTypes']; - } elseif ($input->getOption('parameters')) { - $parameters = []; - foreach ($object->getParameterBag()->all() as $k => $v) { - $parameters[$k] = $object->resolveEnvPlaceholders($v); - } - $object = new ParameterBag($parameters); - $options = []; - } elseif ($parameter = $input->getOption('parameter')) { - $options = ['parameter' => $parameter]; - } elseif ($input->getOption('tags')) { - $options = ['group_by' => 'tags']; - } elseif ($tag = $input->getOption('tag')) { - $options = ['tag' => $tag]; - } elseif ($name = $input->getArgument('name')) { - $name = $this->findProperServiceName($input, $errorIo, $object, $name, $input->getOption('show-hidden')); - $options = ['id' => $name]; - } else { - $options = []; - } - - $helper = new DescriptorHelper(); - $options['format'] = $input->getOption('format'); - $options['show_arguments'] = $input->getOption('show-arguments'); - $options['show_hidden'] = $input->getOption('show-hidden'); - $options['raw_text'] = $input->getOption('raw'); - $options['output'] = $io; - $options['is_debug'] = $this->getApplication()->getKernel()->isDebug(); - - try { - $helper->describe($io, $object, $options); - - if (isset($options['id']) && isset($this->getApplication()->getKernel()->getContainer()->getRemovedIds()[$options['id']])) { - $errorIo->note(sprintf('The "%s" service or alias has been removed or inlined when the container was compiled.', $options['id'])); - } - } catch (ServiceNotFoundException $e) { - if ('' !== $e->getId() && '@' === $e->getId()[0]) { - throw new ServiceNotFoundException($e->getId(), $e->getSourceId(), null, [substr($e->getId(), 1)]); - } - - throw $e; - } - - if (!$input->getArgument('name') && !$input->getOption('tag') && !$input->getOption('parameter') && !$input->getOption('env-vars') && !$input->getOption('env-var') && $input->isInteractive()) { - if ($input->getOption('tags')) { - $errorIo->comment('To search for a specific tag, re-run this command with a search term. (e.g. debug:container --tag=form.type)'); - } elseif ($input->getOption('parameters')) { - $errorIo->comment('To search for a specific parameter, re-run this command with a search term. (e.g. debug:container --parameter=kernel.debug)'); - } else { - $errorIo->comment('To search for a specific service, re-run this command with a search term. (e.g. debug:container log)'); - } - } - - return 0; - } - - /** - * Validates input arguments and options. - * - * @throws \InvalidArgumentException - */ - protected function validateInput(InputInterface $input) - { - $options = ['tags', 'tag', 'parameters', 'parameter']; - - $optionsCount = 0; - foreach ($options as $option) { - if ($input->getOption($option)) { - ++$optionsCount; - } - } - - $name = $input->getArgument('name'); - if ((null !== $name) && ($optionsCount > 0)) { - throw new InvalidArgumentException('The options tags, tag, parameters & parameter can not be combined with the service name argument.'); - } elseif ((null === $name) && $optionsCount > 1) { - throw new InvalidArgumentException('The options tags, tag, parameters & parameter can not be combined together.'); - } - } - - /** - * Loads the ContainerBuilder from the cache. - * - * @throws \LogicException - */ - protected function getContainerBuilder(): ContainerBuilder - { - if ($this->containerBuilder) { - return $this->containerBuilder; - } - - $kernel = $this->getApplication()->getKernel(); - - if (!$kernel->isDebug() || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), true))->isFresh()) { - $buildContainer = \Closure::bind(function () { return $this->buildContainer(); }, $kernel, \get_class($kernel)); - $container = $buildContainer(); - $container->getCompilerPassConfig()->setRemovingPasses([]); - $container->getCompilerPassConfig()->setAfterRemovingPasses([]); - $container->compile(); - } else { - (new XmlFileLoader($container = new ContainerBuilder(), new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump')); - $locatorPass = new ServiceLocatorTagPass(); - $locatorPass->process($container); - } - - return $this->containerBuilder = $container; - } - - private function findProperServiceName(InputInterface $input, SymfonyStyle $io, ContainerBuilder $builder, string $name, bool $showHidden): string - { - $name = ltrim($name, '\\'); - - if ($builder->has($name) || !$input->isInteractive()) { - return $name; - } - - $matchingServices = $this->findServiceIdsContaining($builder, $name, $showHidden); - if (empty($matchingServices)) { - throw new InvalidArgumentException(sprintf('No services found that match "%s".', $name)); - } - - if (1 === \count($matchingServices)) { - return $matchingServices[0]; - } - - return $io->choice('Select one of the following services to display its information', $matchingServices); - } - - private function findServiceIdsContaining(ContainerBuilder $builder, string $name, bool $showHidden): array - { - $serviceIds = $builder->getServiceIds(); - $foundServiceIds = $foundServiceIdsIgnoringBackslashes = []; - foreach ($serviceIds as $serviceId) { - if (!$showHidden && 0 === strpos($serviceId, '.')) { - continue; - } - if (false !== stripos(str_replace('\\', '', $serviceId), $name)) { - $foundServiceIdsIgnoringBackslashes[] = $serviceId; - } - if (false !== stripos($serviceId, $name)) { - $foundServiceIds[] = $serviceId; - } - } - - return $foundServiceIds ?: $foundServiceIdsIgnoringBackslashes; - } - - /** - * @internal - */ - public function filterToServiceTypes(string $serviceId): bool - { - // filter out things that could not be valid class names - if (!preg_match('/(?(DEFINE)(?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^(?&V)(?:\\\\(?&V))*+(?: \$(?&V))?$/', $serviceId)) { - return false; - } - - // if the id has a \, assume it is a class - if (false !== strpos($serviceId, '\\')) { - return true; - } - - return class_exists($serviceId) || interface_exists($serviceId, false); - } -} diff --git a/vendor/symfony/framework-bundle/Command/ContainerLintCommand.php b/vendor/symfony/framework-bundle/Command/ContainerLintCommand.php deleted file mode 100644 index 5e62775..0000000 --- a/vendor/symfony/framework-bundle/Command/ContainerLintCommand.php +++ /dev/null @@ -1,119 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Config\ConfigCache; -use Symfony\Component\Config\FileLocator; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass; -use Symfony\Component\DependencyInjection\Compiler\PassConfig; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; -use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; -use Symfony\Component\HttpKernel\Kernel; - -final class ContainerLintCommand extends Command -{ - protected static $defaultName = 'lint:container'; - - /** - * @var ContainerBuilder - */ - private $containerBuilder; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription('Ensures that arguments injected into services match type declarations') - ->setHelp('This command parses service definitions and ensures that injected values match the type declarations of each services\' class.') - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $errorIo = $io->getErrorStyle(); - - try { - $container = $this->getContainerBuilder(); - } catch (RuntimeException $e) { - $errorIo->error($e->getMessage()); - - return 2; - } - - $container->setParameter('container.build_time', time()); - - $container->compile(); - - return 0; - } - - private function getContainerBuilder(): ContainerBuilder - { - if ($this->containerBuilder) { - return $this->containerBuilder; - } - - $kernel = $this->getApplication()->getKernel(); - $kernelContainer = $kernel->getContainer(); - - if (!$kernel->isDebug() || !(new ConfigCache($kernelContainer->getParameter('debug.container.dump'), true))->isFresh()) { - if (!$kernel instanceof Kernel) { - throw new RuntimeException(sprintf('This command does not support the application kernel: "%s" does not extend "%s".', \get_class($kernel), Kernel::class)); - } - - $buildContainer = \Closure::bind(function (): ContainerBuilder { - $this->initializeBundles(); - - return $this->buildContainer(); - }, $kernel, \get_class($kernel)); - $container = $buildContainer(); - - $skippedIds = []; - } else { - if (!$kernelContainer instanceof Container) { - throw new RuntimeException(sprintf('This command does not support the application container: "%s" does not extend "%s".', \get_class($kernelContainer), Container::class)); - } - - (new XmlFileLoader($container = new ContainerBuilder($parameterBag = new EnvPlaceholderParameterBag()), new FileLocator()))->load($kernelContainer->getParameter('debug.container.dump')); - - $refl = new \ReflectionProperty($parameterBag, 'resolved'); - $refl->setAccessible(true); - $refl->setValue($parameterBag, true); - - $passConfig = $container->getCompilerPassConfig(); - $passConfig->setRemovingPasses([]); - $passConfig->setAfterRemovingPasses([]); - - $skippedIds = $kernelContainer->getRemovedIds(); - } - - $container->setParameter('container.build_hash', 'lint_container'); - $container->setParameter('container.build_id', 'lint_container'); - - $container->addCompilerPass(new CheckTypeDeclarationsPass(true, $skippedIds), PassConfig::TYPE_AFTER_REMOVING, -100); - - return $this->containerBuilder = $container; - } -} diff --git a/vendor/symfony/framework-bundle/Command/DebugAutowiringCommand.php b/vendor/symfony/framework-bundle/Command/DebugAutowiringCommand.php deleted file mode 100644 index 04d391d..0000000 --- a/vendor/symfony/framework-bundle/Command/DebugAutowiringCommand.php +++ /dev/null @@ -1,161 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Console\Descriptor\Descriptor; -use Symfony\Component\Console\Formatter\OutputFormatterStyle; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; - -/** - * A console command for autowiring information. - * - * @author Ryan Weaver - * - * @internal - */ -class DebugAutowiringCommand extends ContainerDebugCommand -{ - protected static $defaultName = 'debug:autowiring'; - private $supportsHref; - private $fileLinkFormatter; - - public function __construct(string $name = null, FileLinkFormatter $fileLinkFormatter = null) - { - $this->supportsHref = method_exists(OutputFormatterStyle::class, 'setHref'); - $this->fileLinkFormatter = $fileLinkFormatter; - parent::__construct($name); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('search', InputArgument::OPTIONAL, 'A search filter'), - new InputOption('all', null, InputOption::VALUE_NONE, 'Show also services that are not aliased'), - ]) - ->setDescription('Lists classes/interfaces you can use for autowiring') - ->setHelp(<<<'EOF' -The %command.name% command displays the classes and interfaces that -you can use as type-hints for autowiring: - - php %command.full_name% - -You can also pass a search term to filter the list: - - php %command.full_name% log - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $errorIo = $io->getErrorStyle(); - - $builder = $this->getContainerBuilder(); - $serviceIds = $builder->getServiceIds(); - $serviceIds = array_filter($serviceIds, [$this, 'filterToServiceTypes']); - - if ($search = $input->getArgument('search')) { - $serviceIds = array_filter($serviceIds, function ($serviceId) use ($search) { - return false !== stripos(str_replace('\\', '', $serviceId), $search) && 0 !== strpos($serviceId, '.'); - }); - - if (empty($serviceIds)) { - $errorIo->error(sprintf('No autowirable classes or interfaces found matching "%s"', $search)); - - return 1; - } - } - - uasort($serviceIds, 'strnatcmp'); - - $io->title('Autowirable Types'); - $io->text('The following classes & interfaces can be used as type-hints when autowiring:'); - if ($search) { - $io->text(sprintf('(only showing classes/interfaces matching %s)', $search)); - } - $hasAlias = []; - $all = $input->getOption('all'); - $previousId = '-'; - $serviceIdsNb = 0; - foreach ($serviceIds as $serviceId) { - $text = []; - if (0 !== strpos($serviceId, $previousId)) { - $text[] = ''; - if ('' !== $description = Descriptor::getClassDescription($serviceId, $serviceId)) { - if (isset($hasAlias[$serviceId])) { - continue; - } - $text[] = $description; - } - $previousId = $serviceId.' $'; - } - - $serviceLine = sprintf('%s', $serviceId); - if ($this->supportsHref && '' !== $fileLink = $this->getFileLink($serviceId)) { - $serviceLine = sprintf('%s', $fileLink, $serviceId); - } - - if ($builder->hasAlias($serviceId)) { - $hasAlias[$serviceId] = true; - $serviceAlias = $builder->getAlias($serviceId); - $serviceLine .= ' ('.$serviceAlias.')'; - - if ($serviceAlias->isDeprecated()) { - $serviceLine .= ' - deprecated'; - } - } elseif (!$all) { - ++$serviceIdsNb; - continue; - } - $text[] = $serviceLine; - $io->text($text); - } - - $io->newLine(); - - if (0 < $serviceIdsNb) { - $io->text(sprintf('%s more concrete service%s would be displayed when adding the "--all" option.', $serviceIdsNb, $serviceIdsNb > 1 ? 's' : '')); - } - if ($all) { - $io->text('Pro-tip: use interfaces in your type-hints instead of classes to benefit from the dependency inversion principle.'); - } - - $io->newLine(); - - return 0; - } - - private function getFileLink(string $class): string - { - if (null === $this->fileLinkFormatter - || (null === $r = $this->getContainerBuilder()->getReflectionClass($class, false))) { - return ''; - } - - return (string) $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine()); - } -} diff --git a/vendor/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php b/vendor/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php deleted file mode 100644 index ad49cde..0000000 --- a/vendor/symfony/framework-bundle/Command/EventDispatcherDebugCommand.php +++ /dev/null @@ -1,95 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; - -/** - * A console command for retrieving information about event dispatcher. - * - * @author Matthieu Auger - * - * @final - */ -class EventDispatcherDebugCommand extends Command -{ - protected static $defaultName = 'debug:event-dispatcher'; - private $dispatcher; - - public function __construct(EventDispatcherInterface $dispatcher) - { - parent::__construct(); - - $this->dispatcher = $dispatcher; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('event', InputArgument::OPTIONAL, 'An event name'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), - new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'), - ]) - ->setDescription('Displays configured listeners for an application') - ->setHelp(<<<'EOF' -The %command.name% command displays all configured listeners: - - php %command.full_name% - -To get specific listeners for an event, specify its name: - - php %command.full_name% kernel.request -EOF - ) - ; - } - - /** - * {@inheritdoc} - * - * @throws \LogicException - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - $options = []; - if ($event = $input->getArgument('event')) { - if (!$this->dispatcher->hasListeners($event)) { - $io->getErrorStyle()->warning(sprintf('The event "%s" does not have any registered listeners.', $event)); - - return 0; - } - - $options = ['event' => $event]; - } - - $helper = new DescriptorHelper(); - $options['format'] = $input->getOption('format'); - $options['raw_text'] = $input->getOption('raw'); - $options['output'] = $io; - $helper->describe($io, $this->dispatcher, $options); - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/RouterDebugCommand.php b/vendor/symfony/framework-bundle/Command/RouterDebugCommand.php deleted file mode 100644 index 9724e51..0000000 --- a/vendor/symfony/framework-bundle/Command/RouterDebugCommand.php +++ /dev/null @@ -1,123 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RouterInterface; - -/** - * A console command for retrieving information about routes. - * - * @author Fabien Potencier - * @author Tobias Schultze - * - * @final - */ -class RouterDebugCommand extends Command -{ - protected static $defaultName = 'debug:router'; - private $router; - private $fileLinkFormatter; - - public function __construct(RouterInterface $router, FileLinkFormatter $fileLinkFormatter = null) - { - parent::__construct(); - - $this->router = $router; - $this->fileLinkFormatter = $fileLinkFormatter; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('name', InputArgument::OPTIONAL, 'A route name'), - new InputOption('show-controllers', null, InputOption::VALUE_NONE, 'Show assigned controllers in overview'), - new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), - new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw route(s)'), - ]) - ->setDescription('Displays current routes for an application') - ->setHelp(<<<'EOF' -The %command.name% displays the configured routes: - - php %command.full_name% - -EOF - ) - ; - } - - /** - * {@inheritdoc} - * - * @throws InvalidArgumentException When route does not exist - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $name = $input->getArgument('name'); - $helper = new DescriptorHelper($this->fileLinkFormatter); - $routes = $this->router->getRouteCollection(); - - if ($name) { - if (!($route = $routes->get($name)) && $matchingRoutes = $this->findRouteNameContaining($name, $routes)) { - $default = 1 === \count($matchingRoutes) ? $matchingRoutes[0] : null; - $name = $io->choice('Select one of the matching routes', $matchingRoutes, $default); - $route = $routes->get($name); - } - - if (!$route) { - throw new InvalidArgumentException(sprintf('The route "%s" does not exist.', $name)); - } - - $helper->describe($io, $route, [ - 'format' => $input->getOption('format'), - 'raw_text' => $input->getOption('raw'), - 'name' => $name, - 'output' => $io, - ]); - } else { - $helper->describe($io, $routes, [ - 'format' => $input->getOption('format'), - 'raw_text' => $input->getOption('raw'), - 'show_controllers' => $input->getOption('show-controllers'), - 'output' => $io, - ]); - } - - return 0; - } - - private function findRouteNameContaining(string $name, RouteCollection $routes): array - { - $foundRoutesNames = []; - foreach ($routes as $routeName => $route) { - if (false !== stripos($routeName, $name)) { - $foundRoutesNames[] = $routeName; - } - } - - return $foundRoutesNames; - } -} diff --git a/vendor/symfony/framework-bundle/Command/RouterMatchCommand.php b/vendor/symfony/framework-bundle/Command/RouterMatchCommand.php deleted file mode 100644 index 454767e..0000000 --- a/vendor/symfony/framework-bundle/Command/RouterMatchCommand.php +++ /dev/null @@ -1,119 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Routing\Matcher\TraceableUrlMatcher; -use Symfony\Component\Routing\RouterInterface; - -/** - * A console command to test route matching. - * - * @author Fabien Potencier - * - * @final - */ -class RouterMatchCommand extends Command -{ - protected static $defaultName = 'router:match'; - - private $router; - - public function __construct(RouterInterface $router) - { - parent::__construct(); - - $this->router = $router; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('path_info', InputArgument::REQUIRED, 'A path info'), - new InputOption('method', null, InputOption::VALUE_REQUIRED, 'Sets the HTTP method'), - new InputOption('scheme', null, InputOption::VALUE_REQUIRED, 'Sets the URI scheme (usually http or https)'), - new InputOption('host', null, InputOption::VALUE_REQUIRED, 'Sets the URI host'), - ]) - ->setDescription('Helps debug routes by simulating a path info match') - ->setHelp(<<<'EOF' -The %command.name% shows which routes match a given request and which don't and for what reason: - - php %command.full_name% /foo - -or - - php %command.full_name% /foo --method POST --scheme https --host symfony.com --verbose - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - $context = $this->router->getContext(); - if (null !== $method = $input->getOption('method')) { - $context->setMethod($method); - } - if (null !== $scheme = $input->getOption('scheme')) { - $context->setScheme($scheme); - } - if (null !== $host = $input->getOption('host')) { - $context->setHost($host); - } - - $matcher = new TraceableUrlMatcher($this->router->getRouteCollection(), $context); - - $traces = $matcher->getTraces($input->getArgument('path_info')); - - $io->newLine(); - - $matches = false; - foreach ($traces as $trace) { - if (TraceableUrlMatcher::ROUTE_ALMOST_MATCHES == $trace['level']) { - $io->text(sprintf('Route "%s" almost matches but %s', $trace['name'], lcfirst($trace['log']))); - } elseif (TraceableUrlMatcher::ROUTE_MATCHES == $trace['level']) { - $io->success(sprintf('Route "%s" matches', $trace['name'])); - - $routerDebugCommand = $this->getApplication()->find('debug:router'); - $routerDebugCommand->run(new ArrayInput(['name' => $trace['name']]), $output); - - $matches = true; - } elseif ($input->getOption('verbose')) { - $io->text(sprintf('Route "%s" does not match: %s', $trace['name'], $trace['log'])); - } - } - - if (!$matches) { - $io->error(sprintf('None of the routes match the path "%s"', $input->getArgument('path_info'))); - - return 1; - } - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php b/vendor/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php deleted file mode 100644 index e4fbfd2..0000000 --- a/vendor/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php +++ /dev/null @@ -1,90 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * @author Nicolas Grekas - * - * @internal - */ -final class SecretsDecryptToLocalCommand extends Command -{ - protected static $defaultName = 'secrets:decrypt-to-local'; - - private $vault; - private $localVault; - - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - - parent::__construct(); - } - - protected function configure() - { - $this - ->setDescription('Decrypts all secrets and stores them in the local vault.') - ->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces overriding of secrets that already exist in the local vault') - ->setHelp(<<<'EOF' -The %command.name% command decrypts all secrets and copies them in the local vault. - - %command.full_name% - -When the option --force is provided, secrets that already exist in the local vault are overriden. - - %command.full_name% --force -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); - - if (null === $this->localVault) { - $io->error('The local vault is disabled.'); - - return 1; - } - - $secrets = $this->vault->list(true); - - if (!$input->getOption('force')) { - foreach ($this->localVault->list() as $k => $v) { - unset($secrets[$k]); - } - } - - foreach ($secrets as $k => $v) { - if (null === $v) { - $io->error($this->vault->getLastMessage()); - - return 1; - } - - $this->localVault->seal($k, $v); - } - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php b/vendor/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php deleted file mode 100644 index 607140e..0000000 --- a/vendor/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php +++ /dev/null @@ -1,78 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * @author Nicolas Grekas - * - * @internal - */ -final class SecretsEncryptFromLocalCommand extends Command -{ - protected static $defaultName = 'secrets:encrypt-from-local'; - - private $vault; - private $localVault; - - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - - parent::__construct(); - } - - protected function configure() - { - $this - ->setDescription('Encrypts all local secrets to the vault.') - ->setHelp(<<<'EOF' -The %command.name% command encrypts all locally overridden secrets to the vault. - - %command.full_name% -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); - - if (null === $this->localVault) { - $io->error('The local vault is disabled.'); - - return 1; - } - - foreach ($this->vault->list(true) as $name => $value) { - $localValue = $this->localVault->reveal($name); - - if (null !== $localValue && $value !== $localValue) { - $this->vault->seal($name, $localValue); - } elseif (null !== $message = $this->localVault->getLastMessage()) { - $io->error($message); - - return 1; - } - } - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php b/vendor/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php deleted file mode 100644 index f56fd0f..0000000 --- a/vendor/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php +++ /dev/null @@ -1,125 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * @author Tobias Schultze - * @author Jérémy Derussé - * @author Nicolas Grekas - * - * @internal - */ -final class SecretsGenerateKeysCommand extends Command -{ - protected static $defaultName = 'secrets:generate-keys'; - - private $vault; - private $localVault; - - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - - parent::__construct(); - } - - protected function configure() - { - $this - ->setDescription('Generates new encryption keys.') - ->addOption('local', 'l', InputOption::VALUE_NONE, 'Updates the local vault.') - ->addOption('rotate', 'r', InputOption::VALUE_NONE, 'Re-encrypts existing secrets with the newly generated keys.') - ->setHelp(<<<'EOF' -The %command.name% command generates a new encryption key. - - %command.full_name% - -If encryption keys already exist, the command must be called with -the --rotate option in order to override those keys and re-encrypt -existing secrets. - - %command.full_name% --rotate -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); - $vault = $input->getOption('local') ? $this->localVault : $this->vault; - - if (null === $vault) { - $io->success('The local vault is disabled.'); - - return 1; - } - - if (!$input->getOption('rotate')) { - if ($vault->generateKeys()) { - $io->success($vault->getLastMessage()); - - if ($this->vault === $vault) { - $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️'); - } - - return 0; - } - - $io->warning($vault->getLastMessage()); - - return 1; - } - - $secrets = []; - foreach ($vault->list(true) as $name => $value) { - if (null === $value) { - $io->error($vault->getLastMessage()); - - return 1; - } - - $secrets[$name] = $value; - } - - if (!$vault->generateKeys(true)) { - $io->warning($vault->getLastMessage()); - - return 1; - } - - $io->success($vault->getLastMessage()); - - if ($secrets) { - foreach ($secrets as $name => $value) { - $vault->seal($name, $value); - } - - $io->comment('Existing secrets have been rotated to the new keys.'); - } - - if ($this->vault === $vault) { - $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️'); - } - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/SecretsListCommand.php b/vendor/symfony/framework-bundle/Command/SecretsListCommand.php deleted file mode 100644 index cc32284..0000000 --- a/vendor/symfony/framework-bundle/Command/SecretsListCommand.php +++ /dev/null @@ -1,108 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\Dumper; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * @author Tobias Schultze - * @author Jérémy Derussé - * @author Nicolas Grekas - * - * @internal - */ -final class SecretsListCommand extends Command -{ - protected static $defaultName = 'secrets:list'; - - private $vault; - private $localVault; - - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - - parent::__construct(); - } - - protected function configure() - { - $this - ->setDescription('Lists all secrets.') - ->addOption('reveal', 'r', InputOption::VALUE_NONE, 'Display decrypted values alongside names') - ->setHelp(<<<'EOF' -The %command.name% command list all stored secrets. - - %command.full_name% - -When the option --reveal is provided, the decrypted secrets are also displayed. - - %command.full_name% --reveal -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); - - $io->comment('Use "%env()%" to reference a secret in a config file.'); - - if (!$reveal = $input->getOption('reveal')) { - $io->comment(sprintf('To reveal the secrets run php %s %s --reveal', $_SERVER['PHP_SELF'], $this->getName())); - } - - $secrets = $this->vault->list($reveal); - $localSecrets = null !== $this->localVault ? $this->localVault->list($reveal) : null; - - $rows = []; - - $dump = new Dumper($output); - $dump = static function (?string $v) use ($dump) { - return null === $v ? '******' : $dump($v); - }; - - foreach ($secrets as $name => $value) { - $rows[$name] = [$name, $dump($value)]; - } - - if (null !== $message = $this->vault->getLastMessage()) { - $io->comment($message); - } - - foreach ($localSecrets ?? [] as $name => $value) { - if (isset($rows[$name])) { - $rows[$name][] = $dump($value); - } - } - - if (null !== $this->localVault && null !== $message = $this->localVault->getLastMessage()) { - $io->comment($message); - } - - (new SymfonyStyle($input, $output)) - ->table(['Secret', 'Value'] + (null !== $localSecrets ? [2 => 'Local Value'] : []), $rows); - - $io->comment("Local values override secret values.\nUse secrets:set --local to defined them."); - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/SecretsRemoveCommand.php b/vendor/symfony/framework-bundle/Command/SecretsRemoveCommand.php deleted file mode 100644 index b0ce9a8..0000000 --- a/vendor/symfony/framework-bundle/Command/SecretsRemoveCommand.php +++ /dev/null @@ -1,82 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * @author Jérémy Derussé - * @author Nicolas Grekas - * - * @internal - */ -final class SecretsRemoveCommand extends Command -{ - protected static $defaultName = 'secrets:remove'; - - private $vault; - private $localVault; - - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - - parent::__construct(); - } - - protected function configure() - { - $this - ->setDescription('Removes a secret from the vault.') - ->addArgument('name', InputArgument::REQUIRED, 'The name of the secret') - ->addOption('local', 'l', InputOption::VALUE_NONE, 'Updates the local vault.') - ->setHelp(<<<'EOF' -The %command.name% command removes a secret from the vault. - - %command.full_name% -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); - $vault = $input->getOption('local') ? $this->localVault : $this->vault; - - if (null === $vault) { - $io->success('The local vault is disabled.'); - - return 1; - } - - if ($vault->remove($name = $input->getArgument('name'))) { - $io->success($vault->getLastMessage() ?? 'Secret was removed from the vault.'); - } else { - $io->comment($vault->getLastMessage() ?? 'Secret was not found in the vault.'); - } - - if ($this->vault === $vault && null !== $this->localVault->reveal($name)) { - $io->comment('Note that this secret is overridden in the local vault.'); - } - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/SecretsSetCommand.php b/vendor/symfony/framework-bundle/Command/SecretsSetCommand.php deleted file mode 100644 index 5cca8d7..0000000 --- a/vendor/symfony/framework-bundle/Command/SecretsSetCommand.php +++ /dev/null @@ -1,140 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Bundle\FrameworkBundle\Secrets\AbstractVault; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * @author Tobias Schultze - * @author Jérémy Derussé - * @author Nicolas Grekas - * - * @internal - */ -final class SecretsSetCommand extends Command -{ - protected static $defaultName = 'secrets:set'; - - private $vault; - private $localVault; - - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) - { - $this->vault = $vault; - $this->localVault = $localVault; - - parent::__construct(); - } - - protected function configure() - { - $this - ->setDescription('Sets a secret in the vault.') - ->addArgument('name', InputArgument::REQUIRED, 'The name of the secret') - ->addArgument('file', InputArgument::OPTIONAL, 'A file where to read the secret from or "-" for reading from STDIN') - ->addOption('local', 'l', InputOption::VALUE_NONE, 'Updates the local vault.') - ->addOption('random', 'r', InputOption::VALUE_OPTIONAL, 'Generates a random value.', false) - ->setHelp(<<<'EOF' -The %command.name% command stores a secret in the vault. - - %command.full_name% - -To reference secrets in services.yaml or any other config -files, use "%env()%". - -By default, the secret value should be entered interactively. -Alternatively, provide a file where to read the secret from: - - php %command.full_name% filename - -Use "-" as a file name to read from STDIN: - - cat filename | php %command.full_name% - - -Use --local to override secrets for local needs. -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $errOutput = $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output; - $io = new SymfonyStyle($input, $errOutput); - $name = $input->getArgument('name'); - $vault = $input->getOption('local') ? $this->localVault : $this->vault; - - if (null === $vault) { - $io->error('The local vault is disabled.'); - - return 1; - } - - if ($this->localVault === $vault && !\array_key_exists($name, $this->vault->list())) { - $io->error(sprintf('Secret "%s" does not exist in the vault, you cannot override it locally.', $name)); - - return 1; - } - - if (0 < $random = $input->getOption('random') ?? 16) { - $value = strtr(substr(base64_encode(random_bytes($random)), 0, $random), '+/', '-_'); - } elseif (!$file = $input->getArgument('file')) { - $value = $io->askHidden('Please type the secret value'); - } elseif ('-' === $file) { - $value = file_get_contents('php://stdin'); - } elseif (is_file($file) && is_readable($file)) { - $value = file_get_contents($file); - } elseif (!is_file($file)) { - throw new \InvalidArgumentException(sprintf('File not found: "%s".', $file)); - } elseif (!is_readable($file)) { - throw new \InvalidArgumentException(sprintf('File is not readable: "%s".', $file)); - } - - if (null === $value) { - $io->warning('No value provided, aborting.'); - - return 1; - } - - if ($vault->generateKeys()) { - $io->success($vault->getLastMessage()); - - if ($this->vault === $vault) { - $io->caution('DO NOT COMMIT THE DECRYPTION KEY FOR THE PROD ENVIRONMENT⚠️'); - } - } - - $vault->seal($name, $value); - - $io->success($vault->getLastMessage() ?? 'Secret was successfully stored in the vault.'); - - if (0 < $random) { - $errOutput->write(' // The generated random value is: '); - $output->write($value); - $errOutput->writeln(''); - $io->newLine(); - } - - if ($this->vault === $vault && null !== $this->localVault->reveal($name)) { - $io->comment('Note that this secret is overridden in the local vault.'); - } - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/TranslationDebugCommand.php b/vendor/symfony/framework-bundle/Command/TranslationDebugCommand.php deleted file mode 100644 index 24290a4..0000000 --- a/vendor/symfony/framework-bundle/Command/TranslationDebugCommand.php +++ /dev/null @@ -1,342 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\Translation\Catalogue\MergeOperation; -use Symfony\Component\Translation\DataCollectorTranslator; -use Symfony\Component\Translation\Extractor\ExtractorInterface; -use Symfony\Component\Translation\LoggingTranslator; -use Symfony\Component\Translation\MessageCatalogue; -use Symfony\Component\Translation\Reader\TranslationReaderInterface; -use Symfony\Component\Translation\Translator; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * Helps finding unused or missing translation messages in a given locale - * and comparing them with the fallback ones. - * - * @author Florian Voutzinos - * - * @final - */ -class TranslationDebugCommand extends Command -{ - const MESSAGE_MISSING = 0; - const MESSAGE_UNUSED = 1; - const MESSAGE_EQUALS_FALLBACK = 2; - - protected static $defaultName = 'debug:translation'; - - private $translator; - private $reader; - private $extractor; - private $defaultTransPath; - private $defaultViewsPath; - private $transPaths; - private $viewsPaths; - - public function __construct(TranslatorInterface $translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $viewsPaths = []) - { - parent::__construct(); - - $this->translator = $translator; - $this->reader = $reader; - $this->extractor = $extractor; - $this->defaultTransPath = $defaultTransPath; - $this->defaultViewsPath = $defaultViewsPath; - $this->transPaths = $transPaths; - $this->viewsPaths = $viewsPaths; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), - new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages'), - new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'The messages domain'), - new InputOption('only-missing', null, InputOption::VALUE_NONE, 'Displays only missing messages'), - new InputOption('only-unused', null, InputOption::VALUE_NONE, 'Displays only unused messages'), - new InputOption('all', null, InputOption::VALUE_NONE, 'Load messages from all registered bundles'), - ]) - ->setDescription('Displays translation messages information') - ->setHelp(<<<'EOF' -The %command.name% command helps finding unused or missing translation -messages and comparing them with the fallback ones by inspecting the -templates and translation files of a given bundle or the default translations directory. - -You can display information about bundle translations in a specific locale: - - php %command.full_name% en AcmeDemoBundle - -You can also specify a translation domain for the search: - - php %command.full_name% --domain=messages en AcmeDemoBundle - -You can only display missing messages: - - php %command.full_name% --only-missing en AcmeDemoBundle - -You can only display unused messages: - - php %command.full_name% --only-unused en AcmeDemoBundle - -You can display information about application translations in a specific locale: - - php %command.full_name% en - -You can display information about translations in all registered bundles in a specific locale: - - php %command.full_name% --all en - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - $locale = $input->getArgument('locale'); - $domain = $input->getOption('domain'); - /** @var KernelInterface $kernel */ - $kernel = $this->getApplication()->getKernel(); - - // Define Root Paths - $transPaths = $this->transPaths; - if ($this->defaultTransPath) { - $transPaths[] = $this->defaultTransPath; - } - $viewsPaths = $this->viewsPaths; - if ($this->defaultViewsPath) { - $viewsPaths[] = $this->defaultViewsPath; - } - - // Override with provided Bundle info - if (null !== $input->getArgument('bundle')) { - try { - $bundle = $kernel->getBundle($input->getArgument('bundle')); - $bundleDir = $bundle->getPath(); - $transPaths = [is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundleDir.'/translations']; - $viewsPaths = [is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundleDir.'/templates']; - if ($this->defaultTransPath) { - $transPaths[] = $this->defaultTransPath; - } - if ($this->defaultViewsPath) { - $viewsPaths[] = $this->defaultViewsPath; - } - } catch (\InvalidArgumentException $e) { - // such a bundle does not exist, so treat the argument as path - $path = $input->getArgument('bundle'); - - $transPaths = [$path.'/translations']; - $viewsPaths = [$path.'/templates']; - - if (!is_dir($transPaths[0]) && !isset($transPaths[1])) { - throw new InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0])); - } - } - } elseif ($input->getOption('all')) { - foreach ($kernel->getBundles() as $bundle) { - $bundleDir = $bundle->getPath(); - $transPaths[] = is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundle->getPath().'/translations'; - $viewsPaths[] = is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundle->getPath().'/templates'; - } - } - - // Extract used messages - $extractedCatalogue = $this->extractMessages($locale, $viewsPaths); - - // Load defined messages - $currentCatalogue = $this->loadCurrentMessages($locale, $transPaths); - - // Merge defined and extracted messages to get all message ids - $mergeOperation = new MergeOperation($extractedCatalogue, $currentCatalogue); - $allMessages = $mergeOperation->getResult()->all($domain); - if (null !== $domain) { - $allMessages = [$domain => $allMessages]; - } - - // No defined or extracted messages - if (empty($allMessages) || null !== $domain && empty($allMessages[$domain])) { - $outputMessage = sprintf('No defined or extracted messages for locale "%s"', $locale); - - if (null !== $domain) { - $outputMessage .= sprintf(' and domain "%s"', $domain); - } - - $io->getErrorStyle()->warning($outputMessage); - - return 0; - } - - // Load the fallback catalogues - $fallbackCatalogues = $this->loadFallbackCatalogues($locale, $transPaths); - - // Display header line - $headers = ['State', 'Domain', 'Id', sprintf('Message Preview (%s)', $locale)]; - foreach ($fallbackCatalogues as $fallbackCatalogue) { - $headers[] = sprintf('Fallback Message Preview (%s)', $fallbackCatalogue->getLocale()); - } - $rows = []; - // Iterate all message ids and determine their state - foreach ($allMessages as $domain => $messages) { - foreach (array_keys($messages) as $messageId) { - $value = $currentCatalogue->get($messageId, $domain); - $states = []; - - if ($extractedCatalogue->defines($messageId, $domain)) { - if (!$currentCatalogue->defines($messageId, $domain)) { - $states[] = self::MESSAGE_MISSING; - } - } elseif ($currentCatalogue->defines($messageId, $domain)) { - $states[] = self::MESSAGE_UNUSED; - } - - if (!\in_array(self::MESSAGE_UNUSED, $states) && true === $input->getOption('only-unused') - || !\in_array(self::MESSAGE_MISSING, $states) && true === $input->getOption('only-missing')) { - continue; - } - - foreach ($fallbackCatalogues as $fallbackCatalogue) { - if ($fallbackCatalogue->defines($messageId, $domain) && $value === $fallbackCatalogue->get($messageId, $domain)) { - $states[] = self::MESSAGE_EQUALS_FALLBACK; - - break; - } - } - - $row = [$this->formatStates($states), $domain, $this->formatId($messageId), $this->sanitizeString($value)]; - foreach ($fallbackCatalogues as $fallbackCatalogue) { - $row[] = $this->sanitizeString($fallbackCatalogue->get($messageId, $domain)); - } - - $rows[] = $row; - } - } - - $io->table($headers, $rows); - - return 0; - } - - private function formatState(int $state): string - { - if (self::MESSAGE_MISSING === $state) { - return ' missing '; - } - - if (self::MESSAGE_UNUSED === $state) { - return ' unused '; - } - - if (self::MESSAGE_EQUALS_FALLBACK === $state) { - return ' fallback '; - } - - return $state; - } - - private function formatStates(array $states): string - { - $result = []; - foreach ($states as $state) { - $result[] = $this->formatState($state); - } - - return implode(' ', $result); - } - - private function formatId(string $id): string - { - return sprintf('%s', $id); - } - - private function sanitizeString(string $string, int $length = 40): string - { - $string = trim(preg_replace('/\s+/', ' ', $string)); - - if (false !== $encoding = mb_detect_encoding($string, null, true)) { - if (mb_strlen($string, $encoding) > $length) { - return mb_substr($string, 0, $length - 3, $encoding).'...'; - } - } elseif (\strlen($string) > $length) { - return substr($string, 0, $length - 3).'...'; - } - - return $string; - } - - private function extractMessages(string $locale, array $transPaths): MessageCatalogue - { - $extractedCatalogue = new MessageCatalogue($locale); - foreach ($transPaths as $path) { - if (is_dir($path) || is_file($path)) { - $this->extractor->extract($path, $extractedCatalogue); - } - } - - return $extractedCatalogue; - } - - private function loadCurrentMessages(string $locale, array $transPaths): MessageCatalogue - { - $currentCatalogue = new MessageCatalogue($locale); - foreach ($transPaths as $path) { - if (is_dir($path)) { - $this->reader->read($path, $currentCatalogue); - } - } - - return $currentCatalogue; - } - - /** - * @return MessageCatalogue[] - */ - private function loadFallbackCatalogues(string $locale, array $transPaths): array - { - $fallbackCatalogues = []; - if ($this->translator instanceof Translator || $this->translator instanceof DataCollectorTranslator || $this->translator instanceof LoggingTranslator) { - foreach ($this->translator->getFallbackLocales() as $fallbackLocale) { - if ($fallbackLocale === $locale) { - continue; - } - - $fallbackCatalogue = new MessageCatalogue($fallbackLocale); - foreach ($transPaths as $path) { - if (is_dir($path)) { - $this->reader->read($path, $fallbackCatalogue); - } - } - $fallbackCatalogues[] = $fallbackCatalogue; - } - } - - return $fallbackCatalogues; - } -} diff --git a/vendor/symfony/framework-bundle/Command/TranslationUpdateCommand.php b/vendor/symfony/framework-bundle/Command/TranslationUpdateCommand.php deleted file mode 100644 index e717b07..0000000 --- a/vendor/symfony/framework-bundle/Command/TranslationUpdateCommand.php +++ /dev/null @@ -1,316 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\Translation\Catalogue\MergeOperation; -use Symfony\Component\Translation\Catalogue\TargetOperation; -use Symfony\Component\Translation\Extractor\ExtractorInterface; -use Symfony\Component\Translation\MessageCatalogue; -use Symfony\Component\Translation\Reader\TranslationReaderInterface; -use Symfony\Component\Translation\Writer\TranslationWriterInterface; - -/** - * A command that parses templates to extract translation messages and adds them - * into the translation files. - * - * @author Michel Salib - * - * @final - */ -class TranslationUpdateCommand extends Command -{ - private const ASC = 'asc'; - private const DESC = 'desc'; - private const SORT_ORDERS = [self::ASC, self::DESC]; - - protected static $defaultName = 'translation:update'; - - private $writer; - private $reader; - private $extractor; - private $defaultLocale; - private $defaultTransPath; - private $defaultViewsPath; - private $transPaths; - private $viewsPaths; - - public function __construct(TranslationWriterInterface $writer, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultLocale, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $viewsPaths = []) - { - parent::__construct(); - - $this->writer = $writer; - $this->reader = $reader; - $this->extractor = $extractor; - $this->defaultLocale = $defaultLocale; - $this->defaultTransPath = $defaultTransPath; - $this->defaultViewsPath = $defaultViewsPath; - $this->transPaths = $transPaths; - $this->viewsPaths = $viewsPaths; - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), - new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages'), - new InputOption('prefix', null, InputOption::VALUE_OPTIONAL, 'Override the default prefix', '__'), - new InputOption('output-format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format', 'xlf'), - new InputOption('dump-messages', null, InputOption::VALUE_NONE, 'Should the messages be dumped in the console'), - new InputOption('force', null, InputOption::VALUE_NONE, 'Should the update be done'), - new InputOption('no-backup', null, InputOption::VALUE_NONE, 'Should backup be disabled'), - new InputOption('clean', null, InputOption::VALUE_NONE, 'Should clean not found messages'), - new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'Specify the domain to update'), - new InputOption('xliff-version', null, InputOption::VALUE_OPTIONAL, 'Override the default xliff version', '1.2'), - new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically'), - ]) - ->setDescription('Updates the translation file') - ->setHelp(<<<'EOF' -The %command.name% command extracts translation strings from templates -of a given bundle or the default translations directory. It can display them or merge -the new ones into the translation files. - -When new translation strings are found it can automatically add a prefix to the translation -message. - -Example running against a Bundle (AcmeBundle) - - php %command.full_name% --dump-messages en AcmeBundle - php %command.full_name% --force --prefix="new_" fr AcmeBundle - -Example running against default messages directory - - php %command.full_name% --dump-messages en - php %command.full_name% --force --prefix="new_" fr - -You can sort the output with the --sort flag: - - php %command.full_name% --dump-messages --sort=asc en AcmeBundle - php %command.full_name% --dump-messages --sort=desc fr -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $errorIo = $io->getErrorStyle(); - - // check presence of force or dump-message - if (true !== $input->getOption('force') && true !== $input->getOption('dump-messages')) { - $errorIo->error('You must choose one of --force or --dump-messages'); - - return 1; - } - - // check format - $supportedFormats = $this->writer->getFormats(); - if (!\in_array($input->getOption('output-format'), $supportedFormats, true)) { - $errorIo->error(['Wrong output format', 'Supported formats are: '.implode(', ', $supportedFormats).'.']); - - return 1; - } - /** @var KernelInterface $kernel */ - $kernel = $this->getApplication()->getKernel(); - - // Define Root Paths - $transPaths = $this->transPaths; - if ($this->defaultTransPath) { - $transPaths[] = $this->defaultTransPath; - } - $viewsPaths = $this->viewsPaths; - if ($this->defaultViewsPath) { - $viewsPaths[] = $this->defaultViewsPath; - } - $currentName = 'default directory'; - - // Override with provided Bundle info - if (null !== $input->getArgument('bundle')) { - try { - $foundBundle = $kernel->getBundle($input->getArgument('bundle')); - $bundleDir = $foundBundle->getPath(); - $transPaths = [is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundleDir.'/translations']; - $viewsPaths = [is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundleDir.'/templates']; - if ($this->defaultTransPath) { - $transPaths[] = $this->defaultTransPath; - } - if ($this->defaultViewsPath) { - $viewsPaths[] = $this->defaultViewsPath; - } - $currentName = $foundBundle->getName(); - } catch (\InvalidArgumentException $e) { - // such a bundle does not exist, so treat the argument as path - $path = $input->getArgument('bundle'); - - $transPaths = [$path.'/translations']; - $viewsPaths = [$path.'/templates']; - - if (!is_dir($transPaths[0]) && !isset($transPaths[1])) { - throw new InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0])); - } - } - } - - $errorIo->title('Translation Messages Extractor and Dumper'); - $errorIo->comment(sprintf('Generating "%s" translation files for "%s"', $input->getArgument('locale'), $currentName)); - - // load any messages from templates - $extractedCatalogue = new MessageCatalogue($input->getArgument('locale')); - $errorIo->comment('Parsing templates...'); - $this->extractor->setPrefix($input->getOption('prefix')); - foreach ($viewsPaths as $path) { - if (is_dir($path) || is_file($path)) { - $this->extractor->extract($path, $extractedCatalogue); - } - } - - // load any existing messages from the translation files - $currentCatalogue = new MessageCatalogue($input->getArgument('locale')); - $errorIo->comment('Loading translation files...'); - foreach ($transPaths as $path) { - if (is_dir($path)) { - $this->reader->read($path, $currentCatalogue); - } - } - - if (null !== $domain = $input->getOption('domain')) { - $currentCatalogue = $this->filterCatalogue($currentCatalogue, $domain); - $extractedCatalogue = $this->filterCatalogue($extractedCatalogue, $domain); - } - - // process catalogues - $operation = $input->getOption('clean') - ? new TargetOperation($currentCatalogue, $extractedCatalogue) - : new MergeOperation($currentCatalogue, $extractedCatalogue); - - // Exit if no messages found. - if (!\count($operation->getDomains())) { - $errorIo->warning('No translation messages were found.'); - - return 0; - } - - $resultMessage = 'Translation files were successfully updated'; - - // show compiled list of messages - if (true === $input->getOption('dump-messages')) { - $extractedMessagesCount = 0; - $io->newLine(); - foreach ($operation->getDomains() as $domain) { - $newKeys = array_keys($operation->getNewMessages($domain)); - $allKeys = array_keys($operation->getMessages($domain)); - - $list = array_merge( - array_diff($allKeys, $newKeys), - array_map(function ($id) { - return sprintf('%s', $id); - }, $newKeys), - array_map(function ($id) { - return sprintf('%s', $id); - }, array_keys($operation->getObsoleteMessages($domain))) - ); - - $domainMessagesCount = \count($list); - - if ($sort = $input->getOption('sort')) { - $sort = strtolower($sort); - if (!\in_array($sort, self::SORT_ORDERS, true)) { - $errorIo->error(['Wrong sort order', 'Supported formats are: '.implode(', ', self::SORT_ORDERS).'.']); - - return 1; - } - - if (self::DESC === $sort) { - rsort($list); - } else { - sort($list); - } - } - - $io->section(sprintf('Messages extracted for domain "%s" (%d message%s)', $domain, $domainMessagesCount, $domainMessagesCount > 1 ? 's' : '')); - $io->listing($list); - - $extractedMessagesCount += $domainMessagesCount; - } - - if ('xlf' === $input->getOption('output-format')) { - $errorIo->comment(sprintf('Xliff output version is %s', $input->getOption('xliff-version'))); - } - - $resultMessage = sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was'); - } - - if (true === $input->getOption('no-backup')) { - $this->writer->disableBackup(); - } - - // save the files - if (true === $input->getOption('force')) { - $errorIo->comment('Writing files...'); - - $bundleTransPath = false; - foreach ($transPaths as $path) { - if (is_dir($path)) { - $bundleTransPath = $path; - } - } - - if (!$bundleTransPath) { - $bundleTransPath = end($transPaths); - } - - $this->writer->write($operation->getResult(), $input->getOption('output-format'), ['path' => $bundleTransPath, 'default_locale' => $this->defaultLocale, 'xliff_version' => $input->getOption('xliff-version')]); - - if (true === $input->getOption('dump-messages')) { - $resultMessage .= ' and translation files were updated'; - } - } - - $errorIo->success($resultMessage.'.'); - - return 0; - } - - private function filterCatalogue(MessageCatalogue $catalogue, string $domain): MessageCatalogue - { - $filteredCatalogue = new MessageCatalogue($catalogue->getLocale()); - - if ($messages = $catalogue->all($domain)) { - $filteredCatalogue->add($messages, $domain); - } - foreach ($catalogue->getResources() as $resource) { - $filteredCatalogue->addResource($resource); - } - if ($metadata = $catalogue->getMetadata('', $domain)) { - foreach ($metadata as $k => $v) { - $filteredCatalogue->setMetadata($k, $v, $domain); - } - } - - return $filteredCatalogue; - } -} diff --git a/vendor/symfony/framework-bundle/Command/WorkflowDumpCommand.php b/vendor/symfony/framework-bundle/Command/WorkflowDumpCommand.php deleted file mode 100644 index cec930d..0000000 --- a/vendor/symfony/framework-bundle/Command/WorkflowDumpCommand.php +++ /dev/null @@ -1,103 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Workflow\Dumper\GraphvizDumper; -use Symfony\Component\Workflow\Dumper\PlantUmlDumper; -use Symfony\Component\Workflow\Dumper\StateMachineGraphvizDumper; -use Symfony\Component\Workflow\Marking; - -/** - * @author Grégoire Pineau - * - * @final - */ -class WorkflowDumpCommand extends Command -{ - protected static $defaultName = 'workflow:dump'; - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDefinition([ - new InputArgument('name', InputArgument::REQUIRED, 'A workflow name'), - new InputArgument('marking', InputArgument::IS_ARRAY, 'A marking (a list of places)'), - new InputOption('label', 'l', InputOption::VALUE_REQUIRED, 'Labels a graph'), - new InputOption('dump-format', null, InputOption::VALUE_REQUIRED, 'The dump format [dot|puml]', 'dot'), - ]) - ->setDescription('Dump a workflow') - ->setHelp(<<<'EOF' -The %command.name% command dumps the graphical representation of a -workflow in different formats - -DOT: %command.full_name% | dot -Tpng > workflow.png -PUML: %command.full_name% --dump-format=puml | java -jar plantuml.jar -p > workflow.png - -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output): int - { - $container = $this->getApplication()->getKernel()->getContainer(); - $serviceId = $input->getArgument('name'); - - if ($container->has('workflow.'.$serviceId)) { - $workflow = $container->get('workflow.'.$serviceId); - $type = 'workflow'; - } elseif ($container->has('state_machine.'.$serviceId)) { - $workflow = $container->get('state_machine.'.$serviceId); - $type = 'state_machine'; - } else { - throw new InvalidArgumentException(sprintf('No service found for "workflow.%1$s" nor "state_machine.%1$s".', $serviceId)); - } - - if ('puml' === $input->getOption('dump-format')) { - $transitionType = 'workflow' === $type ? PlantUmlDumper::WORKFLOW_TRANSITION : PlantUmlDumper::STATEMACHINE_TRANSITION; - $dumper = new PlantUmlDumper($transitionType); - } elseif ('workflow' === $type) { - $dumper = new GraphvizDumper(); - } else { - $dumper = new StateMachineGraphvizDumper(); - } - - $marking = new Marking(); - - foreach ($input->getArgument('marking') as $place) { - $marking->mark($place); - } - - $options = [ - 'name' => $serviceId, - 'nofooter' => true, - 'graph' => [ - 'label' => $input->getOption('label'), - ], - ]; - $output->writeln($dumper->dump($workflow->getDefinition(), $marking, $options)); - - return 0; - } -} diff --git a/vendor/symfony/framework-bundle/Command/XliffLintCommand.php b/vendor/symfony/framework-bundle/Command/XliffLintCommand.php deleted file mode 100644 index 0b5bb06..0000000 --- a/vendor/symfony/framework-bundle/Command/XliffLintCommand.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Translation\Command\XliffLintCommand as BaseLintCommand; - -/** - * Validates XLIFF files syntax and outputs encountered errors. - * - * @author Grégoire Pineau - * @author Robin Chalas - * @author Javier Eguiluz - * - * @final - */ -class XliffLintCommand extends BaseLintCommand -{ - protected static $defaultName = 'lint:xliff'; - - public function __construct() - { - $directoryIteratorProvider = function ($directory, $default) { - if (!is_dir($directory)) { - $directory = $this->getApplication()->getKernel()->locateResource($directory); - } - - return $default($directory); - }; - - $isReadableProvider = function ($fileOrDirectory, $default) { - return 0 === strpos($fileOrDirectory, '@') || $default($fileOrDirectory); - }; - - parent::__construct(null, $directoryIteratorProvider, $isReadableProvider); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - parent::configure(); - - $this->setHelp($this->getHelp().<<<'EOF' - -Or find all files in a bundle: - - php %command.full_name% @AcmeDemoBundle - -EOF - ); - } -} diff --git a/vendor/symfony/framework-bundle/Command/YamlLintCommand.php b/vendor/symfony/framework-bundle/Command/YamlLintCommand.php deleted file mode 100644 index 1163ff1..0000000 --- a/vendor/symfony/framework-bundle/Command/YamlLintCommand.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Command; - -use Symfony\Component\Yaml\Command\LintCommand as BaseLintCommand; - -/** - * Validates YAML files syntax and outputs encountered errors. - * - * @author Grégoire Pineau - * @author Robin Chalas - * - * @final - */ -class YamlLintCommand extends BaseLintCommand -{ - protected static $defaultName = 'lint:yaml'; - - public function __construct() - { - $directoryIteratorProvider = function ($directory, $default) { - if (!is_dir($directory)) { - $directory = $this->getApplication()->getKernel()->locateResource($directory); - } - - return $default($directory); - }; - - $isReadableProvider = function ($fileOrDirectory, $default) { - return 0 === strpos($fileOrDirectory, '@') || $default($fileOrDirectory); - }; - - parent::__construct(null, $directoryIteratorProvider, $isReadableProvider); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - parent::configure(); - - $this->setHelp($this->getHelp().<<<'EOF' - -Or find all files in a bundle: - - php %command.full_name% @AcmeDemoBundle - -EOF - ); - } -} diff --git a/vendor/symfony/framework-bundle/Console/Application.php b/vendor/symfony/framework-bundle/Console/Application.php deleted file mode 100644 index dddde43..0000000 --- a/vendor/symfony/framework-bundle/Console/Application.php +++ /dev/null @@ -1,221 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console; - -use Symfony\Component\Console\Application as BaseApplication; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Command\ListCommand; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Debug\Exception\FatalThrowableError; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\HttpKernel\Bundle\Bundle; -use Symfony\Component\HttpKernel\Kernel; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * @author Fabien Potencier - */ -class Application extends BaseApplication -{ - private $kernel; - private $commandsRegistered = false; - private $registrationErrors = []; - - public function __construct(KernelInterface $kernel) - { - $this->kernel = $kernel; - - parent::__construct('Symfony', Kernel::VERSION); - - $inputDefinition = $this->getDefinition(); - $inputDefinition->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'The Environment name.', $kernel->getEnvironment())); - $inputDefinition->addOption(new InputOption('--no-debug', null, InputOption::VALUE_NONE, 'Switches off debug mode.')); - } - - /** - * Gets the Kernel associated with this Console. - * - * @return KernelInterface A KernelInterface instance - */ - public function getKernel() - { - return $this->kernel; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - if ($this->kernel->getContainer()->has('services_resetter')) { - $this->kernel->getContainer()->get('services_resetter')->reset(); - } - } - - /** - * Runs the current application. - * - * @return int 0 if everything went fine, or an error code - */ - public function doRun(InputInterface $input, OutputInterface $output) - { - $this->registerCommands(); - - if ($this->registrationErrors) { - $this->renderRegistrationErrors($input, $output); - } - - $this->setDispatcher($this->kernel->getContainer()->get('event_dispatcher')); - - return parent::doRun($input, $output); - } - - /** - * {@inheritdoc} - */ - protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) - { - if (!$command instanceof ListCommand) { - if ($this->registrationErrors) { - $this->renderRegistrationErrors($input, $output); - $this->registrationErrors = []; - } - - return parent::doRunCommand($command, $input, $output); - } - - $returnCode = parent::doRunCommand($command, $input, $output); - - if ($this->registrationErrors) { - $this->renderRegistrationErrors($input, $output); - $this->registrationErrors = []; - } - - return $returnCode; - } - - /** - * {@inheritdoc} - */ - public function find($name) - { - $this->registerCommands(); - - return parent::find($name); - } - - /** - * {@inheritdoc} - */ - public function get($name) - { - $this->registerCommands(); - - $command = parent::get($name); - - if ($command instanceof ContainerAwareInterface) { - $command->setContainer($this->kernel->getContainer()); - } - - return $command; - } - - /** - * {@inheritdoc} - */ - public function all($namespace = null) - { - $this->registerCommands(); - - return parent::all($namespace); - } - - /** - * {@inheritdoc} - */ - public function getLongVersion() - { - return parent::getLongVersion().sprintf(' (env: %s, debug: %s)', $this->kernel->getEnvironment(), $this->kernel->isDebug() ? 'true' : 'false'); - } - - public function add(Command $command) - { - $this->registerCommands(); - - return parent::add($command); - } - - protected function registerCommands() - { - if ($this->commandsRegistered) { - return; - } - - $this->commandsRegistered = true; - - $this->kernel->boot(); - - $container = $this->kernel->getContainer(); - - foreach ($this->kernel->getBundles() as $bundle) { - if ($bundle instanceof Bundle) { - try { - $bundle->registerCommands($this); - } catch (\Throwable $e) { - $this->registrationErrors[] = $e; - } - } - } - - if ($container->has('console.command_loader')) { - $this->setCommandLoader($container->get('console.command_loader')); - } - - if ($container->hasParameter('console.command.ids')) { - $lazyCommandIds = $container->hasParameter('console.lazy_command.ids') ? $container->getParameter('console.lazy_command.ids') : []; - foreach ($container->getParameter('console.command.ids') as $id) { - if (!isset($lazyCommandIds[$id])) { - try { - $this->add($container->get($id)); - } catch (\Throwable $e) { - $this->registrationErrors[] = $e; - } - } - } - } - } - - private function renderRegistrationErrors(InputInterface $input, OutputInterface $output) - { - if ($output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - - (new SymfonyStyle($input, $output))->warning('Some commands could not be registered:'); - - foreach ($this->registrationErrors as $error) { - if (method_exists($this, 'doRenderThrowable')) { - $this->doRenderThrowable($error, $output); - } else { - if (!$error instanceof \Exception) { - $error = new FatalThrowableError($error); - } - - $this->doRenderException($error, $output); - } - } - } -} diff --git a/vendor/symfony/framework-bundle/Console/Descriptor/Descriptor.php b/vendor/symfony/framework-bundle/Console/Descriptor/Descriptor.php deleted file mode 100644 index cbb01dc..0000000 --- a/vendor/symfony/framework-bundle/Console/Descriptor/Descriptor.php +++ /dev/null @@ -1,384 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; - -use Symfony\Component\Config\Resource\ClassExistenceResource; -use Symfony\Component\Console\Descriptor\DescriptorInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Jean-François Simon - * - * @internal - */ -abstract class Descriptor implements DescriptorInterface -{ - /** - * @var OutputInterface - */ - protected $output; - - /** - * {@inheritdoc} - */ - public function describe(OutputInterface $output, $object, array $options = []) - { - $this->output = $output; - - switch (true) { - case $object instanceof RouteCollection: - $this->describeRouteCollection($object, $options); - break; - case $object instanceof Route: - $this->describeRoute($object, $options); - break; - case $object instanceof ParameterBag: - $this->describeContainerParameters($object, $options); - break; - case $object instanceof ContainerBuilder && !empty($options['env-vars']): - $this->describeContainerEnvVars($this->getContainerEnvVars($object), $options); - break; - case $object instanceof ContainerBuilder && isset($options['group_by']) && 'tags' === $options['group_by']: - $this->describeContainerTags($object, $options); - break; - case $object instanceof ContainerBuilder && isset($options['id']): - $this->describeContainerService($this->resolveServiceDefinition($object, $options['id']), $options, $object); - break; - case $object instanceof ContainerBuilder && isset($options['parameter']): - $this->describeContainerParameter($object->resolveEnvPlaceholders($object->getParameter($options['parameter'])), $options); - break; - case $object instanceof ContainerBuilder: - $this->describeContainerServices($object, $options); - break; - case $object instanceof Definition: - $this->describeContainerDefinition($object, $options); - break; - case $object instanceof Alias: - $this->describeContainerAlias($object, $options); - break; - case $object instanceof EventDispatcherInterface: - $this->describeEventDispatcherListeners($object, $options); - break; - case \is_callable($object): - $this->describeCallable($object, $options); - break; - default: - throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', \get_class($object))); - } - } - - protected function getOutput(): OutputInterface - { - return $this->output; - } - - protected function write(string $content, bool $decorated = false) - { - $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); - } - - /** - * Describes an InputArgument instance. - */ - abstract protected function describeRouteCollection(RouteCollection $routes, array $options = []); - - /** - * Describes an InputOption instance. - */ - abstract protected function describeRoute(Route $route, array $options = []); - - /** - * Describes container parameters. - */ - abstract protected function describeContainerParameters(ParameterBag $parameters, array $options = []); - - /** - * Describes container tags. - */ - abstract protected function describeContainerTags(ContainerBuilder $builder, array $options = []); - - /** - * Describes a container service by its name. - * - * Common options are: - * * name: name of described service - * - * @param Definition|Alias|object $service - */ - abstract protected function describeContainerService($service, array $options = [], ContainerBuilder $builder = null); - - /** - * Describes container services. - * - * Common options are: - * * tag: filters described services by given tag - */ - abstract protected function describeContainerServices(ContainerBuilder $builder, array $options = []); - - /** - * Describes a service definition. - */ - abstract protected function describeContainerDefinition(Definition $definition, array $options = []); - - /** - * Describes a service alias. - */ - abstract protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null); - - /** - * Describes a container parameter. - */ - abstract protected function describeContainerParameter($parameter, array $options = []); - - /** - * Describes container environment variables. - */ - abstract protected function describeContainerEnvVars(array $envs, array $options = []); - - /** - * Describes event dispatcher listeners. - * - * Common options are: - * * name: name of listened event - */ - abstract protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []); - - /** - * Describes a callable. - * - * @param mixed $callable - */ - abstract protected function describeCallable($callable, array $options = []); - - /** - * Formats a value as string. - * - * @param mixed $value - */ - protected function formatValue($value): string - { - if (\is_object($value)) { - return sprintf('object(%s)', \get_class($value)); - } - - if (\is_string($value)) { - return $value; - } - - return preg_replace("/\n\s*/s", '', var_export($value, true)); - } - - /** - * Formats a parameter. - * - * @param mixed $value - */ - protected function formatParameter($value): string - { - if (\is_bool($value) || \is_array($value) || (null === $value)) { - $jsonString = json_encode($value); - - if (preg_match('/^(.{60})./us', $jsonString, $matches)) { - return $matches[1].'...'; - } - - return $jsonString; - } - - return (string) $value; - } - - /** - * @return mixed - */ - protected function resolveServiceDefinition(ContainerBuilder $builder, string $serviceId) - { - if ($builder->hasDefinition($serviceId)) { - return $builder->getDefinition($serviceId); - } - - // Some service IDs don't have a Definition, they're aliases - if ($builder->hasAlias($serviceId)) { - return $builder->getAlias($serviceId); - } - - if ('service_container' === $serviceId) { - return (new Definition(ContainerInterface::class))->setPublic(true)->setSynthetic(true); - } - - // the service has been injected in some special way, just return the service - return $builder->get($serviceId); - } - - protected function findDefinitionsByTag(ContainerBuilder $builder, bool $showHidden): array - { - $definitions = []; - $tags = $builder->findTags(); - asort($tags); - - foreach ($tags as $tag) { - foreach ($builder->findTaggedServiceIds($tag) as $serviceId => $attributes) { - $definition = $this->resolveServiceDefinition($builder, $serviceId); - - if ($showHidden xor '.' === ($serviceId[0] ?? null)) { - continue; - } - - if (!isset($definitions[$tag])) { - $definitions[$tag] = []; - } - - $definitions[$tag][$serviceId] = $definition; - } - } - - return $definitions; - } - - protected function sortParameters(ParameterBag $parameters) - { - $parameters = $parameters->all(); - ksort($parameters); - - return $parameters; - } - - protected function sortServiceIds(array $serviceIds) - { - asort($serviceIds); - - return $serviceIds; - } - - protected function sortTaggedServicesByPriority(array $services): array - { - $maxPriority = []; - foreach ($services as $service => $tags) { - $maxPriority[$service] = 0; - foreach ($tags as $tag) { - $currentPriority = $tag['priority'] ?? 0; - if ($maxPriority[$service] < $currentPriority) { - $maxPriority[$service] = $currentPriority; - } - } - } - uasort($maxPriority, function ($a, $b) { - return $b <=> $a; - }); - - return array_keys($maxPriority); - } - - protected function sortTagsByPriority(array $tags): array - { - $sortedTags = []; - foreach ($tags as $tagName => $tag) { - $sortedTags[$tagName] = $this->sortByPriority($tag); - } - - return $sortedTags; - } - - protected function sortByPriority(array $tag): array - { - usort($tag, function ($a, $b) { - return ($b['priority'] ?? 0) <=> ($a['priority'] ?? 0); - }); - - return $tag; - } - - /** - * Gets class description from a docblock. - */ - public static function getClassDescription(string $class, string &$resolvedClass = null): string - { - $resolvedClass = $class; - try { - $resource = new ClassExistenceResource($class, false); - - // isFresh() will explode ONLY if a parent class/trait does not exist - $resource->isFresh(0); - - $r = new \ReflectionClass($class); - $resolvedClass = $r->name; - - if ($docComment = $r->getDocComment()) { - $docComment = preg_split('#\n\s*\*\s*[\n@]#', substr($docComment, 3, -2), 2)[0]; - - return trim(preg_replace('#\s*\n\s*\*\s*#', ' ', $docComment)); - } - } catch (\ReflectionException $e) { - } - - return ''; - } - - private function getContainerEnvVars(ContainerBuilder $container): array - { - if (!$container->hasParameter('debug.container.dump')) { - return []; - } - - if (!is_file($container->getParameter('debug.container.dump'))) { - return []; - } - - $file = file_get_contents($container->getParameter('debug.container.dump')); - preg_match_all('{%env\(((?:\w++:)*+\w++)\)%}', $file, $envVars); - $envVars = array_unique($envVars[1]); - - $bag = $container->getParameterBag(); - $getDefaultParameter = function (string $name) { - return parent::get($name); - }; - $getDefaultParameter = $getDefaultParameter->bindTo($bag, \get_class($bag)); - - $getEnvReflection = new \ReflectionMethod($container, 'getEnv'); - $getEnvReflection->setAccessible(true); - - $envs = []; - - foreach ($envVars as $env) { - $processor = 'string'; - if (false !== $i = strrpos($name = $env, ':')) { - $name = substr($env, $i + 1); - $processor = substr($env, 0, $i); - } - $defaultValue = ($hasDefault = $container->hasParameter("env($name)")) ? $getDefaultParameter("env($name)") : null; - if (false === ($runtimeValue = $_ENV[$name] ?? $_SERVER[$name] ?? getenv($name))) { - $runtimeValue = null; - } - $processedValue = ($hasRuntime = null !== $runtimeValue) || $hasDefault ? $getEnvReflection->invoke($container, $env) : null; - $envs["$name$processor"] = [ - 'name' => $name, - 'processor' => $processor, - 'default_available' => $hasDefault, - 'default_value' => $defaultValue, - 'runtime_available' => $hasRuntime, - 'runtime_value' => $runtimeValue, - 'processed_value' => $processedValue, - ]; - } - ksort($envs); - - return array_values($envs); - } -} diff --git a/vendor/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php b/vendor/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php deleted file mode 100644 index 9d1e97d..0000000 --- a/vendor/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php +++ /dev/null @@ -1,420 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; - -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Jean-François Simon - * - * @internal - */ -class JsonDescriptor extends Descriptor -{ - /** - * {@inheritdoc} - */ - protected function describeRouteCollection(RouteCollection $routes, array $options = []) - { - $data = []; - foreach ($routes->all() as $name => $route) { - $data[$name] = $this->getRouteData($route); - } - - $this->writeData($data, $options); - } - - /** - * {@inheritdoc} - */ - protected function describeRoute(Route $route, array $options = []) - { - $this->writeData($this->getRouteData($route), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerParameters(ParameterBag $parameters, array $options = []) - { - $this->writeData($this->sortParameters($parameters), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerTags(ContainerBuilder $builder, array $options = []) - { - $showHidden = isset($options['show_hidden']) && $options['show_hidden']; - $data = []; - - foreach ($this->findDefinitionsByTag($builder, $showHidden) as $tag => $definitions) { - $data[$tag] = []; - foreach ($definitions as $definition) { - $data[$tag][] = $this->getContainerDefinitionData($definition, true); - } - } - - $this->writeData($data, $options); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerService($service, array $options = [], ContainerBuilder $builder = null) - { - if (!isset($options['id'])) { - throw new \InvalidArgumentException('An "id" option must be provided.'); - } - - if ($service instanceof Alias) { - $this->describeContainerAlias($service, $options, $builder); - } elseif ($service instanceof Definition) { - $this->writeData($this->getContainerDefinitionData($service, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments']), $options); - } else { - $this->writeData(\get_class($service), $options); - } - } - - /** - * {@inheritdoc} - */ - protected function describeContainerServices(ContainerBuilder $builder, array $options = []) - { - $serviceIds = isset($options['tag']) && $options['tag'] - ? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($options['tag'])) - : $this->sortServiceIds($builder->getServiceIds()); - $showHidden = isset($options['show_hidden']) && $options['show_hidden']; - $omitTags = isset($options['omit_tags']) && $options['omit_tags']; - $showArguments = isset($options['show_arguments']) && $options['show_arguments']; - $data = ['definitions' => [], 'aliases' => [], 'services' => []]; - - if (isset($options['filter'])) { - $serviceIds = array_filter($serviceIds, $options['filter']); - } - - foreach ($serviceIds as $serviceId) { - $service = $this->resolveServiceDefinition($builder, $serviceId); - - if ($showHidden xor '.' === ($serviceId[0] ?? null)) { - continue; - } - - if ($service instanceof Alias) { - $data['aliases'][$serviceId] = $this->getContainerAliasData($service); - } elseif ($service instanceof Definition) { - $data['definitions'][$serviceId] = $this->getContainerDefinitionData($service, $omitTags, $showArguments); - } else { - $data['services'][$serviceId] = \get_class($service); - } - } - - $this->writeData($data, $options); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerDefinition(Definition $definition, array $options = []) - { - $this->writeData($this->getContainerDefinitionData($definition, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments']), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null) - { - if (!$builder) { - $this->writeData($this->getContainerAliasData($alias), $options); - - return; - } - - $this->writeData( - [$this->getContainerAliasData($alias), $this->getContainerDefinitionData($builder->getDefinition((string) $alias), isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'])], - array_merge($options, ['id' => (string) $alias]) - ); - } - - /** - * {@inheritdoc} - */ - protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) - { - $this->writeData($this->getEventDispatcherListenersData($eventDispatcher, \array_key_exists('event', $options) ? $options['event'] : null), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeCallable($callable, array $options = []) - { - $this->writeData($this->getCallableData($callable), $options); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerParameter($parameter, array $options = []) - { - $key = isset($options['parameter']) ? $options['parameter'] : ''; - - $this->writeData([$key => $parameter], $options); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerEnvVars(array $envs, array $options = []) - { - throw new LogicException('Using the JSON format to debug environment variables is not supported.'); - } - - /** - * Writes data as json. - */ - private function writeData(array $data, array $options) - { - $flags = isset($options['json_encoding']) ? $options['json_encoding'] : 0; - - $this->write(json_encode($data, $flags | JSON_PRETTY_PRINT)."\n"); - } - - protected function getRouteData(Route $route): array - { - $data = [ - 'path' => $route->getPath(), - 'pathRegex' => $route->compile()->getRegex(), - 'host' => '' !== $route->getHost() ? $route->getHost() : 'ANY', - 'hostRegex' => '' !== $route->getHost() ? $route->compile()->getHostRegex() : '', - 'scheme' => $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY', - 'method' => $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY', - 'class' => \get_class($route), - 'defaults' => $route->getDefaults(), - 'requirements' => $route->getRequirements() ?: 'NO CUSTOM', - 'options' => $route->getOptions(), - ]; - - if ('' !== $route->getCondition()) { - $data['condition'] = $route->getCondition(); - } - - return $data; - } - - private function getContainerDefinitionData(Definition $definition, bool $omitTags = false, bool $showArguments = false): array - { - $data = [ - 'class' => (string) $definition->getClass(), - 'public' => $definition->isPublic() && !$definition->isPrivate(), - 'synthetic' => $definition->isSynthetic(), - 'lazy' => $definition->isLazy(), - 'shared' => $definition->isShared(), - 'abstract' => $definition->isAbstract(), - 'autowire' => $definition->isAutowired(), - 'autoconfigure' => $definition->isAutoconfigured(), - ]; - - if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) { - $data['description'] = $classDescription; - } - - if ($showArguments) { - $data['arguments'] = $this->describeValue($definition->getArguments(), $omitTags, $showArguments); - } - - $data['file'] = $definition->getFile(); - - if ($factory = $definition->getFactory()) { - if (\is_array($factory)) { - if ($factory[0] instanceof Reference) { - $data['factory_service'] = (string) $factory[0]; - } elseif ($factory[0] instanceof Definition) { - throw new \InvalidArgumentException('Factory is not describable.'); - } else { - $data['factory_class'] = $factory[0]; - } - $data['factory_method'] = $factory[1]; - } else { - $data['factory_function'] = $factory; - } - } - - $calls = $definition->getMethodCalls(); - if (\count($calls) > 0) { - $data['calls'] = []; - foreach ($calls as $callData) { - $data['calls'][] = $callData[0]; - } - } - - if (!$omitTags) { - $data['tags'] = []; - foreach ($this->sortTagsByPriority($definition->getTags()) as $tagName => $tagData) { - foreach ($tagData as $parameters) { - $data['tags'][] = ['name' => $tagName, 'parameters' => $parameters]; - } - } - } - - return $data; - } - - private function getContainerAliasData(Alias $alias): array - { - return [ - 'service' => (string) $alias, - 'public' => $alias->isPublic() && !$alias->isPrivate(), - ]; - } - - private function getEventDispatcherListenersData(EventDispatcherInterface $eventDispatcher, string $event = null): array - { - $data = []; - - $registeredListeners = $eventDispatcher->getListeners($event); - if (null !== $event) { - foreach ($registeredListeners as $listener) { - $l = $this->getCallableData($listener); - $l['priority'] = $eventDispatcher->getListenerPriority($event, $listener); - $data[] = $l; - } - } else { - ksort($registeredListeners); - - foreach ($registeredListeners as $eventListened => $eventListeners) { - foreach ($eventListeners as $eventListener) { - $l = $this->getCallableData($eventListener); - $l['priority'] = $eventDispatcher->getListenerPriority($eventListened, $eventListener); - $data[$eventListened][] = $l; - } - } - } - - return $data; - } - - private function getCallableData($callable): array - { - $data = []; - - if (\is_array($callable)) { - $data['type'] = 'function'; - - if (\is_object($callable[0])) { - $data['name'] = $callable[1]; - $data['class'] = \get_class($callable[0]); - } else { - if (0 !== strpos($callable[1], 'parent::')) { - $data['name'] = $callable[1]; - $data['class'] = $callable[0]; - $data['static'] = true; - } else { - $data['name'] = substr($callable[1], 8); - $data['class'] = $callable[0]; - $data['static'] = true; - $data['parent'] = true; - } - } - - return $data; - } - - if (\is_string($callable)) { - $data['type'] = 'function'; - - if (false === strpos($callable, '::')) { - $data['name'] = $callable; - } else { - $callableParts = explode('::', $callable); - - $data['name'] = $callableParts[1]; - $data['class'] = $callableParts[0]; - $data['static'] = true; - } - - return $data; - } - - if ($callable instanceof \Closure) { - $data['type'] = 'closure'; - - $r = new \ReflectionFunction($callable); - if (false !== strpos($r->name, '{closure}')) { - return $data; - } - $data['name'] = $r->name; - - if ($class = $r->getClosureScopeClass()) { - $data['class'] = $class->name; - if (!$r->getClosureThis()) { - $data['static'] = true; - } - } - - return $data; - } - - if (method_exists($callable, '__invoke')) { - $data['type'] = 'object'; - $data['name'] = \get_class($callable); - - return $data; - } - - throw new \InvalidArgumentException('Callable is not describable.'); - } - - private function describeValue($value, bool $omitTags, bool $showArguments) - { - if (\is_array($value)) { - $data = []; - foreach ($value as $k => $v) { - $data[$k] = $this->describeValue($v, $omitTags, $showArguments); - } - - return $data; - } - - if ($value instanceof ServiceClosureArgument) { - $value = $value->getValues()[0]; - } - - if ($value instanceof Reference) { - return [ - 'type' => 'service', - 'id' => (string) $value, - ]; - } - - if ($value instanceof ArgumentInterface) { - return $this->describeValue($value->getValues(), $omitTags, $showArguments); - } - - if ($value instanceof Definition) { - return $this->getContainerDefinitionData($value, $omitTags, $showArguments); - } - - return $value; - } -} diff --git a/vendor/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php b/vendor/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php deleted file mode 100644 index ab4f056..0000000 --- a/vendor/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php +++ /dev/null @@ -1,413 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; - -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Jean-François Simon - * - * @internal - */ -class MarkdownDescriptor extends Descriptor -{ - /** - * {@inheritdoc} - */ - protected function describeRouteCollection(RouteCollection $routes, array $options = []) - { - $first = true; - foreach ($routes->all() as $name => $route) { - if ($first) { - $first = false; - } else { - $this->write("\n\n"); - } - $this->describeRoute($route, ['name' => $name]); - } - $this->write("\n"); - } - - /** - * {@inheritdoc} - */ - protected function describeRoute(Route $route, array $options = []) - { - $output = '- Path: '.$route->getPath() - ."\n".'- Path Regex: '.$route->compile()->getRegex() - ."\n".'- Host: '.('' !== $route->getHost() ? $route->getHost() : 'ANY') - ."\n".'- Host Regex: '.('' !== $route->getHost() ? $route->compile()->getHostRegex() : '') - ."\n".'- Scheme: '.($route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY') - ."\n".'- Method: '.($route->getMethods() ? implode('|', $route->getMethods()) : 'ANY') - ."\n".'- Class: '.\get_class($route) - ."\n".'- Defaults: '.$this->formatRouterConfig($route->getDefaults()) - ."\n".'- Requirements: '.($route->getRequirements() ? $this->formatRouterConfig($route->getRequirements()) : 'NO CUSTOM') - ."\n".'- Options: '.$this->formatRouterConfig($route->getOptions()); - - if ('' !== $route->getCondition()) { - $output .= "\n".'- Condition: '.$route->getCondition(); - } - - $this->write(isset($options['name']) - ? $options['name']."\n".str_repeat('-', \strlen($options['name']))."\n\n".$output - : $output); - $this->write("\n"); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerParameters(ParameterBag $parameters, array $options = []) - { - $this->write("Container parameters\n====================\n"); - foreach ($this->sortParameters($parameters) as $key => $value) { - $this->write(sprintf("\n- `%s`: `%s`", $key, $this->formatParameter($value))); - } - } - - /** - * {@inheritdoc} - */ - protected function describeContainerTags(ContainerBuilder $builder, array $options = []) - { - $showHidden = isset($options['show_hidden']) && $options['show_hidden']; - $this->write("Container tags\n=============="); - - foreach ($this->findDefinitionsByTag($builder, $showHidden) as $tag => $definitions) { - $this->write("\n\n".$tag."\n".str_repeat('-', \strlen($tag))); - foreach ($definitions as $serviceId => $definition) { - $this->write("\n\n"); - $this->describeContainerDefinition($definition, ['omit_tags' => true, 'id' => $serviceId]); - } - } - } - - /** - * {@inheritdoc} - */ - protected function describeContainerService($service, array $options = [], ContainerBuilder $builder = null) - { - if (!isset($options['id'])) { - throw new \InvalidArgumentException('An "id" option must be provided.'); - } - - $childOptions = array_merge($options, ['id' => $options['id'], 'as_array' => true]); - - if ($service instanceof Alias) { - $this->describeContainerAlias($service, $childOptions, $builder); - } elseif ($service instanceof Definition) { - $this->describeContainerDefinition($service, $childOptions); - } else { - $this->write(sprintf('**`%s`:** `%s`', $options['id'], \get_class($service))); - } - } - - /** - * {@inheritdoc} - */ - protected function describeContainerServices(ContainerBuilder $builder, array $options = []) - { - $showHidden = isset($options['show_hidden']) && $options['show_hidden']; - - $title = $showHidden ? 'Hidden services' : 'Services'; - if (isset($options['tag'])) { - $title .= ' with tag `'.$options['tag'].'`'; - } - $this->write($title."\n".str_repeat('=', \strlen($title))); - - $serviceIds = isset($options['tag']) && $options['tag'] - ? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($options['tag'])) - : $this->sortServiceIds($builder->getServiceIds()); - $showArguments = isset($options['show_arguments']) && $options['show_arguments']; - $services = ['definitions' => [], 'aliases' => [], 'services' => []]; - - if (isset($options['filter'])) { - $serviceIds = array_filter($serviceIds, $options['filter']); - } - - foreach ($serviceIds as $serviceId) { - $service = $this->resolveServiceDefinition($builder, $serviceId); - - if ($showHidden xor '.' === ($serviceId[0] ?? null)) { - continue; - } - - if ($service instanceof Alias) { - $services['aliases'][$serviceId] = $service; - } elseif ($service instanceof Definition) { - $services['definitions'][$serviceId] = $service; - } else { - $services['services'][$serviceId] = $service; - } - } - - if (!empty($services['definitions'])) { - $this->write("\n\nDefinitions\n-----------\n"); - foreach ($services['definitions'] as $id => $service) { - $this->write("\n"); - $this->describeContainerDefinition($service, ['id' => $id, 'show_arguments' => $showArguments]); - } - } - - if (!empty($services['aliases'])) { - $this->write("\n\nAliases\n-------\n"); - foreach ($services['aliases'] as $id => $service) { - $this->write("\n"); - $this->describeContainerAlias($service, ['id' => $id]); - } - } - - if (!empty($services['services'])) { - $this->write("\n\nServices\n--------\n"); - foreach ($services['services'] as $id => $service) { - $this->write("\n"); - $this->write(sprintf('- `%s`: `%s`', $id, \get_class($service))); - } - } - } - - /** - * {@inheritdoc} - */ - protected function describeContainerDefinition(Definition $definition, array $options = []) - { - $output = ''; - - if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) { - $output .= '- Description: `'.$classDescription.'`'."\n"; - } - - $output .= '- Class: `'.$definition->getClass().'`' - ."\n".'- Public: '.($definition->isPublic() && !$definition->isPrivate() ? 'yes' : 'no') - ."\n".'- Synthetic: '.($definition->isSynthetic() ? 'yes' : 'no') - ."\n".'- Lazy: '.($definition->isLazy() ? 'yes' : 'no') - ."\n".'- Shared: '.($definition->isShared() ? 'yes' : 'no') - ."\n".'- Abstract: '.($definition->isAbstract() ? 'yes' : 'no') - ."\n".'- Autowired: '.($definition->isAutowired() ? 'yes' : 'no') - ."\n".'- Autoconfigured: '.($definition->isAutoconfigured() ? 'yes' : 'no') - ; - - if (isset($options['show_arguments']) && $options['show_arguments']) { - $output .= "\n".'- Arguments: '.($definition->getArguments() ? 'yes' : 'no'); - } - - if ($definition->getFile()) { - $output .= "\n".'- File: `'.$definition->getFile().'`'; - } - - if ($factory = $definition->getFactory()) { - if (\is_array($factory)) { - if ($factory[0] instanceof Reference) { - $output .= "\n".'- Factory Service: `'.$factory[0].'`'; - } elseif ($factory[0] instanceof Definition) { - throw new \InvalidArgumentException('Factory is not describable.'); - } else { - $output .= "\n".'- Factory Class: `'.$factory[0].'`'; - } - $output .= "\n".'- Factory Method: `'.$factory[1].'`'; - } else { - $output .= "\n".'- Factory Function: `'.$factory.'`'; - } - } - - $calls = $definition->getMethodCalls(); - foreach ($calls as $callData) { - $output .= "\n".'- Call: `'.$callData[0].'`'; - } - - if (!(isset($options['omit_tags']) && $options['omit_tags'])) { - foreach ($this->sortTagsByPriority($definition->getTags()) as $tagName => $tagData) { - foreach ($tagData as $parameters) { - $output .= "\n".'- Tag: `'.$tagName.'`'; - foreach ($parameters as $name => $value) { - $output .= "\n".' - '.ucfirst($name).': '.$value; - } - } - } - } - - $this->write(isset($options['id']) ? sprintf("### %s\n\n%s\n", $options['id'], $output) : $output); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null) - { - $output = '- Service: `'.$alias.'`' - ."\n".'- Public: '.($alias->isPublic() && !$alias->isPrivate() ? 'yes' : 'no'); - - if (!isset($options['id'])) { - $this->write($output); - - return; - } - - $this->write(sprintf("### %s\n\n%s\n", $options['id'], $output)); - - if (!$builder) { - return; - } - - $this->write("\n"); - $this->describeContainerDefinition($builder->getDefinition((string) $alias), array_merge($options, ['id' => (string) $alias])); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerParameter($parameter, array $options = []) - { - $this->write(isset($options['parameter']) ? sprintf("%s\n%s\n\n%s", $options['parameter'], str_repeat('=', \strlen($options['parameter'])), $this->formatParameter($parameter)) : $parameter); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerEnvVars(array $envs, array $options = []) - { - throw new LogicException('Using the markdown format to debug environment variables is not supported.'); - } - - /** - * {@inheritdoc} - */ - protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) - { - $event = \array_key_exists('event', $options) ? $options['event'] : null; - - $title = 'Registered listeners'; - if (null !== $event) { - $title .= sprintf(' for event `%s` ordered by descending priority', $event); - } - - $this->write(sprintf('# %s', $title)."\n"); - - $registeredListeners = $eventDispatcher->getListeners($event); - if (null !== $event) { - foreach ($registeredListeners as $order => $listener) { - $this->write("\n".sprintf('## Listener %d', $order + 1)."\n"); - $this->describeCallable($listener); - $this->write(sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($event, $listener))."\n"); - } - } else { - ksort($registeredListeners); - - foreach ($registeredListeners as $eventListened => $eventListeners) { - $this->write("\n".sprintf('## %s', $eventListened)."\n"); - - foreach ($eventListeners as $order => $eventListener) { - $this->write("\n".sprintf('### Listener %d', $order + 1)."\n"); - $this->describeCallable($eventListener); - $this->write(sprintf('- Priority: `%d`', $eventDispatcher->getListenerPriority($eventListened, $eventListener))."\n"); - } - } - } - } - - /** - * {@inheritdoc} - */ - protected function describeCallable($callable, array $options = []) - { - $string = ''; - - if (\is_array($callable)) { - $string .= "\n- Type: `function`"; - - if (\is_object($callable[0])) { - $string .= "\n".sprintf('- Name: `%s`', $callable[1]); - $string .= "\n".sprintf('- Class: `%s`', \get_class($callable[0])); - } else { - if (0 !== strpos($callable[1], 'parent::')) { - $string .= "\n".sprintf('- Name: `%s`', $callable[1]); - $string .= "\n".sprintf('- Class: `%s`', $callable[0]); - $string .= "\n- Static: yes"; - } else { - $string .= "\n".sprintf('- Name: `%s`', substr($callable[1], 8)); - $string .= "\n".sprintf('- Class: `%s`', $callable[0]); - $string .= "\n- Static: yes"; - $string .= "\n- Parent: yes"; - } - } - - return $this->write($string."\n"); - } - - if (\is_string($callable)) { - $string .= "\n- Type: `function`"; - - if (false === strpos($callable, '::')) { - $string .= "\n".sprintf('- Name: `%s`', $callable); - } else { - $callableParts = explode('::', $callable); - - $string .= "\n".sprintf('- Name: `%s`', $callableParts[1]); - $string .= "\n".sprintf('- Class: `%s`', $callableParts[0]); - $string .= "\n- Static: yes"; - } - - return $this->write($string."\n"); - } - - if ($callable instanceof \Closure) { - $string .= "\n- Type: `closure`"; - - $r = new \ReflectionFunction($callable); - if (false !== strpos($r->name, '{closure}')) { - return $this->write($string."\n"); - } - $string .= "\n".sprintf('- Name: `%s`', $r->name); - - if ($class = $r->getClosureScopeClass()) { - $string .= "\n".sprintf('- Class: `%s`', $class->name); - if (!$r->getClosureThis()) { - $string .= "\n- Static: yes"; - } - } - - return $this->write($string."\n"); - } - - if (method_exists($callable, '__invoke')) { - $string .= "\n- Type: `object`"; - $string .= "\n".sprintf('- Name: `%s`', \get_class($callable)); - - return $this->write($string."\n"); - } - - throw new \InvalidArgumentException('Callable is not describable.'); - } - - private function formatRouterConfig(array $array): string - { - if (!$array) { - return 'NONE'; - } - - $string = ''; - ksort($array); - foreach ($array as $name => $value) { - $string .= "\n".' - `'.$name.'`: '.$this->formatValue($value); - } - - return $string; - } -} diff --git a/vendor/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php b/vendor/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php deleted file mode 100644 index 37e2117..0000000 --- a/vendor/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php +++ /dev/null @@ -1,608 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; - -use Symfony\Component\Console\Formatter\OutputFormatter; -use Symfony\Component\Console\Helper\Dumper; -use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Jean-François Simon - * - * @internal - */ -class TextDescriptor extends Descriptor -{ - private $fileLinkFormatter; - - public function __construct(FileLinkFormatter $fileLinkFormatter = null) - { - $this->fileLinkFormatter = $fileLinkFormatter; - } - - /** - * {@inheritdoc} - */ - protected function describeRouteCollection(RouteCollection $routes, array $options = []) - { - $showControllers = isset($options['show_controllers']) && $options['show_controllers']; - - $tableHeaders = ['Name', 'Method', 'Scheme', 'Host', 'Path']; - if ($showControllers) { - $tableHeaders[] = 'Controller'; - } - - $tableRows = []; - foreach ($routes->all() as $name => $route) { - $controller = $route->getDefault('_controller'); - - $row = [ - $name, - $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY', - $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY', - '' !== $route->getHost() ? $route->getHost() : 'ANY', - $this->formatControllerLink($controller, $route->getPath()), - ]; - - if ($showControllers) { - $row[] = $controller ? $this->formatControllerLink($controller, $this->formatCallable($controller)) : ''; - } - - $tableRows[] = $row; - } - - if (isset($options['output'])) { - $options['output']->table($tableHeaders, $tableRows); - } else { - $table = new Table($this->getOutput()); - $table->setHeaders($tableHeaders)->setRows($tableRows); - $table->render(); - } - } - - /** - * {@inheritdoc} - */ - protected function describeRoute(Route $route, array $options = []) - { - $tableHeaders = ['Property', 'Value']; - $tableRows = [ - ['Route Name', isset($options['name']) ? $options['name'] : ''], - ['Path', $route->getPath()], - ['Path Regex', $route->compile()->getRegex()], - ['Host', ('' !== $route->getHost() ? $route->getHost() : 'ANY')], - ['Host Regex', ('' !== $route->getHost() ? $route->compile()->getHostRegex() : '')], - ['Scheme', ($route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY')], - ['Method', ($route->getMethods() ? implode('|', $route->getMethods()) : 'ANY')], - ['Requirements', ($route->getRequirements() ? $this->formatRouterConfig($route->getRequirements()) : 'NO CUSTOM')], - ['Class', \get_class($route)], - ['Defaults', $this->formatRouterConfig($route->getDefaults())], - ['Options', $this->formatRouterConfig($route->getOptions())], - ]; - - if ('' !== $route->getCondition()) { - $tableRows[] = ['Condition', $route->getCondition()]; - } - - $table = new Table($this->getOutput()); - $table->setHeaders($tableHeaders)->setRows($tableRows); - $table->render(); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerParameters(ParameterBag $parameters, array $options = []) - { - $tableHeaders = ['Parameter', 'Value']; - - $tableRows = []; - foreach ($this->sortParameters($parameters) as $parameter => $value) { - $tableRows[] = [$parameter, $this->formatParameter($value)]; - } - - $options['output']->title('Symfony Container Parameters'); - $options['output']->table($tableHeaders, $tableRows); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerTags(ContainerBuilder $builder, array $options = []) - { - $showHidden = isset($options['show_hidden']) && $options['show_hidden']; - - if ($showHidden) { - $options['output']->title('Symfony Container Hidden Tags'); - } else { - $options['output']->title('Symfony Container Tags'); - } - - foreach ($this->findDefinitionsByTag($builder, $showHidden) as $tag => $definitions) { - $options['output']->section(sprintf('"%s" tag', $tag)); - $options['output']->listing(array_keys($definitions)); - } - } - - /** - * {@inheritdoc} - */ - protected function describeContainerService($service, array $options = [], ContainerBuilder $builder = null) - { - if (!isset($options['id'])) { - throw new \InvalidArgumentException('An "id" option must be provided.'); - } - - if ($service instanceof Alias) { - $this->describeContainerAlias($service, $options, $builder); - } elseif ($service instanceof Definition) { - $this->describeContainerDefinition($service, $options); - } else { - $options['output']->title(sprintf('Information for Service "%s"', $options['id'])); - $options['output']->table( - ['Service ID', 'Class'], - [ - [isset($options['id']) ? $options['id'] : '-', \get_class($service)], - ] - ); - } - } - - /** - * {@inheritdoc} - */ - protected function describeContainerServices(ContainerBuilder $builder, array $options = []) - { - $showHidden = isset($options['show_hidden']) && $options['show_hidden']; - $showTag = isset($options['tag']) ? $options['tag'] : null; - - if ($showHidden) { - $title = 'Symfony Container Hidden Services'; - } else { - $title = 'Symfony Container Services'; - } - - if ($showTag) { - $title .= sprintf(' Tagged with "%s" Tag', $options['tag']); - } - - $options['output']->title($title); - - $serviceIds = isset($options['tag']) && $options['tag'] - ? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($options['tag'])) - : $this->sortServiceIds($builder->getServiceIds()); - $maxTags = []; - - if (isset($options['filter'])) { - $serviceIds = array_filter($serviceIds, $options['filter']); - } - - foreach ($serviceIds as $key => $serviceId) { - $definition = $this->resolveServiceDefinition($builder, $serviceId); - - // filter out hidden services unless shown explicitly - if ($showHidden xor '.' === ($serviceId[0] ?? null)) { - unset($serviceIds[$key]); - continue; - } - - if ($definition instanceof Definition) { - if ($showTag) { - $tags = $definition->getTag($showTag); - foreach ($tags as $tag) { - foreach ($tag as $key => $value) { - if (!isset($maxTags[$key])) { - $maxTags[$key] = \strlen($key); - } - if (\strlen($value) > $maxTags[$key]) { - $maxTags[$key] = \strlen($value); - } - } - } - } - } - } - - $tagsCount = \count($maxTags); - $tagsNames = array_keys($maxTags); - - $tableHeaders = array_merge(['Service ID'], $tagsNames, ['Class name']); - $tableRows = []; - $rawOutput = isset($options['raw_text']) && $options['raw_text']; - foreach ($serviceIds as $serviceId) { - $definition = $this->resolveServiceDefinition($builder, $serviceId); - - $styledServiceId = $rawOutput ? $serviceId : sprintf('%s', OutputFormatter::escape($serviceId)); - if ($definition instanceof Definition) { - if ($showTag) { - foreach ($this->sortByPriority($definition->getTag($showTag)) as $key => $tag) { - $tagValues = []; - foreach ($tagsNames as $tagName) { - $tagValues[] = isset($tag[$tagName]) ? $tag[$tagName] : ''; - } - if (0 === $key) { - $tableRows[] = array_merge([$serviceId], $tagValues, [$definition->getClass()]); - } else { - $tableRows[] = array_merge([' "'], $tagValues, ['']); - } - } - } else { - $tableRows[] = [$styledServiceId, $definition->getClass()]; - } - } elseif ($definition instanceof Alias) { - $alias = $definition; - $tableRows[] = array_merge([$styledServiceId, sprintf('alias for "%s"', $alias)], $tagsCount ? array_fill(0, $tagsCount, '') : []); - } else { - $tableRows[] = array_merge([$styledServiceId, \get_class($definition)], $tagsCount ? array_fill(0, $tagsCount, '') : []); - } - } - - $options['output']->table($tableHeaders, $tableRows); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerDefinition(Definition $definition, array $options = []) - { - if (isset($options['id'])) { - $options['output']->title(sprintf('Information for Service "%s"', $options['id'])); - } - - if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) { - $options['output']->text($classDescription."\n"); - } - - $tableHeaders = ['Option', 'Value']; - - $tableRows[] = ['Service ID', isset($options['id']) ? $options['id'] : '-']; - $tableRows[] = ['Class', $definition->getClass() ?: '-']; - - $omitTags = isset($options['omit_tags']) && $options['omit_tags']; - if (!$omitTags && ($tags = $definition->getTags())) { - $tagInformation = []; - foreach ($tags as $tagName => $tagData) { - foreach ($tagData as $tagParameters) { - $parameters = array_map(function ($key, $value) { - return sprintf('%s: %s', $key, $value); - }, array_keys($tagParameters), array_values($tagParameters)); - $parameters = implode(', ', $parameters); - - if ('' === $parameters) { - $tagInformation[] = sprintf('%s', $tagName); - } else { - $tagInformation[] = sprintf('%s (%s)', $tagName, $parameters); - } - } - } - $tagInformation = implode("\n", $tagInformation); - } else { - $tagInformation = '-'; - } - $tableRows[] = ['Tags', $tagInformation]; - - $calls = $definition->getMethodCalls(); - if (\count($calls) > 0) { - $callInformation = []; - foreach ($calls as $call) { - $callInformation[] = $call[0]; - } - $tableRows[] = ['Calls', implode(', ', $callInformation)]; - } - - $tableRows[] = ['Public', $definition->isPublic() && !$definition->isPrivate() ? 'yes' : 'no']; - $tableRows[] = ['Synthetic', $definition->isSynthetic() ? 'yes' : 'no']; - $tableRows[] = ['Lazy', $definition->isLazy() ? 'yes' : 'no']; - $tableRows[] = ['Shared', $definition->isShared() ? 'yes' : 'no']; - $tableRows[] = ['Abstract', $definition->isAbstract() ? 'yes' : 'no']; - $tableRows[] = ['Autowired', $definition->isAutowired() ? 'yes' : 'no']; - $tableRows[] = ['Autoconfigured', $definition->isAutoconfigured() ? 'yes' : 'no']; - - if ($definition->getFile()) { - $tableRows[] = ['Required File', $definition->getFile() ?: '-']; - } - - if ($factory = $definition->getFactory()) { - if (\is_array($factory)) { - if ($factory[0] instanceof Reference) { - $tableRows[] = ['Factory Service', $factory[0]]; - } elseif ($factory[0] instanceof Definition) { - throw new \InvalidArgumentException('Factory is not describable.'); - } else { - $tableRows[] = ['Factory Class', $factory[0]]; - } - $tableRows[] = ['Factory Method', $factory[1]]; - } else { - $tableRows[] = ['Factory Function', $factory]; - } - } - - $showArguments = isset($options['show_arguments']) && $options['show_arguments']; - $argumentsInformation = []; - if ($showArguments && ($arguments = $definition->getArguments())) { - foreach ($arguments as $argument) { - if ($argument instanceof ServiceClosureArgument) { - $argument = $argument->getValues()[0]; - } - if ($argument instanceof Reference) { - $argumentsInformation[] = sprintf('Service(%s)', (string) $argument); - } elseif ($argument instanceof IteratorArgument) { - if ($argument instanceof TaggedIteratorArgument) { - $argumentsInformation[] = sprintf('Tagged Iterator for "%s"%s', $argument->getTag(), $options['is_debug'] ? '' : sprintf(' (%d element(s))', \count($argument->getValues()))); - } else { - $argumentsInformation[] = sprintf('Iterator (%d element(s))', \count($argument->getValues())); - } - - foreach ($argument->getValues() as $ref) { - $argumentsInformation[] = sprintf('- Service(%s)', $ref); - } - } elseif ($argument instanceof ServiceLocatorArgument) { - $argumentsInformation[] = sprintf('Service locator (%d element(s))', \count($argument->getValues())); - } elseif ($argument instanceof Definition) { - $argumentsInformation[] = 'Inlined Service'; - } else { - $argumentsInformation[] = \is_array($argument) ? sprintf('Array (%d element(s))', \count($argument)) : $argument; - } - } - - $tableRows[] = ['Arguments', implode("\n", $argumentsInformation)]; - } - - $options['output']->table($tableHeaders, $tableRows); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null) - { - if ($alias->isPublic()) { - $options['output']->comment(sprintf('This service is a public alias for the service %s', (string) $alias)); - } else { - $options['output']->comment(sprintf('This service is a private alias for the service %s', (string) $alias)); - } - - if (!$builder) { - return; - } - - $this->describeContainerDefinition($builder->getDefinition((string) $alias), array_merge($options, ['id' => (string) $alias])); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerParameter($parameter, array $options = []) - { - $options['output']->table( - ['Parameter', 'Value'], - [ - [$options['parameter'], $this->formatParameter($parameter), - ], - ]); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerEnvVars(array $envs, array $options = []) - { - $dump = new Dumper($this->output); - $options['output']->title('Symfony Container Environment Variables'); - - if (null !== $name = $options['name'] ?? null) { - $options['output']->comment('Displaying detailed environment variable usage matching '.$name); - - $matches = false; - foreach ($envs as $env) { - if ($name === $env['name'] || false !== stripos($env['name'], $name)) { - $matches = true; - $options['output']->section('%env('.$env['processor'].':'.$env['name'].')%'); - $options['output']->table([], [ - ['Default value', $env['default_available'] ? $dump($env['default_value']) : 'n/a'], - ['Real value', $env['runtime_available'] ? $dump($env['runtime_value']) : 'n/a'], - ['Processed value', $env['default_available'] || $env['runtime_available'] ? $dump($env['processed_value']) : 'n/a'], - ]); - } - } - - if (!$matches) { - $options['output']->block('None of the environment variables match this name.'); - } else { - $options['output']->comment('Note real values might be different between web and CLI.'); - } - - return; - } - - if (!$envs) { - $options['output']->block('No environment variables are being used.'); - - return; - } - - $rows = []; - $missing = []; - foreach ($envs as $env) { - if (isset($rows[$env['name']])) { - continue; - } - - $rows[$env['name']] = [ - $env['name'], - $env['default_available'] ? $dump($env['default_value']) : 'n/a', - $env['runtime_available'] ? $dump($env['runtime_value']) : 'n/a', - ]; - if (!$env['default_available'] && !$env['runtime_available']) { - $missing[$env['name']] = true; - } - } - - $options['output']->table(['Name', 'Default value', 'Real value'], $rows); - $options['output']->comment('Note real values might be different between web and CLI.'); - - if ($missing) { - $options['output']->warning('The following variables are missing:'); - $options['output']->listing(array_keys($missing)); - } - } - - /** - * {@inheritdoc} - */ - protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) - { - $event = \array_key_exists('event', $options) ? $options['event'] : null; - - if (null !== $event) { - $title = sprintf('Registered Listeners for "%s" Event', $event); - } else { - $title = 'Registered Listeners Grouped by Event'; - } - - $options['output']->title($title); - - $registeredListeners = $eventDispatcher->getListeners($event); - if (null !== $event) { - $this->renderEventListenerTable($eventDispatcher, $event, $registeredListeners, $options['output']); - } else { - ksort($registeredListeners); - foreach ($registeredListeners as $eventListened => $eventListeners) { - $options['output']->section(sprintf('"%s" event', $eventListened)); - $this->renderEventListenerTable($eventDispatcher, $eventListened, $eventListeners, $options['output']); - } - } - } - - /** - * {@inheritdoc} - */ - protected function describeCallable($callable, array $options = []) - { - $this->writeText($this->formatCallable($callable), $options); - } - - private function renderEventListenerTable(EventDispatcherInterface $eventDispatcher, string $event, array $eventListeners, SymfonyStyle $io) - { - $tableHeaders = ['Order', 'Callable', 'Priority']; - $tableRows = []; - - foreach ($eventListeners as $order => $listener) { - $tableRows[] = [sprintf('#%d', $order + 1), $this->formatCallable($listener), $eventDispatcher->getListenerPriority($event, $listener)]; - } - - $io->table($tableHeaders, $tableRows); - } - - private function formatRouterConfig(array $config): string - { - if (empty($config)) { - return 'NONE'; - } - - ksort($config); - - $configAsString = ''; - foreach ($config as $key => $value) { - $configAsString .= sprintf("\n%s: %s", $key, $this->formatValue($value)); - } - - return trim($configAsString); - } - - private function formatControllerLink($controller, string $anchorText): string - { - if (null === $this->fileLinkFormatter) { - return $anchorText; - } - - try { - if (\is_array($controller)) { - $r = new \ReflectionMethod($controller[0], $controller[1]); - } elseif ($controller instanceof \Closure) { - $r = new \ReflectionFunction($controller); - } elseif (method_exists($controller, '__invoke')) { - $r = new \ReflectionMethod($controller, '__invoke'); - } elseif (!\is_string($controller)) { - return $anchorText; - } elseif (false !== strpos($controller, '::')) { - $r = new \ReflectionMethod($controller); - } else { - $r = new \ReflectionFunction($controller); - } - } catch (\ReflectionException $e) { - return $anchorText; - } - - $fileLink = $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine()); - if ($fileLink) { - return sprintf('%s', $fileLink, $anchorText); - } - - return $anchorText; - } - - private function formatCallable($callable): string - { - if (\is_array($callable)) { - if (\is_object($callable[0])) { - return sprintf('%s::%s()', \get_class($callable[0]), $callable[1]); - } - - return sprintf('%s::%s()', $callable[0], $callable[1]); - } - - if (\is_string($callable)) { - return sprintf('%s()', $callable); - } - - if ($callable instanceof \Closure) { - $r = new \ReflectionFunction($callable); - if (false !== strpos($r->name, '{closure}')) { - return 'Closure()'; - } - if ($class = $r->getClosureScopeClass()) { - return sprintf('%s::%s()', $class->name, $r->name); - } - - return $r->name.'()'; - } - - if (method_exists($callable, '__invoke')) { - return sprintf('%s::__invoke()', \get_class($callable)); - } - - throw new \InvalidArgumentException('Callable is not describable.'); - } - - private function writeText(string $content, array $options = []) - { - $this->write( - isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, - isset($options['raw_output']) ? !$options['raw_output'] : true - ); - } -} diff --git a/vendor/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php b/vendor/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php deleted file mode 100644 index 16e79f4..0000000 --- a/vendor/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php +++ /dev/null @@ -1,570 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; - -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Jean-François Simon - * - * @internal - */ -class XmlDescriptor extends Descriptor -{ - /** - * {@inheritdoc} - */ - protected function describeRouteCollection(RouteCollection $routes, array $options = []) - { - $this->writeDocument($this->getRouteCollectionDocument($routes)); - } - - /** - * {@inheritdoc} - */ - protected function describeRoute(Route $route, array $options = []) - { - $this->writeDocument($this->getRouteDocument($route, isset($options['name']) ? $options['name'] : null)); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerParameters(ParameterBag $parameters, array $options = []) - { - $this->writeDocument($this->getContainerParametersDocument($parameters)); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerTags(ContainerBuilder $builder, array $options = []) - { - $this->writeDocument($this->getContainerTagsDocument($builder, isset($options['show_hidden']) && $options['show_hidden'])); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerService($service, array $options = [], ContainerBuilder $builder = null) - { - if (!isset($options['id'])) { - throw new \InvalidArgumentException('An "id" option must be provided.'); - } - - $this->writeDocument($this->getContainerServiceDocument($service, $options['id'], $builder, isset($options['show_arguments']) && $options['show_arguments'])); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerServices(ContainerBuilder $builder, array $options = []) - { - $this->writeDocument($this->getContainerServicesDocument($builder, isset($options['tag']) ? $options['tag'] : null, isset($options['show_hidden']) && $options['show_hidden'], isset($options['show_arguments']) && $options['show_arguments'], isset($options['filter']) ? $options['filter'] : null)); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerDefinition(Definition $definition, array $options = []) - { - $this->writeDocument($this->getContainerDefinitionDocument($definition, isset($options['id']) ? $options['id'] : null, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'])); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null) - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($dom->importNode($this->getContainerAliasDocument($alias, isset($options['id']) ? $options['id'] : null)->childNodes->item(0), true)); - - if (!$builder) { - $this->writeDocument($dom); - - return; - } - - $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($builder->getDefinition((string) $alias), (string) $alias)->childNodes->item(0), true)); - - $this->writeDocument($dom); - } - - /** - * {@inheritdoc} - */ - protected function describeEventDispatcherListeners(EventDispatcherInterface $eventDispatcher, array $options = []) - { - $this->writeDocument($this->getEventDispatcherListenersDocument($eventDispatcher, \array_key_exists('event', $options) ? $options['event'] : null)); - } - - /** - * {@inheritdoc} - */ - protected function describeCallable($callable, array $options = []) - { - $this->writeDocument($this->getCallableDocument($callable)); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerParameter($parameter, array $options = []) - { - $this->writeDocument($this->getContainerParameterDocument($parameter, $options)); - } - - /** - * {@inheritdoc} - */ - protected function describeContainerEnvVars(array $envs, array $options = []) - { - throw new LogicException('Using the XML format to debug environment variables is not supported.'); - } - - /** - * Writes DOM document. - */ - private function writeDocument(\DOMDocument $dom) - { - $dom->formatOutput = true; - $this->write($dom->saveXML()); - } - - private function getRouteCollectionDocument(RouteCollection $routes): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($routesXML = $dom->createElement('routes')); - - foreach ($routes->all() as $name => $route) { - $routeXML = $this->getRouteDocument($route, $name); - $routesXML->appendChild($routesXML->ownerDocument->importNode($routeXML->childNodes->item(0), true)); - } - - return $dom; - } - - private function getRouteDocument(Route $route, string $name = null): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($routeXML = $dom->createElement('route')); - - if ($name) { - $routeXML->setAttribute('name', $name); - } - - $routeXML->setAttribute('class', \get_class($route)); - - $routeXML->appendChild($pathXML = $dom->createElement('path')); - $pathXML->setAttribute('regex', $route->compile()->getRegex()); - $pathXML->appendChild(new \DOMText($route->getPath())); - - if ('' !== $route->getHost()) { - $routeXML->appendChild($hostXML = $dom->createElement('host')); - $hostXML->setAttribute('regex', $route->compile()->getHostRegex()); - $hostXML->appendChild(new \DOMText($route->getHost())); - } - - foreach ($route->getSchemes() as $scheme) { - $routeXML->appendChild($schemeXML = $dom->createElement('scheme')); - $schemeXML->appendChild(new \DOMText($scheme)); - } - - foreach ($route->getMethods() as $method) { - $routeXML->appendChild($methodXML = $dom->createElement('method')); - $methodXML->appendChild(new \DOMText($method)); - } - - if ($route->getDefaults()) { - $routeXML->appendChild($defaultsXML = $dom->createElement('defaults')); - foreach ($route->getDefaults() as $attribute => $value) { - $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); - $defaultXML->setAttribute('key', $attribute); - $defaultXML->appendChild(new \DOMText($this->formatValue($value))); - } - } - - $originRequirements = $requirements = $route->getRequirements(); - unset($requirements['_scheme'], $requirements['_method']); - if ($requirements) { - $routeXML->appendChild($requirementsXML = $dom->createElement('requirements')); - foreach ($originRequirements as $attribute => $pattern) { - $requirementsXML->appendChild($requirementXML = $dom->createElement('requirement')); - $requirementXML->setAttribute('key', $attribute); - $requirementXML->appendChild(new \DOMText($pattern)); - } - } - - if ($route->getOptions()) { - $routeXML->appendChild($optionsXML = $dom->createElement('options')); - foreach ($route->getOptions() as $name => $value) { - $optionsXML->appendChild($optionXML = $dom->createElement('option')); - $optionXML->setAttribute('key', $name); - $optionXML->appendChild(new \DOMText($this->formatValue($value))); - } - } - - if ('' !== $route->getCondition()) { - $routeXML->appendChild($conditionXML = $dom->createElement('condition')); - $conditionXML->appendChild(new \DOMText($route->getCondition())); - } - - return $dom; - } - - private function getContainerParametersDocument(ParameterBag $parameters): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($parametersXML = $dom->createElement('parameters')); - - foreach ($this->sortParameters($parameters) as $key => $value) { - $parametersXML->appendChild($parameterXML = $dom->createElement('parameter')); - $parameterXML->setAttribute('key', $key); - $parameterXML->appendChild(new \DOMText($this->formatParameter($value))); - } - - return $dom; - } - - private function getContainerTagsDocument(ContainerBuilder $builder, bool $showHidden = false): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($containerXML = $dom->createElement('container')); - - foreach ($this->findDefinitionsByTag($builder, $showHidden) as $tag => $definitions) { - $containerXML->appendChild($tagXML = $dom->createElement('tag')); - $tagXML->setAttribute('name', $tag); - - foreach ($definitions as $serviceId => $definition) { - $definitionXML = $this->getContainerDefinitionDocument($definition, $serviceId, true); - $tagXML->appendChild($dom->importNode($definitionXML->childNodes->item(0), true)); - } - } - - return $dom; - } - - private function getContainerServiceDocument($service, string $id, ContainerBuilder $builder = null, bool $showArguments = false): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - - if ($service instanceof Alias) { - $dom->appendChild($dom->importNode($this->getContainerAliasDocument($service, $id)->childNodes->item(0), true)); - if ($builder) { - $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($builder->getDefinition((string) $service), (string) $service, false, $showArguments)->childNodes->item(0), true)); - } - } elseif ($service instanceof Definition) { - $dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($service, $id, false, $showArguments)->childNodes->item(0), true)); - } else { - $dom->appendChild($serviceXML = $dom->createElement('service')); - $serviceXML->setAttribute('id', $id); - $serviceXML->setAttribute('class', \get_class($service)); - } - - return $dom; - } - - private function getContainerServicesDocument(ContainerBuilder $builder, string $tag = null, bool $showHidden = false, bool $showArguments = false, callable $filter = null): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($containerXML = $dom->createElement('container')); - - $serviceIds = $tag - ? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($tag)) - : $this->sortServiceIds($builder->getServiceIds()); - if ($filter) { - $serviceIds = array_filter($serviceIds, $filter); - } - - foreach ($serviceIds as $serviceId) { - $service = $this->resolveServiceDefinition($builder, $serviceId); - - if ($showHidden xor '.' === ($serviceId[0] ?? null)) { - continue; - } - - $serviceXML = $this->getContainerServiceDocument($service, $serviceId, null, $showArguments); - $containerXML->appendChild($containerXML->ownerDocument->importNode($serviceXML->childNodes->item(0), true)); - } - - return $dom; - } - - private function getContainerDefinitionDocument(Definition $definition, string $id = null, bool $omitTags = false, bool $showArguments = false): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($serviceXML = $dom->createElement('definition')); - - if ($id) { - $serviceXML->setAttribute('id', $id); - } - - if ('' !== $classDescription = $this->getClassDescription((string) $definition->getClass())) { - $serviceXML->appendChild($descriptionXML = $dom->createElement('description')); - $descriptionXML->appendChild($dom->createCDATASection($classDescription)); - } - - $serviceXML->setAttribute('class', $definition->getClass()); - - if ($factory = $definition->getFactory()) { - $serviceXML->appendChild($factoryXML = $dom->createElement('factory')); - - if (\is_array($factory)) { - if ($factory[0] instanceof Reference) { - $factoryXML->setAttribute('service', (string) $factory[0]); - } elseif ($factory[0] instanceof Definition) { - throw new \InvalidArgumentException('Factory is not describable.'); - } else { - $factoryXML->setAttribute('class', $factory[0]); - } - $factoryXML->setAttribute('method', $factory[1]); - } else { - $factoryXML->setAttribute('function', $factory); - } - } - - $serviceXML->setAttribute('public', $definition->isPublic() && !$definition->isPrivate() ? 'true' : 'false'); - $serviceXML->setAttribute('synthetic', $definition->isSynthetic() ? 'true' : 'false'); - $serviceXML->setAttribute('lazy', $definition->isLazy() ? 'true' : 'false'); - $serviceXML->setAttribute('shared', $definition->isShared() ? 'true' : 'false'); - $serviceXML->setAttribute('abstract', $definition->isAbstract() ? 'true' : 'false'); - $serviceXML->setAttribute('autowired', $definition->isAutowired() ? 'true' : 'false'); - $serviceXML->setAttribute('autoconfigured', $definition->isAutoconfigured() ? 'true' : 'false'); - $serviceXML->setAttribute('file', $definition->getFile()); - - $calls = $definition->getMethodCalls(); - if (\count($calls) > 0) { - $serviceXML->appendChild($callsXML = $dom->createElement('calls')); - foreach ($calls as $callData) { - $callsXML->appendChild($callXML = $dom->createElement('call')); - $callXML->setAttribute('method', $callData[0]); - if ($callData[2] ?? false) { - $callXML->setAttribute('returns-clone', 'true'); - } - } - } - - if ($showArguments) { - foreach ($this->getArgumentNodes($definition->getArguments(), $dom) as $node) { - $serviceXML->appendChild($node); - } - } - - if (!$omitTags) { - if ($tags = $this->sortTagsByPriority($definition->getTags())) { - $serviceXML->appendChild($tagsXML = $dom->createElement('tags')); - foreach ($tags as $tagName => $tagData) { - foreach ($tagData as $parameters) { - $tagsXML->appendChild($tagXML = $dom->createElement('tag')); - $tagXML->setAttribute('name', $tagName); - foreach ($parameters as $name => $value) { - $tagXML->appendChild($parameterXML = $dom->createElement('parameter')); - $parameterXML->setAttribute('name', $name); - $parameterXML->appendChild(new \DOMText($this->formatParameter($value))); - } - } - } - } - } - - return $dom; - } - - /** - * @return \DOMNode[] - */ - private function getArgumentNodes(array $arguments, \DOMDocument $dom): array - { - $nodes = []; - - foreach ($arguments as $argumentKey => $argument) { - $argumentXML = $dom->createElement('argument'); - - if (\is_string($argumentKey)) { - $argumentXML->setAttribute('key', $argumentKey); - } - - if ($argument instanceof ServiceClosureArgument) { - $argument = $argument->getValues()[0]; - } - - if ($argument instanceof Reference) { - $argumentXML->setAttribute('type', 'service'); - $argumentXML->setAttribute('id', (string) $argument); - } elseif ($argument instanceof IteratorArgument || $argument instanceof ServiceLocatorArgument) { - $argumentXML->setAttribute('type', $argument instanceof IteratorArgument ? 'iterator' : 'service_locator'); - - foreach ($this->getArgumentNodes($argument->getValues(), $dom) as $childArgumentXML) { - $argumentXML->appendChild($childArgumentXML); - } - } elseif ($argument instanceof Definition) { - $argumentXML->appendChild($dom->importNode($this->getContainerDefinitionDocument($argument, null, false, true)->childNodes->item(0), true)); - } elseif (\is_array($argument)) { - $argumentXML->setAttribute('type', 'collection'); - - foreach ($this->getArgumentNodes($argument, $dom) as $childArgumenXML) { - $argumentXML->appendChild($childArgumenXML); - } - } else { - $argumentXML->appendChild(new \DOMText($argument)); - } - - $nodes[] = $argumentXML; - } - - return $nodes; - } - - private function getContainerAliasDocument(Alias $alias, string $id = null): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($aliasXML = $dom->createElement('alias')); - - if ($id) { - $aliasXML->setAttribute('id', $id); - } - - $aliasXML->setAttribute('service', (string) $alias); - $aliasXML->setAttribute('public', $alias->isPublic() && !$alias->isPrivate() ? 'true' : 'false'); - - return $dom; - } - - private function getContainerParameterDocument($parameter, array $options = []): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($parameterXML = $dom->createElement('parameter')); - - if (isset($options['parameter'])) { - $parameterXML->setAttribute('key', $options['parameter']); - } - - $parameterXML->appendChild(new \DOMText($this->formatParameter($parameter))); - - return $dom; - } - - private function getEventDispatcherListenersDocument(EventDispatcherInterface $eventDispatcher, string $event = null): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($eventDispatcherXML = $dom->createElement('event-dispatcher')); - - $registeredListeners = $eventDispatcher->getListeners($event); - if (null !== $event) { - $this->appendEventListenerDocument($eventDispatcher, $event, $eventDispatcherXML, $registeredListeners); - } else { - ksort($registeredListeners); - - foreach ($registeredListeners as $eventListened => $eventListeners) { - $eventDispatcherXML->appendChild($eventXML = $dom->createElement('event')); - $eventXML->setAttribute('name', $eventListened); - - $this->appendEventListenerDocument($eventDispatcher, $eventListened, $eventXML, $eventListeners); - } - } - - return $dom; - } - - private function appendEventListenerDocument(EventDispatcherInterface $eventDispatcher, string $event, \DOMElement $element, array $eventListeners) - { - foreach ($eventListeners as $listener) { - $callableXML = $this->getCallableDocument($listener); - $callableXML->childNodes->item(0)->setAttribute('priority', $eventDispatcher->getListenerPriority($event, $listener)); - - $element->appendChild($element->ownerDocument->importNode($callableXML->childNodes->item(0), true)); - } - } - - private function getCallableDocument($callable): \DOMDocument - { - $dom = new \DOMDocument('1.0', 'UTF-8'); - $dom->appendChild($callableXML = $dom->createElement('callable')); - - if (\is_array($callable)) { - $callableXML->setAttribute('type', 'function'); - - if (\is_object($callable[0])) { - $callableXML->setAttribute('name', $callable[1]); - $callableXML->setAttribute('class', \get_class($callable[0])); - } else { - if (0 !== strpos($callable[1], 'parent::')) { - $callableXML->setAttribute('name', $callable[1]); - $callableXML->setAttribute('class', $callable[0]); - $callableXML->setAttribute('static', 'true'); - } else { - $callableXML->setAttribute('name', substr($callable[1], 8)); - $callableXML->setAttribute('class', $callable[0]); - $callableXML->setAttribute('static', 'true'); - $callableXML->setAttribute('parent', 'true'); - } - } - - return $dom; - } - - if (\is_string($callable)) { - $callableXML->setAttribute('type', 'function'); - - if (false === strpos($callable, '::')) { - $callableXML->setAttribute('name', $callable); - } else { - $callableParts = explode('::', $callable); - - $callableXML->setAttribute('name', $callableParts[1]); - $callableXML->setAttribute('class', $callableParts[0]); - $callableXML->setAttribute('static', 'true'); - } - - return $dom; - } - - if ($callable instanceof \Closure) { - $callableXML->setAttribute('type', 'closure'); - - $r = new \ReflectionFunction($callable); - if (false !== strpos($r->name, '{closure}')) { - return $dom; - } - $callableXML->setAttribute('name', $r->name); - - if ($class = $r->getClosureScopeClass()) { - $callableXML->setAttribute('class', $class->name); - if (!$r->getClosureThis()) { - $callableXML->setAttribute('static', 'true'); - } - } - - return $dom; - } - - if (method_exists($callable, '__invoke')) { - $callableXML->setAttribute('type', 'object'); - $callableXML->setAttribute('name', \get_class($callable)); - - return $dom; - } - - throw new \InvalidArgumentException('Callable is not describable.'); - } -} diff --git a/vendor/symfony/framework-bundle/Console/Helper/DescriptorHelper.php b/vendor/symfony/framework-bundle/Console/Helper/DescriptorHelper.php deleted file mode 100644 index 1f17c99..0000000 --- a/vendor/symfony/framework-bundle/Console/Helper/DescriptorHelper.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Console\Helper; - -use Symfony\Bundle\FrameworkBundle\Console\Descriptor\JsonDescriptor; -use Symfony\Bundle\FrameworkBundle\Console\Descriptor\MarkdownDescriptor; -use Symfony\Bundle\FrameworkBundle\Console\Descriptor\TextDescriptor; -use Symfony\Bundle\FrameworkBundle\Console\Descriptor\XmlDescriptor; -use Symfony\Component\Console\Helper\DescriptorHelper as BaseDescriptorHelper; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; - -/** - * @author Jean-François Simon - * - * @internal - */ -class DescriptorHelper extends BaseDescriptorHelper -{ - public function __construct(FileLinkFormatter $fileLinkFormatter = null) - { - $this - ->register('txt', new TextDescriptor($fileLinkFormatter)) - ->register('xml', new XmlDescriptor()) - ->register('json', new JsonDescriptor()) - ->register('md', new MarkdownDescriptor()) - ; - } -} diff --git a/vendor/symfony/framework-bundle/Controller/AbstractController.php b/vendor/symfony/framework-bundle/Controller/AbstractController.php deleted file mode 100644 index 20f420c..0000000 --- a/vendor/symfony/framework-bundle/Controller/AbstractController.php +++ /dev/null @@ -1,427 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Controller; - -use Doctrine\Persistence\ManagerRegistry; -use Psr\Container\ContainerInterface; -use Psr\Link\LinkInterface; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; -use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface; -use Symfony\Component\Form\Extension\Core\Type\FormType; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormFactoryInterface; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\HttpFoundation\BinaryFileResponse; -use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpFoundation\RedirectResponse; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\ResponseHeaderBag; -use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpFoundation\StreamedResponse; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\Messenger\Envelope; -use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Routing\RouterInterface; -use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; -use Symfony\Component\Security\Core\Exception\AccessDeniedException; -use Symfony\Component\Security\Csrf\CsrfToken; -use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; -use Symfony\Component\Serializer\SerializerInterface; -use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener; -use Symfony\Component\WebLink\GenericLinkProvider; -use Symfony\Contracts\Service\ServiceSubscriberInterface; -use Twig\Environment; - -/** - * Provides common features needed in controllers. - * - * @author Fabien Potencier - */ -abstract class AbstractController implements ServiceSubscriberInterface -{ - /** - * @var ContainerInterface - */ - protected $container; - - /** - * @internal - * @required - */ - public function setContainer(ContainerInterface $container): ?ContainerInterface - { - $previous = $this->container; - $this->container = $container; - - return $previous; - } - - /** - * Gets a container parameter by its name. - * - * @return mixed - */ - protected function getParameter(string $name) - { - if (!$this->container->has('parameter_bag')) { - throw new ServiceNotFoundException('parameter_bag', null, null, [], sprintf('The "%s::getParameter()" method is missing a parameter bag to work properly. Did you forget to register your controller as a service subscriber? This can be fixed either by using autoconfiguration or by manually wiring a "parameter_bag" in the service locator passed to the controller.', \get_class($this))); - } - - return $this->container->get('parameter_bag')->get($name); - } - - public static function getSubscribedServices() - { - return [ - 'router' => '?'.RouterInterface::class, - 'request_stack' => '?'.RequestStack::class, - 'http_kernel' => '?'.HttpKernelInterface::class, - 'serializer' => '?'.SerializerInterface::class, - 'session' => '?'.SessionInterface::class, - 'security.authorization_checker' => '?'.AuthorizationCheckerInterface::class, - 'twig' => '?'.Environment::class, - 'doctrine' => '?'.ManagerRegistry::class, - 'form.factory' => '?'.FormFactoryInterface::class, - 'security.token_storage' => '?'.TokenStorageInterface::class, - 'security.csrf.token_manager' => '?'.CsrfTokenManagerInterface::class, - 'parameter_bag' => '?'.ContainerBagInterface::class, - 'message_bus' => '?'.MessageBusInterface::class, - 'messenger.default_bus' => '?'.MessageBusInterface::class, - ]; - } - - /** - * Returns true if the service id is defined. - */ - protected function has(string $id): bool - { - return $this->container->has($id); - } - - /** - * Gets a container service by its id. - * - * @return object The service - */ - protected function get(string $id): object - { - return $this->container->get($id); - } - - /** - * Generates a URL from the given parameters. - * - * @see UrlGeneratorInterface - */ - protected function generateUrl(string $route, array $parameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): string - { - return $this->container->get('router')->generate($route, $parameters, $referenceType); - } - - /** - * Forwards the request to another controller. - * - * @param string $controller The controller name (a string like Bundle\BlogBundle\Controller\PostController::indexAction) - */ - protected function forward(string $controller, array $path = [], array $query = []): Response - { - $request = $this->container->get('request_stack')->getCurrentRequest(); - $path['_controller'] = $controller; - $subRequest = $request->duplicate($query, null, $path); - - return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST); - } - - /** - * Returns a RedirectResponse to the given URL. - */ - protected function redirect(string $url, int $status = 302): RedirectResponse - { - return new RedirectResponse($url, $status); - } - - /** - * Returns a RedirectResponse to the given route with the given parameters. - */ - protected function redirectToRoute(string $route, array $parameters = [], int $status = 302): RedirectResponse - { - return $this->redirect($this->generateUrl($route, $parameters), $status); - } - - /** - * Returns a JsonResponse that uses the serializer component if enabled, or json_encode. - */ - protected function json($data, int $status = 200, array $headers = [], array $context = []): JsonResponse - { - if ($this->container->has('serializer')) { - $json = $this->container->get('serializer')->serialize($data, 'json', array_merge([ - 'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS, - ], $context)); - - return new JsonResponse($json, $status, $headers, true); - } - - return new JsonResponse($data, $status, $headers); - } - - /** - * Returns a BinaryFileResponse object with original or customized file name and disposition header. - * - * @param \SplFileInfo|string $file File object or path to file to be sent as response - */ - protected function file($file, string $fileName = null, string $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT): BinaryFileResponse - { - $response = new BinaryFileResponse($file); - $response->setContentDisposition($disposition, null === $fileName ? $response->getFile()->getFilename() : $fileName); - - return $response; - } - - /** - * Adds a flash message to the current session for type. - * - * @throws \LogicException - */ - protected function addFlash(string $type, string $message): void - { - if (!$this->container->has('session')) { - throw new \LogicException('You can not use the addFlash method if sessions are disabled. Enable them in "config/packages/framework.yaml".'); - } - - $this->container->get('session')->getFlashBag()->add($type, $message); - } - - /** - * Checks if the attributes are granted against the current authentication token and optionally supplied subject. - * - * @throws \LogicException - */ - protected function isGranted($attributes, $subject = null): bool - { - if (!$this->container->has('security.authorization_checker')) { - throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".'); - } - - return $this->container->get('security.authorization_checker')->isGranted($attributes, $subject); - } - - /** - * Throws an exception unless the attributes are granted against the current authentication token and optionally - * supplied subject. - * - * @throws AccessDeniedException - */ - protected function denyAccessUnlessGranted($attributes, $subject = null, string $message = 'Access Denied.'): void - { - if (!$this->isGranted($attributes, $subject)) { - $exception = $this->createAccessDeniedException($message); - $exception->setAttributes($attributes); - $exception->setSubject($subject); - - throw $exception; - } - } - - /** - * Returns a rendered view. - */ - protected function renderView(string $view, array $parameters = []): string - { - if (!$this->container->has('twig')) { - throw new \LogicException('You can not use the "renderView" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".'); - } - - return $this->container->get('twig')->render($view, $parameters); - } - - /** - * Renders a view. - */ - protected function render(string $view, array $parameters = [], Response $response = null): Response - { - $content = $this->renderView($view, $parameters); - - if (null === $response) { - $response = new Response(); - } - - $response->setContent($content); - - return $response; - } - - /** - * Streams a view. - */ - protected function stream(string $view, array $parameters = [], StreamedResponse $response = null): StreamedResponse - { - if (!$this->container->has('twig')) { - throw new \LogicException('You can not use the "stream" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".'); - } - - $twig = $this->container->get('twig'); - - $callback = function () use ($twig, $view, $parameters) { - $twig->display($view, $parameters); - }; - - if (null === $response) { - return new StreamedResponse($callback); - } - - $response->setCallback($callback); - - return $response; - } - - /** - * Returns a NotFoundHttpException. - * - * This will result in a 404 response code. Usage example: - * - * throw $this->createNotFoundException('Page not found!'); - */ - protected function createNotFoundException(string $message = 'Not Found', \Throwable $previous = null): NotFoundHttpException - { - return new NotFoundHttpException($message, $previous); - } - - /** - * Returns an AccessDeniedException. - * - * This will result in a 403 response code. Usage example: - * - * throw $this->createAccessDeniedException('Unable to access this page!'); - * - * @throws \LogicException If the Security component is not available - */ - protected function createAccessDeniedException(string $message = 'Access Denied.', \Throwable $previous = null): AccessDeniedException - { - if (!class_exists(AccessDeniedException::class)) { - throw new \LogicException('You can not use the "createAccessDeniedException" method if the Security component is not available. Try running "composer require symfony/security-bundle".'); - } - - return new AccessDeniedException($message, $previous); - } - - /** - * Creates and returns a Form instance from the type of the form. - */ - protected function createForm(string $type, $data = null, array $options = []): FormInterface - { - return $this->container->get('form.factory')->create($type, $data, $options); - } - - /** - * Creates and returns a form builder instance. - */ - protected function createFormBuilder($data = null, array $options = []): FormBuilderInterface - { - return $this->container->get('form.factory')->createBuilder(FormType::class, $data, $options); - } - - /** - * Shortcut to return the Doctrine Registry service. - * - * @throws \LogicException If DoctrineBundle is not available - */ - protected function getDoctrine(): ManagerRegistry - { - if (!$this->container->has('doctrine')) { - throw new \LogicException('The DoctrineBundle is not registered in your application. Try running "composer require symfony/orm-pack".'); - } - - return $this->container->get('doctrine'); - } - - /** - * Get a user from the Security Token Storage. - * - * @return UserInterface|object|null - * - * @throws \LogicException If SecurityBundle is not available - * - * @see TokenInterface::getUser() - */ - protected function getUser() - { - if (!$this->container->has('security.token_storage')) { - throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".'); - } - - if (null === $token = $this->container->get('security.token_storage')->getToken()) { - return null; - } - - if (!\is_object($user = $token->getUser())) { - // e.g. anonymous authentication - return null; - } - - return $user; - } - - /** - * Checks the validity of a CSRF token. - * - * @param string $id The id used when generating the token - * @param string|null $token The actual token sent with the request that should be validated - */ - protected function isCsrfTokenValid(string $id, ?string $token): bool - { - if (!$this->container->has('security.csrf.token_manager')) { - throw new \LogicException('CSRF protection is not enabled in your application. Enable it with the "csrf_protection" key in "config/packages/framework.yaml".'); - } - - return $this->container->get('security.csrf.token_manager')->isTokenValid(new CsrfToken($id, $token)); - } - - /** - * Dispatches a message to the bus. - * - * @param object|Envelope $message The message or the message pre-wrapped in an envelope - */ - protected function dispatchMessage($message, array $stamps = []): Envelope - { - if (!$this->container->has('messenger.default_bus')) { - $message = class_exists(Envelope::class) ? 'You need to define the "messenger.default_bus" configuration option.' : 'Try running "composer require symfony/messenger".'; - throw new \LogicException('The message bus is not enabled in your application. '.$message); - } - - return $this->container->get('messenger.default_bus')->dispatch($message, $stamps); - } - - /** - * Adds a Link HTTP header to the current response. - * - * @see https://tools.ietf.org/html/rfc5988 - */ - protected function addLink(Request $request, LinkInterface $link): void - { - if (!class_exists(AddLinkHeaderListener::class)) { - throw new \LogicException('You can not use the "addLink" method if the WebLink component is not available. Try running "composer require symfony/web-link".'); - } - - if (null === $linkProvider = $request->attributes->get('_links')) { - $request->attributes->set('_links', new GenericLinkProvider([$link])); - - return; - } - - $request->attributes->set('_links', $linkProvider->withLink($link)); - } -} diff --git a/vendor/symfony/framework-bundle/Controller/ControllerResolver.php b/vendor/symfony/framework-bundle/Controller/ControllerResolver.php deleted file mode 100644 index 859d1c2..0000000 --- a/vendor/symfony/framework-bundle/Controller/ControllerResolver.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Controller; - -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver; - -/** - * @author Fabien Potencier - * - * @final - */ -class ControllerResolver extends ContainerControllerResolver -{ - /** - * {@inheritdoc} - */ - protected function instantiateController($class): object - { - return $this->configureController(parent::instantiateController($class), $class); - } - - private function configureController($controller, string $class): object - { - if ($controller instanceof ContainerAwareInterface) { - $controller->setContainer($this->container); - } - if ($controller instanceof AbstractController) { - if (null === $previousContainer = $controller->setContainer($this->container)) { - throw new \LogicException(sprintf('"%s" has no container set, did you forget to define it as a service subscriber?', $class)); - } else { - $controller->setContainer($previousContainer); - } - } - - return $controller; - } -} diff --git a/vendor/symfony/framework-bundle/Controller/RedirectController.php b/vendor/symfony/framework-bundle/Controller/RedirectController.php deleted file mode 100644 index 00d1a4a..0000000 --- a/vendor/symfony/framework-bundle/Controller/RedirectController.php +++ /dev/null @@ -1,179 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Controller; - -use Symfony\Component\HttpFoundation\RedirectResponse; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Exception\HttpException; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; - -/** - * Redirects a request to another URL. - * - * @author Fabien Potencier - * - * @final - */ -class RedirectController -{ - private $router; - private $httpPort; - private $httpsPort; - - public function __construct(UrlGeneratorInterface $router = null, int $httpPort = null, int $httpsPort = null) - { - $this->router = $router; - $this->httpPort = $httpPort; - $this->httpsPort = $httpsPort; - } - - /** - * Redirects to another route with the given name. - * - * The response status code is 302 if the permanent parameter is false (default), - * and 301 if the redirection is permanent. - * - * In case the route name is empty, the status code will be 404 when permanent is false - * and 410 otherwise. - * - * @param string $route The route name to redirect to - * @param bool $permanent Whether the redirection is permanent - * @param bool|array $ignoreAttributes Whether to ignore attributes or an array of attributes to ignore - * @param bool $keepRequestMethod Whether redirect action should keep HTTP request method - * - * @throws HttpException In case the route name is empty - */ - public function redirectAction(Request $request, string $route, bool $permanent = false, $ignoreAttributes = false, bool $keepRequestMethod = false, bool $keepQueryParams = false): Response - { - if ('' == $route) { - throw new HttpException($permanent ? 410 : 404); - } - - $attributes = []; - if (false === $ignoreAttributes || \is_array($ignoreAttributes)) { - $attributes = $request->attributes->get('_route_params'); - $attributes = $keepQueryParams ? array_merge($request->query->all(), $attributes) : $attributes; - unset($attributes['route'], $attributes['permanent'], $attributes['ignoreAttributes'], $attributes['keepRequestMethod'], $attributes['keepQueryParams']); - if ($ignoreAttributes) { - $attributes = array_diff_key($attributes, array_flip($ignoreAttributes)); - } - } - - if ($keepRequestMethod) { - $statusCode = $permanent ? 308 : 307; - } else { - $statusCode = $permanent ? 301 : 302; - } - - return new RedirectResponse($this->router->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), $statusCode); - } - - /** - * Redirects to a URL. - * - * The response status code is 302 if the permanent parameter is false (default), - * and 301 if the redirection is permanent. - * - * In case the path is empty, the status code will be 404 when permanent is false - * and 410 otherwise. - * - * @param string $path The absolute path or URL to redirect to - * @param bool $permanent Whether the redirect is permanent or not - * @param string|null $scheme The URL scheme (null to keep the current one) - * @param int|null $httpPort The HTTP port (null to keep the current one for the same scheme or the default configured port) - * @param int|null $httpsPort The HTTPS port (null to keep the current one for the same scheme or the default configured port) - * @param bool $keepRequestMethod Whether redirect action should keep HTTP request method - * - * @throws HttpException In case the path is empty - */ - public function urlRedirectAction(Request $request, string $path, bool $permanent = false, string $scheme = null, int $httpPort = null, int $httpsPort = null, bool $keepRequestMethod = false): Response - { - if ('' == $path) { - throw new HttpException($permanent ? 410 : 404); - } - - if ($keepRequestMethod) { - $statusCode = $permanent ? 308 : 307; - } else { - $statusCode = $permanent ? 301 : 302; - } - - // redirect if the path is a full URL - if (parse_url($path, PHP_URL_SCHEME)) { - return new RedirectResponse($path, $statusCode); - } - - if (null === $scheme) { - $scheme = $request->getScheme(); - } - - $qs = $request->getQueryString(); - if ($qs) { - if (false === strpos($path, '?')) { - $qs = '?'.$qs; - } else { - $qs = '&'.$qs; - } - } - - $port = ''; - if ('http' === $scheme) { - if (null === $httpPort) { - if ('http' === $request->getScheme()) { - $httpPort = $request->getPort(); - } else { - $httpPort = $this->httpPort; - } - } - - if (null !== $httpPort && 80 != $httpPort) { - $port = ":$httpPort"; - } - } elseif ('https' === $scheme) { - if (null === $httpsPort) { - if ('https' === $request->getScheme()) { - $httpsPort = $request->getPort(); - } else { - $httpsPort = $this->httpsPort; - } - } - - if (null !== $httpsPort && 443 != $httpsPort) { - $port = ":$httpsPort"; - } - } - - $url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$path.$qs; - - return new RedirectResponse($url, $statusCode); - } - - public function __invoke(Request $request): Response - { - $p = $request->attributes->get('_route_params', []); - - if (\array_key_exists('route', $p)) { - if (\array_key_exists('path', $p)) { - throw new \RuntimeException(sprintf('Ambiguous redirection settings, use the "path" or "route" parameter, not both: "%s" and "%s" found respectively in "%s" routing configuration.', $p['path'], $p['route'], $request->attributes->get('_route'))); - } - - return $this->redirectAction($request, $p['route'], $p['permanent'] ?? false, $p['ignoreAttributes'] ?? false, $p['keepRequestMethod'] ?? false, $p['keepQueryParams'] ?? false); - } - - if (\array_key_exists('path', $p)) { - return $this->urlRedirectAction($request, $p['path'], $p['permanent'] ?? false, $p['scheme'] ?? null, $p['httpPort'] ?? null, $p['httpsPort'] ?? null, $p['keepRequestMethod'] ?? false); - } - - throw new \RuntimeException(sprintf('The parameter "path" or "route" is required to configure the redirect action in "%s" routing configuration.', $request->attributes->get('_route'))); - } -} diff --git a/vendor/symfony/framework-bundle/Controller/TemplateController.php b/vendor/symfony/framework-bundle/Controller/TemplateController.php deleted file mode 100644 index 0fff40b..0000000 --- a/vendor/symfony/framework-bundle/Controller/TemplateController.php +++ /dev/null @@ -1,70 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Controller; - -use Symfony\Component\HttpFoundation\Response; -use Twig\Environment; - -/** - * TemplateController. - * - * @author Fabien Potencier - * - * @final - */ -class TemplateController -{ - private $twig; - - public function __construct(Environment $twig = null) - { - $this->twig = $twig; - } - - /** - * Renders a template. - * - * @param string $template The template name - * @param int|null $maxAge Max age for client caching - * @param int|null $sharedAge Max age for shared (proxy) caching - * @param bool|null $private Whether or not caching should apply for client caches only - */ - public function templateAction(string $template, int $maxAge = null, int $sharedAge = null, bool $private = null): Response - { - if (null === $this->twig) { - throw new \LogicException('You can not use the TemplateController if the Twig Bundle is not available.'); - } - - $response = new Response($this->twig->render($template)); - - if ($maxAge) { - $response->setMaxAge($maxAge); - } - - if ($sharedAge) { - $response->setSharedMaxAge($sharedAge); - } - - if ($private) { - $response->setPrivate(); - } elseif (false === $private || (null === $private && ($maxAge || $sharedAge))) { - $response->setPublic(); - } - - return $response; - } - - public function __invoke(string $template, int $maxAge = null, int $sharedAge = null, bool $private = null): Response - { - return $this->templateAction($template, $maxAge, $sharedAge, $private); - } -} diff --git a/vendor/symfony/framework-bundle/DataCollector/RouterDataCollector.php b/vendor/symfony/framework-bundle/DataCollector/RouterDataCollector.php deleted file mode 100644 index 0acdc61..0000000 --- a/vendor/symfony/framework-bundle/DataCollector/RouterDataCollector.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DataCollector; - -use Symfony\Bundle\FrameworkBundle\Controller\RedirectController; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\DataCollector\RouterDataCollector as BaseRouterDataCollector; - -/** - * RouterDataCollector. - * - * @author Fabien Potencier - * - * @final - */ -class RouterDataCollector extends BaseRouterDataCollector -{ - public function guessRoute(Request $request, $controller) - { - if (\is_array($controller)) { - $controller = $controller[0]; - } - - if ($controller instanceof RedirectController) { - return $request->attributes->get('_route'); - } - - return parent::guessRoute($request, $controller); - } -} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php deleted file mode 100644 index 4f09e52..0000000 --- a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddAnnotationsCachedReaderPass.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * @internal - */ -class AddAnnotationsCachedReaderPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - // "annotations.cached_reader" is wired late so that any passes using - // "annotation_reader" at build time don't get any cache - foreach ($container->findTaggedServiceIds('annotations.cached_reader') as $id => $tags) { - $reader = $container->getDefinition($id); - $properties = $reader->getProperties(); - - if (isset($properties['cacheProviderBackup'])) { - $provider = $properties['cacheProviderBackup']->getValues()[0]; - unset($properties['cacheProviderBackup']); - $reader->setProperties($properties); - $container->set($id, null); - $container->setDefinition($id, $reader->replaceArgument(1, $provider)); - } - } - } -} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php deleted file mode 100644 index dbe88b0..0000000 --- a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddDebugLogProcessorPass.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -class AddDebugLogProcessorPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('profiler')) { - return; - } - if (!$container->hasDefinition('monolog.logger_prototype')) { - return; - } - if (!$container->hasDefinition('debug.log_processor')) { - return; - } - - $definition = $container->getDefinition('monolog.logger_prototype'); - $definition->setConfigurator([__CLASS__, 'configureLogger']); - $definition->addMethodCall('pushProcessor', [new Reference('debug.log_processor')]); - } - - public static function configureLogger($logger) - { - if (method_exists($logger, 'removeDebugLogger') && \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { - $logger->removeDebugLogger(); - } - } -} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php deleted file mode 100644 index 47195b4..0000000 --- a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Registers the expression language providers. - * - * @author Fabien Potencier - */ -class AddExpressionLanguageProvidersPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - // routing - if ($container->has('router')) { - $definition = $container->findDefinition('router'); - foreach ($container->findTaggedServiceIds('routing.expression_language_provider', true) as $id => $attributes) { - $definition->addMethodCall('addExpressionLanguageProvider', [new Reference($id)]); - } - } - } -} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php deleted file mode 100644 index 0df5420..0000000 --- a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/ContainerBuilderDebugDumpPass.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\Config\ConfigCache; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Dumper\XmlDumper; - -/** - * Dumps the ContainerBuilder to a cache file so that it can be used by - * debugging tools such as the debug:container console command. - * - * @author Ryan Weaver - * @author Fabien Potencier - */ -class ContainerBuilderDebugDumpPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - $cache = new ConfigCache($container->getParameter('debug.container.dump'), true); - if (!$cache->isFresh()) { - $cache->write((new XmlDumper($container))->dump(), $container->getResources()); - } - } -} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php deleted file mode 100644 index ee2bbb6..0000000 --- a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/DataCollectorTranslatorPass.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * @author Christian Flothmann - */ -class DataCollectorTranslatorPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->has('translator')) { - return; - } - - $translatorClass = $container->getParameterBag()->resolveValue($container->findDefinition('translator')->getClass()); - - if (!is_subclass_of($translatorClass, 'Symfony\Component\Translation\TranslatorBagInterface')) { - $container->removeDefinition('translator.data_collector'); - $container->removeDefinition('data_collector.translation'); - } - } -} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php deleted file mode 100644 index 80cbe52..0000000 --- a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/LoggingTranslatorPass.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\Translation\TranslatorBagInterface; -use Symfony\Contracts\Translation\TranslatorInterface; - -/** - * @author Abdellatif Ait boudad - */ -class LoggingTranslatorPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->hasAlias('logger') || !$container->hasAlias('translator')) { - return; - } - - if ($container->hasParameter('translator.logging') && $container->getParameter('translator.logging')) { - $translatorAlias = $container->getAlias('translator'); - $definition = $container->getDefinition((string) $translatorAlias); - $class = $container->getParameterBag()->resolveValue($definition->getClass()); - - if (!$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $translatorAlias)); - } - if ($r->isSubclassOf(TranslatorInterface::class) && $r->isSubclassOf(TranslatorBagInterface::class)) { - $container->getDefinition('translator.logging')->setDecoratedService('translator'); - $warmer = $container->getDefinition('translation.warmer'); - $subscriberAttributes = $warmer->getTag('container.service_subscriber'); - $warmer->clearTag('container.service_subscriber'); - - foreach ($subscriberAttributes as $k => $v) { - if ((!isset($v['id']) || 'translator' !== $v['id']) && (!isset($v['key']) || 'translator' !== $v['key'])) { - $warmer->addTag('container.service_subscriber', $v); - } - } - $warmer->addTag('container.service_subscriber', ['key' => 'translator', 'id' => 'translator.logging.inner']); - } - } - } -} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php deleted file mode 100644 index 357c079..0000000 --- a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/ProfilerPass.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Adds tagged data_collector services to profiler service. - * - * @author Fabien Potencier - */ -class ProfilerPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (false === $container->hasDefinition('profiler')) { - return; - } - - $definition = $container->getDefinition('profiler'); - - $collectors = new \SplPriorityQueue(); - $order = PHP_INT_MAX; - foreach ($container->findTaggedServiceIds('data_collector', true) as $id => $attributes) { - $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; - $template = null; - - if (isset($attributes[0]['template'])) { - if (!isset($attributes[0]['id'])) { - throw new InvalidArgumentException(sprintf('Data collector service "%s" must have an id attribute in order to specify a template', $id)); - } - $template = [$attributes[0]['id'], $attributes[0]['template']]; - } - - $collectors->insert([$id, $template], [$priority, --$order]); - } - - $templates = []; - foreach ($collectors as $collector) { - $definition->addMethodCall('add', [new Reference($collector[0])]); - $templates[$collector[0]] = $collector[1]; - } - - $container->setParameter('data_collector.templates', $templates); - } -} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php deleted file mode 100644 index 222b5c7..0000000 --- a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Nicolas Grekas - */ -class TestServiceContainerRealRefPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('test.private_services_locator')) { - return; - } - - $privateContainer = $container->getDefinition('test.private_services_locator'); - $definitions = $container->getDefinitions(); - $privateServices = $privateContainer->getArgument(0); - - foreach ($privateServices as $id => $argument) { - if (isset($definitions[$target = (string) $argument->getValues()[0]])) { - $argument->setValues([new Reference($target)]); - } else { - unset($privateServices[$id]); - } - } - - $privateContainer->replaceArgument(0, $privateServices); - } -} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php deleted file mode 100644 index 57aa592..0000000 --- a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php +++ /dev/null @@ -1,60 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Nicolas Grekas - */ -class TestServiceContainerWeakRefPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('test.private_services_locator')) { - return; - } - - $privateServices = []; - $definitions = $container->getDefinitions(); - $hasErrors = method_exists(Definition::class, 'hasErrors') ? 'hasErrors' : 'getErrors'; - - foreach ($definitions as $id => $definition) { - if ($id && '.' !== $id[0] && (!$definition->isPublic() || $definition->isPrivate()) && !$definition->$hasErrors() && !$definition->isAbstract()) { - $privateServices[$id] = new Reference($id, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE); - } - } - - $aliases = $container->getAliases(); - - foreach ($aliases as $id => $alias) { - if ($id && '.' !== $id[0] && (!$alias->isPublic() || $alias->isPrivate())) { - while (isset($aliases[$target = (string) $alias])) { - $alias = $aliases[$target]; - } - if (isset($definitions[$target]) && !$definitions[$target]->$hasErrors() && !$definitions[$target]->isAbstract()) { - $privateServices[$id] = new Reference($target, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE); - } - } - } - - if ($privateServices) { - $id = (string) ServiceLocatorTagPass::register($container, $privateServices); - $container->setDefinition('test.private_services_locator', $container->getDefinition($id))->setPublic(true); - $container->removeDefinition($id); - } - } -} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php deleted file mode 100644 index 5bbcb74..0000000 --- a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php +++ /dev/null @@ -1,100 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Find all service tags which are defined, but not used and yield a warning log message. - * - * @author Florian Pfitzer - */ -class UnusedTagsPass implements CompilerPassInterface -{ - private $whitelist = [ - 'annotations.cached_reader', - 'cache.pool.clearer', - 'console.command', - 'container.hot_path', - 'container.reversible', - 'container.service_locator', - 'container.service_subscriber', - 'controller.service_arguments', - 'config_cache.resource_checker', - 'data_collector', - 'form.type', - 'form.type_extension', - 'form.type_guesser', - 'http_client.client', - 'kernel.cache_clearer', - 'kernel.cache_warmer', - 'kernel.event_listener', - 'kernel.event_subscriber', - 'kernel.fragment_renderer', - 'kernel.locale_aware', - 'messenger.bus', - 'messenger.receiver', - 'messenger.message_handler', - 'mime.mime_type_guesser', - 'monolog.logger', - 'proxy', - 'routing.expression_language_provider', - 'routing.loader', - 'routing.route_loader', - 'security.expression_language_provider', - 'security.remember_me_aware', - 'security.voter', - 'serializer.encoder', - 'serializer.normalizer', - 'translation.dumper', - 'translation.extractor', - 'translation.loader', - 'twig.extension', - 'twig.loader', - 'validator.constraint_validator', - 'validator.initializer', - 'validator.auto_mapper', - ]; - - public function process(ContainerBuilder $container) - { - $tags = array_unique(array_merge($container->findTags(), $this->whitelist)); - - foreach ($container->findUnusedTags() as $tag) { - // skip whitelisted tags - if (\in_array($tag, $this->whitelist)) { - continue; - } - - // check for typos - $candidates = []; - foreach ($tags as $definedTag) { - if ($definedTag === $tag) { - continue; - } - - if (false !== strpos($definedTag, $tag) || levenshtein($tag, $definedTag) <= \strlen($tag) / 3) { - $candidates[] = $definedTag; - } - } - - $services = array_keys($container->findTaggedServiceIds($tag)); - $message = sprintf('Tag "%s" was defined on service(s) "%s", but was never used.', $tag, implode('", "', $services)); - if (!empty($candidates)) { - $message .= sprintf(' Did you mean "%s"?', implode('", "', $candidates)); - } - - $container->log($this, $message); - } - } -} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php b/vendor/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php deleted file mode 100644 index ad62e19..0000000 --- a/vendor/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\LogicException; - -/** - * @author Christian Flothmann - * @author Grégoire Pineau - */ -class WorkflowGuardListenerPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->hasParameter('workflow.has_guard_listeners')) { - return; - } - - $container->getParameterBag()->remove('workflow.has_guard_listeners'); - - $servicesNeeded = [ - 'security.token_storage', - 'security.authorization_checker', - 'security.authentication.trust_resolver', - 'security.role_hierarchy', - ]; - - foreach ($servicesNeeded as $service) { - if (!$container->has($service)) { - throw new LogicException(sprintf('The "%s" service is needed to be able to use the workflow guard listener.', $service)); - } - } - } -} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/Configuration.php b/vendor/symfony/framework-bundle/DependencyInjection/Configuration.php deleted file mode 100644 index 47a508c..0000000 --- a/vendor/symfony/framework-bundle/DependencyInjection/Configuration.php +++ /dev/null @@ -1,1558 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; - -use Doctrine\Common\Annotations\Annotation; -use Doctrine\Common\Cache\Cache; -use Doctrine\DBAL\Connection; -use Symfony\Bundle\FullStack; -use Symfony\Component\Asset\Package; -use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; -use Symfony\Component\Config\Definition\Builder\TreeBuilder; -use Symfony\Component\Config\Definition\ConfigurationInterface; -use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\Form\Form; -use Symfony\Component\HttpClient\HttpClient; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\Lock\Lock; -use Symfony\Component\Lock\Store\SemaphoreStore; -use Symfony\Component\Mailer\Mailer; -use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Notifier\Notifier; -use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; -use Symfony\Component\Serializer\Serializer; -use Symfony\Component\Translation\Translator; -use Symfony\Component\Validator\Validation; -use Symfony\Component\WebLink\HttpHeaderSerializer; - -/** - * FrameworkExtension configuration structure. - * - * @author Jeremy Mikola - * @author Grégoire Pineau - */ -class Configuration implements ConfigurationInterface -{ - private $debug; - - /** - * @param bool $debug Whether debugging is enabled or not - */ - public function __construct(bool $debug) - { - $this->debug = $debug; - } - - /** - * Generates the configuration tree builder. - * - * @return TreeBuilder The tree builder - */ - public function getConfigTreeBuilder() - { - $treeBuilder = new TreeBuilder('framework'); - $rootNode = $treeBuilder->getRootNode(); - - $rootNode - ->beforeNormalization() - ->ifTrue(function ($v) { return !isset($v['assets']) && isset($v['templating']) && class_exists(Package::class); }) - ->then(function ($v) { - $v['assets'] = []; - - return $v; - }) - ->end() - ->children() - ->scalarNode('secret')->end() - ->scalarNode('http_method_override') - ->info("Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. Note: When using the HttpCache, you need to call the method in your front controller instead") - ->defaultTrue() - ->end() - ->scalarNode('ide')->defaultNull()->end() - ->booleanNode('test')->end() - ->scalarNode('default_locale')->defaultValue('en')->end() - ->arrayNode('trusted_hosts') - ->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end() - ->prototype('scalar')->end() - ->end() - ->scalarNode('error_controller') - ->defaultValue('error_controller') - ->end() - ->end() - ; - - $this->addCsrfSection($rootNode); - $this->addFormSection($rootNode); - $this->addEsiSection($rootNode); - $this->addSsiSection($rootNode); - $this->addFragmentsSection($rootNode); - $this->addProfilerSection($rootNode); - $this->addWorkflowSection($rootNode); - $this->addRouterSection($rootNode); - $this->addSessionSection($rootNode); - $this->addRequestSection($rootNode); - $this->addAssetsSection($rootNode); - $this->addTranslatorSection($rootNode); - $this->addValidationSection($rootNode); - $this->addAnnotationsSection($rootNode); - $this->addSerializerSection($rootNode); - $this->addPropertyAccessSection($rootNode); - $this->addPropertyInfoSection($rootNode); - $this->addCacheSection($rootNode); - $this->addPhpErrorsSection($rootNode); - $this->addWebLinkSection($rootNode); - $this->addLockSection($rootNode); - $this->addMessengerSection($rootNode); - $this->addRobotsIndexSection($rootNode); - $this->addHttpClientSection($rootNode); - $this->addMailerSection($rootNode); - $this->addSecretsSection($rootNode); - $this->addNotifierSection($rootNode); - - return $treeBuilder; - } - - private function addSecretsSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('secrets') - ->canBeDisabled() - ->children() - ->scalarNode('vault_directory')->defaultValue('%kernel.project_dir%/config/secrets/%kernel.environment%')->cannotBeEmpty()->end() - ->scalarNode('local_dotenv_file')->defaultValue('%kernel.project_dir%/.env.%kernel.environment%.local')->end() - ->scalarNode('decryption_env_var')->defaultValue('base64:default::SYMFONY_DECRYPTION_SECRET')->end() - ->end() - ->end() - ->end() - ; - } - - private function addCsrfSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('csrf_protection') - ->treatFalseLike(['enabled' => false]) - ->treatTrueLike(['enabled' => true]) - ->treatNullLike(['enabled' => true]) - ->addDefaultsIfNotSet() - ->children() - // defaults to framework.session.enabled && !class_exists(FullStack::class) && interface_exists(CsrfTokenManagerInterface::class) - ->booleanNode('enabled')->defaultNull()->end() - ->end() - ->end() - ->end() - ; - } - - private function addFormSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('form') - ->info('form configuration') - ->{!class_exists(FullStack::class) && class_exists(Form::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->children() - ->arrayNode('csrf_protection') - ->treatFalseLike(['enabled' => false]) - ->treatTrueLike(['enabled' => true]) - ->treatNullLike(['enabled' => true]) - ->addDefaultsIfNotSet() - ->children() - ->booleanNode('enabled')->defaultNull()->end() // defaults to framework.csrf_protection.enabled - ->scalarNode('field_name')->defaultValue('_token')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addEsiSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('esi') - ->info('esi configuration') - ->canBeEnabled() - ->end() - ->end() - ; - } - - private function addSsiSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('ssi') - ->info('ssi configuration') - ->canBeEnabled() - ->end() - ->end(); - } - - private function addFragmentsSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('fragments') - ->info('fragments configuration') - ->canBeEnabled() - ->children() - ->scalarNode('hinclude_default_template')->defaultNull()->end() - ->scalarNode('path')->defaultValue('/_fragment')->end() - ->end() - ->end() - ->end() - ; - } - - private function addProfilerSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('profiler') - ->info('profiler configuration') - ->canBeEnabled() - ->children() - ->booleanNode('collect')->defaultTrue()->end() - ->booleanNode('only_exceptions')->defaultFalse()->end() - ->booleanNode('only_master_requests')->defaultFalse()->end() - ->scalarNode('dsn')->defaultValue('file:%kernel.cache_dir%/profiler')->end() - ->end() - ->end() - ->end() - ; - } - - private function addWorkflowSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->fixXmlConfig('workflow') - ->children() - ->arrayNode('workflows') - ->canBeEnabled() - ->beforeNormalization() - ->always(function ($v) { - if (\is_array($v) && true === $v['enabled']) { - $workflows = $v; - unset($workflows['enabled']); - - if (1 === \count($workflows) && isset($workflows[0]['enabled']) && 1 === \count($workflows[0])) { - $workflows = []; - } - - if (1 === \count($workflows) && isset($workflows['workflows']) && array_keys($workflows['workflows']) !== range(0, \count($workflows) - 1) && !empty(array_diff(array_keys($workflows['workflows']), ['audit_trail', 'type', 'marking_store', 'supports', 'support_strategy', 'initial_marking', 'places', 'transitions']))) { - $workflows = $workflows['workflows']; - } - - foreach ($workflows as $key => $workflow) { - if (isset($workflow['enabled']) && false === $workflow['enabled']) { - throw new LogicException(sprintf('Cannot disable a single workflow. Remove the configuration for the workflow "%s" instead.', $workflow['name'])); - } - - unset($workflows[$key]['enabled']); - } - - $v = [ - 'enabled' => true, - 'workflows' => $workflows, - ]; - } - - return $v; - }) - ->end() - ->children() - ->arrayNode('workflows') - ->useAttributeAsKey('name') - ->prototype('array') - ->fixXmlConfig('support') - ->fixXmlConfig('place') - ->fixXmlConfig('transition') - ->children() - ->arrayNode('audit_trail') - ->canBeEnabled() - ->end() - ->enumNode('type') - ->values(['workflow', 'state_machine']) - ->defaultValue('state_machine') - ->end() - ->arrayNode('marking_store') - ->children() - ->enumNode('type') - ->values(['method']) - ->end() - ->scalarNode('property') - ->defaultValue('marking') - ->end() - ->scalarNode('service') - ->cannotBeEmpty() - ->end() - ->end() - ->end() - ->arrayNode('supports') - ->beforeNormalization() - ->ifString() - ->then(function ($v) { return [$v]; }) - ->end() - ->prototype('scalar') - ->cannotBeEmpty() - ->validate() - ->ifTrue(function ($v) { return !class_exists($v) && !interface_exists($v, false); }) - ->thenInvalid('The supported class or interface "%s" does not exist.') - ->end() - ->end() - ->end() - ->scalarNode('support_strategy') - ->cannotBeEmpty() - ->end() - ->arrayNode('initial_marking') - ->beforeNormalization()->castToArray()->end() - ->defaultValue([]) - ->prototype('scalar')->end() - ->end() - ->arrayNode('places') - ->beforeNormalization() - ->always() - ->then(function ($places) { - // It's an indexed array of shape ['place1', 'place2'] - if (isset($places[0]) && \is_string($places[0])) { - return array_map(function (string $place) { - return ['name' => $place]; - }, $places); - } - - // It's an indexed array, we let the validation occur - if (isset($places[0]) && \is_array($places[0])) { - return $places; - } - - foreach ($places as $name => $place) { - if (\is_array($place) && \array_key_exists('name', $place)) { - continue; - } - $place['name'] = $name; - $places[$name] = $place; - } - - return array_values($places); - }) - ->end() - ->isRequired() - ->requiresAtLeastOneElement() - ->prototype('array') - ->children() - ->scalarNode('name') - ->isRequired() - ->cannotBeEmpty() - ->end() - ->arrayNode('metadata') - ->normalizeKeys(false) - ->defaultValue([]) - ->example(['color' => 'blue', 'description' => 'Workflow to manage article.']) - ->prototype('variable') - ->end() - ->end() - ->end() - ->end() - ->end() - ->arrayNode('transitions') - ->beforeNormalization() - ->always() - ->then(function ($transitions) { - // It's an indexed array, we let the validation occur - if (isset($transitions[0]) && \is_array($transitions[0])) { - return $transitions; - } - - foreach ($transitions as $name => $transition) { - if (\is_array($transition) && \array_key_exists('name', $transition)) { - continue; - } - $transition['name'] = $name; - $transitions[$name] = $transition; - } - - return $transitions; - }) - ->end() - ->isRequired() - ->requiresAtLeastOneElement() - ->prototype('array') - ->children() - ->scalarNode('name') - ->isRequired() - ->cannotBeEmpty() - ->end() - ->scalarNode('guard') - ->cannotBeEmpty() - ->info('An expression to block the transition') - ->example('is_fully_authenticated() and is_granted(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'') - ->end() - ->arrayNode('from') - ->beforeNormalization() - ->ifString() - ->then(function ($v) { return [$v]; }) - ->end() - ->requiresAtLeastOneElement() - ->prototype('scalar') - ->cannotBeEmpty() - ->end() - ->end() - ->arrayNode('to') - ->beforeNormalization() - ->ifString() - ->then(function ($v) { return [$v]; }) - ->end() - ->requiresAtLeastOneElement() - ->prototype('scalar') - ->cannotBeEmpty() - ->end() - ->end() - ->arrayNode('metadata') - ->normalizeKeys(false) - ->defaultValue([]) - ->example(['color' => 'blue', 'description' => 'Workflow to manage article.']) - ->prototype('variable') - ->end() - ->end() - ->end() - ->end() - ->end() - ->arrayNode('metadata') - ->normalizeKeys(false) - ->defaultValue([]) - ->example(['color' => 'blue', 'description' => 'Workflow to manage article.']) - ->prototype('variable') - ->end() - ->end() - ->end() - ->validate() - ->ifTrue(function ($v) { - return $v['supports'] && isset($v['support_strategy']); - }) - ->thenInvalid('"supports" and "support_strategy" cannot be used together.') - ->end() - ->validate() - ->ifTrue(function ($v) { - return !$v['supports'] && !isset($v['support_strategy']); - }) - ->thenInvalid('"supports" or "support_strategy" should be configured.') - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addRouterSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('router') - ->info('router configuration') - ->canBeEnabled() - ->children() - ->scalarNode('resource')->isRequired()->end() - ->scalarNode('type')->end() - ->scalarNode('http_port')->defaultValue(80)->end() - ->scalarNode('https_port')->defaultValue(443)->end() - ->scalarNode('strict_requirements') - ->info( - "set to true to throw an exception when a parameter does not match the requirements\n". - "set to false to disable exceptions when a parameter does not match the requirements (and return null instead)\n". - "set to null to disable parameter checks against requirements\n". - "'true' is the preferred configuration in development mode, while 'false' or 'null' might be preferred in production" - ) - ->defaultTrue() - ->end() - ->booleanNode('utf8')->defaultFalse()->end() - ->end() - ->end() - ->end() - ; - } - - private function addSessionSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('session') - ->info('session configuration') - ->canBeEnabled() - ->children() - ->scalarNode('storage_id')->defaultValue('session.storage.native')->end() - ->scalarNode('handler_id')->defaultValue('session.handler.native_file')->end() - ->scalarNode('name') - ->validate() - ->ifTrue(function ($v) { - parse_str($v, $parsed); - - return implode('&', array_keys($parsed)) !== (string) $v; - }) - ->thenInvalid('Session name %s contains illegal character(s)') - ->end() - ->end() - ->scalarNode('cookie_lifetime')->end() - ->scalarNode('cookie_path')->end() - ->scalarNode('cookie_domain')->end() - ->enumNode('cookie_secure')->values([true, false, 'auto'])->end() - ->booleanNode('cookie_httponly')->defaultTrue()->end() - ->enumNode('cookie_samesite')->values([null, Cookie::SAMESITE_LAX, Cookie::SAMESITE_STRICT, Cookie::SAMESITE_NONE])->defaultNull()->end() - ->booleanNode('use_cookies')->end() - ->scalarNode('gc_divisor')->end() - ->scalarNode('gc_probability')->defaultValue(1)->end() - ->scalarNode('gc_maxlifetime')->end() - ->scalarNode('save_path')->defaultValue('%kernel.cache_dir%/sessions')->end() - ->integerNode('metadata_update_threshold') - ->defaultValue(0) - ->info('seconds to wait between 2 session metadata updates') - ->end() - ->integerNode('sid_length') - ->min(22) - ->max(256) - ->end() - ->integerNode('sid_bits_per_character') - ->min(4) - ->max(6) - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addRequestSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('request') - ->info('request configuration') - ->canBeEnabled() - ->fixXmlConfig('format') - ->children() - ->arrayNode('formats') - ->useAttributeAsKey('name') - ->prototype('array') - ->beforeNormalization() - ->ifTrue(function ($v) { return \is_array($v) && isset($v['mime_type']); }) - ->then(function ($v) { return $v['mime_type']; }) - ->end() - ->beforeNormalization()->castToArray()->end() - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addAssetsSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('assets') - ->info('assets configuration') - ->{!class_exists(FullStack::class) && class_exists(Package::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->fixXmlConfig('base_url') - ->children() - ->scalarNode('version_strategy')->defaultNull()->end() - ->scalarNode('version')->defaultNull()->end() - ->scalarNode('version_format')->defaultValue('%%s?%%s')->end() - ->scalarNode('json_manifest_path')->defaultNull()->end() - ->scalarNode('base_path')->defaultValue('')->end() - ->arrayNode('base_urls') - ->requiresAtLeastOneElement() - ->beforeNormalization()->castToArray()->end() - ->prototype('scalar')->end() - ->end() - ->end() - ->validate() - ->ifTrue(function ($v) { - return isset($v['version_strategy']) && isset($v['version']); - }) - ->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets".') - ->end() - ->validate() - ->ifTrue(function ($v) { - return isset($v['version_strategy']) && isset($v['json_manifest_path']); - }) - ->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets".') - ->end() - ->validate() - ->ifTrue(function ($v) { - return isset($v['version']) && isset($v['json_manifest_path']); - }) - ->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets".') - ->end() - ->fixXmlConfig('package') - ->children() - ->arrayNode('packages') - ->normalizeKeys(false) - ->useAttributeAsKey('name') - ->prototype('array') - ->fixXmlConfig('base_url') - ->children() - ->scalarNode('version_strategy')->defaultNull()->end() - ->scalarNode('version') - ->beforeNormalization() - ->ifTrue(function ($v) { return '' === $v; }) - ->then(function ($v) { return; }) - ->end() - ->end() - ->scalarNode('version_format')->defaultNull()->end() - ->scalarNode('json_manifest_path')->defaultNull()->end() - ->scalarNode('base_path')->defaultValue('')->end() - ->arrayNode('base_urls') - ->requiresAtLeastOneElement() - ->beforeNormalization()->castToArray()->end() - ->prototype('scalar')->end() - ->end() - ->end() - ->validate() - ->ifTrue(function ($v) { - return isset($v['version_strategy']) && isset($v['version']); - }) - ->thenInvalid('You cannot use both "version_strategy" and "version" at the same time under "assets" packages.') - ->end() - ->validate() - ->ifTrue(function ($v) { - return isset($v['version_strategy']) && isset($v['json_manifest_path']); - }) - ->thenInvalid('You cannot use both "version_strategy" and "json_manifest_path" at the same time under "assets" packages.') - ->end() - ->validate() - ->ifTrue(function ($v) { - return isset($v['version']) && isset($v['json_manifest_path']); - }) - ->thenInvalid('You cannot use both "version" and "json_manifest_path" at the same time under "assets" packages.') - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addTranslatorSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('translator') - ->info('translator configuration') - ->{!class_exists(FullStack::class) && class_exists(Translator::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->fixXmlConfig('fallback') - ->fixXmlConfig('path') - ->children() - ->arrayNode('fallbacks') - ->info('Defaults to the value of "default_locale".') - ->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end() - ->prototype('scalar')->end() - ->defaultValue([]) - ->end() - ->booleanNode('logging')->defaultValue(false)->end() - ->scalarNode('formatter')->defaultValue('translator.formatter.default')->end() - ->scalarNode('cache_dir')->defaultValue('%kernel.cache_dir%/translations')->end() - ->scalarNode('default_path') - ->info('The default path used to load translations') - ->defaultValue('%kernel.project_dir%/translations') - ->end() - ->arrayNode('paths') - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addValidationSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('validation') - ->info('validation configuration') - ->{!class_exists(FullStack::class) && class_exists(Validation::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->children() - ->scalarNode('cache')->end() - ->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && class_exists(Annotation::class) ? 'defaultTrue' : 'defaultFalse'}()->end() - ->arrayNode('static_method') - ->defaultValue(['loadValidatorMetadata']) - ->prototype('scalar')->end() - ->treatFalseLike([]) - ->validate()->castToArray()->end() - ->end() - ->scalarNode('translation_domain')->defaultValue('validators')->end() - ->enumNode('email_validation_mode')->values(['html5', 'loose', 'strict'])->end() - ->arrayNode('mapping') - ->addDefaultsIfNotSet() - ->fixXmlConfig('path') - ->children() - ->arrayNode('paths') - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->arrayNode('not_compromised_password') - ->canBeDisabled() - ->children() - ->booleanNode('enabled') - ->defaultTrue() - ->info('When disabled, compromised passwords will be accepted as valid.') - ->end() - ->scalarNode('endpoint') - ->defaultNull() - ->info('API endpoint for the NotCompromisedPassword Validator.') - ->end() - ->end() - ->end() - ->arrayNode('auto_mapping') - ->info('A collection of namespaces for which auto-mapping will be enabled by default, or null to opt-in with the EnableAutoMapping constraint.') - ->example([ - 'App\\Entity\\' => [], - 'App\\WithSpecificLoaders\\' => ['validator.property_info_loader'], - ]) - ->useAttributeAsKey('namespace') - ->normalizeKeys(false) - ->beforeNormalization() - ->ifArray() - ->then(function (array $values): array { - foreach ($values as $k => $v) { - if (isset($v['service'])) { - continue; - } - - if (isset($v['namespace'])) { - $values[$k]['services'] = []; - continue; - } - - if (!\is_array($v)) { - $values[$v]['services'] = []; - unset($values[$k]); - continue; - } - - $tmp = $v; - unset($values[$k]); - $values[$k]['services'] = $tmp; - } - - return $values; - }) - ->end() - ->arrayPrototype() - ->fixXmlConfig('service') - ->children() - ->arrayNode('services') - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addAnnotationsSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('annotations') - ->info('annotation configuration') - ->{class_exists(Annotation::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->children() - ->scalarNode('cache')->defaultValue(interface_exists(Cache::class) ? 'php_array' : 'none')->end() - ->scalarNode('file_cache_dir')->defaultValue('%kernel.cache_dir%/annotations')->end() - ->booleanNode('debug')->defaultValue($this->debug)->end() - ->end() - ->end() - ->end() - ; - } - - private function addSerializerSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('serializer') - ->info('serializer configuration') - ->{!class_exists(FullStack::class) && class_exists(Serializer::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->children() - ->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && class_exists(Annotation::class) ? 'defaultTrue' : 'defaultFalse'}()->end() - ->scalarNode('name_converter')->end() - ->scalarNode('circular_reference_handler')->end() - ->scalarNode('max_depth_handler')->end() - ->arrayNode('mapping') - ->addDefaultsIfNotSet() - ->fixXmlConfig('path') - ->children() - ->arrayNode('paths') - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addPropertyAccessSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('property_access') - ->addDefaultsIfNotSet() - ->info('Property access configuration') - ->children() - ->booleanNode('magic_call')->defaultFalse()->end() - ->booleanNode('throw_exception_on_invalid_index')->defaultFalse()->end() - ->booleanNode('throw_exception_on_invalid_property_path')->defaultTrue()->end() - ->end() - ->end() - ->end() - ; - } - - private function addPropertyInfoSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('property_info') - ->info('Property info configuration') - ->{!class_exists(FullStack::class) && interface_exists(PropertyInfoExtractorInterface::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->end() - ->end() - ; - } - - private function addCacheSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('cache') - ->info('Cache configuration') - ->addDefaultsIfNotSet() - ->fixXmlConfig('pool') - ->children() - ->scalarNode('prefix_seed') - ->info('Used to namespace cache keys when using several apps with the same shared backend') - ->example('my-application-name') - ->end() - ->scalarNode('app') - ->info('App related cache pools configuration') - ->defaultValue('cache.adapter.filesystem') - ->end() - ->scalarNode('system') - ->info('System related cache pools configuration') - ->defaultValue('cache.adapter.system') - ->end() - ->scalarNode('directory')->defaultValue('%kernel.cache_dir%/pools')->end() - ->scalarNode('default_doctrine_provider')->end() - ->scalarNode('default_psr6_provider')->end() - ->scalarNode('default_redis_provider')->defaultValue('redis://localhost')->end() - ->scalarNode('default_memcached_provider')->defaultValue('memcached://localhost')->end() - ->scalarNode('default_pdo_provider')->defaultValue(class_exists(Connection::class) ? 'database_connection' : null)->end() - ->arrayNode('pools') - ->useAttributeAsKey('name') - ->prototype('array') - ->fixXmlConfig('adapter') - ->beforeNormalization() - ->ifTrue(function ($v) { return (isset($v['adapters']) || \is_array($v['adapter'] ?? null)) && isset($v['provider']); }) - ->thenInvalid('Pool cannot have a "provider" while "adapter" is set to a map') - ->end() - ->children() - ->arrayNode('adapters') - ->performNoDeepMerging() - ->info('One or more adapters to chain for creating the pool, defaults to "cache.app".') - ->beforeNormalization() - ->always()->then(function ($values) { - if ([0] === array_keys($values) && \is_array($values[0])) { - return $values[0]; - } - $adapters = []; - - foreach ($values as $k => $v) { - if (\is_int($k) && \is_string($v)) { - $adapters[] = $v; - } elseif (!\is_array($v)) { - $adapters[$k] = $v; - } elseif (isset($v['provider'])) { - $adapters[$v['provider']] = $v['name'] ?? $v; - } else { - $adapters[] = $v['name'] ?? $v; - } - } - - return $adapters; - }) - ->end() - ->prototype('scalar')->end() - ->end() - ->scalarNode('tags')->defaultNull()->end() - ->booleanNode('public')->defaultFalse()->end() - ->integerNode('default_lifetime')->end() - ->scalarNode('provider') - ->info('Overwrite the setting from the default provider for this adapter.') - ->end() - ->scalarNode('clearer')->end() - ->end() - ->end() - ->validate() - ->ifTrue(function ($v) { return isset($v['cache.app']) || isset($v['cache.system']); }) - ->thenInvalid('"cache.app" and "cache.system" are reserved names') - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addPhpErrorsSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('php_errors') - ->info('PHP errors handling configuration') - ->addDefaultsIfNotSet() - ->children() - ->scalarNode('log') - ->info('Use the application logger instead of the PHP logger for logging PHP errors.') - ->example('"true" to use the default configuration: log all errors. "false" to disable. An integer bit field of E_* constants.') - ->defaultValue($this->debug) - ->treatNullLike($this->debug) - ->validate() - ->ifTrue(function ($v) { return !(\is_int($v) || \is_bool($v)); }) - ->thenInvalid('The "php_errors.log" parameter should be either an integer or a boolean.') - ->end() - ->end() - ->booleanNode('throw') - ->info('Throw PHP errors as \ErrorException instances.') - ->defaultValue($this->debug) - ->treatNullLike($this->debug) - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addLockSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('lock') - ->info('Lock configuration') - ->{!class_exists(FullStack::class) && class_exists(Lock::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->beforeNormalization() - ->ifString()->then(function ($v) { return ['enabled' => true, 'resources' => $v]; }) - ->end() - ->beforeNormalization() - ->ifTrue(function ($v) { return \is_array($v) && !isset($v['enabled']); }) - ->then(function ($v) { return $v + ['enabled' => true]; }) - ->end() - ->beforeNormalization() - ->ifTrue(function ($v) { return \is_array($v) && !isset($v['resources']) && !isset($v['resource']); }) - ->then(function ($v) { - $e = $v['enabled']; - unset($v['enabled']); - - return ['enabled' => $e, 'resources' => $v]; - }) - ->end() - ->addDefaultsIfNotSet() - ->fixXmlConfig('resource') - ->children() - ->arrayNode('resources') - ->requiresAtLeastOneElement() - ->defaultValue(['default' => [class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphore' : 'flock']]) - ->beforeNormalization() - ->ifString()->then(function ($v) { return ['default' => $v]; }) - ->end() - ->beforeNormalization() - ->ifTrue(function ($v) { return \is_array($v) && array_keys($v) === range(0, \count($v) - 1); }) - ->then(function ($v) { - $resources = []; - foreach ($v as $resource) { - $resources = array_merge_recursive( - $resources, - \is_array($resource) && isset($resource['name']) - ? [$resource['name'] => $resource['value']] - : ['default' => $resource] - ); - } - - return $resources; - }) - ->end() - ->prototype('array') - ->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end() - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addWebLinkSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('web_link') - ->info('web links configuration') - ->{!class_exists(FullStack::class) && class_exists(HttpHeaderSerializer::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->end() - ->end() - ; - } - - private function addMessengerSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('messenger') - ->info('Messenger configuration') - ->{!class_exists(FullStack::class) && interface_exists(MessageBusInterface::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->fixXmlConfig('transport') - ->fixXmlConfig('bus', 'buses') - ->validate() - ->ifTrue(function ($v) { return isset($v['buses']) && \count($v['buses']) > 1 && null === $v['default_bus']; }) - ->thenInvalid('You must specify the "default_bus" if you define more than one bus.') - ->end() - ->validate() - ->ifTrue(static function ($v): bool { return isset($v['buses']) && null !== $v['default_bus'] && !isset($v['buses'][$v['default_bus']]); }) - ->then(static function (array $v): void { throw new InvalidConfigurationException(sprintf('The specified default bus "%s" is not configured. Available buses are "%s".', $v['default_bus'], implode('", "', array_keys($v['buses'])))); }) - ->end() - ->children() - ->arrayNode('routing') - ->normalizeKeys(false) - ->useAttributeAsKey('message_class') - ->beforeNormalization() - ->always() - ->then(function ($config) { - if (!\is_array($config)) { - return []; - } - - $newConfig = []; - foreach ($config as $k => $v) { - if (!\is_int($k)) { - $newConfig[$k] = [ - 'senders' => $v['senders'] ?? (\is_array($v) ? array_values($v) : [$v]), - ]; - } else { - $newConfig[$v['message-class']]['senders'] = array_map( - function ($a) { - return \is_string($a) ? $a : $a['service']; - }, - array_values($v['sender']) - ); - } - } - - return $newConfig; - }) - ->end() - ->prototype('array') - ->performNoDeepMerging() - ->children() - ->arrayNode('senders') - ->requiresAtLeastOneElement() - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->end() - ->arrayNode('serializer') - ->addDefaultsIfNotSet() - ->children() - ->scalarNode('default_serializer') - ->defaultValue('messenger.transport.native_php_serializer') - ->info('Service id to use as the default serializer for the transports.') - ->end() - ->arrayNode('symfony_serializer') - ->addDefaultsIfNotSet() - ->children() - ->scalarNode('format')->defaultValue('json')->info('Serialization format for the messenger.transport.symfony_serializer service (which is not the serializer used by default).')->end() - ->arrayNode('context') - ->normalizeKeys(false) - ->useAttributeAsKey('name') - ->defaultValue([]) - ->info('Context array for the messenger.transport.symfony_serializer service (which is not the serializer used by default).') - ->prototype('variable')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->arrayNode('transports') - ->normalizeKeys(false) - ->useAttributeAsKey('name') - ->arrayPrototype() - ->beforeNormalization() - ->ifString() - ->then(function (string $dsn) { - return ['dsn' => $dsn]; - }) - ->end() - ->fixXmlConfig('option') - ->children() - ->scalarNode('dsn')->end() - ->scalarNode('serializer')->defaultNull()->info('Service id of a custom serializer to use.')->end() - ->arrayNode('options') - ->normalizeKeys(false) - ->defaultValue([]) - ->prototype('variable') - ->end() - ->end() - ->arrayNode('retry_strategy') - ->addDefaultsIfNotSet() - ->beforeNormalization() - ->always(function ($v) { - if (isset($v['service']) && (isset($v['max_retries']) || isset($v['delay']) || isset($v['multiplier']) || isset($v['max_delay']))) { - throw new \InvalidArgumentException('The "service" cannot be used along with the other "retry_strategy" options.'); - } - - return $v; - }) - ->end() - ->children() - ->scalarNode('service')->defaultNull()->info('Service id to override the retry strategy entirely')->end() - ->integerNode('max_retries')->defaultValue(3)->min(0)->end() - ->integerNode('delay')->defaultValue(1000)->min(0)->info('Time in ms to delay (or the initial value when multiplier is used)')->end() - ->floatNode('multiplier')->defaultValue(2)->min(1)->info('If greater than 1, delay will grow exponentially for each retry: this delay = (delay * (multiple ^ retries))')->end() - ->integerNode('max_delay')->defaultValue(0)->min(0)->info('Max time in ms that a retry should ever be delayed (0 = infinite)')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->scalarNode('failure_transport') - ->defaultNull() - ->info('Transport name to send failed messages to (after all retries have failed).') - ->end() - ->scalarNode('default_bus')->defaultNull()->end() - ->arrayNode('buses') - ->defaultValue(['messenger.bus.default' => ['default_middleware' => true, 'middleware' => []]]) - ->normalizeKeys(false) - ->useAttributeAsKey('name') - ->arrayPrototype() - ->addDefaultsIfNotSet() - ->children() - ->enumNode('default_middleware') - ->values([true, false, 'allow_no_handlers']) - ->defaultTrue() - ->end() - ->arrayNode('middleware') - ->performNoDeepMerging() - ->beforeNormalization() - ->ifTrue(function ($v) { return \is_string($v) || (\is_array($v) && !\is_int(key($v))); }) - ->then(function ($v) { return [$v]; }) - ->end() - ->defaultValue([]) - ->arrayPrototype() - ->beforeNormalization() - ->always() - ->then(function ($middleware): array { - if (!\is_array($middleware)) { - return ['id' => $middleware]; - } - if (isset($middleware['id'])) { - return $middleware; - } - if (1 < \count($middleware)) { - throw new \InvalidArgumentException(sprintf('Invalid middleware at path "framework.messenger": a map with a single factory id as key and its arguments as value was expected, %s given.', json_encode($middleware))); - } - - return [ - 'id' => key($middleware), - 'arguments' => current($middleware), - ]; - }) - ->end() - ->fixXmlConfig('argument') - ->children() - ->scalarNode('id')->isRequired()->cannotBeEmpty()->end() - ->arrayNode('arguments') - ->normalizeKeys(false) - ->defaultValue([]) - ->prototype('variable') - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addRobotsIndexSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->booleanNode('disallow_search_engine_index') - ->info('Enabled by default when debug is enabled.') - ->defaultValue($this->debug) - ->treatNullLike($this->debug) - ->end() - ->end() - ; - } - - private function addHttpClientSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('http_client') - ->info('HTTP Client configuration') - ->{!class_exists(FullStack::class) && class_exists(HttpClient::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->fixXmlConfig('scoped_client') - ->children() - ->integerNode('max_host_connections') - ->info('The maximum number of connections to a single host.') - ->end() - ->arrayNode('default_options') - ->fixXmlConfig('header') - ->children() - ->arrayNode('headers') - ->info('Associative array: header => value(s).') - ->useAttributeAsKey('name') - ->normalizeKeys(false) - ->variablePrototype()->end() - ->end() - ->integerNode('max_redirects') - ->info('The maximum number of redirects to follow.') - ->end() - ->scalarNode('http_version') - ->info('The default HTTP version, typically 1.1 or 2.0, leave to null for the best version.') - ->end() - ->arrayNode('resolve') - ->info('Associative array: domain => IP.') - ->useAttributeAsKey('host') - ->beforeNormalization() - ->always(function ($config) { - if (!\is_array($config)) { - return []; - } - if (!isset($config['host'])) { - return $config; - } - - return [$config['host'] => $config['value']]; - }) - ->end() - ->normalizeKeys(false) - ->scalarPrototype()->end() - ->end() - ->scalarNode('proxy') - ->info('The URL of the proxy to pass requests through or null for automatic detection.') - ->end() - ->scalarNode('no_proxy') - ->info('A comma separated list of hosts that do not require a proxy to be reached.') - ->end() - ->floatNode('timeout') - ->info('The idle timeout, defaults to the "default_socket_timeout" ini parameter.') - ->end() - ->floatNode('max_duration') - ->info('The maximum execution time for the request+response as a whole.') - ->end() - ->scalarNode('bindto') - ->info('A network interface name, IP address, a host name or a UNIX socket to bind to.') - ->end() - ->booleanNode('verify_peer') - ->info('Indicates if the peer should be verified in a SSL/TLS context.') - ->end() - ->booleanNode('verify_host') - ->info('Indicates if the host should exist as a certificate common name.') - ->end() - ->scalarNode('cafile') - ->info('A certificate authority file.') - ->end() - ->scalarNode('capath') - ->info('A directory that contains multiple certificate authority files.') - ->end() - ->scalarNode('local_cert') - ->info('A PEM formatted certificate file.') - ->end() - ->scalarNode('local_pk') - ->info('A private key file.') - ->end() - ->scalarNode('passphrase') - ->info('The passphrase used to encrypt the "local_pk" file.') - ->end() - ->scalarNode('ciphers') - ->info('A list of SSL/TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...)') - ->end() - ->arrayNode('peer_fingerprint') - ->info('Associative array: hashing algorithm => hash(es).') - ->normalizeKeys(false) - ->children() - ->variableNode('sha1')->end() - ->variableNode('pin-sha256')->end() - ->variableNode('md5')->end() - ->end() - ->end() - ->end() - ->end() - ->arrayNode('scoped_clients') - ->useAttributeAsKey('name') - ->normalizeKeys(false) - ->arrayPrototype() - ->fixXmlConfig('header') - ->beforeNormalization() - ->always() - ->then(function ($config) { - if (!class_exists(HttpClient::class)) { - throw new LogicException('HttpClient support cannot be enabled as the component is not installed. Try running "composer require symfony/http-client".'); - } - - return \is_array($config) ? $config : ['base_uri' => $config]; - }) - ->end() - ->validate() - ->ifTrue(function ($v) { return !isset($v['scope']) && !isset($v['base_uri']); }) - ->thenInvalid('Either "scope" or "base_uri" should be defined.') - ->end() - ->validate() - ->ifTrue(function ($v) { return isset($v['query']) && !isset($v['base_uri']); }) - ->thenInvalid('"query" applies to "base_uri" but no base URI is defined.') - ->end() - ->children() - ->scalarNode('scope') - ->info('The regular expression that the request URL must match before adding the other options. When none is provided, the base URI is used instead.') - ->cannotBeEmpty() - ->end() - ->scalarNode('base_uri') - ->info('The URI to resolve relative URLs, following rules in RFC 3985, section 2.') - ->cannotBeEmpty() - ->end() - ->scalarNode('auth_basic') - ->info('An HTTP Basic authentication "username:password".') - ->end() - ->scalarNode('auth_bearer') - ->info('A token enabling HTTP Bearer authorization.') - ->end() - ->scalarNode('auth_ntlm') - ->info('A "username:password" pair to use Microsoft NTLM authentication (requires the cURL extension).') - ->end() - ->arrayNode('query') - ->info('Associative array of query string values merged with the base URI.') - ->useAttributeAsKey('key') - ->beforeNormalization() - ->always(function ($config) { - if (!\is_array($config)) { - return []; - } - if (!isset($config['key'])) { - return $config; - } - - return [$config['key'] => $config['value']]; - }) - ->end() - ->normalizeKeys(false) - ->scalarPrototype()->end() - ->end() - ->arrayNode('headers') - ->info('Associative array: header => value(s).') - ->useAttributeAsKey('name') - ->normalizeKeys(false) - ->variablePrototype()->end() - ->end() - ->integerNode('max_redirects') - ->info('The maximum number of redirects to follow.') - ->end() - ->scalarNode('http_version') - ->info('The default HTTP version, typically 1.1 or 2.0, leave to null for the best version.') - ->end() - ->arrayNode('resolve') - ->info('Associative array: domain => IP.') - ->useAttributeAsKey('host') - ->beforeNormalization() - ->always(function ($config) { - if (!\is_array($config)) { - return []; - } - if (!isset($config['host'])) { - return $config; - } - - return [$config['host'] => $config['value']]; - }) - ->end() - ->normalizeKeys(false) - ->scalarPrototype()->end() - ->end() - ->scalarNode('proxy') - ->info('The URL of the proxy to pass requests through or null for automatic detection.') - ->end() - ->scalarNode('no_proxy') - ->info('A comma separated list of hosts that do not require a proxy to be reached.') - ->end() - ->floatNode('timeout') - ->info('The idle timeout, defaults to the "default_socket_timeout" ini parameter.') - ->end() - ->floatNode('max_duration') - ->info('The maximum execution time for the request+response as a whole.') - ->end() - ->scalarNode('bindto') - ->info('A network interface name, IP address, a host name or a UNIX socket to bind to.') - ->end() - ->booleanNode('verify_peer') - ->info('Indicates if the peer should be verified in a SSL/TLS context.') - ->end() - ->booleanNode('verify_host') - ->info('Indicates if the host should exist as a certificate common name.') - ->end() - ->scalarNode('cafile') - ->info('A certificate authority file.') - ->end() - ->scalarNode('capath') - ->info('A directory that contains multiple certificate authority files.') - ->end() - ->scalarNode('local_cert') - ->info('A PEM formatted certificate file.') - ->end() - ->scalarNode('local_pk') - ->info('A private key file.') - ->end() - ->scalarNode('passphrase') - ->info('The passphrase used to encrypt the "local_pk" file.') - ->end() - ->scalarNode('ciphers') - ->info('A list of SSL/TLS ciphers separated by colons, commas or spaces (e.g. "RC3-SHA:TLS13-AES-128-GCM-SHA256"...)') - ->end() - ->arrayNode('peer_fingerprint') - ->info('Associative array: hashing algorithm => hash(es).') - ->normalizeKeys(false) - ->children() - ->variableNode('sha1')->end() - ->variableNode('pin-sha256')->end() - ->variableNode('md5')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addMailerSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('mailer') - ->info('Mailer configuration') - ->{!class_exists(FullStack::class) && class_exists(Mailer::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->validate() - ->ifTrue(function ($v) { return isset($v['dsn']) && \count($v['transports']); }) - ->thenInvalid('"dsn" and "transports" cannot be used together.') - ->end() - ->fixXmlConfig('transport') - ->children() - ->scalarNode('dsn')->defaultNull()->end() - ->arrayNode('transports') - ->useAttributeAsKey('name') - ->prototype('scalar')->end() - ->end() - ->arrayNode('envelope') - ->info('Mailer Envelope configuration') - ->children() - ->scalarNode('sender')->end() - ->arrayNode('recipients') - ->performNoDeepMerging() - ->beforeNormalization() - ->ifArray() - ->then(function ($v) { - return array_filter(array_values($v)); - }) - ->end() - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - - private function addNotifierSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('notifier') - ->info('Notifier configuration') - ->{!class_exists(FullStack::class) && class_exists(Notifier::class) ? 'canBeDisabled' : 'canBeEnabled'}() - ->fixXmlConfig('chatter_transport') - ->children() - ->arrayNode('chatter_transports') - ->useAttributeAsKey('name') - ->prototype('scalar')->end() - ->end() - ->end() - ->fixXmlConfig('texter_transport') - ->children() - ->arrayNode('texter_transports') - ->useAttributeAsKey('name') - ->prototype('scalar')->end() - ->end() - ->end() - ->children() - ->booleanNode('notification_on_failed_messages')->defaultFalse()->end() - ->end() - ->children() - ->arrayNode('channel_policy') - ->useAttributeAsKey('name') - ->prototype('array') - ->beforeNormalization()->ifString()->then(function (string $v) { return [$v]; })->end() - ->prototype('scalar')->end() - ->end() - ->end() - ->end() - ->fixXmlConfig('admin_recipient') - ->children() - ->arrayNode('admin_recipients') - ->prototype('array') - ->children() - ->scalarNode('email')->cannotBeEmpty()->end() - ->scalarNode('phone')->defaultValue('')->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } -} diff --git a/vendor/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php b/vendor/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php deleted file mode 100644 index 8f1b86b..0000000 --- a/vendor/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php +++ /dev/null @@ -1,1989 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection; - -use Doctrine\Common\Annotations\AnnotationRegistry; -use Doctrine\Common\Annotations\Reader; -use Http\Client\HttpClient; -use Psr\Cache\CacheItemPoolInterface; -use Psr\Container\ContainerInterface as PsrContainerInterface; -use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface; -use Psr\Http\Client\ClientInterface; -use Psr\Log\LoggerAwareInterface; -use Symfony\Bridge\Monolog\Processor\DebugProcessor; -use Symfony\Bridge\Twig\Extension\CsrfExtension; -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader; -use Symfony\Bundle\FrameworkBundle\Routing\RouteLoaderInterface; -use Symfony\Bundle\FullStack; -use Symfony\Component\Asset\PackageInterface; -use Symfony\Component\BrowserKit\AbstractBrowser; -use Symfony\Component\Cache\Adapter\AdapterInterface; -use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\ChainAdapter; -use Symfony\Component\Cache\Adapter\TagAwareAdapter; -use Symfony\Component\Cache\DependencyInjection\CachePoolPass; -use Symfony\Component\Cache\Marshaller\DefaultMarshaller; -use Symfony\Component\Cache\Marshaller\MarshallerInterface; -use Symfony\Component\Cache\ResettableInterface; -use Symfony\Component\Config\FileLocator; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\Config\Resource\DirectoryResource; -use Symfony\Component\Config\ResourceCheckerInterface; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\EnvVarLoaderInterface; -use Symfony\Component\DependencyInjection\EnvVarProcessorInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\LogicException; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ServiceLocator; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\Finder\Finder; -use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator; -use Symfony\Component\Form\FormTypeExtensionInterface; -use Symfony\Component\Form\FormTypeGuesserInterface; -use Symfony\Component\Form\FormTypeInterface; -use Symfony\Component\HttpClient\ScopingHttpClient; -use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; -use Symfony\Component\HttpKernel\DependencyInjection\Extension; -use Symfony\Component\Lock\Lock; -use Symfony\Component\Lock\LockFactory; -use Symfony\Component\Lock\LockInterface; -use Symfony\Component\Lock\PersistingStoreInterface; -use Symfony\Component\Lock\Store\StoreFactory; -use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesTransportFactory; -use Symfony\Component\Mailer\Bridge\Google\Transport\GmailTransportFactory; -use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; -use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; -use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; -use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; -use Symfony\Component\Mailer\Mailer; -use Symfony\Component\Messenger\Handler\MessageHandlerInterface; -use Symfony\Component\Messenger\MessageBus; -use Symfony\Component\Messenger\MessageBusInterface; -use Symfony\Component\Messenger\Transport\TransportFactoryInterface; -use Symfony\Component\Messenger\Transport\TransportInterface; -use Symfony\Component\Mime\MimeTypeGuesserInterface; -use Symfony\Component\Mime\MimeTypes; -use Symfony\Component\Notifier\Bridge\Nexmo\NexmoTransportFactory; -use Symfony\Component\Notifier\Bridge\Slack\SlackTransportFactory; -use Symfony\Component\Notifier\Bridge\Telegram\TelegramTransportFactory; -use Symfony\Component\Notifier\Bridge\Twilio\TwilioTransportFactory; -use Symfony\Component\Notifier\Notifier; -use Symfony\Component\Notifier\Recipient\AdminRecipient; -use Symfony\Component\PropertyAccess\PropertyAccessor; -use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyInitializableExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; -use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; -use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader; -use Symfony\Component\Routing\Loader\AnnotationFileLoader; -use Symfony\Component\Security\Core\Security; -use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; -use Symfony\Component\Serializer\Encoder\DecoderInterface; -use Symfony\Component\Serializer\Encoder\EncoderInterface; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Symfony\Component\Stopwatch\Stopwatch; -use Symfony\Component\String\Slugger\SluggerInterface; -use Symfony\Component\Translation\Command\XliffLintCommand as BaseXliffLintCommand; -use Symfony\Component\Translation\Translator; -use Symfony\Component\Validator\ConstraintValidatorInterface; -use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader; -use Symfony\Component\Validator\ObjectInitializerInterface; -use Symfony\Component\WebLink\HttpHeaderSerializer; -use Symfony\Component\Workflow; -use Symfony\Component\Workflow\WorkflowInterface; -use Symfony\Component\Yaml\Command\LintCommand as BaseYamlLintCommand; -use Symfony\Component\Yaml\Yaml; -use Symfony\Contracts\Cache\CacheInterface; -use Symfony\Contracts\Cache\TagAwareCacheInterface; -use Symfony\Contracts\HttpClient\HttpClientInterface; -use Symfony\Contracts\Service\ResetInterface; -use Symfony\Contracts\Service\ServiceSubscriberInterface; -use Symfony\Contracts\Translation\LocaleAwareInterface; - -/** - * FrameworkExtension. - * - * @author Fabien Potencier - * @author Jeremy Mikola - * @author Kévin Dunglas - * @author Grégoire Pineau - */ -class FrameworkExtension extends Extension -{ - private $formConfigEnabled = false; - private $translationConfigEnabled = false; - private $sessionConfigEnabled = false; - private $annotationsConfigEnabled = false; - private $validatorConfigEnabled = false; - private $messengerConfigEnabled = false; - private $mailerConfigEnabled = false; - private $httpClientConfigEnabled = false; - - /** - * Responds to the app.config configuration parameter. - * - * @throws LogicException - */ - public function load(array $configs, ContainerBuilder $container) - { - $loader = new XmlFileLoader($container, new FileLocator(\dirname(__DIR__).'/Resources/config')); - - $loader->load('web.xml'); - $loader->load('services.xml'); - $loader->load('fragment_renderer.xml'); - $loader->load('error_renderer.xml'); - - if (interface_exists(PsrEventDispatcherInterface::class)) { - $container->setAlias(PsrEventDispatcherInterface::class, 'event_dispatcher'); - } - - $container->registerAliasForArgument('parameter_bag', PsrContainerInterface::class); - - if (class_exists(Application::class)) { - $loader->load('console.xml'); - - if (!class_exists(BaseXliffLintCommand::class)) { - $container->removeDefinition('console.command.xliff_lint'); - } - if (!class_exists(BaseYamlLintCommand::class)) { - $container->removeDefinition('console.command.yaml_lint'); - } - } - - // Load Cache configuration first as it is used by other components - $loader->load('cache.xml'); - - $configuration = $this->getConfiguration($configs, $container); - $config = $this->processConfiguration($configuration, $configs); - - $this->annotationsConfigEnabled = $this->isConfigEnabled($container, $config['annotations']); - $this->translationConfigEnabled = $this->isConfigEnabled($container, $config['translator']); - - // A translator must always be registered (as support is included by - // default in the Form and Validator component). If disabled, an identity - // translator will be used and everything will still work as expected. - if ($this->isConfigEnabled($container, $config['translator']) || $this->isConfigEnabled($container, $config['form']) || $this->isConfigEnabled($container, $config['validation'])) { - if (!class_exists('Symfony\Component\Translation\Translator') && $this->isConfigEnabled($container, $config['translator'])) { - throw new LogicException('Translation support cannot be enabled as the Translation component is not installed. Try running "composer require symfony/translation".'); - } - - if (class_exists(Translator::class)) { - $loader->load('identity_translator.xml'); - } - } - - // If the slugger is used but the String component is not available, we should throw an error - if (!interface_exists(SluggerInterface::class)) { - $container->register('slugger', 'stdClass') - ->addError('You cannot use the "slugger" service since the String component is not installed. Try running "composer require symfony/string".'); - } else { - if (!interface_exists(LocaleAwareInterface::class)) { - $container->register('slugger', 'stdClass') - ->addError('You cannot use the "slugger" service since the Translation contracts are not installed. Try running "composer require symfony/translation".'); - } - - if (!\extension_loaded('intl') && !\defined('PHPUNIT_COMPOSER_INSTALL')) { - @trigger_error('Please install the "intl" PHP extension for best performance.', E_USER_DEPRECATED); - } - } - - if (isset($config['secret'])) { - $container->setParameter('kernel.secret', $config['secret']); - } - - $container->setParameter('kernel.http_method_override', $config['http_method_override']); - $container->setParameter('kernel.trusted_hosts', $config['trusted_hosts']); - $container->setParameter('kernel.default_locale', $config['default_locale']); - $container->setParameter('kernel.error_controller', $config['error_controller']); - - if (!$container->hasParameter('debug.file_link_format')) { - $links = [ - 'textmate' => 'txmt://open?url=file://%%f&line=%%l', - 'macvim' => 'mvim://open?url=file://%%f&line=%%l', - 'emacs' => 'emacs://open?url=file://%%f&line=%%l', - 'sublime' => 'subl://open?url=file://%%f&line=%%l', - 'phpstorm' => 'phpstorm://open?file=%%f&line=%%l', - 'atom' => 'atom://core/open/file?filename=%%f&line=%%l', - 'vscode' => 'vscode://file/%%f:%%l', - ]; - $ide = $config['ide']; - // mark any env vars found in the ide setting as used - $container->resolveEnvPlaceholders($ide); - - $container->setParameter('debug.file_link_format', str_replace('%', '%%', ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')) ?: (isset($links[$ide]) ? $links[$ide] : $ide)); - } - - if (!empty($config['test'])) { - $loader->load('test.xml'); - - if (!class_exists(AbstractBrowser::class)) { - $container->removeDefinition('test.client'); - } - } - - // register cache before session so both can share the connection services - $this->registerCacheConfiguration($config['cache'], $container); - - if ($this->isConfigEnabled($container, $config['session'])) { - if (!\extension_loaded('session')) { - throw new LogicException('Session support cannot be enabled as the session extension is not installed. See https://php.net/session.installation for instructions.'); - } - - $this->sessionConfigEnabled = true; - $this->registerSessionConfiguration($config['session'], $container, $loader); - if (!empty($config['test'])) { - $container->getDefinition('test.session.listener')->setArgument(1, '%session.storage.options%'); - } - } - - if ($this->isConfigEnabled($container, $config['request'])) { - $this->registerRequestConfiguration($config['request'], $container, $loader); - } - - if (null === $config['csrf_protection']['enabled']) { - $config['csrf_protection']['enabled'] = $this->sessionConfigEnabled && !class_exists(FullStack::class) && interface_exists(CsrfTokenManagerInterface::class); - } - $this->registerSecurityCsrfConfiguration($config['csrf_protection'], $container, $loader); - - if ($this->isConfigEnabled($container, $config['form'])) { - if (!class_exists('Symfony\Component\Form\Form')) { - throw new LogicException('Form support cannot be enabled as the Form component is not installed. Try running "composer require symfony/form".'); - } - - $this->formConfigEnabled = true; - $this->registerFormConfiguration($config, $container, $loader); - - if (class_exists('Symfony\Component\Validator\Validation')) { - $config['validation']['enabled'] = true; - } else { - $container->setParameter('validator.translation_domain', 'validators'); - - $container->removeDefinition('form.type_extension.form.validator'); - $container->removeDefinition('form.type_guesser.validator'); - } - } else { - $container->removeDefinition('console.command.form_debug'); - } - - if ($this->isConfigEnabled($container, $config['assets'])) { - if (!class_exists('Symfony\Component\Asset\Package')) { - throw new LogicException('Asset support cannot be enabled as the Asset component is not installed. Try running "composer require symfony/asset".'); - } - - $this->registerAssetsConfiguration($config['assets'], $container, $loader); - } - - if ($this->messengerConfigEnabled = $this->isConfigEnabled($container, $config['messenger'])) { - $this->registerMessengerConfiguration($config['messenger'], $container, $loader, $config['validation']); - } else { - $container->removeDefinition('console.command.messenger_consume_messages'); - $container->removeDefinition('console.command.messenger_debug'); - $container->removeDefinition('console.command.messenger_stop_workers'); - $container->removeDefinition('console.command.messenger_setup_transports'); - $container->removeDefinition('console.command.messenger_failed_messages_retry'); - $container->removeDefinition('console.command.messenger_failed_messages_show'); - $container->removeDefinition('console.command.messenger_failed_messages_remove'); - } - - if ($this->httpClientConfigEnabled = $this->isConfigEnabled($container, $config['http_client'])) { - $this->registerHttpClientConfiguration($config['http_client'], $container, $loader, $config['profiler']); - } - - if ($this->mailerConfigEnabled = $this->isConfigEnabled($container, $config['mailer'])) { - $this->registerMailerConfiguration($config['mailer'], $container, $loader); - } - - if ($this->isConfigEnabled($container, $config['notifier'])) { - $this->registerNotifierConfiguration($config['notifier'], $container, $loader); - } - - $propertyInfoEnabled = $this->isConfigEnabled($container, $config['property_info']); - $this->registerValidationConfiguration($config['validation'], $container, $loader, $propertyInfoEnabled); - $this->registerEsiConfiguration($config['esi'], $container, $loader); - $this->registerSsiConfiguration($config['ssi'], $container, $loader); - $this->registerFragmentsConfiguration($config['fragments'], $container, $loader); - $this->registerTranslatorConfiguration($config['translator'], $container, $loader, $config['default_locale']); - $this->registerProfilerConfiguration($config['profiler'], $container, $loader); - $this->registerWorkflowConfiguration($config['workflows'], $container, $loader); - $this->registerDebugConfiguration($config['php_errors'], $container, $loader); - $this->registerRouterConfiguration($config['router'], $container, $loader); - $this->registerAnnotationsConfiguration($config['annotations'], $container, $loader); - $this->registerPropertyAccessConfiguration($config['property_access'], $container, $loader); - $this->registerSecretsConfiguration($config['secrets'], $container, $loader); - - if ($this->isConfigEnabled($container, $config['serializer'])) { - if (!class_exists('Symfony\Component\Serializer\Serializer')) { - throw new LogicException('Serializer support cannot be enabled as the Serializer component is not installed. Try running "composer require symfony/serializer-pack".'); - } - - $this->registerSerializerConfiguration($config['serializer'], $container, $loader); - } - - if ($propertyInfoEnabled) { - $this->registerPropertyInfoConfiguration($container, $loader); - } - - if ($this->isConfigEnabled($container, $config['lock'])) { - $this->registerLockConfiguration($config['lock'], $container, $loader); - } - - if ($this->isConfigEnabled($container, $config['web_link'])) { - if (!class_exists(HttpHeaderSerializer::class)) { - throw new LogicException('WebLink support cannot be enabled as the WebLink component is not installed. Try running "composer require symfony/weblink".'); - } - - $loader->load('web_link.xml'); - } - - $this->addAnnotatedClassesToCompile([ - '**\\Controller\\', - '**\\Entity\\', - - // Added explicitly so that we don't rely on the class map being dumped to make it work - 'Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController', - ]); - - if (class_exists(MimeTypes::class)) { - $loader->load('mime_type.xml'); - } - - $container->registerForAutoconfiguration(Command::class) - ->addTag('console.command'); - $container->registerForAutoconfiguration(ResourceCheckerInterface::class) - ->addTag('config_cache.resource_checker'); - $container->registerForAutoconfiguration(EnvVarLoaderInterface::class) - ->addTag('container.env_var_loader'); - $container->registerForAutoconfiguration(EnvVarProcessorInterface::class) - ->addTag('container.env_var_processor'); - $container->registerForAutoconfiguration(ServiceLocator::class) - ->addTag('container.service_locator'); - $container->registerForAutoconfiguration(ServiceSubscriberInterface::class) - ->addTag('container.service_subscriber'); - $container->registerForAutoconfiguration(ArgumentValueResolverInterface::class) - ->addTag('controller.argument_value_resolver'); - $container->registerForAutoconfiguration(AbstractController::class) - ->addTag('controller.service_arguments'); - $container->registerForAutoconfiguration('Symfony\Bundle\FrameworkBundle\Controller\Controller') - ->addTag('controller.service_arguments'); - $container->registerForAutoconfiguration(DataCollectorInterface::class) - ->addTag('data_collector'); - $container->registerForAutoconfiguration(FormTypeInterface::class) - ->addTag('form.type'); - $container->registerForAutoconfiguration(FormTypeGuesserInterface::class) - ->addTag('form.type_guesser'); - $container->registerForAutoconfiguration(FormTypeExtensionInterface::class) - ->addTag('form.type_extension'); - $container->registerForAutoconfiguration(CacheClearerInterface::class) - ->addTag('kernel.cache_clearer'); - $container->registerForAutoconfiguration(CacheWarmerInterface::class) - ->addTag('kernel.cache_warmer'); - $container->registerForAutoconfiguration(EventSubscriberInterface::class) - ->addTag('kernel.event_subscriber'); - $container->registerForAutoconfiguration(LocaleAwareInterface::class) - ->addTag('kernel.locale_aware'); - $container->registerForAutoconfiguration(ResetInterface::class) - ->addTag('kernel.reset', ['method' => 'reset']); - - if (!interface_exists(MarshallerInterface::class)) { - $container->registerForAutoconfiguration(ResettableInterface::class) - ->addTag('kernel.reset', ['method' => 'reset']); - } - - $container->registerForAutoconfiguration(PropertyListExtractorInterface::class) - ->addTag('property_info.list_extractor'); - $container->registerForAutoconfiguration(PropertyTypeExtractorInterface::class) - ->addTag('property_info.type_extractor'); - $container->registerForAutoconfiguration(PropertyDescriptionExtractorInterface::class) - ->addTag('property_info.description_extractor'); - $container->registerForAutoconfiguration(PropertyAccessExtractorInterface::class) - ->addTag('property_info.access_extractor'); - $container->registerForAutoconfiguration(PropertyInitializableExtractorInterface::class) - ->addTag('property_info.initializable_extractor'); - $container->registerForAutoconfiguration(EncoderInterface::class) - ->addTag('serializer.encoder'); - $container->registerForAutoconfiguration(DecoderInterface::class) - ->addTag('serializer.encoder'); - $container->registerForAutoconfiguration(NormalizerInterface::class) - ->addTag('serializer.normalizer'); - $container->registerForAutoconfiguration(DenormalizerInterface::class) - ->addTag('serializer.normalizer'); - $container->registerForAutoconfiguration(ConstraintValidatorInterface::class) - ->addTag('validator.constraint_validator'); - $container->registerForAutoconfiguration(ObjectInitializerInterface::class) - ->addTag('validator.initializer'); - $container->registerForAutoconfiguration(MessageHandlerInterface::class) - ->addTag('messenger.message_handler'); - $container->registerForAutoconfiguration(TransportFactoryInterface::class) - ->addTag('messenger.transport_factory'); - $container->registerForAutoconfiguration(MimeTypeGuesserInterface::class) - ->addTag('mime.mime_type_guesser'); - $container->registerForAutoconfiguration(LoggerAwareInterface::class) - ->addMethodCall('setLogger', [new Reference('logger')]); - - if (!$container->getParameter('kernel.debug')) { - // remove tagged iterator argument for resource checkers - $container->getDefinition('config_cache_factory')->setArguments([]); - } - - if (!$config['disallow_search_engine_index'] ?? false) { - $container->removeDefinition('disallow_search_engine_index_response_listener'); - } - - $container->registerForAutoconfiguration(RouteLoaderInterface::class) - ->addTag('routing.route_loader'); - } - - /** - * {@inheritdoc} - */ - public function getConfiguration(array $config, ContainerBuilder $container) - { - return new Configuration($container->getParameter('kernel.debug')); - } - - private function registerFormConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - $loader->load('form.xml'); - - if (null === $config['form']['csrf_protection']['enabled']) { - $config['form']['csrf_protection']['enabled'] = $config['csrf_protection']['enabled']; - } - - if ($this->isConfigEnabled($container, $config['form']['csrf_protection'])) { - $loader->load('form_csrf.xml'); - - $container->setParameter('form.type_extension.csrf.enabled', true); - $container->setParameter('form.type_extension.csrf.field_name', $config['form']['csrf_protection']['field_name']); - } else { - $container->setParameter('form.type_extension.csrf.enabled', false); - } - - if (!class_exists(Translator::class)) { - $container->removeDefinition('form.type_extension.upload.validator'); - } - if (!method_exists(CachingFactoryDecorator::class, 'reset')) { - $container->getDefinition('form.choice_list_factory.cached') - ->clearTag('kernel.reset') - ; - } - } - - private function registerEsiConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - if (!$this->isConfigEnabled($container, $config)) { - $container->removeDefinition('fragment.renderer.esi'); - - return; - } - - $loader->load('esi.xml'); - } - - private function registerSsiConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - if (!$this->isConfigEnabled($container, $config)) { - $container->removeDefinition('fragment.renderer.ssi'); - - return; - } - - $loader->load('ssi.xml'); - } - - private function registerFragmentsConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - if (!$this->isConfigEnabled($container, $config)) { - $container->removeDefinition('fragment.renderer.hinclude'); - - return; - } - - $container->setParameter('fragment.renderer.hinclude.global_template', $config['hinclude_default_template']); - - $loader->load('fragment_listener.xml'); - $container->setParameter('fragment.path', $config['path']); - } - - private function registerProfilerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - if (!$this->isConfigEnabled($container, $config)) { - // this is needed for the WebProfiler to work even if the profiler is disabled - $container->setParameter('data_collector.templates', []); - - return; - } - - $loader->load('profiling.xml'); - $loader->load('collectors.xml'); - $loader->load('cache_debug.xml'); - - if ($this->formConfigEnabled) { - $loader->load('form_debug.xml'); - } - - if ($this->validatorConfigEnabled) { - $loader->load('validator_debug.xml'); - } - - if ($this->translationConfigEnabled) { - $loader->load('translation_debug.xml'); - - $container->getDefinition('translator.data_collector')->setDecoratedService('translator'); - } - - if ($this->messengerConfigEnabled) { - $loader->load('messenger_debug.xml'); - } - - if ($this->mailerConfigEnabled) { - $loader->load('mailer_debug.xml'); - } - - if ($this->httpClientConfigEnabled) { - $loader->load('http_client_debug.xml'); - } - - $container->setParameter('profiler_listener.only_exceptions', $config['only_exceptions']); - $container->setParameter('profiler_listener.only_master_requests', $config['only_master_requests']); - - // Choose storage class based on the DSN - list($class) = explode(':', $config['dsn'], 2); - if ('file' !== $class) { - throw new \LogicException(sprintf('Driver "%s" is not supported for the profiler.', $class)); - } - - $container->setParameter('profiler.storage.dsn', $config['dsn']); - - $container->getDefinition('profiler') - ->addArgument($config['collect']) - ->addTag('kernel.reset', ['method' => 'reset']); - } - - private function registerWorkflowConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - if (!$config['enabled']) { - $container->removeDefinition('console.command.workflow_dump'); - - return; - } - - if (!class_exists(Workflow\Workflow::class)) { - throw new LogicException('Workflow support cannot be enabled as the Workflow component is not installed. Try running "composer require symfony/workflow".'); - } - - $loader->load('workflow.xml'); - - $registryDefinition = $container->getDefinition('workflow.registry'); - - foreach ($config['workflows'] as $name => $workflow) { - $type = $workflow['type']; - $workflowId = sprintf('%s.%s', $type, $name); - - // Process Metadata (workflow + places (transition is done in the "create transition" block)) - $metadataStoreDefinition = new Definition(Workflow\Metadata\InMemoryMetadataStore::class, [[], [], null]); - if ($workflow['metadata']) { - $metadataStoreDefinition->replaceArgument(0, $workflow['metadata']); - } - $placesMetadata = []; - foreach ($workflow['places'] as $place) { - if ($place['metadata']) { - $placesMetadata[$place['name']] = $place['metadata']; - } - } - if ($placesMetadata) { - $metadataStoreDefinition->replaceArgument(1, $placesMetadata); - } - - // Create transitions - $transitions = []; - $guardsConfiguration = []; - $transitionsMetadataDefinition = new Definition(\SplObjectStorage::class); - // Global transition counter per workflow - $transitionCounter = 0; - foreach ($workflow['transitions'] as $transition) { - if ('workflow' === $type) { - $transitionDefinition = new Definition(Workflow\Transition::class, [$transition['name'], $transition['from'], $transition['to']]); - $transitionDefinition->setPublic(false); - $transitionId = sprintf('%s.transition.%s', $workflowId, $transitionCounter++); - $container->setDefinition($transitionId, $transitionDefinition); - $transitions[] = new Reference($transitionId); - if (isset($transition['guard'])) { - $configuration = new Definition(Workflow\EventListener\GuardExpression::class); - $configuration->addArgument(new Reference($transitionId)); - $configuration->addArgument($transition['guard']); - $configuration->setPublic(false); - $eventName = sprintf('workflow.%s.guard.%s', $name, $transition['name']); - $guardsConfiguration[$eventName][] = $configuration; - } - if ($transition['metadata']) { - $transitionsMetadataDefinition->addMethodCall('attach', [ - new Reference($transitionId), - $transition['metadata'], - ]); - } - } elseif ('state_machine' === $type) { - foreach ($transition['from'] as $from) { - foreach ($transition['to'] as $to) { - $transitionDefinition = new Definition(Workflow\Transition::class, [$transition['name'], $from, $to]); - $transitionDefinition->setPublic(false); - $transitionId = sprintf('%s.transition.%s', $workflowId, $transitionCounter++); - $container->setDefinition($transitionId, $transitionDefinition); - $transitions[] = new Reference($transitionId); - if (isset($transition['guard'])) { - $configuration = new Definition(Workflow\EventListener\GuardExpression::class); - $configuration->addArgument(new Reference($transitionId)); - $configuration->addArgument($transition['guard']); - $configuration->setPublic(false); - $eventName = sprintf('workflow.%s.guard.%s', $name, $transition['name']); - $guardsConfiguration[$eventName][] = $configuration; - } - if ($transition['metadata']) { - $transitionsMetadataDefinition->addMethodCall('attach', [ - new Reference($transitionId), - $transition['metadata'], - ]); - } - } - } - } - } - $metadataStoreDefinition->replaceArgument(2, $transitionsMetadataDefinition); - - // Create places - $places = array_column($workflow['places'], 'name'); - $initialMarking = $workflow['initial_marking'] ?? []; - - // Create a Definition - $definitionDefinition = new Definition(Workflow\Definition::class); - $definitionDefinition->setPublic(false); - $definitionDefinition->addArgument($places); - $definitionDefinition->addArgument($transitions); - $definitionDefinition->addArgument($initialMarking); - $definitionDefinition->addArgument($metadataStoreDefinition); - $definitionDefinition->addTag('workflow.definition', [ - 'name' => $name, - 'type' => $type, - ]); - - // Create MarkingStore - if (isset($workflow['marking_store']['type'])) { - $markingStoreDefinition = new ChildDefinition('workflow.marking_store.method'); - $markingStoreDefinition->setArguments([ - 'state_machine' === $type, //single state - $workflow['marking_store']['property'], - ]); - } elseif (isset($workflow['marking_store']['service'])) { - $markingStoreDefinition = new Reference($workflow['marking_store']['service']); - } - - // Create Workflow - $workflowDefinition = new ChildDefinition(sprintf('%s.abstract', $type)); - $workflowDefinition->replaceArgument(0, new Reference(sprintf('%s.definition', $workflowId))); - if (isset($markingStoreDefinition)) { - $workflowDefinition->replaceArgument(1, $markingStoreDefinition); - } - $workflowDefinition->replaceArgument(3, $name); - - // Store to container - $container->setDefinition($workflowId, $workflowDefinition); - $container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition); - $container->registerAliasForArgument($workflowId, WorkflowInterface::class, $name.'.'.$type); - - // Validate Workflow - if ('state_machine' === $workflow['type']) { - $validator = new Workflow\Validator\StateMachineValidator(); - } else { - $validator = new Workflow\Validator\WorkflowValidator(); - } - - $trs = array_map(function (Reference $ref) use ($container): Workflow\Transition { - return $container->get((string) $ref); - }, $transitions); - $realDefinition = new Workflow\Definition($places, $trs, $initialMarking); - $validator->validate($realDefinition, $name); - - // Add workflow to Registry - if ($workflow['supports']) { - foreach ($workflow['supports'] as $supportedClassName) { - $strategyDefinition = new Definition(Workflow\SupportStrategy\InstanceOfSupportStrategy::class, [$supportedClassName]); - $strategyDefinition->setPublic(false); - $registryDefinition->addMethodCall('addWorkflow', [new Reference($workflowId), $strategyDefinition]); - } - } elseif (isset($workflow['support_strategy'])) { - $registryDefinition->addMethodCall('addWorkflow', [new Reference($workflowId), new Reference($workflow['support_strategy'])]); - } - - // Enable the AuditTrail - if ($workflow['audit_trail']['enabled']) { - $listener = new Definition(Workflow\EventListener\AuditTrailListener::class); - $listener->setPrivate(true); - $listener->addTag('monolog.logger', ['channel' => 'workflow']); - $listener->addTag('kernel.event_listener', ['event' => sprintf('workflow.%s.leave', $name), 'method' => 'onLeave']); - $listener->addTag('kernel.event_listener', ['event' => sprintf('workflow.%s.transition', $name), 'method' => 'onTransition']); - $listener->addTag('kernel.event_listener', ['event' => sprintf('workflow.%s.enter', $name), 'method' => 'onEnter']); - $listener->addArgument(new Reference('logger')); - $container->setDefinition(sprintf('%s.listener.audit_trail', $workflowId), $listener); - } - - // Add Guard Listener - if ($guardsConfiguration) { - if (!class_exists(ExpressionLanguage::class)) { - throw new LogicException('Cannot guard workflows as the ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".'); - } - - if (!class_exists(Security::class)) { - throw new LogicException('Cannot guard workflows as the Security component is not installed. Try running "composer require symfony/security-core".'); - } - - $guard = new Definition(Workflow\EventListener\GuardListener::class); - $guard->setPrivate(true); - - $guard->setArguments([ - $guardsConfiguration, - new Reference('workflow.security.expression_language'), - new Reference('security.token_storage'), - new Reference('security.authorization_checker'), - new Reference('security.authentication.trust_resolver'), - new Reference('security.role_hierarchy'), - new Reference('validator', ContainerInterface::NULL_ON_INVALID_REFERENCE), - ]); - foreach ($guardsConfiguration as $eventName => $config) { - $guard->addTag('kernel.event_listener', ['event' => $eventName, 'method' => 'onTransition']); - } - - $container->setDefinition(sprintf('%s.listener.guard', $workflowId), $guard); - $container->setParameter('workflow.has_guard_listeners', true); - } - } - } - - private function registerDebugConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - $loader->load('debug_prod.xml'); - - if (class_exists(Stopwatch::class)) { - $container->register('debug.stopwatch', Stopwatch::class) - ->addArgument(true) - ->setPrivate(true) - ->addTag('kernel.reset', ['method' => 'reset']); - $container->setAlias(Stopwatch::class, new Alias('debug.stopwatch', false)); - } - - $debug = $container->getParameter('kernel.debug'); - - if ($debug) { - $container->setParameter('debug.container.dump', '%kernel.cache_dir%/%kernel.container_class%.xml'); - } - - if ($debug && class_exists(Stopwatch::class)) { - $loader->load('debug.xml'); - } - - $definition = $container->findDefinition('debug.debug_handlers_listener'); - - if (false === $config['log']) { - $definition->replaceArgument(1, null); - } elseif (true !== $config['log']) { - $definition->replaceArgument(2, $config['log']); - } - - if (!$config['throw']) { - $container->setParameter('debug.error_handler.throw_at', 0); - } - - if ($debug && class_exists(DebugProcessor::class)) { - $definition = new Definition(DebugProcessor::class); - $definition->setPublic(false); - $definition->addArgument(new Reference('request_stack')); - $container->setDefinition('debug.log_processor', $definition); - } - } - - private function registerRouterConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - if (!$this->isConfigEnabled($container, $config)) { - $container->removeDefinition('console.command.router_debug'); - $container->removeDefinition('console.command.router_match'); - - return; - } - - $loader->load('routing.xml'); - - if ($config['utf8']) { - $container->getDefinition('routing.loader')->replaceArgument(1, ['utf8' => true]); - } - - $container->setParameter('router.resource', $config['resource']); - $router = $container->findDefinition('router.default'); - $argument = $router->getArgument(2); - $argument['strict_requirements'] = $config['strict_requirements']; - if (isset($config['type'])) { - $argument['resource_type'] = $config['type']; - } - $router->replaceArgument(2, $argument); - - $container->setParameter('request_listener.http_port', $config['http_port']); - $container->setParameter('request_listener.https_port', $config['https_port']); - - if ($this->annotationsConfigEnabled) { - $container->register('routing.loader.annotation', AnnotatedRouteControllerLoader::class) - ->setPublic(false) - ->addTag('routing.loader', ['priority' => -10]) - ->addArgument(new Reference('annotation_reader')); - - $container->register('routing.loader.annotation.directory', AnnotationDirectoryLoader::class) - ->setPublic(false) - ->addTag('routing.loader', ['priority' => -10]) - ->setArguments([ - new Reference('file_locator'), - new Reference('routing.loader.annotation'), - ]); - - $container->register('routing.loader.annotation.file', AnnotationFileLoader::class) - ->setPublic(false) - ->addTag('routing.loader', ['priority' => -10]) - ->setArguments([ - new Reference('file_locator'), - new Reference('routing.loader.annotation'), - ]); - } - } - - private function registerSessionConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - $loader->load('session.xml'); - - // session storage - $container->setAlias('session.storage', $config['storage_id'])->setPrivate(true); - $options = ['cache_limiter' => '0']; - foreach (['name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'cookie_samesite', 'use_cookies', 'gc_maxlifetime', 'gc_probability', 'gc_divisor', 'sid_length', 'sid_bits_per_character'] as $key) { - if (isset($config[$key])) { - $options[$key] = $config[$key]; - } - } - - if ('auto' === ($options['cookie_secure'] ?? null)) { - $locator = $container->getDefinition('session_listener')->getArgument(0); - $locator->setValues($locator->getValues() + [ - 'session_storage' => new Reference('session.storage', ContainerInterface::IGNORE_ON_INVALID_REFERENCE), - 'request_stack' => new Reference('request_stack'), - ]); - } - - $container->setParameter('session.storage.options', $options); - - // session handler (the internal callback registered with PHP session management) - if (null === $config['handler_id']) { - // Set the handler class to be null - $container->getDefinition('session.storage.native')->replaceArgument(1, null); - $container->getDefinition('session.storage.php_bridge')->replaceArgument(0, null); - } else { - $container->resolveEnvPlaceholders($config['handler_id'], null, $usedEnvs); - - if ($usedEnvs || preg_match('#^[a-z]++://#', $config['handler_id'])) { - $id = '.cache_connection.'.ContainerBuilder::hash($config['handler_id']); - - $container->getDefinition('session.abstract_handler') - ->replaceArgument(0, $container->hasDefinition($id) ? new Reference($id) : $config['handler_id']); - - $container->setAlias('session.handler', 'session.abstract_handler')->setPrivate(true); - } else { - $container->setAlias('session.handler', $config['handler_id'])->setPrivate(true); - } - } - - $container->setParameter('session.save_path', $config['save_path']); - - $container->setParameter('session.metadata.update_threshold', $config['metadata_update_threshold']); - } - - private function registerRequestConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - if ($config['formats']) { - $loader->load('request.xml'); - - $listener = $container->getDefinition('request.add_request_formats_listener'); - $listener->replaceArgument(0, $config['formats']); - } - } - - private function registerAssetsConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - $loader->load('assets.xml'); - - if ($config['version_strategy']) { - $defaultVersion = new Reference($config['version_strategy']); - } else { - $defaultVersion = $this->createVersion($container, $config['version'], $config['version_format'], $config['json_manifest_path'], '_default'); - } - - $defaultPackage = $this->createPackageDefinition($config['base_path'], $config['base_urls'], $defaultVersion); - $container->setDefinition('assets._default_package', $defaultPackage); - - $namedPackages = []; - foreach ($config['packages'] as $name => $package) { - if (null !== $package['version_strategy']) { - $version = new Reference($package['version_strategy']); - } elseif (!\array_key_exists('version', $package) && null === $package['json_manifest_path']) { - // if neither version nor json_manifest_path are specified, use the default - $version = $defaultVersion; - } else { - // let format fallback to main version_format - $format = $package['version_format'] ?: $config['version_format']; - $version = isset($package['version']) ? $package['version'] : null; - $version = $this->createVersion($container, $version, $format, $package['json_manifest_path'], $name); - } - - $container->setDefinition('assets._package_'.$name, $this->createPackageDefinition($package['base_path'], $package['base_urls'], $version)); - $container->registerAliasForArgument('assets._package_'.$name, PackageInterface::class, $name.'.package'); - $namedPackages[$name] = new Reference('assets._package_'.$name); - } - - $container->getDefinition('assets.packages') - ->replaceArgument(0, new Reference('assets._default_package')) - ->replaceArgument(1, $namedPackages) - ; - } - - /** - * Returns a definition for an asset package. - */ - private function createPackageDefinition(?string $basePath, array $baseUrls, Reference $version): Definition - { - if ($basePath && $baseUrls) { - throw new \LogicException('An asset package cannot have base URLs and base paths.'); - } - - $package = new ChildDefinition($baseUrls ? 'assets.url_package' : 'assets.path_package'); - $package - ->setPublic(false) - ->replaceArgument(0, $baseUrls ?: $basePath) - ->replaceArgument(1, $version) - ; - - return $package; - } - - private function createVersion(ContainerBuilder $container, ?string $version, ?string $format, ?string $jsonManifestPath, string $name): Reference - { - // Configuration prevents $version and $jsonManifestPath from being set - if (null !== $version) { - $def = new ChildDefinition('assets.static_version_strategy'); - $def - ->replaceArgument(0, $version) - ->replaceArgument(1, $format) - ; - $container->setDefinition('assets._version_'.$name, $def); - - return new Reference('assets._version_'.$name); - } - - if (null !== $jsonManifestPath) { - $def = new ChildDefinition('assets.json_manifest_version_strategy'); - $def->replaceArgument(0, $jsonManifestPath); - $container->setDefinition('assets._version_'.$name, $def); - - return new Reference('assets._version_'.$name); - } - - return new Reference('assets.empty_version_strategy'); - } - - private function registerTranslatorConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader, string $defaultLocale) - { - if (!$this->isConfigEnabled($container, $config)) { - $container->removeDefinition('console.command.translation_debug'); - $container->removeDefinition('console.command.translation_update'); - - return; - } - - $loader->load('translation.xml'); - - // Use the "real" translator instead of the identity default - $container->setAlias('translator', 'translator.default')->setPublic(true); - $container->setAlias('translator.formatter', new Alias($config['formatter'], false)); - $translator = $container->findDefinition('translator.default'); - $translator->addMethodCall('setFallbackLocales', [$config['fallbacks'] ?: [$defaultLocale]]); - - $defaultOptions = $translator->getArgument(4); - $defaultOptions['cache_dir'] = $config['cache_dir']; - $translator->setArgument(4, $defaultOptions); - - $container->setParameter('translator.logging', $config['logging']); - $container->setParameter('translator.default_path', $config['default_path']); - - // Discover translation directories - $dirs = []; - $transPaths = []; - $nonExistingDirs = []; - if (class_exists('Symfony\Component\Validator\Validation')) { - $r = new \ReflectionClass('Symfony\Component\Validator\Validation'); - - $dirs[] = $transPaths[] = \dirname($r->getFileName()).'/Resources/translations'; - } - if (class_exists('Symfony\Component\Form\Form')) { - $r = new \ReflectionClass('Symfony\Component\Form\Form'); - - $dirs[] = $transPaths[] = \dirname($r->getFileName()).'/Resources/translations'; - } - if (class_exists('Symfony\Component\Security\Core\Exception\AuthenticationException')) { - $r = new \ReflectionClass('Symfony\Component\Security\Core\Exception\AuthenticationException'); - - $dirs[] = $transPaths[] = \dirname($r->getFileName(), 2).'/Resources/translations'; - } - $defaultDir = $container->getParameterBag()->resolveValue($config['default_path']); - foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) { - if ($container->fileExists($dir = $bundle['path'].'/Resources/translations') || $container->fileExists($dir = $bundle['path'].'/translations')) { - $dirs[] = $dir; - } else { - $nonExistingDirs[] = $dir; - } - } - - foreach ($config['paths'] as $dir) { - if ($container->fileExists($dir)) { - $dirs[] = $transPaths[] = $dir; - } else { - throw new \UnexpectedValueException(sprintf('%s defined in translator.paths does not exist or is not a directory', $dir)); - } - } - - if ($container->hasDefinition('console.command.translation_debug')) { - $container->getDefinition('console.command.translation_debug')->replaceArgument(5, $transPaths); - } - - if ($container->hasDefinition('console.command.translation_update')) { - $container->getDefinition('console.command.translation_update')->replaceArgument(6, $transPaths); - } - - if ($container->fileExists($defaultDir)) { - $dirs[] = $defaultDir; - } else { - $nonExistingDirs[] = $defaultDir; - } - - // Register translation resources - if ($dirs) { - $files = []; - $finder = Finder::create() - ->followLinks() - ->files() - ->filter(function (\SplFileInfo $file) { - return 2 <= substr_count($file->getBasename(), '.') && preg_match('/\.\w+$/', $file->getBasename()); - }) - ->in($dirs) - ->sortByName() - ; - - foreach ($finder as $file) { - $fileNameParts = explode('.', basename($file)); - $locale = $fileNameParts[\count($fileNameParts) - 2]; - if (!isset($files[$locale])) { - $files[$locale] = []; - } - - $files[$locale][] = (string) $file; - } - - $projectDir = $container->getParameter('kernel.project_dir'); - - $options = array_merge( - $translator->getArgument(4), - [ - 'resource_files' => $files, - 'scanned_directories' => $scannedDirectories = array_merge($dirs, $nonExistingDirs), - 'cache_vary' => [ - 'scanned_directories' => array_map(static function (string $dir) use ($projectDir): string { - return 0 === strpos($dir, $projectDir.'/') ? substr($dir, 1 + \strlen($projectDir)) : $dir; - }, $scannedDirectories), - ], - ] - ); - - $translator->replaceArgument(4, $options); - } - } - - private function registerValidationConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader, bool $propertyInfoEnabled) - { - if (!$this->validatorConfigEnabled = $this->isConfigEnabled($container, $config)) { - return; - } - - if (!class_exists('Symfony\Component\Validator\Validation')) { - throw new LogicException('Validation support cannot be enabled as the Validator component is not installed. Try running "composer require symfony/validator".'); - } - - if (!isset($config['email_validation_mode'])) { - $config['email_validation_mode'] = 'loose'; - } - - $loader->load('validator.xml'); - - $validatorBuilder = $container->getDefinition('validator.builder'); - - $container->setParameter('validator.translation_domain', $config['translation_domain']); - - $files = ['xml' => [], 'yml' => []]; - $this->registerValidatorMapping($container, $config, $files); - - if (!empty($files['xml'])) { - $validatorBuilder->addMethodCall('addXmlMappings', [$files['xml']]); - } - - if (!empty($files['yml'])) { - $validatorBuilder->addMethodCall('addYamlMappings', [$files['yml']]); - } - - $definition = $container->findDefinition('validator.email'); - $definition->replaceArgument(0, $config['email_validation_mode']); - - if (\array_key_exists('enable_annotations', $config) && $config['enable_annotations']) { - if (!$this->annotationsConfigEnabled) { - throw new \LogicException('"enable_annotations" on the validator cannot be set as Annotations support is disabled.'); - } - - $validatorBuilder->addMethodCall('enableAnnotationMapping', [new Reference('annotation_reader')]); - } - - if (\array_key_exists('static_method', $config) && $config['static_method']) { - foreach ($config['static_method'] as $methodName) { - $validatorBuilder->addMethodCall('addMethodMapping', [$methodName]); - } - } - - if (!$container->getParameter('kernel.debug')) { - $validatorBuilder->addMethodCall('setMappingCache', [new Reference('validator.mapping.cache.adapter')]); - } - - $container->setParameter('validator.auto_mapping', $config['auto_mapping']); - if (!$propertyInfoEnabled || !class_exists(PropertyInfoLoader::class)) { - $container->removeDefinition('validator.property_info_loader'); - } - - $container - ->getDefinition('validator.not_compromised_password') - ->setArgument(2, $config['not_compromised_password']['enabled']) - ->setArgument(3, $config['not_compromised_password']['endpoint']) - ; - } - - private function registerValidatorMapping(ContainerBuilder $container, array $config, array &$files) - { - $fileRecorder = function ($extension, $path) use (&$files) { - $files['yaml' === $extension ? 'yml' : $extension][] = $path; - }; - - if (interface_exists('Symfony\Component\Form\FormInterface')) { - $reflClass = new \ReflectionClass('Symfony\Component\Form\FormInterface'); - $fileRecorder('xml', \dirname($reflClass->getFileName()).'/Resources/config/validation.xml'); - } - - foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { - $configDir = is_dir($bundle['path'].'/Resources/config') ? $bundle['path'].'/Resources/config' : $bundle['path'].'/config'; - - if ( - $container->fileExists($file = $configDir.'/validation.yaml', false) || - $container->fileExists($file = $configDir.'/validation.yml', false) - ) { - $fileRecorder('yml', $file); - } - - if ($container->fileExists($file = $configDir.'/validation.xml', false)) { - $fileRecorder('xml', $file); - } - - if ($container->fileExists($dir = $configDir.'/validation', '/^$/')) { - $this->registerMappingFilesFromDir($dir, $fileRecorder); - } - } - - $projectDir = $container->getParameter('kernel.project_dir'); - if ($container->fileExists($dir = $projectDir.'/config/validator', '/^$/')) { - $this->registerMappingFilesFromDir($dir, $fileRecorder); - } - - $this->registerMappingFilesFromConfig($container, $config, $fileRecorder); - } - - private function registerMappingFilesFromDir(string $dir, callable $fileRecorder) - { - foreach (Finder::create()->followLinks()->files()->in($dir)->name('/\.(xml|ya?ml)$/')->sortByName() as $file) { - $fileRecorder($file->getExtension(), $file->getRealPath()); - } - } - - private function registerMappingFilesFromConfig(ContainerBuilder $container, array $config, callable $fileRecorder) - { - foreach ($config['mapping']['paths'] as $path) { - if (is_dir($path)) { - $this->registerMappingFilesFromDir($path, $fileRecorder); - $container->addResource(new DirectoryResource($path, '/^$/')); - } elseif ($container->fileExists($path, false)) { - if (!preg_match('/\.(xml|ya?ml)$/', $path, $matches)) { - throw new \RuntimeException(sprintf('Unsupported mapping type in "%s", supported types are XML & Yaml.', $path)); - } - $fileRecorder($matches[1], $path); - } else { - throw new \RuntimeException(sprintf('Could not open file or directory "%s".', $path)); - } - } - } - - private function registerAnnotationsConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader) - { - if (!$this->annotationsConfigEnabled) { - return; - } - - if (!class_exists('Doctrine\Common\Annotations\Annotation')) { - throw new LogicException('Annotations cannot be enabled as the Doctrine Annotation library is not installed.'); - } - - $loader->load('annotations.xml'); - - if (!method_exists(AnnotationRegistry::class, 'registerUniqueLoader')) { - $container->getDefinition('annotations.dummy_registry') - ->setMethodCalls([['registerLoader', ['class_exists']]]); - } - - if ('none' !== $config['cache']) { - if (!class_exists('Doctrine\Common\Cache\CacheProvider')) { - throw new LogicException('Annotations cannot be enabled as the Doctrine Cache library is not installed.'); - } - - $cacheService = $config['cache']; - - if ('php_array' === $config['cache']) { - $cacheService = 'annotations.cache'; - - // Enable warmer only if PHP array is used for cache - $definition = $container->findDefinition('annotations.cache_warmer'); - $definition->addTag('kernel.cache_warmer'); - } elseif ('file' === $config['cache']) { - $cacheDir = $container->getParameterBag()->resolveValue($config['file_cache_dir']); - - if (!is_dir($cacheDir) && false === @mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) { - throw new \RuntimeException(sprintf('Could not create cache directory "%s".', $cacheDir)); - } - - $container - ->getDefinition('annotations.filesystem_cache') - ->replaceArgument(0, $cacheDir) - ; - - $cacheService = 'annotations.filesystem_cache'; - } - - $container - ->getDefinition('annotations.cached_reader') - ->replaceArgument(2, $config['debug']) - // temporary property to lazy-reference the cache provider without using it until AddAnnotationsCachedReaderPass runs - ->setProperty('cacheProviderBackup', new ServiceClosureArgument(new Reference($cacheService))) - ->addTag('annotations.cached_reader') - ; - - $container->setAlias('annotation_reader', 'annotations.cached_reader')->setPrivate(true); - $container->setAlias(Reader::class, new Alias('annotations.cached_reader', false)); - } else { - $container->removeDefinition('annotations.cached_reader'); - } - } - - private function registerPropertyAccessConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccessor')) { - return; - } - - $loader->load('property_access.xml'); - - $container - ->getDefinition('property_accessor') - ->replaceArgument(0, $config['magic_call']) - ->replaceArgument(1, $config['throw_exception_on_invalid_index']) - ->replaceArgument(3, $config['throw_exception_on_invalid_property_path']) - ; - } - - private function registerSecretsConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - if (!$this->isConfigEnabled($container, $config)) { - $container->removeDefinition('console.command.secrets_set'); - $container->removeDefinition('console.command.secrets_list'); - $container->removeDefinition('console.command.secrets_remove'); - $container->removeDefinition('console.command.secrets_generate_key'); - $container->removeDefinition('console.command.secrets_decrypt_to_local'); - $container->removeDefinition('console.command.secrets_encrypt_from_local'); - - return; - } - - $loader->load('secrets.xml'); - - $container->getDefinition('secrets.vault')->replaceArgument(0, $config['vault_directory']); - - if ($config['local_dotenv_file']) { - $container->getDefinition('secrets.local_vault')->replaceArgument(0, $config['local_dotenv_file']); - } else { - $container->removeDefinition('secrets.local_vault'); - } - - if ($config['decryption_env_var']) { - if (!preg_match('/^(?:\w*+:)*+\w++$/', $config['decryption_env_var'])) { - throw new InvalidArgumentException(sprintf('Invalid value "%s" set as "decryption_env_var": only "word" characters are allowed.', $config['decryption_env_var'])); - } - - $container->getDefinition('secrets.vault')->replaceArgument(1, "%env({$config['decryption_env_var']})%"); - } else { - $container->getDefinition('secrets.vault')->replaceArgument(1, null); - } - } - - private function registerSecurityCsrfConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - if (!$this->isConfigEnabled($container, $config)) { - return; - } - - if (!class_exists('Symfony\Component\Security\Csrf\CsrfToken')) { - throw new LogicException('CSRF support cannot be enabled as the Security CSRF component is not installed. Try running "composer require symfony/security-csrf".'); - } - - if (!$this->sessionConfigEnabled) { - throw new \LogicException('CSRF protection needs sessions to be enabled.'); - } - - // Enable services for CSRF protection (even without forms) - $loader->load('security_csrf.xml'); - - if (!class_exists(CsrfExtension::class)) { - $container->removeDefinition('twig.extension.security_csrf'); - } - } - - private function registerSerializerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - $loader->load('serializer.xml'); - - $chainLoader = $container->getDefinition('serializer.mapping.chain_loader'); - - if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccessor')) { - $container->removeAlias('serializer.property_accessor'); - $container->removeDefinition('serializer.normalizer.object'); - } - - if (!class_exists(Yaml::class)) { - $container->removeDefinition('serializer.encoder.yaml'); - } - - $serializerLoaders = []; - if (isset($config['enable_annotations']) && $config['enable_annotations']) { - if (!$this->annotationsConfigEnabled) { - throw new \LogicException('"enable_annotations" on the serializer cannot be set as Annotations support is disabled.'); - } - - $annotationLoader = new Definition( - 'Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader', - [new Reference('annotation_reader')] - ); - $annotationLoader->setPublic(false); - - $serializerLoaders[] = $annotationLoader; - } - - $fileRecorder = function ($extension, $path) use (&$serializerLoaders) { - $definition = new Definition(\in_array($extension, ['yaml', 'yml']) ? 'Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader' : 'Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', [$path]); - $definition->setPublic(false); - $serializerLoaders[] = $definition; - }; - - foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { - $configDir = is_dir($bundle['path'].'/Resources/config') ? $bundle['path'].'/Resources/config' : $bundle['path'].'/config'; - - if ($container->fileExists($file = $configDir.'/serialization.xml', false)) { - $fileRecorder('xml', $file); - } - - if ( - $container->fileExists($file = $configDir.'/serialization.yaml', false) || - $container->fileExists($file = $configDir.'/serialization.yml', false) - ) { - $fileRecorder('yml', $file); - } - - if ($container->fileExists($dir = $configDir.'/serialization', '/^$/')) { - $this->registerMappingFilesFromDir($dir, $fileRecorder); - } - } - - $projectDir = $container->getParameter('kernel.project_dir'); - if ($container->fileExists($dir = $projectDir.'/config/serializer', '/^$/')) { - $this->registerMappingFilesFromDir($dir, $fileRecorder); - } - - $this->registerMappingFilesFromConfig($container, $config, $fileRecorder); - - $chainLoader->replaceArgument(0, $serializerLoaders); - $container->getDefinition('serializer.mapping.cache_warmer')->replaceArgument(0, $serializerLoaders); - - if ($container->getParameter('kernel.debug')) { - $container->removeDefinition('serializer.mapping.cache_class_metadata_factory'); - } - - if (isset($config['name_converter']) && $config['name_converter']) { - $container->getDefinition('serializer.name_converter.metadata_aware')->setArgument(1, new Reference($config['name_converter'])); - } - - if (isset($config['circular_reference_handler']) && $config['circular_reference_handler']) { - $arguments = $container->getDefinition('serializer.normalizer.object')->getArguments(); - $context = ($arguments[6] ?? []) + ['circular_reference_handler' => new Reference($config['circular_reference_handler'])]; - $container->getDefinition('serializer.normalizer.object')->setArgument(5, null); - $container->getDefinition('serializer.normalizer.object')->setArgument(6, $context); - } - - if ($config['max_depth_handler'] ?? false) { - $defaultContext = $container->getDefinition('serializer.normalizer.object')->getArgument(6); - $defaultContext += ['max_depth_handler' => new Reference($config['max_depth_handler'])]; - $container->getDefinition('serializer.normalizer.object')->replaceArgument(6, $defaultContext); - } - } - - private function registerPropertyInfoConfiguration(ContainerBuilder $container, XmlFileLoader $loader) - { - if (!interface_exists(PropertyInfoExtractorInterface::class)) { - throw new LogicException('PropertyInfo support cannot be enabled as the PropertyInfo component is not installed. Try running "composer require symfony/property-info".'); - } - - $loader->load('property_info.xml'); - - if (interface_exists('phpDocumentor\Reflection\DocBlockFactoryInterface')) { - $definition = $container->register('property_info.php_doc_extractor', 'Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor'); - $definition->setPrivate(true); - $definition->addTag('property_info.description_extractor', ['priority' => -1000]); - $definition->addTag('property_info.type_extractor', ['priority' => -1001]); - } - - if ($container->getParameter('kernel.debug')) { - $container->removeDefinition('property_info.cache'); - } - } - - private function registerLockConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - $loader->load('lock.xml'); - - foreach ($config['resources'] as $resourceName => $resourceStores) { - if (0 === \count($resourceStores)) { - continue; - } - - // Generate stores - $storeDefinitions = []; - foreach ($resourceStores as $storeDsn) { - $storeDsn = $container->resolveEnvPlaceholders($storeDsn, null, $usedEnvs); - $storeDefinition = new Definition(interface_exists(StoreInterface::class) ? StoreInterface::class : PersistingStoreInterface::class); - $storeDefinition->setFactory([StoreFactory::class, 'createStore']); - $storeDefinition->setArguments([$storeDsn]); - - $container->setDefinition($storeDefinitionId = '.lock.'.$resourceName.'.store.'.$container->hash($storeDsn), $storeDefinition); - - $storeDefinition = new Reference($storeDefinitionId); - - $storeDefinitions[] = $storeDefinition; - } - - // Wrap array of stores with CombinedStore - if (\count($storeDefinitions) > 1) { - $combinedDefinition = new ChildDefinition('lock.store.combined.abstract'); - $combinedDefinition->replaceArgument(0, $storeDefinitions); - $container->setDefinition('lock.'.$resourceName.'.store', $combinedDefinition); - } else { - $container->setAlias('lock.'.$resourceName.'.store', new Alias((string) $storeDefinitions[0], false)); - } - - // Generate factories for each resource - $factoryDefinition = new ChildDefinition('lock.factory.abstract'); - $factoryDefinition->replaceArgument(0, new Reference('lock.'.$resourceName.'.store')); - $container->setDefinition('lock.'.$resourceName.'.factory', $factoryDefinition); - - // Generate services for lock instances - $lockDefinition = new Definition(Lock::class); - $lockDefinition->setPublic(false); - $lockDefinition->setFactory([new Reference('lock.'.$resourceName.'.factory'), 'createLock']); - $lockDefinition->setArguments([$resourceName]); - $container->setDefinition('lock.'.$resourceName, $lockDefinition); - - // provide alias for default resource - if ('default' === $resourceName) { - $container->setAlias('lock.store', new Alias('lock.'.$resourceName.'.store', false)); - $container->setAlias('lock.factory', new Alias('lock.'.$resourceName.'.factory', false)); - $container->setAlias('lock', new Alias('lock.'.$resourceName, false)); - $container->setAlias(PersistingStoreInterface::class, new Alias('lock.store', false)); - $container->setAlias(LockFactory::class, new Alias('lock.factory', false)); - $container->setAlias(LockInterface::class, new Alias('lock', false)); - } else { - $container->registerAliasForArgument('lock.'.$resourceName.'.store', PersistingStoreInterface::class, $resourceName.'.lock.store'); - $container->registerAliasForArgument('lock.'.$resourceName.'.factory', LockFactory::class, $resourceName.'.lock.factory'); - $container->registerAliasForArgument('lock.'.$resourceName, LockInterface::class, $resourceName.'.lock'); - } - } - } - - private function registerMessengerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader, array $validationConfig) - { - if (!interface_exists(MessageBusInterface::class)) { - throw new LogicException('Messenger support cannot be enabled as the Messenger component is not installed. Try running "composer require symfony/messenger".'); - } - - $loader->load('messenger.xml'); - - if (null === $config['default_bus'] && 1 === \count($config['buses'])) { - $config['default_bus'] = key($config['buses']); - } - - $defaultMiddleware = [ - 'before' => [ - ['id' => 'add_bus_name_stamp_middleware'], - ['id' => 'reject_redelivered_message_middleware'], - ['id' => 'dispatch_after_current_bus'], - ['id' => 'failed_message_processing_middleware'], - ], - 'after' => [ - ['id' => 'send_message'], - ['id' => 'handle_message'], - ], - ]; - foreach ($config['buses'] as $busId => $bus) { - $middleware = $bus['middleware']; - - if ($bus['default_middleware']) { - if ('allow_no_handlers' === $bus['default_middleware']) { - $defaultMiddleware['after'][1]['arguments'] = [true]; - } else { - unset($defaultMiddleware['after'][1]['arguments']); - } - - // argument to add_bus_name_stamp_middleware - $defaultMiddleware['before'][0]['arguments'] = [$busId]; - - $middleware = array_merge($defaultMiddleware['before'], $middleware, $defaultMiddleware['after']); - } - - foreach ($middleware as $middlewareItem) { - if (!$validationConfig['enabled'] && \in_array($middlewareItem['id'], ['validation', 'messenger.middleware.validation'], true)) { - throw new LogicException('The Validation middleware is only available when the Validator component is installed and enabled. Try running "composer require symfony/validator".'); - } - } - - if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class)) { - array_unshift($middleware, ['id' => 'traceable', 'arguments' => [$busId]]); - } - - $container->setParameter($busId.'.middleware', $middleware); - $container->register($busId, MessageBus::class)->addArgument([])->addTag('messenger.bus'); - - if ($busId === $config['default_bus']) { - $container->setAlias('messenger.default_bus', $busId)->setPublic(true); - $container->setAlias(MessageBusInterface::class, $busId); - } else { - $container->registerAliasForArgument($busId, MessageBusInterface::class); - } - } - - if (empty($config['transports'])) { - $container->removeDefinition('messenger.transport.symfony_serializer'); - $container->removeDefinition('messenger.transport.amqp.factory'); - $container->removeDefinition('messenger.transport.redis.factory'); - } else { - $container->getDefinition('messenger.transport.symfony_serializer') - ->replaceArgument(1, $config['serializer']['symfony_serializer']['format']) - ->replaceArgument(2, $config['serializer']['symfony_serializer']['context']); - $container->setAlias('messenger.default_serializer', $config['serializer']['default_serializer']); - } - - $senderAliases = []; - $transportRetryReferences = []; - foreach ($config['transports'] as $name => $transport) { - $serializerId = $transport['serializer'] ?? 'messenger.default_serializer'; - - $transportDefinition = (new Definition(TransportInterface::class)) - ->setFactory([new Reference('messenger.transport_factory'), 'createTransport']) - ->setArguments([$transport['dsn'], $transport['options'] + ['transport_name' => $name], new Reference($serializerId)]) - ->addTag('messenger.receiver', ['alias' => $name]) - ; - $container->setDefinition($transportId = 'messenger.transport.'.$name, $transportDefinition); - $senderAliases[$name] = $transportId; - - if (null !== $transport['retry_strategy']['service']) { - $transportRetryReferences[$name] = new Reference($transport['retry_strategy']['service']); - } else { - $retryServiceId = sprintf('messenger.retry.multiplier_retry_strategy.%s', $name); - $retryDefinition = new ChildDefinition('messenger.retry.abstract_multiplier_retry_strategy'); - $retryDefinition - ->replaceArgument(0, $transport['retry_strategy']['max_retries']) - ->replaceArgument(1, $transport['retry_strategy']['delay']) - ->replaceArgument(2, $transport['retry_strategy']['multiplier']) - ->replaceArgument(3, $transport['retry_strategy']['max_delay']); - $container->setDefinition($retryServiceId, $retryDefinition); - - $transportRetryReferences[$name] = new Reference($retryServiceId); - } - } - - $senderReferences = []; - // alias => service_id - foreach ($senderAliases as $alias => $serviceId) { - $senderReferences[$alias] = new Reference($serviceId); - } - // service_id => service_id - foreach ($senderAliases as $serviceId) { - $senderReferences[$serviceId] = new Reference($serviceId); - } - - $messageToSendersMapping = []; - foreach ($config['routing'] as $message => $messageConfiguration) { - if ('*' !== $message && !class_exists($message) && !interface_exists($message, false)) { - throw new LogicException(sprintf('Invalid Messenger routing configuration: class or interface "%s" not found.', $message)); - } - - // make sure senderAliases contains all senders - foreach ($messageConfiguration['senders'] as $sender) { - if (!isset($senderReferences[$sender])) { - throw new LogicException(sprintf('Invalid Messenger routing configuration: the "%s" class is being routed to a sender called "%s". This is not a valid transport or service id.', $message, $sender)); - } - } - - $messageToSendersMapping[$message] = $messageConfiguration['senders']; - } - - $sendersServiceLocator = ServiceLocatorTagPass::register($container, $senderReferences); - - $container->getDefinition('messenger.senders_locator') - ->replaceArgument(0, $messageToSendersMapping) - ->replaceArgument(1, $sendersServiceLocator) - ; - - $container->getDefinition('messenger.retry.send_failed_message_for_retry_listener') - ->replaceArgument(0, $sendersServiceLocator) - ; - - $container->getDefinition('messenger.retry_strategy_locator') - ->replaceArgument(0, $transportRetryReferences); - - if ($config['failure_transport']) { - if (!isset($senderReferences[$config['failure_transport']])) { - throw new LogicException(sprintf('Invalid Messenger configuration: the failure transport "%s" is not a valid transport or service id.', $config['failure_transport'])); - } - - $container->getDefinition('messenger.failure.send_failed_message_to_failure_transport_listener') - ->replaceArgument(0, $senderReferences[$config['failure_transport']]); - $container->getDefinition('console.command.messenger_failed_messages_retry') - ->replaceArgument(0, $config['failure_transport']); - $container->getDefinition('console.command.messenger_failed_messages_show') - ->replaceArgument(0, $config['failure_transport']); - $container->getDefinition('console.command.messenger_failed_messages_remove') - ->replaceArgument(0, $config['failure_transport']); - } else { - $container->removeDefinition('messenger.failure.send_failed_message_to_failure_transport_listener'); - $container->removeDefinition('console.command.messenger_failed_messages_retry'); - $container->removeDefinition('console.command.messenger_failed_messages_show'); - $container->removeDefinition('console.command.messenger_failed_messages_remove'); - } - } - - private function registerCacheConfiguration(array $config, ContainerBuilder $container) - { - if (!class_exists(DefaultMarshaller::class)) { - $container->removeDefinition('cache.default_marshaller'); - } - - $version = new Parameter('container.build_id'); - $container->getDefinition('cache.adapter.apcu')->replaceArgument(2, $version); - $container->getDefinition('cache.adapter.system')->replaceArgument(2, $version); - $container->getDefinition('cache.adapter.filesystem')->replaceArgument(2, $config['directory']); - - if (isset($config['prefix_seed'])) { - $container->setParameter('cache.prefix.seed', $config['prefix_seed']); - } - if ($container->hasParameter('cache.prefix.seed')) { - // Inline any env vars referenced in the parameter - $container->setParameter('cache.prefix.seed', $container->resolveEnvPlaceholders($container->getParameter('cache.prefix.seed'), true)); - } - foreach (['doctrine', 'psr6', 'redis', 'memcached', 'pdo'] as $name) { - if (isset($config[$name = 'default_'.$name.'_provider'])) { - $container->setAlias('cache.'.$name, new Alias(CachePoolPass::getServiceProvider($container, $config[$name]), false)); - } - } - foreach (['app', 'system'] as $name) { - $config['pools']['cache.'.$name] = [ - 'adapters' => [$config[$name]], - 'public' => true, - 'tags' => false, - ]; - } - foreach ($config['pools'] as $name => $pool) { - $pool['adapters'] = $pool['adapters'] ?: ['cache.app']; - - foreach ($pool['adapters'] as $provider => $adapter) { - if ($config['pools'][$adapter]['tags'] ?? false) { - $pool['adapters'][$provider] = $adapter = '.'.$adapter.'.inner'; - } - } - - if (1 === \count($pool['adapters'])) { - if (!isset($pool['provider']) && !\is_int($provider)) { - $pool['provider'] = $provider; - } - $definition = new ChildDefinition($adapter); - } else { - $definition = new Definition(ChainAdapter::class, [$pool['adapters'], 0]); - $pool['reset'] = 'reset'; - } - - if ($pool['tags']) { - if (true !== $pool['tags'] && ($config['pools'][$pool['tags']]['tags'] ?? false)) { - $pool['tags'] = '.'.$pool['tags'].'.inner'; - } - $container->register($name, TagAwareAdapter::class) - ->addArgument(new Reference('.'.$name.'.inner')) - ->addArgument(true !== $pool['tags'] ? new Reference($pool['tags']) : null) - ->setPublic($pool['public']) - ; - - $pool['name'] = $name; - $pool['public'] = false; - $name = '.'.$name.'.inner'; - - if (!\in_array($pool['name'], ['cache.app', 'cache.system'], true)) { - $container->registerAliasForArgument($pool['name'], TagAwareCacheInterface::class); - $container->registerAliasForArgument($name, CacheInterface::class, $pool['name']); - $container->registerAliasForArgument($name, CacheItemPoolInterface::class, $pool['name']); - } - } elseif (!\in_array($name, ['cache.app', 'cache.system'], true)) { - $container->register('.'.$name.'.taggable', TagAwareAdapter::class) - ->addArgument(new Reference($name)) - ; - $container->registerAliasForArgument('.'.$name.'.taggable', TagAwareCacheInterface::class, $name); - $container->registerAliasForArgument($name, CacheInterface::class); - $container->registerAliasForArgument($name, CacheItemPoolInterface::class); - } - - $definition->setPublic($pool['public']); - unset($pool['adapters'], $pool['public'], $pool['tags']); - - $definition->addTag('cache.pool', $pool); - $container->setDefinition($name, $definition); - } - - if (method_exists(PropertyAccessor::class, 'createCache')) { - $propertyAccessDefinition = $container->register('cache.property_access', AdapterInterface::class); - $propertyAccessDefinition->setPublic(false); - - if (!$container->getParameter('kernel.debug')) { - $propertyAccessDefinition->setFactory([PropertyAccessor::class, 'createCache']); - $propertyAccessDefinition->setArguments([null, 0, $version, new Reference('logger', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)]); - $propertyAccessDefinition->addTag('cache.pool', ['clearer' => 'cache.system_clearer']); - $propertyAccessDefinition->addTag('monolog.logger', ['channel' => 'cache']); - } else { - $propertyAccessDefinition->setClass(ArrayAdapter::class); - $propertyAccessDefinition->setArguments([0, false]); - } - } - } - - private function registerHttpClientConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader, array $profilerConfig) - { - $loader->load('http_client.xml'); - - $container->getDefinition('http_client')->setArguments([$config['default_options'] ?? [], $config['max_host_connections'] ?? 6]); - - if (!$hasPsr18 = interface_exists(ClientInterface::class)) { - $container->removeDefinition('psr18.http_client'); - $container->removeAlias(ClientInterface::class); - } - - if (!interface_exists(HttpClient::class)) { - $container->removeDefinition(HttpClient::class); - } - - $httpClientId = $this->isConfigEnabled($container, $profilerConfig) ? '.debug.http_client.inner' : 'http_client'; - - foreach ($config['scoped_clients'] as $name => $scopeConfig) { - if ('http_client' === $name) { - throw new InvalidArgumentException(sprintf('Invalid scope name: "%s" is reserved.', $name)); - } - - $scope = $scopeConfig['scope'] ?? null; - unset($scopeConfig['scope']); - - if (null === $scope) { - $container->register($name, ScopingHttpClient::class) - ->setFactory([ScopingHttpClient::class, 'forBaseUri']) - ->setArguments([new Reference($httpClientId), $scopeConfig['base_uri'], $scopeConfig]) - ->addTag('http_client.client') - ; - } else { - $container->register($name, ScopingHttpClient::class) - ->setArguments([new Reference($httpClientId), [$scope => $scopeConfig], $scope]) - ->addTag('http_client.client') - ; - } - - $container->registerAliasForArgument($name, HttpClientInterface::class); - - if ($hasPsr18) { - $container->setDefinition('psr18.'.$name, new ChildDefinition('psr18.http_client')) - ->replaceArgument(0, new Reference($name)); - - $container->registerAliasForArgument('psr18.'.$name, ClientInterface::class, $name); - } - } - } - - private function registerMailerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - if (!class_exists(Mailer::class)) { - throw new LogicException('Mailer support cannot be enabled as the component is not installed. Try running "composer require symfony/mailer".'); - } - - $loader->load('mailer.xml'); - $loader->load('mailer_transports.xml'); - if (!\count($config['transports']) && null === $config['dsn']) { - $config['dsn'] = 'smtp://null'; - } - $transports = $config['dsn'] ? ['main' => $config['dsn']] : $config['transports']; - $container->getDefinition('mailer.transports')->setArgument(0, $transports); - $container->getDefinition('mailer.default_transport')->setArgument(0, current($transports)); - - $classToServices = [ - SesTransportFactory::class => 'mailer.transport_factory.amazon', - GmailTransportFactory::class => 'mailer.transport_factory.gmail', - MandrillTransportFactory::class => 'mailer.transport_factory.mailchimp', - MailgunTransportFactory::class => 'mailer.transport_factory.mailgun', - PostmarkTransportFactory::class => 'mailer.transport_factory.postmark', - SendgridTransportFactory::class => 'mailer.transport_factory.sendgrid', - ]; - - foreach ($classToServices as $class => $service) { - if (!class_exists($class)) { - $container->removeDefinition($service); - } - } - - $recipients = $config['envelope']['recipients'] ?? null; - $sender = $config['envelope']['sender'] ?? null; - - $envelopeListener = $container->getDefinition('mailer.envelope_listener'); - $envelopeListener->setArgument(0, $sender); - $envelopeListener->setArgument(1, $recipients); - } - - private function registerNotifierConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) - { - if (!class_exists(Notifier::class)) { - throw new LogicException('Notifier support cannot be enabled as the component is not installed. Try running "composer require symfony/notifier".'); - } - - $loader->load('notifier.xml'); - $loader->load('notifier_transports.xml'); - - if ($config['chatter_transports']) { - $container->getDefinition('chatter.transports')->setArgument(0, $config['chatter_transports']); - } else { - $container->removeDefinition('chatter'); - } - if ($config['texter_transports']) { - $container->getDefinition('texter.transports')->setArgument(0, $config['texter_transports']); - } else { - $container->removeDefinition('texter'); - } - - if ($this->mailerConfigEnabled) { - $sender = $container->getDefinition('mailer.envelope_listener')->getArgument(0); - $container->getDefinition('notifier.channel.email')->setArgument(2, $sender); - } else { - $container->removeDefinition('notifier.channel.email'); - } - - if ($this->messengerConfigEnabled) { - if ($config['notification_on_failed_messages']) { - $container->getDefinition('notifier.failed_message_listener')->addTag('kernel.event_subscriber'); - } - - // as we have a bus, the channels don't need the transports - $container->getDefinition('notifier.channel.chat')->setArgument(0, null); - if ($container->hasDefinition('notifier.channel.email')) { - $container->getDefinition('notifier.channel.email')->setArgument(0, null); - } - $container->getDefinition('notifier.channel.sms')->setArgument(0, null); - } - - $container->getDefinition('notifier.channel_policy')->setArgument(0, $config['channel_policy']); - - $classToServices = [ - SlackTransportFactory::class => 'notifier.transport_factory.slack', - TelegramTransportFactory::class => 'notifier.transport_factory.telegram', - NexmoTransportFactory::class => 'notifier.transport_factory.nexmo', - TwilioTransportFactory::class => 'notifier.transport_factory.twilio', - ]; - - foreach ($classToServices as $class => $service) { - if (!class_exists($class)) { - $container->removeDefinition($service); - } - } - - if (isset($config['admin_recipients'])) { - $notifier = $container->getDefinition('notifier'); - foreach ($config['admin_recipients'] as $i => $recipient) { - $id = 'notifier.admin_recipient.'.$i; - $container->setDefinition($id, new Definition(AdminRecipient::class, [$recipient['email'], $recipient['phone']])); - $notifier->addMethodCall('addAdminRecipient', [new Reference($id)]); - } - } - } - - /** - * {@inheritdoc} - */ - public function getXsdValidationBasePath() - { - return \dirname(__DIR__).'/Resources/config/schema'; - } - - public function getNamespace() - { - return 'http://symfony.com/schema/dic/symfony'; - } -} diff --git a/vendor/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php b/vendor/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php deleted file mode 100644 index 231329c..0000000 --- a/vendor/symfony/framework-bundle/EventListener/SuggestMissingPackageSubscriber.php +++ /dev/null @@ -1,83 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\EventListener; - -use Symfony\Component\Console\ConsoleEvents; -use Symfony\Component\Console\Event\ConsoleErrorEvent; -use Symfony\Component\Console\Exception\CommandNotFoundException; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; - -/** - * Suggests a package, that should be installed (via composer), - * if the package is missing, and the input command namespace can be mapped to a Symfony bundle. - * - * @author Przemysław Bogusz - * - * @internal - */ -final class SuggestMissingPackageSubscriber implements EventSubscriberInterface -{ - private const PACKAGES = [ - 'doctrine' => [ - 'fixtures' => ['DoctrineFixturesBundle', 'doctrine/doctrine-fixtures-bundle --dev'], - 'mongodb' => ['DoctrineMongoDBBundle', 'doctrine/mongodb-odm-bundle'], - '_default' => ['Doctrine ORM', 'symfony/orm-pack'], - ], - 'generate' => [ - '_default' => ['SensioGeneratorBundle', 'sensio/generator-bundle'], - ], - 'make' => [ - '_default' => ['MakerBundle', 'symfony/maker-bundle --dev'], - ], - 'server' => [ - 'dump' => ['Debug Bundle', 'symfony/debug-bundle --dev'], - '_default' => ['WebServerBundle', 'symfony/web-server-bundle --dev'], - ], - ]; - - public function onConsoleError(ConsoleErrorEvent $event): void - { - if (!$event->getError() instanceof CommandNotFoundException) { - return; - } - - [$namespace, $command] = explode(':', $event->getInput()->getFirstArgument()) + [1 => '']; - - if (!isset(self::PACKAGES[$namespace])) { - return; - } - - if (isset(self::PACKAGES[$namespace][$command])) { - $suggestion = self::PACKAGES[$namespace][$command]; - $exact = true; - } else { - $suggestion = self::PACKAGES[$namespace]['_default']; - $exact = false; - } - - $error = $event->getError(); - - if ($error->getAlternatives() && !$exact) { - return; - } - - $message = sprintf("%s\n\nYou may be looking for a command provided by the \"%s\" which is currently not installed. Try running \"composer require %s\".", $error->getMessage(), $suggestion[0], $suggestion[1]); - $event->setError(new CommandNotFoundException($message)); - } - - public static function getSubscribedEvents(): array - { - return [ - ConsoleEvents::ERROR => ['onConsoleError', 0], - ]; - } -} diff --git a/vendor/symfony/framework-bundle/FrameworkBundle.php b/vendor/symfony/framework-bundle/FrameworkBundle.php deleted file mode 100644 index 6cafc43..0000000 --- a/vendor/symfony/framework-bundle/FrameworkBundle.php +++ /dev/null @@ -1,150 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle; - -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerRealRefPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerWeakRefPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass; -use Symfony\Component\Cache\DependencyInjection\CacheCollectorPass; -use Symfony\Component\Cache\DependencyInjection\CachePoolClearerPass; -use Symfony\Component\Cache\DependencyInjection\CachePoolPass; -use Symfony\Component\Cache\DependencyInjection\CachePoolPrunerPass; -use Symfony\Component\Config\Resource\ClassExistenceResource; -use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; -use Symfony\Component\DependencyInjection\Compiler\PassConfig; -use Symfony\Component\DependencyInjection\Compiler\RegisterReverseContainerPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\ErrorHandler\ErrorHandler; -use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; -use Symfony\Component\Form\DependencyInjection\FormPass; -use Symfony\Component\HttpClient\DependencyInjection\HttpClientPass; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Bundle\Bundle; -use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass; -use Symfony\Component\HttpKernel\DependencyInjection\FragmentRendererPass; -use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; -use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass; -use Symfony\Component\HttpKernel\DependencyInjection\RegisterLocaleAwareServicesPass; -use Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass; -use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\Messenger\DependencyInjection\MessengerPass; -use Symfony\Component\Mime\DependencyInjection\AddMimeTypeGuesserPass; -use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass; -use Symfony\Component\Routing\DependencyInjection\RoutingResolverPass; -use Symfony\Component\Serializer\DependencyInjection\SerializerPass; -use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass; -use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass; -use Symfony\Component\Translation\DependencyInjection\TranslatorPass; -use Symfony\Component\Translation\DependencyInjection\TranslatorPathsPass; -use Symfony\Component\Validator\DependencyInjection\AddAutoMappingConfigurationPass; -use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass; -use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass; - -/** - * Bundle. - * - * @author Fabien Potencier - */ -class FrameworkBundle extends Bundle -{ - public function boot() - { - ErrorHandler::register(null, false)->throwAt($this->container->getParameter('debug.error_handler.throw_at'), true); - - if ($this->container->getParameter('kernel.http_method_override')) { - Request::enableHttpMethodParameterOverride(); - } - - if ($trustedHosts = $this->container->getParameter('kernel.trusted_hosts')) { - Request::setTrustedHosts($trustedHosts); - } - } - - public function build(ContainerBuilder $container) - { - parent::build($container); - - $hotPathEvents = [ - KernelEvents::REQUEST, - KernelEvents::CONTROLLER, - KernelEvents::CONTROLLER_ARGUMENTS, - KernelEvents::RESPONSE, - KernelEvents::FINISH_REQUEST, - ]; - - $container->addCompilerPass(new LoggerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); - $container->addCompilerPass(new RegisterControllerArgumentLocatorsPass()); - $container->addCompilerPass(new RemoveEmptyControllerArgumentLocatorsPass(), PassConfig::TYPE_BEFORE_REMOVING); - $container->addCompilerPass(new RoutingResolverPass()); - $container->addCompilerPass(new ProfilerPass()); - // must be registered before removing private services as some might be listeners/subscribers - // but as late as possible to get resolved parameters - $container->addCompilerPass((new RegisterListenersPass())->setHotPathEvents($hotPathEvents), PassConfig::TYPE_BEFORE_REMOVING); - $this->addCompilerPassIfExists($container, AddConstraintValidatorsPass::class); - $container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_AFTER_REMOVING, -255); - $this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class); - $this->addCompilerPassIfExists($container, AddConsoleCommandPass::class, PassConfig::TYPE_BEFORE_REMOVING); - // must be registered as late as possible to get access to all Twig paths registered in - // twig.template_iterator definition - $this->addCompilerPassIfExists($container, TranslatorPass::class, PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); - $this->addCompilerPassIfExists($container, TranslatorPathsPass::class, PassConfig::TYPE_AFTER_REMOVING); - $container->addCompilerPass(new LoggingTranslatorPass()); - $container->addCompilerPass(new AddExpressionLanguageProvidersPass(false)); - $this->addCompilerPassIfExists($container, TranslationExtractorPass::class); - $this->addCompilerPassIfExists($container, TranslationDumperPass::class); - $container->addCompilerPass(new FragmentRendererPass()); - $this->addCompilerPassIfExists($container, SerializerPass::class); - $this->addCompilerPassIfExists($container, PropertyInfoPass::class); - $container->addCompilerPass(new DataCollectorTranslatorPass()); - $container->addCompilerPass(new ControllerArgumentValueResolverPass()); - $container->addCompilerPass(new CachePoolPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 32); - $container->addCompilerPass(new CachePoolClearerPass(), PassConfig::TYPE_AFTER_REMOVING); - $container->addCompilerPass(new CachePoolPrunerPass(), PassConfig::TYPE_AFTER_REMOVING); - $this->addCompilerPassIfExists($container, FormPass::class); - $container->addCompilerPass(new WorkflowGuardListenerPass()); - $container->addCompilerPass(new ResettableServicePass()); - $container->addCompilerPass(new RegisterLocaleAwareServicesPass()); - $container->addCompilerPass(new TestServiceContainerWeakRefPass(), PassConfig::TYPE_BEFORE_REMOVING, -32); - $container->addCompilerPass(new TestServiceContainerRealRefPass(), PassConfig::TYPE_AFTER_REMOVING); - $this->addCompilerPassIfExists($container, AddMimeTypeGuesserPass::class); - $this->addCompilerPassIfExists($container, MessengerPass::class); - $this->addCompilerPassIfExists($container, HttpClientPass::class); - $this->addCompilerPassIfExists($container, AddAutoMappingConfigurationPass::class); - $container->addCompilerPass(new RegisterReverseContainerPass(true)); - $container->addCompilerPass(new RegisterReverseContainerPass(false), PassConfig::TYPE_AFTER_REMOVING); - - if ($container->getParameter('kernel.debug')) { - $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 2); - $container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING); - $container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_BEFORE_REMOVING, -255); - $container->addCompilerPass(new CacheCollectorPass(), PassConfig::TYPE_BEFORE_REMOVING); - } - } - - private function addCompilerPassIfExists(ContainerBuilder $container, string $class, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) - { - $container->addResource(new ClassExistenceResource($class)); - - if (class_exists($class)) { - $container->addCompilerPass(new $class(), $type, $priority); - } - } -} diff --git a/vendor/symfony/framework-bundle/HttpCache/HttpCache.php b/vendor/symfony/framework-bundle/HttpCache/HttpCache.php deleted file mode 100644 index 037d0f0..0000000 --- a/vendor/symfony/framework-bundle/HttpCache/HttpCache.php +++ /dev/null @@ -1,72 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpCache\Esi; -use Symfony\Component\HttpKernel\HttpCache\HttpCache as BaseHttpCache; -use Symfony\Component\HttpKernel\HttpCache\Store; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * Manages HTTP cache objects in a Container. - * - * @author Fabien Potencier - */ -class HttpCache extends BaseHttpCache -{ - protected $cacheDir; - protected $kernel; - - /** - * @param string $cacheDir The cache directory (default used if null) - */ - public function __construct(KernelInterface $kernel, string $cacheDir = null) - { - $this->kernel = $kernel; - $this->cacheDir = $cacheDir; - - parent::__construct($kernel, $this->createStore(), $this->createSurrogate(), array_merge(['debug' => $kernel->isDebug()], $this->getOptions())); - } - - /** - * {@inheritdoc} - */ - protected function forward(Request $request, bool $catch = false, Response $entry = null) - { - $this->getKernel()->boot(); - $this->getKernel()->getContainer()->set('cache', $this); - - return parent::forward($request, $catch, $entry); - } - - /** - * Returns an array of options to customize the Cache configuration. - * - * @return array An array of options - */ - protected function getOptions() - { - return []; - } - - protected function createSurrogate() - { - return new Esi(); - } - - protected function createStore() - { - return new Store($this->cacheDir ?: $this->kernel->getCacheDir().'/http_cache'); - } -} diff --git a/vendor/symfony/framework-bundle/Kernel/MicroKernelTrait.php b/vendor/symfony/framework-bundle/Kernel/MicroKernelTrait.php deleted file mode 100644 index 181ea82..0000000 --- a/vendor/symfony/framework-bundle/Kernel/MicroKernelTrait.php +++ /dev/null @@ -1,97 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Kernel; - -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Routing\RouteCollectionBuilder; - -/** - * A Kernel that provides configuration hooks. - * - * @author Ryan Weaver - * @author Fabien Potencier - */ -trait MicroKernelTrait -{ - /** - * Add or import routes into your application. - * - * $routes->import('config/routing.yml'); - * $routes->add('/admin', 'App\Controller\AdminController::dashboard', 'admin_dashboard'); - */ - abstract protected function configureRoutes(RouteCollectionBuilder $routes); - - /** - * Configures the container. - * - * You can register extensions: - * - * $c->loadFromExtension('framework', [ - * 'secret' => '%secret%' - * ]); - * - * Or services: - * - * $c->register('halloween', 'FooBundle\HalloweenProvider'); - * - * Or parameters: - * - * $c->setParameter('halloween', 'lot of fun'); - */ - abstract protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader); - - /** - * {@inheritdoc} - */ - public function registerContainerConfiguration(LoaderInterface $loader) - { - $loader->load(function (ContainerBuilder $container) use ($loader) { - $container->loadFromExtension('framework', [ - 'router' => [ - 'resource' => 'kernel::loadRoutes', - 'type' => 'service', - ], - ]); - - if (!$container->hasDefinition('kernel')) { - $container->register('kernel', static::class) - ->setSynthetic(true) - ->setPublic(true) - ; - } - - $kernelDefinition = $container->getDefinition('kernel'); - $kernelDefinition->addTag('routing.route_loader'); - - if ($this instanceof EventSubscriberInterface) { - $kernelDefinition->addTag('kernel.event_subscriber'); - } - - $this->configureContainer($container, $loader); - - $container->addObjectResource($this); - }); - } - - /** - * @internal - */ - public function loadRoutes(LoaderInterface $loader) - { - $routes = new RouteCollectionBuilder($loader); - $this->configureRoutes($routes); - - return $routes->build(); - } -} diff --git a/vendor/symfony/framework-bundle/KernelBrowser.php b/vendor/symfony/framework-bundle/KernelBrowser.php deleted file mode 100644 index 38d2f06..0000000 --- a/vendor/symfony/framework-bundle/KernelBrowser.php +++ /dev/null @@ -1,206 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle; - -use Symfony\Component\BrowserKit\CookieJar; -use Symfony\Component\BrowserKit\History; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelBrowser; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\HttpKernel\Profiler\Profile as HttpProfile; - -/** - * Simulates a browser and makes requests to a Kernel object. - * - * @author Fabien Potencier - */ -class KernelBrowser extends HttpKernelBrowser -{ - private $hasPerformedRequest = false; - private $profiler = false; - private $reboot = true; - - /** - * {@inheritdoc} - */ - public function __construct(KernelInterface $kernel, array $server = [], History $history = null, CookieJar $cookieJar = null) - { - parent::__construct($kernel, $server, $history, $cookieJar); - } - - /** - * Returns the container. - * - * @return ContainerInterface|null Returns null when the Kernel has been shutdown or not started yet - */ - public function getContainer() - { - return $this->kernel->getContainer(); - } - - /** - * Returns the kernel. - * - * @return KernelInterface - */ - public function getKernel() - { - return $this->kernel; - } - - /** - * Gets the profile associated with the current Response. - * - * @return HttpProfile|false A Profile instance - */ - public function getProfile() - { - if (null === $this->response || !$this->kernel->getContainer()->has('profiler')) { - return false; - } - - return $this->kernel->getContainer()->get('profiler')->loadProfileFromResponse($this->response); - } - - /** - * Enables the profiler for the very next request. - * - * If the profiler is not enabled, the call to this method does nothing. - */ - public function enableProfiler() - { - if ($this->kernel->getContainer()->has('profiler')) { - $this->profiler = true; - } - } - - /** - * Disables kernel reboot between requests. - * - * By default, the Client reboots the Kernel for each request. This method - * allows to keep the same kernel across requests. - */ - public function disableReboot() - { - $this->reboot = false; - } - - /** - * Enables kernel reboot between requests. - */ - public function enableReboot() - { - $this->reboot = true; - } - - /** - * {@inheritdoc} - * - * @param Request $request A Request instance - * - * @return Response A Response instance - */ - protected function doRequest($request) - { - // avoid shutting down the Kernel if no request has been performed yet - // WebTestCase::createClient() boots the Kernel but do not handle a request - if ($this->hasPerformedRequest && $this->reboot) { - $this->kernel->shutdown(); - } else { - $this->hasPerformedRequest = true; - } - - if ($this->profiler) { - $this->profiler = false; - - $this->kernel->boot(); - $this->kernel->getContainer()->get('profiler')->enable(); - } - - return parent::doRequest($request); - } - - /** - * {@inheritdoc} - * - * @param Request $request A Request instance - * - * @return Response A Response instance - */ - protected function doRequestInProcess($request) - { - $response = parent::doRequestInProcess($request); - - $this->profiler = false; - - return $response; - } - - /** - * Returns the script to execute when the request must be insulated. - * - * It assumes that the autoloader is named 'autoload.php' and that it is - * stored in the same directory as the kernel (this is the case for the - * Symfony Standard Edition). If this is not your case, create your own - * client and override this method. - * - * @param Request $request A Request instance - * - * @return string The script content - */ - protected function getScript($request) - { - $kernel = var_export(serialize($this->kernel), true); - $request = var_export(serialize($request), true); - $errorReporting = error_reporting(); - - $requires = ''; - foreach (get_declared_classes() as $class) { - if (0 === strpos($class, 'ComposerAutoloaderInit')) { - $r = new \ReflectionClass($class); - $file = \dirname($r->getFileName(), 2).'/autoload.php'; - if (file_exists($file)) { - $requires .= 'require_once '.var_export($file, true).";\n"; - } - } - } - - if (!$requires) { - throw new \RuntimeException('Composer autoloader not found.'); - } - - $requires .= 'require_once '.var_export((new \ReflectionObject($this->kernel))->getFileName(), true).";\n"; - - $profilerCode = ''; - if ($this->profiler) { - $profilerCode = '$kernel->getContainer()->get(\'profiler\')->enable();'; - } - - $code = <<boot(); -$profilerCode - -\$request = unserialize($request); -EOF; - - return $code.$this->getHandleScript(); - } -} diff --git a/vendor/symfony/framework-bundle/LICENSE b/vendor/symfony/framework-bundle/LICENSE deleted file mode 100644 index a677f43..0000000 --- a/vendor/symfony/framework-bundle/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/framework-bundle/README.md b/vendor/symfony/framework-bundle/README.md deleted file mode 100644 index 9280d87..0000000 --- a/vendor/symfony/framework-bundle/README.md +++ /dev/null @@ -1,10 +0,0 @@ -FrameworkBundle -=============== - -Resources ---------- - - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/framework-bundle/Resources/config/annotations.xml b/vendor/symfony/framework-bundle/Resources/config/annotations.xml deleted file mode 100644 index 0ce6bf6..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/annotations.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - required - - - - - - - - class_exists - - - - - - - - - - - - - - - - - - %kernel.cache_dir%/annotations.php - #^Symfony\\(?:Component\\HttpKernel\\|Bundle\\FrameworkBundle\\Controller\\(?!.*Controller$))# - %kernel.debug% - - - - - - - %kernel.cache_dir%/annotations.php - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/assets.xml b/vendor/symfony/framework-bundle/Resources/config/assets.xml deleted file mode 100644 index 4aaa702..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/assets.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - false - - - - - - - - - - - - - - - - - - %asset.request_context.base_path% - %asset.request_context.secure% - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/cache.xml b/vendor/symfony/framework-bundle/Resources/config/cache.xml deleted file mode 100644 index 9959deb..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/cache.xml +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - %kernel.cache_dir%/pools - - - - - - - - 0 - - - - - - - - - - - - 0 - - - - - - - - - - 0 - %kernel.cache_dir%/pools - - - - - - - - - - - 0 - - - - - - - - 0 - - - - - - - - - - - - 0 - - - - - - - - - - - - 0 - - - - - - - - - - - 0 - - - - - - - null - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/cache_debug.xml b/vendor/symfony/framework-bundle/Resources/config/cache_debug.xml deleted file mode 100644 index 20e2276..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/cache_debug.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/collectors.xml b/vendor/symfony/framework-bundle/Resources/config/collectors.xml deleted file mode 100644 index 17df61d..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/collectors.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %kernel.cache_dir%/%kernel.container_class% - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/console.xml b/vendor/symfony/framework-bundle/Resources/config/console.xml deleted file mode 100644 index 6333f2d..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/console.xml +++ /dev/null @@ -1,232 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - %kernel.project_dir% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - null - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %translator.default_path% - - - - - - - - - - - %kernel.default_locale% - %translator.default_path% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/debug.xml b/vendor/symfony/framework-bundle/Resources/config/debug.xml deleted file mode 100644 index 63a61ef..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/debug.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/debug_prod.xml b/vendor/symfony/framework-bundle/Resources/config/debug_prod.xml deleted file mode 100644 index 786158d..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/debug_prod.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - -1 - - - - - - - - - null - - null - %debug.error_handler.throw_at% - %kernel.debug% - - %kernel.debug% - - - - %debug.file_link_format% - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/error_renderer.xml b/vendor/symfony/framework-bundle/Resources/config/error_renderer.xml deleted file mode 100644 index 4d2423f..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/error_renderer.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - %kernel.debug% - - - %kernel.charset% - - %kernel.project_dir% - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/esi.xml b/vendor/symfony/framework-bundle/Resources/config/esi.xml deleted file mode 100644 index 65e26d8..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/esi.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/form.xml b/vendor/symfony/framework-bundle/Resources/config/form.xml deleted file mode 100644 index 17598fa..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/form.xml +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %validator.translation_domain% - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/form_csrf.xml b/vendor/symfony/framework-bundle/Resources/config/form_csrf.xml deleted file mode 100644 index 5e897be..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/form_csrf.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - %form.type_extension.csrf.enabled% - %form.type_extension.csrf.field_name% - - %validator.translation_domain% - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/form_debug.xml b/vendor/symfony/framework-bundle/Resources/config/form_debug.xml deleted file mode 100644 index 5e3e97a..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/form_debug.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/fragment_listener.xml b/vendor/symfony/framework-bundle/Resources/config/fragment_listener.xml deleted file mode 100644 index b7c6411..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/fragment_listener.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - %fragment.path% - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/fragment_renderer.xml b/vendor/symfony/framework-bundle/Resources/config/fragment_renderer.xml deleted file mode 100644 index 827a22f..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/fragment_renderer.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - /_fragment - - - - - - - - - %kernel.debug% - - - - - - - %fragment.path% - - - - - - %fragment.renderer.hinclude.global_template% - %fragment.path% - - - - - - - - %fragment.path% - - - - - - - - %fragment.path% - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/http_client.xml b/vendor/symfony/framework-bundle/Resources/config/http_client.xml deleted file mode 100644 index 10256b6..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/http_client.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/http_client_debug.xml b/vendor/symfony/framework-bundle/Resources/config/http_client_debug.xml deleted file mode 100644 index 6d6ae4b..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/http_client_debug.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/identity_translator.xml b/vendor/symfony/framework-bundle/Resources/config/identity_translator.xml deleted file mode 100644 index 9dccb43..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/identity_translator.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/lock.xml b/vendor/symfony/framework-bundle/Resources/config/lock.xml deleted file mode 100644 index 86b8571..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/lock.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/mailer.xml b/vendor/symfony/framework-bundle/Resources/config/mailer.xml deleted file mode 100644 index 8a99eeb..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/mailer.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/mailer_debug.xml b/vendor/symfony/framework-bundle/Resources/config/mailer_debug.xml deleted file mode 100644 index 17e1a6e..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/mailer_debug.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/mailer_transports.xml b/vendor/symfony/framework-bundle/Resources/config/mailer_transports.xml deleted file mode 100644 index d478942..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/mailer_transports.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/messenger.xml b/vendor/symfony/framework-bundle/Resources/config/messenger.xml deleted file mode 100644 index 14117ee..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/messenger.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/messenger_debug.xml b/vendor/symfony/framework-bundle/Resources/config/messenger_debug.xml deleted file mode 100644 index 96f43b3..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/messenger_debug.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/mime_type.xml b/vendor/symfony/framework-bundle/Resources/config/mime_type.xml deleted file mode 100644 index d4c1eb1..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/mime_type.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/notifier.xml b/vendor/symfony/framework-bundle/Resources/config/notifier.xml deleted file mode 100644 index dfc6cdc..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/notifier.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/notifier_transports.xml b/vendor/symfony/framework-bundle/Resources/config/notifier_transports.xml deleted file mode 100644 index c4d9cf8..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/notifier_transports.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/profiling.xml b/vendor/symfony/framework-bundle/Resources/config/profiling.xml deleted file mode 100644 index 166be86..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/profiling.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - %profiler.storage.dsn% - - - - - - - null - %profiler_listener.only_exceptions% - %profiler_listener.only_master_requests% - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/property_access.xml b/vendor/symfony/framework-bundle/Resources/config/property_access.xml deleted file mode 100644 index 424f9f6..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/property_access.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/property_info.xml b/vendor/symfony/framework-bundle/Resources/config/property_info.xml deleted file mode 100644 index cd78d7f..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/property_info.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/request.xml b/vendor/symfony/framework-bundle/Resources/config/request.xml deleted file mode 100644 index 048b61e..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/request.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/routing.xml b/vendor/symfony/framework-bundle/Resources/config/routing.xml deleted file mode 100644 index 49a3936..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/routing.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - localhost - http - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %router.resource% - - %kernel.cache_dir% - %kernel.debug% - Symfony\Component\Routing\Generator\CompiledUrlGenerator - Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper - Symfony\Bundle\FrameworkBundle\Routing\RedirectableCompiledUrlMatcher - Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper - - - - - %kernel.default_locale% - - - - - - - - - - - - - %router.request_context.base_url% - GET - %router.request_context.host% - %router.request_context.scheme% - %request_listener.http_port% - %request_listener.https_port% - - - - - - - - - - - - - - - - - %kernel.project_dir% - %kernel.debug% - - - - - %request_listener.http_port% - %request_listener.https_port% - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/routing/errors.xml b/vendor/symfony/framework-bundle/Resources/config/routing/errors.xml deleted file mode 100644 index 13a9cc4..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/routing/errors.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - error_controller::preview - html - \d+ - - diff --git a/vendor/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd b/vendor/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd deleted file mode 100644 index b8e4488..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/schema/symfony-1.0.xsd +++ /dev/null @@ -1,560 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/secrets.xml b/vendor/symfony/framework-bundle/Resources/config/secrets.xml deleted file mode 100644 index 65fd107..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/secrets.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/security_csrf.xml b/vendor/symfony/framework-bundle/Resources/config/security_csrf.xml deleted file mode 100644 index eefe6ad..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/security_csrf.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/serializer.xml b/vendor/symfony/framework-bundle/Resources/config/serializer.xml deleted file mode 100644 index 0dbc388..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/serializer.xml +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - %kernel.cache_dir%/serialization.php - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %kernel.debug% - - - - - - - - - - - null - - - - - - - - - - - - - - - - - - - - - null - - - - - - - - %serializer.mapping.cache.file% - - - - - - %serializer.mapping.cache.file% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %kernel.debug% - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/services.xml b/vendor/symfony/framework-bundle/Resources/config/services.xml deleted file mode 100644 index ac406aa..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/services.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - console.command - console.error - console.terminate - form.pre_submit - form.submit - form.post_submit - form.pre_set_data - form.post_set_data - kernel.controller_arguments - kernel.controller - kernel.response - kernel.finish_request - kernel.request - kernel.view - kernel.exception - kernel.terminate - workflow.guard - workflow.leave - workflow.transition - workflow.enter - workflow.entered - workflow.completed - workflow.announce - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %kernel.debug% - %kernel.cache_dir%/%kernel.container_class%Deprecations.log - - - - - - - - - - - - - - - - - - - %kernel.secret% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %kernel.default_locale% - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/session.xml b/vendor/symfony/framework-bundle/Resources/config/session.xml deleted file mode 100644 index 0cb7b4e..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/session.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - _sf2_meta - - - - - - - - - - - - - - - - - %session.metadata.storage_key% - %session.metadata.update_threshold% - - - - %session.storage.options% - - - - - - - - - - - - - - - - %kernel.cache_dir%/sessions - MOCKSESSID - - - - - - - %session.save_path% - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/ssi.xml b/vendor/symfony/framework-bundle/Resources/config/ssi.xml deleted file mode 100644 index b4e5b3d..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/ssi.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/test.xml b/vendor/symfony/framework-bundle/Resources/config/test.xml deleted file mode 100644 index ef571fd..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/test.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - %test.client.parameters% - - - - - - - - - - - - - - - - - - test.private_services_locator - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/translation.xml b/vendor/symfony/framework-bundle/Resources/config/translation.xml deleted file mode 100644 index 07213a2..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/translation.xml +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - - - - %kernel.default_locale% - - - %kernel.cache_dir%/translations - %kernel.debug% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - yaml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/translation_debug.xml b/vendor/symfony/framework-bundle/Resources/config/translation_debug.xml deleted file mode 100644 index c9c5385..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/translation_debug.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/validator.xml b/vendor/symfony/framework-bundle/Resources/config/validator.xml deleted file mode 100644 index 070908f..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/validator.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - %kernel.cache_dir%/validation.php - - - - - - - - - - - - - - - - - - - - %validator.translation_domain% - - - - - - - - %validator.mapping.cache.file% - - - - - - %validator.mapping.cache.file% - - - - - - - - - - - - - - - - - - - %kernel.charset% - false - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/validator_debug.xml b/vendor/symfony/framework-bundle/Resources/config/validator_debug.xml deleted file mode 100644 index 939c555..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/validator_debug.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/web.xml b/vendor/symfony/framework-bundle/Resources/config/web.xml deleted file mode 100644 index cbdc558..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/web.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %kernel.charset% - - - - - - - - - - %kernel.default_locale% - - - - - - - - - - - - - - %kernel.error_controller% - - - - - - - %kernel.error_controller% - - %kernel.debug% - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/web_link.xml b/vendor/symfony/framework-bundle/Resources/config/web_link.xml deleted file mode 100644 index bf3e8d7..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/web_link.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/config/workflow.xml b/vendor/symfony/framework-bundle/Resources/config/workflow.xml deleted file mode 100644 index 78741de..0000000 --- a/vendor/symfony/framework-bundle/Resources/config/workflow.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - null - - - - - - null - - - - - - - - - - - - diff --git a/vendor/symfony/framework-bundle/Resources/views/Form/week_widget.html.php b/vendor/symfony/framework-bundle/Resources/views/Form/week_widget.html.php deleted file mode 100644 index 610b6e0..0000000 --- a/vendor/symfony/framework-bundle/Resources/views/Form/week_widget.html.php +++ /dev/null @@ -1,14 +0,0 @@ - - block($form, 'form_widget_simple'); ?> - - ['size' => 1]] : [] ?> -
    block($form, 'widget_container_attributes') ?>> - widget($form['year'], $vars); - echo '-'; - echo $view['form']->widget($form['week'], $vars); - ?> -
    - diff --git a/vendor/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php b/vendor/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php deleted file mode 100644 index 51419c8..0000000 --- a/vendor/symfony/framework-bundle/Routing/AnnotatedRouteControllerLoader.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Routing; - -use Symfony\Component\Routing\Loader\AnnotationClassLoader; -use Symfony\Component\Routing\Route; - -/** - * AnnotatedRouteControllerLoader is an implementation of AnnotationClassLoader - * that sets the '_controller' default based on the class and method names. - * - * @author Fabien Potencier - */ -class AnnotatedRouteControllerLoader extends AnnotationClassLoader -{ - /** - * Configures the _controller default parameter of a given Route instance. - * - * @param mixed $annot The annotation class instance - */ - protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot) - { - if ('__invoke' === $method->getName()) { - $route->setDefault('_controller', $class->getName()); - } else { - $route->setDefault('_controller', $class->getName().'::'.$method->getName()); - } - } - - /** - * Makes the default route name more sane by removing common keywords. - * - * @return string - */ - protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) - { - return preg_replace([ - '/(bundle|controller)_/', - '/action(_\d+)?$/', - '/__/', - ], [ - '_', - '\\1', - '_', - ], parent::getDefaultRouteName($class, $method)); - } -} diff --git a/vendor/symfony/framework-bundle/Routing/DelegatingLoader.php b/vendor/symfony/framework-bundle/Routing/DelegatingLoader.php deleted file mode 100644 index f25bdf3..0000000 --- a/vendor/symfony/framework-bundle/Routing/DelegatingLoader.php +++ /dev/null @@ -1,89 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Routing; - -use Symfony\Component\Config\Exception\LoaderLoadException; -use Symfony\Component\Config\Loader\DelegatingLoader as BaseDelegatingLoader; -use Symfony\Component\Config\Loader\LoaderResolverInterface; - -/** - * DelegatingLoader delegates route loading to other loaders using a loader resolver. - * - * This implementation resolves the _controller attribute from the short notation - * to the fully-qualified form (from a:b:c to class::method). - * - * @author Fabien Potencier - * - * @final - */ -class DelegatingLoader extends BaseDelegatingLoader -{ - private $loading = false; - private $defaultOptions; - - public function __construct(LoaderResolverInterface $resolver, array $defaultOptions = []) - { - $this->defaultOptions = $defaultOptions; - - parent::__construct($resolver); - } - - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - if ($this->loading) { - // This can happen if a fatal error occurs in parent::load(). - // Here is the scenario: - // - while routes are being loaded by parent::load() below, a fatal error - // occurs (e.g. parse error in a controller while loading annotations); - // - PHP abruptly empties the stack trace, bypassing all catch/finally blocks; - // it then calls the registered shutdown functions; - // - the ErrorHandler catches the fatal error and re-injects it for rendering - // thanks to HttpKernel->terminateWithException() (that calls handleException()); - // - at this stage, if we try to load the routes again, we must prevent - // the fatal error from occurring a second time, - // otherwise the PHP process would be killed immediately; - // - while rendering the exception page, the router can be required - // (by e.g. the web profiler that needs to generate an URL); - // - this handles the case and prevents the second fatal error - // by triggering an exception beforehand. - - throw new LoaderLoadException($resource, null, null, null, $type); - } - $this->loading = true; - - try { - $collection = parent::load($resource, $type); - } finally { - $this->loading = false; - } - - foreach ($collection->all() as $route) { - if ($this->defaultOptions) { - $route->setOptions($route->getOptions() + $this->defaultOptions); - } - if (!\is_string($controller = $route->getDefault('_controller'))) { - continue; - } - - if (false !== strpos($controller, '::')) { - continue; - } - - $route->setDefault('_controller', $controller); - } - - return $collection; - } -} diff --git a/vendor/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php b/vendor/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php deleted file mode 100644 index dba9d6d..0000000 --- a/vendor/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Routing; - -use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; -use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; - -/** - * @author Fabien Potencier - * - * @internal - */ -class RedirectableCompiledUrlMatcher extends CompiledUrlMatcher implements RedirectableUrlMatcherInterface -{ - /** - * {@inheritdoc} - */ - public function redirect(string $path, string $route, string $scheme = null): array - { - return [ - '_controller' => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController::urlRedirectAction', - 'path' => $path, - 'permanent' => true, - 'scheme' => $scheme, - 'httpPort' => $this->context->getHttpPort(), - 'httpsPort' => $this->context->getHttpsPort(), - '_route' => $route, - ]; - } -} diff --git a/vendor/symfony/framework-bundle/Routing/RouteLoaderInterface.php b/vendor/symfony/framework-bundle/Routing/RouteLoaderInterface.php deleted file mode 100644 index d1cb55a..0000000 --- a/vendor/symfony/framework-bundle/Routing/RouteLoaderInterface.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Routing; - -/** - * Marker interface for service route loaders. - */ -interface RouteLoaderInterface -{ -} diff --git a/vendor/symfony/framework-bundle/Routing/Router.php b/vendor/symfony/framework-bundle/Routing/Router.php deleted file mode 100644 index f9def3d..0000000 --- a/vendor/symfony/framework-bundle/Routing/Router.php +++ /dev/null @@ -1,189 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Routing; - -use Psr\Container\ContainerInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\DependencyInjection\Config\ContainerParametersResource; -use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; -use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\Router as BaseRouter; -use Symfony\Contracts\Service\ServiceSubscriberInterface; - -/** - * This Router creates the Loader only when the cache is empty. - * - * @author Fabien Potencier - */ -class Router extends BaseRouter implements WarmableInterface, ServiceSubscriberInterface -{ - private $container; - private $collectedParameters = []; - private $paramFetcher; - - /** - * @param mixed $resource The main resource to load - */ - public function __construct(ContainerInterface $container, $resource, array $options = [], RequestContext $context = null, ContainerInterface $parameters = null, LoggerInterface $logger = null, string $defaultLocale = null) - { - $this->container = $container; - $this->resource = $resource; - $this->context = $context ?: new RequestContext(); - $this->logger = $logger; - $this->setOptions($options); - - if ($parameters) { - $this->paramFetcher = [$parameters, 'get']; - } elseif ($container instanceof SymfonyContainerInterface) { - $this->paramFetcher = [$container, 'getParameter']; - } else { - throw new \LogicException(sprintf('You should either pass a "%s" instance or provide the $parameters argument of the "%s" method.', SymfonyContainerInterface::class, __METHOD__)); - } - - $this->defaultLocale = $defaultLocale; - } - - /** - * {@inheritdoc} - */ - public function getRouteCollection() - { - if (null === $this->collection) { - $this->collection = $this->container->get('routing.loader')->load($this->resource, $this->options['resource_type']); - $this->resolveParameters($this->collection); - $this->collection->addResource(new ContainerParametersResource($this->collectedParameters)); - } - - return $this->collection; - } - - /** - * {@inheritdoc} - */ - public function warmUp(string $cacheDir) - { - $currentDir = $this->getOption('cache_dir'); - - // force cache generation - $this->setOption('cache_dir', $cacheDir); - $this->getMatcher(); - $this->getGenerator(); - - $this->setOption('cache_dir', $currentDir); - } - - /** - * Replaces placeholders with service container parameter values in: - * - the route defaults, - * - the route requirements, - * - the route path, - * - the route host, - * - the route schemes, - * - the route methods. - */ - private function resolveParameters(RouteCollection $collection) - { - foreach ($collection as $route) { - foreach ($route->getDefaults() as $name => $value) { - $route->setDefault($name, $this->resolve($value)); - } - - foreach ($route->getRequirements() as $name => $value) { - $route->setRequirement($name, $this->resolve($value)); - } - - $route->setPath($this->resolve($route->getPath())); - $route->setHost($this->resolve($route->getHost())); - - $schemes = []; - foreach ($route->getSchemes() as $scheme) { - $schemes = array_merge($schemes, explode('|', $this->resolve($scheme))); - } - $route->setSchemes($schemes); - - $methods = []; - foreach ($route->getMethods() as $method) { - $methods = array_merge($methods, explode('|', $this->resolve($method))); - } - $route->setMethods($methods); - $route->setCondition($this->resolve($route->getCondition())); - } - } - - /** - * Recursively replaces placeholders with the service container parameters. - * - * @param mixed $value The source which might contain "%placeholders%" - * - * @return mixed The source with the placeholders replaced by the container - * parameters. Arrays are resolved recursively. - * - * @throws ParameterNotFoundException When a placeholder does not exist as a container parameter - * @throws RuntimeException When a container value is not a string or a numeric value - */ - private function resolve($value) - { - if (\is_array($value)) { - foreach ($value as $key => $val) { - $value[$key] = $this->resolve($val); - } - - return $value; - } - - if (!\is_string($value)) { - return $value; - } - - $escapedValue = preg_replace_callback('/%%|%([^%\s]++)%/', function ($match) use ($value) { - // skip %% - if (!isset($match[1])) { - return '%%'; - } - - if (preg_match('/^env\((?:\w++:)*+\w++\)$/', $match[1])) { - throw new RuntimeException(sprintf('Using "%%%s%%" is not allowed in routing configuration.', $match[1])); - } - - $resolved = ($this->paramFetcher)($match[1]); - - if (\is_bool($resolved)) { - $resolved = (string) (int) $resolved; - } - - if (\is_string($resolved) || is_numeric($resolved)) { - $this->collectedParameters[$match[1]] = $resolved; - - return (string) $this->resolve($resolved); - } - - throw new RuntimeException(sprintf('The container parameter "%s", used in the route configuration value "%s", must be a string or numeric, but it is of type %s.', $match[1], $value, \gettype($resolved))); - }, $value); - - return str_replace('%%', '%', $escapedValue); - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedServices() - { - return [ - 'routing.loader' => LoaderInterface::class, - ]; - } -} diff --git a/vendor/symfony/framework-bundle/Secrets/AbstractVault.php b/vendor/symfony/framework-bundle/Secrets/AbstractVault.php deleted file mode 100644 index eeecbbb..0000000 --- a/vendor/symfony/framework-bundle/Secrets/AbstractVault.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Secrets; - -/** - * @author Nicolas Grekas - * - * @internal - */ -abstract class AbstractVault -{ - protected $lastMessage; - - public function getLastMessage(): ?string - { - return $this->lastMessage; - } - - abstract public function generateKeys(bool $override = false): bool; - - abstract public function seal(string $name, string $value): void; - - abstract public function reveal(string $name): ?string; - - abstract public function remove(string $name): bool; - - abstract public function list(bool $reveal = false): array; - - protected function validateName(string $name): void - { - if (!preg_match('/^\w++$/D', $name)) { - throw new \LogicException(sprintf('Invalid secret name "%s": only "word" characters are allowed.', $name)); - } - } - - protected function getPrettyPath(string $path) - { - return str_replace(getcwd().\DIRECTORY_SEPARATOR, '', $path); - } -} diff --git a/vendor/symfony/framework-bundle/Secrets/DotenvVault.php b/vendor/symfony/framework-bundle/Secrets/DotenvVault.php deleted file mode 100644 index a64a744..0000000 --- a/vendor/symfony/framework-bundle/Secrets/DotenvVault.php +++ /dev/null @@ -1,107 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Secrets; - -/** - * @author Nicolas Grekas - * - * @internal - */ -class DotenvVault extends AbstractVault -{ - private $dotenvFile; - - public function __construct(string $dotenvFile) - { - $this->dotenvFile = strtr($dotenvFile, '/', \DIRECTORY_SEPARATOR); - } - - public function generateKeys(bool $override = false): bool - { - $this->lastMessage = 'The dotenv vault doesn\'t encrypt secrets thus doesn\'t need keys.'; - - return false; - } - - public function seal(string $name, string $value): void - { - $this->lastMessage = null; - $this->validateName($name); - $v = str_replace("'", "'\\''", $value); - - $content = file_exists($this->dotenvFile) ? file_get_contents($this->dotenvFile) : ''; - $content = preg_replace("/^$name=((\\\\'|'[^']++')++|.*)/m", "$name='$v'", $content, -1, $count); - - if (!$count) { - $content .= "$name='$v'\n"; - } - - file_put_contents($this->dotenvFile, $content); - - $this->lastMessage = sprintf('Secret "%s" %s in "%s".', $name, $count ? 'added' : 'updated', $this->getPrettyPath($this->dotenvFile)); - } - - public function reveal(string $name): ?string - { - $this->lastMessage = null; - $this->validateName($name); - $v = \is_string($_SERVER[$name] ?? null) && 0 !== strpos($name, 'HTTP_') ? $_SERVER[$name] : ($_ENV[$name] ?? null); - - if (null === $v) { - $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile)); - - return null; - } - - return $v; - } - - public function remove(string $name): bool - { - $this->lastMessage = null; - $this->validateName($name); - - $content = file_exists($this->dotenvFile) ? file_get_contents($this->dotenvFile) : ''; - $content = preg_replace("/^$name=((\\\\'|'[^']++')++|.*)\n?/m", '', $content, -1, $count); - - if ($count) { - file_put_contents($this->dotenvFile, $content); - $this->lastMessage = sprintf('Secret "%s" removed from file "%s".', $name, $this->getPrettyPath($this->dotenvFile)); - - return true; - } - - $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath($this->dotenvFile)); - - return false; - } - - public function list(bool $reveal = false): array - { - $this->lastMessage = null; - $secrets = []; - - foreach ($_ENV as $k => $v) { - if (preg_match('/^\w+$/D', $k)) { - $secrets[$k] = $reveal ? $v : null; - } - } - - foreach ($_SERVER as $k => $v) { - if (\is_string($v) && preg_match('/^\w+$/D', $k)) { - $secrets[$k] = $reveal ? $v : null; - } - } - - return $secrets; - } -} diff --git a/vendor/symfony/framework-bundle/Secrets/SodiumVault.php b/vendor/symfony/framework-bundle/Secrets/SodiumVault.php deleted file mode 100644 index 883a686..0000000 --- a/vendor/symfony/framework-bundle/Secrets/SodiumVault.php +++ /dev/null @@ -1,220 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Secrets; - -use Symfony\Component\DependencyInjection\EnvVarLoaderInterface; - -/** - * @author Tobias Schultze - * @author Jérémy Derussé - * @author Nicolas Grekas - * - * @internal - */ -class SodiumVault extends AbstractVault implements EnvVarLoaderInterface -{ - private $encryptionKey; - private $decryptionKey; - private $pathPrefix; - private $secretsDir; - - /** - * @param string|object|null $decryptionKey A string or a stringable object that defines the private key to use to decrypt the vault - * or null to store generated keys in the provided $secretsDir - */ - public function __construct(string $secretsDir, $decryptionKey = null) - { - if (null !== $decryptionKey && !\is_string($decryptionKey) && !(\is_object($decryptionKey) && method_exists($decryptionKey, '__toString'))) { - throw new \TypeError(sprintf('Decryption key should be a string or an object that implements the __toString() method, %s given.', \gettype($decryptionKey))); - } - - $this->pathPrefix = rtrim(strtr($secretsDir, '/', \DIRECTORY_SEPARATOR), \DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR.basename($secretsDir).'.'; - $this->decryptionKey = $decryptionKey; - $this->secretsDir = $secretsDir; - } - - public function generateKeys(bool $override = false): bool - { - $this->lastMessage = null; - - if (null === $this->encryptionKey && '' !== $this->decryptionKey = (string) $this->decryptionKey) { - throw new \LogicException('Cannot generate keys when a decryption key has been provided while instantiating the vault.'); - } - - try { - $this->loadKeys(); - } catch (\RuntimeException $e) { - // ignore failures to load keys - } - - if ('' !== $this->decryptionKey && !file_exists($this->pathPrefix.'encrypt.public.php')) { - $this->export('encrypt.public', $this->encryptionKey); - } - - if (!$override && null !== $this->encryptionKey) { - $this->lastMessage = sprintf('Sodium keys already exist at "%s*.{public,private}" and won\'t be overridden.', $this->getPrettyPath($this->pathPrefix)); - - return false; - } - - $this->decryptionKey = sodium_crypto_box_keypair(); - $this->encryptionKey = sodium_crypto_box_publickey($this->decryptionKey); - - $this->export('encrypt.public', $this->encryptionKey); - $this->export('decrypt.private', $this->decryptionKey); - - $this->lastMessage = sprintf('Sodium keys have been generated at "%s*.public/private.php".', $this->getPrettyPath($this->pathPrefix)); - - return true; - } - - public function seal(string $name, string $value): void - { - $this->lastMessage = null; - $this->validateName($name); - $this->loadKeys(); - $this->export($name.'.'.substr(md5($name), 0, 6), sodium_crypto_box_seal($value, $this->encryptionKey ?? sodium_crypto_box_publickey($this->decryptionKey))); - - $list = $this->list(); - $list[$name] = null; - uksort($list, 'strnatcmp'); - file_put_contents($this->pathPrefix.'list.php', sprintf("lastMessage = sprintf('Secret "%s" encrypted in "%s"; you can commit it.', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); - } - - public function reveal(string $name): ?string - { - $this->lastMessage = null; - $this->validateName($name); - - if (!file_exists($file = $this->pathPrefix.$name.'.'.substr_replace(md5($name), '.php', -26))) { - $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); - - return null; - } - - if (!\function_exists('sodium_crypto_box_seal')) { - $this->lastMessage = sprintf('Secret "%s" cannot be revealed as the "sodium" PHP extension missing. Try running "composer require paragonie/sodium_compat" if you cannot enable the extension."', $name); - - return null; - } - - $this->loadKeys(); - - if ('' === $this->decryptionKey) { - $this->lastMessage = sprintf('Secret "%s" cannot be revealed as no decryption key was found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); - - return null; - } - - if (false === $value = sodium_crypto_box_seal_open(include $file, $this->decryptionKey)) { - $this->lastMessage = sprintf('Secret "%s" cannot be revealed as the wrong decryption key was provided for "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); - - return null; - } - - return $value; - } - - public function remove(string $name): bool - { - $this->lastMessage = null; - $this->validateName($name); - - if (!file_exists($file = $this->pathPrefix.$name.'.'.substr_replace(md5($name), '.php', -26))) { - $this->lastMessage = sprintf('Secret "%s" not found in "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); - - return false; - } - - $list = $this->list(); - unset($list[$name]); - file_put_contents($this->pathPrefix.'list.php', sprintf("lastMessage = sprintf('Secret "%s" removed from "%s".', $name, $this->getPrettyPath(\dirname($this->pathPrefix).\DIRECTORY_SEPARATOR)); - - return @unlink($file) || !file_exists($file); - } - - public function list(bool $reveal = false): array - { - $this->lastMessage = null; - - if (!file_exists($file = $this->pathPrefix.'list.php')) { - return []; - } - - $secrets = include $file; - - if (!$reveal) { - return $secrets; - } - - foreach ($secrets as $name => $value) { - $secrets[$name] = $this->reveal($name); - } - - return $secrets; - } - - public function loadEnvVars(): array - { - return $this->list(true); - } - - private function loadKeys(): void - { - if (!\function_exists('sodium_crypto_box_seal')) { - throw new \LogicException('The "sodium" PHP extension is required to deal with secrets. Alternatively, try running "composer require paragonie/sodium_compat" if you cannot enable the extension."'); - } - - if (null !== $this->encryptionKey || '' !== $this->decryptionKey = (string) $this->decryptionKey) { - return; - } - - if (file_exists($this->pathPrefix.'decrypt.private.php')) { - $this->decryptionKey = (string) include $this->pathPrefix.'decrypt.private.php'; - } - - if (file_exists($this->pathPrefix.'encrypt.public.php')) { - $this->encryptionKey = (string) include $this->pathPrefix.'encrypt.public.php'; - } elseif ('' !== $this->decryptionKey) { - $this->encryptionKey = sodium_crypto_box_publickey($this->decryptionKey); - } else { - throw new \RuntimeException(sprintf('Encryption key not found in "%s".', \dirname($this->pathPrefix))); - } - } - - private function export(string $file, string $data): void - { - $name = basename($this->pathPrefix.$file); - $data = str_replace('%', '\x', rawurlencode($data)); - $data = sprintf("createSecretsDir(); - - if (false === file_put_contents($this->pathPrefix.$file.'.php', $data, LOCK_EX)) { - $e = error_get_last(); - throw new \ErrorException($e['message'] ?? 'Failed to write secrets data.', 0, $e['type'] ?? E_USER_WARNING); - } - } - - private function createSecretsDir(): void - { - if ($this->secretsDir && !is_dir($this->secretsDir) && !@mkdir($this->secretsDir, 0777, true) && !is_dir($this->secretsDir)) { - throw new \RuntimeException(sprintf('Unable to create the secrets directory (%s)', $this->secretsDir)); - } - - $this->secretsDir = null; - } -} diff --git a/vendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php b/vendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php deleted file mode 100644 index 086d83e..0000000 --- a/vendor/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php +++ /dev/null @@ -1,159 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Test; - -use PHPUnit\Framework\Constraint\LogicalAnd; -use PHPUnit\Framework\Constraint\LogicalNot; -use Symfony\Component\BrowserKit\AbstractBrowser; -use Symfony\Component\BrowserKit\Test\Constraint as BrowserKitConstraint; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\Test\Constraint as ResponseConstraint; - -/** - * Ideas borrowed from Laravel Dusk's assertions. - * - * @see https://laravel.com/docs/5.7/dusk#available-assertions - */ -trait BrowserKitAssertionsTrait -{ - public static function assertResponseIsSuccessful(string $message = ''): void - { - self::assertThat(self::getResponse(), new ResponseConstraint\ResponseIsSuccessful(), $message); - } - - public static function assertResponseStatusCodeSame(int $expectedCode, string $message = ''): void - { - self::assertThat(self::getResponse(), new ResponseConstraint\ResponseStatusCodeSame($expectedCode), $message); - } - - public static function assertResponseRedirects(string $expectedLocation = null, int $expectedCode = null, string $message = ''): void - { - $constraint = new ResponseConstraint\ResponseIsRedirected(); - if ($expectedLocation) { - $constraint = LogicalAnd::fromConstraints($constraint, new ResponseConstraint\ResponseHeaderSame('Location', $expectedLocation)); - } - if ($expectedCode) { - $constraint = LogicalAnd::fromConstraints($constraint, new ResponseConstraint\ResponseStatusCodeSame($expectedCode)); - } - - self::assertThat(self::getResponse(), $constraint, $message); - } - - public static function assertResponseHasHeader(string $headerName, string $message = ''): void - { - self::assertThat(self::getResponse(), new ResponseConstraint\ResponseHasHeader($headerName), $message); - } - - public static function assertResponseNotHasHeader(string $headerName, string $message = ''): void - { - self::assertThat(self::getResponse(), new LogicalNot(new ResponseConstraint\ResponseHasHeader($headerName)), $message); - } - - public static function assertResponseHeaderSame(string $headerName, string $expectedValue, string $message = ''): void - { - self::assertThat(self::getResponse(), new ResponseConstraint\ResponseHeaderSame($headerName, $expectedValue), $message); - } - - public static function assertResponseHeaderNotSame(string $headerName, string $expectedValue, string $message = ''): void - { - self::assertThat(self::getResponse(), new LogicalNot(new ResponseConstraint\ResponseHeaderSame($headerName, $expectedValue)), $message); - } - - public static function assertResponseHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void - { - self::assertThat(self::getResponse(), new ResponseConstraint\ResponseHasCookie($name, $path, $domain), $message); - } - - public static function assertResponseNotHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void - { - self::assertThat(self::getResponse(), new LogicalNot(new ResponseConstraint\ResponseHasCookie($name, $path, $domain)), $message); - } - - public static function assertResponseCookieValueSame(string $name, string $expectedValue, string $path = '/', string $domain = null, string $message = ''): void - { - self::assertThat(self::getResponse(), LogicalAnd::fromConstraints( - new ResponseConstraint\ResponseHasCookie($name, $path, $domain), - new ResponseConstraint\ResponseCookieValueSame($name, $expectedValue, $path, $domain) - ), $message); - } - - public static function assertBrowserHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void - { - self::assertThat(self::getClient(), new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain), $message); - } - - public static function assertBrowserNotHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void - { - self::assertThat(self::getClient(), new LogicalNot(new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain)), $message); - } - - public static function assertBrowserCookieValueSame(string $name, string $expectedValue, bool $raw = false, string $path = '/', string $domain = null, string $message = ''): void - { - self::assertThat(self::getClient(), LogicalAnd::fromConstraints( - new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain), - new BrowserKitConstraint\BrowserCookieValueSame($name, $expectedValue, $raw, $path, $domain) - ), $message); - } - - public static function assertRequestAttributeValueSame(string $name, string $expectedValue, string $message = ''): void - { - self::assertThat(self::getRequest(), new ResponseConstraint\RequestAttributeValueSame($name, $expectedValue), $message); - } - - public static function assertRouteSame($expectedRoute, array $parameters = [], string $message = ''): void - { - $constraint = new ResponseConstraint\RequestAttributeValueSame('_route', $expectedRoute); - $constraints = []; - foreach ($parameters as $key => $value) { - $constraints[] = new ResponseConstraint\RequestAttributeValueSame($key, $value); - } - if ($constraints) { - $constraint = LogicalAnd::fromConstraints($constraint, ...$constraints); - } - - self::assertThat(self::getRequest(), $constraint, $message); - } - - private static function getClient(AbstractBrowser $newClient = null): ?AbstractBrowser - { - static $client; - - if (0 < \func_num_args()) { - return $client = $newClient; - } - - if (!$client instanceof AbstractBrowser) { - static::fail(sprintf('A client must be set to make assertions on it. Did you forget to call "%s::createClient()"?', __CLASS__)); - } - - return $client; - } - - private static function getResponse(): Response - { - if (!$response = self::getClient()->getResponse()) { - static::fail('A client must have an HTTP Response to make assertions. Did you forget to make an HTTP request?'); - } - - return $response; - } - - private static function getRequest(): Request - { - if (!$request = self::getClient()->getRequest()) { - static::fail('A client must have an HTTP Request to make assertions. Did you forget to make an HTTP request?'); - } - - return $request; - } -} diff --git a/vendor/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php b/vendor/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php deleted file mode 100644 index 465c265..0000000 --- a/vendor/symfony/framework-bundle/Test/DomCrawlerAssertionsTrait.php +++ /dev/null @@ -1,94 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Test; - -use PHPUnit\Framework\Constraint\LogicalAnd; -use PHPUnit\Framework\Constraint\LogicalNot; -use Symfony\Component\DomCrawler\Crawler; -use Symfony\Component\DomCrawler\Test\Constraint as DomCrawlerConstraint; - -/** - * Ideas borrowed from Laravel Dusk's assertions. - * - * @see https://laravel.com/docs/5.7/dusk#available-assertions - */ -trait DomCrawlerAssertionsTrait -{ - public static function assertSelectorExists(string $selector, string $message = ''): void - { - self::assertThat(self::getCrawler(), new DomCrawlerConstraint\CrawlerSelectorExists($selector), $message); - } - - public static function assertSelectorNotExists(string $selector, string $message = ''): void - { - self::assertThat(self::getCrawler(), new LogicalNot(new DomCrawlerConstraint\CrawlerSelectorExists($selector)), $message); - } - - public static function assertSelectorTextContains(string $selector, string $text, string $message = ''): void - { - self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( - new DomCrawlerConstraint\CrawlerSelectorExists($selector), - new DomCrawlerConstraint\CrawlerSelectorTextContains($selector, $text) - ), $message); - } - - public static function assertSelectorTextSame(string $selector, string $text, string $message = ''): void - { - self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( - new DomCrawlerConstraint\CrawlerSelectorExists($selector), - new DomCrawlerConstraint\CrawlerSelectorTextSame($selector, $text) - ), $message); - } - - public static function assertSelectorTextNotContains(string $selector, string $text, string $message = ''): void - { - self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( - new DomCrawlerConstraint\CrawlerSelectorExists($selector), - new LogicalNot(new DomCrawlerConstraint\CrawlerSelectorTextContains($selector, $text)) - ), $message); - } - - public static function assertPageTitleSame(string $expectedTitle, string $message = ''): void - { - self::assertSelectorTextSame('title', $expectedTitle, $message); - } - - public static function assertPageTitleContains(string $expectedTitle, string $message = ''): void - { - self::assertSelectorTextContains('title', $expectedTitle, $message); - } - - public static function assertInputValueSame(string $fieldName, string $expectedValue, string $message = ''): void - { - self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( - new DomCrawlerConstraint\CrawlerSelectorExists("input[name=\"$fieldName\"]"), - new DomCrawlerConstraint\CrawlerSelectorAttributeValueSame("input[name=\"$fieldName\"]", 'value', $expectedValue) - ), $message); - } - - public static function assertInputValueNotSame(string $fieldName, string $expectedValue, string $message = ''): void - { - self::assertThat(self::getCrawler(), LogicalAnd::fromConstraints( - new DomCrawlerConstraint\CrawlerSelectorExists("input[name=\"$fieldName\"]"), - new LogicalNot(new DomCrawlerConstraint\CrawlerSelectorAttributeValueSame("input[name=\"$fieldName\"]", 'value', $expectedValue)) - ), $message); - } - - private static function getCrawler(): Crawler - { - if (!$crawler = self::getClient()->getCrawler()) { - static::fail('A client must have a crawler to make assertions. Did you forget to make an HTTP request?'); - } - - return $crawler; - } -} diff --git a/vendor/symfony/framework-bundle/Test/KernelTestCase.php b/vendor/symfony/framework-bundle/Test/KernelTestCase.php deleted file mode 100644 index 478b398..0000000 --- a/vendor/symfony/framework-bundle/Test/KernelTestCase.php +++ /dev/null @@ -1,141 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Test; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * KernelTestCase is the base class for tests needing a Kernel. - * - * @author Fabien Potencier - */ -abstract class KernelTestCase extends TestCase -{ - protected static $class; - - /** - * @var KernelInterface - */ - protected static $kernel; - - /** - * @var ContainerInterface - */ - protected static $container; - - protected static $booted = false; - - private static $kernelContainer; - - protected function tearDown(): void - { - static::ensureKernelShutdown(); - static::$kernel = null; - } - - /** - * @return string The Kernel class name - * - * @throws \RuntimeException - * @throws \LogicException - */ - protected static function getKernelClass() - { - if (!isset($_SERVER['KERNEL_CLASS']) && !isset($_ENV['KERNEL_CLASS'])) { - throw new \LogicException(sprintf('You must set the KERNEL_CLASS environment variable to the fully-qualified class name of your Kernel in phpunit.xml / phpunit.xml.dist or override the %1$s::createKernel() or %1$s::getKernelClass() method.', static::class)); - } - - if (!class_exists($class = $_ENV['KERNEL_CLASS'] ?? $_SERVER['KERNEL_CLASS'])) { - throw new \RuntimeException(sprintf('Class "%s" doesn\'t exist or cannot be autoloaded. Check that the KERNEL_CLASS value in phpunit.xml matches the fully-qualified class name of your Kernel or override the %s::createKernel() method.', $class, static::class)); - } - - return $class; - } - - /** - * Boots the Kernel for this test. - * - * @return KernelInterface A KernelInterface instance - */ - protected static function bootKernel(array $options = []) - { - static::ensureKernelShutdown(); - - static::$kernel = static::createKernel($options); - static::$kernel->boot(); - static::$booted = true; - - self::$kernelContainer = $container = static::$kernel->getContainer(); - static::$container = $container->has('test.service_container') ? $container->get('test.service_container') : $container; - - return static::$kernel; - } - - /** - * Creates a Kernel. - * - * Available options: - * - * * environment - * * debug - * - * @return KernelInterface A KernelInterface instance - */ - protected static function createKernel(array $options = []) - { - if (null === static::$class) { - static::$class = static::getKernelClass(); - } - - if (isset($options['environment'])) { - $env = $options['environment']; - } elseif (isset($_ENV['APP_ENV'])) { - $env = $_ENV['APP_ENV']; - } elseif (isset($_SERVER['APP_ENV'])) { - $env = $_SERVER['APP_ENV']; - } else { - $env = 'test'; - } - - if (isset($options['debug'])) { - $debug = $options['debug']; - } elseif (isset($_ENV['APP_DEBUG'])) { - $debug = $_ENV['APP_DEBUG']; - } elseif (isset($_SERVER['APP_DEBUG'])) { - $debug = $_SERVER['APP_DEBUG']; - } else { - $debug = true; - } - - return new static::$class($env, $debug); - } - - /** - * Shuts the kernel down if it was used in the test - called by the tearDown method by default. - */ - protected static function ensureKernelShutdown() - { - if (null !== static::$kernel) { - static::$kernel->shutdown(); - static::$booted = false; - } - - if (self::$kernelContainer instanceof ResetInterface) { - self::$kernelContainer->reset(); - } - - static::$container = self::$kernelContainer = null; - } -} diff --git a/vendor/symfony/framework-bundle/Test/MailerAssertionsTrait.php b/vendor/symfony/framework-bundle/Test/MailerAssertionsTrait.php deleted file mode 100644 index 15446a8..0000000 --- a/vendor/symfony/framework-bundle/Test/MailerAssertionsTrait.php +++ /dev/null @@ -1,131 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Test; - -use PHPUnit\Framework\Constraint\LogicalNot; -use Symfony\Component\Mailer\Event\MessageEvent; -use Symfony\Component\Mailer\Event\MessageEvents; -use Symfony\Component\Mailer\Test\Constraint as MailerConstraint; -use Symfony\Component\Mime\RawMessage; -use Symfony\Component\Mime\Test\Constraint as MimeConstraint; - -trait MailerAssertionsTrait -{ - public static function assertEmailCount(int $count, string $transport = null, string $message = ''): void - { - self::assertThat(self::getMessageMailerEvents(), new MailerConstraint\EmailCount($count, $transport), $message); - } - - public static function assertQueuedEmailCount(int $count, string $transport = null, string $message = ''): void - { - self::assertThat(self::getMessageMailerEvents(), new MailerConstraint\EmailCount($count, $transport, true), $message); - } - - public static function assertEmailIsQueued(MessageEvent $event, string $message = ''): void - { - self::assertThat($event, new MailerConstraint\EmailIsQueued(), $message); - } - - public static function assertEmailIsNotQueued(MessageEvent $event, string $message = ''): void - { - self::assertThat($event, new LogicalNot(new MailerConstraint\EmailIsQueued()), $message); - } - - public static function assertEmailAttachmentCount(RawMessage $email, int $count, string $message = ''): void - { - self::assertThat($email, new MimeConstraint\EmailAttachmentCount($count), $message); - } - - public static function assertEmailTextBodyContains(RawMessage $email, string $text, string $message = ''): void - { - self::assertThat($email, new MimeConstraint\EmailTextBodyContains($text), $message); - } - - public static function assertEmailTextBodyNotContains(RawMessage $email, string $text, string $message = ''): void - { - self::assertThat($email, new LogicalNot(new MimeConstraint\EmailTextBodyContains($text)), $message); - } - - public static function assertEmailHtmlBodyContains(RawMessage $email, string $text, string $message = ''): void - { - self::assertThat($email, new MimeConstraint\EmailHtmlBodyContains($text), $message); - } - - public static function assertEmailHtmlBodyNotContains(RawMessage $email, string $text, string $message = ''): void - { - self::assertThat($email, new LogicalNot(new MimeConstraint\EmailHtmlBodyContains($text)), $message); - } - - public static function assertEmailHasHeader(RawMessage $email, string $headerName, string $message = ''): void - { - self::assertThat($email, new MimeConstraint\EmailHasHeader($headerName), $message); - } - - public static function assertEmailNotHasHeader(RawMessage $email, string $headerName, string $message = ''): void - { - self::assertThat($email, new LogicalNot(new MimeConstraint\EmailHasHeader($headerName)), $message); - } - - public static function assertEmailHeaderSame(RawMessage $email, string $headerName, string $expectedValue, string $message = ''): void - { - self::assertThat($email, new MimeConstraint\EmailHeaderSame($headerName, $expectedValue), $message); - } - - public static function assertEmailHeaderNotSame(RawMessage $email, string $headerName, string $expectedValue, string $message = ''): void - { - self::assertThat($email, new LogicalNot(new MimeConstraint\EmailHeaderSame($headerName, $expectedValue)), $message); - } - - public static function assertEmailAddressContains(RawMessage $email, string $headerName, string $expectedValue, string $message = ''): void - { - self::assertThat($email, new MimeConstraint\EmailAddressContains($headerName, $expectedValue), $message); - } - - /** - * @return MessageEvents[] - */ - public static function getMailerEvents(string $transport = null): array - { - return self::getMessageMailerEvents()->getEvents($transport); - } - - public static function getMailerEvent(int $index = 0, string $transport = null): ?MessageEvent - { - return self::getMailerEvents($transport)[$index] ?? null; - } - - /** - * @return RawMessage[] - */ - public static function getMailerMessages(string $transport = null): array - { - return self::getMessageMailerEvents()->getMessages($transport); - } - - public static function getMailerMessage(int $index = 0, string $transport = null): ?RawMessage - { - return self::getMailerMessages($transport)[$index] ?? null; - } - - private static function getMessageMailerEvents(): MessageEvents - { - if (!self::getClient()->getRequest()) { - static::fail('Unable to make email assertions. Did you forget to make an HTTP request?'); - } - - if (!$logger = self::$container->get('mailer.logger_message_listener')) { - static::fail('A client must have Mailer enabled to make email assertions. Did you forget to require symfony/mailer?'); - } - - return $logger->getEvents(); - } -} diff --git a/vendor/symfony/framework-bundle/Test/TestContainer.php b/vendor/symfony/framework-bundle/Test/TestContainer.php deleted file mode 100644 index a0dd847..0000000 --- a/vendor/symfony/framework-bundle/Test/TestContainer.php +++ /dev/null @@ -1,152 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Test; - -use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * @author Nicolas Grekas - * - * @internal - */ -class TestContainer extends Container -{ - private $kernel; - private $privateServicesLocatorId; - - public function __construct(KernelInterface $kernel, string $privateServicesLocatorId) - { - $this->kernel = $kernel; - $this->privateServicesLocatorId = $privateServicesLocatorId; - } - - /** - * {@inheritdoc} - */ - public function compile() - { - $this->getPublicContainer()->compile(); - } - - /** - * {@inheritdoc} - */ - public function isCompiled(): bool - { - return $this->getPublicContainer()->isCompiled(); - } - - /** - * {@inheritdoc} - */ - public function getParameterBag(): ParameterBagInterface - { - return $this->getPublicContainer()->getParameterBag(); - } - - /** - * {@inheritdoc} - */ - public function getParameter(string $name) - { - return $this->getPublicContainer()->getParameter($name); - } - - /** - * {@inheritdoc} - */ - public function hasParameter(string $name): bool - { - return $this->getPublicContainer()->hasParameter($name); - } - - /** - * {@inheritdoc} - */ - public function setParameter(string $name, $value) - { - $this->getPublicContainer()->setParameter($name, $value); - } - - /** - * {@inheritdoc} - */ - public function set(string $id, $service) - { - $this->getPublicContainer()->set($id, $service); - } - - /** - * {@inheritdoc} - */ - public function has($id): bool - { - return $this->getPublicContainer()->has($id) || $this->getPrivateContainer()->has($id); - } - - /** - * {@inheritdoc} - */ - public function get($id, int $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERENCE */ 1): ?object - { - return $this->getPrivateContainer()->has($id) ? $this->getPrivateContainer()->get($id) : $this->getPublicContainer()->get($id, $invalidBehavior); - } - - /** - * {@inheritdoc} - */ - public function initialized(string $id): bool - { - return $this->getPublicContainer()->initialized($id); - } - - /** - * {@inheritdoc} - */ - public function reset() - { - // ignore the call - } - - /** - * {@inheritdoc} - */ - public function getServiceIds(): array - { - return $this->getPublicContainer()->getServiceIds(); - } - - /** - * {@inheritdoc} - */ - public function getRemovedIds(): array - { - return $this->getPublicContainer()->getRemovedIds(); - } - - private function getPublicContainer(): Container - { - if (null === $container = $this->kernel->getContainer()) { - throw new \LogicException('Cannot access the container on a non-booted kernel. Did you forget to boot it?'); - } - - return $container; - } - - private function getPrivateContainer(): ContainerInterface - { - return $this->getPublicContainer()->get($this->privateServicesLocatorId); - } -} diff --git a/vendor/symfony/framework-bundle/Test/WebTestAssertionsTrait.php b/vendor/symfony/framework-bundle/Test/WebTestAssertionsTrait.php deleted file mode 100644 index 0f1742e..0000000 --- a/vendor/symfony/framework-bundle/Test/WebTestAssertionsTrait.php +++ /dev/null @@ -1,18 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Test; - -trait WebTestAssertionsTrait -{ - use BrowserKitAssertionsTrait; - use DomCrawlerAssertionsTrait; -} diff --git a/vendor/symfony/framework-bundle/Test/WebTestCase.php b/vendor/symfony/framework-bundle/Test/WebTestCase.php deleted file mode 100644 index 4935dd8..0000000 --- a/vendor/symfony/framework-bundle/Test/WebTestCase.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Test; - -use Symfony\Bundle\FrameworkBundle\KernelBrowser; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; - -/** - * WebTestCase is the base class for functional tests. - * - * @author Fabien Potencier - */ -abstract class WebTestCase extends KernelTestCase -{ - use WebTestAssertionsTrait; - use MailerAssertionsTrait; - - protected function tearDown(): void - { - parent::tearDown(); - self::getClient(null); - } - - /** - * Creates a KernelBrowser. - * - * @param array $options An array of options to pass to the createKernel method - * @param array $server An array of server parameters - * - * @return KernelBrowser A KernelBrowser instance - */ - protected static function createClient(array $options = [], array $server = []) - { - if (static::$booted) { - throw new \LogicException(sprintf('Booting the kernel before calling %s() is not supported, the kernel should only be booted once.', __METHOD__)); - } - - $kernel = static::bootKernel($options); - - try { - $client = $kernel->getContainer()->get('test.client'); - } catch (ServiceNotFoundException $e) { - if (class_exists(KernelBrowser::class)) { - throw new \LogicException('You cannot create the client used in functional tests if the "framework.test" config is not set to true.'); - } - throw new \LogicException('You cannot create the client used in functional tests if the BrowserKit component is not available. Try running "composer require symfony/browser-kit"'); - } - - $client->setServerParameters($server); - - return self::getClient($client); - } -} diff --git a/vendor/symfony/framework-bundle/Translation/Translator.php b/vendor/symfony/framework-bundle/Translation/Translator.php deleted file mode 100644 index da4384d..0000000 --- a/vendor/symfony/framework-bundle/Translation/Translator.php +++ /dev/null @@ -1,175 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Translation; - -use Psr\Container\ContainerInterface; -use Symfony\Component\Config\Resource\DirectoryResource; -use Symfony\Component\Config\Resource\FileExistenceResource; -use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; -use Symfony\Component\Translation\Exception\InvalidArgumentException; -use Symfony\Component\Translation\Formatter\MessageFormatterInterface; -use Symfony\Component\Translation\Translator as BaseTranslator; - -/** - * Translator. - * - * @author Fabien Potencier - */ -class Translator extends BaseTranslator implements WarmableInterface -{ - protected $container; - protected $loaderIds; - - protected $options = [ - 'cache_dir' => null, - 'debug' => false, - 'resource_files' => [], - 'scanned_directories' => [], - 'cache_vary' => [], - ]; - - /** - * @var array - */ - private $resourceLocales; - - /** - * Holds parameters from addResource() calls so we can defer the actual - * parent::addResource() calls until initialize() is executed. - * - * @var array - */ - private $resources = []; - - private $resourceFiles; - - /** - * @var string[] - */ - private $scannedDirectories; - - /** - * Constructor. - * - * Available options: - * - * * cache_dir: The cache directory (or null to disable caching) - * * debug: Whether to enable debugging or not (false by default) - * * resource_files: List of translation resources available grouped by locale. - * * cache_vary: An array of data that is serialized to generate the cached catalogue name. - * - * @throws InvalidArgumentException - */ - public function __construct(ContainerInterface $container, MessageFormatterInterface $formatter, string $defaultLocale, array $loaderIds = [], array $options = []) - { - $this->container = $container; - $this->loaderIds = $loaderIds; - - // check option names - if ($diff = array_diff(array_keys($options), array_keys($this->options))) { - throw new InvalidArgumentException(sprintf('The Translator does not support the following options: \'%s\'.', implode('\', \'', $diff))); - } - - $this->options = array_merge($this->options, $options); - $this->resourceLocales = array_keys($this->options['resource_files']); - $this->resourceFiles = $this->options['resource_files']; - $this->scannedDirectories = $this->options['scanned_directories']; - - parent::__construct($defaultLocale, $formatter, $this->options['cache_dir'], $this->options['debug'], $this->options['cache_vary']); - } - - /** - * {@inheritdoc} - */ - public function warmUp(string $cacheDir) - { - // skip warmUp when translator doesn't use cache - if (null === $this->options['cache_dir']) { - return; - } - - $locales = array_merge($this->getFallbackLocales(), [$this->getLocale()], $this->resourceLocales); - foreach (array_unique($locales) as $locale) { - // reset catalogue in case it's already loaded during the dump of the other locales. - if (isset($this->catalogues[$locale])) { - unset($this->catalogues[$locale]); - } - - $this->loadCatalogue($locale); - } - } - - public function addResource(string $format, $resource, string $locale, string $domain = null) - { - if ($this->resourceFiles) { - $this->addResourceFiles(); - } - $this->resources[] = [$format, $resource, $locale, $domain]; - } - - /** - * {@inheritdoc} - */ - protected function initializeCatalogue(string $locale) - { - $this->initialize(); - parent::initializeCatalogue($locale); - } - - /** - * @internal - */ - protected function doLoadCatalogue(string $locale): void - { - parent::doLoadCatalogue($locale); - - foreach ($this->scannedDirectories as $directory) { - $resourceClass = file_exists($directory) ? DirectoryResource::class : FileExistenceResource::class; - $this->catalogues[$locale]->addResource(new $resourceClass($directory)); - } - } - - protected function initialize() - { - if ($this->resourceFiles) { - $this->addResourceFiles(); - } - foreach ($this->resources as $key => $params) { - list($format, $resource, $locale, $domain) = $params; - parent::addResource($format, $resource, $locale, $domain); - } - $this->resources = []; - - foreach ($this->loaderIds as $id => $aliases) { - foreach ($aliases as $alias) { - $this->addLoader($alias, $this->container->get($id)); - } - } - } - - private function addResourceFiles() - { - $filesByLocale = $this->resourceFiles; - $this->resourceFiles = []; - - foreach ($filesByLocale as $locale => $files) { - foreach ($files as $key => $file) { - // filename is domain.locale.format - $fileNameParts = explode('.', basename($file)); - $format = array_pop($fileNameParts); - $locale = array_pop($fileNameParts); - $domain = implode('.', $fileNameParts); - $this->addResource($format, $file, $locale, $domain); - } - } - } -} diff --git a/vendor/symfony/framework-bundle/composer.json b/vendor/symfony/framework-bundle/composer.json deleted file mode 100644 index 8bcf9e8..0000000 --- a/vendor/symfony/framework-bundle/composer.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - "name": "symfony/framework-bundle", - "type": "symfony-bundle", - "description": "Symfony FrameworkBundle", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "ext-xml": "*", - "symfony/cache": "^4.4|^5.0", - "symfony/config": "^5.0", - "symfony/dependency-injection": "^5.0.1", - "symfony/error-handler": "^4.4.1|^5.0.1", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/http-kernel": "^5.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/filesystem": "^4.4|^5.0", - "symfony/finder": "^4.4|^5.0", - "symfony/routing": "^5.0" - }, - "require-dev": { - "doctrine/annotations": "~1.7", - "doctrine/cache": "~1.0", - "symfony/asset": "^4.4|^5.0", - "symfony/browser-kit": "^4.4|^5.0", - "symfony/console": "^4.4|^5.0", - "symfony/css-selector": "^4.4|^5.0", - "symfony/dom-crawler": "^4.4|^5.0", - "symfony/dotenv": "^4.4|^5.0", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/form": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/http-client": "^4.4|^5.0", - "symfony/lock": "^4.4|^5.0", - "symfony/mailer": "^4.4|^5.0", - "symfony/messenger": "^4.4|^5.0", - "symfony/mime": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0", - "symfony/security-csrf": "^4.4|^5.0", - "symfony/security-http": "^4.4|^5.0", - "symfony/serializer": "^4.4|^5.0", - "symfony/stopwatch": "^4.4|^5.0", - "symfony/string": "~5.0.0", - "symfony/translation": "^5.0", - "symfony/twig-bundle": "^4.4|^5.0", - "symfony/validator": "^4.4|^5.0", - "symfony/workflow": "^4.4|^5.0", - "symfony/yaml": "^4.4|^5.0", - "symfony/property-info": "^4.4|^5.0", - "symfony/web-link": "^4.4|^5.0", - "phpdocumentor/reflection-docblock": "^3.0|^4.0", - "paragonie/sodium_compat": "^1.8", - "twig/twig": "^2.10|^3.0" - }, - "conflict": { - "doctrine/persistence": "<1.3", - "phpdocumentor/reflection-docblock": "<3.0", - "phpdocumentor/type-resolver": "<0.2.1", - "phpunit/phpunit": "<5.4.3", - "symfony/asset": "<4.4", - "symfony/browser-kit": "<4.4", - "symfony/console": "<4.4", - "symfony/dotenv": "<4.4", - "symfony/dom-crawler": "<4.4", - "symfony/http-client": "<4.4", - "symfony/form": "<4.4", - "symfony/lock": "<4.4", - "symfony/mailer": "<4.4", - "symfony/messenger": "<4.4", - "symfony/mime": "<4.4", - "symfony/property-info": "<4.4", - "symfony/serializer": "<4.4", - "symfony/stopwatch": "<4.4", - "symfony/translation": "<5.0", - "symfony/twig-bridge": "<4.4", - "symfony/twig-bundle": "<4.4", - "symfony/validator": "<4.4", - "symfony/web-profiler-bundle": "<4.4", - "symfony/workflow": "<4.4" - }, - "suggest": { - "ext-apcu": "For best performance of the system caches", - "symfony/console": "For using the console commands", - "symfony/form": "For using forms", - "symfony/serializer": "For using the serializer service", - "symfony/validator": "For using validation", - "symfony/yaml": "For using the debug:config and lint:yaml commands", - "symfony/property-info": "For using the property_info service", - "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering" - }, - "autoload": { - "psr-4": { "Symfony\\Bundle\\FrameworkBundle\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/http-foundation/.gitattributes b/vendor/symfony/http-foundation/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/http-foundation/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/http-foundation/AcceptHeader.php b/vendor/symfony/http-foundation/AcceptHeader.php deleted file mode 100644 index 90f9f47..0000000 --- a/vendor/symfony/http-foundation/AcceptHeader.php +++ /dev/null @@ -1,165 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Represents an Accept-* header. - * - * An accept header is compound with a list of items, - * sorted by descending quality. - * - * @author Jean-François Simon - */ -class AcceptHeader -{ - /** - * @var AcceptHeaderItem[] - */ - private $items = []; - - /** - * @var bool - */ - private $sorted = true; - - /** - * @param AcceptHeaderItem[] $items - */ - public function __construct(array $items) - { - foreach ($items as $item) { - $this->add($item); - } - } - - /** - * Builds an AcceptHeader instance from a string. - * - * @return self - */ - public static function fromString(?string $headerValue) - { - $index = 0; - - $parts = HeaderUtils::split($headerValue ?? '', ',;='); - - return new self(array_map(function ($subParts) use (&$index) { - $part = array_shift($subParts); - $attributes = HeaderUtils::combine($subParts); - - $item = new AcceptHeaderItem($part[0], $attributes); - $item->setIndex($index++); - - return $item; - }, $parts)); - } - - /** - * Returns header value's string representation. - * - * @return string - */ - public function __toString() - { - return implode(',', $this->items); - } - - /** - * Tests if header has given value. - * - * @return bool - */ - public function has(string $value) - { - return isset($this->items[$value]); - } - - /** - * Returns given value's item, if exists. - * - * @return AcceptHeaderItem|null - */ - public function get(string $value) - { - return $this->items[$value] ?? $this->items[explode('/', $value)[0].'/*'] ?? $this->items['*/*'] ?? $this->items['*'] ?? null; - } - - /** - * Adds an item. - * - * @return $this - */ - public function add(AcceptHeaderItem $item) - { - $this->items[$item->getValue()] = $item; - $this->sorted = false; - - return $this; - } - - /** - * Returns all items. - * - * @return AcceptHeaderItem[] - */ - public function all() - { - $this->sort(); - - return $this->items; - } - - /** - * Filters items on their value using given regex. - * - * @return self - */ - public function filter(string $pattern) - { - return new self(array_filter($this->items, function (AcceptHeaderItem $item) use ($pattern) { - return preg_match($pattern, $item->getValue()); - })); - } - - /** - * Returns first item. - * - * @return AcceptHeaderItem|null - */ - public function first() - { - $this->sort(); - - return !empty($this->items) ? reset($this->items) : null; - } - - /** - * Sorts items by descending quality. - */ - private function sort(): void - { - if (!$this->sorted) { - uasort($this->items, function (AcceptHeaderItem $a, AcceptHeaderItem $b) { - $qA = $a->getQuality(); - $qB = $b->getQuality(); - - if ($qA === $qB) { - return $a->getIndex() > $b->getIndex() ? 1 : -1; - } - - return $qA > $qB ? -1 : 1; - }); - - $this->sorted = true; - } - } -} diff --git a/vendor/symfony/http-foundation/AcceptHeaderItem.php b/vendor/symfony/http-foundation/AcceptHeaderItem.php deleted file mode 100644 index bc4014e..0000000 --- a/vendor/symfony/http-foundation/AcceptHeaderItem.php +++ /dev/null @@ -1,177 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Represents an Accept-* header item. - * - * @author Jean-François Simon - */ -class AcceptHeaderItem -{ - private $value; - private $quality = 1.0; - private $index = 0; - private $attributes = []; - - public function __construct(string $value, array $attributes = []) - { - $this->value = $value; - foreach ($attributes as $name => $value) { - $this->setAttribute($name, $value); - } - } - - /** - * Builds an AcceptHeaderInstance instance from a string. - * - * @return self - */ - public static function fromString(?string $itemValue) - { - $parts = HeaderUtils::split($itemValue ?? '', ';='); - - $part = array_shift($parts); - $attributes = HeaderUtils::combine($parts); - - return new self($part[0], $attributes); - } - - /** - * Returns header value's string representation. - * - * @return string - */ - public function __toString() - { - $string = $this->value.($this->quality < 1 ? ';q='.$this->quality : ''); - if (\count($this->attributes) > 0) { - $string .= '; '.HeaderUtils::toString($this->attributes, ';'); - } - - return $string; - } - - /** - * Set the item value. - * - * @return $this - */ - public function setValue(string $value) - { - $this->value = $value; - - return $this; - } - - /** - * Returns the item value. - * - * @return string - */ - public function getValue() - { - return $this->value; - } - - /** - * Set the item quality. - * - * @return $this - */ - public function setQuality(float $quality) - { - $this->quality = $quality; - - return $this; - } - - /** - * Returns the item quality. - * - * @return float - */ - public function getQuality() - { - return $this->quality; - } - - /** - * Set the item index. - * - * @return $this - */ - public function setIndex(int $index) - { - $this->index = $index; - - return $this; - } - - /** - * Returns the item index. - * - * @return int - */ - public function getIndex() - { - return $this->index; - } - - /** - * Tests if an attribute exists. - * - * @return bool - */ - public function hasAttribute(string $name) - { - return isset($this->attributes[$name]); - } - - /** - * Returns an attribute by its name. - * - * @param mixed $default - * - * @return mixed - */ - public function getAttribute(string $name, $default = null) - { - return isset($this->attributes[$name]) ? $this->attributes[$name] : $default; - } - - /** - * Returns all attributes. - * - * @return array - */ - public function getAttributes() - { - return $this->attributes; - } - - /** - * Set an attribute. - * - * @return $this - */ - public function setAttribute(string $name, string $value) - { - if ('q' === $name) { - $this->quality = (float) $value; - } else { - $this->attributes[$name] = $value; - } - - return $this; - } -} diff --git a/vendor/symfony/http-foundation/BinaryFileResponse.php b/vendor/symfony/http-foundation/BinaryFileResponse.php deleted file mode 100644 index d37cbd2..0000000 --- a/vendor/symfony/http-foundation/BinaryFileResponse.php +++ /dev/null @@ -1,354 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\File\Exception\FileException; -use Symfony\Component\HttpFoundation\File\File; - -/** - * BinaryFileResponse represents an HTTP response delivering a file. - * - * @author Niklas Fiekas - * @author stealth35 - * @author Igor Wiedler - * @author Jordan Alliot - * @author Sergey Linnik - */ -class BinaryFileResponse extends Response -{ - protected static $trustXSendfileTypeHeader = false; - - /** - * @var File - */ - protected $file; - protected $offset = 0; - protected $maxlen = -1; - protected $deleteFileAfterSend = false; - - /** - * @param \SplFileInfo|string $file The file to stream - * @param int $status The response status code - * @param array $headers An array of response headers - * @param bool $public Files are public by default - * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename - * @param bool $autoEtag Whether the ETag header should be automatically set - * @param bool $autoLastModified Whether the Last-Modified header should be automatically set - */ - public function __construct($file, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) - { - parent::__construct(null, $status, $headers); - - $this->setFile($file, $contentDisposition, $autoEtag, $autoLastModified); - - if ($public) { - $this->setPublic(); - } - } - - /** - * @param \SplFileInfo|string $file The file to stream - * @param int $status The response status code - * @param array $headers An array of response headers - * @param bool $public Files are public by default - * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename - * @param bool $autoEtag Whether the ETag header should be automatically set - * @param bool $autoLastModified Whether the Last-Modified header should be automatically set - * - * @return static - */ - public static function create($file = null, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) - { - return new static($file, $status, $headers, $public, $contentDisposition, $autoEtag, $autoLastModified); - } - - /** - * Sets the file to stream. - * - * @param \SplFileInfo|string $file The file to stream - * - * @return $this - * - * @throws FileException - */ - public function setFile($file, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) - { - if (!$file instanceof File) { - if ($file instanceof \SplFileInfo) { - $file = new File($file->getPathname()); - } else { - $file = new File((string) $file); - } - } - - if (!$file->isReadable()) { - throw new FileException('File must be readable.'); - } - - $this->file = $file; - - if ($autoEtag) { - $this->setAutoEtag(); - } - - if ($autoLastModified) { - $this->setAutoLastModified(); - } - - if ($contentDisposition) { - $this->setContentDisposition($contentDisposition); - } - - return $this; - } - - /** - * Gets the file. - * - * @return File The file to stream - */ - public function getFile() - { - return $this->file; - } - - /** - * Automatically sets the Last-Modified header according the file modification date. - */ - public function setAutoLastModified() - { - $this->setLastModified(\DateTime::createFromFormat('U', $this->file->getMTime())); - - return $this; - } - - /** - * Automatically sets the ETag header according to the checksum of the file. - */ - public function setAutoEtag() - { - $this->setEtag(base64_encode(hash_file('sha256', $this->file->getPathname(), true))); - - return $this; - } - - /** - * Sets the Content-Disposition header with the given filename. - * - * @param string $disposition ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT - * @param string $filename Optionally use this UTF-8 encoded filename instead of the real name of the file - * @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename - * - * @return $this - */ - public function setContentDisposition(string $disposition, string $filename = '', string $filenameFallback = '') - { - if ('' === $filename) { - $filename = $this->file->getFilename(); - } - - if ('' === $filenameFallback && (!preg_match('/^[\x20-\x7e]*$/', $filename) || false !== strpos($filename, '%'))) { - $encoding = mb_detect_encoding($filename, null, true) ?: '8bit'; - - for ($i = 0, $filenameLength = mb_strlen($filename, $encoding); $i < $filenameLength; ++$i) { - $char = mb_substr($filename, $i, 1, $encoding); - - if ('%' === $char || \ord($char) < 32 || \ord($char) > 126) { - $filenameFallback .= '_'; - } else { - $filenameFallback .= $char; - } - } - } - - $dispositionHeader = $this->headers->makeDisposition($disposition, $filename, $filenameFallback); - $this->headers->set('Content-Disposition', $dispositionHeader); - - return $this; - } - - /** - * {@inheritdoc} - */ - public function prepare(Request $request) - { - if (!$this->headers->has('Content-Type')) { - $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream'); - } - - if ('HTTP/1.0' !== $request->server->get('SERVER_PROTOCOL')) { - $this->setProtocolVersion('1.1'); - } - - $this->ensureIEOverSSLCompatibility($request); - - $this->offset = 0; - $this->maxlen = -1; - - if (false === $fileSize = $this->file->getSize()) { - return $this; - } - $this->headers->set('Content-Length', $fileSize); - - if (!$this->headers->has('Accept-Ranges')) { - // Only accept ranges on safe HTTP methods - $this->headers->set('Accept-Ranges', $request->isMethodSafe() ? 'bytes' : 'none'); - } - - if (self::$trustXSendfileTypeHeader && $request->headers->has('X-Sendfile-Type')) { - // Use X-Sendfile, do not send any content. - $type = $request->headers->get('X-Sendfile-Type'); - $path = $this->file->getRealPath(); - // Fall back to scheme://path for stream wrapped locations. - if (false === $path) { - $path = $this->file->getPathname(); - } - if ('x-accel-redirect' === strtolower($type)) { - // Do X-Accel-Mapping substitutions. - // @link http://wiki.nginx.org/X-accel#X-Accel-Redirect - $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping', ''), ',='); - foreach ($parts as $part) { - list($pathPrefix, $location) = $part; - if (substr($path, 0, \strlen($pathPrefix)) === $pathPrefix) { - $path = $location.substr($path, \strlen($pathPrefix)); - // Only set X-Accel-Redirect header if a valid URI can be produced - // as nginx does not serve arbitrary file paths. - $this->headers->set($type, $path); - $this->maxlen = 0; - break; - } - } - } else { - $this->headers->set($type, $path); - $this->maxlen = 0; - } - } elseif ($request->headers->has('Range')) { - // Process the range headers. - if (!$request->headers->has('If-Range') || $this->hasValidIfRangeHeader($request->headers->get('If-Range'))) { - $range = $request->headers->get('Range'); - - list($start, $end) = explode('-', substr($range, 6), 2) + [0]; - - $end = ('' === $end) ? $fileSize - 1 : (int) $end; - - if ('' === $start) { - $start = $fileSize - $end; - $end = $fileSize - 1; - } else { - $start = (int) $start; - } - - if ($start <= $end) { - if ($start < 0 || $end > $fileSize - 1) { - $this->setStatusCode(416); - $this->headers->set('Content-Range', sprintf('bytes */%s', $fileSize)); - } elseif (0 !== $start || $end !== $fileSize - 1) { - $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1; - $this->offset = $start; - - $this->setStatusCode(206); - $this->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $start, $end, $fileSize)); - $this->headers->set('Content-Length', $end - $start + 1); - } - } - } - } - - return $this; - } - - private function hasValidIfRangeHeader(?string $header): bool - { - if ($this->getEtag() === $header) { - return true; - } - - if (null === $lastModified = $this->getLastModified()) { - return false; - } - - return $lastModified->format('D, d M Y H:i:s').' GMT' === $header; - } - - /** - * Sends the file. - * - * {@inheritdoc} - */ - public function sendContent() - { - if (!$this->isSuccessful()) { - return parent::sendContent(); - } - - if (0 === $this->maxlen) { - return $this; - } - - $out = fopen('php://output', 'wb'); - $file = fopen($this->file->getPathname(), 'rb'); - - stream_copy_to_stream($file, $out, $this->maxlen, $this->offset); - - fclose($out); - fclose($file); - - if ($this->deleteFileAfterSend && file_exists($this->file->getPathname())) { - unlink($this->file->getPathname()); - } - - return $this; - } - - /** - * {@inheritdoc} - * - * @throws \LogicException when the content is not null - */ - public function setContent(?string $content) - { - if (null !== $content) { - throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.'); - } - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getContent() - { - return false; - } - - /** - * Trust X-Sendfile-Type header. - */ - public static function trustXSendfileTypeHeader() - { - self::$trustXSendfileTypeHeader = true; - } - - /** - * If this is set to true, the file will be unlinked after the request is sent - * Note: If the X-Sendfile header is used, the deleteFileAfterSend setting will not be used. - * - * @return $this - */ - public function deleteFileAfterSend(bool $shouldDelete = true) - { - $this->deleteFileAfterSend = $shouldDelete; - - return $this; - } -} diff --git a/vendor/symfony/http-foundation/CHANGELOG.md b/vendor/symfony/http-foundation/CHANGELOG.md deleted file mode 100644 index 0af7d00..0000000 --- a/vendor/symfony/http-foundation/CHANGELOG.md +++ /dev/null @@ -1,247 +0,0 @@ -CHANGELOG -========= - -5.0.0 ------ - - * made `Cookie` auto-secure and lax by default - * removed classes in the `MimeType` namespace, use the Symfony Mime component instead - * removed method `UploadedFile::getClientSize()` and the related constructor argument - * made `Request::getSession()` throw if the session has not been set before - * removed `Response::HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL` - * passing a null url when instantiating a `RedirectResponse` is not allowed - -4.4.0 ------ - - * passing arguments to `Request::isMethodSafe()` is deprecated. - * `ApacheRequest` is deprecated, use the `Request` class instead. - * passing a third argument to `HeaderBag::get()` is deprecated, use method `all()` instead - * [BC BREAK] `PdoSessionHandler` with MySQL changed the type of the lifetime column, - make sure to run `ALTER TABLE sessions MODIFY sess_lifetime INTEGER UNSIGNED NOT NULL` to - update your database. - * `PdoSessionHandler` now precalculates the expiry timestamp in the lifetime column, - make sure to run `CREATE INDEX EXPIRY ON sessions (sess_lifetime)` to update your database - to speed up garbage collection of expired sessions. - * added `SessionHandlerFactory` to create session handlers with a DSN - * added `IpUtils::anonymize()` to help with GDPR compliance. - -4.3.0 ------ - - * added PHPUnit constraints: `RequestAttributeValueSame`, `ResponseCookieValueSame`, `ResponseHasCookie`, - `ResponseHasHeader`, `ResponseHeaderSame`, `ResponseIsRedirected`, `ResponseIsSuccessful`, and `ResponseStatusCodeSame` - * deprecated `MimeTypeGuesserInterface` and `ExtensionGuesserInterface` in favor of `Symfony\Component\Mime\MimeTypesInterface`. - * deprecated `MimeType` and `MimeTypeExtensionGuesser` in favor of `Symfony\Component\Mime\MimeTypes`. - * deprecated `FileBinaryMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileBinaryMimeTypeGuesser`. - * deprecated `FileinfoMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileinfoMimeTypeGuesser`. - * added `UrlHelper` that allows to get an absolute URL and a relative path for a given path - -4.2.0 ------ - - * the default value of the "$secure" and "$samesite" arguments of Cookie's constructor - will respectively change from "false" to "null" and from "null" to "lax" in Symfony - 5.0, you should define their values explicitly or use "Cookie::create()" instead. - * added `matchPort()` in RequestMatcher - -4.1.3 ------ - - * [BC BREAK] Support for the IIS-only `X_ORIGINAL_URL` and `X_REWRITE_URL` - HTTP headers has been dropped for security reasons. - -4.1.0 ------ - - * Query string normalization uses `parse_str()` instead of custom parsing logic. - * Passing the file size to the constructor of the `UploadedFile` class is deprecated. - * The `getClientSize()` method of the `UploadedFile` class is deprecated. Use `getSize()` instead. - * added `RedisSessionHandler` to use Redis as a session storage - * The `get()` method of the `AcceptHeader` class now takes into account the - `*` and `*/*` default values (if they are present in the Accept HTTP header) - when looking for items. - * deprecated `Request::getSession()` when no session has been set. Use `Request::hasSession()` instead. - * added `CannotWriteFileException`, `ExtensionFileException`, `FormSizeFileException`, - `IniSizeFileException`, `NoFileException`, `NoTmpDirFileException`, `PartialFileException` to - handle failed `UploadedFile`. - * added `MigratingSessionHandler` for migrating between two session handlers without losing sessions - * added `HeaderUtils`. - -4.0.0 ------ - - * the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` - methods have been removed - * the `Request::HEADER_CLIENT_IP` constant has been removed, use - `Request::HEADER_X_FORWARDED_FOR` instead - * the `Request::HEADER_CLIENT_HOST` constant has been removed, use - `Request::HEADER_X_FORWARDED_HOST` instead - * the `Request::HEADER_CLIENT_PROTO` constant has been removed, use - `Request::HEADER_X_FORWARDED_PROTO` instead - * the `Request::HEADER_CLIENT_PORT` constant has been removed, use - `Request::HEADER_X_FORWARDED_PORT` instead - * checking for cacheable HTTP methods using the `Request::isMethodSafe()` - method (by not passing `false` as its argument) is not supported anymore and - throws a `\BadMethodCallException` - * the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes have been removed - * setting session save handlers that do not implement `\SessionHandlerInterface` in - `NativeSessionStorage::setSaveHandler()` is not supported anymore and throws a - `\TypeError` - -3.4.0 ------ - - * implemented PHP 7.0's `SessionUpdateTimestampHandlerInterface` with a new - `AbstractSessionHandler` base class and a new `StrictSessionHandler` wrapper - * deprecated the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes - * deprecated setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()` - * deprecated using `MongoDbSessionHandler` with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead - * deprecated `MemcacheSessionHandler`; use `MemcachedSessionHandler` instead - -3.3.0 ------ - - * the `Request::setTrustedProxies()` method takes a new `$trustedHeaderSet` argument, - see https://symfony.com/doc/current/deployment/proxies.html for more info, - * deprecated the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` methods, - * added `File\Stream`, to be passed to `BinaryFileResponse` when the size of the served file is unknown, - disabling `Range` and `Content-Length` handling, switching to chunked encoding instead - * added the `Cookie::fromString()` method that allows to create a cookie from a - raw header string - -3.1.0 ------ - - * Added support for creating `JsonResponse` with a string of JSON data - -3.0.0 ------ - - * The precedence of parameters returned from `Request::get()` changed from "GET, PATH, BODY" to "PATH, GET, BODY" - -2.8.0 ------ - - * Finding deep items in `ParameterBag::get()` is deprecated since version 2.8 and - will be removed in 3.0. - -2.6.0 ------ - - * PdoSessionHandler changes - - implemented different session locking strategies to prevent loss of data by concurrent access to the same session - - [BC BREAK] save session data in a binary column without base64_encode - - [BC BREAK] added lifetime column to the session table which allows to have different lifetimes for each session - - implemented lazy connections that are only opened when a session is used by either passing a dsn string - explicitly or falling back to session.save_path ini setting - - added a createTable method that initializes a correctly defined table depending on the database vendor - -2.5.0 ------ - - * added `JsonResponse::setEncodingOptions()` & `JsonResponse::getEncodingOptions()` for easier manipulation - of the options used while encoding data to JSON format. - -2.4.0 ------ - - * added RequestStack - * added Request::getEncodings() - * added accessors methods to session handlers - -2.3.0 ------ - - * added support for ranges of IPs in trusted proxies - * `UploadedFile::isValid` now returns false if the file was not uploaded via HTTP (in a non-test mode) - * Improved error-handling of `\Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler` - to ensure the supplied PDO handler throws Exceptions on error (as the class expects). Added related test cases - to verify that Exceptions are properly thrown when the PDO queries fail. - -2.2.0 ------ - - * fixed the Request::create() precedence (URI information always take precedence now) - * added Request::getTrustedProxies() - * deprecated Request::isProxyTrusted() - * [BC BREAK] JsonResponse does not turn a top level empty array to an object anymore, use an ArrayObject to enforce objects - * added a IpUtils class to check if an IP belongs to a CIDR - * added Request::getRealMethod() to get the "real" HTTP method (getMethod() returns the "intended" HTTP method) - * disabled _method request parameter support by default (call Request::enableHttpMethodParameterOverride() to - enable it, and Request::getHttpMethodParameterOverride() to check if it is supported) - * Request::splitHttpAcceptHeader() method is deprecated and will be removed in 2.3 - * Deprecated Flashbag::count() and \Countable interface, will be removed in 2.3 - -2.1.0 ------ - - * added Request::getSchemeAndHttpHost() and Request::getUserInfo() - * added a fluent interface to the Response class - * added Request::isProxyTrusted() - * added JsonResponse - * added a getTargetUrl method to RedirectResponse - * added support for streamed responses - * made Response::prepare() method the place to enforce HTTP specification - * [BC BREAK] moved management of the locale from the Session class to the Request class - * added a generic access to the PHP built-in filter mechanism: ParameterBag::filter() - * made FileBinaryMimeTypeGuesser command configurable - * added Request::getUser() and Request::getPassword() - * added support for the PATCH method in Request - * removed the ContentTypeMimeTypeGuesser class as it is deprecated and never used on PHP 5.3 - * added ResponseHeaderBag::makeDisposition() (implements RFC 6266) - * made mimetype to extension conversion configurable - * [BC BREAK] Moved all session related classes and interfaces into own namespace, as - `Symfony\Component\HttpFoundation\Session` and renamed classes accordingly. - Session handlers are located in the subnamespace `Symfony\Component\HttpFoundation\Session\Handler`. - * SessionHandlers must implement `\SessionHandlerInterface` or extend from the - `Symfony\Component\HttpFoundation\Storage\Handler\NativeSessionHandler` base class. - * Added internal storage driver proxy mechanism for forward compatibility with - PHP 5.4 `\SessionHandler` class. - * Added session handlers for custom Memcache, Memcached and Null session save handlers. - * [BC BREAK] Removed `NativeSessionStorage` and replaced with `NativeFileSessionHandler`. - * [BC BREAK] `SessionStorageInterface` methods removed: `write()`, `read()` and - `remove()`. Added `getBag()`, `registerBag()`. The `NativeSessionStorage` class - is a mediator for the session storage internals including the session handlers - which do the real work of participating in the internal PHP session workflow. - * [BC BREAK] Introduced mock implementations of `SessionStorage` to enable unit - and functional testing without starting real PHP sessions. Removed - `ArraySessionStorage`, and replaced with `MockArraySessionStorage` for unit - tests; removed `FilesystemSessionStorage`, and replaced with`MockFileSessionStorage` - for functional tests. These do not interact with global session ini - configuration values, session functions or `$_SESSION` superglobal. This means - they can be configured directly allowing multiple instances to work without - conflicting in the same PHP process. - * [BC BREAK] Removed the `close()` method from the `Session` class, as this is - now redundant. - * Deprecated the following methods from the Session class: `setFlash()`, `setFlashes()` - `getFlash()`, `hasFlash()`, and `removeFlash()`. Use `getFlashBag()` instead - which returns a `FlashBagInterface`. - * `Session->clear()` now only clears session attributes as before it cleared - flash messages and attributes. `Session->getFlashBag()->all()` clears flashes now. - * Session data is now managed by `SessionBagInterface` to better encapsulate - session data. - * Refactored session attribute and flash messages system to their own - `SessionBagInterface` implementations. - * Added `FlashBag`. Flashes expire when retrieved by `get()` or `all()`. This - implementation is ESI compatible. - * Added `AutoExpireFlashBag` (default) to replicate Symfony 2.0.x auto expire - behavior of messages auto expiring after one page page load. Messages must - be retrieved by `get()` or `all()`. - * Added `Symfony\Component\HttpFoundation\Attribute\AttributeBag` to replicate - attributes storage behavior from 2.0.x (default). - * Added `Symfony\Component\HttpFoundation\Attribute\NamespacedAttributeBag` for - namespace session attributes. - * Flash API can stores messages in an array so there may be multiple messages - per flash type. The old `Session` class API remains without BC break as it - will allow single messages as before. - * Added basic session meta-data to the session to record session create time, - last updated time, and the lifetime of the session cookie that was provided - to the client. - * Request::getClientIp() method doesn't take a parameter anymore but bases - itself on the trustProxy parameter. - * Added isMethod() to Request object. - * [BC BREAK] The methods `getPathInfo()`, `getBaseUrl()` and `getBasePath()` of - a `Request` now all return a raw value (vs a urldecoded value before). Any call - to one of these methods must be checked and wrapped in a `rawurldecode()` if - needed. diff --git a/vendor/symfony/http-foundation/Cookie.php b/vendor/symfony/http-foundation/Cookie.php deleted file mode 100644 index fc711ee..0000000 --- a/vendor/symfony/http-foundation/Cookie.php +++ /dev/null @@ -1,302 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Represents a cookie. - * - * @author Johannes M. Schmitt - */ -class Cookie -{ - const SAMESITE_NONE = 'none'; - const SAMESITE_LAX = 'lax'; - const SAMESITE_STRICT = 'strict'; - - protected $name; - protected $value; - protected $domain; - protected $expire; - protected $path; - protected $secure; - protected $httpOnly; - - private $raw; - private $sameSite; - private $secureDefault = false; - - private static $reservedCharsList = "=,; \t\r\n\v\f"; - private static $reservedCharsFrom = ['=', ',', ';', ' ', "\t", "\r", "\n", "\v", "\f"]; - private static $reservedCharsTo = ['%3D', '%2C', '%3B', '%20', '%09', '%0D', '%0A', '%0B', '%0C']; - - /** - * Creates cookie from raw header string. - * - * @return static - */ - public static function fromString(string $cookie, bool $decode = false) - { - $data = [ - 'expires' => 0, - 'path' => '/', - 'domain' => null, - 'secure' => false, - 'httponly' => false, - 'raw' => !$decode, - 'samesite' => null, - ]; - - $parts = HeaderUtils::split($cookie, ';='); - $part = array_shift($parts); - - $name = $decode ? urldecode($part[0]) : $part[0]; - $value = isset($part[1]) ? ($decode ? urldecode($part[1]) : $part[1]) : null; - - $data = HeaderUtils::combine($parts) + $data; - - if (isset($data['max-age'])) { - $data['expires'] = time() + (int) $data['max-age']; - } - - return new static($name, $value, $data['expires'], $data['path'], $data['domain'], $data['secure'], $data['httponly'], $data['raw'], $data['samesite']); - } - - public static function create(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX): self - { - return new self($name, $value, $expire, $path, $domain, $secure, $httpOnly, $raw, $sameSite); - } - - /** - * @param string $name The name of the cookie - * @param string|null $value The value of the cookie - * @param int|string|\DateTimeInterface $expire The time the cookie expires - * @param string $path The path on the server in which the cookie will be available on - * @param string|null $domain The domain that the cookie is available to - * @param bool|null $secure Whether the client should send back the cookie only over HTTPS or null to auto-enable this when the request is already using HTTPS - * @param bool $httpOnly Whether the cookie will be made accessible only through the HTTP protocol - * @param bool $raw Whether the cookie value should be sent with no url encoding - * @param string|null $sameSite Whether the cookie will be available for cross-site requests - * - * @throws \InvalidArgumentException - */ - public function __construct(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = 'lax') - { - // from PHP source code - if ($raw && false !== strpbrk($name, self::$reservedCharsList)) { - throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name)); - } - - if (empty($name)) { - throw new \InvalidArgumentException('The cookie name cannot be empty.'); - } - - // convert expiration time to a Unix timestamp - if ($expire instanceof \DateTimeInterface) { - $expire = $expire->format('U'); - } elseif (!is_numeric($expire)) { - $expire = strtotime($expire); - - if (false === $expire) { - throw new \InvalidArgumentException('The cookie expiration time is not valid.'); - } - } - - $this->name = $name; - $this->value = $value; - $this->domain = $domain; - $this->expire = 0 < $expire ? (int) $expire : 0; - $this->path = empty($path) ? '/' : $path; - $this->secure = $secure; - $this->httpOnly = $httpOnly; - $this->raw = $raw; - - if ('' === $sameSite) { - $sameSite = null; - } elseif (null !== $sameSite) { - $sameSite = strtolower($sameSite); - } - - if (!\in_array($sameSite, [self::SAMESITE_LAX, self::SAMESITE_STRICT, self::SAMESITE_NONE, null], true)) { - throw new \InvalidArgumentException('The "sameSite" parameter value is not valid.'); - } - - $this->sameSite = $sameSite; - } - - /** - * Returns the cookie as a string. - * - * @return string The cookie - */ - public function __toString() - { - if ($this->isRaw()) { - $str = $this->getName(); - } else { - $str = str_replace(self::$reservedCharsFrom, self::$reservedCharsTo, $this->getName()); - } - - $str .= '='; - - if ('' === (string) $this->getValue()) { - $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0'; - } else { - $str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue()); - - if (0 !== $this->getExpiresTime()) { - $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; Max-Age='.$this->getMaxAge(); - } - } - - if ($this->getPath()) { - $str .= '; path='.$this->getPath(); - } - - if ($this->getDomain()) { - $str .= '; domain='.$this->getDomain(); - } - - if (true === $this->isSecure()) { - $str .= '; secure'; - } - - if (true === $this->isHttpOnly()) { - $str .= '; httponly'; - } - - if (null !== $this->getSameSite()) { - $str .= '; samesite='.$this->getSameSite(); - } - - return $str; - } - - /** - * Gets the name of the cookie. - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Gets the value of the cookie. - * - * @return string|null - */ - public function getValue() - { - return $this->value; - } - - /** - * Gets the domain that the cookie is available to. - * - * @return string|null - */ - public function getDomain() - { - return $this->domain; - } - - /** - * Gets the time the cookie expires. - * - * @return int - */ - public function getExpiresTime() - { - return $this->expire; - } - - /** - * Gets the max-age attribute. - * - * @return int - */ - public function getMaxAge() - { - $maxAge = $this->expire - time(); - - return 0 >= $maxAge ? 0 : $maxAge; - } - - /** - * Gets the path on the server in which the cookie will be available on. - * - * @return string - */ - public function getPath() - { - return $this->path; - } - - /** - * Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client. - * - * @return bool - */ - public function isSecure() - { - return $this->secure ?? $this->secureDefault; - } - - /** - * Checks whether the cookie will be made accessible only through the HTTP protocol. - * - * @return bool - */ - public function isHttpOnly() - { - return $this->httpOnly; - } - - /** - * Whether this cookie is about to be cleared. - * - * @return bool - */ - public function isCleared() - { - return 0 !== $this->expire && $this->expire < time(); - } - - /** - * Checks if the cookie value should be sent with no url encoding. - * - * @return bool - */ - public function isRaw() - { - return $this->raw; - } - - /** - * Gets the SameSite attribute. - * - * @return string|null - */ - public function getSameSite() - { - return $this->sameSite; - } - - /** - * @param bool $default The default value of the "secure" flag when it is set to null - */ - public function setSecureDefault(bool $default): void - { - $this->secureDefault = $default; - } -} diff --git a/vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php b/vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php deleted file mode 100644 index 5fcf5b4..0000000 --- a/vendor/symfony/http-foundation/Exception/ConflictingHeadersException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * The HTTP request contains headers with conflicting information. - * - * @author Magnus Nordlander - */ -class ConflictingHeadersException extends \UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php b/vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php deleted file mode 100644 index 478d0dc..0000000 --- a/vendor/symfony/http-foundation/Exception/RequestExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Interface for Request exceptions. - * - * Exceptions implementing this interface should trigger an HTTP 400 response in the application code. - */ -interface RequestExceptionInterface -{ -} diff --git a/vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php b/vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php deleted file mode 100644 index ae7a5f1..0000000 --- a/vendor/symfony/http-foundation/Exception/SuspiciousOperationException.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Exception; - -/** - * Raised when a user has performed an operation that should be considered - * suspicious from a security perspective. - */ -class SuspiciousOperationException extends \UnexpectedValueException implements RequestExceptionInterface -{ -} diff --git a/vendor/symfony/http-foundation/ExpressionRequestMatcher.php b/vendor/symfony/http-foundation/ExpressionRequestMatcher.php deleted file mode 100644 index 26bed7d..0000000 --- a/vendor/symfony/http-foundation/ExpressionRequestMatcher.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; - -/** - * ExpressionRequestMatcher uses an expression to match a Request. - * - * @author Fabien Potencier - */ -class ExpressionRequestMatcher extends RequestMatcher -{ - private $language; - private $expression; - - public function setExpression(ExpressionLanguage $language, $expression) - { - $this->language = $language; - $this->expression = $expression; - } - - public function matches(Request $request) - { - if (!$this->language) { - throw new \LogicException('Unable to match the request as the expression language is not available.'); - } - - return $this->language->evaluate($this->expression, [ - 'request' => $request, - 'method' => $request->getMethod(), - 'path' => rawurldecode($request->getPathInfo()), - 'host' => $request->getHost(), - 'ip' => $request->getClientIp(), - 'attributes' => $request->attributes->all(), - ]) && parent::matches($request); - } -} diff --git a/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php b/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php deleted file mode 100644 index 136d2a9..0000000 --- a/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when the access on a file was denied. - * - * @author Bernhard Schussek - */ -class AccessDeniedException extends FileException -{ - public function __construct(string $path) - { - parent::__construct(sprintf('The file %s could not be accessed', $path)); - } -} diff --git a/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php b/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php deleted file mode 100644 index c49f53a..0000000 --- a/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_CANT_WRITE error occurred with UploadedFile. - * - * @author Florent Mata - */ -class CannotWriteFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php b/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php deleted file mode 100644 index ed83499..0000000 --- a/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_EXTENSION error occurred with UploadedFile. - * - * @author Florent Mata - */ -class ExtensionFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/FileException.php b/vendor/symfony/http-foundation/File/Exception/FileException.php deleted file mode 100644 index fad5133..0000000 --- a/vendor/symfony/http-foundation/File/Exception/FileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an error occurred in the component File. - * - * @author Bernhard Schussek - */ -class FileException extends \RuntimeException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php b/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php deleted file mode 100644 index 31bdf68..0000000 --- a/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when a file was not found. - * - * @author Bernhard Schussek - */ -class FileNotFoundException extends FileException -{ - public function __construct(string $path) - { - parent::__construct(sprintf('The file "%s" does not exist', $path)); - } -} diff --git a/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php b/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php deleted file mode 100644 index 8741be0..0000000 --- a/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_FORM_SIZE error occurred with UploadedFile. - * - * @author Florent Mata - */ -class FormSizeFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php b/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php deleted file mode 100644 index c8fde61..0000000 --- a/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_INI_SIZE error occurred with UploadedFile. - * - * @author Florent Mata - */ -class IniSizeFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/NoFileException.php b/vendor/symfony/http-foundation/File/Exception/NoFileException.php deleted file mode 100644 index 4b48cc7..0000000 --- a/vendor/symfony/http-foundation/File/Exception/NoFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_NO_FILE error occurred with UploadedFile. - * - * @author Florent Mata - */ -class NoFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php b/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php deleted file mode 100644 index bdead2d..0000000 --- a/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_NO_TMP_DIR error occurred with UploadedFile. - * - * @author Florent Mata - */ -class NoTmpDirFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/PartialFileException.php b/vendor/symfony/http-foundation/File/Exception/PartialFileException.php deleted file mode 100644 index 4641efb..0000000 --- a/vendor/symfony/http-foundation/File/Exception/PartialFileException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an UPLOAD_ERR_PARTIAL error occurred with UploadedFile. - * - * @author Florent Mata - */ -class PartialFileException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php b/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php deleted file mode 100644 index 82b982b..0000000 --- a/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -class UnexpectedTypeException extends FileException -{ - public function __construct($value, string $expectedType) - { - parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, \is_object($value) ? \get_class($value) : \gettype($value))); - } -} diff --git a/vendor/symfony/http-foundation/File/Exception/UploadException.php b/vendor/symfony/http-foundation/File/Exception/UploadException.php deleted file mode 100644 index 7074e76..0000000 --- a/vendor/symfony/http-foundation/File/Exception/UploadException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File\Exception; - -/** - * Thrown when an error occurred during file upload. - * - * @author Bernhard Schussek - */ -class UploadException extends FileException -{ -} diff --git a/vendor/symfony/http-foundation/File/File.php b/vendor/symfony/http-foundation/File/File.php deleted file mode 100644 index d79c27f..0000000 --- a/vendor/symfony/http-foundation/File/File.php +++ /dev/null @@ -1,130 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File; - -use Symfony\Component\HttpFoundation\File\Exception\FileException; -use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; -use Symfony\Component\Mime\MimeTypes; - -/** - * A file in the file system. - * - * @author Bernhard Schussek - */ -class File extends \SplFileInfo -{ - /** - * Constructs a new file from the given path. - * - * @param string $path The path to the file - * @param bool $checkPath Whether to check the path or not - * - * @throws FileNotFoundException If the given path is not a file - */ - public function __construct(string $path, bool $checkPath = true) - { - if ($checkPath && !is_file($path)) { - throw new FileNotFoundException($path); - } - - parent::__construct($path); - } - - /** - * Returns the extension based on the mime type. - * - * If the mime type is unknown, returns null. - * - * This method uses the mime type as guessed by getMimeType() - * to guess the file extension. - * - * @return string|null The guessed extension or null if it cannot be guessed - * - * @see MimeTypes - * @see getMimeType() - */ - public function guessExtension() - { - return MimeTypes::getDefault()->getExtensions($this->getMimeType())[0] ?? null; - } - - /** - * Returns the mime type of the file. - * - * The mime type is guessed using a MimeTypeGuesserInterface instance, - * which uses finfo_file() then the "file" system binary, - * depending on which of those are available. - * - * @return string|null The guessed mime type (e.g. "application/pdf") - * - * @see MimeTypes - */ - public function getMimeType() - { - return MimeTypes::getDefault()->guessMimeType($this->getPathname()); - } - - /** - * Moves the file to a new location. - * - * @return self A File object representing the new file - * - * @throws FileException if the target file could not be created - */ - public function move(string $directory, string $name = null) - { - $target = $this->getTargetFile($directory, $name); - - set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); - $renamed = rename($this->getPathname(), $target); - restore_error_handler(); - if (!$renamed) { - throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error))); - } - - @chmod($target, 0666 & ~umask()); - - return $target; - } - - /** - * @return self - */ - protected function getTargetFile(string $directory, string $name = null) - { - if (!is_dir($directory)) { - if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) { - throw new FileException(sprintf('Unable to create the "%s" directory', $directory)); - } - } elseif (!is_writable($directory)) { - throw new FileException(sprintf('Unable to write in the "%s" directory', $directory)); - } - - $target = rtrim($directory, '/\\').\DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name)); - - return new self($target, false); - } - - /** - * Returns locale independent base name of the given path. - * - * @return string - */ - protected function getName(string $name) - { - $originalName = str_replace('\\', '/', $name); - $pos = strrpos($originalName, '/'); - $originalName = false === $pos ? $originalName : substr($originalName, $pos + 1); - - return $originalName; - } -} diff --git a/vendor/symfony/http-foundation/File/Stream.php b/vendor/symfony/http-foundation/File/Stream.php deleted file mode 100644 index 69ae74c..0000000 --- a/vendor/symfony/http-foundation/File/Stream.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File; - -/** - * A PHP stream of unknown size. - * - * @author Nicolas Grekas - */ -class Stream extends File -{ - /** - * {@inheritdoc} - */ - public function getSize() - { - return false; - } -} diff --git a/vendor/symfony/http-foundation/File/UploadedFile.php b/vendor/symfony/http-foundation/File/UploadedFile.php deleted file mode 100644 index 3a258e2..0000000 --- a/vendor/symfony/http-foundation/File/UploadedFile.php +++ /dev/null @@ -1,281 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\File; - -use Symfony\Component\HttpFoundation\File\Exception\CannotWriteFileException; -use Symfony\Component\HttpFoundation\File\Exception\ExtensionFileException; -use Symfony\Component\HttpFoundation\File\Exception\FileException; -use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; -use Symfony\Component\HttpFoundation\File\Exception\FormSizeFileException; -use Symfony\Component\HttpFoundation\File\Exception\IniSizeFileException; -use Symfony\Component\HttpFoundation\File\Exception\NoFileException; -use Symfony\Component\HttpFoundation\File\Exception\NoTmpDirFileException; -use Symfony\Component\HttpFoundation\File\Exception\PartialFileException; -use Symfony\Component\Mime\MimeTypes; - -/** - * A file uploaded through a form. - * - * @author Bernhard Schussek - * @author Florian Eckerstorfer - * @author Fabien Potencier - */ -class UploadedFile extends File -{ - private $test = false; - private $originalName; - private $mimeType; - private $error; - - /** - * Accepts the information of the uploaded file as provided by the PHP global $_FILES. - * - * The file object is only created when the uploaded file is valid (i.e. when the - * isValid() method returns true). Otherwise the only methods that could be called - * on an UploadedFile instance are: - * - * * getClientOriginalName, - * * getClientMimeType, - * * isValid, - * * getError. - * - * Calling any other method on an non-valid instance will cause an unpredictable result. - * - * @param string $path The full temporary path to the file - * @param string $originalName The original file name of the uploaded file - * @param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream - * @param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK - * @param bool $test Whether the test mode is active - * Local files are used in test mode hence the code should not enforce HTTP uploads - * - * @throws FileException If file_uploads is disabled - * @throws FileNotFoundException If the file does not exist - */ - public function __construct(string $path, string $originalName, string $mimeType = null, int $error = null, bool $test = false) - { - $this->originalName = $this->getName($originalName); - $this->mimeType = $mimeType ?: 'application/octet-stream'; - $this->error = $error ?: UPLOAD_ERR_OK; - $this->test = $test; - - parent::__construct($path, UPLOAD_ERR_OK === $this->error); - } - - /** - * Returns the original file name. - * - * It is extracted from the request from which the file has been uploaded. - * Then it should not be considered as a safe value. - * - * @return string|null The original name - */ - public function getClientOriginalName() - { - return $this->originalName; - } - - /** - * Returns the original file extension. - * - * It is extracted from the original file name that was uploaded. - * Then it should not be considered as a safe value. - * - * @return string The extension - */ - public function getClientOriginalExtension() - { - return pathinfo($this->originalName, PATHINFO_EXTENSION); - } - - /** - * Returns the file mime type. - * - * The client mime type is extracted from the request from which the file - * was uploaded, so it should not be considered as a safe value. - * - * For a trusted mime type, use getMimeType() instead (which guesses the mime - * type based on the file content). - * - * @return string|null The mime type - * - * @see getMimeType() - */ - public function getClientMimeType() - { - return $this->mimeType; - } - - /** - * Returns the extension based on the client mime type. - * - * If the mime type is unknown, returns null. - * - * This method uses the mime type as guessed by getClientMimeType() - * to guess the file extension. As such, the extension returned - * by this method cannot be trusted. - * - * For a trusted extension, use guessExtension() instead (which guesses - * the extension based on the guessed mime type for the file). - * - * @return string|null The guessed extension or null if it cannot be guessed - * - * @see guessExtension() - * @see getClientMimeType() - */ - public function guessClientExtension() - { - return MimeTypes::getDefault()->getExtensions($this->getClientMimeType())[0] ?? null; - } - - /** - * Returns the upload error. - * - * If the upload was successful, the constant UPLOAD_ERR_OK is returned. - * Otherwise one of the other UPLOAD_ERR_XXX constants is returned. - * - * @return int The upload error - */ - public function getError() - { - return $this->error; - } - - /** - * Returns whether the file was uploaded successfully. - * - * @return bool True if the file has been uploaded with HTTP and no error occurred - */ - public function isValid() - { - $isOk = UPLOAD_ERR_OK === $this->error; - - return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname()); - } - - /** - * Moves the file to a new location. - * - * @return File A File object representing the new file - * - * @throws FileException if, for any reason, the file could not have been moved - */ - public function move(string $directory, string $name = null) - { - if ($this->isValid()) { - if ($this->test) { - return parent::move($directory, $name); - } - - $target = $this->getTargetFile($directory, $name); - - set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); - $moved = move_uploaded_file($this->getPathname(), $target); - restore_error_handler(); - if (!$moved) { - throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error))); - } - - @chmod($target, 0666 & ~umask()); - - return $target; - } - - switch ($this->error) { - case UPLOAD_ERR_INI_SIZE: - throw new IniSizeFileException($this->getErrorMessage()); - case UPLOAD_ERR_FORM_SIZE: - throw new FormSizeFileException($this->getErrorMessage()); - case UPLOAD_ERR_PARTIAL: - throw new PartialFileException($this->getErrorMessage()); - case UPLOAD_ERR_NO_FILE: - throw new NoFileException($this->getErrorMessage()); - case UPLOAD_ERR_CANT_WRITE: - throw new CannotWriteFileException($this->getErrorMessage()); - case UPLOAD_ERR_NO_TMP_DIR: - throw new NoTmpDirFileException($this->getErrorMessage()); - case UPLOAD_ERR_EXTENSION: - throw new ExtensionFileException($this->getErrorMessage()); - } - - throw new FileException($this->getErrorMessage()); - } - - /** - * Returns the maximum size of an uploaded file as configured in php.ini. - * - * @return int The maximum size of an uploaded file in bytes - */ - public static function getMaxFilesize() - { - $sizePostMax = self::parseFilesize(ini_get('post_max_size')); - $sizeUploadMax = self::parseFilesize(ini_get('upload_max_filesize')); - - return min($sizePostMax ?: PHP_INT_MAX, $sizeUploadMax ?: PHP_INT_MAX); - } - - /** - * Returns the given size from an ini value in bytes. - */ - private static function parseFilesize($size): int - { - if ('' === $size) { - return 0; - } - - $size = strtolower($size); - - $max = ltrim($size, '+'); - if (0 === strpos($max, '0x')) { - $max = \intval($max, 16); - } elseif (0 === strpos($max, '0')) { - $max = \intval($max, 8); - } else { - $max = (int) $max; - } - - switch (substr($size, -1)) { - case 't': $max *= 1024; - // no break - case 'g': $max *= 1024; - // no break - case 'm': $max *= 1024; - // no break - case 'k': $max *= 1024; - } - - return $max; - } - - /** - * Returns an informative upload error message. - * - * @return string The error message regarding the specified error code - */ - public function getErrorMessage() - { - static $errors = [ - UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).', - UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.', - UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.', - UPLOAD_ERR_NO_FILE => 'No file was uploaded.', - UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.', - UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.', - UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.', - ]; - - $errorCode = $this->error; - $maxFilesize = UPLOAD_ERR_INI_SIZE === $errorCode ? self::getMaxFilesize() / 1024 : 0; - $message = isset($errors[$errorCode]) ? $errors[$errorCode] : 'The file "%s" was not uploaded due to an unknown error.'; - - return sprintf($message, $this->getClientOriginalName(), $maxFilesize); - } -} diff --git a/vendor/symfony/http-foundation/FileBag.php b/vendor/symfony/http-foundation/FileBag.php deleted file mode 100644 index 5edd372..0000000 --- a/vendor/symfony/http-foundation/FileBag.php +++ /dev/null @@ -1,142 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\File\UploadedFile; - -/** - * FileBag is a container for uploaded files. - * - * @author Fabien Potencier - * @author Bulat Shakirzyanov - */ -class FileBag extends ParameterBag -{ - private static $fileKeys = ['error', 'name', 'size', 'tmp_name', 'type']; - - /** - * @param array|UploadedFile[] $parameters An array of HTTP files - */ - public function __construct(array $parameters = []) - { - $this->replace($parameters); - } - - /** - * {@inheritdoc} - */ - public function replace(array $files = []) - { - $this->parameters = []; - $this->add($files); - } - - /** - * {@inheritdoc} - */ - public function set(string $key, $value) - { - if (!\is_array($value) && !$value instanceof UploadedFile) { - throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.'); - } - - parent::set($key, $this->convertFileInformation($value)); - } - - /** - * {@inheritdoc} - */ - public function add(array $files = []) - { - foreach ($files as $key => $file) { - $this->set($key, $file); - } - } - - /** - * Converts uploaded files to UploadedFile instances. - * - * @param array|UploadedFile $file A (multi-dimensional) array of uploaded file information - * - * @return UploadedFile[]|UploadedFile|null A (multi-dimensional) array of UploadedFile instances - */ - protected function convertFileInformation($file) - { - if ($file instanceof UploadedFile) { - return $file; - } - - if (\is_array($file)) { - $file = $this->fixPhpFilesArray($file); - $keys = array_keys($file); - sort($keys); - - if ($keys == self::$fileKeys) { - if (UPLOAD_ERR_NO_FILE == $file['error']) { - $file = null; - } else { - $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['error'], false); - } - } else { - $file = array_map([$this, 'convertFileInformation'], $file); - if (array_keys($keys) === $keys) { - $file = array_filter($file); - } - } - } - - return $file; - } - - /** - * Fixes a malformed PHP $_FILES array. - * - * PHP has a bug that the format of the $_FILES array differs, depending on - * whether the uploaded file fields had normal field names or array-like - * field names ("normal" vs. "parent[child]"). - * - * This method fixes the array to look like the "normal" $_FILES array. - * - * It's safe to pass an already converted array, in which case this method - * just returns the original array unmodified. - * - * @param array $data - * - * @return array - */ - protected function fixPhpFilesArray($data) - { - $keys = array_keys($data); - sort($keys); - - if (self::$fileKeys != $keys || !isset($data['name']) || !\is_array($data['name'])) { - return $data; - } - - $files = $data; - foreach (self::$fileKeys as $k) { - unset($files[$k]); - } - - foreach ($data['name'] as $key => $name) { - $files[$key] = $this->fixPhpFilesArray([ - 'error' => $data['error'][$key], - 'name' => $name, - 'type' => $data['type'][$key], - 'tmp_name' => $data['tmp_name'][$key], - 'size' => $data['size'][$key], - ]); - } - - return $files; - } -} diff --git a/vendor/symfony/http-foundation/HeaderBag.php b/vendor/symfony/http-foundation/HeaderBag.php deleted file mode 100644 index 9c7273a..0000000 --- a/vendor/symfony/http-foundation/HeaderBag.php +++ /dev/null @@ -1,288 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * HeaderBag is a container for HTTP headers. - * - * @author Fabien Potencier - */ -class HeaderBag implements \IteratorAggregate, \Countable -{ - protected const UPPER = '_ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - protected const LOWER = '-abcdefghijklmnopqrstuvwxyz'; - - protected $headers = []; - protected $cacheControl = []; - - public function __construct(array $headers = []) - { - foreach ($headers as $key => $values) { - $this->set($key, $values); - } - } - - /** - * Returns the headers as a string. - * - * @return string The headers - */ - public function __toString() - { - if (!$headers = $this->all()) { - return ''; - } - - ksort($headers); - $max = max(array_map('strlen', array_keys($headers))) + 1; - $content = ''; - foreach ($headers as $name => $values) { - $name = ucwords($name, '-'); - foreach ($values as $value) { - $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value); - } - } - - return $content; - } - - /** - * Returns the headers. - * - * @param string|null $key The name of the headers to return or null to get them all - * - * @return array An array of headers - */ - public function all(string $key = null) - { - if (null !== $key) { - return $this->headers[strtr($key, self::UPPER, self::LOWER)] ?? []; - } - - return $this->headers; - } - - /** - * Returns the parameter keys. - * - * @return array An array of parameter keys - */ - public function keys() - { - return array_keys($this->all()); - } - - /** - * Replaces the current HTTP headers by a new set. - */ - public function replace(array $headers = []) - { - $this->headers = []; - $this->add($headers); - } - - /** - * Adds new headers the current HTTP headers set. - */ - public function add(array $headers) - { - foreach ($headers as $key => $values) { - $this->set($key, $values); - } - } - - /** - * Returns a header value by name. - * - * @return string|null The first header value or default value - */ - public function get(string $key, string $default = null) - { - $headers = $this->all($key); - - if (!$headers) { - return $default; - } - - if (null === $headers[0]) { - return null; - } - - return (string) $headers[0]; - } - - /** - * Sets a header by name. - * - * @param string|string[] $values The value or an array of values - * @param bool $replace Whether to replace the actual value or not (true by default) - */ - public function set(string $key, $values, bool $replace = true) - { - $key = strtr($key, self::UPPER, self::LOWER); - - if (\is_array($values)) { - $values = array_values($values); - - if (true === $replace || !isset($this->headers[$key])) { - $this->headers[$key] = $values; - } else { - $this->headers[$key] = array_merge($this->headers[$key], $values); - } - } else { - if (true === $replace || !isset($this->headers[$key])) { - $this->headers[$key] = [$values]; - } else { - $this->headers[$key][] = $values; - } - } - - if ('cache-control' === $key) { - $this->cacheControl = $this->parseCacheControl(implode(', ', $this->headers[$key])); - } - } - - /** - * Returns true if the HTTP header is defined. - * - * @return bool true if the parameter exists, false otherwise - */ - public function has(string $key) - { - return \array_key_exists(strtr($key, self::UPPER, self::LOWER), $this->all()); - } - - /** - * Returns true if the given HTTP header contains the given value. - * - * @return bool true if the value is contained in the header, false otherwise - */ - public function contains(string $key, string $value) - { - return \in_array($value, $this->all($key)); - } - - /** - * Removes a header. - */ - public function remove(string $key) - { - $key = strtr($key, self::UPPER, self::LOWER); - - unset($this->headers[$key]); - - if ('cache-control' === $key) { - $this->cacheControl = []; - } - } - - /** - * Returns the HTTP header value converted to a date. - * - * @return \DateTimeInterface|null The parsed DateTime or the default value if the header does not exist - * - * @throws \RuntimeException When the HTTP header is not parseable - */ - public function getDate(string $key, \DateTime $default = null) - { - if (null === $value = $this->get($key)) { - return $default; - } - - if (false === $date = \DateTime::createFromFormat(DATE_RFC2822, $value)) { - throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value)); - } - - return $date; - } - - /** - * Adds a custom Cache-Control directive. - * - * @param mixed $value The Cache-Control directive value - */ - public function addCacheControlDirective(string $key, $value = true) - { - $this->cacheControl[$key] = $value; - - $this->set('Cache-Control', $this->getCacheControlHeader()); - } - - /** - * Returns true if the Cache-Control directive is defined. - * - * @return bool true if the directive exists, false otherwise - */ - public function hasCacheControlDirective(string $key) - { - return \array_key_exists($key, $this->cacheControl); - } - - /** - * Returns a Cache-Control directive value by name. - * - * @return mixed|null The directive value if defined, null otherwise - */ - public function getCacheControlDirective(string $key) - { - return \array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null; - } - - /** - * Removes a Cache-Control directive. - */ - public function removeCacheControlDirective(string $key) - { - unset($this->cacheControl[$key]); - - $this->set('Cache-Control', $this->getCacheControlHeader()); - } - - /** - * Returns an iterator for headers. - * - * @return \ArrayIterator An \ArrayIterator instance - */ - public function getIterator() - { - return new \ArrayIterator($this->headers); - } - - /** - * Returns the number of headers. - * - * @return int The number of headers - */ - public function count() - { - return \count($this->headers); - } - - protected function getCacheControlHeader() - { - ksort($this->cacheControl); - - return HeaderUtils::toString($this->cacheControl, ','); - } - - /** - * Parses a Cache-Control HTTP header. - * - * @return array An array representing the attribute values - */ - protected function parseCacheControl(string $header) - { - $parts = HeaderUtils::split($header, ',='); - - return HeaderUtils::combine($parts); - } -} diff --git a/vendor/symfony/http-foundation/HeaderUtils.php b/vendor/symfony/http-foundation/HeaderUtils.php deleted file mode 100644 index 5866e3b..0000000 --- a/vendor/symfony/http-foundation/HeaderUtils.php +++ /dev/null @@ -1,224 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * HTTP header utility functions. - * - * @author Christian Schmidt - */ -class HeaderUtils -{ - public const DISPOSITION_ATTACHMENT = 'attachment'; - public const DISPOSITION_INLINE = 'inline'; - - /** - * This class should not be instantiated. - */ - private function __construct() - { - } - - /** - * Splits an HTTP header by one or more separators. - * - * Example: - * - * HeaderUtils::split("da, en-gb;q=0.8", ",;") - * // => ['da'], ['en-gb', 'q=0.8']] - * - * @param string $separators List of characters to split on, ordered by - * precedence, e.g. ",", ";=", or ",;=" - * - * @return array Nested array with as many levels as there are characters in - * $separators - */ - public static function split(string $header, string $separators): array - { - $quotedSeparators = preg_quote($separators, '/'); - - preg_match_all(' - / - (?!\s) - (?: - # quoted-string - "(?:[^"\\\\]|\\\\.)*(?:"|\\\\|$) - | - # token - [^"'.$quotedSeparators.']+ - )+ - (?['.$quotedSeparators.']) - \s* - /x', trim($header), $matches, PREG_SET_ORDER); - - return self::groupParts($matches, $separators); - } - - /** - * Combines an array of arrays into one associative array. - * - * Each of the nested arrays should have one or two elements. The first - * value will be used as the keys in the associative array, and the second - * will be used as the values, or true if the nested array only contains one - * element. Array keys are lowercased. - * - * Example: - * - * HeaderUtils::combine([["foo", "abc"], ["bar"]]) - * // => ["foo" => "abc", "bar" => true] - */ - public static function combine(array $parts): array - { - $assoc = []; - foreach ($parts as $part) { - $name = strtolower($part[0]); - $value = $part[1] ?? true; - $assoc[$name] = $value; - } - - return $assoc; - } - - /** - * Joins an associative array into a string for use in an HTTP header. - * - * The key and value of each entry are joined with "=", and all entries - * are joined with the specified separator and an additional space (for - * readability). Values are quoted if necessary. - * - * Example: - * - * HeaderUtils::toString(["foo" => "abc", "bar" => true, "baz" => "a b c"], ",") - * // => 'foo=abc, bar, baz="a b c"' - */ - public static function toString(array $assoc, string $separator): string - { - $parts = []; - foreach ($assoc as $name => $value) { - if (true === $value) { - $parts[] = $name; - } else { - $parts[] = $name.'='.self::quote($value); - } - } - - return implode($separator.' ', $parts); - } - - /** - * Encodes a string as a quoted string, if necessary. - * - * If a string contains characters not allowed by the "token" construct in - * the HTTP specification, it is backslash-escaped and enclosed in quotes - * to match the "quoted-string" construct. - */ - public static function quote(string $s): string - { - if (preg_match('/^[a-z0-9!#$%&\'*.^_`|~-]+$/i', $s)) { - return $s; - } - - return '"'.addcslashes($s, '"\\"').'"'; - } - - /** - * Decodes a quoted string. - * - * If passed an unquoted string that matches the "token" construct (as - * defined in the HTTP specification), it is passed through verbatimly. - */ - public static function unquote(string $s): string - { - return preg_replace('/\\\\(.)|"/', '$1', $s); - } - - /** - * Generates a HTTP Content-Disposition field-value. - * - * @param string $disposition One of "inline" or "attachment" - * @param string $filename A unicode string - * @param string $filenameFallback A string containing only ASCII characters that - * is semantically equivalent to $filename. If the filename is already ASCII, - * it can be omitted, or just copied from $filename - * - * @return string A string suitable for use as a Content-Disposition field-value - * - * @throws \InvalidArgumentException - * - * @see RFC 6266 - */ - public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string - { - if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE])) { - throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE)); - } - - if ('' === $filenameFallback) { - $filenameFallback = $filename; - } - - // filenameFallback is not ASCII. - if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) { - throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.'); - } - - // percent characters aren't safe in fallback. - if (false !== strpos($filenameFallback, '%')) { - throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.'); - } - - // path separators aren't allowed in either. - if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) { - throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.'); - } - - $params = ['filename' => $filenameFallback]; - if ($filename !== $filenameFallback) { - $params['filename*'] = "utf-8''".rawurlencode($filename); - } - - return $disposition.'; '.self::toString($params, ';'); - } - - private static function groupParts(array $matches, string $separators): array - { - $separator = $separators[0]; - $partSeparators = substr($separators, 1); - - $i = 0; - $partMatches = []; - foreach ($matches as $match) { - if (isset($match['separator']) && $match['separator'] === $separator) { - ++$i; - } else { - $partMatches[$i][] = $match; - } - } - - $parts = []; - if ($partSeparators) { - foreach ($partMatches as $matches) { - $parts[] = self::groupParts($matches, $partSeparators); - } - } else { - foreach ($partMatches as $matches) { - $parts[] = self::unquote($matches[0][0]); - } - } - - return $parts; - } -} diff --git a/vendor/symfony/http-foundation/IpUtils.php b/vendor/symfony/http-foundation/IpUtils.php deleted file mode 100644 index 80c5a95..0000000 --- a/vendor/symfony/http-foundation/IpUtils.php +++ /dev/null @@ -1,185 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Http utility functions. - * - * @author Fabien Potencier - */ -class IpUtils -{ - private static $checkedIps = []; - - /** - * This class should not be instantiated. - */ - private function __construct() - { - } - - /** - * Checks if an IPv4 or IPv6 address is contained in the list of given IPs or subnets. - * - * @param string|array $ips List of IPs or subnets (can be a string if only a single one) - * - * @return bool Whether the IP is valid - */ - public static function checkIp(?string $requestIp, $ips) - { - if (!\is_array($ips)) { - $ips = [$ips]; - } - - $method = substr_count($requestIp, ':') > 1 ? 'checkIp6' : 'checkIp4'; - - foreach ($ips as $ip) { - if (self::$method($requestIp, $ip)) { - return true; - } - } - - return false; - } - - /** - * Compares two IPv4 addresses. - * In case a subnet is given, it checks if it contains the request IP. - * - * @param string $ip IPv4 address or subnet in CIDR notation - * - * @return bool Whether the request IP matches the IP, or whether the request IP is within the CIDR subnet - */ - public static function checkIp4(?string $requestIp, string $ip) - { - $cacheKey = $requestIp.'-'.$ip; - if (isset(self::$checkedIps[$cacheKey])) { - return self::$checkedIps[$cacheKey]; - } - - if (!filter_var($requestIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { - return self::$checkedIps[$cacheKey] = false; - } - - if (false !== strpos($ip, '/')) { - list($address, $netmask) = explode('/', $ip, 2); - - if ('0' === $netmask) { - return self::$checkedIps[$cacheKey] = filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); - } - - if ($netmask < 0 || $netmask > 32) { - return self::$checkedIps[$cacheKey] = false; - } - } else { - $address = $ip; - $netmask = 32; - } - - if (false === ip2long($address)) { - return self::$checkedIps[$cacheKey] = false; - } - - return self::$checkedIps[$cacheKey] = 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); - } - - /** - * Compares two IPv6 addresses. - * In case a subnet is given, it checks if it contains the request IP. - * - * @author David Soria Parra - * - * @see https://github.com/dsp/v6tools - * - * @param string $ip IPv6 address or subnet in CIDR notation - * - * @return bool Whether the IP is valid - * - * @throws \RuntimeException When IPV6 support is not enabled - */ - public static function checkIp6(?string $requestIp, string $ip) - { - $cacheKey = $requestIp.'-'.$ip; - if (isset(self::$checkedIps[$cacheKey])) { - return self::$checkedIps[$cacheKey]; - } - - if (!((\extension_loaded('sockets') && \defined('AF_INET6')) || @inet_pton('::1'))) { - throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); - } - - if (false !== strpos($ip, '/')) { - list($address, $netmask) = explode('/', $ip, 2); - - if ('0' === $netmask) { - return (bool) unpack('n*', @inet_pton($address)); - } - - if ($netmask < 1 || $netmask > 128) { - return self::$checkedIps[$cacheKey] = false; - } - } else { - $address = $ip; - $netmask = 128; - } - - $bytesAddr = unpack('n*', @inet_pton($address)); - $bytesTest = unpack('n*', @inet_pton($requestIp)); - - if (!$bytesAddr || !$bytesTest) { - return self::$checkedIps[$cacheKey] = false; - } - - for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; ++$i) { - $left = $netmask - 16 * ($i - 1); - $left = ($left <= 16) ? $left : 16; - $mask = ~(0xffff >> $left) & 0xffff; - if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { - return self::$checkedIps[$cacheKey] = false; - } - } - - return self::$checkedIps[$cacheKey] = true; - } - - /** - * Anonymizes an IP/IPv6. - * - * Removes the last byte for v4 and the last 8 bytes for v6 IPs - */ - public static function anonymize(string $ip): string - { - $wrappedIPv6 = false; - if ('[' === substr($ip, 0, 1) && ']' === substr($ip, -1, 1)) { - $wrappedIPv6 = true; - $ip = substr($ip, 1, -1); - } - - $packedAddress = inet_pton($ip); - if (4 === \strlen($packedAddress)) { - $mask = '255.255.255.0'; - } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff:ffff'))) { - $mask = '::ffff:ffff:ff00'; - } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff'))) { - $mask = '::ffff:ff00'; - } else { - $mask = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000'; - } - $ip = inet_ntop($packedAddress & inet_pton($mask)); - - if ($wrappedIPv6) { - $ip = '['.$ip.']'; - } - - return $ip; - } -} diff --git a/vendor/symfony/http-foundation/JsonResponse.php b/vendor/symfony/http-foundation/JsonResponse.php deleted file mode 100644 index 8489bc0..0000000 --- a/vendor/symfony/http-foundation/JsonResponse.php +++ /dev/null @@ -1,215 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Response represents an HTTP response in JSON format. - * - * Note that this class does not force the returned JSON content to be an - * object. It is however recommended that you do return an object as it - * protects yourself against XSSI and JSON-JavaScript Hijacking. - * - * @see https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/AJAX_Security_Cheat_Sheet.md#always-return-json-with-an-object-on-the-outside - * - * @author Igor Wiedler - */ -class JsonResponse extends Response -{ - protected $data; - protected $callback; - - // Encode <, >, ', &, and " characters in the JSON, making it also safe to be embedded into HTML. - // 15 === JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT - const DEFAULT_ENCODING_OPTIONS = 15; - - protected $encodingOptions = self::DEFAULT_ENCODING_OPTIONS; - - /** - * @param mixed $data The response data - * @param int $status The response status code - * @param array $headers An array of response headers - * @param bool $json If the data is already a JSON string - */ - public function __construct($data = null, int $status = 200, array $headers = [], bool $json = false) - { - parent::__construct('', $status, $headers); - - if (null === $data) { - $data = new \ArrayObject(); - } - - $json ? $this->setJson($data) : $this->setData($data); - } - - /** - * Factory method for chainability. - * - * Example: - * - * return JsonResponse::create(['key' => 'value']) - * ->setSharedMaxAge(300); - * - * @param mixed $data The JSON response data - * @param int $status The response status code - * @param array $headers An array of response headers - * - * @return static - */ - public static function create($data = null, int $status = 200, array $headers = []) - { - return new static($data, $status, $headers); - } - - /** - * Factory method for chainability. - * - * Example: - * - * return JsonResponse::fromJsonString('{"key": "value"}') - * ->setSharedMaxAge(300); - * - * @param string|null $data The JSON response string - * @param int $status The response status code - * @param array $headers An array of response headers - * - * @return static - */ - public static function fromJsonString(string $data = null, int $status = 200, array $headers = []) - { - return new static($data, $status, $headers, true); - } - - /** - * Sets the JSONP callback. - * - * @param string|null $callback The JSONP callback or null to use none - * - * @return $this - * - * @throws \InvalidArgumentException When the callback name is not valid - */ - public function setCallback(string $callback = null) - { - if (null !== $callback) { - // partially taken from https://geekality.net/2011/08/03/valid-javascript-identifier/ - // partially taken from https://github.com/willdurand/JsonpCallbackValidator - // JsonpCallbackValidator is released under the MIT License. See https://github.com/willdurand/JsonpCallbackValidator/blob/v1.1.0/LICENSE for details. - // (c) William Durand - $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*(?:\[(?:"(?:\\\.|[^"\\\])*"|\'(?:\\\.|[^\'\\\])*\'|\d+)\])*?$/u'; - $reserved = [ - 'break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 'var', 'catch', 'finally', 'return', 'void', 'continue', 'for', 'switch', 'while', - 'debugger', 'function', 'this', 'with', 'default', 'if', 'throw', 'delete', 'in', 'try', 'class', 'enum', 'extends', 'super', 'const', 'export', - 'import', 'implements', 'let', 'private', 'public', 'yield', 'interface', 'package', 'protected', 'static', 'null', 'true', 'false', - ]; - $parts = explode('.', $callback); - foreach ($parts as $part) { - if (!preg_match($pattern, $part) || \in_array($part, $reserved, true)) { - throw new \InvalidArgumentException('The callback name is not valid.'); - } - } - } - - $this->callback = $callback; - - return $this->update(); - } - - /** - * Sets a raw string containing a JSON document to be sent. - * - * @return $this - * - * @throws \InvalidArgumentException - */ - public function setJson(string $json) - { - $this->data = $json; - - return $this->update(); - } - - /** - * Sets the data to be sent as JSON. - * - * @param mixed $data - * - * @return $this - * - * @throws \InvalidArgumentException - */ - public function setData($data = []) - { - try { - $data = json_encode($data, $this->encodingOptions); - } catch (\Exception $e) { - if ('Exception' === \get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) { - throw $e->getPrevious() ?: $e; - } - throw $e; - } - - if (\PHP_VERSION_ID >= 70300 && (JSON_THROW_ON_ERROR & $this->encodingOptions)) { - return $this->setJson($data); - } - - if (JSON_ERROR_NONE !== json_last_error()) { - throw new \InvalidArgumentException(json_last_error_msg()); - } - - return $this->setJson($data); - } - - /** - * Returns options used while encoding data to JSON. - * - * @return int - */ - public function getEncodingOptions() - { - return $this->encodingOptions; - } - - /** - * Sets options used while encoding data to JSON. - * - * @return $this - */ - public function setEncodingOptions(int $encodingOptions) - { - $this->encodingOptions = $encodingOptions; - - return $this->setData(json_decode($this->data)); - } - - /** - * Updates the content and headers according to the JSON data and callback. - * - * @return $this - */ - protected function update() - { - if (null !== $this->callback) { - // Not using application/javascript for compatibility reasons with older browsers. - $this->headers->set('Content-Type', 'text/javascript'); - - return $this->setContent(sprintf('/**/%s(%s);', $this->callback, $this->data)); - } - - // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback) - // in order to not overwrite a custom definition. - if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) { - $this->headers->set('Content-Type', 'application/json'); - } - - return $this->setContent($this->data); - } -} diff --git a/vendor/symfony/http-foundation/LICENSE b/vendor/symfony/http-foundation/LICENSE deleted file mode 100644 index a677f43..0000000 --- a/vendor/symfony/http-foundation/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/http-foundation/ParameterBag.php b/vendor/symfony/http-foundation/ParameterBag.php deleted file mode 100644 index 212149c..0000000 --- a/vendor/symfony/http-foundation/ParameterBag.php +++ /dev/null @@ -1,205 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * ParameterBag is a container for key/value pairs. - * - * @author Fabien Potencier - */ -class ParameterBag implements \IteratorAggregate, \Countable -{ - /** - * Parameter storage. - */ - protected $parameters; - - public function __construct(array $parameters = []) - { - $this->parameters = $parameters; - } - - /** - * Returns the parameters. - * - * @return array An array of parameters - */ - public function all() - { - return $this->parameters; - } - - /** - * Returns the parameter keys. - * - * @return array An array of parameter keys - */ - public function keys() - { - return array_keys($this->parameters); - } - - /** - * Replaces the current parameters by a new set. - */ - public function replace(array $parameters = []) - { - $this->parameters = $parameters; - } - - /** - * Adds parameters. - */ - public function add(array $parameters = []) - { - $this->parameters = array_replace($this->parameters, $parameters); - } - - /** - * Returns a parameter by name. - * - * @param mixed $default The default value if the parameter key does not exist - * - * @return mixed - */ - public function get(string $key, $default = null) - { - return \array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default; - } - - /** - * Sets a parameter by name. - * - * @param mixed $value The value - */ - public function set(string $key, $value) - { - $this->parameters[$key] = $value; - } - - /** - * Returns true if the parameter is defined. - * - * @return bool true if the parameter exists, false otherwise - */ - public function has(string $key) - { - return \array_key_exists($key, $this->parameters); - } - - /** - * Removes a parameter. - */ - public function remove(string $key) - { - unset($this->parameters[$key]); - } - - /** - * Returns the alphabetic characters of the parameter value. - * - * @return string The filtered value - */ - public function getAlpha(string $key, string $default = '') - { - return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default)); - } - - /** - * Returns the alphabetic characters and digits of the parameter value. - * - * @return string The filtered value - */ - public function getAlnum(string $key, string $default = '') - { - return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default)); - } - - /** - * Returns the digits of the parameter value. - * - * @return string The filtered value - */ - public function getDigits(string $key, string $default = '') - { - // we need to remove - and + because they're allowed in the filter - return str_replace(['-', '+'], '', $this->filter($key, $default, FILTER_SANITIZE_NUMBER_INT)); - } - - /** - * Returns the parameter value converted to integer. - * - * @return int The filtered value - */ - public function getInt(string $key, int $default = 0) - { - return (int) $this->get($key, $default); - } - - /** - * Returns the parameter value converted to boolean. - * - * @return bool The filtered value - */ - public function getBoolean(string $key, bool $default = false) - { - return $this->filter($key, $default, FILTER_VALIDATE_BOOLEAN); - } - - /** - * Filter key. - * - * @param mixed $default Default = null - * @param int $filter FILTER_* constant - * @param mixed $options Filter options - * - * @see https://php.net/filter-var - * - * @return mixed - */ - public function filter(string $key, $default = null, int $filter = FILTER_DEFAULT, $options = []) - { - $value = $this->get($key, $default); - - // Always turn $options into an array - this allows filter_var option shortcuts. - if (!\is_array($options) && $options) { - $options = ['flags' => $options]; - } - - // Add a convenience check for arrays. - if (\is_array($value) && !isset($options['flags'])) { - $options['flags'] = FILTER_REQUIRE_ARRAY; - } - - return filter_var($value, $filter, $options); - } - - /** - * Returns an iterator for parameters. - * - * @return \ArrayIterator An \ArrayIterator instance - */ - public function getIterator() - { - return new \ArrayIterator($this->parameters); - } - - /** - * Returns the number of parameters. - * - * @return int The number of parameters - */ - public function count() - { - return \count($this->parameters); - } -} diff --git a/vendor/symfony/http-foundation/README.md b/vendor/symfony/http-foundation/README.md deleted file mode 100644 index 8907f0b..0000000 --- a/vendor/symfony/http-foundation/README.md +++ /dev/null @@ -1,14 +0,0 @@ -HttpFoundation Component -======================== - -The HttpFoundation component defines an object-oriented layer for the HTTP -specification. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/http_foundation/index.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/http-foundation/RedirectResponse.php b/vendor/symfony/http-foundation/RedirectResponse.php deleted file mode 100644 index 13da56a..0000000 --- a/vendor/symfony/http-foundation/RedirectResponse.php +++ /dev/null @@ -1,105 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * RedirectResponse represents an HTTP response doing a redirect. - * - * @author Fabien Potencier - */ -class RedirectResponse extends Response -{ - protected $targetUrl; - - /** - * Creates a redirect response so that it conforms to the rules defined for a redirect status code. - * - * @param string $url The URL to redirect to. The URL should be a full URL, with schema etc., - * but practically every browser redirects on paths only as well - * @param int $status The status code (302 by default) - * @param array $headers The headers (Location is always set to the given URL) - * - * @throws \InvalidArgumentException - * - * @see https://tools.ietf.org/html/rfc2616#section-10.3 - */ - public function __construct(string $url, int $status = 302, array $headers = []) - { - parent::__construct('', $status, $headers); - - $this->setTargetUrl($url); - - if (!$this->isRedirect()) { - throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status)); - } - - if (301 == $status && !\array_key_exists('cache-control', array_change_key_case($headers, \CASE_LOWER))) { - $this->headers->remove('cache-control'); - } - } - - /** - * Factory method for chainability. - * - * @param string $url The URL to redirect to - * - * @return static - */ - public static function create($url = '', int $status = 302, array $headers = []) - { - return new static($url, $status, $headers); - } - - /** - * Returns the target URL. - * - * @return string target URL - */ - public function getTargetUrl() - { - return $this->targetUrl; - } - - /** - * Sets the redirect target of this response. - * - * @return $this - * - * @throws \InvalidArgumentException - */ - public function setTargetUrl(string $url) - { - if ('' === $url) { - throw new \InvalidArgumentException('Cannot redirect to an empty URL.'); - } - - $this->targetUrl = $url; - - $this->setContent( - sprintf(' - - - - - - Redirecting to %1$s - - - Redirecting to %1$s. - -', htmlspecialchars($url, ENT_QUOTES, 'UTF-8'))); - - $this->headers->set('Location', $url); - - return $this; - } -} diff --git a/vendor/symfony/http-foundation/Request.php b/vendor/symfony/http-foundation/Request.php deleted file mode 100644 index 21cb157..0000000 --- a/vendor/symfony/http-foundation/Request.php +++ /dev/null @@ -1,2057 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; -use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; -use Symfony\Component\HttpFoundation\Session\SessionInterface; - -/** - * Request represents an HTTP request. - * - * The methods dealing with URL accept / return a raw path (% encoded): - * * getBasePath - * * getBaseUrl - * * getPathInfo - * * getRequestUri - * * getUri - * * getUriForPath - * - * @author Fabien Potencier - */ -class Request -{ - const HEADER_FORWARDED = 0b00001; // When using RFC 7239 - const HEADER_X_FORWARDED_FOR = 0b00010; - const HEADER_X_FORWARDED_HOST = 0b00100; - const HEADER_X_FORWARDED_PROTO = 0b01000; - const HEADER_X_FORWARDED_PORT = 0b10000; - const HEADER_X_FORWARDED_ALL = 0b11110; // All "X-Forwarded-*" headers - const HEADER_X_FORWARDED_AWS_ELB = 0b11010; // AWS ELB doesn't send X-Forwarded-Host - - const METHOD_HEAD = 'HEAD'; - const METHOD_GET = 'GET'; - const METHOD_POST = 'POST'; - const METHOD_PUT = 'PUT'; - const METHOD_PATCH = 'PATCH'; - const METHOD_DELETE = 'DELETE'; - const METHOD_PURGE = 'PURGE'; - const METHOD_OPTIONS = 'OPTIONS'; - const METHOD_TRACE = 'TRACE'; - const METHOD_CONNECT = 'CONNECT'; - - /** - * @var string[] - */ - protected static $trustedProxies = []; - - /** - * @var string[] - */ - protected static $trustedHostPatterns = []; - - /** - * @var string[] - */ - protected static $trustedHosts = []; - - protected static $httpMethodParameterOverride = false; - - /** - * Custom parameters. - * - * @var ParameterBag - */ - public $attributes; - - /** - * Request body parameters ($_POST). - * - * @var ParameterBag - */ - public $request; - - /** - * Query string parameters ($_GET). - * - * @var ParameterBag - */ - public $query; - - /** - * Server and execution environment parameters ($_SERVER). - * - * @var ServerBag - */ - public $server; - - /** - * Uploaded files ($_FILES). - * - * @var FileBag - */ - public $files; - - /** - * Cookies ($_COOKIE). - * - * @var ParameterBag - */ - public $cookies; - - /** - * Headers (taken from the $_SERVER). - * - * @var HeaderBag - */ - public $headers; - - /** - * @var string|resource|false|null - */ - protected $content; - - /** - * @var array - */ - protected $languages; - - /** - * @var array - */ - protected $charsets; - - /** - * @var array - */ - protected $encodings; - - /** - * @var array - */ - protected $acceptableContentTypes; - - /** - * @var string - */ - protected $pathInfo; - - /** - * @var string - */ - protected $requestUri; - - /** - * @var string - */ - protected $baseUrl; - - /** - * @var string - */ - protected $basePath; - - /** - * @var string - */ - protected $method; - - /** - * @var string - */ - protected $format; - - /** - * @var SessionInterface - */ - protected $session; - - /** - * @var string - */ - protected $locale; - - /** - * @var string - */ - protected $defaultLocale = 'en'; - - /** - * @var array - */ - protected static $formats; - - protected static $requestFactory; - - /** - * @var string|null - */ - private $preferredFormat; - private $isHostValid = true; - private $isForwardedValid = true; - - private static $trustedHeaderSet = -1; - - private static $forwardedParams = [ - self::HEADER_X_FORWARDED_FOR => 'for', - self::HEADER_X_FORWARDED_HOST => 'host', - self::HEADER_X_FORWARDED_PROTO => 'proto', - self::HEADER_X_FORWARDED_PORT => 'host', - ]; - - /** - * Names for headers that can be trusted when - * using trusted proxies. - * - * The FORWARDED header is the standard as of rfc7239. - * - * The other headers are non-standard, but widely used - * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). - */ - private static $trustedHeaders = [ - self::HEADER_FORWARDED => 'FORWARDED', - self::HEADER_X_FORWARDED_FOR => 'X_FORWARDED_FOR', - self::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST', - self::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO', - self::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT', - ]; - - /** - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * @param string|resource|null $content The raw body data - */ - public function __construct(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) - { - $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content); - } - - /** - * Sets the parameters for this request. - * - * This method also re-initializes all properties. - * - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * @param string|resource|null $content The raw body data - */ - public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) - { - $this->request = new ParameterBag($request); - $this->query = new ParameterBag($query); - $this->attributes = new ParameterBag($attributes); - $this->cookies = new ParameterBag($cookies); - $this->files = new FileBag($files); - $this->server = new ServerBag($server); - $this->headers = new HeaderBag($this->server->getHeaders()); - - $this->content = $content; - $this->languages = null; - $this->charsets = null; - $this->encodings = null; - $this->acceptableContentTypes = null; - $this->pathInfo = null; - $this->requestUri = null; - $this->baseUrl = null; - $this->basePath = null; - $this->method = null; - $this->format = null; - } - - /** - * Creates a new request with values from PHP's super globals. - * - * @return static - */ - public static function createFromGlobals() - { - $request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER); - - if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded') - && \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'DELETE', 'PATCH']) - ) { - parse_str($request->getContent(), $data); - $request->request = new ParameterBag($data); - } - - return $request; - } - - /** - * Creates a Request based on a given URI and configuration. - * - * The information contained in the URI always take precedence - * over the other information (server and parameters). - * - * @param string $uri The URI - * @param string $method The HTTP method - * @param array $parameters The query (GET) or request (POST) parameters - * @param array $cookies The request cookies ($_COOKIE) - * @param array $files The request files ($_FILES) - * @param array $server The server parameters ($_SERVER) - * @param string|resource|null $content The raw body data - * - * @return static - */ - public static function create(string $uri, string $method = 'GET', array $parameters = [], array $cookies = [], array $files = [], array $server = [], $content = null) - { - $server = array_replace([ - 'SERVER_NAME' => 'localhost', - 'SERVER_PORT' => 80, - 'HTTP_HOST' => 'localhost', - 'HTTP_USER_AGENT' => 'Symfony', - 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', - 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5', - 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', - 'REMOTE_ADDR' => '127.0.0.1', - 'SCRIPT_NAME' => '', - 'SCRIPT_FILENAME' => '', - 'SERVER_PROTOCOL' => 'HTTP/1.1', - 'REQUEST_TIME' => time(), - ], $server); - - $server['PATH_INFO'] = ''; - $server['REQUEST_METHOD'] = strtoupper($method); - - $components = parse_url($uri); - if (isset($components['host'])) { - $server['SERVER_NAME'] = $components['host']; - $server['HTTP_HOST'] = $components['host']; - } - - if (isset($components['scheme'])) { - if ('https' === $components['scheme']) { - $server['HTTPS'] = 'on'; - $server['SERVER_PORT'] = 443; - } else { - unset($server['HTTPS']); - $server['SERVER_PORT'] = 80; - } - } - - if (isset($components['port'])) { - $server['SERVER_PORT'] = $components['port']; - $server['HTTP_HOST'] .= ':'.$components['port']; - } - - if (isset($components['user'])) { - $server['PHP_AUTH_USER'] = $components['user']; - } - - if (isset($components['pass'])) { - $server['PHP_AUTH_PW'] = $components['pass']; - } - - if (!isset($components['path'])) { - $components['path'] = '/'; - } - - switch (strtoupper($method)) { - case 'POST': - case 'PUT': - case 'DELETE': - if (!isset($server['CONTENT_TYPE'])) { - $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; - } - // no break - case 'PATCH': - $request = $parameters; - $query = []; - break; - default: - $request = []; - $query = $parameters; - break; - } - - $queryString = ''; - if (isset($components['query'])) { - parse_str(html_entity_decode($components['query']), $qs); - - if ($query) { - $query = array_replace($qs, $query); - $queryString = http_build_query($query, '', '&'); - } else { - $query = $qs; - $queryString = $components['query']; - } - } elseif ($query) { - $queryString = http_build_query($query, '', '&'); - } - - $server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : ''); - $server['QUERY_STRING'] = $queryString; - - return self::createRequestFromFactory($query, $request, [], $cookies, $files, $server, $content); - } - - /** - * Sets a callable able to create a Request instance. - * - * This is mainly useful when you need to override the Request class - * to keep BC with an existing system. It should not be used for any - * other purpose. - */ - public static function setFactory(?callable $callable) - { - self::$requestFactory = $callable; - } - - /** - * Clones a request and overrides some of its parameters. - * - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * - * @return static - */ - public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null) - { - $dup = clone $this; - if (null !== $query) { - $dup->query = new ParameterBag($query); - } - if (null !== $request) { - $dup->request = new ParameterBag($request); - } - if (null !== $attributes) { - $dup->attributes = new ParameterBag($attributes); - } - if (null !== $cookies) { - $dup->cookies = new ParameterBag($cookies); - } - if (null !== $files) { - $dup->files = new FileBag($files); - } - if (null !== $server) { - $dup->server = new ServerBag($server); - $dup->headers = new HeaderBag($dup->server->getHeaders()); - } - $dup->languages = null; - $dup->charsets = null; - $dup->encodings = null; - $dup->acceptableContentTypes = null; - $dup->pathInfo = null; - $dup->requestUri = null; - $dup->baseUrl = null; - $dup->basePath = null; - $dup->method = null; - $dup->format = null; - - if (!$dup->get('_format') && $this->get('_format')) { - $dup->attributes->set('_format', $this->get('_format')); - } - - if (!$dup->getRequestFormat(null)) { - $dup->setRequestFormat($this->getRequestFormat(null)); - } - - return $dup; - } - - /** - * Clones the current request. - * - * Note that the session is not cloned as duplicated requests - * are most of the time sub-requests of the main one. - */ - public function __clone() - { - $this->query = clone $this->query; - $this->request = clone $this->request; - $this->attributes = clone $this->attributes; - $this->cookies = clone $this->cookies; - $this->files = clone $this->files; - $this->server = clone $this->server; - $this->headers = clone $this->headers; - } - - /** - * Returns the request as a string. - * - * @return string The request - */ - public function __toString() - { - try { - $content = $this->getContent(); - } catch (\LogicException $e) { - if (\PHP_VERSION_ID >= 70400) { - throw $e; - } - - return trigger_error($e, E_USER_ERROR); - } - - $cookieHeader = ''; - $cookies = []; - - foreach ($this->cookies as $k => $v) { - $cookies[] = $k.'='.$v; - } - - if (!empty($cookies)) { - $cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n"; - } - - return - sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n". - $this->headers. - $cookieHeader."\r\n". - $content; - } - - /** - * Overrides the PHP global variables according to this request instance. - * - * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE. - * $_FILES is never overridden, see rfc1867 - */ - public function overrideGlobals() - { - $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), '', '&'))); - - $_GET = $this->query->all(); - $_POST = $this->request->all(); - $_SERVER = $this->server->all(); - $_COOKIE = $this->cookies->all(); - - foreach ($this->headers->all() as $key => $value) { - $key = strtoupper(str_replace('-', '_', $key)); - if (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) { - $_SERVER[$key] = implode(', ', $value); - } else { - $_SERVER['HTTP_'.$key] = implode(', ', $value); - } - } - - $request = ['g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE]; - - $requestOrder = ini_get('request_order') ?: ini_get('variables_order'); - $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp'; - - $_REQUEST = [[]]; - - foreach (str_split($requestOrder) as $order) { - $_REQUEST[] = $request[$order]; - } - - $_REQUEST = array_merge(...$_REQUEST); - } - - /** - * Sets a list of trusted proxies. - * - * You should only list the reverse proxies that you manage directly. - * - * @param array $proxies A list of trusted proxies, the string 'REMOTE_ADDR' will be replaced with $_SERVER['REMOTE_ADDR'] - * @param int $trustedHeaderSet A bit field of Request::HEADER_*, to set which headers to trust from your proxies - * - * @throws \InvalidArgumentException When $trustedHeaderSet is invalid - */ - public static function setTrustedProxies(array $proxies, int $trustedHeaderSet) - { - self::$trustedProxies = array_reduce($proxies, function ($proxies, $proxy) { - if ('REMOTE_ADDR' !== $proxy) { - $proxies[] = $proxy; - } elseif (isset($_SERVER['REMOTE_ADDR'])) { - $proxies[] = $_SERVER['REMOTE_ADDR']; - } - - return $proxies; - }, []); - self::$trustedHeaderSet = $trustedHeaderSet; - } - - /** - * Gets the list of trusted proxies. - * - * @return array An array of trusted proxies - */ - public static function getTrustedProxies() - { - return self::$trustedProxies; - } - - /** - * Gets the set of trusted headers from trusted proxies. - * - * @return int A bit field of Request::HEADER_* that defines which headers are trusted from your proxies - */ - public static function getTrustedHeaderSet() - { - return self::$trustedHeaderSet; - } - - /** - * Sets a list of trusted host patterns. - * - * You should only list the hosts you manage using regexs. - * - * @param array $hostPatterns A list of trusted host patterns - */ - public static function setTrustedHosts(array $hostPatterns) - { - self::$trustedHostPatterns = array_map(function ($hostPattern) { - return sprintf('{%s}i', $hostPattern); - }, $hostPatterns); - // we need to reset trusted hosts on trusted host patterns change - self::$trustedHosts = []; - } - - /** - * Gets the list of trusted host patterns. - * - * @return array An array of trusted host patterns - */ - public static function getTrustedHosts() - { - return self::$trustedHostPatterns; - } - - /** - * Normalizes a query string. - * - * It builds a normalized query string, where keys/value pairs are alphabetized, - * have consistent escaping and unneeded delimiters are removed. - * - * @return string A normalized query string for the Request - */ - public static function normalizeQueryString(?string $qs) - { - if ('' === ($qs ?? '')) { - return ''; - } - - parse_str($qs, $qs); - ksort($qs); - - return http_build_query($qs, '', '&', PHP_QUERY_RFC3986); - } - - /** - * Enables support for the _method request parameter to determine the intended HTTP method. - * - * Be warned that enabling this feature might lead to CSRF issues in your code. - * Check that you are using CSRF tokens when required. - * If the HTTP method parameter override is enabled, an html-form with method "POST" can be altered - * and used to send a "PUT" or "DELETE" request via the _method request parameter. - * If these methods are not protected against CSRF, this presents a possible vulnerability. - * - * The HTTP method can only be overridden when the real HTTP method is POST. - */ - public static function enableHttpMethodParameterOverride() - { - self::$httpMethodParameterOverride = true; - } - - /** - * Checks whether support for the _method request parameter is enabled. - * - * @return bool True when the _method request parameter is enabled, false otherwise - */ - public static function getHttpMethodParameterOverride() - { - return self::$httpMethodParameterOverride; - } - - /** - * Gets a "parameter" value from any bag. - * - * This method is mainly useful for libraries that want to provide some flexibility. If you don't need the - * flexibility in controllers, it is better to explicitly get request parameters from the appropriate - * public property instead (attributes, query, request). - * - * Order of precedence: PATH (routing placeholders or custom attributes), GET, BODY - * - * @param mixed $default The default value if the parameter key does not exist - * - * @return mixed - */ - public function get(string $key, $default = null) - { - if ($this !== $result = $this->attributes->get($key, $this)) { - return $result; - } - - if ($this !== $result = $this->query->get($key, $this)) { - return $result; - } - - if ($this !== $result = $this->request->get($key, $this)) { - return $result; - } - - return $default; - } - - /** - * Gets the Session. - * - * @return SessionInterface The session - */ - public function getSession() - { - $session = $this->session; - if (!$session instanceof SessionInterface && null !== $session) { - $this->setSession($session = $session()); - } - - if (null === $session) { - throw new \BadMethodCallException('Session has not been set.'); - } - - return $session; - } - - /** - * Whether the request contains a Session which was started in one of the - * previous requests. - * - * @return bool - */ - public function hasPreviousSession() - { - // the check for $this->session avoids malicious users trying to fake a session cookie with proper name - return $this->hasSession() && $this->cookies->has($this->getSession()->getName()); - } - - /** - * Whether the request contains a Session object. - * - * This method does not give any information about the state of the session object, - * like whether the session is started or not. It is just a way to check if this Request - * is associated with a Session instance. - * - * @return bool true when the Request contains a Session object, false otherwise - */ - public function hasSession() - { - return null !== $this->session; - } - - public function setSession(SessionInterface $session) - { - $this->session = $session; - } - - /** - * @internal - */ - public function setSessionFactory(callable $factory) - { - $this->session = $factory; - } - - /** - * Returns the client IP addresses. - * - * In the returned array the most trusted IP address is first, and the - * least trusted one last. The "real" client IP address is the last one, - * but this is also the least trusted one. Trusted proxies are stripped. - * - * Use this method carefully; you should use getClientIp() instead. - * - * @return array The client IP addresses - * - * @see getClientIp() - */ - public function getClientIps() - { - $ip = $this->server->get('REMOTE_ADDR'); - - if (!$this->isFromTrustedProxy()) { - return [$ip]; - } - - return $this->getTrustedValues(self::HEADER_X_FORWARDED_FOR, $ip) ?: [$ip]; - } - - /** - * Returns the client IP address. - * - * This method can read the client IP address from the "X-Forwarded-For" header - * when trusted proxies were set via "setTrustedProxies()". The "X-Forwarded-For" - * header value is a comma+space separated list of IP addresses, the left-most - * being the original client, and each successive proxy that passed the request - * adding the IP address where it received the request from. - * - * If your reverse proxy uses a different header name than "X-Forwarded-For", - * ("Client-Ip" for instance), configure it via the $trustedHeaderSet - * argument of the Request::setTrustedProxies() method instead. - * - * @return string|null The client IP address - * - * @see getClientIps() - * @see https://wikipedia.org/wiki/X-Forwarded-For - */ - public function getClientIp() - { - $ipAddresses = $this->getClientIps(); - - return $ipAddresses[0]; - } - - /** - * Returns current script name. - * - * @return string - */ - public function getScriptName() - { - return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', '')); - } - - /** - * Returns the path being requested relative to the executed script. - * - * The path info always starts with a /. - * - * Suppose this request is instantiated from /mysite on localhost: - * - * * http://localhost/mysite returns an empty string - * * http://localhost/mysite/about returns '/about' - * * http://localhost/mysite/enco%20ded returns '/enco%20ded' - * * http://localhost/mysite/about?var=1 returns '/about' - * - * @return string The raw path (i.e. not urldecoded) - */ - public function getPathInfo() - { - if (null === $this->pathInfo) { - $this->pathInfo = $this->preparePathInfo(); - } - - return $this->pathInfo; - } - - /** - * Returns the root path from which this request is executed. - * - * Suppose that an index.php file instantiates this request object: - * - * * http://localhost/index.php returns an empty string - * * http://localhost/index.php/page returns an empty string - * * http://localhost/web/index.php returns '/web' - * * http://localhost/we%20b/index.php returns '/we%20b' - * - * @return string The raw path (i.e. not urldecoded) - */ - public function getBasePath() - { - if (null === $this->basePath) { - $this->basePath = $this->prepareBasePath(); - } - - return $this->basePath; - } - - /** - * Returns the root URL from which this request is executed. - * - * The base URL never ends with a /. - * - * This is similar to getBasePath(), except that it also includes the - * script filename (e.g. index.php) if one exists. - * - * @return string The raw URL (i.e. not urldecoded) - */ - public function getBaseUrl() - { - if (null === $this->baseUrl) { - $this->baseUrl = $this->prepareBaseUrl(); - } - - return $this->baseUrl; - } - - /** - * Gets the request's scheme. - * - * @return string - */ - public function getScheme() - { - return $this->isSecure() ? 'https' : 'http'; - } - - /** - * Returns the port on which the request is made. - * - * This method can read the client port from the "X-Forwarded-Port" header - * when trusted proxies were set via "setTrustedProxies()". - * - * The "X-Forwarded-Port" header must contain the client port. - * - * @return int|string can be a string if fetched from the server bag - */ - public function getPort() - { - if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_PORT)) { - $host = $host[0]; - } elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { - $host = $host[0]; - } elseif (!$host = $this->headers->get('HOST')) { - return $this->server->get('SERVER_PORT'); - } - - if ('[' === $host[0]) { - $pos = strpos($host, ':', strrpos($host, ']')); - } else { - $pos = strrpos($host, ':'); - } - - if (false !== $pos && $port = substr($host, $pos + 1)) { - return (int) $port; - } - - return 'https' === $this->getScheme() ? 443 : 80; - } - - /** - * Returns the user. - * - * @return string|null - */ - public function getUser() - { - return $this->headers->get('PHP_AUTH_USER'); - } - - /** - * Returns the password. - * - * @return string|null - */ - public function getPassword() - { - return $this->headers->get('PHP_AUTH_PW'); - } - - /** - * Gets the user info. - * - * @return string A user name and, optionally, scheme-specific information about how to gain authorization to access the server - */ - public function getUserInfo() - { - $userinfo = $this->getUser(); - - $pass = $this->getPassword(); - if ('' != $pass) { - $userinfo .= ":$pass"; - } - - return $userinfo; - } - - /** - * Returns the HTTP host being requested. - * - * The port name will be appended to the host if it's non-standard. - * - * @return string - */ - public function getHttpHost() - { - $scheme = $this->getScheme(); - $port = $this->getPort(); - - if (('http' == $scheme && 80 == $port) || ('https' == $scheme && 443 == $port)) { - return $this->getHost(); - } - - return $this->getHost().':'.$port; - } - - /** - * Returns the requested URI (path and query string). - * - * @return string The raw URI (i.e. not URI decoded) - */ - public function getRequestUri() - { - if (null === $this->requestUri) { - $this->requestUri = $this->prepareRequestUri(); - } - - return $this->requestUri; - } - - /** - * Gets the scheme and HTTP host. - * - * If the URL was called with basic authentication, the user - * and the password are not added to the generated string. - * - * @return string The scheme and HTTP host - */ - public function getSchemeAndHttpHost() - { - return $this->getScheme().'://'.$this->getHttpHost(); - } - - /** - * Generates a normalized URI (URL) for the Request. - * - * @return string A normalized URI (URL) for the Request - * - * @see getQueryString() - */ - public function getUri() - { - if (null !== $qs = $this->getQueryString()) { - $qs = '?'.$qs; - } - - return $this->getSchemeAndHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs; - } - - /** - * Generates a normalized URI for the given path. - * - * @param string $path A path to use instead of the current one - * - * @return string The normalized URI for the path - */ - public function getUriForPath(string $path) - { - return $this->getSchemeAndHttpHost().$this->getBaseUrl().$path; - } - - /** - * Returns the path as relative reference from the current Request path. - * - * Only the URIs path component (no schema, host etc.) is relevant and must be given. - * Both paths must be absolute and not contain relative parts. - * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. - * Furthermore, they can be used to reduce the link size in documents. - * - * Example target paths, given a base path of "/a/b/c/d": - * - "/a/b/c/d" -> "" - * - "/a/b/c/" -> "./" - * - "/a/b/" -> "../" - * - "/a/b/c/other" -> "other" - * - "/a/x/y" -> "../../x/y" - * - * @return string The relative target path - */ - public function getRelativeUriForPath(string $path) - { - // be sure that we are dealing with an absolute path - if (!isset($path[0]) || '/' !== $path[0]) { - return $path; - } - - if ($path === $basePath = $this->getPathInfo()) { - return ''; - } - - $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); - $targetDirs = explode('/', substr($path, 1)); - array_pop($sourceDirs); - $targetFile = array_pop($targetDirs); - - foreach ($sourceDirs as $i => $dir) { - if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { - unset($sourceDirs[$i], $targetDirs[$i]); - } else { - break; - } - } - - $targetDirs[] = $targetFile; - $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs); - - // A reference to the same base directory or an empty subdirectory must be prefixed with "./". - // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used - // as the first segment of a relative-path reference, as it would be mistaken for a scheme name - // (see https://tools.ietf.org/html/rfc3986#section-4.2). - return !isset($path[0]) || '/' === $path[0] - || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) - ? "./$path" : $path; - } - - /** - * Generates the normalized query string for the Request. - * - * It builds a normalized query string, where keys/value pairs are alphabetized - * and have consistent escaping. - * - * @return string|null A normalized query string for the Request - */ - public function getQueryString() - { - $qs = static::normalizeQueryString($this->server->get('QUERY_STRING')); - - return '' === $qs ? null : $qs; - } - - /** - * Checks whether the request is secure or not. - * - * This method can read the client protocol from the "X-Forwarded-Proto" header - * when trusted proxies were set via "setTrustedProxies()". - * - * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http". - * - * @return bool - */ - public function isSecure() - { - if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) { - return \in_array(strtolower($proto[0]), ['https', 'on', 'ssl', '1'], true); - } - - $https = $this->server->get('HTTPS'); - - return !empty($https) && 'off' !== strtolower($https); - } - - /** - * Returns the host name. - * - * This method can read the client host name from the "X-Forwarded-Host" header - * when trusted proxies were set via "setTrustedProxies()". - * - * The "X-Forwarded-Host" header must contain the client host name. - * - * @return string - * - * @throws SuspiciousOperationException when the host name is invalid or not trusted - */ - public function getHost() - { - if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { - $host = $host[0]; - } elseif (!$host = $this->headers->get('HOST')) { - if (!$host = $this->server->get('SERVER_NAME')) { - $host = $this->server->get('SERVER_ADDR', ''); - } - } - - // trim and remove port number from host - // host is lowercase as per RFC 952/2181 - $host = strtolower(preg_replace('/:\d+$/', '', trim($host))); - - // as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user) - // check that it does not contain forbidden characters (see RFC 952 and RFC 2181) - // use preg_replace() instead of preg_match() to prevent DoS attacks with long host names - if ($host && '' !== preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host)) { - if (!$this->isHostValid) { - return ''; - } - $this->isHostValid = false; - - throw new SuspiciousOperationException(sprintf('Invalid Host "%s".', $host)); - } - - if (\count(self::$trustedHostPatterns) > 0) { - // to avoid host header injection attacks, you should provide a list of trusted host patterns - - if (\in_array($host, self::$trustedHosts)) { - return $host; - } - - foreach (self::$trustedHostPatterns as $pattern) { - if (preg_match($pattern, $host)) { - self::$trustedHosts[] = $host; - - return $host; - } - } - - if (!$this->isHostValid) { - return ''; - } - $this->isHostValid = false; - - throw new SuspiciousOperationException(sprintf('Untrusted Host "%s".', $host)); - } - - return $host; - } - - /** - * Sets the request method. - */ - public function setMethod(string $method) - { - $this->method = null; - $this->server->set('REQUEST_METHOD', $method); - } - - /** - * Gets the request "intended" method. - * - * If the X-HTTP-Method-Override header is set, and if the method is a POST, - * then it is used to determine the "real" intended HTTP method. - * - * The _method request parameter can also be used to determine the HTTP method, - * but only if enableHttpMethodParameterOverride() has been called. - * - * The method is always an uppercased string. - * - * @return string The request method - * - * @see getRealMethod() - */ - public function getMethod() - { - if (null !== $this->method) { - return $this->method; - } - - $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET')); - - if ('POST' !== $this->method) { - return $this->method; - } - - $method = $this->headers->get('X-HTTP-METHOD-OVERRIDE'); - - if (!$method && self::$httpMethodParameterOverride) { - $method = $this->request->get('_method', $this->query->get('_method', 'POST')); - } - - if (!\is_string($method)) { - return $this->method; - } - - $method = strtoupper($method); - - if (\in_array($method, ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'PATCH', 'PURGE', 'TRACE'], true)) { - return $this->method = $method; - } - - if (!preg_match('/^[A-Z]++$/D', $method)) { - throw new SuspiciousOperationException(sprintf('Invalid method override "%s".', $method)); - } - - return $this->method = $method; - } - - /** - * Gets the "real" request method. - * - * @return string The request method - * - * @see getMethod() - */ - public function getRealMethod() - { - return strtoupper($this->server->get('REQUEST_METHOD', 'GET')); - } - - /** - * Gets the mime type associated with the format. - * - * @return string|null The associated mime type (null if not found) - */ - public function getMimeType(string $format) - { - if (null === static::$formats) { - static::initializeFormats(); - } - - return isset(static::$formats[$format]) ? static::$formats[$format][0] : null; - } - - /** - * Gets the mime types associated with the format. - * - * @return array The associated mime types - */ - public static function getMimeTypes(string $format) - { - if (null === static::$formats) { - static::initializeFormats(); - } - - return isset(static::$formats[$format]) ? static::$formats[$format] : []; - } - - /** - * Gets the format associated with the mime type. - * - * @return string|null The format (null if not found) - */ - public function getFormat(?string $mimeType) - { - $canonicalMimeType = null; - if (false !== $pos = strpos($mimeType, ';')) { - $canonicalMimeType = trim(substr($mimeType, 0, $pos)); - } - - if (null === static::$formats) { - static::initializeFormats(); - } - - foreach (static::$formats as $format => $mimeTypes) { - if (\in_array($mimeType, (array) $mimeTypes)) { - return $format; - } - if (null !== $canonicalMimeType && \in_array($canonicalMimeType, (array) $mimeTypes)) { - return $format; - } - } - - return null; - } - - /** - * Associates a format with mime types. - * - * @param string|array $mimeTypes The associated mime types (the preferred one must be the first as it will be used as the content type) - */ - public function setFormat(?string $format, $mimeTypes) - { - if (null === static::$formats) { - static::initializeFormats(); - } - - static::$formats[$format] = \is_array($mimeTypes) ? $mimeTypes : [$mimeTypes]; - } - - /** - * Gets the request format. - * - * Here is the process to determine the format: - * - * * format defined by the user (with setRequestFormat()) - * * _format request attribute - * * $default - * - * @see getPreferredFormat - * - * @return string|null The request format - */ - public function getRequestFormat(?string $default = 'html') - { - if (null === $this->format) { - $this->format = $this->attributes->get('_format'); - } - - return null === $this->format ? $default : $this->format; - } - - /** - * Sets the request format. - */ - public function setRequestFormat(?string $format) - { - $this->format = $format; - } - - /** - * Gets the format associated with the request. - * - * @return string|null The format (null if no content type is present) - */ - public function getContentType() - { - return $this->getFormat($this->headers->get('CONTENT_TYPE')); - } - - /** - * Sets the default locale. - */ - public function setDefaultLocale(string $locale) - { - $this->defaultLocale = $locale; - - if (null === $this->locale) { - $this->setPhpDefaultLocale($locale); - } - } - - /** - * Get the default locale. - * - * @return string - */ - public function getDefaultLocale() - { - return $this->defaultLocale; - } - - /** - * Sets the locale. - */ - public function setLocale(string $locale) - { - $this->setPhpDefaultLocale($this->locale = $locale); - } - - /** - * Get the locale. - * - * @return string - */ - public function getLocale() - { - return null === $this->locale ? $this->defaultLocale : $this->locale; - } - - /** - * Checks if the request method is of specified type. - * - * @param string $method Uppercase request method (GET, POST etc) - * - * @return bool - */ - public function isMethod(string $method) - { - return $this->getMethod() === strtoupper($method); - } - - /** - * Checks whether or not the method is safe. - * - * @see https://tools.ietf.org/html/rfc7231#section-4.2.1 - * - * @return bool - */ - public function isMethodSafe() - { - return \in_array($this->getMethod(), ['GET', 'HEAD', 'OPTIONS', 'TRACE']); - } - - /** - * Checks whether or not the method is idempotent. - * - * @return bool - */ - public function isMethodIdempotent() - { - return \in_array($this->getMethod(), ['HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE']); - } - - /** - * Checks whether the method is cacheable or not. - * - * @see https://tools.ietf.org/html/rfc7231#section-4.2.3 - * - * @return bool True for GET and HEAD, false otherwise - */ - public function isMethodCacheable() - { - return \in_array($this->getMethod(), ['GET', 'HEAD']); - } - - /** - * Returns the protocol version. - * - * If the application is behind a proxy, the protocol version used in the - * requests between the client and the proxy and between the proxy and the - * server might be different. This returns the former (from the "Via" header) - * if the proxy is trusted (see "setTrustedProxies()"), otherwise it returns - * the latter (from the "SERVER_PROTOCOL" server parameter). - * - * @return string - */ - public function getProtocolVersion() - { - if ($this->isFromTrustedProxy()) { - preg_match('~^(HTTP/)?([1-9]\.[0-9]) ~', $this->headers->get('Via'), $matches); - - if ($matches) { - return 'HTTP/'.$matches[2]; - } - } - - return $this->server->get('SERVER_PROTOCOL'); - } - - /** - * Returns the request body content. - * - * @param bool $asResource If true, a resource will be returned - * - * @return string|resource The request body content or a resource to read the body stream - * - * @throws \LogicException - */ - public function getContent(bool $asResource = false) - { - $currentContentIsResource = \is_resource($this->content); - - if (true === $asResource) { - if ($currentContentIsResource) { - rewind($this->content); - - return $this->content; - } - - // Content passed in parameter (test) - if (\is_string($this->content)) { - $resource = fopen('php://temp', 'r+'); - fwrite($resource, $this->content); - rewind($resource); - - return $resource; - } - - $this->content = false; - - return fopen('php://input', 'rb'); - } - - if ($currentContentIsResource) { - rewind($this->content); - - return stream_get_contents($this->content); - } - - if (null === $this->content || false === $this->content) { - $this->content = file_get_contents('php://input'); - } - - return $this->content; - } - - /** - * Gets the Etags. - * - * @return array The entity tags - */ - public function getETags() - { - return preg_split('/\s*,\s*/', $this->headers->get('if_none_match'), null, PREG_SPLIT_NO_EMPTY); - } - - /** - * @return bool - */ - public function isNoCache() - { - return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma'); - } - - /** - * Gets the preferred format for the response by inspecting, in the following order: - * * the request format set using setRequestFormat - * * the values of the Accept HTTP header - * * the content type of the body of the request. - */ - public function getPreferredFormat(?string $default = 'html'): ?string - { - if (null !== $this->preferredFormat || null !== $this->preferredFormat = $this->getRequestFormat(null)) { - return $this->preferredFormat; - } - - foreach ($this->getAcceptableContentTypes() as $mimeType) { - if ($this->preferredFormat = $this->getFormat($mimeType)) { - return $this->preferredFormat; - } - } - - return $default; - } - - /** - * Returns the preferred language. - * - * @param string[] $locales An array of ordered available locales - * - * @return string|null The preferred locale - */ - public function getPreferredLanguage(array $locales = null) - { - $preferredLanguages = $this->getLanguages(); - - if (empty($locales)) { - return isset($preferredLanguages[0]) ? $preferredLanguages[0] : null; - } - - if (!$preferredLanguages) { - return $locales[0]; - } - - $extendedPreferredLanguages = []; - foreach ($preferredLanguages as $language) { - $extendedPreferredLanguages[] = $language; - if (false !== $position = strpos($language, '_')) { - $superLanguage = substr($language, 0, $position); - if (!\in_array($superLanguage, $preferredLanguages)) { - $extendedPreferredLanguages[] = $superLanguage; - } - } - } - - $preferredLanguages = array_values(array_intersect($extendedPreferredLanguages, $locales)); - - return isset($preferredLanguages[0]) ? $preferredLanguages[0] : $locales[0]; - } - - /** - * Gets a list of languages acceptable by the client browser. - * - * @return array Languages ordered in the user browser preferences - */ - public function getLanguages() - { - if (null !== $this->languages) { - return $this->languages; - } - - $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all(); - $this->languages = []; - foreach ($languages as $lang => $acceptHeaderItem) { - if (false !== strpos($lang, '-')) { - $codes = explode('-', $lang); - if ('i' === $codes[0]) { - // Language not listed in ISO 639 that are not variants - // of any listed language, which can be registered with the - // i-prefix, such as i-cherokee - if (\count($codes) > 1) { - $lang = $codes[1]; - } - } else { - for ($i = 0, $max = \count($codes); $i < $max; ++$i) { - if (0 === $i) { - $lang = strtolower($codes[0]); - } else { - $lang .= '_'.strtoupper($codes[$i]); - } - } - } - } - - $this->languages[] = $lang; - } - - return $this->languages; - } - - /** - * Gets a list of charsets acceptable by the client browser. - * - * @return array List of charsets in preferable order - */ - public function getCharsets() - { - if (null !== $this->charsets) { - return $this->charsets; - } - - return $this->charsets = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all()); - } - - /** - * Gets a list of encodings acceptable by the client browser. - * - * @return array List of encodings in preferable order - */ - public function getEncodings() - { - if (null !== $this->encodings) { - return $this->encodings; - } - - return $this->encodings = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all()); - } - - /** - * Gets a list of content types acceptable by the client browser. - * - * @return array List of content types in preferable order - */ - public function getAcceptableContentTypes() - { - if (null !== $this->acceptableContentTypes) { - return $this->acceptableContentTypes; - } - - return $this->acceptableContentTypes = array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all()); - } - - /** - * Returns true if the request is a XMLHttpRequest. - * - * It works if your JavaScript library sets an X-Requested-With HTTP header. - * It is known to work with common JavaScript frameworks: - * - * @see https://wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript - * - * @return bool true if the request is an XMLHttpRequest, false otherwise - */ - public function isXmlHttpRequest() - { - return 'XMLHttpRequest' == $this->headers->get('X-Requested-With'); - } - - /* - * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24) - * - * Code subject to the new BSD license (https://framework.zend.com/license). - * - * Copyright (c) 2005-2010 Zend Technologies USA Inc. (https://www.zend.com/) - */ - - protected function prepareRequestUri() - { - $requestUri = ''; - - if ('1' == $this->server->get('IIS_WasUrlRewritten') && '' != $this->server->get('UNENCODED_URL')) { - // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem) - $requestUri = $this->server->get('UNENCODED_URL'); - $this->server->remove('UNENCODED_URL'); - $this->server->remove('IIS_WasUrlRewritten'); - } elseif ($this->server->has('REQUEST_URI')) { - $requestUri = $this->server->get('REQUEST_URI'); - - if ('' !== $requestUri && '/' === $requestUri[0]) { - // To only use path and query remove the fragment. - if (false !== $pos = strpos($requestUri, '#')) { - $requestUri = substr($requestUri, 0, $pos); - } - } else { - // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, - // only use URL path. - $uriComponents = parse_url($requestUri); - - if (isset($uriComponents['path'])) { - $requestUri = $uriComponents['path']; - } - - if (isset($uriComponents['query'])) { - $requestUri .= '?'.$uriComponents['query']; - } - } - } elseif ($this->server->has('ORIG_PATH_INFO')) { - // IIS 5.0, PHP as CGI - $requestUri = $this->server->get('ORIG_PATH_INFO'); - if ('' != $this->server->get('QUERY_STRING')) { - $requestUri .= '?'.$this->server->get('QUERY_STRING'); - } - $this->server->remove('ORIG_PATH_INFO'); - } - - // normalize the request URI to ease creating sub-requests from this request - $this->server->set('REQUEST_URI', $requestUri); - - return $requestUri; - } - - /** - * Prepares the base URL. - * - * @return string - */ - protected function prepareBaseUrl() - { - $filename = basename($this->server->get('SCRIPT_FILENAME')); - - if (basename($this->server->get('SCRIPT_NAME')) === $filename) { - $baseUrl = $this->server->get('SCRIPT_NAME'); - } elseif (basename($this->server->get('PHP_SELF')) === $filename) { - $baseUrl = $this->server->get('PHP_SELF'); - } elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) { - $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility - } else { - // Backtrack up the script_filename to find the portion matching - // php_self - $path = $this->server->get('PHP_SELF', ''); - $file = $this->server->get('SCRIPT_FILENAME', ''); - $segs = explode('/', trim($file, '/')); - $segs = array_reverse($segs); - $index = 0; - $last = \count($segs); - $baseUrl = ''; - do { - $seg = $segs[$index]; - $baseUrl = '/'.$seg.$baseUrl; - ++$index; - } while ($last > $index && (false !== $pos = strpos($path, $baseUrl)) && 0 != $pos); - } - - // Does the baseUrl have anything in common with the request_uri? - $requestUri = $this->getRequestUri(); - if ('' !== $requestUri && '/' !== $requestUri[0]) { - $requestUri = '/'.$requestUri; - } - - if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) { - // full $baseUrl matches - return $prefix; - } - - if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(\dirname($baseUrl), '/'.\DIRECTORY_SEPARATOR).'/')) { - // directory portion of $baseUrl matches - return rtrim($prefix, '/'.\DIRECTORY_SEPARATOR); - } - - $truncatedRequestUri = $requestUri; - if (false !== $pos = strpos($requestUri, '?')) { - $truncatedRequestUri = substr($requestUri, 0, $pos); - } - - $basename = basename($baseUrl); - if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) { - // no match whatsoever; set it blank - return ''; - } - - // If using mod_rewrite or ISAPI_Rewrite strip the script filename - // out of baseUrl. $pos !== 0 makes sure it is not matching a value - // from PATH_INFO or QUERY_STRING - if (\strlen($requestUri) >= \strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && 0 !== $pos) { - $baseUrl = substr($requestUri, 0, $pos + \strlen($baseUrl)); - } - - return rtrim($baseUrl, '/'.\DIRECTORY_SEPARATOR); - } - - /** - * Prepares the base path. - * - * @return string base path - */ - protected function prepareBasePath() - { - $baseUrl = $this->getBaseUrl(); - if (empty($baseUrl)) { - return ''; - } - - $filename = basename($this->server->get('SCRIPT_FILENAME')); - if (basename($baseUrl) === $filename) { - $basePath = \dirname($baseUrl); - } else { - $basePath = $baseUrl; - } - - if ('\\' === \DIRECTORY_SEPARATOR) { - $basePath = str_replace('\\', '/', $basePath); - } - - return rtrim($basePath, '/'); - } - - /** - * Prepares the path info. - * - * @return string path info - */ - protected function preparePathInfo() - { - if (null === ($requestUri = $this->getRequestUri())) { - return '/'; - } - - // Remove the query string from REQUEST_URI - if (false !== $pos = strpos($requestUri, '?')) { - $requestUri = substr($requestUri, 0, $pos); - } - if ('' !== $requestUri && '/' !== $requestUri[0]) { - $requestUri = '/'.$requestUri; - } - - if (null === ($baseUrl = $this->getBaseUrl())) { - return $requestUri; - } - - $pathInfo = substr($requestUri, \strlen($baseUrl)); - if (false === $pathInfo || '' === $pathInfo) { - // If substr() returns false then PATH_INFO is set to an empty string - return '/'; - } - - return (string) $pathInfo; - } - - /** - * Initializes HTTP request formats. - */ - protected static function initializeFormats() - { - static::$formats = [ - 'html' => ['text/html', 'application/xhtml+xml'], - 'txt' => ['text/plain'], - 'js' => ['application/javascript', 'application/x-javascript', 'text/javascript'], - 'css' => ['text/css'], - 'json' => ['application/json', 'application/x-json'], - 'jsonld' => ['application/ld+json'], - 'xml' => ['text/xml', 'application/xml', 'application/x-xml'], - 'rdf' => ['application/rdf+xml'], - 'atom' => ['application/atom+xml'], - 'rss' => ['application/rss+xml'], - 'form' => ['application/x-www-form-urlencoded'], - ]; - } - - private function setPhpDefaultLocale(string $locale): void - { - // if either the class Locale doesn't exist, or an exception is thrown when - // setting the default locale, the intl module is not installed, and - // the call can be ignored: - try { - if (class_exists('Locale', false)) { - \Locale::setDefault($locale); - } - } catch (\Exception $e) { - } - } - - /** - * Returns the prefix as encoded in the string when the string starts with - * the given prefix, null otherwise. - */ - private function getUrlencodedPrefix(string $string, string $prefix): ?string - { - if (0 !== strpos(rawurldecode($string), $prefix)) { - return null; - } - - $len = \strlen($prefix); - - if (preg_match(sprintf('#^(%%[[:xdigit:]]{2}|.){%d}#', $len), $string, $match)) { - return $match[0]; - } - - return null; - } - - private static function createRequestFromFactory(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): self - { - if (self::$requestFactory) { - $request = (self::$requestFactory)($query, $request, $attributes, $cookies, $files, $server, $content); - - if (!$request instanceof self) { - throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.'); - } - - return $request; - } - - return new static($query, $request, $attributes, $cookies, $files, $server, $content); - } - - /** - * Indicates whether this request originated from a trusted proxy. - * - * This can be useful to determine whether or not to trust the - * contents of a proxy-specific header. - * - * @return bool true if the request came from a trusted proxy, false otherwise - */ - public function isFromTrustedProxy() - { - return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR'), self::$trustedProxies); - } - - private function getTrustedValues(int $type, string $ip = null): array - { - $clientValues = []; - $forwardedValues = []; - - if ((self::$trustedHeaderSet & $type) && $this->headers->has(self::$trustedHeaders[$type])) { - foreach (explode(',', $this->headers->get(self::$trustedHeaders[$type])) as $v) { - $clientValues[] = (self::HEADER_X_FORWARDED_PORT === $type ? '0.0.0.0:' : '').trim($v); - } - } - - if ((self::$trustedHeaderSet & self::HEADER_FORWARDED) && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) { - $forwarded = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]); - $parts = HeaderUtils::split($forwarded, ',;='); - $forwardedValues = []; - $param = self::$forwardedParams[$type]; - foreach ($parts as $subParts) { - if (null === $v = HeaderUtils::combine($subParts)[$param] ?? null) { - continue; - } - if (self::HEADER_X_FORWARDED_PORT === $type) { - if (']' === substr($v, -1) || false === $v = strrchr($v, ':')) { - $v = $this->isSecure() ? ':443' : ':80'; - } - $v = '0.0.0.0'.$v; - } - $forwardedValues[] = $v; - } - } - - if (null !== $ip) { - $clientValues = $this->normalizeAndFilterClientIps($clientValues, $ip); - $forwardedValues = $this->normalizeAndFilterClientIps($forwardedValues, $ip); - } - - if ($forwardedValues === $clientValues || !$clientValues) { - return $forwardedValues; - } - - if (!$forwardedValues) { - return $clientValues; - } - - if (!$this->isForwardedValid) { - return null !== $ip ? ['0.0.0.0', $ip] : []; - } - $this->isForwardedValid = false; - - throw new ConflictingHeadersException(sprintf('The request has both a trusted "%s" header and a trusted "%s" header, conflicting with each other. You should either configure your proxy to remove one of them, or configure your project to distrust the offending one.', self::$trustedHeaders[self::HEADER_FORWARDED], self::$trustedHeaders[$type])); - } - - private function normalizeAndFilterClientIps(array $clientIps, string $ip): array - { - if (!$clientIps) { - return []; - } - $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from - $firstTrustedIp = null; - - foreach ($clientIps as $key => $clientIp) { - if (strpos($clientIp, '.')) { - // Strip :port from IPv4 addresses. This is allowed in Forwarded - // and may occur in X-Forwarded-For. - $i = strpos($clientIp, ':'); - if ($i) { - $clientIps[$key] = $clientIp = substr($clientIp, 0, $i); - } - } elseif (0 === strpos($clientIp, '[')) { - // Strip brackets and :port from IPv6 addresses. - $i = strpos($clientIp, ']', 1); - $clientIps[$key] = $clientIp = substr($clientIp, 1, $i - 1); - } - - if (!filter_var($clientIp, FILTER_VALIDATE_IP)) { - unset($clientIps[$key]); - - continue; - } - - if (IpUtils::checkIp($clientIp, self::$trustedProxies)) { - unset($clientIps[$key]); - - // Fallback to this when the client IP falls into the range of trusted proxies - if (null === $firstTrustedIp) { - $firstTrustedIp = $clientIp; - } - } - } - - // Now the IP chain contains only untrusted proxies and the client IP - return $clientIps ? array_reverse($clientIps) : [$firstTrustedIp]; - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher.php deleted file mode 100644 index c32c5cd..0000000 --- a/vendor/symfony/http-foundation/RequestMatcher.php +++ /dev/null @@ -1,188 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * RequestMatcher compares a pre-defined set of checks against a Request instance. - * - * @author Fabien Potencier - */ -class RequestMatcher implements RequestMatcherInterface -{ - /** - * @var string|null - */ - private $path; - - /** - * @var string|null - */ - private $host; - - /** - * @var int|null - */ - private $port; - - /** - * @var string[] - */ - private $methods = []; - - /** - * @var string[] - */ - private $ips = []; - - /** - * @var array - */ - private $attributes = []; - - /** - * @var string[] - */ - private $schemes = []; - - /** - * @param string|string[]|null $methods - * @param string|string[]|null $ips - * @param string|string[]|null $schemes - */ - public function __construct(string $path = null, string $host = null, $methods = null, $ips = null, array $attributes = [], $schemes = null, int $port = null) - { - $this->matchPath($path); - $this->matchHost($host); - $this->matchMethod($methods); - $this->matchIps($ips); - $this->matchScheme($schemes); - $this->matchPort($port); - - foreach ($attributes as $k => $v) { - $this->matchAttribute($k, $v); - } - } - - /** - * Adds a check for the HTTP scheme. - * - * @param string|string[]|null $scheme An HTTP scheme or an array of HTTP schemes - */ - public function matchScheme($scheme) - { - $this->schemes = null !== $scheme ? array_map('strtolower', (array) $scheme) : []; - } - - /** - * Adds a check for the URL host name. - */ - public function matchHost(?string $regexp) - { - $this->host = $regexp; - } - - /** - * Adds a check for the the URL port. - * - * @param int|null $port The port number to connect to - */ - public function matchPort(?int $port) - { - $this->port = $port; - } - - /** - * Adds a check for the URL path info. - */ - public function matchPath(?string $regexp) - { - $this->path = $regexp; - } - - /** - * Adds a check for the client IP. - * - * @param string $ip A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 - */ - public function matchIp(string $ip) - { - $this->matchIps($ip); - } - - /** - * Adds a check for the client IP. - * - * @param string|string[]|null $ips A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 - */ - public function matchIps($ips) - { - $this->ips = null !== $ips ? (array) $ips : []; - } - - /** - * Adds a check for the HTTP method. - * - * @param string|string[]|null $method An HTTP method or an array of HTTP methods - */ - public function matchMethod($method) - { - $this->methods = null !== $method ? array_map('strtoupper', (array) $method) : []; - } - - /** - * Adds a check for request attribute. - */ - public function matchAttribute(string $key, string $regexp) - { - $this->attributes[$key] = $regexp; - } - - /** - * {@inheritdoc} - */ - public function matches(Request $request) - { - if ($this->schemes && !\in_array($request->getScheme(), $this->schemes, true)) { - return false; - } - - if ($this->methods && !\in_array($request->getMethod(), $this->methods, true)) { - return false; - } - - foreach ($this->attributes as $key => $pattern) { - if (!preg_match('{'.$pattern.'}', $request->attributes->get($key))) { - return false; - } - } - - if (null !== $this->path && !preg_match('{'.$this->path.'}', rawurldecode($request->getPathInfo()))) { - return false; - } - - if (null !== $this->host && !preg_match('{'.$this->host.'}i', $request->getHost())) { - return false; - } - - if (null !== $this->port && 0 < $this->port && $request->getPort() !== $this->port) { - return false; - } - - if (IpUtils::checkIp($request->getClientIp(), $this->ips)) { - return true; - } - - // Note to future implementors: add additional checks above the - // foreach above or else your check might not be run! - return 0 === \count($this->ips); - } -} diff --git a/vendor/symfony/http-foundation/RequestMatcherInterface.php b/vendor/symfony/http-foundation/RequestMatcherInterface.php deleted file mode 100644 index c26db3e..0000000 --- a/vendor/symfony/http-foundation/RequestMatcherInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * RequestMatcherInterface is an interface for strategies to match a Request. - * - * @author Fabien Potencier - */ -interface RequestMatcherInterface -{ - /** - * Decides whether the rule(s) implemented by the strategy matches the supplied request. - * - * @return bool true if the request matches, false otherwise - */ - public function matches(Request $request); -} diff --git a/vendor/symfony/http-foundation/RequestStack.php b/vendor/symfony/http-foundation/RequestStack.php deleted file mode 100644 index 244a77d..0000000 --- a/vendor/symfony/http-foundation/RequestStack.php +++ /dev/null @@ -1,103 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Request stack that controls the lifecycle of requests. - * - * @author Benjamin Eberlei - */ -class RequestStack -{ - /** - * @var Request[] - */ - private $requests = []; - - /** - * Pushes a Request on the stack. - * - * This method should generally not be called directly as the stack - * management should be taken care of by the application itself. - */ - public function push(Request $request) - { - $this->requests[] = $request; - } - - /** - * Pops the current request from the stack. - * - * This operation lets the current request go out of scope. - * - * This method should generally not be called directly as the stack - * management should be taken care of by the application itself. - * - * @return Request|null - */ - public function pop() - { - if (!$this->requests) { - return null; - } - - return array_pop($this->requests); - } - - /** - * @return Request|null - */ - public function getCurrentRequest() - { - return end($this->requests) ?: null; - } - - /** - * Gets the master Request. - * - * Be warned that making your code aware of the master request - * might make it un-compatible with other features of your framework - * like ESI support. - * - * @return Request|null - */ - public function getMasterRequest() - { - if (!$this->requests) { - return null; - } - - return $this->requests[0]; - } - - /** - * Returns the parent request of the current. - * - * Be warned that making your code aware of the parent request - * might make it un-compatible with other features of your framework - * like ESI support. - * - * If current Request is the master request, it returns null. - * - * @return Request|null - */ - public function getParentRequest() - { - $pos = \count($this->requests) - 2; - - if (!isset($this->requests[$pos])) { - return null; - } - - return $this->requests[$pos]; - } -} diff --git a/vendor/symfony/http-foundation/Response.php b/vendor/symfony/http-foundation/Response.php deleted file mode 100644 index 9122b13..0000000 --- a/vendor/symfony/http-foundation/Response.php +++ /dev/null @@ -1,1224 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * Response represents an HTTP response. - * - * @author Fabien Potencier - */ -class Response -{ - const HTTP_CONTINUE = 100; - const HTTP_SWITCHING_PROTOCOLS = 101; - const HTTP_PROCESSING = 102; // RFC2518 - const HTTP_EARLY_HINTS = 103; // RFC8297 - const HTTP_OK = 200; - const HTTP_CREATED = 201; - const HTTP_ACCEPTED = 202; - const HTTP_NON_AUTHORITATIVE_INFORMATION = 203; - const HTTP_NO_CONTENT = 204; - const HTTP_RESET_CONTENT = 205; - const HTTP_PARTIAL_CONTENT = 206; - const HTTP_MULTI_STATUS = 207; // RFC4918 - const HTTP_ALREADY_REPORTED = 208; // RFC5842 - const HTTP_IM_USED = 226; // RFC3229 - const HTTP_MULTIPLE_CHOICES = 300; - const HTTP_MOVED_PERMANENTLY = 301; - const HTTP_FOUND = 302; - const HTTP_SEE_OTHER = 303; - const HTTP_NOT_MODIFIED = 304; - const HTTP_USE_PROXY = 305; - const HTTP_RESERVED = 306; - const HTTP_TEMPORARY_REDIRECT = 307; - const HTTP_PERMANENTLY_REDIRECT = 308; // RFC7238 - const HTTP_BAD_REQUEST = 400; - const HTTP_UNAUTHORIZED = 401; - const HTTP_PAYMENT_REQUIRED = 402; - const HTTP_FORBIDDEN = 403; - const HTTP_NOT_FOUND = 404; - const HTTP_METHOD_NOT_ALLOWED = 405; - const HTTP_NOT_ACCEPTABLE = 406; - const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; - const HTTP_REQUEST_TIMEOUT = 408; - const HTTP_CONFLICT = 409; - const HTTP_GONE = 410; - const HTTP_LENGTH_REQUIRED = 411; - const HTTP_PRECONDITION_FAILED = 412; - const HTTP_REQUEST_ENTITY_TOO_LARGE = 413; - const HTTP_REQUEST_URI_TOO_LONG = 414; - const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; - const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; - const HTTP_EXPECTATION_FAILED = 417; - const HTTP_I_AM_A_TEAPOT = 418; // RFC2324 - const HTTP_MISDIRECTED_REQUEST = 421; // RFC7540 - const HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918 - const HTTP_LOCKED = 423; // RFC4918 - const HTTP_FAILED_DEPENDENCY = 424; // RFC4918 - const HTTP_TOO_EARLY = 425; // RFC-ietf-httpbis-replay-04 - const HTTP_UPGRADE_REQUIRED = 426; // RFC2817 - const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585 - const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585 - const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585 - const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; - const HTTP_INTERNAL_SERVER_ERROR = 500; - const HTTP_NOT_IMPLEMENTED = 501; - const HTTP_BAD_GATEWAY = 502; - const HTTP_SERVICE_UNAVAILABLE = 503; - const HTTP_GATEWAY_TIMEOUT = 504; - const HTTP_VERSION_NOT_SUPPORTED = 505; - const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506; // RFC2295 - const HTTP_INSUFFICIENT_STORAGE = 507; // RFC4918 - const HTTP_LOOP_DETECTED = 508; // RFC5842 - const HTTP_NOT_EXTENDED = 510; // RFC2774 - const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; // RFC6585 - - /** - * @var ResponseHeaderBag - */ - public $headers; - - /** - * @var string - */ - protected $content; - - /** - * @var string - */ - protected $version; - - /** - * @var int - */ - protected $statusCode; - - /** - * @var string - */ - protected $statusText; - - /** - * @var string - */ - protected $charset; - - /** - * Status codes translation table. - * - * The list of codes is complete according to the - * {@link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml Hypertext Transfer Protocol (HTTP) Status Code Registry} - * (last updated 2016-03-01). - * - * Unless otherwise noted, the status code is defined in RFC2616. - * - * @var array - */ - public static $statusTexts = [ - 100 => 'Continue', - 101 => 'Switching Protocols', - 102 => 'Processing', // RFC2518 - 103 => 'Early Hints', - 200 => 'OK', - 201 => 'Created', - 202 => 'Accepted', - 203 => 'Non-Authoritative Information', - 204 => 'No Content', - 205 => 'Reset Content', - 206 => 'Partial Content', - 207 => 'Multi-Status', // RFC4918 - 208 => 'Already Reported', // RFC5842 - 226 => 'IM Used', // RFC3229 - 300 => 'Multiple Choices', - 301 => 'Moved Permanently', - 302 => 'Found', - 303 => 'See Other', - 304 => 'Not Modified', - 305 => 'Use Proxy', - 307 => 'Temporary Redirect', - 308 => 'Permanent Redirect', // RFC7238 - 400 => 'Bad Request', - 401 => 'Unauthorized', - 402 => 'Payment Required', - 403 => 'Forbidden', - 404 => 'Not Found', - 405 => 'Method Not Allowed', - 406 => 'Not Acceptable', - 407 => 'Proxy Authentication Required', - 408 => 'Request Timeout', - 409 => 'Conflict', - 410 => 'Gone', - 411 => 'Length Required', - 412 => 'Precondition Failed', - 413 => 'Payload Too Large', - 414 => 'URI Too Long', - 415 => 'Unsupported Media Type', - 416 => 'Range Not Satisfiable', - 417 => 'Expectation Failed', - 418 => 'I\'m a teapot', // RFC2324 - 421 => 'Misdirected Request', // RFC7540 - 422 => 'Unprocessable Entity', // RFC4918 - 423 => 'Locked', // RFC4918 - 424 => 'Failed Dependency', // RFC4918 - 425 => 'Too Early', // RFC-ietf-httpbis-replay-04 - 426 => 'Upgrade Required', // RFC2817 - 428 => 'Precondition Required', // RFC6585 - 429 => 'Too Many Requests', // RFC6585 - 431 => 'Request Header Fields Too Large', // RFC6585 - 451 => 'Unavailable For Legal Reasons', // RFC7725 - 500 => 'Internal Server Error', - 501 => 'Not Implemented', - 502 => 'Bad Gateway', - 503 => 'Service Unavailable', - 504 => 'Gateway Timeout', - 505 => 'HTTP Version Not Supported', - 506 => 'Variant Also Negotiates', // RFC2295 - 507 => 'Insufficient Storage', // RFC4918 - 508 => 'Loop Detected', // RFC5842 - 510 => 'Not Extended', // RFC2774 - 511 => 'Network Authentication Required', // RFC6585 - ]; - - /** - * @throws \InvalidArgumentException When the HTTP status code is not valid - */ - public function __construct(?string $content = '', int $status = 200, array $headers = []) - { - $this->headers = new ResponseHeaderBag($headers); - $this->setContent($content); - $this->setStatusCode($status); - $this->setProtocolVersion('1.0'); - } - - /** - * Factory method for chainability. - * - * Example: - * - * return Response::create($body, 200) - * ->setSharedMaxAge(300); - * - * @return static - */ - public static function create(?string $content = '', int $status = 200, array $headers = []) - { - return new static($content, $status, $headers); - } - - /** - * Returns the Response as an HTTP string. - * - * The string representation of the Response is the same as the - * one that will be sent to the client only if the prepare() method - * has been called before. - * - * @return string The Response as an HTTP string - * - * @see prepare() - */ - public function __toString() - { - return - sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\r\n". - $this->headers."\r\n". - $this->getContent(); - } - - /** - * Clones the current Response instance. - */ - public function __clone() - { - $this->headers = clone $this->headers; - } - - /** - * Prepares the Response before it is sent to the client. - * - * This method tweaks the Response to ensure that it is - * compliant with RFC 2616. Most of the changes are based on - * the Request that is "associated" with this Response. - * - * @return $this - */ - public function prepare(Request $request) - { - $headers = $this->headers; - - if ($this->isInformational() || $this->isEmpty()) { - $this->setContent(null); - $headers->remove('Content-Type'); - $headers->remove('Content-Length'); - } else { - // Content-type based on the Request - if (!$headers->has('Content-Type')) { - $format = $request->getPreferredFormat(); - if (null !== $format && $mimeType = $request->getMimeType($format)) { - $headers->set('Content-Type', $mimeType); - } - } - - // Fix Content-Type - $charset = $this->charset ?: 'UTF-8'; - if (!$headers->has('Content-Type')) { - $headers->set('Content-Type', 'text/html; charset='.$charset); - } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) { - // add the charset - $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset); - } - - // Fix Content-Length - if ($headers->has('Transfer-Encoding')) { - $headers->remove('Content-Length'); - } - - if ($request->isMethod('HEAD')) { - // cf. RFC2616 14.13 - $length = $headers->get('Content-Length'); - $this->setContent(null); - if ($length) { - $headers->set('Content-Length', $length); - } - } - } - - // Fix protocol - if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) { - $this->setProtocolVersion('1.1'); - } - - // Check if we need to send extra expire info headers - if ('1.0' == $this->getProtocolVersion() && false !== strpos($headers->get('Cache-Control'), 'no-cache')) { - $headers->set('pragma', 'no-cache'); - $headers->set('expires', -1); - } - - $this->ensureIEOverSSLCompatibility($request); - - if ($request->isSecure()) { - foreach ($headers->getCookies() as $cookie) { - $cookie->setSecureDefault(true); - } - } - - return $this; - } - - /** - * Sends HTTP headers. - * - * @return $this - */ - public function sendHeaders() - { - // headers have already been sent by the developer - if (headers_sent()) { - return $this; - } - - // headers - foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) { - $replace = 0 === strcasecmp($name, 'Content-Type'); - foreach ($values as $value) { - header($name.': '.$value, $replace, $this->statusCode); - } - } - - // cookies - foreach ($this->headers->getCookies() as $cookie) { - header('Set-Cookie: '.$cookie, false, $this->statusCode); - } - - // status - header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode); - - return $this; - } - - /** - * Sends content for the current web response. - * - * @return $this - */ - public function sendContent() - { - echo $this->content; - - return $this; - } - - /** - * Sends HTTP headers and content. - * - * @return $this - */ - public function send() - { - $this->sendHeaders(); - $this->sendContent(); - - if (\function_exists('fastcgi_finish_request')) { - fastcgi_finish_request(); - } elseif (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { - static::closeOutputBuffers(0, true); - } - - return $this; - } - - /** - * Sets the response content. - * - * @return $this - * - * @throws \UnexpectedValueException - */ - public function setContent(?string $content) - { - $this->content = $content ?? ''; - - return $this; - } - - /** - * Gets the current response content. - * - * @return string|false - */ - public function getContent() - { - return $this->content; - } - - /** - * Sets the HTTP protocol version (1.0 or 1.1). - * - * @return $this - * - * @final - */ - public function setProtocolVersion(string $version): object - { - $this->version = $version; - - return $this; - } - - /** - * Gets the HTTP protocol version. - * - * @final - */ - public function getProtocolVersion(): string - { - return $this->version; - } - - /** - * Sets the response status code. - * - * If the status text is null it will be automatically populated for the known - * status codes and left empty otherwise. - * - * @return $this - * - * @throws \InvalidArgumentException When the HTTP status code is not valid - * - * @final - */ - public function setStatusCode(int $code, $text = null): object - { - $this->statusCode = $code; - if ($this->isInvalid()) { - throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code)); - } - - if (null === $text) { - $this->statusText = isset(self::$statusTexts[$code]) ? self::$statusTexts[$code] : 'unknown status'; - - return $this; - } - - if (false === $text) { - $this->statusText = ''; - - return $this; - } - - $this->statusText = $text; - - return $this; - } - - /** - * Retrieves the status code for the current web response. - * - * @final - */ - public function getStatusCode(): int - { - return $this->statusCode; - } - - /** - * Sets the response charset. - * - * @return $this - * - * @final - */ - public function setCharset(string $charset): object - { - $this->charset = $charset; - - return $this; - } - - /** - * Retrieves the response charset. - * - * @final - */ - public function getCharset(): ?string - { - return $this->charset; - } - - /** - * Returns true if the response may safely be kept in a shared (surrogate) cache. - * - * Responses marked "private" with an explicit Cache-Control directive are - * considered uncacheable. - * - * Responses with neither a freshness lifetime (Expires, max-age) nor cache - * validator (Last-Modified, ETag) are considered uncacheable because there is - * no way to tell when or how to remove them from the cache. - * - * Note that RFC 7231 and RFC 7234 possibly allow for a more permissive implementation, - * for example "status codes that are defined as cacheable by default [...] - * can be reused by a cache with heuristic expiration unless otherwise indicated" - * (https://tools.ietf.org/html/rfc7231#section-6.1) - * - * @final - */ - public function isCacheable(): bool - { - if (!\in_array($this->statusCode, [200, 203, 300, 301, 302, 404, 410])) { - return false; - } - - if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) { - return false; - } - - return $this->isValidateable() || $this->isFresh(); - } - - /** - * Returns true if the response is "fresh". - * - * Fresh responses may be served from cache without any interaction with the - * origin. A response is considered fresh when it includes a Cache-Control/max-age - * indicator or Expires header and the calculated age is less than the freshness lifetime. - * - * @final - */ - public function isFresh(): bool - { - return $this->getTtl() > 0; - } - - /** - * Returns true if the response includes headers that can be used to validate - * the response with the origin server using a conditional GET request. - * - * @final - */ - public function isValidateable(): bool - { - return $this->headers->has('Last-Modified') || $this->headers->has('ETag'); - } - - /** - * Marks the response as "private". - * - * It makes the response ineligible for serving other clients. - * - * @return $this - * - * @final - */ - public function setPrivate(): object - { - $this->headers->removeCacheControlDirective('public'); - $this->headers->addCacheControlDirective('private'); - - return $this; - } - - /** - * Marks the response as "public". - * - * It makes the response eligible for serving other clients. - * - * @return $this - * - * @final - */ - public function setPublic(): object - { - $this->headers->addCacheControlDirective('public'); - $this->headers->removeCacheControlDirective('private'); - - return $this; - } - - /** - * Marks the response as "immutable". - * - * @return $this - * - * @final - */ - public function setImmutable(bool $immutable = true): object - { - if ($immutable) { - $this->headers->addCacheControlDirective('immutable'); - } else { - $this->headers->removeCacheControlDirective('immutable'); - } - - return $this; - } - - /** - * Returns true if the response is marked as "immutable". - * - * @final - */ - public function isImmutable(): bool - { - return $this->headers->hasCacheControlDirective('immutable'); - } - - /** - * Returns true if the response must be revalidated by caches. - * - * This method indicates that the response must not be served stale by a - * cache in any circumstance without first revalidating with the origin. - * When present, the TTL of the response should not be overridden to be - * greater than the value provided by the origin. - * - * @final - */ - public function mustRevalidate(): bool - { - return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->hasCacheControlDirective('proxy-revalidate'); - } - - /** - * Returns the Date header as a DateTime instance. - * - * @throws \RuntimeException When the header is not parseable - * - * @final - */ - public function getDate(): ?\DateTimeInterface - { - return $this->headers->getDate('Date'); - } - - /** - * Sets the Date header. - * - * @return $this - * - * @final - */ - public function setDate(\DateTimeInterface $date): object - { - if ($date instanceof \DateTime) { - $date = \DateTimeImmutable::createFromMutable($date); - } - - $date = $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT'); - - return $this; - } - - /** - * Returns the age of the response in seconds. - * - * @final - */ - public function getAge(): int - { - if (null !== $age = $this->headers->get('Age')) { - return (int) $age; - } - - return max(time() - (int) $this->getDate()->format('U'), 0); - } - - /** - * Marks the response stale by setting the Age header to be equal to the maximum age of the response. - * - * @return $this - */ - public function expire() - { - if ($this->isFresh()) { - $this->headers->set('Age', $this->getMaxAge()); - $this->headers->remove('Expires'); - } - - return $this; - } - - /** - * Returns the value of the Expires header as a DateTime instance. - * - * @final - */ - public function getExpires(): ?\DateTimeInterface - { - try { - return $this->headers->getDate('Expires'); - } catch (\RuntimeException $e) { - // according to RFC 2616 invalid date formats (e.g. "0" and "-1") must be treated as in the past - return \DateTime::createFromFormat('U', time() - 172800); - } - } - - /** - * Sets the Expires HTTP header with a DateTime instance. - * - * Passing null as value will remove the header. - * - * @return $this - * - * @final - */ - public function setExpires(\DateTimeInterface $date = null): object - { - if (null === $date) { - $this->headers->remove('Expires'); - - return $this; - } - - if ($date instanceof \DateTime) { - $date = \DateTimeImmutable::createFromMutable($date); - } - - $date = $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT'); - - return $this; - } - - /** - * Returns the number of seconds after the time specified in the response's Date - * header when the response should no longer be considered fresh. - * - * First, it checks for a s-maxage directive, then a max-age directive, and then it falls - * back on an expires header. It returns null when no maximum age can be established. - * - * @final - */ - public function getMaxAge(): ?int - { - if ($this->headers->hasCacheControlDirective('s-maxage')) { - return (int) $this->headers->getCacheControlDirective('s-maxage'); - } - - if ($this->headers->hasCacheControlDirective('max-age')) { - return (int) $this->headers->getCacheControlDirective('max-age'); - } - - if (null !== $this->getExpires()) { - return (int) $this->getExpires()->format('U') - (int) $this->getDate()->format('U'); - } - - return null; - } - - /** - * Sets the number of seconds after which the response should no longer be considered fresh. - * - * This methods sets the Cache-Control max-age directive. - * - * @return $this - * - * @final - */ - public function setMaxAge(int $value): object - { - $this->headers->addCacheControlDirective('max-age', $value); - - return $this; - } - - /** - * Sets the number of seconds after which the response should no longer be considered fresh by shared caches. - * - * This methods sets the Cache-Control s-maxage directive. - * - * @return $this - * - * @final - */ - public function setSharedMaxAge(int $value): object - { - $this->setPublic(); - $this->headers->addCacheControlDirective('s-maxage', $value); - - return $this; - } - - /** - * Returns the response's time-to-live in seconds. - * - * It returns null when no freshness information is present in the response. - * - * When the responses TTL is <= 0, the response may not be served from cache without first - * revalidating with the origin. - * - * @final - */ - public function getTtl(): ?int - { - $maxAge = $this->getMaxAge(); - - return null !== $maxAge ? $maxAge - $this->getAge() : null; - } - - /** - * Sets the response's time-to-live for shared caches in seconds. - * - * This method adjusts the Cache-Control/s-maxage directive. - * - * @return $this - * - * @final - */ - public function setTtl(int $seconds): object - { - $this->setSharedMaxAge($this->getAge() + $seconds); - - return $this; - } - - /** - * Sets the response's time-to-live for private/client caches in seconds. - * - * This method adjusts the Cache-Control/max-age directive. - * - * @return $this - * - * @final - */ - public function setClientTtl(int $seconds): object - { - $this->setMaxAge($this->getAge() + $seconds); - - return $this; - } - - /** - * Returns the Last-Modified HTTP header as a DateTime instance. - * - * @throws \RuntimeException When the HTTP header is not parseable - * - * @final - */ - public function getLastModified(): ?\DateTimeInterface - { - return $this->headers->getDate('Last-Modified'); - } - - /** - * Sets the Last-Modified HTTP header with a DateTime instance. - * - * Passing null as value will remove the header. - * - * @return $this - * - * @final - */ - public function setLastModified(\DateTimeInterface $date = null): object - { - if (null === $date) { - $this->headers->remove('Last-Modified'); - - return $this; - } - - if ($date instanceof \DateTime) { - $date = \DateTimeImmutable::createFromMutable($date); - } - - $date = $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT'); - - return $this; - } - - /** - * Returns the literal value of the ETag HTTP header. - * - * @final - */ - public function getEtag(): ?string - { - return $this->headers->get('ETag'); - } - - /** - * Sets the ETag value. - * - * @param string|null $etag The ETag unique identifier or null to remove the header - * @param bool $weak Whether you want a weak ETag or not - * - * @return $this - * - * @final - */ - public function setEtag(string $etag = null, bool $weak = false): object - { - if (null === $etag) { - $this->headers->remove('Etag'); - } else { - if (0 !== strpos($etag, '"')) { - $etag = '"'.$etag.'"'; - } - - $this->headers->set('ETag', (true === $weak ? 'W/' : '').$etag); - } - - return $this; - } - - /** - * Sets the response's cache headers (validation and/or expiration). - * - * Available options are: etag, last_modified, max_age, s_maxage, private, public and immutable. - * - * @return $this - * - * @throws \InvalidArgumentException - * - * @final - */ - public function setCache(array $options): object - { - if ($diff = array_diff(array_keys($options), ['etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public', 'immutable'])) { - throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', $diff))); - } - - if (isset($options['etag'])) { - $this->setEtag($options['etag']); - } - - if (isset($options['last_modified'])) { - $this->setLastModified($options['last_modified']); - } - - if (isset($options['max_age'])) { - $this->setMaxAge($options['max_age']); - } - - if (isset($options['s_maxage'])) { - $this->setSharedMaxAge($options['s_maxage']); - } - - if (isset($options['public'])) { - if ($options['public']) { - $this->setPublic(); - } else { - $this->setPrivate(); - } - } - - if (isset($options['private'])) { - if ($options['private']) { - $this->setPrivate(); - } else { - $this->setPublic(); - } - } - - if (isset($options['immutable'])) { - $this->setImmutable((bool) $options['immutable']); - } - - return $this; - } - - /** - * Modifies the response so that it conforms to the rules defined for a 304 status code. - * - * This sets the status, removes the body, and discards any headers - * that MUST NOT be included in 304 responses. - * - * @return $this - * - * @see https://tools.ietf.org/html/rfc2616#section-10.3.5 - * - * @final - */ - public function setNotModified(): object - { - $this->setStatusCode(304); - $this->setContent(null); - - // remove headers that MUST NOT be included with 304 Not Modified responses - foreach (['Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified'] as $header) { - $this->headers->remove($header); - } - - return $this; - } - - /** - * Returns true if the response includes a Vary header. - * - * @final - */ - public function hasVary(): bool - { - return null !== $this->headers->get('Vary'); - } - - /** - * Returns an array of header names given in the Vary header. - * - * @final - */ - public function getVary(): array - { - if (!$vary = $this->headers->all('Vary')) { - return []; - } - - $ret = []; - foreach ($vary as $item) { - $ret = array_merge($ret, preg_split('/[\s,]+/', $item)); - } - - return $ret; - } - - /** - * Sets the Vary header. - * - * @param string|array $headers - * @param bool $replace Whether to replace the actual value or not (true by default) - * - * @return $this - * - * @final - */ - public function setVary($headers, bool $replace = true): object - { - $this->headers->set('Vary', $headers, $replace); - - return $this; - } - - /** - * Determines if the Response validators (ETag, Last-Modified) match - * a conditional value specified in the Request. - * - * If the Response is not modified, it sets the status code to 304 and - * removes the actual content by calling the setNotModified() method. - * - * @return bool true if the Response validators match the Request, false otherwise - * - * @final - */ - public function isNotModified(Request $request): bool - { - if (!$request->isMethodCacheable()) { - return false; - } - - $notModified = false; - $lastModified = $this->headers->get('Last-Modified'); - $modifiedSince = $request->headers->get('If-Modified-Since'); - - if ($etags = $request->getETags()) { - $notModified = \in_array($this->getEtag(), $etags) || \in_array('*', $etags); - } - - if ($modifiedSince && $lastModified) { - $notModified = strtotime($modifiedSince) >= strtotime($lastModified) && (!$etags || $notModified); - } - - if ($notModified) { - $this->setNotModified(); - } - - return $notModified; - } - - /** - * Is response invalid? - * - * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html - * - * @final - */ - public function isInvalid(): bool - { - return $this->statusCode < 100 || $this->statusCode >= 600; - } - - /** - * Is response informative? - * - * @final - */ - public function isInformational(): bool - { - return $this->statusCode >= 100 && $this->statusCode < 200; - } - - /** - * Is response successful? - * - * @final - */ - public function isSuccessful(): bool - { - return $this->statusCode >= 200 && $this->statusCode < 300; - } - - /** - * Is the response a redirect? - * - * @final - */ - public function isRedirection(): bool - { - return $this->statusCode >= 300 && $this->statusCode < 400; - } - - /** - * Is there a client error? - * - * @final - */ - public function isClientError(): bool - { - return $this->statusCode >= 400 && $this->statusCode < 500; - } - - /** - * Was there a server side error? - * - * @final - */ - public function isServerError(): bool - { - return $this->statusCode >= 500 && $this->statusCode < 600; - } - - /** - * Is the response OK? - * - * @final - */ - public function isOk(): bool - { - return 200 === $this->statusCode; - } - - /** - * Is the response forbidden? - * - * @final - */ - public function isForbidden(): bool - { - return 403 === $this->statusCode; - } - - /** - * Is the response a not found error? - * - * @final - */ - public function isNotFound(): bool - { - return 404 === $this->statusCode; - } - - /** - * Is the response a redirect of some form? - * - * @final - */ - public function isRedirect(string $location = null): bool - { - return \in_array($this->statusCode, [201, 301, 302, 303, 307, 308]) && (null === $location ?: $location == $this->headers->get('Location')); - } - - /** - * Is the response empty? - * - * @final - */ - public function isEmpty(): bool - { - return \in_array($this->statusCode, [204, 304]); - } - - /** - * Cleans or flushes output buffers up to target level. - * - * Resulting level can be greater than target level if a non-removable buffer has been encountered. - * - * @final - */ - public static function closeOutputBuffers(int $targetLevel, bool $flush): void - { - $status = ob_get_status(true); - $level = \count($status); - $flags = PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? PHP_OUTPUT_HANDLER_FLUSHABLE : PHP_OUTPUT_HANDLER_CLEANABLE); - - while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || ($s['flags'] & $flags) === $flags : $s['del'])) { - if ($flush) { - ob_end_flush(); - } else { - ob_end_clean(); - } - } - } - - /** - * Checks if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9. - * - * @see http://support.microsoft.com/kb/323308 - * - * @final - */ - protected function ensureIEOverSSLCompatibility(Request $request): void - { - if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && 1 == preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) && true === $request->isSecure()) { - if ((int) preg_replace('/(MSIE )(.*?);/', '$2', $match[0]) < 9) { - $this->headers->remove('Cache-Control'); - } - } - } -} diff --git a/vendor/symfony/http-foundation/ResponseHeaderBag.php b/vendor/symfony/http-foundation/ResponseHeaderBag.php deleted file mode 100644 index 56b9245..0000000 --- a/vendor/symfony/http-foundation/ResponseHeaderBag.php +++ /dev/null @@ -1,293 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * ResponseHeaderBag is a container for Response HTTP headers. - * - * @author Fabien Potencier - */ -class ResponseHeaderBag extends HeaderBag -{ - const COOKIES_FLAT = 'flat'; - const COOKIES_ARRAY = 'array'; - - const DISPOSITION_ATTACHMENT = 'attachment'; - const DISPOSITION_INLINE = 'inline'; - - protected $computedCacheControl = []; - protected $cookies = []; - protected $headerNames = []; - - public function __construct(array $headers = []) - { - parent::__construct($headers); - - if (!isset($this->headers['cache-control'])) { - $this->set('Cache-Control', ''); - } - - /* RFC2616 - 14.18 says all Responses need to have a Date */ - if (!isset($this->headers['date'])) { - $this->initDate(); - } - } - - /** - * Returns the headers, with original capitalizations. - * - * @return array An array of headers - */ - public function allPreserveCase() - { - $headers = []; - foreach ($this->all() as $name => $value) { - $headers[$this->headerNames[$name] ?? $name] = $value; - } - - return $headers; - } - - public function allPreserveCaseWithoutCookies() - { - $headers = $this->allPreserveCase(); - if (isset($this->headerNames['set-cookie'])) { - unset($headers[$this->headerNames['set-cookie']]); - } - - return $headers; - } - - /** - * {@inheritdoc} - */ - public function replace(array $headers = []) - { - $this->headerNames = []; - - parent::replace($headers); - - if (!isset($this->headers['cache-control'])) { - $this->set('Cache-Control', ''); - } - - if (!isset($this->headers['date'])) { - $this->initDate(); - } - } - - /** - * {@inheritdoc} - */ - public function all(string $key = null) - { - $headers = parent::all(); - - if (null !== $key) { - $key = strtr($key, self::UPPER, self::LOWER); - - return 'set-cookie' !== $key ? $headers[$key] ?? [] : array_map('strval', $this->getCookies()); - } - - foreach ($this->getCookies() as $cookie) { - $headers['set-cookie'][] = (string) $cookie; - } - - return $headers; - } - - /** - * {@inheritdoc} - */ - public function set(string $key, $values, bool $replace = true) - { - $uniqueKey = strtr($key, self::UPPER, self::LOWER); - - if ('set-cookie' === $uniqueKey) { - if ($replace) { - $this->cookies = []; - } - foreach ((array) $values as $cookie) { - $this->setCookie(Cookie::fromString($cookie)); - } - $this->headerNames[$uniqueKey] = $key; - - return; - } - - $this->headerNames[$uniqueKey] = $key; - - parent::set($key, $values, $replace); - - // ensure the cache-control header has sensible defaults - if (\in_array($uniqueKey, ['cache-control', 'etag', 'last-modified', 'expires'], true) && '' !== $computed = $this->computeCacheControlValue()) { - $this->headers['cache-control'] = [$computed]; - $this->headerNames['cache-control'] = 'Cache-Control'; - $this->computedCacheControl = $this->parseCacheControl($computed); - } - } - - /** - * {@inheritdoc} - */ - public function remove(string $key) - { - $uniqueKey = strtr($key, self::UPPER, self::LOWER); - unset($this->headerNames[$uniqueKey]); - - if ('set-cookie' === $uniqueKey) { - $this->cookies = []; - - return; - } - - parent::remove($key); - - if ('cache-control' === $uniqueKey) { - $this->computedCacheControl = []; - } - - if ('date' === $uniqueKey) { - $this->initDate(); - } - } - - /** - * {@inheritdoc} - */ - public function hasCacheControlDirective(string $key) - { - return \array_key_exists($key, $this->computedCacheControl); - } - - /** - * {@inheritdoc} - */ - public function getCacheControlDirective(string $key) - { - return \array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null; - } - - public function setCookie(Cookie $cookie) - { - $this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie; - $this->headerNames['set-cookie'] = 'Set-Cookie'; - } - - /** - * Removes a cookie from the array, but does not unset it in the browser. - */ - public function removeCookie(string $name, ?string $path = '/', string $domain = null) - { - if (null === $path) { - $path = '/'; - } - - unset($this->cookies[$domain][$path][$name]); - - if (empty($this->cookies[$domain][$path])) { - unset($this->cookies[$domain][$path]); - - if (empty($this->cookies[$domain])) { - unset($this->cookies[$domain]); - } - } - - if (empty($this->cookies)) { - unset($this->headerNames['set-cookie']); - } - } - - /** - * Returns an array with all cookies. - * - * @return Cookie[] - * - * @throws \InvalidArgumentException When the $format is invalid - */ - public function getCookies(string $format = self::COOKIES_FLAT) - { - if (!\in_array($format, [self::COOKIES_FLAT, self::COOKIES_ARRAY])) { - throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', [self::COOKIES_FLAT, self::COOKIES_ARRAY]))); - } - - if (self::COOKIES_ARRAY === $format) { - return $this->cookies; - } - - $flattenedCookies = []; - foreach ($this->cookies as $path) { - foreach ($path as $cookies) { - foreach ($cookies as $cookie) { - $flattenedCookies[] = $cookie; - } - } - } - - return $flattenedCookies; - } - - /** - * Clears a cookie in the browser. - */ - public function clearCookie(string $name, ?string $path = '/', string $domain = null, bool $secure = false, bool $httpOnly = true) - { - $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, null)); - } - - /** - * @see HeaderUtils::makeDisposition() - */ - public function makeDisposition(string $disposition, string $filename, string $filenameFallback = '') - { - return HeaderUtils::makeDisposition($disposition, $filename, $filenameFallback); - } - - /** - * Returns the calculated value of the cache-control header. - * - * This considers several other headers and calculates or modifies the - * cache-control header to a sensible, conservative value. - * - * @return string - */ - protected function computeCacheControlValue() - { - if (!$this->cacheControl) { - if ($this->has('Last-Modified') || $this->has('Expires')) { - return 'private, must-revalidate'; // allows for heuristic expiration (RFC 7234 Section 4.2.2) in the case of "Last-Modified" - } - - // conservative by default - return 'no-cache, private'; - } - - $header = $this->getCacheControlHeader(); - if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) { - return $header; - } - - // public if s-maxage is defined, private otherwise - if (!isset($this->cacheControl['s-maxage'])) { - return $header.', private'; - } - - return $header; - } - - private function initDate(): void - { - $now = \DateTime::createFromFormat('U', time()); - $now->setTimezone(new \DateTimeZone('UTC')); - $this->set('Date', $now->format('D, d M Y H:i:s').' GMT'); - } -} diff --git a/vendor/symfony/http-foundation/ServerBag.php b/vendor/symfony/http-foundation/ServerBag.php deleted file mode 100644 index 02c7091..0000000 --- a/vendor/symfony/http-foundation/ServerBag.php +++ /dev/null @@ -1,99 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * ServerBag is a container for HTTP headers from the $_SERVER variable. - * - * @author Fabien Potencier - * @author Bulat Shakirzyanov - * @author Robert Kiss - */ -class ServerBag extends ParameterBag -{ - /** - * Gets the HTTP headers. - * - * @return array - */ - public function getHeaders() - { - $headers = []; - foreach ($this->parameters as $key => $value) { - if (0 === strpos($key, 'HTTP_')) { - $headers[substr($key, 5)] = $value; - } elseif (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) { - $headers[$key] = $value; - } - } - - if (isset($this->parameters['PHP_AUTH_USER'])) { - $headers['PHP_AUTH_USER'] = $this->parameters['PHP_AUTH_USER']; - $headers['PHP_AUTH_PW'] = isset($this->parameters['PHP_AUTH_PW']) ? $this->parameters['PHP_AUTH_PW'] : ''; - } else { - /* - * php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default - * For this workaround to work, add these lines to your .htaccess file: - * RewriteCond %{HTTP:Authorization} .+ - * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] - * - * A sample .htaccess file: - * RewriteEngine On - * RewriteCond %{HTTP:Authorization} .+ - * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] - * RewriteCond %{REQUEST_FILENAME} !-f - * RewriteRule ^(.*)$ app.php [QSA,L] - */ - - $authorizationHeader = null; - if (isset($this->parameters['HTTP_AUTHORIZATION'])) { - $authorizationHeader = $this->parameters['HTTP_AUTHORIZATION']; - } elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) { - $authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION']; - } - - if (null !== $authorizationHeader) { - if (0 === stripos($authorizationHeader, 'basic ')) { - // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic - $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)), 2); - if (2 == \count($exploded)) { - list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded; - } - } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest '))) { - // In some circumstances PHP_AUTH_DIGEST needs to be set - $headers['PHP_AUTH_DIGEST'] = $authorizationHeader; - $this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader; - } elseif (0 === stripos($authorizationHeader, 'bearer ')) { - /* - * XXX: Since there is no PHP_AUTH_BEARER in PHP predefined variables, - * I'll just set $headers['AUTHORIZATION'] here. - * https://php.net/reserved.variables.server - */ - $headers['AUTHORIZATION'] = $authorizationHeader; - } - } - } - - if (isset($headers['AUTHORIZATION'])) { - return $headers; - } - - // PHP_AUTH_USER/PHP_AUTH_PW - if (isset($headers['PHP_AUTH_USER'])) { - $headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.$headers['PHP_AUTH_PW']); - } elseif (isset($headers['PHP_AUTH_DIGEST'])) { - $headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST']; - } - - return $headers; - } -} diff --git a/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php b/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php deleted file mode 100644 index aad6b61..0000000 --- a/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php +++ /dev/null @@ -1,148 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Attribute; - -/** - * This class relates to session attribute storage. - */ -class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Countable -{ - private $name = 'attributes'; - private $storageKey; - - protected $attributes = []; - - /** - * @param string $storageKey The key used to store attributes in the session - */ - public function __construct(string $storageKey = '_sf2_attributes') - { - $this->storageKey = $storageKey; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$attributes) - { - $this->attributes = &$attributes; - } - - /** - * {@inheritdoc} - */ - public function getStorageKey() - { - return $this->storageKey; - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - return \array_key_exists($name, $this->attributes); - } - - /** - * {@inheritdoc} - */ - public function get(string $name, $default = null) - { - return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; - } - - /** - * {@inheritdoc} - */ - public function set(string $name, $value) - { - $this->attributes[$name] = $value; - } - - /** - * {@inheritdoc} - */ - public function all() - { - return $this->attributes; - } - - /** - * {@inheritdoc} - */ - public function replace(array $attributes) - { - $this->attributes = []; - foreach ($attributes as $key => $value) { - $this->set($key, $value); - } - } - - /** - * {@inheritdoc} - */ - public function remove(string $name) - { - $retval = null; - if (\array_key_exists($name, $this->attributes)) { - $retval = $this->attributes[$name]; - unset($this->attributes[$name]); - } - - return $retval; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - $return = $this->attributes; - $this->attributes = []; - - return $return; - } - - /** - * Returns an iterator for attributes. - * - * @return \ArrayIterator An \ArrayIterator instance - */ - public function getIterator() - { - return new \ArrayIterator($this->attributes); - } - - /** - * Returns the number of attributes. - * - * @return int The number of attributes - */ - public function count() - { - return \count($this->attributes); - } -} diff --git a/vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php b/vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php deleted file mode 100644 index 7017b71..0000000 --- a/vendor/symfony/http-foundation/Session/Attribute/AttributeBagInterface.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Attribute; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * Attributes store. - * - * @author Drak - */ -interface AttributeBagInterface extends SessionBagInterface -{ - /** - * Checks if an attribute is defined. - * - * @return bool true if the attribute is defined, false otherwise - */ - public function has(string $name); - - /** - * Returns an attribute. - * - * @param mixed $default The default value if not found - * - * @return mixed - */ - public function get(string $name, $default = null); - - /** - * Sets an attribute. - * - * @param mixed $value - */ - public function set(string $name, $value); - - /** - * Returns attributes. - * - * @return array - */ - public function all(); - - public function replace(array $attributes); - - /** - * Removes an attribute. - * - * @return mixed The removed value or null when it does not exist - */ - public function remove(string $name); -} diff --git a/vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php b/vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php deleted file mode 100644 index 7e752dd..0000000 --- a/vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php +++ /dev/null @@ -1,157 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Attribute; - -/** - * This class provides structured storage of session attributes using - * a name spacing character in the key. - * - * @author Drak - */ -class NamespacedAttributeBag extends AttributeBag -{ - private $namespaceCharacter; - - /** - * @param string $storageKey Session storage key - * @param string $namespaceCharacter Namespace character to use in keys - */ - public function __construct(string $storageKey = '_sf2_attributes', string $namespaceCharacter = '/') - { - $this->namespaceCharacter = $namespaceCharacter; - parent::__construct($storageKey); - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - // reference mismatch: if fixed, re-introduced in array_key_exists; keep as it is - $attributes = $this->resolveAttributePath($name); - $name = $this->resolveKey($name); - - if (null === $attributes) { - return false; - } - - return \array_key_exists($name, $attributes); - } - - /** - * {@inheritdoc} - */ - public function get(string $name, $default = null) - { - // reference mismatch: if fixed, re-introduced in array_key_exists; keep as it is - $attributes = $this->resolveAttributePath($name); - $name = $this->resolveKey($name); - - if (null === $attributes) { - return $default; - } - - return \array_key_exists($name, $attributes) ? $attributes[$name] : $default; - } - - /** - * {@inheritdoc} - */ - public function set(string $name, $value) - { - $attributes = &$this->resolveAttributePath($name, true); - $name = $this->resolveKey($name); - $attributes[$name] = $value; - } - - /** - * {@inheritdoc} - */ - public function remove(string $name) - { - $retval = null; - $attributes = &$this->resolveAttributePath($name); - $name = $this->resolveKey($name); - if (null !== $attributes && \array_key_exists($name, $attributes)) { - $retval = $attributes[$name]; - unset($attributes[$name]); - } - - return $retval; - } - - /** - * Resolves a path in attributes property and returns it as a reference. - * - * This method allows structured namespacing of session attributes. - * - * @param string $name Key name - * @param bool $writeContext Write context, default false - * - * @return array|null - */ - protected function &resolveAttributePath(string $name, bool $writeContext = false) - { - $array = &$this->attributes; - $name = (0 === strpos($name, $this->namespaceCharacter)) ? substr($name, 1) : $name; - - // Check if there is anything to do, else return - if (!$name) { - return $array; - } - - $parts = explode($this->namespaceCharacter, $name); - if (\count($parts) < 2) { - if (!$writeContext) { - return $array; - } - - $array[$parts[0]] = []; - - return $array; - } - - unset($parts[\count($parts) - 1]); - - foreach ($parts as $part) { - if (null !== $array && !\array_key_exists($part, $array)) { - if (!$writeContext) { - $null = null; - - return $null; - } - - $array[$part] = []; - } - - $array = &$array[$part]; - } - - return $array; - } - - /** - * Resolves the key from the name. - * - * This is the last part in a dot separated string. - * - * @return string - */ - protected function resolveKey(string $name) - { - if (false !== $pos = strrpos($name, $this->namespaceCharacter)) { - $name = substr($name, $pos + 1); - } - - return $name; - } -} diff --git a/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php b/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php deleted file mode 100644 index 2707d64..0000000 --- a/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php +++ /dev/null @@ -1,161 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Flash; - -/** - * AutoExpireFlashBag flash message container. - * - * @author Drak - */ -class AutoExpireFlashBag implements FlashBagInterface -{ - private $name = 'flashes'; - private $flashes = ['display' => [], 'new' => []]; - private $storageKey; - - /** - * @param string $storageKey The key used to store flashes in the session - */ - public function __construct(string $storageKey = '_symfony_flashes') - { - $this->storageKey = $storageKey; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$flashes) - { - $this->flashes = &$flashes; - - // The logic: messages from the last request will be stored in new, so we move them to previous - // This request we will show what is in 'display'. What is placed into 'new' this time round will - // be moved to display next time round. - $this->flashes['display'] = \array_key_exists('new', $this->flashes) ? $this->flashes['new'] : []; - $this->flashes['new'] = []; - } - - /** - * {@inheritdoc} - */ - public function add(string $type, $message) - { - $this->flashes['new'][$type][] = $message; - } - - /** - * {@inheritdoc} - */ - public function peek(string $type, array $default = []) - { - return $this->has($type) ? $this->flashes['display'][$type] : $default; - } - - /** - * {@inheritdoc} - */ - public function peekAll() - { - return \array_key_exists('display', $this->flashes) ? (array) $this->flashes['display'] : []; - } - - /** - * {@inheritdoc} - */ - public function get(string $type, array $default = []) - { - $return = $default; - - if (!$this->has($type)) { - return $return; - } - - if (isset($this->flashes['display'][$type])) { - $return = $this->flashes['display'][$type]; - unset($this->flashes['display'][$type]); - } - - return $return; - } - - /** - * {@inheritdoc} - */ - public function all() - { - $return = $this->flashes['display']; - $this->flashes['display'] = []; - - return $return; - } - - /** - * {@inheritdoc} - */ - public function setAll(array $messages) - { - $this->flashes['new'] = $messages; - } - - /** - * {@inheritdoc} - */ - public function set(string $type, $messages) - { - $this->flashes['new'][$type] = (array) $messages; - } - - /** - * {@inheritdoc} - */ - public function has(string $type) - { - return \array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type]; - } - - /** - * {@inheritdoc} - */ - public function keys() - { - return array_keys($this->flashes['display']); - } - - /** - * {@inheritdoc} - */ - public function getStorageKey() - { - return $this->storageKey; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - return $this->all(); - } -} diff --git a/vendor/symfony/http-foundation/Session/Flash/FlashBag.php b/vendor/symfony/http-foundation/Session/Flash/FlashBag.php deleted file mode 100644 index 88df750..0000000 --- a/vendor/symfony/http-foundation/Session/Flash/FlashBag.php +++ /dev/null @@ -1,152 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Flash; - -/** - * FlashBag flash message container. - * - * @author Drak - */ -class FlashBag implements FlashBagInterface -{ - private $name = 'flashes'; - private $flashes = []; - private $storageKey; - - /** - * @param string $storageKey The key used to store flashes in the session - */ - public function __construct(string $storageKey = '_symfony_flashes') - { - $this->storageKey = $storageKey; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$flashes) - { - $this->flashes = &$flashes; - } - - /** - * {@inheritdoc} - */ - public function add(string $type, $message) - { - $this->flashes[$type][] = $message; - } - - /** - * {@inheritdoc} - */ - public function peek(string $type, array $default = []) - { - return $this->has($type) ? $this->flashes[$type] : $default; - } - - /** - * {@inheritdoc} - */ - public function peekAll() - { - return $this->flashes; - } - - /** - * {@inheritdoc} - */ - public function get(string $type, array $default = []) - { - if (!$this->has($type)) { - return $default; - } - - $return = $this->flashes[$type]; - - unset($this->flashes[$type]); - - return $return; - } - - /** - * {@inheritdoc} - */ - public function all() - { - $return = $this->peekAll(); - $this->flashes = []; - - return $return; - } - - /** - * {@inheritdoc} - */ - public function set(string $type, $messages) - { - $this->flashes[$type] = (array) $messages; - } - - /** - * {@inheritdoc} - */ - public function setAll(array $messages) - { - $this->flashes = $messages; - } - - /** - * {@inheritdoc} - */ - public function has(string $type) - { - return \array_key_exists($type, $this->flashes) && $this->flashes[$type]; - } - - /** - * {@inheritdoc} - */ - public function keys() - { - return array_keys($this->flashes); - } - - /** - * {@inheritdoc} - */ - public function getStorageKey() - { - return $this->storageKey; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - return $this->all(); - } -} diff --git a/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php b/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php deleted file mode 100644 index 8713e71..0000000 --- a/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php +++ /dev/null @@ -1,88 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Flash; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * FlashBagInterface. - * - * @author Drak - */ -interface FlashBagInterface extends SessionBagInterface -{ - /** - * Adds a flash message for the given type. - * - * @param mixed $message - */ - public function add(string $type, $message); - - /** - * Registers one or more messages for a given type. - * - * @param string|array $messages - */ - public function set(string $type, $messages); - - /** - * Gets flash messages for a given type. - * - * @param string $type Message category type - * @param array $default Default value if $type does not exist - * - * @return array - */ - public function peek(string $type, array $default = []); - - /** - * Gets all flash messages. - * - * @return array - */ - public function peekAll(); - - /** - * Gets and clears flash from the stack. - * - * @param array $default Default value if $type does not exist - * - * @return array - */ - public function get(string $type, array $default = []); - - /** - * Gets and clears flashes from the stack. - * - * @return array - */ - public function all(); - - /** - * Sets all flash messages. - */ - public function setAll(array $messages); - - /** - * Has flash messages for a given type? - * - * @return bool - */ - public function has(string $type); - - /** - * Returns a list of all defined types. - * - * @return array - */ - public function keys(); -} diff --git a/vendor/symfony/http-foundation/Session/Session.php b/vendor/symfony/http-foundation/Session/Session.php deleted file mode 100644 index 89071b8..0000000 --- a/vendor/symfony/http-foundation/Session/Session.php +++ /dev/null @@ -1,268 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; -use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; -use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; -use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; -use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; -use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; - -/** - * @author Fabien Potencier - * @author Drak - */ -class Session implements SessionInterface, \IteratorAggregate, \Countable -{ - protected $storage; - - private $flashName; - private $attributeName; - private $data = []; - private $usageIndex = 0; - - public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null) - { - $this->storage = $storage ?: new NativeSessionStorage(); - - $attributes = $attributes ?: new AttributeBag(); - $this->attributeName = $attributes->getName(); - $this->registerBag($attributes); - - $flashes = $flashes ?: new FlashBag(); - $this->flashName = $flashes->getName(); - $this->registerBag($flashes); - } - - /** - * {@inheritdoc} - */ - public function start() - { - return $this->storage->start(); - } - - /** - * {@inheritdoc} - */ - public function has(string $name) - { - return $this->getAttributeBag()->has($name); - } - - /** - * {@inheritdoc} - */ - public function get(string $name, $default = null) - { - return $this->getAttributeBag()->get($name, $default); - } - - /** - * {@inheritdoc} - */ - public function set(string $name, $value) - { - $this->getAttributeBag()->set($name, $value); - } - - /** - * {@inheritdoc} - */ - public function all() - { - return $this->getAttributeBag()->all(); - } - - /** - * {@inheritdoc} - */ - public function replace(array $attributes) - { - $this->getAttributeBag()->replace($attributes); - } - - /** - * {@inheritdoc} - */ - public function remove(string $name) - { - return $this->getAttributeBag()->remove($name); - } - - /** - * {@inheritdoc} - */ - public function clear() - { - $this->getAttributeBag()->clear(); - } - - /** - * {@inheritdoc} - */ - public function isStarted() - { - return $this->storage->isStarted(); - } - - /** - * Returns an iterator for attributes. - * - * @return \ArrayIterator An \ArrayIterator instance - */ - public function getIterator() - { - return new \ArrayIterator($this->getAttributeBag()->all()); - } - - /** - * Returns the number of attributes. - * - * @return int - */ - public function count() - { - return \count($this->getAttributeBag()->all()); - } - - public function &getUsageIndex(): int - { - return $this->usageIndex; - } - - /** - * @internal - */ - public function isEmpty(): bool - { - if ($this->isStarted()) { - ++$this->usageIndex; - } - foreach ($this->data as &$data) { - if (!empty($data)) { - return false; - } - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function invalidate(int $lifetime = null) - { - $this->storage->clear(); - - return $this->migrate(true, $lifetime); - } - - /** - * {@inheritdoc} - */ - public function migrate(bool $destroy = false, int $lifetime = null) - { - return $this->storage->regenerate($destroy, $lifetime); - } - - /** - * {@inheritdoc} - */ - public function save() - { - $this->storage->save(); - } - - /** - * {@inheritdoc} - */ - public function getId() - { - return $this->storage->getId(); - } - - /** - * {@inheritdoc} - */ - public function setId(string $id) - { - if ($this->storage->getId() !== $id) { - $this->storage->setId($id); - } - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->storage->getName(); - } - - /** - * {@inheritdoc} - */ - public function setName(string $name) - { - $this->storage->setName($name); - } - - /** - * {@inheritdoc} - */ - public function getMetadataBag() - { - ++$this->usageIndex; - - return $this->storage->getMetadataBag(); - } - - /** - * {@inheritdoc} - */ - public function registerBag(SessionBagInterface $bag) - { - $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->usageIndex)); - } - - /** - * {@inheritdoc} - */ - public function getBag(string $name) - { - $bag = $this->storage->getBag($name); - - return method_exists($bag, 'getBag') ? $bag->getBag() : $bag; - } - - /** - * Gets the flashbag interface. - * - * @return FlashBagInterface - */ - public function getFlashBag() - { - return $this->getBag($this->flashName); - } - - /** - * Gets the attributebag interface. - * - * Note that this method was added to help with IDE autocompletion. - */ - private function getAttributeBag(): AttributeBagInterface - { - return $this->getBag($this->attributeName); - } -} diff --git a/vendor/symfony/http-foundation/Session/SessionBagInterface.php b/vendor/symfony/http-foundation/Session/SessionBagInterface.php deleted file mode 100644 index 8e37d06..0000000 --- a/vendor/symfony/http-foundation/Session/SessionBagInterface.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * Session Bag store. - * - * @author Drak - */ -interface SessionBagInterface -{ - /** - * Gets this bag's name. - * - * @return string - */ - public function getName(); - - /** - * Initializes the Bag. - */ - public function initialize(array &$array); - - /** - * Gets the storage key for this bag. - * - * @return string - */ - public function getStorageKey(); - - /** - * Clears out data from bag. - * - * @return mixed Whatever data was contained - */ - public function clear(); -} diff --git a/vendor/symfony/http-foundation/Session/SessionBagProxy.php b/vendor/symfony/http-foundation/Session/SessionBagProxy.php deleted file mode 100644 index 0ae8231..0000000 --- a/vendor/symfony/http-foundation/Session/SessionBagProxy.php +++ /dev/null @@ -1,83 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * @author Nicolas Grekas - * - * @internal - */ -final class SessionBagProxy implements SessionBagInterface -{ - private $bag; - private $data; - private $usageIndex; - - public function __construct(SessionBagInterface $bag, array &$data, ?int &$usageIndex) - { - $this->bag = $bag; - $this->data = &$data; - $this->usageIndex = &$usageIndex; - } - - public function getBag(): SessionBagInterface - { - ++$this->usageIndex; - - return $this->bag; - } - - public function isEmpty(): bool - { - if (!isset($this->data[$this->bag->getStorageKey()])) { - return true; - } - ++$this->usageIndex; - - return empty($this->data[$this->bag->getStorageKey()]); - } - - /** - * {@inheritdoc} - */ - public function getName(): string - { - return $this->bag->getName(); - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$array): void - { - ++$this->usageIndex; - $this->data[$this->bag->getStorageKey()] = &$array; - - $this->bag->initialize($array); - } - - /** - * {@inheritdoc} - */ - public function getStorageKey(): string - { - return $this->bag->getStorageKey(); - } - - /** - * {@inheritdoc} - */ - public function clear() - { - return $this->bag->clear(); - } -} diff --git a/vendor/symfony/http-foundation/Session/SessionInterface.php b/vendor/symfony/http-foundation/Session/SessionInterface.php deleted file mode 100644 index b2f09fd..0000000 --- a/vendor/symfony/http-foundation/Session/SessionInterface.php +++ /dev/null @@ -1,166 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; - -/** - * Interface for the session. - * - * @author Drak - */ -interface SessionInterface -{ - /** - * Starts the session storage. - * - * @return bool - * - * @throws \RuntimeException if session fails to start - */ - public function start(); - - /** - * Returns the session ID. - * - * @return string - */ - public function getId(); - - /** - * Sets the session ID. - */ - public function setId(string $id); - - /** - * Returns the session name. - * - * @return string - */ - public function getName(); - - /** - * Sets the session name. - */ - public function setName(string $name); - - /** - * Invalidates the current session. - * - * Clears all session attributes and flashes and regenerates the - * session and deletes the old session from persistence. - * - * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - * - * @return bool - */ - public function invalidate(int $lifetime = null); - - /** - * Migrates the current session to a new session id while maintaining all - * session attributes. - * - * @param bool $destroy Whether to delete the old session or leave it to garbage collection - * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - * - * @return bool - */ - public function migrate(bool $destroy = false, int $lifetime = null); - - /** - * Force the session to be saved and closed. - * - * This method is generally not required for real sessions as - * the session will be automatically saved at the end of - * code execution. - */ - public function save(); - - /** - * Checks if an attribute is defined. - * - * @return bool - */ - public function has(string $name); - - /** - * Returns an attribute. - * - * @param mixed $default The default value if not found - * - * @return mixed - */ - public function get(string $name, $default = null); - - /** - * Sets an attribute. - * - * @param mixed $value - */ - public function set(string $name, $value); - - /** - * Returns attributes. - * - * @return array - */ - public function all(); - - /** - * Sets attributes. - */ - public function replace(array $attributes); - - /** - * Removes an attribute. - * - * @return mixed The removed value or null when it does not exist - */ - public function remove(string $name); - - /** - * Clears all attributes. - */ - public function clear(); - - /** - * Checks if the session was started. - * - * @return bool - */ - public function isStarted(); - - /** - * Registers a SessionBagInterface with the session. - */ - public function registerBag(SessionBagInterface $bag); - - /** - * Gets a bag instance by name. - * - * @return SessionBagInterface - */ - public function getBag(string $name); - - /** - * Gets session meta. - * - * @return MetadataBag - */ - public function getMetadataBag(); -} diff --git a/vendor/symfony/http-foundation/Session/SessionUtils.php b/vendor/symfony/http-foundation/Session/SessionUtils.php deleted file mode 100644 index b5bce4a..0000000 --- a/vendor/symfony/http-foundation/Session/SessionUtils.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session; - -/** - * Session utility functions. - * - * @author Nicolas Grekas - * @author Rémon van de Kamp - * - * @internal - */ -final class SessionUtils -{ - /** - * Finds the session header amongst the headers that are to be sent, removes it, and returns - * it so the caller can process it further. - */ - public static function popSessionCookie(string $sessionName, string $sessionId): ?string - { - $sessionCookie = null; - $sessionCookiePrefix = sprintf(' %s=', urlencode($sessionName)); - $sessionCookieWithId = sprintf('%s%s;', $sessionCookiePrefix, urlencode($sessionId)); - $otherCookies = []; - foreach (headers_list() as $h) { - if (0 !== stripos($h, 'Set-Cookie:')) { - continue; - } - if (11 === strpos($h, $sessionCookiePrefix, 11)) { - $sessionCookie = $h; - - if (11 !== strpos($h, $sessionCookieWithId, 11)) { - $otherCookies[] = $h; - } - } else { - $otherCookies[] = $h; - } - } - if (null === $sessionCookie) { - return null; - } - - header_remove('Set-Cookie'); - foreach ($otherCookies as $h) { - header($h, false); - } - - return $sessionCookie; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php deleted file mode 100644 index 0618035..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php +++ /dev/null @@ -1,141 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Symfony\Component\HttpFoundation\Session\SessionUtils; - -/** - * This abstract session handler provides a generic implementation - * of the PHP 7.0 SessionUpdateTimestampHandlerInterface, - * enabling strict and lazy session handling. - * - * @author Nicolas Grekas - */ -abstract class AbstractSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - private $sessionName; - private $prefetchId; - private $prefetchData; - private $newSessionId; - private $igbinaryEmptyData; - - /** - * @return bool - */ - public function open($savePath, $sessionName) - { - $this->sessionName = $sessionName; - if (!headers_sent() && !ini_get('session.cache_limiter') && '0' !== ini_get('session.cache_limiter')) { - header(sprintf('Cache-Control: max-age=%d, private, must-revalidate', 60 * (int) ini_get('session.cache_expire'))); - } - - return true; - } - - /** - * @return string - */ - abstract protected function doRead(string $sessionId); - - /** - * @return bool - */ - abstract protected function doWrite(string $sessionId, string $data); - - /** - * @return bool - */ - abstract protected function doDestroy(string $sessionId); - - /** - * @return bool - */ - public function validateId($sessionId) - { - $this->prefetchData = $this->read($sessionId); - $this->prefetchId = $sessionId; - - return '' !== $this->prefetchData; - } - - /** - * @return string - */ - public function read($sessionId) - { - if (null !== $this->prefetchId) { - $prefetchId = $this->prefetchId; - $prefetchData = $this->prefetchData; - $this->prefetchId = $this->prefetchData = null; - - if ($prefetchId === $sessionId || '' === $prefetchData) { - $this->newSessionId = '' === $prefetchData ? $sessionId : null; - - return $prefetchData; - } - } - - $data = $this->doRead($sessionId); - $this->newSessionId = '' === $data ? $sessionId : null; - - return $data; - } - - /** - * @return bool - */ - public function write($sessionId, $data) - { - if (null === $this->igbinaryEmptyData) { - // see https://github.com/igbinary/igbinary/issues/146 - $this->igbinaryEmptyData = \function_exists('igbinary_serialize') ? igbinary_serialize([]) : ''; - } - if ('' === $data || $this->igbinaryEmptyData === $data) { - return $this->destroy($sessionId); - } - $this->newSessionId = null; - - return $this->doWrite($sessionId, $data); - } - - /** - * @return bool - */ - public function destroy($sessionId) - { - if (!headers_sent() && filter_var(ini_get('session.use_cookies'), FILTER_VALIDATE_BOOLEAN)) { - if (!$this->sessionName) { - throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', \get_class($this))); - } - $cookie = SessionUtils::popSessionCookie($this->sessionName, $sessionId); - - /* - * We send an invalidation Set-Cookie header (zero lifetime) - * when either the session was started or a cookie with - * the session name was sent by the client (in which case - * we know it's invalid as a valid session cookie would've - * started the session). - */ - if (null === $cookie || isset($_COOKIE[$this->sessionName])) { - if (\PHP_VERSION_ID < 70300) { - setcookie($this->sessionName, '', 0, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), filter_var(ini_get('session.cookie_secure'), FILTER_VALIDATE_BOOLEAN), filter_var(ini_get('session.cookie_httponly'), FILTER_VALIDATE_BOOLEAN)); - } else { - $params = session_get_cookie_params(); - unset($params['lifetime']); - setcookie($this->sessionName, '', $params); - } - } - } - - return $this->newSessionId === $sessionId || $this->doDestroy($sessionId); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php deleted file mode 100644 index 8896964..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ /dev/null @@ -1,119 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Memcached based session storage handler based on the Memcached class - * provided by the PHP memcached extension. - * - * @see https://php.net/memcached - * - * @author Drak - */ -class MemcachedSessionHandler extends AbstractSessionHandler -{ - private $memcached; - - /** - * @var int Time to live in seconds - */ - private $ttl; - - /** - * @var string Key prefix for shared environments - */ - private $prefix; - - /** - * Constructor. - * - * List of available options: - * * prefix: The prefix to use for the memcached keys in order to avoid collision - * * expiretime: The time to live in seconds. - * - * @throws \InvalidArgumentException When unsupported options are passed - */ - public function __construct(\Memcached $memcached, array $options = []) - { - $this->memcached = $memcached; - - if ($diff = array_diff(array_keys($options), ['prefix', 'expiretime'])) { - throw new \InvalidArgumentException(sprintf('The following options are not supported "%s"', implode(', ', $diff))); - } - - $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400; - $this->prefix = isset($options['prefix']) ? $options['prefix'] : 'sf2s'; - } - - /** - * @return bool - */ - public function close() - { - return $this->memcached->quit(); - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId) - { - return $this->memcached->get($this->prefix.$sessionId) ?: ''; - } - - /** - * @return bool - */ - public function updateTimestamp($sessionId, $data) - { - $this->memcached->touch($this->prefix.$sessionId, time() + $this->ttl); - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - return $this->memcached->set($this->prefix.$sessionId, $data, time() + $this->ttl); - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - $result = $this->memcached->delete($this->prefix.$sessionId); - - return $result || \Memcached::RES_NOTFOUND == $this->memcached->getResultCode(); - } - - /** - * @return bool - */ - public function gc($maxlifetime) - { - // not required here because memcached will auto expire the records anyhow. - return true; - } - - /** - * Return a Memcached instance. - * - * @return \Memcached - */ - protected function getMemcached() - { - return $this->memcached; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php deleted file mode 100644 index c6b16d1..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php +++ /dev/null @@ -1,124 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Migrating session handler for migrating from one handler to another. It reads - * from the current handler and writes both the current and new ones. - * - * It ignores errors from the new handler. - * - * @author Ross Motley - * @author Oliver Radwell - */ -class MigratingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - private $currentHandler; - private $writeOnlyHandler; - - public function __construct(\SessionHandlerInterface $currentHandler, \SessionHandlerInterface $writeOnlyHandler) - { - if (!$currentHandler instanceof \SessionUpdateTimestampHandlerInterface) { - $currentHandler = new StrictSessionHandler($currentHandler); - } - if (!$writeOnlyHandler instanceof \SessionUpdateTimestampHandlerInterface) { - $writeOnlyHandler = new StrictSessionHandler($writeOnlyHandler); - } - - $this->currentHandler = $currentHandler; - $this->writeOnlyHandler = $writeOnlyHandler; - } - - /** - * @return bool - */ - public function close() - { - $result = $this->currentHandler->close(); - $this->writeOnlyHandler->close(); - - return $result; - } - - /** - * @return bool - */ - public function destroy($sessionId) - { - $result = $this->currentHandler->destroy($sessionId); - $this->writeOnlyHandler->destroy($sessionId); - - return $result; - } - - /** - * @return bool - */ - public function gc($maxlifetime) - { - $result = $this->currentHandler->gc($maxlifetime); - $this->writeOnlyHandler->gc($maxlifetime); - - return $result; - } - - /** - * @return bool - */ - public function open($savePath, $sessionName) - { - $result = $this->currentHandler->open($savePath, $sessionName); - $this->writeOnlyHandler->open($savePath, $sessionName); - - return $result; - } - - /** - * @return string - */ - public function read($sessionId) - { - // No reading from new handler until switch-over - return $this->currentHandler->read($sessionId); - } - - /** - * @return bool - */ - public function write($sessionId, $sessionData) - { - $result = $this->currentHandler->write($sessionId, $sessionData); - $this->writeOnlyHandler->write($sessionId, $sessionData); - - return $result; - } - - /** - * @return bool - */ - public function validateId($sessionId) - { - // No reading from new handler until switch-over - return $this->currentHandler->validateId($sessionId); - } - - /** - * @return bool - */ - public function updateTimestamp($sessionId, $sessionData) - { - $result = $this->currentHandler->updateTimestamp($sessionId, $sessionData); - $this->writeOnlyHandler->updateTimestamp($sessionId, $sessionData); - - return $result; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php deleted file mode 100644 index a6889e4..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ /dev/null @@ -1,187 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Session handler using the mongodb/mongodb package and MongoDB driver extension. - * - * @author Markus Bachmann - * - * @see https://packagist.org/packages/mongodb/mongodb - * @see https://php.net/mongodb - */ -class MongoDbSessionHandler extends AbstractSessionHandler -{ - private $mongo; - - /** - * @var \MongoDB\Collection - */ - private $collection; - - /** - * @var array - */ - private $options; - - /** - * Constructor. - * - * List of available options: - * * database: The name of the database [required] - * * collection: The name of the collection [required] - * * id_field: The field name for storing the session id [default: _id] - * * data_field: The field name for storing the session data [default: data] - * * time_field: The field name for storing the timestamp [default: time] - * * expiry_field: The field name for storing the expiry-timestamp [default: expires_at]. - * - * It is strongly recommended to put an index on the `expiry_field` for - * garbage-collection. Alternatively it's possible to automatically expire - * the sessions in the database as described below: - * - * A TTL collections can be used on MongoDB 2.2+ to cleanup expired sessions - * automatically. Such an index can for example look like this: - * - * db..ensureIndex( - * { "": 1 }, - * { "expireAfterSeconds": 0 } - * ) - * - * More details on: https://docs.mongodb.org/manual/tutorial/expire-data/ - * - * If you use such an index, you can drop `gc_probability` to 0 since - * no garbage-collection is required. - * - * @throws \InvalidArgumentException When "database" or "collection" not provided - */ - public function __construct(\MongoDB\Client $mongo, array $options) - { - if (!isset($options['database']) || !isset($options['collection'])) { - throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler'); - } - - $this->mongo = $mongo; - - $this->options = array_merge([ - 'id_field' => '_id', - 'data_field' => 'data', - 'time_field' => 'time', - 'expiry_field' => 'expires_at', - ], $options); - } - - /** - * @return bool - */ - public function close() - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - $this->getCollection()->deleteOne([ - $this->options['id_field'] => $sessionId, - ]); - - return true; - } - - /** - * @return bool - */ - public function gc($maxlifetime) - { - $this->getCollection()->deleteMany([ - $this->options['expiry_field'] => ['$lt' => new \MongoDB\BSON\UTCDateTime()], - ]); - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - $expiry = new \MongoDB\BSON\UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000); - - $fields = [ - $this->options['time_field'] => new \MongoDB\BSON\UTCDateTime(), - $this->options['expiry_field'] => $expiry, - $this->options['data_field'] => new \MongoDB\BSON\Binary($data, \MongoDB\BSON\Binary::TYPE_OLD_BINARY), - ]; - - $this->getCollection()->updateOne( - [$this->options['id_field'] => $sessionId], - ['$set' => $fields], - ['upsert' => true] - ); - - return true; - } - - /** - * @return bool - */ - public function updateTimestamp($sessionId, $data) - { - $expiry = new \MongoDB\BSON\UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000); - - $this->getCollection()->updateOne( - [$this->options['id_field'] => $sessionId], - ['$set' => [ - $this->options['time_field'] => new \MongoDB\BSON\UTCDateTime(), - $this->options['expiry_field'] => $expiry, - ]] - ); - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId) - { - $dbData = $this->getCollection()->findOne([ - $this->options['id_field'] => $sessionId, - $this->options['expiry_field'] => ['$gte' => new \MongoDB\BSON\UTCDateTime()], - ]); - - if (null === $dbData) { - return ''; - } - - return $dbData[$this->options['data_field']]->getData(); - } - - private function getCollection(): \MongoDB\Collection - { - if (null === $this->collection) { - $this->collection = $this->mongo->selectCollection($this->options['database'], $this->options['collection']); - } - - return $this->collection; - } - - /** - * @return \MongoDB\Client - */ - protected function getMongo() - { - return $this->mongo; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php deleted file mode 100644 index bdfc9d8..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Native session handler using PHP's built in file storage. - * - * @author Drak - */ -class NativeFileSessionHandler extends \SessionHandler -{ - /** - * @param string $savePath Path of directory to save session files - * Default null will leave setting as defined by PHP. - * '/path', 'N;/path', or 'N;octal-mode;/path - * - * @see https://php.net/session.configuration#ini.session.save-path for further details. - * - * @throws \InvalidArgumentException On invalid $savePath - * @throws \RuntimeException When failing to create the save directory - */ - public function __construct(string $savePath = null) - { - if (null === $savePath) { - $savePath = ini_get('session.save_path'); - } - - $baseDir = $savePath; - - if ($count = substr_count($savePath, ';')) { - if ($count > 2) { - throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'', $savePath)); - } - - // characters after last ';' are the path - $baseDir = ltrim(strrchr($savePath, ';'), ';'); - } - - if ($baseDir && !is_dir($baseDir) && !@mkdir($baseDir, 0777, true) && !is_dir($baseDir)) { - throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"', $baseDir)); - } - - ini_set('session.save_path', $savePath); - ini_set('session.save_handler', 'files'); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php deleted file mode 100644 index aa0e595..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Can be used in unit testing or in a situations where persisted sessions are not desired. - * - * @author Drak - */ -class NullSessionHandler extends AbstractSessionHandler -{ - /** - * @return bool - */ - public function close() - { - return true; - } - - /** - * @return bool - */ - public function validateId($sessionId) - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId) - { - return ''; - } - - /** - * @return bool - */ - public function updateTimestamp($sessionId, $data) - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - return true; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - return true; - } - - /** - * @return bool - */ - public function gc($maxlifetime) - { - return true; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php deleted file mode 100644 index 74412e0..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php +++ /dev/null @@ -1,899 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Session handler using a PDO connection to read and write data. - * - * It works with MySQL, PostgreSQL, Oracle, SQL Server and SQLite and implements - * different locking strategies to handle concurrent access to the same session. - * Locking is necessary to prevent loss of data due to race conditions and to keep - * the session data consistent between read() and write(). With locking, requests - * for the same session will wait until the other one finished writing. For this - * reason it's best practice to close a session as early as possible to improve - * concurrency. PHPs internal files session handler also implements locking. - * - * Attention: Since SQLite does not support row level locks but locks the whole database, - * it means only one session can be accessed at a time. Even different sessions would wait - * for another to finish. So saving session in SQLite should only be considered for - * development or prototypes. - * - * Session data is a binary string that can contain non-printable characters like the null byte. - * For this reason it must be saved in a binary column in the database like BLOB in MySQL. - * Saving it in a character column could corrupt the data. You can use createTable() - * to initialize a correctly defined table. - * - * @see https://php.net/sessionhandlerinterface - * - * @author Fabien Potencier - * @author Michael Williams - * @author Tobias Schultze - */ -class PdoSessionHandler extends AbstractSessionHandler -{ - /** - * No locking is done. This means sessions are prone to loss of data due to - * race conditions of concurrent requests to the same session. The last session - * write will win in this case. It might be useful when you implement your own - * logic to deal with this like an optimistic approach. - */ - const LOCK_NONE = 0; - - /** - * Creates an application-level lock on a session. The disadvantage is that the - * lock is not enforced by the database and thus other, unaware parts of the - * application could still concurrently modify the session. The advantage is it - * does not require a transaction. - * This mode is not available for SQLite and not yet implemented for oci and sqlsrv. - */ - const LOCK_ADVISORY = 1; - - /** - * Issues a real row lock. Since it uses a transaction between opening and - * closing a session, you have to be careful when you use same database connection - * that you also use for your application logic. This mode is the default because - * it's the only reliable solution across DBMSs. - */ - const LOCK_TRANSACTIONAL = 2; - - private const MAX_LIFETIME = 315576000; - - /** - * @var \PDO|null PDO instance or null when not connected yet - */ - private $pdo; - - /** - * @var string|false|null DSN string or null for session.save_path or false when lazy connection disabled - */ - private $dsn = false; - - /** - * @var string Database driver - */ - private $driver; - - /** - * @var string Table name - */ - private $table = 'sessions'; - - /** - * @var string Column for session id - */ - private $idCol = 'sess_id'; - - /** - * @var string Column for session data - */ - private $dataCol = 'sess_data'; - - /** - * @var string Column for lifetime - */ - private $lifetimeCol = 'sess_lifetime'; - - /** - * @var string Column for timestamp - */ - private $timeCol = 'sess_time'; - - /** - * @var string Username when lazy-connect - */ - private $username = ''; - - /** - * @var string Password when lazy-connect - */ - private $password = ''; - - /** - * @var array Connection options when lazy-connect - */ - private $connectionOptions = []; - - /** - * @var int The strategy for locking, see constants - */ - private $lockMode = self::LOCK_TRANSACTIONAL; - - /** - * It's an array to support multiple reads before closing which is manual, non-standard usage. - * - * @var \PDOStatement[] An array of statements to release advisory locks - */ - private $unlockStatements = []; - - /** - * @var bool True when the current session exists but expired according to session.gc_maxlifetime - */ - private $sessionExpired = false; - - /** - * @var bool Whether a transaction is active - */ - private $inTransaction = false; - - /** - * @var bool Whether gc() has been called - */ - private $gcCalled = false; - - /** - * You can either pass an existing database connection as PDO instance or - * pass a DSN string that will be used to lazy-connect to the database - * when the session is actually used. Furthermore it's possible to pass null - * which will then use the session.save_path ini setting as PDO DSN parameter. - * - * List of available options: - * * db_table: The name of the table [default: sessions] - * * db_id_col: The column where to store the session id [default: sess_id] - * * db_data_col: The column where to store the session data [default: sess_data] - * * db_lifetime_col: The column where to store the lifetime [default: sess_lifetime] - * * db_time_col: The column where to store the timestamp [default: sess_time] - * * db_username: The username when lazy-connect [default: ''] - * * db_password: The password when lazy-connect [default: ''] - * * db_connection_options: An array of driver-specific connection options [default: []] - * * lock_mode: The strategy for locking, see constants [default: LOCK_TRANSACTIONAL] - * - * @param \PDO|string|null $pdoOrDsn A \PDO instance or DSN string or URL string or null - * - * @throws \InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION - */ - public function __construct($pdoOrDsn = null, array $options = []) - { - if ($pdoOrDsn instanceof \PDO) { - if (\PDO::ERRMODE_EXCEPTION !== $pdoOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { - throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION))', __CLASS__)); - } - - $this->pdo = $pdoOrDsn; - $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); - } elseif (\is_string($pdoOrDsn) && false !== strpos($pdoOrDsn, '://')) { - $this->dsn = $this->buildDsnFromUrl($pdoOrDsn); - } else { - $this->dsn = $pdoOrDsn; - } - - $this->table = isset($options['db_table']) ? $options['db_table'] : $this->table; - $this->idCol = isset($options['db_id_col']) ? $options['db_id_col'] : $this->idCol; - $this->dataCol = isset($options['db_data_col']) ? $options['db_data_col'] : $this->dataCol; - $this->lifetimeCol = isset($options['db_lifetime_col']) ? $options['db_lifetime_col'] : $this->lifetimeCol; - $this->timeCol = isset($options['db_time_col']) ? $options['db_time_col'] : $this->timeCol; - $this->username = isset($options['db_username']) ? $options['db_username'] : $this->username; - $this->password = isset($options['db_password']) ? $options['db_password'] : $this->password; - $this->connectionOptions = isset($options['db_connection_options']) ? $options['db_connection_options'] : $this->connectionOptions; - $this->lockMode = isset($options['lock_mode']) ? $options['lock_mode'] : $this->lockMode; - } - - /** - * Creates the table to store sessions which can be called once for setup. - * - * Session ID is saved in a column of maximum length 128 because that is enough even - * for a 512 bit configured session.hash_function like Whirlpool. Session data is - * saved in a BLOB. One could also use a shorter inlined varbinary column - * if one was sure the data fits into it. - * - * @throws \PDOException When the table already exists - * @throws \DomainException When an unsupported PDO driver is used - */ - public function createTable() - { - // connect if we are not yet - $this->getConnection(); - - switch ($this->driver) { - case 'mysql': - // We use varbinary for the ID column because it prevents unwanted conversions: - // - character set conversions between server and client - // - trailing space removal - // - case-insensitivity - // - language processing like é == e - $sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB"; - break; - case 'sqlite': - $sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; - break; - case 'pgsql': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; - break; - case 'oci': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR2(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; - break; - case 'sqlsrv': - $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; - break; - default: - throw new \DomainException(sprintf('Creating the session table is currently not implemented for PDO driver "%s".', $this->driver)); - } - - try { - $this->pdo->exec($sql); - $this->pdo->exec("CREATE INDEX EXPIRY ON $this->table ($this->lifetimeCol)"); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - } - - /** - * Returns true when the current session exists but expired according to session.gc_maxlifetime. - * - * Can be used to distinguish between a new session and one that expired due to inactivity. - * - * @return bool Whether current session expired - */ - public function isSessionExpired() - { - return $this->sessionExpired; - } - - /** - * @return bool - */ - public function open($savePath, $sessionName) - { - $this->sessionExpired = false; - - if (null === $this->pdo) { - $this->connect($this->dsn ?: $savePath); - } - - return parent::open($savePath, $sessionName); - } - - /** - * @return string - */ - public function read($sessionId) - { - try { - return parent::read($sessionId); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - } - - /** - * @return bool - */ - public function gc($maxlifetime) - { - // We delay gc() to close() so that it is executed outside the transactional and blocking read-write process. - // This way, pruning expired sessions does not block them from being started while the current session is used. - $this->gcCalled = true; - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - // delete the record associated with this id - $sql = "DELETE FROM $this->table WHERE $this->idCol = :id"; - - try { - $stmt = $this->pdo->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->execute(); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - - return true; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - $maxlifetime = (int) ini_get('session.gc_maxlifetime'); - - try { - // We use a single MERGE SQL query when supported by the database. - $mergeStmt = $this->getMergeStatement($sessionId, $data, $maxlifetime); - if (null !== $mergeStmt) { - $mergeStmt->execute(); - - return true; - } - - $updateStmt = $this->getUpdateStatement($sessionId, $data, $maxlifetime); - $updateStmt->execute(); - - // When MERGE is not supported, like in Postgres < 9.5, we have to use this approach that can result in - // duplicate key errors when the same session is written simultaneously (given the LOCK_NONE behavior). - // We can just catch such an error and re-execute the update. This is similar to a serializable - // transaction with retry logic on serialization failures but without the overhead and without possible - // false positives due to longer gap locking. - if (!$updateStmt->rowCount()) { - try { - $insertStmt = $this->getInsertStatement($sessionId, $data, $maxlifetime); - $insertStmt->execute(); - } catch (\PDOException $e) { - // Handle integrity violation SQLSTATE 23000 (or a subclass like 23505 in Postgres) for duplicate keys - if (0 === strpos($e->getCode(), '23')) { - $updateStmt->execute(); - } else { - throw $e; - } - } - } - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - - return true; - } - - /** - * @return bool - */ - public function updateTimestamp($sessionId, $data) - { - $expiry = time() + (int) ini_get('session.gc_maxlifetime'); - - try { - $updateStmt = $this->pdo->prepare( - "UPDATE $this->table SET $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id" - ); - $updateStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $updateStmt->bindParam(':expiry', $expiry, \PDO::PARAM_INT); - $updateStmt->bindValue(':time', time(), \PDO::PARAM_INT); - $updateStmt->execute(); - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - - return true; - } - - /** - * @return bool - */ - public function close() - { - $this->commit(); - - while ($unlockStmt = array_shift($this->unlockStatements)) { - $unlockStmt->execute(); - } - - if ($this->gcCalled) { - $this->gcCalled = false; - - // delete the session records that have expired - $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol < :time AND $this->lifetimeCol > :min"; - $stmt = $this->pdo->prepare($sql); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - $stmt->bindValue(':min', self::MAX_LIFETIME, \PDO::PARAM_INT); - $stmt->execute(); - // to be removed in 6.0 - if ('mysql' === $this->driver) { - $legacySql = "DELETE FROM $this->table WHERE $this->lifetimeCol <= :min AND $this->lifetimeCol + $this->timeCol < :time"; - } else { - $legacySql = "DELETE FROM $this->table WHERE $this->lifetimeCol <= :min AND $this->lifetimeCol < :time - $this->timeCol"; - } - - $stmt = $this->pdo->prepare($legacySql); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - $stmt->bindValue(':min', self::MAX_LIFETIME, \PDO::PARAM_INT); - $stmt->execute(); - } - - if (false !== $this->dsn) { - $this->pdo = null; // only close lazy-connection - } - - return true; - } - - /** - * Lazy-connects to the database. - */ - private function connect(string $dsn): void - { - $this->pdo = new \PDO($dsn, $this->username, $this->password, $this->connectionOptions); - $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); - } - - /** - * Builds a PDO DSN from a URL-like connection string. - * - * @todo implement missing support for oci DSN (which look totally different from other PDO ones) - */ - private function buildDsnFromUrl(string $dsnOrUrl): string - { - // (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid - $url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $dsnOrUrl); - - $params = parse_url($url); - - if (false === $params) { - return $dsnOrUrl; // If the URL is not valid, let's assume it might be a DSN already. - } - - $params = array_map('rawurldecode', $params); - - // Override the default username and password. Values passed through options will still win over these in the constructor. - if (isset($params['user'])) { - $this->username = $params['user']; - } - - if (isset($params['pass'])) { - $this->password = $params['pass']; - } - - if (!isset($params['scheme'])) { - throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler'); - } - - $driverAliasMap = [ - 'mssql' => 'sqlsrv', - 'mysql2' => 'mysql', // Amazon RDS, for some weird reason - 'postgres' => 'pgsql', - 'postgresql' => 'pgsql', - 'sqlite3' => 'sqlite', - ]; - - $driver = isset($driverAliasMap[$params['scheme']]) ? $driverAliasMap[$params['scheme']] : $params['scheme']; - - // Doctrine DBAL supports passing its internal pdo_* driver names directly too (allowing both dashes and underscores). This allows supporting the same here. - if (0 === strpos($driver, 'pdo_') || 0 === strpos($driver, 'pdo-')) { - $driver = substr($driver, 4); - } - - switch ($driver) { - case 'mysql': - case 'pgsql': - $dsn = $driver.':'; - - if (isset($params['host']) && '' !== $params['host']) { - $dsn .= 'host='.$params['host'].';'; - } - - if (isset($params['port']) && '' !== $params['port']) { - $dsn .= 'port='.$params['port'].';'; - } - - if (isset($params['path'])) { - $dbName = substr($params['path'], 1); // Remove the leading slash - $dsn .= 'dbname='.$dbName.';'; - } - - return $dsn; - - case 'sqlite': - return 'sqlite:'.substr($params['path'], 1); - - case 'sqlsrv': - $dsn = 'sqlsrv:server='; - - if (isset($params['host'])) { - $dsn .= $params['host']; - } - - if (isset($params['port']) && '' !== $params['port']) { - $dsn .= ','.$params['port']; - } - - if (isset($params['path'])) { - $dbName = substr($params['path'], 1); // Remove the leading slash - $dsn .= ';Database='.$dbName; - } - - return $dsn; - - default: - throw new \InvalidArgumentException(sprintf('The scheme "%s" is not supported by the PdoSessionHandler URL configuration. Pass a PDO DSN directly.', $params['scheme'])); - } - } - - /** - * Helper method to begin a transaction. - * - * Since SQLite does not support row level locks, we have to acquire a reserved lock - * on the database immediately. Because of https://bugs.php.net/42766 we have to create - * such a transaction manually which also means we cannot use PDO::commit or - * PDO::rollback or PDO::inTransaction for SQLite. - * - * Also MySQLs default isolation, REPEATABLE READ, causes deadlock for different sessions - * due to https://percona.com/blog/2013/12/12/one-more-innodb-gap-lock-to-avoid/ . - * So we change it to READ COMMITTED. - */ - private function beginTransaction(): void - { - if (!$this->inTransaction) { - if ('sqlite' === $this->driver) { - $this->pdo->exec('BEGIN IMMEDIATE TRANSACTION'); - } else { - if ('mysql' === $this->driver) { - $this->pdo->exec('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); - } - $this->pdo->beginTransaction(); - } - $this->inTransaction = true; - } - } - - /** - * Helper method to commit a transaction. - */ - private function commit(): void - { - if ($this->inTransaction) { - try { - // commit read-write transaction which also releases the lock - if ('sqlite' === $this->driver) { - $this->pdo->exec('COMMIT'); - } else { - $this->pdo->commit(); - } - $this->inTransaction = false; - } catch (\PDOException $e) { - $this->rollback(); - - throw $e; - } - } - } - - /** - * Helper method to rollback a transaction. - */ - private function rollback(): void - { - // We only need to rollback if we are in a transaction. Otherwise the resulting - // error would hide the real problem why rollback was called. We might not be - // in a transaction when not using the transactional locking behavior or when - // two callbacks (e.g. destroy and write) are invoked that both fail. - if ($this->inTransaction) { - if ('sqlite' === $this->driver) { - $this->pdo->exec('ROLLBACK'); - } else { - $this->pdo->rollBack(); - } - $this->inTransaction = false; - } - } - - /** - * Reads the session data in respect to the different locking strategies. - * - * We need to make sure we do not return session data that is already considered garbage according - * to the session.gc_maxlifetime setting because gc() is called after read() and only sometimes. - * - * @return string - */ - protected function doRead(string $sessionId) - { - if (self::LOCK_ADVISORY === $this->lockMode) { - $this->unlockStatements[] = $this->doAdvisoryLock($sessionId); - } - - $selectSql = $this->getSelectSql(); - $selectStmt = $this->pdo->prepare($selectSql); - $selectStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $insertStmt = null; - - do { - $selectStmt->execute(); - $sessionRows = $selectStmt->fetchAll(\PDO::FETCH_NUM); - - if ($sessionRows) { - $expiry = (int) $sessionRows[0][1]; - if ($expiry <= self::MAX_LIFETIME) { - $expiry += $sessionRows[0][2]; - } - - if ($expiry < time()) { - $this->sessionExpired = true; - - return ''; - } - - return \is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0]; - } - - if (null !== $insertStmt) { - $this->rollback(); - throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.'); - } - - if (!filter_var(ini_get('session.use_strict_mode'), FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { - // In strict mode, session fixation is not possible: new sessions always start with a unique - // random id, so that concurrency is not possible and this code path can be skipped. - // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block - // until other connections to the session are committed. - try { - $insertStmt = $this->getInsertStatement($sessionId, '', 0); - $insertStmt->execute(); - } catch (\PDOException $e) { - // Catch duplicate key error because other connection created the session already. - // It would only not be the case when the other connection destroyed the session. - if (0 === strpos($e->getCode(), '23')) { - // Retrieve finished session data written by concurrent connection by restarting the loop. - // We have to start a new transaction as a failed query will mark the current transaction as - // aborted in PostgreSQL and disallow further queries within it. - $this->rollback(); - $this->beginTransaction(); - continue; - } - - throw $e; - } - } - - return ''; - } while (true); - } - - /** - * Executes an application-level lock on the database. - * - * @return \PDOStatement The statement that needs to be executed later to release the lock - * - * @throws \DomainException When an unsupported PDO driver is used - * - * @todo implement missing advisory locks - * - for oci using DBMS_LOCK.REQUEST - * - for sqlsrv using sp_getapplock with LockOwner = Session - */ - private function doAdvisoryLock(string $sessionId): \PDOStatement - { - switch ($this->driver) { - case 'mysql': - // MySQL 5.7.5 and later enforces a maximum length on lock names of 64 characters. Previously, no limit was enforced. - $lockId = substr($sessionId, 0, 64); - // should we handle the return value? 0 on timeout, null on error - // we use a timeout of 50 seconds which is also the default for innodb_lock_wait_timeout - $stmt = $this->pdo->prepare('SELECT GET_LOCK(:key, 50)'); - $stmt->bindValue(':key', $lockId, \PDO::PARAM_STR); - $stmt->execute(); - - $releaseStmt = $this->pdo->prepare('DO RELEASE_LOCK(:key)'); - $releaseStmt->bindValue(':key', $lockId, \PDO::PARAM_STR); - - return $releaseStmt; - case 'pgsql': - // Obtaining an exclusive session level advisory lock requires an integer key. - // When session.sid_bits_per_character > 4, the session id can contain non-hex-characters. - // So we cannot just use hexdec(). - if (4 === \PHP_INT_SIZE) { - $sessionInt1 = $this->convertStringToInt($sessionId); - $sessionInt2 = $this->convertStringToInt(substr($sessionId, 4, 4)); - - $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key1, :key2)'); - $stmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); - $stmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT); - $stmt->execute(); - - $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key1, :key2)'); - $releaseStmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); - $releaseStmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT); - } else { - $sessionBigInt = $this->convertStringToInt($sessionId); - - $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key)'); - $stmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT); - $stmt->execute(); - - $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key)'); - $releaseStmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT); - } - - return $releaseStmt; - case 'sqlite': - throw new \DomainException('SQLite does not support advisory locks.'); - default: - throw new \DomainException(sprintf('Advisory locks are currently not implemented for PDO driver "%s".', $this->driver)); - } - } - - /** - * Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer. - * - * Keep in mind, PHP integers are signed. - */ - private function convertStringToInt(string $string): int - { - if (4 === \PHP_INT_SIZE) { - return (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); - } - - $int1 = (\ord($string[7]) << 24) + (\ord($string[6]) << 16) + (\ord($string[5]) << 8) + \ord($string[4]); - $int2 = (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); - - return $int2 + ($int1 << 32); - } - - /** - * Return a locking or nonlocking SQL query to read session information. - * - * @throws \DomainException When an unsupported PDO driver is used - */ - private function getSelectSql(): string - { - if (self::LOCK_TRANSACTIONAL === $this->lockMode) { - $this->beginTransaction(); - - // selecting the time column should be removed in 6.0 - switch ($this->driver) { - case 'mysql': - case 'oci': - case 'pgsql': - return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WHERE $this->idCol = :id FOR UPDATE"; - case 'sqlsrv': - return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WITH (UPDLOCK, ROWLOCK) WHERE $this->idCol = :id"; - case 'sqlite': - // we already locked when starting transaction - break; - default: - throw new \DomainException(sprintf('Transactional locks are currently not implemented for PDO driver "%s".', $this->driver)); - } - } - - return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WHERE $this->idCol = :id"; - } - - /** - * Returns an insert statement supported by the database for writing session data. - */ - private function getInsertStatement(string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement - { - switch ($this->driver) { - case 'oci': - $data = fopen('php://memory', 'r+'); - fwrite($data, $sessionData); - rewind($data); - $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, EMPTY_BLOB(), :expiry, :time) RETURNING $this->dataCol into :data"; - break; - default: - $data = $sessionData; - $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)"; - break; - } - - $stmt = $this->pdo->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - - return $stmt; - } - - /** - * Returns an update statement supported by the database for writing session data. - */ - private function getUpdateStatement(string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement - { - switch ($this->driver) { - case 'oci': - $data = fopen('php://memory', 'r+'); - fwrite($data, $sessionData); - rewind($data); - $sql = "UPDATE $this->table SET $this->dataCol = EMPTY_BLOB(), $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id RETURNING $this->dataCol into :data"; - break; - default: - $data = $sessionData; - $sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id"; - break; - } - - $stmt = $this->pdo->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); - $stmt->bindValue(':time', time(), \PDO::PARAM_INT); - - return $stmt; - } - - /** - * Returns a merge/upsert (i.e. insert or update) statement when supported by the database for writing session data. - */ - private function getMergeStatement(string $sessionId, string $data, int $maxlifetime): ?\PDOStatement - { - switch (true) { - case 'mysql' === $this->driver: - $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ". - "ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)"; - break; - case 'sqlsrv' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '10', '>='): - // MERGE is only available since SQL Server 2008 and must be terminated by semicolon - // It also requires HOLDLOCK according to https://weblogs.sqlteam.com/dang/2009/01/31/upsert-race-condition-with-merge/ - $mergeSql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ". - "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". - "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;"; - break; - case 'sqlite' === $this->driver: - $mergeSql = "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)"; - break; - case 'pgsql' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '9.5', '>='): - $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ". - "ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; - break; - default: - // MERGE is not supported with LOBs: https://oracle.com/technetwork/articles/fuecks-lobs-095315.html - return null; - } - - $mergeStmt = $this->pdo->prepare($mergeSql); - - if ('sqlsrv' === $this->driver) { - $mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(3, $data, \PDO::PARAM_LOB); - $mergeStmt->bindValue(4, time() + $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(5, time(), \PDO::PARAM_INT); - $mergeStmt->bindParam(6, $data, \PDO::PARAM_LOB); - $mergeStmt->bindValue(7, time() + $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(8, time(), \PDO::PARAM_INT); - } else { - $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $mergeStmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT); - } - - return $mergeStmt; - } - - /** - * Return a PDO instance. - * - * @return \PDO - */ - protected function getConnection() - { - if (null === $this->pdo) { - $this->connect($this->dsn ?: ini_get('session.save_path')); - } - - return $this->pdo; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php deleted file mode 100644 index b9ca28f..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php +++ /dev/null @@ -1,120 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Predis\Response\ErrorInterface; -use Symfony\Component\Cache\Traits\RedisClusterProxy; -use Symfony\Component\Cache\Traits\RedisProxy; - -/** - * Redis based session storage handler based on the Redis class - * provided by the PHP redis extension. - * - * @author Dalibor Karlović - */ -class RedisSessionHandler extends AbstractSessionHandler -{ - private $redis; - - /** - * @var string Key prefix for shared environments - */ - private $prefix; - - /** - * @var int Time to live in seconds - */ - private $ttl; - - /** - * List of available options: - * * prefix: The prefix to use for the keys in order to avoid collision on the Redis server - * * ttl: The time to live in seconds. - * - * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis - * - * @throws \InvalidArgumentException When unsupported client or options are passed - */ - public function __construct($redis, array $options = []) - { - if ( - !$redis instanceof \Redis && - !$redis instanceof \RedisArray && - !$redis instanceof \RedisCluster && - !$redis instanceof \Predis\ClientInterface && - !$redis instanceof RedisProxy && - !$redis instanceof RedisClusterProxy - ) { - throw new \InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, %s given', __METHOD__, \is_object($redis) ? \get_class($redis) : \gettype($redis))); - } - - if ($diff = array_diff(array_keys($options), ['prefix', 'ttl'])) { - throw new \InvalidArgumentException(sprintf('The following options are not supported "%s"', implode(', ', $diff))); - } - - $this->redis = $redis; - $this->prefix = $options['prefix'] ?? 'sf_s'; - $this->ttl = $options['ttl'] ?? null; - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId): string - { - return $this->redis->get($this->prefix.$sessionId) ?: ''; - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data): bool - { - $result = $this->redis->setEx($this->prefix.$sessionId, (int) ($this->ttl ?? ini_get('session.gc_maxlifetime')), $data); - - return $result && !$result instanceof ErrorInterface; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId): bool - { - $this->redis->del($this->prefix.$sessionId); - - return true; - } - - /** - * {@inheritdoc} - */ - public function close(): bool - { - return true; - } - - /** - * {@inheritdoc} - */ - public function gc($maxlifetime): bool - { - return true; - } - - /** - * @return bool - */ - public function updateTimestamp($sessionId, $data) - { - return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ($this->ttl ?? ini_get('session.gc_maxlifetime'))); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php b/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php deleted file mode 100644 index 1f017c8..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/SessionHandlerFactory.php +++ /dev/null @@ -1,85 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -use Doctrine\DBAL\DriverManager; -use Symfony\Component\Cache\Adapter\AbstractAdapter; -use Symfony\Component\Cache\Traits\RedisClusterProxy; -use Symfony\Component\Cache\Traits\RedisProxy; - -/** - * @author Nicolas Grekas - */ -class SessionHandlerFactory -{ - /** - * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy|\Memcached|\PDO|string $connection Connection or DSN - */ - public static function createHandler($connection): AbstractSessionHandler - { - if (!\is_string($connection) && !\is_object($connection)) { - throw new \TypeError(sprintf('Argument 1 passed to %s() must be a string or a connection object, %s given.', __METHOD__, \gettype($connection))); - } - - switch (true) { - case $connection instanceof \Redis: - case $connection instanceof \RedisArray: - case $connection instanceof \RedisCluster: - case $connection instanceof \Predis\ClientInterface: - case $connection instanceof RedisProxy: - case $connection instanceof RedisClusterProxy: - return new RedisSessionHandler($connection); - - case $connection instanceof \Memcached: - return new MemcachedSessionHandler($connection); - - case $connection instanceof \PDO: - return new PdoSessionHandler($connection); - - case !\is_string($connection): - throw new \InvalidArgumentException(sprintf('Unsupported Connection: %s.', \get_class($connection))); - case 0 === strpos($connection, 'file://'): - return new StrictSessionHandler(new NativeFileSessionHandler(substr($connection, 7))); - - case 0 === strpos($connection, 'redis:'): - case 0 === strpos($connection, 'rediss:'): - case 0 === strpos($connection, 'memcached:'): - if (!class_exists(AbstractAdapter::class)) { - throw new InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require symfony/cache".', $connection)); - } - $handlerClass = 0 === strpos($connection, 'memcached:') ? MemcachedSessionHandler::class : RedisSessionHandler::class; - $connection = AbstractAdapter::createConnection($connection, ['lazy' => true]); - - return new $handlerClass($connection); - - case 0 === strpos($connection, 'pdo_oci://'): - if (!class_exists(DriverManager::class)) { - throw new \InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require doctrine/dbal".', $connection)); - } - $connection = DriverManager::getConnection(['url' => $connection])->getWrappedConnection(); - // no break; - - case 0 === strpos($connection, 'mssql://'): - case 0 === strpos($connection, 'mysql://'): - case 0 === strpos($connection, 'mysql2://'): - case 0 === strpos($connection, 'pgsql://'): - case 0 === strpos($connection, 'postgres://'): - case 0 === strpos($connection, 'postgresql://'): - case 0 === strpos($connection, 'sqlsrv://'): - case 0 === strpos($connection, 'sqlite://'): - case 0 === strpos($connection, 'sqlite3://'): - return new PdoSessionHandler($connection); - } - - throw new \InvalidArgumentException(sprintf('Unsupported Connection: %s.', $connection)); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php deleted file mode 100644 index 4292a3b..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php +++ /dev/null @@ -1,103 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * Adds basic `SessionUpdateTimestampHandlerInterface` behaviors to another `SessionHandlerInterface`. - * - * @author Nicolas Grekas - */ -class StrictSessionHandler extends AbstractSessionHandler -{ - private $handler; - private $doDestroy; - - public function __construct(\SessionHandlerInterface $handler) - { - if ($handler instanceof \SessionUpdateTimestampHandlerInterface) { - throw new \LogicException(sprintf('"%s" is already an instance of "SessionUpdateTimestampHandlerInterface", you cannot wrap it with "%s".', \get_class($handler), self::class)); - } - - $this->handler = $handler; - } - - /** - * @return bool - */ - public function open($savePath, $sessionName) - { - parent::open($savePath, $sessionName); - - return $this->handler->open($savePath, $sessionName); - } - - /** - * {@inheritdoc} - */ - protected function doRead(string $sessionId) - { - return $this->handler->read($sessionId); - } - - /** - * @return bool - */ - public function updateTimestamp($sessionId, $data) - { - return $this->write($sessionId, $data); - } - - /** - * {@inheritdoc} - */ - protected function doWrite(string $sessionId, string $data) - { - return $this->handler->write($sessionId, $data); - } - - /** - * @return bool - */ - public function destroy($sessionId) - { - $this->doDestroy = true; - $destroyed = parent::destroy($sessionId); - - return $this->doDestroy ? $this->doDestroy($sessionId) : $destroyed; - } - - /** - * {@inheritdoc} - */ - protected function doDestroy(string $sessionId) - { - $this->doDestroy = false; - - return $this->handler->destroy($sessionId); - } - - /** - * @return bool - */ - public function close() - { - return $this->handler->close(); - } - - /** - * @return bool - */ - public function gc($maxlifetime) - { - return $this->handler->gc($maxlifetime); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php b/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php deleted file mode 100644 index c79ee02..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php +++ /dev/null @@ -1,166 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * Metadata container. - * - * Adds metadata to the session. - * - * @author Drak - */ -class MetadataBag implements SessionBagInterface -{ - const CREATED = 'c'; - const UPDATED = 'u'; - const LIFETIME = 'l'; - - /** - * @var string - */ - private $name = '__metadata'; - - /** - * @var string - */ - private $storageKey; - - /** - * @var array - */ - protected $meta = [self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0]; - - /** - * Unix timestamp. - * - * @var int - */ - private $lastUsed; - - /** - * @var int - */ - private $updateThreshold; - - /** - * @param string $storageKey The key used to store bag in the session - * @param int $updateThreshold The time to wait between two UPDATED updates - */ - public function __construct(string $storageKey = '_sf2_meta', int $updateThreshold = 0) - { - $this->storageKey = $storageKey; - $this->updateThreshold = $updateThreshold; - } - - /** - * {@inheritdoc} - */ - public function initialize(array &$array) - { - $this->meta = &$array; - - if (isset($array[self::CREATED])) { - $this->lastUsed = $this->meta[self::UPDATED]; - - $timeStamp = time(); - if ($timeStamp - $array[self::UPDATED] >= $this->updateThreshold) { - $this->meta[self::UPDATED] = $timeStamp; - } - } else { - $this->stampCreated(); - } - } - - /** - * Gets the lifetime that the session cookie was set with. - * - * @return int - */ - public function getLifetime() - { - return $this->meta[self::LIFETIME]; - } - - /** - * Stamps a new session's metadata. - * - * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - */ - public function stampNew(int $lifetime = null) - { - $this->stampCreated($lifetime); - } - - /** - * {@inheritdoc} - */ - public function getStorageKey() - { - return $this->storageKey; - } - - /** - * Gets the created timestamp metadata. - * - * @return int Unix timestamp - */ - public function getCreated() - { - return $this->meta[self::CREATED]; - } - - /** - * Gets the last used metadata. - * - * @return int Unix timestamp - */ - public function getLastUsed() - { - return $this->lastUsed; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - // nothing to do - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - /** - * Sets name. - */ - public function setName(string $name) - { - $this->name = $name; - } - - private function stampCreated(int $lifetime = null): void - { - $timeStamp = time(); - $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; - $this->meta[self::LIFETIME] = (null === $lifetime) ? ini_get('session.cookie_lifetime') : $lifetime; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php deleted file mode 100644 index 4662bd8..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php +++ /dev/null @@ -1,252 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * MockArraySessionStorage mocks the session for unit tests. - * - * No PHP session is actually started since a session can be initialized - * and shutdown only once per PHP execution cycle. - * - * When doing functional testing, you should use MockFileSessionStorage instead. - * - * @author Fabien Potencier - * @author Bulat Shakirzyanov - * @author Drak - */ -class MockArraySessionStorage implements SessionStorageInterface -{ - /** - * @var string - */ - protected $id = ''; - - /** - * @var string - */ - protected $name; - - /** - * @var bool - */ - protected $started = false; - - /** - * @var bool - */ - protected $closed = false; - - /** - * @var array - */ - protected $data = []; - - /** - * @var MetadataBag - */ - protected $metadataBag; - - /** - * @var array|SessionBagInterface[] - */ - protected $bags = []; - - public function __construct(string $name = 'MOCKSESSID', MetadataBag $metaBag = null) - { - $this->name = $name; - $this->setMetadataBag($metaBag); - } - - public function setSessionData(array $array) - { - $this->data = $array; - } - - /** - * {@inheritdoc} - */ - public function start() - { - if ($this->started) { - return true; - } - - if (empty($this->id)) { - $this->id = $this->generateId(); - } - - $this->loadSession(); - - return true; - } - - /** - * {@inheritdoc} - */ - public function regenerate(bool $destroy = false, int $lifetime = null) - { - if (!$this->started) { - $this->start(); - } - - $this->metadataBag->stampNew($lifetime); - $this->id = $this->generateId(); - - return true; - } - - /** - * {@inheritdoc} - */ - public function getId() - { - return $this->id; - } - - /** - * {@inheritdoc} - */ - public function setId(string $id) - { - if ($this->started) { - throw new \LogicException('Cannot set session ID after the session has started.'); - } - - $this->id = $id; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->name; - } - - /** - * {@inheritdoc} - */ - public function setName(string $name) - { - $this->name = $name; - } - - /** - * {@inheritdoc} - */ - public function save() - { - if (!$this->started || $this->closed) { - throw new \RuntimeException('Trying to save a session that was not started yet or was already closed'); - } - // nothing to do since we don't persist the session data - $this->closed = false; - $this->started = false; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - // clear out the bags - foreach ($this->bags as $bag) { - $bag->clear(); - } - - // clear out the session - $this->data = []; - - // reconnect the bags to the session - $this->loadSession(); - } - - /** - * {@inheritdoc} - */ - public function registerBag(SessionBagInterface $bag) - { - $this->bags[$bag->getName()] = $bag; - } - - /** - * {@inheritdoc} - */ - public function getBag(string $name) - { - if (!isset($this->bags[$name])) { - throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); - } - - if (!$this->started) { - $this->start(); - } - - return $this->bags[$name]; - } - - /** - * {@inheritdoc} - */ - public function isStarted() - { - return $this->started; - } - - public function setMetadataBag(MetadataBag $bag = null) - { - if (null === $bag) { - $bag = new MetadataBag(); - } - - $this->metadataBag = $bag; - } - - /** - * Gets the MetadataBag. - * - * @return MetadataBag - */ - public function getMetadataBag() - { - return $this->metadataBag; - } - - /** - * Generates a session ID. - * - * This doesn't need to be particularly cryptographically secure since this is just - * a mock. - * - * @return string - */ - protected function generateId() - { - return hash('sha256', uniqid('ss_mock_', true)); - } - - protected function loadSession() - { - $bags = array_merge($this->bags, [$this->metadataBag]); - - foreach ($bags as $bag) { - $key = $bag->getStorageKey(); - $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : []; - $bag->initialize($this->data[$key]); - } - - $this->started = true; - $this->closed = false; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php deleted file mode 100644 index 019a634..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php +++ /dev/null @@ -1,148 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -/** - * MockFileSessionStorage is used to mock sessions for - * functional testing when done in a single PHP process. - * - * No PHP session is actually started since a session can be initialized - * and shutdown only once per PHP execution cycle and this class does - * not pollute any session related globals, including session_*() functions - * or session.* PHP ini directives. - * - * @author Drak - */ -class MockFileSessionStorage extends MockArraySessionStorage -{ - private $savePath; - - /** - * @param string $savePath Path of directory to save session files - */ - public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null) - { - if (null === $savePath) { - $savePath = sys_get_temp_dir(); - } - - if (!is_dir($savePath) && !@mkdir($savePath, 0777, true) && !is_dir($savePath)) { - throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"', $savePath)); - } - - $this->savePath = $savePath; - - parent::__construct($name, $metaBag); - } - - /** - * {@inheritdoc} - */ - public function start() - { - if ($this->started) { - return true; - } - - if (!$this->id) { - $this->id = $this->generateId(); - } - - $this->read(); - - $this->started = true; - - return true; - } - - /** - * {@inheritdoc} - */ - public function regenerate(bool $destroy = false, int $lifetime = null) - { - if (!$this->started) { - $this->start(); - } - - if ($destroy) { - $this->destroy(); - } - - return parent::regenerate($destroy, $lifetime); - } - - /** - * {@inheritdoc} - */ - public function save() - { - if (!$this->started) { - throw new \RuntimeException('Trying to save a session that was not started yet or was already closed'); - } - - $data = $this->data; - - foreach ($this->bags as $bag) { - if (empty($data[$key = $bag->getStorageKey()])) { - unset($data[$key]); - } - } - if ([$key = $this->metadataBag->getStorageKey()] === array_keys($data)) { - unset($data[$key]); - } - - try { - if ($data) { - file_put_contents($this->getFilePath(), serialize($data)); - } else { - $this->destroy(); - } - } finally { - $this->data = $data; - } - - // this is needed for Silex, where the session object is re-used across requests - // in functional tests. In Symfony, the container is rebooted, so we don't have - // this issue - $this->started = false; - } - - /** - * Deletes a session from persistent storage. - * Deliberately leaves session data in memory intact. - */ - private function destroy(): void - { - if (is_file($this->getFilePath())) { - unlink($this->getFilePath()); - } - } - - /** - * Calculate path to file. - */ - private function getFilePath(): string - { - return $this->savePath.'/'.$this->id.'.mocksess'; - } - - /** - * Reads session from storage and loads session. - */ - private function read(): void - { - $filePath = $this->getFilePath(); - $this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : []; - - $this->loadSession(); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php deleted file mode 100644 index eb754db..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php +++ /dev/null @@ -1,464 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; -use Symfony\Component\HttpFoundation\Session\SessionUtils; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; - -/** - * This provides a base class for session attribute storage. - * - * @author Drak - */ -class NativeSessionStorage implements SessionStorageInterface -{ - /** - * @var SessionBagInterface[] - */ - protected $bags = []; - - /** - * @var bool - */ - protected $started = false; - - /** - * @var bool - */ - protected $closed = false; - - /** - * @var AbstractProxy|\SessionHandlerInterface - */ - protected $saveHandler; - - /** - * @var MetadataBag - */ - protected $metadataBag; - - /** - * @var string|null - */ - private $emulateSameSite; - - /** - * Depending on how you want the storage driver to behave you probably - * want to override this constructor entirely. - * - * List of options for $options array with their defaults. - * - * @see https://php.net/session.configuration for options - * but we omit 'session.' from the beginning of the keys for convenience. - * - * ("auto_start", is not supported as it tells PHP to start a session before - * PHP starts to execute user-land code. Setting during runtime has no effect). - * - * cache_limiter, "" (use "0" to prevent headers from being sent entirely). - * cache_expire, "0" - * cookie_domain, "" - * cookie_httponly, "" - * cookie_lifetime, "0" - * cookie_path, "/" - * cookie_secure, "" - * cookie_samesite, null - * gc_divisor, "100" - * gc_maxlifetime, "1440" - * gc_probability, "1" - * lazy_write, "1" - * name, "PHPSESSID" - * referer_check, "" - * serialize_handler, "php" - * use_strict_mode, "0" - * use_cookies, "1" - * use_only_cookies, "1" - * use_trans_sid, "0" - * upload_progress.enabled, "1" - * upload_progress.cleanup, "1" - * upload_progress.prefix, "upload_progress_" - * upload_progress.name, "PHP_SESSION_UPLOAD_PROGRESS" - * upload_progress.freq, "1%" - * upload_progress.min-freq, "1" - * url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset=" - * sid_length, "32" - * sid_bits_per_character, "5" - * trans_sid_hosts, $_SERVER['HTTP_HOST'] - * trans_sid_tags, "a=href,area=href,frame=src,form=" - * - * @param AbstractProxy|\SessionHandlerInterface|null $handler - */ - public function __construct(array $options = [], $handler = null, MetadataBag $metaBag = null) - { - if (!\extension_loaded('session')) { - throw new \LogicException('PHP extension "session" is required.'); - } - - $options += [ - 'cache_limiter' => '', - 'cache_expire' => 0, - 'use_cookies' => 1, - 'lazy_write' => 1, - 'use_strict_mode' => 1, - ]; - - session_register_shutdown(); - - $this->setMetadataBag($metaBag); - $this->setOptions($options); - $this->setSaveHandler($handler); - } - - /** - * Gets the save handler instance. - * - * @return AbstractProxy|\SessionHandlerInterface - */ - public function getSaveHandler() - { - return $this->saveHandler; - } - - /** - * {@inheritdoc} - */ - public function start() - { - if ($this->started) { - return true; - } - - if (\PHP_SESSION_ACTIVE === session_status()) { - throw new \RuntimeException('Failed to start the session: already started by PHP.'); - } - - if (filter_var(ini_get('session.use_cookies'), FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) { - throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line)); - } - - // ok to try and start the session - if (!session_start()) { - throw new \RuntimeException('Failed to start the session'); - } - - if (null !== $this->emulateSameSite) { - $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); - if (null !== $originalCookie) { - header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); - } - } - - $this->loadSession(); - - return true; - } - - /** - * {@inheritdoc} - */ - public function getId() - { - return $this->saveHandler->getId(); - } - - /** - * {@inheritdoc} - */ - public function setId(string $id) - { - $this->saveHandler->setId($id); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return $this->saveHandler->getName(); - } - - /** - * {@inheritdoc} - */ - public function setName(string $name) - { - $this->saveHandler->setName($name); - } - - /** - * {@inheritdoc} - */ - public function regenerate(bool $destroy = false, int $lifetime = null) - { - // Cannot regenerate the session ID for non-active sessions. - if (\PHP_SESSION_ACTIVE !== session_status()) { - return false; - } - - if (headers_sent()) { - return false; - } - - if (null !== $lifetime) { - ini_set('session.cookie_lifetime', $lifetime); - } - - if ($destroy) { - $this->metadataBag->stampNew(); - } - - $isRegenerated = session_regenerate_id($destroy); - - // The reference to $_SESSION in session bags is lost in PHP7 and we need to re-create it. - // @see https://bugs.php.net/70013 - $this->loadSession(); - - if (null !== $this->emulateSameSite) { - $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); - if (null !== $originalCookie) { - header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); - } - } - - return $isRegenerated; - } - - /** - * {@inheritdoc} - */ - public function save() - { - // Store a copy so we can restore the bags in case the session was not left empty - $session = $_SESSION; - - foreach ($this->bags as $bag) { - if (empty($_SESSION[$key = $bag->getStorageKey()])) { - unset($_SESSION[$key]); - } - } - if ([$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) { - unset($_SESSION[$key]); - } - - // Register error handler to add information about the current save handler - $previousHandler = set_error_handler(function ($type, $msg, $file, $line) use (&$previousHandler) { - if (E_WARNING === $type && 0 === strpos($msg, 'session_write_close():')) { - $handler = $this->saveHandler instanceof SessionHandlerProxy ? $this->saveHandler->getHandler() : $this->saveHandler; - $msg = sprintf('session_write_close(): Failed to write session data with "%s" handler', \get_class($handler)); - } - - return $previousHandler ? $previousHandler($type, $msg, $file, $line) : false; - }); - - try { - session_write_close(); - } finally { - restore_error_handler(); - - // Restore only if not empty - if ($_SESSION) { - $_SESSION = $session; - } - } - - $this->closed = true; - $this->started = false; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - // clear out the bags - foreach ($this->bags as $bag) { - $bag->clear(); - } - - // clear out the session - $_SESSION = []; - - // reconnect the bags to the session - $this->loadSession(); - } - - /** - * {@inheritdoc} - */ - public function registerBag(SessionBagInterface $bag) - { - if ($this->started) { - throw new \LogicException('Cannot register a bag when the session is already started.'); - } - - $this->bags[$bag->getName()] = $bag; - } - - /** - * {@inheritdoc} - */ - public function getBag(string $name) - { - if (!isset($this->bags[$name])) { - throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); - } - - if (!$this->started && $this->saveHandler->isActive()) { - $this->loadSession(); - } elseif (!$this->started) { - $this->start(); - } - - return $this->bags[$name]; - } - - public function setMetadataBag(MetadataBag $metaBag = null) - { - if (null === $metaBag) { - $metaBag = new MetadataBag(); - } - - $this->metadataBag = $metaBag; - } - - /** - * Gets the MetadataBag. - * - * @return MetadataBag - */ - public function getMetadataBag() - { - return $this->metadataBag; - } - - /** - * {@inheritdoc} - */ - public function isStarted() - { - return $this->started; - } - - /** - * Sets session.* ini variables. - * - * For convenience we omit 'session.' from the beginning of the keys. - * Explicitly ignores other ini keys. - * - * @param array $options Session ini directives [key => value] - * - * @see https://php.net/session.configuration - */ - public function setOptions(array $options) - { - if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { - return; - } - - $validOptions = array_flip([ - 'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', - 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'cookie_samesite', - 'gc_divisor', 'gc_maxlifetime', 'gc_probability', - 'lazy_write', 'name', 'referer_check', - 'serialize_handler', 'use_strict_mode', 'use_cookies', - 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', - 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', - 'upload_progress.freq', 'upload_progress.min_freq', 'url_rewriter.tags', - 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', - ]); - - foreach ($options as $key => $value) { - if (isset($validOptions[$key])) { - if ('cookie_samesite' === $key && \PHP_VERSION_ID < 70300) { - // PHP < 7.3 does not support same_site cookies. We will emulate it in - // the start() method instead. - $this->emulateSameSite = $value; - continue; - } - ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value); - } - } - } - - /** - * Registers session save handler as a PHP session handler. - * - * To use internal PHP session save handlers, override this method using ini_set with - * session.save_handler and session.save_path e.g. - * - * ini_set('session.save_handler', 'files'); - * ini_set('session.save_path', '/tmp'); - * - * or pass in a \SessionHandler instance which configures session.save_handler in the - * constructor, for a template see NativeFileSessionHandler. - * - * @see https://php.net/session-set-save-handler - * @see https://php.net/sessionhandlerinterface - * @see https://php.net/sessionhandler - * - * @param AbstractProxy|\SessionHandlerInterface|null $saveHandler - * - * @throws \InvalidArgumentException - */ - public function setSaveHandler($saveHandler = null) - { - if (!$saveHandler instanceof AbstractProxy && - !$saveHandler instanceof \SessionHandlerInterface && - null !== $saveHandler) { - throw new \InvalidArgumentException('Must be instance of AbstractProxy; implement \SessionHandlerInterface; or be null.'); - } - - // Wrap $saveHandler in proxy and prevent double wrapping of proxy - if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { - $saveHandler = new SessionHandlerProxy($saveHandler); - } elseif (!$saveHandler instanceof AbstractProxy) { - $saveHandler = new SessionHandlerProxy(new StrictSessionHandler(new \SessionHandler())); - } - $this->saveHandler = $saveHandler; - - if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { - return; - } - - if ($this->saveHandler instanceof SessionHandlerProxy) { - session_set_save_handler($this->saveHandler, false); - } - } - - /** - * Load the session with attributes. - * - * After starting the session, PHP retrieves the session from whatever handlers - * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()). - * PHP takes the return value from the read() handler, unserializes it - * and populates $_SESSION with the result automatically. - */ - protected function loadSession(array &$session = null) - { - if (null === $session) { - $session = &$_SESSION; - } - - $bags = array_merge($this->bags, [$this->metadataBag]); - - foreach ($bags as $bag) { - $key = $bag->getStorageKey(); - $session[$key] = isset($session[$key]) && \is_array($session[$key]) ? $session[$key] : []; - $bag->initialize($session[$key]); - } - - $this->started = true; - $this->closed = false; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php deleted file mode 100644 index 72dbef1..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; - -/** - * Allows session to be started by PHP and managed by Symfony. - * - * @author Drak - */ -class PhpBridgeSessionStorage extends NativeSessionStorage -{ - /** - * @param AbstractProxy|\SessionHandlerInterface|null $handler - */ - public function __construct($handler = null, MetadataBag $metaBag = null) - { - if (!\extension_loaded('session')) { - throw new \LogicException('PHP extension "session" is required.'); - } - - $this->setMetadataBag($metaBag); - $this->setSaveHandler($handler); - } - - /** - * {@inheritdoc} - */ - public function start() - { - if ($this->started) { - return true; - } - - $this->loadSession(); - - return true; - } - - /** - * {@inheritdoc} - */ - public function clear() - { - // clear out the bags and nothing else that may be set - // since the purpose of this driver is to share a handler - foreach ($this->bags as $bag) { - $bag->clear(); - } - - // reconnect the bags to the session - $this->loadSession(); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php b/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php deleted file mode 100644 index ded79d6..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php +++ /dev/null @@ -1,118 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; - -/** - * @author Drak - */ -abstract class AbstractProxy -{ - /** - * Flag if handler wraps an internal PHP session handler (using \SessionHandler). - * - * @var bool - */ - protected $wrapper = false; - - /** - * @var string - */ - protected $saveHandlerName; - - /** - * Gets the session.save_handler name. - * - * @return string|null - */ - public function getSaveHandlerName() - { - return $this->saveHandlerName; - } - - /** - * Is this proxy handler and instance of \SessionHandlerInterface. - * - * @return bool - */ - public function isSessionHandlerInterface() - { - return $this instanceof \SessionHandlerInterface; - } - - /** - * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. - * - * @return bool - */ - public function isWrapper() - { - return $this->wrapper; - } - - /** - * Has a session started? - * - * @return bool - */ - public function isActive() - { - return \PHP_SESSION_ACTIVE === session_status(); - } - - /** - * Gets the session ID. - * - * @return string - */ - public function getId() - { - return session_id(); - } - - /** - * Sets the session ID. - * - * @throws \LogicException - */ - public function setId(string $id) - { - if ($this->isActive()) { - throw new \LogicException('Cannot change the ID of an active session'); - } - - session_id($id); - } - - /** - * Gets the session name. - * - * @return string - */ - public function getName() - { - return session_name(); - } - - /** - * Sets the session name. - * - * @throws \LogicException - */ - public function setName(string $name) - { - if ($this->isActive()) { - throw new \LogicException('Cannot change the name of an active session'); - } - - session_name($name); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php b/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php deleted file mode 100644 index de4f550..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php +++ /dev/null @@ -1,101 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; - -/** - * @author Drak - */ -class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface -{ - protected $handler; - - public function __construct(\SessionHandlerInterface $handler) - { - $this->handler = $handler; - $this->wrapper = ($handler instanceof \SessionHandler); - $this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') : 'user'; - } - - /** - * @return \SessionHandlerInterface - */ - public function getHandler() - { - return $this->handler; - } - - // \SessionHandlerInterface - - /** - * @return bool - */ - public function open($savePath, $sessionName) - { - return (bool) $this->handler->open($savePath, $sessionName); - } - - /** - * @return bool - */ - public function close() - { - return (bool) $this->handler->close(); - } - - /** - * @return string - */ - public function read($sessionId) - { - return (string) $this->handler->read($sessionId); - } - - /** - * @return bool - */ - public function write($sessionId, $data) - { - return (bool) $this->handler->write($sessionId, $data); - } - - /** - * @return bool - */ - public function destroy($sessionId) - { - return (bool) $this->handler->destroy($sessionId); - } - - /** - * @return bool - */ - public function gc($maxlifetime) - { - return (bool) $this->handler->gc($maxlifetime); - } - - /** - * @return bool - */ - public function validateId($sessionId) - { - return !$this->handler instanceof \SessionUpdateTimestampHandlerInterface || $this->handler->validateId($sessionId); - } - - /** - * @return bool - */ - public function updateTimestamp($sessionId, $data) - { - return $this->handler instanceof \SessionUpdateTimestampHandlerInterface ? $this->handler->updateTimestamp($sessionId, $data) : $this->write($sessionId, $data); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php b/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php deleted file mode 100644 index eb8e8ff..0000000 --- a/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php +++ /dev/null @@ -1,131 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage; - -use Symfony\Component\HttpFoundation\Session\SessionBagInterface; - -/** - * StorageInterface. - * - * @author Fabien Potencier - * @author Drak - */ -interface SessionStorageInterface -{ - /** - * Starts the session. - * - * @return bool True if started - * - * @throws \RuntimeException if something goes wrong starting the session - */ - public function start(); - - /** - * Checks if the session is started. - * - * @return bool True if started, false otherwise - */ - public function isStarted(); - - /** - * Returns the session ID. - * - * @return string The session ID or empty - */ - public function getId(); - - /** - * Sets the session ID. - */ - public function setId(string $id); - - /** - * Returns the session name. - * - * @return string The session name - */ - public function getName(); - - /** - * Sets the session name. - */ - public function setName(string $name); - - /** - * Regenerates id that represents this storage. - * - * This method must invoke session_regenerate_id($destroy) unless - * this interface is used for a storage object designed for unit - * or functional testing where a real PHP session would interfere - * with testing. - * - * Note regenerate+destroy should not clear the session data in memory - * only delete the session data from persistent storage. - * - * Care: When regenerating the session ID no locking is involved in PHP's - * session design. See https://bugs.php.net/61470 for a discussion. - * So you must make sure the regenerated session is saved BEFORE sending the - * headers with the new ID. Symfony's HttpKernel offers a listener for this. - * See Symfony\Component\HttpKernel\EventListener\SaveSessionListener. - * Otherwise session data could get lost again for concurrent requests with the - * new ID. One result could be that you get logged out after just logging in. - * - * @param bool $destroy Destroy session when regenerating? - * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value - * will leave the system settings unchanged, 0 sets the cookie - * to expire with browser session. Time is in seconds, and is - * not a Unix timestamp. - * - * @return bool True if session regenerated, false if error - * - * @throws \RuntimeException If an error occurs while regenerating this storage - */ - public function regenerate(bool $destroy = false, int $lifetime = null); - - /** - * Force the session to be saved and closed. - * - * This method must invoke session_write_close() unless this interface is - * used for a storage object design for unit or functional testing where - * a real PHP session would interfere with testing, in which case - * it should actually persist the session data if required. - * - * @throws \RuntimeException if the session is saved without being started, or if the session - * is already closed - */ - public function save(); - - /** - * Clear all session data in memory. - */ - public function clear(); - - /** - * Gets a SessionBagInterface by name. - * - * @return SessionBagInterface - * - * @throws \InvalidArgumentException If the bag does not exist - */ - public function getBag(string $name); - - /** - * Registers a SessionBagInterface for use. - */ - public function registerBag(SessionBagInterface $bag); - - /** - * @return MetadataBag - */ - public function getMetadataBag(); -} diff --git a/vendor/symfony/http-foundation/StreamedResponse.php b/vendor/symfony/http-foundation/StreamedResponse.php deleted file mode 100644 index 65ec2d9..0000000 --- a/vendor/symfony/http-foundation/StreamedResponse.php +++ /dev/null @@ -1,135 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -/** - * StreamedResponse represents a streamed HTTP response. - * - * A StreamedResponse uses a callback for its content. - * - * The callback should use the standard PHP functions like echo - * to stream the response back to the client. The flush() function - * can also be used if needed. - * - * @see flush() - * - * @author Fabien Potencier - */ -class StreamedResponse extends Response -{ - protected $callback; - protected $streamed; - private $headersSent; - - public function __construct(callable $callback = null, int $status = 200, array $headers = []) - { - parent::__construct(null, $status, $headers); - - if (null !== $callback) { - $this->setCallback($callback); - } - $this->streamed = false; - $this->headersSent = false; - } - - /** - * Factory method for chainability. - * - * @param callable|null $callback A valid PHP callback or null to set it later - * - * @return static - */ - public static function create($callback = null, int $status = 200, array $headers = []) - { - return new static($callback, $status, $headers); - } - - /** - * Sets the PHP callback associated with this Response. - * - * @return $this - */ - public function setCallback(callable $callback) - { - $this->callback = $callback; - - return $this; - } - - /** - * {@inheritdoc} - * - * This method only sends the headers once. - * - * @return $this - */ - public function sendHeaders() - { - if ($this->headersSent) { - return $this; - } - - $this->headersSent = true; - - return parent::sendHeaders(); - } - - /** - * {@inheritdoc} - * - * This method only sends the content once. - * - * @return $this - */ - public function sendContent() - { - if ($this->streamed) { - return $this; - } - - $this->streamed = true; - - if (null === $this->callback) { - throw new \LogicException('The Response callback must not be null.'); - } - - ($this->callback)(); - - return $this; - } - - /** - * {@inheritdoc} - * - * @throws \LogicException when the content is not null - * - * @return $this - */ - public function setContent(?string $content) - { - if (null !== $content) { - throw new \LogicException('The content cannot be set on a StreamedResponse instance.'); - } - - $this->streamed = true; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function getContent() - { - return false; - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php b/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php deleted file mode 100644 index cb216ea..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Request; - -final class RequestAttributeValueSame extends Constraint -{ - private $name; - private $value; - - public function __construct(string $name, string $value) - { - $this->name = $name; - $this->value = $value; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return sprintf('has attribute "%s" with value "%s"', $this->name, $this->value); - } - - /** - * @param Request $request - * - * {@inheritdoc} - */ - protected function matches($request): bool - { - return $this->value === $request->attributes->get($this->name); - } - - /** - * @param Request $request - * - * {@inheritdoc} - */ - protected function failureDescription($request): string - { - return 'the Request '.$this->toString(); - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php deleted file mode 100644 index 554e1a1..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php +++ /dev/null @@ -1,85 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseCookieValueSame extends Constraint -{ - private $name; - private $value; - private $path; - private $domain; - - public function __construct(string $name, string $value, string $path = '/', string $domain = null) - { - $this->name = $name; - $this->value = $value; - $this->path = $path; - $this->domain = $domain; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - $str = sprintf('has cookie "%s"', $this->name); - if ('/' !== $this->path) { - $str .= sprintf(' with path "%s"', $this->path); - } - if ($this->domain) { - $str .= sprintf(' for domain "%s"', $this->domain); - } - $str .= sprintf(' with value "%s"', $this->value); - - return $str; - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - $cookie = $this->getCookie($response); - if (!$cookie) { - return false; - } - - return $this->value === $cookie->getValue(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - protected function getCookie(Response $response): ?Cookie - { - $cookies = $response->headers->getCookies(); - - $filteredCookies = array_filter($cookies, function (Cookie $cookie) { - return $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain; - }); - - return reset($filteredCookies) ?: null; - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php deleted file mode 100644 index eae9e27..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php +++ /dev/null @@ -1,77 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseHasCookie extends Constraint -{ - private $name; - private $path; - private $domain; - - public function __construct(string $name, string $path = '/', string $domain = null) - { - $this->name = $name; - $this->path = $path; - $this->domain = $domain; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - $str = sprintf('has cookie "%s"', $this->name); - if ('/' !== $this->path) { - $str .= sprintf(' with path "%s"', $this->path); - } - if ($this->domain) { - $str .= sprintf(' for domain "%s"', $this->domain); - } - - return $str; - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - return null !== $this->getCookie($response); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - private function getCookie(Response $response): ?Cookie - { - $cookies = $response->headers->getCookies(); - - $filteredCookies = array_filter($cookies, function (Cookie $cookie) { - return $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain; - }); - - return reset($filteredCookies) ?: null; - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php deleted file mode 100644 index 68ad827..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseHasHeader extends Constraint -{ - private $headerName; - - public function __construct(string $headerName) - { - $this->headerName = $headerName; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return sprintf('has header "%s"', $this->headerName); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - return $response->headers->has($this->headerName); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php deleted file mode 100644 index a27d0c7..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseHeaderSame extends Constraint -{ - private $headerName; - private $expectedValue; - - public function __construct(string $headerName, string $expectedValue) - { - $this->headerName = $headerName; - $this->expectedValue = $expectedValue; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return sprintf('has header "%s" with value "%s"', $this->headerName, $this->expectedValue); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - return $this->expectedValue === $response->headers->get($this->headerName, null); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php deleted file mode 100644 index 8c4b883..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseIsRedirected extends Constraint -{ - /** - * {@inheritdoc} - */ - public function toString(): string - { - return 'is redirected'; - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - return $response->isRedirect(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function additionalFailureDescription($response): string - { - return (string) $response; - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php deleted file mode 100644 index 9c66558..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseIsSuccessful extends Constraint -{ - /** - * {@inheritdoc} - */ - public function toString(): string - { - return 'is successful'; - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - return $response->isSuccessful(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function additionalFailureDescription($response): string - { - return (string) $response; - } -} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php deleted file mode 100644 index 72bb000..0000000 --- a/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\HttpFoundation\Response; - -final class ResponseStatusCodeSame extends Constraint -{ - private $statusCode; - - public function __construct(int $statusCode) - { - $this->statusCode = $statusCode; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return 'status code is '.$this->statusCode; - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function matches($response): bool - { - return $this->statusCode === $response->getStatusCode(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function failureDescription($response): string - { - return 'the Response '.$this->toString(); - } - - /** - * @param Response $response - * - * {@inheritdoc} - */ - protected function additionalFailureDescription($response): string - { - return (string) $response; - } -} diff --git a/vendor/symfony/http-foundation/UrlHelper.php b/vendor/symfony/http-foundation/UrlHelper.php deleted file mode 100644 index f114c0a..0000000 --- a/vendor/symfony/http-foundation/UrlHelper.php +++ /dev/null @@ -1,102 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation; - -use Symfony\Component\Routing\RequestContext; - -/** - * A helper service for manipulating URLs within and outside the request scope. - * - * @author Valentin Udaltsov - */ -final class UrlHelper -{ - private $requestStack; - private $requestContext; - - public function __construct(RequestStack $requestStack, RequestContext $requestContext = null) - { - $this->requestStack = $requestStack; - $this->requestContext = $requestContext; - } - - public function getAbsoluteUrl(string $path): string - { - if (false !== strpos($path, '://') || '//' === substr($path, 0, 2)) { - return $path; - } - - if (null === $request = $this->requestStack->getMasterRequest()) { - return $this->getAbsoluteUrlFromContext($path); - } - - if ('#' === $path[0]) { - $path = $request->getRequestUri().$path; - } elseif ('?' === $path[0]) { - $path = $request->getPathInfo().$path; - } - - if (!$path || '/' !== $path[0]) { - $prefix = $request->getPathInfo(); - $last = \strlen($prefix) - 1; - if ($last !== $pos = strrpos($prefix, '/')) { - $prefix = substr($prefix, 0, $pos).'/'; - } - - return $request->getUriForPath($prefix.$path); - } - - return $request->getSchemeAndHttpHost().$path; - } - - public function getRelativePath(string $path): string - { - if (false !== strpos($path, '://') || '//' === substr($path, 0, 2)) { - return $path; - } - - if (null === $request = $this->requestStack->getMasterRequest()) { - return $path; - } - - return $request->getRelativeUriForPath($path); - } - - private function getAbsoluteUrlFromContext(string $path): string - { - if (null === $this->requestContext || '' === $host = $this->requestContext->getHost()) { - return $path; - } - - $scheme = $this->requestContext->getScheme(); - $port = ''; - - if ('http' === $scheme && 80 !== $this->requestContext->getHttpPort()) { - $port = ':'.$this->requestContext->getHttpPort(); - } elseif ('https' === $scheme && 443 !== $this->requestContext->getHttpsPort()) { - $port = ':'.$this->requestContext->getHttpsPort(); - } - - if ('#' === $path[0]) { - $queryString = $this->requestContext->getQueryString(); - $path = $this->requestContext->getPathInfo().($queryString ? '?'.$queryString : '').$path; - } elseif ('?' === $path[0]) { - $path = $this->requestContext->getPathInfo().$path; - } - - if ('/' !== $path[0]) { - $path = rtrim($this->requestContext->getBaseUrl(), '/').'/'.$path; - } - - return $scheme.'://'.$host.$port.$path; - } -} diff --git a/vendor/symfony/http-foundation/composer.json b/vendor/symfony/http-foundation/composer.json deleted file mode 100644 index fcec68c..0000000 --- a/vendor/symfony/http-foundation/composer.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "symfony/http-foundation", - "type": "library", - "description": "Symfony HttpFoundation Component", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "symfony/mime": "^4.4|^5.0", - "symfony/polyfill-mbstring": "~1.1" - }, - "require-dev": { - "predis/predis": "~1.0", - "symfony/expression-language": "^4.4|^5.0" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/http-kernel/.gitattributes b/vendor/symfony/http-kernel/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/http-kernel/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/http-kernel/Bundle/Bundle.php b/vendor/symfony/http-kernel/Bundle/Bundle.php deleted file mode 100644 index 2ff356c..0000000 --- a/vendor/symfony/http-kernel/Bundle/Bundle.php +++ /dev/null @@ -1,163 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Bundle; - -use Symfony\Component\Console\Application; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ContainerAwareTrait; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; - -/** - * An implementation of BundleInterface that adds a few conventions for DependencyInjection extensions. - * - * @author Fabien Potencier - */ -abstract class Bundle implements BundleInterface -{ - use ContainerAwareTrait; - - protected $name; - protected $extension; - protected $path; - private $namespace; - - /** - * {@inheritdoc} - */ - public function boot() - { - } - - /** - * {@inheritdoc} - */ - public function shutdown() - { - } - - /** - * {@inheritdoc} - * - * This method can be overridden to register compilation passes, - * other extensions, ... - */ - public function build(ContainerBuilder $container) - { - } - - /** - * Returns the bundle's container extension. - * - * @return ExtensionInterface|null The container extension - * - * @throws \LogicException - */ - public function getContainerExtension() - { - if (null === $this->extension) { - $extension = $this->createContainerExtension(); - - if (null !== $extension) { - if (!$extension instanceof ExtensionInterface) { - throw new \LogicException(sprintf('Extension %s must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', \get_class($extension))); - } - - // check naming convention - $basename = preg_replace('/Bundle$/', '', $this->getName()); - $expectedAlias = Container::underscore($basename); - - if ($expectedAlias != $extension->getAlias()) { - throw new \LogicException(sprintf('Users will expect the alias of the default extension of a bundle to be the underscored version of the bundle name ("%s"). You can override "Bundle::getContainerExtension()" if you want to use "%s" or another alias.', $expectedAlias, $extension->getAlias())); - } - - $this->extension = $extension; - } else { - $this->extension = false; - } - } - - return $this->extension ?: null; - } - - /** - * {@inheritdoc} - */ - public function getNamespace() - { - if (null === $this->namespace) { - $this->parseClassName(); - } - - return $this->namespace; - } - - /** - * {@inheritdoc} - */ - public function getPath() - { - if (null === $this->path) { - $reflected = new \ReflectionObject($this); - $this->path = \dirname($reflected->getFileName()); - } - - return $this->path; - } - - /** - * Returns the bundle name (the class short name). - */ - final public function getName(): string - { - if (null === $this->name) { - $this->parseClassName(); - } - - return $this->name; - } - - public function registerCommands(Application $application) - { - } - - /** - * Returns the bundle's container extension class. - * - * @return string - */ - protected function getContainerExtensionClass() - { - $basename = preg_replace('/Bundle$/', '', $this->getName()); - - return $this->getNamespace().'\\DependencyInjection\\'.$basename.'Extension'; - } - - /** - * Creates the bundle's container extension. - * - * @return ExtensionInterface|null - */ - protected function createContainerExtension() - { - return class_exists($class = $this->getContainerExtensionClass()) ? new $class() : null; - } - - private function parseClassName() - { - $pos = strrpos(static::class, '\\'); - $this->namespace = false === $pos ? '' : substr(static::class, 0, $pos); - if (null === $this->name) { - $this->name = false === $pos ? static::class : substr(static::class, $pos + 1); - } - } -} diff --git a/vendor/symfony/http-kernel/Bundle/BundleInterface.php b/vendor/symfony/http-kernel/Bundle/BundleInterface.php deleted file mode 100644 index 88a95d8..0000000 --- a/vendor/symfony/http-kernel/Bundle/BundleInterface.php +++ /dev/null @@ -1,71 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Bundle; - -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; - -/** - * BundleInterface. - * - * @author Fabien Potencier - */ -interface BundleInterface extends ContainerAwareInterface -{ - /** - * Boots the Bundle. - */ - public function boot(); - - /** - * Shutdowns the Bundle. - */ - public function shutdown(); - - /** - * Builds the bundle. - * - * It is only ever called once when the cache is empty. - */ - public function build(ContainerBuilder $container); - - /** - * Returns the container extension that should be implicitly loaded. - * - * @return ExtensionInterface|null The default extension or null if there is none - */ - public function getContainerExtension(); - - /** - * Returns the bundle name (the class short name). - * - * @return string The Bundle name - */ - public function getName(); - - /** - * Gets the Bundle namespace. - * - * @return string The Bundle namespace - */ - public function getNamespace(); - - /** - * Gets the Bundle directory path. - * - * The path should always be returned as a Unix path (with /). - * - * @return string The Bundle absolute path - */ - public function getPath(); -} diff --git a/vendor/symfony/http-kernel/CHANGELOG.md b/vendor/symfony/http-kernel/CHANGELOG.md deleted file mode 100644 index adcbe66..0000000 --- a/vendor/symfony/http-kernel/CHANGELOG.md +++ /dev/null @@ -1,269 +0,0 @@ -CHANGELOG -========= - -5.0.0 ------ - - * removed support for getting the container from a non-booted kernel - * removed the first and second constructor argument of `ConfigDataCollector` - * removed `ConfigDataCollector::getApplicationName()` - * removed `ConfigDataCollector::getApplicationVersion()` - * removed support for `Symfony\Component\Templating\EngineInterface` in `HIncludeFragmentRenderer`, use a `Twig\Environment` only - * removed `TranslatorListener` in favor of `LocaleAwareListener` - * removed `getRootDir()` and `getName()` from `Kernel` and `KernelInterface` - * removed `FilterControllerArgumentsEvent`, use `ControllerArgumentsEvent` instead - * removed `FilterControllerEvent`, use `ControllerEvent` instead - * removed `FilterResponseEvent`, use `ResponseEvent` instead - * removed `GetResponseEvent`, use `RequestEvent` instead - * removed `GetResponseForControllerResultEvent`, use `ViewEvent` instead - * removed `GetResponseForExceptionEvent`, use `ExceptionEvent` instead - * removed `PostResponseEvent`, use `TerminateEvent` instead - * removed `SaveSessionListener` in favor of `AbstractSessionListener` - * removed `Client`, use `HttpKernelBrowser` instead - * added method `getProjectDir()` to `KernelInterface` - * removed methods `serialize` and `unserialize` from `DataCollector`, store the serialized state in the data property instead - * made `ProfilerStorageInterface` internal - * removed the second and third argument of `KernelInterface::locateResource` - * removed the second and third argument of `FileLocator::__construct` - * removed loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as - fallback directories. - * removed class `ExceptionListener`, use `ErrorListener` instead - -4.4.0 ------ - - * The `DebugHandlersListener` class has been marked as `final` - * Added new Bundle directory convention consistent with standard skeletons - * Deprecated the second and third argument of `KernelInterface::locateResource` - * Deprecated the second and third argument of `FileLocator::__construct` - * Deprecated loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as - fallback directories. Resources like service definitions are usually loaded relative to the - current directory or with a glob pattern. The fallback directories have never been advocated - so you likely do not use those in any app based on the SF Standard or Flex edition. - * Marked all dispatched event classes as `@final` - * Added `ErrorController` to enable the preview and error rendering mechanism - * Getting the container from a non-booted kernel is deprecated. - * Marked the `AjaxDataCollector`, `ConfigDataCollector`, `EventDataCollector`, - `ExceptionDataCollector`, `LoggerDataCollector`, `MemoryDataCollector`, - `RequestDataCollector` and `TimeDataCollector` classes as `@final`. - * Marked the `RouterDataCollector::collect()` method as `@final`. - * The `DataCollectorInterface::collect()` and `Profiler::collect()` methods third parameter signature - will be `\Throwable $exception = null` instead of `\Exception $exception = null` in Symfony 5.0. - * Deprecated methods `ExceptionEvent::get/setException()`, use `get/setThrowable()` instead - * Deprecated class `ExceptionListener`, use `ErrorListener` instead - -4.3.0 ------ - - * renamed `Client` to `HttpKernelBrowser` - * `KernelInterface` doesn't extend `Serializable` anymore - * deprecated the `Kernel::serialize()` and `unserialize()` methods - * increased the priority of `Symfony\Component\HttpKernel\EventListener\AddRequestFormatsListener` - * made `Symfony\Component\HttpKernel\EventListener\LocaleListener` set the default locale early - * deprecated `TranslatorListener` in favor of `LocaleAwareListener` - * added the registration of all `LocaleAwareInterface` implementations into the `LocaleAwareListener` - * made `FileLinkFormatter` final and not implement `Serializable` anymore - * the base `DataCollector` doesn't implement `Serializable` anymore, you should - store all the serialized state in the data property instead - * `DumpDataCollector` has been marked as `final` - * added an event listener to prevent search engines from indexing applications in debug mode. - * renamed `FilterControllerArgumentsEvent` to `ControllerArgumentsEvent` - * renamed `FilterControllerEvent` to `ControllerEvent` - * renamed `FilterResponseEvent` to `ResponseEvent` - * renamed `GetResponseEvent` to `RequestEvent` - * renamed `GetResponseForControllerResultEvent` to `ViewEvent` - * renamed `GetResponseForExceptionEvent` to `ExceptionEvent` - * renamed `PostResponseEvent` to `TerminateEvent` - * added `HttpClientKernel` for handling requests with an `HttpClientInterface` instance - * added `trace_header` and `trace_level` configuration options to `HttpCache` - -4.2.0 ------ - - * deprecated `KernelInterface::getRootDir()` and the `kernel.root_dir` parameter - * deprecated `KernelInterface::getName()` and the `kernel.name` parameter - * deprecated the first and second constructor argument of `ConfigDataCollector` - * deprecated `ConfigDataCollector::getApplicationName()` - * deprecated `ConfigDataCollector::getApplicationVersion()` - -4.1.0 ------ - - * added orphaned events support to `EventDataCollector` - * `ExceptionListener` now logs exceptions at priority `0` (previously logged at `-128`) - * Added support for using `service::method` to reference controllers, making it consistent with other cases. It is recommended over the `service:action` syntax with a single colon, which will be deprecated in the future. - * Added the ability to profile individual argument value resolvers via the - `Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver` - -4.0.0 ------ - - * removed the `DataCollector::varToString()` method, use `DataCollector::cloneVar()` - instead - * using the `DataCollector::cloneVar()` method requires the VarDumper component - * removed the `ValueExporter` class - * removed `ControllerResolverInterface::getArguments()` - * removed `TraceableControllerResolver::getArguments()` - * removed `ControllerResolver::getArguments()` and the ability to resolve arguments - * removed the `argument_resolver` service dependency from the `debug.controller_resolver` - * removed `LazyLoadingFragmentHandler::addRendererService()` - * removed `Psr6CacheClearer::addPool()` - * removed `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()` - * removed `Kernel::loadClassCache()`, `Kernel::doLoadClassCache()`, `Kernel::setClassCache()`, - and `Kernel::getEnvParameters()` - * support for the `X-Status-Code` when handling exceptions in the `HttpKernel` - has been dropped, use the `HttpKernel::allowCustomResponseCode()` method - instead - * removed convention-based commands registration - * removed the `ChainCacheClearer::add()` method - * removed the `CacheaWarmerAggregate::add()` and `setWarmers()` methods - * made `CacheWarmerAggregate` and `ChainCacheClearer` classes final - -3.4.0 ------ - - * added a minimalist PSR-3 `Logger` class that writes in `stderr` - * made kernels implementing `CompilerPassInterface` able to process the container - * deprecated bundle inheritance - * added `RebootableInterface` and implemented it in `Kernel` - * deprecated commands auto registration - * deprecated `EnvParametersResource` - * added `Symfony\Component\HttpKernel\Client::catchExceptions()` - * deprecated the `ChainCacheClearer::add()` method - * deprecated the `CacheaWarmerAggregate::add()` and `setWarmers()` methods - * made `CacheWarmerAggregate` and `ChainCacheClearer` classes final - * added the possibility to reset the profiler to its initial state - * deprecated data collectors without a `reset()` method - * deprecated implementing `DebugLoggerInterface` without a `clear()` method - -3.3.0 ------ - - * added `kernel.project_dir` and `Kernel::getProjectDir()` - * deprecated `kernel.root_dir` and `Kernel::getRootDir()` - * deprecated `Kernel::getEnvParameters()` - * deprecated the special `SYMFONY__` environment variables - * added the possibility to change the query string parameter used by `UriSigner` - * deprecated `LazyLoadingFragmentHandler::addRendererService()` - * deprecated `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()` - * deprecated `Psr6CacheClearer::addPool()` - -3.2.0 ------ - - * deprecated `DataCollector::varToString()`, use `cloneVar()` instead - * changed surrogate capability name in `AbstractSurrogate::addSurrogateCapability` to 'symfony' - * Added `ControllerArgumentValueResolverPass` - -3.1.0 ------ - * deprecated passing objects as URI attributes to the ESI and SSI renderers - * deprecated `ControllerResolver::getArguments()` - * added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface` - * added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface` as argument to `HttpKernel` - * added `Symfony\Component\HttpKernel\Controller\ArgumentResolver` - * added `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector::getMethod()` - * added `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector::getRedirect()` - * added the `kernel.controller_arguments` event, triggered after controller arguments have been resolved - -3.0.0 ------ - - * removed `Symfony\Component\HttpKernel\Kernel::init()` - * removed `Symfony\Component\HttpKernel\Kernel::isClassInActiveBundle()` and `Symfony\Component\HttpKernel\KernelInterface::isClassInActiveBundle()` - * removed `Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher::setProfiler()` - * removed `Symfony\Component\HttpKernel\EventListener\FragmentListener::getLocalIpAddresses()` - * removed `Symfony\Component\HttpKernel\EventListener\LocaleListener::setRequest()` - * removed `Symfony\Component\HttpKernel\EventListener\RouterListener::setRequest()` - * removed `Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelRequest()` - * removed `Symfony\Component\HttpKernel\Fragment\FragmentHandler::setRequest()` - * removed `Symfony\Component\HttpKernel\HttpCache\Esi::hasSurrogateEsiCapability()` - * removed `Symfony\Component\HttpKernel\HttpCache\Esi::addSurrogateEsiCapability()` - * removed `Symfony\Component\HttpKernel\HttpCache\Esi::needsEsiParsing()` - * removed `Symfony\Component\HttpKernel\HttpCache\HttpCache::getEsi()` - * removed `Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel` - * removed `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass` - * removed `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener` - * removed `Symfony\Component\HttpKernel\EventListener\EsiListener` - * removed `Symfony\Component\HttpKernel\HttpCache\EsiResponseCacheStrategy` - * removed `Symfony\Component\HttpKernel\HttpCache\EsiResponseCacheStrategyInterface` - * removed `Symfony\Component\HttpKernel\Log\LoggerInterface` - * removed `Symfony\Component\HttpKernel\Log\NullLogger` - * removed `Symfony\Component\HttpKernel\Profiler::import()` - * removed `Symfony\Component\HttpKernel\Profiler::export()` - -2.8.0 ------ - - * deprecated `Profiler::import` and `Profiler::export` - -2.7.0 ------ - - * added the HTTP status code to profiles - -2.6.0 ------ - - * deprecated `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener`, use `Symfony\Component\HttpKernel\EventListener\DebugHandlersListener` instead - * deprecated unused method `Symfony\Component\HttpKernel\Kernel::isClassInActiveBundle` and `Symfony\Component\HttpKernel\KernelInterface::isClassInActiveBundle` - -2.5.0 ------ - - * deprecated `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass`, use `Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass` instead - -2.4.0 ------ - - * added event listeners for the session - * added the KernelEvents::FINISH_REQUEST event - -2.3.0 ------ - - * [BC BREAK] renamed `Symfony\Component\HttpKernel\EventListener\DeprecationLoggerListener` to `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener` and changed its constructor - * deprecated `Symfony\Component\HttpKernel\Debug\ErrorHandler`, `Symfony\Component\HttpKernel\Debug\ExceptionHandler`, - `Symfony\Component\HttpKernel\Exception\FatalErrorException` and `Symfony\Component\HttpKernel\Exception\FlattenException` - * deprecated `Symfony\Component\HttpKernel\Kernel::init()` - * added the possibility to specify an id an extra attributes to hinclude tags - * added the collect of data if a controller is a Closure in the Request collector - * pass exceptions from the ExceptionListener to the logger using the logging context to allow for more - detailed messages - -2.2.0 ------ - - * [BC BREAK] the path info for sub-request is now always _fragment (or whatever you configured instead of the default) - * added Symfony\Component\HttpKernel\EventListener\FragmentListener - * added Symfony\Component\HttpKernel\UriSigner - * added Symfony\Component\HttpKernel\FragmentRenderer and rendering strategies (in Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface) - * added Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel - * added ControllerReference to create reference of Controllers (used in the FragmentRenderer class) - * [BC BREAK] renamed TimeDataCollector::getTotalTime() to - TimeDataCollector::getDuration() - * updated the MemoryDataCollector to include the memory used in the - kernel.terminate event listeners - * moved the Stopwatch classes to a new component - * added TraceableControllerResolver - * added TraceableEventDispatcher (removed ContainerAwareTraceableEventDispatcher) - * added support for WinCache opcode cache in ConfigDataCollector - -2.1.0 ------ - - * [BC BREAK] the charset is now configured via the Kernel::getCharset() method - * [BC BREAK] the current locale for the user is not stored anymore in the session - * added the HTTP method to the profiler storage - * updated all listeners to implement EventSubscriberInterface - * added TimeDataCollector - * added ContainerAwareTraceableEventDispatcher - * moved TraceableEventDispatcherInterface to the EventDispatcher component - * added RouterListener, LocaleListener, and StreamedResponseListener - * added CacheClearerInterface (and ChainCacheClearer) - * added a kernel.terminate event (via TerminableInterface and PostResponseEvent) - * added a Stopwatch class - * added WarmableInterface - * improved extensibility between bundles - * added profiler storages for Memcache(d), File-based, MongoDB, Redis - * moved Filesystem class to its own component diff --git a/vendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.php b/vendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.php deleted file mode 100644 index 270f690..0000000 --- a/vendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheClearer; - -/** - * CacheClearerInterface. - * - * @author Dustin Dobervich - */ -interface CacheClearerInterface -{ - /** - * Clears any caches necessary. - */ - public function clear(string $cacheDir); -} diff --git a/vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php b/vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php deleted file mode 100644 index 95d41a8..0000000 --- a/vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheClearer; - -/** - * ChainCacheClearer. - * - * @author Dustin Dobervich - * - * @final - */ -class ChainCacheClearer implements CacheClearerInterface -{ - private $clearers; - - public function __construct(iterable $clearers = []) - { - $this->clearers = $clearers; - } - - /** - * {@inheritdoc} - */ - public function clear(string $cacheDir) - { - foreach ($this->clearers as $clearer) { - $clearer->clear($cacheDir); - } - } -} diff --git a/vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php b/vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php deleted file mode 100644 index ab37853..0000000 --- a/vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheClearer; - -/** - * @author Nicolas Grekas - */ -class Psr6CacheClearer implements CacheClearerInterface -{ - private $pools = []; - - public function __construct(array $pools = []) - { - $this->pools = $pools; - } - - public function hasPool(string $name) - { - return isset($this->pools[$name]); - } - - public function getPool(string $name) - { - if (!$this->hasPool($name)) { - throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name)); - } - - return $this->pools[$name]; - } - - public function clearPool(string $name) - { - if (!isset($this->pools[$name])) { - throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name)); - } - - return $this->pools[$name]->clear(); - } - - /** - * {@inheritdoc} - */ - public function clear(string $cacheDir) - { - foreach ($this->pools as $pool) { - $pool->clear(); - } - } -} diff --git a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php deleted file mode 100644 index aef42d6..0000000 --- a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheWarmer; - -/** - * Abstract cache warmer that knows how to write a file to the cache. - * - * @author Fabien Potencier - */ -abstract class CacheWarmer implements CacheWarmerInterface -{ - protected function writeCacheFile(string $file, $content) - { - $tmpFile = @tempnam(\dirname($file), basename($file)); - if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) { - @chmod($file, 0666 & ~umask()); - - return; - } - - throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file)); - } -} diff --git a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php deleted file mode 100644 index 1b3d73b..0000000 --- a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php +++ /dev/null @@ -1,120 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheWarmer; - -/** - * Aggregates several cache warmers into a single one. - * - * @author Fabien Potencier - * - * @final - */ -class CacheWarmerAggregate implements CacheWarmerInterface -{ - private $warmers; - private $debug; - private $deprecationLogsFilepath; - private $optionalsEnabled = false; - private $onlyOptionalsEnabled = false; - - public function __construct(iterable $warmers = [], bool $debug = false, string $deprecationLogsFilepath = null) - { - $this->warmers = $warmers; - $this->debug = $debug; - $this->deprecationLogsFilepath = $deprecationLogsFilepath; - } - - public function enableOptionalWarmers() - { - $this->optionalsEnabled = true; - } - - public function enableOnlyOptionalWarmers() - { - $this->onlyOptionalsEnabled = $this->optionalsEnabled = true; - } - - /** - * Warms up the cache. - */ - public function warmUp(string $cacheDir) - { - if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) { - $collectedLogs = []; - $previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) { - if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) { - return $previousHandler ? $previousHandler($type, $message, $file, $line) : false; - } - - if (isset($collectedLogs[$message])) { - ++$collectedLogs[$message]['count']; - - return null; - } - - $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3); - // Clean the trace by removing first frames added by the error handler itself. - for ($i = 0; isset($backtrace[$i]); ++$i) { - if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { - $backtrace = \array_slice($backtrace, 1 + $i); - break; - } - } - - $collectedLogs[$message] = [ - 'type' => $type, - 'message' => $message, - 'file' => $file, - 'line' => $line, - 'trace' => $backtrace, - 'count' => 1, - ]; - - return null; - }); - } - - try { - foreach ($this->warmers as $warmer) { - if (!$this->optionalsEnabled && $warmer->isOptional()) { - continue; - } - if ($this->onlyOptionalsEnabled && !$warmer->isOptional()) { - continue; - } - - $warmer->warmUp($cacheDir); - } - } finally { - if ($collectDeprecations) { - restore_error_handler(); - - if (file_exists($this->deprecationLogsFilepath)) { - $previousLogs = unserialize(file_get_contents($this->deprecationLogsFilepath)); - $collectedLogs = array_merge($previousLogs, $collectedLogs); - } - - file_put_contents($this->deprecationLogsFilepath, serialize(array_values($collectedLogs))); - } - } - } - - /** - * Checks whether this warmer is optional or not. - * - * @return bool always false - */ - public function isOptional(): bool - { - return false; - } -} diff --git a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php deleted file mode 100644 index 8fece5e..0000000 --- a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheWarmer; - -/** - * Interface for classes able to warm up the cache. - * - * @author Fabien Potencier - */ -interface CacheWarmerInterface extends WarmableInterface -{ - /** - * Checks whether this warmer is optional or not. - * - * Optional warmers can be ignored on certain conditions. - * - * A warmer should return true if the cache can be - * generated incrementally and on-demand. - * - * @return bool true if the warmer is optional, false otherwise - */ - public function isOptional(); -} diff --git a/vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.php b/vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.php deleted file mode 100644 index e7715a3..0000000 --- a/vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\CacheWarmer; - -/** - * Interface for classes that support warming their cache. - * - * @author Fabien Potencier - */ -interface WarmableInterface -{ - /** - * Warms up the cache. - */ - public function warmUp(string $cacheDir); -} diff --git a/vendor/symfony/http-kernel/Config/FileLocator.php b/vendor/symfony/http-kernel/Config/FileLocator.php deleted file mode 100644 index 6eca986..0000000 --- a/vendor/symfony/http-kernel/Config/FileLocator.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Config; - -use Symfony\Component\Config\FileLocator as BaseFileLocator; -use Symfony\Component\HttpKernel\KernelInterface; - -/** - * FileLocator uses the KernelInterface to locate resources in bundles. - * - * @author Fabien Potencier - */ -class FileLocator extends BaseFileLocator -{ - private $kernel; - - public function __construct(KernelInterface $kernel) - { - $this->kernel = $kernel; - - parent::__construct(); - } - - /** - * {@inheritdoc} - */ - public function locate(string $file, string $currentPath = null, bool $first = true) - { - if (isset($file[0]) && '@' === $file[0]) { - $resource = $this->kernel->locateResource($file); - - return $first ? $resource : [$resource]; - } - - return parent::locate($file, $currentPath, $first); - } -} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver.php deleted file mode 100644 index 43bbe17..0000000 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface; - -/** - * Responsible for resolving the arguments passed to an action. - * - * @author Iltar van der Berg - */ -final class ArgumentResolver implements ArgumentResolverInterface -{ - private $argumentMetadataFactory; - - /** - * @var iterable|ArgumentValueResolverInterface[] - */ - private $argumentValueResolvers; - - public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = []) - { - $this->argumentMetadataFactory = $argumentMetadataFactory ?: new ArgumentMetadataFactory(); - $this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers(); - } - - /** - * {@inheritdoc} - */ - public function getArguments(Request $request, callable $controller): array - { - $arguments = []; - - foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller) as $metadata) { - foreach ($this->argumentValueResolvers as $resolver) { - if (!$resolver->supports($request, $metadata)) { - continue; - } - - $resolved = $resolver->resolve($request, $metadata); - - $atLeastOne = false; - foreach ($resolved as $append) { - $atLeastOne = true; - $arguments[] = $append; - } - - if (!$atLeastOne) { - throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', \get_class($resolver))); - } - - // continue to the next controller argument - continue 2; - } - - $representative = $controller; - - if (\is_array($representative)) { - $representative = sprintf('%s::%s()', \get_class($representative[0]), $representative[1]); - } elseif (\is_object($representative)) { - $representative = \get_class($representative); - } - - throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.', $representative, $metadata->getName())); - } - - return $arguments; - } - - public static function getDefaultArgumentValueResolvers(): iterable - { - return [ - new RequestAttributeValueResolver(), - new RequestValueResolver(), - new SessionValueResolver(), - new DefaultValueResolver(), - new VariadicValueResolver(), - ]; - } -} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php deleted file mode 100644 index 32a0e07..0000000 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Yields the default value defined in the action signature when no value has been given. - * - * @author Iltar van der Berg - */ -final class DefaultValueResolver implements ArgumentValueResolverInterface -{ - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - return $argument->hasDefaultValue() || (null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic()); - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - yield $argument->hasDefaultValue() ? $argument->getDefaultValue() : null; - } -} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php deleted file mode 100644 index d4971cc..0000000 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php +++ /dev/null @@ -1,81 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Provides an intuitive error message when controller fails because it is not registered as a service. - * - * @author Simeon Kolev - */ -final class NotTaggedControllerValueResolver implements ArgumentValueResolverInterface -{ - private $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - $controller = $request->attributes->get('_controller'); - - if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) { - $controller = $controller[0].'::'.$controller[1]; - } elseif (!\is_string($controller) || '' === $controller) { - return false; - } - - if ('\\' === $controller[0]) { - $controller = ltrim($controller, '\\'); - } - - if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) { - $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); - } - - return false === $this->container->has($controller); - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - if (\is_array($controller = $request->attributes->get('_controller'))) { - $controller = $controller[0].'::'.$controller[1]; - } - - if ('\\' === $controller[0]) { - $controller = ltrim($controller, '\\'); - } - - if (!$this->container->has($controller)) { - $i = strrpos($controller, ':'); - $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); - } - - $what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller); - $message = sprintf('Could not resolve %s, maybe you forgot to register the controller as a service or missed tagging it with the "controller.service_arguments"?', $what); - - throw new RuntimeException($message); - } -} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php deleted file mode 100644 index c62d327..0000000 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Yields a non-variadic argument's value from the request attributes. - * - * @author Iltar van der Berg - */ -final class RequestAttributeValueResolver implements ArgumentValueResolverInterface -{ - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - return !$argument->isVariadic() && $request->attributes->has($argument->getName()); - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - yield $request->attributes->get($argument->getName()); - } -} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php deleted file mode 100644 index 75cbd97..0000000 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Yields the same instance as the request object passed along. - * - * @author Iltar van der Berg - */ -final class RequestValueResolver implements ArgumentValueResolverInterface -{ - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - return Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class); - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - yield $request; - } -} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php deleted file mode 100644 index 4ffb8c9..0000000 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php +++ /dev/null @@ -1,93 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Yields a service keyed by _controller and argument name. - * - * @author Nicolas Grekas - */ -final class ServiceValueResolver implements ArgumentValueResolverInterface -{ - private $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - $controller = $request->attributes->get('_controller'); - - if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) { - $controller = $controller[0].'::'.$controller[1]; - } elseif (!\is_string($controller) || '' === $controller) { - return false; - } - - if ('\\' === $controller[0]) { - $controller = ltrim($controller, '\\'); - } - - if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) { - $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); - } - - return $this->container->has($controller) && $this->container->get($controller)->has($argument->getName()); - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - if (\is_array($controller = $request->attributes->get('_controller'))) { - $controller = $controller[0].'::'.$controller[1]; - } - - if ('\\' === $controller[0]) { - $controller = ltrim($controller, '\\'); - } - - if (!$this->container->has($controller)) { - $i = strrpos($controller, ':'); - $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); - } - - try { - yield $this->container->get($controller)->get($argument->getName()); - } catch (RuntimeException $e) { - $what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller); - $message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage()); - - if ($e->getMessage() === $message) { - $message = sprintf('Cannot resolve %s: %s', $what, $message); - } - - $r = new \ReflectionProperty($e, 'message'); - $r->setAccessible(true); - $r->setValue($e, $message); - - throw $e; - } - } -} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php deleted file mode 100644 index a1e6b43..0000000 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Yields the Session. - * - * @author Iltar van der Berg - */ -final class SessionValueResolver implements ArgumentValueResolverInterface -{ - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - if (!$request->hasSession()) { - return false; - } - - $type = $argument->getType(); - if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) { - return false; - } - - return $request->getSession() instanceof $type; - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - yield $request->getSession(); - } -} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php deleted file mode 100644 index bde3c90..0000000 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; -use Symfony\Component\Stopwatch\Stopwatch; - -/** - * Provides timing information via the stopwatch. - * - * @author Iltar van der Berg - */ -final class TraceableValueResolver implements ArgumentValueResolverInterface -{ - private $inner; - private $stopwatch; - - public function __construct(ArgumentValueResolverInterface $inner, Stopwatch $stopwatch) - { - $this->inner = $inner; - $this->stopwatch = $stopwatch; - } - - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - $method = \get_class($this->inner).'::'.__FUNCTION__; - $this->stopwatch->start($method, 'controller.argument_value_resolver'); - - $return = $this->inner->supports($request, $argument); - - $this->stopwatch->stop($method); - - return $return; - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - $method = \get_class($this->inner).'::'.__FUNCTION__; - $this->stopwatch->start($method, 'controller.argument_value_resolver'); - - yield from $this->inner->resolve($request, $argument); - - $this->stopwatch->stop($method); - } -} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php deleted file mode 100644 index ed61420..0000000 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Yields a variadic argument's values from the request attributes. - * - * @author Iltar van der Berg - */ -final class VariadicValueResolver implements ArgumentValueResolverInterface -{ - /** - * {@inheritdoc} - */ - public function supports(Request $request, ArgumentMetadata $argument): bool - { - return $argument->isVariadic() && $request->attributes->has($argument->getName()); - } - - /** - * {@inheritdoc} - */ - public function resolve(Request $request, ArgumentMetadata $argument): iterable - { - $values = $request->attributes->get($argument->getName()); - - if (!\is_array($values)) { - throw new \InvalidArgumentException(sprintf('The action argument "...$%1$s" is required to be an array, the request attribute "%1$s" contains a type of "%2$s" instead.', $argument->getName(), \gettype($values))); - } - - yield from $values; - } -} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php b/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php deleted file mode 100644 index 2c32492..0000000 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpFoundation\Request; - -/** - * An ArgumentResolverInterface instance knows how to determine the - * arguments for a specific action. - * - * @author Fabien Potencier - */ -interface ArgumentResolverInterface -{ - /** - * Returns the arguments to pass to the controller. - * - * @return array An array of arguments to pass to the controller - * - * @throws \RuntimeException When no value could be provided for a required argument - */ - public function getArguments(Request $request, callable $controller); -} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php b/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php deleted file mode 100644 index 1317707..0000000 --- a/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; - -/** - * Responsible for resolving the value of an argument based on its metadata. - * - * @author Iltar van der Berg - */ -interface ArgumentValueResolverInterface -{ - /** - * Whether this resolver can resolve the value for the given ArgumentMetadata. - * - * @return bool - */ - public function supports(Request $request, ArgumentMetadata $argument); - - /** - * Returns the possible value(s). - * - * @return iterable - */ - public function resolve(Request $request, ArgumentMetadata $argument); -} diff --git a/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php b/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php deleted file mode 100644 index 447df4a..0000000 --- a/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Psr\Container\ContainerInterface; -use Psr\Log\LoggerInterface; -use Symfony\Component\DependencyInjection\Container; - -/** - * A controller resolver searching for a controller in a psr-11 container when using the "service:method" notation. - * - * @author Fabien Potencier - * @author Maxime Steinhausser - */ -class ContainerControllerResolver extends ControllerResolver -{ - protected $container; - - public function __construct(ContainerInterface $container, LoggerInterface $logger = null) - { - $this->container = $container; - - parent::__construct($logger); - } - - protected function createController(string $controller) - { - if (1 === substr_count($controller, ':')) { - $controller = str_replace(':', '::', $controller); - // TODO deprecate this in 5.1 - } - - return parent::createController($controller); - } - - /** - * {@inheritdoc} - */ - protected function instantiateController(string $class) - { - $class = ltrim($class, '\\'); - - if ($this->container->has($class)) { - return $this->container->get($class); - } - - try { - return parent::instantiateController($class); - } catch (\Error $e) { - } - - $this->throwExceptionIfControllerWasRemoved($class, $e); - - if ($e instanceof \ArgumentCountError) { - throw new \InvalidArgumentException(sprintf('Controller "%s" has required constructor arguments and does not exist in the container. Did you forget to define the controller as a service?', $class), 0, $e); - } - - throw new \InvalidArgumentException(sprintf('Controller "%s" does neither exist as service nor as class', $class), 0, $e); - } - - private function throwExceptionIfControllerWasRemoved(string $controller, \Throwable $previous) - { - if ($this->container instanceof Container && isset($this->container->getRemovedIds()[$controller])) { - throw new \InvalidArgumentException(sprintf('Controller "%s" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?', $controller), 0, $previous); - } - } -} diff --git a/vendor/symfony/http-kernel/Controller/ControllerReference.php b/vendor/symfony/http-kernel/Controller/ControllerReference.php deleted file mode 100644 index b4fdadd..0000000 --- a/vendor/symfony/http-kernel/Controller/ControllerReference.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface; - -/** - * Acts as a marker and a data holder for a Controller. - * - * Some methods in Symfony accept both a URI (as a string) or a controller as - * an argument. In the latter case, instead of passing an array representing - * the controller, you can use an instance of this class. - * - * @author Fabien Potencier - * - * @see FragmentRendererInterface - */ -class ControllerReference -{ - public $controller; - public $attributes = []; - public $query = []; - - /** - * @param string $controller The controller name - * @param array $attributes An array of parameters to add to the Request attributes - * @param array $query An array of parameters to add to the Request query string - */ - public function __construct(string $controller, array $attributes = [], array $query = []) - { - $this->controller = $controller; - $this->attributes = $attributes; - $this->query = $query; - } -} diff --git a/vendor/symfony/http-kernel/Controller/ControllerResolver.php b/vendor/symfony/http-kernel/Controller/ControllerResolver.php deleted file mode 100644 index b5bd403..0000000 --- a/vendor/symfony/http-kernel/Controller/ControllerResolver.php +++ /dev/null @@ -1,220 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Psr\Log\LoggerInterface; -use Symfony\Component\HttpFoundation\Request; - -/** - * This implementation uses the '_controller' request attribute to determine - * the controller to execute. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class ControllerResolver implements ControllerResolverInterface -{ - private $logger; - - public function __construct(LoggerInterface $logger = null) - { - $this->logger = $logger; - } - - /** - * {@inheritdoc} - */ - public function getController(Request $request) - { - if (!$controller = $request->attributes->get('_controller')) { - if (null !== $this->logger) { - $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.'); - } - - return false; - } - - if (\is_array($controller)) { - if (isset($controller[0]) && \is_string($controller[0]) && isset($controller[1])) { - try { - $controller[0] = $this->instantiateController($controller[0]); - } catch (\Error | \LogicException $e) { - try { - // We cannot just check is_callable but have to use reflection because a non-static method - // can still be called statically in PHP but we don't want that. This is deprecated in PHP 7, so we - // could simplify this with PHP 8. - if ((new \ReflectionMethod($controller[0], $controller[1]))->isStatic()) { - return $controller; - } - } catch (\ReflectionException $reflectionException) { - throw $e; - } - - throw $e; - } - } - - if (!\is_callable($controller)) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($controller))); - } - - return $controller; - } - - if (\is_object($controller)) { - if (!\is_callable($controller)) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($controller))); - } - - return $controller; - } - - if (\function_exists($controller)) { - return $controller; - } - - try { - $callable = $this->createController($controller); - } catch (\InvalidArgumentException $e) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $e->getMessage())); - } - - if (!\is_callable($callable)) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($callable))); - } - - return $callable; - } - - /** - * Returns a callable for the given controller. - * - * @return callable A PHP callable - * - * @throws \InvalidArgumentException When the controller cannot be created - */ - protected function createController(string $controller) - { - if (false === strpos($controller, '::')) { - $controller = $this->instantiateController($controller); - - if (!\is_callable($controller)) { - throw new \InvalidArgumentException($this->getControllerError($controller)); - } - - return $controller; - } - - list($class, $method) = explode('::', $controller, 2); - - try { - $controller = [$this->instantiateController($class), $method]; - } catch (\Error | \LogicException $e) { - try { - if ((new \ReflectionMethod($class, $method))->isStatic()) { - return $class.'::'.$method; - } - } catch (\ReflectionException $reflectionException) { - throw $e; - } - - throw $e; - } - - if (!\is_callable($controller)) { - throw new \InvalidArgumentException($this->getControllerError($controller)); - } - - return $controller; - } - - /** - * Returns an instantiated controller. - * - * @return object - */ - protected function instantiateController(string $class) - { - return new $class(); - } - - private function getControllerError($callable): string - { - if (\is_string($callable)) { - if (false !== strpos($callable, '::')) { - $callable = explode('::', $callable, 2); - } else { - return sprintf('Function "%s" does not exist.', $callable); - } - } - - if (\is_object($callable)) { - $availableMethods = $this->getClassMethodsWithoutMagicMethods($callable); - $alternativeMsg = $availableMethods ? sprintf(' or use one of the available methods: "%s"', implode('", "', $availableMethods)) : ''; - - return sprintf('Controller class "%s" cannot be called without a method name. You need to implement "__invoke"%s.', \get_class($callable), $alternativeMsg); - } - - if (!\is_array($callable)) { - return sprintf('Invalid type for controller given, expected string, array or object, got "%s".', \gettype($callable)); - } - - if (!isset($callable[0]) || !isset($callable[1]) || 2 !== \count($callable)) { - return 'Invalid array callable, expected [controller, method].'; - } - - list($controller, $method) = $callable; - - if (\is_string($controller) && !class_exists($controller)) { - return sprintf('Class "%s" does not exist.', $controller); - } - - $className = \is_object($controller) ? \get_class($controller) : $controller; - - if (method_exists($controller, $method)) { - return sprintf('Method "%s" on class "%s" should be public and non-abstract.', $method, $className); - } - - $collection = $this->getClassMethodsWithoutMagicMethods($controller); - - $alternatives = []; - - foreach ($collection as $item) { - $lev = levenshtein($method, $item); - - if ($lev <= \strlen($method) / 3 || false !== strpos($item, $method)) { - $alternatives[] = $item; - } - } - - asort($alternatives); - - $message = sprintf('Expected method "%s" on class "%s"', $method, $className); - - if (\count($alternatives) > 0) { - $message .= sprintf(', did you mean "%s"?', implode('", "', $alternatives)); - } else { - $message .= sprintf('. Available methods: "%s".', implode('", "', $collection)); - } - - return $message; - } - - private function getClassMethodsWithoutMagicMethods($classOrObject): array - { - $methods = get_class_methods($classOrObject); - - return array_filter($methods, function (string $method) { - return 0 !== strncmp($method, '__', 2); - }); - } -} diff --git a/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php b/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php deleted file mode 100644 index 8b70a88..0000000 --- a/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpFoundation\Request; - -/** - * A ControllerResolverInterface implementation knows how to determine the - * controller to execute based on a Request object. - * - * A Controller can be any valid PHP callable. - * - * @author Fabien Potencier - */ -interface ControllerResolverInterface -{ - /** - * Returns the Controller instance associated with a Request. - * - * As several resolvers can exist for a single application, a resolver must - * return false when it is not able to determine the controller. - * - * The resolver must only throw an exception when it should be able to load a - * controller but cannot because of some errors made by the developer. - * - * @return callable|false A PHP callable representing the Controller, - * or false if this resolver is not able to determine the controller - * - * @throws \LogicException If a controller was found based on the request but it is not callable - */ - public function getController(Request $request); -} diff --git a/vendor/symfony/http-kernel/Controller/ErrorController.php b/vendor/symfony/http-kernel/Controller/ErrorController.php deleted file mode 100644 index b6c4401..0000000 --- a/vendor/symfony/http-kernel/Controller/ErrorController.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Exception\HttpException; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Renders error or exception pages from a given FlattenException. - * - * @author Yonel Ceruto - * @author Matthias Pigulla - */ -class ErrorController -{ - private $kernel; - private $controller; - private $errorRenderer; - - public function __construct(HttpKernelInterface $kernel, $controller, ErrorRendererInterface $errorRenderer) - { - $this->kernel = $kernel; - $this->controller = $controller; - $this->errorRenderer = $errorRenderer; - } - - public function __invoke(\Throwable $exception): Response - { - $exception = $this->errorRenderer->render($exception); - - return new Response($exception->getAsString(), $exception->getStatusCode(), $exception->getHeaders()); - } - - public function preview(Request $request, int $code): Response - { - /* - * This Request mimics the parameters set by - * \Symfony\Component\HttpKernel\EventListener\ErrorListener::duplicateRequest, with - * the additional "showException" flag. - */ - $subRequest = $request->duplicate(null, null, [ - '_controller' => $this->controller, - 'exception' => new HttpException($code, 'This is a sample exception.'), - 'logger' => null, - 'showException' => false, - ]); - - return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST); - } -} diff --git a/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php b/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php deleted file mode 100644 index e22cf08..0000000 --- a/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Stopwatch\Stopwatch; - -/** - * @author Fabien Potencier - */ -class TraceableArgumentResolver implements ArgumentResolverInterface -{ - private $resolver; - private $stopwatch; - - public function __construct(ArgumentResolverInterface $resolver, Stopwatch $stopwatch) - { - $this->resolver = $resolver; - $this->stopwatch = $stopwatch; - } - - /** - * {@inheritdoc} - */ - public function getArguments(Request $request, callable $controller) - { - $e = $this->stopwatch->start('controller.get_arguments'); - - $ret = $this->resolver->getArguments($request, $controller); - - $e->stop(); - - return $ret; - } -} diff --git a/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php b/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php deleted file mode 100644 index bf6b6aa..0000000 --- a/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Controller; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Stopwatch\Stopwatch; - -/** - * @author Fabien Potencier - */ -class TraceableControllerResolver implements ControllerResolverInterface -{ - private $resolver; - private $stopwatch; - - public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch) - { - $this->resolver = $resolver; - $this->stopwatch = $stopwatch; - } - - /** - * {@inheritdoc} - */ - public function getController(Request $request) - { - $e = $this->stopwatch->start('controller.get_callable'); - - $ret = $this->resolver->getController($request); - - $e->stop(); - - return $ret; - } -} diff --git a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php deleted file mode 100644 index e73b848..0000000 --- a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php +++ /dev/null @@ -1,107 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\ControllerMetadata; - -/** - * Responsible for storing metadata of an argument. - * - * @author Iltar van der Berg - */ -class ArgumentMetadata -{ - private $name; - private $type; - private $isVariadic; - private $hasDefaultValue; - private $defaultValue; - private $isNullable; - - public function __construct(string $name, ?string $type, bool $isVariadic, bool $hasDefaultValue, $defaultValue, bool $isNullable = false) - { - $this->name = $name; - $this->type = $type; - $this->isVariadic = $isVariadic; - $this->hasDefaultValue = $hasDefaultValue; - $this->defaultValue = $defaultValue; - $this->isNullable = $isNullable || null === $type || ($hasDefaultValue && null === $defaultValue); - } - - /** - * Returns the name as given in PHP, $foo would yield "foo". - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Returns the type of the argument. - * - * The type is the PHP class in 5.5+ and additionally the basic type in PHP 7.0+. - * - * @return string|null - */ - public function getType() - { - return $this->type; - } - - /** - * Returns whether the argument is defined as "...$variadic". - * - * @return bool - */ - public function isVariadic() - { - return $this->isVariadic; - } - - /** - * Returns whether the argument has a default value. - * - * Implies whether an argument is optional. - * - * @return bool - */ - public function hasDefaultValue() - { - return $this->hasDefaultValue; - } - - /** - * Returns whether the argument accepts null values. - * - * @return bool - */ - public function isNullable() - { - return $this->isNullable; - } - - /** - * Returns the default value of the argument. - * - * @throws \LogicException if no default value is present; {@see self::hasDefaultValue()} - * - * @return mixed - */ - public function getDefaultValue() - { - if (!$this->hasDefaultValue) { - throw new \LogicException(sprintf('Argument $%s does not have a default value. Use %s::hasDefaultValue() to avoid this exception.', $this->name, __CLASS__)); - } - - return $this->defaultValue; - } -} diff --git a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php deleted file mode 100644 index 9370174..0000000 --- a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\ControllerMetadata; - -/** - * Builds {@see ArgumentMetadata} objects based on the given Controller. - * - * @author Iltar van der Berg - */ -final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface -{ - /** - * {@inheritdoc} - */ - public function createArgumentMetadata($controller): array - { - $arguments = []; - - if (\is_array($controller)) { - $reflection = new \ReflectionMethod($controller[0], $controller[1]); - } elseif (\is_object($controller) && !$controller instanceof \Closure) { - $reflection = (new \ReflectionObject($controller))->getMethod('__invoke'); - } else { - $reflection = new \ReflectionFunction($controller); - } - - foreach ($reflection->getParameters() as $param) { - $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param, $reflection), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull()); - } - - return $arguments; - } - - /** - * Returns an associated type to the given parameter if available. - */ - private function getType(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $function): ?string - { - if (!$type = $parameter->getType()) { - return null; - } - $name = $type->getName(); - - if ($function instanceof \ReflectionMethod) { - $lcName = strtolower($name); - switch ($lcName) { - case 'self': - return $function->getDeclaringClass()->name; - case 'parent': - return ($parent = $function->getDeclaringClass()->getParentClass()) ? $parent->name : null; - } - } - - return $name; - } -} diff --git a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php deleted file mode 100644 index 6ea179d..0000000 --- a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\ControllerMetadata; - -/** - * Builds method argument data. - * - * @author Iltar van der Berg - */ -interface ArgumentMetadataFactoryInterface -{ - /** - * @param mixed $controller The controller to resolve the arguments for - * - * @return ArgumentMetadata[] - */ - public function createArgumentMetadata($controller); -} diff --git a/vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.php b/vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.php deleted file mode 100644 index 7b38ed5..0000000 --- a/vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * AjaxDataCollector. - * - * @author Bart van den Burg - * - * @final - */ -class AjaxDataCollector extends DataCollector -{ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - // all collecting is done client side - } - - public function reset() - { - // all collecting is done client side - } - - public function getName() - { - return 'ajax'; - } -} diff --git a/vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php b/vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php deleted file mode 100644 index 1e435cd..0000000 --- a/vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php +++ /dev/null @@ -1,306 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Kernel; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\VarDumper\Caster\ClassStub; - -/** - * @author Fabien Potencier - * - * @final - */ -class ConfigDataCollector extends DataCollector implements LateDataCollectorInterface -{ - /** - * @var KernelInterface - */ - private $kernel; - - /** - * Sets the Kernel associated with this Request. - */ - public function setKernel(KernelInterface $kernel = null) - { - $this->kernel = $kernel; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - $this->data = [ - 'token' => $response->headers->get('X-Debug-Token'), - 'symfony_version' => Kernel::VERSION, - 'symfony_state' => 'unknown', - 'env' => isset($this->kernel) ? $this->kernel->getEnvironment() : 'n/a', - 'debug' => isset($this->kernel) ? $this->kernel->isDebug() : 'n/a', - 'php_version' => PHP_VERSION, - 'php_architecture' => PHP_INT_SIZE * 8, - 'php_intl_locale' => class_exists('Locale', false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a', - 'php_timezone' => date_default_timezone_get(), - 'xdebug_enabled' => \extension_loaded('xdebug'), - 'apcu_enabled' => \extension_loaded('apcu') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN), - 'zend_opcache_enabled' => \extension_loaded('Zend OPcache') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN), - 'bundles' => [], - 'sapi_name' => \PHP_SAPI, - ]; - - if (isset($this->kernel)) { - foreach ($this->kernel->getBundles() as $name => $bundle) { - $this->data['bundles'][$name] = new ClassStub(\get_class($bundle)); - } - - $this->data['symfony_state'] = $this->determineSymfonyState(); - $this->data['symfony_minor_version'] = sprintf('%s.%s', Kernel::MAJOR_VERSION, Kernel::MINOR_VERSION); - $this->data['symfony_lts'] = 4 === Kernel::MINOR_VERSION; - $eom = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_MAINTENANCE); - $eol = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_LIFE); - $this->data['symfony_eom'] = $eom->format('F Y'); - $this->data['symfony_eol'] = $eol->format('F Y'); - } - - if (preg_match('~^(\d+(?:\.\d+)*)(.+)?$~', $this->data['php_version'], $matches) && isset($matches[2])) { - $this->data['php_version'] = $matches[1]; - $this->data['php_version_extra'] = $matches[2]; - } - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $this->data = []; - } - - public function lateCollect() - { - $this->data = $this->cloneVar($this->data); - } - - /** - * Gets the token. - * - * @return string|null The token - */ - public function getToken() - { - return $this->data['token']; - } - - /** - * Gets the Symfony version. - * - * @return string The Symfony version - */ - public function getSymfonyVersion() - { - return $this->data['symfony_version']; - } - - /** - * Returns the state of the current Symfony release. - * - * @return string One of: unknown, dev, stable, eom, eol - */ - public function getSymfonyState() - { - return $this->data['symfony_state']; - } - - /** - * Returns the minor Symfony version used (without patch numbers of extra - * suffix like "RC", "beta", etc.). - * - * @return string - */ - public function getSymfonyMinorVersion() - { - return $this->data['symfony_minor_version']; - } - - /** - * Returns if the current Symfony version is a Long-Term Support one. - */ - public function isSymfonyLts(): bool - { - return $this->data['symfony_lts']; - } - - /** - * Returns the human redable date when this Symfony version ends its - * maintenance period. - * - * @return string - */ - public function getSymfonyEom() - { - return $this->data['symfony_eom']; - } - - /** - * Returns the human redable date when this Symfony version reaches its - * "end of life" and won't receive bugs or security fixes. - * - * @return string - */ - public function getSymfonyEol() - { - return $this->data['symfony_eol']; - } - - /** - * Gets the PHP version. - * - * @return string The PHP version - */ - public function getPhpVersion() - { - return $this->data['php_version']; - } - - /** - * Gets the PHP version extra part. - * - * @return string|null The extra part - */ - public function getPhpVersionExtra() - { - return isset($this->data['php_version_extra']) ? $this->data['php_version_extra'] : null; - } - - /** - * @return int The PHP architecture as number of bits (e.g. 32 or 64) - */ - public function getPhpArchitecture() - { - return $this->data['php_architecture']; - } - - /** - * @return string - */ - public function getPhpIntlLocale() - { - return $this->data['php_intl_locale']; - } - - /** - * @return string - */ - public function getPhpTimezone() - { - return $this->data['php_timezone']; - } - - /** - * Gets the environment. - * - * @return string The environment - */ - public function getEnv() - { - return $this->data['env']; - } - - /** - * Returns true if the debug is enabled. - * - * @return bool true if debug is enabled, false otherwise - */ - public function isDebug() - { - return $this->data['debug']; - } - - /** - * Returns true if the XDebug is enabled. - * - * @return bool true if XDebug is enabled, false otherwise - */ - public function hasXDebug() - { - return $this->data['xdebug_enabled']; - } - - /** - * Returns true if APCu is enabled. - * - * @return bool true if APCu is enabled, false otherwise - */ - public function hasApcu() - { - return $this->data['apcu_enabled']; - } - - /** - * Returns true if Zend OPcache is enabled. - * - * @return bool true if Zend OPcache is enabled, false otherwise - */ - public function hasZendOpcache() - { - return $this->data['zend_opcache_enabled']; - } - - public function getBundles() - { - return $this->data['bundles']; - } - - /** - * Gets the PHP SAPI name. - * - * @return string The environment - */ - public function getSapiName() - { - return $this->data['sapi_name']; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'config'; - } - - /** - * Tries to retrieve information about the current Symfony version. - * - * @return string One of: dev, stable, eom, eol - */ - private function determineSymfonyState(): string - { - $now = new \DateTime(); - $eom = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_MAINTENANCE)->modify('last day of this month'); - $eol = \DateTime::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_LIFE)->modify('last day of this month'); - - if ($now > $eol) { - $versionState = 'eol'; - } elseif ($now > $eom) { - $versionState = 'eom'; - } elseif ('' !== Kernel::EXTRA_VERSION) { - $versionState = 'dev'; - } else { - $versionState = 'stable'; - } - - return $versionState; - } -} diff --git a/vendor/symfony/http-kernel/DataCollector/DataCollector.php b/vendor/symfony/http-kernel/DataCollector/DataCollector.php deleted file mode 100644 index ccaf66d..0000000 --- a/vendor/symfony/http-kernel/DataCollector/DataCollector.php +++ /dev/null @@ -1,112 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\VarDumper\Caster\CutStub; -use Symfony\Component\VarDumper\Caster\ReflectionCaster; -use Symfony\Component\VarDumper\Cloner\ClonerInterface; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Cloner\Stub; -use Symfony\Component\VarDumper\Cloner\VarCloner; - -/** - * DataCollector. - * - * Children of this class must store the collected data in the data property. - * - * @author Fabien Potencier - * @author Bernhard Schussek - */ -abstract class DataCollector implements DataCollectorInterface -{ - /** - * @var array|Data - */ - protected $data = []; - - /** - * @var ClonerInterface - */ - private $cloner; - - /** - * Converts the variable into a serializable Data instance. - * - * This array can be displayed in the template using - * the VarDumper component. - * - * @param mixed $var - * - * @return Data - */ - protected function cloneVar($var) - { - if ($var instanceof Data) { - return $var; - } - if (null === $this->cloner) { - $this->cloner = new VarCloner(); - $this->cloner->setMaxItems(-1); - $this->cloner->addCasters($this->getCasters()); - } - - return $this->cloner->cloneVar($var); - } - - /** - * @return callable[] The casters to add to the cloner - */ - protected function getCasters() - { - $casters = [ - '*' => function ($v, array $a, Stub $s, $isNested) { - if (!$v instanceof Stub) { - foreach ($a as $k => $v) { - if (\is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) { - $a[$k] = new CutStub($v); - } - } - } - - return $a; - }, - ] + ReflectionCaster::UNSET_CLOSURE_FILE_INFO; - - return $casters; - } - - /** - * @return array - */ - public function __sleep() - { - return ['data']; - } - - public function __wakeup() - { - } - - /** - * @internal to prevent implementing \Serializable - */ - final protected function serialize() - { - } - - /** - * @internal to prevent implementing \Serializable - */ - final protected function unserialize($data) - { - } -} diff --git a/vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php b/vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php deleted file mode 100644 index 30ab7cc..0000000 --- a/vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Contracts\Service\ResetInterface; - -/** - * DataCollectorInterface. - * - * @author Fabien Potencier - */ -interface DataCollectorInterface extends ResetInterface -{ - /** - * Collects data for the given Request and Response. - */ - public function collect(Request $request, Response $response, \Throwable $exception = null); - - /** - * Returns the name of the collector. - * - * @return string The collector name - */ - public function getName(); -} diff --git a/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php b/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php deleted file mode 100644 index b3288b5..0000000 --- a/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php +++ /dev/null @@ -1,290 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Stopwatch\Stopwatch; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Cloner\VarCloner; -use Symfony\Component\VarDumper\Dumper\CliDumper; -use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; -use Symfony\Component\VarDumper\Dumper\DataDumperInterface; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; -use Symfony\Component\VarDumper\Server\Connection; - -/** - * @author Nicolas Grekas - * - * @final - */ -class DumpDataCollector extends DataCollector implements DataDumperInterface -{ - private $stopwatch; - private $fileLinkFormat; - private $dataCount = 0; - private $isCollected = true; - private $clonesCount = 0; - private $clonesIndex = 0; - private $rootRefs; - private $charset; - private $requestStack; - private $dumper; - private $sourceContextProvider; - - /** - * @param DataDumperInterface|Connection|null $dumper - */ - public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, string $charset = null, RequestStack $requestStack = null, $dumper = null) - { - $this->stopwatch = $stopwatch; - $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); - $this->charset = $charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8'; - $this->requestStack = $requestStack; - $this->dumper = $dumper; - - // All clones share these properties by reference: - $this->rootRefs = [ - &$this->data, - &$this->dataCount, - &$this->isCollected, - &$this->clonesCount, - ]; - - $this->sourceContextProvider = $dumper instanceof Connection && isset($dumper->getContextProviders()['source']) ? $dumper->getContextProviders()['source'] : new SourceContextProvider($this->charset); - } - - public function __clone() - { - $this->clonesIndex = ++$this->clonesCount; - } - - public function dump(Data $data) - { - if ($this->stopwatch) { - $this->stopwatch->start('dump'); - } - - list('name' => $name, 'file' => $file, 'line' => $line, 'file_excerpt' => $fileExcerpt) = $this->sourceContextProvider->getContext(); - - if ($this->dumper instanceof Connection) { - if (!$this->dumper->write($data)) { - $this->isCollected = false; - } - } elseif ($this->dumper) { - $this->doDump($this->dumper, $data, $name, $file, $line); - } else { - $this->isCollected = false; - } - - if (!$this->dataCount) { - $this->data = []; - } - $this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt'); - ++$this->dataCount; - - if ($this->stopwatch) { - $this->stopwatch->stop('dump'); - } - } - - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - if (!$this->dataCount) { - $this->data = []; - } - - // Sub-requests and programmatic calls stay in the collected profile. - if ($this->dumper || ($this->requestStack && $this->requestStack->getMasterRequest() !== $request) || $request->isXmlHttpRequest() || $request->headers->has('Origin')) { - return; - } - - // In all other conditions that remove the web debug toolbar, dumps are written on the output. - if (!$this->requestStack - || !$response->headers->has('X-Debug-Token') - || $response->isRedirection() - || ($response->headers->has('Content-Type') && false === strpos($response->headers->get('Content-Type'), 'html')) - || 'html' !== $request->getRequestFormat() - || false === strripos($response->getContent(), '') - ) { - if ($response->headers->has('Content-Type') && false !== strpos($response->headers->get('Content-Type'), 'html')) { - $dumper = new HtmlDumper('php://output', $this->charset); - $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); - } else { - $dumper = new CliDumper('php://output', $this->charset); - if (method_exists($dumper, 'setDisplayOptions')) { - $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); - } - } - - foreach ($this->data as $dump) { - $this->doDump($dumper, $dump['data'], $dump['name'], $dump['file'], $dump['line']); - } - } - } - - public function reset() - { - if ($this->stopwatch) { - $this->stopwatch->reset(); - } - $this->data = []; - $this->dataCount = 0; - $this->isCollected = true; - $this->clonesCount = 0; - $this->clonesIndex = 0; - } - - /** - * @internal - */ - public function __sleep(): array - { - if (!$this->dataCount) { - $this->data = []; - } - - if ($this->clonesCount !== $this->clonesIndex) { - return []; - } - - $this->data[] = $this->fileLinkFormat; - $this->data[] = $this->charset; - $this->dataCount = 0; - $this->isCollected = true; - - return parent::__sleep(); - } - - /** - * @internal - */ - public function __wakeup() - { - parent::__wakeup(); - - $charset = array_pop($this->data); - $fileLinkFormat = array_pop($this->data); - $this->dataCount = \count($this->data); - - self::__construct($this->stopwatch, $fileLinkFormat, $charset); - } - - public function getDumpsCount(): int - { - return $this->dataCount; - } - - public function getDumps($format, $maxDepthLimit = -1, $maxItemsPerDepth = -1): array - { - $data = fopen('php://memory', 'r+b'); - - if ('html' === $format) { - $dumper = new HtmlDumper($data, $this->charset); - $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); - } else { - throw new \InvalidArgumentException(sprintf('Invalid dump format: %s', $format)); - } - $dumps = []; - - if (!$this->dataCount) { - return $this->data = []; - } - - foreach ($this->data as $dump) { - $dumper->dump($dump['data']->withMaxDepth($maxDepthLimit)->withMaxItemsPerDepth($maxItemsPerDepth)); - $dump['data'] = stream_get_contents($data, -1, 0); - ftruncate($data, 0); - rewind($data); - $dumps[] = $dump; - } - - return $dumps; - } - - public function getName(): string - { - return 'dump'; - } - - public function __destruct() - { - if (0 === $this->clonesCount-- && !$this->isCollected && $this->dataCount) { - $this->clonesCount = 0; - $this->isCollected = true; - - $h = headers_list(); - $i = \count($h); - array_unshift($h, 'Content-Type: '.ini_get('default_mimetype')); - while (0 !== stripos($h[$i], 'Content-Type:')) { - --$i; - } - - if (isset($_SERVER['VAR_DUMPER_FORMAT'])) { - $html = 'html' === $_SERVER['VAR_DUMPER_FORMAT']; - } else { - $html = !\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && stripos($h[$i], 'html'); - } - - if ($html) { - $dumper = new HtmlDumper('php://output', $this->charset); - $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); - } else { - $dumper = new CliDumper('php://output', $this->charset); - if (method_exists($dumper, 'setDisplayOptions')) { - $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); - } - } - - foreach ($this->data as $i => $dump) { - $this->data[$i] = null; - $this->doDump($dumper, $dump['data'], $dump['name'], $dump['file'], $dump['line']); - } - - $this->data = []; - $this->dataCount = 0; - } - } - - private function doDump(DataDumperInterface $dumper, $data, string $name, string $file, int $line) - { - if ($dumper instanceof CliDumper) { - $contextDumper = function ($name, $file, $line, $fmt) { - if ($this instanceof HtmlDumper) { - if ($file) { - $s = $this->style('meta', '%s'); - $f = strip_tags($this->style('', $file)); - $name = strip_tags($this->style('', $name)); - if ($fmt && $link = \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line)) { - $name = sprintf(''.$s.'', strip_tags($this->style('', $link)), $f, $name); - } else { - $name = sprintf(''.$s.'', $f, $name); - } - } else { - $name = $this->style('meta', $name); - } - $this->line = $name.' on line '.$this->style('meta', $line).':'; - } else { - $this->line = $this->style('meta', $name).' on line '.$this->style('meta', $line).':'; - } - $this->dumpLine(0); - }; - $contextDumper = $contextDumper->bindTo($dumper, $dumper); - $contextDumper($name, $file, $line, $this->fileLinkFormat); - } else { - $cloner = new VarCloner(); - $dumper->dump($cloner->cloneVar($name.' on line '.$line.':')); - } - $dumper->dump($data); - } -} diff --git a/vendor/symfony/http-kernel/DataCollector/EventDataCollector.php b/vendor/symfony/http-kernel/DataCollector/EventDataCollector.php deleted file mode 100644 index 27930fe..0000000 --- a/vendor/symfony/http-kernel/DataCollector/EventDataCollector.php +++ /dev/null @@ -1,150 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * EventDataCollector. - * - * @author Fabien Potencier - * - * @final - */ -class EventDataCollector extends DataCollector implements LateDataCollectorInterface -{ - protected $dispatcher; - private $requestStack; - private $currentRequest; - - public function __construct(EventDispatcherInterface $dispatcher = null, RequestStack $requestStack = null) - { - $this->dispatcher = $dispatcher; - $this->requestStack = $requestStack; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - $this->currentRequest = $this->requestStack && $this->requestStack->getMasterRequest() !== $request ? $request : null; - $this->data = [ - 'called_listeners' => [], - 'not_called_listeners' => [], - 'orphaned_events' => [], - ]; - } - - public function reset() - { - $this->data = []; - - if ($this->dispatcher instanceof ResetInterface) { - $this->dispatcher->reset(); - } - } - - public function lateCollect() - { - if ($this->dispatcher instanceof TraceableEventDispatcher) { - $this->setCalledListeners($this->dispatcher->getCalledListeners($this->currentRequest)); - $this->setNotCalledListeners($this->dispatcher->getNotCalledListeners($this->currentRequest)); - $this->setOrphanedEvents($this->dispatcher->getOrphanedEvents($this->currentRequest)); - } - - $this->data = $this->cloneVar($this->data); - } - - /** - * Sets the called listeners. - * - * @param array $listeners An array of called listeners - * - * @see TraceableEventDispatcher - */ - public function setCalledListeners(array $listeners) - { - $this->data['called_listeners'] = $listeners; - } - - /** - * Gets the called listeners. - * - * @return array An array of called listeners - * - * @see TraceableEventDispatcher - */ - public function getCalledListeners() - { - return $this->data['called_listeners']; - } - - /** - * Sets the not called listeners. - * - * @see TraceableEventDispatcher - */ - public function setNotCalledListeners(array $listeners) - { - $this->data['not_called_listeners'] = $listeners; - } - - /** - * Gets the not called listeners. - * - * @return array - * - * @see TraceableEventDispatcher - */ - public function getNotCalledListeners() - { - return $this->data['not_called_listeners']; - } - - /** - * Sets the orphaned events. - * - * @param array $events An array of orphaned events - * - * @see TraceableEventDispatcher - */ - public function setOrphanedEvents(array $events) - { - $this->data['orphaned_events'] = $events; - } - - /** - * Gets the orphaned events. - * - * @return array An array of orphaned events - * - * @see TraceableEventDispatcher - */ - public function getOrphanedEvents() - { - return $this->data['orphaned_events']; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'events'; - } -} diff --git a/vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php b/vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php deleted file mode 100644 index 5ff13f7..0000000 --- a/vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php +++ /dev/null @@ -1,114 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * ExceptionDataCollector. - * - * @author Fabien Potencier - * - * @final - */ -class ExceptionDataCollector extends DataCollector -{ - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - if (null !== $exception) { - $this->data = [ - 'exception' => FlattenException::createFromThrowable($exception), - ]; - } - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $this->data = []; - } - - /** - * Checks if the exception is not null. - * - * @return bool true if the exception is not null, false otherwise - */ - public function hasException() - { - return isset($this->data['exception']); - } - - /** - * Gets the exception. - * - * @return \Exception|FlattenException - */ - public function getException() - { - return $this->data['exception']; - } - - /** - * Gets the exception message. - * - * @return string The exception message - */ - public function getMessage() - { - return $this->data['exception']->getMessage(); - } - - /** - * Gets the exception code. - * - * @return int The exception code - */ - public function getCode() - { - return $this->data['exception']->getCode(); - } - - /** - * Gets the status code. - * - * @return int The status code - */ - public function getStatusCode() - { - return $this->data['exception']->getStatusCode(); - } - - /** - * Gets the exception trace. - * - * @return array The exception trace - */ - public function getTrace() - { - return $this->data['exception']->getTrace(); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'exception'; - } -} diff --git a/vendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php b/vendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php deleted file mode 100644 index 012332d..0000000 --- a/vendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -/** - * LateDataCollectorInterface. - * - * @author Fabien Potencier - */ -interface LateDataCollectorInterface -{ - /** - * Collects data as late as possible. - */ - public function lateCollect(); -} diff --git a/vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php b/vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php deleted file mode 100644 index f8dc885..0000000 --- a/vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php +++ /dev/null @@ -1,282 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; - -/** - * LogDataCollector. - * - * @author Fabien Potencier - * - * @final - */ -class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface -{ - private $logger; - private $containerPathPrefix; - private $currentRequest; - private $requestStack; - - public function __construct($logger = null, string $containerPathPrefix = null, RequestStack $requestStack = null) - { - if (null !== $logger && $logger instanceof DebugLoggerInterface) { - $this->logger = $logger; - } - - $this->containerPathPrefix = $containerPathPrefix; - $this->requestStack = $requestStack; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - $this->currentRequest = $this->requestStack && $this->requestStack->getMasterRequest() !== $request ? $request : null; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - if ($this->logger instanceof DebugLoggerInterface) { - $this->logger->clear(); - } - $this->data = []; - } - - /** - * {@inheritdoc} - */ - public function lateCollect() - { - if (null !== $this->logger) { - $containerDeprecationLogs = $this->getContainerDeprecationLogs(); - $this->data = $this->computeErrorsCount($containerDeprecationLogs); - // get compiler logs later (only when they are needed) to improve performance - $this->data['compiler_logs'] = []; - $this->data['compiler_logs_filepath'] = $this->containerPathPrefix.'Compiler.log'; - $this->data['logs'] = $this->sanitizeLogs(array_merge($this->logger->getLogs($this->currentRequest), $containerDeprecationLogs)); - $this->data = $this->cloneVar($this->data); - } - $this->currentRequest = null; - } - - public function getLogs() - { - return isset($this->data['logs']) ? $this->data['logs'] : []; - } - - public function getPriorities() - { - return isset($this->data['priorities']) ? $this->data['priorities'] : []; - } - - public function countErrors() - { - return isset($this->data['error_count']) ? $this->data['error_count'] : 0; - } - - public function countDeprecations() - { - return isset($this->data['deprecation_count']) ? $this->data['deprecation_count'] : 0; - } - - public function countWarnings() - { - return isset($this->data['warning_count']) ? $this->data['warning_count'] : 0; - } - - public function countScreams() - { - return isset($this->data['scream_count']) ? $this->data['scream_count'] : 0; - } - - public function getCompilerLogs() - { - return $this->cloneVar($this->getContainerCompilerLogs($this->data['compiler_logs_filepath'] ?? null)); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'logger'; - } - - private function getContainerDeprecationLogs(): array - { - if (null === $this->containerPathPrefix || !file_exists($file = $this->containerPathPrefix.'Deprecations.log')) { - return []; - } - - if ('' === $logContent = trim(file_get_contents($file))) { - return []; - } - - $bootTime = filemtime($file); - $logs = []; - foreach (unserialize($logContent) as $log) { - $log['context'] = ['exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'], $log['trace'], $log['count'])]; - $log['timestamp'] = $bootTime; - $log['priority'] = 100; - $log['priorityName'] = 'DEBUG'; - $log['channel'] = null; - $log['scream'] = false; - unset($log['type'], $log['file'], $log['line'], $log['trace'], $log['trace'], $log['count']); - $logs[] = $log; - } - - return $logs; - } - - private function getContainerCompilerLogs(string $compilerLogsFilepath = null): array - { - if (!file_exists($compilerLogsFilepath)) { - return []; - } - - $logs = []; - foreach (file($compilerLogsFilepath, FILE_IGNORE_NEW_LINES) as $log) { - $log = explode(': ', $log, 2); - if (!isset($log[1]) || !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $log[0])) { - $log = ['Unknown Compiler Pass', implode(': ', $log)]; - } - - $logs[$log[0]][] = ['message' => $log[1]]; - } - - return $logs; - } - - private function sanitizeLogs(array $logs) - { - $sanitizedLogs = []; - $silencedLogs = []; - - foreach ($logs as $log) { - if (!$this->isSilencedOrDeprecationErrorLog($log)) { - $sanitizedLogs[] = $log; - - continue; - } - - $message = $log['message']; - $exception = $log['context']['exception']; - - if ($exception instanceof SilencedErrorContext) { - if (isset($silencedLogs[$h = spl_object_hash($exception)])) { - continue; - } - $silencedLogs[$h] = true; - - if (!isset($sanitizedLogs[$message])) { - $sanitizedLogs[$message] = $log + [ - 'errorCount' => 0, - 'scream' => true, - ]; - } - $sanitizedLogs[$message]['errorCount'] += $exception->count; - - continue; - } - - $errorId = md5("{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}\0{$message}", true); - - if (isset($sanitizedLogs[$errorId])) { - ++$sanitizedLogs[$errorId]['errorCount']; - } else { - $log += [ - 'errorCount' => 1, - 'scream' => false, - ]; - - $sanitizedLogs[$errorId] = $log; - } - } - - return array_values($sanitizedLogs); - } - - private function isSilencedOrDeprecationErrorLog(array $log): bool - { - if (!isset($log['context']['exception'])) { - return false; - } - - $exception = $log['context']['exception']; - - if ($exception instanceof SilencedErrorContext) { - return true; - } - - if ($exception instanceof \ErrorException && \in_array($exception->getSeverity(), [E_DEPRECATED, E_USER_DEPRECATED], true)) { - return true; - } - - return false; - } - - private function computeErrorsCount(array $containerDeprecationLogs): array - { - $silencedLogs = []; - $count = [ - 'error_count' => $this->logger->countErrors($this->currentRequest), - 'deprecation_count' => 0, - 'warning_count' => 0, - 'scream_count' => 0, - 'priorities' => [], - ]; - - foreach ($this->logger->getLogs($this->currentRequest) as $log) { - if (isset($count['priorities'][$log['priority']])) { - ++$count['priorities'][$log['priority']]['count']; - } else { - $count['priorities'][$log['priority']] = [ - 'count' => 1, - 'name' => $log['priorityName'], - ]; - } - if ('WARNING' === $log['priorityName']) { - ++$count['warning_count']; - } - - if ($this->isSilencedOrDeprecationErrorLog($log)) { - $exception = $log['context']['exception']; - if ($exception instanceof SilencedErrorContext) { - if (isset($silencedLogs[$h = spl_object_hash($exception)])) { - continue; - } - $silencedLogs[$h] = true; - $count['scream_count'] += $exception->count; - } else { - ++$count['deprecation_count']; - } - } - } - - foreach ($containerDeprecationLogs as $deprecationLog) { - $count['deprecation_count'] += $deprecationLog['context']['exception']->count; - } - - ksort($count['priorities']); - - return $count; - } -} diff --git a/vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php b/vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php deleted file mode 100644 index 3730212..0000000 --- a/vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php +++ /dev/null @@ -1,125 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * MemoryDataCollector. - * - * @author Fabien Potencier - * - * @final - */ -class MemoryDataCollector extends DataCollector implements LateDataCollectorInterface -{ - public function __construct() - { - $this->reset(); - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - $this->updateMemoryUsage(); - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $this->data = [ - 'memory' => 0, - 'memory_limit' => $this->convertToBytes(ini_get('memory_limit')), - ]; - } - - /** - * {@inheritdoc} - */ - public function lateCollect() - { - $this->updateMemoryUsage(); - } - - /** - * Gets the memory. - * - * @return int The memory - */ - public function getMemory() - { - return $this->data['memory']; - } - - /** - * Gets the PHP memory limit. - * - * @return int The memory limit - */ - public function getMemoryLimit() - { - return $this->data['memory_limit']; - } - - /** - * Updates the memory usage data. - */ - public function updateMemoryUsage() - { - $this->data['memory'] = memory_get_peak_usage(true); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'memory'; - } - - /** - * @return int|float - */ - private function convertToBytes(string $memoryLimit) - { - if ('-1' === $memoryLimit) { - return -1; - } - - $memoryLimit = strtolower($memoryLimit); - $max = strtolower(ltrim($memoryLimit, '+')); - if (0 === strpos($max, '0x')) { - $max = \intval($max, 16); - } elseif (0 === strpos($max, '0')) { - $max = \intval($max, 8); - } else { - $max = (int) $max; - } - - switch (substr($memoryLimit, -1)) { - case 't': $max *= 1024; - // no break - case 'g': $max *= 1024; - // no break - case 'm': $max *= 1024; - // no break - case 'k': $max *= 1024; - } - - return $max; - } -} diff --git a/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php b/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php deleted file mode 100644 index 9585c13..0000000 --- a/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php +++ /dev/null @@ -1,458 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpFoundation\ParameterBag; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\ControllerEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * @author Fabien Potencier - * - * @final - */ -class RequestDataCollector extends DataCollector implements EventSubscriberInterface, LateDataCollectorInterface -{ - protected $controllers; - - public function __construct() - { - $this->controllers = new \SplObjectStorage(); - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - // attributes are serialized and as they can be anything, they need to be converted to strings. - $attributes = []; - $route = ''; - foreach ($request->attributes->all() as $key => $value) { - if ('_route' === $key) { - $route = \is_object($value) ? $value->getPath() : $value; - $attributes[$key] = $route; - } else { - $attributes[$key] = $value; - } - } - - try { - $content = $request->getContent(); - } catch (\LogicException $e) { - // the user already got the request content as a resource - $content = false; - } - - $sessionMetadata = []; - $sessionAttributes = []; - $flashes = []; - if ($request->hasSession()) { - $session = $request->getSession(); - if ($session->isStarted()) { - $sessionMetadata['Created'] = date(DATE_RFC822, $session->getMetadataBag()->getCreated()); - $sessionMetadata['Last used'] = date(DATE_RFC822, $session->getMetadataBag()->getLastUsed()); - $sessionMetadata['Lifetime'] = $session->getMetadataBag()->getLifetime(); - $sessionAttributes = $session->all(); - $flashes = $session->getFlashBag()->peekAll(); - } - } - - $statusCode = $response->getStatusCode(); - - $responseCookies = []; - foreach ($response->headers->getCookies() as $cookie) { - $responseCookies[$cookie->getName()] = $cookie; - } - - $dotenvVars = []; - foreach (explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? $_ENV['SYMFONY_DOTENV_VARS'] ?? '') as $name) { - if ('' !== $name && isset($_ENV[$name])) { - $dotenvVars[$name] = $_ENV[$name]; - } - } - - $this->data = [ - 'method' => $request->getMethod(), - 'format' => $request->getRequestFormat(), - 'content' => $content, - 'content_type' => $response->headers->get('Content-Type', 'text/html'), - 'status_text' => isset(Response::$statusTexts[$statusCode]) ? Response::$statusTexts[$statusCode] : '', - 'status_code' => $statusCode, - 'request_query' => $request->query->all(), - 'request_request' => $request->request->all(), - 'request_files' => $request->files->all(), - 'request_headers' => $request->headers->all(), - 'request_server' => $request->server->all(), - 'request_cookies' => $request->cookies->all(), - 'request_attributes' => $attributes, - 'route' => $route, - 'response_headers' => $response->headers->all(), - 'response_cookies' => $responseCookies, - 'session_metadata' => $sessionMetadata, - 'session_attributes' => $sessionAttributes, - 'flashes' => $flashes, - 'path_info' => $request->getPathInfo(), - 'controller' => 'n/a', - 'locale' => $request->getLocale(), - 'dotenv_vars' => $dotenvVars, - ]; - - if (isset($this->data['request_headers']['php-auth-pw'])) { - $this->data['request_headers']['php-auth-pw'] = '******'; - } - - if (isset($this->data['request_server']['PHP_AUTH_PW'])) { - $this->data['request_server']['PHP_AUTH_PW'] = '******'; - } - - if (isset($this->data['request_request']['_password'])) { - $this->data['request_request']['_password'] = '******'; - } - - foreach ($this->data as $key => $value) { - if (!\is_array($value)) { - continue; - } - if ('request_headers' === $key || 'response_headers' === $key) { - $this->data[$key] = array_map(function ($v) { return isset($v[0]) && !isset($v[1]) ? $v[0] : $v; }, $value); - } - } - - if (isset($this->controllers[$request])) { - $this->data['controller'] = $this->parseController($this->controllers[$request]); - unset($this->controllers[$request]); - } - - if ($request->attributes->has('_redirected') && $redirectCookie = $request->cookies->get('sf_redirect')) { - $this->data['redirect'] = json_decode($redirectCookie, true); - - $response->headers->clearCookie('sf_redirect'); - } - - if ($response->isRedirect()) { - $response->headers->setCookie(new Cookie( - 'sf_redirect', - json_encode([ - 'token' => $response->headers->get('x-debug-token'), - 'route' => $request->attributes->get('_route', 'n/a'), - 'method' => $request->getMethod(), - 'controller' => $this->parseController($request->attributes->get('_controller')), - 'status_code' => $statusCode, - 'status_text' => Response::$statusTexts[(int) $statusCode], - ]), - 0, '/', null, $request->isSecure(), true, false, 'lax' - )); - } - - $this->data['identifier'] = $this->data['route'] ?: (\is_array($this->data['controller']) ? $this->data['controller']['class'].'::'.$this->data['controller']['method'].'()' : $this->data['controller']); - - if ($response->headers->has('x-previous-debug-token')) { - $this->data['forward_token'] = $response->headers->get('x-previous-debug-token'); - } - } - - public function lateCollect() - { - $this->data = $this->cloneVar($this->data); - } - - public function reset() - { - $this->data = []; - $this->controllers = new \SplObjectStorage(); - } - - public function getMethod() - { - return $this->data['method']; - } - - public function getPathInfo() - { - return $this->data['path_info']; - } - - public function getRequestRequest() - { - return new ParameterBag($this->data['request_request']->getValue()); - } - - public function getRequestQuery() - { - return new ParameterBag($this->data['request_query']->getValue()); - } - - public function getRequestFiles() - { - return new ParameterBag($this->data['request_files']->getValue()); - } - - public function getRequestHeaders() - { - return new ParameterBag($this->data['request_headers']->getValue()); - } - - public function getRequestServer($raw = false) - { - return new ParameterBag($this->data['request_server']->getValue($raw)); - } - - public function getRequestCookies($raw = false) - { - return new ParameterBag($this->data['request_cookies']->getValue($raw)); - } - - public function getRequestAttributes() - { - return new ParameterBag($this->data['request_attributes']->getValue()); - } - - public function getResponseHeaders() - { - return new ParameterBag($this->data['response_headers']->getValue()); - } - - public function getResponseCookies() - { - return new ParameterBag($this->data['response_cookies']->getValue()); - } - - public function getSessionMetadata() - { - return $this->data['session_metadata']->getValue(); - } - - public function getSessionAttributes() - { - return $this->data['session_attributes']->getValue(); - } - - public function getFlashes() - { - return $this->data['flashes']->getValue(); - } - - public function getContent() - { - return $this->data['content']; - } - - public function isJsonRequest() - { - return 1 === preg_match('{^application/(?:\w+\++)*json$}i', $this->data['request_headers']['content-type']); - } - - public function getPrettyJson() - { - $decoded = json_decode($this->getContent()); - - return JSON_ERROR_NONE === json_last_error() ? json_encode($decoded, JSON_PRETTY_PRINT) : null; - } - - public function getContentType() - { - return $this->data['content_type']; - } - - public function getStatusText() - { - return $this->data['status_text']; - } - - public function getStatusCode() - { - return $this->data['status_code']; - } - - public function getFormat() - { - return $this->data['format']; - } - - public function getLocale() - { - return $this->data['locale']; - } - - public function getDotenvVars() - { - return new ParameterBag($this->data['dotenv_vars']->getValue()); - } - - /** - * Gets the route name. - * - * The _route request attributes is automatically set by the Router Matcher. - * - * @return string The route - */ - public function getRoute() - { - return $this->data['route']; - } - - public function getIdentifier() - { - return $this->data['identifier']; - } - - /** - * Gets the route parameters. - * - * The _route_params request attributes is automatically set by the RouterListener. - * - * @return array The parameters - */ - public function getRouteParams() - { - return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params']->getValue() : []; - } - - /** - * Gets the parsed controller. - * - * @return array|string The controller as a string or array of data - * with keys 'class', 'method', 'file' and 'line' - */ - public function getController() - { - return $this->data['controller']; - } - - /** - * Gets the previous request attributes. - * - * @return array|bool A legacy array of data from the previous redirection response - * or false otherwise - */ - public function getRedirect() - { - return isset($this->data['redirect']) ? $this->data['redirect'] : false; - } - - public function getForwardToken() - { - return isset($this->data['forward_token']) ? $this->data['forward_token'] : null; - } - - public function onKernelController(ControllerEvent $event) - { - $this->controllers[$event->getRequest()] = $event->getController(); - } - - public function onKernelResponse(ResponseEvent $event) - { - if (!$event->isMasterRequest()) { - return; - } - - if ($event->getRequest()->cookies->has('sf_redirect')) { - $event->getRequest()->attributes->set('_redirected', true); - } - } - - public static function getSubscribedEvents() - { - return [ - KernelEvents::CONTROLLER => 'onKernelController', - KernelEvents::RESPONSE => 'onKernelResponse', - ]; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'request'; - } - - /** - * Parse a controller. - * - * @param mixed $controller The controller to parse - * - * @return array|string An array of controller data or a simple string - */ - protected function parseController($controller) - { - if (\is_string($controller) && false !== strpos($controller, '::')) { - $controller = explode('::', $controller); - } - - if (\is_array($controller)) { - try { - $r = new \ReflectionMethod($controller[0], $controller[1]); - - return [ - 'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0], - 'method' => $controller[1], - 'file' => $r->getFileName(), - 'line' => $r->getStartLine(), - ]; - } catch (\ReflectionException $e) { - if (\is_callable($controller)) { - // using __call or __callStatic - return [ - 'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0], - 'method' => $controller[1], - 'file' => 'n/a', - 'line' => 'n/a', - ]; - } - } - } - - if ($controller instanceof \Closure) { - $r = new \ReflectionFunction($controller); - - $controller = [ - 'class' => $r->getName(), - 'method' => null, - 'file' => $r->getFileName(), - 'line' => $r->getStartLine(), - ]; - - if (false !== strpos($r->name, '{closure}')) { - return $controller; - } - $controller['method'] = $r->name; - - if ($class = $r->getClosureScopeClass()) { - $controller['class'] = $class->name; - } else { - return $r->name; - } - - return $controller; - } - - if (\is_object($controller)) { - $r = new \ReflectionClass($controller); - - return [ - 'class' => $r->getName(), - 'method' => null, - 'file' => $r->getFileName(), - 'line' => $r->getStartLine(), - ]; - } - - return \is_string($controller) ? $controller : 'n/a'; - } -} diff --git a/vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php b/vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php deleted file mode 100644 index 5ed6970..0000000 --- a/vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php +++ /dev/null @@ -1,108 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\RedirectResponse; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\ControllerEvent; - -/** - * @author Fabien Potencier - */ -class RouterDataCollector extends DataCollector -{ - /** - * @var \SplObjectStorage - */ - protected $controllers; - - public function __construct() - { - $this->reset(); - } - - /** - * {@inheritdoc} - * - * @final - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - if ($response instanceof RedirectResponse) { - $this->data['redirect'] = true; - $this->data['url'] = $response->getTargetUrl(); - - if ($this->controllers->contains($request)) { - $this->data['route'] = $this->guessRoute($request, $this->controllers[$request]); - } - } - - unset($this->controllers[$request]); - } - - public function reset() - { - $this->controllers = new \SplObjectStorage(); - - $this->data = [ - 'redirect' => false, - 'url' => null, - 'route' => null, - ]; - } - - protected function guessRoute(Request $request, $controller) - { - return 'n/a'; - } - - /** - * Remembers the controller associated to each request. - */ - public function onKernelController(ControllerEvent $event) - { - $this->controllers[$event->getRequest()] = $event->getController(); - } - - /** - * @return bool Whether this request will result in a redirect - */ - public function getRedirect() - { - return $this->data['redirect']; - } - - /** - * @return string|null The target URL - */ - public function getTargetUrl() - { - return $this->data['url']; - } - - /** - * @return string|null The target route - */ - public function getTargetRoute() - { - return $this->data['route']; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'router'; - } -} diff --git a/vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php b/vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php deleted file mode 100644 index 4e95603..0000000 --- a/vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php +++ /dev/null @@ -1,159 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\Stopwatch\Stopwatch; -use Symfony\Component\Stopwatch\StopwatchEvent; - -/** - * @author Fabien Potencier - * - * @final - */ -class TimeDataCollector extends DataCollector implements LateDataCollectorInterface -{ - protected $kernel; - protected $stopwatch; - - public function __construct(KernelInterface $kernel = null, Stopwatch $stopwatch = null) - { - $this->kernel = $kernel; - $this->stopwatch = $stopwatch; - } - - /** - * {@inheritdoc} - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - if (null !== $this->kernel) { - $startTime = $this->kernel->getStartTime(); - } else { - $startTime = $request->server->get('REQUEST_TIME_FLOAT'); - } - - $this->data = [ - 'token' => $response->headers->get('X-Debug-Token'), - 'start_time' => $startTime * 1000, - 'events' => [], - 'stopwatch_installed' => class_exists(Stopwatch::class, false), - ]; - } - - /** - * {@inheritdoc} - */ - public function reset() - { - $this->data = []; - - if (null !== $this->stopwatch) { - $this->stopwatch->reset(); - } - } - - /** - * {@inheritdoc} - */ - public function lateCollect() - { - if (null !== $this->stopwatch && isset($this->data['token'])) { - $this->setEvents($this->stopwatch->getSectionEvents($this->data['token'])); - } - unset($this->data['token']); - } - - /** - * Sets the request events. - * - * @param StopwatchEvent[] $events The request events - */ - public function setEvents(array $events) - { - foreach ($events as $event) { - $event->ensureStopped(); - } - - $this->data['events'] = $events; - } - - /** - * Gets the request events. - * - * @return StopwatchEvent[] The request events - */ - public function getEvents() - { - return $this->data['events']; - } - - /** - * Gets the request elapsed time. - * - * @return float The elapsed time - */ - public function getDuration() - { - if (!isset($this->data['events']['__section__'])) { - return 0; - } - - $lastEvent = $this->data['events']['__section__']; - - return $lastEvent->getOrigin() + $lastEvent->getDuration() - $this->getStartTime(); - } - - /** - * Gets the initialization time. - * - * This is the time spent until the beginning of the request handling. - * - * @return float The elapsed time - */ - public function getInitTime() - { - if (!isset($this->data['events']['__section__'])) { - return 0; - } - - return $this->data['events']['__section__']->getOrigin() - $this->getStartTime(); - } - - /** - * Gets the request time. - * - * @return float - */ - public function getStartTime() - { - return $this->data['start_time']; - } - - /** - * @return bool whether or not the stopwatch component is installed - */ - public function isStopwatchInstalled() - { - return $this->data['stopwatch_installed']; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'time'; - } -} diff --git a/vendor/symfony/http-kernel/Debug/FileLinkFormatter.php b/vendor/symfony/http-kernel/Debug/FileLinkFormatter.php deleted file mode 100644 index 74abb81..0000000 --- a/vendor/symfony/http-kernel/Debug/FileLinkFormatter.php +++ /dev/null @@ -1,106 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Debug; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; - -/** - * Formats debug file links. - * - * @author Jérémy Romey - * - * @final - */ -class FileLinkFormatter -{ - private $fileLinkFormat; - private $requestStack; - private $baseDir; - private $urlFormat; - - /** - * @param string|\Closure $urlFormat the URL format, or a closure that returns it on-demand - */ - public function __construct($fileLinkFormat = null, RequestStack $requestStack = null, string $baseDir = null, $urlFormat = null) - { - $fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); - if ($fileLinkFormat && !\is_array($fileLinkFormat)) { - $i = strpos($f = $fileLinkFormat, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: \strlen($f); - $fileLinkFormat = [substr($f, 0, $i)] + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE); - } - - $this->fileLinkFormat = $fileLinkFormat; - $this->requestStack = $requestStack; - $this->baseDir = $baseDir; - $this->urlFormat = $urlFormat; - } - - public function format(string $file, int $line) - { - if ($fmt = $this->getFileLinkFormat()) { - for ($i = 1; isset($fmt[$i]); ++$i) { - if (0 === strpos($file, $k = $fmt[$i++])) { - $file = substr_replace($file, $fmt[$i], 0, \strlen($k)); - break; - } - } - - return strtr($fmt[0], ['%f' => $file, '%l' => $line]); - } - - return false; - } - - /** - * @internal - */ - public function __sleep(): array - { - $this->fileLinkFormat = $this->getFileLinkFormat(); - - return ['fileLinkFormat']; - } - - /** - * @internal - */ - public static function generateUrlFormat(UrlGeneratorInterface $router, string $routeName, string $queryString): ?string - { - try { - return $router->generate($routeName).$queryString; - } catch (\Throwable $e) { - return null; - } - } - - private function getFileLinkFormat() - { - if ($this->fileLinkFormat) { - return $this->fileLinkFormat; - } - - if ($this->requestStack && $this->baseDir && $this->urlFormat) { - $request = $this->requestStack->getMasterRequest(); - - if ($request instanceof Request && (!$this->urlFormat instanceof \Closure || $this->urlFormat = ($this->urlFormat)())) { - return [ - $request->getSchemeAndHttpHost().$this->urlFormat, - $this->baseDir.\DIRECTORY_SEPARATOR, '', - ]; - } - } - - return null; - } -} diff --git a/vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php b/vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php deleted file mode 100644 index 1ece493..0000000 --- a/vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php +++ /dev/null @@ -1,90 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Debug; - -use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher as BaseTraceableEventDispatcher; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * Collects some data about event listeners. - * - * This event dispatcher delegates the dispatching to another one. - * - * @author Fabien Potencier - */ -class TraceableEventDispatcher extends BaseTraceableEventDispatcher -{ - /** - * {@inheritdoc} - */ - protected function beforeDispatch(string $eventName, object $event) - { - switch ($eventName) { - case KernelEvents::REQUEST: - $this->stopwatch->openSection(); - break; - case KernelEvents::VIEW: - case KernelEvents::RESPONSE: - // stop only if a controller has been executed - if ($this->stopwatch->isStarted('controller')) { - $this->stopwatch->stop('controller'); - } - break; - case KernelEvents::TERMINATE: - $token = $event->getResponse()->headers->get('X-Debug-Token'); - if (null === $token) { - break; - } - // There is a very special case when using built-in AppCache class as kernel wrapper, in the case - // of an ESI request leading to a `stale` response [B] inside a `fresh` cached response [A]. - // In this case, `$token` contains the [B] debug token, but the open `stopwatch` section ID - // is equal to the [A] debug token. Trying to reopen section with the [B] token throws an exception - // which must be caught. - try { - $this->stopwatch->openSection($token); - } catch (\LogicException $e) { - } - break; - } - } - - /** - * {@inheritdoc} - */ - protected function afterDispatch(string $eventName, object $event) - { - switch ($eventName) { - case KernelEvents::CONTROLLER_ARGUMENTS: - $this->stopwatch->start('controller', 'section'); - break; - case KernelEvents::RESPONSE: - $token = $event->getResponse()->headers->get('X-Debug-Token'); - if (null === $token) { - break; - } - $this->stopwatch->stopSection($token); - break; - case KernelEvents::TERMINATE: - // In the special case described in the `preDispatch` method above, the `$token` section - // does not exist, then closing it throws an exception which must be caught. - $token = $event->getResponse()->headers->get('X-Debug-Token'); - if (null === $token) { - break; - } - try { - $this->stopwatch->stopSection($token); - } catch (\LogicException $e) { - } - break; - } - } -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php b/vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php deleted file mode 100644 index 70a987e..0000000 --- a/vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php +++ /dev/null @@ -1,144 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Composer\Autoload\ClassLoader; -use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\ErrorHandler\DebugClassLoader; -use Symfony\Component\HttpKernel\Kernel; - -/** - * Sets the classes to compile in the cache for the container. - * - * @author Fabien Potencier - */ -class AddAnnotatedClassesToCachePass implements CompilerPassInterface -{ - private $kernel; - - public function __construct(Kernel $kernel) - { - $this->kernel = $kernel; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $annotatedClasses = $this->kernel->getAnnotatedClassesToCompile(); - foreach ($container->getExtensions() as $extension) { - if ($extension instanceof Extension) { - $annotatedClasses = array_merge($annotatedClasses, $extension->getAnnotatedClassesToCompile()); - } - } - - $existingClasses = $this->getClassesInComposerClassMaps(); - - $annotatedClasses = $container->getParameterBag()->resolveValue($annotatedClasses); - $this->kernel->setAnnotatedClassCache($this->expandClasses($annotatedClasses, $existingClasses)); - } - - /** - * Expands the given class patterns using a list of existing classes. - * - * @param array $patterns The class patterns to expand - * @param array $classes The existing classes to match against the patterns - */ - private function expandClasses(array $patterns, array $classes): array - { - $expanded = []; - - // Explicit classes declared in the patterns are returned directly - foreach ($patterns as $key => $pattern) { - if ('\\' !== substr($pattern, -1) && false === strpos($pattern, '*')) { - unset($patterns[$key]); - $expanded[] = ltrim($pattern, '\\'); - } - } - - // Match patterns with the classes list - $regexps = $this->patternsToRegexps($patterns); - - foreach ($classes as $class) { - $class = ltrim($class, '\\'); - - if ($this->matchAnyRegexps($class, $regexps)) { - $expanded[] = $class; - } - } - - return array_unique($expanded); - } - - private function getClassesInComposerClassMaps(): array - { - $classes = []; - - foreach (spl_autoload_functions() as $function) { - if (!\is_array($function)) { - continue; - } - - if ($function[0] instanceof DebugClassLoader || $function[0] instanceof LegacyDebugClassLoader) { - $function = $function[0]->getClassLoader(); - } - - if (\is_array($function) && $function[0] instanceof ClassLoader) { - $classes += array_filter($function[0]->getClassMap()); - } - } - - return array_keys($classes); - } - - private function patternsToRegexps(array $patterns): array - { - $regexps = []; - - foreach ($patterns as $pattern) { - // Escape user input - $regex = preg_quote(ltrim($pattern, '\\')); - - // Wildcards * and ** - $regex = strtr($regex, ['\\*\\*' => '.*?', '\\*' => '[^\\\\]*?']); - - // If this class does not end by a slash, anchor the end - if ('\\' !== substr($regex, -1)) { - $regex .= '$'; - } - - $regexps[] = '{^\\\\'.$regex.'}'; - } - - return $regexps; - } - - private function matchAnyRegexps(string $class, array $regexps): bool - { - $blacklisted = false !== strpos($class, 'Test'); - - foreach ($regexps as $regex) { - if ($blacklisted && false === strpos($regex, 'Test')) { - continue; - } - - if (preg_match($regex, '\\'.$class)) { - return true; - } - } - - return false; - } -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php b/vendor/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php deleted file mode 100644 index 072c35f..0000000 --- a/vendor/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * This extension sub-class provides first-class integration with the - * Config/Definition Component. - * - * You can use this as base class if - * - * a) you use the Config/Definition component for configuration, - * b) your configuration class is named "Configuration", and - * c) the configuration class resides in the DependencyInjection sub-folder. - * - * @author Johannes M. Schmitt - */ -abstract class ConfigurableExtension extends Extension -{ - /** - * {@inheritdoc} - */ - final public function load(array $configs, ContainerBuilder $container) - { - $this->loadInternal($this->processConfiguration($this->getConfiguration($configs, $container), $configs), $container); - } - - /** - * Configures the passed container according to the merged configuration. - */ - abstract protected function loadInternal(array $mergedConfig, ContainerBuilder $container); -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php b/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php deleted file mode 100644 index 705c88d..0000000 --- a/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver; -use Symfony\Component\Stopwatch\Stopwatch; - -/** - * Gathers and configures the argument value resolvers. - * - * @author Iltar van der Berg - */ -class ControllerArgumentValueResolverPass implements CompilerPassInterface -{ - use PriorityTaggedServiceTrait; - - private $argumentResolverService; - private $argumentValueResolverTag; - private $traceableResolverStopwatch; - - public function __construct(string $argumentResolverService = 'argument_resolver', string $argumentValueResolverTag = 'controller.argument_value_resolver', string $traceableResolverStopwatch = 'debug.stopwatch') - { - $this->argumentResolverService = $argumentResolverService; - $this->argumentValueResolverTag = $argumentValueResolverTag; - $this->traceableResolverStopwatch = $traceableResolverStopwatch; - } - - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->argumentResolverService)) { - return; - } - - $resolvers = $this->findAndSortTaggedServices($this->argumentValueResolverTag, $container); - - if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class) && $container->has($this->traceableResolverStopwatch)) { - foreach ($resolvers as $resolverReference) { - $id = (string) $resolverReference; - $container->register("debug.$id", TraceableValueResolver::class) - ->setDecoratedService($id) - ->setArguments([new Reference("debug.$id.inner"), new Reference($this->traceableResolverStopwatch)]); - } - } - - $container - ->getDefinition($this->argumentResolverService) - ->replaceArgument(1, new IteratorArgument($resolvers)) - ; - } -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/Extension.php b/vendor/symfony/http-kernel/DependencyInjection/Extension.php deleted file mode 100644 index db376e6..0000000 --- a/vendor/symfony/http-kernel/DependencyInjection/Extension.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Extension\Extension as BaseExtension; - -/** - * Allow adding classes to the class cache. - * - * @author Fabien Potencier - */ -abstract class Extension extends BaseExtension -{ - private $annotatedClasses = []; - - /** - * Gets the annotated classes to cache. - * - * @return array An array of classes - */ - public function getAnnotatedClassesToCompile() - { - return $this->annotatedClasses; - } - - /** - * Adds annotated classes to the class cache. - * - * @param array $annotatedClasses An array of class patterns - */ - public function addAnnotatedClassesToCompile(array $annotatedClasses) - { - $this->annotatedClasses = array_merge($this->annotatedClasses, $annotatedClasses); - } -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php b/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php deleted file mode 100644 index 432f767..0000000 --- a/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface; - -/** - * Adds services tagged kernel.fragment_renderer as HTTP content rendering strategies. - * - * @author Fabien Potencier - */ -class FragmentRendererPass implements CompilerPassInterface -{ - private $handlerService; - private $rendererTag; - - public function __construct(string $handlerService = 'fragment.handler', string $rendererTag = 'kernel.fragment_renderer') - { - $this->handlerService = $handlerService; - $this->rendererTag = $rendererTag; - } - - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->handlerService)) { - return; - } - - $definition = $container->getDefinition($this->handlerService); - $renderers = []; - foreach ($container->findTaggedServiceIds($this->rendererTag, true) as $id => $tags) { - $def = $container->getDefinition($id); - $class = $container->getParameterBag()->resolveValue($def->getClass()); - - if (!$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } - if (!$r->isSubclassOf(FragmentRendererInterface::class)) { - throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, FragmentRendererInterface::class)); - } - - foreach ($tags as $tag) { - $renderers[$tag['alias']] = new Reference($id); - } - } - - $definition->replaceArgument(0, ServiceLocatorTagPass::register($container, $renderers)); - } -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php b/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php deleted file mode 100644 index 2ee6737..0000000 --- a/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpKernel\Fragment\FragmentHandler; - -/** - * Lazily loads fragment renderers from the dependency injection container. - * - * @author Fabien Potencier - */ -class LazyLoadingFragmentHandler extends FragmentHandler -{ - private $container; - private $initialized = []; - - public function __construct(ContainerInterface $container, RequestStack $requestStack, bool $debug = false) - { - $this->container = $container; - - parent::__construct($requestStack, [], $debug); - } - - /** - * {@inheritdoc} - */ - public function render($uri, string $renderer = 'inline', array $options = []) - { - if (!isset($this->initialized[$renderer]) && $this->container->has($renderer)) { - $this->addRenderer($this->container->get($renderer)); - $this->initialized[$renderer] = true; - } - - return parent::render($uri, $renderer, $options); - } -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php b/vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php deleted file mode 100644 index b6df1f6..0000000 --- a/vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Psr\Log\LoggerInterface; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\HttpKernel\Log\Logger; - -/** - * Registers the default logger if necessary. - * - * @author Kévin Dunglas - */ -class LoggerPass implements CompilerPassInterface -{ - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $container->setAlias(LoggerInterface::class, 'logger') - ->setPublic(false); - - if ($container->has('logger')) { - return; - } - - $container->register('logger', Logger::class) - ->setPublic(false); - } -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php b/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php deleted file mode 100644 index 83e1b75..0000000 --- a/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass as BaseMergeExtensionConfigurationPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Ensures certain extensions are always loaded. - * - * @author Kris Wallsmith - */ -class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPass -{ - private $extensions; - - public function __construct(array $extensions) - { - $this->extensions = $extensions; - } - - public function process(ContainerBuilder $container) - { - foreach ($this->extensions as $extension) { - if (!\count($container->getExtensionConfig($extension))) { - $container->loadFromExtension($extension, []); - } - } - - parent::process($container); - } -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php deleted file mode 100644 index a3f5012..0000000 --- a/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ /dev/null @@ -1,200 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\TypedReference; -use Symfony\Component\HttpFoundation\Request; - -/** - * Creates the service-locators required by ServiceValueResolver. - * - * @author Nicolas Grekas - */ -class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface -{ - private $resolverServiceId; - private $controllerTag; - private $controllerLocator; - private $notTaggedControllerResolverServiceId; - - public function __construct(string $resolverServiceId = 'argument_resolver.service', string $controllerTag = 'controller.service_arguments', string $controllerLocator = 'argument_resolver.controller_locator', string $notTaggedControllerResolverServiceId = 'argument_resolver.not_tagged_controller') - { - $this->resolverServiceId = $resolverServiceId; - $this->controllerTag = $controllerTag; - $this->controllerLocator = $controllerLocator; - $this->notTaggedControllerResolverServiceId = $notTaggedControllerResolverServiceId; - } - - public function process(ContainerBuilder $container) - { - if (false === $container->hasDefinition($this->resolverServiceId) && false === $container->hasDefinition($this->notTaggedControllerResolverServiceId)) { - return; - } - - $parameterBag = $container->getParameterBag(); - $controllers = []; - - foreach ($container->findTaggedServiceIds($this->controllerTag, true) as $id => $tags) { - $def = $container->getDefinition($id); - $def->setPublic(true); - $class = $def->getClass(); - $autowire = $def->isAutowired(); - $bindings = $def->getBindings(); - - // resolve service class, taking parent definitions into account - while ($def instanceof ChildDefinition) { - $def = $container->findDefinition($def->getParent()); - $class = $class ?: $def->getClass(); - $bindings += $def->getBindings(); - } - $class = $parameterBag->resolveValue($class); - - if (!$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } - $isContainerAware = $r->implementsInterface(ContainerAwareInterface::class) || is_subclass_of($class, AbstractController::class); - - // get regular public methods - $methods = []; - $arguments = []; - foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $r) { - if ('setContainer' === $r->name && $isContainerAware) { - continue; - } - if (!$r->isConstructor() && !$r->isDestructor() && !$r->isAbstract()) { - $methods[strtolower($r->name)] = [$r, $r->getParameters()]; - } - } - - // validate and collect explicit per-actions and per-arguments service references - foreach ($tags as $attributes) { - if (!isset($attributes['action']) && !isset($attributes['argument']) && !isset($attributes['id'])) { - $autowire = true; - continue; - } - foreach (['action', 'argument', 'id'] as $k) { - if (!isset($attributes[$k][0])) { - throw new InvalidArgumentException(sprintf('Missing "%s" attribute on tag "%s" %s for service "%s".', $k, $this->controllerTag, json_encode($attributes, JSON_UNESCAPED_UNICODE), $id)); - } - } - if (!isset($methods[$action = strtolower($attributes['action'])])) { - throw new InvalidArgumentException(sprintf('Invalid "action" attribute on tag "%s" for service "%s": no public "%s()" method found on class "%s".', $this->controllerTag, $id, $attributes['action'], $class)); - } - list($r, $parameters) = $methods[$action]; - $found = false; - - foreach ($parameters as $p) { - if ($attributes['argument'] === $p->name) { - if (!isset($arguments[$r->name][$p->name])) { - $arguments[$r->name][$p->name] = $attributes['id']; - } - $found = true; - break; - } - } - - if (!$found) { - throw new InvalidArgumentException(sprintf('Invalid "%s" tag for service "%s": method "%s()" has no "%s" argument on class "%s".', $this->controllerTag, $id, $r->name, $attributes['argument'], $class)); - } - } - - foreach ($methods as list($r, $parameters)) { - /** @var \ReflectionMethod $r */ - - // create a per-method map of argument-names to service/type-references - $args = []; - foreach ($parameters as $p) { - /** @var \ReflectionParameter $p */ - $type = ltrim($target = ProxyHelper::getTypeHint($r, $p), '\\'); - $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - - if (isset($arguments[$r->name][$p->name])) { - $target = $arguments[$r->name][$p->name]; - if ('?' !== $target[0]) { - $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE; - } elseif ('' === $target = (string) substr($target, 1)) { - throw new InvalidArgumentException(sprintf('A "%s" tag must have non-empty "id" attributes for service "%s".', $this->controllerTag, $id)); - } elseif ($p->allowsNull() && !$p->isOptional()) { - $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; - } - } elseif (isset($bindings[$bindingName = $type.' $'.$p->name]) || isset($bindings[$bindingName = '$'.$p->name]) || isset($bindings[$bindingName = $type])) { - $binding = $bindings[$bindingName]; - - list($bindingValue, $bindingId, , $bindingType, $bindingFile) = $binding->getValues(); - $binding->setValues([$bindingValue, $bindingId, true, $bindingType, $bindingFile]); - - if (!$bindingValue instanceof Reference) { - $args[$p->name] = new Reference('.value.'.$container->hash($bindingValue)); - $container->register((string) $args[$p->name], 'mixed') - ->setFactory('current') - ->addArgument([$bindingValue]); - } else { - $args[$p->name] = $bindingValue; - } - - continue; - } elseif (!$type || !$autowire || '\\' !== $target[0]) { - continue; - } elseif (!$p->allowsNull()) { - $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE; - } - - if (Request::class === $type) { - continue; - } - - if ($type && !$p->isOptional() && !$p->allowsNull() && !class_exists($type) && !interface_exists($type, false)) { - $message = sprintf('Cannot determine controller argument for "%s::%s()": the $%s argument is type-hinted with the non-existent class or interface: "%s".', $class, $r->name, $p->name, $type); - - // see if the type-hint lives in the same namespace as the controller - if (0 === strncmp($type, $class, strrpos($class, '\\'))) { - $message .= ' Did you forget to add a use statement?'; - } - - throw new InvalidArgumentException($message); - } - - $target = ltrim($target, '\\'); - $args[$p->name] = $type ? new TypedReference($target, $type, $invalidBehavior, $p->name) : new Reference($target, $invalidBehavior); - } - // register the maps as a per-method service-locators - if ($args) { - $controllers[$id.'::'.$r->name] = ServiceLocatorTagPass::register($container, $args); - } - } - } - - $controllerLocatorRef = ServiceLocatorTagPass::register($container, $controllers); - - if ($container->hasDefinition($this->resolverServiceId)) { - $container->getDefinition($this->resolverServiceId) - ->replaceArgument(0, $controllerLocatorRef); - } - - if ($container->hasDefinition($this->notTaggedControllerResolverServiceId)) { - $container->getDefinition($this->notTaggedControllerResolverServiceId) - ->replaceArgument(0, $controllerLocatorRef); - } - - $container->setAlias($this->controllerLocator, (string) $controllerLocatorRef); - } -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php b/vendor/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php deleted file mode 100644 index 0efb164..0000000 --- a/vendor/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Register all services that have the "kernel.locale_aware" tag into the listener. - * - * @author Pierre Bobiet - */ -class RegisterLocaleAwareServicesPass implements CompilerPassInterface -{ - private $listenerServiceId; - private $localeAwareTag; - - public function __construct(string $listenerServiceId = 'locale_aware_listener', string $localeAwareTag = 'kernel.locale_aware') - { - $this->listenerServiceId = $listenerServiceId; - $this->localeAwareTag = $localeAwareTag; - } - - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->listenerServiceId)) { - return; - } - - $services = []; - - foreach ($container->findTaggedServiceIds($this->localeAwareTag) as $id => $tags) { - $services[] = new Reference($id); - } - - if (!$services) { - $container->removeDefinition($this->listenerServiceId); - - return; - } - - $container - ->getDefinition($this->listenerServiceId) - ->setArgument(0, new IteratorArgument($services)) - ; - } -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php b/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php deleted file mode 100644 index 596b618..0000000 --- a/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php +++ /dev/null @@ -1,70 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Removes empty service-locators registered for ServiceValueResolver. - * - * @author Nicolas Grekas - */ -class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface -{ - private $controllerLocator; - - public function __construct(string $controllerLocator = 'argument_resolver.controller_locator') - { - $this->controllerLocator = $controllerLocator; - } - - public function process(ContainerBuilder $container) - { - $controllerLocator = $container->findDefinition($this->controllerLocator); - $controllers = $controllerLocator->getArgument(0); - - foreach ($controllers as $controller => $argumentRef) { - $argumentLocator = $container->getDefinition((string) $argumentRef->getValues()[0]); - - if (!$argumentLocator->getArgument(0)) { - // remove empty argument locators - $reason = sprintf('Removing service-argument resolver for controller "%s": no corresponding services exist for the referenced types.', $controller); - } else { - // any methods listed for call-at-instantiation cannot be actions - $reason = false; - list($id, $action) = explode('::', $controller); - $controllerDef = $container->getDefinition($id); - foreach ($controllerDef->getMethodCalls() as list($method)) { - if (0 === strcasecmp($action, $method)) { - $reason = sprintf('Removing method "%s" of service "%s" from controller candidates: the method is called at instantiation, thus cannot be an action.', $action, $id); - break; - } - } - if (!$reason) { - // Deprecated since Symfony 4.1. See Symfony\Component\HttpKernel\Controller\ContainerControllerResolver - $controllers[$id.':'.$action] = $argumentRef; - - if ('__invoke' === $action) { - $controllers[$id] = $argumentRef; - } - continue; - } - } - - unset($controllers[$controller]); - $container->log($this, $reason); - } - - $controllerLocator->replaceArgument(0, $controllers); - } -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php b/vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php deleted file mode 100644 index b5e4610..0000000 --- a/vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php +++ /dev/null @@ -1,71 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Alexander M. Turek - */ -class ResettableServicePass implements CompilerPassInterface -{ - private $tagName; - - public function __construct(string $tagName = 'kernel.reset') - { - $this->tagName = $tagName; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->has('services_resetter')) { - return; - } - - $services = $methods = []; - - foreach ($container->findTaggedServiceIds($this->tagName, true) as $id => $tags) { - $services[$id] = new Reference($id, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE); - - foreach ($tags as $attributes) { - if (!isset($attributes['method'])) { - throw new RuntimeException(sprintf('Tag "%s" requires the "method" attribute to be set.', $this->tagName)); - } - - if (!isset($methods[$id])) { - $methods[$id] = []; - } - - $methods[$id][] = $attributes['method']; - } - } - - if (!$services) { - $container->removeAlias('services_resetter'); - $container->removeDefinition('services_resetter'); - - return; - } - - $container->findDefinition('services_resetter') - ->setArgument(0, new IteratorArgument($services)) - ->setArgument(1, $methods); - } -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php b/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php deleted file mode 100644 index d9e0028..0000000 --- a/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Contracts\Service\ResetInterface; - -/** - * Resets provided services. - * - * @author Alexander M. Turek - * @author Nicolas Grekas - * - * @internal - */ -class ServicesResetter implements ResetInterface -{ - private $resettableServices; - private $resetMethods; - - public function __construct(\Traversable $resettableServices, array $resetMethods) - { - $this->resettableServices = $resettableServices; - $this->resetMethods = $resetMethods; - } - - public function reset() - { - foreach ($this->resettableServices as $id => $service) { - foreach ((array) $this->resetMethods[$id] as $resetMethod) { - $service->$resetMethod(); - } - } - } -} diff --git a/vendor/symfony/http-kernel/Event/ControllerArgumentsEvent.php b/vendor/symfony/http-kernel/Event/ControllerArgumentsEvent.php deleted file mode 100644 index d075ee9..0000000 --- a/vendor/symfony/http-kernel/Event/ControllerArgumentsEvent.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Allows filtering of controller arguments. - * - * You can call getController() to retrieve the controller and getArguments - * to retrieve the current arguments. With setArguments() you can replace - * arguments that are used to call the controller. - * - * Arguments set in the event must be compatible with the signature of the - * controller. - * - * @author Christophe Coevoet - */ -final class ControllerArgumentsEvent extends KernelEvent -{ - private $controller; - private $arguments; - - public function __construct(HttpKernelInterface $kernel, callable $controller, array $arguments, Request $request, ?int $requestType) - { - parent::__construct($kernel, $request, $requestType); - - $this->controller = $controller; - $this->arguments = $arguments; - } - - public function getController(): callable - { - return $this->controller; - } - - public function setController(callable $controller) - { - $this->controller = $controller; - } - - public function getArguments(): array - { - return $this->arguments; - } - - public function setArguments(array $arguments) - { - $this->arguments = $arguments; - } -} diff --git a/vendor/symfony/http-kernel/Event/ControllerEvent.php b/vendor/symfony/http-kernel/Event/ControllerEvent.php deleted file mode 100644 index da88800..0000000 --- a/vendor/symfony/http-kernel/Event/ControllerEvent.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Allows filtering of a controller callable. - * - * You can call getController() to retrieve the current controller. With - * setController() you can set a new controller that is used in the processing - * of the request. - * - * Controllers should be callables. - * - * @author Bernhard Schussek - */ -final class ControllerEvent extends KernelEvent -{ - private $controller; - - public function __construct(HttpKernelInterface $kernel, callable $controller, Request $request, ?int $requestType) - { - parent::__construct($kernel, $request, $requestType); - - $this->setController($controller); - } - - public function getController(): callable - { - return $this->controller; - } - - public function setController(callable $controller): void - { - $this->controller = $controller; - } -} diff --git a/vendor/symfony/http-kernel/Event/ExceptionEvent.php b/vendor/symfony/http-kernel/Event/ExceptionEvent.php deleted file mode 100644 index a10741a..0000000 --- a/vendor/symfony/http-kernel/Event/ExceptionEvent.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Allows to create a response for a thrown exception. - * - * Call setResponse() to set the response that will be returned for the - * current request. The propagation of this event is stopped as soon as a - * response is set. - * - * You can also call setException() to replace the thrown exception. This - * exception will be thrown if no response is set during processing of this - * event. - * - * @author Bernhard Schussek - */ -final class ExceptionEvent extends RequestEvent -{ - private $throwable; - - /** - * @var bool - */ - private $allowCustomResponseCode = false; - - public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, \Throwable $e) - { - parent::__construct($kernel, $request, $requestType); - - $this->setThrowable($e); - } - - public function getThrowable(): \Throwable - { - return $this->throwable; - } - - /** - * Replaces the thrown exception. - * - * This exception will be thrown if no response is set in the event. - */ - public function setThrowable(\Throwable $exception): void - { - $this->throwable = $exception; - } - - /** - * Mark the event as allowing a custom response code. - */ - public function allowCustomResponseCode(): void - { - $this->allowCustomResponseCode = true; - } - - /** - * Returns true if the event allows a custom response code. - */ - public function isAllowingCustomResponseCode(): bool - { - return $this->allowCustomResponseCode; - } -} diff --git a/vendor/symfony/http-kernel/Event/FinishRequestEvent.php b/vendor/symfony/http-kernel/Event/FinishRequestEvent.php deleted file mode 100644 index 306a7ad..0000000 --- a/vendor/symfony/http-kernel/Event/FinishRequestEvent.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -/** - * Triggered whenever a request is fully processed. - * - * @author Benjamin Eberlei - */ -final class FinishRequestEvent extends KernelEvent -{ -} diff --git a/vendor/symfony/http-kernel/Event/KernelEvent.php b/vendor/symfony/http-kernel/Event/KernelEvent.php deleted file mode 100644 index 08558d5..0000000 --- a/vendor/symfony/http-kernel/Event/KernelEvent.php +++ /dev/null @@ -1,80 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Contracts\EventDispatcher\Event; - -/** - * Base class for events thrown in the HttpKernel component. - * - * @author Bernhard Schussek - */ -class KernelEvent extends Event -{ - private $kernel; - private $request; - private $requestType; - - /** - * @param int $requestType The request type the kernel is currently processing; one of - * HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST - */ - public function __construct(HttpKernelInterface $kernel, Request $request, ?int $requestType) - { - $this->kernel = $kernel; - $this->request = $request; - $this->requestType = $requestType; - } - - /** - * Returns the kernel in which this event was thrown. - * - * @return HttpKernelInterface - */ - public function getKernel() - { - return $this->kernel; - } - - /** - * Returns the request the kernel is currently processing. - * - * @return Request - */ - public function getRequest() - { - return $this->request; - } - - /** - * Returns the request type the kernel is currently processing. - * - * @return int One of HttpKernelInterface::MASTER_REQUEST and - * HttpKernelInterface::SUB_REQUEST - */ - public function getRequestType() - { - return $this->requestType; - } - - /** - * Checks if this is a master request. - * - * @return bool True if the request is a master request - */ - public function isMasterRequest() - { - return HttpKernelInterface::MASTER_REQUEST === $this->requestType; - } -} diff --git a/vendor/symfony/http-kernel/Event/RequestEvent.php b/vendor/symfony/http-kernel/Event/RequestEvent.php deleted file mode 100644 index 0b2b98e..0000000 --- a/vendor/symfony/http-kernel/Event/RequestEvent.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Response; - -/** - * Allows to create a response for a request. - * - * Call setResponse() to set the response that will be returned for the - * current request. The propagation of this event is stopped as soon as a - * response is set. - * - * @author Bernhard Schussek - */ -class RequestEvent extends KernelEvent -{ - private $response; - - /** - * Returns the response object. - * - * @return Response|null - */ - public function getResponse() - { - return $this->response; - } - - /** - * Sets a response and stops event propagation. - */ - public function setResponse(Response $response) - { - $this->response = $response; - - $this->stopPropagation(); - } - - /** - * Returns whether a response was set. - * - * @return bool Whether a response was set - */ - public function hasResponse() - { - return null !== $this->response; - } -} diff --git a/vendor/symfony/http-kernel/Event/ResponseEvent.php b/vendor/symfony/http-kernel/Event/ResponseEvent.php deleted file mode 100644 index 1e56ebe..0000000 --- a/vendor/symfony/http-kernel/Event/ResponseEvent.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Allows to filter a Response object. - * - * You can call getResponse() to retrieve the current response. With - * setResponse() you can set a new response that will be returned to the - * browser. - * - * @author Bernhard Schussek - */ -final class ResponseEvent extends KernelEvent -{ - private $response; - - public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, Response $response) - { - parent::__construct($kernel, $request, $requestType); - - $this->setResponse($response); - } - - public function getResponse(): Response - { - return $this->response; - } - - public function setResponse(Response $response): void - { - $this->response = $response; - } -} diff --git a/vendor/symfony/http-kernel/Event/TerminateEvent.php b/vendor/symfony/http-kernel/Event/TerminateEvent.php deleted file mode 100644 index e0002fb..0000000 --- a/vendor/symfony/http-kernel/Event/TerminateEvent.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Allows to execute logic after a response was sent. - * - * Since it's only triggered on master requests, the `getRequestType()` method - * will always return the value of `HttpKernelInterface::MASTER_REQUEST`. - * - * @author Jordi Boggiano - */ -final class TerminateEvent extends KernelEvent -{ - private $response; - - public function __construct(HttpKernelInterface $kernel, Request $request, Response $response) - { - parent::__construct($kernel, $request, HttpKernelInterface::MASTER_REQUEST); - - $this->response = $response; - } - - public function getResponse(): Response - { - return $this->response; - } -} diff --git a/vendor/symfony/http-kernel/Event/ViewEvent.php b/vendor/symfony/http-kernel/Event/ViewEvent.php deleted file mode 100644 index 66a4cea..0000000 --- a/vendor/symfony/http-kernel/Event/ViewEvent.php +++ /dev/null @@ -1,61 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Allows to create a response for the return value of a controller. - * - * Call setResponse() to set the response that will be returned for the - * current request. The propagation of this event is stopped as soon as a - * response is set. - * - * @author Bernhard Schussek - */ -final class ViewEvent extends RequestEvent -{ - /** - * The return value of the controller. - * - * @var mixed - */ - private $controllerResult; - - public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, $controllerResult) - { - parent::__construct($kernel, $request, $requestType); - - $this->controllerResult = $controllerResult; - } - - /** - * Returns the return value of the controller. - * - * @return mixed The controller return value - */ - public function getControllerResult() - { - return $this->controllerResult; - } - - /** - * Assigns the return value of the controller. - * - * @param mixed $controllerResult The controller return value - */ - public function setControllerResult($controllerResult): void - { - $this->controllerResult = $controllerResult; - } -} diff --git a/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php b/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php deleted file mode 100644 index 9c9c422..0000000 --- a/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php +++ /dev/null @@ -1,148 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Psr\Container\ContainerInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * Sets the session onto the request on the "kernel.request" event and saves - * it on the "kernel.response" event. - * - * In addition, if the session has been started it overrides the Cache-Control - * header in such a way that all caching is disabled in that case. - * If you have a scenario where caching responses with session information in - * them makes sense, you can disable this behaviour by setting the header - * AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER on the response. - * - * @author Johannes M. Schmitt - * @author Tobias Schultze - * - * @internal - */ -abstract class AbstractSessionListener implements EventSubscriberInterface -{ - const NO_AUTO_CACHE_CONTROL_HEADER = 'Symfony-Session-NoAutoCacheControl'; - - protected $container; - private $sessionUsageStack = []; - - public function __construct(ContainerInterface $container = null) - { - $this->container = $container; - } - - public function onKernelRequest(RequestEvent $event) - { - if (!$event->isMasterRequest()) { - return; - } - - $session = null; - $request = $event->getRequest(); - if ($request->hasSession()) { - // no-op - } elseif (method_exists($request, 'setSessionFactory')) { - $request->setSessionFactory(function () { return $this->getSession(); }); - } elseif ($session = $this->getSession()) { - $request->setSession($session); - } - - $session = $session ?? ($this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : null); - $this->sessionUsageStack[] = $session instanceof Session ? $session->getUsageIndex() : 0; - } - - public function onKernelResponse(ResponseEvent $event) - { - if (!$event->isMasterRequest()) { - return; - } - - $response = $event->getResponse(); - $autoCacheControl = !$response->headers->has(self::NO_AUTO_CACHE_CONTROL_HEADER); - // Always remove the internal header if present - $response->headers->remove(self::NO_AUTO_CACHE_CONTROL_HEADER); - - if (!$session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : $event->getRequest()->getSession()) { - return; - } - - if ($session instanceof Session ? $session->getUsageIndex() !== end($this->sessionUsageStack) : $session->isStarted()) { - if ($autoCacheControl) { - $response - ->setExpires(new \DateTime()) - ->setPrivate() - ->setMaxAge(0) - ->headers->addCacheControlDirective('must-revalidate'); - } - } - - if ($session->isStarted()) { - /* - * Saves the session, in case it is still open, before sending the response/headers. - * - * This ensures several things in case the developer did not save the session explicitly: - * - * * If a session save handler without locking is used, it ensures the data is available - * on the next request, e.g. after a redirect. PHPs auto-save at script end via - * session_register_shutdown is executed after fastcgi_finish_request. So in this case - * the data could be missing the next request because it might not be saved the moment - * the new request is processed. - * * A locking save handler (e.g. the native 'files') circumvents concurrency problems like - * the one above. But by saving the session before long-running things in the terminate event, - * we ensure the session is not blocked longer than needed. - * * When regenerating the session ID no locking is involved in PHPs session design. See - * https://bugs.php.net/61470 for a discussion. So in this case, the session must - * be saved anyway before sending the headers with the new session ID. Otherwise session - * data could get lost again for concurrent requests with the new ID. One result could be - * that you get logged out after just logging in. - * - * This listener should be executed as one of the last listeners, so that previous listeners - * can still operate on the open session. This prevents the overhead of restarting it. - * Listeners after closing the session can still work with the session as usual because - * Symfonys session implementation starts the session on demand. So writing to it after - * it is saved will just restart it. - */ - $session->save(); - } - } - - public function onFinishRequest(FinishRequestEvent $event) - { - if ($event->isMasterRequest()) { - array_pop($this->sessionUsageStack); - } - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => ['onKernelRequest', 128], - // low priority to come after regular response listeners, but higher than StreamedResponseListener - KernelEvents::RESPONSE => ['onKernelResponse', -1000], - KernelEvents::FINISH_REQUEST => ['onFinishRequest'], - ]; - } - - /** - * Gets the session object. - * - * @return SessionInterface|null A SessionInterface instance or null if no session is available - */ - abstract protected function getSession(); -} diff --git a/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php b/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php deleted file mode 100644 index 19d13b8..0000000 --- a/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php +++ /dev/null @@ -1,114 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * TestSessionListener. - * - * Saves session in test environment. - * - * @author Bulat Shakirzyanov - * @author Fabien Potencier - * - * @internal - */ -abstract class AbstractTestSessionListener implements EventSubscriberInterface -{ - private $sessionId; - private $sessionOptions; - - public function __construct(array $sessionOptions = []) - { - $this->sessionOptions = $sessionOptions; - } - - public function onKernelRequest(RequestEvent $event) - { - if (!$event->isMasterRequest()) { - return; - } - - // bootstrap the session - if (!$session = $this->getSession()) { - return; - } - - $cookies = $event->getRequest()->cookies; - - if ($cookies->has($session->getName())) { - $this->sessionId = $cookies->get($session->getName()); - $session->setId($this->sessionId); - } - } - - /** - * Checks if session was initialized and saves if current request is master - * Runs on 'kernel.response' in test environment. - */ - public function onKernelResponse(ResponseEvent $event) - { - if (!$event->isMasterRequest()) { - return; - } - - $request = $event->getRequest(); - if (!$request->hasSession()) { - return; - } - - $session = $request->getSession(); - if ($wasStarted = $session->isStarted()) { - $session->save(); - } - - if ($session instanceof Session ? !$session->isEmpty() || (null !== $this->sessionId && $session->getId() !== $this->sessionId) : $wasStarted) { - $params = session_get_cookie_params() + ['samesite' => null]; - foreach ($this->sessionOptions as $k => $v) { - if (0 === strpos($k, 'cookie_')) { - $params[substr($k, 7)] = $v; - } - } - - foreach ($event->getResponse()->headers->getCookies() as $cookie) { - if ($session->getName() === $cookie->getName() && $params['path'] === $cookie->getPath() && $params['domain'] == $cookie->getDomain()) { - return; - } - } - - $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'], false, $params['samesite'] ?: null)); - $this->sessionId = $session->getId(); - } - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => ['onKernelRequest', 192], - KernelEvents::RESPONSE => ['onKernelResponse', -128], - ]; - } - - /** - * Gets the session object. - * - * @return SessionInterface|null A SessionInterface instance or null if no session is available - */ - abstract protected function getSession(); -} diff --git a/vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php b/vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php deleted file mode 100644 index 9e896ad..0000000 --- a/vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * Adds configured formats to each request. - * - * @author Gildas Quemener - * - * @final - */ -class AddRequestFormatsListener implements EventSubscriberInterface -{ - protected $formats; - - public function __construct(array $formats) - { - $this->formats = $formats; - } - - /** - * Adds request formats. - */ - public function onKernelRequest(RequestEvent $event) - { - $request = $event->getRequest(); - foreach ($this->formats as $format => $mimeTypes) { - $request->setFormat($format, $mimeTypes); - } - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents(): array - { - return [KernelEvents::REQUEST => ['onKernelRequest', 100]]; - } -} diff --git a/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php b/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php deleted file mode 100644 index fbb1f2e..0000000 --- a/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php +++ /dev/null @@ -1,153 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Console\ConsoleEvents; -use Symfony\Component\Console\Event\ConsoleEvent; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\ErrorHandler\ErrorHandler; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Symfony\Component\HttpKernel\Event\KernelEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * Configures errors and exceptions handlers. - * - * @author Nicolas Grekas - * - * @final - */ -class DebugHandlersListener implements EventSubscriberInterface -{ - private $exceptionHandler; - private $logger; - private $levels; - private $throwAt; - private $scream; - private $fileLinkFormat; - private $scope; - private $firstCall = true; - private $hasTerminatedWithException; - - /** - * @param callable|null $exceptionHandler A handler that must support \Throwable instances that will be called on Exception - * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants - * @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value - * @param bool $scream Enables/disables screaming mode, where even silenced errors are logged - * @param string|FileLinkFormatter|null $fileLinkFormat The format for links to source files - * @param bool $scope Enables/disables scoping mode - */ - public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = E_ALL, ?int $throwAt = E_ALL, bool $scream = true, $fileLinkFormat = null, bool $scope = true) - { - $this->exceptionHandler = $exceptionHandler; - $this->logger = $logger; - $this->levels = null === $levels ? E_ALL : $levels; - $this->throwAt = \is_int($throwAt) ? $throwAt : (null === $throwAt ? null : ($throwAt ? E_ALL : null)); - $this->scream = $scream; - $this->fileLinkFormat = $fileLinkFormat; - $this->scope = $scope; - } - - /** - * Configures the error handler. - */ - public function configure(object $event = null) - { - if (!$event instanceof KernelEvent ? !$this->firstCall : !$event->isMasterRequest()) { - return; - } - $this->firstCall = $this->hasTerminatedWithException = false; - - $handler = set_exception_handler('var_dump'); - $handler = \is_array($handler) ? $handler[0] : null; - restore_exception_handler(); - - if ($this->logger || null !== $this->throwAt) { - if ($handler instanceof ErrorHandler) { - if ($this->logger) { - $handler->setDefaultLogger($this->logger, $this->levels); - if (\is_array($this->levels)) { - $levels = 0; - foreach ($this->levels as $type => $log) { - $levels |= $type; - } - } else { - $levels = $this->levels; - } - if ($this->scream) { - $handler->screamAt($levels); - } - if ($this->scope) { - $handler->scopeAt($levels & ~E_USER_DEPRECATED & ~E_DEPRECATED); - } else { - $handler->scopeAt(0, true); - } - $this->logger = $this->levels = null; - } - if (null !== $this->throwAt) { - $handler->throwAt($this->throwAt, true); - } - } - } - if (!$this->exceptionHandler) { - if ($event instanceof KernelEvent) { - if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) { - $request = $event->getRequest(); - $hasRun = &$this->hasTerminatedWithException; - $this->exceptionHandler = static function (\Throwable $e) use ($kernel, $request, &$hasRun) { - if ($hasRun) { - throw $e; - } - - $hasRun = true; - $kernel->terminateWithException($e, $request); - }; - } - } elseif ($event instanceof ConsoleEvent && $app = $event->getCommand()->getApplication()) { - $output = $event->getOutput(); - if ($output instanceof ConsoleOutputInterface) { - $output = $output->getErrorOutput(); - } - $this->exceptionHandler = static function (\Throwable $e) use ($app, $output) { - if (method_exists($app, 'renderThrowable')) { - $app->renderThrowable($e, $output); - } else { - if (!$e instanceof \Exception) { - $e = new FatalThrowableError($e); - } - - $app->renderException($e, $output); - } - }; - } - } - if ($this->exceptionHandler) { - if ($handler instanceof ErrorHandler) { - $handler->setExceptionHandler($this->exceptionHandler); - } - $this->exceptionHandler = null; - } - } - - public static function getSubscribedEvents(): array - { - $events = [KernelEvents::REQUEST => ['configure', 2048]]; - - if ('cli' === \PHP_SAPI && \defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) { - $events[ConsoleEvents::COMMAND] = ['configure', 2048]; - } - - return $events; - } -} diff --git a/vendor/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php b/vendor/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php deleted file mode 100644 index 6607e49..0000000 --- a/vendor/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * Ensures that the application is not indexed by search engines. - * - * @author Gary PEGEOT - */ -class DisallowRobotsIndexingListener implements EventSubscriberInterface -{ - private const HEADER_NAME = 'X-Robots-Tag'; - - public function onResponse(ResponseEvent $event): void - { - if (!$event->getResponse()->headers->has(static::HEADER_NAME)) { - $event->getResponse()->headers->set(static::HEADER_NAME, 'noindex'); - } - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents() - { - return [ - KernelEvents::RESPONSE => ['onResponse', -255], - ]; - } -} diff --git a/vendor/symfony/http-kernel/EventListener/DumpListener.php b/vendor/symfony/http-kernel/EventListener/DumpListener.php deleted file mode 100644 index 30908a4..0000000 --- a/vendor/symfony/http-kernel/EventListener/DumpListener.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\Console\ConsoleEvents; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\VarDumper\Cloner\ClonerInterface; -use Symfony\Component\VarDumper\Dumper\DataDumperInterface; -use Symfony\Component\VarDumper\Server\Connection; -use Symfony\Component\VarDumper\VarDumper; - -/** - * Configures dump() handler. - * - * @author Nicolas Grekas - */ -class DumpListener implements EventSubscriberInterface -{ - private $cloner; - private $dumper; - private $connection; - - public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper, Connection $connection = null) - { - $this->cloner = $cloner; - $this->dumper = $dumper; - $this->connection = $connection; - } - - public function configure() - { - $cloner = $this->cloner; - $dumper = $this->dumper; - $connection = $this->connection; - - VarDumper::setHandler(static function ($var) use ($cloner, $dumper, $connection) { - $data = $cloner->cloneVar($var); - - if (!$connection || !$connection->write($data)) { - $dumper->dump($data); - } - }); - } - - public static function getSubscribedEvents() - { - if (!class_exists(ConsoleEvents::class)) { - return []; - } - - // Register early to have a working dump() as early as possible - return [ConsoleEvents::COMMAND => ['configure', 1024]]; - } -} diff --git a/vendor/symfony/http-kernel/EventListener/ErrorListener.php b/vendor/symfony/http-kernel/EventListener/ErrorListener.php deleted file mode 100644 index 26c361f..0000000 --- a/vendor/symfony/http-kernel/EventListener/ErrorListener.php +++ /dev/null @@ -1,149 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException; -use Symfony\Component\ErrorHandler\Exception\FlattenException; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; -use Symfony\Component\HttpKernel\Event\ExceptionEvent; -use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; - -/** - * @author Fabien Potencier - */ -class ErrorListener implements EventSubscriberInterface -{ - protected $controller; - protected $logger; - protected $debug; - - public function __construct($controller, LoggerInterface $logger = null, $debug = false) - { - $this->controller = $controller; - $this->logger = $logger; - $this->debug = $debug; - } - - public function logKernelException(ExceptionEvent $event) - { - $e = FlattenException::createFromThrowable($event->getThrowable()); - - $this->logException($event->getThrowable(), sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $e->getClass(), $e->getMessage(), $e->getFile(), $e->getLine())); - } - - public function onKernelException(ExceptionEvent $event, string $eventName = null, EventDispatcherInterface $eventDispatcher = null) - { - if (null === $this->controller) { - return; - } - - $exception = $event->getThrowable(); - $request = $this->duplicateRequest($exception, $event->getRequest()); - - try { - $response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, false); - } catch (\Exception $e) { - $f = FlattenException::createFromThrowable($e); - - $this->logException($e, sprintf('Exception thrown when handling an exception (%s: %s at %s line %s)', $f->getClass(), $f->getMessage(), $e->getFile(), $e->getLine())); - - $prev = $e; - do { - if ($exception === $wrapper = $prev) { - throw $e; - } - } while ($prev = $wrapper->getPrevious()); - - $prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous'); - $prev->setAccessible(true); - $prev->setValue($wrapper, $exception); - - throw $e; - } - - $event->setResponse($response); - - if ($this->debug && $eventDispatcher instanceof EventDispatcherInterface) { - $cspRemovalListener = function ($event) use (&$cspRemovalListener, $eventDispatcher) { - $event->getResponse()->headers->remove('Content-Security-Policy'); - $eventDispatcher->removeListener(KernelEvents::RESPONSE, $cspRemovalListener); - }; - $eventDispatcher->addListener(KernelEvents::RESPONSE, $cspRemovalListener, -128); - } - } - - public function onControllerArguments(ControllerArgumentsEvent $event) - { - $e = $event->getRequest()->attributes->get('exception'); - - if (!$e instanceof \Throwable || false === $k = array_search($e, $event->getArguments(), true)) { - return; - } - - $r = new \ReflectionFunction(\Closure::fromCallable($event->getController())); - $r = $r->getParameters()[$k] ?? null; - - if ($r && (!$r->hasType() || \in_array($r->getType()->getName(), [FlattenException::class, LegacyFlattenException::class], true))) { - $arguments = $event->getArguments(); - $arguments[$k] = FlattenException::createFromThrowable($e); - $event->setArguments($arguments); - } - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::CONTROLLER_ARGUMENTS => 'onControllerArguments', - KernelEvents::EXCEPTION => [ - ['logKernelException', 0], - ['onKernelException', -128], - ], - ]; - } - - /** - * Logs an exception. - */ - protected function logException(\Throwable $exception, string $message): void - { - if (null !== $this->logger) { - if (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) { - $this->logger->critical($message, ['exception' => $exception]); - } else { - $this->logger->error($message, ['exception' => $exception]); - } - } - } - - /** - * Clones the request for the exception. - */ - protected function duplicateRequest(\Throwable $exception, Request $request): Request - { - $attributes = [ - '_controller' => $this->controller, - 'exception' => $exception, - 'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null, - ]; - $request = $request->duplicate(null, null, $attributes); - $request->setMethod('GET'); - - return $request; - } -} diff --git a/vendor/symfony/http-kernel/EventListener/FragmentListener.php b/vendor/symfony/http-kernel/EventListener/FragmentListener.php deleted file mode 100644 index afe5cb1..0000000 --- a/vendor/symfony/http-kernel/EventListener/FragmentListener.php +++ /dev/null @@ -1,100 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\UriSigner; - -/** - * Handles content fragments represented by special URIs. - * - * All URL paths starting with /_fragment are handled as - * content fragments by this listener. - * - * Throws an AccessDeniedHttpException exception if the request - * is not signed or if it is not an internal sub-request. - * - * @author Fabien Potencier - * - * @final - */ -class FragmentListener implements EventSubscriberInterface -{ - private $signer; - private $fragmentPath; - - /** - * @param string $fragmentPath The path that triggers this listener - */ - public function __construct(UriSigner $signer, string $fragmentPath = '/_fragment') - { - $this->signer = $signer; - $this->fragmentPath = $fragmentPath; - } - - /** - * Fixes request attributes when the path is '/_fragment'. - * - * @throws AccessDeniedHttpException if the request does not come from a trusted IP - */ - public function onKernelRequest(RequestEvent $event) - { - $request = $event->getRequest(); - - if ($this->fragmentPath !== rawurldecode($request->getPathInfo())) { - return; - } - - if ($request->attributes->has('_controller')) { - // Is a sub-request: no need to parse _path but it should still be removed from query parameters as below. - $request->query->remove('_path'); - - return; - } - - if ($event->isMasterRequest()) { - $this->validateRequest($request); - } - - parse_str($request->query->get('_path', ''), $attributes); - $request->attributes->add($attributes); - $request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', []), $attributes)); - $request->query->remove('_path'); - } - - protected function validateRequest(Request $request) - { - // is the Request safe? - if (!$request->isMethodSafe()) { - throw new AccessDeniedHttpException(); - } - - // is the Request signed? - // we cannot use $request->getUri() here as we want to work with the original URI (no query string reordering) - if ($this->signer->check($request->getSchemeAndHttpHost().$request->getBaseUrl().$request->getPathInfo().(null !== ($qs = $request->server->get('QUERY_STRING')) ? '?'.$qs : ''))) { - return; - } - - throw new AccessDeniedHttpException(); - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => [['onKernelRequest', 48]], - ]; - } -} diff --git a/vendor/symfony/http-kernel/EventListener/LocaleAwareListener.php b/vendor/symfony/http-kernel/EventListener/LocaleAwareListener.php deleted file mode 100644 index 62d0302..0000000 --- a/vendor/symfony/http-kernel/EventListener/LocaleAwareListener.php +++ /dev/null @@ -1,77 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Contracts\Translation\LocaleAwareInterface; - -/** - * Pass the current locale to the provided services. - * - * @author Pierre Bobiet - */ -class LocaleAwareListener implements EventSubscriberInterface -{ - private $localeAwareServices; - private $requestStack; - - /** - * @param LocaleAwareInterface[] $localeAwareServices - */ - public function __construct(iterable $localeAwareServices, RequestStack $requestStack) - { - $this->localeAwareServices = $localeAwareServices; - $this->requestStack = $requestStack; - } - - public function onKernelRequest(RequestEvent $event): void - { - $this->setLocale($event->getRequest()->getLocale(), $event->getRequest()->getDefaultLocale()); - } - - public function onKernelFinishRequest(FinishRequestEvent $event): void - { - if (null === $parentRequest = $this->requestStack->getParentRequest()) { - foreach ($this->localeAwareServices as $service) { - $service->setLocale($event->getRequest()->getDefaultLocale()); - } - - return; - } - - $this->setLocale($parentRequest->getLocale(), $parentRequest->getDefaultLocale()); - } - - public static function getSubscribedEvents() - { - return [ - // must be registered after the Locale listener - KernelEvents::REQUEST => [['onKernelRequest', 15]], - KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', -15]], - ]; - } - - private function setLocale(string $locale, string $defaultLocale): void - { - foreach ($this->localeAwareServices as $service) { - try { - $service->setLocale($locale); - } catch (\InvalidArgumentException $e) { - $service->setLocale($defaultLocale); - } - } - } -} diff --git a/vendor/symfony/http-kernel/EventListener/LocaleListener.php b/vendor/symfony/http-kernel/EventListener/LocaleListener.php deleted file mode 100644 index 8037e32..0000000 --- a/vendor/symfony/http-kernel/EventListener/LocaleListener.php +++ /dev/null @@ -1,88 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\KernelEvent; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\Routing\RequestContextAwareInterface; - -/** - * Initializes the locale based on the current request. - * - * @author Fabien Potencier - * - * @final - */ -class LocaleListener implements EventSubscriberInterface -{ - private $router; - private $defaultLocale; - private $requestStack; - - public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null) - { - $this->defaultLocale = $defaultLocale; - $this->requestStack = $requestStack; - $this->router = $router; - } - - public function setDefaultLocale(KernelEvent $event) - { - $event->getRequest()->setDefaultLocale($this->defaultLocale); - } - - public function onKernelRequest(RequestEvent $event) - { - $request = $event->getRequest(); - - $this->setLocale($request); - $this->setRouterContext($request); - } - - public function onKernelFinishRequest(FinishRequestEvent $event) - { - if (null !== $parentRequest = $this->requestStack->getParentRequest()) { - $this->setRouterContext($parentRequest); - } - } - - private function setLocale(Request $request) - { - if ($locale = $request->attributes->get('_locale')) { - $request->setLocale($locale); - } - } - - private function setRouterContext(Request $request) - { - if (null !== $this->router) { - $this->router->getContext()->setParameter('_locale', $request->getLocale()); - } - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => [ - ['setDefaultLocale', 100], - // must be registered after the Router to have access to the _locale - ['onKernelRequest', 16], - ], - KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]], - ]; - } -} diff --git a/vendor/symfony/http-kernel/EventListener/ProfilerListener.php b/vendor/symfony/http-kernel/EventListener/ProfilerListener.php deleted file mode 100644 index 3143f2b..0000000 --- a/vendor/symfony/http-kernel/EventListener/ProfilerListener.php +++ /dev/null @@ -1,127 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpKernel\Event\ExceptionEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\Event\TerminateEvent; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\Profiler\Profiler; - -/** - * ProfilerListener collects data for the current request by listening to the kernel events. - * - * @author Fabien Potencier - * - * @final - */ -class ProfilerListener implements EventSubscriberInterface -{ - protected $profiler; - protected $matcher; - protected $onlyException; - protected $onlyMasterRequests; - protected $exception; - protected $profiles; - protected $requestStack; - protected $parents; - - /** - * @param bool $onlyException True if the profiler only collects data when an exception occurs, false otherwise - * @param bool $onlyMasterRequests True if the profiler only collects data when the request is a master request, false otherwise - */ - public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMasterRequests = false) - { - $this->profiler = $profiler; - $this->matcher = $matcher; - $this->onlyException = $onlyException; - $this->onlyMasterRequests = $onlyMasterRequests; - $this->profiles = new \SplObjectStorage(); - $this->parents = new \SplObjectStorage(); - $this->requestStack = $requestStack; - } - - /** - * Handles the onKernelException event. - */ - public function onKernelException(ExceptionEvent $event) - { - if ($this->onlyMasterRequests && !$event->isMasterRequest()) { - return; - } - - $this->exception = $event->getThrowable(); - } - - /** - * Handles the onKernelResponse event. - */ - public function onKernelResponse(ResponseEvent $event) - { - $master = $event->isMasterRequest(); - if ($this->onlyMasterRequests && !$master) { - return; - } - - if ($this->onlyException && null === $this->exception) { - return; - } - - $request = $event->getRequest(); - $exception = $this->exception; - $this->exception = null; - - if (null !== $this->matcher && !$this->matcher->matches($request)) { - return; - } - - if (!$profile = $this->profiler->collect($request, $event->getResponse(), $exception)) { - return; - } - - $this->profiles[$request] = $profile; - - $this->parents[$request] = $this->requestStack->getParentRequest(); - } - - public function onKernelTerminate(TerminateEvent $event) - { - // attach children to parents - foreach ($this->profiles as $request) { - if (null !== $parentRequest = $this->parents[$request]) { - if (isset($this->profiles[$parentRequest])) { - $this->profiles[$parentRequest]->addChild($this->profiles[$request]); - } - } - } - - // save profiles - foreach ($this->profiles as $request) { - $this->profiler->saveProfile($this->profiles[$request]); - } - - $this->profiles = new \SplObjectStorage(); - $this->parents = new \SplObjectStorage(); - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::RESPONSE => ['onKernelResponse', -100], - KernelEvents::EXCEPTION => ['onKernelException', 0], - KernelEvents::TERMINATE => ['onKernelTerminate', -1024], - ]; - } -} diff --git a/vendor/symfony/http-kernel/EventListener/ResponseListener.php b/vendor/symfony/http-kernel/EventListener/ResponseListener.php deleted file mode 100644 index d8292ae..0000000 --- a/vendor/symfony/http-kernel/EventListener/ResponseListener.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * ResponseListener fixes the Response headers based on the Request. - * - * @author Fabien Potencier - * - * @final - */ -class ResponseListener implements EventSubscriberInterface -{ - private $charset; - - public function __construct(string $charset) - { - $this->charset = $charset; - } - - /** - * Filters the Response. - */ - public function onKernelResponse(ResponseEvent $event) - { - if (!$event->isMasterRequest()) { - return; - } - - $response = $event->getResponse(); - - if (null === $response->getCharset()) { - $response->setCharset($this->charset); - } - - $response->prepare($event->getRequest()); - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::RESPONSE => 'onKernelResponse', - ]; - } -} diff --git a/vendor/symfony/http-kernel/EventListener/RouterListener.php b/vendor/symfony/http-kernel/EventListener/RouterListener.php deleted file mode 100644 index 31bbc3b..0000000 --- a/vendor/symfony/http-kernel/EventListener/RouterListener.php +++ /dev/null @@ -1,175 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Psr\Log\LoggerInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\ExceptionEvent; -use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\HttpKernel\Kernel; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\Matcher\RequestMatcherInterface; -use Symfony\Component\Routing\Matcher\UrlMatcherInterface; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\RequestContextAwareInterface; - -/** - * Initializes the context from the request and sets request attributes based on a matching route. - * - * @author Fabien Potencier - * @author Yonel Ceruto - * - * @final - */ -class RouterListener implements EventSubscriberInterface -{ - private $matcher; - private $context; - private $logger; - private $requestStack; - private $projectDir; - private $debug; - - /** - * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher - * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface) - * @param string $projectDir - * - * @throws \InvalidArgumentException - */ - public function __construct($matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null, string $projectDir = null, bool $debug = true) - { - if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) { - throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); - } - - if (null === $context && !$matcher instanceof RequestContextAwareInterface) { - throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.'); - } - - $this->matcher = $matcher; - $this->context = $context ?: $matcher->getContext(); - $this->requestStack = $requestStack; - $this->logger = $logger; - $this->projectDir = $projectDir; - $this->debug = $debug; - } - - private function setCurrentRequest(Request $request = null) - { - if (null !== $request) { - try { - $this->context->fromRequest($request); - } catch (\UnexpectedValueException $e) { - throw new BadRequestHttpException($e->getMessage(), $e, $e->getCode()); - } - } - } - - /** - * After a sub-request is done, we need to reset the routing context to the parent request so that the URL generator - * operates on the correct context again. - */ - public function onKernelFinishRequest(FinishRequestEvent $event) - { - $this->setCurrentRequest($this->requestStack->getParentRequest()); - } - - public function onKernelRequest(RequestEvent $event) - { - $request = $event->getRequest(); - - $this->setCurrentRequest($request); - - if ($request->attributes->has('_controller')) { - // routing is already done - return; - } - - // add attributes based on the request (routing) - try { - // matching a request is more powerful than matching a URL path + context, so try that first - if ($this->matcher instanceof RequestMatcherInterface) { - $parameters = $this->matcher->matchRequest($request); - } else { - $parameters = $this->matcher->match($request->getPathInfo()); - } - - if (null !== $this->logger) { - $this->logger->info('Matched route "{route}".', [ - 'route' => isset($parameters['_route']) ? $parameters['_route'] : 'n/a', - 'route_parameters' => $parameters, - 'request_uri' => $request->getUri(), - 'method' => $request->getMethod(), - ]); - } - - $request->attributes->add($parameters); - unset($parameters['_route'], $parameters['_controller']); - $request->attributes->set('_route_params', $parameters); - } catch (ResourceNotFoundException $e) { - $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo()); - - if ($referer = $request->headers->get('referer')) { - $message .= sprintf(' (from "%s")', $referer); - } - - throw new NotFoundHttpException($message, $e); - } catch (MethodNotAllowedException $e) { - $message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getPathInfo(), implode(', ', $e->getAllowedMethods())); - - throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e); - } - } - - public function onKernelException(ExceptionEvent $event) - { - if (!$this->debug || !($e = $event->getThrowable()) instanceof NotFoundHttpException) { - return; - } - - if ($e->getPrevious() instanceof NoConfigurationException) { - $event->setResponse($this->createWelcomeResponse()); - } - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => [['onKernelRequest', 32]], - KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]], - KernelEvents::EXCEPTION => ['onKernelException', -64], - ]; - } - - private function createWelcomeResponse(): Response - { - $version = Kernel::VERSION; - $projectDir = realpath($this->projectDir).\DIRECTORY_SEPARATOR; - $docVersion = substr(Kernel::VERSION, 0, 3); - - ob_start(); - include \dirname(__DIR__).'/Resources/welcome.html.php'; - - return new Response(ob_get_clean(), Response::HTTP_NOT_FOUND); - } -} diff --git a/vendor/symfony/http-kernel/EventListener/SessionListener.php b/vendor/symfony/http-kernel/EventListener/SessionListener.php deleted file mode 100644 index a53ade7..0000000 --- a/vendor/symfony/http-kernel/EventListener/SessionListener.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; - -/** - * Sets the session in the request. - * - * When the passed container contains a "session_storage" entry which - * holds a NativeSessionStorage instance, the "cookie_secure" option - * will be set to true whenever the current master request is secure. - * - * @author Fabien Potencier - * - * @final - */ -class SessionListener extends AbstractSessionListener -{ - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - protected function getSession(): ?SessionInterface - { - if (!$this->container->has('session')) { - return null; - } - - if ($this->container->has('session_storage') - && ($storage = $this->container->get('session_storage')) instanceof NativeSessionStorage - && ($masterRequest = $this->container->get('request_stack')->getMasterRequest()) - && $masterRequest->isSecure() - ) { - $storage->setOptions(['cookie_secure' => true]); - } - - return $this->container->get('session'); - } -} diff --git a/vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php b/vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php deleted file mode 100644 index 730ee54..0000000 --- a/vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\StreamedResponse; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * StreamedResponseListener is responsible for sending the Response - * to the client. - * - * @author Fabien Potencier - * - * @final - */ -class StreamedResponseListener implements EventSubscriberInterface -{ - /** - * Filters the Response. - */ - public function onKernelResponse(ResponseEvent $event) - { - if (!$event->isMasterRequest()) { - return; - } - - $response = $event->getResponse(); - - if ($response instanceof StreamedResponse) { - $response->send(); - } - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::RESPONSE => ['onKernelResponse', -1024], - ]; - } -} diff --git a/vendor/symfony/http-kernel/EventListener/SurrogateListener.php b/vendor/symfony/http-kernel/EventListener/SurrogateListener.php deleted file mode 100644 index 2ef4af7..0000000 --- a/vendor/symfony/http-kernel/EventListener/SurrogateListener.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\HttpCache\HttpCache; -use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * SurrogateListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for Surrogates. - * - * @author Fabien Potencier - * - * @final - */ -class SurrogateListener implements EventSubscriberInterface -{ - private $surrogate; - - public function __construct(SurrogateInterface $surrogate = null) - { - $this->surrogate = $surrogate; - } - - /** - * Filters the Response. - */ - public function onKernelResponse(ResponseEvent $event) - { - if (!$event->isMasterRequest()) { - return; - } - - $kernel = $event->getKernel(); - $surrogate = $this->surrogate; - if ($kernel instanceof HttpCache) { - $surrogate = $kernel->getSurrogate(); - if (null !== $this->surrogate && $this->surrogate->getName() !== $surrogate->getName()) { - $surrogate = $this->surrogate; - } - } - - if (null === $surrogate) { - return; - } - - $surrogate->addSurrogateControl($event->getResponse()); - } - - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::RESPONSE => 'onKernelResponse', - ]; - } -} diff --git a/vendor/symfony/http-kernel/EventListener/TestSessionListener.php b/vendor/symfony/http-kernel/EventListener/TestSessionListener.php deleted file mode 100644 index ff8b4aa..0000000 --- a/vendor/symfony/http-kernel/EventListener/TestSessionListener.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Psr\Container\ContainerInterface; -use Symfony\Component\HttpFoundation\Session\SessionInterface; - -/** - * Sets the session in the request. - * - * @author Fabien Potencier - * - * @final - */ -class TestSessionListener extends AbstractTestSessionListener -{ - private $container; - - public function __construct(ContainerInterface $container, array $sessionOptions = []) - { - $this->container = $container; - parent::__construct($sessionOptions); - } - - protected function getSession(): ?SessionInterface - { - if (!$this->container->has('session')) { - return null; - } - - return $this->container->get('session'); - } -} diff --git a/vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php b/vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php deleted file mode 100644 index 1f0c798..0000000 --- a/vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\EventListener; - -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\KernelEvents; - -/** - * Validates Requests. - * - * @author Magnus Nordlander - * - * @final - */ -class ValidateRequestListener implements EventSubscriberInterface -{ - /** - * Performs the validation. - */ - public function onKernelRequest(RequestEvent $event) - { - if (!$event->isMasterRequest()) { - return; - } - $request = $event->getRequest(); - - if ($request::getTrustedProxies()) { - $request->getClientIps(); - } - - $request->getHost(); - } - - /** - * {@inheritdoc} - */ - public static function getSubscribedEvents(): array - { - return [ - KernelEvents::REQUEST => [ - ['onKernelRequest', 256], - ], - ]; - } -} diff --git a/vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php b/vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php deleted file mode 100644 index 65e5f8c..0000000 --- a/vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Fabien Potencier - * @author Christophe Coevoet - */ -class AccessDeniedHttpException extends HttpException -{ - /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) - { - parent::__construct(403, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/BadRequestHttpException.php b/vendor/symfony/http-kernel/Exception/BadRequestHttpException.php deleted file mode 100644 index 7de9105..0000000 --- a/vendor/symfony/http-kernel/Exception/BadRequestHttpException.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey - */ -class BadRequestHttpException extends HttpException -{ - /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) - { - parent::__construct(400, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/ConflictHttpException.php b/vendor/symfony/http-kernel/Exception/ConflictHttpException.php deleted file mode 100644 index ebb86ba..0000000 --- a/vendor/symfony/http-kernel/Exception/ConflictHttpException.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey - */ -class ConflictHttpException extends HttpException -{ - /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) - { - parent::__construct(409, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php b/vendor/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php deleted file mode 100644 index 1e87690..0000000 --- a/vendor/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php +++ /dev/null @@ -1,84 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Grégoire Pineau - */ -class ControllerDoesNotReturnResponseException extends \LogicException -{ - public function __construct(string $message, callable $controller, string $file, int $line) - { - parent::__construct($message); - - if (!$controllerDefinition = $this->parseControllerDefinition($controller)) { - return; - } - - $this->file = $controllerDefinition['file']; - $this->line = $controllerDefinition['line']; - $r = new \ReflectionProperty(\Exception::class, 'trace'); - $r->setAccessible(true); - $r->setValue($this, array_merge([ - [ - 'line' => $line, - 'file' => $file, - ], - ], $this->getTrace())); - } - - private function parseControllerDefinition(callable $controller): ?array - { - if (\is_string($controller) && false !== strpos($controller, '::')) { - $controller = explode('::', $controller); - } - - if (\is_array($controller)) { - try { - $r = new \ReflectionMethod($controller[0], $controller[1]); - - return [ - 'file' => $r->getFileName(), - 'line' => $r->getEndLine(), - ]; - } catch (\ReflectionException $e) { - return null; - } - } - - if ($controller instanceof \Closure) { - $r = new \ReflectionFunction($controller); - - return [ - 'file' => $r->getFileName(), - 'line' => $r->getEndLine(), - ]; - } - - if (\is_object($controller)) { - $r = new \ReflectionClass($controller); - - try { - $line = $r->getMethod('__invoke')->getEndLine(); - } catch (\ReflectionException $e) { - $line = $r->getEndLine(); - } - - return [ - 'file' => $r->getFileName(), - 'line' => $line, - ]; - } - - return null; - } -} diff --git a/vendor/symfony/http-kernel/Exception/GoneHttpException.php b/vendor/symfony/http-kernel/Exception/GoneHttpException.php deleted file mode 100644 index aea283a..0000000 --- a/vendor/symfony/http-kernel/Exception/GoneHttpException.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey - */ -class GoneHttpException extends HttpException -{ - /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) - { - parent::__construct(410, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/HttpException.php b/vendor/symfony/http-kernel/Exception/HttpException.php deleted file mode 100644 index d822cd5..0000000 --- a/vendor/symfony/http-kernel/Exception/HttpException.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * HttpException. - * - * @author Kris Wallsmith - */ -class HttpException extends \RuntimeException implements HttpExceptionInterface -{ - private $statusCode; - private $headers; - - public function __construct(int $statusCode, string $message = null, \Throwable $previous = null, array $headers = [], ?int $code = 0) - { - $this->statusCode = $statusCode; - $this->headers = $headers; - - parent::__construct($message, $code, $previous); - } - - public function getStatusCode() - { - return $this->statusCode; - } - - public function getHeaders() - { - return $this->headers; - } - - /** - * Set response headers. - * - * @param array $headers Response headers - */ - public function setHeaders(array $headers) - { - $this->headers = $headers; - } -} diff --git a/vendor/symfony/http-kernel/Exception/HttpExceptionInterface.php b/vendor/symfony/http-kernel/Exception/HttpExceptionInterface.php deleted file mode 100644 index 735e9c8..0000000 --- a/vendor/symfony/http-kernel/Exception/HttpExceptionInterface.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * Interface for HTTP error exceptions. - * - * @author Kris Wallsmith - */ -interface HttpExceptionInterface extends \Throwable -{ - /** - * Returns the status code. - * - * @return int An HTTP response status code - */ - public function getStatusCode(); - - /** - * Returns response headers. - * - * @return array Response headers - */ - public function getHeaders(); -} diff --git a/vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php b/vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php deleted file mode 100644 index 44fb770..0000000 --- a/vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey - */ -class LengthRequiredHttpException extends HttpException -{ - /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) - { - parent::__construct(411, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php b/vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php deleted file mode 100644 index c15e46f..0000000 --- a/vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Kris Wallsmith - */ -class MethodNotAllowedHttpException extends HttpException -{ - /** - * @param array $allow An array of allowed methods - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(array $allow, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) - { - $headers['Allow'] = strtoupper(implode(', ', $allow)); - - parent::__construct(405, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.php b/vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.php deleted file mode 100644 index c5f5324..0000000 --- a/vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey - */ -class NotAcceptableHttpException extends HttpException -{ - /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) - { - parent::__construct(406, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/NotFoundHttpException.php b/vendor/symfony/http-kernel/Exception/NotFoundHttpException.php deleted file mode 100644 index 146b908..0000000 --- a/vendor/symfony/http-kernel/Exception/NotFoundHttpException.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Fabien Potencier - */ -class NotFoundHttpException extends HttpException -{ - /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) - { - parent::__construct(404, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php b/vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php deleted file mode 100644 index e878b10..0000000 --- a/vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey - */ -class PreconditionFailedHttpException extends HttpException -{ - /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) - { - parent::__construct(412, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php b/vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php deleted file mode 100644 index a6cb2f0..0000000 --- a/vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey - * - * @see http://tools.ietf.org/html/rfc6585 - */ -class PreconditionRequiredHttpException extends HttpException -{ - /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) - { - parent::__construct(428, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php b/vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php deleted file mode 100644 index c786ccf..0000000 --- a/vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey - */ -class ServiceUnavailableHttpException extends HttpException -{ - /** - * @param int|string $retryAfter The number of seconds or HTTP-date after which the request may be retried - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct($retryAfter = null, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) - { - if ($retryAfter) { - $headers['Retry-After'] = $retryAfter; - } - - parent::__construct(503, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php b/vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php deleted file mode 100644 index b709f1a..0000000 --- a/vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey - * - * @see http://tools.ietf.org/html/rfc6585 - */ -class TooManyRequestsHttpException extends HttpException -{ - /** - * @param int|string $retryAfter The number of seconds or HTTP-date after which the request may be retried - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct($retryAfter = null, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) - { - if ($retryAfter) { - $headers['Retry-After'] = $retryAfter; - } - - parent::__construct(429, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php b/vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php deleted file mode 100644 index fb86c1e..0000000 --- a/vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey - */ -class UnauthorizedHttpException extends HttpException -{ - /** - * @param string $challenge WWW-Authenticate challenge string - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(string $challenge, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) - { - $headers['WWW-Authenticate'] = $challenge; - - parent::__construct(401, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php b/vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php deleted file mode 100644 index 93d4bce..0000000 --- a/vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Steve Hutchins - */ -class UnprocessableEntityHttpException extends HttpException -{ - /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) - { - parent::__construct(422, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php b/vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php deleted file mode 100644 index 7cda3a6..0000000 --- a/vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Exception; - -/** - * @author Ben Ramsey - */ -class UnsupportedMediaTypeHttpException extends HttpException -{ - /** - * @param string $message The internal exception message - * @param \Throwable $previous The previous exception - * @param int $code The internal exception code - */ - public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) - { - parent::__construct(415, $message, $previous, $headers, $code); - } -} diff --git a/vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php deleted file mode 100644 index f81199d..0000000 --- a/vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php +++ /dev/null @@ -1,108 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Controller\ControllerReference; -use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface; -use Symfony\Component\HttpKernel\UriSigner; - -/** - * Implements Surrogate rendering strategy. - * - * @author Fabien Potencier - */ -abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRenderer -{ - private $surrogate; - private $inlineStrategy; - private $signer; - - /** - * The "fallback" strategy when surrogate is not available should always be an - * instance of InlineFragmentRenderer. - * - * @param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported - */ - public function __construct(SurrogateInterface $surrogate = null, FragmentRendererInterface $inlineStrategy, UriSigner $signer = null) - { - $this->surrogate = $surrogate; - $this->inlineStrategy = $inlineStrategy; - $this->signer = $signer; - } - - /** - * {@inheritdoc} - * - * Note that if the current Request has no surrogate capability, this method - * falls back to use the inline rendering strategy. - * - * Additional available options: - * - * * alt: an alternative URI to render in case of an error - * * comment: a comment to add when returning the surrogate tag - * - * Note, that not all surrogate strategies support all options. For now - * 'alt' and 'comment' are only supported by ESI. - * - * @see Symfony\Component\HttpKernel\HttpCache\SurrogateInterface - */ - public function render($uri, Request $request, array $options = []) - { - if (!$this->surrogate || !$this->surrogate->hasSurrogateCapability($request)) { - if ($uri instanceof ControllerReference && $this->containsNonScalars($uri->attributes)) { - throw new \InvalidArgumentException('Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is not supported. Use a different rendering strategy or pass scalar values.'); - } - - return $this->inlineStrategy->render($uri, $request, $options); - } - - if ($uri instanceof ControllerReference) { - $uri = $this->generateSignedFragmentUri($uri, $request); - } - - $alt = isset($options['alt']) ? $options['alt'] : null; - if ($alt instanceof ControllerReference) { - $alt = $this->generateSignedFragmentUri($alt, $request); - } - - $tag = $this->surrogate->renderIncludeTag($uri, $alt, isset($options['ignore_errors']) ? $options['ignore_errors'] : false, isset($options['comment']) ? $options['comment'] : ''); - - return new Response($tag); - } - - private function generateSignedFragmentUri(ControllerReference $uri, Request $request): string - { - if (null === $this->signer) { - throw new \LogicException('You must use a URI when using the ESI rendering strategy or set a URL signer.'); - } - - // we need to sign the absolute URI, but want to return the path only. - $fragmentUri = $this->signer->sign($this->generateFragmentUri($uri, $request, true)); - - return substr($fragmentUri, \strlen($request->getSchemeAndHttpHost())); - } - - private function containsNonScalars(array $values): bool - { - foreach ($values as $value) { - if (\is_array($value)) { - return $this->containsNonScalars($value); - } elseif (!is_scalar($value) && null !== $value) { - return true; - } - } - - return false; - } -} diff --git a/vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.php deleted file mode 100644 index a4570e3..0000000 --- a/vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -/** - * Implements the ESI rendering strategy. - * - * @author Fabien Potencier - */ -class EsiFragmentRenderer extends AbstractSurrogateFragmentRenderer -{ - /** - * {@inheritdoc} - */ - public function getName() - { - return 'esi'; - } -} diff --git a/vendor/symfony/http-kernel/Fragment/FragmentHandler.php b/vendor/symfony/http-kernel/Fragment/FragmentHandler.php deleted file mode 100644 index f3d3f0d..0000000 --- a/vendor/symfony/http-kernel/Fragment/FragmentHandler.php +++ /dev/null @@ -1,111 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\StreamedResponse; -use Symfony\Component\HttpKernel\Controller\ControllerReference; - -/** - * Renders a URI that represents a resource fragment. - * - * This class handles the rendering of resource fragments that are included into - * a main resource. The handling of the rendering is managed by specialized renderers. - * - * @author Fabien Potencier - * - * @see FragmentRendererInterface - */ -class FragmentHandler -{ - private $debug; - private $renderers = []; - private $requestStack; - - /** - * @param FragmentRendererInterface[] $renderers An array of FragmentRendererInterface instances - * @param bool $debug Whether the debug mode is enabled or not - */ - public function __construct(RequestStack $requestStack, array $renderers = [], bool $debug = false) - { - $this->requestStack = $requestStack; - foreach ($renderers as $renderer) { - $this->addRenderer($renderer); - } - $this->debug = $debug; - } - - /** - * Adds a renderer. - */ - public function addRenderer(FragmentRendererInterface $renderer) - { - $this->renderers[$renderer->getName()] = $renderer; - } - - /** - * Renders a URI and returns the Response content. - * - * Available options: - * - * * ignore_errors: true to return an empty string in case of an error - * - * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance - * - * @return string|null The Response content or null when the Response is streamed - * - * @throws \InvalidArgumentException when the renderer does not exist - * @throws \LogicException when no master request is being handled - */ - public function render($uri, string $renderer = 'inline', array $options = []) - { - if (!isset($options['ignore_errors'])) { - $options['ignore_errors'] = !$this->debug; - } - - if (!isset($this->renderers[$renderer])) { - throw new \InvalidArgumentException(sprintf('The "%s" renderer does not exist.', $renderer)); - } - - if (!$request = $this->requestStack->getCurrentRequest()) { - throw new \LogicException('Rendering a fragment can only be done when handling a Request.'); - } - - return $this->deliver($this->renderers[$renderer]->render($uri, $request, $options)); - } - - /** - * Delivers the Response as a string. - * - * When the Response is a StreamedResponse, the content is streamed immediately - * instead of being returned. - * - * @return string|null The Response content or null when the Response is streamed - * - * @throws \RuntimeException when the Response is not successful - */ - protected function deliver(Response $response) - { - if (!$response->isSuccessful()) { - throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $this->requestStack->getCurrentRequest()->getUri(), $response->getStatusCode())); - } - - if (!$response instanceof StreamedResponse) { - return $response->getContent(); - } - - $response->sendContent(); - - return null; - } -} diff --git a/vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php b/vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php deleted file mode 100644 index 4f8ac50..0000000 --- a/vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Controller\ControllerReference; - -/** - * Interface implemented by all rendering strategies. - * - * @author Fabien Potencier - */ -interface FragmentRendererInterface -{ - /** - * Renders a URI and returns the Response content. - * - * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance - * - * @return Response A Response instance - */ - public function render($uri, Request $request, array $options = []); - - /** - * Gets the name of the strategy. - * - * @return string The strategy name - */ - public function getName(); -} diff --git a/vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php deleted file mode 100644 index 9db6557..0000000 --- a/vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php +++ /dev/null @@ -1,112 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Controller\ControllerReference; -use Symfony\Component\HttpKernel\UriSigner; -use Twig\Environment; -use Twig\Error\LoaderError; -use Twig\Loader\ExistsLoaderInterface; -use Twig\Loader\SourceContextLoaderInterface; - -/** - * Implements the Hinclude rendering strategy. - * - * @author Fabien Potencier - */ -class HIncludeFragmentRenderer extends RoutableFragmentRenderer -{ - private $globalDefaultTemplate; - private $signer; - private $twig; - private $charset; - - /** - * @param string $globalDefaultTemplate The global default content (it can be a template name or the content) - */ - public function __construct(Environment $twig = null, UriSigner $signer = null, string $globalDefaultTemplate = null, string $charset = 'utf-8') - { - $this->twig = $twig; - $this->globalDefaultTemplate = $globalDefaultTemplate; - $this->signer = $signer; - $this->charset = $charset; - } - - /** - * Checks if a templating engine has been set. - * - * @return bool true if the templating engine has been set, false otherwise - */ - public function hasTemplating() - { - return null !== $this->twig; - } - - /** - * {@inheritdoc} - * - * Additional available options: - * - * * default: The default content (it can be a template name or the content) - * * id: An optional hx:include tag id attribute - * * attributes: An optional array of hx:include tag attributes - */ - public function render($uri, Request $request, array $options = []) - { - if ($uri instanceof ControllerReference) { - if (null === $this->signer) { - throw new \LogicException('You must use a proper URI when using the Hinclude rendering strategy or set a URL signer.'); - } - - // we need to sign the absolute URI, but want to return the path only. - $uri = substr($this->signer->sign($this->generateFragmentUri($uri, $request, true)), \strlen($request->getSchemeAndHttpHost())); - } - - // We need to replace ampersands in the URI with the encoded form in order to return valid html/xml content. - $uri = str_replace('&', '&', $uri); - - $template = isset($options['default']) ? $options['default'] : $this->globalDefaultTemplate; - if (null !== $this->twig && $template && $this->twig->getLoader()->exists($template)) { - $content = $this->twig->render($template); - } else { - $content = $template; - } - - $attributes = isset($options['attributes']) && \is_array($options['attributes']) ? $options['attributes'] : []; - if (isset($options['id']) && $options['id']) { - $attributes['id'] = $options['id']; - } - $renderedAttributes = ''; - if (\count($attributes) > 0) { - $flags = ENT_QUOTES | ENT_SUBSTITUTE; - foreach ($attributes as $attribute => $value) { - $renderedAttributes .= sprintf( - ' %s="%s"', - htmlspecialchars($attribute, $flags, $this->charset, false), - htmlspecialchars($value, $flags, $this->charset, false) - ); - } - } - - return new Response(sprintf('%s', $uri, $renderedAttributes, $content)); - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'hinclude'; - } -} diff --git a/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php deleted file mode 100644 index 3bbdbd3..0000000 --- a/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php +++ /dev/null @@ -1,145 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Controller\ControllerReference; -use Symfony\Component\HttpKernel\Event\ExceptionEvent; -use Symfony\Component\HttpKernel\HttpCache\SubRequestHandler; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; - -/** - * Implements the inline rendering strategy where the Request is rendered by the current HTTP kernel. - * - * @author Fabien Potencier - */ -class InlineFragmentRenderer extends RoutableFragmentRenderer -{ - private $kernel; - private $dispatcher; - - public function __construct(HttpKernelInterface $kernel, EventDispatcherInterface $dispatcher = null) - { - $this->kernel = $kernel; - $this->dispatcher = $dispatcher; - } - - /** - * {@inheritdoc} - * - * Additional available options: - * - * * alt: an alternative URI to render in case of an error - */ - public function render($uri, Request $request, array $options = []) - { - $reference = null; - if ($uri instanceof ControllerReference) { - $reference = $uri; - - // Remove attributes from the generated URI because if not, the Symfony - // routing system will use them to populate the Request attributes. We don't - // want that as we want to preserve objects (so we manually set Request attributes - // below instead) - $attributes = $reference->attributes; - $reference->attributes = []; - - // The request format and locale might have been overridden by the user - foreach (['_format', '_locale'] as $key) { - if (isset($attributes[$key])) { - $reference->attributes[$key] = $attributes[$key]; - } - } - - $uri = $this->generateFragmentUri($uri, $request, false, false); - - $reference->attributes = array_merge($attributes, $reference->attributes); - } - - $subRequest = $this->createSubRequest($uri, $request); - - // override Request attributes as they can be objects (which are not supported by the generated URI) - if (null !== $reference) { - $subRequest->attributes->add($reference->attributes); - } - - $level = ob_get_level(); - try { - return SubRequestHandler::handle($this->kernel, $subRequest, HttpKernelInterface::SUB_REQUEST, false); - } catch (\Exception $e) { - // we dispatch the exception event to trigger the logging - // the response that comes back is ignored - if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) { - $event = new ExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e); - - $this->dispatcher->dispatch($event, KernelEvents::EXCEPTION); - } - - // let's clean up the output buffers that were created by the sub-request - Response::closeOutputBuffers($level, false); - - if (isset($options['alt'])) { - $alt = $options['alt']; - unset($options['alt']); - - return $this->render($alt, $request, $options); - } - - if (!isset($options['ignore_errors']) || !$options['ignore_errors']) { - throw $e; - } - - return new Response(); - } - } - - protected function createSubRequest($uri, Request $request) - { - $cookies = $request->cookies->all(); - $server = $request->server->all(); - - unset($server['HTTP_IF_MODIFIED_SINCE']); - unset($server['HTTP_IF_NONE_MATCH']); - - $subRequest = Request::create($uri, 'get', [], $cookies, [], $server); - if ($request->headers->has('Surrogate-Capability')) { - $subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability')); - } - - static $setSession; - - if (null === $setSession) { - $setSession = \Closure::bind(static function ($subRequest, $request) { $subRequest->session = $request->session; }, null, Request::class); - } - $setSession($subRequest, $request); - - if ($request->get('_format')) { - $subRequest->attributes->set('_format', $request->get('_format')); - } - if ($request->getDefaultLocale() !== $request->getLocale()) { - $subRequest->setLocale($request->getLocale()); - } - - return $subRequest; - } - - /** - * {@inheritdoc} - */ - public function getName() - { - return 'inline'; - } -} diff --git a/vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php deleted file mode 100644 index c9a1757..0000000 --- a/vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php +++ /dev/null @@ -1,86 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ControllerReference; -use Symfony\Component\HttpKernel\EventListener\FragmentListener; - -/** - * Adds the possibility to generate a fragment URI for a given Controller. - * - * @author Fabien Potencier - */ -abstract class RoutableFragmentRenderer implements FragmentRendererInterface -{ - private $fragmentPath = '/_fragment'; - - /** - * Sets the fragment path that triggers the fragment listener. - * - * @see FragmentListener - */ - public function setFragmentPath(string $path) - { - $this->fragmentPath = $path; - } - - /** - * Generates a fragment URI for a given controller. - * - * @param bool $absolute Whether to generate an absolute URL or not - * @param bool $strict Whether to allow non-scalar attributes or not - * - * @return string A fragment URI - */ - protected function generateFragmentUri(ControllerReference $reference, Request $request, bool $absolute = false, bool $strict = true) - { - if ($strict) { - $this->checkNonScalar($reference->attributes); - } - - // We need to forward the current _format and _locale values as we don't have - // a proper routing pattern to do the job for us. - // This makes things inconsistent if you switch from rendering a controller - // to rendering a route if the route pattern does not contain the special - // _format and _locale placeholders. - if (!isset($reference->attributes['_format'])) { - $reference->attributes['_format'] = $request->getRequestFormat(); - } - if (!isset($reference->attributes['_locale'])) { - $reference->attributes['_locale'] = $request->getLocale(); - } - - $reference->attributes['_controller'] = $reference->controller; - - $reference->query['_path'] = http_build_query($reference->attributes, '', '&'); - - $path = $this->fragmentPath.'?'.http_build_query($reference->query, '', '&'); - - if ($absolute) { - return $request->getUriForPath($path); - } - - return $request->getBaseUrl().$path; - } - - private function checkNonScalar(array $values) - { - foreach ($values as $key => $value) { - if (\is_array($value)) { - $this->checkNonScalar($value); - } elseif (!is_scalar($value) && null !== $value) { - throw new \LogicException(sprintf('Controller attributes cannot contain non-scalar/non-null values (value for key "%s" is not a scalar or null).', $key)); - } - } - } -} diff --git a/vendor/symfony/http-kernel/Fragment/SsiFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/SsiFragmentRenderer.php deleted file mode 100644 index 45e7122..0000000 --- a/vendor/symfony/http-kernel/Fragment/SsiFragmentRenderer.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Fragment; - -/** - * Implements the SSI rendering strategy. - * - * @author Sebastian Krebs - */ -class SsiFragmentRenderer extends AbstractSurrogateFragmentRenderer -{ - /** - * {@inheritdoc} - */ - public function getName() - { - return 'ssi'; - } -} diff --git a/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php b/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php deleted file mode 100644 index ac2c341..0000000 --- a/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php +++ /dev/null @@ -1,136 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * Abstract class implementing Surrogate capabilities to Request and Response instances. - * - * @author Fabien Potencier - * @author Robin Chalas - */ -abstract class AbstractSurrogate implements SurrogateInterface -{ - protected $contentTypes; - protected $phpEscapeMap = [ - ['', '', '', ''], - ]; - - /** - * @param array $contentTypes An array of content-type that should be parsed for Surrogate information - * (default: text/html, text/xml, application/xhtml+xml, and application/xml) - */ - public function __construct(array $contentTypes = ['text/html', 'text/xml', 'application/xhtml+xml', 'application/xml']) - { - $this->contentTypes = $contentTypes; - } - - /** - * Returns a new cache strategy instance. - * - * @return ResponseCacheStrategyInterface A ResponseCacheStrategyInterface instance - */ - public function createCacheStrategy() - { - return new ResponseCacheStrategy(); - } - - /** - * {@inheritdoc} - */ - public function hasSurrogateCapability(Request $request) - { - if (null === $value = $request->headers->get('Surrogate-Capability')) { - return false; - } - - return false !== strpos($value, sprintf('%s/1.0', strtoupper($this->getName()))); - } - - /** - * {@inheritdoc} - */ - public function addSurrogateCapability(Request $request) - { - $current = $request->headers->get('Surrogate-Capability'); - $new = sprintf('symfony="%s/1.0"', strtoupper($this->getName())); - - $request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new); - } - - /** - * {@inheritdoc} - */ - public function needsParsing(Response $response) - { - if (!$control = $response->headers->get('Surrogate-Control')) { - return false; - } - - $pattern = sprintf('#content="[^"]*%s/1.0[^"]*"#', strtoupper($this->getName())); - - return (bool) preg_match($pattern, $control); - } - - /** - * {@inheritdoc} - */ - public function handle(HttpCache $cache, string $uri, string $alt, bool $ignoreErrors) - { - $subRequest = Request::create($uri, Request::METHOD_GET, [], $cache->getRequest()->cookies->all(), [], $cache->getRequest()->server->all()); - - try { - $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true); - - if (!$response->isSuccessful()) { - throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode())); - } - - return $response->getContent(); - } catch (\Exception $e) { - if ($alt) { - return $this->handle($cache, $alt, '', $ignoreErrors); - } - - if (!$ignoreErrors) { - throw $e; - } - } - - return ''; - } - - /** - * Remove the Surrogate from the Surrogate-Control header. - */ - protected function removeFromControl(Response $response) - { - if (!$response->headers->has('Surrogate-Control')) { - return; - } - - $value = $response->headers->get('Surrogate-Control'); - $upperName = strtoupper($this->getName()); - - if (sprintf('content="%s/1.0"', $upperName) == $value) { - $response->headers->remove('Surrogate-Control'); - } elseif (preg_match(sprintf('#,\s*content="%s/1.0"#', $upperName), $value)) { - $response->headers->set('Surrogate-Control', preg_replace(sprintf('#,\s*content="%s/1.0"#', $upperName), '', $value)); - } elseif (preg_match(sprintf('#content="%s/1.0",\s*#', $upperName), $value)) { - $response->headers->set('Surrogate-Control', preg_replace(sprintf('#content="%s/1.0",\s*#', $upperName), '', $value)); - } - } -} diff --git a/vendor/symfony/http-kernel/HttpCache/Esi.php b/vendor/symfony/http-kernel/HttpCache/Esi.php deleted file mode 100644 index af67e8f..0000000 --- a/vendor/symfony/http-kernel/HttpCache/Esi.php +++ /dev/null @@ -1,117 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Esi implements the ESI capabilities to Request and Response instances. - * - * For more information, read the following W3C notes: - * - * * ESI Language Specification 1.0 (http://www.w3.org/TR/esi-lang) - * - * * Edge Architecture Specification (http://www.w3.org/TR/edge-arch) - * - * @author Fabien Potencier - */ -class Esi extends AbstractSurrogate -{ - public function getName() - { - return 'esi'; - } - - /** - * {@inheritdoc} - */ - public function addSurrogateControl(Response $response) - { - if (false !== strpos($response->getContent(), 'headers->set('Surrogate-Control', 'content="ESI/1.0"'); - } - } - - /** - * {@inheritdoc} - */ - public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = '') - { - $html = sprintf('', - $uri, - $ignoreErrors ? ' onerror="continue"' : '', - $alt ? sprintf(' alt="%s"', $alt) : '' - ); - - if (!empty($comment)) { - return sprintf("\n%s", $comment, $html); - } - - return $html; - } - - /** - * {@inheritdoc} - */ - public function process(Request $request, Response $response) - { - $type = $response->headers->get('Content-Type'); - if (empty($type)) { - $type = 'text/html'; - } - - $parts = explode(';', $type); - if (!\in_array($parts[0], $this->contentTypes)) { - return $response; - } - - // we don't use a proper XML parser here as we can have ESI tags in a plain text response - $content = $response->getContent(); - $content = preg_replace('#.*?#s', '', $content); - $content = preg_replace('#]+>#s', '', $content); - - $chunks = preg_split('##', $content, -1, PREG_SPLIT_DELIM_CAPTURE); - $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]); - - $i = 1; - while (isset($chunks[$i])) { - $options = []; - preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER); - foreach ($matches as $set) { - $options[$set[1]] = $set[2]; - } - - if (!isset($options['src'])) { - throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.'); - } - - $chunks[$i] = sprintf('surrogate->handle($this, %s, %s, %s) ?>'."\n", - var_export($options['src'], true), - var_export(isset($options['alt']) ? $options['alt'] : '', true), - isset($options['onerror']) && 'continue' === $options['onerror'] ? 'true' : 'false' - ); - ++$i; - $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]); - ++$i; - } - $content = implode('', $chunks); - - $response->setContent($content); - $response->headers->set('X-Body-Eval', 'ESI'); - - // remove ESI/1.0 from the Surrogate-Control header - $this->removeFromControl($response); - - return $response; - } -} diff --git a/vendor/symfony/http-kernel/HttpCache/HttpCache.php b/vendor/symfony/http-kernel/HttpCache/HttpCache.php deleted file mode 100644 index 698af72..0000000 --- a/vendor/symfony/http-kernel/HttpCache/HttpCache.php +++ /dev/null @@ -1,707 +0,0 @@ - - * - * This code is partially based on the Rack-Cache library by Ryan Tomayko, - * which is released under the MIT license. - * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\TerminableInterface; - -/** - * Cache provides HTTP caching. - * - * @author Fabien Potencier - */ -class HttpCache implements HttpKernelInterface, TerminableInterface -{ - private $kernel; - private $store; - private $request; - private $surrogate; - private $surrogateCacheStrategy; - private $options = []; - private $traces = []; - - /** - * Constructor. - * - * The available options are: - * - * * debug If true, exceptions are thrown when things go wrong. Otherwise, the cache - * will try to carry on and deliver a meaningful response. - * - * * trace_level May be one of 'none', 'short' and 'full'. For 'short', a concise trace of the - * master request will be added as an HTTP header. 'full' will add traces for all - * requests (including ESI subrequests). (default: 'full' if in debug; 'none' otherwise) - * - * * trace_header Header name to use for traces. (default: X-Symfony-Cache) - * - * * default_ttl The number of seconds that a cache entry should be considered - * fresh when no explicit freshness information is provided in - * a response. Explicit Cache-Control or Expires headers - * override this value. (default: 0) - * - * * private_headers Set of request headers that trigger "private" cache-control behavior - * on responses that don't explicitly state whether the response is - * public or private via a Cache-Control directive. (default: Authorization and Cookie) - * - * * allow_reload Specifies whether the client can force a cache reload by including a - * Cache-Control "no-cache" directive in the request. Set it to ``true`` - * for compliance with RFC 2616. (default: false) - * - * * allow_revalidate Specifies whether the client can force a cache revalidate by including - * a Cache-Control "max-age=0" directive in the request. Set it to ``true`` - * for compliance with RFC 2616. (default: false) - * - * * stale_while_revalidate Specifies the default number of seconds (the granularity is the second as the - * Response TTL precision is a second) during which the cache can immediately return - * a stale response while it revalidates it in the background (default: 2). - * This setting is overridden by the stale-while-revalidate HTTP Cache-Control - * extension (see RFC 5861). - * - * * stale_if_error Specifies the default number of seconds (the granularity is the second) during which - * the cache can serve a stale response when an error is encountered (default: 60). - * This setting is overridden by the stale-if-error HTTP Cache-Control extension - * (see RFC 5861). - */ - public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = []) - { - $this->store = $store; - $this->kernel = $kernel; - $this->surrogate = $surrogate; - - // needed in case there is a fatal error because the backend is too slow to respond - register_shutdown_function([$this->store, 'cleanup']); - - $this->options = array_merge([ - 'debug' => false, - 'default_ttl' => 0, - 'private_headers' => ['Authorization', 'Cookie'], - 'allow_reload' => false, - 'allow_revalidate' => false, - 'stale_while_revalidate' => 2, - 'stale_if_error' => 60, - 'trace_level' => 'none', - 'trace_header' => 'X-Symfony-Cache', - ], $options); - - if (!isset($options['trace_level'])) { - $this->options['trace_level'] = $this->options['debug'] ? 'full' : 'none'; - } - } - - /** - * Gets the current store. - * - * @return StoreInterface A StoreInterface instance - */ - public function getStore() - { - return $this->store; - } - - /** - * Returns an array of events that took place during processing of the last request. - * - * @return array An array of events - */ - public function getTraces() - { - return $this->traces; - } - - private function addTraces(Response $response) - { - $traceString = null; - - if ('full' === $this->options['trace_level']) { - $traceString = $this->getLog(); - } - - if ('short' === $this->options['trace_level'] && $masterId = array_key_first($this->traces)) { - $traceString = implode('/', $this->traces[$masterId]); - } - - if (null !== $traceString) { - $response->headers->add([$this->options['trace_header'] => $traceString]); - } - } - - /** - * Returns a log message for the events of the last request processing. - * - * @return string A log message - */ - public function getLog() - { - $log = []; - foreach ($this->traces as $request => $traces) { - $log[] = sprintf('%s: %s', $request, implode(', ', $traces)); - } - - return implode('; ', $log); - } - - /** - * Gets the Request instance associated with the master request. - * - * @return Request A Request instance - */ - public function getRequest() - { - return $this->request; - } - - /** - * Gets the Kernel instance. - * - * @return HttpKernelInterface An HttpKernelInterface instance - */ - public function getKernel() - { - return $this->kernel; - } - - /** - * Gets the Surrogate instance. - * - * @return SurrogateInterface A Surrogate instance - * - * @throws \LogicException - */ - public function getSurrogate() - { - return $this->surrogate; - } - - /** - * {@inheritdoc} - */ - public function handle(Request $request, int $type = HttpKernelInterface::MASTER_REQUEST, bool $catch = true) - { - // FIXME: catch exceptions and implement a 500 error page here? -> in Varnish, there is a built-in error page mechanism - if (HttpKernelInterface::MASTER_REQUEST === $type) { - $this->traces = []; - // Keep a clone of the original request for surrogates so they can access it. - // We must clone here to get a separate instance because the application will modify the request during - // the application flow (we know it always does because we do ourselves by setting REMOTE_ADDR to 127.0.0.1 - // and adding the X-Forwarded-For header, see HttpCache::forward()). - $this->request = clone $request; - if (null !== $this->surrogate) { - $this->surrogateCacheStrategy = $this->surrogate->createCacheStrategy(); - } - } - - $this->traces[$this->getTraceKey($request)] = []; - - if (!$request->isMethodSafe()) { - $response = $this->invalidate($request, $catch); - } elseif ($request->headers->has('expect') || !$request->isMethodCacheable()) { - $response = $this->pass($request, $catch); - } elseif ($this->options['allow_reload'] && $request->isNoCache()) { - /* - If allow_reload is configured and the client requests "Cache-Control: no-cache", - reload the cache by fetching a fresh response and caching it (if possible). - */ - $this->record($request, 'reload'); - $response = $this->fetch($request, $catch); - } else { - $response = $this->lookup($request, $catch); - } - - $this->restoreResponseBody($request, $response); - - if (HttpKernelInterface::MASTER_REQUEST === $type) { - $this->addTraces($response); - } - - if (null !== $this->surrogate) { - if (HttpKernelInterface::MASTER_REQUEST === $type) { - $this->surrogateCacheStrategy->update($response); - } else { - $this->surrogateCacheStrategy->add($response); - } - } - - $response->prepare($request); - - $response->isNotModified($request); - - return $response; - } - - /** - * {@inheritdoc} - */ - public function terminate(Request $request, Response $response) - { - if ($this->getKernel() instanceof TerminableInterface) { - $this->getKernel()->terminate($request, $response); - } - } - - /** - * Forwards the Request to the backend without storing the Response in the cache. - * - * @param bool $catch Whether to process exceptions - * - * @return Response A Response instance - */ - protected function pass(Request $request, bool $catch = false) - { - $this->record($request, 'pass'); - - return $this->forward($request, $catch); - } - - /** - * Invalidates non-safe methods (like POST, PUT, and DELETE). - * - * @param bool $catch Whether to process exceptions - * - * @return Response A Response instance - * - * @throws \Exception - * - * @see RFC2616 13.10 - */ - protected function invalidate(Request $request, bool $catch = false) - { - $response = $this->pass($request, $catch); - - // invalidate only when the response is successful - if ($response->isSuccessful() || $response->isRedirect()) { - try { - $this->store->invalidate($request); - - // As per the RFC, invalidate Location and Content-Location URLs if present - foreach (['Location', 'Content-Location'] as $header) { - if ($uri = $response->headers->get($header)) { - $subRequest = Request::create($uri, 'get', [], [], [], $request->server->all()); - - $this->store->invalidate($subRequest); - } - } - - $this->record($request, 'invalidate'); - } catch (\Exception $e) { - $this->record($request, 'invalidate-failed'); - - if ($this->options['debug']) { - throw $e; - } - } - } - - return $response; - } - - /** - * Lookups a Response from the cache for the given Request. - * - * When a matching cache entry is found and is fresh, it uses it as the - * response without forwarding any request to the backend. When a matching - * cache entry is found but is stale, it attempts to "validate" the entry with - * the backend using conditional GET. When no matching cache entry is found, - * it triggers "miss" processing. - * - * @param bool $catch Whether to process exceptions - * - * @return Response A Response instance - * - * @throws \Exception - */ - protected function lookup(Request $request, bool $catch = false) - { - try { - $entry = $this->store->lookup($request); - } catch (\Exception $e) { - $this->record($request, 'lookup-failed'); - - if ($this->options['debug']) { - throw $e; - } - - return $this->pass($request, $catch); - } - - if (null === $entry) { - $this->record($request, 'miss'); - - return $this->fetch($request, $catch); - } - - if (!$this->isFreshEnough($request, $entry)) { - $this->record($request, 'stale'); - - return $this->validate($request, $entry, $catch); - } - - $this->record($request, 'fresh'); - - $entry->headers->set('Age', $entry->getAge()); - - return $entry; - } - - /** - * Validates that a cache entry is fresh. - * - * The original request is used as a template for a conditional - * GET request with the backend. - * - * @param bool $catch Whether to process exceptions - * - * @return Response A Response instance - */ - protected function validate(Request $request, Response $entry, bool $catch = false) - { - $subRequest = clone $request; - - // send no head requests because we want content - if ('HEAD' === $request->getMethod()) { - $subRequest->setMethod('GET'); - } - - // add our cached last-modified validator - if ($entry->headers->has('Last-Modified')) { - $subRequest->headers->set('if_modified_since', $entry->headers->get('Last-Modified')); - } - - // Add our cached etag validator to the environment. - // We keep the etags from the client to handle the case when the client - // has a different private valid entry which is not cached here. - $cachedEtags = $entry->getEtag() ? [$entry->getEtag()] : []; - $requestEtags = $request->getETags(); - if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) { - $subRequest->headers->set('if_none_match', implode(', ', $etags)); - } - - $response = $this->forward($subRequest, $catch, $entry); - - if (304 == $response->getStatusCode()) { - $this->record($request, 'valid'); - - // return the response and not the cache entry if the response is valid but not cached - $etag = $response->getEtag(); - if ($etag && \in_array($etag, $requestEtags) && !\in_array($etag, $cachedEtags)) { - return $response; - } - - $entry = clone $entry; - $entry->headers->remove('Date'); - - foreach (['Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified'] as $name) { - if ($response->headers->has($name)) { - $entry->headers->set($name, $response->headers->get($name)); - } - } - - $response = $entry; - } else { - $this->record($request, 'invalid'); - } - - if ($response->isCacheable()) { - $this->store($request, $response); - } - - return $response; - } - - /** - * Unconditionally fetches a fresh response from the backend and - * stores it in the cache if is cacheable. - * - * @param bool $catch Whether to process exceptions - * - * @return Response A Response instance - */ - protected function fetch(Request $request, bool $catch = false) - { - $subRequest = clone $request; - - // send no head requests because we want content - if ('HEAD' === $request->getMethod()) { - $subRequest->setMethod('GET'); - } - - // avoid that the backend sends no content - $subRequest->headers->remove('if_modified_since'); - $subRequest->headers->remove('if_none_match'); - - $response = $this->forward($subRequest, $catch); - - if ($response->isCacheable()) { - $this->store($request, $response); - } - - return $response; - } - - /** - * Forwards the Request to the backend and returns the Response. - * - * All backend requests (cache passes, fetches, cache validations) - * run through this method. - * - * @param bool $catch Whether to catch exceptions or not - * @param Response|null $entry A Response instance (the stale entry if present, null otherwise) - * - * @return Response A Response instance - */ - protected function forward(Request $request, bool $catch = false, Response $entry = null) - { - if ($this->surrogate) { - $this->surrogate->addSurrogateCapability($request); - } - - // always a "master" request (as the real master request can be in cache) - $response = SubRequestHandler::handle($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $catch); - - // we don't implement the stale-if-error on Requests, which is nonetheless part of the RFC - if (null !== $entry && \in_array($response->getStatusCode(), [500, 502, 503, 504])) { - if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) { - $age = $this->options['stale_if_error']; - } - - if (abs($entry->getTtl()) < $age) { - $this->record($request, 'stale-if-error'); - - return $entry; - } - } - - /* - RFC 7231 Sect. 7.1.1.2 says that a server that does not have a reasonably accurate - clock MUST NOT send a "Date" header, although it MUST send one in most other cases - except for 1xx or 5xx responses where it MAY do so. - - Anyway, a client that received a message without a "Date" header MUST add it. - */ - if (!$response->headers->has('Date')) { - $response->setDate(\DateTime::createFromFormat('U', time())); - } - - $this->processResponseBody($request, $response); - - if ($this->isPrivateRequest($request) && !$response->headers->hasCacheControlDirective('public')) { - $response->setPrivate(); - } elseif ($this->options['default_ttl'] > 0 && null === $response->getTtl() && !$response->headers->getCacheControlDirective('must-revalidate')) { - $response->setTtl($this->options['default_ttl']); - } - - return $response; - } - - /** - * Checks whether the cache entry is "fresh enough" to satisfy the Request. - * - * @return bool true if the cache entry if fresh enough, false otherwise - */ - protected function isFreshEnough(Request $request, Response $entry) - { - if (!$entry->isFresh()) { - return $this->lock($request, $entry); - } - - if ($this->options['allow_revalidate'] && null !== $maxAge = $request->headers->getCacheControlDirective('max-age')) { - return $maxAge > 0 && $maxAge >= $entry->getAge(); - } - - return true; - } - - /** - * Locks a Request during the call to the backend. - * - * @return bool true if the cache entry can be returned even if it is staled, false otherwise - */ - protected function lock(Request $request, Response $entry) - { - // try to acquire a lock to call the backend - $lock = $this->store->lock($request); - - if (true === $lock) { - // we have the lock, call the backend - return false; - } - - // there is already another process calling the backend - - // May we serve a stale response? - if ($this->mayServeStaleWhileRevalidate($entry)) { - $this->record($request, 'stale-while-revalidate'); - - return true; - } - - // wait for the lock to be released - if ($this->waitForLock($request)) { - // replace the current entry with the fresh one - $new = $this->lookup($request); - $entry->headers = $new->headers; - $entry->setContent($new->getContent()); - $entry->setStatusCode($new->getStatusCode()); - $entry->setProtocolVersion($new->getProtocolVersion()); - foreach ($new->headers->getCookies() as $cookie) { - $entry->headers->setCookie($cookie); - } - } else { - // backend is slow as hell, send a 503 response (to avoid the dog pile effect) - $entry->setStatusCode(503); - $entry->setContent('503 Service Unavailable'); - $entry->headers->set('Retry-After', 10); - } - - return true; - } - - /** - * Writes the Response to the cache. - * - * @throws \Exception - */ - protected function store(Request $request, Response $response) - { - try { - $this->store->write($request, $response); - - $this->record($request, 'store'); - - $response->headers->set('Age', $response->getAge()); - } catch (\Exception $e) { - $this->record($request, 'store-failed'); - - if ($this->options['debug']) { - throw $e; - } - } - - // now that the response is cached, release the lock - $this->store->unlock($request); - } - - /** - * Restores the Response body. - */ - private function restoreResponseBody(Request $request, Response $response) - { - if ($response->headers->has('X-Body-Eval')) { - ob_start(); - - if ($response->headers->has('X-Body-File')) { - include $response->headers->get('X-Body-File'); - } else { - eval('; ?>'.$response->getContent().'setContent(ob_get_clean()); - $response->headers->remove('X-Body-Eval'); - if (!$response->headers->has('Transfer-Encoding')) { - $response->headers->set('Content-Length', \strlen($response->getContent())); - } - } elseif ($response->headers->has('X-Body-File')) { - // Response does not include possibly dynamic content (ESI, SSI), so we need - // not handle the content for HEAD requests - if (!$request->isMethod('HEAD')) { - $response->setContent(file_get_contents($response->headers->get('X-Body-File'))); - } - } else { - return; - } - - $response->headers->remove('X-Body-File'); - } - - protected function processResponseBody(Request $request, Response $response) - { - if (null !== $this->surrogate && $this->surrogate->needsParsing($response)) { - $this->surrogate->process($request, $response); - } - } - - /** - * Checks if the Request includes authorization or other sensitive information - * that should cause the Response to be considered private by default. - */ - private function isPrivateRequest(Request $request): bool - { - foreach ($this->options['private_headers'] as $key) { - $key = strtolower(str_replace('HTTP_', '', $key)); - - if ('cookie' === $key) { - if (\count($request->cookies->all())) { - return true; - } - } elseif ($request->headers->has($key)) { - return true; - } - } - - return false; - } - - /** - * Records that an event took place. - */ - private function record(Request $request, string $event) - { - $this->traces[$this->getTraceKey($request)][] = $event; - } - - /** - * Calculates the key we use in the "trace" array for a given request. - */ - private function getTraceKey(Request $request): string - { - $path = $request->getPathInfo(); - if ($qs = $request->getQueryString()) { - $path .= '?'.$qs; - } - - return $request->getMethod().' '.$path; - } - - /** - * Checks whether the given (cached) response may be served as "stale" when a revalidation - * is currently in progress. - */ - private function mayServeStaleWhileRevalidate(Response $entry): bool - { - $timeout = $entry->headers->getCacheControlDirective('stale-while-revalidate'); - - if (null === $timeout) { - $timeout = $this->options['stale_while_revalidate']; - } - - return abs($entry->getTtl()) < $timeout; - } - - /** - * Waits for the store to release a locked entry. - */ - private function waitForLock(Request $request): bool - { - $wait = 0; - while ($this->store->isLocked($request) && $wait < 100) { - usleep(50000); - ++$wait; - } - - return $wait < 100; - } -} diff --git a/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php b/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php deleted file mode 100644 index c30ffac..0000000 --- a/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php +++ /dev/null @@ -1,213 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Response; - -/** - * ResponseCacheStrategy knows how to compute the Response cache HTTP header - * based on the different response cache headers. - * - * This implementation changes the master response TTL to the smallest TTL received - * or force validation if one of the surrogates has validation cache strategy. - * - * @author Fabien Potencier - */ -class ResponseCacheStrategy implements ResponseCacheStrategyInterface -{ - /** - * Cache-Control headers that are sent to the final response if they appear in ANY of the responses. - */ - private static $overrideDirectives = ['private', 'no-cache', 'no-store', 'no-transform', 'must-revalidate', 'proxy-revalidate']; - - /** - * Cache-Control headers that are sent to the final response if they appear in ALL of the responses. - */ - private static $inheritDirectives = ['public', 'immutable']; - - private $embeddedResponses = 0; - private $isNotCacheableResponseEmbedded = false; - private $age = 0; - private $flagDirectives = [ - 'no-cache' => null, - 'no-store' => null, - 'no-transform' => null, - 'must-revalidate' => null, - 'proxy-revalidate' => null, - 'public' => null, - 'private' => null, - 'immutable' => null, - ]; - private $ageDirectives = [ - 'max-age' => null, - 's-maxage' => null, - 'expires' => null, - ]; - - /** - * {@inheritdoc} - */ - public function add(Response $response) - { - ++$this->embeddedResponses; - - foreach (self::$overrideDirectives as $directive) { - if ($response->headers->hasCacheControlDirective($directive)) { - $this->flagDirectives[$directive] = true; - } - } - - foreach (self::$inheritDirectives as $directive) { - if (false !== $this->flagDirectives[$directive]) { - $this->flagDirectives[$directive] = $response->headers->hasCacheControlDirective($directive); - } - } - - $age = $response->getAge(); - $this->age = max($this->age, $age); - - if ($this->willMakeFinalResponseUncacheable($response)) { - $this->isNotCacheableResponseEmbedded = true; - - return; - } - - $this->storeRelativeAgeDirective('max-age', $response->headers->getCacheControlDirective('max-age'), $age); - $this->storeRelativeAgeDirective('s-maxage', $response->headers->getCacheControlDirective('s-maxage') ?: $response->headers->getCacheControlDirective('max-age'), $age); - - $expires = $response->getExpires(); - $expires = null !== $expires ? (int) $expires->format('U') - (int) $response->getDate()->format('U') : null; - $this->storeRelativeAgeDirective('expires', $expires >= 0 ? $expires : null, 0); - } - - /** - * {@inheritdoc} - */ - public function update(Response $response) - { - // if we have no embedded Response, do nothing - if (0 === $this->embeddedResponses) { - return; - } - - // Remove validation related headers of the master response, - // because some of the response content comes from at least - // one embedded response (which likely has a different caching strategy). - $response->setEtag(null); - $response->setLastModified(null); - - $this->add($response); - - $response->headers->set('Age', $this->age); - - if ($this->isNotCacheableResponseEmbedded) { - if ($this->flagDirectives['no-store']) { - $response->headers->set('Cache-Control', 'no-cache, no-store, must-revalidate'); - } else { - $response->headers->set('Cache-Control', 'no-cache, must-revalidate'); - } - - return; - } - - $flags = array_filter($this->flagDirectives); - - if (isset($flags['must-revalidate'])) { - $flags['no-cache'] = true; - } - - $response->headers->set('Cache-Control', implode(', ', array_keys($flags))); - - $maxAge = null; - - if (is_numeric($this->ageDirectives['max-age'])) { - $maxAge = $this->ageDirectives['max-age'] + $this->age; - $response->headers->addCacheControlDirective('max-age', $maxAge); - } - - if (is_numeric($this->ageDirectives['s-maxage'])) { - $sMaxage = $this->ageDirectives['s-maxage'] + $this->age; - - if ($maxAge !== $sMaxage) { - $response->headers->addCacheControlDirective('s-maxage', $sMaxage); - } - } - - if (is_numeric($this->ageDirectives['expires'])) { - $date = clone $response->getDate(); - $date->modify('+'.($this->ageDirectives['expires'] + $this->age).' seconds'); - $response->setExpires($date); - } - } - - /** - * RFC2616, Section 13.4. - * - * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4 - */ - private function willMakeFinalResponseUncacheable(Response $response): bool - { - // RFC2616: A response received with a status code of 200, 203, 300, 301 or 410 - // MAY be stored by a cache […] unless a cache-control directive prohibits caching. - if ($response->headers->hasCacheControlDirective('no-cache') - || $response->headers->getCacheControlDirective('no-store') - ) { - return true; - } - - // Last-Modified and Etag headers cannot be merged, they render the response uncacheable - // by default (except if the response also has max-age etc.). - if (\in_array($response->getStatusCode(), [200, 203, 300, 301, 410]) - && null === $response->getLastModified() - && null === $response->getEtag() - ) { - return false; - } - - // RFC2616: A response received with any other status code (e.g. status codes 302 and 307) - // MUST NOT be returned in a reply to a subsequent request unless there are - // cache-control directives or another header(s) that explicitly allow it. - $cacheControl = ['max-age', 's-maxage', 'must-revalidate', 'proxy-revalidate', 'public', 'private']; - foreach ($cacheControl as $key) { - if ($response->headers->hasCacheControlDirective($key)) { - return false; - } - } - - if ($response->headers->has('Expires')) { - return false; - } - - return true; - } - - /** - * Store lowest max-age/s-maxage/expires for the final response. - * - * The response might have been stored in cache a while ago. To keep things comparable, - * we have to subtract the age so that the value is normalized for an age of 0. - * - * If the value is lower than the currently stored value, we update the value, to keep a rolling - * minimal value of each instruction. If the value is NULL, the directive will not be set on the final response. - */ - private function storeRelativeAgeDirective(string $directive, ?int $value, int $age) - { - if (null === $value) { - $this->ageDirectives[$directive] = false; - } - - if (false !== $this->ageDirectives[$directive]) { - $value -= $age; - $this->ageDirectives[$directive] = null !== $this->ageDirectives[$directive] ? min($this->ageDirectives[$directive], $value) : $value; - } - } -} diff --git a/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php b/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php deleted file mode 100644 index e282299..0000000 --- a/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * This code is partially based on the Rack-Cache library by Ryan Tomayko, - * which is released under the MIT license. - * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Response; - -/** - * ResponseCacheStrategyInterface implementations know how to compute the - * Response cache HTTP header based on the different response cache headers. - * - * @author Fabien Potencier - */ -interface ResponseCacheStrategyInterface -{ - /** - * Adds a Response. - */ - public function add(Response $response); - - /** - * Updates the Response HTTP headers based on the embedded Responses. - */ - public function update(Response $response); -} diff --git a/vendor/symfony/http-kernel/HttpCache/Ssi.php b/vendor/symfony/http-kernel/HttpCache/Ssi.php deleted file mode 100644 index 587c43a..0000000 --- a/vendor/symfony/http-kernel/HttpCache/Ssi.php +++ /dev/null @@ -1,100 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Ssi implements the SSI capabilities to Request and Response instances. - * - * @author Sebastian Krebs - */ -class Ssi extends AbstractSurrogate -{ - /** - * {@inheritdoc} - */ - public function getName() - { - return 'ssi'; - } - - /** - * {@inheritdoc} - */ - public function addSurrogateControl(Response $response) - { - if (false !== strpos($response->getContent(), '', $uri); - } - - /** - * {@inheritdoc} - */ - public function process(Request $request, Response $response) - { - $type = $response->headers->get('Content-Type'); - if (empty($type)) { - $type = 'text/html'; - } - - $parts = explode(';', $type); - if (!\in_array($parts[0], $this->contentTypes)) { - return $response; - } - - // we don't use a proper XML parser here as we can have SSI tags in a plain text response - $content = $response->getContent(); - - $chunks = preg_split('##', $content, -1, PREG_SPLIT_DELIM_CAPTURE); - $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]); - - $i = 1; - while (isset($chunks[$i])) { - $options = []; - preg_match_all('/(virtual)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER); - foreach ($matches as $set) { - $options[$set[1]] = $set[2]; - } - - if (!isset($options['virtual'])) { - throw new \RuntimeException('Unable to process an SSI tag without a "virtual" attribute.'); - } - - $chunks[$i] = sprintf('surrogate->handle($this, %s, \'\', false) ?>'."\n", - var_export($options['virtual'], true) - ); - ++$i; - $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]); - ++$i; - } - $content = implode('', $chunks); - - $response->setContent($content); - $response->headers->set('X-Body-Eval', 'SSI'); - - // remove SSI/1.0 from the Surrogate-Control header - $this->removeFromControl($response); - - return $response; - } -} diff --git a/vendor/symfony/http-kernel/HttpCache/Store.php b/vendor/symfony/http-kernel/HttpCache/Store.php deleted file mode 100644 index b7953e1..0000000 --- a/vendor/symfony/http-kernel/HttpCache/Store.php +++ /dev/null @@ -1,460 +0,0 @@ - - * - * This code is partially based on the Rack-Cache library by Ryan Tomayko, - * which is released under the MIT license. - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Store implements all the logic for storing cache metadata (Request and Response headers). - * - * @author Fabien Potencier - */ -class Store implements StoreInterface -{ - protected $root; - private $keyCache; - private $locks; - - /** - * @throws \RuntimeException - */ - public function __construct(string $root) - { - $this->root = $root; - if (!file_exists($this->root) && !@mkdir($this->root, 0777, true) && !is_dir($this->root)) { - throw new \RuntimeException(sprintf('Unable to create the store directory (%s).', $this->root)); - } - $this->keyCache = new \SplObjectStorage(); - $this->locks = []; - } - - /** - * Cleanups storage. - */ - public function cleanup() - { - // unlock everything - foreach ($this->locks as $lock) { - flock($lock, LOCK_UN); - fclose($lock); - } - - $this->locks = []; - } - - /** - * Tries to lock the cache for a given Request, without blocking. - * - * @return bool|string true if the lock is acquired, the path to the current lock otherwise - */ - public function lock(Request $request) - { - $key = $this->getCacheKey($request); - - if (!isset($this->locks[$key])) { - $path = $this->getPath($key); - if (!file_exists(\dirname($path)) && false === @mkdir(\dirname($path), 0777, true) && !is_dir(\dirname($path))) { - return $path; - } - $h = fopen($path, 'cb'); - if (!flock($h, LOCK_EX | LOCK_NB)) { - fclose($h); - - return $path; - } - - $this->locks[$key] = $h; - } - - return true; - } - - /** - * Releases the lock for the given Request. - * - * @return bool False if the lock file does not exist or cannot be unlocked, true otherwise - */ - public function unlock(Request $request) - { - $key = $this->getCacheKey($request); - - if (isset($this->locks[$key])) { - flock($this->locks[$key], LOCK_UN); - fclose($this->locks[$key]); - unset($this->locks[$key]); - - return true; - } - - return false; - } - - public function isLocked(Request $request) - { - $key = $this->getCacheKey($request); - - if (isset($this->locks[$key])) { - return true; // shortcut if lock held by this process - } - - if (!file_exists($path = $this->getPath($key))) { - return false; - } - - $h = fopen($path, 'rb'); - flock($h, LOCK_EX | LOCK_NB, $wouldBlock); - flock($h, LOCK_UN); // release the lock we just acquired - fclose($h); - - return (bool) $wouldBlock; - } - - /** - * Locates a cached Response for the Request provided. - * - * @return Response|null A Response instance, or null if no cache entry was found - */ - public function lookup(Request $request) - { - $key = $this->getCacheKey($request); - - if (!$entries = $this->getMetadata($key)) { - return null; - } - - // find a cached entry that matches the request. - $match = null; - foreach ($entries as $entry) { - if ($this->requestsMatch(isset($entry[1]['vary'][0]) ? implode(', ', $entry[1]['vary']) : '', $request->headers->all(), $entry[0])) { - $match = $entry; - - break; - } - } - - if (null === $match) { - return null; - } - - $headers = $match[1]; - if (file_exists($body = $this->getPath($headers['x-content-digest'][0]))) { - return $this->restoreResponse($headers, $body); - } - - // TODO the metaStore referenced an entity that doesn't exist in - // the entityStore. We definitely want to return nil but we should - // also purge the entry from the meta-store when this is detected. - return null; - } - - /** - * Writes a cache entry to the store for the given Request and Response. - * - * Existing entries are read and any that match the response are removed. This - * method calls write with the new list of cache entries. - * - * @return string The key under which the response is stored - * - * @throws \RuntimeException - */ - public function write(Request $request, Response $response) - { - $key = $this->getCacheKey($request); - $storedEnv = $this->persistRequest($request); - - // write the response body to the entity store if this is the original response - if (!$response->headers->has('X-Content-Digest')) { - $digest = $this->generateContentDigest($response); - - if (!$this->save($digest, $response->getContent())) { - throw new \RuntimeException('Unable to store the entity.'); - } - - $response->headers->set('X-Content-Digest', $digest); - - if (!$response->headers->has('Transfer-Encoding')) { - $response->headers->set('Content-Length', \strlen($response->getContent())); - } - } - - // read existing cache entries, remove non-varying, and add this one to the list - $entries = []; - $vary = $response->headers->get('vary'); - foreach ($this->getMetadata($key) as $entry) { - if (!isset($entry[1]['vary'][0])) { - $entry[1]['vary'] = ['']; - } - - if ($entry[1]['vary'][0] != $vary || !$this->requestsMatch($vary ?? '', $entry[0], $storedEnv)) { - $entries[] = $entry; - } - } - - $headers = $this->persistResponse($response); - unset($headers['age']); - - array_unshift($entries, [$storedEnv, $headers]); - - if (!$this->save($key, serialize($entries))) { - throw new \RuntimeException('Unable to store the metadata.'); - } - - return $key; - } - - /** - * Returns content digest for $response. - * - * @return string - */ - protected function generateContentDigest(Response $response) - { - return 'en'.hash('sha256', $response->getContent()); - } - - /** - * Invalidates all cache entries that match the request. - * - * @throws \RuntimeException - */ - public function invalidate(Request $request) - { - $modified = false; - $key = $this->getCacheKey($request); - - $entries = []; - foreach ($this->getMetadata($key) as $entry) { - $response = $this->restoreResponse($entry[1]); - if ($response->isFresh()) { - $response->expire(); - $modified = true; - $entries[] = [$entry[0], $this->persistResponse($response)]; - } else { - $entries[] = $entry; - } - } - - if ($modified && !$this->save($key, serialize($entries))) { - throw new \RuntimeException('Unable to store the metadata.'); - } - } - - /** - * Determines whether two Request HTTP header sets are non-varying based on - * the vary response header value provided. - * - * @param string|null $vary A Response vary header - * @param array $env1 A Request HTTP header array - * @param array $env2 A Request HTTP header array - */ - private function requestsMatch(?string $vary, array $env1, array $env2): bool - { - if (empty($vary)) { - return true; - } - - foreach (preg_split('/[\s,]+/', $vary) as $header) { - $key = str_replace('_', '-', strtolower($header)); - $v1 = isset($env1[$key]) ? $env1[$key] : null; - $v2 = isset($env2[$key]) ? $env2[$key] : null; - if ($v1 !== $v2) { - return false; - } - } - - return true; - } - - /** - * Gets all data associated with the given key. - * - * Use this method only if you know what you are doing. - */ - private function getMetadata(string $key): array - { - if (!$entries = $this->load($key)) { - return []; - } - - return unserialize($entries); - } - - /** - * Purges data for the given URL. - * - * This method purges both the HTTP and the HTTPS version of the cache entry. - * - * @return bool true if the URL exists with either HTTP or HTTPS scheme and has been purged, false otherwise - */ - public function purge(string $url) - { - $http = preg_replace('#^https:#', 'http:', $url); - $https = preg_replace('#^http:#', 'https:', $url); - - $purgedHttp = $this->doPurge($http); - $purgedHttps = $this->doPurge($https); - - return $purgedHttp || $purgedHttps; - } - - /** - * Purges data for the given URL. - */ - private function doPurge(string $url): bool - { - $key = $this->getCacheKey(Request::create($url)); - if (isset($this->locks[$key])) { - flock($this->locks[$key], LOCK_UN); - fclose($this->locks[$key]); - unset($this->locks[$key]); - } - - if (file_exists($path = $this->getPath($key))) { - unlink($path); - - return true; - } - - return false; - } - - /** - * Loads data for the given key. - */ - private function load(string $key): ?string - { - $path = $this->getPath($key); - - return file_exists($path) && false !== ($contents = file_get_contents($path)) ? $contents : null; - } - - /** - * Save data for the given key. - */ - private function save(string $key, string $data): bool - { - $path = $this->getPath($key); - - if (isset($this->locks[$key])) { - $fp = $this->locks[$key]; - @ftruncate($fp, 0); - @fseek($fp, 0); - $len = @fwrite($fp, $data); - if (\strlen($data) !== $len) { - @ftruncate($fp, 0); - - return false; - } - } else { - if (!file_exists(\dirname($path)) && false === @mkdir(\dirname($path), 0777, true) && !is_dir(\dirname($path))) { - return false; - } - - $tmpFile = tempnam(\dirname($path), basename($path)); - if (false === $fp = @fopen($tmpFile, 'wb')) { - @unlink($tmpFile); - - return false; - } - @fwrite($fp, $data); - @fclose($fp); - - if ($data != file_get_contents($tmpFile)) { - @unlink($tmpFile); - - return false; - } - - if (false === @rename($tmpFile, $path)) { - @unlink($tmpFile); - - return false; - } - } - - @chmod($path, 0666 & ~umask()); - - return true; - } - - public function getPath(string $key) - { - return $this->root.\DIRECTORY_SEPARATOR.substr($key, 0, 2).\DIRECTORY_SEPARATOR.substr($key, 2, 2).\DIRECTORY_SEPARATOR.substr($key, 4, 2).\DIRECTORY_SEPARATOR.substr($key, 6); - } - - /** - * Generates a cache key for the given Request. - * - * This method should return a key that must only depend on a - * normalized version of the request URI. - * - * If the same URI can have more than one representation, based on some - * headers, use a Vary header to indicate them, and each representation will - * be stored independently under the same cache key. - * - * @return string A key for the given Request - */ - protected function generateCacheKey(Request $request) - { - return 'md'.hash('sha256', $request->getUri()); - } - - /** - * Returns a cache key for the given Request. - */ - private function getCacheKey(Request $request): string - { - if (isset($this->keyCache[$request])) { - return $this->keyCache[$request]; - } - - return $this->keyCache[$request] = $this->generateCacheKey($request); - } - - /** - * Persists the Request HTTP headers. - */ - private function persistRequest(Request $request): array - { - return $request->headers->all(); - } - - /** - * Persists the Response HTTP headers. - */ - private function persistResponse(Response $response): array - { - $headers = $response->headers->all(); - $headers['X-Status'] = [$response->getStatusCode()]; - - return $headers; - } - - /** - * Restores a Response from the HTTP headers and body. - */ - private function restoreResponse(array $headers, string $body = null): Response - { - $status = $headers['X-Status'][0]; - unset($headers['X-Status']); - - if (null !== $body) { - $headers['X-Body-File'] = [$body]; - } - - return new Response($body, $status, $headers); - } -} diff --git a/vendor/symfony/http-kernel/HttpCache/StoreInterface.php b/vendor/symfony/http-kernel/HttpCache/StoreInterface.php deleted file mode 100644 index 49d88c2..0000000 --- a/vendor/symfony/http-kernel/HttpCache/StoreInterface.php +++ /dev/null @@ -1,81 +0,0 @@ - - * - * This code is partially based on the Rack-Cache library by Ryan Tomayko, - * which is released under the MIT license. - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Interface implemented by HTTP cache stores. - * - * @author Fabien Potencier - */ -interface StoreInterface -{ - /** - * Locates a cached Response for the Request provided. - * - * @return Response|null A Response instance, or null if no cache entry was found - */ - public function lookup(Request $request); - - /** - * Writes a cache entry to the store for the given Request and Response. - * - * Existing entries are read and any that match the response are removed. This - * method calls write with the new list of cache entries. - * - * @return string The key under which the response is stored - */ - public function write(Request $request, Response $response); - - /** - * Invalidates all cache entries that match the request. - */ - public function invalidate(Request $request); - - /** - * Locks the cache for a given Request. - * - * @return bool|string true if the lock is acquired, the path to the current lock otherwise - */ - public function lock(Request $request); - - /** - * Releases the lock for the given Request. - * - * @return bool False if the lock file does not exist or cannot be unlocked, true otherwise - */ - public function unlock(Request $request); - - /** - * Returns whether or not a lock exists. - * - * @return bool true if lock exists, false otherwise - */ - public function isLocked(Request $request); - - /** - * Purges data for the given URL. - * - * @return bool true if the URL exists and has been purged, false otherwise - */ - public function purge(string $url); - - /** - * Cleanups storage. - */ - public function cleanup(); -} diff --git a/vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php b/vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php deleted file mode 100644 index 294b964..0000000 --- a/vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php +++ /dev/null @@ -1,91 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\IpUtils; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelInterface; - -/** - * @author Nicolas Grekas - * - * @internal - */ -class SubRequestHandler -{ - public static function handle(HttpKernelInterface $kernel, Request $request, int $type, bool $catch): Response - { - // save global state related to trusted headers and proxies - $trustedProxies = Request::getTrustedProxies(); - $trustedHeaderSet = Request::getTrustedHeaderSet(); - - // remove untrusted values - $remoteAddr = $request->server->get('REMOTE_ADDR'); - if (!IpUtils::checkIp($remoteAddr, $trustedProxies)) { - $trustedHeaders = [ - 'FORWARDED' => $trustedHeaderSet & Request::HEADER_FORWARDED, - 'X_FORWARDED_FOR' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_FOR, - 'X_FORWARDED_HOST' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_HOST, - 'X_FORWARDED_PROTO' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PROTO, - 'X_FORWARDED_PORT' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PORT, - ]; - foreach (array_filter($trustedHeaders) as $name => $key) { - $request->headers->remove($name); - $request->server->remove('HTTP_'.$name); - } - } - - // compute trusted values, taking any trusted proxies into account - $trustedIps = []; - $trustedValues = []; - foreach (array_reverse($request->getClientIps()) as $ip) { - $trustedIps[] = $ip; - $trustedValues[] = sprintf('for="%s"', $ip); - } - if ($ip !== $remoteAddr) { - $trustedIps[] = $remoteAddr; - $trustedValues[] = sprintf('for="%s"', $remoteAddr); - } - - // set trusted values, reusing as much as possible the global trusted settings - if (Request::HEADER_FORWARDED & $trustedHeaderSet) { - $trustedValues[0] .= sprintf(';host="%s";proto=%s', $request->getHttpHost(), $request->getScheme()); - $request->headers->set('Forwarded', $v = implode(', ', $trustedValues)); - $request->server->set('HTTP_FORWARDED', $v); - } - if (Request::HEADER_X_FORWARDED_FOR & $trustedHeaderSet) { - $request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps)); - $request->server->set('HTTP_X_FORWARDED_FOR', $v); - } elseif (!(Request::HEADER_FORWARDED & $trustedHeaderSet)) { - Request::setTrustedProxies($trustedProxies, $trustedHeaderSet | Request::HEADER_X_FORWARDED_FOR); - $request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps)); - $request->server->set('HTTP_X_FORWARDED_FOR', $v); - } - - // fix the client IP address by setting it to 127.0.0.1, - // which is the core responsibility of this method - $request->server->set('REMOTE_ADDR', '127.0.0.1'); - - // ensure 127.0.0.1 is set as trusted proxy - if (!IpUtils::checkIp('127.0.0.1', $trustedProxies)) { - Request::setTrustedProxies(array_merge($trustedProxies, ['127.0.0.1']), Request::getTrustedHeaderSet()); - } - - try { - return $kernel->handle($request, $type, $catch); - } finally { - // restore global state - Request::setTrustedProxies($trustedProxies, $trustedHeaderSet); - } - } -} diff --git a/vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php b/vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php deleted file mode 100644 index 53a7e2a..0000000 --- a/vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\HttpCache; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -interface SurrogateInterface -{ - /** - * Returns surrogate name. - * - * @return string - */ - public function getName(); - - /** - * Returns a new cache strategy instance. - * - * @return ResponseCacheStrategyInterface A ResponseCacheStrategyInterface instance - */ - public function createCacheStrategy(); - - /** - * Checks that at least one surrogate has Surrogate capability. - * - * @return bool true if one surrogate has Surrogate capability, false otherwise - */ - public function hasSurrogateCapability(Request $request); - - /** - * Adds Surrogate-capability to the given Request. - */ - public function addSurrogateCapability(Request $request); - - /** - * Adds HTTP headers to specify that the Response needs to be parsed for Surrogate. - * - * This method only adds an Surrogate HTTP header if the Response has some Surrogate tags. - */ - public function addSurrogateControl(Response $response); - - /** - * Checks that the Response needs to be parsed for Surrogate tags. - * - * @return bool true if the Response needs to be parsed, false otherwise - */ - public function needsParsing(Response $response); - - /** - * Renders a Surrogate tag. - * - * @param string $alt An alternate URI - * @param string $comment A comment to add as an esi:include tag - * - * @return string - */ - public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = ''); - - /** - * Replaces a Response Surrogate tags with the included resource content. - * - * @return Response - */ - public function process(Request $request, Response $response); - - /** - * Handles a Surrogate from the cache. - * - * @param string $alt An alternative URI - * - * @return string - * - * @throws \RuntimeException - * @throws \Exception - */ - public function handle(HttpCache $cache, string $uri, string $alt, bool $ignoreErrors); -} diff --git a/vendor/symfony/http-kernel/HttpClientKernel.php b/vendor/symfony/http-kernel/HttpClientKernel.php deleted file mode 100644 index 10bac3a..0000000 --- a/vendor/symfony/http-kernel/HttpClientKernel.php +++ /dev/null @@ -1,106 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\HttpClient\HttpClient; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\ResponseHeaderBag; -use Symfony\Component\Mime\Part\AbstractPart; -use Symfony\Component\Mime\Part\DataPart; -use Symfony\Component\Mime\Part\Multipart\FormDataPart; -use Symfony\Component\Mime\Part\TextPart; -use Symfony\Contracts\HttpClient\HttpClientInterface; - -/** - * An implementation of a Symfony HTTP kernel using a "real" HTTP client. - * - * @author Fabien Potencier - */ -final class HttpClientKernel implements HttpKernelInterface -{ - private $client; - - public function __construct(HttpClientInterface $client = null) - { - if (!class_exists(HttpClient::class)) { - throw new \LogicException(sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__)); - } - - $this->client = $client ?? HttpClient::create(); - } - - public function handle(Request $request, int $type = HttpKernelInterface::MASTER_REQUEST, bool $catch = true): Response - { - $headers = $this->getHeaders($request); - $body = ''; - if (null !== $part = $this->getBody($request)) { - $headers = array_merge($headers, $part->getPreparedHeaders()->toArray()); - $body = $part->bodyToIterable(); - } - $response = $this->client->request($request->getMethod(), $request->getUri(), [ - 'headers' => $headers, - 'body' => $body, - 'max_redirects' => 0, - ] + $request->attributes->get('http_client_options', [])); - - $response = new Response($response->getContent(!$catch), $response->getStatusCode(), $response->getHeaders(!$catch)); - - $response->headers = new class($response->headers->all()) extends ResponseHeaderBag { - protected function computeCacheControlValue(): string - { - return $this->getCacheControlHeader(); // preserve the original value - } - }; - - return $response; - } - - private function getBody(Request $request): ?AbstractPart - { - if (\in_array($request->getMethod(), ['GET', 'HEAD'])) { - return null; - } - - if (!class_exists(AbstractPart::class)) { - throw new \LogicException('You cannot pass non-empty bodies as the Mime component is not installed. Try running "composer require symfony/mime".'); - } - - if ($content = $request->getContent()) { - return new TextPart($content, 'utf-8', 'plain', '8bit'); - } - - $fields = $request->request->all(); - foreach ($request->files->all() as $name => $file) { - $fields[$name] = DataPart::fromPath($file->getPathname(), $file->getClientOriginalName(), $file->getClientMimeType()); - } - - return new FormDataPart($fields); - } - - private function getHeaders(Request $request): array - { - $headers = []; - foreach ($request->headers as $key => $value) { - $headers[$key] = $value; - } - $cookies = []; - foreach ($request->cookies->all() as $name => $value) { - $cookies[] = $name.'='.$value; - } - if ($cookies) { - $headers['cookie'] = implode('; ', $cookies); - } - - return $headers; - } -} diff --git a/vendor/symfony/http-kernel/HttpKernel.php b/vendor/symfony/http-kernel/HttpKernel.php deleted file mode 100644 index 04b3183..0000000 --- a/vendor/symfony/http-kernel/HttpKernel.php +++ /dev/null @@ -1,282 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; -use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; -use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; -use Symfony\Component\HttpKernel\Event\ControllerEvent; -use Symfony\Component\HttpKernel\Event\ExceptionEvent; -use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\RequestEvent; -use Symfony\Component\HttpKernel\Event\ResponseEvent; -use Symfony\Component\HttpKernel\Event\TerminateEvent; -use Symfony\Component\HttpKernel\Event\ViewEvent; -use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Symfony\Component\HttpKernel\Exception\ControllerDoesNotReturnResponseException; -use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; - -/** - * HttpKernel notifies events to convert a Request object to a Response one. - * - * @author Fabien Potencier - */ -class HttpKernel implements HttpKernelInterface, TerminableInterface -{ - protected $dispatcher; - protected $resolver; - protected $requestStack; - private $argumentResolver; - - public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null, ArgumentResolverInterface $argumentResolver = null) - { - $this->dispatcher = $dispatcher; - $this->resolver = $resolver; - $this->requestStack = $requestStack ?: new RequestStack(); - $this->argumentResolver = $argumentResolver; - - if (null === $this->argumentResolver) { - $this->argumentResolver = new ArgumentResolver(); - } - } - - /** - * {@inheritdoc} - */ - public function handle(Request $request, int $type = HttpKernelInterface::MASTER_REQUEST, bool $catch = true) - { - $request->headers->set('X-Php-Ob-Level', (string) ob_get_level()); - - try { - return $this->handleRaw($request, $type); - } catch (\Exception $e) { - if ($e instanceof RequestExceptionInterface) { - $e = new BadRequestHttpException($e->getMessage(), $e); - } - if (false === $catch) { - $this->finishRequest($request, $type); - - throw $e; - } - - return $this->handleThrowable($e, $request, $type); - } - } - - /** - * {@inheritdoc} - */ - public function terminate(Request $request, Response $response) - { - $this->dispatcher->dispatch(new TerminateEvent($this, $request, $response), KernelEvents::TERMINATE); - } - - /** - * @internal - */ - public function terminateWithException(\Throwable $exception, Request $request = null) - { - if (!$request = $request ?: $this->requestStack->getMasterRequest()) { - throw $exception; - } - - $response = $this->handleThrowable($exception, $request, self::MASTER_REQUEST); - - $response->sendHeaders(); - $response->sendContent(); - - $this->terminate($request, $response); - } - - /** - * Handles a request to convert it to a response. - * - * Exceptions are not caught. - * - * @throws \LogicException If one of the listener does not behave as expected - * @throws NotFoundHttpException When controller cannot be found - */ - private function handleRaw(Request $request, int $type = self::MASTER_REQUEST): Response - { - $this->requestStack->push($request); - - // request - $event = new RequestEvent($this, $request, $type); - $this->dispatcher->dispatch($event, KernelEvents::REQUEST); - - if ($event->hasResponse()) { - return $this->filterResponse($event->getResponse(), $request, $type); - } - - // load controller - if (false === $controller = $this->resolver->getController($request)) { - throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". The route is wrongly configured.', $request->getPathInfo())); - } - - $event = new ControllerEvent($this, $controller, $request, $type); - $this->dispatcher->dispatch($event, KernelEvents::CONTROLLER); - $controller = $event->getController(); - - // controller arguments - $arguments = $this->argumentResolver->getArguments($request, $controller); - - $event = new ControllerArgumentsEvent($this, $controller, $arguments, $request, $type); - $this->dispatcher->dispatch($event, KernelEvents::CONTROLLER_ARGUMENTS); - $controller = $event->getController(); - $arguments = $event->getArguments(); - - // call controller - $response = $controller(...$arguments); - - // view - if (!$response instanceof Response) { - $event = new ViewEvent($this, $request, $type, $response); - $this->dispatcher->dispatch($event, KernelEvents::VIEW); - - if ($event->hasResponse()) { - $response = $event->getResponse(); - } else { - $msg = sprintf('The controller must return a "Symfony\Component\HttpFoundation\Response" object but it returned %s.', $this->varToString($response)); - - // the user may have forgotten to return something - if (null === $response) { - $msg .= ' Did you forget to add a return statement somewhere in your controller?'; - } - - throw new ControllerDoesNotReturnResponseException($msg, $controller, __FILE__, __LINE__ - 17); - } - } - - return $this->filterResponse($response, $request, $type); - } - - /** - * Filters a response object. - * - * @throws \RuntimeException if the passed object is not a Response instance - */ - private function filterResponse(Response $response, Request $request, int $type): Response - { - $event = new ResponseEvent($this, $request, $type, $response); - - $this->dispatcher->dispatch($event, KernelEvents::RESPONSE); - - $this->finishRequest($request, $type); - - return $event->getResponse(); - } - - /** - * Publishes the finish request event, then pop the request from the stack. - * - * Note that the order of the operations is important here, otherwise - * operations such as {@link RequestStack::getParentRequest()} can lead to - * weird results. - */ - private function finishRequest(Request $request, int $type) - { - $this->dispatcher->dispatch(new FinishRequestEvent($this, $request, $type), KernelEvents::FINISH_REQUEST); - $this->requestStack->pop(); - } - - /** - * Handles a throwable by trying to convert it to a Response. - * - * @throws \Exception - */ - private function handleThrowable(\Throwable $e, Request $request, int $type): Response - { - $event = new ExceptionEvent($this, $request, $type, $e); - $this->dispatcher->dispatch($event, KernelEvents::EXCEPTION); - - // a listener might have replaced the exception - $e = $event->getThrowable(); - - if (!$event->hasResponse()) { - $this->finishRequest($request, $type); - - throw $e; - } - - $response = $event->getResponse(); - - // the developer asked for a specific status code - if (!$event->isAllowingCustomResponseCode() && !$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) { - // ensure that we actually have an error response - if ($e instanceof HttpExceptionInterface) { - // keep the HTTP status code and headers - $response->setStatusCode($e->getStatusCode()); - $response->headers->add($e->getHeaders()); - } else { - $response->setStatusCode(500); - } - } - - try { - return $this->filterResponse($response, $request, $type); - } catch (\Exception $e) { - return $response; - } - } - - /** - * Returns a human-readable string for the specified variable. - */ - private function varToString($var): string - { - if (\is_object($var)) { - return sprintf('an object of type %s', \get_class($var)); - } - - if (\is_array($var)) { - $a = []; - foreach ($var as $k => $v) { - $a[] = sprintf('%s => ...', $k); - } - - return sprintf('an array ([%s])', mb_substr(implode(', ', $a), 0, 255)); - } - - if (\is_resource($var)) { - return sprintf('a resource (%s)', get_resource_type($var)); - } - - if (null === $var) { - return 'null'; - } - - if (false === $var) { - return 'a boolean value (false)'; - } - - if (true === $var) { - return 'a boolean value (true)'; - } - - if (\is_string($var)) { - return sprintf('a string ("%s%s")', mb_substr($var, 0, 255), mb_strlen($var) > 255 ? '...' : ''); - } - - if (is_numeric($var)) { - return sprintf('a number (%s)', (string) $var); - } - - return (string) $var; - } -} diff --git a/vendor/symfony/http-kernel/HttpKernelBrowser.php b/vendor/symfony/http-kernel/HttpKernelBrowser.php deleted file mode 100644 index d28be99..0000000 --- a/vendor/symfony/http-kernel/HttpKernelBrowser.php +++ /dev/null @@ -1,199 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\BrowserKit\AbstractBrowser; -use Symfony\Component\BrowserKit\CookieJar; -use Symfony\Component\BrowserKit\History; -use Symfony\Component\BrowserKit\Request as DomRequest; -use Symfony\Component\BrowserKit\Response as DomResponse; -use Symfony\Component\HttpFoundation\File\UploadedFile; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Simulates a browser and makes requests to an HttpKernel instance. - * - * @author Fabien Potencier - * - * @method Request getRequest() A Request instance - * @method Response getResponse() A Response instance - */ -class HttpKernelBrowser extends AbstractBrowser -{ - protected $kernel; - private $catchExceptions = true; - - /** - * @param array $server The server parameters (equivalent of $_SERVER) - */ - public function __construct(HttpKernelInterface $kernel, array $server = [], History $history = null, CookieJar $cookieJar = null) - { - // These class properties must be set before calling the parent constructor, as it may depend on it. - $this->kernel = $kernel; - $this->followRedirects = false; - - parent::__construct($server, $history, $cookieJar); - } - - /** - * Sets whether to catch exceptions when the kernel is handling a request. - */ - public function catchExceptions(bool $catchExceptions) - { - $this->catchExceptions = $catchExceptions; - } - - /** - * Makes a request. - * - * @return Response A Response instance - */ - protected function doRequest($request) - { - $response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $this->catchExceptions); - - if ($this->kernel instanceof TerminableInterface) { - $this->kernel->terminate($request, $response); - } - - return $response; - } - - /** - * Returns the script to execute when the request must be insulated. - * - * @return string - */ - protected function getScript($request) - { - $kernel = var_export(serialize($this->kernel), true); - $request = var_export(serialize($request), true); - - $errorReporting = error_reporting(); - - $requires = ''; - foreach (get_declared_classes() as $class) { - if (0 === strpos($class, 'ComposerAutoloaderInit')) { - $r = new \ReflectionClass($class); - $file = \dirname($r->getFileName(), 2).'/autoload.php'; - if (file_exists($file)) { - $requires .= 'require_once '.var_export($file, true).";\n"; - } - } - } - - if (!$requires) { - throw new \RuntimeException('Composer autoloader not found.'); - } - - $code = <<getHandleScript(); - } - - protected function getHandleScript() - { - return <<<'EOF' -$response = $kernel->handle($request); - -if ($kernel instanceof Symfony\Component\HttpKernel\TerminableInterface) { - $kernel->terminate($request, $response); -} - -echo serialize($response); -EOF; - } - - /** - * Converts the BrowserKit request to a HttpKernel request. - * - * @return Request A Request instance - */ - protected function filterRequest(DomRequest $request) - { - $httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $request->getServer(), $request->getContent()); - - foreach ($this->filterFiles($httpRequest->files->all()) as $key => $value) { - $httpRequest->files->set($key, $value); - } - - return $httpRequest; - } - - /** - * Filters an array of files. - * - * This method created test instances of UploadedFile so that the move() - * method can be called on those instances. - * - * If the size of a file is greater than the allowed size (from php.ini) then - * an invalid UploadedFile is returned with an error set to UPLOAD_ERR_INI_SIZE. - * - * @see UploadedFile - * - * @return array An array with all uploaded files marked as already moved - */ - protected function filterFiles(array $files) - { - $filtered = []; - foreach ($files as $key => $value) { - if (\is_array($value)) { - $filtered[$key] = $this->filterFiles($value); - } elseif ($value instanceof UploadedFile) { - if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) { - $filtered[$key] = new UploadedFile( - '', - $value->getClientOriginalName(), - $value->getClientMimeType(), - UPLOAD_ERR_INI_SIZE, - true - ); - } else { - $filtered[$key] = new UploadedFile( - $value->getPathname(), - $value->getClientOriginalName(), - $value->getClientMimeType(), - $value->getError(), - true - ); - } - } - } - - return $filtered; - } - - /** - * Converts the HttpKernel response to a BrowserKit response. - * - * @return DomResponse A DomResponse instance - */ - protected function filterResponse($response) - { - // this is needed to support StreamedResponse - ob_start(); - $response->sendContent(); - $content = ob_get_clean(); - - return new DomResponse($content, $response->getStatusCode(), $response->headers->all()); - } -} diff --git a/vendor/symfony/http-kernel/HttpKernelInterface.php b/vendor/symfony/http-kernel/HttpKernelInterface.php deleted file mode 100644 index a75d1a8..0000000 --- a/vendor/symfony/http-kernel/HttpKernelInterface.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * HttpKernelInterface handles a Request to convert it to a Response. - * - * @author Fabien Potencier - */ -interface HttpKernelInterface -{ - const MASTER_REQUEST = 1; - const SUB_REQUEST = 2; - - /** - * Handles a Request to convert it to a Response. - * - * When $catch is true, the implementation must catch all exceptions - * and do its best to convert them to a Response instance. - * - * @param int $type The type of the request - * (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) - * @param bool $catch Whether to catch exceptions or not - * - * @return Response A Response instance - * - * @throws \Exception When an Exception occurs during processing - */ - public function handle(Request $request, int $type = self::MASTER_REQUEST, bool $catch = true); -} diff --git a/vendor/symfony/http-kernel/Kernel.php b/vendor/symfony/http-kernel/Kernel.php deleted file mode 100644 index 2394fac..0000000 --- a/vendor/symfony/http-kernel/Kernel.php +++ /dev/null @@ -1,825 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; -use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; -use Symfony\Component\Config\ConfigCache; -use Symfony\Component\Config\Loader\DelegatingLoader; -use Symfony\Component\Config\Loader\LoaderResolver; -use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\PassConfig; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Dumper\PhpDumper; -use Symfony\Component\DependencyInjection\Loader\ClosureLoader; -use Symfony\Component\DependencyInjection\Loader\DirectoryLoader; -use Symfony\Component\DependencyInjection\Loader\GlobFileLoader; -use Symfony\Component\DependencyInjection\Loader\IniFileLoader; -use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; -use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; -use Symfony\Component\ErrorHandler\DebugClassLoader; -use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Bundle\BundleInterface; -use Symfony\Component\HttpKernel\Config\FileLocator; -use Symfony\Component\HttpKernel\DependencyInjection\AddAnnotatedClassesToCachePass; -use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; - -/** - * The Kernel is the heart of the Symfony system. - * - * It manages an environment made of bundles. - * - * Environment names must always start with a letter and - * they must only contain letters and numbers. - * - * @author Fabien Potencier - */ -abstract class Kernel implements KernelInterface, RebootableInterface, TerminableInterface -{ - /** - * @var BundleInterface[] - */ - protected $bundles = []; - - protected $container; - protected $environment; - protected $debug; - protected $booted = false; - protected $startTime; - - private $projectDir; - private $warmupDir; - private $requestStackSize = 0; - private $resetServices = false; - - private static $freshCache = []; - - const VERSION = '5.0.2'; - const VERSION_ID = 50002; - const MAJOR_VERSION = 5; - const MINOR_VERSION = 0; - const RELEASE_VERSION = 2; - const EXTRA_VERSION = ''; - - const END_OF_MAINTENANCE = '07/2020'; - const END_OF_LIFE = '07/2020'; - - public function __construct(string $environment, bool $debug) - { - $this->environment = $environment; - $this->debug = $debug; - } - - public function __clone() - { - $this->booted = false; - $this->container = null; - $this->requestStackSize = 0; - $this->resetServices = false; - } - - /** - * {@inheritdoc} - */ - public function boot() - { - if (true === $this->booted) { - if (!$this->requestStackSize && $this->resetServices) { - if ($this->container->has('services_resetter')) { - $this->container->get('services_resetter')->reset(); - } - $this->resetServices = false; - if ($this->debug) { - $this->startTime = microtime(true); - } - } - - return; - } - if ($this->debug) { - $this->startTime = microtime(true); - } - if ($this->debug && !isset($_ENV['SHELL_VERBOSITY']) && !isset($_SERVER['SHELL_VERBOSITY'])) { - putenv('SHELL_VERBOSITY=3'); - $_ENV['SHELL_VERBOSITY'] = 3; - $_SERVER['SHELL_VERBOSITY'] = 3; - } - - // init bundles - $this->initializeBundles(); - - // init container - $this->initializeContainer(); - - foreach ($this->getBundles() as $bundle) { - $bundle->setContainer($this->container); - $bundle->boot(); - } - - $this->booted = true; - } - - /** - * {@inheritdoc} - */ - public function reboot(?string $warmupDir) - { - $this->shutdown(); - $this->warmupDir = $warmupDir; - $this->boot(); - } - - /** - * {@inheritdoc} - */ - public function terminate(Request $request, Response $response) - { - if (false === $this->booted) { - return; - } - - if ($this->getHttpKernel() instanceof TerminableInterface) { - $this->getHttpKernel()->terminate($request, $response); - } - } - - /** - * {@inheritdoc} - */ - public function shutdown() - { - if (false === $this->booted) { - return; - } - - $this->booted = false; - - foreach ($this->getBundles() as $bundle) { - $bundle->shutdown(); - $bundle->setContainer(null); - } - - $this->container = null; - $this->requestStackSize = 0; - $this->resetServices = false; - } - - /** - * {@inheritdoc} - */ - public function handle(Request $request, int $type = HttpKernelInterface::MASTER_REQUEST, bool $catch = true) - { - $this->boot(); - ++$this->requestStackSize; - $this->resetServices = true; - - try { - return $this->getHttpKernel()->handle($request, $type, $catch); - } finally { - --$this->requestStackSize; - } - } - - /** - * Gets a HTTP kernel from the container. - * - * @return HttpKernelInterface - */ - protected function getHttpKernel() - { - return $this->container->get('http_kernel'); - } - - /** - * {@inheritdoc} - */ - public function getBundles() - { - return $this->bundles; - } - - /** - * {@inheritdoc} - */ - public function getBundle(string $name) - { - if (!isset($this->bundles[$name])) { - $class = \get_class($this); - $class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; - - throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, $class)); - } - - return $this->bundles[$name]; - } - - /** - * {@inheritdoc} - */ - public function locateResource(string $name) - { - if ('@' !== $name[0]) { - throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name)); - } - - if (false !== strpos($name, '..')) { - throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name)); - } - - $bundleName = substr($name, 1); - $path = ''; - if (false !== strpos($bundleName, '/')) { - list($bundleName, $path) = explode('/', $bundleName, 2); - } - - $bundle = $this->getBundle($bundleName); - if (file_exists($file = $bundle->getPath().'/'.$path)) { - return $file; - } - - throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name)); - } - - /** - * {@inheritdoc} - */ - public function getEnvironment() - { - return $this->environment; - } - - /** - * {@inheritdoc} - */ - public function isDebug() - { - return $this->debug; - } - - /** - * Gets the application root dir (path of the project's composer file). - * - * @return string The project root dir - */ - public function getProjectDir() - { - if (null === $this->projectDir) { - $r = new \ReflectionObject($this); - - if (!file_exists($dir = $r->getFileName())) { - throw new \LogicException(sprintf('Cannot auto-detect project dir for kernel of class "%s".', $r->name)); - } - - $dir = $rootDir = \dirname($dir); - while (!file_exists($dir.'/composer.json')) { - if ($dir === \dirname($dir)) { - return $this->projectDir = $rootDir; - } - $dir = \dirname($dir); - } - $this->projectDir = $dir; - } - - return $this->projectDir; - } - - /** - * {@inheritdoc} - */ - public function getContainer() - { - if (!$this->container) { - throw new \LogicException('Cannot retrieve the container from a non-booted kernel.'); - } - - return $this->container; - } - - /** - * @internal - */ - public function setAnnotatedClassCache(array $annotatedClasses) - { - file_put_contents(($this->warmupDir ?: $this->getCacheDir()).'/annotations.map', sprintf('debug && null !== $this->startTime ? $this->startTime : -INF; - } - - /** - * {@inheritdoc} - */ - public function getCacheDir() - { - return $this->getProjectDir().'/var/cache/'.$this->environment; - } - - /** - * {@inheritdoc} - */ - public function getLogDir() - { - return $this->getProjectDir().'/var/log'; - } - - /** - * {@inheritdoc} - */ - public function getCharset() - { - return 'UTF-8'; - } - - /** - * Gets the patterns defining the classes to parse and cache for annotations. - */ - public function getAnnotatedClassesToCompile(): array - { - return []; - } - - /** - * Initializes bundles. - * - * @throws \LogicException if two bundles share a common name - */ - protected function initializeBundles() - { - // init bundles - $this->bundles = []; - foreach ($this->registerBundles() as $bundle) { - $name = $bundle->getName(); - if (isset($this->bundles[$name])) { - throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name)); - } - $this->bundles[$name] = $bundle; - } - } - - /** - * The extension point similar to the Bundle::build() method. - * - * Use this method to register compiler passes and manipulate the container during the building process. - */ - protected function build(ContainerBuilder $container) - { - } - - /** - * Gets the container class. - * - * @throws \InvalidArgumentException If the generated classname is invalid - * - * @return string The container class - */ - protected function getContainerClass() - { - $class = \get_class($this); - $class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).str_replace('.', '_', ContainerBuilder::hash($class)) : $class; - $class = str_replace('\\', '_', $class).ucfirst($this->environment).($this->debug ? 'Debug' : '').'Container'; - if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $class)) { - throw new \InvalidArgumentException(sprintf('The environment "%s" contains invalid characters, it can only contain characters allowed in PHP class names.', $this->environment)); - } - - return $class; - } - - /** - * Gets the container's base class. - * - * All names except Container must be fully qualified. - * - * @return string - */ - protected function getContainerBaseClass() - { - return 'Container'; - } - - /** - * Initializes the service container. - * - * The cached version of the service container is used when fresh, otherwise the - * container is built. - */ - protected function initializeContainer() - { - $class = $this->getContainerClass(); - $cacheDir = $this->warmupDir ?: $this->getCacheDir(); - $cache = new ConfigCache($cacheDir.'/'.$class.'.php', $this->debug); - $cachePath = $cache->getPath(); - - // Silence E_WARNING to ignore "include" failures - don't use "@" to prevent silencing fatal errors - $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); - - try { - if (file_exists($cachePath) && \is_object($this->container = include $cachePath) - && (!$this->debug || (self::$freshCache[$cachePath] ?? $cache->isFresh())) - ) { - self::$freshCache[$cachePath] = true; - $this->container->set('kernel', $this); - error_reporting($errorLevel); - - return; - } - } catch (\Throwable $e) { - } - - $oldContainer = \is_object($this->container) ? new \ReflectionClass($this->container) : $this->container = null; - - try { - is_dir($cacheDir) ?: mkdir($cacheDir, 0777, true); - - if ($lock = fopen($cachePath, 'w')) { - chmod($cachePath, 0666 & ~umask()); - flock($lock, LOCK_EX | LOCK_NB, $wouldBlock); - - if (!flock($lock, $wouldBlock ? LOCK_SH : LOCK_EX)) { - fclose($lock); - } else { - $cache = new class($cachePath, $this->debug) extends ConfigCache { - public $lock; - - public function write(string $content, array $metadata = null) - { - rewind($this->lock); - ftruncate($this->lock, 0); - fwrite($this->lock, $content); - - if (null !== $metadata) { - file_put_contents($this->getPath().'.meta', serialize($metadata)); - @chmod($this->getPath().'.meta', 0666 & ~umask()); - } - - if (\function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN)) { - @opcache_invalidate($this->getPath(), true); - } - } - - public function __destruct() - { - flock($this->lock, LOCK_UN); - fclose($this->lock); - } - }; - $cache->lock = $lock; - - if (!\is_object($this->container = include $cachePath)) { - $this->container = null; - } elseif (!$oldContainer || \get_class($this->container) !== $oldContainer->name) { - $this->container->set('kernel', $this); - - return; - } - } - } - } catch (\Throwable $e) { - } finally { - error_reporting($errorLevel); - } - - if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) { - $collectedLogs = []; - $previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) { - if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) { - return $previousHandler ? $previousHandler($type, $message, $file, $line) : false; - } - - if (isset($collectedLogs[$message])) { - ++$collectedLogs[$message]['count']; - - return null; - } - - $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5); - // Clean the trace by removing first frames added by the error handler itself. - for ($i = 0; isset($backtrace[$i]); ++$i) { - if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { - $backtrace = \array_slice($backtrace, 1 + $i); - break; - } - } - // Remove frames added by DebugClassLoader. - for ($i = \count($backtrace) - 2; 0 < $i; --$i) { - if (\in_array($backtrace[$i]['class'] ?? null, [DebugClassLoader::class, LegacyDebugClassLoader::class], true)) { - $backtrace = [$backtrace[$i + 1]]; - break; - } - } - - $collectedLogs[$message] = [ - 'type' => $type, - 'message' => $message, - 'file' => $file, - 'line' => $line, - 'trace' => [$backtrace[0]], - 'count' => 1, - ]; - - return null; - }); - } - - try { - $container = null; - $container = $this->buildContainer(); - $container->compile(); - } finally { - if ($collectDeprecations) { - restore_error_handler(); - - file_put_contents($cacheDir.'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs))); - file_put_contents($cacheDir.'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : ''); - } - } - - $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); - unset($cache); - $this->container = require $cachePath; - $this->container->set('kernel', $this); - - if ($oldContainer && \get_class($this->container) !== $oldContainer->name) { - // Because concurrent requests might still be using them, - // old container files are not removed immediately, - // but on a next dump of the container. - static $legacyContainers = []; - $oldContainerDir = \dirname($oldContainer->getFileName()); - $legacyContainers[$oldContainerDir.'.legacy'] = true; - foreach (glob(\dirname($oldContainerDir).\DIRECTORY_SEPARATOR.'*.legacy', GLOB_NOSORT) as $legacyContainer) { - if (!isset($legacyContainers[$legacyContainer]) && @unlink($legacyContainer)) { - (new Filesystem())->remove(substr($legacyContainer, 0, -7)); - } - } - - touch($oldContainerDir.'.legacy'); - } - - if ($this->container->has('cache_warmer')) { - $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir')); - } - } - - /** - * Returns the kernel parameters. - * - * @return array An array of kernel parameters - */ - protected function getKernelParameters() - { - $bundles = []; - $bundlesMetadata = []; - - foreach ($this->bundles as $name => $bundle) { - $bundles[$name] = \get_class($bundle); - $bundlesMetadata[$name] = [ - 'path' => $bundle->getPath(), - 'namespace' => $bundle->getNamespace(), - ]; - } - - return [ - 'kernel.project_dir' => realpath($this->getProjectDir()) ?: $this->getProjectDir(), - 'kernel.environment' => $this->environment, - 'kernel.debug' => $this->debug, - 'kernel.cache_dir' => realpath($cacheDir = $this->warmupDir ?: $this->getCacheDir()) ?: $cacheDir, - 'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(), - 'kernel.bundles' => $bundles, - 'kernel.bundles_metadata' => $bundlesMetadata, - 'kernel.charset' => $this->getCharset(), - 'kernel.container_class' => $this->getContainerClass(), - ]; - } - - /** - * Builds the service container. - * - * @return ContainerBuilder The compiled service container - * - * @throws \RuntimeException - */ - protected function buildContainer() - { - foreach (['cache' => $this->warmupDir ?: $this->getCacheDir(), 'logs' => $this->getLogDir()] as $name => $dir) { - if (!is_dir($dir)) { - if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) { - throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir)); - } - } elseif (!is_writable($dir)) { - throw new \RuntimeException(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir)); - } - } - - $container = $this->getContainerBuilder(); - $container->addObjectResource($this); - $this->prepareContainer($container); - - if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) { - $container->merge($cont); - } - - $container->addCompilerPass(new AddAnnotatedClassesToCachePass($this)); - - return $container; - } - - /** - * Prepares the ContainerBuilder before it is compiled. - */ - protected function prepareContainer(ContainerBuilder $container) - { - $extensions = []; - foreach ($this->bundles as $bundle) { - if ($extension = $bundle->getContainerExtension()) { - $container->registerExtension($extension); - } - - if ($this->debug) { - $container->addObjectResource($bundle); - } - } - - foreach ($this->bundles as $bundle) { - $bundle->build($container); - } - - $this->build($container); - - foreach ($container->getExtensions() as $extension) { - $extensions[] = $extension->getAlias(); - } - - // ensure these extensions are implicitly loaded - $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions)); - } - - /** - * Gets a new ContainerBuilder instance used to build the service container. - * - * @return ContainerBuilder - */ - protected function getContainerBuilder() - { - $container = new ContainerBuilder(); - $container->getParameterBag()->add($this->getKernelParameters()); - - if ($this instanceof CompilerPassInterface) { - $container->addCompilerPass($this, PassConfig::TYPE_BEFORE_OPTIMIZATION, -10000); - } - if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator')) { - $container->setProxyInstantiator(new RuntimeInstantiator()); - } - - return $container; - } - - /** - * Dumps the service container to PHP code in the cache. - * - * @param string $class The name of the class to generate - * @param string $baseClass The name of the container's base class - */ - protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, string $class, string $baseClass) - { - // cache the container - $dumper = new PhpDumper($container); - - if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper')) { - $dumper->setProxyDumper(new ProxyDumper()); - } - - $content = $dumper->dump([ - 'class' => $class, - 'base_class' => $baseClass, - 'file' => $cache->getPath(), - 'as_files' => true, - 'debug' => $this->debug, - 'build_time' => $container->hasParameter('kernel.container_build_time') ? $container->getParameter('kernel.container_build_time') : time(), - ]); - - $rootCode = array_pop($content); - $dir = \dirname($cache->getPath()).'/'; - $fs = new Filesystem(); - - foreach ($content as $file => $code) { - $fs->dumpFile($dir.$file, $code); - @chmod($dir.$file, 0666 & ~umask()); - } - $legacyFile = \dirname($dir.key($content)).'.legacy'; - if (file_exists($legacyFile)) { - @unlink($legacyFile); - } - - $cache->write($rootCode, $container->getResources()); - } - - /** - * Returns a loader for the container. - * - * @return DelegatingLoader The loader - */ - protected function getContainerLoader(ContainerInterface $container) - { - $locator = new FileLocator($this); - $resolver = new LoaderResolver([ - new XmlFileLoader($container, $locator), - new YamlFileLoader($container, $locator), - new IniFileLoader($container, $locator), - new PhpFileLoader($container, $locator), - new GlobFileLoader($container, $locator), - new DirectoryLoader($container, $locator), - new ClosureLoader($container), - ]); - - return new DelegatingLoader($resolver); - } - - /** - * Removes comments from a PHP source string. - * - * We don't use the PHP php_strip_whitespace() function - * as we want the content to be readable and well-formatted. - * - * @return string The PHP string with the comments removed - */ - public static function stripComments(string $source) - { - if (!\function_exists('token_get_all')) { - return $source; - } - - $rawChunk = ''; - $output = ''; - $tokens = token_get_all($source); - $ignoreSpace = false; - for ($i = 0; isset($tokens[$i]); ++$i) { - $token = $tokens[$i]; - if (!isset($token[1]) || 'b"' === $token) { - $rawChunk .= $token; - } elseif (T_START_HEREDOC === $token[0]) { - $output .= $rawChunk.$token[1]; - do { - $token = $tokens[++$i]; - $output .= isset($token[1]) && 'b"' !== $token ? $token[1] : $token; - } while (T_END_HEREDOC !== $token[0]); - $rawChunk = ''; - } elseif (T_WHITESPACE === $token[0]) { - if ($ignoreSpace) { - $ignoreSpace = false; - - continue; - } - - // replace multiple new lines with a single newline - $rawChunk .= preg_replace(['/\n{2,}/S'], "\n", $token[1]); - } elseif (\in_array($token[0], [T_COMMENT, T_DOC_COMMENT])) { - $ignoreSpace = true; - } else { - $rawChunk .= $token[1]; - - // The PHP-open tag already has a new-line - if (T_OPEN_TAG === $token[0]) { - $ignoreSpace = true; - } - } - } - - $output .= $rawChunk; - - unset($tokens, $rawChunk); - gc_mem_caches(); - - return $output; - } - - /** - * @return array - */ - public function __sleep() - { - return ['environment', 'debug']; - } - - public function __wakeup() - { - $this->__construct($this->environment, $this->debug); - } -} diff --git a/vendor/symfony/http-kernel/KernelEvents.php b/vendor/symfony/http-kernel/KernelEvents.php deleted file mode 100644 index 682561c..0000000 --- a/vendor/symfony/http-kernel/KernelEvents.php +++ /dev/null @@ -1,103 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -/** - * Contains all events thrown in the HttpKernel component. - * - * @author Bernhard Schussek - */ -final class KernelEvents -{ - /** - * The REQUEST event occurs at the very beginning of request - * dispatching. - * - * This event allows you to create a response for a request before any - * other code in the framework is executed. - * - * @Event("Symfony\Component\HttpKernel\Event\RequestEvent") - */ - const REQUEST = 'kernel.request'; - - /** - * The EXCEPTION event occurs when an uncaught exception appears. - * - * This event allows you to create a response for a thrown exception or - * to modify the thrown exception. - * - * @Event("Symfony\Component\HttpKernel\Event\ExceptionEvent") - */ - const EXCEPTION = 'kernel.exception'; - - /** - * The VIEW event occurs when the return value of a controller - * is not a Response instance. - * - * This event allows you to create a response for the return value of the - * controller. - * - * @Event("Symfony\Component\HttpKernel\Event\ViewEvent") - */ - const VIEW = 'kernel.view'; - - /** - * The CONTROLLER event occurs once a controller was found for - * handling a request. - * - * This event allows you to change the controller that will handle the - * request. - * - * @Event("Symfony\Component\HttpKernel\Event\ControllerEvent") - */ - const CONTROLLER = 'kernel.controller'; - - /** - * The CONTROLLER_ARGUMENTS event occurs once controller arguments have been resolved. - * - * This event allows you to change the arguments that will be passed to - * the controller. - * - * @Event("Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent") - */ - const CONTROLLER_ARGUMENTS = 'kernel.controller_arguments'; - - /** - * The RESPONSE event occurs once a response was created for - * replying to a request. - * - * This event allows you to modify or replace the response that will be - * replied. - * - * @Event("Symfony\Component\HttpKernel\Event\ResponseEvent") - */ - const RESPONSE = 'kernel.response'; - - /** - * The TERMINATE event occurs once a response was sent. - * - * This event allows you to run expensive post-response jobs. - * - * @Event("Symfony\Component\HttpKernel\Event\TerminateEvent") - */ - const TERMINATE = 'kernel.terminate'; - - /** - * The FINISH_REQUEST event occurs when a response was generated for a request. - * - * This event allows you to reset the global and environmental state of - * the application, when it was changed during the request. - * - * @Event("Symfony\Component\HttpKernel\Event\FinishRequestEvent") - */ - const FINISH_REQUEST = 'kernel.finish_request'; -} diff --git a/vendor/symfony/http-kernel/KernelInterface.php b/vendor/symfony/http-kernel/KernelInterface.php deleted file mode 100644 index cea86f6..0000000 --- a/vendor/symfony/http-kernel/KernelInterface.php +++ /dev/null @@ -1,141 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpKernel\Bundle\BundleInterface; - -/** - * The Kernel is the heart of the Symfony system. - * - * It manages an environment made of application kernel and bundles. - * - * @author Fabien Potencier - */ -interface KernelInterface extends HttpKernelInterface -{ - /** - * Returns an array of bundles to register. - * - * @return iterable|BundleInterface[] An iterable of bundle instances - */ - public function registerBundles(); - - /** - * Loads the container configuration. - */ - public function registerContainerConfiguration(LoaderInterface $loader); - - /** - * Boots the current kernel. - */ - public function boot(); - - /** - * Shutdowns the kernel. - * - * This method is mainly useful when doing functional testing. - */ - public function shutdown(); - - /** - * Gets the registered bundle instances. - * - * @return BundleInterface[] An array of registered bundle instances - */ - public function getBundles(); - - /** - * Returns a bundle. - * - * @return BundleInterface A BundleInterface instance - * - * @throws \InvalidArgumentException when the bundle is not enabled - */ - public function getBundle(string $name); - - /** - * Returns the file path for a given bundle resource. - * - * A Resource can be a file or a directory. - * - * The resource name must follow the following pattern: - * - * "@BundleName/path/to/a/file.something" - * - * where BundleName is the name of the bundle - * and the remaining part is the relative path in the bundle. - * - * @return string The absolute path of the resource - * - * @throws \InvalidArgumentException if the file cannot be found or the name is not valid - * @throws \RuntimeException if the name contains invalid/unsafe characters - */ - public function locateResource(string $name); - - /** - * Gets the environment. - * - * @return string The current environment - */ - public function getEnvironment(); - - /** - * Checks if debug mode is enabled. - * - * @return bool true if debug mode is enabled, false otherwise - */ - public function isDebug(); - - /** - * Gets the project dir (path of the project's composer file). - * - * @return string - */ - public function getProjectDir(); - - /** - * Gets the current container. - * - * @return ContainerInterface - */ - public function getContainer(); - - /** - * Gets the request start time (not available if debug is disabled). - * - * @return float The request start timestamp - */ - public function getStartTime(); - - /** - * Gets the cache directory. - * - * @return string The cache directory - */ - public function getCacheDir(); - - /** - * Gets the log directory. - * - * @return string The log directory - */ - public function getLogDir(); - - /** - * Gets the charset of the application. - * - * @return string The charset - */ - public function getCharset(); -} diff --git a/vendor/symfony/http-kernel/LICENSE b/vendor/symfony/http-kernel/LICENSE deleted file mode 100644 index a677f43..0000000 --- a/vendor/symfony/http-kernel/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/http-kernel/Log/DebugLoggerInterface.php b/vendor/symfony/http-kernel/Log/DebugLoggerInterface.php deleted file mode 100644 index 2c2eae6..0000000 --- a/vendor/symfony/http-kernel/Log/DebugLoggerInterface.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Log; - -use Symfony\Component\HttpFoundation\Request; - -/** - * DebugLoggerInterface. - * - * @author Fabien Potencier - */ -interface DebugLoggerInterface -{ - /** - * Returns an array of logs. - * - * A log is an array with the following mandatory keys: - * timestamp, message, priority, and priorityName. - * It can also have an optional context key containing an array. - * - * @return array An array of logs - */ - public function getLogs(Request $request = null); - - /** - * Returns the number of errors. - * - * @return int The number of errors - */ - public function countErrors(Request $request = null); - - /** - * Removes all log records. - */ - public function clear(); -} diff --git a/vendor/symfony/http-kernel/Log/Logger.php b/vendor/symfony/http-kernel/Log/Logger.php deleted file mode 100644 index c27bb3f..0000000 --- a/vendor/symfony/http-kernel/Log/Logger.php +++ /dev/null @@ -1,106 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Log; - -use Psr\Log\AbstractLogger; -use Psr\Log\InvalidArgumentException; -use Psr\Log\LogLevel; - -/** - * Minimalist PSR-3 logger designed to write in stderr or any other stream. - * - * @author Kévin Dunglas - */ -class Logger extends AbstractLogger -{ - private static $levels = [ - LogLevel::DEBUG => 0, - LogLevel::INFO => 1, - LogLevel::NOTICE => 2, - LogLevel::WARNING => 3, - LogLevel::ERROR => 4, - LogLevel::CRITICAL => 5, - LogLevel::ALERT => 6, - LogLevel::EMERGENCY => 7, - ]; - - private $minLevelIndex; - private $formatter; - private $handle; - - public function __construct(string $minLevel = null, $output = 'php://stderr', callable $formatter = null) - { - if (null === $minLevel) { - $minLevel = 'php://stdout' === $output || 'php://stderr' === $output ? LogLevel::CRITICAL : LogLevel::WARNING; - - if (isset($_ENV['SHELL_VERBOSITY']) || isset($_SERVER['SHELL_VERBOSITY'])) { - switch ((int) (isset($_ENV['SHELL_VERBOSITY']) ? $_ENV['SHELL_VERBOSITY'] : $_SERVER['SHELL_VERBOSITY'])) { - case -1: $minLevel = LogLevel::ERROR; break; - case 1: $minLevel = LogLevel::NOTICE; break; - case 2: $minLevel = LogLevel::INFO; break; - case 3: $minLevel = LogLevel::DEBUG; break; - } - } - } - - if (!isset(self::$levels[$minLevel])) { - throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $minLevel)); - } - - $this->minLevelIndex = self::$levels[$minLevel]; - $this->formatter = $formatter ?: [$this, 'format']; - if (false === $this->handle = \is_resource($output) ? $output : @fopen($output, 'a')) { - throw new InvalidArgumentException(sprintf('Unable to open "%s".', $output)); - } - } - - /** - * {@inheritdoc} - * - * @return void - */ - public function log($level, $message, array $context = []) - { - if (!isset(self::$levels[$level])) { - throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); - } - - if (self::$levels[$level] < $this->minLevelIndex) { - return; - } - - $formatter = $this->formatter; - fwrite($this->handle, $formatter($level, $message, $context)); - } - - private function format(string $level, string $message, array $context): string - { - if (false !== strpos($message, '{')) { - $replacements = []; - foreach ($context as $key => $val) { - if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { - $replacements["{{$key}}"] = $val; - } elseif ($val instanceof \DateTimeInterface) { - $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); - } elseif (\is_object($val)) { - $replacements["{{$key}}"] = '[object '.\get_class($val).']'; - } else { - $replacements["{{$key}}"] = '['.\gettype($val).']'; - } - } - - $message = strtr($message, $replacements); - } - - return sprintf('%s [%s] %s', date(\DateTime::RFC3339), $level, $message).\PHP_EOL; - } -} diff --git a/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php b/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php deleted file mode 100644 index 3b5dfbf..0000000 --- a/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php +++ /dev/null @@ -1,303 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Profiler; - -/** - * Storage for profiler using files. - * - * @author Alexandre Salomé - */ -class FileProfilerStorage implements ProfilerStorageInterface -{ - /** - * Folder where profiler data are stored. - * - * @var string - */ - private $folder; - - /** - * Constructs the file storage using a "dsn-like" path. - * - * Example : "file:/path/to/the/storage/folder" - * - * @throws \RuntimeException - */ - public function __construct(string $dsn) - { - if (0 !== strpos($dsn, 'file:')) { - throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use FileStorage with an invalid dsn "%s". The expected format is "file:/path/to/the/storage/folder".', $dsn)); - } - $this->folder = substr($dsn, 5); - - if (!is_dir($this->folder) && false === @mkdir($this->folder, 0777, true) && !is_dir($this->folder)) { - throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $this->folder)); - } - } - - /** - * {@inheritdoc} - */ - public function find(?string $ip, ?string $url, ?int $limit, ?string $method, int $start = null, int $end = null, string $statusCode = null): array - { - $file = $this->getIndexFilename(); - - if (!file_exists($file)) { - return []; - } - - $file = fopen($file, 'r'); - fseek($file, 0, SEEK_END); - - $result = []; - while (\count($result) < $limit && $line = $this->readLineFromFile($file)) { - $values = str_getcsv($line); - list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode) = $values; - $csvTime = (int) $csvTime; - - if ($ip && false === strpos($csvIp, $ip) || $url && false === strpos($csvUrl, $url) || $method && false === strpos($csvMethod, $method) || $statusCode && false === strpos($csvStatusCode, $statusCode)) { - continue; - } - - if (!empty($start) && $csvTime < $start) { - continue; - } - - if (!empty($end) && $csvTime > $end) { - continue; - } - - $result[$csvToken] = [ - 'token' => $csvToken, - 'ip' => $csvIp, - 'method' => $csvMethod, - 'url' => $csvUrl, - 'time' => $csvTime, - 'parent' => $csvParent, - 'status_code' => $csvStatusCode, - ]; - } - - fclose($file); - - return array_values($result); - } - - /** - * {@inheritdoc} - */ - public function purge() - { - $flags = \FilesystemIterator::SKIP_DOTS; - $iterator = new \RecursiveDirectoryIterator($this->folder, $flags); - $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST); - - foreach ($iterator as $file) { - if (is_file($file)) { - unlink($file); - } else { - rmdir($file); - } - } - } - - /** - * {@inheritdoc} - */ - public function read(string $token): ?Profile - { - if (!$token || !file_exists($file = $this->getFilename($token))) { - return null; - } - - if (\function_exists('gzcompress')) { - $file = 'compress.zlib://'.$file; - } - - return $this->createProfileFromData($token, unserialize(file_get_contents($file))); - } - - /** - * {@inheritdoc} - * - * @throws \RuntimeException - */ - public function write(Profile $profile): bool - { - $file = $this->getFilename($profile->getToken()); - - $profileIndexed = is_file($file); - if (!$profileIndexed) { - // Create directory - $dir = \dirname($file); - if (!is_dir($dir) && false === @mkdir($dir, 0777, true) && !is_dir($dir)) { - throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $dir)); - } - } - - $profileToken = $profile->getToken(); - // when there are errors in sub-requests, the parent and/or children tokens - // may equal the profile token, resulting in infinite loops - $parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null; - $childrenToken = array_filter(array_map(function (Profile $p) use ($profileToken) { - return $profileToken !== $p->getToken() ? $p->getToken() : null; - }, $profile->getChildren())); - - // Store profile - $data = [ - 'token' => $profileToken, - 'parent' => $parentToken, - 'children' => $childrenToken, - 'data' => $profile->getCollectors(), - 'ip' => $profile->getIp(), - 'method' => $profile->getMethod(), - 'url' => $profile->getUrl(), - 'time' => $profile->getTime(), - 'status_code' => $profile->getStatusCode(), - ]; - - $context = stream_context_create(); - - if (\function_exists('gzcompress')) { - $file = 'compress.zlib://'.$file; - stream_context_set_option($context, 'zlib', 'level', 3); - } - - if (false === file_put_contents($file, serialize($data), 0, $context)) { - return false; - } - - if (!$profileIndexed) { - // Add to index - if (false === $file = fopen($this->getIndexFilename(), 'a')) { - return false; - } - - fputcsv($file, [ - $profile->getToken(), - $profile->getIp(), - $profile->getMethod(), - $profile->getUrl(), - $profile->getTime(), - $profile->getParentToken(), - $profile->getStatusCode(), - ]); - fclose($file); - } - - return true; - } - - /** - * Gets filename to store data, associated to the token. - * - * @return string The profile filename - */ - protected function getFilename(string $token) - { - // Uses 4 last characters, because first are mostly the same. - $folderA = substr($token, -2, 2); - $folderB = substr($token, -4, 2); - - return $this->folder.'/'.$folderA.'/'.$folderB.'/'.$token; - } - - /** - * Gets the index filename. - * - * @return string The index filename - */ - protected function getIndexFilename() - { - return $this->folder.'/index.csv'; - } - - /** - * Reads a line in the file, backward. - * - * This function automatically skips the empty lines and do not include the line return in result value. - * - * @param resource $file The file resource, with the pointer placed at the end of the line to read - * - * @return mixed A string representing the line or null if beginning of file is reached - */ - protected function readLineFromFile($file) - { - $line = ''; - $position = ftell($file); - - if (0 === $position) { - return null; - } - - while (true) { - $chunkSize = min($position, 1024); - $position -= $chunkSize; - fseek($file, $position); - - if (0 === $chunkSize) { - // bof reached - break; - } - - $buffer = fread($file, $chunkSize); - - if (false === ($upTo = strrpos($buffer, "\n"))) { - $line = $buffer.$line; - continue; - } - - $position += $upTo; - $line = substr($buffer, $upTo + 1).$line; - fseek($file, max(0, $position), SEEK_SET); - - if ('' !== $line) { - break; - } - } - - return '' === $line ? null : $line; - } - - protected function createProfileFromData(string $token, array $data, Profile $parent = null) - { - $profile = new Profile($token); - $profile->setIp($data['ip']); - $profile->setMethod($data['method']); - $profile->setUrl($data['url']); - $profile->setTime($data['time']); - $profile->setStatusCode($data['status_code']); - $profile->setCollectors($data['data']); - - if (!$parent && $data['parent']) { - $parent = $this->read($data['parent']); - } - - if ($parent) { - $profile->setParent($parent); - } - - foreach ($data['children'] as $token) { - if (!$token || !file_exists($file = $this->getFilename($token))) { - continue; - } - - if (\function_exists('gzcompress')) { - $file = 'compress.zlib://'.$file; - } - - $profile->addChild($this->createProfileFromData($token, unserialize(file_get_contents($file)), $profile)); - } - - return $profile; - } -} diff --git a/vendor/symfony/http-kernel/Profiler/Profile.php b/vendor/symfony/http-kernel/Profiler/Profile.php deleted file mode 100644 index c18e998..0000000 --- a/vendor/symfony/http-kernel/Profiler/Profile.php +++ /dev/null @@ -1,274 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Profiler; - -use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; - -/** - * Profile. - * - * @author Fabien Potencier - */ -class Profile -{ - private $token; - - /** - * @var DataCollectorInterface[] - */ - private $collectors = []; - - private $ip; - private $method; - private $url; - private $time; - private $statusCode; - - /** - * @var Profile - */ - private $parent; - - /** - * @var Profile[] - */ - private $children = []; - - public function __construct(string $token) - { - $this->token = $token; - } - - public function setToken(string $token) - { - $this->token = $token; - } - - /** - * Gets the token. - * - * @return string The token - */ - public function getToken() - { - return $this->token; - } - - /** - * Sets the parent token. - */ - public function setParent(self $parent) - { - $this->parent = $parent; - } - - /** - * Returns the parent profile. - * - * @return self - */ - public function getParent() - { - return $this->parent; - } - - /** - * Returns the parent token. - * - * @return string|null The parent token - */ - public function getParentToken() - { - return $this->parent ? $this->parent->getToken() : null; - } - - /** - * Returns the IP. - * - * @return string|null The IP - */ - public function getIp() - { - return $this->ip; - } - - public function setIp(string $ip) - { - $this->ip = $ip; - } - - /** - * Returns the request method. - * - * @return string|null The request method - */ - public function getMethod() - { - return $this->method; - } - - public function setMethod(string $method) - { - $this->method = $method; - } - - /** - * Returns the URL. - * - * @return string|null The URL - */ - public function getUrl() - { - return $this->url; - } - - public function setUrl(string $url) - { - $this->url = $url; - } - - /** - * @return int The time - */ - public function getTime() - { - if (null === $this->time) { - return 0; - } - - return $this->time; - } - - public function setTime(int $time) - { - $this->time = $time; - } - - public function setStatusCode(int $statusCode) - { - $this->statusCode = $statusCode; - } - - /** - * @return int|null - */ - public function getStatusCode() - { - return $this->statusCode; - } - - /** - * Finds children profilers. - * - * @return self[] - */ - public function getChildren() - { - return $this->children; - } - - /** - * Sets children profiler. - * - * @param Profile[] $children - */ - public function setChildren(array $children) - { - $this->children = []; - foreach ($children as $child) { - $this->addChild($child); - } - } - - /** - * Adds the child token. - */ - public function addChild(self $child) - { - $this->children[] = $child; - $child->setParent($this); - } - - public function getChildByToken(string $token): ?self - { - foreach ($this->children as $child) { - if ($token === $child->getToken()) { - return $child; - } - } - - return null; - } - - /** - * Gets a Collector by name. - * - * @return DataCollectorInterface A DataCollectorInterface instance - * - * @throws \InvalidArgumentException if the collector does not exist - */ - public function getCollector(string $name) - { - if (!isset($this->collectors[$name])) { - throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name)); - } - - return $this->collectors[$name]; - } - - /** - * Gets the Collectors associated with this profile. - * - * @return DataCollectorInterface[] - */ - public function getCollectors() - { - return $this->collectors; - } - - /** - * Sets the Collectors associated with this profile. - * - * @param DataCollectorInterface[] $collectors - */ - public function setCollectors(array $collectors) - { - $this->collectors = []; - foreach ($collectors as $collector) { - $this->addCollector($collector); - } - } - - /** - * Adds a Collector. - */ - public function addCollector(DataCollectorInterface $collector) - { - $this->collectors[$collector->getName()] = $collector; - } - - /** - * @return bool - */ - public function hasCollector(string $name) - { - return isset($this->collectors[$name]); - } - - /** - * @return array - */ - public function __sleep() - { - return ['token', 'parent', 'children', 'collectors', 'ip', 'method', 'url', 'time', 'statusCode']; - } -} diff --git a/vendor/symfony/http-kernel/Profiler/Profiler.php b/vendor/symfony/http-kernel/Profiler/Profiler.php deleted file mode 100644 index 72af8e0..0000000 --- a/vendor/symfony/http-kernel/Profiler/Profiler.php +++ /dev/null @@ -1,253 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Profiler; - -use Psr\Log\LoggerInterface; -use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; -use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; -use Symfony\Contracts\Service\ResetInterface; - -/** - * Profiler. - * - * @author Fabien Potencier - */ -class Profiler implements ResetInterface -{ - private $storage; - - /** - * @var DataCollectorInterface[] - */ - private $collectors = []; - - private $logger; - private $initiallyEnabled = true; - private $enabled = true; - - public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null, bool $enable = true) - { - $this->storage = $storage; - $this->logger = $logger; - $this->initiallyEnabled = $this->enabled = $enable; - } - - /** - * Disables the profiler. - */ - public function disable() - { - $this->enabled = false; - } - - /** - * Enables the profiler. - */ - public function enable() - { - $this->enabled = true; - } - - /** - * Loads the Profile for the given Response. - * - * @return Profile|null A Profile instance - */ - public function loadProfileFromResponse(Response $response) - { - if (!$token = $response->headers->get('X-Debug-Token')) { - return null; - } - - return $this->loadProfile($token); - } - - /** - * Loads the Profile for the given token. - * - * @return Profile|null A Profile instance - */ - public function loadProfile(string $token) - { - return $this->storage->read($token); - } - - /** - * Saves a Profile. - * - * @return bool - */ - public function saveProfile(Profile $profile) - { - // late collect - foreach ($profile->getCollectors() as $collector) { - if ($collector instanceof LateDataCollectorInterface) { - $collector->lateCollect(); - } - } - - if (!($ret = $this->storage->write($profile)) && null !== $this->logger) { - $this->logger->warning('Unable to store the profiler information.', ['configured_storage' => \get_class($this->storage)]); - } - - return $ret; - } - - /** - * Purges all data from the storage. - */ - public function purge() - { - $this->storage->purge(); - } - - /** - * Finds profiler tokens for the given criteria. - * - * @param string|null $limit The maximum number of tokens to return - * @param string|null $start The start date to search from - * @param string|null $end The end date to search to - * - * @return array An array of tokens - * - * @see https://php.net/datetime.formats for the supported date/time formats - */ - public function find(?string $ip, ?string $url, ?string $limit, ?string $method, ?string $start, ?string $end, string $statusCode = null) - { - return $this->storage->find($ip, $url, $limit, $method, $this->getTimestamp($start), $this->getTimestamp($end), $statusCode); - } - - /** - * Collects data for the given Response. - * - * @return Profile|null A Profile instance or null if the profiler is disabled - */ - public function collect(Request $request, Response $response, \Throwable $exception = null) - { - if (false === $this->enabled) { - return null; - } - - $profile = new Profile(substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6)); - $profile->setTime(time()); - $profile->setUrl($request->getUri()); - $profile->setMethod($request->getMethod()); - $profile->setStatusCode($response->getStatusCode()); - try { - $profile->setIp($request->getClientIp()); - } catch (ConflictingHeadersException $e) { - $profile->setIp('Unknown'); - } - - if ($prevToken = $response->headers->get('X-Debug-Token')) { - $response->headers->set('X-Previous-Debug-Token', $prevToken); - } - - $response->headers->set('X-Debug-Token', $profile->getToken()); - - foreach ($this->collectors as $collector) { - $collector->collect($request, $response, $exception); - - // we need to clone for sub-requests - $profile->addCollector(clone $collector); - } - - return $profile; - } - - public function reset() - { - foreach ($this->collectors as $collector) { - $collector->reset(); - } - $this->enabled = $this->initiallyEnabled; - } - - /** - * Gets the Collectors associated with this profiler. - * - * @return array An array of collectors - */ - public function all() - { - return $this->collectors; - } - - /** - * Sets the Collectors associated with this profiler. - * - * @param DataCollectorInterface[] $collectors An array of collectors - */ - public function set(array $collectors = []) - { - $this->collectors = []; - foreach ($collectors as $collector) { - $this->add($collector); - } - } - - /** - * Adds a Collector. - */ - public function add(DataCollectorInterface $collector) - { - $this->collectors[$collector->getName()] = $collector; - } - - /** - * Returns true if a Collector for the given name exists. - * - * @param string $name A collector name - * - * @return bool - */ - public function has(string $name) - { - return isset($this->collectors[$name]); - } - - /** - * Gets a Collector by name. - * - * @param string $name A collector name - * - * @return DataCollectorInterface A DataCollectorInterface instance - * - * @throws \InvalidArgumentException if the collector does not exist - */ - public function get(string $name) - { - if (!isset($this->collectors[$name])) { - throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name)); - } - - return $this->collectors[$name]; - } - - private function getTimestamp(?string $value): ?int - { - if (null === $value || '' === $value) { - return null; - } - - try { - $value = new \DateTime(is_numeric($value) ? '@'.$value : $value); - } catch (\Exception $e) { - return null; - } - - return $value->getTimestamp(); - } -} diff --git a/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php b/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php deleted file mode 100644 index 0fbc449..0000000 --- a/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php +++ /dev/null @@ -1,60 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Profiler; - -/** - * ProfilerStorageInterface. - * - * This interface exists for historical reasons. The only supported - * implementation is FileProfilerStorage. - * - * As the profiler must only be used on non-production servers, the file storage - * is more than enough and no other implementations will ever be supported. - * - * @internal - * - * @author Fabien Potencier - */ -interface ProfilerStorageInterface -{ - /** - * Finds profiler tokens for the given criteria. - * - * @param int|null $limit The maximum number of tokens to return - * @param int|null $start The start date to search from - * @param int|null $end The end date to search to - * - * @return array An array of tokens - */ - public function find(?string $ip, ?string $url, ?int $limit, ?string $method, int $start = null, int $end = null): array; - - /** - * Reads data associated with the given token. - * - * The method returns false if the token does not exist in the storage. - * - * @return Profile|null The profile associated with token - */ - public function read(string $token): ?Profile; - - /** - * Saves a Profile. - * - * @return bool Write operation successful - */ - public function write(Profile $profile): bool; - - /** - * Purges all data from the database. - */ - public function purge(); -} diff --git a/vendor/symfony/http-kernel/README.md b/vendor/symfony/http-kernel/README.md deleted file mode 100644 index cc5e74b..0000000 --- a/vendor/symfony/http-kernel/README.md +++ /dev/null @@ -1,16 +0,0 @@ -HttpKernel Component -==================== - -The HttpKernel component provides a structured process for converting a Request -into a Response by making use of the EventDispatcher component. It's flexible -enough to create a full-stack framework (Symfony), a micro-framework (Silex) or -an advanced CMS system (Drupal). - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/http_kernel/index.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/http-kernel/RebootableInterface.php b/vendor/symfony/http-kernel/RebootableInterface.php deleted file mode 100644 index 0dc46c3..0000000 --- a/vendor/symfony/http-kernel/RebootableInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -/** - * Allows the Kernel to be rebooted using a temporary cache directory. - * - * @author Nicolas Grekas - */ -interface RebootableInterface -{ - /** - * Reboots a kernel. - * - * The getCacheDir() method of a rebootable kernel should not be called - * while building the container. Use the %kernel.cache_dir% parameter instead. - * - * @param string|null $warmupDir pass null to reboot in the regular cache directory - */ - public function reboot(?string $warmupDir); -} diff --git a/vendor/symfony/http-kernel/Resources/welcome.html.php b/vendor/symfony/http-kernel/Resources/welcome.html.php deleted file mode 100644 index e1c0ff1..0000000 --- a/vendor/symfony/http-kernel/Resources/welcome.html.php +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - Welcome to Symfony! - - - -
    -
    - - You're seeing this page because you haven't configured any homepage URL. -
    - -
    -
    - -

    Welcome to Symfony

    -
    - -
    - - - - - - -

    Your application is now ready and you can start working on it.

    -
    - - -
    - -
    - -
    -
    - - diff --git a/vendor/symfony/http-kernel/TerminableInterface.php b/vendor/symfony/http-kernel/TerminableInterface.php deleted file mode 100644 index 8aa3319..0000000 --- a/vendor/symfony/http-kernel/TerminableInterface.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; - -/** - * Terminable extends the Kernel request/response cycle with dispatching a post - * response event after sending the response and before shutting down the kernel. - * - * @author Jordi Boggiano - * @author Pierre Minnieur - */ -interface TerminableInterface -{ - /** - * Terminates a request/response cycle. - * - * Should be called after sending the response and before shutting down the kernel. - */ - public function terminate(Request $request, Response $response); -} diff --git a/vendor/symfony/http-kernel/UriSigner.php b/vendor/symfony/http-kernel/UriSigner.php deleted file mode 100644 index 4dfb2bb..0000000 --- a/vendor/symfony/http-kernel/UriSigner.php +++ /dev/null @@ -1,103 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel; - -/** - * Signs URIs. - * - * @author Fabien Potencier - */ -class UriSigner -{ - private $secret; - private $parameter; - - /** - * @param string $secret A secret - * @param string $parameter Query string parameter to use - */ - public function __construct(string $secret, string $parameter = '_hash') - { - $this->secret = $secret; - $this->parameter = $parameter; - } - - /** - * Signs a URI. - * - * The given URI is signed by adding the query string parameter - * which value depends on the URI and the secret. - * - * @return string The signed URI - */ - public function sign(string $uri) - { - $url = parse_url($uri); - if (isset($url['query'])) { - parse_str($url['query'], $params); - } else { - $params = []; - } - - $uri = $this->buildUrl($url, $params); - $params[$this->parameter] = $this->computeHash($uri); - - return $this->buildUrl($url, $params); - } - - /** - * Checks that a URI contains the correct hash. - * - * @return bool True if the URI is signed correctly, false otherwise - */ - public function check(string $uri) - { - $url = parse_url($uri); - if (isset($url['query'])) { - parse_str($url['query'], $params); - } else { - $params = []; - } - - if (empty($params[$this->parameter])) { - return false; - } - - $hash = $params[$this->parameter]; - unset($params[$this->parameter]); - - return hash_equals($this->computeHash($this->buildUrl($url, $params)), $hash); - } - - private function computeHash(string $uri): string - { - return base64_encode(hash_hmac('sha256', $uri, $this->secret, true)); - } - - private function buildUrl(array $url, array $params = []): string - { - ksort($params, SORT_STRING); - $url['query'] = http_build_query($params, '', '&'); - - $scheme = isset($url['scheme']) ? $url['scheme'].'://' : ''; - $host = isset($url['host']) ? $url['host'] : ''; - $port = isset($url['port']) ? ':'.$url['port'] : ''; - $user = isset($url['user']) ? $url['user'] : ''; - $pass = isset($url['pass']) ? ':'.$url['pass'] : ''; - $pass = ($user || $pass) ? "$pass@" : ''; - $path = isset($url['path']) ? $url['path'] : ''; - $query = isset($url['query']) && $url['query'] ? '?'.$url['query'] : ''; - $fragment = isset($url['fragment']) ? '#'.$url['fragment'] : ''; - - return $scheme.$user.$pass.$host.$port.$path.$query.$fragment; - } -} diff --git a/vendor/symfony/http-kernel/composer.json b/vendor/symfony/http-kernel/composer.json deleted file mode 100644 index 73621a5..0000000 --- a/vendor/symfony/http-kernel/composer.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "name": "symfony/http-kernel", - "type": "library", - "description": "Symfony HttpKernel Component", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "symfony/error-handler": "^4.4|^5.0", - "symfony/event-dispatcher": "^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-php73": "^1.9", - "psr/log": "~1.0" - }, - "require-dev": { - "symfony/browser-kit": "^4.4|^5.0", - "symfony/config": "^5.0", - "symfony/console": "^4.4|^5.0", - "symfony/css-selector": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "symfony/dom-crawler": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/finder": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0", - "symfony/routing": "^4.4|^5.0", - "symfony/stopwatch": "^4.4|^5.0", - "symfony/translation": "^4.4|^5.0", - "symfony/translation-contracts": "^1.1|^2", - "psr/cache": "~1.0", - "twig/twig": "^2.4|^3.0" - }, - "provide": { - "psr/log-implementation": "1.0" - }, - "conflict": { - "symfony/browser-kit": "<4.4", - "symfony/cache": "<5.0", - "symfony/config": "<5.0", - "symfony/form": "<5.0", - "symfony/dependency-injection": "<4.4", - "symfony/doctrine-bridge": "<5.0", - "symfony/http-client": "<5.0", - "symfony/mailer": "<5.0", - "symfony/messenger": "<5.0", - "symfony/translation": "<5.0", - "symfony/twig-bridge": "<5.0", - "symfony/validator": "<5.0", - "twig/twig": "<2.4" - }, - "suggest": { - "symfony/browser-kit": "", - "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\HttpKernel\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/mime/.gitattributes b/vendor/symfony/mime/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/mime/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/mime/Address.php b/vendor/symfony/mime/Address.php deleted file mode 100644 index b0dcbd0..0000000 --- a/vendor/symfony/mime/Address.php +++ /dev/null @@ -1,125 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime; - -use Egulias\EmailValidator\EmailValidator; -use Egulias\EmailValidator\Validation\RFCValidation; -use Symfony\Component\Mime\Encoder\IdnAddressEncoder; -use Symfony\Component\Mime\Exception\InvalidArgumentException; -use Symfony\Component\Mime\Exception\LogicException; -use Symfony\Component\Mime\Exception\RfcComplianceException; - -/** - * @author Fabien Potencier - */ -final class Address -{ - /** - * A regex that matches a structure like 'Name '. - * It matches anything between the first < and last > as email address. - * This allows to use a single string to construct an Address, which can be convenient to use in - * config, and allows to have more readable config. - * This does not try to cover all edge cases for address. - */ - private const FROM_STRING_PATTERN = '~(?[^<]*)<(?.*)>[^>]*~'; - - private static $validator; - private static $encoder; - - private $address; - private $name; - - public function __construct(string $address, string $name = '') - { - if (!class_exists(EmailValidator::class)) { - throw new LogicException(sprintf('The "%s" class cannot be used as it needs "%s"; try running "composer require egulias/email-validator".', __CLASS__, EmailValidator::class)); - } - - if (null === self::$validator) { - self::$validator = new EmailValidator(); - } - - $this->address = trim($address); - $this->name = trim(str_replace(["\n", "\r"], '', $name)); - - if (!self::$validator->isValid($this->address, new RFCValidation())) { - throw new RfcComplianceException(sprintf('Email "%s" does not comply with addr-spec of RFC 2822.', $address)); - } - } - - public function getAddress(): string - { - return $this->address; - } - - public function getName(): string - { - return $this->name; - } - - public function getEncodedAddress(): string - { - if (null === self::$encoder) { - self::$encoder = new IdnAddressEncoder(); - } - - return self::$encoder->encodeString($this->address); - } - - public function toString(): string - { - return ($n = $this->getName()) ? $n.' <'.$this->getEncodedAddress().'>' : $this->getEncodedAddress(); - } - - /** - * @param Address|string $address - */ - public static function create($address): self - { - if ($address instanceof self) { - return $address; - } - if (\is_string($address)) { - return new self($address); - } - - throw new InvalidArgumentException(sprintf('An address can be an instance of Address or a string ("%s") given).', \is_object($address) ? \get_class($address) : \gettype($address))); - } - - /** - * @param (Address|string)[] $addresses - * - * @return Address[] - */ - public static function createArray(array $addresses): array - { - $addrs = []; - foreach ($addresses as $address) { - $addrs[] = self::create($address); - } - - return $addrs; - } - - public static function fromString(string $string): self - { - if (false === strpos($string, '<')) { - return new self($string, ''); - } - - if (!preg_match(self::FROM_STRING_PATTERN, $string, $matches)) { - throw new InvalidArgumentException(sprintf('Could not parse "%s" to a "%s" instance.', $string, static::class)); - } - - return new self($matches['addrSpec'], trim($matches['displayName'], ' \'"')); - } -} diff --git a/vendor/symfony/mime/BodyRendererInterface.php b/vendor/symfony/mime/BodyRendererInterface.php deleted file mode 100644 index d692172..0000000 --- a/vendor/symfony/mime/BodyRendererInterface.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime; - -/** - * @author Fabien Potencier - */ -interface BodyRendererInterface -{ - public function render(Message $message): void; -} diff --git a/vendor/symfony/mime/CHANGELOG.md b/vendor/symfony/mime/CHANGELOG.md deleted file mode 100644 index 6148360..0000000 --- a/vendor/symfony/mime/CHANGELOG.md +++ /dev/null @@ -1,20 +0,0 @@ -CHANGELOG -========= - -4.4.0 ------ - - * [BC BREAK] Removed `NamedAddress` (`Address` now supports a name) - * Added PHPUnit constraints - * Added `AbstractPart::asDebugString()` - * Added `Address::fromString()` - -4.3.3 ------ - - * [BC BREAK] Renamed method `Headers::getAll()` to `Headers::all()`. - -4.3.0 ------ - - * Introduced the component as experimental diff --git a/vendor/symfony/mime/CharacterStream.php b/vendor/symfony/mime/CharacterStream.php deleted file mode 100644 index 749066f..0000000 --- a/vendor/symfony/mime/CharacterStream.php +++ /dev/null @@ -1,221 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime; - -/** - * @author Fabien Potencier - * @author Xavier De Cock - * - * @internal - */ -final class CharacterStream -{ - /** Pre-computed for optimization */ - private const UTF8_LENGTH_MAP = [ - "\x00" => 1, "\x01" => 1, "\x02" => 1, "\x03" => 1, "\x04" => 1, "\x05" => 1, "\x06" => 1, "\x07" => 1, - "\x08" => 1, "\x09" => 1, "\x0a" => 1, "\x0b" => 1, "\x0c" => 1, "\x0d" => 1, "\x0e" => 1, "\x0f" => 1, - "\x10" => 1, "\x11" => 1, "\x12" => 1, "\x13" => 1, "\x14" => 1, "\x15" => 1, "\x16" => 1, "\x17" => 1, - "\x18" => 1, "\x19" => 1, "\x1a" => 1, "\x1b" => 1, "\x1c" => 1, "\x1d" => 1, "\x1e" => 1, "\x1f" => 1, - "\x20" => 1, "\x21" => 1, "\x22" => 1, "\x23" => 1, "\x24" => 1, "\x25" => 1, "\x26" => 1, "\x27" => 1, - "\x28" => 1, "\x29" => 1, "\x2a" => 1, "\x2b" => 1, "\x2c" => 1, "\x2d" => 1, "\x2e" => 1, "\x2f" => 1, - "\x30" => 1, "\x31" => 1, "\x32" => 1, "\x33" => 1, "\x34" => 1, "\x35" => 1, "\x36" => 1, "\x37" => 1, - "\x38" => 1, "\x39" => 1, "\x3a" => 1, "\x3b" => 1, "\x3c" => 1, "\x3d" => 1, "\x3e" => 1, "\x3f" => 1, - "\x40" => 1, "\x41" => 1, "\x42" => 1, "\x43" => 1, "\x44" => 1, "\x45" => 1, "\x46" => 1, "\x47" => 1, - "\x48" => 1, "\x49" => 1, "\x4a" => 1, "\x4b" => 1, "\x4c" => 1, "\x4d" => 1, "\x4e" => 1, "\x4f" => 1, - "\x50" => 1, "\x51" => 1, "\x52" => 1, "\x53" => 1, "\x54" => 1, "\x55" => 1, "\x56" => 1, "\x57" => 1, - "\x58" => 1, "\x59" => 1, "\x5a" => 1, "\x5b" => 1, "\x5c" => 1, "\x5d" => 1, "\x5e" => 1, "\x5f" => 1, - "\x60" => 1, "\x61" => 1, "\x62" => 1, "\x63" => 1, "\x64" => 1, "\x65" => 1, "\x66" => 1, "\x67" => 1, - "\x68" => 1, "\x69" => 1, "\x6a" => 1, "\x6b" => 1, "\x6c" => 1, "\x6d" => 1, "\x6e" => 1, "\x6f" => 1, - "\x70" => 1, "\x71" => 1, "\x72" => 1, "\x73" => 1, "\x74" => 1, "\x75" => 1, "\x76" => 1, "\x77" => 1, - "\x78" => 1, "\x79" => 1, "\x7a" => 1, "\x7b" => 1, "\x7c" => 1, "\x7d" => 1, "\x7e" => 1, "\x7f" => 1, - "\x80" => 0, "\x81" => 0, "\x82" => 0, "\x83" => 0, "\x84" => 0, "\x85" => 0, "\x86" => 0, "\x87" => 0, - "\x88" => 0, "\x89" => 0, "\x8a" => 0, "\x8b" => 0, "\x8c" => 0, "\x8d" => 0, "\x8e" => 0, "\x8f" => 0, - "\x90" => 0, "\x91" => 0, "\x92" => 0, "\x93" => 0, "\x94" => 0, "\x95" => 0, "\x96" => 0, "\x97" => 0, - "\x98" => 0, "\x99" => 0, "\x9a" => 0, "\x9b" => 0, "\x9c" => 0, "\x9d" => 0, "\x9e" => 0, "\x9f" => 0, - "\xa0" => 0, "\xa1" => 0, "\xa2" => 0, "\xa3" => 0, "\xa4" => 0, "\xa5" => 0, "\xa6" => 0, "\xa7" => 0, - "\xa8" => 0, "\xa9" => 0, "\xaa" => 0, "\xab" => 0, "\xac" => 0, "\xad" => 0, "\xae" => 0, "\xaf" => 0, - "\xb0" => 0, "\xb1" => 0, "\xb2" => 0, "\xb3" => 0, "\xb4" => 0, "\xb5" => 0, "\xb6" => 0, "\xb7" => 0, - "\xb8" => 0, "\xb9" => 0, "\xba" => 0, "\xbb" => 0, "\xbc" => 0, "\xbd" => 0, "\xbe" => 0, "\xbf" => 0, - "\xc0" => 2, "\xc1" => 2, "\xc2" => 2, "\xc3" => 2, "\xc4" => 2, "\xc5" => 2, "\xc6" => 2, "\xc7" => 2, - "\xc8" => 2, "\xc9" => 2, "\xca" => 2, "\xcb" => 2, "\xcc" => 2, "\xcd" => 2, "\xce" => 2, "\xcf" => 2, - "\xd0" => 2, "\xd1" => 2, "\xd2" => 2, "\xd3" => 2, "\xd4" => 2, "\xd5" => 2, "\xd6" => 2, "\xd7" => 2, - "\xd8" => 2, "\xd9" => 2, "\xda" => 2, "\xdb" => 2, "\xdc" => 2, "\xdd" => 2, "\xde" => 2, "\xdf" => 2, - "\xe0" => 3, "\xe1" => 3, "\xe2" => 3, "\xe3" => 3, "\xe4" => 3, "\xe5" => 3, "\xe6" => 3, "\xe7" => 3, - "\xe8" => 3, "\xe9" => 3, "\xea" => 3, "\xeb" => 3, "\xec" => 3, "\xed" => 3, "\xee" => 3, "\xef" => 3, - "\xf0" => 4, "\xf1" => 4, "\xf2" => 4, "\xf3" => 4, "\xf4" => 4, "\xf5" => 4, "\xf6" => 4, "\xf7" => 4, - "\xf8" => 5, "\xf9" => 5, "\xfa" => 5, "\xfb" => 5, "\xfc" => 6, "\xfd" => 6, "\xfe" => 0, "\xff" => 0, - ]; - - private $data = ''; - private $dataSize = 0; - private $map = []; - private $charCount = 0; - private $currentPos = 0; - private $fixedWidth = 0; - - /** - * @param resource|string $input - */ - public function __construct($input, ?string $charset = 'utf-8') - { - $charset = strtolower(trim($charset)) ?: 'utf-8'; - if ('utf-8' === $charset || 'utf8' === $charset) { - $this->fixedWidth = 0; - $this->map = ['p' => [], 'i' => []]; - } else { - switch ($charset) { - // 16 bits - case 'ucs2': - case 'ucs-2': - case 'utf16': - case 'utf-16': - $this->fixedWidth = 2; - break; - - // 32 bits - case 'ucs4': - case 'ucs-4': - case 'utf32': - case 'utf-32': - $this->fixedWidth = 4; - break; - - // 7-8 bit charsets: (us-)?ascii, (iso|iec)-?8859-?[0-9]+, windows-?125[0-9], cp-?[0-9]+, ansi, macintosh, - // koi-?7, koi-?8-?.+, mik, (cork|t1), v?iscii - // and fallback - default: - $this->fixedWidth = 1; - } - } - if (\is_resource($input)) { - $blocks = 512; - if (stream_get_meta_data($input)['seekable'] ?? false) { - rewind($input); - } - while (false !== $read = fread($input, $blocks)) { - $this->write($read); - } - } else { - $this->write($input); - } - } - - public function read(int $length): ?string - { - if ($this->currentPos >= $this->charCount) { - return null; - } - $length = ($this->currentPos + $length > $this->charCount) ? $this->charCount - $this->currentPos : $length; - if ($this->fixedWidth > 0) { - $len = $length * $this->fixedWidth; - $ret = substr($this->data, $this->currentPos * $this->fixedWidth, $len); - $this->currentPos += $length; - } else { - $end = $this->currentPos + $length; - $end = $end > $this->charCount ? $this->charCount : $end; - $ret = ''; - $start = 0; - if ($this->currentPos > 0) { - $start = $this->map['p'][$this->currentPos - 1]; - } - $to = $start; - for (; $this->currentPos < $end; ++$this->currentPos) { - if (isset($this->map['i'][$this->currentPos])) { - $ret .= substr($this->data, $start, $to - $start).'?'; - $start = $this->map['p'][$this->currentPos]; - } else { - $to = $this->map['p'][$this->currentPos]; - } - } - $ret .= substr($this->data, $start, $to - $start); - } - - return $ret; - } - - public function readBytes(int $length): ?array - { - if (null !== $read = $this->read($length)) { - return array_map('ord', str_split($read, 1)); - } - - return null; - } - - public function setPointer(int $charOffset): void - { - if ($this->charCount < $charOffset) { - $charOffset = $this->charCount; - } - $this->currentPos = $charOffset; - } - - public function write(string $chars): void - { - $ignored = ''; - $this->data .= $chars; - if ($this->fixedWidth > 0) { - $strlen = \strlen($chars); - $ignoredL = $strlen % $this->fixedWidth; - $ignored = $ignoredL ? substr($chars, -$ignoredL) : ''; - $this->charCount += ($strlen - $ignoredL) / $this->fixedWidth; - } else { - $this->charCount += $this->getUtf8CharPositions($chars, $this->dataSize, $ignored); - } - $this->dataSize = \strlen($this->data) - \strlen($ignored); - } - - private function getUtf8CharPositions(string $string, int $startOffset, string &$ignoredChars): int - { - $strlen = \strlen($string); - $charPos = \count($this->map['p']); - $foundChars = 0; - $invalid = false; - for ($i = 0; $i < $strlen; ++$i) { - $char = $string[$i]; - $size = self::UTF8_LENGTH_MAP[$char]; - if (0 == $size) { - /* char is invalid, we must wait for a resync */ - $invalid = true; - continue; - } - - if ($invalid) { - /* We mark the chars as invalid and start a new char */ - $this->map['p'][$charPos + $foundChars] = $startOffset + $i; - $this->map['i'][$charPos + $foundChars] = true; - ++$foundChars; - $invalid = false; - } - if (($i + $size) > $strlen) { - $ignoredChars = substr($string, $i); - break; - } - for ($j = 1; $j < $size; ++$j) { - $char = $string[$i + $j]; - if ($char > "\x7F" && $char < "\xC0") { - // Valid - continue parsing - } else { - /* char is invalid, we must wait for a resync */ - $invalid = true; - continue 2; - } - } - /* Ok we got a complete char here */ - $this->map['p'][$charPos + $foundChars] = $startOffset + $i + $size; - $i += $j - 1; - ++$foundChars; - } - - return $foundChars; - } -} diff --git a/vendor/symfony/mime/Crypto/SMime.php b/vendor/symfony/mime/Crypto/SMime.php deleted file mode 100644 index 55941be..0000000 --- a/vendor/symfony/mime/Crypto/SMime.php +++ /dev/null @@ -1,111 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Crypto; - -use Symfony\Component\Mime\Exception\RuntimeException; -use Symfony\Component\Mime\Part\SMimePart; - -/** - * @author Sebastiaan Stok - * - * @internal - */ -abstract class SMime -{ - protected function normalizeFilePath(string $path): string - { - if (!file_exists($path)) { - throw new RuntimeException(sprintf('File does not exist: %s.', $path)); - } - - return 'file://'.str_replace('\\', '/', realpath($path)); - } - - protected function iteratorToFile(iterable $iterator, $stream): void - { - foreach ($iterator as $chunk) { - fwrite($stream, $chunk); - } - } - - protected function convertMessageToSMimePart($stream, string $type, string $subtype): SMimePart - { - rewind($stream); - - $headers = ''; - - while (!feof($stream)) { - $buffer = fread($stream, 78); - $headers .= $buffer; - - // Detect ending of header list - if (preg_match('/(\r\n\r\n|\n\n)/', $headers, $match)) { - $headersPosEnd = strpos($headers, $headerBodySeparator = $match[0]); - - break; - } - } - - $headers = $this->getMessageHeaders(trim(substr($headers, 0, $headersPosEnd))); - - fseek($stream, $headersPosEnd + \strlen($headerBodySeparator)); - - return new SMimePart($this->getStreamIterator($stream), $type, $subtype, $this->getParametersFromHeader($headers['content-type'])); - } - - protected function getStreamIterator($stream): iterable - { - while (!feof($stream)) { - yield fread($stream, 16372); - } - } - - private function getMessageHeaders(string $headerData): array - { - $headers = []; - $headerLines = explode("\r\n", str_replace("\n", "\r\n", str_replace("\r\n", "\n", $headerData))); - $currentHeaderName = ''; - - // Transform header lines into an associative array - foreach ($headerLines as $headerLine) { - // Empty lines between headers indicate a new mime-entity - if ('' === $headerLine) { - break; - } - - // Handle headers that span multiple lines - if (false === strpos($headerLine, ':')) { - $headers[$currentHeaderName] .= ' '.trim($headerLine); - continue; - } - - $header = explode(':', $headerLine, 2); - $currentHeaderName = strtolower($header[0]); - $headers[$currentHeaderName] = trim($header[1]); - } - - return $headers; - } - - private function getParametersFromHeader(string $header): array - { - $params = []; - - preg_match_all('/(?P[a-z-0-9]+)=(?P"[^"]+"|(?:[^\s;]+|$))(?:\s+;)?/i', $header, $matches); - - foreach ($matches['value'] as $pos => $paramValue) { - $params[$matches['name'][$pos]] = trim($paramValue, '"'); - } - - return $params; - } -} diff --git a/vendor/symfony/mime/Crypto/SMimeEncrypter.php b/vendor/symfony/mime/Crypto/SMimeEncrypter.php deleted file mode 100644 index d6961a6..0000000 --- a/vendor/symfony/mime/Crypto/SMimeEncrypter.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Crypto; - -use Symfony\Component\Mime\Exception\RuntimeException; -use Symfony\Component\Mime\Message; - -/** - * @author Sebastiaan Stok - */ -final class SMimeEncrypter extends SMime -{ - private $certs; - private $cipher; - - /** - * @param string|string[] $certificate The path (or array of paths) of the file(s) containing the X.509 certificate(s) - * @param int|null $cipher A set of algorithms used to encrypt the message. Must be one of these PHP constants: https://www.php.net/manual/en/openssl.ciphers.php - */ - public function __construct($certificate, int $cipher = null) - { - if (!\extension_loaded('openssl')) { - throw new \LogicException('PHP extension "openssl" is required to use SMime.'); - } - - if (\is_array($certificate)) { - $this->certs = array_map([$this, 'normalizeFilePath'], $certificate); - } else { - $this->certs = $this->normalizeFilePath($certificate); - } - - $this->cipher = $cipher ?? OPENSSL_CIPHER_AES_256_CBC; - } - - public function encrypt(Message $message): Message - { - $bufferFile = tmpfile(); - $outputFile = tmpfile(); - - $this->iteratorToFile($message->toIterable(), $bufferFile); - - if (!@openssl_pkcs7_encrypt(stream_get_meta_data($bufferFile)['uri'], stream_get_meta_data($outputFile)['uri'], $this->certs, [], 0, $this->cipher)) { - throw new RuntimeException(sprintf('Failed to encrypt S/Mime message. Error: "%s".', openssl_error_string())); - } - - $mimePart = $this->convertMessageToSMimePart($outputFile, 'application', 'pkcs7-mime'); - $mimePart->getHeaders() - ->addTextHeader('Content-Transfer-Encoding', 'base64') - ->addParameterizedHeader('Content-Disposition', 'attachment', ['name' => 'smime.p7m']) - ; - - return new Message($message->getHeaders(), $mimePart); - } -} diff --git a/vendor/symfony/mime/Crypto/SMimeSigner.php b/vendor/symfony/mime/Crypto/SMimeSigner.php deleted file mode 100644 index 243aaf1..0000000 --- a/vendor/symfony/mime/Crypto/SMimeSigner.php +++ /dev/null @@ -1,71 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Crypto; - -use Symfony\Component\Mime\Exception\RuntimeException; -use Symfony\Component\Mime\Message; - -/** - * @author Sebastiaan Stok - */ -final class SMimeSigner extends SMime -{ - private $signCertificate; - private $signPrivateKey; - private $signOptions; - private $extraCerts; - - /** - * @var string|null - */ - private $privateKeyPassphrase; - - /** - * @param string $certificate The path of the file containing the signing certificate (in PEM format) - * @param string $privateKey The path of the file containing the private key (in PEM format) - * @param string|null $privateKeyPassphrase A passphrase of the private key (if any) - * @param string|null $extraCerts The path of the file containing intermediate certificates (in PEM format) needed by the signing certificate - * @param int|null $signOptions Bitwise operator options for openssl_pkcs7_sign() (@see https://secure.php.net/manual/en/openssl.pkcs7.flags.php) - */ - public function __construct(string $certificate, string $privateKey, string $privateKeyPassphrase = null, string $extraCerts = null, int $signOptions = null) - { - if (!\extension_loaded('openssl')) { - throw new \LogicException('PHP extension "openssl" is required to use SMime.'); - } - - $this->signCertificate = $this->normalizeFilePath($certificate); - - if (null !== $privateKeyPassphrase) { - $this->signPrivateKey = [$this->normalizeFilePath($privateKey), $privateKeyPassphrase]; - } else { - $this->signPrivateKey = $this->normalizeFilePath($privateKey); - } - - $this->signOptions = $signOptions ?? PKCS7_DETACHED; - $this->extraCerts = $extraCerts ? realpath($extraCerts) : null; - $this->privateKeyPassphrase = $privateKeyPassphrase; - } - - public function sign(Message $message): Message - { - $bufferFile = tmpfile(); - $outputFile = tmpfile(); - - $this->iteratorToFile($message->getBody()->toIterable(), $bufferFile); - - if (!@openssl_pkcs7_sign(stream_get_meta_data($bufferFile)['uri'], stream_get_meta_data($outputFile)['uri'], $this->signCertificate, $this->signPrivateKey, [], $this->signOptions, $this->extraCerts)) { - throw new RuntimeException(sprintf('Failed to sign S/Mime message. Error: "%s".', openssl_error_string())); - } - - return new Message($message->getHeaders(), $this->convertMessageToSMimePart($outputFile, 'multipart', 'signed')); - } -} diff --git a/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php b/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php deleted file mode 100644 index e24beb0..0000000 --- a/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Registers custom mime types guessers. - * - * @author Fabien Potencier - */ -class AddMimeTypeGuesserPass implements CompilerPassInterface -{ - private $mimeTypesService; - private $mimeTypeGuesserTag; - - public function __construct(string $mimeTypesService = 'mime_types', string $mimeTypeGuesserTag = 'mime.mime_type_guesser') - { - $this->mimeTypesService = $mimeTypesService; - $this->mimeTypeGuesserTag = $mimeTypeGuesserTag; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if ($container->has($this->mimeTypesService)) { - $definition = $container->findDefinition($this->mimeTypesService); - foreach ($container->findTaggedServiceIds($this->mimeTypeGuesserTag, true) as $id => $attributes) { - $definition->addMethodCall('registerGuesser', [new Reference($id)]); - } - } - } -} diff --git a/vendor/symfony/mime/Email.php b/vendor/symfony/mime/Email.php deleted file mode 100644 index fb91262..0000000 --- a/vendor/symfony/mime/Email.php +++ /dev/null @@ -1,599 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime; - -use Symfony\Component\Mime\Exception\LogicException; -use Symfony\Component\Mime\Part\AbstractPart; -use Symfony\Component\Mime\Part\DataPart; -use Symfony\Component\Mime\Part\Multipart\AlternativePart; -use Symfony\Component\Mime\Part\Multipart\MixedPart; -use Symfony\Component\Mime\Part\Multipart\RelatedPart; -use Symfony\Component\Mime\Part\TextPart; - -/** - * @author Fabien Potencier - */ -class Email extends Message -{ - const PRIORITY_HIGHEST = 1; - const PRIORITY_HIGH = 2; - const PRIORITY_NORMAL = 3; - const PRIORITY_LOW = 4; - const PRIORITY_LOWEST = 5; - - private const PRIORITY_MAP = [ - self::PRIORITY_HIGHEST => 'Highest', - self::PRIORITY_HIGH => 'High', - self::PRIORITY_NORMAL => 'Normal', - self::PRIORITY_LOW => 'Low', - self::PRIORITY_LOWEST => 'Lowest', - ]; - - private $text; - private $textCharset; - private $html; - private $htmlCharset; - private $attachments = []; - - /** - * @return $this - */ - public function subject(string $subject) - { - return $this->setHeaderBody('Text', 'Subject', $subject); - } - - public function getSubject(): ?string - { - return $this->getHeaders()->getHeaderBody('Subject'); - } - - /** - * @return $this - */ - public function date(\DateTimeInterface $dateTime) - { - return $this->setHeaderBody('Date', 'Date', $dateTime); - } - - public function getDate(): ?\DateTimeImmutable - { - return $this->getHeaders()->getHeaderBody('Date'); - } - - /** - * @param Address|string $address - * - * @return $this - */ - public function returnPath($address) - { - return $this->setHeaderBody('Path', 'Return-Path', Address::create($address)); - } - - public function getReturnPath(): ?Address - { - return $this->getHeaders()->getHeaderBody('Return-Path'); - } - - /** - * @param Address|string $address - * - * @return $this - */ - public function sender($address) - { - return $this->setHeaderBody('Mailbox', 'Sender', Address::create($address)); - } - - public function getSender(): ?Address - { - return $this->getHeaders()->getHeaderBody('Sender'); - } - - /** - * @param Address|string ...$addresses - * - * @return $this - */ - public function addFrom(...$addresses) - { - return $this->addListAddressHeaderBody('From', $addresses); - } - - /** - * @param Address|string ...$addresses - * - * @return $this - */ - public function from(...$addresses) - { - return $this->setListAddressHeaderBody('From', $addresses); - } - - /** - * @return Address[] - */ - public function getFrom(): array - { - return $this->getHeaders()->getHeaderBody('From') ?: []; - } - - /** - * @param Address|string ...$addresses - * - * @return $this - */ - public function addReplyTo(...$addresses) - { - return $this->addListAddressHeaderBody('Reply-To', $addresses); - } - - /** - * @param Address|string ...$addresses - * - * @return $this - */ - public function replyTo(...$addresses) - { - return $this->setListAddressHeaderBody('Reply-To', $addresses); - } - - /** - * @return Address[] - */ - public function getReplyTo(): array - { - return $this->getHeaders()->getHeaderBody('Reply-To') ?: []; - } - - /** - * @param Address|string ...$addresses - * - * @return $this - */ - public function addTo(...$addresses) - { - return $this->addListAddressHeaderBody('To', $addresses); - } - - /** - * @param Address|string ...$addresses - * - * @return $this - */ - public function to(...$addresses) - { - return $this->setListAddressHeaderBody('To', $addresses); - } - - /** - * @return Address[] - */ - public function getTo(): array - { - return $this->getHeaders()->getHeaderBody('To') ?: []; - } - - /** - * @param Address|string ...$addresses - * - * @return $this - */ - public function addCc(...$addresses) - { - return $this->addListAddressHeaderBody('Cc', $addresses); - } - - /** - * @param Address|string ...$addresses - * - * @return $this - */ - public function cc(...$addresses) - { - return $this->setListAddressHeaderBody('Cc', $addresses); - } - - /** - * @return Address[] - */ - public function getCc(): array - { - return $this->getHeaders()->getHeaderBody('Cc') ?: []; - } - - /** - * @param Address|string ...$addresses - * - * @return $this - */ - public function addBcc(...$addresses) - { - return $this->addListAddressHeaderBody('Bcc', $addresses); - } - - /** - * @param Address|string ...$addresses - * - * @return $this - */ - public function bcc(...$addresses) - { - return $this->setListAddressHeaderBody('Bcc', $addresses); - } - - /** - * @return Address[] - */ - public function getBcc(): array - { - return $this->getHeaders()->getHeaderBody('Bcc') ?: []; - } - - /** - * Sets the priority of this message. - * - * The value is an integer where 1 is the highest priority and 5 is the lowest. - * - * @return $this - */ - public function priority(int $priority) - { - if ($priority > 5) { - $priority = 5; - } elseif ($priority < 1) { - $priority = 1; - } - - return $this->setHeaderBody('Text', 'X-Priority', sprintf('%d (%s)', $priority, self::PRIORITY_MAP[$priority])); - } - - /** - * Get the priority of this message. - * - * The returned value is an integer where 1 is the highest priority and 5 - * is the lowest. - */ - public function getPriority(): int - { - list($priority) = sscanf($this->getHeaders()->getHeaderBody('X-Priority'), '%[1-5]'); - - return $priority ?? 3; - } - - /** - * @param resource|string $body - * - * @return $this - */ - public function text($body, string $charset = 'utf-8') - { - $this->text = $body; - $this->textCharset = $charset; - - return $this; - } - - /** - * @return resource|string|null - */ - public function getTextBody() - { - return $this->text; - } - - public function getTextCharset(): ?string - { - return $this->textCharset; - } - - /** - * @param resource|string|null $body - * - * @return $this - */ - public function html($body, string $charset = 'utf-8') - { - $this->html = $body; - $this->htmlCharset = $charset; - - return $this; - } - - /** - * @return resource|string|null - */ - public function getHtmlBody() - { - return $this->html; - } - - public function getHtmlCharset(): ?string - { - return $this->htmlCharset; - } - - /** - * @param resource|string $body - * - * @return $this - */ - public function attach($body, string $name = null, string $contentType = null) - { - $this->attachments[] = ['body' => $body, 'name' => $name, 'content-type' => $contentType, 'inline' => false]; - - return $this; - } - - /** - * @return $this - */ - public function attachFromPath(string $path, string $name = null, string $contentType = null) - { - $this->attachments[] = ['path' => $path, 'name' => $name, 'content-type' => $contentType, 'inline' => false]; - - return $this; - } - - /** - * @param resource|string $body - * - * @return $this - */ - public function embed($body, string $name = null, string $contentType = null) - { - $this->attachments[] = ['body' => $body, 'name' => $name, 'content-type' => $contentType, 'inline' => true]; - - return $this; - } - - /** - * @return $this - */ - public function embedFromPath(string $path, string $name = null, string $contentType = null) - { - $this->attachments[] = ['path' => $path, 'name' => $name, 'content-type' => $contentType, 'inline' => true]; - - return $this; - } - - /** - * @return $this - */ - public function attachPart(DataPart $part) - { - $this->attachments[] = ['part' => $part]; - - return $this; - } - - /** - * @return DataPart[] - */ - public function getAttachments(): array - { - $parts = []; - foreach ($this->attachments as $attachment) { - $parts[] = $this->createDataPart($attachment); - } - - return $parts; - } - - public function getBody(): AbstractPart - { - if (null !== $body = parent::getBody()) { - return $body; - } - - return $this->generateBody(); - } - - public function ensureValidity() - { - if (null === $this->text && null === $this->html && !$this->attachments) { - throw new LogicException('A message must have a text or an HTML part or attachments.'); - } - - parent::ensureValidity(); - } - - /** - * Generates an AbstractPart based on the raw body of a message. - * - * The most "complex" part generated by this method is when there is text and HTML bodies - * with related images for the HTML part and some attachments: - * - * multipart/mixed - * | - * |------------> multipart/related - * | | - * | |------------> multipart/alternative - * | | | - * | | ------------> text/plain (with content) - * | | | - * | | ------------> text/html (with content) - * | | - * | ------------> image/png (with content) - * | - * ------------> application/pdf (with content) - */ - private function generateBody(): AbstractPart - { - $this->ensureValidity(); - - [$htmlPart, $attachmentParts, $inlineParts] = $this->prepareParts(); - - $part = null === $this->text ? null : new TextPart($this->text, $this->textCharset); - if (null !== $htmlPart) { - if (null !== $part) { - $part = new AlternativePart($part, $htmlPart); - } else { - $part = $htmlPart; - } - } - - if ($inlineParts) { - $part = new RelatedPart($part, ...$inlineParts); - } - - if ($attachmentParts) { - if ($part) { - $part = new MixedPart($part, ...$attachmentParts); - } else { - $part = new MixedPart(...$attachmentParts); - } - } - - return $part; - } - - private function prepareParts(): ?array - { - $names = []; - $htmlPart = null; - $html = $this->html; - if (null !== $this->html) { - if (\is_resource($html)) { - if (stream_get_meta_data($html)['seekable'] ?? false) { - rewind($html); - } - - $html = stream_get_contents($html); - } - $htmlPart = new TextPart($html, $this->htmlCharset, 'html'); - preg_match_all('(]*src\s*=\s*(?:([\'"])cid:([^"]+)\\1|cid:([^>\s]+)))i', $html, $names); - $names = array_filter(array_unique(array_merge($names[2], $names[3]))); - } - - $attachmentParts = $inlineParts = []; - foreach ($this->attachments as $attachment) { - foreach ($names as $name) { - if (isset($attachment['part'])) { - continue; - } - if ($name !== $attachment['name']) { - continue; - } - if (isset($inlineParts[$name])) { - continue 2; - } - $attachment['inline'] = true; - $inlineParts[$name] = $part = $this->createDataPart($attachment); - $html = str_replace('cid:'.$name, 'cid:'.$part->getContentId(), $html); - continue 2; - } - $attachmentParts[] = $this->createDataPart($attachment); - } - if (null !== $htmlPart) { - $htmlPart = new TextPart($html, $this->htmlCharset, 'html'); - } - - return [$htmlPart, $attachmentParts, array_values($inlineParts)]; - } - - private function createDataPart(array $attachment): DataPart - { - if (isset($attachment['part'])) { - return $attachment['part']; - } - - if (isset($attachment['body'])) { - $part = new DataPart($attachment['body'], $attachment['name'] ?? null, $attachment['content-type'] ?? null); - } else { - $part = DataPart::fromPath($attachment['path'] ?? '', $attachment['name'] ?? null, $attachment['content-type'] ?? null); - } - if ($attachment['inline']) { - $part->asInline(); - } - - return $part; - } - - /** - * @return $this - */ - private function setHeaderBody(string $type, string $name, $body): object - { - $this->getHeaders()->setHeaderBody($type, $name, $body); - - return $this; - } - - private function addListAddressHeaderBody(string $name, array $addresses) - { - if (!$header = $this->getHeaders()->get($name)) { - return $this->setListAddressHeaderBody($name, $addresses); - } - $header->addAddresses(Address::createArray($addresses)); - - return $this; - } - - private function setListAddressHeaderBody(string $name, array $addresses) - { - $addresses = Address::createArray($addresses); - $headers = $this->getHeaders(); - if ($header = $headers->get($name)) { - $header->setAddresses($addresses); - } else { - $headers->addMailboxListHeader($name, $addresses); - } - - return $this; - } - - /** - * @internal - */ - public function __serialize(): array - { - if (\is_resource($this->text)) { - if (stream_get_meta_data($this->text)['seekable'] ?? false) { - rewind($this->text); - } - - $this->text = stream_get_contents($this->text); - } - - if (\is_resource($this->html)) { - if (stream_get_meta_data($this->html)['seekable'] ?? false) { - rewind($this->html); - } - - $this->html = stream_get_contents($this->html); - } - - foreach ($this->attachments as $i => $attachment) { - if (isset($attachment['body']) && \is_resource($attachment['body'])) { - if (stream_get_meta_data($attachment['body'])['seekable'] ?? false) { - rewind($attachment['body']); - } - - $this->attachments[$i]['body'] = stream_get_contents($attachment['body']); - } - } - - return [$this->text, $this->textCharset, $this->html, $this->htmlCharset, $this->attachments, parent::__serialize()]; - } - - /** - * @internal - */ - public function __unserialize(array $data): void - { - [$this->text, $this->textCharset, $this->html, $this->htmlCharset, $this->attachments, $parentData] = $data; - - parent::__unserialize($parentData); - } -} diff --git a/vendor/symfony/mime/Encoder/AddressEncoderInterface.php b/vendor/symfony/mime/Encoder/AddressEncoderInterface.php deleted file mode 100644 index de477d8..0000000 --- a/vendor/symfony/mime/Encoder/AddressEncoderInterface.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Encoder; - -use Symfony\Component\Mime\Exception\AddressEncoderException; - -/** - * @author Christian Schmidt - */ -interface AddressEncoderInterface -{ - /** - * Encodes an email address. - * - * @throws AddressEncoderException if the email cannot be represented in - * the encoding implemented by this class - */ - public function encodeString(string $address): string; -} diff --git a/vendor/symfony/mime/Encoder/Base64ContentEncoder.php b/vendor/symfony/mime/Encoder/Base64ContentEncoder.php deleted file mode 100644 index 338490b..0000000 --- a/vendor/symfony/mime/Encoder/Base64ContentEncoder.php +++ /dev/null @@ -1,48 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Encoder; - -use Symfony\Component\Mime\Exception\RuntimeException; - -/** - * @author Fabien Potencier - */ -final class Base64ContentEncoder extends Base64Encoder implements ContentEncoderInterface -{ - public function encodeByteStream($stream, int $maxLineLength = 0): iterable - { - if (!\is_resource($stream)) { - throw new \TypeError(sprintf('Method "%s" takes a stream as a first argument.', __METHOD__)); - } - - $filter = stream_filter_append($stream, 'convert.base64-encode', \STREAM_FILTER_READ, [ - 'line-length' => 0 >= $maxLineLength || 76 < $maxLineLength ? 76 : $maxLineLength, - 'line-break-chars' => "\r\n", - ]); - if (!\is_resource($filter)) { - throw new RuntimeException('Unable to set the base64 content encoder to the filter.'); - } - - if (stream_get_meta_data($stream)['seekable'] ?? false) { - rewind($stream); - } - while (!feof($stream)) { - yield fread($stream, 8192); - } - stream_filter_remove($filter); - } - - public function getName(): string - { - return 'base64'; - } -} diff --git a/vendor/symfony/mime/Encoder/Base64Encoder.php b/vendor/symfony/mime/Encoder/Base64Encoder.php deleted file mode 100644 index 7106478..0000000 --- a/vendor/symfony/mime/Encoder/Base64Encoder.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Encoder; - -/** - * @author Chris Corbyn - */ -class Base64Encoder implements EncoderInterface -{ - /** - * Takes an unencoded string and produces a Base64 encoded string from it. - * - * Base64 encoded strings have a maximum line length of 76 characters. - * If the first line needs to be shorter, indicate the difference with - * $firstLineOffset. - */ - public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string - { - if (0 >= $maxLineLength || 76 < $maxLineLength) { - $maxLineLength = 76; - } - - $encodedString = base64_encode($string); - $firstLine = ''; - if (0 !== $firstLineOffset) { - $firstLine = substr($encodedString, 0, $maxLineLength - $firstLineOffset)."\r\n"; - $encodedString = substr($encodedString, $maxLineLength - $firstLineOffset); - } - - return $firstLine.trim(chunk_split($encodedString, $maxLineLength, "\r\n")); - } -} diff --git a/vendor/symfony/mime/Encoder/Base64MimeHeaderEncoder.php b/vendor/symfony/mime/Encoder/Base64MimeHeaderEncoder.php deleted file mode 100644 index 5c06f6d..0000000 --- a/vendor/symfony/mime/Encoder/Base64MimeHeaderEncoder.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Encoder; - -/** - * @author Chris Corbyn - */ -final class Base64MimeHeaderEncoder extends Base64Encoder implements MimeHeaderEncoderInterface -{ - public function getName(): string - { - return 'B'; - } - - /** - * Takes an unencoded string and produces a Base64 encoded string from it. - * - * If the charset is iso-2022-jp, it uses mb_encode_mimeheader instead of - * default encodeString, otherwise pass to the parent method. - */ - public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string - { - if ('iso-2022-jp' === strtolower($charset)) { - $old = mb_internal_encoding(); - mb_internal_encoding('utf-8'); - $newstring = mb_encode_mimeheader($string, 'iso-2022-jp', $this->getName(), "\r\n"); - mb_internal_encoding($old); - - return $newstring; - } - - return parent::encodeString($string, $charset, $firstLineOffset, $maxLineLength); - } -} diff --git a/vendor/symfony/mime/Encoder/ContentEncoderInterface.php b/vendor/symfony/mime/Encoder/ContentEncoderInterface.php deleted file mode 100644 index a45ad04..0000000 --- a/vendor/symfony/mime/Encoder/ContentEncoderInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Encoder; - -/** - * @author Chris Corbyn - */ -interface ContentEncoderInterface extends EncoderInterface -{ - /** - * Encodes the stream to a Generator. - * - * @param resource $stream - */ - public function encodeByteStream($stream, int $maxLineLength = 0): iterable; - - /** - * Gets the MIME name of this content encoding scheme. - */ - public function getName(): string; -} diff --git a/vendor/symfony/mime/Encoder/EightBitContentEncoder.php b/vendor/symfony/mime/Encoder/EightBitContentEncoder.php deleted file mode 100644 index 8283120..0000000 --- a/vendor/symfony/mime/Encoder/EightBitContentEncoder.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Encoder; - -/** - * @author Fabien Potencier - */ -final class EightBitContentEncoder implements ContentEncoderInterface -{ - public function encodeByteStream($stream, int $maxLineLength = 0): iterable - { - while (!feof($stream)) { - yield fread($stream, 16372); - } - } - - public function getName(): string - { - return '8bit'; - } - - public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string - { - return $string; - } -} diff --git a/vendor/symfony/mime/Encoder/EncoderInterface.php b/vendor/symfony/mime/Encoder/EncoderInterface.php deleted file mode 100644 index bbf6d48..0000000 --- a/vendor/symfony/mime/Encoder/EncoderInterface.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Encoder; - -/** - * @author Chris Corbyn - */ -interface EncoderInterface -{ - /** - * Encode a given string to produce an encoded string. - * - * @param int $firstLineOffset if first line needs to be shorter - * @param int $maxLineLength - 0 indicates the default length for this encoding - */ - public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string; -} diff --git a/vendor/symfony/mime/Encoder/IdnAddressEncoder.php b/vendor/symfony/mime/Encoder/IdnAddressEncoder.php deleted file mode 100644 index 1c5e32c..0000000 --- a/vendor/symfony/mime/Encoder/IdnAddressEncoder.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Encoder; - -use Symfony\Component\Mime\Exception\AddressEncoderException; - -/** - * An IDN email address encoder. - * - * Encodes the domain part of an address using IDN. This is compatible will all - * SMTP servers. - * - * This encoder does not support email addresses with non-ASCII characters in - * local-part (the substring before @). To send to such addresses, use - * Utf8AddressEncoder together with SmtpUtf8Handler. Your outbound SMTP server must support - * the SMTPUTF8 extension. - * - * @author Christian Schmidt - */ -final class IdnAddressEncoder implements AddressEncoderInterface -{ - /** - * Encodes the domain part of an address using IDN. - * - * @throws AddressEncoderException If local-part contains non-ASCII characters - */ - public function encodeString(string $address): string - { - $i = strrpos($address, '@'); - if (false !== $i) { - $local = substr($address, 0, $i); - $domain = substr($address, $i + 1); - - if (preg_match('/[^\x00-\x7F]/', $local)) { - throw new AddressEncoderException(sprintf('Non-ASCII characters not supported in local-part os "%s".', $address)); - } - - if (preg_match('/[^\x00-\x7F]/', $domain)) { - $address = sprintf('%s@%s', $local, idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46)); - } - } - - return $address; - } -} diff --git a/vendor/symfony/mime/Encoder/MimeHeaderEncoderInterface.php b/vendor/symfony/mime/Encoder/MimeHeaderEncoderInterface.php deleted file mode 100644 index fff2c78..0000000 --- a/vendor/symfony/mime/Encoder/MimeHeaderEncoderInterface.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Encoder; - -/** - * @author Chris Corbyn - */ -interface MimeHeaderEncoderInterface -{ - /** - * Get the MIME name of this content encoding scheme. - */ - public function getName(): string; -} diff --git a/vendor/symfony/mime/Encoder/QpContentEncoder.php b/vendor/symfony/mime/Encoder/QpContentEncoder.php deleted file mode 100644 index e0b8605..0000000 --- a/vendor/symfony/mime/Encoder/QpContentEncoder.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Encoder; - -/** - * @author Lars Strojny - */ -final class QpContentEncoder implements ContentEncoderInterface -{ - public function encodeByteStream($stream, int $maxLineLength = 0): iterable - { - if (!\is_resource($stream)) { - throw new \TypeError(sprintf('Method "%s" takes a stream as a first argument.', __METHOD__)); - } - - // we don't use PHP stream filters here as the content should be small enough - if (stream_get_meta_data($stream)['seekable'] ?? false) { - rewind($stream); - } - - yield $this->encodeString(stream_get_contents($stream), 'utf-8', 0, $maxLineLength); - } - - public function getName(): string - { - return 'quoted-printable'; - } - - public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string - { - return $this->standardize(quoted_printable_encode($string)); - } - - /** - * Make sure CRLF is correct and HT/SPACE are in valid places. - */ - private function standardize(string $string): string - { - // transform CR or LF to CRLF - $string = preg_replace('~=0D(?!=0A)|(? - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Encoder; - -use Symfony\Component\Mime\CharacterStream; - -/** - * @author Chris Corbyn - */ -class QpEncoder implements EncoderInterface -{ - /** - * Pre-computed QP for HUGE optimization. - */ - private static $qpMap = [ - 0 => '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04', - 5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09', - 10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E', - 15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13', - 20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18', - 25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D', - 30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22', - 35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27', - 40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C', - 45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31', - 50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36', - 55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B', - 60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40', - 65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45', - 70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A', - 75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F', - 80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54', - 85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59', - 90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E', - 95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63', - 100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68', - 105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D', - 110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72', - 115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77', - 120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C', - 125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81', - 130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86', - 135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B', - 140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90', - 145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95', - 150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A', - 155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F', - 160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4', - 165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9', - 170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE', - 175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3', - 180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8', - 185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD', - 190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2', - 195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7', - 200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC', - 205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1', - 210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6', - 215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB', - 220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0', - 225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5', - 230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA', - 235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF', - 240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4', - 245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9', - 250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE', - 255 => '=FF', - ]; - - private static $safeMapShare = []; - - /** - * A map of non-encoded ascii characters. - * - * @var string[] - * - * @internal - */ - protected $safeMap = []; - - public function __construct() - { - $id = \get_class($this); - if (!isset(self::$safeMapShare[$id])) { - $this->initSafeMap(); - self::$safeMapShare[$id] = $this->safeMap; - } else { - $this->safeMap = self::$safeMapShare[$id]; - } - } - - protected function initSafeMap(): void - { - foreach (array_merge([0x09, 0x20], range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte) { - $this->safeMap[$byte] = \chr($byte); - } - } - - /** - * {@inheritdoc} - * - * Takes an unencoded string and produces a QP encoded string from it. - * - * QP encoded strings have a maximum line length of 76 characters. - * If the first line needs to be shorter, indicate the difference with - * $firstLineOffset. - */ - public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string - { - if ($maxLineLength > 76 || $maxLineLength <= 0) { - $maxLineLength = 76; - } - - $thisLineLength = $maxLineLength - $firstLineOffset; - - $lines = []; - $lNo = 0; - $lines[$lNo] = ''; - $currentLine = &$lines[$lNo++]; - $size = $lineLen = 0; - $charStream = new CharacterStream($string, $charset); - - // Fetching more than 4 chars at one is slower, as is fetching fewer bytes - // Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6 - // bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes - while (null !== $bytes = $charStream->readBytes(4)) { - $enc = $this->encodeByteSequence($bytes, $size); - - $i = strpos($enc, '=0D=0A'); - $newLineLength = $lineLen + (false === $i ? $size : $i); - - if ($currentLine && $newLineLength >= $thisLineLength) { - $lines[$lNo] = ''; - $currentLine = &$lines[$lNo++]; - $thisLineLength = $maxLineLength; - $lineLen = 0; - } - - $currentLine .= $enc; - - if (false === $i) { - $lineLen += $size; - } else { - // 6 is the length of '=0D=0A'. - $lineLen = $size - strrpos($enc, '=0D=0A') - 6; - } - } - - return $this->standardize(implode("=\r\n", $lines)); - } - - /** - * Encode the given byte array into a verbatim QP form. - */ - private function encodeByteSequence(array $bytes, int &$size): string - { - $ret = ''; - $size = 0; - foreach ($bytes as $b) { - if (isset($this->safeMap[$b])) { - $ret .= $this->safeMap[$b]; - ++$size; - } else { - $ret .= self::$qpMap[$b]; - $size += 3; - } - } - - return $ret; - } - - /** - * Make sure CRLF is correct and HT/SPACE are in valid places. - */ - private function standardize(string $string): string - { - $string = str_replace(["\t=0D=0A", ' =0D=0A', '=0D=0A'], ["=09\r\n", "=20\r\n", "\r\n"], $string); - switch ($end = \ord(substr($string, -1))) { - case 0x09: - case 0x20: - $string = substr_replace($string, self::$qpMap[$end], -1); - } - - return $string; - } -} diff --git a/vendor/symfony/mime/Encoder/QpMimeHeaderEncoder.php b/vendor/symfony/mime/Encoder/QpMimeHeaderEncoder.php deleted file mode 100644 index d1d3837..0000000 --- a/vendor/symfony/mime/Encoder/QpMimeHeaderEncoder.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Encoder; - -/** - * @author Chris Corbyn - */ -final class QpMimeHeaderEncoder extends QpEncoder implements MimeHeaderEncoderInterface -{ - protected function initSafeMap(): void - { - foreach (array_merge( - range(0x61, 0x7A), range(0x41, 0x5A), - range(0x30, 0x39), [0x20, 0x21, 0x2A, 0x2B, 0x2D, 0x2F] - ) as $byte) { - $this->safeMap[$byte] = \chr($byte); - } - } - - public function getName(): string - { - return 'Q'; - } - - public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string - { - return str_replace([' ', '=20', "=\r\n"], ['_', '_', "\r\n"], - parent::encodeString($string, $charset, $firstLineOffset, $maxLineLength) - ); - } -} diff --git a/vendor/symfony/mime/Encoder/Rfc2231Encoder.php b/vendor/symfony/mime/Encoder/Rfc2231Encoder.php deleted file mode 100644 index aa3e062..0000000 --- a/vendor/symfony/mime/Encoder/Rfc2231Encoder.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Encoder; - -use Symfony\Component\Mime\CharacterStream; - -/** - * @author Chris Corbyn - */ -final class Rfc2231Encoder implements EncoderInterface -{ - /** - * Takes an unencoded string and produces a string encoded according to RFC 2231 from it. - */ - public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string - { - $lines = []; - $lineCount = 0; - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; - - if (0 >= $maxLineLength) { - $maxLineLength = 75; - } - - $charStream = new CharacterStream($string, $charset); - $thisLineLength = $maxLineLength - $firstLineOffset; - - while (null !== $char = $charStream->read(4)) { - $encodedChar = rawurlencode($char); - if (0 !== \strlen($currentLine) && \strlen($currentLine.$encodedChar) > $thisLineLength) { - $lines[] = ''; - $currentLine = &$lines[$lineCount++]; - $thisLineLength = $maxLineLength; - } - $currentLine .= $encodedChar; - } - - return implode("\r\n", $lines); - } -} diff --git a/vendor/symfony/mime/Exception/AddressEncoderException.php b/vendor/symfony/mime/Exception/AddressEncoderException.php deleted file mode 100644 index 51ee2e0..0000000 --- a/vendor/symfony/mime/Exception/AddressEncoderException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Exception; - -/** - * @author Fabien Potencier - */ -class AddressEncoderException extends RfcComplianceException -{ -} diff --git a/vendor/symfony/mime/Exception/ExceptionInterface.php b/vendor/symfony/mime/Exception/ExceptionInterface.php deleted file mode 100644 index 1193390..0000000 --- a/vendor/symfony/mime/Exception/ExceptionInterface.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Exception; - -/** - * @author Fabien Potencier - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/vendor/symfony/mime/Exception/InvalidArgumentException.php b/vendor/symfony/mime/Exception/InvalidArgumentException.php deleted file mode 100644 index e89ebae..0000000 --- a/vendor/symfony/mime/Exception/InvalidArgumentException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Exception; - -/** - * @author Fabien Potencier - */ -class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/mime/Exception/LogicException.php b/vendor/symfony/mime/Exception/LogicException.php deleted file mode 100644 index 0508ee7..0000000 --- a/vendor/symfony/mime/Exception/LogicException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Exception; - -/** - * @author Fabien Potencier - */ -class LogicException extends \LogicException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/mime/Exception/RfcComplianceException.php b/vendor/symfony/mime/Exception/RfcComplianceException.php deleted file mode 100644 index 26e4a50..0000000 --- a/vendor/symfony/mime/Exception/RfcComplianceException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Exception; - -/** - * @author Fabien Potencier - */ -class RfcComplianceException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/mime/Exception/RuntimeException.php b/vendor/symfony/mime/Exception/RuntimeException.php deleted file mode 100644 index fb018b0..0000000 --- a/vendor/symfony/mime/Exception/RuntimeException.php +++ /dev/null @@ -1,19 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Exception; - -/** - * @author Fabien Potencier - */ -class RuntimeException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php b/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php deleted file mode 100644 index fe1e0cd..0000000 --- a/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php +++ /dev/null @@ -1,93 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime; - -use Symfony\Component\Mime\Exception\InvalidArgumentException; -use Symfony\Component\Mime\Exception\LogicException; - -/** - * Guesses the MIME type with the binary "file" (only available on *nix). - * - * @author Bernhard Schussek - */ -class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface -{ - private $cmd; - - /** - * The $cmd pattern must contain a "%s" string that will be replaced - * with the file name to guess. - * - * The command output must start with the MIME type of the file. - * - * @param string $cmd The command to run to get the MIME type of a file - */ - public function __construct(string $cmd = 'file -b --mime -- %s 2>/dev/null') - { - $this->cmd = $cmd; - } - - /** - * {@inheritdoc} - */ - public function isGuesserSupported(): bool - { - static $supported = null; - - if (null !== $supported) { - return $supported; - } - - if ('\\' === \DIRECTORY_SEPARATOR || !\function_exists('passthru') || !\function_exists('escapeshellarg')) { - return $supported = false; - } - - ob_start(); - passthru('command -v file', $exitStatus); - $binPath = trim(ob_get_clean()); - - return $supported = 0 === $exitStatus && '' !== $binPath; - } - - /** - * {@inheritdoc} - */ - public function guessMimeType(string $path): ?string - { - if (!is_file($path) || !is_readable($path)) { - throw new InvalidArgumentException(sprintf('The "%s" file does not exist or is not readable.', $path)); - } - - if (!$this->isGuesserSupported()) { - throw new LogicException(sprintf('The "%s" guesser is not supported.', __CLASS__)); - } - - ob_start(); - - // need to use --mime instead of -i. see #6641 - passthru(sprintf($this->cmd, escapeshellarg((0 === strpos($path, '-') ? './' : '').$path)), $return); - if ($return > 0) { - ob_end_clean(); - - return null; - } - - $type = trim(ob_get_clean()); - - if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\+\.]+)#i', $type, $match)) { - // it's not a type, but an error message - return null; - } - - return $match[1]; - } -} diff --git a/vendor/symfony/mime/FileinfoMimeTypeGuesser.php b/vendor/symfony/mime/FileinfoMimeTypeGuesser.php deleted file mode 100644 index b91a4ff..0000000 --- a/vendor/symfony/mime/FileinfoMimeTypeGuesser.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime; - -use Symfony\Component\Mime\Exception\InvalidArgumentException; -use Symfony\Component\Mime\Exception\LogicException; - -/** - * Guesses the MIME type using the PECL extension FileInfo. - * - * @author Bernhard Schussek - */ -class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface -{ - private $magicFile; - - /** - * @param string $magicFile A magic file to use with the finfo instance - * - * @see http://www.php.net/manual/en/function.finfo-open.php - */ - public function __construct(string $magicFile = null) - { - $this->magicFile = $magicFile; - } - - /** - * {@inheritdoc} - */ - public function isGuesserSupported(): bool - { - return \function_exists('finfo_open'); - } - - /** - * {@inheritdoc} - */ - public function guessMimeType(string $path): ?string - { - if (!is_file($path) || !is_readable($path)) { - throw new InvalidArgumentException(sprintf('The "%s" file does not exist or is not readable.', $path)); - } - - if (!$this->isGuesserSupported()) { - throw new LogicException(sprintf('The "%s" guesser is not supported.', __CLASS__)); - } - - if (false === $finfo = new \finfo(FILEINFO_MIME_TYPE, $this->magicFile)) { - return null; - } - - return $finfo->file($path); - } -} diff --git a/vendor/symfony/mime/Header/AbstractHeader.php b/vendor/symfony/mime/Header/AbstractHeader.php deleted file mode 100644 index 548c192..0000000 --- a/vendor/symfony/mime/Header/AbstractHeader.php +++ /dev/null @@ -1,279 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Header; - -use Symfony\Component\Mime\Encoder\QpMimeHeaderEncoder; - -/** - * An abstract base MIME Header. - * - * @author Chris Corbyn - */ -abstract class AbstractHeader implements HeaderInterface -{ - const PHRASE_PATTERN = '(?:(?:(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]+(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?)|(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?"((?:(?:[ \t]*(?:\r\n))?[ \t])?(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])))*(?:(?:[ \t]*(?:\r\n))?[ \t])?"(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?))+?)'; - - private static $encoder; - - private $name; - private $lineLength = 76; - private $lang; - private $charset = 'utf-8'; - - public function __construct(string $name) - { - $this->name = $name; - } - - public function setCharset(string $charset) - { - $this->charset = $charset; - } - - public function getCharset(): ?string - { - return $this->charset; - } - - /** - * Set the language used in this Header. - * - * For example, for US English, 'en-us'. - */ - public function setLanguage(string $lang) - { - $this->lang = $lang; - } - - public function getLanguage(): ?string - { - return $this->lang; - } - - public function getName(): string - { - return $this->name; - } - - public function setMaxLineLength(int $lineLength) - { - $this->lineLength = $lineLength; - } - - public function getMaxLineLength(): int - { - return $this->lineLength; - } - - public function toString(): string - { - return $this->tokensToString($this->toTokens()); - } - - /** - * Produces a compliant, formatted RFC 2822 'phrase' based on the string given. - * - * @param string $string as displayed - * @param bool $shorten the first line to make remove for header name - */ - protected function createPhrase(HeaderInterface $header, string $string, string $charset, bool $shorten = false): string - { - // Treat token as exactly what was given - $phraseStr = $string; - - // If it's not valid - if (!preg_match('/^'.self::PHRASE_PATTERN.'$/D', $phraseStr)) { - // .. but it is just ascii text, try escaping some characters - // and make it a quoted-string - if (preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $phraseStr)) { - foreach (['\\', '"'] as $char) { - $phraseStr = str_replace($char, '\\'.$char, $phraseStr); - } - $phraseStr = '"'.$phraseStr.'"'; - } else { - // ... otherwise it needs encoding - // Determine space remaining on line if first line - if ($shorten) { - $usedLength = \strlen($header->getName().': '); - } else { - $usedLength = 0; - } - $phraseStr = $this->encodeWords($header, $string, $usedLength); - } - } - - return $phraseStr; - } - - /** - * Encode needed word tokens within a string of input. - */ - protected function encodeWords(HeaderInterface $header, string $input, int $usedLength = -1): string - { - $value = ''; - $tokens = $this->getEncodableWordTokens($input); - foreach ($tokens as $token) { - // See RFC 2822, Sect 2.2 (really 2.2 ??) - if ($this->tokenNeedsEncoding($token)) { - // Don't encode starting WSP - $firstChar = substr($token, 0, 1); - switch ($firstChar) { - case ' ': - case "\t": - $value .= $firstChar; - $token = substr($token, 1); - } - - if (-1 == $usedLength) { - $usedLength = \strlen($header->getName().': ') + \strlen($value); - } - $value .= $this->getTokenAsEncodedWord($token, $usedLength); - } else { - $value .= $token; - } - } - - return $value; - } - - protected function tokenNeedsEncoding(string $token): bool - { - return (bool) preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token); - } - - /** - * Splits a string into tokens in blocks of words which can be encoded quickly. - * - * @return string[] - */ - protected function getEncodableWordTokens(string $string): array - { - $tokens = []; - $encodedToken = ''; - // Split at all whitespace boundaries - foreach (preg_split('~(?=[\t ])~', $string) as $token) { - if ($this->tokenNeedsEncoding($token)) { - $encodedToken .= $token; - } else { - if (\strlen($encodedToken) > 0) { - $tokens[] = $encodedToken; - $encodedToken = ''; - } - $tokens[] = $token; - } - } - if (\strlen($encodedToken)) { - $tokens[] = $encodedToken; - } - - return $tokens; - } - - /** - * Get a token as an encoded word for safe insertion into headers. - */ - protected function getTokenAsEncodedWord(string $token, int $firstLineOffset = 0): string - { - if (null === self::$encoder) { - self::$encoder = new QpMimeHeaderEncoder(); - } - - // Adjust $firstLineOffset to account for space needed for syntax - $charsetDecl = $this->charset; - if (null !== $this->lang) { - $charsetDecl .= '*'.$this->lang; - } - $encodingWrapperLength = \strlen('=?'.$charsetDecl.'?'.self::$encoder->getName().'??='); - - if ($firstLineOffset >= 75) { - //Does this logic need to be here? - $firstLineOffset = 0; - } - - $encodedTextLines = explode("\r\n", - self::$encoder->encodeString($token, $this->charset, $firstLineOffset, 75 - $encodingWrapperLength) - ); - - if ('iso-2022-jp' !== strtolower($this->charset)) { - // special encoding for iso-2022-jp using mb_encode_mimeheader - foreach ($encodedTextLines as $lineNum => $line) { - $encodedTextLines[$lineNum] = '=?'.$charsetDecl.'?'.self::$encoder->getName().'?'.$line.'?='; - } - } - - return implode("\r\n ", $encodedTextLines); - } - - /** - * Generates tokens from the given string which include CRLF as individual tokens. - * - * @return string[] - */ - protected function generateTokenLines(string $token): array - { - return preg_split('~(\r\n)~', $token, -1, PREG_SPLIT_DELIM_CAPTURE); - } - - /** - * Generate a list of all tokens in the final header. - */ - protected function toTokens(string $string = null): array - { - if (null === $string) { - $string = $this->getBodyAsString(); - } - - $tokens = []; - // Generate atoms; split at all invisible boundaries followed by WSP - foreach (preg_split('~(?=[ \t])~', $string) as $token) { - $newTokens = $this->generateTokenLines($token); - foreach ($newTokens as $newToken) { - $tokens[] = $newToken; - } - } - - return $tokens; - } - - /** - * Takes an array of tokens which appear in the header and turns them into - * an RFC 2822 compliant string, adding FWSP where needed. - * - * @param string[] $tokens - */ - private function tokensToString(array $tokens): string - { - $lineCount = 0; - $headerLines = []; - $headerLines[] = $this->name.': '; - $currentLine = &$headerLines[$lineCount++]; - - // Build all tokens back into compliant header - foreach ($tokens as $i => $token) { - // Line longer than specified maximum or token was just a new line - if (("\r\n" === $token) || - ($i > 0 && \strlen($currentLine.$token) > $this->lineLength) - && 0 < \strlen($currentLine)) { - $headerLines[] = ''; - $currentLine = &$headerLines[$lineCount++]; - } - - // Append token to the line - if ("\r\n" !== $token) { - $currentLine .= $token; - } - } - - // Implode with FWS (RFC 2822, 2.2.3) - return implode("\r\n", $headerLines); - } -} diff --git a/vendor/symfony/mime/Header/DateHeader.php b/vendor/symfony/mime/Header/DateHeader.php deleted file mode 100644 index a7385d4..0000000 --- a/vendor/symfony/mime/Header/DateHeader.php +++ /dev/null @@ -1,66 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Header; - -/** - * A Date MIME Header. - * - * @author Chris Corbyn - */ -final class DateHeader extends AbstractHeader -{ - private $dateTime; - - public function __construct(string $name, \DateTimeInterface $date) - { - parent::__construct($name); - - $this->setDateTime($date); - } - - /** - * @param \DateTimeInterface $body - */ - public function setBody($body) - { - $this->setDateTime($body); - } - - public function getBody(): \DateTimeImmutable - { - return $this->getDateTime(); - } - - public function getDateTime(): \DateTimeImmutable - { - return $this->dateTime; - } - - /** - * Set the date-time of the Date in this Header. - * - * If a DateTime instance is provided, it is converted to DateTimeImmutable. - */ - public function setDateTime(\DateTimeInterface $dateTime) - { - if ($dateTime instanceof \DateTime) { - $immutable = new \DateTimeImmutable('@'.$dateTime->getTimestamp()); - $dateTime = $immutable->setTimezone($dateTime->getTimezone()); - } - $this->dateTime = $dateTime; - } - - public function getBodyAsString(): string - { - return $this->dateTime->format(\DateTime::RFC2822); - } -} diff --git a/vendor/symfony/mime/Header/HeaderInterface.php b/vendor/symfony/mime/Header/HeaderInterface.php deleted file mode 100644 index 4546947..0000000 --- a/vendor/symfony/mime/Header/HeaderInterface.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Header; - -/** - * A MIME Header. - * - * @author Chris Corbyn - */ -interface HeaderInterface -{ - /** - * Sets the body. - * - * The type depends on the Header concrete class. - * - * @param mixed $body - */ - public function setBody($body); - - /** - * Gets the body. - * - * The return type depends on the Header concrete class. - * - * @return mixed - */ - public function getBody(); - - public function setCharset(string $charset); - - public function getCharset(): ?string; - - public function setLanguage(string $lang); - - public function getLanguage(): ?string; - - public function getName(): string; - - public function setMaxLineLength(int $lineLength); - - public function getMaxLineLength(): int; - - /** - * Gets this Header rendered as a compliant string. - */ - public function toString(): string; - - /** - * Gets the header's body, prepared for folding into a final header value. - * - * This is not necessarily RFC 2822 compliant since folding white space is - * not added at this stage (see {@link toString()} for that). - */ - public function getBodyAsString(): string; -} diff --git a/vendor/symfony/mime/Header/Headers.php b/vendor/symfony/mime/Header/Headers.php deleted file mode 100644 index 9de506e..0000000 --- a/vendor/symfony/mime/Header/Headers.php +++ /dev/null @@ -1,282 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Header; - -use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Exception\LogicException; - -/** - * A collection of headers. - * - * @author Fabien Potencier - */ -final class Headers -{ - private static $uniqueHeaders = [ - 'date', 'from', 'sender', 'reply-to', 'to', 'cc', 'bcc', - 'message-id', 'in-reply-to', 'references', 'subject', - ]; - - private $headers = []; - private $lineLength = 76; - - public function __construct(HeaderInterface ...$headers) - { - foreach ($headers as $header) { - $this->add($header); - } - } - - public function __clone() - { - foreach ($this->headers as $name => $collection) { - foreach ($collection as $i => $header) { - $this->headers[$name][$i] = clone $header; - } - } - } - - public function setMaxLineLength(int $lineLength) - { - $this->lineLength = $lineLength; - foreach ($this->all() as $header) { - $header->setMaxLineLength($lineLength); - } - } - - public function getMaxLineLength(): int - { - return $this->lineLength; - } - - /** - * @param (Address|string)[] $addresses - * - * @return $this - */ - public function addMailboxListHeader(string $name, array $addresses): self - { - return $this->add(new MailboxListHeader($name, Address::createArray($addresses))); - } - - /** - * @param Address|string $address - * - * @return $this - */ - public function addMailboxHeader(string $name, $address): self - { - return $this->add(new MailboxHeader($name, Address::create($address))); - } - - /** - * @param string|array $ids - * - * @return $this - */ - public function addIdHeader(string $name, $ids): self - { - return $this->add(new IdentificationHeader($name, $ids)); - } - - /** - * @param Address|string $path - * - * @return $this - */ - public function addPathHeader(string $name, $path): self - { - return $this->add(new PathHeader($name, $path instanceof Address ? $path : new Address($path))); - } - - /** - * @return $this - */ - public function addDateHeader(string $name, \DateTimeInterface $dateTime): self - { - return $this->add(new DateHeader($name, $dateTime)); - } - - /** - * @return $this - */ - public function addTextHeader(string $name, string $value): self - { - return $this->add(new UnstructuredHeader($name, $value)); - } - - /** - * @return $this - */ - public function addParameterizedHeader(string $name, string $value, array $params = []): self - { - return $this->add(new ParameterizedHeader($name, $value, $params)); - } - - public function has(string $name): bool - { - return isset($this->headers[strtolower($name)]); - } - - /** - * @return $this - */ - public function add(HeaderInterface $header): self - { - static $map = [ - 'date' => DateHeader::class, - 'from' => MailboxListHeader::class, - 'sender' => MailboxHeader::class, - 'reply-to' => MailboxListHeader::class, - 'to' => MailboxListHeader::class, - 'cc' => MailboxListHeader::class, - 'bcc' => MailboxListHeader::class, - 'message-id' => IdentificationHeader::class, - 'in-reply-to' => IdentificationHeader::class, - 'references' => IdentificationHeader::class, - 'return-path' => PathHeader::class, - ]; - - $header->setMaxLineLength($this->lineLength); - $name = strtolower($header->getName()); - - if (isset($map[$name]) && !$header instanceof $map[$name]) { - throw new LogicException(sprintf('The "%s" header must be an instance of "%s" (got "%s").', $header->getName(), $map[$name], \get_class($header))); - } - - if (\in_array($name, self::$uniqueHeaders, true) && isset($this->headers[$name]) && \count($this->headers[$name]) > 0) { - throw new LogicException(sprintf('Impossible to set header "%s" as it\'s already defined and must be unique.', $header->getName())); - } - - $this->headers[$name][] = $header; - - return $this; - } - - public function get(string $name): ?HeaderInterface - { - $name = strtolower($name); - if (!isset($this->headers[$name])) { - return null; - } - - $values = array_values($this->headers[$name]); - - return array_shift($values); - } - - public function all(string $name = null): iterable - { - if (null === $name) { - foreach ($this->headers as $name => $collection) { - foreach ($collection as $header) { - yield $name => $header; - } - } - } elseif (isset($this->headers[strtolower($name)])) { - foreach ($this->headers[strtolower($name)] as $header) { - yield $header; - } - } - } - - public function getNames(): array - { - return array_keys($this->headers); - } - - public function remove(string $name): void - { - unset($this->headers[strtolower($name)]); - } - - public static function isUniqueHeader(string $name): bool - { - return \in_array($name, self::$uniqueHeaders, true); - } - - public function toString(): string - { - $string = ''; - foreach ($this->toArray() as $str) { - $string .= $str."\r\n"; - } - - return $string; - } - - public function toArray(): array - { - $arr = []; - foreach ($this->all() as $header) { - if ('' !== $header->getBodyAsString()) { - $arr[] = $header->toString(); - } - } - - return $arr; - } - - /** - * @internal - */ - public function getHeaderBody($name) - { - return $this->has($name) ? $this->get($name)->getBody() : null; - } - - /** - * @internal - */ - public function setHeaderBody(string $type, string $name, $body): void - { - if ($this->has($name)) { - $this->get($name)->setBody($body); - } else { - $this->{'add'.$type.'Header'}($name, $body); - } - } - - /** - * @internal - */ - public function getHeaderParameter(string $name, string $parameter): ?string - { - if (!$this->has($name)) { - return null; - } - - $header = $this->get($name); - if (!$header instanceof ParameterizedHeader) { - throw new LogicException(sprintf('Unable to get parameter "%s" on header "%s" as the header is not of class "%s".', $parameter, $name, ParameterizedHeader::class)); - } - - return $header->getParameter($parameter); - } - - /** - * @internal - */ - public function setHeaderParameter(string $name, string $parameter, $value): void - { - if (!$this->has($name)) { - throw new LogicException(sprintf('Unable to set parameter "%s" on header "%s" as the header is not defined.', $parameter, $name)); - } - - $header = $this->get($name); - if (!$header instanceof ParameterizedHeader) { - throw new LogicException(sprintf('Unable to set parameter "%s" on header "%s" as the header is not of class "%s".', $parameter, $name, ParameterizedHeader::class)); - } - - $header->setParameter($parameter, $value); - } -} diff --git a/vendor/symfony/mime/Header/IdentificationHeader.php b/vendor/symfony/mime/Header/IdentificationHeader.php deleted file mode 100644 index 8a94574..0000000 --- a/vendor/symfony/mime/Header/IdentificationHeader.php +++ /dev/null @@ -1,110 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Header; - -use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Exception\RfcComplianceException; - -/** - * An ID MIME Header for something like Message-ID or Content-ID (one or more addresses). - * - * @author Chris Corbyn - */ -final class IdentificationHeader extends AbstractHeader -{ - private $ids = []; - private $idsAsAddresses = []; - - /** - * @param string|array $ids - */ - public function __construct(string $name, $ids) - { - parent::__construct($name); - - $this->setId($ids); - } - - /** - * @param string|array $body a string ID or an array of IDs - * - * @throws RfcComplianceException - */ - public function setBody($body) - { - $this->setId($body); - } - - public function getBody(): array - { - return $this->getIds(); - } - - /** - * Set the ID used in the value of this header. - * - * @param string|array $id - * - * @throws RfcComplianceException - */ - public function setId($id) - { - $this->setIds(\is_array($id) ? $id : [$id]); - } - - /** - * Get the ID used in the value of this Header. - * - * If multiple IDs are set only the first is returned. - */ - public function getId(): ?string - { - return $this->ids[0] ?? null; - } - - /** - * Set a collection of IDs to use in the value of this Header. - * - * @param string[] $ids - * - * @throws RfcComplianceException - */ - public function setIds(array $ids) - { - $this->ids = []; - $this->idsAsAddresses = []; - foreach ($ids as $id) { - $this->idsAsAddresses[] = new Address($id); - $this->ids[] = $id; - } - } - - /** - * Get the list of IDs used in this Header. - * - * @return string[] - */ - public function getIds(): array - { - return $this->ids; - } - - public function getBodyAsString(): string - { - $addrs = []; - foreach ($this->idsAsAddresses as $address) { - $addrs[] = '<'.$address->toString().'>'; - } - - return implode(' ', $addrs); - } -} diff --git a/vendor/symfony/mime/Header/MailboxHeader.php b/vendor/symfony/mime/Header/MailboxHeader.php deleted file mode 100644 index b58c825..0000000 --- a/vendor/symfony/mime/Header/MailboxHeader.php +++ /dev/null @@ -1,85 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Header; - -use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Exception\RfcComplianceException; - -/** - * A Mailbox MIME Header for something like Sender (one named address). - * - * @author Fabien Potencier - */ -final class MailboxHeader extends AbstractHeader -{ - private $address; - - public function __construct(string $name, Address $address) - { - parent::__construct($name); - - $this->setAddress($address); - } - - /** - * @param Address $body - * - * @throws RfcComplianceException - */ - public function setBody($body) - { - $this->setAddress($body); - } - - /** - * @throws RfcComplianceException - */ - public function getBody(): Address - { - return $this->getAddress(); - } - - /** - * @throws RfcComplianceException - */ - public function setAddress(Address $address) - { - $this->address = $address; - } - - public function getAddress(): Address - { - return $this->address; - } - - public function getBodyAsString(): string - { - $str = $this->address->getEncodedAddress(); - if ($name = $this->address->getName()) { - $str = $this->createPhrase($this, $name, $this->getCharset(), true).' <'.$str.'>'; - } - - return $str; - } - - /** - * Redefine the encoding requirements for an address. - * - * All "specials" must be encoded as the full header value will not be quoted - * - * @see RFC 2822 3.2.1 - */ - protected function tokenNeedsEncoding(string $token): bool - { - return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token); - } -} diff --git a/vendor/symfony/mime/Header/MailboxListHeader.php b/vendor/symfony/mime/Header/MailboxListHeader.php deleted file mode 100644 index 1d00fdb..0000000 --- a/vendor/symfony/mime/Header/MailboxListHeader.php +++ /dev/null @@ -1,136 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Header; - -use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Exception\RfcComplianceException; - -/** - * A Mailbox list MIME Header for something like From, To, Cc, and Bcc (one or more named addresses). - * - * @author Chris Corbyn - */ -final class MailboxListHeader extends AbstractHeader -{ - private $addresses = []; - - /** - * @param Address[] $addresses - */ - public function __construct(string $name, array $addresses) - { - parent::__construct($name); - - $this->setAddresses($addresses); - } - - /** - * @param Address[] $body - * - * @throws RfcComplianceException - */ - public function setBody($body) - { - $this->setAddresses($body); - } - - /** - * @throws RfcComplianceException - * - * @return Address[] - */ - public function getBody(): array - { - return $this->getAddresses(); - } - - /** - * Sets a list of addresses to be shown in this Header. - * - * @param Address[] $addresses - * - * @throws RfcComplianceException - */ - public function setAddresses(array $addresses) - { - $this->addresses = []; - $this->addAddresses($addresses); - } - - /** - * Sets a list of addresses to be shown in this Header. - * - * @param Address[] $addresses - * - * @throws RfcComplianceException - */ - public function addAddresses(array $addresses) - { - foreach ($addresses as $address) { - $this->addAddress($address); - } - } - - /** - * @throws RfcComplianceException - */ - public function addAddress(Address $address) - { - $this->addresses[] = $address; - } - - /** - * @return Address[] - */ - public function getAddresses(): array - { - return $this->addresses; - } - - /** - * Gets the full mailbox list of this Header as an array of valid RFC 2822 strings. - * - * @throws RfcComplianceException - * - * @return string[] - */ - public function getAddressStrings(): array - { - $strings = []; - foreach ($this->addresses as $address) { - $str = $address->getEncodedAddress(); - if ($name = $address->getName()) { - $str = $this->createPhrase($this, $name, $this->getCharset(), !$strings).' <'.$str.'>'; - } - $strings[] = $str; - } - - return $strings; - } - - public function getBodyAsString(): string - { - return implode(', ', $this->getAddressStrings()); - } - - /** - * Redefine the encoding requirements for addresses. - * - * All "specials" must be encoded as the full header value will not be quoted - * - * @see RFC 2822 3.2.1 - */ - protected function tokenNeedsEncoding(string $token): bool - { - return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token); - } -} diff --git a/vendor/symfony/mime/Header/ParameterizedHeader.php b/vendor/symfony/mime/Header/ParameterizedHeader.php deleted file mode 100644 index d8e5001..0000000 --- a/vendor/symfony/mime/Header/ParameterizedHeader.php +++ /dev/null @@ -1,174 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Header; - -use Symfony\Component\Mime\Encoder\Rfc2231Encoder; - -/** - * @author Chris Corbyn - */ -final class ParameterizedHeader extends UnstructuredHeader -{ - /** - * RFC 2231's definition of a token. - * - * @var string - */ - const TOKEN_REGEX = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)'; - - private $encoder; - private $parameters = []; - - public function __construct(string $name, string $value, array $parameters = []) - { - parent::__construct($name, $value); - - foreach ($parameters as $k => $v) { - $this->setParameter($k, $v); - } - - if ('content-type' !== strtolower($name)) { - $this->encoder = new Rfc2231Encoder(); - } - } - - public function setParameter(string $parameter, ?string $value) - { - $this->setParameters(array_merge($this->getParameters(), [$parameter => $value])); - } - - public function getParameter(string $parameter): string - { - return $this->getParameters()[$parameter] ?? ''; - } - - /** - * @param string[] $parameters - */ - public function setParameters(array $parameters) - { - $this->parameters = $parameters; - } - - /** - * @return string[] - */ - public function getParameters(): array - { - return $this->parameters; - } - - public function getBodyAsString(): string - { - $body = parent::getBodyAsString(); - foreach ($this->parameters as $name => $value) { - if (null !== $value) { - $body .= '; '.$this->createParameter($name, $value); - } - } - - return $body; - } - - /** - * Generate a list of all tokens in the final header. - * - * This doesn't need to be overridden in theory, but it is for implementation - * reasons to prevent potential breakage of attributes. - */ - protected function toTokens(string $string = null): array - { - $tokens = parent::toTokens(parent::getBodyAsString()); - - // Try creating any parameters - foreach ($this->parameters as $name => $value) { - if (null !== $value) { - // Add the semi-colon separator - $tokens[\count($tokens) - 1] .= ';'; - $tokens = array_merge($tokens, $this->generateTokenLines(' '.$this->createParameter($name, $value))); - } - } - - return $tokens; - } - - /** - * Render a RFC 2047 compliant header parameter from the $name and $value. - */ - private function createParameter(string $name, string $value): string - { - $origValue = $value; - - $encoded = false; - // Allow room for parameter name, indices, "=" and DQUOTEs - $maxValueLength = $this->getMaxLineLength() - \strlen($name.'=*N"";') - 1; - $firstLineOffset = 0; - - // If it's not already a valid parameter value... - if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { - // TODO: text, or something else?? - // ... and it's not ascii - if (!preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $value)) { - $encoded = true; - // Allow space for the indices, charset and language - $maxValueLength = $this->getMaxLineLength() - \strlen($name.'*N*="";') - 1; - $firstLineOffset = \strlen($this->getCharset()."'".$this->getLanguage()."'"); - } - } - - // Encode if we need to - if ($encoded || \strlen($value) > $maxValueLength) { - if (null !== $this->encoder) { - $value = $this->encoder->encodeString($origValue, $this->getCharset(), $firstLineOffset, $maxValueLength); - } else { - // We have to go against RFC 2183/2231 in some areas for interoperability - $value = $this->getTokenAsEncodedWord($origValue); - $encoded = false; - } - } - - $valueLines = $this->encoder ? explode("\r\n", $value) : [$value]; - - // Need to add indices - if (\count($valueLines) > 1) { - $paramLines = []; - foreach ($valueLines as $i => $line) { - $paramLines[] = $name.'*'.$i.$this->getEndOfParameterValue($line, true, 0 === $i); - } - - return implode(";\r\n ", $paramLines); - } else { - return $name.$this->getEndOfParameterValue($valueLines[0], $encoded, true); - } - } - - /** - * Returns the parameter value from the "=" and beyond. - * - * @param string $value to append - */ - private function getEndOfParameterValue(string $value, bool $encoded = false, bool $firstLine = false): string - { - if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { - $value = '"'.$value.'"'; - } - $prepend = '='; - if ($encoded) { - $prepend = '*='; - if ($firstLine) { - $prepend = '*='.$this->getCharset()."'".$this->getLanguage()."'"; - } - } - - return $prepend.$value; - } -} diff --git a/vendor/symfony/mime/Header/PathHeader.php b/vendor/symfony/mime/Header/PathHeader.php deleted file mode 100644 index 5101ad0..0000000 --- a/vendor/symfony/mime/Header/PathHeader.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Header; - -use Symfony\Component\Mime\Address; -use Symfony\Component\Mime\Exception\RfcComplianceException; - -/** - * A Path Header, such a Return-Path (one address). - * - * @author Chris Corbyn - */ -final class PathHeader extends AbstractHeader -{ - private $address; - - public function __construct(string $name, Address $address) - { - parent::__construct($name); - - $this->setAddress($address); - } - - /** - * @param Address $body - * - * @throws RfcComplianceException - */ - public function setBody($body) - { - $this->setAddress($body); - } - - public function getBody(): Address - { - return $this->getAddress(); - } - - public function setAddress(Address $address) - { - $this->address = $address; - } - - public function getAddress(): Address - { - return $this->address; - } - - public function getBodyAsString(): string - { - return '<'.$this->address->toString().'>'; - } -} diff --git a/vendor/symfony/mime/Header/UnstructuredHeader.php b/vendor/symfony/mime/Header/UnstructuredHeader.php deleted file mode 100644 index 2085ddf..0000000 --- a/vendor/symfony/mime/Header/UnstructuredHeader.php +++ /dev/null @@ -1,69 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Header; - -/** - * A Simple MIME Header. - * - * @author Chris Corbyn - */ -class UnstructuredHeader extends AbstractHeader -{ - private $value; - - public function __construct(string $name, string $value) - { - parent::__construct($name); - - $this->setValue($value); - } - - /** - * @param string $body - */ - public function setBody($body) - { - $this->setValue($body); - } - - /** - * @return string - */ - public function getBody() - { - return $this->getValue(); - } - - /** - * Get the (unencoded) value of this header. - */ - public function getValue(): string - { - return $this->value; - } - - /** - * Set the (unencoded) value of this header. - */ - public function setValue(string $value) - { - $this->value = $value; - } - - /** - * Get the value of this header prepared for rendering. - */ - public function getBodyAsString(): string - { - return $this->encodeWords($this, $this->value); - } -} diff --git a/vendor/symfony/mime/LICENSE b/vendor/symfony/mime/LICENSE deleted file mode 100644 index 9a9a61b..0000000 --- a/vendor/symfony/mime/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2010-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/mime/Message.php b/vendor/symfony/mime/Message.php deleted file mode 100644 index 5b4e67f..0000000 --- a/vendor/symfony/mime/Message.php +++ /dev/null @@ -1,151 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime; - -use Symfony\Component\Mime\Exception\LogicException; -use Symfony\Component\Mime\Header\Headers; -use Symfony\Component\Mime\Part\AbstractPart; -use Symfony\Component\Mime\Part\TextPart; - -/** - * @author Fabien Potencier - */ -class Message extends RawMessage -{ - private $headers; - private $body; - - public function __construct(Headers $headers = null, AbstractPart $body = null) - { - $this->headers = $headers ? clone $headers : new Headers(); - $this->body = $body; - } - - public function __clone() - { - $this->headers = clone $this->headers; - - if (null !== $this->body) { - $this->body = clone $this->body; - } - } - - /** - * @return $this - */ - public function setBody(AbstractPart $body = null) - { - $this->body = $body; - - return $this; - } - - public function getBody(): ?AbstractPart - { - return $this->body; - } - - /** - * @return $this - */ - public function setHeaders(Headers $headers) - { - $this->headers = $headers; - - return $this; - } - - public function getHeaders(): Headers - { - return $this->headers; - } - - public function getPreparedHeaders(): Headers - { - $headers = clone $this->headers; - - if (!$headers->has('From')) { - throw new LogicException('An email must have a "From" header.'); - } - - $headers->addTextHeader('MIME-Version', '1.0'); - - if (!$headers->has('Date')) { - $headers->addDateHeader('Date', new \DateTimeImmutable()); - } - - // determine the "real" sender - if (!$headers->has('Sender') && \count($froms = $headers->get('From')->getAddresses()) > 1) { - $headers->addMailboxHeader('Sender', $froms[0]); - } - - if (!$headers->has('Message-ID')) { - $headers->addIdHeader('Message-ID', $this->generateMessageId()); - } - - // remove the Bcc field which should NOT be part of the sent message - $headers->remove('Bcc'); - - return $headers; - } - - public function toString(): string - { - if (null === $body = $this->getBody()) { - $body = new TextPart(''); - } - - return $this->getPreparedHeaders()->toString().$body->toString(); - } - - public function toIterable(): iterable - { - if (null === $body = $this->getBody()) { - $body = new TextPart(''); - } - - yield $this->getPreparedHeaders()->toString(); - yield from $body->toIterable(); - } - - public function ensureValidity() - { - if (!$this->headers->has('From')) { - throw new LogicException('An email must have a "From" header.'); - } - - parent::ensureValidity(); - } - - public function generateMessageId(): string - { - if ($this->headers->has('Sender')) { - $sender = $this->headers->get('Sender')->getAddress(); - } elseif ($this->headers->has('From')) { - $sender = $this->headers->get('From')->getAddresses()[0]; - } else { - throw new LogicException('An email must have a "From" or a "Sender" header to compute a Messsage ID.'); - } - - return bin2hex(random_bytes(16)).strstr($sender->getAddress(), '@'); - } - - public function __serialize(): array - { - return [$this->headers, $this->body]; - } - - public function __unserialize(array $data): void - { - [$this->headers, $this->body] = $data; - } -} diff --git a/vendor/symfony/mime/MessageConverter.php b/vendor/symfony/mime/MessageConverter.php deleted file mode 100644 index a810cb7..0000000 --- a/vendor/symfony/mime/MessageConverter.php +++ /dev/null @@ -1,125 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime; - -use Symfony\Component\Mime\Exception\RuntimeException; -use Symfony\Component\Mime\Part\DataPart; -use Symfony\Component\Mime\Part\Multipart\AlternativePart; -use Symfony\Component\Mime\Part\Multipart\MixedPart; -use Symfony\Component\Mime\Part\Multipart\RelatedPart; -use Symfony\Component\Mime\Part\TextPart; - -/** - * @author Fabien Potencier - */ -final class MessageConverter -{ - /** - * @throws RuntimeException when unable to convert the message to an email - */ - public static function toEmail(Message $message): Email - { - if ($message instanceof Email) { - return $message; - } - - // try to convert to a "simple" Email instance - $body = $message->getBody(); - if ($body instanceof TextPart) { - return self::createEmailFromTextPart($message, $body); - } - - if ($body instanceof AlternativePart) { - return self::createEmailFromAlternativePart($message, $body); - } - - if ($body instanceof RelatedPart) { - return self::createEmailFromRelatedPart($message, $body); - } - - if ($body instanceof MixedPart) { - $parts = $body->getParts(); - if ($parts[0] instanceof RelatedPart) { - $email = self::createEmailFromRelatedPart($message, $parts[0]); - } elseif ($parts[0] instanceof AlternativePart) { - $email = self::createEmailFromAlternativePart($message, $parts[0]); - } elseif ($parts[0] instanceof TextPart) { - $email = self::createEmailFromTextPart($message, $parts[0]); - } else { - throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); - } - - return self::attachParts($email, \array_slice($parts, 1)); - } - - throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); - } - - private static function createEmailFromTextPart(Message $message, TextPart $part): Email - { - if ('text' === $part->getMediaType() && 'plain' === $part->getMediaSubtype()) { - return (new Email(clone $message->getHeaders()))->text($part->getBody(), $part->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8'); - } - if ('text' === $part->getMediaType() && 'html' === $part->getMediaSubtype()) { - return (new Email(clone $message->getHeaders()))->html($part->getBody(), $part->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8'); - } - - throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); - } - - private static function createEmailFromAlternativePart(Message $message, AlternativePart $part): Email - { - $parts = $part->getParts(); - if ( - 2 === \count($parts) && - $parts[0] instanceof TextPart && 'text' === $parts[0]->getMediaType() && 'plain' === $parts[0]->getMediaSubtype() && - $parts[1] instanceof TextPart && 'text' === $parts[1]->getMediaType() && 'html' === $parts[1]->getMediaSubtype() - ) { - return (new Email(clone $message->getHeaders())) - ->text($parts[0]->getBody(), $parts[0]->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8') - ->html($parts[1]->getBody(), $parts[1]->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8') - ; - } - - throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); - } - - private static function createEmailFromRelatedPart(Message $message, RelatedPart $part): Email - { - $parts = $part->getParts(); - if ($parts[0] instanceof AlternativePart) { - $email = self::createEmailFromAlternativePart($message, $parts[0]); - } elseif ($parts[0] instanceof TextPart) { - $email = self::createEmailFromTextPart($message, $parts[0]); - } else { - throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); - } - - return self::attachParts($email, \array_slice($parts, 1)); - } - - private static function attachParts(Email $email, array $parts): Email - { - foreach ($parts as $part) { - if (!$part instanceof DataPart) { - throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($email))); - } - - $headers = $part->getPreparedHeaders(); - $method = 'inline' === $headers->getHeaderBody('Content-Disposition') ? 'embed' : 'attach'; - $name = $headers->getHeaderParameter('Content-Disposition', 'filename'); - $email->$method($part->getBody(), $name, $part->getMediaType().'/'.$part->getMediaSubtype()); - } - - return $email; - } -} diff --git a/vendor/symfony/mime/MimeTypeGuesserInterface.php b/vendor/symfony/mime/MimeTypeGuesserInterface.php deleted file mode 100644 index 68b0505..0000000 --- a/vendor/symfony/mime/MimeTypeGuesserInterface.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime; - -/** - * Guesses the MIME type of a file. - * - * @author Fabien Potencier - */ -interface MimeTypeGuesserInterface -{ - /** - * Returns true if this guesser is supported. - */ - public function isGuesserSupported(): bool; - - /** - * Guesses the MIME type of the file with the given path. - * - * @param string $path The path to the file - * - * @return string|null The MIME type or null, if none could be guessed - * - * @throws \LogicException If the guesser is not supported - * @throws \InvalidArgumentException If the file does not exist or is not readable - */ - public function guessMimeType(string $path): ?string; -} diff --git a/vendor/symfony/mime/MimeTypes.php b/vendor/symfony/mime/MimeTypes.php deleted file mode 100644 index 268658d..0000000 --- a/vendor/symfony/mime/MimeTypes.php +++ /dev/null @@ -1,3153 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime; - -use Symfony\Component\Mime\Exception\LogicException; - -/** - * Manages MIME types and file extensions. - * - * For MIME type guessing, you can register custom guessers - * by calling the registerGuesser() method. - * Custom guessers are always called before any default ones: - * - * $guesser = new MimeTypes(); - * $guesser->registerGuesser(new MyCustomMimeTypeGuesser()); - * - * If you want to change the order of the default guessers, just re-register your - * preferred one as a custom one. The last registered guesser is preferred over - * previously registered ones. - * - * Re-registering a built-in guesser also allows you to configure it: - * - * $guesser = new MimeTypes(); - * $guesser->registerGuesser(new FileinfoMimeTypeGuesser('/path/to/magic/file')); - * - * @author Fabien Potencier - */ -final class MimeTypes implements MimeTypesInterface -{ - private $extensions = []; - private $mimeTypes = []; - - /** - * @var MimeTypeGuesserInterface[] - */ - private $guessers = []; - private static $default; - - public function __construct(array $map = []) - { - foreach ($map as $mimeType => $extensions) { - $this->extensions[$mimeType] = $extensions; - - foreach ($extensions as $extension) { - $this->mimeTypes[$extension] = $mimeType; - } - } - $this->registerGuesser(new FileBinaryMimeTypeGuesser()); - $this->registerGuesser(new FileinfoMimeTypeGuesser()); - } - - public static function setDefault(self $default) - { - self::$default = $default; - } - - public static function getDefault(): self - { - return self::$default ?? self::$default = new self(); - } - - /** - * Registers a MIME type guesser. - * - * The last registered guesser has precedence over the other ones. - */ - public function registerGuesser(MimeTypeGuesserInterface $guesser) - { - array_unshift($this->guessers, $guesser); - } - - /** - * {@inheritdoc} - */ - public function getExtensions(string $mimeType): array - { - if ($this->extensions) { - $extensions = $this->extensions[$mimeType] ?? $this->extensions[$lcMimeType = strtolower($mimeType)] ?? null; - } - - return $extensions ?? self::$map[$mimeType] ?? self::$map[$lcMimeType ?? strtolower($mimeType)] ?? []; - } - - /** - * {@inheritdoc} - */ - public function getMimeTypes(string $ext): array - { - if ($this->mimeTypes) { - $mimeTypes = $this->mimeTypes[$ext] ?? $this->mimeTypes[$lcExt = strtolower($ext)] ?? null; - } - - return $mimeTypes ?? self::$reverseMap[$ext] ?? self::$reverseMap[$lcExt ?? strtolower($ext)] ?? []; - } - - /** - * {@inheritdoc} - */ - public function isGuesserSupported(): bool - { - foreach ($this->guessers as $guesser) { - if ($guesser->isGuesserSupported()) { - return true; - } - } - - return false; - } - - /** - * {@inheritdoc} - * - * The file is passed to each registered MIME type guesser in reverse order - * of their registration (last registered is queried first). Once a guesser - * returns a value that is not null, this method terminates and returns the - * value. - */ - public function guessMimeType(string $path): ?string - { - foreach ($this->guessers as $guesser) { - if (!$guesser->isGuesserSupported()) { - continue; - } - - if (null !== $mimeType = $guesser->guessMimeType($path)) { - return $mimeType; - } - } - - if (!$this->isGuesserSupported()) { - throw new LogicException('Unable to guess the MIME type as no guessers are available (have you enable the php_fileinfo extension?).'); - } - - return null; - } - - /** - * A map of MIME types and their default extensions. - * - * Updated from upstream on 2019-01-16 - * - * @see Resources/bin/update_mime_types.php - */ - private static $map = [ - 'application/acrobat' => ['pdf'], - 'application/andrew-inset' => ['ez'], - 'application/annodex' => ['anx'], - 'application/applixware' => ['aw'], - 'application/atom+xml' => ['atom'], - 'application/atomcat+xml' => ['atomcat'], - 'application/atomsvc+xml' => ['atomsvc'], - 'application/ccxml+xml' => ['ccxml'], - 'application/cdmi-capability' => ['cdmia'], - 'application/cdmi-container' => ['cdmic'], - 'application/cdmi-domain' => ['cdmid'], - 'application/cdmi-object' => ['cdmio'], - 'application/cdmi-queue' => ['cdmiq'], - 'application/cdr' => ['cdr'], - 'application/coreldraw' => ['cdr'], - 'application/cu-seeme' => ['cu'], - 'application/davmount+xml' => ['davmount'], - 'application/dbase' => ['dbf'], - 'application/dbf' => ['dbf'], - 'application/dicom' => ['dcm'], - 'application/docbook+xml' => ['dbk', 'docbook'], - 'application/dssc+der' => ['dssc'], - 'application/dssc+xml' => ['xdssc'], - 'application/ecmascript' => ['ecma', 'es'], - 'application/emf' => ['emf'], - 'application/emma+xml' => ['emma'], - 'application/epub+zip' => ['epub'], - 'application/exi' => ['exi'], - 'application/font-tdpfr' => ['pfr'], - 'application/font-woff' => ['woff'], - 'application/futuresplash' => ['swf', 'spl'], - 'application/geo+json' => ['geojson', 'geo.json'], - 'application/gml+xml' => ['gml'], - 'application/gnunet-directory' => ['gnd'], - 'application/gpx' => ['gpx'], - 'application/gpx+xml' => ['gpx'], - 'application/gxf' => ['gxf'], - 'application/gzip' => ['gz'], - 'application/hyperstudio' => ['stk'], - 'application/ico' => ['ico'], - 'application/ics' => ['vcs', 'ics'], - 'application/illustrator' => ['ai'], - 'application/inkml+xml' => ['ink', 'inkml'], - 'application/ipfix' => ['ipfix'], - 'application/java' => ['class'], - 'application/java-archive' => ['jar'], - 'application/java-byte-code' => ['class'], - 'application/java-serialized-object' => ['ser'], - 'application/java-vm' => ['class'], - 'application/javascript' => ['js', 'jsm', 'mjs'], - 'application/jrd+json' => ['jrd'], - 'application/json' => ['json'], - 'application/json-patch+json' => ['json-patch'], - 'application/jsonml+json' => ['jsonml'], - 'application/ld+json' => ['jsonld'], - 'application/lost+xml' => ['lostxml'], - 'application/lotus123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], - 'application/m3u' => ['m3u', 'm3u8', 'vlc'], - 'application/mac-binhex40' => ['hqx'], - 'application/mac-compactpro' => ['cpt'], - 'application/mads+xml' => ['mads'], - 'application/marc' => ['mrc'], - 'application/marcxml+xml' => ['mrcx'], - 'application/mathematica' => ['ma', 'nb', 'mb'], - 'application/mathml+xml' => ['mathml', 'mml'], - 'application/mbox' => ['mbox'], - 'application/mdb' => ['mdb'], - 'application/mediaservercontrol+xml' => ['mscml'], - 'application/metalink+xml' => ['metalink'], - 'application/metalink4+xml' => ['meta4'], - 'application/mets+xml' => ['mets'], - 'application/mods+xml' => ['mods'], - 'application/mp21' => ['m21', 'mp21'], - 'application/mp4' => ['mp4s'], - 'application/ms-tnef' => ['tnef', 'tnf'], - 'application/msaccess' => ['mdb'], - 'application/msexcel' => ['xls', 'xlc', 'xll', 'xlm', 'xlw', 'xla', 'xlt', 'xld'], - 'application/mspowerpoint' => ['ppz', 'ppt', 'pps', 'pot'], - 'application/msword' => ['doc', 'dot'], - 'application/msword-template' => ['dot'], - 'application/mxf' => ['mxf'], - 'application/nappdf' => ['pdf'], - 'application/octet-stream' => ['bin', 'dms', 'lrf', 'mar', 'so', 'dist', 'distz', 'pkg', 'bpk', 'dump', 'elc', 'deploy'], - 'application/oda' => ['oda'], - 'application/oebps-package+xml' => ['opf'], - 'application/ogg' => ['ogx'], - 'application/omdoc+xml' => ['omdoc'], - 'application/onenote' => ['onetoc', 'onetoc2', 'onetmp', 'onepkg'], - 'application/owl+xml' => ['owx'], - 'application/oxps' => ['oxps', 'xps'], - 'application/patch-ops-error+xml' => ['xer'], - 'application/pcap' => ['pcap', 'cap', 'dmp'], - 'application/pdf' => ['pdf'], - 'application/pgp' => ['pgp', 'gpg', 'asc'], - 'application/pgp-encrypted' => ['pgp', 'gpg', 'asc'], - 'application/pgp-keys' => ['skr', 'pkr', 'asc', 'pgp', 'gpg'], - 'application/pgp-signature' => ['asc', 'sig', 'pgp', 'gpg'], - 'application/photoshop' => ['psd'], - 'application/pics-rules' => ['prf'], - 'application/pkcs10' => ['p10'], - 'application/pkcs12' => ['p12', 'pfx'], - 'application/pkcs7-mime' => ['p7m', 'p7c'], - 'application/pkcs7-signature' => ['p7s'], - 'application/pkcs8' => ['p8'], - 'application/pkcs8-encrypted' => ['p8e'], - 'application/pkix-attr-cert' => ['ac'], - 'application/pkix-cert' => ['cer'], - 'application/pkix-crl' => ['crl'], - 'application/pkix-pkipath' => ['pkipath'], - 'application/pkixcmp' => ['pki'], - 'application/pls' => ['pls'], - 'application/pls+xml' => ['pls'], - 'application/postscript' => ['ai', 'eps', 'ps'], - 'application/powerpoint' => ['ppz', 'ppt', 'pps', 'pot'], - 'application/prs.cww' => ['cww'], - 'application/pskc+xml' => ['pskcxml'], - 'application/ram' => ['ram'], - 'application/raml+yaml' => ['raml'], - 'application/rdf+xml' => ['rdf', 'rdfs', 'owl'], - 'application/reginfo+xml' => ['rif'], - 'application/relax-ng-compact-syntax' => ['rnc'], - 'application/resource-lists+xml' => ['rl'], - 'application/resource-lists-diff+xml' => ['rld'], - 'application/rls-services+xml' => ['rs'], - 'application/rpki-ghostbusters' => ['gbr'], - 'application/rpki-manifest' => ['mft'], - 'application/rpki-roa' => ['roa'], - 'application/rsd+xml' => ['rsd'], - 'application/rss+xml' => ['rss'], - 'application/rtf' => ['rtf'], - 'application/sbml+xml' => ['sbml'], - 'application/scvp-cv-request' => ['scq'], - 'application/scvp-cv-response' => ['scs'], - 'application/scvp-vp-request' => ['spq'], - 'application/scvp-vp-response' => ['spp'], - 'application/sdp' => ['sdp'], - 'application/set-payment-initiation' => ['setpay'], - 'application/set-registration-initiation' => ['setreg'], - 'application/shf+xml' => ['shf'], - 'application/sieve' => ['siv'], - 'application/smil' => ['smil', 'smi', 'sml', 'kino'], - 'application/smil+xml' => ['smi', 'smil', 'sml', 'kino'], - 'application/sparql-query' => ['rq'], - 'application/sparql-results+xml' => ['srx'], - 'application/sql' => ['sql'], - 'application/srgs' => ['gram'], - 'application/srgs+xml' => ['grxml'], - 'application/sru+xml' => ['sru'], - 'application/ssdl+xml' => ['ssdl'], - 'application/ssml+xml' => ['ssml'], - 'application/stuffit' => ['sit'], - 'application/tei+xml' => ['tei', 'teicorpus'], - 'application/thraud+xml' => ['tfi'], - 'application/timestamped-data' => ['tsd'], - 'application/trig' => ['trig'], - 'application/vnd.3gpp.pic-bw-large' => ['plb'], - 'application/vnd.3gpp.pic-bw-small' => ['psb'], - 'application/vnd.3gpp.pic-bw-var' => ['pvb'], - 'application/vnd.3gpp2.tcap' => ['tcap'], - 'application/vnd.3m.post-it-notes' => ['pwn'], - 'application/vnd.accpac.simply.aso' => ['aso'], - 'application/vnd.accpac.simply.imp' => ['imp'], - 'application/vnd.acucobol' => ['acu'], - 'application/vnd.acucorp' => ['atc', 'acutc'], - 'application/vnd.adobe.air-application-installer-package+zip' => ['air'], - 'application/vnd.adobe.flash.movie' => ['swf', 'spl'], - 'application/vnd.adobe.formscentral.fcdt' => ['fcdt'], - 'application/vnd.adobe.fxp' => ['fxp', 'fxpl'], - 'application/vnd.adobe.illustrator' => ['ai'], - 'application/vnd.adobe.xdp+xml' => ['xdp'], - 'application/vnd.adobe.xfdf' => ['xfdf'], - 'application/vnd.ahead.space' => ['ahead'], - 'application/vnd.airzip.filesecure.azf' => ['azf'], - 'application/vnd.airzip.filesecure.azs' => ['azs'], - 'application/vnd.amazon.ebook' => ['azw'], - 'application/vnd.americandynamics.acc' => ['acc'], - 'application/vnd.amiga.ami' => ['ami'], - 'application/vnd.android.package-archive' => ['apk'], - 'application/vnd.anser-web-certificate-issue-initiation' => ['cii'], - 'application/vnd.anser-web-funds-transfer-initiation' => ['fti'], - 'application/vnd.antix.game-component' => ['atx'], - 'application/vnd.appimage' => ['appimage'], - 'application/vnd.apple.installer+xml' => ['mpkg'], - 'application/vnd.apple.keynote' => ['key'], - 'application/vnd.apple.mpegurl' => ['m3u8', 'm3u'], - 'application/vnd.aristanetworks.swi' => ['swi'], - 'application/vnd.astraea-software.iota' => ['iota'], - 'application/vnd.audiograph' => ['aep'], - 'application/vnd.blueice.multipass' => ['mpm'], - 'application/vnd.bmi' => ['bmi'], - 'application/vnd.businessobjects' => ['rep'], - 'application/vnd.chemdraw+xml' => ['cdxml'], - 'application/vnd.chess-pgn' => ['pgn'], - 'application/vnd.chipnuts.karaoke-mmd' => ['mmd'], - 'application/vnd.cinderella' => ['cdy'], - 'application/vnd.claymore' => ['cla'], - 'application/vnd.cloanto.rp9' => ['rp9'], - 'application/vnd.clonk.c4group' => ['c4g', 'c4d', 'c4f', 'c4p', 'c4u'], - 'application/vnd.cluetrust.cartomobile-config' => ['c11amc'], - 'application/vnd.cluetrust.cartomobile-config-pkg' => ['c11amz'], - 'application/vnd.coffeescript' => ['coffee'], - 'application/vnd.comicbook+zip' => ['cbz'], - 'application/vnd.comicbook-rar' => ['cbr'], - 'application/vnd.commonspace' => ['csp'], - 'application/vnd.contact.cmsg' => ['cdbcmsg'], - 'application/vnd.corel-draw' => ['cdr'], - 'application/vnd.cosmocaller' => ['cmc'], - 'application/vnd.crick.clicker' => ['clkx'], - 'application/vnd.crick.clicker.keyboard' => ['clkk'], - 'application/vnd.crick.clicker.palette' => ['clkp'], - 'application/vnd.crick.clicker.template' => ['clkt'], - 'application/vnd.crick.clicker.wordbank' => ['clkw'], - 'application/vnd.criticaltools.wbs+xml' => ['wbs'], - 'application/vnd.ctc-posml' => ['pml'], - 'application/vnd.cups-ppd' => ['ppd'], - 'application/vnd.curl.car' => ['car'], - 'application/vnd.curl.pcurl' => ['pcurl'], - 'application/vnd.dart' => ['dart'], - 'application/vnd.data-vision.rdz' => ['rdz'], - 'application/vnd.debian.binary-package' => ['deb', 'udeb'], - 'application/vnd.dece.data' => ['uvf', 'uvvf', 'uvd', 'uvvd'], - 'application/vnd.dece.ttml+xml' => ['uvt', 'uvvt'], - 'application/vnd.dece.unspecified' => ['uvx', 'uvvx'], - 'application/vnd.dece.zip' => ['uvz', 'uvvz'], - 'application/vnd.denovo.fcselayout-link' => ['fe_launch'], - 'application/vnd.dna' => ['dna'], - 'application/vnd.dolby.mlp' => ['mlp'], - 'application/vnd.dpgraph' => ['dpg'], - 'application/vnd.dreamfactory' => ['dfac'], - 'application/vnd.ds-keypoint' => ['kpxx'], - 'application/vnd.dvb.ait' => ['ait'], - 'application/vnd.dvb.service' => ['svc'], - 'application/vnd.dynageo' => ['geo'], - 'application/vnd.ecowin.chart' => ['mag'], - 'application/vnd.emusic-emusic_package' => ['emp'], - 'application/vnd.enliven' => ['nml'], - 'application/vnd.epson.esf' => ['esf'], - 'application/vnd.epson.msf' => ['msf'], - 'application/vnd.epson.quickanime' => ['qam'], - 'application/vnd.epson.salt' => ['slt'], - 'application/vnd.epson.ssf' => ['ssf'], - 'application/vnd.eszigno3+xml' => ['es3', 'et3'], - 'application/vnd.ezpix-album' => ['ez2'], - 'application/vnd.ezpix-package' => ['ez3'], - 'application/vnd.fdf' => ['fdf'], - 'application/vnd.fdsn.mseed' => ['mseed'], - 'application/vnd.fdsn.seed' => ['seed', 'dataless'], - 'application/vnd.flatpak' => ['flatpak', 'xdgapp'], - 'application/vnd.flatpak.ref' => ['flatpakref'], - 'application/vnd.flatpak.repo' => ['flatpakrepo'], - 'application/vnd.flographit' => ['gph'], - 'application/vnd.fluxtime.clip' => ['ftc'], - 'application/vnd.framemaker' => ['fm', 'frame', 'maker', 'book'], - 'application/vnd.frogans.fnc' => ['fnc'], - 'application/vnd.frogans.ltf' => ['ltf'], - 'application/vnd.fsc.weblaunch' => ['fsc'], - 'application/vnd.fujitsu.oasys' => ['oas'], - 'application/vnd.fujitsu.oasys2' => ['oa2'], - 'application/vnd.fujitsu.oasys3' => ['oa3'], - 'application/vnd.fujitsu.oasysgp' => ['fg5'], - 'application/vnd.fujitsu.oasysprs' => ['bh2'], - 'application/vnd.fujixerox.ddd' => ['ddd'], - 'application/vnd.fujixerox.docuworks' => ['xdw'], - 'application/vnd.fujixerox.docuworks.binder' => ['xbd'], - 'application/vnd.fuzzysheet' => ['fzs'], - 'application/vnd.genomatix.tuxedo' => ['txd'], - 'application/vnd.geo+json' => ['geojson', 'geo.json'], - 'application/vnd.geogebra.file' => ['ggb'], - 'application/vnd.geogebra.tool' => ['ggt'], - 'application/vnd.geometry-explorer' => ['gex', 'gre'], - 'application/vnd.geonext' => ['gxt'], - 'application/vnd.geoplan' => ['g2w'], - 'application/vnd.geospace' => ['g3w'], - 'application/vnd.gmx' => ['gmx'], - 'application/vnd.google-earth.kml+xml' => ['kml'], - 'application/vnd.google-earth.kmz' => ['kmz'], - 'application/vnd.grafeq' => ['gqf', 'gqs'], - 'application/vnd.groove-account' => ['gac'], - 'application/vnd.groove-help' => ['ghf'], - 'application/vnd.groove-identity-message' => ['gim'], - 'application/vnd.groove-injector' => ['grv'], - 'application/vnd.groove-tool-message' => ['gtm'], - 'application/vnd.groove-tool-template' => ['tpl'], - 'application/vnd.groove-vcard' => ['vcg'], - 'application/vnd.haansoft-hwp' => ['hwp'], - 'application/vnd.haansoft-hwt' => ['hwt'], - 'application/vnd.hal+xml' => ['hal'], - 'application/vnd.handheld-entertainment+xml' => ['zmm'], - 'application/vnd.hbci' => ['hbci'], - 'application/vnd.hhe.lesson-player' => ['les'], - 'application/vnd.hp-hpgl' => ['hpgl'], - 'application/vnd.hp-hpid' => ['hpid'], - 'application/vnd.hp-hps' => ['hps'], - 'application/vnd.hp-jlyt' => ['jlt'], - 'application/vnd.hp-pcl' => ['pcl'], - 'application/vnd.hp-pclxl' => ['pclxl'], - 'application/vnd.hydrostatix.sof-data' => ['sfd-hdstx'], - 'application/vnd.ibm.minipay' => ['mpy'], - 'application/vnd.ibm.modcap' => ['afp', 'listafp', 'list3820'], - 'application/vnd.ibm.rights-management' => ['irm'], - 'application/vnd.ibm.secure-container' => ['sc'], - 'application/vnd.iccprofile' => ['icc', 'icm'], - 'application/vnd.igloader' => ['igl'], - 'application/vnd.immervision-ivp' => ['ivp'], - 'application/vnd.immervision-ivu' => ['ivu'], - 'application/vnd.insors.igm' => ['igm'], - 'application/vnd.intercon.formnet' => ['xpw', 'xpx'], - 'application/vnd.intergeo' => ['i2g'], - 'application/vnd.intu.qbo' => ['qbo'], - 'application/vnd.intu.qfx' => ['qfx'], - 'application/vnd.ipunplugged.rcprofile' => ['rcprofile'], - 'application/vnd.irepository.package+xml' => ['irp'], - 'application/vnd.is-xpr' => ['xpr'], - 'application/vnd.isac.fcs' => ['fcs'], - 'application/vnd.jam' => ['jam'], - 'application/vnd.jcp.javame.midlet-rms' => ['rms'], - 'application/vnd.jisp' => ['jisp'], - 'application/vnd.joost.joda-archive' => ['joda'], - 'application/vnd.kahootz' => ['ktz', 'ktr'], - 'application/vnd.kde.karbon' => ['karbon'], - 'application/vnd.kde.kchart' => ['chrt'], - 'application/vnd.kde.kformula' => ['kfo'], - 'application/vnd.kde.kivio' => ['flw'], - 'application/vnd.kde.kontour' => ['kon'], - 'application/vnd.kde.kpresenter' => ['kpr', 'kpt'], - 'application/vnd.kde.kspread' => ['ksp'], - 'application/vnd.kde.kword' => ['kwd', 'kwt'], - 'application/vnd.kenameaapp' => ['htke'], - 'application/vnd.kidspiration' => ['kia'], - 'application/vnd.kinar' => ['kne', 'knp'], - 'application/vnd.koan' => ['skp', 'skd', 'skt', 'skm'], - 'application/vnd.kodak-descriptor' => ['sse'], - 'application/vnd.las.las+xml' => ['lasxml'], - 'application/vnd.llamagraphics.life-balance.desktop' => ['lbd'], - 'application/vnd.llamagraphics.life-balance.exchange+xml' => ['lbe'], - 'application/vnd.lotus-1-2-3' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], - 'application/vnd.lotus-approach' => ['apr'], - 'application/vnd.lotus-freelance' => ['pre'], - 'application/vnd.lotus-notes' => ['nsf'], - 'application/vnd.lotus-organizer' => ['org'], - 'application/vnd.lotus-screencam' => ['scm'], - 'application/vnd.lotus-wordpro' => ['lwp'], - 'application/vnd.macports.portpkg' => ['portpkg'], - 'application/vnd.mcd' => ['mcd'], - 'application/vnd.medcalcdata' => ['mc1'], - 'application/vnd.mediastation.cdkey' => ['cdkey'], - 'application/vnd.mfer' => ['mwf'], - 'application/vnd.mfmp' => ['mfm'], - 'application/vnd.micrografx.flo' => ['flo'], - 'application/vnd.micrografx.igx' => ['igx'], - 'application/vnd.mif' => ['mif'], - 'application/vnd.mobius.daf' => ['daf'], - 'application/vnd.mobius.dis' => ['dis'], - 'application/vnd.mobius.mbk' => ['mbk'], - 'application/vnd.mobius.mqy' => ['mqy'], - 'application/vnd.mobius.msl' => ['msl'], - 'application/vnd.mobius.plc' => ['plc'], - 'application/vnd.mobius.txf' => ['txf'], - 'application/vnd.mophun.application' => ['mpn'], - 'application/vnd.mophun.certificate' => ['mpc'], - 'application/vnd.mozilla.xul+xml' => ['xul'], - 'application/vnd.ms-access' => ['mdb'], - 'application/vnd.ms-artgalry' => ['cil'], - 'application/vnd.ms-asf' => ['asf'], - 'application/vnd.ms-cab-compressed' => ['cab'], - 'application/vnd.ms-excel' => ['xls', 'xlm', 'xla', 'xlc', 'xlt', 'xlw', 'xll', 'xld'], - 'application/vnd.ms-excel.addin.macroenabled.12' => ['xlam'], - 'application/vnd.ms-excel.sheet.binary.macroenabled.12' => ['xlsb'], - 'application/vnd.ms-excel.sheet.macroenabled.12' => ['xlsm'], - 'application/vnd.ms-excel.template.macroenabled.12' => ['xltm'], - 'application/vnd.ms-fontobject' => ['eot'], - 'application/vnd.ms-htmlhelp' => ['chm'], - 'application/vnd.ms-ims' => ['ims'], - 'application/vnd.ms-lrm' => ['lrm'], - 'application/vnd.ms-officetheme' => ['thmx'], - 'application/vnd.ms-pki.seccat' => ['cat'], - 'application/vnd.ms-pki.stl' => ['stl'], - 'application/vnd.ms-powerpoint' => ['ppt', 'pps', 'pot', 'ppz'], - 'application/vnd.ms-powerpoint.addin.macroenabled.12' => ['ppam'], - 'application/vnd.ms-powerpoint.presentation.macroenabled.12' => ['pptm'], - 'application/vnd.ms-powerpoint.slide.macroenabled.12' => ['sldm'], - 'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => ['ppsm'], - 'application/vnd.ms-powerpoint.template.macroenabled.12' => ['potm'], - 'application/vnd.ms-project' => ['mpp', 'mpt'], - 'application/vnd.ms-publisher' => ['pub'], - 'application/vnd.ms-tnef' => ['tnef', 'tnf'], - 'application/vnd.ms-visio.drawing.macroenabled.main+xml' => ['vsdm'], - 'application/vnd.ms-visio.drawing.main+xml' => ['vsdx'], - 'application/vnd.ms-visio.stencil.macroenabled.main+xml' => ['vssm'], - 'application/vnd.ms-visio.stencil.main+xml' => ['vssx'], - 'application/vnd.ms-visio.template.macroenabled.main+xml' => ['vstm'], - 'application/vnd.ms-visio.template.main+xml' => ['vstx'], - 'application/vnd.ms-word' => ['doc'], - 'application/vnd.ms-word.document.macroenabled.12' => ['docm'], - 'application/vnd.ms-word.template.macroenabled.12' => ['dotm'], - 'application/vnd.ms-works' => ['wps', 'wks', 'wcm', 'wdb', 'xlr'], - 'application/vnd.ms-wpl' => ['wpl'], - 'application/vnd.ms-xpsdocument' => ['xps', 'oxps'], - 'application/vnd.msaccess' => ['mdb'], - 'application/vnd.mseq' => ['mseq'], - 'application/vnd.musician' => ['mus'], - 'application/vnd.muvee.style' => ['msty'], - 'application/vnd.mynfc' => ['taglet'], - 'application/vnd.neurolanguage.nlu' => ['nlu'], - 'application/vnd.nintendo.snes.rom' => ['sfc', 'smc'], - 'application/vnd.nitf' => ['ntf', 'nitf'], - 'application/vnd.noblenet-directory' => ['nnd'], - 'application/vnd.noblenet-sealer' => ['nns'], - 'application/vnd.noblenet-web' => ['nnw'], - 'application/vnd.nokia.n-gage.data' => ['ngdat'], - 'application/vnd.nokia.n-gage.symbian.install' => ['n-gage'], - 'application/vnd.nokia.radio-preset' => ['rpst'], - 'application/vnd.nokia.radio-presets' => ['rpss'], - 'application/vnd.novadigm.edm' => ['edm'], - 'application/vnd.novadigm.edx' => ['edx'], - 'application/vnd.novadigm.ext' => ['ext'], - 'application/vnd.oasis.docbook+xml' => ['dbk', 'docbook'], - 'application/vnd.oasis.opendocument.chart' => ['odc'], - 'application/vnd.oasis.opendocument.chart-template' => ['otc'], - 'application/vnd.oasis.opendocument.database' => ['odb'], - 'application/vnd.oasis.opendocument.formula' => ['odf'], - 'application/vnd.oasis.opendocument.formula-template' => ['odft', 'otf'], - 'application/vnd.oasis.opendocument.graphics' => ['odg'], - 'application/vnd.oasis.opendocument.graphics-flat-xml' => ['fodg'], - 'application/vnd.oasis.opendocument.graphics-template' => ['otg'], - 'application/vnd.oasis.opendocument.image' => ['odi'], - 'application/vnd.oasis.opendocument.image-template' => ['oti'], - 'application/vnd.oasis.opendocument.presentation' => ['odp'], - 'application/vnd.oasis.opendocument.presentation-flat-xml' => ['fodp'], - 'application/vnd.oasis.opendocument.presentation-template' => ['otp'], - 'application/vnd.oasis.opendocument.spreadsheet' => ['ods'], - 'application/vnd.oasis.opendocument.spreadsheet-flat-xml' => ['fods'], - 'application/vnd.oasis.opendocument.spreadsheet-template' => ['ots'], - 'application/vnd.oasis.opendocument.text' => ['odt'], - 'application/vnd.oasis.opendocument.text-flat-xml' => ['fodt'], - 'application/vnd.oasis.opendocument.text-master' => ['odm'], - 'application/vnd.oasis.opendocument.text-template' => ['ott'], - 'application/vnd.oasis.opendocument.text-web' => ['oth'], - 'application/vnd.olpc-sugar' => ['xo'], - 'application/vnd.oma.dd2+xml' => ['dd2'], - 'application/vnd.openofficeorg.extension' => ['oxt'], - 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => ['pptx'], - 'application/vnd.openxmlformats-officedocument.presentationml.slide' => ['sldx'], - 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => ['ppsx'], - 'application/vnd.openxmlformats-officedocument.presentationml.template' => ['potx'], - 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => ['xlsx'], - 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => ['xltx'], - 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => ['docx'], - 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => ['dotx'], - 'application/vnd.osgeo.mapguide.package' => ['mgp'], - 'application/vnd.osgi.dp' => ['dp'], - 'application/vnd.osgi.subsystem' => ['esa'], - 'application/vnd.palm' => ['pdb', 'pqa', 'oprc', 'prc'], - 'application/vnd.pawaafile' => ['paw'], - 'application/vnd.pg.format' => ['str'], - 'application/vnd.pg.osasli' => ['ei6'], - 'application/vnd.picsel' => ['efif'], - 'application/vnd.pmi.widget' => ['wg'], - 'application/vnd.pocketlearn' => ['plf'], - 'application/vnd.powerbuilder6' => ['pbd'], - 'application/vnd.previewsystems.box' => ['box'], - 'application/vnd.proteus.magazine' => ['mgz'], - 'application/vnd.publishare-delta-tree' => ['qps'], - 'application/vnd.pvi.ptid1' => ['ptid'], - 'application/vnd.quark.quarkxpress' => ['qxd', 'qxt', 'qwd', 'qwt', 'qxl', 'qxb'], - 'application/vnd.rar' => ['rar'], - 'application/vnd.realvnc.bed' => ['bed'], - 'application/vnd.recordare.musicxml' => ['mxl'], - 'application/vnd.recordare.musicxml+xml' => ['musicxml'], - 'application/vnd.rig.cryptonote' => ['cryptonote'], - 'application/vnd.rim.cod' => ['cod'], - 'application/vnd.rn-realmedia' => ['rm', 'rmj', 'rmm', 'rms', 'rmx', 'rmvb'], - 'application/vnd.rn-realmedia-vbr' => ['rmvb', 'rm', 'rmj', 'rmm', 'rms', 'rmx'], - 'application/vnd.route66.link66+xml' => ['link66'], - 'application/vnd.sailingtracker.track' => ['st'], - 'application/vnd.sdp' => ['sdp'], - 'application/vnd.seemail' => ['see'], - 'application/vnd.sema' => ['sema'], - 'application/vnd.semd' => ['semd'], - 'application/vnd.semf' => ['semf'], - 'application/vnd.shana.informed.formdata' => ['ifm'], - 'application/vnd.shana.informed.formtemplate' => ['itp'], - 'application/vnd.shana.informed.interchange' => ['iif'], - 'application/vnd.shana.informed.package' => ['ipk'], - 'application/vnd.simtech-mindmapper' => ['twd', 'twds'], - 'application/vnd.smaf' => ['mmf', 'smaf'], - 'application/vnd.smart.teacher' => ['teacher'], - 'application/vnd.snap' => ['snap'], - 'application/vnd.solent.sdkm+xml' => ['sdkm', 'sdkd'], - 'application/vnd.spotfire.dxp' => ['dxp'], - 'application/vnd.spotfire.sfs' => ['sfs'], - 'application/vnd.sqlite3' => ['sqlite3'], - 'application/vnd.squashfs' => ['sqsh'], - 'application/vnd.stardivision.calc' => ['sdc'], - 'application/vnd.stardivision.chart' => ['sds'], - 'application/vnd.stardivision.draw' => ['sda'], - 'application/vnd.stardivision.impress' => ['sdd', 'sdp'], - 'application/vnd.stardivision.mail' => ['smd'], - 'application/vnd.stardivision.math' => ['smf'], - 'application/vnd.stardivision.writer' => ['sdw', 'vor', 'sgl'], - 'application/vnd.stardivision.writer-global' => ['sgl', 'sdw', 'vor'], - 'application/vnd.stepmania.package' => ['smzip'], - 'application/vnd.stepmania.stepchart' => ['sm'], - 'application/vnd.sun.xml.base' => ['odb'], - 'application/vnd.sun.xml.calc' => ['sxc'], - 'application/vnd.sun.xml.calc.template' => ['stc'], - 'application/vnd.sun.xml.draw' => ['sxd'], - 'application/vnd.sun.xml.draw.template' => ['std'], - 'application/vnd.sun.xml.impress' => ['sxi'], - 'application/vnd.sun.xml.impress.template' => ['sti'], - 'application/vnd.sun.xml.math' => ['sxm'], - 'application/vnd.sun.xml.writer' => ['sxw'], - 'application/vnd.sun.xml.writer.global' => ['sxg'], - 'application/vnd.sun.xml.writer.template' => ['stw'], - 'application/vnd.sus-calendar' => ['sus', 'susp'], - 'application/vnd.svd' => ['svd'], - 'application/vnd.symbian.install' => ['sis', 'sisx'], - 'application/vnd.syncml+xml' => ['xsm'], - 'application/vnd.syncml.dm+wbxml' => ['bdm'], - 'application/vnd.syncml.dm+xml' => ['xdm'], - 'application/vnd.tao.intent-module-archive' => ['tao'], - 'application/vnd.tcpdump.pcap' => ['pcap', 'cap', 'dmp'], - 'application/vnd.tmobile-livetv' => ['tmo'], - 'application/vnd.trid.tpt' => ['tpt'], - 'application/vnd.triscape.mxs' => ['mxs'], - 'application/vnd.trueapp' => ['tra'], - 'application/vnd.ufdl' => ['ufd', 'ufdl'], - 'application/vnd.uiq.theme' => ['utz'], - 'application/vnd.umajin' => ['umj'], - 'application/vnd.unity' => ['unityweb'], - 'application/vnd.uoml+xml' => ['uoml'], - 'application/vnd.vcx' => ['vcx'], - 'application/vnd.visio' => ['vsd', 'vst', 'vss', 'vsw'], - 'application/vnd.visionary' => ['vis'], - 'application/vnd.vsf' => ['vsf'], - 'application/vnd.wap.wbxml' => ['wbxml'], - 'application/vnd.wap.wmlc' => ['wmlc'], - 'application/vnd.wap.wmlscriptc' => ['wmlsc'], - 'application/vnd.webturbo' => ['wtb'], - 'application/vnd.wolfram.player' => ['nbp'], - 'application/vnd.wordperfect' => ['wpd', 'wp', 'wp4', 'wp5', 'wp6', 'wpp'], - 'application/vnd.wqd' => ['wqd'], - 'application/vnd.wt.stf' => ['stf'], - 'application/vnd.xara' => ['xar'], - 'application/vnd.xdgapp' => ['flatpak', 'xdgapp'], - 'application/vnd.xfdl' => ['xfdl'], - 'application/vnd.yamaha.hv-dic' => ['hvd'], - 'application/vnd.yamaha.hv-script' => ['hvs'], - 'application/vnd.yamaha.hv-voice' => ['hvp'], - 'application/vnd.yamaha.openscoreformat' => ['osf'], - 'application/vnd.yamaha.openscoreformat.osfpvg+xml' => ['osfpvg'], - 'application/vnd.yamaha.smaf-audio' => ['saf'], - 'application/vnd.yamaha.smaf-phrase' => ['spf'], - 'application/vnd.yellowriver-custom-menu' => ['cmp'], - 'application/vnd.youtube.yt' => ['yt'], - 'application/vnd.zul' => ['zir', 'zirz'], - 'application/vnd.zzazz.deck+xml' => ['zaz'], - 'application/voicexml+xml' => ['vxml'], - 'application/widget' => ['wgt'], - 'application/winhlp' => ['hlp'], - 'application/wk1' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], - 'application/wmf' => ['wmf'], - 'application/wordperfect' => ['wp', 'wp4', 'wp5', 'wp6', 'wpd', 'wpp'], - 'application/wsdl+xml' => ['wsdl'], - 'application/wspolicy+xml' => ['wspolicy'], - 'application/wwf' => ['wwf'], - 'application/x-123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], - 'application/x-7z-compressed' => ['7z'], - 'application/x-abiword' => ['abw', 'abw.CRASHED', 'abw.gz', 'zabw'], - 'application/x-ace' => ['ace'], - 'application/x-ace-compressed' => ['ace'], - 'application/x-alz' => ['alz'], - 'application/x-amiga-disk-format' => ['adf'], - 'application/x-amipro' => ['sam'], - 'application/x-annodex' => ['anx'], - 'application/x-aportisdoc' => ['pdb', 'pdc'], - 'application/x-apple-diskimage' => ['dmg'], - 'application/x-applix-spreadsheet' => ['as'], - 'application/x-applix-word' => ['aw'], - 'application/x-archive' => ['a', 'ar'], - 'application/x-arj' => ['arj'], - 'application/x-asp' => ['asp'], - 'application/x-atari-2600-rom' => ['a26'], - 'application/x-atari-7800-rom' => ['a78'], - 'application/x-atari-lynx-rom' => ['lnx'], - 'application/x-authorware-bin' => ['aab', 'x32', 'u32', 'vox'], - 'application/x-authorware-map' => ['aam'], - 'application/x-authorware-seg' => ['aas'], - 'application/x-awk' => ['awk'], - 'application/x-bcpio' => ['bcpio'], - 'application/x-bittorrent' => ['torrent'], - 'application/x-blender' => ['blender', 'blend', 'BLEND'], - 'application/x-blorb' => ['blb', 'blorb'], - 'application/x-bsdiff' => ['bsdiff'], - 'application/x-bzdvi' => ['dvi.bz2'], - 'application/x-bzip' => ['bz', 'bz2'], - 'application/x-bzip-compressed-tar' => ['tar.bz2', 'tar.bz', 'tbz2', 'tbz', 'tb2'], - 'application/x-bzip2' => ['bz2', 'boz', 'bz'], - 'application/x-bzpdf' => ['pdf.bz2'], - 'application/x-bzpostscript' => ['ps.bz2'], - 'application/x-cb7' => ['cb7'], - 'application/x-cbr' => ['cbr', 'cba', 'cbt', 'cbz', 'cb7'], - 'application/x-cbt' => ['cbt'], - 'application/x-cbz' => ['cbz'], - 'application/x-ccmx' => ['ccmx'], - 'application/x-cd-image' => ['iso', 'iso9660'], - 'application/x-cdlink' => ['vcd'], - 'application/x-cdr' => ['cdr'], - 'application/x-cdrdao-toc' => ['toc'], - 'application/x-cfs-compressed' => ['cfs'], - 'application/x-chat' => ['chat'], - 'application/x-chess-pgn' => ['pgn'], - 'application/x-chm' => ['chm'], - 'application/x-cisco-vpn-settings' => ['pcf'], - 'application/x-compress' => ['Z'], - 'application/x-compressed-tar' => ['tar.gz', 'tgz'], - 'application/x-conference' => ['nsc'], - 'application/x-coreldraw' => ['cdr'], - 'application/x-cpio' => ['cpio'], - 'application/x-cpio-compressed' => ['cpio.gz'], - 'application/x-csh' => ['csh'], - 'application/x-cue' => ['cue'], - 'application/x-dar' => ['dar'], - 'application/x-dbase' => ['dbf'], - 'application/x-dbf' => ['dbf'], - 'application/x-dc-rom' => ['dc'], - 'application/x-deb' => ['deb', 'udeb'], - 'application/x-debian-package' => ['deb', 'udeb'], - 'application/x-designer' => ['ui'], - 'application/x-desktop' => ['desktop', 'kdelnk'], - 'application/x-dgc-compressed' => ['dgc'], - 'application/x-dia-diagram' => ['dia'], - 'application/x-dia-shape' => ['shape'], - 'application/x-director' => ['dir', 'dcr', 'dxr', 'cst', 'cct', 'cxt', 'w3d', 'fgd', 'swa'], - 'application/x-docbook+xml' => ['dbk', 'docbook'], - 'application/x-doom' => ['wad'], - 'application/x-doom-wad' => ['wad'], - 'application/x-dtbncx+xml' => ['ncx'], - 'application/x-dtbook+xml' => ['dtb'], - 'application/x-dtbresource+xml' => ['res'], - 'application/x-dvi' => ['dvi'], - 'application/x-e-theme' => ['etheme'], - 'application/x-egon' => ['egon'], - 'application/x-emf' => ['emf'], - 'application/x-envoy' => ['evy'], - 'application/x-eva' => ['eva'], - 'application/x-fd-file' => ['fd', 'qd'], - 'application/x-fds-disk' => ['fds'], - 'application/x-fictionbook' => ['fb2'], - 'application/x-fictionbook+xml' => ['fb2'], - 'application/x-flash-video' => ['flv'], - 'application/x-fluid' => ['fl'], - 'application/x-font-afm' => ['afm'], - 'application/x-font-bdf' => ['bdf'], - 'application/x-font-ghostscript' => ['gsf'], - 'application/x-font-linux-psf' => ['psf'], - 'application/x-font-otf' => ['otf'], - 'application/x-font-pcf' => ['pcf', 'pcf.Z', 'pcf.gz'], - 'application/x-font-snf' => ['snf'], - 'application/x-font-speedo' => ['spd'], - 'application/x-font-ttf' => ['ttf'], - 'application/x-font-ttx' => ['ttx'], - 'application/x-font-type1' => ['pfa', 'pfb', 'pfm', 'afm', 'gsf'], - 'application/x-font-woff' => ['woff'], - 'application/x-frame' => ['fm'], - 'application/x-freearc' => ['arc'], - 'application/x-futuresplash' => ['spl'], - 'application/x-gameboy-color-rom' => ['gbc', 'cgb'], - 'application/x-gameboy-rom' => ['gb', 'sgb'], - 'application/x-gamecube-iso-image' => ['iso'], - 'application/x-gamecube-rom' => ['iso'], - 'application/x-gamegear-rom' => ['gg'], - 'application/x-gba-rom' => ['gba', 'agb'], - 'application/x-gca-compressed' => ['gca'], - 'application/x-gedcom' => ['ged', 'gedcom'], - 'application/x-genesis-32x-rom' => ['32x', 'mdx'], - 'application/x-genesis-rom' => ['gen', 'smd'], - 'application/x-gettext' => ['po'], - 'application/x-gettext-translation' => ['gmo', 'mo'], - 'application/x-glade' => ['glade'], - 'application/x-glulx' => ['ulx'], - 'application/x-gnome-app-info' => ['desktop', 'kdelnk'], - 'application/x-gnucash' => ['gnucash', 'gnc', 'xac'], - 'application/x-gnumeric' => ['gnumeric'], - 'application/x-gnuplot' => ['gp', 'gplt', 'gnuplot'], - 'application/x-go-sgf' => ['sgf'], - 'application/x-gpx' => ['gpx'], - 'application/x-gpx+xml' => ['gpx'], - 'application/x-gramps-xml' => ['gramps'], - 'application/x-graphite' => ['gra'], - 'application/x-gtar' => ['gtar', 'tar', 'gem'], - 'application/x-gtk-builder' => ['ui'], - 'application/x-gz-font-linux-psf' => ['psf.gz'], - 'application/x-gzdvi' => ['dvi.gz'], - 'application/x-gzip' => ['gz'], - 'application/x-gzpdf' => ['pdf.gz'], - 'application/x-gzpostscript' => ['ps.gz'], - 'application/x-hdf' => ['hdf', 'hdf4', 'h4', 'hdf5', 'h5'], - 'application/x-hfe-file' => ['hfe'], - 'application/x-hfe-floppy-image' => ['hfe'], - 'application/x-hwp' => ['hwp'], - 'application/x-hwt' => ['hwt'], - 'application/x-ica' => ['ica'], - 'application/x-install-instructions' => ['install'], - 'application/x-ipynb+json' => ['ipynb'], - 'application/x-iso9660-appimage' => ['appimage'], - 'application/x-iso9660-image' => ['iso', 'iso9660'], - 'application/x-it87' => ['it87'], - 'application/x-iwork-keynote-sffkey' => ['key'], - 'application/x-jar' => ['jar'], - 'application/x-java' => ['class'], - 'application/x-java-archive' => ['jar'], - 'application/x-java-class' => ['class'], - 'application/x-java-jce-keystore' => ['jceks'], - 'application/x-java-jnlp-file' => ['jnlp'], - 'application/x-java-keystore' => ['jks', 'ks'], - 'application/x-java-pack200' => ['pack'], - 'application/x-java-vm' => ['class'], - 'application/x-javascript' => ['js', 'jsm', 'mjs'], - 'application/x-jbuilder-project' => ['jpr', 'jpx'], - 'application/x-karbon' => ['karbon'], - 'application/x-kchart' => ['chrt'], - 'application/x-kexi-connectiondata' => ['kexic'], - 'application/x-kexiproject-shortcut' => ['kexis'], - 'application/x-kexiproject-sqlite' => ['kexi'], - 'application/x-kexiproject-sqlite2' => ['kexi'], - 'application/x-kexiproject-sqlite3' => ['kexi'], - 'application/x-kformula' => ['kfo'], - 'application/x-killustrator' => ['kil'], - 'application/x-kivio' => ['flw'], - 'application/x-kontour' => ['kon'], - 'application/x-kpovmodeler' => ['kpm'], - 'application/x-kpresenter' => ['kpr', 'kpt'], - 'application/x-krita' => ['kra'], - 'application/x-kspread' => ['ksp'], - 'application/x-kugar' => ['kud'], - 'application/x-kword' => ['kwd', 'kwt'], - 'application/x-latex' => ['latex'], - 'application/x-lha' => ['lha', 'lzh'], - 'application/x-lhz' => ['lhz'], - 'application/x-linguist' => ['ts'], - 'application/x-lotus123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], - 'application/x-lrzip' => ['lrz'], - 'application/x-lrzip-compressed-tar' => ['tar.lrz', 'tlrz'], - 'application/x-lyx' => ['lyx'], - 'application/x-lz4' => ['lz4'], - 'application/x-lz4-compressed-tar' => ['tar.lz4'], - 'application/x-lzh-compressed' => ['lzh', 'lha'], - 'application/x-lzip' => ['lz'], - 'application/x-lzip-compressed-tar' => ['tar.lz'], - 'application/x-lzma' => ['lzma'], - 'application/x-lzma-compressed-tar' => ['tar.lzma', 'tlz'], - 'application/x-lzop' => ['lzo'], - 'application/x-lzpdf' => ['pdf.lz'], - 'application/x-m4' => ['m4'], - 'application/x-magicpoint' => ['mgp'], - 'application/x-markaby' => ['mab'], - 'application/x-mathematica' => ['nb'], - 'application/x-mdb' => ['mdb'], - 'application/x-mie' => ['mie'], - 'application/x-mif' => ['mif'], - 'application/x-mimearchive' => ['mhtml', 'mht'], - 'application/x-mobipocket-ebook' => ['prc', 'mobi'], - 'application/x-ms-application' => ['application'], - 'application/x-ms-asx' => ['asx', 'wax', 'wvx', 'wmx'], - 'application/x-ms-dos-executable' => ['exe'], - 'application/x-ms-shortcut' => ['lnk'], - 'application/x-ms-wim' => ['wim', 'swm'], - 'application/x-ms-wmd' => ['wmd'], - 'application/x-ms-wmz' => ['wmz'], - 'application/x-ms-xbap' => ['xbap'], - 'application/x-msaccess' => ['mdb'], - 'application/x-msbinder' => ['obd'], - 'application/x-mscardfile' => ['crd'], - 'application/x-msclip' => ['clp'], - 'application/x-msdownload' => ['exe', 'dll', 'com', 'bat', 'msi'], - 'application/x-msexcel' => ['xls', 'xlc', 'xll', 'xlm', 'xlw', 'xla', 'xlt', 'xld'], - 'application/x-msi' => ['msi'], - 'application/x-msmediaview' => ['mvb', 'm13', 'm14'], - 'application/x-msmetafile' => ['wmf', 'wmz', 'emf', 'emz'], - 'application/x-msmoney' => ['mny'], - 'application/x-mspowerpoint' => ['ppz', 'ppt', 'pps', 'pot'], - 'application/x-mspublisher' => ['pub'], - 'application/x-msschedule' => ['scd'], - 'application/x-msterminal' => ['trm'], - 'application/x-mswinurl' => ['url'], - 'application/x-msword' => ['doc'], - 'application/x-mswrite' => ['wri'], - 'application/x-msx-rom' => ['msx'], - 'application/x-n64-rom' => ['n64', 'z64', 'v64'], - 'application/x-navi-animation' => ['ani'], - 'application/x-neo-geo-pocket-color-rom' => ['ngc'], - 'application/x-neo-geo-pocket-rom' => ['ngp'], - 'application/x-nes-rom' => ['nes', 'nez', 'unf', 'unif'], - 'application/x-netcdf' => ['nc', 'cdf'], - 'application/x-netshow-channel' => ['nsc'], - 'application/x-nintendo-ds-rom' => ['nds'], - 'application/x-nzb' => ['nzb'], - 'application/x-object' => ['o'], - 'application/x-ogg' => ['ogx'], - 'application/x-oleo' => ['oleo'], - 'application/x-pagemaker' => ['p65', 'pm', 'pm6', 'pmd'], - 'application/x-pak' => ['pak'], - 'application/x-palm-database' => ['prc', 'pdb', 'pqa', 'oprc'], - 'application/x-par2' => ['PAR2', 'par2'], - 'application/x-partial-download' => ['wkdownload', 'crdownload', 'part'], - 'application/x-pc-engine-rom' => ['pce'], - 'application/x-pcap' => ['pcap', 'cap', 'dmp'], - 'application/x-pdf' => ['pdf'], - 'application/x-perl' => ['pl', 'PL', 'pm', 'al', 'perl', 'pod', 't'], - 'application/x-photoshop' => ['psd'], - 'application/x-php' => ['php', 'php3', 'php4', 'php5', 'phps'], - 'application/x-pkcs12' => ['p12', 'pfx'], - 'application/x-pkcs7-certificates' => ['p7b', 'spc'], - 'application/x-pkcs7-certreqresp' => ['p7r'], - 'application/x-planperfect' => ['pln'], - 'application/x-pocket-word' => ['psw'], - 'application/x-pw' => ['pw'], - 'application/x-python-bytecode' => ['pyc', 'pyo'], - 'application/x-qpress' => ['qp'], - 'application/x-qtiplot' => ['qti', 'qti.gz'], - 'application/x-quattropro' => ['wb1', 'wb2', 'wb3'], - 'application/x-quicktime-media-link' => ['qtl'], - 'application/x-quicktimeplayer' => ['qtl'], - 'application/x-qw' => ['qif'], - 'application/x-rar' => ['rar'], - 'application/x-rar-compressed' => ['rar'], - 'application/x-raw-disk-image' => ['raw-disk-image', 'img'], - 'application/x-raw-disk-image-xz-compressed' => ['raw-disk-image.xz', 'img.xz'], - 'application/x-raw-floppy-disk-image' => ['fd', 'qd'], - 'application/x-redhat-package-manager' => ['rpm'], - 'application/x-reject' => ['rej'], - 'application/x-research-info-systems' => ['ris'], - 'application/x-rnc' => ['rnc'], - 'application/x-rpm' => ['rpm'], - 'application/x-ruby' => ['rb'], - 'application/x-sami' => ['smi', 'sami'], - 'application/x-sap-file' => ['sap'], - 'application/x-saturn-rom' => ['bin', 'iso'], - 'application/x-sdp' => ['sdp'], - 'application/x-sega-cd-rom' => ['bin', 'iso'], - 'application/x-sg1000-rom' => ['sg'], - 'application/x-sh' => ['sh'], - 'application/x-shar' => ['shar'], - 'application/x-shared-library-la' => ['la'], - 'application/x-sharedlib' => ['so'], - 'application/x-shellscript' => ['sh'], - 'application/x-shockwave-flash' => ['swf', 'spl'], - 'application/x-shorten' => ['shn'], - 'application/x-siag' => ['siag'], - 'application/x-silverlight-app' => ['xap'], - 'application/x-sit' => ['sit'], - 'application/x-smaf' => ['mmf', 'smaf'], - 'application/x-sms-rom' => ['sms'], - 'application/x-snes-rom' => ['sfc', 'smc'], - 'application/x-source-rpm' => ['src.rpm', 'spm'], - 'application/x-spss-por' => ['por'], - 'application/x-spss-sav' => ['sav', 'zsav'], - 'application/x-spss-savefile' => ['sav', 'zsav'], - 'application/x-sql' => ['sql'], - 'application/x-sqlite2' => ['sqlite2'], - 'application/x-sqlite3' => ['sqlite3'], - 'application/x-srt' => ['srt'], - 'application/x-stuffit' => ['sit'], - 'application/x-stuffitx' => ['sitx'], - 'application/x-subrip' => ['srt'], - 'application/x-sv4cpio' => ['sv4cpio'], - 'application/x-sv4crc' => ['sv4crc'], - 'application/x-t3vm-image' => ['t3'], - 'application/x-t602' => ['602'], - 'application/x-tads' => ['gam'], - 'application/x-tar' => ['tar', 'gtar', 'gem'], - 'application/x-tarz' => ['tar.Z', 'taz'], - 'application/x-tcl' => ['tcl'], - 'application/x-tex' => ['tex', 'ltx', 'sty', 'cls', 'dtx', 'ins', 'latex'], - 'application/x-tex-gf' => ['gf'], - 'application/x-tex-pk' => ['pk'], - 'application/x-tex-tfm' => ['tfm'], - 'application/x-texinfo' => ['texinfo', 'texi'], - 'application/x-tgif' => ['obj'], - 'application/x-theme' => ['theme'], - 'application/x-thomson-cartridge-memo7' => ['m7'], - 'application/x-thomson-cassette' => ['k7'], - 'application/x-thomson-sap-image' => ['sap'], - 'application/x-trash' => ['bak', 'old', 'sik'], - 'application/x-trig' => ['trig'], - 'application/x-troff' => ['tr', 'roff', 't'], - 'application/x-troff-man' => ['man'], - 'application/x-tzo' => ['tar.lzo', 'tzo'], - 'application/x-ufraw' => ['ufraw'], - 'application/x-ustar' => ['ustar'], - 'application/x-virtual-boy-rom' => ['vb'], - 'application/x-vnd.kde.kexi' => ['kexi'], - 'application/x-wais-source' => ['src'], - 'application/x-wbfs' => ['iso'], - 'application/x-wia' => ['iso'], - 'application/x-wii-iso-image' => ['iso'], - 'application/x-wii-rom' => ['iso'], - 'application/x-wii-wad' => ['wad'], - 'application/x-windows-themepack' => ['themepack'], - 'application/x-wmf' => ['wmf'], - 'application/x-wonderswan-color-rom' => ['wsc'], - 'application/x-wonderswan-rom' => ['ws'], - 'application/x-wordperfect' => ['wp', 'wp4', 'wp5', 'wp6', 'wpd', 'wpp'], - 'application/x-wpg' => ['wpg'], - 'application/x-wwf' => ['wwf'], - 'application/x-x509-ca-cert' => ['der', 'crt', 'cert', 'pem'], - 'application/x-xar' => ['xar', 'pkg'], - 'application/x-xbel' => ['xbel'], - 'application/x-xfig' => ['fig'], - 'application/x-xliff' => ['xlf', 'xliff'], - 'application/x-xliff+xml' => ['xlf'], - 'application/x-xpinstall' => ['xpi'], - 'application/x-xspf+xml' => ['xspf'], - 'application/x-xz' => ['xz'], - 'application/x-xz-compressed-tar' => ['tar.xz', 'txz'], - 'application/x-xzpdf' => ['pdf.xz'], - 'application/x-yaml' => ['yaml', 'yml'], - 'application/x-zip' => ['zip'], - 'application/x-zip-compressed' => ['zip'], - 'application/x-zip-compressed-fb2' => ['fb2.zip'], - 'application/x-zmachine' => ['z1', 'z2', 'z3', 'z4', 'z5', 'z6', 'z7', 'z8'], - 'application/x-zoo' => ['zoo'], - 'application/xaml+xml' => ['xaml'], - 'application/xcap-diff+xml' => ['xdf'], - 'application/xenc+xml' => ['xenc'], - 'application/xhtml+xml' => ['xhtml', 'xht'], - 'application/xliff+xml' => ['xlf', 'xliff'], - 'application/xml' => ['xml', 'xsl', 'xbl', 'xsd', 'rng'], - 'application/xml-dtd' => ['dtd'], - 'application/xml-external-parsed-entity' => ['ent'], - 'application/xop+xml' => ['xop'], - 'application/xproc+xml' => ['xpl'], - 'application/xps' => ['oxps', 'xps'], - 'application/xslt+xml' => ['xslt', 'xsl'], - 'application/xspf+xml' => ['xspf'], - 'application/xv+xml' => ['mxml', 'xhvml', 'xvml', 'xvm'], - 'application/yang' => ['yang'], - 'application/yin+xml' => ['yin'], - 'application/zip' => ['zip'], - 'application/zlib' => ['zz'], - 'audio/3gpp' => ['3gp', '3gpp', '3ga'], - 'audio/3gpp-encrypted' => ['3gp', '3gpp', '3ga'], - 'audio/3gpp2' => ['3g2', '3gp2', '3gpp2'], - 'audio/aac' => ['aac', 'adts', 'ass'], - 'audio/ac3' => ['ac3'], - 'audio/adpcm' => ['adp'], - 'audio/amr' => ['amr'], - 'audio/amr-encrypted' => ['amr'], - 'audio/amr-wb' => ['awb'], - 'audio/amr-wb-encrypted' => ['awb'], - 'audio/annodex' => ['axa'], - 'audio/basic' => ['au', 'snd'], - 'audio/flac' => ['flac'], - 'audio/imelody' => ['imy', 'ime'], - 'audio/m3u' => ['m3u', 'm3u8', 'vlc'], - 'audio/m4a' => ['m4a', 'f4a'], - 'audio/midi' => ['mid', 'midi', 'kar', 'rmi'], - 'audio/mobile-xmf' => ['xmf'], - 'audio/mp2' => ['mp2'], - 'audio/mp3' => ['mp3', 'mpga'], - 'audio/mp4' => ['m4a', 'mp4a', 'f4a'], - 'audio/mpeg' => ['mpga', 'mp2', 'mp2a', 'mp3', 'm2a', 'm3a'], - 'audio/mpegurl' => ['m3u', 'm3u8', 'vlc'], - 'audio/ogg' => ['oga', 'ogg', 'spx', 'opus'], - 'audio/prs.sid' => ['sid', 'psid'], - 'audio/s3m' => ['s3m'], - 'audio/scpls' => ['pls'], - 'audio/silk' => ['sil'], - 'audio/tta' => ['tta'], - 'audio/usac' => ['loas', 'xhe'], - 'audio/vnd.audible' => ['aa', 'aax'], - 'audio/vnd.audible.aax' => ['aa', 'aax'], - 'audio/vnd.dece.audio' => ['uva', 'uvva'], - 'audio/vnd.digital-winds' => ['eol'], - 'audio/vnd.dra' => ['dra'], - 'audio/vnd.dts' => ['dts'], - 'audio/vnd.dts.hd' => ['dtshd'], - 'audio/vnd.lucent.voice' => ['lvp'], - 'audio/vnd.m-realaudio' => ['ra', 'rax'], - 'audio/vnd.ms-playready.media.pya' => ['pya'], - 'audio/vnd.nuera.ecelp4800' => ['ecelp4800'], - 'audio/vnd.nuera.ecelp7470' => ['ecelp7470'], - 'audio/vnd.nuera.ecelp9600' => ['ecelp9600'], - 'audio/vnd.rip' => ['rip'], - 'audio/vnd.rn-realaudio' => ['ra', 'rax'], - 'audio/vnd.wave' => ['wav'], - 'audio/vorbis' => ['oga', 'ogg'], - 'audio/wav' => ['wav'], - 'audio/webm' => ['weba'], - 'audio/wma' => ['wma'], - 'audio/x-aac' => ['aac', 'adts', 'ass'], - 'audio/x-aifc' => ['aifc', 'aiffc'], - 'audio/x-aiff' => ['aif', 'aiff', 'aifc'], - 'audio/x-aiffc' => ['aifc', 'aiffc'], - 'audio/x-amzxml' => ['amz'], - 'audio/x-annodex' => ['axa'], - 'audio/x-ape' => ['ape'], - 'audio/x-caf' => ['caf'], - 'audio/x-dts' => ['dts'], - 'audio/x-dtshd' => ['dtshd'], - 'audio/x-flac' => ['flac'], - 'audio/x-flac+ogg' => ['oga', 'ogg'], - 'audio/x-gsm' => ['gsm'], - 'audio/x-hx-aac-adts' => ['aac', 'adts', 'ass'], - 'audio/x-imelody' => ['imy', 'ime'], - 'audio/x-iriver-pla' => ['pla'], - 'audio/x-it' => ['it'], - 'audio/x-m3u' => ['m3u', 'm3u8', 'vlc'], - 'audio/x-m4a' => ['m4a', 'f4a'], - 'audio/x-m4b' => ['m4b', 'f4b'], - 'audio/x-m4r' => ['m4r'], - 'audio/x-matroska' => ['mka'], - 'audio/x-midi' => ['mid', 'midi', 'kar'], - 'audio/x-minipsf' => ['minipsf'], - 'audio/x-mo3' => ['mo3'], - 'audio/x-mod' => ['mod', 'ult', 'uni', 'm15', 'mtm', '669', 'med'], - 'audio/x-mp2' => ['mp2'], - 'audio/x-mp3' => ['mp3', 'mpga'], - 'audio/x-mp3-playlist' => ['m3u', 'm3u8', 'vlc'], - 'audio/x-mpeg' => ['mp3', 'mpga'], - 'audio/x-mpegurl' => ['m3u', 'm3u8', 'vlc'], - 'audio/x-mpg' => ['mp3', 'mpga'], - 'audio/x-ms-asx' => ['asx', 'wax', 'wvx', 'wmx'], - 'audio/x-ms-wax' => ['wax'], - 'audio/x-ms-wma' => ['wma'], - 'audio/x-musepack' => ['mpc', 'mpp', 'mp+'], - 'audio/x-ogg' => ['oga', 'ogg', 'opus'], - 'audio/x-oggflac' => ['oga', 'ogg'], - 'audio/x-opus+ogg' => ['opus'], - 'audio/x-pn-audibleaudio' => ['aa', 'aax'], - 'audio/x-pn-realaudio' => ['ram', 'ra', 'rax'], - 'audio/x-pn-realaudio-plugin' => ['rmp'], - 'audio/x-psf' => ['psf'], - 'audio/x-psflib' => ['psflib'], - 'audio/x-rn-3gpp-amr' => ['3gp', '3gpp', '3ga'], - 'audio/x-rn-3gpp-amr-encrypted' => ['3gp', '3gpp', '3ga'], - 'audio/x-rn-3gpp-amr-wb' => ['3gp', '3gpp', '3ga'], - 'audio/x-rn-3gpp-amr-wb-encrypted' => ['3gp', '3gpp', '3ga'], - 'audio/x-s3m' => ['s3m'], - 'audio/x-scpls' => ['pls'], - 'audio/x-shorten' => ['shn'], - 'audio/x-speex' => ['spx'], - 'audio/x-speex+ogg' => ['oga', 'ogg'], - 'audio/x-stm' => ['stm'], - 'audio/x-tta' => ['tta'], - 'audio/x-voc' => ['voc'], - 'audio/x-vorbis' => ['oga', 'ogg'], - 'audio/x-vorbis+ogg' => ['oga', 'ogg'], - 'audio/x-wav' => ['wav'], - 'audio/x-wavpack' => ['wv', 'wvp'], - 'audio/x-wavpack-correction' => ['wvc'], - 'audio/x-xi' => ['xi'], - 'audio/x-xm' => ['xm'], - 'audio/x-xmf' => ['xmf'], - 'audio/xm' => ['xm'], - 'audio/xmf' => ['xmf'], - 'chemical/x-cdx' => ['cdx'], - 'chemical/x-cif' => ['cif'], - 'chemical/x-cmdf' => ['cmdf'], - 'chemical/x-cml' => ['cml'], - 'chemical/x-csml' => ['csml'], - 'chemical/x-xyz' => ['xyz'], - 'flv-application/octet-stream' => ['flv'], - 'font/collection' => ['ttc'], - 'font/otf' => ['otf'], - 'font/ttf' => ['ttf'], - 'font/woff' => ['woff', 'woff2'], - 'font/woff2' => ['woff2'], - 'image/bmp' => ['bmp', 'dib'], - 'image/cdr' => ['cdr'], - 'image/cgm' => ['cgm'], - 'image/emf' => ['emf'], - 'image/fax-g3' => ['g3'], - 'image/fits' => ['fits'], - 'image/g3fax' => ['g3'], - 'image/gif' => ['gif'], - 'image/heic' => ['heic', 'heif'], - 'image/heic-sequence' => ['heic', 'heif'], - 'image/heif' => ['heic', 'heif'], - 'image/heif-sequence' => ['heic', 'heif'], - 'image/ico' => ['ico'], - 'image/icon' => ['ico'], - 'image/ief' => ['ief'], - 'image/jp2' => ['jp2', 'jpg2'], - 'image/jpeg' => ['jpeg', 'jpg', 'jpe'], - 'image/jpeg2000' => ['jp2', 'jpg2'], - 'image/jpeg2000-image' => ['jp2', 'jpg2'], - 'image/jpm' => ['jpm', 'jpgm'], - 'image/jpx' => ['jpf', 'jpx'], - 'image/ktx' => ['ktx'], - 'image/openraster' => ['ora'], - 'image/pdf' => ['pdf'], - 'image/photoshop' => ['psd'], - 'image/pjpeg' => ['jpeg', 'jpg', 'jpe'], - 'image/png' => ['png'], - 'image/prs.btif' => ['btif'], - 'image/psd' => ['psd'], - 'image/rle' => ['rle'], - 'image/sgi' => ['sgi'], - 'image/svg' => ['svg'], - 'image/svg+xml' => ['svg', 'svgz'], - 'image/svg+xml-compressed' => ['svgz'], - 'image/tiff' => ['tiff', 'tif'], - 'image/vnd.adobe.photoshop' => ['psd'], - 'image/vnd.dece.graphic' => ['uvi', 'uvvi', 'uvg', 'uvvg'], - 'image/vnd.djvu' => ['djvu', 'djv'], - 'image/vnd.djvu+multipage' => ['djvu', 'djv'], - 'image/vnd.dvb.subtitle' => ['sub'], - 'image/vnd.dwg' => ['dwg'], - 'image/vnd.dxf' => ['dxf'], - 'image/vnd.fastbidsheet' => ['fbs'], - 'image/vnd.fpx' => ['fpx'], - 'image/vnd.fst' => ['fst'], - 'image/vnd.fujixerox.edmics-mmr' => ['mmr'], - 'image/vnd.fujixerox.edmics-rlc' => ['rlc'], - 'image/vnd.microsoft.icon' => ['ico'], - 'image/vnd.ms-modi' => ['mdi'], - 'image/vnd.ms-photo' => ['wdp'], - 'image/vnd.net-fpx' => ['npx'], - 'image/vnd.rn-realpix' => ['rp'], - 'image/vnd.wap.wbmp' => ['wbmp'], - 'image/vnd.xiff' => ['xif'], - 'image/vnd.zbrush.pcx' => ['pcx'], - 'image/webp' => ['webp'], - 'image/wmf' => ['wmf'], - 'image/x-3ds' => ['3ds'], - 'image/x-adobe-dng' => ['dng'], - 'image/x-applix-graphics' => ['ag'], - 'image/x-bmp' => ['bmp', 'dib'], - 'image/x-bzeps' => ['eps.bz2', 'epsi.bz2', 'epsf.bz2'], - 'image/x-canon-cr2' => ['cr2'], - 'image/x-canon-crw' => ['crw'], - 'image/x-cdr' => ['cdr'], - 'image/x-cmu-raster' => ['ras'], - 'image/x-cmx' => ['cmx'], - 'image/x-compressed-xcf' => ['xcf.gz', 'xcf.bz2'], - 'image/x-dds' => ['dds'], - 'image/x-djvu' => ['djvu', 'djv'], - 'image/x-emf' => ['emf'], - 'image/x-eps' => ['eps', 'epsi', 'epsf'], - 'image/x-exr' => ['exr'], - 'image/x-fits' => ['fits'], - 'image/x-freehand' => ['fh', 'fhc', 'fh4', 'fh5', 'fh7'], - 'image/x-fuji-raf' => ['raf'], - 'image/x-gimp-gbr' => ['gbr'], - 'image/x-gimp-gih' => ['gih'], - 'image/x-gimp-pat' => ['pat'], - 'image/x-gzeps' => ['eps.gz', 'epsi.gz', 'epsf.gz'], - 'image/x-icb' => ['tga', 'icb', 'tpic', 'vda', 'vst'], - 'image/x-icns' => ['icns'], - 'image/x-ico' => ['ico'], - 'image/x-icon' => ['ico'], - 'image/x-iff' => ['iff', 'ilbm', 'lbm'], - 'image/x-ilbm' => ['iff', 'ilbm', 'lbm'], - 'image/x-jng' => ['jng'], - 'image/x-jp2-codestream' => ['j2c', 'j2k', 'jpc'], - 'image/x-jpeg2000-image' => ['jp2', 'jpg2'], - 'image/x-kodak-dcr' => ['dcr'], - 'image/x-kodak-k25' => ['k25'], - 'image/x-kodak-kdc' => ['kdc'], - 'image/x-lwo' => ['lwo', 'lwob'], - 'image/x-lws' => ['lws'], - 'image/x-macpaint' => ['pntg'], - 'image/x-minolta-mrw' => ['mrw'], - 'image/x-mrsid-image' => ['sid'], - 'image/x-ms-bmp' => ['bmp', 'dib'], - 'image/x-msod' => ['msod'], - 'image/x-nikon-nef' => ['nef'], - 'image/x-olympus-orf' => ['orf'], - 'image/x-panasonic-raw' => ['raw'], - 'image/x-panasonic-raw2' => ['rw2'], - 'image/x-panasonic-rw' => ['raw'], - 'image/x-panasonic-rw2' => ['rw2'], - 'image/x-pcx' => ['pcx'], - 'image/x-pentax-pef' => ['pef'], - 'image/x-photo-cd' => ['pcd'], - 'image/x-photoshop' => ['psd'], - 'image/x-pict' => ['pic', 'pct', 'pict', 'pict1', 'pict2'], - 'image/x-portable-anymap' => ['pnm'], - 'image/x-portable-bitmap' => ['pbm'], - 'image/x-portable-graymap' => ['pgm'], - 'image/x-portable-pixmap' => ['ppm'], - 'image/x-psd' => ['psd'], - 'image/x-quicktime' => ['qtif', 'qif'], - 'image/x-rgb' => ['rgb'], - 'image/x-sgi' => ['sgi'], - 'image/x-sigma-x3f' => ['x3f'], - 'image/x-skencil' => ['sk', 'sk1'], - 'image/x-sony-arw' => ['arw'], - 'image/x-sony-sr2' => ['sr2'], - 'image/x-sony-srf' => ['srf'], - 'image/x-sun-raster' => ['sun'], - 'image/x-tga' => ['tga', 'icb', 'tpic', 'vda', 'vst'], - 'image/x-win-bitmap' => ['cur'], - 'image/x-win-metafile' => ['wmf'], - 'image/x-wmf' => ['wmf'], - 'image/x-xbitmap' => ['xbm'], - 'image/x-xcf' => ['xcf'], - 'image/x-xfig' => ['fig'], - 'image/x-xpixmap' => ['xpm'], - 'image/x-xpm' => ['xpm'], - 'image/x-xwindowdump' => ['xwd'], - 'image/x.djvu' => ['djvu', 'djv'], - 'message/rfc822' => ['eml', 'mime'], - 'model/iges' => ['igs', 'iges'], - 'model/mesh' => ['msh', 'mesh', 'silo'], - 'model/stl' => ['stl'], - 'model/vnd.collada+xml' => ['dae'], - 'model/vnd.dwf' => ['dwf'], - 'model/vnd.gdl' => ['gdl'], - 'model/vnd.gtw' => ['gtw'], - 'model/vnd.mts' => ['mts'], - 'model/vnd.vtu' => ['vtu'], - 'model/vrml' => ['wrl', 'vrml', 'vrm'], - 'model/x.stl-ascii' => ['stl'], - 'model/x.stl-binary' => ['stl'], - 'model/x3d+binary' => ['x3db', 'x3dbz'], - 'model/x3d+vrml' => ['x3dv', 'x3dvz'], - 'model/x3d+xml' => ['x3d', 'x3dz'], - 'text/cache-manifest' => ['appcache', 'manifest'], - 'text/calendar' => ['ics', 'ifb', 'vcs'], - 'text/css' => ['css'], - 'text/csv' => ['csv'], - 'text/csv-schema' => ['csvs'], - 'text/directory' => ['vcard', 'vcf', 'vct', 'gcrd'], - 'text/ecmascript' => ['es'], - 'text/gedcom' => ['ged', 'gedcom'], - 'text/google-video-pointer' => ['gvp'], - 'text/html' => ['html', 'htm'], - 'text/ico' => ['ico'], - 'text/javascript' => ['js', 'jsm', 'mjs'], - 'text/markdown' => ['md', 'mkd', 'markdown'], - 'text/mathml' => ['mml'], - 'text/n3' => ['n3'], - 'text/plain' => ['txt', 'text', 'conf', 'def', 'list', 'log', 'in', 'asc'], - 'text/prs.lines.tag' => ['dsc'], - 'text/rdf' => ['rdf', 'rdfs', 'owl'], - 'text/richtext' => ['rtx'], - 'text/rss' => ['rss'], - 'text/rtf' => ['rtf'], - 'text/rust' => ['rs'], - 'text/sgml' => ['sgml', 'sgm'], - 'text/spreadsheet' => ['sylk', 'slk'], - 'text/tab-separated-values' => ['tsv'], - 'text/troff' => ['t', 'tr', 'roff', 'man', 'me', 'ms'], - 'text/turtle' => ['ttl'], - 'text/uri-list' => ['uri', 'uris', 'urls'], - 'text/vcard' => ['vcard', 'vcf', 'vct', 'gcrd'], - 'text/vnd.curl' => ['curl'], - 'text/vnd.curl.dcurl' => ['dcurl'], - 'text/vnd.curl.mcurl' => ['mcurl'], - 'text/vnd.curl.scurl' => ['scurl'], - 'text/vnd.dvb.subtitle' => ['sub'], - 'text/vnd.fly' => ['fly'], - 'text/vnd.fmi.flexstor' => ['flx'], - 'text/vnd.graphviz' => ['gv', 'dot'], - 'text/vnd.in3d.3dml' => ['3dml'], - 'text/vnd.in3d.spot' => ['spot'], - 'text/vnd.qt.linguist' => ['ts'], - 'text/vnd.rn-realtext' => ['rt'], - 'text/vnd.sun.j2me.app-descriptor' => ['jad'], - 'text/vnd.trolltech.linguist' => ['ts'], - 'text/vnd.wap.wml' => ['wml'], - 'text/vnd.wap.wmlscript' => ['wmls'], - 'text/vtt' => ['vtt'], - 'text/x-adasrc' => ['adb', 'ads'], - 'text/x-asm' => ['s', 'asm'], - 'text/x-bibtex' => ['bib'], - 'text/x-c' => ['c', 'cc', 'cxx', 'cpp', 'h', 'hh', 'dic'], - 'text/x-c++hdr' => ['hh', 'hp', 'hpp', 'h++', 'hxx'], - 'text/x-c++src' => ['cpp', 'cxx', 'cc', 'C', 'c++'], - 'text/x-chdr' => ['h'], - 'text/x-cmake' => ['cmake'], - 'text/x-cobol' => ['cbl', 'cob'], - 'text/x-comma-separated-values' => ['csv'], - 'text/x-csharp' => ['cs'], - 'text/x-csrc' => ['c'], - 'text/x-csv' => ['csv'], - 'text/x-dbus-service' => ['service'], - 'text/x-dcl' => ['dcl'], - 'text/x-diff' => ['diff', 'patch'], - 'text/x-dsl' => ['dsl'], - 'text/x-dsrc' => ['d', 'di'], - 'text/x-dtd' => ['dtd'], - 'text/x-eiffel' => ['e', 'eif'], - 'text/x-emacs-lisp' => ['el'], - 'text/x-erlang' => ['erl'], - 'text/x-fortran' => ['f', 'for', 'f77', 'f90', 'f95'], - 'text/x-genie' => ['gs'], - 'text/x-gettext-translation' => ['po'], - 'text/x-gettext-translation-template' => ['pot'], - 'text/x-gherkin' => ['feature'], - 'text/x-go' => ['go'], - 'text/x-google-video-pointer' => ['gvp'], - 'text/x-haskell' => ['hs'], - 'text/x-idl' => ['idl'], - 'text/x-imelody' => ['imy', 'ime'], - 'text/x-iptables' => ['iptables'], - 'text/x-java' => ['java'], - 'text/x-java-source' => ['java'], - 'text/x-ldif' => ['ldif'], - 'text/x-lilypond' => ['ly'], - 'text/x-literate-haskell' => ['lhs'], - 'text/x-log' => ['log'], - 'text/x-lua' => ['lua'], - 'text/x-lyx' => ['lyx'], - 'text/x-makefile' => ['mk', 'mak'], - 'text/x-markdown' => ['md', 'mkd', 'markdown'], - 'text/x-matlab' => ['m'], - 'text/x-microdvd' => ['sub'], - 'text/x-moc' => ['moc'], - 'text/x-modelica' => ['mo'], - 'text/x-mof' => ['mof'], - 'text/x-mpsub' => ['sub'], - 'text/x-mrml' => ['mrml', 'mrl'], - 'text/x-ms-regedit' => ['reg'], - 'text/x-mup' => ['mup', 'not'], - 'text/x-nfo' => ['nfo'], - 'text/x-objcsrc' => ['m'], - 'text/x-ocaml' => ['ml', 'mli'], - 'text/x-ocl' => ['ocl'], - 'text/x-octave' => ['m'], - 'text/x-ooc' => ['ooc'], - 'text/x-opencl-src' => ['cl'], - 'text/x-opml' => ['opml'], - 'text/x-opml+xml' => ['opml'], - 'text/x-pascal' => ['p', 'pas'], - 'text/x-patch' => ['diff', 'patch'], - 'text/x-perl' => ['pl', 'PL', 'pm', 'al', 'perl', 'pod', 't'], - 'text/x-po' => ['po'], - 'text/x-pot' => ['pot'], - 'text/x-python' => ['py', 'pyx', 'wsgi'], - 'text/x-python3' => ['py', 'py3', 'py3x'], - 'text/x-qml' => ['qml', 'qmltypes', 'qmlproject'], - 'text/x-reject' => ['rej'], - 'text/x-rpm-spec' => ['spec'], - 'text/x-sass' => ['sass'], - 'text/x-scala' => ['scala'], - 'text/x-scheme' => ['scm', 'ss'], - 'text/x-scss' => ['scss'], - 'text/x-setext' => ['etx'], - 'text/x-sfv' => ['sfv'], - 'text/x-sh' => ['sh'], - 'text/x-sql' => ['sql'], - 'text/x-ssa' => ['ssa', 'ass'], - 'text/x-subviewer' => ['sub'], - 'text/x-svhdr' => ['svh'], - 'text/x-svsrc' => ['sv'], - 'text/x-systemd-unit' => ['automount', 'device', 'mount', 'path', 'scope', 'service', 'slice', 'socket', 'swap', 'target', 'timer'], - 'text/x-tcl' => ['tcl', 'tk'], - 'text/x-tex' => ['tex', 'ltx', 'sty', 'cls', 'dtx', 'ins', 'latex'], - 'text/x-texinfo' => ['texi', 'texinfo'], - 'text/x-troff' => ['tr', 'roff', 't'], - 'text/x-troff-me' => ['me'], - 'text/x-troff-mm' => ['mm'], - 'text/x-troff-ms' => ['ms'], - 'text/x-twig' => ['twig'], - 'text/x-txt2tags' => ['t2t'], - 'text/x-uil' => ['uil'], - 'text/x-uuencode' => ['uu', 'uue'], - 'text/x-vala' => ['vala', 'vapi'], - 'text/x-vcalendar' => ['vcs', 'ics'], - 'text/x-vcard' => ['vcf', 'vcard', 'vct', 'gcrd'], - 'text/x-verilog' => ['v'], - 'text/x-vhdl' => ['vhd', 'vhdl'], - 'text/x-xmi' => ['xmi'], - 'text/x-xslfo' => ['fo', 'xslfo'], - 'text/x-yaml' => ['yaml', 'yml'], - 'text/x.gcode' => ['gcode'], - 'text/xml' => ['xml', 'xbl', 'xsd', 'rng'], - 'text/xml-external-parsed-entity' => ['ent'], - 'text/yaml' => ['yaml', 'yml'], - 'video/3gp' => ['3gp', '3gpp', '3ga'], - 'video/3gpp' => ['3gp', '3gpp', '3ga'], - 'video/3gpp-encrypted' => ['3gp', '3gpp', '3ga'], - 'video/3gpp2' => ['3g2', '3gp2', '3gpp2'], - 'video/annodex' => ['axv'], - 'video/avi' => ['avi', 'avf', 'divx'], - 'video/divx' => ['avi', 'avf', 'divx'], - 'video/dv' => ['dv'], - 'video/fli' => ['fli', 'flc'], - 'video/flv' => ['flv'], - 'video/h261' => ['h261'], - 'video/h263' => ['h263'], - 'video/h264' => ['h264'], - 'video/jpeg' => ['jpgv'], - 'video/jpm' => ['jpm', 'jpgm'], - 'video/mj2' => ['mj2', 'mjp2'], - 'video/mp2t' => ['m2t', 'm2ts', 'ts', 'mts', 'cpi', 'clpi', 'mpl', 'mpls', 'bdm', 'bdmv'], - 'video/mp4' => ['mp4', 'mp4v', 'mpg4', 'm4v', 'f4v', 'lrv'], - 'video/mp4v-es' => ['mp4', 'm4v', 'f4v', 'lrv'], - 'video/mpeg' => ['mpeg', 'mpg', 'mpe', 'm1v', 'm2v', 'mp2', 'vob'], - 'video/mpeg-system' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], - 'video/msvideo' => ['avi', 'avf', 'divx'], - 'video/ogg' => ['ogv', 'ogg'], - 'video/quicktime' => ['qt', 'mov', 'moov', 'qtvr'], - 'video/vivo' => ['viv', 'vivo'], - 'video/vnd.dece.hd' => ['uvh', 'uvvh'], - 'video/vnd.dece.mobile' => ['uvm', 'uvvm'], - 'video/vnd.dece.pd' => ['uvp', 'uvvp'], - 'video/vnd.dece.sd' => ['uvs', 'uvvs'], - 'video/vnd.dece.video' => ['uvv', 'uvvv'], - 'video/vnd.divx' => ['avi', 'avf', 'divx'], - 'video/vnd.dvb.file' => ['dvb'], - 'video/vnd.fvt' => ['fvt'], - 'video/vnd.mpegurl' => ['mxu', 'm4u', 'm1u'], - 'video/vnd.ms-playready.media.pyv' => ['pyv'], - 'video/vnd.rn-realvideo' => ['rv', 'rvx'], - 'video/vnd.uvvu.mp4' => ['uvu', 'uvvu'], - 'video/vnd.vivo' => ['viv', 'vivo'], - 'video/webm' => ['webm'], - 'video/x-anim' => ['anim[1-9j]'], - 'video/x-annodex' => ['axv'], - 'video/x-avi' => ['avi', 'avf', 'divx'], - 'video/x-f4v' => ['f4v'], - 'video/x-fli' => ['fli', 'flc'], - 'video/x-flic' => ['fli', 'flc'], - 'video/x-flv' => ['flv'], - 'video/x-javafx' => ['fxm'], - 'video/x-m4v' => ['m4v', 'mp4', 'f4v', 'lrv'], - 'video/x-matroska' => ['mkv', 'mk3d', 'mks'], - 'video/x-matroska-3d' => ['mk3d'], - 'video/x-mjpeg' => ['mjpeg', 'mjpg'], - 'video/x-mng' => ['mng'], - 'video/x-mpeg' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], - 'video/x-mpeg-system' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], - 'video/x-mpeg2' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], - 'video/x-mpegurl' => ['m1u', 'm4u', 'mxu'], - 'video/x-ms-asf' => ['asf', 'asx'], - 'video/x-ms-asf-plugin' => ['asf'], - 'video/x-ms-vob' => ['vob'], - 'video/x-ms-wax' => ['asx', 'wax', 'wvx', 'wmx'], - 'video/x-ms-wm' => ['wm', 'asf'], - 'video/x-ms-wmv' => ['wmv'], - 'video/x-ms-wmx' => ['wmx', 'asx', 'wax', 'wvx'], - 'video/x-ms-wvx' => ['wvx', 'asx', 'wax', 'wmx'], - 'video/x-msvideo' => ['avi', 'avf', 'divx'], - 'video/x-nsv' => ['nsv'], - 'video/x-ogg' => ['ogv', 'ogg'], - 'video/x-ogm' => ['ogm'], - 'video/x-ogm+ogg' => ['ogm'], - 'video/x-real-video' => ['rv', 'rvx'], - 'video/x-sgi-movie' => ['movie'], - 'video/x-smv' => ['smv'], - 'video/x-theora' => ['ogg'], - 'video/x-theora+ogg' => ['ogg'], - 'x-conference/x-cooltalk' => ['ice'], - 'x-epoc/x-sisx-app' => ['sisx'], - 'zz-application/zz-winassoc-123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], - 'zz-application/zz-winassoc-cab' => ['cab'], - 'zz-application/zz-winassoc-cdr' => ['cdr'], - 'zz-application/zz-winassoc-doc' => ['doc'], - 'zz-application/zz-winassoc-hlp' => ['hlp'], - 'zz-application/zz-winassoc-mdb' => ['mdb'], - 'zz-application/zz-winassoc-uu' => ['uue'], - 'zz-application/zz-winassoc-xls' => ['xls', 'xlc', 'xll', 'xlm', 'xlw', 'xla', 'xlt', 'xld'], - ]; - - private static $reverseMap = [ - '32x' => ['application/x-genesis-32x-rom'], - '3dml' => ['text/vnd.in3d.3dml'], - '3ds' => ['image/x-3ds'], - '3g2' => ['audio/3gpp2', 'video/3gpp2'], - '3ga' => ['audio/3gpp', 'audio/3gpp-encrypted', 'audio/x-rn-3gpp-amr', 'audio/x-rn-3gpp-amr-encrypted', 'audio/x-rn-3gpp-amr-wb', 'audio/x-rn-3gpp-amr-wb-encrypted', 'video/3gp', 'video/3gpp', 'video/3gpp-encrypted'], - '3gp' => ['audio/3gpp', 'audio/3gpp-encrypted', 'audio/x-rn-3gpp-amr', 'audio/x-rn-3gpp-amr-encrypted', 'audio/x-rn-3gpp-amr-wb', 'audio/x-rn-3gpp-amr-wb-encrypted', 'video/3gp', 'video/3gpp', 'video/3gpp-encrypted'], - '3gp2' => ['audio/3gpp2', 'video/3gpp2'], - '3gpp' => ['audio/3gpp', 'audio/3gpp-encrypted', 'audio/x-rn-3gpp-amr', 'audio/x-rn-3gpp-amr-encrypted', 'audio/x-rn-3gpp-amr-wb', 'audio/x-rn-3gpp-amr-wb-encrypted', 'video/3gp', 'video/3gpp', 'video/3gpp-encrypted'], - '3gpp2' => ['audio/3gpp2', 'video/3gpp2'], - '7z' => ['application/x-7z-compressed'], - 'BLEND' => ['application/x-blender'], - 'C' => ['text/x-c++src'], - 'PAR2' => ['application/x-par2'], - 'PL' => ['application/x-perl', 'text/x-perl'], - 'Z' => ['application/x-compress'], - 'a' => ['application/x-archive'], - 'a26' => ['application/x-atari-2600-rom'], - 'a78' => ['application/x-atari-7800-rom'], - 'aa' => ['audio/vnd.audible', 'audio/vnd.audible.aax', 'audio/x-pn-audibleaudio'], - 'aab' => ['application/x-authorware-bin'], - 'aac' => ['audio/aac', 'audio/x-aac', 'audio/x-hx-aac-adts'], - 'aam' => ['application/x-authorware-map'], - 'aas' => ['application/x-authorware-seg'], - 'aax' => ['audio/vnd.audible', 'audio/vnd.audible.aax', 'audio/x-pn-audibleaudio'], - 'abw' => ['application/x-abiword'], - 'abw.CRASHED' => ['application/x-abiword'], - 'abw.gz' => ['application/x-abiword'], - 'ac' => ['application/pkix-attr-cert'], - 'ac3' => ['audio/ac3'], - 'acc' => ['application/vnd.americandynamics.acc'], - 'ace' => ['application/x-ace', 'application/x-ace-compressed'], - 'acu' => ['application/vnd.acucobol'], - 'acutc' => ['application/vnd.acucorp'], - 'adb' => ['text/x-adasrc'], - 'adf' => ['application/x-amiga-disk-format'], - 'adp' => ['audio/adpcm'], - 'ads' => ['text/x-adasrc'], - 'adts' => ['audio/aac', 'audio/x-aac', 'audio/x-hx-aac-adts'], - 'aep' => ['application/vnd.audiograph'], - 'afm' => ['application/x-font-afm', 'application/x-font-type1'], - 'afp' => ['application/vnd.ibm.modcap'], - 'ag' => ['image/x-applix-graphics'], - 'agb' => ['application/x-gba-rom'], - 'ahead' => ['application/vnd.ahead.space'], - 'ai' => ['application/illustrator', 'application/postscript', 'application/vnd.adobe.illustrator'], - 'aif' => ['audio/x-aiff'], - 'aifc' => ['audio/x-aifc', 'audio/x-aiff', 'audio/x-aiffc'], - 'aiff' => ['audio/x-aiff'], - 'aiffc' => ['audio/x-aifc', 'audio/x-aiffc'], - 'air' => ['application/vnd.adobe.air-application-installer-package+zip'], - 'ait' => ['application/vnd.dvb.ait'], - 'al' => ['application/x-perl', 'text/x-perl'], - 'alz' => ['application/x-alz'], - 'ami' => ['application/vnd.amiga.ami'], - 'amr' => ['audio/amr', 'audio/amr-encrypted'], - 'amz' => ['audio/x-amzxml'], - 'ani' => ['application/x-navi-animation'], - 'anim[1-9j]' => ['video/x-anim'], - 'anx' => ['application/annodex', 'application/x-annodex'], - 'ape' => ['audio/x-ape'], - 'apk' => ['application/vnd.android.package-archive'], - 'appcache' => ['text/cache-manifest'], - 'appimage' => ['application/vnd.appimage', 'application/x-iso9660-appimage'], - 'application' => ['application/x-ms-application'], - 'apr' => ['application/vnd.lotus-approach'], - 'aps' => ['application/postscript'], - 'ar' => ['application/x-archive'], - 'arc' => ['application/x-freearc'], - 'arj' => ['application/x-arj'], - 'arw' => ['image/x-sony-arw'], - 'as' => ['application/x-applix-spreadsheet'], - 'asc' => ['application/pgp', 'application/pgp-encrypted', 'application/pgp-keys', 'application/pgp-signature', 'text/plain'], - 'asf' => ['application/vnd.ms-asf', 'video/x-ms-asf', 'video/x-ms-asf-plugin', 'video/x-ms-wm'], - 'asm' => ['text/x-asm'], - 'aso' => ['application/vnd.accpac.simply.aso'], - 'asp' => ['application/x-asp'], - 'ass' => ['audio/aac', 'audio/x-aac', 'audio/x-hx-aac-adts', 'text/x-ssa'], - 'asx' => ['application/x-ms-asx', 'audio/x-ms-asx', 'video/x-ms-asf', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], - 'atc' => ['application/vnd.acucorp'], - 'atom' => ['application/atom+xml'], - 'atomcat' => ['application/atomcat+xml'], - 'atomsvc' => ['application/atomsvc+xml'], - 'atx' => ['application/vnd.antix.game-component'], - 'au' => ['audio/basic'], - 'automount' => ['text/x-systemd-unit'], - 'avf' => ['video/avi', 'video/divx', 'video/msvideo', 'video/vnd.divx', 'video/x-avi', 'video/x-msvideo'], - 'avi' => ['video/avi', 'video/divx', 'video/msvideo', 'video/vnd.divx', 'video/x-avi', 'video/x-msvideo'], - 'aw' => ['application/applixware', 'application/x-applix-word'], - 'awb' => ['audio/amr-wb', 'audio/amr-wb-encrypted'], - 'awk' => ['application/x-awk'], - 'axa' => ['audio/annodex', 'audio/x-annodex'], - 'axv' => ['video/annodex', 'video/x-annodex'], - 'azf' => ['application/vnd.airzip.filesecure.azf'], - 'azs' => ['application/vnd.airzip.filesecure.azs'], - 'azw' => ['application/vnd.amazon.ebook'], - 'bak' => ['application/x-trash'], - 'bat' => ['application/x-msdownload'], - 'bcpio' => ['application/x-bcpio'], - 'bdf' => ['application/x-font-bdf'], - 'bdm' => ['application/vnd.syncml.dm+wbxml', 'video/mp2t'], - 'bdmv' => ['video/mp2t'], - 'bed' => ['application/vnd.realvnc.bed'], - 'bh2' => ['application/vnd.fujitsu.oasysprs'], - 'bib' => ['text/x-bibtex'], - 'bin' => ['application/octet-stream', 'application/x-saturn-rom', 'application/x-sega-cd-rom'], - 'blb' => ['application/x-blorb'], - 'blend' => ['application/x-blender'], - 'blender' => ['application/x-blender'], - 'blorb' => ['application/x-blorb'], - 'bmi' => ['application/vnd.bmi'], - 'bmp' => ['image/bmp', 'image/x-bmp', 'image/x-ms-bmp'], - 'book' => ['application/vnd.framemaker'], - 'box' => ['application/vnd.previewsystems.box'], - 'boz' => ['application/x-bzip2'], - 'bpk' => ['application/octet-stream'], - 'bsdiff' => ['application/x-bsdiff'], - 'btif' => ['image/prs.btif'], - 'bz' => ['application/x-bzip', 'application/x-bzip2'], - 'bz2' => ['application/x-bz2', 'application/x-bzip', 'application/x-bzip2'], - 'c' => ['text/x-c', 'text/x-csrc'], - 'c++' => ['text/x-c++src'], - 'c11amc' => ['application/vnd.cluetrust.cartomobile-config'], - 'c11amz' => ['application/vnd.cluetrust.cartomobile-config-pkg'], - 'c4d' => ['application/vnd.clonk.c4group'], - 'c4f' => ['application/vnd.clonk.c4group'], - 'c4g' => ['application/vnd.clonk.c4group'], - 'c4p' => ['application/vnd.clonk.c4group'], - 'c4u' => ['application/vnd.clonk.c4group'], - 'cab' => ['application/vnd.ms-cab-compressed', 'zz-application/zz-winassoc-cab'], - 'caf' => ['audio/x-caf'], - 'cap' => ['application/pcap', 'application/vnd.tcpdump.pcap', 'application/x-pcap'], - 'car' => ['application/vnd.curl.car'], - 'cat' => ['application/vnd.ms-pki.seccat'], - 'cb7' => ['application/x-cb7', 'application/x-cbr'], - 'cba' => ['application/x-cbr'], - 'cbl' => ['text/x-cobol'], - 'cbr' => ['application/vnd.comicbook-rar', 'application/x-cbr'], - 'cbt' => ['application/x-cbr', 'application/x-cbt'], - 'cbz' => ['application/vnd.comicbook+zip', 'application/x-cbr', 'application/x-cbz'], - 'cc' => ['text/x-c', 'text/x-c++src'], - 'ccmx' => ['application/x-ccmx'], - 'cct' => ['application/x-director'], - 'ccxml' => ['application/ccxml+xml'], - 'cdbcmsg' => ['application/vnd.contact.cmsg'], - 'cdf' => ['application/x-netcdf'], - 'cdkey' => ['application/vnd.mediastation.cdkey'], - 'cdmia' => ['application/cdmi-capability'], - 'cdmic' => ['application/cdmi-container'], - 'cdmid' => ['application/cdmi-domain'], - 'cdmio' => ['application/cdmi-object'], - 'cdmiq' => ['application/cdmi-queue'], - 'cdr' => ['application/cdr', 'application/coreldraw', 'application/vnd.corel-draw', 'application/x-cdr', 'application/x-coreldraw', 'image/cdr', 'image/x-cdr', 'zz-application/zz-winassoc-cdr'], - 'cdx' => ['chemical/x-cdx'], - 'cdxml' => ['application/vnd.chemdraw+xml'], - 'cdy' => ['application/vnd.cinderella'], - 'cer' => ['application/pkix-cert'], - 'cert' => ['application/x-x509-ca-cert'], - 'cfs' => ['application/x-cfs-compressed'], - 'cgb' => ['application/x-gameboy-color-rom'], - 'cgm' => ['image/cgm'], - 'chat' => ['application/x-chat'], - 'chm' => ['application/vnd.ms-htmlhelp', 'application/x-chm'], - 'chrt' => ['application/vnd.kde.kchart', 'application/x-kchart'], - 'cif' => ['chemical/x-cif'], - 'cii' => ['application/vnd.anser-web-certificate-issue-initiation'], - 'cil' => ['application/vnd.ms-artgalry'], - 'cl' => ['text/x-opencl-src'], - 'cla' => ['application/vnd.claymore'], - 'class' => ['application/java', 'application/java-byte-code', 'application/java-vm', 'application/x-java', 'application/x-java-class', 'application/x-java-vm'], - 'clkk' => ['application/vnd.crick.clicker.keyboard'], - 'clkp' => ['application/vnd.crick.clicker.palette'], - 'clkt' => ['application/vnd.crick.clicker.template'], - 'clkw' => ['application/vnd.crick.clicker.wordbank'], - 'clkx' => ['application/vnd.crick.clicker'], - 'clp' => ['application/x-msclip'], - 'clpi' => ['video/mp2t'], - 'cls' => ['application/x-tex', 'text/x-tex'], - 'cmake' => ['text/x-cmake'], - 'cmc' => ['application/vnd.cosmocaller'], - 'cmdf' => ['chemical/x-cmdf'], - 'cml' => ['chemical/x-cml'], - 'cmp' => ['application/vnd.yellowriver-custom-menu'], - 'cmx' => ['image/x-cmx'], - 'cob' => ['text/x-cobol'], - 'cod' => ['application/vnd.rim.cod'], - 'coffee' => ['application/vnd.coffeescript'], - 'com' => ['application/x-msdownload'], - 'conf' => ['text/plain'], - 'cpi' => ['video/mp2t'], - 'cpio' => ['application/x-cpio'], - 'cpio.gz' => ['application/x-cpio-compressed'], - 'cpp' => ['text/x-c', 'text/x-c++src'], - 'cpt' => ['application/mac-compactpro'], - 'cr2' => ['image/x-canon-cr2'], - 'crd' => ['application/x-mscardfile'], - 'crdownload' => ['application/x-partial-download'], - 'crl' => ['application/pkix-crl'], - 'crt' => ['application/x-x509-ca-cert'], - 'crw' => ['image/x-canon-crw'], - 'cryptonote' => ['application/vnd.rig.cryptonote'], - 'cs' => ['text/x-csharp'], - 'csh' => ['application/x-csh'], - 'csml' => ['chemical/x-csml'], - 'csp' => ['application/vnd.commonspace'], - 'css' => ['text/css'], - 'cst' => ['application/x-director'], - 'csv' => ['text/csv', 'text/x-comma-separated-values', 'text/x-csv'], - 'csvs' => ['text/csv-schema'], - 'cu' => ['application/cu-seeme'], - 'cue' => ['application/x-cue'], - 'cur' => ['image/x-win-bitmap'], - 'curl' => ['text/vnd.curl'], - 'cww' => ['application/prs.cww'], - 'cxt' => ['application/x-director'], - 'cxx' => ['text/x-c', 'text/x-c++src'], - 'd' => ['text/x-dsrc'], - 'dae' => ['model/vnd.collada+xml'], - 'daf' => ['application/vnd.mobius.daf'], - 'dar' => ['application/x-dar'], - 'dart' => ['application/vnd.dart'], - 'dataless' => ['application/vnd.fdsn.seed'], - 'davmount' => ['application/davmount+xml'], - 'dbf' => ['application/dbase', 'application/dbf', 'application/x-dbase', 'application/x-dbf'], - 'dbk' => ['application/docbook+xml', 'application/vnd.oasis.docbook+xml', 'application/x-docbook+xml'], - 'dc' => ['application/x-dc-rom'], - 'dcl' => ['text/x-dcl'], - 'dcm' => ['application/dicom'], - 'dcr' => ['application/x-director', 'image/x-kodak-dcr'], - 'dcurl' => ['text/vnd.curl.dcurl'], - 'dd2' => ['application/vnd.oma.dd2+xml'], - 'ddd' => ['application/vnd.fujixerox.ddd'], - 'dds' => ['image/x-dds'], - 'deb' => ['application/vnd.debian.binary-package', 'application/x-deb', 'application/x-debian-package'], - 'def' => ['text/plain'], - 'deploy' => ['application/octet-stream'], - 'der' => ['application/x-x509-ca-cert'], - 'desktop' => ['application/x-desktop', 'application/x-gnome-app-info'], - 'device' => ['text/x-systemd-unit'], - 'dfac' => ['application/vnd.dreamfactory'], - 'dgc' => ['application/x-dgc-compressed'], - 'di' => ['text/x-dsrc'], - 'dia' => ['application/x-dia-diagram'], - 'dib' => ['image/bmp', 'image/x-bmp', 'image/x-ms-bmp'], - 'dic' => ['text/x-c'], - 'diff' => ['text/x-diff', 'text/x-patch'], - 'dir' => ['application/x-director'], - 'dis' => ['application/vnd.mobius.dis'], - 'dist' => ['application/octet-stream'], - 'distz' => ['application/octet-stream'], - 'divx' => ['video/avi', 'video/divx', 'video/msvideo', 'video/vnd.divx', 'video/x-avi', 'video/x-msvideo'], - 'djv' => ['image/vnd.djvu', 'image/vnd.djvu+multipage', 'image/x-djvu', 'image/x.djvu'], - 'djvu' => ['image/vnd.djvu', 'image/vnd.djvu+multipage', 'image/x-djvu', 'image/x.djvu'], - 'dll' => ['application/x-msdownload'], - 'dmg' => ['application/x-apple-diskimage'], - 'dmp' => ['application/pcap', 'application/vnd.tcpdump.pcap', 'application/x-pcap'], - 'dms' => ['application/octet-stream'], - 'dna' => ['application/vnd.dna'], - 'dng' => ['image/x-adobe-dng'], - 'doc' => ['application/msword', 'application/vnd.ms-word', 'application/x-msword', 'zz-application/zz-winassoc-doc'], - 'docbook' => ['application/docbook+xml', 'application/vnd.oasis.docbook+xml', 'application/x-docbook+xml'], - 'docm' => ['application/vnd.ms-word.document.macroenabled.12'], - 'docx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'], - 'dot' => ['application/msword', 'application/msword-template', 'text/vnd.graphviz'], - 'dotm' => ['application/vnd.ms-word.template.macroenabled.12'], - 'dotx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.template'], - 'dp' => ['application/vnd.osgi.dp'], - 'dpg' => ['application/vnd.dpgraph'], - 'dra' => ['audio/vnd.dra'], - 'dsc' => ['text/prs.lines.tag'], - 'dsl' => ['text/x-dsl'], - 'dssc' => ['application/dssc+der'], - 'dtb' => ['application/x-dtbook+xml'], - 'dtd' => ['application/xml-dtd', 'text/x-dtd'], - 'dts' => ['audio/vnd.dts', 'audio/x-dts'], - 'dtshd' => ['audio/vnd.dts.hd', 'audio/x-dtshd'], - 'dtx' => ['application/x-tex', 'text/x-tex'], - 'dump' => ['application/octet-stream'], - 'dv' => ['video/dv'], - 'dvb' => ['video/vnd.dvb.file'], - 'dvi' => ['application/x-dvi'], - 'dvi.bz2' => ['application/x-bzdvi'], - 'dvi.gz' => ['application/x-gzdvi'], - 'dwf' => ['model/vnd.dwf'], - 'dwg' => ['image/vnd.dwg'], - 'dxf' => ['image/vnd.dxf'], - 'dxp' => ['application/vnd.spotfire.dxp'], - 'dxr' => ['application/x-director'], - 'e' => ['text/x-eiffel'], - 'ecelp4800' => ['audio/vnd.nuera.ecelp4800'], - 'ecelp7470' => ['audio/vnd.nuera.ecelp7470'], - 'ecelp9600' => ['audio/vnd.nuera.ecelp9600'], - 'ecma' => ['application/ecmascript'], - 'edm' => ['application/vnd.novadigm.edm'], - 'edx' => ['application/vnd.novadigm.edx'], - 'efif' => ['application/vnd.picsel'], - 'egon' => ['application/x-egon'], - 'ei6' => ['application/vnd.pg.osasli'], - 'eif' => ['text/x-eiffel'], - 'el' => ['text/x-emacs-lisp'], - 'elc' => ['application/octet-stream'], - 'emf' => ['application/emf', 'application/x-emf', 'application/x-msmetafile', 'image/emf', 'image/x-emf'], - 'eml' => ['message/rfc822'], - 'emma' => ['application/emma+xml'], - 'emp' => ['application/vnd.emusic-emusic_package'], - 'emz' => ['application/x-msmetafile'], - 'ent' => ['application/xml-external-parsed-entity', 'text/xml-external-parsed-entity'], - 'eol' => ['audio/vnd.digital-winds'], - 'eot' => ['application/vnd.ms-fontobject'], - 'eps' => ['application/postscript', 'image/x-eps'], - 'eps.bz2' => ['image/x-bzeps'], - 'eps.gz' => ['image/x-gzeps'], - 'epsf' => ['image/x-eps'], - 'epsf.bz2' => ['image/x-bzeps'], - 'epsf.gz' => ['image/x-gzeps'], - 'epsi' => ['image/x-eps'], - 'epsi.bz2' => ['image/x-bzeps'], - 'epsi.gz' => ['image/x-gzeps'], - 'epub' => ['application/epub+zip'], - 'erl' => ['text/x-erlang'], - 'es' => ['application/ecmascript', 'text/ecmascript'], - 'es3' => ['application/vnd.eszigno3+xml'], - 'esa' => ['application/vnd.osgi.subsystem'], - 'esf' => ['application/vnd.epson.esf'], - 'et3' => ['application/vnd.eszigno3+xml'], - 'etheme' => ['application/x-e-theme'], - 'etx' => ['text/x-setext'], - 'eva' => ['application/x-eva'], - 'evy' => ['application/x-envoy'], - 'exe' => ['application/x-ms-dos-executable', 'application/x-msdownload'], - 'exi' => ['application/exi'], - 'exr' => ['image/x-exr'], - 'ext' => ['application/vnd.novadigm.ext'], - 'ez' => ['application/andrew-inset'], - 'ez2' => ['application/vnd.ezpix-album'], - 'ez3' => ['application/vnd.ezpix-package'], - 'f' => ['text/x-fortran'], - 'f4a' => ['audio/m4a', 'audio/mp4', 'audio/x-m4a'], - 'f4b' => ['audio/x-m4b'], - 'f4v' => ['video/mp4', 'video/mp4v-es', 'video/x-f4v', 'video/x-m4v'], - 'f77' => ['text/x-fortran'], - 'f90' => ['text/x-fortran'], - 'f95' => ['text/x-fortran'], - 'fb2' => ['application/x-fictionbook', 'application/x-fictionbook+xml'], - 'fb2.zip' => ['application/x-zip-compressed-fb2'], - 'fbs' => ['image/vnd.fastbidsheet'], - 'fcdt' => ['application/vnd.adobe.formscentral.fcdt'], - 'fcs' => ['application/vnd.isac.fcs'], - 'fd' => ['application/x-fd-file', 'application/x-raw-floppy-disk-image'], - 'fdf' => ['application/vnd.fdf'], - 'fds' => ['application/x-fds-disk'], - 'fe_launch' => ['application/vnd.denovo.fcselayout-link'], - 'feature' => ['text/x-gherkin'], - 'fg5' => ['application/vnd.fujitsu.oasysgp'], - 'fgd' => ['application/x-director'], - 'fh' => ['image/x-freehand'], - 'fh4' => ['image/x-freehand'], - 'fh5' => ['image/x-freehand'], - 'fh7' => ['image/x-freehand'], - 'fhc' => ['image/x-freehand'], - 'fig' => ['application/x-xfig', 'image/x-xfig'], - 'fits' => ['image/fits', 'image/x-fits'], - 'fl' => ['application/x-fluid'], - 'flac' => ['audio/flac', 'audio/x-flac'], - 'flatpak' => ['application/vnd.flatpak', 'application/vnd.xdgapp'], - 'flatpakref' => ['application/vnd.flatpak.ref'], - 'flatpakrepo' => ['application/vnd.flatpak.repo'], - 'flc' => ['video/fli', 'video/x-fli', 'video/x-flic'], - 'fli' => ['video/fli', 'video/x-fli', 'video/x-flic'], - 'flo' => ['application/vnd.micrografx.flo'], - 'flv' => ['video/x-flv', 'application/x-flash-video', 'flv-application/octet-stream', 'video/flv'], - 'flw' => ['application/vnd.kde.kivio', 'application/x-kivio'], - 'flx' => ['text/vnd.fmi.flexstor'], - 'fly' => ['text/vnd.fly'], - 'fm' => ['application/vnd.framemaker', 'application/x-frame'], - 'fnc' => ['application/vnd.frogans.fnc'], - 'fo' => ['text/x-xslfo'], - 'fodg' => ['application/vnd.oasis.opendocument.graphics-flat-xml'], - 'fodp' => ['application/vnd.oasis.opendocument.presentation-flat-xml'], - 'fods' => ['application/vnd.oasis.opendocument.spreadsheet-flat-xml'], - 'fodt' => ['application/vnd.oasis.opendocument.text-flat-xml'], - 'for' => ['text/x-fortran'], - 'fpx' => ['image/vnd.fpx'], - 'frame' => ['application/vnd.framemaker'], - 'fsc' => ['application/vnd.fsc.weblaunch'], - 'fst' => ['image/vnd.fst'], - 'ftc' => ['application/vnd.fluxtime.clip'], - 'fti' => ['application/vnd.anser-web-funds-transfer-initiation'], - 'fvt' => ['video/vnd.fvt'], - 'fxm' => ['video/x-javafx'], - 'fxp' => ['application/vnd.adobe.fxp'], - 'fxpl' => ['application/vnd.adobe.fxp'], - 'fzs' => ['application/vnd.fuzzysheet'], - 'g2w' => ['application/vnd.geoplan'], - 'g3' => ['image/fax-g3', 'image/g3fax'], - 'g3w' => ['application/vnd.geospace'], - 'gac' => ['application/vnd.groove-account'], - 'gam' => ['application/x-tads'], - 'gb' => ['application/x-gameboy-rom'], - 'gba' => ['application/x-gba-rom'], - 'gbc' => ['application/x-gameboy-color-rom'], - 'gbr' => ['application/rpki-ghostbusters', 'image/x-gimp-gbr'], - 'gca' => ['application/x-gca-compressed'], - 'gcode' => ['text/x.gcode'], - 'gcrd' => ['text/directory', 'text/vcard', 'text/x-vcard'], - 'gdl' => ['model/vnd.gdl'], - 'ged' => ['application/x-gedcom', 'text/gedcom'], - 'gedcom' => ['application/x-gedcom', 'text/gedcom'], - 'gem' => ['application/x-gtar', 'application/x-tar'], - 'gen' => ['application/x-genesis-rom'], - 'geo' => ['application/vnd.dynageo'], - 'geo.json' => ['application/geo+json', 'application/vnd.geo+json'], - 'geojson' => ['application/geo+json', 'application/vnd.geo+json'], - 'gex' => ['application/vnd.geometry-explorer'], - 'gf' => ['application/x-tex-gf'], - 'gg' => ['application/x-gamegear-rom'], - 'ggb' => ['application/vnd.geogebra.file'], - 'ggt' => ['application/vnd.geogebra.tool'], - 'ghf' => ['application/vnd.groove-help'], - 'gif' => ['image/gif'], - 'gih' => ['image/x-gimp-gih'], - 'gim' => ['application/vnd.groove-identity-message'], - 'glade' => ['application/x-glade'], - 'gml' => ['application/gml+xml'], - 'gmo' => ['application/x-gettext-translation'], - 'gmx' => ['application/vnd.gmx'], - 'gnc' => ['application/x-gnucash'], - 'gnd' => ['application/gnunet-directory'], - 'gnucash' => ['application/x-gnucash'], - 'gnumeric' => ['application/x-gnumeric'], - 'gnuplot' => ['application/x-gnuplot'], - 'go' => ['text/x-go'], - 'gp' => ['application/x-gnuplot'], - 'gpg' => ['application/pgp', 'application/pgp-encrypted', 'application/pgp-keys', 'application/pgp-signature'], - 'gph' => ['application/vnd.flographit'], - 'gplt' => ['application/x-gnuplot'], - 'gpx' => ['application/gpx', 'application/gpx+xml', 'application/x-gpx', 'application/x-gpx+xml'], - 'gqf' => ['application/vnd.grafeq'], - 'gqs' => ['application/vnd.grafeq'], - 'gra' => ['application/x-graphite'], - 'gram' => ['application/srgs'], - 'gramps' => ['application/x-gramps-xml'], - 'gre' => ['application/vnd.geometry-explorer'], - 'grv' => ['application/vnd.groove-injector'], - 'grxml' => ['application/srgs+xml'], - 'gs' => ['text/x-genie'], - 'gsf' => ['application/x-font-ghostscript', 'application/x-font-type1'], - 'gsm' => ['audio/x-gsm'], - 'gtar' => ['application/x-gtar', 'application/x-tar'], - 'gtm' => ['application/vnd.groove-tool-message'], - 'gtw' => ['model/vnd.gtw'], - 'gv' => ['text/vnd.graphviz'], - 'gvp' => ['text/google-video-pointer', 'text/x-google-video-pointer'], - 'gxf' => ['application/gxf'], - 'gxt' => ['application/vnd.geonext'], - 'gz' => ['application/x-gzip', 'application/gzip'], - 'h' => ['text/x-c', 'text/x-chdr'], - 'h++' => ['text/x-c++hdr'], - 'h261' => ['video/h261'], - 'h263' => ['video/h263'], - 'h264' => ['video/h264'], - 'h4' => ['application/x-hdf'], - 'h5' => ['application/x-hdf'], - 'hal' => ['application/vnd.hal+xml'], - 'hbci' => ['application/vnd.hbci'], - 'hdf' => ['application/x-hdf'], - 'hdf4' => ['application/x-hdf'], - 'hdf5' => ['application/x-hdf'], - 'heic' => ['image/heic', 'image/heic-sequence', 'image/heif', 'image/heif-sequence'], - 'heif' => ['image/heic', 'image/heic-sequence', 'image/heif', 'image/heif-sequence'], - 'hfe' => ['application/x-hfe-file', 'application/x-hfe-floppy-image'], - 'hh' => ['text/x-c', 'text/x-c++hdr'], - 'hlp' => ['application/winhlp', 'zz-application/zz-winassoc-hlp'], - 'hp' => ['text/x-c++hdr'], - 'hpgl' => ['application/vnd.hp-hpgl'], - 'hpid' => ['application/vnd.hp-hpid'], - 'hpp' => ['text/x-c++hdr'], - 'hps' => ['application/vnd.hp-hps'], - 'hqx' => ['application/stuffit', 'application/mac-binhex40'], - 'hs' => ['text/x-haskell'], - 'htke' => ['application/vnd.kenameaapp'], - 'htm' => ['text/html'], - 'html' => ['text/html'], - 'hvd' => ['application/vnd.yamaha.hv-dic'], - 'hvp' => ['application/vnd.yamaha.hv-voice'], - 'hvs' => ['application/vnd.yamaha.hv-script'], - 'hwp' => ['application/vnd.haansoft-hwp', 'application/x-hwp'], - 'hwt' => ['application/vnd.haansoft-hwt', 'application/x-hwt'], - 'hxx' => ['text/x-c++hdr'], - 'i2g' => ['application/vnd.intergeo'], - 'ica' => ['application/x-ica'], - 'icb' => ['image/x-icb', 'image/x-tga'], - 'icc' => ['application/vnd.iccprofile'], - 'ice' => ['x-conference/x-cooltalk'], - 'icm' => ['application/vnd.iccprofile'], - 'icns' => ['image/x-icns'], - 'ico' => ['application/ico', 'image/ico', 'image/icon', 'image/vnd.microsoft.icon', 'image/x-ico', 'image/x-icon', 'text/ico'], - 'ics' => ['application/ics', 'text/calendar', 'text/x-vcalendar'], - 'idl' => ['text/x-idl'], - 'ief' => ['image/ief'], - 'ifb' => ['text/calendar'], - 'iff' => ['image/x-iff', 'image/x-ilbm'], - 'ifm' => ['application/vnd.shana.informed.formdata'], - 'iges' => ['model/iges'], - 'igl' => ['application/vnd.igloader'], - 'igm' => ['application/vnd.insors.igm'], - 'igs' => ['model/iges'], - 'igx' => ['application/vnd.micrografx.igx'], - 'iif' => ['application/vnd.shana.informed.interchange'], - 'ilbm' => ['image/x-iff', 'image/x-ilbm'], - 'ime' => ['audio/imelody', 'audio/x-imelody', 'text/x-imelody'], - 'img' => ['application/x-raw-disk-image'], - 'img.xz' => ['application/x-raw-disk-image-xz-compressed'], - 'imp' => ['application/vnd.accpac.simply.imp'], - 'ims' => ['application/vnd.ms-ims'], - 'imy' => ['audio/imelody', 'audio/x-imelody', 'text/x-imelody'], - 'in' => ['text/plain'], - 'ink' => ['application/inkml+xml'], - 'inkml' => ['application/inkml+xml'], - 'ins' => ['application/x-tex', 'text/x-tex'], - 'install' => ['application/x-install-instructions'], - 'iota' => ['application/vnd.astraea-software.iota'], - 'ipfix' => ['application/ipfix'], - 'ipk' => ['application/vnd.shana.informed.package'], - 'iptables' => ['text/x-iptables'], - 'ipynb' => ['application/x-ipynb+json'], - 'irm' => ['application/vnd.ibm.rights-management'], - 'irp' => ['application/vnd.irepository.package+xml'], - 'iso' => ['application/x-cd-image', 'application/x-gamecube-iso-image', 'application/x-gamecube-rom', 'application/x-iso9660-image', 'application/x-saturn-rom', 'application/x-sega-cd-rom', 'application/x-wbfs', 'application/x-wia', 'application/x-wii-iso-image', 'application/x-wii-rom'], - 'iso9660' => ['application/x-cd-image', 'application/x-iso9660-image'], - 'it' => ['audio/x-it'], - 'it87' => ['application/x-it87'], - 'itp' => ['application/vnd.shana.informed.formtemplate'], - 'ivp' => ['application/vnd.immervision-ivp'], - 'ivu' => ['application/vnd.immervision-ivu'], - 'j2c' => ['image/x-jp2-codestream'], - 'j2k' => ['image/x-jp2-codestream'], - 'jad' => ['text/vnd.sun.j2me.app-descriptor'], - 'jam' => ['application/vnd.jam'], - 'jar' => ['application/x-java-archive', 'application/java-archive', 'application/x-jar'], - 'java' => ['text/x-java', 'text/x-java-source'], - 'jceks' => ['application/x-java-jce-keystore'], - 'jisp' => ['application/vnd.jisp'], - 'jks' => ['application/x-java-keystore'], - 'jlt' => ['application/vnd.hp-jlyt'], - 'jng' => ['image/x-jng'], - 'jnlp' => ['application/x-java-jnlp-file'], - 'joda' => ['application/vnd.joost.joda-archive'], - 'jp2' => ['image/jp2', 'image/jpeg2000', 'image/jpeg2000-image', 'image/x-jpeg2000-image'], - 'jpc' => ['image/x-jp2-codestream'], - 'jpe' => ['image/jpeg', 'image/pjpeg'], - 'jpeg' => ['image/jpeg', 'image/pjpeg'], - 'jpf' => ['image/jpx'], - 'jpg' => ['image/jpeg', 'image/pjpeg'], - 'jpg2' => ['image/jp2', 'image/jpeg2000', 'image/jpeg2000-image', 'image/x-jpeg2000-image'], - 'jpgm' => ['image/jpm', 'video/jpm'], - 'jpgv' => ['video/jpeg'], - 'jpm' => ['image/jpm', 'video/jpm'], - 'jpr' => ['application/x-jbuilder-project'], - 'jpx' => ['application/x-jbuilder-project', 'image/jpx'], - 'jrd' => ['application/jrd+json'], - 'js' => ['text/javascript', 'application/javascript', 'application/x-javascript'], - 'jsm' => ['application/javascript', 'application/x-javascript', 'text/javascript'], - 'json' => ['application/json'], - 'json-patch' => ['application/json-patch+json'], - 'jsonld' => ['application/ld+json'], - 'jsonml' => ['application/jsonml+json'], - 'k25' => ['image/x-kodak-k25'], - 'k7' => ['application/x-thomson-cassette'], - 'kar' => ['audio/midi', 'audio/x-midi'], - 'karbon' => ['application/vnd.kde.karbon', 'application/x-karbon'], - 'kdc' => ['image/x-kodak-kdc'], - 'kdelnk' => ['application/x-desktop', 'application/x-gnome-app-info'], - 'kexi' => ['application/x-kexiproject-sqlite', 'application/x-kexiproject-sqlite2', 'application/x-kexiproject-sqlite3', 'application/x-vnd.kde.kexi'], - 'kexic' => ['application/x-kexi-connectiondata'], - 'kexis' => ['application/x-kexiproject-shortcut'], - 'key' => ['application/vnd.apple.keynote', 'application/x-iwork-keynote-sffkey'], - 'kfo' => ['application/vnd.kde.kformula', 'application/x-kformula'], - 'kia' => ['application/vnd.kidspiration'], - 'kil' => ['application/x-killustrator'], - 'kino' => ['application/smil', 'application/smil+xml'], - 'kml' => ['application/vnd.google-earth.kml+xml'], - 'kmz' => ['application/vnd.google-earth.kmz'], - 'kne' => ['application/vnd.kinar'], - 'knp' => ['application/vnd.kinar'], - 'kon' => ['application/vnd.kde.kontour', 'application/x-kontour'], - 'kpm' => ['application/x-kpovmodeler'], - 'kpr' => ['application/vnd.kde.kpresenter', 'application/x-kpresenter'], - 'kpt' => ['application/vnd.kde.kpresenter', 'application/x-kpresenter'], - 'kpxx' => ['application/vnd.ds-keypoint'], - 'kra' => ['application/x-krita'], - 'ks' => ['application/x-java-keystore'], - 'ksp' => ['application/vnd.kde.kspread', 'application/x-kspread'], - 'ktr' => ['application/vnd.kahootz'], - 'ktx' => ['image/ktx'], - 'ktz' => ['application/vnd.kahootz'], - 'kud' => ['application/x-kugar'], - 'kwd' => ['application/vnd.kde.kword', 'application/x-kword'], - 'kwt' => ['application/vnd.kde.kword', 'application/x-kword'], - 'la' => ['application/x-shared-library-la'], - 'lasxml' => ['application/vnd.las.las+xml'], - 'latex' => ['application/x-latex', 'application/x-tex', 'text/x-tex'], - 'lbd' => ['application/vnd.llamagraphics.life-balance.desktop'], - 'lbe' => ['application/vnd.llamagraphics.life-balance.exchange+xml'], - 'lbm' => ['image/x-iff', 'image/x-ilbm'], - 'ldif' => ['text/x-ldif'], - 'les' => ['application/vnd.hhe.lesson-player'], - 'lha' => ['application/x-lha', 'application/x-lzh-compressed'], - 'lhs' => ['text/x-literate-haskell'], - 'lhz' => ['application/x-lhz'], - 'link66' => ['application/vnd.route66.link66+xml'], - 'list' => ['text/plain'], - 'list3820' => ['application/vnd.ibm.modcap'], - 'listafp' => ['application/vnd.ibm.modcap'], - 'lnk' => ['application/x-ms-shortcut'], - 'lnx' => ['application/x-atari-lynx-rom'], - 'loas' => ['audio/usac'], - 'log' => ['text/plain', 'text/x-log'], - 'lostxml' => ['application/lost+xml'], - 'lrf' => ['application/octet-stream'], - 'lrm' => ['application/vnd.ms-lrm'], - 'lrv' => ['video/mp4', 'video/mp4v-es', 'video/x-m4v'], - 'lrz' => ['application/x-lrzip'], - 'ltf' => ['application/vnd.frogans.ltf'], - 'ltx' => ['application/x-tex', 'text/x-tex'], - 'lua' => ['text/x-lua'], - 'lvp' => ['audio/vnd.lucent.voice'], - 'lwo' => ['image/x-lwo'], - 'lwob' => ['image/x-lwo'], - 'lwp' => ['application/vnd.lotus-wordpro'], - 'lws' => ['image/x-lws'], - 'ly' => ['text/x-lilypond'], - 'lyx' => ['application/x-lyx', 'text/x-lyx'], - 'lz' => ['application/x-lzip'], - 'lz4' => ['application/x-lz4'], - 'lzh' => ['application/x-lha', 'application/x-lzh-compressed'], - 'lzma' => ['application/x-lzma'], - 'lzo' => ['application/x-lzop'], - 'm' => ['text/x-matlab', 'text/x-objcsrc', 'text/x-octave'], - 'm13' => ['application/x-msmediaview'], - 'm14' => ['application/x-msmediaview'], - 'm15' => ['audio/x-mod'], - 'm1u' => ['video/vnd.mpegurl', 'video/x-mpegurl'], - 'm1v' => ['video/mpeg'], - 'm21' => ['application/mp21'], - 'm2a' => ['audio/mpeg'], - 'm2t' => ['video/mp2t'], - 'm2ts' => ['video/mp2t'], - 'm2v' => ['video/mpeg'], - 'm3a' => ['audio/mpeg'], - 'm3u' => ['audio/x-mpegurl', 'application/m3u', 'application/vnd.apple.mpegurl', 'audio/m3u', 'audio/mpegurl', 'audio/x-m3u', 'audio/x-mp3-playlist'], - 'm3u8' => ['application/m3u', 'application/vnd.apple.mpegurl', 'audio/m3u', 'audio/mpegurl', 'audio/x-m3u', 'audio/x-mp3-playlist', 'audio/x-mpegurl'], - 'm4' => ['application/x-m4'], - 'm4a' => ['audio/mp4', 'audio/m4a', 'audio/x-m4a'], - 'm4b' => ['audio/x-m4b'], - 'm4r' => ['audio/x-m4r'], - 'm4u' => ['video/vnd.mpegurl', 'video/x-mpegurl'], - 'm4v' => ['video/mp4', 'video/mp4v-es', 'video/x-m4v'], - 'm7' => ['application/x-thomson-cartridge-memo7'], - 'ma' => ['application/mathematica'], - 'mab' => ['application/x-markaby'], - 'mads' => ['application/mads+xml'], - 'mag' => ['application/vnd.ecowin.chart'], - 'mak' => ['text/x-makefile'], - 'maker' => ['application/vnd.framemaker'], - 'man' => ['application/x-troff-man', 'text/troff'], - 'manifest' => ['text/cache-manifest'], - 'mar' => ['application/octet-stream'], - 'markdown' => ['text/markdown', 'text/x-markdown'], - 'mathml' => ['application/mathml+xml'], - 'mb' => ['application/mathematica'], - 'mbk' => ['application/vnd.mobius.mbk'], - 'mbox' => ['application/mbox'], - 'mc1' => ['application/vnd.medcalcdata'], - 'mcd' => ['application/vnd.mcd'], - 'mcurl' => ['text/vnd.curl.mcurl'], - 'md' => ['text/markdown', 'text/x-markdown'], - 'mdb' => ['application/x-msaccess', 'application/mdb', 'application/msaccess', 'application/vnd.ms-access', 'application/vnd.msaccess', 'application/x-mdb', 'zz-application/zz-winassoc-mdb'], - 'mdi' => ['image/vnd.ms-modi'], - 'mdx' => ['application/x-genesis-32x-rom'], - 'me' => ['text/troff', 'text/x-troff-me'], - 'med' => ['audio/x-mod'], - 'mesh' => ['model/mesh'], - 'meta4' => ['application/metalink4+xml'], - 'metalink' => ['application/metalink+xml'], - 'mets' => ['application/mets+xml'], - 'mfm' => ['application/vnd.mfmp'], - 'mft' => ['application/rpki-manifest'], - 'mgp' => ['application/vnd.osgeo.mapguide.package', 'application/x-magicpoint'], - 'mgz' => ['application/vnd.proteus.magazine'], - 'mht' => ['application/x-mimearchive'], - 'mhtml' => ['application/x-mimearchive'], - 'mid' => ['audio/midi', 'audio/x-midi'], - 'midi' => ['audio/midi', 'audio/x-midi'], - 'mie' => ['application/x-mie'], - 'mif' => ['application/vnd.mif', 'application/x-mif'], - 'mime' => ['message/rfc822'], - 'minipsf' => ['audio/x-minipsf'], - 'mj2' => ['video/mj2'], - 'mjp2' => ['video/mj2'], - 'mjpeg' => ['video/x-mjpeg'], - 'mjpg' => ['video/x-mjpeg'], - 'mjs' => ['application/javascript', 'application/x-javascript', 'text/javascript'], - 'mk' => ['text/x-makefile'], - 'mk3d' => ['video/x-matroska', 'video/x-matroska-3d'], - 'mka' => ['audio/x-matroska'], - 'mkd' => ['text/markdown', 'text/x-markdown'], - 'mks' => ['video/x-matroska'], - 'mkv' => ['video/x-matroska'], - 'ml' => ['text/x-ocaml'], - 'mli' => ['text/x-ocaml'], - 'mlp' => ['application/vnd.dolby.mlp'], - 'mm' => ['text/x-troff-mm'], - 'mmd' => ['application/vnd.chipnuts.karaoke-mmd'], - 'mmf' => ['application/vnd.smaf', 'application/x-smaf'], - 'mml' => ['application/mathml+xml', 'text/mathml'], - 'mmr' => ['image/vnd.fujixerox.edmics-mmr'], - 'mng' => ['video/x-mng'], - 'mny' => ['application/x-msmoney'], - 'mo' => ['application/x-gettext-translation', 'text/x-modelica'], - 'mo3' => ['audio/x-mo3'], - 'mobi' => ['application/x-mobipocket-ebook'], - 'moc' => ['text/x-moc'], - 'mod' => ['audio/x-mod'], - 'mods' => ['application/mods+xml'], - 'mof' => ['text/x-mof'], - 'moov' => ['video/quicktime'], - 'mount' => ['text/x-systemd-unit'], - 'mov' => ['video/quicktime'], - 'movie' => ['video/x-sgi-movie'], - 'mp+' => ['audio/x-musepack'], - 'mp2' => ['audio/mp2', 'audio/mpeg', 'audio/x-mp2', 'video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], - 'mp21' => ['application/mp21'], - 'mp2a' => ['audio/mpeg'], - 'mp3' => ['audio/mpeg', 'audio/mp3', 'audio/x-mp3', 'audio/x-mpeg', 'audio/x-mpg'], - 'mp4' => ['video/mp4', 'video/mp4v-es', 'video/x-m4v'], - 'mp4a' => ['audio/mp4'], - 'mp4s' => ['application/mp4'], - 'mp4v' => ['video/mp4'], - 'mpc' => ['application/vnd.mophun.certificate', 'audio/x-musepack'], - 'mpe' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], - 'mpeg' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], - 'mpg' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], - 'mpg4' => ['video/mp4'], - 'mpga' => ['audio/mp3', 'audio/mpeg', 'audio/x-mp3', 'audio/x-mpeg', 'audio/x-mpg'], - 'mpkg' => ['application/vnd.apple.installer+xml'], - 'mpl' => ['video/mp2t'], - 'mpls' => ['video/mp2t'], - 'mpm' => ['application/vnd.blueice.multipass'], - 'mpn' => ['application/vnd.mophun.application'], - 'mpp' => ['application/vnd.ms-project', 'audio/x-musepack'], - 'mpt' => ['application/vnd.ms-project'], - 'mpy' => ['application/vnd.ibm.minipay'], - 'mqy' => ['application/vnd.mobius.mqy'], - 'mrc' => ['application/marc'], - 'mrcx' => ['application/marcxml+xml'], - 'mrl' => ['text/x-mrml'], - 'mrml' => ['text/x-mrml'], - 'mrw' => ['image/x-minolta-mrw'], - 'ms' => ['text/troff', 'text/x-troff-ms'], - 'mscml' => ['application/mediaservercontrol+xml'], - 'mseed' => ['application/vnd.fdsn.mseed'], - 'mseq' => ['application/vnd.mseq'], - 'msf' => ['application/vnd.epson.msf'], - 'msh' => ['model/mesh'], - 'msi' => ['application/x-msdownload', 'application/x-msi'], - 'msl' => ['application/vnd.mobius.msl'], - 'msod' => ['image/x-msod'], - 'msty' => ['application/vnd.muvee.style'], - 'msx' => ['application/x-msx-rom'], - 'mtm' => ['audio/x-mod'], - 'mts' => ['model/vnd.mts', 'video/mp2t'], - 'mup' => ['text/x-mup'], - 'mus' => ['application/vnd.musician'], - 'musicxml' => ['application/vnd.recordare.musicxml+xml'], - 'mvb' => ['application/x-msmediaview'], - 'mwf' => ['application/vnd.mfer'], - 'mxf' => ['application/mxf'], - 'mxl' => ['application/vnd.recordare.musicxml'], - 'mxml' => ['application/xv+xml'], - 'mxs' => ['application/vnd.triscape.mxs'], - 'mxu' => ['video/vnd.mpegurl', 'video/x-mpegurl'], - 'n-gage' => ['application/vnd.nokia.n-gage.symbian.install'], - 'n3' => ['text/n3'], - 'n64' => ['application/x-n64-rom'], - 'nb' => ['application/mathematica', 'application/x-mathematica'], - 'nbp' => ['application/vnd.wolfram.player'], - 'nc' => ['application/x-netcdf'], - 'ncx' => ['application/x-dtbncx+xml'], - 'nds' => ['application/x-nintendo-ds-rom'], - 'nef' => ['image/x-nikon-nef'], - 'nes' => ['application/x-nes-rom'], - 'nez' => ['application/x-nes-rom'], - 'nfo' => ['text/x-nfo'], - 'ngc' => ['application/x-neo-geo-pocket-color-rom'], - 'ngdat' => ['application/vnd.nokia.n-gage.data'], - 'ngp' => ['application/x-neo-geo-pocket-rom'], - 'nitf' => ['application/vnd.nitf'], - 'nlu' => ['application/vnd.neurolanguage.nlu'], - 'nml' => ['application/vnd.enliven'], - 'nnd' => ['application/vnd.noblenet-directory'], - 'nns' => ['application/vnd.noblenet-sealer'], - 'nnw' => ['application/vnd.noblenet-web'], - 'not' => ['text/x-mup'], - 'npx' => ['image/vnd.net-fpx'], - 'nsc' => ['application/x-conference', 'application/x-netshow-channel'], - 'nsf' => ['application/vnd.lotus-notes'], - 'nsv' => ['video/x-nsv'], - 'ntf' => ['application/vnd.nitf'], - 'nzb' => ['application/x-nzb'], - 'o' => ['application/x-object'], - 'oa2' => ['application/vnd.fujitsu.oasys2'], - 'oa3' => ['application/vnd.fujitsu.oasys3'], - 'oas' => ['application/vnd.fujitsu.oasys'], - 'obd' => ['application/x-msbinder'], - 'obj' => ['application/x-tgif'], - 'ocl' => ['text/x-ocl'], - 'oda' => ['application/oda'], - 'odb' => ['application/vnd.oasis.opendocument.database', 'application/vnd.sun.xml.base'], - 'odc' => ['application/vnd.oasis.opendocument.chart'], - 'odf' => ['application/vnd.oasis.opendocument.formula'], - 'odft' => ['application/vnd.oasis.opendocument.formula-template'], - 'odg' => ['application/vnd.oasis.opendocument.graphics'], - 'odi' => ['application/vnd.oasis.opendocument.image'], - 'odm' => ['application/vnd.oasis.opendocument.text-master'], - 'odp' => ['application/vnd.oasis.opendocument.presentation'], - 'ods' => ['application/vnd.oasis.opendocument.spreadsheet'], - 'odt' => ['application/vnd.oasis.opendocument.text'], - 'oga' => ['audio/ogg', 'audio/vorbis', 'audio/x-flac+ogg', 'audio/x-ogg', 'audio/x-oggflac', 'audio/x-speex+ogg', 'audio/x-vorbis', 'audio/x-vorbis+ogg'], - 'ogg' => ['audio/ogg', 'audio/vorbis', 'audio/x-flac+ogg', 'audio/x-ogg', 'audio/x-oggflac', 'audio/x-speex+ogg', 'audio/x-vorbis', 'audio/x-vorbis+ogg', 'video/ogg', 'video/x-ogg', 'video/x-theora', 'video/x-theora+ogg'], - 'ogm' => ['video/x-ogm', 'video/x-ogm+ogg'], - 'ogv' => ['video/ogg', 'video/x-ogg'], - 'ogx' => ['application/ogg', 'application/x-ogg'], - 'old' => ['application/x-trash'], - 'oleo' => ['application/x-oleo'], - 'omdoc' => ['application/omdoc+xml'], - 'onepkg' => ['application/onenote'], - 'onetmp' => ['application/onenote'], - 'onetoc' => ['application/onenote'], - 'onetoc2' => ['application/onenote'], - 'ooc' => ['text/x-ooc'], - 'opf' => ['application/oebps-package+xml'], - 'opml' => ['text/x-opml', 'text/x-opml+xml'], - 'oprc' => ['application/vnd.palm', 'application/x-palm-database'], - 'opus' => ['audio/ogg', 'audio/x-ogg', 'audio/x-opus+ogg'], - 'ora' => ['image/openraster'], - 'orf' => ['image/x-olympus-orf'], - 'org' => ['application/vnd.lotus-organizer'], - 'osf' => ['application/vnd.yamaha.openscoreformat'], - 'osfpvg' => ['application/vnd.yamaha.openscoreformat.osfpvg+xml'], - 'otc' => ['application/vnd.oasis.opendocument.chart-template'], - 'otf' => ['application/vnd.oasis.opendocument.formula-template', 'application/x-font-otf', 'font/otf'], - 'otg' => ['application/vnd.oasis.opendocument.graphics-template'], - 'oth' => ['application/vnd.oasis.opendocument.text-web'], - 'oti' => ['application/vnd.oasis.opendocument.image-template'], - 'otp' => ['application/vnd.oasis.opendocument.presentation-template'], - 'ots' => ['application/vnd.oasis.opendocument.spreadsheet-template'], - 'ott' => ['application/vnd.oasis.opendocument.text-template'], - 'owl' => ['application/rdf+xml', 'text/rdf'], - 'owx' => ['application/owl+xml'], - 'oxps' => ['application/oxps', 'application/vnd.ms-xpsdocument', 'application/xps'], - 'oxt' => ['application/vnd.openofficeorg.extension'], - 'p' => ['text/x-pascal'], - 'p10' => ['application/pkcs10'], - 'p12' => ['application/pkcs12', 'application/x-pkcs12'], - 'p65' => ['application/x-pagemaker'], - 'p7b' => ['application/x-pkcs7-certificates'], - 'p7c' => ['application/pkcs7-mime'], - 'p7m' => ['application/pkcs7-mime'], - 'p7r' => ['application/x-pkcs7-certreqresp'], - 'p7s' => ['application/pkcs7-signature'], - 'p8' => ['application/pkcs8'], - 'p8e' => ['application/pkcs8-encrypted'], - 'pack' => ['application/x-java-pack200'], - 'pak' => ['application/x-pak'], - 'par2' => ['application/x-par2'], - 'part' => ['application/x-partial-download'], - 'pas' => ['text/x-pascal'], - 'pat' => ['image/x-gimp-pat'], - 'patch' => ['text/x-diff', 'text/x-patch'], - 'path' => ['text/x-systemd-unit'], - 'paw' => ['application/vnd.pawaafile'], - 'pbd' => ['application/vnd.powerbuilder6'], - 'pbm' => ['image/x-portable-bitmap'], - 'pcap' => ['application/pcap', 'application/vnd.tcpdump.pcap', 'application/x-pcap'], - 'pcd' => ['image/x-photo-cd'], - 'pce' => ['application/x-pc-engine-rom'], - 'pcf' => ['application/x-cisco-vpn-settings', 'application/x-font-pcf'], - 'pcf.Z' => ['application/x-font-pcf'], - 'pcf.gz' => ['application/x-font-pcf'], - 'pcl' => ['application/vnd.hp-pcl'], - 'pclxl' => ['application/vnd.hp-pclxl'], - 'pct' => ['image/x-pict'], - 'pcurl' => ['application/vnd.curl.pcurl'], - 'pcx' => ['image/vnd.zbrush.pcx', 'image/x-pcx'], - 'pdb' => ['application/vnd.palm', 'application/x-aportisdoc', 'application/x-palm-database'], - 'pdc' => ['application/x-aportisdoc'], - 'pdf' => ['application/pdf', 'application/acrobat', 'application/nappdf', 'application/x-pdf', 'image/pdf'], - 'pdf.bz2' => ['application/x-bzpdf'], - 'pdf.gz' => ['application/x-gzpdf'], - 'pdf.lz' => ['application/x-lzpdf'], - 'pdf.xz' => ['application/x-xzpdf'], - 'pef' => ['image/x-pentax-pef'], - 'pem' => ['application/x-x509-ca-cert'], - 'perl' => ['application/x-perl', 'text/x-perl'], - 'pfa' => ['application/x-font-type1'], - 'pfb' => ['application/x-font-type1'], - 'pfm' => ['application/x-font-type1'], - 'pfr' => ['application/font-tdpfr'], - 'pfx' => ['application/pkcs12', 'application/x-pkcs12'], - 'pgm' => ['image/x-portable-graymap'], - 'pgn' => ['application/vnd.chess-pgn', 'application/x-chess-pgn'], - 'pgp' => ['application/pgp', 'application/pgp-encrypted', 'application/pgp-keys', 'application/pgp-signature'], - 'php' => ['application/x-php'], - 'php3' => ['application/x-php'], - 'php4' => ['application/x-php'], - 'php5' => ['application/x-php'], - 'phps' => ['application/x-php'], - 'pic' => ['image/x-pict'], - 'pict' => ['image/x-pict'], - 'pict1' => ['image/x-pict'], - 'pict2' => ['image/x-pict'], - 'pk' => ['application/x-tex-pk'], - 'pkg' => ['application/octet-stream', 'application/x-xar'], - 'pki' => ['application/pkixcmp'], - 'pkipath' => ['application/pkix-pkipath'], - 'pkr' => ['application/pgp-keys'], - 'pl' => ['application/x-perl', 'text/x-perl'], - 'pla' => ['audio/x-iriver-pla'], - 'plb' => ['application/vnd.3gpp.pic-bw-large'], - 'plc' => ['application/vnd.mobius.plc'], - 'plf' => ['application/vnd.pocketlearn'], - 'pln' => ['application/x-planperfect'], - 'pls' => ['application/pls', 'application/pls+xml', 'audio/scpls', 'audio/x-scpls'], - 'pm' => ['application/x-pagemaker', 'application/x-perl', 'text/x-perl'], - 'pm6' => ['application/x-pagemaker'], - 'pmd' => ['application/x-pagemaker'], - 'pml' => ['application/vnd.ctc-posml'], - 'png' => ['image/png'], - 'pnm' => ['image/x-portable-anymap'], - 'pntg' => ['image/x-macpaint'], - 'po' => ['application/x-gettext', 'text/x-gettext-translation', 'text/x-po'], - 'pod' => ['application/x-perl', 'text/x-perl'], - 'por' => ['application/x-spss-por'], - 'portpkg' => ['application/vnd.macports.portpkg'], - 'pot' => ['application/mspowerpoint', 'application/powerpoint', 'application/vnd.ms-powerpoint', 'application/x-mspowerpoint', 'text/x-gettext-translation-template', 'text/x-pot'], - 'potm' => ['application/vnd.ms-powerpoint.template.macroenabled.12'], - 'potx' => ['application/vnd.openxmlformats-officedocument.presentationml.template'], - 'ppam' => ['application/vnd.ms-powerpoint.addin.macroenabled.12'], - 'ppd' => ['application/vnd.cups-ppd'], - 'ppm' => ['image/x-portable-pixmap'], - 'pps' => ['application/mspowerpoint', 'application/powerpoint', 'application/vnd.ms-powerpoint', 'application/x-mspowerpoint'], - 'ppsm' => ['application/vnd.ms-powerpoint.slideshow.macroenabled.12'], - 'ppsx' => ['application/vnd.openxmlformats-officedocument.presentationml.slideshow'], - 'ppt' => ['application/vnd.ms-powerpoint', 'application/mspowerpoint', 'application/powerpoint', 'application/x-mspowerpoint'], - 'pptm' => ['application/vnd.ms-powerpoint.presentation.macroenabled.12'], - 'pptx' => ['application/vnd.openxmlformats-officedocument.presentationml.presentation'], - 'ppz' => ['application/mspowerpoint', 'application/powerpoint', 'application/vnd.ms-powerpoint', 'application/x-mspowerpoint'], - 'pqa' => ['application/vnd.palm', 'application/x-palm-database'], - 'prc' => ['application/vnd.palm', 'application/x-mobipocket-ebook', 'application/x-palm-database'], - 'pre' => ['application/vnd.lotus-freelance'], - 'prf' => ['application/pics-rules'], - 'ps' => ['application/postscript'], - 'ps.bz2' => ['application/x-bzpostscript'], - 'ps.gz' => ['application/x-gzpostscript'], - 'psb' => ['application/vnd.3gpp.pic-bw-small'], - 'psd' => ['application/photoshop', 'application/x-photoshop', 'image/photoshop', 'image/psd', 'image/vnd.adobe.photoshop', 'image/x-photoshop', 'image/x-psd'], - 'psf' => ['application/x-font-linux-psf', 'audio/x-psf'], - 'psf.gz' => ['application/x-gz-font-linux-psf'], - 'psflib' => ['audio/x-psflib'], - 'psid' => ['audio/prs.sid'], - 'pskcxml' => ['application/pskc+xml'], - 'psw' => ['application/x-pocket-word'], - 'ptid' => ['application/vnd.pvi.ptid1'], - 'pub' => ['application/vnd.ms-publisher', 'application/x-mspublisher'], - 'pvb' => ['application/vnd.3gpp.pic-bw-var'], - 'pw' => ['application/x-pw'], - 'pwn' => ['application/vnd.3m.post-it-notes'], - 'py' => ['text/x-python', 'text/x-python3'], - 'py3' => ['text/x-python3'], - 'py3x' => ['text/x-python3'], - 'pya' => ['audio/vnd.ms-playready.media.pya'], - 'pyc' => ['application/x-python-bytecode'], - 'pyo' => ['application/x-python-bytecode'], - 'pyv' => ['video/vnd.ms-playready.media.pyv'], - 'pyx' => ['text/x-python'], - 'qam' => ['application/vnd.epson.quickanime'], - 'qbo' => ['application/vnd.intu.qbo'], - 'qd' => ['application/x-fd-file', 'application/x-raw-floppy-disk-image'], - 'qfx' => ['application/vnd.intu.qfx'], - 'qif' => ['application/x-qw', 'image/x-quicktime'], - 'qml' => ['text/x-qml'], - 'qmlproject' => ['text/x-qml'], - 'qmltypes' => ['text/x-qml'], - 'qp' => ['application/x-qpress'], - 'qps' => ['application/vnd.publishare-delta-tree'], - 'qt' => ['video/quicktime'], - 'qti' => ['application/x-qtiplot'], - 'qti.gz' => ['application/x-qtiplot'], - 'qtif' => ['image/x-quicktime'], - 'qtl' => ['application/x-quicktime-media-link', 'application/x-quicktimeplayer'], - 'qtvr' => ['video/quicktime'], - 'qwd' => ['application/vnd.quark.quarkxpress'], - 'qwt' => ['application/vnd.quark.quarkxpress'], - 'qxb' => ['application/vnd.quark.quarkxpress'], - 'qxd' => ['application/vnd.quark.quarkxpress'], - 'qxl' => ['application/vnd.quark.quarkxpress'], - 'qxt' => ['application/vnd.quark.quarkxpress'], - 'ra' => ['audio/vnd.m-realaudio', 'audio/vnd.rn-realaudio', 'audio/x-pn-realaudio'], - 'raf' => ['image/x-fuji-raf'], - 'ram' => ['application/ram', 'audio/x-pn-realaudio'], - 'raml' => ['application/raml+yaml'], - 'rar' => ['application/x-rar-compressed', 'application/vnd.rar', 'application/x-rar'], - 'ras' => ['image/x-cmu-raster'], - 'raw' => ['image/x-panasonic-raw', 'image/x-panasonic-rw'], - 'raw-disk-image' => ['application/x-raw-disk-image'], - 'raw-disk-image.xz' => ['application/x-raw-disk-image-xz-compressed'], - 'rax' => ['audio/vnd.m-realaudio', 'audio/vnd.rn-realaudio', 'audio/x-pn-realaudio'], - 'rb' => ['application/x-ruby'], - 'rcprofile' => ['application/vnd.ipunplugged.rcprofile'], - 'rdf' => ['application/rdf+xml', 'text/rdf'], - 'rdfs' => ['application/rdf+xml', 'text/rdf'], - 'rdz' => ['application/vnd.data-vision.rdz'], - 'reg' => ['text/x-ms-regedit'], - 'rej' => ['application/x-reject', 'text/x-reject'], - 'rep' => ['application/vnd.businessobjects'], - 'res' => ['application/x-dtbresource+xml'], - 'rgb' => ['image/x-rgb'], - 'rif' => ['application/reginfo+xml'], - 'rip' => ['audio/vnd.rip'], - 'ris' => ['application/x-research-info-systems'], - 'rl' => ['application/resource-lists+xml'], - 'rlc' => ['image/vnd.fujixerox.edmics-rlc'], - 'rld' => ['application/resource-lists-diff+xml'], - 'rle' => ['image/rle'], - 'rm' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], - 'rmi' => ['audio/midi'], - 'rmj' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], - 'rmm' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], - 'rmp' => ['audio/x-pn-realaudio-plugin'], - 'rms' => ['application/vnd.jcp.javame.midlet-rms', 'application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], - 'rmvb' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], - 'rmx' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], - 'rnc' => ['application/relax-ng-compact-syntax', 'application/x-rnc'], - 'rng' => ['application/xml', 'text/xml'], - 'roa' => ['application/rpki-roa'], - 'roff' => ['application/x-troff', 'text/troff', 'text/x-troff'], - 'rp' => ['image/vnd.rn-realpix'], - 'rp9' => ['application/vnd.cloanto.rp9'], - 'rpm' => ['application/x-redhat-package-manager', 'application/x-rpm'], - 'rpss' => ['application/vnd.nokia.radio-presets'], - 'rpst' => ['application/vnd.nokia.radio-preset'], - 'rq' => ['application/sparql-query'], - 'rs' => ['application/rls-services+xml', 'text/rust'], - 'rsd' => ['application/rsd+xml'], - 'rss' => ['application/rss+xml', 'text/rss'], - 'rt' => ['text/vnd.rn-realtext'], - 'rtf' => ['application/rtf', 'text/rtf'], - 'rtx' => ['text/richtext'], - 'rv' => ['video/vnd.rn-realvideo', 'video/x-real-video'], - 'rvx' => ['video/vnd.rn-realvideo', 'video/x-real-video'], - 'rw2' => ['image/x-panasonic-raw2', 'image/x-panasonic-rw2'], - 's' => ['text/x-asm'], - 's3m' => ['audio/s3m', 'audio/x-s3m'], - 'saf' => ['application/vnd.yamaha.smaf-audio'], - 'sam' => ['application/x-amipro'], - 'sami' => ['application/x-sami'], - 'sap' => ['application/x-sap-file', 'application/x-thomson-sap-image'], - 'sass' => ['text/x-sass'], - 'sav' => ['application/x-spss-sav', 'application/x-spss-savefile'], - 'sbml' => ['application/sbml+xml'], - 'sc' => ['application/vnd.ibm.secure-container'], - 'scala' => ['text/x-scala'], - 'scd' => ['application/x-msschedule'], - 'scm' => ['application/vnd.lotus-screencam', 'text/x-scheme'], - 'scope' => ['text/x-systemd-unit'], - 'scq' => ['application/scvp-cv-request'], - 'scs' => ['application/scvp-cv-response'], - 'scss' => ['text/x-scss'], - 'scurl' => ['text/vnd.curl.scurl'], - 'sda' => ['application/vnd.stardivision.draw'], - 'sdc' => ['application/vnd.stardivision.calc'], - 'sdd' => ['application/vnd.stardivision.impress'], - 'sdkd' => ['application/vnd.solent.sdkm+xml'], - 'sdkm' => ['application/vnd.solent.sdkm+xml'], - 'sdp' => ['application/sdp', 'application/vnd.sdp', 'application/vnd.stardivision.impress', 'application/x-sdp'], - 'sds' => ['application/vnd.stardivision.chart'], - 'sdw' => ['application/vnd.stardivision.writer', 'application/vnd.stardivision.writer-global'], - 'see' => ['application/vnd.seemail'], - 'seed' => ['application/vnd.fdsn.seed'], - 'sema' => ['application/vnd.sema'], - 'semd' => ['application/vnd.semd'], - 'semf' => ['application/vnd.semf'], - 'ser' => ['application/java-serialized-object'], - 'service' => ['text/x-dbus-service', 'text/x-systemd-unit'], - 'setpay' => ['application/set-payment-initiation'], - 'setreg' => ['application/set-registration-initiation'], - 'sfc' => ['application/vnd.nintendo.snes.rom', 'application/x-snes-rom'], - 'sfd-hdstx' => ['application/vnd.hydrostatix.sof-data'], - 'sfs' => ['application/vnd.spotfire.sfs'], - 'sfv' => ['text/x-sfv'], - 'sg' => ['application/x-sg1000-rom'], - 'sgb' => ['application/x-gameboy-rom'], - 'sgf' => ['application/x-go-sgf'], - 'sgi' => ['image/sgi', 'image/x-sgi'], - 'sgl' => ['application/vnd.stardivision.writer', 'application/vnd.stardivision.writer-global'], - 'sgm' => ['text/sgml'], - 'sgml' => ['text/sgml'], - 'sh' => ['application/x-sh', 'application/x-shellscript', 'text/x-sh'], - 'shape' => ['application/x-dia-shape'], - 'shar' => ['application/x-shar'], - 'shf' => ['application/shf+xml'], - 'shn' => ['application/x-shorten', 'audio/x-shorten'], - 'siag' => ['application/x-siag'], - 'sid' => ['audio/prs.sid', 'image/x-mrsid-image'], - 'sig' => ['application/pgp-signature'], - 'sik' => ['application/x-trash'], - 'sil' => ['audio/silk'], - 'silo' => ['model/mesh'], - 'sis' => ['application/vnd.symbian.install'], - 'sisx' => ['application/vnd.symbian.install', 'x-epoc/x-sisx-app'], - 'sit' => ['application/x-stuffit', 'application/stuffit', 'application/x-sit'], - 'sitx' => ['application/x-stuffitx'], - 'siv' => ['application/sieve'], - 'sk' => ['image/x-skencil'], - 'sk1' => ['image/x-skencil'], - 'skd' => ['application/vnd.koan'], - 'skm' => ['application/vnd.koan'], - 'skp' => ['application/vnd.koan'], - 'skr' => ['application/pgp-keys'], - 'skt' => ['application/vnd.koan'], - 'sldm' => ['application/vnd.ms-powerpoint.slide.macroenabled.12'], - 'sldx' => ['application/vnd.openxmlformats-officedocument.presentationml.slide'], - 'slice' => ['text/x-systemd-unit'], - 'slk' => ['text/spreadsheet'], - 'slt' => ['application/vnd.epson.salt'], - 'sm' => ['application/vnd.stepmania.stepchart'], - 'smaf' => ['application/vnd.smaf', 'application/x-smaf'], - 'smc' => ['application/vnd.nintendo.snes.rom', 'application/x-snes-rom'], - 'smd' => ['application/vnd.stardivision.mail', 'application/x-genesis-rom'], - 'smf' => ['application/vnd.stardivision.math'], - 'smi' => ['application/smil', 'application/smil+xml', 'application/x-sami'], - 'smil' => ['application/smil', 'application/smil+xml'], - 'sml' => ['application/smil', 'application/smil+xml'], - 'sms' => ['application/x-sms-rom'], - 'smv' => ['video/x-smv'], - 'smzip' => ['application/vnd.stepmania.package'], - 'snap' => ['application/vnd.snap'], - 'snd' => ['audio/basic'], - 'snf' => ['application/x-font-snf'], - 'so' => ['application/octet-stream', 'application/x-sharedlib'], - 'socket' => ['text/x-systemd-unit'], - 'spc' => ['application/x-pkcs7-certificates'], - 'spd' => ['application/x-font-speedo'], - 'spec' => ['text/x-rpm-spec'], - 'spf' => ['application/vnd.yamaha.smaf-phrase'], - 'spl' => ['application/futuresplash', 'application/vnd.adobe.flash.movie', 'application/x-futuresplash', 'application/x-shockwave-flash'], - 'spm' => ['application/x-source-rpm'], - 'spot' => ['text/vnd.in3d.spot'], - 'spp' => ['application/scvp-vp-response'], - 'spq' => ['application/scvp-vp-request'], - 'spx' => ['audio/ogg', 'audio/x-speex'], - 'sql' => ['application/sql', 'application/x-sql', 'text/x-sql'], - 'sqlite2' => ['application/x-sqlite2'], - 'sqlite3' => ['application/vnd.sqlite3', 'application/x-sqlite3'], - 'sqsh' => ['application/vnd.squashfs'], - 'sr2' => ['image/x-sony-sr2'], - 'src' => ['application/x-wais-source'], - 'src.rpm' => ['application/x-source-rpm'], - 'srf' => ['image/x-sony-srf'], - 'srt' => ['application/x-srt', 'application/x-subrip'], - 'sru' => ['application/sru+xml'], - 'srx' => ['application/sparql-results+xml'], - 'ss' => ['text/x-scheme'], - 'ssa' => ['text/x-ssa'], - 'ssdl' => ['application/ssdl+xml'], - 'sse' => ['application/vnd.kodak-descriptor'], - 'ssf' => ['application/vnd.epson.ssf'], - 'ssml' => ['application/ssml+xml'], - 'st' => ['application/vnd.sailingtracker.track'], - 'stc' => ['application/vnd.sun.xml.calc.template'], - 'std' => ['application/vnd.sun.xml.draw.template'], - 'stf' => ['application/vnd.wt.stf'], - 'sti' => ['application/vnd.sun.xml.impress.template'], - 'stk' => ['application/hyperstudio'], - 'stl' => ['application/vnd.ms-pki.stl', 'model/stl', 'model/x.stl-ascii', 'model/x.stl-binary'], - 'stm' => ['audio/x-stm'], - 'str' => ['application/vnd.pg.format'], - 'stw' => ['application/vnd.sun.xml.writer.template'], - 'sty' => ['application/x-tex', 'text/x-tex'], - 'sub' => ['image/vnd.dvb.subtitle', 'text/vnd.dvb.subtitle', 'text/x-microdvd', 'text/x-mpsub', 'text/x-subviewer'], - 'sun' => ['image/x-sun-raster'], - 'sus' => ['application/vnd.sus-calendar'], - 'susp' => ['application/vnd.sus-calendar'], - 'sv' => ['text/x-svsrc'], - 'sv4cpio' => ['application/x-sv4cpio'], - 'sv4crc' => ['application/x-sv4crc'], - 'svc' => ['application/vnd.dvb.service'], - 'svd' => ['application/vnd.svd'], - 'svg' => ['image/svg+xml', 'image/svg'], - 'svgz' => ['image/svg+xml', 'image/svg+xml-compressed'], - 'svh' => ['text/x-svhdr'], - 'swa' => ['application/x-director'], - 'swap' => ['text/x-systemd-unit'], - 'swf' => ['application/futuresplash', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash'], - 'swi' => ['application/vnd.aristanetworks.swi'], - 'swm' => ['application/x-ms-wim'], - 'sxc' => ['application/vnd.sun.xml.calc'], - 'sxd' => ['application/vnd.sun.xml.draw'], - 'sxg' => ['application/vnd.sun.xml.writer.global'], - 'sxi' => ['application/vnd.sun.xml.impress'], - 'sxm' => ['application/vnd.sun.xml.math'], - 'sxw' => ['application/vnd.sun.xml.writer'], - 'sylk' => ['text/spreadsheet'], - 't' => ['application/x-perl', 'application/x-troff', 'text/troff', 'text/x-perl', 'text/x-troff'], - 't2t' => ['text/x-txt2tags'], - 't3' => ['application/x-t3vm-image'], - 'taglet' => ['application/vnd.mynfc'], - 'tao' => ['application/vnd.tao.intent-module-archive'], - 'tar' => ['application/x-tar', 'application/x-gtar'], - 'tar.Z' => ['application/x-tarz'], - 'tar.bz' => ['application/x-bzip-compressed-tar'], - 'tar.bz2' => ['application/x-bzip-compressed-tar'], - 'tar.gz' => ['application/x-compressed-tar'], - 'tar.lrz' => ['application/x-lrzip-compressed-tar'], - 'tar.lz' => ['application/x-lzip-compressed-tar'], - 'tar.lz4' => ['application/x-lz4-compressed-tar'], - 'tar.lzma' => ['application/x-lzma-compressed-tar'], - 'tar.lzo' => ['application/x-tzo'], - 'tar.xz' => ['application/x-xz-compressed-tar'], - 'target' => ['text/x-systemd-unit'], - 'taz' => ['application/x-tarz'], - 'tb2' => ['application/x-bzip-compressed-tar'], - 'tbz' => ['application/x-bzip-compressed-tar'], - 'tbz2' => ['application/x-bzip-compressed-tar'], - 'tcap' => ['application/vnd.3gpp2.tcap'], - 'tcl' => ['application/x-tcl', 'text/x-tcl'], - 'teacher' => ['application/vnd.smart.teacher'], - 'tei' => ['application/tei+xml'], - 'teicorpus' => ['application/tei+xml'], - 'tex' => ['application/x-tex', 'text/x-tex'], - 'texi' => ['application/x-texinfo', 'text/x-texinfo'], - 'texinfo' => ['application/x-texinfo', 'text/x-texinfo'], - 'text' => ['text/plain'], - 'tfi' => ['application/thraud+xml'], - 'tfm' => ['application/x-tex-tfm'], - 'tga' => ['image/x-icb', 'image/x-tga'], - 'tgz' => ['application/x-compressed-tar'], - 'theme' => ['application/x-theme'], - 'themepack' => ['application/x-windows-themepack'], - 'thmx' => ['application/vnd.ms-officetheme'], - 'tif' => ['image/tiff'], - 'tiff' => ['image/tiff'], - 'timer' => ['text/x-systemd-unit'], - 'tk' => ['text/x-tcl'], - 'tlrz' => ['application/x-lrzip-compressed-tar'], - 'tlz' => ['application/x-lzma-compressed-tar'], - 'tmo' => ['application/vnd.tmobile-livetv'], - 'tnef' => ['application/ms-tnef', 'application/vnd.ms-tnef'], - 'tnf' => ['application/ms-tnef', 'application/vnd.ms-tnef'], - 'toc' => ['application/x-cdrdao-toc'], - 'torrent' => ['application/x-bittorrent'], - 'tpic' => ['image/x-icb', 'image/x-tga'], - 'tpl' => ['application/vnd.groove-tool-template'], - 'tpt' => ['application/vnd.trid.tpt'], - 'tr' => ['application/x-troff', 'text/troff', 'text/x-troff'], - 'tra' => ['application/vnd.trueapp'], - 'trig' => ['application/trig', 'application/x-trig'], - 'trm' => ['application/x-msterminal'], - 'ts' => ['application/x-linguist', 'text/vnd.qt.linguist', 'text/vnd.trolltech.linguist', 'video/mp2t'], - 'tsd' => ['application/timestamped-data'], - 'tsv' => ['text/tab-separated-values'], - 'tta' => ['audio/tta', 'audio/x-tta'], - 'ttc' => ['font/collection'], - 'ttf' => ['application/x-font-truetype', 'application/x-font-ttf', 'font/ttf'], - 'ttl' => ['text/turtle'], - 'ttx' => ['application/x-font-ttx'], - 'twd' => ['application/vnd.simtech-mindmapper'], - 'twds' => ['application/vnd.simtech-mindmapper'], - 'twig' => ['text/x-twig'], - 'txd' => ['application/vnd.genomatix.tuxedo'], - 'txf' => ['application/vnd.mobius.txf'], - 'txt' => ['text/plain'], - 'txz' => ['application/x-xz-compressed-tar'], - 'tzo' => ['application/x-tzo'], - 'u32' => ['application/x-authorware-bin'], - 'udeb' => ['application/vnd.debian.binary-package', 'application/x-deb', 'application/x-debian-package'], - 'ufd' => ['application/vnd.ufdl'], - 'ufdl' => ['application/vnd.ufdl'], - 'ufraw' => ['application/x-ufraw'], - 'ui' => ['application/x-designer', 'application/x-gtk-builder'], - 'uil' => ['text/x-uil'], - 'ult' => ['audio/x-mod'], - 'ulx' => ['application/x-glulx'], - 'umj' => ['application/vnd.umajin'], - 'unf' => ['application/x-nes-rom'], - 'uni' => ['audio/x-mod'], - 'unif' => ['application/x-nes-rom'], - 'unityweb' => ['application/vnd.unity'], - 'uoml' => ['application/vnd.uoml+xml'], - 'uri' => ['text/uri-list'], - 'uris' => ['text/uri-list'], - 'url' => ['application/x-mswinurl'], - 'urls' => ['text/uri-list'], - 'ustar' => ['application/x-ustar'], - 'utz' => ['application/vnd.uiq.theme'], - 'uu' => ['text/x-uuencode'], - 'uue' => ['text/x-uuencode', 'zz-application/zz-winassoc-uu'], - 'uva' => ['audio/vnd.dece.audio'], - 'uvd' => ['application/vnd.dece.data'], - 'uvf' => ['application/vnd.dece.data'], - 'uvg' => ['image/vnd.dece.graphic'], - 'uvh' => ['video/vnd.dece.hd'], - 'uvi' => ['image/vnd.dece.graphic'], - 'uvm' => ['video/vnd.dece.mobile'], - 'uvp' => ['video/vnd.dece.pd'], - 'uvs' => ['video/vnd.dece.sd'], - 'uvt' => ['application/vnd.dece.ttml+xml'], - 'uvu' => ['video/vnd.uvvu.mp4'], - 'uvv' => ['video/vnd.dece.video'], - 'uvva' => ['audio/vnd.dece.audio'], - 'uvvd' => ['application/vnd.dece.data'], - 'uvvf' => ['application/vnd.dece.data'], - 'uvvg' => ['image/vnd.dece.graphic'], - 'uvvh' => ['video/vnd.dece.hd'], - 'uvvi' => ['image/vnd.dece.graphic'], - 'uvvm' => ['video/vnd.dece.mobile'], - 'uvvp' => ['video/vnd.dece.pd'], - 'uvvs' => ['video/vnd.dece.sd'], - 'uvvt' => ['application/vnd.dece.ttml+xml'], - 'uvvu' => ['video/vnd.uvvu.mp4'], - 'uvvv' => ['video/vnd.dece.video'], - 'uvvx' => ['application/vnd.dece.unspecified'], - 'uvvz' => ['application/vnd.dece.zip'], - 'uvx' => ['application/vnd.dece.unspecified'], - 'uvz' => ['application/vnd.dece.zip'], - 'v' => ['text/x-verilog'], - 'v64' => ['application/x-n64-rom'], - 'vala' => ['text/x-vala'], - 'vapi' => ['text/x-vala'], - 'vb' => ['application/x-virtual-boy-rom'], - 'vcard' => ['text/directory', 'text/vcard', 'text/x-vcard'], - 'vcd' => ['application/x-cdlink'], - 'vcf' => ['text/x-vcard', 'text/directory', 'text/vcard'], - 'vcg' => ['application/vnd.groove-vcard'], - 'vcs' => ['application/ics', 'text/calendar', 'text/x-vcalendar'], - 'vct' => ['text/directory', 'text/vcard', 'text/x-vcard'], - 'vcx' => ['application/vnd.vcx'], - 'vda' => ['image/x-icb', 'image/x-tga'], - 'vhd' => ['text/x-vhdl'], - 'vhdl' => ['text/x-vhdl'], - 'vis' => ['application/vnd.visionary'], - 'viv' => ['video/vivo', 'video/vnd.vivo'], - 'vivo' => ['video/vivo', 'video/vnd.vivo'], - 'vlc' => ['application/m3u', 'audio/m3u', 'audio/mpegurl', 'audio/x-m3u', 'audio/x-mp3-playlist', 'audio/x-mpegurl'], - 'vob' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2', 'video/x-ms-vob'], - 'voc' => ['audio/x-voc'], - 'vor' => ['application/vnd.stardivision.writer', 'application/vnd.stardivision.writer-global'], - 'vox' => ['application/x-authorware-bin'], - 'vrm' => ['model/vrml'], - 'vrml' => ['model/vrml'], - 'vsd' => ['application/vnd.visio'], - 'vsdm' => ['application/vnd.ms-visio.drawing.macroenabled.main+xml'], - 'vsdx' => ['application/vnd.ms-visio.drawing.main+xml'], - 'vsf' => ['application/vnd.vsf'], - 'vss' => ['application/vnd.visio'], - 'vssm' => ['application/vnd.ms-visio.stencil.macroenabled.main+xml'], - 'vssx' => ['application/vnd.ms-visio.stencil.main+xml'], - 'vst' => ['application/vnd.visio', 'image/x-icb', 'image/x-tga'], - 'vstm' => ['application/vnd.ms-visio.template.macroenabled.main+xml'], - 'vstx' => ['application/vnd.ms-visio.template.main+xml'], - 'vsw' => ['application/vnd.visio'], - 'vtt' => ['text/vtt'], - 'vtu' => ['model/vnd.vtu'], - 'vxml' => ['application/voicexml+xml'], - 'w3d' => ['application/x-director'], - 'wad' => ['application/x-doom', 'application/x-doom-wad', 'application/x-wii-wad'], - 'wav' => ['audio/wav', 'audio/vnd.wave', 'audio/x-wav'], - 'wax' => ['application/x-ms-asx', 'audio/x-ms-asx', 'audio/x-ms-wax', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], - 'wb1' => ['application/x-quattropro'], - 'wb2' => ['application/x-quattropro'], - 'wb3' => ['application/x-quattropro'], - 'wbmp' => ['image/vnd.wap.wbmp'], - 'wbs' => ['application/vnd.criticaltools.wbs+xml'], - 'wbxml' => ['application/vnd.wap.wbxml'], - 'wcm' => ['application/vnd.ms-works'], - 'wdb' => ['application/vnd.ms-works'], - 'wdp' => ['image/vnd.ms-photo'], - 'weba' => ['audio/webm'], - 'webm' => ['video/webm'], - 'webp' => ['image/webp'], - 'wg' => ['application/vnd.pmi.widget'], - 'wgt' => ['application/widget'], - 'wim' => ['application/x-ms-wim'], - 'wk1' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], - 'wk3' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], - 'wk4' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], - 'wkdownload' => ['application/x-partial-download'], - 'wks' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/vnd.ms-works', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], - 'wm' => ['video/x-ms-wm'], - 'wma' => ['audio/x-ms-wma', 'audio/wma'], - 'wmd' => ['application/x-ms-wmd'], - 'wmf' => ['application/wmf', 'application/x-msmetafile', 'application/x-wmf', 'image/wmf', 'image/x-win-metafile', 'image/x-wmf'], - 'wml' => ['text/vnd.wap.wml'], - 'wmlc' => ['application/vnd.wap.wmlc'], - 'wmls' => ['text/vnd.wap.wmlscript'], - 'wmlsc' => ['application/vnd.wap.wmlscriptc'], - 'wmv' => ['audio/x-ms-wmv', 'video/x-ms-wmv'], - 'wmx' => ['application/x-ms-asx', 'audio/x-ms-asx', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], - 'wmz' => ['application/x-ms-wmz', 'application/x-msmetafile'], - 'woff' => ['application/font-woff', 'application/x-font-woff', 'font/woff'], - 'woff2' => ['font/woff', 'font/woff2'], - 'wp' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], - 'wp4' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], - 'wp5' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], - 'wp6' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], - 'wpd' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], - 'wpg' => ['application/x-wpg'], - 'wpl' => ['application/vnd.ms-wpl'], - 'wpp' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], - 'wps' => ['application/vnd.ms-works'], - 'wqd' => ['application/vnd.wqd'], - 'wri' => ['application/x-mswrite'], - 'wrl' => ['model/vrml'], - 'ws' => ['application/x-wonderswan-rom'], - 'wsc' => ['application/x-wonderswan-color-rom'], - 'wsdl' => ['application/wsdl+xml'], - 'wsgi' => ['text/x-python'], - 'wspolicy' => ['application/wspolicy+xml'], - 'wtb' => ['application/vnd.webturbo'], - 'wv' => ['audio/x-wavpack'], - 'wvc' => ['audio/x-wavpack-correction'], - 'wvp' => ['audio/x-wavpack'], - 'wvx' => ['application/x-ms-asx', 'audio/x-ms-asx', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], - 'wwf' => ['application/wwf', 'application/x-wwf'], - 'x32' => ['application/x-authorware-bin'], - 'x3d' => ['model/x3d+xml'], - 'x3db' => ['model/x3d+binary'], - 'x3dbz' => ['model/x3d+binary'], - 'x3dv' => ['model/x3d+vrml'], - 'x3dvz' => ['model/x3d+vrml'], - 'x3dz' => ['model/x3d+xml'], - 'x3f' => ['image/x-sigma-x3f'], - 'xac' => ['application/x-gnucash'], - 'xaml' => ['application/xaml+xml'], - 'xap' => ['application/x-silverlight-app'], - 'xar' => ['application/vnd.xara', 'application/x-xar'], - 'xbap' => ['application/x-ms-xbap'], - 'xbd' => ['application/vnd.fujixerox.docuworks.binder'], - 'xbel' => ['application/x-xbel'], - 'xbl' => ['application/xml', 'text/xml'], - 'xbm' => ['image/x-xbitmap'], - 'xcf' => ['image/x-xcf'], - 'xcf.bz2' => ['image/x-compressed-xcf'], - 'xcf.gz' => ['image/x-compressed-xcf'], - 'xdf' => ['application/xcap-diff+xml'], - 'xdgapp' => ['application/vnd.flatpak', 'application/vnd.xdgapp'], - 'xdm' => ['application/vnd.syncml.dm+xml'], - 'xdp' => ['application/vnd.adobe.xdp+xml'], - 'xdssc' => ['application/dssc+xml'], - 'xdw' => ['application/vnd.fujixerox.docuworks'], - 'xenc' => ['application/xenc+xml'], - 'xer' => ['application/patch-ops-error+xml'], - 'xfdf' => ['application/vnd.adobe.xfdf'], - 'xfdl' => ['application/vnd.xfdl'], - 'xhe' => ['audio/usac'], - 'xht' => ['application/xhtml+xml'], - 'xhtml' => ['application/xhtml+xml'], - 'xhvml' => ['application/xv+xml'], - 'xi' => ['audio/x-xi'], - 'xif' => ['image/vnd.xiff'], - 'xla' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], - 'xlam' => ['application/vnd.ms-excel.addin.macroenabled.12'], - 'xlc' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], - 'xld' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], - 'xlf' => ['application/x-xliff', 'application/x-xliff+xml', 'application/xliff+xml'], - 'xliff' => ['application/x-xliff', 'application/xliff+xml'], - 'xll' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], - 'xlm' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], - 'xlr' => ['application/vnd.ms-works'], - 'xls' => ['application/vnd.ms-excel', 'application/msexcel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], - 'xlsb' => ['application/vnd.ms-excel.sheet.binary.macroenabled.12'], - 'xlsm' => ['application/vnd.ms-excel.sheet.macroenabled.12'], - 'xlsx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], - 'xlt' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], - 'xltm' => ['application/vnd.ms-excel.template.macroenabled.12'], - 'xltx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.template'], - 'xlw' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], - 'xm' => ['audio/x-xm', 'audio/xm'], - 'xmf' => ['audio/mobile-xmf', 'audio/x-xmf', 'audio/xmf'], - 'xmi' => ['text/x-xmi'], - 'xml' => ['application/xml', 'text/xml'], - 'xo' => ['application/vnd.olpc-sugar'], - 'xop' => ['application/xop+xml'], - 'xpi' => ['application/x-xpinstall'], - 'xpl' => ['application/xproc+xml'], - 'xpm' => ['image/x-xpixmap', 'image/x-xpm'], - 'xpr' => ['application/vnd.is-xpr'], - 'xps' => ['application/oxps', 'application/vnd.ms-xpsdocument', 'application/xps'], - 'xpw' => ['application/vnd.intercon.formnet'], - 'xpx' => ['application/vnd.intercon.formnet'], - 'xsd' => ['application/xml', 'text/xml'], - 'xsl' => ['application/xml', 'application/xslt+xml'], - 'xslfo' => ['text/x-xslfo'], - 'xslt' => ['application/xslt+xml'], - 'xsm' => ['application/vnd.syncml+xml'], - 'xspf' => ['application/x-xspf+xml', 'application/xspf+xml'], - 'xul' => ['application/vnd.mozilla.xul+xml'], - 'xvm' => ['application/xv+xml'], - 'xvml' => ['application/xv+xml'], - 'xwd' => ['image/x-xwindowdump'], - 'xyz' => ['chemical/x-xyz'], - 'xz' => ['application/x-xz'], - 'yaml' => ['application/x-yaml', 'text/x-yaml', 'text/yaml'], - 'yang' => ['application/yang'], - 'yin' => ['application/yin+xml'], - 'yml' => ['application/x-yaml', 'text/x-yaml', 'text/yaml'], - 'yt' => ['application/vnd.youtube.yt'], - 'z1' => ['application/x-zmachine'], - 'z2' => ['application/x-zmachine'], - 'z3' => ['application/x-zmachine'], - 'z4' => ['application/x-zmachine'], - 'z5' => ['application/x-zmachine'], - 'z6' => ['application/x-zmachine'], - 'z64' => ['application/x-n64-rom'], - 'z7' => ['application/x-zmachine'], - 'z8' => ['application/x-zmachine'], - 'zabw' => ['application/x-abiword'], - 'zaz' => ['application/vnd.zzazz.deck+xml'], - 'zip' => ['application/zip', 'application/x-zip', 'application/x-zip-compressed'], - 'zir' => ['application/vnd.zul'], - 'zirz' => ['application/vnd.zul'], - 'zmm' => ['application/vnd.handheld-entertainment+xml'], - 'zoo' => ['application/x-zoo'], - 'zsav' => ['application/x-spss-sav', 'application/x-spss-savefile'], - 'zz' => ['application/zlib'], - '123' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], - '602' => ['application/x-t602'], - '669' => ['audio/x-mod'], - ]; -} diff --git a/vendor/symfony/mime/MimeTypesInterface.php b/vendor/symfony/mime/MimeTypesInterface.php deleted file mode 100644 index 9fbd2cc..0000000 --- a/vendor/symfony/mime/MimeTypesInterface.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime; - -/** - * @author Fabien Potencier - */ -interface MimeTypesInterface extends MimeTypeGuesserInterface -{ - /** - * Gets the extensions for the given MIME type. - * - * @return string[] an array of extensions (first one is the preferred one) - */ - public function getExtensions(string $mimeType): array; - - /** - * Gets the MIME types for the given extension. - * - * @return string[] an array of MIME types (first one is the preferred one) - */ - public function getMimeTypes(string $ext): array; -} diff --git a/vendor/symfony/mime/Part/AbstractMultipartPart.php b/vendor/symfony/mime/Part/AbstractMultipartPart.php deleted file mode 100644 index 48b8620..0000000 --- a/vendor/symfony/mime/Part/AbstractMultipartPart.php +++ /dev/null @@ -1,99 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Part; - -use Symfony\Component\Mime\Header\Headers; - -/** - * @author Fabien Potencier - */ -abstract class AbstractMultipartPart extends AbstractPart -{ - private $boundary; - private $parts = []; - - public function __construct(AbstractPart ...$parts) - { - parent::__construct(); - - foreach ($parts as $part) { - $this->parts[] = $part; - } - } - - /** - * @return AbstractPart[] - */ - public function getParts(): array - { - return $this->parts; - } - - public function getMediaType(): string - { - return 'multipart'; - } - - public function getPreparedHeaders(): Headers - { - $headers = parent::getPreparedHeaders(); - $headers->setHeaderParameter('Content-Type', 'boundary', $this->getBoundary()); - - return $headers; - } - - public function bodyToString(): string - { - $parts = $this->getParts(); - $string = ''; - foreach ($parts as $part) { - $string .= '--'.$this->getBoundary()."\r\n".$part->toString()."\r\n"; - } - $string .= '--'.$this->getBoundary()."--\r\n"; - - return $string; - } - - public function bodyToIterable(): iterable - { - $parts = $this->getParts(); - foreach ($parts as $part) { - yield '--'.$this->getBoundary()."\r\n"; - yield from $part->toIterable(); - yield "\r\n"; - } - yield '--'.$this->getBoundary()."--\r\n"; - } - - public function asDebugString(): string - { - $str = parent::asDebugString(); - foreach ($this->getParts() as $part) { - $lines = explode("\n", $part->asDebugString()); - $str .= "\n └ ".array_shift($lines); - foreach ($lines as $line) { - $str .= "\n |".$line; - } - } - - return $str; - } - - private function getBoundary(): string - { - if (null === $this->boundary) { - $this->boundary = '_=_symfony_'.time().'_'.bin2hex(random_bytes(16)).'_=_'; - } - - return $this->boundary; - } -} diff --git a/vendor/symfony/mime/Part/AbstractPart.php b/vendor/symfony/mime/Part/AbstractPart.php deleted file mode 100644 index 93892d9..0000000 --- a/vendor/symfony/mime/Part/AbstractPart.php +++ /dev/null @@ -1,65 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Part; - -use Symfony\Component\Mime\Header\Headers; - -/** - * @author Fabien Potencier - */ -abstract class AbstractPart -{ - private $headers; - - public function __construct() - { - $this->headers = new Headers(); - } - - public function getHeaders(): Headers - { - return $this->headers; - } - - public function getPreparedHeaders(): Headers - { - $headers = clone $this->headers; - $headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype()); - - return $headers; - } - - public function toString(): string - { - return $this->getPreparedHeaders()->toString()."\r\n".$this->bodyToString(); - } - - public function toIterable(): iterable - { - yield $this->getPreparedHeaders()->toString(); - yield "\r\n"; - yield from $this->bodyToIterable(); - } - - public function asDebugString(): string - { - return $this->getMediaType().'/'.$this->getMediaSubtype(); - } - - abstract public function bodyToString(): string; - - abstract public function bodyToIterable(): iterable; - - abstract public function getMediaType(): string; - - abstract public function getMediaSubtype(): string; -} diff --git a/vendor/symfony/mime/Part/DataPart.php b/vendor/symfony/mime/Part/DataPart.php deleted file mode 100644 index 423185f..0000000 --- a/vendor/symfony/mime/Part/DataPart.php +++ /dev/null @@ -1,161 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Part; - -use Symfony\Component\Mime\Exception\InvalidArgumentException; -use Symfony\Component\Mime\Header\Headers; -use Symfony\Component\Mime\MimeTypes; - -/** - * @author Fabien Potencier - */ -class DataPart extends TextPart -{ - private static $mimeTypes; - - private $filename; - private $mediaType; - private $cid; - private $handle; - - /** - * @param resource|string $body - */ - public function __construct($body, string $filename = null, string $contentType = null, string $encoding = null) - { - if (null === $contentType) { - $contentType = 'application/octet-stream'; - } - list($this->mediaType, $subtype) = explode('/', $contentType); - - parent::__construct($body, null, $subtype, $encoding); - - $this->filename = $filename; - $this->setName($filename); - $this->setDisposition('attachment'); - } - - public static function fromPath(string $path, string $name = null, string $contentType = null): self - { - // FIXME: if file is not readable, exception? - - if (null === $contentType) { - $ext = strtolower(substr($path, strrpos($path, '.') + 1)); - if (null === self::$mimeTypes) { - self::$mimeTypes = new MimeTypes(); - } - $contentType = self::$mimeTypes->getMimeTypes($ext)[0] ?? 'application/octet-stream'; - } - - if (false === $handle = @fopen($path, 'r', false)) { - throw new InvalidArgumentException(sprintf('Unable to open path "%s"', $path)); - } - $p = new self($handle, $name ?: basename($path), $contentType); - $p->handle = $handle; - - return $p; - } - - /** - * @return $this - */ - public function asInline() - { - return $this->setDisposition('inline'); - } - - public function getContentId(): string - { - return $this->cid ?: $this->cid = $this->generateContentId(); - } - - public function hasContentId(): bool - { - return null !== $this->cid; - } - - public function getMediaType(): string - { - return $this->mediaType; - } - - public function getPreparedHeaders(): Headers - { - $headers = parent::getPreparedHeaders(); - - if (null !== $this->cid) { - $headers->setHeaderBody('Id', 'Content-ID', $this->cid); - } - - if (null !== $this->filename) { - $headers->setHeaderParameter('Content-Disposition', 'filename', $this->filename); - } - - return $headers; - } - - public function asDebugString(): string - { - $str = parent::asDebugString(); - if (null !== $this->filename) { - $str .= ' filename: '.$this->filename; - } - - return $str; - } - - private function generateContentId(): string - { - return bin2hex(random_bytes(16)).'@symfony'; - } - - public function __destruct() - { - if (null !== $this->handle && \is_resource($this->handle)) { - fclose($this->handle); - } - } - - /** - * @return array - */ - public function __sleep() - { - // converts the body to a string - parent::__sleep(); - - $this->_parent = []; - foreach (['body', 'charset', 'subtype', 'disposition', 'name', 'encoding'] as $name) { - $r = new \ReflectionProperty(TextPart::class, $name); - $r->setAccessible(true); - $this->_parent[$name] = $r->getValue($this); - } - $this->_headers = $this->getHeaders(); - - return ['_headers', '_parent', 'filename', 'mediaType']; - } - - public function __wakeup() - { - $r = new \ReflectionProperty(AbstractPart::class, 'headers'); - $r->setAccessible(true); - $r->setValue($this, $this->_headers); - unset($this->_headers); - - foreach (['body', 'charset', 'subtype', 'disposition', 'name', 'encoding'] as $name) { - $r = new \ReflectionProperty(TextPart::class, $name); - $r->setAccessible(true); - $r->setValue($this, $this->_parent[$name]); - } - unset($this->_parent); - } -} diff --git a/vendor/symfony/mime/Part/MessagePart.php b/vendor/symfony/mime/Part/MessagePart.php deleted file mode 100644 index 1b5c23e..0000000 --- a/vendor/symfony/mime/Part/MessagePart.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Part; - -use Symfony\Component\Mime\Message; -use Symfony\Component\Mime\RawMessage; - -/** - * @final - * - * @author Fabien Potencier - */ -class MessagePart extends DataPart -{ - private $message; - - public function __construct(RawMessage $message) - { - if ($message instanceof Message) { - $name = $message->getHeaders()->getHeaderBody('Subject').'.eml'; - } else { - $name = 'email.eml'; - } - parent::__construct('', $name); - - $this->message = $message; - } - - public function getMediaType(): string - { - return 'message'; - } - - public function getMediaSubtype(): string - { - return 'rfc822'; - } - - public function getBody(): string - { - return $this->message->toString(); - } - - public function bodyToString(): string - { - return $this->getBody(); - } - - public function bodyToIterable(): iterable - { - return $this->message->toIterable(); - } -} diff --git a/vendor/symfony/mime/Part/Multipart/AlternativePart.php b/vendor/symfony/mime/Part/Multipart/AlternativePart.php deleted file mode 100644 index fd75423..0000000 --- a/vendor/symfony/mime/Part/Multipart/AlternativePart.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Part\Multipart; - -use Symfony\Component\Mime\Part\AbstractMultipartPart; - -/** - * @author Fabien Potencier - */ -final class AlternativePart extends AbstractMultipartPart -{ - public function getMediaSubtype(): string - { - return 'alternative'; - } -} diff --git a/vendor/symfony/mime/Part/Multipart/DigestPart.php b/vendor/symfony/mime/Part/Multipart/DigestPart.php deleted file mode 100644 index 27537f1..0000000 --- a/vendor/symfony/mime/Part/Multipart/DigestPart.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Part\Multipart; - -use Symfony\Component\Mime\Part\AbstractMultipartPart; -use Symfony\Component\Mime\Part\MessagePart; - -/** - * @author Fabien Potencier - */ -final class DigestPart extends AbstractMultipartPart -{ - public function __construct(MessagePart ...$parts) - { - parent::__construct(...$parts); - } - - public function getMediaSubtype(): string - { - return 'digest'; - } -} diff --git a/vendor/symfony/mime/Part/Multipart/FormDataPart.php b/vendor/symfony/mime/Part/Multipart/FormDataPart.php deleted file mode 100644 index 6838620..0000000 --- a/vendor/symfony/mime/Part/Multipart/FormDataPart.php +++ /dev/null @@ -1,103 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Part\Multipart; - -use Symfony\Component\Mime\Exception\InvalidArgumentException; -use Symfony\Component\Mime\Part\AbstractMultipartPart; -use Symfony\Component\Mime\Part\DataPart; -use Symfony\Component\Mime\Part\TextPart; - -/** - * Implements RFC 7578. - * - * @author Fabien Potencier - */ -final class FormDataPart extends AbstractMultipartPart -{ - private $fields = []; - - /** - * @param (string|array|DataPart)[] $fields - */ - public function __construct(array $fields = []) - { - parent::__construct(); - - foreach ($fields as $name => $value) { - if (!\is_string($value) && !\is_array($value) && !$value instanceof TextPart) { - throw new InvalidArgumentException(sprintf('A form field value can only be a string, an array, or an instance of TextPart ("%s" given).', \is_object($value) ? \get_class($value) : \gettype($value))); - } - - $this->fields[$name] = $value; - } - // HTTP does not support \r\n in header values - $this->getHeaders()->setMaxLineLength(PHP_INT_MAX); - } - - public function getMediaSubtype(): string - { - return 'form-data'; - } - - public function getParts(): array - { - return $this->prepareFields($this->fields); - } - - private function prepareFields(array $fields): array - { - $values = []; - - $prepare = function ($item, $key, $root = null) use (&$values, &$prepare) { - $fieldName = $root ? sprintf('%s[%s]', $root, $key) : $key; - - if (\is_array($item)) { - array_walk($item, $prepare, $fieldName); - - return; - } - - $values[] = $this->preparePart($fieldName, $item); - }; - - array_walk($fields, $prepare); - - return $values; - } - - private function preparePart(string $name, $value): TextPart - { - if (\is_string($value)) { - return $this->configurePart($name, new TextPart($value, 'utf-8', 'plain', '8bit')); - } - - return $this->configurePart($name, $value); - } - - private function configurePart(string $name, TextPart $part): TextPart - { - static $r; - - if (null === $r) { - $r = new \ReflectionProperty(TextPart::class, 'encoding'); - $r->setAccessible(true); - } - - $part->setDisposition('form-data'); - $part->setName($name); - // HTTP does not support \r\n in header values - $part->getHeaders()->setMaxLineLength(PHP_INT_MAX); - $r->setValue($part, '8bit'); - - return $part; - } -} diff --git a/vendor/symfony/mime/Part/Multipart/MixedPart.php b/vendor/symfony/mime/Part/Multipart/MixedPart.php deleted file mode 100644 index c8d7028..0000000 --- a/vendor/symfony/mime/Part/Multipart/MixedPart.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Part\Multipart; - -use Symfony\Component\Mime\Part\AbstractMultipartPart; - -/** - * @author Fabien Potencier - */ -final class MixedPart extends AbstractMultipartPart -{ - public function getMediaSubtype(): string - { - return 'mixed'; - } -} diff --git a/vendor/symfony/mime/Part/Multipart/RelatedPart.php b/vendor/symfony/mime/Part/Multipart/RelatedPart.php deleted file mode 100644 index 08fdd5f..0000000 --- a/vendor/symfony/mime/Part/Multipart/RelatedPart.php +++ /dev/null @@ -1,55 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Part\Multipart; - -use Symfony\Component\Mime\Part\AbstractMultipartPart; -use Symfony\Component\Mime\Part\AbstractPart; - -/** - * @author Fabien Potencier - */ -final class RelatedPart extends AbstractMultipartPart -{ - private $mainPart; - - public function __construct(AbstractPart $mainPart, AbstractPart $part, AbstractPart ...$parts) - { - $this->mainPart = $mainPart; - $this->prepareParts($part, ...$parts); - - parent::__construct($part, ...$parts); - } - - public function getParts(): array - { - return array_merge([$this->mainPart], parent::getParts()); - } - - public function getMediaSubtype(): string - { - return 'related'; - } - - private function generateContentId(): string - { - return bin2hex(random_bytes(16)).'@symfony'; - } - - private function prepareParts(AbstractPart ...$parts): void - { - foreach ($parts as $part) { - if (!$part->getHeaders()->has('Content-ID')) { - $part->getHeaders()->setHeaderBody('Id', 'Content-ID', $this->generateContentId()); - } - } - } -} diff --git a/vendor/symfony/mime/Part/SMimePart.php b/vendor/symfony/mime/Part/SMimePart.php deleted file mode 100644 index 1dfc1ae..0000000 --- a/vendor/symfony/mime/Part/SMimePart.php +++ /dev/null @@ -1,116 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Part; - -use Symfony\Component\Mime\Header\Headers; - -/** - * @author Sebastiaan Stok - */ -class SMimePart extends AbstractPart -{ - private $body; - private $type; - private $subtype; - private $parameters; - - /** - * @param iterable|string $body - */ - public function __construct($body, string $type, string $subtype, array $parameters) - { - parent::__construct(); - - if (!\is_string($body) && !is_iterable($body)) { - throw new \TypeError(sprintf('The body of "%s" must be a string or a iterable (got "%s").', self::class, \is_object($body) ? \get_class($body) : \gettype($body))); - } - - $this->body = $body; - $this->type = $type; - $this->subtype = $subtype; - $this->parameters = $parameters; - } - - public function getMediaType(): string - { - return $this->type; - } - - public function getMediaSubtype(): string - { - return $this->subtype; - } - - public function bodyToString(): string - { - if (\is_string($this->body)) { - return $this->body; - } - - $body = ''; - foreach ($this->body as $chunk) { - $body .= $chunk; - } - $this->body = $body; - - return $body; - } - - public function bodyToIterable(): iterable - { - if (\is_string($this->body)) { - yield $this->body; - - return; - } - - $body = ''; - foreach ($this->body as $chunk) { - $body .= $chunk; - yield $chunk; - } - $this->body = $body; - } - - public function getPreparedHeaders(): Headers - { - $headers = clone parent::getHeaders(); - - $headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype()); - - foreach ($this->parameters as $name => $value) { - $headers->setHeaderParameter('Content-Type', $name, $value); - } - - return $headers; - } - - public function __sleep(): array - { - // convert iterables to strings for serialization - if (is_iterable($this->body)) { - $this->body = $this->bodyToString(); - } - - $this->_headers = $this->getHeaders(); - - return ['_headers', 'body', 'type', 'subtype', 'parameters']; - } - - public function __wakeup(): void - { - $r = new \ReflectionProperty(AbstractPart::class, 'headers'); - $r->setAccessible(true); - $r->setValue($this, $this->_headers); - unset($this->_headers); - } -} diff --git a/vendor/symfony/mime/Part/TextPart.php b/vendor/symfony/mime/Part/TextPart.php deleted file mode 100644 index a41d91d..0000000 --- a/vendor/symfony/mime/Part/TextPart.php +++ /dev/null @@ -1,204 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Part; - -use Symfony\Component\Mime\Encoder\Base64ContentEncoder; -use Symfony\Component\Mime\Encoder\ContentEncoderInterface; -use Symfony\Component\Mime\Encoder\EightBitContentEncoder; -use Symfony\Component\Mime\Encoder\QpContentEncoder; -use Symfony\Component\Mime\Exception\InvalidArgumentException; -use Symfony\Component\Mime\Header\Headers; - -/** - * @author Fabien Potencier - */ -class TextPart extends AbstractPart -{ - private static $encoders = []; - - private $body; - private $charset; - private $subtype; - private $disposition; - private $name; - private $encoding; - - /** - * @param resource|string $body - */ - public function __construct($body, ?string $charset = 'utf-8', $subtype = 'plain', string $encoding = null) - { - parent::__construct(); - - if (!\is_string($body) && !\is_resource($body)) { - throw new \TypeError(sprintf('The body of "%s" must be a string or a resource (got "%s").', self::class, \is_object($body) ? \get_class($body) : \gettype($body))); - } - - $this->body = $body; - $this->charset = $charset; - $this->subtype = $subtype; - - if (null === $encoding) { - $this->encoding = $this->chooseEncoding(); - } else { - if ('quoted-printable' !== $encoding && 'base64' !== $encoding && '8bit' !== $encoding) { - throw new InvalidArgumentException(sprintf('The encoding must be one of "quoted-printable", "base64", or "8bit" ("%s" given).', $encoding)); - } - $this->encoding = $encoding; - } - } - - public function getMediaType(): string - { - return 'text'; - } - - public function getMediaSubtype(): string - { - return $this->subtype; - } - - /** - * @param string $disposition one of attachment, inline, or form-data - * - * @return $this - */ - public function setDisposition(string $disposition) - { - $this->disposition = $disposition; - - return $this; - } - - /** - * Sets the name of the file (used by FormDataPart). - * - * @return $this - */ - public function setName($name) - { - $this->name = $name; - - return $this; - } - - public function getBody(): string - { - if (!\is_resource($this->body)) { - return $this->body; - } - - if (stream_get_meta_data($this->body)['seekable'] ?? false) { - rewind($this->body); - } - - return stream_get_contents($this->body) ?: ''; - } - - public function bodyToString(): string - { - return $this->getEncoder()->encodeString($this->getBody(), $this->charset); - } - - public function bodyToIterable(): iterable - { - if (\is_resource($this->body)) { - if (stream_get_meta_data($this->body)['seekable'] ?? false) { - rewind($this->body); - } - yield from $this->getEncoder()->encodeByteStream($this->body); - } else { - yield $this->getEncoder()->encodeString($this->body); - } - } - - public function getPreparedHeaders(): Headers - { - $headers = parent::getPreparedHeaders(); - - $headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype()); - if ($this->charset) { - $headers->setHeaderParameter('Content-Type', 'charset', $this->charset); - } - if ($this->name) { - $headers->setHeaderParameter('Content-Type', 'name', $this->name); - } - $headers->setHeaderBody('Text', 'Content-Transfer-Encoding', $this->encoding); - - if (!$headers->has('Content-Disposition') && null !== $this->disposition) { - $headers->setHeaderBody('Parameterized', 'Content-Disposition', $this->disposition); - if ($this->name) { - $headers->setHeaderParameter('Content-Disposition', 'name', $this->name); - } - } - - return $headers; - } - - public function asDebugString(): string - { - $str = parent::asDebugString(); - if (null !== $this->charset) { - $str .= ' charset: '.$this->charset; - } - if (null !== $this->disposition) { - $str .= ' disposition: '.$this->disposition; - } - - return $str; - } - - private function getEncoder(): ContentEncoderInterface - { - if ('8bit' === $this->encoding) { - return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new EightBitContentEncoder()); - } - - if ('quoted-printable' === $this->encoding) { - return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new QpContentEncoder()); - } - - return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new Base64ContentEncoder()); - } - - private function chooseEncoding(): string - { - if (null === $this->charset) { - return 'base64'; - } - - return 'quoted-printable'; - } - - /** - * @return array - */ - public function __sleep() - { - // convert resources to strings for serialization - if (\is_resource($this->body)) { - $this->body = $this->getBody(); - } - - $this->_headers = $this->getHeaders(); - - return ['_headers', 'body', 'charset', 'subtype', 'disposition', 'name', 'encoding']; - } - - public function __wakeup() - { - $r = new \ReflectionProperty(AbstractPart::class, 'headers'); - $r->setAccessible(true); - $r->setValue($this, $this->_headers); - unset($this->_headers); - } -} diff --git a/vendor/symfony/mime/README.md b/vendor/symfony/mime/README.md deleted file mode 100644 index 4d565c9..0000000 --- a/vendor/symfony/mime/README.md +++ /dev/null @@ -1,13 +0,0 @@ -MIME Component -============== - -The MIME component allows manipulating MIME messages. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/mime.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/mime/RawMessage.php b/vendor/symfony/mime/RawMessage.php deleted file mode 100644 index 79a27e9..0000000 --- a/vendor/symfony/mime/RawMessage.php +++ /dev/null @@ -1,88 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime; - -use Symfony\Component\Mime\Exception\LogicException; - -/** - * @author Fabien Potencier - */ -class RawMessage implements \Serializable -{ - private $message; - - /** - * @param iterable|string $message - */ - public function __construct($message) - { - $this->message = $message; - } - - public function toString(): string - { - if (\is_string($this->message)) { - return $this->message; - } - - return $this->message = implode('', iterator_to_array($this->message, false)); - } - - public function toIterable(): iterable - { - if (\is_string($this->message)) { - yield $this->message; - - return; - } - - $message = ''; - foreach ($this->message as $chunk) { - $message .= $chunk; - yield $chunk; - } - $this->message = $message; - } - - /** - * @throws LogicException if the message is not valid - */ - public function ensureValidity() - { - } - - /** - * @internal - */ - final public function serialize(): string - { - return serialize($this->__serialize()); - } - - /** - * @internal - */ - final public function unserialize($serialized) - { - $this->__unserialize(unserialize($serialized)); - } - - public function __serialize(): array - { - return [$this->message]; - } - - public function __unserialize(array $data): void - { - [$this->message] = $data; - } -} diff --git a/vendor/symfony/mime/Resources/bin/update_mime_types.php b/vendor/symfony/mime/Resources/bin/update_mime_types.php deleted file mode 100644 index 74a9449..0000000 --- a/vendor/symfony/mime/Resources/bin/update_mime_types.php +++ /dev/null @@ -1,166 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -// load new map -$data = file_get_contents('https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types'); -$new = []; -foreach (explode("\n", $data) as $line) { - if (!$line || '#' == $line[0]) { - continue; - } - $mimeType = substr($line, 0, strpos($line, "\t")); - $extensions = explode(' ', substr($line, strrpos($line, "\t") + 1)); - $new[$mimeType] = $extensions; -} - -$xml = simplexml_load_string(file_get_contents('https://raw.github.com/minad/mimemagic/master/script/freedesktop.org.xml')); -foreach ($xml as $node) { - $exts = []; - foreach ($node->glob as $glob) { - $pattern = (string) $glob['pattern']; - if ('*' != $pattern[0] || '.' != $pattern[1]) { - continue; - } - - $exts[] = substr($pattern, 2); - } - - if (!$exts) { - continue; - } - - $mt = strtolower((string) $node['type']); - $new[$mt] = array_merge($new[$mt] ?? [], $exts); - foreach ($node->alias as $alias) { - $mt = strtolower((string) $alias['type']); - $new[$mt] = array_merge($new[$mt] ?? [], $exts); - } -} - -// load current map -$data = file_get_contents($output = __DIR__.'/../../MimeTypes.php'); -$current = []; -$pre = ''; -$post = ''; -foreach (explode("\n", $data) as $line) { - if (!preg_match("{^ '([^']+/[^']+)' => \['(.+)'\],$}", $line, $matches)) { - if (!$current) { - $pre .= $line."\n"; - } else { - $post .= $line."\n"; - } - continue; - } - $current[$matches[1]] = explode("', '", $matches[2]); -} - -// we merge the 2 maps (we never remove old mime types) -$map = array_replace_recursive($current, $new); -ksort($map); - -$data = $pre; -foreach ($map as $mimeType => $exts) { - $data .= sprintf(" '%s' => ['%s'],\n", $mimeType, implode("', '", array_unique($exts))); -} -$data .= $post; - -// reverse map -// we prefill the extensions with some preferences for content-types -$exts = [ - 'aif' => ['audio/x-aiff'], - 'aiff' => ['audio/x-aiff'], - 'aps' => ['application/postscript'], - 'avi' => ['video/avi'], - 'bmp' => ['image/bmp'], - 'bz2' => ['application/x-bz2'], - 'css' => ['text/css'], - 'csv' => ['text/csv'], - 'dmg' => ['application/x-apple-diskimage'], - 'doc' => ['application/msword'], - 'docx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'], - 'eml' => ['message/rfc822'], - 'exe' => ['application/x-ms-dos-executable'], - 'flv' => ['video/x-flv'], - 'gif' => ['image/gif'], - 'gz' => ['application/x-gzip'], - 'hqx' => ['application/stuffit'], - 'htm' => ['text/html'], - 'html' => ['text/html'], - 'jar' => ['application/x-java-archive'], - 'jpeg' => ['image/jpeg'], - 'jpg' => ['image/jpeg'], - 'js' => ['text/javascript'], - 'm3u' => ['audio/x-mpegurl'], - 'm4a' => ['audio/mp4'], - 'mdb' => ['application/x-msaccess'], - 'mid' => ['audio/midi'], - 'midi' => ['audio/midi'], - 'mov' => ['video/quicktime'], - 'mp3' => ['audio/mpeg'], - 'mp4' => ['video/mp4'], - 'mpeg' => ['video/mpeg'], - 'mpg' => ['video/mpeg'], - 'ogg' => ['audio/ogg'], - 'pdf' => ['application/pdf'], - 'php' => ['application/x-php'], - 'php3' => ['application/x-php'], - 'php4' => ['application/x-php'], - 'php5' => ['application/x-php'], - 'png' => ['image/png'], - 'ppt' => ['application/vnd.ms-powerpoint'], - 'pptx' => ['application/vnd.openxmlformats-officedocument.presentationml.presentation'], - 'ps' => ['application/postscript'], - 'rar' => ['application/x-rar-compressed'], - 'rtf' => ['application/rtf'], - 'sit' => ['application/x-stuffit'], - 'svg' => ['image/svg+xml'], - 'tar' => ['application/x-tar'], - 'tif' => ['image/tiff'], - 'tiff' => ['image/tiff'], - 'ttf' => ['application/x-font-truetype'], - 'txt' => ['text/plain'], - 'vcf' => ['text/x-vcard'], - 'wav' => ['audio/wav'], - 'wma' => ['audio/x-ms-wma'], - 'wmv' => ['audio/x-ms-wmv'], - 'xls' => ['application/vnd.ms-excel'], - 'xlsx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], - 'xml' => ['application/xml'], - 'zip' => ['application/zip'], -]; -foreach ($map as $mimeType => $extensions) { - foreach ($extensions as $extension) { - $exts[$extension][] = $mimeType; - } -} -ksort($exts); - -$updated = ''; -$state = 0; -foreach (explode("\n", $data) as $line) { - if (!preg_match("{^ '([^'/]+)' => \['(.+)'\],$}", $line, $matches)) { - if (1 === $state) { - $state = 2; - foreach ($exts as $ext => $mimeTypes) { - $updated .= sprintf(" '%s' => ['%s'],\n", $ext, implode("', '", array_unique($mimeTypes))); - } - } - $updated .= $line."\n"; - continue; - } - $state = 1; -} - -$updated = preg_replace('{Updated from upstream on .+?\.}', 'Updated from upstream on '.date('Y-m-d'), $updated, -1); - -file_put_contents($output, rtrim($updated, "\n")."\n"); - -echo "Done.\n"; diff --git a/vendor/symfony/mime/Test/Constraint/EmailAddressContains.php b/vendor/symfony/mime/Test/Constraint/EmailAddressContains.php deleted file mode 100644 index 58ef360..0000000 --- a/vendor/symfony/mime/Test/Constraint/EmailAddressContains.php +++ /dev/null @@ -1,74 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\Mime\Header\MailboxHeader; -use Symfony\Component\Mime\Header\MailboxListHeader; -use Symfony\Component\Mime\RawMessage; - -final class EmailAddressContains extends Constraint -{ - private $headerName; - private $expectedValue; - - public function __construct(string $headerName, string $expectedValue) - { - $this->headerName = $headerName; - $this->expectedValue = $expectedValue; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return sprintf('contains address "%s" with value "%s"', $this->headerName, $this->expectedValue); - } - - /** - * @param RawMessage $message - * - * {@inheritdoc} - */ - protected function matches($message): bool - { - if (RawMessage::class === \get_class($message)) { - throw new \LogicException('Unable to test a message address on a RawMessage instance.'); - } - - $header = $message->getHeaders()->get($this->headerName); - if ($header instanceof MailboxHeader) { - return $this->expectedValue === $header->Address()->getAddress(); - } elseif ($header instanceof MailboxListHeader) { - foreach ($header->getAddresses() as $address) { - if ($this->expectedValue === $address->getAddress()) { - return true; - } - } - - return false; - } - - throw new \LogicException(sprintf('Unable to test a message address on a non-address header.')); - } - - /** - * @param RawMessage $message - * - * {@inheritdoc} - */ - protected function failureDescription($message): string - { - return sprintf('the Email %s (value is %s)', $this->toString(), $message->getHeaders()->get($this->headerName)->getBodyAsString()); - } -} diff --git a/vendor/symfony/mime/Test/Constraint/EmailAttachmentCount.php b/vendor/symfony/mime/Test/Constraint/EmailAttachmentCount.php deleted file mode 100644 index b219f28..0000000 --- a/vendor/symfony/mime/Test/Constraint/EmailAttachmentCount.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\Mime\RawMessage; - -final class EmailAttachmentCount extends Constraint -{ - private $expectedValue; - private $transport; - - public function __construct(int $expectedValue, string $transport = null) - { - $this->expectedValue = $expectedValue; - $this->transport = $transport; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return sprintf('has sent "%d" attachment(s)', $this->expectedValue); - } - - /** - * @param RawMessage $message - * - * {@inheritdoc} - */ - protected function matches($message): bool - { - if (RawMessage::class === \get_class($message) || Message::class === \get_class($message)) { - throw new \LogicException('Unable to test a message attachment on a RawMessage or Message instance.'); - } - - return $this->expectedValue === \count($message->getAttachments()); - } - - /** - * @param RawMessage $message - * - * {@inheritdoc} - */ - protected function failureDescription($message): string - { - return 'the Email '.$this->toString(); - } -} diff --git a/vendor/symfony/mime/Test/Constraint/EmailHasHeader.php b/vendor/symfony/mime/Test/Constraint/EmailHasHeader.php deleted file mode 100644 index a29f835..0000000 --- a/vendor/symfony/mime/Test/Constraint/EmailHasHeader.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\Mime\RawMessage; - -final class EmailHasHeader extends Constraint -{ - private $headerName; - - public function __construct(string $headerName) - { - $this->headerName = $headerName; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return sprintf('has header "%s"', $this->headerName); - } - - /** - * @param RawMessage $message - * - * {@inheritdoc} - */ - protected function matches($message): bool - { - if (RawMessage::class === \get_class($message)) { - throw new \LogicException('Unable to test a message header on a RawMessage instance.'); - } - - return $message->getHeaders()->has($this->headerName); - } - - /** - * @param RawMessage $message - * - * {@inheritdoc} - */ - protected function failureDescription($message): string - { - return 'the Email '.$this->toString(); - } -} diff --git a/vendor/symfony/mime/Test/Constraint/EmailHeaderSame.php b/vendor/symfony/mime/Test/Constraint/EmailHeaderSame.php deleted file mode 100644 index bc7e330..0000000 --- a/vendor/symfony/mime/Test/Constraint/EmailHeaderSame.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; -use Symfony\Component\Mime\RawMessage; - -final class EmailHeaderSame extends Constraint -{ - private $headerName; - private $expectedValue; - - public function __construct(string $headerName, string $expectedValue) - { - $this->headerName = $headerName; - $this->expectedValue = $expectedValue; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return sprintf('has header "%s" with value "%s"', $this->headerName, $this->expectedValue); - } - - /** - * @param RawMessage $message - * - * {@inheritdoc} - */ - protected function matches($message): bool - { - if (RawMessage::class === \get_class($message)) { - throw new \LogicException('Unable to test a message header on a RawMessage instance.'); - } - - return $this->expectedValue === $message->getHeaders()->get($this->headerName)->getBodyAsString(); - } - - /** - * @param RawMessage $message - * - * {@inheritdoc} - */ - protected function failureDescription($message): string - { - return sprintf('the Email %s (value is %s)', $this->toString(), $message->getHeaders()->get($this->headerName)->getBodyAsString()); - } -} diff --git a/vendor/symfony/mime/Test/Constraint/EmailHtmlBodyContains.php b/vendor/symfony/mime/Test/Constraint/EmailHtmlBodyContains.php deleted file mode 100644 index 8965195..0000000 --- a/vendor/symfony/mime/Test/Constraint/EmailHtmlBodyContains.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; - -final class EmailHtmlBodyContains extends Constraint -{ - private $expectedText; - - public function __construct(string $expectedText) - { - $this->expectedText = $expectedText; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return sprintf('contains "%s"', $this->expectedText); - } - - /** - * {@inheritdoc} - * - * @param RawMessage $message - */ - protected function matches($message): bool - { - if (RawMessage::class === \get_class($message) || Message::class === \get_class($message)) { - throw new \LogicException('Unable to test a message HTML body on a RawMessage or Message instance.'); - } - - return false !== mb_strpos($message->getHtmlBody(), $this->expectedText); - } - - /** - * {@inheritdoc} - * - * @param RawMessage $message - */ - protected function failureDescription($message): string - { - return 'the Email HTML body '.$this->toString(); - } -} diff --git a/vendor/symfony/mime/Test/Constraint/EmailTextBodyContains.php b/vendor/symfony/mime/Test/Constraint/EmailTextBodyContains.php deleted file mode 100644 index b5e87f9..0000000 --- a/vendor/symfony/mime/Test/Constraint/EmailTextBodyContains.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Mime\Test\Constraint; - -use PHPUnit\Framework\Constraint\Constraint; - -final class EmailTextBodyContains extends Constraint -{ - private $expectedText; - - public function __construct(string $expectedText) - { - $this->expectedText = $expectedText; - } - - /** - * {@inheritdoc} - */ - public function toString(): string - { - return sprintf('contains "%s"', $this->expectedText); - } - - /** - * {@inheritdoc} - * - * @param RawMessage $message - */ - protected function matches($message): bool - { - if (RawMessage::class === \get_class($message) || Message::class === \get_class($message)) { - throw new \LogicException('Unable to test a message text body on a RawMessage or Message instance.'); - } - - return false !== mb_strpos($message->getTextBody(), $this->expectedText); - } - - /** - * {@inheritdoc} - * - * @param RawMessage $message - */ - protected function failureDescription($message): string - { - return 'the Email text body '.$this->toString(); - } -} diff --git a/vendor/symfony/mime/composer.json b/vendor/symfony/mime/composer.json deleted file mode 100644 index c3f2626..0000000 --- a/vendor/symfony/mime/composer.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "symfony/mime", - "type": "library", - "description": "A library to manipulate MIME messages", - "keywords": ["mime", "mime-type"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "symfony/polyfill-intl-idn": "^1.10", - "symfony/polyfill-mbstring": "^1.0" - }, - "require-dev": { - "egulias/email-validator": "^2.1.10", - "symfony/dependency-injection": "^4.4|^5.0" - }, - "conflict": { - "symfony/mailer": "<4.4" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Mime\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/polyfill-ctype/Ctype.php b/vendor/symfony/polyfill-ctype/Ctype.php deleted file mode 100644 index 58414dc..0000000 --- a/vendor/symfony/polyfill-ctype/Ctype.php +++ /dev/null @@ -1,227 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Ctype; - -/** - * Ctype implementation through regex. - * - * @internal - * - * @author Gert de Pagter - */ -final class Ctype -{ - /** - * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise. - * - * @see https://php.net/ctype-alnum - * - * @param string|int $text - * - * @return bool - */ - public static function ctype_alnum($text) - { - $text = self::convert_int_to_char_for_ctype($text); - - return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text); - } - - /** - * Returns TRUE if every character in text is a letter, FALSE otherwise. - * - * @see https://php.net/ctype-alpha - * - * @param string|int $text - * - * @return bool - */ - public static function ctype_alpha($text) - { - $text = self::convert_int_to_char_for_ctype($text); - - return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text); - } - - /** - * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise. - * - * @see https://php.net/ctype-cntrl - * - * @param string|int $text - * - * @return bool - */ - public static function ctype_cntrl($text) - { - $text = self::convert_int_to_char_for_ctype($text); - - return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text); - } - - /** - * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise. - * - * @see https://php.net/ctype-digit - * - * @param string|int $text - * - * @return bool - */ - public static function ctype_digit($text) - { - $text = self::convert_int_to_char_for_ctype($text); - - return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text); - } - - /** - * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise. - * - * @see https://php.net/ctype-graph - * - * @param string|int $text - * - * @return bool - */ - public static function ctype_graph($text) - { - $text = self::convert_int_to_char_for_ctype($text); - - return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text); - } - - /** - * Returns TRUE if every character in text is a lowercase letter. - * - * @see https://php.net/ctype-lower - * - * @param string|int $text - * - * @return bool - */ - public static function ctype_lower($text) - { - $text = self::convert_int_to_char_for_ctype($text); - - return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text); - } - - /** - * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all. - * - * @see https://php.net/ctype-print - * - * @param string|int $text - * - * @return bool - */ - public static function ctype_print($text) - { - $text = self::convert_int_to_char_for_ctype($text); - - return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text); - } - - /** - * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise. - * - * @see https://php.net/ctype-punct - * - * @param string|int $text - * - * @return bool - */ - public static function ctype_punct($text) - { - $text = self::convert_int_to_char_for_ctype($text); - - return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text); - } - - /** - * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters. - * - * @see https://php.net/ctype-space - * - * @param string|int $text - * - * @return bool - */ - public static function ctype_space($text) - { - $text = self::convert_int_to_char_for_ctype($text); - - return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text); - } - - /** - * Returns TRUE if every character in text is an uppercase letter. - * - * @see https://php.net/ctype-upper - * - * @param string|int $text - * - * @return bool - */ - public static function ctype_upper($text) - { - $text = self::convert_int_to_char_for_ctype($text); - - return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text); - } - - /** - * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise. - * - * @see https://php.net/ctype-xdigit - * - * @param string|int $text - * - * @return bool - */ - public static function ctype_xdigit($text) - { - $text = self::convert_int_to_char_for_ctype($text); - - return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text); - } - - /** - * Converts integers to their char versions according to normal ctype behaviour, if needed. - * - * If an integer between -128 and 255 inclusive is provided, - * it is interpreted as the ASCII value of a single character - * (negative values have 256 added in order to allow characters in the Extended ASCII range). - * Any other integer is interpreted as a string containing the decimal digits of the integer. - * - * @param string|int $int - * - * @return mixed - */ - private static function convert_int_to_char_for_ctype($int) - { - if (!\is_int($int)) { - return $int; - } - - if ($int < -128 || $int > 255) { - return (string) $int; - } - - if ($int < 0) { - $int += 256; - } - - return \chr($int); - } -} diff --git a/vendor/symfony/polyfill-ctype/LICENSE b/vendor/symfony/polyfill-ctype/LICENSE deleted file mode 100644 index 3f853aa..0000000 --- a/vendor/symfony/polyfill-ctype/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2018-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/polyfill-ctype/README.md b/vendor/symfony/polyfill-ctype/README.md deleted file mode 100644 index 8add1ab..0000000 --- a/vendor/symfony/polyfill-ctype/README.md +++ /dev/null @@ -1,12 +0,0 @@ -Symfony Polyfill / Ctype -======================== - -This component provides `ctype_*` functions to users who run php versions without the ctype extension. - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-ctype/bootstrap.php b/vendor/symfony/polyfill-ctype/bootstrap.php deleted file mode 100644 index 14d1d0f..0000000 --- a/vendor/symfony/polyfill-ctype/bootstrap.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Ctype as p; - -if (!function_exists('ctype_alnum')) { - function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); } - function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); } - function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); } - function ctype_digit($text) { return p\Ctype::ctype_digit($text); } - function ctype_graph($text) { return p\Ctype::ctype_graph($text); } - function ctype_lower($text) { return p\Ctype::ctype_lower($text); } - function ctype_print($text) { return p\Ctype::ctype_print($text); } - function ctype_punct($text) { return p\Ctype::ctype_punct($text); } - function ctype_space($text) { return p\Ctype::ctype_space($text); } - function ctype_upper($text) { return p\Ctype::ctype_upper($text); } - function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); } -} diff --git a/vendor/symfony/polyfill-ctype/composer.json b/vendor/symfony/polyfill-ctype/composer.json deleted file mode 100644 index 2a2ea04..0000000 --- a/vendor/symfony/polyfill-ctype/composer.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "symfony/polyfill-ctype", - "type": "library", - "description": "Symfony polyfill for ctype functions", - "keywords": ["polyfill", "compatibility", "portable", "ctype"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=5.3.3" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" }, - "files": [ "bootstrap.php" ] - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "1.13-dev" - } - } -} diff --git a/vendor/symfony/polyfill-intl-idn/Idn.php b/vendor/symfony/polyfill-intl-idn/Idn.php deleted file mode 100644 index adb718d..0000000 --- a/vendor/symfony/polyfill-intl-idn/Idn.php +++ /dev/null @@ -1,283 +0,0 @@ - - * @author Sebastian Kroczek - * @author Dmitry Lukashin - * @author Laurent Bassin - * - * @internal - */ -final class Idn -{ - const INTL_IDNA_VARIANT_2003 = 0; - const INTL_IDNA_VARIANT_UTS46 = 1; - - private static $encodeTable = array( - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - ); - - private static $decodeTable = array( - 'a' => 0, 'b' => 1, 'c' => 2, 'd' => 3, 'e' => 4, 'f' => 5, - 'g' => 6, 'h' => 7, 'i' => 8, 'j' => 9, 'k' => 10, 'l' => 11, - 'm' => 12, 'n' => 13, 'o' => 14, 'p' => 15, 'q' => 16, 'r' => 17, - 's' => 18, 't' => 19, 'u' => 20, 'v' => 21, 'w' => 22, 'x' => 23, - 'y' => 24, 'z' => 25, '0' => 26, '1' => 27, '2' => 28, '3' => 29, - '4' => 30, '5' => 31, '6' => 32, '7' => 33, '8' => 34, '9' => 35, - ); - - public static function idn_to_ascii($domain, $options, $variant, &$idna_info = array()) - { - if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) { - @trigger_error('idn_to_ascii(): INTL_IDNA_VARIANT_2003 is deprecated', E_USER_DEPRECATED); - } - - if (self::INTL_IDNA_VARIANT_UTS46 === $variant) { - $domain = mb_strtolower($domain, 'utf-8'); - } - - $parts = explode('.', $domain); - - foreach ($parts as $i => &$part) { - if ('' === $part && \count($parts) > 1 + $i) { - return false; - } - if (false === $part = self::encodePart($part)) { - return false; - } - } - - $output = implode('.', $parts); - - $idna_info = array( - 'result' => \strlen($output) > 255 ? false : $output, - 'isTransitionalDifferent' => false, - 'errors' => 0, - ); - - return $idna_info['result']; - } - - public static function idn_to_utf8($domain, $options, $variant, &$idna_info = array()) - { - if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) { - @trigger_error('idn_to_utf8(): INTL_IDNA_VARIANT_2003 is deprecated', E_USER_DEPRECATED); - } - - $parts = explode('.', $domain); - - foreach ($parts as &$part) { - $length = \strlen($part); - if ($length < 1 || 63 < $length) { - continue; - } - if (0 !== strpos($part, 'xn--')) { - continue; - } - - $part = substr($part, 4); - $part = self::decodePart($part); - } - - $output = implode('.', $parts); - - $idna_info = array( - 'result' => \strlen($output) > 255 ? false : $output, - 'isTransitionalDifferent' => false, - 'errors' => 0, - ); - - return $idna_info['result']; - } - - private static function encodePart($input) - { - $codePoints = self::listCodePoints($input); - - $n = 128; - $bias = 72; - $delta = 0; - $h = $b = \count($codePoints['basic']); - - $output = ''; - foreach ($codePoints['basic'] as $code) { - $output .= mb_chr($code, 'utf-8'); - } - if ($input === $output) { - return $output; - } - if ($b > 0) { - $output .= '-'; - } - - $codePoints['nonBasic'] = array_unique($codePoints['nonBasic']); - sort($codePoints['nonBasic']); - - $i = 0; - $length = mb_strlen($input, 'utf-8'); - while ($h < $length) { - $m = $codePoints['nonBasic'][$i++]; - $delta += ($m - $n) * ($h + 1); - $n = $m; - - foreach ($codePoints['all'] as $c) { - if ($c < $n || $c < 128) { - ++$delta; - } - if ($c === $n) { - $q = $delta; - for ($k = 36;; $k += 36) { - $t = self::calculateThreshold($k, $bias); - if ($q < $t) { - break; - } - - $code = $t + (($q - $t) % (36 - $t)); - $output .= self::$encodeTable[$code]; - - $q = ($q - $t) / (36 - $t); - } - - $output .= self::$encodeTable[$q]; - $bias = self::adapt($delta, $h + 1, ($h === $b)); - $delta = 0; - ++$h; - } - } - - ++$delta; - ++$n; - } - - $output = 'xn--'.$output; - - return \strlen($output) < 1 || 63 < \strlen($output) ? false : strtolower($output); - } - - private static function listCodePoints($input) - { - $codePoints = array( - 'all' => array(), - 'basic' => array(), - 'nonBasic' => array(), - ); - - $length = mb_strlen($input, 'utf-8'); - for ($i = 0; $i < $length; ++$i) { - $char = mb_substr($input, $i, 1, 'utf-8'); - $code = mb_ord($char, 'utf-8'); - if ($code < 128) { - $codePoints['all'][] = $codePoints['basic'][] = $code; - } else { - $codePoints['all'][] = $codePoints['nonBasic'][] = $code; - } - } - - return $codePoints; - } - - private static function calculateThreshold($k, $bias) - { - if ($k <= $bias + 1) { - return 1; - } - if ($k >= $bias + 26) { - return 26; - } - - return $k - $bias; - } - - private static function adapt($delta, $numPoints, $firstTime) - { - $delta = (int) ($firstTime ? $delta / 700 : $delta / 2); - $delta += (int) ($delta / $numPoints); - - $k = 0; - while ($delta > 35 * 13) { - $delta = (int) ($delta / 35); - $k = $k + 36; - } - - return $k + (int) (36 * $delta / ($delta + 38)); - } - - private static function decodePart($input) - { - $n = 128; - $i = 0; - $bias = 72; - $output = ''; - - $pos = strrpos($input, '-'); - if (false !== $pos) { - $output = substr($input, 0, $pos++); - } else { - $pos = 0; - } - - $outputLength = \strlen($output); - $inputLength = \strlen($input); - - while ($pos < $inputLength) { - $oldi = $i; - $w = 1; - - for ($k = 36;; $k += 36) { - $digit = self::$decodeTable[$input[$pos++]]; - $i += $digit * $w; - $t = self::calculateThreshold($k, $bias); - - if ($digit < $t) { - break; - } - - $w *= 36 - $t; - } - - $bias = self::adapt($i - $oldi, ++$outputLength, 0 === $oldi); - $n = $n + (int) ($i / $outputLength); - $i = $i % $outputLength; - $output = mb_substr($output, 0, $i, 'utf-8').mb_chr($n, 'utf-8').mb_substr($output, $i, $outputLength - 1, 'utf-8'); - - ++$i; - } - - return $output; - } -} diff --git a/vendor/symfony/polyfill-intl-idn/LICENSE b/vendor/symfony/polyfill-intl-idn/LICENSE deleted file mode 100644 index 3f853aa..0000000 --- a/vendor/symfony/polyfill-intl-idn/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2018-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/polyfill-intl-idn/README.md b/vendor/symfony/polyfill-intl-idn/README.md deleted file mode 100644 index 5fd8c6e..0000000 --- a/vendor/symfony/polyfill-intl-idn/README.md +++ /dev/null @@ -1,12 +0,0 @@ -Symfony Polyfill / Intl: Idn -============================ - -This component provides `idn_to_ascii` and `idn_to_utf8` functions to users who run php versions without the intl extension. - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-intl-idn/bootstrap.php b/vendor/symfony/polyfill-intl-idn/bootstrap.php deleted file mode 100644 index c6e3921..0000000 --- a/vendor/symfony/polyfill-intl-idn/bootstrap.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Intl\Idn as p; - -if (!function_exists('idn_to_ascii')) { - define('U_IDNA_PROHIBITED_ERROR', 66560); - define('U_IDNA_ERROR_START', 66560); - define('U_IDNA_UNASSIGNED_ERROR', 66561); - define('U_IDNA_CHECK_BIDI_ERROR', 66562); - define('U_IDNA_STD3_ASCII_RULES_ERROR', 66563); - define('U_IDNA_ACE_PREFIX_ERROR', 66564); - define('U_IDNA_VERIFICATION_ERROR', 66565); - define('U_IDNA_LABEL_TOO_LONG_ERROR', 66566); - define('U_IDNA_ZERO_LENGTH_LABEL_ERROR', 66567); - define('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR', 66568); - define('U_IDNA_ERROR_LIMIT', 66569); - define('U_STRINGPREP_PROHIBITED_ERROR', 66560); - define('U_STRINGPREP_UNASSIGNED_ERROR', 66561); - define('U_STRINGPREP_CHECK_BIDI_ERROR', 66562); - define('IDNA_DEFAULT', 0); - define('IDNA_ALLOW_UNASSIGNED', 1); - define('IDNA_USE_STD3_RULES', 2); - define('IDNA_CHECK_BIDI', 4); - define('IDNA_CHECK_CONTEXTJ', 8); - define('IDNA_NONTRANSITIONAL_TO_ASCII', 16); - define('IDNA_NONTRANSITIONAL_TO_UNICODE', 32); - define('INTL_IDNA_VARIANT_2003', 0); - define('INTL_IDNA_VARIANT_UTS46', 1); - define('IDNA_ERROR_EMPTY_LABEL', 1); - define('IDNA_ERROR_LABEL_TOO_LONG', 2); - define('IDNA_ERROR_DOMAIN_NAME_TOO_LONG', 4); - define('IDNA_ERROR_LEADING_HYPHEN', 8); - define('IDNA_ERROR_TRAILING_HYPHEN', 16); - define('IDNA_ERROR_HYPHEN_3_4', 32); - define('IDNA_ERROR_LEADING_COMBINING_MARK', 64); - define('IDNA_ERROR_DISALLOWED', 128); - define('IDNA_ERROR_PUNYCODE', 256); - define('IDNA_ERROR_LABEL_HAS_DOT', 512); - define('IDNA_ERROR_INVALID_ACE_LABEL', 1024); - define('IDNA_ERROR_BIDI', 2048); - define('IDNA_ERROR_CONTEXTJ', 4096); - - if (PHP_VERSION_ID < 70400) { - function idn_to_ascii($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_2003, &$idna_info = array()) { return p\Idn::idn_to_ascii($domain, $options, $variant, $idna_info); } - function idn_to_utf8($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_2003, &$idna_info = array()) { return p\Idn::idn_to_utf8($domain, $options, $variant, $idna_info); } - } else { - function idn_to_ascii($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = array()) { return p\Idn::idn_to_ascii($domain, $options, $variant, $idna_info); } - function idn_to_utf8($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = array()) { return p\Idn::idn_to_utf8($domain, $options, $variant, $idna_info); } - } -} diff --git a/vendor/symfony/polyfill-intl-idn/composer.json b/vendor/symfony/polyfill-intl-idn/composer.json deleted file mode 100644 index 428c13e..0000000 --- a/vendor/symfony/polyfill-intl-idn/composer.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "symfony/polyfill-intl-idn", - "type": "library", - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", - "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "idn"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=5.3.3", - "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php72": "^1.9" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Intl\\Idn\\": "" }, - "files": [ "bootstrap.php" ] - }, - "suggest": { - "ext-intl": "For best performance" - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "1.13-dev" - } - } -} diff --git a/vendor/symfony/polyfill-mbstring/LICENSE b/vendor/symfony/polyfill-mbstring/LICENSE deleted file mode 100644 index 4cd8bdd..0000000 --- a/vendor/symfony/polyfill-mbstring/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2015-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/polyfill-mbstring/Mbstring.php b/vendor/symfony/polyfill-mbstring/Mbstring.php deleted file mode 100644 index bf882ba..0000000 --- a/vendor/symfony/polyfill-mbstring/Mbstring.php +++ /dev/null @@ -1,840 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Mbstring; - -/** - * Partial mbstring implementation in PHP, iconv based, UTF-8 centric. - * - * Implemented: - * - mb_chr - Returns a specific character from its Unicode code point - * - mb_convert_encoding - Convert character encoding - * - mb_convert_variables - Convert character code in variable(s) - * - mb_decode_mimeheader - Decode string in MIME header field - * - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED - * - mb_decode_numericentity - Decode HTML numeric string reference to character - * - mb_encode_numericentity - Encode character to HTML numeric string reference - * - mb_convert_case - Perform case folding on a string - * - mb_detect_encoding - Detect character encoding - * - mb_get_info - Get internal settings of mbstring - * - mb_http_input - Detect HTTP input character encoding - * - mb_http_output - Set/Get HTTP output character encoding - * - mb_internal_encoding - Set/Get internal character encoding - * - mb_list_encodings - Returns an array of all supported encodings - * - mb_ord - Returns the Unicode code point of a character - * - mb_output_handler - Callback function converts character encoding in output buffer - * - mb_scrub - Replaces ill-formed byte sequences with substitute characters - * - mb_strlen - Get string length - * - mb_strpos - Find position of first occurrence of string in a string - * - mb_strrpos - Find position of last occurrence of a string in a string - * - mb_str_split - Convert a string to an array - * - mb_strtolower - Make a string lowercase - * - mb_strtoupper - Make a string uppercase - * - mb_substitute_character - Set/Get substitution character - * - mb_substr - Get part of string - * - mb_stripos - Finds position of first occurrence of a string within another, case insensitive - * - mb_stristr - Finds first occurrence of a string within another, case insensitive - * - mb_strrchr - Finds the last occurrence of a character in a string within another - * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive - * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive - * - mb_strstr - Finds first occurrence of a string within another - * - mb_strwidth - Return width of string - * - mb_substr_count - Count the number of substring occurrences - * - * Not implemented: - * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more) - * - mb_ereg_* - Regular expression with multibyte support - * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable - * - mb_preferred_mime_name - Get MIME charset string - * - mb_regex_encoding - Returns current encoding for multibyte regex as string - * - mb_regex_set_options - Set/Get the default options for mbregex functions - * - mb_send_mail - Send encoded mail - * - mb_split - Split multibyte string using regular expression - * - mb_strcut - Get part of string - * - mb_strimwidth - Get truncated string with specified width - * - * @author Nicolas Grekas - * - * @internal - */ -final class Mbstring -{ - const MB_CASE_FOLD = PHP_INT_MAX; - - private static $encodingList = array('ASCII', 'UTF-8'); - private static $language = 'neutral'; - private static $internalEncoding = 'UTF-8'; - private static $caseFold = array( - array('µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"), - array('μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'), - ); - - public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) - { - if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) { - $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); - } else { - $fromEncoding = self::getEncoding($fromEncoding); - } - - $toEncoding = self::getEncoding($toEncoding); - - if ('BASE64' === $fromEncoding) { - $s = base64_decode($s); - $fromEncoding = $toEncoding; - } - - if ('BASE64' === $toEncoding) { - return base64_encode($s); - } - - if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) { - if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) { - $fromEncoding = 'Windows-1252'; - } - if ('UTF-8' !== $fromEncoding) { - $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s); - } - - return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s); - } - - if ('HTML-ENTITIES' === $fromEncoding) { - $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8'); - $fromEncoding = 'UTF-8'; - } - - return iconv($fromEncoding, $toEncoding.'//IGNORE', $s); - } - - public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) - { - $vars = array(&$a, &$b, &$c, &$d, &$e, &$f); - - $ok = true; - array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) { - if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) { - $ok = false; - } - }); - - return $ok ? $fromEncoding : false; - } - - public static function mb_decode_mimeheader($s) - { - return iconv_mime_decode($s, 2, self::$internalEncoding); - } - - public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null) - { - trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING); - } - - public static function mb_decode_numericentity($s, $convmap, $encoding = null) - { - if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) { - trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING); - - return null; - } - - if (!\is_array($convmap) || !$convmap) { - return false; - } - - if (null !== $encoding && !\is_scalar($encoding)) { - trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING); - - return ''; // Instead of null (cf. mb_encode_numericentity). - } - - $s = (string) $s; - if ('' === $s) { - return ''; - } - - $encoding = self::getEncoding($encoding); - - if ('UTF-8' === $encoding) { - $encoding = null; - if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); - } - } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); - } - - $cnt = floor(\count($convmap) / 4) * 4; - - for ($i = 0; $i < $cnt; $i += 4) { - // collector_decode_htmlnumericentity ignores $convmap[$i + 3] - $convmap[$i] += $convmap[$i + 2]; - $convmap[$i + 1] += $convmap[$i + 2]; - } - - $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) { - $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1]; - for ($i = 0; $i < $cnt; $i += 4) { - if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) { - return Mbstring::mb_chr($c - $convmap[$i + 2]); - } - } - - return $m[0]; - }, $s); - - if (null === $encoding) { - return $s; - } - - return iconv('UTF-8', $encoding.'//IGNORE', $s); - } - - public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false) - { - if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) { - trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING); - - return null; - } - - if (!\is_array($convmap) || !$convmap) { - return false; - } - - if (null !== $encoding && !\is_scalar($encoding)) { - trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING); - - return null; // Instead of '' (cf. mb_decode_numericentity). - } - - if (null !== $is_hex && !\is_scalar($is_hex)) { - trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', E_USER_WARNING); - - return null; - } - - $s = (string) $s; - if ('' === $s) { - return ''; - } - - $encoding = self::getEncoding($encoding); - - if ('UTF-8' === $encoding) { - $encoding = null; - if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); - } - } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); - } - - static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4); - - $cnt = floor(\count($convmap) / 4) * 4; - $i = 0; - $len = \strlen($s); - $result = ''; - - while ($i < $len) { - $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; - $uchr = substr($s, $i, $ulen); - $i += $ulen; - $c = self::mb_ord($uchr); - - for ($j = 0; $j < $cnt; $j += 4) { - if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) { - $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3]; - $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';'; - continue 2; - } - } - $result .= $uchr; - } - - if (null === $encoding) { - return $result; - } - - return iconv('UTF-8', $encoding.'//IGNORE', $result); - } - - public static function mb_convert_case($s, $mode, $encoding = null) - { - $s = (string) $s; - if ('' === $s) { - return ''; - } - - $encoding = self::getEncoding($encoding); - - if ('UTF-8' === $encoding) { - $encoding = null; - if (!preg_match('//u', $s)) { - $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s); - } - } else { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); - } - - if (MB_CASE_TITLE == $mode) { - static $titleRegexp = null; - if (null === $titleRegexp) { - $titleRegexp = self::getData('titleCaseRegexp'); - } - $s = preg_replace_callback($titleRegexp, array(__CLASS__, 'title_case'), $s); - } else { - if (MB_CASE_UPPER == $mode) { - static $upper = null; - if (null === $upper) { - $upper = self::getData('upperCase'); - } - $map = $upper; - } else { - if (self::MB_CASE_FOLD === $mode) { - $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s); - } - - static $lower = null; - if (null === $lower) { - $lower = self::getData('lowerCase'); - } - $map = $lower; - } - - static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4); - - $i = 0; - $len = \strlen($s); - - while ($i < $len) { - $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; - $uchr = substr($s, $i, $ulen); - $i += $ulen; - - if (isset($map[$uchr])) { - $uchr = $map[$uchr]; - $nlen = \strlen($uchr); - - if ($nlen == $ulen) { - $nlen = $i; - do { - $s[--$nlen] = $uchr[--$ulen]; - } while ($ulen); - } else { - $s = substr_replace($s, $uchr, $i - $ulen, $ulen); - $len += $nlen - $ulen; - $i += $nlen - $ulen; - } - } - } - } - - if (null === $encoding) { - return $s; - } - - return iconv('UTF-8', $encoding.'//IGNORE', $s); - } - - public static function mb_internal_encoding($encoding = null) - { - if (null === $encoding) { - return self::$internalEncoding; - } - - $encoding = self::getEncoding($encoding); - - if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) { - self::$internalEncoding = $encoding; - - return true; - } - - return false; - } - - public static function mb_language($lang = null) - { - if (null === $lang) { - return self::$language; - } - - switch ($lang = strtolower($lang)) { - case 'uni': - case 'neutral': - self::$language = $lang; - - return true; - } - - return false; - } - - public static function mb_list_encodings() - { - return array('UTF-8'); - } - - public static function mb_encoding_aliases($encoding) - { - switch (strtoupper($encoding)) { - case 'UTF8': - case 'UTF-8': - return array('utf8'); - } - - return false; - } - - public static function mb_check_encoding($var = null, $encoding = null) - { - if (null === $encoding) { - if (null === $var) { - return false; - } - $encoding = self::$internalEncoding; - } - - return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var); - } - - public static function mb_detect_encoding($str, $encodingList = null, $strict = false) - { - if (null === $encodingList) { - $encodingList = self::$encodingList; - } else { - if (!\is_array($encodingList)) { - $encodingList = array_map('trim', explode(',', $encodingList)); - } - $encodingList = array_map('strtoupper', $encodingList); - } - - foreach ($encodingList as $enc) { - switch ($enc) { - case 'ASCII': - if (!preg_match('/[\x80-\xFF]/', $str)) { - return $enc; - } - break; - - case 'UTF8': - case 'UTF-8': - if (preg_match('//u', $str)) { - return 'UTF-8'; - } - break; - - default: - if (0 === strncmp($enc, 'ISO-8859-', 9)) { - return $enc; - } - } - } - - return false; - } - - public static function mb_detect_order($encodingList = null) - { - if (null === $encodingList) { - return self::$encodingList; - } - - if (!\is_array($encodingList)) { - $encodingList = array_map('trim', explode(',', $encodingList)); - } - $encodingList = array_map('strtoupper', $encodingList); - - foreach ($encodingList as $enc) { - switch ($enc) { - default: - if (strncmp($enc, 'ISO-8859-', 9)) { - return false; - } - // no break - case 'ASCII': - case 'UTF8': - case 'UTF-8': - } - } - - self::$encodingList = $encodingList; - - return true; - } - - public static function mb_strlen($s, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - return \strlen($s); - } - - return @iconv_strlen($s, $encoding); - } - - public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - return strpos($haystack, $needle, $offset); - } - - $needle = (string) $needle; - if ('' === $needle) { - trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING); - - return false; - } - - return iconv_strpos($haystack, $needle, $offset, $encoding); - } - - public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - return strrpos($haystack, $needle, $offset); - } - - if ($offset != (int) $offset) { - $offset = 0; - } elseif ($offset = (int) $offset) { - if ($offset < 0) { - if (0 > $offset += self::mb_strlen($needle)) { - $haystack = self::mb_substr($haystack, 0, $offset, $encoding); - } - $offset = 0; - } else { - $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding); - } - } - - $pos = iconv_strrpos($haystack, $needle, $encoding); - - return false !== $pos ? $offset + $pos : false; - } - - public static function mb_str_split($string, $split_length = 1, $encoding = null) - { - if (null !== $string && !\is_scalar($string) && !(\is_object($string) && \method_exists($string, '__toString'))) { - trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', E_USER_WARNING); - - return null; - } - - if (1 > $split_length = (int) $split_length) { - trigger_error('The length of each segment must be greater than zero', E_USER_WARNING); - - return false; - } - - if (null === $encoding) { - $encoding = mb_internal_encoding(); - } - - if ('UTF-8' === $encoding = self::getEncoding($encoding)) { - return preg_split("/(.{{$split_length}})/u", $string, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); - } - - $result = array(); - $length = mb_strlen($string, $encoding); - - for ($i = 0; $i < $length; $i += $split_length) { - $result[] = mb_substr($string, $i, $split_length, $encoding); - } - - return $result; - } - - public static function mb_strtolower($s, $encoding = null) - { - return self::mb_convert_case($s, MB_CASE_LOWER, $encoding); - } - - public static function mb_strtoupper($s, $encoding = null) - { - return self::mb_convert_case($s, MB_CASE_UPPER, $encoding); - } - - public static function mb_substitute_character($c = null) - { - if (0 === strcasecmp($c, 'none')) { - return true; - } - - return null !== $c ? false : 'none'; - } - - public static function mb_substr($s, $start, $length = null, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - return (string) substr($s, $start, null === $length ? 2147483647 : $length); - } - - if ($start < 0) { - $start = iconv_strlen($s, $encoding) + $start; - if ($start < 0) { - $start = 0; - } - } - - if (null === $length) { - $length = 2147483647; - } elseif ($length < 0) { - $length = iconv_strlen($s, $encoding) + $length - $start; - if ($length < 0) { - return ''; - } - } - - return (string) iconv_substr($s, $start, $length, $encoding); - } - - public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) - { - $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); - $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); - - return self::mb_strpos($haystack, $needle, $offset, $encoding); - } - - public static function mb_stristr($haystack, $needle, $part = false, $encoding = null) - { - $pos = self::mb_stripos($haystack, $needle, 0, $encoding); - - return self::getSubpart($pos, $part, $haystack, $encoding); - } - - public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null) - { - $encoding = self::getEncoding($encoding); - if ('CP850' === $encoding || 'ASCII' === $encoding) { - return strrchr($haystack, $needle, $part); - } - $needle = self::mb_substr($needle, 0, 1, $encoding); - $pos = iconv_strrpos($haystack, $needle, $encoding); - - return self::getSubpart($pos, $part, $haystack, $encoding); - } - - public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null) - { - $needle = self::mb_substr($needle, 0, 1, $encoding); - $pos = self::mb_strripos($haystack, $needle, $encoding); - - return self::getSubpart($pos, $part, $haystack, $encoding); - } - - public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) - { - $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); - $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); - - return self::mb_strrpos($haystack, $needle, $offset, $encoding); - } - - public static function mb_strstr($haystack, $needle, $part = false, $encoding = null) - { - $pos = strpos($haystack, $needle); - if (false === $pos) { - return false; - } - if ($part) { - return substr($haystack, 0, $pos); - } - - return substr($haystack, $pos); - } - - public static function mb_get_info($type = 'all') - { - $info = array( - 'internal_encoding' => self::$internalEncoding, - 'http_output' => 'pass', - 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)', - 'func_overload' => 0, - 'func_overload_list' => 'no overload', - 'mail_charset' => 'UTF-8', - 'mail_header_encoding' => 'BASE64', - 'mail_body_encoding' => 'BASE64', - 'illegal_chars' => 0, - 'encoding_translation' => 'Off', - 'language' => self::$language, - 'detect_order' => self::$encodingList, - 'substitute_character' => 'none', - 'strict_detection' => 'Off', - ); - - if ('all' === $type) { - return $info; - } - if (isset($info[$type])) { - return $info[$type]; - } - - return false; - } - - public static function mb_http_input($type = '') - { - return false; - } - - public static function mb_http_output($encoding = null) - { - return null !== $encoding ? 'pass' === $encoding : 'pass'; - } - - public static function mb_strwidth($s, $encoding = null) - { - $encoding = self::getEncoding($encoding); - - if ('UTF-8' !== $encoding) { - $s = iconv($encoding, 'UTF-8//IGNORE', $s); - } - - $s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide); - - return ($wide << 1) + iconv_strlen($s, 'UTF-8'); - } - - public static function mb_substr_count($haystack, $needle, $encoding = null) - { - return substr_count($haystack, $needle); - } - - public static function mb_output_handler($contents, $status) - { - return $contents; - } - - public static function mb_chr($code, $encoding = null) - { - if (0x80 > $code %= 0x200000) { - $s = \chr($code); - } elseif (0x800 > $code) { - $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); - } elseif (0x10000 > $code) { - $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); - } else { - $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); - } - - if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { - $s = mb_convert_encoding($s, $encoding, 'UTF-8'); - } - - return $s; - } - - public static function mb_ord($s, $encoding = null) - { - if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { - $s = mb_convert_encoding($s, 'UTF-8', $encoding); - } - - if (1 === \strlen($s)) { - return \ord($s); - } - - $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; - if (0xF0 <= $code) { - return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; - } - if (0xE0 <= $code) { - return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; - } - if (0xC0 <= $code) { - return (($code - 0xC0) << 6) + $s[2] - 0x80; - } - - return $code; - } - - private static function getSubpart($pos, $part, $haystack, $encoding) - { - if (false === $pos) { - return false; - } - if ($part) { - return self::mb_substr($haystack, 0, $pos, $encoding); - } - - return self::mb_substr($haystack, $pos, null, $encoding); - } - - private static function html_encoding_callback(array $m) - { - $i = 1; - $entities = ''; - $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8')); - - while (isset($m[$i])) { - if (0x80 > $m[$i]) { - $entities .= \chr($m[$i++]); - continue; - } - if (0xF0 <= $m[$i]) { - $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; - } elseif (0xE0 <= $m[$i]) { - $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; - } else { - $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80; - } - - $entities .= '&#'.$c.';'; - } - - return $entities; - } - - private static function title_case(array $s) - { - return self::mb_convert_case($s[1], MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], MB_CASE_LOWER, 'UTF-8'); - } - - private static function getData($file) - { - if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) { - return require $file; - } - - return false; - } - - private static function getEncoding($encoding) - { - if (null === $encoding) { - return self::$internalEncoding; - } - - if ('UTF-8' === $encoding) { - return 'UTF-8'; - } - - $encoding = strtoupper($encoding); - - if ('8BIT' === $encoding || 'BINARY' === $encoding) { - return 'CP850'; - } - - if ('UTF8' === $encoding) { - return 'UTF-8'; - } - - return $encoding; - } -} diff --git a/vendor/symfony/polyfill-mbstring/README.md b/vendor/symfony/polyfill-mbstring/README.md deleted file mode 100644 index 342e828..0000000 --- a/vendor/symfony/polyfill-mbstring/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Symfony Polyfill / Mbstring -=========================== - -This component provides a partial, native PHP implementation for the -[Mbstring](http://php.net/mbstring) extension. - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php deleted file mode 100644 index e6fbfa6..0000000 --- a/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php +++ /dev/null @@ -1,1096 +0,0 @@ - 'a', - 'B' => 'b', - 'C' => 'c', - 'D' => 'd', - 'E' => 'e', - 'F' => 'f', - 'G' => 'g', - 'H' => 'h', - 'I' => 'i', - 'J' => 'j', - 'K' => 'k', - 'L' => 'l', - 'M' => 'm', - 'N' => 'n', - 'O' => 'o', - 'P' => 'p', - 'Q' => 'q', - 'R' => 'r', - 'S' => 's', - 'T' => 't', - 'U' => 'u', - 'V' => 'v', - 'W' => 'w', - 'X' => 'x', - 'Y' => 'y', - 'Z' => 'z', - 'À' => 'à', - 'Á' => 'á', - 'Â' => 'â', - 'Ã' => 'ã', - 'Ä' => 'ä', - 'Å' => 'å', - 'Æ' => 'æ', - 'Ç' => 'ç', - 'È' => 'è', - 'É' => 'é', - 'Ê' => 'ê', - 'Ë' => 'ë', - 'Ì' => 'ì', - 'Í' => 'í', - 'Î' => 'î', - 'Ï' => 'ï', - 'Ð' => 'ð', - 'Ñ' => 'ñ', - 'Ò' => 'ò', - 'Ó' => 'ó', - 'Ô' => 'ô', - 'Õ' => 'õ', - 'Ö' => 'ö', - 'Ø' => 'ø', - 'Ù' => 'ù', - 'Ú' => 'ú', - 'Û' => 'û', - 'Ü' => 'ü', - 'Ý' => 'ý', - 'Þ' => 'þ', - 'Ā' => 'ā', - 'Ă' => 'ă', - 'Ą' => 'ą', - 'Ć' => 'ć', - 'Ĉ' => 'ĉ', - 'Ċ' => 'ċ', - 'Č' => 'č', - 'Ď' => 'ď', - 'Đ' => 'đ', - 'Ē' => 'ē', - 'Ĕ' => 'ĕ', - 'Ė' => 'ė', - 'Ę' => 'ę', - 'Ě' => 'ě', - 'Ĝ' => 'ĝ', - 'Ğ' => 'ğ', - 'Ġ' => 'ġ', - 'Ģ' => 'ģ', - 'Ĥ' => 'ĥ', - 'Ħ' => 'ħ', - 'Ĩ' => 'ĩ', - 'Ī' => 'ī', - 'Ĭ' => 'ĭ', - 'Į' => 'į', - 'İ' => 'i', - 'IJ' => 'ij', - 'Ĵ' => 'ĵ', - 'Ķ' => 'ķ', - 'Ĺ' => 'ĺ', - 'Ļ' => 'ļ', - 'Ľ' => 'ľ', - 'Ŀ' => 'ŀ', - 'Ł' => 'ł', - 'Ń' => 'ń', - 'Ņ' => 'ņ', - 'Ň' => 'ň', - 'Ŋ' => 'ŋ', - 'Ō' => 'ō', - 'Ŏ' => 'ŏ', - 'Ő' => 'ő', - 'Œ' => 'œ', - 'Ŕ' => 'ŕ', - 'Ŗ' => 'ŗ', - 'Ř' => 'ř', - 'Ś' => 'ś', - 'Ŝ' => 'ŝ', - 'Ş' => 'ş', - 'Š' => 'š', - 'Ţ' => 'ţ', - 'Ť' => 'ť', - 'Ŧ' => 'ŧ', - 'Ũ' => 'ũ', - 'Ū' => 'ū', - 'Ŭ' => 'ŭ', - 'Ů' => 'ů', - 'Ű' => 'ű', - 'Ų' => 'ų', - 'Ŵ' => 'ŵ', - 'Ŷ' => 'ŷ', - 'Ÿ' => 'ÿ', - 'Ź' => 'ź', - 'Ż' => 'ż', - 'Ž' => 'ž', - 'Ɓ' => 'ɓ', - 'Ƃ' => 'ƃ', - 'Ƅ' => 'ƅ', - 'Ɔ' => 'ɔ', - 'Ƈ' => 'ƈ', - 'Ɖ' => 'ɖ', - 'Ɗ' => 'ɗ', - 'Ƌ' => 'ƌ', - 'Ǝ' => 'ǝ', - 'Ə' => 'ə', - 'Ɛ' => 'ɛ', - 'Ƒ' => 'ƒ', - 'Ɠ' => 'ɠ', - 'Ɣ' => 'ɣ', - 'Ɩ' => 'ɩ', - 'Ɨ' => 'ɨ', - 'Ƙ' => 'ƙ', - 'Ɯ' => 'ɯ', - 'Ɲ' => 'ɲ', - 'Ɵ' => 'ɵ', - 'Ơ' => 'ơ', - 'Ƣ' => 'ƣ', - 'Ƥ' => 'ƥ', - 'Ʀ' => 'ʀ', - 'Ƨ' => 'ƨ', - 'Ʃ' => 'ʃ', - 'Ƭ' => 'ƭ', - 'Ʈ' => 'ʈ', - 'Ư' => 'ư', - 'Ʊ' => 'ʊ', - 'Ʋ' => 'ʋ', - 'Ƴ' => 'ƴ', - 'Ƶ' => 'ƶ', - 'Ʒ' => 'ʒ', - 'Ƹ' => 'ƹ', - 'Ƽ' => 'ƽ', - 'DŽ' => 'dž', - 'Dž' => 'dž', - 'LJ' => 'lj', - 'Lj' => 'lj', - 'NJ' => 'nj', - 'Nj' => 'nj', - 'Ǎ' => 'ǎ', - 'Ǐ' => 'ǐ', - 'Ǒ' => 'ǒ', - 'Ǔ' => 'ǔ', - 'Ǖ' => 'ǖ', - 'Ǘ' => 'ǘ', - 'Ǚ' => 'ǚ', - 'Ǜ' => 'ǜ', - 'Ǟ' => 'ǟ', - 'Ǡ' => 'ǡ', - 'Ǣ' => 'ǣ', - 'Ǥ' => 'ǥ', - 'Ǧ' => 'ǧ', - 'Ǩ' => 'ǩ', - 'Ǫ' => 'ǫ', - 'Ǭ' => 'ǭ', - 'Ǯ' => 'ǯ', - 'DZ' => 'dz', - 'Dz' => 'dz', - 'Ǵ' => 'ǵ', - 'Ƕ' => 'ƕ', - 'Ƿ' => 'ƿ', - 'Ǹ' => 'ǹ', - 'Ǻ' => 'ǻ', - 'Ǽ' => 'ǽ', - 'Ǿ' => 'ǿ', - 'Ȁ' => 'ȁ', - 'Ȃ' => 'ȃ', - 'Ȅ' => 'ȅ', - 'Ȇ' => 'ȇ', - 'Ȉ' => 'ȉ', - 'Ȋ' => 'ȋ', - 'Ȍ' => 'ȍ', - 'Ȏ' => 'ȏ', - 'Ȑ' => 'ȑ', - 'Ȓ' => 'ȓ', - 'Ȕ' => 'ȕ', - 'Ȗ' => 'ȗ', - 'Ș' => 'ș', - 'Ț' => 'ț', - 'Ȝ' => 'ȝ', - 'Ȟ' => 'ȟ', - 'Ƞ' => 'ƞ', - 'Ȣ' => 'ȣ', - 'Ȥ' => 'ȥ', - 'Ȧ' => 'ȧ', - 'Ȩ' => 'ȩ', - 'Ȫ' => 'ȫ', - 'Ȭ' => 'ȭ', - 'Ȯ' => 'ȯ', - 'Ȱ' => 'ȱ', - 'Ȳ' => 'ȳ', - 'Ⱥ' => 'ⱥ', - 'Ȼ' => 'ȼ', - 'Ƚ' => 'ƚ', - 'Ⱦ' => 'ⱦ', - 'Ɂ' => 'ɂ', - 'Ƀ' => 'ƀ', - 'Ʉ' => 'ʉ', - 'Ʌ' => 'ʌ', - 'Ɇ' => 'ɇ', - 'Ɉ' => 'ɉ', - 'Ɋ' => 'ɋ', - 'Ɍ' => 'ɍ', - 'Ɏ' => 'ɏ', - 'Ͱ' => 'ͱ', - 'Ͳ' => 'ͳ', - 'Ͷ' => 'ͷ', - 'Ϳ' => 'ϳ', - 'Ά' => 'ά', - 'Έ' => 'έ', - 'Ή' => 'ή', - 'Ί' => 'ί', - 'Ό' => 'ό', - 'Ύ' => 'ύ', - 'Ώ' => 'ώ', - 'Α' => 'α', - 'Β' => 'β', - 'Γ' => 'γ', - 'Δ' => 'δ', - 'Ε' => 'ε', - 'Ζ' => 'ζ', - 'Η' => 'η', - 'Θ' => 'θ', - 'Ι' => 'ι', - 'Κ' => 'κ', - 'Λ' => 'λ', - 'Μ' => 'μ', - 'Ν' => 'ν', - 'Ξ' => 'ξ', - 'Ο' => 'ο', - 'Π' => 'π', - 'Ρ' => 'ρ', - 'Σ' => 'σ', - 'Τ' => 'τ', - 'Υ' => 'υ', - 'Φ' => 'φ', - 'Χ' => 'χ', - 'Ψ' => 'ψ', - 'Ω' => 'ω', - 'Ϊ' => 'ϊ', - 'Ϋ' => 'ϋ', - 'Ϗ' => 'ϗ', - 'Ϙ' => 'ϙ', - 'Ϛ' => 'ϛ', - 'Ϝ' => 'ϝ', - 'Ϟ' => 'ϟ', - 'Ϡ' => 'ϡ', - 'Ϣ' => 'ϣ', - 'Ϥ' => 'ϥ', - 'Ϧ' => 'ϧ', - 'Ϩ' => 'ϩ', - 'Ϫ' => 'ϫ', - 'Ϭ' => 'ϭ', - 'Ϯ' => 'ϯ', - 'ϴ' => 'θ', - 'Ϸ' => 'ϸ', - 'Ϲ' => 'ϲ', - 'Ϻ' => 'ϻ', - 'Ͻ' => 'ͻ', - 'Ͼ' => 'ͼ', - 'Ͽ' => 'ͽ', - 'Ѐ' => 'ѐ', - 'Ё' => 'ё', - 'Ђ' => 'ђ', - 'Ѓ' => 'ѓ', - 'Є' => 'є', - 'Ѕ' => 'ѕ', - 'І' => 'і', - 'Ї' => 'ї', - 'Ј' => 'ј', - 'Љ' => 'љ', - 'Њ' => 'њ', - 'Ћ' => 'ћ', - 'Ќ' => 'ќ', - 'Ѝ' => 'ѝ', - 'Ў' => 'ў', - 'Џ' => 'џ', - 'А' => 'а', - 'Б' => 'б', - 'В' => 'в', - 'Г' => 'г', - 'Д' => 'д', - 'Е' => 'е', - 'Ж' => 'ж', - 'З' => 'з', - 'И' => 'и', - 'Й' => 'й', - 'К' => 'к', - 'Л' => 'л', - 'М' => 'м', - 'Н' => 'н', - 'О' => 'о', - 'П' => 'п', - 'Р' => 'р', - 'С' => 'с', - 'Т' => 'т', - 'У' => 'у', - 'Ф' => 'ф', - 'Х' => 'х', - 'Ц' => 'ц', - 'Ч' => 'ч', - 'Ш' => 'ш', - 'Щ' => 'щ', - 'Ъ' => 'ъ', - 'Ы' => 'ы', - 'Ь' => 'ь', - 'Э' => 'э', - 'Ю' => 'ю', - 'Я' => 'я', - 'Ѡ' => 'ѡ', - 'Ѣ' => 'ѣ', - 'Ѥ' => 'ѥ', - 'Ѧ' => 'ѧ', - 'Ѩ' => 'ѩ', - 'Ѫ' => 'ѫ', - 'Ѭ' => 'ѭ', - 'Ѯ' => 'ѯ', - 'Ѱ' => 'ѱ', - 'Ѳ' => 'ѳ', - 'Ѵ' => 'ѵ', - 'Ѷ' => 'ѷ', - 'Ѹ' => 'ѹ', - 'Ѻ' => 'ѻ', - 'Ѽ' => 'ѽ', - 'Ѿ' => 'ѿ', - 'Ҁ' => 'ҁ', - 'Ҋ' => 'ҋ', - 'Ҍ' => 'ҍ', - 'Ҏ' => 'ҏ', - 'Ґ' => 'ґ', - 'Ғ' => 'ғ', - 'Ҕ' => 'ҕ', - 'Җ' => 'җ', - 'Ҙ' => 'ҙ', - 'Қ' => 'қ', - 'Ҝ' => 'ҝ', - 'Ҟ' => 'ҟ', - 'Ҡ' => 'ҡ', - 'Ң' => 'ң', - 'Ҥ' => 'ҥ', - 'Ҧ' => 'ҧ', - 'Ҩ' => 'ҩ', - 'Ҫ' => 'ҫ', - 'Ҭ' => 'ҭ', - 'Ү' => 'ү', - 'Ұ' => 'ұ', - 'Ҳ' => 'ҳ', - 'Ҵ' => 'ҵ', - 'Ҷ' => 'ҷ', - 'Ҹ' => 'ҹ', - 'Һ' => 'һ', - 'Ҽ' => 'ҽ', - 'Ҿ' => 'ҿ', - 'Ӏ' => 'ӏ', - 'Ӂ' => 'ӂ', - 'Ӄ' => 'ӄ', - 'Ӆ' => 'ӆ', - 'Ӈ' => 'ӈ', - 'Ӊ' => 'ӊ', - 'Ӌ' => 'ӌ', - 'Ӎ' => 'ӎ', - 'Ӑ' => 'ӑ', - 'Ӓ' => 'ӓ', - 'Ӕ' => 'ӕ', - 'Ӗ' => 'ӗ', - 'Ә' => 'ә', - 'Ӛ' => 'ӛ', - 'Ӝ' => 'ӝ', - 'Ӟ' => 'ӟ', - 'Ӡ' => 'ӡ', - 'Ӣ' => 'ӣ', - 'Ӥ' => 'ӥ', - 'Ӧ' => 'ӧ', - 'Ө' => 'ө', - 'Ӫ' => 'ӫ', - 'Ӭ' => 'ӭ', - 'Ӯ' => 'ӯ', - 'Ӱ' => 'ӱ', - 'Ӳ' => 'ӳ', - 'Ӵ' => 'ӵ', - 'Ӷ' => 'ӷ', - 'Ӹ' => 'ӹ', - 'Ӻ' => 'ӻ', - 'Ӽ' => 'ӽ', - 'Ӿ' => 'ӿ', - 'Ԁ' => 'ԁ', - 'Ԃ' => 'ԃ', - 'Ԅ' => 'ԅ', - 'Ԇ' => 'ԇ', - 'Ԉ' => 'ԉ', - 'Ԋ' => 'ԋ', - 'Ԍ' => 'ԍ', - 'Ԏ' => 'ԏ', - 'Ԑ' => 'ԑ', - 'Ԓ' => 'ԓ', - 'Ԕ' => 'ԕ', - 'Ԗ' => 'ԗ', - 'Ԙ' => 'ԙ', - 'Ԛ' => 'ԛ', - 'Ԝ' => 'ԝ', - 'Ԟ' => 'ԟ', - 'Ԡ' => 'ԡ', - 'Ԣ' => 'ԣ', - 'Ԥ' => 'ԥ', - 'Ԧ' => 'ԧ', - 'Ԩ' => 'ԩ', - 'Ԫ' => 'ԫ', - 'Ԭ' => 'ԭ', - 'Ԯ' => 'ԯ', - 'Ա' => 'ա', - 'Բ' => 'բ', - 'Գ' => 'գ', - 'Դ' => 'դ', - 'Ե' => 'ե', - 'Զ' => 'զ', - 'Է' => 'է', - 'Ը' => 'ը', - 'Թ' => 'թ', - 'Ժ' => 'ժ', - 'Ի' => 'ի', - 'Լ' => 'լ', - 'Խ' => 'խ', - 'Ծ' => 'ծ', - 'Կ' => 'կ', - 'Հ' => 'հ', - 'Ձ' => 'ձ', - 'Ղ' => 'ղ', - 'Ճ' => 'ճ', - 'Մ' => 'մ', - 'Յ' => 'յ', - 'Ն' => 'ն', - 'Շ' => 'շ', - 'Ո' => 'ո', - 'Չ' => 'չ', - 'Պ' => 'պ', - 'Ջ' => 'ջ', - 'Ռ' => 'ռ', - 'Ս' => 'ս', - 'Վ' => 'վ', - 'Տ' => 'տ', - 'Ր' => 'ր', - 'Ց' => 'ց', - 'Ւ' => 'ւ', - 'Փ' => 'փ', - 'Ք' => 'ք', - 'Օ' => 'օ', - 'Ֆ' => 'ֆ', - 'Ⴀ' => 'ⴀ', - 'Ⴁ' => 'ⴁ', - 'Ⴂ' => 'ⴂ', - 'Ⴃ' => 'ⴃ', - 'Ⴄ' => 'ⴄ', - 'Ⴅ' => 'ⴅ', - 'Ⴆ' => 'ⴆ', - 'Ⴇ' => 'ⴇ', - 'Ⴈ' => 'ⴈ', - 'Ⴉ' => 'ⴉ', - 'Ⴊ' => 'ⴊ', - 'Ⴋ' => 'ⴋ', - 'Ⴌ' => 'ⴌ', - 'Ⴍ' => 'ⴍ', - 'Ⴎ' => 'ⴎ', - 'Ⴏ' => 'ⴏ', - 'Ⴐ' => 'ⴐ', - 'Ⴑ' => 'ⴑ', - 'Ⴒ' => 'ⴒ', - 'Ⴓ' => 'ⴓ', - 'Ⴔ' => 'ⴔ', - 'Ⴕ' => 'ⴕ', - 'Ⴖ' => 'ⴖ', - 'Ⴗ' => 'ⴗ', - 'Ⴘ' => 'ⴘ', - 'Ⴙ' => 'ⴙ', - 'Ⴚ' => 'ⴚ', - 'Ⴛ' => 'ⴛ', - 'Ⴜ' => 'ⴜ', - 'Ⴝ' => 'ⴝ', - 'Ⴞ' => 'ⴞ', - 'Ⴟ' => 'ⴟ', - 'Ⴠ' => 'ⴠ', - 'Ⴡ' => 'ⴡ', - 'Ⴢ' => 'ⴢ', - 'Ⴣ' => 'ⴣ', - 'Ⴤ' => 'ⴤ', - 'Ⴥ' => 'ⴥ', - 'Ⴧ' => 'ⴧ', - 'Ⴭ' => 'ⴭ', - 'Ḁ' => 'ḁ', - 'Ḃ' => 'ḃ', - 'Ḅ' => 'ḅ', - 'Ḇ' => 'ḇ', - 'Ḉ' => 'ḉ', - 'Ḋ' => 'ḋ', - 'Ḍ' => 'ḍ', - 'Ḏ' => 'ḏ', - 'Ḑ' => 'ḑ', - 'Ḓ' => 'ḓ', - 'Ḕ' => 'ḕ', - 'Ḗ' => 'ḗ', - 'Ḙ' => 'ḙ', - 'Ḛ' => 'ḛ', - 'Ḝ' => 'ḝ', - 'Ḟ' => 'ḟ', - 'Ḡ' => 'ḡ', - 'Ḣ' => 'ḣ', - 'Ḥ' => 'ḥ', - 'Ḧ' => 'ḧ', - 'Ḩ' => 'ḩ', - 'Ḫ' => 'ḫ', - 'Ḭ' => 'ḭ', - 'Ḯ' => 'ḯ', - 'Ḱ' => 'ḱ', - 'Ḳ' => 'ḳ', - 'Ḵ' => 'ḵ', - 'Ḷ' => 'ḷ', - 'Ḹ' => 'ḹ', - 'Ḻ' => 'ḻ', - 'Ḽ' => 'ḽ', - 'Ḿ' => 'ḿ', - 'Ṁ' => 'ṁ', - 'Ṃ' => 'ṃ', - 'Ṅ' => 'ṅ', - 'Ṇ' => 'ṇ', - 'Ṉ' => 'ṉ', - 'Ṋ' => 'ṋ', - 'Ṍ' => 'ṍ', - 'Ṏ' => 'ṏ', - 'Ṑ' => 'ṑ', - 'Ṓ' => 'ṓ', - 'Ṕ' => 'ṕ', - 'Ṗ' => 'ṗ', - 'Ṙ' => 'ṙ', - 'Ṛ' => 'ṛ', - 'Ṝ' => 'ṝ', - 'Ṟ' => 'ṟ', - 'Ṡ' => 'ṡ', - 'Ṣ' => 'ṣ', - 'Ṥ' => 'ṥ', - 'Ṧ' => 'ṧ', - 'Ṩ' => 'ṩ', - 'Ṫ' => 'ṫ', - 'Ṭ' => 'ṭ', - 'Ṯ' => 'ṯ', - 'Ṱ' => 'ṱ', - 'Ṳ' => 'ṳ', - 'Ṵ' => 'ṵ', - 'Ṷ' => 'ṷ', - 'Ṹ' => 'ṹ', - 'Ṻ' => 'ṻ', - 'Ṽ' => 'ṽ', - 'Ṿ' => 'ṿ', - 'Ẁ' => 'ẁ', - 'Ẃ' => 'ẃ', - 'Ẅ' => 'ẅ', - 'Ẇ' => 'ẇ', - 'Ẉ' => 'ẉ', - 'Ẋ' => 'ẋ', - 'Ẍ' => 'ẍ', - 'Ẏ' => 'ẏ', - 'Ẑ' => 'ẑ', - 'Ẓ' => 'ẓ', - 'Ẕ' => 'ẕ', - 'ẞ' => 'ß', - 'Ạ' => 'ạ', - 'Ả' => 'ả', - 'Ấ' => 'ấ', - 'Ầ' => 'ầ', - 'Ẩ' => 'ẩ', - 'Ẫ' => 'ẫ', - 'Ậ' => 'ậ', - 'Ắ' => 'ắ', - 'Ằ' => 'ằ', - 'Ẳ' => 'ẳ', - 'Ẵ' => 'ẵ', - 'Ặ' => 'ặ', - 'Ẹ' => 'ẹ', - 'Ẻ' => 'ẻ', - 'Ẽ' => 'ẽ', - 'Ế' => 'ế', - 'Ề' => 'ề', - 'Ể' => 'ể', - 'Ễ' => 'ễ', - 'Ệ' => 'ệ', - 'Ỉ' => 'ỉ', - 'Ị' => 'ị', - 'Ọ' => 'ọ', - 'Ỏ' => 'ỏ', - 'Ố' => 'ố', - 'Ồ' => 'ồ', - 'Ổ' => 'ổ', - 'Ỗ' => 'ỗ', - 'Ộ' => 'ộ', - 'Ớ' => 'ớ', - 'Ờ' => 'ờ', - 'Ở' => 'ở', - 'Ỡ' => 'ỡ', - 'Ợ' => 'ợ', - 'Ụ' => 'ụ', - 'Ủ' => 'ủ', - 'Ứ' => 'ứ', - 'Ừ' => 'ừ', - 'Ử' => 'ử', - 'Ữ' => 'ữ', - 'Ự' => 'ự', - 'Ỳ' => 'ỳ', - 'Ỵ' => 'ỵ', - 'Ỷ' => 'ỷ', - 'Ỹ' => 'ỹ', - 'Ỻ' => 'ỻ', - 'Ỽ' => 'ỽ', - 'Ỿ' => 'ỿ', - 'Ἀ' => 'ἀ', - 'Ἁ' => 'ἁ', - 'Ἂ' => 'ἂ', - 'Ἃ' => 'ἃ', - 'Ἄ' => 'ἄ', - 'Ἅ' => 'ἅ', - 'Ἆ' => 'ἆ', - 'Ἇ' => 'ἇ', - 'Ἐ' => 'ἐ', - 'Ἑ' => 'ἑ', - 'Ἒ' => 'ἒ', - 'Ἓ' => 'ἓ', - 'Ἔ' => 'ἔ', - 'Ἕ' => 'ἕ', - 'Ἠ' => 'ἠ', - 'Ἡ' => 'ἡ', - 'Ἢ' => 'ἢ', - 'Ἣ' => 'ἣ', - 'Ἤ' => 'ἤ', - 'Ἥ' => 'ἥ', - 'Ἦ' => 'ἦ', - 'Ἧ' => 'ἧ', - 'Ἰ' => 'ἰ', - 'Ἱ' => 'ἱ', - 'Ἲ' => 'ἲ', - 'Ἳ' => 'ἳ', - 'Ἴ' => 'ἴ', - 'Ἵ' => 'ἵ', - 'Ἶ' => 'ἶ', - 'Ἷ' => 'ἷ', - 'Ὀ' => 'ὀ', - 'Ὁ' => 'ὁ', - 'Ὂ' => 'ὂ', - 'Ὃ' => 'ὃ', - 'Ὄ' => 'ὄ', - 'Ὅ' => 'ὅ', - 'Ὑ' => 'ὑ', - 'Ὓ' => 'ὓ', - 'Ὕ' => 'ὕ', - 'Ὗ' => 'ὗ', - 'Ὠ' => 'ὠ', - 'Ὡ' => 'ὡ', - 'Ὢ' => 'ὢ', - 'Ὣ' => 'ὣ', - 'Ὤ' => 'ὤ', - 'Ὥ' => 'ὥ', - 'Ὦ' => 'ὦ', - 'Ὧ' => 'ὧ', - 'ᾈ' => 'ᾀ', - 'ᾉ' => 'ᾁ', - 'ᾊ' => 'ᾂ', - 'ᾋ' => 'ᾃ', - 'ᾌ' => 'ᾄ', - 'ᾍ' => 'ᾅ', - 'ᾎ' => 'ᾆ', - 'ᾏ' => 'ᾇ', - 'ᾘ' => 'ᾐ', - 'ᾙ' => 'ᾑ', - 'ᾚ' => 'ᾒ', - 'ᾛ' => 'ᾓ', - 'ᾜ' => 'ᾔ', - 'ᾝ' => 'ᾕ', - 'ᾞ' => 'ᾖ', - 'ᾟ' => 'ᾗ', - 'ᾨ' => 'ᾠ', - 'ᾩ' => 'ᾡ', - 'ᾪ' => 'ᾢ', - 'ᾫ' => 'ᾣ', - 'ᾬ' => 'ᾤ', - 'ᾭ' => 'ᾥ', - 'ᾮ' => 'ᾦ', - 'ᾯ' => 'ᾧ', - 'Ᾰ' => 'ᾰ', - 'Ᾱ' => 'ᾱ', - 'Ὰ' => 'ὰ', - 'Ά' => 'ά', - 'ᾼ' => 'ᾳ', - 'Ὲ' => 'ὲ', - 'Έ' => 'έ', - 'Ὴ' => 'ὴ', - 'Ή' => 'ή', - 'ῌ' => 'ῃ', - 'Ῐ' => 'ῐ', - 'Ῑ' => 'ῑ', - 'Ὶ' => 'ὶ', - 'Ί' => 'ί', - 'Ῠ' => 'ῠ', - 'Ῡ' => 'ῡ', - 'Ὺ' => 'ὺ', - 'Ύ' => 'ύ', - 'Ῥ' => 'ῥ', - 'Ὸ' => 'ὸ', - 'Ό' => 'ό', - 'Ὼ' => 'ὼ', - 'Ώ' => 'ώ', - 'ῼ' => 'ῳ', - 'Ω' => 'ω', - 'K' => 'k', - 'Å' => 'å', - 'Ⅎ' => 'ⅎ', - 'Ⅰ' => 'ⅰ', - 'Ⅱ' => 'ⅱ', - 'Ⅲ' => 'ⅲ', - 'Ⅳ' => 'ⅳ', - 'Ⅴ' => 'ⅴ', - 'Ⅵ' => 'ⅵ', - 'Ⅶ' => 'ⅶ', - 'Ⅷ' => 'ⅷ', - 'Ⅸ' => 'ⅸ', - 'Ⅹ' => 'ⅹ', - 'Ⅺ' => 'ⅺ', - 'Ⅻ' => 'ⅻ', - 'Ⅼ' => 'ⅼ', - 'Ⅽ' => 'ⅽ', - 'Ⅾ' => 'ⅾ', - 'Ⅿ' => 'ⅿ', - 'Ↄ' => 'ↄ', - 'Ⓐ' => 'ⓐ', - 'Ⓑ' => 'ⓑ', - 'Ⓒ' => 'ⓒ', - 'Ⓓ' => 'ⓓ', - 'Ⓔ' => 'ⓔ', - 'Ⓕ' => 'ⓕ', - 'Ⓖ' => 'ⓖ', - 'Ⓗ' => 'ⓗ', - 'Ⓘ' => 'ⓘ', - 'Ⓙ' => 'ⓙ', - 'Ⓚ' => 'ⓚ', - 'Ⓛ' => 'ⓛ', - 'Ⓜ' => 'ⓜ', - 'Ⓝ' => 'ⓝ', - 'Ⓞ' => 'ⓞ', - 'Ⓟ' => 'ⓟ', - 'Ⓠ' => 'ⓠ', - 'Ⓡ' => 'ⓡ', - 'Ⓢ' => 'ⓢ', - 'Ⓣ' => 'ⓣ', - 'Ⓤ' => 'ⓤ', - 'Ⓥ' => 'ⓥ', - 'Ⓦ' => 'ⓦ', - 'Ⓧ' => 'ⓧ', - 'Ⓨ' => 'ⓨ', - 'Ⓩ' => 'ⓩ', - 'Ⰰ' => 'ⰰ', - 'Ⰱ' => 'ⰱ', - 'Ⰲ' => 'ⰲ', - 'Ⰳ' => 'ⰳ', - 'Ⰴ' => 'ⰴ', - 'Ⰵ' => 'ⰵ', - 'Ⰶ' => 'ⰶ', - 'Ⰷ' => 'ⰷ', - 'Ⰸ' => 'ⰸ', - 'Ⰹ' => 'ⰹ', - 'Ⰺ' => 'ⰺ', - 'Ⰻ' => 'ⰻ', - 'Ⰼ' => 'ⰼ', - 'Ⰽ' => 'ⰽ', - 'Ⰾ' => 'ⰾ', - 'Ⰿ' => 'ⰿ', - 'Ⱀ' => 'ⱀ', - 'Ⱁ' => 'ⱁ', - 'Ⱂ' => 'ⱂ', - 'Ⱃ' => 'ⱃ', - 'Ⱄ' => 'ⱄ', - 'Ⱅ' => 'ⱅ', - 'Ⱆ' => 'ⱆ', - 'Ⱇ' => 'ⱇ', - 'Ⱈ' => 'ⱈ', - 'Ⱉ' => 'ⱉ', - 'Ⱊ' => 'ⱊ', - 'Ⱋ' => 'ⱋ', - 'Ⱌ' => 'ⱌ', - 'Ⱍ' => 'ⱍ', - 'Ⱎ' => 'ⱎ', - 'Ⱏ' => 'ⱏ', - 'Ⱐ' => 'ⱐ', - 'Ⱑ' => 'ⱑ', - 'Ⱒ' => 'ⱒ', - 'Ⱓ' => 'ⱓ', - 'Ⱔ' => 'ⱔ', - 'Ⱕ' => 'ⱕ', - 'Ⱖ' => 'ⱖ', - 'Ⱗ' => 'ⱗ', - 'Ⱘ' => 'ⱘ', - 'Ⱙ' => 'ⱙ', - 'Ⱚ' => 'ⱚ', - 'Ⱛ' => 'ⱛ', - 'Ⱜ' => 'ⱜ', - 'Ⱝ' => 'ⱝ', - 'Ⱞ' => 'ⱞ', - 'Ⱡ' => 'ⱡ', - 'Ɫ' => 'ɫ', - 'Ᵽ' => 'ᵽ', - 'Ɽ' => 'ɽ', - 'Ⱨ' => 'ⱨ', - 'Ⱪ' => 'ⱪ', - 'Ⱬ' => 'ⱬ', - 'Ɑ' => 'ɑ', - 'Ɱ' => 'ɱ', - 'Ɐ' => 'ɐ', - 'Ɒ' => 'ɒ', - 'Ⱳ' => 'ⱳ', - 'Ⱶ' => 'ⱶ', - 'Ȿ' => 'ȿ', - 'Ɀ' => 'ɀ', - 'Ⲁ' => 'ⲁ', - 'Ⲃ' => 'ⲃ', - 'Ⲅ' => 'ⲅ', - 'Ⲇ' => 'ⲇ', - 'Ⲉ' => 'ⲉ', - 'Ⲋ' => 'ⲋ', - 'Ⲍ' => 'ⲍ', - 'Ⲏ' => 'ⲏ', - 'Ⲑ' => 'ⲑ', - 'Ⲓ' => 'ⲓ', - 'Ⲕ' => 'ⲕ', - 'Ⲗ' => 'ⲗ', - 'Ⲙ' => 'ⲙ', - 'Ⲛ' => 'ⲛ', - 'Ⲝ' => 'ⲝ', - 'Ⲟ' => 'ⲟ', - 'Ⲡ' => 'ⲡ', - 'Ⲣ' => 'ⲣ', - 'Ⲥ' => 'ⲥ', - 'Ⲧ' => 'ⲧ', - 'Ⲩ' => 'ⲩ', - 'Ⲫ' => 'ⲫ', - 'Ⲭ' => 'ⲭ', - 'Ⲯ' => 'ⲯ', - 'Ⲱ' => 'ⲱ', - 'Ⲳ' => 'ⲳ', - 'Ⲵ' => 'ⲵ', - 'Ⲷ' => 'ⲷ', - 'Ⲹ' => 'ⲹ', - 'Ⲻ' => 'ⲻ', - 'Ⲽ' => 'ⲽ', - 'Ⲿ' => 'ⲿ', - 'Ⳁ' => 'ⳁ', - 'Ⳃ' => 'ⳃ', - 'Ⳅ' => 'ⳅ', - 'Ⳇ' => 'ⳇ', - 'Ⳉ' => 'ⳉ', - 'Ⳋ' => 'ⳋ', - 'Ⳍ' => 'ⳍ', - 'Ⳏ' => 'ⳏ', - 'Ⳑ' => 'ⳑ', - 'Ⳓ' => 'ⳓ', - 'Ⳕ' => 'ⳕ', - 'Ⳗ' => 'ⳗ', - 'Ⳙ' => 'ⳙ', - 'Ⳛ' => 'ⳛ', - 'Ⳝ' => 'ⳝ', - 'Ⳟ' => 'ⳟ', - 'Ⳡ' => 'ⳡ', - 'Ⳣ' => 'ⳣ', - 'Ⳬ' => 'ⳬ', - 'Ⳮ' => 'ⳮ', - 'Ⳳ' => 'ⳳ', - 'Ꙁ' => 'ꙁ', - 'Ꙃ' => 'ꙃ', - 'Ꙅ' => 'ꙅ', - 'Ꙇ' => 'ꙇ', - 'Ꙉ' => 'ꙉ', - 'Ꙋ' => 'ꙋ', - 'Ꙍ' => 'ꙍ', - 'Ꙏ' => 'ꙏ', - 'Ꙑ' => 'ꙑ', - 'Ꙓ' => 'ꙓ', - 'Ꙕ' => 'ꙕ', - 'Ꙗ' => 'ꙗ', - 'Ꙙ' => 'ꙙ', - 'Ꙛ' => 'ꙛ', - 'Ꙝ' => 'ꙝ', - 'Ꙟ' => 'ꙟ', - 'Ꙡ' => 'ꙡ', - 'Ꙣ' => 'ꙣ', - 'Ꙥ' => 'ꙥ', - 'Ꙧ' => 'ꙧ', - 'Ꙩ' => 'ꙩ', - 'Ꙫ' => 'ꙫ', - 'Ꙭ' => 'ꙭ', - 'Ꚁ' => 'ꚁ', - 'Ꚃ' => 'ꚃ', - 'Ꚅ' => 'ꚅ', - 'Ꚇ' => 'ꚇ', - 'Ꚉ' => 'ꚉ', - 'Ꚋ' => 'ꚋ', - 'Ꚍ' => 'ꚍ', - 'Ꚏ' => 'ꚏ', - 'Ꚑ' => 'ꚑ', - 'Ꚓ' => 'ꚓ', - 'Ꚕ' => 'ꚕ', - 'Ꚗ' => 'ꚗ', - 'Ꚙ' => 'ꚙ', - 'Ꚛ' => 'ꚛ', - 'Ꜣ' => 'ꜣ', - 'Ꜥ' => 'ꜥ', - 'Ꜧ' => 'ꜧ', - 'Ꜩ' => 'ꜩ', - 'Ꜫ' => 'ꜫ', - 'Ꜭ' => 'ꜭ', - 'Ꜯ' => 'ꜯ', - 'Ꜳ' => 'ꜳ', - 'Ꜵ' => 'ꜵ', - 'Ꜷ' => 'ꜷ', - 'Ꜹ' => 'ꜹ', - 'Ꜻ' => 'ꜻ', - 'Ꜽ' => 'ꜽ', - 'Ꜿ' => 'ꜿ', - 'Ꝁ' => 'ꝁ', - 'Ꝃ' => 'ꝃ', - 'Ꝅ' => 'ꝅ', - 'Ꝇ' => 'ꝇ', - 'Ꝉ' => 'ꝉ', - 'Ꝋ' => 'ꝋ', - 'Ꝍ' => 'ꝍ', - 'Ꝏ' => 'ꝏ', - 'Ꝑ' => 'ꝑ', - 'Ꝓ' => 'ꝓ', - 'Ꝕ' => 'ꝕ', - 'Ꝗ' => 'ꝗ', - 'Ꝙ' => 'ꝙ', - 'Ꝛ' => 'ꝛ', - 'Ꝝ' => 'ꝝ', - 'Ꝟ' => 'ꝟ', - 'Ꝡ' => 'ꝡ', - 'Ꝣ' => 'ꝣ', - 'Ꝥ' => 'ꝥ', - 'Ꝧ' => 'ꝧ', - 'Ꝩ' => 'ꝩ', - 'Ꝫ' => 'ꝫ', - 'Ꝭ' => 'ꝭ', - 'Ꝯ' => 'ꝯ', - 'Ꝺ' => 'ꝺ', - 'Ꝼ' => 'ꝼ', - 'Ᵹ' => 'ᵹ', - 'Ꝿ' => 'ꝿ', - 'Ꞁ' => 'ꞁ', - 'Ꞃ' => 'ꞃ', - 'Ꞅ' => 'ꞅ', - 'Ꞇ' => 'ꞇ', - 'Ꞌ' => 'ꞌ', - 'Ɥ' => 'ɥ', - 'Ꞑ' => 'ꞑ', - 'Ꞓ' => 'ꞓ', - 'Ꞗ' => 'ꞗ', - 'Ꞙ' => 'ꞙ', - 'Ꞛ' => 'ꞛ', - 'Ꞝ' => 'ꞝ', - 'Ꞟ' => 'ꞟ', - 'Ꞡ' => 'ꞡ', - 'Ꞣ' => 'ꞣ', - 'Ꞥ' => 'ꞥ', - 'Ꞧ' => 'ꞧ', - 'Ꞩ' => 'ꞩ', - 'Ɦ' => 'ɦ', - 'Ɜ' => 'ɜ', - 'Ɡ' => 'ɡ', - 'Ɬ' => 'ɬ', - 'Ʞ' => 'ʞ', - 'Ʇ' => 'ʇ', - 'A' => 'a', - 'B' => 'b', - 'C' => 'c', - 'D' => 'd', - 'E' => 'e', - 'F' => 'f', - 'G' => 'g', - 'H' => 'h', - 'I' => 'i', - 'J' => 'j', - 'K' => 'k', - 'L' => 'l', - 'M' => 'm', - 'N' => 'n', - 'O' => 'o', - 'P' => 'p', - 'Q' => 'q', - 'R' => 'r', - 'S' => 's', - 'T' => 't', - 'U' => 'u', - 'V' => 'v', - 'W' => 'w', - 'X' => 'x', - 'Y' => 'y', - 'Z' => 'z', - '𐐀' => '𐐨', - '𐐁' => '𐐩', - '𐐂' => '𐐪', - '𐐃' => '𐐫', - '𐐄' => '𐐬', - '𐐅' => '𐐭', - '𐐆' => '𐐮', - '𐐇' => '𐐯', - '𐐈' => '𐐰', - '𐐉' => '𐐱', - '𐐊' => '𐐲', - '𐐋' => '𐐳', - '𐐌' => '𐐴', - '𐐍' => '𐐵', - '𐐎' => '𐐶', - '𐐏' => '𐐷', - '𐐐' => '𐐸', - '𐐑' => '𐐹', - '𐐒' => '𐐺', - '𐐓' => '𐐻', - '𐐔' => '𐐼', - '𐐕' => '𐐽', - '𐐖' => '𐐾', - '𐐗' => '𐐿', - '𐐘' => '𐑀', - '𐐙' => '𐑁', - '𐐚' => '𐑂', - '𐐛' => '𐑃', - '𐐜' => '𐑄', - '𐐝' => '𐑅', - '𐐞' => '𐑆', - '𐐟' => '𐑇', - '𐐠' => '𐑈', - '𐐡' => '𐑉', - '𐐢' => '𐑊', - '𐐣' => '𐑋', - '𐐤' => '𐑌', - '𐐥' => '𐑍', - '𐐦' => '𐑎', - '𐐧' => '𐑏', - '𑢠' => '𑣀', - '𑢡' => '𑣁', - '𑢢' => '𑣂', - '𑢣' => '𑣃', - '𑢤' => '𑣄', - '𑢥' => '𑣅', - '𑢦' => '𑣆', - '𑢧' => '𑣇', - '𑢨' => '𑣈', - '𑢩' => '𑣉', - '𑢪' => '𑣊', - '𑢫' => '𑣋', - '𑢬' => '𑣌', - '𑢭' => '𑣍', - '𑢮' => '𑣎', - '𑢯' => '𑣏', - '𑢰' => '𑣐', - '𑢱' => '𑣑', - '𑢲' => '𑣒', - '𑢳' => '𑣓', - '𑢴' => '𑣔', - '𑢵' => '𑣕', - '𑢶' => '𑣖', - '𑢷' => '𑣗', - '𑢸' => '𑣘', - '𑢹' => '𑣙', - '𑢺' => '𑣚', - '𑢻' => '𑣛', - '𑢼' => '𑣜', - '𑢽' => '𑣝', - '𑢾' => '𑣞', - '𑢿' => '𑣟', -); diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php deleted file mode 100644 index 2a8f6e7..0000000 --- a/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php +++ /dev/null @@ -1,5 +0,0 @@ - 'A', - 'b' => 'B', - 'c' => 'C', - 'd' => 'D', - 'e' => 'E', - 'f' => 'F', - 'g' => 'G', - 'h' => 'H', - 'i' => 'I', - 'j' => 'J', - 'k' => 'K', - 'l' => 'L', - 'm' => 'M', - 'n' => 'N', - 'o' => 'O', - 'p' => 'P', - 'q' => 'Q', - 'r' => 'R', - 's' => 'S', - 't' => 'T', - 'u' => 'U', - 'v' => 'V', - 'w' => 'W', - 'x' => 'X', - 'y' => 'Y', - 'z' => 'Z', - 'µ' => 'Μ', - 'à' => 'À', - 'á' => 'Á', - 'â' => 'Â', - 'ã' => 'Ã', - 'ä' => 'Ä', - 'å' => 'Å', - 'æ' => 'Æ', - 'ç' => 'Ç', - 'è' => 'È', - 'é' => 'É', - 'ê' => 'Ê', - 'ë' => 'Ë', - 'ì' => 'Ì', - 'í' => 'Í', - 'î' => 'Î', - 'ï' => 'Ï', - 'ð' => 'Ð', - 'ñ' => 'Ñ', - 'ò' => 'Ò', - 'ó' => 'Ó', - 'ô' => 'Ô', - 'õ' => 'Õ', - 'ö' => 'Ö', - 'ø' => 'Ø', - 'ù' => 'Ù', - 'ú' => 'Ú', - 'û' => 'Û', - 'ü' => 'Ü', - 'ý' => 'Ý', - 'þ' => 'Þ', - 'ÿ' => 'Ÿ', - 'ā' => 'Ā', - 'ă' => 'Ă', - 'ą' => 'Ą', - 'ć' => 'Ć', - 'ĉ' => 'Ĉ', - 'ċ' => 'Ċ', - 'č' => 'Č', - 'ď' => 'Ď', - 'đ' => 'Đ', - 'ē' => 'Ē', - 'ĕ' => 'Ĕ', - 'ė' => 'Ė', - 'ę' => 'Ę', - 'ě' => 'Ě', - 'ĝ' => 'Ĝ', - 'ğ' => 'Ğ', - 'ġ' => 'Ġ', - 'ģ' => 'Ģ', - 'ĥ' => 'Ĥ', - 'ħ' => 'Ħ', - 'ĩ' => 'Ĩ', - 'ī' => 'Ī', - 'ĭ' => 'Ĭ', - 'į' => 'Į', - 'ı' => 'I', - 'ij' => 'IJ', - 'ĵ' => 'Ĵ', - 'ķ' => 'Ķ', - 'ĺ' => 'Ĺ', - 'ļ' => 'Ļ', - 'ľ' => 'Ľ', - 'ŀ' => 'Ŀ', - 'ł' => 'Ł', - 'ń' => 'Ń', - 'ņ' => 'Ņ', - 'ň' => 'Ň', - 'ŋ' => 'Ŋ', - 'ō' => 'Ō', - 'ŏ' => 'Ŏ', - 'ő' => 'Ő', - 'œ' => 'Œ', - 'ŕ' => 'Ŕ', - 'ŗ' => 'Ŗ', - 'ř' => 'Ř', - 'ś' => 'Ś', - 'ŝ' => 'Ŝ', - 'ş' => 'Ş', - 'š' => 'Š', - 'ţ' => 'Ţ', - 'ť' => 'Ť', - 'ŧ' => 'Ŧ', - 'ũ' => 'Ũ', - 'ū' => 'Ū', - 'ŭ' => 'Ŭ', - 'ů' => 'Ů', - 'ű' => 'Ű', - 'ų' => 'Ų', - 'ŵ' => 'Ŵ', - 'ŷ' => 'Ŷ', - 'ź' => 'Ź', - 'ż' => 'Ż', - 'ž' => 'Ž', - 'ſ' => 'S', - 'ƀ' => 'Ƀ', - 'ƃ' => 'Ƃ', - 'ƅ' => 'Ƅ', - 'ƈ' => 'Ƈ', - 'ƌ' => 'Ƌ', - 'ƒ' => 'Ƒ', - 'ƕ' => 'Ƕ', - 'ƙ' => 'Ƙ', - 'ƚ' => 'Ƚ', - 'ƞ' => 'Ƞ', - 'ơ' => 'Ơ', - 'ƣ' => 'Ƣ', - 'ƥ' => 'Ƥ', - 'ƨ' => 'Ƨ', - 'ƭ' => 'Ƭ', - 'ư' => 'Ư', - 'ƴ' => 'Ƴ', - 'ƶ' => 'Ƶ', - 'ƹ' => 'Ƹ', - 'ƽ' => 'Ƽ', - 'ƿ' => 'Ƿ', - 'Dž' => 'DŽ', - 'dž' => 'DŽ', - 'Lj' => 'LJ', - 'lj' => 'LJ', - 'Nj' => 'NJ', - 'nj' => 'NJ', - 'ǎ' => 'Ǎ', - 'ǐ' => 'Ǐ', - 'ǒ' => 'Ǒ', - 'ǔ' => 'Ǔ', - 'ǖ' => 'Ǖ', - 'ǘ' => 'Ǘ', - 'ǚ' => 'Ǚ', - 'ǜ' => 'Ǜ', - 'ǝ' => 'Ǝ', - 'ǟ' => 'Ǟ', - 'ǡ' => 'Ǡ', - 'ǣ' => 'Ǣ', - 'ǥ' => 'Ǥ', - 'ǧ' => 'Ǧ', - 'ǩ' => 'Ǩ', - 'ǫ' => 'Ǫ', - 'ǭ' => 'Ǭ', - 'ǯ' => 'Ǯ', - 'Dz' => 'DZ', - 'dz' => 'DZ', - 'ǵ' => 'Ǵ', - 'ǹ' => 'Ǹ', - 'ǻ' => 'Ǻ', - 'ǽ' => 'Ǽ', - 'ǿ' => 'Ǿ', - 'ȁ' => 'Ȁ', - 'ȃ' => 'Ȃ', - 'ȅ' => 'Ȅ', - 'ȇ' => 'Ȇ', - 'ȉ' => 'Ȉ', - 'ȋ' => 'Ȋ', - 'ȍ' => 'Ȍ', - 'ȏ' => 'Ȏ', - 'ȑ' => 'Ȑ', - 'ȓ' => 'Ȓ', - 'ȕ' => 'Ȕ', - 'ȗ' => 'Ȗ', - 'ș' => 'Ș', - 'ț' => 'Ț', - 'ȝ' => 'Ȝ', - 'ȟ' => 'Ȟ', - 'ȣ' => 'Ȣ', - 'ȥ' => 'Ȥ', - 'ȧ' => 'Ȧ', - 'ȩ' => 'Ȩ', - 'ȫ' => 'Ȫ', - 'ȭ' => 'Ȭ', - 'ȯ' => 'Ȯ', - 'ȱ' => 'Ȱ', - 'ȳ' => 'Ȳ', - 'ȼ' => 'Ȼ', - 'ȿ' => 'Ȿ', - 'ɀ' => 'Ɀ', - 'ɂ' => 'Ɂ', - 'ɇ' => 'Ɇ', - 'ɉ' => 'Ɉ', - 'ɋ' => 'Ɋ', - 'ɍ' => 'Ɍ', - 'ɏ' => 'Ɏ', - 'ɐ' => 'Ɐ', - 'ɑ' => 'Ɑ', - 'ɒ' => 'Ɒ', - 'ɓ' => 'Ɓ', - 'ɔ' => 'Ɔ', - 'ɖ' => 'Ɖ', - 'ɗ' => 'Ɗ', - 'ə' => 'Ə', - 'ɛ' => 'Ɛ', - 'ɜ' => 'Ɜ', - 'ɠ' => 'Ɠ', - 'ɡ' => 'Ɡ', - 'ɣ' => 'Ɣ', - 'ɥ' => 'Ɥ', - 'ɦ' => 'Ɦ', - 'ɨ' => 'Ɨ', - 'ɩ' => 'Ɩ', - 'ɫ' => 'Ɫ', - 'ɬ' => 'Ɬ', - 'ɯ' => 'Ɯ', - 'ɱ' => 'Ɱ', - 'ɲ' => 'Ɲ', - 'ɵ' => 'Ɵ', - 'ɽ' => 'Ɽ', - 'ʀ' => 'Ʀ', - 'ʃ' => 'Ʃ', - 'ʇ' => 'Ʇ', - 'ʈ' => 'Ʈ', - 'ʉ' => 'Ʉ', - 'ʊ' => 'Ʊ', - 'ʋ' => 'Ʋ', - 'ʌ' => 'Ʌ', - 'ʒ' => 'Ʒ', - 'ʞ' => 'Ʞ', - 'ͅ' => 'Ι', - 'ͱ' => 'Ͱ', - 'ͳ' => 'Ͳ', - 'ͷ' => 'Ͷ', - 'ͻ' => 'Ͻ', - 'ͼ' => 'Ͼ', - 'ͽ' => 'Ͽ', - 'ά' => 'Ά', - 'έ' => 'Έ', - 'ή' => 'Ή', - 'ί' => 'Ί', - 'α' => 'Α', - 'β' => 'Β', - 'γ' => 'Γ', - 'δ' => 'Δ', - 'ε' => 'Ε', - 'ζ' => 'Ζ', - 'η' => 'Η', - 'θ' => 'Θ', - 'ι' => 'Ι', - 'κ' => 'Κ', - 'λ' => 'Λ', - 'μ' => 'Μ', - 'ν' => 'Ν', - 'ξ' => 'Ξ', - 'ο' => 'Ο', - 'π' => 'Π', - 'ρ' => 'Ρ', - 'ς' => 'Σ', - 'σ' => 'Σ', - 'τ' => 'Τ', - 'υ' => 'Υ', - 'φ' => 'Φ', - 'χ' => 'Χ', - 'ψ' => 'Ψ', - 'ω' => 'Ω', - 'ϊ' => 'Ϊ', - 'ϋ' => 'Ϋ', - 'ό' => 'Ό', - 'ύ' => 'Ύ', - 'ώ' => 'Ώ', - 'ϐ' => 'Β', - 'ϑ' => 'Θ', - 'ϕ' => 'Φ', - 'ϖ' => 'Π', - 'ϗ' => 'Ϗ', - 'ϙ' => 'Ϙ', - 'ϛ' => 'Ϛ', - 'ϝ' => 'Ϝ', - 'ϟ' => 'Ϟ', - 'ϡ' => 'Ϡ', - 'ϣ' => 'Ϣ', - 'ϥ' => 'Ϥ', - 'ϧ' => 'Ϧ', - 'ϩ' => 'Ϩ', - 'ϫ' => 'Ϫ', - 'ϭ' => 'Ϭ', - 'ϯ' => 'Ϯ', - 'ϰ' => 'Κ', - 'ϱ' => 'Ρ', - 'ϲ' => 'Ϲ', - 'ϳ' => 'Ϳ', - 'ϵ' => 'Ε', - 'ϸ' => 'Ϸ', - 'ϻ' => 'Ϻ', - 'а' => 'А', - 'б' => 'Б', - 'в' => 'В', - 'г' => 'Г', - 'д' => 'Д', - 'е' => 'Е', - 'ж' => 'Ж', - 'з' => 'З', - 'и' => 'И', - 'й' => 'Й', - 'к' => 'К', - 'л' => 'Л', - 'м' => 'М', - 'н' => 'Н', - 'о' => 'О', - 'п' => 'П', - 'р' => 'Р', - 'с' => 'С', - 'т' => 'Т', - 'у' => 'У', - 'ф' => 'Ф', - 'х' => 'Х', - 'ц' => 'Ц', - 'ч' => 'Ч', - 'ш' => 'Ш', - 'щ' => 'Щ', - 'ъ' => 'Ъ', - 'ы' => 'Ы', - 'ь' => 'Ь', - 'э' => 'Э', - 'ю' => 'Ю', - 'я' => 'Я', - 'ѐ' => 'Ѐ', - 'ё' => 'Ё', - 'ђ' => 'Ђ', - 'ѓ' => 'Ѓ', - 'є' => 'Є', - 'ѕ' => 'Ѕ', - 'і' => 'І', - 'ї' => 'Ї', - 'ј' => 'Ј', - 'љ' => 'Љ', - 'њ' => 'Њ', - 'ћ' => 'Ћ', - 'ќ' => 'Ќ', - 'ѝ' => 'Ѝ', - 'ў' => 'Ў', - 'џ' => 'Џ', - 'ѡ' => 'Ѡ', - 'ѣ' => 'Ѣ', - 'ѥ' => 'Ѥ', - 'ѧ' => 'Ѧ', - 'ѩ' => 'Ѩ', - 'ѫ' => 'Ѫ', - 'ѭ' => 'Ѭ', - 'ѯ' => 'Ѯ', - 'ѱ' => 'Ѱ', - 'ѳ' => 'Ѳ', - 'ѵ' => 'Ѵ', - 'ѷ' => 'Ѷ', - 'ѹ' => 'Ѹ', - 'ѻ' => 'Ѻ', - 'ѽ' => 'Ѽ', - 'ѿ' => 'Ѿ', - 'ҁ' => 'Ҁ', - 'ҋ' => 'Ҋ', - 'ҍ' => 'Ҍ', - 'ҏ' => 'Ҏ', - 'ґ' => 'Ґ', - 'ғ' => 'Ғ', - 'ҕ' => 'Ҕ', - 'җ' => 'Җ', - 'ҙ' => 'Ҙ', - 'қ' => 'Қ', - 'ҝ' => 'Ҝ', - 'ҟ' => 'Ҟ', - 'ҡ' => 'Ҡ', - 'ң' => 'Ң', - 'ҥ' => 'Ҥ', - 'ҧ' => 'Ҧ', - 'ҩ' => 'Ҩ', - 'ҫ' => 'Ҫ', - 'ҭ' => 'Ҭ', - 'ү' => 'Ү', - 'ұ' => 'Ұ', - 'ҳ' => 'Ҳ', - 'ҵ' => 'Ҵ', - 'ҷ' => 'Ҷ', - 'ҹ' => 'Ҹ', - 'һ' => 'Һ', - 'ҽ' => 'Ҽ', - 'ҿ' => 'Ҿ', - 'ӂ' => 'Ӂ', - 'ӄ' => 'Ӄ', - 'ӆ' => 'Ӆ', - 'ӈ' => 'Ӈ', - 'ӊ' => 'Ӊ', - 'ӌ' => 'Ӌ', - 'ӎ' => 'Ӎ', - 'ӏ' => 'Ӏ', - 'ӑ' => 'Ӑ', - 'ӓ' => 'Ӓ', - 'ӕ' => 'Ӕ', - 'ӗ' => 'Ӗ', - 'ә' => 'Ә', - 'ӛ' => 'Ӛ', - 'ӝ' => 'Ӝ', - 'ӟ' => 'Ӟ', - 'ӡ' => 'Ӡ', - 'ӣ' => 'Ӣ', - 'ӥ' => 'Ӥ', - 'ӧ' => 'Ӧ', - 'ө' => 'Ө', - 'ӫ' => 'Ӫ', - 'ӭ' => 'Ӭ', - 'ӯ' => 'Ӯ', - 'ӱ' => 'Ӱ', - 'ӳ' => 'Ӳ', - 'ӵ' => 'Ӵ', - 'ӷ' => 'Ӷ', - 'ӹ' => 'Ӹ', - 'ӻ' => 'Ӻ', - 'ӽ' => 'Ӽ', - 'ӿ' => 'Ӿ', - 'ԁ' => 'Ԁ', - 'ԃ' => 'Ԃ', - 'ԅ' => 'Ԅ', - 'ԇ' => 'Ԇ', - 'ԉ' => 'Ԉ', - 'ԋ' => 'Ԋ', - 'ԍ' => 'Ԍ', - 'ԏ' => 'Ԏ', - 'ԑ' => 'Ԑ', - 'ԓ' => 'Ԓ', - 'ԕ' => 'Ԕ', - 'ԗ' => 'Ԗ', - 'ԙ' => 'Ԙ', - 'ԛ' => 'Ԛ', - 'ԝ' => 'Ԝ', - 'ԟ' => 'Ԟ', - 'ԡ' => 'Ԡ', - 'ԣ' => 'Ԣ', - 'ԥ' => 'Ԥ', - 'ԧ' => 'Ԧ', - 'ԩ' => 'Ԩ', - 'ԫ' => 'Ԫ', - 'ԭ' => 'Ԭ', - 'ԯ' => 'Ԯ', - 'ա' => 'Ա', - 'բ' => 'Բ', - 'գ' => 'Գ', - 'դ' => 'Դ', - 'ե' => 'Ե', - 'զ' => 'Զ', - 'է' => 'Է', - 'ը' => 'Ը', - 'թ' => 'Թ', - 'ժ' => 'Ժ', - 'ի' => 'Ի', - 'լ' => 'Լ', - 'խ' => 'Խ', - 'ծ' => 'Ծ', - 'կ' => 'Կ', - 'հ' => 'Հ', - 'ձ' => 'Ձ', - 'ղ' => 'Ղ', - 'ճ' => 'Ճ', - 'մ' => 'Մ', - 'յ' => 'Յ', - 'ն' => 'Ն', - 'շ' => 'Շ', - 'ո' => 'Ո', - 'չ' => 'Չ', - 'պ' => 'Պ', - 'ջ' => 'Ջ', - 'ռ' => 'Ռ', - 'ս' => 'Ս', - 'վ' => 'Վ', - 'տ' => 'Տ', - 'ր' => 'Ր', - 'ց' => 'Ց', - 'ւ' => 'Ւ', - 'փ' => 'Փ', - 'ք' => 'Ք', - 'օ' => 'Օ', - 'ֆ' => 'Ֆ', - 'ᵹ' => 'Ᵹ', - 'ᵽ' => 'Ᵽ', - 'ḁ' => 'Ḁ', - 'ḃ' => 'Ḃ', - 'ḅ' => 'Ḅ', - 'ḇ' => 'Ḇ', - 'ḉ' => 'Ḉ', - 'ḋ' => 'Ḋ', - 'ḍ' => 'Ḍ', - 'ḏ' => 'Ḏ', - 'ḑ' => 'Ḑ', - 'ḓ' => 'Ḓ', - 'ḕ' => 'Ḕ', - 'ḗ' => 'Ḗ', - 'ḙ' => 'Ḙ', - 'ḛ' => 'Ḛ', - 'ḝ' => 'Ḝ', - 'ḟ' => 'Ḟ', - 'ḡ' => 'Ḡ', - 'ḣ' => 'Ḣ', - 'ḥ' => 'Ḥ', - 'ḧ' => 'Ḧ', - 'ḩ' => 'Ḩ', - 'ḫ' => 'Ḫ', - 'ḭ' => 'Ḭ', - 'ḯ' => 'Ḯ', - 'ḱ' => 'Ḱ', - 'ḳ' => 'Ḳ', - 'ḵ' => 'Ḵ', - 'ḷ' => 'Ḷ', - 'ḹ' => 'Ḹ', - 'ḻ' => 'Ḻ', - 'ḽ' => 'Ḽ', - 'ḿ' => 'Ḿ', - 'ṁ' => 'Ṁ', - 'ṃ' => 'Ṃ', - 'ṅ' => 'Ṅ', - 'ṇ' => 'Ṇ', - 'ṉ' => 'Ṉ', - 'ṋ' => 'Ṋ', - 'ṍ' => 'Ṍ', - 'ṏ' => 'Ṏ', - 'ṑ' => 'Ṑ', - 'ṓ' => 'Ṓ', - 'ṕ' => 'Ṕ', - 'ṗ' => 'Ṗ', - 'ṙ' => 'Ṙ', - 'ṛ' => 'Ṛ', - 'ṝ' => 'Ṝ', - 'ṟ' => 'Ṟ', - 'ṡ' => 'Ṡ', - 'ṣ' => 'Ṣ', - 'ṥ' => 'Ṥ', - 'ṧ' => 'Ṧ', - 'ṩ' => 'Ṩ', - 'ṫ' => 'Ṫ', - 'ṭ' => 'Ṭ', - 'ṯ' => 'Ṯ', - 'ṱ' => 'Ṱ', - 'ṳ' => 'Ṳ', - 'ṵ' => 'Ṵ', - 'ṷ' => 'Ṷ', - 'ṹ' => 'Ṹ', - 'ṻ' => 'Ṻ', - 'ṽ' => 'Ṽ', - 'ṿ' => 'Ṿ', - 'ẁ' => 'Ẁ', - 'ẃ' => 'Ẃ', - 'ẅ' => 'Ẅ', - 'ẇ' => 'Ẇ', - 'ẉ' => 'Ẉ', - 'ẋ' => 'Ẋ', - 'ẍ' => 'Ẍ', - 'ẏ' => 'Ẏ', - 'ẑ' => 'Ẑ', - 'ẓ' => 'Ẓ', - 'ẕ' => 'Ẕ', - 'ẛ' => 'Ṡ', - 'ạ' => 'Ạ', - 'ả' => 'Ả', - 'ấ' => 'Ấ', - 'ầ' => 'Ầ', - 'ẩ' => 'Ẩ', - 'ẫ' => 'Ẫ', - 'ậ' => 'Ậ', - 'ắ' => 'Ắ', - 'ằ' => 'Ằ', - 'ẳ' => 'Ẳ', - 'ẵ' => 'Ẵ', - 'ặ' => 'Ặ', - 'ẹ' => 'Ẹ', - 'ẻ' => 'Ẻ', - 'ẽ' => 'Ẽ', - 'ế' => 'Ế', - 'ề' => 'Ề', - 'ể' => 'Ể', - 'ễ' => 'Ễ', - 'ệ' => 'Ệ', - 'ỉ' => 'Ỉ', - 'ị' => 'Ị', - 'ọ' => 'Ọ', - 'ỏ' => 'Ỏ', - 'ố' => 'Ố', - 'ồ' => 'Ồ', - 'ổ' => 'Ổ', - 'ỗ' => 'Ỗ', - 'ộ' => 'Ộ', - 'ớ' => 'Ớ', - 'ờ' => 'Ờ', - 'ở' => 'Ở', - 'ỡ' => 'Ỡ', - 'ợ' => 'Ợ', - 'ụ' => 'Ụ', - 'ủ' => 'Ủ', - 'ứ' => 'Ứ', - 'ừ' => 'Ừ', - 'ử' => 'Ử', - 'ữ' => 'Ữ', - 'ự' => 'Ự', - 'ỳ' => 'Ỳ', - 'ỵ' => 'Ỵ', - 'ỷ' => 'Ỷ', - 'ỹ' => 'Ỹ', - 'ỻ' => 'Ỻ', - 'ỽ' => 'Ỽ', - 'ỿ' => 'Ỿ', - 'ἀ' => 'Ἀ', - 'ἁ' => 'Ἁ', - 'ἂ' => 'Ἂ', - 'ἃ' => 'Ἃ', - 'ἄ' => 'Ἄ', - 'ἅ' => 'Ἅ', - 'ἆ' => 'Ἆ', - 'ἇ' => 'Ἇ', - 'ἐ' => 'Ἐ', - 'ἑ' => 'Ἑ', - 'ἒ' => 'Ἒ', - 'ἓ' => 'Ἓ', - 'ἔ' => 'Ἔ', - 'ἕ' => 'Ἕ', - 'ἠ' => 'Ἠ', - 'ἡ' => 'Ἡ', - 'ἢ' => 'Ἢ', - 'ἣ' => 'Ἣ', - 'ἤ' => 'Ἤ', - 'ἥ' => 'Ἥ', - 'ἦ' => 'Ἦ', - 'ἧ' => 'Ἧ', - 'ἰ' => 'Ἰ', - 'ἱ' => 'Ἱ', - 'ἲ' => 'Ἲ', - 'ἳ' => 'Ἳ', - 'ἴ' => 'Ἴ', - 'ἵ' => 'Ἵ', - 'ἶ' => 'Ἶ', - 'ἷ' => 'Ἷ', - 'ὀ' => 'Ὀ', - 'ὁ' => 'Ὁ', - 'ὂ' => 'Ὂ', - 'ὃ' => 'Ὃ', - 'ὄ' => 'Ὄ', - 'ὅ' => 'Ὅ', - 'ὑ' => 'Ὑ', - 'ὓ' => 'Ὓ', - 'ὕ' => 'Ὕ', - 'ὗ' => 'Ὗ', - 'ὠ' => 'Ὠ', - 'ὡ' => 'Ὡ', - 'ὢ' => 'Ὢ', - 'ὣ' => 'Ὣ', - 'ὤ' => 'Ὤ', - 'ὥ' => 'Ὥ', - 'ὦ' => 'Ὦ', - 'ὧ' => 'Ὧ', - 'ὰ' => 'Ὰ', - 'ά' => 'Ά', - 'ὲ' => 'Ὲ', - 'έ' => 'Έ', - 'ὴ' => 'Ὴ', - 'ή' => 'Ή', - 'ὶ' => 'Ὶ', - 'ί' => 'Ί', - 'ὸ' => 'Ὸ', - 'ό' => 'Ό', - 'ὺ' => 'Ὺ', - 'ύ' => 'Ύ', - 'ὼ' => 'Ὼ', - 'ώ' => 'Ώ', - 'ᾀ' => 'ᾈ', - 'ᾁ' => 'ᾉ', - 'ᾂ' => 'ᾊ', - 'ᾃ' => 'ᾋ', - 'ᾄ' => 'ᾌ', - 'ᾅ' => 'ᾍ', - 'ᾆ' => 'ᾎ', - 'ᾇ' => 'ᾏ', - 'ᾐ' => 'ᾘ', - 'ᾑ' => 'ᾙ', - 'ᾒ' => 'ᾚ', - 'ᾓ' => 'ᾛ', - 'ᾔ' => 'ᾜ', - 'ᾕ' => 'ᾝ', - 'ᾖ' => 'ᾞ', - 'ᾗ' => 'ᾟ', - 'ᾠ' => 'ᾨ', - 'ᾡ' => 'ᾩ', - 'ᾢ' => 'ᾪ', - 'ᾣ' => 'ᾫ', - 'ᾤ' => 'ᾬ', - 'ᾥ' => 'ᾭ', - 'ᾦ' => 'ᾮ', - 'ᾧ' => 'ᾯ', - 'ᾰ' => 'Ᾰ', - 'ᾱ' => 'Ᾱ', - 'ᾳ' => 'ᾼ', - 'ι' => 'Ι', - 'ῃ' => 'ῌ', - 'ῐ' => 'Ῐ', - 'ῑ' => 'Ῑ', - 'ῠ' => 'Ῠ', - 'ῡ' => 'Ῡ', - 'ῥ' => 'Ῥ', - 'ῳ' => 'ῼ', - 'ⅎ' => 'Ⅎ', - 'ⅰ' => 'Ⅰ', - 'ⅱ' => 'Ⅱ', - 'ⅲ' => 'Ⅲ', - 'ⅳ' => 'Ⅳ', - 'ⅴ' => 'Ⅴ', - 'ⅵ' => 'Ⅵ', - 'ⅶ' => 'Ⅶ', - 'ⅷ' => 'Ⅷ', - 'ⅸ' => 'Ⅸ', - 'ⅹ' => 'Ⅹ', - 'ⅺ' => 'Ⅺ', - 'ⅻ' => 'Ⅻ', - 'ⅼ' => 'Ⅼ', - 'ⅽ' => 'Ⅽ', - 'ⅾ' => 'Ⅾ', - 'ⅿ' => 'Ⅿ', - 'ↄ' => 'Ↄ', - 'ⓐ' => 'Ⓐ', - 'ⓑ' => 'Ⓑ', - 'ⓒ' => 'Ⓒ', - 'ⓓ' => 'Ⓓ', - 'ⓔ' => 'Ⓔ', - 'ⓕ' => 'Ⓕ', - 'ⓖ' => 'Ⓖ', - 'ⓗ' => 'Ⓗ', - 'ⓘ' => 'Ⓘ', - 'ⓙ' => 'Ⓙ', - 'ⓚ' => 'Ⓚ', - 'ⓛ' => 'Ⓛ', - 'ⓜ' => 'Ⓜ', - 'ⓝ' => 'Ⓝ', - 'ⓞ' => 'Ⓞ', - 'ⓟ' => 'Ⓟ', - 'ⓠ' => 'Ⓠ', - 'ⓡ' => 'Ⓡ', - 'ⓢ' => 'Ⓢ', - 'ⓣ' => 'Ⓣ', - 'ⓤ' => 'Ⓤ', - 'ⓥ' => 'Ⓥ', - 'ⓦ' => 'Ⓦ', - 'ⓧ' => 'Ⓧ', - 'ⓨ' => 'Ⓨ', - 'ⓩ' => 'Ⓩ', - 'ⰰ' => 'Ⰰ', - 'ⰱ' => 'Ⰱ', - 'ⰲ' => 'Ⰲ', - 'ⰳ' => 'Ⰳ', - 'ⰴ' => 'Ⰴ', - 'ⰵ' => 'Ⰵ', - 'ⰶ' => 'Ⰶ', - 'ⰷ' => 'Ⰷ', - 'ⰸ' => 'Ⰸ', - 'ⰹ' => 'Ⰹ', - 'ⰺ' => 'Ⰺ', - 'ⰻ' => 'Ⰻ', - 'ⰼ' => 'Ⰼ', - 'ⰽ' => 'Ⰽ', - 'ⰾ' => 'Ⰾ', - 'ⰿ' => 'Ⰿ', - 'ⱀ' => 'Ⱀ', - 'ⱁ' => 'Ⱁ', - 'ⱂ' => 'Ⱂ', - 'ⱃ' => 'Ⱃ', - 'ⱄ' => 'Ⱄ', - 'ⱅ' => 'Ⱅ', - 'ⱆ' => 'Ⱆ', - 'ⱇ' => 'Ⱇ', - 'ⱈ' => 'Ⱈ', - 'ⱉ' => 'Ⱉ', - 'ⱊ' => 'Ⱊ', - 'ⱋ' => 'Ⱋ', - 'ⱌ' => 'Ⱌ', - 'ⱍ' => 'Ⱍ', - 'ⱎ' => 'Ⱎ', - 'ⱏ' => 'Ⱏ', - 'ⱐ' => 'Ⱐ', - 'ⱑ' => 'Ⱑ', - 'ⱒ' => 'Ⱒ', - 'ⱓ' => 'Ⱓ', - 'ⱔ' => 'Ⱔ', - 'ⱕ' => 'Ⱕ', - 'ⱖ' => 'Ⱖ', - 'ⱗ' => 'Ⱗ', - 'ⱘ' => 'Ⱘ', - 'ⱙ' => 'Ⱙ', - 'ⱚ' => 'Ⱚ', - 'ⱛ' => 'Ⱛ', - 'ⱜ' => 'Ⱜ', - 'ⱝ' => 'Ⱝ', - 'ⱞ' => 'Ⱞ', - 'ⱡ' => 'Ⱡ', - 'ⱥ' => 'Ⱥ', - 'ⱦ' => 'Ⱦ', - 'ⱨ' => 'Ⱨ', - 'ⱪ' => 'Ⱪ', - 'ⱬ' => 'Ⱬ', - 'ⱳ' => 'Ⱳ', - 'ⱶ' => 'Ⱶ', - 'ⲁ' => 'Ⲁ', - 'ⲃ' => 'Ⲃ', - 'ⲅ' => 'Ⲅ', - 'ⲇ' => 'Ⲇ', - 'ⲉ' => 'Ⲉ', - 'ⲋ' => 'Ⲋ', - 'ⲍ' => 'Ⲍ', - 'ⲏ' => 'Ⲏ', - 'ⲑ' => 'Ⲑ', - 'ⲓ' => 'Ⲓ', - 'ⲕ' => 'Ⲕ', - 'ⲗ' => 'Ⲗ', - 'ⲙ' => 'Ⲙ', - 'ⲛ' => 'Ⲛ', - 'ⲝ' => 'Ⲝ', - 'ⲟ' => 'Ⲟ', - 'ⲡ' => 'Ⲡ', - 'ⲣ' => 'Ⲣ', - 'ⲥ' => 'Ⲥ', - 'ⲧ' => 'Ⲧ', - 'ⲩ' => 'Ⲩ', - 'ⲫ' => 'Ⲫ', - 'ⲭ' => 'Ⲭ', - 'ⲯ' => 'Ⲯ', - 'ⲱ' => 'Ⲱ', - 'ⲳ' => 'Ⲳ', - 'ⲵ' => 'Ⲵ', - 'ⲷ' => 'Ⲷ', - 'ⲹ' => 'Ⲹ', - 'ⲻ' => 'Ⲻ', - 'ⲽ' => 'Ⲽ', - 'ⲿ' => 'Ⲿ', - 'ⳁ' => 'Ⳁ', - 'ⳃ' => 'Ⳃ', - 'ⳅ' => 'Ⳅ', - 'ⳇ' => 'Ⳇ', - 'ⳉ' => 'Ⳉ', - 'ⳋ' => 'Ⳋ', - 'ⳍ' => 'Ⳍ', - 'ⳏ' => 'Ⳏ', - 'ⳑ' => 'Ⳑ', - 'ⳓ' => 'Ⳓ', - 'ⳕ' => 'Ⳕ', - 'ⳗ' => 'Ⳗ', - 'ⳙ' => 'Ⳙ', - 'ⳛ' => 'Ⳛ', - 'ⳝ' => 'Ⳝ', - 'ⳟ' => 'Ⳟ', - 'ⳡ' => 'Ⳡ', - 'ⳣ' => 'Ⳣ', - 'ⳬ' => 'Ⳬ', - 'ⳮ' => 'Ⳮ', - 'ⳳ' => 'Ⳳ', - 'ⴀ' => 'Ⴀ', - 'ⴁ' => 'Ⴁ', - 'ⴂ' => 'Ⴂ', - 'ⴃ' => 'Ⴃ', - 'ⴄ' => 'Ⴄ', - 'ⴅ' => 'Ⴅ', - 'ⴆ' => 'Ⴆ', - 'ⴇ' => 'Ⴇ', - 'ⴈ' => 'Ⴈ', - 'ⴉ' => 'Ⴉ', - 'ⴊ' => 'Ⴊ', - 'ⴋ' => 'Ⴋ', - 'ⴌ' => 'Ⴌ', - 'ⴍ' => 'Ⴍ', - 'ⴎ' => 'Ⴎ', - 'ⴏ' => 'Ⴏ', - 'ⴐ' => 'Ⴐ', - 'ⴑ' => 'Ⴑ', - 'ⴒ' => 'Ⴒ', - 'ⴓ' => 'Ⴓ', - 'ⴔ' => 'Ⴔ', - 'ⴕ' => 'Ⴕ', - 'ⴖ' => 'Ⴖ', - 'ⴗ' => 'Ⴗ', - 'ⴘ' => 'Ⴘ', - 'ⴙ' => 'Ⴙ', - 'ⴚ' => 'Ⴚ', - 'ⴛ' => 'Ⴛ', - 'ⴜ' => 'Ⴜ', - 'ⴝ' => 'Ⴝ', - 'ⴞ' => 'Ⴞ', - 'ⴟ' => 'Ⴟ', - 'ⴠ' => 'Ⴠ', - 'ⴡ' => 'Ⴡ', - 'ⴢ' => 'Ⴢ', - 'ⴣ' => 'Ⴣ', - 'ⴤ' => 'Ⴤ', - 'ⴥ' => 'Ⴥ', - 'ⴧ' => 'Ⴧ', - 'ⴭ' => 'Ⴭ', - 'ꙁ' => 'Ꙁ', - 'ꙃ' => 'Ꙃ', - 'ꙅ' => 'Ꙅ', - 'ꙇ' => 'Ꙇ', - 'ꙉ' => 'Ꙉ', - 'ꙋ' => 'Ꙋ', - 'ꙍ' => 'Ꙍ', - 'ꙏ' => 'Ꙏ', - 'ꙑ' => 'Ꙑ', - 'ꙓ' => 'Ꙓ', - 'ꙕ' => 'Ꙕ', - 'ꙗ' => 'Ꙗ', - 'ꙙ' => 'Ꙙ', - 'ꙛ' => 'Ꙛ', - 'ꙝ' => 'Ꙝ', - 'ꙟ' => 'Ꙟ', - 'ꙡ' => 'Ꙡ', - 'ꙣ' => 'Ꙣ', - 'ꙥ' => 'Ꙥ', - 'ꙧ' => 'Ꙧ', - 'ꙩ' => 'Ꙩ', - 'ꙫ' => 'Ꙫ', - 'ꙭ' => 'Ꙭ', - 'ꚁ' => 'Ꚁ', - 'ꚃ' => 'Ꚃ', - 'ꚅ' => 'Ꚅ', - 'ꚇ' => 'Ꚇ', - 'ꚉ' => 'Ꚉ', - 'ꚋ' => 'Ꚋ', - 'ꚍ' => 'Ꚍ', - 'ꚏ' => 'Ꚏ', - 'ꚑ' => 'Ꚑ', - 'ꚓ' => 'Ꚓ', - 'ꚕ' => 'Ꚕ', - 'ꚗ' => 'Ꚗ', - 'ꚙ' => 'Ꚙ', - 'ꚛ' => 'Ꚛ', - 'ꜣ' => 'Ꜣ', - 'ꜥ' => 'Ꜥ', - 'ꜧ' => 'Ꜧ', - 'ꜩ' => 'Ꜩ', - 'ꜫ' => 'Ꜫ', - 'ꜭ' => 'Ꜭ', - 'ꜯ' => 'Ꜯ', - 'ꜳ' => 'Ꜳ', - 'ꜵ' => 'Ꜵ', - 'ꜷ' => 'Ꜷ', - 'ꜹ' => 'Ꜹ', - 'ꜻ' => 'Ꜻ', - 'ꜽ' => 'Ꜽ', - 'ꜿ' => 'Ꜿ', - 'ꝁ' => 'Ꝁ', - 'ꝃ' => 'Ꝃ', - 'ꝅ' => 'Ꝅ', - 'ꝇ' => 'Ꝇ', - 'ꝉ' => 'Ꝉ', - 'ꝋ' => 'Ꝋ', - 'ꝍ' => 'Ꝍ', - 'ꝏ' => 'Ꝏ', - 'ꝑ' => 'Ꝑ', - 'ꝓ' => 'Ꝓ', - 'ꝕ' => 'Ꝕ', - 'ꝗ' => 'Ꝗ', - 'ꝙ' => 'Ꝙ', - 'ꝛ' => 'Ꝛ', - 'ꝝ' => 'Ꝝ', - 'ꝟ' => 'Ꝟ', - 'ꝡ' => 'Ꝡ', - 'ꝣ' => 'Ꝣ', - 'ꝥ' => 'Ꝥ', - 'ꝧ' => 'Ꝧ', - 'ꝩ' => 'Ꝩ', - 'ꝫ' => 'Ꝫ', - 'ꝭ' => 'Ꝭ', - 'ꝯ' => 'Ꝯ', - 'ꝺ' => 'Ꝺ', - 'ꝼ' => 'Ꝼ', - 'ꝿ' => 'Ꝿ', - 'ꞁ' => 'Ꞁ', - 'ꞃ' => 'Ꞃ', - 'ꞅ' => 'Ꞅ', - 'ꞇ' => 'Ꞇ', - 'ꞌ' => 'Ꞌ', - 'ꞑ' => 'Ꞑ', - 'ꞓ' => 'Ꞓ', - 'ꞗ' => 'Ꞗ', - 'ꞙ' => 'Ꞙ', - 'ꞛ' => 'Ꞛ', - 'ꞝ' => 'Ꞝ', - 'ꞟ' => 'Ꞟ', - 'ꞡ' => 'Ꞡ', - 'ꞣ' => 'Ꞣ', - 'ꞥ' => 'Ꞥ', - 'ꞧ' => 'Ꞧ', - 'ꞩ' => 'Ꞩ', - 'a' => 'A', - 'b' => 'B', - 'c' => 'C', - 'd' => 'D', - 'e' => 'E', - 'f' => 'F', - 'g' => 'G', - 'h' => 'H', - 'i' => 'I', - 'j' => 'J', - 'k' => 'K', - 'l' => 'L', - 'm' => 'M', - 'n' => 'N', - 'o' => 'O', - 'p' => 'P', - 'q' => 'Q', - 'r' => 'R', - 's' => 'S', - 't' => 'T', - 'u' => 'U', - 'v' => 'V', - 'w' => 'W', - 'x' => 'X', - 'y' => 'Y', - 'z' => 'Z', - '𐐨' => '𐐀', - '𐐩' => '𐐁', - '𐐪' => '𐐂', - '𐐫' => '𐐃', - '𐐬' => '𐐄', - '𐐭' => '𐐅', - '𐐮' => '𐐆', - '𐐯' => '𐐇', - '𐐰' => '𐐈', - '𐐱' => '𐐉', - '𐐲' => '𐐊', - '𐐳' => '𐐋', - '𐐴' => '𐐌', - '𐐵' => '𐐍', - '𐐶' => '𐐎', - '𐐷' => '𐐏', - '𐐸' => '𐐐', - '𐐹' => '𐐑', - '𐐺' => '𐐒', - '𐐻' => '𐐓', - '𐐼' => '𐐔', - '𐐽' => '𐐕', - '𐐾' => '𐐖', - '𐐿' => '𐐗', - '𐑀' => '𐐘', - '𐑁' => '𐐙', - '𐑂' => '𐐚', - '𐑃' => '𐐛', - '𐑄' => '𐐜', - '𐑅' => '𐐝', - '𐑆' => '𐐞', - '𐑇' => '𐐟', - '𐑈' => '𐐠', - '𐑉' => '𐐡', - '𐑊' => '𐐢', - '𐑋' => '𐐣', - '𐑌' => '𐐤', - '𐑍' => '𐐥', - '𐑎' => '𐐦', - '𐑏' => '𐐧', - '𑣀' => '𑢠', - '𑣁' => '𑢡', - '𑣂' => '𑢢', - '𑣃' => '𑢣', - '𑣄' => '𑢤', - '𑣅' => '𑢥', - '𑣆' => '𑢦', - '𑣇' => '𑢧', - '𑣈' => '𑢨', - '𑣉' => '𑢩', - '𑣊' => '𑢪', - '𑣋' => '𑢫', - '𑣌' => '𑢬', - '𑣍' => '𑢭', - '𑣎' => '𑢮', - '𑣏' => '𑢯', - '𑣐' => '𑢰', - '𑣑' => '𑢱', - '𑣒' => '𑢲', - '𑣓' => '𑢳', - '𑣔' => '𑢴', - '𑣕' => '𑢵', - '𑣖' => '𑢶', - '𑣗' => '𑢷', - '𑣘' => '𑢸', - '𑣙' => '𑢹', - '𑣚' => '𑢺', - '𑣛' => '𑢻', - '𑣜' => '𑢼', - '𑣝' => '𑢽', - '𑣞' => '𑢾', - '𑣟' => '𑢿', -); diff --git a/vendor/symfony/polyfill-mbstring/bootstrap.php b/vendor/symfony/polyfill-mbstring/bootstrap.php deleted file mode 100644 index 204a41b..0000000 --- a/vendor/symfony/polyfill-mbstring/bootstrap.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Mbstring as p; - -if (!function_exists('mb_strlen')) { - define('MB_CASE_UPPER', 0); - define('MB_CASE_LOWER', 1); - define('MB_CASE_TITLE', 2); - - function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); } - function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); } - function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); } - function mb_decode_numericentity($s, $convmap, $enc = null) { return p\Mbstring::mb_decode_numericentity($s, $convmap, $enc); } - function mb_encode_numericentity($s, $convmap, $enc = null, $is_hex = false) { return p\Mbstring::mb_encode_numericentity($s, $convmap, $enc, $is_hex); } - function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); } - function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); } - function mb_language($lang = null) { return p\Mbstring::mb_language($lang); } - function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); } - function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); } - function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); } - function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); } - function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); } - function mb_parse_str($s, &$result = array()) { parse_str($s, $result); } - function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); } - function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); } - function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); } - function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); } - function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); } - function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); } - function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); } - function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); } - function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); } - function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); } - function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); } - function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); } - function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); } - function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); } - function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); } - function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); } - function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); } - function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); } - function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); } - function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null) { return p\Mbstring::mb_convert_variables($toEncoding, $fromEncoding, $a, $b, $c, $d, $e, $f); } -} -if (!function_exists('mb_chr')) { - function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); } - function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); } - function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); } -} - -if (!function_exists('mb_str_split')) { - function mb_str_split($string, $split_length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $split_length, $encoding); } -} diff --git a/vendor/symfony/polyfill-mbstring/composer.json b/vendor/symfony/polyfill-mbstring/composer.json deleted file mode 100644 index c968074..0000000 --- a/vendor/symfony/polyfill-mbstring/composer.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "symfony/polyfill-mbstring", - "type": "library", - "description": "Symfony polyfill for the Mbstring extension", - "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=5.3.3" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" }, - "files": [ "bootstrap.php" ] - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "1.13-dev" - } - } -} diff --git a/vendor/symfony/polyfill-php72/LICENSE b/vendor/symfony/polyfill-php72/LICENSE deleted file mode 100644 index 4cd8bdd..0000000 --- a/vendor/symfony/polyfill-php72/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2015-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/polyfill-php72/Php72.php b/vendor/symfony/polyfill-php72/Php72.php deleted file mode 100644 index d531e84..0000000 --- a/vendor/symfony/polyfill-php72/Php72.php +++ /dev/null @@ -1,216 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Php72; - -/** - * @author Nicolas Grekas - * @author Dariusz Rumiński - * - * @internal - */ -final class Php72 -{ - private static $hashMask; - - public static function utf8_encode($s) - { - $s .= $s; - $len = \strlen($s); - - for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) { - switch (true) { - case $s[$i] < "\x80": $s[$j] = $s[$i]; break; - case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break; - default: $s[$j] = "\xC3"; $s[++$j] = \chr(\ord($s[$i]) - 64); break; - } - } - - return substr($s, 0, $j); - } - - public static function utf8_decode($s) - { - $s = (string) $s; - $len = \strlen($s); - - for ($i = 0, $j = 0; $i < $len; ++$i, ++$j) { - switch ($s[$i] & "\xF0") { - case "\xC0": - case "\xD0": - $c = (\ord($s[$i] & "\x1F") << 6) | \ord($s[++$i] & "\x3F"); - $s[$j] = $c < 256 ? \chr($c) : '?'; - break; - - case "\xF0": - ++$i; - // no break - - case "\xE0": - $s[$j] = '?'; - $i += 2; - break; - - default: - $s[$j] = $s[$i]; - } - } - - return substr($s, 0, $j); - } - - public static function php_os_family() - { - if ('\\' === \DIRECTORY_SEPARATOR) { - return 'Windows'; - } - - $map = array( - 'Darwin' => 'Darwin', - 'DragonFly' => 'BSD', - 'FreeBSD' => 'BSD', - 'NetBSD' => 'BSD', - 'OpenBSD' => 'BSD', - 'Linux' => 'Linux', - 'SunOS' => 'Solaris', - ); - - return isset($map[PHP_OS]) ? $map[PHP_OS] : 'Unknown'; - } - - public static function spl_object_id($object) - { - if (null === self::$hashMask) { - self::initHashMask(); - } - if (null === $hash = spl_object_hash($object)) { - return; - } - - return self::$hashMask ^ hexdec(substr($hash, 16 - \PHP_INT_SIZE, \PHP_INT_SIZE)); - } - - public static function sapi_windows_vt100_support($stream, $enable = null) - { - if (!\is_resource($stream)) { - trigger_error('sapi_windows_vt100_support() expects parameter 1 to be resource, '.\gettype($stream).' given', E_USER_WARNING); - - return false; - } - - $meta = stream_get_meta_data($stream); - - if ('STDIO' !== $meta['stream_type']) { - trigger_error('sapi_windows_vt100_support() was not able to analyze the specified stream', E_USER_WARNING); - - return false; - } - - // We cannot actually disable vt100 support if it is set - if (false === $enable || !self::stream_isatty($stream)) { - return false; - } - - // The native function does not apply to stdin - $meta = array_map('strtolower', $meta); - $stdin = 'php://stdin' === $meta['uri'] || 'php://fd/0' === $meta['uri']; - - return !$stdin - && (false !== getenv('ANSICON') - || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM') - || 'Hyper' === getenv('TERM_PROGRAM')); - } - - public static function stream_isatty($stream) - { - if (!\is_resource($stream)) { - trigger_error('stream_isatty() expects parameter 1 to be resource, '.\gettype($stream).' given', E_USER_WARNING); - - return false; - } - - if ('\\' === \DIRECTORY_SEPARATOR) { - $stat = @fstat($stream); - // Check if formatted mode is S_IFCHR - return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; - } - - return \function_exists('posix_isatty') && @posix_isatty($stream); - } - - private static function initHashMask() - { - $obj = (object) array(); - self::$hashMask = -1; - - // check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below - $obFuncs = array('ob_clean', 'ob_end_clean', 'ob_flush', 'ob_end_flush', 'ob_get_contents', 'ob_get_flush'); - foreach (debug_backtrace(\PHP_VERSION_ID >= 50400 ? DEBUG_BACKTRACE_IGNORE_ARGS : false) as $frame) { - if (isset($frame['function'][0]) && !isset($frame['class']) && 'o' === $frame['function'][0] && \in_array($frame['function'], $obFuncs)) { - $frame['line'] = 0; - break; - } - } - if (!empty($frame['line'])) { - ob_start(); - debug_zval_dump($obj); - self::$hashMask = (int) substr(ob_get_clean(), 17); - } - - self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - \PHP_INT_SIZE, \PHP_INT_SIZE)); - } - - public static function mb_chr($code, $encoding = null) - { - if (0x80 > $code %= 0x200000) { - $s = \chr($code); - } elseif (0x800 > $code) { - $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); - } elseif (0x10000 > $code) { - $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); - } else { - $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); - } - - if ('UTF-8' !== $encoding) { - $s = mb_convert_encoding($s, $encoding, 'UTF-8'); - } - - return $s; - } - - public static function mb_ord($s, $encoding = null) - { - if (null == $encoding) { - $s = mb_convert_encoding($s, 'UTF-8'); - } elseif ('UTF-8' !== $encoding) { - $s = mb_convert_encoding($s, 'UTF-8', $encoding); - } - - if (1 === \strlen($s)) { - return \ord($s); - } - - $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; - if (0xF0 <= $code) { - return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; - } - if (0xE0 <= $code) { - return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; - } - if (0xC0 <= $code) { - return (($code - 0xC0) << 6) + $s[2] - 0x80; - } - - return $code; - } -} diff --git a/vendor/symfony/polyfill-php72/README.md b/vendor/symfony/polyfill-php72/README.md deleted file mode 100644 index 82c45f7..0000000 --- a/vendor/symfony/polyfill-php72/README.md +++ /dev/null @@ -1,27 +0,0 @@ -Symfony Polyfill / Php72 -======================== - -This component provides functions added to PHP 7.2 core: - -- [`spl_object_id`](https://php.net/spl_object_id) -- [`stream_isatty`](https://php.net/stream_isatty) - -On Windows only: - -- [`sapi_windows_vt100_support`](https://php.net/sapi_windows_vt100_support) - -Moved to core since 7.2 (was in the optional XML extension earlier): - -- [`utf8_encode`](https://php.net/utf8_encode) -- [`utf8_decode`](https://php.net/utf8_decode) - -Also, it provides a constant added to PHP 7.2: -- [`PHP_OS_FAMILY`](http://php.net/manual/en/reserved.constants.php#constant.php-os-family) - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-php72/bootstrap.php b/vendor/symfony/polyfill-php72/bootstrap.php deleted file mode 100644 index 519056d..0000000 --- a/vendor/symfony/polyfill-php72/bootstrap.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Php72 as p; - -if (PHP_VERSION_ID < 70200) { - if ('\\' === DIRECTORY_SEPARATOR && !function_exists('sapi_windows_vt100_support')) { - function sapi_windows_vt100_support($stream, $enable = null) { return p\Php72::sapi_windows_vt100_support($stream, $enable); } - } - if (!function_exists('stream_isatty')) { - function stream_isatty($stream) { return p\Php72::stream_isatty($stream); } - } - if (!function_exists('utf8_encode')) { - function utf8_encode($s) { return p\Php72::utf8_encode($s); } - function utf8_decode($s) { return p\Php72::utf8_decode($s); } - } - if (!function_exists('spl_object_id')) { - function spl_object_id($s) { return p\Php72::spl_object_id($s); } - } - if (!defined('PHP_OS_FAMILY')) { - define('PHP_OS_FAMILY', p\Php72::php_os_family()); - } - if (!function_exists('mb_chr')) { - function mb_ord($s, $enc = null) { return p\Php72::mb_ord($s, $enc); } - function mb_chr($code, $enc = null) { return p\Php72::mb_chr($code, $enc); } - function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); } - } -} diff --git a/vendor/symfony/polyfill-php72/composer.json b/vendor/symfony/polyfill-php72/composer.json deleted file mode 100644 index 0d37167..0000000 --- a/vendor/symfony/polyfill-php72/composer.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "symfony/polyfill-php72", - "type": "library", - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "keywords": ["polyfill", "shim", "compatibility", "portable"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=5.3.3" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Php72\\": "" }, - "files": [ "bootstrap.php" ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "1.13-dev" - } - } -} diff --git a/vendor/symfony/polyfill-php73/LICENSE b/vendor/symfony/polyfill-php73/LICENSE deleted file mode 100644 index 3f853aa..0000000 --- a/vendor/symfony/polyfill-php73/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2018-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/polyfill-php73/Php73.php b/vendor/symfony/polyfill-php73/Php73.php deleted file mode 100644 index 7c99d19..0000000 --- a/vendor/symfony/polyfill-php73/Php73.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Php73; - -/** - * @author Gabriel Caruso - * @author Ion Bazan - * - * @internal - */ -final class Php73 -{ - public static $startAt = 1533462603; - - /** - * @param bool $asNum - * - * @return array|float|int - */ - public static function hrtime($asNum = false) - { - $ns = microtime(false); - $s = substr($ns, 11) - self::$startAt; - $ns = 1E9 * (float) $ns; - - if ($asNum) { - $ns += $s * 1E9; - - return \PHP_INT_SIZE === 4 ? $ns : (int) $ns; - } - - return array($s, (int) $ns); - } -} diff --git a/vendor/symfony/polyfill-php73/README.md b/vendor/symfony/polyfill-php73/README.md deleted file mode 100644 index b3ebbce..0000000 --- a/vendor/symfony/polyfill-php73/README.md +++ /dev/null @@ -1,18 +0,0 @@ -Symfony Polyfill / Php73 -======================== - -This component provides functions added to PHP 7.3 core: - -- [`array_key_first`](https://php.net/array_key_first) -- [`array_key_last`](https://php.net/array_key_last) -- [`hrtime`](https://php.net/function.hrtime) -- [`is_countable`](https://php.net/is_countable) -- [`JsonException`](https://php.net/JsonException) - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php b/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php deleted file mode 100644 index 673d100..0000000 --- a/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php +++ /dev/null @@ -1,14 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class JsonException extends Exception -{ -} diff --git a/vendor/symfony/polyfill-php73/bootstrap.php b/vendor/symfony/polyfill-php73/bootstrap.php deleted file mode 100644 index 4c3f44f..0000000 --- a/vendor/symfony/polyfill-php73/bootstrap.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Php73 as p; - -if (PHP_VERSION_ID < 70300) { - if (!function_exists('is_countable')) { - function is_countable($var) { return is_array($var) || $var instanceof Countable || $var instanceof ResourceBundle || $var instanceof SimpleXmlElement; } - } - - if (!function_exists('hrtime')) { - require_once __DIR__.'/Php73.php'; - p\Php73::$startAt = (int) microtime(true); - function hrtime($asNum = false) { return p\Php73::hrtime($asNum); } - } - - if (!function_exists('array_key_first')) { - function array_key_first(array $array) { foreach ($array as $key => $value) { return $key; } } - } - - if (!function_exists('array_key_last')) { - function array_key_last(array $array) { end($array); return key($array); } - } -} diff --git a/vendor/symfony/polyfill-php73/composer.json b/vendor/symfony/polyfill-php73/composer.json deleted file mode 100644 index cffa32f..0000000 --- a/vendor/symfony/polyfill-php73/composer.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "symfony/polyfill-php73", - "type": "library", - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "keywords": ["polyfill", "shim", "compatibility", "portable"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": ">=5.3.3" - }, - "autoload": { - "psr-4": { "Symfony\\Polyfill\\Php73\\": "" }, - "files": [ "bootstrap.php" ], - "classmap": [ "Resources/stubs" ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "1.13-dev" - } - } -} diff --git a/vendor/symfony/routing/.gitattributes b/vendor/symfony/routing/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/routing/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/routing/Annotation/Route.php b/vendor/symfony/routing/Annotation/Route.php deleted file mode 100644 index 4d5f618..0000000 --- a/vendor/symfony/routing/Annotation/Route.php +++ /dev/null @@ -1,182 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Annotation; - -/** - * Annotation class for @Route(). - * - * @Annotation - * @Target({"CLASS", "METHOD"}) - * - * @author Fabien Potencier - */ -class Route -{ - private $path; - private $localizedPaths = []; - private $name; - private $requirements = []; - private $options = []; - private $defaults = []; - private $host; - private $methods = []; - private $schemes = []; - private $condition; - private $locale; - private $format; - private $utf8; - - /** - * @param array $data An array of key/value parameters - * - * @throws \BadMethodCallException - */ - public function __construct(array $data) - { - if (isset($data['localized_paths'])) { - throw new \BadMethodCallException(sprintf('Unknown property "localized_paths" on annotation "%s".', \get_class($this))); - } - - if (isset($data['value'])) { - $data[\is_array($data['value']) ? 'localized_paths' : 'path'] = $data['value']; - unset($data['value']); - } - - if (isset($data['path']) && \is_array($data['path'])) { - $data['localized_paths'] = $data['path']; - unset($data['path']); - } - - if (isset($data['locale'])) { - $data['defaults']['_locale'] = $data['locale']; - unset($data['locale']); - } - - if (isset($data['format'])) { - $data['defaults']['_format'] = $data['format']; - unset($data['format']); - } - - if (isset($data['utf8'])) { - $data['options']['utf8'] = filter_var($data['utf8'], FILTER_VALIDATE_BOOLEAN) ?: false; - unset($data['utf8']); - } - - foreach ($data as $key => $value) { - $method = 'set'.str_replace('_', '', $key); - if (!method_exists($this, $method)) { - throw new \BadMethodCallException(sprintf('Unknown property "%s" on annotation "%s".', $key, \get_class($this))); - } - $this->$method($value); - } - } - - public function setPath($path) - { - $this->path = $path; - } - - public function getPath() - { - return $this->path; - } - - public function setLocalizedPaths(array $localizedPaths) - { - $this->localizedPaths = $localizedPaths; - } - - public function getLocalizedPaths(): array - { - return $this->localizedPaths; - } - - public function setHost($pattern) - { - $this->host = $pattern; - } - - public function getHost() - { - return $this->host; - } - - public function setName($name) - { - $this->name = $name; - } - - public function getName() - { - return $this->name; - } - - public function setRequirements($requirements) - { - $this->requirements = $requirements; - } - - public function getRequirements() - { - return $this->requirements; - } - - public function setOptions($options) - { - $this->options = $options; - } - - public function getOptions() - { - return $this->options; - } - - public function setDefaults($defaults) - { - $this->defaults = $defaults; - } - - public function getDefaults() - { - return $this->defaults; - } - - public function setSchemes($schemes) - { - $this->schemes = \is_array($schemes) ? $schemes : [$schemes]; - } - - public function getSchemes() - { - return $this->schemes; - } - - public function setMethods($methods) - { - $this->methods = \is_array($methods) ? $methods : [$methods]; - } - - public function getMethods() - { - return $this->methods; - } - - public function setCondition($condition) - { - $this->condition = $condition; - } - - public function getCondition() - { - return $this->condition; - } -} diff --git a/vendor/symfony/routing/CHANGELOG.md b/vendor/symfony/routing/CHANGELOG.md deleted file mode 100644 index f304a12..0000000 --- a/vendor/symfony/routing/CHANGELOG.md +++ /dev/null @@ -1,268 +0,0 @@ -CHANGELOG -========= - -5.0.0 ------ - - * removed `PhpGeneratorDumper` and `PhpMatcherDumper` - * removed `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options - * `Serializable` implementing methods for `Route` and `CompiledRoute` are final - * removed referencing service route loaders with a single colon - * Removed `ServiceRouterLoader` and `ObjectRouteLoader`. - -4.4.0 ------ - - * Deprecated `ServiceRouterLoader` in favor of `ContainerLoader`. - * Deprecated `ObjectRouteLoader` in favor of `ObjectLoader`. - * Added a way to exclude patterns of resources from being imported by the `import()` method - -4.3.0 ------ - - * added `CompiledUrlMatcher` and `CompiledUrlMatcherDumper` - * added `CompiledUrlGenerator` and `CompiledUrlGeneratorDumper` - * deprecated `PhpGeneratorDumper` and `PhpMatcherDumper` - * deprecated `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options - * `Serializable` implementing methods for `Route` and `CompiledRoute` are marked as `@internal` and `@final`. - Instead of overwriting them, use `__serialize` and `__unserialize` as extension points which are forward compatible - with the new serialization methods in PHP 7.4. - * exposed `utf8` Route option, defaults "locale" and "format" in configuration loaders and configurators - * added support for invokable service route loaders - -4.2.0 ------ - - * added fallback to cultureless locale for internationalized routes - -4.0.0 ------ - - * dropped support for using UTF-8 route patterns without using the `utf8` option - * dropped support for using UTF-8 route requirements without using the `utf8` option - -3.4.0 ------ - - * Added `NoConfigurationException`. - * Added the possibility to define a prefix for all routes of a controller via @Route(name="prefix_") - * Added support for prioritized routing loaders. - * Add matched and default parameters to redirect responses - * Added support for a `controller` keyword for configuring route controllers in YAML and XML configurations. - -3.3.0 ------ - - * [DEPRECATION] Class parameters have been deprecated and will be removed in 4.0. - * router.options.generator_class - * router.options.generator_base_class - * router.options.generator_dumper_class - * router.options.matcher_class - * router.options.matcher_base_class - * router.options.matcher_dumper_class - * router.options.matcher.cache_class - * router.options.generator.cache_class - -3.2.0 ------ - - * Added support for `bool`, `int`, `float`, `string`, `list` and `map` defaults in XML configurations. - * Added support for UTF-8 requirements - -2.8.0 ------ - - * allowed specifying a directory to recursively load all routing configuration files it contains - * Added ObjectRouteLoader and ServiceRouteLoader that allow routes to be loaded - by calling a method on an object/service. - * [DEPRECATION] Deprecated the hardcoded value for the `$referenceType` argument of the `UrlGeneratorInterface::generate` method. - Use the constants defined in the `UrlGeneratorInterface` instead. - - Before: - - ```php - $router->generate('blog_show', ['slug' => 'my-blog-post'], true); - ``` - - After: - - ```php - use Symfony\Component\Routing\Generator\UrlGeneratorInterface; - - $router->generate('blog_show', ['slug' => 'my-blog-post'], UrlGeneratorInterface::ABSOLUTE_URL); - ``` - -2.5.0 ------ - - * [DEPRECATION] The `ApacheMatcherDumper` and `ApacheUrlMatcher` were deprecated and - will be removed in Symfony 3.0, since the performance gains were minimal and - it's hard to replicate the behavior of PHP implementation. - -2.3.0 ------ - - * added RequestContext::getQueryString() - -2.2.0 ------ - - * [DEPRECATION] Several route settings have been renamed (the old ones will be removed in 3.0): - - * The `pattern` setting for a route has been deprecated in favor of `path` - * The `_scheme` and `_method` requirements have been moved to the `schemes` and `methods` settings - - Before: - - ```yaml - article_edit: - pattern: /article/{id} - requirements: { '_method': 'POST|PUT', '_scheme': 'https', 'id': '\d+' } - ``` - - ```xml - - POST|PUT - https - \d+ - - ``` - - ```php - $route = new Route(); - $route->setPattern('/article/{id}'); - $route->setRequirement('_method', 'POST|PUT'); - $route->setRequirement('_scheme', 'https'); - ``` - - After: - - ```yaml - article_edit: - path: /article/{id} - methods: [POST, PUT] - schemes: https - requirements: { 'id': '\d+' } - ``` - - ```xml - - \d+ - - ``` - - ```php - $route = new Route(); - $route->setPath('/article/{id}'); - $route->setMethods(['POST', 'PUT']); - $route->setSchemes('https'); - ``` - - * [BC BREAK] RouteCollection does not behave like a tree structure anymore but as - a flat array of Routes. So when using PHP to build the RouteCollection, you must - make sure to add routes to the sub-collection before adding it to the parent - collection (this is not relevant when using YAML or XML for Route definitions). - - Before: - - ```php - $rootCollection = new RouteCollection(); - $subCollection = new RouteCollection(); - $rootCollection->addCollection($subCollection); - $subCollection->add('foo', new Route('/foo')); - ``` - - After: - - ```php - $rootCollection = new RouteCollection(); - $subCollection = new RouteCollection(); - $subCollection->add('foo', new Route('/foo')); - $rootCollection->addCollection($subCollection); - ``` - - Also one must call `addCollection` from the bottom to the top hierarchy. - So the correct sequence is the following (and not the reverse): - - ```php - $childCollection->addCollection($grandchildCollection); - $rootCollection->addCollection($childCollection); - ``` - - * [DEPRECATION] The methods `RouteCollection::getParent()` and `RouteCollection::getRoot()` - have been deprecated and will be removed in Symfony 2.3. - * [BC BREAK] Misusing the `RouteCollection::addPrefix` method to add defaults, requirements - or options without adding a prefix is not supported anymore. So if you called `addPrefix` - with an empty prefix or `/` only (both have no relevance), like - `addPrefix('', $defaultsArray, $requirementsArray, $optionsArray)` - you need to use the new dedicated methods `addDefaults($defaultsArray)`, - `addRequirements($requirementsArray)` or `addOptions($optionsArray)` instead. - * [DEPRECATION] The `$options` parameter to `RouteCollection::addPrefix()` has been deprecated - because adding options has nothing to do with adding a path prefix. If you want to add options - to all child routes of a RouteCollection, you can use `addOptions()`. - * [DEPRECATION] The method `RouteCollection::getPrefix()` has been deprecated - because it suggested that all routes in the collection would have this prefix, which is - not necessarily true. On top of that, since there is no tree structure anymore, this method - is also useless. Don't worry about performance, prefix optimization for matching is still done - in the dumper, which was also improved in 2.2.0 to find even more grouping possibilities. - * [DEPRECATION] `RouteCollection::addCollection(RouteCollection $collection)` should now only be - used with a single parameter. The other params `$prefix`, `$default`, `$requirements` and `$options` - will still work, but have been deprecated. The `addPrefix` method should be used for this - use-case instead. - Before: `$parentCollection->addCollection($collection, '/prefix', [...], [...])` - After: - ```php - $collection->addPrefix('/prefix', [...], [...]); - $parentCollection->addCollection($collection); - ``` - * added support for the method default argument values when defining a @Route - * Adjacent placeholders without separator work now, e.g. `/{x}{y}{z}.{_format}`. - * Characters that function as separator between placeholders are now whitelisted - to fix routes with normal text around a variable, e.g. `/prefix{var}suffix`. - * [BC BREAK] The default requirement of a variable has been changed slightly. - Previously it disallowed the previous and the next char around a variable. Now - it disallows the slash (`/`) and the next char. Using the previous char added - no value and was problematic because the route `/index.{_format}` would be - matched by `/index.ht/ml`. - * The default requirement now uses possessive quantifiers when possible which - improves matching performance by up to 20% because it prevents backtracking - when it's not needed. - * The ConfigurableRequirementsInterface can now also be used to disable the requirements - check on URL generation completely by calling `setStrictRequirements(null)`. It - improves performance in production environment as you should know that params always - pass the requirements (otherwise it would break your link anyway). - * There is no restriction on the route name anymore. So non-alphanumeric characters - are now also allowed. - * [BC BREAK] `RouteCompilerInterface::compile(Route $route)` was made static - (only relevant if you implemented your own RouteCompiler). - * Added possibility to generate relative paths and network paths in the UrlGenerator, e.g. - "../parent-file" and "//example.com/dir/file". The third parameter in - `UrlGeneratorInterface::generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)` - now accepts more values and you should use the constants defined in `UrlGeneratorInterface` for - claritiy. The old method calls with a Boolean parameter will continue to work because they - equal the signature using the constants. - -2.1.0 ------ - - * added RequestMatcherInterface - * added RequestContext::fromRequest() - * the UrlMatcher does not throw a \LogicException anymore when the required - scheme is not the current one - * added TraceableUrlMatcher - * added the possibility to define options, default values and requirements - for placeholders in prefix, including imported routes - * added RouterInterface::getRouteCollection - * [BC BREAK] the UrlMatcher urldecodes the route parameters only once, they - were decoded twice before. Note that the `urldecode()` calls have been - changed for a single `rawurldecode()` in order to support `+` for input - paths. - * added RouteCollection::getRoot method to retrieve the root of a - RouteCollection tree - * [BC BREAK] made RouteCollection::setParent private which could not have - been used anyway without creating inconsistencies - * [BC BREAK] RouteCollection::remove also removes a route from parent - collections (not only from its children) - * added ConfigurableRequirementsInterface that allows to disable exceptions - (and generate empty URLs instead) when generating a route with an invalid - parameter value diff --git a/vendor/symfony/routing/CompiledRoute.php b/vendor/symfony/routing/CompiledRoute.php deleted file mode 100644 index 9ffd1b5..0000000 --- a/vendor/symfony/routing/CompiledRoute.php +++ /dev/null @@ -1,173 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -/** - * CompiledRoutes are returned by the RouteCompiler class. - * - * @author Fabien Potencier - */ -class CompiledRoute implements \Serializable -{ - private $variables; - private $tokens; - private $staticPrefix; - private $regex; - private $pathVariables; - private $hostVariables; - private $hostRegex; - private $hostTokens; - - /** - * @param string $staticPrefix The static prefix of the compiled route - * @param string $regex The regular expression to use to match this route - * @param array $tokens An array of tokens to use to generate URL for this route - * @param array $pathVariables An array of path variables - * @param string|null $hostRegex Host regex - * @param array $hostTokens Host tokens - * @param array $hostVariables An array of host variables - * @param array $variables An array of variables (variables defined in the path and in the host patterns) - */ - public function __construct(string $staticPrefix, string $regex, array $tokens, array $pathVariables, string $hostRegex = null, array $hostTokens = [], array $hostVariables = [], array $variables = []) - { - $this->staticPrefix = $staticPrefix; - $this->regex = $regex; - $this->tokens = $tokens; - $this->pathVariables = $pathVariables; - $this->hostRegex = $hostRegex; - $this->hostTokens = $hostTokens; - $this->hostVariables = $hostVariables; - $this->variables = $variables; - } - - public function __serialize(): array - { - return [ - 'vars' => $this->variables, - 'path_prefix' => $this->staticPrefix, - 'path_regex' => $this->regex, - 'path_tokens' => $this->tokens, - 'path_vars' => $this->pathVariables, - 'host_regex' => $this->hostRegex, - 'host_tokens' => $this->hostTokens, - 'host_vars' => $this->hostVariables, - ]; - } - - /** - * @internal - */ - final public function serialize(): string - { - return serialize($this->__serialize()); - } - - public function __unserialize(array $data): void - { - $this->variables = $data['vars']; - $this->staticPrefix = $data['path_prefix']; - $this->regex = $data['path_regex']; - $this->tokens = $data['path_tokens']; - $this->pathVariables = $data['path_vars']; - $this->hostRegex = $data['host_regex']; - $this->hostTokens = $data['host_tokens']; - $this->hostVariables = $data['host_vars']; - } - - /** - * @internal - */ - final public function unserialize($serialized) - { - $this->__unserialize(unserialize($serialized, ['allowed_classes' => false])); - } - - /** - * Returns the static prefix. - * - * @return string The static prefix - */ - public function getStaticPrefix() - { - return $this->staticPrefix; - } - - /** - * Returns the regex. - * - * @return string The regex - */ - public function getRegex() - { - return $this->regex; - } - - /** - * Returns the host regex. - * - * @return string|null The host regex or null - */ - public function getHostRegex() - { - return $this->hostRegex; - } - - /** - * Returns the tokens. - * - * @return array The tokens - */ - public function getTokens() - { - return $this->tokens; - } - - /** - * Returns the host tokens. - * - * @return array The tokens - */ - public function getHostTokens() - { - return $this->hostTokens; - } - - /** - * Returns the variables. - * - * @return array The variables - */ - public function getVariables() - { - return $this->variables; - } - - /** - * Returns the path variables. - * - * @return array The variables - */ - public function getPathVariables() - { - return $this->pathVariables; - } - - /** - * Returns the host variables. - * - * @return array The variables - */ - public function getHostVariables() - { - return $this->hostVariables; - } -} diff --git a/vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php b/vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php deleted file mode 100644 index 7068825..0000000 --- a/vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Adds tagged routing.loader services to routing.resolver service. - * - * @author Fabien Potencier - */ -class RoutingResolverPass implements CompilerPassInterface -{ - use PriorityTaggedServiceTrait; - - private $resolverServiceId; - private $loaderTag; - - public function __construct(string $resolverServiceId = 'routing.resolver', string $loaderTag = 'routing.loader') - { - $this->resolverServiceId = $resolverServiceId; - $this->loaderTag = $loaderTag; - } - - public function process(ContainerBuilder $container) - { - if (false === $container->hasDefinition($this->resolverServiceId)) { - return; - } - - $definition = $container->getDefinition($this->resolverServiceId); - - foreach ($this->findAndSortTaggedServices($this->loaderTag, $container) as $id) { - $definition->addMethodCall('addLoader', [new Reference($id)]); - } - } -} diff --git a/vendor/symfony/routing/Exception/ExceptionInterface.php b/vendor/symfony/routing/Exception/ExceptionInterface.php deleted file mode 100644 index 22e72b1..0000000 --- a/vendor/symfony/routing/Exception/ExceptionInterface.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * ExceptionInterface. - * - * @author Alexandre Salomé - */ -interface ExceptionInterface extends \Throwable -{ -} diff --git a/vendor/symfony/routing/Exception/InvalidParameterException.php b/vendor/symfony/routing/Exception/InvalidParameterException.php deleted file mode 100644 index 94d841f..0000000 --- a/vendor/symfony/routing/Exception/InvalidParameterException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * Exception thrown when a parameter is not valid. - * - * @author Alexandre Salomé - */ -class InvalidParameterException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/routing/Exception/MethodNotAllowedException.php b/vendor/symfony/routing/Exception/MethodNotAllowedException.php deleted file mode 100644 index b897081..0000000 --- a/vendor/symfony/routing/Exception/MethodNotAllowedException.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * The resource was found but the request method is not allowed. - * - * This exception should trigger an HTTP 405 response in your application code. - * - * @author Kris Wallsmith - */ -class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface -{ - protected $allowedMethods = []; - - public function __construct(array $allowedMethods, string $message = null, int $code = 0, \Throwable $previous = null) - { - $this->allowedMethods = array_map('strtoupper', $allowedMethods); - - parent::__construct($message, $code, $previous); - } - - /** - * Gets the allowed HTTP methods. - * - * @return array - */ - public function getAllowedMethods() - { - return $this->allowedMethods; - } -} diff --git a/vendor/symfony/routing/Exception/MissingMandatoryParametersException.php b/vendor/symfony/routing/Exception/MissingMandatoryParametersException.php deleted file mode 100644 index 57f3a40..0000000 --- a/vendor/symfony/routing/Exception/MissingMandatoryParametersException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * Exception thrown when a route cannot be generated because of missing - * mandatory parameters. - * - * @author Alexandre Salomé - */ -class MissingMandatoryParametersException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/routing/Exception/NoConfigurationException.php b/vendor/symfony/routing/Exception/NoConfigurationException.php deleted file mode 100644 index 333bc74..0000000 --- a/vendor/symfony/routing/Exception/NoConfigurationException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * Exception thrown when no routes are configured. - * - * @author Yonel Ceruto - */ -class NoConfigurationException extends ResourceNotFoundException -{ -} diff --git a/vendor/symfony/routing/Exception/ResourceNotFoundException.php b/vendor/symfony/routing/Exception/ResourceNotFoundException.php deleted file mode 100644 index ccbca15..0000000 --- a/vendor/symfony/routing/Exception/ResourceNotFoundException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * The resource was not found. - * - * This exception should trigger an HTTP 404 response in your application code. - * - * @author Kris Wallsmith - */ -class ResourceNotFoundException extends \RuntimeException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/routing/Exception/RouteNotFoundException.php b/vendor/symfony/routing/Exception/RouteNotFoundException.php deleted file mode 100644 index 24ab0b4..0000000 --- a/vendor/symfony/routing/Exception/RouteNotFoundException.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Exception; - -/** - * Exception thrown when a route does not exist. - * - * @author Alexandre Salomé - */ -class RouteNotFoundException extends \InvalidArgumentException implements ExceptionInterface -{ -} diff --git a/vendor/symfony/routing/Generator/CompiledUrlGenerator.php b/vendor/symfony/routing/Generator/CompiledUrlGenerator.php deleted file mode 100644 index 8c489f8..0000000 --- a/vendor/symfony/routing/Generator/CompiledUrlGenerator.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\RequestContext; - -/** - * Generates URLs based on rules dumped by CompiledUrlGeneratorDumper. - */ -class CompiledUrlGenerator extends UrlGenerator -{ - private $compiledRoutes = []; - private $defaultLocale; - - public function __construct(array $compiledRoutes, RequestContext $context, LoggerInterface $logger = null, string $defaultLocale = null) - { - $this->compiledRoutes = $compiledRoutes; - $this->context = $context; - $this->logger = $logger; - $this->defaultLocale = $defaultLocale; - } - - public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) - { - $locale = $parameters['_locale'] - ?? $this->context->getParameter('_locale') - ?: $this->defaultLocale; - - if (null !== $locale) { - do { - if (($this->compiledRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) { - unset($parameters['_locale']); - $name .= '.'.$locale; - break; - } - } while (false !== $locale = strstr($locale, '_', true)); - } - - if (!isset($this->compiledRoutes[$name])) { - throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); - } - - list($variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes) = $this->compiledRoutes[$name]; - - return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes); - } -} diff --git a/vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php b/vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php deleted file mode 100644 index 568f7f7..0000000 --- a/vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator; - -/** - * ConfigurableRequirementsInterface must be implemented by URL generators that - * can be configured whether an exception should be generated when the parameters - * do not match the requirements. It is also possible to disable the requirements - * check for URL generation completely. - * - * The possible configurations and use-cases: - * - setStrictRequirements(true): Throw an exception for mismatching requirements. This - * is mostly useful in development environment. - * - setStrictRequirements(false): Don't throw an exception but return an empty string as URL for - * mismatching requirements and log the problem. Useful when you cannot control all - * params because they come from third party libs but don't want to have a 404 in - * production environment. It should log the mismatch so one can review it. - * - setStrictRequirements(null): Return the URL with the given parameters without - * checking the requirements at all. When generating a URL you should either trust - * your params or you validated them beforehand because otherwise it would break your - * link anyway. So in production environment you should know that params always pass - * the requirements. Thus this option allows to disable the check on URL generation for - * performance reasons (saving a preg_match for each requirement every time a URL is - * generated). - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -interface ConfigurableRequirementsInterface -{ - /** - * Enables or disables the exception on incorrect parameters. - * Passing null will deactivate the requirements check completely. - */ - public function setStrictRequirements(?bool $enabled); - - /** - * Returns whether to throw an exception on incorrect parameters. - * Null means the requirements check is deactivated completely. - * - * @return bool|null - */ - public function isStrictRequirements(); -} diff --git a/vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php b/vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php deleted file mode 100644 index e90a40a..0000000 --- a/vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php +++ /dev/null @@ -1,73 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator\Dumper; - -use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; - -/** - * CompiledUrlGeneratorDumper creates a PHP array to be used with CompiledUrlGenerator. - * - * @author Fabien Potencier - * @author Tobias Schultze - * @author Nicolas Grekas - */ -class CompiledUrlGeneratorDumper extends GeneratorDumper -{ - public function getCompiledRoutes(): array - { - $compiledRoutes = []; - foreach ($this->getRoutes()->all() as $name => $route) { - $compiledRoute = $route->compile(); - - $compiledRoutes[$name] = [ - $compiledRoute->getVariables(), - $route->getDefaults(), - $route->getRequirements(), - $compiledRoute->getTokens(), - $compiledRoute->getHostTokens(), - $route->getSchemes(), - ]; - } - - return $compiledRoutes; - } - - /** - * {@inheritdoc} - */ - public function dump(array $options = []) - { - return <<generateDeclaredRoutes()} -]; - -EOF; - } - - /** - * Generates PHP code representing an array of defined routes - * together with the routes properties (e.g. requirements). - */ - private function generateDeclaredRoutes(): string - { - $routes = ''; - foreach ($this->getCompiledRoutes() as $name => $properties) { - $routes .= sprintf("\n '%s' => %s,", $name, CompiledUrlMatcherDumper::export($properties)); - } - - return $routes; - } -} diff --git a/vendor/symfony/routing/Generator/Dumper/GeneratorDumper.php b/vendor/symfony/routing/Generator/Dumper/GeneratorDumper.php deleted file mode 100644 index 659c5ba..0000000 --- a/vendor/symfony/routing/Generator/Dumper/GeneratorDumper.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * GeneratorDumper is the base class for all built-in generator dumpers. - * - * @author Fabien Potencier - */ -abstract class GeneratorDumper implements GeneratorDumperInterface -{ - private $routes; - - public function __construct(RouteCollection $routes) - { - $this->routes = $routes; - } - - /** - * {@inheritdoc} - */ - public function getRoutes() - { - return $this->routes; - } -} diff --git a/vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php b/vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php deleted file mode 100644 index 26daefc..0000000 --- a/vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * GeneratorDumperInterface is the interface that all generator dumper classes must implement. - * - * @author Fabien Potencier - */ -interface GeneratorDumperInterface -{ - /** - * Dumps a set of routes to a string representation of executable code - * that can then be used to generate a URL of such a route. - * - * @return string Executable code - */ - public function dump(array $options = []); - - /** - * Gets the routes to dump. - * - * @return RouteCollection A RouteCollection instance - */ - public function getRoutes(); -} diff --git a/vendor/symfony/routing/Generator/UrlGenerator.php b/vendor/symfony/routing/Generator/UrlGenerator.php deleted file mode 100644 index 504dd32..0000000 --- a/vendor/symfony/routing/Generator/UrlGenerator.php +++ /dev/null @@ -1,356 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Routing\Exception\InvalidParameterException; -use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; -use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\RouteCollection; - -/** - * UrlGenerator can generate a URL or a path for any route in the RouteCollection - * based on the passed parameters. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface -{ - private const QUERY_FRAGMENT_DECODED = [ - // RFC 3986 explicitly allows those in the query/fragment to reference other URIs unencoded - '%2F' => '/', - '%3F' => '?', - // reserved chars that have no special meaning for HTTP URIs in a query or fragment - // this excludes esp. "&", "=" and also "+" because PHP would treat it as a space (form-encoded) - '%40' => '@', - '%3A' => ':', - '%21' => '!', - '%3B' => ';', - '%2C' => ',', - '%2A' => '*', - ]; - - protected $routes; - protected $context; - - /** - * @var bool|null - */ - protected $strictRequirements = true; - - protected $logger; - - private $defaultLocale; - - /** - * This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL. - * - * PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars - * to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g. - * "?" and "#" (would be interpreted wrongly as query and fragment identifier), - * "'" and """ (are used as delimiters in HTML). - */ - protected $decodedChars = [ - // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning - // some webservers don't allow the slash in encoded form in the path for security reasons anyway - // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss - '%2F' => '/', - // the following chars are general delimiters in the URI specification but have only special meaning in the authority component - // so they can safely be used in the path in unencoded form - '%40' => '@', - '%3A' => ':', - // these chars are only sub-delimiters that have no predefined meaning and can therefore be used literally - // so URI producing applications can use these chars to delimit subcomponents in a path segment without being encoded for better readability - '%3B' => ';', - '%2C' => ',', - '%3D' => '=', - '%2B' => '+', - '%21' => '!', - '%2A' => '*', - '%7C' => '|', - ]; - - public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null, string $defaultLocale = null) - { - $this->routes = $routes; - $this->context = $context; - $this->logger = $logger; - $this->defaultLocale = $defaultLocale; - } - - /** - * {@inheritdoc} - */ - public function setContext(RequestContext $context) - { - $this->context = $context; - } - - /** - * {@inheritdoc} - */ - public function getContext() - { - return $this->context; - } - - /** - * {@inheritdoc} - */ - public function setStrictRequirements(?bool $enabled) - { - $this->strictRequirements = $enabled; - } - - /** - * {@inheritdoc} - */ - public function isStrictRequirements() - { - return $this->strictRequirements; - } - - /** - * {@inheritdoc} - */ - public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) - { - $route = null; - $locale = $parameters['_locale'] - ?? $this->context->getParameter('_locale') - ?: $this->defaultLocale; - - if (null !== $locale) { - do { - if (null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) { - unset($parameters['_locale']); - break; - } - } while (false !== $locale = strstr($locale, '_', true)); - } - - if (null === $route = $route ?? $this->routes->get($name)) { - throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); - } - - // the Route has a cache of its own and is not recompiled as long as it does not get modified - $compiledRoute = $route->compile(); - - return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens(), $route->getSchemes()); - } - - /** - * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route - * @throws InvalidParameterException When a parameter value for a placeholder is not correct because - * it does not match the requirement - * - * @return string - */ - protected function doGenerate(array $variables, array $defaults, array $requirements, array $tokens, array $parameters, string $name, int $referenceType, array $hostTokens, array $requiredSchemes = []) - { - $variables = array_flip($variables); - $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters); - - // all params must be given - if ($diff = array_diff_key($variables, $mergedParams)) { - throw new MissingMandatoryParametersException(sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', array_keys($diff)), $name)); - } - - $url = ''; - $optional = true; - $message = 'Parameter "{parameter}" for route "{route}" must match "{expected}" ("{given}" given) to generate a corresponding URL.'; - foreach ($tokens as $token) { - if ('variable' === $token[0]) { - $varName = $token[3]; - // variable is not important by default - $important = $token[5] ?? false; - - if (!$optional || $important || !\array_key_exists($varName, $defaults) || (null !== $mergedParams[$varName] && (string) $mergedParams[$varName] !== (string) $defaults[$varName])) { - // check requirement (while ignoring look-around patterns) - if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|strictRequirements) { - throw new InvalidParameterException(strtr($message, ['{parameter}' => $varName, '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$varName]])); - } - - if ($this->logger) { - $this->logger->error($message, ['parameter' => $varName, 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$varName]]); - } - - return ''; - } - - $url = $token[1].$mergedParams[$varName].$url; - $optional = false; - } - } else { - // static text - $url = $token[1].$url; - $optional = false; - } - } - - if ('' === $url) { - $url = '/'; - } - - // the contexts base URL is already encoded (see Symfony\Component\HttpFoundation\Request) - $url = strtr(rawurlencode($url), $this->decodedChars); - - // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3 - // so we need to encode them as they are not used for this purpose here - // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route - $url = strtr($url, ['/../' => '/%2E%2E/', '/./' => '/%2E/']); - if ('/..' === substr($url, -3)) { - $url = substr($url, 0, -2).'%2E%2E'; - } elseif ('/.' === substr($url, -2)) { - $url = substr($url, 0, -1).'%2E'; - } - - $schemeAuthority = ''; - $host = $this->context->getHost(); - $scheme = $this->context->getScheme(); - - if ($requiredSchemes) { - if (!\in_array($scheme, $requiredSchemes, true)) { - $referenceType = self::ABSOLUTE_URL; - $scheme = current($requiredSchemes); - } - } - - if ($hostTokens) { - $routeHost = ''; - foreach ($hostTokens as $token) { - if ('variable' === $token[0]) { - // check requirement (while ignoring look-around patterns) - if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|strictRequirements) { - throw new InvalidParameterException(strtr($message, ['{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]])); - } - - if ($this->logger) { - $this->logger->error($message, ['parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]]]); - } - - return ''; - } - - $routeHost = $token[1].$mergedParams[$token[3]].$routeHost; - } else { - $routeHost = $token[1].$routeHost; - } - } - - if ($routeHost !== $host) { - $host = $routeHost; - if (self::ABSOLUTE_URL !== $referenceType) { - $referenceType = self::NETWORK_PATH; - } - } - } - - if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) { - if ('' !== $host || ('' !== $scheme && 'http' !== $scheme && 'https' !== $scheme)) { - $port = ''; - if ('http' === $scheme && 80 !== $this->context->getHttpPort()) { - $port = ':'.$this->context->getHttpPort(); - } elseif ('https' === $scheme && 443 !== $this->context->getHttpsPort()) { - $port = ':'.$this->context->getHttpsPort(); - } - - $schemeAuthority = self::NETWORK_PATH === $referenceType || '' === $scheme ? '//' : "$scheme://"; - $schemeAuthority .= $host.$port; - } - } - - if (self::RELATIVE_PATH === $referenceType) { - $url = self::getRelativePath($this->context->getPathInfo(), $url); - } else { - $url = $schemeAuthority.$this->context->getBaseUrl().$url; - } - - // add a query string if needed - $extra = array_udiff_assoc(array_diff_key($parameters, $variables), $defaults, function ($a, $b) { - return $a == $b ? 0 : 1; - }); - - // extract fragment - $fragment = $defaults['_fragment'] ?? ''; - - if (isset($extra['_fragment'])) { - $fragment = $extra['_fragment']; - unset($extra['_fragment']); - } - - if ($extra && $query = http_build_query($extra, '', '&', PHP_QUERY_RFC3986)) { - $url .= '?'.strtr($query, self::QUERY_FRAGMENT_DECODED); - } - - if ('' !== $fragment) { - $url .= '#'.strtr(rawurlencode($fragment), self::QUERY_FRAGMENT_DECODED); - } - - return $url; - } - - /** - * Returns the target path as relative reference from the base path. - * - * Only the URIs path component (no schema, host etc.) is relevant and must be given, starting with a slash. - * Both paths must be absolute and not contain relative parts. - * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. - * Furthermore, they can be used to reduce the link size in documents. - * - * Example target paths, given a base path of "/a/b/c/d": - * - "/a/b/c/d" -> "" - * - "/a/b/c/" -> "./" - * - "/a/b/" -> "../" - * - "/a/b/c/other" -> "other" - * - "/a/x/y" -> "../../x/y" - * - * @param string $basePath The base path - * @param string $targetPath The target path - * - * @return string The relative target path - */ - public static function getRelativePath(string $basePath, string $targetPath) - { - if ($basePath === $targetPath) { - return ''; - } - - $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); - $targetDirs = explode('/', isset($targetPath[0]) && '/' === $targetPath[0] ? substr($targetPath, 1) : $targetPath); - array_pop($sourceDirs); - $targetFile = array_pop($targetDirs); - - foreach ($sourceDirs as $i => $dir) { - if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { - unset($sourceDirs[$i], $targetDirs[$i]); - } else { - break; - } - } - - $targetDirs[] = $targetFile; - $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs); - - // A reference to the same base directory or an empty subdirectory must be prefixed with "./". - // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used - // as the first segment of a relative-path reference, as it would be mistaken for a scheme name - // (see http://tools.ietf.org/html/rfc3986#section-4.2). - return '' === $path || '/' === $path[0] - || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) - ? "./$path" : $path; - } -} diff --git a/vendor/symfony/routing/Generator/UrlGeneratorInterface.php b/vendor/symfony/routing/Generator/UrlGeneratorInterface.php deleted file mode 100644 index 5890ffa..0000000 --- a/vendor/symfony/routing/Generator/UrlGeneratorInterface.php +++ /dev/null @@ -1,82 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Generator; - -use Symfony\Component\Routing\Exception\InvalidParameterException; -use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; -use Symfony\Component\Routing\Exception\RouteNotFoundException; -use Symfony\Component\Routing\RequestContextAwareInterface; - -/** - * UrlGeneratorInterface is the interface that all URL generator classes must implement. - * - * The constants in this interface define the different types of resource references that - * are declared in RFC 3986: http://tools.ietf.org/html/rfc3986 - * We are using the term "URL" instead of "URI" as this is more common in web applications - * and we do not need to distinguish them as the difference is mostly semantical and - * less technical. Generating URIs, i.e. representation-independent resource identifiers, - * is also possible. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -interface UrlGeneratorInterface extends RequestContextAwareInterface -{ - /** - * Generates an absolute URL, e.g. "http://example.com/dir/file". - */ - const ABSOLUTE_URL = 0; - - /** - * Generates an absolute path, e.g. "/dir/file". - */ - const ABSOLUTE_PATH = 1; - - /** - * Generates a relative path based on the current request path, e.g. "../parent-file". - * - * @see UrlGenerator::getRelativePath() - */ - const RELATIVE_PATH = 2; - - /** - * Generates a network path, e.g. "//example.com/dir/file". - * Such reference reuses the current scheme but specifies the host. - */ - const NETWORK_PATH = 3; - - /** - * Generates a URL or path for a specific route based on the given parameters. - * - * Parameters that reference placeholders in the route pattern will substitute them in the - * path or host. Extra params are added as query string to the URL. - * - * When the passed reference type cannot be generated for the route because it requires a different - * host or scheme than the current one, the method will return a more comprehensive reference - * that includes the required params. For example, when you call this method with $referenceType = ABSOLUTE_PATH - * but the route requires the https scheme whereas the current scheme is http, it will instead return an - * ABSOLUTE_URL with the https scheme and the current host. This makes sure the generated URL matches - * the route in any case. - * - * If there is no route with the given name, the generator must throw the RouteNotFoundException. - * - * The special parameter _fragment will be used as the document fragment suffixed to the final URL. - * - * @return string The generated URL - * - * @throws RouteNotFoundException If the named route doesn't exist - * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route - * @throws InvalidParameterException When a parameter value for a placeholder is not correct because - * it does not match the requirement - */ - public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH); -} diff --git a/vendor/symfony/routing/LICENSE b/vendor/symfony/routing/LICENSE deleted file mode 100644 index a677f43..0000000 --- a/vendor/symfony/routing/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/routing/Loader/AnnotationClassLoader.php b/vendor/symfony/routing/Loader/AnnotationClassLoader.php deleted file mode 100644 index 0c52b12..0000000 --- a/vendor/symfony/routing/Loader/AnnotationClassLoader.php +++ /dev/null @@ -1,332 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Doctrine\Common\Annotations\Reader; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\Config\Loader\LoaderResolverInterface; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\Annotation\Route as RouteAnnotation; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * AnnotationClassLoader loads routing information from a PHP class and its methods. - * - * You need to define an implementation for the getRouteDefaults() method. Most of the - * time, this method should define some PHP callable to be called for the route - * (a controller in MVC speak). - * - * The @Route annotation can be set on the class (for global parameters), - * and on each method. - * - * The @Route annotation main value is the route path. The annotation also - * recognizes several parameters: requirements, options, defaults, schemes, - * methods, host, and name. The name parameter is mandatory. - * Here is an example of how you should be able to use it: - * /** - * * @Route("/Blog") - * * / - * class Blog - * { - * /** - * * @Route("/", name="blog_index") - * * / - * public function index() - * { - * } - * /** - * * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"}) - * * / - * public function show() - * { - * } - * } - * - * @author Fabien Potencier - */ -abstract class AnnotationClassLoader implements LoaderInterface -{ - protected $reader; - - /** - * @var string - */ - protected $routeAnnotationClass = 'Symfony\\Component\\Routing\\Annotation\\Route'; - - /** - * @var int - */ - protected $defaultRouteIndex = 0; - - public function __construct(Reader $reader) - { - $this->reader = $reader; - } - - /** - * Sets the annotation class to read route properties from. - */ - public function setRouteAnnotationClass(string $class) - { - $this->routeAnnotationClass = $class; - } - - /** - * Loads from annotations from a class. - * - * @param string $class A class name - * - * @return RouteCollection A RouteCollection instance - * - * @throws \InvalidArgumentException When route can't be parsed - */ - public function load($class, string $type = null) - { - if (!class_exists($class)) { - throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); - } - - $class = new \ReflectionClass($class); - if ($class->isAbstract()) { - throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class->getName())); - } - - $globals = $this->getGlobals($class); - - $collection = new RouteCollection(); - $collection->addResource(new FileResource($class->getFileName())); - - foreach ($class->getMethods() as $method) { - $this->defaultRouteIndex = 0; - foreach ($this->reader->getMethodAnnotations($method) as $annot) { - if ($annot instanceof $this->routeAnnotationClass) { - $this->addRoute($collection, $annot, $globals, $class, $method); - } - } - } - - if (0 === $collection->count() && $class->hasMethod('__invoke')) { - $globals = $this->resetGlobals(); - foreach ($this->reader->getClassAnnotations($class) as $annot) { - if ($annot instanceof $this->routeAnnotationClass) { - $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); - } - } - } - - return $collection; - } - - /** - * @param RouteAnnotation $annot or an object that exposes a similar interface - */ - protected function addRoute(RouteCollection $collection, $annot, array $globals, \ReflectionClass $class, \ReflectionMethod $method) - { - $name = $annot->getName(); - if (null === $name) { - $name = $this->getDefaultRouteName($class, $method); - } - $name = $globals['name'].$name; - - $requirements = $annot->getRequirements(); - - foreach ($requirements as $placeholder => $requirement) { - if (\is_int($placeholder)) { - throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s::%s()"?', $placeholder, $requirement, $name, $class->getName(), $method->getName())); - } - } - - $defaults = array_replace($globals['defaults'], $annot->getDefaults()); - $requirements = array_replace($globals['requirements'], $requirements); - $options = array_replace($globals['options'], $annot->getOptions()); - $schemes = array_merge($globals['schemes'], $annot->getSchemes()); - $methods = array_merge($globals['methods'], $annot->getMethods()); - - $host = $annot->getHost(); - if (null === $host) { - $host = $globals['host']; - } - - $condition = $annot->getCondition(); - if (null === $condition) { - $condition = $globals['condition']; - } - - $path = $annot->getLocalizedPaths() ?: $annot->getPath(); - $prefix = $globals['localized_paths'] ?: $globals['path']; - $paths = []; - - if (\is_array($path)) { - if (!\is_array($prefix)) { - foreach ($path as $locale => $localePath) { - $paths[$locale] = $prefix.$localePath; - } - } elseif ($missing = array_diff_key($prefix, $path)) { - throw new \LogicException(sprintf('Route to "%s" is missing paths for locale(s) "%s".', $class->name.'::'.$method->name, implode('", "', array_keys($missing)))); - } else { - foreach ($path as $locale => $localePath) { - if (!isset($prefix[$locale])) { - throw new \LogicException(sprintf('Route to "%s" with locale "%s" is missing a corresponding prefix in class "%s".', $method->name, $locale, $class->name)); - } - - $paths[$locale] = $prefix[$locale].$localePath; - } - } - } elseif (\is_array($prefix)) { - foreach ($prefix as $locale => $localePrefix) { - $paths[$locale] = $localePrefix.$path; - } - } else { - $paths[] = $prefix.$path; - } - - foreach ($method->getParameters() as $param) { - if (isset($defaults[$param->name]) || !$param->isDefaultValueAvailable()) { - continue; - } - foreach ($paths as $locale => $path) { - if (preg_match(sprintf('/\{%s(?:<.*?>)?\}/', preg_quote($param->name)), $path)) { - $defaults[$param->name] = $param->getDefaultValue(); - break; - } - } - } - - foreach ($paths as $locale => $path) { - $route = $this->createRoute($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition); - $this->configureRoute($route, $class, $method, $annot); - if (0 !== $locale) { - $route->setDefault('_locale', $locale); - $route->setDefault('_canonical_route', $name); - $collection->add($name.'.'.$locale, $route); - } else { - $collection->add($name, $route); - } - } - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return \is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type); - } - - /** - * {@inheritdoc} - */ - public function setResolver(LoaderResolverInterface $resolver) - { - } - - /** - * {@inheritdoc} - */ - public function getResolver() - { - } - - /** - * Gets the default route name for a class method. - * - * @return string - */ - protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) - { - $name = str_replace('\\', '_', $class->name).'_'.$method->name; - $name = \function_exists('mb_strtolower') && preg_match('//u', $name) ? mb_strtolower($name, 'UTF-8') : strtolower($name); - if ($this->defaultRouteIndex > 0) { - $name .= '_'.$this->defaultRouteIndex; - } - ++$this->defaultRouteIndex; - - return $name; - } - - protected function getGlobals(\ReflectionClass $class) - { - $globals = $this->resetGlobals(); - - if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) { - if (null !== $annot->getName()) { - $globals['name'] = $annot->getName(); - } - - if (null !== $annot->getPath()) { - $globals['path'] = $annot->getPath(); - } - - $globals['localized_paths'] = $annot->getLocalizedPaths(); - - if (null !== $annot->getRequirements()) { - $globals['requirements'] = $annot->getRequirements(); - } - - if (null !== $annot->getOptions()) { - $globals['options'] = $annot->getOptions(); - } - - if (null !== $annot->getDefaults()) { - $globals['defaults'] = $annot->getDefaults(); - } - - if (null !== $annot->getSchemes()) { - $globals['schemes'] = $annot->getSchemes(); - } - - if (null !== $annot->getMethods()) { - $globals['methods'] = $annot->getMethods(); - } - - if (null !== $annot->getHost()) { - $globals['host'] = $annot->getHost(); - } - - if (null !== $annot->getCondition()) { - $globals['condition'] = $annot->getCondition(); - } - - foreach ($globals['requirements'] as $placeholder => $requirement) { - if (\is_int($placeholder)) { - throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" in "%s"?', $placeholder, $requirement, $class->getName())); - } - } - } - - return $globals; - } - - private function resetGlobals(): array - { - return [ - 'path' => null, - 'localized_paths' => [], - 'requirements' => [], - 'options' => [], - 'defaults' => [], - 'schemes' => [], - 'methods' => [], - 'host' => '', - 'condition' => '', - 'name' => '', - ]; - } - - protected function createRoute(string $path, array $defaults, array $requirements, array $options, ?string $host, array $schemes, array $methods, ?string $condition) - { - return new Route($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition); - } - - abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot); -} diff --git a/vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php b/vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php deleted file mode 100644 index 7e52f31..0000000 --- a/vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php +++ /dev/null @@ -1,93 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Resource\DirectoryResource; -use Symfony\Component\Routing\RouteCollection; - -/** - * AnnotationDirectoryLoader loads routing information from annotations set - * on PHP classes and methods. - * - * @author Fabien Potencier - */ -class AnnotationDirectoryLoader extends AnnotationFileLoader -{ - /** - * Loads from annotations from a directory. - * - * @param string $path A directory path - * @param string|null $type The resource type - * - * @return RouteCollection A RouteCollection instance - * - * @throws \InvalidArgumentException When the directory does not exist or its routes cannot be parsed - */ - public function load($path, string $type = null) - { - if (!is_dir($dir = $this->locator->locate($path))) { - return parent::supports($path, $type) ? parent::load($path, $type) : new RouteCollection(); - } - - $collection = new RouteCollection(); - $collection->addResource(new DirectoryResource($dir, '/\.php$/')); - $files = iterator_to_array(new \RecursiveIteratorIterator( - new \RecursiveCallbackFilterIterator( - new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), - function (\SplFileInfo $current) { - return '.' !== substr($current->getBasename(), 0, 1); - } - ), - \RecursiveIteratorIterator::LEAVES_ONLY - )); - usort($files, function (\SplFileInfo $a, \SplFileInfo $b) { - return (string) $a > (string) $b ? 1 : -1; - }); - - foreach ($files as $file) { - if (!$file->isFile() || '.php' !== substr($file->getFilename(), -4)) { - continue; - } - - if ($class = $this->findClass($file)) { - $refl = new \ReflectionClass($class); - if ($refl->isAbstract()) { - continue; - } - - $collection->addCollection($this->loader->load($class, $type)); - } - } - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - if ('annotation' === $type) { - return true; - } - - if ($type || !\is_string($resource)) { - return false; - } - - try { - return is_dir($this->locator->locate($resource)); - } catch (\Exception $e) { - return false; - } - } -} diff --git a/vendor/symfony/routing/Loader/AnnotationFileLoader.php b/vendor/symfony/routing/Loader/AnnotationFileLoader.php deleted file mode 100644 index c183d77..0000000 --- a/vendor/symfony/routing/Loader/AnnotationFileLoader.php +++ /dev/null @@ -1,143 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\FileLocatorInterface; -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\RouteCollection; - -/** - * AnnotationFileLoader loads routing information from annotations set - * on a PHP class and its methods. - * - * @author Fabien Potencier - */ -class AnnotationFileLoader extends FileLoader -{ - protected $loader; - - /** - * @throws \RuntimeException - */ - public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $loader) - { - if (!\function_exists('token_get_all')) { - throw new \LogicException('The Tokenizer extension is required for the routing annotation loaders.'); - } - - parent::__construct($locator); - - $this->loader = $loader; - } - - /** - * Loads from annotations from a file. - * - * @param string $file A PHP file path - * @param string|null $type The resource type - * - * @return RouteCollection|null A RouteCollection instance - * - * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed - */ - public function load($file, string $type = null) - { - $path = $this->locator->locate($file); - - $collection = new RouteCollection(); - if ($class = $this->findClass($path)) { - $refl = new \ReflectionClass($class); - if ($refl->isAbstract()) { - return null; - } - - $collection->addResource(new FileResource($path)); - $collection->addCollection($this->loader->load($class, $type)); - } - - gc_mem_caches(); - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return \is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'annotation' === $type); - } - - /** - * Returns the full class name for the first class in the file. - * - * @return string|false Full class name if found, false otherwise - */ - protected function findClass(string $file) - { - $class = false; - $namespace = false; - $tokens = token_get_all(file_get_contents($file)); - - if (1 === \count($tokens) && T_INLINE_HTML === $tokens[0][0]) { - throw new \InvalidArgumentException(sprintf('The file "%s" does not contain PHP code. Did you forgot to add the " 0; --$j) { - if (!isset($tokens[$j][1])) { - break; - } - - if (T_DOUBLE_COLON === $tokens[$j][0] || T_NEW === $tokens[$j][0]) { - $skipClassToken = true; - break; - } elseif (!\in_array($tokens[$j][0], [T_WHITESPACE, T_DOC_COMMENT, T_COMMENT])) { - break; - } - } - - if (!$skipClassToken) { - $class = true; - } - } - - if (T_NAMESPACE === $token[0]) { - $namespace = true; - } - } - - return false; - } -} diff --git a/vendor/symfony/routing/Loader/ClosureLoader.php b/vendor/symfony/routing/Loader/ClosureLoader.php deleted file mode 100644 index cea5f9c..0000000 --- a/vendor/symfony/routing/Loader/ClosureLoader.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\Loader; -use Symfony\Component\Routing\RouteCollection; - -/** - * ClosureLoader loads routes from a PHP closure. - * - * The Closure must return a RouteCollection instance. - * - * @author Fabien Potencier - */ -class ClosureLoader extends Loader -{ - /** - * Loads a Closure. - * - * @param \Closure $closure A Closure - * @param string|null $type The resource type - * - * @return RouteCollection A RouteCollection instance - */ - public function load($closure, string $type = null) - { - return $closure(); - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return $resource instanceof \Closure && (!$type || 'closure' === $type); - } -} diff --git a/vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php b/vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php deleted file mode 100644 index 79c1100..0000000 --- a/vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php +++ /dev/null @@ -1,93 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas - */ -class CollectionConfigurator -{ - use Traits\AddTrait; - use Traits\RouteTrait; - - private $parent; - private $parentConfigurator; - private $parentPrefixes; - - public function __construct(RouteCollection $parent, string $name, self $parentConfigurator = null, array $parentPrefixes = null) - { - $this->parent = $parent; - $this->name = $name; - $this->collection = new RouteCollection(); - $this->route = new Route(''); - $this->parentConfigurator = $parentConfigurator; // for GC control - $this->parentPrefixes = $parentPrefixes; - } - - public function __destruct() - { - if (null === $this->prefixes) { - $this->collection->addPrefix($this->route->getPath()); - } - - $this->parent->addCollection($this->collection); - } - - /** - * Creates a sub-collection. - */ - final public function collection(string $name = ''): self - { - return new self($this->collection, $this->name.$name, $this, $this->prefixes); - } - - /** - * Sets the prefix to add to the path of all child routes. - * - * @param string|array $prefix the prefix, or the localized prefixes - * - * @return $this - */ - final public function prefix($prefix): self - { - if (\is_array($prefix)) { - if (null === $this->parentPrefixes) { - // no-op - } elseif ($missing = array_diff_key($this->parentPrefixes, $prefix)) { - throw new \LogicException(sprintf('Collection "%s" is missing prefixes for locale(s) "%s".', $this->name, implode('", "', array_keys($missing)))); - } else { - foreach ($prefix as $locale => $localePrefix) { - if (!isset($this->parentPrefixes[$locale])) { - throw new \LogicException(sprintf('Collection "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $this->name, $locale)); - } - - $prefix[$locale] = $this->parentPrefixes[$locale].$localePrefix; - } - } - $this->prefixes = $prefix; - $this->route->setPath('/'); - } else { - $this->prefixes = null; - $this->route->setPath($prefix); - } - - return $this; - } - - private function createRoute(string $path): Route - { - return (clone $this->route)->setPath($path); - } -} diff --git a/vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php b/vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php deleted file mode 100644 index f11b795..0000000 --- a/vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php +++ /dev/null @@ -1,93 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas - */ -class ImportConfigurator -{ - use Traits\RouteTrait; - - private $parent; - - public function __construct(RouteCollection $parent, RouteCollection $route) - { - $this->parent = $parent; - $this->route = $route; - } - - public function __destruct() - { - $this->parent->addCollection($this->route); - } - - /** - * Sets the prefix to add to the path of all child routes. - * - * @param string|array $prefix the prefix, or the localized prefixes - * - * @return $this - */ - final public function prefix($prefix, bool $trailingSlashOnRoot = true): self - { - if (!\is_array($prefix)) { - $this->route->addPrefix($prefix); - if (!$trailingSlashOnRoot) { - $rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath(); - foreach ($this->route->all() as $route) { - if ($route->getPath() === $rootPath) { - $route->setPath(rtrim($rootPath, '/')); - } - } - } - } else { - foreach ($prefix as $locale => $localePrefix) { - $prefix[$locale] = trim(trim($localePrefix), '/'); - } - foreach ($this->route->all() as $name => $route) { - if (null === $locale = $route->getDefault('_locale')) { - $this->route->remove($name); - foreach ($prefix as $locale => $localePrefix) { - $localizedRoute = clone $route; - $localizedRoute->setDefault('_locale', $locale); - $localizedRoute->setDefault('_canonical_route', $name); - $localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); - $this->route->add($name.'.'.$locale, $localizedRoute); - } - } elseif (!isset($prefix[$locale])) { - throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale)); - } else { - $route->setPath($prefix[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); - $this->route->add($name, $route); - } - } - } - - return $this; - } - - /** - * Sets the prefix to add to the name of all child routes. - * - * @return $this - */ - final public function namePrefix(string $namePrefix): self - { - $this->route->addNamePrefix($namePrefix); - - return $this; - } -} diff --git a/vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php b/vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php deleted file mode 100644 index e700f8d..0000000 --- a/vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas - */ -class RouteConfigurator -{ - use Traits\AddTrait; - use Traits\RouteTrait; - - private $parentConfigurator; - - public function __construct(RouteCollection $collection, $route, string $name = '', CollectionConfigurator $parentConfigurator = null, array $prefixes = null) - { - $this->collection = $collection; - $this->route = $route; - $this->name = $name; - $this->parentConfigurator = $parentConfigurator; // for GC control - $this->prefixes = $prefixes; - } -} diff --git a/vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php b/vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php deleted file mode 100644 index 8ed06f3..0000000 --- a/vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php +++ /dev/null @@ -1,60 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator; - -use Symfony\Component\Routing\Loader\PhpFileLoader; -use Symfony\Component\Routing\RouteCollection; - -/** - * @author Nicolas Grekas - */ -class RoutingConfigurator -{ - use Traits\AddTrait; - - private $loader; - private $path; - private $file; - - public function __construct(RouteCollection $collection, PhpFileLoader $loader, string $path, string $file) - { - $this->collection = $collection; - $this->loader = $loader; - $this->path = $path; - $this->file = $file; - } - - /** - * @param string|string[]|null $exclude Glob patterns to exclude from the import - */ - final public function import($resource, string $type = null, bool $ignoreErrors = false, $exclude = null): ImportConfigurator - { - $this->loader->setCurrentDir(\dirname($this->path)); - - $imported = $this->loader->import($resource, $type, $ignoreErrors, $this->file, $exclude) ?: []; - if (!\is_array($imported)) { - return new ImportConfigurator($this->collection, $imported); - } - - $mergedCollection = new RouteCollection(); - foreach ($imported as $subCollection) { - $mergedCollection->addCollection($subCollection); - } - - return new ImportConfigurator($this->collection, $mergedCollection); - } - - final public function collection(string $name = ''): CollectionConfigurator - { - return new CollectionConfigurator($this->collection, $name); - } -} diff --git a/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php b/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php deleted file mode 100644 index 085fde4..0000000 --- a/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php +++ /dev/null @@ -1,90 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator\Traits; - -use Symfony\Component\Routing\Loader\Configurator\CollectionConfigurator; -use Symfony\Component\Routing\Loader\Configurator\RouteConfigurator; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -trait AddTrait -{ - /** - * @var RouteCollection - */ - private $collection; - - private $name = ''; - - private $prefixes; - - /** - * Adds a route. - * - * @param string|array $path the path, or the localized paths of the route - */ - final public function add(string $name, $path): RouteConfigurator - { - $paths = []; - $parentConfigurator = $this instanceof CollectionConfigurator ? $this : ($this instanceof RouteConfigurator ? $this->parentConfigurator : null); - - if (\is_array($path)) { - if (null === $this->prefixes) { - $paths = $path; - } elseif ($missing = array_diff_key($this->prefixes, $path)) { - throw new \LogicException(sprintf('Route "%s" is missing routes for locale(s) "%s".', $name, implode('", "', array_keys($missing)))); - } else { - foreach ($path as $locale => $localePath) { - if (!isset($this->prefixes[$locale])) { - throw new \LogicException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale)); - } - - $paths[$locale] = $this->prefixes[$locale].$localePath; - } - } - } elseif (null !== $this->prefixes) { - foreach ($this->prefixes as $locale => $prefix) { - $paths[$locale] = $prefix.$path; - } - } else { - $this->collection->add($this->name.$name, $route = $this->createRoute($path)); - - return new RouteConfigurator($this->collection, $route, $this->name, $parentConfigurator, $this->prefixes); - } - - $routes = new RouteCollection(); - - foreach ($paths as $locale => $path) { - $routes->add($name.'.'.$locale, $route = $this->createRoute($path)); - $this->collection->add($this->name.$name.'.'.$locale, $route); - $route->setDefault('_locale', $locale); - $route->setDefault('_canonical_route', $this->name.$name); - } - - return new RouteConfigurator($this->collection, $routes, $this->name, $parentConfigurator, $this->prefixes); - } - - /** - * Adds a route. - * - * @param string|array $path the path, or the localized paths of the route - */ - final public function __invoke(string $name, $path): RouteConfigurator - { - return $this->add($name, $path); - } - - private function createRoute(string $path): Route - { - return new Route($path); - } -} diff --git a/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php b/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php deleted file mode 100644 index 04009cd..0000000 --- a/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php +++ /dev/null @@ -1,163 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader\Configurator\Traits; - -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -trait RouteTrait -{ - /** - * @var RouteCollection|Route - */ - private $route; - - /** - * Adds defaults. - * - * @return $this - */ - final public function defaults(array $defaults): self - { - $this->route->addDefaults($defaults); - - return $this; - } - - /** - * Adds requirements. - * - * @return $this - */ - final public function requirements(array $requirements): self - { - $this->route->addRequirements($requirements); - - return $this; - } - - /** - * Adds options. - * - * @return $this - */ - final public function options(array $options): self - { - $this->route->addOptions($options); - - return $this; - } - - /** - * Whether paths should accept utf8 encoding. - * - * @return $this - */ - final public function utf8(bool $utf8 = true): self - { - $this->route->addOptions(['utf8' => $utf8]); - - return $this; - } - - /** - * Sets the condition. - * - * @return $this - */ - final public function condition(string $condition): self - { - $this->route->setCondition($condition); - - return $this; - } - - /** - * Sets the pattern for the host. - * - * @return $this - */ - final public function host(string $pattern): self - { - $this->route->setHost($pattern); - - return $this; - } - - /** - * Sets the schemes (e.g. 'https') this route is restricted to. - * So an empty array means that any scheme is allowed. - * - * @param string[] $schemes - * - * @return $this - */ - final public function schemes(array $schemes): self - { - $this->route->setSchemes($schemes); - - return $this; - } - - /** - * Sets the HTTP methods (e.g. 'POST') this route is restricted to. - * So an empty array means that any method is allowed. - * - * @param string[] $methods - * - * @return $this - */ - final public function methods(array $methods): self - { - $this->route->setMethods($methods); - - return $this; - } - - /** - * Adds the "_controller" entry to defaults. - * - * @param callable|string $controller a callable or parseable pseudo-callable - * - * @return $this - */ - final public function controller($controller): self - { - $this->route->addDefaults(['_controller' => $controller]); - - return $this; - } - - /** - * Adds the "_locale" entry to defaults. - * - * @return $this - */ - final public function locale(string $locale): self - { - $this->route->addDefaults(['_locale' => $locale]); - - return $this; - } - - /** - * Adds the "_format" entry to defaults. - * - * @return $this - */ - final public function format(string $format): self - { - $this->route->addDefaults(['_format' => $format]); - - return $this; - } -} diff --git a/vendor/symfony/routing/Loader/ContainerLoader.php b/vendor/symfony/routing/Loader/ContainerLoader.php deleted file mode 100644 index 92bf2a0..0000000 --- a/vendor/symfony/routing/Loader/ContainerLoader.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Psr\Container\ContainerInterface; - -/** - * A route loader that executes a service from a PSR-11 container to load the routes. - * - * @author Ryan Weaver - */ -class ContainerLoader extends ObjectLoader -{ - private $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return 'service' === $type; - } - - /** - * {@inheritdoc} - */ - protected function getObject(string $id) - { - return $this->container->get($id); - } -} diff --git a/vendor/symfony/routing/Loader/DirectoryLoader.php b/vendor/symfony/routing/Loader/DirectoryLoader.php deleted file mode 100644 index c0f3491..0000000 --- a/vendor/symfony/routing/Loader/DirectoryLoader.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\DirectoryResource; -use Symfony\Component\Routing\RouteCollection; - -class DirectoryLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($file, string $type = null) - { - $path = $this->locator->locate($file); - - $collection = new RouteCollection(); - $collection->addResource(new DirectoryResource($path)); - - foreach (scandir($path) as $dir) { - if ('.' !== $dir[0]) { - $this->setCurrentDir($path); - $subPath = $path.'/'.$dir; - $subType = null; - - if (is_dir($subPath)) { - $subPath .= '/'; - $subType = 'directory'; - } - - $subCollection = $this->import($subPath, $subType, false, $path); - $collection->addCollection($subCollection); - } - } - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - // only when type is forced to directory, not to conflict with AnnotationLoader - - return 'directory' === $type; - } -} diff --git a/vendor/symfony/routing/Loader/GlobFileLoader.php b/vendor/symfony/routing/Loader/GlobFileLoader.php deleted file mode 100644 index 780fb15..0000000 --- a/vendor/symfony/routing/Loader/GlobFileLoader.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Routing\RouteCollection; - -/** - * GlobFileLoader loads files from a glob pattern. - * - * @author Nicolas Grekas - */ -class GlobFileLoader extends FileLoader -{ - /** - * {@inheritdoc} - */ - public function load($resource, string $type = null) - { - $collection = new RouteCollection(); - - foreach ($this->glob($resource, false, $globResource) as $path => $info) { - $collection->addCollection($this->import($path)); - } - - $collection->addResource($globResource); - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return 'glob' === $type; - } -} diff --git a/vendor/symfony/routing/Loader/ObjectLoader.php b/vendor/symfony/routing/Loader/ObjectLoader.php deleted file mode 100644 index aefb829..0000000 --- a/vendor/symfony/routing/Loader/ObjectLoader.php +++ /dev/null @@ -1,84 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\Loader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\RouteCollection; - -/** - * A route loader that calls a method on an object to load the routes. - * - * @author Ryan Weaver - */ -abstract class ObjectLoader extends Loader -{ - /** - * Returns the object that the method will be called on to load routes. - * - * For example, if your application uses a service container, - * the $id may be a service id. - * - * @return object - */ - abstract protected function getObject(string $id); - - /** - * Calls the object method that will load the routes. - * - * @param string $resource object_id::method - * @param string|null $type The resource type - * - * @return RouteCollection - */ - public function load($resource, string $type = null) - { - if (!preg_match('/^[^\:]+(?:::(?:[^\:]+))?$/', $resource)) { - throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the %s route loader: use the format "object_id::method" or "object_id" if your object class has an "__invoke" method.', $resource, \is_string($type) ? '"'.$type.'"' : 'object')); - } - - $parts = explode('::', $resource); - $method = $parts[1] ?? '__invoke'; - - $loaderObject = $this->getObject($parts[0]); - - if (!\is_object($loaderObject)) { - throw new \TypeError(sprintf('%s:getObject() must return an object: %s returned', \get_class($this), \gettype($loaderObject))); - } - - if (!\is_callable([$loaderObject, $method])) { - throw new \BadMethodCallException(sprintf('Method "%s" not found on "%s" when importing routing resource "%s"', $method, \get_class($loaderObject), $resource)); - } - - $routeCollection = $loaderObject->$method($this); - - if (!$routeCollection instanceof RouteCollection) { - $type = \is_object($routeCollection) ? \get_class($routeCollection) : \gettype($routeCollection); - - throw new \LogicException(sprintf('The %s::%s method must return a RouteCollection: %s returned', \get_class($loaderObject), $method, $type)); - } - - // make the object file tracked so that if it changes, the cache rebuilds - $this->addClassResource(new \ReflectionClass($loaderObject), $routeCollection); - - return $routeCollection; - } - - private function addClassResource(\ReflectionClass $class, RouteCollection $collection) - { - do { - if (is_file($class->getFileName())) { - $collection->addResource(new FileResource($class->getFileName())); - } - } while ($class = $class->getParentClass()); - } -} diff --git a/vendor/symfony/routing/Loader/PhpFileLoader.php b/vendor/symfony/routing/Loader/PhpFileLoader.php deleted file mode 100644 index 31fe88d..0000000 --- a/vendor/symfony/routing/Loader/PhpFileLoader.php +++ /dev/null @@ -1,75 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; -use Symfony\Component\Routing\RouteCollection; - -/** - * PhpFileLoader loads routes from a PHP file. - * - * The file must return a RouteCollection instance. - * - * @author Fabien Potencier - */ -class PhpFileLoader extends FileLoader -{ - /** - * Loads a PHP file. - * - * @param string $file A PHP file path - * @param string|null $type The resource type - * - * @return RouteCollection A RouteCollection instance - */ - public function load($file, string $type = null) - { - $path = $this->locator->locate($file); - $this->setCurrentDir(\dirname($path)); - - // the closure forbids access to the private scope in the included file - $loader = $this; - $load = \Closure::bind(static function ($file) use ($loader) { - return include $file; - }, null, ProtectedPhpFileLoader::class); - - $result = $load($path); - - if (\is_object($result) && \is_callable($result)) { - $collection = new RouteCollection(); - $result(new RoutingConfigurator($collection, $this, $path, $file)); - } else { - $collection = $result; - } - - $collection->addResource(new FileResource($path)); - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return \is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'php' === $type); - } -} - -/** - * @internal - */ -final class ProtectedPhpFileLoader extends PhpFileLoader -{ -} diff --git a/vendor/symfony/routing/Loader/XmlFileLoader.php b/vendor/symfony/routing/Loader/XmlFileLoader.php deleted file mode 100644 index 9d46cfd..0000000 --- a/vendor/symfony/routing/Loader/XmlFileLoader.php +++ /dev/null @@ -1,436 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Config\Util\XmlUtils; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * XmlFileLoader loads XML routing files. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class XmlFileLoader extends FileLoader -{ - const NAMESPACE_URI = 'http://symfony.com/schema/routing'; - const SCHEME_PATH = '/schema/routing/routing-1.0.xsd'; - - /** - * Loads an XML file. - * - * @param string $file An XML file path - * @param string|null $type The resource type - * - * @return RouteCollection A RouteCollection instance - * - * @throws \InvalidArgumentException when the file cannot be loaded or when the XML cannot be - * parsed because it does not validate against the scheme - */ - public function load($file, string $type = null) - { - $path = $this->locator->locate($file); - - $xml = $this->loadFile($path); - - $collection = new RouteCollection(); - $collection->addResource(new FileResource($path)); - - // process routes and imports - foreach ($xml->documentElement->childNodes as $node) { - if (!$node instanceof \DOMElement) { - continue; - } - - $this->parseNode($collection, $node, $path, $file); - } - - return $collection; - } - - /** - * Parses a node from a loaded XML file. - * - * @param \DOMElement $node Element to parse - * @param string $path Full path of the XML file being processed - * @param string $file Loaded file name - * - * @throws \InvalidArgumentException When the XML is invalid - */ - protected function parseNode(RouteCollection $collection, \DOMElement $node, string $path, string $file) - { - if (self::NAMESPACE_URI !== $node->namespaceURI) { - return; - } - - switch ($node->localName) { - case 'route': - $this->parseRoute($collection, $node, $path); - break; - case 'import': - $this->parseImport($collection, $node, $path, $file); - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path)); - } - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return \is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'xml' === $type); - } - - /** - * Parses a route and adds it to the RouteCollection. - * - * @param \DOMElement $node Element to parse that represents a Route - * @param string $path Full path of the XML file being processed - * - * @throws \InvalidArgumentException When the XML is invalid - */ - protected function parseRoute(RouteCollection $collection, \DOMElement $node, string $path) - { - if ('' === $id = $node->getAttribute('id')) { - throw new \InvalidArgumentException(sprintf('The element in file "%s" must have an "id" attribute.', $path)); - } - - $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY); - $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY); - - list($defaults, $requirements, $options, $condition, $paths) = $this->parseConfigs($node, $path); - - if (!$paths && '' === $node->getAttribute('path')) { - throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "path" attribute or child nodes.', $path)); - } - - if ($paths && '' !== $node->getAttribute('path')) { - throw new \InvalidArgumentException(sprintf('The element in file "%s" must not have both a "path" attribute and child nodes.', $path)); - } - - if (!$paths) { - $route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition); - $collection->add($id, $route); - } else { - foreach ($paths as $locale => $p) { - $defaults['_locale'] = $locale; - $defaults['_canonical_route'] = $id; - $route = new Route($p, $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition); - $collection->add($id.'.'.$locale, $route); - } - } - } - - /** - * Parses an import and adds the routes in the resource to the RouteCollection. - * - * @param \DOMElement $node Element to parse that represents a Route - * @param string $path Full path of the XML file being processed - * @param string $file Loaded file name - * - * @throws \InvalidArgumentException When the XML is invalid - */ - protected function parseImport(RouteCollection $collection, \DOMElement $node, string $path, string $file) - { - if ('' === $resource = $node->getAttribute('resource')) { - throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "resource" attribute.', $path)); - } - - $type = $node->getAttribute('type'); - $prefix = $node->getAttribute('prefix'); - $host = $node->hasAttribute('host') ? $node->getAttribute('host') : null; - $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY) : null; - $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY) : null; - $trailingSlashOnRoot = $node->hasAttribute('trailing-slash-on-root') ? XmlUtils::phpize($node->getAttribute('trailing-slash-on-root')) : true; - - list($defaults, $requirements, $options, $condition, /* $paths */, $prefixes) = $this->parseConfigs($node, $path); - - if ('' !== $prefix && $prefixes) { - throw new \InvalidArgumentException(sprintf('The element in file "%s" must not have both a "prefix" attribute and child nodes.', $path)); - } - - $exclude = []; - foreach ($node->childNodes as $child) { - if ($child instanceof \DOMElement && $child->localName === $exclude && self::NAMESPACE_URI === $child->namespaceURI) { - $exclude[] = $child->nodeValue; - } - } - - if ($node->hasAttribute('exclude')) { - if ($exclude) { - throw new \InvalidArgumentException('You cannot use both the attribute "exclude" and tags at the same time.'); - } - $exclude = [$node->getAttribute('exclude')]; - } - - $this->setCurrentDir(\dirname($path)); - - /** @var RouteCollection[] $imported */ - $imported = $this->import($resource, ('' !== $type ? $type : null), false, $file, $exclude) ?: []; - - if (!\is_array($imported)) { - $imported = [$imported]; - } - - foreach ($imported as $subCollection) { - /* @var $subCollection RouteCollection */ - if ('' !== $prefix || !$prefixes) { - $subCollection->addPrefix($prefix); - if (!$trailingSlashOnRoot) { - $rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath(); - foreach ($subCollection->all() as $route) { - if ($route->getPath() === $rootPath) { - $route->setPath(rtrim($rootPath, '/')); - } - } - } - } else { - foreach ($prefixes as $locale => $localePrefix) { - $prefixes[$locale] = trim(trim($localePrefix), '/'); - } - foreach ($subCollection->all() as $name => $route) { - if (null === $locale = $route->getDefault('_locale')) { - $subCollection->remove($name); - foreach ($prefixes as $locale => $localePrefix) { - $localizedRoute = clone $route; - $localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); - $localizedRoute->setDefault('_locale', $locale); - $localizedRoute->setDefault('_canonical_route', $name); - $subCollection->add($name.'.'.$locale, $localizedRoute); - } - } elseif (!isset($prefixes[$locale])) { - throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix when imported in "%s".', $name, $locale, $path)); - } else { - $route->setPath($prefixes[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); - $subCollection->add($name, $route); - } - } - } - - if (null !== $host) { - $subCollection->setHost($host); - } - if (null !== $condition) { - $subCollection->setCondition($condition); - } - if (null !== $schemes) { - $subCollection->setSchemes($schemes); - } - if (null !== $methods) { - $subCollection->setMethods($methods); - } - $subCollection->addDefaults($defaults); - $subCollection->addRequirements($requirements); - $subCollection->addOptions($options); - - if ($namePrefix = $node->getAttribute('name-prefix')) { - $subCollection->addNamePrefix($namePrefix); - } - - $collection->addCollection($subCollection); - } - } - - /** - * Loads an XML file. - * - * @param string $file An XML file path - * - * @return \DOMDocument - * - * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors - * or when the XML structure is not as expected by the scheme - - * see validate() - */ - protected function loadFile(string $file) - { - return XmlUtils::loadFile($file, __DIR__.static::SCHEME_PATH); - } - - /** - * Parses the config elements (default, requirement, option). - * - * @throws \InvalidArgumentException When the XML is invalid - */ - private function parseConfigs(\DOMElement $node, string $path): array - { - $defaults = []; - $requirements = []; - $options = []; - $condition = null; - $prefixes = []; - $paths = []; - - /** @var \DOMElement $n */ - foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) { - if ($node !== $n->parentNode) { - continue; - } - - switch ($n->localName) { - case 'path': - $paths[$n->getAttribute('locale')] = trim($n->textContent); - break; - case 'prefix': - $prefixes[$n->getAttribute('locale')] = trim($n->textContent); - break; - case 'default': - if ($this->isElementValueNull($n)) { - $defaults[$n->getAttribute('key')] = null; - } else { - $defaults[$n->getAttribute('key')] = $this->parseDefaultsConfig($n, $path); - } - - break; - case 'requirement': - $requirements[$n->getAttribute('key')] = trim($n->textContent); - break; - case 'option': - $options[$n->getAttribute('key')] = XmlUtils::phpize(trim($n->textContent)); - break; - case 'condition': - $condition = trim($n->textContent); - break; - default: - throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path)); - } - } - - if ($controller = $node->getAttribute('controller')) { - if (isset($defaults['_controller'])) { - $name = $node->hasAttribute('id') ? sprintf('"%s"', $node->getAttribute('id')) : sprintf('the "%s" tag', $node->tagName); - - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for %s.', $path, $name)); - } - - $defaults['_controller'] = $controller; - } - if ($node->hasAttribute('locale')) { - $defaults['_locale'] = $node->getAttribute('locale'); - } - if ($node->hasAttribute('format')) { - $defaults['_format'] = $node->getAttribute('format'); - } - if ($node->hasAttribute('utf8')) { - $options['utf8'] = XmlUtils::phpize($node->getAttribute('utf8')); - } - - return [$defaults, $requirements, $options, $condition, $paths, $prefixes]; - } - - /** - * Parses the "default" elements. - * - * @return array|bool|float|int|string|null The parsed value of the "default" element - */ - private function parseDefaultsConfig(\DOMElement $element, string $path) - { - if ($this->isElementValueNull($element)) { - return null; - } - - // Check for existing element nodes in the default element. There can - // only be a single element inside a default element. So this element - // (if one was found) can safely be returned. - foreach ($element->childNodes as $child) { - if (!$child instanceof \DOMElement) { - continue; - } - - if (self::NAMESPACE_URI !== $child->namespaceURI) { - continue; - } - - return $this->parseDefaultNode($child, $path); - } - - // If the default element doesn't contain a nested "bool", "int", "float", - // "string", "list", or "map" element, the element contents will be treated - // as the string value of the associated default option. - return trim($element->textContent); - } - - /** - * Recursively parses the value of a "default" element. - * - * @return array|bool|float|int|string The parsed value - * - * @throws \InvalidArgumentException when the XML is invalid - */ - private function parseDefaultNode(\DOMElement $node, string $path) - { - if ($this->isElementValueNull($node)) { - return null; - } - - switch ($node->localName) { - case 'bool': - return 'true' === trim($node->nodeValue) || '1' === trim($node->nodeValue); - case 'int': - return (int) trim($node->nodeValue); - case 'float': - return (float) trim($node->nodeValue); - case 'string': - return trim($node->nodeValue); - case 'list': - $list = []; - - foreach ($node->childNodes as $element) { - if (!$element instanceof \DOMElement) { - continue; - } - - if (self::NAMESPACE_URI !== $element->namespaceURI) { - continue; - } - - $list[] = $this->parseDefaultNode($element, $path); - } - - return $list; - case 'map': - $map = []; - - foreach ($node->childNodes as $element) { - if (!$element instanceof \DOMElement) { - continue; - } - - if (self::NAMESPACE_URI !== $element->namespaceURI) { - continue; - } - - $map[$element->getAttribute('key')] = $this->parseDefaultNode($element, $path); - } - - return $map; - default: - throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "bool", "int", "float", "string", "list", or "map".', $node->localName, $path)); - } - } - - private function isElementValueNull(\DOMElement $element): bool - { - $namespaceUri = 'http://www.w3.org/2001/XMLSchema-instance'; - - if (!$element->hasAttributeNS($namespaceUri, 'nil')) { - return false; - } - - return 'true' === $element->getAttributeNS($namespaceUri, 'nil') || '1' === $element->getAttributeNS($namespaceUri, 'nil'); - } -} diff --git a/vendor/symfony/routing/Loader/YamlFileLoader.php b/vendor/symfony/routing/Loader/YamlFileLoader.php deleted file mode 100644 index 3b47b20..0000000 --- a/vendor/symfony/routing/Loader/YamlFileLoader.php +++ /dev/null @@ -1,285 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Loader; - -use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Parser as YamlParser; -use Symfony\Component\Yaml\Yaml; - -/** - * YamlFileLoader loads Yaml routing files. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class YamlFileLoader extends FileLoader -{ - private static $availableKeys = [ - 'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller', 'name_prefix', 'trailing_slash_on_root', 'locale', 'format', 'utf8', 'exclude', - ]; - private $yamlParser; - - /** - * Loads a Yaml file. - * - * @param string $file A Yaml file path - * @param string|null $type The resource type - * - * @return RouteCollection A RouteCollection instance - * - * @throws \InvalidArgumentException When a route can't be parsed because YAML is invalid - */ - public function load($file, string $type = null) - { - $path = $this->locator->locate($file); - - if (!stream_is_local($path)) { - throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $path)); - } - - if (!file_exists($path)) { - throw new \InvalidArgumentException(sprintf('File "%s" not found.', $path)); - } - - if (null === $this->yamlParser) { - $this->yamlParser = new YamlParser(); - } - - try { - $parsedConfig = $this->yamlParser->parseFile($path, Yaml::PARSE_CONSTANT); - } catch (ParseException $e) { - throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); - } - - $collection = new RouteCollection(); - $collection->addResource(new FileResource($path)); - - // empty file - if (null === $parsedConfig) { - return $collection; - } - - // not an array - if (!\is_array($parsedConfig)) { - throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path)); - } - - foreach ($parsedConfig as $name => $config) { - $this->validate($config, $name, $path); - - if (isset($config['resource'])) { - $this->parseImport($collection, $config, $path, $file); - } else { - $this->parseRoute($collection, $name, $config, $path); - } - } - - return $collection; - } - - /** - * {@inheritdoc} - */ - public function supports($resource, string $type = null) - { - return \is_string($resource) && \in_array(pathinfo($resource, PATHINFO_EXTENSION), ['yml', 'yaml'], true) && (!$type || 'yaml' === $type); - } - - /** - * Parses a route and adds it to the RouteCollection. - * - * @param string $name Route name - * @param array $config Route definition - * @param string $path Full path of the YAML file being processed - */ - protected function parseRoute(RouteCollection $collection, string $name, array $config, string $path) - { - $defaults = isset($config['defaults']) ? $config['defaults'] : []; - $requirements = isset($config['requirements']) ? $config['requirements'] : []; - $options = isset($config['options']) ? $config['options'] : []; - $host = isset($config['host']) ? $config['host'] : ''; - $schemes = isset($config['schemes']) ? $config['schemes'] : []; - $methods = isset($config['methods']) ? $config['methods'] : []; - $condition = isset($config['condition']) ? $config['condition'] : null; - - foreach ($requirements as $placeholder => $requirement) { - if (\is_int($placeholder)) { - throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s"?', $placeholder, $requirement, $name, $path)); - } - } - - if (isset($config['controller'])) { - $defaults['_controller'] = $config['controller']; - } - if (isset($config['locale'])) { - $defaults['_locale'] = $config['locale']; - } - if (isset($config['format'])) { - $defaults['_format'] = $config['format']; - } - if (isset($config['utf8'])) { - $options['utf8'] = $config['utf8']; - } - - if (\is_array($config['path'])) { - $route = new Route('', $defaults, $requirements, $options, $host, $schemes, $methods, $condition); - - foreach ($config['path'] as $locale => $path) { - $localizedRoute = clone $route; - $localizedRoute->setDefault('_locale', $locale); - $localizedRoute->setDefault('_canonical_route', $name); - $localizedRoute->setPath($path); - $collection->add($name.'.'.$locale, $localizedRoute); - } - } else { - $route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition); - $collection->add($name, $route); - } - } - - /** - * Parses an import and adds the routes in the resource to the RouteCollection. - * - * @param array $config Route definition - * @param string $path Full path of the YAML file being processed - * @param string $file Loaded file name - */ - protected function parseImport(RouteCollection $collection, array $config, string $path, string $file) - { - $type = isset($config['type']) ? $config['type'] : null; - $prefix = isset($config['prefix']) ? $config['prefix'] : ''; - $defaults = isset($config['defaults']) ? $config['defaults'] : []; - $requirements = isset($config['requirements']) ? $config['requirements'] : []; - $options = isset($config['options']) ? $config['options'] : []; - $host = isset($config['host']) ? $config['host'] : null; - $condition = isset($config['condition']) ? $config['condition'] : null; - $schemes = isset($config['schemes']) ? $config['schemes'] : null; - $methods = isset($config['methods']) ? $config['methods'] : null; - $trailingSlashOnRoot = $config['trailing_slash_on_root'] ?? true; - $exclude = $config['exclude'] ?? null; - - if (isset($config['controller'])) { - $defaults['_controller'] = $config['controller']; - } - if (isset($config['locale'])) { - $defaults['_locale'] = $config['locale']; - } - if (isset($config['format'])) { - $defaults['_format'] = $config['format']; - } - if (isset($config['utf8'])) { - $options['utf8'] = $config['utf8']; - } - - $this->setCurrentDir(\dirname($path)); - - $imported = $this->import($config['resource'], $type, false, $file, $exclude) ?: []; - - if (!\is_array($imported)) { - $imported = [$imported]; - } - - foreach ($imported as $subCollection) { - /* @var $subCollection RouteCollection */ - if (!\is_array($prefix)) { - $subCollection->addPrefix($prefix); - if (!$trailingSlashOnRoot) { - $rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath(); - foreach ($subCollection->all() as $route) { - if ($route->getPath() === $rootPath) { - $route->setPath(rtrim($rootPath, '/')); - } - } - } - } else { - foreach ($prefix as $locale => $localePrefix) { - $prefix[$locale] = trim(trim($localePrefix), '/'); - } - foreach ($subCollection->all() as $name => $route) { - if (null === $locale = $route->getDefault('_locale')) { - $subCollection->remove($name); - foreach ($prefix as $locale => $localePrefix) { - $localizedRoute = clone $route; - $localizedRoute->setDefault('_locale', $locale); - $localizedRoute->setDefault('_canonical_route', $name); - $localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); - $subCollection->add($name.'.'.$locale, $localizedRoute); - } - } elseif (!isset($prefix[$locale])) { - throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix when imported in "%s".', $name, $locale, $file)); - } else { - $route->setPath($prefix[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); - $subCollection->add($name, $route); - } - } - } - - if (null !== $host) { - $subCollection->setHost($host); - } - if (null !== $condition) { - $subCollection->setCondition($condition); - } - if (null !== $schemes) { - $subCollection->setSchemes($schemes); - } - if (null !== $methods) { - $subCollection->setMethods($methods); - } - $subCollection->addDefaults($defaults); - $subCollection->addRequirements($requirements); - $subCollection->addOptions($options); - - if (isset($config['name_prefix'])) { - $subCollection->addNamePrefix($config['name_prefix']); - } - - $collection->addCollection($subCollection); - } - } - - /** - * Validates the route configuration. - * - * @param array $config A resource config - * @param string $name The config key - * @param string $path The loaded file path - * - * @throws \InvalidArgumentException If one of the provided config keys is not supported, - * something is missing or the combination is nonsense - */ - protected function validate($config, string $name, string $path) - { - if (!\is_array($config)) { - throw new \InvalidArgumentException(sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path)); - } - if ($extraKeys = array_diff(array_keys($config), self::$availableKeys)) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', $path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys))); - } - if (isset($config['resource']) && isset($config['path'])) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', $path, $name)); - } - if (!isset($config['resource']) && isset($config['type'])) { - throw new \InvalidArgumentException(sprintf('The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', $name, $path)); - } - if (!isset($config['resource']) && !isset($config['path'])) { - throw new \InvalidArgumentException(sprintf('You must define a "path" for the route "%s" in file "%s".', $name, $path)); - } - if (isset($config['controller']) && isset($config['defaults']['_controller'])) { - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name)); - } - } -} diff --git a/vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd b/vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd deleted file mode 100644 index 8e61d03..0000000 --- a/vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/symfony/routing/Matcher/CompiledUrlMatcher.php b/vendor/symfony/routing/Matcher/CompiledUrlMatcher.php deleted file mode 100644 index e15cda7..0000000 --- a/vendor/symfony/routing/Matcher/CompiledUrlMatcher.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; -use Symfony\Component\Routing\RequestContext; - -/** - * Matches URLs based on rules dumped by CompiledUrlMatcherDumper. - * - * @author Nicolas Grekas - */ -class CompiledUrlMatcher extends UrlMatcher -{ - use CompiledUrlMatcherTrait; - - public function __construct(array $compiledRoutes, RequestContext $context) - { - $this->context = $context; - list($this->matchHost, $this->staticRoutes, $this->regexpList, $this->dynamicRoutes, $this->checkCondition) = $compiledRoutes; - } -} diff --git a/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php b/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php deleted file mode 100644 index 936dd16..0000000 --- a/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php +++ /dev/null @@ -1,501 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * CompiledUrlMatcherDumper creates PHP arrays to be used with CompiledUrlMatcher. - * - * @author Fabien Potencier - * @author Tobias Schultze - * @author Arnaud Le Blanc - * @author Nicolas Grekas - */ -class CompiledUrlMatcherDumper extends MatcherDumper -{ - private $expressionLanguage; - private $signalingException; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - private $expressionLanguageProviders = []; - - /** - * {@inheritdoc} - */ - public function dump(array $options = []) - { - return <<generateCompiledRoutes()}]; - -EOF; - } - - public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) - { - $this->expressionLanguageProviders[] = $provider; - } - - /** - * Generates the arrays for CompiledUrlMatcher's constructor. - */ - public function getCompiledRoutes(bool $forDump = false): array - { - // Group hosts by same-suffix, re-order when possible - $matchHost = false; - $routes = new StaticPrefixCollection(); - foreach ($this->getRoutes()->all() as $name => $route) { - if ($host = $route->getHost()) { - $matchHost = true; - $host = '/'.strtr(strrev($host), '}.{', '(/)'); - } - - $routes->addRoute($host ?: '/(.*)', [$name, $route]); - } - - if ($matchHost) { - $compiledRoutes = [true]; - $routes = $routes->populateCollection(new RouteCollection()); - } else { - $compiledRoutes = [false]; - $routes = $this->getRoutes(); - } - - list($staticRoutes, $dynamicRoutes) = $this->groupStaticRoutes($routes); - - $conditions = [null]; - $compiledRoutes[] = $this->compileStaticRoutes($staticRoutes, $conditions); - $chunkLimit = \count($dynamicRoutes); - - while (true) { - try { - $this->signalingException = new \RuntimeException('Compilation failed: regular expression is too large'); - $compiledRoutes = array_merge($compiledRoutes, $this->compileDynamicRoutes($dynamicRoutes, $matchHost, $chunkLimit, $conditions)); - - break; - } catch (\Exception $e) { - if (1 < $chunkLimit && $this->signalingException === $e) { - $chunkLimit = 1 + ($chunkLimit >> 1); - continue; - } - throw $e; - } - } - - if ($forDump) { - $compiledRoutes[2] = $compiledRoutes[4]; - } - unset($conditions[0]); - - if ($conditions) { - foreach ($conditions as $expression => $condition) { - $conditions[$expression] = "case {$condition}: return {$expression};"; - } - - $checkConditionCode = <<indent(implode("\n", $conditions), 3)} - } - } -EOF; - $compiledRoutes[4] = $forDump ? $checkConditionCode.",\n" : eval('return '.$checkConditionCode.';'); - } else { - $compiledRoutes[4] = $forDump ? " null, // \$checkCondition\n" : null; - } - - return $compiledRoutes; - } - - private function generateCompiledRoutes(): string - { - list($matchHost, $staticRoutes, $regexpCode, $dynamicRoutes, $checkConditionCode) = $this->getCompiledRoutes(true); - - $code = self::export($matchHost).', // $matchHost'."\n"; - - $code .= '[ // $staticRoutes'."\n"; - foreach ($staticRoutes as $path => $routes) { - $code .= sprintf(" %s => [\n", self::export($path)); - foreach ($routes as $route) { - $code .= sprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", ...array_map([__CLASS__, 'export'], $route)); - } - $code .= " ],\n"; - } - $code .= "],\n"; - - $code .= sprintf("[ // \$regexpList%s\n],\n", $regexpCode); - - $code .= '[ // $dynamicRoutes'."\n"; - foreach ($dynamicRoutes as $path => $routes) { - $code .= sprintf(" %s => [\n", self::export($path)); - foreach ($routes as $route) { - $code .= sprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", ...array_map([__CLASS__, 'export'], $route)); - } - $code .= " ],\n"; - } - $code .= "],\n"; - $code = preg_replace('/ => \[\n (\[.+?),\n \],/', ' => [$1],', $code); - - return $this->indent($code, 1).$checkConditionCode; - } - - /** - * Splits static routes from dynamic routes, so that they can be matched first, using a simple switch. - */ - private function groupStaticRoutes(RouteCollection $collection): array - { - $staticRoutes = $dynamicRegex = []; - $dynamicRoutes = new RouteCollection(); - - foreach ($collection->all() as $name => $route) { - $compiledRoute = $route->compile(); - $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); - $hostRegex = $compiledRoute->getHostRegex(); - $regex = $compiledRoute->getRegex(); - if ($hasTrailingSlash = '/' !== $route->getPath()) { - $pos = strrpos($regex, '$'); - $hasTrailingSlash = '/' === $regex[$pos - 1]; - $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); - } - - if (!$compiledRoute->getPathVariables()) { - $host = !$compiledRoute->getHostVariables() ? $route->getHost() : ''; - $url = $route->getPath(); - if ($hasTrailingSlash) { - $url = substr($url, 0, -1); - } - foreach ($dynamicRegex as list($hostRx, $rx, $prefix)) { - if (('' === $prefix || 0 === strpos($url, $prefix)) && (preg_match($rx, $url) || preg_match($rx, $url.'/')) && (!$host || !$hostRx || preg_match($hostRx, $host))) { - $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix]; - $dynamicRoutes->add($name, $route); - continue 2; - } - } - - $staticRoutes[$url][$name] = [$route, $hasTrailingSlash]; - } else { - $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix]; - $dynamicRoutes->add($name, $route); - } - } - - return [$staticRoutes, $dynamicRoutes]; - } - - /** - * Compiles static routes in a switch statement. - * - * Condition-less paths are put in a static array in the switch's default, with generic matching logic. - * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases. - * - * @throws \LogicException - */ - private function compileStaticRoutes(array $staticRoutes, array &$conditions): array - { - if (!$staticRoutes) { - return []; - } - $compiledRoutes = []; - - foreach ($staticRoutes as $url => $routes) { - $compiledRoutes[$url] = []; - foreach ($routes as $name => list($route, $hasTrailingSlash)) { - $compiledRoutes[$url][] = $this->compileRoute($route, $name, (!$route->compile()->getHostVariables() ? $route->getHost() : $route->compile()->getHostRegex()) ?: null, $hasTrailingSlash, false, $conditions); - } - } - - return $compiledRoutes; - } - - /** - * Compiles a regular expression followed by a switch statement to match dynamic routes. - * - * The regular expression matches both the host and the pathinfo at the same time. For stellar performance, - * it is built as a tree of patterns, with re-ordering logic to group same-prefix routes together when possible. - * - * Patterns are named so that we know which one matched (https://pcre.org/current/doc/html/pcre2syntax.html#SEC23). - * This name is used to "switch" to the additional logic required to match the final route. - * - * Condition-less paths are put in a static array in the switch's default, with generic matching logic. - * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases. - * - * Last but not least: - * - Because it is not possibe to mix unicode/non-unicode patterns in a single regexp, several of them can be generated. - * - The same regexp can be used several times when the logic in the switch rejects the match. When this happens, the - * matching-but-failing subpattern is blacklisted by replacing its name by "(*F)", which forces a failure-to-match. - * To ease this backlisting operation, the name of subpatterns is also the string offset where the replacement should occur. - */ - private function compileDynamicRoutes(RouteCollection $collection, bool $matchHost, int $chunkLimit, array &$conditions): array - { - if (!$collection->all()) { - return [[], [], '']; - } - $regexpList = []; - $code = ''; - $state = (object) [ - 'regexMark' => 0, - 'regex' => [], - 'routes' => [], - 'mark' => 0, - 'markTail' => 0, - 'hostVars' => [], - 'vars' => [], - ]; - $state->getVars = static function ($m) use ($state) { - if ('_route' === $m[1]) { - return '?:'; - } - - $state->vars[] = $m[1]; - - return ''; - }; - - $chunkSize = 0; - $prev = null; - $perModifiers = []; - foreach ($collection->all() as $name => $route) { - preg_match('#[a-zA-Z]*$#', $route->compile()->getRegex(), $rx); - if ($chunkLimit < ++$chunkSize || $prev !== $rx[0] && $route->compile()->getPathVariables()) { - $chunkSize = 1; - $routes = new RouteCollection(); - $perModifiers[] = [$rx[0], $routes]; - $prev = $rx[0]; - } - $routes->add($name, $route); - } - - foreach ($perModifiers as list($modifiers, $routes)) { - $prev = false; - $perHost = []; - foreach ($routes->all() as $name => $route) { - $regex = $route->compile()->getHostRegex(); - if ($prev !== $regex) { - $routes = new RouteCollection(); - $perHost[] = [$regex, $routes]; - $prev = $regex; - } - $routes->add($name, $route); - } - $prev = false; - $rx = '{^(?'; - $code .= "\n {$state->mark} => ".self::export($rx); - $startingMark = $state->mark; - $state->mark += \strlen($rx); - $state->regex = $rx; - - foreach ($perHost as list($hostRegex, $routes)) { - if ($matchHost) { - if ($hostRegex) { - preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $hostRegex, $rx); - $state->vars = []; - $hostRegex = '(?i:'.preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]).')\.'; - $state->hostVars = $state->vars; - } else { - $hostRegex = '(?:(?:[^./]*+\.)++)'; - $state->hostVars = []; - } - $state->mark += \strlen($rx = ($prev ? ')' : '')."|{$hostRegex}(?"); - $code .= "\n .".self::export($rx); - $state->regex .= $rx; - $prev = true; - } - - $tree = new StaticPrefixCollection(); - foreach ($routes->all() as $name => $route) { - preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $route->compile()->getRegex(), $rx); - - $state->vars = []; - $regex = preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]); - if ($hasTrailingSlash = '/' !== $regex && '/' === $regex[-1]) { - $regex = substr($regex, 0, -1); - } - $hasTrailingVar = (bool) preg_match('#\{\w+\}/?$#', $route->getPath()); - - $tree->addRoute($regex, [$name, $regex, $state->vars, $route, $hasTrailingSlash, $hasTrailingVar]); - } - - $code .= $this->compileStaticPrefixCollection($tree, $state, 0, $conditions); - } - if ($matchHost) { - $code .= "\n .')'"; - $state->regex .= ')'; - } - $rx = ")/?$}{$modifiers}"; - $code .= "\n .'{$rx}',"; - $state->regex .= $rx; - $state->markTail = 0; - - // if the regex is too large, throw a signaling exception to recompute with smaller chunk size - set_error_handler(function ($type, $message) { throw false !== strpos($message, $this->signalingException->getMessage()) ? $this->signalingException : new \ErrorException($message); }); - try { - preg_match($state->regex, ''); - } finally { - restore_error_handler(); - } - - $regexpList[$startingMark] = $state->regex; - } - - $state->routes[$state->mark][] = [null, null, null, null, false, false, 0]; - unset($state->getVars); - - return [$regexpList, $state->routes, $code]; - } - - /** - * Compiles a regexp tree of subpatterns that matches nested same-prefix routes. - * - * @param \stdClass $state A simple state object that keeps track of the progress of the compilation, - * and gathers the generated switch's "case" and "default" statements - */ - private function compileStaticPrefixCollection(StaticPrefixCollection $tree, \stdClass $state, int $prefixLen, array &$conditions): string - { - $code = ''; - $prevRegex = null; - $routes = $tree->getRoutes(); - - foreach ($routes as $i => $route) { - if ($route instanceof StaticPrefixCollection) { - $prevRegex = null; - $prefix = substr($route->getPrefix(), $prefixLen); - $state->mark += \strlen($rx = "|{$prefix}(?"); - $code .= "\n .".self::export($rx); - $state->regex .= $rx; - $code .= $this->indent($this->compileStaticPrefixCollection($route, $state, $prefixLen + \strlen($prefix), $conditions)); - $code .= "\n .')'"; - $state->regex .= ')'; - ++$state->markTail; - continue; - } - - list($name, $regex, $vars, $route, $hasTrailingSlash, $hasTrailingVar) = $route; - $compiledRoute = $route->compile(); - $vars = array_merge($state->hostVars, $vars); - - if ($compiledRoute->getRegex() === $prevRegex) { - $state->routes[$state->mark][] = $this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions); - continue; - } - - $state->mark += 3 + $state->markTail + \strlen($regex) - $prefixLen; - $state->markTail = 2 + \strlen($state->mark); - $rx = sprintf('|%s(*:%s)', substr($regex, $prefixLen), $state->mark); - $code .= "\n .".self::export($rx); - $state->regex .= $rx; - - $prevRegex = $compiledRoute->getRegex(); - $state->routes[$state->mark] = [$this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions)]; - } - - return $code; - } - - /** - * Compiles a single Route to PHP code used to match it against the path info. - */ - private function compileRoute(Route $route, string $name, $vars, bool $hasTrailingSlash, bool $hasTrailingVar, array &$conditions): array - { - $defaults = $route->getDefaults(); - - if (isset($defaults['_canonical_route'])) { - $name = $defaults['_canonical_route']; - unset($defaults['_canonical_route']); - } - - if ($condition = $route->getCondition()) { - $condition = $this->getExpressionLanguage()->compile($condition, ['context', 'request']); - $condition = $conditions[$condition] ?? $conditions[$condition] = (false !== strpos($condition, '$request') ? 1 : -1) * \count($conditions); - } else { - $condition = null; - } - - return [ - ['_route' => $name] + $defaults, - $vars, - array_flip($route->getMethods()) ?: null, - array_flip($route->getSchemes()) ?: null, - $hasTrailingSlash, - $hasTrailingVar, - $condition, - ]; - } - - private function getExpressionLanguage(): ExpressionLanguage - { - if (null === $this->expressionLanguage) { - if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { - throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); - } - - return $this->expressionLanguage; - } - - private function indent(string $code, int $level = 1): string - { - return preg_replace('/^./m', str_repeat(' ', $level).'$0', $code); - } - - /** - * @internal - */ - public static function export($value): string - { - if (null === $value) { - return 'null'; - } - if (!\is_array($value)) { - if (\is_object($value)) { - throw new \InvalidArgumentException('Symfony\Component\Routing\Route cannot contain objects.'); - } - - return str_replace("\n", '\'."\n".\'', var_export($value, true)); - } - if (!$value) { - return '[]'; - } - - $i = 0; - $export = '['; - - foreach ($value as $k => $v) { - if ($i === $k) { - ++$i; - } else { - $export .= self::export($k).' => '; - - if (\is_int($k) && $i < $k) { - $i = 1 + $k; - } - } - - $export .= self::export($v).', '; - } - - return substr_replace($export, ']', -2); - } -} diff --git a/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php b/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php deleted file mode 100644 index c5980b1..0000000 --- a/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php +++ /dev/null @@ -1,187 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; -use Symfony\Component\Routing\RequestContext; - -/** - * @author Nicolas Grekas - * - * @internal - * - * @property RequestContext $context - */ -trait CompiledUrlMatcherTrait -{ - private $matchHost = false; - private $staticRoutes = []; - private $regexpList = []; - private $dynamicRoutes = []; - private $checkCondition; - - public function match(string $pathinfo): array - { - $allow = $allowSchemes = []; - if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) { - return $ret; - } - if ($allow) { - throw new MethodNotAllowedException(array_keys($allow)); - } - if (!$this instanceof RedirectableUrlMatcherInterface) { - throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); - } - if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], true)) { - // no-op - } elseif ($allowSchemes) { - redirect_scheme: - $scheme = $this->context->getScheme(); - $this->context->setScheme(key($allowSchemes)); - try { - if ($ret = $this->doMatch($pathinfo)) { - return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret; - } - } finally { - $this->context->setScheme($scheme); - } - } elseif ('/' !== $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') { - $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo.'/' : $trimmedPathinfo; - if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) { - return $this->redirect($pathinfo, $ret['_route']) + $ret; - } - if ($allowSchemes) { - goto redirect_scheme; - } - } - - throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); - } - - private function doMatch(string $pathinfo, array &$allow = [], array &$allowSchemes = []): array - { - $allow = $allowSchemes = []; - $pathinfo = rawurldecode($pathinfo) ?: '/'; - $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; - $context = $this->context; - $requestMethod = $canonicalMethod = $context->getMethod(); - - if ($this->matchHost) { - $host = strtolower($context->getHost()); - } - - if ('HEAD' === $requestMethod) { - $canonicalMethod = 'GET'; - } - $supportsRedirections = 'GET' === $canonicalMethod && $this instanceof RedirectableUrlMatcherInterface; - - foreach ($this->staticRoutes[$trimmedPathinfo] ?? [] as list($ret, $requiredHost, $requiredMethods, $requiredSchemes, $hasTrailingSlash, , $condition)) { - if ($condition && !($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { - continue; - } - - if ($requiredHost) { - if ('#' !== $requiredHost[0] ? $requiredHost !== $host : !preg_match($requiredHost, $host, $hostMatches)) { - continue; - } - if ('#' === $requiredHost[0] && $hostMatches) { - $hostMatches['_route'] = $ret['_route']; - $ret = $this->mergeDefaults($hostMatches, $ret); - } - } - - if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { - if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) { - return $allow = $allowSchemes = []; - } - continue; - } - - $hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]); - if ($hasRequiredScheme && $requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) { - $allow += $requiredMethods; - continue; - } - - if (!$hasRequiredScheme) { - $allowSchemes += $requiredSchemes; - continue; - } - - return $ret; - } - - $matchedPathinfo = $this->matchHost ? $host.'.'.$pathinfo : $pathinfo; - - foreach ($this->regexpList as $offset => $regex) { - while (preg_match($regex, $matchedPathinfo, $matches)) { - foreach ($this->dynamicRoutes[$m = (int) $matches['MARK']] as list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar, $condition)) { - if (null !== $condition) { - if (0 === $condition) { // marks the last route in the regexp - continue 3; - } - if (!($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { - continue; - } - } - - $hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar; - - if ($hasTrailingVar && ($hasTrailingSlash || (null === $n = $matches[\count($vars)] ?? null) || '/' !== ($n[-1] ?? '/')) && preg_match($regex, $this->matchHost ? $host.'.'.$trimmedPathinfo : $trimmedPathinfo, $n) && $m === (int) $n['MARK']) { - if ($hasTrailingSlash) { - $matches = $n; - } else { - $hasTrailingVar = false; - } - } - - if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { - if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) { - return $allow = $allowSchemes = []; - } - continue; - } - - foreach ($vars as $i => $v) { - if (isset($matches[1 + $i])) { - $ret[$v] = $matches[1 + $i]; - } - } - - if ($requiredSchemes && !isset($requiredSchemes[$context->getScheme()])) { - $allowSchemes += $requiredSchemes; - continue; - } - - if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) { - $allow += $requiredMethods; - continue; - } - - return $ret; - } - - $regex = substr_replace($regex, 'F', $m - $offset, 1 + \strlen($m)); - $offset += \strlen($m); - } - } - - if ('/' === $pathinfo && !$allow && !$allowSchemes) { - throw new NoConfigurationException(); - } - - return []; - } -} diff --git a/vendor/symfony/routing/Matcher/Dumper/MatcherDumper.php b/vendor/symfony/routing/Matcher/Dumper/MatcherDumper.php deleted file mode 100644 index ea51ab4..0000000 --- a/vendor/symfony/routing/Matcher/Dumper/MatcherDumper.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * MatcherDumper is the abstract class for all built-in matcher dumpers. - * - * @author Fabien Potencier - */ -abstract class MatcherDumper implements MatcherDumperInterface -{ - private $routes; - - public function __construct(RouteCollection $routes) - { - $this->routes = $routes; - } - - /** - * {@inheritdoc} - */ - public function getRoutes() - { - return $this->routes; - } -} diff --git a/vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php b/vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php deleted file mode 100644 index 34aad92..0000000 --- a/vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * MatcherDumperInterface is the interface that all matcher dumper classes must implement. - * - * @author Fabien Potencier - */ -interface MatcherDumperInterface -{ - /** - * Dumps a set of routes to a string representation of executable code - * that can then be used to match a request against these routes. - * - * @return string Executable code - */ - public function dump(array $options = []); - - /** - * Gets the routes to dump. - * - * @return RouteCollection A RouteCollection instance - */ - public function getRoutes(); -} diff --git a/vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php b/vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php deleted file mode 100644 index 65b6c07..0000000 --- a/vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php +++ /dev/null @@ -1,202 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\Routing\RouteCollection; - -/** - * Prefix tree of routes preserving routes order. - * - * @author Frank de Jonge - * @author Nicolas Grekas - * - * @internal - */ -class StaticPrefixCollection -{ - private $prefix; - - /** - * @var string[] - */ - private $staticPrefixes = []; - - /** - * @var string[] - */ - private $prefixes = []; - - /** - * @var array[]|self[] - */ - private $items = []; - - public function __construct(string $prefix = '/') - { - $this->prefix = $prefix; - } - - public function getPrefix(): string - { - return $this->prefix; - } - - /** - * @return array[]|self[] - */ - public function getRoutes(): array - { - return $this->items; - } - - /** - * Adds a route to a group. - * - * @param array|self $route - */ - public function addRoute(string $prefix, $route) - { - list($prefix, $staticPrefix) = $this->getCommonPrefix($prefix, $prefix); - - for ($i = \count($this->items) - 1; 0 <= $i; --$i) { - $item = $this->items[$i]; - - list($commonPrefix, $commonStaticPrefix) = $this->getCommonPrefix($prefix, $this->prefixes[$i]); - - if ($this->prefix === $commonPrefix) { - // the new route and a previous one have no common prefix, let's see if they are exclusive to each others - - if ($this->prefix !== $staticPrefix && $this->prefix !== $this->staticPrefixes[$i]) { - // the new route and the previous one have exclusive static prefixes - continue; - } - - if ($this->prefix === $staticPrefix && $this->prefix === $this->staticPrefixes[$i]) { - // the new route and the previous one have no static prefix - break; - } - - if ($this->prefixes[$i] !== $this->staticPrefixes[$i] && $this->prefix === $this->staticPrefixes[$i]) { - // the previous route is non-static and has no static prefix - break; - } - - if ($prefix !== $staticPrefix && $this->prefix === $staticPrefix) { - // the new route is non-static and has no static prefix - break; - } - - continue; - } - - if ($item instanceof self && $this->prefixes[$i] === $commonPrefix) { - // the new route is a child of a previous one, let's nest it - $item->addRoute($prefix, $route); - } else { - // the new route and a previous one have a common prefix, let's merge them - $child = new self($commonPrefix); - list($child->prefixes[0], $child->staticPrefixes[0]) = $child->getCommonPrefix($this->prefixes[$i], $this->prefixes[$i]); - list($child->prefixes[1], $child->staticPrefixes[1]) = $child->getCommonPrefix($prefix, $prefix); - $child->items = [$this->items[$i], $route]; - - $this->staticPrefixes[$i] = $commonStaticPrefix; - $this->prefixes[$i] = $commonPrefix; - $this->items[$i] = $child; - } - - return; - } - - // No optimised case was found, in this case we simple add the route for possible - // grouping when new routes are added. - $this->staticPrefixes[] = $staticPrefix; - $this->prefixes[] = $prefix; - $this->items[] = $route; - } - - /** - * Linearizes back a set of nested routes into a collection. - */ - public function populateCollection(RouteCollection $routes): RouteCollection - { - foreach ($this->items as $route) { - if ($route instanceof self) { - $route->populateCollection($routes); - } else { - $routes->add(...$route); - } - } - - return $routes; - } - - /** - * Gets the full and static common prefixes between two route patterns. - * - * The static prefix stops at last at the first opening bracket. - */ - private function getCommonPrefix(string $prefix, string $anotherPrefix): array - { - $baseLength = \strlen($this->prefix); - $end = min(\strlen($prefix), \strlen($anotherPrefix)); - $staticLength = null; - set_error_handler([__CLASS__, 'handleError']); - - for ($i = $baseLength; $i < $end && $prefix[$i] === $anotherPrefix[$i]; ++$i) { - if ('(' === $prefix[$i]) { - $staticLength = $staticLength ?? $i; - for ($j = 1 + $i, $n = 1; $j < $end && 0 < $n; ++$j) { - if ($prefix[$j] !== $anotherPrefix[$j]) { - break 2; - } - if ('(' === $prefix[$j]) { - ++$n; - } elseif (')' === $prefix[$j]) { - --$n; - } elseif ('\\' === $prefix[$j] && (++$j === $end || $prefix[$j] !== $anotherPrefix[$j])) { - --$j; - break; - } - } - if (0 < $n) { - break; - } - if (('?' === ($prefix[$j] ?? '') || '?' === ($anotherPrefix[$j] ?? '')) && ($prefix[$j] ?? '') !== ($anotherPrefix[$j] ?? '')) { - break; - } - $subPattern = substr($prefix, $i, $j - $i); - if ($prefix !== $anotherPrefix && !preg_match('/^\(\[[^\]]++\]\+\+\)$/', $subPattern) && !preg_match('{(?> 6) && preg_match('//u', $prefix.' '.$anotherPrefix)) { - do { - // Prevent cutting in the middle of an UTF-8 characters - --$i; - } while (0b10 === (\ord($prefix[$i]) >> 6)); - } - - return [substr($prefix, 0, $i), substr($prefix, 0, $staticLength ?? $i)]; - } - - public static function handleError($type, $msg) - { - return false !== strpos($msg, 'Compilation failed: lookbehind assertion is not fixed length'); - } -} diff --git a/vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php b/vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php deleted file mode 100644 index 3cd7c81..0000000 --- a/vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\Routing\Exception\ExceptionInterface; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; - -/** - * @author Fabien Potencier - */ -abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface -{ - /** - * {@inheritdoc} - */ - public function match(string $pathinfo) - { - try { - return parent::match($pathinfo); - } catch (ResourceNotFoundException $e) { - if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], true)) { - throw $e; - } - - if ($this->allowSchemes) { - redirect_scheme: - $scheme = $this->context->getScheme(); - $this->context->setScheme(current($this->allowSchemes)); - try { - $ret = parent::match($pathinfo); - - return $this->redirect($pathinfo, $ret['_route'] ?? null, $this->context->getScheme()) + $ret; - } catch (ExceptionInterface $e2) { - throw $e; - } finally { - $this->context->setScheme($scheme); - } - } elseif ('/' === $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') { - throw $e; - } else { - try { - $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo.'/' : $trimmedPathinfo; - $ret = parent::match($pathinfo); - - return $this->redirect($pathinfo, $ret['_route'] ?? null) + $ret; - } catch (ExceptionInterface $e2) { - if ($this->allowSchemes) { - goto redirect_scheme; - } - throw $e; - } - } - } - } -} diff --git a/vendor/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php b/vendor/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php deleted file mode 100644 index 144945d..0000000 --- a/vendor/symfony/routing/Matcher/RedirectableUrlMatcherInterface.php +++ /dev/null @@ -1,31 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -/** - * RedirectableUrlMatcherInterface knows how to redirect the user. - * - * @author Fabien Potencier - */ -interface RedirectableUrlMatcherInterface -{ - /** - * Redirects the user to another URL. - * - * @param string $path The path info to redirect to - * @param string $route The route name that matched - * @param string|null $scheme The URL scheme (null to keep the current one) - * - * @return array An array of parameters - */ - public function redirect(string $path, string $route, string $scheme = null); -} diff --git a/vendor/symfony/routing/Matcher/RequestMatcherInterface.php b/vendor/symfony/routing/Matcher/RequestMatcherInterface.php deleted file mode 100644 index 0c193ff..0000000 --- a/vendor/symfony/routing/Matcher/RequestMatcherInterface.php +++ /dev/null @@ -1,39 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; - -/** - * RequestMatcherInterface is the interface that all request matcher classes must implement. - * - * @author Fabien Potencier - */ -interface RequestMatcherInterface -{ - /** - * Tries to match a request with a set of routes. - * - * If the matcher can not find information, it must throw one of the exceptions documented - * below. - * - * @return array An array of parameters - * - * @throws NoConfigurationException If no routing configuration could be found - * @throws ResourceNotFoundException If no matching resource could be found - * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed - */ - public function matchRequest(Request $request); -} diff --git a/vendor/symfony/routing/Matcher/TraceableUrlMatcher.php b/vendor/symfony/routing/Matcher/TraceableUrlMatcher.php deleted file mode 100644 index 627cd02..0000000 --- a/vendor/symfony/routing/Matcher/TraceableUrlMatcher.php +++ /dev/null @@ -1,164 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Exception\ExceptionInterface; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * TraceableUrlMatcher helps debug path info matching by tracing the match. - * - * @author Fabien Potencier - */ -class TraceableUrlMatcher extends UrlMatcher -{ - const ROUTE_DOES_NOT_MATCH = 0; - const ROUTE_ALMOST_MATCHES = 1; - const ROUTE_MATCHES = 2; - - protected $traces; - - public function getTraces(string $pathinfo) - { - $this->traces = []; - - try { - $this->match($pathinfo); - } catch (ExceptionInterface $e) { - } - - return $this->traces; - } - - public function getTracesForRequest(Request $request) - { - $this->request = $request; - $traces = $this->getTraces($request->getPathInfo()); - $this->request = null; - - return $traces; - } - - protected function matchCollection(string $pathinfo, RouteCollection $routes) - { - // HEAD and GET are equivalent as per RFC - if ('HEAD' === $method = $this->context->getMethod()) { - $method = 'GET'; - } - $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface; - $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; - - foreach ($routes as $name => $route) { - $compiledRoute = $route->compile(); - $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); - $requiredMethods = $route->getMethods(); - - // check the static prefix of the URL first. Only use the more expensive preg_match when it matches - if ('' !== $staticPrefix && 0 !== strpos($trimmedPathinfo, $staticPrefix)) { - $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); - continue; - } - $regex = $compiledRoute->getRegex(); - - $pos = strrpos($regex, '$'); - $hasTrailingSlash = '/' === $regex[$pos - 1]; - $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); - - if (!preg_match($regex, $pathinfo, $matches)) { - // does it match without any requirements? - $r = new Route($route->getPath(), $route->getDefaults(), [], $route->getOptions()); - $cr = $r->compile(); - if (!preg_match($cr->getRegex(), $pathinfo)) { - $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); - - continue; - } - - foreach ($route->getRequirements() as $n => $regex) { - $r = new Route($route->getPath(), $route->getDefaults(), [$n => $regex], $route->getOptions()); - $cr = $r->compile(); - - if (\in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) { - $this->addTrace(sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route); - - continue 2; - } - } - - continue; - } - - $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); - - if ($hasTrailingVar && ($hasTrailingSlash || (null === $m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) { - if ($hasTrailingSlash) { - $matches = $m; - } else { - $hasTrailingVar = false; - } - } - - $hostMatches = []; - if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { - $this->addTrace(sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route); - continue; - } - - $status = $this->handleRouteRequirements($pathinfo, $name, $route); - - if (self::REQUIREMENT_MISMATCH === $status[0]) { - $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $route->getCondition()), self::ROUTE_ALMOST_MATCHES, $name, $route); - continue; - } - - if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { - if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) { - $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); - - return $this->allow = $this->allowSchemes = []; - } - $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); - continue; - } - - if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) { - $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes()); - $this->addTrace(sprintf('Scheme "%s" does not match any of the required schemes (%s)', $this->context->getScheme(), implode(', ', $route->getSchemes())), self::ROUTE_ALMOST_MATCHES, $name, $route); - continue; - } - - if ($requiredMethods && !\in_array($method, $requiredMethods)) { - $this->allow = array_merge($this->allow, $requiredMethods); - $this->addTrace(sprintf('Method "%s" does not match any of the required methods (%s)', $this->context->getMethod(), implode(', ', $requiredMethods)), self::ROUTE_ALMOST_MATCHES, $name, $route); - continue; - } - - $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); - - return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : [])); - } - - return []; - } - - private function addTrace(string $log, int $level = self::ROUTE_DOES_NOT_MATCH, string $name = null, Route $route = null) - { - $this->traces[] = [ - 'log' => $log, - 'name' => $name, - 'level' => $level, - 'path' => null !== $route ? $route->getPath() : null, - ]; - } -} diff --git a/vendor/symfony/routing/Matcher/UrlMatcher.php b/vendor/symfony/routing/Matcher/UrlMatcher.php deleted file mode 100644 index 4c76231..0000000 --- a/vendor/symfony/routing/Matcher/UrlMatcher.php +++ /dev/null @@ -1,279 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; - -/** - * UrlMatcher matches URL based on a set of routes. - * - * @author Fabien Potencier - */ -class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface -{ - const REQUIREMENT_MATCH = 0; - const REQUIREMENT_MISMATCH = 1; - const ROUTE_MATCH = 2; - - /** @var RequestContext */ - protected $context; - - /** - * Collects HTTP methods that would be allowed for the request. - */ - protected $allow = []; - - /** - * Collects URI schemes that would be allowed for the request. - * - * @internal - */ - protected $allowSchemes = []; - - protected $routes; - protected $request; - protected $expressionLanguage; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - protected $expressionLanguageProviders = []; - - public function __construct(RouteCollection $routes, RequestContext $context) - { - $this->routes = $routes; - $this->context = $context; - } - - /** - * {@inheritdoc} - */ - public function setContext(RequestContext $context) - { - $this->context = $context; - } - - /** - * {@inheritdoc} - */ - public function getContext() - { - return $this->context; - } - - /** - * {@inheritdoc} - */ - public function match(string $pathinfo) - { - $this->allow = $this->allowSchemes = []; - - if ($ret = $this->matchCollection(rawurldecode($pathinfo) ?: '/', $this->routes)) { - return $ret; - } - - if ('/' === $pathinfo && !$this->allow && !$this->allowSchemes) { - throw new NoConfigurationException(); - } - - throw 0 < \count($this->allow) ? new MethodNotAllowedException(array_unique($this->allow)) : new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); - } - - /** - * {@inheritdoc} - */ - public function matchRequest(Request $request) - { - $this->request = $request; - - $ret = $this->match($request->getPathInfo()); - - $this->request = null; - - return $ret; - } - - public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) - { - $this->expressionLanguageProviders[] = $provider; - } - - /** - * Tries to match a URL with a set of routes. - * - * @param string $pathinfo The path info to be parsed - * - * @return array An array of parameters - * - * @throws NoConfigurationException If no routing configuration could be found - * @throws ResourceNotFoundException If the resource could not be found - * @throws MethodNotAllowedException If the resource was found but the request method is not allowed - */ - protected function matchCollection(string $pathinfo, RouteCollection $routes) - { - // HEAD and GET are equivalent as per RFC - if ('HEAD' === $method = $this->context->getMethod()) { - $method = 'GET'; - } - $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface; - $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; - - foreach ($routes as $name => $route) { - $compiledRoute = $route->compile(); - $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); - $requiredMethods = $route->getMethods(); - - // check the static prefix of the URL first. Only use the more expensive preg_match when it matches - if ('' !== $staticPrefix && 0 !== strpos($trimmedPathinfo, $staticPrefix)) { - continue; - } - $regex = $compiledRoute->getRegex(); - - $pos = strrpos($regex, '$'); - $hasTrailingSlash = '/' === $regex[$pos - 1]; - $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); - - if (!preg_match($regex, $pathinfo, $matches)) { - continue; - } - - $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); - - if ($hasTrailingVar && ($hasTrailingSlash || (null === $m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) { - if ($hasTrailingSlash) { - $matches = $m; - } else { - $hasTrailingVar = false; - } - } - - $hostMatches = []; - if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { - continue; - } - - $status = $this->handleRouteRequirements($pathinfo, $name, $route); - - if (self::REQUIREMENT_MISMATCH === $status[0]) { - continue; - } - - if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { - if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) { - return $this->allow = $this->allowSchemes = []; - } - continue; - } - - if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) { - $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes()); - continue; - } - - if ($requiredMethods && !\in_array($method, $requiredMethods)) { - $this->allow = array_merge($this->allow, $requiredMethods); - continue; - } - - return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : [])); - } - - return []; - } - - /** - * Returns an array of values to use as request attributes. - * - * As this method requires the Route object, it is not available - * in matchers that do not have access to the matched Route instance - * (like the PHP and Apache matcher dumpers). - * - * @return array An array of parameters - */ - protected function getAttributes(Route $route, string $name, array $attributes) - { - $defaults = $route->getDefaults(); - if (isset($defaults['_canonical_route'])) { - $name = $defaults['_canonical_route']; - unset($defaults['_canonical_route']); - } - $attributes['_route'] = $name; - - return $this->mergeDefaults($attributes, $defaults); - } - - /** - * Handles specific route requirements. - * - * @return array The first element represents the status, the second contains additional information - */ - protected function handleRouteRequirements(string $pathinfo, string $name, Route $route) - { - // expression condition - if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), ['context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)])) { - return [self::REQUIREMENT_MISMATCH, null]; - } - - return [self::REQUIREMENT_MATCH, null]; - } - - /** - * Get merged default parameters. - * - * @return array Merged default parameters - */ - protected function mergeDefaults(array $params, array $defaults) - { - foreach ($params as $key => $value) { - if (!\is_int($key) && null !== $value) { - $defaults[$key] = $value; - } - } - - return $defaults; - } - - protected function getExpressionLanguage() - { - if (null === $this->expressionLanguage) { - if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { - throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); - } - - return $this->expressionLanguage; - } - - /** - * @internal - */ - protected function createRequest(string $pathinfo): ?Request - { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - return null; - } - - return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo, $this->context->getMethod(), $this->context->getParameters(), [], [], [ - 'SCRIPT_FILENAME' => $this->context->getBaseUrl(), - 'SCRIPT_NAME' => $this->context->getBaseUrl(), - ]); - } -} diff --git a/vendor/symfony/routing/Matcher/UrlMatcherInterface.php b/vendor/symfony/routing/Matcher/UrlMatcherInterface.php deleted file mode 100644 index 24f23e3..0000000 --- a/vendor/symfony/routing/Matcher/UrlMatcherInterface.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher; - -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\RequestContextAwareInterface; - -/** - * UrlMatcherInterface is the interface that all URL matcher classes must implement. - * - * @author Fabien Potencier - */ -interface UrlMatcherInterface extends RequestContextAwareInterface -{ - /** - * Tries to match a URL path with a set of routes. - * - * If the matcher can not find information, it must throw one of the exceptions documented - * below. - * - * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded) - * - * @return array An array of parameters - * - * @throws NoConfigurationException If no routing configuration could be found - * @throws ResourceNotFoundException If the resource could not be found - * @throws MethodNotAllowedException If the resource was found but the request method is not allowed - */ - public function match(string $pathinfo); -} diff --git a/vendor/symfony/routing/README.md b/vendor/symfony/routing/README.md deleted file mode 100644 index 88fb1fd..0000000 --- a/vendor/symfony/routing/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Routing Component -================= - -The Routing component maps an HTTP request to a set of configuration variables. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/routing/index.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/routing/RequestContext.php b/vendor/symfony/routing/RequestContext.php deleted file mode 100644 index cb655f4..0000000 --- a/vendor/symfony/routing/RequestContext.php +++ /dev/null @@ -1,305 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\HttpFoundation\Request; - -/** - * Holds information about the current request. - * - * This class implements a fluent interface. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class RequestContext -{ - private $baseUrl; - private $pathInfo; - private $method; - private $host; - private $scheme; - private $httpPort; - private $httpsPort; - private $queryString; - private $parameters = []; - - public function __construct(string $baseUrl = '', string $method = 'GET', string $host = 'localhost', string $scheme = 'http', int $httpPort = 80, int $httpsPort = 443, string $path = '/', string $queryString = '') - { - $this->setBaseUrl($baseUrl); - $this->setMethod($method); - $this->setHost($host); - $this->setScheme($scheme); - $this->setHttpPort($httpPort); - $this->setHttpsPort($httpsPort); - $this->setPathInfo($path); - $this->setQueryString($queryString); - } - - /** - * Updates the RequestContext information based on a HttpFoundation Request. - * - * @return $this - */ - public function fromRequest(Request $request) - { - $this->setBaseUrl($request->getBaseUrl()); - $this->setPathInfo($request->getPathInfo()); - $this->setMethod($request->getMethod()); - $this->setHost($request->getHost()); - $this->setScheme($request->getScheme()); - $this->setHttpPort($request->isSecure() || null === $request->getPort() ? $this->httpPort : $request->getPort()); - $this->setHttpsPort($request->isSecure() && null !== $request->getPort() ? $request->getPort() : $this->httpsPort); - $this->setQueryString($request->server->get('QUERY_STRING', '')); - - return $this; - } - - /** - * Gets the base URL. - * - * @return string The base URL - */ - public function getBaseUrl() - { - return $this->baseUrl; - } - - /** - * Sets the base URL. - * - * @return $this - */ - public function setBaseUrl(string $baseUrl) - { - $this->baseUrl = $baseUrl; - - return $this; - } - - /** - * Gets the path info. - * - * @return string The path info - */ - public function getPathInfo() - { - return $this->pathInfo; - } - - /** - * Sets the path info. - * - * @return $this - */ - public function setPathInfo(string $pathInfo) - { - $this->pathInfo = $pathInfo; - - return $this; - } - - /** - * Gets the HTTP method. - * - * The method is always an uppercased string. - * - * @return string The HTTP method - */ - public function getMethod() - { - return $this->method; - } - - /** - * Sets the HTTP method. - * - * @return $this - */ - public function setMethod(string $method) - { - $this->method = strtoupper($method); - - return $this; - } - - /** - * Gets the HTTP host. - * - * The host is always lowercased because it must be treated case-insensitive. - * - * @return string The HTTP host - */ - public function getHost() - { - return $this->host; - } - - /** - * Sets the HTTP host. - * - * @return $this - */ - public function setHost(string $host) - { - $this->host = strtolower($host); - - return $this; - } - - /** - * Gets the HTTP scheme. - * - * @return string The HTTP scheme - */ - public function getScheme() - { - return $this->scheme; - } - - /** - * Sets the HTTP scheme. - * - * @return $this - */ - public function setScheme(string $scheme) - { - $this->scheme = strtolower($scheme); - - return $this; - } - - /** - * Gets the HTTP port. - * - * @return int The HTTP port - */ - public function getHttpPort() - { - return $this->httpPort; - } - - /** - * Sets the HTTP port. - * - * @return $this - */ - public function setHttpPort(int $httpPort) - { - $this->httpPort = $httpPort; - - return $this; - } - - /** - * Gets the HTTPS port. - * - * @return int The HTTPS port - */ - public function getHttpsPort() - { - return $this->httpsPort; - } - - /** - * Sets the HTTPS port. - * - * @return $this - */ - public function setHttpsPort(int $httpsPort) - { - $this->httpsPort = $httpsPort; - - return $this; - } - - /** - * Gets the query string. - * - * @return string The query string without the "?" - */ - public function getQueryString() - { - return $this->queryString; - } - - /** - * Sets the query string. - * - * @return $this - */ - public function setQueryString(?string $queryString) - { - // string cast to be fault-tolerant, accepting null - $this->queryString = (string) $queryString; - - return $this; - } - - /** - * Returns the parameters. - * - * @return array The parameters - */ - public function getParameters() - { - return $this->parameters; - } - - /** - * Sets the parameters. - * - * @param array $parameters The parameters - * - * @return $this - */ - public function setParameters(array $parameters) - { - $this->parameters = $parameters; - - return $this; - } - - /** - * Gets a parameter value. - * - * @return mixed The parameter value or null if nonexistent - */ - public function getParameter(string $name) - { - return isset($this->parameters[$name]) ? $this->parameters[$name] : null; - } - - /** - * Checks if a parameter value is set for the given parameter. - * - * @return bool True if the parameter value is set, false otherwise - */ - public function hasParameter(string $name) - { - return \array_key_exists($name, $this->parameters); - } - - /** - * Sets a parameter value. - * - * @param mixed $parameter The parameter value - * - * @return $this - */ - public function setParameter(string $name, $parameter) - { - $this->parameters[$name] = $parameter; - - return $this; - } -} diff --git a/vendor/symfony/routing/RequestContextAwareInterface.php b/vendor/symfony/routing/RequestContextAwareInterface.php deleted file mode 100644 index df5b9fc..0000000 --- a/vendor/symfony/routing/RequestContextAwareInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -interface RequestContextAwareInterface -{ - /** - * Sets the request context. - */ - public function setContext(RequestContext $context); - - /** - * Gets the request context. - * - * @return RequestContext The context - */ - public function getContext(); -} diff --git a/vendor/symfony/routing/Route.php b/vendor/symfony/routing/Route.php deleted file mode 100644 index 3b4d04c..0000000 --- a/vendor/symfony/routing/Route.php +++ /dev/null @@ -1,547 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -/** - * A Route describes a route and its parameters. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class Route implements \Serializable -{ - private $path = '/'; - private $host = ''; - private $schemes = []; - private $methods = []; - private $defaults = []; - private $requirements = []; - private $options = []; - private $condition = ''; - - /** - * @var CompiledRoute|null - */ - private $compiled; - - /** - * Constructor. - * - * Available options: - * - * * compiler_class: A class name able to compile this route instance (RouteCompiler by default) - * * utf8: Whether UTF-8 matching is enforced ot not - * - * @param string $path The path pattern to match - * @param array $defaults An array of default parameter values - * @param array $requirements An array of requirements for parameters (regexes) - * @param array $options An array of options - * @param string|null $host The host pattern to match - * @param string|string[] $schemes A required URI scheme or an array of restricted schemes - * @param string|string[] $methods A required HTTP method or an array of restricted methods - * @param string|null $condition A condition that should evaluate to true for the route to match - */ - public function __construct(string $path, array $defaults = [], array $requirements = [], array $options = [], ?string $host = '', $schemes = [], $methods = [], ?string $condition = '') - { - $this->setPath($path); - $this->addDefaults($defaults); - $this->addRequirements($requirements); - $this->setOptions($options); - $this->setHost($host); - $this->setSchemes($schemes); - $this->setMethods($methods); - $this->setCondition($condition); - } - - public function __serialize(): array - { - return [ - 'path' => $this->path, - 'host' => $this->host, - 'defaults' => $this->defaults, - 'requirements' => $this->requirements, - 'options' => $this->options, - 'schemes' => $this->schemes, - 'methods' => $this->methods, - 'condition' => $this->condition, - 'compiled' => $this->compiled, - ]; - } - - /** - * @internal - */ - final public function serialize(): string - { - return serialize($this->__serialize()); - } - - public function __unserialize(array $data): void - { - $this->path = $data['path']; - $this->host = $data['host']; - $this->defaults = $data['defaults']; - $this->requirements = $data['requirements']; - $this->options = $data['options']; - $this->schemes = $data['schemes']; - $this->methods = $data['methods']; - - if (isset($data['condition'])) { - $this->condition = $data['condition']; - } - if (isset($data['compiled'])) { - $this->compiled = $data['compiled']; - } - } - - /** - * @internal - */ - final public function unserialize($serialized) - { - $this->__unserialize(unserialize($serialized)); - } - - /** - * Returns the pattern for the path. - * - * @return string The path pattern - */ - public function getPath() - { - return $this->path; - } - - /** - * Sets the pattern for the path. - * - * This method implements a fluent interface. - * - * @return $this - */ - public function setPath(string $pattern) - { - if (false !== strpbrk($pattern, '?<')) { - $pattern = preg_replace_callback('#\{(\w++)(<.*?>)?(\?[^\}]*+)?\}#', function ($m) { - if (isset($m[3][0])) { - $this->setDefault($m[1], '?' !== $m[3] ? substr($m[3], 1) : null); - } - if (isset($m[2][0])) { - $this->setRequirement($m[1], substr($m[2], 1, -1)); - } - - return '{'.$m[1].'}'; - }, $pattern); - } - - // A pattern must start with a slash and must not have multiple slashes at the beginning because the - // generated path for this route would be confused with a network path, e.g. '//domain.com/path'. - $this->path = '/'.ltrim(trim($pattern), '/'); - $this->compiled = null; - - return $this; - } - - /** - * Returns the pattern for the host. - * - * @return string The host pattern - */ - public function getHost() - { - return $this->host; - } - - /** - * Sets the pattern for the host. - * - * This method implements a fluent interface. - * - * @return $this - */ - public function setHost(?string $pattern) - { - $this->host = (string) $pattern; - $this->compiled = null; - - return $this; - } - - /** - * Returns the lowercased schemes this route is restricted to. - * So an empty array means that any scheme is allowed. - * - * @return string[] The schemes - */ - public function getSchemes() - { - return $this->schemes; - } - - /** - * Sets the schemes (e.g. 'https') this route is restricted to. - * So an empty array means that any scheme is allowed. - * - * This method implements a fluent interface. - * - * @param string|string[] $schemes The scheme or an array of schemes - * - * @return $this - */ - public function setSchemes($schemes) - { - $this->schemes = array_map('strtolower', (array) $schemes); - $this->compiled = null; - - return $this; - } - - /** - * Checks if a scheme requirement has been set. - * - * @return bool true if the scheme requirement exists, otherwise false - */ - public function hasScheme(string $scheme) - { - return \in_array(strtolower($scheme), $this->schemes, true); - } - - /** - * Returns the uppercased HTTP methods this route is restricted to. - * So an empty array means that any method is allowed. - * - * @return string[] The methods - */ - public function getMethods() - { - return $this->methods; - } - - /** - * Sets the HTTP methods (e.g. 'POST') this route is restricted to. - * So an empty array means that any method is allowed. - * - * This method implements a fluent interface. - * - * @param string|string[] $methods The method or an array of methods - * - * @return $this - */ - public function setMethods($methods) - { - $this->methods = array_map('strtoupper', (array) $methods); - $this->compiled = null; - - return $this; - } - - /** - * Returns the options. - * - * @return array The options - */ - public function getOptions() - { - return $this->options; - } - - /** - * Sets the options. - * - * This method implements a fluent interface. - * - * @return $this - */ - public function setOptions(array $options) - { - $this->options = [ - 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', - ]; - - return $this->addOptions($options); - } - - /** - * Adds options. - * - * This method implements a fluent interface. - * - * @return $this - */ - public function addOptions(array $options) - { - foreach ($options as $name => $option) { - $this->options[$name] = $option; - } - $this->compiled = null; - - return $this; - } - - /** - * Sets an option value. - * - * This method implements a fluent interface. - * - * @param mixed $value The option value - * - * @return $this - */ - public function setOption(string $name, $value) - { - $this->options[$name] = $value; - $this->compiled = null; - - return $this; - } - - /** - * Get an option value. - * - * @return mixed The option value or null when not given - */ - public function getOption(string $name) - { - return isset($this->options[$name]) ? $this->options[$name] : null; - } - - /** - * Checks if an option has been set. - * - * @return bool true if the option is set, false otherwise - */ - public function hasOption(string $name) - { - return \array_key_exists($name, $this->options); - } - - /** - * Returns the defaults. - * - * @return array The defaults - */ - public function getDefaults() - { - return $this->defaults; - } - - /** - * Sets the defaults. - * - * This method implements a fluent interface. - * - * @param array $defaults The defaults - * - * @return $this - */ - public function setDefaults(array $defaults) - { - $this->defaults = []; - - return $this->addDefaults($defaults); - } - - /** - * Adds defaults. - * - * This method implements a fluent interface. - * - * @param array $defaults The defaults - * - * @return $this - */ - public function addDefaults(array $defaults) - { - foreach ($defaults as $name => $default) { - $this->defaults[$name] = $default; - } - $this->compiled = null; - - return $this; - } - - /** - * Gets a default value. - * - * @return mixed The default value or null when not given - */ - public function getDefault(string $name) - { - return isset($this->defaults[$name]) ? $this->defaults[$name] : null; - } - - /** - * Checks if a default value is set for the given variable. - * - * @return bool true if the default value is set, false otherwise - */ - public function hasDefault(string $name) - { - return \array_key_exists($name, $this->defaults); - } - - /** - * Sets a default value. - * - * @param mixed $default The default value - * - * @return $this - */ - public function setDefault(string $name, $default) - { - $this->defaults[$name] = $default; - $this->compiled = null; - - return $this; - } - - /** - * Returns the requirements. - * - * @return array The requirements - */ - public function getRequirements() - { - return $this->requirements; - } - - /** - * Sets the requirements. - * - * This method implements a fluent interface. - * - * @param array $requirements The requirements - * - * @return $this - */ - public function setRequirements(array $requirements) - { - $this->requirements = []; - - return $this->addRequirements($requirements); - } - - /** - * Adds requirements. - * - * This method implements a fluent interface. - * - * @param array $requirements The requirements - * - * @return $this - */ - public function addRequirements(array $requirements) - { - foreach ($requirements as $key => $regex) { - $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); - } - $this->compiled = null; - - return $this; - } - - /** - * Returns the requirement for the given key. - * - * @return string|null The regex or null when not given - */ - public function getRequirement(string $key) - { - return isset($this->requirements[$key]) ? $this->requirements[$key] : null; - } - - /** - * Checks if a requirement is set for the given key. - * - * @return bool true if a requirement is specified, false otherwise - */ - public function hasRequirement(string $key) - { - return \array_key_exists($key, $this->requirements); - } - - /** - * Sets a requirement for the given key. - * - * @return $this - */ - public function setRequirement(string $key, string $regex) - { - $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); - $this->compiled = null; - - return $this; - } - - /** - * Returns the condition. - * - * @return string The condition - */ - public function getCondition() - { - return $this->condition; - } - - /** - * Sets the condition. - * - * This method implements a fluent interface. - * - * @return $this - */ - public function setCondition(?string $condition) - { - $this->condition = (string) $condition; - $this->compiled = null; - - return $this; - } - - /** - * Compiles the route. - * - * @return CompiledRoute A CompiledRoute instance - * - * @throws \LogicException If the Route cannot be compiled because the - * path or host pattern is invalid - * - * @see RouteCompiler which is responsible for the compilation process - */ - public function compile() - { - if (null !== $this->compiled) { - return $this->compiled; - } - - $class = $this->getOption('compiler_class'); - - return $this->compiled = $class::compile($this); - } - - private function sanitizeRequirement(string $key, string $regex) - { - if ('' !== $regex && '^' === $regex[0]) { - $regex = (string) substr($regex, 1); // returns false for a single character - } - - if ('$' === substr($regex, -1)) { - $regex = substr($regex, 0, -1); - } - - if ('' === $regex) { - throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key)); - } - - return $regex; - } -} diff --git a/vendor/symfony/routing/RouteCollection.php b/vendor/symfony/routing/RouteCollection.php deleted file mode 100644 index 6c7bcf1..0000000 --- a/vendor/symfony/routing/RouteCollection.php +++ /dev/null @@ -1,273 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\Config\Resource\ResourceInterface; - -/** - * A RouteCollection represents a set of Route instances. - * - * When adding a route at the end of the collection, an existing route - * with the same name is removed first. So there can only be one route - * with a given name. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class RouteCollection implements \IteratorAggregate, \Countable -{ - /** - * @var Route[] - */ - private $routes = []; - - /** - * @var array - */ - private $resources = []; - - public function __clone() - { - foreach ($this->routes as $name => $route) { - $this->routes[$name] = clone $route; - } - } - - /** - * Gets the current RouteCollection as an Iterator that includes all routes. - * - * It implements \IteratorAggregate. - * - * @see all() - * - * @return \ArrayIterator|Route[] An \ArrayIterator object for iterating over routes - */ - public function getIterator() - { - return new \ArrayIterator($this->routes); - } - - /** - * Gets the number of Routes in this collection. - * - * @return int The number of routes - */ - public function count() - { - return \count($this->routes); - } - - public function add(string $name, Route $route) - { - unset($this->routes[$name]); - - $this->routes[$name] = $route; - } - - /** - * Returns all routes in this collection. - * - * @return Route[] An array of routes - */ - public function all() - { - return $this->routes; - } - - /** - * Gets a route by name. - * - * @return Route|null A Route instance or null when not found - */ - public function get(string $name) - { - return isset($this->routes[$name]) ? $this->routes[$name] : null; - } - - /** - * Removes a route or an array of routes by name from the collection. - * - * @param string|string[] $name The route name or an array of route names - */ - public function remove($name) - { - foreach ((array) $name as $n) { - unset($this->routes[$n]); - } - } - - /** - * Adds a route collection at the end of the current set by appending all - * routes of the added collection. - */ - public function addCollection(self $collection) - { - // we need to remove all routes with the same names first because just replacing them - // would not place the new route at the end of the merged array - foreach ($collection->all() as $name => $route) { - unset($this->routes[$name]); - $this->routes[$name] = $route; - } - - foreach ($collection->getResources() as $resource) { - $this->addResource($resource); - } - } - - /** - * Adds a prefix to the path of all child routes. - */ - public function addPrefix(string $prefix, array $defaults = [], array $requirements = []) - { - $prefix = trim(trim($prefix), '/'); - - if ('' === $prefix) { - return; - } - - foreach ($this->routes as $route) { - $route->setPath('/'.$prefix.$route->getPath()); - $route->addDefaults($defaults); - $route->addRequirements($requirements); - } - } - - /** - * Adds a prefix to the name of all the routes within in the collection. - */ - public function addNamePrefix(string $prefix) - { - $prefixedRoutes = []; - - foreach ($this->routes as $name => $route) { - $prefixedRoutes[$prefix.$name] = $route; - if (null !== $name = $route->getDefault('_canonical_route')) { - $route->setDefault('_canonical_route', $prefix.$name); - } - } - - $this->routes = $prefixedRoutes; - } - - /** - * Sets the host pattern on all routes. - */ - public function setHost(?string $pattern, array $defaults = [], array $requirements = []) - { - foreach ($this->routes as $route) { - $route->setHost($pattern); - $route->addDefaults($defaults); - $route->addRequirements($requirements); - } - } - - /** - * Sets a condition on all routes. - * - * Existing conditions will be overridden. - */ - public function setCondition(?string $condition) - { - foreach ($this->routes as $route) { - $route->setCondition($condition); - } - } - - /** - * Adds defaults to all routes. - * - * An existing default value under the same name in a route will be overridden. - */ - public function addDefaults(array $defaults) - { - if ($defaults) { - foreach ($this->routes as $route) { - $route->addDefaults($defaults); - } - } - } - - /** - * Adds requirements to all routes. - * - * An existing requirement under the same name in a route will be overridden. - */ - public function addRequirements(array $requirements) - { - if ($requirements) { - foreach ($this->routes as $route) { - $route->addRequirements($requirements); - } - } - } - - /** - * Adds options to all routes. - * - * An existing option value under the same name in a route will be overridden. - */ - public function addOptions(array $options) - { - if ($options) { - foreach ($this->routes as $route) { - $route->addOptions($options); - } - } - } - - /** - * Sets the schemes (e.g. 'https') all child routes are restricted to. - * - * @param string|string[] $schemes The scheme or an array of schemes - */ - public function setSchemes($schemes) - { - foreach ($this->routes as $route) { - $route->setSchemes($schemes); - } - } - - /** - * Sets the HTTP methods (e.g. 'POST') all child routes are restricted to. - * - * @param string|string[] $methods The method or an array of methods - */ - public function setMethods($methods) - { - foreach ($this->routes as $route) { - $route->setMethods($methods); - } - } - - /** - * Returns an array of resources loaded to build this collection. - * - * @return ResourceInterface[] An array of resources - */ - public function getResources() - { - return array_values($this->resources); - } - - /** - * Adds a resource for this collection. If the resource already exists - * it is not added. - */ - public function addResource(ResourceInterface $resource) - { - $key = (string) $resource; - - if (!isset($this->resources[$key])) { - $this->resources[$key] = $resource; - } - } -} diff --git a/vendor/symfony/routing/RouteCollectionBuilder.php b/vendor/symfony/routing/RouteCollectionBuilder.php deleted file mode 100644 index 406e3c0..0000000 --- a/vendor/symfony/routing/RouteCollectionBuilder.php +++ /dev/null @@ -1,359 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\Config\Exception\LoaderLoadException; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\Config\Resource\ResourceInterface; - -/** - * Helps add and import routes into a RouteCollection. - * - * @author Ryan Weaver - */ -class RouteCollectionBuilder -{ - /** - * @var Route[]|RouteCollectionBuilder[] - */ - private $routes = []; - - private $loader; - private $defaults = []; - private $prefix; - private $host; - private $condition; - private $requirements = []; - private $options = []; - private $schemes; - private $methods; - private $resources = []; - - public function __construct(LoaderInterface $loader = null) - { - $this->loader = $loader; - } - - /** - * Import an external routing resource and returns the RouteCollectionBuilder. - * - * $routes->import('blog.yml', '/blog'); - * - * @param mixed $resource - * - * @return self - * - * @throws LoaderLoadException - */ - public function import($resource, string $prefix = '/', string $type = null) - { - /** @var RouteCollection[] $collections */ - $collections = $this->load($resource, $type); - - // create a builder from the RouteCollection - $builder = $this->createBuilder(); - - foreach ($collections as $collection) { - if (null === $collection) { - continue; - } - - foreach ($collection->all() as $name => $route) { - $builder->addRoute($route, $name); - } - - foreach ($collection->getResources() as $resource) { - $builder->addResource($resource); - } - } - - // mount into this builder - $this->mount($prefix, $builder); - - return $builder; - } - - /** - * Adds a route and returns it for future modification. - * - * @return Route - */ - public function add(string $path, string $controller, string $name = null) - { - $route = new Route($path); - $route->setDefault('_controller', $controller); - $this->addRoute($route, $name); - - return $route; - } - - /** - * Returns a RouteCollectionBuilder that can be configured and then added with mount(). - * - * @return self - */ - public function createBuilder() - { - return new self($this->loader); - } - - /** - * Add a RouteCollectionBuilder. - */ - public function mount(string $prefix, self $builder) - { - $builder->prefix = trim(trim($prefix), '/'); - $this->routes[] = $builder; - } - - /** - * Adds a Route object to the builder. - * - * @return $this - */ - public function addRoute(Route $route, string $name = null) - { - if (null === $name) { - // used as a flag to know which routes will need a name later - $name = '_unnamed_route_'.spl_object_hash($route); - } - - $this->routes[$name] = $route; - - return $this; - } - - /** - * Sets the host on all embedded routes (unless already set). - * - * @return $this - */ - public function setHost(?string $pattern) - { - $this->host = $pattern; - - return $this; - } - - /** - * Sets a condition on all embedded routes (unless already set). - * - * @return $this - */ - public function setCondition(?string $condition) - { - $this->condition = $condition; - - return $this; - } - - /** - * Sets a default value that will be added to all embedded routes (unless that - * default value is already set). - * - * @param mixed $value - * - * @return $this - */ - public function setDefault(string $key, $value) - { - $this->defaults[$key] = $value; - - return $this; - } - - /** - * Sets a requirement that will be added to all embedded routes (unless that - * requirement is already set). - * - * @param mixed $regex - * - * @return $this - */ - public function setRequirement(string $key, $regex) - { - $this->requirements[$key] = $regex; - - return $this; - } - - /** - * Sets an option that will be added to all embedded routes (unless that - * option is already set). - * - * @param mixed $value - * - * @return $this - */ - public function setOption(string $key, $value) - { - $this->options[$key] = $value; - - return $this; - } - - /** - * Sets the schemes on all embedded routes (unless already set). - * - * @param array|string $schemes - * - * @return $this - */ - public function setSchemes($schemes) - { - $this->schemes = $schemes; - - return $this; - } - - /** - * Sets the methods on all embedded routes (unless already set). - * - * @param array|string $methods - * - * @return $this - */ - public function setMethods($methods) - { - $this->methods = $methods; - - return $this; - } - - /** - * Adds a resource for this collection. - * - * @return $this - */ - private function addResource(ResourceInterface $resource): self - { - $this->resources[] = $resource; - - return $this; - } - - /** - * Creates the final RouteCollection and returns it. - * - * @return RouteCollection - */ - public function build() - { - $routeCollection = new RouteCollection(); - - foreach ($this->routes as $name => $route) { - if ($route instanceof Route) { - $route->setDefaults(array_merge($this->defaults, $route->getDefaults())); - $route->setOptions(array_merge($this->options, $route->getOptions())); - - foreach ($this->requirements as $key => $val) { - if (!$route->hasRequirement($key)) { - $route->setRequirement($key, $val); - } - } - - if (null !== $this->prefix) { - $route->setPath('/'.$this->prefix.$route->getPath()); - } - - if (!$route->getHost()) { - $route->setHost($this->host); - } - - if (!$route->getCondition()) { - $route->setCondition($this->condition); - } - - if (!$route->getSchemes()) { - $route->setSchemes($this->schemes); - } - - if (!$route->getMethods()) { - $route->setMethods($this->methods); - } - - // auto-generate the route name if it's been marked - if ('_unnamed_route_' === substr($name, 0, 15)) { - $name = $this->generateRouteName($route); - } - - $routeCollection->add($name, $route); - } else { - /* @var self $route */ - $subCollection = $route->build(); - if (null !== $this->prefix) { - $subCollection->addPrefix($this->prefix); - } - - $routeCollection->addCollection($subCollection); - } - } - - foreach ($this->resources as $resource) { - $routeCollection->addResource($resource); - } - - return $routeCollection; - } - - /** - * Generates a route name based on details of this route. - */ - private function generateRouteName(Route $route): string - { - $methods = implode('_', $route->getMethods()).'_'; - - $routeName = $methods.$route->getPath(); - $routeName = str_replace(['/', ':', '|', '-'], '_', $routeName); - $routeName = preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName); - - // Collapse consecutive underscores down into a single underscore. - $routeName = preg_replace('/_+/', '_', $routeName); - - return $routeName; - } - - /** - * Finds a loader able to load an imported resource and loads it. - * - * @param mixed $resource A resource - * @param string|null $type The resource type or null if unknown - * - * @return RouteCollection[] - * - * @throws LoaderLoadException If no loader is found - */ - private function load($resource, string $type = null): array - { - if (null === $this->loader) { - throw new \BadMethodCallException('Cannot import other routing resources: you must pass a LoaderInterface when constructing RouteCollectionBuilder.'); - } - - if ($this->loader->supports($resource, $type)) { - $collections = $this->loader->load($resource, $type); - - return \is_array($collections) ? $collections : [$collections]; - } - - if (null === $resolver = $this->loader->getResolver()) { - throw new LoaderLoadException($resource, null, null, null, $type); - } - - if (false === $loader = $resolver->resolve($resource, $type)) { - throw new LoaderLoadException($resource, null, null, null, $type); - } - - $collections = $loader->load($resource, $type); - - return \is_array($collections) ? $collections : [$collections]; - } -} diff --git a/vendor/symfony/routing/RouteCompiler.php b/vendor/symfony/routing/RouteCompiler.php deleted file mode 100644 index 59f3a32..0000000 --- a/vendor/symfony/routing/RouteCompiler.php +++ /dev/null @@ -1,337 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -/** - * RouteCompiler compiles Route instances to CompiledRoute instances. - * - * @author Fabien Potencier - * @author Tobias Schultze - */ -class RouteCompiler implements RouteCompilerInterface -{ - const REGEX_DELIMITER = '#'; - - /** - * This string defines the characters that are automatically considered separators in front of - * optional placeholders (with default and no static text following). Such a single separator - * can be left out together with the optional placeholder from matching and generating URLs. - */ - const SEPARATORS = '/,;.:-_~+*=@|'; - - /** - * The maximum supported length of a PCRE subpattern name - * http://pcre.org/current/doc/html/pcre2pattern.html#SEC16. - * - * @internal - */ - const VARIABLE_MAXIMUM_LENGTH = 32; - - /** - * {@inheritdoc} - * - * @throws \InvalidArgumentException if a path variable is named _fragment - * @throws \LogicException if a variable is referenced more than once - * @throws \DomainException if a variable name starts with a digit or if it is too long to be successfully used as - * a PCRE subpattern - */ - public static function compile(Route $route) - { - $hostVariables = []; - $variables = []; - $hostRegex = null; - $hostTokens = []; - - if ('' !== $host = $route->getHost()) { - $result = self::compilePattern($route, $host, true); - - $hostVariables = $result['variables']; - $variables = $hostVariables; - - $hostTokens = $result['tokens']; - $hostRegex = $result['regex']; - } - - $path = $route->getPath(); - - $result = self::compilePattern($route, $path, false); - - $staticPrefix = $result['staticPrefix']; - - $pathVariables = $result['variables']; - - foreach ($pathVariables as $pathParam) { - if ('_fragment' === $pathParam) { - throw new \InvalidArgumentException(sprintf('Route pattern "%s" cannot contain "_fragment" as a path parameter.', $route->getPath())); - } - } - - $variables = array_merge($variables, $pathVariables); - - $tokens = $result['tokens']; - $regex = $result['regex']; - - return new CompiledRoute( - $staticPrefix, - $regex, - $tokens, - $pathVariables, - $hostRegex, - $hostTokens, - $hostVariables, - array_unique($variables) - ); - } - - private static function compilePattern(Route $route, string $pattern, bool $isHost): array - { - $tokens = []; - $variables = []; - $matches = []; - $pos = 0; - $defaultSeparator = $isHost ? '.' : '/'; - $useUtf8 = preg_match('//u', $pattern); - $needsUtf8 = $route->getOption('utf8'); - - if (!$needsUtf8 && $useUtf8 && preg_match('/[\x80-\xFF]/', $pattern)) { - throw new \LogicException(sprintf('Cannot use UTF-8 route patterns without setting the "utf8" option for route "%s".', $route->getPath())); - } - if (!$useUtf8 && $needsUtf8) { - throw new \LogicException(sprintf('Cannot mix UTF-8 requirements with non-UTF-8 pattern "%s".', $pattern)); - } - - // Match all variables enclosed in "{}" and iterate over them. But we only want to match the innermost variable - // in case of nested "{}", e.g. {foo{bar}}. This in ensured because \w does not match "{" or "}" itself. - preg_match_all('#\{(!)?(\w+)\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); - foreach ($matches as $match) { - $important = $match[1][1] >= 0; - $varName = $match[2][0]; - // get all static text preceding the current variable - $precedingText = substr($pattern, $pos, $match[0][1] - $pos); - $pos = $match[0][1] + \strlen($match[0][0]); - - if (!\strlen($precedingText)) { - $precedingChar = ''; - } elseif ($useUtf8) { - preg_match('/.$/u', $precedingText, $precedingChar); - $precedingChar = $precedingChar[0]; - } else { - $precedingChar = substr($precedingText, -1); - } - $isSeparator = '' !== $precedingChar && false !== strpos(static::SEPARATORS, $precedingChar); - - // A PCRE subpattern name must start with a non-digit. Also a PHP variable cannot start with a digit so the - // variable would not be usable as a Controller action argument. - if (preg_match('/^\d/', $varName)) { - throw new \DomainException(sprintf('Variable name "%s" cannot start with a digit in route pattern "%s". Please use a different name.', $varName, $pattern)); - } - if (\in_array($varName, $variables)) { - throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName)); - } - - if (\strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) { - throw new \DomainException(sprintf('Variable name "%s" cannot be longer than %s characters in route pattern "%s". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern)); - } - - if ($isSeparator && $precedingText !== $precedingChar) { - $tokens[] = ['text', substr($precedingText, 0, -\strlen($precedingChar))]; - } elseif (!$isSeparator && \strlen($precedingText) > 0) { - $tokens[] = ['text', $precedingText]; - } - - $regexp = $route->getRequirement($varName); - if (null === $regexp) { - $followingPattern = (string) substr($pattern, $pos); - // Find the next static character after the variable that functions as a separator. By default, this separator and '/' - // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all - // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are - // the same that will be matched. Example: new Route('/{page}.{_format}', ['_format' => 'html']) - // If {page} would also match the separating dot, {_format} would never match as {page} will eagerly consume everything. - // Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally - // part of {_format} when generating the URL, e.g. _format = 'mobile.html'. - $nextSeparator = self::findNextSeparator($followingPattern, $useUtf8); - $regexp = sprintf( - '[^%s%s]+', - preg_quote($defaultSeparator, self::REGEX_DELIMITER), - $defaultSeparator !== $nextSeparator && '' !== $nextSeparator ? preg_quote($nextSeparator, self::REGEX_DELIMITER) : '' - ); - if (('' !== $nextSeparator && !preg_match('#^\{\w+\}#', $followingPattern)) || '' === $followingPattern) { - // When we have a separator, which is disallowed for the variable, we can optimize the regex with a possessive - // quantifier. This prevents useless backtracking of PCRE and improves performance by 20% for matching those patterns. - // Given the above example, there is no point in backtracking into {page} (that forbids the dot) when a dot must follow - // after it. This optimization cannot be applied when the next char is no real separator or when the next variable is - // directly adjacent, e.g. '/{x}{y}'. - $regexp .= '+'; - } - } else { - if (!preg_match('//u', $regexp)) { - $useUtf8 = false; - } elseif (!$needsUtf8 && preg_match('/[\x80-\xFF]|(?= 0; --$i) { - $token = $tokens[$i]; - // variable is optional when it is not important and has a default value - if ('variable' === $token[0] && !($token[5] ?? false) && $route->hasDefault($token[3])) { - $firstOptional = $i; - } else { - break; - } - } - } - - // compute the matching regexp - $regexp = ''; - for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { - $regexp .= self::computeRegexp($tokens, $i, $firstOptional); - } - $regexp = self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'sD'.($isHost ? 'i' : ''); - - // enable Utf8 matching if really required - if ($needsUtf8) { - $regexp .= 'u'; - for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { - if ('variable' === $tokens[$i][0]) { - $tokens[$i][4] = true; - } - } - } - - return [ - 'staticPrefix' => self::determineStaticPrefix($route, $tokens), - 'regex' => $regexp, - 'tokens' => array_reverse($tokens), - 'variables' => $variables, - ]; - } - - /** - * Determines the longest static prefix possible for a route. - */ - private static function determineStaticPrefix(Route $route, array $tokens): string - { - if ('text' !== $tokens[0][0]) { - return ($route->hasDefault($tokens[0][3]) || '/' === $tokens[0][1]) ? '' : $tokens[0][1]; - } - - $prefix = $tokens[0][1]; - - if (isset($tokens[1][1]) && '/' !== $tokens[1][1] && false === $route->hasDefault($tokens[1][3])) { - $prefix .= $tokens[1][1]; - } - - return $prefix; - } - - /** - * Returns the next static character in the Route pattern that will serve as a separator (or the empty string when none available). - */ - private static function findNextSeparator(string $pattern, bool $useUtf8): string - { - if ('' == $pattern) { - // return empty string if pattern is empty or false (false which can be returned by substr) - return ''; - } - // first remove all placeholders from the pattern so we can find the next real static character - if ('' === $pattern = preg_replace('#\{\w+\}#', '', $pattern)) { - return ''; - } - if ($useUtf8) { - preg_match('/^./u', $pattern, $pattern); - } - - return false !== strpos(static::SEPARATORS, $pattern[0]) ? $pattern[0] : ''; - } - - /** - * Computes the regexp used to match a specific token. It can be static text or a subpattern. - * - * @param array $tokens The route tokens - * @param int $index The index of the current token - * @param int $firstOptional The index of the first optional token - * - * @return string The regexp pattern for a single token - */ - private static function computeRegexp(array $tokens, int $index, int $firstOptional): string - { - $token = $tokens[$index]; - if ('text' === $token[0]) { - // Text tokens - return preg_quote($token[1], self::REGEX_DELIMITER); - } else { - // Variable tokens - if (0 === $index && 0 === $firstOptional) { - // When the only token is an optional variable token, the separator is required - return sprintf('%s(?P<%s>%s)?', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]); - } else { - $regexp = sprintf('%s(?P<%s>%s)', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]); - if ($index >= $firstOptional) { - // Enclose each optional token in a subpattern to make it optional. - // "?:" means it is non-capturing, i.e. the portion of the subject string that - // matched the optional subpattern is not passed back. - $regexp = "(?:$regexp"; - $nbTokens = \count($tokens); - if ($nbTokens - 1 == $index) { - // Close the optional subpatterns - $regexp .= str_repeat(')?', $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0)); - } - } - - return $regexp; - } - } - } - - private static function transformCapturingGroupsToNonCapturings(string $regexp): string - { - for ($i = 0; $i < \strlen($regexp); ++$i) { - if ('\\' === $regexp[$i]) { - ++$i; - continue; - } - if ('(' !== $regexp[$i] || !isset($regexp[$i + 2])) { - continue; - } - if ('*' === $regexp[++$i] || '?' === $regexp[$i]) { - ++$i; - continue; - } - $regexp = substr_replace($regexp, '?:', $i, 0); - ++$i; - } - - return $regexp; - } -} diff --git a/vendor/symfony/routing/RouteCompilerInterface.php b/vendor/symfony/routing/RouteCompilerInterface.php deleted file mode 100644 index ddfa7ca..0000000 --- a/vendor/symfony/routing/RouteCompilerInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -/** - * RouteCompilerInterface is the interface that all RouteCompiler classes must implement. - * - * @author Fabien Potencier - */ -interface RouteCompilerInterface -{ - /** - * Compiles the current route instance. - * - * @return CompiledRoute A CompiledRoute instance - * - * @throws \LogicException If the Route cannot be compiled because the - * path or host pattern is invalid - */ - public static function compile(Route $route); -} diff --git a/vendor/symfony/routing/Router.php b/vendor/symfony/routing/Router.php deleted file mode 100644 index 031749b..0000000 --- a/vendor/symfony/routing/Router.php +++ /dev/null @@ -1,390 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Psr\Log\LoggerInterface; -use Symfony\Component\Config\ConfigCacheFactory; -use Symfony\Component\Config\ConfigCacheFactoryInterface; -use Symfony\Component\Config\ConfigCacheInterface; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Routing\Generator\CompiledUrlGenerator; -use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface; -use Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper; -use Symfony\Component\Routing\Generator\Dumper\GeneratorDumperInterface; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; -use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; -use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface; -use Symfony\Component\Routing\Matcher\RequestMatcherInterface; -use Symfony\Component\Routing\Matcher\UrlMatcherInterface; - -/** - * The Router class is an example of the integration of all pieces of the - * routing system for easier use. - * - * @author Fabien Potencier - */ -class Router implements RouterInterface, RequestMatcherInterface -{ - /** - * @var UrlMatcherInterface|null - */ - protected $matcher; - - /** - * @var UrlGeneratorInterface|null - */ - protected $generator; - - /** - * @var RequestContext - */ - protected $context; - - /** - * @var LoaderInterface - */ - protected $loader; - - /** - * @var RouteCollection|null - */ - protected $collection; - - /** - * @var mixed - */ - protected $resource; - - /** - * @var array - */ - protected $options = []; - - /** - * @var LoggerInterface|null - */ - protected $logger; - - /** - * @var string|null - */ - protected $defaultLocale; - - /** - * @var ConfigCacheFactoryInterface|null - */ - private $configCacheFactory; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - private $expressionLanguageProviders = []; - - private static $cache = []; - - /** - * @param mixed $resource The main resource to load - */ - public function __construct(LoaderInterface $loader, $resource, array $options = [], RequestContext $context = null, LoggerInterface $logger = null, string $defaultLocale = null) - { - $this->loader = $loader; - $this->resource = $resource; - $this->logger = $logger; - $this->context = $context ?: new RequestContext(); - $this->setOptions($options); - $this->defaultLocale = $defaultLocale; - } - - /** - * Sets options. - * - * Available options: - * - * * cache_dir: The cache directory (or null to disable caching) - * * debug: Whether to enable debugging or not (false by default) - * * generator_class: The name of a UrlGeneratorInterface implementation - * * generator_dumper_class: The name of a GeneratorDumperInterface implementation - * * matcher_class: The name of a UrlMatcherInterface implementation - * * matcher_dumper_class: The name of a MatcherDumperInterface implementation - * * resource_type: Type hint for the main resource (optional) - * * strict_requirements: Configure strict requirement checking for generators - * implementing ConfigurableRequirementsInterface (default is true) - * - * @throws \InvalidArgumentException When unsupported option is provided - */ - public function setOptions(array $options) - { - $this->options = [ - 'cache_dir' => null, - 'debug' => false, - 'generator_class' => CompiledUrlGenerator::class, - 'generator_dumper_class' => CompiledUrlGeneratorDumper::class, - 'matcher_class' => CompiledUrlMatcher::class, - 'matcher_dumper_class' => CompiledUrlMatcherDumper::class, - 'resource_type' => null, - 'strict_requirements' => true, - ]; - - // check option names and live merge, if errors are encountered Exception will be thrown - $invalid = []; - foreach ($options as $key => $value) { - if (\array_key_exists($key, $this->options)) { - $this->options[$key] = $value; - } else { - $invalid[] = $key; - } - } - - if ($invalid) { - throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid))); - } - } - - /** - * Sets an option. - * - * @param mixed $value The value - * - * @throws \InvalidArgumentException - */ - public function setOption(string $key, $value) - { - if (!\array_key_exists($key, $this->options)) { - throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); - } - - $this->options[$key] = $value; - } - - /** - * Gets an option value. - * - * @return mixed The value - * - * @throws \InvalidArgumentException - */ - public function getOption(string $key) - { - if (!\array_key_exists($key, $this->options)) { - throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); - } - - return $this->options[$key]; - } - - /** - * {@inheritdoc} - */ - public function getRouteCollection() - { - if (null === $this->collection) { - $this->collection = $this->loader->load($this->resource, $this->options['resource_type']); - } - - return $this->collection; - } - - /** - * {@inheritdoc} - */ - public function setContext(RequestContext $context) - { - $this->context = $context; - - if (null !== $this->matcher) { - $this->getMatcher()->setContext($context); - } - if (null !== $this->generator) { - $this->getGenerator()->setContext($context); - } - } - - /** - * {@inheritdoc} - */ - public function getContext() - { - return $this->context; - } - - /** - * Sets the ConfigCache factory to use. - */ - public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory) - { - $this->configCacheFactory = $configCacheFactory; - } - - /** - * {@inheritdoc} - */ - public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) - { - return $this->getGenerator()->generate($name, $parameters, $referenceType); - } - - /** - * {@inheritdoc} - */ - public function match(string $pathinfo) - { - return $this->getMatcher()->match($pathinfo); - } - - /** - * {@inheritdoc} - */ - public function matchRequest(Request $request) - { - $matcher = $this->getMatcher(); - if (!$matcher instanceof RequestMatcherInterface) { - // fallback to the default UrlMatcherInterface - return $matcher->match($request->getPathInfo()); - } - - return $matcher->matchRequest($request); - } - - /** - * Gets the UrlMatcher or RequestMatcher instance associated with this Router. - * - * @return UrlMatcherInterface|RequestMatcherInterface - */ - public function getMatcher() - { - if (null !== $this->matcher) { - return $this->matcher; - } - - if (null === $this->options['cache_dir']) { - $routes = $this->getRouteCollection(); - $compiled = is_a($this->options['matcher_class'], CompiledUrlMatcher::class, true); - if ($compiled) { - $routes = (new CompiledUrlMatcherDumper($routes))->getCompiledRoutes(); - } - $this->matcher = new $this->options['matcher_class']($routes, $this->context); - if (method_exists($this->matcher, 'addExpressionLanguageProvider')) { - foreach ($this->expressionLanguageProviders as $provider) { - $this->matcher->addExpressionLanguageProvider($provider); - } - } - - return $this->matcher; - } - - $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/url_matching_routes.php', - function (ConfigCacheInterface $cache) { - $dumper = $this->getMatcherDumperInstance(); - if (method_exists($dumper, 'addExpressionLanguageProvider')) { - foreach ($this->expressionLanguageProviders as $provider) { - $dumper->addExpressionLanguageProvider($provider); - } - } - - $cache->write($dumper->dump(), $this->getRouteCollection()->getResources()); - } - ); - - return $this->matcher = new $this->options['matcher_class'](self::getCompiledRoutes($cache->getPath()), $this->context); - } - - /** - * Gets the UrlGenerator instance associated with this Router. - * - * @return UrlGeneratorInterface A UrlGeneratorInterface instance - */ - public function getGenerator() - { - if (null !== $this->generator) { - return $this->generator; - } - - if (null === $this->options['cache_dir']) { - $routes = $this->getRouteCollection(); - $compiled = is_a($this->options['generator_class'], CompiledUrlGenerator::class, true); - if ($compiled) { - $routes = (new CompiledUrlGeneratorDumper($routes))->getCompiledRoutes(); - } - $this->generator = new $this->options['generator_class']($routes, $this->context, $this->logger, $this->defaultLocale); - } else { - $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/url_generating_routes.php', - function (ConfigCacheInterface $cache) { - $dumper = $this->getGeneratorDumperInstance(); - - $cache->write($dumper->dump(), $this->getRouteCollection()->getResources()); - } - ); - - $this->generator = new $this->options['generator_class'](self::getCompiledRoutes($cache->getPath()), $this->context, $this->logger, $this->defaultLocale); - } - - if ($this->generator instanceof ConfigurableRequirementsInterface) { - $this->generator->setStrictRequirements($this->options['strict_requirements']); - } - - return $this->generator; - } - - public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) - { - $this->expressionLanguageProviders[] = $provider; - } - - /** - * @return GeneratorDumperInterface - */ - protected function getGeneratorDumperInstance() - { - return new $this->options['generator_dumper_class']($this->getRouteCollection()); - } - - /** - * @return MatcherDumperInterface - */ - protected function getMatcherDumperInstance() - { - return new $this->options['matcher_dumper_class']($this->getRouteCollection()); - } - - /** - * Provides the ConfigCache factory implementation, falling back to a - * default implementation if necessary. - */ - private function getConfigCacheFactory(): ConfigCacheFactoryInterface - { - if (null === $this->configCacheFactory) { - $this->configCacheFactory = new ConfigCacheFactory($this->options['debug']); - } - - return $this->configCacheFactory; - } - - private static function getCompiledRoutes(string $path): array - { - if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(ini_get('opcache.enable_cli'), FILTER_VALIDATE_BOOLEAN))) { - self::$cache = null; - } - - if (null === self::$cache) { - return require $path; - } - - if (isset(self::$cache[$path])) { - return self::$cache[$path]; - } - - return self::$cache[$path] = require $path; - } -} diff --git a/vendor/symfony/routing/RouterInterface.php b/vendor/symfony/routing/RouterInterface.php deleted file mode 100644 index 8a3e33d..0000000 --- a/vendor/symfony/routing/RouterInterface.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing; - -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Routing\Matcher\UrlMatcherInterface; - -/** - * RouterInterface is the interface that all Router classes must implement. - * - * This interface is the concatenation of UrlMatcherInterface and UrlGeneratorInterface. - * - * @author Fabien Potencier - */ -interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface -{ - /** - * Gets the RouteCollection instance associated with this Router. - * - * WARNING: This method should never be used at runtime as it is SLOW. - * You might use it in a cache warmer though. - * - * @return RouteCollection A RouteCollection instance - */ - public function getRouteCollection(); -} diff --git a/vendor/symfony/routing/composer.json b/vendor/symfony/routing/composer.json deleted file mode 100644 index 1e039cb..0000000 --- a/vendor/symfony/routing/composer.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "symfony/routing", - "type": "library", - "description": "Symfony Routing Component", - "keywords": ["routing", "router", "URL", "URI"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5" - }, - "require-dev": { - "symfony/config": "^5.0", - "symfony/http-foundation": "^4.4|^5.0", - "symfony/yaml": "^4.4|^5.0", - "symfony/expression-language": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", - "doctrine/annotations": "~1.2", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/config": "<5.0", - "symfony/dependency-injection": "<4.4", - "symfony/yaml": "<4.4" - }, - "suggest": { - "symfony/http-foundation": "For using a Symfony Request object", - "symfony/config": "For using the all-in-one router or any loader", - "symfony/yaml": "For using the YAML loader", - "symfony/expression-language": "For using expression matching", - "doctrine/annotations": "For using the annotation loader" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\Routing\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/service-contracts/.gitignore b/vendor/symfony/service-contracts/.gitignore deleted file mode 100644 index c49a5d8..0000000 --- a/vendor/symfony/service-contracts/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/vendor/symfony/service-contracts/LICENSE b/vendor/symfony/service-contracts/LICENSE deleted file mode 100644 index 3f853aa..0000000 --- a/vendor/symfony/service-contracts/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2018-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/service-contracts/README.md b/vendor/symfony/service-contracts/README.md deleted file mode 100644 index d033a43..0000000 --- a/vendor/symfony/service-contracts/README.md +++ /dev/null @@ -1,9 +0,0 @@ -Symfony Service Contracts -========================= - -A set of abstractions extracted out of the Symfony components. - -Can be used to build on semantics that the Symfony components proved useful - and -that already have battle tested implementations. - -See https://github.com/symfony/contracts/blob/master/README.md for more information. diff --git a/vendor/symfony/service-contracts/ResetInterface.php b/vendor/symfony/service-contracts/ResetInterface.php deleted file mode 100644 index 1af1075..0000000 --- a/vendor/symfony/service-contracts/ResetInterface.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service; - -/** - * Provides a way to reset an object to its initial state. - * - * When calling the "reset()" method on an object, it should be put back to its - * initial state. This usually means clearing any internal buffers and forwarding - * the call to internal dependencies. All properties of the object should be put - * back to the same state it had when it was first ready to use. - * - * This method could be called, for example, to recycle objects that are used as - * services, so that they can be used to handle several requests in the same - * process loop (note that we advise making your services stateless instead of - * implementing this interface when possible.) - */ -interface ResetInterface -{ - public function reset(); -} diff --git a/vendor/symfony/service-contracts/ServiceLocatorTrait.php b/vendor/symfony/service-contracts/ServiceLocatorTrait.php deleted file mode 100644 index 4ec6eb4..0000000 --- a/vendor/symfony/service-contracts/ServiceLocatorTrait.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service; - -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\NotFoundExceptionInterface; - -/** - * A trait to help implement ServiceProviderInterface. - * - * @author Robin Chalas - * @author Nicolas Grekas - */ -trait ServiceLocatorTrait -{ - private $factories; - private $loading = []; - private $providedTypes; - - /** - * @param callable[] $factories - */ - public function __construct(array $factories) - { - $this->factories = $factories; - } - - /** - * {@inheritdoc} - * - * @return bool - */ - public function has($id) - { - return isset($this->factories[$id]); - } - - /** - * {@inheritdoc} - */ - public function get($id) - { - if (!isset($this->factories[$id])) { - throw $this->createNotFoundException($id); - } - - if (isset($this->loading[$id])) { - $ids = array_values($this->loading); - $ids = \array_slice($this->loading, array_search($id, $ids)); - $ids[] = $id; - - throw $this->createCircularReferenceException($id, $ids); - } - - $this->loading[$id] = $id; - try { - return $this->factories[$id]($this); - } finally { - unset($this->loading[$id]); - } - } - - /** - * {@inheritdoc} - */ - public function getProvidedServices(): array - { - if (null === $this->providedTypes) { - $this->providedTypes = []; - - foreach ($this->factories as $name => $factory) { - if (!\is_callable($factory)) { - $this->providedTypes[$name] = '?'; - } else { - $type = (new \ReflectionFunction($factory))->getReturnType(); - - $this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '').$type->getName() : '?'; - } - } - } - - return $this->providedTypes; - } - - private function createNotFoundException(string $id): NotFoundExceptionInterface - { - if (!$alternatives = array_keys($this->factories)) { - $message = 'is empty...'; - } else { - $last = array_pop($alternatives); - if ($alternatives) { - $message = sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last); - } else { - $message = sprintf('only knows about the "%s" service.', $last); - } - } - - if ($this->loading) { - $message = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message); - } else { - $message = sprintf('Service "%s" not found: the current service locator %s', $id, $message); - } - - return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface { - }; - } - - private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface - { - return new class(sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface { - }; - } -} diff --git a/vendor/symfony/service-contracts/ServiceProviderInterface.php b/vendor/symfony/service-contracts/ServiceProviderInterface.php deleted file mode 100644 index c60ad0b..0000000 --- a/vendor/symfony/service-contracts/ServiceProviderInterface.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service; - -use Psr\Container\ContainerInterface; - -/** - * A ServiceProviderInterface exposes the identifiers and the types of services provided by a container. - * - * @author Nicolas Grekas - * @author Mateusz Sip - */ -interface ServiceProviderInterface extends ContainerInterface -{ - /** - * Returns an associative array of service types keyed by the identifiers provided by the current container. - * - * Examples: - * - * * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface - * * ['foo' => '?'] means the container provides service name "foo" of unspecified type - * * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null - * - * @return string[] The provided service types, keyed by service names - */ - public function getProvidedServices(): array; -} diff --git a/vendor/symfony/service-contracts/ServiceSubscriberInterface.php b/vendor/symfony/service-contracts/ServiceSubscriberInterface.php deleted file mode 100644 index 8bb320f..0000000 --- a/vendor/symfony/service-contracts/ServiceSubscriberInterface.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service; - -/** - * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method. - * - * The getSubscribedServices method returns an array of service types required by such instances, - * optionally keyed by the service names used internally. Service types that start with an interrogation - * mark "?" are optional, while the other ones are mandatory service dependencies. - * - * The injected service locators SHOULD NOT allow access to any other services not specified by the method. - * - * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally. - * This interface does not dictate any injection method for these service locators, although constructor - * injection is recommended. - * - * @author Nicolas Grekas - */ -interface ServiceSubscriberInterface -{ - /** - * Returns an array of service types required by such instances, optionally keyed by the service names used internally. - * - * For mandatory dependencies: - * - * * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name - * internally to fetch a service which must implement Psr\Log\LoggerInterface. - * * ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name - * internally to fetch an iterable of Psr\Log\LoggerInterface instances. - * * ['Psr\Log\LoggerInterface'] is a shortcut for - * * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface'] - * - * otherwise: - * - * * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency - * * ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency - * * ['?Psr\Log\LoggerInterface'] is a shortcut for - * * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface'] - * - * @return array The required service types, optionally keyed by service names - */ - public static function getSubscribedServices(); -} diff --git a/vendor/symfony/service-contracts/ServiceSubscriberTrait.php b/vendor/symfony/service-contracts/ServiceSubscriberTrait.php deleted file mode 100644 index 5d9d456..0000000 --- a/vendor/symfony/service-contracts/ServiceSubscriberTrait.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service; - -use Psr\Container\ContainerInterface; - -/** - * Implementation of ServiceSubscriberInterface that determines subscribed services from - * private method return types. Service ids are available as "ClassName::methodName". - * - * @author Kevin Bond - */ -trait ServiceSubscriberTrait -{ - /** @var ContainerInterface */ - protected $container; - - public static function getSubscribedServices(): array - { - static $services; - - if (null !== $services) { - return $services; - } - - $services = \is_callable(['parent', __FUNCTION__]) ? parent::getSubscribedServices() : []; - - foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { - if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { - continue; - } - - if (self::class === $method->getDeclaringClass()->name && ($returnType = $method->getReturnType()) && !$returnType->isBuiltin()) { - $services[self::class.'::'.$method->name] = '?'.$returnType->getName(); - } - } - - return $services; - } - - /** - * @required - */ - public function setContainer(ContainerInterface $container) - { - $this->container = $container; - - if (\is_callable(['parent', __FUNCTION__])) { - return parent::setContainer($container); - } - - return null; - } -} diff --git a/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php b/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php deleted file mode 100644 index 5ed9149..0000000 --- a/vendor/symfony/service-contracts/Test/ServiceLocatorTest.php +++ /dev/null @@ -1,92 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Contracts\Service\Test; - -use PHPUnit\Framework\TestCase; -use Psr\Container\ContainerInterface; -use Symfony\Contracts\Service\ServiceLocatorTrait; - -abstract class ServiceLocatorTest extends TestCase -{ - protected function getServiceLocator(array $factories) - { - return new class($factories) implements ContainerInterface { - use ServiceLocatorTrait; - }; - } - - public function testHas() - { - $locator = $this->getServiceLocator([ - 'foo' => function () { return 'bar'; }, - 'bar' => function () { return 'baz'; }, - function () { return 'dummy'; }, - ]); - - $this->assertTrue($locator->has('foo')); - $this->assertTrue($locator->has('bar')); - $this->assertFalse($locator->has('dummy')); - } - - public function testGet() - { - $locator = $this->getServiceLocator([ - 'foo' => function () { return 'bar'; }, - 'bar' => function () { return 'baz'; }, - ]); - - $this->assertSame('bar', $locator->get('foo')); - $this->assertSame('baz', $locator->get('bar')); - } - - public function testGetDoesNotMemoize() - { - $i = 0; - $locator = $this->getServiceLocator([ - 'foo' => function () use (&$i) { - ++$i; - - return 'bar'; - }, - ]); - - $this->assertSame('bar', $locator->get('foo')); - $this->assertSame('bar', $locator->get('foo')); - $this->assertSame(2, $i); - } - - public function testThrowsOnUndefinedInternalService() - { - if (!$this->getExpectedException()) { - $this->expectException('Psr\Container\NotFoundExceptionInterface'); - $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.'); - } - $locator = $this->getServiceLocator([ - 'foo' => function () use (&$locator) { return $locator->get('bar'); }, - ]); - - $locator->get('foo'); - } - - public function testThrowsOnCircularReference() - { - $this->expectException('Psr\Container\ContainerExceptionInterface'); - $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); - $locator = $this->getServiceLocator([ - 'foo' => function () use (&$locator) { return $locator->get('bar'); }, - 'bar' => function () use (&$locator) { return $locator->get('baz'); }, - 'baz' => function () use (&$locator) { return $locator->get('bar'); }, - ]); - - $locator->get('foo'); - } -} diff --git a/vendor/symfony/service-contracts/composer.json b/vendor/symfony/service-contracts/composer.json deleted file mode 100644 index cbd491b..0000000 --- a/vendor/symfony/service-contracts/composer.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "symfony/service-contracts", - "type": "library", - "description": "Generic abstractions related to writing services", - "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "psr/container": "^1.0" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "autoload": { - "psr-4": { "Symfony\\Contracts\\Service\\": "" } - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - } -} diff --git a/vendor/symfony/var-dumper/.gitattributes b/vendor/symfony/var-dumper/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/var-dumper/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/var-dumper/CHANGELOG.md b/vendor/symfony/var-dumper/CHANGELOG.md deleted file mode 100644 index 94b1c17..0000000 --- a/vendor/symfony/var-dumper/CHANGELOG.md +++ /dev/null @@ -1,53 +0,0 @@ -CHANGELOG -========= - -4.4.0 ------ - - * added `VarDumperTestTrait::setUpVarDumper()` and `VarDumperTestTrait::tearDownVarDumper()` - to configure casters & flags to use in tests - * added `ImagineCaster` and infrastructure to dump images - * added the stamps of a message after it is dispatched in `TraceableMessageBus` and `MessengerDataCollector` collected data - * added `UuidCaster` - * made all casters final - * added support for the `NO_COLOR` env var (https://no-color.org/) - -4.3.0 ------ - - * added `DsCaster` to support dumping the contents of data structures from the Ds extension - -4.2.0 ------ - - * support selecting the format to use by setting the environment variable `VAR_DUMPER_FORMAT` to `html` or `cli` - -4.1.0 ------ - - * added a `ServerDumper` to send serialized Data clones to a server - * added a `ServerDumpCommand` and `DumpServer` to run a server collecting - and displaying dumps on a single place with multiple formats support - * added `CliDescriptor` and `HtmlDescriptor` descriptors for `server:dump` CLI and HTML formats support - -4.0.0 ------ - - * support for passing `\ReflectionClass` instances to the `Caster::castObject()` - method has been dropped, pass class names as strings instead - * the `Data::getRawData()` method has been removed - * the `VarDumperTestTrait::assertDumpEquals()` method expects a 3rd `$filter = 0` - argument and moves `$message = ''` argument at 4th position. - * the `VarDumperTestTrait::assertDumpMatchesFormat()` method expects a 3rd `$filter = 0` - argument and moves `$message = ''` argument at 4th position. - -3.4.0 ------ - - * added `AbstractCloner::setMinDepth()` function to ensure minimum tree depth - * deprecated `MongoCaster` - -2.7.0 ------ - - * deprecated `Cloner\Data::getLimitedClone()`. Use `withMaxDepth`, `withMaxItemsPerDepth` or `withRefHandles` instead. diff --git a/vendor/symfony/var-dumper/Caster/AmqpCaster.php b/vendor/symfony/var-dumper/Caster/AmqpCaster.php deleted file mode 100644 index 883d02b..0000000 --- a/vendor/symfony/var-dumper/Caster/AmqpCaster.php +++ /dev/null @@ -1,212 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts Amqp related classes to array representation. - * - * @author Grégoire Pineau - * - * @final - */ -class AmqpCaster -{ - private static $flags = [ - AMQP_DURABLE => 'AMQP_DURABLE', - AMQP_PASSIVE => 'AMQP_PASSIVE', - AMQP_EXCLUSIVE => 'AMQP_EXCLUSIVE', - AMQP_AUTODELETE => 'AMQP_AUTODELETE', - AMQP_INTERNAL => 'AMQP_INTERNAL', - AMQP_NOLOCAL => 'AMQP_NOLOCAL', - AMQP_AUTOACK => 'AMQP_AUTOACK', - AMQP_IFEMPTY => 'AMQP_IFEMPTY', - AMQP_IFUNUSED => 'AMQP_IFUNUSED', - AMQP_MANDATORY => 'AMQP_MANDATORY', - AMQP_IMMEDIATE => 'AMQP_IMMEDIATE', - AMQP_MULTIPLE => 'AMQP_MULTIPLE', - AMQP_NOWAIT => 'AMQP_NOWAIT', - AMQP_REQUEUE => 'AMQP_REQUEUE', - ]; - - private static $exchangeTypes = [ - AMQP_EX_TYPE_DIRECT => 'AMQP_EX_TYPE_DIRECT', - AMQP_EX_TYPE_FANOUT => 'AMQP_EX_TYPE_FANOUT', - AMQP_EX_TYPE_TOPIC => 'AMQP_EX_TYPE_TOPIC', - AMQP_EX_TYPE_HEADERS => 'AMQP_EX_TYPE_HEADERS', - ]; - - public static function castConnection(\AMQPConnection $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'is_connected' => $c->isConnected(), - ]; - - // Recent version of the extension already expose private properties - if (isset($a["\x00AMQPConnection\x00login"])) { - return $a; - } - - // BC layer in the amqp lib - if (method_exists($c, 'getReadTimeout')) { - $timeout = $c->getReadTimeout(); - } else { - $timeout = $c->getTimeout(); - } - - $a += [ - $prefix.'is_connected' => $c->isConnected(), - $prefix.'login' => $c->getLogin(), - $prefix.'password' => $c->getPassword(), - $prefix.'host' => $c->getHost(), - $prefix.'vhost' => $c->getVhost(), - $prefix.'port' => $c->getPort(), - $prefix.'read_timeout' => $timeout, - ]; - - return $a; - } - - public static function castChannel(\AMQPChannel $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'is_connected' => $c->isConnected(), - $prefix.'channel_id' => $c->getChannelId(), - ]; - - // Recent version of the extension already expose private properties - if (isset($a["\x00AMQPChannel\x00connection"])) { - return $a; - } - - $a += [ - $prefix.'connection' => $c->getConnection(), - $prefix.'prefetch_size' => $c->getPrefetchSize(), - $prefix.'prefetch_count' => $c->getPrefetchCount(), - ]; - - return $a; - } - - public static function castQueue(\AMQPQueue $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'flags' => self::extractFlags($c->getFlags()), - ]; - - // Recent version of the extension already expose private properties - if (isset($a["\x00AMQPQueue\x00name"])) { - return $a; - } - - $a += [ - $prefix.'connection' => $c->getConnection(), - $prefix.'channel' => $c->getChannel(), - $prefix.'name' => $c->getName(), - $prefix.'arguments' => $c->getArguments(), - ]; - - return $a; - } - - public static function castExchange(\AMQPExchange $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'flags' => self::extractFlags($c->getFlags()), - ]; - - $type = isset(self::$exchangeTypes[$c->getType()]) ? new ConstStub(self::$exchangeTypes[$c->getType()], $c->getType()) : $c->getType(); - - // Recent version of the extension already expose private properties - if (isset($a["\x00AMQPExchange\x00name"])) { - $a["\x00AMQPExchange\x00type"] = $type; - - return $a; - } - - $a += [ - $prefix.'connection' => $c->getConnection(), - $prefix.'channel' => $c->getChannel(), - $prefix.'name' => $c->getName(), - $prefix.'type' => $type, - $prefix.'arguments' => $c->getArguments(), - ]; - - return $a; - } - - public static function castEnvelope(\AMQPEnvelope $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $deliveryMode = new ConstStub($c->getDeliveryMode().(2 === $c->getDeliveryMode() ? ' (persistent)' : ' (non-persistent)'), $c->getDeliveryMode()); - - // Recent version of the extension already expose private properties - if (isset($a["\x00AMQPEnvelope\x00body"])) { - $a["\0AMQPEnvelope\0delivery_mode"] = $deliveryMode; - - return $a; - } - - if (!($filter & Caster::EXCLUDE_VERBOSE)) { - $a += [$prefix.'body' => $c->getBody()]; - } - - $a += [ - $prefix.'delivery_tag' => $c->getDeliveryTag(), - $prefix.'is_redelivery' => $c->isRedelivery(), - $prefix.'exchange_name' => $c->getExchangeName(), - $prefix.'routing_key' => $c->getRoutingKey(), - $prefix.'content_type' => $c->getContentType(), - $prefix.'content_encoding' => $c->getContentEncoding(), - $prefix.'headers' => $c->getHeaders(), - $prefix.'delivery_mode' => $deliveryMode, - $prefix.'priority' => $c->getPriority(), - $prefix.'correlation_id' => $c->getCorrelationId(), - $prefix.'reply_to' => $c->getReplyTo(), - $prefix.'expiration' => $c->getExpiration(), - $prefix.'message_id' => $c->getMessageId(), - $prefix.'timestamp' => $c->getTimeStamp(), - $prefix.'type' => $c->getType(), - $prefix.'user_id' => $c->getUserId(), - $prefix.'app_id' => $c->getAppId(), - ]; - - return $a; - } - - private static function extractFlags(int $flags): ConstStub - { - $flagsArray = []; - - foreach (self::$flags as $value => $name) { - if ($flags & $value) { - $flagsArray[] = $name; - } - } - - if (!$flagsArray) { - $flagsArray = ['AMQP_NOPARAM']; - } - - return new ConstStub(implode('|', $flagsArray), $flags); - } -} diff --git a/vendor/symfony/var-dumper/Caster/ArgsStub.php b/vendor/symfony/var-dumper/Caster/ArgsStub.php deleted file mode 100644 index 591c7e2..0000000 --- a/vendor/symfony/var-dumper/Caster/ArgsStub.php +++ /dev/null @@ -1,80 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Represents a list of function arguments. - * - * @author Nicolas Grekas - */ -class ArgsStub extends EnumStub -{ - private static $parameters = []; - - public function __construct(array $args, string $function, ?string $class) - { - list($variadic, $params) = self::getParameters($function, $class); - - $values = []; - foreach ($args as $k => $v) { - $values[$k] = !is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v; - } - if (null === $params) { - parent::__construct($values, false); - - return; - } - if (\count($values) < \count($params)) { - $params = \array_slice($params, 0, \count($values)); - } elseif (\count($values) > \count($params)) { - $values[] = new EnumStub(array_splice($values, \count($params)), false); - $params[] = $variadic; - } - if (['...'] === $params) { - $this->dumpKeys = false; - $this->value = $values[0]->value; - } else { - $this->value = array_combine($params, $values); - } - } - - private static function getParameters(string $function, ?string $class): array - { - if (isset(self::$parameters[$k = $class.'::'.$function])) { - return self::$parameters[$k]; - } - - try { - $r = null !== $class ? new \ReflectionMethod($class, $function) : new \ReflectionFunction($function); - } catch (\ReflectionException $e) { - return [null, null]; - } - - $variadic = '...'; - $params = []; - foreach ($r->getParameters() as $v) { - $k = '$'.$v->name; - if ($v->isPassedByReference()) { - $k = '&'.$k; - } - if ($v->isVariadic()) { - $variadic .= $k; - } else { - $params[] = $k; - } - } - - return self::$parameters[$k] = [$variadic, $params]; - } -} diff --git a/vendor/symfony/var-dumper/Caster/Caster.php b/vendor/symfony/var-dumper/Caster/Caster.php deleted file mode 100644 index 5f3550f..0000000 --- a/vendor/symfony/var-dumper/Caster/Caster.php +++ /dev/null @@ -1,170 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Helper for filtering out properties in casters. - * - * @author Nicolas Grekas - * - * @final - */ -class Caster -{ - const EXCLUDE_VERBOSE = 1; - const EXCLUDE_VIRTUAL = 2; - const EXCLUDE_DYNAMIC = 4; - const EXCLUDE_PUBLIC = 8; - const EXCLUDE_PROTECTED = 16; - const EXCLUDE_PRIVATE = 32; - const EXCLUDE_NULL = 64; - const EXCLUDE_EMPTY = 128; - const EXCLUDE_NOT_IMPORTANT = 256; - const EXCLUDE_STRICT = 512; - - const PREFIX_VIRTUAL = "\0~\0"; - const PREFIX_DYNAMIC = "\0+\0"; - const PREFIX_PROTECTED = "\0*\0"; - - /** - * Casts objects to arrays and adds the dynamic property prefix. - * - * @param bool $hasDebugInfo Whether the __debugInfo method exists on $obj or not - * - * @return array The array-cast of the object, with prefixed dynamic properties - */ - public static function castObject(object $obj, string $class, bool $hasDebugInfo = false): array - { - if ($hasDebugInfo) { - try { - $debugInfo = $obj->__debugInfo(); - } catch (\Exception $e) { - // ignore failing __debugInfo() - $hasDebugInfo = false; - } - } - - $a = $obj instanceof \Closure ? [] : (array) $obj; - - if ($obj instanceof \__PHP_Incomplete_Class) { - return $a; - } - - if ($a) { - static $publicProperties = []; - - $i = 0; - $prefixedKeys = []; - foreach ($a as $k => $v) { - if ("\0" !== ($k[0] ?? '')) { - if (!isset($publicProperties[$class])) { - foreach ((new \ReflectionClass($class))->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) { - $publicProperties[$class][$prop->name] = true; - } - } - if (!isset($publicProperties[$class][$k])) { - $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k; - } - } elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) { - $prefixedKeys[$i] = "\0".get_parent_class($class).'@anonymous'.strrchr($k, "\0"); - } - ++$i; - } - if ($prefixedKeys) { - $keys = array_keys($a); - foreach ($prefixedKeys as $i => $k) { - $keys[$i] = $k; - } - $a = array_combine($keys, $a); - } - } - - if ($hasDebugInfo && \is_array($debugInfo)) { - foreach ($debugInfo as $k => $v) { - if (!isset($k[0]) || "\0" !== $k[0]) { - $k = self::PREFIX_VIRTUAL.$k; - } - - unset($a[$k]); - $a[$k] = $v; - } - } - - return $a; - } - - /** - * Filters out the specified properties. - * - * By default, a single match in the $filter bit field filters properties out, following an "or" logic. - * When EXCLUDE_STRICT is set, an "and" logic is applied: all bits must match for a property to be removed. - * - * @param array $a The array containing the properties to filter - * @param int $filter A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out - * @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set - * @param int &$count Set to the number of removed properties - * - * @return array The filtered array - */ - public static function filter(array $a, int $filter, array $listedProperties = [], ?int &$count = 0): array - { - $count = 0; - - foreach ($a as $k => $v) { - $type = self::EXCLUDE_STRICT & $filter; - - if (null === $v) { - $type |= self::EXCLUDE_NULL & $filter; - $type |= self::EXCLUDE_EMPTY & $filter; - } elseif (false === $v || '' === $v || '0' === $v || 0 === $v || 0.0 === $v || [] === $v) { - $type |= self::EXCLUDE_EMPTY & $filter; - } - if ((self::EXCLUDE_NOT_IMPORTANT & $filter) && !\in_array($k, $listedProperties, true)) { - $type |= self::EXCLUDE_NOT_IMPORTANT; - } - if ((self::EXCLUDE_VERBOSE & $filter) && \in_array($k, $listedProperties, true)) { - $type |= self::EXCLUDE_VERBOSE; - } - - if (!isset($k[1]) || "\0" !== $k[0]) { - $type |= self::EXCLUDE_PUBLIC & $filter; - } elseif ('~' === $k[1]) { - $type |= self::EXCLUDE_VIRTUAL & $filter; - } elseif ('+' === $k[1]) { - $type |= self::EXCLUDE_DYNAMIC & $filter; - } elseif ('*' === $k[1]) { - $type |= self::EXCLUDE_PROTECTED & $filter; - } else { - $type |= self::EXCLUDE_PRIVATE & $filter; - } - - if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) { - unset($a[$k]); - ++$count; - } - } - - return $a; - } - - public static function castPhpIncompleteClass(\__PHP_Incomplete_Class $c, array $a, Stub $stub, bool $isNested): array - { - if (isset($a['__PHP_Incomplete_Class_Name'])) { - $stub->class .= '('.$a['__PHP_Incomplete_Class_Name'].')'; - unset($a['__PHP_Incomplete_Class_Name']); - } - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/ClassStub.php b/vendor/symfony/var-dumper/Caster/ClassStub.php deleted file mode 100644 index 758fe57..0000000 --- a/vendor/symfony/var-dumper/Caster/ClassStub.php +++ /dev/null @@ -1,106 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Represents a PHP class identifier. - * - * @author Nicolas Grekas - */ -class ClassStub extends ConstStub -{ - /** - * @param string $identifier A PHP identifier, e.g. a class, method, interface, etc. name - * @param callable $callable The callable targeted by the identifier when it is ambiguous or not a real PHP identifier - */ - public function __construct(string $identifier, $callable = null) - { - $this->value = $identifier; - - try { - if (null !== $callable) { - if ($callable instanceof \Closure) { - $r = new \ReflectionFunction($callable); - } elseif (\is_object($callable)) { - $r = [$callable, '__invoke']; - } elseif (\is_array($callable)) { - $r = $callable; - } elseif (false !== $i = strpos($callable, '::')) { - $r = [substr($callable, 0, $i), substr($callable, 2 + $i)]; - } else { - $r = new \ReflectionFunction($callable); - } - } elseif (0 < $i = strpos($identifier, '::') ?: strpos($identifier, '->')) { - $r = [substr($identifier, 0, $i), substr($identifier, 2 + $i)]; - } else { - $r = new \ReflectionClass($identifier); - } - - if (\is_array($r)) { - try { - $r = new \ReflectionMethod($r[0], $r[1]); - } catch (\ReflectionException $e) { - $r = new \ReflectionClass($r[0]); - } - } - - if (false !== strpos($identifier, "class@anonymous\0")) { - $this->value = $identifier = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:)[0-9a-fA-F]++/', function ($m) { - return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0]; - }, $identifier); - } - - if (null !== $callable && $r instanceof \ReflectionFunctionAbstract) { - $s = ReflectionCaster::castFunctionAbstract($r, [], new Stub(), true, Caster::EXCLUDE_VERBOSE); - $s = ReflectionCaster::getSignature($s); - - if ('()' === substr($identifier, -2)) { - $this->value = substr_replace($identifier, $s, -2); - } else { - $this->value .= $s; - } - } - } catch (\ReflectionException $e) { - return; - } finally { - if (0 < $i = strrpos($this->value, '\\')) { - $this->attr['ellipsis'] = \strlen($this->value) - $i; - $this->attr['ellipsis-type'] = 'class'; - $this->attr['ellipsis-tail'] = 1; - } - } - - if ($f = $r->getFileName()) { - $this->attr['file'] = $f; - $this->attr['line'] = $r->getStartLine(); - } - } - - public static function wrapCallable($callable) - { - if (\is_object($callable) || !\is_callable($callable)) { - return $callable; - } - - if (!\is_array($callable)) { - $callable = new static($callable, $callable); - } elseif (\is_string($callable[0])) { - $callable[0] = new static($callable[0], $callable); - } else { - $callable[1] = new static($callable[1], $callable); - } - - return $callable; - } -} diff --git a/vendor/symfony/var-dumper/Caster/ConstStub.php b/vendor/symfony/var-dumper/Caster/ConstStub.php deleted file mode 100644 index 8b01797..0000000 --- a/vendor/symfony/var-dumper/Caster/ConstStub.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Represents a PHP constant and its value. - * - * @author Nicolas Grekas - */ -class ConstStub extends Stub -{ - public function __construct(string $name, $value = null) - { - $this->class = $name; - $this->value = 1 < \func_num_args() ? $value : $name; - } - - /** - * @return string - */ - public function __toString() - { - return (string) $this->value; - } -} diff --git a/vendor/symfony/var-dumper/Caster/CutArrayStub.php b/vendor/symfony/var-dumper/Caster/CutArrayStub.php deleted file mode 100644 index 0e4fb36..0000000 --- a/vendor/symfony/var-dumper/Caster/CutArrayStub.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -/** - * Represents a cut array. - * - * @author Nicolas Grekas - */ -class CutArrayStub extends CutStub -{ - public $preservedSubset; - - public function __construct(array $value, array $preservedKeys) - { - parent::__construct($value); - - $this->preservedSubset = array_intersect_key($value, array_flip($preservedKeys)); - $this->cut -= \count($this->preservedSubset); - } -} diff --git a/vendor/symfony/var-dumper/Caster/CutStub.php b/vendor/symfony/var-dumper/Caster/CutStub.php deleted file mode 100644 index 464c6db..0000000 --- a/vendor/symfony/var-dumper/Caster/CutStub.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Represents the main properties of a PHP variable, pre-casted by a caster. - * - * @author Nicolas Grekas - */ -class CutStub extends Stub -{ - public function __construct($value) - { - $this->value = $value; - - switch (\gettype($value)) { - case 'object': - $this->type = self::TYPE_OBJECT; - $this->class = \get_class($value); - - if ($value instanceof \Closure) { - ReflectionCaster::castClosure($value, [], $this, true, Caster::EXCLUDE_VERBOSE); - } - - $this->cut = -1; - break; - - case 'array': - $this->type = self::TYPE_ARRAY; - $this->class = self::ARRAY_ASSOC; - $this->cut = $this->value = \count($value); - break; - - case 'resource': - case 'unknown type': - case 'resource (closed)': - $this->type = self::TYPE_RESOURCE; - $this->handle = (int) $value; - if ('Unknown' === $this->class = @get_resource_type($value)) { - $this->class = 'Closed'; - } - $this->cut = -1; - break; - - case 'string': - $this->type = self::TYPE_STRING; - $this->class = preg_match('//u', $value) ? self::STRING_UTF8 : self::STRING_BINARY; - $this->cut = self::STRING_BINARY === $this->class ? \strlen($value) : mb_strlen($value, 'UTF-8'); - $this->value = ''; - break; - } - } -} diff --git a/vendor/symfony/var-dumper/Caster/DOMCaster.php b/vendor/symfony/var-dumper/Caster/DOMCaster.php deleted file mode 100644 index 98359ff..0000000 --- a/vendor/symfony/var-dumper/Caster/DOMCaster.php +++ /dev/null @@ -1,304 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts DOM related classes to array representation. - * - * @author Nicolas Grekas - * - * @final - */ -class DOMCaster -{ - private static $errorCodes = [ - DOM_PHP_ERR => 'DOM_PHP_ERR', - DOM_INDEX_SIZE_ERR => 'DOM_INDEX_SIZE_ERR', - DOMSTRING_SIZE_ERR => 'DOMSTRING_SIZE_ERR', - DOM_HIERARCHY_REQUEST_ERR => 'DOM_HIERARCHY_REQUEST_ERR', - DOM_WRONG_DOCUMENT_ERR => 'DOM_WRONG_DOCUMENT_ERR', - DOM_INVALID_CHARACTER_ERR => 'DOM_INVALID_CHARACTER_ERR', - DOM_NO_DATA_ALLOWED_ERR => 'DOM_NO_DATA_ALLOWED_ERR', - DOM_NO_MODIFICATION_ALLOWED_ERR => 'DOM_NO_MODIFICATION_ALLOWED_ERR', - DOM_NOT_FOUND_ERR => 'DOM_NOT_FOUND_ERR', - DOM_NOT_SUPPORTED_ERR => 'DOM_NOT_SUPPORTED_ERR', - DOM_INUSE_ATTRIBUTE_ERR => 'DOM_INUSE_ATTRIBUTE_ERR', - DOM_INVALID_STATE_ERR => 'DOM_INVALID_STATE_ERR', - DOM_SYNTAX_ERR => 'DOM_SYNTAX_ERR', - DOM_INVALID_MODIFICATION_ERR => 'DOM_INVALID_MODIFICATION_ERR', - DOM_NAMESPACE_ERR => 'DOM_NAMESPACE_ERR', - DOM_INVALID_ACCESS_ERR => 'DOM_INVALID_ACCESS_ERR', - DOM_VALIDATION_ERR => 'DOM_VALIDATION_ERR', - ]; - - private static $nodeTypes = [ - XML_ELEMENT_NODE => 'XML_ELEMENT_NODE', - XML_ATTRIBUTE_NODE => 'XML_ATTRIBUTE_NODE', - XML_TEXT_NODE => 'XML_TEXT_NODE', - XML_CDATA_SECTION_NODE => 'XML_CDATA_SECTION_NODE', - XML_ENTITY_REF_NODE => 'XML_ENTITY_REF_NODE', - XML_ENTITY_NODE => 'XML_ENTITY_NODE', - XML_PI_NODE => 'XML_PI_NODE', - XML_COMMENT_NODE => 'XML_COMMENT_NODE', - XML_DOCUMENT_NODE => 'XML_DOCUMENT_NODE', - XML_DOCUMENT_TYPE_NODE => 'XML_DOCUMENT_TYPE_NODE', - XML_DOCUMENT_FRAG_NODE => 'XML_DOCUMENT_FRAG_NODE', - XML_NOTATION_NODE => 'XML_NOTATION_NODE', - XML_HTML_DOCUMENT_NODE => 'XML_HTML_DOCUMENT_NODE', - XML_DTD_NODE => 'XML_DTD_NODE', - XML_ELEMENT_DECL_NODE => 'XML_ELEMENT_DECL_NODE', - XML_ATTRIBUTE_DECL_NODE => 'XML_ATTRIBUTE_DECL_NODE', - XML_ENTITY_DECL_NODE => 'XML_ENTITY_DECL_NODE', - XML_NAMESPACE_DECL_NODE => 'XML_NAMESPACE_DECL_NODE', - ]; - - public static function castException(\DOMException $e, array $a, Stub $stub, bool $isNested) - { - $k = Caster::PREFIX_PROTECTED.'code'; - if (isset($a[$k], self::$errorCodes[$a[$k]])) { - $a[$k] = new ConstStub(self::$errorCodes[$a[$k]], $a[$k]); - } - - return $a; - } - - public static function castLength($dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'length' => $dom->length, - ]; - - return $a; - } - - public static function castImplementation($dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - Caster::PREFIX_VIRTUAL.'Core' => '1.0', - Caster::PREFIX_VIRTUAL.'XML' => '2.0', - ]; - - return $a; - } - - public static function castNode(\DOMNode $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'nodeName' => $dom->nodeName, - 'nodeValue' => new CutStub($dom->nodeValue), - 'nodeType' => new ConstStub(self::$nodeTypes[$dom->nodeType], $dom->nodeType), - 'parentNode' => new CutStub($dom->parentNode), - 'childNodes' => $dom->childNodes, - 'firstChild' => new CutStub($dom->firstChild), - 'lastChild' => new CutStub($dom->lastChild), - 'previousSibling' => new CutStub($dom->previousSibling), - 'nextSibling' => new CutStub($dom->nextSibling), - 'attributes' => $dom->attributes, - 'ownerDocument' => new CutStub($dom->ownerDocument), - 'namespaceURI' => $dom->namespaceURI, - 'prefix' => $dom->prefix, - 'localName' => $dom->localName, - 'baseURI' => $dom->baseURI ? new LinkStub($dom->baseURI) : $dom->baseURI, - 'textContent' => new CutStub($dom->textContent), - ]; - - return $a; - } - - public static function castNameSpaceNode(\DOMNameSpaceNode $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'nodeName' => $dom->nodeName, - 'nodeValue' => new CutStub($dom->nodeValue), - 'nodeType' => new ConstStub(self::$nodeTypes[$dom->nodeType], $dom->nodeType), - 'prefix' => $dom->prefix, - 'localName' => $dom->localName, - 'namespaceURI' => $dom->namespaceURI, - 'ownerDocument' => new CutStub($dom->ownerDocument), - 'parentNode' => new CutStub($dom->parentNode), - ]; - - return $a; - } - - public static function castDocument(\DOMDocument $dom, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $a += [ - 'doctype' => $dom->doctype, - 'implementation' => $dom->implementation, - 'documentElement' => new CutStub($dom->documentElement), - 'actualEncoding' => $dom->actualEncoding, - 'encoding' => $dom->encoding, - 'xmlEncoding' => $dom->xmlEncoding, - 'standalone' => $dom->standalone, - 'xmlStandalone' => $dom->xmlStandalone, - 'version' => $dom->version, - 'xmlVersion' => $dom->xmlVersion, - 'strictErrorChecking' => $dom->strictErrorChecking, - 'documentURI' => $dom->documentURI ? new LinkStub($dom->documentURI) : $dom->documentURI, - 'config' => $dom->config, - 'formatOutput' => $dom->formatOutput, - 'validateOnParse' => $dom->validateOnParse, - 'resolveExternals' => $dom->resolveExternals, - 'preserveWhiteSpace' => $dom->preserveWhiteSpace, - 'recover' => $dom->recover, - 'substituteEntities' => $dom->substituteEntities, - ]; - - if (!($filter & Caster::EXCLUDE_VERBOSE)) { - $formatOutput = $dom->formatOutput; - $dom->formatOutput = true; - $a += [Caster::PREFIX_VIRTUAL.'xml' => $dom->saveXML()]; - $dom->formatOutput = $formatOutput; - } - - return $a; - } - - public static function castCharacterData(\DOMCharacterData $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'data' => $dom->data, - 'length' => $dom->length, - ]; - - return $a; - } - - public static function castAttr(\DOMAttr $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'name' => $dom->name, - 'specified' => $dom->specified, - 'value' => $dom->value, - 'ownerElement' => $dom->ownerElement, - 'schemaTypeInfo' => $dom->schemaTypeInfo, - ]; - - return $a; - } - - public static function castElement(\DOMElement $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'tagName' => $dom->tagName, - 'schemaTypeInfo' => $dom->schemaTypeInfo, - ]; - - return $a; - } - - public static function castText(\DOMText $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'wholeText' => $dom->wholeText, - ]; - - return $a; - } - - public static function castTypeinfo(\DOMTypeinfo $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'typeName' => $dom->typeName, - 'typeNamespace' => $dom->typeNamespace, - ]; - - return $a; - } - - public static function castDomError(\DOMDomError $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'severity' => $dom->severity, - 'message' => $dom->message, - 'type' => $dom->type, - 'relatedException' => $dom->relatedException, - 'related_data' => $dom->related_data, - 'location' => $dom->location, - ]; - - return $a; - } - - public static function castLocator(\DOMLocator $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'lineNumber' => $dom->lineNumber, - 'columnNumber' => $dom->columnNumber, - 'offset' => $dom->offset, - 'relatedNode' => $dom->relatedNode, - 'uri' => $dom->uri ? new LinkStub($dom->uri, $dom->lineNumber) : $dom->uri, - ]; - - return $a; - } - - public static function castDocumentType(\DOMDocumentType $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'name' => $dom->name, - 'entities' => $dom->entities, - 'notations' => $dom->notations, - 'publicId' => $dom->publicId, - 'systemId' => $dom->systemId, - 'internalSubset' => $dom->internalSubset, - ]; - - return $a; - } - - public static function castNotation(\DOMNotation $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'publicId' => $dom->publicId, - 'systemId' => $dom->systemId, - ]; - - return $a; - } - - public static function castEntity(\DOMEntity $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'publicId' => $dom->publicId, - 'systemId' => $dom->systemId, - 'notationName' => $dom->notationName, - 'actualEncoding' => $dom->actualEncoding, - 'encoding' => $dom->encoding, - 'version' => $dom->version, - ]; - - return $a; - } - - public static function castProcessingInstruction(\DOMProcessingInstruction $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'target' => $dom->target, - 'data' => $dom->data, - ]; - - return $a; - } - - public static function castXPath(\DOMXPath $dom, array $a, Stub $stub, bool $isNested) - { - $a += [ - 'document' => $dom->document, - ]; - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/DateCaster.php b/vendor/symfony/var-dumper/Caster/DateCaster.php deleted file mode 100644 index e36fbe3..0000000 --- a/vendor/symfony/var-dumper/Caster/DateCaster.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts DateTimeInterface related classes to array representation. - * - * @author Dany Maillard - * - * @final - */ -class DateCaster -{ - private const PERIOD_LIMIT = 3; - - public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, bool $isNested, int $filter) - { - $prefix = Caster::PREFIX_VIRTUAL; - $location = $d->getTimezone()->getLocation(); - $fromNow = (new \DateTime())->diff($d); - - $title = $d->format('l, F j, Y') - ."\n".self::formatInterval($fromNow).' from now' - .($location ? ($d->format('I') ? "\nDST On" : "\nDST Off") : '') - ; - - $a = []; - $a[$prefix.'date'] = new ConstStub(self::formatDateTime($d, $location ? ' e (P)' : ' P'), $title); - - $stub->class .= $d->format(' @U'); - - return $a; - } - - public static function castInterval(\DateInterval $interval, array $a, Stub $stub, bool $isNested, int $filter) - { - $now = new \DateTimeImmutable(); - $numberOfSeconds = $now->add($interval)->getTimestamp() - $now->getTimestamp(); - $title = number_format($numberOfSeconds, 0, '.', ' ').'s'; - - $i = [Caster::PREFIX_VIRTUAL.'interval' => new ConstStub(self::formatInterval($interval), $title)]; - - return $filter & Caster::EXCLUDE_VERBOSE ? $i : $i + $a; - } - - private static function formatInterval(\DateInterval $i): string - { - $format = '%R '; - - if (0 === $i->y && 0 === $i->m && ($i->h >= 24 || $i->i >= 60 || $i->s >= 60)) { - $i = date_diff($d = new \DateTime(), date_add(clone $d, $i)); // recalculate carry over points - $format .= 0 < $i->days ? '%ad ' : ''; - } else { - $format .= ($i->y ? '%yy ' : '').($i->m ? '%mm ' : '').($i->d ? '%dd ' : ''); - } - - $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:'.self::formatSeconds($i->s, substr($i->f, 2)) : ''; - $format = '%R ' === $format ? '0s' : $format; - - return $i->format(rtrim($format)); - } - - public static function castTimeZone(\DateTimeZone $timeZone, array $a, Stub $stub, bool $isNested, int $filter) - { - $location = $timeZone->getLocation(); - $formatted = (new \DateTime('now', $timeZone))->format($location ? 'e (P)' : 'P'); - $title = $location && \extension_loaded('intl') ? \Locale::getDisplayRegion('-'.$location['country_code']) : ''; - - $z = [Caster::PREFIX_VIRTUAL.'timezone' => new ConstStub($formatted, $title)]; - - return $filter & Caster::EXCLUDE_VERBOSE ? $z : $z + $a; - } - - public static function castPeriod(\DatePeriod $p, array $a, Stub $stub, bool $isNested, int $filter) - { - $dates = []; - foreach (clone $p as $i => $d) { - if (self::PERIOD_LIMIT === $i) { - $now = new \DateTimeImmutable(); - $dates[] = sprintf('%s more', ($end = $p->getEndDate()) - ? ceil(($end->format('U.u') - $d->format('U.u')) / ((int) $now->add($p->getDateInterval())->format('U.u') - (int) $now->format('U.u'))) - : $p->recurrences - $i - ); - break; - } - $dates[] = sprintf('%s) %s', $i + 1, self::formatDateTime($d)); - } - - $period = sprintf( - 'every %s, from %s (%s) %s', - self::formatInterval($p->getDateInterval()), - self::formatDateTime($p->getStartDate()), - $p->include_start_date ? 'included' : 'excluded', - ($end = $p->getEndDate()) ? 'to '.self::formatDateTime($end) : 'recurring '.$p->recurrences.' time/s' - ); - - $p = [Caster::PREFIX_VIRTUAL.'period' => new ConstStub($period, implode("\n", $dates))]; - - return $filter & Caster::EXCLUDE_VERBOSE ? $p : $p + $a; - } - - private static function formatDateTime(\DateTimeInterface $d, string $extra = ''): string - { - return $d->format('Y-m-d H:i:'.self::formatSeconds($d->format('s'), $d->format('u')).$extra); - } - - private static function formatSeconds(string $s, string $us): string - { - return sprintf('%02d.%s', $s, 0 === ($len = \strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us)); - } -} diff --git a/vendor/symfony/var-dumper/Caster/DoctrineCaster.php b/vendor/symfony/var-dumper/Caster/DoctrineCaster.php deleted file mode 100644 index 129b2cb..0000000 --- a/vendor/symfony/var-dumper/Caster/DoctrineCaster.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Doctrine\Common\Proxy\Proxy as CommonProxy; -use Doctrine\ORM\PersistentCollection; -use Doctrine\ORM\Proxy\Proxy as OrmProxy; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts Doctrine related classes to array representation. - * - * @author Nicolas Grekas - * - * @final - */ -class DoctrineCaster -{ - public static function castCommonProxy(CommonProxy $proxy, array $a, Stub $stub, bool $isNested) - { - foreach (['__cloner__', '__initializer__'] as $k) { - if (\array_key_exists($k, $a)) { - unset($a[$k]); - ++$stub->cut; - } - } - - return $a; - } - - public static function castOrmProxy(OrmProxy $proxy, array $a, Stub $stub, bool $isNested) - { - foreach (['_entityPersister', '_identifier'] as $k) { - if (\array_key_exists($k = "\0Doctrine\\ORM\\Proxy\\Proxy\0".$k, $a)) { - unset($a[$k]); - ++$stub->cut; - } - } - - return $a; - } - - public static function castPersistentCollection(PersistentCollection $coll, array $a, Stub $stub, bool $isNested) - { - foreach (['snapshot', 'association', 'typeClass'] as $k) { - if (\array_key_exists($k = "\0Doctrine\\ORM\\PersistentCollection\0".$k, $a)) { - $a[$k] = new CutStub($a[$k]); - } - } - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/DsCaster.php b/vendor/symfony/var-dumper/Caster/DsCaster.php deleted file mode 100644 index b34b670..0000000 --- a/vendor/symfony/var-dumper/Caster/DsCaster.php +++ /dev/null @@ -1,70 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Ds\Collection; -use Ds\Map; -use Ds\Pair; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts Ds extension classes to array representation. - * - * @author Jáchym Toušek - * - * @final - */ -class DsCaster -{ - public static function castCollection(Collection $c, array $a, Stub $stub, bool $isNested): array - { - $a[Caster::PREFIX_VIRTUAL.'count'] = $c->count(); - $a[Caster::PREFIX_VIRTUAL.'capacity'] = $c->capacity(); - - if (!$c instanceof Map) { - $a += $c->toArray(); - } - - return $a; - } - - public static function castMap(Map $c, array $a, Stub $stub, bool $isNested): array - { - foreach ($c as $k => $v) { - $a[] = new DsPairStub($k, $v); - } - - return $a; - } - - public static function castPair(Pair $c, array $a, Stub $stub, bool $isNested): array - { - foreach ($c->toArray() as $k => $v) { - $a[Caster::PREFIX_VIRTUAL.$k] = $v; - } - - return $a; - } - - public static function castPairStub(DsPairStub $c, array $a, Stub $stub, bool $isNested): array - { - if ($isNested) { - $stub->class = Pair::class; - $stub->value = null; - $stub->handle = 0; - - $a = $c->value; - } - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/DsPairStub.php b/vendor/symfony/var-dumper/Caster/DsPairStub.php deleted file mode 100644 index a1dcc15..0000000 --- a/vendor/symfony/var-dumper/Caster/DsPairStub.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @author Nicolas Grekas - */ -class DsPairStub extends Stub -{ - public function __construct($key, $value) - { - $this->value = [ - Caster::PREFIX_VIRTUAL.'key' => $key, - Caster::PREFIX_VIRTUAL.'value' => $value, - ]; - } -} diff --git a/vendor/symfony/var-dumper/Caster/EnumStub.php b/vendor/symfony/var-dumper/Caster/EnumStub.php deleted file mode 100644 index 7a4e98a..0000000 --- a/vendor/symfony/var-dumper/Caster/EnumStub.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Represents an enumeration of values. - * - * @author Nicolas Grekas - */ -class EnumStub extends Stub -{ - public $dumpKeys = true; - - public function __construct(array $values, bool $dumpKeys = true) - { - $this->value = $values; - $this->dumpKeys = $dumpKeys; - } -} diff --git a/vendor/symfony/var-dumper/Caster/ExceptionCaster.php b/vendor/symfony/var-dumper/Caster/ExceptionCaster.php deleted file mode 100644 index 214026b..0000000 --- a/vendor/symfony/var-dumper/Caster/ExceptionCaster.php +++ /dev/null @@ -1,383 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; -use Symfony\Component\VarDumper\Cloner\Stub; -use Symfony\Component\VarDumper\Exception\ThrowingCasterException; - -/** - * Casts common Exception classes to array representation. - * - * @author Nicolas Grekas - * - * @final - */ -class ExceptionCaster -{ - public static $srcContext = 1; - public static $traceArgs = true; - public static $errorTypes = [ - E_DEPRECATED => 'E_DEPRECATED', - E_USER_DEPRECATED => 'E_USER_DEPRECATED', - E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR', - E_ERROR => 'E_ERROR', - E_WARNING => 'E_WARNING', - E_PARSE => 'E_PARSE', - E_NOTICE => 'E_NOTICE', - E_CORE_ERROR => 'E_CORE_ERROR', - E_CORE_WARNING => 'E_CORE_WARNING', - E_COMPILE_ERROR => 'E_COMPILE_ERROR', - E_COMPILE_WARNING => 'E_COMPILE_WARNING', - E_USER_ERROR => 'E_USER_ERROR', - E_USER_WARNING => 'E_USER_WARNING', - E_USER_NOTICE => 'E_USER_NOTICE', - E_STRICT => 'E_STRICT', - ]; - - private static $framesCache = []; - - public static function castError(\Error $e, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - return self::filterExceptionArray($stub->class, $a, "\0Error\0", $filter); - } - - public static function castException(\Exception $e, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - return self::filterExceptionArray($stub->class, $a, "\0Exception\0", $filter); - } - - public static function castErrorException(\ErrorException $e, array $a, Stub $stub, bool $isNested) - { - if (isset($a[$s = Caster::PREFIX_PROTECTED.'severity'], self::$errorTypes[$a[$s]])) { - $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]); - } - - return $a; - } - - public static function castThrowingCasterException(ThrowingCasterException $e, array $a, Stub $stub, bool $isNested) - { - $trace = Caster::PREFIX_VIRTUAL.'trace'; - $prefix = Caster::PREFIX_PROTECTED; - $xPrefix = "\0Exception\0"; - - if (isset($a[$xPrefix.'previous'], $a[$trace]) && $a[$xPrefix.'previous'] instanceof \Exception) { - $b = (array) $a[$xPrefix.'previous']; - $class = \get_class($a[$xPrefix.'previous']); - $class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; - self::traceUnshift($b[$xPrefix.'trace'], $class, $b[$prefix.'file'], $b[$prefix.'line']); - $a[$trace] = new TraceStub($b[$xPrefix.'trace'], false, 0, -\count($a[$trace]->value)); - } - - unset($a[$xPrefix.'previous'], $a[$prefix.'code'], $a[$prefix.'file'], $a[$prefix.'line']); - - return $a; - } - - public static function castSilencedErrorContext(SilencedErrorContext $e, array $a, Stub $stub, bool $isNested) - { - $sPrefix = "\0".SilencedErrorContext::class."\0"; - - if (!isset($a[$s = $sPrefix.'severity'])) { - return $a; - } - - if (isset(self::$errorTypes[$a[$s]])) { - $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]); - } - - $trace = [[ - 'file' => $a[$sPrefix.'file'], - 'line' => $a[$sPrefix.'line'], - ]]; - - if (isset($a[$sPrefix.'trace'])) { - $trace = array_merge($trace, $a[$sPrefix.'trace']); - } - - unset($a[$sPrefix.'file'], $a[$sPrefix.'line'], $a[$sPrefix.'trace']); - $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs); - - return $a; - } - - public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, bool $isNested) - { - if (!$isNested) { - return $a; - } - $stub->class = ''; - $stub->handle = 0; - $frames = $trace->value; - $prefix = Caster::PREFIX_VIRTUAL; - - $a = []; - $j = \count($frames); - if (0 > $i = $trace->sliceOffset) { - $i = max(0, $j + $i); - } - if (!isset($trace->value[$i])) { - return []; - } - $lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : ''; - $frames[] = ['function' => '']; - $collapse = false; - - for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) { - $f = $frames[$i]; - $call = isset($f['function']) ? (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'] : '???'; - - $frame = new FrameStub( - [ - 'object' => isset($f['object']) ? $f['object'] : null, - 'class' => isset($f['class']) ? $f['class'] : null, - 'type' => isset($f['type']) ? $f['type'] : null, - 'function' => isset($f['function']) ? $f['function'] : null, - ] + $frames[$i - 1], - false, - true - ); - $f = self::castFrameStub($frame, [], $frame, true); - if (isset($f[$prefix.'src'])) { - foreach ($f[$prefix.'src']->value as $label => $frame) { - if (0 === strpos($label, "\0~collapse=0")) { - if ($collapse) { - $label = substr_replace($label, '1', 11, 1); - } else { - $collapse = true; - } - } - $label = substr_replace($label, "title=Stack level $j.&", 2, 0); - } - $f = $frames[$i - 1]; - if ($trace->keepArgs && !empty($f['args']) && $frame instanceof EnumStub) { - $frame->value['arguments'] = new ArgsStub($f['args'], isset($f['function']) ? $f['function'] : null, isset($f['class']) ? $f['class'] : null); - } - } elseif ('???' !== $lastCall) { - $label = new ClassStub($lastCall); - if (isset($label->attr['ellipsis'])) { - $label->attr['ellipsis'] += 2; - $label = substr_replace($prefix, "ellipsis-type=class&ellipsis={$label->attr['ellipsis']}&ellipsis-tail=1&title=Stack level $j.", 2, 0).$label->value.'()'; - } else { - $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$label->value.'()'; - } - } else { - $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$lastCall; - } - $a[substr_replace($label, sprintf('separator=%s&', $frame instanceof EnumStub ? ' ' : ':'), 2, 0)] = $frame; - - $lastCall = $call; - } - if (null !== $trace->sliceLength) { - $a = \array_slice($a, 0, $trace->sliceLength, true); - } - - return $a; - } - - public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, bool $isNested) - { - if (!$isNested) { - return $a; - } - $f = $frame->value; - $prefix = Caster::PREFIX_VIRTUAL; - - if (isset($f['file'], $f['line'])) { - $cacheKey = $f; - unset($cacheKey['object'], $cacheKey['args']); - $cacheKey[] = self::$srcContext; - $cacheKey = implode('-', $cacheKey); - - if (isset(self::$framesCache[$cacheKey])) { - $a[$prefix.'src'] = self::$framesCache[$cacheKey]; - } else { - if (preg_match('/\((\d+)\)(?:\([\da-f]{32}\))? : (?:eval\(\)\'d code|runtime-created function)$/', $f['file'], $match)) { - $f['file'] = substr($f['file'], 0, -\strlen($match[0])); - $f['line'] = (int) $match[1]; - } - $src = $f['line']; - $srcKey = $f['file']; - $ellipsis = new LinkStub($srcKey, 0); - $srcAttr = 'collapse='.(int) $ellipsis->inVendor; - $ellipsisTail = isset($ellipsis->attr['ellipsis-tail']) ? $ellipsis->attr['ellipsis-tail'] : 0; - $ellipsis = isset($ellipsis->attr['ellipsis']) ? $ellipsis->attr['ellipsis'] : 0; - - if (file_exists($f['file']) && 0 <= self::$srcContext) { - if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) { - $template = isset($f['object']) ? $f['object'] : unserialize(sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class'])); - - $ellipsis = 0; - $templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : ''); - $templateInfo = $template->getDebugInfo(); - if (isset($templateInfo[$f['line']])) { - if (!method_exists($template, 'getSourceContext') || !file_exists($templatePath = $template->getSourceContext()->getPath())) { - $templatePath = null; - } - if ($templateSrc) { - $src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f); - $srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']]; - } - } - } - if ($srcKey == $f['file']) { - $src = self::extractSource(file_get_contents($f['file']), $f['line'], self::$srcContext, 'php', $f['file'], $f); - $srcKey .= ':'.$f['line']; - if ($ellipsis) { - $ellipsis += 1 + \strlen($f['line']); - } - } - $srcAttr .= sprintf('&separator= &file=%s&line=%d', rawurlencode($f['file']), $f['line']); - } else { - $srcAttr .= '&separator=:'; - } - $srcAttr .= $ellipsis ? '&ellipsis-type=path&ellipsis='.$ellipsis.'&ellipsis-tail='.$ellipsisTail : ''; - self::$framesCache[$cacheKey] = $a[$prefix.'src'] = new EnumStub(["\0~$srcAttr\0$srcKey" => $src]); - } - } - - unset($a[$prefix.'args'], $a[$prefix.'line'], $a[$prefix.'file']); - if ($frame->inTraceStub) { - unset($a[$prefix.'class'], $a[$prefix.'type'], $a[$prefix.'function']); - } - foreach ($a as $k => $v) { - if (!$v) { - unset($a[$k]); - } - } - if ($frame->keepArgs && !empty($f['args'])) { - $a[$prefix.'arguments'] = new ArgsStub($f['args'], $f['function'], $f['class']); - } - - return $a; - } - - private static function filterExceptionArray(string $xClass, array $a, string $xPrefix, int $filter): array - { - if (isset($a[$xPrefix.'trace'])) { - $trace = $a[$xPrefix.'trace']; - unset($a[$xPrefix.'trace']); // Ensures the trace is always last - } else { - $trace = []; - } - - if (!($filter & Caster::EXCLUDE_VERBOSE) && $trace) { - if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { - self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']); - } - $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs); - } - if (empty($a[$xPrefix.'previous'])) { - unset($a[$xPrefix.'previous']); - } - unset($a[$xPrefix.'string'], $a[Caster::PREFIX_DYNAMIC.'xdebug_message'], $a[Caster::PREFIX_DYNAMIC.'__destructorException']); - - if (isset($a[Caster::PREFIX_PROTECTED.'message']) && false !== strpos($a[Caster::PREFIX_PROTECTED.'message'], "class@anonymous\0")) { - $a[Caster::PREFIX_PROTECTED.'message'] = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:)[0-9a-fA-F]++/', function ($m) { - return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0]; - }, $a[Caster::PREFIX_PROTECTED.'message']); - } - - if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { - $a[Caster::PREFIX_PROTECTED.'file'] = new LinkStub($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']); - } - - return $a; - } - - private static function traceUnshift(array &$trace, ?string $class, string $file, int $line): void - { - if (isset($trace[0]['file'], $trace[0]['line']) && $trace[0]['file'] === $file && $trace[0]['line'] === $line) { - return; - } - array_unshift($trace, [ - 'function' => $class ? 'new '.$class : null, - 'file' => $file, - 'line' => $line, - ]); - } - - private static function extractSource(string $srcLines, int $line, int $srcContext, string $lang, ?string $file, array $frame): EnumStub - { - $srcLines = explode("\n", $srcLines); - $src = []; - - for ($i = $line - 1 - $srcContext; $i <= $line - 1 + $srcContext; ++$i) { - $src[] = (isset($srcLines[$i]) ? $srcLines[$i] : '')."\n"; - } - - if ($frame['function'] ?? false) { - $stub = new CutStub(new \stdClass()); - $stub->class = (isset($frame['class']) ? $frame['class'].$frame['type'] : '').$frame['function']; - $stub->type = Stub::TYPE_OBJECT; - $stub->attr['cut_hash'] = true; - $stub->attr['file'] = $frame['file']; - $stub->attr['line'] = $frame['line']; - - try { - $caller = isset($frame['class']) ? new \ReflectionMethod($frame['class'], $frame['function']) : new \ReflectionFunction($frame['function']); - $stub->class .= ReflectionCaster::getSignature(ReflectionCaster::castFunctionAbstract($caller, [], $stub, true, Caster::EXCLUDE_VERBOSE)); - - if ($f = $caller->getFileName()) { - $stub->attr['file'] = $f; - $stub->attr['line'] = $caller->getStartLine(); - } - } catch (\ReflectionException $e) { - // ignore fake class/function - } - - $srcLines = ["\0~separator=\0" => $stub]; - } else { - $stub = null; - $srcLines = []; - } - - $ltrim = 0; - do { - $pad = null; - for ($i = $srcContext << 1; $i >= 0; --$i) { - if (isset($src[$i][$ltrim]) && "\r" !== ($c = $src[$i][$ltrim]) && "\n" !== $c) { - if (null === $pad) { - $pad = $c; - } - if ((' ' !== $c && "\t" !== $c) || $pad !== $c) { - break; - } - } - } - ++$ltrim; - } while (0 > $i && null !== $pad); - - --$ltrim; - - foreach ($src as $i => $c) { - if ($ltrim) { - $c = isset($c[$ltrim]) && "\r" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, " \t"); - } - $c = substr($c, 0, -1); - if ($i !== $srcContext) { - $c = new ConstStub('default', $c); - } else { - $c = new ConstStub($c, $stub ? 'in '.$stub->class : ''); - if (null !== $file) { - $c->attr['file'] = $file; - $c->attr['line'] = $line; - } - } - $c->attr['lang'] = $lang; - $srcLines[sprintf("\0~separator=› &%d\0", $i + $line - $srcContext)] = $c; - } - - return new EnumStub($srcLines); - } -} diff --git a/vendor/symfony/var-dumper/Caster/FrameStub.php b/vendor/symfony/var-dumper/Caster/FrameStub.php deleted file mode 100644 index 8786755..0000000 --- a/vendor/symfony/var-dumper/Caster/FrameStub.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -/** - * Represents a single backtrace frame as returned by debug_backtrace() or Exception->getTrace(). - * - * @author Nicolas Grekas - */ -class FrameStub extends EnumStub -{ - public $keepArgs; - public $inTraceStub; - - public function __construct(array $frame, bool $keepArgs = true, bool $inTraceStub = false) - { - $this->value = $frame; - $this->keepArgs = $keepArgs; - $this->inTraceStub = $inTraceStub; - } -} diff --git a/vendor/symfony/var-dumper/Caster/GmpCaster.php b/vendor/symfony/var-dumper/Caster/GmpCaster.php deleted file mode 100644 index b018cc7..0000000 --- a/vendor/symfony/var-dumper/Caster/GmpCaster.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts GMP objects to array representation. - * - * @author Hamza Amrouche - * @author Nicolas Grekas - * - * @final - */ -class GmpCaster -{ - public static function castGmp(\GMP $gmp, array $a, Stub $stub, bool $isNested, int $filter): array - { - $a[Caster::PREFIX_VIRTUAL.'value'] = new ConstStub(gmp_strval($gmp), gmp_strval($gmp)); - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/ImagineCaster.php b/vendor/symfony/var-dumper/Caster/ImagineCaster.php deleted file mode 100644 index d1289da..0000000 --- a/vendor/symfony/var-dumper/Caster/ImagineCaster.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Imagine\Image\ImageInterface; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @author Grégoire Pineau - */ -final class ImagineCaster -{ - public static function castImage(ImageInterface $c, array $a, Stub $stub, bool $isNested): array - { - $imgData = $c->get('png'); - if (\strlen($imgData) > 1 * 1000 * 1000) { - $a += [ - Caster::PREFIX_VIRTUAL.'image' => new ConstStub($c->getSize()), - ]; - } else { - $a += [ - Caster::PREFIX_VIRTUAL.'image' => new ImgStub($imgData, 'image/png', $c->getSize()), - ]; - } - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/ImgStub.php b/vendor/symfony/var-dumper/Caster/ImgStub.php deleted file mode 100644 index 05789fe..0000000 --- a/vendor/symfony/var-dumper/Caster/ImgStub.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -/** - * @author Grégoire Pineau - */ -class ImgStub extends ConstStub -{ - public function __construct(string $data, string $contentType, string $size) - { - $this->value = ''; - $this->attr['img-data'] = $data; - $this->attr['img-size'] = $size; - $this->attr['content-type'] = $contentType; - } -} diff --git a/vendor/symfony/var-dumper/Caster/IntlCaster.php b/vendor/symfony/var-dumper/Caster/IntlCaster.php deleted file mode 100644 index 23b9d5d..0000000 --- a/vendor/symfony/var-dumper/Caster/IntlCaster.php +++ /dev/null @@ -1,172 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @author Nicolas Grekas - * @author Jan Schädlich - * - * @final - */ -class IntlCaster -{ - public static function castMessageFormatter(\MessageFormatter $c, array $a, Stub $stub, bool $isNested) - { - $a += [ - Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), - Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), - ]; - - return self::castError($c, $a); - } - - public static function castNumberFormatter(\NumberFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $a += [ - Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), - Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), - ]; - - if ($filter & Caster::EXCLUDE_VERBOSE) { - $stub->cut += 3; - - return self::castError($c, $a); - } - - $a += [ - Caster::PREFIX_VIRTUAL.'attributes' => new EnumStub( - [ - 'PARSE_INT_ONLY' => $c->getAttribute(\NumberFormatter::PARSE_INT_ONLY), - 'GROUPING_USED' => $c->getAttribute(\NumberFormatter::GROUPING_USED), - 'DECIMAL_ALWAYS_SHOWN' => $c->getAttribute(\NumberFormatter::DECIMAL_ALWAYS_SHOWN), - 'MAX_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_INTEGER_DIGITS), - 'MIN_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_INTEGER_DIGITS), - 'INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::INTEGER_DIGITS), - 'MAX_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_FRACTION_DIGITS), - 'MIN_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_FRACTION_DIGITS), - 'FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::FRACTION_DIGITS), - 'MULTIPLIER' => $c->getAttribute(\NumberFormatter::MULTIPLIER), - 'GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::GROUPING_SIZE), - 'ROUNDING_MODE' => $c->getAttribute(\NumberFormatter::ROUNDING_MODE), - 'ROUNDING_INCREMENT' => $c->getAttribute(\NumberFormatter::ROUNDING_INCREMENT), - 'FORMAT_WIDTH' => $c->getAttribute(\NumberFormatter::FORMAT_WIDTH), - 'PADDING_POSITION' => $c->getAttribute(\NumberFormatter::PADDING_POSITION), - 'SECONDARY_GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::SECONDARY_GROUPING_SIZE), - 'SIGNIFICANT_DIGITS_USED' => $c->getAttribute(\NumberFormatter::SIGNIFICANT_DIGITS_USED), - 'MIN_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_SIGNIFICANT_DIGITS), - 'MAX_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_SIGNIFICANT_DIGITS), - 'LENIENT_PARSE' => $c->getAttribute(\NumberFormatter::LENIENT_PARSE), - ] - ), - Caster::PREFIX_VIRTUAL.'text_attributes' => new EnumStub( - [ - 'POSITIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_PREFIX), - 'POSITIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_SUFFIX), - 'NEGATIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_PREFIX), - 'NEGATIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_SUFFIX), - 'PADDING_CHARACTER' => $c->getTextAttribute(\NumberFormatter::PADDING_CHARACTER), - 'CURRENCY_CODE' => $c->getTextAttribute(\NumberFormatter::CURRENCY_CODE), - 'DEFAULT_RULESET' => $c->getTextAttribute(\NumberFormatter::DEFAULT_RULESET), - 'PUBLIC_RULESETS' => $c->getTextAttribute(\NumberFormatter::PUBLIC_RULESETS), - ] - ), - Caster::PREFIX_VIRTUAL.'symbols' => new EnumStub( - [ - 'DECIMAL_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL), - 'GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL), - 'PATTERN_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::PATTERN_SEPARATOR_SYMBOL), - 'PERCENT_SYMBOL' => $c->getSymbol(\NumberFormatter::PERCENT_SYMBOL), - 'ZERO_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::ZERO_DIGIT_SYMBOL), - 'DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::DIGIT_SYMBOL), - 'MINUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::MINUS_SIGN_SYMBOL), - 'PLUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::PLUS_SIGN_SYMBOL), - 'CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::CURRENCY_SYMBOL), - 'INTL_CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::INTL_CURRENCY_SYMBOL), - 'MONETARY_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_SEPARATOR_SYMBOL), - 'EXPONENTIAL_SYMBOL' => $c->getSymbol(\NumberFormatter::EXPONENTIAL_SYMBOL), - 'PERMILL_SYMBOL' => $c->getSymbol(\NumberFormatter::PERMILL_SYMBOL), - 'PAD_ESCAPE_SYMBOL' => $c->getSymbol(\NumberFormatter::PAD_ESCAPE_SYMBOL), - 'INFINITY_SYMBOL' => $c->getSymbol(\NumberFormatter::INFINITY_SYMBOL), - 'NAN_SYMBOL' => $c->getSymbol(\NumberFormatter::NAN_SYMBOL), - 'SIGNIFICANT_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL), - 'MONETARY_GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL), - ] - ), - ]; - - return self::castError($c, $a); - } - - public static function castIntlTimeZone(\IntlTimeZone $c, array $a, Stub $stub, bool $isNested) - { - $a += [ - Caster::PREFIX_VIRTUAL.'display_name' => $c->getDisplayName(), - Caster::PREFIX_VIRTUAL.'id' => $c->getID(), - Caster::PREFIX_VIRTUAL.'raw_offset' => $c->getRawOffset(), - ]; - - if ($c->useDaylightTime()) { - $a += [ - Caster::PREFIX_VIRTUAL.'dst_savings' => $c->getDSTSavings(), - ]; - } - - return self::castError($c, $a); - } - - public static function castIntlCalendar(\IntlCalendar $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $a += [ - Caster::PREFIX_VIRTUAL.'type' => $c->getType(), - Caster::PREFIX_VIRTUAL.'first_day_of_week' => $c->getFirstDayOfWeek(), - Caster::PREFIX_VIRTUAL.'minimal_days_in_first_week' => $c->getMinimalDaysInFirstWeek(), - Caster::PREFIX_VIRTUAL.'repeated_wall_time_option' => $c->getRepeatedWallTimeOption(), - Caster::PREFIX_VIRTUAL.'skipped_wall_time_option' => $c->getSkippedWallTimeOption(), - Caster::PREFIX_VIRTUAL.'time' => $c->getTime(), - Caster::PREFIX_VIRTUAL.'in_daylight_time' => $c->inDaylightTime(), - Caster::PREFIX_VIRTUAL.'is_lenient' => $c->isLenient(), - Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(), - ]; - - return self::castError($c, $a); - } - - public static function castIntlDateFormatter(\IntlDateFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $a += [ - Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), - Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), - Caster::PREFIX_VIRTUAL.'calendar' => $c->getCalendar(), - Caster::PREFIX_VIRTUAL.'time_zone_id' => $c->getTimeZoneId(), - Caster::PREFIX_VIRTUAL.'time_type' => $c->getTimeType(), - Caster::PREFIX_VIRTUAL.'date_type' => $c->getDateType(), - Caster::PREFIX_VIRTUAL.'calendar_object' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getCalendarObject()) : $c->getCalendarObject(), - Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(), - ]; - - return self::castError($c, $a); - } - - private static function castError(object $c, array $a): array - { - if ($errorCode = $c->getErrorCode()) { - $a += [ - Caster::PREFIX_VIRTUAL.'error_code' => $errorCode, - Caster::PREFIX_VIRTUAL.'error_message' => $c->getErrorMessage(), - ]; - } - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/LinkStub.php b/vendor/symfony/var-dumper/Caster/LinkStub.php deleted file mode 100644 index 6360716..0000000 --- a/vendor/symfony/var-dumper/Caster/LinkStub.php +++ /dev/null @@ -1,108 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -/** - * Represents a file or a URL. - * - * @author Nicolas Grekas - */ -class LinkStub extends ConstStub -{ - public $inVendor = false; - - private static $vendorRoots; - private static $composerRoots; - - public function __construct($label, int $line = 0, $href = null) - { - $this->value = $label; - - if (null === $href) { - $href = $label; - } - if (!\is_string($href)) { - return; - } - if (0 === strpos($href, 'file://')) { - if ($href === $label) { - $label = substr($label, 7); - } - $href = substr($href, 7); - } elseif (false !== strpos($href, '://')) { - $this->attr['href'] = $href; - - return; - } - if (!file_exists($href)) { - return; - } - if ($line) { - $this->attr['line'] = $line; - } - if ($label !== $this->attr['file'] = realpath($href) ?: $href) { - return; - } - if ($composerRoot = $this->getComposerRoot($href, $this->inVendor)) { - $this->attr['ellipsis'] = \strlen($href) - \strlen($composerRoot) + 1; - $this->attr['ellipsis-type'] = 'path'; - $this->attr['ellipsis-tail'] = 1 + ($this->inVendor ? 2 + \strlen(implode('', \array_slice(explode(\DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0); - } elseif (3 < \count($ellipsis = explode(\DIRECTORY_SEPARATOR, $href))) { - $this->attr['ellipsis'] = 2 + \strlen(implode('', \array_slice($ellipsis, -2))); - $this->attr['ellipsis-type'] = 'path'; - $this->attr['ellipsis-tail'] = 1; - } - } - - private function getComposerRoot(string $file, bool &$inVendor) - { - if (null === self::$vendorRoots) { - self::$vendorRoots = []; - - foreach (get_declared_classes() as $class) { - if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) { - $r = new \ReflectionClass($class); - $v = \dirname($r->getFileName(), 2); - if (file_exists($v.'/composer/installed.json')) { - self::$vendorRoots[] = $v.\DIRECTORY_SEPARATOR; - } - } - } - } - $inVendor = false; - - if (isset(self::$composerRoots[$dir = \dirname($file)])) { - return self::$composerRoots[$dir]; - } - - foreach (self::$vendorRoots as $root) { - if ($inVendor = 0 === strpos($file, $root)) { - return $root; - } - } - - $parent = $dir; - while (!@file_exists($parent.'/composer.json')) { - if (!@file_exists($parent)) { - // open_basedir restriction in effect - break; - } - if ($parent === \dirname($parent)) { - return self::$composerRoots[$dir] = false; - } - - $parent = \dirname($parent); - } - - return self::$composerRoots[$dir] = $parent.\DIRECTORY_SEPARATOR; - } -} diff --git a/vendor/symfony/var-dumper/Caster/MemcachedCaster.php b/vendor/symfony/var-dumper/Caster/MemcachedCaster.php deleted file mode 100644 index 111b060..0000000 --- a/vendor/symfony/var-dumper/Caster/MemcachedCaster.php +++ /dev/null @@ -1,81 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @author Jan Schädlich - * - * @final - */ -class MemcachedCaster -{ - private static $optionConstants; - private static $defaultOptions; - - public static function castMemcached(\Memcached $c, array $a, Stub $stub, bool $isNested) - { - $a += [ - Caster::PREFIX_VIRTUAL.'servers' => $c->getServerList(), - Caster::PREFIX_VIRTUAL.'options' => new EnumStub( - self::getNonDefaultOptions($c) - ), - ]; - - return $a; - } - - private static function getNonDefaultOptions(\Memcached $c): array - { - self::$defaultOptions = self::$defaultOptions ?? self::discoverDefaultOptions(); - self::$optionConstants = self::$optionConstants ?? self::getOptionConstants(); - - $nonDefaultOptions = []; - foreach (self::$optionConstants as $constantKey => $value) { - if (self::$defaultOptions[$constantKey] !== $option = $c->getOption($value)) { - $nonDefaultOptions[$constantKey] = $option; - } - } - - return $nonDefaultOptions; - } - - private static function discoverDefaultOptions(): array - { - $defaultMemcached = new \Memcached(); - $defaultMemcached->addServer('127.0.0.1', 11211); - - $defaultOptions = []; - self::$optionConstants = self::$optionConstants ?? self::getOptionConstants(); - - foreach (self::$optionConstants as $constantKey => $value) { - $defaultOptions[$constantKey] = $defaultMemcached->getOption($value); - } - - return $defaultOptions; - } - - private static function getOptionConstants(): array - { - $reflectedMemcached = new \ReflectionClass(\Memcached::class); - - $optionConstants = []; - foreach ($reflectedMemcached->getConstants() as $constantKey => $value) { - if (0 === strpos($constantKey, 'OPT_')) { - $optionConstants[$constantKey] = $value; - } - } - - return $optionConstants; - } -} diff --git a/vendor/symfony/var-dumper/Caster/PdoCaster.php b/vendor/symfony/var-dumper/Caster/PdoCaster.php deleted file mode 100644 index 4ba302b..0000000 --- a/vendor/symfony/var-dumper/Caster/PdoCaster.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts PDO related classes to array representation. - * - * @author Nicolas Grekas - * - * @final - */ -class PdoCaster -{ - private static $pdoAttributes = [ - 'CASE' => [ - \PDO::CASE_LOWER => 'LOWER', - \PDO::CASE_NATURAL => 'NATURAL', - \PDO::CASE_UPPER => 'UPPER', - ], - 'ERRMODE' => [ - \PDO::ERRMODE_SILENT => 'SILENT', - \PDO::ERRMODE_WARNING => 'WARNING', - \PDO::ERRMODE_EXCEPTION => 'EXCEPTION', - ], - 'TIMEOUT', - 'PREFETCH', - 'AUTOCOMMIT', - 'PERSISTENT', - 'DRIVER_NAME', - 'SERVER_INFO', - 'ORACLE_NULLS' => [ - \PDO::NULL_NATURAL => 'NATURAL', - \PDO::NULL_EMPTY_STRING => 'EMPTY_STRING', - \PDO::NULL_TO_STRING => 'TO_STRING', - ], - 'CLIENT_VERSION', - 'SERVER_VERSION', - 'STATEMENT_CLASS', - 'EMULATE_PREPARES', - 'CONNECTION_STATUS', - 'STRINGIFY_FETCHES', - 'DEFAULT_FETCH_MODE' => [ - \PDO::FETCH_ASSOC => 'ASSOC', - \PDO::FETCH_BOTH => 'BOTH', - \PDO::FETCH_LAZY => 'LAZY', - \PDO::FETCH_NUM => 'NUM', - \PDO::FETCH_OBJ => 'OBJ', - ], - ]; - - public static function castPdo(\PDO $c, array $a, Stub $stub, bool $isNested) - { - $attr = []; - $errmode = $c->getAttribute(\PDO::ATTR_ERRMODE); - $c->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - - foreach (self::$pdoAttributes as $k => $v) { - if (!isset($k[0])) { - $k = $v; - $v = []; - } - - try { - $attr[$k] = 'ERRMODE' === $k ? $errmode : $c->getAttribute(\constant('PDO::ATTR_'.$k)); - if ($v && isset($v[$attr[$k]])) { - $attr[$k] = new ConstStub($v[$attr[$k]], $attr[$k]); - } - } catch (\Exception $e) { - } - } - if (isset($attr[$k = 'STATEMENT_CLASS'][1])) { - if ($attr[$k][1]) { - $attr[$k][1] = new ArgsStub($attr[$k][1], '__construct', $attr[$k][0]); - } - $attr[$k][0] = new ClassStub($attr[$k][0]); - } - - $prefix = Caster::PREFIX_VIRTUAL; - $a += [ - $prefix.'inTransaction' => method_exists($c, 'inTransaction'), - $prefix.'errorInfo' => $c->errorInfo(), - $prefix.'attributes' => new EnumStub($attr), - ]; - - if ($a[$prefix.'inTransaction']) { - $a[$prefix.'inTransaction'] = $c->inTransaction(); - } else { - unset($a[$prefix.'inTransaction']); - } - - if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) { - unset($a[$prefix.'errorInfo']); - } - - $c->setAttribute(\PDO::ATTR_ERRMODE, $errmode); - - return $a; - } - - public static function castPdoStatement(\PDOStatement $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - $a[$prefix.'errorInfo'] = $c->errorInfo(); - - if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) { - unset($a[$prefix.'errorInfo']); - } - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/PgSqlCaster.php b/vendor/symfony/var-dumper/Caster/PgSqlCaster.php deleted file mode 100644 index f9f3c6f..0000000 --- a/vendor/symfony/var-dumper/Caster/PgSqlCaster.php +++ /dev/null @@ -1,156 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts pqsql resources to array representation. - * - * @author Nicolas Grekas - * - * @final - */ -class PgSqlCaster -{ - private static $paramCodes = [ - 'server_encoding', - 'client_encoding', - 'is_superuser', - 'session_authorization', - 'DateStyle', - 'TimeZone', - 'IntervalStyle', - 'integer_datetimes', - 'application_name', - 'standard_conforming_strings', - ]; - - private static $transactionStatus = [ - PGSQL_TRANSACTION_IDLE => 'PGSQL_TRANSACTION_IDLE', - PGSQL_TRANSACTION_ACTIVE => 'PGSQL_TRANSACTION_ACTIVE', - PGSQL_TRANSACTION_INTRANS => 'PGSQL_TRANSACTION_INTRANS', - PGSQL_TRANSACTION_INERROR => 'PGSQL_TRANSACTION_INERROR', - PGSQL_TRANSACTION_UNKNOWN => 'PGSQL_TRANSACTION_UNKNOWN', - ]; - - private static $resultStatus = [ - PGSQL_EMPTY_QUERY => 'PGSQL_EMPTY_QUERY', - PGSQL_COMMAND_OK => 'PGSQL_COMMAND_OK', - PGSQL_TUPLES_OK => 'PGSQL_TUPLES_OK', - PGSQL_COPY_OUT => 'PGSQL_COPY_OUT', - PGSQL_COPY_IN => 'PGSQL_COPY_IN', - PGSQL_BAD_RESPONSE => 'PGSQL_BAD_RESPONSE', - PGSQL_NONFATAL_ERROR => 'PGSQL_NONFATAL_ERROR', - PGSQL_FATAL_ERROR => 'PGSQL_FATAL_ERROR', - ]; - - private static $diagCodes = [ - 'severity' => PGSQL_DIAG_SEVERITY, - 'sqlstate' => PGSQL_DIAG_SQLSTATE, - 'message' => PGSQL_DIAG_MESSAGE_PRIMARY, - 'detail' => PGSQL_DIAG_MESSAGE_DETAIL, - 'hint' => PGSQL_DIAG_MESSAGE_HINT, - 'statement position' => PGSQL_DIAG_STATEMENT_POSITION, - 'internal position' => PGSQL_DIAG_INTERNAL_POSITION, - 'internal query' => PGSQL_DIAG_INTERNAL_QUERY, - 'context' => PGSQL_DIAG_CONTEXT, - 'file' => PGSQL_DIAG_SOURCE_FILE, - 'line' => PGSQL_DIAG_SOURCE_LINE, - 'function' => PGSQL_DIAG_SOURCE_FUNCTION, - ]; - - public static function castLargeObject($lo, array $a, Stub $stub, bool $isNested) - { - $a['seek position'] = pg_lo_tell($lo); - - return $a; - } - - public static function castLink($link, array $a, Stub $stub, bool $isNested) - { - $a['status'] = pg_connection_status($link); - $a['status'] = new ConstStub(PGSQL_CONNECTION_OK === $a['status'] ? 'PGSQL_CONNECTION_OK' : 'PGSQL_CONNECTION_BAD', $a['status']); - $a['busy'] = pg_connection_busy($link); - - $a['transaction'] = pg_transaction_status($link); - if (isset(self::$transactionStatus[$a['transaction']])) { - $a['transaction'] = new ConstStub(self::$transactionStatus[$a['transaction']], $a['transaction']); - } - - $a['pid'] = pg_get_pid($link); - $a['last error'] = pg_last_error($link); - $a['last notice'] = pg_last_notice($link); - $a['host'] = pg_host($link); - $a['port'] = pg_port($link); - $a['dbname'] = pg_dbname($link); - $a['options'] = pg_options($link); - $a['version'] = pg_version($link); - - foreach (self::$paramCodes as $v) { - if (false !== $s = pg_parameter_status($link, $v)) { - $a['param'][$v] = $s; - } - } - - $a['param']['client_encoding'] = pg_client_encoding($link); - $a['param'] = new EnumStub($a['param']); - - return $a; - } - - public static function castResult($result, array $a, Stub $stub, bool $isNested) - { - $a['num rows'] = pg_num_rows($result); - $a['status'] = pg_result_status($result); - if (isset(self::$resultStatus[$a['status']])) { - $a['status'] = new ConstStub(self::$resultStatus[$a['status']], $a['status']); - } - $a['command-completion tag'] = pg_result_status($result, PGSQL_STATUS_STRING); - - if (-1 === $a['num rows']) { - foreach (self::$diagCodes as $k => $v) { - $a['error'][$k] = pg_result_error_field($result, $v); - } - } - - $a['affected rows'] = pg_affected_rows($result); - $a['last OID'] = pg_last_oid($result); - - $fields = pg_num_fields($result); - - for ($i = 0; $i < $fields; ++$i) { - $field = [ - 'name' => pg_field_name($result, $i), - 'table' => sprintf('%s (OID: %s)', pg_field_table($result, $i), pg_field_table($result, $i, true)), - 'type' => sprintf('%s (OID: %s)', pg_field_type($result, $i), pg_field_type_oid($result, $i)), - 'nullable' => (bool) pg_field_is_null($result, $i), - 'storage' => pg_field_size($result, $i).' bytes', - 'display' => pg_field_prtlen($result, $i).' chars', - ]; - if (' (OID: )' === $field['table']) { - $field['table'] = null; - } - if ('-1 bytes' === $field['storage']) { - $field['storage'] = 'variable size'; - } elseif ('1 bytes' === $field['storage']) { - $field['storage'] = '1 byte'; - } - if ('1 chars' === $field['display']) { - $field['display'] = '1 char'; - } - $a['fields'][] = new EnumStub($field); - } - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php b/vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php deleted file mode 100644 index e712019..0000000 --- a/vendor/symfony/var-dumper/Caster/ProxyManagerCaster.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use ProxyManager\Proxy\ProxyInterface; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @author Nicolas Grekas - * - * @final - */ -class ProxyManagerCaster -{ - public static function castProxy(ProxyInterface $c, array $a, Stub $stub, bool $isNested) - { - if ($parent = get_parent_class($c)) { - $stub->class .= ' - '.$parent; - } - $stub->class .= '@proxy'; - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/RedisCaster.php b/vendor/symfony/var-dumper/Caster/RedisCaster.php deleted file mode 100644 index a7ca8ec..0000000 --- a/vendor/symfony/var-dumper/Caster/RedisCaster.php +++ /dev/null @@ -1,152 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts Redis class from ext-redis to array representation. - * - * @author Nicolas Grekas - * - * @final - */ -class RedisCaster -{ - private static $serializer = [ - \Redis::SERIALIZER_NONE => 'NONE', - \Redis::SERIALIZER_PHP => 'PHP', - 2 => 'IGBINARY', // Optional Redis::SERIALIZER_IGBINARY - ]; - - private static $mode = [ - \Redis::ATOMIC => 'ATOMIC', - \Redis::MULTI => 'MULTI', - \Redis::PIPELINE => 'PIPELINE', - ]; - - private static $compression = [ - 0 => 'NONE', // Redis::COMPRESSION_NONE - 1 => 'LZF', // Redis::COMPRESSION_LZF - ]; - - private static $failover = [ - \RedisCluster::FAILOVER_NONE => 'NONE', - \RedisCluster::FAILOVER_ERROR => 'ERROR', - \RedisCluster::FAILOVER_DISTRIBUTE => 'DISTRIBUTE', - \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES => 'DISTRIBUTE_SLAVES', - ]; - - public static function castRedis(\Redis $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - if (!$connected = $c->isConnected()) { - return $a + [ - $prefix.'isConnected' => $connected, - ]; - } - - $mode = $c->getMode(); - - return $a + [ - $prefix.'isConnected' => $connected, - $prefix.'host' => $c->getHost(), - $prefix.'port' => $c->getPort(), - $prefix.'auth' => $c->getAuth(), - $prefix.'mode' => isset(self::$mode[$mode]) ? new ConstStub(self::$mode[$mode], $mode) : $mode, - $prefix.'dbNum' => $c->getDbNum(), - $prefix.'timeout' => $c->getTimeout(), - $prefix.'lastError' => $c->getLastError(), - $prefix.'persistentId' => $c->getPersistentID(), - $prefix.'options' => self::getRedisOptions($c), - ]; - } - - public static function castRedisArray(\RedisArray $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - return $a + [ - $prefix.'hosts' => $c->_hosts(), - $prefix.'function' => ClassStub::wrapCallable($c->_function()), - $prefix.'lastError' => $c->getLastError(), - $prefix.'options' => self::getRedisOptions($c), - ]; - } - - public static function castRedisCluster(\RedisCluster $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - $failover = $c->getOption(\RedisCluster::OPT_SLAVE_FAILOVER); - - $a += [ - $prefix.'_masters' => $c->_masters(), - $prefix.'_redir' => $c->_redir(), - $prefix.'mode' => new ConstStub($c->getMode() ? 'MULTI' : 'ATOMIC', $c->getMode()), - $prefix.'lastError' => $c->getLastError(), - $prefix.'options' => self::getRedisOptions($c, [ - 'SLAVE_FAILOVER' => isset(self::$failover[$failover]) ? new ConstStub(self::$failover[$failover], $failover) : $failover, - ]), - ]; - - return $a; - } - - /** - * @param \Redis|\RedisArray|\RedisCluster $redis - */ - private static function getRedisOptions($redis, array $options = []): EnumStub - { - $serializer = $redis->getOption(\Redis::OPT_SERIALIZER); - if (\is_array($serializer)) { - foreach ($serializer as &$v) { - if (isset(self::$serializer[$v])) { - $v = new ConstStub(self::$serializer[$v], $v); - } - } - } elseif (isset(self::$serializer[$serializer])) { - $serializer = new ConstStub(self::$serializer[$serializer], $serializer); - } - - $compression = \defined('Redis::OPT_COMPRESSION') ? $redis->getOption(\Redis::OPT_COMPRESSION) : 0; - if (\is_array($compression)) { - foreach ($compression as &$v) { - if (isset(self::$compression[$v])) { - $v = new ConstStub(self::$compression[$v], $v); - } - } - } elseif (isset(self::$compression[$compression])) { - $compression = new ConstStub(self::$compression[$compression], $compression); - } - - $retry = \defined('Redis::OPT_SCAN') ? $redis->getOption(\Redis::OPT_SCAN) : 0; - if (\is_array($retry)) { - foreach ($retry as &$v) { - $v = new ConstStub($v ? 'RETRY' : 'NORETRY', $v); - } - } else { - $retry = new ConstStub($retry ? 'RETRY' : 'NORETRY', $retry); - } - - $options += [ - 'TCP_KEEPALIVE' => \defined('Redis::OPT_TCP_KEEPALIVE') ? $redis->getOption(\Redis::OPT_TCP_KEEPALIVE) : 0, - 'READ_TIMEOUT' => $redis->getOption(\Redis::OPT_READ_TIMEOUT), - 'COMPRESSION' => $compression, - 'SERIALIZER' => $serializer, - 'PREFIX' => $redis->getOption(\Redis::OPT_PREFIX), - 'SCAN' => $retry, - ]; - - return new EnumStub($options); - } -} diff --git a/vendor/symfony/var-dumper/Caster/ReflectionCaster.php b/vendor/symfony/var-dumper/Caster/ReflectionCaster.php deleted file mode 100644 index 94c2f3e..0000000 --- a/vendor/symfony/var-dumper/Caster/ReflectionCaster.php +++ /dev/null @@ -1,384 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts Reflector related classes to array representation. - * - * @author Nicolas Grekas - * - * @final - */ -class ReflectionCaster -{ - const UNSET_CLOSURE_FILE_INFO = ['Closure' => __CLASS__.'::unsetClosureFileInfo']; - - private static $extraMap = [ - 'docComment' => 'getDocComment', - 'extension' => 'getExtensionName', - 'isDisabled' => 'isDisabled', - 'isDeprecated' => 'isDeprecated', - 'isInternal' => 'isInternal', - 'isUserDefined' => 'isUserDefined', - 'isGenerator' => 'isGenerator', - 'isVariadic' => 'isVariadic', - ]; - - public static function castClosure(\Closure $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $prefix = Caster::PREFIX_VIRTUAL; - $c = new \ReflectionFunction($c); - - $a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter); - - if (false === strpos($c->name, '{closure}')) { - $stub->class = isset($a[$prefix.'class']) ? $a[$prefix.'class']->value.'::'.$c->name : $c->name; - unset($a[$prefix.'class']); - } - unset($a[$prefix.'extra']); - - $stub->class .= self::getSignature($a); - - if ($f = $c->getFileName()) { - $stub->attr['file'] = $f; - $stub->attr['line'] = $c->getStartLine(); - } - - unset($a[$prefix.'parameters']); - - if ($filter & Caster::EXCLUDE_VERBOSE) { - $stub->cut += ($c->getFileName() ? 2 : 0) + \count($a); - - return []; - } - - if ($f) { - $a[$prefix.'file'] = new LinkStub($f, $c->getStartLine()); - $a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine(); - } - - return $a; - } - - public static function unsetClosureFileInfo(\Closure $c, array $a) - { - unset($a[Caster::PREFIX_VIRTUAL.'file'], $a[Caster::PREFIX_VIRTUAL.'line']); - - return $a; - } - - public static function castGenerator(\Generator $c, array $a, Stub $stub, bool $isNested) - { - // Cannot create ReflectionGenerator based on a terminated Generator - try { - $reflectionGenerator = new \ReflectionGenerator($c); - } catch (\Exception $e) { - $a[Caster::PREFIX_VIRTUAL.'closed'] = true; - - return $a; - } - - return self::castReflectionGenerator($reflectionGenerator, $a, $stub, $isNested); - } - - public static function castType(\ReflectionType $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - $a += [ - $prefix.'name' => $c->getName(), - $prefix.'allowsNull' => $c->allowsNull(), - $prefix.'isBuiltin' => $c->isBuiltin(), - ]; - - return $a; - } - - public static function castReflectionGenerator(\ReflectionGenerator $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - if ($c->getThis()) { - $a[$prefix.'this'] = new CutStub($c->getThis()); - } - $function = $c->getFunction(); - $frame = [ - 'class' => isset($function->class) ? $function->class : null, - 'type' => isset($function->class) ? ($function->isStatic() ? '::' : '->') : null, - 'function' => $function->name, - 'file' => $c->getExecutingFile(), - 'line' => $c->getExecutingLine(), - ]; - if ($trace = $c->getTrace(DEBUG_BACKTRACE_IGNORE_ARGS)) { - $function = new \ReflectionGenerator($c->getExecutingGenerator()); - array_unshift($trace, [ - 'function' => 'yield', - 'file' => $function->getExecutingFile(), - 'line' => $function->getExecutingLine() - 1, - ]); - $trace[] = $frame; - $a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1); - } else { - $function = new FrameStub($frame, false, true); - $function = ExceptionCaster::castFrameStub($function, [], $function, true); - $a[$prefix.'executing'] = $function[$prefix.'src']; - } - - $a[Caster::PREFIX_VIRTUAL.'closed'] = false; - - return $a; - } - - public static function castClass(\ReflectionClass $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $prefix = Caster::PREFIX_VIRTUAL; - - if ($n = \Reflection::getModifierNames($c->getModifiers())) { - $a[$prefix.'modifiers'] = implode(' ', $n); - } - - self::addMap($a, $c, [ - 'extends' => 'getParentClass', - 'implements' => 'getInterfaceNames', - 'constants' => 'getConstants', - ]); - - foreach ($c->getProperties() as $n) { - $a[$prefix.'properties'][$n->name] = $n; - } - - foreach ($c->getMethods() as $n) { - $a[$prefix.'methods'][$n->name] = $n; - } - - if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) { - self::addExtra($a, $c); - } - - return $a; - } - - public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, array $a, Stub $stub, bool $isNested, int $filter = 0) - { - $prefix = Caster::PREFIX_VIRTUAL; - - self::addMap($a, $c, [ - 'returnsReference' => 'returnsReference', - 'returnType' => 'getReturnType', - 'class' => 'getClosureScopeClass', - 'this' => 'getClosureThis', - ]); - - if (isset($a[$prefix.'returnType'])) { - $v = $a[$prefix.'returnType']; - $v = $v->getName(); - $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType']->allowsNull() ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); - } - if (isset($a[$prefix.'class'])) { - $a[$prefix.'class'] = new ClassStub($a[$prefix.'class']); - } - if (isset($a[$prefix.'this'])) { - $a[$prefix.'this'] = new CutStub($a[$prefix.'this']); - } - - foreach ($c->getParameters() as $v) { - $k = '$'.$v->name; - if ($v->isVariadic()) { - $k = '...'.$k; - } - if ($v->isPassedByReference()) { - $k = '&'.$k; - } - $a[$prefix.'parameters'][$k] = $v; - } - if (isset($a[$prefix.'parameters'])) { - $a[$prefix.'parameters'] = new EnumStub($a[$prefix.'parameters']); - } - - if (!($filter & Caster::EXCLUDE_VERBOSE) && $v = $c->getStaticVariables()) { - foreach ($v as $k => &$v) { - if (\is_object($v)) { - $a[$prefix.'use']['$'.$k] = new CutStub($v); - } else { - $a[$prefix.'use']['$'.$k] = &$v; - } - } - unset($v); - $a[$prefix.'use'] = new EnumStub($a[$prefix.'use']); - } - - if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) { - self::addExtra($a, $c); - } - - return $a; - } - - public static function castMethod(\ReflectionMethod $c, array $a, Stub $stub, bool $isNested) - { - $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers())); - - return $a; - } - - public static function castParameter(\ReflectionParameter $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - - self::addMap($a, $c, [ - 'position' => 'getPosition', - 'isVariadic' => 'isVariadic', - 'byReference' => 'isPassedByReference', - 'allowsNull' => 'allowsNull', - ]); - - if ($v = $c->getType()) { - $a[$prefix.'typeHint'] = $v->getName(); - } - - if (isset($a[$prefix.'typeHint'])) { - $v = $a[$prefix.'typeHint']; - $a[$prefix.'typeHint'] = new ClassStub($v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); - } else { - unset($a[$prefix.'allowsNull']); - } - - try { - $a[$prefix.'default'] = $v = $c->getDefaultValue(); - if ($c->isDefaultValueConstant()) { - $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v); - } - if (null === $v) { - unset($a[$prefix.'allowsNull']); - } - } catch (\ReflectionException $e) { - } - - return $a; - } - - public static function castProperty(\ReflectionProperty $c, array $a, Stub $stub, bool $isNested) - { - $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers())); - self::addExtra($a, $c); - - return $a; - } - - public static function castReference(\ReflectionReference $c, array $a, Stub $stub, bool $isNested) - { - $a[Caster::PREFIX_VIRTUAL.'id'] = $c->getId(); - - return $a; - } - - public static function castExtension(\ReflectionExtension $c, array $a, Stub $stub, bool $isNested) - { - self::addMap($a, $c, [ - 'version' => 'getVersion', - 'dependencies' => 'getDependencies', - 'iniEntries' => 'getIniEntries', - 'isPersistent' => 'isPersistent', - 'isTemporary' => 'isTemporary', - 'constants' => 'getConstants', - 'functions' => 'getFunctions', - 'classes' => 'getClasses', - ]); - - return $a; - } - - public static function castZendExtension(\ReflectionZendExtension $c, array $a, Stub $stub, bool $isNested) - { - self::addMap($a, $c, [ - 'version' => 'getVersion', - 'author' => 'getAuthor', - 'copyright' => 'getCopyright', - 'url' => 'getURL', - ]); - - return $a; - } - - public static function getSignature(array $a) - { - $prefix = Caster::PREFIX_VIRTUAL; - $signature = ''; - - if (isset($a[$prefix.'parameters'])) { - foreach ($a[$prefix.'parameters']->value as $k => $param) { - $signature .= ', '; - if ($type = $param->getType()) { - if (!$param->isOptional() && $param->allowsNull()) { - $signature .= '?'; - } - $signature .= substr(strrchr('\\'.$type->getName(), '\\'), 1).' '; - } - $signature .= $k; - - if (!$param->isDefaultValueAvailable()) { - continue; - } - $v = $param->getDefaultValue(); - $signature .= ' = '; - - if ($param->isDefaultValueConstant()) { - $signature .= substr(strrchr('\\'.$param->getDefaultValueConstantName(), '\\'), 1); - } elseif (null === $v) { - $signature .= 'null'; - } elseif (\is_array($v)) { - $signature .= $v ? '[…'.\count($v).']' : '[]'; - } elseif (\is_string($v)) { - $signature .= 10 > \strlen($v) && false === strpos($v, '\\') ? "'{$v}'" : "'…".\strlen($v)."'"; - } elseif (\is_bool($v)) { - $signature .= $v ? 'true' : 'false'; - } else { - $signature .= $v; - } - } - } - $signature = (empty($a[$prefix.'returnsReference']) ? '' : '&').'('.substr($signature, 2).')'; - - if (isset($a[$prefix.'returnType'])) { - $signature .= ': '.substr(strrchr('\\'.$a[$prefix.'returnType'], '\\'), 1); - } - - return $signature; - } - - private static function addExtra(array &$a, \Reflector $c) - { - $x = isset($a[Caster::PREFIX_VIRTUAL.'extra']) ? $a[Caster::PREFIX_VIRTUAL.'extra']->value : []; - - if (method_exists($c, 'getFileName') && $m = $c->getFileName()) { - $x['file'] = new LinkStub($m, $c->getStartLine()); - $x['line'] = $c->getStartLine().' to '.$c->getEndLine(); - } - - self::addMap($x, $c, self::$extraMap, ''); - - if ($x) { - $a[Caster::PREFIX_VIRTUAL.'extra'] = new EnumStub($x); - } - } - - private static function addMap(array &$a, \Reflector $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL) - { - foreach ($map as $k => $m) { - if (method_exists($c, $m) && false !== ($m = $c->$m()) && null !== $m) { - $a[$prefix.$k] = $m instanceof \Reflector ? $m->name : $m; - } - } - } -} diff --git a/vendor/symfony/var-dumper/Caster/ResourceCaster.php b/vendor/symfony/var-dumper/Caster/ResourceCaster.php deleted file mode 100644 index 94ff5a9..0000000 --- a/vendor/symfony/var-dumper/Caster/ResourceCaster.php +++ /dev/null @@ -1,100 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts common resource types to array representation. - * - * @author Nicolas Grekas - * - * @final - */ -class ResourceCaster -{ - public static function castCurl($h, array $a, Stub $stub, bool $isNested) - { - return curl_getinfo($h); - } - - public static function castDba($dba, array $a, Stub $stub, bool $isNested) - { - $list = dba_list(); - $a['file'] = $list[(int) $dba]; - - return $a; - } - - public static function castProcess($process, array $a, Stub $stub, bool $isNested) - { - return proc_get_status($process); - } - - public static function castStream($stream, array $a, Stub $stub, bool $isNested) - { - $a = stream_get_meta_data($stream) + static::castStreamContext($stream, $a, $stub, $isNested); - if (isset($a['uri'])) { - $a['uri'] = new LinkStub($a['uri']); - } - - return $a; - } - - public static function castStreamContext($stream, array $a, Stub $stub, bool $isNested) - { - return @stream_context_get_params($stream) ?: $a; - } - - public static function castGd($gd, array $a, Stub $stub, $isNested) - { - $a['size'] = imagesx($gd).'x'.imagesy($gd); - $a['trueColor'] = imageistruecolor($gd); - - return $a; - } - - public static function castMysqlLink($h, array $a, Stub $stub, bool $isNested) - { - $a['host'] = mysql_get_host_info($h); - $a['protocol'] = mysql_get_proto_info($h); - $a['server'] = mysql_get_server_info($h); - - return $a; - } - - public static function castOpensslX509($h, array $a, Stub $stub, bool $isNested) - { - $stub->cut = -1; - $info = openssl_x509_parse($h, false); - - $pin = openssl_pkey_get_public($h); - $pin = openssl_pkey_get_details($pin)['key']; - $pin = \array_slice(explode("\n", $pin), 1, -2); - $pin = base64_decode(implode('', $pin)); - $pin = base64_encode(hash('sha256', $pin, true)); - - $a += [ - 'subject' => new EnumStub(array_intersect_key($info['subject'], ['organizationName' => true, 'commonName' => true])), - 'issuer' => new EnumStub(array_intersect_key($info['issuer'], ['organizationName' => true, 'commonName' => true])), - 'expiry' => new ConstStub(date(\DateTime::ISO8601, $info['validTo_time_t']), $info['validTo_time_t']), - 'fingerprint' => new EnumStub([ - 'md5' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'md5')), 2, ':', true)), - 'sha1' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha1')), 2, ':', true)), - 'sha256' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha256')), 2, ':', true)), - 'pin-sha256' => new ConstStub($pin), - ]), - ]; - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/SplCaster.php b/vendor/symfony/var-dumper/Caster/SplCaster.php deleted file mode 100644 index e6c5b17..0000000 --- a/vendor/symfony/var-dumper/Caster/SplCaster.php +++ /dev/null @@ -1,228 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts SPL related classes to array representation. - * - * @author Nicolas Grekas - * - * @final - */ -class SplCaster -{ - private static $splFileObjectFlags = [ - \SplFileObject::DROP_NEW_LINE => 'DROP_NEW_LINE', - \SplFileObject::READ_AHEAD => 'READ_AHEAD', - \SplFileObject::SKIP_EMPTY => 'SKIP_EMPTY', - \SplFileObject::READ_CSV => 'READ_CSV', - ]; - - public static function castArrayObject(\ArrayObject $c, array $a, Stub $stub, bool $isNested) - { - return self::castSplArray($c, $a, $stub, $isNested); - } - - public static function castArrayIterator(\ArrayIterator $c, array $a, Stub $stub, bool $isNested) - { - return self::castSplArray($c, $a, $stub, $isNested); - } - - public static function castHeap(\Iterator $c, array $a, Stub $stub, $isNested) - { - $a += [ - Caster::PREFIX_VIRTUAL.'heap' => iterator_to_array(clone $c), - ]; - - return $a; - } - - public static function castDoublyLinkedList(\SplDoublyLinkedList $c, array $a, Stub $stub, bool $isNested) - { - $prefix = Caster::PREFIX_VIRTUAL; - $mode = $c->getIteratorMode(); - $c->setIteratorMode(\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\SplDoublyLinkedList::IT_MODE_DELETE); - - $a += [ - $prefix.'mode' => new ConstStub((($mode & \SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \SplDoublyLinkedList::IT_MODE_DELETE) ? 'IT_MODE_DELETE' : 'IT_MODE_KEEP'), $mode), - $prefix.'dllist' => iterator_to_array($c), - ]; - $c->setIteratorMode($mode); - - return $a; - } - - public static function castFileInfo(\SplFileInfo $c, array $a, Stub $stub, bool $isNested) - { - static $map = [ - 'path' => 'getPath', - 'filename' => 'getFilename', - 'basename' => 'getBasename', - 'pathname' => 'getPathname', - 'extension' => 'getExtension', - 'realPath' => 'getRealPath', - 'aTime' => 'getATime', - 'mTime' => 'getMTime', - 'cTime' => 'getCTime', - 'inode' => 'getInode', - 'size' => 'getSize', - 'perms' => 'getPerms', - 'owner' => 'getOwner', - 'group' => 'getGroup', - 'type' => 'getType', - 'writable' => 'isWritable', - 'readable' => 'isReadable', - 'executable' => 'isExecutable', - 'file' => 'isFile', - 'dir' => 'isDir', - 'link' => 'isLink', - 'linkTarget' => 'getLinkTarget', - ]; - - $prefix = Caster::PREFIX_VIRTUAL; - - if (false === $c->getPathname()) { - $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state'; - - return $a; - } - - foreach ($map as $key => $accessor) { - try { - $a[$prefix.$key] = $c->$accessor(); - } catch (\Exception $e) { - } - } - - if (isset($a[$prefix.'realPath'])) { - $a[$prefix.'realPath'] = new LinkStub($a[$prefix.'realPath']); - } - - if (isset($a[$prefix.'perms'])) { - $a[$prefix.'perms'] = new ConstStub(sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']); - } - - static $mapDate = ['aTime', 'mTime', 'cTime']; - foreach ($mapDate as $key) { - if (isset($a[$prefix.$key])) { - $a[$prefix.$key] = new ConstStub(date('Y-m-d H:i:s', $a[$prefix.$key]), $a[$prefix.$key]); - } - } - - return $a; - } - - public static function castFileObject(\SplFileObject $c, array $a, Stub $stub, bool $isNested) - { - static $map = [ - 'csvControl' => 'getCsvControl', - 'flags' => 'getFlags', - 'maxLineLen' => 'getMaxLineLen', - 'fstat' => 'fstat', - 'eof' => 'eof', - 'key' => 'key', - ]; - - $prefix = Caster::PREFIX_VIRTUAL; - - foreach ($map as $key => $accessor) { - try { - $a[$prefix.$key] = $c->$accessor(); - } catch (\Exception $e) { - } - } - - if (isset($a[$prefix.'flags'])) { - $flagsArray = []; - foreach (self::$splFileObjectFlags as $value => $name) { - if ($a[$prefix.'flags'] & $value) { - $flagsArray[] = $name; - } - } - $a[$prefix.'flags'] = new ConstStub(implode('|', $flagsArray), $a[$prefix.'flags']); - } - - if (isset($a[$prefix.'fstat'])) { - $a[$prefix.'fstat'] = new CutArrayStub($a[$prefix.'fstat'], ['dev', 'ino', 'nlink', 'rdev', 'blksize', 'blocks']); - } - - return $a; - } - - public static function castFixedArray(\SplFixedArray $c, array $a, Stub $stub, bool $isNested) - { - $a += [ - Caster::PREFIX_VIRTUAL.'storage' => $c->toArray(), - ]; - - return $a; - } - - public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $stub, bool $isNested) - { - $storage = []; - unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967 - - $clone = clone $c; - foreach ($clone as $obj) { - $storage[] = [ - 'object' => $obj, - 'info' => $clone->getInfo(), - ]; - } - - $a += [ - Caster::PREFIX_VIRTUAL.'storage' => $storage, - ]; - - return $a; - } - - public static function castOuterIterator(\OuterIterator $c, array $a, Stub $stub, bool $isNested) - { - $a[Caster::PREFIX_VIRTUAL.'innerIterator'] = $c->getInnerIterator(); - - return $a; - } - - public static function castWeakReference(\WeakReference $c, array $a, Stub $stub, bool $isNested) - { - $a[Caster::PREFIX_VIRTUAL.'object'] = $c->get(); - - return $a; - } - - private static function castSplArray($c, array $a, Stub $stub, bool $isNested): array - { - $prefix = Caster::PREFIX_VIRTUAL; - $class = $stub->class; - $flags = $c->getFlags(); - - if (!($flags & \ArrayObject::STD_PROP_LIST)) { - $c->setFlags(\ArrayObject::STD_PROP_LIST); - $a = Caster::castObject($c, $class); - $c->setFlags($flags); - } - $a += [ - $prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST), - $prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS), - ]; - if ($c instanceof \ArrayObject) { - $a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass()); - } - $a[$prefix.'storage'] = $c->getArrayCopy(); - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/StubCaster.php b/vendor/symfony/var-dumper/Caster/StubCaster.php deleted file mode 100644 index 32ead7c..0000000 --- a/vendor/symfony/var-dumper/Caster/StubCaster.php +++ /dev/null @@ -1,84 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts a caster's Stub. - * - * @author Nicolas Grekas - * - * @final - */ -class StubCaster -{ - public static function castStub(Stub $c, array $a, Stub $stub, bool $isNested) - { - if ($isNested) { - $stub->type = $c->type; - $stub->class = $c->class; - $stub->value = $c->value; - $stub->handle = $c->handle; - $stub->cut = $c->cut; - $stub->attr = $c->attr; - - if (Stub::TYPE_REF === $c->type && !$c->class && \is_string($c->value) && !preg_match('//u', $c->value)) { - $stub->type = Stub::TYPE_STRING; - $stub->class = Stub::STRING_BINARY; - } - - $a = []; - } - - return $a; - } - - public static function castCutArray(CutArrayStub $c, array $a, Stub $stub, bool $isNested) - { - return $isNested ? $c->preservedSubset : $a; - } - - public static function cutInternals($obj, array $a, Stub $stub, bool $isNested) - { - if ($isNested) { - $stub->cut += \count($a); - - return []; - } - - return $a; - } - - public static function castEnum(EnumStub $c, array $a, Stub $stub, bool $isNested) - { - if ($isNested) { - $stub->class = $c->dumpKeys ? '' : null; - $stub->handle = 0; - $stub->value = null; - $stub->cut = $c->cut; - $stub->attr = $c->attr; - - $a = []; - - if ($c->value) { - foreach (array_keys($c->value) as $k) { - $keys[] = !isset($k[0]) || "\0" !== $k[0] ? Caster::PREFIX_VIRTUAL.$k : $k; - } - // Preserve references with array_combine() - $a = array_combine($keys, $c->value); - } - } - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/SymfonyCaster.php b/vendor/symfony/var-dumper/Caster/SymfonyCaster.php deleted file mode 100644 index 6b87bde..0000000 --- a/vendor/symfony/var-dumper/Caster/SymfonyCaster.php +++ /dev/null @@ -1,69 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @final - */ -class SymfonyCaster -{ - private static $requestGetters = [ - 'pathInfo' => 'getPathInfo', - 'requestUri' => 'getRequestUri', - 'baseUrl' => 'getBaseUrl', - 'basePath' => 'getBasePath', - 'method' => 'getMethod', - 'format' => 'getRequestFormat', - ]; - - public static function castRequest(Request $request, array $a, Stub $stub, bool $isNested) - { - $clone = null; - - foreach (self::$requestGetters as $prop => $getter) { - $key = Caster::PREFIX_PROTECTED.$prop; - if (\array_key_exists($key, $a) && null === $a[$key]) { - if (null === $clone) { - $clone = clone $request; - } - $a[Caster::PREFIX_VIRTUAL.$prop] = $clone->{$getter}(); - } - } - - return $a; - } - - public static function castHttpClient($client, array $a, Stub $stub, bool $isNested) - { - $multiKey = sprintf("\0%s\0multi", \get_class($client)); - if (isset($a[$multiKey])) { - $a[$multiKey] = new CutStub($a[$multiKey]); - } - - return $a; - } - - public static function castHttpClientResponse($response, array $a, Stub $stub, bool $isNested) - { - $stub->cut += \count($a); - $a = []; - - foreach ($response->getInfo() as $k => $v) { - $a[Caster::PREFIX_VIRTUAL.$k] = $v; - } - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/TraceStub.php b/vendor/symfony/var-dumper/Caster/TraceStub.php deleted file mode 100644 index 5eea1c8..0000000 --- a/vendor/symfony/var-dumper/Caster/TraceStub.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Represents a backtrace as returned by debug_backtrace() or Exception->getTrace(). - * - * @author Nicolas Grekas - */ -class TraceStub extends Stub -{ - public $keepArgs; - public $sliceOffset; - public $sliceLength; - public $numberingOffset; - - public function __construct(array $trace, bool $keepArgs = true, int $sliceOffset = 0, int $sliceLength = null, int $numberingOffset = 0) - { - $this->value = $trace; - $this->keepArgs = $keepArgs; - $this->sliceOffset = $sliceOffset; - $this->sliceLength = $sliceLength; - $this->numberingOffset = $numberingOffset; - } -} diff --git a/vendor/symfony/var-dumper/Caster/UuidCaster.php b/vendor/symfony/var-dumper/Caster/UuidCaster.php deleted file mode 100644 index b102774..0000000 --- a/vendor/symfony/var-dumper/Caster/UuidCaster.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Ramsey\Uuid\UuidInterface; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * @author Grégoire Pineau - */ -final class UuidCaster -{ - public static function castRamseyUuid(UuidInterface $c, array $a, Stub $stub, bool $isNested): array - { - $a += [ - Caster::PREFIX_VIRTUAL.'uuid' => (string) $c, - ]; - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Caster/XmlReaderCaster.php b/vendor/symfony/var-dumper/Caster/XmlReaderCaster.php deleted file mode 100644 index 1bca357..0000000 --- a/vendor/symfony/var-dumper/Caster/XmlReaderCaster.php +++ /dev/null @@ -1,79 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts XmlReader class to array representation. - * - * @author Baptiste Clavié - * - * @final - */ -class XmlReaderCaster -{ - private static $nodeTypes = [ - \XMLReader::NONE => 'NONE', - \XMLReader::ELEMENT => 'ELEMENT', - \XMLReader::ATTRIBUTE => 'ATTRIBUTE', - \XMLReader::TEXT => 'TEXT', - \XMLReader::CDATA => 'CDATA', - \XMLReader::ENTITY_REF => 'ENTITY_REF', - \XMLReader::ENTITY => 'ENTITY', - \XMLReader::PI => 'PI (Processing Instruction)', - \XMLReader::COMMENT => 'COMMENT', - \XMLReader::DOC => 'DOC', - \XMLReader::DOC_TYPE => 'DOC_TYPE', - \XMLReader::DOC_FRAGMENT => 'DOC_FRAGMENT', - \XMLReader::NOTATION => 'NOTATION', - \XMLReader::WHITESPACE => 'WHITESPACE', - \XMLReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE', - \XMLReader::END_ELEMENT => 'END_ELEMENT', - \XMLReader::END_ENTITY => 'END_ENTITY', - \XMLReader::XML_DECLARATION => 'XML_DECLARATION', - ]; - - public static function castXmlReader(\XMLReader $reader, array $a, Stub $stub, bool $isNested) - { - $props = Caster::PREFIX_VIRTUAL.'parserProperties'; - $info = [ - 'localName' => $reader->localName, - 'prefix' => $reader->prefix, - 'nodeType' => new ConstStub(self::$nodeTypes[$reader->nodeType], $reader->nodeType), - 'depth' => $reader->depth, - 'isDefault' => $reader->isDefault, - 'isEmptyElement' => \XMLReader::NONE === $reader->nodeType ? null : $reader->isEmptyElement, - 'xmlLang' => $reader->xmlLang, - 'attributeCount' => $reader->attributeCount, - 'value' => $reader->value, - 'namespaceURI' => $reader->namespaceURI, - 'baseURI' => $reader->baseURI ? new LinkStub($reader->baseURI) : $reader->baseURI, - $props => [ - 'LOADDTD' => $reader->getParserProperty(\XMLReader::LOADDTD), - 'DEFAULTATTRS' => $reader->getParserProperty(\XMLReader::DEFAULTATTRS), - 'VALIDATE' => $reader->getParserProperty(\XMLReader::VALIDATE), - 'SUBST_ENTITIES' => $reader->getParserProperty(\XMLReader::SUBST_ENTITIES), - ], - ]; - - if ($info[$props] = Caster::filter($info[$props], Caster::EXCLUDE_EMPTY, [], $count)) { - $info[$props] = new EnumStub($info[$props]); - $info[$props]->cut = $count; - } - - $info = Caster::filter($info, Caster::EXCLUDE_EMPTY, [], $count); - // +2 because hasValue and hasAttributes are always filtered - $stub->cut += $count + 2; - - return $a + $info; - } -} diff --git a/vendor/symfony/var-dumper/Caster/XmlResourceCaster.php b/vendor/symfony/var-dumper/Caster/XmlResourceCaster.php deleted file mode 100644 index edece30..0000000 --- a/vendor/symfony/var-dumper/Caster/XmlResourceCaster.php +++ /dev/null @@ -1,63 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * Casts XML resources to array representation. - * - * @author Nicolas Grekas - * - * @final - */ -class XmlResourceCaster -{ - private static $xmlErrors = [ - XML_ERROR_NONE => 'XML_ERROR_NONE', - XML_ERROR_NO_MEMORY => 'XML_ERROR_NO_MEMORY', - XML_ERROR_SYNTAX => 'XML_ERROR_SYNTAX', - XML_ERROR_NO_ELEMENTS => 'XML_ERROR_NO_ELEMENTS', - XML_ERROR_INVALID_TOKEN => 'XML_ERROR_INVALID_TOKEN', - XML_ERROR_UNCLOSED_TOKEN => 'XML_ERROR_UNCLOSED_TOKEN', - XML_ERROR_PARTIAL_CHAR => 'XML_ERROR_PARTIAL_CHAR', - XML_ERROR_TAG_MISMATCH => 'XML_ERROR_TAG_MISMATCH', - XML_ERROR_DUPLICATE_ATTRIBUTE => 'XML_ERROR_DUPLICATE_ATTRIBUTE', - XML_ERROR_JUNK_AFTER_DOC_ELEMENT => 'XML_ERROR_JUNK_AFTER_DOC_ELEMENT', - XML_ERROR_PARAM_ENTITY_REF => 'XML_ERROR_PARAM_ENTITY_REF', - XML_ERROR_UNDEFINED_ENTITY => 'XML_ERROR_UNDEFINED_ENTITY', - XML_ERROR_RECURSIVE_ENTITY_REF => 'XML_ERROR_RECURSIVE_ENTITY_REF', - XML_ERROR_ASYNC_ENTITY => 'XML_ERROR_ASYNC_ENTITY', - XML_ERROR_BAD_CHAR_REF => 'XML_ERROR_BAD_CHAR_REF', - XML_ERROR_BINARY_ENTITY_REF => 'XML_ERROR_BINARY_ENTITY_REF', - XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF => 'XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF', - XML_ERROR_MISPLACED_XML_PI => 'XML_ERROR_MISPLACED_XML_PI', - XML_ERROR_UNKNOWN_ENCODING => 'XML_ERROR_UNKNOWN_ENCODING', - XML_ERROR_INCORRECT_ENCODING => 'XML_ERROR_INCORRECT_ENCODING', - XML_ERROR_UNCLOSED_CDATA_SECTION => 'XML_ERROR_UNCLOSED_CDATA_SECTION', - XML_ERROR_EXTERNAL_ENTITY_HANDLING => 'XML_ERROR_EXTERNAL_ENTITY_HANDLING', - ]; - - public static function castXml($h, array $a, Stub $stub, bool $isNested) - { - $a['current_byte_index'] = xml_get_current_byte_index($h); - $a['current_column_number'] = xml_get_current_column_number($h); - $a['current_line_number'] = xml_get_current_line_number($h); - $a['error_code'] = xml_get_error_code($h); - - if (isset(self::$xmlErrors[$a['error_code']])) { - $a['error_code'] = new ConstStub(self::$xmlErrors[$a['error_code']], $a['error_code']); - } - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Cloner/AbstractCloner.php b/vendor/symfony/var-dumper/Cloner/AbstractCloner.php deleted file mode 100644 index 56b2384..0000000 --- a/vendor/symfony/var-dumper/Cloner/AbstractCloner.php +++ /dev/null @@ -1,360 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -use Symfony\Component\VarDumper\Caster\Caster; -use Symfony\Component\VarDumper\Exception\ThrowingCasterException; - -/** - * AbstractCloner implements a generic caster mechanism for objects and resources. - * - * @author Nicolas Grekas - */ -abstract class AbstractCloner implements ClonerInterface -{ - public static $defaultCasters = [ - '__PHP_Incomplete_Class' => ['Symfony\Component\VarDumper\Caster\Caster', 'castPhpIncompleteClass'], - - 'Symfony\Component\VarDumper\Caster\CutStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'], - 'Symfony\Component\VarDumper\Caster\CutArrayStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castCutArray'], - 'Symfony\Component\VarDumper\Caster\ConstStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'], - 'Symfony\Component\VarDumper\Caster\EnumStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castEnum'], - - 'Closure' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClosure'], - 'Generator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castGenerator'], - 'ReflectionType' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castType'], - 'ReflectionGenerator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReflectionGenerator'], - 'ReflectionClass' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClass'], - 'ReflectionFunctionAbstract' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castFunctionAbstract'], - 'ReflectionMethod' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castMethod'], - 'ReflectionParameter' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castParameter'], - 'ReflectionProperty' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castProperty'], - 'ReflectionReference' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReference'], - 'ReflectionExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castExtension'], - 'ReflectionZendExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castZendExtension'], - - 'Doctrine\Common\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'Doctrine\Common\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castCommonProxy'], - 'Doctrine\ORM\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castOrmProxy'], - 'Doctrine\ORM\PersistentCollection' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castPersistentCollection'], - 'Doctrine\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - - 'DOMException' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castException'], - 'DOMStringList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], - 'DOMNameList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], - 'DOMImplementation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castImplementation'], - 'DOMImplementationList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], - 'DOMNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNode'], - 'DOMNameSpaceNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNameSpaceNode'], - 'DOMDocument' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocument'], - 'DOMNodeList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], - 'DOMNamedNodeMap' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], - 'DOMCharacterData' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castCharacterData'], - 'DOMAttr' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castAttr'], - 'DOMElement' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castElement'], - 'DOMText' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castText'], - 'DOMTypeinfo' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castTypeinfo'], - 'DOMDomError' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDomError'], - 'DOMLocator' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLocator'], - 'DOMDocumentType' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocumentType'], - 'DOMNotation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNotation'], - 'DOMEntity' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castEntity'], - 'DOMProcessingInstruction' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castProcessingInstruction'], - 'DOMXPath' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castXPath'], - - 'XMLReader' => ['Symfony\Component\VarDumper\Caster\XmlReaderCaster', 'castXmlReader'], - - 'ErrorException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castErrorException'], - 'Exception' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castException'], - 'Error' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castError'], - 'Symfony\Component\DependencyInjection\ContainerInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'Symfony\Component\EventDispatcher\EventDispatcherInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'Symfony\Component\HttpClient\CurlHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], - 'Symfony\Component\HttpClient\NativeHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], - 'Symfony\Component\HttpClient\Response\CurlResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], - 'Symfony\Component\HttpClient\Response\NativeResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], - 'Symfony\Component\HttpFoundation\Request' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castRequest'], - 'Symfony\Component\VarDumper\Exception\ThrowingCasterException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castThrowingCasterException'], - 'Symfony\Component\VarDumper\Caster\TraceStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castTraceStub'], - 'Symfony\Component\VarDumper\Caster\FrameStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castFrameStub'], - 'Symfony\Component\VarDumper\Cloner\AbstractCloner' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'Symfony\Component\ErrorHandler\Exception\SilencedErrorContext' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castSilencedErrorContext'], - - 'Imagine\Image\ImageInterface' => ['Symfony\Component\VarDumper\Caster\ImagineCaster', 'castImage'], - - 'Ramsey\Uuid\UuidInterface' => ['Symfony\Component\VarDumper\Caster\UuidCaster', 'castRamseyUuid'], - - 'ProxyManager\Proxy\ProxyInterface' => ['Symfony\Component\VarDumper\Caster\ProxyManagerCaster', 'castProxy'], - 'PHPUnit_Framework_MockObject_MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'PHPUnit\Framework\MockObject\MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'PHPUnit\Framework\MockObject\Stub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'Prophecy\Prophecy\ProphecySubjectInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - 'Mockery\MockInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], - - 'PDO' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdo'], - 'PDOStatement' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdoStatement'], - - 'AMQPConnection' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castConnection'], - 'AMQPChannel' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castChannel'], - 'AMQPQueue' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castQueue'], - 'AMQPExchange' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castExchange'], - 'AMQPEnvelope' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castEnvelope'], - - 'ArrayObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayObject'], - 'ArrayIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayIterator'], - 'SplDoublyLinkedList' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'], - 'SplFileInfo' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'], - 'SplFileObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'], - 'SplFixedArray' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFixedArray'], - 'SplHeap' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], - 'SplObjectStorage' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castObjectStorage'], - 'SplPriorityQueue' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], - 'OuterIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castOuterIterator'], - 'WeakReference' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castWeakReference'], - - 'Redis' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedis'], - 'RedisArray' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisArray'], - 'RedisCluster' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisCluster'], - - 'DateTimeInterface' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castDateTime'], - 'DateInterval' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castInterval'], - 'DateTimeZone' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castTimeZone'], - 'DatePeriod' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castPeriod'], - - 'GMP' => ['Symfony\Component\VarDumper\Caster\GmpCaster', 'castGmp'], - - 'MessageFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castMessageFormatter'], - 'NumberFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castNumberFormatter'], - 'IntlTimeZone' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlTimeZone'], - 'IntlCalendar' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlCalendar'], - 'IntlDateFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlDateFormatter'], - - 'Memcached' => ['Symfony\Component\VarDumper\Caster\MemcachedCaster', 'castMemcached'], - - 'Ds\Collection' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castCollection'], - 'Ds\Map' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castMap'], - 'Ds\Pair' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castPair'], - 'Symfony\Component\VarDumper\Caster\DsPairStub' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castPairStub'], - - ':curl' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'], - ':dba' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'], - ':dba persistent' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'], - ':gd' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'], - ':mysql link' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castMysqlLink'], - ':pgsql large object' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLargeObject'], - ':pgsql link' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'], - ':pgsql link persistent' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'], - ':pgsql result' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castResult'], - ':process' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castProcess'], - ':stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'], - ':OpenSSL X.509' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castOpensslX509'], - ':persistent stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'], - ':stream-context' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStreamContext'], - ':xml' => ['Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'], - ]; - - protected $maxItems = 2500; - protected $maxString = -1; - protected $minDepth = 1; - - private $casters = []; - private $prevErrorHandler; - private $classInfo = []; - private $filter = 0; - - /** - * @param callable[]|null $casters A map of casters - * - * @see addCasters - */ - public function __construct(array $casters = null) - { - if (null === $casters) { - $casters = static::$defaultCasters; - } - $this->addCasters($casters); - } - - /** - * Adds casters for resources and objects. - * - * Maps resources or objects types to a callback. - * Types are in the key, with a callable caster for value. - * Resource types are to be prefixed with a `:`, - * see e.g. static::$defaultCasters. - * - * @param callable[] $casters A map of casters - */ - public function addCasters(array $casters) - { - foreach ($casters as $type => $callback) { - $this->casters[$type][] = $callback; - } - } - - /** - * Sets the maximum number of items to clone past the minimum depth in nested structures. - */ - public function setMaxItems(int $maxItems) - { - $this->maxItems = $maxItems; - } - - /** - * Sets the maximum cloned length for strings. - */ - public function setMaxString(int $maxString) - { - $this->maxString = $maxString; - } - - /** - * Sets the minimum tree depth where we are guaranteed to clone all the items. After this - * depth is reached, only setMaxItems items will be cloned. - */ - public function setMinDepth(int $minDepth) - { - $this->minDepth = $minDepth; - } - - /** - * Clones a PHP variable. - * - * @param mixed $var Any PHP variable - * @param int $filter A bit field of Caster::EXCLUDE_* constants - * - * @return Data The cloned variable represented by a Data object - */ - public function cloneVar($var, int $filter = 0) - { - $this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) { - if (E_RECOVERABLE_ERROR === $type || E_USER_ERROR === $type) { - // Cloner never dies - throw new \ErrorException($msg, 0, $type, $file, $line); - } - - if ($this->prevErrorHandler) { - return ($this->prevErrorHandler)($type, $msg, $file, $line, $context); - } - - return false; - }); - $this->filter = $filter; - - if ($gc = gc_enabled()) { - gc_disable(); - } - try { - return new Data($this->doClone($var)); - } finally { - if ($gc) { - gc_enable(); - } - restore_error_handler(); - $this->prevErrorHandler = null; - } - } - - /** - * Effectively clones the PHP variable. - * - * @param mixed $var Any PHP variable - * - * @return array The cloned variable represented in an array - */ - abstract protected function doClone($var); - - /** - * Casts an object to an array representation. - * - * @param bool $isNested True if the object is nested in the dumped structure - * - * @return array The object casted as array - */ - protected function castObject(Stub $stub, bool $isNested) - { - $obj = $stub->value; - $class = $stub->class; - - if (isset($class[15]) && "\0" === $class[15] && 0 === strpos($class, "class@anonymous\x00")) { - $stub->class = get_parent_class($class).'@anonymous'; - } - if (isset($this->classInfo[$class])) { - list($i, $parents, $hasDebugInfo, $fileInfo) = $this->classInfo[$class]; - } else { - $i = 2; - $parents = [$class]; - $hasDebugInfo = method_exists($class, '__debugInfo'); - - foreach (class_parents($class) as $p) { - $parents[] = $p; - ++$i; - } - foreach (class_implements($class) as $p) { - $parents[] = $p; - ++$i; - } - $parents[] = '*'; - - $r = new \ReflectionClass($class); - $fileInfo = $r->isInternal() || $r->isSubclassOf(Stub::class) ? [] : [ - 'file' => $r->getFileName(), - 'line' => $r->getStartLine(), - ]; - - $this->classInfo[$class] = [$i, $parents, $hasDebugInfo, $fileInfo]; - } - - $stub->attr += $fileInfo; - $a = Caster::castObject($obj, $class, $hasDebugInfo); - - try { - while ($i--) { - if (!empty($this->casters[$p = $parents[$i]])) { - foreach ($this->casters[$p] as $callback) { - $a = $callback($obj, $a, $stub, $isNested, $this->filter); - } - } - } - } catch (\Exception $e) { - $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a; - } - - return $a; - } - - /** - * Casts a resource to an array representation. - * - * @param bool $isNested True if the object is nested in the dumped structure - * - * @return array The resource casted as array - */ - protected function castResource(Stub $stub, bool $isNested) - { - $a = []; - $res = $stub->value; - $type = $stub->class; - - try { - if (!empty($this->casters[':'.$type])) { - foreach ($this->casters[':'.$type] as $callback) { - $a = $callback($res, $a, $stub, $isNested, $this->filter); - } - } - } catch (\Exception $e) { - $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a; - } - - return $a; - } -} diff --git a/vendor/symfony/var-dumper/Cloner/ClonerInterface.php b/vendor/symfony/var-dumper/Cloner/ClonerInterface.php deleted file mode 100644 index 7ed287a..0000000 --- a/vendor/symfony/var-dumper/Cloner/ClonerInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -/** - * @author Nicolas Grekas - */ -interface ClonerInterface -{ - /** - * Clones a PHP variable. - * - * @param mixed $var Any PHP variable - * - * @return Data The cloned variable represented by a Data object - */ - public function cloneVar($var); -} diff --git a/vendor/symfony/var-dumper/Cloner/Cursor.php b/vendor/symfony/var-dumper/Cloner/Cursor.php deleted file mode 100644 index 5b0542f..0000000 --- a/vendor/symfony/var-dumper/Cloner/Cursor.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -/** - * Represents the current state of a dumper while dumping. - * - * @author Nicolas Grekas - */ -class Cursor -{ - const HASH_INDEXED = Stub::ARRAY_INDEXED; - const HASH_ASSOC = Stub::ARRAY_ASSOC; - const HASH_OBJECT = Stub::TYPE_OBJECT; - const HASH_RESOURCE = Stub::TYPE_RESOURCE; - - public $depth = 0; - public $refIndex = 0; - public $softRefTo = 0; - public $softRefCount = 0; - public $softRefHandle = 0; - public $hardRefTo = 0; - public $hardRefCount = 0; - public $hardRefHandle = 0; - public $hashType; - public $hashKey; - public $hashKeyIsBinary; - public $hashIndex = 0; - public $hashLength = 0; - public $hashCut = 0; - public $stop = false; - public $attr = []; - public $skipChildren = false; -} diff --git a/vendor/symfony/var-dumper/Cloner/Data.php b/vendor/symfony/var-dumper/Cloner/Data.php deleted file mode 100644 index e907197..0000000 --- a/vendor/symfony/var-dumper/Cloner/Data.php +++ /dev/null @@ -1,451 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -use Symfony\Component\VarDumper\Caster\Caster; -use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; - -/** - * @author Nicolas Grekas - */ -class Data implements \ArrayAccess, \Countable, \IteratorAggregate -{ - private $data; - private $position = 0; - private $key = 0; - private $maxDepth = 20; - private $maxItemsPerDepth = -1; - private $useRefHandles = -1; - private $context = []; - - /** - * @param array $data An array as returned by ClonerInterface::cloneVar() - */ - public function __construct(array $data) - { - $this->data = $data; - } - - /** - * @return string|null The type of the value - */ - public function getType() - { - $item = $this->data[$this->position][$this->key]; - - if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { - $item = $item->value; - } - if (!$item instanceof Stub) { - return \gettype($item); - } - if (Stub::TYPE_STRING === $item->type) { - return 'string'; - } - if (Stub::TYPE_ARRAY === $item->type) { - return 'array'; - } - if (Stub::TYPE_OBJECT === $item->type) { - return $item->class; - } - if (Stub::TYPE_RESOURCE === $item->type) { - return $item->class.' resource'; - } - - return null; - } - - /** - * @param array|bool $recursive Whether values should be resolved recursively or not - * - * @return string|int|float|bool|array|Data[]|null A native representation of the original value - */ - public function getValue($recursive = false) - { - $item = $this->data[$this->position][$this->key]; - - if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { - $item = $item->value; - } - if (!($item = $this->getStub($item)) instanceof Stub) { - return $item; - } - if (Stub::TYPE_STRING === $item->type) { - return $item->value; - } - - $children = $item->position ? $this->data[$item->position] : []; - - foreach ($children as $k => $v) { - if ($recursive && !($v = $this->getStub($v)) instanceof Stub) { - continue; - } - $children[$k] = clone $this; - $children[$k]->key = $k; - $children[$k]->position = $item->position; - - if ($recursive) { - if (Stub::TYPE_REF === $v->type && ($v = $this->getStub($v->value)) instanceof Stub) { - $recursive = (array) $recursive; - if (isset($recursive[$v->position])) { - continue; - } - $recursive[$v->position] = true; - } - $children[$k] = $children[$k]->getValue($recursive); - } - } - - return $children; - } - - /** - * @return int - */ - public function count() - { - return \count($this->getValue()); - } - - /** - * @return \Traversable - */ - public function getIterator() - { - if (!\is_array($value = $this->getValue())) { - throw new \LogicException(sprintf('%s object holds non-iterable type "%s".', self::class, \gettype($value))); - } - - yield from $value; - } - - public function __get(string $key) - { - if (null !== $data = $this->seek($key)) { - $item = $this->getStub($data->data[$data->position][$data->key]); - - return $item instanceof Stub || [] === $item ? $data : $item; - } - - return null; - } - - /** - * @return bool - */ - public function __isset(string $key) - { - return null !== $this->seek($key); - } - - /** - * @return bool - */ - public function offsetExists($key) - { - return $this->__isset($key); - } - - public function offsetGet($key) - { - return $this->__get($key); - } - - public function offsetSet($key, $value) - { - throw new \BadMethodCallException(self::class.' objects are immutable.'); - } - - public function offsetUnset($key) - { - throw new \BadMethodCallException(self::class.' objects are immutable.'); - } - - /** - * @return string - */ - public function __toString() - { - $value = $this->getValue(); - - if (!\is_array($value)) { - return (string) $value; - } - - return sprintf('%s (count=%d)', $this->getType(), \count($value)); - } - - /** - * Returns a depth limited clone of $this. - * - * @return static - */ - public function withMaxDepth(int $maxDepth) - { - $data = clone $this; - $data->maxDepth = (int) $maxDepth; - - return $data; - } - - /** - * Limits the number of elements per depth level. - * - * @return static - */ - public function withMaxItemsPerDepth(int $maxItemsPerDepth) - { - $data = clone $this; - $data->maxItemsPerDepth = (int) $maxItemsPerDepth; - - return $data; - } - - /** - * Enables/disables objects' identifiers tracking. - * - * @param bool $useRefHandles False to hide global ref. handles - * - * @return static - */ - public function withRefHandles(bool $useRefHandles) - { - $data = clone $this; - $data->useRefHandles = $useRefHandles ? -1 : 0; - - return $data; - } - - /** - * @return static - */ - public function withContext(array $context) - { - $data = clone $this; - $data->context = $context; - - return $data; - } - - /** - * Seeks to a specific key in nested data structures. - * - * @param string|int $key The key to seek to - * - * @return static|null Null if the key is not set - */ - public function seek($key) - { - $item = $this->data[$this->position][$this->key]; - - if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { - $item = $item->value; - } - if (!($item = $this->getStub($item)) instanceof Stub || !$item->position) { - return null; - } - $keys = [$key]; - - switch ($item->type) { - case Stub::TYPE_OBJECT: - $keys[] = Caster::PREFIX_DYNAMIC.$key; - $keys[] = Caster::PREFIX_PROTECTED.$key; - $keys[] = Caster::PREFIX_VIRTUAL.$key; - $keys[] = "\0$item->class\0$key"; - // no break - case Stub::TYPE_ARRAY: - case Stub::TYPE_RESOURCE: - break; - default: - return null; - } - - $data = null; - $children = $this->data[$item->position]; - - foreach ($keys as $key) { - if (isset($children[$key]) || \array_key_exists($key, $children)) { - $data = clone $this; - $data->key = $key; - $data->position = $item->position; - break; - } - } - - return $data; - } - - /** - * Dumps data with a DumperInterface dumper. - */ - public function dump(DumperInterface $dumper) - { - $refs = [0]; - $cursor = new Cursor(); - - if ($cursor->attr = $this->context[SourceContextProvider::class] ?? []) { - $cursor->attr['if_links'] = true; - $cursor->hashType = -1; - $dumper->dumpScalar($cursor, 'default', '^'); - $cursor->attr = ['if_links' => true]; - $dumper->dumpScalar($cursor, 'default', ' '); - $cursor->hashType = 0; - } - - $this->dumpItem($dumper, $cursor, $refs, $this->data[$this->position][$this->key]); - } - - /** - * Depth-first dumping of items. - * - * @param mixed $item A Stub object or the original value being dumped - */ - private function dumpItem(DumperInterface $dumper, Cursor $cursor, array &$refs, $item) - { - $cursor->refIndex = 0; - $cursor->softRefTo = $cursor->softRefHandle = $cursor->softRefCount = 0; - $cursor->hardRefTo = $cursor->hardRefHandle = $cursor->hardRefCount = 0; - $firstSeen = true; - - if (!$item instanceof Stub) { - $cursor->attr = []; - $type = \gettype($item); - if ($item && 'array' === $type) { - $item = $this->getStub($item); - } - } elseif (Stub::TYPE_REF === $item->type) { - if ($item->handle) { - if (!isset($refs[$r = $item->handle - (PHP_INT_MAX >> 1)])) { - $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0]; - } else { - $firstSeen = false; - } - $cursor->hardRefTo = $refs[$r]; - $cursor->hardRefHandle = $this->useRefHandles & $item->handle; - $cursor->hardRefCount = $item->refCount; - } - $cursor->attr = $item->attr; - $type = $item->class ?: \gettype($item->value); - $item = $this->getStub($item->value); - } - if ($item instanceof Stub) { - if ($item->refCount) { - if (!isset($refs[$r = $item->handle])) { - $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0]; - } else { - $firstSeen = false; - } - $cursor->softRefTo = $refs[$r]; - } - $cursor->softRefHandle = $this->useRefHandles & $item->handle; - $cursor->softRefCount = $item->refCount; - $cursor->attr = $item->attr; - $cut = $item->cut; - - if ($item->position && $firstSeen) { - $children = $this->data[$item->position]; - - if ($cursor->stop) { - if ($cut >= 0) { - $cut += \count($children); - } - $children = []; - } - } else { - $children = []; - } - switch ($item->type) { - case Stub::TYPE_STRING: - $dumper->dumpString($cursor, $item->value, Stub::STRING_BINARY === $item->class, $cut); - break; - - case Stub::TYPE_ARRAY: - $item = clone $item; - $item->type = $item->class; - $item->class = $item->value; - // no break - case Stub::TYPE_OBJECT: - case Stub::TYPE_RESOURCE: - $withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth; - $dumper->enterHash($cursor, $item->type, $item->class, $withChildren); - if ($withChildren) { - if ($cursor->skipChildren) { - $withChildren = false; - $cut = -1; - } else { - $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class); - } - } elseif ($children && 0 <= $cut) { - $cut += \count($children); - } - $cursor->skipChildren = false; - $dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut); - break; - - default: - throw new \RuntimeException(sprintf('Unexpected Stub type: %s', $item->type)); - } - } elseif ('array' === $type) { - $dumper->enterHash($cursor, Cursor::HASH_INDEXED, 0, false); - $dumper->leaveHash($cursor, Cursor::HASH_INDEXED, 0, false, 0); - } elseif ('string' === $type) { - $dumper->dumpString($cursor, $item, false, 0); - } else { - $dumper->dumpScalar($cursor, $type, $item); - } - } - - /** - * Dumps children of hash structures. - * - * @return int The final number of removed items - */ - private function dumpChildren(DumperInterface $dumper, Cursor $parentCursor, array &$refs, array $children, int $hashCut, int $hashType, bool $dumpKeys): int - { - $cursor = clone $parentCursor; - ++$cursor->depth; - $cursor->hashType = $hashType; - $cursor->hashIndex = 0; - $cursor->hashLength = \count($children); - $cursor->hashCut = $hashCut; - foreach ($children as $key => $child) { - $cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key); - $cursor->hashKey = $dumpKeys ? $key : null; - $this->dumpItem($dumper, $cursor, $refs, $child); - if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) { - $parentCursor->stop = true; - - return $hashCut >= 0 ? $hashCut + $cursor->hashLength - $cursor->hashIndex : $hashCut; - } - } - - return $hashCut; - } - - private function getStub($item) - { - if (!$item || !\is_array($item)) { - return $item; - } - - $stub = new Stub(); - $stub->type = Stub::TYPE_ARRAY; - foreach ($item as $stub->class => $stub->position) { - } - if (isset($item[0])) { - $stub->cut = $item[0]; - } - $stub->value = $stub->cut + ($stub->position ? \count($this->data[$stub->position]) : 0); - - return $stub; - } -} diff --git a/vendor/symfony/var-dumper/Cloner/DumperInterface.php b/vendor/symfony/var-dumper/Cloner/DumperInterface.php deleted file mode 100644 index 6d60b72..0000000 --- a/vendor/symfony/var-dumper/Cloner/DumperInterface.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -/** - * DumperInterface used by Data objects. - * - * @author Nicolas Grekas - */ -interface DumperInterface -{ - /** - * Dumps a scalar value. - * - * @param string $type The PHP type of the value being dumped - * @param string|int|float|bool $value The scalar value being dumped - */ - public function dumpScalar(Cursor $cursor, string $type, $value); - - /** - * Dumps a string. - * - * @param string $str The string being dumped - * @param bool $bin Whether $str is UTF-8 or binary encoded - * @param int $cut The number of characters $str has been cut by - */ - public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut); - - /** - * Dumps while entering an hash. - * - * @param int $type A Cursor::HASH_* const for the type of hash - * @param string|int $class The object class, resource type or array count - * @param bool $hasChild When the dump of the hash has child item - */ - public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild); - - /** - * Dumps while leaving an hash. - * - * @param int $type A Cursor::HASH_* const for the type of hash - * @param string|int $class The object class, resource type or array count - * @param bool $hasChild When the dump of the hash has child item - * @param int $cut The number of items the hash has been cut by - */ - public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut); -} diff --git a/vendor/symfony/var-dumper/Cloner/Stub.php b/vendor/symfony/var-dumper/Cloner/Stub.php deleted file mode 100644 index 7e9eb6d..0000000 --- a/vendor/symfony/var-dumper/Cloner/Stub.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -/** - * Represents the main properties of a PHP variable. - * - * @author Nicolas Grekas - */ -class Stub -{ - const TYPE_REF = 1; - const TYPE_STRING = 2; - const TYPE_ARRAY = 3; - const TYPE_OBJECT = 4; - const TYPE_RESOURCE = 5; - - const STRING_BINARY = 1; - const STRING_UTF8 = 2; - - const ARRAY_ASSOC = 1; - const ARRAY_INDEXED = 2; - - public $type = self::TYPE_REF; - public $class = ''; - public $value; - public $cut = 0; - public $handle = 0; - public $refCount = 0; - public $position = 0; - public $attr = []; - - private static $defaultProperties = []; - - /** - * @internal - */ - public function __sleep(): array - { - $properties = []; - - if (!isset(self::$defaultProperties[$c = \get_class($this)])) { - self::$defaultProperties[$c] = get_class_vars($c); - - foreach ((new \ReflectionClass($c))->getStaticProperties() as $k => $v) { - unset(self::$defaultProperties[$c][$k]); - } - } - - foreach (self::$defaultProperties[$c] as $k => $v) { - if ($this->$k !== $v) { - $properties[] = $k; - } - } - - return $properties; - } -} diff --git a/vendor/symfony/var-dumper/Cloner/VarCloner.php b/vendor/symfony/var-dumper/Cloner/VarCloner.php deleted file mode 100644 index 4c653d6..0000000 --- a/vendor/symfony/var-dumper/Cloner/VarCloner.php +++ /dev/null @@ -1,285 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Cloner; - -/** - * @author Nicolas Grekas - */ -class VarCloner extends AbstractCloner -{ - private static $gid; - private static $arrayCache = []; - - /** - * {@inheritdoc} - */ - protected function doClone($var) - { - $len = 1; // Length of $queue - $pos = 0; // Number of cloned items past the minimum depth - $refsCounter = 0; // Hard references counter - $queue = [[$var]]; // This breadth-first queue is the return value - $indexedArrays = []; // Map of queue indexes that hold numerically indexed arrays - $hardRefs = []; // Map of original zval ids to stub objects - $objRefs = []; // Map of original object handles to their stub object counterpart - $objects = []; // Keep a ref to objects to ensure their handle cannot be reused while cloning - $resRefs = []; // Map of original resource handles to their stub object counterpart - $values = []; // Map of stub objects' ids to original values - $maxItems = $this->maxItems; - $maxString = $this->maxString; - $minDepth = $this->minDepth; - $currentDepth = 0; // Current tree depth - $currentDepthFinalIndex = 0; // Final $queue index for current tree depth - $minimumDepthReached = 0 === $minDepth; // Becomes true when minimum tree depth has been reached - $cookie = (object) []; // Unique object used to detect hard references - $a = null; // Array cast for nested structures - $stub = null; // Stub capturing the main properties of an original item value - // or null if the original value is used directly - - if (!$gid = self::$gid) { - $gid = self::$gid = uniqid(mt_rand(), true); // Unique string used to detect the special $GLOBALS variable - } - $arrayStub = new Stub(); - $arrayStub->type = Stub::TYPE_ARRAY; - $fromObjCast = false; - - for ($i = 0; $i < $len; ++$i) { - // Detect when we move on to the next tree depth - if ($i > $currentDepthFinalIndex) { - ++$currentDepth; - $currentDepthFinalIndex = $len - 1; - if ($currentDepth >= $minDepth) { - $minimumDepthReached = true; - } - } - - $refs = $vals = $queue[$i]; - foreach ($vals as $k => $v) { - // $v is the original value or a stub object in case of hard references - - if (\PHP_VERSION_ID >= 70400) { - $zvalIsRef = null !== \ReflectionReference::fromArrayElement($vals, $k); - } else { - $refs[$k] = $cookie; - $zvalIsRef = $vals[$k] === $cookie; - } - - if ($zvalIsRef) { - $vals[$k] = &$stub; // Break hard references to make $queue completely - unset($stub); // independent from the original structure - if ($v instanceof Stub && isset($hardRefs[spl_object_id($v)])) { - $vals[$k] = $refs[$k] = $v; - if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) { - ++$v->value->refCount; - } - ++$v->refCount; - continue; - } - $refs[$k] = $vals[$k] = new Stub(); - $refs[$k]->value = $v; - $h = spl_object_id($refs[$k]); - $hardRefs[$h] = &$refs[$k]; - $values[$h] = $v; - $vals[$k]->handle = ++$refsCounter; - } - // Create $stub when the original value $v can not be used directly - // If $v is a nested structure, put that structure in array $a - switch (true) { - case null === $v: - case \is_bool($v): - case \is_int($v): - case \is_float($v): - continue 2; - - case \is_string($v): - if ('' === $v) { - continue 2; - } - if (!preg_match('//u', $v)) { - $stub = new Stub(); - $stub->type = Stub::TYPE_STRING; - $stub->class = Stub::STRING_BINARY; - if (0 <= $maxString && 0 < $cut = \strlen($v) - $maxString) { - $stub->cut = $cut; - $stub->value = substr($v, 0, -$cut); - } else { - $stub->value = $v; - } - } elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) { - $stub = new Stub(); - $stub->type = Stub::TYPE_STRING; - $stub->class = Stub::STRING_UTF8; - $stub->cut = $cut; - $stub->value = mb_substr($v, 0, $maxString, 'UTF-8'); - } else { - continue 2; - } - $a = null; - break; - - case \is_array($v): - if (!$v) { - continue 2; - } - $stub = $arrayStub; - $stub->class = Stub::ARRAY_INDEXED; - - $j = -1; - foreach ($v as $gk => $gv) { - if ($gk !== ++$j) { - $stub->class = Stub::ARRAY_ASSOC; - break; - } - } - $a = $v; - - if (Stub::ARRAY_ASSOC === $stub->class) { - // Copies of $GLOBALS have very strange behavior, - // let's detect them with some black magic - $a[$gid] = true; - - // Happens with copies of $GLOBALS - if (isset($v[$gid])) { - unset($v[$gid]); - $a = []; - foreach ($v as $gk => &$gv) { - $a[$gk] = &$gv; - } - unset($gv); - } else { - $a = $v; - } - } - break; - - case \is_object($v): - case $v instanceof \__PHP_Incomplete_Class: - if (empty($objRefs[$h = spl_object_id($v)])) { - $stub = new Stub(); - $stub->type = Stub::TYPE_OBJECT; - $stub->class = \get_class($v); - $stub->value = $v; - $stub->handle = $h; - $a = $this->castObject($stub, 0 < $i); - if ($v !== $stub->value) { - if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) { - break; - } - $stub->handle = $h = spl_object_id($stub->value); - } - $stub->value = null; - if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) { - $stub->cut = \count($a); - $a = null; - } - } - if (empty($objRefs[$h])) { - $objRefs[$h] = $stub; - $objects[] = $v; - } else { - $stub = $objRefs[$h]; - ++$stub->refCount; - $a = null; - } - break; - - default: // resource - if (empty($resRefs[$h = (int) $v])) { - $stub = new Stub(); - $stub->type = Stub::TYPE_RESOURCE; - if ('Unknown' === $stub->class = @get_resource_type($v)) { - $stub->class = 'Closed'; - } - $stub->value = $v; - $stub->handle = $h; - $a = $this->castResource($stub, 0 < $i); - $stub->value = null; - if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) { - $stub->cut = \count($a); - $a = null; - } - } - if (empty($resRefs[$h])) { - $resRefs[$h] = $stub; - } else { - $stub = $resRefs[$h]; - ++$stub->refCount; - $a = null; - } - break; - } - - if ($a) { - if (!$minimumDepthReached || 0 > $maxItems) { - $queue[$len] = $a; - $stub->position = $len++; - } elseif ($pos < $maxItems) { - if ($maxItems < $pos += \count($a)) { - $a = \array_slice($a, 0, $maxItems - $pos); - if ($stub->cut >= 0) { - $stub->cut += $pos - $maxItems; - } - } - $queue[$len] = $a; - $stub->position = $len++; - } elseif ($stub->cut >= 0) { - $stub->cut += \count($a); - $stub->position = 0; - } - } - - if ($arrayStub === $stub) { - if ($arrayStub->cut) { - $stub = [$arrayStub->cut, $arrayStub->class => $arrayStub->position]; - $arrayStub->cut = 0; - } elseif (isset(self::$arrayCache[$arrayStub->class][$arrayStub->position])) { - $stub = self::$arrayCache[$arrayStub->class][$arrayStub->position]; - } else { - self::$arrayCache[$arrayStub->class][$arrayStub->position] = $stub = [$arrayStub->class => $arrayStub->position]; - } - } - - if ($zvalIsRef) { - $refs[$k]->value = $stub; - } else { - $vals[$k] = $stub; - } - } - - if ($fromObjCast) { - $fromObjCast = false; - $refs = $vals; - $vals = []; - $j = -1; - foreach ($queue[$i] as $k => $v) { - foreach ([$k => true] as $gk => $gv) { - } - if ($gk !== $k) { - $vals = (object) $vals; - $vals->{$k} = $refs[++$j]; - $vals = (array) $vals; - } else { - $vals[$k] = $refs[++$j]; - } - } - } - - $queue[$i] = $vals; - } - - foreach ($values as $h => $v) { - $hardRefs[$h] = $v; - } - - return $queue; - } -} diff --git a/vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php b/vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php deleted file mode 100644 index dc77d03..0000000 --- a/vendor/symfony/var-dumper/Command/Descriptor/CliDescriptor.php +++ /dev/null @@ -1,88 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Command\Descriptor; - -use Symfony\Component\Console\Formatter\OutputFormatterStyle; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Dumper\CliDumper; - -/** - * Describe collected data clones for cli output. - * - * @author Maxime Steinhausser - * - * @final - */ -class CliDescriptor implements DumpDescriptorInterface -{ - private $dumper; - private $lastIdentifier; - private $supportsHref; - - public function __construct(CliDumper $dumper) - { - $this->dumper = $dumper; - $this->supportsHref = method_exists(OutputFormatterStyle::class, 'setHref'); - } - - public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void - { - $io = $output instanceof SymfonyStyle ? $output : new SymfonyStyle(new ArrayInput([]), $output); - $this->dumper->setColors($output->isDecorated()); - - $rows = [['date', date('r', $context['timestamp'])]]; - $lastIdentifier = $this->lastIdentifier; - $this->lastIdentifier = $clientId; - - $section = "Received from client #$clientId"; - if (isset($context['request'])) { - $request = $context['request']; - $this->lastIdentifier = $request['identifier']; - $section = sprintf('%s %s', $request['method'], $request['uri']); - if ($controller = $request['controller']) { - $rows[] = ['controller', rtrim($this->dumper->dump($controller, true), "\n")]; - } - } elseif (isset($context['cli'])) { - $this->lastIdentifier = $context['cli']['identifier']; - $section = '$ '.$context['cli']['command_line']; - } - - if ($this->lastIdentifier !== $lastIdentifier) { - $io->section($section); - } - - if (isset($context['source'])) { - $source = $context['source']; - $sourceInfo = sprintf('%s on line %d', $source['name'], $source['line']); - $fileLink = $source['file_link'] ?? null; - if ($this->supportsHref && $fileLink) { - $sourceInfo = sprintf('%s', $fileLink, $sourceInfo); - } - $rows[] = ['source', $sourceInfo]; - $file = $source['file_relative'] ?? $source['file']; - $rows[] = ['file', $file]; - } - - $io->table([], $rows); - - if (!$this->supportsHref && isset($fileLink)) { - $io->writeln(['Open source in your IDE/browser:', $fileLink]); - $io->newLine(); - } - - $this->dumper->dump($data); - $io->newLine(); - } -} diff --git a/vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php b/vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php deleted file mode 100644 index 267d27b..0000000 --- a/vendor/symfony/var-dumper/Command/Descriptor/DumpDescriptorInterface.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Command\Descriptor; - -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\VarDumper\Cloner\Data; - -/** - * @author Maxime Steinhausser - */ -interface DumpDescriptorInterface -{ - public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void; -} diff --git a/vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php b/vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php deleted file mode 100644 index 35a203b..0000000 --- a/vendor/symfony/var-dumper/Command/Descriptor/HtmlDescriptor.php +++ /dev/null @@ -1,119 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Command\Descriptor; - -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; - -/** - * Describe collected data clones for html output. - * - * @author Maxime Steinhausser - * - * @final - */ -class HtmlDescriptor implements DumpDescriptorInterface -{ - private $dumper; - private $initialized = false; - - public function __construct(HtmlDumper $dumper) - { - $this->dumper = $dumper; - } - - public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void - { - if (!$this->initialized) { - $styles = file_get_contents(__DIR__.'/../../Resources/css/htmlDescriptor.css'); - $scripts = file_get_contents(__DIR__.'/../../Resources/js/htmlDescriptor.js'); - $output->writeln(""); - $this->initialized = true; - } - - $title = '-'; - if (isset($context['request'])) { - $request = $context['request']; - $controller = "{$this->dumper->dump($request['controller'], true, ['maxDepth' => 0])}"; - $title = sprintf('%s %s', $request['method'], $uri = $request['uri'], $uri); - $dedupIdentifier = $request['identifier']; - } elseif (isset($context['cli'])) { - $title = '$ '.$context['cli']['command_line']; - $dedupIdentifier = $context['cli']['identifier']; - } else { - $dedupIdentifier = uniqid('', true); - } - - $sourceDescription = ''; - if (isset($context['source'])) { - $source = $context['source']; - $projectDir = $source['project_dir'] ?? null; - $sourceDescription = sprintf('%s on line %d', $source['name'], $source['line']); - if (isset($source['file_link'])) { - $sourceDescription = sprintf('%s', $source['file_link'], $sourceDescription); - } - } - - $isoDate = $this->extractDate($context, 'c'); - $tags = array_filter([ - 'controller' => $controller ?? null, - 'project dir' => $projectDir ?? null, - ]); - - $output->writeln(<< -
    -
    -

    $title

    - -
    - {$this->renderTags($tags)} -
    -
    -

    - $sourceDescription -

    - {$this->dumper->dump($data, true)} -
    - -HTML - ); - } - - private function extractDate(array $context, string $format = 'r'): string - { - return date($format, $context['timestamp']); - } - - private function renderTags(array $tags): string - { - if (!$tags) { - return ''; - } - - $renderedTags = ''; - foreach ($tags as $key => $value) { - $renderedTags .= sprintf('
  • %s%s
  • ', $key, $value); - } - - return << -
      - $renderedTags -
    - -HTML; - } -} diff --git a/vendor/symfony/var-dumper/Command/ServerDumpCommand.php b/vendor/symfony/var-dumper/Command/ServerDumpCommand.php deleted file mode 100644 index c8a61da..0000000 --- a/vendor/symfony/var-dumper/Command/ServerDumpCommand.php +++ /dev/null @@ -1,99 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Command\Descriptor\CliDescriptor; -use Symfony\Component\VarDumper\Command\Descriptor\DumpDescriptorInterface; -use Symfony\Component\VarDumper\Command\Descriptor\HtmlDescriptor; -use Symfony\Component\VarDumper\Dumper\CliDumper; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; -use Symfony\Component\VarDumper\Server\DumpServer; - -/** - * Starts a dump server to collect and output dumps on a single place with multiple formats support. - * - * @author Maxime Steinhausser - * - * @final - */ -class ServerDumpCommand extends Command -{ - protected static $defaultName = 'server:dump'; - - private $server; - - /** @var DumpDescriptorInterface[] */ - private $descriptors; - - public function __construct(DumpServer $server, array $descriptors = []) - { - $this->server = $server; - $this->descriptors = $descriptors + [ - 'cli' => new CliDescriptor(new CliDumper()), - 'html' => new HtmlDescriptor(new HtmlDumper()), - ]; - - parent::__construct(); - } - - protected function configure() - { - $availableFormats = implode(', ', array_keys($this->descriptors)); - - $this - ->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format (%s)', $availableFormats), 'cli') - ->setDescription('Starts a dump server that collects and displays dumps in a single place') - ->setHelp(<<<'EOF' -%command.name% starts a dump server that collects and displays -dumps in a single place for debugging you application: - - php %command.full_name% - -You can consult dumped data in HTML format in your browser by providing the --format=html option -and redirecting the output to a file: - - php %command.full_name% --format="html" > dump.html - -EOF - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - $format = $input->getOption('format'); - - if (!$descriptor = $this->descriptors[$format] ?? null) { - throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $format)); - } - - $errorIo = $io->getErrorStyle(); - $errorIo->title('Symfony Var Dumper Server'); - - $this->server->start(); - - $errorIo->success(sprintf('Server listening on %s', $this->server->getHost())); - $errorIo->comment('Quit the server with CONTROL-C.'); - - $this->server->listen(function (Data $data, array $context, int $clientId) use ($descriptor, $io) { - $descriptor->describe($io, $data, $context, $clientId); - }); - } -} diff --git a/vendor/symfony/var-dumper/Dumper/AbstractDumper.php b/vendor/symfony/var-dumper/Dumper/AbstractDumper.php deleted file mode 100644 index 1a00038..0000000 --- a/vendor/symfony/var-dumper/Dumper/AbstractDumper.php +++ /dev/null @@ -1,204 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper; - -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Cloner\DumperInterface; - -/** - * Abstract mechanism for dumping a Data object. - * - * @author Nicolas Grekas - */ -abstract class AbstractDumper implements DataDumperInterface, DumperInterface -{ - const DUMP_LIGHT_ARRAY = 1; - const DUMP_STRING_LENGTH = 2; - const DUMP_COMMA_SEPARATOR = 4; - const DUMP_TRAILING_COMMA = 8; - - public static $defaultOutput = 'php://output'; - - protected $line = ''; - protected $lineDumper; - protected $outputStream; - protected $decimalPoint; // This is locale dependent - protected $indentPad = ' '; - protected $flags; - - private $charset = ''; - - /** - * @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput - * @param string|null $charset The default character encoding to use for non-UTF8 strings - * @param int $flags A bit field of static::DUMP_* constants to fine tune dumps representation - */ - public function __construct($output = null, string $charset = null, int $flags = 0) - { - $this->flags = $flags; - $this->setCharset($charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8'); - $this->decimalPoint = localeconv(); - $this->decimalPoint = $this->decimalPoint['decimal_point']; - $this->setOutput($output ?: static::$defaultOutput); - if (!$output && \is_string(static::$defaultOutput)) { - static::$defaultOutput = $this->outputStream; - } - } - - /** - * Sets the output destination of the dumps. - * - * @param callable|resource|string $output A line dumper callable, an opened stream or an output path - * - * @return callable|resource|string The previous output destination - */ - public function setOutput($output) - { - $prev = null !== $this->outputStream ? $this->outputStream : $this->lineDumper; - - if (\is_callable($output)) { - $this->outputStream = null; - $this->lineDumper = $output; - } else { - if (\is_string($output)) { - $output = fopen($output, 'wb'); - } - $this->outputStream = $output; - $this->lineDumper = [$this, 'echoLine']; - } - - return $prev; - } - - /** - * Sets the default character encoding to use for non-UTF8 strings. - * - * @return string The previous charset - */ - public function setCharset(string $charset) - { - $prev = $this->charset; - - $charset = strtoupper($charset); - $charset = null === $charset || 'UTF-8' === $charset || 'UTF8' === $charset ? 'CP1252' : $charset; - - $this->charset = $charset; - - return $prev; - } - - /** - * Sets the indentation pad string. - * - * @param string $pad A string that will be prepended to dumped lines, repeated by nesting level - * - * @return string The previous indent pad - */ - public function setIndentPad(string $pad) - { - $prev = $this->indentPad; - $this->indentPad = $pad; - - return $prev; - } - - /** - * Dumps a Data object. - * - * @param callable|resource|string|true|null $output A line dumper callable, an opened stream, an output path or true to return the dump - * - * @return string|null The dump as string when $output is true - */ - public function dump(Data $data, $output = null) - { - $this->decimalPoint = localeconv(); - $this->decimalPoint = $this->decimalPoint['decimal_point']; - - if ($locale = $this->flags & (self::DUMP_COMMA_SEPARATOR | self::DUMP_TRAILING_COMMA) ? setlocale(LC_NUMERIC, 0) : null) { - setlocale(LC_NUMERIC, 'C'); - } - - if ($returnDump = true === $output) { - $output = fopen('php://memory', 'r+b'); - } - if ($output) { - $prevOutput = $this->setOutput($output); - } - try { - $data->dump($this); - $this->dumpLine(-1); - - if ($returnDump) { - $result = stream_get_contents($output, -1, 0); - fclose($output); - - return $result; - } - } finally { - if ($output) { - $this->setOutput($prevOutput); - } - if ($locale) { - setlocale(LC_NUMERIC, $locale); - } - } - - return null; - } - - /** - * Dumps the current line. - * - * @param int $depth The recursive depth in the dumped structure for the line being dumped, - * or -1 to signal the end-of-dump to the line dumper callable - */ - protected function dumpLine(int $depth) - { - ($this->lineDumper)($this->line, $depth, $this->indentPad); - $this->line = ''; - } - - /** - * Generic line dumper callback. - */ - protected function echoLine(string $line, int $depth, string $indentPad) - { - if (-1 !== $depth) { - fwrite($this->outputStream, str_repeat($indentPad, $depth).$line."\n"); - } - } - - /** - * Converts a non-UTF-8 string to UTF-8. - * - * @return string|null The string converted to UTF-8 - */ - protected function utf8Encode(?string $s) - { - if (null === $s || preg_match('//u', $s)) { - return $s; - } - - if (!\function_exists('iconv')) { - throw new \RuntimeException('Unable to convert a non-UTF-8 string to UTF-8: required function iconv() does not exist. You should install ext-iconv or symfony/polyfill-iconv.'); - } - - if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) { - return $c; - } - if ('CP1252' !== $this->charset && false !== $c = @iconv('CP1252', 'UTF-8', $s)) { - return $c; - } - - return iconv('CP850', 'UTF-8', $s); - } -} diff --git a/vendor/symfony/var-dumper/Dumper/CliDumper.php b/vendor/symfony/var-dumper/Dumper/CliDumper.php deleted file mode 100644 index 326ce1d..0000000 --- a/vendor/symfony/var-dumper/Dumper/CliDumper.php +++ /dev/null @@ -1,636 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper; - -use Symfony\Component\VarDumper\Cloner\Cursor; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * CliDumper dumps variables for command line output. - * - * @author Nicolas Grekas - */ -class CliDumper extends AbstractDumper -{ - public static $defaultColors; - public static $defaultOutput = 'php://stdout'; - - protected $colors; - protected $maxStringWidth = 0; - protected $styles = [ - // See http://en.wikipedia.org/wiki/ANSI_escape_code#graphics - 'default' => '0;38;5;208', - 'num' => '1;38;5;38', - 'const' => '1;38;5;208', - 'str' => '1;38;5;113', - 'note' => '38;5;38', - 'ref' => '38;5;247', - 'public' => '', - 'protected' => '', - 'private' => '', - 'meta' => '38;5;170', - 'key' => '38;5;113', - 'index' => '38;5;38', - ]; - - protected static $controlCharsRx = '/[\x00-\x1F\x7F]+/'; - protected static $controlCharsMap = [ - "\t" => '\t', - "\n" => '\n', - "\v" => '\v', - "\f" => '\f', - "\r" => '\r', - "\033" => '\e', - ]; - - protected $collapseNextHash = false; - protected $expandNextHash = false; - - private $displayOptions = [ - 'fileLinkFormat' => null, - ]; - - private $handlesHrefGracefully; - - /** - * {@inheritdoc} - */ - public function __construct($output = null, string $charset = null, int $flags = 0) - { - parent::__construct($output, $charset, $flags); - - if ('\\' === \DIRECTORY_SEPARATOR && !$this->isWindowsTrueColor()) { - // Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI - $this->setStyles([ - 'default' => '31', - 'num' => '1;34', - 'const' => '1;31', - 'str' => '1;32', - 'note' => '34', - 'ref' => '1;30', - 'meta' => '35', - 'key' => '32', - 'index' => '34', - ]); - } - - $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l'; - } - - /** - * Enables/disables colored output. - */ - public function setColors(bool $colors) - { - $this->colors = $colors; - } - - /** - * Sets the maximum number of characters per line for dumped strings. - */ - public function setMaxStringWidth(int $maxStringWidth) - { - $this->maxStringWidth = $maxStringWidth; - } - - /** - * Configures styles. - * - * @param array $styles A map of style names to style definitions - */ - public function setStyles(array $styles) - { - $this->styles = $styles + $this->styles; - } - - /** - * Configures display options. - * - * @param array $displayOptions A map of display options to customize the behavior - */ - public function setDisplayOptions(array $displayOptions) - { - $this->displayOptions = $displayOptions + $this->displayOptions; - } - - /** - * {@inheritdoc} - */ - public function dumpScalar(Cursor $cursor, string $type, $value) - { - $this->dumpKey($cursor); - - $style = 'const'; - $attr = $cursor->attr; - - switch ($type) { - case 'default': - $style = 'default'; - break; - - case 'integer': - $style = 'num'; - break; - - case 'double': - $style = 'num'; - - switch (true) { - case INF === $value: $value = 'INF'; break; - case -INF === $value: $value = '-INF'; break; - case is_nan($value): $value = 'NAN'; break; - default: - $value = (string) $value; - if (false === strpos($value, $this->decimalPoint)) { - $value .= $this->decimalPoint.'0'; - } - break; - } - break; - - case 'NULL': - $value = 'null'; - break; - - case 'boolean': - $value = $value ? 'true' : 'false'; - break; - - default: - $attr += ['value' => $this->utf8Encode($value)]; - $value = $this->utf8Encode($type); - break; - } - - $this->line .= $this->style($style, $value, $attr); - - $this->endValue($cursor); - } - - /** - * {@inheritdoc} - */ - public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut) - { - $this->dumpKey($cursor); - $attr = $cursor->attr; - - if ($bin) { - $str = $this->utf8Encode($str); - } - if ('' === $str) { - $this->line .= '""'; - $this->endValue($cursor); - } else { - $attr += [ - 'length' => 0 <= $cut ? mb_strlen($str, 'UTF-8') + $cut : 0, - 'binary' => $bin, - ]; - $str = explode("\n", $str); - if (isset($str[1]) && !isset($str[2]) && !isset($str[1][0])) { - unset($str[1]); - $str[0] .= "\n"; - } - $m = \count($str) - 1; - $i = $lineCut = 0; - - if (self::DUMP_STRING_LENGTH & $this->flags) { - $this->line .= '('.$attr['length'].') '; - } - if ($bin) { - $this->line .= 'b'; - } - - if ($m) { - $this->line .= '"""'; - $this->dumpLine($cursor->depth); - } else { - $this->line .= '"'; - } - - foreach ($str as $str) { - if ($i < $m) { - $str .= "\n"; - } - if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = mb_strlen($str, 'UTF-8')) { - $str = mb_substr($str, 0, $this->maxStringWidth, 'UTF-8'); - $lineCut = $len - $this->maxStringWidth; - } - if ($m && 0 < $cursor->depth) { - $this->line .= $this->indentPad; - } - if ('' !== $str) { - $this->line .= $this->style('str', $str, $attr); - } - if ($i++ == $m) { - if ($m) { - if ('' !== $str) { - $this->dumpLine($cursor->depth); - if (0 < $cursor->depth) { - $this->line .= $this->indentPad; - } - } - $this->line .= '"""'; - } else { - $this->line .= '"'; - } - if ($cut < 0) { - $this->line .= '…'; - $lineCut = 0; - } elseif ($cut) { - $lineCut += $cut; - } - } - if ($lineCut) { - $this->line .= '…'.$lineCut; - $lineCut = 0; - } - - if ($i > $m) { - $this->endValue($cursor); - } else { - $this->dumpLine($cursor->depth); - } - } - } - } - - /** - * {@inheritdoc} - */ - public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild) - { - $this->dumpKey($cursor); - $attr = $cursor->attr; - - if ($this->collapseNextHash) { - $cursor->skipChildren = true; - $this->collapseNextHash = $hasChild = false; - } - - $class = $this->utf8Encode($class); - if (Cursor::HASH_OBJECT === $type) { - $prefix = $class && 'stdClass' !== $class ? $this->style('note', $class, $attr).(empty($attr['cut_hash']) ? ' {' : '') : '{'; - } elseif (Cursor::HASH_RESOURCE === $type) { - $prefix = $this->style('note', $class.' resource', $attr).($hasChild ? ' {' : ' '); - } else { - $prefix = $class && !(self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:'.$class, $attr).' [' : '['; - } - - if (($cursor->softRefCount || 0 < $cursor->softRefHandle) && empty($attr['cut_hash'])) { - $prefix .= $this->style('ref', (Cursor::HASH_RESOURCE === $type ? '@' : '#').(0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->softRefTo), ['count' => $cursor->softRefCount]); - } elseif ($cursor->hardRefTo && !$cursor->refIndex && $class) { - $prefix .= $this->style('ref', '&'.$cursor->hardRefTo, ['count' => $cursor->hardRefCount]); - } elseif (!$hasChild && Cursor::HASH_RESOURCE === $type) { - $prefix = substr($prefix, 0, -1); - } - - $this->line .= $prefix; - - if ($hasChild) { - $this->dumpLine($cursor->depth); - } - } - - /** - * {@inheritdoc} - */ - public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut) - { - if (empty($cursor->attr['cut_hash'])) { - $this->dumpEllipsis($cursor, $hasChild, $cut); - $this->line .= Cursor::HASH_OBJECT === $type ? '}' : (Cursor::HASH_RESOURCE !== $type ? ']' : ($hasChild ? '}' : '')); - } - - $this->endValue($cursor); - } - - /** - * Dumps an ellipsis for cut children. - * - * @param bool $hasChild When the dump of the hash has child item - * @param int $cut The number of items the hash has been cut by - */ - protected function dumpEllipsis(Cursor $cursor, $hasChild, $cut) - { - if ($cut) { - $this->line .= ' …'; - if (0 < $cut) { - $this->line .= $cut; - } - if ($hasChild) { - $this->dumpLine($cursor->depth + 1); - } - } - } - - /** - * Dumps a key in a hash structure. - */ - protected function dumpKey(Cursor $cursor) - { - if (null !== $key = $cursor->hashKey) { - if ($cursor->hashKeyIsBinary) { - $key = $this->utf8Encode($key); - } - $attr = ['binary' => $cursor->hashKeyIsBinary]; - $bin = $cursor->hashKeyIsBinary ? 'b' : ''; - $style = 'key'; - switch ($cursor->hashType) { - default: - case Cursor::HASH_INDEXED: - if (self::DUMP_LIGHT_ARRAY & $this->flags) { - break; - } - $style = 'index'; - // no break - case Cursor::HASH_ASSOC: - if (\is_int($key)) { - $this->line .= $this->style($style, $key).' => '; - } else { - $this->line .= $bin.'"'.$this->style($style, $key).'" => '; - } - break; - - case Cursor::HASH_RESOURCE: - $key = "\0~\0".$key; - // no break - case Cursor::HASH_OBJECT: - if (!isset($key[0]) || "\0" !== $key[0]) { - $this->line .= '+'.$bin.$this->style('public', $key).': '; - } elseif (0 < strpos($key, "\0", 1)) { - $key = explode("\0", substr($key, 1), 2); - - switch ($key[0][0]) { - case '+': // User inserted keys - $attr['dynamic'] = true; - $this->line .= '+'.$bin.'"'.$this->style('public', $key[1], $attr).'": '; - break 2; - case '~': - $style = 'meta'; - if (isset($key[0][1])) { - parse_str(substr($key[0], 1), $attr); - $attr += ['binary' => $cursor->hashKeyIsBinary]; - } - break; - case '*': - $style = 'protected'; - $bin = '#'.$bin; - break; - default: - $attr['class'] = $key[0]; - $style = 'private'; - $bin = '-'.$bin; - break; - } - - if (isset($attr['collapse'])) { - if ($attr['collapse']) { - $this->collapseNextHash = true; - } else { - $this->expandNextHash = true; - } - } - - $this->line .= $bin.$this->style($style, $key[1], $attr).(isset($attr['separator']) ? $attr['separator'] : ': '); - } else { - // This case should not happen - $this->line .= '-'.$bin.'"'.$this->style('private', $key, ['class' => '']).'": '; - } - break; - } - - if ($cursor->hardRefTo) { - $this->line .= $this->style('ref', '&'.($cursor->hardRefCount ? $cursor->hardRefTo : ''), ['count' => $cursor->hardRefCount]).' '; - } - } - } - - /** - * Decorates a value with some style. - * - * @param string $style The type of style being applied - * @param string $value The value being styled - * @param array $attr Optional context information - * - * @return string The value with style decoration - */ - protected function style($style, $value, $attr = []) - { - if (null === $this->colors) { - $this->colors = $this->supportsColors(); - } - - if (null === $this->handlesHrefGracefully) { - $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') && !getenv('KONSOLE_VERSION'); - } - - if (isset($attr['ellipsis'], $attr['ellipsis-type'])) { - $prefix = substr($value, 0, -$attr['ellipsis']); - if ('cli' === \PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\' === \DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && 0 === strpos($prefix, $_SERVER[$pwd])) { - $prefix = '.'.substr($prefix, \strlen($_SERVER[$pwd])); - } - if (!empty($attr['ellipsis-tail'])) { - $prefix .= substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']); - $value = substr($value, -$attr['ellipsis'] + $attr['ellipsis-tail']); - } else { - $value = substr($value, -$attr['ellipsis']); - } - - $value = $this->style('default', $prefix).$this->style($style, $value); - - goto href; - } - - $map = static::$controlCharsMap; - $startCchr = $this->colors ? "\033[m\033[{$this->styles['default']}m" : ''; - $endCchr = $this->colors ? "\033[m\033[{$this->styles[$style]}m" : ''; - $value = preg_replace_callback(static::$controlCharsRx, function ($c) use ($map, $startCchr, $endCchr) { - $s = $startCchr; - $c = $c[$i = 0]; - do { - $s .= isset($map[$c[$i]]) ? $map[$c[$i]] : sprintf('\x%02X', \ord($c[$i])); - } while (isset($c[++$i])); - - return $s.$endCchr; - }, $value, -1, $cchrCount); - - if ($this->colors) { - if ($cchrCount && "\033" === $value[0]) { - $value = substr($value, \strlen($startCchr)); - } else { - $value = "\033[{$this->styles[$style]}m".$value; - } - if ($cchrCount && $endCchr === substr($value, -\strlen($endCchr))) { - $value = substr($value, 0, -\strlen($endCchr)); - } else { - $value .= "\033[{$this->styles['default']}m"; - } - } - - href: - if ($this->colors && $this->handlesHrefGracefully) { - if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], isset($attr['line']) ? $attr['line'] : 0)) { - if ('note' === $style) { - $value .= "\033]8;;{$href}\033\\^\033]8;;\033\\"; - } else { - $attr['href'] = $href; - } - } - if (isset($attr['href'])) { - $value = "\033]8;;{$attr['href']}\033\\{$value}\033]8;;\033\\"; - } - } elseif ($attr['if_links'] ?? false) { - return ''; - } - - return $value; - } - - /** - * @return bool Tells if the current output stream supports ANSI colors or not - */ - protected function supportsColors() - { - if ($this->outputStream !== static::$defaultOutput) { - return $this->hasColorSupport($this->outputStream); - } - if (null !== static::$defaultColors) { - return static::$defaultColors; - } - if (isset($_SERVER['argv'][1])) { - $colors = $_SERVER['argv']; - $i = \count($colors); - while (--$i > 0) { - if (isset($colors[$i][5])) { - switch ($colors[$i]) { - case '--ansi': - case '--color': - case '--color=yes': - case '--color=force': - case '--color=always': - return static::$defaultColors = true; - - case '--no-ansi': - case '--color=no': - case '--color=none': - case '--color=never': - return static::$defaultColors = false; - } - } - } - } - - $h = stream_get_meta_data($this->outputStream) + ['wrapper_type' => null]; - $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'wb') : $this->outputStream; - - return static::$defaultColors = $this->hasColorSupport($h); - } - - /** - * {@inheritdoc} - */ - protected function dumpLine(int $depth, bool $endOfValue = false) - { - if ($this->colors) { - $this->line = sprintf("\033[%sm%s\033[m", $this->styles['default'], $this->line); - } - parent::dumpLine($depth); - } - - protected function endValue(Cursor $cursor) - { - if (-1 === $cursor->hashType) { - return; - } - - if (Stub::ARRAY_INDEXED === $cursor->hashType || Stub::ARRAY_ASSOC === $cursor->hashType) { - if (self::DUMP_TRAILING_COMMA & $this->flags && 0 < $cursor->depth) { - $this->line .= ','; - } elseif (self::DUMP_COMMA_SEPARATOR & $this->flags && 1 < $cursor->hashLength - $cursor->hashIndex) { - $this->line .= ','; - } - } - - $this->dumpLine($cursor->depth, true); - } - - /** - * Returns true if the stream supports colorization. - * - * Reference: Composer\XdebugHandler\Process::supportsColor - * https://github.com/composer/xdebug-handler - * - * @param mixed $stream A CLI output stream - */ - private function hasColorSupport($stream): bool - { - if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) { - return false; - } - - // Follow https://no-color.org/ - if (isset($_SERVER['NO_COLOR']) || false !== getenv('NO_COLOR')) { - return false; - } - - if ('Hyper' === getenv('TERM_PROGRAM')) { - return true; - } - - if (\DIRECTORY_SEPARATOR === '\\') { - return (\function_exists('sapi_windows_vt100_support') - && @sapi_windows_vt100_support($stream)) - || false !== getenv('ANSICON') - || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM'); - } - - return stream_isatty($stream); - } - - /** - * Returns true if the Windows terminal supports true color. - * - * Note that this does not check an output stream, but relies on environment - * variables from known implementations, or a PHP and Windows version that - * supports true color. - */ - private function isWindowsTrueColor(): bool - { - $result = 183 <= getenv('ANSICON_VER') - || 'ON' === getenv('ConEmuANSI') - || 'xterm' === getenv('TERM') - || 'Hyper' === getenv('TERM_PROGRAM'); - - if (!$result) { - $version = sprintf( - '%s.%s.%s', - PHP_WINDOWS_VERSION_MAJOR, - PHP_WINDOWS_VERSION_MINOR, - PHP_WINDOWS_VERSION_BUILD - ); - $result = $version >= '10.0.15063'; - } - - return $result; - } - - private function getSourceLink(string $file, int $line) - { - if ($fmt = $this->displayOptions['fileLinkFormat']) { - return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : ($fmt->format($file, $line) ?: 'file://'.$file.'#L'.$line); - } - - return false; - } -} diff --git a/vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php b/vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php deleted file mode 100644 index e7f8ccf..0000000 --- a/vendor/symfony/var-dumper/Dumper/ContextProvider/CliContextProvider.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper\ContextProvider; - -/** - * Tries to provide context on CLI. - * - * @author Maxime Steinhausser - */ -final class CliContextProvider implements ContextProviderInterface -{ - public function getContext(): ?array - { - if ('cli' !== \PHP_SAPI) { - return null; - } - - return [ - 'command_line' => $commandLine = implode(' ', $_SERVER['argv']), - 'identifier' => hash('crc32b', $commandLine.$_SERVER['REQUEST_TIME_FLOAT']), - ]; - } -} diff --git a/vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php b/vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php deleted file mode 100644 index 38ef3b0..0000000 --- a/vendor/symfony/var-dumper/Dumper/ContextProvider/ContextProviderInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper\ContextProvider; - -/** - * Interface to provide contextual data about dump data clones sent to a server. - * - * @author Maxime Steinhausser - */ -interface ContextProviderInterface -{ - /** - * @return array|null Context data or null if unable to provide any context - */ - public function getContext(): ?array; -} diff --git a/vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php b/vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php deleted file mode 100644 index 3684a47..0000000 --- a/vendor/symfony/var-dumper/Dumper/ContextProvider/RequestContextProvider.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper\ContextProvider; - -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\VarDumper\Caster\ReflectionCaster; -use Symfony\Component\VarDumper\Cloner\VarCloner; - -/** - * Tries to provide context from a request. - * - * @author Maxime Steinhausser - */ -final class RequestContextProvider implements ContextProviderInterface -{ - private $requestStack; - private $cloner; - - public function __construct(RequestStack $requestStack) - { - $this->requestStack = $requestStack; - $this->cloner = new VarCloner(); - $this->cloner->setMaxItems(0); - $this->cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO); - } - - public function getContext(): ?array - { - if (null === $request = $this->requestStack->getCurrentRequest()) { - return null; - } - - $controller = $request->attributes->get('_controller'); - - return [ - 'uri' => $request->getUri(), - 'method' => $request->getMethod(), - 'controller' => $controller ? $this->cloner->cloneVar($controller) : $controller, - 'identifier' => spl_object_hash($request), - ]; - } -} diff --git a/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php b/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php deleted file mode 100644 index 6f4caba..0000000 --- a/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php +++ /dev/null @@ -1,126 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper\ContextProvider; - -use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; -use Symfony\Component\VarDumper\Cloner\VarCloner; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; -use Symfony\Component\VarDumper\VarDumper; -use Twig\Template; - -/** - * Tries to provide context from sources (class name, file, line, code excerpt, ...). - * - * @author Nicolas Grekas - * @author Maxime Steinhausser - */ -final class SourceContextProvider implements ContextProviderInterface -{ - private $limit; - private $charset; - private $projectDir; - private $fileLinkFormatter; - - public function __construct(string $charset = null, string $projectDir = null, FileLinkFormatter $fileLinkFormatter = null, int $limit = 9) - { - $this->charset = $charset; - $this->projectDir = $projectDir; - $this->fileLinkFormatter = $fileLinkFormatter; - $this->limit = $limit; - } - - public function getContext(): ?array - { - $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, $this->limit); - - $file = $trace[1]['file']; - $line = $trace[1]['line']; - $name = false; - $fileExcerpt = false; - - for ($i = 2; $i < $this->limit; ++$i) { - if (isset($trace[$i]['class'], $trace[$i]['function']) - && 'dump' === $trace[$i]['function'] - && VarDumper::class === $trace[$i]['class'] - ) { - $file = $trace[$i]['file'] ?? $file; - $line = $trace[$i]['line'] ?? $line; - - while (++$i < $this->limit) { - if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && 0 !== strpos($trace[$i]['function'], 'call_user_func')) { - $file = $trace[$i]['file']; - $line = $trace[$i]['line']; - - break; - } elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof Template) { - $template = $trace[$i]['object']; - $name = $template->getTemplateName(); - $src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : false); - $info = $template->getDebugInfo(); - if (isset($info[$trace[$i - 1]['line']])) { - $line = $info[$trace[$i - 1]['line']]; - $file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : null; - - if ($src) { - $src = explode("\n", $src); - $fileExcerpt = []; - - for ($i = max($line - 3, 1), $max = min($line + 3, \count($src)); $i <= $max; ++$i) { - $fileExcerpt[] = ''.$this->htmlEncode($src[$i - 1]).''; - } - - $fileExcerpt = '
      '.implode("\n", $fileExcerpt).'
    '; - } - } - break; - } - } - break; - } - } - - if (false === $name) { - $name = str_replace('\\', '/', $file); - $name = substr($name, strrpos($name, '/') + 1); - } - - $context = ['name' => $name, 'file' => $file, 'line' => $line]; - $context['file_excerpt'] = $fileExcerpt; - - if (null !== $this->projectDir) { - $context['project_dir'] = $this->projectDir; - if (0 === strpos($file, $this->projectDir)) { - $context['file_relative'] = ltrim(substr($file, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR); - } - } - - if ($this->fileLinkFormatter && $fileLink = $this->fileLinkFormatter->format($context['file'], $context['line'])) { - $context['file_link'] = $fileLink; - } - - return $context; - } - - private function htmlEncode(string $s): string - { - $html = ''; - - $dumper = new HtmlDumper(function ($line) use (&$html) { $html .= $line; }, $this->charset); - $dumper->setDumpHeader(''); - $dumper->setDumpBoundaries('', ''); - - $cloner = new VarCloner(); - $dumper->dump($cloner->cloneVar($s)); - - return substr(strip_tags($html), 1, -1); - } -} diff --git a/vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php b/vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php deleted file mode 100644 index 7638417..0000000 --- a/vendor/symfony/var-dumper/Dumper/ContextualizedDumper.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper; - -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; - -/** - * @author Kévin Thérage - */ -class ContextualizedDumper implements DataDumperInterface -{ - private $wrappedDumper; - private $contextProviders; - - /** - * @param ContextProviderInterface[] $contextProviders - */ - public function __construct(DataDumperInterface $wrappedDumper, array $contextProviders) - { - $this->wrappedDumper = $wrappedDumper; - $this->contextProviders = $contextProviders; - } - - public function dump(Data $data) - { - $context = []; - foreach ($this->contextProviders as $contextProvider) { - $context[\get_class($contextProvider)] = $contextProvider->getContext(); - } - - $this->wrappedDumper->dump($data->withContext($context)); - } -} diff --git a/vendor/symfony/var-dumper/Dumper/DataDumperInterface.php b/vendor/symfony/var-dumper/Dumper/DataDumperInterface.php deleted file mode 100644 index b173bcc..0000000 --- a/vendor/symfony/var-dumper/Dumper/DataDumperInterface.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper; - -use Symfony\Component\VarDumper\Cloner\Data; - -/** - * DataDumperInterface for dumping Data objects. - * - * @author Nicolas Grekas - */ -interface DataDumperInterface -{ - public function dump(Data $data); -} diff --git a/vendor/symfony/var-dumper/Dumper/HtmlDumper.php b/vendor/symfony/var-dumper/Dumper/HtmlDumper.php deleted file mode 100644 index d89fecf..0000000 --- a/vendor/symfony/var-dumper/Dumper/HtmlDumper.php +++ /dev/null @@ -1,1004 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper; - -use Symfony\Component\VarDumper\Cloner\Cursor; -use Symfony\Component\VarDumper\Cloner\Data; - -/** - * HtmlDumper dumps variables as HTML. - * - * @author Nicolas Grekas - */ -class HtmlDumper extends CliDumper -{ - public static $defaultOutput = 'php://output'; - - protected static $themes = [ - 'dark' => [ - 'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', - 'num' => 'font-weight:bold; color:#1299DA', - 'const' => 'font-weight:bold', - 'str' => 'font-weight:bold; color:#56DB3A', - 'note' => 'color:#1299DA', - 'ref' => 'color:#A0A0A0', - 'public' => 'color:#FFFFFF', - 'protected' => 'color:#FFFFFF', - 'private' => 'color:#FFFFFF', - 'meta' => 'color:#B729D9', - 'key' => 'color:#56DB3A', - 'index' => 'color:#1299DA', - 'ellipsis' => 'color:#FF8400', - 'ns' => 'user-select:none;', - ], - 'light' => [ - 'default' => 'background:none; color:#CC7832; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', - 'num' => 'font-weight:bold; color:#1299DA', - 'const' => 'font-weight:bold', - 'str' => 'font-weight:bold; color:#629755;', - 'note' => 'color:#6897BB', - 'ref' => 'color:#6E6E6E', - 'public' => 'color:#262626', - 'protected' => 'color:#262626', - 'private' => 'color:#262626', - 'meta' => 'color:#B729D9', - 'key' => 'color:#789339', - 'index' => 'color:#1299DA', - 'ellipsis' => 'color:#CC7832', - 'ns' => 'user-select:none;', - ], - ]; - - protected $dumpHeader; - protected $dumpPrefix = '
    ';
    -    protected $dumpSuffix = '
    '; - protected $dumpId = 'sf-dump'; - protected $colors = true; - protected $headerIsDumped = false; - protected $lastDepth = -1; - protected $styles; - - private $displayOptions = [ - 'maxDepth' => 1, - 'maxStringLength' => 160, - 'fileLinkFormat' => null, - ]; - private $extraDisplayOptions = []; - - /** - * {@inheritdoc} - */ - public function __construct($output = null, string $charset = null, int $flags = 0) - { - AbstractDumper::__construct($output, $charset, $flags); - $this->dumpId = 'sf-dump-'.mt_rand(); - $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); - $this->styles = static::$themes['dark'] ?? self::$themes['dark']; - } - - /** - * {@inheritdoc} - */ - public function setStyles(array $styles) - { - $this->headerIsDumped = false; - $this->styles = $styles + $this->styles; - } - - public function setTheme(string $themeName) - { - if (!isset(static::$themes[$themeName])) { - throw new \InvalidArgumentException(sprintf('Theme "%s" does not exist in class "%s".', $themeName, static::class)); - } - - $this->setStyles(static::$themes[$themeName]); - } - - /** - * Configures display options. - * - * @param array $displayOptions A map of display options to customize the behavior - */ - public function setDisplayOptions(array $displayOptions) - { - $this->headerIsDumped = false; - $this->displayOptions = $displayOptions + $this->displayOptions; - } - - /** - * Sets an HTML header that will be dumped once in the output stream. - * - * @param string $header An HTML string - */ - public function setDumpHeader($header) - { - $this->dumpHeader = $header; - } - - /** - * Sets an HTML prefix and suffix that will encapse every single dump. - * - * @param string $prefix The prepended HTML string - * @param string $suffix The appended HTML string - */ - public function setDumpBoundaries($prefix, $suffix) - { - $this->dumpPrefix = $prefix; - $this->dumpSuffix = $suffix; - } - - /** - * {@inheritdoc} - */ - public function dump(Data $data, $output = null, array $extraDisplayOptions = []) - { - $this->extraDisplayOptions = $extraDisplayOptions; - $result = parent::dump($data, $output); - $this->dumpId = 'sf-dump-'.mt_rand(); - - return $result; - } - - /** - * Dumps the HTML header. - */ - protected function getDumpHeader() - { - $this->headerIsDumped = null !== $this->outputStream ? $this->outputStream : $this->lineDumper; - - if (null !== $this->dumpHeader) { - return $this->dumpHeader; - } - - $line = str_replace('{$options}', json_encode($this->displayOptions, JSON_FORCE_OBJECT), <<<'EOHTML' -'.$this->dumpHeader; - } - - /** - * {@inheritdoc} - */ - public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut) - { - if ('' === $str && isset($cursor->attr['img-data'], $cursor->attr['content-type'])) { - $this->dumpKey($cursor); - $this->line .= $this->style('default', $cursor->attr['img-size'] ?? '', []).' '; - $this->endValue($cursor); - $this->line .= $this->indentPad; - $this->line .= sprintf('', $cursor->attr['content-type'], base64_encode($cursor->attr['img-data'])); - $this->endValue($cursor); - } else { - parent::dumpString($cursor, $str, $bin, $cut); - } - } - - /** - * {@inheritdoc} - */ - public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild) - { - if (Cursor::HASH_OBJECT === $type) { - $cursor->attr['depth'] = $cursor->depth; - } - parent::enterHash($cursor, $type, $class, false); - - if ($cursor->skipChildren) { - $cursor->skipChildren = false; - $eol = ' class=sf-dump-compact>'; - } elseif ($this->expandNextHash) { - $this->expandNextHash = false; - $eol = ' class=sf-dump-expanded>'; - } else { - $eol = '>'; - } - - if ($hasChild) { - $this->line .= 'refIndex) { - $r = Cursor::HASH_OBJECT !== $type ? 1 - (Cursor::HASH_RESOURCE !== $type) : 2; - $r .= $r && 0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->refIndex; - - $this->line .= sprintf(' id=%s-ref%s', $this->dumpId, $r); - } - $this->line .= $eol; - $this->dumpLine($cursor->depth); - } - } - - /** - * {@inheritdoc} - */ - public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut) - { - $this->dumpEllipsis($cursor, $hasChild, $cut); - if ($hasChild) { - $this->line .= ''; - } - parent::leaveHash($cursor, $type, $class, $hasChild, 0); - } - - /** - * {@inheritdoc} - */ - protected function style($style, $value, $attr = []) - { - if ('' === $value) { - return ''; - } - - $v = esc($value); - - if ('ref' === $style) { - if (empty($attr['count'])) { - return sprintf('%s', $v); - } - $r = ('#' !== $v[0] ? 1 - ('@' !== $v[0]) : 2).substr($value, 1); - - return sprintf('%s', $this->dumpId, $r, 1 + $attr['count'], $v); - } - - if ('const' === $style && isset($attr['value'])) { - $style .= sprintf(' title="%s"', esc(is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value']))); - } elseif ('public' === $style) { - $style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property'); - } elseif ('str' === $style && 1 < $attr['length']) { - $style .= sprintf(' title="%d%s characters"', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : ''); - } elseif ('note' === $style && 0 < ($attr['depth'] ?? 0) && false !== $c = strrpos($value, '\\')) { - $style .= ' title=""'; - $attr += [ - 'ellipsis' => \strlen($value) - $c, - 'ellipsis-type' => 'note', - 'ellipsis-tail' => 1, - ]; - } elseif ('protected' === $style) { - $style .= ' title="Protected property"'; - } elseif ('meta' === $style && isset($attr['title'])) { - $style .= sprintf(' title="%s"', esc($this->utf8Encode($attr['title']))); - } elseif ('private' === $style) { - $style .= sprintf(' title="Private property defined in class: `%s`"', esc($this->utf8Encode($attr['class']))); - } - $map = static::$controlCharsMap; - - if (isset($attr['ellipsis'])) { - $class = 'sf-dump-ellipsis'; - if (isset($attr['ellipsis-type'])) { - $class = sprintf('"%s sf-dump-ellipsis-%s"', $class, $attr['ellipsis-type']); - } - $label = esc(substr($value, -$attr['ellipsis'])); - $style = str_replace(' title="', " title=\"$v\n", $style); - $v = sprintf('%s', $class, substr($v, 0, -\strlen($label))); - - if (!empty($attr['ellipsis-tail'])) { - $tail = \strlen(esc(substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']))); - $v .= sprintf('%s%s', $class, substr($label, 0, $tail), substr($label, $tail)); - } else { - $v .= $label; - } - } - - $v = "".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) { - $s = $b = ''; - }, $v).''; - - if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], isset($attr['line']) ? $attr['line'] : 0)) { - $attr['href'] = $href; - } - if (isset($attr['href'])) { - $target = isset($attr['file']) ? '' : ' target="_blank"'; - $v = sprintf('%s', esc($this->utf8Encode($attr['href'])), $target, $v); - } - if (isset($attr['lang'])) { - $v = sprintf('%s', esc($attr['lang']), $v); - } - - return $v; - } - - /** - * {@inheritdoc} - */ - protected function dumpLine(int $depth, bool $endOfValue = false) - { - if (-1 === $this->lastDepth) { - $this->line = sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad).$this->line; - } - if ($this->headerIsDumped !== (null !== $this->outputStream ? $this->outputStream : $this->lineDumper)) { - $this->line = $this->getDumpHeader().$this->line; - } - - if (-1 === $depth) { - $args = ['"'.$this->dumpId.'"']; - if ($this->extraDisplayOptions) { - $args[] = json_encode($this->extraDisplayOptions, JSON_FORCE_OBJECT); - } - // Replace is for BC - $this->line .= sprintf(str_replace('"%s"', '%s', $this->dumpSuffix), implode(', ', $args)); - } - $this->lastDepth = $depth; - - $this->line = mb_convert_encoding($this->line, 'HTML-ENTITIES', 'UTF-8'); - - if (-1 === $depth) { - AbstractDumper::dumpLine(0); - } - AbstractDumper::dumpLine($depth); - } - - private function getSourceLink(string $file, int $line) - { - $options = $this->extraDisplayOptions + $this->displayOptions; - - if ($fmt = $options['fileLinkFormat']) { - return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line); - } - - return false; - } -} - -function esc($str) -{ - return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); -} diff --git a/vendor/symfony/var-dumper/Dumper/ServerDumper.php b/vendor/symfony/var-dumper/Dumper/ServerDumper.php deleted file mode 100644 index 94795bf..0000000 --- a/vendor/symfony/var-dumper/Dumper/ServerDumper.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Dumper; - -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; -use Symfony\Component\VarDumper\Server\Connection; - -/** - * ServerDumper forwards serialized Data clones to a server. - * - * @author Maxime Steinhausser - */ -class ServerDumper implements DataDumperInterface -{ - private $connection; - private $wrappedDumper; - - /** - * @param string $host The server host - * @param DataDumperInterface|null $wrappedDumper A wrapped instance used whenever we failed contacting the server - * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name - */ - public function __construct(string $host, DataDumperInterface $wrappedDumper = null, array $contextProviders = []) - { - $this->connection = new Connection($host, $contextProviders); - $this->wrappedDumper = $wrappedDumper; - } - - public function getContextProviders(): array - { - return $this->connection->getContextProviders(); - } - - /** - * {@inheritdoc} - */ - public function dump(Data $data) - { - if (!$this->connection->write($data) && $this->wrappedDumper) { - $this->wrappedDumper->dump($data); - } - } -} diff --git a/vendor/symfony/var-dumper/Exception/ThrowingCasterException.php b/vendor/symfony/var-dumper/Exception/ThrowingCasterException.php deleted file mode 100644 index 122f0d3..0000000 --- a/vendor/symfony/var-dumper/Exception/ThrowingCasterException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Exception; - -/** - * @author Nicolas Grekas - */ -class ThrowingCasterException extends \Exception -{ - /** - * @param \Throwable $prev The exception thrown from the caster - */ - public function __construct(\Throwable $prev) - { - parent::__construct('Unexpected '.\get_class($prev).' thrown from a caster: '.$prev->getMessage(), 0, $prev); - } -} diff --git a/vendor/symfony/var-dumper/LICENSE b/vendor/symfony/var-dumper/LICENSE deleted file mode 100644 index cf8b3eb..0000000 --- a/vendor/symfony/var-dumper/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2014-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/var-dumper/README.md b/vendor/symfony/var-dumper/README.md deleted file mode 100644 index 339f73e..0000000 --- a/vendor/symfony/var-dumper/README.md +++ /dev/null @@ -1,15 +0,0 @@ -VarDumper Component -=================== - -The VarDumper component provides mechanisms for walking through any arbitrary -PHP variable. It provides a better `dump()` function that you can use instead -of `var_dump`. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/var_dumper/introduction.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/var-dumper/Resources/bin/var-dump-server b/vendor/symfony/var-dumper/Resources/bin/var-dump-server deleted file mode 100755 index 98c813a..0000000 --- a/vendor/symfony/var-dumper/Resources/bin/var-dump-server +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env php - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Starts a dump server to collect and output dumps on a single place with multiple formats support. - * - * @author Maxime Steinhausser - */ - -use Psr\Log\LoggerInterface; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Logger\ConsoleLogger; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\VarDumper\Command\ServerDumpCommand; -use Symfony\Component\VarDumper\Server\DumpServer; - -function includeIfExists(string $file): bool -{ - return file_exists($file) && include $file; -} - -if ( - !includeIfExists(__DIR__ . '/../../../../autoload.php') && - !includeIfExists(__DIR__ . '/../../vendor/autoload.php') && - !includeIfExists(__DIR__ . '/../../../../../../vendor/autoload.php') -) { - fwrite(STDERR, 'Install dependencies using Composer.'.PHP_EOL); - exit(1); -} - -if (!class_exists(Application::class)) { - fwrite(STDERR, 'You need the "symfony/console" component in order to run the VarDumper server.'.PHP_EOL); - exit(1); -} - -$input = new ArgvInput(); -$output = new ConsoleOutput(); -$defaultHost = '127.0.0.1:9912'; -$host = $input->getParameterOption(['--host'], $_SERVER['VAR_DUMPER_SERVER'] ?? $defaultHost, true); -$logger = interface_exists(LoggerInterface::class) ? new ConsoleLogger($output->getErrorOutput()) : null; - -$app = new Application(); - -$app->getDefinition()->addOption( - new InputOption('--host', null, InputOption::VALUE_REQUIRED, 'The address the server should listen to', $defaultHost) -); - -$app->add($command = new ServerDumpCommand(new DumpServer($host, $logger))) - ->getApplication() - ->setDefaultCommand($command->getName(), true) - ->run($input, $output) -; diff --git a/vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css b/vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css deleted file mode 100644 index 8f706d6..0000000 --- a/vendor/symfony/var-dumper/Resources/css/htmlDescriptor.css +++ /dev/null @@ -1,130 +0,0 @@ -body { - display: flex; - flex-direction: column-reverse; - justify-content: flex-end; - max-width: 1140px; - margin: auto; - padding: 15px; - word-wrap: break-word; - background-color: #F9F9F9; - color: #222; - font-family: Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.4; -} -p { - margin: 0; -} -a { - color: #218BC3; - text-decoration: none; -} -a:hover { - text-decoration: underline; -} -.text-small { - font-size: 12px !important; -} -article { - margin: 5px; - margin-bottom: 10px; -} -article > header > .row { - display: flex; - flex-direction: row; - align-items: baseline; - margin-bottom: 10px; -} -article > header > .row > .col { - flex: 1; - display: flex; - align-items: baseline; -} -article > header > .row > h2 { - font-size: 14px; - color: #222; - font-weight: normal; - font-family: "Lucida Console", monospace, sans-serif; - word-break: break-all; - margin: 20px 5px 0 0; - user-select: all; -} -article > header > .row > h2 > code { - white-space: nowrap; - user-select: none; - color: #cc2255; - background-color: #f7f7f9; - border: 1px solid #e1e1e8; - border-radius: 3px; - margin-right: 5px; - padding: 0 3px; -} -article > header > .row > time.col { - flex: 0; - text-align: right; - white-space: nowrap; - color: #999; - font-style: italic; -} -article > header ul.tags { - list-style: none; - padding: 0; - margin: 0; - font-size: 12px; -} -article > header ul.tags > li { - user-select: all; - margin-bottom: 2px; -} -article > header ul.tags > li > span.badge { - display: inline-block; - padding: .25em .4em; - margin-right: 5px; - border-radius: 4px; - background-color: #6c757d3b; - color: #524d4d; - font-size: 12px; - text-align: center; - font-weight: 700; - line-height: 1; - white-space: nowrap; - vertical-align: baseline; - user-select: none; -} -article > section.body { - border: 1px solid #d8d8d8; - background: #FFF; - padding: 10px; - border-radius: 3px; -} -pre.sf-dump { - border-radius: 3px; - margin-bottom: 0; -} -.hidden { - display: none !important; -} -.dumped-tag > .sf-dump { - display: inline-block; - margin: 0; - padding: 1px 5px; - line-height: 1.4; - vertical-align: top; - background-color: transparent; - user-select: auto; -} -.dumped-tag > pre.sf-dump, -.dumped-tag > .sf-dump-default { - color: #CC7832; - background: none; -} -.dumped-tag > .sf-dump .sf-dump-str { color: #629755; } -.dumped-tag > .sf-dump .sf-dump-private, -.dumped-tag > .sf-dump .sf-dump-protected, -.dumped-tag > .sf-dump .sf-dump-public { color: #262626; } -.dumped-tag > .sf-dump .sf-dump-note { color: #6897BB; } -.dumped-tag > .sf-dump .sf-dump-key { color: #789339; } -.dumped-tag > .sf-dump .sf-dump-ref { color: #6E6E6E; } -.dumped-tag > .sf-dump .sf-dump-ellipsis { color: #CC7832; max-width: 100em; } -.dumped-tag > .sf-dump .sf-dump-ellipsis-path { max-width: 5em; } -.dumped-tag > .sf-dump .sf-dump-ns { user-select: none; } diff --git a/vendor/symfony/var-dumper/Resources/functions/dump.php b/vendor/symfony/var-dumper/Resources/functions/dump.php deleted file mode 100644 index e1543a8..0000000 --- a/vendor/symfony/var-dumper/Resources/functions/dump.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Component\VarDumper\VarDumper; - -if (!function_exists('dump')) { - /** - * @author Nicolas Grekas - */ - function dump($var, ...$moreVars) - { - VarDumper::dump($var); - - foreach ($moreVars as $v) { - VarDumper::dump($v); - } - - if (1 < func_num_args()) { - return func_get_args(); - } - - return $var; - } -} - -if (!function_exists('dd')) { - function dd(...$vars) - { - foreach ($vars as $v) { - VarDumper::dump($v); - } - - die(1); - } -} diff --git a/vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js b/vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js deleted file mode 100644 index 63101e5..0000000 --- a/vendor/symfony/var-dumper/Resources/js/htmlDescriptor.js +++ /dev/null @@ -1,10 +0,0 @@ -document.addEventListener('DOMContentLoaded', function() { - let prev = null; - Array.from(document.getElementsByTagName('article')).reverse().forEach(function (article) { - const dedupId = article.dataset.dedupId; - if (dedupId === prev) { - article.getElementsByTagName('header')[0].classList.add('hidden'); - } - prev = dedupId; - }); -}); diff --git a/vendor/symfony/var-dumper/Server/Connection.php b/vendor/symfony/var-dumper/Server/Connection.php deleted file mode 100644 index 8b814cb..0000000 --- a/vendor/symfony/var-dumper/Server/Connection.php +++ /dev/null @@ -1,95 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Server; - -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; - -/** - * Forwards serialized Data clones to a server. - * - * @author Maxime Steinhausser - */ -class Connection -{ - private $host; - private $contextProviders; - private $socket; - - /** - * @param string $host The server host - * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name - */ - public function __construct(string $host, array $contextProviders = []) - { - if (false === strpos($host, '://')) { - $host = 'tcp://'.$host; - } - - $this->host = $host; - $this->contextProviders = $contextProviders; - } - - public function getContextProviders(): array - { - return $this->contextProviders; - } - - public function write(Data $data): bool - { - $socketIsFresh = !$this->socket; - if (!$this->socket = $this->socket ?: $this->createSocket()) { - return false; - } - - $context = ['timestamp' => microtime(true)]; - foreach ($this->contextProviders as $name => $provider) { - $context[$name] = $provider->getContext(); - } - $context = array_filter($context); - $encodedPayload = base64_encode(serialize([$data, $context]))."\n"; - - set_error_handler([self::class, 'nullErrorHandler']); - try { - if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) { - return true; - } - if (!$socketIsFresh) { - stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR); - fclose($this->socket); - $this->socket = $this->createSocket(); - } - if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) { - return true; - } - } finally { - restore_error_handler(); - } - - return false; - } - - private static function nullErrorHandler($t, $m) - { - // no-op - } - - private function createSocket() - { - set_error_handler([self::class, 'nullErrorHandler']); - try { - return stream_socket_client($this->host, $errno, $errstr, 3, STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT); - } finally { - restore_error_handler(); - } - } -} diff --git a/vendor/symfony/var-dumper/Server/DumpServer.php b/vendor/symfony/var-dumper/Server/DumpServer.php deleted file mode 100644 index ad920bd..0000000 --- a/vendor/symfony/var-dumper/Server/DumpServer.php +++ /dev/null @@ -1,107 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Server; - -use Psr\Log\LoggerInterface; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Cloner\Stub; - -/** - * A server collecting Data clones sent by a ServerDumper. - * - * @author Maxime Steinhausser - * - * @final - */ -class DumpServer -{ - private $host; - private $socket; - private $logger; - - public function __construct(string $host, LoggerInterface $logger = null) - { - if (false === strpos($host, '://')) { - $host = 'tcp://'.$host; - } - - $this->host = $host; - $this->logger = $logger; - } - - public function start(): void - { - if (!$this->socket = stream_socket_server($this->host, $errno, $errstr)) { - throw new \RuntimeException(sprintf('Server start failed on "%s": %s %s.', $this->host, $errstr, $errno)); - } - } - - public function listen(callable $callback): void - { - if (null === $this->socket) { - $this->start(); - } - - foreach ($this->getMessages() as $clientId => $message) { - $payload = @unserialize(base64_decode($message), ['allowed_classes' => [Data::class, Stub::class]]); - - // Impossible to decode the message, give up. - if (false === $payload) { - if ($this->logger) { - $this->logger->warning('Unable to decode a message from {clientId} client.', ['clientId' => $clientId]); - } - - continue; - } - - if (!\is_array($payload) || \count($payload) < 2 || !$payload[0] instanceof Data || !\is_array($payload[1])) { - if ($this->logger) { - $this->logger->warning('Invalid payload from {clientId} client. Expected an array of two elements (Data $data, array $context)', ['clientId' => $clientId]); - } - - continue; - } - - list($data, $context) = $payload; - - $callback($data, $context, $clientId); - } - } - - public function getHost(): string - { - return $this->host; - } - - private function getMessages(): iterable - { - $sockets = [(int) $this->socket => $this->socket]; - $write = []; - - while (true) { - $read = $sockets; - stream_select($read, $write, $write, null); - - foreach ($read as $stream) { - if ($this->socket === $stream) { - $stream = stream_socket_accept($this->socket); - $sockets[(int) $stream] = $stream; - } elseif (feof($stream)) { - unset($sockets[(int) $stream]); - fclose($stream); - } else { - yield (int) $stream => fgets($stream); - } - } - } - } -} diff --git a/vendor/symfony/var-dumper/Test/VarDumperTestTrait.php b/vendor/symfony/var-dumper/Test/VarDumperTestTrait.php deleted file mode 100644 index 258419c..0000000 --- a/vendor/symfony/var-dumper/Test/VarDumperTestTrait.php +++ /dev/null @@ -1,87 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Test; - -use Symfony\Component\VarDumper\Cloner\VarCloner; -use Symfony\Component\VarDumper\Dumper\CliDumper; - -/** - * @author Nicolas Grekas - */ -trait VarDumperTestTrait -{ - /** - * @internal - */ - private $varDumperConfig = [ - 'casters' => [], - 'flags' => null, - ]; - - protected function setUpVarDumper(array $casters, int $flags = null): void - { - $this->varDumperConfig['casters'] = $casters; - $this->varDumperConfig['flags'] = $flags; - } - - /** - * @after - */ - protected function tearDownVarDumper(): void - { - $this->varDumperConfig['casters'] = []; - $this->varDumperConfig['flags'] = null; - } - - public function assertDumpEquals($expected, $data, int $filter = 0, string $message = '') - { - $this->assertSame($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message); - } - - public function assertDumpMatchesFormat($expected, $data, int $filter = 0, string $message = '') - { - $this->assertStringMatchesFormat($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message); - } - - /** - * @return string|null - */ - protected function getDump($data, $key = null, int $filter = 0): ?string - { - if (null === $flags = $this->varDumperConfig['flags']) { - $flags = getenv('DUMP_LIGHT_ARRAY') ? CliDumper::DUMP_LIGHT_ARRAY : 0; - $flags |= getenv('DUMP_STRING_LENGTH') ? CliDumper::DUMP_STRING_LENGTH : 0; - $flags |= getenv('DUMP_COMMA_SEPARATOR') ? CliDumper::DUMP_COMMA_SEPARATOR : 0; - } - - $cloner = new VarCloner(); - $cloner->addCasters($this->varDumperConfig['casters']); - $cloner->setMaxItems(-1); - $dumper = new CliDumper(null, null, $flags); - $dumper->setColors(false); - $data = $cloner->cloneVar($data, $filter)->withRefHandles(false); - if (null !== $key && null === $data = $data->seek($key)) { - return null; - } - - return rtrim($dumper->dump($data, true)); - } - - private function prepareExpectation($expected, int $filter): string - { - if (!\is_string($expected)) { - $expected = $this->getDump($expected, null, $filter); - } - - return rtrim($expected); - } -} diff --git a/vendor/symfony/var-dumper/VarDumper.php b/vendor/symfony/var-dumper/VarDumper.php deleted file mode 100644 index d336d5d..0000000 --- a/vendor/symfony/var-dumper/VarDumper.php +++ /dev/null @@ -1,60 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper; - -use Symfony\Component\VarDumper\Caster\ReflectionCaster; -use Symfony\Component\VarDumper\Cloner\VarCloner; -use Symfony\Component\VarDumper\Dumper\CliDumper; -use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; -use Symfony\Component\VarDumper\Dumper\ContextualizedDumper; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; - -// Load the global dump() function -require_once __DIR__.'/Resources/functions/dump.php'; - -/** - * @author Nicolas Grekas - */ -class VarDumper -{ - private static $handler; - - public static function dump($var) - { - if (null === self::$handler) { - $cloner = new VarCloner(); - $cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO); - - if (isset($_SERVER['VAR_DUMPER_FORMAT'])) { - $dumper = 'html' === $_SERVER['VAR_DUMPER_FORMAT'] ? new HtmlDumper() : new CliDumper(); - } else { - $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg']) ? new CliDumper() : new HtmlDumper(); - } - - $dumper = new ContextualizedDumper($dumper, [new SourceContextProvider()]); - - self::$handler = function ($var) use ($cloner, $dumper) { - $dumper->dump($cloner->cloneVar($var)); - }; - } - - return (self::$handler)($var); - } - - public static function setHandler(callable $callable = null) - { - $prevHandler = self::$handler; - self::$handler = $callable; - - return $prevHandler; - } -} diff --git a/vendor/symfony/var-dumper/composer.json b/vendor/symfony/var-dumper/composer.json deleted file mode 100644 index c7e668c..0000000 --- a/vendor/symfony/var-dumper/composer.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "symfony/var-dumper", - "type": "library", - "description": "Symfony mechanism for exploring and dumping PHP variables", - "keywords": ["dump", "debug"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5", - "symfony/polyfill-mbstring": "~1.0" - }, - "require-dev": { - "ext-iconv": "*", - "symfony/console": "^4.4|^5.0", - "symfony/process": "^4.4|^5.0", - "twig/twig": "^2.4|^3.0" - }, - "conflict": { - "phpunit/phpunit": "<5.4.3", - "symfony/console": "<4.4" - }, - "suggest": { - "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", - "ext-intl": "To show region name in time zone dump", - "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" - }, - "autoload": { - "files": [ "Resources/functions/dump.php" ], - "psr-4": { "Symfony\\Component\\VarDumper\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "bin": [ - "Resources/bin/var-dump-server" - ], - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} diff --git a/vendor/symfony/var-exporter/.gitattributes b/vendor/symfony/var-exporter/.gitattributes deleted file mode 100644 index ebb9287..0000000 --- a/vendor/symfony/var-exporter/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -/Tests export-ignore -/phpunit.xml.dist export-ignore -/.gitignore export-ignore diff --git a/vendor/symfony/var-exporter/CHANGELOG.md b/vendor/symfony/var-exporter/CHANGELOG.md deleted file mode 100644 index 9aa4a8b..0000000 --- a/vendor/symfony/var-exporter/CHANGELOG.md +++ /dev/null @@ -1,7 +0,0 @@ -CHANGELOG -========= - -4.2.0 ------ - - * added the component diff --git a/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php b/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php deleted file mode 100644 index 4cebe44..0000000 --- a/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Exception; - -class ClassNotFoundException extends \Exception implements ExceptionInterface -{ - public function __construct(string $class, \Throwable $previous = null) - { - parent::__construct(sprintf('Class "%s" not found.', $class), 0, $previous); - } -} diff --git a/vendor/symfony/var-exporter/Exception/ExceptionInterface.php b/vendor/symfony/var-exporter/Exception/ExceptionInterface.php deleted file mode 100644 index adfaed4..0000000 --- a/vendor/symfony/var-exporter/Exception/ExceptionInterface.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Exception; - -interface ExceptionInterface extends \Throwable -{ -} diff --git a/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php b/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php deleted file mode 100644 index 7ca4884..0000000 --- a/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Exception; - -class NotInstantiableTypeException extends \Exception implements ExceptionInterface -{ - public function __construct(string $type) - { - parent::__construct(sprintf('Type "%s" is not instantiable.', $type)); - } -} diff --git a/vendor/symfony/var-exporter/Instantiator.php b/vendor/symfony/var-exporter/Instantiator.php deleted file mode 100644 index 9fd8cf3..0000000 --- a/vendor/symfony/var-exporter/Instantiator.php +++ /dev/null @@ -1,94 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -use Symfony\Component\VarExporter\Exception\ExceptionInterface; -use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; -use Symfony\Component\VarExporter\Internal\Hydrator; -use Symfony\Component\VarExporter\Internal\Registry; - -/** - * A utility class to create objects without calling their constructor. - * - * @author Nicolas Grekas - */ -final class Instantiator -{ - /** - * Creates an object and sets its properties without calling its constructor nor any other methods. - * - * For example: - * - * // creates an empty instance of Foo - * Instantiator::instantiate(Foo::class); - * - * // creates a Foo instance and sets one of its properties - * Instantiator::instantiate(Foo::class, ['propertyName' => $propertyValue]); - * - * // creates a Foo instance and sets a private property defined on its parent Bar class - * Instantiator::instantiate(Foo::class, [], [ - * Bar::class => ['privateBarProperty' => $propertyValue], - * ]); - * - * Instances of ArrayObject, ArrayIterator and SplObjectHash can be created - * by using the special "\0" property name to define their internal value: - * - * // creates an SplObjectHash where $info1 is attached to $obj1, etc. - * Instantiator::instantiate(SplObjectStorage::class, ["\0" => [$obj1, $info1, $obj2, $info2...]]); - * - * // creates an ArrayObject populated with $inputArray - * Instantiator::instantiate(ArrayObject::class, ["\0" => [$inputArray]]); - * - * @param string $class The class of the instance to create - * @param array $properties The properties to set on the instance - * @param array $privateProperties The private properties to set on the instance, - * keyed by their declaring class - * - * @return object The created instance - * - * @throws ExceptionInterface When the instance cannot be created - */ - public static function instantiate(string $class, array $properties = [], array $privateProperties = []): object - { - $reflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class); - - if (Registry::$cloneable[$class]) { - $wrappedInstance = [clone Registry::$prototypes[$class]]; - } elseif (Registry::$instantiableWithoutConstructor[$class]) { - $wrappedInstance = [$reflector->newInstanceWithoutConstructor()]; - } elseif (null === Registry::$prototypes[$class]) { - throw new NotInstantiableTypeException($class); - } elseif ($reflector->implementsInterface('Serializable') && (\PHP_VERSION_ID < 70400 || !method_exists($class, '__unserialize'))) { - $wrappedInstance = [unserialize('C:'.\strlen($class).':"'.$class.'":0:{}')]; - } else { - $wrappedInstance = [unserialize('O:'.\strlen($class).':"'.$class.'":0:{}')]; - } - - if ($properties) { - $privateProperties[$class] = isset($privateProperties[$class]) ? $properties + $privateProperties[$class] : $properties; - } - - foreach ($privateProperties as $class => $properties) { - if (!$properties) { - continue; - } - foreach ($properties as $name => $value) { - // because they're also used for "unserialization", hydrators - // deal with array of instances, so we need to wrap values - $properties[$name] = [$value]; - } - (Hydrator::$hydrators[$class] ?? Hydrator::getHydrator($class))($properties, $wrappedInstance); - } - - return $wrappedInstance[0]; - } -} diff --git a/vendor/symfony/var-exporter/Internal/Exporter.php b/vendor/symfony/var-exporter/Internal/Exporter.php deleted file mode 100644 index 4d83a4b..0000000 --- a/vendor/symfony/var-exporter/Internal/Exporter.php +++ /dev/null @@ -1,407 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; - -/** - * @author Nicolas Grekas - * - * @internal - */ -class Exporter -{ - /** - * Prepares an array of values for VarExporter. - * - * For performance this method is public and has no type-hints. - * - * @param array &$values - * @param \SplObjectStorage $objectsPool - * @param array &$refsPool - * @param int &$objectsCount - * @param bool &$valuesAreStatic - * - * @return array - * - * @throws NotInstantiableTypeException When a value cannot be serialized - */ - public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic): array - { - $refs = $values; - foreach ($values as $k => $value) { - if (\is_resource($value)) { - throw new NotInstantiableTypeException(get_resource_type($value).' resource'); - } - $refs[$k] = $objectsPool; - - if ($isRef = !$valueIsStatic = $values[$k] !== $objectsPool) { - $values[$k] = &$value; // Break hard references to make $values completely - unset($value); // independent from the original structure - $refs[$k] = $value = $values[$k]; - if ($value instanceof Reference && 0 > $value->id) { - $valuesAreStatic = false; - ++$value->count; - continue; - } - $refsPool[] = [&$refs[$k], $value, &$value]; - $refs[$k] = $values[$k] = new Reference(-\count($refsPool), $value); - } - - if (\is_array($value)) { - if ($value) { - $value = self::prepare($value, $objectsPool, $refsPool, $objectsCount, $valueIsStatic); - } - goto handle_value; - } elseif (!\is_object($value) && !$value instanceof \__PHP_Incomplete_Class) { - goto handle_value; - } - - $valueIsStatic = false; - if (isset($objectsPool[$value])) { - ++$objectsCount; - $value = new Reference($objectsPool[$value][0]); - goto handle_value; - } - - $class = \get_class($value); - $reflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class); - - if ($reflector->hasMethod('__serialize')) { - if (!$reflector->getMethod('__serialize')->isPublic()) { - throw new \Error(sprintf('Call to %s method %s::__serialize()', $reflector->getMethod('__serialize')->isProtected() ? 'protected' : 'private', $class)); - } - - if (!\is_array($properties = $value->__serialize())) { - throw new \Typerror($class.'::__serialize() must return an array'); - } - - goto prepare_value; - } - - $properties = []; - $sleep = null; - $arrayValue = (array) $value; - $proto = Registry::$prototypes[$class]; - - if (($value instanceof \ArrayIterator || $value instanceof \ArrayObject) && null !== $proto) { - // ArrayIterator and ArrayObject need special care because their "flags" - // option changes the behavior of the (array) casting operator. - $properties = self::getArrayObjectProperties($value, $arrayValue, $proto); - - // populates Registry::$prototypes[$class] with a new instance - Registry::getClassReflector($class, Registry::$instantiableWithoutConstructor[$class], Registry::$cloneable[$class]); - } elseif ($value instanceof \SplObjectStorage && Registry::$cloneable[$class] && null !== $proto) { - // By implementing Serializable, SplObjectStorage breaks - // internal references; let's deal with it on our own. - foreach (clone $value as $v) { - $properties[] = $v; - $properties[] = $value[$v]; - } - $properties = ['SplObjectStorage' => ["\0" => $properties]]; - } elseif ($value instanceof \Serializable || $value instanceof \__PHP_Incomplete_Class) { - ++$objectsCount; - $objectsPool[$value] = [$id = \count($objectsPool), serialize($value), [], 0]; - $value = new Reference($id); - goto handle_value; - } - - if (method_exists($class, '__sleep')) { - if (!\is_array($sleep = $value->__sleep())) { - trigger_error('serialize(): __sleep should return an array only containing the names of instance-variables to serialize', E_USER_NOTICE); - $value = null; - goto handle_value; - } - foreach ($sleep as $name) { - if (property_exists($value, $name) && !$reflector->hasProperty($name)) { - $arrayValue[$name] = $value->$name; - } - } - $sleep = array_flip($sleep); - } - - $proto = (array) $proto; - - foreach ($arrayValue as $name => $v) { - $i = 0; - $n = (string) $name; - if ('' === $n || "\0" !== $n[0]) { - $c = 'stdClass'; - } elseif ('*' === $n[1]) { - $n = substr($n, 3); - $c = $reflector->getProperty($n)->class; - if ('Error' === $c) { - $c = 'TypeError'; - } elseif ('Exception' === $c) { - $c = 'ErrorException'; - } - } else { - $i = strpos($n, "\0", 2); - $c = substr($n, 1, $i - 1); - $n = substr($n, 1 + $i); - } - if (null !== $sleep) { - if (!isset($sleep[$n]) || ($i && $c !== $class)) { - continue; - } - $sleep[$n] = false; - } - if (!\array_key_exists($name, $proto) || $proto[$name] !== $v || "\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) { - $properties[$c][$n] = $v; - } - } - if ($sleep) { - foreach ($sleep as $n => $v) { - if (false !== $v) { - trigger_error(sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $n), E_USER_NOTICE); - } - } - } - - prepare_value: - $objectsPool[$value] = [$id = \count($objectsPool)]; - $properties = self::prepare($properties, $objectsPool, $refsPool, $objectsCount, $valueIsStatic); - ++$objectsCount; - $objectsPool[$value] = [$id, $class, $properties, method_exists($class, '__unserialize') ? -$objectsCount : (method_exists($class, '__wakeup') ? $objectsCount : 0)]; - - $value = new Reference($id); - - handle_value: - if ($isRef) { - unset($value); // Break the hard reference created above - } elseif (!$valueIsStatic) { - $values[$k] = $value; - } - $valuesAreStatic = $valueIsStatic && $valuesAreStatic; - } - - return $values; - } - - public static function export($value, string $indent = '') - { - switch (true) { - case \is_int($value) || \is_float($value): return var_export($value, true); - case [] === $value: return '[]'; - case false === $value: return 'false'; - case true === $value: return 'true'; - case null === $value: return 'null'; - case '' === $value: return "''"; - } - - if ($value instanceof Reference) { - if (0 <= $value->id) { - return '$o['.$value->id.']'; - } - if (!$value->count) { - return self::export($value->value, $indent); - } - $value = -$value->id; - - return '&$r['.$value.']'; - } - $subIndent = $indent.' '; - - if (\is_string($value)) { - $code = sprintf("'%s'", addcslashes($value, "'\\")); - - $code = preg_replace_callback('/([\0\r\n]++)(.)/', function ($m) use ($subIndent) { - $m[1] = sprintf('\'."%s".\'', str_replace( - ["\0", "\r", "\n", '\n\\'], - ['\0', '\r', '\n', '\n"'."\n".$subIndent.'."\\'], - $m[1] - )); - - if ("'" === $m[2]) { - return substr($m[1], 0, -2); - } - - if ('n".\'' === substr($m[1], -4)) { - return substr_replace($m[1], "\n".$subIndent.".'".$m[2], -2); - } - - return $m[1].$m[2]; - }, $code, -1, $count); - - if ($count && 0 === strpos($code, "''.")) { - $code = substr($code, 3); - } - - return $code; - } - - if (\is_array($value)) { - $j = -1; - $code = ''; - foreach ($value as $k => $v) { - $code .= $subIndent; - if (!\is_int($k) || 1 !== $k - $j) { - $code .= self::export($k, $subIndent).' => '; - } - if (\is_int($k) && $k > $j) { - $j = $k; - } - $code .= self::export($v, $subIndent).",\n"; - } - - return "[\n".$code.$indent.']'; - } - - if ($value instanceof Values) { - $code = $subIndent."\$r = [],\n"; - foreach ($value->values as $k => $v) { - $code .= $subIndent.'$r['.$k.'] = '.self::export($v, $subIndent).",\n"; - } - - return "[\n".$code.$indent.']'; - } - - if ($value instanceof Registry) { - return self::exportRegistry($value, $indent, $subIndent); - } - - if ($value instanceof Hydrator) { - return self::exportHydrator($value, $indent, $subIndent); - } - - throw new \UnexpectedValueException(sprintf('Cannot export value of type "%s".', \is_object($value) ? \get_class($value) : \gettype($value))); - } - - private static function exportRegistry(Registry $value, string $indent, string $subIndent): string - { - $code = ''; - $serializables = []; - $seen = []; - $prototypesAccess = 0; - $factoriesAccess = 0; - $r = '\\'.Registry::class; - $j = -1; - - foreach ($value as $k => $class) { - if (':' === ($class[1] ?? null)) { - $serializables[$k] = $class; - continue; - } - if (!Registry::$instantiableWithoutConstructor[$class]) { - if (is_subclass_of($class, 'Serializable') && !method_exists($class, '__unserialize')) { - $serializables[$k] = 'C:'.\strlen($class).':"'.$class.'":0:{}'; - } else { - $serializables[$k] = 'O:'.\strlen($class).':"'.$class.'":0:{}'; - } - if (is_subclass_of($class, 'Throwable')) { - $eol = is_subclass_of($class, 'Error') ? "\0Error\0" : "\0Exception\0"; - $serializables[$k] = substr_replace($serializables[$k], '1:{s:'.(5 + \strlen($eol)).':"'.$eol.'trace";a:0:{}}', -4); - } - continue; - } - $code .= $subIndent.(1 !== $k - $j ? $k.' => ' : ''); - $j = $k; - $eol = ",\n"; - $c = '['.self::export($class).']'; - - if ($seen[$class] ?? false) { - if (Registry::$cloneable[$class]) { - ++$prototypesAccess; - $code .= 'clone $p'.$c; - } else { - ++$factoriesAccess; - $code .= '$f'.$c.'()'; - } - } else { - $seen[$class] = true; - if (Registry::$cloneable[$class]) { - $code .= 'clone ('.($prototypesAccess++ ? '$p' : '($p = &'.$r.'::$prototypes)').$c.' ?? '.$r.'::p'; - } else { - $code .= '('.($factoriesAccess++ ? '$f' : '($f = &'.$r.'::$factories)').$c.' ?? '.$r.'::f'; - $eol = '()'.$eol; - } - $code .= '('.substr($c, 1, -1).'))'; - } - $code .= $eol; - } - - if (1 === $prototypesAccess) { - $code = str_replace('($p = &'.$r.'::$prototypes)', $r.'::$prototypes', $code); - } - if (1 === $factoriesAccess) { - $code = str_replace('($f = &'.$r.'::$factories)', $r.'::$factories', $code); - } - if ('' !== $code) { - $code = "\n".$code.$indent; - } - - if ($serializables) { - $code = $r.'::unserialize(['.$code.'], '.self::export($serializables, $indent).')'; - } else { - $code = '['.$code.']'; - } - - return '$o = '.$code; - } - - private static function exportHydrator(Hydrator $value, string $indent, string $subIndent): string - { - $code = ''; - foreach ($value->properties as $class => $properties) { - $code .= $subIndent.' '.self::export($class).' => '.self::export($properties, $subIndent.' ').",\n"; - } - - $code = [ - self::export($value->registry, $subIndent), - self::export($value->values, $subIndent), - '' !== $code ? "[\n".$code.$subIndent.']' : '[]', - self::export($value->value, $subIndent), - self::export($value->wakeups, $subIndent), - ]; - - return '\\'.\get_class($value)."::hydrate(\n".$subIndent.implode(",\n".$subIndent, $code)."\n".$indent.')'; - } - - /** - * @param \ArrayIterator|\ArrayObject $value - * @param \ArrayIterator|\ArrayObject $proto - */ - private static function getArrayObjectProperties($value, array &$arrayValue, $proto): array - { - $reflector = $value instanceof \ArrayIterator ? 'ArrayIterator' : 'ArrayObject'; - $reflector = Registry::$reflectors[$reflector] ?? Registry::getClassReflector($reflector); - - $properties = [ - $arrayValue, - $reflector->getMethod('getFlags')->invoke($value), - $value instanceof \ArrayObject ? $reflector->getMethod('getIteratorClass')->invoke($value) : 'ArrayIterator', - ]; - - $reflector = $reflector->getMethod('setFlags'); - $reflector->invoke($proto, \ArrayObject::STD_PROP_LIST); - - if ($properties[1] & \ArrayObject::STD_PROP_LIST) { - $reflector->invoke($value, 0); - $properties[0] = (array) $value; - } else { - $reflector->invoke($value, \ArrayObject::STD_PROP_LIST); - $arrayValue = (array) $value; - } - $reflector->invoke($value, $properties[1]); - - if ([[], 0, 'ArrayIterator'] === $properties) { - $properties = []; - } else { - if ('ArrayIterator' === $properties[2]) { - unset($properties[2]); - } - $properties = [$reflector->class => ["\0" => $properties]]; - } - - return $properties; - } -} diff --git a/vendor/symfony/var-exporter/Internal/Hydrator.php b/vendor/symfony/var-exporter/Internal/Hydrator.php deleted file mode 100644 index 364d292..0000000 --- a/vendor/symfony/var-exporter/Internal/Hydrator.php +++ /dev/null @@ -1,151 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -use Symfony\Component\VarExporter\Exception\ClassNotFoundException; - -/** - * @author Nicolas Grekas - * - * @internal - */ -class Hydrator -{ - public static $hydrators = []; - - public $registry; - public $values; - public $properties; - public $value; - public $wakeups; - - public function __construct(?Registry $registry, ?Values $values, array $properties, $value, array $wakeups) - { - $this->registry = $registry; - $this->values = $values; - $this->properties = $properties; - $this->value = $value; - $this->wakeups = $wakeups; - } - - public static function hydrate($objects, $values, $properties, $value, $wakeups) - { - foreach ($properties as $class => $vars) { - (self::$hydrators[$class] ?? self::getHydrator($class))($vars, $objects); - } - foreach ($wakeups as $k => $v) { - if (\is_array($v)) { - $objects[-$k]->__unserialize($v); - } else { - $objects[$v]->__wakeup(); - } - } - - return $value; - } - - public static function getHydrator($class) - { - if ('stdClass' === $class) { - return self::$hydrators[$class] = static function ($properties, $objects) { - foreach ($properties as $name => $values) { - foreach ($values as $i => $v) { - $objects[$i]->$name = $v; - } - } - }; - } - - if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) { - throw new ClassNotFoundException($class); - } - $classReflector = new \ReflectionClass($class); - - if (!$classReflector->isInternal()) { - return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, $class); - } - - if ($classReflector->name !== $class) { - return self::$hydrators[$classReflector->name] ?? self::getHydrator($classReflector->name); - } - - switch ($class) { - case 'ArrayIterator': - case 'ArrayObject': - $constructor = \Closure::fromCallable([$classReflector->getConstructor(), 'invokeArgs']); - - return self::$hydrators[$class] = static function ($properties, $objects) use ($constructor) { - foreach ($properties as $name => $values) { - if ("\0" !== $name) { - foreach ($values as $i => $v) { - $objects[$i]->$name = $v; - } - } - } - foreach ($properties["\0"] ?? [] as $i => $v) { - $constructor($objects[$i], $v); - } - }; - - case 'ErrorException': - return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, new class() extends \ErrorException { - }); - - case 'TypeError': - return self::$hydrators[$class] = (self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'))->bindTo(null, new class() extends \Error { - }); - - case 'SplObjectStorage': - return self::$hydrators[$class] = static function ($properties, $objects) { - foreach ($properties as $name => $values) { - if ("\0" === $name) { - foreach ($values as $i => $v) { - for ($j = 0; $j < \count($v); ++$j) { - $objects[$i]->attach($v[$j], $v[++$j]); - } - } - continue; - } - foreach ($values as $i => $v) { - $objects[$i]->$name = $v; - } - } - }; - } - - $propertySetters = []; - foreach ($classReflector->getProperties() as $propertyReflector) { - if (!$propertyReflector->isStatic()) { - $propertyReflector->setAccessible(true); - $propertySetters[$propertyReflector->name] = \Closure::fromCallable([$propertyReflector, 'setValue']); - } - } - - if (!$propertySetters) { - return self::$hydrators[$class] = self::$hydrators['stdClass'] ?? self::getHydrator('stdClass'); - } - - return self::$hydrators[$class] = static function ($properties, $objects) use ($propertySetters) { - foreach ($properties as $name => $values) { - if ($setValue = $propertySetters[$name] ?? null) { - foreach ($values as $i => $v) { - $setValue($objects[$i], $v); - } - continue; - } - foreach ($values as $i => $v) { - $objects[$i]->$name = $v; - } - } - }; - } -} diff --git a/vendor/symfony/var-exporter/Internal/Reference.php b/vendor/symfony/var-exporter/Internal/Reference.php deleted file mode 100644 index e371c07..0000000 --- a/vendor/symfony/var-exporter/Internal/Reference.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -/** - * @author Nicolas Grekas - * - * @internal - */ -class Reference -{ - public $id; - public $value; - public $count = 0; - - public function __construct(int $id, $value = null) - { - $this->id = $id; - $this->value = $value; - } -} diff --git a/vendor/symfony/var-exporter/Internal/Registry.php b/vendor/symfony/var-exporter/Internal/Registry.php deleted file mode 100644 index 19d91c9..0000000 --- a/vendor/symfony/var-exporter/Internal/Registry.php +++ /dev/null @@ -1,136 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -use Symfony\Component\VarExporter\Exception\ClassNotFoundException; -use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException; - -/** - * @author Nicolas Grekas - * - * @internal - */ -class Registry -{ - public static $reflectors = []; - public static $prototypes = []; - public static $factories = []; - public static $cloneable = []; - public static $instantiableWithoutConstructor = []; - - public function __construct(array $classes) - { - foreach ($classes as $i => $class) { - $this->$i = $class; - } - } - - public static function unserialize($objects, $serializables) - { - $unserializeCallback = ini_set('unserialize_callback_func', __CLASS__.'::getClassReflector'); - - try { - foreach ($serializables as $k => $v) { - $objects[$k] = unserialize($v); - } - } finally { - ini_set('unserialize_callback_func', $unserializeCallback); - } - - return $objects; - } - - public static function p($class) - { - self::getClassReflector($class, true, true); - - return self::$prototypes[$class]; - } - - public static function f($class) - { - $reflector = self::$reflectors[$class] ?? self::getClassReflector($class, true, false); - - return self::$factories[$class] = \Closure::fromCallable([$reflector, 'newInstanceWithoutConstructor']); - } - - public static function getClassReflector($class, $instantiableWithoutConstructor = false, $cloneable = null) - { - if (!($isClass = class_exists($class)) && !interface_exists($class, false) && !trait_exists($class, false)) { - throw new ClassNotFoundException($class); - } - $reflector = new \ReflectionClass($class); - - if ($instantiableWithoutConstructor) { - $proto = $reflector->newInstanceWithoutConstructor(); - } elseif (!$isClass || $reflector->isAbstract()) { - throw new NotInstantiableTypeException($class); - } elseif ($reflector->name !== $class) { - $reflector = self::$reflectors[$name = $reflector->name] ?? self::getClassReflector($name, false, $cloneable); - self::$cloneable[$class] = self::$cloneable[$name]; - self::$instantiableWithoutConstructor[$class] = self::$instantiableWithoutConstructor[$name]; - self::$prototypes[$class] = self::$prototypes[$name]; - - return self::$reflectors[$class] = $reflector; - } else { - try { - $proto = $reflector->newInstanceWithoutConstructor(); - $instantiableWithoutConstructor = true; - } catch (\ReflectionException $e) { - $proto = $reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize') ? 'C:' : 'O:'; - if ('C:' === $proto && !$reflector->getMethod('unserialize')->isInternal()) { - $proto = null; - } elseif (false === $proto = @unserialize($proto.\strlen($class).':"'.$class.'":0:{}')) { - throw new NotInstantiableTypeException($class); - } - } - if (null !== $proto && !$proto instanceof \Throwable && !$proto instanceof \Serializable && !method_exists($class, '__sleep') && (\PHP_VERSION_ID < 70400 || !method_exists($class, '__serialize'))) { - try { - serialize($proto); - } catch (\Exception $e) { - throw new NotInstantiableTypeException($class, $e); - } - } - } - - if (null === $cloneable) { - if (($proto instanceof \Reflector || $proto instanceof \ReflectionGenerator || $proto instanceof \ReflectionType || $proto instanceof \IteratorIterator || $proto instanceof \RecursiveIteratorIterator) && (!$proto instanceof \Serializable && !method_exists($proto, '__wakeup') && (\PHP_VERSION_ID < 70400 || !method_exists($class, '__unserialize')))) { - throw new NotInstantiableTypeException($class); - } - - $cloneable = $reflector->isCloneable() && !$reflector->hasMethod('__clone'); - } - - self::$cloneable[$class] = $cloneable; - self::$instantiableWithoutConstructor[$class] = $instantiableWithoutConstructor; - self::$prototypes[$class] = $proto; - - if ($proto instanceof \Throwable) { - static $setTrace; - - if (null === $setTrace) { - $setTrace = [ - new \ReflectionProperty(\Error::class, 'trace'), - new \ReflectionProperty(\Exception::class, 'trace'), - ]; - $setTrace[0]->setAccessible(true); - $setTrace[1]->setAccessible(true); - $setTrace[0] = \Closure::fromCallable([$setTrace[0], 'setValue']); - $setTrace[1] = \Closure::fromCallable([$setTrace[1], 'setValue']); - } - - $setTrace[$proto instanceof \Exception]($proto, []); - } - - return self::$reflectors[$class] = $reflector; - } -} diff --git a/vendor/symfony/var-exporter/Internal/Values.php b/vendor/symfony/var-exporter/Internal/Values.php deleted file mode 100644 index 21ae04e..0000000 --- a/vendor/symfony/var-exporter/Internal/Values.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter\Internal; - -/** - * @author Nicolas Grekas - * - * @internal - */ -class Values -{ - public $values; - - public function __construct(array $values) - { - $this->values = $values; - } -} diff --git a/vendor/symfony/var-exporter/LICENSE b/vendor/symfony/var-exporter/LICENSE deleted file mode 100644 index 3f853aa..0000000 --- a/vendor/symfony/var-exporter/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2018-2019 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/symfony/var-exporter/README.md b/vendor/symfony/var-exporter/README.md deleted file mode 100644 index bb13960..0000000 --- a/vendor/symfony/var-exporter/README.md +++ /dev/null @@ -1,38 +0,0 @@ -VarExporter Component -===================== - -The VarExporter component allows exporting any serializable PHP data structure to -plain PHP code. While doing so, it preserves all the semantics associated with -the serialization mechanism of PHP (`__wakeup`, `__sleep`, `Serializable`, -`__serialize`, `__unserialize`). - -It also provides an instantiator that allows creating and populating objects -without calling their constructor nor any other methods. - -The reason to use this component *vs* `serialize()` or -[igbinary](https://github.com/igbinary/igbinary) is performance: thanks to -OPcache, the resulting code is significantly faster and more memory efficient -than using `unserialize()` or `igbinary_unserialize()`. - -Unlike `var_export()`, this works on any serializable PHP value. - -It also provides a few improvements over `var_export()`/`serialize()`: - - * the output is PSR-2 compatible; - * the output can be re-indented without messing up with `\r` or `\n` in the data - * missing classes throw a `ClassNotFoundException` instead of being unserialized to - `PHP_Incomplete_Class` objects; - * references involving `SplObjectStorage`, `ArrayObject` or `ArrayIterator` - instances are preserved; - * `Reflection*`, `IteratorIterator` and `RecursiveIteratorIterator` classes - throw an exception when being serialized (their unserialized version is broken - anyway, see https://bugs.php.net/76737). - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/var_exporter.html) - * [Contributing](https://symfony.com/doc/current/contributing/index.html) - * [Report issues](https://github.com/symfony/symfony/issues) and - [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/var-exporter/VarExporter.php b/vendor/symfony/var-exporter/VarExporter.php deleted file mode 100644 index da9a8d4..0000000 --- a/vendor/symfony/var-exporter/VarExporter.php +++ /dev/null @@ -1,114 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarExporter; - -use Symfony\Component\VarExporter\Exception\ExceptionInterface; -use Symfony\Component\VarExporter\Internal\Exporter; -use Symfony\Component\VarExporter\Internal\Hydrator; -use Symfony\Component\VarExporter\Internal\Registry; -use Symfony\Component\VarExporter\Internal\Values; - -/** - * Exports serializable PHP values to PHP code. - * - * VarExporter allows serializing PHP data structures to plain PHP code (like var_export()) - * while preserving all the semantics associated with serialize() (unlike var_export()). - * - * By leveraging OPcache, the generated PHP code is faster than doing the same with unserialize(). - * - * @author Nicolas Grekas - */ -final class VarExporter -{ - /** - * Exports a serializable PHP value to PHP code. - * - * @param mixed $value The value to export - * @param bool &$isStaticValue Set to true after execution if the provided value is static, false otherwise - * - * @return string The value exported as PHP code - * - * @throws ExceptionInterface When the provided value cannot be serialized - */ - public static function export($value, bool &$isStaticValue = null): string - { - $isStaticValue = true; - - if (!\is_object($value) && !(\is_array($value) && $value) && !$value instanceof \__PHP_Incomplete_Class && !\is_resource($value)) { - return Exporter::export($value); - } - - $objectsPool = new \SplObjectStorage(); - $refsPool = []; - $objectsCount = 0; - - try { - $value = Exporter::prepare([$value], $objectsPool, $refsPool, $objectsCount, $isStaticValue)[0]; - } finally { - $references = []; - foreach ($refsPool as $i => $v) { - if ($v[0]->count) { - $references[1 + $i] = $v[2]; - } - $v[0] = $v[1]; - } - } - - if ($isStaticValue) { - return Exporter::export($value); - } - - $classes = []; - $values = []; - $states = []; - foreach ($objectsPool as $i => $v) { - list(, $classes[], $values[], $wakeup) = $objectsPool[$v]; - if (0 < $wakeup) { - $states[$wakeup] = $i; - } elseif (0 > $wakeup) { - $states[-$wakeup] = [$i, array_pop($values)]; - $values[] = []; - } - } - ksort($states); - - $wakeups = [null]; - foreach ($states as $k => $v) { - if (\is_array($v)) { - $wakeups[-$v[0]] = $v[1]; - } else { - $wakeups[] = $v; - } - } - - if (null === $wakeups[0]) { - unset($wakeups[0]); - } - - $properties = []; - foreach ($values as $i => $vars) { - foreach ($vars as $class => $values) { - foreach ($values as $name => $v) { - $properties[$class][$name][$i] = $v; - } - } - } - - if ($classes || $references) { - $value = new Hydrator(new Registry($classes), $references ? new Values($references) : null, $properties, $value, $wakeups); - } else { - $isStaticValue = true; - } - - return Exporter::export($value); - } -} diff --git a/vendor/symfony/var-exporter/composer.json b/vendor/symfony/var-exporter/composer.json deleted file mode 100644 index 6ccfc63..0000000 --- a/vendor/symfony/var-exporter/composer.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "symfony/var-exporter", - "type": "library", - "description": "A blend of var_export() + serialize() to turn any serializable data structure to plain PHP code", - "keywords": ["export", "serialize", "instantiate", "hydrate", "construct", "clone"], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "require": { - "php": "^7.2.5" - }, - "require-dev": { - "symfony/var-dumper": "^4.4|^5.0" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\VarExporter\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "minimum-stability": "dev", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - } -} -- GitLab From 5958ec5b88b9fb33a2dfe7f08d27df9bf3763199 Mon Sep 17 00:00:00 2001 From: Florian Boulant Date: Sun, 5 Jan 2020 20:07:14 +0100 Subject: [PATCH 4/4] Ignore vendor folder --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e9c9d3d..b476279 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ valeursfoncieres-* .vscode/ +vendor/ \ No newline at end of file -- GitLab